/*
This file is part of jpcsp.
Jpcsp is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Jpcsp is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Jpcsp. If not, see <http://www.gnu.org/licenses/>.
*/
package jpcsp.HLE.kernel.types;
import static jpcsp.HLE.modules.sceMp4.TRACK_TYPE_AUDIO;
import static jpcsp.HLE.modules.sceMp4.TRACK_TYPE_VIDEO;
import static jpcsp.util.Utilities.alignUp;
public class SceMp4TrackSampleBuf extends pspAbstractMemoryMappedStructure {
public int mp4;
public int baseBufferAddr;
public int samplesPut;
public int sampleSize;
public int unknown;
public int currentSample; // Incremented at each sceMp4TrackSamplePutBuf by the number of samples put
public int timeScale;
public int duration;
public int totalNumberSamples;
public int trackType;
public int readBufferAddr;
public int readBufferSize;
public long currentFileOffset;
public int sizeAvailableInReadBuffer;
public int bytesBufferAddr;
public int bytesBufferLength;
public SceMp4TrackSampleBufInfo bufBytes;
public SceMp4TrackSampleBufInfo bufSamples;
public static class SceMp4TrackSampleBufInfo extends pspAbstractMemoryMappedStructure {
public int totalSize;
public int readOffset;
public int writeOffset;
public int sizeAvailableForRead;
public int unknown16;
public int bufferAddr;
public int callback24;
public int unknown28;
public int unknown36;
@Override
protected void read() {
totalSize = read32();
readOffset = read32();
writeOffset = read32();
sizeAvailableForRead = read32();
unknown16 = read32();
bufferAddr = read32();
callback24 = read32();
unknown28 = read32();
readUnknown(4);
unknown36 = read32();
}
@Override
protected void write() {
write32(totalSize);
write32(readOffset);
write32(writeOffset);
write32(sizeAvailableForRead);
write32(unknown16);
write32(bufferAddr);
write32(callback24);
write32(unknown28);
writeUnknown(4);
write32(unknown36);
}
public int getWritableSpace() {
return totalSize - sizeAvailableForRead;
}
public void notifyRead(int length) {
length = Math.min(length, sizeAvailableForRead);
if (length > 0) {
readOffset += length;
if (readOffset >= totalSize) {
readOffset -= totalSize;
}
sizeAvailableForRead -= length;
}
}
public void flush() {
readOffset = 0;
writeOffset = 0;
sizeAvailableForRead = 0;
}
@Override
public int sizeof() {
return 40;
}
@Override
public String toString() {
return String.format("SceMp4TrackSampleBufInfo[totalSize=0x%X, readOffset=0x%X, writeOffset=0x%X, sizeAvailableForRead=0x%X, bufferAddr=0x%08X]", totalSize, readOffset, writeOffset, sizeAvailableForRead, bufferAddr);
}
}
@Override
protected void read() {
readUnknown(36);
currentSample = read32(); // Offset 36
timeScale = read32(); // Offset 40
duration = read32(); // Offset 44
totalNumberSamples = read32(); // Offset 48
read32(); // Offset 52
read32(); // Offset 56
trackType = read32(); // Offset 60
readUnknown(4);
baseBufferAddr = read32(); // Offset 68
samplesPut = read32(); // Offset 72
sampleSize = read32(); // Offset 76
unknown = read32(); // Offset 80
bytesBufferAddr = read32(); // Offset 84
bytesBufferLength = read32(); // Offset 88
read32(); // Offset 92
read32(); // Offset 96
bufBytes = new SceMp4TrackSampleBufInfo(); // Offset 100
read(bufBytes);
bufSamples = new SceMp4TrackSampleBufInfo(); // Offset 140
read(bufSamples);
read32(); // Offset 180
currentFileOffset = read64(); // Offset 184
read32(); // Offset 192
read32(); // Offset 196
read32(); // Offset 200
read32(); // Offset 204
read32(); // Offset 208
read32(); // Offset 212
read32(); // Offset 216
read32(); // Offset 220
readBufferAddr = read32(); // Offset 224
readBufferSize = read32(); // Offset 228
sizeAvailableInReadBuffer = read32(); // Offset 232
read32(); // Offset 236
}
@Override
protected void write() {
writeUnknown(36);
write32(currentSample); // Offset 36
write32(timeScale); // Offset 40
write32(duration); // Offset 44
write32(totalNumberSamples); // Offset 48
write32(getBaseAddress() + 240); // Offset 52
write32(getBaseAddress() + 72); // Offset 56
write32(trackType); // Offset 60
writeUnknown(4);
write32(baseBufferAddr); // Offset 68
write32(samplesPut); // Offset 72
write32(sampleSize); // Offset 76
write32(unknown); // Offset 80
write32(bytesBufferAddr); // Offset 84
write32(bytesBufferLength); // Offset 88
write32(alignUp(baseBufferAddr, 63)); // Offset 92
write32(samplesPut << 6); // Offset 96
write(bufBytes); // Offset 100
write(bufSamples); // Offset 140
write32(getBaseAddress() + 184); // Offset 180
write64(currentFileOffset); // Offset 184
write32(0); // Offset 192 (callback address in libmp4 module?)
write32(0); // Offset 196
write32(0); // Offset 200
write32(0); // Offset 204
write32(mp4); // Offset 208
write32(0); // Offset 212
write32(0); // Offset 216
write32(0); // Offset 220
write32(readBufferAddr); // Offset 224
write32(readBufferSize); // Offset 228
write32(sizeAvailableInReadBuffer); // Offset 232
write32(1); // Offset 236
}
public boolean isOfType(int trackType) {
int mask = TRACK_TYPE_VIDEO | TRACK_TYPE_AUDIO;
return (this.trackType & mask) == (trackType & mask);
}
public boolean isInReadBuffer(int offset) {
return offset >= currentFileOffset && offset < currentFileOffset + sizeAvailableInReadBuffer;
}
private void addBytesToTrackSequential(int addr, int length) {
if (length > 0) {
mem.memcpy(bufBytes.bufferAddr + bufBytes.writeOffset, addr, length);
bufBytes.writeOffset += length;
bufBytes.sizeAvailableForRead += length;
}
}
public void addBytesToTrack(int addr, int length) {
int length1 = Math.min(length, bufBytes.totalSize - bufBytes.writeOffset);
addBytesToTrackSequential(addr, length1);
int length2 = length - length1;
if (length2 > 0) {
bufBytes.writeOffset = 0;
addBytesToTrackSequential(addr + length1, length2);
}
}
public void addSamplesToTrack(int samples) {
bufSamples.sizeAvailableForRead += samples;
currentSample += samples;
}
public void readBytes(int addr, int length) {
length = Math.min(length, bufBytes.sizeAvailableForRead);
if (length > 0) {
int length1 = Math.min(length, bufBytes.totalSize - bufBytes.readOffset);
mem.memcpy(addr, bufBytes.bufferAddr + bufBytes.readOffset, length1);
int length2 = length - length1;
if (length2 > 0) {
mem.memcpy(addr + length1, bufBytes.bufferAddr, length2);
}
bufBytes.notifyRead(length);
}
}
@Override
public int sizeof() {
return 240;
}
@Override
public String toString() {
return String.format("SceMp4TrackSampleBuf currentSample=0x%X, timeScale=0x%X, duration=0x%X, totalNumberSamples=0x%X, trackType=0x%X, baseBufferAddr=0x%08X, numSamples=0x%X, sampleSize=0x%X, unknown=0x%X, readBufferAddr=0x%08X, readBufferSize=0x%X, currentFileOffset=0x%X, sizeAvailableInReadBuffer=0x%X, bufBytes=%s, bufSamples=%s", currentSample, timeScale, duration, totalNumberSamples, trackType, baseBufferAddr, samplesPut, sampleSize, unknown, readBufferAddr, readBufferSize, currentFileOffset, sizeAvailableInReadBuffer, bufBytes, bufSamples);
}
}