Commit 0810fe91 by olly Committed by Toni

Remove "variant" terminology from HlsChunkSource

HlsChunkSource may also be downloading segments from demuxed
renditions, which are not variants.

PiperOrigin-RevId: 240625139
parent 65bab95f
...@@ -96,7 +96,7 @@ import java.util.Map; ...@@ -96,7 +96,7 @@ import java.util.Map;
private final DataSource mediaDataSource; private final DataSource mediaDataSource;
private final DataSource encryptionDataSource; private final DataSource encryptionDataSource;
private final TimestampAdjusterProvider timestampAdjusterProvider; private final TimestampAdjusterProvider timestampAdjusterProvider;
private final HlsUrl[] variants; private final HlsUrl[] hlsUrls;
private final HlsPlaylistTracker playlistTracker; private final HlsPlaylistTracker playlistTracker;
private final TrackGroup trackGroup; private final TrackGroup trackGroup;
private final List<Format> muxedCaptionFormats; private final List<Format> muxedCaptionFormats;
...@@ -119,7 +119,8 @@ import java.util.Map; ...@@ -119,7 +119,8 @@ import java.util.Map;
* @param extractorFactory An {@link HlsExtractorFactory} from which to obtain the extractors for * @param extractorFactory An {@link HlsExtractorFactory} from which to obtain the extractors for
* media chunks. * media chunks.
* @param playlistTracker The {@link HlsPlaylistTracker} from which to obtain media playlists. * @param playlistTracker The {@link HlsPlaylistTracker} from which to obtain media playlists.
* @param variants The available variants. * @param hlsUrls The {@link HlsUrl} instances corresponding to media playlists from which this
* chunk source can obtain media.
* @param dataSourceFactory An {@link HlsDataSourceFactory} to create {@link DataSource}s for the * @param dataSourceFactory An {@link HlsDataSourceFactory} to create {@link DataSource}s for the
* chunks. * chunks.
* @param mediaTransferListener The transfer listener which should be informed of any media data * @param mediaTransferListener The transfer listener which should be informed of any media data
...@@ -133,22 +134,22 @@ import java.util.Map; ...@@ -133,22 +134,22 @@ import java.util.Map;
public HlsChunkSource( public HlsChunkSource(
HlsExtractorFactory extractorFactory, HlsExtractorFactory extractorFactory,
HlsPlaylistTracker playlistTracker, HlsPlaylistTracker playlistTracker,
HlsUrl[] variants, HlsUrl[] hlsUrls,
HlsDataSourceFactory dataSourceFactory, HlsDataSourceFactory dataSourceFactory,
@Nullable TransferListener mediaTransferListener, @Nullable TransferListener mediaTransferListener,
TimestampAdjusterProvider timestampAdjusterProvider, TimestampAdjusterProvider timestampAdjusterProvider,
List<Format> muxedCaptionFormats) { List<Format> muxedCaptionFormats) {
this.extractorFactory = extractorFactory; this.extractorFactory = extractorFactory;
this.playlistTracker = playlistTracker; this.playlistTracker = playlistTracker;
this.variants = variants; this.hlsUrls = hlsUrls;
this.timestampAdjusterProvider = timestampAdjusterProvider; this.timestampAdjusterProvider = timestampAdjusterProvider;
this.muxedCaptionFormats = muxedCaptionFormats; this.muxedCaptionFormats = muxedCaptionFormats;
keyCache = new FullSegmentEncryptionKeyCache(); keyCache = new FullSegmentEncryptionKeyCache();
liveEdgeInPeriodTimeUs = C.TIME_UNSET; liveEdgeInPeriodTimeUs = C.TIME_UNSET;
Format[] variantFormats = new Format[variants.length]; Format[] trackFormats = new Format[hlsUrls.length];
int[] initialTrackSelection = new int[variants.length]; int[] initialTrackSelection = new int[hlsUrls.length];
for (int i = 0; i < variants.length; i++) { for (int i = 0; i < hlsUrls.length; i++) {
variantFormats[i] = variants[i].format; trackFormats[i] = hlsUrls[i].format;
initialTrackSelection[i] = i; initialTrackSelection[i] = i;
} }
mediaDataSource = dataSourceFactory.createDataSource(C.DATA_TYPE_MEDIA); mediaDataSource = dataSourceFactory.createDataSource(C.DATA_TYPE_MEDIA);
...@@ -156,7 +157,7 @@ import java.util.Map; ...@@ -156,7 +157,7 @@ import java.util.Map;
mediaDataSource.addTransferListener(mediaTransferListener); mediaDataSource.addTransferListener(mediaTransferListener);
} }
encryptionDataSource = dataSourceFactory.createDataSource(C.DATA_TYPE_DRM); encryptionDataSource = dataSourceFactory.createDataSource(C.DATA_TYPE_DRM);
trackGroup = new TrackGroup(variantFormats); trackGroup = new TrackGroup(trackFormats);
trackSelection = new InitializationTrackSelection(trackGroup, initialTrackSelection); trackSelection = new InitializationTrackSelection(trackGroup, initialTrackSelection);
} }
...@@ -234,12 +235,11 @@ import java.util.Map; ...@@ -234,12 +235,11 @@ import java.util.Map;
public void getNextChunk( public void getNextChunk(
long playbackPositionUs, long loadPositionUs, List<HlsMediaChunk> queue, HlsChunkHolder out) { long playbackPositionUs, long loadPositionUs, List<HlsMediaChunk> queue, HlsChunkHolder out) {
HlsMediaChunk previous = queue.isEmpty() ? null : queue.get(queue.size() - 1); HlsMediaChunk previous = queue.isEmpty() ? null : queue.get(queue.size() - 1);
int oldVariantIndex = previous == null ? C.INDEX_UNSET int oldTrackIndex = previous == null ? C.INDEX_UNSET : trackGroup.indexOf(previous.trackFormat);
: trackGroup.indexOf(previous.trackFormat);
long bufferedDurationUs = loadPositionUs - playbackPositionUs; long bufferedDurationUs = loadPositionUs - playbackPositionUs;
long timeToLiveEdgeUs = resolveTimeToLiveEdgeUs(playbackPositionUs); long timeToLiveEdgeUs = resolveTimeToLiveEdgeUs(playbackPositionUs);
if (previous != null && !independentSegments) { if (previous != null && !independentSegments) {
// Unless segments are known to be independent, switching variant requires downloading // Unless segments are known to be independent, switching tracks requires downloading
// overlapping segments. Hence we subtract the previous segment's duration from the buffered // overlapping segments. Hence we subtract the previous segment's duration from the buffered
// duration. // duration.
// This may affect the live-streaming adaptive track selection logic, when we compare the // This may affect the live-streaming adaptive track selection logic, when we compare the
...@@ -252,23 +252,23 @@ import java.util.Map; ...@@ -252,23 +252,23 @@ import java.util.Map;
} }
} }
// Select the variant. // Select the track.
MediaChunkIterator[] mediaChunkIterators = createMediaChunkIterators(previous, loadPositionUs); MediaChunkIterator[] mediaChunkIterators = createMediaChunkIterators(previous, loadPositionUs);
trackSelection.updateSelectedTrack( trackSelection.updateSelectedTrack(
playbackPositionUs, bufferedDurationUs, timeToLiveEdgeUs, queue, mediaChunkIterators); playbackPositionUs, bufferedDurationUs, timeToLiveEdgeUs, queue, mediaChunkIterators);
int selectedVariantIndex = trackSelection.getSelectedIndexInTrackGroup(); int selectedTrackIndex = trackSelection.getSelectedIndexInTrackGroup();
boolean switchingVariant = oldVariantIndex != selectedVariantIndex; boolean switchingTrack = oldTrackIndex != selectedTrackIndex;
HlsUrl selectedUrl = variants[selectedVariantIndex]; HlsUrl selectedHlsUrl = hlsUrls[selectedTrackIndex];
if (!playlistTracker.isSnapshotValid(selectedUrl)) { if (!playlistTracker.isSnapshotValid(selectedHlsUrl)) {
out.playlist = selectedUrl; out.playlist = selectedHlsUrl;
seenExpectedPlaylistError &= expectedPlaylistUrl == selectedUrl; seenExpectedPlaylistError &= expectedPlaylistUrl == selectedHlsUrl;
expectedPlaylistUrl = selectedUrl; expectedPlaylistUrl = selectedHlsUrl;
// Retry when playlist is refreshed. // Retry when playlist is refreshed.
return; return;
} }
HlsMediaPlaylist mediaPlaylist = HlsMediaPlaylist mediaPlaylist =
playlistTracker.getPlaylistSnapshot(selectedUrl, /* isForPlayback= */ true); playlistTracker.getPlaylistSnapshot(selectedHlsUrl, /* isForPlayback= */ true);
independentSegments = mediaPlaylist.hasIndependentSegments; independentSegments = mediaPlaylist.hasIndependentSegments;
updateLiveEdgeTimeUs(mediaPlaylist); updateLiveEdgeTimeUs(mediaPlaylist);
...@@ -278,14 +278,15 @@ import java.util.Map; ...@@ -278,14 +278,15 @@ import java.util.Map;
mediaPlaylist.startTimeUs - playlistTracker.getInitialStartTimeUs(); mediaPlaylist.startTimeUs - playlistTracker.getInitialStartTimeUs();
long chunkMediaSequence = long chunkMediaSequence =
getChunkMediaSequence( getChunkMediaSequence(
previous, switchingVariant, mediaPlaylist, startOfPlaylistInPeriodUs, loadPositionUs); previous, switchingTrack, mediaPlaylist, startOfPlaylistInPeriodUs, loadPositionUs);
if (chunkMediaSequence < mediaPlaylist.mediaSequence) { if (chunkMediaSequence < mediaPlaylist.mediaSequence) {
if (previous != null && switchingVariant) { if (previous != null && switchingTrack) {
// We try getting the next chunk without adapting in case that's the reason for falling // We try getting the next chunk without adapting in case that's the reason for falling
// behind the live window. // behind the live window.
selectedVariantIndex = oldVariantIndex; selectedTrackIndex = oldTrackIndex;
selectedUrl = variants[selectedVariantIndex]; selectedHlsUrl = hlsUrls[selectedTrackIndex];
mediaPlaylist = playlistTracker.getPlaylistSnapshot(selectedUrl, /* isForPlayback= */ true); mediaPlaylist =
playlistTracker.getPlaylistSnapshot(selectedHlsUrl, /* isForPlayback= */ true);
startOfPlaylistInPeriodUs = startOfPlaylistInPeriodUs =
mediaPlaylist.startTimeUs - playlistTracker.getInitialStartTimeUs(); mediaPlaylist.startTimeUs - playlistTracker.getInitialStartTimeUs();
chunkMediaSequence = previous.getNextChunkIndex(); chunkMediaSequence = previous.getNextChunkIndex();
...@@ -300,9 +301,9 @@ import java.util.Map; ...@@ -300,9 +301,9 @@ import java.util.Map;
if (mediaPlaylist.hasEndTag) { if (mediaPlaylist.hasEndTag) {
out.endOfStream = true; out.endOfStream = true;
} else /* Live */ { } else /* Live */ {
out.playlist = selectedUrl; out.playlist = selectedHlsUrl;
seenExpectedPlaylistError &= expectedPlaylistUrl == selectedUrl; seenExpectedPlaylistError &= expectedPlaylistUrl == selectedHlsUrl;
expectedPlaylistUrl = selectedUrl; expectedPlaylistUrl = selectedHlsUrl;
} }
return; return;
} }
...@@ -315,12 +316,12 @@ import java.util.Map; ...@@ -315,12 +316,12 @@ import java.util.Map;
// Check if the segment or its initialization segment are fully encrypted. // Check if the segment or its initialization segment are fully encrypted.
Uri initSegmentKeyUri = getFullEncryptionKeyUri(mediaPlaylist, segment.initializationSegment); Uri initSegmentKeyUri = getFullEncryptionKeyUri(mediaPlaylist, segment.initializationSegment);
out.chunk = maybeCreateEncryptionChunkFor(initSegmentKeyUri, selectedVariantIndex); out.chunk = maybeCreateEncryptionChunkFor(initSegmentKeyUri, selectedTrackIndex);
if (out.chunk != null) { if (out.chunk != null) {
return; return;
} }
Uri mediaSegmentKeyUri = getFullEncryptionKeyUri(mediaPlaylist, segment); Uri mediaSegmentKeyUri = getFullEncryptionKeyUri(mediaPlaylist, segment);
out.chunk = maybeCreateEncryptionChunkFor(mediaSegmentKeyUri, selectedVariantIndex); out.chunk = maybeCreateEncryptionChunkFor(mediaSegmentKeyUri, selectedTrackIndex);
if (out.chunk != null) { if (out.chunk != null) {
return; return;
} }
...@@ -332,7 +333,7 @@ import java.util.Map; ...@@ -332,7 +333,7 @@ import java.util.Map;
startOfPlaylistInPeriodUs, startOfPlaylistInPeriodUs,
mediaPlaylist, mediaPlaylist,
segmentIndexInPlaylist, segmentIndexInPlaylist,
selectedUrl, selectedHlsUrl,
muxedCaptionFormats, muxedCaptionFormats,
trackSelection.getSelectionReason(), trackSelection.getSelectionReason(),
trackSelection.getSelectionData(), trackSelection.getSelectionData(),
...@@ -374,13 +375,13 @@ import java.util.Map; ...@@ -374,13 +375,13 @@ import java.util.Map;
/** /**
* Called when a playlist load encounters an error. * Called when a playlist load encounters an error.
* *
* @param url The url of the playlist whose load encountered an error. * @param hlsUrl The {@link HlsUrl} of the playlist whose load encountered an error.
* @param blacklistDurationMs The duration for which the playlist should be blacklisted. Or {@link * @param blacklistDurationMs The duration for which the playlist should be blacklisted. Or {@link
* C#TIME_UNSET} if the playlist should not be blacklisted. * C#TIME_UNSET} if the playlist should not be blacklisted.
* @return True if blacklisting did not encounter errors. False otherwise. * @return True if blacklisting did not encounter errors. False otherwise.
*/ */
public boolean onPlaylistError(HlsUrl url, long blacklistDurationMs) { public boolean onPlaylistError(HlsUrl hlsUrl, long blacklistDurationMs) {
int trackGroupIndex = trackGroup.indexOf(url.format); int trackGroupIndex = trackGroup.indexOf(hlsUrl.format);
if (trackGroupIndex == C.INDEX_UNSET) { if (trackGroupIndex == C.INDEX_UNSET) {
return true; return true;
} }
...@@ -388,7 +389,7 @@ import java.util.Map; ...@@ -388,7 +389,7 @@ import java.util.Map;
if (trackSelectionIndex == C.INDEX_UNSET) { if (trackSelectionIndex == C.INDEX_UNSET) {
return true; return true;
} }
seenExpectedPlaylistError |= expectedPlaylistUrl == url; seenExpectedPlaylistError |= expectedPlaylistUrl == hlsUrl;
return blacklistDurationMs == C.TIME_UNSET return blacklistDurationMs == C.TIME_UNSET
|| trackSelection.blacklist(trackSelectionIndex, blacklistDurationMs); || trackSelection.blacklist(trackSelectionIndex, blacklistDurationMs);
} }
...@@ -402,24 +403,23 @@ import java.util.Map; ...@@ -402,24 +403,23 @@ import java.util.Map;
*/ */
public MediaChunkIterator[] createMediaChunkIterators( public MediaChunkIterator[] createMediaChunkIterators(
@Nullable HlsMediaChunk previous, long loadPositionUs) { @Nullable HlsMediaChunk previous, long loadPositionUs) {
int oldVariantIndex = int oldTrackIndex = previous == null ? C.INDEX_UNSET : trackGroup.indexOf(previous.trackFormat);
previous == null ? C.INDEX_UNSET : trackGroup.indexOf(previous.trackFormat);
MediaChunkIterator[] chunkIterators = new MediaChunkIterator[trackSelection.length()]; MediaChunkIterator[] chunkIterators = new MediaChunkIterator[trackSelection.length()];
for (int i = 0; i < chunkIterators.length; i++) { for (int i = 0; i < chunkIterators.length; i++) {
int variantIndex = trackSelection.getIndexInTrackGroup(i); int trackIndex = trackSelection.getIndexInTrackGroup(i);
HlsUrl variantUrl = variants[variantIndex]; HlsUrl hlsUrl = hlsUrls[trackIndex];
if (!playlistTracker.isSnapshotValid(variantUrl)) { if (!playlistTracker.isSnapshotValid(hlsUrl)) {
chunkIterators[i] = MediaChunkIterator.EMPTY; chunkIterators[i] = MediaChunkIterator.EMPTY;
continue; continue;
} }
HlsMediaPlaylist playlist = HlsMediaPlaylist playlist =
playlistTracker.getPlaylistSnapshot(variantUrl, /* isForPlayback= */ false); playlistTracker.getPlaylistSnapshot(hlsUrl, /* isForPlayback= */ false);
long startOfPlaylistInPeriodUs = long startOfPlaylistInPeriodUs =
playlist.startTimeUs - playlistTracker.getInitialStartTimeUs(); playlist.startTimeUs - playlistTracker.getInitialStartTimeUs();
boolean switchingVariant = variantIndex != oldVariantIndex; boolean switchingTrack = trackIndex != oldTrackIndex;
long chunkMediaSequence = long chunkMediaSequence =
getChunkMediaSequence( getChunkMediaSequence(
previous, switchingVariant, playlist, startOfPlaylistInPeriodUs, loadPositionUs); previous, switchingTrack, playlist, startOfPlaylistInPeriodUs, loadPositionUs);
if (chunkMediaSequence < playlist.mediaSequence) { if (chunkMediaSequence < playlist.mediaSequence) {
chunkIterators[i] = MediaChunkIterator.EMPTY; chunkIterators[i] = MediaChunkIterator.EMPTY;
continue; continue;
...@@ -437,8 +437,8 @@ import java.util.Map; ...@@ -437,8 +437,8 @@ import java.util.Map;
* Returns the media sequence number of the segment to load next in {@code mediaPlaylist}. * Returns the media sequence number of the segment to load next in {@code mediaPlaylist}.
* *
* @param previous The last (at least partially) loaded segment. * @param previous The last (at least partially) loaded segment.
* @param switchingVariant Whether the segment to load is not preceded by a segment in the same * @param switchingTrack Whether the segment to load is not preceded by a segment in the same
* variant. * track.
* @param mediaPlaylist The media playlist to which the segment to load belongs. * @param mediaPlaylist The media playlist to which the segment to load belongs.
* @param startOfPlaylistInPeriodUs The start of {@code mediaPlaylist} relative to the period * @param startOfPlaylistInPeriodUs The start of {@code mediaPlaylist} relative to the period
* start in microseconds. * start in microseconds.
...@@ -447,11 +447,11 @@ import java.util.Map; ...@@ -447,11 +447,11 @@ import java.util.Map;
*/ */
private long getChunkMediaSequence( private long getChunkMediaSequence(
@Nullable HlsMediaChunk previous, @Nullable HlsMediaChunk previous,
boolean switchingVariant, boolean switchingTrack,
HlsMediaPlaylist mediaPlaylist, HlsMediaPlaylist mediaPlaylist,
long startOfPlaylistInPeriodUs, long startOfPlaylistInPeriodUs,
long loadPositionUs) { long loadPositionUs) {
if (previous == null || switchingVariant) { if (previous == null || switchingTrack) {
long endOfPlaylistInPeriodUs = startOfPlaylistInPeriodUs + mediaPlaylist.durationUs; long endOfPlaylistInPeriodUs = startOfPlaylistInPeriodUs + mediaPlaylist.durationUs;
long targetPositionInPeriodUs = long targetPositionInPeriodUs =
(previous == null || independentSegments) ? loadPositionUs : previous.startTimeUs; (previous == null || independentSegments) ? loadPositionUs : previous.startTimeUs;
...@@ -487,7 +487,7 @@ import java.util.Map; ...@@ -487,7 +487,7 @@ import java.util.Map;
} }
@Nullable @Nullable
private Chunk maybeCreateEncryptionChunkFor(@Nullable Uri keyUri, int selectedVariantIndex) { private Chunk maybeCreateEncryptionChunkFor(@Nullable Uri keyUri, int selectedTrackIndex) {
if (keyUri == null) { if (keyUri == null) {
return null; return null;
} }
...@@ -502,7 +502,7 @@ import java.util.Map; ...@@ -502,7 +502,7 @@ import java.util.Map;
return new EncryptionKeyChunk( return new EncryptionKeyChunk(
encryptionDataSource, encryptionDataSource,
dataSpec, dataSpec,
variants[selectedVariantIndex].format, hlsUrls[selectedTrackIndex].format,
trackSelection.getSelectionReason(), trackSelection.getSelectionReason(),
trackSelection.getSelectionData(), trackSelection.getSelectionData(),
scratchSpace); scratchSpace);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment