Add a test for 33-bit HLS WebVTT wraparound

This also gives some general test coverage for HLS' WebvttExtractor

Issue: #7462
PiperOrigin-RevId: 315257252
This commit is contained in:
ibaker 2020-06-08 13:38:21 +01:00 committed by Ian Baker
parent bc7310240d
commit b7486f4883
4 changed files with 56 additions and 0 deletions

View file

@ -33,6 +33,8 @@ android {
}
}
sourceSets.test.assets.srcDir '../../testdata/src/test/assets/'
testOptions.unitTests.includeAndroidResources = true
}
@ -44,6 +46,7 @@ dependencies {
compileOnly 'org.jetbrains.kotlin:kotlin-annotations-jvm:' + kotlinAnnotationsVersion
implementation project(modulePrefix + 'library-core')
testImplementation project(modulePrefix + 'testutils')
testImplementation project(modulePrefix + 'testdata')
testImplementation 'org.robolectric:robolectric:' + robolectricVersion
}

View file

@ -17,9 +17,12 @@ package com.google.android.exoplayer2.source.hls;
import static com.google.common.truth.Truth.assertThat;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.google.android.exoplayer2.extractor.ExtractorInput;
import com.google.android.exoplayer2.testutil.FakeExtractorInput;
import com.google.android.exoplayer2.testutil.FakeExtractorOutput;
import com.google.android.exoplayer2.testutil.TestUtil;
import com.google.android.exoplayer2.util.TimestampAdjuster;
import java.io.EOFException;
import java.io.IOException;
@ -63,6 +66,27 @@ public class WebvttExtractorTest {
assertThat(sniffData(data)).isFalse();
}
@Test
public void read_handlesLargeCueTimestamps() throws Exception {
TimestampAdjuster timestampAdjuster = new TimestampAdjuster(/* firstSampleTimestampUs= */ 0);
// Prime the TimestampAdjuster with a close-ish timestamp (5s before the first cue).
timestampAdjuster.adjustTsTimestamp(384615190);
WebvttExtractor extractor = new WebvttExtractor(/* language= */ null, timestampAdjuster);
// We can't use ExtractorAsserts because WebvttExtractor doesn't fulfill the whole Extractor
// interface (e.g. throws an exception from seek()).
FakeExtractorOutput output =
TestUtil.extractAllSamplesFromFile(
extractor,
ApplicationProvider.getApplicationContext(),
"webvtt/with_x-timestamp-map_header");
// The output has a ~5s sampleTime and a large, negative subsampleOffset because the cue
// timestamps are ~10 days ahead of the PTS (due to wrapping) so the offset is used to ensure
// they're rendered at the right time.
output.assertOutput(
ApplicationProvider.getApplicationContext(), "webvtt/with_x-timestamp-map_header.dump");
}
private static boolean sniffData(byte[] data) throws IOException {
ExtractorInput input = new FakeExtractorInput.Builder().setData(data).build();
try {

View file

@ -0,0 +1,13 @@
WEBVTT
X-TIMESTAMP-MAP=LOCAL:1:11:16.443,MPEGTS:384879885
NOTE
X-TIMESTAMP-MAP is defined in RFC 8216 section 3.5 (HLS spec).
The cue times below are deliberately greater than 2^33 in 90kHz PTS clock,
to test wraparound logic.
266:18:35.679 --> 266:18:37.305
Cue text one
266:18:37.433 --> 266:18:38.276
Cue text two

View file

@ -0,0 +1,16 @@
seekMap:
isSeekable = false
duration = UNSET TIME
getPosition(0) = [[timeUs=0, position=0]]
numberOfTracks = 1
track 0:
total output bytes = 324
sample count = 1
format 0:
sampleMimeType = text/vtt
subsampleOffsetUs = -958710678845
sample 0:
time = 5000155
flags = 1
data = length 324, hash C0D159A2
tracksEnded = true