mirror of
https://github.com/androidx/media.git
synced 2025-04-29 22:36:54 +08:00
Refactor MediaCodecVideoRenderer to use a Builder
MediaCodecVideoRenderer is becoming unwieldy with the numerous constructors and optional settings. This refactors MediaCodecVideoRenderer to use a builder pattern for simplicity. PiperOrigin-RevId: 723022129
This commit is contained in:
parent
1431497e7f
commit
decfb9b0a9
@ -367,15 +367,15 @@ public class DefaultRenderersFactory implements RenderersFactory {
|
||||
long allowedVideoJoiningTimeMs,
|
||||
ArrayList<Renderer> out) {
|
||||
MediaCodecVideoRenderer videoRenderer =
|
||||
new MediaCodecVideoRenderer(
|
||||
context,
|
||||
getCodecAdapterFactory(),
|
||||
mediaCodecSelector,
|
||||
allowedVideoJoiningTimeMs,
|
||||
enableDecoderFallback,
|
||||
eventHandler,
|
||||
eventListener,
|
||||
MAX_DROPPED_VIDEO_FRAME_COUNT_TO_NOTIFY);
|
||||
new MediaCodecVideoRenderer.Builder(context)
|
||||
.setCodecAdapterFactory(getCodecAdapterFactory())
|
||||
.setMediaCodecSelector(mediaCodecSelector)
|
||||
.setAllowedJoiningTimeMs(allowedVideoJoiningTimeMs)
|
||||
.setEnableDecoderFallback(enableDecoderFallback)
|
||||
.setEventHandler(eventHandler)
|
||||
.setEventListener(eventListener)
|
||||
.setMaxDroppedFramesToNotify(MAX_DROPPED_VIDEO_FRAME_COUNT_TO_NOTIFY)
|
||||
.build();
|
||||
out.add(videoRenderer);
|
||||
|
||||
if (extensionRendererMode == EXTENSION_RENDERER_MODE_OFF) {
|
||||
@ -770,15 +770,15 @@ public class DefaultRenderersFactory implements RenderersFactory {
|
||||
long allowedVideoJoiningTimeMs) {
|
||||
if (enableMediaCodecVideoRendererPrewarming
|
||||
&& renderer.getClass() == MediaCodecVideoRenderer.class) {
|
||||
return new MediaCodecVideoRenderer(
|
||||
context,
|
||||
getCodecAdapterFactory(),
|
||||
mediaCodecSelector,
|
||||
allowedVideoJoiningTimeMs,
|
||||
enableDecoderFallback,
|
||||
eventHandler,
|
||||
eventListener,
|
||||
MAX_DROPPED_VIDEO_FRAME_COUNT_TO_NOTIFY);
|
||||
return new MediaCodecVideoRenderer.Builder(context)
|
||||
.setCodecAdapterFactory(getCodecAdapterFactory())
|
||||
.setMediaCodecSelector(mediaCodecSelector)
|
||||
.setAllowedJoiningTimeMs(allowedVideoJoiningTimeMs)
|
||||
.setEnableDecoderFallback(enableDecoderFallback)
|
||||
.setEventHandler(eventHandler)
|
||||
.setEventListener(eventListener)
|
||||
.setMaxDroppedFramesToNotify(MAX_DROPPED_VIDEO_FRAME_COUNT_TO_NOTIFY)
|
||||
.build();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -78,6 +78,7 @@ import androidx.media3.exoplayer.mediacodec.MediaCodecUtil.DecoderQueryException
|
||||
import androidx.media3.exoplayer.source.MediaSource;
|
||||
import androidx.media3.exoplayer.video.VideoRendererEventListener.EventDispatcher;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.errorprone.annotations.CanIgnoreReturnValue;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.List;
|
||||
import org.checkerframework.checker.initialization.qual.Initialized;
|
||||
@ -187,42 +188,168 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer
|
||||
private long periodDurationUs;
|
||||
private boolean pendingVideoSinkInputStreamChange;
|
||||
|
||||
/**
|
||||
* @param context A context.
|
||||
* @param mediaCodecSelector A decoder selector.
|
||||
*/
|
||||
public MediaCodecVideoRenderer(Context context, MediaCodecSelector mediaCodecSelector) {
|
||||
this(context, mediaCodecSelector, 0);
|
||||
/** A builder to create {@link MediaCodecVideoRenderer} instances. */
|
||||
public static final class Builder {
|
||||
private final Context context;
|
||||
private boolean buildCalled;
|
||||
private MediaCodecSelector mediaCodecSelector;
|
||||
private MediaCodecAdapter.Factory codecAdapterFactory;
|
||||
private long allowedJoiningTimeMs;
|
||||
private boolean enableDecoderFallback;
|
||||
@Nullable private Handler eventHandler;
|
||||
@Nullable private VideoRendererEventListener eventListener;
|
||||
private int maxDroppedFramesToNotify;
|
||||
private float assumedMinimumCodecOperatingRate;
|
||||
@Nullable private VideoSink videoSink;
|
||||
|
||||
/**
|
||||
* Creates a new builder.
|
||||
*
|
||||
* @param context A context.
|
||||
*/
|
||||
public Builder(Context context) {
|
||||
this.context = context;
|
||||
this.mediaCodecSelector = MediaCodecSelector.DEFAULT;
|
||||
this.codecAdapterFactory = MediaCodecAdapter.Factory.getDefault(context);
|
||||
this.assumedMinimumCodecOperatingRate = 30;
|
||||
}
|
||||
|
||||
/** Sets the {@link MediaCodecSelector decoder selector}. */
|
||||
@CanIgnoreReturnValue
|
||||
public Builder setMediaCodecSelector(MediaCodecSelector mediaCodecSelector) {
|
||||
this.mediaCodecSelector = mediaCodecSelector;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@link MediaCodecAdapter.Factory} used to create {@link MediaCodecAdapter}
|
||||
* instances.
|
||||
*/
|
||||
@CanIgnoreReturnValue
|
||||
public Builder setCodecAdapterFactory(MediaCodecAdapter.Factory codecAdapterFactory) {
|
||||
this.codecAdapterFactory = codecAdapterFactory;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the maximum duration in milliseconds for which this video renderer can attempt to
|
||||
* seamlessly join an ongoing playback.
|
||||
*/
|
||||
@CanIgnoreReturnValue
|
||||
public Builder setAllowedJoiningTimeMs(long allowedJoiningTimeMs) {
|
||||
this.allowedJoiningTimeMs = allowedJoiningTimeMs;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether to enable fallback to lower-priority decoders if decoder initialization fails.
|
||||
* This may result in using a decoder that is slower/less efficient than the primary decoder.
|
||||
*/
|
||||
@CanIgnoreReturnValue
|
||||
public Builder setEnableDecoderFallback(boolean enableDecoderFallback) {
|
||||
this.enableDecoderFallback = enableDecoderFallback;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a handler to use when delivering events to {@code eventListener}.
|
||||
*
|
||||
* <p>The {@link #setEventHandler event handler} and {@link #setEventListener event listener}
|
||||
* are linked in that both should be set to either {@code null} or non-{@code null} values.
|
||||
*/
|
||||
@CanIgnoreReturnValue
|
||||
public Builder setEventHandler(@Nullable Handler eventHandler) {
|
||||
this.eventHandler = eventHandler;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a listener for {@link VideoRendererEventListener} events.
|
||||
*
|
||||
* <p>The {@link #setEventHandler event handler} and {@link #setEventListener event listener}
|
||||
* are linked in that both should be set to either {@code null} or non-{@code null} values.
|
||||
*/
|
||||
@CanIgnoreReturnValue
|
||||
public Builder setEventListener(@Nullable VideoRendererEventListener eventListener) {
|
||||
this.eventListener = eventListener;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the maximum number of frames that can be dropped between invocations of {@link
|
||||
* VideoRendererEventListener#onDroppedFrames(int, long)}.
|
||||
*/
|
||||
@CanIgnoreReturnValue
|
||||
public Builder setMaxDroppedFramesToNotify(int maxDroppedFramesToNotify) {
|
||||
this.maxDroppedFramesToNotify = maxDroppedFramesToNotify;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a codec operating rate that all codecs instantiated by this renderer are assumed to meet
|
||||
* implicitly (i.e. without the operating rate being set explicitly using {@link
|
||||
* MediaFormat#KEY_OPERATING_RATE}).
|
||||
*/
|
||||
@CanIgnoreReturnValue
|
||||
public Builder setAssumedMinimumCodecOperatingRate(float assumedMinimumCodecOperatingRate) {
|
||||
this.assumedMinimumCodecOperatingRate = assumedMinimumCodecOperatingRate;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a {@link VideoSink} to consume the frames.
|
||||
*
|
||||
* <p>If a {@link VideoSink} is not set and effects are {@linkplain #MSG_SET_VIDEO_EFFECTS set},
|
||||
* a {@link VideoSink} produced by a {@link PlaybackVideoGraphWrapper} with its default
|
||||
* configuration will be used to apply effects and render the frames on the output.
|
||||
*/
|
||||
@CanIgnoreReturnValue
|
||||
public Builder setVideoSink(@Nullable VideoSink videoSink) {
|
||||
this.videoSink = videoSink;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the {@link MediaCodecVideoRenderer}. Must only be called once per Builder instance.
|
||||
*
|
||||
* <p>Throws {@link IllegalStateException} if the {@link #setEventHandler event handler} and the
|
||||
* {@link #setEventListener event listener} are neither both {@code null} nor both non-{@code
|
||||
* null}.
|
||||
*/
|
||||
public MediaCodecVideoRenderer build() {
|
||||
checkState(!buildCalled);
|
||||
checkState(
|
||||
(eventHandler == null && eventListener == null)
|
||||
|| (eventHandler != null && eventListener != null));
|
||||
buildCalled = true;
|
||||
return new MediaCodecVideoRenderer(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param context A context.
|
||||
* @param mediaCodecSelector A decoder selector.
|
||||
* @param allowedJoiningTimeMs The maximum duration in milliseconds for which this video renderer
|
||||
* can attempt to seamlessly join an ongoing playback.
|
||||
* @deprecated Use {@link Builder} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public MediaCodecVideoRenderer(Context context, MediaCodecSelector mediaCodecSelector) {
|
||||
this(new Builder(context).setMediaCodecSelector(mediaCodecSelector));
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link Builder} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public MediaCodecVideoRenderer(
|
||||
Context context, MediaCodecSelector mediaCodecSelector, long allowedJoiningTimeMs) {
|
||||
this(
|
||||
context,
|
||||
mediaCodecSelector,
|
||||
allowedJoiningTimeMs,
|
||||
/* eventHandler= */ null,
|
||||
/* eventListener= */ null,
|
||||
/* maxDroppedFramesToNotify= */ 0);
|
||||
new Builder(context)
|
||||
.setMediaCodecSelector(mediaCodecSelector)
|
||||
.setAllowedJoiningTimeMs(allowedJoiningTimeMs));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param context A context.
|
||||
* @param mediaCodecSelector A decoder selector.
|
||||
* @param allowedJoiningTimeMs The maximum duration in milliseconds for which this video renderer
|
||||
* can attempt to seamlessly join an ongoing playback.
|
||||
* @param eventHandler A handler to use when delivering events to {@code eventListener}. May be
|
||||
* null if delivery of events is not required.
|
||||
* @param eventListener A listener of events. May be null if delivery of events is not required.
|
||||
* @param maxDroppedFramesToNotify The maximum number of frames that can be dropped between
|
||||
* invocations of {@link VideoRendererEventListener#onDroppedFrames(int, long)}.
|
||||
* @deprecated Use {@link Builder} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public MediaCodecVideoRenderer(
|
||||
Context context,
|
||||
MediaCodecSelector mediaCodecSelector,
|
||||
@ -231,31 +358,18 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer
|
||||
@Nullable VideoRendererEventListener eventListener,
|
||||
int maxDroppedFramesToNotify) {
|
||||
this(
|
||||
context,
|
||||
MediaCodecAdapter.Factory.getDefault(context),
|
||||
mediaCodecSelector,
|
||||
allowedJoiningTimeMs,
|
||||
/* enableDecoderFallback= */ false,
|
||||
eventHandler,
|
||||
eventListener,
|
||||
maxDroppedFramesToNotify,
|
||||
/* assumedMinimumCodecOperatingRate= */ 30);
|
||||
new Builder(context)
|
||||
.setMediaCodecSelector(mediaCodecSelector)
|
||||
.setAllowedJoiningTimeMs(allowedJoiningTimeMs)
|
||||
.setEventHandler(eventHandler)
|
||||
.setEventListener(eventListener)
|
||||
.setMaxDroppedFramesToNotify(maxDroppedFramesToNotify));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param context A context.
|
||||
* @param mediaCodecSelector A decoder selector.
|
||||
* @param allowedJoiningTimeMs The maximum duration in milliseconds for which this video renderer
|
||||
* can attempt to seamlessly join an ongoing playback.
|
||||
* @param enableDecoderFallback Whether to enable fallback to lower-priority decoders if decoder
|
||||
* initialization fails. This may result in using a decoder that is slower/less efficient than
|
||||
* the primary decoder.
|
||||
* @param eventHandler A handler to use when delivering events to {@code eventListener}. May be
|
||||
* null if delivery of events is not required.
|
||||
* @param eventListener A listener of events. May be null if delivery of events is not required.
|
||||
* @param maxDroppedFramesToNotify The maximum number of frames that can be dropped between
|
||||
* invocations of {@link VideoRendererEventListener#onDroppedFrames(int, long)}.
|
||||
* @deprecated Use {@link Builder} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public MediaCodecVideoRenderer(
|
||||
Context context,
|
||||
MediaCodecSelector mediaCodecSelector,
|
||||
@ -265,33 +379,19 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer
|
||||
@Nullable VideoRendererEventListener eventListener,
|
||||
int maxDroppedFramesToNotify) {
|
||||
this(
|
||||
context,
|
||||
MediaCodecAdapter.Factory.getDefault(context),
|
||||
mediaCodecSelector,
|
||||
allowedJoiningTimeMs,
|
||||
enableDecoderFallback,
|
||||
eventHandler,
|
||||
eventListener,
|
||||
maxDroppedFramesToNotify,
|
||||
/* assumedMinimumCodecOperatingRate= */ 30);
|
||||
new Builder(context)
|
||||
.setMediaCodecSelector(mediaCodecSelector)
|
||||
.setAllowedJoiningTimeMs(allowedJoiningTimeMs)
|
||||
.setEnableDecoderFallback(enableDecoderFallback)
|
||||
.setEventHandler(eventHandler)
|
||||
.setEventListener(eventListener)
|
||||
.setMaxDroppedFramesToNotify(maxDroppedFramesToNotify));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param context A context.
|
||||
* @param codecAdapterFactory The {@link MediaCodecAdapter.Factory} used to create {@link
|
||||
* MediaCodecAdapter} instances.
|
||||
* @param mediaCodecSelector A decoder selector.
|
||||
* @param allowedJoiningTimeMs The maximum duration in milliseconds for which this video renderer
|
||||
* can attempt to seamlessly join an ongoing playback.
|
||||
* @param enableDecoderFallback Whether to enable fallback to lower-priority decoders if decoder
|
||||
* initialization fails. This may result in using a decoder that is slower/less efficient than
|
||||
* the primary decoder.
|
||||
* @param eventHandler A handler to use when delivering events to {@code eventListener}. May be
|
||||
* null if delivery of events is not required.
|
||||
* @param eventListener A listener of events. May be null if delivery of events is not required.
|
||||
* @param maxDroppedFramesToNotify The maximum number of frames that can be dropped between
|
||||
* invocations of {@link VideoRendererEventListener#onDroppedFrames(int, long)}.
|
||||
* @deprecated Use {@link Builder} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public MediaCodecVideoRenderer(
|
||||
Context context,
|
||||
MediaCodecAdapter.Factory codecAdapterFactory,
|
||||
@ -302,38 +402,20 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer
|
||||
@Nullable VideoRendererEventListener eventListener,
|
||||
int maxDroppedFramesToNotify) {
|
||||
this(
|
||||
context,
|
||||
codecAdapterFactory,
|
||||
mediaCodecSelector,
|
||||
allowedJoiningTimeMs,
|
||||
enableDecoderFallback,
|
||||
eventHandler,
|
||||
eventListener,
|
||||
maxDroppedFramesToNotify,
|
||||
/* assumedMinimumCodecOperatingRate= */ 30);
|
||||
new Builder(context)
|
||||
.setMediaCodecSelector(mediaCodecSelector)
|
||||
.setCodecAdapterFactory(codecAdapterFactory)
|
||||
.setAllowedJoiningTimeMs(allowedJoiningTimeMs)
|
||||
.setEnableDecoderFallback(enableDecoderFallback)
|
||||
.setEventHandler(eventHandler)
|
||||
.setEventListener(eventListener)
|
||||
.setMaxDroppedFramesToNotify(maxDroppedFramesToNotify));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*
|
||||
* @param context A context.
|
||||
* @param codecAdapterFactory The {@link MediaCodecAdapter.Factory} used to create {@link
|
||||
* MediaCodecAdapter} instances.
|
||||
* @param mediaCodecSelector A decoder selector.
|
||||
* @param allowedJoiningTimeMs The maximum duration in milliseconds for which this video renderer
|
||||
* can attempt to seamlessly join an ongoing playback.
|
||||
* @param enableDecoderFallback Whether to enable fallback to lower-priority decoders if decoder
|
||||
* initialization fails. This may result in using a decoder that is slower/less efficient than
|
||||
* the primary decoder.
|
||||
* @param eventHandler A handler to use when delivering events to {@code eventListener}. May be
|
||||
* null if delivery of events is not required.
|
||||
* @param eventListener A listener of events. May be null if delivery of events is not required.
|
||||
* @param maxDroppedFramesToNotify The maximum number of frames that can be dropped between
|
||||
* invocations of {@link VideoRendererEventListener#onDroppedFrames(int, long)}.
|
||||
* @param assumedMinimumCodecOperatingRate A codec operating rate that all codecs instantiated by
|
||||
* this renderer are assumed to meet implicitly (i.e. without the operating rate being set
|
||||
* explicitly using {@link MediaFormat#KEY_OPERATING_RATE}).
|
||||
* @deprecated Use {@link Builder} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public MediaCodecVideoRenderer(
|
||||
Context context,
|
||||
MediaCodecAdapter.Factory codecAdapterFactory,
|
||||
@ -345,22 +427,19 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer
|
||||
int maxDroppedFramesToNotify,
|
||||
float assumedMinimumCodecOperatingRate) {
|
||||
this(
|
||||
context,
|
||||
codecAdapterFactory,
|
||||
mediaCodecSelector,
|
||||
allowedJoiningTimeMs,
|
||||
enableDecoderFallback,
|
||||
eventHandler,
|
||||
eventListener,
|
||||
maxDroppedFramesToNotify,
|
||||
assumedMinimumCodecOperatingRate,
|
||||
/* videoSink= */ (VideoSink) null);
|
||||
new Builder(context)
|
||||
.setMediaCodecSelector(mediaCodecSelector)
|
||||
.setCodecAdapterFactory(codecAdapterFactory)
|
||||
.setAllowedJoiningTimeMs(allowedJoiningTimeMs)
|
||||
.setEnableDecoderFallback(enableDecoderFallback)
|
||||
.setEventHandler(eventHandler)
|
||||
.setEventListener(eventListener)
|
||||
.setMaxDroppedFramesToNotify(maxDroppedFramesToNotify)
|
||||
.setAssumedMinimumCodecOperatingRate(assumedMinimumCodecOperatingRate));
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #MediaCodecVideoRenderer(Context, MediaCodecAdapter.Factory,
|
||||
* MediaCodecSelector, long, boolean, Handler, VideoRendererEventListener, int, float,
|
||||
* VideoSink)} instead.
|
||||
* @deprecated Use {@link Builder} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public MediaCodecVideoRenderer(
|
||||
@ -375,45 +454,23 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer
|
||||
float assumedMinimumCodecOperatingRate,
|
||||
@Nullable VideoSinkProvider videoSinkProvider) {
|
||||
this(
|
||||
context,
|
||||
codecAdapterFactory,
|
||||
mediaCodecSelector,
|
||||
allowedJoiningTimeMs,
|
||||
enableDecoderFallback,
|
||||
eventHandler,
|
||||
eventListener,
|
||||
maxDroppedFramesToNotify,
|
||||
assumedMinimumCodecOperatingRate,
|
||||
/* videoSink= */ videoSinkProvider == null
|
||||
? null
|
||||
: videoSinkProvider.getSink(/* inputIndex= */ 0));
|
||||
new Builder(context)
|
||||
.setMediaCodecSelector(mediaCodecSelector)
|
||||
.setCodecAdapterFactory(codecAdapterFactory)
|
||||
.setAllowedJoiningTimeMs(allowedJoiningTimeMs)
|
||||
.setEnableDecoderFallback(enableDecoderFallback)
|
||||
.setEventHandler(eventHandler)
|
||||
.setEventListener(eventListener)
|
||||
.setMaxDroppedFramesToNotify(maxDroppedFramesToNotify)
|
||||
.setAssumedMinimumCodecOperatingRate(assumedMinimumCodecOperatingRate)
|
||||
.setVideoSink(
|
||||
videoSinkProvider == null ? null : videoSinkProvider.getSink(/* inputIndex= */ 0)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*
|
||||
* @param context A context.
|
||||
* @param codecAdapterFactory The {@link MediaCodecAdapter.Factory} used to create {@link
|
||||
* MediaCodecAdapter} instances.
|
||||
* @param mediaCodecSelector A decoder selector.
|
||||
* @param allowedJoiningTimeMs The maximum duration in milliseconds for which this video renderer
|
||||
* can attempt to seamlessly join an ongoing playback.
|
||||
* @param enableDecoderFallback Whether to enable fallback to lower-priority decoders if decoder
|
||||
* initialization fails. This may result in using a decoder that is slower/less efficient than
|
||||
* the primary decoder.
|
||||
* @param eventHandler A handler to use when delivering events to {@code eventListener}. May be
|
||||
* null if delivery of events is not required.
|
||||
* @param eventListener A listener of events. May be null if delivery of events is not required.
|
||||
* @param maxDroppedFramesToNotify The maximum number of frames that can be dropped between
|
||||
* invocations of {@link VideoRendererEventListener#onDroppedFrames(int, long)}.
|
||||
* @param assumedMinimumCodecOperatingRate A codec operating rate that all codecs instantiated by
|
||||
* this renderer are assumed to meet implicitly (i.e. without the operating rate being set
|
||||
* explicitly using {@link MediaFormat#KEY_OPERATING_RATE}).
|
||||
* @param videoSink The {@link VideoSink} consuming the frames. If {@code null} and effects are
|
||||
* {@linkplain #MSG_SET_VIDEO_EFFECTS set}, a {@link VideoSink} produced by a {@link
|
||||
* PlaybackVideoGraphWrapper} with its default configuration will be used to apply effects and
|
||||
* render the frames on the output.
|
||||
* @deprecated Use {@link Builder} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public MediaCodecVideoRenderer(
|
||||
Context context,
|
||||
MediaCodecAdapter.Factory codecAdapterFactory,
|
||||
@ -425,22 +482,39 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer
|
||||
int maxDroppedFramesToNotify,
|
||||
float assumedMinimumCodecOperatingRate,
|
||||
@Nullable VideoSink videoSink) {
|
||||
this(
|
||||
new Builder(context)
|
||||
.setMediaCodecSelector(mediaCodecSelector)
|
||||
.setCodecAdapterFactory(codecAdapterFactory)
|
||||
.setAllowedJoiningTimeMs(allowedJoiningTimeMs)
|
||||
.setEnableDecoderFallback(enableDecoderFallback)
|
||||
.setEventHandler(eventHandler)
|
||||
.setEventListener(eventListener)
|
||||
.setMaxDroppedFramesToNotify(maxDroppedFramesToNotify)
|
||||
.setAssumedMinimumCodecOperatingRate(assumedMinimumCodecOperatingRate)
|
||||
.setVideoSink(videoSink));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param builder The {@link Builder} containing construction parameters.
|
||||
*/
|
||||
protected MediaCodecVideoRenderer(Builder builder) {
|
||||
super(
|
||||
C.TRACK_TYPE_VIDEO,
|
||||
codecAdapterFactory,
|
||||
mediaCodecSelector,
|
||||
enableDecoderFallback,
|
||||
assumedMinimumCodecOperatingRate);
|
||||
this.context = context.getApplicationContext();
|
||||
this.maxDroppedFramesToNotify = maxDroppedFramesToNotify;
|
||||
this.videoSink = videoSink;
|
||||
eventDispatcher = new EventDispatcher(eventHandler, eventListener);
|
||||
builder.codecAdapterFactory,
|
||||
builder.mediaCodecSelector,
|
||||
builder.enableDecoderFallback,
|
||||
builder.assumedMinimumCodecOperatingRate);
|
||||
this.context = builder.context.getApplicationContext();
|
||||
this.maxDroppedFramesToNotify = builder.maxDroppedFramesToNotify;
|
||||
this.videoSink = builder.videoSink;
|
||||
eventDispatcher = new EventDispatcher(builder.eventHandler, builder.eventListener);
|
||||
ownsVideoSink = videoSink == null;
|
||||
@SuppressWarnings("nullness:assignment")
|
||||
VideoFrameReleaseControl.@Initialized FrameTimingEvaluator thisRef = this;
|
||||
videoFrameReleaseControl =
|
||||
new VideoFrameReleaseControl(
|
||||
this.context, /* frameTimingEvaluator= */ thisRef, allowedJoiningTimeMs);
|
||||
this.context, /* frameTimingEvaluator= */ thisRef, builder.allowedJoiningTimeMs);
|
||||
videoFrameReleaseInfo = new VideoFrameReleaseControl.FrameReleaseInfo();
|
||||
deviceNeedsNoPostProcessWorkaround = deviceNeedsNoPostProcessWorkaround();
|
||||
outputResolution = Size.UNKNOWN;
|
||||
|
@ -22,6 +22,7 @@ import static androidx.media3.test.utils.FakeSampleStream.FakeSampleStreamItem.f
|
||||
import static androidx.media3.test.utils.FakeSampleStream.FakeSampleStreamItem.oneByteSample;
|
||||
import static androidx.media3.test.utils.FakeTimeline.TimelineWindowDefinition.DEFAULT_WINDOW_OFFSET_IN_FIRST_PERIOD_US;
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static org.junit.Assert.assertThrows;
|
||||
import static org.mockito.ArgumentMatchers.anyLong;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.never;
|
||||
@ -175,23 +176,24 @@ public class MediaCodecVideoRendererTest {
|
||||
/* forceSecure= */ false));
|
||||
mediaCodecVideoRenderer =
|
||||
new MediaCodecVideoRenderer(
|
||||
ApplicationProvider.getApplicationContext(),
|
||||
new DefaultMediaCodecAdapterFactory(
|
||||
ApplicationProvider.getApplicationContext(),
|
||||
() -> {
|
||||
callbackThread = new HandlerThread("MCVRTest:MediaCodecAsyncAdapter");
|
||||
return callbackThread;
|
||||
},
|
||||
() -> {
|
||||
queueingThread = new HandlerThread("MCVRTest:MediaCodecQueueingThread");
|
||||
return queueingThread;
|
||||
}),
|
||||
mediaCodecSelector,
|
||||
/* allowedJoiningTimeMs= */ 0,
|
||||
/* enableDecoderFallback= */ false,
|
||||
/* eventHandler= */ new Handler(testMainLooper),
|
||||
/* eventListener= */ eventListener,
|
||||
/* maxDroppedFramesToNotify= */ 1) {
|
||||
new MediaCodecVideoRenderer.Builder(ApplicationProvider.getApplicationContext())
|
||||
.setCodecAdapterFactory(
|
||||
new DefaultMediaCodecAdapterFactory(
|
||||
ApplicationProvider.getApplicationContext(),
|
||||
() -> {
|
||||
callbackThread = new HandlerThread("MCVRTest:MediaCodecAsyncAdapter");
|
||||
return callbackThread;
|
||||
},
|
||||
() -> {
|
||||
queueingThread = new HandlerThread("MCVRTest:MediaCodecQueueingThread");
|
||||
return queueingThread;
|
||||
}))
|
||||
.setMediaCodecSelector(mediaCodecSelector)
|
||||
.setAllowedJoiningTimeMs(0)
|
||||
.setEnableDecoderFallback(false)
|
||||
.setEventHandler(new Handler(testMainLooper))
|
||||
.setEventListener(eventListener)
|
||||
.setMaxDroppedFramesToNotify(1)) {
|
||||
@Override
|
||||
protected @Capabilities int supportsFormat(
|
||||
MediaCodecSelector mediaCodecSelector, Format format) {
|
||||
@ -1336,13 +1338,13 @@ public class MediaCodecVideoRendererTest {
|
||||
}
|
||||
};
|
||||
MediaCodecVideoRenderer renderer =
|
||||
new MediaCodecVideoRenderer(
|
||||
ApplicationProvider.getApplicationContext(),
|
||||
mediaCodecSelector,
|
||||
/* allowedJoiningTimeMs= */ 0,
|
||||
/* eventHandler= */ new Handler(testMainLooper),
|
||||
/* eventListener= */ eventListener,
|
||||
/* maxDroppedFramesToNotify= */ 1);
|
||||
new MediaCodecVideoRenderer.Builder(ApplicationProvider.getApplicationContext())
|
||||
.setMediaCodecSelector(mediaCodecSelector)
|
||||
.setAllowedJoiningTimeMs(0)
|
||||
.setEventHandler(new Handler(testMainLooper))
|
||||
.setEventListener(eventListener)
|
||||
.setMaxDroppedFramesToNotify(1)
|
||||
.build();
|
||||
renderer.init(/* index= */ 0, PlayerId.UNSET, Clock.DEFAULT);
|
||||
|
||||
@Capabilities
|
||||
@ -1421,13 +1423,13 @@ public class MediaCodecVideoRendererTest {
|
||||
}
|
||||
};
|
||||
MediaCodecVideoRenderer renderer =
|
||||
new MediaCodecVideoRenderer(
|
||||
ApplicationProvider.getApplicationContext(),
|
||||
mediaCodecSelector,
|
||||
/* allowedJoiningTimeMs= */ 0,
|
||||
/* eventHandler= */ new Handler(testMainLooper),
|
||||
/* eventListener= */ eventListener,
|
||||
/* maxDroppedFramesToNotify= */ 1);
|
||||
new MediaCodecVideoRenderer.Builder(ApplicationProvider.getApplicationContext())
|
||||
.setMediaCodecSelector(mediaCodecSelector)
|
||||
.setAllowedJoiningTimeMs(0)
|
||||
.setEventHandler(new Handler(testMainLooper))
|
||||
.setEventListener(eventListener)
|
||||
.setMaxDroppedFramesToNotify(1)
|
||||
.build();
|
||||
renderer.init(/* index= */ 0, PlayerId.UNSET, Clock.DEFAULT);
|
||||
|
||||
@Capabilities int capabilitiesDvheDtr = renderer.supportsFormat(formatDvheDtr);
|
||||
@ -1481,13 +1483,13 @@ public class MediaCodecVideoRendererTest {
|
||||
H264_PROFILE8_LEVEL4_HW_MEDIA_CODEC_INFO, H264_PROFILE8_LEVEL5_SW_MEDIA_CODEC_INFO);
|
||||
};
|
||||
MediaCodecVideoRenderer renderer =
|
||||
new MediaCodecVideoRenderer(
|
||||
ApplicationProvider.getApplicationContext(),
|
||||
mediaCodecSelector,
|
||||
/* allowedJoiningTimeMs= */ 0,
|
||||
/* eventHandler= */ new Handler(testMainLooper),
|
||||
/* eventListener= */ eventListener,
|
||||
/* maxDroppedFramesToNotify= */ 1);
|
||||
new MediaCodecVideoRenderer.Builder(ApplicationProvider.getApplicationContext())
|
||||
.setMediaCodecSelector(mediaCodecSelector)
|
||||
.setAllowedJoiningTimeMs(0)
|
||||
.setEventHandler(new Handler(testMainLooper))
|
||||
.setEventListener(eventListener)
|
||||
.setMaxDroppedFramesToNotify(1)
|
||||
.build();
|
||||
renderer.init(/* index= */ 0, PlayerId.UNSET, Clock.DEFAULT);
|
||||
|
||||
List<MediaCodecInfo> mediaCodecInfoList =
|
||||
@ -1524,13 +1526,13 @@ public class MediaCodecVideoRendererTest {
|
||||
H264_PROFILE8_LEVEL5_SW_MEDIA_CODEC_INFO, H264_PROFILE8_LEVEL4_HW_MEDIA_CODEC_INFO);
|
||||
};
|
||||
MediaCodecVideoRenderer renderer =
|
||||
new MediaCodecVideoRenderer(
|
||||
ApplicationProvider.getApplicationContext(),
|
||||
mediaCodecSelector,
|
||||
/* allowedJoiningTimeMs= */ 0,
|
||||
/* eventHandler= */ new Handler(testMainLooper),
|
||||
/* eventListener= */ eventListener,
|
||||
/* maxDroppedFramesToNotify= */ 1);
|
||||
new MediaCodecVideoRenderer.Builder(ApplicationProvider.getApplicationContext())
|
||||
.setMediaCodecSelector(mediaCodecSelector)
|
||||
.setAllowedJoiningTimeMs(0)
|
||||
.setEventHandler(new Handler(testMainLooper))
|
||||
.setEventListener(eventListener)
|
||||
.setMaxDroppedFramesToNotify(1)
|
||||
.build();
|
||||
renderer.init(/* index= */ 0, PlayerId.UNSET, Clock.DEFAULT);
|
||||
|
||||
List<MediaCodecInfo> mediaCodecInfoList =
|
||||
@ -1609,6 +1611,15 @@ public class MediaCodecVideoRendererTest {
|
||||
assertThat(surfacesSet).containsExactly(newSurface);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void build_calledTwice_throwsIllegalStateException() throws Exception {
|
||||
MediaCodecVideoRenderer.Builder mediaCodecVideoRendererBuilder =
|
||||
new MediaCodecVideoRenderer.Builder(ApplicationProvider.getApplicationContext());
|
||||
mediaCodecVideoRendererBuilder.build();
|
||||
|
||||
assertThrows(IllegalStateException.class, mediaCodecVideoRendererBuilder::build);
|
||||
}
|
||||
|
||||
private void maybeIdleAsynchronousMediaCodecAdapterThreads() {
|
||||
if (queueingThread != null) {
|
||||
shadowOf(queueingThread.getLooper()).idle();
|
||||
|
@ -104,12 +104,12 @@ import java.util.ArrayList;
|
||||
VideoRendererEventListener eventListener,
|
||||
int maxDroppedFrameCountToNotify) {
|
||||
super(
|
||||
context,
|
||||
mediaCodecSelector,
|
||||
allowedJoiningTimeMs,
|
||||
eventHandler,
|
||||
eventListener,
|
||||
maxDroppedFrameCountToNotify);
|
||||
new Builder(context)
|
||||
.setMediaCodecSelector(mediaCodecSelector)
|
||||
.setAllowedJoiningTimeMs(allowedJoiningTimeMs)
|
||||
.setEventHandler(eventHandler)
|
||||
.setEventListener(eventListener)
|
||||
.setMaxDroppedFramesToNotify(maxDroppedFrameCountToNotify));
|
||||
timestampsList = new long[ARRAY_SIZE];
|
||||
inputFormatChangeTimesUs = new ArrayDeque<>();
|
||||
|
||||
|
@ -205,14 +205,14 @@ public class CapturingRenderersFactory implements RenderersFactory, Dumper.Dumpa
|
||||
@Nullable VideoRendererEventListener eventListener,
|
||||
int maxDroppedFramesToNotify) {
|
||||
super(
|
||||
context,
|
||||
codecAdapterFactory,
|
||||
mediaCodecSelector,
|
||||
allowedJoiningTimeMs,
|
||||
enableDecoderFallback,
|
||||
eventHandler,
|
||||
eventListener,
|
||||
maxDroppedFramesToNotify);
|
||||
new Builder(context)
|
||||
.setCodecAdapterFactory(codecAdapterFactory)
|
||||
.setMediaCodecSelector(mediaCodecSelector)
|
||||
.setAllowedJoiningTimeMs(allowedJoiningTimeMs)
|
||||
.setEnableDecoderFallback(enableDecoderFallback)
|
||||
.setEventHandler(eventHandler)
|
||||
.setEventListener(eventListener)
|
||||
.setMaxDroppedFramesToNotify(maxDroppedFramesToNotify));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -431,7 +431,7 @@ public class EffectPlaybackPixelTest {
|
||||
private static class NoFrameDroppedVideoRenderer extends MediaCodecVideoRenderer {
|
||||
|
||||
public NoFrameDroppedVideoRenderer(Context context, MediaCodecSelector mediaCodecSelector) {
|
||||
super(context, mediaCodecSelector);
|
||||
super(new Builder(context).setMediaCodecSelector(mediaCodecSelector));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -640,12 +640,12 @@ public final class ExperimentalFrameExtractor {
|
||||
VideoRendererEventListener videoRendererEventListener,
|
||||
boolean toneMapHdrToSdr) {
|
||||
super(
|
||||
context,
|
||||
mediaCodecSelector,
|
||||
/* allowedJoiningTimeMs= */ 0,
|
||||
Util.createHandlerForCurrentOrMainLooper(),
|
||||
videoRendererEventListener,
|
||||
/* maxDroppedFramesToNotify= */ 0);
|
||||
new Builder(context)
|
||||
.setMediaCodecSelector(mediaCodecSelector)
|
||||
.setAllowedJoiningTimeMs(0)
|
||||
.setEventHandler(Util.createHandlerForCurrentOrMainLooper())
|
||||
.setEventListener(videoRendererEventListener)
|
||||
.setMaxDroppedFramesToNotify(0));
|
||||
this.toneMapHdrToSdr = toneMapHdrToSdr;
|
||||
effectsFromPlayer = ImmutableList.of();
|
||||
}
|
||||
|
@ -282,16 +282,16 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||
VideoSink videoSink,
|
||||
boolean requestToneMapping) {
|
||||
super(
|
||||
context,
|
||||
MediaCodecAdapter.Factory.getDefault(context),
|
||||
MediaCodecSelector.DEFAULT,
|
||||
DEFAULT_ALLOWED_VIDEO_JOINING_TIME_MS,
|
||||
/* enableDecoderFallback= */ false,
|
||||
eventHandler,
|
||||
videoRendererEventListener,
|
||||
MAX_DROPPED_VIDEO_FRAME_COUNT_TO_NOTIFY,
|
||||
/* assumedMinimumCodecOperatingRate= */ DEFAULT_FRAME_RATE,
|
||||
videoSink);
|
||||
new Builder(context)
|
||||
.setMediaCodecSelector(MediaCodecSelector.DEFAULT)
|
||||
.setCodecAdapterFactory(MediaCodecAdapter.Factory.getDefault(context))
|
||||
.setAllowedJoiningTimeMs(DEFAULT_ALLOWED_VIDEO_JOINING_TIME_MS)
|
||||
.setEnableDecoderFallback(false)
|
||||
.setEventHandler(eventHandler)
|
||||
.setEventListener(videoRendererEventListener)
|
||||
.setMaxDroppedFramesToNotify(MAX_DROPPED_VIDEO_FRAME_COUNT_TO_NOTIFY)
|
||||
.setAssumedMinimumCodecOperatingRate(DEFAULT_FRAME_RATE)
|
||||
.setVideoSink(videoSink));
|
||||
this.sequence = sequence;
|
||||
this.videoSink = videoSink;
|
||||
this.requestToneMapping = requestToneMapping;
|
||||
|
Loading…
x
Reference in New Issue
Block a user