mirror of
https://github.com/samsonjs/media.git
synced 2026-04-02 10:45:51 +00:00
Merge branch 'dev-v2' of https://github.com/google/ExoPlayer into dev-v2
This commit is contained in:
commit
30cfc3c6c4
31 changed files with 1228 additions and 1019 deletions
|
|
@ -85,6 +85,10 @@
|
|||
* RTMP extension:
|
||||
* Upgrade to `io.antmedia:rtmp_client`, which does not rely on `jcenter()`
|
||||
([#9591](https://github.com/google/ExoPlayer/issues/9591)).
|
||||
* MediaSession extension:
|
||||
* Rename
|
||||
`MediaSessionConnector.QueueNavigator#onCurrentWindowIndexChanged` to
|
||||
`onCurrentMediaItemIndexChanged`.
|
||||
* Remove deprecated symbols:
|
||||
* Remove `Renderer.VIDEO_SCALING_MODE_*` constants. Use identically named
|
||||
constants in `C` instead.
|
||||
|
|
|
|||
|
|
@ -261,7 +261,7 @@ import java.util.ArrayList;
|
|||
int playbackState = currentPlayer.getPlaybackState();
|
||||
maybeSetCurrentItemAndNotify(
|
||||
playbackState != Player.STATE_IDLE && playbackState != Player.STATE_ENDED
|
||||
? currentPlayer.getCurrentWindowIndex()
|
||||
? currentPlayer.getCurrentMediaItemIndex()
|
||||
: C.INDEX_UNSET);
|
||||
}
|
||||
|
||||
|
|
@ -281,7 +281,7 @@ import java.util.ArrayList;
|
|||
|
||||
// Player state management.
|
||||
long playbackPositionMs = C.TIME_UNSET;
|
||||
int windowIndex = C.INDEX_UNSET;
|
||||
int currentItemIndex = C.INDEX_UNSET;
|
||||
boolean playWhenReady = false;
|
||||
|
||||
Player previousPlayer = this.currentPlayer;
|
||||
|
|
@ -291,10 +291,10 @@ import java.util.ArrayList;
|
|||
if (playbackState != Player.STATE_ENDED) {
|
||||
playbackPositionMs = previousPlayer.getCurrentPosition();
|
||||
playWhenReady = previousPlayer.getPlayWhenReady();
|
||||
windowIndex = previousPlayer.getCurrentWindowIndex();
|
||||
if (windowIndex != currentItemIndex) {
|
||||
currentItemIndex = previousPlayer.getCurrentMediaItemIndex();
|
||||
if (currentItemIndex != this.currentItemIndex) {
|
||||
playbackPositionMs = C.TIME_UNSET;
|
||||
windowIndex = currentItemIndex;
|
||||
currentItemIndex = this.currentItemIndex;
|
||||
}
|
||||
}
|
||||
previousPlayer.stop();
|
||||
|
|
@ -304,7 +304,7 @@ import java.util.ArrayList;
|
|||
this.currentPlayer = currentPlayer;
|
||||
|
||||
// Media queue management.
|
||||
currentPlayer.setMediaItems(mediaQueue, windowIndex, playbackPositionMs);
|
||||
currentPlayer.setMediaItems(mediaQueue, currentItemIndex, playbackPositionMs);
|
||||
currentPlayer.setPlayWhenReady(playWhenReady);
|
||||
currentPlayer.prepare();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ public class PlayerActivity extends AppCompatActivity
|
|||
// Saved instance state keys.
|
||||
|
||||
private static final String KEY_TRACK_SELECTION_PARAMETERS = "track_selection_parameters";
|
||||
private static final String KEY_WINDOW = "window";
|
||||
private static final String KEY_ITEM_INDEX = "item_index";
|
||||
private static final String KEY_POSITION = "position";
|
||||
private static final String KEY_AUTO_PLAY = "auto_play";
|
||||
|
||||
|
|
@ -83,7 +83,7 @@ public class PlayerActivity extends AppCompatActivity
|
|||
private DebugTextViewHelper debugViewHelper;
|
||||
private TracksInfo lastSeenTracksInfo;
|
||||
private boolean startAutoPlay;
|
||||
private int startWindow;
|
||||
private int startItemIndex;
|
||||
private long startPosition;
|
||||
|
||||
// For ad playback only.
|
||||
|
|
@ -114,7 +114,7 @@ public class PlayerActivity extends AppCompatActivity
|
|||
DefaultTrackSelector.Parameters.CREATOR.fromBundle(
|
||||
savedInstanceState.getBundle(KEY_TRACK_SELECTION_PARAMETERS));
|
||||
startAutoPlay = savedInstanceState.getBoolean(KEY_AUTO_PLAY);
|
||||
startWindow = savedInstanceState.getInt(KEY_WINDOW);
|
||||
startItemIndex = savedInstanceState.getInt(KEY_ITEM_INDEX);
|
||||
startPosition = savedInstanceState.getLong(KEY_POSITION);
|
||||
} else {
|
||||
trackSelectionParameters =
|
||||
|
|
@ -206,7 +206,7 @@ public class PlayerActivity extends AppCompatActivity
|
|||
updateStartPosition();
|
||||
outState.putBundle(KEY_TRACK_SELECTION_PARAMETERS, trackSelectionParameters.toBundle());
|
||||
outState.putBoolean(KEY_AUTO_PLAY, startAutoPlay);
|
||||
outState.putInt(KEY_WINDOW, startWindow);
|
||||
outState.putInt(KEY_ITEM_INDEX, startItemIndex);
|
||||
outState.putLong(KEY_POSITION, startPosition);
|
||||
}
|
||||
|
||||
|
|
@ -282,9 +282,9 @@ public class PlayerActivity extends AppCompatActivity
|
|||
debugViewHelper = new DebugTextViewHelper(player, debugTextView);
|
||||
debugViewHelper.start();
|
||||
}
|
||||
boolean haveStartPosition = startWindow != C.INDEX_UNSET;
|
||||
boolean haveStartPosition = startItemIndex != C.INDEX_UNSET;
|
||||
if (haveStartPosition) {
|
||||
player.seekTo(startWindow, startPosition);
|
||||
player.seekTo(startItemIndex, startPosition);
|
||||
}
|
||||
player.setMediaItems(mediaItems, /* resetPosition= */ !haveStartPosition);
|
||||
player.prepare();
|
||||
|
|
@ -382,14 +382,14 @@ public class PlayerActivity extends AppCompatActivity
|
|||
private void updateStartPosition() {
|
||||
if (player != null) {
|
||||
startAutoPlay = player.getPlayWhenReady();
|
||||
startWindow = player.getCurrentWindowIndex();
|
||||
startItemIndex = player.getCurrentMediaItemIndex();
|
||||
startPosition = Math.max(0, player.getContentPosition());
|
||||
}
|
||||
}
|
||||
|
||||
protected void clearStartPosition() {
|
||||
startAutoPlay = true;
|
||||
startWindow = C.INDEX_UNSET;
|
||||
startItemIndex = C.INDEX_UNSET;
|
||||
startPosition = C.TIME_UNSET;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -318,9 +318,9 @@ public final class CastPlayer extends BasePlayer {
|
|||
|
||||
@Override
|
||||
public void setMediaItems(List<MediaItem> mediaItems, boolean resetPosition) {
|
||||
int windowIndex = resetPosition ? 0 : getCurrentWindowIndex();
|
||||
int mediaItemIndex = resetPosition ? 0 : getCurrentMediaItemIndex();
|
||||
long startPositionMs = resetPosition ? C.TIME_UNSET : getContentPosition();
|
||||
setMediaItems(mediaItems, windowIndex, startPositionMs);
|
||||
setMediaItems(mediaItems, mediaItemIndex, startPositionMs);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -443,7 +443,7 @@ public final class CastPlayer extends BasePlayer {
|
|||
// in RemoteMediaClient.
|
||||
positionMs = positionMs != C.TIME_UNSET ? positionMs : 0;
|
||||
if (mediaStatus != null) {
|
||||
if (getCurrentWindowIndex() != mediaItemIndex) {
|
||||
if (getCurrentMediaItemIndex() != mediaItemIndex) {
|
||||
remoteMediaClient
|
||||
.queueJumpToItem(
|
||||
(int) currentTimeline.getPeriod(mediaItemIndex, period).uid, positionMs, null)
|
||||
|
|
@ -636,7 +636,7 @@ public final class CastPlayer extends BasePlayer {
|
|||
|
||||
@Override
|
||||
public int getCurrentPeriodIndex() {
|
||||
return getCurrentWindowIndex();
|
||||
return getCurrentMediaItemIndex();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -1103,15 +1103,15 @@ public final class CastPlayer extends BasePlayer {
|
|||
@Nullable
|
||||
private PendingResult<MediaChannelResult> setMediaItemsInternal(
|
||||
MediaQueueItem[] mediaQueueItems,
|
||||
int startWindowIndex,
|
||||
int startIndex,
|
||||
long startPositionMs,
|
||||
@RepeatMode int repeatMode) {
|
||||
if (remoteMediaClient == null || mediaQueueItems.length == 0) {
|
||||
return null;
|
||||
}
|
||||
startPositionMs = startPositionMs == C.TIME_UNSET ? 0 : startPositionMs;
|
||||
if (startWindowIndex == C.INDEX_UNSET) {
|
||||
startWindowIndex = getCurrentWindowIndex();
|
||||
if (startIndex == C.INDEX_UNSET) {
|
||||
startIndex = getCurrentMediaItemIndex();
|
||||
startPositionMs = getCurrentPosition();
|
||||
}
|
||||
Timeline currentTimeline = getCurrentTimeline();
|
||||
|
|
@ -1120,7 +1120,7 @@ public final class CastPlayer extends BasePlayer {
|
|||
}
|
||||
return remoteMediaClient.queueLoad(
|
||||
mediaQueueItems,
|
||||
min(startWindowIndex, mediaQueueItems.length - 1),
|
||||
min(startIndex, mediaQueueItems.length - 1),
|
||||
getCastRepeatMode(repeatMode),
|
||||
startPositionMs,
|
||||
/* customData= */ null);
|
||||
|
|
@ -1180,7 +1180,7 @@ public final class CastPlayer extends BasePlayer {
|
|||
}
|
||||
return new PositionInfo(
|
||||
newWindowUid,
|
||||
getCurrentWindowIndex(),
|
||||
getCurrentMediaItemIndex(),
|
||||
newMediaItem,
|
||||
newPeriodUid,
|
||||
getCurrentPeriodIndex(),
|
||||
|
|
|
|||
|
|
@ -279,7 +279,7 @@ import com.google.android.exoplayer2.util.Util;
|
|||
timeline.getPeriod(0, period).getAdDurationUs(adGroupIndex, adIndexInAdGroup);
|
||||
return Util.usToMs(adDurationUs);
|
||||
} else {
|
||||
return timeline.getWindow(getCurrentWindowIndex(), window).getDurationMs();
|
||||
return timeline.getWindow(getCurrentMediaItemIndex(), window).getDurationMs();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -141,7 +141,7 @@ public final class LeanbackPlayerAdapter extends PlayerAdapter implements Runnab
|
|||
if (player.getPlaybackState() == Player.STATE_IDLE) {
|
||||
player.prepare();
|
||||
} else if (player.getPlaybackState() == Player.STATE_ENDED) {
|
||||
player.seekToDefaultPosition(player.getCurrentWindowIndex());
|
||||
player.seekToDefaultPosition(player.getCurrentMediaItemIndex());
|
||||
}
|
||||
if (player.isCommandAvailable(Player.COMMAND_PLAY_PAUSE)) {
|
||||
player.play();
|
||||
|
|
|
|||
|
|
@ -253,8 +253,8 @@ import java.util.List;
|
|||
// checkIndex() throws IndexOutOfBoundsException which maps the RESULT_ERROR_BAD_VALUE
|
||||
// but RESULT_ERROR_INVALID_STATE with IllegalStateException is expected here.
|
||||
Assertions.checkState(0 <= index && index < timeline.getWindowCount());
|
||||
int windowIndex = player.getCurrentWindowIndex();
|
||||
if (windowIndex == index || !player.isCommandAvailable(COMMAND_SEEK_TO_MEDIA_ITEM)) {
|
||||
int currentIndex = player.getCurrentMediaItemIndex();
|
||||
if (currentIndex == index || !player.isCommandAvailable(COMMAND_SEEK_TO_MEDIA_ITEM)) {
|
||||
return false;
|
||||
}
|
||||
player.seekToDefaultPosition(index);
|
||||
|
|
@ -301,7 +301,7 @@ import java.util.List;
|
|||
}
|
||||
|
||||
public int getCurrentMediaItemIndex() {
|
||||
return media2Playlist.isEmpty() ? C.INDEX_UNSET : player.getCurrentWindowIndex();
|
||||
return media2Playlist.isEmpty() ? C.INDEX_UNSET : player.getCurrentMediaItemIndex();
|
||||
}
|
||||
|
||||
public int getPreviousMediaItemIndex() {
|
||||
|
|
@ -331,7 +331,7 @@ import java.util.List;
|
|||
if (!player.isCommandAvailable(COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM)) {
|
||||
return false;
|
||||
}
|
||||
player.seekTo(player.getCurrentWindowIndex(), /* positionMs= */ 0);
|
||||
player.seekTo(player.getCurrentMediaItemIndex(), /* positionMs= */ 0);
|
||||
}
|
||||
boolean playWhenReady = player.getPlayWhenReady();
|
||||
int suppressReason = player.getPlaybackSuppressionReason();
|
||||
|
|
@ -358,7 +358,7 @@ import java.util.List;
|
|||
if (!player.isCommandAvailable(COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM)) {
|
||||
return false;
|
||||
}
|
||||
player.seekTo(player.getCurrentWindowIndex(), position);
|
||||
player.seekTo(player.getCurrentMediaItemIndex(), position);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -493,7 +493,7 @@ import java.util.List;
|
|||
public boolean isCurrentMediaItemSeekable() {
|
||||
return getCurrentMediaItem() != null
|
||||
&& !player.isPlayingAd()
|
||||
&& player.isCurrentWindowSeekable();
|
||||
&& player.isCurrentMediaItemSeekable();
|
||||
}
|
||||
|
||||
public boolean canSkipToPlaylistItem() {
|
||||
|
|
@ -502,11 +502,11 @@ import java.util.List;
|
|||
}
|
||||
|
||||
public boolean canSkipToPreviousPlaylistItem() {
|
||||
return player.hasPreviousWindow();
|
||||
return player.hasPreviousMediaItem();
|
||||
}
|
||||
|
||||
public boolean canSkipToNextPlaylistItem() {
|
||||
return player.hasNextWindow();
|
||||
return player.hasNextMediaItem();
|
||||
}
|
||||
|
||||
public boolean hasError() {
|
||||
|
|
|
|||
|
|
@ -263,12 +263,13 @@ public final class MediaSessionConnector {
|
|||
* @param player The player connected to the media session.
|
||||
*/
|
||||
void onTimelineChanged(Player player);
|
||||
|
||||
/**
|
||||
* Called when the current window index changed.
|
||||
* Called when the current media item index changed.
|
||||
*
|
||||
* @param player The player connected to the media session.
|
||||
*/
|
||||
void onCurrentWindowIndexChanged(Player player);
|
||||
default void onCurrentMediaItemIndexChanged(Player player) {}
|
||||
/**
|
||||
* Gets the id of the currently active queue item, or {@link
|
||||
* MediaSessionCompat.QueueItem#UNKNOWN_ID} if the active item is unknown.
|
||||
|
|
@ -969,8 +970,8 @@ public final class MediaSessionConnector {
|
|||
return player != null && mediaButtonEventHandler != null;
|
||||
}
|
||||
|
||||
private void seekTo(Player player, int windowIndex, long positionMs) {
|
||||
player.seekTo(windowIndex, positionMs);
|
||||
private void seekTo(Player player, int mediaItemIndex, long positionMs) {
|
||||
player.seekTo(mediaItemIndex, positionMs);
|
||||
}
|
||||
|
||||
private static int getMediaSessionPlaybackState(
|
||||
|
|
@ -1023,7 +1024,7 @@ public final class MediaSessionConnector {
|
|||
}
|
||||
builder.putLong(
|
||||
MediaMetadataCompat.METADATA_KEY_DURATION,
|
||||
player.isCurrentWindowDynamic() || player.getDuration() == C.TIME_UNSET
|
||||
player.isCurrentMediaItemDynamic() || player.getDuration() == C.TIME_UNSET
|
||||
? -1
|
||||
: player.getDuration());
|
||||
long activeQueueItemId = mediaController.getPlaybackState().getActiveQueueItemId();
|
||||
|
|
@ -1097,7 +1098,7 @@ public final class MediaSessionConnector {
|
|||
|
||||
private class ComponentListener extends MediaSessionCompat.Callback implements Player.Listener {
|
||||
|
||||
private int currentWindowIndex;
|
||||
private int currentMediaItemIndex;
|
||||
private int currentWindowCount;
|
||||
|
||||
// Player.Listener implementation.
|
||||
|
|
@ -1107,9 +1108,9 @@ public final class MediaSessionConnector {
|
|||
boolean invalidatePlaybackState = false;
|
||||
boolean invalidateMetadata = false;
|
||||
if (events.contains(Player.EVENT_POSITION_DISCONTINUITY)) {
|
||||
if (currentWindowIndex != player.getCurrentWindowIndex()) {
|
||||
if (currentMediaItemIndex != player.getCurrentMediaItemIndex()) {
|
||||
if (queueNavigator != null) {
|
||||
queueNavigator.onCurrentWindowIndexChanged(player);
|
||||
queueNavigator.onCurrentMediaItemIndexChanged(player);
|
||||
}
|
||||
invalidateMetadata = true;
|
||||
}
|
||||
|
|
@ -1118,11 +1119,11 @@ public final class MediaSessionConnector {
|
|||
|
||||
if (events.contains(Player.EVENT_TIMELINE_CHANGED)) {
|
||||
int windowCount = player.getCurrentTimeline().getWindowCount();
|
||||
int windowIndex = player.getCurrentWindowIndex();
|
||||
int mediaItemIndex = player.getCurrentMediaItemIndex();
|
||||
if (queueNavigator != null) {
|
||||
queueNavigator.onTimelineChanged(player);
|
||||
invalidatePlaybackState = true;
|
||||
} else if (currentWindowCount != windowCount || currentWindowIndex != windowIndex) {
|
||||
} else if (currentWindowCount != windowCount || currentMediaItemIndex != mediaItemIndex) {
|
||||
// active queue item and queue navigation actions may need to be updated
|
||||
invalidatePlaybackState = true;
|
||||
}
|
||||
|
|
@ -1130,8 +1131,8 @@ public final class MediaSessionConnector {
|
|||
invalidateMetadata = true;
|
||||
}
|
||||
|
||||
// Update currentWindowIndex after comparisons above.
|
||||
currentWindowIndex = player.getCurrentWindowIndex();
|
||||
// Update currentMediaItemIndex after comparisons above.
|
||||
currentMediaItemIndex = player.getCurrentMediaItemIndex();
|
||||
|
||||
if (events.containsAny(
|
||||
EVENT_PLAYBACK_STATE_CHANGED,
|
||||
|
|
@ -1170,7 +1171,7 @@ public final class MediaSessionConnector {
|
|||
player.prepare();
|
||||
}
|
||||
} else if (player.getPlaybackState() == Player.STATE_ENDED) {
|
||||
seekTo(player, player.getCurrentWindowIndex(), C.TIME_UNSET);
|
||||
seekTo(player, player.getCurrentMediaItemIndex(), C.TIME_UNSET);
|
||||
}
|
||||
Assertions.checkNotNull(player).play();
|
||||
}
|
||||
|
|
@ -1186,7 +1187,7 @@ public final class MediaSessionConnector {
|
|||
@Override
|
||||
public void onSeekTo(long positionMs) {
|
||||
if (canDispatchPlaybackAction(PlaybackStateCompat.ACTION_SEEK_TO)) {
|
||||
seekTo(player, player.getCurrentWindowIndex(), positionMs);
|
||||
seekTo(player, player.getCurrentMediaItemIndex(), positionMs);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ public abstract class TimelineQueueNavigator implements MediaSessionConnector.Qu
|
|||
boolean enableNext = false;
|
||||
Timeline timeline = player.getCurrentTimeline();
|
||||
if (!timeline.isEmpty() && !player.isPlayingAd()) {
|
||||
timeline.getWindow(player.getCurrentWindowIndex(), window);
|
||||
timeline.getWindow(player.getCurrentMediaItemIndex(), window);
|
||||
enableSkipTo = timeline.getWindowCount() > 1;
|
||||
enablePrevious =
|
||||
player.isCommandAvailable(COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM)
|
||||
|
|
@ -128,12 +128,12 @@ public abstract class TimelineQueueNavigator implements MediaSessionConnector.Qu
|
|||
}
|
||||
|
||||
@Override
|
||||
public final void onCurrentWindowIndexChanged(Player player) {
|
||||
public final void onCurrentMediaItemIndexChanged(Player player) {
|
||||
if (activeQueueItemId == MediaSessionCompat.QueueItem.UNKNOWN_ID
|
||||
|| player.getCurrentTimeline().getWindowCount() > maxQueueSize) {
|
||||
publishFloatingQueueWindow(player);
|
||||
} else if (!player.getCurrentTimeline().isEmpty()) {
|
||||
activeQueueItemId = player.getCurrentWindowIndex();
|
||||
activeQueueItemId = player.getCurrentMediaItemIndex();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -185,40 +185,40 @@ public abstract class TimelineQueueNavigator implements MediaSessionConnector.Qu
|
|||
int queueSize = min(maxQueueSize, timeline.getWindowCount());
|
||||
|
||||
// Add the active queue item.
|
||||
int currentWindowIndex = player.getCurrentWindowIndex();
|
||||
int currentMediaItemIndex = player.getCurrentMediaItemIndex();
|
||||
queue.add(
|
||||
new MediaSessionCompat.QueueItem(
|
||||
getMediaDescription(player, currentWindowIndex), currentWindowIndex));
|
||||
getMediaDescription(player, currentMediaItemIndex), currentMediaItemIndex));
|
||||
|
||||
// Fill queue alternating with next and/or previous queue items.
|
||||
int firstWindowIndex = currentWindowIndex;
|
||||
int lastWindowIndex = currentWindowIndex;
|
||||
int firstMediaItemIndex = currentMediaItemIndex;
|
||||
int lastMediaItemIndex = currentMediaItemIndex;
|
||||
boolean shuffleModeEnabled = player.getShuffleModeEnabled();
|
||||
while ((firstWindowIndex != C.INDEX_UNSET || lastWindowIndex != C.INDEX_UNSET)
|
||||
while ((firstMediaItemIndex != C.INDEX_UNSET || lastMediaItemIndex != C.INDEX_UNSET)
|
||||
&& queue.size() < queueSize) {
|
||||
// Begin with next to have a longer tail than head if an even sized queue needs to be trimmed.
|
||||
if (lastWindowIndex != C.INDEX_UNSET) {
|
||||
lastWindowIndex =
|
||||
if (lastMediaItemIndex != C.INDEX_UNSET) {
|
||||
lastMediaItemIndex =
|
||||
timeline.getNextWindowIndex(
|
||||
lastWindowIndex, Player.REPEAT_MODE_OFF, shuffleModeEnabled);
|
||||
if (lastWindowIndex != C.INDEX_UNSET) {
|
||||
lastMediaItemIndex, Player.REPEAT_MODE_OFF, shuffleModeEnabled);
|
||||
if (lastMediaItemIndex != C.INDEX_UNSET) {
|
||||
queue.add(
|
||||
new MediaSessionCompat.QueueItem(
|
||||
getMediaDescription(player, lastWindowIndex), lastWindowIndex));
|
||||
getMediaDescription(player, lastMediaItemIndex), lastMediaItemIndex));
|
||||
}
|
||||
}
|
||||
if (firstWindowIndex != C.INDEX_UNSET && queue.size() < queueSize) {
|
||||
firstWindowIndex =
|
||||
if (firstMediaItemIndex != C.INDEX_UNSET && queue.size() < queueSize) {
|
||||
firstMediaItemIndex =
|
||||
timeline.getPreviousWindowIndex(
|
||||
firstWindowIndex, Player.REPEAT_MODE_OFF, shuffleModeEnabled);
|
||||
if (firstWindowIndex != C.INDEX_UNSET) {
|
||||
firstMediaItemIndex, Player.REPEAT_MODE_OFF, shuffleModeEnabled);
|
||||
if (firstMediaItemIndex != C.INDEX_UNSET) {
|
||||
queue.addFirst(
|
||||
new MediaSessionCompat.QueueItem(
|
||||
getMediaDescription(player, firstWindowIndex), firstWindowIndex));
|
||||
getMediaDescription(player, firstMediaItemIndex), firstMediaItemIndex));
|
||||
}
|
||||
}
|
||||
}
|
||||
mediaSession.setQueue(new ArrayList<>(queue));
|
||||
activeQueueItemId = currentWindowIndex;
|
||||
activeQueueItemId = currentMediaItemIndex;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -118,7 +118,7 @@ public abstract class BasePlayer implements Player {
|
|||
|
||||
@Override
|
||||
public final void seekToDefaultPosition() {
|
||||
seekToDefaultPosition(getCurrentWindowIndex());
|
||||
seekToDefaultPosition(getCurrentMediaItemIndex());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -128,7 +128,7 @@ public abstract class BasePlayer implements Player {
|
|||
|
||||
@Override
|
||||
public final void seekTo(long positionMs) {
|
||||
seekTo(getCurrentWindowIndex(), positionMs);
|
||||
seekTo(getCurrentMediaItemIndex(), positionMs);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -184,13 +184,13 @@ public abstract class BasePlayer implements Player {
|
|||
if (timeline.isEmpty() || isPlayingAd()) {
|
||||
return;
|
||||
}
|
||||
boolean hasPreviousWindow = hasPreviousWindow();
|
||||
if (isCurrentWindowLive() && !isCurrentWindowSeekable()) {
|
||||
if (hasPreviousWindow) {
|
||||
seekToPreviousWindow();
|
||||
boolean hasPreviousMediaItem = hasPreviousMediaItem();
|
||||
if (isCurrentMediaItemLive() && !isCurrentMediaItemSeekable()) {
|
||||
if (hasPreviousMediaItem) {
|
||||
seekToPreviousMediaItem();
|
||||
}
|
||||
} else if (hasPreviousWindow && getCurrentPosition() <= getMaxSeekToPreviousPosition()) {
|
||||
seekToPreviousWindow();
|
||||
} else if (hasPreviousMediaItem && getCurrentPosition() <= getMaxSeekToPreviousPosition()) {
|
||||
seekToPreviousMediaItem();
|
||||
} else {
|
||||
seekTo(/* positionMs= */ 0);
|
||||
}
|
||||
|
|
@ -239,9 +239,9 @@ public abstract class BasePlayer implements Player {
|
|||
if (timeline.isEmpty() || isPlayingAd()) {
|
||||
return;
|
||||
}
|
||||
if (hasNextWindow()) {
|
||||
seekToNextWindow();
|
||||
} else if (isCurrentWindowLive() && isCurrentWindowDynamic()) {
|
||||
if (hasNextMediaItem()) {
|
||||
seekToNextMediaItem();
|
||||
} else if (isCurrentMediaItemLive() && isCurrentMediaItemDynamic()) {
|
||||
seekToDefaultPosition();
|
||||
}
|
||||
}
|
||||
|
|
@ -293,7 +293,7 @@ public abstract class BasePlayer implements Player {
|
|||
Timeline timeline = getCurrentTimeline();
|
||||
return timeline.isEmpty()
|
||||
? null
|
||||
: timeline.getWindow(getCurrentWindowIndex(), window).mediaItem;
|
||||
: timeline.getWindow(getCurrentMediaItemIndex(), window).mediaItem;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -310,7 +310,9 @@ public abstract class BasePlayer implements Player {
|
|||
@Nullable
|
||||
public final Object getCurrentManifest() {
|
||||
Timeline timeline = getCurrentTimeline();
|
||||
return timeline.isEmpty() ? null : timeline.getWindow(getCurrentWindowIndex(), window).manifest;
|
||||
return timeline.isEmpty()
|
||||
? null
|
||||
: timeline.getWindow(getCurrentMediaItemIndex(), window).manifest;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -352,7 +354,8 @@ public abstract class BasePlayer implements Player {
|
|||
if (timeline.isEmpty()) {
|
||||
return C.TIME_UNSET;
|
||||
}
|
||||
long windowStartTimeMs = timeline.getWindow(getCurrentWindowIndex(), window).windowStartTimeMs;
|
||||
long windowStartTimeMs =
|
||||
timeline.getWindow(getCurrentMediaItemIndex(), window).windowStartTimeMs;
|
||||
if (windowStartTimeMs == C.TIME_UNSET) {
|
||||
return C.TIME_UNSET;
|
||||
}
|
||||
|
|
@ -376,7 +379,7 @@ public abstract class BasePlayer implements Player {
|
|||
Timeline timeline = getCurrentTimeline();
|
||||
return timeline.isEmpty()
|
||||
? C.TIME_UNSET
|
||||
: timeline.getWindow(getCurrentWindowIndex(), window).getDurationMs();
|
||||
: timeline.getWindow(getCurrentMediaItemIndex(), window).getDurationMs();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -389,22 +392,24 @@ public abstract class BasePlayer implements Player {
|
|||
return new Commands.Builder()
|
||||
.addAll(permanentAvailableCommands)
|
||||
.addIf(COMMAND_SEEK_TO_DEFAULT_POSITION, !isPlayingAd())
|
||||
.addIf(COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM, isCurrentWindowSeekable() && !isPlayingAd())
|
||||
.addIf(COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM, hasPreviousWindow() && !isPlayingAd())
|
||||
.addIf(COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM, isCurrentMediaItemSeekable() && !isPlayingAd())
|
||||
.addIf(COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM, hasPreviousMediaItem() && !isPlayingAd())
|
||||
.addIf(
|
||||
COMMAND_SEEK_TO_PREVIOUS,
|
||||
!getCurrentTimeline().isEmpty()
|
||||
&& (hasPreviousWindow() || !isCurrentWindowLive() || isCurrentWindowSeekable())
|
||||
&& (hasPreviousMediaItem()
|
||||
|| !isCurrentMediaItemLive()
|
||||
|| isCurrentMediaItemSeekable())
|
||||
&& !isPlayingAd())
|
||||
.addIf(COMMAND_SEEK_TO_NEXT_MEDIA_ITEM, hasNextWindow() && !isPlayingAd())
|
||||
.addIf(COMMAND_SEEK_TO_NEXT_MEDIA_ITEM, hasNextMediaItem() && !isPlayingAd())
|
||||
.addIf(
|
||||
COMMAND_SEEK_TO_NEXT,
|
||||
!getCurrentTimeline().isEmpty()
|
||||
&& (hasNextWindow() || (isCurrentWindowLive() && isCurrentWindowDynamic()))
|
||||
&& (hasNextMediaItem() || (isCurrentMediaItemLive() && isCurrentMediaItemDynamic()))
|
||||
&& !isPlayingAd())
|
||||
.addIf(COMMAND_SEEK_TO_MEDIA_ITEM, !isPlayingAd())
|
||||
.addIf(COMMAND_SEEK_BACK, isCurrentWindowSeekable() && !isPlayingAd())
|
||||
.addIf(COMMAND_SEEK_FORWARD, isCurrentWindowSeekable() && !isPlayingAd())
|
||||
.addIf(COMMAND_SEEK_BACK, isCurrentMediaItemSeekable() && !isPlayingAd())
|
||||
.addIf(COMMAND_SEEK_FORWARD, isCurrentMediaItemSeekable() && !isPlayingAd())
|
||||
.build();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1126,7 +1126,7 @@ public interface ExoPlayer extends Player {
|
|||
* @param mediaSources The new {@link MediaSource MediaSources}.
|
||||
* @param resetPosition Whether the playback position should be reset to the default position in
|
||||
* the first {@link Timeline.Window}. If false, playback will start from the position defined
|
||||
* by {@link #getCurrentWindowIndex()} and {@link #getCurrentPosition()}.
|
||||
* by {@link #getCurrentMediaItemIndex()} and {@link #getCurrentPosition()}.
|
||||
*/
|
||||
void setMediaSources(List<MediaSource> mediaSources, boolean resetPosition);
|
||||
|
||||
|
|
@ -1134,14 +1134,15 @@ public interface ExoPlayer extends Player {
|
|||
* Clears the playlist and adds the specified {@link MediaSource MediaSources}.
|
||||
*
|
||||
* @param mediaSources The new {@link MediaSource MediaSources}.
|
||||
* @param startWindowIndex The window index to start playback from. If {@link C#INDEX_UNSET} is
|
||||
* passed, the current position is not reset.
|
||||
* @param startMediaItemIndex The media item index to start playback from. If {@link
|
||||
* C#INDEX_UNSET} is passed, the current position is not reset.
|
||||
* @param startPositionMs The position in milliseconds to start playback from. If {@link
|
||||
* C#TIME_UNSET} is passed, the default position of the given window is used. In any case, if
|
||||
* {@code startWindowIndex} is set to {@link C#INDEX_UNSET}, this parameter is ignored and the
|
||||
* position is not reset at all.
|
||||
* C#TIME_UNSET} is passed, the default position of the given media item is used. In any case,
|
||||
* if {@code startMediaItemIndex} is set to {@link C#INDEX_UNSET}, this parameter is ignored
|
||||
* and the position is not reset at all.
|
||||
*/
|
||||
void setMediaSources(List<MediaSource> mediaSources, int startWindowIndex, long startPositionMs);
|
||||
void setMediaSources(
|
||||
List<MediaSource> mediaSources, int startMediaItemIndex, long startPositionMs);
|
||||
|
||||
/**
|
||||
* Clears the playlist, adds the specified {@link MediaSource} and resets the position to the
|
||||
|
|
@ -1164,7 +1165,7 @@ public interface ExoPlayer extends Player {
|
|||
*
|
||||
* @param mediaSource The new {@link MediaSource}.
|
||||
* @param resetPosition Whether the playback position should be reset to the default position. If
|
||||
* false, playback will start from the position defined by {@link #getCurrentWindowIndex()}
|
||||
* false, playback will start from the position defined by {@link #getCurrentMediaItemIndex()}
|
||||
* and {@link #getCurrentPosition()}.
|
||||
*/
|
||||
void setMediaSource(MediaSource mediaSource, boolean resetPosition);
|
||||
|
|
@ -1331,9 +1332,9 @@ public interface ExoPlayer extends Player {
|
|||
* will be delivered immediately without blocking on the playback thread. The default {@link
|
||||
* PlayerMessage#getType()} is 0 and the default {@link PlayerMessage#getPayload()} is null. If a
|
||||
* position is specified with {@link PlayerMessage#setPosition(long)}, the message will be
|
||||
* delivered at this position in the current window defined by {@link #getCurrentWindowIndex()}.
|
||||
* Alternatively, the message can be sent at a specific window using {@link
|
||||
* PlayerMessage#setPosition(int, long)}.
|
||||
* delivered at this position in the current media item defined by {@link
|
||||
* #getCurrentMediaItemIndex()}. Alternatively, the message can be sent at a specific mediaItem
|
||||
* using {@link PlayerMessage#setPosition(int, long)}.
|
||||
*/
|
||||
PlayerMessage createMessage(PlayerMessage.Target target);
|
||||
|
||||
|
|
|
|||
|
|
@ -537,7 +537,7 @@ import java.util.concurrent.CopyOnWriteArraySet;
|
|||
playbackInfo,
|
||||
timeline,
|
||||
getPeriodPositionOrMaskWindowPosition(
|
||||
timeline, getCurrentWindowIndex(), getCurrentPosition()));
|
||||
timeline, getCurrentMediaItemIndex(), getCurrentPosition()));
|
||||
pendingOperationAcks++;
|
||||
this.shuffleOrder = shuffleOrder;
|
||||
internalPlayer.setShuffleOrder(shuffleOrder);
|
||||
|
|
@ -662,7 +662,7 @@ import java.util.concurrent.CopyOnWriteArraySet;
|
|||
@Player.State
|
||||
int newPlaybackState =
|
||||
getPlaybackState() == Player.STATE_IDLE ? Player.STATE_IDLE : Player.STATE_BUFFERING;
|
||||
int oldMaskingWindowIndex = getCurrentWindowIndex();
|
||||
int oldMaskingMediaItemIndex = getCurrentMediaItemIndex();
|
||||
PlaybackInfo newPlaybackInfo = playbackInfo.copyWithPlaybackState(newPlaybackState);
|
||||
newPlaybackInfo =
|
||||
maskTimelineAndPosition(
|
||||
|
|
@ -678,7 +678,7 @@ import java.util.concurrent.CopyOnWriteArraySet;
|
|||
/* positionDiscontinuity= */ true,
|
||||
/* positionDiscontinuityReason= */ DISCONTINUITY_REASON_SEEK,
|
||||
/* discontinuityWindowStartPositionUs= */ getCurrentPositionUsInternal(newPlaybackInfo),
|
||||
oldMaskingWindowIndex);
|
||||
oldMaskingMediaItemIndex);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -839,7 +839,7 @@ import java.util.concurrent.CopyOnWriteArraySet;
|
|||
internalPlayer,
|
||||
target,
|
||||
playbackInfo.timeline,
|
||||
getCurrentWindowIndex(),
|
||||
getCurrentMediaItemIndex(),
|
||||
clock,
|
||||
internalPlayer.getPlaybackLooper());
|
||||
}
|
||||
|
|
@ -910,7 +910,10 @@ import java.util.concurrent.CopyOnWriteArraySet;
|
|||
if (isPlayingAd()) {
|
||||
playbackInfo.timeline.getPeriodByUid(playbackInfo.periodId.periodUid, period);
|
||||
return playbackInfo.requestedContentPositionUs == C.TIME_UNSET
|
||||
? playbackInfo.timeline.getWindow(getCurrentWindowIndex(), window).getDefaultPositionMs()
|
||||
? playbackInfo
|
||||
.timeline
|
||||
.getWindow(getCurrentMediaItemIndex(), window)
|
||||
.getDefaultPositionMs()
|
||||
: period.getPositionInWindowMs() + Util.usToMs(playbackInfo.requestedContentPositionUs);
|
||||
} else {
|
||||
return getCurrentPosition();
|
||||
|
|
@ -924,7 +927,7 @@ import java.util.concurrent.CopyOnWriteArraySet;
|
|||
}
|
||||
if (playbackInfo.loadingMediaPeriodId.windowSequenceNumber
|
||||
!= playbackInfo.periodId.windowSequenceNumber) {
|
||||
return playbackInfo.timeline.getWindow(getCurrentWindowIndex(), window).getDurationMs();
|
||||
return playbackInfo.timeline.getWindow(getCurrentMediaItemIndex(), window).getDurationMs();
|
||||
}
|
||||
long contentBufferedPositionUs = playbackInfo.bufferedPositionUs;
|
||||
if (playbackInfo.loadingMediaPeriodId.isAd()) {
|
||||
|
|
@ -1218,7 +1221,7 @@ import java.util.concurrent.CopyOnWriteArraySet;
|
|||
boolean positionDiscontinuity,
|
||||
@DiscontinuityReason int positionDiscontinuityReason,
|
||||
long discontinuityWindowStartPositionUs,
|
||||
int oldMaskingWindowIndex) {
|
||||
int oldMaskingMediaItemIndex) {
|
||||
|
||||
// Assign playback info immediately such that all getters return the right values, but keep
|
||||
// snapshot of previous and new state so that listener invocations are triggered correctly.
|
||||
|
|
@ -1267,7 +1270,7 @@ import java.util.concurrent.CopyOnWriteArraySet;
|
|||
if (positionDiscontinuity) {
|
||||
PositionInfo previousPositionInfo =
|
||||
getPreviousPositionInfo(
|
||||
positionDiscontinuityReason, previousPlaybackInfo, oldMaskingWindowIndex);
|
||||
positionDiscontinuityReason, previousPlaybackInfo, oldMaskingMediaItemIndex);
|
||||
PositionInfo positionInfo = getPositionInfo(discontinuityWindowStartPositionUs);
|
||||
listeners.queueEvent(
|
||||
Player.EVENT_POSITION_DISCONTINUITY,
|
||||
|
|
@ -1378,19 +1381,19 @@ import java.util.concurrent.CopyOnWriteArraySet;
|
|||
private PositionInfo getPreviousPositionInfo(
|
||||
@DiscontinuityReason int positionDiscontinuityReason,
|
||||
PlaybackInfo oldPlaybackInfo,
|
||||
int oldMaskingWindowIndex) {
|
||||
int oldMaskingMediaItemIndex) {
|
||||
@Nullable Object oldWindowUid = null;
|
||||
@Nullable Object oldPeriodUid = null;
|
||||
int oldWindowIndex = oldMaskingWindowIndex;
|
||||
int oldMediaItemIndex = oldMaskingMediaItemIndex;
|
||||
int oldPeriodIndex = C.INDEX_UNSET;
|
||||
@Nullable MediaItem oldMediaItem = null;
|
||||
Timeline.Period oldPeriod = new Timeline.Period();
|
||||
if (!oldPlaybackInfo.timeline.isEmpty()) {
|
||||
oldPeriodUid = oldPlaybackInfo.periodId.periodUid;
|
||||
oldPlaybackInfo.timeline.getPeriodByUid(oldPeriodUid, oldPeriod);
|
||||
oldWindowIndex = oldPeriod.windowIndex;
|
||||
oldMediaItemIndex = oldPeriod.windowIndex;
|
||||
oldPeriodIndex = oldPlaybackInfo.timeline.getIndexOfPeriod(oldPeriodUid);
|
||||
oldWindowUid = oldPlaybackInfo.timeline.getWindow(oldWindowIndex, window).uid;
|
||||
oldWindowUid = oldPlaybackInfo.timeline.getWindow(oldMediaItemIndex, window).uid;
|
||||
oldMediaItem = window.mediaItem;
|
||||
}
|
||||
long oldPositionUs;
|
||||
|
|
@ -1421,7 +1424,7 @@ import java.util.concurrent.CopyOnWriteArraySet;
|
|||
}
|
||||
return new PositionInfo(
|
||||
oldWindowUid,
|
||||
oldWindowIndex,
|
||||
oldMediaItemIndex,
|
||||
oldMediaItem,
|
||||
oldPeriodUid,
|
||||
oldPeriodIndex,
|
||||
|
|
@ -1434,20 +1437,20 @@ import java.util.concurrent.CopyOnWriteArraySet;
|
|||
private PositionInfo getPositionInfo(long discontinuityWindowStartPositionUs) {
|
||||
@Nullable Object newWindowUid = null;
|
||||
@Nullable Object newPeriodUid = null;
|
||||
int newWindowIndex = getCurrentWindowIndex();
|
||||
int newMediaItemIndex = getCurrentMediaItemIndex();
|
||||
int newPeriodIndex = C.INDEX_UNSET;
|
||||
@Nullable MediaItem newMediaItem = null;
|
||||
if (!playbackInfo.timeline.isEmpty()) {
|
||||
newPeriodUid = playbackInfo.periodId.periodUid;
|
||||
playbackInfo.timeline.getPeriodByUid(newPeriodUid, period);
|
||||
newPeriodIndex = playbackInfo.timeline.getIndexOfPeriod(newPeriodUid);
|
||||
newWindowUid = playbackInfo.timeline.getWindow(newWindowIndex, window).uid;
|
||||
newWindowUid = playbackInfo.timeline.getWindow(newMediaItemIndex, window).uid;
|
||||
newMediaItem = window.mediaItem;
|
||||
}
|
||||
long positionMs = Util.usToMs(discontinuityWindowStartPositionUs);
|
||||
return new PositionInfo(
|
||||
newWindowUid,
|
||||
newWindowIndex,
|
||||
newMediaItemIndex,
|
||||
newMediaItem,
|
||||
newPeriodUid,
|
||||
newPeriodIndex,
|
||||
|
|
@ -1601,7 +1604,7 @@ import java.util.concurrent.CopyOnWriteArraySet;
|
|||
private PlaybackInfo removeMediaItemsInternal(int fromIndex, int toIndex) {
|
||||
Assertions.checkArgument(
|
||||
fromIndex >= 0 && toIndex >= fromIndex && toIndex <= mediaSourceHolderSnapshots.size());
|
||||
int currentWindowIndex = getCurrentWindowIndex();
|
||||
int currentIndex = getCurrentMediaItemIndex();
|
||||
Timeline oldTimeline = getCurrentTimeline();
|
||||
int currentMediaSourceCount = mediaSourceHolderSnapshots.size();
|
||||
pendingOperationAcks++;
|
||||
|
|
@ -1618,7 +1621,7 @@ import java.util.concurrent.CopyOnWriteArraySet;
|
|||
&& newPlaybackInfo.playbackState != STATE_ENDED
|
||||
&& fromIndex < toIndex
|
||||
&& toIndex == currentMediaSourceCount
|
||||
&& currentWindowIndex >= newPlaybackInfo.timeline.getWindowCount();
|
||||
&& currentIndex >= newPlaybackInfo.timeline.getWindowCount();
|
||||
if (transitionsToEnded) {
|
||||
newPlaybackInfo = newPlaybackInfo.copyWithPlaybackState(STATE_ENDED);
|
||||
}
|
||||
|
|
@ -1753,11 +1756,11 @@ import java.util.concurrent.CopyOnWriteArraySet;
|
|||
isCleared ? C.INDEX_UNSET : getCurrentWindowIndexInternal(),
|
||||
isCleared ? C.TIME_UNSET : currentPositionMs);
|
||||
}
|
||||
int currentWindowIndex = getCurrentWindowIndex();
|
||||
int currentMediaItemIndex = getCurrentMediaItemIndex();
|
||||
@Nullable
|
||||
Pair<Object, Long> oldPeriodPosition =
|
||||
oldTimeline.getPeriodPosition(
|
||||
window, period, currentWindowIndex, Util.msToUs(currentPositionMs));
|
||||
window, period, currentMediaItemIndex, Util.msToUs(currentPositionMs));
|
||||
Object periodUid = castNonNull(oldPeriodPosition).first;
|
||||
if (newTimeline.getIndexOfPeriod(periodUid) != C.INDEX_UNSET) {
|
||||
// The old period position is still available in the new timeline.
|
||||
|
|
|
|||
|
|
@ -2718,7 +2718,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||
newTimeline,
|
||||
new SeekPosition(
|
||||
pendingMessageInfo.message.getTimeline(),
|
||||
pendingMessageInfo.message.getWindowIndex(),
|
||||
pendingMessageInfo.message.getMediaItemIndex(),
|
||||
requestPositionUs),
|
||||
/* trySubsequentPeriods= */ false,
|
||||
repeatMode,
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ public final class PlayerMessage {
|
|||
private int type;
|
||||
@Nullable private Object payload;
|
||||
private Looper looper;
|
||||
private int windowIndex;
|
||||
private int mediaItemIndex;
|
||||
private long positionMs;
|
||||
private boolean deleteAfterDelivery;
|
||||
private boolean isSent;
|
||||
|
|
@ -78,8 +78,8 @@ public final class PlayerMessage {
|
|||
* @param target The {@link Target} the message is sent to.
|
||||
* @param timeline The timeline used when setting the position with {@link #setPosition(long)}. If
|
||||
* set to {@link Timeline#EMPTY}, any position can be specified.
|
||||
* @param defaultWindowIndex The default window index in the {@code timeline} when no other window
|
||||
* index is specified.
|
||||
* @param defaultMediaItemIndex The default media item index in the {@code timeline} when no other
|
||||
* media item index is specified.
|
||||
* @param clock The {@link Clock}.
|
||||
* @param defaultLooper The default {@link Looper} to send the message on when no other looper is
|
||||
* specified.
|
||||
|
|
@ -88,7 +88,7 @@ public final class PlayerMessage {
|
|||
Sender sender,
|
||||
Target target,
|
||||
Timeline timeline,
|
||||
int defaultWindowIndex,
|
||||
int defaultMediaItemIndex,
|
||||
Clock clock,
|
||||
Looper defaultLooper) {
|
||||
this.sender = sender;
|
||||
|
|
@ -96,7 +96,7 @@ public final class PlayerMessage {
|
|||
this.timeline = timeline;
|
||||
this.looper = defaultLooper;
|
||||
this.clock = clock;
|
||||
this.windowIndex = defaultWindowIndex;
|
||||
this.mediaItemIndex = defaultMediaItemIndex;
|
||||
this.positionMs = C.TIME_UNSET;
|
||||
this.deleteAfterDelivery = true;
|
||||
}
|
||||
|
|
@ -173,21 +173,21 @@ public final class PlayerMessage {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns position in window at {@link #getWindowIndex()} at which the message will be delivered,
|
||||
* in milliseconds. If {@link C#TIME_UNSET}, the message will be delivered immediately. If {@link
|
||||
* C#TIME_END_OF_SOURCE}, the message will be delivered at the end of the window at {@link
|
||||
* #getWindowIndex()}.
|
||||
* Returns position in the media item at {@link #getMediaItemIndex()} at which the message will be
|
||||
* delivered, in milliseconds. If {@link C#TIME_UNSET}, the message will be delivered immediately.
|
||||
* If {@link C#TIME_END_OF_SOURCE}, the message will be delivered at the end of the media item at
|
||||
* {@link #getMediaItemIndex()}.
|
||||
*/
|
||||
public long getPositionMs() {
|
||||
return positionMs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a position in the current window at which the message will be delivered.
|
||||
* Sets a position in the current media item at which the message will be delivered.
|
||||
*
|
||||
* @param positionMs The position in the current window at which the message will be sent, in
|
||||
* @param positionMs The position in the current media item at which the message will be sent, in
|
||||
* milliseconds, or {@link C#TIME_END_OF_SOURCE} to deliver the message at the end of the
|
||||
* current window.
|
||||
* current media item.
|
||||
* @return This message.
|
||||
* @throws IllegalStateException If {@link #send()} has already been called.
|
||||
*/
|
||||
|
|
@ -198,31 +198,32 @@ public final class PlayerMessage {
|
|||
}
|
||||
|
||||
/**
|
||||
* Sets a position in a window at which the message will be delivered.
|
||||
* Sets a position in a media item at which the message will be delivered.
|
||||
*
|
||||
* @param windowIndex The index of the window at which the message will be sent.
|
||||
* @param positionMs The position in the window with index {@code windowIndex} at which the
|
||||
* @param mediaItemIndex The index of the media item at which the message will be sent.
|
||||
* @param positionMs The position in the media item with index {@code mediaItemIndex} at which the
|
||||
* message will be sent, in milliseconds, or {@link C#TIME_END_OF_SOURCE} to deliver the
|
||||
* message at the end of the window with index {@code windowIndex}.
|
||||
* message at the end of the media item with index {@code mediaItemIndex}.
|
||||
* @return This message.
|
||||
* @throws IllegalSeekPositionException If the timeline returned by {@link #getTimeline()} is not
|
||||
* empty and the provided window index is not within the bounds of the timeline.
|
||||
* empty and the provided media item index is not within the bounds of the timeline.
|
||||
* @throws IllegalStateException If {@link #send()} has already been called.
|
||||
*/
|
||||
public PlayerMessage setPosition(int windowIndex, long positionMs) {
|
||||
public PlayerMessage setPosition(int mediaItemIndex, long positionMs) {
|
||||
Assertions.checkState(!isSent);
|
||||
Assertions.checkArgument(positionMs != C.TIME_UNSET);
|
||||
if (windowIndex < 0 || (!timeline.isEmpty() && windowIndex >= timeline.getWindowCount())) {
|
||||
throw new IllegalSeekPositionException(timeline, windowIndex, positionMs);
|
||||
if (mediaItemIndex < 0
|
||||
|| (!timeline.isEmpty() && mediaItemIndex >= timeline.getWindowCount())) {
|
||||
throw new IllegalSeekPositionException(timeline, mediaItemIndex, positionMs);
|
||||
}
|
||||
this.windowIndex = windowIndex;
|
||||
this.mediaItemIndex = mediaItemIndex;
|
||||
this.positionMs = positionMs;
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Returns window index at which the message will be delivered. */
|
||||
public int getWindowIndex() {
|
||||
return windowIndex;
|
||||
/** Returns media item index at which the message will be delivered. */
|
||||
public int getMediaItemIndex() {
|
||||
return mediaItemIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1110,9 +1110,9 @@ public class SimpleExoPlayer extends BasePlayer
|
|||
|
||||
@Override
|
||||
public void setMediaSources(
|
||||
List<MediaSource> mediaSources, int startWindowIndex, long startPositionMs) {
|
||||
List<MediaSource> mediaSources, int startMediaItemIndex, long startPositionMs) {
|
||||
verifyApplicationThread();
|
||||
player.setMediaSources(mediaSources, startWindowIndex, startPositionMs);
|
||||
player.setMediaSources(mediaSources, startMediaItemIndex, startPositionMs);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -1419,7 +1419,7 @@ public class SimpleExoPlayer extends BasePlayer
|
|||
@Override
|
||||
public int getCurrentMediaItemIndex() {
|
||||
verifyApplicationThread();
|
||||
return player.getCurrentWindowIndex();
|
||||
return player.getCurrentMediaItemIndex();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -914,7 +914,7 @@ public class AnalyticsCollector
|
|||
long eventPositionMs;
|
||||
boolean isInCurrentWindow =
|
||||
timeline.equals(player.getCurrentTimeline())
|
||||
&& windowIndex == player.getCurrentWindowIndex();
|
||||
&& windowIndex == player.getCurrentMediaItemIndex();
|
||||
if (mediaPeriodId != null && mediaPeriodId.isAd()) {
|
||||
boolean isCurrentAd =
|
||||
isInCurrentWindow
|
||||
|
|
@ -939,7 +939,7 @@ public class AnalyticsCollector
|
|||
mediaPeriodId,
|
||||
eventPositionMs,
|
||||
player.getCurrentTimeline(),
|
||||
player.getCurrentWindowIndex(),
|
||||
player.getCurrentMediaItemIndex(),
|
||||
currentMediaPeriodId,
|
||||
player.getCurrentPosition(),
|
||||
player.getTotalBufferedDuration());
|
||||
|
|
@ -962,7 +962,7 @@ public class AnalyticsCollector
|
|||
? null
|
||||
: mediaPeriodQueueTracker.getMediaPeriodIdTimeline(mediaPeriodId);
|
||||
if (mediaPeriodId == null || knownTimeline == null) {
|
||||
int windowIndex = player.getCurrentWindowIndex();
|
||||
int windowIndex = player.getCurrentMediaItemIndex();
|
||||
Timeline timeline = player.getCurrentTimeline();
|
||||
boolean windowIsInTimeline = windowIndex < timeline.getWindowCount();
|
||||
return generateEventTime(
|
||||
|
|
|
|||
|
|
@ -382,7 +382,7 @@ public interface AnalyticsListener {
|
|||
/**
|
||||
* The current window index in {@link #currentTimeline} at the time of the event, or the
|
||||
* prospective window index if the timeline is not yet known and empty (equivalent to {@link
|
||||
* Player#getCurrentWindowIndex()}).
|
||||
* Player#getCurrentMediaItemIndex()}).
|
||||
*/
|
||||
public final int currentWindowIndex;
|
||||
|
||||
|
|
@ -419,7 +419,7 @@ public interface AnalyticsListener {
|
|||
* {@link Player#getCurrentTimeline()}).
|
||||
* @param currentWindowIndex The current window index in {@code currentTimeline} at the time of
|
||||
* the event, or the prospective window index if the timeline is not yet known and empty
|
||||
* (equivalent to {@link Player#getCurrentWindowIndex()}).
|
||||
* (equivalent to {@link Player#getCurrentMediaItemIndex()}).
|
||||
* @param currentMediaPeriodId {@link MediaPeriodId Media period identifier} for the currently
|
||||
* playing media period at the time of the event, or {@code null} if no current media period
|
||||
* identifier is available.
|
||||
|
|
@ -1204,9 +1204,9 @@ public interface AnalyticsListener {
|
|||
* {@link Player#seekTo(long)} after a {@link
|
||||
* AnalyticsListener#onMediaItemTransition(EventTime, MediaItem, int)}).
|
||||
* <li>They intend to use multiple state values together or in combination with {@link Player}
|
||||
* getter methods. For example using {@link Player#getCurrentWindowIndex()} with the {@code
|
||||
* timeline} provided in {@link #onTimelineChanged(EventTime, int)} is only safe from within
|
||||
* this method.
|
||||
* getter methods. For example using {@link Player#getCurrentMediaItemIndex()} with the
|
||||
* {@code timeline} provided in {@link #onTimelineChanged(EventTime, int)} is only safe from
|
||||
* within this method.
|
||||
* <li>They are interested in events that logically happened together (e.g {@link
|
||||
* #onPlaybackStateChanged(EventTime, int)} to {@link Player#STATE_BUFFERING} because of
|
||||
* {@link #onMediaItemTransition(EventTime, MediaItem, int)}).
|
||||
|
|
|
|||
|
|
@ -182,6 +182,8 @@ public final class FrameworkMediaDrm implements ExoMediaDrm {
|
|||
mediaDrm.closeSession(sessionId);
|
||||
}
|
||||
|
||||
// Return values of MediaDrm.KeyRequest.getRequestType are equal to KeyRequest.RequestType.
|
||||
@SuppressLint("WrongConstant")
|
||||
@Override
|
||||
public KeyRequest getKeyRequest(
|
||||
byte[] scope,
|
||||
|
|
|
|||
|
|
@ -26,10 +26,8 @@ import com.google.android.exoplayer2.util.NetworkTypeObserver;
|
|||
import com.google.android.exoplayer2.util.Util;
|
||||
import com.google.common.base.Ascii;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableListMultimap;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
|
|
@ -42,13 +40,6 @@ import java.util.Map;
|
|||
*/
|
||||
public final class DefaultBandwidthMeter implements BandwidthMeter, TransferListener {
|
||||
|
||||
/**
|
||||
* Country groups used to determine the default initial bitrate estimate. The group assignment for
|
||||
* each country is a list for [Wifi, 2G, 3G, 4G, 5G_NSA, 5G_SA].
|
||||
*/
|
||||
public static final ImmutableListMultimap<String, Integer>
|
||||
DEFAULT_INITIAL_BITRATE_COUNTRY_GROUPS = createInitialBitrateCountryGroupAssignment();
|
||||
|
||||
/** Default initial Wifi bitrate estimate in bits per second. */
|
||||
public static final ImmutableList<Long> DEFAULT_INITIAL_BITRATE_ESTIMATES_WIFI =
|
||||
ImmutableList.of(5_400_000L, 3_300_000L, 2_000_000L, 1_300_000L, 760_000L);
|
||||
|
|
@ -82,17 +73,35 @@ public final class DefaultBandwidthMeter implements BandwidthMeter, TransferList
|
|||
/** Default maximum weight for the sliding window. */
|
||||
public static final int DEFAULT_SLIDING_WINDOW_MAX_WEIGHT = 2000;
|
||||
|
||||
/** Index for the Wifi group index in {@link #DEFAULT_INITIAL_BITRATE_COUNTRY_GROUPS}. */
|
||||
/**
|
||||
* Index for the Wifi group index in the array returned by {@link
|
||||
* #getInitialBitrateCountryGroupAssignment}.
|
||||
*/
|
||||
private static final int COUNTRY_GROUP_INDEX_WIFI = 0;
|
||||
/** Index for the 2G group index in {@link #DEFAULT_INITIAL_BITRATE_COUNTRY_GROUPS}. */
|
||||
/**
|
||||
* Index for the 2G group index in the array returned by {@link
|
||||
* #getInitialBitrateCountryGroupAssignment}.
|
||||
*/
|
||||
private static final int COUNTRY_GROUP_INDEX_2G = 1;
|
||||
/** Index for the 3G group index in {@link #DEFAULT_INITIAL_BITRATE_COUNTRY_GROUPS}. */
|
||||
/**
|
||||
* Index for the 3G group index in the array returned by {@link
|
||||
* #getInitialBitrateCountryGroupAssignment}.
|
||||
*/
|
||||
private static final int COUNTRY_GROUP_INDEX_3G = 2;
|
||||
/** Index for the 4G group index in {@link #DEFAULT_INITIAL_BITRATE_COUNTRY_GROUPS}. */
|
||||
/**
|
||||
* Index for the 4G group index in the array returned by {@link
|
||||
* #getInitialBitrateCountryGroupAssignment}.
|
||||
*/
|
||||
private static final int COUNTRY_GROUP_INDEX_4G = 3;
|
||||
/** Index for the 5G-NSA group index in {@link #DEFAULT_INITIAL_BITRATE_COUNTRY_GROUPS}. */
|
||||
/**
|
||||
* Index for the 5G-NSA group index in the array returned by {@link
|
||||
* #getInitialBitrateCountryGroupAssignment}.
|
||||
*/
|
||||
private static final int COUNTRY_GROUP_INDEX_5G_NSA = 4;
|
||||
/** Index for the 5G-SA group index in {@link #DEFAULT_INITIAL_BITRATE_COUNTRY_GROUPS}. */
|
||||
/**
|
||||
* Index for the 5G-SA group index in the array returned by {@link
|
||||
* #getInitialBitrateCountryGroupAssignment}.
|
||||
*/
|
||||
private static final int COUNTRY_GROUP_INDEX_5G_SA = 5;
|
||||
|
||||
@Nullable private static DefaultBandwidthMeter singletonInstance;
|
||||
|
|
@ -212,40 +221,33 @@ public final class DefaultBandwidthMeter implements BandwidthMeter, TransferList
|
|||
}
|
||||
|
||||
private static Map<Integer, Long> getInitialBitrateEstimatesForCountry(String countryCode) {
|
||||
List<Integer> groupIndices = getCountryGroupIndices(countryCode);
|
||||
int[] groupIndices = getInitialBitrateCountryGroupAssignment(countryCode);
|
||||
Map<Integer, Long> result = new HashMap<>(/* initialCapacity= */ 8);
|
||||
result.put(C.NETWORK_TYPE_UNKNOWN, DEFAULT_INITIAL_BITRATE_ESTIMATE);
|
||||
result.put(
|
||||
C.NETWORK_TYPE_WIFI,
|
||||
DEFAULT_INITIAL_BITRATE_ESTIMATES_WIFI.get(groupIndices.get(COUNTRY_GROUP_INDEX_WIFI)));
|
||||
DEFAULT_INITIAL_BITRATE_ESTIMATES_WIFI.get(groupIndices[COUNTRY_GROUP_INDEX_WIFI]));
|
||||
result.put(
|
||||
C.NETWORK_TYPE_2G,
|
||||
DEFAULT_INITIAL_BITRATE_ESTIMATES_2G.get(groupIndices.get(COUNTRY_GROUP_INDEX_2G)));
|
||||
DEFAULT_INITIAL_BITRATE_ESTIMATES_2G.get(groupIndices[COUNTRY_GROUP_INDEX_2G]));
|
||||
result.put(
|
||||
C.NETWORK_TYPE_3G,
|
||||
DEFAULT_INITIAL_BITRATE_ESTIMATES_3G.get(groupIndices.get(COUNTRY_GROUP_INDEX_3G)));
|
||||
DEFAULT_INITIAL_BITRATE_ESTIMATES_3G.get(groupIndices[COUNTRY_GROUP_INDEX_3G]));
|
||||
result.put(
|
||||
C.NETWORK_TYPE_4G,
|
||||
DEFAULT_INITIAL_BITRATE_ESTIMATES_4G.get(groupIndices.get(COUNTRY_GROUP_INDEX_4G)));
|
||||
DEFAULT_INITIAL_BITRATE_ESTIMATES_4G.get(groupIndices[COUNTRY_GROUP_INDEX_4G]));
|
||||
result.put(
|
||||
C.NETWORK_TYPE_5G_NSA,
|
||||
DEFAULT_INITIAL_BITRATE_ESTIMATES_5G_NSA.get(
|
||||
groupIndices.get(COUNTRY_GROUP_INDEX_5G_NSA)));
|
||||
DEFAULT_INITIAL_BITRATE_ESTIMATES_5G_NSA.get(groupIndices[COUNTRY_GROUP_INDEX_5G_NSA]));
|
||||
result.put(
|
||||
C.NETWORK_TYPE_5G_SA,
|
||||
DEFAULT_INITIAL_BITRATE_ESTIMATES_5G_SA.get(groupIndices.get(COUNTRY_GROUP_INDEX_5G_SA)));
|
||||
DEFAULT_INITIAL_BITRATE_ESTIMATES_5G_SA.get(groupIndices[COUNTRY_GROUP_INDEX_5G_SA]));
|
||||
// Assume default Wifi speed for Ethernet to prevent using the slower fallback.
|
||||
result.put(
|
||||
C.NETWORK_TYPE_ETHERNET,
|
||||
DEFAULT_INITIAL_BITRATE_ESTIMATES_WIFI.get(groupIndices.get(COUNTRY_GROUP_INDEX_WIFI)));
|
||||
DEFAULT_INITIAL_BITRATE_ESTIMATES_WIFI.get(groupIndices[COUNTRY_GROUP_INDEX_WIFI]));
|
||||
return result;
|
||||
}
|
||||
|
||||
private static ImmutableList<Integer> getCountryGroupIndices(String countryCode) {
|
||||
ImmutableList<Integer> groupIndices = DEFAULT_INITIAL_BITRATE_COUNTRY_GROUPS.get(countryCode);
|
||||
// Assume median group if not found.
|
||||
return groupIndices.isEmpty() ? ImmutableList.of(2, 2, 2, 2, 2, 2) : groupIndices;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -461,250 +463,411 @@ public final class DefaultBandwidthMeter implements BandwidthMeter, TransferList
|
|||
return isNetwork && !dataSpec.isFlagSet(DataSpec.FLAG_MIGHT_NOT_USE_FULL_NETWORK_SPEED);
|
||||
}
|
||||
|
||||
private static ImmutableListMultimap<String, Integer>
|
||||
createInitialBitrateCountryGroupAssignment() {
|
||||
return ImmutableListMultimap.<String, Integer>builder()
|
||||
.putAll("AD", 1, 2, 0, 0, 2, 2)
|
||||
.putAll("AE", 1, 4, 4, 4, 3, 2)
|
||||
.putAll("AF", 4, 4, 4, 4, 2, 2)
|
||||
.putAll("AG", 2, 3, 1, 2, 2, 2)
|
||||
.putAll("AI", 1, 2, 2, 2, 2, 2)
|
||||
.putAll("AL", 1, 2, 0, 1, 2, 2)
|
||||
.putAll("AM", 2, 3, 2, 4, 2, 2)
|
||||
.putAll("AO", 3, 4, 3, 2, 2, 2)
|
||||
.putAll("AQ", 4, 2, 2, 2, 2, 2)
|
||||
.putAll("AR", 2, 4, 1, 1, 2, 2)
|
||||
.putAll("AS", 2, 2, 2, 3, 2, 2)
|
||||
.putAll("AT", 0, 0, 0, 0, 0, 2)
|
||||
.putAll("AU", 0, 1, 0, 1, 2, 2)
|
||||
.putAll("AW", 1, 2, 4, 4, 2, 2)
|
||||
.putAll("AX", 0, 2, 2, 2, 2, 2)
|
||||
.putAll("AZ", 3, 2, 4, 4, 2, 2)
|
||||
.putAll("BA", 1, 2, 0, 1, 2, 2)
|
||||
.putAll("BB", 0, 2, 0, 0, 2, 2)
|
||||
.putAll("BD", 2, 1, 3, 3, 2, 2)
|
||||
.putAll("BE", 0, 0, 3, 3, 2, 2)
|
||||
.putAll("BF", 4, 3, 4, 3, 2, 2)
|
||||
.putAll("BG", 0, 0, 0, 0, 1, 2)
|
||||
.putAll("BH", 1, 2, 2, 4, 4, 2)
|
||||
.putAll("BI", 4, 3, 4, 4, 2, 2)
|
||||
.putAll("BJ", 4, 4, 3, 4, 2, 2)
|
||||
.putAll("BL", 1, 2, 2, 2, 2, 2)
|
||||
.putAll("BM", 1, 2, 0, 0, 2, 2)
|
||||
.putAll("BN", 3, 2, 1, 1, 2, 2)
|
||||
.putAll("BO", 1, 3, 3, 2, 2, 2)
|
||||
.putAll("BQ", 1, 2, 2, 0, 2, 2)
|
||||
.putAll("BR", 2, 3, 2, 2, 2, 2)
|
||||
.putAll("BS", 4, 2, 2, 3, 2, 2)
|
||||
.putAll("BT", 3, 1, 3, 2, 2, 2)
|
||||
.putAll("BW", 3, 4, 1, 0, 2, 2)
|
||||
.putAll("BY", 0, 1, 1, 3, 2, 2)
|
||||
.putAll("BZ", 2, 4, 2, 2, 2, 2)
|
||||
.putAll("CA", 0, 2, 1, 2, 4, 1)
|
||||
.putAll("CD", 4, 2, 3, 1, 2, 2)
|
||||
.putAll("CF", 4, 2, 3, 2, 2, 2)
|
||||
.putAll("CG", 2, 4, 3, 4, 2, 2)
|
||||
.putAll("CH", 0, 0, 0, 0, 0, 2)
|
||||
.putAll("CI", 3, 3, 3, 4, 2, 2)
|
||||
.putAll("CK", 2, 2, 2, 1, 2, 2)
|
||||
.putAll("CL", 1, 1, 2, 2, 3, 2)
|
||||
.putAll("CM", 3, 4, 3, 2, 2, 2)
|
||||
.putAll("CN", 2, 0, 2, 2, 3, 1)
|
||||
.putAll("CO", 2, 2, 4, 2, 2, 2)
|
||||
.putAll("CR", 2, 2, 4, 4, 2, 2)
|
||||
.putAll("CU", 4, 4, 3, 2, 2, 2)
|
||||
.putAll("CV", 2, 3, 1, 0, 2, 2)
|
||||
.putAll("CW", 2, 2, 0, 0, 2, 2)
|
||||
.putAll("CX", 1, 2, 2, 2, 2, 2)
|
||||
.putAll("CY", 1, 0, 0, 0, 1, 2)
|
||||
.putAll("CZ", 0, 0, 0, 0, 1, 2)
|
||||
.putAll("DE", 0, 0, 2, 2, 1, 2)
|
||||
.putAll("DJ", 4, 1, 4, 4, 2, 2)
|
||||
.putAll("DK", 0, 0, 1, 0, 0, 2)
|
||||
.putAll("DM", 1, 2, 2, 2, 2, 2)
|
||||
.putAll("DO", 3, 4, 4, 4, 2, 2)
|
||||
.putAll("DZ", 4, 3, 4, 4, 2, 2)
|
||||
.putAll("EC", 2, 4, 2, 1, 2, 2)
|
||||
.putAll("EE", 0, 0, 0, 0, 2, 2)
|
||||
.putAll("EG", 3, 4, 2, 3, 2, 2)
|
||||
.putAll("EH", 2, 2, 2, 2, 2, 2)
|
||||
.putAll("ER", 4, 2, 2, 2, 2, 2)
|
||||
.putAll("ES", 0, 1, 1, 1, 2, 2)
|
||||
.putAll("ET", 4, 4, 3, 1, 2, 2)
|
||||
.putAll("FI", 0, 0, 0, 1, 0, 2)
|
||||
.putAll("FJ", 3, 1, 3, 3, 2, 2)
|
||||
.putAll("FK", 3, 2, 2, 2, 2, 2)
|
||||
.putAll("FM", 3, 2, 4, 2, 2, 2)
|
||||
.putAll("FO", 0, 2, 0, 0, 2, 2)
|
||||
.putAll("FR", 1, 1, 2, 1, 1, 1)
|
||||
.putAll("GA", 2, 3, 1, 1, 2, 2)
|
||||
.putAll("GB", 0, 0, 1, 1, 2, 3)
|
||||
.putAll("GD", 1, 2, 2, 2, 2, 2)
|
||||
.putAll("GE", 1, 1, 1, 3, 2, 2)
|
||||
.putAll("GF", 2, 1, 2, 3, 2, 2)
|
||||
.putAll("GG", 0, 2, 0, 0, 2, 2)
|
||||
.putAll("GH", 3, 2, 3, 2, 2, 2)
|
||||
.putAll("GI", 0, 2, 2, 2, 2, 2)
|
||||
.putAll("GL", 1, 2, 0, 0, 2, 2)
|
||||
.putAll("GM", 4, 2, 2, 4, 2, 2)
|
||||
.putAll("GN", 4, 3, 4, 2, 2, 2)
|
||||
.putAll("GP", 2, 1, 2, 3, 2, 2)
|
||||
.putAll("GQ", 4, 2, 3, 4, 2, 2)
|
||||
.putAll("GR", 1, 0, 0, 0, 2, 2)
|
||||
.putAll("GT", 2, 3, 2, 1, 2, 2)
|
||||
.putAll("GU", 1, 2, 4, 4, 2, 2)
|
||||
.putAll("GW", 3, 4, 3, 3, 2, 2)
|
||||
.putAll("GY", 3, 4, 1, 0, 2, 2)
|
||||
.putAll("HK", 0, 1, 2, 3, 2, 0)
|
||||
.putAll("HN", 3, 2, 3, 3, 2, 2)
|
||||
.putAll("HR", 1, 0, 0, 0, 2, 2)
|
||||
.putAll("HT", 4, 4, 4, 4, 2, 2)
|
||||
.putAll("HU", 0, 0, 0, 1, 3, 2)
|
||||
.putAll("ID", 3, 2, 3, 3, 3, 2)
|
||||
.putAll("IE", 0, 1, 1, 1, 2, 2)
|
||||
.putAll("IL", 1, 1, 2, 3, 4, 2)
|
||||
.putAll("IM", 0, 2, 0, 1, 2, 2)
|
||||
.putAll("IN", 1, 1, 3, 2, 4, 3)
|
||||
.putAll("IO", 4, 2, 2, 2, 2, 2)
|
||||
.putAll("IQ", 3, 3, 3, 3, 2, 2)
|
||||
.putAll("IR", 3, 0, 1, 1, 3, 0)
|
||||
.putAll("IS", 0, 0, 0, 0, 0, 2)
|
||||
.putAll("IT", 0, 1, 0, 1, 1, 2)
|
||||
.putAll("JE", 3, 2, 1, 2, 2, 2)
|
||||
.putAll("JM", 3, 4, 4, 4, 2, 2)
|
||||
.putAll("JO", 1, 0, 0, 1, 2, 2)
|
||||
.putAll("JP", 0, 1, 0, 1, 1, 1)
|
||||
.putAll("KE", 3, 3, 2, 2, 2, 2)
|
||||
.putAll("KG", 2, 1, 1, 1, 2, 2)
|
||||
.putAll("KH", 1, 1, 4, 2, 2, 2)
|
||||
.putAll("KI", 4, 2, 4, 3, 2, 2)
|
||||
.putAll("KM", 4, 2, 4, 3, 2, 2)
|
||||
.putAll("KN", 2, 2, 2, 2, 2, 2)
|
||||
.putAll("KP", 3, 2, 2, 2, 2, 2)
|
||||
.putAll("KR", 0, 0, 1, 3, 4, 4)
|
||||
.putAll("KW", 1, 1, 0, 0, 0, 2)
|
||||
.putAll("KY", 1, 2, 0, 1, 2, 2)
|
||||
.putAll("KZ", 1, 1, 2, 2, 2, 2)
|
||||
.putAll("LA", 2, 2, 1, 2, 2, 2)
|
||||
.putAll("LB", 3, 2, 1, 4, 2, 2)
|
||||
.putAll("LC", 1, 2, 0, 0, 2, 2)
|
||||
.putAll("LI", 0, 2, 2, 2, 2, 2)
|
||||
.putAll("LK", 3, 1, 3, 4, 4, 2)
|
||||
.putAll("LR", 3, 4, 4, 3, 2, 2)
|
||||
.putAll("LS", 3, 3, 4, 3, 2, 2)
|
||||
.putAll("LT", 0, 0, 0, 0, 2, 2)
|
||||
.putAll("LU", 1, 0, 2, 2, 2, 2)
|
||||
.putAll("LV", 0, 0, 0, 0, 2, 2)
|
||||
.putAll("LY", 4, 2, 4, 3, 2, 2)
|
||||
.putAll("MA", 3, 2, 2, 2, 2, 2)
|
||||
.putAll("MC", 0, 2, 2, 0, 2, 2)
|
||||
.putAll("MD", 1, 0, 0, 0, 2, 2)
|
||||
.putAll("ME", 1, 0, 0, 1, 2, 2)
|
||||
.putAll("MF", 1, 2, 1, 0, 2, 2)
|
||||
.putAll("MG", 3, 4, 2, 2, 2, 2)
|
||||
.putAll("MH", 3, 2, 2, 4, 2, 2)
|
||||
.putAll("MK", 1, 0, 0, 0, 2, 2)
|
||||
.putAll("ML", 4, 3, 3, 1, 2, 2)
|
||||
.putAll("MM", 2, 4, 3, 3, 2, 2)
|
||||
.putAll("MN", 2, 0, 1, 2, 2, 2)
|
||||
.putAll("MO", 0, 2, 4, 4, 2, 2)
|
||||
.putAll("MP", 0, 2, 2, 2, 2, 2)
|
||||
.putAll("MQ", 2, 1, 2, 3, 2, 2)
|
||||
.putAll("MR", 4, 1, 3, 4, 2, 2)
|
||||
.putAll("MS", 1, 2, 2, 2, 2, 2)
|
||||
.putAll("MT", 0, 0, 0, 0, 2, 2)
|
||||
.putAll("MU", 3, 1, 1, 2, 2, 2)
|
||||
.putAll("MV", 3, 4, 1, 4, 2, 2)
|
||||
.putAll("MW", 4, 2, 1, 0, 2, 2)
|
||||
.putAll("MX", 2, 4, 3, 4, 2, 2)
|
||||
.putAll("MY", 2, 1, 3, 3, 2, 2)
|
||||
.putAll("MZ", 3, 2, 2, 2, 2, 2)
|
||||
.putAll("NA", 4, 3, 2, 2, 2, 2)
|
||||
.putAll("NC", 3, 2, 4, 4, 2, 2)
|
||||
.putAll("NE", 4, 4, 4, 4, 2, 2)
|
||||
.putAll("NF", 2, 2, 2, 2, 2, 2)
|
||||
.putAll("NG", 3, 4, 1, 1, 2, 2)
|
||||
.putAll("NI", 2, 3, 4, 3, 2, 2)
|
||||
.putAll("NL", 0, 0, 3, 2, 0, 4)
|
||||
.putAll("NO", 0, 0, 2, 0, 0, 2)
|
||||
.putAll("NP", 2, 1, 4, 3, 2, 2)
|
||||
.putAll("NR", 3, 2, 2, 0, 2, 2)
|
||||
.putAll("NU", 4, 2, 2, 2, 2, 2)
|
||||
.putAll("NZ", 1, 0, 1, 2, 4, 2)
|
||||
.putAll("OM", 2, 3, 1, 3, 4, 2)
|
||||
.putAll("PA", 1, 3, 3, 3, 2, 2)
|
||||
.putAll("PE", 2, 3, 4, 4, 4, 2)
|
||||
.putAll("PF", 2, 3, 3, 1, 2, 2)
|
||||
.putAll("PG", 4, 4, 3, 2, 2, 2)
|
||||
.putAll("PH", 2, 2, 3, 3, 3, 2)
|
||||
.putAll("PK", 3, 2, 3, 3, 2, 2)
|
||||
.putAll("PL", 1, 1, 2, 2, 3, 2)
|
||||
.putAll("PM", 0, 2, 2, 2, 2, 2)
|
||||
.putAll("PR", 2, 3, 2, 2, 3, 3)
|
||||
.putAll("PS", 3, 4, 1, 2, 2, 2)
|
||||
.putAll("PT", 0, 1, 0, 0, 2, 2)
|
||||
.putAll("PW", 2, 2, 4, 1, 2, 2)
|
||||
.putAll("PY", 2, 2, 3, 2, 2, 2)
|
||||
.putAll("QA", 2, 4, 2, 4, 4, 2)
|
||||
.putAll("RE", 1, 1, 1, 2, 2, 2)
|
||||
.putAll("RO", 0, 0, 1, 1, 1, 2)
|
||||
.putAll("RS", 1, 0, 0, 0, 2, 2)
|
||||
.putAll("RU", 0, 0, 0, 1, 2, 2)
|
||||
.putAll("RW", 3, 4, 3, 0, 2, 2)
|
||||
.putAll("SA", 2, 2, 1, 1, 2, 2)
|
||||
.putAll("SB", 4, 2, 4, 3, 2, 2)
|
||||
.putAll("SC", 4, 3, 0, 2, 2, 2)
|
||||
.putAll("SD", 4, 4, 4, 4, 2, 2)
|
||||
.putAll("SE", 0, 0, 0, 0, 0, 2)
|
||||
.putAll("SG", 1, 1, 2, 3, 1, 4)
|
||||
.putAll("SH", 4, 2, 2, 2, 2, 2)
|
||||
.putAll("SI", 0, 0, 0, 0, 1, 2)
|
||||
.putAll("SJ", 0, 2, 2, 2, 2, 2)
|
||||
.putAll("SK", 0, 0, 0, 0, 0, 2)
|
||||
.putAll("SL", 4, 3, 4, 1, 2, 2)
|
||||
.putAll("SM", 0, 2, 2, 2, 2, 2)
|
||||
.putAll("SN", 4, 4, 4, 4, 2, 2)
|
||||
.putAll("SO", 3, 2, 3, 3, 2, 2)
|
||||
.putAll("SR", 2, 3, 2, 2, 2, 2)
|
||||
.putAll("SS", 4, 2, 2, 2, 2, 2)
|
||||
.putAll("ST", 3, 2, 2, 2, 2, 2)
|
||||
.putAll("SV", 2, 2, 3, 3, 2, 2)
|
||||
.putAll("SX", 2, 2, 1, 0, 2, 2)
|
||||
.putAll("SY", 4, 3, 4, 4, 2, 2)
|
||||
.putAll("SZ", 4, 3, 2, 4, 2, 2)
|
||||
.putAll("TC", 2, 2, 1, 0, 2, 2)
|
||||
.putAll("TD", 4, 4, 4, 4, 2, 2)
|
||||
.putAll("TG", 3, 3, 2, 0, 2, 2)
|
||||
.putAll("TH", 0, 3, 2, 3, 3, 0)
|
||||
.putAll("TJ", 4, 2, 4, 4, 2, 2)
|
||||
.putAll("TL", 4, 3, 4, 4, 2, 2)
|
||||
.putAll("TM", 4, 2, 4, 2, 2, 2)
|
||||
.putAll("TN", 2, 2, 1, 1, 2, 2)
|
||||
.putAll("TO", 4, 2, 3, 3, 2, 2)
|
||||
.putAll("TR", 1, 1, 0, 1, 2, 2)
|
||||
.putAll("TT", 1, 4, 1, 1, 2, 2)
|
||||
.putAll("TV", 4, 2, 2, 2, 2, 2)
|
||||
.putAll("TW", 0, 0, 0, 0, 0, 0)
|
||||
.putAll("TZ", 3, 4, 3, 3, 2, 2)
|
||||
.putAll("UA", 0, 3, 1, 1, 2, 2)
|
||||
.putAll("UG", 3, 3, 3, 3, 2, 2)
|
||||
.putAll("US", 1, 1, 2, 2, 3, 2)
|
||||
.putAll("UY", 2, 2, 1, 2, 2, 2)
|
||||
.putAll("UZ", 2, 2, 3, 4, 2, 2)
|
||||
.putAll("VC", 1, 2, 2, 2, 2, 2)
|
||||
.putAll("VE", 4, 4, 4, 4, 2, 2)
|
||||
.putAll("VG", 2, 2, 1, 1, 2, 2)
|
||||
.putAll("VI", 1, 2, 1, 3, 2, 2)
|
||||
.putAll("VN", 0, 3, 3, 4, 2, 2)
|
||||
.putAll("VU", 4, 2, 2, 1, 2, 2)
|
||||
.putAll("WF", 4, 2, 2, 4, 2, 2)
|
||||
.putAll("WS", 3, 1, 2, 1, 2, 2)
|
||||
.putAll("XK", 1, 1, 1, 1, 2, 2)
|
||||
.putAll("YE", 4, 4, 4, 4, 2, 2)
|
||||
.putAll("YT", 4, 1, 1, 1, 2, 2)
|
||||
.putAll("ZA", 3, 3, 1, 1, 1, 2)
|
||||
.putAll("ZM", 3, 3, 4, 2, 2, 2)
|
||||
.putAll("ZW", 3, 2, 4, 3, 2, 2)
|
||||
.build();
|
||||
/**
|
||||
* Returns initial bitrate group assignments for a {@code country}. The initial bitrate is a list
|
||||
* of indexes for [Wifi, 2G, 3G, 4G, 5G_NSA, 5G_SA].
|
||||
*/
|
||||
private static int[] getInitialBitrateCountryGroupAssignment(String country) {
|
||||
switch (country) {
|
||||
case "AE":
|
||||
return new int[] {1, 4, 4, 4, 3, 2};
|
||||
case "AG":
|
||||
return new int[] {2, 3, 1, 2, 2, 2};
|
||||
case "AM":
|
||||
return new int[] {2, 3, 2, 4, 2, 2};
|
||||
case "AR":
|
||||
return new int[] {2, 4, 1, 1, 2, 2};
|
||||
case "AS":
|
||||
return new int[] {2, 2, 2, 3, 2, 2};
|
||||
case "AU":
|
||||
return new int[] {0, 1, 0, 1, 2, 2};
|
||||
case "BE":
|
||||
return new int[] {0, 0, 3, 3, 2, 2};
|
||||
case "BF":
|
||||
return new int[] {4, 3, 4, 3, 2, 2};
|
||||
case "BH":
|
||||
return new int[] {1, 2, 2, 4, 4, 2};
|
||||
case "BJ":
|
||||
return new int[] {4, 4, 3, 4, 2, 2};
|
||||
case "BN":
|
||||
return new int[] {3, 2, 1, 1, 2, 2};
|
||||
case "BO":
|
||||
return new int[] {1, 3, 3, 2, 2, 2};
|
||||
case "BQ":
|
||||
return new int[] {1, 2, 2, 0, 2, 2};
|
||||
case "BS":
|
||||
return new int[] {4, 2, 2, 3, 2, 2};
|
||||
case "BT":
|
||||
return new int[] {3, 1, 3, 2, 2, 2};
|
||||
case "BY":
|
||||
return new int[] {0, 1, 1, 3, 2, 2};
|
||||
case "BZ":
|
||||
return new int[] {2, 4, 2, 2, 2, 2};
|
||||
case "CA":
|
||||
return new int[] {0, 2, 1, 2, 4, 1};
|
||||
case "CD":
|
||||
return new int[] {4, 2, 3, 1, 2, 2};
|
||||
case "CF":
|
||||
return new int[] {4, 2, 3, 2, 2, 2};
|
||||
case "CI":
|
||||
return new int[] {3, 3, 3, 4, 2, 2};
|
||||
case "CK":
|
||||
return new int[] {2, 2, 2, 1, 2, 2};
|
||||
case "AO":
|
||||
case "CM":
|
||||
return new int[] {3, 4, 3, 2, 2, 2};
|
||||
case "CN":
|
||||
return new int[] {2, 0, 2, 2, 3, 1};
|
||||
case "CO":
|
||||
return new int[] {2, 2, 4, 2, 2, 2};
|
||||
case "CR":
|
||||
return new int[] {2, 2, 4, 4, 2, 2};
|
||||
case "CV":
|
||||
return new int[] {2, 3, 1, 0, 2, 2};
|
||||
case "CW":
|
||||
return new int[] {2, 2, 0, 0, 2, 2};
|
||||
case "CY":
|
||||
return new int[] {1, 0, 0, 0, 1, 2};
|
||||
case "DE":
|
||||
return new int[] {0, 0, 2, 2, 1, 2};
|
||||
case "DJ":
|
||||
return new int[] {4, 1, 4, 4, 2, 2};
|
||||
case "DK":
|
||||
return new int[] {0, 0, 1, 0, 0, 2};
|
||||
case "EC":
|
||||
return new int[] {2, 4, 2, 1, 2, 2};
|
||||
case "EG":
|
||||
return new int[] {3, 4, 2, 3, 2, 2};
|
||||
case "ET":
|
||||
return new int[] {4, 4, 3, 1, 2, 2};
|
||||
case "FI":
|
||||
return new int[] {0, 0, 0, 1, 0, 2};
|
||||
case "FJ":
|
||||
return new int[] {3, 1, 3, 3, 2, 2};
|
||||
case "FM":
|
||||
return new int[] {3, 2, 4, 2, 2, 2};
|
||||
case "FR":
|
||||
return new int[] {1, 1, 2, 1, 1, 1};
|
||||
case "GA":
|
||||
return new int[] {2, 3, 1, 1, 2, 2};
|
||||
case "GB":
|
||||
return new int[] {0, 0, 1, 1, 2, 3};
|
||||
case "GE":
|
||||
return new int[] {1, 1, 1, 3, 2, 2};
|
||||
case "BB":
|
||||
case "FO":
|
||||
case "GG":
|
||||
return new int[] {0, 2, 0, 0, 2, 2};
|
||||
case "GH":
|
||||
return new int[] {3, 2, 3, 2, 2, 2};
|
||||
case "GN":
|
||||
return new int[] {4, 3, 4, 2, 2, 2};
|
||||
case "GQ":
|
||||
return new int[] {4, 2, 3, 4, 2, 2};
|
||||
case "GT":
|
||||
return new int[] {2, 3, 2, 1, 2, 2};
|
||||
case "AW":
|
||||
case "GU":
|
||||
return new int[] {1, 2, 4, 4, 2, 2};
|
||||
case "BW":
|
||||
case "GY":
|
||||
return new int[] {3, 4, 1, 0, 2, 2};
|
||||
case "HK":
|
||||
return new int[] {0, 1, 2, 3, 2, 0};
|
||||
case "HU":
|
||||
return new int[] {0, 0, 0, 1, 3, 2};
|
||||
case "ID":
|
||||
return new int[] {3, 2, 3, 3, 3, 2};
|
||||
case "ES":
|
||||
case "IE":
|
||||
return new int[] {0, 1, 1, 1, 2, 2};
|
||||
case "IL":
|
||||
return new int[] {1, 1, 2, 3, 4, 2};
|
||||
case "IM":
|
||||
return new int[] {0, 2, 0, 1, 2, 2};
|
||||
case "IN":
|
||||
return new int[] {1, 1, 3, 2, 4, 3};
|
||||
case "IR":
|
||||
return new int[] {3, 0, 1, 1, 3, 0};
|
||||
case "IT":
|
||||
return new int[] {0, 1, 0, 1, 1, 2};
|
||||
case "JE":
|
||||
return new int[] {3, 2, 1, 2, 2, 2};
|
||||
case "DO":
|
||||
case "JM":
|
||||
return new int[] {3, 4, 4, 4, 2, 2};
|
||||
case "JP":
|
||||
return new int[] {0, 1, 0, 1, 1, 1};
|
||||
case "KE":
|
||||
return new int[] {3, 3, 2, 2, 2, 2};
|
||||
case "KG":
|
||||
return new int[] {2, 1, 1, 1, 2, 2};
|
||||
case "KH":
|
||||
return new int[] {1, 1, 4, 2, 2, 2};
|
||||
case "KR":
|
||||
return new int[] {0, 0, 1, 3, 4, 4};
|
||||
case "KW":
|
||||
return new int[] {1, 1, 0, 0, 0, 2};
|
||||
case "AL":
|
||||
case "BA":
|
||||
case "KY":
|
||||
return new int[] {1, 2, 0, 1, 2, 2};
|
||||
case "KZ":
|
||||
return new int[] {1, 1, 2, 2, 2, 2};
|
||||
case "LB":
|
||||
return new int[] {3, 2, 1, 4, 2, 2};
|
||||
case "AD":
|
||||
case "BM":
|
||||
case "GL":
|
||||
case "LC":
|
||||
return new int[] {1, 2, 0, 0, 2, 2};
|
||||
case "LK":
|
||||
return new int[] {3, 1, 3, 4, 4, 2};
|
||||
case "LR":
|
||||
return new int[] {3, 4, 4, 3, 2, 2};
|
||||
case "LS":
|
||||
return new int[] {3, 3, 4, 3, 2, 2};
|
||||
case "LU":
|
||||
return new int[] {1, 0, 2, 2, 2, 2};
|
||||
case "MC":
|
||||
return new int[] {0, 2, 2, 0, 2, 2};
|
||||
case "JO":
|
||||
case "ME":
|
||||
return new int[] {1, 0, 0, 1, 2, 2};
|
||||
case "MF":
|
||||
return new int[] {1, 2, 1, 0, 2, 2};
|
||||
case "MG":
|
||||
return new int[] {3, 4, 2, 2, 2, 2};
|
||||
case "MH":
|
||||
return new int[] {3, 2, 2, 4, 2, 2};
|
||||
case "ML":
|
||||
return new int[] {4, 3, 3, 1, 2, 2};
|
||||
case "MM":
|
||||
return new int[] {2, 4, 3, 3, 2, 2};
|
||||
case "MN":
|
||||
return new int[] {2, 0, 1, 2, 2, 2};
|
||||
case "MO":
|
||||
return new int[] {0, 2, 4, 4, 2, 2};
|
||||
case "GF":
|
||||
case "GP":
|
||||
case "MQ":
|
||||
return new int[] {2, 1, 2, 3, 2, 2};
|
||||
case "MR":
|
||||
return new int[] {4, 1, 3, 4, 2, 2};
|
||||
case "EE":
|
||||
case "LT":
|
||||
case "LV":
|
||||
case "MT":
|
||||
return new int[] {0, 0, 0, 0, 2, 2};
|
||||
case "MU":
|
||||
return new int[] {3, 1, 1, 2, 2, 2};
|
||||
case "MV":
|
||||
return new int[] {3, 4, 1, 4, 2, 2};
|
||||
case "MW":
|
||||
return new int[] {4, 2, 1, 0, 2, 2};
|
||||
case "CG":
|
||||
case "MX":
|
||||
return new int[] {2, 4, 3, 4, 2, 2};
|
||||
case "BD":
|
||||
case "MY":
|
||||
return new int[] {2, 1, 3, 3, 2, 2};
|
||||
case "NA":
|
||||
return new int[] {4, 3, 2, 2, 2, 2};
|
||||
case "AZ":
|
||||
case "NC":
|
||||
return new int[] {3, 2, 4, 4, 2, 2};
|
||||
case "NG":
|
||||
return new int[] {3, 4, 1, 1, 2, 2};
|
||||
case "NI":
|
||||
return new int[] {2, 3, 4, 3, 2, 2};
|
||||
case "NL":
|
||||
return new int[] {0, 0, 3, 2, 0, 4};
|
||||
case "NO":
|
||||
return new int[] {0, 0, 2, 0, 0, 2};
|
||||
case "NP":
|
||||
return new int[] {2, 1, 4, 3, 2, 2};
|
||||
case "NR":
|
||||
return new int[] {3, 2, 2, 0, 2, 2};
|
||||
case "NZ":
|
||||
return new int[] {1, 0, 1, 2, 4, 2};
|
||||
case "OM":
|
||||
return new int[] {2, 3, 1, 3, 4, 2};
|
||||
case "PA":
|
||||
return new int[] {1, 3, 3, 3, 2, 2};
|
||||
case "PE":
|
||||
return new int[] {2, 3, 4, 4, 4, 2};
|
||||
case "PF":
|
||||
return new int[] {2, 3, 3, 1, 2, 2};
|
||||
case "CU":
|
||||
case "PG":
|
||||
return new int[] {4, 4, 3, 2, 2, 2};
|
||||
case "PH":
|
||||
return new int[] {2, 2, 3, 3, 3, 2};
|
||||
case "PR":
|
||||
return new int[] {2, 3, 2, 2, 3, 3};
|
||||
case "PS":
|
||||
return new int[] {3, 4, 1, 2, 2, 2};
|
||||
case "PT":
|
||||
return new int[] {0, 1, 0, 0, 2, 2};
|
||||
case "PW":
|
||||
return new int[] {2, 2, 4, 1, 2, 2};
|
||||
case "PY":
|
||||
return new int[] {2, 2, 3, 2, 2, 2};
|
||||
case "QA":
|
||||
return new int[] {2, 4, 2, 4, 4, 2};
|
||||
case "RE":
|
||||
return new int[] {1, 1, 1, 2, 2, 2};
|
||||
case "RO":
|
||||
return new int[] {0, 0, 1, 1, 1, 2};
|
||||
case "GR":
|
||||
case "HR":
|
||||
case "MD":
|
||||
case "MK":
|
||||
case "RS":
|
||||
return new int[] {1, 0, 0, 0, 2, 2};
|
||||
case "RU":
|
||||
return new int[] {0, 0, 0, 1, 2, 2};
|
||||
case "RW":
|
||||
return new int[] {3, 4, 3, 0, 2, 2};
|
||||
case "KI":
|
||||
case "KM":
|
||||
case "LY":
|
||||
case "SB":
|
||||
return new int[] {4, 2, 4, 3, 2, 2};
|
||||
case "SC":
|
||||
return new int[] {4, 3, 0, 2, 2, 2};
|
||||
case "SG":
|
||||
return new int[] {1, 1, 2, 3, 1, 4};
|
||||
case "BG":
|
||||
case "CZ":
|
||||
case "SI":
|
||||
return new int[] {0, 0, 0, 0, 1, 2};
|
||||
case "AT":
|
||||
case "CH":
|
||||
case "IS":
|
||||
case "SE":
|
||||
case "SK":
|
||||
return new int[] {0, 0, 0, 0, 0, 2};
|
||||
case "SL":
|
||||
return new int[] {4, 3, 4, 1, 2, 2};
|
||||
case "AX":
|
||||
case "GI":
|
||||
case "LI":
|
||||
case "MP":
|
||||
case "PM":
|
||||
case "SJ":
|
||||
case "SM":
|
||||
return new int[] {0, 2, 2, 2, 2, 2};
|
||||
case "HN":
|
||||
case "PK":
|
||||
case "SO":
|
||||
return new int[] {3, 2, 3, 3, 2, 2};
|
||||
case "BR":
|
||||
case "SR":
|
||||
return new int[] {2, 3, 2, 2, 2, 2};
|
||||
case "FK":
|
||||
case "KP":
|
||||
case "MA":
|
||||
case "MZ":
|
||||
case "ST":
|
||||
return new int[] {3, 2, 2, 2, 2, 2};
|
||||
case "SV":
|
||||
return new int[] {2, 2, 3, 3, 2, 2};
|
||||
case "SZ":
|
||||
return new int[] {4, 3, 2, 4, 2, 2};
|
||||
case "SX":
|
||||
case "TC":
|
||||
return new int[] {2, 2, 1, 0, 2, 2};
|
||||
case "TG":
|
||||
return new int[] {3, 3, 2, 0, 2, 2};
|
||||
case "TH":
|
||||
return new int[] {0, 3, 2, 3, 3, 0};
|
||||
case "TJ":
|
||||
return new int[] {4, 2, 4, 4, 2, 2};
|
||||
case "BI":
|
||||
case "DZ":
|
||||
case "SY":
|
||||
case "TL":
|
||||
return new int[] {4, 3, 4, 4, 2, 2};
|
||||
case "TM":
|
||||
return new int[] {4, 2, 4, 2, 2, 2};
|
||||
case "TO":
|
||||
return new int[] {4, 2, 3, 3, 2, 2};
|
||||
case "TR":
|
||||
return new int[] {1, 1, 0, 1, 2, 2};
|
||||
case "TT":
|
||||
return new int[] {1, 4, 1, 1, 2, 2};
|
||||
case "AQ":
|
||||
case "ER":
|
||||
case "IO":
|
||||
case "NU":
|
||||
case "SH":
|
||||
case "SS":
|
||||
case "TV":
|
||||
return new int[] {4, 2, 2, 2, 2, 2};
|
||||
case "TW":
|
||||
return new int[] {0, 0, 0, 0, 0, 0};
|
||||
case "GW":
|
||||
case "TZ":
|
||||
return new int[] {3, 4, 3, 3, 2, 2};
|
||||
case "UA":
|
||||
return new int[] {0, 3, 1, 1, 2, 2};
|
||||
case "IQ":
|
||||
case "UG":
|
||||
return new int[] {3, 3, 3, 3, 2, 2};
|
||||
case "CL":
|
||||
case "PL":
|
||||
case "US":
|
||||
return new int[] {1, 1, 2, 2, 3, 2};
|
||||
case "LA":
|
||||
case "UY":
|
||||
return new int[] {2, 2, 1, 2, 2, 2};
|
||||
case "UZ":
|
||||
return new int[] {2, 2, 3, 4, 2, 2};
|
||||
case "AI":
|
||||
case "BL":
|
||||
case "CX":
|
||||
case "DM":
|
||||
case "GD":
|
||||
case "MS":
|
||||
case "VC":
|
||||
return new int[] {1, 2, 2, 2, 2, 2};
|
||||
case "SA":
|
||||
case "TN":
|
||||
case "VG":
|
||||
return new int[] {2, 2, 1, 1, 2, 2};
|
||||
case "VI":
|
||||
return new int[] {1, 2, 1, 3, 2, 2};
|
||||
case "VN":
|
||||
return new int[] {0, 3, 3, 4, 2, 2};
|
||||
case "VU":
|
||||
return new int[] {4, 2, 2, 1, 2, 2};
|
||||
case "GM":
|
||||
case "WF":
|
||||
return new int[] {4, 2, 2, 4, 2, 2};
|
||||
case "WS":
|
||||
return new int[] {3, 1, 2, 1, 2, 2};
|
||||
case "XK":
|
||||
return new int[] {1, 1, 1, 1, 2, 2};
|
||||
case "AF":
|
||||
case "HT":
|
||||
case "NE":
|
||||
case "SD":
|
||||
case "SN":
|
||||
case "TD":
|
||||
case "VE":
|
||||
case "YE":
|
||||
return new int[] {4, 4, 4, 4, 2, 2};
|
||||
case "YT":
|
||||
return new int[] {4, 1, 1, 1, 2, 2};
|
||||
case "ZA":
|
||||
return new int[] {3, 3, 1, 1, 1, 2};
|
||||
case "ZM":
|
||||
return new int[] {3, 3, 4, 2, 2, 2};
|
||||
case "ZW":
|
||||
return new int[] {3, 2, 4, 3, 2, 2};
|
||||
default:
|
||||
return new int[] {2, 2, 2, 2, 2, 2};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -138,8 +138,8 @@ public class DebugTextViewHelper implements Player.Listener, Runnable {
|
|||
break;
|
||||
}
|
||||
return String.format(
|
||||
"playWhenReady:%s playbackState:%s window:%s",
|
||||
player.getPlayWhenReady(), playbackStateString, player.getCurrentWindowIndex());
|
||||
"playWhenReady:%s playbackState:%s item:%s",
|
||||
player.getPlayWhenReady(), playbackStateString, player.getCurrentMediaItemIndex());
|
||||
}
|
||||
|
||||
/** Returns a string containing video debugging information. */
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -950,7 +950,7 @@ public class PlayerControlView extends FrameLayout {
|
|||
int adGroupCount = 0;
|
||||
Timeline timeline = player.getCurrentTimeline();
|
||||
if (!timeline.isEmpty()) {
|
||||
int currentWindowIndex = player.getCurrentWindowIndex();
|
||||
int currentWindowIndex = player.getCurrentMediaItemIndex();
|
||||
int firstWindowIndex = multiWindowTimeBar ? 0 : currentWindowIndex;
|
||||
int lastWindowIndex = multiWindowTimeBar ? timeline.getWindowCount() - 1 : currentWindowIndex;
|
||||
for (int i = firstWindowIndex; i <= lastWindowIndex; i++) {
|
||||
|
|
@ -1110,7 +1110,7 @@ public class PlayerControlView extends FrameLayout {
|
|||
windowIndex++;
|
||||
}
|
||||
} else {
|
||||
windowIndex = player.getCurrentWindowIndex();
|
||||
windowIndex = player.getCurrentMediaItemIndex();
|
||||
}
|
||||
seekTo(player, windowIndex, positionMs);
|
||||
updateProgress();
|
||||
|
|
@ -1228,7 +1228,7 @@ public class PlayerControlView extends FrameLayout {
|
|||
if (state == Player.STATE_IDLE) {
|
||||
player.prepare();
|
||||
} else if (state == Player.STATE_ENDED) {
|
||||
seekTo(player, player.getCurrentWindowIndex(), C.TIME_UNSET);
|
||||
seekTo(player, player.getCurrentMediaItemIndex(), C.TIME_UNSET);
|
||||
}
|
||||
player.play();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -605,9 +605,9 @@ public class PlayerNotificationManager {
|
|||
public static final String ACTION_PLAY = "com.google.android.exoplayer.play";
|
||||
/** The action which pauses playback. */
|
||||
public static final String ACTION_PAUSE = "com.google.android.exoplayer.pause";
|
||||
/** The action which skips to the previous window. */
|
||||
/** The action which skips to the previous media item. */
|
||||
public static final String ACTION_PREVIOUS = "com.google.android.exoplayer.prev";
|
||||
/** The action which skips to the next window. */
|
||||
/** The action which skips to the next media item. */
|
||||
public static final String ACTION_NEXT = "com.google.android.exoplayer.next";
|
||||
/** The action which fast forwards. */
|
||||
public static final String ACTION_FAST_FORWARD = "com.google.android.exoplayer.ffwd";
|
||||
|
|
@ -1095,7 +1095,7 @@ public class PlayerNotificationManager {
|
|||
*
|
||||
* <ul>
|
||||
* <li>The media is {@link Player#isPlaying() actively playing}.
|
||||
* <li>The media is not {@link Player#isCurrentWindowDynamic() dynamically changing its
|
||||
* <li>The media is not {@link Player#isCurrentMediaItemDynamic() dynamically changing its
|
||||
* duration} (like for example a live stream).
|
||||
* <li>The media is not {@link Player#isPlayingAd() interrupted by an ad}.
|
||||
* <li>The media is played at {@link Player#getPlaybackParameters() regular speed}.
|
||||
|
|
@ -1253,7 +1253,7 @@ public class PlayerNotificationManager {
|
|||
&& useChronometer
|
||||
&& player.isPlaying()
|
||||
&& !player.isPlayingAd()
|
||||
&& !player.isCurrentWindowDynamic()
|
||||
&& !player.isCurrentMediaItemDynamic()
|
||||
&& player.getPlaybackParameters().speed == 1f) {
|
||||
builder
|
||||
.setWhen(System.currentTimeMillis() - player.getContentPosition())
|
||||
|
|
@ -1531,7 +1531,7 @@ public class PlayerNotificationManager {
|
|||
if (player.getPlaybackState() == Player.STATE_IDLE) {
|
||||
player.prepare();
|
||||
} else if (player.getPlaybackState() == Player.STATE_ENDED) {
|
||||
player.seekToDefaultPosition(player.getCurrentWindowIndex());
|
||||
player.seekToDefaultPosition(player.getCurrentMediaItemIndex());
|
||||
}
|
||||
player.play();
|
||||
} else if (ACTION_PAUSE.equals(action)) {
|
||||
|
|
|
|||
|
|
@ -1501,8 +1501,8 @@ public class PlayerView extends FrameLayout implements AdViewProvider {
|
|||
if (lastPeriodIndexWithTracks != C.INDEX_UNSET) {
|
||||
int lastWindowIndexWithTracks =
|
||||
timeline.getPeriod(lastPeriodIndexWithTracks, period).windowIndex;
|
||||
if (player.getCurrentWindowIndex() == lastWindowIndexWithTracks) {
|
||||
// We're in the same window. Suppress the update.
|
||||
if (player.getCurrentMediaItemIndex() == lastWindowIndexWithTracks) {
|
||||
// We're in the same media item. Suppress the update.
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1269,7 +1269,7 @@ public class StyledPlayerControlView extends FrameLayout {
|
|||
int adGroupCount = 0;
|
||||
Timeline timeline = player.getCurrentTimeline();
|
||||
if (!timeline.isEmpty()) {
|
||||
int currentWindowIndex = player.getCurrentWindowIndex();
|
||||
int currentWindowIndex = player.getCurrentMediaItemIndex();
|
||||
int firstWindowIndex = multiWindowTimeBar ? 0 : currentWindowIndex;
|
||||
int lastWindowIndex = multiWindowTimeBar ? timeline.getWindowCount() - 1 : currentWindowIndex;
|
||||
for (int i = firstWindowIndex; i <= lastWindowIndex; i++) {
|
||||
|
|
@ -1453,7 +1453,7 @@ public class StyledPlayerControlView extends FrameLayout {
|
|||
windowIndex++;
|
||||
}
|
||||
} else {
|
||||
windowIndex = player.getCurrentWindowIndex();
|
||||
windowIndex = player.getCurrentMediaItemIndex();
|
||||
}
|
||||
seekTo(player, windowIndex, positionMs);
|
||||
updateProgress();
|
||||
|
|
@ -1616,13 +1616,12 @@ public class StyledPlayerControlView extends FrameLayout {
|
|||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private void dispatchPlay(Player player) {
|
||||
@State int state = player.getPlaybackState();
|
||||
if (state == Player.STATE_IDLE) {
|
||||
player.prepare();
|
||||
} else if (state == Player.STATE_ENDED) {
|
||||
seekTo(player, player.getCurrentWindowIndex(), C.TIME_UNSET);
|
||||
seekTo(player, player.getCurrentMediaItemIndex(), C.TIME_UNSET);
|
||||
}
|
||||
player.play();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1540,8 +1540,8 @@ public class StyledPlayerView extends FrameLayout implements AdViewProvider {
|
|||
if (lastPeriodIndexWithTracks != C.INDEX_UNSET) {
|
||||
int lastWindowIndexWithTracks =
|
||||
timeline.getPeriod(lastPeriodIndexWithTracks, period).windowIndex;
|
||||
if (player.getCurrentWindowIndex() == lastWindowIndexWithTracks) {
|
||||
// We're in the same window. Suppress the update.
|
||||
if (player.getCurrentMediaItemIndex() == lastWindowIndexWithTracks) {
|
||||
// We're in the same media item. Suppress the update.
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -284,12 +284,12 @@ public class TestPlayerRunHelper {
|
|||
* <p>If a playback error occurs it will be thrown wrapped in an {@link IllegalStateException}.
|
||||
*
|
||||
* @param player The {@link Player}.
|
||||
* @param windowIndex The window.
|
||||
* @param positionMs The position within the window, in milliseconds.
|
||||
* @param mediaItemIndex The index of the media item.
|
||||
* @param positionMs The position within the media item, in milliseconds.
|
||||
* @throws TimeoutException If the {@link RobolectricUtil#DEFAULT_TIMEOUT_MS default timeout} is
|
||||
* exceeded.
|
||||
*/
|
||||
public static void playUntilPosition(ExoPlayer player, int windowIndex, long positionMs)
|
||||
public static void playUntilPosition(ExoPlayer player, int mediaItemIndex, long positionMs)
|
||||
throws TimeoutException {
|
||||
verifyMainTestThread(player);
|
||||
Looper applicationLooper = Util.getCurrentOrMainLooper();
|
||||
|
|
@ -315,7 +315,7 @@ public class TestPlayerRunHelper {
|
|||
// Ignore.
|
||||
}
|
||||
})
|
||||
.setPosition(windowIndex, positionMs)
|
||||
.setPosition(mediaItemIndex, positionMs)
|
||||
.send();
|
||||
player.play();
|
||||
runMainLooperUntil(() -> messageHandled.get() || player.getPlayerError() != null);
|
||||
|
|
@ -326,18 +326,19 @@ public class TestPlayerRunHelper {
|
|||
|
||||
/**
|
||||
* Calls {@link Player#play()}, runs tasks of the main {@link Looper} until the {@code player}
|
||||
* reaches the specified window or a playback error occurs, and then pauses the {@code player}.
|
||||
* reaches the specified media item or a playback error occurs, and then pauses the {@code
|
||||
* player}.
|
||||
*
|
||||
* <p>If a playback error occurs it will be thrown wrapped in an {@link IllegalStateException}.
|
||||
*
|
||||
* @param player The {@link Player}.
|
||||
* @param windowIndex The window.
|
||||
* @param mediaItemIndex The index of the media item.
|
||||
* @throws TimeoutException If the {@link RobolectricUtil#DEFAULT_TIMEOUT_MS default timeout} is
|
||||
* exceeded.
|
||||
*/
|
||||
public static void playUntilStartOfWindow(ExoPlayer player, int windowIndex)
|
||||
public static void playUntilStartOfMediaItem(ExoPlayer player, int mediaItemIndex)
|
||||
throws TimeoutException {
|
||||
playUntilPosition(player, windowIndex, /* positionMs= */ 0);
|
||||
playUntilPosition(player, mediaItemIndex, /* positionMs= */ 0);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -121,7 +121,7 @@ public abstract class Action {
|
|||
/** Calls {@link Player#seekTo(long)} or {@link Player#seekTo(int, long)}. */
|
||||
public static final class Seek extends Action {
|
||||
|
||||
@Nullable private final Integer windowIndex;
|
||||
@Nullable private final Integer mediaItemIndex;
|
||||
private final long positionMs;
|
||||
private final boolean catchIllegalSeekException;
|
||||
|
||||
|
|
@ -133,7 +133,7 @@ public abstract class Action {
|
|||
*/
|
||||
public Seek(String tag, long positionMs) {
|
||||
super(tag, "Seek:" + positionMs);
|
||||
this.windowIndex = null;
|
||||
this.mediaItemIndex = null;
|
||||
this.positionMs = positionMs;
|
||||
catchIllegalSeekException = false;
|
||||
}
|
||||
|
|
@ -142,14 +142,15 @@ public abstract class Action {
|
|||
* Action calls {@link Player#seekTo(int, long)}.
|
||||
*
|
||||
* @param tag A tag to use for logging.
|
||||
* @param windowIndex The window to seek to.
|
||||
* @param mediaItemIndex The media item to seek to.
|
||||
* @param positionMs The seek position.
|
||||
* @param catchIllegalSeekException Whether {@link IllegalSeekPositionException} should be
|
||||
* silently caught or not.
|
||||
*/
|
||||
public Seek(String tag, int windowIndex, long positionMs, boolean catchIllegalSeekException) {
|
||||
public Seek(
|
||||
String tag, int mediaItemIndex, long positionMs, boolean catchIllegalSeekException) {
|
||||
super(tag, "Seek:" + positionMs);
|
||||
this.windowIndex = windowIndex;
|
||||
this.mediaItemIndex = mediaItemIndex;
|
||||
this.positionMs = positionMs;
|
||||
this.catchIllegalSeekException = catchIllegalSeekException;
|
||||
}
|
||||
|
|
@ -158,10 +159,10 @@ public abstract class Action {
|
|||
protected void doActionImpl(
|
||||
ExoPlayer player, DefaultTrackSelector trackSelector, @Nullable Surface surface) {
|
||||
try {
|
||||
if (windowIndex == null) {
|
||||
if (mediaItemIndex == null) {
|
||||
player.seekTo(positionMs);
|
||||
} else {
|
||||
player.seekTo(windowIndex, positionMs);
|
||||
player.seekTo(mediaItemIndex, positionMs);
|
||||
}
|
||||
} catch (IllegalSeekPositionException e) {
|
||||
if (!catchIllegalSeekException) {
|
||||
|
|
@ -174,20 +175,20 @@ public abstract class Action {
|
|||
/** Calls {@link ExoPlayer#setMediaSources(List, int, long)}. */
|
||||
public static final class SetMediaItems extends Action {
|
||||
|
||||
private final int windowIndex;
|
||||
private final int mediaItemIndex;
|
||||
private final long positionMs;
|
||||
private final MediaSource[] mediaSources;
|
||||
|
||||
/**
|
||||
* @param tag A tag to use for logging.
|
||||
* @param windowIndex The window index to start playback from.
|
||||
* @param mediaItemIndex The media item index to start playback from.
|
||||
* @param positionMs The position in milliseconds to start playback from.
|
||||
* @param mediaSources The media sources to populate the playlist with.
|
||||
*/
|
||||
public SetMediaItems(
|
||||
String tag, int windowIndex, long positionMs, MediaSource... mediaSources) {
|
||||
String tag, int mediaItemIndex, long positionMs, MediaSource... mediaSources) {
|
||||
super(tag, "SetMediaItems");
|
||||
this.windowIndex = windowIndex;
|
||||
this.mediaItemIndex = mediaItemIndex;
|
||||
this.positionMs = positionMs;
|
||||
this.mediaSources = mediaSources;
|
||||
}
|
||||
|
|
@ -195,7 +196,7 @@ public abstract class Action {
|
|||
@Override
|
||||
protected void doActionImpl(
|
||||
ExoPlayer player, DefaultTrackSelector trackSelector, @Nullable Surface surface) {
|
||||
player.setMediaSources(Arrays.asList(mediaSources), windowIndex, positionMs);
|
||||
player.setMediaSources(Arrays.asList(mediaSources), mediaItemIndex, positionMs);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -553,7 +554,7 @@ public abstract class Action {
|
|||
public static final class SendMessages extends Action {
|
||||
|
||||
private final Target target;
|
||||
private final int windowIndex;
|
||||
private final int mediaItemIndex;
|
||||
private final long positionMs;
|
||||
private final boolean deleteAfterDelivery;
|
||||
|
||||
|
|
@ -566,7 +567,7 @@ public abstract class Action {
|
|||
this(
|
||||
tag,
|
||||
target,
|
||||
/* windowIndex= */ C.INDEX_UNSET,
|
||||
/* mediaItemIndex= */ C.INDEX_UNSET,
|
||||
positionMs,
|
||||
/* deleteAfterDelivery= */ true);
|
||||
}
|
||||
|
|
@ -574,16 +575,20 @@ public abstract class Action {
|
|||
/**
|
||||
* @param tag A tag to use for logging.
|
||||
* @param target A message target.
|
||||
* @param windowIndex The window index at which the message should be sent, or {@link
|
||||
* C#INDEX_UNSET} for the current window.
|
||||
* @param mediaItemIndex The media item index at which the message should be sent, or {@link
|
||||
* C#INDEX_UNSET} for the current media item.
|
||||
* @param positionMs The position at which the message should be sent, in milliseconds.
|
||||
* @param deleteAfterDelivery Whether the message will be deleted after delivery.
|
||||
*/
|
||||
public SendMessages(
|
||||
String tag, Target target, int windowIndex, long positionMs, boolean deleteAfterDelivery) {
|
||||
String tag,
|
||||
Target target,
|
||||
int mediaItemIndex,
|
||||
long positionMs,
|
||||
boolean deleteAfterDelivery) {
|
||||
super(tag, "SendMessages");
|
||||
this.target = target;
|
||||
this.windowIndex = windowIndex;
|
||||
this.mediaItemIndex = mediaItemIndex;
|
||||
this.positionMs = positionMs;
|
||||
this.deleteAfterDelivery = deleteAfterDelivery;
|
||||
}
|
||||
|
|
@ -595,8 +600,8 @@ public abstract class Action {
|
|||
((PlayerTarget) target).setPlayer(player);
|
||||
}
|
||||
PlayerMessage message = player.createMessage(target);
|
||||
if (windowIndex != C.INDEX_UNSET) {
|
||||
message.setPosition(windowIndex, positionMs);
|
||||
if (mediaItemIndex != C.INDEX_UNSET) {
|
||||
message.setPosition(mediaItemIndex, positionMs);
|
||||
} else {
|
||||
message.setPosition(positionMs);
|
||||
}
|
||||
|
|
@ -661,17 +666,17 @@ public abstract class Action {
|
|||
*/
|
||||
public static final class PlayUntilPosition extends Action {
|
||||
|
||||
private final int windowIndex;
|
||||
private final int mediaItemIndex;
|
||||
private final long positionMs;
|
||||
|
||||
/**
|
||||
* @param tag A tag to use for logging.
|
||||
* @param windowIndex The window index at which the player should be paused again.
|
||||
* @param positionMs The position in that window at which the player should be paused again.
|
||||
* @param mediaItemIndex The media item index at which the player should be paused again.
|
||||
* @param positionMs The position in that media item at which the player should be paused again.
|
||||
*/
|
||||
public PlayUntilPosition(String tag, int windowIndex, long positionMs) {
|
||||
super(tag, "PlayUntilPosition:" + windowIndex + ":" + positionMs);
|
||||
this.windowIndex = windowIndex;
|
||||
public PlayUntilPosition(String tag, int mediaItemIndex, long positionMs) {
|
||||
super(tag, "PlayUntilPosition:" + mediaItemIndex + ":" + positionMs);
|
||||
this.mediaItemIndex = mediaItemIndex;
|
||||
this.positionMs = positionMs;
|
||||
}
|
||||
|
||||
|
|
@ -704,7 +709,7 @@ public abstract class Action {
|
|||
// Ignore.
|
||||
}
|
||||
})
|
||||
.setPosition(windowIndex, positionMs)
|
||||
.setPosition(mediaItemIndex, positionMs)
|
||||
.send();
|
||||
if (nextAction != null) {
|
||||
// Schedule another message on this test thread to continue action schedule.
|
||||
|
|
@ -712,7 +717,7 @@ public abstract class Action {
|
|||
.createMessage(
|
||||
(messageType, payload) ->
|
||||
nextAction.schedule(player, trackSelector, surface, handler))
|
||||
.setPosition(windowIndex, positionMs)
|
||||
.setPosition(mediaItemIndex, positionMs)
|
||||
.setLooper(applicationLooper)
|
||||
.send();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -161,24 +161,25 @@ public final class ActionSchedule {
|
|||
/**
|
||||
* Schedules a seek action.
|
||||
*
|
||||
* @param windowIndex The window to seek to.
|
||||
* @param mediaItemIndex The media item to seek to.
|
||||
* @param positionMs The seek position.
|
||||
* @return The builder, for convenience.
|
||||
*/
|
||||
public Builder seek(int windowIndex, long positionMs) {
|
||||
return apply(new Seek(tag, windowIndex, positionMs, /* catchIllegalSeekException= */ false));
|
||||
public Builder seek(int mediaItemIndex, long positionMs) {
|
||||
return apply(
|
||||
new Seek(tag, mediaItemIndex, positionMs, /* catchIllegalSeekException= */ false));
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedules a seek action to be executed.
|
||||
*
|
||||
* @param windowIndex The window to seek to.
|
||||
* @param mediaItemIndex The media item to seek to.
|
||||
* @param positionMs The seek position.
|
||||
* @param catchIllegalSeekException Whether an illegal seek position should be caught or not.
|
||||
* @return The builder, for convenience.
|
||||
*/
|
||||
public Builder seek(int windowIndex, long positionMs, boolean catchIllegalSeekException) {
|
||||
return apply(new Seek(tag, windowIndex, positionMs, catchIllegalSeekException));
|
||||
public Builder seek(int mediaItemIndex, long positionMs, boolean catchIllegalSeekException) {
|
||||
return apply(new Seek(tag, mediaItemIndex, positionMs, catchIllegalSeekException));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -247,23 +248,23 @@ public final class ActionSchedule {
|
|||
* Schedules a play action, waits until the player reaches the specified position, and pauses
|
||||
* the player again.
|
||||
*
|
||||
* @param windowIndex The window index at which the player should be paused again.
|
||||
* @param positionMs The position in that window at which the player should be paused again.
|
||||
* @param mediaItemIndex The media item index at which the player should be paused again.
|
||||
* @param positionMs The position in that media item at which the player should be paused again.
|
||||
* @return The builder, for convenience.
|
||||
*/
|
||||
public Builder playUntilPosition(int windowIndex, long positionMs) {
|
||||
return apply(new PlayUntilPosition(tag, windowIndex, positionMs));
|
||||
public Builder playUntilPosition(int mediaItemIndex, long positionMs) {
|
||||
return apply(new PlayUntilPosition(tag, mediaItemIndex, positionMs));
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedules a play action, waits until the player reaches the start of the specified window,
|
||||
* and pauses the player again.
|
||||
* Schedules a play action, waits until the player reaches the start of the specified media
|
||||
* item, and pauses the player again.
|
||||
*
|
||||
* @param windowIndex The window index at which the player should be paused again.
|
||||
* @param mediaItemIndex The media item index at which the player should be paused again.
|
||||
* @return The builder, for convenience.
|
||||
*/
|
||||
public Builder playUntilStartOfWindow(int windowIndex) {
|
||||
return apply(new PlayUntilPosition(tag, windowIndex, /* positionMs= */ 0));
|
||||
public Builder playUntilStartOfMediaItem(int mediaItemIndex) {
|
||||
return apply(new PlayUntilPosition(tag, mediaItemIndex, /* positionMs= */ 0));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -323,16 +324,16 @@ public final class ActionSchedule {
|
|||
/**
|
||||
* Schedules a set media items action to be executed.
|
||||
*
|
||||
* @param windowIndex The window index to start playback from or {@link C#INDEX_UNSET} if the
|
||||
* playback position should not be reset.
|
||||
* @param mediaItemIndex The media item index to start playback from or {@link C#INDEX_UNSET} if
|
||||
* the playback position should not be reset.
|
||||
* @param positionMs The position in milliseconds from where playback should start. If {@link
|
||||
* C#TIME_UNSET} is passed the default position is used. In any case, if {@code windowIndex}
|
||||
* is set to {@link C#INDEX_UNSET} the position is not reset at all and this parameter is
|
||||
* ignored.
|
||||
* C#TIME_UNSET} is passed the default position is used. In any case, if {@code
|
||||
* mediaItemIndex} is set to {@link C#INDEX_UNSET} the position is not reset at all and this
|
||||
* parameter is ignored.
|
||||
* @return The builder, for convenience.
|
||||
*/
|
||||
public Builder setMediaSources(int windowIndex, long positionMs, MediaSource... sources) {
|
||||
return apply(new Action.SetMediaItems(tag, windowIndex, positionMs, sources));
|
||||
public Builder setMediaSources(int mediaItemIndex, long positionMs, MediaSource... sources) {
|
||||
return apply(new Action.SetMediaItems(tag, mediaItemIndex, positionMs, sources));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -354,7 +355,10 @@ public final class ActionSchedule {
|
|||
public Builder setMediaSources(MediaSource... mediaSources) {
|
||||
return apply(
|
||||
new Action.SetMediaItems(
|
||||
tag, /* windowIndex= */ C.INDEX_UNSET, /* positionMs= */ C.TIME_UNSET, mediaSources));
|
||||
tag,
|
||||
/* mediaItemIndex= */ C.INDEX_UNSET,
|
||||
/* positionMs= */ C.TIME_UNSET,
|
||||
mediaSources));
|
||||
}
|
||||
/**
|
||||
* Schedules a add media items action to be executed.
|
||||
|
|
@ -447,8 +451,8 @@ public final class ActionSchedule {
|
|||
/**
|
||||
* Schedules sending a {@link PlayerMessage}.
|
||||
*
|
||||
* @param positionMs The position in the current window at which the message should be sent, in
|
||||
* milliseconds.
|
||||
* @param positionMs The position in the current media item at which the message should be sent,
|
||||
* in milliseconds.
|
||||
* @return The builder, for convenience.
|
||||
*/
|
||||
public Builder sendMessage(Target target, long positionMs) {
|
||||
|
|
@ -459,27 +463,28 @@ public final class ActionSchedule {
|
|||
* Schedules sending a {@link PlayerMessage}.
|
||||
*
|
||||
* @param target A message target.
|
||||
* @param windowIndex The window index at which the message should be sent.
|
||||
* @param mediaItemIndex The media item index at which the message should be sent.
|
||||
* @param positionMs The position at which the message should be sent, in milliseconds.
|
||||
* @return The builder, for convenience.
|
||||
*/
|
||||
public Builder sendMessage(Target target, int windowIndex, long positionMs) {
|
||||
public Builder sendMessage(Target target, int mediaItemIndex, long positionMs) {
|
||||
return apply(
|
||||
new SendMessages(tag, target, windowIndex, positionMs, /* deleteAfterDelivery= */ true));
|
||||
new SendMessages(
|
||||
tag, target, mediaItemIndex, positionMs, /* deleteAfterDelivery= */ true));
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedules to send a {@link PlayerMessage}.
|
||||
*
|
||||
* @param target A message target.
|
||||
* @param windowIndex The window index at which the message should be sent.
|
||||
* @param mediaItemIndex The media item index at which the message should be sent.
|
||||
* @param positionMs The position at which the message should be sent, in milliseconds.
|
||||
* @param deleteAfterDelivery Whether the message will be deleted after delivery.
|
||||
* @return The builder, for convenience.
|
||||
*/
|
||||
public Builder sendMessage(
|
||||
Target target, int windowIndex, long positionMs, boolean deleteAfterDelivery) {
|
||||
return apply(new SendMessages(tag, target, windowIndex, positionMs, deleteAfterDelivery));
|
||||
Target target, int mediaItemIndex, long positionMs, boolean deleteAfterDelivery) {
|
||||
return apply(new SendMessages(tag, target, mediaItemIndex, positionMs, deleteAfterDelivery));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -85,7 +85,7 @@ public final class ExoPlayerTestRunner implements Player.Listener, ActionSchedul
|
|||
private AnalyticsListener analyticsListener;
|
||||
private Integer expectedPlayerEndedCount;
|
||||
private boolean pauseAtEndOfMediaItems;
|
||||
private int initialWindowIndex;
|
||||
private int initialMediaItemIndex;
|
||||
private long initialPositionMs;
|
||||
private boolean skipSettingMediaSources;
|
||||
|
||||
|
|
@ -93,7 +93,7 @@ public final class ExoPlayerTestRunner implements Player.Listener, ActionSchedul
|
|||
testPlayerBuilder = new TestExoPlayerBuilder(context);
|
||||
mediaSources = new ArrayList<>();
|
||||
supportedFormats = new Format[] {VIDEO_FORMAT};
|
||||
initialWindowIndex = C.INDEX_UNSET;
|
||||
initialMediaItemIndex = C.INDEX_UNSET;
|
||||
initialPositionMs = C.TIME_UNSET;
|
||||
}
|
||||
|
||||
|
|
@ -133,12 +133,12 @@ public final class ExoPlayerTestRunner implements Player.Listener, ActionSchedul
|
|||
/**
|
||||
* Seeks before setting the media sources and preparing the player.
|
||||
*
|
||||
* @param windowIndex The window index to seek to.
|
||||
* @param mediaItemIndex The media item index to seek to.
|
||||
* @param positionMs The position in milliseconds to seek to.
|
||||
* @return This builder.
|
||||
*/
|
||||
public Builder initialSeek(int windowIndex, long positionMs) {
|
||||
this.initialWindowIndex = windowIndex;
|
||||
public Builder initialSeek(int mediaItemIndex, long positionMs) {
|
||||
this.initialMediaItemIndex = mediaItemIndex;
|
||||
this.initialPositionMs = positionMs;
|
||||
return this;
|
||||
}
|
||||
|
|
@ -343,7 +343,7 @@ public final class ExoPlayerTestRunner implements Player.Listener, ActionSchedul
|
|||
testPlayerBuilder,
|
||||
mediaSources,
|
||||
skipSettingMediaSources,
|
||||
initialWindowIndex,
|
||||
initialMediaItemIndex,
|
||||
initialPositionMs,
|
||||
surface,
|
||||
actionSchedule,
|
||||
|
|
@ -357,7 +357,7 @@ public final class ExoPlayerTestRunner implements Player.Listener, ActionSchedul
|
|||
private final TestExoPlayerBuilder playerBuilder;
|
||||
private final List<MediaSource> mediaSources;
|
||||
private final boolean skipSettingMediaSources;
|
||||
private final int initialWindowIndex;
|
||||
private final int initialMediaItemIndex;
|
||||
private final long initialPositionMs;
|
||||
@Nullable private final Surface surface;
|
||||
@Nullable private final ActionSchedule actionSchedule;
|
||||
|
|
@ -386,7 +386,7 @@ public final class ExoPlayerTestRunner implements Player.Listener, ActionSchedul
|
|||
TestExoPlayerBuilder playerBuilder,
|
||||
List<MediaSource> mediaSources,
|
||||
boolean skipSettingMediaSources,
|
||||
int initialWindowIndex,
|
||||
int initialMediaItemIndex,
|
||||
long initialPositionMs,
|
||||
@Nullable Surface surface,
|
||||
@Nullable ActionSchedule actionSchedule,
|
||||
|
|
@ -397,7 +397,7 @@ public final class ExoPlayerTestRunner implements Player.Listener, ActionSchedul
|
|||
this.playerBuilder = playerBuilder;
|
||||
this.mediaSources = mediaSources;
|
||||
this.skipSettingMediaSources = skipSettingMediaSources;
|
||||
this.initialWindowIndex = initialWindowIndex;
|
||||
this.initialMediaItemIndex = initialMediaItemIndex;
|
||||
this.initialPositionMs = initialPositionMs;
|
||||
this.surface = surface;
|
||||
this.actionSchedule = actionSchedule;
|
||||
|
|
@ -466,8 +466,8 @@ public final class ExoPlayerTestRunner implements Player.Listener, ActionSchedul
|
|||
handler,
|
||||
/* callback= */ ExoPlayerTestRunner.this);
|
||||
}
|
||||
if (initialWindowIndex != C.INDEX_UNSET) {
|
||||
player.seekTo(initialWindowIndex, initialPositionMs);
|
||||
if (initialMediaItemIndex != C.INDEX_UNSET) {
|
||||
player.seekTo(initialMediaItemIndex, initialPositionMs);
|
||||
}
|
||||
if (!skipSettingMediaSources) {
|
||||
player.setMediaSources(mediaSources, /* resetPosition= */ false);
|
||||
|
|
|
|||
|
|
@ -162,7 +162,7 @@ public class StubExoPlayer extends StubPlayer implements ExoPlayer {
|
|||
|
||||
@Override
|
||||
public void setMediaSources(
|
||||
List<MediaSource> mediaSources, int startWindowIndex, long startPositionMs) {
|
||||
List<MediaSource> mediaSources, int startMediaItemIndex, long startPositionMs) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue