summaryrefslogtreecommitdiff
path: root/libavcodec/nvenc.c
diff options
context:
space:
mode:
Diffstat (limited to 'libavcodec/nvenc.c')
-rw-r--r--libavcodec/nvenc.c134
1 files changed, 126 insertions, 8 deletions
diff --git a/libavcodec/nvenc.c b/libavcodec/nvenc.c
index 73c05fcd37..8228c66f64 100644
--- a/libavcodec/nvenc.c
+++ b/libavcodec/nvenc.c
@@ -1,5 +1,5 @@
/*
- * H.264/HEVC hardware encoding using nvidia nvenc
+ * H.264/HEVC/AV1 hardware encoding using nvidia nvenc
* Copyright (c) 2016 Timo Rothenpieler <timo@rothenpieler.org>
*
* This file is part of FFmpeg.
@@ -222,8 +222,14 @@ static void nvenc_map_preset(NvencContext *ctx)
static void nvenc_print_driver_requirement(AVCodecContext *avctx, int level)
{
-#if NVENCAPI_CHECK_VERSION(11, 2)
+#if NVENCAPI_CHECK_VERSION(12, 1)
const char *minver = "(unknown)";
+#elif NVENCAPI_CHECK_VERSION(12, 0)
+# if defined(_WIN32) || defined(__CYGWIN__)
+ const char *minver = "522.25";
+# else
+ const char *minver = "520.56.06";
+# endif
#elif NVENCAPI_CHECK_VERSION(11, 1)
# if defined(_WIN32) || defined(__CYGWIN__)
const char *minver = "471.41";
@@ -658,6 +664,11 @@ static av_cold int nvenc_setup_device(AVCodecContext *avctx)
case AV_CODEC_ID_HEVC:
ctx->init_encode_params.encodeGUID = NV_ENC_CODEC_HEVC_GUID;
break;
+#if CONFIG_AV1_NVENC_ENCODER
+ case AV_CODEC_ID_AV1:
+ ctx->init_encode_params.encodeGUID = NV_ENC_CODEC_AV1_GUID;
+ break;
+#endif
default:
return AVERROR_BUG;
}
@@ -761,6 +772,11 @@ static av_cold void set_constqp(AVCodecContext *avctx)
{
NvencContext *ctx = avctx->priv_data;
NV_ENC_RC_PARAMS *rc = &ctx->encode_config.rcParams;
+#if CONFIG_AV1_NVENC_ENCODER
+ int qmax = avctx->codec->id == AV_CODEC_ID_AV1 ? 255 : 51;
+#else
+ int qmax = 51;
+#endif
rc->rateControlMode = NV_ENC_PARAMS_RC_CONSTQP;
@@ -771,9 +787,9 @@ static av_cold void set_constqp(AVCodecContext *avctx)
rc->constQP.qpInterB = ctx->init_qp_b;
} else if (avctx->i_quant_factor != 0.0 && avctx->b_quant_factor != 0.0) {
rc->constQP.qpIntra = av_clip(
- rc->constQP.qpInterP * fabs(avctx->i_quant_factor) + avctx->i_quant_offset + 0.5, 0, 51);
+ rc->constQP.qpInterP * fabs(avctx->i_quant_factor) + avctx->i_quant_offset + 0.5, 0, qmax);
rc->constQP.qpInterB = av_clip(
- rc->constQP.qpInterP * fabs(avctx->b_quant_factor) + avctx->b_quant_offset + 0.5, 0, 51);
+ rc->constQP.qpInterP * fabs(avctx->b_quant_factor) + avctx->b_quant_offset + 0.5, 0, qmax);
} else {
rc->constQP.qpIntra = rc->constQP.qpInterP;
rc->constQP.qpInterB = rc->constQP.qpInterP;
@@ -781,9 +797,9 @@ static av_cold void set_constqp(AVCodecContext *avctx)
} else if (ctx->cqp >= 0) {
rc->constQP.qpInterP = rc->constQP.qpInterB = rc->constQP.qpIntra = ctx->cqp;
if (avctx->b_quant_factor != 0.0)
- rc->constQP.qpInterB = av_clip(ctx->cqp * fabs(avctx->b_quant_factor) + avctx->b_quant_offset + 0.5, 0, 51);
+ rc->constQP.qpInterB = av_clip(ctx->cqp * fabs(avctx->b_quant_factor) + avctx->b_quant_offset + 0.5, 0, qmax);
if (avctx->i_quant_factor != 0.0)
- rc->constQP.qpIntra = av_clip(ctx->cqp * fabs(avctx->i_quant_factor) + avctx->i_quant_offset + 0.5, 0, 51);
+ rc->constQP.qpIntra = av_clip(ctx->cqp * fabs(avctx->i_quant_factor) + avctx->i_quant_offset + 0.5, 0, qmax);
}
avctx->qmin = -1;
@@ -795,6 +811,11 @@ static av_cold void set_vbr(AVCodecContext *avctx)
NvencContext *ctx = avctx->priv_data;
NV_ENC_RC_PARAMS *rc = &ctx->encode_config.rcParams;
int qp_inter_p;
+#if CONFIG_AV1_NVENC_ENCODER
+ int qmax = avctx->codec->id == AV_CODEC_ID_AV1 ? 255 : 51;
+#else
+ int qmax = 51;
+#endif
if (avctx->qmin >= 0 && avctx->qmax >= 0) {
rc->enableMinQP = 1;
@@ -832,7 +853,7 @@ static av_cold void set_vbr(AVCodecContext *avctx)
if (ctx->init_qp_i < 0) {
if (avctx->i_quant_factor != 0.0 && avctx->b_quant_factor != 0.0) {
rc->initialRCQP.qpIntra = av_clip(
- rc->initialRCQP.qpInterP * fabs(avctx->i_quant_factor) + avctx->i_quant_offset + 0.5, 0, 51);
+ rc->initialRCQP.qpInterP * fabs(avctx->i_quant_factor) + avctx->i_quant_offset + 0.5, 0, qmax);
} else {
rc->initialRCQP.qpIntra = rc->initialRCQP.qpInterP;
}
@@ -843,7 +864,7 @@ static av_cold void set_vbr(AVCodecContext *avctx)
if (ctx->init_qp_b < 0) {
if (avctx->i_quant_factor != 0.0 && avctx->b_quant_factor != 0.0) {
rc->initialRCQP.qpInterB = av_clip(
- rc->initialRCQP.qpInterP * fabs(avctx->b_quant_factor) + avctx->b_quant_offset + 0.5, 0, 51);
+ rc->initialRCQP.qpInterP * fabs(avctx->b_quant_factor) + avctx->b_quant_offset + 0.5, 0, qmax);
} else {
rc->initialRCQP.qpInterB = rc->initialRCQP.qpInterP;
}
@@ -1327,6 +1348,86 @@ static av_cold int nvenc_setup_hevc_config(AVCodecContext *avctx)
return 0;
}
+#if CONFIG_AV1_NVENC_ENCODER
+static av_cold int nvenc_setup_av1_config(AVCodecContext *avctx)
+{
+ NvencContext *ctx = avctx->priv_data;
+ NV_ENC_CONFIG *cc = &ctx->encode_config;
+ NV_ENC_CONFIG_AV1 *av1 = &cc->encodeCodecConfig.av1Config;
+
+ const AVPixFmtDescriptor *pixdesc = av_pix_fmt_desc_get(ctx->data_pix_fmt);
+
+ if ((pixdesc->flags & AV_PIX_FMT_FLAG_RGB) && !IS_GBRP(ctx->data_pix_fmt)) {
+ av1->matrixCoefficients = AVCOL_SPC_BT470BG;
+ av1->colorPrimaries = avctx->color_primaries;
+ av1->transferCharacteristics = avctx->color_trc;
+ av1->colorRange = 0;
+ } else {
+ av1->matrixCoefficients = IS_GBRP(ctx->data_pix_fmt) ? AVCOL_SPC_RGB : avctx->colorspace;
+ av1->colorPrimaries = avctx->color_primaries;
+ av1->transferCharacteristics = avctx->color_trc;
+ av1->colorRange = (avctx->color_range == AVCOL_RANGE_JPEG
+ || ctx->data_pix_fmt == AV_PIX_FMT_YUVJ420P || ctx->data_pix_fmt == AV_PIX_FMT_YUVJ422P || ctx->data_pix_fmt == AV_PIX_FMT_YUVJ444P);
+ }
+
+ if (IS_YUV444(ctx->data_pix_fmt)) {
+ cc->profileGUID = NV_ENC_AV1_PROFILE_HIGH_GUID;
+ avctx->profile = FF_PROFILE_AV1_HIGH;
+ } else {
+ cc->profileGUID = NV_ENC_AV1_PROFILE_MAIN_GUID;
+ avctx->profile = FF_PROFILE_AV1_MAIN;
+ }
+
+ if (ctx->dpb_size >= 0) {
+ /* 0 means "let the hardware decide" */
+ av1->maxNumRefFramesInDPB = ctx->dpb_size;
+ }
+
+ if (ctx->intra_refresh) {
+ av1->enableIntraRefresh = 1;
+ av1->intraRefreshPeriod = avctx->gop_size;
+ av1->intraRefreshCnt = avctx->gop_size - 1;
+
+ av1->idrPeriod = NVENC_INFINITE_GOPLENGTH;
+ } else if (avctx->gop_size >= 0) {
+ av1->idrPeriod = avctx->gop_size;
+ }
+
+ if (IS_CBR(cc->rcParams.rateControlMode)) {
+ av1->enableBitstreamPadding = 1;
+ }
+
+ if (ctx->tile_cols >= 0)
+ av1->numTileColumns = ctx->tile_cols;
+ if (ctx->tile_rows >= 0)
+ av1->numTileRows = ctx->tile_rows;
+
+ av1->outputAnnexBFormat = 0;
+
+ av1->level = ctx->level;
+ av1->tier = ctx->tier;
+
+ av1->enableTimingInfo = ctx->timing_info;
+
+ /* mp4 encapsulation requires sequence headers to be present on all keyframes for AV1 */
+ av1->disableSeqHdr = 0;
+ av1->repeatSeqHdr = 1;
+
+ av1->chromaFormatIDC = IS_YUV444(ctx->data_pix_fmt) ? 3 : 1;
+
+ av1->inputPixelBitDepthMinus8 = IS_10BIT(ctx->data_pix_fmt) ? 2 : 0;
+ av1->pixelBitDepthMinus8 = (IS_10BIT(ctx->data_pix_fmt) || ctx->highbitdepth) ? 2 : 0;
+
+ if (ctx->b_ref_mode >= 0)
+ av1->useBFramesAsRef = ctx->b_ref_mode;
+
+ av1->numFwdRefs = avctx->refs;
+ av1->numBwdRefs = avctx->refs;
+
+ return 0;
+}
+#endif
+
static av_cold int nvenc_setup_codec_config(AVCodecContext *avctx)
{
switch (avctx->codec->id) {
@@ -1334,6 +1435,10 @@ static av_cold int nvenc_setup_codec_config(AVCodecContext *avctx)
return nvenc_setup_h264_config(avctx);
case AV_CODEC_ID_HEVC:
return nvenc_setup_hevc_config(avctx);
+#if CONFIG_AV1_NVENC_ENCODER
+ case AV_CODEC_ID_AV1:
+ return nvenc_setup_av1_config(avctx);
+#endif
/* Earlier switch/case will return if unknown codec is passed. */
}
@@ -2025,6 +2130,19 @@ static void nvenc_codec_specific_pic_params(AVCodecContext *avctx,
}
break;
+#if CONFIG_AV1_NVENC_ENCODER
+ case AV_CODEC_ID_AV1:
+ params->codecPicParams.av1PicParams.numTileColumns =
+ ctx->encode_config.encodeCodecConfig.av1Config.numTileColumns;
+ params->codecPicParams.av1PicParams.numTileRows =
+ ctx->encode_config.encodeCodecConfig.av1Config.numTileRows;
+ if (sei_count > 0) {
+ params->codecPicParams.av1PicParams.obuPayloadArray = sei_data;
+ params->codecPicParams.av1PicParams.obuPayloadArrayCnt = sei_count;
+ }
+
+ break;
+#endif
}
}