avcodec/nvenc: add AV1 encoding support
The encoder seems to be trading blows with hevc_nvenc. In terms of quality at low bitrate cbr settings, it seems to outperform it even. It produces fewer artifacts and the ones it does produce are less jarring to my perception. At higher bitrates I had a hard time finding differences between the two encoders in terms of subjective visual quality. Using the 'slow' preset, av1_nvenc outperformed hevc_nvenc in terms of encoding speed by 75% to 100% while performing above tests. Needless to say, it always massively outperformed h264_nvenc in terms of quality for a given bitrate, while also being slightly faster.
This commit is contained in:
parent
28680e2f41
commit
5c288a44ad
14
configure
vendored
14
configure
vendored
@ -3184,6 +3184,8 @@ nvenc_deps_any="libdl LoadLibrary"
|
||||
aac_mf_encoder_deps="mediafoundation"
|
||||
ac3_mf_encoder_deps="mediafoundation"
|
||||
av1_cuvid_decoder_deps="cuvid CUVIDAV1PICPARAMS"
|
||||
av1_nvenc_encoder_deps="nvenc NV_ENC_PIC_PARAMS_AV1"
|
||||
av1_nvenc_encoder_select="atsc_a53"
|
||||
h263_v4l2m2m_decoder_deps="v4l2_m2m h263_v4l2_m2m"
|
||||
h263_v4l2m2m_encoder_deps="v4l2_m2m h263_v4l2_m2m"
|
||||
h264_amf_encoder_deps="amf"
|
||||
@ -6466,10 +6468,10 @@ fi
|
||||
|
||||
if ! disabled ffnvcodec; then
|
||||
ffnv_hdr_list="ffnvcodec/nvEncodeAPI.h ffnvcodec/dynlink_cuda.h ffnvcodec/dynlink_cuviddec.h ffnvcodec/dynlink_nvcuvid.h"
|
||||
check_pkg_config ffnvcodec "ffnvcodec >= 9.1.23.1" "$ffnv_hdr_list" "" || \
|
||||
check_pkg_config ffnvcodec "ffnvcodec >= 9.0.18.3 ffnvcodec < 9.1" "$ffnv_hdr_list" "" || \
|
||||
check_pkg_config ffnvcodec "ffnvcodec >= 8.2.15.10 ffnvcodec < 8.3" "$ffnv_hdr_list" "" || \
|
||||
check_pkg_config ffnvcodec "ffnvcodec >= 8.1.24.11 ffnvcodec < 8.2" "$ffnv_hdr_list" ""
|
||||
check_pkg_config ffnvcodec "ffnvcodec >= 12.0.11.0" "$ffnv_hdr_list" "" || \
|
||||
check_pkg_config ffnvcodec "ffnvcodec >= 11.1.5.2 ffnvcodec < 12.0" "$ffnv_hdr_list" "" || \
|
||||
check_pkg_config ffnvcodec "ffnvcodec >= 11.0.10.2 ffnvcodec < 11.1" "$ffnv_hdr_list" "" || \
|
||||
check_pkg_config ffnvcodec "ffnvcodec >= 8.1.24.14 ffnvcodec < 8.2" "$ffnv_hdr_list" ""
|
||||
fi
|
||||
|
||||
if enabled_all libglslang libshaderc; then
|
||||
@ -7050,6 +7052,10 @@ void f(void) { struct { const GUID guid; } s[] = { { NV_ENC_PRESET_HQ_GUID } };
|
||||
int main(void) { return 0; }
|
||||
EOF
|
||||
|
||||
if enabled nvenc; then
|
||||
check_type "ffnvcodec/nvEncodeAPI.h" "NV_ENC_PIC_PARAMS_AV1"
|
||||
fi
|
||||
|
||||
if enabled_any nvdec cuvid; then
|
||||
check_type "ffnvcodec/dynlink_cuda.h ffnvcodec/dynlink_cuviddec.h" "CUVIDAV1PICPARAMS"
|
||||
fi
|
||||
|
@ -244,6 +244,7 @@ OBJS-$(CONFIG_AURA_DECODER) += cyuv.o
|
||||
OBJS-$(CONFIG_AURA2_DECODER) += aura.o
|
||||
OBJS-$(CONFIG_AV1_DECODER) += av1dec.o
|
||||
OBJS-$(CONFIG_AV1_CUVID_DECODER) += cuviddec.o
|
||||
OBJS-$(CONFIG_AV1_NVENC_ENCODER) += nvenc_av1.o nvenc.o
|
||||
OBJS-$(CONFIG_AV1_QSV_ENCODER) += qsvenc_av1.o
|
||||
OBJS-$(CONFIG_AVRN_DECODER) += avrndec.o
|
||||
OBJS-$(CONFIG_AVRP_DECODER) += r210dec.o
|
||||
|
@ -827,6 +827,7 @@ extern const FFCodec ff_libaom_av1_decoder;
|
||||
/* hwaccel hooks only, so prefer external decoders */
|
||||
extern const FFCodec ff_av1_decoder;
|
||||
extern const FFCodec ff_av1_cuvid_decoder;
|
||||
extern const FFCodec ff_av1_nvenc_encoder;
|
||||
extern const FFCodec ff_av1_qsv_decoder;
|
||||
extern const FFCodec ff_av1_qsv_encoder;
|
||||
extern const FFCodec ff_libopenh264_encoder;
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -199,6 +199,8 @@ typedef struct NvencContext
|
||||
int tier;
|
||||
int rc;
|
||||
int cbr;
|
||||
int tile_rows;
|
||||
int tile_cols;
|
||||
int twopass;
|
||||
int device;
|
||||
int flags;
|
||||
@ -236,6 +238,8 @@ typedef struct NvencContext
|
||||
int single_slice_intra_refresh;
|
||||
int constrained_encoding;
|
||||
int udu_sei;
|
||||
int timing_info;
|
||||
int highbitdepth;
|
||||
} NvencContext;
|
||||
|
||||
int ff_nvenc_encode_init(AVCodecContext *avctx);
|
||||
|
189
libavcodec/nvenc_av1.c
Normal file
189
libavcodec/nvenc_av1.c
Normal file
@ -0,0 +1,189 @@
|
||||
/*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FFmpeg is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "libavutil/internal.h"
|
||||
|
||||
#include "avcodec.h"
|
||||
#include "codec_internal.h"
|
||||
|
||||
#include "nvenc.h"
|
||||
|
||||
#define OFFSET(x) offsetof(NvencContext, x)
|
||||
#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
|
||||
static const AVOption options[] = {
|
||||
{ "preset", "Set the encoding preset", OFFSET(preset), AV_OPT_TYPE_INT, { .i64 = PRESET_P4 }, PRESET_DEFAULT, PRESET_P7, VE, "preset" },
|
||||
{ "default", "", 0, AV_OPT_TYPE_CONST, { .i64 = PRESET_DEFAULT }, 0, 0, VE, "preset" },
|
||||
{ "slow", "hq 2 passes", 0, AV_OPT_TYPE_CONST, { .i64 = PRESET_SLOW }, 0, 0, VE, "preset" },
|
||||
{ "medium", "hq 1 pass", 0, AV_OPT_TYPE_CONST, { .i64 = PRESET_MEDIUM }, 0, 0, VE, "preset" },
|
||||
{ "fast", "hp 1 pass", 0, AV_OPT_TYPE_CONST, { .i64 = PRESET_FAST }, 0, 0, VE, "preset" },
|
||||
{ "p1", "fastest (lowest quality)", 0, AV_OPT_TYPE_CONST, { .i64 = PRESET_P1 }, 0, 0, VE, "preset" },
|
||||
{ "p2", "faster (lower quality)", 0, AV_OPT_TYPE_CONST, { .i64 = PRESET_P2 }, 0, 0, VE, "preset" },
|
||||
{ "p3", "fast (low quality)", 0, AV_OPT_TYPE_CONST, { .i64 = PRESET_P3 }, 0, 0, VE, "preset" },
|
||||
{ "p4", "medium (default)", 0, AV_OPT_TYPE_CONST, { .i64 = PRESET_P4 }, 0, 0, VE, "preset" },
|
||||
{ "p5", "slow (good quality)", 0, AV_OPT_TYPE_CONST, { .i64 = PRESET_P5 }, 0, 0, VE, "preset" },
|
||||
{ "p6", "slower (better quality)", 0, AV_OPT_TYPE_CONST, { .i64 = PRESET_P6 }, 0, 0, VE, "preset" },
|
||||
{ "p7", "slowest (best quality)", 0, AV_OPT_TYPE_CONST, { .i64 = PRESET_P7 }, 0, 0, VE, "preset" },
|
||||
{ "tune", "Set the encoding tuning info", OFFSET(tuning_info), AV_OPT_TYPE_INT, { .i64 = NV_ENC_TUNING_INFO_HIGH_QUALITY }, NV_ENC_TUNING_INFO_HIGH_QUALITY, NV_ENC_TUNING_INFO_LOSSLESS, VE, "tune" },
|
||||
{ "hq", "High quality", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_TUNING_INFO_HIGH_QUALITY }, 0, 0, VE, "tune" },
|
||||
{ "ll", "Low latency", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_TUNING_INFO_LOW_LATENCY }, 0, 0, VE, "tune" },
|
||||
{ "ull", "Ultra low latency", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_TUNING_INFO_ULTRA_LOW_LATENCY }, 0, 0, VE, "tune" },
|
||||
{ "lossless", "Lossless", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_TUNING_INFO_LOSSLESS }, 0, 0, VE, "tune" },
|
||||
{ "level", "Set the encoding level restriction", OFFSET(level), AV_OPT_TYPE_INT, { .i64 = NV_ENC_LEVEL_AV1_AUTOSELECT }, NV_ENC_LEVEL_AV1_2, NV_ENC_LEVEL_AV1_AUTOSELECT, VE, "level" },
|
||||
{ "auto", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_LEVEL_AV1_AUTOSELECT }, 0, 0, VE, "level" },
|
||||
{ "2", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_LEVEL_AV1_2 }, 0, 0, VE, "level" },
|
||||
{ "2.0", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_LEVEL_AV1_2 }, 0, 0, VE, "level" },
|
||||
{ "2.1", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_LEVEL_AV1_21 }, 0, 0, VE, "level" },
|
||||
{ "2.2", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_LEVEL_AV1_22 }, 0, 0, VE, "level" },
|
||||
{ "2.3", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_LEVEL_AV1_23 }, 0, 0, VE, "level" },
|
||||
{ "3", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_LEVEL_AV1_3 }, 0, 0, VE, "level" },
|
||||
{ "3.0", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_LEVEL_AV1_3 }, 0, 0, VE, "level" },
|
||||
{ "3.1", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_LEVEL_AV1_31 }, 0, 0, VE, "level" },
|
||||
{ "3.2", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_LEVEL_AV1_32 }, 0, 0, VE, "level" },
|
||||
{ "3.3", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_LEVEL_AV1_33 }, 0, 0, VE, "level" },
|
||||
{ "4", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_LEVEL_AV1_4 }, 0, 0, VE, "level" },
|
||||
{ "4.0", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_LEVEL_AV1_4 }, 0, 0, VE, "level" },
|
||||
{ "4.1", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_LEVEL_AV1_41 }, 0, 0, VE, "level" },
|
||||
{ "4.2", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_LEVEL_AV1_42 }, 0, 0, VE, "level" },
|
||||
{ "4.3", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_LEVEL_AV1_43 }, 0, 0, VE, "level" },
|
||||
{ "5", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_LEVEL_AV1_5 }, 0, 0, VE, "level" },
|
||||
{ "5.0", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_LEVEL_AV1_5 }, 0, 0, VE, "level" },
|
||||
{ "5.1", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_LEVEL_AV1_51 }, 0, 0, VE, "level" },
|
||||
{ "5.2", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_LEVEL_AV1_52 }, 0, 0, VE, "level" },
|
||||
{ "5.3", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_LEVEL_AV1_53 }, 0, 0, VE, "level" },
|
||||
{ "6", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_LEVEL_AV1_6 }, 0, 0, VE, "level" },
|
||||
{ "6.0", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_LEVEL_AV1_6 }, 0, 0, VE, "level" },
|
||||
{ "6.1", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_LEVEL_AV1_61 }, 0, 0, VE, "level" },
|
||||
{ "6.2", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_LEVEL_AV1_62 }, 0, 0, VE, "level" },
|
||||
{ "6.3", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_LEVEL_AV1_63 }, 0, 0, VE, "level" },
|
||||
{ "7", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_LEVEL_AV1_7 }, 0, 0, VE, "level" },
|
||||
{ "7.0", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_LEVEL_AV1_7 }, 0, 0, VE, "level" },
|
||||
{ "7.1", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_LEVEL_AV1_71 }, 0, 0, VE, "level" },
|
||||
{ "7.2", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_LEVEL_AV1_72 }, 0, 0, VE, "level" },
|
||||
{ "7.3", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_LEVEL_AV1_73 }, 0, 0, VE, "level" },
|
||||
{ "tier", "Set the encoding tier", OFFSET(tier), AV_OPT_TYPE_INT, { .i64 = NV_ENC_TIER_AV1_0 }, NV_ENC_TIER_AV1_0, NV_ENC_TIER_AV1_1, VE, "tier"},
|
||||
{ "0", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_TIER_AV1_0 }, 0, 0, VE, "tier" },
|
||||
{ "1", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_TIER_AV1_1 }, 0, 0, VE, "tier" },
|
||||
{ "rc", "Override the preset rate-control", OFFSET(rc), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, VE, "rc" },
|
||||
{ "constqp", "Constant QP mode", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_PARAMS_RC_CONSTQP }, 0, 0, VE, "rc" },
|
||||
{ "vbr", "Variable bitrate mode", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_PARAMS_RC_VBR }, 0, 0, VE, "rc" },
|
||||
{ "cbr", "Constant bitrate mode", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_PARAMS_RC_CBR }, 0, 0, VE, "rc" },
|
||||
{ "multipass", "Set the multipass encoding", OFFSET(multipass), AV_OPT_TYPE_INT, { .i64 = NV_ENC_MULTI_PASS_DISABLED }, NV_ENC_MULTI_PASS_DISABLED, NV_ENC_TWO_PASS_FULL_RESOLUTION, VE, "multipass" },
|
||||
{ "disabled", "Single Pass", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_MULTI_PASS_DISABLED }, 0, 0, VE, "multipass" },
|
||||
{ "qres", "Two Pass encoding is enabled where first Pass is quarter resolution",
|
||||
0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_TWO_PASS_QUARTER_RESOLUTION }, 0, 0, VE, "multipass" },
|
||||
{ "fullres", "Two Pass encoding is enabled where first Pass is full resolution",
|
||||
0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_TWO_PASS_FULL_RESOLUTION }, 0, 0, VE, "multipass" },
|
||||
{ "highbitdepth", "Enable 10 bit encode for 8 bit input",OFFSET(highbitdepth),AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE },
|
||||
{ "tile-rows", "Number of tile rows to encode with", OFFSET(tile_rows), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, NV_MAX_TILE_ROWS_AV1, VE },
|
||||
{ "tile-columns", "Number of tile columns to encode with", OFFSET(tile_cols), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, NV_MAX_TILE_COLS_AV1, VE },
|
||||
{ "surfaces", "Number of concurrent surfaces", OFFSET(nb_surfaces), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, MAX_REGISTERED_FRAMES, VE },
|
||||
{ "gpu", "Selects which NVENC capable GPU to use. First GPU is 0, second is 1, and so on.",
|
||||
OFFSET(device), AV_OPT_TYPE_INT, { .i64 = ANY_DEVICE }, -2, INT_MAX, VE, "gpu" },
|
||||
{ "any", "Pick the first device available", 0, AV_OPT_TYPE_CONST, { .i64 = ANY_DEVICE }, 0, 0, VE, "gpu" },
|
||||
{ "list", "List the available devices", 0, AV_OPT_TYPE_CONST, { .i64 = LIST_DEVICES }, 0, 0, VE, "gpu" },
|
||||
{ "delay", "Delay frame output by the given amount of frames",
|
||||
OFFSET(async_depth), AV_OPT_TYPE_INT, { .i64 = INT_MAX }, 0, INT_MAX, VE },
|
||||
{ "rc-lookahead", "Number of frames to look ahead for rate-control",
|
||||
OFFSET(rc_lookahead), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, VE },
|
||||
{ "cq", "Set target quality level (0 to 51, 0 means automatic) for constant quality mode in VBR rate control",
|
||||
OFFSET(quality), AV_OPT_TYPE_FLOAT, { .dbl = 0.}, 0., 51., VE },
|
||||
{ "init_qpP", "Initial QP value for P frame", OFFSET(init_qp_p), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 255, VE },
|
||||
{ "init_qpB", "Initial QP value for B frame", OFFSET(init_qp_b), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 255, VE },
|
||||
{ "init_qpI", "Initial QP value for I frame", OFFSET(init_qp_i), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 255, VE },
|
||||
{ "qp", "Constant quantization parameter rate control method",
|
||||
OFFSET(cqp), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 255, VE },
|
||||
{ "qp_cb_offset", "Quantization parameter offset for cb channel",
|
||||
OFFSET(qp_cb_offset), AV_OPT_TYPE_INT, { .i64 = 0 }, -12, 12, VE },
|
||||
{ "qp_cr_offset", "Quantization parameter offset for cr channel",
|
||||
OFFSET(qp_cr_offset), AV_OPT_TYPE_INT, { .i64 = 0 }, -12, 12, VE },
|
||||
{ "no-scenecut", "When lookahead is enabled, set this to 1 to disable adaptive I-frame insertion at scene cuts",
|
||||
OFFSET(no_scenecut), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE },
|
||||
{ "forced-idr", "If forcing keyframes, force them as IDR frames.",
|
||||
OFFSET(forced_idr), AV_OPT_TYPE_BOOL, { .i64 = 0 }, -1, 1, VE },
|
||||
{ "b_adapt", "When lookahead is enabled, set this to 0 to disable adaptive B-frame decision",
|
||||
OFFSET(b_adapt), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, VE },
|
||||
{ "spatial-aq", "set to 1 to enable Spatial AQ", OFFSET(aq), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE },
|
||||
{ "temporal-aq", "set to 1 to enable Temporal AQ", OFFSET(temporal_aq), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE },
|
||||
{ "zerolatency", "Set 1 to indicate zero latency operation (no reordering delay)",
|
||||
OFFSET(zerolatency), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE },
|
||||
{ "nonref_p", "Set this to 1 to enable automatic insertion of non-reference P-frames",
|
||||
OFFSET(nonref_p), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE },
|
||||
{ "strict_gop", "Set 1 to minimize GOP-to-GOP rate fluctuations",
|
||||
OFFSET(strict_gop), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE },
|
||||
{ "aq-strength", "When Spatial AQ is enabled, this field is used to specify AQ strength. AQ strength scale is from 1 (low) - 15 (aggressive)",
|
||||
OFFSET(aq_strength), AV_OPT_TYPE_INT, { .i64 = 8 }, 1, 15, VE },
|
||||
{ "weighted_pred","Enable weighted prediction", OFFSET(weighted_pred),AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE },
|
||||
{ "b_ref_mode", "Use B frames as references", OFFSET(b_ref_mode), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, NV_ENC_BFRAME_REF_MODE_MIDDLE, VE, "b_ref_mode" },
|
||||
{ "disabled", "B frames will not be used for reference", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_BFRAME_REF_MODE_DISABLED }, 0, 0, VE, "b_ref_mode" },
|
||||
{ "each", "Each B frame will be used for reference", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_BFRAME_REF_MODE_EACH }, 0, 0, VE, "b_ref_mode" },
|
||||
{ "middle", "Only (number of B frames)/2 will be used for reference", 0,AV_OPT_TYPE_CONST, { .i64 = NV_ENC_BFRAME_REF_MODE_MIDDLE }, 0, 0, VE, "b_ref_mode" },
|
||||
{ "dpb_size", "Specifies the DPB size used for encoding (0 means automatic)",
|
||||
OFFSET(dpb_size), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, VE },
|
||||
{ "ldkfs", "Low delay key frame scale; Specifies the Scene Change frame size increase allowed in case of single frame VBV and CBR",
|
||||
OFFSET(ldkfs), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, UCHAR_MAX, VE },
|
||||
{ "intra-refresh","Use Periodic Intra Refresh instead of IDR frames",
|
||||
OFFSET(intra_refresh),AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE },
|
||||
{ "timing-info", "Include timing info in sequence/frame headers",
|
||||
OFFSET(timing_info), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE },
|
||||
{ "extra_sei", "Pass on extra SEI data (e.g. a53 cc) to be included in the bitstream",
|
||||
OFFSET(extra_sei), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, VE },
|
||||
{ "a53cc", "Use A53 Closed Captions (if available)", OFFSET(a53_cc), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, VE },
|
||||
{ "s12m_tc", "Use timecode (if available)", OFFSET(s12m_tc), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, VE },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
static const FFCodecDefault defaults[] = {
|
||||
{ "b", "2M" },
|
||||
{ "qmin", "-1" },
|
||||
{ "qmax", "-1" },
|
||||
{ "qdiff", "-1" },
|
||||
{ "qblur", "-1" },
|
||||
{ "qcomp", "-1" },
|
||||
{ "g", "250" },
|
||||
{ "bf", "-1" },
|
||||
{ "refs", "0" },
|
||||
{ NULL },
|
||||
};
|
||||
|
||||
static const AVClass av1_nvenc_class = {
|
||||
.class_name = "av1_nvenc",
|
||||
.item_name = av_default_item_name,
|
||||
.option = options,
|
||||
.version = LIBAVUTIL_VERSION_INT,
|
||||
};
|
||||
|
||||
const FFCodec ff_av1_nvenc_encoder = {
|
||||
.p.name = "av1_nvenc",
|
||||
CODEC_LONG_NAME("NVIDIA NVENC av1 encoder"),
|
||||
.p.type = AVMEDIA_TYPE_VIDEO,
|
||||
.p.id = AV_CODEC_ID_AV1,
|
||||
.init = ff_nvenc_encode_init,
|
||||
FF_CODEC_RECEIVE_PACKET_CB(ff_nvenc_receive_packet),
|
||||
.close = ff_nvenc_encode_close,
|
||||
.flush = ff_nvenc_encode_flush,
|
||||
.priv_data_size = sizeof(NvencContext),
|
||||
.p.priv_class = &av1_nvenc_class,
|
||||
.defaults = defaults,
|
||||
.p.pix_fmts = ff_nvenc_pix_fmts,
|
||||
.p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE |
|
||||
AV_CODEC_CAP_ENCODER_FLUSH | AV_CODEC_CAP_DR1,
|
||||
.caps_internal = FF_CODEC_CAP_NOT_INIT_THREADSAFE |
|
||||
FF_CODEC_CAP_INIT_CLEANUP,
|
||||
.p.wrapper_name = "nvenc",
|
||||
.hw_configs = ff_nvenc_hw_configs,
|
||||
};
|
@ -29,8 +29,8 @@
|
||||
|
||||
#include "version_major.h"
|
||||
|
||||
#define LIBAVCODEC_VERSION_MINOR 51
|
||||
#define LIBAVCODEC_VERSION_MICRO 101
|
||||
#define LIBAVCODEC_VERSION_MINOR 52
|
||||
#define LIBAVCODEC_VERSION_MICRO 100
|
||||
|
||||
#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
|
||||
LIBAVCODEC_VERSION_MINOR, \
|
||||
|
Loading…
Reference in New Issue
Block a user