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
This commit is contained in:
Kacper Michajłow committed 2025-08-15 20:24:19 +02:00
1 parent fcb50a77bb
commit dbda70a11c
3 files changed
+24 -3

No files matched your search

+1
View File
@@ -0,0 +1 @@
add `--hwdec-threads`
+9
View File
@@ -1848,6 +1848,15 @@ Video
``mpv --hwdec=vdpau --hwdec-codecs=h264,mpeg2video``
Enable vdpau decoding for h264 and mpeg2 only.
``--hwdec-threads=<N>``
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=<yes|no|N>``
Fallback to software decoding if the hardware-accelerated decoder fails
(default: 3). If this is a number, then fallback will be triggered if
+14 -3
View File
@@ -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;