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
This commit is contained in:
olly 2017-11-23 04:26:05 -08:00 committed by Oliver Woodman
parent ba5f35995f
commit 2086c129fc
3 changed files with 59 additions and 27 deletions

View File

@ -343,12 +343,9 @@ public final class ExoPlayerTest extends TestCase {
@Override @Override
protected FakeMediaPeriod createFakeMediaPeriod(MediaPeriodId id, protected FakeMediaPeriod createFakeMediaPeriod(MediaPeriodId id,
TrackGroupArray trackGroupArray, Allocator allocator) { TrackGroupArray trackGroupArray, Allocator allocator) {
return new FakeMediaPeriod(trackGroupArray) { FakeMediaPeriod mediaPeriod = new FakeMediaPeriod(trackGroupArray);
@Override mediaPeriod.setSeekToUsOffset(10);
public long seekToUs(long positionUs) { return mediaPeriod;
return positionUs + 10; // Adjusts the requested seek position.
}
};
} }
}; };
ActionSchedule actionSchedule = new ActionSchedule.Builder("testSeekDiscontinuityAdjust") ActionSchedule actionSchedule = new ActionSchedule.Builder("testSeekDiscontinuityAdjust")
@ -359,32 +356,39 @@ public final class ExoPlayerTest extends TestCase {
Player.DISCONTINUITY_REASON_SEEK_ADJUSTMENT); Player.DISCONTINUITY_REASON_SEEK_ADJUSTMENT);
} }
public void testInternalDiscontinuity() throws Exception { public void testInternalDiscontinuityAtNewPosition() throws Exception {
FakeTimeline timeline = new FakeTimeline(1); FakeTimeline timeline = new FakeTimeline(1);
FakeMediaSource mediaSource = new FakeMediaSource(timeline, null, Builder.VIDEO_FORMAT) { FakeMediaSource mediaSource = new FakeMediaSource(timeline, null, Builder.VIDEO_FORMAT) {
@Override @Override
protected FakeMediaPeriod createFakeMediaPeriod(MediaPeriodId id, protected FakeMediaPeriod createFakeMediaPeriod(MediaPeriodId id,
TrackGroupArray trackGroupArray, Allocator allocator) { TrackGroupArray trackGroupArray, Allocator allocator) {
return new FakeMediaPeriod(trackGroupArray) { FakeMediaPeriod mediaPeriod = new FakeMediaPeriod(trackGroupArray);
boolean discontinuityRead; mediaPeriod.setDiscontinuityPositionUs(10);
@Override return mediaPeriod;
public long readDiscontinuity() {
if (!discontinuityRead) {
discontinuityRead = true;
return 10; // Return a discontinuity.
}
return C.TIME_UNSET;
}
};
} }
}; };
ActionSchedule actionSchedule = new ActionSchedule.Builder("testInternalDiscontinuity")
.waitForPlaybackState(Player.STATE_READY).build();
ExoPlayerTestRunner testRunner = new ExoPlayerTestRunner.Builder().setMediaSource(mediaSource) 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); 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 { public void testAllActivatedTrackSelectionAreReleasedForSinglePeriod() throws Exception {
Timeline timeline = new FakeTimeline(/* windowCount= */ 1); Timeline timeline = new FakeTimeline(/* windowCount= */ 1);
MediaSource mediaSource = MediaSource mediaSource =

View File

@ -509,10 +509,14 @@ import java.io.IOException;
long periodPositionUs = playingPeriodHolder.mediaPeriod.readDiscontinuity(); long periodPositionUs = playingPeriodHolder.mediaPeriod.readDiscontinuity();
if (periodPositionUs != C.TIME_UNSET) { if (periodPositionUs != C.TIME_UNSET) {
resetRendererPosition(periodPositionUs); resetRendererPosition(periodPositionUs);
playbackInfo = playbackInfo.fromNewPosition(playbackInfo.periodId, periodPositionUs, // A MediaPeriod may report a discontinuity at the current playback position to ensure the
playbackInfo.contentPositionUs); // renderers are flushed. Only report the discontinuity externally if the position changed.
eventHandler.obtainMessage(MSG_POSITION_DISCONTINUITY, Player.DISCONTINUITY_REASON_INTERNAL, if (periodPositionUs != playbackInfo.positionUs) {
0, playbackInfo).sendToTarget(); playbackInfo = playbackInfo.fromNewPosition(playbackInfo.periodId, periodPositionUs,
playbackInfo.contentPositionUs);
eventHandler.obtainMessage(MSG_POSITION_DISCONTINUITY, Player.DISCONTINUITY_REASON_INTERNAL,
0, playbackInfo).sendToTarget();
}
} else { } else {
rendererPositionUs = mediaClock.syncAndGetPositionUs(); rendererPositionUs = mediaClock.syncAndGetPositionUs();
periodPositionUs = playingPeriodHolder.toPeriodTime(rendererPositionUs); periodPositionUs = playingPeriodHolder.toPeriodTime(rendererPositionUs);

View File

@ -33,9 +33,31 @@ public class FakeMediaPeriod implements MediaPeriod {
private final TrackGroupArray trackGroupArray; private final TrackGroupArray trackGroupArray;
private boolean preparedPeriod; private boolean preparedPeriod;
private long seekOffsetUs;
private long discontinuityPositionUs;
public FakeMediaPeriod(TrackGroupArray trackGroupArray) { public FakeMediaPeriod(TrackGroupArray trackGroupArray) {
this.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() { public void release() {
@ -92,7 +114,9 @@ public class FakeMediaPeriod implements MediaPeriod {
@Override @Override
public long readDiscontinuity() { public long readDiscontinuity() {
Assert.assertTrue(preparedPeriod); Assert.assertTrue(preparedPeriod);
return C.TIME_UNSET; long positionDiscontinuityUs = this.discontinuityPositionUs;
this.discontinuityPositionUs = C.TIME_UNSET;
return positionDiscontinuityUs;
} }
@Override @Override
@ -104,7 +128,7 @@ public class FakeMediaPeriod implements MediaPeriod {
@Override @Override
public long seekToUs(long positionUs) { public long seekToUs(long positionUs) {
Assert.assertTrue(preparedPeriod); Assert.assertTrue(preparedPeriod);
return positionUs; return positionUs + seekOffsetUs;
} }
@Override @Override