From dbda70a11c213e7eb07c8fc8a491f5b01d20914b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kacper=20Michaj=C5=82ow?= Date: Sat, 26 Jul 2025 19:37:52 +0200 Subject: [PATCH] vd_lavc: add `--hwdec-threads` No reason to not enable threads if lavc supports them, same as for software decoding. Might help with pipelining of decoding and filtering. Performance difference may vary, but in my testing everything is working as expected and I didn't notice any regressions. Set to 2 threads by default as conservative value that should resolve stalling issue, while also not spawn too many cpu threads, which won't help with hwdec anyway and only can cause too deep queue of hardware surfaces. Fixes: #16578 --- DOCS/interface-changes/hwdec-threads.txt | 1 + DOCS/man/options.rst | 9 +++++++++ video/decode/vd_lavc.c | 17 ++++++++++++++--- 3 files changed, 24 insertions(+), 3 deletions(-) create mode 100644 DOCS/interface-changes/hwdec-threads.txt 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;