Report duration only via Timeline

It's error prone (and more code) to report two ways

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=129999117
This commit is contained in:
olly 2016-08-11 10:06:43 -07:00 committed by Oliver Woodman
parent d8ffafea65
commit 1811b01b07
13 changed files with 58 additions and 84 deletions

View File

@ -53,7 +53,6 @@ import java.util.concurrent.CopyOnWriteArraySet;
// Playback information when there is a pending seek/set source operation. // Playback information when there is a pending seek/set source operation.
private int maskingPeriodIndex; private int maskingPeriodIndex;
private long maskingPositionMs; private long maskingPositionMs;
private long maskingDurationMs;
/** /**
* Constructs an instance. Must be called from a thread that has an associated {@link Looper}. * Constructs an instance. Must be called from a thread that has an associated {@link Looper}.
@ -142,11 +141,9 @@ import java.util.concurrent.CopyOnWriteArraySet;
@Override @Override
public void seekTo(int periodIndex, long positionMs) { public void seekTo(int periodIndex, long positionMs) {
boolean periodChanging = periodIndex != getCurrentPeriodIndex();
boolean seekToDefaultPosition = positionMs == ExoPlayer.UNKNOWN_TIME; boolean seekToDefaultPosition = positionMs == ExoPlayer.UNKNOWN_TIME;
maskingPeriodIndex = periodIndex; maskingPeriodIndex = periodIndex;
maskingPositionMs = seekToDefaultPosition ? 0 : positionMs; maskingPositionMs = seekToDefaultPosition ? 0 : positionMs;
maskingDurationMs = periodChanging ? ExoPlayer.UNKNOWN_TIME : getDuration();
pendingSeekAcks++; pendingSeekAcks++;
internalPlayer.seekTo(periodIndex, seekToDefaultPosition ? C.UNSET_TIME_US : positionMs * 1000); internalPlayer.seekTo(periodIndex, seekToDefaultPosition ? C.UNSET_TIME_US : positionMs * 1000);
if (!seekToDefaultPosition) { if (!seekToDefaultPosition) {
@ -184,12 +181,10 @@ import java.util.concurrent.CopyOnWriteArraySet;
@Override @Override
public long getDuration() { public long getDuration() {
if (pendingSeekAcks == 0) { if (timeline == null) {
long durationUs = playbackInfo.durationUs; return UNKNOWN_TIME;
return durationUs == C.UNSET_TIME_US ? ExoPlayer.UNKNOWN_TIME : durationUs / 1000;
} else {
return maskingDurationMs;
} }
return timeline.getPeriodDurationMs(getCurrentPeriodIndex());
} }
@Override @Override

View File

@ -54,12 +54,10 @@ import java.io.IOException;
public volatile long positionUs; public volatile long positionUs;
public volatile long bufferedPositionUs; public volatile long bufferedPositionUs;
public volatile long durationUs;
public volatile long startPositionUs; public volatile long startPositionUs;
public PlaybackInfo(int periodIndex) { public PlaybackInfo(int periodIndex) {
this.periodIndex = periodIndex; this.periodIndex = periodIndex;
durationUs = C.UNSET_TIME_US;
} }
} }
@ -394,11 +392,6 @@ import java.io.IOException;
} }
MediaPeriod mediaPeriod = playingPeriod.mediaPeriod; MediaPeriod mediaPeriod = playingPeriod.mediaPeriod;
// Update the duration.
if (playbackInfo.durationUs == C.UNSET_TIME_US) {
playbackInfo.durationUs = mediaPeriod.getDurationUs();
}
// Update the playback position. // Update the playback position.
long positionUs = mediaPeriod.readDiscontinuity(); long positionUs = mediaPeriod.readDiscontinuity();
if (positionUs != C.UNSET_TIME_US) { if (positionUs != C.UNSET_TIME_US) {
@ -460,9 +453,10 @@ import java.io.IOException;
maybeThrowPeriodPrepareError(); maybeThrowPeriodPrepareError();
} }
long playingPeriodDuration = timeline.getPeriodDurationUs(playingPeriod.index);
if (allRenderersEnded if (allRenderersEnded
&& (playbackInfo.durationUs == C.UNSET_TIME_US && (playingPeriodDuration == C.UNSET_TIME_US
|| playbackInfo.durationUs <= playbackInfo.positionUs) || playingPeriodDuration <= playbackInfo.positionUs)
&& isTimelineEnded) { && isTimelineEnded) {
setState(ExoPlayer.STATE_ENDED); setState(ExoPlayer.STATE_ENDED);
stopRenderers(); stopRenderers();
@ -796,7 +790,7 @@ import java.io.IOException;
if (loadingPeriod.isLast) { if (loadingPeriod.isLast) {
return true; return true;
} }
bufferedPositionUs = loadingPeriod.mediaPeriod.getDurationUs(); bufferedPositionUs = timeline.getPeriodDurationUs(loadingPeriod.index);
} }
return loadControl.shouldStartPlayback(bufferedPositionUs - positionUs, rebuffering); return loadControl.shouldStartPlayback(bufferedPositionUs - positionUs, rebuffering);
} }
@ -945,6 +939,8 @@ import java.io.IOException;
newPeriod.isLast = timeline.isFinal() && periodIndex == timeline.getPeriodCount() - 1; newPeriod.isLast = timeline.isFinal() && periodIndex == timeline.getPeriodCount() - 1;
if (loadingPeriod != null) { if (loadingPeriod != null) {
loadingPeriod.setNextPeriod(newPeriod); loadingPeriod.setNextPeriod(newPeriod);
newPeriod.offsetUs = loadingPeriod.offsetUs
+ timeline.getPeriodDurationUs(loadingPeriod.index);
} }
bufferAheadPeriodCount++; bufferAheadPeriodCount++;
loadingPeriod = newPeriod; loadingPeriod = newPeriod;
@ -967,7 +963,7 @@ import java.io.IOException;
// Update the playing and reading periods. // Update the playing and reading periods.
if (playingPeriodEndPositionUs == C.UNSET_TIME_US && playingPeriod.isFullyBuffered()) { if (playingPeriodEndPositionUs == C.UNSET_TIME_US && playingPeriod.isFullyBuffered()) {
playingPeriodEndPositionUs = playingPeriod.offsetUs playingPeriodEndPositionUs = playingPeriod.offsetUs
+ playingPeriod.mediaPeriod.getDurationUs(); + timeline.getPeriodDurationUs(playingPeriod.index);
} }
while (playingPeriod != readingPeriod && playingPeriod.nextPeriod != null while (playingPeriod != readingPeriod && playingPeriod.nextPeriod != null
&& internalPositionUs >= playingPeriod.nextPeriod.offsetUs) { && internalPositionUs >= playingPeriod.nextPeriod.offsetUs) {
@ -1198,7 +1194,6 @@ import java.io.IOException;
public void setNextPeriod(Period nextPeriod) { public void setNextPeriod(Period nextPeriod) {
this.nextPeriod = nextPeriod; this.nextPeriod = nextPeriod;
nextPeriod.offsetUs = offsetUs + mediaPeriod.getDurationUs();
} }
public boolean isFullyBuffered() { public boolean isFullyBuffered() {

View File

@ -148,10 +148,17 @@ public final class ConcatenatingMediaSource implements MediaSource {
} }
@Override @Override
public long getPeriodDuration(int index) { public long getPeriodDurationMs(int index) {
int sourceIndex = getSourceIndexForPeriod(index); int sourceIndex = getSourceIndexForPeriod(index);
int firstPeriodIndexInSource = getFirstPeriodIndexInSource(sourceIndex); int firstPeriodIndexInSource = getFirstPeriodIndexInSource(sourceIndex);
return timelines[sourceIndex].getPeriodDuration(index - firstPeriodIndexInSource); return timelines[sourceIndex].getPeriodDurationMs(index - firstPeriodIndexInSource);
}
@Override
public long getPeriodDurationUs(int index) {
int sourceIndex = getSourceIndexForPeriod(index);
int firstPeriodIndexInSource = getFirstPeriodIndexInSource(sourceIndex);
return timelines[sourceIndex].getPeriodDurationUs(index - firstPeriodIndexInSource);
} }
@Override @Override

View File

@ -228,11 +228,6 @@ public final class ExtractorMediaSource implements MediaPeriod, MediaSource,
maybeThrowError(); maybeThrowError();
} }
@Override
public long getDurationUs() {
return durationUs;
}
@Override @Override
public TrackGroupArray getTrackGroups() { public TrackGroupArray getTrackGroups() {
return tracks; return tracks;
@ -432,6 +427,9 @@ public final class ExtractorMediaSource implements MediaPeriod, MediaSource,
long largestQueuedTimestampUs = getLargestQueuedTimestampUs(); long largestQueuedTimestampUs = getLargestQueuedTimestampUs();
durationUs = largestQueuedTimestampUs == Long.MIN_VALUE ? 0 durationUs = largestQueuedTimestampUs == Long.MIN_VALUE ? 0
: largestQueuedTimestampUs + DEFAULT_LAST_SAMPLE_DURATION_US; : largestQueuedTimestampUs + DEFAULT_LAST_SAMPLE_DURATION_US;
sourceListener.onSourceInfoRefreshed(seekMap.isSeekable()
? SinglePeriodTimeline.createSeekableFinalTimeline(this, durationUs)
: SinglePeriodTimeline.createUnseekableFinalTimeline(this, durationUs), null);
} }
} }

View File

@ -66,19 +66,6 @@ public interface MediaPeriod extends SequenceableLoader {
*/ */
void maybeThrowPrepareError() throws IOException; void maybeThrowPrepareError() throws IOException;
/**
* Returns the duration of the period in microseconds, or {@link C#UNSET_TIME_US} if not known.
* <p>
* If {@link #getBufferedPositionUs()} returns {@link C#END_OF_SOURCE_US}, the duration is
* guaranteed to be known.
* <p>
* This method should only be called after the period has been prepared.
*
* @return The duration of the period in microseconds, or {@link C#UNSET_TIME_US} if the duration
* is not known.
*/
long getDurationUs();
/** /**
* Returns the {@link TrackGroup}s exposed by the period. * Returns the {@link TrackGroup}s exposed by the period.
* <p> * <p>

View File

@ -32,7 +32,6 @@ public final class MergingMediaPeriod implements MediaPeriod, MediaPeriod.Callba
private Callback callback; private Callback callback;
private int pendingChildPrepareCount; private int pendingChildPrepareCount;
private long durationUs;
private TrackGroupArray trackGroups; private TrackGroupArray trackGroups;
private MediaPeriod[] enabledPeriods; private MediaPeriod[] enabledPeriods;
@ -59,11 +58,6 @@ public final class MergingMediaPeriod implements MediaPeriod, MediaPeriod.Callba
} }
} }
@Override
public long getDurationUs() {
return durationUs;
}
@Override @Override
public TrackGroupArray getTrackGroups() { public TrackGroupArray getTrackGroups() {
return trackGroups; return trackGroups;
@ -194,15 +188,9 @@ public final class MergingMediaPeriod implements MediaPeriod, MediaPeriod.Callba
if (--pendingChildPrepareCount > 0) { if (--pendingChildPrepareCount > 0) {
return; return;
} }
durationUs = 0;
int totalTrackGroupCount = 0; int totalTrackGroupCount = 0;
for (MediaPeriod period : periods) { for (MediaPeriod period : periods) {
totalTrackGroupCount += period.getTrackGroups().length; totalTrackGroupCount += period.getTrackGroups().length;
if (durationUs != C.UNSET_TIME_US) {
long periodDurationUs = period.getDurationUs();
durationUs = periodDurationUs == C.UNSET_TIME_US
? C.UNSET_TIME_US : Math.max(durationUs, periodDurationUs);
}
} }
TrackGroup[] trackGroupArray = new TrackGroup[totalTrackGroupCount]; TrackGroup[] trackGroupArray = new TrackGroup[totalTrackGroupCount];
int trackGroupIndex = 0; int trackGroupIndex = 0;

View File

@ -16,6 +16,7 @@
package com.google.android.exoplayer2.source; package com.google.android.exoplayer2.source;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.ExoPlayer;
import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Assertions;
/** /**
@ -52,7 +53,7 @@ public final class SinglePeriodTimeline implements Timeline {
* @return A new, unseekable, final timeline with one period. * @return A new, unseekable, final timeline with one period.
*/ */
public static Timeline createUnseekableFinalTimeline(Object id, long durationUs) { public static Timeline createUnseekableFinalTimeline(Object id, long durationUs) {
return new SinglePeriodTimeline(id, true, durationUs / 1000, SeekWindow.UNSEEKABLE); return new SinglePeriodTimeline(id, true, durationUs, SeekWindow.UNSEEKABLE);
} }
/** /**
@ -64,19 +65,19 @@ public final class SinglePeriodTimeline implements Timeline {
* @return A new, seekable, final timeline with one period. * @return A new, seekable, final timeline with one period.
*/ */
public static Timeline createSeekableFinalTimeline(Object id, long durationUs) { public static Timeline createSeekableFinalTimeline(Object id, long durationUs) {
return new SinglePeriodTimeline(id, true, durationUs / 1000, return new SinglePeriodTimeline(id, true, durationUs,
SeekWindow.createWindowFromZero(durationUs)); SeekWindow.createWindowFromZero(durationUs));
} }
private final Object id; private final Object id;
private final boolean isFinal; private final boolean isFinal;
private final long durationMs; private final long durationUs;
private final SeekWindow seekWindow; private final SeekWindow seekWindow;
private SinglePeriodTimeline(Object id, boolean isFinal, long durationMs, SeekWindow seekWindow) { private SinglePeriodTimeline(Object id, boolean isFinal, long durationUs, SeekWindow seekWindow) {
this.id = Assertions.checkNotNull(id); this.id = Assertions.checkNotNull(id);
this.isFinal = isFinal; this.isFinal = isFinal;
this.durationMs = durationMs; this.durationUs = durationUs;
this.seekWindow = seekWindow; this.seekWindow = seekWindow;
} }
@ -96,11 +97,19 @@ public final class SinglePeriodTimeline implements Timeline {
} }
@Override @Override
public long getPeriodDuration(int index) { public long getPeriodDurationMs(int index) {
if (index != 0) { if (index != 0) {
throw new IndexOutOfBoundsException(); throw new IndexOutOfBoundsException();
} }
return durationMs; return durationUs == C.UNSET_TIME_US ? ExoPlayer.UNKNOWN_TIME : (durationUs / 1000);
}
@Override
public long getPeriodDurationUs(int index) {
if (index != 0) {
throw new IndexOutOfBoundsException();
}
return durationUs;
} }
@Override @Override

