Move default start position into Window

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=130610236
This commit is contained in:
olly 2016-08-18 01:11:10 -07:00 committed by Oliver Woodman
parent 3e0bae616f
commit b2a28a140c
10 changed files with 111 additions and 176 deletions

View File

@ -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

View File

@ -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

View File

@ -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) {

View File

@ -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.

View File

@ -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.
*/ */

View File

@ -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) {

View File

@ -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.

View File

@ -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);
} }

View File

@ -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.

View File

@ -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();
} }