Commit 5296d5b1 by andrewlewis Committed by Oliver Woodman

Move isFinal flag to the Window.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=130503190
parent 671a15ba
......@@ -87,11 +87,10 @@ import java.util.Locale;
@Override
public void onSourceInfoRefreshed(Timeline timeline, Object manifest) {
boolean isFinal = timeline.isFinal();
int periodCount = timeline.getPeriodCount();
int windowCount = timeline.getWindowCount();
Log.d(TAG, "sourceInfo[isFinal=" + isFinal + ", startTime=" + timeline.getAbsoluteStartTime()
+ ", periodCount=" + periodCount + ", windows: " + windowCount);
Log.d(TAG, "sourceInfo[startTime=" + timeline.getAbsoluteStartTime() + ", periodCount="
+ periodCount + ", windows: " + windowCount);
for (int windowIndex = 0; windowIndex < windowCount; windowIndex++) {
Log.d(TAG, " " + timeline.getWindow(windowIndex));
}
......
......@@ -42,6 +42,7 @@ import com.google.android.exoplayer2.ExoPlayer;
import com.google.android.exoplayer2.ExoPlayerFactory;
import com.google.android.exoplayer2.SimpleExoPlayer;
import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.Window;
import com.google.android.exoplayer2.drm.DrmSessionManager;
import com.google.android.exoplayer2.drm.HttpMediaDrmCallback;
import com.google.android.exoplayer2.drm.StreamingDrmSessionManager;
......@@ -371,8 +372,14 @@ public class PlayerActivity extends Activity implements OnKeyListener, OnTouchLi
debugViewHelper = null;
playerPeriodIndex = player.getCurrentPeriodIndex();
playerPosition = player.getCurrentPosition();
shouldRestorePosition = false;
Timeline playerTimeline = player.getCurrentTimeline();
shouldRestorePosition = playerTimeline != null && playerTimeline.isFinal();
if (playerTimeline != null) {
Window window = playerTimeline.getWindow(playerPeriodIndex);
if (window.isSeekable && !window.isDynamic) {
shouldRestorePosition = true;
}
}
player.release();
player = null;
trackSelector = null;
......
......@@ -829,11 +829,9 @@ import java.io.IOException;
return;
}
// The playing period is also in the new timeline. Update index and isLast on each loaded
// period until a period is found that has changed.
int periodCount = timeline.getPeriodCount();
playingPeriod.index = index;
playingPeriod.isLast = timeline.isFinal() && index == periodCount - 1;
// The playing period is also in the new timeline. Update the index for each loaded period
// until a period is found that does not match the old timeline.
playingPeriod.setIndex(timeline, index);
Period previousPeriod = playingPeriod;
boolean seenReadingPeriod = false;
......@@ -864,8 +862,7 @@ import java.io.IOException;
}
bufferAheadPeriodCount++;
period.index = index;
period.isLast = timeline.isFinal() && index == periodCount - 1;
period.setIndex(timeline, index);
if (period == readingPeriod) {
seenReadingPeriod = true;
}
......@@ -879,9 +876,7 @@ import java.io.IOException;
loadingPeriod = null;
bufferAheadPeriodCount = 0;
} else {
int periodCount = timeline.getPeriodCount();
loadingPeriod.index = index;
loadingPeriod.isLast = timeline.isFinal() && index == periodCount - 1;
loadingPeriod.setIndex(timeline, index);
}
}
......@@ -932,8 +927,8 @@ import java.io.IOException;
MediaPeriod mediaPeriod = mediaSource.createPeriod(periodIndex, this,
loadControl.getAllocator(), startPositionUs);
Period newPeriod = new Period(renderers, rendererCapabilities, trackSelector, mediaSource,
mediaPeriod, timeline.getPeriodId(periodIndex), periodIndex, startPositionUs);
newPeriod.isLast = timeline.isFinal() && periodIndex == timeline.getPeriodCount() - 1;
mediaPeriod, timeline.getPeriodId(periodIndex), startPositionUs);
newPeriod.setIndex(timeline, periodIndex);
if (loadingPeriod != null) {
loadingPeriod.setNextPeriod(newPeriod);
newPeriod.offsetUs = loadingPeriod.offsetUs
......@@ -1177,7 +1172,7 @@ import java.io.IOException;
public Period(Renderer[] renderers, RendererCapabilities[] rendererCapabilities,
TrackSelector trackSelector, MediaSource mediaSource, MediaPeriod mediaPeriod, Object id,
int index, long positionUs) {
long positionUs) {
this.renderers = renderers;
this.rendererCapabilities = rendererCapabilities;
this.trackSelector = trackSelector;
......@@ -1187,13 +1182,17 @@ import java.io.IOException;
sampleStreams = new SampleStream[renderers.length];
mayRetainStreamFlags = new boolean[renderers.length];
startPositionUs = positionUs;
this.index = index;
}
public void setNextPeriod(Period nextPeriod) {
this.nextPeriod = nextPeriod;
}
public void setIndex(Timeline timeline, int index) {
this.index = index;
isLast = index == timeline.getPeriodCount() - 1 && !timeline.getPeriodWindow(index).isDynamic;
}
public boolean isFullyBuffered() {
return prepared
&& (!hasEnabledTracks || mediaPeriod.getBufferedPositionUs() == C.END_OF_SOURCE_US);
......
......@@ -32,11 +32,6 @@ public interface Timeline {
int getPeriodCount();
/**
* Returns whether the timeline is final, which means it will not change.
*/
boolean isFinal();
/**
* Returns the absolute start time of the timeline in milliseconds.
*/
long getAbsoluteStartTime();
......@@ -70,6 +65,14 @@ public interface Timeline {
Object getPeriodId(int periodIndex);
/**
* Returns the {@link Window} to which the period with the specified index belongs.
*
* @param periodIndex The period index.
* @return The corresponding window.
*/
Window getPeriodWindow(int periodIndex);
/**
* Returns the index of the window to which the period with the specified index belongs.
*
* @param periodIndex The period index.
......
......@@ -26,9 +26,11 @@ public final class Window {
*
* @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 createWindowFromZero(long durationUs, boolean isSeekable) {
return createWindow(0, 0, 0, durationUs, durationUs, isSeekable);
public static Window createWindowFromZero(long durationUs, boolean isSeekable,
boolean isDynamic) {
return createWindow(0, 0, 0, durationUs, durationUs, isSeekable, isDynamic);
}
/**
......@@ -42,13 +44,14 @@ public final class Window {
* 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) {
int endPeriodIndex, long endTimeUs, long durationUs, boolean isSeekable, boolean isDynamic) {
return new Window(startPeriodIndex, startTimeUs / 1000, endPeriodIndex,
endTimeUs == C.UNSET_TIME_US ? ExoPlayer.UNKNOWN_TIME : (endTimeUs / 1000),
durationUs == C.UNSET_TIME_US ? ExoPlayer.UNKNOWN_TIME : (durationUs / 1000),
isSeekable);
isSeekable, isDynamic);
}
/**
......@@ -77,15 +80,20 @@ public final class Window {
* Whether it's possible to seek within the window.
*/
public final boolean isSeekable;
/**
* Whether this seek window may change when the timeline is updated.
*/
public final boolean isDynamic;
private Window(int startPeriodIndex, long startTimeMs, int endPeriodIndex, long endTimeMs,
long durationMs, boolean isSeekable) {
long durationMs, boolean isSeekable, boolean isDynamic) {
this.startPeriodIndex = startPeriodIndex;
this.startTimeMs = startTimeMs;
this.endPeriodIndex = endPeriodIndex;
this.endTimeMs = endTimeMs;
this.durationMs = durationMs;
this.isSeekable = isSeekable;
this.isDynamic = isDynamic;
}
/**
......@@ -97,7 +105,7 @@ public final class Window {
*/
public Window copyOffsetByPeriodCount(int periodCount) {
return new Window(startPeriodIndex + periodCount, startTimeMs, endPeriodIndex + periodCount,
endTimeMs, durationMs, isSeekable);
endTimeMs, durationMs, isSeekable, isDynamic);
}
@Override
......@@ -107,6 +115,7 @@ public final class Window {
result = 31 * result + (int) startTimeMs;
result = 31 * result + endPeriodIndex;
result = 31 * result + (int) endTimeMs;
result = 31 * result + (isDynamic ? 1 : 2);
return result;
}
......@@ -124,13 +133,14 @@ public final class Window {
&& other.endPeriodIndex == endPeriodIndex
&& other.endTimeMs == endTimeMs
&& other.durationMs == durationMs
&& other.isSeekable == isSeekable;
&& other.isSeekable == isSeekable
&& other.isDynamic == isDynamic;
}
@Override
public String toString() {
return "Window[" + startPeriodIndex + ", " + startTimeMs + ", " + endPeriodIndex + ", "
+ endTimeMs + "]";
+ endTimeMs + ", " + isDynamic + "]";
}
}
......@@ -55,7 +55,7 @@ public interface SeekMap {
}
/**
* Whether or not the seeking is supported.
* Returns whether seeking is supported.
* <p>
* If seeking is not supported then the only valid seek position is the start of the file, and so
* {@link #getPosition(long)} will return 0 for all input values.
......
......@@ -130,13 +130,11 @@ public final class ConcatenatingMediaSource implements MediaSource {
private static final class ConcatenatedTimeline implements Timeline {
private final Timeline[] timelines;
private final boolean isFinal;
private final int[] sourcePeriodOffsets;
private final int[] sourceWindowOffsets;
private final Window[] windows;
public ConcatenatedTimeline(Timeline[] timelines) {
boolean isFinal = true;
int[] sourcePeriodOffsets = new int[timelines.length];
int[] sourceWindowOffsets = new int[timelines.length];
int periodCount = 0;
......@@ -144,7 +142,6 @@ public final class ConcatenatingMediaSource implements MediaSource {
ArrayList<Window> concatenatedWindows = new ArrayList<>();
for (int i = 0; i < timelines.length; i++) {
Timeline timeline = timelines[i];
isFinal &= timeline.isFinal();
// Offset the windows so they are relative to the source.
int sourceWindowCount = timeline.getWindowCount();
for (int j = 0; j < sourceWindowCount; j++) {
......@@ -157,18 +154,12 @@ public final class ConcatenatingMediaSource implements MediaSource {
sourceWindowOffsets[i] = windowCount;
}
this.timelines = timelines;
this.isFinal = isFinal;
this.sourcePeriodOffsets = sourcePeriodOffsets;
this.sourceWindowOffsets = sourceWindowOffsets;
windows = concatenatedWindows.toArray(new Window[concatenatedWindows.size()]);
}
@Override
public boolean isFinal() {
return isFinal;
}
@Override
public long getAbsoluteStartTime() {
return timelines[0].getAbsoluteStartTime();
}
......@@ -201,6 +192,11 @@ public final class ConcatenatingMediaSource implements MediaSource {
}
@Override
public Window getPeriodWindow(int periodIndex) {
return windows[getPeriodWindowIndex(periodIndex)];
}
@Override
public int getPeriodWindowIndex(int periodIndex) {
int sourceIndex = getSourceIndexForPeriod(periodIndex);
int firstPeriodIndexInSource = getFirstPeriodIndexInSource(periodIndex);
......
......@@ -36,8 +36,8 @@ import java.io.IOException;
* If the possible input stream container formats are known, pass a factory that instantiates
* extractors for them to the constructor. Otherwise, pass a {@link DefaultExtractorsFactory} to
* use the default extractors. When reading a new stream, the first {@link Extractor} in the array
* of extractors created by the factory that returns {@code true} from
* {@link Extractor#sniff(ExtractorInput)} will be used to extract samples from the input stream.
* of extractors created by the factory that returns {@code true} from {@link Extractor#sniff} will
* be used to extract samples from the input stream.
* <p>
* Note that the built-in extractors for AAC, MPEG PS/TS and FLV streams do not support seeking.
*/
......@@ -177,10 +177,13 @@ public final class ExtractorMediaSource implements MediaSource, MediaSource.List
@Override
public void onSourceInfoRefreshed(Timeline timeline, Object manifest) {
if (!this.timeline.isFinal() || timeline.getPeriodDurationUs(0) != C.UNSET_TIME_US) {
this.timeline = timeline;
sourceListener.onSourceInfoRefreshed(timeline, null);
if (this.timeline.getPeriodDurationUs(0) != C.UNSET_TIME_US
&& timeline.getPeriodDurationUs(0) == C.UNSET_TIME_US) {
// Suppress source info changes that would make the duration unknown when it is already known.
return;
}
this.timeline = timeline;
sourceListener.onSourceInfoRefreshed(timeline, null);
}
}
......@@ -24,7 +24,7 @@ import java.io.IOException;
/**
* Merges multiple {@link MediaPeriod} instances.
* <p>
* The {@link MediaSource}s being merged must have final timelines and equal period counts.
* The {@link MediaSource}s being merged must have final windows and an equal number of periods.
*/
public final class MergingMediaSource implements MediaSource {
......@@ -111,7 +111,10 @@ public final class MergingMediaSource implements MediaSource {
}
private void checkConsistentTimeline(Timeline timeline) {
Assertions.checkArgument(timeline.isFinal());
int windowCount = timeline.getWindowCount();
for (int i = 0; i < windowCount; i++) {
Assertions.checkArgument(!timeline.getWindow(i).isDynamic);
}
int periodCount = timeline.getPeriodCount();
if (this.periodCount == -1) {
this.periodCount = periodCount;
......
......@@ -22,30 +22,29 @@ import com.google.android.exoplayer2.Window;
import com.google.android.exoplayer2.util.Assertions;
/**
* A {@link Timeline} consisting of a single period and window.
* A {@link Timeline} consisting of a single period and static window.
*/
public final class SinglePeriodTimeline implements Timeline {
private static final Object ID = new Object();
private final boolean isFinal;
private final long durationUs;
private final Window window;
/**
* Creates a final timeline with one period of known duration and a window extending from
* zero to its duration.
* Creates a timeline with one period of known duration and a window extending from zero to its
* duration.
*
* @param durationUs The duration of the period, in microseconds.
* @param isSeekable Whether seeking is supported within the period.
*/
public SinglePeriodTimeline(long durationUs, boolean isSeekable) {
this(durationUs, Window.createWindowFromZero(durationUs, isSeekable));
this(durationUs, Window.createWindowFromZero(durationUs, isSeekable, false /* isDynamic */));
}
/**
* Creates a final timeline with one period of known duration and a window extending from
* zero to its duration.
* Creates a timeline with one period of known duration and a window extending from zero to its
* duration.
*
* @param durationUs The duration of the period, in microseconds.
* @param window The available window within the period.
......@@ -53,12 +52,6 @@ public final class SinglePeriodTimeline implements Timeline {
public SinglePeriodTimeline(long durationUs, Window window) {
this.durationUs = durationUs;
this.window = window;
this.isFinal = true; // TODO: Remove.
}
@Override
public boolean isFinal() {
return isFinal;
}
@Override
......@@ -90,6 +83,12 @@ public final class SinglePeriodTimeline implements Timeline {
}
@Override
public Window getPeriodWindow(int periodIndex) {
Assertions.checkIndex(periodIndex, 0, 1);
return window;
}
@Override
public int getPeriodWindowIndex(int periodIndex) {
Assertions.checkIndex(periodIndex, 0, 1);
return 0;
......
......@@ -416,7 +416,7 @@ public final class DashMediaSource implements MediaSource {
windowDurationUs += manifest.getPeriodDurationUs(i);
}
window = Window.createWindow(0, currentStartTimeUs, lastPeriodIndex, currentEndTimeUs,
windowDurationUs, true);
windowDurationUs, true /* isSeekable */, manifest.dynamic);
sourceListener.onSourceInfoRefreshed(new DashTimeline(firstPeriodId, manifest, window),
manifest);
}
......@@ -515,11 +515,6 @@ public final class DashMediaSource implements MediaSource {
}
@Override
public boolean isFinal() {
return !manifest.dynamic;
}
@Override
public long getAbsoluteStartTime() {
return manifest.availabilityStartTime + manifest.getPeriod(0).startMs;
}
......@@ -547,6 +542,12 @@ public final class DashMediaSource implements MediaSource {
}
@Override
public Window getPeriodWindow(int periodIndex) {
Assertions.checkIndex(periodIndex, 0, manifest.getPeriodCount());
return window;
}
@Override
public int getPeriodWindowIndex(int periodIndex) {
Assertions.checkIndex(periodIndex, 0, manifest.getPeriodCount());
return 0;
......
......@@ -196,7 +196,8 @@ public final class SsMediaSource implements MediaSource,
startTimeUs = Math.max(startTimeUs, endTimeUs - manifest.dvrWindowLengthUs);
}
long durationUs = endTimeUs - startTimeUs;
Window window = Window.createWindow(0, startTimeUs, 0, endTimeUs, durationUs, true);
Window window = Window.createWindow(0, startTimeUs, 0, endTimeUs, durationUs,
true /* isSeekable */, true /* isDynamic */);
timeline = new SinglePeriodTimeline(endTimeUs, window);
}
} else {
......
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