diff mbox series

[FFmpeg-devel,v3] libavcodec/qsvenc: Enable fixed QP configure in qsv CQP runtime

Message ID 20220623053242.360909-1-wenbin.chen@intel.com
State Accepted
Commit 53baf606038f710f0cbd3f19b3d416978b98167f
Headers show
Series [FFmpeg-devel,v3] libavcodec/qsvenc: Enable fixed QP configure in qsv CQP runtime | expand

Checks

Context Check Description
yinshiyou/configure_loongarch64 warning Failed to run configure
andriy/make_x86 success Make finished
andriy/make_fate_x86 success Make fate finished
andriy/make_armv7_RPi4 success Make finished
andriy/make_fate_armv7_RPi4 success Make fate finished

Commit Message

Chen, Wenbin June 23, 2022, 5:32 a.m. UTC
From: Yue Heng <yue.heng@intel.com>

Enable dynamic QP configuration in runtime on qsv encoder. Through
AVFrame->metadata, we can set key "qsv_config_qp" to change QP
configuration when we encode video in CQP mode.

Signed-off-by: Yue Heng <yue.heng@intel.com>
Signed-off-by: Wenbin Chen <wenbin.chen@intel.com>
---
 doc/encoders.texi   | 10 +++++
 libavcodec/qsvenc.c | 89 +++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 99 insertions(+)

Comments

