use of androidx.media2.common.SessionPlayer.PlayerResult in project ExoPlayer by google.
the class PlayerCommandQueue method processPendingCommandOnHandler.
private void processPendingCommandOnHandler() {
while (pendingAsyncPlayerCommandResult == null) {
@Nullable PlayerCommand playerCommand;
synchronized (lock) {
playerCommand = pendingPlayerCommandQueue.poll();
}
if (playerCommand == null) {
return;
}
int commandCode = playerCommand.commandCode;
// Check if it's @AsyncCommandCode
boolean asyncCommand = isAsyncCommand(playerCommand.commandCode);
// Continuous COMMAND_CODE_PLAYER_SEEK_TO can be skipped.
if (commandCode == COMMAND_CODE_PLAYER_SEEK_TO) {
@Nullable List<PlayerCommand> skippingCommands = null;
while (true) {
synchronized (lock) {
@Nullable PlayerCommand pendingCommand = pendingPlayerCommandQueue.peek();
if (pendingCommand == null || pendingCommand.commandCode != commandCode) {
break;
}
pendingPlayerCommandQueue.poll();
if (skippingCommands == null) {
skippingCommands = new ArrayList<>();
}
skippingCommands.add(playerCommand);
playerCommand = pendingCommand;
}
}
if (skippingCommands != null) {
for (PlayerCommand skippingCommand : skippingCommands) {
skippingCommand.result.set(new PlayerResult(PlayerResult.RESULT_INFO_SKIPPED, player.getCurrentMediaItem()));
if (DEBUG) {
Log.d(TAG, "skipping pending command, " + skippingCommand);
}
}
}
}
if (asyncCommand) {
// Result would come later, via #notifyCommandCompleted().
// Set pending player result first because it may be notified while the command is running.
pendingAsyncPlayerCommandResult = new AsyncPlayerCommandResult(commandCode, playerCommand.result);
}
if (DEBUG) {
Log.d(TAG, "start processing command, " + playerCommand);
}
int resultCode;
if (player.hasError()) {
resultCode = PlayerResult.RESULT_ERROR_INVALID_STATE;
} else {
try {
boolean handled = playerCommand.command.call();
resultCode = handled ? PlayerResult.RESULT_SUCCESS : PlayerResult.RESULT_INFO_SKIPPED;
} catch (IllegalStateException e) {
resultCode = PlayerResult.RESULT_ERROR_INVALID_STATE;
} catch (IllegalArgumentException | IndexOutOfBoundsException e) {
resultCode = PlayerResult.RESULT_ERROR_BAD_VALUE;
} catch (SecurityException e) {
resultCode = PlayerResult.RESULT_ERROR_PERMISSION_DENIED;
} catch (Exception e) {
resultCode = PlayerResult.RESULT_ERROR_UNKNOWN;
}
}
if (DEBUG) {
Log.d(TAG, "command processed, " + playerCommand);
}
if (asyncCommand) {
if (resultCode != PlayerResult.RESULT_SUCCESS && pendingAsyncPlayerCommandResult != null && playerCommand.result == pendingAsyncPlayerCommandResult.result) {
pendingAsyncPlayerCommandResult = null;
playerCommand.result.set(new PlayerResult(resultCode, player.getCurrentMediaItem()));
}
} else {
playerCommand.result.set(new PlayerResult(resultCode, player.getCurrentMediaItem()));
}
}
}
use of androidx.media2.common.SessionPlayer.PlayerResult in project ExoPlayer by google.
the class TestUtils method assertPlayerResult.
public static void assertPlayerResult(Future<PlayerResult> future, /* @PlayerResult.ResultCode */
int playerResult) throws Exception {
assertThat(future).isNotNull();
PlayerResult result = future.get(PLAYER_STATE_CHANGE_WAIT_TIME_MS, MILLISECONDS);
assertThat(result).isNotNull();
assertThat(result.getResultCode()).isEqualTo(playerResult);
}
use of androidx.media2.common.SessionPlayer.PlayerResult in project ExoPlayer by google.
the class SessionPlayerConnectorTest method cancelReturnedFuture_withSeekTo_cancelsPendingCommand.
@Test
@LargeTest
public void cancelReturnedFuture_withSeekTo_cancelsPendingCommand() throws Exception {
CountDownLatch readRequestedLatch = new CountDownLatch(1);
CountDownLatch readAllowedLatch = new CountDownLatch(1);
// Need to wait from prepare() to counting down readAllowedLatch.
playerTestRule.setDataSourceInstrumentation(dataSpec -> {
readRequestedLatch.countDown();
try {
assertThat(readAllowedLatch.await(PLAYER_STATE_CHANGE_WAIT_TIME_MS, MILLISECONDS)).isTrue();
} catch (Exception e) {
assertWithMessage("Unexpected exception %s", e).fail();
}
});
assertPlayerResultSuccess(sessionPlayerConnector.setMediaItem(TestUtils.createMediaItem(R.raw.audio)));
// prepare() will be pending until readAllowed is countDowned.
ListenableFuture<PlayerResult> prepareFuture = sessionPlayerConnector.prepare();
ListenableFuture<PlayerResult> seekFuture = sessionPlayerConnector.seekTo(1000);
assertThat(readRequestedLatch.await(PLAYER_STATE_CHANGE_WAIT_TIME_MS, MILLISECONDS)).isTrue();
// Cancel the pending commands while preparation is on hold.
seekFuture.cancel(false);
// Make the on-going prepare operation resumed and finished.
readAllowedLatch.countDown();
assertPlayerResultSuccess(prepareFuture);
// Check whether the canceled seek() didn't happened.
// Checking seekFuture.get() will be useless because it always throws CancellationException due
// to the CallbackToFuture implementation.
Thread.sleep(PLAYER_STATE_CHANGE_WAIT_TIME_MS);
assertThat(sessionPlayerConnector.getCurrentPosition()).isEqualTo(0);
}
use of androidx.media2.common.SessionPlayer.PlayerResult in project ExoPlayer by google.
the class PlayerCommandQueue method notifyCommandError.
public void notifyCommandError() {
postOrRun(handler, () -> {
@Nullable AsyncPlayerCommandResult pendingResult = pendingAsyncPlayerCommandResult;
if (pendingResult == null) {
if (DEBUG) {
Log.d(TAG, "Ignoring notifyCommandError(). No pending async command.");
}
return;
}
pendingResult.result.set(new PlayerResult(PlayerResult.RESULT_ERROR_UNKNOWN, player.getCurrentMediaItem()));
pendingAsyncPlayerCommandResult = null;
if (DEBUG) {
Log.d(TAG, "error on " + pendingResult);
}
processPendingCommandOnHandler();
});
}
use of androidx.media2.common.SessionPlayer.PlayerResult in project ExoPlayer by google.
the class SessionPlayerConnector method setPlaylist.
/**
* {@inheritDoc}
*
* <p>{@link FileMediaItem} and {@link CallbackMediaItem} are not supported.
*/
@Override
public ListenableFuture<PlayerResult> setPlaylist(final List<MediaItem> playlist, @Nullable MediaMetadata metadata) {
Assertions.checkNotNull(playlist);
Assertions.checkArgument(!playlist.isEmpty());
for (int i = 0; i < playlist.size(); i++) {
MediaItem item = playlist.get(i);
Assertions.checkNotNull(item);
Assertions.checkArgument(!(item instanceof FileMediaItem));
Assertions.checkArgument(!(item instanceof CallbackMediaItem));
for (int j = 0; j < i; j++) {
Assertions.checkArgument(item != playlist.get(j), "playlist shouldn't contain duplicated item, index=" + i + " vs index=" + j);
}
}
ListenableFuture<PlayerResult> result = playerCommandQueue.addCommand(PlayerCommandQueue.COMMAND_CODE_PLAYER_SET_PLAYLIST, /* command= */
() -> player.setPlaylist(playlist, metadata));
return result;
}
Aggregations