From 2086c129fcea32590a3b43e0919137c21d61cf1b Mon Sep 17 00:00:00 2001 From: olly Date: Thu, 23 Nov 2017 04:26:05 -0800 Subject: [PATCH] Suppress discontinuities that don't change the position This is mostly useful for suppressing the initial position discontinuity reported by ClippingMediaPeriod. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=176758972 --- .../android/exoplayer2/ExoPlayerTest.java | 46 ++++++++++--------- .../exoplayer2/ExoPlayerImplInternal.java | 12 +++-- .../exoplayer2/testutil/FakeMediaPeriod.java | 28 ++++++++++- 3 files changed, 59 insertions(+), 27 deletions(-) diff --git a/library/core/src/androidTest/java/com/google/android/exoplayer2/ExoPlayerTest.java b/library/core/src/androidTest/java/com/google/android/exoplayer2/ExoPlayerTest.java index 2392c32e0a..e911778992 100644 --- a/library/core/src/androidTest/java/com/google/android/exoplayer2/ExoPlayerTest.java +++ b/library/core/src/androidTest/java/com/google/android/exoplayer2/ExoPlayerTest.java @@ -343,12 +343,9 @@ public final class ExoPlayerTest extends TestCase { @Override protected FakeMediaPeriod createFakeMediaPeriod(MediaPeriodId id, TrackGroupArray trackGroupArray, Allocator allocator) { - return new FakeMediaPeriod(trackGroupArray) { - @Override - public long seekToUs(long positionUs) { - return positionUs + 10; // Adjusts the requested seek position. - } - }; + FakeMediaPeriod mediaPeriod = new FakeMediaPeriod(trackGroupArray); + mediaPeriod.setSeekToUsOffset(10); + return mediaPeriod; } }; ActionSchedule actionSchedule = new ActionSchedule.Builder("testSeekDiscontinuityAdjust") @@ -359,32 +356,39 @@ public final class ExoPlayerTest extends TestCase { Player.DISCONTINUITY_REASON_SEEK_ADJUSTMENT); } - public void testInternalDiscontinuity() throws Exception { + public void testInternalDiscontinuityAtNewPosition() throws Exception { FakeTimeline timeline = new FakeTimeline(1); FakeMediaSource mediaSource = new FakeMediaSource(timeline, null, Builder.VIDEO_FORMAT) { @Override protected FakeMediaPeriod createFakeMediaPeriod(MediaPeriodId id, TrackGroupArray trackGroupArray, Allocator allocator) { - return new FakeMediaPeriod(trackGroupArray) { - boolean discontinuityRead; - @Override - public long readDiscontinuity() { - if (!discontinuityRead) { - discontinuityRead = true; - return 10; // Return a discontinuity. - } - return C.TIME_UNSET; - } - }; + FakeMediaPeriod mediaPeriod = new FakeMediaPeriod(trackGroupArray); + mediaPeriod.setDiscontinuityPositionUs(10); + return mediaPeriod; } }; - ActionSchedule actionSchedule = new ActionSchedule.Builder("testInternalDiscontinuity") - .waitForPlaybackState(Player.STATE_READY).build(); ExoPlayerTestRunner testRunner = new ExoPlayerTestRunner.Builder().setMediaSource(mediaSource) - .setActionSchedule(actionSchedule).build().start().blockUntilEnded(TIMEOUT_MS); + .build().start().blockUntilEnded(TIMEOUT_MS); testRunner.assertPositionDiscontinuityReasonsEqual(Player.DISCONTINUITY_REASON_INTERNAL); } + public void testInternalDiscontinuityAtInitialPosition() throws Exception { + FakeTimeline timeline = new FakeTimeline(1); + FakeMediaSource mediaSource = new FakeMediaSource(timeline, null, Builder.VIDEO_FORMAT) { + @Override + protected FakeMediaPeriod createFakeMediaPeriod(MediaPeriodId id, + TrackGroupArray trackGroupArray, Allocator allocator) { + FakeMediaPeriod mediaPeriod = new FakeMediaPeriod(trackGroupArray); + mediaPeriod.setDiscontinuityPositionUs(0); + return mediaPeriod; + } + }; + ExoPlayerTestRunner testRunner = new ExoPlayerTestRunner.Builder().setMediaSource(mediaSource) + .build().start().blockUntilEnded(TIMEOUT_MS); + // If the position is unchanged we do not expect the discontinuity to be reported externally. + testRunner.assertNoPositionDiscontinuities(); + } + public void testAllActivatedTrackSelectionAreReleasedForSinglePeriod() throws Exception { Timeline timeline = new FakeTimeline(/* windowCount= */ 1); MediaSource mediaSource = 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 316735da77..69da4b1f5b 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 @@ -509,10 +509,14 @@ import java.io.IOException; long periodPositionUs = playingPeriodHolder.mediaPeriod.readDiscontinuity(); if (periodPositionUs != C.TIME_UNSET) { resetRendererPosition(periodPositionUs); - playbackInfo = playbackInfo.fromNewPosition(playbackInfo.periodId, periodPositionUs, - playbackInfo.contentPositionUs); - eventHandler.obtainMessage(MSG_POSITION_DISCONTINUITY, Player.DISCONTINUITY_REASON_INTERNAL, - 0, playbackInfo).sendToTarget(); + // A MediaPeriod may report a discontinuity at the current playback position to ensure the + // renderers are flushed. Only report the discontinuity externally if the position changed. + if (periodPositionUs != playbackInfo.positionUs) { + playbackInfo = playbackInfo.fromNewPosition(playbackInfo.periodId, periodPositionUs, + playbackInfo.contentPositionUs); + eventHandler.obtainMessage(MSG_POSITION_DISCONTINUITY, Player.DISCONTINUITY_REASON_INTERNAL, + 0, playbackInfo).sendToTarget(); + } } else { rendererPositionUs = mediaClock.syncAndGetPositionUs(); periodPositionUs = playingPeriodHolder.toPeriodTime(rendererPositionUs); diff --git a/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeMediaPeriod.java b/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeMediaPeriod.java index 153a427bbd..0b409f5348 100644 --- a/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeMediaPeriod.java +++ b/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeMediaPeriod.java @@ -33,9 +33,31 @@ public class FakeMediaPeriod implements MediaPeriod { private final TrackGroupArray trackGroupArray; private boolean preparedPeriod; + private long seekOffsetUs; + private long discontinuityPositionUs; public FakeMediaPeriod(TrackGroupArray trackGroupArray) { this.trackGroupArray = trackGroupArray; + discontinuityPositionUs = C.TIME_UNSET; + } + + /** + * Sets a discontinuity position to be returned from the next call to + * {@link #readDiscontinuity()}. + * + * @param discontinuityPositionUs The position to be returned, in microseconds. + */ + public void setDiscontinuityPositionUs(long discontinuityPositionUs) { + this.discontinuityPositionUs = discontinuityPositionUs; + } + + /** + * Sets an offset to be applied to positions returned by {@link #seekToUs(long)}. + * + * @param seekOffsetUs The offset to be applied, in microseconds. + */ + public void setSeekToUsOffset(long seekOffsetUs) { + this.seekOffsetUs = seekOffsetUs; } public void release() { @@ -92,7 +114,9 @@ public class FakeMediaPeriod implements MediaPeriod { @Override public long readDiscontinuity() { Assert.assertTrue(preparedPeriod); - return C.TIME_UNSET; + long positionDiscontinuityUs = this.discontinuityPositionUs; + this.discontinuityPositionUs = C.TIME_UNSET; + return positionDiscontinuityUs; } @Override @@ -104,7 +128,7 @@ public class FakeMediaPeriod implements MediaPeriod { @Override public long seekToUs(long positionUs) { Assert.assertTrue(preparedPeriod); - return positionUs; + return positionUs + seekOffsetUs; } @Override