Group audio renditions by name
Allows the player to adapt between audio renditions with different names. PiperOrigin-RevId: 233052105
This commit is contained in:
parent
891ec2230e
commit
36da5fb511
@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
### dev-v2 (not yet released) ###
|
### dev-v2 (not yet released) ###
|
||||||
|
|
||||||
|
* HLS:
|
||||||
|
* Form an adaptive track group out of audio renditions with matching name.
|
||||||
* `ExtractorMediaSource` renamed to `ProgressiveMediaSource`.
|
* `ExtractorMediaSource` renamed to `ProgressiveMediaSource`.
|
||||||
* Support for playing spherical videos on Daydream.
|
* Support for playing spherical videos on Daydream.
|
||||||
* Improve decoder re-use between playbacks. TODO: Write and link a blog post
|
* Improve decoder re-use between playbacks. TODO: Write and link a blog post
|
||||||
|
@ -43,6 +43,7 @@ import java.io.IOException;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.IdentityHashMap;
|
import java.util.IdentityHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -70,7 +71,7 @@ public final class HlsMediaPeriod implements MediaPeriod, HlsSampleStreamWrapper
|
|||||||
private HlsSampleStreamWrapper[] sampleStreamWrappers;
|
private HlsSampleStreamWrapper[] sampleStreamWrappers;
|
||||||
private HlsSampleStreamWrapper[] enabledSampleStreamWrappers;
|
private HlsSampleStreamWrapper[] enabledSampleStreamWrappers;
|
||||||
// Maps sample stream wrappers to variant/rendition index by matching array positions.
|
// Maps sample stream wrappers to variant/rendition index by matching array positions.
|
||||||
private int[][] manifestUrlsIndicesPerWrapper;
|
private int[][] manifestUrlIndicesPerWrapper;
|
||||||
private SequenceableLoader compositeSequenceableLoader;
|
private SequenceableLoader compositeSequenceableLoader;
|
||||||
private boolean notifiedReadingStarted;
|
private boolean notifiedReadingStarted;
|
||||||
|
|
||||||
@ -115,7 +116,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];
|
||||||
manifestUrlsIndicesPerWrapper = new int[0][];
|
manifestUrlIndicesPerWrapper = new int[0][];
|
||||||
eventDispatcher.mediaPeriodCreated();
|
eventDispatcher.mediaPeriodCreated();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -153,14 +154,15 @@ public final class HlsMediaPeriod implements MediaPeriod, HlsSampleStreamWrapper
|
|||||||
HlsMasterPlaylist masterPlaylist = Assertions.checkNotNull(playlistTracker.getMasterPlaylist());
|
HlsMasterPlaylist masterPlaylist = Assertions.checkNotNull(playlistTracker.getMasterPlaylist());
|
||||||
boolean hasVariants = !masterPlaylist.variants.isEmpty();
|
boolean hasVariants = !masterPlaylist.variants.isEmpty();
|
||||||
int audioWrapperOffset = hasVariants ? 1 : 0;
|
int audioWrapperOffset = hasVariants ? 1 : 0;
|
||||||
int subtitleWrapperOffset = audioWrapperOffset + masterPlaylist.audios.size();
|
// Subtitle sample stream wrappers are held last.
|
||||||
|
int subtitleWrapperOffset = sampleStreamWrappers.length - masterPlaylist.subtitles.size();
|
||||||
|
|
||||||
TrackGroupArray mainWrapperTrackGroups;
|
TrackGroupArray mainWrapperTrackGroups;
|
||||||
int mainWrapperPrimaryGroupIndex;
|
int mainWrapperPrimaryGroupIndex;
|
||||||
int[] mainWrapperVariantIndices;
|
int[] mainWrapperVariantIndices;
|
||||||
if (hasVariants) {
|
if (hasVariants) {
|
||||||
HlsSampleStreamWrapper mainWrapper = sampleStreamWrappers[0];
|
HlsSampleStreamWrapper mainWrapper = sampleStreamWrappers[0];
|
||||||
mainWrapperVariantIndices = manifestUrlsIndicesPerWrapper[0];
|
mainWrapperVariantIndices = manifestUrlIndicesPerWrapper[0];
|
||||||
mainWrapperTrackGroups = mainWrapper.getTrackGroups();
|
mainWrapperTrackGroups = mainWrapper.getTrackGroups();
|
||||||
mainWrapperPrimaryGroupIndex = mainWrapper.getPrimaryTrackGroupIndex();
|
mainWrapperPrimaryGroupIndex = mainWrapper.getPrimaryTrackGroupIndex();
|
||||||
} else {
|
} else {
|
||||||
@ -191,12 +193,18 @@ public final class HlsMediaPeriod implements MediaPeriod, HlsSampleStreamWrapper
|
|||||||
// Audio or subtitle group.
|
// Audio or subtitle group.
|
||||||
for (int i = audioWrapperOffset; i < sampleStreamWrappers.length; i++) {
|
for (int i = audioWrapperOffset; i < sampleStreamWrappers.length; i++) {
|
||||||
TrackGroupArray wrapperTrackGroups = sampleStreamWrappers[i].getTrackGroups();
|
TrackGroupArray wrapperTrackGroups = sampleStreamWrappers[i].getTrackGroups();
|
||||||
if (wrapperTrackGroups.indexOf(trackSelectionGroup) != C.INDEX_UNSET) {
|
int selectedTrackGroupIndex = wrapperTrackGroups.indexOf(trackSelectionGroup);
|
||||||
|
if (selectedTrackGroupIndex != C.INDEX_UNSET) {
|
||||||
int groupIndexType =
|
int groupIndexType =
|
||||||
i < subtitleWrapperOffset
|
i < subtitleWrapperOffset
|
||||||
? HlsMasterPlaylist.GROUP_INDEX_AUDIO
|
? HlsMasterPlaylist.GROUP_INDEX_AUDIO
|
||||||
: HlsMasterPlaylist.GROUP_INDEX_SUBTITLE;
|
: HlsMasterPlaylist.GROUP_INDEX_SUBTITLE;
|
||||||
streamKeys.add(new StreamKey(groupIndexType, manifestUrlsIndicesPerWrapper[i][0]));
|
int[] selectedWrapperUrlIndices = manifestUrlIndicesPerWrapper[i];
|
||||||
|
for (int trackIndex = 0; trackIndex < trackSelection.length(); trackIndex++) {
|
||||||
|
int renditionIndex =
|
||||||
|
selectedWrapperUrlIndices[trackSelection.getIndexInTrackGroup(trackIndex)];
|
||||||
|
streamKeys.add(new StreamKey(groupIndexType, renditionIndex));
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -424,37 +432,19 @@ public final class HlsMediaPeriod implements MediaPeriod, HlsSampleStreamWrapper
|
|||||||
List<HlsUrl> audioRenditions = masterPlaylist.audios;
|
List<HlsUrl> audioRenditions = masterPlaylist.audios;
|
||||||
List<HlsUrl> subtitleRenditions = masterPlaylist.subtitles;
|
List<HlsUrl> subtitleRenditions = masterPlaylist.subtitles;
|
||||||
|
|
||||||
int wrapperCount = (hasVariants ? 1 : 0) + audioRenditions.size() + subtitleRenditions.size();
|
pendingPrepareCount = 0;
|
||||||
sampleStreamWrappers = new HlsSampleStreamWrapper[wrapperCount];
|
ArrayList<HlsSampleStreamWrapper> sampleStreamWrappers = new ArrayList<>();
|
||||||
manifestUrlsIndicesPerWrapper = new int[wrapperCount][];
|
ArrayList<int[]> manifestUrlIndicesPerWrapper = new ArrayList<>();
|
||||||
pendingPrepareCount = wrapperCount;
|
|
||||||
|
|
||||||
int currentWrapperIndex = 0;
|
|
||||||
if (hasVariants) {
|
if (hasVariants) {
|
||||||
buildAndPrepareMainSampleStreamWrapper(masterPlaylist, positionUs);
|
buildAndPrepareMainSampleStreamWrapper(
|
||||||
currentWrapperIndex++;
|
masterPlaylist, positionUs, sampleStreamWrappers, manifestUrlIndicesPerWrapper);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Build video stream wrappers here.
|
// TODO: Build video stream wrappers here.
|
||||||
|
|
||||||
// Audio sample stream wrappers.
|
buildAndPrepareAudioSampleStreamWrappers(
|
||||||
for (int i = 0; i < audioRenditions.size(); i++) {
|
positionUs, audioRenditions, sampleStreamWrappers, manifestUrlIndicesPerWrapper);
|
||||||
HlsUrl audioRendition = audioRenditions.get(i);
|
|
||||||
HlsSampleStreamWrapper sampleStreamWrapper =
|
|
||||||
buildSampleStreamWrapper(
|
|
||||||
C.TRACK_TYPE_AUDIO,
|
|
||||||
new HlsUrl[] {audioRendition},
|
|
||||||
null,
|
|
||||||
Collections.emptyList(),
|
|
||||||
positionUs);
|
|
||||||
manifestUrlsIndicesPerWrapper[currentWrapperIndex] = new int[] {i};
|
|
||||||
sampleStreamWrappers[currentWrapperIndex++] = sampleStreamWrapper;
|
|
||||||
Format renditionFormat = audioRendition.format;
|
|
||||||
if (allowChunklessPreparation && renditionFormat.codecs != null) {
|
|
||||||
sampleStreamWrapper.prepareWithMasterPlaylistInfo(
|
|
||||||
new TrackGroupArray(new TrackGroup(audioRendition.format)), 0, TrackGroupArray.EMPTY);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Subtitle stream wrappers. We can always use master playlist information to prepare these.
|
// Subtitle stream wrappers. We can always use master playlist information to prepare these.
|
||||||
for (int i = 0; i < subtitleRenditions.size(); i++) {
|
for (int i = 0; i < subtitleRenditions.size(); i++) {
|
||||||
@ -462,20 +452,22 @@ public final class HlsMediaPeriod implements MediaPeriod, HlsSampleStreamWrapper
|
|||||||
HlsSampleStreamWrapper sampleStreamWrapper =
|
HlsSampleStreamWrapper sampleStreamWrapper =
|
||||||
buildSampleStreamWrapper(
|
buildSampleStreamWrapper(
|
||||||
C.TRACK_TYPE_TEXT, new HlsUrl[] {url}, null, Collections.emptyList(), positionUs);
|
C.TRACK_TYPE_TEXT, new HlsUrl[] {url}, null, Collections.emptyList(), positionUs);
|
||||||
manifestUrlsIndicesPerWrapper[currentWrapperIndex] = new int[] {i};
|
manifestUrlIndicesPerWrapper.add(new int[] {i});
|
||||||
sampleStreamWrappers[currentWrapperIndex++] = sampleStreamWrapper;
|
sampleStreamWrappers.add(sampleStreamWrapper);
|
||||||
sampleStreamWrapper.prepareWithMasterPlaylistInfo(
|
sampleStreamWrapper.prepareWithMasterPlaylistInfo(
|
||||||
new TrackGroupArray(new TrackGroup(url.format)), 0, TrackGroupArray.EMPTY);
|
new TrackGroupArray(new TrackGroup(url.format)), 0, TrackGroupArray.EMPTY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.sampleStreamWrappers = sampleStreamWrappers.toArray(new HlsSampleStreamWrapper[0]);
|
||||||
|
this.manifestUrlIndicesPerWrapper = manifestUrlIndicesPerWrapper.toArray(new int[0][]);
|
||||||
|
pendingPrepareCount = this.sampleStreamWrappers.length;
|
||||||
// Set timestamp master and trigger preparation (if not already prepared)
|
// Set timestamp master and trigger preparation (if not already prepared)
|
||||||
sampleStreamWrappers[0].setIsTimestampMaster(true);
|
this.sampleStreamWrappers[0].setIsTimestampMaster(true);
|
||||||
for (HlsSampleStreamWrapper sampleStreamWrapper : sampleStreamWrappers) {
|
for (HlsSampleStreamWrapper sampleStreamWrapper : this.sampleStreamWrappers) {
|
||||||
sampleStreamWrapper.continuePreparing();
|
sampleStreamWrapper.continuePreparing();
|
||||||
}
|
}
|
||||||
|
|
||||||
// All wrappers are enabled during preparation.
|
// All wrappers are enabled during preparation.
|
||||||
enabledSampleStreamWrappers = sampleStreamWrappers;
|
enabledSampleStreamWrappers = this.sampleStreamWrappers;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -501,9 +493,14 @@ public final class HlsMediaPeriod implements MediaPeriod, HlsSampleStreamWrapper
|
|||||||
* @param masterPlaylist The HLS master playlist.
|
* @param masterPlaylist The HLS master playlist.
|
||||||
* @param positionUs If preparation requires any chunk downloads, the position in microseconds at
|
* @param positionUs If preparation requires any chunk downloads, the position in microseconds at
|
||||||
* which downloading should start. Ignored otherwise.
|
* which downloading should start. Ignored otherwise.
|
||||||
|
* @param sampleStreamWrappers List to which the built main sample stream wrapper should be added.
|
||||||
|
* @param manifestUrlIndicesPerWrapper List to which the selected variant indices should be added.
|
||||||
*/
|
*/
|
||||||
private void buildAndPrepareMainSampleStreamWrapper(
|
private void buildAndPrepareMainSampleStreamWrapper(
|
||||||
HlsMasterPlaylist masterPlaylist, long positionUs) {
|
HlsMasterPlaylist masterPlaylist,
|
||||||
|
long positionUs,
|
||||||
|
List<HlsSampleStreamWrapper> sampleStreamWrappers,
|
||||||
|
List<int[]> manifestUrlIndicesPerWrapper) {
|
||||||
int[] variantTypes = new int[masterPlaylist.variants.size()];
|
int[] variantTypes = new int[masterPlaylist.variants.size()];
|
||||||
int videoVariantCount = 0;
|
int videoVariantCount = 0;
|
||||||
int audioVariantCount = 0;
|
int audioVariantCount = 0;
|
||||||
@ -536,13 +533,13 @@ public final class HlsMediaPeriod implements MediaPeriod, HlsSampleStreamWrapper
|
|||||||
selectedVariantsCount = variantTypes.length - audioVariantCount;
|
selectedVariantsCount = variantTypes.length - audioVariantCount;
|
||||||
}
|
}
|
||||||
HlsUrl[] selectedVariants = new HlsUrl[selectedVariantsCount];
|
HlsUrl[] selectedVariants = new HlsUrl[selectedVariantsCount];
|
||||||
manifestUrlsIndicesPerWrapper[0] = new int[selectedVariantsCount];
|
int[] selectedVariantIndices = new int[selectedVariantsCount];
|
||||||
int outIndex = 0;
|
int outIndex = 0;
|
||||||
for (int i = 0; i < masterPlaylist.variants.size(); i++) {
|
for (int i = 0; i < masterPlaylist.variants.size(); i++) {
|
||||||
if ((!useVideoVariantsOnly || variantTypes[i] == C.TRACK_TYPE_VIDEO)
|
if ((!useVideoVariantsOnly || variantTypes[i] == C.TRACK_TYPE_VIDEO)
|
||||||
&& (!useNonAudioVariantsOnly || variantTypes[i] != C.TRACK_TYPE_AUDIO)) {
|
&& (!useNonAudioVariantsOnly || variantTypes[i] != C.TRACK_TYPE_AUDIO)) {
|
||||||
selectedVariants[outIndex] = masterPlaylist.variants.get(i);
|
selectedVariants[outIndex] = masterPlaylist.variants.get(i);
|
||||||
manifestUrlsIndicesPerWrapper[0][outIndex++] = i;
|
selectedVariantIndices[outIndex++] = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
String codecs = selectedVariants[0].format.codecs;
|
String codecs = selectedVariants[0].format.codecs;
|
||||||
@ -553,7 +550,8 @@ public final class HlsMediaPeriod implements MediaPeriod, HlsSampleStreamWrapper
|
|||||||
masterPlaylist.muxedAudioFormat,
|
masterPlaylist.muxedAudioFormat,
|
||||||
masterPlaylist.muxedCaptionFormats,
|
masterPlaylist.muxedCaptionFormats,
|
||||||
positionUs);
|
positionUs);
|
||||||
sampleStreamWrappers[0] = sampleStreamWrapper;
|
sampleStreamWrappers.add(sampleStreamWrapper);
|
||||||
|
manifestUrlIndicesPerWrapper.add(selectedVariantIndices);
|
||||||
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;
|
||||||
@ -614,6 +612,60 @@ public final class HlsMediaPeriod implements MediaPeriod, HlsSampleStreamWrapper
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void buildAndPrepareAudioSampleStreamWrappers(
|
||||||
|
long positionUs,
|
||||||
|
List<HlsUrl> audioRenditions,
|
||||||
|
List<HlsSampleStreamWrapper> sampleStreamWrappers,
|
||||||
|
List<int[]> manifestUrlsIndicesPerWrapper) {
|
||||||
|
|
||||||
|
ArrayList<HlsUrl> scratchRenditionList =
|
||||||
|
new ArrayList<>(/* initialCapacity= */ audioRenditions.size());
|
||||||
|
ArrayList<Integer> scratchIndicesList =
|
||||||
|
new ArrayList<>(/* initialCapacity= */ audioRenditions.size());
|
||||||
|
HashSet<String> alreadyGroupedNames = new HashSet<>();
|
||||||
|
for (int renditionByNameIndex = 0;
|
||||||
|
renditionByNameIndex < audioRenditions.size();
|
||||||
|
renditionByNameIndex++) {
|
||||||
|
String name = audioRenditions.get(renditionByNameIndex).name;
|
||||||
|
if (!alreadyGroupedNames.add(name)) {
|
||||||
|
// This name already has a corresponding group.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean renditionsHaveCodecs = true;
|
||||||
|
scratchRenditionList.clear();
|
||||||
|
scratchIndicesList.clear();
|
||||||
|
// Group all renditions with matching name.
|
||||||
|
for (int renditionIndex = 0; renditionIndex < audioRenditions.size(); renditionIndex++) {
|
||||||
|
if (Util.areEqual(name, audioRenditions.get(renditionIndex).name)) {
|
||||||
|
HlsUrl rendition = audioRenditions.get(renditionIndex);
|
||||||
|
scratchIndicesList.add(renditionIndex);
|
||||||
|
scratchRenditionList.add(rendition);
|
||||||
|
renditionsHaveCodecs &= rendition.format.codecs != null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HlsSampleStreamWrapper sampleStreamWrapper =
|
||||||
|
buildSampleStreamWrapper(
|
||||||
|
C.TRACK_TYPE_AUDIO,
|
||||||
|
scratchRenditionList.toArray(new HlsUrl[0]),
|
||||||
|
/* muxedAudioFormat= */ null,
|
||||||
|
/* muxedCaptionFormats= */ Collections.emptyList(),
|
||||||
|
positionUs);
|
||||||
|
manifestUrlsIndicesPerWrapper.add(Util.toArray(scratchIndicesList));
|
||||||
|
sampleStreamWrappers.add(sampleStreamWrapper);
|
||||||
|
|
||||||
|
if (allowChunklessPreparation && renditionsHaveCodecs) {
|
||||||
|
Format[] renditionFormats = new Format[scratchRenditionList.size()];
|
||||||
|
for (int i = 0; i < renditionFormats.length; i++) {
|
||||||
|
renditionFormats[i] = scratchRenditionList.get(i).format;
|
||||||
|
}
|
||||||
|
sampleStreamWrapper.prepareWithMasterPlaylistInfo(
|
||||||
|
new TrackGroupArray(new TrackGroup(renditionFormats)), 0, TrackGroupArray.EMPTY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private HlsSampleStreamWrapper buildSampleStreamWrapper(int trackType, HlsUrl[] variants,
|
private HlsSampleStreamWrapper buildSampleStreamWrapper(int trackType, HlsUrl[] variants,
|
||||||
Format muxedAudioFormat, List<Format> muxedCaptionFormats, long positionUs) {
|
Format muxedAudioFormat, List<Format> muxedCaptionFormats, long positionUs) {
|
||||||
HlsChunkSource defaultChunkSource =
|
HlsChunkSource defaultChunkSource =
|
||||||
|
@ -67,6 +67,9 @@ import java.util.List;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when the wrapper has been prepared.
|
* Called when the wrapper has been prepared.
|
||||||
|
*
|
||||||
|
* <p>Note: This method will be called on a later handler loop than the one on which either
|
||||||
|
* {@link #prepareWithMasterPlaylistInfo} or {@link #continuePreparing} are invoked.
|
||||||
*/
|
*/
|
||||||
void onPrepared();
|
void onPrepared();
|
||||||
|
|
||||||
@ -203,7 +206,7 @@ import java.util.List;
|
|||||||
this.trackGroups = trackGroups;
|
this.trackGroups = trackGroups;
|
||||||
this.optionalTrackGroups = optionalTrackGroups;
|
this.optionalTrackGroups = optionalTrackGroups;
|
||||||
this.primaryTrackGroupIndex = primaryTrackGroupIndex;
|
this.primaryTrackGroupIndex = primaryTrackGroupIndex;
|
||||||
callback.onPrepared();
|
handler.post(callback::onPrepared);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void maybeThrowPrepareError() throws IOException {
|
public void maybeThrowPrepareError() throws IOException {
|
||||||
|
@ -56,6 +56,11 @@ public final class HlsMasterPlaylist extends HlsPlaylist {
|
|||||||
* Format information associated with the HLS url.
|
* Format information associated with the HLS url.
|
||||||
*/
|
*/
|
||||||
public final Format format;
|
public final Format format;
|
||||||
|
/**
|
||||||
|
* Value of the NAME attribute as defined by the #EXT-X-MEDIA tag, or empty if the HLS url is
|
||||||
|
* not associated with any name.
|
||||||
|
*/
|
||||||
|
public final String name;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an HLS url from a given http url.
|
* Creates an HLS url from a given http url.
|
||||||
@ -74,16 +79,18 @@ public final class HlsMasterPlaylist extends HlsPlaylist {
|
|||||||
/* bitrate= */ Format.NO_VALUE,
|
/* bitrate= */ Format.NO_VALUE,
|
||||||
/* selectionFlags= */ 0,
|
/* selectionFlags= */ 0,
|
||||||
/* language= */ null);
|
/* language= */ null);
|
||||||
return new HlsUrl(url, format);
|
return new HlsUrl(url, format, /* name= */ "");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param url See {@link #url}.
|
* @param url See {@link #url}.
|
||||||
* @param format See {@link #format}.
|
* @param format See {@link #format}.
|
||||||
|
* @param name See {@link #name}.
|
||||||
*/
|
*/
|
||||||
public HlsUrl(String url, Format format) {
|
public HlsUrl(String url, Format format, String name) {
|
||||||
this.url = url;
|
this.url = url;
|
||||||
this.format = format;
|
this.format = format;
|
||||||
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -330,7 +330,7 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
|
|||||||
frameRate,
|
frameRate,
|
||||||
/* initializationData= */ null,
|
/* initializationData= */ null,
|
||||||
/* selectionFlags= */ 0);
|
/* selectionFlags= */ 0);
|
||||||
variants.add(new HlsMasterPlaylist.HlsUrl(line, format));
|
variants.add(new HlsMasterPlaylist.HlsUrl(line, format, /* name= */ ""));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -365,7 +365,7 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
|
|||||||
if (isMediaTagMuxed(variants, uri)) {
|
if (isMediaTagMuxed(variants, uri)) {
|
||||||
muxedAudioFormat = format;
|
muxedAudioFormat = format;
|
||||||
} else {
|
} else {
|
||||||
audios.add(new HlsMasterPlaylist.HlsUrl(uri, format));
|
audios.add(new HlsMasterPlaylist.HlsUrl(uri, format, name));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case TYPE_SUBTITLES:
|
case TYPE_SUBTITLES:
|
||||||
@ -379,7 +379,7 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
|
|||||||
/* bitrate= */ Format.NO_VALUE,
|
/* bitrate= */ Format.NO_VALUE,
|
||||||
selectionFlags,
|
selectionFlags,
|
||||||
language);
|
language);
|
||||||
subtitles.add(new HlsMasterPlaylist.HlsUrl(uri, format));
|
subtitles.add(new HlsMasterPlaylist.HlsUrl(uri, format, name));
|
||||||
break;
|
break;
|
||||||
case TYPE_CLOSED_CAPTIONS:
|
case TYPE_CLOSED_CAPTIONS:
|
||||||
String instreamId = parseStringAttr(line, REGEX_INSTREAM_ID, variableDefinitions);
|
String instreamId = parseStringAttr(line, REGEX_INSTREAM_ID, variableDefinitions);
|
||||||
|
@ -49,7 +49,7 @@ import org.robolectric.annotation.Config;
|
|||||||
public final class HlsMediaPeriodTest {
|
public final class HlsMediaPeriodTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getSteamKeys_isCompatibleWithhHlsMasterPlaylistFilter() {
|
public void getSteamKeys_isCompatibleWithHlsMasterPlaylistFilter() {
|
||||||
HlsMasterPlaylist testMasterPlaylist =
|
HlsMasterPlaylist testMasterPlaylist =
|
||||||
createMasterPlaylist(
|
createMasterPlaylist(
|
||||||
/* variants= */ Arrays.asList(
|
/* variants= */ Arrays.asList(
|
||||||
@ -127,7 +127,8 @@ public final class HlsMediaPeriodTest {
|
|||||||
/* height= */ Format.NO_VALUE,
|
/* height= */ Format.NO_VALUE,
|
||||||
/* frameRate= */ Format.NO_VALUE,
|
/* frameRate= */ Format.NO_VALUE,
|
||||||
/* initializationData= */ null,
|
/* initializationData= */ null,
|
||||||
/* selectionFlags= */ 0));
|
/* selectionFlags= */ 0),
|
||||||
|
/* name= */ "");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static HlsUrl createAudioOnlyVariantHlsUrl(int bitrate) {
|
private static HlsUrl createAudioOnlyVariantHlsUrl(int bitrate) {
|
||||||
@ -144,15 +145,16 @@ public final class HlsMediaPeriodTest {
|
|||||||
/* height= */ Format.NO_VALUE,
|
/* height= */ Format.NO_VALUE,
|
||||||
/* frameRate= */ Format.NO_VALUE,
|
/* frameRate= */ Format.NO_VALUE,
|
||||||
/* initializationData= */ null,
|
/* initializationData= */ null,
|
||||||
/* selectionFlags= */ 0));
|
/* selectionFlags= */ 0),
|
||||||
|
/* name= */ "");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static HlsUrl createAudioHlsUrl(String language) {
|
private static HlsUrl createAudioHlsUrl(String language) {
|
||||||
return new HlsUrl("http://url", createAudioFormat(language));
|
return new HlsUrl("http://url", createAudioFormat(language), /* name= */ "");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static HlsUrl createSubtitleHlsUrl(String language) {
|
private static HlsUrl createSubtitleHlsUrl(String language) {
|
||||||
return new HlsUrl("http://url", createSubtitleFormat(language));
|
return new HlsUrl("http://url", createSubtitleFormat(language), /* name= */ "");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Format createAudioFormat(String language) {
|
private static Format createAudioFormat(String language) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user