[FFmpeg-devel] [PATCH v5] lavc/qsvenc: enable QVBR mode
Zhong Li
zhong.li at intel.com
Wed Jan 23 13:16:17 EET 2019
QVBR mode is to use the variable bitrate control algorithm
with constant quality.
mfxExtCodingOption3 should be supported to enable QVBR mode.
Example usage: ffmpeg -hwaccel qsv -c:v h264_qsv -i input.mp4 -c:v
h264_qsv -global_quality 25 -maxrate 2M test_qvbr.mp4 -v verbose
Clip QVBR quality range to be [0, 51] as Mark's commments.
It is similar to qp range of CQP but possibly should be updated when VP8/VP9
encoding can be supported.
Reviewed-by: Mark Thompson <sw at jkqxz.net>
Signed-off-by: Zhong Li <zhong.li at intel.com>
---
libavcodec/qsvenc.c | 39 +++++++++++++++++++++++++++++++++++++--
libavcodec/qsvenc.h | 7 +++++--
2 files changed, 42 insertions(+), 4 deletions(-)
diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c
index ba9bcf1..5aa020d 100644
--- a/libavcodec/qsvenc.c
+++ b/libavcodec/qsvenc.c
@@ -136,6 +136,9 @@ static void dump_video_param(AVCodecContext *avctx, QSVEncContext *q,
#if QSV_HAVE_CO2
mfxExtCodingOption2 *co2 = (mfxExtCodingOption2*)coding_opts[1];
#endif
+#if QSV_HAVE_CO3
+ mfxExtCodingOption3 *co3 = (mfxExtCodingOption3*)coding_opts[2];
+#endif
av_log(avctx, AV_LOG_VERBOSE, "profile: %s; level: %"PRIu16"\n",
print_profile(info->CodecProfile), info->CodecLevel);
@@ -190,7 +193,12 @@ static void dump_video_param(AVCodecContext *avctx, QSVEncContext *q,
info->ICQQuality, co2->LookAheadDepth);
}
#endif
-
+#if QSV_HAVE_QVBR
+ else if (info->RateControlMethod == MFX_RATECONTROL_QVBR) {
+ av_log(avctx, AV_LOG_VERBOSE, "QVBRQuality: %"PRIu16"\n",
+ co3->QVBRQuality);
+ }
+#endif
av_log(avctx, AV_LOG_VERBOSE, "NumSlice: %"PRIu16"; NumRefFrame: %"PRIu16"\n",
info->NumSlice, info->NumRefFrame);
av_log(avctx, AV_LOG_VERBOSE, "RateDistortionOpt: %s\n",
@@ -330,7 +338,7 @@ static int select_rc_mode(AVCodecContext *avctx, QSVEncContext *q)
}
#endif
#if QSV_HAVE_ICQ
- else if (avctx->global_quality > 0) {
+ else if (avctx->global_quality > 0 && !avctx->rc_max_rate) {
rc_mode = MFX_RATECONTROL_ICQ;
rc_desc = "intelligent constant quality (ICQ)";
}
@@ -345,6 +353,12 @@ static int select_rc_mode(AVCodecContext *avctx, QSVEncContext *q)
rc_desc = "average variable bitrate (AVBR)";
}
#endif
+#if QSV_HAVE_QVBR
+ else if (avctx->global_quality > 0) {
+ rc_mode = MFX_RATECONTROL_QVBR;
+ rc_desc = "constant quality with VBR algorithm (QVBR)";
+ }
+#endif
else {
rc_mode = MFX_RATECONTROL_VBR;
rc_desc = "variable bitrate (VBR)";
@@ -568,11 +582,18 @@ static int init_video_param(AVCodecContext *avctx, QSVEncContext *q)
#if QSV_HAVE_VCM
case MFX_RATECONTROL_VCM:
#endif
+#if QSV_HAVE_QVBR
+ case MFX_RATECONTROL_QVBR:
+#endif
q->param.mfx.BufferSizeInKB = buffer_size_in_kilobytes / brc_param_multiplier;
q->param.mfx.InitialDelayInKB = initial_delay_in_kilobytes / brc_param_multiplier;
q->param.mfx.TargetKbps = target_bitrate_kbps / brc_param_multiplier;
q->param.mfx.MaxKbps = max_bitrate_kbps / brc_param_multiplier;
q->param.mfx.BRCParamMultiplier = brc_param_multiplier;
+#if QSV_HAVE_QVBR
+ if (q->param.mfx.RateControlMethod == MFX_RATECONTROL_QVBR)
+ q->extco3.QVBRQuality = av_clip(avctx->global_quality, 0, 51);
+#endif
break;
case MFX_RATECONTROL_CQP:
quant = avctx->global_quality / FF_QP2LAMBDA;
@@ -718,6 +739,11 @@ FF_ENABLE_DEPRECATION_WARNINGS
}
#endif
}
+#if QSV_HAVE_CO3
+ q->extco3.Header.BufferId = MFX_EXTBUFF_CODING_OPTION3;
+ q->extco3.Header.BufferSz = sizeof(q->extco3);
+ q->extparam_internal[q->nb_extparam_internal++] = (mfxExtBuffer *)&q->extco3;
+#endif
}
if (!check_enc_param(avctx,q)) {
@@ -772,6 +798,12 @@ static int qsv_retrieve_enc_params(AVCodecContext *avctx, QSVEncContext *q)
.Header.BufferSz = sizeof(co2),
};
#endif
+#if QSV_HAVE_CO3
+ mfxExtCodingOption3 co3 = {
+ .Header.BufferId = MFX_EXTBUFF_CODING_OPTION3,
+ .Header.BufferSz = sizeof(co3),
+ };
+#endif
mfxExtBuffer *ext_buffers[] = {
(mfxExtBuffer*)&extradata,
@@ -779,6 +811,9 @@ static int qsv_retrieve_enc_params(AVCodecContext *avctx, QSVEncContext *q)
#if QSV_HAVE_CO2
(mfxExtBuffer*)&co2,
#endif
+#if QSV_HAVE_CO3
+ (mfxExtBuffer*)&co3,
+#endif
};
int need_pps = avctx->codec_id != AV_CODEC_ID_MPEG2VIDEO;
diff --git a/libavcodec/qsvenc.h b/libavcodec/qsvenc.h
index 47a70a4..00afbd8 100644
--- a/libavcodec/qsvenc.h
+++ b/libavcodec/qsvenc.h
@@ -56,7 +56,7 @@
#define QSV_HAVE_AVBR 0
#define QSV_HAVE_ICQ QSV_VERSION_ATLEAST(1, 28)
#define QSV_HAVE_VCM 0
-#define QSV_HAVE_QVBR 0
+#define QSV_HAVE_QVBR QSV_VERSION_ATLEAST(1, 28)
#define QSV_HAVE_MF QSV_VERSION_ATLEAST(1, 25)
#endif
@@ -111,6 +111,9 @@ typedef struct QSVEncContext {
#if QSV_HAVE_CO2
mfxExtCodingOption2 extco2;
#endif
+#if QSV_HAVE_CO3
+ mfxExtCodingOption3 extco3;
+#endif
#if QSV_HAVE_MF
mfxExtMultiFrameParam extmfp;
mfxExtMultiFrameControl extmfc;
@@ -119,7 +122,7 @@ typedef struct QSVEncContext {
mfxFrameSurface1 **opaque_surfaces;
AVBufferRef *opaque_alloc_buf;
- mfxExtBuffer *extparam_internal[2 + QSV_HAVE_CO2 + (QSV_HAVE_MF * 2)];
+ mfxExtBuffer *extparam_internal[2 + QSV_HAVE_CO2 + QSV_HAVE_CO3 + (QSV_HAVE_MF * 2)];
int nb_extparam_internal;
mfxExtBuffer **extparam;
--
2.7.4
More information about the ffmpeg-devel
mailing list