diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 793a5bacef..c880d831e8 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -3,6 +3,10 @@ ### dev-v2 (not yet released) * Core Library: + * Enable MediaCodec asynchronous queueing by default on devices with API + level >= 31. Add methods in `DefaultMediaCodecRendererFactory` and + `DefaultRenderersFactory` to force enable or force disable asynchronous + queueing ([6348](https://github.com/google/ExoPlayer/issues/6348)). * Move `com.google.android.exoplayer2.device.DeviceInfo` to `com.google.android.exoplayer2.DeviceInfo`. * Move `com.google.android.exoplayer2.drm.DecryptionException` to @@ -13,8 +17,8 @@ `GlUtil.glAssertionsEnabled` instead. * Move `Player.addListener(EventListener)` and `Player.removeListener(EventListener)` out of `Player` into subclasses. - * Fix `mediaMetadata` being reset when media is - repeated ([#9458](https://github.com/google/ExoPlayer/issues/9458)). + * Fix `mediaMetadata` being reset when media is repeated + ([#9458](https://github.com/google/ExoPlayer/issues/9458)). * Video: * Fix bug in `MediaCodecVideoRenderer` that resulted in re-using a released `Surface` when playing without an app-provided `Surface` diff --git a/library/core/src/main/java/com/google/android/exoplayer2/DefaultRenderersFactory.java b/library/core/src/main/java/com/google/android/exoplayer2/DefaultRenderersFactory.java index d4284842df..03ccc297a8 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/DefaultRenderersFactory.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/DefaultRenderersFactory.java @@ -28,6 +28,7 @@ import com.google.android.exoplayer2.audio.AudioSink; import com.google.android.exoplayer2.audio.DefaultAudioSink; import com.google.android.exoplayer2.audio.DefaultAudioSink.DefaultAudioProcessorChain; import com.google.android.exoplayer2.audio.MediaCodecAudioRenderer; +import com.google.android.exoplayer2.mediacodec.DefaultMediaCodecAdapterFactory; import com.google.android.exoplayer2.mediacodec.MediaCodecSelector; import com.google.android.exoplayer2.metadata.MetadataOutput; import com.google.android.exoplayer2.metadata.MetadataRenderer; @@ -87,13 +88,11 @@ public class DefaultRenderersFactory implements RenderersFactory { private static final String TAG = "DefaultRenderersFactory"; private final Context context; + private final DefaultMediaCodecAdapterFactory codecAdapterFactory; @ExtensionRendererMode private int extensionRendererMode; private long allowedVideoJoiningTimeMs; private boolean enableDecoderFallback; private MediaCodecSelector mediaCodecSelector; - private boolean enableAsyncQueueing; - private boolean forceAsyncQueueingSynchronizationWorkaround; - private boolean enableSynchronizeCodecInteractionsWithQueueing; private boolean enableFloatOutput; private boolean enableAudioTrackPlaybackParams; private boolean enableOffload; @@ -101,6 +100,7 @@ public class DefaultRenderersFactory implements RenderersFactory { /** @param context A {@link Context}. */ public DefaultRenderersFactory(Context context) { this.context = context; + codecAdapterFactory = new DefaultMediaCodecAdapterFactory(); extensionRendererMode = EXTENSION_RENDERER_MODE_OFF; allowedVideoJoiningTimeMs = DEFAULT_ALLOWED_VIDEO_JOINING_TIME_MS; mediaCodecSelector = MediaCodecSelector.DEFAULT; @@ -130,6 +130,7 @@ public class DefaultRenderersFactory implements RenderersFactory { this.extensionRendererMode = extensionRendererMode; this.allowedVideoJoiningTimeMs = allowedVideoJoiningTimeMs; mediaCodecSelector = MediaCodecSelector.DEFAULT; + codecAdapterFactory = new DefaultMediaCodecAdapterFactory(); } /** @@ -149,34 +150,28 @@ public class DefaultRenderersFactory implements RenderersFactory { } /** - * Enable asynchronous buffer queueing for both {@link MediaCodecAudioRenderer} and {@link - * MediaCodecVideoRenderer} instances. + * Enables {@link com.google.android.exoplayer2.mediacodec.MediaCodecRenderer} instances to + * operate their {@link MediaCodec} in asynchronous mode and perform asynchronous queueing. * - *

