mirror of
https://github.com/androidx/media.git
synced 2025-05-17 04:29:55 +08:00
Create HlsMediaChunkExtractor
To be the abstraction to use for integrating with MediaParser. PiperOrigin-RevId: 316710421
This commit is contained in:
parent
aed8cad8c3
commit
2273b00a53
@ -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);
|
||||
}
|
||||
}
|
@ -88,8 +88,8 @@ public final class DefaultHlsExtractorFactory implements HlsExtractorFactory {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result createExtractor(
|
||||
@Nullable Extractor previousExtractor,
|
||||
public BundledHlsMediaChunkExtractor createExtractor(
|
||||
@Nullable HlsMediaChunkExtractor previousExtractor,
|
||||
Uri uri,
|
||||
Format format,
|
||||
@Nullable List<Format> muxedCaptionFormats,
|
||||
@ -97,22 +97,6 @@ public final class DefaultHlsExtractorFactory implements HlsExtractorFactory {
|
||||
Map<String, List<String>> responseHeaders,
|
||||
ExtractorInput extractorInput)
|
||||
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
|
||||
int formatInferredFileType = FileTypes.inferFileTypeFromMimeType(format.sampleMimeType);
|
||||
@FileTypes.Type
|
||||
@ -139,14 +123,15 @@ public final class DefaultHlsExtractorFactory implements HlsExtractorFactory {
|
||||
checkNotNull(
|
||||
createExtractorByFileType(fileType, format, muxedCaptionFormats, timestampAdjuster));
|
||||
if (sniffQuietly(extractor, extractorInput)) {
|
||||
return buildResult(extractor);
|
||||
return new BundledHlsMediaChunkExtractor(extractor, format, timestampAdjuster);
|
||||
}
|
||||
if (fileType == FileTypes.TS) {
|
||||
fallBackExtractor = extractor;
|
||||
}
|
||||
}
|
||||
|
||||
return buildResult(checkNotNull(fallBackExtractor));
|
||||
return new BundledHlsMediaChunkExtractor(
|
||||
checkNotNull(fallBackExtractor), format, timestampAdjuster);
|
||||
}
|
||||
|
||||
private static void addFileTypeIfNotPresent(
|
||||
@ -257,34 +242,6 @@ public final class DefaultHlsExtractorFactory implements HlsExtractorFactory {
|
||||
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)
|
||||
throws IOException {
|
||||
boolean result = false;
|
||||
@ -297,9 +254,4 @@ public final class DefaultHlsExtractorFactory implements HlsExtractorFactory {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static boolean isReusable(Extractor previousExtractor) {
|
||||
return previousExtractor instanceof TsExtractor
|
||||
|| previousExtractor instanceof FragmentedMp4Extractor;
|
||||
}
|
||||
}
|
||||
|
@ -31,33 +31,6 @@ import java.util.Map;
|
||||
*/
|
||||
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();
|
||||
|
||||
/**
|
||||
@ -76,11 +49,11 @@ public interface HlsExtractorFactory {
|
||||
* @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
|
||||
* call {@link Extractor#sniff(ExtractorInput)}.
|
||||
* @return A {@link Result}.
|
||||
* @return An {@link HlsMediaChunkExtractor}.
|
||||
* @throws IOException If an I/O error is encountered while sniffing.
|
||||
*/
|
||||
Result createExtractor(
|
||||
@Nullable Extractor previousExtractor,
|
||||
HlsMediaChunkExtractor createExtractor(
|
||||
@Nullable HlsMediaChunkExtractor previousExtractor,
|
||||
Uri uri,
|
||||
Format format,
|
||||
@Nullable List<Format> muxedCaptionFormats,
|
||||
|
@ -21,9 +21,7 @@ import com.google.android.exoplayer2.C;
|
||||
import com.google.android.exoplayer2.Format;
|
||||
import com.google.android.exoplayer2.drm.DrmInitData;
|
||||
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.PositionHolder;
|
||||
import com.google.android.exoplayer2.metadata.Metadata;
|
||||
import com.google.android.exoplayer2.metadata.id3.Id3Decoder;
|
||||
import com.google.android.exoplayer2.metadata.id3.PrivFrame;
|
||||
@ -56,8 +54,8 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*
|
||||
* @param extractorFactory A {@link HlsExtractorFactory} from which the HLS media chunk extractor
|
||||
* is obtained.
|
||||
* @param extractorFactory A {@link HlsExtractorFactory} from which the {@link
|
||||
* HlsMediaChunkExtractor} is obtained.
|
||||
* @param dataSource The source from which the data should be loaded.
|
||||
* @param format The chunk format.
|
||||
* @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 =
|
||||
mediaPlaylist.discontinuitySequence + mediaSegment.relativeDiscontinuitySequence;
|
||||
|
||||
@Nullable Extractor previousExtractor = null;
|
||||
@Nullable HlsMediaChunkExtractor previousExtractor = null;
|
||||
Id3Decoder id3Decoder;
|
||||
ParsableByteArray scratchId3Data;
|
||||
boolean shouldSpliceIn;
|
||||
@ -147,8 +145,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
||||
sampleQueueDiscardFromIndices = previousChunk.sampleQueueDiscardFromIndices;
|
||||
}
|
||||
previousExtractor =
|
||||
previousChunk.isExtractorReusable
|
||||
&& previousChunk.discontinuitySequenceNumber == discontinuitySequenceNumber
|
||||
previousChunk.discontinuitySequenceNumber == discontinuitySequenceNumber
|
||||
&& !shouldSpliceIn
|
||||
? previousChunk.extractor
|
||||
: null;
|
||||
@ -188,7 +185,6 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
||||
|
||||
public static final String PRIV_TIMESTAMP_FRAME_OWNER =
|
||||
"com.apple.streaming.transportStreamTimestamp";
|
||||
private static final PositionHolder DUMMY_POSITION_HOLDER = new PositionHolder();
|
||||
|
||||
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 DataSpec initDataSpec;
|
||||
@Nullable private final Extractor previousExtractor;
|
||||
@Nullable private final HlsMediaChunkExtractor previousExtractor;
|
||||
|
||||
private final boolean isMasterTimestampSource;
|
||||
private final boolean hasGapTag;
|
||||
@ -221,8 +217,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
||||
private final boolean initSegmentEncrypted;
|
||||
private final boolean shouldSpliceIn;
|
||||
|
||||
private @MonotonicNonNull Extractor extractor;
|
||||
private boolean isExtractorReusable;
|
||||
private @MonotonicNonNull HlsMediaChunkExtractor extractor;
|
||||
private @MonotonicNonNull HlsSampleStreamWrapper output;
|
||||
// nextLoadPosition refers to the init segment if initDataLoadRequired is true.
|
||||
// Otherwise, nextLoadPosition refers to the media segment.
|
||||
@ -253,7 +248,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
||||
boolean isMasterTimestampSource,
|
||||
TimestampAdjuster timestampAdjuster,
|
||||
@Nullable DrmInitData drmInitData,
|
||||
@Nullable Extractor previousExtractor,
|
||||
@Nullable HlsMediaChunkExtractor previousExtractor,
|
||||
Id3Decoder id3Decoder,
|
||||
ParsableByteArray scratchId3Data,
|
||||
boolean shouldSpliceIn,
|
||||
@ -340,9 +335,8 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
||||
// output == null means init() hasn't been called.
|
||||
Assertions.checkNotNull(output);
|
||||
if (extractor == null && previousExtractor != null) {
|
||||
extractor = previousExtractor;
|
||||
isExtractorReusable = true;
|
||||
initDataLoadRequired = false;
|
||||
extractor = previousExtractor.reuseOrRecreate();
|
||||
initDataLoadRequired = extractor != previousExtractor;
|
||||
}
|
||||
maybeLoadInitData();
|
||||
if (!loadCanceled) {
|
||||
@ -410,10 +404,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
||||
input.skipFully(nextLoadPosition);
|
||||
}
|
||||
try {
|
||||
int result = Extractor.RESULT_CONTINUE;
|
||||
while (result == Extractor.RESULT_CONTINUE && !loadCanceled) {
|
||||
result = extractor.read(input, DUMMY_POSITION_HOLDER);
|
||||
}
|
||||
while (!loadCanceled && extractor.read(input)) {}
|
||||
} finally {
|
||||
nextLoadPosition = (int) (input.getPosition() - dataSpec.position);
|
||||
}
|
||||
@ -434,7 +425,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
||||
long id3Timestamp = peekId3PrivTimestamp(extractorInput);
|
||||
extractorInput.resetPeekPosition();
|
||||
|
||||
HlsExtractorFactory.Result result =
|
||||
extractor =
|
||||
extractorFactory.createExtractor(
|
||||
previousExtractor,
|
||||
dataSpec.uri,
|
||||
@ -443,9 +434,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
||||
timestampAdjuster,
|
||||
dataSource.getResponseHeaders(),
|
||||
extractorInput);
|
||||
extractor = result.extractor;
|
||||
isExtractorReusable = result.isReusable;
|
||||
if (result.isPackedAudioExtractor) {
|
||||
if (extractor.isPackedAudioExtractor()) {
|
||||
output.setSampleOffsetUs(
|
||||
id3Timestamp != C.TIME_UNSET
|
||||
? timestampAdjuster.adjustTsTimestamp(id3Timestamp)
|
||||
|
@ -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();
|
||||
}
|
@ -22,10 +22,8 @@ import androidx.test.core.app.ApplicationProvider;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
import com.google.android.exoplayer2.Format;
|
||||
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.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.TsExtractor;
|
||||
import com.google.android.exoplayer2.testutil.FakeExtractorInput;
|
||||
@ -44,7 +42,6 @@ import org.junit.runner.RunWith;
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class DefaultHlsExtractorFactoryTest {
|
||||
|
||||
private Extractor fMp4Extractor;
|
||||
private Uri tsUri;
|
||||
private Format webVttFormat;
|
||||
private TimestampAdjuster timestampAdjuster;
|
||||
@ -52,7 +49,6 @@ public class DefaultHlsExtractorFactoryTest {
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
fMp4Extractor = new FragmentedMp4Extractor();
|
||||
tsUri = Uri.parse("http://path/filename.ts");
|
||||
webVttFormat = new Format.Builder().setSampleMimeType(MimeTypes.TEXT_VTT).build();
|
||||
timestampAdjuster = new TimestampAdjuster(/* firstSampleTimestampUs= */ 0);
|
||||
@ -60,24 +56,6 @@ public class DefaultHlsExtractorFactoryTest {
|
||||
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
|
||||
public void createExtractor_withFileTypeInFormat_returnsExtractorMatchingFormat()
|
||||
throws Exception {
|
||||
@ -88,7 +66,7 @@ public class DefaultHlsExtractorFactoryTest {
|
||||
ApplicationProvider.getApplicationContext(), "webvtt/typical"))
|
||||
.build();
|
||||
|
||||
HlsExtractorFactory.Result result =
|
||||
BundledHlsMediaChunkExtractor result =
|
||||
new DefaultHlsExtractorFactory()
|
||||
.createExtractor(
|
||||
/* previousExtractor= */ null,
|
||||
@ -112,7 +90,7 @@ public class DefaultHlsExtractorFactoryTest {
|
||||
TestUtil.getByteArray(ApplicationProvider.getApplicationContext(), "ts/sample.ac3"))
|
||||
.build();
|
||||
|
||||
HlsExtractorFactory.Result result =
|
||||
BundledHlsMediaChunkExtractor result =
|
||||
new DefaultHlsExtractorFactory()
|
||||
.createExtractor(
|
||||
/* previousExtractor= */ null,
|
||||
@ -135,7 +113,7 @@ public class DefaultHlsExtractorFactoryTest {
|
||||
ApplicationProvider.getApplicationContext(), "ts/sample_ac3.ts"))
|
||||
.build();
|
||||
|
||||
HlsExtractorFactory.Result result =
|
||||
BundledHlsMediaChunkExtractor result =
|
||||
new DefaultHlsExtractorFactory()
|
||||
.createExtractor(
|
||||
/* previousExtractor= */ null,
|
||||
@ -159,7 +137,7 @@ public class DefaultHlsExtractorFactoryTest {
|
||||
ApplicationProvider.getApplicationContext(), "mp3/bear-id3.mp3"))
|
||||
.build();
|
||||
|
||||
HlsExtractorFactory.Result result =
|
||||
BundledHlsMediaChunkExtractor result =
|
||||
new DefaultHlsExtractorFactory()
|
||||
.createExtractor(
|
||||
/* previousExtractor= */ null,
|
||||
@ -177,7 +155,7 @@ public class DefaultHlsExtractorFactoryTest {
|
||||
public void createExtractor_withNoMatchingExtractor_fallsBackOnTsExtractor() throws Exception {
|
||||
ExtractorInput emptyExtractorInput = new FakeExtractorInput.Builder().build();
|
||||
|
||||
HlsExtractorFactory.Result result =
|
||||
BundledHlsMediaChunkExtractor result =
|
||||
new DefaultHlsExtractorFactory()
|
||||
.createExtractor(
|
||||
/* previousExtractor= */ null,
|
||||
|
Loading…
x
Reference in New Issue
Block a user