Refactor ComponentListener of PlayerWrapper

PiperOrigin-RevId: 343432873
This commit is contained in:
sungsoo 2020-11-20 06:06:55 +00:00 committed by Ian Baker
parent 8c8176647c
commit d67b70340e
3 changed files with 88 additions and 112 deletions

View File

@ -80,6 +80,9 @@
that lie outside the length of the cue text. that lie outside the length of the cue text.
* Metadata retriever: * Metadata retriever:
* Parse Google Photos HEIC motion photos metadata. * Parse Google Photos HEIC motion photos metadata.
* Media2 extention:
* Notify onBufferingEnded when the state of origin player becomes
STATE_IDLE or STATE_ENDED.
### 2.12.1 (2020-10-23) ### ### 2.12.1 (2020-10-23) ###

View File

@ -826,7 +826,6 @@ public class SessionPlayerConnectorTest {
} }
} }
}); });
sessionPlayerConnector.setPlaylist(playlistToSessionPlayer, /* metadata= */ null);
InstrumentationRegistry.getInstrumentation() InstrumentationRegistry.getInstrumentation()
.runOnMainSync(() -> playerTestRule.getSimpleExoPlayer().setMediaItems(exoMediaItems)); .runOnMainSync(() -> playerTestRule.getSimpleExoPlayer().setMediaItems(exoMediaItems));
assertThat(onPlaylistChangedLatch.await(PLAYLIST_CHANGE_WAIT_TIME_MS, MILLISECONDS)).isTrue(); assertThat(onPlaylistChangedLatch.await(PLAYLIST_CHANGE_WAIT_TIME_MS, MILLISECONDS)).isTrue();

View File

