}
}
- static int init_video_param(AVCodecContext *avctx, QSVEncContext *q)
+ static int select_rc_mode(AVCodecContext *avctx, QSVEncContext *q)
{
- const char *ratecontrol_desc;
+ const char *rc_desc;
+ mfxU16 rc_mode;
+
- int want_la = q->la_depth >= 0;
++ int want_la = q->look_ahead;
+ int want_qscale = !!(avctx->flags & AV_CODEC_FLAG_QSCALE);
+ int want_vcm = q->vcm;
+
+ if (want_la && !QSV_HAVE_LA) {
+ av_log(avctx, AV_LOG_ERROR,
+ "Lookahead ratecontrol mode requested, but is not supported by this SDK version\n");
+ return AVERROR(ENOSYS);
+ }
+ if (want_vcm && !QSV_HAVE_VCM) {
+ av_log(avctx, AV_LOG_ERROR,
+ "VCM ratecontrol mode requested, but is not supported by this SDK version\n");
+ return AVERROR(ENOSYS);
+ }
+
+ if (want_la + want_qscale + want_vcm > 1) {
+ av_log(avctx, AV_LOG_ERROR,
+ "More than one of: { constant qscale, lookahead, VCM } requested, "
+ "only one of them can be used at a time.\n");
+ return AVERROR(EINVAL);
+ }
+ if (want_qscale) {
+ rc_mode = MFX_RATECONTROL_CQP;
+ rc_desc = "constant quantization parameter (CQP)";
+ }
+ #if QSV_HAVE_VCM
+ else if (want_vcm) {
+ rc_mode = MFX_RATECONTROL_VCM;
+ rc_desc = "video conferencing mode (VCM)";
+ }
+ #endif
+ #if QSV_HAVE_LA
+ else if (want_la) {
+ rc_mode = MFX_RATECONTROL_LA;
+ rc_desc = "VBR with lookahead (LA)";
+
+ #if QSV_HAVE_ICQ
+ if (avctx->global_quality > 0) {
+ rc_mode = MFX_RATECONTROL_LA_ICQ;
+ rc_desc = "intelligent constant quality with lookahead (LA_ICQ)";
+ }
+ #endif
+ }
+ #endif
+ #if QSV_HAVE_ICQ
+ else if (avctx->global_quality > 0) {
+ rc_mode = MFX_RATECONTROL_ICQ;
+ rc_desc = "intelligent constant quality (ICQ)";
+ }
+ #endif
+ else if (avctx->rc_max_rate == avctx->bit_rate) {
+ rc_mode = MFX_RATECONTROL_CBR;
+ rc_desc = "constant bitrate (CBR)";
+ } else if (!avctx->rc_max_rate) {
+ rc_mode = MFX_RATECONTROL_AVBR;
+ rc_desc = "average variable bitrate (AVBR)";
+ } else {
+ rc_mode = MFX_RATECONTROL_VBR;
+ rc_desc = "variable bitrate (VBR)";
+ }
+
+ q->param.mfx.RateControlMethod = rc_mode;
+ av_log(avctx, AV_LOG_VERBOSE, "Using the %s ratecontrol method\n", rc_desc);
+
+ return 0;
+ }
+
+ static int rc_supported(QSVEncContext *q)
+ {
+ mfxVideoParam param_out = { .mfx.CodecId = q->param.mfx.CodecId };
+ mfxStatus ret;
+
+ ret = MFXVideoENCODE_Query(q->session, &q->param, ¶m_out);
+ if (ret < 0 ||
+ param_out.mfx.RateControlMethod != q->param.mfx.RateControlMethod)
+ return 0;
+ return 1;
+ }
+
+ static int init_video_param(AVCodecContext *avctx, QSVEncContext *q)
+ {
float quant;
int ret;
q->param.mfx.Convergence = q->avbr_convergence;
q->param.mfx.Accuracy = q->avbr_accuracy;
break;
- q->extco2.LookAheadDepth = q->la_depth;
+ #if QSV_HAVE_LA
+ case MFX_RATECONTROL_LA:
+ q->param.mfx.TargetKbps = avctx->bit_rate / 1000;
- q->extco2.LookAheadDepth = q->la_depth;
++ q->extco2.LookAheadDepth = q->look_ahead_depth;
+ break;
+ #if QSV_HAVE_ICQ
+ case MFX_RATECONTROL_LA_ICQ:
++ q->extco2.LookAheadDepth = q->look_ahead_depth;
+ case MFX_RATECONTROL_ICQ:
+ q->param.mfx.ICQQuality = avctx->global_quality;
+ break;
+ #endif
+ #endif
}
// the HEVC encoder plugin currently fails if coding options
q->extco.CAVLC = avctx->coder_type == FF_CODER_TYPE_VLC ?
MFX_CODINGOPTION_ON : MFX_CODINGOPTION_UNKNOWN;
+ q->extco.PicTimingSEI = q->pic_timing_sei ?
+ MFX_CODINGOPTION_ON : MFX_CODINGOPTION_UNKNOWN;
+
q->extparam_internal[q->nb_extparam_internal++] = (mfxExtBuffer *)&q->extco;
- #if QSV_VERSION_ATLEAST(1,6)
- q->extco2.Header.BufferId = MFX_EXTBUFF_CODING_OPTION2;
- q->extco2.Header.BufferSz = sizeof(q->extco2);
+ #if QSV_HAVE_CO2
+ if (avctx->codec_id == AV_CODEC_ID_H264) {
+ q->extco2.Header.BufferId = MFX_EXTBUFF_CODING_OPTION2;
+ q->extco2.Header.BufferSz = sizeof(q->extco2);
+ q->extparam_internal[q->nb_extparam_internal++] = (mfxExtBuffer *)&q->extco2;
+
- #if QSV_VERSION_ATLEAST(1,7)
- // valid value range is from 10 to 100 inclusive
- // to instruct the encoder to use the default value this should be set to zero
- q->extco2.LookAheadDepth = q->look_ahead_depth != 0 ? FFMAX(10, q->look_ahead_depth) : 0;
- #endif
+#if QSV_VERSION_ATLEAST(1,8)
- q->extco2.LookAheadDS = q->look_ahead_downsampling;
++ q->extco2.LookAheadDS = q->look_ahead_downsampling;
+#endif
-
- q->extparam_internal[q->nb_extparam_internal++] = (mfxExtBuffer *)&q->extco2;
-
+ }
#endif
}
#define QSV_HAVE_QVBR QSV_VERSION_ATLEAST(1, 11)
#define QSV_COMMON_OPTS \
-{ "async_depth", "Maximum processing parallelism", OFFSET(qsv.async_depth), AV_OPT_TYPE_INT, { .i64 = ASYNC_DEPTH_DEFAULT }, 0, INT_MAX, VE }, \
-{ "avbr_accuracy", "Accuracy of the AVBR ratecontrol", OFFSET(qsv.avbr_accuracy), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, VE }, \
-{ "avbr_convergence", "Convergence of the AVBR ratecontrol", OFFSET(qsv.avbr_convergence), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, VE }, \
-{ "preset", NULL, OFFSET(qsv.preset), AV_OPT_TYPE_INT, { .i64 = MFX_TARGETUSAGE_BALANCED }, 0, 7, VE, "preset" }, \
-{ "fast", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_TARGETUSAGE_BEST_SPEED }, INT_MIN, INT_MAX, VE, "preset" }, \
-{ "medium", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_TARGETUSAGE_BALANCED }, INT_MIN, INT_MAX, VE, "preset" }, \
-{ "slow", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_TARGETUSAGE_BEST_QUALITY }, INT_MIN, INT_MAX, VE, "preset" }, \
-{ "la_depth", "Number of frames to analyze before encoding.", OFFSET(qsv.la_depth), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT16_MAX, VE }, \
-{ "vcm", "Use the video conferencing mode ratecontrol", OFFSET(qsv.vcm), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE }, \
+{ "async_depth", "Maximum processing parallelism", OFFSET(qsv.async_depth), AV_OPT_TYPE_INT, { .i64 = ASYNC_DEPTH_DEFAULT }, 0, INT_MAX, VE }, \
+{ "avbr_accuracy", "Accuracy of the AVBR ratecontrol", OFFSET(qsv.avbr_accuracy), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, VE }, \
+{ "avbr_convergence", "Convergence of the AVBR ratecontrol", OFFSET(qsv.avbr_convergence), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, VE }, \
+{ "preset", NULL, OFFSET(qsv.preset), AV_OPT_TYPE_INT, { .i64 = MFX_TARGETUSAGE_BALANCED }, MFX_TARGETUSAGE_BEST_QUALITY, MFX_TARGETUSAGE_BEST_SPEED, VE, "preset" }, \
+{ "veryfast", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_TARGETUSAGE_BEST_SPEED }, INT_MIN, INT_MAX, VE, "preset" }, \
+{ "faster", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_TARGETUSAGE_6 }, INT_MIN, INT_MAX, VE, "preset" }, \
+{ "fast", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_TARGETUSAGE_5 }, INT_MIN, INT_MAX, VE, "preset" }, \
+{ "medium", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_TARGETUSAGE_BALANCED }, INT_MIN, INT_MAX, VE, "preset" }, \
+{ "slow", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_TARGETUSAGE_3 }, INT_MIN, INT_MAX, VE, "preset" }, \
+{ "slower", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_TARGETUSAGE_2 }, INT_MIN, INT_MAX, VE, "preset" }, \
+{ "veryslow", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_TARGETUSAGE_BEST_QUALITY }, INT_MIN, INT_MAX, VE, "preset" }, \
++{ "vcm", "Use the video conferencing mode ratecontrol", OFFSET(qsv.vcm), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE }, \
typedef struct QSVEncContext {
AVCodecContext *avctx;
int preset;
int avbr_accuracy;
int avbr_convergence;
- int la_depth;
+ int pic_timing_sei;
+ int look_ahead;
+ int look_ahead_depth;
+ int look_ahead_downsampling;
+ int vcm;
char *load_plugins;
} QSVEncContext;
QSV_COMMON_OPTS
{ "idr_interval", "Distance (in I-frames) between IDR frames", OFFSET(qsv.idr_interval), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, VE },
- #if QSV_VERSION_ATLEAST(1,7)
+ { "pic_timing_sei", "Insert picture timing SEI with pic_struct_syntax element", OFFSET(qsv.pic_timing_sei), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, VE },
+
++#if QSV_HAVE_LA
+ { "look_ahead", "Use VBR algorithm with look ahead", OFFSET(qsv.look_ahead), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, VE },
+ { "look_ahead_depth", "Depth of look ahead in number frames", OFFSET(qsv.look_ahead_depth), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 100, VE },
+#endif
+
+#if QSV_VERSION_ATLEAST(1,8)
+ { "look_ahead_downsampling", NULL, OFFSET(qsv.look_ahead_downsampling), AV_OPT_TYPE_INT, { .i64 = MFX_LOOKAHEAD_DS_UNKNOWN }, MFX_LOOKAHEAD_DS_UNKNOWN, MFX_LOOKAHEAD_DS_2x, VE, "look_ahead_downsampling" },
+ { "unknown" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_LOOKAHEAD_DS_UNKNOWN }, INT_MIN, INT_MAX, VE, "look_ahead_downsampling" },
+ { "off" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_LOOKAHEAD_DS_OFF }, INT_MIN, INT_MAX, VE, "look_ahead_downsampling" },
+ { "2x" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_LOOKAHEAD_DS_2x }, INT_MIN, INT_MAX, VE, "look_ahead_downsampling" },
+#endif
{ "profile", NULL, OFFSET(qsv.profile), AV_OPT_TYPE_INT, { .i64 = MFX_PROFILE_UNKNOWN }, 0, INT_MAX, VE, "profile" },
{ "unknown" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_PROFILE_UNKNOWN }, INT_MIN, INT_MAX, VE, "profile" },