mirror of
https://github.com/androidx/media.git
synced 2025-04-30 06:46:50 +08:00
Add initial playWhenReady setting and tests
Also includes a new test for a similar logic that already exists for speed changes.
This commit is contained in:
parent
e4b32e4e31
commit
513ebf67b7
@ -1879,7 +1879,9 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
// The reselection did not change any prepared periods.
|
// The reselection did not change any prepared periods.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
newTrackSelectorResult = periodHolder.selectTracks(playbackSpeed, playbackInfo.timeline);
|
newTrackSelectorResult =
|
||||||
|
periodHolder.selectTracks(
|
||||||
|
playbackSpeed, playbackInfo.timeline, playbackInfo.playWhenReady);
|
||||||
if (periodHolder == queue.getPlayingPeriod()) {
|
if (periodHolder == queue.getPlayingPeriod()) {
|
||||||
newPlayingPeriodTrackSelectorResult = newTrackSelectorResult;
|
newPlayingPeriodTrackSelectorResult = newTrackSelectorResult;
|
||||||
}
|
}
|
||||||
@ -2563,7 +2565,9 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
if (preloadHolder != null) {
|
if (preloadHolder != null) {
|
||||||
checkState(!preloadHolder.prepared);
|
checkState(!preloadHolder.prepared);
|
||||||
preloadHolder.handlePrepared(
|
preloadHolder.handlePrepared(
|
||||||
mediaClock.getPlaybackParameters().speed, playbackInfo.timeline);
|
mediaClock.getPlaybackParameters().speed,
|
||||||
|
playbackInfo.timeline,
|
||||||
|
playbackInfo.playWhenReady);
|
||||||
if (queue.isPreloading(mediaPeriod)) {
|
if (queue.isPreloading(mediaPeriod)) {
|
||||||
maybeContinuePreloading();
|
maybeContinuePreloading();
|
||||||
}
|
}
|
||||||
@ -2575,7 +2579,9 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
throws ExoPlaybackException {
|
throws ExoPlaybackException {
|
||||||
if (!loadingPeriodHolder.prepared) {
|
if (!loadingPeriodHolder.prepared) {
|
||||||
loadingPeriodHolder.handlePrepared(
|
loadingPeriodHolder.handlePrepared(
|
||||||
mediaClock.getPlaybackParameters().speed, playbackInfo.timeline);
|
mediaClock.getPlaybackParameters().speed,
|
||||||
|
playbackInfo.timeline,
|
||||||
|
playbackInfo.playWhenReady);
|
||||||
}
|
}
|
||||||
updateLoadControlTrackSelection(
|
updateLoadControlTrackSelection(
|
||||||
loadingPeriodHolder.info.id,
|
loadingPeriodHolder.info.id,
|
||||||
|
@ -203,12 +203,14 @@ import java.io.IOException;
|
|||||||
*
|
*
|
||||||
* @param playbackSpeed The current factor by which playback is sped up.
|
* @param playbackSpeed The current factor by which playback is sped up.
|
||||||
* @param timeline The current {@link Timeline}.
|
* @param timeline The current {@link Timeline}.
|
||||||
|
* @param playWhenReady The current value of whether playback should proceed when ready.
|
||||||
* @throws ExoPlaybackException If an error occurs during track selection.
|
* @throws ExoPlaybackException If an error occurs during track selection.
|
||||||
*/
|
*/
|
||||||
public void handlePrepared(float playbackSpeed, Timeline timeline) throws ExoPlaybackException {
|
public void handlePrepared(float playbackSpeed, Timeline timeline, boolean playWhenReady)
|
||||||
|
throws ExoPlaybackException {
|
||||||
prepared = true;
|
prepared = true;
|
||||||
trackGroups = mediaPeriod.getTrackGroups();
|
trackGroups = mediaPeriod.getTrackGroups();
|
||||||
TrackSelectorResult selectorResult = selectTracks(playbackSpeed, timeline);
|
TrackSelectorResult selectorResult = selectTracks(playbackSpeed, timeline, playWhenReady);
|
||||||
long requestedStartPositionUs = info.startPositionUs;
|
long requestedStartPositionUs = info.startPositionUs;
|
||||||
if (info.durationUs != C.TIME_UNSET && requestedStartPositionUs >= info.durationUs) {
|
if (info.durationUs != C.TIME_UNSET && requestedStartPositionUs >= info.durationUs) {
|
||||||
// Make sure start position doesn't exceed period duration.
|
// Make sure start position doesn't exceed period duration.
|
||||||
@ -254,11 +256,12 @@ import java.io.IOException;
|
|||||||
*
|
*
|
||||||
* @param playbackSpeed The current factor by which playback is sped up.
|
* @param playbackSpeed The current factor by which playback is sped up.
|
||||||
* @param timeline The current {@link Timeline}.
|
* @param timeline The current {@link Timeline}.
|
||||||
|
* @param playWhenReady The current value of whether playback should proceed when ready.
|
||||||
* @return The {@link TrackSelectorResult}.
|
* @return The {@link TrackSelectorResult}.
|
||||||
* @throws ExoPlaybackException If an error occurs during track selection.
|
* @throws ExoPlaybackException If an error occurs during track selection.
|
||||||
*/
|
*/
|
||||||
public TrackSelectorResult selectTracks(float playbackSpeed, Timeline timeline)
|
public TrackSelectorResult selectTracks(
|
||||||
throws ExoPlaybackException {
|
float playbackSpeed, Timeline timeline, boolean playWhenReady) throws ExoPlaybackException {
|
||||||
TrackSelectorResult selectorResult =
|
TrackSelectorResult selectorResult =
|
||||||
trackSelector.selectTracks(rendererCapabilities, getTrackGroups(), info.id, timeline);
|
trackSelector.selectTracks(rendererCapabilities, getTrackGroups(), info.id, timeline);
|
||||||
for (int i = 0; i < selectorResult.length; i++) {
|
for (int i = 0; i < selectorResult.length; i++) {
|
||||||
@ -273,6 +276,7 @@ import java.io.IOException;
|
|||||||
for (ExoTrackSelection trackSelection : selectorResult.selections) {
|
for (ExoTrackSelection trackSelection : selectorResult.selections) {
|
||||||
if (trackSelection != null) {
|
if (trackSelection != null) {
|
||||||
trackSelection.onPlaybackSpeed(playbackSpeed);
|
trackSelection.onPlaybackSpeed(playbackSpeed);
|
||||||
|
trackSelection.onPlayWhenReadyChanged(playWhenReady);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return selectorResult;
|
return selectorResult;
|
||||||
|
@ -18,6 +18,7 @@ package androidx.media3.exoplayer.trackselection;
|
|||||||
import static java.lang.Math.max;
|
import static java.lang.Math.max;
|
||||||
|
|
||||||
import android.os.SystemClock;
|
import android.os.SystemClock;
|
||||||
|
import androidx.annotation.CallSuper;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.media3.common.C;
|
import androidx.media3.common.C;
|
||||||
import androidx.media3.common.Format;
|
import androidx.media3.common.Format;
|
||||||
@ -54,8 +55,8 @@ public abstract class BaseTrackSelection implements ExoTrackSelection {
|
|||||||
// Lazily initialized hashcode.
|
// Lazily initialized hashcode.
|
||||||
private int hashCode;
|
private int hashCode;
|
||||||
|
|
||||||
/** The last playWhenReady value when {@link #onPlayWhenReadyChanged(boolean)} was triggered */
|
/** The current value of whether playback will proceed when ready. */
|
||||||
private boolean lastPlayWhenReady;
|
private boolean playWhenReady;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param group The {@link TrackGroup}. Must not be null.
|
* @param group The {@link TrackGroup}. Must not be null.
|
||||||
@ -90,7 +91,7 @@ public abstract class BaseTrackSelection implements ExoTrackSelection {
|
|||||||
this.tracks[i] = group.indexOf(formats[i]);
|
this.tracks[i] = group.indexOf(formats[i]);
|
||||||
}
|
}
|
||||||
excludeUntilTimes = new long[length];
|
excludeUntilTimes = new long[length];
|
||||||
lastPlayWhenReady = false;
|
playWhenReady = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TrackSelection implementation.
|
// TrackSelection implementation.
|
||||||
@ -195,13 +196,15 @@ public abstract class BaseTrackSelection implements ExoTrackSelection {
|
|||||||
return excludeUntilTimes[index] > nowMs;
|
return excludeUntilTimes[index] > nowMs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@CallSuper
|
||||||
@Override
|
@Override
|
||||||
public void onPlayWhenReadyChanged(boolean playWhenReady) {
|
public void onPlayWhenReadyChanged(boolean playWhenReady) {
|
||||||
lastPlayWhenReady = playWhenReady;
|
this.playWhenReady = playWhenReady;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Returns whether the playback using this track selection will proceed when ready. */
|
||||||
protected final boolean getPlayWhenReady() {
|
protected final boolean getPlayWhenReady() {
|
||||||
return lastPlayWhenReady;
|
return playWhenReady;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Object overrides.
|
// Object overrides.
|
||||||
|
@ -16174,6 +16174,79 @@ public class ExoPlayerTest {
|
|||||||
assertThat(deviceVolumeChanged.get()).isFalse();
|
assertThat(deviceVolumeChanged.get()).isFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void playWhenReadyChanges_areForwardedToTrackSelection() throws Exception {
|
||||||
|
ArrayList<Boolean> reportedPlayWhenReadyChanges = new ArrayList<>();
|
||||||
|
ArrayList<Boolean> playWhenReadyStatesInTrackSelector = new ArrayList<>();
|
||||||
|
ExoPlayer player =
|
||||||
|
new TestExoPlayerBuilder(context)
|
||||||
|
.setTrackSelector(
|
||||||
|
new FakeTrackSelector(
|
||||||
|
new FakeTrackSelector.FakeTrackSelectionFactory(
|
||||||
|
/* mayReuseTrackSelection= */ false) {
|
||||||
|
@Override
|
||||||
|
protected ExoTrackSelection createTrackSelection(TrackGroup trackGroup) {
|
||||||
|
return new FakeTrackSelection(trackGroup) {
|
||||||
|
@Override
|
||||||
|
public void onPlayWhenReadyChanged(boolean playWhenReady) {
|
||||||
|
super.onPlayWhenReadyChanged(playWhenReady);
|
||||||
|
reportedPlayWhenReadyChanges.add(playWhenReady);
|
||||||
|
playWhenReadyStatesInTrackSelector.add(getPlayWhenReady());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
.build();
|
||||||
|
player.setMediaSource(
|
||||||
|
new FakeMediaSource(new FakeTimeline(), ExoPlayerTestRunner.VIDEO_FORMAT));
|
||||||
|
|
||||||
|
player.setPlayWhenReady(true);
|
||||||
|
player.prepare();
|
||||||
|
run(player).untilState(Player.STATE_READY);
|
||||||
|
player.setPlayWhenReady(false);
|
||||||
|
player.setPlayWhenReady(true);
|
||||||
|
run(player).untilPendingCommandsAreFullyHandled();
|
||||||
|
player.release();
|
||||||
|
|
||||||
|
assertThat(reportedPlayWhenReadyChanges).containsExactly(true, false, true).inOrder();
|
||||||
|
assertThat(playWhenReadyStatesInTrackSelector).containsExactly(true, false, true).inOrder();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void playbackSpeedChanges_areForwardedToTrackSelection() throws Exception {
|
||||||
|
ArrayList<Float> reportedSpeedChanges = new ArrayList<>();
|
||||||
|
ExoPlayer player =
|
||||||
|
new TestExoPlayerBuilder(context)
|
||||||
|
.setTrackSelector(
|
||||||
|
new FakeTrackSelector(
|
||||||
|
new FakeTrackSelector.FakeTrackSelectionFactory(
|
||||||
|
/* mayReuseTrackSelection= */ false) {
|
||||||
|
@Override
|
||||||
|
protected ExoTrackSelection createTrackSelection(TrackGroup trackGroup) {
|
||||||
|
return new FakeTrackSelection(trackGroup) {
|
||||||
|
@Override
|
||||||
|
public void onPlaybackSpeed(float playbackSpeed) {
|
||||||
|
super.onPlaybackSpeed(playbackSpeed);
|
||||||
|
reportedSpeedChanges.add(playbackSpeed);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
.build();
|
||||||
|
player.setMediaSource(
|
||||||
|
new FakeMediaSource(new FakeTimeline(), ExoPlayerTestRunner.VIDEO_FORMAT));
|
||||||
|
|
||||||
|
player.setPlaybackSpeed(2f);
|
||||||
|
player.prepare();
|
||||||
|
run(player).untilState(Player.STATE_READY);
|
||||||
|
player.setPlaybackSpeed(1.5f);
|
||||||
|
player.setPlaybackSpeed(1f);
|
||||||
|
run(player).untilPendingCommandsAreFullyHandled();
|
||||||
|
player.release();
|
||||||
|
|
||||||
|
assertThat(reportedSpeedChanges).containsExactly(2f, 1.5f, 1f).inOrder();
|
||||||
|
}
|
||||||
|
|
||||||
// Internal methods.
|
// Internal methods.
|
||||||
|
|
||||||
private void addWatchAsSystemFeature() {
|
private void addWatchAsSystemFeature() {
|
||||||
|
@ -33,7 +33,7 @@ import java.util.List;
|
|||||||
* of calls to its methods.
|
* of calls to its methods.
|
||||||
*/
|
*/
|
||||||
@UnstableApi
|
@UnstableApi
|
||||||
public final class FakeTrackSelection extends BaseTrackSelection {
|
public class FakeTrackSelection extends BaseTrackSelection {
|
||||||
|
|
||||||
private final TrackGroup rendererTrackGroup;
|
private final TrackGroup rendererTrackGroup;
|
||||||
private final int selectedIndex;
|
private final int selectedIndex;
|
||||||
|
@ -50,7 +50,11 @@ public class FakeTrackSelector extends DefaultTrackSelector {
|
|||||||
this(new FakeTrackSelectionFactory(mayReuseTrackSelection));
|
this(new FakeTrackSelectionFactory(mayReuseTrackSelection));
|
||||||
}
|
}
|
||||||
|
|
||||||
private FakeTrackSelector(FakeTrackSelectionFactory fakeTrackSelectionFactory) {
|
/**
|
||||||
|
* @param fakeTrackSelectionFactory The {@link FakeTrackSelectionFactory} used to create the
|
||||||
|
* {@link FakeTrackSelection} instances.
|
||||||
|
*/
|
||||||
|
public FakeTrackSelector(FakeTrackSelectionFactory fakeTrackSelectionFactory) {
|
||||||
super(ApplicationProvider.getApplicationContext(), fakeTrackSelectionFactory);
|
super(ApplicationProvider.getApplicationContext(), fakeTrackSelectionFactory);
|
||||||
this.fakeTrackSelectionFactory = fakeTrackSelectionFactory;
|
this.fakeTrackSelectionFactory = fakeTrackSelectionFactory;
|
||||||
}
|
}
|
||||||
@ -80,7 +84,11 @@ public class FakeTrackSelector extends DefaultTrackSelector {
|
|||||||
return fakeTrackSelectionFactory.trackSelections;
|
return fakeTrackSelectionFactory.trackSelections;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class FakeTrackSelectionFactory implements ExoTrackSelection.Factory {
|
/**
|
||||||
|
* A factory for the {@link androidx.media3.test.utils.FakeTrackSelection} instances requested by
|
||||||
|
* the {@link FakeTrackSelector}.
|
||||||
|
*/
|
||||||
|
public static class FakeTrackSelectionFactory implements ExoTrackSelection.Factory {
|
||||||
|
|
||||||
private final List<FakeTrackSelection> trackSelections;
|
private final List<FakeTrackSelection> trackSelections;
|
||||||
private final boolean mayReuseTrackSelection;
|
private final boolean mayReuseTrackSelection;
|
||||||
@ -91,7 +99,7 @@ public class FakeTrackSelector extends DefaultTrackSelector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ExoTrackSelection[] createTrackSelections(
|
public final ExoTrackSelection[] createTrackSelections(
|
||||||
ExoTrackSelection.@NullableType Definition[] definitions,
|
ExoTrackSelection.@NullableType Definition[] definitions,
|
||||||
BandwidthMeter bandwidthMeter,
|
BandwidthMeter bandwidthMeter,
|
||||||
MediaPeriodId mediaPeriodId,
|
MediaPeriodId mediaPeriodId,
|
||||||
@ -106,7 +114,8 @@ public class FakeTrackSelector extends DefaultTrackSelector {
|
|||||||
return selections;
|
return selections;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ExoTrackSelection createTrackSelection(TrackGroup trackGroup) {
|
/** Creates the {@link FakeTrackSelection} from a {@link TrackGroup}. */
|
||||||
|
protected ExoTrackSelection createTrackSelection(TrackGroup trackGroup) {
|
||||||
if (mayReuseTrackSelection) {
|
if (mayReuseTrackSelection) {
|
||||||
for (FakeTrackSelection trackSelection : trackSelections) {
|
for (FakeTrackSelection trackSelection : trackSelections) {
|
||||||
if (trackSelection.getTrackGroup().equals(trackGroup)) {
|
if (trackSelection.getTrackGroup().equals(trackGroup)) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user