Commit 05c5fe23 by huangdarwin Committed by Tofunmi Adigun-Hameed

ExoPlayer: Add setVideoFrameProcessorFactory().

This allows apps to use a custom VideoFrameProcessor implementation for video
playback. This may be useful, for example, when outputting to a texture.

PiperOrigin-RevId: 534044831
(cherry picked from commit 703923d196934fdcc019ffd610b6f778f8fa043d)
parent a80b1675
...@@ -61,6 +61,7 @@ import com.google.android.exoplayer2.util.Clock; ...@@ -61,6 +61,7 @@ import com.google.android.exoplayer2.util.Clock;
import com.google.android.exoplayer2.util.Effect; import com.google.android.exoplayer2.util.Effect;
import com.google.android.exoplayer2.util.PriorityTaskManager; import com.google.android.exoplayer2.util.PriorityTaskManager;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
import com.google.android.exoplayer2.util.VideoFrameProcessor;
import com.google.android.exoplayer2.video.MediaCodecVideoRenderer; import com.google.android.exoplayer2.video.MediaCodecVideoRenderer;
import com.google.android.exoplayer2.video.VideoFrameMetadataListener; import com.google.android.exoplayer2.video.VideoFrameMetadataListener;
import com.google.android.exoplayer2.video.VideoSize; import com.google.android.exoplayer2.video.VideoSize;
...@@ -1488,6 +1489,18 @@ public interface ExoPlayer extends Player { ...@@ -1488,6 +1489,18 @@ public interface ExoPlayer extends Player {
void setVideoEffects(List<Effect> videoEffects); void setVideoEffects(List<Effect> videoEffects);
/** /**
* Sets a {@link VideoFrameProcessor.Factory} to create the {@link VideoFrameProcessor} that
* applies video effects set in {@link #setVideoEffects}.
*
* <p>See {@link #setVideoEffects} for limitations.
*
* @param videoFrameProcessorFactory The {@link VideoFrameProcessor.Factory} to use to apply the
* video effects.
*/
@RequiresApi(18)
void setVideoFrameProcessorFactory(VideoFrameProcessor.Factory videoFrameProcessorFactory);
/**
* Sets the {@link C.VideoScalingMode}. * Sets the {@link C.VideoScalingMode}.
* *
* <p>The scaling mode only applies if a {@link MediaCodec}-based video {@link Renderer} is * <p>The scaling mode only applies if a {@link MediaCodec}-based video {@link Renderer} is
......
...@@ -28,6 +28,7 @@ import static com.google.android.exoplayer2.Renderer.MSG_SET_SCALING_MODE; ...@@ -28,6 +28,7 @@ import static com.google.android.exoplayer2.Renderer.MSG_SET_SCALING_MODE;
import static com.google.android.exoplayer2.Renderer.MSG_SET_SKIP_SILENCE_ENABLED; import static com.google.android.exoplayer2.Renderer.MSG_SET_SKIP_SILENCE_ENABLED;
import static com.google.android.exoplayer2.Renderer.MSG_SET_VIDEO_EFFECTS; import static com.google.android.exoplayer2.Renderer.MSG_SET_VIDEO_EFFECTS;
import static com.google.android.exoplayer2.Renderer.MSG_SET_VIDEO_FRAME_METADATA_LISTENER; import static com.google.android.exoplayer2.Renderer.MSG_SET_VIDEO_FRAME_METADATA_LISTENER;
import static com.google.android.exoplayer2.Renderer.MSG_SET_VIDEO_FRAME_PROCESSOR_FACTORY;
import static com.google.android.exoplayer2.Renderer.MSG_SET_VIDEO_OUTPUT; import static com.google.android.exoplayer2.Renderer.MSG_SET_VIDEO_OUTPUT;
import static com.google.android.exoplayer2.Renderer.MSG_SET_VIDEO_OUTPUT_RESOLUTION; import static com.google.android.exoplayer2.Renderer.MSG_SET_VIDEO_OUTPUT_RESOLUTION;
import static com.google.android.exoplayer2.Renderer.MSG_SET_VOLUME; import static com.google.android.exoplayer2.Renderer.MSG_SET_VOLUME;
...@@ -94,6 +95,7 @@ import com.google.android.exoplayer2.util.Log; ...@@ -94,6 +95,7 @@ import com.google.android.exoplayer2.util.Log;
import com.google.android.exoplayer2.util.PriorityTaskManager; import com.google.android.exoplayer2.util.PriorityTaskManager;
import com.google.android.exoplayer2.util.Size; import com.google.android.exoplayer2.util.Size;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
import com.google.android.exoplayer2.util.VideoFrameProcessor;
import com.google.android.exoplayer2.video.VideoDecoderOutputBufferRenderer; import com.google.android.exoplayer2.video.VideoDecoderOutputBufferRenderer;
import com.google.android.exoplayer2.video.VideoFrameMetadataListener; import com.google.android.exoplayer2.video.VideoFrameMetadataListener;
import com.google.android.exoplayer2.video.VideoRendererEventListener; import com.google.android.exoplayer2.video.VideoRendererEventListener;
...@@ -1228,6 +1230,14 @@ import java.util.concurrent.TimeoutException; ...@@ -1228,6 +1230,14 @@ import java.util.concurrent.TimeoutException;
} }
@Override @Override
public void setVideoFrameProcessorFactory(
VideoFrameProcessor.Factory videoFrameProcessorFactory) {
verifyApplicationThread();
sendRendererMessage(
TRACK_TYPE_VIDEO, MSG_SET_VIDEO_FRAME_PROCESSOR_FACTORY, videoFrameProcessorFactory);
}
@Override
public void setVideoScalingMode(@C.VideoScalingMode int videoScalingMode) { public void setVideoScalingMode(@C.VideoScalingMode int videoScalingMode) {
verifyApplicationThread(); verifyApplicationThread();
this.videoScalingMode = videoScalingMode; this.videoScalingMode = videoScalingMode;
......
...@@ -29,6 +29,7 @@ import com.google.android.exoplayer2.util.Effect; ...@@ -29,6 +29,7 @@ import com.google.android.exoplayer2.util.Effect;
import com.google.android.exoplayer2.util.MediaClock; import com.google.android.exoplayer2.util.MediaClock;
import com.google.android.exoplayer2.util.Size; import com.google.android.exoplayer2.util.Size;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
import com.google.android.exoplayer2.util.VideoFrameProcessor;
import com.google.android.exoplayer2.video.VideoDecoderOutputBufferRenderer; import com.google.android.exoplayer2.video.VideoDecoderOutputBufferRenderer;
import com.google.android.exoplayer2.video.VideoFrameMetadataListener; import com.google.android.exoplayer2.video.VideoFrameMetadataListener;
import com.google.android.exoplayer2.video.spherical.CameraMotionListener; import com.google.android.exoplayer2.video.spherical.CameraMotionListener;
...@@ -86,9 +87,9 @@ public interface Renderer extends PlayerMessage.Target { ...@@ -86,9 +87,9 @@ public interface Renderer extends PlayerMessage.Target {
* #MSG_SET_SCALING_MODE}, {@link #MSG_SET_CHANGE_FRAME_RATE_STRATEGY}, {@link * #MSG_SET_SCALING_MODE}, {@link #MSG_SET_CHANGE_FRAME_RATE_STRATEGY}, {@link
* #MSG_SET_AUX_EFFECT_INFO}, {@link #MSG_SET_VIDEO_FRAME_METADATA_LISTENER}, {@link * #MSG_SET_AUX_EFFECT_INFO}, {@link #MSG_SET_VIDEO_FRAME_METADATA_LISTENER}, {@link
* #MSG_SET_CAMERA_MOTION_LISTENER}, {@link #MSG_SET_SKIP_SILENCE_ENABLED}, {@link * #MSG_SET_CAMERA_MOTION_LISTENER}, {@link #MSG_SET_SKIP_SILENCE_ENABLED}, {@link
* #MSG_SET_AUDIO_SESSION_ID}, {@link #MSG_SET_WAKEUP_LISTENER}, {@link #MSG_SET_VIDEO_EFFECTS} or * #MSG_SET_AUDIO_SESSION_ID}, {@link #MSG_SET_WAKEUP_LISTENER}, {@link #MSG_SET_VIDEO_EFFECTS},
* {@link #MSG_SET_VIDEO_OUTPUT_RESOLUTION}. May also be an app-defined value (see {@link * {@link #MSG_SET_VIDEO_FRAME_PROCESSOR_FACTORY} or {@link #MSG_SET_VIDEO_OUTPUT_RESOLUTION}. May
* #MSG_CUSTOM_BASE}). * also be an app-defined value (see {@link #MSG_CUSTOM_BASE}).
*/ */
@Documented @Documented
@Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE)
...@@ -108,6 +109,7 @@ public interface Renderer extends PlayerMessage.Target { ...@@ -108,6 +109,7 @@ public interface Renderer extends PlayerMessage.Target {
MSG_SET_AUDIO_SESSION_ID, MSG_SET_AUDIO_SESSION_ID,
MSG_SET_WAKEUP_LISTENER, MSG_SET_WAKEUP_LISTENER,
MSG_SET_VIDEO_EFFECTS, MSG_SET_VIDEO_EFFECTS,
MSG_SET_VIDEO_FRAME_PROCESSOR_FACTORY,
MSG_SET_VIDEO_OUTPUT_RESOLUTION MSG_SET_VIDEO_OUTPUT_RESOLUTION
}) })
public @interface MessageType {} public @interface MessageType {}
...@@ -216,11 +218,16 @@ public interface Renderer extends PlayerMessage.Target { ...@@ -216,11 +218,16 @@ public interface Renderer extends PlayerMessage.Target {
*/ */
int MSG_SET_VIDEO_EFFECTS = 13; int MSG_SET_VIDEO_EFFECTS = 13;
/** /**
* The type of a message that can be passed to a video renderer. The message payload should be a
* {@link VideoFrameProcessor.Factory}.
*/
int MSG_SET_VIDEO_FRAME_PROCESSOR_FACTORY = 14;
/**
* The type of a message that can be passed to a video renderer to set the desired output * The type of a message that can be passed to a video renderer to set the desired output
* resolution. The message payload should be a {@link Size} of the desired output width and * resolution. The message payload should be a {@link Size} of the desired output width and
* height. Use this method only when playing with video {@linkplain Effect effects}. * height. Use this method only when playing with video {@linkplain Effect effects}.
*/ */
int MSG_SET_VIDEO_OUTPUT_RESOLUTION = 14; int MSG_SET_VIDEO_OUTPUT_RESOLUTION = 15;
/** /**
* Applications or extensions may define custom {@code MSG_*} constants that can be passed to * Applications or extensions may define custom {@code MSG_*} constants that can be passed to
* renderers. These custom constants must be greater than or equal to this value. * renderers. These custom constants must be greater than or equal to this value.
......
...@@ -48,6 +48,7 @@ import com.google.android.exoplayer2.util.ConditionVariable; ...@@ -48,6 +48,7 @@ import com.google.android.exoplayer2.util.ConditionVariable;
import com.google.android.exoplayer2.util.Effect; import com.google.android.exoplayer2.util.Effect;
import com.google.android.exoplayer2.util.PriorityTaskManager; import com.google.android.exoplayer2.util.PriorityTaskManager;
import com.google.android.exoplayer2.util.Size; import com.google.android.exoplayer2.util.Size;
import com.google.android.exoplayer2.util.VideoFrameProcessor;
import com.google.android.exoplayer2.video.VideoFrameMetadataListener; import com.google.android.exoplayer2.video.VideoFrameMetadataListener;
import com.google.android.exoplayer2.video.VideoSize; import com.google.android.exoplayer2.video.VideoSize;
import com.google.android.exoplayer2.video.spherical.CameraMotionListener; import com.google.android.exoplayer2.video.spherical.CameraMotionListener;
...@@ -661,6 +662,13 @@ public class SimpleExoPlayer extends BasePlayer ...@@ -661,6 +662,13 @@ public class SimpleExoPlayer extends BasePlayer
} }
@Override @Override
public void setVideoFrameProcessorFactory(
VideoFrameProcessor.Factory videoFrameProcessorFactory) {
blockUntilConstructorFinished();
player.setVideoFrameProcessorFactory(videoFrameProcessorFactory);
}
@Override
public void setSkipSilenceEnabled(boolean skipSilenceEnabled) { public void setSkipSilenceEnabled(boolean skipSilenceEnabled) {
blockUntilConstructorFinished(); blockUntilConstructorFinished();
player.setSkipSilenceEnabled(skipSilenceEnabled); player.setSkipSilenceEnabled(skipSilenceEnabled);
......
...@@ -683,6 +683,11 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer { ...@@ -683,6 +683,11 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
List<Effect> videoEffects = (List<Effect>) checkNotNull(message); List<Effect> videoEffects = (List<Effect>) checkNotNull(message);
videoFrameProcessorManager.setVideoEffects(videoEffects); videoFrameProcessorManager.setVideoEffects(videoEffects);
break; break;
case MSG_SET_VIDEO_FRAME_PROCESSOR_FACTORY:
VideoFrameProcessor.Factory videoFrameProcessorFactory =
(VideoFrameProcessor.Factory) checkNotNull(message);
videoFrameProcessorManager.setVideoFrameProcessorFactory(videoFrameProcessorFactory);
break;
case MSG_SET_VIDEO_OUTPUT_RESOLUTION: case MSG_SET_VIDEO_OUTPUT_RESOLUTION:
Size outputResolution = (Size) checkNotNull(message); Size outputResolution = (Size) checkNotNull(message);
if (outputResolution.getWidth() != 0 if (outputResolution.getWidth() != 0
...@@ -1872,6 +1877,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer { ...@@ -1872,6 +1877,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
private final ArrayDeque<Pair<Long, Format>> pendingFrameFormats; private final ArrayDeque<Pair<Long, Format>> pendingFrameFormats;
private @MonotonicNonNull Handler handler; private @MonotonicNonNull Handler handler;
private VideoFrameProcessor.@MonotonicNonNull Factory videoFrameProcessorFactory;
@Nullable private VideoFrameProcessor videoFrameProcessor; @Nullable private VideoFrameProcessor videoFrameProcessor;
@Nullable private CopyOnWriteArrayList<Effect> videoEffects; @Nullable private CopyOnWriteArrayList<Effect> videoEffects;
@Nullable private Format inputFormat; @Nullable private Format inputFormat;
...@@ -1933,6 +1939,12 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer { ...@@ -1933,6 +1939,12 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
this.videoEffects.addAll(videoEffects); this.videoEffects.addAll(videoEffects);
} }
/** Sets the {@link VideoFrameProcessor.Factory}. */
public void setVideoFrameProcessorFactory(
VideoFrameProcessor.Factory videoFrameProcessorFactory) {
this.videoFrameProcessorFactory = videoFrameProcessorFactory;
}
/** Returns whether video frame processing is enabled. */ /** Returns whether video frame processing is enabled. */
public boolean isEnabled() { public boolean isEnabled() {
return videoFrameProcessor != null; return videoFrameProcessor != null;
...@@ -2005,9 +2017,12 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer { ...@@ -2005,9 +2017,12 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
VideoFrameProcessorAccessor.createRotationEffect(inputFormat.rotationDegrees)); VideoFrameProcessorAccessor.createRotationEffect(inputFormat.rotationDegrees));
} }
videoFrameProcessorFactory =
videoFrameProcessorFactory == null
? VideoFrameProcessorAccessor.getFrameProcessorFactory()
: videoFrameProcessorFactory;
videoFrameProcessor = videoFrameProcessor =
VideoFrameProcessorAccessor.getFrameProcessorFactory() videoFrameProcessorFactory.create(
.create(
renderer.context, renderer.context,
checkNotNull(videoEffects), checkNotNull(videoEffects),
DebugViewProvider.NONE, DebugViewProvider.NONE,
......
...@@ -38,6 +38,7 @@ import com.google.android.exoplayer2.trackselection.TrackSelector; ...@@ -38,6 +38,7 @@ import com.google.android.exoplayer2.trackselection.TrackSelector;
import com.google.android.exoplayer2.util.Clock; import com.google.android.exoplayer2.util.Clock;
import com.google.android.exoplayer2.util.Effect; import com.google.android.exoplayer2.util.Effect;
import com.google.android.exoplayer2.util.PriorityTaskManager; import com.google.android.exoplayer2.util.PriorityTaskManager;
import com.google.android.exoplayer2.util.VideoFrameProcessor;
import com.google.android.exoplayer2.video.VideoFrameMetadataListener; import com.google.android.exoplayer2.video.VideoFrameMetadataListener;
import com.google.android.exoplayer2.video.spherical.CameraMotionListener; import com.google.android.exoplayer2.video.spherical.CameraMotionListener;
import java.util.List; import java.util.List;
...@@ -248,6 +249,12 @@ public class StubExoPlayer extends StubPlayer implements ExoPlayer { ...@@ -248,6 +249,12 @@ public class StubExoPlayer extends StubPlayer implements ExoPlayer {
} }
@Override @Override
public void setVideoFrameProcessorFactory(
VideoFrameProcessor.Factory videoFrameProcessorFactory) {
throw new UnsupportedOperationException();
}
@Override
public void setVideoScalingMode(int videoScalingMode) { public void setVideoScalingMode(int videoScalingMode) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment