By default the SDK creates a thread for each CPU when creating a mfx session for decoding / encoding, which results in CPU overhead on a multi CPU system. Actually creating 2 threads is a better choice for most cases in practice.
This patch allows user to specify the number of threads created for a mfx session via option -threads. If the number is not specified, 2 threads will be created by default. Note the SDK requires at least 2 threads to avoid dead locks[1] [1]https://github.com/Intel-Media-SDK/MediaSDK/blob/master/_studio/mfx_lib/scheduler/linux/src/mfx_scheduler_core_ischeduler.cpp#L90-L93 --- libavcodec/qsv.c | 32 ++++++++++++++++++++++++++++++++ libavcodec/qsvdec.c | 1 + libavcodec/qsvenc_h264.c | 2 +- libavcodec/qsvenc_hevc.c | 2 +- libavcodec/qsvenc_jpeg.c | 1 + libavcodec/qsvenc_mpeg2.c | 2 +- libavcodec/qsvenc_vp9.c | 2 +- 7 files changed, 38 insertions(+), 4 deletions(-) diff --git a/libavcodec/qsv.c b/libavcodec/qsv.c index 6e3154e1a3..c725883c5c 100644 --- a/libavcodec/qsv.c +++ b/libavcodec/qsv.c @@ -390,11 +390,27 @@ int ff_qsv_init_internal_session(AVCodecContext *avctx, QSVSession *qs, const char *desc; int ret; +#if QSV_VERSION_ATLEAST(1, 15) + mfxExtBuffer *ext_params[1]; + mfxExtThreadsParam thread_param; +#endif + #if QSV_VERSION_ATLEAST(1, 16) init_par.GPUCopy = gpu_copy; #endif init_par.Implementation = impl; init_par.Version = ver; + +#if QSV_VERSION_ATLEAST(1, 15) + memset(&thread_param, 0, sizeof(thread_param)); + thread_param.Header.BufferId = MFX_EXTBUFF_THREADS_PARAM; + thread_param.Header.BufferSz = sizeof(thread_param); + thread_param.NumThread = FFMAX(2, avctx->thread_count); + ext_params[0] = (mfxExtBuffer *)&thread_param; + init_par.ExtParam = (mfxExtBuffer **)&ext_params; + init_par.NumExtParam = 1; +#endif + ret = MFXInitEx(init_par, &qs->session); if (ret < 0) return ff_qsv_print_error(avctx, ret, @@ -709,6 +725,11 @@ int ff_qsv_init_session_device(AVCodecContext *avctx, mfxSession *psession, int i, ret; +#if QSV_VERSION_ATLEAST(1, 15) + mfxExtBuffer *ext_params[1]; + mfxExtThreadsParam thread_param; +#endif + err = MFXQueryIMPL(parent_session, &impl); if (err == MFX_ERR_NONE) err = MFXQueryVersion(parent_session, &ver); @@ -734,6 +755,17 @@ int ff_qsv_init_session_device(AVCodecContext *avctx, mfxSession *psession, #endif init_par.Implementation = impl; init_par.Version = ver; + +#if QSV_VERSION_ATLEAST(1, 15) + memset(&thread_param, 0, sizeof(thread_param)); + thread_param.Header.BufferId = MFX_EXTBUFF_THREADS_PARAM; + thread_param.Header.BufferSz = sizeof(thread_param); + thread_param.NumThread = FFMAX(2, avctx->thread_count); + ext_params[0] = (mfxExtBuffer *)&thread_param; + init_par.ExtParam = (mfxExtBuffer **)&ext_params; + init_par.NumExtParam = 1; +#endif + err = MFXInitEx(init_par, &session); if (err != MFX_ERR_NONE) return ff_qsv_print_error(avctx, err, diff --git a/libavcodec/qsvdec.c b/libavcodec/qsvdec.c index 5f2e641373..d3365b6f3b 100644 --- a/libavcodec/qsvdec.c +++ b/libavcodec/qsvdec.c @@ -846,6 +846,7 @@ AVCodec ff_##x##_qsv_decoder = { \ .close = qsv_decode_close, \ .bsfs = bsf_name, \ .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1 | AV_CODEC_CAP_AVOID_PROBING | AV_CODEC_CAP_HYBRID, \ + .caps_internal = FF_CODEC_CAP_AUTO_THREADS, \ .priv_class = &x##_qsv_class, \ .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12, \ AV_PIX_FMT_P010, \ diff --git a/libavcodec/qsvenc_h264.c b/libavcodec/qsvenc_h264.c index ddafc45ec3..fb587ff87c 100644 --- a/libavcodec/qsvenc_h264.c +++ b/libavcodec/qsvenc_h264.c @@ -196,7 +196,7 @@ AVCodec ff_h264_qsv_encoder = { AV_PIX_FMT_NONE }, .priv_class = &class, .defaults = qsv_enc_defaults, - .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_AUTO_THREADS, .wrapper_name = "qsv", .hw_configs = ff_qsv_enc_hw_configs, }; diff --git a/libavcodec/qsvenc_hevc.c b/libavcodec/qsvenc_hevc.c index 347f30655e..a9e5906309 100644 --- a/libavcodec/qsvenc_hevc.c +++ b/libavcodec/qsvenc_hevc.c @@ -289,7 +289,7 @@ AVCodec ff_hevc_qsv_encoder = { AV_PIX_FMT_NONE }, .priv_class = &class, .defaults = qsv_enc_defaults, - .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_AUTO_THREADS, .wrapper_name = "qsv", .hw_configs = ff_qsv_enc_hw_configs, }; diff --git a/libavcodec/qsvenc_jpeg.c b/libavcodec/qsvenc_jpeg.c index f76af9486b..c0af8ad5b4 100644 --- a/libavcodec/qsvenc_jpeg.c +++ b/libavcodec/qsvenc_jpeg.c @@ -94,6 +94,7 @@ AVCodec ff_mjpeg_qsv_encoder = { AV_PIX_FMT_NONE }, .priv_class = &class, .defaults = qsv_enc_defaults, + .caps_internal = FF_CODEC_CAP_AUTO_THREADS, .wrapper_name = "qsv", .hw_configs = ff_qsv_enc_hw_configs, }; diff --git a/libavcodec/qsvenc_mpeg2.c b/libavcodec/qsvenc_mpeg2.c index 0e34bb75dc..e53e42c812 100644 --- a/libavcodec/qsvenc_mpeg2.c +++ b/libavcodec/qsvenc_mpeg2.c @@ -110,7 +110,7 @@ AVCodec ff_mpeg2_qsv_encoder = { AV_PIX_FMT_NONE }, .priv_class = &class, .defaults = qsv_enc_defaults, - .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_AUTO_THREADS, .wrapper_name = "qsv", .hw_configs = ff_qsv_enc_hw_configs, }; diff --git a/libavcodec/qsvenc_vp9.c b/libavcodec/qsvenc_vp9.c index ce44c09397..eae100b18b 100644 --- a/libavcodec/qsvenc_vp9.c +++ b/libavcodec/qsvenc_vp9.c @@ -108,7 +108,7 @@ AVCodec ff_vp9_qsv_encoder = { AV_PIX_FMT_NONE }, .priv_class = &class, .defaults = qsv_enc_defaults, - .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_AUTO_THREADS, .wrapper_name = "qsv", .hw_configs = ff_qsv_enc_hw_configs, }; -- 2.25.1 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".