Create HlsMediaChunkExtractor

To be the abstraction to use for integrating with MediaParser.

PiperOrigin-RevId: 316710421
This commit is contained in:
aquilescanta 2020-06-16 18:38:04 +01:00 committed by Andrew Lewis
parent aed8cad8c3
commit 2273b00a53
6 changed files with 185 additions and 133 deletions

View File

@ -0,0 +1,101 @@
/*
* Copyright 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.android.exoplayer2.source.hls;
import androidx.annotation.VisibleForTesting;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.extractor.Extractor;
import com.google.android.exoplayer2.extractor.ExtractorInput;
import com.google.android.exoplayer2.extractor.ExtractorOutput;
import com.google.android.exoplayer2.extractor.PositionHolder;
import com.google.android.exoplayer2.extractor.mp3.Mp3Extractor;
import com.google.android.exoplayer2.extractor.mp4.FragmentedMp4Extractor;
import com.google.android.exoplayer2.extractor.ts.Ac3Extractor;
import com.google.android.exoplayer2.extractor.ts.Ac4Extractor;
import com.google.android.exoplayer2.extractor.ts.AdtsExtractor;
import com.google.android.exoplayer2.extractor.ts.TsExtractor;
import com.google.android.exoplayer2.util.TimestampAdjuster;
import java.io.IOException;
/**
* {@link HlsMediaChunkExtractor} implementation that uses ExoPlayer app-bundled {@link Extractor
* Extractors}.
*/
public final class BundledHlsMediaChunkExtractor implements HlsMediaChunkExtractor {
private static final PositionHolder DUMMY_POSITION_HOLDER = new PositionHolder();
@VisibleForTesting /* package */ final Extractor extractor;
private final Format masterPlaylistFormat;
private final TimestampAdjuster timestampAdjuster;
/**
* Creates a new instance.
*
* @param extractor The underlying {@link Extractor}.
* @param masterPlaylistFormat The {@link Format} obtained from the master playlist.
* @param timestampAdjuster A {@link TimestampAdjuster} to adjust sample timestamps.
*/
public BundledHlsMediaChunkExtractor(
Extractor extractor, Format masterPlaylistFormat, TimestampAdjuster timestampAdjuster) {
this.extractor = extractor;
this.masterPlaylistFormat = masterPlaylistFormat;
this.timestampAdjuster = timestampAdjuster;
}
@Override
public void init(ExtractorOutput extractorOutput) {
extractor.init(extractorOutput);
}
@Override
public boolean read(ExtractorInput extractorInput) throws IOException {
return extractor.read(extractorInput, DUMMY_POSITION_HOLDER) == Extractor.RESULT_CONTINUE;
}
@Override
public boolean isPackedAudioExtractor() {
return extractor instanceof AdtsExtractor
|| extractor instanceof Ac3Extractor
|| extractor instanceof Ac4Extractor
|| extractor instanceof Mp3Extractor;
}
@Override
public HlsMediaChunkExtractor reuseOrRecreate() {
if (extractor instanceof TsExtractor || extractor instanceof FragmentedMp4Extractor) {
// We can reuse this instance.
return this;
}
Extractor newExtractorInstance;
if (extractor instanceof WebvttExtractor) {
newExtractorInstance = new WebvttExtractor(masterPlaylistFormat.language, timestampAdjuster);
} else if (extractor instanceof AdtsExtractor) {
newExtractorInstance = new AdtsExtractor();
} else if (extractor instanceof Ac3Extractor) {
newExtractorInstance = new Ac3Extractor();
} else if (extractor instanceof Ac4Extractor) {
newExtractorInstance = new Ac4Extractor();
} else if (extractor instanceof Mp3Extractor) {
newExtractorInstance = new Mp3Extractor();
} else {
throw new IllegalStateException(
"Unexpected previousExtractor type: " + extractor.getClass().getSimpleName());
}
return new BundledHlsMediaChunkExtractor(
newExtractorInstance, masterPlaylistFormat, timestampAdjuster);
}
}

View File

@ -88,8 +88,8 @@ public final class DefaultHlsExtractorFactory implements HlsExtractorFactory {
} }
@Override @Override
public Result createExtractor( public BundledHlsMediaChunkExtractor createExtractor(
@Nullable Extractor previousExtractor, @Nullable HlsMediaChunkExtractor previousExtractor,
Uri uri, Uri uri,
Format format, Format format,
@Nullable List<Format> muxedCaptionFormats, @Nullable List<Format> muxedCaptionFormats,
@ -97,22 +97,6 @@ public final class DefaultHlsExtractorFactory implements HlsExtractorFactory {
Map<String, List<String>> responseHeaders, Map<String, List<String>> responseHeaders,
ExtractorInput extractorInput) ExtractorInput extractorInput)
throws IOException { throws IOException {
if (previousExtractor != null) {
// An extractor has already been successfully used. Return one of the same type.
if (isReusable(previousExtractor)) {
return buildResult(previousExtractor);
} else {
@Nullable
Result result =
buildResultForSameExtractorType(previousExtractor, format, timestampAdjuster);
if (result == null) {
throw new IllegalArgumentException(
"Unexpected previousExtractor type: " + previousExtractor.getClass().getSimpleName());
}
}
}
@FileTypes.Type @FileTypes.Type
int formatInferredFileType = FileTypes.inferFileTypeFromMimeType(format.sampleMimeType); int formatInferredFileType = FileTypes.inferFileTypeFromMimeType(format.sampleMimeType);
@FileTypes.Type @FileTypes.Type
@ -139,14 +123,15 @@ public final class DefaultHlsExtractorFactory implements HlsExtractorFactory {
checkNotNull( checkNotNull(
createExtractorByFileType(fileType, format, muxedCaptionFormats, timestampAdjuster)); createExtractorByFileType(fileType, format, muxedCaptionFormats, timestampAdjuster));
if (sniffQuietly(extractor, extractorInput)) { if (sniffQuietly(extractor, extractorInput)) {
return buildResult(extractor); return new BundledHlsMediaChunkExtractor(extractor, format, timestampAdjuster);
} }
if (fileType == FileTypes.TS) { if (fileType == FileTypes.TS) {
fallBackExtractor = extractor; fallBackExtractor = extractor;
} }
} }
return buildResult(checkNotNull(fallBackExtractor)); return new BundledHlsMediaChunkExtractor(
checkNotNull(fallBackExtractor), format, timestampAdjuster);
} }
private static void addFileTypeIfNotPresent( private static void addFileTypeIfNotPresent(
@ -257,34 +242,6 @@ public final class DefaultHlsExtractorFactory implements HlsExtractorFactory {
return false; return false;
} }
@Nullable
private static Result buildResultForSameExtractorType(
Extractor previousExtractor, Format format, TimestampAdjuster timestampAdjuster) {
if (previousExtractor instanceof WebvttExtractor) {
return buildResult(new WebvttExtractor(format.language, timestampAdjuster));
} else if (previousExtractor instanceof AdtsExtractor) {
return buildResult(new AdtsExtractor());
} else if (previousExtractor instanceof Ac3Extractor) {
return buildResult(new Ac3Extractor());
} else if (previousExtractor instanceof Ac4Extractor) {
return buildResult(new Ac4Extractor());
} else if (previousExtractor instanceof Mp3Extractor) {
return buildResult(new Mp3Extractor());
} else {
return null;
}
}
private static Result buildResult(Extractor extractor) {
return new Result(
extractor,
extractor instanceof AdtsExtractor
|| extractor instanceof Ac3Extractor
|| extractor instanceof Ac4Extractor
|| extractor instanceof Mp3Extractor,
isReusable(extractor));
}
private static boolean sniffQuietly(Extractor extractor, ExtractorInput input) private static boolean sniffQuietly(Extractor extractor, ExtractorInput input)
throws IOException { throws IOException {
boolean result = false; boolean result = false;
@ -297,9 +254,4 @@ public final class DefaultHlsExtractorFactory implements HlsExtractorFactory {
} }
return result; return result;
} }
private static boolean isReusable(Extractor previousExtractor) {
return previousExtractor instanceof TsExtractor
|| previousExtractor instanceof FragmentedMp4Extractor;
}
} }

View File

@ -31,33 +31,6 @@ import java.util.Map;
*/ */
public interface HlsExtractorFactory { public interface HlsExtractorFactory {
/** Holds an {@link Extractor} and associated parameters. */
final class Result {
/** The created extractor; */
public final Extractor extractor;
/** Whether the segments for which {@link #extractor} is created are packed audio segments. */
public final boolean isPackedAudioExtractor;
/**
* Whether {@link #extractor} may be reused for following continuous (no immediately preceding
* discontinuities) segments of the same variant.
*/
public final boolean isReusable;
/**
* Creates a result.
*
* @param extractor See {@link #extractor}.
* @param isPackedAudioExtractor See {@link #isPackedAudioExtractor}.
* @param isReusable See {@link #isReusable}.
*/
public Result(Extractor extractor, boolean isPackedAudioExtractor, boolean isReusable) {
this.extractor = extractor;
this.isPackedAudioExtractor = isPackedAudioExtractor;
this.isReusable = isReusable;
}
}
HlsExtractorFactory DEFAULT = new DefaultHlsExtractorFactory(); HlsExtractorFactory DEFAULT = new DefaultHlsExtractorFactory();
/** /**
@ -76,11 +49,11 @@ public interface HlsExtractorFactory {
* @param sniffingExtractorInput The first extractor input that will be passed to the returned * @param sniffingExtractorInput The first extractor input that will be passed to the returned
* extractor's {@link Extractor#read(ExtractorInput, PositionHolder)}. Must only be used to * extractor's {@link Extractor#read(ExtractorInput, PositionHolder)}. Must only be used to
* call {@link Extractor#sniff(ExtractorInput)}. * call {@link Extractor#sniff(ExtractorInput)}.
* @return A {@link Result}. * @return An {@link HlsMediaChunkExtractor}.
* @throws IOException If an I/O error is encountered while sniffing. * @throws IOException If an I/O error is encountered while sniffing.
*/ */
Result createExtractor( HlsMediaChunkExtractor createExtractor(
@Nullable Extractor previousExtractor, @Nullable HlsMediaChunkExtractor previousExtractor,
Uri uri, Uri uri,
Format format, Format format,
@Nullable List<Format> muxedCaptionFormats, @Nullable List<Format> muxedCaptionFormats,

View File

@ -21,9 +21,7 @@ import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.drm.DrmInitData; import com.google.android.exoplayer2.drm.DrmInitData;
import com.google.android.exoplayer2.extractor.DefaultExtractorInput; import com.google.android.exoplayer2.extractor.DefaultExtractorInput;
import com.google.android.exoplayer2.extractor.Extractor;
import com.google.android.exoplayer2.extractor.ExtractorInput; import com.google.android.exoplayer2.extractor.ExtractorInput;
import com.google.android.exoplayer2.extractor.PositionHolder;
import com.google.android.exoplayer2.metadata.Metadata; import com.google.android.exoplayer2.metadata.Metadata;
import com.google.android.exoplayer2.metadata.id3.Id3Decoder; import com.google.android.exoplayer2.metadata.id3.Id3Decoder;
import com.google.android.exoplayer2.metadata.id3.PrivFrame; import com.google.android.exoplayer2.metadata.id3.PrivFrame;
@ -56,8 +54,8 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
/** /**
* Creates a new instance. * Creates a new instance.
* *
* @param extractorFactory A {@link HlsExtractorFactory} from which the HLS media chunk extractor * @param extractorFactory A {@link HlsExtractorFactory} from which the {@link
* is obtained. * HlsMediaChunkExtractor} is obtained.
* @param dataSource The source from which the data should be loaded. * @param dataSource The source from which the data should be loaded.
* @param format The chunk format. * @param format The chunk format.
* @param startOfPlaylistInPeriodUs The position of the playlist in the period in microseconds. * @param startOfPlaylistInPeriodUs The position of the playlist in the period in microseconds.
@ -130,7 +128,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
int discontinuitySequenceNumber = int discontinuitySequenceNumber =
mediaPlaylist.discontinuitySequence + mediaSegment.relativeDiscontinuitySequence; mediaPlaylist.discontinuitySequence + mediaSegment.relativeDiscontinuitySequence;
@Nullable Extractor previousExtractor = null; @Nullable HlsMediaChunkExtractor previousExtractor = null;
Id3Decoder id3Decoder; Id3Decoder id3Decoder;
ParsableByteArray scratchId3Data; ParsableByteArray scratchId3Data;
boolean shouldSpliceIn; boolean shouldSpliceIn;
@ -147,8 +145,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
sampleQueueDiscardFromIndices = previousChunk.sampleQueueDiscardFromIndices; sampleQueueDiscardFromIndices = previousChunk.sampleQueueDiscardFromIndices;
} }
previousExtractor = previousExtractor =
previousChunk.isExtractorReusable previousChunk.discontinuitySequenceNumber == discontinuitySequenceNumber
&& previousChunk.discontinuitySequenceNumber == discontinuitySequenceNumber
&& !shouldSpliceIn && !shouldSpliceIn
? previousChunk.extractor ? previousChunk.extractor
: null; : null;
@ -188,7 +185,6 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
public static final String PRIV_TIMESTAMP_FRAME_OWNER = public static final String PRIV_TIMESTAMP_FRAME_OWNER =
"com.apple.streaming.transportStreamTimestamp"; "com.apple.streaming.transportStreamTimestamp";
private static final PositionHolder DUMMY_POSITION_HOLDER = new PositionHolder();
private static final AtomicInteger uidSource = new AtomicInteger(); private static final AtomicInteger uidSource = new AtomicInteger();
@ -207,7 +203,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
@Nullable private final DataSource initDataSource; @Nullable private final DataSource initDataSource;
@Nullable private final DataSpec initDataSpec; @Nullable private final DataSpec initDataSpec;
@Nullable private final Extractor previousExtractor; @Nullable private final HlsMediaChunkExtractor previousExtractor;
private final boolean isMasterTimestampSource; private final boolean isMasterTimestampSource;
private final boolean hasGapTag; private final boolean hasGapTag;
@ -221,8 +217,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
private final boolean initSegmentEncrypted; private final boolean initSegmentEncrypted;
private final boolean shouldSpliceIn; private final boolean shouldSpliceIn;
private @MonotonicNonNull Extractor extractor; private @MonotonicNonNull HlsMediaChunkExtractor extractor;
private boolean isExtractorReusable;
private @MonotonicNonNull HlsSampleStreamWrapper output; private @MonotonicNonNull HlsSampleStreamWrapper output;
// nextLoadPosition refers to the init segment if initDataLoadRequired is true. // nextLoadPosition refers to the init segment if initDataLoadRequired is true.
// Otherwise, nextLoadPosition refers to the media segment. // Otherwise, nextLoadPosition refers to the media segment.
@ -253,7 +248,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
boolean isMasterTimestampSource, boolean isMasterTimestampSource,
TimestampAdjuster timestampAdjuster, TimestampAdjuster timestampAdjuster,
@Nullable DrmInitData drmInitData, @Nullable DrmInitData drmInitData,
@Nullable Extractor previousExtractor, @Nullable HlsMediaChunkExtractor previousExtractor,
Id3Decoder id3Decoder, Id3Decoder id3Decoder,
ParsableByteArray scratchId3Data, ParsableByteArray scratchId3Data,
boolean shouldSpliceIn, boolean shouldSpliceIn,
@ -340,9 +335,8 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
// output == null means init() hasn't been called. // output == null means init() hasn't been called.
Assertions.checkNotNull(output); Assertions.checkNotNull(output);
if (extractor == null && previousExtractor != null) { if (extractor == null && previousExtractor != null) {
extractor = previousExtractor; extractor = previousExtractor.reuseOrRecreate();
isExtractorReusable = true; initDataLoadRequired = extractor != previousExtractor;
initDataLoadRequired = false;
} }
maybeLoadInitData(); maybeLoadInitData();
if (!loadCanceled) { if (!loadCanceled) {
@ -410,10 +404,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
input.skipFully(nextLoadPosition); input.skipFully(nextLoadPosition);
} }
try { try {
int result = Extractor.RESULT_CONTINUE; while (!loadCanceled && extractor.read(input)) {}
while (result == Extractor.RESULT_CONTINUE && !loadCanceled) {
result = extractor.read(input, DUMMY_POSITION_HOLDER);
}
} finally { } finally {
nextLoadPosition = (int) (input.getPosition() - dataSpec.position); nextLoadPosition = (int) (input.getPosition() - dataSpec.position);
} }
@ -434,7 +425,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
long id3Timestamp = peekId3PrivTimestamp(extractorInput); long id3Timestamp = peekId3PrivTimestamp(extractorInput);
extractorInput.resetPeekPosition(); extractorInput.resetPeekPosition();
HlsExtractorFactory.Result result = extractor =
extractorFactory.createExtractor( extractorFactory.createExtractor(
previousExtractor, previousExtractor,
dataSpec.uri, dataSpec.uri,
@ -443,9 +434,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
timestampAdjuster, timestampAdjuster,
dataSource.getResponseHeaders(), dataSource.getResponseHeaders(),
extractorInput); extractorInput);
extractor = result.extractor; if (extractor.isPackedAudioExtractor()) {
isExtractorReusable = result.isReusable;
if (result.isPackedAudioExtractor) {
output.setSampleOffsetUs( output.setSampleOffsetUs(
id3Timestamp != C.TIME_UNSET id3Timestamp != C.TIME_UNSET
? timestampAdjuster.adjustTsTimestamp(id3Timestamp) ? timestampAdjuster.adjustTsTimestamp(id3Timestamp)

View File

@ -0,0 +1,59 @@
/*
* Copyright 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.android.exoplayer2.source.hls;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.extractor.ExtractorInput;
import com.google.android.exoplayer2.extractor.ExtractorOutput;
import java.io.IOException;
/** Extracts samples and track {@link Format Formats} from {@link HlsMediaChunk HlsMediaChunks}. */
public interface HlsMediaChunkExtractor {
/**
* Initializes the extractor with an {@link ExtractorOutput}. Called at most once.
*
* @param extractorOutput An {@link ExtractorOutput} to receive extracted data.
*/
void init(ExtractorOutput extractorOutput);
/**
* Extracts data read from a provided {@link ExtractorInput}. Must not be called before {@link
* #init(ExtractorOutput)}.
*
* <p>A single call to this method will block until some progress has been made, but will not
* block for longer than this. Hence each call will consume only a small amount of input data.
*
* <p>When this method throws an {@link IOException}, extraction may continue by providing an
* {@link ExtractorInput} with an unchanged {@link ExtractorInput#getPosition() read position} to
* a subsequent call to this method.
*
* @param extractorInput The input to read from.
* @return Whether there is any data left to extract. Returns false if the end of input has been
* reached.
* @throws IOException If an error occurred reading from or parsing the input.
*/
boolean read(ExtractorInput extractorInput) throws IOException;
/** Returns whether this is a packed audio extractor, as defined in RFC 8216, Section 3.4. */
boolean isPackedAudioExtractor();
/**
* If this instance can be used for extracting multiple continuous segments, returns itself.
* Otherwise, returns a new instance for extracting the same type of media.
*/
HlsMediaChunkExtractor reuseOrRecreate();
}

View File

@ -22,10 +22,8 @@ import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.extractor.DefaultExtractorsFactory; import com.google.android.exoplayer2.extractor.DefaultExtractorsFactory;
import com.google.android.exoplayer2.extractor.Extractor;
import com.google.android.exoplayer2.extractor.ExtractorInput; import com.google.android.exoplayer2.extractor.ExtractorInput;
import com.google.android.exoplayer2.extractor.mp3.Mp3Extractor; import com.google.android.exoplayer2.extractor.mp3.Mp3Extractor;
import com.google.android.exoplayer2.extractor.mp4.FragmentedMp4Extractor;
import com.google.android.exoplayer2.extractor.ts.Ac3Extractor; import com.google.android.exoplayer2.extractor.ts.Ac3Extractor;
import com.google.android.exoplayer2.extractor.ts.TsExtractor; import com.google.android.exoplayer2.extractor.ts.TsExtractor;
import com.google.android.exoplayer2.testutil.FakeExtractorInput; import com.google.android.exoplayer2.testutil.FakeExtractorInput;
@ -44,7 +42,6 @@ import org.junit.runner.RunWith;
@RunWith(AndroidJUnit4.class) @RunWith(AndroidJUnit4.class)
public class DefaultHlsExtractorFactoryTest { public class DefaultHlsExtractorFactoryTest {
private Extractor fMp4Extractor;
private Uri tsUri; private Uri tsUri;
private Format webVttFormat; private Format webVttFormat;
private TimestampAdjuster timestampAdjuster; private TimestampAdjuster timestampAdjuster;
@ -52,7 +49,6 @@ public class DefaultHlsExtractorFactoryTest {
@Before @Before
public void setUp() { public void setUp() {
fMp4Extractor = new FragmentedMp4Extractor();
tsUri = Uri.parse("http://path/filename.ts"); tsUri = Uri.parse("http://path/filename.ts");
webVttFormat = new Format.Builder().setSampleMimeType(MimeTypes.TEXT_VTT).build(); webVttFormat = new Format.Builder().setSampleMimeType(MimeTypes.TEXT_VTT).build();
timestampAdjuster = new TimestampAdjuster(/* firstSampleTimestampUs= */ 0); timestampAdjuster = new TimestampAdjuster(/* firstSampleTimestampUs= */ 0);
@ -60,24 +56,6 @@ public class DefaultHlsExtractorFactoryTest {
ac3ResponseHeaders.put("Content-Type", Collections.singletonList(MimeTypes.AUDIO_AC3)); ac3ResponseHeaders.put("Content-Type", Collections.singletonList(MimeTypes.AUDIO_AC3));
} }
@Test
public void createExtractor_withPreviousExtractor_returnsSameExtractorType() throws Exception {
ExtractorInput extractorInput = new FakeExtractorInput.Builder().build();
HlsExtractorFactory.Result result =
new DefaultHlsExtractorFactory()
.createExtractor(
/* previousExtractor= */ fMp4Extractor,
tsUri,
webVttFormat,
/* muxedCaptionFormats= */ null,
timestampAdjuster,
ac3ResponseHeaders,
extractorInput);
assertThat(result.extractor.getClass()).isEqualTo(FragmentedMp4Extractor.class);
}
@Test @Test
public void createExtractor_withFileTypeInFormat_returnsExtractorMatchingFormat() public void createExtractor_withFileTypeInFormat_returnsExtractorMatchingFormat()
throws Exception { throws Exception {
@ -88,7 +66,7 @@ public class DefaultHlsExtractorFactoryTest {
ApplicationProvider.getApplicationContext(), "webvtt/typical")) ApplicationProvider.getApplicationContext(), "webvtt/typical"))
.build(); .build();
HlsExtractorFactory.Result result = BundledHlsMediaChunkExtractor result =
new DefaultHlsExtractorFactory() new DefaultHlsExtractorFactory()
.createExtractor( .createExtractor(
/* previousExtractor= */ null, /* previousExtractor= */ null,
@ -112,7 +90,7 @@ public class DefaultHlsExtractorFactoryTest {
TestUtil.getByteArray(ApplicationProvider.getApplicationContext(), "ts/sample.ac3")) TestUtil.getByteArray(ApplicationProvider.getApplicationContext(), "ts/sample.ac3"))
.build(); .build();
HlsExtractorFactory.Result result = BundledHlsMediaChunkExtractor result =
new DefaultHlsExtractorFactory() new DefaultHlsExtractorFactory()
.createExtractor( .createExtractor(
/* previousExtractor= */ null, /* previousExtractor= */ null,
@ -135,7 +113,7 @@ public class DefaultHlsExtractorFactoryTest {
ApplicationProvider.getApplicationContext(), "ts/sample_ac3.ts")) ApplicationProvider.getApplicationContext(), "ts/sample_ac3.ts"))
.build(); .build();
HlsExtractorFactory.Result result = BundledHlsMediaChunkExtractor result =
new DefaultHlsExtractorFactory() new DefaultHlsExtractorFactory()
.createExtractor( .createExtractor(
/* previousExtractor= */ null, /* previousExtractor= */ null,
@ -159,7 +137,7 @@ public class DefaultHlsExtractorFactoryTest {
ApplicationProvider.getApplicationContext(), "mp3/bear-id3.mp3")) ApplicationProvider.getApplicationContext(), "mp3/bear-id3.mp3"))
.build(); .build();
HlsExtractorFactory.Result result = BundledHlsMediaChunkExtractor result =
new DefaultHlsExtractorFactory() new DefaultHlsExtractorFactory()
.createExtractor( .createExtractor(
/* previousExtractor= */ null, /* previousExtractor= */ null,
@ -177,7 +155,7 @@ public class DefaultHlsExtractorFactoryTest {
public void createExtractor_withNoMatchingExtractor_fallsBackOnTsExtractor() throws Exception { public void createExtractor_withNoMatchingExtractor_fallsBackOnTsExtractor() throws Exception {
ExtractorInput emptyExtractorInput = new FakeExtractorInput.Builder().build(); ExtractorInput emptyExtractorInput = new FakeExtractorInput.Builder().build();
HlsExtractorFactory.Result result = BundledHlsMediaChunkExtractor result =
new DefaultHlsExtractorFactory() new DefaultHlsExtractorFactory()
.createExtractor( .createExtractor(
/* previousExtractor= */ null, /* previousExtractor= */ null,