mirror of
https://github.com/androidx/media.git
synced 2025-05-15 11:39:56 +08:00
Extend ActionSchedule with new actions.
The new actions are: prepare source, set repeat mode, wait for timeline change, wait for position discontinuity, execute Runnable. Moreover, this change removes the restriction of using a SimpleExoPlayer to allow ActionSchedule to be used in other scenarios. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=162918554
This commit is contained in:
parent
0411add91e
commit
3991a6198b
@ -15,11 +15,20 @@
|
|||||||
*/
|
*/
|
||||||
package com.google.android.exoplayer2.testutil;
|
package com.google.android.exoplayer2.testutil;
|
||||||
|
|
||||||
|
import android.os.Handler;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.Surface;
|
import android.view.Surface;
|
||||||
|
import com.google.android.exoplayer2.ExoPlaybackException;
|
||||||
import com.google.android.exoplayer2.ExoPlayer;
|
import com.google.android.exoplayer2.ExoPlayer;
|
||||||
|
import com.google.android.exoplayer2.PlaybackParameters;
|
||||||
|
import com.google.android.exoplayer2.Player;
|
||||||
import com.google.android.exoplayer2.SimpleExoPlayer;
|
import com.google.android.exoplayer2.SimpleExoPlayer;
|
||||||
|
import com.google.android.exoplayer2.Timeline;
|
||||||
|
import com.google.android.exoplayer2.source.MediaSource;
|
||||||
|
import com.google.android.exoplayer2.source.TrackGroupArray;
|
||||||
|
import com.google.android.exoplayer2.testutil.ActionSchedule.ActionNode;
|
||||||
import com.google.android.exoplayer2.trackselection.MappingTrackSelector;
|
import com.google.android.exoplayer2.trackselection.MappingTrackSelector;
|
||||||
|
import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class for actions to perform during playback tests.
|
* Base class for actions to perform during playback tests.
|
||||||
@ -39,21 +48,41 @@ public abstract class Action {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Executes the action.
|
* Executes the action and schedules the next.
|
||||||
*
|
*
|
||||||
* @param player The player to which the action should be applied.
|
* @param player The player to which the action should be applied.
|
||||||
* @param trackSelector The track selector to which the action should be applied.
|
* @param trackSelector The track selector to which the action should be applied.
|
||||||
* @param surface The surface to use when applying actions.
|
* @param surface The surface to use when applying actions.
|
||||||
|
* @param handler The handler to use to pass to the next action.
|
||||||
|
* @param nextAction The next action to schedule immediately after this action finished.
|
||||||
*/
|
*/
|
||||||
public final void doAction(SimpleExoPlayer player, MappingTrackSelector trackSelector,
|
public final void doActionAndScheduleNext(SimpleExoPlayer player,
|
||||||
Surface surface) {
|
MappingTrackSelector trackSelector, Surface surface, Handler handler, ActionNode nextAction) {
|
||||||
Log.i(tag, description);
|
Log.i(tag, description);
|
||||||
doActionImpl(player, trackSelector, surface);
|
doActionAndScheduleNextImpl(player, trackSelector, surface, handler, nextAction);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called by {@link #doAction(SimpleExoPlayer, MappingTrackSelector, Surface)} do perform the
|
* Called by {@link #doActionAndScheduleNext(SimpleExoPlayer, MappingTrackSelector, Surface,
|
||||||
* action.
|
* Handler, ActionNode)} to perform the action and to schedule the next action node.
|
||||||
|
*
|
||||||
|
* @param player The player to which the action should be applied.
|
||||||
|
* @param trackSelector The track selector to which the action should be applied.
|
||||||
|
* @param surface The surface to use when applying actions.
|
||||||
|
* @param handler The handler to use to pass to the next action.
|
||||||
|
* @param nextAction The next action to schedule immediately after this action finished.
|
||||||
|
*/
|
||||||
|
protected void doActionAndScheduleNextImpl(SimpleExoPlayer player,
|
||||||
|
MappingTrackSelector trackSelector, Surface surface, Handler handler, ActionNode nextAction) {
|
||||||
|
doActionImpl(player, trackSelector, surface);
|
||||||
|
if (nextAction != null) {
|
||||||
|
nextAction.schedule(player, trackSelector, surface, handler);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called by {@link #doActionAndScheduleNextImpl(SimpleExoPlayer, MappingTrackSelector, Surface,
|
||||||
|
* Handler, ActionNode)} to perform the action.
|
||||||
*
|
*
|
||||||
* @param player The player to which the action should be applied.
|
* @param player The player to which the action should be applied.
|
||||||
* @param trackSelector The track selector to which the action should be applied.
|
* @param trackSelector The track selector to which the action should be applied.
|
||||||
@ -63,7 +92,7 @@ public abstract class Action {
|
|||||||
Surface surface);
|
Surface surface);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calls {@link ExoPlayer#seekTo(long)}.
|
* Calls {@link Player#seekTo(long)}.
|
||||||
*/
|
*/
|
||||||
public static final class Seek extends Action {
|
public static final class Seek extends Action {
|
||||||
|
|
||||||
@ -87,7 +116,7 @@ public abstract class Action {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calls {@link ExoPlayer#stop()}.
|
* Calls {@link Player#stop()}.
|
||||||
*/
|
*/
|
||||||
public static final class Stop extends Action {
|
public static final class Stop extends Action {
|
||||||
|
|
||||||
@ -107,7 +136,7 @@ public abstract class Action {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calls {@link ExoPlayer#setPlayWhenReady(boolean)}.
|
* Calls {@link Player#setPlayWhenReady(boolean)}.
|
||||||
*/
|
*/
|
||||||
public static final class SetPlayWhenReady extends Action {
|
public static final class SetPlayWhenReady extends Action {
|
||||||
|
|
||||||
@ -197,5 +226,206 @@ public abstract class Action {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calls {@link ExoPlayer#prepare(MediaSource)}.
|
||||||
|
*/
|
||||||
|
public static final class PrepareSource extends Action {
|
||||||
|
|
||||||
|
private final MediaSource mediaSource;
|
||||||
|
private final boolean resetPosition;
|
||||||
|
private final boolean resetState;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param tag A tag to use for logging.
|
||||||
|
*/
|
||||||
|
public PrepareSource(String tag, MediaSource mediaSource) {
|
||||||
|
this(tag, mediaSource, true, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param tag A tag to use for logging.
|
||||||
|
*/
|
||||||
|
public PrepareSource(String tag, MediaSource mediaSource, boolean resetPosition,
|
||||||
|
boolean resetState) {
|
||||||
|
super(tag, "PrepareSource");
|
||||||
|
this.mediaSource = mediaSource;
|
||||||
|
this.resetPosition = resetPosition;
|
||||||
|
this.resetState = resetState;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doActionImpl(SimpleExoPlayer player, MappingTrackSelector trackSelector,
|
||||||
|
Surface surface) {
|
||||||
|
player.prepare(mediaSource, resetPosition, resetState);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calls {@link Player#setRepeatMode(int)}.
|
||||||
|
*/
|
||||||
|
public static final class SetRepeatMode extends Action {
|
||||||
|
|
||||||
|
private final @Player.RepeatMode int repeatMode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param tag A tag to use for logging.
|
||||||
|
*/
|
||||||
|
public SetRepeatMode(String tag, @Player.RepeatMode int repeatMode) {
|
||||||
|
super(tag, "SetRepeatMode:" + repeatMode);
|
||||||
|
this.repeatMode = repeatMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doActionImpl(SimpleExoPlayer player, MappingTrackSelector trackSelector,
|
||||||
|
Surface surface) {
|
||||||
|
player.setRepeatMode(repeatMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Waits for {@link Player.EventListener#onTimelineChanged(Timeline, Object)}.
|
||||||
|
*/
|
||||||
|
public static final class WaitForTimelineChanged extends Action {
|
||||||
|
|
||||||
|
private final Timeline expectedTimeline;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param tag A tag to use for logging.
|
||||||
|
*/
|
||||||
|
public WaitForTimelineChanged(String tag, Timeline expectedTimeline) {
|
||||||
|
super(tag, "WaitForTimelineChanged");
|
||||||
|
this.expectedTimeline = expectedTimeline;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doActionAndScheduleNextImpl(final SimpleExoPlayer player,
|
||||||
|
final MappingTrackSelector trackSelector, final Surface surface, final Handler handler,
|
||||||
|
final ActionNode nextAction) {
|
||||||
|
PlayerListener listener = new PlayerListener() {
|
||||||
|
@Override
|
||||||
|
public void onTimelineChanged(Timeline timeline, Object manifest) {
|
||||||
|
if (timeline.equals(expectedTimeline)) {
|
||||||
|
player.removeListener(this);
|
||||||
|
nextAction.schedule(player, trackSelector, surface, handler);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
player.addListener(listener);
|
||||||
|
if (player.getCurrentTimeline().equals(expectedTimeline)) {
|
||||||
|
player.removeListener(listener);
|
||||||
|
nextAction.schedule(player, trackSelector, surface, handler);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doActionImpl(SimpleExoPlayer player, MappingTrackSelector trackSelector,
|
||||||
|
Surface surface) {
|
||||||
|
// Not triggered.
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Waits for {@link Player.EventListener#onPositionDiscontinuity()}.
|
||||||
|
*/
|
||||||
|
public static final class WaitForPositionDiscontinuity extends Action {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param tag A tag to use for logging.
|
||||||
|
*/
|
||||||
|
public WaitForPositionDiscontinuity(String tag) {
|
||||||
|
super(tag, "WaitForPositionDiscontinuity");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doActionAndScheduleNextImpl(final SimpleExoPlayer player,
|
||||||
|
final MappingTrackSelector trackSelector, final Surface surface, final Handler handler,
|
||||||
|
final ActionNode nextAction) {
|
||||||
|
player.addListener(new PlayerListener() {
|
||||||
|
@Override
|
||||||
|
public void onPositionDiscontinuity() {
|
||||||
|
player.removeListener(this);
|
||||||
|
nextAction.schedule(player, trackSelector, surface, handler);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doActionImpl(SimpleExoPlayer player, MappingTrackSelector trackSelector,
|
||||||
|
Surface surface) {
|
||||||
|
// Not triggered.
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calls {@link Runnable#run()}.
|
||||||
|
*/
|
||||||
|
public static final class ExecuteRunnable extends Action {
|
||||||
|
|
||||||
|
private final Runnable runnable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param tag A tag to use for logging.
|
||||||
|
*/
|
||||||
|
public ExecuteRunnable(String tag, Runnable runnable) {
|
||||||
|
super(tag, "ExecuteRunnable");
|
||||||
|
this.runnable = runnable;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doActionImpl(SimpleExoPlayer player, MappingTrackSelector trackSelector,
|
||||||
|
Surface surface) {
|
||||||
|
runnable.run();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Listener implementation used for overriding. Does nothing. */
|
||||||
|
private static class PlayerListener implements Player.EventListener {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTimelineChanged(Timeline timeline, Object manifest) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLoadingChanged(boolean isLoading) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onRepeatModeChanged(@ExoPlayer.RepeatMode int repeatMode) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPlayerError(ExoPlaybackException error) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPositionDiscontinuity() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -18,13 +18,22 @@ package com.google.android.exoplayer2.testutil;
|
|||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.view.Surface;
|
import android.view.Surface;
|
||||||
import com.google.android.exoplayer2.C;
|
import com.google.android.exoplayer2.C;
|
||||||
|
import com.google.android.exoplayer2.ExoPlayer;
|
||||||
|
import com.google.android.exoplayer2.Player;
|
||||||
import com.google.android.exoplayer2.SimpleExoPlayer;
|
import com.google.android.exoplayer2.SimpleExoPlayer;
|
||||||
|
import com.google.android.exoplayer2.Timeline;
|
||||||
|
import com.google.android.exoplayer2.source.MediaSource;
|
||||||
import com.google.android.exoplayer2.testutil.Action.ClearVideoSurface;
|
import com.google.android.exoplayer2.testutil.Action.ClearVideoSurface;
|
||||||
|
import com.google.android.exoplayer2.testutil.Action.ExecuteRunnable;
|
||||||
|
import com.google.android.exoplayer2.testutil.Action.PrepareSource;
|
||||||
import com.google.android.exoplayer2.testutil.Action.Seek;
|
import com.google.android.exoplayer2.testutil.Action.Seek;
|
||||||
import com.google.android.exoplayer2.testutil.Action.SetPlayWhenReady;
|
import com.google.android.exoplayer2.testutil.Action.SetPlayWhenReady;
|
||||||
import com.google.android.exoplayer2.testutil.Action.SetRendererDisabled;
|
import com.google.android.exoplayer2.testutil.Action.SetRendererDisabled;
|
||||||
|
import com.google.android.exoplayer2.testutil.Action.SetRepeatMode;
|
||||||
import com.google.android.exoplayer2.testutil.Action.SetVideoSurface;
|
import com.google.android.exoplayer2.testutil.Action.SetVideoSurface;
|
||||||
import com.google.android.exoplayer2.testutil.Action.Stop;
|
import com.google.android.exoplayer2.testutil.Action.Stop;
|
||||||
|
import com.google.android.exoplayer2.testutil.Action.WaitForPositionDiscontinuity;
|
||||||
|
import com.google.android.exoplayer2.testutil.Action.WaitForTimelineChanged;
|
||||||
import com.google.android.exoplayer2.trackselection.MappingTrackSelector;
|
import com.google.android.exoplayer2.trackselection.MappingTrackSelector;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -179,6 +188,63 @@ public final class ActionSchedule {
|
|||||||
return apply(new SetVideoSurface(tag));
|
return apply(new SetVideoSurface(tag));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Schedules a new source preparation action to be executed.
|
||||||
|
*
|
||||||
|
* @return The builder, for convenience.
|
||||||
|
*/
|
||||||
|
public Builder prepareSource(MediaSource mediaSource) {
|
||||||
|
return apply(new PrepareSource(tag, mediaSource));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Schedules a new source preparation action to be executed.
|
||||||
|
* @see ExoPlayer#prepare(MediaSource, boolean, boolean).
|
||||||
|
*
|
||||||
|
* @return The builder, for convenience.
|
||||||
|
*/
|
||||||
|
public Builder prepareSource(MediaSource mediaSource, boolean resetPosition,
|
||||||
|
boolean resetState) {
|
||||||
|
return apply(new PrepareSource(tag, mediaSource, resetPosition, resetState));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Schedules a repeat mode setting action to be executed.
|
||||||
|
*
|
||||||
|
* @return The builder, for convenience.
|
||||||
|
*/
|
||||||
|
public Builder setRepeatMode(@Player.RepeatMode int repeatMode) {
|
||||||
|
return apply(new SetRepeatMode(tag, repeatMode));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Schedules a delay until the timeline changed to a specified expected timeline.
|
||||||
|
*
|
||||||
|
* @param expectedTimeline The expected timeline to wait for.
|
||||||
|
* @return The builder, for convenience.
|
||||||
|
*/
|
||||||
|
public Builder waitForTimelineChanged(Timeline expectedTimeline) {
|
||||||
|
return apply(new WaitForTimelineChanged(tag, expectedTimeline));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Schedules a delay until the next position discontinuity.
|
||||||
|
*
|
||||||
|
* @return The builder, for convenience.
|
||||||
|
*/
|
||||||
|
public Builder waitForPositionDiscontinuity() {
|
||||||
|
return apply(new WaitForPositionDiscontinuity(tag));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Schedules a {@link Runnable} to be executed.
|
||||||
|
*
|
||||||
|
* @return The builder, for convenience.
|
||||||
|
*/
|
||||||
|
public Builder executeRunnable(Runnable runnable) {
|
||||||
|
return apply(new ExecuteRunnable(tag, runnable));
|
||||||
|
}
|
||||||
|
|
||||||
public ActionSchedule build() {
|
public ActionSchedule build() {
|
||||||
return new ActionSchedule(rootNode);
|
return new ActionSchedule(rootNode);
|
||||||
}
|
}
|
||||||
@ -195,7 +261,7 @@ public final class ActionSchedule {
|
|||||||
/**
|
/**
|
||||||
* Wraps an {@link Action}, allowing a delay and a next {@link Action} to be specified.
|
* Wraps an {@link Action}, allowing a delay and a next {@link Action} to be specified.
|
||||||
*/
|
*/
|
||||||
private static final class ActionNode implements Runnable {
|
/* package */ static final class ActionNode implements Runnable {
|
||||||
|
|
||||||
private final Action action;
|
private final Action action;
|
||||||
private final long delayMs;
|
private final long delayMs;
|
||||||
@ -257,10 +323,7 @@ public final class ActionSchedule {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
action.doAction(player, trackSelector, surface);
|
action.doActionAndScheduleNext(player, trackSelector, surface, mainHandler, next);
|
||||||
if (next != null) {
|
|
||||||
next.schedule(player, trackSelector, surface, mainHandler);
|
|
||||||
}
|
|
||||||
if (repeatIntervalMs != C.TIME_UNSET) {
|
if (repeatIntervalMs != C.TIME_UNSET) {
|
||||||
mainHandler.postDelayed(this, repeatIntervalMs);
|
mainHandler.postDelayed(this, repeatIntervalMs);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user