diff --git a/extensions/vp9/src/main/java/com/google/android/exoplayer2/ext/vp9/LibvpxVideoRenderer.java b/extensions/vp9/src/main/java/com/google/android/exoplayer2/ext/vp9/LibvpxVideoRenderer.java index e64a128a86..be4e358073 100644 --- a/extensions/vp9/src/main/java/com/google/android/exoplayer2/ext/vp9/LibvpxVideoRenderer.java +++ b/extensions/vp9/src/main/java/com/google/android/exoplayer2/ext/vp9/LibvpxVideoRenderer.java @@ -107,6 +107,7 @@ public class LibvpxVideoRenderer extends BaseRenderer { /** The default input buffer size. */ private static final int DEFAULT_INPUT_BUFFER_SIZE = 768 * 1024; // Value based on cs/SoftVpx.cpp. + private final boolean enableRowMultiThreadMode; private final boolean disableLoopFilter; private final long allowedJoiningTimeMs; private final int maxDroppedFramesToNotify; @@ -218,6 +219,7 @@ public class LibvpxVideoRenderer extends BaseRenderer { drmSessionManager, playClearSamplesWithoutKeys, disableLoopFilter, + /* enableRowMultiThreadMode= */ false, getRuntime().availableProcessors()); } @@ -237,6 +239,7 @@ public class LibvpxVideoRenderer extends BaseRenderer { * permitted to play clear regions of encrypted media files before {@code drmSessionManager} * has obtained the keys necessary to decrypt encrypted regions of the media. * @param disableLoopFilter Disable the libvpx in-loop smoothing filter. + * @param enableRowMultiThreadMode Whether row multi threading decoding is enabled. * @param threads Number of threads libvpx will use to decode. */ public LibvpxVideoRenderer( @@ -247,6 +250,7 @@ public class LibvpxVideoRenderer extends BaseRenderer { DrmSessionManager drmSessionManager, boolean playClearSamplesWithoutKeys, boolean disableLoopFilter, + boolean enableRowMultiThreadMode, int threads) { super(C.TRACK_TYPE_VIDEO); this.disableLoopFilter = disableLoopFilter; @@ -254,6 +258,7 @@ public class LibvpxVideoRenderer extends BaseRenderer { this.maxDroppedFramesToNotify = maxDroppedFramesToNotify; this.drmSessionManager = drmSessionManager; this.playClearSamplesWithoutKeys = playClearSamplesWithoutKeys; + this.enableRowMultiThreadMode = enableRowMultiThreadMode; this.threads = threads; joiningDeadlineMs = C.TIME_UNSET; clearReportedVideoSize(); @@ -762,6 +767,7 @@ public class LibvpxVideoRenderer extends BaseRenderer { initialInputBufferSize, mediaCrypto, disableLoopFilter, + enableRowMultiThreadMode, threads); decoder.setOutputMode(outputMode); TraceUtil.endSection(); diff --git a/extensions/vp9/src/main/java/com/google/android/exoplayer2/ext/vp9/VpxDecoder.java b/extensions/vp9/src/main/java/com/google/android/exoplayer2/ext/vp9/VpxDecoder.java index 33064af178..57e5481b55 100644 --- a/extensions/vp9/src/main/java/com/google/android/exoplayer2/ext/vp9/VpxDecoder.java +++ b/extensions/vp9/src/main/java/com/google/android/exoplayer2/ext/vp9/VpxDecoder.java @@ -51,6 +51,7 @@ import java.nio.ByteBuffer; * @param exoMediaCrypto The {@link ExoMediaCrypto} object required for decoding encrypted * content. Maybe null and can be ignored if decoder does not handle encrypted content. * @param disableLoopFilter Disable the libvpx in-loop smoothing filter. + * @param enableRowMultiThreadMode Whether row multi threading decoding is enabled. * @param threads Number of threads libvpx will use to decode. * @throws VpxDecoderException Thrown if an exception occurs when initializing the decoder. */ @@ -60,6 +61,7 @@ import java.nio.ByteBuffer; int initialInputBufferSize, ExoMediaCrypto exoMediaCrypto, boolean disableLoopFilter, + boolean enableRowMultiThreadMode, int threads) throws VpxDecoderException { super(new VpxInputBuffer[numInputBuffers], new VpxOutputBuffer[numOutputBuffers]); @@ -70,7 +72,7 @@ import java.nio.ByteBuffer; if (exoMediaCrypto != null && !VpxLibrary.vpxIsSecureDecodeSupported()) { throw new VpxDecoderException("Vpx decoder does not support secure decode."); } - vpxDecContext = vpxInit(disableLoopFilter, threads); + vpxDecContext = vpxInit(disableLoopFilter, enableRowMultiThreadMode, threads); if (vpxDecContext == 0) { throw new VpxDecoderException("Failed to initialize decoder"); } @@ -167,7 +169,8 @@ import java.nio.ByteBuffer; } } - private native long vpxInit(boolean disableLoopFilter, int threads); + private native long vpxInit( + boolean disableLoopFilter, boolean enableRowMultiThreadMode, int threads); private native long vpxClose(long context); private native long vpxDecode(long context, ByteBuffer encoded, int length); diff --git a/extensions/vp9/src/main/jni/vpx_jni.cc b/extensions/vp9/src/main/jni/vpx_jni.cc index 6ff86af355..8036e78cbe 100644 --- a/extensions/vp9/src/main/jni/vpx_jni.cc +++ b/extensions/vp9/src/main/jni/vpx_jni.cc @@ -433,7 +433,8 @@ int vpx_release_frame_buffer(void* priv, vpx_codec_frame_buffer_t* fb) { return buffer_manager->release(*(int*)fb->priv); } -DECODER_FUNC(jlong, vpxInit, jboolean disableLoopFilter, jint threads) { +DECODER_FUNC(jlong, vpxInit, jboolean disableLoopFilter, + jboolean enableRowMultiThreadMode, jint threads) { JniCtx* context = new JniCtx(); context->decoder = new vpx_codec_ctx_t(); vpx_codec_dec_cfg_t cfg = {0, 0, 0}; @@ -446,6 +447,13 @@ DECODER_FUNC(jlong, vpxInit, jboolean disableLoopFilter, jint threads) { errorCode = err; return 0; } +#ifdef VPX_CTRL_VP9_DECODE_SET_ROW_MT + err = vpx_codec_control_(context->decoder, VP9D_SET_ROW_MT, + enableRowMultiThreadMode); + if (err) { + LOGE("ERROR: Failed to enable row multi thread mode, error = %d.", err); + } +#endif if (disableLoopFilter) { // TODO(b/71930387): Use vpx_codec_control(), not vpx_codec_control_(). err = vpx_codec_control_(context->decoder, VP9_SET_SKIP_LOOP_FILTER, true);