diff --git a/library/src/main/java/com/google/android/exoplayer2/ExoPlayerImpl.java b/library/src/main/java/com/google/android/exoplayer2/ExoPlayerImpl.java index 0461465672..b167597e16 100644 --- a/library/src/main/java/com/google/android/exoplayer2/ExoPlayerImpl.java +++ b/library/src/main/java/com/google/android/exoplayer2/ExoPlayerImpl.java @@ -53,7 +53,6 @@ import java.util.concurrent.CopyOnWriteArraySet; // Playback information when there is a pending seek/set source operation. private int maskingPeriodIndex; private long maskingPositionMs; - private long maskingDurationMs; /** * 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 public void seekTo(int periodIndex, long positionMs) { - boolean periodChanging = periodIndex != getCurrentPeriodIndex(); boolean seekToDefaultPosition = positionMs == ExoPlayer.UNKNOWN_TIME; maskingPeriodIndex = periodIndex; maskingPositionMs = seekToDefaultPosition ? 0 : positionMs; - maskingDurationMs = periodChanging ? ExoPlayer.UNKNOWN_TIME : getDuration(); pendingSeekAcks++; internalPlayer.seekTo(periodIndex, seekToDefaultPosition ? C.UNSET_TIME_US : positionMs * 1000); if (!seekToDefaultPosition) { @@ -184,12 +181,10 @@ import java.util.concurrent.CopyOnWriteArraySet; @Override public long getDuration() { - if (pendingSeekAcks == 0) { - long durationUs = playbackInfo.durationUs; - return durationUs == C.UNSET_TIME_US ? ExoPlayer.UNKNOWN_TIME : durationUs / 1000; - } else { - return maskingDurationMs; + if (timeline == null) { + return UNKNOWN_TIME; } + return timeline.getPeriodDurationMs(getCurrentPeriodIndex()); } @Override diff --git a/library/src/main/java/com/google/android/exoplayer2/ExoPlayerImplInternal.java b/library/src/main/java/com/google/android/exoplayer2/ExoPlayerImplInternal.java index 5c76bc63a6..5a410b78ed 100644 --- a/library/src/main/java/com/google/android/exoplayer2/ExoPlayerImplInternal.java +++ b/library/src/main/java/com/google/android/exoplayer2/ExoPlayerImplInternal.java @@ -54,12 +54,10 @@ import java.io.IOException; public volatile long positionUs; public volatile long bufferedPositionUs; - public volatile long durationUs; public volatile long startPositionUs; public PlaybackInfo(int periodIndex) { this.periodIndex = periodIndex; - durationUs = C.UNSET_TIME_US; } } @@ -394,11 +392,6 @@ import java.io.IOException; } MediaPeriod mediaPeriod = playingPeriod.mediaPeriod; - // Update the duration. - if (playbackInfo.durationUs == C.UNSET_TIME_US) { - playbackInfo.durationUs = mediaPeriod.getDurationUs(); - } - // Update the playback position. long positionUs = mediaPeriod.readDiscontinuity(); if (positionUs != C.UNSET_TIME_US) { @@ -460,9 +453,10 @@ import java.io.IOException; maybeThrowPeriodPrepareError(); } + long playingPeriodDuration = timeline.getPeriodDurationUs(playingPeriod.index); if (allRenderersEnded - && (playbackInfo.durationUs == C.UNSET_TIME_US - || playbackInfo.durationUs <= playbackInfo.positionUs) + && (playingPeriodDuration == C.UNSET_TIME_US + || playingPeriodDuration <= playbackInfo.positionUs) && isTimelineEnded) { setState(ExoPlayer.STATE_ENDED); stopRenderers(); @@ -796,7 +790,7 @@ import java.io.IOException; if (loadingPeriod.isLast) { return true; } - bufferedPositionUs = loadingPeriod.mediaPeriod.getDurationUs(); + bufferedPositionUs = timeline.getPeriodDurationUs(loadingPeriod.index); } return loadControl.shouldStartPlayback(bufferedPositionUs - positionUs, rebuffering); } @@ -945,6 +939,8 @@ import java.io.IOException; newPeriod.isLast = timeline.isFinal() && periodIndex == timeline.getPeriodCount() - 1; if (loadingPeriod != null) { loadingPeriod.setNextPeriod(newPeriod); + newPeriod.offsetUs = loadingPeriod.offsetUs + + timeline.getPeriodDurationUs(loadingPeriod.index); } bufferAheadPeriodCount++; loadingPeriod = newPeriod; @@ -967,7 +963,7 @@ import java.io.IOException; // Update the playing and reading periods. if (playingPeriodEndPositionUs == C.UNSET_TIME_US && playingPeriod.isFullyBuffered()) { playingPeriodEndPositionUs = playingPeriod.offsetUs - + playingPeriod.mediaPeriod.getDurationUs(); + + timeline.getPeriodDurationUs(playingPeriod.index); } while (playingPeriod != readingPeriod && playingPeriod.nextPeriod != null && internalPositionUs >= playingPeriod.nextPeriod.offsetUs) { @@ -1198,7 +1194,6 @@ import java.io.IOException; public void setNextPeriod(Period nextPeriod) { this.nextPeriod = nextPeriod; - nextPeriod.offsetUs = offsetUs + mediaPeriod.getDurationUs(); } public boolean isFullyBuffered() { diff --git a/library/src/main/java/com/google/android/exoplayer2/source/ConcatenatingMediaSource.java b/library/src/main/java/com/google/android/exoplayer2/source/ConcatenatingMediaSource.java index f97b99b798..6987b18d70 100644 --- a/library/src/main/java/com/google/android/exoplayer2/source/ConcatenatingMediaSource.java +++ b/library/src/main/java/com/google/android/exoplayer2/source/ConcatenatingMediaSource.java @@ -148,10 +148,17 @@ public final class ConcatenatingMediaSource implements MediaSource { } @Override - public long getPeriodDuration(int index) { + public long getPeriodDurationMs(int index) { int sourceIndex = getSourceIndexForPeriod(index); 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 diff --git a/library/src/main/java/com/google/android/exoplayer2/source/ExtractorMediaSource.java b/library/src/main/java/com/google/android/exoplayer2/source/ExtractorMediaSource.java index df9a6c9ce8..846bf8aea1 100644 --- a/library/src/main/java/com/google/android/exoplayer2/source/ExtractorMediaSource.java +++ b/library/src/main/java/com/google/android/exoplayer2/source/ExtractorMediaSource.java @@ -228,11 +228,6 @@ public final class ExtractorMediaSource implements MediaPeriod, MediaSource, maybeThrowError(); } - @Override - public long getDurationUs() { - return durationUs; - } - @Override public TrackGroupArray getTrackGroups() { return tracks; @@ -432,6 +427,9 @@ public final class ExtractorMediaSource implements MediaPeriod, MediaSource, long largestQueuedTimestampUs = getLargestQueuedTimestampUs(); durationUs = largestQueuedTimestampUs == Long.MIN_VALUE ? 0 : largestQueuedTimestampUs + DEFAULT_LAST_SAMPLE_DURATION_US; + sourceListener.onSourceInfoRefreshed(seekMap.isSeekable() + ? SinglePeriodTimeline.createSeekableFinalTimeline(this, durationUs) + : SinglePeriodTimeline.createUnseekableFinalTimeline(this, durationUs), null); } } diff --git a/library/src/main/java/com/google/android/exoplayer2/source/MediaPeriod.java b/library/src/main/java/com/google/android/exoplayer2/source/MediaPeriod.java index 422725bc8f..323d5d8864 100644 --- a/library/src/main/java/com/google/android/exoplayer2/source/MediaPeriod.java +++ b/library/src/main/java/com/google/android/exoplayer2/source/MediaPeriod.java @@ -66,19 +66,6 @@ public interface MediaPeriod extends SequenceableLoader { */ void maybeThrowPrepareError() throws IOException; - /** - * Returns the duration of the period in microseconds, or {@link C#UNSET_TIME_US} if not known. - *
- * If {@link #getBufferedPositionUs()} returns {@link C#END_OF_SOURCE_US}, the duration is - * guaranteed to be known. - *
- * 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. *
diff --git a/library/src/main/java/com/google/android/exoplayer2/source/MergingMediaPeriod.java b/library/src/main/java/com/google/android/exoplayer2/source/MergingMediaPeriod.java
index 5ba321dd54..82029dd940 100644
--- a/library/src/main/java/com/google/android/exoplayer2/source/MergingMediaPeriod.java
+++ b/library/src/main/java/com/google/android/exoplayer2/source/MergingMediaPeriod.java
@@ -32,7 +32,6 @@ public final class MergingMediaPeriod implements MediaPeriod, MediaPeriod.Callba
private Callback callback;
private int pendingChildPrepareCount;
- private long durationUs;
private TrackGroupArray trackGroups;
private MediaPeriod[] enabledPeriods;
@@ -59,11 +58,6 @@ public final class MergingMediaPeriod implements MediaPeriod, MediaPeriod.Callba
}
}
- @Override
- public long getDurationUs() {
- return durationUs;
- }
-
@Override
public TrackGroupArray getTrackGroups() {
return trackGroups;
@@ -194,15 +188,9 @@ public final class MergingMediaPeriod implements MediaPeriod, MediaPeriod.Callba
if (--pendingChildPrepareCount > 0) {
return;
}
- durationUs = 0;
int totalTrackGroupCount = 0;
for (MediaPeriod period : periods) {
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];
int trackGroupIndex = 0;
diff --git a/library/src/main/java/com/google/android/exoplayer2/source/SinglePeriodTimeline.java b/library/src/main/java/com/google/android/exoplayer2/source/SinglePeriodTimeline.java
index fa36d27b59..3e08c6ffa9 100644
--- a/library/src/main/java/com/google/android/exoplayer2/source/SinglePeriodTimeline.java
+++ b/library/src/main/java/com/google/android/exoplayer2/source/SinglePeriodTimeline.java
@@ -16,6 +16,7 @@
package com.google.android.exoplayer2.source;
import com.google.android.exoplayer2.C;
+import com.google.android.exoplayer2.ExoPlayer;
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.
*/
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.
*/
public static Timeline createSeekableFinalTimeline(Object id, long durationUs) {
- return new SinglePeriodTimeline(id, true, durationUs / 1000,
+ return new SinglePeriodTimeline(id, true, durationUs,
SeekWindow.createWindowFromZero(durationUs));
}
private final Object id;
private final boolean isFinal;
- private final long durationMs;
+ private final long durationUs;
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.isFinal = isFinal;
- this.durationMs = durationMs;
+ this.durationUs = durationUs;
this.seekWindow = seekWindow;
}
@@ -96,11 +97,19 @@ public final class SinglePeriodTimeline implements Timeline {
}
@Override
- public long getPeriodDuration(int index) {
+ public long getPeriodDurationMs(int index) {
if (index != 0) {
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
diff --git a/library/src/main/java/com/google/android/exoplayer2/source/SingleSampleMediaSource.java b/library/src/main/java/com/google/android/exoplayer2/source/SingleSampleMediaSource.java
index 1f1d0c51db..099ceb9481 100644
--- a/library/src/main/java/com/google/android/exoplayer2/source/SingleSampleMediaSource.java
+++ b/library/src/main/java/com/google/android/exoplayer2/source/SingleSampleMediaSource.java
@@ -147,11 +147,6 @@ public final class SingleSampleMediaSource implements MediaPeriod, MediaSource,
// Do nothing.
}
- @Override
- public long getDurationUs() {
- return durationUs;
- }
-
@Override
public TrackGroupArray getTrackGroups() {
return tracks;
diff --git a/library/src/main/java/com/google/android/exoplayer2/source/Timeline.java b/library/src/main/java/com/google/android/exoplayer2/source/Timeline.java
index 0b344d38d5..940e671e51 100644
--- a/library/src/main/java/com/google/android/exoplayer2/source/Timeline.java
+++ b/library/src/main/java/com/google/android/exoplayer2/source/Timeline.java
@@ -15,6 +15,7 @@
*/
package com.google.android.exoplayer2.source;
+import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.ExoPlayer;
/**
@@ -50,7 +51,16 @@ public interface Timeline {
* @param index The index of the period.
* @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
diff --git a/library/src/main/java/com/google/android/exoplayer2/source/dash/DashMediaPeriod.java b/library/src/main/java/com/google/android/exoplayer2/source/dash/DashMediaPeriod.java
index 8eee46afbf..03575037eb 100644
--- a/library/src/main/java/com/google/android/exoplayer2/source/dash/DashMediaPeriod.java
+++ b/library/src/main/java/com/google/android/exoplayer2/source/dash/DashMediaPeriod.java
@@ -54,7 +54,6 @@ import java.util.List;
private Callback callback;
private Allocator allocator;
private DashManifest manifest;
- private long durationUs;
private int index;
private Period period;
@@ -69,7 +68,6 @@ import java.util.List;
this.eventDispatcher = eventDispatcher;
this.elapsedRealtimeOffset = elapsedRealtimeOffset;
this.manifestLoaderErrorThrower = manifestLoaderErrorThrower;
- durationUs = manifest.getPeriodDurationUs(index);
period = manifest.getPeriod(index);
trackGroups = buildTrackGroups(period);
}
@@ -77,7 +75,6 @@ import java.util.List;
public void updateManifest(DashManifest manifest, int index) {
this.manifest = manifest;
this.index = index;
- durationUs = manifest.getPeriodDurationUs(index);
period = manifest.getPeriod(index);
if (sampleStreams != null) {
for (ChunkSampleStream