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;
|
||||
|
||||
import android.os.Handler;
|
||||
import android.util.Log;
|
||||
import android.view.Surface;
|
||||
import com.google.android.exoplayer2.ExoPlaybackException;
|
||||
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.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.TrackSelectionArray;
|
||||
|
||||
/**
|
||||
* 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 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.
|
||||
*/
|
||||
public final void doAction(SimpleExoPlayer player, MappingTrackSelector trackSelector,
|
||||
Surface surface) {
|
||||
public final void doActionAndScheduleNext(SimpleExoPlayer player,
|
||||
MappingTrackSelector trackSelector, Surface surface, Handler handler, ActionNode nextAction) {
|
||||
Log.i(tag, description);
|
||||
doActionImpl(player, trackSelector, surface);
|
||||
doActionAndScheduleNextImpl(player, trackSelector, surface, handler, nextAction);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by {@link #doAction(SimpleExoPlayer, MappingTrackSelector, Surface)} do perform the
|
||||
* action.
|
||||
* Called by {@link #doActionAndScheduleNext(SimpleExoPlayer, MappingTrackSelector, Surface,
|
||||
* 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 trackSelector The track selector to which the action should be applied.
|
||||
@ -63,7 +92,7 @@ public abstract class Action {
|
||||
Surface surface);
|
||||
|
||||
/**
|
||||
* Calls {@link ExoPlayer#seekTo(long)}.
|
||||
* Calls {@link Player#seekTo(long)}.
|
||||
*/
|
||||
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 {
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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.view.Surface;
|
||||
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.Timeline;
|
||||
import com.google.android.exoplayer2.source.MediaSource;
|
||||
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.SetPlayWhenReady;
|
||||
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.Stop;
|
||||
import com.google.android.exoplayer2.testutil.Action.WaitForPositionDiscontinuity;
|
||||
import com.google.android.exoplayer2.testutil.Action.WaitForTimelineChanged;
|
||||
import com.google.android.exoplayer2.trackselection.MappingTrackSelector;
|
||||
|
||||
/**
|
||||
@ -179,6 +188,63 @@ public final class ActionSchedule {
|
||||
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() {
|
||||
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.
|
||||
*/
|
||||
private static final class ActionNode implements Runnable {
|
||||
/* package */ static final class ActionNode implements Runnable {
|
||||
|
||||
private final Action action;
|
||||
private final long delayMs;
|
||||
@ -257,10 +323,7 @@ public final class ActionSchedule {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
action.doAction(player, trackSelector, surface);
|
||||
if (next != null) {
|
||||
next.schedule(player, trackSelector, surface, mainHandler);
|
||||
}
|
||||
action.doActionAndScheduleNext(player, trackSelector, surface, mainHandler, next);
|
||||
if (repeatIntervalMs != C.TIME_UNSET) {
|
||||
mainHandler.postDelayed(this, repeatIntervalMs);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user