diff mbox series

[FFmpeg-devel] avcodec/nvenc: add AV1 encoding support

Message ID 20221101235933.114146-1-timo@rothenpieler.org
State New
Headers show
Series [FFmpeg-devel] avcodec/nvenc: add AV1 encoding support | expand

Checks

Context Check Description
yinshiyou/make_loongarch64 success Make finished
yinshiyou/make_fate_loongarch64 success Make fate finished
andriy/make_x86 success Make finished
andriy/make_fate_x86 success Make fate finished

Commit Message

Timo Rothenpieler Nov. 1, 2022, 11:59 p.m. UTC
---

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

Comments

Andreas Rheinhardt Nov. 2, 2022, 1:14 a.m. UTC | #1
Timo Rothenpieler:
> ---
> 
> 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 <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 = "???.??";
> +# else
> +    const char *minver = "???.??";
> +# endif

Either one of the above is wrong or the above #if is superfluous (or I
am blind).

>  #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;
>  }
>
Timo Rothenpieler Nov. 2, 2022, 10:12 a.m. UTC | #2
On 02/11/2022 02:14, Andreas Rheinhardt wrote:
> Timo Rothenpieler:
>> ---
>>
>> 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 <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 = "???.??";
>> +# else
>> +    const char *minver = "???.??";
>> +# endif
> 
> Either one of the above is wrong or the above #if is superfluous (or I
> am blind).

Video SDK 12 is not released yet, so there is no documentation on the 
driver versions.
Whenever it gets release, which was scheduled to happen in October 
already, those need filled in.
diff mbox series

Patch

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 <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 = "???.??";
+# 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, \