@ -65,10 +65,10 @@ import java.util.List;
/** Called when a seek request has completed. */ /** Called when a seek request has completed. */
void onSeekCompleted(); void onSeekCompleted();
/** Called when the player rebuffers. */ /** Called when the player starts buffering. */
void onBufferingStarted(androidx.media2.common.MediaItem media2MediaItem); void onBufferingStarted(androidx.media2.common.MediaItem media2MediaItem);
/** Called when the player becomes ready again after rebuffering. */ /** Called when the player becomes ready again after buffering started. */
void onBufferingEnded( void onBufferingEnded(
androidx.media2.common.MediaItem media2MediaItem, int bufferingPercentage); androidx.media2.common.MediaItem media2MediaItem, int bufferingPercentage);
@ -120,8 +120,9 @@ import java.util.List;
private final List<MediaItem> exoPlayerPlaylist; private final List<MediaItem> exoPlayerPlaylist;
private ControlDispatcher controlDispatcher; private ControlDispatcher controlDispatcher;
private int sessionPlayerState;
private boolean prepared; private boolean prepared;
private boolean rebuffering; @Nullable private androidx.media2.common.MediaItem bufferingItem;
private int currentWindowIndex; private int currentWindowIndex;
private boolean ignoreTimelineUpdates; private boolean ignoreTimelineUpdates;
@ -154,11 +155,14 @@ import java.util.List;
media2Playlist = new ArrayList<>(); media2Playlist = new ArrayList<>();
exoPlayerPlaylist = new ArrayList<>(); exoPlayerPlaylist = new ArrayList<>();
currentWindowIndex = C.INDEX_UNSET; currentWindowIndex = C.INDEX_UNSET;
prepared = player.getPlaybackState() != Player.STATE_IDLE;
rebuffering = player.getPlaybackState() == Player.STATE_BUFFERING;
updatePlaylist(player.getCurrentTimeline()); updatePlaylist(player.getCurrentTimeline());
sessionPlayerState = evaluateSessionPlayerState();
@Player.State int playbackState = player.getPlaybackState();
prepared = playbackState != Player.STATE_IDLE;
if (playbackState == Player.STATE_BUFFERING) {
bufferingItem = getCurrentMediaItem();
}
} }
public void setControlDispatcher(ControlDispatcher controlDispatcher) { public void setControlDispatcher(ControlDispatcher controlDispatcher) {
@ -360,7 +364,7 @@ import java.util.List;
} }
/* @SessionPlayer.PlayerState */ /* @SessionPlayer.PlayerState */
private int getState() { private int evaluateSessionPlayerState() {
if (hasError()) { if (hasError()) {
return SessionPlayer.PLAYER_STATE_ERROR; return SessionPlayer.PLAYER_STATE_ERROR;
} }
@ -381,6 +385,63 @@ import java.util.List;
} }
} }
private void updateSessionPlayerState() {
int newState = evaluateSessionPlayerState();
if (sessionPlayerState != newState) {
sessionPlayerState = newState;
listener.onPlayerStateChanged(newState);
if (newState == SessionPlayer.PLAYER_STATE_ERROR) {
listener.onError(getCurrentMediaItem());
}
}
}
private void updateBufferingState(boolean isBuffering) {
if (isBuffering) {
androidx.media2.common.MediaItem curMediaItem = getCurrentMediaItem();
if (prepared && (bufferingItem == null || !bufferingItem.equals(curMediaItem))) {
bufferingItem = getCurrentMediaItem();
listener.onBufferingStarted(Assertions.checkNotNull(bufferingItem));
}
} else if (bufferingItem != null) {
listener.onBufferingEnded(bufferingItem, player.getBufferedPercentage());
bufferingItem = null;
}
}
private void handlePlayerStateChanged() {
updateSessionPlayerState();
int playbackState = player.getPlaybackState();
handler.removeCallbacks(pollBufferRunnable);
switch (playbackState) {
case Player.STATE_IDLE:
prepared = false;
updateBufferingState(/* isBuffering= */ false);
break;
case Player.STATE_BUFFERING:
updateBufferingState(/* isBuffering= */ true);
postOrRun(handler, pollBufferRunnable);
break;
case Player.STATE_READY:
if (!prepared) {
prepared = true;
handlePositionDiscontinuity(Player.DISCONTINUITY_REASON_PERIOD_TRANSITION);
listener.onPrepared(
Assertions.checkNotNull(getCurrentMediaItem()), player.getBufferedPercentage());
}
updateBufferingState(/* isBuffering= */ false);
postOrRun(handler, pollBufferRunnable);
break;
case Player.STATE_ENDED:
listener.onPlaybackEnded();
player.setPlayWhenReady(false);
updateBufferingState(/* isBuffering= */ false);
break;
}
}
public void setAudioAttributes(AudioAttributesCompat audioAttributes) { public void setAudioAttributes(AudioAttributesCompat audioAttributes) {
Player.AudioComponent audioComponent = Assertions.checkStateNotNull(player.getAudioComponent()); Player.AudioComponent audioComponent = Assertions.checkStateNotNull(player.getAudioComponent());
audioComponent.setAudioAttributes( audioComponent.setAudioAttributes(
@ -407,7 +468,7 @@ import java.util.List;
public void reset() { public void reset() {
controlDispatcher.dispatchStop(player, /* reset= */ true); controlDispatcher.dispatchStop(player, /* reset= */ true);
prepared = false; prepared = false;
rebuffering = false; bufferingItem = null;
} }
public void close() { public void close() {
@ -446,35 +507,6 @@ import java.util.List;
return player.getPlayerError() != null; return player.getPlayerError() != null;
} }
private void handlePlayWhenReadyChanged() {
listener.onPlayerStateChanged(getState());
}
private void handlePlayerStateChanged(@Player.State int state) {
if (state == Player.STATE_READY || state == Player.STATE_BUFFERING) {
postOrRun(handler, pollBufferRunnable);
} else {
handler.removeCallbacks(pollBufferRunnable);
}
switch (state) {
case Player.STATE_BUFFERING:
maybeNotifyBufferingEvents();
break;
case Player.STATE_READY:
maybeNotifyReadyEvents();
break;
case Player.STATE_ENDED:
maybeNotifyEndedEvents();
break;
case Player.STATE_IDLE:
// Do nothing.
break;
default:
throw new IllegalStateException();
}
}
private void handlePositionDiscontinuity(@Player.DiscontinuityReason int reason) { private void handlePositionDiscontinuity(@Player.DiscontinuityReason int reason) {
int currentWindowIndex = getCurrentMediaItemIndex(); int currentWindowIndex = getCurrentMediaItemIndex();
if (this.currentWindowIndex != currentWindowIndex) { if (this.currentWindowIndex != currentWindowIndex) {
@ -487,34 +519,6 @@ import java.util.List;
} }
} }
private void handlePlayerError() {
listener.onPlayerStateChanged(SessionPlayer.PLAYER_STATE_ERROR);
listener.onError(getCurrentMediaItem());
}
private void handleRepeatModeChanged(@Player.RepeatMode int repeatMode) {
listener.onRepeatModeChanged(Utils.getRepeatMode(repeatMode));
}
private void handleShuffleMode(boolean shuffleModeEnabled) {
listener.onShuffleModeChanged(Utils.getShuffleMode(shuffleModeEnabled));
}
private void handlePlaybackParametersChanged(PlaybackParameters playbackParameters) {
listener.onPlaybackSpeedChanged(playbackParameters.speed);
}
private void handleTimelineChanged(Timeline timeline) {
if (ignoreTimelineUpdates) {
return;
}
if (!isExoPlayerMediaItemsChanged(timeline)) {
return;
}
updatePlaylist(timeline);
listener.onPlaylistChanged();
}
// Check whether Timeline is changed by media item changes or not // Check whether Timeline is changed by media item changes or not
private boolean isExoPlayerMediaItemsChanged(Timeline timeline) { private boolean isExoPlayerMediaItemsChanged(Timeline timeline) {
if (exoPlayerPlaylist.size() != timeline.getWindowCount()) { if (exoPlayerPlaylist.size() != timeline.getWindowCount()) {
@ -554,10 +558,6 @@ import java.util.List;
} }
} }
private void handleAudioAttributesChanged(AudioAttributes audioAttributes) {
listener.onAudioAttributesChanged(Utils.getAudioAttributesCompat(audioAttributes));
}
private void updateBufferingAndScheduleNextPollBuffer() { private void updateBufferingAndScheduleNextPollBuffer() {
androidx.media2.common.MediaItem media2MediaItem = androidx.media2.common.MediaItem media2MediaItem =
Assertions.checkNotNull(getCurrentMediaItem()); Assertions.checkNotNull(getCurrentMediaItem());
@ -566,39 +566,6 @@ import java.util.List;
handler.postDelayed(pollBufferRunnable, POLL_BUFFER_INTERVAL_MS); handler.postDelayed(pollBufferRunnable, POLL_BUFFER_INTERVAL_MS);
} }
private void maybeNotifyBufferingEvents() {
androidx.media2.common.MediaItem media2MediaItem =
Assertions.checkNotNull(getCurrentMediaItem());
if (prepared && !rebuffering) {
rebuffering = true;
listener.onBufferingStarted(media2MediaItem);
}
}
private void maybeNotifyReadyEvents() {
androidx.media2.common.MediaItem media2MediaItem =
Assertions.checkNotNull(getCurrentMediaItem());
boolean prepareComplete = !prepared;
if (prepareComplete) {
prepared = true;
handlePositionDiscontinuity(Player.DISCONTINUITY_REASON_PERIOD_TRANSITION);
listener.onPlayerStateChanged(SessionPlayer.PLAYER_STATE_PAUSED);
listener.onPrepared(media2MediaItem, player.getBufferedPercentage());
}
if (rebuffering) {
rebuffering = false;
listener.onBufferingEnded(media2MediaItem, player.getBufferedPercentage());
}
}
private void maybeNotifyEndedEvents() {
if (player.getPlayWhenReady()) {
listener.onPlayerStateChanged(SessionPlayer.PLAYER_STATE_PAUSED);
listener.onPlaybackEnded();
player.setPlayWhenReady(false);
}
}
private void releaseMediaItem(androidx.media2.common.MediaItem media2MediaItem) { private void releaseMediaItem(androidx.media2.common.MediaItem media2MediaItem) {
try { try {
if (media2MediaItem instanceof CallbackMediaItem) { if (media2MediaItem instanceof CallbackMediaItem) {
@ -615,12 +582,12 @@ import java.util.List;
@Override @Override
public void onPlayWhenReadyChanged(boolean playWhenReady, int reason) { public void onPlayWhenReadyChanged(boolean playWhenReady, int reason) {
handlePlayWhenReadyChanged(); updateSessionPlayerState();
} }
@Override @Override
public void onPlaybackStateChanged(@Player.State int state) { public void onPlaybackStateChanged(@Player.State int state) {
handlePlayerStateChanged(state); handlePlayerStateChanged();
} }
@Override @Override
@ -630,34 +597,41 @@ import java.util.List;
@Override @Override
public void onPlayerError(ExoPlaybackException error) { public void onPlayerError(ExoPlaybackException error) {
handlePlayerError(); updateSessionPlayerState();
} }
@Override @Override
public void onRepeatModeChanged(@Player.RepeatMode int repeatMode) { public void onRepeatModeChanged(@Player.RepeatMode int repeatMode) {
handleRepeatModeChanged(repeatMode); listener.onRepeatModeChanged(Utils.getRepeatMode(repeatMode));
} }
@Override @Override
public void onShuffleModeEnabledChanged(boolean shuffleModeEnabled) { public void onShuffleModeEnabledChanged(boolean shuffleModeEnabled) {
handleShuffleMode(shuffleModeEnabled); listener.onShuffleModeChanged(Utils.getShuffleMode(shuffleModeEnabled));
} }
@Override @Override
public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) { public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) {
handlePlaybackParametersChanged(playbackParameters); listener.onPlaybackSpeedChanged(playbackParameters.speed);
} }
@Override @Override
public void onTimelineChanged(Timeline timeline, int reason) { public void onTimelineChanged(Timeline timeline, int reason) {
handleTimelineChanged(timeline); if (ignoreTimelineUpdates) {
return;
}
if (!isExoPlayerMediaItemsChanged(timeline)) {
return;
}
updatePlaylist(timeline);
listener.onPlaylistChanged();
} }
// AudioListener implementation. // AudioListener implementation.
@Override @Override
public void onAudioAttributesChanged(AudioAttributes audioAttributes) { public void onAudioAttributesChanged(AudioAttributes audioAttributes) {
handleAudioAttributesChanged(audioAttributes); listener.onAudioAttributesChanged(Utils.getAudioAttributesCompat(audioAttributes));
} }
} }