View File

@ -147,11 +147,6 @@ public final class SingleSampleMediaSource implements MediaPeriod, MediaSource,
// Do nothing. // Do nothing.
} }
@Override
public long getDurationUs() {
return durationUs;
}
@Override @Override
public TrackGroupArray getTrackGroups() { public TrackGroupArray getTrackGroups() {
return tracks; return tracks;

View File

@ -15,6 +15,7 @@
*/ */
package com.google.android.exoplayer2.source; package com.google.android.exoplayer2.source;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.ExoPlayer; import com.google.android.exoplayer2.ExoPlayer;
/** /**
@ -50,7 +51,16 @@ public interface Timeline {
* @param index The index of the period. * @param index The index of the period.
* @return The duration of the period in milliseconds, or {@link ExoPlayer#UNKNOWN_TIME}. * @return The duration of the period in milliseconds, or {@link ExoPlayer#UNKNOWN_TIME}.
*/ */
long getPeriodDuration(int index); long getPeriodDurationMs(int index);
/**
* Returns the duration of the period at {@code index} in the timeline, in microseconds, or
* {@link C#UNSET_TIME_US} if not known.
*
* @param index The index of the period.
* @return The duration of the period in microseconds, or {@link C#UNSET_TIME_US}.
*/
long getPeriodDurationUs(int index);
/** /**
* Returns a unique identifier for the period at {@code index}, or {@code null} if the period at * Returns a unique identifier for the period at {@code index}, or {@code null} if the period at

View File

@ -54,7 +54,6 @@ import java.util.List;
private Callback callback; private Callback callback;
private Allocator allocator; private Allocator allocator;
private DashManifest manifest; private DashManifest manifest;
private long durationUs;
private int index; private int index;
private Period period; private Period period;
@ -69,7 +68,6 @@ import java.util.List;
this.eventDispatcher = eventDispatcher; this.eventDispatcher = eventDispatcher;
this.elapsedRealtimeOffset = elapsedRealtimeOffset; this.elapsedRealtimeOffset = elapsedRealtimeOffset;
this.manifestLoaderErrorThrower = manifestLoaderErrorThrower; this.manifestLoaderErrorThrower = manifestLoaderErrorThrower;
durationUs = manifest.getPeriodDurationUs(index);
period = manifest.getPeriod(index); period = manifest.getPeriod(index);
trackGroups = buildTrackGroups(period); trackGroups = buildTrackGroups(period);
} }
@ -77,7 +75,6 @@ import java.util.List;
public void updateManifest(DashManifest manifest, int index) { public void updateManifest(DashManifest manifest, int index) {
this.manifest = manifest; this.manifest = manifest;
this.index = index; this.index = index;
durationUs = manifest.getPeriodDurationUs(index);
period = manifest.getPeriod(index); period = manifest.getPeriod(index);
if (sampleStreams != null) { if (sampleStreams != null) {
for (ChunkSampleStream<DashChunkSource> sampleStream : sampleStreams) { for (ChunkSampleStream<DashChunkSource> sampleStream : sampleStreams) {
@ -107,11 +104,6 @@ import java.util.List;
manifestLoaderErrorThrower.maybeThrowError(); manifestLoaderErrorThrower.maybeThrowError();
} }
@Override
public long getDurationUs() {
return durationUs;
}
@Override @Override
public TrackGroupArray getTrackGroups() { public TrackGroupArray getTrackGroups() {
return trackGroups; return trackGroups;

View File

@ -509,13 +509,21 @@ public final class DashMediaSource implements MediaSource {
} }
@Override @Override
public long getPeriodDuration(int index) { public long getPeriodDurationMs(int index) {
if (index < 0 || index >= manifest.getPeriodCount()) { if (index < 0 || index >= manifest.getPeriodCount()) {
throw new IndexOutOfBoundsException(); throw new IndexOutOfBoundsException();
} }
return manifest.getPeriodDurationMs(index); return manifest.getPeriodDurationMs(index);
} }
@Override
public long getPeriodDurationUs(int index) {
if (index < 0 || index >= manifest.getPeriodCount()) {
throw new IndexOutOfBoundsException();
}
return manifest.getPeriodDurationUs(index);
}
@Override @Override
public Object getPeriodId(int index) { public Object getPeriodId(int index) {
if (index < 0 || index >= manifest.getPeriodCount()) { if (index < 0 || index >= manifest.getPeriodCount()) {

View File

@ -160,11 +160,6 @@ public final class HlsMediaSource implements MediaPeriod, MediaSource,
} }
} }
@Override
public long getDurationUs() {
return durationUs;
}
@Override @Override
public TrackGroupArray getTrackGroups() { public TrackGroupArray getTrackGroups() {
return trackGroups; return trackGroups;

View File

@ -98,11 +98,6 @@ import java.util.ArrayList;
manifestLoaderErrorThrower.maybeThrowError(); manifestLoaderErrorThrower.maybeThrowError();
} }
@Override
public long getDurationUs() {
return manifest.durationUs;
}
@Override @Override
public TrackGroupArray getTrackGroups() { public TrackGroupArray getTrackGroups() {
return trackGroups; return trackGroups;