This method is experimental, and will be renamed or removed in a future release. + *

This feature can be enabled only on devices with API versions >= 23. For devices with + * older API versions, this method is a no-op. * - * @param enabled Whether asynchronous queueing is enabled. * @return This factory, for convenience. */ - public DefaultRenderersFactory experimentalSetAsynchronousBufferQueueingEnabled(boolean enabled) { - enableAsyncQueueing = enabled; + public DefaultRenderersFactory forceEnableMediaCodecAsynchronousQueueing() { + codecAdapterFactory.forceEnableAsynchronous(); return this; } /** - * Enable the asynchronous queueing synchronization workaround. + * Disables {@link com.google.android.exoplayer2.mediacodec.MediaCodecRenderer} instances from + * operating their {@link MediaCodec} in asynchronous mode and perform asynchronous queueing. + * {@link MediaCodec} instances will be operated synchronous mode. * - *

When enabled, the queueing threads for {@link MediaCodec} instances will synchronize on a - * shared lock when submitting buffers to the respective {@link MediaCodec}. - * - *

This method is experimental, and will be renamed or removed in a future release. - * - * @param enabled Whether the asynchronous queueing synchronization workaround is enabled by - * default. * @return This factory, for convenience. */ - public DefaultRenderersFactory experimentalSetForceAsyncQueueingSynchronizationWorkaround( - boolean enabled) { - this.forceAsyncQueueingSynchronizationWorkaround = enabled; + public DefaultRenderersFactory forceDisableMediaCodecAsynchronousQueueing() { + codecAdapterFactory.forceDisableAsynchronous(); return this; } @@ -191,7 +186,7 @@ public class DefaultRenderersFactory implements RenderersFactory { */ public DefaultRenderersFactory experimentalSetSynchronizeCodecInteractionsWithQueueingEnabled( boolean enabled) { - enableSynchronizeCodecInteractionsWithQueueing = enabled; + codecAdapterFactory.experimentalSetSynchronizeCodecInteractionsWithQueueingEnabled(enabled); return this; } @@ -373,17 +368,13 @@ public class DefaultRenderersFactory implements RenderersFactory { MediaCodecVideoRenderer videoRenderer = new MediaCodecVideoRenderer( context, + codecAdapterFactory, mediaCodecSelector, allowedVideoJoiningTimeMs, enableDecoderFallback, eventHandler, eventListener, MAX_DROPPED_VIDEO_FRAME_COUNT_TO_NOTIFY); - videoRenderer.experimentalSetAsynchronousBufferQueueingEnabled(enableAsyncQueueing); - videoRenderer.experimentalSetForceAsyncQueueingSynchronizationWorkaround( - forceAsyncQueueingSynchronizationWorkaround); - videoRenderer.experimentalSetSynchronizeCodecInteractionsWithQueueingEnabled( - enableSynchronizeCodecInteractionsWithQueueing); out.add(videoRenderer); if (extensionRendererMode == EXTENSION_RENDERER_MODE_OFF) { @@ -497,16 +488,12 @@ public class DefaultRenderersFactory implements RenderersFactory { MediaCodecAudioRenderer audioRenderer = new MediaCodecAudioRenderer( context, + codecAdapterFactory, mediaCodecSelector, enableDecoderFallback, eventHandler, eventListener, audioSink); - audioRenderer.experimentalSetAsynchronousBufferQueueingEnabled(enableAsyncQueueing); - audioRenderer.experimentalSetForceAsyncQueueingSynchronizationWorkaround( - forceAsyncQueueingSynchronizationWorkaround); - audioRenderer.experimentalSetSynchronizeCodecInteractionsWithQueueingEnabled( - enableSynchronizeCodecInteractionsWithQueueing); out.add(audioRenderer); if (extensionRendererMode == EXTENSION_RENDERER_MODE_OFF) { diff --git a/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/AsynchronousMediaCodecAdapter.java b/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/AsynchronousMediaCodecAdapter.java index 5832144f5a..8302bd2903 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/AsynchronousMediaCodecAdapter.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/AsynchronousMediaCodecAdapter.java @@ -49,15 +49,11 @@ import java.nio.ByteBuffer; public static final class Factory implements MediaCodecAdapter.Factory { private final Supplier callbackThreadSupplier; private final Supplier queueingThreadSupplier; - private final boolean forceQueueingSynchronizationWorkaround; private final boolean synchronizeCodecInteractionsWithQueueing; /** Creates a factory for codecs handling the specified {@link C.TrackType track type}. */ public Factory(@C.TrackType int trackType) { - this( - trackType, - /* forceQueueingSynchronizationWorkaround= */ false, - /* synchronizeCodecInteractionsWithQueueing= */ false); + this(trackType, /* synchronizeCodecInteractionsWithQueueing= */ false); } /** @@ -65,23 +61,17 @@ import java.nio.ByteBuffer; * * @param trackType One of {@link C#TRACK_TYPE_AUDIO} or {@link C#TRACK_TYPE_VIDEO}. Used for * labelling the internal thread accordingly. - * @param forceQueueingSynchronizationWorkaround Whether the queueing synchronization workaround - * will be enabled by default or only for the predefined devices. * @param synchronizeCodecInteractionsWithQueueing Whether the adapter should synchronize {@link * MediaCodec} interactions with asynchronous buffer queueing. When {@code true}, codec * interactions will wait until all input buffers pending queueing wil be submitted to the * {@link MediaCodec}. */ - public Factory( - @C.TrackType int trackType, - boolean forceQueueingSynchronizationWorkaround, - boolean synchronizeCodecInteractionsWithQueueing) { + public Factory(@C.TrackType int trackType, boolean synchronizeCodecInteractionsWithQueueing) { this( /* callbackThreadSupplier= */ () -> new HandlerThread(createCallbackThreadLabel(trackType)), /* queueingThreadSupplier= */ () -> new HandlerThread(createQueueingThreadLabel(trackType)), - forceQueueingSynchronizationWorkaround, synchronizeCodecInteractionsWithQueueing); } @@ -89,11 +79,9 @@ import java.nio.ByteBuffer; /* package */ Factory( Supplier callbackThreadSupplier, Supplier queueingThreadSupplier, - boolean forceQueueingSynchronizationWorkaround, boolean synchronizeCodecInteractionsWithQueueing) { this.callbackThreadSupplier = callbackThreadSupplier; this.queueingThreadSupplier = queueingThreadSupplier; - this.forceQueueingSynchronizationWorkaround = forceQueueingSynchronizationWorkaround; this.synchronizeCodecInteractionsWithQueueing = synchronizeCodecInteractionsWithQueueing; } @@ -111,7 +99,6 @@ import java.nio.ByteBuffer; codec, callbackThreadSupplier.get(), queueingThreadSupplier.get(), - forceQueueingSynchronizationWorkaround, synchronizeCodecInteractionsWithQueueing); TraceUtil.endSection(); codecAdapter.initialize( @@ -153,13 +140,10 @@ import java.nio.ByteBuffer; MediaCodec codec, HandlerThread callbackThread, HandlerThread enqueueingThread, - boolean forceQueueingSynchronizationWorkaround, boolean synchronizeCodecInteractionsWithQueueing) { this.codec = codec; this.asynchronousMediaCodecCallback = new AsynchronousMediaCodecCallback(callbackThread); - this.bufferEnqueuer = - new AsynchronousMediaCodecBufferEnqueuer( - codec, enqueueingThread, forceQueueingSynchronizationWorkaround); + this.bufferEnqueuer = new AsynchronousMediaCodecBufferEnqueuer(codec, enqueueingThread); this.synchronizeCodecInteractionsWithQueueing = synchronizeCodecInteractionsWithQueueing; this.state = STATE_CREATED; } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/AsynchronousMediaCodecBufferEnqueuer.java b/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/AsynchronousMediaCodecBufferEnqueuer.java index 8a2bb9a9bc..1605c669e7 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/AsynchronousMediaCodecBufferEnqueuer.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/AsynchronousMediaCodecBufferEnqueuer.java @@ -30,7 +30,6 @@ import androidx.annotation.VisibleForTesting; import com.google.android.exoplayer2.decoder.CryptoInfo; import com.google.android.exoplayer2.util.ConditionVariable; import com.google.android.exoplayer2.util.Util; -import com.google.common.base.Ascii; import java.util.ArrayDeque; import java.util.Arrays; import java.util.concurrent.atomic.AtomicReference; @@ -60,7 +59,6 @@ class AsynchronousMediaCodecBufferEnqueuer { private @MonotonicNonNull Handler handler; private final AtomicReference<@NullableType RuntimeException> pendingRuntimeException; private final ConditionVariable conditionVariable; - private final boolean needsSynchronizationWorkaround; private boolean started; /** @@ -69,29 +67,17 @@ class AsynchronousMediaCodecBufferEnqueuer { * @param codec The {@link MediaCodec} to submit input buffers to. * @param queueingThread The {@link HandlerThread} to use for queueing buffers. */ - public AsynchronousMediaCodecBufferEnqueuer( - MediaCodec codec, - HandlerThread queueingThread, - boolean forceQueueingSynchronizationWorkaround) { - this( - codec, - queueingThread, - forceQueueingSynchronizationWorkaround, - /* conditionVariable= */ new ConditionVariable()); + public AsynchronousMediaCodecBufferEnqueuer(MediaCodec codec, HandlerThread queueingThread) { + this(codec, queueingThread, /* conditionVariable= */ new ConditionVariable()); } @VisibleForTesting /* package */ AsynchronousMediaCodecBufferEnqueuer( - MediaCodec codec, - HandlerThread handlerThread, - boolean forceQueueingSynchronizationWorkaround, - ConditionVariable conditionVariable) { + MediaCodec codec, HandlerThread handlerThread, ConditionVariable conditionVariable) { this.codec = codec; this.handlerThread = handlerThread; this.conditionVariable = conditionVariable; pendingRuntimeException = new AtomicReference<>(); - needsSynchronizationWorkaround = - forceQueueingSynchronizationWorkaround || needsSynchronizationWorkaround(); } /** @@ -247,11 +233,10 @@ class AsynchronousMediaCodecBufferEnqueuer { private void doQueueSecureInputBuffer( int index, int offset, MediaCodec.CryptoInfo info, long presentationTimeUs, int flags) { try { - if (needsSynchronizationWorkaround) { - synchronized (QUEUE_SECURE_LOCK) { - codec.queueSecureInputBuffer(index, offset, info, presentationTimeUs, flags); - } - } else { + // Synchronize calls to MediaCodec.queueSecureInputBuffer() to avoid race conditions inside + // the crypto module when audio and video are sharing the same DRM session + // (see [Internal: b/149908061]). + synchronized (QUEUE_SECURE_LOCK) { codec.queueSecureInputBuffer(index, offset, info, presentationTimeUs, flags); } } catch (RuntimeException e) { @@ -299,15 +284,6 @@ class AsynchronousMediaCodecBufferEnqueuer { } } - /** - * Returns whether this device needs the synchronization workaround when queueing secure input - * buffers (see [Internal: b/149908061]). - */ - private static boolean needsSynchronizationWorkaround() { - String manufacturer = Ascii.toLowerCase(Util.MANUFACTURER); - return manufacturer.contains("samsung") || manufacturer.contains("motorola"); - } - /** Performs a deep copy of {@code cryptoInfo} to {@code frameworkCryptoInfo}. */ private static void copy( CryptoInfo cryptoInfo, android.media.MediaCodec.CryptoInfo frameworkCryptoInfo) { diff --git a/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/DefaultMediaCodecAdapterFactory.java b/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/DefaultMediaCodecAdapterFactory.java new file mode 100644 index 0000000000..f371d92598 --- /dev/null +++ b/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/DefaultMediaCodecAdapterFactory.java @@ -0,0 +1,105 @@ +/* + * Copyright 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.android.exoplayer2.mediacodec; + +import androidx.annotation.IntDef; +import com.google.android.exoplayer2.util.Log; +import com.google.android.exoplayer2.util.MimeTypes; +import com.google.android.exoplayer2.util.Util; +import java.io.IOException; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * The default {@link MediaCodecAdapter.Factory}. + * + *

By default, this factory {@link #createAdapter creates} {@link AsynchronousMediaCodecAdapter} + * instances on devices with API level >= 31 (Android 12+). For devices with older API versions, + * the default behavior is to create {@link SynchronousMediaCodecAdapter} instances. The factory + * offers APIs to force the creation of {@link AsynchronousMediaCodecAdapter} (applicable for + * devices with API >= 23) or {@link SynchronousMediaCodecAdapter} instances. + */ +public final class DefaultMediaCodecAdapterFactory implements MediaCodecAdapter.Factory { + + @Retention(RetentionPolicy.SOURCE) + @IntDef({MODE_DEFAULT, MODE_ENABLED, MODE_DISABLED}) + private @interface Mode {} + + private static final int MODE_DEFAULT = 0; + private static final int MODE_ENABLED = 1; + private static final int MODE_DISABLED = 2; + + private static final String TAG = "DefaultMediaCodecAdapterFactory"; + + @Mode private int asynchronousMode; + private boolean enableSynchronizeCodecInteractionsWithQueueing; + + public DefaultMediaCodecAdapterFactory() { + asynchronousMode = MODE_DEFAULT; + } + + /** + * Forces this factory to always create {@link AsynchronousMediaCodecAdapter} instances, provided + * the device API level is >= 23. For devices with API level < 23, the factory will create + * {@link SynchronousMediaCodecAdapter SynchronousMediaCodecAdapters}. + * + * @return This factory, for convenience. + */ + public DefaultMediaCodecAdapterFactory forceEnableAsynchronous() { + asynchronousMode = MODE_ENABLED; + return this; + } + + /** + * Forces the factory to always create {@link SynchronousMediaCodecAdapter} instances. + * + * @return This factory, for convenience. + */ + public DefaultMediaCodecAdapterFactory forceDisableAsynchronous() { + asynchronousMode = MODE_DISABLED; + return this; + } + + /** + * Enable synchronizing codec interactions with asynchronous buffer queueing. + * + *

This method is experimental, and will be renamed or removed in a future release. + * + * @param enabled Whether codec interactions will be synchronized with asynchronous buffer + * queueing. + */ + public void experimentalSetSynchronizeCodecInteractionsWithQueueingEnabled(boolean enabled) { + enableSynchronizeCodecInteractionsWithQueueing = enabled; + } + + @Override + public MediaCodecAdapter createAdapter(MediaCodecAdapter.Configuration configuration) + throws IOException { + if ((asynchronousMode == MODE_ENABLED && Util.SDK_INT >= 23) + || (asynchronousMode == MODE_DEFAULT && Util.SDK_INT >= 31)) { + int trackType = MimeTypes.getTrackType(configuration.format.sampleMimeType); + Log.i( + TAG, + "Creating an asynchronous MediaCodec adapter for track type " + + Util.getTrackTypeString(trackType)); + AsynchronousMediaCodecAdapter.Factory factory = + new AsynchronousMediaCodecAdapter.Factory( + trackType, enableSynchronizeCodecInteractionsWithQueueing); + return factory.createAdapter(configuration); + } + return new SynchronousMediaCodecAdapter.Factory().createAdapter(configuration); + } +} diff --git a/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecAdapter.java b/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecAdapter.java index 2353baf516..ffd7758680 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecAdapter.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecAdapter.java @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.google.android.exoplayer2.mediacodec; import android.media.MediaCodec; @@ -179,7 +178,7 @@ public interface MediaCodecAdapter { interface Factory { /** Default factory used in most cases. */ - Factory DEFAULT = new SynchronousMediaCodecAdapter.Factory(); + Factory DEFAULT = new DefaultMediaCodecAdapterFactory(); /** Creates a {@link MediaCodecAdapter} instance. */ MediaCodecAdapter createAdapter(Configuration configuration) throws IOException; diff --git a/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecRenderer.java b/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecRenderer.java index 0836102ae6..389e675c59 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecRenderer.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecRenderer.java @@ -350,9 +350,6 @@ public abstract class MediaCodecRenderer extends BaseRenderer { private boolean outputStreamEnded; private boolean waitingForFirstSampleInFormat; private boolean pendingOutputEndOfStream; - private boolean enableAsynchronousBufferQueueing; - private boolean forceAsyncQueueingSynchronizationWorkaround; - private boolean enableSynchronizeCodecInteractionsWithQueueing; @Nullable private ExoPlaybackException pendingPlaybackException; protected DecoderCounters decoderCounters; private long outputStreamStartPositionUs; @@ -428,46 +425,6 @@ public abstract class MediaCodecRenderer extends BaseRenderer { this.renderTimeLimitMs = renderTimeLimitMs; } - /** - * Enables asynchronous input buffer queueing. - * - *

Operates the underlying {@link MediaCodec} in asynchronous mode and submits input buffers - * from a separate thread to unblock the playback thread. - * - *

This method is experimental, and will be renamed or removed in a future release. It should - * only be called before the renderer is used. - */ - public void experimentalSetAsynchronousBufferQueueingEnabled(boolean enabled) { - enableAsynchronousBufferQueueing = enabled; - } - - /** - * Enables the asynchronous queueing synchronization workaround. - * - *

When enabled, the queueing threads for {@link MediaCodec} instance will synchronize on a - * shared lock when submitting buffers to the respective {@link MediaCodec}. - * - *

This method is experimental, and will be renamed or removed in a future release. It should - * only be called before the renderer is used. - */ - public void experimentalSetForceAsyncQueueingSynchronizationWorkaround(boolean enabled) { - this.forceAsyncQueueingSynchronizationWorkaround = enabled; - } - - /** - * Enables synchronizing codec interactions with asynchronous buffer queueing. - * - *

When enabled, codec interactions will wait until all input buffers pending for asynchronous - * queueing are submitted to the {@link MediaCodec} first. This method is effective only if {@link - * #experimentalSetAsynchronousBufferQueueingEnabled asynchronous buffer queueing} is enabled. - * - *

This method is experimental, and will be renamed or removed in a future release. It should - * only be called before the renderer is used. - */ - public void experimentalSetSynchronizeCodecInteractionsWithQueueingEnabled(boolean enabled) { - enableSynchronizeCodecInteractionsWithQueueing = enabled; - } - @Override @AdaptiveSupport public final int supportsMixedMimeTypeAdaptation() { @@ -520,7 +477,6 @@ public abstract class MediaCodecRenderer extends BaseRenderer { * no codec operating rate should be set. * @return The parameters needed to call {@link MediaCodec#configure}. */ - @Nullable protected abstract MediaCodecAdapter.Configuration getMediaCodecConfiguration( MediaCodecInfo codecInfo, Format format, @@ -1092,7 +1048,6 @@ public abstract class MediaCodecRenderer extends BaseRenderer { private void initCodec(MediaCodecInfo codecInfo, MediaCrypto crypto) throws Exception { long codecInitializingTimestamp; long codecInitializedTimestamp; - @Nullable MediaCodecAdapter codecAdapter = null; String codecName = codecInfo.name; float codecOperatingRate = Util.SDK_INT < 23 @@ -1105,19 +1060,9 @@ public abstract class MediaCodecRenderer extends BaseRenderer { TraceUtil.beginSection("createCodec:" + codecName); MediaCodecAdapter.Configuration configuration = getMediaCodecConfiguration(codecInfo, inputFormat, crypto, codecOperatingRate); - if (enableAsynchronousBufferQueueing && Util.SDK_INT >= 23) { - codecAdapter = - new AsynchronousMediaCodecAdapter.Factory( - getTrackType(), - forceAsyncQueueingSynchronizationWorkaround, - enableSynchronizeCodecInteractionsWithQueueing) - .createAdapter(configuration); - } else { - codecAdapter = codecAdapterFactory.createAdapter(configuration); - } + codec = codecAdapterFactory.createAdapter(configuration); codecInitializedTimestamp = SystemClock.elapsedRealtime(); - this.codec = codecAdapter; this.codecInfo = codecInfo; this.codecOperatingRate = codecOperatingRate; codecInputFormat = inputFormat; @@ -1133,7 +1078,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer { codecNeedsMonoChannelCountWorkaround(codecName, codecInputFormat); codecNeedsEosPropagation = codecNeedsEosPropagationWorkaround(codecInfo) || getCodecNeedsEosPropagation(); - if (codecAdapter.needsReconfiguration()) { + if (codec.needsReconfiguration()) { this.codecReconfigured = true; this.codecReconfigurationState = RECONFIGURATION_STATE_WRITE_PENDING; this.codecNeedsAdaptationWorkaroundBuffer = diff --git a/library/core/src/test/java/com/google/android/exoplayer2/mediacodec/AsynchronousMediaCodecAdapterTest.java b/library/core/src/test/java/com/google/android/exoplayer2/mediacodec/AsynchronousMediaCodecAdapterTest.java index 94410ab11f..9aa2b5f3ba 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/mediacodec/AsynchronousMediaCodecAdapterTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/mediacodec/AsynchronousMediaCodecAdapterTest.java @@ -54,7 +54,6 @@ public class AsynchronousMediaCodecAdapterTest { new AsynchronousMediaCodecAdapter.Factory( /* callbackThreadSupplier= */ () -> callbackThread, /* queueingThreadSupplier= */ () -> queueingThread, - /* forceQueueingSynchronizationWorkaround= */ false, /* synchronizeCodecInteractionsWithQueueing= */ false) .createAdapter(configuration); bufferInfo = new MediaCodec.BufferInfo(); diff --git a/library/core/src/test/java/com/google/android/exoplayer2/mediacodec/AsynchronousMediaCodecBufferEnqueuerTest.java b/library/core/src/test/java/com/google/android/exoplayer2/mediacodec/AsynchronousMediaCodecBufferEnqueuerTest.java index e5fdd126f4..f3a08df819 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/mediacodec/AsynchronousMediaCodecBufferEnqueuerTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/mediacodec/AsynchronousMediaCodecBufferEnqueuerTest.java @@ -56,11 +56,7 @@ public class AsynchronousMediaCodecBufferEnqueuerTest { codec.start(); handlerThread = new TestHandlerThread("TestHandlerThread"); enqueuer = - new AsynchronousMediaCodecBufferEnqueuer( - codec, - handlerThread, - /* forceQueueingSynchronizationWorkaround= */ false, - mockConditionVariable); + new AsynchronousMediaCodecBufferEnqueuer(codec, handlerThread, mockConditionVariable); } @After