Xiang, Haihao June 25, 2022, 2:47 a.m. UTC | #1
On Thu, 2022-06-23 at 13:32 +0800, Wenbin Chen wrote:
> From: Yue Heng <yue.heng@intel.com>
> 
> Enable dynamic QP configuration in runtime on qsv encoder. Through
> AVFrame->metadata, we can set key "qsv_config_qp" to change QP
> configuration when we encode video in CQP mode.
> 
> Signed-off-by: Yue Heng <yue.heng@intel.com>
> Signed-off-by: Wenbin Chen <wenbin.chen@intel.com>
> ---
>  doc/encoders.texi   | 10 +++++
>  libavcodec/qsvenc.c | 89 +++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 99 insertions(+)
> 
> diff --git a/doc/encoders.texi b/doc/encoders.texi
> index 1850c99fe9..02a91ffe96 100644
> --- a/doc/encoders.texi
> +++ b/doc/encoders.texi
> @@ -3333,6 +3333,16 @@ Forcing I frames as IDR frames.
>  For encoders set this flag to ON to reduce power consumption and GPU usage.
>  @end table
>  
> +@subsection Runtime Options
> +Following options can be used durning qsv encoding.
> +
> +@table @option
> +@item @var{qsv_config_qp}
> +Supported in h264_qsv and hevc_qsv.
> +This option can be set in per-frame metadata. QP parameter can be dynamically
> +changed when encoding in CQP mode.
> +@end table
> +
>  @subsection H264 options
>  These options are used by h264_qsv
>  
> diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c
> index 902bada55b..2382c2f5f7 100644
> --- a/libavcodec/qsvenc.c
> +++ b/libavcodec/qsvenc.c
> @@ -146,6 +146,14 @@ static const struct {
>      { MFX_RATECONTROL_QVBR,    "QVBR" },
>  };
>  
> +#define UPDATE_PARAM(a, b)  \
> +do {                        \
> +    if ((a) != (b)) {       \
> +        a = b;              \
> +        updated = 1;        \
> +    }                       \
> +} while (0)                 \
> +
>  static const char *print_ratecontrol(mfxU16 rc_mode)
>  {
>      int i;
> @@ -1613,6 +1621,83 @@ static int set_roi_encode_ctrl(AVCodecContext *avctx,
> const AVFrame *frame,
>      return 0;
>  }
>  
> +static int update_qp(AVCodecContext *avctx, QSVEncContext *q,
> +                     const AVFrame *frame)
> +{
> +    int updated = 0, qp = 0, new_qp;
> +    char *tail;
> +    AVDictionaryEntry *entry = NULL;
> +
> +    if (avctx->codec_id != AV_CODEC_ID_H264 && avctx->codec_id !=
> AV_CODEC_ID_HEVC)
> +        return 0;
> +
> +    entry = av_dict_get(frame->metadata, "qsv_config_qp", NULL, 0);
> +    if (entry && q->param.mfx.RateControlMethod == MFX_RATECONTROL_CQP) {
> +        qp = strtol(entry->value, &tail, 10);
> +        if (*tail) {
> +            av_log(avctx, AV_LOG_WARNING, "Invalid qsv_config_qp string.
> Ignore this metadata\n");
> +            return 0;
> +        }
> +        if (qp < 0 || qp > 51) {
> +            av_log(avctx, AV_LOG_WARNING, "Invalid qp, clip to 0 ~ 51\n");
> +            qp = av_clip(qp, 0, 51);
> +        }
> +        av_log(avctx, AV_LOG_DEBUG, "Configure qp: %d\n",qp);
> +        UPDATE_PARAM(q->param.mfx.QPP, qp);
> +        new_qp = av_clip(qp * fabs(avctx->i_quant_factor) +
> +                            avctx->i_quant_offset, 0, 51);
> +        UPDATE_PARAM(q->param.mfx.QPI, new_qp);
> +        new_qp = av_clip(qp * fabs(avctx->b_quant_factor) +
> +                            avctx->b_quant_offset, 0, 51);
> +        UPDATE_PARAM(q->param.mfx.QPB, new_qp);
> +        av_log(avctx, AV_LOG_DEBUG,
> +                "using fixed qp = %d/%d/%d for idr/p/b frames\n",
> +                q->param.mfx.QPI, q->param.mfx.QPP, q->param.mfx.QPB);
> +    }
> +    return updated;
> +}
> +
> +static int update_parameters(AVCodecContext *avctx, QSVEncContext *q,
> +                             const AVFrame *frame)
> +{
> +    int needReset = 0, ret = 0;
> +
> +    if (!frame)
> +        return 0;
> +
> +    needReset = update_qp(avctx, q, frame);
> +    if (!needReset)
> +        return 0;
> +
> +    if (avctx->hwaccel_context) {
> +        AVQSVContext *qsv = avctx->hwaccel_context;
> +        int i, j;
> +        q->param.ExtParam = q->extparam;
> +        for (i = 0; i < qsv->nb_ext_buffers; i++)
> +            q->param.ExtParam[i] = qsv->ext_buffers[i];
> +        q->param.NumExtParam = qsv->nb_ext_buffers;
> +
> +        for (i = 0; i < q->nb_extparam_internal; i++) {
> +            for (j = 0; j < qsv->nb_ext_buffers; j++) {
> +                if (qsv->ext_buffers[j]->BufferId == q->extparam_internal[i]-
> >BufferId)
> +                    break;
> +            }
> +            if (j < qsv->nb_ext_buffers)
> +                continue;
> +            q->param.ExtParam[q->param.NumExtParam++] = q-
> >extparam_internal[i];
> +        }
> +    } else {
> +        q->param.ExtParam    = q->extparam_internal;
> +        q->param.NumExtParam = q->nb_extparam_internal;
> +    }
> +    av_log(avctx, AV_LOG_DEBUG, "Parameter change, call msdk reset.\n");
> +    ret = MFXVideoENCODE_Reset(q->session, &q->param);
> +    if (ret < 0)
> +        return ff_qsv_print_error(avctx, ret, "Error during resetting");
> +
> +    return 0;
> +}
> +
>  static int encode_frame(AVCodecContext *avctx, QSVEncContext *q,
>                          const AVFrame *frame)
>  {
> @@ -1731,6 +1816,10 @@ int ff_qsv_encode(AVCodecContext *avctx, QSVEncContext
> *q,
>  {
>      int ret;
>  
> +    ret = update_parameters(avctx, q, frame);
> +    if (ret < 0)
> +        return ret;
> +
>      ret = encode_frame(avctx, q, frame);
>      if (ret < 0)
>          return ret;

LGTM, will apply.

-Haihao
Anton Khirnov July 2, 2022, 9:39 a.m. UTC | #2
Quoting Wenbin Chen (2022-06-23 07:32:42)
> From: Yue Heng <yue.heng@intel.com>
> 
> Enable dynamic QP configuration in runtime on qsv encoder. Through
> AVFrame->metadata, we can set key "qsv_config_qp" to change QP
> configuration when we encode video in CQP mode.
> 
> Signed-off-by: Yue Heng <yue.heng@intel.com>
> Signed-off-by: Wenbin Chen <wenbin.chen@intel.com>
> ---
>  doc/encoders.texi   | 10 +++++
>  libavcodec/qsvenc.c | 89 +++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 99 insertions(+)
> 
> diff --git a/doc/encoders.texi b/doc/encoders.texi
> index 1850c99fe9..02a91ffe96 100644
> --- a/doc/encoders.texi
> +++ b/doc/encoders.texi
> @@ -3333,6 +3333,16 @@ Forcing I frames as IDR frames.
>  For encoders set this flag to ON to reduce power consumption and GPU usage.
>  @end table
>  
> +@subsection Runtime Options
> +Following options can be used durning qsv encoding.
> +
> +@table @option
> +@item @var{qsv_config_qp}
> +Supported in h264_qsv and hevc_qsv.
> +This option can be set in per-frame metadata. QP parameter can be dynamically
> +changed when encoding in CQP mode.
> +@end table
> +
>  @subsection H264 options
>  These options are used by h264_qsv
>  
> diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c
> index 902bada55b..2382c2f5f7 100644
> --- a/libavcodec/qsvenc.c
> +++ b/libavcodec/qsvenc.c
> @@ -146,6 +146,14 @@ static const struct {
>      { MFX_RATECONTROL_QVBR,    "QVBR" },
>  };
>  
> +#define UPDATE_PARAM(a, b)  \
> +do {                        \
> +    if ((a) != (b)) {       \
> +        a = b;              \
> +        updated = 1;        \
> +    }                       \
> +} while (0)                 \
> +
>  static const char *print_ratecontrol(mfxU16 rc_mode)
>  {
>      int i;
> @@ -1613,6 +1621,83 @@ static int set_roi_encode_ctrl(AVCodecContext *avctx, const AVFrame *frame,
>      return 0;
>  }
>  
> +static int update_qp(AVCodecContext *avctx, QSVEncContext *q,
> +                     const AVFrame *frame)
> +{
> +    int updated = 0, qp = 0, new_qp;
> +    char *tail;
> +    AVDictionaryEntry *entry = NULL;
> +
> +    if (avctx->codec_id != AV_CODEC_ID_H264 && avctx->codec_id != AV_CODEC_ID_HEVC)
> +        return 0;
> +
> +    entry = av_dict_get(frame->metadata, "qsv_config_qp", NULL, 0);

Why is this using frame metadata rather than the AVVideoEncParams side
data?

Frame metadata should not be used in encoders at all. Longer term it
should not be used at all by anything.
Paul B Mahol July 2, 2022, 2:21 p.m. UTC | #3
On Sat, Jul 2, 2022 at 11:39 AM Anton Khirnov <anton@khirnov.net> wrote:

> Quoting Wenbin Chen (2022-06-23 07:32:42)
> > From: Yue Heng <yue.heng@intel.com>
> >
> > Enable dynamic QP configuration in runtime on qsv encoder. Through
> > AVFrame->metadata, we can set key "qsv_config_qp" to change QP
> > configuration when we encode video in CQP mode.
> >
> > Signed-off-by: Yue Heng <yue.heng@intel.com>
> > Signed-off-by: Wenbin Chen <wenbin.chen@intel.com>
> > ---
> >  doc/encoders.texi   | 10 +++++
> >  libavcodec/qsvenc.c | 89 +++++++++++++++++++++++++++++++++++++++++++++
> >  2 files changed, 99 insertions(+)
> >
> > diff --git a/doc/encoders.texi b/doc/encoders.texi
> > index 1850c99fe9..02a91ffe96 100644
> > --- a/doc/encoders.texi
> > +++ b/doc/encoders.texi
> > @@ -3333,6 +3333,16 @@ Forcing I frames as IDR frames.
> >  For encoders set this flag to ON to reduce power consumption and GPU
> usage.
> >  @end table
> >
> > +@subsection Runtime Options
> > +Following options can be used durning qsv encoding.
> > +
> > +@table @option
> > +@item @var{qsv_config_qp}
> > +Supported in h264_qsv and hevc_qsv.
> > +This option can be set in per-frame metadata. QP parameter can be
> dynamically
> > +changed when encoding in CQP mode.
> > +@end table
> > +
> >  @subsection H264 options
> >  These options are used by h264_qsv
> >
> > diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c
> > index 902bada55b..2382c2f5f7 100644
> > --- a/libavcodec/qsvenc.c
> > +++ b/libavcodec/qsvenc.c
> > @@ -146,6 +146,14 @@ static const struct {
> >      { MFX_RATECONTROL_QVBR,    "QVBR" },
> >  };
> >
> > +#define UPDATE_PARAM(a, b)  \
> > +do {                        \
> > +    if ((a) != (b)) {       \
> > +        a = b;              \
> > +        updated = 1;        \
> > +    }                       \
> > +} while (0)                 \
> > +
> >  static const char *print_ratecontrol(mfxU16 rc_mode)
> >  {
> >      int i;
> > @@ -1613,6 +1621,83 @@ static int set_roi_encode_ctrl(AVCodecContext
> *avctx, const AVFrame *frame,
> >      return 0;
> >  }
> >
> > +static int update_qp(AVCodecContext *avctx, QSVEncContext *q,
> > +                     const AVFrame *frame)
> > +{
> > +    int updated = 0, qp = 0, new_qp;
> > +    char *tail;
> > +    AVDictionaryEntry *entry = NULL;
> > +
> > +    if (avctx->codec_id != AV_CODEC_ID_H264 && avctx->codec_id !=
> AV_CODEC_ID_HEVC)
> > +        return 0;
> > +
> > +    entry = av_dict_get(frame->metadata, "qsv_config_qp", NULL, 0);
>
> Why is this using frame metadata rather than the AVVideoEncParams side
> data?
>
> Frame metadata should not be used in encoders at all. Longer term it
> should not be used at all by anything.
>

Disagreed. Stop sharing your agenda.


>
> --
> Anton Khirnov
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
>
Chen, Wenbin July 4, 2022, 6:33 a.m. UTC | #4
> Quoting Wenbin Chen (2022-06-23 07:32:42)
> > From: Yue Heng <yue.heng@intel.com>
> >
> > Enable dynamic QP configuration in runtime on qsv encoder. Through
> > AVFrame->metadata, we can set key "qsv_config_qp" to change QP
> > configuration when we encode video in CQP mode.
> >
> > Signed-off-by: Yue Heng <yue.heng@intel.com>
> > Signed-off-by: Wenbin Chen <wenbin.chen@intel.com>
> > ---
> >  doc/encoders.texi   | 10 +++++
> >  libavcodec/qsvenc.c | 89
> +++++++++++++++++++++++++++++++++++++++++++++
> >  2 files changed, 99 insertions(+)
> >
> > diff --git a/doc/encoders.texi b/doc/encoders.texi
> > index 1850c99fe9..02a91ffe96 100644
> > --- a/doc/encoders.texi
> > +++ b/doc/encoders.texi
> > @@ -3333,6 +3333,16 @@ Forcing I frames as IDR frames.
> >  For encoders set this flag to ON to reduce power consumption and GPU
> usage.
> >  @end table
> >
> > +@subsection Runtime Options
> > +Following options can be used durning qsv encoding.
> > +
> > +@table @option
> > +@item @var{qsv_config_qp}
> > +Supported in h264_qsv and hevc_qsv.
> > +This option can be set in per-frame metadata. QP parameter can be
> dynamically
> > +changed when encoding in CQP mode.
> > +@end table
> > +
> >  @subsection H264 options
> >  These options are used by h264_qsv
> >
> > diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c
> > index 902bada55b..2382c2f5f7 100644
> > --- a/libavcodec/qsvenc.c
> > +++ b/libavcodec/qsvenc.c
> > @@ -146,6 +146,14 @@ static const struct {
> >      { MFX_RATECONTROL_QVBR,    "QVBR" },
> >  };
> >
> > +#define UPDATE_PARAM(a, b)  \
> > +do {                        \
> > +    if ((a) != (b)) {       \
> > +        a = b;              \
> > +        updated = 1;        \
> > +    }                       \
> > +} while (0)                 \
> > +
> >  static const char *print_ratecontrol(mfxU16 rc_mode)
> >  {
> >      int i;
> > @@ -1613,6 +1621,83 @@ static int set_roi_encode_ctrl(AVCodecContext
> *avctx, const AVFrame *frame,
> >      return 0;
> >  }
> >
> > +static int update_qp(AVCodecContext *avctx, QSVEncContext *q,
> > +                     const AVFrame *frame)
> > +{
> > +    int updated = 0, qp = 0, new_qp;
> > +    char *tail;
> > +    AVDictionaryEntry *entry = NULL;
> > +
> > +    if (avctx->codec_id != AV_CODEC_ID_H264 && avctx->codec_id !=
> AV_CODEC_ID_HEVC)
> > +        return 0;
> > +
> > +    entry = av_dict_get(frame->metadata, "qsv_config_qp", NULL, 0);
> 
> Why is this using frame metadata rather than the AVVideoEncParams side
> data?

The usage of AVVideoEncParams relates to the "qp" variable in mfxEncodeCtrl which is passed
to MFXVideoENCODE_encoderFrameAsync(). This variable in qsv is for per-frame QP
configuration.
There are other parameter changing supports I want to add besides QP, for
example, gop_size, max_frame_size, intra_refresh. These parameter configurations are not
all included in mfxEncodeCtrl, so I choose to use MFXVideoENCODE_Reset() to do this. This
code changes the encoding parameters which means these changes are applied to all
the following frames, but AVVideoEncParams is per-frame configuration, so I think
AVVideoEncParams is not suitable for this.

> 
> Frame metadata should not be used in encoders at all. Longer term it
> should not be used at all by anything.
> 
> --
> Anton Khirnov
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
> 
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
Anton Khirnov July 4, 2022, 6:45 a.m. UTC | #5
Quoting Chen, Wenbin (2022-07-04 08:33:49)
> > Why is this using frame metadata rather than the AVVideoEncParams side
> > data?
> 
> The usage of AVVideoEncParams relates to the "qp" variable in mfxEncodeCtrl which is passed
> to MFXVideoENCODE_encoderFrameAsync(). This variable in qsv is for per-frame QP
> configuration.
> There are other parameter changing supports I want to add besides QP, for
> example, gop_size, max_frame_size, intra_refresh. These parameter configurations are not
> all included in mfxEncodeCtrl, so I choose to use MFXVideoENCODE_Reset() to do this. This
> code changes the encoding parameters which means these changes are applied to all
> the following frames, but AVVideoEncParams is per-frame configuration, so I think
> AVVideoEncParams is not suitable for this.

AVFrame metadata is also per-frame, so your logic does not make sense to
me.

You could also just update the AVCodecContext/private context values
directly or using AVOptions.
Chen, Wenbin July 4, 2022, 8:40 a.m. UTC | #6
> Quoting Chen, Wenbin (2022-07-04 08:33:49)
> > > Why is this using frame metadata rather than the AVVideoEncParams
> side
> > > data?
> >
> > The usage of AVVideoEncParams relates to the "qp" variable in
> mfxEncodeCtrl which is passed
> > to MFXVideoENCODE_encoderFrameAsync(). This variable in qsv is for per-
> frame QP
> > configuration.
> > There are other parameter changing supports I want to add besides QP, for
> > example, gop_size, max_frame_size, intra_refresh. These parameter
> configurations are not
> > all included in mfxEncodeCtrl, so I choose to use MFXVideoENCODE_Reset()
> to do this. This
> > code changes the encoding parameters which means these changes are
> applied to all
> > the following frames, but AVVideoEncParams is per-frame configuration,
> so I think
> > AVVideoEncParams is not suitable for this.
> 
> AVFrame metadata is also per-frame, so your logic does not make sense to
> me.
> 
> You could also just update the AVCodecContext/private context values
> directly or using AVOptions.

This is a possible way. I will change it. Thanks for your advice.

> 
> --
> Anton Khirnov
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
> 
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
diff mbox series

Patch

diff --git a/doc/encoders.texi b/doc/encoders.texi
index 1850c99fe9..02a91ffe96 100644
--- a/doc/encoders.texi
+++ b/doc/encoders.texi
@@ -3333,6 +3333,16 @@  Forcing I frames as IDR frames.
 For encoders set this flag to ON to reduce power consumption and GPU usage.
 @end table
 
+@subsection Runtime Options
+Following options can be used durning qsv encoding.
+
+@table @option
+@item @var{qsv_config_qp}
+Supported in h264_qsv and hevc_qsv.
+This option can be set in per-frame metadata. QP parameter can be dynamically
+changed when encoding in CQP mode.
+@end table
+
 @subsection H264 options
 These options are used by h264_qsv
 
diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c
index 902bada55b..2382c2f5f7 100644
--- a/libavcodec/qsvenc.c
+++ b/libavcodec/qsvenc.c
@@ -146,6 +146,14 @@  static const struct {
     { MFX_RATECONTROL_QVBR,    "QVBR" },
 };
 
+#define UPDATE_PARAM(a, b)  \
+do {                        \
+    if ((a) != (b)) {       \
+        a = b;              \
+        updated = 1;        \
+    }                       \
+} while (0)                 \
+
 static const char *print_ratecontrol(mfxU16 rc_mode)
 {
     int i;
@@ -1613,6 +1621,83 @@  static int set_roi_encode_ctrl(AVCodecContext *avctx, const AVFrame *frame,
     return 0;
 }
 
+static int update_qp(AVCodecContext *avctx, QSVEncContext *q,
+                     const AVFrame *frame)
+{
+    int updated = 0, qp = 0, new_qp;
+    char *tail;
+    AVDictionaryEntry *entry = NULL;
+
+    if (avctx->codec_id != AV_CODEC_ID_H264 && avctx->codec_id != AV_CODEC_ID_HEVC)
+        return 0;
+
+    entry = av_dict_get(frame->metadata, "qsv_config_qp", NULL, 0);
+    if (entry && q->param.mfx.RateControlMethod == MFX_RATECONTROL_CQP) {
+        qp = strtol(entry->value, &tail, 10);
+        if (*tail) {
+            av_log(avctx, AV_LOG_WARNING, "Invalid qsv_config_qp string. Ignore this metadata\n");
+            return 0;
+        }
+        if (qp < 0 || qp > 51) {
+            av_log(avctx, AV_LOG_WARNING, "Invalid qp, clip to 0 ~ 51\n");
+            qp = av_clip(qp, 0, 51);
+        }
+        av_log(avctx, AV_LOG_DEBUG, "Configure qp: %d\n",qp);
+        UPDATE_PARAM(q->param.mfx.QPP, qp);
+        new_qp = av_clip(qp * fabs(avctx->i_quant_factor) +
+                            avctx->i_quant_offset, 0, 51);
+        UPDATE_PARAM(q->param.mfx.QPI, new_qp);
+        new_qp = av_clip(qp * fabs(avctx->b_quant_factor) +
+                            avctx->b_quant_offset, 0, 51);
+        UPDATE_PARAM(q->param.mfx.QPB, new_qp);
+        av_log(avctx, AV_LOG_DEBUG,
+                "using fixed qp = %d/%d/%d for idr/p/b frames\n",
+                q->param.mfx.QPI, q->param.mfx.QPP, q->param.mfx.QPB);
+    }
+    return updated;
+}
+
+static int update_parameters(AVCodecContext *avctx, QSVEncContext *q,
+                             const AVFrame *frame)
+{
+    int needReset = 0, ret = 0;
+
+    if (!frame)
+        return 0;
+
+    needReset = update_qp(avctx, q, frame);
+    if (!needReset)
+        return 0;
+
+    if (avctx->hwaccel_context) {
+        AVQSVContext *qsv = avctx->hwaccel_context;
+        int i, j;
+        q->param.ExtParam = q->extparam;
+        for (i = 0; i < qsv->nb_ext_buffers; i++)
+            q->param.ExtParam[i] = qsv->ext_buffers[i];
+        q->param.NumExtParam = qsv->nb_ext_buffers;
+
+        for (i = 0; i < q->nb_extparam_internal; i++) {
+            for (j = 0; j < qsv->nb_ext_buffers; j++) {
+                if (qsv->ext_buffers[j]->BufferId == q->extparam_internal[i]->BufferId)
+                    break;
+            }
+            if (j < qsv->nb_ext_buffers)
+                continue;
+            q->param.ExtParam[q->param.NumExtParam++] = q->extparam_internal[i];
+        }
+    } else {
+        q->param.ExtParam    = q->extparam_internal;
+        q->param.NumExtParam = q->nb_extparam_internal;
+    }
+    av_log(avctx, AV_LOG_DEBUG, "Parameter change, call msdk reset.\n");
+    ret = MFXVideoENCODE_Reset(q->session, &q->param);
+    if (ret < 0)
+        return ff_qsv_print_error(avctx, ret, "Error during resetting");
+
+    return 0;
+}
+
 static int encode_frame(AVCodecContext *avctx, QSVEncContext *q,
                         const AVFrame *frame)
 {
@@ -1731,6 +1816,10 @@  int ff_qsv_encode(AVCodecContext *avctx, QSVEncContext *q,
 {
     int ret;
 
+    ret = update_parameters(avctx, q, frame);
+    if (ret < 0)
+        return ret;
+
     ret = encode_frame(avctx, q, frame);
     if (ret < 0)
         return ret;