Avoid chunkless preparation if the codec mapping is ambiguous

Issue: #7877
PiperOrigin-RevId: 338659937
This commit is contained in:
aquilescanta 2020-10-23 14:11:49 +01:00 committed by Ian Baker
parent 806681dd16
commit da663aa081
2 changed files with 26 additions and 12 deletions

View file

@ -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}.

View file

@ -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<TrackGroup> 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);