diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 519541359b8..884dbe4c62e 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -25,6 +25,8 @@ ([#6019](https://github.com/google/ExoPlayer/issues/6019)). * Fix application of `maxAudioBitrate` for adaptive audio track groups ([#6006](https://github.com/google/ExoPlayer/issues/6006)). +* Fix decoding problems when seeking back after seeking beyond a mid-roll ad + ([#6009](https://github.com/google/ExoPlayer/issues/6009)). ### 2.10.2 ### diff --git a/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayerImplInternal.java b/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayerImplInternal.java index 7fbde3c7b20..a6d43528803 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayerImplInternal.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayerImplInternal.java @@ -728,13 +728,20 @@ private long seekToPeriodPosition( newPlayingPeriodHolder = queue.advancePlayingPeriod(); } - // Disable all the renderers if the period being played is changing, or if forced. - if (oldPlayingPeriodHolder != newPlayingPeriodHolder || forceDisableRenderers) { + // Disable all renderers if the period being played is changing, if the seek results in negative + // renderer timestamps, or if forced. + if (forceDisableRenderers + || oldPlayingPeriodHolder != newPlayingPeriodHolder + || (newPlayingPeriodHolder != null + && newPlayingPeriodHolder.toRendererTime(periodPositionUs) < 0)) { for (Renderer renderer : enabledRenderers) { disableRenderer(renderer); } enabledRenderers = new Renderer[0]; oldPlayingPeriodHolder = null; + if (newPlayingPeriodHolder != null) { + newPlayingPeriodHolder.setRendererOffset(/* rendererPositionOffsetUs= */ 0); + } } // Update the holders. diff --git a/library/core/src/main/java/com/google/android/exoplayer2/MediaPeriodHolder.java b/library/core/src/main/java/com/google/android/exoplayer2/MediaPeriodHolder.java index 5950bc627fd..a21afc4b51e 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/MediaPeriodHolder.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/MediaPeriodHolder.java @@ -67,8 +67,7 @@ * Creates a new holder with information required to play it as part of a timeline. * * @param rendererCapabilities The renderer capabilities. - * @param rendererPositionOffsetUs The time offset of the start of the media period to provide to - * renderers. + * @param rendererPositionOffsetUs The renderer time of the start of the period, in microseconds. * @param trackSelector The track selector. * @param allocator The allocator. * @param mediaSource The media source that produced the media period. @@ -82,7 +81,7 @@ public MediaPeriodHolder( MediaSource mediaSource, MediaPeriodInfo info) { this.rendererCapabilities = rendererCapabilities; - this.rendererPositionOffsetUs = rendererPositionOffsetUs - info.startPositionUs; + this.rendererPositionOffsetUs = rendererPositionOffsetUs; this.trackSelector = trackSelector; this.mediaSource = mediaSource; this.uid = info.id.periodUid; @@ -115,6 +114,15 @@ public long getRendererOffset() { return rendererPositionOffsetUs; } + /** + * Sets the renderer time of the start of the period, in microseconds. + * + * @param rendererPositionOffsetUs The new renderer position offset, in microseconds. + */ + public void setRendererOffset(long rendererPositionOffsetUs) { + this.rendererPositionOffsetUs = rendererPositionOffsetUs; + } + /** Returns start position of period in renderer time. */ public long getStartPositionRendererTime() { return info.startPositionUs + rendererPositionOffsetUs; diff --git a/library/core/src/main/java/com/google/android/exoplayer2/MediaPeriodQueue.java b/library/core/src/main/java/com/google/android/exoplayer2/MediaPeriodQueue.java index 58000d6f580..e47d8af3812 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/MediaPeriodQueue.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/MediaPeriodQueue.java @@ -144,8 +144,8 @@ public MediaPeriod enqueueNextMediaPeriod( MediaPeriodInfo info) { long rendererPositionOffsetUs = loading == null - ? info.startPositionUs - : (loading.getRendererOffset() + loading.info.durationUs); + ? (info.id.isAd() ? info.contentPositionUs : 0) + : (loading.getRendererOffset() + loading.info.durationUs - info.startPositionUs); MediaPeriodHolder newPeriodHolder = new MediaPeriodHolder( rendererCapabilities,