diff --git a/DOCS/interface-changes/hwdec-threads.txt b/DOCS/interface-changes/hwdec-threads.txt new file mode 100644 index 0000000000..6b5c93b3d0 --- /dev/null +++ b/DOCS/interface-changes/hwdec-threads.txt @@ -0,0 +1 @@ +add `--hwdec-threads` diff --git a/DOCS/man/options.rst b/DOCS/man/options.rst index c9c9dcfac6..d718baed62 100644 --- a/DOCS/man/options.rst +++ b/DOCS/man/options.rst @@ -1848,6 +1848,15 @@ Video ``mpv --hwdec=vdpau --hwdec-codecs=h264,mpeg2video`` Enable vdpau decoding for h264 and mpeg2 only. +``--hwdec-threads=`` + Number of threads used for hardware decoding (default: 4). This, as opposed + to vd-queue, enables frame and slice threading in libavcodec. It can help + with pipelining the decoding process and improve performance. The exact + behavior depends on the hardware decoder API used. + + If this is set to 0, the number of threads will be automatically determined + by the number of CPU cores available. + ``--hwdec-software-fallback=`` Fallback to software decoding if the hardware-accelerated decoder fails (default: 3). If this is a number, then fallback will be triggered if diff --git a/video/decode/vd_lavc.c b/video/decode/vd_lavc.c index a7c21548df..2bc9f6ef8c 100644 --- a/video/decode/vd_lavc.c +++ b/video/decode/vd_lavc.c @@ -140,6 +140,7 @@ struct hwdec_opts { char *hwdec_codecs; int hwdec_image_format; int hwdec_extra_frames; + int hwdec_threads; }; const struct m_sub_options hwdec_conf = { @@ -156,6 +157,7 @@ const struct m_sub_options hwdec_conf = { {"hwdec-software-fallback", OPT_CHOICE(software_fallback, {"no", INT_MAX}, {"yes", 1}), M_RANGE(1, INT_MAX), .flags = UPDATE_HWDEC}, + {"hwdec-threads", OPT_INT(hwdec_threads), M_RANGE(0, DBL_MAX)}, {"vd-lavc-software-fallback", OPT_REPLACED("hwdec-software-fallback")}, {0} }, @@ -169,6 +171,7 @@ const struct m_sub_options hwdec_conf = { // for example, if vo_gpu increases the number of reference surfaces for // interpolation, this value has to be increased too. .hwdec_extra_frames = 6, + .hwdec_threads = 4, }, }; @@ -741,9 +744,9 @@ static void init_avctx(struct mp_filter *vd) if (!ctx->avpkt) goto error; + int threads = lavc_param->threads; if (ctx->use_hwdec) { avctx->opaque = vd; - avctx->thread_count = 1; avctx->hwaccel_flags |= AV_HWACCEL_FLAG_IGNORE_LEVEL; if (!lavc_param->check_hw_profile) avctx->hwaccel_flags |= AV_HWACCEL_FLAG_ALLOW_PROFILE_MISMATCH; @@ -777,10 +780,18 @@ static void init_avctx(struct mp_filter *vd) if (ctx->hwdec.copying) ctx->max_delay_queue = HWDEC_DELAY_QUEUE_COUNT; ctx->hw_probing = true; - } else { - mp_set_avcodec_threads(vd->log, avctx, lavc_param->threads); + + threads = ctx->hwdec_opts->hwdec_threads; +#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(62, 11, 100) + // Vulkan threading was not safe before 62.11.100 + bstr hwdec_name = bstr0(ctx->hwdec.name); + if (bstr_endswith0(hwdec_name, "vulkan") || bstr_endswith0(hwdec_name, "vulkan-copy")) + threads = 1; +#endif } + mp_set_avcodec_threads(vd->log, avctx, threads); + if (!ctx->use_hwdec && ctx->vo && lavc_param->dr) { avctx->opaque = vd; avctx->get_buffer2 = get_buffer2_direct;