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:
michaelkatz 2025-02-04 04:05:58 -08:00 committed by Copybara-Service
parent 1431497e7f
commit decfb9b0a9
8 changed files with 333 additions and 248 deletions

View File

@ -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;
}

View File

@ -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;

View File

@ -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();

View File

@ -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<>();

View File

@ -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

View File

@ -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

View File

@ -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();
}

View File

@ -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;