diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/text/ssa/SsaDecoder.java b/library/extractor/src/main/java/com/google/android/exoplayer2/text/ssa/SsaDecoder.java index c6df62bb5f..c02e2338ab 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/text/ssa/SsaDecoder.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/text/ssa/SsaDecoder.java @@ -21,6 +21,7 @@ import static com.google.android.exoplayer2.util.Util.castNonNull; import android.graphics.Typeface; import android.text.Layout; import android.text.SpannableString; +import android.text.style.BackgroundColorSpan; import android.text.style.ForegroundColorSpan; import android.text.style.StrikethroughSpan; import android.text.style.StyleSpan; @@ -319,6 +320,13 @@ public final class SsaDecoder extends SimpleSubtitleDecoder { /* end= */ spannableText.length(), SpannableString.SPAN_EXCLUSIVE_EXCLUSIVE); } + if (style.outlineColor != null) { + spannableText.setSpan( + new BackgroundColorSpan(style.outlineColor), + /* start= */ 0, + /* end= */ spannableText.length(), + 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); diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/text/ssa/SsaStyle.java b/library/extractor/src/main/java/com/google/android/exoplayer2/text/ssa/SsaStyle.java index 8e09291312..92821c02d9 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/text/ssa/SsaStyle.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/text/ssa/SsaStyle.java @@ -95,6 +95,7 @@ import java.util.regex.Pattern; public final String name; public final @SsaAlignment int alignment; @Nullable @ColorInt public final Integer primaryColor; + @Nullable @ColorInt public final Integer outlineColor; public final float fontSize; public final boolean bold; public final boolean italic; @@ -105,6 +106,7 @@ import java.util.regex.Pattern; String name, @SsaAlignment int alignment, @Nullable @ColorInt Integer primaryColor, + @Nullable @ColorInt Integer outlineColor, float fontSize, boolean bold, boolean italic, @@ -113,6 +115,7 @@ import java.util.regex.Pattern; this.name = name; this.alignment = alignment; this.primaryColor = primaryColor; + this.outlineColor = outlineColor; this.fontSize = fontSize; this.bold = bold; this.italic = italic; @@ -141,6 +144,9 @@ import java.util.regex.Pattern; format.primaryColorIndex != C.INDEX_UNSET ? parseColor(styleValues[format.primaryColorIndex].trim()) : null, + format.outlineColorIndex != C.INDEX_UNSET + ? parseColor(styleValues[format.outlineColorIndex].trim()) + : null, format.fontSizeIndex != C.INDEX_UNSET ? parseFontSize(styleValues[format.fontSizeIndex].trim()) : Cue.DIMEN_UNSET, @@ -257,6 +263,7 @@ import java.util.regex.Pattern; public final int nameIndex; public final int alignmentIndex; public final int primaryColorIndex; + public final int outlineColorIndex; public final int fontSizeIndex; public final int boldIndex; public final int italicIndex; @@ -268,6 +275,7 @@ import java.util.regex.Pattern; int nameIndex, int alignmentIndex, int primaryColorIndex, + int outlineColorIndex, int fontSizeIndex, int boldIndex, int italicIndex, @@ -277,6 +285,7 @@ import java.util.regex.Pattern; this.nameIndex = nameIndex; this.alignmentIndex = alignmentIndex; this.primaryColorIndex = primaryColorIndex; + this.outlineColorIndex = outlineColorIndex; this.fontSizeIndex = fontSizeIndex; this.boldIndex = boldIndex; this.italicIndex = italicIndex; @@ -295,6 +304,7 @@ import java.util.regex.Pattern; int nameIndex = C.INDEX_UNSET; int alignmentIndex = C.INDEX_UNSET; int primaryColorIndex = C.INDEX_UNSET; + int outlineColorIndex = C.INDEX_UNSET; int fontSizeIndex = C.INDEX_UNSET; int boldIndex = C.INDEX_UNSET; int italicIndex = C.INDEX_UNSET; @@ -313,6 +323,9 @@ import java.util.regex.Pattern; case "primarycolour": primaryColorIndex = i; break; + case "outlinecolour": + outlineColorIndex = i; + break; case "fontsize": fontSizeIndex = i; break; @@ -335,6 +348,7 @@ import java.util.regex.Pattern; nameIndex, alignmentIndex, primaryColorIndex, + outlineColorIndex, fontSizeIndex, boldIndex, italicIndex, diff --git a/library/extractor/src/test/java/com/google/android/exoplayer2/text/ssa/SsaDecoderTest.java b/library/extractor/src/test/java/com/google/android/exoplayer2/text/ssa/SsaDecoderTest.java index 4b3b8cef64..a4001a2d4b 100644 --- a/library/extractor/src/test/java/com/google/android/exoplayer2/text/ssa/SsaDecoderTest.java +++ b/library/extractor/src/test/java/com/google/android/exoplayer2/text/ssa/SsaDecoderTest.java @@ -301,7 +301,7 @@ public final class SsaDecoderTest { SsaDecoder decoder = new SsaDecoder(); byte[] bytes = TestUtil.getByteArray(ApplicationProvider.getApplicationContext(), STYLE_COLORS); Subtitle subtitle = decoder.decode(bytes, bytes.length, false); - assertThat(subtitle.getEventTimeCount()).isEqualTo(14); + assertThat(subtitle.getEventTimeCount()).isEqualTo(16); // &H000000FF (AABBGGRR) -> #FFFF0000 (AARRGGBB) Spanned firstCueText = (Spanned) Iterables.getOnlyElement(subtitle.getCues(subtitle.getEventTime(0))).text; @@ -342,6 +342,11 @@ public final class SsaDecoderTest { (Spanned) Iterables.getOnlyElement(subtitle.getCues(subtitle.getEventTime(12))).text; SpannedSubject.assertThat(seventhCueText) .hasNoForegroundColorSpanBetween(0, seventhCueText.length()); + Spanned eighthCueText = + (Spanned) Iterables.getOnlyElement(subtitle.getCues(subtitle.getEventTime(14))).text; + SpannedSubject.assertThat(eighthCueText) + .hasBackgroundColorSpanBetween(0, eighthCueText.length()) + .withColor(Color.BLUE); } @Test diff --git a/testdata/src/test/assets/media/ssa/style_colors b/testdata/src/test/assets/media/ssa/style_colors index a224e7ed4d..fe31e66380 100644 --- a/testdata/src/test/assets/media/ssa/style_colors +++ b/testdata/src/test/assets/media/ssa/style_colors @@ -5,14 +5,15 @@ PlayResX: 1280 PlayResY: 720 [V4+ Styles] -Format: Name ,PrimaryColour -Style: PrimaryColourStyleHexRed ,&H000000FF -Style: PrimaryColourStyleHexYellow ,&H0000FFFF -Style: PrimaryColourStyleHexGreen ,&HFF00 -Style: PrimaryColourStyleHexAlpha ,&HA00000FF -Style: PrimaryColourStyleDecimal ,16711680 -Style: PrimaryColourStyleDecimalAlpha,2164195328 -Style: PrimaryColourStyleInvalid ,blue +Format: Name ,PrimaryColour,OutlineColour +Style: PrimaryColourStyleHexRed ,&H000000FF ,&H00000000 +Style: PrimaryColourStyleHexYellow ,&H0000FFFF ,&H00000000 +Style: PrimaryColourStyleHexGreen ,&HFF00 ,&H00000000 +Style: PrimaryColourStyleHexAlpha ,&HA00000FF ,&H00000000 +Style: PrimaryColourStyleDecimal ,16711680 ,&H00000000 +Style: PrimaryColourStyleDecimalAlpha,2164195328 ,&H00000000 +Style: PrimaryColourStyleInvalid ,blue ,&H00000000 +Style: OutlineColourStyleBlue ,&H00000000 ,&H00FF0000 [Events] @@ -24,3 +25,4 @@ Dialogue: 0:00:07.00,0:00:08.00,PrimaryColourStyleHexAlpha ,Fourth line in RE Dialogue: 0:00:09.00,0:00:10.00,PrimaryColourStyleDecimal ,Fifth line in BLUE (16711680). Dialogue: 0:00:11.00,0:00:12.00,PrimaryColourStyleDecimalAlpha,Sixth line in BLUE with alpha (2164195328). Dialogue: 0:00:13.00,0:00:14.00,PrimaryColourInvalid ,Seventh line with invalid color. +Dialogue: 0:00:15.00,0:00:16.00,OutlineColourStyleBlue ,Eighth line with BLUE (&H00FF0000) outline.