Add reason to onTimelineChanged.
Currently onTimelineChanged doesn't allow to distinguish easily between the different reasons why it's being called. Especially, finding out whether a new media source has been prepared or the current source refreshed dynamically was impossible without tightly coupling the player operations with the listener. The new reasons provide this disdinction by either indicating a newly initialized media source, a dynamic update to an existing timeline or manifest, or a reset of the player (which usually results in an empty timeline). The original onTimelineChanged method without reason is kept in the DefaultEventListener as deprecated to prevent the need to update all existing listeners in one go. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=176478701
This commit is contained in:
parent
13b595ed39
commit
aac53cac56
@ -22,6 +22,8 @@
|
|||||||
use this with `FfmpegAudioRenderer`.
|
use this with `FfmpegAudioRenderer`.
|
||||||
* Support extraction and decoding of Dolby Atmos
|
* Support extraction and decoding of Dolby Atmos
|
||||||
([#2465](https://github.com/google/ExoPlayer/issues/2465)).
|
([#2465](https://github.com/google/ExoPlayer/issues/2465)).
|
||||||
|
* Added a reason to `EventListener.onTimelineChanged` to distinguish between
|
||||||
|
initial preparation, reset and dynamic updates.
|
||||||
|
|
||||||
### 2.6.0 ###
|
### 2.6.0 ###
|
||||||
|
|
||||||
|
@ -116,10 +116,12 @@ import java.util.Locale;
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTimelineChanged(Timeline timeline, Object manifest) {
|
public void onTimelineChanged(Timeline timeline, Object manifest,
|
||||||
|
@Player.TimelineChangeReason int reason) {
|
||||||
int periodCount = timeline.getPeriodCount();
|
int periodCount = timeline.getPeriodCount();
|
||||||
int windowCount = timeline.getWindowCount();
|
int windowCount = timeline.getWindowCount();
|
||||||
Log.d(TAG, "sourceInfo [periodCount=" + periodCount + ", windowCount=" + windowCount);
|
Log.d(TAG, "timelineChanged [periodCount=" + periodCount + ", windowCount=" + windowCount
|
||||||
|
+ ", reason=" + getTimelineChangeReasonString(reason));
|
||||||
for (int i = 0; i < Math.min(periodCount, MAX_TIMELINE_ITEM_LINES); i++) {
|
for (int i = 0; i < Math.min(periodCount, MAX_TIMELINE_ITEM_LINES); i++) {
|
||||||
timeline.getPeriod(i, period);
|
timeline.getPeriod(i, period);
|
||||||
Log.d(TAG, " " + "period [" + getTimeString(period.getDurationMs()) + "]");
|
Log.d(TAG, " " + "period [" + getTimeString(period.getDurationMs()) + "]");
|
||||||
@ -507,4 +509,18 @@ import java.util.Locale;
|
|||||||
return "?";
|
return "?";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static String getTimelineChangeReasonString(@Player.TimelineChangeReason int reason) {
|
||||||
|
switch (reason) {
|
||||||
|
case Player.TIMELINE_CHANGE_REASON_PREPARED:
|
||||||
|
return "PREPARED";
|
||||||
|
case Player.TIMELINE_CHANGE_REASON_RESET:
|
||||||
|
return "RESET";
|
||||||
|
case Player.TIMELINE_CHANGE_REASON_DYNAMIC:
|
||||||
|
return "DYNAMIC";
|
||||||
|
default:
|
||||||
|
return "?";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -116,6 +116,7 @@ public final class CastPlayer implements Player {
|
|||||||
private int pendingSeekCount;
|
private int pendingSeekCount;
|
||||||
private int pendingSeekWindowIndex;
|
private int pendingSeekWindowIndex;
|
||||||
private long pendingSeekPositionMs;
|
private long pendingSeekPositionMs;
|
||||||
|
private boolean waitingForInitialTimeline;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param castContext The context from which the cast session is obtained.
|
* @param castContext The context from which the cast session is obtained.
|
||||||
@ -170,6 +171,7 @@ public final class CastPlayer implements Player {
|
|||||||
public PendingResult<MediaChannelResult> loadItems(MediaQueueItem[] items, int startIndex,
|
public PendingResult<MediaChannelResult> loadItems(MediaQueueItem[] items, int startIndex,
|
||||||
long positionMs, @RepeatMode int repeatMode) {
|
long positionMs, @RepeatMode int repeatMode) {
|
||||||
if (remoteMediaClient != null) {
|
if (remoteMediaClient != null) {
|
||||||
|
waitingForInitialTimeline = true;
|
||||||
return remoteMediaClient.queueLoad(items, startIndex, getCastRepeatMode(repeatMode),
|
return remoteMediaClient.queueLoad(items, startIndex, getCastRepeatMode(repeatMode),
|
||||||
positionMs, null);
|
positionMs, null);
|
||||||
}
|
}
|
||||||
@ -556,8 +558,11 @@ public final class CastPlayer implements Player {
|
|||||||
|
|
||||||
private void maybeUpdateTimelineAndNotify() {
|
private void maybeUpdateTimelineAndNotify() {
|
||||||
if (updateTimeline()) {
|
if (updateTimeline()) {
|
||||||
|
@Player.TimelineChangeReason int reason = waitingForInitialTimeline
|
||||||
|
? Player.TIMELINE_CHANGE_REASON_PREPARED : Player.TIMELINE_CHANGE_REASON_DYNAMIC;
|
||||||
|
waitingForInitialTimeline = false;
|
||||||
for (EventListener listener : listeners) {
|
for (EventListener listener : listeners) {
|
||||||
listener.onTimelineChanged(currentTimeline, null);
|
listener.onTimelineChanged(currentTimeline, null, reason);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -523,9 +523,10 @@ public final class ImaAdsLoader extends Player.DefaultEventListener implements A
|
|||||||
// Player.EventListener implementation.
|
// Player.EventListener implementation.
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTimelineChanged(Timeline timeline, Object manifest) {
|
public void onTimelineChanged(Timeline timeline, Object manifest,
|
||||||
if (timeline.isEmpty()) {
|
@Player.TimelineChangeReason int reason) {
|
||||||
// The player is being re-prepared and this source will be released.
|
if (reason == Player.TIMELINE_CHANGE_REASON_RESET) {
|
||||||
|
// The player is being reset and this source will be released.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Assertions.checkArgument(timeline.getPeriodCount() == 1);
|
Assertions.checkArgument(timeline.getPeriodCount() == 1);
|
||||||
|
@ -32,6 +32,7 @@ import com.google.android.exoplayer2.ExoPlaybackException;
|
|||||||
import com.google.android.exoplayer2.ExoPlayerLibraryInfo;
|
import com.google.android.exoplayer2.ExoPlayerLibraryInfo;
|
||||||
import com.google.android.exoplayer2.Player;
|
import com.google.android.exoplayer2.Player;
|
||||||
import com.google.android.exoplayer2.Player.DiscontinuityReason;
|
import com.google.android.exoplayer2.Player.DiscontinuityReason;
|
||||||
|
import com.google.android.exoplayer2.Player.TimelineChangeReason;
|
||||||
import com.google.android.exoplayer2.SimpleExoPlayer;
|
import com.google.android.exoplayer2.SimpleExoPlayer;
|
||||||
import com.google.android.exoplayer2.Timeline;
|
import com.google.android.exoplayer2.Timeline;
|
||||||
import com.google.android.exoplayer2.util.ErrorMessageProvider;
|
import com.google.android.exoplayer2.util.ErrorMessageProvider;
|
||||||
@ -258,7 +259,8 @@ public final class LeanbackPlayerAdapter extends PlayerAdapter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTimelineChanged(Timeline timeline, Object manifest) {
|
public void onTimelineChanged(Timeline timeline, Object manifest,
|
||||||
|
@TimelineChangeReason int reason) {
|
||||||
Callback callback = getCallback();
|
Callback callback = getCallback();
|
||||||
callback.onDurationChanged(LeanbackPlayerAdapter.this);
|
callback.onDurationChanged(LeanbackPlayerAdapter.this);
|
||||||
callback.onCurrentPositionChanged(LeanbackPlayerAdapter.this);
|
callback.onCurrentPositionChanged(LeanbackPlayerAdapter.this);
|
||||||
|
@ -628,7 +628,8 @@ public final class MediaSessionConnector {
|
|||||||
private int currentWindowCount;
|
private int currentWindowCount;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTimelineChanged(Timeline timeline, Object manifest) {
|
public void onTimelineChanged(Timeline timeline, Object manifest,
|
||||||
|
@Player.TimelineChangeReason int reason) {
|
||||||
int windowCount = player.getCurrentTimeline().getWindowCount();
|
int windowCount = player.getCurrentTimeline().getWindowCount();
|
||||||
int windowIndex = player.getCurrentWindowIndex();
|
int windowIndex = player.getCurrentWindowIndex();
|
||||||
if (queueNavigator != null) {
|
if (queueNavigator != null) {
|
||||||
|
@ -17,6 +17,7 @@ package com.google.android.exoplayer2;
|
|||||||
|
|
||||||
import com.google.android.exoplayer2.source.ConcatenatingMediaSource;
|
import com.google.android.exoplayer2.source.ConcatenatingMediaSource;
|
||||||
import com.google.android.exoplayer2.source.MediaSource;
|
import com.google.android.exoplayer2.source.MediaSource;
|
||||||
|
import com.google.android.exoplayer2.source.MediaSource.Listener;
|
||||||
import com.google.android.exoplayer2.source.TrackGroup;
|
import com.google.android.exoplayer2.source.TrackGroup;
|
||||||
import com.google.android.exoplayer2.source.TrackGroupArray;
|
import com.google.android.exoplayer2.source.TrackGroupArray;
|
||||||
import com.google.android.exoplayer2.testutil.ActionSchedule;
|
import com.google.android.exoplayer2.testutil.ActionSchedule;
|
||||||
@ -28,6 +29,7 @@ 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.FakeTimeline.TimelineWindowDefinition;
|
||||||
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 com.google.android.exoplayer2.upstream.Allocator;
|
||||||
@ -59,7 +61,7 @@ public final class ExoPlayerTest extends TestCase {
|
|||||||
.setTimeline(timeline).setRenderers(renderer)
|
.setTimeline(timeline).setRenderers(renderer)
|
||||||
.build().start().blockUntilEnded(TIMEOUT_MS);
|
.build().start().blockUntilEnded(TIMEOUT_MS);
|
||||||
testRunner.assertNoPositionDiscontinuities();
|
testRunner.assertNoPositionDiscontinuities();
|
||||||
testRunner.assertTimelinesEqual();
|
testRunner.assertTimelinesEqual(timeline);
|
||||||
assertEquals(0, renderer.formatReadCount);
|
assertEquals(0, renderer.formatReadCount);
|
||||||
assertEquals(0, renderer.bufferReadCount);
|
assertEquals(0, renderer.bufferReadCount);
|
||||||
assertFalse(renderer.isEnded);
|
assertFalse(renderer.isEnded);
|
||||||
@ -78,6 +80,7 @@ public final class ExoPlayerTest extends TestCase {
|
|||||||
testRunner.assertNoPositionDiscontinuities();
|
testRunner.assertNoPositionDiscontinuities();
|
||||||
testRunner.assertTimelinesEqual(timeline);
|
testRunner.assertTimelinesEqual(timeline);
|
||||||
testRunner.assertManifestsEqual(manifest);
|
testRunner.assertManifestsEqual(manifest);
|
||||||
|
testRunner.assertTimelineChangeReasonsEqual(Player.TIMELINE_CHANGE_REASON_PREPARED);
|
||||||
testRunner.assertTrackGroupsEqual(new TrackGroupArray(new TrackGroup(Builder.VIDEO_FORMAT)));
|
testRunner.assertTrackGroupsEqual(new TrackGroupArray(new TrackGroup(Builder.VIDEO_FORMAT)));
|
||||||
assertEquals(1, renderer.formatReadCount);
|
assertEquals(1, renderer.formatReadCount);
|
||||||
assertEquals(1, renderer.bufferReadCount);
|
assertEquals(1, renderer.bufferReadCount);
|
||||||
@ -97,6 +100,7 @@ public final class ExoPlayerTest extends TestCase {
|
|||||||
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);
|
||||||
|
testRunner.assertTimelineChangeReasonsEqual(Player.TIMELINE_CHANGE_REASON_PREPARED);
|
||||||
assertEquals(3, renderer.formatReadCount);
|
assertEquals(3, renderer.formatReadCount);
|
||||||
assertEquals(1, renderer.bufferReadCount);
|
assertEquals(1, renderer.bufferReadCount);
|
||||||
assertTrue(renderer.isEnded);
|
assertTrue(renderer.isEnded);
|
||||||
@ -210,6 +214,8 @@ public final class ExoPlayerTest extends TestCase {
|
|||||||
// 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.
|
||||||
testRunner.assertTimelinesEqual(timeline, Timeline.EMPTY, timeline);
|
testRunner.assertTimelinesEqual(timeline, Timeline.EMPTY, timeline);
|
||||||
testRunner.assertManifestsEqual(firstSourceManifest, null, thirdSourceManifest);
|
testRunner.assertManifestsEqual(firstSourceManifest, null, thirdSourceManifest);
|
||||||
|
testRunner.assertTimelineChangeReasonsEqual(Player.TIMELINE_CHANGE_REASON_PREPARED,
|
||||||
|
Player.TIMELINE_CHANGE_REASON_RESET, Player.TIMELINE_CHANGE_REASON_PREPARED);
|
||||||
testRunner.assertTrackGroupsEqual(new TrackGroupArray(new TrackGroup(Builder.VIDEO_FORMAT)));
|
testRunner.assertTrackGroupsEqual(new TrackGroupArray(new TrackGroup(Builder.VIDEO_FORMAT)));
|
||||||
assertEquals(1, renderer.formatReadCount);
|
assertEquals(1, renderer.formatReadCount);
|
||||||
assertEquals(1, renderer.bufferReadCount);
|
assertEquals(1, renderer.bufferReadCount);
|
||||||
@ -243,6 +249,7 @@ public final class ExoPlayerTest extends TestCase {
|
|||||||
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);
|
||||||
|
testRunner.assertTimelineChangeReasonsEqual(Player.TIMELINE_CHANGE_REASON_PREPARED);
|
||||||
assertTrue(renderer.isEnded);
|
assertTrue(renderer.isEnded);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -513,4 +520,25 @@ public final class ExoPlayerTest extends TestCase {
|
|||||||
assertEquals(3, numSelectionsEnabled);
|
assertEquals(3, numSelectionsEnabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testDynamicTimelineChangeReason() throws Exception {
|
||||||
|
Timeline timeline1 = new FakeTimeline(new TimelineWindowDefinition(false, false, 100000));
|
||||||
|
final Timeline timeline2 = new FakeTimeline(new TimelineWindowDefinition(false, false, 20000));
|
||||||
|
final FakeMediaSource mediaSource = new FakeMediaSource(timeline1, null, Builder.VIDEO_FORMAT);
|
||||||
|
ActionSchedule actionSchedule = new ActionSchedule.Builder("testDynamicTimelineChangeReason")
|
||||||
|
.waitForTimelineChanged(timeline1)
|
||||||
|
.executeRunnable(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
mediaSource.setNewSourceInfo(timeline2, null);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.build();
|
||||||
|
ExoPlayerTestRunner testRunner = new ExoPlayerTestRunner.Builder()
|
||||||
|
.setMediaSource(mediaSource).setActionSchedule(actionSchedule)
|
||||||
|
.build().start().blockUntilEnded(TIMEOUT_MS);
|
||||||
|
testRunner.assertTimelinesEqual(timeline1, timeline2);
|
||||||
|
testRunner.assertTimelineChangeReasonsEqual(Player.TIMELINE_CHANGE_REASON_PREPARED,
|
||||||
|
Player.TIMELINE_CHANGE_REASON_DYNAMIC);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -56,6 +56,7 @@ import java.util.concurrent.CopyOnWriteArraySet;
|
|||||||
private int playbackState;
|
private int playbackState;
|
||||||
private int pendingSeekAcks;
|
private int pendingSeekAcks;
|
||||||
private int pendingPrepareAcks;
|
private int pendingPrepareAcks;
|
||||||
|
private boolean waitingForInitialTimeline;
|
||||||
private boolean isLoading;
|
private boolean isLoading;
|
||||||
private TrackGroupArray trackGroups;
|
private TrackGroupArray trackGroups;
|
||||||
private TrackSelectionArray trackSelections;
|
private TrackSelectionArray trackSelections;
|
||||||
@ -146,7 +147,8 @@ import java.util.concurrent.CopyOnWriteArraySet;
|
|||||||
if (!playbackInfo.timeline.isEmpty() || playbackInfo.manifest != null) {
|
if (!playbackInfo.timeline.isEmpty() || playbackInfo.manifest != null) {
|
||||||
playbackInfo = playbackInfo.copyWithTimeline(Timeline.EMPTY, null);
|
playbackInfo = playbackInfo.copyWithTimeline(Timeline.EMPTY, null);
|
||||||
for (Player.EventListener listener : listeners) {
|
for (Player.EventListener listener : listeners) {
|
||||||
listener.onTimelineChanged(playbackInfo.timeline, playbackInfo.manifest);
|
listener.onTimelineChanged(playbackInfo.timeline, playbackInfo.manifest,
|
||||||
|
Player.TIMELINE_CHANGE_REASON_RESET);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (tracksSelected) {
|
if (tracksSelected) {
|
||||||
@ -159,6 +161,7 @@ import java.util.concurrent.CopyOnWriteArraySet;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
waitingForInitialTimeline = true;
|
||||||
pendingPrepareAcks++;
|
pendingPrepareAcks++;
|
||||||
internalPlayer.prepare(mediaSource, resetPosition);
|
internalPlayer.prepare(mediaSource, resetPosition);
|
||||||
}
|
}
|
||||||
@ -532,9 +535,12 @@ import java.util.concurrent.CopyOnWriteArraySet;
|
|||||||
maskingWindowIndex = 0;
|
maskingWindowIndex = 0;
|
||||||
maskingWindowPositionMs = 0;
|
maskingWindowPositionMs = 0;
|
||||||
}
|
}
|
||||||
if (timelineOrManifestChanged) {
|
if (timelineOrManifestChanged || waitingForInitialTimeline) {
|
||||||
|
@Player.TimelineChangeReason int reason = waitingForInitialTimeline
|
||||||
|
? Player.TIMELINE_CHANGE_REASON_PREPARED : Player.TIMELINE_CHANGE_REASON_DYNAMIC;
|
||||||
|
waitingForInitialTimeline = false;
|
||||||
for (Player.EventListener listener : listeners) {
|
for (Player.EventListener listener : listeners) {
|
||||||
listener.onTimelineChanged(playbackInfo.timeline, playbackInfo.manifest);
|
listener.onTimelineChanged(playbackInfo.timeline, playbackInfo.manifest, reason);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (positionDiscontinuity) {
|
if (positionDiscontinuity) {
|
||||||
|
@ -59,8 +59,9 @@ public interface Player {
|
|||||||
*
|
*
|
||||||
* @param timeline The latest timeline. Never null, but may be empty.
|
* @param timeline The latest timeline. Never null, but may be empty.
|
||||||
* @param manifest The latest manifest. May be null.
|
* @param manifest The latest manifest. May be null.
|
||||||
|
* @param reason The {@link TimelineChangeReason} responsible for this timeline change.
|
||||||
*/
|
*/
|
||||||
void onTimelineChanged(Timeline timeline, Object manifest);
|
void onTimelineChanged(Timeline timeline, Object manifest, @TimelineChangeReason int reason);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when the available or selected tracks change.
|
* Called when the available or selected tracks change.
|
||||||
@ -118,7 +119,8 @@ public interface Player {
|
|||||||
* when the source introduces a discontinuity internally).
|
* when the source introduces a discontinuity internally).
|
||||||
* <p>
|
* <p>
|
||||||
* When a position discontinuity occurs as a result of a change to the timeline this method is
|
* When a position discontinuity occurs as a result of a change to the timeline this method is
|
||||||
* <em>not</em> called. {@link #onTimelineChanged(Timeline, Object)} is called in this case.
|
* <em>not</em> called. {@link #onTimelineChanged(Timeline, Object, int)} is called in this
|
||||||
|
* case.
|
||||||
*
|
*
|
||||||
* @param reason The {@link DiscontinuityReason} responsible for the discontinuity.
|
* @param reason The {@link DiscontinuityReason} responsible for the discontinuity.
|
||||||
*/
|
*/
|
||||||
@ -149,8 +151,10 @@ public interface Player {
|
|||||||
abstract class DefaultEventListener implements EventListener {
|
abstract class DefaultEventListener implements EventListener {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTimelineChanged(Timeline timeline, Object manifest) {
|
public void onTimelineChanged(Timeline timeline, Object manifest,
|
||||||
// Do nothing.
|
@TimelineChangeReason int reason) {
|
||||||
|
// Call deprecated version. Otherwise, do nothing.
|
||||||
|
onTimelineChanged(timeline, manifest);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -198,6 +202,15 @@ public interface Player {
|
|||||||
// Do nothing.
|
// Do nothing.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated Use {@link DefaultEventListener#onTimelineChanged(Timeline, Object, int)}
|
||||||
|
* instead.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
public void onTimelineChanged(Timeline timeline, Object manifest) {
|
||||||
|
// Do nothing.
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -264,6 +277,26 @@ public interface Player {
|
|||||||
*/
|
*/
|
||||||
int DISCONTINUITY_REASON_INTERNAL = 3;
|
int DISCONTINUITY_REASON_INTERNAL = 3;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reasons for timeline and/or manifest changes.
|
||||||
|
*/
|
||||||
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
|
@IntDef({TIMELINE_CHANGE_REASON_PREPARED, TIMELINE_CHANGE_REASON_RESET,
|
||||||
|
TIMELINE_CHANGE_REASON_DYNAMIC})
|
||||||
|
public @interface TimelineChangeReason {}
|
||||||
|
/**
|
||||||
|
* Timeline and manifest changed as a result of a player initialization with new media.
|
||||||
|
*/
|
||||||
|
int TIMELINE_CHANGE_REASON_PREPARED = 0;
|
||||||
|
/**
|
||||||
|
* Timeline and manifest changed as a result of a player reset.
|
||||||
|
*/
|
||||||
|
int TIMELINE_CHANGE_REASON_RESET = 1;
|
||||||
|
/**
|
||||||
|
* Timeline or manifest changed as a result of an dynamic update introduced by the played media.
|
||||||
|
*/
|
||||||
|
int TIMELINE_CHANGE_REASON_DYNAMIC = 2;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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
|
||||||
* the thread that was used to construct the player. However, if the thread used to construct the
|
* the thread that was used to construct the player. However, if the thread used to construct the
|
||||||
|
@ -699,6 +699,8 @@ public class PlaybackControlView extends FrameLayout {
|
|||||||
repeatToggleButton.setImageDrawable(repeatAllButtonDrawable);
|
repeatToggleButton.setImageDrawable(repeatAllButtonDrawable);
|
||||||
repeatToggleButton.setContentDescription(repeatAllButtonContentDescription);
|
repeatToggleButton.setContentDescription(repeatAllButtonContentDescription);
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
// Never happens.
|
||||||
}
|
}
|
||||||
repeatToggleButton.setVisibility(View.VISIBLE);
|
repeatToggleButton.setVisibility(View.VISIBLE);
|
||||||
}
|
}
|
||||||
@ -1098,7 +1100,8 @@ public class PlaybackControlView extends FrameLayout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTimelineChanged(Timeline timeline, Object manifest) {
|
public void onTimelineChanged(Timeline timeline, Object manifest,
|
||||||
|
@Player.TimelineChangeReason int reason) {
|
||||||
updateNavigation();
|
updateNavigation();
|
||||||
updateTimeBarMode();
|
updateTimeBarMode();
|
||||||
updateProgress();
|
updateProgress();
|
||||||
|
@ -304,7 +304,7 @@ public abstract class Action {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Waits for {@link Player.EventListener#onTimelineChanged(Timeline, Object)}.
|
* Waits for {@link Player.EventListener#onTimelineChanged(Timeline, Object, int)}.
|
||||||
*/
|
*/
|
||||||
public static final class WaitForTimelineChanged extends Action {
|
public static final class WaitForTimelineChanged extends Action {
|
||||||
|
|
||||||
@ -327,7 +327,8 @@ public abstract class Action {
|
|||||||
}
|
}
|
||||||
Player.EventListener listener = new Player.DefaultEventListener() {
|
Player.EventListener listener = new Player.DefaultEventListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onTimelineChanged(Timeline timeline, Object manifest) {
|
public void onTimelineChanged(Timeline timeline, Object manifest,
|
||||||
|
@Player.TimelineChangeReason int reason) {
|
||||||
if (timeline.equals(expectedTimeline)) {
|
if (timeline.equals(expectedTimeline)) {
|
||||||
player.removeListener(this);
|
player.removeListener(this);
|
||||||
nextAction.schedule(player, trackSelector, surface, handler);
|
nextAction.schedule(player, trackSelector, surface, handler);
|
||||||
|
@ -318,6 +318,7 @@ public final class ExoPlayerTestRunner extends Player.DefaultEventListener {
|
|||||||
private final CountDownLatch endedCountDownLatch;
|
private final CountDownLatch endedCountDownLatch;
|
||||||
private final LinkedList<Timeline> timelines;
|
private final LinkedList<Timeline> timelines;
|
||||||
private final LinkedList<Object> manifests;
|
private final LinkedList<Object> manifests;
|
||||||
|
private final ArrayList<Integer> timelineChangeReasons;
|
||||||
private final LinkedList<Integer> periodIndices;
|
private final LinkedList<Integer> periodIndices;
|
||||||
private final ArrayList<Integer> discontinuityReasons;
|
private final ArrayList<Integer> discontinuityReasons;
|
||||||
|
|
||||||
@ -338,6 +339,7 @@ public final class ExoPlayerTestRunner extends Player.DefaultEventListener {
|
|||||||
this.eventListener = eventListener;
|
this.eventListener = eventListener;
|
||||||
this.timelines = new LinkedList<>();
|
this.timelines = new LinkedList<>();
|
||||||
this.manifests = new LinkedList<>();
|
this.manifests = new LinkedList<>();
|
||||||
|
this.timelineChangeReasons = new ArrayList<>();
|
||||||
this.periodIndices = new LinkedList<>();
|
this.periodIndices = new LinkedList<>();
|
||||||
this.discontinuityReasons = new ArrayList<>();
|
this.discontinuityReasons = new ArrayList<>();
|
||||||
this.endedCountDownLatch = new CountDownLatch(1);
|
this.endedCountDownLatch = new CountDownLatch(1);
|
||||||
@ -430,6 +432,18 @@ public final class ExoPlayerTestRunner extends Player.DefaultEventListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Asserts that the timeline change reasons reported by
|
||||||
|
* {@link Player.EventListener#onTimelineChanged(Timeline, Object, int)} are equal to the provided
|
||||||
|
* timeline change reasons.
|
||||||
|
*/
|
||||||
|
public void assertTimelineChangeReasonsEqual(@Player.TimelineChangeReason int... reasons) {
|
||||||
|
Assert.assertEquals(reasons.length, timelineChangeReasons.size());
|
||||||
|
for (int i = 0; i < reasons.length; i++) {
|
||||||
|
Assert.assertEquals(reasons[i], (int) timelineChangeReasons.get(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Asserts that the last track group array reported by
|
* Asserts that the last track group array reported by
|
||||||
* {@link Player.EventListener#onTracksChanged(TrackGroupArray, TrackSelectionArray)} is equal to
|
* {@link Player.EventListener#onTracksChanged(TrackGroupArray, TrackSelectionArray)} is equal to
|
||||||
@ -507,9 +521,11 @@ public final class ExoPlayerTestRunner extends Player.DefaultEventListener {
|
|||||||
// Player.EventListener
|
// Player.EventListener
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTimelineChanged(Timeline timeline, Object manifest) {
|
public void onTimelineChanged(Timeline timeline, Object manifest,
|
||||||
|
@Player.TimelineChangeReason int reason) {
|
||||||
timelines.add(timeline);
|
timelines.add(timeline);
|
||||||
manifests.add(manifest);
|
manifests.add(manifest);
|
||||||
|
timelineChangeReasons.add(reason);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -340,7 +340,8 @@ public class FakeSimpleExoPlayer extends SimpleExoPlayer {
|
|||||||
FakeExoPlayer.this.durationUs = timeline.getPeriod(0, new Period()).durationUs;
|
FakeExoPlayer.this.durationUs = timeline.getPeriod(0, new Period()).durationUs;
|
||||||
FakeExoPlayer.this.timeline = timeline;
|
FakeExoPlayer.this.timeline = timeline;
|
||||||
FakeExoPlayer.this.manifest = manifest;
|
FakeExoPlayer.this.manifest = manifest;
|
||||||
eventListener.onTimelineChanged(timeline, manifest);
|
eventListener.onTimelineChanged(timeline, manifest,
|
||||||
|
Player.TIMELINE_CHANGE_REASON_PREPARED);
|
||||||
waitForNotification.open();
|
waitForNotification.open();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user