diff mbox series

[FFmpeg-devel,v4] avfilter/vpp_qsv: fix regression on older api versions (e.g. 1.11)

Message ID pull.15.v4.ffstaging.FFmpeg.1641538891098.ffmpegagent@gmail.com
State Accepted
Commit 479f3c65986fca0ccf56f4dadb5a5b167f466fc7
Headers show
Series [FFmpeg-devel,v4] avfilter/vpp_qsv: fix regression on older api versions (e.g. 1.11) | expand

Checks

Context Check Description
andriy/make_x86 success Make finished
andriy/make_fate_x86 success Make fate finished
andriy/make_ppc success Make finished
andriy/make_fate_ppc success Make fate finished

Commit Message

Aman Karmani Jan. 7, 2022, 7:01 a.m. UTC
From: softworkz <softworkz@hotmail.com>

Commit 8b83dad82512a6948b63408f964463b063ad24c9 introduced a
regression in a way that scaling via vpp_qsv doesn't work any longer
for devices with an MSDK runtime version lower than 1.19. This is true
for older CPUs which are stuck at 1.11.
The commit added checks for the compile-sdk version but it didn't test
for the runtime version.

Signed-off-by: softworkz <softworkz@hotmail.com>
---
    avfilter/vpp_qsv: fix regression on older api versions (e.g. 1.11)
    
    Fix a recently introduced regression when using QSV VPP.
    
    v2: Fixed commit message wrapping
    
    v3: Use different way to acquire runtime version
    
    v4: Use mfxStatus as return type for get_mfx_version()

Published-As: https://github.com/ffstaging/FFmpeg/releases/tag/pr-ffstaging-15%2Fsoftworkz%2Fqsv_vpp_regression-v4
Fetch-It-Via: git fetch https://github.com/ffstaging/FFmpeg pr-ffstaging-15/softworkz/qsv_vpp_regression-v4
Pull-Request: https://github.com/ffstaging/FFmpeg/pull/15

