Report additional position discontinuities
- Properly report internal discontinuities - Add DISCONTINUITY_REASON_SEEK_ADJUSTMENT to distinguish seek adjustments from other internal discontinuity events ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=176367365
This commit is contained in:
parent
c06fe73b66
commit
275292cb63
@ -2,6 +2,10 @@
|
|||||||
|
|
||||||
### dev-v2 (not yet released) ###
|
### dev-v2 (not yet released) ###
|
||||||
|
|
||||||
|
* Fix reporting of internal position discontinuities via
|
||||||
|
`Player.onPositionDiscontinuity`. `DISCONTINUITY_REASON_SEEK_ADJUSTMENT` is
|
||||||
|
added to disambiguate position adjustments during seeks from other types of
|
||||||
|
internal position discontinuity.
|
||||||
* Allow more flexible loading strategy when playing media containing multiple
|
* Allow more flexible loading strategy when playing media containing multiple
|
||||||
sub-streams, by allowing injection of custom `CompositeSequenceableLoader`
|
sub-streams, by allowing injection of custom `CompositeSequenceableLoader`
|
||||||
factories through `DashMediaSource.Builder`, `HlsMediaSource.Builder`,
|
factories through `DashMediaSource.Builder`, `HlsMediaSource.Builder`,
|
||||||
|
@ -499,6 +499,8 @@ import java.util.Locale;
|
|||||||
return "PERIOD_TRANSITION";
|
return "PERIOD_TRANSITION";
|
||||||
case Player.DISCONTINUITY_REASON_SEEK:
|
case Player.DISCONTINUITY_REASON_SEEK:
|
||||||
return "SEEK";
|
return "SEEK";
|
||||||
|
case Player.DISCONTINUITY_REASON_SEEK_ADJUSTMENT:
|
||||||
|
return "SEEK_ADJUSTMENT";
|
||||||
case Player.DISCONTINUITY_REASON_INTERNAL:
|
case Player.DISCONTINUITY_REASON_INTERNAL:
|
||||||
return "INTERNAL";
|
return "INTERNAL";
|
||||||
default:
|
default:
|
||||||
|
@ -23,12 +23,14 @@ import com.google.android.exoplayer2.testutil.ActionSchedule;
|
|||||||
import com.google.android.exoplayer2.testutil.ExoPlayerTestRunner;
|
import com.google.android.exoplayer2.testutil.ExoPlayerTestRunner;
|
||||||
import com.google.android.exoplayer2.testutil.ExoPlayerTestRunner.Builder;
|
import com.google.android.exoplayer2.testutil.ExoPlayerTestRunner.Builder;
|
||||||
import com.google.android.exoplayer2.testutil.FakeMediaClockRenderer;
|
import com.google.android.exoplayer2.testutil.FakeMediaClockRenderer;
|
||||||
|
import com.google.android.exoplayer2.testutil.FakeMediaPeriod;
|
||||||
import com.google.android.exoplayer2.testutil.FakeMediaSource;
|
import com.google.android.exoplayer2.testutil.FakeMediaSource;
|
||||||
import com.google.android.exoplayer2.testutil.FakeRenderer;
|
import com.google.android.exoplayer2.testutil.FakeRenderer;
|
||||||
import com.google.android.exoplayer2.testutil.FakeShuffleOrder;
|
import com.google.android.exoplayer2.testutil.FakeShuffleOrder;
|
||||||
import com.google.android.exoplayer2.testutil.FakeTimeline;
|
import com.google.android.exoplayer2.testutil.FakeTimeline;
|
||||||
import com.google.android.exoplayer2.testutil.FakeTrackSelection;
|
import com.google.android.exoplayer2.testutil.FakeTrackSelection;
|
||||||
import com.google.android.exoplayer2.testutil.FakeTrackSelector;
|
import com.google.android.exoplayer2.testutil.FakeTrackSelector;
|
||||||
|
import com.google.android.exoplayer2.upstream.Allocator;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.CountDownLatch;
|
import java.util.concurrent.CountDownLatch;
|
||||||
@ -56,7 +58,7 @@ public final class ExoPlayerTest extends TestCase {
|
|||||||
ExoPlayerTestRunner testRunner = new ExoPlayerTestRunner.Builder()
|
ExoPlayerTestRunner testRunner = new ExoPlayerTestRunner.Builder()
|
||||||
.setTimeline(timeline).setRenderers(renderer)
|
.setTimeline(timeline).setRenderers(renderer)
|
||||||
.build().start().blockUntilEnded(TIMEOUT_MS);
|
.build().start().blockUntilEnded(TIMEOUT_MS);
|
||||||
testRunner.assertPositionDiscontinuityCount(0);
|
testRunner.assertNoPositionDiscontinuities();
|
||||||
testRunner.assertTimelinesEqual();
|
testRunner.assertTimelinesEqual();
|
||||||
assertEquals(0, renderer.formatReadCount);
|
assertEquals(0, renderer.formatReadCount);
|
||||||
assertEquals(0, renderer.bufferReadCount);
|
assertEquals(0, renderer.bufferReadCount);
|
||||||
@ -73,7 +75,7 @@ public final class ExoPlayerTest extends TestCase {
|
|||||||
ExoPlayerTestRunner testRunner = new ExoPlayerTestRunner.Builder()
|
ExoPlayerTestRunner testRunner = new ExoPlayerTestRunner.Builder()
|
||||||
.setTimeline(timeline).setManifest(manifest).setRenderers(renderer)
|
.setTimeline(timeline).setManifest(manifest).setRenderers(renderer)
|
||||||
.build().start().blockUntilEnded(TIMEOUT_MS);
|
.build().start().blockUntilEnded(TIMEOUT_MS);
|
||||||
testRunner.assertPositionDiscontinuityCount(0);
|
testRunner.assertNoPositionDiscontinuities();
|
||||||
testRunner.assertTimelinesEqual(timeline);
|
testRunner.assertTimelinesEqual(timeline);
|
||||||
testRunner.assertManifestsEqual(manifest);
|
testRunner.assertManifestsEqual(manifest);
|
||||||
testRunner.assertTrackGroupsEqual(new TrackGroupArray(new TrackGroup(Builder.VIDEO_FORMAT)));
|
testRunner.assertTrackGroupsEqual(new TrackGroupArray(new TrackGroup(Builder.VIDEO_FORMAT)));
|
||||||
@ -91,7 +93,9 @@ public final class ExoPlayerTest extends TestCase {
|
|||||||
ExoPlayerTestRunner testRunner = new ExoPlayerTestRunner.Builder()
|
ExoPlayerTestRunner testRunner = new ExoPlayerTestRunner.Builder()
|
||||||
.setTimeline(timeline).setRenderers(renderer)
|
.setTimeline(timeline).setRenderers(renderer)
|
||||||
.build().start().blockUntilEnded(TIMEOUT_MS);
|
.build().start().blockUntilEnded(TIMEOUT_MS);
|
||||||
testRunner.assertPositionDiscontinuityCount(2);
|
testRunner.assertPositionDiscontinuityReasonsEqual(
|
||||||
|
Player.DISCONTINUITY_REASON_PERIOD_TRANSITION,
|
||||||
|
Player.DISCONTINUITY_REASON_PERIOD_TRANSITION);
|
||||||
testRunner.assertTimelinesEqual(timeline);
|
testRunner.assertTimelinesEqual(timeline);
|
||||||
assertEquals(3, renderer.formatReadCount);
|
assertEquals(3, renderer.formatReadCount);
|
||||||
assertEquals(1, renderer.bufferReadCount);
|
assertEquals(1, renderer.bufferReadCount);
|
||||||
@ -136,7 +140,9 @@ public final class ExoPlayerTest extends TestCase {
|
|||||||
.setTimeline(timeline).setRenderers(videoRenderer, audioRenderer)
|
.setTimeline(timeline).setRenderers(videoRenderer, audioRenderer)
|
||||||
.setSupportedFormats(Builder.VIDEO_FORMAT, Builder.AUDIO_FORMAT)
|
.setSupportedFormats(Builder.VIDEO_FORMAT, Builder.AUDIO_FORMAT)
|
||||||
.build().start().blockUntilEnded(TIMEOUT_MS);
|
.build().start().blockUntilEnded(TIMEOUT_MS);
|
||||||
testRunner.assertPositionDiscontinuityCount(2);
|
testRunner.assertPositionDiscontinuityReasonsEqual(
|
||||||
|
Player.DISCONTINUITY_REASON_PERIOD_TRANSITION,
|
||||||
|
Player.DISCONTINUITY_REASON_PERIOD_TRANSITION);
|
||||||
testRunner.assertTimelinesEqual(timeline);
|
testRunner.assertTimelinesEqual(timeline);
|
||||||
assertEquals(1, audioRenderer.positionResetCount);
|
assertEquals(1, audioRenderer.positionResetCount);
|
||||||
assertTrue(videoRenderer.isEnded);
|
assertTrue(videoRenderer.isEnded);
|
||||||
@ -198,7 +204,7 @@ public final class ExoPlayerTest extends TestCase {
|
|||||||
ExoPlayerTestRunner testRunner = new ExoPlayerTestRunner.Builder()
|
ExoPlayerTestRunner testRunner = new ExoPlayerTestRunner.Builder()
|
||||||
.setMediaSource(firstSource).setRenderers(renderer).setActionSchedule(actionSchedule)
|
.setMediaSource(firstSource).setRenderers(renderer).setActionSchedule(actionSchedule)
|
||||||
.build().start().blockUntilEnded(TIMEOUT_MS);
|
.build().start().blockUntilEnded(TIMEOUT_MS);
|
||||||
testRunner.assertPositionDiscontinuityCount(0);
|
testRunner.assertNoPositionDiscontinuities();
|
||||||
// The first source's preparation completed with a non-empty timeline. When the player was
|
// The first source's preparation completed with a non-empty timeline. When the player was
|
||||||
// re-prepared with the second source, it immediately exposed an empty timeline, but the source
|
// re-prepared with the second source, it immediately exposed an empty timeline, but the source
|
||||||
// info refresh from the second source was suppressed as we re-prepared with the third source.
|
// info refresh from the second source was suppressed as we re-prepared with the third source.
|
||||||
@ -226,6 +232,16 @@ public final class ExoPlayerTest extends TestCase {
|
|||||||
.setTimeline(timeline).setRenderers(renderer).setActionSchedule(actionSchedule)
|
.setTimeline(timeline).setRenderers(renderer).setActionSchedule(actionSchedule)
|
||||||
.build().start().blockUntilEnded(TIMEOUT_MS);
|
.build().start().blockUntilEnded(TIMEOUT_MS);
|
||||||
testRunner.assertPlayedPeriodIndices(0, 1, 1, 2, 2, 0, 0, 0, 1, 2);
|
testRunner.assertPlayedPeriodIndices(0, 1, 1, 2, 2, 0, 0, 0, 1, 2);
|
||||||
|
testRunner.assertPositionDiscontinuityReasonsEqual(
|
||||||
|
Player.DISCONTINUITY_REASON_PERIOD_TRANSITION,
|
||||||
|
Player.DISCONTINUITY_REASON_PERIOD_TRANSITION,
|
||||||
|
Player.DISCONTINUITY_REASON_PERIOD_TRANSITION,
|
||||||
|
Player.DISCONTINUITY_REASON_PERIOD_TRANSITION,
|
||||||
|
Player.DISCONTINUITY_REASON_PERIOD_TRANSITION,
|
||||||
|
Player.DISCONTINUITY_REASON_PERIOD_TRANSITION,
|
||||||
|
Player.DISCONTINUITY_REASON_PERIOD_TRANSITION,
|
||||||
|
Player.DISCONTINUITY_REASON_PERIOD_TRANSITION,
|
||||||
|
Player.DISCONTINUITY_REASON_PERIOD_TRANSITION);
|
||||||
testRunner.assertTimelinesEqual(timeline);
|
testRunner.assertTimelinesEqual(timeline);
|
||||||
assertTrue(renderer.isEnded);
|
assertTrue(renderer.isEnded);
|
||||||
}
|
}
|
||||||
@ -250,6 +266,12 @@ public final class ExoPlayerTest extends TestCase {
|
|||||||
.setMediaSource(mediaSource).setRenderers(renderer).setActionSchedule(actionSchedule)
|
.setMediaSource(mediaSource).setRenderers(renderer).setActionSchedule(actionSchedule)
|
||||||
.build().start().blockUntilEnded(TIMEOUT_MS);
|
.build().start().blockUntilEnded(TIMEOUT_MS);
|
||||||
testRunner.assertPlayedPeriodIndices(0, 1, 0, 2, 1, 2);
|
testRunner.assertPlayedPeriodIndices(0, 1, 0, 2, 1, 2);
|
||||||
|
testRunner.assertPositionDiscontinuityReasonsEqual(
|
||||||
|
Player.DISCONTINUITY_REASON_PERIOD_TRANSITION,
|
||||||
|
Player.DISCONTINUITY_REASON_PERIOD_TRANSITION,
|
||||||
|
Player.DISCONTINUITY_REASON_PERIOD_TRANSITION,
|
||||||
|
Player.DISCONTINUITY_REASON_PERIOD_TRANSITION,
|
||||||
|
Player.DISCONTINUITY_REASON_PERIOD_TRANSITION);
|
||||||
assertTrue(renderer.isEnded);
|
assertTrue(renderer.isEnded);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -300,6 +322,63 @@ public final class ExoPlayerTest extends TestCase {
|
|||||||
assertEquals(Player.STATE_BUFFERING, (int) playbackStatesWhenSeekProcessed.get(2));
|
assertEquals(Player.STATE_BUFFERING, (int) playbackStatesWhenSeekProcessed.get(2));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testSeekDiscontinuity() throws Exception {
|
||||||
|
FakeTimeline timeline = new FakeTimeline(1);
|
||||||
|
ActionSchedule actionSchedule = new ActionSchedule.Builder("testSeekDiscontinuity")
|
||||||
|
.seek(10).build();
|
||||||
|
ExoPlayerTestRunner testRunner = new ExoPlayerTestRunner.Builder().setTimeline(timeline)
|
||||||
|
.setActionSchedule(actionSchedule).build().start().blockUntilEnded(TIMEOUT_MS);
|
||||||
|
testRunner.assertPositionDiscontinuityReasonsEqual(Player.DISCONTINUITY_REASON_SEEK);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testSeekDiscontinuityWithAdjustment() 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) {
|
||||||
|
@Override
|
||||||
|
public long seekToUs(long positionUs) {
|
||||||
|
return positionUs + 10; // Adjusts the requested seek position.
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
ActionSchedule actionSchedule = new ActionSchedule.Builder("testSeekDiscontinuityAdjust")
|
||||||
|
.waitForPlaybackState(Player.STATE_READY).seek(10).build();
|
||||||
|
ExoPlayerTestRunner testRunner = new ExoPlayerTestRunner.Builder().setMediaSource(mediaSource)
|
||||||
|
.setActionSchedule(actionSchedule).build().start().blockUntilEnded(TIMEOUT_MS);
|
||||||
|
testRunner.assertPositionDiscontinuityReasonsEqual(Player.DISCONTINUITY_REASON_SEEK,
|
||||||
|
Player.DISCONTINUITY_REASON_SEEK_ADJUSTMENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testInternalDiscontinuity() 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;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
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);
|
||||||
|
testRunner.assertPositionDiscontinuityReasonsEqual(Player.DISCONTINUITY_REASON_INTERNAL);
|
||||||
|
}
|
||||||
|
|
||||||
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 =
|
||||||
|
@ -467,7 +467,8 @@ import java.util.concurrent.CopyOnWriteArraySet;
|
|||||||
case ExoPlayerImplInternal.MSG_SOURCE_INFO_REFRESHED: {
|
case ExoPlayerImplInternal.MSG_SOURCE_INFO_REFRESHED: {
|
||||||
int prepareAcks = msg.arg1;
|
int prepareAcks = msg.arg1;
|
||||||
int seekAcks = msg.arg2;
|
int seekAcks = msg.arg2;
|
||||||
handlePlaybackInfo((PlaybackInfo) msg.obj, prepareAcks, seekAcks, false);
|
handlePlaybackInfo((PlaybackInfo) msg.obj, prepareAcks, seekAcks, false,
|
||||||
|
/* ignored */ DISCONTINUITY_REASON_INTERNAL);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ExoPlayerImplInternal.MSG_TRACKS_CHANGED: {
|
case ExoPlayerImplInternal.MSG_TRACKS_CHANGED: {
|
||||||
@ -485,11 +486,13 @@ import java.util.concurrent.CopyOnWriteArraySet;
|
|||||||
}
|
}
|
||||||
case ExoPlayerImplInternal.MSG_SEEK_ACK: {
|
case ExoPlayerImplInternal.MSG_SEEK_ACK: {
|
||||||
boolean seekPositionAdjusted = msg.arg1 != 0;
|
boolean seekPositionAdjusted = msg.arg1 != 0;
|
||||||
handlePlaybackInfo((PlaybackInfo) msg.obj, 0, 1, seekPositionAdjusted);
|
handlePlaybackInfo((PlaybackInfo) msg.obj, 0, 1, seekPositionAdjusted,
|
||||||
|
DISCONTINUITY_REASON_SEEK_ADJUSTMENT);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ExoPlayerImplInternal.MSG_POSITION_DISCONTINUITY: {
|
case ExoPlayerImplInternal.MSG_POSITION_DISCONTINUITY: {
|
||||||
handlePlaybackInfo((PlaybackInfo) msg.obj, 0, 0, true);
|
@DiscontinuityReason int discontinuityReason = msg.arg1;
|
||||||
|
handlePlaybackInfo((PlaybackInfo) msg.obj, 0, 0, true, discontinuityReason);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ExoPlayerImplInternal.MSG_PLAYBACK_PARAMETERS_CHANGED: {
|
case ExoPlayerImplInternal.MSG_PLAYBACK_PARAMETERS_CHANGED: {
|
||||||
@ -515,7 +518,7 @@ import java.util.concurrent.CopyOnWriteArraySet;
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void handlePlaybackInfo(PlaybackInfo playbackInfo, int prepareAcks, int seekAcks,
|
private void handlePlaybackInfo(PlaybackInfo playbackInfo, int prepareAcks, int seekAcks,
|
||||||
boolean positionDiscontinuity) {
|
boolean positionDiscontinuity, @DiscontinuityReason int positionDiscontinuityReason) {
|
||||||
Assertions.checkNotNull(playbackInfo.timeline);
|
Assertions.checkNotNull(playbackInfo.timeline);
|
||||||
pendingPrepareAcks -= prepareAcks;
|
pendingPrepareAcks -= prepareAcks;
|
||||||
pendingSeekAcks -= seekAcks;
|
pendingSeekAcks -= seekAcks;
|
||||||
@ -536,9 +539,7 @@ import java.util.concurrent.CopyOnWriteArraySet;
|
|||||||
}
|
}
|
||||||
if (positionDiscontinuity) {
|
if (positionDiscontinuity) {
|
||||||
for (Player.EventListener listener : listeners) {
|
for (Player.EventListener listener : listeners) {
|
||||||
listener.onPositionDiscontinuity(
|
listener.onPositionDiscontinuity(positionDiscontinuityReason);
|
||||||
seekAcks > 0 ? DISCONTINUITY_REASON_INTERNAL : DISCONTINUITY_REASON_PERIOD_TRANSITION
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -514,6 +514,10 @@ 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,
|
||||||
|
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);
|
||||||
@ -875,7 +879,10 @@ import java.io.IOException;
|
|||||||
long periodPositionUs = playingPeriodHolder.updatePeriodTrackSelection(
|
long periodPositionUs = playingPeriodHolder.updatePeriodTrackSelection(
|
||||||
playbackInfo.positionUs, recreateStreams, streamResetFlags);
|
playbackInfo.positionUs, recreateStreams, streamResetFlags);
|
||||||
if (periodPositionUs != playbackInfo.positionUs) {
|
if (periodPositionUs != playbackInfo.positionUs) {
|
||||||
playbackInfo.positionUs = periodPositionUs;
|
playbackInfo = playbackInfo.fromNewPosition(playbackInfo.periodId, periodPositionUs,
|
||||||
|
playbackInfo.contentPositionUs);
|
||||||
|
eventHandler.obtainMessage(MSG_POSITION_DISCONTINUITY, Player.DISCONTINUITY_REASON_INTERNAL,
|
||||||
|
0, playbackInfo).sendToTarget();
|
||||||
resetRendererPosition(periodPositionUs);
|
resetRendererPosition(periodPositionUs);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1262,7 +1269,8 @@ import java.io.IOException;
|
|||||||
playbackInfo = playbackInfo.fromNewPosition(playingPeriodHolder.info.id,
|
playbackInfo = playbackInfo.fromNewPosition(playingPeriodHolder.info.id,
|
||||||
playingPeriodHolder.info.startPositionUs, playingPeriodHolder.info.contentPositionUs);
|
playingPeriodHolder.info.startPositionUs, playingPeriodHolder.info.contentPositionUs);
|
||||||
updatePlaybackPositions();
|
updatePlaybackPositions();
|
||||||
eventHandler.obtainMessage(MSG_POSITION_DISCONTINUITY, playbackInfo).sendToTarget();
|
eventHandler.obtainMessage(MSG_POSITION_DISCONTINUITY,
|
||||||
|
Player.DISCONTINUITY_REASON_PERIOD_TRANSITION, 0, playbackInfo).sendToTarget();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (readingPeriodHolder.info.isFinal) {
|
if (readingPeriodHolder.info.isFinal) {
|
||||||
|
@ -243,7 +243,7 @@ public interface Player {
|
|||||||
*/
|
*/
|
||||||
@Retention(RetentionPolicy.SOURCE)
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
@IntDef({DISCONTINUITY_REASON_PERIOD_TRANSITION, DISCONTINUITY_REASON_SEEK,
|
@IntDef({DISCONTINUITY_REASON_PERIOD_TRANSITION, DISCONTINUITY_REASON_SEEK,
|
||||||
DISCONTINUITY_REASON_INTERNAL})
|
DISCONTINUITY_REASON_SEEK_ADJUSTMENT, DISCONTINUITY_REASON_INTERNAL})
|
||||||
public @interface DiscontinuityReason {}
|
public @interface DiscontinuityReason {}
|
||||||
/**
|
/**
|
||||||
* Automatic playback transition from one period in the timeline to the next. The period index may
|
* Automatic playback transition from one period in the timeline to the next. The period index may
|
||||||
@ -254,10 +254,15 @@ public interface Player {
|
|||||||
* Seek within the current period or to another period.
|
* Seek within the current period or to another period.
|
||||||
*/
|
*/
|
||||||
int DISCONTINUITY_REASON_SEEK = 1;
|
int DISCONTINUITY_REASON_SEEK = 1;
|
||||||
|
/**
|
||||||
|
* Seek adjustment due to being unable to seek to the requested position or because the seek was
|
||||||
|
* permitted to be inexact.
|
||||||
|
*/
|
||||||
|
int DISCONTINUITY_REASON_SEEK_ADJUSTMENT = 2;
|
||||||
/**
|
/**
|
||||||
* Discontinuity introduced internally by the source.
|
* Discontinuity introduced internally by the source.
|
||||||
*/
|
*/
|
||||||
int DISCONTINUITY_REASON_INTERNAL = 2;
|
int DISCONTINUITY_REASON_INTERNAL = 3;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register a listener to receive events from the player. The listener's methods will be called on
|
* Register a listener to receive events from the player. The listener's methods will be called on
|
||||||
|
@ -23,6 +23,7 @@ import com.google.android.exoplayer2.ExoPlayerFactory;
|
|||||||
import com.google.android.exoplayer2.Format;
|
import com.google.android.exoplayer2.Format;
|
||||||
import com.google.android.exoplayer2.LoadControl;
|
import com.google.android.exoplayer2.LoadControl;
|
||||||
import com.google.android.exoplayer2.Player;
|
import com.google.android.exoplayer2.Player;
|
||||||
|
import com.google.android.exoplayer2.Player.DiscontinuityReason;
|
||||||
import com.google.android.exoplayer2.Renderer;
|
import com.google.android.exoplayer2.Renderer;
|
||||||
import com.google.android.exoplayer2.RenderersFactory;
|
import com.google.android.exoplayer2.RenderersFactory;
|
||||||
import com.google.android.exoplayer2.SimpleExoPlayer;
|
import com.google.android.exoplayer2.SimpleExoPlayer;
|
||||||
@ -38,6 +39,7 @@ import com.google.android.exoplayer2.trackselection.MappingTrackSelector;
|
|||||||
import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
|
import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
|
||||||
import com.google.android.exoplayer2.util.MimeTypes;
|
import com.google.android.exoplayer2.util.MimeTypes;
|
||||||
import com.google.android.exoplayer2.video.VideoRendererEventListener;
|
import com.google.android.exoplayer2.video.VideoRendererEventListener;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.concurrent.CountDownLatch;
|
import java.util.concurrent.CountDownLatch;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
@ -317,11 +319,11 @@ public final class ExoPlayerTestRunner extends Player.DefaultEventListener {
|
|||||||
private final LinkedList<Timeline> timelines;
|
private final LinkedList<Timeline> timelines;
|
||||||
private final LinkedList<Object> manifests;
|
private final LinkedList<Object> manifests;
|
||||||
private final LinkedList<Integer> periodIndices;
|
private final LinkedList<Integer> periodIndices;
|
||||||
|
private final ArrayList<Integer> discontinuityReasons;
|
||||||
|
|
||||||
private SimpleExoPlayer player;
|
private SimpleExoPlayer player;
|
||||||
private Exception exception;
|
private Exception exception;
|
||||||
private TrackGroupArray trackGroups;
|
private TrackGroupArray trackGroups;
|
||||||
private int positionDiscontinuityCount;
|
|
||||||
private boolean playerWasPrepared;
|
private boolean playerWasPrepared;
|
||||||
|
|
||||||
private ExoPlayerTestRunner(PlayerFactory playerFactory, MediaSource mediaSource,
|
private ExoPlayerTestRunner(PlayerFactory playerFactory, MediaSource mediaSource,
|
||||||
@ -337,6 +339,7 @@ public final class ExoPlayerTestRunner extends Player.DefaultEventListener {
|
|||||||
this.timelines = new LinkedList<>();
|
this.timelines = new LinkedList<>();
|
||||||
this.manifests = new LinkedList<>();
|
this.manifests = new LinkedList<>();
|
||||||
this.periodIndices = new LinkedList<>();
|
this.periodIndices = new LinkedList<>();
|
||||||
|
this.discontinuityReasons = new ArrayList<>();
|
||||||
this.endedCountDownLatch = new CountDownLatch(1);
|
this.endedCountDownLatch = new CountDownLatch(1);
|
||||||
this.playerThread = new HandlerThread("ExoPlayerTest thread");
|
this.playerThread = new HandlerThread("ExoPlayerTest thread");
|
||||||
playerThread.start();
|
playerThread.start();
|
||||||
@ -439,13 +442,24 @@ public final class ExoPlayerTestRunner extends Player.DefaultEventListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Asserts that the number of reported discontinuities by
|
* Asserts that {@link Player.EventListener#onPositionDiscontinuity(int)} was not called.
|
||||||
* {@link Player.EventListener#onPositionDiscontinuity(int)} is equal to the provided number.
|
|
||||||
*
|
|
||||||
* @param expectedCount The expected number of position discontinuities.
|
|
||||||
*/
|
*/
|
||||||
public void assertPositionDiscontinuityCount(int expectedCount) {
|
public void assertNoPositionDiscontinuities() {
|
||||||
Assert.assertEquals(expectedCount, positionDiscontinuityCount);
|
Assert.assertTrue(discontinuityReasons.isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Asserts that the discontinuity reasons reported by
|
||||||
|
* {@link Player.EventListener#onPositionDiscontinuity(int)} are equal to the provided values.
|
||||||
|
*
|
||||||
|
* @param discontinuityReasons The expected discontinuity reasons.
|
||||||
|
*/
|
||||||
|
public void assertPositionDiscontinuityReasonsEqual(
|
||||||
|
@DiscontinuityReason int... discontinuityReasons) {
|
||||||
|
Assert.assertEquals(discontinuityReasons.length, this.discontinuityReasons.size());
|
||||||
|
for (int i = 0; i < discontinuityReasons.length; i++) {
|
||||||
|
Assert.assertEquals(discontinuityReasons[i], (int) this.discontinuityReasons.get(i));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -522,7 +536,7 @@ public final class ExoPlayerTestRunner extends Player.DefaultEventListener {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPositionDiscontinuity(@Player.DiscontinuityReason int reason) {
|
public void onPositionDiscontinuity(@Player.DiscontinuityReason int reason) {
|
||||||
positionDiscontinuityCount++;
|
discontinuityReasons.add(reason);
|
||||||
periodIndices.add(player.getCurrentPeriodIndex());
|
periodIndices.add(player.getCurrentPeriodIndex());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user