From 0ee8c07fe5ad94e38621f4ffcf9d11930b87a9f5 Mon Sep 17 00:00:00 2001 From: Oliver Woodman Date: Thu, 18 Jun 2015 14:21:32 +0100 Subject: [PATCH] Better handle duration + disabled renderers - Fix bug where duration of initially disabled tracks wasn't correctly incorporated into the overall duration reported by the player. - Don't transition to STATE_ENDED unless the position has reached the duration, if the duration is known. This allows for "playback" to continue when all renderers are disabled, rather than jumping straight to STATE_ENDED. --- .../exoplayer/ExoPlayerImplInternal.java | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/library/src/main/java/com/google/android/exoplayer/ExoPlayerImplInternal.java b/library/src/main/java/com/google/android/exoplayer/ExoPlayerImplInternal.java index 943c5f53b1..d828b8275c 100644 --- a/library/src/main/java/com/google/android/exoplayer/ExoPlayerImplInternal.java +++ b/library/src/main/java/com/google/android/exoplayer/ExoPlayerImplInternal.java @@ -278,15 +278,11 @@ import java.util.List; } long durationUs = 0; - boolean isEnded = true; + boolean allRenderersEnded = true; boolean allRenderersReadyOrEnded = true; for (int i = 0; i < renderers.length; i++) { TrackRenderer renderer = renderers[i]; - if (rendererEnabledFlags[i] && renderer.getState() == TrackRenderer.STATE_PREPARED) { - renderer.enable(positionUs, false); - enabledRenderers.add(renderer); - isEnded = isEnded && renderer.isEnded(); - allRenderersReadyOrEnded = allRenderersReadyOrEnded && rendererReadyOrEnded(renderer); + if (renderer.getState() == TrackRenderer.STATE_PREPARED) { if (durationUs == TrackRenderer.UNKNOWN_TIME_US) { // We've already encountered a track for which the duration is unknown, so the media // duration is unknown regardless of the duration of this track. @@ -300,11 +296,18 @@ import java.util.List; durationUs = Math.max(durationUs, trackDurationUs); } } + if (rendererEnabledFlags[i]) { + renderer.enable(positionUs, false); + enabledRenderers.add(renderer); + allRenderersEnded = allRenderersEnded && renderer.isEnded(); + allRenderersReadyOrEnded = allRenderersReadyOrEnded && rendererReadyOrEnded(renderer); + } } } this.durationUs = durationUs; - if (isEnded) { + if (allRenderersEnded + && (durationUs == TrackRenderer.UNKNOWN_TIME_US || durationUs <= positionUs)) { // We don't expect this case, but handle it anyway. setState(ExoPlayer.STATE_ENDED); } else { @@ -390,7 +393,7 @@ import java.util.List; long operationStartTimeMs = SystemClock.elapsedRealtime(); long bufferedPositionUs = durationUs != TrackRenderer.UNKNOWN_TIME_US ? durationUs : Long.MAX_VALUE; - boolean isEnded = true; + boolean allRenderersEnded = true; boolean allRenderersReadyOrEnded = true; updatePositionUs(); for (int i = 0; i < enabledRenderers.size(); i++) { @@ -399,7 +402,7 @@ import java.util.List; // invoked again. The minimum of these values should then be used as the delay before the next // invocation of this method. renderer.doSomeWork(positionUs, elapsedRealtimeUs); - isEnded = isEnded && renderer.isEnded(); + allRenderersEnded = allRenderersEnded && renderer.isEnded(); allRenderersReadyOrEnded = allRenderersReadyOrEnded && rendererReadyOrEnded(renderer); if (bufferedPositionUs == TrackRenderer.UNKNOWN_TIME_US) { @@ -422,7 +425,8 @@ import java.util.List; } this.bufferedPositionUs = bufferedPositionUs; - if (isEnded) { + if (allRenderersEnded + && (durationUs == TrackRenderer.UNKNOWN_TIME_US || durationUs <= positionUs)) { setState(ExoPlayer.STATE_ENDED); stopRenderers(); } else if (state == ExoPlayer.STATE_BUFFERING && allRenderersReadyOrEnded) {