Commit e21b99a6 by marcbaechinger

Merge pull request #8615 from szaboa:dev-v2-8435-ssa-font-size

PiperOrigin-RevId: 359244236
parent 3f8f7ba9
...@@ -21,6 +21,9 @@ ...@@ -21,6 +21,9 @@
* Fix a bug with playback of ads in playlists, where the incorrect period * Fix a bug with playback of ads in playlists, where the incorrect period
index was used when deciding whether to trigger playback of an ad after index was used when deciding whether to trigger playback of an ad after
a seek. a seek.
* Text:
* Parse SSA/ASS font size in `Style:` lines
([#8435](https://github.com/google/ExoPlayer/issues/8435)).
* VP9 extension: Update to use NDK r22 * VP9 extension: Update to use NDK r22
([#8581](https://github.com/google/ExoPlayer/issues/8581)). ([#8581](https://github.com/google/ExoPlayer/issues/8581)).
* FLAC extension: Update to use NDK r22 * FLAC extension: Update to use NDK r22
......
...@@ -314,6 +314,10 @@ public final class SsaDecoder extends SimpleSubtitleDecoder { ...@@ -314,6 +314,10 @@ public final class SsaDecoder extends SimpleSubtitleDecoder {
/* end= */ spannableText.length(), /* end= */ spannableText.length(),
SpannableString.SPAN_EXCLUSIVE_EXCLUSIVE); SpannableString.SPAN_EXCLUSIVE_EXCLUSIVE);
} }
if (style.fontSize != Cue.DIMEN_UNSET && screenHeight != Cue.DIMEN_UNSET) {
cue.setTextSize(
style.fontSize / screenHeight, Cue.TEXT_SIZE_TYPE_FRACTIONAL_IGNORE_PADDING);
}
} }
@SsaStyle.SsaAlignment int alignment; @SsaStyle.SsaAlignment int alignment;
......
...@@ -27,6 +27,7 @@ import androidx.annotation.ColorInt; ...@@ -27,6 +27,7 @@ import androidx.annotation.ColorInt;
import androidx.annotation.IntDef; import androidx.annotation.IntDef;
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.util.Assertions; import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.Log; import com.google.android.exoplayer2.util.Log;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
...@@ -90,12 +91,17 @@ import java.util.regex.Pattern; ...@@ -90,12 +91,17 @@ import java.util.regex.Pattern;
public final String name; public final String name;
@SsaAlignment public final int alignment; @SsaAlignment public final int alignment;
@Nullable @ColorInt public final Integer primaryColor; @Nullable @ColorInt public final Integer primaryColor;
public final float fontSize;
private SsaStyle( private SsaStyle(
String name, @SsaAlignment int alignment, @Nullable @ColorInt Integer primaryColor) { String name,
@SsaAlignment int alignment,
@Nullable @ColorInt Integer primaryColor,
float fontSize) {
this.name = name; this.name = name;
this.alignment = alignment; this.alignment = alignment;
this.primaryColor = primaryColor; this.primaryColor = primaryColor;
this.fontSize = fontSize;
} }
@Nullable @Nullable
...@@ -114,7 +120,8 @@ import java.util.regex.Pattern; ...@@ -114,7 +120,8 @@ import java.util.regex.Pattern;
return new SsaStyle( return new SsaStyle(
styleValues[format.nameIndex].trim(), styleValues[format.nameIndex].trim(),
parseAlignment(styleValues[format.alignmentIndex].trim()), parseAlignment(styleValues[format.alignmentIndex].trim()),
parseColor(styleValues[format.primaryColorIndex].trim())); parseColor(styleValues[format.primaryColorIndex].trim()),
parseFontSize(styleValues[format.fontSizeIndex].trim()));
} catch (RuntimeException e) { } catch (RuntimeException e) {
Log.w(TAG, "Skipping malformed 'Style:' line: '" + styleLine + "'", e); Log.w(TAG, "Skipping malformed 'Style:' line: '" + styleLine + "'", e);
return null; return null;
...@@ -191,6 +198,15 @@ import java.util.regex.Pattern; ...@@ -191,6 +198,15 @@ import java.util.regex.Pattern;
return Color.argb(a, r, g, b); return Color.argb(a, r, g, b);
} }
private static float parseFontSize(String fontSize) {
try {
return Float.parseFloat(fontSize);
} catch (NumberFormatException e) {
Log.w(TAG, "Failed to parse font size: '" + fontSize + "'", e);
return Cue.DIMEN_UNSET;
}
}
/** /**
* Represents a {@code Format:} line from the {@code [V4+ Styles]} section * Represents a {@code Format:} line from the {@code [V4+ Styles]} section
* *
...@@ -202,12 +218,15 @@ import java.util.regex.Pattern; ...@@ -202,12 +218,15 @@ import java.util.regex.Pattern;
public final int nameIndex; public final int nameIndex;
public final int alignmentIndex; public final int alignmentIndex;
public final int primaryColorIndex; public final int primaryColorIndex;
public final int fontSizeIndex;
public final int length; public final int length;
private Format(int nameIndex, int alignmentIndex, int primaryColorIndex, int length) { private Format(
int nameIndex, int alignmentIndex, int primaryColorIndex, int fontSizeIndex, int length) {
this.nameIndex = nameIndex; this.nameIndex = nameIndex;
this.alignmentIndex = alignmentIndex; this.alignmentIndex = alignmentIndex;
this.primaryColorIndex = primaryColorIndex; this.primaryColorIndex = primaryColorIndex;
this.fontSizeIndex = fontSizeIndex;
this.length = length; this.length = length;
} }
...@@ -221,6 +240,7 @@ import java.util.regex.Pattern; ...@@ -221,6 +240,7 @@ import java.util.regex.Pattern;
int nameIndex = C.INDEX_UNSET; int nameIndex = C.INDEX_UNSET;
int alignmentIndex = C.INDEX_UNSET; int alignmentIndex = C.INDEX_UNSET;
int primaryColorIndex = C.INDEX_UNSET; int primaryColorIndex = C.INDEX_UNSET;
int fontSizeIndex = C.INDEX_UNSET;
String[] keys = String[] keys =
TextUtils.split(styleFormatLine.substring(SsaDecoder.FORMAT_LINE_PREFIX.length()), ","); TextUtils.split(styleFormatLine.substring(SsaDecoder.FORMAT_LINE_PREFIX.length()), ",");
for (int i = 0; i < keys.length; i++) { for (int i = 0; i < keys.length; i++) {
...@@ -234,10 +254,13 @@ import java.util.regex.Pattern; ...@@ -234,10 +254,13 @@ import java.util.regex.Pattern;
case "primarycolour": case "primarycolour":
primaryColorIndex = i; primaryColorIndex = i;
break; break;
case "fontsize":
fontSizeIndex = i;
break;
} }
} }
return nameIndex != C.INDEX_UNSET return nameIndex != C.INDEX_UNSET
? new Format(nameIndex, alignmentIndex, primaryColorIndex, keys.length) ? new Format(nameIndex, alignmentIndex, primaryColorIndex, fontSizeIndex, keys.length)
: null; : null;
} }
} }
......
...@@ -47,7 +47,8 @@ public final class SsaDecoderTest { ...@@ -47,7 +47,8 @@ public final class SsaDecoderTest {
private static final String INVALID_TIMECODES = "media/ssa/invalid_timecodes"; private static final String INVALID_TIMECODES = "media/ssa/invalid_timecodes";
private static final String INVALID_POSITIONS = "media/ssa/invalid_positioning"; private static final String INVALID_POSITIONS = "media/ssa/invalid_positioning";
private static final String POSITIONS_WITHOUT_PLAYRES = "media/ssa/positioning_without_playres"; private static final String POSITIONS_WITHOUT_PLAYRES = "media/ssa/positioning_without_playres";
private static final String COLORS = "media/ssa/colors"; private static final String STYLE_COLORS = "media/ssa/style_colors";
private static final String STYLE_FONT_SIZE = "media/ssa/style_font_size";
@Test @Test
public void decodeEmpty() throws IOException { public void decodeEmpty() throws IOException {
...@@ -274,7 +275,7 @@ public final class SsaDecoderTest { ...@@ -274,7 +275,7 @@ public final class SsaDecoderTest {
@Test @Test
public void decodeColors() throws IOException { public void decodeColors() throws IOException {
SsaDecoder decoder = new SsaDecoder(); SsaDecoder decoder = new SsaDecoder();
byte[] bytes = TestUtil.getByteArray(ApplicationProvider.getApplicationContext(), COLORS); byte[] bytes = TestUtil.getByteArray(ApplicationProvider.getApplicationContext(), STYLE_COLORS);
Subtitle subtitle = decoder.decode(bytes, bytes.length, false); Subtitle subtitle = decoder.decode(bytes, bytes.length, false);
assertThat(subtitle.getEventTimeCount()).isEqualTo(14); assertThat(subtitle.getEventTimeCount()).isEqualTo(14);
// &H000000FF (AABBGGRR) -> #FFFF0000 (AARRGGBB) // &H000000FF (AABBGGRR) -> #FFFF0000 (AARRGGBB)
...@@ -319,6 +320,22 @@ public final class SsaDecoderTest { ...@@ -319,6 +320,22 @@ public final class SsaDecoderTest {
.hasNoForegroundColorSpanBetween(0, seventhCueText.length()); .hasNoForegroundColorSpanBetween(0, seventhCueText.length());
} }
@Test
public void decodeFontSize() throws IOException {
SsaDecoder decoder = new SsaDecoder();
byte[] bytes =
TestUtil.getByteArray(ApplicationProvider.getApplicationContext(), STYLE_FONT_SIZE);
Subtitle subtitle = decoder.decode(bytes, bytes.length, false);
assertThat(subtitle.getEventTimeCount()).isEqualTo(4);
Cue firstCue = Iterables.getOnlyElement(subtitle.getCues(subtitle.getEventTime(0)));
assertThat(firstCue.textSize).isWithin(1.0e-8f).of(30f / 720f);
assertThat(firstCue.textSizeType).isEqualTo(Cue.TEXT_SIZE_TYPE_FRACTIONAL_IGNORE_PADDING);
Cue secondCue = Iterables.getOnlyElement(subtitle.getCues(subtitle.getEventTime(2)));
assertThat(secondCue.textSize).isWithin(1.0e-8f).of(72.2f / 720f);
assertThat(secondCue.textSizeType).isEqualTo(Cue.TEXT_SIZE_TYPE_FRACTIONAL_IGNORE_PADDING);
}
private static void assertTypicalCue1(Subtitle subtitle, int eventIndex) { private static void assertTypicalCue1(Subtitle subtitle, int eventIndex) {
assertThat(subtitle.getEventTime(eventIndex)).isEqualTo(0); assertThat(subtitle.getEventTime(eventIndex)).isEqualTo(0);
assertThat(subtitle.getCues(subtitle.getEventTime(eventIndex)).get(0).text.toString()) assertThat(subtitle.getCues(subtitle.getEventTime(eventIndex)).get(0).text.toString())
......
[Script Info]
Title: SSA/ASS Test
Original Script: Arnold Szabo
Script Type: V4.00+
PlayResX: 1280
PlayResY: 720
[V4+ Styles]
Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding
Style: FontSizeSmall ,Roboto,30, &H000000FF,&H000000FF,&H00000000,&H00000000,0,0,0,0,100,100,0,0,1,3,0,2,50,50,70,1
Style: FontSizeBig ,Roboto,72.2,&H000000FF,&H000000FF,&H00000000,&H00000000,0,0,0,0,100,100,0,0,1,3,0,2,50,50,70,1
[Events]
Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
Dialogue: 0,0:00:00.95,0:00:03.11,FontSizeSmall ,Arnold,0,0,0,,First line with font size 30.
Dialogue: 0,0:00:08.50,0:00:11.50,FontSizeBig ,Arnold,0,0,0,,Second line with font size 72.2.
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