diff options
author | Wenbin Chen <wenbin.chen@intel.com> | 2022-10-13 16:25:23 +0800 |
---|---|---|
committer | Haihao Xiang <haihao.xiang@intel.com> | 2022-10-24 13:30:22 +0800 |
commit | dc9e4789a3b504c08c8cd24e990aa692dde50bc6 (patch) | |
tree | b6cf9df9d012d4b40452578a52c380f6fe0a101d /libavcodec/qsvenc.c | |
parent | 874a6f20902c91eb32b790b042ba77221f60c96b (diff) | |
download | ffmpeg-dc9e4789a3b504c08c8cd24e990aa692dde50bc6.tar.gz |
libavcodec/qsvenc_av1: add av1_qsv encoder
It is available only when libvpl is enabled. MSDK doesn't support av1
encoding.
sample command:
ffmpeg -f rawvideo -pix_fmt nv12 -s 1920x1080 -i input.yuv \
-c:v av1_qsv output.ivf
Signed-off-by: Wenbin Chen <wenbin.chen@intel.com>
Signed-off-by: Haihao Xiang <haihao.xiang@intel.com>
Diffstat (limited to 'libavcodec/qsvenc.c')
-rw-r--r-- | libavcodec/qsvenc.c | 196 |
1 files changed, 192 insertions, 4 deletions
diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c index 15e6936a65..54b11c6ddd 100644 --- a/libavcodec/qsvenc.c +++ b/libavcodec/qsvenc.c @@ -82,6 +82,14 @@ static const struct profile_names vp9_profiles[] = { { MFX_PROFILE_VP9_3, "vp9 3" }, }; +static const struct profile_names av1_profiles[] = { +#if QSV_VERSION_ATLEAST(1, 34) + { MFX_PROFILE_AV1_MAIN, "av1 main" }, + { MFX_PROFILE_AV1_HIGH, "av1 high" }, + { MFX_PROFILE_AV1_PRO, "av1 professional" }, +#endif +}; + typedef struct QSVPacket { AVPacket pkt; mfxSyncPoint *sync; @@ -114,6 +122,11 @@ static const char *print_profile(enum AVCodecID codec_id, mfxU16 profile) num_profiles = FF_ARRAY_ELEMS(vp9_profiles); break; + case AV_CODEC_ID_AV1: + profiles = av1_profiles; + num_profiles = FF_ARRAY_ELEMS(av1_profiles); + break; + default: return "unknown"; } @@ -429,6 +442,88 @@ static void dump_video_mjpeg_param(AVCodecContext *avctx, QSVEncContext *q) info->FrameInfo.FrameRateExtD, info->FrameInfo.FrameRateExtN); } +#if QSV_HAVE_EXT_AV1_PARAM +static void dump_video_av1_param(AVCodecContext *avctx, QSVEncContext *q, + mfxExtBuffer **coding_opts) +{ + mfxInfoMFX *info = &q->param.mfx; + mfxExtAV1TileParam *av1_tile_param = (mfxExtAV1TileParam *)coding_opts[0]; + mfxExtAV1BitstreamParam *av1_bs_param = (mfxExtAV1BitstreamParam *)coding_opts[1]; + mfxExtCodingOption2 *co2 = (mfxExtCodingOption2*)coding_opts[2]; + mfxExtCodingOption3 *co3 = (mfxExtCodingOption3*)coding_opts[3]; + + av_log(avctx, AV_LOG_VERBOSE, "profile: %s; level: %"PRIu16"\n", + print_profile(avctx->codec_id, info->CodecProfile), info->CodecLevel); + + av_log(avctx, AV_LOG_VERBOSE, + "GopPicSize: %"PRIu16"; GopRefDist: %"PRIu16"; GopOptFlag:%s%s; IdrInterval: %"PRIu16"\n", + info->GopPicSize, info->GopRefDist, + info->GopOptFlag & MFX_GOP_CLOSED ? " closed" : "", + info->GopOptFlag & MFX_GOP_STRICT ? " strict" : "", + info->IdrInterval); + + av_log(avctx, AV_LOG_VERBOSE, "TargetUsage: %"PRIu16"; RateControlMethod: %s\n", + info->TargetUsage, print_ratecontrol(info->RateControlMethod)); + + if (info->RateControlMethod == MFX_RATECONTROL_CBR || + info->RateControlMethod == MFX_RATECONTROL_VBR) + av_log(avctx, AV_LOG_VERBOSE, + "BufferSizeInKB: %"PRIu16"; InitialDelayInKB: %"PRIu16"; TargetKbps: %"PRIu16"; MaxKbps: %"PRIu16"; BRCParamMultiplier: %"PRIu16"\n", + info->BufferSizeInKB, info->InitialDelayInKB, info->TargetKbps, info->MaxKbps, info->BRCParamMultiplier); + else if (info->RateControlMethod == MFX_RATECONTROL_CQP) + av_log(avctx, AV_LOG_VERBOSE, "QPI: %"PRIu16"; QPP: %"PRIu16"; QPB: %"PRIu16"\n", + info->QPI, info->QPP, info->QPB); + else if (info->RateControlMethod == MFX_RATECONTROL_ICQ) + av_log(avctx, AV_LOG_VERBOSE, "ICQQuality: %"PRIu16"\n", info->ICQQuality); + else + av_log(avctx, AV_LOG_VERBOSE, "Unsupported ratecontrol method: %d \n", info->RateControlMethod); + + av_log(avctx, AV_LOG_VERBOSE, "NumRefFrame: %"PRIu16"\n", info->NumRefFrame); + + av_log(avctx, AV_LOG_VERBOSE, + "IntRefType: %"PRIu16"; IntRefCycleSize: %"PRIu16 + "; IntRefQPDelta: %"PRId16"; IntRefCycleDist: %"PRId16"\n", + co2->IntRefType, co2->IntRefCycleSize, + co2->IntRefQPDelta, co3->IntRefCycleDist); + + av_log(avctx, AV_LOG_VERBOSE, "MaxFrameSize: %d;\n", co2->MaxFrameSize); + + av_log(avctx, AV_LOG_VERBOSE, + "BitrateLimit: %s; MBBRC: %s; ExtBRC: %s\n", + print_threestate(co2->BitrateLimit), print_threestate(co2->MBBRC), + print_threestate(co2->ExtBRC)); + + av_log(avctx, AV_LOG_VERBOSE, "VDENC: %s\n", print_threestate(info->LowPower)); + + switch (co2->BRefType) { + case MFX_B_REF_OFF: av_log(avctx, AV_LOG_VERBOSE, "BRefType: off\n"); break; + case MFX_B_REF_PYRAMID: av_log(avctx, AV_LOG_VERBOSE, "BRefType: pyramid\n"); break; + default: av_log(avctx, AV_LOG_VERBOSE, "BRefType: auto\n"); break; + } + + switch (co3->PRefType) { + case MFX_P_REF_DEFAULT: av_log(avctx, AV_LOG_VERBOSE, "PRefType: default\n"); break; + case MFX_P_REF_SIMPLE: av_log(avctx, AV_LOG_VERBOSE, "PRefType: simple\n"); break; + case MFX_P_REF_PYRAMID: av_log(avctx, AV_LOG_VERBOSE, "PRefType: pyramid\n"); break; + default: av_log(avctx, AV_LOG_VERBOSE, "PRefType: unknown\n"); break; + } + + av_log(avctx, AV_LOG_VERBOSE, + "MinQPI: %"PRIu8"; MaxQPI: %"PRIu8"; MinQPP: %"PRIu8"; MaxQPP: %"PRIu8"; MinQPB: %"PRIu8"; MaxQPB: %"PRIu8"\n", + co2->MinQPI, co2->MaxQPI, co2->MinQPP, co2->MaxQPP, co2->MinQPB, co2->MaxQPB); + + av_log(avctx, AV_LOG_VERBOSE, "FrameRateExtD: %"PRIu32"; FrameRateExtN: %"PRIu32" \n", + info->FrameInfo.FrameRateExtD, info->FrameInfo.FrameRateExtN); + + av_log(avctx, AV_LOG_VERBOSE, + "NumTileRows: %"PRIu16"; NumTileColumns: %"PRIu16"; NumTileGroups: %"PRIu16"\n", + av1_tile_param->NumTileRows, av1_tile_param->NumTileColumns, av1_tile_param->NumTileGroups); + + av_log(avctx, AV_LOG_VERBOSE, "WriteIVFHeaders: %s \n", + print_threestate(av1_bs_param->WriteIVFHeaders)); +} +#endif + static int select_rc_mode(AVCodecContext *avctx, QSVEncContext *q) { const char *rc_desc; @@ -741,10 +836,15 @@ static int init_video_param(AVCodecContext *avctx, QSVEncContext *q) break; case MFX_RATECONTROL_CQP: quant = avctx->global_quality / FF_QP2LAMBDA; - - q->param.mfx.QPI = av_clip(quant * fabs(avctx->i_quant_factor) + avctx->i_quant_offset, 0, 51); - q->param.mfx.QPP = av_clip(quant, 0, 51); - q->param.mfx.QPB = av_clip(quant * fabs(avctx->b_quant_factor) + avctx->b_quant_offset, 0, 51); + if (avctx->codec_id == AV_CODEC_ID_AV1) { + q->param.mfx.QPI = av_clip_uintp2(quant * fabs(avctx->i_quant_factor) + avctx->i_quant_offset, 8); + q->param.mfx.QPP = av_clip_uintp2(quant, 8); + q->param.mfx.QPB = av_clip_uintp2(quant * fabs(avctx->b_quant_factor) + avctx->b_quant_offset, 8); + } else { + q->param.mfx.QPI = av_clip(quant * fabs(avctx->i_quant_factor) + avctx->i_quant_offset, 0, 51); + q->param.mfx.QPP = av_clip(quant, 0, 51); + q->param.mfx.QPB = av_clip(quant * fabs(avctx->b_quant_factor) + avctx->b_quant_offset, 0, 51); + } q->old_global_quality = avctx->global_quality; q->old_i_quant_factor = avctx->i_quant_factor; q->old_i_quant_offset = avctx->i_quant_offset; @@ -896,6 +996,20 @@ static int init_video_param(AVCodecContext *avctx, QSVEncContext *q) q->extco2.Header.BufferSz = sizeof(q->extco2); q->extparam_internal[q->nb_extparam_internal++] = (mfxExtBuffer *)&q->extco2; + } else if (avctx->codec_id == AV_CODEC_ID_AV1) { + if (q->extbrc >= 0) + q->extco2.ExtBRC = q->extbrc ? MFX_CODINGOPTION_ON : MFX_CODINGOPTION_OFF; + if (q->b_strategy >= 0) + q->extco2.BRefType = q->b_strategy ? MFX_B_REF_PYRAMID : MFX_B_REF_OFF; + if (q->adaptive_i >= 0) + q->extco2.AdaptiveI = q->adaptive_i ? MFX_CODINGOPTION_ON : MFX_CODINGOPTION_OFF; + if (q->adaptive_b >= 0) + q->extco2.AdaptiveB = q->adaptive_b ? MFX_CODINGOPTION_ON : MFX_CODINGOPTION_OFF; + + 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 (avctx->codec_id == AV_CODEC_ID_H264) { @@ -972,6 +1086,27 @@ static int init_video_param(AVCodecContext *avctx, QSVEncContext *q) q->extparam_internal[q->nb_extparam_internal++] = (mfxExtBuffer *)&q->extvp9param; } +#if QSV_HAVE_EXT_AV1_PARAM + if (avctx->codec_id == AV_CODEC_ID_AV1) { + if (QSV_RUNTIME_VERSION_ATLEAST(q->ver, 2, 5)) { + q->extav1tileparam.Header.BufferId = MFX_EXTBUFF_AV1_TILE_PARAM; + q->extav1tileparam.Header.BufferSz = sizeof(q->extav1tileparam); + q->extav1tileparam.NumTileColumns = q->tile_cols; + q->extav1tileparam.NumTileRows = q->tile_rows; + q->extparam_internal[q->nb_extparam_internal++] = (mfxExtBuffer *)&q->extav1tileparam; + + q->extav1bsparam.Header.BufferId = MFX_EXTBUFF_AV1_BITSTREAM_PARAM; + q->extav1bsparam.Header.BufferSz = sizeof(q->extav1bsparam); + q->extav1bsparam.WriteIVFHeaders = MFX_CODINGOPTION_OFF; + q->extparam_internal[q->nb_extparam_internal++] = (mfxExtBuffer *)&q->extav1bsparam; + } else { + av_log(avctx, AV_LOG_ERROR, + "This version of runtime doesn't support AV1 encoding\n"); + return AVERROR_UNKNOWN; + } + } +#endif + if (avctx->codec_id == AV_CODEC_ID_HEVC) { q->exthevctiles.Header.BufferId = MFX_EXTBUFF_HEVC_TILES; q->exthevctiles.Header.BufferSz = sizeof(q->exthevctiles); @@ -1082,6 +1217,56 @@ static int qsv_retrieve_enc_vp9_params(AVCodecContext *avctx, QSVEncContext *q) return 0; } +static int qsv_retrieve_enc_av1_params(AVCodecContext *avctx, QSVEncContext *q) +{ +#if QSV_HAVE_EXT_AV1_PARAM + int ret = 0; + mfxExtAV1TileParam av1_extend_tile_buf = { + .Header.BufferId = MFX_EXTBUFF_AV1_TILE_PARAM, + .Header.BufferSz = sizeof(av1_extend_tile_buf), + }; + mfxExtAV1BitstreamParam av1_bs_param = { + .Header.BufferId = MFX_EXTBUFF_AV1_BITSTREAM_PARAM, + .Header.BufferSz = sizeof(av1_bs_param), + }; + + mfxExtCodingOption2 co2 = { + .Header.BufferId = MFX_EXTBUFF_CODING_OPTION2, + .Header.BufferSz = sizeof(co2), + }; + + mfxExtCodingOption3 co3 = { + .Header.BufferId = MFX_EXTBUFF_CODING_OPTION3, + .Header.BufferSz = sizeof(co3), + }; + + mfxExtBuffer *ext_buffers[] = { + (mfxExtBuffer*)&av1_extend_tile_buf, + (mfxExtBuffer*)&av1_bs_param, + (mfxExtBuffer*)&co2, + (mfxExtBuffer*)&co3, + }; + + if (!QSV_RUNTIME_VERSION_ATLEAST(q->ver, 2, 5)) { + av_log(avctx, AV_LOG_ERROR, + "This version of runtime doesn't support AV1 encoding\n"); + return AVERROR_UNKNOWN; + } + + q->param.ExtParam = ext_buffers; + q->param.NumExtParam = FF_ARRAY_ELEMS(ext_buffers); + + ret = MFXVideoENCODE_GetVideoParam(q->session, &q->param); + if (ret < 0) + return ff_qsv_print_error(avctx, ret, + "Error calling GetVideoParam"); + + q->packet_size = q->param.mfx.BufferSizeInKB * q->param.mfx.BRCParamMultiplier * 1000; + dump_video_av1_param(avctx, q, ext_buffers); +#endif + return 0; +} + static int qsv_retrieve_enc_params(AVCodecContext *avctx, QSVEncContext *q) { AVCPBProperties *cpb_props; @@ -1420,6 +1605,9 @@ int ff_qsv_enc_init(AVCodecContext *avctx, QSVEncContext *q) case AV_CODEC_ID_VP9: ret = qsv_retrieve_enc_vp9_params(avctx, q); break; + case AV_CODEC_ID_AV1: + ret = qsv_retrieve_enc_av1_params(avctx, q); + break; default: ret = qsv_retrieve_enc_params(avctx, q); break; |