mirror of
https://github.com/androidx/media.git
synced 2025-04-30 06:46:50 +08:00
Start and stop video rendering from CompositionPlayer
Before, we were starting and stopping video rendering when the renderers were started/stopped. This doesn't work for multi-video sequences though because we shouldn't stop and start rendering at every MediaItem transition in any of the input sequences. PiperOrigin-RevId: 750206410
This commit is contained in:
parent
ab6b0f6e10
commit
fe10ca2c9a
@ -983,6 +983,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer
|
|||||||
Context context, VideoFrameReleaseControl videoFrameReleaseControl) {
|
Context context, VideoFrameReleaseControl videoFrameReleaseControl) {
|
||||||
// TODO: b/391109644 - Add a more explicit API to enable replaying.
|
// TODO: b/391109644 - Add a more explicit API to enable replaying.
|
||||||
return new PlaybackVideoGraphWrapper.Builder(context, videoFrameReleaseControl)
|
return new PlaybackVideoGraphWrapper.Builder(context, videoFrameReleaseControl)
|
||||||
|
.setEnablePlaylistMode(true)
|
||||||
.setClock(getClock())
|
.setClock(getClock())
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
@ -115,6 +115,7 @@ public final class PlaybackVideoGraphWrapper implements VideoSinkProvider, Video
|
|||||||
private VideoGraph.@MonotonicNonNull Factory videoGraphFactory;
|
private VideoGraph.@MonotonicNonNull Factory videoGraphFactory;
|
||||||
private List<Effect> compositionEffects;
|
private List<Effect> compositionEffects;
|
||||||
private VideoCompositorSettings compositorSettings;
|
private VideoCompositorSettings compositorSettings;
|
||||||
|
private boolean enablePlaylistMode;
|
||||||
private Clock clock;
|
private Clock clock;
|
||||||
private boolean requestOpenGlToneMapping;
|
private boolean requestOpenGlToneMapping;
|
||||||
private boolean built;
|
private boolean built;
|
||||||
@ -185,6 +186,36 @@ public final class PlaybackVideoGraphWrapper implements VideoSinkProvider, Video
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets whether to enable playlist mode.
|
||||||
|
*
|
||||||
|
* <p>The default value is {@code false}.
|
||||||
|
*
|
||||||
|
* <p>This should only be set to {@code true} if there is a single {@linkplain
|
||||||
|
* PlaybackVideoGraphWrapper#getSink(int) input sink}.
|
||||||
|
*
|
||||||
|
* <p>If {@code true}, the {@link VideoGraph} output is considered as a playlist of clips. In
|
||||||
|
* this case, {@link PlaybackVideoGraphWrapper#startRendering()} and {@link
|
||||||
|
* PlaybackVideoGraphWrapper#stopRendering()} are called internally, when the corresponding
|
||||||
|
* methods are caller on the sink.
|
||||||
|
*
|
||||||
|
* <p>If {@code false}, the {@link VideoGraph} output is considered as a single clip. In this
|
||||||
|
* case, the caller is responsible for calling {@link
|
||||||
|
* PlaybackVideoGraphWrapper#startRendering()} and {@link
|
||||||
|
* PlaybackVideoGraphWrapper#stopRendering()}.
|
||||||
|
*
|
||||||
|
* @param enablePlaylistMode Whether to enable playlist mode.
|
||||||
|
* @return This builder, for convenience.
|
||||||
|
*/
|
||||||
|
@CanIgnoreReturnValue
|
||||||
|
public Builder setEnablePlaylistMode(boolean enablePlaylistMode) {
|
||||||
|
// This is set to true for ExoPlayer.setVideoEffects(). It's always false in
|
||||||
|
// CompositionPlayer, even if the Composition has a single sequence, because CompositionPlayer
|
||||||
|
// shouldn't behave differently for single and multi-sequence.
|
||||||
|
this.enablePlaylistMode = enablePlaylistMode;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the {@link Clock} that will be used.
|
* Sets the {@link Clock} that will be used.
|
||||||
*
|
*
|
||||||
@ -271,6 +302,7 @@ public final class PlaybackVideoGraphWrapper implements VideoSinkProvider, Video
|
|||||||
private final SparseArray<InputVideoSink> inputVideoSinks;
|
private final SparseArray<InputVideoSink> inputVideoSinks;
|
||||||
private final List<Effect> compositionEffects;
|
private final List<Effect> compositionEffects;
|
||||||
private final VideoCompositorSettings compositorSettings;
|
private final VideoCompositorSettings compositorSettings;
|
||||||
|
private final boolean enablePlaylistMode;
|
||||||
private final VideoSink defaultVideoSink;
|
private final VideoSink defaultVideoSink;
|
||||||
private final VideoSink.VideoFrameHandler videoFrameHandler;
|
private final VideoSink.VideoFrameHandler videoFrameHandler;
|
||||||
private final Clock clock;
|
private final Clock clock;
|
||||||
@ -321,6 +353,7 @@ public final class PlaybackVideoGraphWrapper implements VideoSinkProvider, Video
|
|||||||
inputVideoSinks = new SparseArray<>();
|
inputVideoSinks = new SparseArray<>();
|
||||||
compositionEffects = builder.compositionEffects;
|
compositionEffects = builder.compositionEffects;
|
||||||
compositorSettings = builder.compositorSettings;
|
compositorSettings = builder.compositorSettings;
|
||||||
|
enablePlaylistMode = builder.enablePlaylistMode;
|
||||||
clock = builder.clock;
|
clock = builder.clock;
|
||||||
defaultVideoSink = new DefaultVideoSink(builder.videoFrameReleaseControl, clock);
|
defaultVideoSink = new DefaultVideoSink(builder.videoFrameReleaseControl, clock);
|
||||||
videoFrameHandler =
|
videoFrameHandler =
|
||||||
@ -363,6 +396,16 @@ public final class PlaybackVideoGraphWrapper implements VideoSinkProvider, Video
|
|||||||
listeners.remove(listener);
|
listeners.remove(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Starts rendering to the output surface. */
|
||||||
|
public void startRendering() {
|
||||||
|
defaultVideoSink.startRendering();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Stops rendering to the output surface. */
|
||||||
|
public void stopRendering() {
|
||||||
|
defaultVideoSink.stopRendering();
|
||||||
|
}
|
||||||
|
|
||||||
// VideoSinkProvider methods
|
// VideoSinkProvider methods
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -704,12 +747,16 @@ public final class PlaybackVideoGraphWrapper implements VideoSinkProvider, Video
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void startRendering() {
|
public void startRendering() {
|
||||||
defaultVideoSink.startRendering();
|
if (enablePlaylistMode) {
|
||||||
|
PlaybackVideoGraphWrapper.this.startRendering();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void stopRendering() {
|
public void stopRendering() {
|
||||||
defaultVideoSink.stopRendering();
|
if (enablePlaylistMode) {
|
||||||
|
PlaybackVideoGraphWrapper.this.stopRendering();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -743,6 +743,7 @@ public final class CompositionPlayer extends SimpleBasePlayer
|
|||||||
}
|
}
|
||||||
} else if (endedCount == players.size()) {
|
} else if (endedCount == players.size()) {
|
||||||
playbackState = STATE_ENDED;
|
playbackState = STATE_ENDED;
|
||||||
|
checkStateNotNull(compositionPlayerInternal).stopRendering();
|
||||||
} else {
|
} else {
|
||||||
playbackState = STATE_READY;
|
playbackState = STATE_READY;
|
||||||
if (oldPlaybackState != STATE_READY && playWhenReady) {
|
if (oldPlaybackState != STATE_READY && playWhenReady) {
|
||||||
|
@ -155,10 +155,10 @@ import androidx.media3.exoplayer.video.PlaybackVideoGraphWrapper;
|
|||||||
try {
|
try {
|
||||||
switch (message.what) {
|
switch (message.what) {
|
||||||
case MSG_START_RENDERING:
|
case MSG_START_RENDERING:
|
||||||
playbackAudioGraphWrapper.startRendering();
|
startRenderingInternal();
|
||||||
break;
|
break;
|
||||||
case MSG_STOP_RENDERING:
|
case MSG_STOP_RENDERING:
|
||||||
playbackAudioGraphWrapper.stopRendering();
|
stopRenderingInternal();
|
||||||
break;
|
break;
|
||||||
case MSG_SET_VOLUME:
|
case MSG_SET_VOLUME:
|
||||||
playbackAudioGraphWrapper.setVolume(/* volume= */ (float) message.obj);
|
playbackAudioGraphWrapper.setVolume(/* volume= */ (float) message.obj);
|
||||||
@ -210,6 +210,16 @@ import androidx.media3.exoplayer.video.PlaybackVideoGraphWrapper;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void startRenderingInternal() {
|
||||||
|
playbackAudioGraphWrapper.startRendering();
|
||||||
|
playbackVideoGraphWrapper.startRendering();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void stopRenderingInternal() {
|
||||||
|
playbackAudioGraphWrapper.stopRendering();
|
||||||
|
playbackVideoGraphWrapper.stopRendering();
|
||||||
|
}
|
||||||
|
|
||||||
private void clearOutputSurfaceInternal() {
|
private void clearOutputSurfaceInternal() {
|
||||||
try {
|
try {
|
||||||
playbackVideoGraphWrapper.clearOutputSurfaceInfo();
|
playbackVideoGraphWrapper.clearOutputSurfaceInfo();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user