Commit 59cf3e02 by olly Committed by Oliver Woodman

HlsChunkSource: Expose stuff for WebVtt/Variant selection.

Issue: #151
Issue: #676
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=111945466
parent 2a9eeaa8
...@@ -129,8 +129,8 @@ public class HlsRendererBuilder implements RendererBuilder { ...@@ -129,8 +129,8 @@ public class HlsRendererBuilder implements RendererBuilder {
DefaultBandwidthMeter bandwidthMeter = new DefaultBandwidthMeter(); DefaultBandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
DataSource dataSource = new DefaultUriDataSource(context, bandwidthMeter, userAgent); DataSource dataSource = new DefaultUriDataSource(context, bandwidthMeter, userAgent);
HlsChunkSource chunkSource = new HlsChunkSource(dataSource, url, manifest, HlsChunkSource chunkSource = new HlsChunkSource(true /* isMaster */, dataSource, url,
DefaultHlsTrackSelector.newDefaultInstance(context), bandwidthMeter, manifest, DefaultHlsTrackSelector.newDefaultInstance(context), bandwidthMeter,
new PtsTimestampAdjusterProvider(), HlsChunkSource.ADAPTIVE_MODE_SPLICE); new PtsTimestampAdjusterProvider(), HlsChunkSource.ADAPTIVE_MODE_SPLICE);
HlsSampleSource sampleSource = new HlsSampleSource(chunkSource, loadControl, HlsSampleSource sampleSource = new HlsSampleSource(chunkSource, loadControl,
BUFFER_SEGMENTS * BUFFER_SEGMENT_SIZE, mainHandler, player, DemoPlayer.TYPE_VIDEO); BUFFER_SEGMENTS * BUFFER_SEGMENT_SIZE, mainHandler, player, DemoPlayer.TYPE_VIDEO);
......
...@@ -118,6 +118,7 @@ public class HlsChunkSource implements HlsTrackSelector.Output { ...@@ -118,6 +118,7 @@ public class HlsChunkSource implements HlsTrackSelector.Output {
private static final String VTT_FILE_EXTENSION = ".webvtt"; private static final String VTT_FILE_EXTENSION = ".webvtt";
private static final float BANDWIDTH_FRACTION = 0.8f; private static final float BANDWIDTH_FRACTION = 0.8f;
private final boolean isMaster;
private final DataSource dataSource; private final DataSource dataSource;
private final HlsPlaylistParser playlistParser; private final HlsPlaylistParser playlistParser;
private final HlsMasterPlaylist masterPlaylist; private final HlsMasterPlaylist masterPlaylist;
...@@ -157,6 +158,9 @@ public class HlsChunkSource implements HlsTrackSelector.Output { ...@@ -157,6 +158,9 @@ public class HlsChunkSource implements HlsTrackSelector.Output {
private byte[] encryptionIv; private byte[] encryptionIv;
/** /**
* @param isMaster True if this is the master source for the playback. False otherwise. Each
* playback must have exactly one master source, which should be the source providing video
* chunks (or audio chunks for audio only playbacks).
* @param dataSource A {@link DataSource} suitable for loading the media data. * @param dataSource A {@link DataSource} suitable for loading the media data.
* @param playlistUrl The playlist URL. * @param playlistUrl The playlist URL.
* @param playlist The hls playlist. * @param playlist The hls playlist.
...@@ -169,15 +173,18 @@ public class HlsChunkSource implements HlsTrackSelector.Output { ...@@ -169,15 +173,18 @@ public class HlsChunkSource implements HlsTrackSelector.Output {
* {@link #ADAPTIVE_MODE_NONE}, {@link #ADAPTIVE_MODE_ABRUPT} and * {@link #ADAPTIVE_MODE_NONE}, {@link #ADAPTIVE_MODE_ABRUPT} and
* {@link #ADAPTIVE_MODE_SPLICE}. * {@link #ADAPTIVE_MODE_SPLICE}.
*/ */
public HlsChunkSource(DataSource dataSource, String playlistUrl, HlsPlaylist playlist, public HlsChunkSource(boolean isMaster, DataSource dataSource, String playlistUrl,
HlsTrackSelector trackSelector, BandwidthMeter bandwidthMeter, HlsPlaylist playlist, HlsTrackSelector trackSelector, BandwidthMeter bandwidthMeter,
PtsTimestampAdjusterProvider timestampAdjusterProvider, int adaptiveMode) { PtsTimestampAdjusterProvider timestampAdjusterProvider, int adaptiveMode) {
this(dataSource, playlistUrl, playlist, trackSelector, bandwidthMeter, this(isMaster, dataSource, playlistUrl, playlist, trackSelector, bandwidthMeter,
timestampAdjusterProvider, adaptiveMode, DEFAULT_MIN_BUFFER_TO_SWITCH_UP_MS, timestampAdjusterProvider, adaptiveMode, DEFAULT_MIN_BUFFER_TO_SWITCH_UP_MS,
DEFAULT_MAX_BUFFER_TO_SWITCH_DOWN_MS); DEFAULT_MAX_BUFFER_TO_SWITCH_DOWN_MS);
} }
/** /**
* @param isMaster True if this is the master source for the playback. False otherwise. Each
* playback must have exactly one master source, which should be the source providing video
* chunks (or audio chunks for audio only playbacks).
* @param dataSource A {@link DataSource} suitable for loading the media data. * @param dataSource A {@link DataSource} suitable for loading the media data.
* @param playlistUrl The playlist URL. * @param playlistUrl The playlist URL.
* @param playlist The hls playlist. * @param playlist The hls playlist.
...@@ -194,10 +201,11 @@ public class HlsChunkSource implements HlsTrackSelector.Output { ...@@ -194,10 +201,11 @@ public class HlsChunkSource implements HlsTrackSelector.Output {
* @param maxBufferDurationToSwitchDownMs The maximum duration of media that needs to be buffered * @param maxBufferDurationToSwitchDownMs The maximum duration of media that needs to be buffered
* for a switch to a lower quality variant to be considered. * for a switch to a lower quality variant to be considered.
*/ */
public HlsChunkSource(DataSource dataSource, String playlistUrl, HlsPlaylist playlist, public HlsChunkSource(boolean isMaster, DataSource dataSource, String playlistUrl,
HlsTrackSelector trackSelector, BandwidthMeter bandwidthMeter, HlsPlaylist playlist, HlsTrackSelector trackSelector, BandwidthMeter bandwidthMeter,
PtsTimestampAdjusterProvider timestampAdjusterProvider, int adaptiveMode, PtsTimestampAdjusterProvider timestampAdjusterProvider, int adaptiveMode,
long minBufferDurationToSwitchUpMs, long maxBufferDurationToSwitchDownMs) { long minBufferDurationToSwitchUpMs, long maxBufferDurationToSwitchDownMs) {
this.isMaster = isMaster;
this.dataSource = dataSource; this.dataSource = dataSource;
this.trackSelector = trackSelector; this.trackSelector = trackSelector;
this.bandwidthMeter = bandwidthMeter; this.bandwidthMeter = bandwidthMeter;
...@@ -221,10 +229,6 @@ public class HlsChunkSource implements HlsTrackSelector.Output { ...@@ -221,10 +229,6 @@ public class HlsChunkSource implements HlsTrackSelector.Output {
} }
} }
public long getDurationUs() {
return durationUs;
}
/** /**
* If the source is currently having difficulty providing chunks, then this method throws the * If the source is currently having difficulty providing chunks, then this method throws the
* underlying error. Otherwise does nothing. * underlying error. Otherwise does nothing.
...@@ -247,13 +251,7 @@ public class HlsChunkSource implements HlsTrackSelector.Output { ...@@ -247,13 +251,7 @@ public class HlsChunkSource implements HlsTrackSelector.Output {
prepareCalled = true; prepareCalled = true;
try { try {
trackSelector.selectTracks(masterPlaylist, this); trackSelector.selectTracks(masterPlaylist, this);
// The following 5 lines are temporarily located here until the tracks are exposed. selectTrack(0);
enabledTrack = tracks.get(0);
selectedVariantIndex = enabledTrack.defaultVariantIndex;
variants = enabledTrack.variants;
variantPlaylists = new HlsMediaPlaylist[variants.length];
variantLastPlaylistLoadTimesMs = new long[variants.length];
variantBlacklistTimes = new long[variants.length];
} catch (IOException e) { } catch (IOException e) {
fatalError = e; fatalError = e;
} }
...@@ -262,6 +260,78 @@ public class HlsChunkSource implements HlsTrackSelector.Output { ...@@ -262,6 +260,78 @@ public class HlsChunkSource implements HlsTrackSelector.Output {
} }
/** /**
* Returns the duration of the source, or {@link C#UNKNOWN_TIME_US} if the duration is unknown.
* <p>
* This method should only be called after the source has been prepared.
*
* @return The number of tracks.
*/
public long getDurationUs() {
return durationUs;
}
/**
* Returns the number of tracks exposed by the source.
* <p>
* This method should only be called after the source has been prepared.
*
* @return The number of tracks.
*/
public int getTrackCount() {
return tracks.size();
}
/**
* Returns the variant corresponding to the fixed track at the specified index, or null if the
* track at the specified index is adaptive.
* <p>
* This method should only be called after the source has been prepared.
*
* @param index The track index.
* @return The variant corresponding to the fixed track, or null if the track is adaptive.
*/
public Variant getFixedTrackVariant(int index) {
Variant[] variants = tracks.get(index).variants;
return variants.length == 1 ? variants[0] : null;
}
/**
* Selects a track for use.
* <p>
* This method should only be called after the source has been prepared.
*
* @param index The track index.
*/
public void selectTrack(int index) {
enabledTrack = tracks.get(index);
selectedVariantIndex = enabledTrack.defaultVariantIndex;
variants = enabledTrack.variants;
variantPlaylists = new HlsMediaPlaylist[variants.length];
variantLastPlaylistLoadTimesMs = new long[variants.length];
variantBlacklistTimes = new long[variants.length];
}
/**
* Notifies the source that a seek has occurred.
* <p>
* This method should only be called after the source has been prepared.
*/
public void seek() {
if (isMaster) {
timestampAdjusterProvider.reset();
}
}
/**
* Resets the source.
* <p>
* This method should only be called after the source has been prepared.
*/
public void reset() {
fatalError = null;
}
/**
* Updates the provided {@link ChunkOperationHolder} to contain the next operation that should * Updates the provided {@link ChunkOperationHolder} to contain the next operation that should
* be performed by the calling {@link HlsSampleSource}. * be performed by the calling {@link HlsSampleSource}.
* *
...@@ -381,11 +451,12 @@ public class HlsChunkSource implements HlsTrackSelector.Output { ...@@ -381,11 +451,12 @@ public class HlsChunkSource implements HlsTrackSelector.Output {
extractorWrapper = new HlsExtractorWrapper(trigger, format, startTimeUs, extractor, extractorWrapper = new HlsExtractorWrapper(trigger, format, startTimeUs, extractor,
switchingVariantSpliced, MediaFormat.NO_VALUE, MediaFormat.NO_VALUE); switchingVariantSpliced, MediaFormat.NO_VALUE, MediaFormat.NO_VALUE);
} else if (lastPathSegment.endsWith(VTT_FILE_EXTENSION)) { } else if (lastPathSegment.endsWith(VTT_FILE_EXTENSION)) {
PtsTimestampAdjuster timestampAdjuster = timestampAdjusterProvider.getAdjuster(false, PtsTimestampAdjuster timestampAdjuster = timestampAdjusterProvider.getAdjuster(isMaster,
segment.discontinuitySequenceNumber, startTimeUs); segment.discontinuitySequenceNumber, startTimeUs);
if (timestampAdjuster == null) { if (timestampAdjuster == null) {
// The master source has yet to instantiate an adjuster for the discontinuity sequence. // The master source has yet to instantiate an adjuster for the discontinuity sequence.
// TODO: Allow VTT to be the master in the case that this is the only chunks source. // TODO: There's probably an edge case if the master starts playback at a chunk belonging to
// a discontinuity sequence greater than the one that this source is trying to start at.
return; return;
} }
Extractor extractor = new WebvttExtractor(timestampAdjuster); Extractor extractor = new WebvttExtractor(timestampAdjuster);
...@@ -395,8 +466,12 @@ public class HlsChunkSource implements HlsTrackSelector.Output { ...@@ -395,8 +466,12 @@ public class HlsChunkSource implements HlsTrackSelector.Output {
|| previousTsChunk.discontinuitySequenceNumber != segment.discontinuitySequenceNumber || previousTsChunk.discontinuitySequenceNumber != segment.discontinuitySequenceNumber
|| !format.equals(previousTsChunk.format)) { || !format.equals(previousTsChunk.format)) {
// MPEG-2 TS segments, but we need a new extractor. // MPEG-2 TS segments, but we need a new extractor.
PtsTimestampAdjuster timestampAdjuster = timestampAdjusterProvider.getAdjuster(true, PtsTimestampAdjuster timestampAdjuster = timestampAdjusterProvider.getAdjuster(isMaster,
segment.discontinuitySequenceNumber, startTimeUs); segment.discontinuitySequenceNumber, startTimeUs);
if (timestampAdjuster == null) {
// The master source has yet to instantiate an adjuster for the discontinuity sequence.
return;
}
Extractor extractor = new TsExtractor(timestampAdjuster); Extractor extractor = new TsExtractor(timestampAdjuster);
extractorWrapper = new HlsExtractorWrapper(trigger, format, startTimeUs, extractor, extractorWrapper = new HlsExtractorWrapper(trigger, format, startTimeUs, extractor,
switchingVariantSpliced, enabledTrack.adaptiveMaxWidth, enabledTrack.adaptiveMaxHeight); switchingVariantSpliced, enabledTrack.adaptiveMaxWidth, enabledTrack.adaptiveMaxHeight);
...@@ -480,11 +555,6 @@ public class HlsChunkSource implements HlsTrackSelector.Output { ...@@ -480,11 +555,6 @@ public class HlsChunkSource implements HlsTrackSelector.Output {
return false; return false;
} }
public void reset() {
timestampAdjusterProvider.reset();
fatalError = null;
}
// HlsTrackSelector.Output implementation. // HlsTrackSelector.Output implementation.
@Override @Override
......
...@@ -358,7 +358,7 @@ public final class HlsSampleSource implements SampleSource, SampleSourceReader, ...@@ -358,7 +358,7 @@ public final class HlsSampleSource implements SampleSource, SampleSourceReader,
for (int i = 0; i < pendingDiscontinuities.length; i++) { for (int i = 0; i < pendingDiscontinuities.length; i++) {
pendingDiscontinuities[i] = true; pendingDiscontinuities[i] = true;
} }
chunkSource.reset(); chunkSource.seek();
restartFrom(positionUs); restartFrom(positionUs);
} }
......
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