Commit 57916774 by Arnold Szabo

Parse and apply position attribute in SSA subtitles

parent 694ccf42
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
package com.google.android.exoplayer2.text.ssa; package com.google.android.exoplayer2.text.ssa;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Pair;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.text.Cue; import com.google.android.exoplayer2.text.Cue;
...@@ -40,6 +41,9 @@ public final class SsaDecoder extends SimpleSubtitleDecoder { ...@@ -40,6 +41,9 @@ public final class SsaDecoder extends SimpleSubtitleDecoder {
private static final Pattern SSA_TIMECODE_PATTERN = Pattern.compile( private static final Pattern SSA_TIMECODE_PATTERN = Pattern.compile(
"(?:(\\d+):)?(\\d+):(\\d+)(?::|\\.)(\\d+)"); "(?:(\\d+):)?(\\d+):(\\d+)(?::|\\.)(\\d+)");
private static final Pattern SSA_POSITION_PATTERN = Pattern.compile(
"\\\\pos\\((\\d+(\\.\\d+)?),\\s*(\\d+(\\.\\d+)?)");
private static final String FORMAT_LINE_PREFIX = "Format: "; private static final String FORMAT_LINE_PREFIX = "Format: ";
private static final String DIALOGUE_LINE_PREFIX = "Dialogue: "; private static final String DIALOGUE_LINE_PREFIX = "Dialogue: ";
...@@ -50,6 +54,9 @@ public final class SsaDecoder extends SimpleSubtitleDecoder { ...@@ -50,6 +54,9 @@ public final class SsaDecoder extends SimpleSubtitleDecoder {
private int formatEndIndex; private int formatEndIndex;
private int formatTextIndex; private int formatTextIndex;
private int playResX;
private int playResY;
public SsaDecoder() { public SsaDecoder() {
this(/* initializationData= */ null); this(/* initializationData= */ null);
} }
...@@ -98,6 +105,12 @@ public final class SsaDecoder extends SimpleSubtitleDecoder { ...@@ -98,6 +105,12 @@ public final class SsaDecoder extends SimpleSubtitleDecoder {
private void parseHeader(ParsableByteArray data) { private void parseHeader(ParsableByteArray data) {
String currentLine; String currentLine;
while ((currentLine = data.readLine()) != null) { while ((currentLine = data.readLine()) != null) {
if (currentLine.startsWith("PlayResX:")) {
playResX = Integer.valueOf(currentLine.substring(9).trim());
}
if (currentLine.startsWith("PlayResY:")) {
playResY = Integer.valueOf(currentLine.substring(9).trim());
}
// TODO: Parse useful data from the header. // TODO: Parse useful data from the header.
if (currentLine.startsWith("[Events]")) { if (currentLine.startsWith("[Events]")) {
// We've reached the event body. // We've reached the event body.
...@@ -196,11 +209,30 @@ public final class SsaDecoder extends SimpleSubtitleDecoder { ...@@ -196,11 +209,30 @@ public final class SsaDecoder extends SimpleSubtitleDecoder {
} }
} }
// Parse \pos{x,y} attribute
Pair<Float, Float> position = parsePosition(lineValues[formatTextIndex]);
String text = lineValues[formatTextIndex] String text = lineValues[formatTextIndex]
.replaceAll("\\{.*?\\}", "") .replaceAll("\\{.*?\\}", "")
.replaceAll("\\\\N", "\n") .replaceAll("\\\\N", "\n")
.replaceAll("\\\\n", "\n"); .replaceAll("\\\\n", "\n");
cues.add(new Cue(text));
Cue cue;
if (position != null && playResX != 0 && playResY != 0) {
cue = new Cue(
text,
/* textAlignment */ null,
1 - position.second / playResY,
Cue.LINE_TYPE_FRACTION,
Cue.ANCHOR_TYPE_START,
position.first / playResX,
Cue.ANCHOR_TYPE_MIDDLE,
Cue.DIMEN_UNSET);
} else {
cue = new Cue(text);
}
cues.add(cue);
cueTimesUs.add(startTimeUs); cueTimesUs.add(startTimeUs);
if (endTimeUs != C.TIME_UNSET) { if (endTimeUs != C.TIME_UNSET) {
cues.add(Cue.EMPTY); cues.add(Cue.EMPTY);
...@@ -226,4 +258,21 @@ public final class SsaDecoder extends SimpleSubtitleDecoder { ...@@ -226,4 +258,21 @@ public final class SsaDecoder extends SimpleSubtitleDecoder {
return timestampUs; return timestampUs;
} }
/**
* Parses an SSA position attribute.
*
* @param line The string to parse.
* @return The parsed position in a pair (x,y).
*/
@Nullable
public static Pair<Float, Float> parsePosition(String line) {
Matcher matcher = SSA_POSITION_PATTERN.matcher(line);
if (!matcher.find()) {
return null;
}
float x = Float.parseFloat(matcher.group(1));
float y = Float.parseFloat(matcher.group(3));
return new Pair<>(x, y);
}
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment