mirror of
https://github.com/androidx/media.git
synced 2025-05-14 02:59:52 +08:00
Fallback to inferred file types when sniffing fails
If none of the extractors successfully sniff the content then we will fall back to inferred file types in the following order: - Webvtt if the media comes from a SUBTITLE EXT-X-MEDIA. - The type of media declared in the HTTP "Content-Type" header. - The type of the media according to the file extension. - Transport stream. Issue: #8700 PiperOrigin-RevId: 362519769
This commit is contained in:
parent
3dae045487
commit
21326e67e3
@ -125,9 +125,13 @@ public final class DefaultHlsExtractorFactory implements HlsExtractorFactory {
|
||||
if (sniffQuietly(extractor, extractorInput)) {
|
||||
return new BundledHlsMediaChunkExtractor(extractor, format, timestampAdjuster);
|
||||
}
|
||||
if (fileType == FileTypes.TS) {
|
||||
// Fall back on TsExtractor to handle TS streams with an EXT-X-MAP tag. See
|
||||
// https://github.com/google/ExoPlayer/issues/8219.
|
||||
if (fallBackExtractor == null
|
||||
&& (fileType == formatInferredFileType
|
||||
|| fileType == responseHeadersInferredFileType
|
||||
|| fileType == uriInferredFileType
|
||||
|| fileType == FileTypes.TS)) {
|
||||
// If sniffing fails, fallback to the file types inferred from context. If all else fails,
|
||||
// fallback to Transport Stream. See https://github.com/google/ExoPlayer/issues/8219.
|
||||
fallBackExtractor = extractor;
|
||||
}
|
||||
}
|
||||
|
@ -24,12 +24,14 @@ import com.google.android.exoplayer2.Format;
|
||||
import com.google.android.exoplayer2.extractor.DefaultExtractorsFactory;
|
||||
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;
|
||||
import com.google.android.exoplayer2.testutil.TestUtil;
|
||||
import com.google.android.exoplayer2.util.MimeTypes;
|
||||
import com.google.android.exoplayer2.util.TimestampAdjuster;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
@ -42,14 +44,15 @@ import org.junit.runner.RunWith;
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class DefaultHlsExtractorFactoryTest {
|
||||
|
||||
private Uri tsUri;
|
||||
private static final Uri URI_WITH_TS_EXTENSION = Uri.parse("http://path/filename.ts");
|
||||
private static final Uri URI_WITH_MP4_EXTENSION = Uri.parse("http://path/filename.mp4");
|
||||
|
||||
private Format webVttFormat;
|
||||
private TimestampAdjuster timestampAdjuster;
|
||||
private Map<String, List<String>> ac3ResponseHeaders;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
tsUri = Uri.parse("http://path/filename.ts");
|
||||
webVttFormat = new Format.Builder().setSampleMimeType(MimeTypes.TEXT_VTT).build();
|
||||
timestampAdjuster = new TimestampAdjuster(/* firstSampleTimestampUs= */ 0);
|
||||
ac3ResponseHeaders = new HashMap<>();
|
||||
@ -69,7 +72,7 @@ public class DefaultHlsExtractorFactoryTest {
|
||||
BundledHlsMediaChunkExtractor result =
|
||||
new DefaultHlsExtractorFactory()
|
||||
.createExtractor(
|
||||
tsUri,
|
||||
URI_WITH_TS_EXTENSION,
|
||||
webVttFormat,
|
||||
/* muxedCaptionFormats= */ null,
|
||||
timestampAdjuster,
|
||||
@ -93,7 +96,7 @@ public class DefaultHlsExtractorFactoryTest {
|
||||
BundledHlsMediaChunkExtractor result =
|
||||
new DefaultHlsExtractorFactory()
|
||||
.createExtractor(
|
||||
tsUri,
|
||||
URI_WITH_TS_EXTENSION,
|
||||
webVttFormat,
|
||||
/* muxedCaptionFormats= */ null,
|
||||
timestampAdjuster,
|
||||
@ -115,7 +118,7 @@ public class DefaultHlsExtractorFactoryTest {
|
||||
BundledHlsMediaChunkExtractor result =
|
||||
new DefaultHlsExtractorFactory()
|
||||
.createExtractor(
|
||||
tsUri,
|
||||
URI_WITH_TS_EXTENSION,
|
||||
webVttFormat,
|
||||
/* muxedCaptionFormats= */ null,
|
||||
timestampAdjuster,
|
||||
@ -138,7 +141,7 @@ public class DefaultHlsExtractorFactoryTest {
|
||||
BundledHlsMediaChunkExtractor result =
|
||||
new DefaultHlsExtractorFactory()
|
||||
.createExtractor(
|
||||
tsUri,
|
||||
URI_WITH_TS_EXTENSION,
|
||||
webVttFormat,
|
||||
/* muxedCaptionFormats= */ null,
|
||||
timestampAdjuster,
|
||||
@ -149,19 +152,75 @@ public class DefaultHlsExtractorFactoryTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createExtractor_withNoMatchingExtractor_fallsBackOnTsExtractor() throws Exception {
|
||||
public void createExtractor_onFailedSniff_fallsBackOnFormatInferred() throws Exception {
|
||||
ExtractorInput emptyExtractorInput = new FakeExtractorInput.Builder().build();
|
||||
|
||||
BundledHlsMediaChunkExtractor result =
|
||||
new DefaultHlsExtractorFactory()
|
||||
.createExtractor(
|
||||
tsUri,
|
||||
URI_WITH_MP4_EXTENSION,
|
||||
webVttFormat,
|
||||
/* muxedCaptionFormats= */ null,
|
||||
timestampAdjuster,
|
||||
ac3ResponseHeaders,
|
||||
emptyExtractorInput);
|
||||
|
||||
// The format indicates WebVTT so we expect a WebVTT extractor.
|
||||
assertThat(result.extractor.getClass()).isEqualTo(WebvttExtractor.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createExtractor_onFailedSniff_fallsBackOnHttpContentType() throws Exception {
|
||||
ExtractorInput emptyExtractorInput = new FakeExtractorInput.Builder().build();
|
||||
|
||||
BundledHlsMediaChunkExtractor result =
|
||||
new DefaultHlsExtractorFactory()
|
||||
.createExtractor(
|
||||
URI_WITH_MP4_EXTENSION,
|
||||
new Format.Builder().build(),
|
||||
/* muxedCaptionFormats= */ null,
|
||||
timestampAdjuster,
|
||||
ac3ResponseHeaders,
|
||||
emptyExtractorInput);
|
||||
|
||||
// No format info, so we expect an AC-3 Extractor, as per HTTP Content-Type header.
|
||||
assertThat(result.extractor.getClass()).isEqualTo(Ac3Extractor.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createExtractor_onFailedSniff_fallsBackOnFileExtension() throws Exception {
|
||||
ExtractorInput emptyExtractorInput = new FakeExtractorInput.Builder().build();
|
||||
|
||||
BundledHlsMediaChunkExtractor result =
|
||||
new DefaultHlsExtractorFactory()
|
||||
.createExtractor(
|
||||
URI_WITH_MP4_EXTENSION,
|
||||
new Format.Builder().build(),
|
||||
/* muxedCaptionFormats= */ null,
|
||||
timestampAdjuster,
|
||||
/* responseHeaders= */ ImmutableMap.of(),
|
||||
emptyExtractorInput);
|
||||
|
||||
// No format info, and no HTTP headers, so we expect an fMP4 extractor, as per file extension.
|
||||
assertThat(result.extractor.getClass()).isEqualTo(FragmentedMp4Extractor.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createExtractor_onFailedSniff_fallsBackOnTsExtractor() throws Exception {
|
||||
ExtractorInput emptyExtractorInput = new FakeExtractorInput.Builder().build();
|
||||
|
||||
BundledHlsMediaChunkExtractor result =
|
||||
new DefaultHlsExtractorFactory()
|
||||
.createExtractor(
|
||||
Uri.parse("http://path/no_extension"),
|
||||
new Format.Builder().build(),
|
||||
/* muxedCaptionFormats= */ null,
|
||||
timestampAdjuster,
|
||||
/* responseHeaders= */ ImmutableMap.of(),
|
||||
emptyExtractorInput);
|
||||
|
||||
// There's no information for inferring the file type, we expect the factory to fall back on
|
||||
// Transport Stream.
|
||||
assertThat(result.extractor.getClass()).isEqualTo(TsExtractor.class);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user