int rleSize = 0;
int rleBufferFound = 0;
int ctrlSize = -1;
int ctrlHeaderCopied = 0;
byte ctrlHeader[] = null;
ImageObjectFragment rleFrag;
int length;
int packHeaderSize;
boolean firstPackFound = false;
try {
do {
// 4 bytes: packet identifier 0x000001ba
long startOfs = ofs;
if (buffer.getDWord(ofs) != 0x000001ba) {
throw new CoreException("Missing packet identifier at ofs " + ToolBox.toHexLeftZeroPadded(ofs,8));
}
// 6 bytes: system clock reference
// 3 bytes: multiplexer rate
// 1 byte: stuffing info
int stuffOfs = buffer.getByte(ofs+=13) & 7;
// 4 bytes: sub packet ID 0x000001bd
if (buffer.getDWord(ofs += (1+stuffOfs)) != 0x000001bd) {
throw new CoreException("Missing packet identifier at ofs " + ToolBox.toHexLeftZeroPadded(ofs,8));
}
// 2 bytes: packet length (number of bytes after this entry)
length = buffer.getWord(ofs+=4);
nextOfs = ofs+2+length;
// 2 bytes: packet type
ofs += 2;
packHeaderSize = (int)(ofs-startOfs);
boolean firstPack = ((buffer.getByte(++ofs) & 0x80) == 0x80);
// 1 byte pts length
int ptsLength = buffer.getByte(ofs+=1);
ofs += 1 + ptsLength; // skip PTS and stream ID
int packetStreamID = buffer.getByte(ofs++) - 0x20;
if (packetStreamID != streamID) {
// packet doesn't belong to stream -> skip
if (nextOfs % 0x800 != 0) {
ofs = (nextOfs/0x800 + 1)*0x800;
logger.warn("Offset to next fragment is invalid. Fixed to:" + ToolBox.toHexLeftZeroPadded(ofs, 8) + "\n");
} else {
ofs = nextOfs;
}
ctrlOfs += 0x800;
continue;
}
int headerSize = (int)(ofs-startOfs); // only valid for additional packets
if (firstPack && ptsLength >= 5) {
int size = buffer.getWord(ofs);
ofs += 2;
ctrlOfsRel = buffer.getWord(ofs);
rleSize = ctrlOfsRel-2; // calculate size of RLE buffer
ctrlSize = size-ctrlOfsRel-2; // calculate size of control header
if (ctrlSize < 0) {
throw new CoreException("Invalid control buffer size");
}
ctrlHeader = new byte[ctrlSize];
ctrlOfs = ctrlOfsRel + ofs; // might have to be corrected for multiple packets
ofs += 2;
headerSize = (int)(ofs-startOfs);
pic.setRleFragments(new ArrayList<ImageObjectFragment>());
firstPackFound = true;
} else {
if (firstPackFound) {
ctrlOfs += headerSize; // fix absolute offset by adding header bytes
} else {
logger.warn("Invalid fragment skipped at ofs " + ToolBox.toHexLeftZeroPadded(startOfs, 8) + "\n");
}
}
// check if control header is (partly) in this packet
int diff = (int)(nextOfs - ctrlOfs - ctrlHeaderCopied);
if (diff<0) {
diff = 0;
}
int copied = ctrlHeaderCopied;
try {
for (int i=0; (i < diff) && (ctrlHeaderCopied<ctrlSize); i++) {
ctrlHeader[ctrlHeaderCopied] = (byte)buffer.getByte(ctrlOfs + i + copied);
ctrlHeaderCopied++;
}
} catch (ArrayIndexOutOfBoundsException ex) {
throw new CoreException("Inconsistent control buffer access (" + ex.getMessage() + ")");
}
rleFrag = new ImageObjectFragment(ofs, length - headerSize - diff + packHeaderSize);
pic.getRleFragments().add(rleFrag);
rleBufferFound += rleFrag.getImagePacketSize();
if (ctrlHeaderCopied != ctrlSize && (nextOfs % 0x800 != 0)) {
ofs = (nextOfs/0x800 + 1) * 0x800;
logger.warn("Offset to next fragment is invalid. Fixed to:" + ToolBox.toHexLeftZeroPadded(ofs, 8) + "\n");
rleBufferFound += ofs-nextOfs;