diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 23ba7ca161..46364e50f7 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -39,6 +39,9 @@ `EXT-X-DISCONTINUITY` tags in different media playlists occur at different positions in time ([#8372](https://github.com/google/ExoPlayer/issues/8372)). + * Fix container type detection for segments with incorrect file extension + or HTTP Content-Type + ([#8733](https://github.com/google/ExoPlayer/issues/8733)). * Remove deprecated symbols: * Remove `Player.DefaultEventListener`. Use `Player.EventListener` instead. diff --git a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/DefaultHlsExtractorFactory.java b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/DefaultHlsExtractorFactory.java index 4c7b5629ba..77333fd4cb 100644 --- a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/DefaultHlsExtractorFactory.java +++ b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/DefaultHlsExtractorFactory.java @@ -35,6 +35,7 @@ import com.google.android.exoplayer2.metadata.Metadata; import com.google.android.exoplayer2.util.FileTypes; import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.TimestampAdjuster; +import com.google.common.primitives.Ints; import java.io.EOFException; import java.io.IOException; import java.util.ArrayList; @@ -107,11 +108,11 @@ public final class DefaultHlsExtractorFactory implements HlsExtractorFactory { // Defines the order in which to try the extractors. List fileTypeOrder = new ArrayList<>(/* initialCapacity= */ DEFAULT_EXTRACTOR_ORDER.length); - addFileTypeIfNotPresent(formatInferredFileType, fileTypeOrder); - addFileTypeIfNotPresent(responseHeadersInferredFileType, fileTypeOrder); - addFileTypeIfNotPresent(uriInferredFileType, fileTypeOrder); + addFileTypeIfValidAndNotPresent(formatInferredFileType, fileTypeOrder); + addFileTypeIfValidAndNotPresent(responseHeadersInferredFileType, fileTypeOrder); + addFileTypeIfValidAndNotPresent(uriInferredFileType, fileTypeOrder); for (int fileType : DEFAULT_EXTRACTOR_ORDER) { - addFileTypeIfNotPresent(fileType, fileTypeOrder); + addFileTypeIfValidAndNotPresent(fileType, fileTypeOrder); } // Extractor to be used if the type is not recognized. @@ -140,9 +141,9 @@ public final class DefaultHlsExtractorFactory implements HlsExtractorFactory { checkNotNull(fallBackExtractor), format, timestampAdjuster); } - private static void addFileTypeIfNotPresent( + private static void addFileTypeIfValidAndNotPresent( @FileTypes.Type int fileType, List fileTypes) { - if (fileType == FileTypes.UNKNOWN || fileTypes.contains(fileType)) { + if (Ints.indexOf(DEFAULT_EXTRACTOR_ORDER, fileType) == -1 || fileTypes.contains(fileType)) { return; } fileTypes.add(fileType); diff --git a/library/hls/src/test/java/com/google/android/exoplayer2/source/hls/DefaultHlsExtractorFactoryTest.java b/library/hls/src/test/java/com/google/android/exoplayer2/source/hls/DefaultHlsExtractorFactoryTest.java index 2bbc5bb0f9..7055bc1ba4 100644 --- a/library/hls/src/test/java/com/google/android/exoplayer2/source/hls/DefaultHlsExtractorFactoryTest.java +++ b/library/hls/src/test/java/com/google/android/exoplayer2/source/hls/DefaultHlsExtractorFactoryTest.java @@ -31,6 +31,7 @@ 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.ImmutableList; import com.google.common.collect.ImmutableMap; import java.util.Collections; import java.util.HashMap; @@ -44,8 +45,9 @@ import org.junit.runner.RunWith; @RunWith(AndroidJUnit4.class) public class DefaultHlsExtractorFactoryTest { - private static final Uri URI_WITH_TS_EXTENSION = Uri.parse("http://path/filename.ts"); + private static final Uri URI_WITH_JPEG_EXTENSION = Uri.parse("http://path/filename.jpg"); private static final Uri URI_WITH_MP4_EXTENSION = Uri.parse("http://path/filename.mp4"); + private static final Uri URI_WITH_TS_EXTENSION = Uri.parse("http://path/filename.ts"); private Format webVttFormat; private TimestampAdjuster timestampAdjuster; @@ -151,6 +153,28 @@ public class DefaultHlsExtractorFactoryTest { assertThat(result.extractor.getClass()).isEqualTo(Mp3Extractor.class); } + @Test + public void createExtractor_withInvalidFileTypeInUri_returnsSniffedType() throws Exception { + ExtractorInput tsExtractorInput = + new FakeExtractorInput.Builder() + .setData( + TestUtil.getByteArray( + ApplicationProvider.getApplicationContext(), "media/ts/sample_ac3.ts")) + .build(); + + BundledHlsMediaChunkExtractor result = + new DefaultHlsExtractorFactory() + .createExtractor( + URI_WITH_JPEG_EXTENSION, + webVttFormat, + /* muxedCaptionFormats= */ null, + timestampAdjuster, + ImmutableMap.of("Content-Type", ImmutableList.of(MimeTypes.IMAGE_JPEG)), + tsExtractorInput); + + assertThat(result.extractor.getClass()).isEqualTo(TsExtractor.class); + } + @Test public void createExtractor_onFailedSniff_fallsBackOnFormatInferred() throws Exception { ExtractorInput emptyExtractorInput = new FakeExtractorInput.Builder().build();