Range-diff vs v3:

 1:  cbf53d8ef4 ! 1:  bf53154420 avfilter/vpp_qsv: fix regression on older api versions (e.g. 1.11)
     @@ libavfilter/vf_vpp_qsv.c: static int config_input(AVFilterLink *inlink)
           return 0;
       }
       
     -+static int get_mfx_version(const AVFilterContext *ctx, mfxVersion *mfx_version)
     ++static mfxStatus get_mfx_version(const AVFilterContext *ctx, mfxVersion *mfx_version)
      +{
      +    const AVFilterLink *inlink = ctx->inputs[0];
      +    AVBufferRef *device_ref;
     @@ libavfilter/vf_vpp_qsv.c: static int config_input(AVFilterLink *inlink)
      +        // so don't error here but let runtime version checks fail by setting to 0.0
      +        mfx_version->Major = 0;
      +        mfx_version->Minor = 0;
     -+        return 0;
     ++        return MFX_ERR_NONE;
      +    }
      +
      +    device_ctx   = (AVHWDeviceContext *)device_ref->data;
     @@ libavfilter/vf_vpp_qsv.c: static int config_output(AVFilterLink *outlink)
           param.ext_buf       = ext_buf;
           param.async_depth   = vpp->async_depth;
       
     -+    if (get_mfx_version(ctx, &mfx_version) < 0) {
     ++    if (get_mfx_version(ctx, &mfx_version) != MFX_ERR_NONE) {
      +        av_log(ctx, AV_LOG_ERROR, "Failed to query mfx version.\n");
      +        return AVERROR(EINVAL);
      +    }


 libavfilter/vf_vpp_qsv.c | 59 ++++++++++++++++++++++++++++++++--------
 1 file changed, 47 insertions(+), 12 deletions(-)


base-commit: 242ed971cb005157488b9a21942d9fb4be4d0347

Comments

Xiang, Haihao Jan. 10, 2022, 7:02 a.m. UTC | #1
On Fri, 2022-01-07 at 07:01 +0000, ffmpegagent wrote:
> From: softworkz <softworkz@hotmail.com>
> 
> Commit 8b83dad82512a6948b63408f964463b063ad24c9 introduced a
> regression in a way that scaling via vpp_qsv doesn't work any longer
> for devices with an MSDK runtime version lower than 1.19. This is true
> for older CPUs which are stuck at 1.11.
> The commit added checks for the compile-sdk version but it didn't test
> for the runtime version.
> 
> Signed-off-by: softworkz <softworkz@hotmail.com>
> ---
>     avfilter/vpp_qsv: fix regression on older api versions (e.g. 1.11)
>     
>     Fix a recently introduced regression when using QSV VPP.
>     
>     v2: Fixed commit message wrapping
>     
>     v3: Use different way to acquire runtime version
>     
>     v4: Use mfxStatus as return type for get_mfx_version()
> 
> Published-As: 
> https://github.com/ffstaging/FFmpeg/releases/tag/pr-ffstaging-15%2Fsoftworkz%2Fqsv_vpp_regression-v4
> Fetch-It-Via: git fetch https://github.com/ffstaging/FFmpeg pr-ffstaging-
> 15/softworkz/qsv_vpp_regression-v4
> Pull-Request: https://github.com/ffstaging/FFmpeg/pull/15
> 
> Range-diff vs v3:
> 
>  1:  cbf53d8ef4 ! 1:  bf53154420 avfilter/vpp_qsv: fix regression on older api
> versions (e.g. 1.11)
>      @@ libavfilter/vf_vpp_qsv.c: static int config_input(AVFilterLink
> *inlink)
>            return 0;
>        }
>        
>      -+static int get_mfx_version(const AVFilterContext *ctx, mfxVersion
> *mfx_version)
>      ++static mfxStatus get_mfx_version(const AVFilterContext *ctx, mfxVersion
> *mfx_version)
>       +{
>       +    const AVFilterLink *inlink = ctx->inputs[0];
>       +    AVBufferRef *device_ref;
>      @@ libavfilter/vf_vpp_qsv.c: static int config_input(AVFilterLink
> *inlink)
>       +        // so don't error here but let runtime version checks fail by
> setting to 0.0
>       +        mfx_version->Major = 0;
>       +        mfx_version->Minor = 0;
>      -+        return 0;
>      ++        return MFX_ERR_NONE;
>       +    }
>       +
>       +    device_ctx   = (AVHWDeviceContext *)device_ref->data;
>      @@ libavfilter/vf_vpp_qsv.c: static int config_output(AVFilterLink
> *outlink)
>            param.ext_buf       = ext_buf;
>            param.async_depth   = vpp->async_depth;
>        
>      -+    if (get_mfx_version(ctx, &mfx_version) < 0) {
>      ++    if (get_mfx_version(ctx, &mfx_version) != MFX_ERR_NONE) {
>       +        av_log(ctx, AV_LOG_ERROR, "Failed to query mfx version.\n");
>       +        return AVERROR(EINVAL);
>       +    }
> 
> 
>  libavfilter/vf_vpp_qsv.c | 59 ++++++++++++++++++++++++++++++++--------
>  1 file changed, 47 insertions(+), 12 deletions(-)
> 
> diff --git a/libavfilter/vf_vpp_qsv.c b/libavfilter/vf_vpp_qsv.c
> index ab58a5777e..5c96703fd3 100644
> --- a/libavfilter/vf_vpp_qsv.c
> +++ b/libavfilter/vf_vpp_qsv.c
> @@ -26,6 +26,7 @@
>  #include "libavutil/opt.h"
>  #include "libavutil/eval.h"
>  #include "libavutil/hwcontext.h"
> +#include "libavutil/hwcontext_qsv.h"
>  #include "libavutil/pixdesc.h"
>  #include "libavutil/mathematics.h"
>  
> @@ -139,8 +140,9 @@ static const AVOption options[] = {
>      { "height", "Output video height", OFFSET(oh), AV_OPT_TYPE_STRING, {
> .str="w*ch/cw" }, 0, 255, .flags = FLAGS },
>      { "format", "Output pixel format", OFFSET(output_format_str),
> AV_OPT_TYPE_STRING, { .str = "same" }, .flags = FLAGS },
>      { "async_depth", "Internal parallelization depth, the higher the value
> the higher the latency.", OFFSET(async_depth), AV_OPT_TYPE_INT, { .i64 = 0 },
> 0, INT_MAX, .flags = FLAGS },
> +#ifdef QSV_HAVE_SCALING_CONFIG
>      { "scale_mode", "scale mode: 0=auto, 1=low power, 2=high quality",
> OFFSET(scale_mode), AV_OPT_TYPE_INT, { .i64 = MFX_SCALING_MODE_DEFAULT },
> MFX_SCALING_MODE_DEFAULT, MFX_SCALING_MODE_QUALITY, .flags = FLAGS, "scale
> mode" },
> -
> +#endif
>      { NULL }
>  };
>  
> @@ -297,6 +299,32 @@ static int config_input(AVFilterLink *inlink)
>      return 0;
>  }
>  
> +static mfxStatus get_mfx_version(const AVFilterContext *ctx, mfxVersion
> *mfx_version)
> +{
> +    const AVFilterLink *inlink = ctx->inputs[0];
> +    AVBufferRef *device_ref;
> +    AVHWDeviceContext *device_ctx;
> +    AVQSVDeviceContext *device_hwctx;
> +
> +    if (inlink->hw_frames_ctx) {
> +        AVHWFramesContext *frames_ctx = (AVHWFramesContext *)inlink-
> >hw_frames_ctx->data;
> +        device_ref = frames_ctx->device_ref;
> +    } else if (ctx->hw_device_ctx) {
> +        device_ref = ctx->hw_device_ctx;
> +    } else {
> +        // Unavailable hw context doesn't matter in pass-through mode,
> +        // so don't error here but let runtime version checks fail by setting
> to 0.0
> +        mfx_version->Major = 0;
> +        mfx_version->Minor = 0;
> +        return MFX_ERR_NONE;
> +    }
> +
> +    device_ctx   = (AVHWDeviceContext *)device_ref->data;
> +    device_hwctx = device_ctx->hwctx;
> +
> +    return MFXQueryVersion(device_hwctx->session, mfx_version);
> +}
> +
>  static int config_output(AVFilterLink *outlink)
>  {
>      AVFilterContext *ctx = outlink->src;
> @@ -304,6 +332,7 @@ static int config_output(AVFilterLink *outlink)
>      QSVVPPParam     param = { NULL };
>      QSVVPPCrop      crop  = { 0 };
>      mfxExtBuffer    *ext_buf[ENH_FILTERS_COUNT];
> +    mfxVersion      mfx_version;
>      AVFilterLink    *inlink = ctx->inputs[0];
>      enum AVPixelFormat in_format;
>  
> @@ -317,6 +346,11 @@ static int config_output(AVFilterLink *outlink)
>      param.ext_buf       = ext_buf;
>      param.async_depth   = vpp->async_depth;
>  
> +    if (get_mfx_version(ctx, &mfx_version) != MFX_ERR_NONE) {
> +        av_log(ctx, AV_LOG_ERROR, "Failed to query mfx version.\n");
> +        return AVERROR(EINVAL);
> +    }
> +
>      if (inlink->format == AV_PIX_FMT_QSV) {
>           if (!inlink->hw_frames_ctx || !inlink->hw_frames_ctx->data)
>               return AVERROR(EINVAL);
> @@ -467,19 +501,20 @@ static int config_output(AVFilterLink *outlink)
>  #endif
>      }
>  
> -    if (inlink->w != outlink->w || inlink->h != outlink->h) {
>  #ifdef QSV_HAVE_SCALING_CONFIG
> -        memset(&vpp->scale_conf, 0, sizeof(mfxExtVPPScaling));
> -        vpp->scale_conf.Header.BufferId    = MFX_EXTBUFF_VPP_SCALING;
> -        vpp->scale_conf.Header.BufferSz    = sizeof(mfxExtVPPScaling);
> -        vpp->scale_conf.ScalingMode        = vpp->scale_mode;
> -
> -        param.ext_buf[param.num_ext_buf++] = (mfxExtBuffer*)&vpp->scale_conf;
> -#else
> -        av_log(ctx, AV_LOG_WARNING, "The QSV VPP Scale option is "
> -            "not supported with this MSDK version.\n");
> -#endif
> +    if (inlink->w != outlink->w || inlink->h != outlink->h) {
> +        if (QSV_RUNTIME_VERSION_ATLEAST(mfx_version, 1, 19)) {
> +            memset(&vpp->scale_conf, 0, sizeof(mfxExtVPPScaling));
> +            vpp->scale_conf.Header.BufferId    = MFX_EXTBUFF_VPP_SCALING;
> +            vpp->scale_conf.Header.BufferSz    = sizeof(mfxExtVPPScaling);
> +            vpp->scale_conf.ScalingMode        = vpp->scale_mode;
> +
> +            param.ext_buf[param.num_ext_buf++] = (mfxExtBuffer*)&vpp-
> >scale_conf;
> +        } else
> +            av_log(ctx, AV_LOG_WARNING, "The QSV VPP Scale option is "
> +                "not supported with this MSDK version.\n");
>      }
> +#endif
>  
>      if (vpp->use_frc || vpp->use_crop || vpp->deinterlace || vpp->denoise ||
>          vpp->detail || vpp->procamp || vpp->rotate || vpp->hflip ||
> 
> base-commit: 242ed971cb005157488b9a21942d9fb4be4d0347

LGTM and applied, thx!

-Haihao
Soft Works Jan. 10, 2022, 7:17 a.m. UTC | #2
> -----Original Message-----
> From: Xiang, Haihao <haihao.xiang@intel.com>
> Sent: Monday, January 10, 2022 8:03 AM
> To: ffmpeg-devel@ffmpeg.org
> Cc: haihao.xiang-at-intel.com@ffmpeg.org; softworkz@hotmail.com
> Subject: Re: [FFmpeg-devel] [PATCH v4] avfilter/vpp_qsv: fix regression on
> older api versions (e.g. 1.11)
> 
> On Fri, 2022-01-07 at 07:01 +0000, ffmpegagent wrote:
> > From: softworkz <softworkz@hotmail.com>
> >
> > Commit 8b83dad82512a6948b63408f964463b063ad24c9 introduced a
> > regression in a way that scaling via vpp_qsv doesn't work any longer
> > for devices with an MSDK runtime version lower than 1.19. This is true
> > for older CPUs which are stuck at 1.11.
> > The commit added checks for the compile-sdk version but it didn't test
> > for the runtime version.
> >
> > Signed-off-by: softworkz <softworkz@hotmail.com>
> > ---
> >     avfilter/vpp_qsv: fix regression on older api versions (e.g. 1.11)
> >
> >     Fix a recently introduced regression when using QSV VPP.
> >
> >     v2: Fixed commit message wrapping
> >
> >     v3: Use different way to acquire runtime version
> >
> >     v4: Use mfxStatus as return type for get_mfx_version()
> >
> > Published-As:
> > https://github.com/ffstaging/FFmpeg/releases/tag/pr-ffstaging-
> 15%2Fsoftworkz%2Fqsv_vpp_regression-v4
> > Fetch-It-Via: git fetch https://github.com/ffstaging/FFmpeg pr-ffstaging-
> > 15/softworkz/qsv_vpp_regression-v4
> > Pull-Request: https://github.com/ffstaging/FFmpeg/pull/15
> >
> > Range-diff vs v3:
> >
> >  1:  cbf53d8ef4 ! 1:  bf53154420 avfilter/vpp_qsv: fix regression on older
> api
> > versions (e.g. 1.11)
> >      @@ libavfilter/vf_vpp_qsv.c: static int config_input(AVFilterLink
> > *inlink)
> >            return 0;
> >        }
> >
> >      -+static int get_mfx_version(const AVFilterContext *ctx, mfxVersion
> > *mfx_version)
> >      ++static mfxStatus get_mfx_version(const AVFilterContext *ctx,
> mfxVersion
> > *mfx_version)
> >       +{
> >       +    const AVFilterLink *inlink = ctx->inputs[0];
> >       +    AVBufferRef *device_ref;
> >      @@ libavfilter/vf_vpp_qsv.c: static int config_input(AVFilterLink
> > *inlink)
> >       +        // so don't error here but let runtime version checks fail
> by
> > setting to 0.0
> >       +        mfx_version->Major = 0;
> >       +        mfx_version->Minor = 0;
> >      -+        return 0;
> >      ++        return MFX_ERR_NONE;
> >       +    }
> >       +
> >       +    device_ctx   = (AVHWDeviceContext *)device_ref->data;
> >      @@ libavfilter/vf_vpp_qsv.c: static int config_output(AVFilterLink
> > *outlink)
> >            param.ext_buf       = ext_buf;
> >            param.async_depth   = vpp->async_depth;
> >
> >      -+    if (get_mfx_version(ctx, &mfx_version) < 0) {
> >      ++    if (get_mfx_version(ctx, &mfx_version) != MFX_ERR_NONE) {
> >       +        av_log(ctx, AV_LOG_ERROR, "Failed to query mfx version.\n");
> >       +        return AVERROR(EINVAL);
> >       +    }
> >
> >
> >  libavfilter/vf_vpp_qsv.c | 59 ++++++++++++++++++++++++++++++++--------
> >  1 file changed, 47 insertions(+), 12 deletions(-)
> >
> > diff --git a/libavfilter/vf_vpp_qsv.c b/libavfilter/vf_vpp_qsv.c
> > index ab58a5777e..5c96703fd3 100644
> > --- a/libavfilter/vf_vpp_qsv.c
> > +++ b/libavfilter/vf_vpp_qsv.c
> > @@ -26,6 +26,7 @@
> >  #include "libavutil/opt.h"
> >  #include "libavutil/eval.h"
> >  #include "libavutil/hwcontext.h"
> > +#include "libavutil/hwcontext_qsv.h"
> >  #include "libavutil/pixdesc.h"
> >  #include "libavutil/mathematics.h"
> >
> > @@ -139,8 +140,9 @@ static const AVOption options[] = {
> >      { "height", "Output video height", OFFSET(oh), AV_OPT_TYPE_STRING, {
> > .str="w*ch/cw" }, 0, 255, .flags = FLAGS },
> >      { "format", "Output pixel format", OFFSET(output_format_str),
> > AV_OPT_TYPE_STRING, { .str = "same" }, .flags = FLAGS },
> >      { "async_depth", "Internal parallelization depth, the higher the value
> > the higher the latency.", OFFSET(async_depth), AV_OPT_TYPE_INT, { .i64 = 0
> },
> > 0, INT_MAX, .flags = FLAGS },
> > +#ifdef QSV_HAVE_SCALING_CONFIG
> >      { "scale_mode", "scale mode: 0=auto, 1=low power, 2=high quality",
> > OFFSET(scale_mode), AV_OPT_TYPE_INT, { .i64 = MFX_SCALING_MODE_DEFAULT },
> > MFX_SCALING_MODE_DEFAULT, MFX_SCALING_MODE_QUALITY, .flags = FLAGS, "scale
> > mode" },
> > -
> > +#endif
> >      { NULL }
> >  };
> >
> > @@ -297,6 +299,32 @@ static int config_input(AVFilterLink *inlink)
> >      return 0;
> >  }
> >
> > +static mfxStatus get_mfx_version(const AVFilterContext *ctx, mfxVersion
> > *mfx_version)
> > +{
> > +    const AVFilterLink *inlink = ctx->inputs[0];
> > +    AVBufferRef *device_ref;
> > +    AVHWDeviceContext *device_ctx;
> > +    AVQSVDeviceContext *device_hwctx;
> > +
> > +    if (inlink->hw_frames_ctx) {
> > +        AVHWFramesContext *frames_ctx = (AVHWFramesContext *)inlink-
> > >hw_frames_ctx->data;
> > +        device_ref = frames_ctx->device_ref;
> > +    } else if (ctx->hw_device_ctx) {
> > +        device_ref = ctx->hw_device_ctx;
> > +    } else {
> > +        // Unavailable hw context doesn't matter in pass-through mode,
> > +        // so don't error here but let runtime version checks fail by
> setting
> > to 0.0
> > +        mfx_version->Major = 0;
> > +        mfx_version->Minor = 0;
> > +        return MFX_ERR_NONE;
> > +    }
> > +
> > +    device_ctx   = (AVHWDeviceContext *)device_ref->data;
> > +    device_hwctx = device_ctx->hwctx;
> > +
> > +    return MFXQueryVersion(device_hwctx->session, mfx_version);
> > +}
> > +
> >  static int config_output(AVFilterLink *outlink)
> >  {
> >      AVFilterContext *ctx = outlink->src;
> > @@ -304,6 +332,7 @@ static int config_output(AVFilterLink *outlink)
> >      QSVVPPParam     param = { NULL };
> >      QSVVPPCrop      crop  = { 0 };
> >      mfxExtBuffer    *ext_buf[ENH_FILTERS_COUNT];
> > +    mfxVersion      mfx_version;
> >      AVFilterLink    *inlink = ctx->inputs[0];
> >      enum AVPixelFormat in_format;
> >
> > @@ -317,6 +346,11 @@ static int config_output(AVFilterLink *outlink)
> >      param.ext_buf       = ext_buf;
> >      param.async_depth   = vpp->async_depth;
> >
> > +    if (get_mfx_version(ctx, &mfx_version) != MFX_ERR_NONE) {
> > +        av_log(ctx, AV_LOG_ERROR, "Failed to query mfx version.\n");
> > +        return AVERROR(EINVAL);
> > +    }
> > +
> >      if (inlink->format == AV_PIX_FMT_QSV) {
> >           if (!inlink->hw_frames_ctx || !inlink->hw_frames_ctx->data)
> >               return AVERROR(EINVAL);
> > @@ -467,19 +501,20 @@ static int config_output(AVFilterLink *outlink)
> >  #endif
> >      }
> >
> > -    if (inlink->w != outlink->w || inlink->h != outlink->h) {
> >  #ifdef QSV_HAVE_SCALING_CONFIG
> > -        memset(&vpp->scale_conf, 0, sizeof(mfxExtVPPScaling));
> > -        vpp->scale_conf.Header.BufferId    = MFX_EXTBUFF_VPP_SCALING;
> > -        vpp->scale_conf.Header.BufferSz    = sizeof(mfxExtVPPScaling);
> > -        vpp->scale_conf.ScalingMode        = vpp->scale_mode;
> > -
> > -        param.ext_buf[param.num_ext_buf++] = (mfxExtBuffer*)&vpp-
> >scale_conf;
> > -#else
> > -        av_log(ctx, AV_LOG_WARNING, "The QSV VPP Scale option is "
> > -            "not supported with this MSDK version.\n");
> > -#endif
> > +    if (inlink->w != outlink->w || inlink->h != outlink->h) {
> > +        if (QSV_RUNTIME_VERSION_ATLEAST(mfx_version, 1, 19)) {
> > +            memset(&vpp->scale_conf, 0, sizeof(mfxExtVPPScaling));
> > +            vpp->scale_conf.Header.BufferId    = MFX_EXTBUFF_VPP_SCALING;
> > +            vpp->scale_conf.Header.BufferSz    = sizeof(mfxExtVPPScaling);
> > +            vpp->scale_conf.ScalingMode        = vpp->scale_mode;
> > +
> > +            param.ext_buf[param.num_ext_buf++] = (mfxExtBuffer*)&vpp-
> > >scale_conf;
> > +        } else
> > +            av_log(ctx, AV_LOG_WARNING, "The QSV VPP Scale option is "
> > +                "not supported with this MSDK version.\n");
> >      }
> > +#endif
> >
> >      if (vpp->use_frc || vpp->use_crop || vpp->deinterlace || vpp->denoise
> ||
> >          vpp->detail || vpp->procamp || vpp->rotate || vpp->hflip ||
> >
> > base-commit: 242ed971cb005157488b9a21942d9fb4be4d0347
> 
> LGTM and applied, thx!
> 
> -Haihao
> 

Thanks
diff mbox series

Patch

diff --git a/libavfilter/vf_vpp_qsv.c b/libavfilter/vf_vpp_qsv.c
index ab58a5777e..5c96703fd3 100644
--- a/libavfilter/vf_vpp_qsv.c
+++ b/libavfilter/vf_vpp_qsv.c
@@ -26,6 +26,7 @@ 
 #include "libavutil/opt.h"
 #include "libavutil/eval.h"
 #include "libavutil/hwcontext.h"
+#include "libavutil/hwcontext_qsv.h"
 #include "libavutil/pixdesc.h"
 #include "libavutil/mathematics.h"
 
@@ -139,8 +140,9 @@  static const AVOption options[] = {
     { "height", "Output video height", OFFSET(oh), AV_OPT_TYPE_STRING, { .str="w*ch/cw" }, 0, 255, .flags = FLAGS },
     { "format", "Output pixel format", OFFSET(output_format_str), AV_OPT_TYPE_STRING, { .str = "same" }, .flags = FLAGS },
     { "async_depth", "Internal parallelization depth, the higher the value the higher the latency.", OFFSET(async_depth), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, .flags = FLAGS },
+#ifdef QSV_HAVE_SCALING_CONFIG
     { "scale_mode", "scale mode: 0=auto, 1=low power, 2=high quality", OFFSET(scale_mode), AV_OPT_TYPE_INT, { .i64 = MFX_SCALING_MODE_DEFAULT }, MFX_SCALING_MODE_DEFAULT, MFX_SCALING_MODE_QUALITY, .flags = FLAGS, "scale mode" },
-
+#endif
     { NULL }
 };
 
@@ -297,6 +299,32 @@  static int config_input(AVFilterLink *inlink)
     return 0;
 }
 
+static mfxStatus get_mfx_version(const AVFilterContext *ctx, mfxVersion *mfx_version)
+{
+    const AVFilterLink *inlink = ctx->inputs[0];
+    AVBufferRef *device_ref;
+    AVHWDeviceContext *device_ctx;
+    AVQSVDeviceContext *device_hwctx;
+
+    if (inlink->hw_frames_ctx) {
+        AVHWFramesContext *frames_ctx = (AVHWFramesContext *)inlink->hw_frames_ctx->data;
+        device_ref = frames_ctx->device_ref;
+    } else if (ctx->hw_device_ctx) {
+        device_ref = ctx->hw_device_ctx;
+    } else {
+        // Unavailable hw context doesn't matter in pass-through mode,
+        // so don't error here but let runtime version checks fail by setting to 0.0
+        mfx_version->Major = 0;
+        mfx_version->Minor = 0;
+        return MFX_ERR_NONE;
+    }
+
+    device_ctx   = (AVHWDeviceContext *)device_ref->data;
+    device_hwctx = device_ctx->hwctx;
+
+    return MFXQueryVersion(device_hwctx->session, mfx_version);
+}
+
 static int config_output(AVFilterLink *outlink)
 {
     AVFilterContext *ctx = outlink->src;
@@ -304,6 +332,7 @@  static int config_output(AVFilterLink *outlink)
     QSVVPPParam     param = { NULL };
     QSVVPPCrop      crop  = { 0 };
     mfxExtBuffer    *ext_buf[ENH_FILTERS_COUNT];
+    mfxVersion      mfx_version;
     AVFilterLink    *inlink = ctx->inputs[0];
     enum AVPixelFormat in_format;
 
@@ -317,6 +346,11 @@  static int config_output(AVFilterLink *outlink)
     param.ext_buf       = ext_buf;
     param.async_depth   = vpp->async_depth;
 
+    if (get_mfx_version(ctx, &mfx_version) != MFX_ERR_NONE) {
+        av_log(ctx, AV_LOG_ERROR, "Failed to query mfx version.\n");
+        return AVERROR(EINVAL);
+    }
+
     if (inlink->format == AV_PIX_FMT_QSV) {
          if (!inlink->hw_frames_ctx || !inlink->hw_frames_ctx->data)
              return AVERROR(EINVAL);
@@ -467,19 +501,20 @@  static int config_output(AVFilterLink *outlink)
 #endif
     }
 
-    if (inlink->w != outlink->w || inlink->h != outlink->h) {
 #ifdef QSV_HAVE_SCALING_CONFIG
-        memset(&vpp->scale_conf, 0, sizeof(mfxExtVPPScaling));
-        vpp->scale_conf.Header.BufferId    = MFX_EXTBUFF_VPP_SCALING;
-        vpp->scale_conf.Header.BufferSz    = sizeof(mfxExtVPPScaling);
-        vpp->scale_conf.ScalingMode        = vpp->scale_mode;
-
-        param.ext_buf[param.num_ext_buf++] = (mfxExtBuffer*)&vpp->scale_conf;
-#else
-        av_log(ctx, AV_LOG_WARNING, "The QSV VPP Scale option is "
-            "not supported with this MSDK version.\n");
-#endif
+    if (inlink->w != outlink->w || inlink->h != outlink->h) {
+        if (QSV_RUNTIME_VERSION_ATLEAST(mfx_version, 1, 19)) {
+            memset(&vpp->scale_conf, 0, sizeof(mfxExtVPPScaling));
+            vpp->scale_conf.Header.BufferId    = MFX_EXTBUFF_VPP_SCALING;
+            vpp->scale_conf.Header.BufferSz    = sizeof(mfxExtVPPScaling);
+            vpp->scale_conf.ScalingMode        = vpp->scale_mode;
+
+            param.ext_buf[param.num_ext_buf++] = (mfxExtBuffer*)&vpp->scale_conf;
+        } else
+            av_log(ctx, AV_LOG_WARNING, "The QSV VPP Scale option is "
+                "not supported with this MSDK version.\n");
     }
+#endif
 
     if (vpp->use_frc || vpp->use_crop || vpp->deinterlace || vpp->denoise ||
         vpp->detail || vpp->procamp || vpp->rotate || vpp->hflip ||