Commit 8e2692dc by tonihei Committed by christosts

Allow unset index and position values + remove period index

This simplifies some position tracking needs for an app implementing
SimpleBasePlayer.
 - The period index can always be derived from the media item index
   and the position. So there is no need to set it separately.
 - The media item index can be left unset in the State in case the app
   doesn't care about the value or wants to set it the default start
   index (e.g. while the playlist is still empty where UNSET is
   different from zero).
 - Similarly, we should allow to set the content position (and buffered
   position) to C.TIME_UNSET to let the app ignore it or indicate the
   default position explictly.

PiperOrigin-RevId: 495352633
(cherry picked from commit 91557ac9)
parent 0e921d1a
...@@ -19,6 +19,7 @@ import static androidx.annotation.VisibleForTesting.PROTECTED; ...@@ -19,6 +19,7 @@ import static androidx.annotation.VisibleForTesting.PROTECTED;
import static com.google.android.exoplayer2.util.Assertions.checkArgument; import static com.google.android.exoplayer2.util.Assertions.checkArgument;
import static com.google.android.exoplayer2.util.Assertions.checkNotNull; import static com.google.android.exoplayer2.util.Assertions.checkNotNull;
import static com.google.android.exoplayer2.util.Util.castNonNull; import static com.google.android.exoplayer2.util.Util.castNonNull;
import static com.google.android.exoplayer2.util.Util.msToUs;
import static com.google.android.exoplayer2.util.Util.usToMs; import static com.google.android.exoplayer2.util.Util.usToMs;
import static java.lang.Math.max; import static java.lang.Math.max;
...@@ -130,12 +131,11 @@ public abstract class SimpleBasePlayer extends BasePlayer { ...@@ -130,12 +131,11 @@ public abstract class SimpleBasePlayer extends BasePlayer {
private Timeline timeline; private Timeline timeline;
private MediaMetadata playlistMetadata; private MediaMetadata playlistMetadata;
private int currentMediaItemIndex; private int currentMediaItemIndex;
private int currentPeriodIndex;
private int currentAdGroupIndex; private int currentAdGroupIndex;
private int currentAdIndexInAdGroup; private int currentAdIndexInAdGroup;
private long contentPositionMs; @Nullable private Long contentPositionMs;
private PositionSupplier contentPositionMsSupplier; private PositionSupplier contentPositionMsSupplier;
private long adPositionMs; @Nullable private Long adPositionMs;
private PositionSupplier adPositionMsSupplier; private PositionSupplier adPositionMsSupplier;
private PositionSupplier contentBufferedPositionMsSupplier; private PositionSupplier contentBufferedPositionMsSupplier;
private PositionSupplier adBufferedPositionMsSupplier; private PositionSupplier adBufferedPositionMsSupplier;
...@@ -173,15 +173,14 @@ public abstract class SimpleBasePlayer extends BasePlayer { ...@@ -173,15 +173,14 @@ public abstract class SimpleBasePlayer extends BasePlayer {
playlist = ImmutableList.of(); playlist = ImmutableList.of();
timeline = Timeline.EMPTY; timeline = Timeline.EMPTY;
playlistMetadata = MediaMetadata.EMPTY; playlistMetadata = MediaMetadata.EMPTY;
currentMediaItemIndex = 0; currentMediaItemIndex = C.INDEX_UNSET;
currentPeriodIndex = C.INDEX_UNSET;
currentAdGroupIndex = C.INDEX_UNSET; currentAdGroupIndex = C.INDEX_UNSET;
currentAdIndexInAdGroup = C.INDEX_UNSET; currentAdIndexInAdGroup = C.INDEX_UNSET;
contentPositionMs = C.TIME_UNSET; contentPositionMs = null;
contentPositionMsSupplier = PositionSupplier.ZERO; contentPositionMsSupplier = PositionSupplier.getConstant(C.TIME_UNSET);
adPositionMs = C.TIME_UNSET; adPositionMs = null;
adPositionMsSupplier = PositionSupplier.ZERO; adPositionMsSupplier = PositionSupplier.ZERO;
contentBufferedPositionMsSupplier = PositionSupplier.ZERO; contentBufferedPositionMsSupplier = PositionSupplier.getConstant(C.TIME_UNSET);
adBufferedPositionMsSupplier = PositionSupplier.ZERO; adBufferedPositionMsSupplier = PositionSupplier.ZERO;
totalBufferedDurationMsSupplier = PositionSupplier.ZERO; totalBufferedDurationMsSupplier = PositionSupplier.ZERO;
hasPositionDiscontinuity = false; hasPositionDiscontinuity = false;
...@@ -218,12 +217,11 @@ public abstract class SimpleBasePlayer extends BasePlayer { ...@@ -218,12 +217,11 @@ public abstract class SimpleBasePlayer extends BasePlayer {
this.timeline = state.timeline; this.timeline = state.timeline;
this.playlistMetadata = state.playlistMetadata; this.playlistMetadata = state.playlistMetadata;
this.currentMediaItemIndex = state.currentMediaItemIndex; this.currentMediaItemIndex = state.currentMediaItemIndex;
this.currentPeriodIndex = state.currentPeriodIndex;
this.currentAdGroupIndex = state.currentAdGroupIndex; this.currentAdGroupIndex = state.currentAdGroupIndex;
this.currentAdIndexInAdGroup = state.currentAdIndexInAdGroup; this.currentAdIndexInAdGroup = state.currentAdIndexInAdGroup;
this.contentPositionMs = C.TIME_UNSET; this.contentPositionMs = null;
this.contentPositionMsSupplier = state.contentPositionMsSupplier; this.contentPositionMsSupplier = state.contentPositionMsSupplier;
this.adPositionMs = C.TIME_UNSET; this.adPositionMs = null;
this.adPositionMsSupplier = state.adPositionMsSupplier; this.adPositionMsSupplier = state.adPositionMsSupplier;
this.contentBufferedPositionMsSupplier = state.contentBufferedPositionMsSupplier; this.contentBufferedPositionMsSupplier = state.contentBufferedPositionMsSupplier;
this.adBufferedPositionMsSupplier = state.adBufferedPositionMsSupplier; this.adBufferedPositionMsSupplier = state.adBufferedPositionMsSupplier;
...@@ -577,7 +575,8 @@ public abstract class SimpleBasePlayer extends BasePlayer { ...@@ -577,7 +575,8 @@ public abstract class SimpleBasePlayer extends BasePlayer {
* <p>The media item index must be less than the number of {@linkplain #setPlaylist media * <p>The media item index must be less than the number of {@linkplain #setPlaylist media
* items in the playlist}, if set. * items in the playlist}, if set.
* *
* @param currentMediaItemIndex The current media item index. * @param currentMediaItemIndex The current media item index, or {@link C#INDEX_UNSET} to
* assume the default first item in the playlist.
* @return This builder. * @return This builder.
*/ */
@CanIgnoreReturnValue @CanIgnoreReturnValue
...@@ -587,26 +586,6 @@ public abstract class SimpleBasePlayer extends BasePlayer { ...@@ -587,26 +586,6 @@ public abstract class SimpleBasePlayer extends BasePlayer {
} }
/** /**
* Sets the current period index, or {@link C#INDEX_UNSET} to assume the first period of the
* current media item is played.
*
* <p>The period index must be less than the total number of {@linkplain
* MediaItemData.Builder#setPeriods periods} in the media item, if set, and the period at the
* specified index must be part of the {@linkplain #setCurrentMediaItemIndex current media
* item}.
*
* @param currentPeriodIndex The current period index, or {@link C#INDEX_UNSET} to assume the
* first period of the current media item is played.
* @return This builder.
*/
@CanIgnoreReturnValue
public Builder setCurrentPeriodIndex(int currentPeriodIndex) {
checkArgument(currentPeriodIndex == C.INDEX_UNSET || currentPeriodIndex >= 0);
this.currentPeriodIndex = currentPeriodIndex;
return this;
}
/**
* Sets the current ad indices, or {@link C#INDEX_UNSET} if no ad is playing. * Sets the current ad indices, or {@link C#INDEX_UNSET} if no ad is playing.
* *
* <p>Either both indices need to be {@link C#INDEX_UNSET} or both are not {@link * <p>Either both indices need to be {@link C#INDEX_UNSET} or both are not {@link
...@@ -635,7 +614,11 @@ public abstract class SimpleBasePlayer extends BasePlayer { ...@@ -635,7 +614,11 @@ public abstract class SimpleBasePlayer extends BasePlayer {
* <p>This position will be converted to an advancing {@link PositionSupplier} if the overall * <p>This position will be converted to an advancing {@link PositionSupplier} if the overall
* state indicates an advancing playback position. * state indicates an advancing playback position.
* *
* @param positionMs The current content playback position in milliseconds. * <p>This method overrides any other {@link PositionSupplier} set via {@link
* #setContentPositionMs(PositionSupplier)}.
*
* @param positionMs The current content playback position in milliseconds, or {@link
* C#TIME_UNSET} to indicate the default start position.
* @return This builder. * @return This builder.
*/ */
@CanIgnoreReturnValue @CanIgnoreReturnValue
...@@ -651,24 +634,30 @@ public abstract class SimpleBasePlayer extends BasePlayer { ...@@ -651,24 +634,30 @@ public abstract class SimpleBasePlayer extends BasePlayer {
* <p>The supplier is expected to return the updated position on every call if the playback is * <p>The supplier is expected to return the updated position on every call if the playback is
* advancing, for example by using {@link PositionSupplier#getExtrapolating}. * advancing, for example by using {@link PositionSupplier#getExtrapolating}.
* *
* <p>This method overrides any other position set via {@link #setContentPositionMs(long)}.
*
* @param contentPositionMsSupplier The {@link PositionSupplier} for the current content * @param contentPositionMsSupplier The {@link PositionSupplier} for the current content
* playback position in milliseconds. * playback position in milliseconds, or {@link C#TIME_UNSET} to indicate the default
* start position.
* @return This builder. * @return This builder.
*/ */
@CanIgnoreReturnValue @CanIgnoreReturnValue
public Builder setContentPositionMs(PositionSupplier contentPositionMsSupplier) { public Builder setContentPositionMs(PositionSupplier contentPositionMsSupplier) {
this.contentPositionMs = C.TIME_UNSET; this.contentPositionMs = null;
this.contentPositionMsSupplier = contentPositionMsSupplier; this.contentPositionMsSupplier = contentPositionMsSupplier;
return this; return this;
} }
/** /**
* Sets the current ad playback position in milliseconds. The * value is unused if no ad is * Sets the current ad playback position in milliseconds. The value is unused if no ad is
* playing. * playing.
* *
* <p>This position will be converted to an advancing {@link PositionSupplier} if the overall * <p>This position will be converted to an advancing {@link PositionSupplier} if the overall
* state indicates an advancing ad playback position. * state indicates an advancing ad playback position.
* *
* <p>This method overrides any other {@link PositionSupplier} set via {@link
* #setAdPositionMs(PositionSupplier)}.
*
* @param positionMs The current ad playback position in milliseconds. * @param positionMs The current ad playback position in milliseconds.
* @return This builder. * @return This builder.
*/ */
...@@ -685,13 +674,15 @@ public abstract class SimpleBasePlayer extends BasePlayer { ...@@ -685,13 +674,15 @@ public abstract class SimpleBasePlayer extends BasePlayer {
* <p>The supplier is expected to return the updated position on every call if the playback is * <p>The supplier is expected to return the updated position on every call if the playback is
* advancing, for example by using {@link PositionSupplier#getExtrapolating}. * advancing, for example by using {@link PositionSupplier#getExtrapolating}.
* *
* <p>This method overrides any other position set via {@link #setAdPositionMs(long)}.
*
* @param adPositionMsSupplier The {@link PositionSupplier} for the current ad playback * @param adPositionMsSupplier The {@link PositionSupplier} for the current ad playback
* position in milliseconds. The value is unused if no ad is playing. * position in milliseconds. The value is unused if no ad is playing.
* @return This builder. * @return This builder.
*/ */
@CanIgnoreReturnValue @CanIgnoreReturnValue
public Builder setAdPositionMs(PositionSupplier adPositionMsSupplier) { public Builder setAdPositionMs(PositionSupplier adPositionMsSupplier) {
this.adPositionMs = C.TIME_UNSET; this.adPositionMs = null;
this.adPositionMsSupplier = adPositionMsSupplier; this.adPositionMsSupplier = adPositionMsSupplier;
return this; return this;
} }
...@@ -701,7 +692,8 @@ public abstract class SimpleBasePlayer extends BasePlayer { ...@@ -701,7 +692,8 @@ public abstract class SimpleBasePlayer extends BasePlayer {
* playing content is buffered, in milliseconds. * playing content is buffered, in milliseconds.
* *
* @param contentBufferedPositionMsSupplier The {@link PositionSupplier} for the estimated * @param contentBufferedPositionMsSupplier The {@link PositionSupplier} for the estimated
* position up to which the currently playing content is buffered, in milliseconds. * position up to which the currently playing content is buffered, in milliseconds, or
* {@link C#TIME_UNSET} to indicate the default start position.
* @return This builder. * @return This builder.
*/ */
@CanIgnoreReturnValue @CanIgnoreReturnValue
...@@ -841,18 +833,19 @@ public abstract class SimpleBasePlayer extends BasePlayer { ...@@ -841,18 +833,19 @@ public abstract class SimpleBasePlayer extends BasePlayer {
public final Timeline timeline; public final Timeline timeline;
/** The playlist {@link MediaMetadata}. */ /** The playlist {@link MediaMetadata}. */
public final MediaMetadata playlistMetadata; public final MediaMetadata playlistMetadata;
/** The current media item index. */
public final int currentMediaItemIndex;
/** /**
* The current period index, or {@link C#INDEX_UNSET} to assume the first period of the current * The current media item index, or {@link C#INDEX_UNSET} to assume the default first item of
* media item is played. * the playlist is played.
*/ */
public final int currentPeriodIndex; public final int currentMediaItemIndex;
/** The current ad group index, or {@link C#INDEX_UNSET} if no ad is playing. */ /** The current ad group index, or {@link C#INDEX_UNSET} if no ad is playing. */
public final int currentAdGroupIndex; public final int currentAdGroupIndex;
/** The current ad index in the ad group, or {@link C#INDEX_UNSET} if no ad is playing. */ /** The current ad index in the ad group, or {@link C#INDEX_UNSET} if no ad is playing. */
public final int currentAdIndexInAdGroup; public final int currentAdIndexInAdGroup;
/** The {@link PositionSupplier} for the current content playback position in milliseconds. */ /**
* The {@link PositionSupplier} for the current content playback position in milliseconds, or
* {@link C#TIME_UNSET} to indicate the default start position.
*/
public final PositionSupplier contentPositionMsSupplier; public final PositionSupplier contentPositionMsSupplier;
/** /**
* The {@link PositionSupplier} for the current ad playback position in milliseconds. The value * The {@link PositionSupplier} for the current ad playback position in milliseconds. The value
...@@ -861,7 +854,8 @@ public abstract class SimpleBasePlayer extends BasePlayer { ...@@ -861,7 +854,8 @@ public abstract class SimpleBasePlayer extends BasePlayer {
public final PositionSupplier adPositionMsSupplier; public final PositionSupplier adPositionMsSupplier;
/** /**
* The {@link PositionSupplier} for the estimated position up to which the currently playing * The {@link PositionSupplier} for the estimated position up to which the currently playing
* content is buffered, in milliseconds. * content is buffered, in milliseconds, or {@link C#TIME_UNSET} to indicate the default start
* position.
*/ */
public final PositionSupplier contentBufferedPositionMsSupplier; public final PositionSupplier contentBufferedPositionMsSupplier;
/** /**
...@@ -890,22 +884,27 @@ public abstract class SimpleBasePlayer extends BasePlayer { ...@@ -890,22 +884,27 @@ public abstract class SimpleBasePlayer extends BasePlayer {
checkArgument( checkArgument(
builder.playbackState == Player.STATE_IDLE builder.playbackState == Player.STATE_IDLE
|| builder.playbackState == Player.STATE_ENDED); || builder.playbackState == Player.STATE_ENDED);
checkArgument(
builder.currentAdGroupIndex == C.INDEX_UNSET
&& builder.currentAdIndexInAdGroup == C.INDEX_UNSET);
} else { } else {
checkArgument(builder.currentMediaItemIndex < builder.timeline.getWindowCount()); int mediaItemIndex = builder.currentMediaItemIndex;
if (builder.currentPeriodIndex != C.INDEX_UNSET) { if (mediaItemIndex == C.INDEX_UNSET) {
checkArgument(builder.currentPeriodIndex < builder.timeline.getPeriodCount()); mediaItemIndex = 0; // TODO: Use shuffle order to find first index.
checkArgument( } else {
builder.timeline.getPeriod(builder.currentPeriodIndex, new Timeline.Period()) checkArgument(builder.currentMediaItemIndex < builder.timeline.getWindowCount());
.windowIndex
== builder.currentMediaItemIndex);
} }
if (builder.currentAdGroupIndex != C.INDEX_UNSET) { if (builder.currentAdGroupIndex != C.INDEX_UNSET) {
Timeline.Period period = new Timeline.Period();
Timeline.Window window = new Timeline.Window();
long contentPositionMs =
builder.contentPositionMs != null
? builder.contentPositionMs
: builder.contentPositionMsSupplier.get();
int periodIndex = int periodIndex =
builder.currentPeriodIndex != C.INDEX_UNSET getPeriodIndexFromWindowPosition(
? builder.currentPeriodIndex builder.timeline, mediaItemIndex, contentPositionMs, window, period);
: builder.timeline.getWindow(builder.currentMediaItemIndex, new Timeline.Window()) builder.timeline.getPeriod(periodIndex, period);
.firstPeriodIndex;
Timeline.Period period = builder.timeline.getPeriod(periodIndex, new Timeline.Period());
checkArgument(builder.currentAdGroupIndex < period.getAdGroupCount()); checkArgument(builder.currentAdGroupIndex < period.getAdGroupCount());
int adCountInGroup = period.getAdCountInAdGroup(builder.currentAdGroupIndex); int adCountInGroup = period.getAdCountInAdGroup(builder.currentAdGroupIndex);
if (adCountInGroup != C.LENGTH_UNSET) { if (adCountInGroup != C.LENGTH_UNSET) {
...@@ -921,11 +920,12 @@ public abstract class SimpleBasePlayer extends BasePlayer { ...@@ -921,11 +920,12 @@ public abstract class SimpleBasePlayer extends BasePlayer {
checkArgument(!builder.isLoading); checkArgument(!builder.isLoading);
} }
PositionSupplier contentPositionMsSupplier = builder.contentPositionMsSupplier; PositionSupplier contentPositionMsSupplier = builder.contentPositionMsSupplier;
if (builder.contentPositionMs != C.TIME_UNSET) { if (builder.contentPositionMs != null) {
if (builder.currentAdGroupIndex == C.INDEX_UNSET if (builder.currentAdGroupIndex == C.INDEX_UNSET
&& builder.playWhenReady && builder.playWhenReady
&& builder.playbackState == Player.STATE_READY && builder.playbackState == Player.STATE_READY
&& builder.playbackSuppressionReason == Player.PLAYBACK_SUPPRESSION_REASON_NONE) { && builder.playbackSuppressionReason == Player.PLAYBACK_SUPPRESSION_REASON_NONE
&& builder.contentPositionMs != C.TIME_UNSET) {
contentPositionMsSupplier = contentPositionMsSupplier =
PositionSupplier.getExtrapolating( PositionSupplier.getExtrapolating(
builder.contentPositionMs, builder.playbackParameters.speed); builder.contentPositionMs, builder.playbackParameters.speed);
...@@ -934,7 +934,7 @@ public abstract class SimpleBasePlayer extends BasePlayer { ...@@ -934,7 +934,7 @@ public abstract class SimpleBasePlayer extends BasePlayer {
} }
} }
PositionSupplier adPositionMsSupplier = builder.adPositionMsSupplier; PositionSupplier adPositionMsSupplier = builder.adPositionMsSupplier;
if (builder.adPositionMs != C.TIME_UNSET) { if (builder.adPositionMs != null) {
if (builder.currentAdGroupIndex != C.INDEX_UNSET if (builder.currentAdGroupIndex != C.INDEX_UNSET
&& builder.playWhenReady && builder.playWhenReady
&& builder.playbackState == Player.STATE_READY && builder.playbackState == Player.STATE_READY
...@@ -973,7 +973,6 @@ public abstract class SimpleBasePlayer extends BasePlayer { ...@@ -973,7 +973,6 @@ public abstract class SimpleBasePlayer extends BasePlayer {
this.timeline = builder.timeline; this.timeline = builder.timeline;
this.playlistMetadata = builder.playlistMetadata; this.playlistMetadata = builder.playlistMetadata;
this.currentMediaItemIndex = builder.currentMediaItemIndex; this.currentMediaItemIndex = builder.currentMediaItemIndex;
this.currentPeriodIndex = builder.currentPeriodIndex;
this.currentAdGroupIndex = builder.currentAdGroupIndex; this.currentAdGroupIndex = builder.currentAdGroupIndex;
this.currentAdIndexInAdGroup = builder.currentAdIndexInAdGroup; this.currentAdIndexInAdGroup = builder.currentAdIndexInAdGroup;
this.contentPositionMsSupplier = contentPositionMsSupplier; this.contentPositionMsSupplier = contentPositionMsSupplier;
...@@ -1027,7 +1026,6 @@ public abstract class SimpleBasePlayer extends BasePlayer { ...@@ -1027,7 +1026,6 @@ public abstract class SimpleBasePlayer extends BasePlayer {
&& playlist.equals(state.playlist) && playlist.equals(state.playlist)
&& playlistMetadata.equals(state.playlistMetadata) && playlistMetadata.equals(state.playlistMetadata)
&& currentMediaItemIndex == state.currentMediaItemIndex && currentMediaItemIndex == state.currentMediaItemIndex
&& currentPeriodIndex == state.currentPeriodIndex
&& currentAdGroupIndex == state.currentAdGroupIndex && currentAdGroupIndex == state.currentAdGroupIndex
&& currentAdIndexInAdGroup == state.currentAdIndexInAdGroup && currentAdIndexInAdGroup == state.currentAdIndexInAdGroup
&& contentPositionMsSupplier.equals(state.contentPositionMsSupplier) && contentPositionMsSupplier.equals(state.contentPositionMsSupplier)
...@@ -1071,7 +1069,6 @@ public abstract class SimpleBasePlayer extends BasePlayer { ...@@ -1071,7 +1069,6 @@ public abstract class SimpleBasePlayer extends BasePlayer {
result = 31 * result + playlist.hashCode(); result = 31 * result + playlist.hashCode();
result = 31 * result + playlistMetadata.hashCode(); result = 31 * result + playlistMetadata.hashCode();
result = 31 * result + currentMediaItemIndex; result = 31 * result + currentMediaItemIndex;
result = 31 * result + currentPeriodIndex;
result = 31 * result + currentAdGroupIndex; result = 31 * result + currentAdGroupIndex;
result = 31 * result + currentAdIndexInAdGroup; result = 31 * result + currentAdIndexInAdGroup;
result = 31 * result + contentPositionMsSupplier.hashCode(); result = 31 * result + contentPositionMsSupplier.hashCode();
...@@ -2201,7 +2198,8 @@ public abstract class SimpleBasePlayer extends BasePlayer { ...@@ -2201,7 +2198,8 @@ public abstract class SimpleBasePlayer extends BasePlayer {
.buildUpon() .buildUpon()
.setPlaybackState(Player.STATE_IDLE) .setPlaybackState(Player.STATE_IDLE)
.setTotalBufferedDurationMs(PositionSupplier.ZERO) .setTotalBufferedDurationMs(PositionSupplier.ZERO)
.setContentBufferedPositionMs(state.contentPositionMsSupplier) .setContentBufferedPositionMs(
PositionSupplier.getConstant(getContentPositionMsInternal(state)))
.setAdBufferedPositionMs(state.adPositionMsSupplier) .setAdBufferedPositionMs(state.adPositionMsSupplier)
.setIsLoading(false) .setIsLoading(false)
.build()); .build());
...@@ -2233,7 +2231,8 @@ public abstract class SimpleBasePlayer extends BasePlayer { ...@@ -2233,7 +2231,8 @@ public abstract class SimpleBasePlayer extends BasePlayer {
.buildUpon() .buildUpon()
.setPlaybackState(Player.STATE_IDLE) .setPlaybackState(Player.STATE_IDLE)
.setTotalBufferedDurationMs(PositionSupplier.ZERO) .setTotalBufferedDurationMs(PositionSupplier.ZERO)
.setContentBufferedPositionMs(state.contentPositionMsSupplier) .setContentBufferedPositionMs(
PositionSupplier.getConstant(getContentPositionMsInternal(state)))
.setAdBufferedPositionMs(state.adPositionMsSupplier) .setAdBufferedPositionMs(state.adPositionMsSupplier)
.setIsLoading(false) .setIsLoading(false)
.build(); .build();
...@@ -2300,13 +2299,13 @@ public abstract class SimpleBasePlayer extends BasePlayer { ...@@ -2300,13 +2299,13 @@ public abstract class SimpleBasePlayer extends BasePlayer {
@Override @Override
public final int getCurrentPeriodIndex() { public final int getCurrentPeriodIndex() {
verifyApplicationThreadAndInitState(); verifyApplicationThreadAndInitState();
return getCurrentPeriodIndexInternal(state, window); return getCurrentPeriodIndexInternal(state, window, period);
} }
@Override @Override
public final int getCurrentMediaItemIndex() { public final int getCurrentMediaItemIndex() {
verifyApplicationThreadAndInitState(); verifyApplicationThreadAndInitState();
return state.currentMediaItemIndex; return getCurrentMediaItemIndexInternal(state);
} }
@Override @Override
...@@ -2362,14 +2361,13 @@ public abstract class SimpleBasePlayer extends BasePlayer { ...@@ -2362,14 +2361,13 @@ public abstract class SimpleBasePlayer extends BasePlayer {
@Override @Override
public final long getContentPosition() { public final long getContentPosition() {
verifyApplicationThreadAndInitState(); verifyApplicationThreadAndInitState();
return state.contentPositionMsSupplier.get(); return getContentPositionMsInternal(state);
} }
@Override @Override
public final long getContentBufferedPosition() { public final long getContentBufferedPosition() {
verifyApplicationThreadAndInitState(); verifyApplicationThreadAndInitState();
return max( return max(getContentBufferedPositionMsInternal(state), getContentPositionMsInternal(state));
state.contentBufferedPositionMsSupplier.get(), state.contentPositionMsSupplier.get());
} }
@Override @Override
...@@ -2942,7 +2940,7 @@ public abstract class SimpleBasePlayer extends BasePlayer { ...@@ -2942,7 +2940,7 @@ public abstract class SimpleBasePlayer extends BasePlayer {
MediaItem mediaItem = MediaItem mediaItem =
newState.timeline.isEmpty() newState.timeline.isEmpty()
? null ? null
: newState.playlist.get(state.currentMediaItemIndex).mediaItem; : newState.playlist.get(getCurrentMediaItemIndexInternal(newState)).mediaItem;
listeners.queueEvent( listeners.queueEvent(
Player.EVENT_MEDIA_ITEM_TRANSITION, Player.EVENT_MEDIA_ITEM_TRANSITION,
listener -> listener.onMediaItemTransition(mediaItem, mediaItemTransitionReason)); listener -> listener.onMediaItemTransition(mediaItem, mediaItemTransitionReason));
...@@ -3162,23 +3160,59 @@ public abstract class SimpleBasePlayer extends BasePlayer { ...@@ -3162,23 +3160,59 @@ public abstract class SimpleBasePlayer extends BasePlayer {
private static Tracks getCurrentTracksInternal(State state) { private static Tracks getCurrentTracksInternal(State state) {
return state.playlist.isEmpty() return state.playlist.isEmpty()
? Tracks.EMPTY ? Tracks.EMPTY
: state.playlist.get(state.currentMediaItemIndex).tracks; : state.playlist.get(getCurrentMediaItemIndexInternal(state)).tracks;
} }
private static MediaMetadata getMediaMetadataInternal(State state) { private static MediaMetadata getMediaMetadataInternal(State state) {
return state.playlist.isEmpty() return state.playlist.isEmpty()
? MediaMetadata.EMPTY ? MediaMetadata.EMPTY
: state.playlist.get(state.currentMediaItemIndex).combinedMediaMetadata; : state.playlist.get(getCurrentMediaItemIndexInternal(state)).combinedMediaMetadata;
}
private static int getCurrentMediaItemIndexInternal(State state) {
if (state.currentMediaItemIndex != C.INDEX_UNSET) {
return state.currentMediaItemIndex;
}
return 0; // TODO: Use shuffle order to get first item if playlist is not empty.
}
private static long getContentPositionMsInternal(State state) {
return getPositionOrDefaultInMediaItem(state.contentPositionMsSupplier.get(), state);
}
private static long getContentBufferedPositionMsInternal(State state) {
return getPositionOrDefaultInMediaItem(state.contentBufferedPositionMsSupplier.get(), state);
} }
private static int getCurrentPeriodIndexInternal(State state, Timeline.Window window) { private static long getPositionOrDefaultInMediaItem(long positionMs, State state) {
if (state.currentPeriodIndex != C.INDEX_UNSET) { if (positionMs != C.TIME_UNSET) {
return state.currentPeriodIndex; return positionMs;
}
if (state.playlist.isEmpty()) {
return 0;
} }
return usToMs(state.playlist.get(getCurrentMediaItemIndexInternal(state)).defaultPositionUs);
}
private static int getCurrentPeriodIndexInternal(
State state, Timeline.Window window, Timeline.Period period) {
int currentMediaItemIndex = getCurrentMediaItemIndexInternal(state);
if (state.timeline.isEmpty()) { if (state.timeline.isEmpty()) {
return state.currentMediaItemIndex; return currentMediaItemIndex;
} }
return state.timeline.getWindow(state.currentMediaItemIndex, window).firstPeriodIndex; return getPeriodIndexFromWindowPosition(
state.timeline, currentMediaItemIndex, getContentPositionMsInternal(state), window, period);
}
private static int getPeriodIndexFromWindowPosition(
Timeline timeline,
int windowIndex,
long windowPositionMs,
Timeline.Window window,
Timeline.Period period) {
Object periodUid =
timeline.getPeriodPositionUs(window, period, windowIndex, msToUs(windowPositionMs)).first;
return timeline.getIndexOfPeriod(periodUid);
} }
private static @Player.TimelineChangeReason int getTimelineChangeReason( private static @Player.TimelineChangeReason int getTimelineChangeReason(
...@@ -3209,9 +3243,10 @@ public abstract class SimpleBasePlayer extends BasePlayer { ...@@ -3209,9 +3243,10 @@ public abstract class SimpleBasePlayer extends BasePlayer {
return Player.DISCONTINUITY_REASON_REMOVE; return Player.DISCONTINUITY_REASON_REMOVE;
} }
Object previousPeriodUid = Object previousPeriodUid =
previousState.timeline.getUidOfPeriod(getCurrentPeriodIndexInternal(previousState, window)); previousState.timeline.getUidOfPeriod(
getCurrentPeriodIndexInternal(previousState, window, period));
Object newPeriodUid = Object newPeriodUid =
newState.timeline.getUidOfPeriod(getCurrentPeriodIndexInternal(newState, window)); newState.timeline.getUidOfPeriod(getCurrentPeriodIndexInternal(newState, window, period));
if (!newPeriodUid.equals(previousPeriodUid) if (!newPeriodUid.equals(previousPeriodUid)
|| previousState.currentAdGroupIndex != newState.currentAdGroupIndex || previousState.currentAdGroupIndex != newState.currentAdGroupIndex
|| previousState.currentAdIndexInAdGroup != newState.currentAdIndexInAdGroup) { || previousState.currentAdIndexInAdGroup != newState.currentAdIndexInAdGroup) {
...@@ -3247,7 +3282,7 @@ public abstract class SimpleBasePlayer extends BasePlayer { ...@@ -3247,7 +3282,7 @@ public abstract class SimpleBasePlayer extends BasePlayer {
State state, Object currentPeriodUid, Timeline.Period period) { State state, Object currentPeriodUid, Timeline.Period period) {
return state.currentAdGroupIndex != C.INDEX_UNSET return state.currentAdGroupIndex != C.INDEX_UNSET
? state.adPositionMsSupplier.get() ? state.adPositionMsSupplier.get()
: state.contentPositionMsSupplier.get() : getContentPositionMsInternal(state)
- state.timeline.getPeriodByUid(currentPeriodUid, period).getPositionInWindowMs(); - state.timeline.getPeriodByUid(currentPeriodUid, period).getPositionInWindowMs();
} }
...@@ -3268,11 +3303,11 @@ public abstract class SimpleBasePlayer extends BasePlayer { ...@@ -3268,11 +3303,11 @@ public abstract class SimpleBasePlayer extends BasePlayer {
Timeline.Period period) { Timeline.Period period) {
@Nullable Object windowUid = null; @Nullable Object windowUid = null;
@Nullable Object periodUid = null; @Nullable Object periodUid = null;
int mediaItemIndex = state.currentMediaItemIndex; int mediaItemIndex = getCurrentMediaItemIndexInternal(state);
int periodIndex = C.INDEX_UNSET; int periodIndex = C.INDEX_UNSET;
@Nullable MediaItem mediaItem = null; @Nullable MediaItem mediaItem = null;
if (!state.timeline.isEmpty()) { if (!state.timeline.isEmpty()) {
periodIndex = getCurrentPeriodIndexInternal(state, window); periodIndex = getCurrentPeriodIndexInternal(state, window, period);
periodUid = state.timeline.getPeriod(periodIndex, period, /* setIds= */ true).uid; periodUid = state.timeline.getPeriod(periodIndex, period, /* setIds= */ true).uid;
windowUid = state.timeline.getWindow(mediaItemIndex, window).uid; windowUid = state.timeline.getWindow(mediaItemIndex, window).uid;
mediaItem = window.mediaItem; mediaItem = window.mediaItem;
...@@ -3284,9 +3319,9 @@ public abstract class SimpleBasePlayer extends BasePlayer { ...@@ -3284,9 +3319,9 @@ public abstract class SimpleBasePlayer extends BasePlayer {
contentPositionMs = contentPositionMs =
state.currentAdGroupIndex == C.INDEX_UNSET state.currentAdGroupIndex == C.INDEX_UNSET
? positionMs ? positionMs
: state.contentPositionMsSupplier.get(); : getContentPositionMsInternal(state);
} else { } else {
contentPositionMs = state.contentPositionMsSupplier.get(); contentPositionMs = getContentPositionMsInternal(state);
positionMs = positionMs =
state.currentAdGroupIndex != C.INDEX_UNSET state.currentAdGroupIndex != C.INDEX_UNSET
? state.adPositionMsSupplier.get() ? state.adPositionMsSupplier.get()
...@@ -3317,8 +3352,10 @@ public abstract class SimpleBasePlayer extends BasePlayer { ...@@ -3317,8 +3352,10 @@ public abstract class SimpleBasePlayer extends BasePlayer {
return MEDIA_ITEM_TRANSITION_REASON_PLAYLIST_CHANGED; return MEDIA_ITEM_TRANSITION_REASON_PLAYLIST_CHANGED;
} }
Object previousWindowUid = Object previousWindowUid =
previousState.timeline.getWindow(previousState.currentMediaItemIndex, window).uid; previousState.timeline.getWindow(getCurrentMediaItemIndexInternal(previousState), window)
Object newWindowUid = newState.timeline.getWindow(newState.currentMediaItemIndex, window).uid; .uid;
Object newWindowUid =
newState.timeline.getWindow(getCurrentMediaItemIndexInternal(newState), window).uid;
if (!previousWindowUid.equals(newWindowUid)) { if (!previousWindowUid.equals(newWindowUid)) {
if (positionDiscontinuityReason == DISCONTINUITY_REASON_AUTO_TRANSITION) { if (positionDiscontinuityReason == DISCONTINUITY_REASON_AUTO_TRANSITION) {
return MEDIA_ITEM_TRANSITION_REASON_AUTO; return MEDIA_ITEM_TRANSITION_REASON_AUTO;
...@@ -3331,8 +3368,7 @@ public abstract class SimpleBasePlayer extends BasePlayer { ...@@ -3331,8 +3368,7 @@ public abstract class SimpleBasePlayer extends BasePlayer {
// Only mark changes within the current item as a transition if we are repeating automatically // Only mark changes within the current item as a transition if we are repeating automatically
// or via a seek to next/previous. // or via a seek to next/previous.
if (positionDiscontinuityReason == DISCONTINUITY_REASON_AUTO_TRANSITION if (positionDiscontinuityReason == DISCONTINUITY_REASON_AUTO_TRANSITION
&& previousState.contentPositionMsSupplier.get() && getContentPositionMsInternal(previousState) > getContentPositionMsInternal(newState)) {
> newState.contentPositionMsSupplier.get()) {
return MEDIA_ITEM_TRANSITION_REASON_REPEAT; return MEDIA_ITEM_TRANSITION_REASON_REPEAT;
} }
if (positionDiscontinuityReason == DISCONTINUITY_REASON_SEEK if (positionDiscontinuityReason == DISCONTINUITY_REASON_SEEK
......
...@@ -135,7 +135,6 @@ public class SimpleBasePlayerTest { ...@@ -135,7 +135,6 @@ public class SimpleBasePlayerTest {
.build())) .build()))
.setPlaylistMetadata(new MediaMetadata.Builder().setArtist("artist").build()) .setPlaylistMetadata(new MediaMetadata.Builder().setArtist("artist").build())
.setCurrentMediaItemIndex(1) .setCurrentMediaItemIndex(1)
.setCurrentPeriodIndex(1)
.setCurrentAd(/* adGroupIndex= */ 1, /* adIndexInAdGroup= */ 2) .setCurrentAd(/* adGroupIndex= */ 1, /* adIndexInAdGroup= */ 2)
.setContentPositionMs(() -> 456) .setContentPositionMs(() -> 456)
.setAdPositionMs(() -> 6678) .setAdPositionMs(() -> 6678)
...@@ -282,7 +281,6 @@ public class SimpleBasePlayerTest { ...@@ -282,7 +281,6 @@ public class SimpleBasePlayerTest {
.setPlaylist(playlist) .setPlaylist(playlist)
.setPlaylistMetadata(playlistMetadata) .setPlaylistMetadata(playlistMetadata)
.setCurrentMediaItemIndex(1) .setCurrentMediaItemIndex(1)
.setCurrentPeriodIndex(1)
.setCurrentAd(/* adGroupIndex= */ 1, /* adIndexInAdGroup= */ 2) .setCurrentAd(/* adGroupIndex= */ 1, /* adIndexInAdGroup= */ 2)
.setContentPositionMs(contentPositionSupplier) .setContentPositionMs(contentPositionSupplier)
.setAdPositionMs(adPositionSupplier) .setAdPositionMs(adPositionSupplier)
...@@ -322,7 +320,6 @@ public class SimpleBasePlayerTest { ...@@ -322,7 +320,6 @@ public class SimpleBasePlayerTest {
assertThat(state.playlist).isEqualTo(playlist); assertThat(state.playlist).isEqualTo(playlist);
assertThat(state.playlistMetadata).isEqualTo(playlistMetadata); assertThat(state.playlistMetadata).isEqualTo(playlistMetadata);
assertThat(state.currentMediaItemIndex).isEqualTo(1); assertThat(state.currentMediaItemIndex).isEqualTo(1);
assertThat(state.currentPeriodIndex).isEqualTo(1);
assertThat(state.currentAdGroupIndex).isEqualTo(1); assertThat(state.currentAdGroupIndex).isEqualTo(1);
assertThat(state.currentAdIndexInAdGroup).isEqualTo(2); assertThat(state.currentAdIndexInAdGroup).isEqualTo(2);
assertThat(state.contentPositionMsSupplier).isEqualTo(contentPositionSupplier); assertThat(state.contentPositionMsSupplier).isEqualTo(contentPositionSupplier);
...@@ -369,37 +366,32 @@ public class SimpleBasePlayerTest { ...@@ -369,37 +366,32 @@ public class SimpleBasePlayerTest {
} }
@Test @Test
public void stateBuilderBuild_currentWindowIndexExceedsPlaylistLength_throwsException() { public void stateBuilderBuild_currentMediaItemIndexUnset_doesNotThrow() {
assertThrows( SimpleBasePlayer.State state =
IllegalArgumentException.class, new SimpleBasePlayer.State.Builder()
() -> .setPlaylist(
new SimpleBasePlayer.State.Builder() ImmutableList.of(
.setPlaylist( new SimpleBasePlayer.MediaItemData.Builder(/* uid= */ new Object()).build(),
ImmutableList.of( new SimpleBasePlayer.MediaItemData.Builder(/* uid= */ new Object()).build()))
new SimpleBasePlayer.MediaItemData.Builder(/* uid= */ new Object()).build(), .setCurrentMediaItemIndex(C.INDEX_UNSET)
new SimpleBasePlayer.MediaItemData.Builder(/* uid= */ new Object()) .build();
.build()))
.setCurrentMediaItemIndex(2) assertThat(state.currentMediaItemIndex).isEqualTo(C.INDEX_UNSET);
.build());
} }
@Test @Test
public void stateBuilderBuild_currentPeriodIndexExceedsPlaylistLength_throwsException() { public void stateBuilderBuild_currentMediaItemIndexSetForEmptyPlaylist_doesNotThrow() {
assertThrows( SimpleBasePlayer.State state =
IllegalArgumentException.class, new SimpleBasePlayer.State.Builder()
() -> .setPlaylist(ImmutableList.of())
new SimpleBasePlayer.State.Builder() .setCurrentMediaItemIndex(20)
.setPlaylist( .build();
ImmutableList.of(
new SimpleBasePlayer.MediaItemData.Builder(/* uid= */ new Object()).build(), assertThat(state.currentMediaItemIndex).isEqualTo(20);
new SimpleBasePlayer.MediaItemData.Builder(/* uid= */ new Object())
.build()))
.setCurrentPeriodIndex(2)
.build());
} }
@Test @Test
public void stateBuilderBuild_currentPeriodIndexInOtherMediaItem_throwsException() { public void stateBuilderBuild_currentMediaItemIndexExceedsPlaylistLength_throwsException() {
assertThrows( assertThrows(
IllegalArgumentException.class, IllegalArgumentException.class,
() -> () ->
...@@ -409,8 +401,7 @@ public class SimpleBasePlayerTest { ...@@ -409,8 +401,7 @@ public class SimpleBasePlayerTest {
new SimpleBasePlayer.MediaItemData.Builder(/* uid= */ new Object()).build(), new SimpleBasePlayer.MediaItemData.Builder(/* uid= */ new Object()).build(),
new SimpleBasePlayer.MediaItemData.Builder(/* uid= */ new Object()) new SimpleBasePlayer.MediaItemData.Builder(/* uid= */ new Object())
.build())) .build()))
.setCurrentMediaItemIndex(0) .setCurrentMediaItemIndex(2)
.setCurrentPeriodIndex(1)
.build()); .build());
} }
...@@ -461,6 +452,16 @@ public class SimpleBasePlayerTest { ...@@ -461,6 +452,16 @@ public class SimpleBasePlayerTest {
} }
@Test @Test
public void stateBuilderBuild_setAdAndEmptyPlaylist_throwsException() {
assertThrows(
IllegalArgumentException.class,
() ->
new SimpleBasePlayer.State.Builder()
.setCurrentAd(/* adGroupIndex= */ 1, /* adIndexInAdGroup= */ 3)
.build());
}
@Test
public void stateBuilderBuild_playerErrorInNonIdleState_throwsException() { public void stateBuilderBuild_playerErrorInNonIdleState_throwsException() {
assertThrows( assertThrows(
IllegalArgumentException.class, IllegalArgumentException.class,
...@@ -542,6 +543,27 @@ public class SimpleBasePlayerTest { ...@@ -542,6 +543,27 @@ public class SimpleBasePlayerTest {
} }
@Test @Test
public void stateBuilderBuild_withUnsetPositionAndPlaying_returnsConstantContentPosition() {
SystemClock.setCurrentTimeMillis(10000);
SimpleBasePlayer.State state =
new SimpleBasePlayer.State.Builder()
.setPlaylist(
ImmutableList.of(
new SimpleBasePlayer.MediaItemData.Builder(/* uid= */ new Object()).build()))
.setContentPositionMs(C.TIME_UNSET)
.setPlayWhenReady(true, Player.PLAY_WHEN_READY_CHANGE_REASON_USER_REQUEST)
.setPlaybackState(Player.STATE_READY)
.build();
long position1 = state.contentPositionMsSupplier.get();
SystemClock.setCurrentTimeMillis(12000);
long position2 = state.contentPositionMsSupplier.get();
assertThat(position1).isEqualTo(C.TIME_UNSET);
assertThat(position2).isEqualTo(C.TIME_UNSET);
}
@Test
public void stateBuilderBuild_returnsConstantContentPositionWhenNotPlaying() { public void stateBuilderBuild_returnsConstantContentPositionWhenNotPlaying() {
SystemClock.setCurrentTimeMillis(10000); SystemClock.setCurrentTimeMillis(10000);
...@@ -872,7 +894,6 @@ public class SimpleBasePlayerTest { ...@@ -872,7 +894,6 @@ public class SimpleBasePlayerTest {
.setPlaylist(playlist) .setPlaylist(playlist)
.setPlaylistMetadata(playlistMetadata) .setPlaylistMetadata(playlistMetadata)
.setCurrentMediaItemIndex(1) .setCurrentMediaItemIndex(1)
.setCurrentPeriodIndex(1)
.setContentPositionMs(contentPositionSupplier) .setContentPositionMs(contentPositionSupplier)
.setContentBufferedPositionMs(contentBufferedPositionSupplier) .setContentBufferedPositionMs(contentBufferedPositionSupplier)
.setTotalBufferedDurationMs(totalBufferedPositionSupplier) .setTotalBufferedDurationMs(totalBufferedPositionSupplier)
...@@ -1056,6 +1077,131 @@ public class SimpleBasePlayerTest { ...@@ -1056,6 +1077,131 @@ public class SimpleBasePlayerTest {
assertThat(player.getCurrentMediaItemIndex()).isEqualTo(4); assertThat(player.getCurrentMediaItemIndex()).isEqualTo(4);
} }
@Test
public void getCurrentMediaItemIndex_withUnsetIndexInState_returnsDefaultIndex() {
State state = new State.Builder().setCurrentMediaItemIndex(C.INDEX_UNSET).build();
SimpleBasePlayer player =
new SimpleBasePlayer(Looper.myLooper()) {
@Override
protected State getState() {
return state;
}
};
assertThat(player.getCurrentMediaItemIndex()).isEqualTo(0);
}
@Test
public void getCurrentPeriodIndex_withUnsetIndexInState_returnsPeriodForCurrentPosition() {
State state =
new State.Builder()
.setPlaylist(
ImmutableList.of(
new SimpleBasePlayer.MediaItemData.Builder(/* uid= */ 0).build(),
new SimpleBasePlayer.MediaItemData.Builder(/* uid= */ 1)
.setPeriods(
ImmutableList.of(
new SimpleBasePlayer.PeriodData.Builder(/* uid= */ "period0")
.setDurationUs(60_000_000)
.build(),
new SimpleBasePlayer.PeriodData.Builder(/* uid= */ "period1")
.setDurationUs(5_000_000)
.build(),
new SimpleBasePlayer.PeriodData.Builder(/* uid= */ "period2")
.setDurationUs(5_000_000)
.build()))
.setPositionInFirstPeriodUs(50_000_000)
.build(),
new SimpleBasePlayer.MediaItemData.Builder(/* uid= */ 2).build()))
.setCurrentMediaItemIndex(1)
.setContentPositionMs(12_000)
.build();
SimpleBasePlayer player =
new SimpleBasePlayer(Looper.myLooper()) {
@Override
protected State getState() {
return state;
}
};
assertThat(player.getCurrentPeriodIndex()).isEqualTo(2);
}
@Test
public void getCurrentPosition_withUnsetPositionInState_returnsDefaultPosition() {
State state =
new State.Builder()
.setPlaylist(
ImmutableList.of(
new SimpleBasePlayer.MediaItemData.Builder(/* uid= */ 0)
.setDefaultPositionUs(5_000_000)
.build()))
.setContentPositionMs(C.TIME_UNSET)
.build();
SimpleBasePlayer player =
new SimpleBasePlayer(Looper.myLooper()) {
@Override
protected State getState() {
return state;
}
};
assertThat(player.getCurrentPosition()).isEqualTo(5000);
}
@Test
public void getBufferedPosition_withUnsetBufferedPositionInState_returnsDefaultPosition() {
State state =
new State.Builder()
.setPlaylist(
ImmutableList.of(
new SimpleBasePlayer.MediaItemData.Builder(/* uid= */ 0)
.setDefaultPositionUs(5_000_000)
.build()))
.setContentBufferedPositionMs(
SimpleBasePlayer.PositionSupplier.getConstant(C.TIME_UNSET))
.build();
SimpleBasePlayer player =
new SimpleBasePlayer(Looper.myLooper()) {
@Override
protected State getState() {
return state;
}
};
assertThat(player.getBufferedPosition()).isEqualTo(5000);
}
@Test
public void
getBufferedPosition_withUnsetBufferedPositionAndPositionInState_returnsDefaultPosition() {
State state =
new State.Builder()
.setPlaylist(
ImmutableList.of(
new SimpleBasePlayer.MediaItemData.Builder(/* uid= */ 0)
.setDefaultPositionUs(5_000_000)
.build()))
.setContentPositionMs(C.TIME_UNSET)
.setContentBufferedPositionMs(
SimpleBasePlayer.PositionSupplier.getConstant(C.TIME_UNSET))
.build();
SimpleBasePlayer player =
new SimpleBasePlayer(Looper.myLooper()) {
@Override
protected State getState() {
return state;
}
};
assertThat(player.getBufferedPosition()).isEqualTo(5000);
}
@SuppressWarnings("deprecation") // Verifying deprecated listener call. @SuppressWarnings("deprecation") // Verifying deprecated listener call.
@Test @Test
public void invalidateState_updatesStateAndInformsListeners() throws Exception { public void invalidateState_updatesStateAndInformsListeners() throws Exception {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment