mirror of
https://github.com/samsonjs/media.git
synced 2026-04-20 13:45:47 +00:00
Move isFinal flag to the Window.
------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=130503190
This commit is contained in:
parent
671a15badf
commit
5296d5b198
12 changed files with 89 additions and 68 deletions
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -31,11 +31,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.
|
||||
*/
|
||||
|
|
@ -69,6 +64,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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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,17 +154,11 @@ 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();
|
||||
|
|
@ -200,6 +191,11 @@ public final class ConcatenatingMediaSource implements MediaSource {
|
|||
return Pair.create(sourceIndex, periodId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Window getPeriodWindow(int periodIndex) {
|
||||
return windows[getPeriodWindowIndex(periodIndex)];
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPeriodWindowIndex(int periodIndex) {
|
||||
int sourceIndex = getSourceIndexForPeriod(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
|
||||
|
|
@ -89,6 +82,12 @@ public final class SinglePeriodTimeline implements Timeline {
|
|||
return ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Window getPeriodWindow(int periodIndex) {
|
||||
Assertions.checkIndex(periodIndex, 0, 1);
|
||||
return window;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPeriodWindowIndex(int periodIndex) {
|
||||
Assertions.checkIndex(periodIndex, 0, 1);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -514,11 +514,6 @@ public final class DashMediaSource implements MediaSource {
|
|||
this.window = window;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFinal() {
|
||||
return !manifest.dynamic;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getAbsoluteStartTime() {
|
||||
return manifest.availabilityStartTime + manifest.getPeriod(0).startMs;
|
||||
|
|
@ -546,6 +541,12 @@ public final class DashMediaSource implements MediaSource {
|
|||
return firstPeriodId + Assertions.checkIndex(periodIndex, 0, manifest.getPeriodCount());
|
||||
}
|
||||
|
||||
@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());
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
Loading…
Reference in a new issue