Add HlsMediaPeriod getStreamKeys implementation and tests.
PiperOrigin-RevId: 231385563
This commit is contained in:
parent
6a52cd7445
commit
32b40502fc
@ -20,6 +20,7 @@ import com.google.android.exoplayer2.C;
|
|||||||
import com.google.android.exoplayer2.Format;
|
import com.google.android.exoplayer2.Format;
|
||||||
import com.google.android.exoplayer2.SeekParameters;
|
import com.google.android.exoplayer2.SeekParameters;
|
||||||
import com.google.android.exoplayer2.extractor.Extractor;
|
import com.google.android.exoplayer2.extractor.Extractor;
|
||||||
|
import com.google.android.exoplayer2.offline.StreamKey;
|
||||||
import com.google.android.exoplayer2.source.CompositeSequenceableLoaderFactory;
|
import com.google.android.exoplayer2.source.CompositeSequenceableLoaderFactory;
|
||||||
import com.google.android.exoplayer2.source.MediaPeriod;
|
import com.google.android.exoplayer2.source.MediaPeriod;
|
||||||
import com.google.android.exoplayer2.source.MediaSourceEventListener.EventDispatcher;
|
import com.google.android.exoplayer2.source.MediaSourceEventListener.EventDispatcher;
|
||||||
@ -68,6 +69,7 @@ public final class HlsMediaPeriod implements MediaPeriod, HlsSampleStreamWrapper
|
|||||||
private TrackGroupArray trackGroups;
|
private TrackGroupArray trackGroups;
|
||||||
private HlsSampleStreamWrapper[] sampleStreamWrappers;
|
private HlsSampleStreamWrapper[] sampleStreamWrappers;
|
||||||
private HlsSampleStreamWrapper[] enabledSampleStreamWrappers;
|
private HlsSampleStreamWrapper[] enabledSampleStreamWrappers;
|
||||||
|
private int[] selectedVariantIndices;
|
||||||
private SequenceableLoader compositeSequenceableLoader;
|
private SequenceableLoader compositeSequenceableLoader;
|
||||||
private boolean notifiedReadingStarted;
|
private boolean notifiedReadingStarted;
|
||||||
|
|
||||||
@ -112,6 +114,7 @@ public final class HlsMediaPeriod implements MediaPeriod, HlsSampleStreamWrapper
|
|||||||
timestampAdjusterProvider = new TimestampAdjusterProvider();
|
timestampAdjusterProvider = new TimestampAdjusterProvider();
|
||||||
sampleStreamWrappers = new HlsSampleStreamWrapper[0];
|
sampleStreamWrappers = new HlsSampleStreamWrapper[0];
|
||||||
enabledSampleStreamWrappers = new HlsSampleStreamWrapper[0];
|
enabledSampleStreamWrappers = new HlsSampleStreamWrapper[0];
|
||||||
|
selectedVariantIndices = new int[0];
|
||||||
eventDispatcher.mediaPeriodCreated();
|
eventDispatcher.mediaPeriodCreated();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,6 +146,77 @@ public final class HlsMediaPeriod implements MediaPeriod, HlsSampleStreamWrapper
|
|||||||
return trackGroups;
|
return trackGroups;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<StreamKey> getStreamKeys(List<TrackSelection> trackSelections) {
|
||||||
|
// See HlsMasterPlaylist.copy for interpretation of StreamKeys.
|
||||||
|
HlsMasterPlaylist masterPlaylist = Assertions.checkNotNull(playlistTracker.getMasterPlaylist());
|
||||||
|
boolean hasVariants = !masterPlaylist.variants.isEmpty();
|
||||||
|
int audioWrapperOffset = hasVariants ? 1 : 0;
|
||||||
|
int subtitleWrapperOffset = audioWrapperOffset + masterPlaylist.audios.size();
|
||||||
|
|
||||||
|
TrackGroupArray mainWrapperTrackGroups;
|
||||||
|
int mainWrapperPrimaryGroupIndex;
|
||||||
|
if (hasVariants) {
|
||||||
|
HlsSampleStreamWrapper mainWrapper = sampleStreamWrappers[0];
|
||||||
|
mainWrapperTrackGroups = mainWrapper.getTrackGroups();
|
||||||
|
mainWrapperPrimaryGroupIndex = mainWrapper.getPrimaryTrackGroupIndex();
|
||||||
|
} else {
|
||||||
|
mainWrapperTrackGroups = TrackGroupArray.EMPTY;
|
||||||
|
mainWrapperPrimaryGroupIndex = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<StreamKey> streamKeys = new ArrayList<>();
|
||||||
|
boolean needsPrimaryTrackGroupSelection = false;
|
||||||
|
boolean hasPrimaryTrackGroupSelection = false;
|
||||||
|
for (TrackSelection trackSelection : trackSelections) {
|
||||||
|
TrackGroup trackSelectionGroup = trackSelection.getTrackGroup();
|
||||||
|
int mainWrapperTrackGroupIndex = mainWrapperTrackGroups.indexOf(trackSelectionGroup);
|
||||||
|
if (mainWrapperTrackGroupIndex != C.INDEX_UNSET) {
|
||||||
|
if (mainWrapperTrackGroupIndex == mainWrapperPrimaryGroupIndex) {
|
||||||
|
// Primary group in main wrapper.
|
||||||
|
hasPrimaryTrackGroupSelection = true;
|
||||||
|
for (int i = 0; i < trackSelection.length(); i++) {
|
||||||
|
int variantIndex = selectedVariantIndices[trackSelection.getIndexInTrackGroup(i)];
|
||||||
|
streamKeys.add(new StreamKey(HlsMasterPlaylist.GROUP_INDEX_VARIANT, variantIndex));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Embedded group in main wrapper.
|
||||||
|
needsPrimaryTrackGroupSelection = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Audio or subtitle group.
|
||||||
|
for (int i = audioWrapperOffset; i < sampleStreamWrappers.length; i++) {
|
||||||
|
TrackGroupArray wrapperTrackGroups = sampleStreamWrappers[i].getTrackGroups();
|
||||||
|
if (wrapperTrackGroups.indexOf(trackSelectionGroup) != C.INDEX_UNSET) {
|
||||||
|
if (i < subtitleWrapperOffset) {
|
||||||
|
streamKeys.add(
|
||||||
|
new StreamKey(HlsMasterPlaylist.GROUP_INDEX_AUDIO, i - audioWrapperOffset));
|
||||||
|
} else {
|
||||||
|
streamKeys.add(
|
||||||
|
new StreamKey(HlsMasterPlaylist.GROUP_INDEX_SUBTITLE, i - subtitleWrapperOffset));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (needsPrimaryTrackGroupSelection && !hasPrimaryTrackGroupSelection) {
|
||||||
|
// A track selection includes a variant-embedded track, but no variant is added yet. We use
|
||||||
|
// the valid variant with the lowest bitrate to reduce overhead.
|
||||||
|
int lowestBitrateIndex = selectedVariantIndices[0];
|
||||||
|
int lowestBitrate = masterPlaylist.variants.get(selectedVariantIndices[0]).format.bitrate;
|
||||||
|
for (int i = 1; i < selectedVariantIndices.length; i++) {
|
||||||
|
int variantBitrate = masterPlaylist.variants.get(selectedVariantIndices[i]).format.bitrate;
|
||||||
|
if (variantBitrate < lowestBitrate) {
|
||||||
|
lowestBitrate = variantBitrate;
|
||||||
|
lowestBitrateIndex = selectedVariantIndices[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
streamKeys.add(new StreamKey(HlsMasterPlaylist.GROUP_INDEX_VARIANT, lowestBitrateIndex));
|
||||||
|
}
|
||||||
|
return streamKeys;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long selectTracks(TrackSelection[] selections, boolean[] mayRetainStreamFlags,
|
public long selectTracks(TrackSelection[] selections, boolean[] mayRetainStreamFlags,
|
||||||
SampleStream[] streams, boolean[] streamResetFlags, long positionUs) {
|
SampleStream[] streams, boolean[] streamResetFlags, long positionUs) {
|
||||||
@ -424,44 +498,64 @@ public final class HlsMediaPeriod implements MediaPeriod, HlsSampleStreamWrapper
|
|||||||
*/
|
*/
|
||||||
private void buildAndPrepareMainSampleStreamWrapper(
|
private void buildAndPrepareMainSampleStreamWrapper(
|
||||||
HlsMasterPlaylist masterPlaylist, long positionUs) {
|
HlsMasterPlaylist masterPlaylist, long positionUs) {
|
||||||
List<HlsUrl> selectedVariants = new ArrayList<>(masterPlaylist.variants);
|
int[] variantTypes = new int[masterPlaylist.variants.size()];
|
||||||
ArrayList<HlsUrl> definiteVideoVariants = new ArrayList<>();
|
int videoVariantCount = 0;
|
||||||
ArrayList<HlsUrl> definiteAudioOnlyVariants = new ArrayList<>();
|
int audioVariantCount = 0;
|
||||||
for (int i = 0; i < selectedVariants.size(); i++) {
|
for (int i = 0; i < masterPlaylist.variants.size(); i++) {
|
||||||
HlsUrl variant = selectedVariants.get(i);
|
HlsUrl variant = masterPlaylist.variants.get(i);
|
||||||
Format format = variant.format;
|
Format format = variant.format;
|
||||||
if (format.height > 0 || Util.getCodecsOfType(format.codecs, C.TRACK_TYPE_VIDEO) != null) {
|
if (format.height > 0 || Util.getCodecsOfType(format.codecs, C.TRACK_TYPE_VIDEO) != null) {
|
||||||
definiteVideoVariants.add(variant);
|
variantTypes[i] = C.TRACK_TYPE_VIDEO;
|
||||||
|
videoVariantCount++;
|
||||||
} else if (Util.getCodecsOfType(format.codecs, C.TRACK_TYPE_AUDIO) != null) {
|
} else if (Util.getCodecsOfType(format.codecs, C.TRACK_TYPE_AUDIO) != null) {
|
||||||
definiteAudioOnlyVariants.add(variant);
|
variantTypes[i] = C.TRACK_TYPE_AUDIO;
|
||||||
|
audioVariantCount++;
|
||||||
|
} else {
|
||||||
|
variantTypes[i] = C.TRACK_TYPE_UNKNOWN;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!definiteVideoVariants.isEmpty()) {
|
boolean useVideoVariantsOnly = false;
|
||||||
|
boolean useNonAudioVariantsOnly = false;
|
||||||
|
int selectedVariantsCount = variantTypes.length;
|
||||||
|
if (videoVariantCount > 0) {
|
||||||
// We've identified some variants as definitely containing video. Assume variants within the
|
// We've identified some variants as definitely containing video. Assume variants within the
|
||||||
// master playlist are marked consistently, and hence that we have the full set. Filter out
|
// master playlist are marked consistently, and hence that we have the full set. Filter out
|
||||||
// any other variants, which are likely to be audio only.
|
// any other variants, which are likely to be audio only.
|
||||||
selectedVariants = definiteVideoVariants;
|
useVideoVariantsOnly = true;
|
||||||
} else if (definiteAudioOnlyVariants.size() < selectedVariants.size()) {
|
selectedVariantsCount = videoVariantCount;
|
||||||
|
} else if (audioVariantCount < variantTypes.length) {
|
||||||
// We've identified some variants, but not all, as being audio only. Filter them out to leave
|
// We've identified some variants, but not all, as being audio only. Filter them out to leave
|
||||||
// the remaining variants, which are likely to contain video.
|
// the remaining variants, which are likely to contain video.
|
||||||
selectedVariants.removeAll(definiteAudioOnlyVariants);
|
useNonAudioVariantsOnly = true;
|
||||||
} else {
|
selectedVariantsCount = variantTypes.length - audioVariantCount;
|
||||||
// Leave the enabled variants unchanged. They're likely either all video or all audio.
|
|
||||||
}
|
}
|
||||||
Assertions.checkArgument(!selectedVariants.isEmpty());
|
HlsUrl[] selectedVariants = new HlsUrl[selectedVariantsCount];
|
||||||
HlsUrl[] variants = selectedVariants.toArray(new HlsUrl[0]);
|
selectedVariantIndices = new int[selectedVariantsCount];
|
||||||
String codecs = variants[0].format.codecs;
|
int outIndex = 0;
|
||||||
HlsSampleStreamWrapper sampleStreamWrapper = buildSampleStreamWrapper(C.TRACK_TYPE_DEFAULT,
|
for (int i = 0; i < masterPlaylist.variants.size(); i++) {
|
||||||
variants, masterPlaylist.muxedAudioFormat, masterPlaylist.muxedCaptionFormats, positionUs);
|
if ((!useVideoVariantsOnly || variantTypes[i] == C.TRACK_TYPE_VIDEO)
|
||||||
|
&& (!useNonAudioVariantsOnly || variantTypes[i] != C.TRACK_TYPE_AUDIO)) {
|
||||||
|
selectedVariants[outIndex] = masterPlaylist.variants.get(i);
|
||||||
|
selectedVariantIndices[outIndex++] = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
String codecs = selectedVariants[0].format.codecs;
|
||||||
|
HlsSampleStreamWrapper sampleStreamWrapper =
|
||||||
|
buildSampleStreamWrapper(
|
||||||
|
C.TRACK_TYPE_DEFAULT,
|
||||||
|
selectedVariants,
|
||||||
|
masterPlaylist.muxedAudioFormat,
|
||||||
|
masterPlaylist.muxedCaptionFormats,
|
||||||
|
positionUs);
|
||||||
sampleStreamWrappers[0] = sampleStreamWrapper;
|
sampleStreamWrappers[0] = sampleStreamWrapper;
|
||||||
if (allowChunklessPreparation && codecs != null) {
|
if (allowChunklessPreparation && codecs != null) {
|
||||||
boolean variantsContainVideoCodecs = Util.getCodecsOfType(codecs, C.TRACK_TYPE_VIDEO) != null;
|
boolean variantsContainVideoCodecs = Util.getCodecsOfType(codecs, C.TRACK_TYPE_VIDEO) != null;
|
||||||
boolean variantsContainAudioCodecs = Util.getCodecsOfType(codecs, C.TRACK_TYPE_AUDIO) != null;
|
boolean variantsContainAudioCodecs = Util.getCodecsOfType(codecs, C.TRACK_TYPE_AUDIO) != null;
|
||||||
List<TrackGroup> muxedTrackGroups = new ArrayList<>();
|
List<TrackGroup> muxedTrackGroups = new ArrayList<>();
|
||||||
if (variantsContainVideoCodecs) {
|
if (variantsContainVideoCodecs) {
|
||||||
Format[] videoFormats = new Format[selectedVariants.size()];
|
Format[] videoFormats = new Format[selectedVariantsCount];
|
||||||
for (int i = 0; i < videoFormats.length; i++) {
|
for (int i = 0; i < videoFormats.length; i++) {
|
||||||
videoFormats[i] = deriveVideoFormat(variants[i].format);
|
videoFormats[i] = deriveVideoFormat(selectedVariants[i].format);
|
||||||
}
|
}
|
||||||
muxedTrackGroups.add(new TrackGroup(videoFormats));
|
muxedTrackGroups.add(new TrackGroup(videoFormats));
|
||||||
|
|
||||||
@ -470,7 +564,7 @@ public final class HlsMediaPeriod implements MediaPeriod, HlsSampleStreamWrapper
|
|||||||
muxedTrackGroups.add(
|
muxedTrackGroups.add(
|
||||||
new TrackGroup(
|
new TrackGroup(
|
||||||
deriveAudioFormat(
|
deriveAudioFormat(
|
||||||
variants[0].format,
|
selectedVariants[0].format,
|
||||||
masterPlaylist.muxedAudioFormat,
|
masterPlaylist.muxedAudioFormat,
|
||||||
/* isPrimaryTrackInVariant= */ false)));
|
/* isPrimaryTrackInVariant= */ false)));
|
||||||
}
|
}
|
||||||
@ -482,9 +576,9 @@ public final class HlsMediaPeriod implements MediaPeriod, HlsSampleStreamWrapper
|
|||||||
}
|
}
|
||||||
} else if (variantsContainAudioCodecs) {
|
} else if (variantsContainAudioCodecs) {
|
||||||
// Variants only contain audio.
|
// Variants only contain audio.
|
||||||
Format[] audioFormats = new Format[selectedVariants.size()];
|
Format[] audioFormats = new Format[selectedVariantsCount];
|
||||||
for (int i = 0; i < audioFormats.length; i++) {
|
for (int i = 0; i < audioFormats.length; i++) {
|
||||||
Format variantFormat = variants[i].format;
|
Format variantFormat = selectedVariants[i].format;
|
||||||
audioFormats[i] =
|
audioFormats[i] =
|
||||||
deriveAudioFormat(
|
deriveAudioFormat(
|
||||||
variantFormat,
|
variantFormat,
|
||||||
|
@ -214,6 +214,10 @@ import java.util.List;
|
|||||||
return trackGroups;
|
return trackGroups;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getPrimaryTrackGroupIndex() {
|
||||||
|
return primaryTrackGroupIndex;
|
||||||
|
}
|
||||||
|
|
||||||
public int bindSampleQueueToSampleStream(int trackGroupIndex) {
|
public int bindSampleQueueToSampleStream(int trackGroupIndex) {
|
||||||
int sampleQueueIndex = trackGroupToSampleQueueIndex[trackGroupIndex];
|
int sampleQueueIndex = trackGroupToSampleQueueIndex[trackGroupIndex];
|
||||||
if (sampleQueueIndex == C.INDEX_UNSET) {
|
if (sampleQueueIndex == C.INDEX_UNSET) {
|
||||||
|
@ -0,0 +1,184 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 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 static org.mockito.Matchers.anyInt;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
import com.google.android.exoplayer2.Format;
|
||||||
|
import com.google.android.exoplayer2.source.CompositeSequenceableLoaderFactory;
|
||||||
|
import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId;
|
||||||
|
import com.google.android.exoplayer2.source.MediaSourceEventListener.EventDispatcher;
|
||||||
|
import com.google.android.exoplayer2.source.hls.playlist.HlsMasterPlaylist;
|
||||||
|
import com.google.android.exoplayer2.source.hls.playlist.HlsMasterPlaylist.HlsUrl;
|
||||||
|
import com.google.android.exoplayer2.source.hls.playlist.HlsPlaylist;
|
||||||
|
import com.google.android.exoplayer2.source.hls.playlist.HlsPlaylistTracker;
|
||||||
|
import com.google.android.exoplayer2.testutil.MediaPeriodAsserts;
|
||||||
|
import com.google.android.exoplayer2.testutil.MediaPeriodAsserts.FilterableManifestMediaPeriodFactory;
|
||||||
|
import com.google.android.exoplayer2.testutil.RobolectricUtil;
|
||||||
|
import com.google.android.exoplayer2.upstream.Allocator;
|
||||||
|
import com.google.android.exoplayer2.upstream.DataSource;
|
||||||
|
import com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy;
|
||||||
|
import com.google.android.exoplayer2.upstream.TransferListener;
|
||||||
|
import com.google.android.exoplayer2.util.MimeTypes;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.robolectric.RobolectricTestRunner;
|
||||||
|
import org.robolectric.annotation.Config;
|
||||||
|
|
||||||
|
/** Unit test for {@link HlsMediaPeriod}. */
|
||||||
|
@RunWith(RobolectricTestRunner.class)
|
||||||
|
@Config(shadows = {RobolectricUtil.CustomLooper.class, RobolectricUtil.CustomMessageQueue.class})
|
||||||
|
public final class HlsMediaPeriodTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getSteamKeys_isCompatibleWithhHlsMasterPlaylistFilter() {
|
||||||
|
HlsMasterPlaylist testMasterPlaylist =
|
||||||
|
createMasterPlaylist(
|
||||||
|
/* variants= */ Arrays.asList(
|
||||||
|
createAudioOnlyVariantHlsUrl(/* bitrate= */ 10000),
|
||||||
|
createMuxedVideoAudioVariantHlsUrl(/* bitrate= */ 200000),
|
||||||
|
createAudioOnlyVariantHlsUrl(/* bitrate= */ 300000),
|
||||||
|
createMuxedVideoAudioVariantHlsUrl(/* bitrate= */ 400000),
|
||||||
|
createMuxedVideoAudioVariantHlsUrl(/* bitrate= */ 600000)),
|
||||||
|
/* audios= */ Arrays.asList(
|
||||||
|
createAudioHlsUrl(/* language= */ "spa"),
|
||||||
|
createAudioHlsUrl(/* language= */ "ger"),
|
||||||
|
createAudioHlsUrl(/* language= */ "tur")),
|
||||||
|
/* subtitles= */ Arrays.asList(
|
||||||
|
createSubtitleHlsUrl(/* language= */ "spa"),
|
||||||
|
createSubtitleHlsUrl(/* language= */ "ger"),
|
||||||
|
createSubtitleHlsUrl(/* language= */ "tur")),
|
||||||
|
/* muxedAudioFormat= */ createAudioFormat("eng"),
|
||||||
|
/* muxedCaptionFormats= */ Arrays.asList(
|
||||||
|
createSubtitleFormat("eng"), createSubtitleFormat("gsw")));
|
||||||
|
FilterableManifestMediaPeriodFactory<HlsPlaylist> mediaPeriodFactory =
|
||||||
|
(playlist, periodIndex) -> {
|
||||||
|
HlsDataSourceFactory mockDataSourceFactory = mock(HlsDataSourceFactory.class);
|
||||||
|
when(mockDataSourceFactory.createDataSource(anyInt())).thenReturn(mock(DataSource.class));
|
||||||
|
HlsPlaylistTracker mockPlaylistTracker = mock(HlsPlaylistTracker.class);
|
||||||
|
when(mockPlaylistTracker.getMasterPlaylist()).thenReturn((HlsMasterPlaylist) playlist);
|
||||||
|
return new HlsMediaPeriod(
|
||||||
|
mock(HlsExtractorFactory.class),
|
||||||
|
mockPlaylistTracker,
|
||||||
|
mockDataSourceFactory,
|
||||||
|
mock(TransferListener.class),
|
||||||
|
mock(LoadErrorHandlingPolicy.class),
|
||||||
|
new EventDispatcher()
|
||||||
|
.withParameters(
|
||||||
|
/* windowIndex= */ 0,
|
||||||
|
/* mediaPeriodId= */ new MediaPeriodId(/* periodUid= */ new Object()),
|
||||||
|
/* mediaTimeOffsetMs= */ 0),
|
||||||
|
mock(Allocator.class),
|
||||||
|
mock(CompositeSequenceableLoaderFactory.class),
|
||||||
|
/* allowChunklessPreparation =*/ true);
|
||||||
|
};
|
||||||
|
|
||||||
|
MediaPeriodAsserts.assertGetStreamKeysAndManifestFilterIntegration(
|
||||||
|
mediaPeriodFactory, testMasterPlaylist);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static HlsMasterPlaylist createMasterPlaylist(
|
||||||
|
List<HlsUrl> variants,
|
||||||
|
List<HlsUrl> audios,
|
||||||
|
List<HlsUrl> subtitles,
|
||||||
|
Format muxedAudioFormat,
|
||||||
|
List<Format> muxedCaptionFormats) {
|
||||||
|
return new HlsMasterPlaylist(
|
||||||
|
"http://baseUri",
|
||||||
|
/* tags= */ Collections.emptyList(),
|
||||||
|
variants,
|
||||||
|
audios,
|
||||||
|
subtitles,
|
||||||
|
muxedAudioFormat,
|
||||||
|
muxedCaptionFormats,
|
||||||
|
/* hasIndependentSegments= */ true,
|
||||||
|
/* variableDefinitions= */ Collections.emptyMap());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static HlsUrl createMuxedVideoAudioVariantHlsUrl(int bitrate) {
|
||||||
|
return new HlsUrl(
|
||||||
|
"http://url",
|
||||||
|
Format.createVideoContainerFormat(
|
||||||
|
/* id= */ null,
|
||||||
|
/* label= */ null,
|
||||||
|
/* containerMimeType= */ MimeTypes.APPLICATION_M3U8,
|
||||||
|
/* sampleMimeType= */ null,
|
||||||
|
/* codecs= */ "avc1.100.41,mp4a.40.2",
|
||||||
|
bitrate,
|
||||||
|
/* width= */ Format.NO_VALUE,
|
||||||
|
/* height= */ Format.NO_VALUE,
|
||||||
|
/* frameRate= */ Format.NO_VALUE,
|
||||||
|
/* initializationData= */ null,
|
||||||
|
/* selectionFlags= */ 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static HlsUrl createAudioOnlyVariantHlsUrl(int bitrate) {
|
||||||
|
return new HlsUrl(
|
||||||
|
"http://url",
|
||||||
|
Format.createVideoContainerFormat(
|
||||||
|
/* id= */ null,
|
||||||
|
/* label= */ null,
|
||||||
|
/* containerMimeType= */ MimeTypes.APPLICATION_M3U8,
|
||||||
|
/* sampleMimeType= */ null,
|
||||||
|
/* codecs= */ "mp4a.40.2",
|
||||||
|
bitrate,
|
||||||
|
/* width= */ Format.NO_VALUE,
|
||||||
|
/* height= */ Format.NO_VALUE,
|
||||||
|
/* frameRate= */ Format.NO_VALUE,
|
||||||
|
/* initializationData= */ null,
|
||||||
|
/* selectionFlags= */ 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static HlsUrl createAudioHlsUrl(String language) {
|
||||||
|
return new HlsUrl("http://url", createAudioFormat(language));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static HlsUrl createSubtitleHlsUrl(String language) {
|
||||||
|
return new HlsUrl("http://url", createSubtitleFormat(language));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Format createAudioFormat(String language) {
|
||||||
|
return Format.createAudioContainerFormat(
|
||||||
|
/* id= */ null,
|
||||||
|
/* label= */ null,
|
||||||
|
/* containerMimeType= */ MimeTypes.APPLICATION_M3U8,
|
||||||
|
MimeTypes.getMediaMimeType("mp4a.40.2"),
|
||||||
|
/* codecs= */ "mp4a.40.2",
|
||||||
|
/* bitrate= */ Format.NO_VALUE,
|
||||||
|
/* channelCount= */ Format.NO_VALUE,
|
||||||
|
/* sampleRate= */ Format.NO_VALUE,
|
||||||
|
/* initializationData= */ null,
|
||||||
|
/* selectionFlags= */ 0,
|
||||||
|
language);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Format createSubtitleFormat(String language) {
|
||||||
|
return Format.createTextContainerFormat(
|
||||||
|
/* id= */ null,
|
||||||
|
/* label= */ null,
|
||||||
|
/* containerMimeType= */ MimeTypes.APPLICATION_M3U8,
|
||||||
|
/* sampleMimeType= */ MimeTypes.TEXT_VTT,
|
||||||
|
/* codecs= */ null,
|
||||||
|
/* bitrate= */ Format.NO_VALUE,
|
||||||
|
/* selectionFlags= */ 0,
|
||||||
|
language);
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user