mirror of
https://github.com/androidx/media.git
synced 2025-05-04 14:10:40 +08:00
Revert "Playlist API: Add setMediaItem() and prepare()"
This reverts commit cd2c1f2f24c3a17ffa59f0c5ba9d17d55f141793.
This commit is contained in:
parent
c9cc147fb9
commit
30ed83ecef
@ -394,8 +394,7 @@ public class PlayerActivity extends AppCompatActivity
|
|||||||
if (haveStartPosition) {
|
if (haveStartPosition) {
|
||||||
player.seekTo(startWindow, startPosition);
|
player.seekTo(startWindow, startPosition);
|
||||||
}
|
}
|
||||||
player.setMediaItem(mediaSource);
|
player.prepare(mediaSource, !haveStartPosition, false);
|
||||||
player.prepare();
|
|
||||||
updateButtonVisibility();
|
updateButtonVisibility();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -331,51 +331,26 @@ public interface ExoPlayer extends Player {
|
|||||||
*/
|
*/
|
||||||
void retry();
|
void retry();
|
||||||
|
|
||||||
/** Prepares the player. */
|
|
||||||
void prepare();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated Use {@code setMediaItem(mediaSource, C.TIME_UNSET)} and {@link #prepare()} instead.
|
* Prepares the player to play the provided {@link MediaSource}. Equivalent to {@code
|
||||||
|
* prepare(mediaSource, true, true)}.
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
|
||||||
void prepare(MediaSource mediaSource);
|
void prepare(MediaSource mediaSource);
|
||||||
|
|
||||||
/** @deprecated Use {@link #setMediaItem(MediaSource, long)} and {@link #prepare()} instead. */
|
/**
|
||||||
@Deprecated
|
* Prepares the player to play the provided {@link MediaSource}, optionally resetting the playback
|
||||||
|
* position the default position in the first {@link Timeline.Window}.
|
||||||
|
*
|
||||||
|
* @param mediaSource The {@link MediaSource} to play.
|
||||||
|
* @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()}.
|
||||||
|
* @param resetState Whether the timeline, manifest, tracks and track selections should be reset.
|
||||||
|
* Should be true unless the player is being prepared to play the same media as it was playing
|
||||||
|
* previously (e.g. if playback failed and is being retried).
|
||||||
|
*/
|
||||||
void prepare(MediaSource mediaSource, boolean resetPosition, boolean resetState);
|
void prepare(MediaSource mediaSource, boolean resetPosition, boolean resetState);
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the specified {@link MediaSource}.
|
|
||||||
*
|
|
||||||
* <p>Note: This is an intermediate implementation towards a larger change. Until then {@link
|
|
||||||
* #prepare()} has to be called immediately after calling this method.
|
|
||||||
*
|
|
||||||
* @param mediaItem The new {@link MediaSource}.
|
|
||||||
*/
|
|
||||||
void setMediaItem(MediaSource mediaItem);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the specified {@link MediaSource}.
|
|
||||||
*
|
|
||||||
* <p>Note: This is an intermediate implementation towards a larger change. Until then {@link
|
|
||||||
* #prepare()} has to be called immediately after calling this method.
|
|
||||||
*
|
|
||||||
* <p>This intermediate implementation calls {@code stop(true)} before seeking to avoid seeking in
|
|
||||||
* a media item that has been set previously. It is equivalent with calling
|
|
||||||
*
|
|
||||||
* <pre><code>
|
|
||||||
* if (!getCurrentTimeline().isEmpty()) {
|
|
||||||
* player.stop(true);
|
|
||||||
* }
|
|
||||||
* player.seekTo(0, startPositionMs);
|
|
||||||
* player.setMediaItem(mediaItem);
|
|
||||||
* </code></pre>
|
|
||||||
*
|
|
||||||
* @param mediaItem The new {@link MediaSource}.
|
|
||||||
* @param startPositionMs The position in milliseconds to start playback from.
|
|
||||||
*/
|
|
||||||
void setMediaItem(MediaSource mediaItem, long startPositionMs);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a message that can be sent to a {@link PlayerMessage.Target}. By default, the message
|
* Creates a message that can be sent to a {@link PlayerMessage.Target}. By default, the message
|
||||||
* will be delivered immediately without blocking on the playback thread. The default {@link
|
* will be delivered immediately without blocking on the playback thread. The default {@link
|
||||||
|
@ -62,7 +62,7 @@ import java.util.concurrent.CopyOnWriteArrayList;
|
|||||||
private final Timeline.Period period;
|
private final Timeline.Period period;
|
||||||
private final ArrayDeque<Runnable> pendingListenerNotifications;
|
private final ArrayDeque<Runnable> pendingListenerNotifications;
|
||||||
|
|
||||||
@Nullable private MediaSource mediaSource;
|
private MediaSource mediaSource;
|
||||||
private boolean playWhenReady;
|
private boolean playWhenReady;
|
||||||
@PlaybackSuppressionReason private int playbackSuppressionReason;
|
@PlaybackSuppressionReason private int playbackSuppressionReason;
|
||||||
@RepeatMode private int repeatMode;
|
@RepeatMode private int repeatMode;
|
||||||
@ -219,38 +219,34 @@ import java.util.concurrent.CopyOnWriteArrayList;
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Deprecated
|
|
||||||
public void prepare(MediaSource mediaSource) {
|
public void prepare(MediaSource mediaSource) {
|
||||||
setMediaItem(mediaSource);
|
prepare(mediaSource, /* resetPosition= */ true, /* resetState= */ true);
|
||||||
prepareInternal(/* resetPosition= */ true, /* resetState= */ true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Deprecated
|
|
||||||
public void prepare(MediaSource mediaSource, boolean resetPosition, boolean resetState) {
|
public void prepare(MediaSource mediaSource, boolean resetPosition, boolean resetState) {
|
||||||
setMediaItem(mediaSource);
|
this.mediaSource = mediaSource;
|
||||||
prepareInternal(resetPosition, resetState);
|
PlaybackInfo playbackInfo =
|
||||||
|
getResetPlaybackInfo(
|
||||||
|
resetPosition,
|
||||||
|
resetState,
|
||||||
|
/* resetError= */ true,
|
||||||
|
/* playbackState= */ Player.STATE_BUFFERING);
|
||||||
|
// Trigger internal prepare first before updating the playback info and notifying external
|
||||||
|
// listeners to ensure that new operations issued in the listener notifications reach the
|
||||||
|
// player after this prepare. The internal player can't change the playback info immediately
|
||||||
|
// because it uses a callback.
|
||||||
|
hasPendingPrepare = true;
|
||||||
|
pendingOperationAcks++;
|
||||||
|
internalPlayer.prepare(mediaSource, resetPosition, resetState);
|
||||||
|
updatePlaybackInfo(
|
||||||
|
playbackInfo,
|
||||||
|
/* positionDiscontinuity= */ false,
|
||||||
|
/* ignored */ DISCONTINUITY_REASON_INTERNAL,
|
||||||
|
TIMELINE_CHANGE_REASON_RESET,
|
||||||
|
/* seekProcessed= */ false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void prepare() {
|
|
||||||
Assertions.checkNotNull(mediaSource);
|
|
||||||
prepareInternal(/* resetPosition= */ false, /* resetState= */ true);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setMediaItem(MediaSource mediaItem, long startPositionMs) {
|
|
||||||
if (!getCurrentTimeline().isEmpty()) {
|
|
||||||
stop(/* reset= */ true);
|
|
||||||
}
|
|
||||||
seekTo(/* windowIndex= */ 0, startPositionMs);
|
|
||||||
setMediaItem(mediaItem);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setMediaItem(MediaSource mediaItem) {
|
|
||||||
mediaSource = mediaItem;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setPlayWhenReady(boolean playWhenReady) {
|
public void setPlayWhenReady(boolean playWhenReady) {
|
||||||
@ -610,29 +606,6 @@ import java.util.concurrent.CopyOnWriteArrayList;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* package */ void prepareInternal(boolean resetPosition, boolean resetState) {
|
|
||||||
Assertions.checkNotNull(mediaSource);
|
|
||||||
PlaybackInfo playbackInfo =
|
|
||||||
getResetPlaybackInfo(
|
|
||||||
resetPosition,
|
|
||||||
resetState,
|
|
||||||
/* resetError= */ true,
|
|
||||||
/* playbackState= */ Player.STATE_BUFFERING);
|
|
||||||
// Trigger internal prepare first before updating the playback info and notifying external
|
|
||||||
// listeners to ensure that new operations issued in the listener notifications reach the
|
|
||||||
// player after this prepare. The internal player can't change the playback info immediately
|
|
||||||
// because it uses a callback.
|
|
||||||
hasPendingPrepare = true;
|
|
||||||
pendingOperationAcks++;
|
|
||||||
internalPlayer.prepare(mediaSource, resetPosition, resetState);
|
|
||||||
updatePlaybackInfo(
|
|
||||||
playbackInfo,
|
|
||||||
/* positionDiscontinuity= */ false,
|
|
||||||
/* ignored */ DISCONTINUITY_REASON_INTERNAL,
|
|
||||||
TIMELINE_CHANGE_REASON_RESET,
|
|
||||||
/* seekProcessed= */ false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void handlePlaybackParameters(
|
private void handlePlaybackParameters(
|
||||||
PlaybackParameters playbackParameters, boolean operationAck) {
|
PlaybackParameters playbackParameters, boolean operationAck) {
|
||||||
if (operationAck) {
|
if (operationAck) {
|
||||||
|
@ -1162,7 +1162,6 @@ public class SimpleExoPlayer extends BasePlayer
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
public void retry() {
|
public void retry() {
|
||||||
verifyApplicationThread();
|
verifyApplicationThread();
|
||||||
if (mediaSource != null
|
if (mediaSource != null
|
||||||
@ -1172,38 +1171,23 @@ public class SimpleExoPlayer extends BasePlayer
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Deprecated
|
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
public void prepare(MediaSource mediaSource) {
|
public void prepare(MediaSource mediaSource) {
|
||||||
prepare(mediaSource, /* resetPosition= */ true, /* resetState= */ true);
|
prepare(mediaSource, /* resetPosition= */ true, /* resetState= */ true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Deprecated
|
|
||||||
public void prepare(MediaSource mediaSource, boolean resetPosition, boolean resetState) {
|
public void prepare(MediaSource mediaSource, boolean resetPosition, boolean resetState) {
|
||||||
verifyApplicationThread();
|
verifyApplicationThread();
|
||||||
setMediaItem(mediaSource);
|
if (this.mediaSource != null) {
|
||||||
prepareInternal(resetPosition, resetState);
|
this.mediaSource.removeEventListener(analyticsCollector);
|
||||||
}
|
analyticsCollector.resetForNewMediaSource();
|
||||||
|
}
|
||||||
@Override
|
this.mediaSource = mediaSource;
|
||||||
public void prepare() {
|
mediaSource.addEventListener(eventHandler, analyticsCollector);
|
||||||
verifyApplicationThread();
|
@AudioFocusManager.PlayerCommand
|
||||||
prepareInternal(/* resetPosition= */ false, /* resetState= */ true);
|
int playerCommand = audioFocusManager.handlePrepare(getPlayWhenReady());
|
||||||
}
|
updatePlayWhenReady(getPlayWhenReady(), playerCommand);
|
||||||
|
player.prepare(mediaSource, resetPosition, resetState);
|
||||||
@Override
|
|
||||||
public void setMediaItem(MediaSource mediaItem, long startPositionMs) {
|
|
||||||
verifyApplicationThread();
|
|
||||||
setMediaItemInternal(mediaItem);
|
|
||||||
player.setMediaItem(mediaItem, startPositionMs);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setMediaItem(MediaSource mediaItem) {
|
|
||||||
verifyApplicationThread();
|
|
||||||
setMediaItemInternal(mediaItem);
|
|
||||||
player.setMediaItem(mediaItem);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -1448,23 +1432,6 @@ public class SimpleExoPlayer extends BasePlayer
|
|||||||
|
|
||||||
// Internal methods.
|
// Internal methods.
|
||||||
|
|
||||||
private void prepareInternal(boolean resetPosition, boolean resetState) {
|
|
||||||
Assertions.checkNotNull(mediaSource);
|
|
||||||
@AudioFocusManager.PlayerCommand
|
|
||||||
int playerCommand = audioFocusManager.handlePrepare(getPlayWhenReady());
|
|
||||||
updatePlayWhenReady(getPlayWhenReady(), playerCommand);
|
|
||||||
player.prepareInternal(resetPosition, resetState);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setMediaItemInternal(MediaSource mediaItem) {
|
|
||||||
if (mediaSource != null) {
|
|
||||||
mediaSource.removeEventListener(analyticsCollector);
|
|
||||||
analyticsCollector.resetForNewMediaSource();
|
|
||||||
}
|
|
||||||
mediaSource = mediaItem;
|
|
||||||
mediaSource.addEventListener(eventHandler, analyticsCollector);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void removeSurfaceCallbacks() {
|
private void removeSurfaceCallbacks() {
|
||||||
if (textureView != null) {
|
if (textureView != null) {
|
||||||
if (textureView.getSurfaceTextureListener() != componentListener) {
|
if (textureView.getSurfaceTextureListener() != componentListener) {
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
package com.google.android.exoplayer2;
|
package com.google.android.exoplayer2;
|
||||||
|
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
import static org.junit.Assert.assertArrayEquals;
|
|
||||||
import static org.junit.Assert.fail;
|
import static org.junit.Assert.fail;
|
||||||
import static org.robolectric.Shadows.shadowOf;
|
import static org.robolectric.Shadows.shadowOf;
|
||||||
|
|
||||||
@ -36,10 +35,7 @@ import com.google.android.exoplayer2.Timeline.Window;
|
|||||||
import com.google.android.exoplayer2.analytics.AnalyticsListener;
|
import com.google.android.exoplayer2.analytics.AnalyticsListener;
|
||||||
import com.google.android.exoplayer2.audio.AudioAttributes;
|
import com.google.android.exoplayer2.audio.AudioAttributes;
|
||||||
import com.google.android.exoplayer2.source.ClippingMediaSource;
|
import com.google.android.exoplayer2.source.ClippingMediaSource;
|
||||||
import com.google.android.exoplayer2.source.CompositeMediaSource;
|
|
||||||
import com.google.android.exoplayer2.source.ConcatenatingMediaSource;
|
import com.google.android.exoplayer2.source.ConcatenatingMediaSource;
|
||||||
import com.google.android.exoplayer2.source.LoopingMediaSource;
|
|
||||||
import com.google.android.exoplayer2.source.MediaPeriod;
|
|
||||||
import com.google.android.exoplayer2.source.MediaSource;
|
import com.google.android.exoplayer2.source.MediaSource;
|
||||||
import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId;
|
import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId;
|
||||||
import com.google.android.exoplayer2.source.MediaSourceEventListener.EventDispatcher;
|
import com.google.android.exoplayer2.source.MediaSourceEventListener.EventDispatcher;
|
||||||
@ -1588,7 +1584,6 @@ public final class ExoPlayerTest {
|
|||||||
AtomicInteger counter = new AtomicInteger();
|
AtomicInteger counter = new AtomicInteger();
|
||||||
ActionSchedule actionSchedule =
|
ActionSchedule actionSchedule =
|
||||||
new ActionSchedule.Builder("testSendMessagesFromStartPositionOnlyOnce")
|
new ActionSchedule.Builder("testSendMessagesFromStartPositionOnlyOnce")
|
||||||
.waitForTimelineChanged()
|
|
||||||
.pause()
|
.pause()
|
||||||
.sendMessage(
|
.sendMessage(
|
||||||
(messageType, payload) -> {
|
(messageType, payload) -> {
|
||||||
@ -2931,218 +2926,6 @@ public final class ExoPlayerTest {
|
|||||||
assertThat(seenPlaybackSuppression.get()).isFalse();
|
assertThat(seenPlaybackSuppression.get()).isFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testDelegatingMediaSourceApproach() throws Exception {
|
|
||||||
Timeline fakeTimeline =
|
|
||||||
new FakeTimeline(
|
|
||||||
new TimelineWindowDefinition(
|
|
||||||
/* isSeekable= */ true, /* isDynamic= */ false, /* durationUs= */ 10_000));
|
|
||||||
final ConcatenatingMediaSource underlyingSource = new ConcatenatingMediaSource();
|
|
||||||
CompositeMediaSource<Void> delegatingMediaSource =
|
|
||||||
new CompositeMediaSource<Void>() {
|
|
||||||
@Override
|
|
||||||
public void prepareSourceInternal(@Nullable TransferListener mediaTransferListener) {
|
|
||||||
super.prepareSourceInternal(mediaTransferListener);
|
|
||||||
underlyingSource.addMediaSource(
|
|
||||||
new FakeMediaSource(fakeTimeline, Builder.VIDEO_FORMAT));
|
|
||||||
underlyingSource.addMediaSource(
|
|
||||||
new FakeMediaSource(fakeTimeline, Builder.VIDEO_FORMAT));
|
|
||||||
prepareChildSource(null, underlyingSource);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MediaPeriod createPeriod(
|
|
||||||
MediaPeriodId id, Allocator allocator, long startPositionUs) {
|
|
||||||
return underlyingSource.createPeriod(id, allocator, startPositionUs);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void releasePeriod(MediaPeriod mediaPeriod) {
|
|
||||||
underlyingSource.releasePeriod(mediaPeriod);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onChildSourceInfoRefreshed(
|
|
||||||
Void id, MediaSource mediaSource, Timeline timeline) {
|
|
||||||
refreshSourceInfo(timeline);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
int[] currentWindowIndices = new int[1];
|
|
||||||
long[] currentPlaybackPositions = new long[1];
|
|
||||||
long[] windowCounts = new long[1];
|
|
||||||
int seekToWindowIndex = 1;
|
|
||||||
ActionSchedule actionSchedule =
|
|
||||||
new ActionSchedule.Builder("testDelegatingMediaSourceApproach")
|
|
||||||
.seek(/* windowIndex= */ 1, /* positionMs= */ 5000)
|
|
||||||
.waitForSeekProcessed()
|
|
||||||
.executeRunnable(
|
|
||||||
new PlayerRunnable() {
|
|
||||||
@Override
|
|
||||||
public void run(SimpleExoPlayer player) {
|
|
||||||
currentWindowIndices[0] = player.getCurrentWindowIndex();
|
|
||||||
currentPlaybackPositions[0] = player.getCurrentPosition();
|
|
||||||
windowCounts[0] = player.getCurrentTimeline().getWindowCount();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.build();
|
|
||||||
ExoPlayerTestRunner exoPlayerTestRunner =
|
|
||||||
new Builder()
|
|
||||||
.setMediaSource(delegatingMediaSource)
|
|
||||||
.setActionSchedule(actionSchedule)
|
|
||||||
.build(context)
|
|
||||||
.start()
|
|
||||||
.blockUntilActionScheduleFinished(TIMEOUT_MS)
|
|
||||||
.blockUntilEnded(TIMEOUT_MS);
|
|
||||||
exoPlayerTestRunner.assertTimelineChangeReasonsEqual(Player.TIMELINE_CHANGE_REASON_PREPARED);
|
|
||||||
assertArrayEquals(new long[] {2}, windowCounts);
|
|
||||||
assertArrayEquals(new int[] {seekToWindowIndex}, currentWindowIndices);
|
|
||||||
assertArrayEquals(new long[] {5_000}, currentPlaybackPositions);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testSeekTo_windowIndexIsReset_deprecated() throws Exception {
|
|
||||||
FakeTimeline fakeTimeline = new FakeTimeline(/* windowCount= */ 1);
|
|
||||||
FakeMediaSource mediaSource = new FakeMediaSource(fakeTimeline);
|
|
||||||
LoopingMediaSource loopingMediaSource = new LoopingMediaSource(mediaSource, 2);
|
|
||||||
final int[] windowIndex = {C.INDEX_UNSET};
|
|
||||||
final long[] positionMs = {C.TIME_UNSET};
|
|
||||||
ActionSchedule actionSchedule =
|
|
||||||
new ActionSchedule.Builder("testSeekTo_windowIndexIsReset_deprecated")
|
|
||||||
.seek(/* windowIndex= */ 1, /* positionMs= */ C.TIME_UNSET)
|
|
||||||
.waitForSeekProcessed()
|
|
||||||
.playUntilPosition(/* windowIndex= */ 1, /* positionMs= */ 5000)
|
|
||||||
.executeRunnable(
|
|
||||||
new PlayerRunnable() {
|
|
||||||
@Override
|
|
||||||
public void run(SimpleExoPlayer player) {
|
|
||||||
//noinspection deprecation
|
|
||||||
player.prepare(mediaSource);
|
|
||||||
player.seekTo(/* positionMs= */ 5000);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.executeRunnable(
|
|
||||||
new PlayerRunnable() {
|
|
||||||
@Override
|
|
||||||
public void run(SimpleExoPlayer player) {
|
|
||||||
windowIndex[0] = player.getCurrentWindowIndex();
|
|
||||||
positionMs[0] = player.getCurrentPosition();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.build();
|
|
||||||
new ExoPlayerTestRunner.Builder()
|
|
||||||
.setMediaSource(loopingMediaSource)
|
|
||||||
.setActionSchedule(actionSchedule)
|
|
||||||
.build(context)
|
|
||||||
.start()
|
|
||||||
.blockUntilActionScheduleFinished(TIMEOUT_MS);
|
|
||||||
|
|
||||||
assertThat(windowIndex[0]).isEqualTo(0);
|
|
||||||
assertThat(positionMs[0]).isAtLeast(5000L);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testSeekTo_windowIndexIsReset() throws Exception {
|
|
||||||
FakeTimeline fakeTimeline = new FakeTimeline(/* windowCount= */ 1);
|
|
||||||
FakeMediaSource mediaSource = new FakeMediaSource(fakeTimeline);
|
|
||||||
LoopingMediaSource loopingMediaSource = new LoopingMediaSource(mediaSource, 2);
|
|
||||||
final int[] windowIndex = {C.INDEX_UNSET};
|
|
||||||
final long[] positionMs = {C.TIME_UNSET};
|
|
||||||
ActionSchedule actionSchedule =
|
|
||||||
new ActionSchedule.Builder("testSeekTo_windowIndexIsReset")
|
|
||||||
.seek(/* windowIndex= */ 1, /* positionMs= */ C.TIME_UNSET)
|
|
||||||
.waitForSeekProcessed()
|
|
||||||
.playUntilPosition(/* windowIndex= */ 1, /* positionMs= */ 5000)
|
|
||||||
.executeRunnable(
|
|
||||||
new PlayerRunnable() {
|
|
||||||
@Override
|
|
||||||
public void run(SimpleExoPlayer player) {
|
|
||||||
player.setMediaItem(mediaSource, /* startPositionMs= */ 5000);
|
|
||||||
player.prepare();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.executeRunnable(
|
|
||||||
new PlayerRunnable() {
|
|
||||||
@Override
|
|
||||||
public void run(SimpleExoPlayer player) {
|
|
||||||
windowIndex[0] = player.getCurrentWindowIndex();
|
|
||||||
positionMs[0] = player.getCurrentPosition();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.build();
|
|
||||||
new ExoPlayerTestRunner.Builder()
|
|
||||||
.setMediaSource(loopingMediaSource)
|
|
||||||
.setActionSchedule(actionSchedule)
|
|
||||||
.build(context)
|
|
||||||
.start()
|
|
||||||
.blockUntilActionScheduleFinished(TIMEOUT_MS);
|
|
||||||
|
|
||||||
assertThat(windowIndex[0]).isEqualTo(0);
|
|
||||||
assertThat(positionMs[0]).isAtLeast(5000L);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void becomingNoisyIgnoredIfBecomingNoisyHandlingIsDisabled() throws Exception {
|
|
||||||
CountDownLatch becomingNoisyHandlingDisabled = new CountDownLatch(1);
|
|
||||||
CountDownLatch becomingNoisyDelivered = new CountDownLatch(1);
|
|
||||||
PlayerStateGrabber playerStateGrabber = new PlayerStateGrabber();
|
|
||||||
ActionSchedule actionSchedule =
|
|
||||||
new ActionSchedule.Builder("becomingNoisyIgnoredIfBecomingNoisyHandlingIsDisabled")
|
|
||||||
.executeRunnable(
|
|
||||||
new PlayerRunnable() {
|
|
||||||
@Override
|
|
||||||
public void run(SimpleExoPlayer player) {
|
|
||||||
player.setHandleAudioBecomingNoisy(false);
|
|
||||||
becomingNoisyHandlingDisabled.countDown();
|
|
||||||
|
|
||||||
// Wait for the broadcast to be delivered from the main thread.
|
|
||||||
try {
|
|
||||||
becomingNoisyDelivered.await();
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
throw new IllegalStateException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.delay(1) // Handle pending messages on the playback thread.
|
|
||||||
.executeRunnable(playerStateGrabber)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
ExoPlayerTestRunner testRunner =
|
|
||||||
new ExoPlayerTestRunner.Builder().setActionSchedule(actionSchedule).build(context).start();
|
|
||||||
becomingNoisyHandlingDisabled.await();
|
|
||||||
deliverBroadcast(new Intent(AudioManager.ACTION_AUDIO_BECOMING_NOISY));
|
|
||||||
becomingNoisyDelivered.countDown();
|
|
||||||
|
|
||||||
testRunner.blockUntilActionScheduleFinished(TIMEOUT_MS).blockUntilEnded(TIMEOUT_MS);
|
|
||||||
assertThat(playerStateGrabber.playWhenReady).isTrue();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void pausesWhenBecomingNoisyIfBecomingNoisyHandlingIsEnabled() throws Exception {
|
|
||||||
CountDownLatch becomingNoisyHandlingEnabled = new CountDownLatch(1);
|
|
||||||
ActionSchedule actionSchedule =
|
|
||||||
new ActionSchedule.Builder("pausesWhenBecomingNoisyIfBecomingNoisyHandlingIsEnabled")
|
|
||||||
.executeRunnable(
|
|
||||||
new PlayerRunnable() {
|
|
||||||
@Override
|
|
||||||
public void run(SimpleExoPlayer player) {
|
|
||||||
player.setHandleAudioBecomingNoisy(true);
|
|
||||||
becomingNoisyHandlingEnabled.countDown();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.waitForPlayWhenReady(false) // Becoming noisy should set playWhenReady = false
|
|
||||||
.play()
|
|
||||||
.build();
|
|
||||||
|
|
||||||
ExoPlayerTestRunner testRunner =
|
|
||||||
new ExoPlayerTestRunner.Builder().setActionSchedule(actionSchedule).build(context).start();
|
|
||||||
becomingNoisyHandlingEnabled.await();
|
|
||||||
deliverBroadcast(new Intent(AudioManager.ACTION_AUDIO_BECOMING_NOISY));
|
|
||||||
|
|
||||||
// If the player fails to handle becoming noisy, blockUntilActionScheduleFinished will time out
|
|
||||||
// and throw, causing the test to fail.
|
|
||||||
testRunner.blockUntilActionScheduleFinished(TIMEOUT_MS).blockUntilEnded(TIMEOUT_MS);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Internal methods.
|
// Internal methods.
|
||||||
|
|
||||||
private static ActionSchedule.Builder addSurfaceSwitch(ActionSchedule.Builder builder) {
|
private static ActionSchedule.Builder addSurfaceSwitch(ActionSchedule.Builder builder) {
|
||||||
|
@ -431,8 +431,7 @@ public final class ExoPlayerTestRunner implements Player.EventListener, ActionSc
|
|||||||
if (actionSchedule != null) {
|
if (actionSchedule != null) {
|
||||||
actionSchedule.start(player, trackSelector, null, handler, ExoPlayerTestRunner.this);
|
actionSchedule.start(player, trackSelector, null, handler, ExoPlayerTestRunner.this);
|
||||||
}
|
}
|
||||||
player.setMediaItem(mediaSource);
|
player.prepare(mediaSource, /* resetPosition= */ false, /* resetState= */ false);
|
||||||
player.prepare();
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
handleException(e);
|
handleException(e);
|
||||||
}
|
}
|
||||||
|
@ -96,11 +96,6 @@ public abstract class StubExoPlayer extends BasePlayer implements ExoPlayer {
|
|||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void prepare() {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void prepare(MediaSource mediaSource) {
|
public void prepare(MediaSource mediaSource) {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
@ -111,16 +106,6 @@ public abstract class StubExoPlayer extends BasePlayer implements ExoPlayer {
|
|||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setMediaItem(MediaSource mediaItem) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setMediaItem(MediaSource mediaItem, long startPositionMs) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setPlayWhenReady(boolean playWhenReady) {
|
public void setPlayWhenReady(boolean playWhenReady) {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user