From da663aa0812f346d68b172ba6f7c59caa00b3523 Mon Sep 17 00:00:00 2001 From: aquilescanta Date: Fri, 23 Oct 2020 14:11:49 +0100 Subject: [PATCH] Avoid chunkless preparation if the codec mapping is ambiguous Issue: #7877 PiperOrigin-RevId: 338659937 --- .../google/android/exoplayer2/util/Util.java | 12 +++++++++ .../exoplayer2/source/hls/HlsMediaPeriod.java | 26 ++++++++++--------- 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/library/common/src/main/java/com/google/android/exoplayer2/util/Util.java b/library/common/src/main/java/com/google/android/exoplayer2/util/Util.java index 745c44395f..441ce84f8d 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/util/Util.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/util/Util.java @@ -1485,6 +1485,18 @@ public final class Util { + ") " + ExoPlayerLibraryInfo.VERSION_SLASHY; } + /** Returns the number of codec strings in {@code codecs} whose type matches {@code trackType}. */ + public static int getCodecCountOfType(@Nullable String codecs, int trackType) { + String[] codecArray = splitCodecs(codecs); + int count = 0; + for (String codec : codecArray) { + if (trackType == MimeTypes.getTrackTypeOfCodec(codec)) { + count++; + } + } + return count; + } + /** * Returns a copy of {@code codecs} without the codecs whose track type doesn't match {@code * trackType}. diff --git a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaPeriod.java b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaPeriod.java index 5e0709228d..0089f68bf4 100644 --- a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaPeriod.java +++ b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaPeriod.java @@ -603,6 +603,12 @@ public final class HlsMediaPeriod implements MediaPeriod, HlsSampleStreamWrapper } } String codecs = selectedPlaylistFormats[0].codecs; + int numberOfVideoCodecs = Util.getCodecCountOfType(codecs, C.TRACK_TYPE_VIDEO); + int numberOfAudioCodecs = Util.getCodecCountOfType(codecs, C.TRACK_TYPE_AUDIO); + boolean codecsStringAllowsChunklessPreparation = + numberOfAudioCodecs <= 1 + && numberOfVideoCodecs <= 1 + && numberOfAudioCodecs + numberOfVideoCodecs > 0; HlsSampleStreamWrapper sampleStreamWrapper = buildSampleStreamWrapper( C.TRACK_TYPE_DEFAULT, @@ -614,18 +620,16 @@ public final class HlsMediaPeriod implements MediaPeriod, HlsSampleStreamWrapper positionUs); sampleStreamWrappers.add(sampleStreamWrapper); manifestUrlIndicesPerWrapper.add(selectedVariantIndices); - if (allowChunklessPreparation && codecs != null) { - boolean variantsContainVideoCodecs = Util.getCodecsOfType(codecs, C.TRACK_TYPE_VIDEO) != null; - boolean variantsContainAudioCodecs = Util.getCodecsOfType(codecs, C.TRACK_TYPE_AUDIO) != null; + if (allowChunklessPreparation && codecsStringAllowsChunklessPreparation) { List muxedTrackGroups = new ArrayList<>(); - if (variantsContainVideoCodecs) { + if (numberOfVideoCodecs > 0) { Format[] videoFormats = new Format[selectedVariantsCount]; for (int i = 0; i < videoFormats.length; i++) { videoFormats[i] = deriveVideoFormat(selectedPlaylistFormats[i]); } muxedTrackGroups.add(new TrackGroup(videoFormats)); - if (variantsContainAudioCodecs + if (numberOfAudioCodecs > 0 && (masterPlaylist.muxedAudioFormat != null || masterPlaylist.audios.isEmpty())) { muxedTrackGroups.add( new TrackGroup( @@ -640,7 +644,7 @@ public final class HlsMediaPeriod implements MediaPeriod, HlsSampleStreamWrapper muxedTrackGroups.add(new TrackGroup(ccFormats.get(i))); } } - } else if (variantsContainAudioCodecs) { + } else /* numberOfAudioCodecs > 0 */ { // Variants only contain audio. Format[] audioFormats = new Format[selectedVariantsCount]; for (int i = 0; i < audioFormats.length; i++) { @@ -651,9 +655,6 @@ public final class HlsMediaPeriod implements MediaPeriod, HlsSampleStreamWrapper /* isPrimaryTrackInVariant= */ true); } muxedTrackGroups.add(new TrackGroup(audioFormats)); - } else { - // Variants contain codecs but no video or audio entries could be identified. - throw new IllegalArgumentException("Unexpected codecs attribute: " + codecs); } TrackGroup id3TrackGroup = @@ -693,7 +694,7 @@ public final class HlsMediaPeriod implements MediaPeriod, HlsSampleStreamWrapper continue; } - boolean renditionsHaveCodecs = true; + boolean codecStringsAllowChunklessPreparation = true; scratchPlaylistUrls.clear(); scratchPlaylistFormats.clear(); scratchIndicesList.clear(); @@ -704,7 +705,8 @@ public final class HlsMediaPeriod implements MediaPeriod, HlsSampleStreamWrapper scratchIndicesList.add(renditionIndex); scratchPlaylistUrls.add(rendition.url); scratchPlaylistFormats.add(rendition.format); - renditionsHaveCodecs &= rendition.format.codecs != null; + codecStringsAllowChunklessPreparation &= + Util.getCodecCountOfType(rendition.format.codecs, C.TRACK_TYPE_AUDIO) == 1; } } @@ -720,7 +722,7 @@ public final class HlsMediaPeriod implements MediaPeriod, HlsSampleStreamWrapper manifestUrlsIndicesPerWrapper.add(Ints.toArray(scratchIndicesList)); sampleStreamWrappers.add(sampleStreamWrapper); - if (allowChunklessPreparation && renditionsHaveCodecs) { + if (allowChunklessPreparation && codecStringsAllowChunklessPreparation) { Format[] renditionFormats = scratchPlaylistFormats.toArray(new Format[0]); sampleStreamWrapper.prepareWithMasterPlaylistInfo( new TrackGroup[] {new TrackGroup(renditionFormats)}, /* primaryTrackGroupIndex= */ 0);