From patchwork Tue Nov 1 23:59:33 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Timo Rothenpieler X-Patchwork-Id: 39108 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a21:999a:b0:a4:2148:650a with SMTP id ve26csp479526pzb; Tue, 1 Nov 2022 16:59:59 -0700 (PDT) X-Google-Smtp-Source: AMsMyM7AFGUQc0SfeF9hFr2HtNl6niA/ASpARZd8iNhmSDSePagH5dbUgVJARXsAHcQJ69hwJuqh X-Received: by 2002:a05:6402:b0e:b0:461:f7a8:3e3a with SMTP id bm14-20020a0564020b0e00b00461f7a83e3amr21559273edb.372.1667347198818; Tue, 01 Nov 2022 16:59:58 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1667347198; cv=none; d=google.com; s=arc-20160816; b=RJ4iT4tt7JJM47wmWPm5e/QDC2DwkHjNQfrbZJ4xsgSJdeBhTt7HtY+zF/epjT94CS xYOTh+oM7pBIz2EIW27TthsVxqoQYnBGD8TgMr26QzI/iv77kpKb/6xZlcI7R5X3ZMMm rNJwUcZwkl0yMCdsaL5FMjZCij1NHB3VVD+bezYBxXGcVm2KIyGtTxQDukAGPDNVx7NL GTtZ77cJFCD9qXpm24UF7CMGVVmtzgGPGdmz4ThFr1coXkV5IgILFqfd4kd8sjNfk9ec 8/z++E2Qwba6JCme95ECY8yPaI+evrirD/uR/piBnbgxNOsOE99b4sx/i0HnjG3mjXBG Z9EA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:cc:reply-to :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:mime-version:message-id:date:to:from :dkim-signature:delivered-to; bh=PyZI6spMilumNhYFgOuGEuy/ar26aBHQCp7YqrLVeNo=; b=07H7gsghZyUWLb/eCu4FnCuJ2IEW/MK/dixLRAzR77jWGVl/ufsL6Y0nmM4xXb3P1I 9JRCY4bkQzquMmT2VLG53yCgWsfz7I/8Q68CpLxK1wnhuNiV59wGtssKwpOdiPQ9wdsX wiXLsCooMoCNlQuh8SF49PPa56ueLUXefIBvQGpMjlvtfIExMsmInGe/1+r6rqRNZS06 heifoT2KRNbtmGZ0dwizUE86s+sP5mszLIEvtT791ixO9eMtzDNiXFVPvN2IetOBRE+u aIRsV1RTCHcz1oUqNUmTr2FtX+5R9PoZhklD6Hch3BUhi1omWqXiYvsB6OshRn37gDDF P4gA== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@rothenpieler.org header.s=mail header.b=kaLlvn3x; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=rothenpieler.org Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id z4-20020a1709067e4400b007413ed9efb1si10887743ejr.543.2022.11.01.16.59.57; Tue, 01 Nov 2022 16:59:58 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@rothenpieler.org header.s=mail header.b=kaLlvn3x; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=rothenpieler.org Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 6474168BBBC; Wed, 2 Nov 2022 01:59:53 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from btbn.de (btbn.de [136.243.74.85]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 5DAE468BDAC for ; Wed, 2 Nov 2022 01:59:47 +0200 (EET) Received: from [authenticated] by btbn.de (Postfix) with ESMTPSA id 4E7702C220C; Wed, 2 Nov 2022 00:59:42 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=rothenpieler.org; s=mail; t=1667347182; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding; bh=AxYuJBn+KzJLtnxnPG9ZvgVRe8aztKe/Yawx8mbf5Iw=; b=kaLlvn3xf3XsTiXbYXVBwy6ZsdxsfV6oAbvd303LlEjLcGW6zf2uZjXcTz3jKRfxs6wGG5 LfqiNNVnOPZ0wdo/20MiQIy98+30789Yl1xA1Z8tYHU12ah9kuSelJK6gc+fM8wvovexM8 5wYoLnECCeUIUZ3JgcatduFR/+E8O7QvYr95TIy424uUbE7/EbRPg01n+JZnrtv/tx95pv 7ATUoaCT5WFCPWM2JxeNrVy/nj627owF5wOhdxNRaLlZKgEsPHEXlWLvb3S5ae3FnE8do2 cfPCiLGEkRuGhErGcykMubLm0lsMCa/5mhpNbajNqylSnWoutCz3PCxvazfPyQ== From: Timo Rothenpieler To: ffmpeg-devel@ffmpeg.org Date: Wed, 2 Nov 2022 00:59:33 +0100 Message-Id: <20221101235933.114146-1-timo@rothenpieler.org> X-Mailer: git-send-email 2.34.1 MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH] avcodec/nvenc: add AV1 encoding support X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Cc: Timo Rothenpieler Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: oZ8+x+lppxYK --- Due to lack of any kind of compatible hardware, I cannot test this yet. Hence I've marked it as experimental, and am submitting it in the hopes of someone with compatible hardware showing up to give it a go. I've tested that it compiles, and gave all the options a good look to make sure they a) still exist and b) make some sense with AV1 It is very likely that this will not work as-is, so I'm unsure if it should be applied as experimental, or if I should wait until I or someone who can test gains access to compatible hardware (right now only the RTX 4090 is available, which obviously is not a sane choice for various reasons). configure | 13 ++- libavcodec/Makefile | 1 + libavcodec/allcodecs.c | 1 + libavcodec/nvenc.c | 112 +++++++++++++++++++++++- libavcodec/nvenc.h | 7 ++ libavcodec/nvenc_av1.c | 191 +++++++++++++++++++++++++++++++++++++++++ libavcodec/version.h | 4 +- 7 files changed, 321 insertions(+), 8 deletions(-) create mode 100644 libavcodec/nvenc_av1.c diff --git a/configure b/configure index 30f0ce4e26..7c180c87c0 100755 --- a/configure +++ b/configure @@ -3184,6 +3184,7 @@ 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" 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 +6467,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.0.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 @@ -7049,6 +7050,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 diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 72d2f92901..32318fd7ed 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -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 diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index 4f1d66cb0c..f5ec3bc6e1 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -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; diff --git a/libavcodec/nvenc.c b/libavcodec/nvenc.c index 3c6fce391d..9a1a1fcc37 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 * * 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 = "???.??"; +# else + const char *minver = "???.??"; +# 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; } @@ -1325,6 +1336,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); + } + + switch (ctx->profile) { + case NV_ENC_AV1_PROFILE_MAIN: + cc->profileGUID = NV_ENC_AV1_PROFILE_MAIN_GUID; + avctx->profile = FF_PROFILE_AV1_MAIN; + break; + case NV_ENC_AV1_PROFILE_HIGH: + cc->profileGUID = NV_ENC_AV1_PROFILE_HIGH_GUID; + avctx->profile = FF_PROFILE_AV1_HIGH; + break; + } + + 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->enableTimingInfo = 1; + + av1->disableSeqHdr = (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) ? 1 : 0; + av1->repeatSeqHdr = (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) ? 0 : 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) ? 2 : 0; + + av1->level = ctx->level; + av1->tier = ctx->tier; + + 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) { @@ -1332,6 +1423,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. */ } @@ -2023,6 +2118,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 } } diff --git a/libavcodec/nvenc.h b/libavcodec/nvenc.h index 9eb129952e..c5d502b0d7 100644 --- a/libavcodec/nvenc.h +++ b/libavcodec/nvenc.h @@ -136,6 +136,11 @@ enum { NV_ENC_HEVC_PROFILE_REXT, }; +enum { + NV_ENC_AV1_PROFILE_MAIN, + NV_ENC_AV1_PROFILE_HIGH, +}; + enum { NVENC_LOWLATENCY = 1, NVENC_LOSSLESS = 2, @@ -199,6 +204,8 @@ typedef struct NvencContext int tier; int rc; int cbr; + int tile_rows; + int tile_cols; int twopass; int device; int flags; diff --git a/libavcodec/nvenc_av1.c b/libavcodec/nvenc_av1.c new file mode 100644 index 0000000000..03e4145028 --- /dev/null +++ b/libavcodec/nvenc_av1.c @@ -0,0 +1,191 @@ +/* + * 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" }, + { "profile", "Set the encoding profile", OFFSET(profile), AV_OPT_TYPE_INT, { .i64 = NV_ENC_AV1_PROFILE_MAIN }, NV_ENC_AV1_PROFILE_MAIN, NV_ENC_AV1_PROFILE_HIGH, VE, "profile" }, + { "main", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_AV1_PROFILE_MAIN }, 0, 0, VE, "profile" }, + { "high", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_AV1_PROFILE_HIGH }, 0, 0, VE, "profile" }, + { "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" }, + { "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 }, + { "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 }, + { "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 }, + { "init_qpP", "Initial QP value for P frame", OFFSET(init_qp_p), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 51, VE }, + { "init_qpB", "Initial QP value for B frame", OFFSET(init_qp_b), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 51, VE }, + { "init_qpI", "Initial QP value for I frame", OFFSET(init_qp_i), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 51, VE }, + { "qp", "Constant quantization parameter rate control method", + OFFSET(cqp), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 51, 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 }, + { "weighted_pred","Set 1 to enable weighted prediction", + OFFSET(weighted_pred),AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE }, + { "b_ref_mode", "Use B frames as references", OFFSET(b_ref_mode), AV_OPT_TYPE_INT, { .i64 = NV_ENC_BFRAME_REF_MODE_DISABLED }, NV_ENC_BFRAME_REF_MODE_DISABLED, 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" }, + { "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 }, + { "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 }, + { "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 }, + { "udu_sei", "Pass on user data unregistered SEI if available", + OFFSET(udu_sei), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, + { "intra-refresh","Use Periodic Intra Refresh instead of IDR frames", + OFFSET(intra_refresh),AV_OPT_TYPE_BOOL, { .i64 = 0 }, 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 | + AV_CODEC_CAP_EXPERIMENTAL, + .caps_internal = FF_CODEC_CAP_NOT_INIT_THREADSAFE | + FF_CODEC_CAP_INIT_CLEANUP, + .p.wrapper_name = "nvenc", + .hw_configs = ff_nvenc_hw_configs, +}; diff --git a/libavcodec/version.h b/libavcodec/version.h index 43d0d9a9fc..86ac0f3871 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -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, \