Commit f4e7af3f by tonihei Committed by Oliver Woodman

Handle duration change in updateQueuedPeriods.

We can keep the reading media period and continue playing if we haven't read
beyond the new duration. Otherwise, we can keep the period, but need to reset
the renderers as we already read too far.

PiperOrigin-RevId: 231406252
parent d49e7eba
...@@ -1376,12 +1376,34 @@ import java.util.concurrent.atomic.AtomicBoolean; ...@@ -1376,12 +1376,34 @@ import java.util.concurrent.atomic.AtomicBoolean;
} }
} }
if (!queue.updateQueuedPeriods(rendererPositionUs)) { if (!queue.updateQueuedPeriods(rendererPositionUs, getMaxRendererReadPositionUs())) {
seekToCurrentPosition(/* sendDiscontinuity= */ false); seekToCurrentPosition(/* sendDiscontinuity= */ false);
} }
handleLoadingMediaPeriodChanged(/* loadingTrackSelectionChanged= */ false); handleLoadingMediaPeriodChanged(/* loadingTrackSelectionChanged= */ false);
} }
private long getMaxRendererReadPositionUs() {
MediaPeriodHolder readingHolder = queue.getReadingPeriod();
if (readingHolder == null) {
return 0;
}
long maxReadPositionUs = readingHolder.getRendererOffset();
for (int i = 0; i < renderers.length; i++) {
if (renderers[i].getState() == Renderer.STATE_DISABLED
|| renderers[i].getStream() != readingHolder.sampleStreams[i]) {
// Ignore disabled renderers and renderers with sample streams from previous periods.
continue;
}
long readingPositionUs = renderers[i].getReadingPositionUs();
if (readingPositionUs == C.TIME_END_OF_SOURCE) {
return C.TIME_END_OF_SOURCE;
} else {
maxReadPositionUs = Math.max(readingPositionUs, maxReadPositionUs);
}
}
return maxReadPositionUs;
}
private void handleSourceInfoRefreshEndedPlayback() { private void handleSourceInfoRefreshEndedPlayback() {
setState(Player.STATE_ENDED); setState(Player.STATE_ENDED);
// Reset, but retain the source so that it can still be used should a seek occur. // Reset, but retain the source so that it can still be used should a seek occur.
......
...@@ -61,8 +61,8 @@ import com.google.android.exoplayer2.util.Assertions; ...@@ -61,8 +61,8 @@ import com.google.android.exoplayer2.util.Assertions;
} }
/** /**
* Sets the {@link Timeline}. Call {@link #updateQueuedPeriods(long)} to update the queued media * Sets the {@link Timeline}. Call {@link #updateQueuedPeriods(long, long)} to update the queued
* periods to take into account the new timeline. * media periods to take into account the new timeline.
*/ */
public void setTimeline(Timeline timeline) { public void setTimeline(Timeline timeline) {
this.timeline = timeline; this.timeline = timeline;
...@@ -293,9 +293,12 @@ import com.google.android.exoplayer2.util.Assertions; ...@@ -293,9 +293,12 @@ import com.google.android.exoplayer2.util.Assertions;
* consistent with the new timeline. * consistent with the new timeline.
* *
* @param rendererPositionUs The current renderer position in microseconds. * @param rendererPositionUs The current renderer position in microseconds.
* @param maxRendererReadPositionUs The maximum renderer position up to which renderers have read
* the current reading media period in microseconds, or {@link C#TIME_END_OF_SOURCE} if they
* have read to the end.
* @return Whether the timeline change has been handled completely. * @return Whether the timeline change has been handled completely.
*/ */
public boolean updateQueuedPeriods(long rendererPositionUs) { public boolean updateQueuedPeriods(long rendererPositionUs, long maxRendererReadPositionUs) {
// TODO: Merge this into setTimeline so that the queue gets updated as soon as the new timeline // TODO: Merge this into setTimeline so that the queue gets updated as soon as the new timeline
// is set, once all cases handled by ExoPlayerImplInternal.handleSourceInfoRefreshed can be // is set, once all cases handled by ExoPlayerImplInternal.handleSourceInfoRefreshed can be
// handled here. // handled here.
...@@ -327,8 +330,18 @@ import com.google.android.exoplayer2.util.Assertions; ...@@ -327,8 +330,18 @@ import com.google.android.exoplayer2.util.Assertions;
periodHolder.info = newPeriodInfo.copyWithContentPositionUs(oldPeriodInfo.contentPositionUs); periodHolder.info = newPeriodInfo.copyWithContentPositionUs(oldPeriodInfo.contentPositionUs);
if (!areDurationsCompatible(oldPeriodInfo.durationUs, newPeriodInfo.durationUs)) { if (!areDurationsCompatible(oldPeriodInfo.durationUs, newPeriodInfo.durationUs)) {
// The period duration changed. Remove all subsequent periods. // The period duration changed. Remove all subsequent periods and check whether we read
return !removeAfter(periodHolder); // beyond the new duration.
long newDurationInRendererTime =
newPeriodInfo.durationUs == C.TIME_UNSET
? Long.MAX_VALUE
: periodHolder.toRendererTime(newPeriodInfo.durationUs);
boolean isReadingAndReadBeyondNewDuration =
periodHolder == reading
&& (maxRendererReadPositionUs == C.TIME_END_OF_SOURCE
|| maxRendererReadPositionUs >= newDurationInRendererTime);
boolean readingPeriodRemoved = removeAfter(periodHolder);
return !readingPeriodRemoved && !isReadingAndReadBeyondNewDuration;
} }
previousPeriodHolder = periodHolder; previousPeriodHolder = periodHolder;
......
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