Allow seeking to a default position in a period.
When seeking to the default position in a period, the containing source may actually return a position in another period. Multi-period live sources can do this to seek the player to the live edge. ExoPlayerImplInternal uses the same functionality when the playback position reaches the end of a period to determine what period/position to play next. This means that when playback transitions to a multi-period live source from some other source (playing a concatenation of those two sources), the player will play the live edge rather than the beginning of the earliest period. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=128984355
This commit is contained in:
parent
abd5653dc4
commit
c1729b640c
@ -300,6 +300,17 @@ public interface ExoPlayer {
|
||||
*/
|
||||
void seekTo(int periodIndex, long positionMs);
|
||||
|
||||
/**
|
||||
* Seeks to the default position associated with the specified period. The position can depend on
|
||||
* the type of source passed to {@link #setMediaSource(MediaSource)}. For live streams it will
|
||||
* typically be the live edge. For other types of streams it will typically be the start of the
|
||||
* stream.
|
||||
*
|
||||
* @param periodIndex The index of the period whose associated default position should be seeked
|
||||
* to.
|
||||
*/
|
||||
void seekToDefaultPosition(int periodIndex);
|
||||
|
||||
/**
|
||||
* Stops playback. Use {@code setPlayWhenReady(false)} rather than this method if the intention
|
||||
* is to pause playback.
|
||||
|
@ -136,17 +136,25 @@ import java.util.concurrent.CopyOnWriteArraySet;
|
||||
@Override
|
||||
public void seekTo(int periodIndex, long positionMs) {
|
||||
boolean periodChanging = periodIndex != getCurrentPeriodIndex();
|
||||
boolean seekToDefaultPosition = positionMs == ExoPlayer.UNKNOWN_TIME;
|
||||
maskingPeriodIndex = periodIndex;
|
||||
maskingPositionMs = positionMs;
|
||||
maskingPositionMs = seekToDefaultPosition ? 0 : positionMs;
|
||||
maskingDurationMs = periodChanging ? ExoPlayer.UNKNOWN_TIME : getDuration();
|
||||
|
||||
pendingSeekAcks++;
|
||||
internalPlayer.seekTo(periodIndex, positionMs * 1000);
|
||||
for (EventListener listener : listeners) {
|
||||
listener.onPositionDiscontinuity(periodIndex, positionMs);
|
||||
internalPlayer.seekTo(periodIndex, seekToDefaultPosition ? C.UNSET_TIME_US : positionMs * 1000);
|
||||
if (!seekToDefaultPosition) {
|
||||
for (EventListener listener : listeners) {
|
||||
listener.onPositionDiscontinuity(periodIndex, positionMs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void seekToDefaultPosition(int periodIndex) {
|
||||
seekTo(periodIndex, ExoPlayer.UNKNOWN_TIME);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
internalPlayer.stop();
|
||||
@ -180,8 +188,8 @@ import java.util.concurrent.CopyOnWriteArraySet;
|
||||
|
||||
@Override
|
||||
public long getCurrentPosition() {
|
||||
return pendingSeekAcks == 0 ? playbackInfo.positionUs / 1000
|
||||
: maskingPositionMs;
|
||||
return pendingSeekAcks > 0 ? maskingPositionMs
|
||||
: playbackInfo.positionUs == C.UNSET_TIME_US ? 0 : (playbackInfo.positionUs / 1000);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -239,14 +247,23 @@ import java.util.concurrent.CopyOnWriteArraySet;
|
||||
break;
|
||||
}
|
||||
case ExoPlayerImplInternal.MSG_SEEK_ACK: {
|
||||
pendingSeekAcks--;
|
||||
if (--pendingSeekAcks == 0) {
|
||||
long positionMs = playbackInfo.startPositionUs == C.UNSET_TIME_US ? 0
|
||||
: playbackInfo.startPositionUs / 1000;
|
||||
if (playbackInfo.periodIndex != maskingPeriodIndex || positionMs != maskingPositionMs) {
|
||||
for (EventListener listener : listeners) {
|
||||
listener.onPositionDiscontinuity(playbackInfo.periodIndex, positionMs);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ExoPlayerImplInternal.MSG_PERIOD_CHANGED: {
|
||||
case ExoPlayerImplInternal.MSG_POSITION_DISCONTINUITY: {
|
||||
playbackInfo = (ExoPlayerImplInternal.PlaybackInfo) msg.obj;
|
||||
if (pendingSeekAcks == 0) {
|
||||
for (EventListener listener : listeners) {
|
||||
listener.onPositionDiscontinuity(playbackInfo.periodIndex, 0);
|
||||
listener.onPositionDiscontinuity(playbackInfo.periodIndex,
|
||||
playbackInfo.startPositionUs / 1000);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -56,6 +56,7 @@ import java.util.ArrayList;
|
||||
public volatile long positionUs;
|
||||
public volatile long bufferedPositionUs;
|
||||
public volatile long durationUs;
|
||||
public volatile long startPositionUs;
|
||||
|
||||
public PlaybackInfo(int periodIndex) {
|
||||
this.periodIndex = periodIndex;
|
||||
@ -71,7 +72,7 @@ import java.util.ArrayList;
|
||||
public static final int MSG_LOADING_CHANGED = 2;
|
||||
public static final int MSG_SET_PLAY_WHEN_READY_ACK = 3;
|
||||
public static final int MSG_SEEK_ACK = 4;
|
||||
public static final int MSG_PERIOD_CHANGED = 5;
|
||||
public static final int MSG_POSITION_DISCONTINUITY = 5;
|
||||
public static final int MSG_TIMELINE_CHANGED = 6;
|
||||
public static final int MSG_ERROR = 7;
|
||||
|
||||
@ -485,9 +486,20 @@ import java.util.ArrayList;
|
||||
|
||||
private void seekToInternal(int periodIndex, long positionUs) throws ExoPlaybackException {
|
||||
try {
|
||||
if (positionUs == C.UNSET_TIME_US && mediaSource != null) {
|
||||
MediaSource.Position defaultStartPosition =
|
||||
mediaSource.getDefaultStartPosition(periodIndex);
|
||||
if (defaultStartPosition != null) {
|
||||
// We know the default position so seek to it now.
|
||||
periodIndex = defaultStartPosition.periodIndex;
|
||||
positionUs = defaultStartPosition.positionUs;
|
||||
}
|
||||
}
|
||||
|
||||
if (periodIndex == playbackInfo.periodIndex
|
||||
&& (positionUs / 1000) == (playbackInfo.positionUs / 1000)) {
|
||||
// Seek position equals the current position to the nearest millisecond. Do nothing.
|
||||
&& ((positionUs == C.UNSET_TIME_US && playbackInfo.positionUs == C.UNSET_TIME_US)
|
||||
|| ((positionUs / 1000) == (playbackInfo.positionUs / 1000)))) {
|
||||
// Seek position equals the current position. Do nothing.
|
||||
return;
|
||||
}
|
||||
seekToPeriodPosition(periodIndex, positionUs);
|
||||
@ -503,13 +515,15 @@ import java.util.ArrayList;
|
||||
positionUs = internalTimeline.seekTo(periodIndex, positionUs);
|
||||
if (periodIndex != playbackInfo.periodIndex) {
|
||||
playbackInfo = new PlaybackInfo(periodIndex);
|
||||
playbackInfo.startPositionUs = positionUs;
|
||||
playbackInfo.positionUs = positionUs;
|
||||
eventHandler.obtainMessage(MSG_PERIOD_CHANGED, playbackInfo).sendToTarget();
|
||||
eventHandler.obtainMessage(MSG_POSITION_DISCONTINUITY, playbackInfo).sendToTarget();
|
||||
} else {
|
||||
playbackInfo.startPositionUs = positionUs;
|
||||
playbackInfo.positionUs = positionUs;
|
||||
}
|
||||
|
||||
updatePlaybackPositions();
|
||||
|
||||
if (mediaSource != null) {
|
||||
setState(ExoPlayer.STATE_BUFFERING);
|
||||
handler.sendEmptyMessage(MSG_DO_SOME_WORK);
|
||||
@ -681,7 +695,14 @@ import java.util.ArrayList;
|
||||
// Release all loaded periods and seek to the new playing period index.
|
||||
releasePeriodsFrom(playingPeriod);
|
||||
playingPeriod = null;
|
||||
seekToPeriodPosition(newPlayingPeriodIndex, 0);
|
||||
|
||||
MediaSource.Position defaultStartPosition =
|
||||
mediaSource.getDefaultStartPosition(newPlayingPeriodIndex);
|
||||
if (defaultStartPosition != null) {
|
||||
seekToPeriodPosition(defaultStartPosition.periodIndex, defaultStartPosition.positionUs);
|
||||
} else {
|
||||
seekToPeriodPosition(newPlayingPeriodIndex, C.UNSET_TIME_US);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@ -746,9 +767,11 @@ import java.util.ArrayList;
|
||||
: mediaSource.getNewPlayingPeriodIndex(playbackInfo.periodIndex, oldTimeline);
|
||||
if (newPlayingIndex != Timeline.NO_PERIOD_INDEX
|
||||
&& newPlayingIndex != playbackInfo.periodIndex) {
|
||||
long oldPositionUs = playbackInfo.positionUs;
|
||||
playbackInfo = new PlaybackInfo(newPlayingIndex);
|
||||
playbackInfo.startPositionUs = oldPositionUs;
|
||||
updatePlaybackPositions();
|
||||
eventHandler.obtainMessage(MSG_PERIOD_CHANGED, playbackInfo).sendToTarget();
|
||||
eventHandler.obtainMessage(MSG_POSITION_DISCONTINUITY, playbackInfo).sendToTarget();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -762,21 +785,33 @@ import java.util.ArrayList;
|
||||
// Update the loading period.
|
||||
if (loadingPeriod == null || (loadingPeriod.isFullyBuffered() && !loadingPeriod.isLast
|
||||
&& bufferAheadPeriodCount < MAXIMUM_BUFFER_AHEAD_PERIODS)) {
|
||||
// Try to obtain the next period to start loading.
|
||||
int periodIndex = loadingPeriod == null ? playbackInfo.periodIndex
|
||||
: loadingPeriod.index + 1;
|
||||
// Attempt to create the next period.
|
||||
MediaPeriod mediaPeriod = mediaSource.createPeriod(periodIndex);
|
||||
if (mediaPeriod != null) {
|
||||
int periodIndex =
|
||||
loadingPeriod == null ? playbackInfo.periodIndex : loadingPeriod.index + 1;
|
||||
long startPositionUs = playbackInfo.positionUs;
|
||||
if (loadingPeriod != null || startPositionUs == C.UNSET_TIME_US) {
|
||||
// We are starting to load the next period or seeking to the default position, so request
|
||||
// a period and position from the source.
|
||||
MediaSource.Position defaultStartPosition =
|
||||
mediaSource.getDefaultStartPosition(periodIndex);
|
||||
if (defaultStartPosition != null) {
|
||||
periodIndex = defaultStartPosition.periodIndex;
|
||||
startPositionUs = defaultStartPosition.positionUs;
|
||||
} else {
|
||||
startPositionUs = C.UNSET_TIME_US;
|
||||
}
|
||||
}
|
||||
|
||||
MediaPeriod mediaPeriod;
|
||||
if (startPositionUs != C.UNSET_TIME_US
|
||||
&& (mediaPeriod = mediaSource.createPeriod(periodIndex)) != null) {
|
||||
Period newPeriod = new Period(renderers, rendererCapabilities, trackSelector, mediaPeriod,
|
||||
timeline.getPeriodId(periodIndex), periodIndex);
|
||||
timeline.getPeriodId(periodIndex), periodIndex, startPositionUs);
|
||||
newPeriod.isLast = timeline.isFinal() && periodIndex == timeline.getPeriodCount() - 1;
|
||||
if (loadingPeriod != null) {
|
||||
loadingPeriod.setNextPeriod(newPeriod);
|
||||
}
|
||||
bufferAheadPeriodCount++;
|
||||
loadingPeriod = newPeriod;
|
||||
long startPositionUs = playingPeriod == null ? playbackInfo.positionUs : 0;
|
||||
setIsLoading(true);
|
||||
loadingPeriod.mediaPeriod.preparePeriod(ExoPlayerImplInternal.this,
|
||||
loadControl.getAllocator(), startPositionUs);
|
||||
@ -807,8 +842,9 @@ import java.util.ArrayList;
|
||||
setPlayingPeriod(playingPeriod.nextPeriod);
|
||||
bufferAheadPeriodCount--;
|
||||
playbackInfo = new PlaybackInfo(playingPeriod.index);
|
||||
playbackInfo.startPositionUs = playingPeriod.startPositionUs;
|
||||
updatePlaybackPositions();
|
||||
eventHandler.obtainMessage(MSG_PERIOD_CHANGED, playbackInfo).sendToTarget();
|
||||
eventHandler.obtainMessage(MSG_POSITION_DISCONTINUITY, playbackInfo).sendToTarget();
|
||||
}
|
||||
updateTimelineState();
|
||||
if (readingPeriod == null) {
|
||||
@ -858,12 +894,19 @@ import java.util.ArrayList;
|
||||
// Stale event.
|
||||
return;
|
||||
}
|
||||
long startPositionUs = playingPeriod == null ? playbackInfo.positionUs : 0;
|
||||
loadingPeriod.handlePrepared(startPositionUs, loadControl);
|
||||
loadingPeriod.handlePrepared(loadingPeriod.startPositionUs, loadControl);
|
||||
if (playingPeriod == null) {
|
||||
// This is the first prepared period, so start playing it.
|
||||
readingPeriod = loadingPeriod;
|
||||
setPlayingPeriod(readingPeriod);
|
||||
if (playbackInfo.startPositionUs == C.UNSET_TIME_US) {
|
||||
// Update the playback info when seeking to a default position.
|
||||
playbackInfo = new PlaybackInfo(playingPeriod.index);
|
||||
playbackInfo.startPositionUs = playingPeriod.startPositionUs;
|
||||
resetInternalPosition(playbackInfo.startPositionUs);
|
||||
updatePlaybackPositions();
|
||||
eventHandler.obtainMessage(MSG_POSITION_DISCONTINUITY, playbackInfo).sendToTarget();
|
||||
}
|
||||
updateTimelineState();
|
||||
}
|
||||
maybeContinueLoading();
|
||||
@ -895,6 +938,11 @@ import java.util.ArrayList;
|
||||
}
|
||||
|
||||
public long seekTo(int periodIndex, long seekPositionUs) throws ExoPlaybackException {
|
||||
if (seekPositionUs == C.UNSET_TIME_US) {
|
||||
// We don't know where to seek to yet, so clear the whole timeline.
|
||||
periodIndex = Timeline.NO_PERIOD_INDEX;
|
||||
}
|
||||
|
||||
// Clear the timeline, but keep the requested period if it is already prepared.
|
||||
Period period = playingPeriod;
|
||||
Period newPlayingPeriod = null;
|
||||
@ -929,7 +977,9 @@ import java.util.ArrayList;
|
||||
playingPeriod = null;
|
||||
readingPeriod = null;
|
||||
loadingPeriod = null;
|
||||
resetInternalPosition(seekPositionUs);
|
||||
if (seekPositionUs != C.UNSET_TIME_US) {
|
||||
resetInternalPosition(seekPositionUs);
|
||||
}
|
||||
}
|
||||
return seekPositionUs;
|
||||
}
|
||||
@ -1120,6 +1170,7 @@ import java.util.ArrayList;
|
||||
public final MediaPeriod mediaPeriod;
|
||||
public final Object id;
|
||||
public final SampleStream[] sampleStreams;
|
||||
public final long startPositionUs;
|
||||
|
||||
public int index;
|
||||
public boolean isLast;
|
||||
@ -1138,13 +1189,15 @@ import java.util.ArrayList;
|
||||
private TrackSelectionArray periodTrackSelections;
|
||||
|
||||
public Period(Renderer[] renderers, RendererCapabilities[] rendererCapabilities,
|
||||
TrackSelector trackSelector, MediaPeriod mediaPeriod, Object id, int index) {
|
||||
TrackSelector trackSelector, MediaPeriod mediaPeriod, Object id, int index,
|
||||
long positionUs) {
|
||||
this.renderers = renderers;
|
||||
this.rendererCapabilities = rendererCapabilities;
|
||||
this.trackSelector = trackSelector;
|
||||
this.mediaPeriod = mediaPeriod;
|
||||
this.id = Assertions.checkNotNull(id);
|
||||
sampleStreams = new SampleStream[renderers.length];
|
||||
startPositionUs = positionUs;
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
|
@ -359,6 +359,11 @@ public final class SimpleExoPlayer implements ExoPlayer {
|
||||
player.seekTo(periodIndex, positionMs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void seekToDefaultPosition(int periodIndex) {
|
||||
player.seekToDefaultPosition(periodIndex);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
player.stop();
|
||||
|
@ -53,15 +53,25 @@ public final class ConcatenatingMediaSource implements MediaSource {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getNewPlayingPeriodIndex(int oldPlayingPeriodIndex, Timeline oldTimeline)
|
||||
public int getNewPlayingPeriodIndex(int oldPlayingPeriodIndex, Timeline oldConcatenatedTimeline)
|
||||
throws IOException {
|
||||
ConcatenatedTimeline oldConcatenatedTimeline = (ConcatenatedTimeline) oldTimeline;
|
||||
int sourceIndex = oldConcatenatedTimeline.getSourceIndexForPeriod(oldPlayingPeriodIndex);
|
||||
int sourceFirstPeriodIndex = oldConcatenatedTimeline.getFirstPeriodIndexInSource(sourceIndex);
|
||||
return sourceFirstPeriodIndex == Timeline.NO_PERIOD_INDEX ? Timeline.NO_PERIOD_INDEX
|
||||
: sourceFirstPeriodIndex + mediaSources[sourceIndex].getNewPlayingPeriodIndex(
|
||||
oldPlayingPeriodIndex - sourceFirstPeriodIndex,
|
||||
oldConcatenatedTimeline.timelines[sourceIndex]);
|
||||
ConcatenatedTimeline oldTimeline = (ConcatenatedTimeline) oldConcatenatedTimeline;
|
||||
int sourceIndex = oldTimeline.getSourceIndexForPeriod(oldPlayingPeriodIndex);
|
||||
int oldFirstPeriodIndex = oldTimeline.getFirstPeriodIndexInSource(sourceIndex);
|
||||
int firstPeriodIndex = timeline.getFirstPeriodIndexInSource(sourceIndex);
|
||||
return firstPeriodIndex == Timeline.NO_PERIOD_INDEX ? Timeline.NO_PERIOD_INDEX
|
||||
: firstPeriodIndex + mediaSources[sourceIndex].getNewPlayingPeriodIndex(
|
||||
oldPlayingPeriodIndex - oldFirstPeriodIndex, oldTimeline.timelines[sourceIndex]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Position getDefaultStartPosition(int index) {
|
||||
int sourceIndex = timeline.getSourceIndexForPeriod(index);
|
||||
int sourceFirstPeriodIndex = timeline.getFirstPeriodIndexInSource(sourceIndex);
|
||||
Position defaultStartPosition =
|
||||
mediaSources[sourceIndex].getDefaultStartPosition(index - sourceFirstPeriodIndex);
|
||||
return new Position(defaultStartPosition.periodIndex + sourceFirstPeriodIndex,
|
||||
defaultStartPosition.positionUs);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -187,6 +187,11 @@ public final class ExtractorMediaSource implements MediaPeriod, MediaSource,
|
||||
return oldPlayingPeriodIndex;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Position getDefaultStartPosition(int index) {
|
||||
return Position.DEFAULT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MediaPeriod createPeriod(int index) {
|
||||
Assertions.checkArgument(index == 0);
|
||||
|
@ -38,6 +38,38 @@ public interface MediaSource {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* A position in the timeline.
|
||||
*/
|
||||
final class Position {
|
||||
|
||||
/**
|
||||
* A start position at the earliest time in the first period.
|
||||
*/
|
||||
public static final Position DEFAULT = new Position(0, 0);
|
||||
|
||||
/**
|
||||
* The index of the period containing the timeline position.
|
||||
*/
|
||||
public final int periodIndex;
|
||||
|
||||
/**
|
||||
* The position in microseconds within the period.
|
||||
*/
|
||||
public final long positionUs;
|
||||
|
||||
/**
|
||||
* Creates a new timeline position.
|
||||
*
|
||||
* @param periodIndex The index of the period containing the timeline position.
|
||||
* @param positionUs The position in microseconds within the period.
|
||||
*/
|
||||
public Position(int periodIndex, long positionUs) {
|
||||
this.periodIndex = periodIndex;
|
||||
this.positionUs = positionUs;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts preparation of the source.
|
||||
*
|
||||
@ -55,6 +87,20 @@ public interface MediaSource {
|
||||
*/
|
||||
int getNewPlayingPeriodIndex(int oldPlayingPeriodIndex, Timeline oldTimeline) throws IOException;
|
||||
|
||||
/**
|
||||
* Returns the default {@link Position} that the player should play when it reaches the period at
|
||||
* {@code index}, or {@code null} if the default start period and position are not yet known.
|
||||
* <p>
|
||||
* For example, sources can return a {@link Position} with the passed period {@code index} to play
|
||||
* the period at {@code index} immediately after the period at {@code index - 1}. Or, sources
|
||||
* providing multi-period live streams may return the index and position of the live edge when
|
||||
* passed {@code index == 0} so that the playback position jumps to the live edge.
|
||||
*
|
||||
* @param index The index of the period the player has just reached.
|
||||
* @return The default start position.
|
||||
*/
|
||||
Position getDefaultStartPosition(int index);
|
||||
|
||||
/**
|
||||
* Returns a {@link MediaPeriod} corresponding to the period at the specified index, or
|
||||
* {@code null} if the period at the specified index is not yet available.
|
||||
|
@ -64,6 +64,11 @@ public final class MergingMediaSource implements MediaSource {
|
||||
return mediaSources[0].getNewPlayingPeriodIndex(oldPlayingPeriodIndex, oldTimeline);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Position getDefaultStartPosition(int index) {
|
||||
return mediaSources[0].getDefaultStartPosition(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MediaPeriod createPeriod(int index) throws IOException {
|
||||
MediaPeriod[] periods = new MediaPeriod[mediaSources.length];
|
||||
|
@ -122,6 +122,11 @@ public final class SingleSampleMediaSource implements MediaPeriod, MediaSource,
|
||||
return oldPlayingPeriodIndex;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Position getDefaultStartPosition(int index) {
|
||||
return Position.DEFAULT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MediaPeriod createPeriod(int index) {
|
||||
Assertions.checkArgument(index == 0);
|
||||
|
@ -122,6 +122,16 @@ public final class DashMediaSource implements MediaSource {
|
||||
return Timeline.NO_PERIOD_INDEX;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Position getDefaultStartPosition(int index) {
|
||||
if (index == 0 && manifest.dynamic) {
|
||||
// The stream is live, so jump to the live edge.
|
||||
// TODO[playlists]: Actually jump to the live edge, rather than the start of the last period.
|
||||
return new Position(periods.size() - 1, 0);
|
||||
}
|
||||
return new Position(index, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MediaPeriod createPeriod(int index) throws IOException {
|
||||
if (periods == null || periods.size() <= index) {
|
||||
|
@ -118,6 +118,12 @@ public final class HlsMediaSource implements MediaPeriod, MediaSource,
|
||||
return oldPlayingPeriodIndex;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Position getDefaultStartPosition(int index) {
|
||||
// TODO: Return the position of the live edge, if applicable.
|
||||
return Position.DEFAULT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MediaPeriod createPeriod(int index) {
|
||||
Assertions.checkArgument(index == 0);
|
||||
|
@ -100,6 +100,12 @@ public final class SsMediaSource implements MediaSource,
|
||||
return oldPlayingPeriodIndex;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Position getDefaultStartPosition(int index) {
|
||||
// TODO: Return the position of the live edge, if applicable.
|
||||
return Position.DEFAULT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MediaPeriod createPeriod(int index) {
|
||||
Assertions.checkArgument(index == 0);
|
||||
|
Loading…
x
Reference in New Issue
Block a user