Move default start position into Window
------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=130610236
This commit is contained in:
parent
3e0bae616f
commit
b2a28a140c
@ -445,7 +445,7 @@ import java.io.IOException;
|
|||||||
long playingPeriodDuration = timeline.getPeriodDurationUs(playingPeriod.index);
|
long playingPeriodDuration = timeline.getPeriodDurationUs(playingPeriod.index);
|
||||||
if (allRenderersEnded
|
if (allRenderersEnded
|
||||||
&& (playingPeriodDuration == C.UNSET_TIME_US
|
&& (playingPeriodDuration == C.UNSET_TIME_US
|
||||||
|| playingPeriodDuration <= playbackInfo.positionUs)
|
|| playingPeriodDuration <= playbackInfo.positionUs)
|
||||||
&& isTimelineEnded) {
|
&& isTimelineEnded) {
|
||||||
setState(ExoPlayer.STATE_ENDED);
|
setState(ExoPlayer.STATE_ENDED);
|
||||||
stopRenderers();
|
stopRenderers();
|
||||||
@ -495,19 +495,17 @@ import java.io.IOException;
|
|||||||
|
|
||||||
private void seekToInternal(int periodIndex, long positionUs) throws ExoPlaybackException {
|
private void seekToInternal(int periodIndex, long positionUs) throws ExoPlaybackException {
|
||||||
try {
|
try {
|
||||||
if (positionUs == C.UNSET_TIME_US && mediaSource != null) {
|
if (positionUs == C.UNSET_TIME_US && timeline != null
|
||||||
MediaSource.Position defaultStartPosition =
|
&& periodIndex < timeline.getPeriodCount()) {
|
||||||
mediaSource.getDefaultStartPosition(periodIndex);
|
// We know about the window, so seek to its default initial position now.
|
||||||
if (defaultStartPosition != null) {
|
Window window = timeline.getPeriodWindow(periodIndex);
|
||||||
// We know the default position so seek to it now.
|
periodIndex = window.defaultInitialPeriodIndex;
|
||||||
periodIndex = defaultStartPosition.periodIndex;
|
positionUs = window.defaultInitialTimeMs * 1000;
|
||||||
positionUs = defaultStartPosition.positionUs;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (periodIndex == playbackInfo.periodIndex
|
if (periodIndex == playbackInfo.periodIndex
|
||||||
&& ((positionUs == C.UNSET_TIME_US && playbackInfo.positionUs == C.UNSET_TIME_US)
|
&& ((positionUs == C.UNSET_TIME_US && playbackInfo.positionUs == C.UNSET_TIME_US)
|
||||||
|| ((positionUs / 1000) == (playbackInfo.positionUs / 1000)))) {
|
|| ((positionUs / 1000) == (playbackInfo.positionUs / 1000)))) {
|
||||||
// Seek position equals the current position. Do nothing.
|
// Seek position equals the current position. Do nothing.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -805,22 +803,18 @@ import java.io.IOException;
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Release all loaded periods and seek to the new playing period index.
|
// Release all loaded periods.
|
||||||
releasePeriodsFrom(playingPeriod);
|
releasePeriodsFrom(playingPeriod);
|
||||||
playingPeriod = null;
|
playingPeriod = null;
|
||||||
readingPeriod = null;
|
readingPeriod = null;
|
||||||
loadingPeriod = null;
|
loadingPeriod = null;
|
||||||
|
|
||||||
MediaSource.Position defaultStartPosition =
|
// Find the default initial position in the window and seek to it.
|
||||||
mediaSource.getDefaultStartPosition(newPlayingPeriodIndex);
|
Window window = timeline.getPeriodWindow(newPlayingPeriodIndex);
|
||||||
long newPlayingPositionUs;
|
newPlayingPeriodIndex = window.defaultInitialPeriodIndex;
|
||||||
if (defaultStartPosition != null) {
|
long newPlayingPositionUs = seekToPeriodPosition(newPlayingPeriodIndex,
|
||||||
newPlayingPeriodIndex = defaultStartPosition.periodIndex;
|
window.defaultInitialTimeMs);
|
||||||
newPlayingPositionUs = seekToPeriodPosition(defaultStartPosition.periodIndex,
|
|
||||||
defaultStartPosition.positionUs);
|
|
||||||
} else {
|
|
||||||
newPlayingPositionUs = seekToPeriodPosition(newPlayingPeriodIndex, C.UNSET_TIME_US);
|
|
||||||
}
|
|
||||||
playbackInfo = new PlaybackInfo(newPlayingPeriodIndex, newPlayingPositionUs);
|
playbackInfo = new PlaybackInfo(newPlayingPeriodIndex, newPlayingPositionUs);
|
||||||
eventHandler.obtainMessage(MSG_POSITION_DISCONTINUITY, playbackInfo).sendToTarget();
|
eventHandler.obtainMessage(MSG_POSITION_DISCONTINUITY, playbackInfo).sendToTarget();
|
||||||
return;
|
return;
|
||||||
@ -901,33 +895,29 @@ import java.io.IOException;
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the loading period.
|
|
||||||
if (loadingPeriod == null || (loadingPeriod.isFullyBuffered() && !loadingPeriod.isLast
|
if (loadingPeriod == null || (loadingPeriod.isFullyBuffered() && !loadingPeriod.isLast
|
||||||
&& bufferAheadPeriodCount < MAXIMUM_BUFFER_AHEAD_PERIODS)) {
|
&& bufferAheadPeriodCount < MAXIMUM_BUFFER_AHEAD_PERIODS)) {
|
||||||
int periodIndex = loadingPeriod == null ? playbackInfo.periodIndex : loadingPeriod.index + 1;
|
// We don't have a loading period or it's fully loaded, so try and create the next one.
|
||||||
long startPositionUs = playbackInfo.positionUs;
|
int newLoadingPeriodIndex = loadingPeriod == null ? playbackInfo.periodIndex
|
||||||
if (loadingPeriod != null || startPositionUs == C.UNSET_TIME_US) {
|
: loadingPeriod.index + 1;
|
||||||
// We are starting to load the next period or seeking to the default position, so request a
|
if (newLoadingPeriodIndex >= timeline.getPeriodCount()) {
|
||||||
// period and position from the source.
|
// The period is not available yet.
|
||||||
MediaSource.Position defaultStartPosition =
|
|
||||||
mediaSource.getDefaultStartPosition(periodIndex);
|
|
||||||
if (defaultStartPosition != null) {
|
|
||||||
periodIndex = defaultStartPosition.periodIndex;
|
|
||||||
startPositionUs = defaultStartPosition.positionUs;
|
|
||||||
} else {
|
|
||||||
startPositionUs = C.UNSET_TIME_US;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (periodIndex >= timeline.getPeriodCount()) {
|
|
||||||
// This period is not available yet.
|
|
||||||
mediaSource.maybeThrowSourceInfoRefreshError();
|
mediaSource.maybeThrowSourceInfoRefreshError();
|
||||||
} else if (startPositionUs != C.UNSET_TIME_US) {
|
} else {
|
||||||
MediaPeriod mediaPeriod = mediaSource.createPeriod(periodIndex, this,
|
Window window = timeline.getPeriodWindow(newLoadingPeriodIndex);
|
||||||
|
long startPositionUs = loadingPeriod == null ? playbackInfo.positionUs : C.UNSET_TIME_US;
|
||||||
|
if (startPositionUs == C.UNSET_TIME_US) {
|
||||||
|
// This is the first period of a new window or we don't have a start position, so seek to
|
||||||
|
// the default position for the window.
|
||||||
|
newLoadingPeriodIndex = window.defaultInitialPeriodIndex;
|
||||||
|
startPositionUs = window.defaultInitialTimeMs * 1000;
|
||||||
|
}
|
||||||
|
MediaPeriod mediaPeriod = mediaSource.createPeriod(newLoadingPeriodIndex, this,
|
||||||
loadControl.getAllocator(), startPositionUs);
|
loadControl.getAllocator(), startPositionUs);
|
||||||
Period newPeriod = new Period(renderers, rendererCapabilities, trackSelector, mediaSource,
|
Period newPeriod = new Period(renderers, rendererCapabilities, trackSelector, mediaSource,
|
||||||
mediaPeriod, timeline.getPeriodId(periodIndex), startPositionUs);
|
mediaPeriod, timeline.getPeriodId(newLoadingPeriodIndex), startPositionUs);
|
||||||
newPeriod.setIndex(timeline, periodIndex);
|
newPeriod.setIndex(timeline, newLoadingPeriodIndex);
|
||||||
if (loadingPeriod != null) {
|
if (loadingPeriod != null) {
|
||||||
loadingPeriod.setNextPeriod(newPeriod);
|
loadingPeriod.setNextPeriod(newPeriod);
|
||||||
newPeriod.offsetUs = loadingPeriod.offsetUs
|
newPeriod.offsetUs = loadingPeriod.offsetUs
|
||||||
|
@ -21,8 +21,8 @@ package com.google.android.exoplayer2;
|
|||||||
public final class Window {
|
public final class Window {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new {@link Window} containing times from zero up to {@code durationUs} in the first
|
* Creates a new {@link Window} consisting of a single period starting at time zero and with the
|
||||||
* period.
|
* specified duration. The default initial position is the start of the window.
|
||||||
*
|
*
|
||||||
* @param durationUs The duration of the window, in microseconds.
|
* @param durationUs The duration of the window, in microseconds.
|
||||||
* @param isSeekable Whether seeking is supported within the window.
|
* @param isSeekable Whether seeking is supported within the window.
|
||||||
@ -30,7 +30,27 @@ public final class Window {
|
|||||||
*/
|
*/
|
||||||
public static Window createWindowFromZero(long durationUs, boolean isSeekable,
|
public static Window createWindowFromZero(long durationUs, boolean isSeekable,
|
||||||
boolean isDynamic) {
|
boolean isDynamic) {
|
||||||
return createWindow(0, 0, 0, durationUs, durationUs, isSeekable, isDynamic);
|
return createWindow(0, 0, 0, durationUs, durationUs, isSeekable, isDynamic, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link Window} representing the specified time range. The default initial
|
||||||
|
* position is the start of the window.
|
||||||
|
*
|
||||||
|
* @param startPeriodIndex The index of the period containing the start of the window.
|
||||||
|
* @param startTimeUs The start time of the window in microseconds, relative to the start of the
|
||||||
|
* specified start period.
|
||||||
|
* @param endPeriodIndex The index of the period containing the end of the window.
|
||||||
|
* @param endTimeUs The end time of the window in microseconds, relative to the start of the
|
||||||
|
* specified end period.
|
||||||
|
* @param durationUs The duration of the window in microseconds.
|
||||||
|
* @param isSeekable Whether seeking is supported within the window.
|
||||||
|
* @param isDynamic Whether this seek window may change when the timeline is updated.
|
||||||
|
*/
|
||||||
|
public static Window createWindow(int startPeriodIndex, long startTimeUs,
|
||||||
|
int endPeriodIndex, long endTimeUs, long durationUs, boolean isSeekable, boolean isDynamic) {
|
||||||
|
return createWindow(startPeriodIndex, startTimeUs, endPeriodIndex, endTimeUs, durationUs,
|
||||||
|
isSeekable, isDynamic, startPeriodIndex, startTimeUs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -45,13 +65,18 @@ public final class Window {
|
|||||||
* @param durationUs The duration of the window in microseconds.
|
* @param durationUs The duration of the window in microseconds.
|
||||||
* @param isSeekable Whether seeking is supported within the window.
|
* @param isSeekable Whether seeking is supported within the window.
|
||||||
* @param isDynamic Whether this seek window may change when the timeline is updated.
|
* @param isDynamic Whether this seek window may change when the timeline is updated.
|
||||||
|
* @param defaultInitialPeriodIndex The index of the period containing the default position from
|
||||||
|
* which playback should start.
|
||||||
|
* @param defaultInitialTimeUs The time of the default position from which playback should start
|
||||||
|
* in microseconds, relative to the start of the period that contains it.
|
||||||
*/
|
*/
|
||||||
public static Window createWindow(int startPeriodIndex, long startTimeUs,
|
public static Window createWindow(int startPeriodIndex, long startTimeUs,
|
||||||
int endPeriodIndex, long endTimeUs, long durationUs, boolean isSeekable, boolean isDynamic) {
|
int endPeriodIndex, long endTimeUs, long durationUs, boolean isSeekable, boolean isDynamic,
|
||||||
|
int defaultInitialPeriodIndex, long defaultInitialTimeUs) {
|
||||||
return new Window(startPeriodIndex, startTimeUs / 1000, endPeriodIndex,
|
return new Window(startPeriodIndex, startTimeUs / 1000, endPeriodIndex,
|
||||||
endTimeUs == C.UNSET_TIME_US ? ExoPlayer.UNKNOWN_TIME : (endTimeUs / 1000),
|
endTimeUs == C.UNSET_TIME_US ? ExoPlayer.UNKNOWN_TIME : (endTimeUs / 1000),
|
||||||
durationUs == C.UNSET_TIME_US ? ExoPlayer.UNKNOWN_TIME : (durationUs / 1000),
|
durationUs == C.UNSET_TIME_US ? ExoPlayer.UNKNOWN_TIME : (durationUs / 1000),
|
||||||
isSeekable, isDynamic);
|
isSeekable, isDynamic, defaultInitialPeriodIndex, defaultInitialTimeUs / 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -84,9 +109,19 @@ public final class Window {
|
|||||||
* Whether this seek window may change when the timeline is updated.
|
* Whether this seek window may change when the timeline is updated.
|
||||||
*/
|
*/
|
||||||
public final boolean isDynamic;
|
public final boolean isDynamic;
|
||||||
|
/**
|
||||||
|
* The period index of the default position from which playback should start.
|
||||||
|
*/
|
||||||
|
public final int defaultInitialPeriodIndex;
|
||||||
|
/**
|
||||||
|
* The time of the default position relative to the start of the period at
|
||||||
|
* {@link #defaultInitialPeriodIndex}, in milliseconds.
|
||||||
|
*/
|
||||||
|
public final long defaultInitialTimeMs;
|
||||||
|
|
||||||
private Window(int startPeriodIndex, long startTimeMs, int endPeriodIndex, long endTimeMs,
|
private Window(int startPeriodIndex, long startTimeMs, int endPeriodIndex, long endTimeMs,
|
||||||
long durationMs, boolean isSeekable, boolean isDynamic) {
|
long durationMs, boolean isSeekable, boolean isDynamic, int defaultInitialPeriodIndex,
|
||||||
|
long defaultInitialTimeMs) {
|
||||||
this.startPeriodIndex = startPeriodIndex;
|
this.startPeriodIndex = startPeriodIndex;
|
||||||
this.startTimeMs = startTimeMs;
|
this.startTimeMs = startTimeMs;
|
||||||
this.endPeriodIndex = endPeriodIndex;
|
this.endPeriodIndex = endPeriodIndex;
|
||||||
@ -94,6 +129,8 @@ public final class Window {
|
|||||||
this.durationMs = durationMs;
|
this.durationMs = durationMs;
|
||||||
this.isSeekable = isSeekable;
|
this.isSeekable = isSeekable;
|
||||||
this.isDynamic = isDynamic;
|
this.isDynamic = isDynamic;
|
||||||
|
this.defaultInitialPeriodIndex = defaultInitialPeriodIndex;
|
||||||
|
this.defaultInitialTimeMs = defaultInitialTimeMs;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -105,7 +142,8 @@ public final class Window {
|
|||||||
*/
|
*/
|
||||||
public Window copyOffsetByPeriodCount(int periodCount) {
|
public Window copyOffsetByPeriodCount(int periodCount) {
|
||||||
return new Window(startPeriodIndex + periodCount, startTimeMs, endPeriodIndex + periodCount,
|
return new Window(startPeriodIndex + periodCount, startTimeMs, endPeriodIndex + periodCount,
|
||||||
endTimeMs, durationMs, isSeekable, isDynamic);
|
endTimeMs, durationMs, isSeekable, isDynamic, defaultInitialPeriodIndex + periodCount,
|
||||||
|
defaultInitialTimeMs);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -115,7 +153,10 @@ public final class Window {
|
|||||||
result = 31 * result + (int) startTimeMs;
|
result = 31 * result + (int) startTimeMs;
|
||||||
result = 31 * result + endPeriodIndex;
|
result = 31 * result + endPeriodIndex;
|
||||||
result = 31 * result + (int) endTimeMs;
|
result = 31 * result + (int) endTimeMs;
|
||||||
|
result = 31 * result + (isSeekable ? 1 : 2);
|
||||||
result = 31 * result + (isDynamic ? 1 : 2);
|
result = 31 * result + (isDynamic ? 1 : 2);
|
||||||
|
result = 31 * result + defaultInitialPeriodIndex;
|
||||||
|
result = 31 * result + (int) defaultInitialTimeMs;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -134,7 +175,9 @@ public final class Window {
|
|||||||
&& other.endTimeMs == endTimeMs
|
&& other.endTimeMs == endTimeMs
|
||||||
&& other.durationMs == durationMs
|
&& other.durationMs == durationMs
|
||||||
&& other.isSeekable == isSeekable
|
&& other.isSeekable == isSeekable
|
||||||
&& other.isDynamic == isDynamic;
|
&& other.isDynamic == isDynamic
|
||||||
|
&& other.defaultInitialPeriodIndex == defaultInitialPeriodIndex
|
||||||
|
&& other.defaultInitialTimeMs == defaultInitialTimeMs;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -82,16 +82,6 @@ public final class ConcatenatingMediaSource implements MediaSource {
|
|||||||
oldPlayingPeriodIndex - oldFirstPeriodIndex, oldTimeline.timelines[sourceIndex]);
|
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
|
@Override
|
||||||
public void maybeThrowSourceInfoRefreshError() throws IOException {
|
public void maybeThrowSourceInfoRefreshError() throws IOException {
|
||||||
for (MediaSource mediaSource : mediaSources) {
|
for (MediaSource mediaSource : mediaSources) {
|
||||||
|
@ -144,11 +144,6 @@ public final class ExtractorMediaSource implements MediaSource, MediaSource.List
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Position getDefaultStartPosition(int index) {
|
|
||||||
return Position.DEFAULT;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void maybeThrowSourceInfoRefreshError() throws IOException {
|
public void maybeThrowSourceInfoRefreshError() throws IOException {
|
||||||
// Do nothing.
|
// Do nothing.
|
||||||
|
@ -40,39 +40,6 @@ 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.
|
* Starts preparation of the source.
|
||||||
*
|
*
|
||||||
@ -93,20 +60,6 @@ public interface MediaSource {
|
|||||||
*/
|
*/
|
||||||
int getNewPlayingPeriodIndex(int oldPlayingPeriodIndex, Timeline oldTimeline);
|
int getNewPlayingPeriodIndex(int oldPlayingPeriodIndex, Timeline oldTimeline);
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the default {@link Position} that the player should play when when starting to play the
|
|
||||||
* period at {@code index}, or {@code null} if the default position is 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}. Sources
|
|
||||||
* providing multi-period live streams may return the index and position of the live edge when
|
|
||||||
* passed {@code index == 0} to play from the live edge.
|
|
||||||
*
|
|
||||||
* @param index The index of the requested period.
|
|
||||||
* @return The default start position.
|
|
||||||
*/
|
|
||||||
Position getDefaultStartPosition(int index);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Throws any pending error encountered while loading or refreshing source information.
|
* Throws any pending error encountered while loading or refreshing source information.
|
||||||
*/
|
*/
|
||||||
|
@ -70,11 +70,6 @@ public final class MergingMediaSource implements MediaSource {
|
|||||||
return mediaSources[0].getNewPlayingPeriodIndex(oldPlayingPeriodIndex, oldTimeline);
|
return mediaSources[0].getNewPlayingPeriodIndex(oldPlayingPeriodIndex, oldTimeline);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Position getDefaultStartPosition(int index) {
|
|
||||||
return mediaSources[0].getDefaultStartPosition(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void maybeThrowSourceInfoRefreshError() throws IOException {
|
public void maybeThrowSourceInfoRefreshError() throws IOException {
|
||||||
for (MediaSource mediaSource : mediaSources) {
|
for (MediaSource mediaSource : mediaSources) {
|
||||||
|
@ -94,11 +94,6 @@ public final class SingleSampleMediaSource implements MediaSource {
|
|||||||
return oldPlayingPeriodIndex;
|
return oldPlayingPeriodIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Position getDefaultStartPosition(int index) {
|
|
||||||
return Position.DEFAULT;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void maybeThrowSourceInfoRefreshError() throws IOException {
|
public void maybeThrowSourceInfoRefreshError() throws IOException {
|
||||||
// Do nothing.
|
// Do nothing.
|
||||||
|
@ -59,14 +59,14 @@ public final class DashMediaSource implements MediaSource {
|
|||||||
public static final int DEFAULT_MIN_LOADABLE_RETRY_COUNT = 3;
|
public static final int DEFAULT_MIN_LOADABLE_RETRY_COUNT = 3;
|
||||||
/**
|
/**
|
||||||
* A constant indicating that the live edge offset (the offset subtracted from the live edge
|
* A constant indicating that the live edge offset (the offset subtracted from the live edge
|
||||||
* when calculating the default position returned by {@link #getDefaultStartPosition(int)}) should
|
* when calculating the default initial playback position) should be set to
|
||||||
* be set to {@link DashManifest#suggestedPresentationDelay} if specified by the manifest, or
|
* {@link DashManifest#suggestedPresentationDelay} if specified by the manifest, or
|
||||||
* {@link #DEFAULT_LIVE_EDGE_OFFSET_FIXED_MS} otherwise.
|
* {@link #DEFAULT_LIVE_EDGE_OFFSET_FIXED_MS} otherwise.
|
||||||
*/
|
*/
|
||||||
public static final long DEFAULT_LIVE_EDGE_OFFSET_PREFER_MANIFEST_MS = -1;
|
public static final long DEFAULT_LIVE_EDGE_OFFSET_PREFER_MANIFEST_MS = -1;
|
||||||
/**
|
/**
|
||||||
* A fixed default live edge offset (the offset subtracted from the live edge when calculating the
|
* A fixed default live edge offset (the offset subtracted from the live edge when calculating the
|
||||||
* default position returned by {@link #getDefaultStartPosition(int)}).
|
* default initial playback position).
|
||||||
*/
|
*/
|
||||||
public static final long DEFAULT_LIVE_EDGE_OFFSET_FIXED_MS = 30000;
|
public static final long DEFAULT_LIVE_EDGE_OFFSET_FIXED_MS = 30000;
|
||||||
/**
|
/**
|
||||||
@ -167,32 +167,6 @@ public final class DashMediaSource implements MediaSource {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Position getDefaultStartPosition(int index) {
|
|
||||||
if (window == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (index == 0 && manifest.dynamic) {
|
|
||||||
// The stream is live, so return a position a position offset from the live edge.
|
|
||||||
int periodIndex = window.endPeriodIndex;
|
|
||||||
long liveEdgeOffsetForManifest = liveEdgeOffsetMs;
|
|
||||||
if (liveEdgeOffsetForManifest == DEFAULT_LIVE_EDGE_OFFSET_PREFER_MANIFEST_MS) {
|
|
||||||
liveEdgeOffsetForManifest = manifest.suggestedPresentationDelay != -1
|
|
||||||
? manifest.suggestedPresentationDelay : DEFAULT_LIVE_EDGE_OFFSET_FIXED_MS;
|
|
||||||
}
|
|
||||||
long positionMs = window.endTimeMs - liveEdgeOffsetForManifest;
|
|
||||||
while (positionMs < 0 && periodIndex > window.startPeriodIndex) {
|
|
||||||
periodIndex--;
|
|
||||||
positionMs += manifest.getPeriodDurationMs(periodIndex);
|
|
||||||
}
|
|
||||||
positionMs = Math.max(positionMs,
|
|
||||||
periodIndex == window.startPeriodIndex ? window.startTimeMs : 0);
|
|
||||||
return new Position(periodIndex, positionMs * 1000);
|
|
||||||
}
|
|
||||||
return new Position(index, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void maybeThrowSourceInfoRefreshError() throws IOException {
|
public void maybeThrowSourceInfoRefreshError() throws IOException {
|
||||||
loader.maybeThrowError();
|
loader.maybeThrowError();
|
||||||
@ -405,8 +379,27 @@ public final class DashMediaSource implements MediaSource {
|
|||||||
for (int i = 0; i < manifest.getPeriodCount() - 1; i++) {
|
for (int i = 0; i < manifest.getPeriodCount() - 1; i++) {
|
||||||
windowDurationUs += manifest.getPeriodDurationUs(i);
|
windowDurationUs += manifest.getPeriodDurationUs(i);
|
||||||
}
|
}
|
||||||
|
int defaultInitialPeriodIndex = 0;
|
||||||
|
long defaultInitialTimeUs = 0;
|
||||||
|
if (manifest.dynamic) {
|
||||||
|
defaultInitialPeriodIndex = lastPeriodIndex;
|
||||||
|
long liveEdgeOffsetForManifestMs = liveEdgeOffsetMs;
|
||||||
|
if (liveEdgeOffsetForManifestMs == DEFAULT_LIVE_EDGE_OFFSET_PREFER_MANIFEST_MS) {
|
||||||
|
liveEdgeOffsetForManifestMs = manifest.suggestedPresentationDelay != -1
|
||||||
|
? manifest.suggestedPresentationDelay : DEFAULT_LIVE_EDGE_OFFSET_FIXED_MS;
|
||||||
|
}
|
||||||
|
defaultInitialTimeUs = currentEndTimeUs - (liveEdgeOffsetForManifestMs * 1000);
|
||||||
|
while (defaultInitialTimeUs < 0 && defaultInitialPeriodIndex > 0) {
|
||||||
|
defaultInitialPeriodIndex--;
|
||||||
|
defaultInitialTimeUs += manifest.getPeriodDurationUs(defaultInitialPeriodIndex);
|
||||||
|
}
|
||||||
|
if (defaultInitialPeriodIndex == 0) {
|
||||||
|
defaultInitialTimeUs = Math.max(defaultInitialTimeUs, currentStartTimeUs);
|
||||||
|
}
|
||||||
|
}
|
||||||
window = Window.createWindow(0, currentStartTimeUs, lastPeriodIndex, currentEndTimeUs,
|
window = Window.createWindow(0, currentStartTimeUs, lastPeriodIndex, currentEndTimeUs,
|
||||||
windowDurationUs, true /* isSeekable */, manifest.dynamic);
|
windowDurationUs, true /* isSeekable */, manifest.dynamic, defaultInitialPeriodIndex,
|
||||||
|
defaultInitialTimeUs);
|
||||||
sourceListener.onSourceInfoRefreshed(new DashTimeline(firstPeriodId, manifest, window),
|
sourceListener.onSourceInfoRefreshed(new DashTimeline(firstPeriodId, manifest, window),
|
||||||
manifest);
|
manifest);
|
||||||
}
|
}
|
||||||
|
@ -73,12 +73,6 @@ public final class HlsMediaSource implements MediaSource {
|
|||||||
return oldPlayingPeriodIndex;
|
return oldPlayingPeriodIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Position getDefaultStartPosition(int index) {
|
|
||||||
// TODO: Return the position of the live edge, if applicable.
|
|
||||||
return Position.DEFAULT;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void maybeThrowSourceInfoRefreshError() {
|
public void maybeThrowSourceInfoRefreshError() {
|
||||||
// Do nothing.
|
// Do nothing.
|
||||||
|
@ -52,7 +52,7 @@ public final class SsMediaSource implements MediaSource,
|
|||||||
public static final int DEFAULT_MIN_LOADABLE_RETRY_COUNT = 3;
|
public static final int DEFAULT_MIN_LOADABLE_RETRY_COUNT = 3;
|
||||||
/**
|
/**
|
||||||
* A default live edge offset (the offset subtracted from the live edge when calculating the
|
* A default live edge offset (the offset subtracted from the live edge when calculating the
|
||||||
* default position returned by {@link #getDefaultStartPosition(int)}).
|
* default initial playback position.
|
||||||
*/
|
*/
|
||||||
public static final long DEFAULT_LIVE_EDGE_OFFSET_MS = 30000;
|
public static final long DEFAULT_LIVE_EDGE_OFFSET_MS = 30000;
|
||||||
|
|
||||||
@ -73,7 +73,6 @@ public final class SsMediaSource implements MediaSource,
|
|||||||
|
|
||||||
private long manifestLoadStartTimestamp;
|
private long manifestLoadStartTimestamp;
|
||||||
private SsManifest manifest;
|
private SsManifest manifest;
|
||||||
private Window window;
|
|
||||||
|
|
||||||
private Handler manifestRefreshHandler;
|
private Handler manifestRefreshHandler;
|
||||||
|
|
||||||
@ -114,19 +113,6 @@ public final class SsMediaSource implements MediaSource,
|
|||||||
return oldPlayingPeriodIndex;
|
return oldPlayingPeriodIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Position getDefaultStartPosition(int index) {
|
|
||||||
if (window == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
if (manifest.isLive) {
|
|
||||||
long startPositionUs = Math.max(window.startTimeMs,
|
|
||||||
window.endTimeMs - liveEdgeOffsetMs) * 1000;
|
|
||||||
return new Position(0, startPositionUs);
|
|
||||||
}
|
|
||||||
return Position.DEFAULT;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void maybeThrowSourceInfoRefreshError() throws IOException {
|
public void maybeThrowSourceInfoRefreshError() throws IOException {
|
||||||
manifestLoader.maybeThrowError();
|
manifestLoader.maybeThrowError();
|
||||||
@ -196,15 +182,16 @@ public final class SsMediaSource implements MediaSource,
|
|||||||
startTimeUs = Math.max(startTimeUs, endTimeUs - manifest.dvrWindowLengthUs);
|
startTimeUs = Math.max(startTimeUs, endTimeUs - manifest.dvrWindowLengthUs);
|
||||||
}
|
}
|
||||||
long durationUs = endTimeUs - startTimeUs;
|
long durationUs = endTimeUs - startTimeUs;
|
||||||
|
long defaultInitialStartPositionUs = Math.max(startTimeUs,
|
||||||
|
endTimeUs - (liveEdgeOffsetMs * 1000));
|
||||||
Window window = Window.createWindow(0, startTimeUs, 0, endTimeUs, durationUs,
|
Window window = Window.createWindow(0, startTimeUs, 0, endTimeUs, durationUs,
|
||||||
true /* isSeekable */, true /* isDynamic */);
|
true /* isSeekable */, true /* isDynamic */, 0, defaultInitialStartPositionUs);
|
||||||
timeline = new SinglePeriodTimeline(endTimeUs, window);
|
timeline = new SinglePeriodTimeline(endTimeUs, window);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
boolean isSeekable = manifest.durationUs != C.UNSET_TIME_US;
|
boolean isSeekable = manifest.durationUs != C.UNSET_TIME_US;
|
||||||
timeline = new SinglePeriodTimeline(manifest.durationUs, isSeekable);
|
timeline = new SinglePeriodTimeline(manifest.durationUs, isSeekable);
|
||||||
}
|
}
|
||||||
window = timeline.getWindow(0);
|
|
||||||
sourceListener.onSourceInfoRefreshed(timeline, manifest);
|
sourceListener.onSourceInfoRefreshed(timeline, manifest);
|
||||||
scheduleManifestRefresh();
|
scheduleManifestRefresh();
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user