try {
while (index < bufferSize) {
// for threaded version
if (Core.isCanceled()) {
throw new CoreException("Canceled by user!");
}
Core.setProgress(index);
segment = readPCSSegment(index);
switch (segment.type) {
case PGSSUP_PALETTE_SEGMENT:
StringBuffer message = new StringBuffer("PDS offset: ").append(ToolBox.toHexLeftZeroPadded(index, 8)).append(", size: ").append(ToolBox.toHexLeftZeroPadded(segment.size, 4));
if (compositionNumber != compositionNumberOld) {
if (subPictureBD != null) {
StringBuffer result = new StringBuffer();
int paletteSize = parsePDS(segment, subPictureBD, result);
if (paletteSize >= 0) {
logger.trace(message + ", " + result + "\n");
if (paletteSize > 0) {
pdsCounter++;
}
} else {
logger.trace(message + "\n");
logger.warn(result + "\n");
}
} else {
logger.trace(message + "\n");
logger.warn("Missing PTS start -> ignored\n");
}
} else {
logger.trace(message + ", composition number unchanged -> ignored\n");
}
break;
case PGSSUP_PICTURE_SEGMENT:
message = new StringBuffer("ODS offset: ").append(ToolBox.toHexLeftZeroPadded(index, 8)).append(", size: ").append(ToolBox.toHexLeftZeroPadded(segment.size, 4));
if (compositionNumber != compositionNumberOld) {
if (!paletteUpdate) {
if (subPictureBD != null) {
StringBuffer result = new StringBuffer();
if (parseODS(segment, subPictureBD, result)) {
odsCounter++;
}
logger.trace(message + ", img size: " + subPictureBD.getImageWidth() + "*" + subPictureBD.getImageHeight() + (result.length() == 0 ? "\n" : ", " + result) + "\n");
} else {
logger.trace(message + "\n");
logger.warn("missing PTS start -> ignored\n");
}
} else {
logger.trace(message + "\n");
logger.warn("palette update only -> ignored\n");
}
} else {
logger.trace(message + ", composition number unchanged -> ignored\n");
}
break;
case PGSSUP_PRESENTATION_SEGMENT:
compositionNumber = getCompositionNumber(segment);
compositionState = getCompositionState(segment);
paletteUpdate = getPaletteUpdateFlag(segment);
ptsPCS = segment.pts;
if (segment.size >= 0x13) {
compositionCount = 1; // could be also 2, but we'll ignore this for the moment
} else {
compositionCount = 0;
}
if (compositionState == PGSCompositionState.INVALID) {
logger.warn("Illegal composition state at offset " + ToolBox.toHexLeftZeroPadded(index, 8) + "\n");
} else if (compositionState == PGSCompositionState.EPOCH_START) {
// new frame
if (subPictures.size() > 0 && (odsCounter == 0 || pdsCounter == 0)) {
logger.warn("Missing PDS/ODS: last epoch is discarded\n");
subPictures.remove(subPictures.size() - 1);
compositionNumberOld = compositionNumber - 1;
if (subPictures.size() > 0) {
lastSubPicture = subPictures.get(subPictures.size() - 1);
} else {
lastSubPicture = null;
}
} else {
lastSubPicture = subPictureBD;
}
subPictureBD = new SubPictureBD();
subPictures.add(subPictureBD);
subPictureBD.setStartTime(segment.pts);
logger.info("#> " + (subPictures.size()) + " (" + ptsToTimeStr(subPictureBD.getStartTime()) + ")\n");
StringBuffer result = new StringBuffer();
parsePCS(segment, subPictureBD, result);
// fix end time stamp of previous subPictureBD if still missing
if (lastSubPicture != null && lastSubPicture.getEndTime() == 0) {
lastSubPicture.setEndTime(subPictureBD.getStartTime());
}
message = new StringBuffer("PCS offset: ").append(ToolBox.toHexLeftZeroPadded(index, 8)).append(", START, size: ").append(ToolBox.toHexLeftZeroPadded(segment.size, 4)).append(", composition number: ").append(compositionNumber).append(", forced: ").append(subPictureBD.isForced()).append((result.length() == 0 ? "\n" : ", " + result + "\n"));
message.append("PTS start: ").append(ptsToTimeStr(subPictureBD.getStartTime())).append(", screen size: ").append(subPictureBD.getWidth()).append("*").append(subPictureBD.getHeight()).append("\n");
logger.trace(message.toString());
odsCounter = 0;
pdsCounter = 0;
odsCounterOld = 0;
pdsCounterOld = 0;
picTmp = null;
} else {
if (subPictureBD == null) {
logger.warn("Missing start of epoch at offset " + ToolBox.toHexLeftZeroPadded(index, 8) + "\n");
break;
}
message = new StringBuffer("PCS offset: ").append(ToolBox.toHexLeftZeroPadded(index, 8)).append(", ");
switch (compositionState) {
case EPOCH_CONTINUE:
message.append("CONT, ");
break;
case ACQU_POINT:
message.append("ACQU, ");
break;
case NORMAL:
message.append("NORM, ");
break;
}
message.append(" size: ").append(ToolBox.toHexLeftZeroPadded(segment.size, 4)).append(", composition number: ").append(compositionNumber).append(", forced: ").append(subPictureBD.isForced());
StringBuffer result = new StringBuffer();
if (compositionNumber != compositionNumberOld) {
// store the state so that we can revert to it
picTmp = new SubPictureBD(subPictureBD);
// create new subPictureBD
parsePCS(segment, subPictureBD, result);
}
if (result.length() > 0) {
message.append(", ").append(result);
}
message.append(", pal update: ").append(paletteUpdate).append("\n").append("PTS: ").append(ptsToTimeStr(segment.pts)).append("\n");
logger.trace(message.toString());
}
break;
case PGSSUP_WINDOW_SEGMENT:
message = new StringBuffer("WDS offset: ").append(ToolBox.toHexLeftZeroPadded(index, 8)).append(", size: ").append(ToolBox.toHexLeftZeroPadded(segment.size, 4));
if (subPictureBD != null) {
parseWDS(segment, subPictureBD);
logger.trace(message + ", dim: " + subPictureBD.getWindowWidth() + "*" + subPictureBD.getWindowHeight() + "\n");
} else {
logger.trace(message + "\n");
logger.warn("Missing PTS start -> ignored\n");
}
break;
case PGSSUP_DISPLAY_SEGMENT:
logger.trace("END offset: " + ToolBox.toHexLeftZeroPadded(index, 8) + "\n");
// decide whether to store this last composition section as caption or merge it
if (compositionState == PGSCompositionState.EPOCH_START) {
if (compositionCount > 0 && odsCounter > odsCounterOld && compositionNumber != compositionNumberOld
&& subPictureBD != null && subPictureBD.isMergableWith(lastSubPicture)) {
// the last start epoch did not contain any (new) content
// and should be merged to the previous frame
subPictures.remove(subPictures.size()-1);
subPictureBD = lastSubPicture;
if (subPictures.size() > 0) {
lastSubPicture = subPictures.get(subPictures.size() - 1);
} else {
lastSubPicture = null;
}
logger.info("#< caption merged\n");
}
} else {
long startTime = 0;
if (subPictureBD != null) {
startTime = subPictureBD.getStartTime(); // store
subPictureBD.setStartTime(ptsPCS); // set for testing merge
}
if (compositionCount > 0 && odsCounter > odsCounterOld && compositionNumber != compositionNumberOld
&& (subPictureBD == null || !subPictureBD.isMergableWith(picTmp))) {
// last PCS should be stored as separate caption
if (odsCounter-odsCounterOld>1 || pdsCounter-pdsCounterOld>1) {
logger.warn("Multiple PDS/ODS definitions: result may be erratic\n");
}
// replace subPictureBD with picTmp (deepCopy created before new PCS)
subPictures.set(subPictures.size() - 1, picTmp); // replace in list
lastSubPicture = picTmp;
subPictures.add(subPictureBD);
logger.info("#< " + (subPictures.size()) + " (" + ptsToTimeStr(subPictureBD.getStartTime()) + ")\n");
odsCounterOld = odsCounter;
} else {
if (subPictureBD != null) {
// merge with previous subPictureBD
subPictureBD.setStartTime(startTime); // restore
subPictureBD.setEndTime(ptsPCS);
// for the unlikely case that forced flag changed during one caption
if (picTmp != null && picTmp.isForced()) {
subPictureBD.setForced(true);
}
if (pdsCounter > pdsCounterOld || paletteUpdate) {
logger.warn("Palette animation: result may be erratic\n");
}
} else {
logger.warn("End without at least one epoch start\n");
}
}
}
pdsCounterOld = pdsCounter;
compositionNumberOld = compositionNumber;
break;
default:
logger.warn("<unknown> " + ToolBox.toHexLeftZeroPadded(segment.type, 2) + " ofs:" + ToolBox.toHexLeftZeroPadded(index, 8) + "\n");
break;
}
index += 13; // header size
index += segment.size;
}
} catch (CoreException ex) {
if (subPictures.size() == 0) {
throw ex;
}
logger.error(ex.getMessage() + "\n");
logger.trace("Probably not all caption imported due to error.\n");
} catch (FileBufferException ex) {
if (subPictures.size() == 0) {
throw new CoreException(ex.getMessage());
}
logger.error(ex.getMessage() + "\n");
logger.trace("Probably not all caption imported due to error.\n");
}