Merge pull request #8615 from szaboa:dev-v2-8435-ssa-font-size
PiperOrigin-RevId: 359244236
This commit is contained in:
commit
4ed36e19cf
@ -51,6 +51,9 @@
|
|||||||
video tracks (previously separate acquire and release events were
|
video tracks (previously separate acquire and release events were
|
||||||
dispatched for each track in each period).
|
dispatched for each track in each period).
|
||||||
* Include the session state in DRM session-acquired listener methods.
|
* Include the session state in DRM session-acquired listener methods.
|
||||||
|
* 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 {
|
|||||||
/* 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;
|
|||||||
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;
|
|||||||
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;
|
|||||||
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;
|
|||||||
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;
|
|||||||
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;
|
|||||||
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;
|
|||||||
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 {
|
|||||||
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 {
|
|||||||
@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 {
|
|||||||
.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())
|
||||||
|
18
testdata/src/test/assets/media/ssa/style_font_size
vendored
Normal file
18
testdata/src/test/assets/media/ssa/style_font_size
vendored
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
[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.
|
Loading…
x
Reference in New Issue
Block a user