[v2] qsv: adding Multi Frame Encode support

Message ID 20180402131723.63486-1-maxim.d33@gmail.com
State New
Headers show
Series
  • [v2] qsv: adding Multi Frame Encode support
Related show

Commit Message

Maxym Dmytrychenko April 2, 2018, 1:17 p.m.
Starting from API 1.25 helps to improve performance of the simultaneous
encode, 1:N scenario, like:

./avconv  -y -hwaccel qsv -c:v h264_qsv -r 30000/1001 -i
~/bbb_sunflower_1080p_60fps_normal.mp4  -vframes 600 -an \
    -filter_complex "split=2[s1][s2]; [s1]scale_qsv=1280:720[o1];
[s2]scale_qsv=960:540[o2]" \
    -map [o1] -c:v h264_qsv -b:v 3200k -minrate 3200k -maxrate 3200k -f
rawvideo /tmp/3200a.264 \
    -map [o2] -c:v h264_qsv -b:v 1750k -minrate 1750k -maxrate 1750k -f
rawvideo /tmp/1750a.264
---
 libavcodec/qsv.c                 | 10 ++++++----
 libavcodec/qsv_internal.h        |  4 ++++
 libavcodec/qsvenc.c              | 16 +++++++++++++++-
 libavcodec/qsvenc.h              | 12 ++++++++++--
 libavcodec/qsvenc_h264.c         |  4 ++++
 libavfilter/qsvvpp.c             |  9 ++++++---
 libavfilter/qsvvpp.h             |  8 ++++++++
 libavfilter/vf_deinterlace_qsv.c |  7 +++++++
 libavfilter/vf_scale_qsv.c       |  7 +++++++
 libavutil/hwcontext_qsv.c        |  5 +++++
 10 files changed, 72 insertions(+), 10 deletions(-)

Comments

Li, Zhong April 4, 2018, 6:54 a.m. | #1
LGTM

> -----Original Message-----
> From: libav-devel [mailto:libav-devel-bounces@libav.org] On Behalf Of
> Maxym Dmytrychenko
> Sent: Monday, April 2, 2018 9:17 PM
> To: libav-devel@libav.org
> Subject: [libav-devel] [PATCH v2] qsv: adding Multi Frame Encode support
> 
> Starting from API 1.25 helps to improve performance of the simultaneous
> encode, 1:N scenario, like:
> 
> ./avconv  -y -hwaccel qsv -c:v h264_qsv -r 30000/1001 -i
> ~/bbb_sunflower_1080p_60fps_normal.mp4  -vframes 600 -an \
>     -filter_complex "split=2[s1][s2]; [s1]scale_qsv=1280:720[o1];
> [s2]scale_qsv=960:540[o2]" \
>     -map [o1] -c:v h264_qsv -b:v 3200k -minrate 3200k -maxrate 3200k -f
> rawvideo /tmp/3200a.264 \
>     -map [o2] -c:v h264_qsv -b:v 1750k -minrate 1750k -maxrate 1750k -f
> rawvideo /tmp/1750a.264
> ---
>  libavcodec/qsv.c                 | 10 ++++++----
>  libavcodec/qsv_internal.h        |  4 ++++
>  libavcodec/qsvenc.c              | 16 +++++++++++++++-
>  libavcodec/qsvenc.h              | 12 ++++++++++--
>  libavcodec/qsvenc_h264.c         |  4 ++++
>  libavfilter/qsvvpp.c             |  9 ++++++---
>  libavfilter/qsvvpp.h             |  8 ++++++++
>  libavfilter/vf_deinterlace_qsv.c |  7 +++++++
>  libavfilter/vf_scale_qsv.c       |  7 +++++++
>  libavutil/hwcontext_qsv.c        |  5 +++++
>  10 files changed, 72 insertions(+), 10 deletions(-)
> 
> diff --git a/libavcodec/qsv.c b/libavcodec/qsv.c index e78633d62..bab32836e
> 100644
> --- a/libavcodec/qsv.c
> +++ b/libavcodec/qsv.c
> @@ -593,10 +593,12 @@ int ff_qsv_init_session_device(AVCodecContext
> *avctx, mfxSession *psession,
>                                        "Error setting a HW
> handle");
>      }
> 
> -    err = MFXJoinSession(parent_session, session);
> -    if (err != MFX_ERR_NONE)
> -        return ff_qsv_print_error(avctx, err,
> -                                  "Error joining session");
> +    if (QSV_RUNTIME_VERSION_ATLEAST(ver, 1, 25)) {
> +        err = MFXJoinSession(parent_session, session);
> +        if (err != MFX_ERR_NONE)
> +            return ff_qsv_print_error(avctx, err,
> +                                      "Error joining session");
> +    }
> 
>      ret = qsv_load_plugins(session, load_plugins, avctx);
>      if (ret < 0) {
> diff --git a/libavcodec/qsv_internal.h b/libavcodec/qsv_internal.h index
> 975c8de44..d2a18eb06 100644
> --- a/libavcodec/qsv_internal.h
> +++ b/libavcodec/qsv_internal.h
> @@ -36,6 +36,10 @@
>      (MFX_VERSION_MAJOR > (MAJOR) ||         \
>       MFX_VERSION_MAJOR == (MAJOR) && MFX_VERSION_MINOR >=
> (MINOR))
> 
> +#define QSV_RUNTIME_VERSION_ATLEAST(MFX_VERSION, MAJOR,
> MINOR) \
> +    (MFX_VERSION.Major > (MAJOR)) ||                           \
> +    (MFX_VERSION.Major == (MAJOR) && MFX_VERSION.Minor >=
> (MINOR))
> +
>  typedef struct QSVMid {
>      AVBufferRef *hw_frames_ref;
>      mfxHDL handle;
> diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c index
> f6b1a0d67..a8b446c5b 100644
> --- a/libavcodec/qsvenc.c
> +++ b/libavcodec/qsvenc.c
> @@ -135,7 +135,7 @@ static void dump_video_param(AVCodecContext
> *avctx, QSVEncContext *q,  #if QSV_HAVE_CO2
>      mfxExtCodingOption2 *co2 = (mfxExtCodingOption2*)coding_opts[1];
>  #endif
> -#if QSV_HAVE_CO3
> +#if QSV_HAVE_CO3 && QSV_HAVE_QVBR
>      mfxExtCodingOption3 *co3 = (mfxExtCodingOption3*)coding_opts[2];
>  #endif
> 
> @@ -656,6 +656,20 @@ FF_ENABLE_DEPRECATION_WARNINGS
> 
>              q->extparam_internal[q->nb_extparam_internal++] =
> (mfxExtBuffer *)&q->extco2;
>          }
> +#endif
> +#if QSV_HAVE_MF
> +        if (avctx->codec_id == AV_CODEC_ID_H264) {
> +            mfxVersion    ver;
> +            ret = MFXQueryVersion(q->session,&ver);
> +            if (ret >= MFX_ERR_NONE &&
> QSV_RUNTIME_VERSION_ATLEAST(ver, 1, 25)) {
> +                q->extmfp.Header.BufferId     =
> MFX_EXTBUFF_MULTI_FRAME_PARAM;
> +                q->extmfp.Header.BufferSz     = sizeof(q->extmfp);
> +
> +                q->extmfp.MFMode = q->mfmode;
> +                av_log(avctx,AV_LOG_VERBOSE,"MFMode:%d\n",
> q->extmfp.MFMode);
> +                q->extparam_internal[q->nb_extparam_internal++] =
> (mfxExtBuffer *)&q->extmfp;
> +            }
> +        }
>  #endif
>      }
> 
> diff --git a/libavcodec/qsvenc.h b/libavcodec/qsvenc.h index
> ab5579595..a7fc57bb4 100644
> --- a/libavcodec/qsvenc.h
> +++ b/libavcodec/qsvenc.h
> @@ -50,11 +50,13 @@
>  #define QSV_HAVE_ICQ    QSV_VERSION_ATLEAST(1, 8)
>  #define QSV_HAVE_VCM    QSV_VERSION_ATLEAST(1, 8)
>  #define QSV_HAVE_QVBR   QSV_VERSION_ATLEAST(1, 11)
> +#define QSV_HAVE_MF     0
>  #else
>  #define QSV_HAVE_AVBR   0
>  #define QSV_HAVE_ICQ    0
>  #define QSV_HAVE_VCM    0
>  #define QSV_HAVE_QVBR   0
> +#define QSV_HAVE_MF     QSV_VERSION_ATLEAST(1, 25)
>  #endif
> 
>  #if !QSV_HAVE_LA_DS
> @@ -109,12 +111,15 @@ typedef struct QSVEncContext {  #if
> QSV_HAVE_CO2
>      mfxExtCodingOption2 extco2;
>  #endif
> -
> +#if QSV_HAVE_MF
> +    mfxExtMultiFrameParam   extmfp;
> +    mfxExtMultiFrameControl extmfc;
> +#endif
>      mfxExtOpaqueSurfaceAlloc opaque_alloc;
>      mfxFrameSurface1       **opaque_surfaces;
>      AVBufferRef             *opaque_alloc_buf;
> 
> -    mfxExtBuffer  *extparam_internal[2 + QSV_HAVE_CO2];
> +    mfxExtBuffer  *extparam_internal[2 + QSV_HAVE_CO2 +
> (QSV_HAVE_MF *
> + 2)];
>      int         nb_extparam_internal;
> 
>      mfxExtBuffer **extparam;
> @@ -156,6 +161,9 @@ typedef struct QSVEncContext {
>      int int_ref_qp_delta;
>      int recovery_point_sei;
> 
> +#if QSV_HAVE_MF
> +    int mfmode;
> +#endif
>      char *load_plugins;
>  } QSVEncContext;
> 
> diff --git a/libavcodec/qsvenc_h264.c b/libavcodec/qsvenc_h264.c index
> 634a7d3f9..ae00ff8d5 100644
> --- a/libavcodec/qsvenc_h264.c
> +++ b/libavcodec/qsvenc_h264.c
> @@ -93,6 +93,10 @@ static const AVOption options[] = {
> 
>      { "aud", "Insert the Access Unit Delimiter NAL", OFFSET(qsv.aud),
> AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE},
> 
> +#if QSV_HAVE_MF
> +    { "mfmode", "Multi-Frame Mode", OFFSET(qsv.mfmode),
> +AV_OPT_TYPE_INT, { .i64 = MFX_MF_AUTO }, 0, INT_MAX, VE }, #endif
> +
>      { NULL },
>  };
> 
> diff --git a/libavfilter/qsvvpp.c b/libavfilter/qsvvpp.c index
> a96cfa65d..f704517ae 100644
> --- a/libavfilter/qsvvpp.c
> +++ b/libavfilter/qsvvpp.c
> @@ -515,9 +515,12 @@ static int init_vpp_session(AVFilterContext *avctx,
> QSVVPPContext *s)
>          if (ret != MFX_ERR_NONE)
>              return AVERROR_UNKNOWN;
>      }
> -    ret = MFXJoinSession(device_hwctx->session, s->session);
> -    if (ret != MFX_ERR_NONE)
> -        return AVERROR_UNKNOWN;
> +
> +    if (QSV_RUNTIME_VERSION_ATLEAST(ver, 1, 25)) {
> +        ret = MFXJoinSession(device_hwctx->session, s->session);
> +        if (ret != MFX_ERR_NONE)
> +            return AVERROR_UNKNOWN;
> +    }
> 
>      if (IS_OPAQUE_MEMORY(s->in_mem_mode) ||
> IS_OPAQUE_MEMORY(s->out_mem_mode)) {
>          s->opaque_alloc.In.Surfaces   = s->surface_ptrs_in;
> diff --git a/libavfilter/qsvvpp.h b/libavfilter/qsvvpp.h index
> 082c0a899..d25ea69e5 100644
> --- a/libavfilter/qsvvpp.h
> +++ b/libavfilter/qsvvpp.h
> @@ -31,6 +31,14 @@
>  #define FF_INLINK_IDX(link)  ((int)((link)->dstpad - (link)->dst->input_pads))
> #define FF_OUTLINK_IDX(link) ((int)((link)->srcpad -
> (link)->src->output_pads))
> 
> +#define QSV_VERSION_ATLEAST(MAJOR, MINOR)   \
> +    (MFX_VERSION_MAJOR > (MAJOR) ||         \
> +     MFX_VERSION_MAJOR == (MAJOR) && MFX_VERSION_MINOR >=
> (MINOR))
> +
> +#define QSV_RUNTIME_VERSION_ATLEAST(MFX_VERSION, MAJOR,
> MINOR) \
> +    (MFX_VERSION.Major > (MAJOR)) ||                           \
> +    (MFX_VERSION.Major == (MAJOR) && MFX_VERSION.Minor >=
> (MINOR))
> +
>  typedef struct QSVVPPContext QSVVPPContext;
> 
>  typedef struct QSVVPPCrop {
> diff --git a/libavfilter/vf_deinterlace_qsv.c b/libavfilter/vf_deinterlace_qsv.c
> index 2360491d3..bb26a4dbf 100644
> --- a/libavfilter/vf_deinterlace_qsv.c
> +++ b/libavfilter/vf_deinterlace_qsv.c
> @@ -35,6 +35,7 @@
>  #include "libavutil/opt.h"
>  #include "libavutil/pixdesc.h"
>  #include "libavutil/time.h"
> +#include "libavfilter/qsvvpp.h"
> 
>  #include "avfilter.h"
>  #include "formats.h"
> @@ -214,6 +215,12 @@ static int init_out_session(AVFilterContext *ctx)
>              return AVERROR_UNKNOWN;
>      }
> 
> +    if (QSV_RUNTIME_VERSION_ATLEAST(ver, 1, 25)) {
> +        err = MFXJoinSession(device_hwctx->session, s->session);
> +        if (err != MFX_ERR_NONE)
> +            return AVERROR_UNKNOWN;
> +    }
> +
>      memset(&par, 0, sizeof(par));
> 
>      s->deint_conf.Header.BufferId = MFX_EXTBUFF_VPP_DEINTERLACING;
> diff --git a/libavfilter/vf_scale_qsv.c b/libavfilter/vf_scale_qsv.c index
> c568e9625..381844cdc 100644
> --- a/libavfilter/vf_scale_qsv.c
> +++ b/libavfilter/vf_scale_qsv.c
> @@ -36,6 +36,7 @@
>  #include "libavutil/opt.h"
>  #include "libavutil/pixdesc.h"
>  #include "libavutil/time.h"
> +#include "libavfilter/qsvvpp.h"
> 
>  #include "avfilter.h"
>  #include "formats.h"
> @@ -313,6 +314,12 @@ static int init_out_session(AVFilterContext *ctx)
>              return AVERROR_UNKNOWN;
>      }
> 
> +    if (QSV_RUNTIME_VERSION_ATLEAST(ver, 1, 25)) {
> +        err = MFXJoinSession(device_hwctx->session, s->session);
> +            if (err != MFX_ERR_NONE)
> +                return AVERROR_UNKNOWN;
> +    }
> +
>      memset(&par, 0, sizeof(par));
> 
>      if (opaque) {
> diff --git a/libavutil/hwcontext_qsv.c b/libavutil/hwcontext_qsv.c index
> f5d78d059..b3eb4a3ea 100644
> --- a/libavutil/hwcontext_qsv.c
> +++ b/libavutil/hwcontext_qsv.c
> @@ -1058,6 +1058,11 @@ static int
> qsv_device_derive_from_child(AVHWDeviceContext *ctx,
>          goto fail;
>      }
> 
> +    ret = MFXQueryVersion(hwctx->session,&ver);
> +    if (ret == MFX_ERR_NONE) {
> +        av_log(ctx, AV_LOG_VERBOSE, "MFX compile/runtime
> API: %d.%d/%d.%d\n",
> +               MFX_VERSION_MAJOR, MFX_VERSION_MINOR,
> ver.Major, ver.Minor);
> +    }
>      return 0;
> 
>  fail:
> --
> 2.14.3 (Apple Git-98)
> 
> _______________________________________________
> libav-devel mailing list
> libav-devel@libav.org
> https://lists.libav.org/mailman/listinfo/libav-devel
Luca Barbato April 4, 2018, 10:07 a.m. | #2
On 02/04/2018 15:17, Maxym Dmytrychenko wrote:
> +    if (QSV_RUNTIME_VERSION_ATLEAST(ver, 1, 25)) {

Maybe use QSV_HAVE_MF ?

The rest looks fine to me.

lu
Maxym Dmytrychenko April 5, 2018, 7:28 a.m. | #3
thanks, Luca

I see QSV_HAVE_MF as compile time definition
where QSV_RUNTIME_VERSION_ATLEAST reflects runtime version check

as it might be two different aspects and it would be more logical to check
both at proper time.

ok?

On Wed, Apr 4, 2018 at 12:07 PM, Luca Barbato <lu_zero@gentoo.org> wrote:

> On 02/04/2018 15:17, Maxym Dmytrychenko wrote:
> > +    if (QSV_RUNTIME_VERSION_ATLEAST(ver, 1, 25)) {
>
> Maybe use QSV_HAVE_MF ?
>
> The rest looks fine to me.
>
> lu
> _______________________________________________
> libav-devel mailing list
> libav-devel@libav.org
> https://lists.libav.org/mailman/listinfo/libav-devel
Luca Barbato April 6, 2018, 12:30 p.m. | #4
On 05/04/2018 09:28, Maxym Dmytrychenko wrote:
> thanks, Luca
> 
> I see QSV_HAVE_MF as compile time definition
> where QSV_RUNTIME_VERSION_ATLEAST reflects runtime version check
> 
> as it might be two different aspects and it would be more logical to check
> both at proper time.
> 
> ok?
> 

Sure :)

lu

Patch

diff --git a/libavcodec/qsv.c b/libavcodec/qsv.c
index e78633d62..bab32836e 100644
--- a/libavcodec/qsv.c
+++ b/libavcodec/qsv.c
@@ -593,10 +593,12 @@  int ff_qsv_init_session_device(AVCodecContext *avctx, mfxSession *psession,
                                       "Error setting a HW handle");
     }
 
-    err = MFXJoinSession(parent_session, session);
-    if (err != MFX_ERR_NONE)
-        return ff_qsv_print_error(avctx, err,
-                                  "Error joining session");
+    if (QSV_RUNTIME_VERSION_ATLEAST(ver, 1, 25)) {
+        err = MFXJoinSession(parent_session, session);
+        if (err != MFX_ERR_NONE)
+            return ff_qsv_print_error(avctx, err,
+                                      "Error joining session");
+    }
 
     ret = qsv_load_plugins(session, load_plugins, avctx);
     if (ret < 0) {
diff --git a/libavcodec/qsv_internal.h b/libavcodec/qsv_internal.h
index 975c8de44..d2a18eb06 100644
--- a/libavcodec/qsv_internal.h
+++ b/libavcodec/qsv_internal.h
@@ -36,6 +36,10 @@ 
     (MFX_VERSION_MAJOR > (MAJOR) ||         \
      MFX_VERSION_MAJOR == (MAJOR) && MFX_VERSION_MINOR >= (MINOR))
 
+#define QSV_RUNTIME_VERSION_ATLEAST(MFX_VERSION, MAJOR, MINOR) \
+    (MFX_VERSION.Major > (MAJOR)) ||                           \
+    (MFX_VERSION.Major == (MAJOR) && MFX_VERSION.Minor >= (MINOR))
+
 typedef struct QSVMid {
     AVBufferRef *hw_frames_ref;
     mfxHDL handle;
diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c
index f6b1a0d67..a8b446c5b 100644
--- a/libavcodec/qsvenc.c
+++ b/libavcodec/qsvenc.c
@@ -135,7 +135,7 @@  static void dump_video_param(AVCodecContext *avctx, QSVEncContext *q,
 #if QSV_HAVE_CO2
     mfxExtCodingOption2 *co2 = (mfxExtCodingOption2*)coding_opts[1];
 #endif
-#if QSV_HAVE_CO3
+#if QSV_HAVE_CO3 && QSV_HAVE_QVBR
     mfxExtCodingOption3 *co3 = (mfxExtCodingOption3*)coding_opts[2];
 #endif
 
@@ -656,6 +656,20 @@  FF_ENABLE_DEPRECATION_WARNINGS
 
             q->extparam_internal[q->nb_extparam_internal++] = (mfxExtBuffer *)&q->extco2;
         }
+#endif
+#if QSV_HAVE_MF
+        if (avctx->codec_id == AV_CODEC_ID_H264) {
+            mfxVersion    ver;
+            ret = MFXQueryVersion(q->session,&ver);
+            if (ret >= MFX_ERR_NONE && QSV_RUNTIME_VERSION_ATLEAST(ver, 1, 25)) {
+                q->extmfp.Header.BufferId     = MFX_EXTBUFF_MULTI_FRAME_PARAM;
+                q->extmfp.Header.BufferSz     = sizeof(q->extmfp);
+
+                q->extmfp.MFMode = q->mfmode;
+                av_log(avctx,AV_LOG_VERBOSE,"MFMode:%d\n", q->extmfp.MFMode);
+                q->extparam_internal[q->nb_extparam_internal++] = (mfxExtBuffer *)&q->extmfp;
+            }
+        }
 #endif
     }
 
diff --git a/libavcodec/qsvenc.h b/libavcodec/qsvenc.h
index ab5579595..a7fc57bb4 100644
--- a/libavcodec/qsvenc.h
+++ b/libavcodec/qsvenc.h
@@ -50,11 +50,13 @@ 
 #define QSV_HAVE_ICQ    QSV_VERSION_ATLEAST(1, 8)
 #define QSV_HAVE_VCM    QSV_VERSION_ATLEAST(1, 8)
 #define QSV_HAVE_QVBR   QSV_VERSION_ATLEAST(1, 11)
+#define QSV_HAVE_MF     0
 #else
 #define QSV_HAVE_AVBR   0
 #define QSV_HAVE_ICQ    0
 #define QSV_HAVE_VCM    0
 #define QSV_HAVE_QVBR   0
+#define QSV_HAVE_MF     QSV_VERSION_ATLEAST(1, 25)
 #endif
 
 #if !QSV_HAVE_LA_DS
@@ -109,12 +111,15 @@  typedef struct QSVEncContext {
 #if QSV_HAVE_CO2
     mfxExtCodingOption2 extco2;
 #endif
-
+#if QSV_HAVE_MF
+    mfxExtMultiFrameParam   extmfp;
+    mfxExtMultiFrameControl extmfc;
+#endif
     mfxExtOpaqueSurfaceAlloc opaque_alloc;
     mfxFrameSurface1       **opaque_surfaces;
     AVBufferRef             *opaque_alloc_buf;
 
-    mfxExtBuffer  *extparam_internal[2 + QSV_HAVE_CO2];
+    mfxExtBuffer  *extparam_internal[2 + QSV_HAVE_CO2 + (QSV_HAVE_MF * 2)];
     int         nb_extparam_internal;
 
     mfxExtBuffer **extparam;
@@ -156,6 +161,9 @@  typedef struct QSVEncContext {
     int int_ref_qp_delta;
     int recovery_point_sei;
 
+#if QSV_HAVE_MF
+    int mfmode;
+#endif
     char *load_plugins;
 } QSVEncContext;
 
diff --git a/libavcodec/qsvenc_h264.c b/libavcodec/qsvenc_h264.c
index 634a7d3f9..ae00ff8d5 100644
--- a/libavcodec/qsvenc_h264.c
+++ b/libavcodec/qsvenc_h264.c
@@ -93,6 +93,10 @@  static const AVOption options[] = {
 
     { "aud", "Insert the Access Unit Delimiter NAL", OFFSET(qsv.aud), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE},
 
+#if QSV_HAVE_MF
+    { "mfmode", "Multi-Frame Mode", OFFSET(qsv.mfmode), AV_OPT_TYPE_INT, { .i64 = MFX_MF_AUTO }, 0, INT_MAX, VE },
+#endif
+
     { NULL },
 };
 
diff --git a/libavfilter/qsvvpp.c b/libavfilter/qsvvpp.c
index a96cfa65d..f704517ae 100644
--- a/libavfilter/qsvvpp.c
+++ b/libavfilter/qsvvpp.c
@@ -515,9 +515,12 @@  static int init_vpp_session(AVFilterContext *avctx, QSVVPPContext *s)
         if (ret != MFX_ERR_NONE)
             return AVERROR_UNKNOWN;
     }
-    ret = MFXJoinSession(device_hwctx->session, s->session);
-    if (ret != MFX_ERR_NONE)
-        return AVERROR_UNKNOWN;
+
+    if (QSV_RUNTIME_VERSION_ATLEAST(ver, 1, 25)) {
+        ret = MFXJoinSession(device_hwctx->session, s->session);
+        if (ret != MFX_ERR_NONE)
+            return AVERROR_UNKNOWN;
+    }
 
     if (IS_OPAQUE_MEMORY(s->in_mem_mode) || IS_OPAQUE_MEMORY(s->out_mem_mode)) {
         s->opaque_alloc.In.Surfaces   = s->surface_ptrs_in;
diff --git a/libavfilter/qsvvpp.h b/libavfilter/qsvvpp.h
index 082c0a899..d25ea69e5 100644
--- a/libavfilter/qsvvpp.h
+++ b/libavfilter/qsvvpp.h
@@ -31,6 +31,14 @@ 
 #define FF_INLINK_IDX(link)  ((int)((link)->dstpad - (link)->dst->input_pads))
 #define FF_OUTLINK_IDX(link) ((int)((link)->srcpad - (link)->src->output_pads))
 
+#define QSV_VERSION_ATLEAST(MAJOR, MINOR)   \
+    (MFX_VERSION_MAJOR > (MAJOR) ||         \
+     MFX_VERSION_MAJOR == (MAJOR) && MFX_VERSION_MINOR >= (MINOR))
+
+#define QSV_RUNTIME_VERSION_ATLEAST(MFX_VERSION, MAJOR, MINOR) \
+    (MFX_VERSION.Major > (MAJOR)) ||                           \
+    (MFX_VERSION.Major == (MAJOR) && MFX_VERSION.Minor >= (MINOR))
+
 typedef struct QSVVPPContext QSVVPPContext;
 
 typedef struct QSVVPPCrop {
diff --git a/libavfilter/vf_deinterlace_qsv.c b/libavfilter/vf_deinterlace_qsv.c
index 2360491d3..bb26a4dbf 100644
--- a/libavfilter/vf_deinterlace_qsv.c
+++ b/libavfilter/vf_deinterlace_qsv.c
@@ -35,6 +35,7 @@ 
 #include "libavutil/opt.h"
 #include "libavutil/pixdesc.h"
 #include "libavutil/time.h"
+#include "libavfilter/qsvvpp.h"
 
 #include "avfilter.h"
 #include "formats.h"
@@ -214,6 +215,12 @@  static int init_out_session(AVFilterContext *ctx)
             return AVERROR_UNKNOWN;
     }
 
+    if (QSV_RUNTIME_VERSION_ATLEAST(ver, 1, 25)) {
+        err = MFXJoinSession(device_hwctx->session, s->session);
+        if (err != MFX_ERR_NONE)
+            return AVERROR_UNKNOWN;
+    }
+
     memset(&par, 0, sizeof(par));
 
     s->deint_conf.Header.BufferId = MFX_EXTBUFF_VPP_DEINTERLACING;
diff --git a/libavfilter/vf_scale_qsv.c b/libavfilter/vf_scale_qsv.c
index c568e9625..381844cdc 100644
--- a/libavfilter/vf_scale_qsv.c
+++ b/libavfilter/vf_scale_qsv.c
@@ -36,6 +36,7 @@ 
 #include "libavutil/opt.h"
 #include "libavutil/pixdesc.h"
 #include "libavutil/time.h"
+#include "libavfilter/qsvvpp.h"
 
 #include "avfilter.h"
 #include "formats.h"
@@ -313,6 +314,12 @@  static int init_out_session(AVFilterContext *ctx)
             return AVERROR_UNKNOWN;
     }
 
+    if (QSV_RUNTIME_VERSION_ATLEAST(ver, 1, 25)) {
+        err = MFXJoinSession(device_hwctx->session, s->session);
+            if (err != MFX_ERR_NONE)
+                return AVERROR_UNKNOWN;
+    }
+
     memset(&par, 0, sizeof(par));
 
     if (opaque) {
diff --git a/libavutil/hwcontext_qsv.c b/libavutil/hwcontext_qsv.c
index f5d78d059..b3eb4a3ea 100644
--- a/libavutil/hwcontext_qsv.c
+++ b/libavutil/hwcontext_qsv.c
@@ -1058,6 +1058,11 @@  static int qsv_device_derive_from_child(AVHWDeviceContext *ctx,
         goto fail;
     }
 
+    ret = MFXQueryVersion(hwctx->session,&ver);
+    if (ret == MFX_ERR_NONE) {
+        av_log(ctx, AV_LOG_VERBOSE, "MFX compile/runtime API: %d.%d/%d.%d\n",
+               MFX_VERSION_MAJOR, MFX_VERSION_MINOR, ver.Major, ver.Minor);
+    }
     return 0;
 
 fail: