Migrate SubtitleParser
tests to incremental parse()
methods
All the production code is already calling these new incremental methods, migrating the tests allows us to remove the old `List`-returning methods in a follow-up change. #minor-release PiperOrigin-RevId: 572822828
This commit is contained in:
parent
d1fc15f207
commit
a12bde4f57
@ -24,6 +24,8 @@ import android.text.Layout;
|
||||
import android.text.Spanned;
|
||||
import androidx.media3.common.text.Cue;
|
||||
import androidx.media3.extractor.text.CuesWithTiming;
|
||||
import androidx.media3.extractor.text.SubtitleParser;
|
||||
import androidx.media3.extractor.text.SubtitleParser.OutputOptions;
|
||||
import androidx.media3.test.utils.TestUtil;
|
||||
import androidx.media3.test.utils.truth.SpannedSubject;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
@ -71,7 +73,7 @@ public final class SsaParserTest {
|
||||
public void parseEmpty() throws IOException {
|
||||
SsaParser parser = new SsaParser();
|
||||
byte[] bytes = TestUtil.getByteArray(ApplicationProvider.getApplicationContext(), EMPTY);
|
||||
List<CuesWithTiming> allCues = parser.parse(bytes);
|
||||
ImmutableList<CuesWithTiming> allCues = parseAllCues(parser, bytes);
|
||||
|
||||
assertThat(allCues).isEmpty();
|
||||
}
|
||||
@ -81,7 +83,7 @@ public final class SsaParserTest {
|
||||
SsaParser parser = new SsaParser();
|
||||
byte[] bytes =
|
||||
TestUtil.getByteArray(ApplicationProvider.getApplicationContext(), EMPTY_STYLE_LINE);
|
||||
List<CuesWithTiming> allCues = parser.parse(bytes);
|
||||
ImmutableList<CuesWithTiming> allCues = parseAllCues(parser, bytes);
|
||||
|
||||
assertThat(allCues).hasSize(1);
|
||||
Cue cue = Iterables.getOnlyElement(allCues.get(0).cues);
|
||||
@ -101,7 +103,7 @@ public final class SsaParserTest {
|
||||
public void parseTypical() throws IOException {
|
||||
SsaParser parser = new SsaParser();
|
||||
byte[] bytes = TestUtil.getByteArray(ApplicationProvider.getApplicationContext(), TYPICAL);
|
||||
List<CuesWithTiming> allCues = parser.parse(bytes);
|
||||
ImmutableList<CuesWithTiming> allCues = parseAllCues(parser, bytes);
|
||||
|
||||
assertThat(allCues).hasSize(3);
|
||||
// Check position, line, anchors & alignment are set from Alignment Style (2 - bottom-center).
|
||||
@ -122,6 +124,34 @@ public final class SsaParserTest {
|
||||
assertTypicalCue3(allCues.get(2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseTypical_onlyCuesAfterTime() throws IOException {
|
||||
SsaParser parser = new SsaParser();
|
||||
byte[] bytes = TestUtil.getByteArray(ApplicationProvider.getApplicationContext(), TYPICAL);
|
||||
List<CuesWithTiming> cues = new ArrayList<>();
|
||||
parser.parse(bytes, OutputOptions.onlyCuesAfter(/* startTimeUs= */ 1_000_000), cues::add);
|
||||
|
||||
assertThat(cues).hasSize(2);
|
||||
assertTypicalCue2(cues.get(0));
|
||||
assertTypicalCue3(cues.get(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseTypical_cuesAfterTimeThenCuesBefore() throws IOException {
|
||||
SsaParser parser = new SsaParser();
|
||||
byte[] bytes = TestUtil.getByteArray(ApplicationProvider.getApplicationContext(), TYPICAL);
|
||||
List<CuesWithTiming> cues = new ArrayList<>();
|
||||
parser.parse(
|
||||
bytes,
|
||||
OutputOptions.cuesAfterThenRemainingCuesBefore(/* startTimeUs= */ 1_000_000),
|
||||
cues::add);
|
||||
|
||||
assertThat(cues).hasSize(3);
|
||||
assertTypicalCue2(cues.get(0));
|
||||
assertTypicalCue3(cues.get(1));
|
||||
assertTypicalCue1(cues.get(2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseTypicalWithInitializationData() throws IOException {
|
||||
byte[] headerBytes =
|
||||
@ -134,7 +164,7 @@ public final class SsaParserTest {
|
||||
SsaParser parser = new SsaParser(initializationData);
|
||||
byte[] bytes =
|
||||
TestUtil.getByteArray(ApplicationProvider.getApplicationContext(), TYPICAL_DIALOGUE_ONLY);
|
||||
List<CuesWithTiming> allCues = parser.parse(bytes);
|
||||
ImmutableList<CuesWithTiming> allCues = parseAllCues(parser, bytes);
|
||||
|
||||
assertThat(allCues).hasSize(3);
|
||||
assertTypicalCue1(allCues.get(0));
|
||||
@ -155,8 +185,13 @@ public final class SsaParserTest {
|
||||
SsaParser parser = new SsaParser(initializationData);
|
||||
byte[] bytes =
|
||||
TestUtil.getByteArray(ApplicationProvider.getApplicationContext(), TYPICAL_DIALOGUE_ONLY);
|
||||
ImmutableList<CuesWithTiming> allCues =
|
||||
parser.parse(bytes, /* offset= */ 10, /* length= */ bytes.length - 30);
|
||||
List<CuesWithTiming> allCues = new ArrayList<>();
|
||||
parser.parse(
|
||||
bytes,
|
||||
/* offset= */ 10,
|
||||
/* length= */ bytes.length - 30,
|
||||
OutputOptions.allCues(),
|
||||
allCues::add);
|
||||
|
||||
assertThat(allCues).hasSize(2);
|
||||
// Because of the offset, we skip the first line of dialogue
|
||||
@ -173,7 +208,7 @@ public final class SsaParserTest {
|
||||
SsaParser parser = new SsaParser();
|
||||
byte[] bytes =
|
||||
TestUtil.getByteArray(ApplicationProvider.getApplicationContext(), TYPICAL_UTF16LE);
|
||||
List<CuesWithTiming> allCues = parser.parse(bytes);
|
||||
ImmutableList<CuesWithTiming> allCues = parseAllCues(parser, bytes);
|
||||
|
||||
assertThat(allCues).hasSize(3);
|
||||
// Check position, line, anchors & alignment are set from Alignment Style (2 - bottom-center).
|
||||
@ -199,7 +234,7 @@ public final class SsaParserTest {
|
||||
SsaParser parser = new SsaParser();
|
||||
byte[] bytes =
|
||||
TestUtil.getByteArray(ApplicationProvider.getApplicationContext(), TYPICAL_UTF16BE);
|
||||
List<CuesWithTiming> allCues = parser.parse(bytes);
|
||||
ImmutableList<CuesWithTiming> allCues = parseAllCues(parser, bytes);
|
||||
|
||||
assertThat(allCues).hasSize(3);
|
||||
// Check position, line, anchors & alignment are set from Alignment Style (2 - bottom-center).
|
||||
@ -225,7 +260,7 @@ public final class SsaParserTest {
|
||||
SsaParser parser = new SsaParser();
|
||||
byte[] bytes =
|
||||
TestUtil.getByteArray(ApplicationProvider.getApplicationContext(), OVERLAPPING_TIMECODES);
|
||||
List<CuesWithTiming> allCues = parser.parse(bytes);
|
||||
ImmutableList<CuesWithTiming> allCues = parseAllCues(parser, bytes);
|
||||
|
||||
String firstSubtitleText = "First subtitle - end overlaps second";
|
||||
String secondSubtitleText = "Second subtitle - beginning overlaps first";
|
||||
@ -289,7 +324,7 @@ public final class SsaParserTest {
|
||||
public void parsePositions() throws IOException {
|
||||
SsaParser parser = new SsaParser();
|
||||
byte[] bytes = TestUtil.getByteArray(ApplicationProvider.getApplicationContext(), POSITIONS);
|
||||
List<CuesWithTiming> allCues = parser.parse(bytes);
|
||||
ImmutableList<CuesWithTiming> allCues = parseAllCues(parser, bytes);
|
||||
|
||||
// Check \pos() sets position & line
|
||||
Cue firstCue = Iterables.getOnlyElement(allCues.get(0).cues);
|
||||
@ -343,7 +378,7 @@ public final class SsaParserTest {
|
||||
SsaParser parser = new SsaParser();
|
||||
byte[] bytes =
|
||||
TestUtil.getByteArray(ApplicationProvider.getApplicationContext(), INVALID_POSITIONS);
|
||||
List<CuesWithTiming> allCues = parser.parse(bytes);
|
||||
ImmutableList<CuesWithTiming> allCues = parseAllCues(parser, bytes);
|
||||
|
||||
// Negative parameter to \pos() - fall back to the positions implied by middle-left alignment.
|
||||
Cue firstCue = Iterables.getOnlyElement(allCues.get(0).cues);
|
||||
@ -380,7 +415,7 @@ public final class SsaParserTest {
|
||||
byte[] bytes =
|
||||
TestUtil.getByteArray(
|
||||
ApplicationProvider.getApplicationContext(), POSITIONS_WITHOUT_PLAYRES);
|
||||
List<CuesWithTiming> allCues = parser.parse(bytes);
|
||||
ImmutableList<CuesWithTiming> allCues = parseAllCues(parser, bytes);
|
||||
|
||||
// The dialogue line has a valid \pos() override, but it's ignored because PlayResY isn't
|
||||
// set (so we don't know the denominator).
|
||||
@ -396,7 +431,7 @@ public final class SsaParserTest {
|
||||
SsaParser parser = new SsaParser();
|
||||
byte[] bytes =
|
||||
TestUtil.getByteArray(ApplicationProvider.getApplicationContext(), INVALID_TIMECODES);
|
||||
List<CuesWithTiming> allCues = parser.parse(bytes);
|
||||
ImmutableList<CuesWithTiming> allCues = parseAllCues(parser, bytes);
|
||||
|
||||
assertThat(allCues).hasSize(1);
|
||||
assertTypicalCue3(Iterables.getOnlyElement(allCues));
|
||||
@ -407,7 +442,7 @@ public final class SsaParserTest {
|
||||
SsaParser parser = new SsaParser();
|
||||
byte[] bytes =
|
||||
TestUtil.getByteArray(ApplicationProvider.getApplicationContext(), STYLE_PRIMARY_COLOR);
|
||||
List<CuesWithTiming> allCues = parser.parse(bytes);
|
||||
ImmutableList<CuesWithTiming> allCues = parseAllCues(parser, bytes);
|
||||
assertThat(allCues).hasSize(7);
|
||||
// &H000000FF (AABBGGRR) -> #FFFF0000 (AARRGGBB)
|
||||
Spanned firstCueText = (Spanned) Iterables.getOnlyElement(allCues.get(0).cues).text;
|
||||
@ -449,7 +484,7 @@ public final class SsaParserTest {
|
||||
SsaParser parser = new SsaParser();
|
||||
byte[] bytes =
|
||||
TestUtil.getByteArray(ApplicationProvider.getApplicationContext(), STYLE_OUTLINE_COLOR);
|
||||
List<CuesWithTiming> allCues = parser.parse(bytes);
|
||||
ImmutableList<CuesWithTiming> allCues = parseAllCues(parser, bytes);
|
||||
assertThat(allCues).hasSize(2);
|
||||
Spanned firstCueText = (Spanned) Iterables.getOnlyElement(allCues.get(0).cues).text;
|
||||
SpannedSubject.assertThat(firstCueText)
|
||||
@ -467,7 +502,7 @@ public final class SsaParserTest {
|
||||
SsaParser parser = new SsaParser();
|
||||
byte[] bytes =
|
||||
TestUtil.getByteArray(ApplicationProvider.getApplicationContext(), STYLE_FONT_SIZE);
|
||||
List<CuesWithTiming> allCues = parser.parse(bytes);
|
||||
ImmutableList<CuesWithTiming> allCues = parseAllCues(parser, bytes);
|
||||
assertThat(allCues).hasSize(2);
|
||||
|
||||
Cue firstCue = Iterables.getOnlyElement(allCues.get(0).cues);
|
||||
@ -483,7 +518,7 @@ public final class SsaParserTest {
|
||||
SsaParser parser = new SsaParser();
|
||||
byte[] bytes =
|
||||
TestUtil.getByteArray(ApplicationProvider.getApplicationContext(), STYLE_BOLD_ITALIC);
|
||||
List<CuesWithTiming> allCues = parser.parse(bytes);
|
||||
ImmutableList<CuesWithTiming> allCues = parseAllCues(parser, bytes);
|
||||
assertThat(allCues).hasSize(3);
|
||||
|
||||
Spanned firstCueText = (Spanned) Iterables.getOnlyElement(allCues.get(0).cues).text;
|
||||
@ -499,7 +534,7 @@ public final class SsaParserTest {
|
||||
SsaParser parser = new SsaParser();
|
||||
byte[] bytes =
|
||||
TestUtil.getByteArray(ApplicationProvider.getApplicationContext(), STYLE_UNDERLINE);
|
||||
List<CuesWithTiming> allCues = parser.parse(bytes);
|
||||
ImmutableList<CuesWithTiming> allCues = parseAllCues(parser, bytes);
|
||||
assertThat(allCues).hasSize(2);
|
||||
|
||||
Spanned firstCueText = (Spanned) Iterables.getOnlyElement(allCues.get(0).cues).text;
|
||||
@ -513,7 +548,7 @@ public final class SsaParserTest {
|
||||
SsaParser parser = new SsaParser();
|
||||
byte[] bytes =
|
||||
TestUtil.getByteArray(ApplicationProvider.getApplicationContext(), STYLE_STRIKEOUT);
|
||||
List<CuesWithTiming> allCues = parser.parse(bytes);
|
||||
ImmutableList<CuesWithTiming> allCues = parseAllCues(parser, bytes);
|
||||
assertThat(allCues).hasSize(2);
|
||||
|
||||
Spanned firstCueText = (Spanned) Iterables.getOnlyElement(allCues.get(0).cues).text;
|
||||
@ -523,6 +558,12 @@ public final class SsaParserTest {
|
||||
.hasNoStrikethroughSpanBetween(0, secondCueText.length());
|
||||
}
|
||||
|
||||
private static ImmutableList<CuesWithTiming> parseAllCues(SubtitleParser parser, byte[] data) {
|
||||
ImmutableList.Builder<CuesWithTiming> cues = ImmutableList.builder();
|
||||
parser.parse(data, OutputOptions.allCues(), cues::add);
|
||||
return cues.build();
|
||||
}
|
||||
|
||||
private static void assertTypicalCue1(CuesWithTiming cuesWithTiming) {
|
||||
assertThat(cuesWithTiming.startTimeUs).isEqualTo(0);
|
||||
assertThat(cuesWithTiming.durationUs).isEqualTo(1230000);
|
||||
|
@ -20,11 +20,14 @@ import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import androidx.media3.common.text.Cue;
|
||||
import androidx.media3.extractor.text.CuesWithTiming;
|
||||
import androidx.media3.extractor.text.SubtitleParser;
|
||||
import androidx.media3.extractor.text.SubtitleParser.OutputOptions;
|
||||
import androidx.media3.test.utils.TestUtil;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
@ -60,7 +63,7 @@ public final class SubripParserTest {
|
||||
SubripParser parser = new SubripParser();
|
||||
byte[] bytes = TestUtil.getByteArray(ApplicationProvider.getApplicationContext(), EMPTY_FILE);
|
||||
|
||||
List<CuesWithTiming> allCues = parser.parse(bytes);
|
||||
ImmutableList<CuesWithTiming> allCues = parseAllCues(parser, bytes);
|
||||
|
||||
assertThat(allCues).isEmpty();
|
||||
}
|
||||
@ -70,7 +73,7 @@ public final class SubripParserTest {
|
||||
SubripParser parser = new SubripParser();
|
||||
byte[] bytes = TestUtil.getByteArray(ApplicationProvider.getApplicationContext(), TYPICAL_FILE);
|
||||
|
||||
List<CuesWithTiming> allCues = parser.parse(bytes);
|
||||
ImmutableList<CuesWithTiming> allCues = parseAllCues(parser, bytes);
|
||||
|
||||
assertThat(allCues).hasSize(3);
|
||||
assertTypicalCue1(allCues.get(0));
|
||||
@ -83,7 +86,8 @@ public final class SubripParserTest {
|
||||
SubripParser parser = new SubripParser();
|
||||
byte[] bytes = TestUtil.getByteArray(ApplicationProvider.getApplicationContext(), TYPICAL_FILE);
|
||||
|
||||
ImmutableList<CuesWithTiming> allCues = parser.parse(bytes, 10, bytes.length - 15);
|
||||
List<CuesWithTiming> allCues = new ArrayList<>();
|
||||
parser.parse(bytes, 10, bytes.length - 15, OutputOptions.allCues(), allCues::add);
|
||||
|
||||
assertThat(allCues).hasSize(2);
|
||||
// Because of the offset, we skip the first line of dialogue
|
||||
@ -93,6 +97,36 @@ public final class SubripParserTest {
|
||||
assertThat(thirdCue.text.toString()).isEqualTo("This is the third subti");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseTypical_onlyCuesAfterTime() throws IOException {
|
||||
SubripParser parser = new SubripParser();
|
||||
byte[] bytes = TestUtil.getByteArray(ApplicationProvider.getApplicationContext(), TYPICAL_FILE);
|
||||
|
||||
List<CuesWithTiming> cues = new ArrayList<>();
|
||||
parser.parse(bytes, OutputOptions.onlyCuesAfter(/* startTimeUs= */ 1_000_000), cues::add);
|
||||
|
||||
assertThat(cues).hasSize(2);
|
||||
assertTypicalCue2(cues.get(0));
|
||||
assertTypicalCue3(cues.get(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseTypical_cuesAfterTimeThenCuesBefore() throws IOException {
|
||||
SubripParser parser = new SubripParser();
|
||||
byte[] bytes = TestUtil.getByteArray(ApplicationProvider.getApplicationContext(), TYPICAL_FILE);
|
||||
|
||||
List<CuesWithTiming> cues = new ArrayList<>();
|
||||
parser.parse(
|
||||
bytes,
|
||||
OutputOptions.cuesAfterThenRemainingCuesBefore(/* startTimeUs= */ 1_000_000),
|
||||
cues::add);
|
||||
|
||||
assertThat(cues).hasSize(3);
|
||||
assertTypicalCue2(cues.get(0));
|
||||
assertTypicalCue3(cues.get(1));
|
||||
assertTypicalCue1(cues.get(2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseTypicalWithByteOrderMark() throws IOException {
|
||||
SubripParser parser = new SubripParser();
|
||||
@ -100,7 +134,7 @@ public final class SubripParserTest {
|
||||
TestUtil.getByteArray(
|
||||
ApplicationProvider.getApplicationContext(), TYPICAL_WITH_BYTE_ORDER_MARK);
|
||||
|
||||
List<CuesWithTiming> allCues = parser.parse(bytes);
|
||||
ImmutableList<CuesWithTiming> allCues = parseAllCues(parser, bytes);
|
||||
|
||||
assertThat(allCues).hasSize(3);
|
||||
assertTypicalCue1(allCues.get(0));
|
||||
@ -115,7 +149,7 @@ public final class SubripParserTest {
|
||||
TestUtil.getByteArray(
|
||||
ApplicationProvider.getApplicationContext(), TYPICAL_EXTRA_BLANK_LINE);
|
||||
|
||||
List<CuesWithTiming> allCues = parser.parse(bytes);
|
||||
ImmutableList<CuesWithTiming> allCues = parseAllCues(parser, bytes);
|
||||
|
||||
assertThat(allCues).hasSize(3);
|
||||
assertTypicalCue1(allCues.get(0));
|
||||
@ -131,7 +165,7 @@ public final class SubripParserTest {
|
||||
TestUtil.getByteArray(
|
||||
ApplicationProvider.getApplicationContext(), TYPICAL_MISSING_TIMECODE);
|
||||
|
||||
List<CuesWithTiming> allCues = parser.parse(bytes);
|
||||
ImmutableList<CuesWithTiming> allCues = parseAllCues(parser, bytes);
|
||||
|
||||
assertThat(allCues).hasSize(2);
|
||||
assertTypicalCue1(allCues.get(0));
|
||||
@ -146,7 +180,7 @@ public final class SubripParserTest {
|
||||
TestUtil.getByteArray(
|
||||
ApplicationProvider.getApplicationContext(), TYPICAL_MISSING_SEQUENCE);
|
||||
|
||||
List<CuesWithTiming> allCues = parser.parse(bytes);
|
||||
ImmutableList<CuesWithTiming> allCues = parseAllCues(parser, bytes);
|
||||
|
||||
assertThat(allCues).hasSize(2);
|
||||
assertTypicalCue1(allCues.get(0));
|
||||
@ -161,7 +195,7 @@ public final class SubripParserTest {
|
||||
TestUtil.getByteArray(
|
||||
ApplicationProvider.getApplicationContext(), TYPICAL_NEGATIVE_TIMESTAMPS);
|
||||
|
||||
List<CuesWithTiming> allCues = parser.parse(bytes);
|
||||
ImmutableList<CuesWithTiming> allCues = parseAllCues(parser, bytes);
|
||||
|
||||
assertThat(allCues).hasSize(1);
|
||||
assertTypicalCue3(allCues.get(0));
|
||||
@ -174,7 +208,7 @@ public final class SubripParserTest {
|
||||
byte[] bytes =
|
||||
TestUtil.getByteArray(ApplicationProvider.getApplicationContext(), TYPICAL_UNEXPECTED_END);
|
||||
|
||||
List<CuesWithTiming> allCues = parser.parse(bytes);
|
||||
ImmutableList<CuesWithTiming> allCues = parseAllCues(parser, bytes);
|
||||
|
||||
assertThat(allCues).hasSize(2);
|
||||
assertTypicalCue1(allCues.get(0));
|
||||
@ -187,7 +221,7 @@ public final class SubripParserTest {
|
||||
byte[] bytes =
|
||||
TestUtil.getByteArray(ApplicationProvider.getApplicationContext(), TYPICAL_UTF16LE);
|
||||
|
||||
List<CuesWithTiming> allCues = parser.parse(bytes);
|
||||
ImmutableList<CuesWithTiming> allCues = parseAllCues(parser, bytes);
|
||||
|
||||
assertThat(allCues).hasSize(3);
|
||||
assertTypicalCue1(allCues.get(0));
|
||||
@ -201,7 +235,7 @@ public final class SubripParserTest {
|
||||
byte[] bytes =
|
||||
TestUtil.getByteArray(ApplicationProvider.getApplicationContext(), TYPICAL_UTF16BE);
|
||||
|
||||
List<CuesWithTiming> allCues = parser.parse(bytes);
|
||||
ImmutableList<CuesWithTiming> allCues = parseAllCues(parser, bytes);
|
||||
|
||||
assertThat(allCues).hasSize(3);
|
||||
assertTypicalCue1(allCues.get(0));
|
||||
@ -215,7 +249,7 @@ public final class SubripParserTest {
|
||||
byte[] bytes =
|
||||
TestUtil.getByteArray(ApplicationProvider.getApplicationContext(), TYPICAL_WITH_TAGS);
|
||||
|
||||
List<CuesWithTiming> allCues = parser.parse(bytes);
|
||||
ImmutableList<CuesWithTiming> allCues = parseAllCues(parser, bytes);
|
||||
|
||||
assertThat(allCues).isNotNull();
|
||||
assertThat(allCues.get(0).cues.get(0).text.toString()).isEqualTo("This is the first subtitle.");
|
||||
@ -244,7 +278,7 @@ public final class SubripParserTest {
|
||||
TestUtil.getByteArray(
|
||||
ApplicationProvider.getApplicationContext(), TYPICAL_NO_HOURS_AND_MILLIS);
|
||||
|
||||
List<CuesWithTiming> allCues = parser.parse(bytes);
|
||||
ImmutableList<CuesWithTiming> allCues = parseAllCues(parser, bytes);
|
||||
|
||||
assertThat(allCues).hasSize(3);
|
||||
assertTypicalCue1(allCues.get(0));
|
||||
@ -254,6 +288,12 @@ public final class SubripParserTest {
|
||||
assertTypicalCue3(allCues.get(2));
|
||||
}
|
||||
|
||||
private static ImmutableList<CuesWithTiming> parseAllCues(SubtitleParser parser, byte[] data) {
|
||||
ImmutableList.Builder<CuesWithTiming> cues = ImmutableList.builder();
|
||||
parser.parse(data, OutputOptions.allCues(), cues::add);
|
||||
return cues.build();
|
||||
}
|
||||
|
||||
private static void assertTypicalCue1(CuesWithTiming cuesWithTiming) {
|
||||
assertThat(cuesWithTiming.startTimeUs).isEqualTo(0);
|
||||
assertThat(cuesWithTiming.cues.get(0).text.toString()).isEqualTo("This is the first subtitle.");
|
||||
|
@ -20,16 +20,20 @@ import static androidx.media3.test.utils.truth.SpannedSubject.assertThat;
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import android.graphics.Color;
|
||||
import android.text.Spanned;
|
||||
import android.text.SpannedString;
|
||||
import androidx.media3.common.C;
|
||||
import androidx.media3.common.text.Cue;
|
||||
import androidx.media3.extractor.text.CuesWithTiming;
|
||||
import androidx.media3.extractor.text.SubtitleParser;
|
||||
import androidx.media3.test.utils.TestUtil;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Iterables;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
@ -67,7 +71,9 @@ public final class Tx3gParserTest {
|
||||
Tx3gParser parser = new Tx3gParser(ImmutableList.of());
|
||||
byte[] bytes = TestUtil.getByteArray(ApplicationProvider.getApplicationContext(), NO_SUBTITLE);
|
||||
|
||||
CuesWithTiming cuesWithTiming = Iterables.getOnlyElement(parser.parse(bytes));
|
||||
List<CuesWithTiming> allCues = new ArrayList<>(/* initialCapacity= */ 1);
|
||||
parser.parse(bytes, SubtitleParser.OutputOptions.allCues(), allCues::add);
|
||||
CuesWithTiming cuesWithTiming = Iterables.getOnlyElement(allCues);
|
||||
|
||||
assertThat(cuesWithTiming.cues).isEmpty();
|
||||
assertThat(cuesWithTiming.startTimeUs).isEqualTo(C.TIME_UNSET);
|
||||
@ -81,13 +87,9 @@ public final class Tx3gParserTest {
|
||||
byte[] bytes =
|
||||
TestUtil.getByteArray(ApplicationProvider.getApplicationContext(), SAMPLE_JUST_TEXT);
|
||||
|
||||
CuesWithTiming cuesWithTiming = Iterables.getOnlyElement(parser.parse(bytes));
|
||||
Cue singleCue = Iterables.getOnlyElement(cuesWithTiming.cues);
|
||||
Cue singleCue = parseToSingleCue(parser, bytes);
|
||||
SpannedString text = new SpannedString(singleCue.text);
|
||||
|
||||
assertThat(cuesWithTiming.startTimeUs).isEqualTo(C.TIME_UNSET);
|
||||
assertThat(cuesWithTiming.durationUs).isEqualTo(C.TIME_UNSET);
|
||||
assertThat(cuesWithTiming.endTimeUs).isEqualTo(C.TIME_UNSET);
|
||||
assertThat(text.toString()).isEqualTo("CC Test");
|
||||
assertThat(text).hasNoSpans();
|
||||
assertFractionalLinePosition(singleCue, 0.85f);
|
||||
@ -99,13 +101,9 @@ public final class Tx3gParserTest {
|
||||
byte[] bytes =
|
||||
TestUtil.getByteArray(ApplicationProvider.getApplicationContext(), SAMPLE_WITH_STYL);
|
||||
|
||||
CuesWithTiming cuesWithTiming = Iterables.getOnlyElement(parser.parse(bytes));
|
||||
Cue singleCue = Iterables.getOnlyElement(cuesWithTiming.cues);
|
||||
SpannedString text = new SpannedString(singleCue.text);
|
||||
Cue singleCue = parseToSingleCue(parser, bytes);
|
||||
Spanned text = (Spanned) singleCue.text;
|
||||
|
||||
assertThat(cuesWithTiming.startTimeUs).isEqualTo(C.TIME_UNSET);
|
||||
assertThat(cuesWithTiming.durationUs).isEqualTo(C.TIME_UNSET);
|
||||
assertThat(cuesWithTiming.endTimeUs).isEqualTo(C.TIME_UNSET);
|
||||
assertThat(text.toString()).isEqualTo("CC Test");
|
||||
assertThat(text).hasBoldItalicSpanBetween(0, 6);
|
||||
assertThat(text).hasUnderlineSpanBetween(0, 6);
|
||||
@ -127,9 +125,8 @@ public final class Tx3gParserTest {
|
||||
TestUtil.getByteArray(
|
||||
ApplicationProvider.getApplicationContext(), SAMPLE_WITH_STYL_START_TOO_LARGE);
|
||||
|
||||
CuesWithTiming cuesWithTiming = Iterables.getOnlyElement(parser.parse(bytes));
|
||||
Cue singleCue = Iterables.getOnlyElement(cuesWithTiming.cues);
|
||||
SpannedString text = new SpannedString(singleCue.text);
|
||||
Cue singleCue = parseToSingleCue(parser, bytes);
|
||||
Spanned text = (Spanned) singleCue.text;
|
||||
|
||||
assertThat(text.toString()).isEqualTo("CC 🙂");
|
||||
assertThat(text).hasNoSpans();
|
||||
@ -150,9 +147,8 @@ public final class Tx3gParserTest {
|
||||
TestUtil.getByteArray(
|
||||
ApplicationProvider.getApplicationContext(), SAMPLE_WITH_STYL_END_TOO_LARGE);
|
||||
|
||||
CuesWithTiming cuesWithTiming = Iterables.getOnlyElement(parser.parse(bytes));
|
||||
Cue singleCue = Iterables.getOnlyElement(cuesWithTiming.cues);
|
||||
SpannedString text = new SpannedString(singleCue.text);
|
||||
Cue singleCue = parseToSingleCue(parser, bytes);
|
||||
Spanned text = (Spanned) singleCue.text;
|
||||
|
||||
assertThat(text.toString()).isEqualTo("CC 🙂");
|
||||
assertThat(text).hasBoldItalicSpanBetween(0, 5);
|
||||
@ -168,13 +164,9 @@ public final class Tx3gParserTest {
|
||||
TestUtil.getByteArray(
|
||||
ApplicationProvider.getApplicationContext(), SAMPLE_WITH_STYL_ALL_DEFAULTS);
|
||||
|
||||
CuesWithTiming cuesWithTiming = Iterables.getOnlyElement(parser.parse(bytes));
|
||||
Cue singleCue = Iterables.getOnlyElement(cuesWithTiming.cues);
|
||||
SpannedString text = new SpannedString(singleCue.text);
|
||||
Cue singleCue = parseToSingleCue(parser, bytes);
|
||||
Spanned text = (Spanned) singleCue.text;
|
||||
|
||||
assertThat(cuesWithTiming.startTimeUs).isEqualTo(C.TIME_UNSET);
|
||||
assertThat(cuesWithTiming.durationUs).isEqualTo(C.TIME_UNSET);
|
||||
assertThat(cuesWithTiming.endTimeUs).isEqualTo(C.TIME_UNSET);
|
||||
assertThat(text.toString()).isEqualTo("CC Test");
|
||||
assertThat(text).hasNoSpans();
|
||||
assertFractionalLinePosition(singleCue, 0.85f);
|
||||
@ -186,13 +178,9 @@ public final class Tx3gParserTest {
|
||||
byte[] bytes =
|
||||
TestUtil.getByteArray(ApplicationProvider.getApplicationContext(), SAMPLE_UTF16_BE_NO_STYL);
|
||||
|
||||
CuesWithTiming cuesWithTiming = Iterables.getOnlyElement(parser.parse(bytes));
|
||||
Cue singleCue = Iterables.getOnlyElement(cuesWithTiming.cues);
|
||||
SpannedString text = new SpannedString(singleCue.text);
|
||||
Cue singleCue = parseToSingleCue(parser, bytes);
|
||||
Spanned text = (Spanned) singleCue.text;
|
||||
|
||||
assertThat(cuesWithTiming.startTimeUs).isEqualTo(C.TIME_UNSET);
|
||||
assertThat(cuesWithTiming.durationUs).isEqualTo(C.TIME_UNSET);
|
||||
assertThat(cuesWithTiming.endTimeUs).isEqualTo(C.TIME_UNSET);
|
||||
assertThat(text.toString()).isEqualTo("你好");
|
||||
assertThat(text).hasNoSpans();
|
||||
assertFractionalLinePosition(singleCue, 0.85f);
|
||||
@ -203,13 +191,8 @@ public final class Tx3gParserTest {
|
||||
Tx3gParser parser = new Tx3gParser(ImmutableList.of());
|
||||
byte[] bytes =
|
||||
TestUtil.getByteArray(ApplicationProvider.getApplicationContext(), SAMPLE_UTF16_LE_NO_STYL);
|
||||
CuesWithTiming cuesWithTiming = Iterables.getOnlyElement(parser.parse(bytes));
|
||||
Cue singleCue = Iterables.getOnlyElement(cuesWithTiming.cues);
|
||||
SpannedString text = new SpannedString(singleCue.text);
|
||||
|
||||
assertThat(cuesWithTiming.startTimeUs).isEqualTo(C.TIME_UNSET);
|
||||
assertThat(cuesWithTiming.durationUs).isEqualTo(C.TIME_UNSET);
|
||||
assertThat(cuesWithTiming.endTimeUs).isEqualTo(C.TIME_UNSET);
|
||||
Cue singleCue = parseToSingleCue(parser, bytes);
|
||||
Spanned text = (Spanned) singleCue.text;
|
||||
|
||||
assertThat(text.toString()).isEqualTo("你好");
|
||||
assertThat(text).hasNoSpans();
|
||||
@ -223,13 +206,9 @@ public final class Tx3gParserTest {
|
||||
TestUtil.getByteArray(
|
||||
ApplicationProvider.getApplicationContext(), SAMPLE_WITH_MULTIPLE_STYL);
|
||||
|
||||
CuesWithTiming cuesWithTiming = Iterables.getOnlyElement(parser.parse(bytes));
|
||||
Cue singleCue = Iterables.getOnlyElement(cuesWithTiming.cues);
|
||||
SpannedString text = new SpannedString(singleCue.text);
|
||||
Cue singleCue = parseToSingleCue(parser, bytes);
|
||||
Spanned text = (Spanned) singleCue.text;
|
||||
|
||||
assertThat(cuesWithTiming.startTimeUs).isEqualTo(C.TIME_UNSET);
|
||||
assertThat(cuesWithTiming.durationUs).isEqualTo(C.TIME_UNSET);
|
||||
assertThat(cuesWithTiming.endTimeUs).isEqualTo(C.TIME_UNSET);
|
||||
assertThat(text.toString()).isEqualTo("Line 2\nLine 3");
|
||||
assertThat(text).hasItalicSpanBetween(0, 5);
|
||||
assertThat(text).hasUnderlineSpanBetween(7, 12);
|
||||
@ -245,13 +224,9 @@ public final class Tx3gParserTest {
|
||||
TestUtil.getByteArray(
|
||||
ApplicationProvider.getApplicationContext(), SAMPLE_WITH_OTHER_EXTENSION);
|
||||
|
||||
CuesWithTiming cuesWithTiming = Iterables.getOnlyElement(parser.parse(bytes));
|
||||
Cue singleCue = Iterables.getOnlyElement(cuesWithTiming.cues);
|
||||
SpannedString text = new SpannedString(singleCue.text);
|
||||
Cue singleCue = parseToSingleCue(parser, bytes);
|
||||
Spanned text = (Spanned) singleCue.text;
|
||||
|
||||
assertThat(cuesWithTiming.startTimeUs).isEqualTo(C.TIME_UNSET);
|
||||
assertThat(cuesWithTiming.durationUs).isEqualTo(C.TIME_UNSET);
|
||||
assertThat(cuesWithTiming.endTimeUs).isEqualTo(C.TIME_UNSET);
|
||||
assertThat(text.toString()).isEqualTo("CC Test");
|
||||
assertThat(text).hasBoldSpanBetween(0, 6);
|
||||
assertThat(text).hasForegroundColorSpanBetween(0, 6).withColor(Color.GREEN);
|
||||
@ -266,13 +241,9 @@ public final class Tx3gParserTest {
|
||||
byte[] bytes =
|
||||
TestUtil.getByteArray(ApplicationProvider.getApplicationContext(), SAMPLE_WITH_STYL);
|
||||
|
||||
CuesWithTiming cuesWithTiming = Iterables.getOnlyElement(parser.parse(bytes));
|
||||
Cue singleCue = Iterables.getOnlyElement(cuesWithTiming.cues);
|
||||
SpannedString text = new SpannedString(singleCue.text);
|
||||
Cue singleCue = parseToSingleCue(parser, bytes);
|
||||
Spanned text = (Spanned) singleCue.text;
|
||||
|
||||
assertThat(cuesWithTiming.startTimeUs).isEqualTo(C.TIME_UNSET);
|
||||
assertThat(cuesWithTiming.durationUs).isEqualTo(C.TIME_UNSET);
|
||||
assertThat(cuesWithTiming.endTimeUs).isEqualTo(C.TIME_UNSET);
|
||||
assertThat(text.toString()).isEqualTo("CC Test");
|
||||
assertThat(text).hasBoldItalicSpanBetween(0, 7);
|
||||
assertThat(text).hasUnderlineSpanBetween(0, 7);
|
||||
@ -291,13 +262,9 @@ public final class Tx3gParserTest {
|
||||
byte[] bytes =
|
||||
TestUtil.getByteArray(ApplicationProvider.getApplicationContext(), SAMPLE_WITH_TBOX);
|
||||
|
||||
CuesWithTiming cuesWithTiming = Iterables.getOnlyElement(parser.parse(bytes));
|
||||
Cue singleCue = Iterables.getOnlyElement(cuesWithTiming.cues);
|
||||
SpannedString text = new SpannedString(singleCue.text);
|
||||
Cue singleCue = parseToSingleCue(parser, bytes);
|
||||
Spanned text = (Spanned) singleCue.text;
|
||||
|
||||
assertThat(cuesWithTiming.startTimeUs).isEqualTo(C.TIME_UNSET);
|
||||
assertThat(cuesWithTiming.durationUs).isEqualTo(C.TIME_UNSET);
|
||||
assertThat(cuesWithTiming.endTimeUs).isEqualTo(C.TIME_UNSET);
|
||||
assertThat(text.toString()).isEqualTo("CC Test");
|
||||
assertThat(text).hasBoldItalicSpanBetween(0, 7);
|
||||
assertThat(text).hasUnderlineSpanBetween(0, 7);
|
||||
@ -315,13 +282,9 @@ public final class Tx3gParserTest {
|
||||
byte[] bytes =
|
||||
TestUtil.getByteArray(ApplicationProvider.getApplicationContext(), SAMPLE_WITH_STYL);
|
||||
|
||||
CuesWithTiming cuesWithTiming = Iterables.getOnlyElement(parser.parse(bytes));
|
||||
Cue singleCue = Iterables.getOnlyElement(cuesWithTiming.cues);
|
||||
SpannedString text = new SpannedString(singleCue.text);
|
||||
Cue singleCue = parseToSingleCue(parser, bytes);
|
||||
Spanned text = (Spanned) singleCue.text;
|
||||
|
||||
assertThat(cuesWithTiming.startTimeUs).isEqualTo(C.TIME_UNSET);
|
||||
assertThat(cuesWithTiming.durationUs).isEqualTo(C.TIME_UNSET);
|
||||
assertThat(cuesWithTiming.endTimeUs).isEqualTo(C.TIME_UNSET);
|
||||
assertThat(text.toString()).isEqualTo("CC Test");
|
||||
assertThat(text).hasBoldItalicSpanBetween(0, 6);
|
||||
assertThat(text).hasUnderlineSpanBetween(0, 6);
|
||||
@ -334,4 +297,16 @@ public final class Tx3gParserTest {
|
||||
assertThat(cue.lineAnchor).isEqualTo(Cue.ANCHOR_TYPE_START);
|
||||
assertThat(cue.line).isWithin(1e-6f).of(expectedFraction);
|
||||
}
|
||||
|
||||
private static Cue parseToSingleCue(SubtitleParser parser, byte[] data) {
|
||||
List<CuesWithTiming> result = new ArrayList<>(/* initialCapacity= */ 1);
|
||||
parser.parse(data, SubtitleParser.OutputOptions.allCues(), result::add);
|
||||
CuesWithTiming cuesWithTiming = Iterables.getOnlyElement(result);
|
||||
|
||||
assertThat(cuesWithTiming.startTimeUs).isEqualTo(C.TIME_UNSET);
|
||||
assertThat(cuesWithTiming.durationUs).isEqualTo(C.TIME_UNSET);
|
||||
assertThat(cuesWithTiming.endTimeUs).isEqualTo(C.TIME_UNSET);
|
||||
|
||||
return Iterables.getOnlyElement(cuesWithTiming.cues);
|
||||
}
|
||||
}
|
||||
|
@ -22,9 +22,13 @@ import static org.junit.Assert.assertThrows;
|
||||
import androidx.media3.common.C;
|
||||
import androidx.media3.common.text.Cue;
|
||||
import androidx.media3.extractor.text.CuesWithTiming;
|
||||
import androidx.media3.extractor.text.SubtitleParser;
|
||||
import androidx.media3.extractor.text.SubtitleParser.OutputOptions;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.truth.Expect;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
@ -171,7 +175,7 @@ public final class Mp4WebvttParserTest {
|
||||
@Test
|
||||
public void singleCueSample() {
|
||||
Mp4WebvttParser parser = new Mp4WebvttParser();
|
||||
List<CuesWithTiming> result = parser.parse(SINGLE_CUE_SAMPLE);
|
||||
CuesWithTiming result = parseToSingleCuesWithTiming(parser, SINGLE_CUE_SAMPLE);
|
||||
// Line feed must be trimmed by the decoder
|
||||
Cue expectedCue = WebvttCueParser.newCueForText("Hello World");
|
||||
assertMp4WebvttSubtitleEquals(result, expectedCue);
|
||||
@ -180,7 +184,7 @@ public final class Mp4WebvttParserTest {
|
||||
@Test
|
||||
public void twoCuesSample() {
|
||||
Mp4WebvttParser parser = new Mp4WebvttParser();
|
||||
List<CuesWithTiming> result = parser.parse(DOUBLE_CUE_SAMPLE);
|
||||
CuesWithTiming result = parseToSingleCuesWithTiming(parser, DOUBLE_CUE_SAMPLE);
|
||||
Cue firstExpectedCue = WebvttCueParser.newCueForText("Hello World");
|
||||
Cue secondExpectedCue = WebvttCueParser.newCueForText("Bye Bye");
|
||||
assertMp4WebvttSubtitleEquals(result, firstExpectedCue, secondExpectedCue);
|
||||
@ -190,13 +194,12 @@ public final class Mp4WebvttParserTest {
|
||||
public void noCueSample() {
|
||||
Mp4WebvttParser parser = new Mp4WebvttParser();
|
||||
|
||||
List<CuesWithTiming> result = parser.parse(NO_CUE_SAMPLE);
|
||||
CuesWithTiming result = parseToSingleCuesWithTiming(parser, NO_CUE_SAMPLE);
|
||||
|
||||
assertThat(result).hasSize(1);
|
||||
assertThat(result.get(0).cues).isEmpty();
|
||||
assertThat(result.get(0).startTimeUs).isEqualTo(C.TIME_UNSET);
|
||||
assertThat(result.get(0).durationUs).isEqualTo(C.TIME_UNSET);
|
||||
assertThat(result.get(0).endTimeUs).isEqualTo(C.TIME_UNSET);
|
||||
assertThat(result.cues).isEmpty();
|
||||
assertThat(result.startTimeUs).isEqualTo(C.TIME_UNSET);
|
||||
assertThat(result.durationUs).isEqualTo(C.TIME_UNSET);
|
||||
assertThat(result.endTimeUs).isEqualTo(C.TIME_UNSET);
|
||||
}
|
||||
|
||||
// Negative tests.
|
||||
@ -204,23 +207,29 @@ public final class Mp4WebvttParserTest {
|
||||
@Test
|
||||
public void sampleWithIncompleteHeader() {
|
||||
Mp4WebvttParser parser = new Mp4WebvttParser();
|
||||
assertThrows(IllegalArgumentException.class, () -> parser.parse(INCOMPLETE_HEADER_SAMPLE));
|
||||
assertThrows(
|
||||
IllegalArgumentException.class,
|
||||
() -> parser.parse(INCOMPLETE_HEADER_SAMPLE, OutputOptions.allCues(), c -> {}));
|
||||
}
|
||||
|
||||
// Util methods
|
||||
|
||||
private static CuesWithTiming parseToSingleCuesWithTiming(SubtitleParser parser, byte[] data) {
|
||||
List<CuesWithTiming> result = new ArrayList<>(/* initialCapacity= */ 1);
|
||||
parser.parse(data, OutputOptions.allCues(), result::add);
|
||||
return Iterables.getOnlyElement(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that the Subtitle's cues (which are all part of the event at t=0) are equal to the
|
||||
* expected Cues.
|
||||
*
|
||||
* @param cuesWithTimings The list of {@link CuesWithTiming} to check.
|
||||
* @param cuesWithTiming The {@link CuesWithTiming} to check.
|
||||
* @param expectedCues The expected {@link Cue}s.
|
||||
*/
|
||||
private void assertMp4WebvttSubtitleEquals(
|
||||
List<CuesWithTiming> cuesWithTimings, Cue... expectedCues) {
|
||||
assertThat(cuesWithTimings).hasSize(1);
|
||||
assertThat(cuesWithTimings.get(0).startTimeUs).isEqualTo(C.TIME_UNSET);
|
||||
ImmutableList<Cue> allCues = cuesWithTimings.get(0).cues;
|
||||
private void assertMp4WebvttSubtitleEquals(CuesWithTiming cuesWithTiming, Cue... expectedCues) {
|
||||
assertThat(cuesWithTiming.startTimeUs).isEqualTo(C.TIME_UNSET);
|
||||
ImmutableList<Cue> allCues = cuesWithTiming.cues;
|
||||
assertThat(allCues).hasSize(expectedCues.length);
|
||||
for (int i = 0; i < allCues.size(); i++) {
|
||||
assertCuesEqual(expectedCues[i], allCues.get(i));
|
||||
|
Loading…
x
Reference in New Issue
Block a user