* @param fsYOld Old free scaling factor in Y direction
*/
public static void reScanSubtitles(Resolution resOld, double fpsTrgOld, int delayOld, boolean convertFpsOld, double fsXOld, double fsYOld) {
//SubPicture subPicturesOld[] = subPictures;
//subPictures = new SubPicture[sup.getNumFrames()];
SubPicture picOld;
SubPicture picSrc;
double factTS;
double factX;
double factY;
double fsXNew;
double fsYNew;
if (configuration.getApplyFreeScale()) {
fsXNew = configuration.getFreeScaleFactorX();
fsYNew = configuration.getFreeScaleFactorY();
} else {
fsXNew = 1.0;
fsYNew = 1.0;
}
boolean convertFPS = configuration.getConvertFPS();
double fpsTrg = configuration.getFpsTrg();
double fpsSrc = configuration.getFPSSrc();
if (convertFPS && !convertFpsOld) {
factTS = fpsSrc / fpsTrg;
} else if (!convertFPS && convertFpsOld) {
factTS = fpsTrgOld / fpsSrc;
} else if (convertFPS && convertFpsOld && (fpsTrg != fpsTrgOld)) {
factTS = fpsTrgOld / fpsTrg;
} else {
factTS = 1.0;
}
// change target resolution to source resolution if no conversion is needed
if (!configuration.getConvertResolution() && getNumFrames() > 0) {
configuration.setOutputResolution(getResolutionForDimension(getSubPictureSrc(0).getWidth(), getSubPictureSrc(0).getHeight()));
}
if (resOld != configuration.getOutputResolution()) {
int rOld[] = resOld.getDimensions();
int rNew[] = configuration.getOutputResolution().getDimensions();
factX = (double)rNew[0]/(double)rOld[0];
factY = (double)rNew[1]/(double)rOld[1];
} else {
factX = 1.0;
factY = 1.0;
}
// first run: clone source subpics, apply speedup/down,
for (int i=0; i < subPictures.length; i++) {
picOld = subPictures[i];
picSrc = subtitleStream.getSubPicture(i);
subPictures[i] = new SubPicture(picOld);
// set forced flag
switch (configuration.getForceAll()) {
case SET:
subPictures[i].setForced(true);
break;
case CLEAR:
subPictures[i].setForced(false);
break;
}
long ts = picOld.getStartTime();
long te = picOld.getEndTime();
// copy time stamps and apply speedup/speeddown
int delayPTS = configuration.getDelayPTS();
if (factTS == 1.0) {
subPictures[i].setStartTime(ts - delayOld + delayPTS);
subPictures[i].setEndTime(te - delayOld + delayPTS);
} else {
subPictures[i].setStartTime((long)(ts * factTS + 0.5) - delayOld + delayPTS);
subPictures[i].setEndTime((long)(te * factTS + 0.5) - delayOld + delayPTS);
}
// synchronize to target frame rate
subPictures[i].setStartTime(SubtitleUtils.syncTimePTS(subPictures[i].getStartTime(), fpsTrg, fpsTrg));
subPictures[i].setEndTime(SubtitleUtils.syncTimePTS(subPictures[i].getEndTime(), fpsTrg, fpsTrg));
// adjust image sizes and offsets
// determine scaling factors
double scaleX;
double scaleY;
if (configuration.getConvertResolution()) {
subPictures[i].setWidth(configuration.getOutputResolution().getDimensions()[0]);
subPictures[i].setHeight(configuration.getOutputResolution().getDimensions()[1]);
scaleX = (double) subPictures[i].getWidth() / picSrc.getWidth();
scaleY = (double) subPictures[i].getHeight() / picSrc.getHeight();
} else {
subPictures[i].setWidth(picSrc.getWidth());
subPictures[i].setHeight(picSrc.getHeight());
scaleX = 1.0;
scaleY = 1.0;
}
int w = (int)(picSrc.getImageWidth() * scaleX * fsXNew + 0.5);
if (w < MIN_IMAGE_DIMENSION) {
w = picSrc.getImageWidth();
} else if (w > subPictures[i].getWidth()) {
w = subPictures[i].getWidth();
fsXNew = (double)w / (double)picSrc.getImageWidth() / scaleX;
}
int h = (int)(picSrc.getImageHeight() * scaleY * fsYNew + 0.5);
if (h < MIN_IMAGE_DIMENSION) {
h = picSrc.getImageHeight();
} else if (h > subPictures[i].getHeight()) {
h = subPictures[i].getHeight();
fsYNew = (double)h / (double)picSrc.getImageHeight() / scaleY;
}
subPictures[i].setImageWidth(w);
subPictures[i].setImageHeight(h);
// correct ratio change
int xOfs = (int)(picOld.getXOffset()*factX + 0.5);
if (fsXNew != fsXOld) {
int spaceTrgOld = (int)((picOld.getWidth() - picOld.getImageWidth())*factX + 0.5);
int spaceTrg = subPictures[i].getWidth() - w;
xOfs += (spaceTrg - spaceTrgOld) / 2;
}
if (xOfs < 0) {
xOfs = 0;
} else if (xOfs+w > subPictures[i].getWidth()) {
xOfs = subPictures[i].getWidth() - w;
}
subPictures[i].setOfsX(xOfs);
int yOfs = (int)(picOld.getYOffset()*factY + 0.5);
if (fsYNew != fsYOld) {
int spaceTrgOld = (int)((picOld.getHeight() - picOld.getImageHeight())*factY + 0.5);
int spaceTrg = subPictures[i].getHeight() - h;
yOfs += (spaceTrg - spaceTrgOld) / 2;
}
if (yOfs < 0) {
yOfs = 0;
}
if (yOfs+h > subPictures[i].getHeight()) {
yOfs = subPictures[i].getHeight() - h;
}
subPictures[i].setOfsY(yOfs);
// fix erase patches
double fx = factX * fsXNew / fsXOld;
double fy = factY * fsYNew / fsYOld;
List<ErasePatch> erasePatches = subPictures[i].getErasePatch();
if (!erasePatches.isEmpty()) {
for (int j = 0; j < erasePatches.size(); j++) {
ErasePatch ep = erasePatches.get(j);
int x = (int)(ep.x * fx + 0.5);
int y = (int)(ep.y * fy + 0.5);
int width = (int)(ep.width * fx + 0.5);
int height = (int)(ep.height * fy + 0.5);
erasePatches.set(j, new ErasePatch(x, y, width, height));
}
}
}
// 2nd run: validate times (not fully necessary, but to avoid overlap due to truncation
SubPicture subPicPrev = null;
SubPicture subPicNext;
for (int i=0; i<subPictures.length; i++) {
if (i < subPictures.length-1) {
subPicNext = subPictures[i+1];
} else {