[FFmpeg-cvslog] avcodec/nvenc: use AVOptions to select presets

Andrey Turkin git at videolan.org
Tue May 31 15:52:46 CEST 2016


ffmpeg | branch: master | Andrey Turkin <andrey.turkin at gmail.com> | Wed May 25 17:05:50 2016 +0300| [faffff88c21c24765e5a3c87ffc657b191c4efc0] | committer: Timo Rothenpieler

avcodec/nvenc: use AVOptions to select presets

Signed-off-by: Timo Rothenpieler <timo at rothenpieler.org>

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=faffff88c21c24765e5a3c87ffc657b191c4efc0
---

 libavcodec/nvenc.c      |  255 +++++++++++++++++++++++------------------------
 libavcodec/nvenc.h      |   25 ++++-
 libavcodec/nvenc_h264.c |   14 ++-
 libavcodec/nvenc_hevc.c |   14 ++-
 4 files changed, 177 insertions(+), 131 deletions(-)

diff --git a/libavcodec/nvenc.c b/libavcodec/nvenc.c
index 4e42202..7166b9d 100644
--- a/libavcodec/nvenc.c
+++ b/libavcodec/nvenc.c
@@ -302,7 +302,7 @@ static av_cold int nvenc_check_cuda(AVCodecContext *avctx)
         goto error;
     }
 
-    if (!strncmp(ctx->preset, "lossless", 8))
+    if (ctx->preset >= PRESET_LOSSLESS_DEFAULT)
         target_smver = 0x52;
 
     if (!nvenc_dyload_cuda(avctx))
@@ -444,6 +444,17 @@ static av_cold int nvenc_setup_device(AVCodecContext *avctx)
     CUresult cu_res;
     CUcontext cu_context_curr;
 
+    switch (avctx->codec->id) {
+    case AV_CODEC_ID_H264:
+        ctx->init_encode_params.encodeGUID = NV_ENC_CODEC_H264_GUID;
+        break;
+    case AV_CODEC_ID_HEVC:
+        ctx->init_encode_params.encodeGUID = NV_ENC_CODEC_HEVC_GUID;
+        break;
+    default:
+        return AVERROR_BUG;
+    }
+
     ctx->data_pix_fmt = avctx->pix_fmt;
 
 #if CONFIG_CUDA
@@ -512,6 +523,34 @@ static av_cold int nvenc_open_session(AVCodecContext *avctx)
     return 0;
 }
 
+typedef struct GUIDTuple {
+    const GUID guid;
+    int flags;
+} GUIDTuple;
+
+static void nvenc_map_preset(NvencContext *ctx)
+{
+    GUIDTuple presets[] = {
+        { NV_ENC_PRESET_DEFAULT_GUID },
+        { NV_ENC_PRESET_HQ_GUID,                  NVENC_TWO_PASSES }, /* slow */
+        { NV_ENC_PRESET_HQ_GUID,                  NVENC_ONE_PASS }, /* medium */
+        { NV_ENC_PRESET_HP_GUID,                  NVENC_ONE_PASS }, /* fast */
+        { NV_ENC_PRESET_HP_GUID },
+        { NV_ENC_PRESET_HQ_GUID },
+        { NV_ENC_PRESET_BD_GUID },
+        { NV_ENC_PRESET_LOW_LATENCY_DEFAULT_GUID, NVENC_LOWLATENCY },
+        { NV_ENC_PRESET_LOW_LATENCY_HQ_GUID,      NVENC_LOWLATENCY },
+        { NV_ENC_PRESET_LOW_LATENCY_HP_GUID,      NVENC_LOWLATENCY },
+        { NV_ENC_PRESET_LOSSLESS_DEFAULT_GUID,    NVENC_LOSSLESS },
+        { NV_ENC_PRESET_LOSSLESS_HP_GUID,         NVENC_LOSSLESS },
+    };
+
+    GUIDTuple *t = &presets[ctx->preset];
+
+    ctx->init_encode_params.presetGUID = t->guid;
+    ctx->flags = t->flags;
+}
+
 static av_cold void set_constqp(AVCodecContext *avctx)
 {
     NvencContext *ctx = avctx->priv_data;
@@ -548,7 +587,7 @@ static av_cold void set_lossless(AVCodecContext *avctx)
     ctx->encode_config.rcParams.constQP.qpIntra = 0;
 }
 
-static av_cold void nvenc_setup_rate_control(AVCodecContext *avctx, int lossless)
+static av_cold void nvenc_setup_rate_control(AVCodecContext *avctx)
 {
     NvencContext *ctx = avctx->priv_data;
 
@@ -563,7 +602,7 @@ static av_cold void nvenc_setup_rate_control(AVCodecContext *avctx, int lossless
     if (avctx->rc_max_rate > 0)
         ctx->encode_config.rcParams.maxBitRate = avctx->rc_max_rate;
 
-    if (lossless) {
+    if (ctx->flags & NVENC_LOSSLESS) {
         if (avctx->codec->id == AV_CODEC_ID_H264)
             ctx->encode_config.encodeCodecConfig.h264Config.qpPrimeYZeroTransformBypassFlag = 1;
 
@@ -641,65 +680,68 @@ static av_cold void nvenc_setup_rate_control(AVCodecContext *avctx, int lossless
     }
 }
 
-static av_cold int nvenc_setup_h264_config(AVCodecContext *avctx, int lossless)
+static av_cold int nvenc_setup_h264_config(AVCodecContext *avctx)
 {
-    NvencContext *ctx = avctx->priv_data;
+    NvencContext *ctx                      = avctx->priv_data;
+    NV_ENC_CONFIG *cc                      = &ctx->encode_config;
+    NV_ENC_CONFIG_H264 *h264               = &cc->encodeCodecConfig.h264Config;
+    NV_ENC_CONFIG_H264_VUI_PARAMETERS *vui = &h264->h264VUIParameters;
     int res;
 
-    ctx->encode_config.encodeCodecConfig.h264Config.h264VUIParameters.colourMatrix = avctx->colorspace;
-    ctx->encode_config.encodeCodecConfig.h264Config.h264VUIParameters.colourPrimaries = avctx->color_primaries;
-    ctx->encode_config.encodeCodecConfig.h264Config.h264VUIParameters.transferCharacteristics = avctx->color_trc;
-    ctx->encode_config.encodeCodecConfig.h264Config.h264VUIParameters.videoFullRangeFlag = (avctx->color_range == AVCOL_RANGE_JPEG
+    vui->colourMatrix = avctx->colorspace;
+    vui->colourPrimaries = avctx->color_primaries;
+    vui->transferCharacteristics = avctx->color_trc;
+    vui->videoFullRangeFlag = (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);
 
-    ctx->encode_config.encodeCodecConfig.h264Config.h264VUIParameters.colourDescriptionPresentFlag =
+    vui->colourDescriptionPresentFlag =
         (avctx->colorspace != 2 || avctx->color_primaries != 2 || avctx->color_trc != 2);
 
-    ctx->encode_config.encodeCodecConfig.h264Config.h264VUIParameters.videoSignalTypePresentFlag =
-        (ctx->encode_config.encodeCodecConfig.h264Config.h264VUIParameters.colourDescriptionPresentFlag
-        || ctx->encode_config.encodeCodecConfig.h264Config.h264VUIParameters.videoFormat != 5
-        || ctx->encode_config.encodeCodecConfig.h264Config.h264VUIParameters.videoFullRangeFlag != 0);
+    vui->videoSignalTypePresentFlag =
+        (vui->colourDescriptionPresentFlag
+        || vui->videoFormat != 5
+        || vui->videoFullRangeFlag != 0);
 
-    ctx->encode_config.encodeCodecConfig.h264Config.sliceMode = 3;
-    ctx->encode_config.encodeCodecConfig.h264Config.sliceModeData = 1;
+    h264->sliceMode = 3;
+    h264->sliceModeData = 1;
 
-    ctx->encode_config.encodeCodecConfig.h264Config.disableSPSPPS = (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) ? 1 : 0;
-    ctx->encode_config.encodeCodecConfig.h264Config.repeatSPSPPS = (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) ? 0 : 1;
+    h264->disableSPSPPS = (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) ? 1 : 0;
+    h264->repeatSPSPPS = (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) ? 0 : 1;
 
-    ctx->encode_config.encodeCodecConfig.h264Config.outputAUD = 1;
+    h264->outputAUD = 1;
 
-    if (!ctx->profile && !lossless) {
+    if (!ctx->profile && !(ctx->flags & NVENC_LOSSLESS)) {
         switch (avctx->profile) {
         case FF_PROFILE_H264_HIGH_444_PREDICTIVE:
-            ctx->encode_config.profileGUID = NV_ENC_H264_PROFILE_HIGH_444_GUID;
+            cc->profileGUID = NV_ENC_H264_PROFILE_HIGH_444_GUID;
             break;
         case FF_PROFILE_H264_BASELINE:
-            ctx->encode_config.profileGUID = NV_ENC_H264_PROFILE_BASELINE_GUID;
+            cc->profileGUID = NV_ENC_H264_PROFILE_BASELINE_GUID;
             break;
         case FF_PROFILE_H264_MAIN:
-            ctx->encode_config.profileGUID = NV_ENC_H264_PROFILE_MAIN_GUID;
+            cc->profileGUID = NV_ENC_H264_PROFILE_MAIN_GUID;
             break;
         case FF_PROFILE_H264_HIGH:
         case FF_PROFILE_UNKNOWN:
-            ctx->encode_config.profileGUID = NV_ENC_H264_PROFILE_HIGH_GUID;
+            cc->profileGUID = NV_ENC_H264_PROFILE_HIGH_GUID;
             break;
         default:
             av_log(avctx, AV_LOG_WARNING, "Unsupported profile requested, falling back to high\n");
-            ctx->encode_config.profileGUID = NV_ENC_H264_PROFILE_HIGH_GUID;
+            cc->profileGUID = NV_ENC_H264_PROFILE_HIGH_GUID;
             break;
         }
-    } else if (!lossless) {
+    } else if (!(ctx->flags & NVENC_LOSSLESS)) {
         if (!strcmp(ctx->profile, "high")) {
-            ctx->encode_config.profileGUID = NV_ENC_H264_PROFILE_HIGH_GUID;
+            cc->profileGUID = NV_ENC_H264_PROFILE_HIGH_GUID;
             avctx->profile = FF_PROFILE_H264_HIGH;
         } else if (!strcmp(ctx->profile, "main")) {
-            ctx->encode_config.profileGUID = NV_ENC_H264_PROFILE_MAIN_GUID;
+            cc->profileGUID = NV_ENC_H264_PROFILE_MAIN_GUID;
             avctx->profile = FF_PROFILE_H264_MAIN;
         } else if (!strcmp(ctx->profile, "baseline")) {
-            ctx->encode_config.profileGUID = NV_ENC_H264_PROFILE_BASELINE_GUID;
+            cc->profileGUID = NV_ENC_H264_PROFILE_BASELINE_GUID;
             avctx->profile = FF_PROFILE_H264_BASELINE;
         } else if (!strcmp(ctx->profile, "high444p")) {
-            ctx->encode_config.profileGUID = NV_ENC_H264_PROFILE_HIGH_444_GUID;
+            cc->profileGUID = NV_ENC_H264_PROFILE_HIGH_444_GUID;
             avctx->profile = FF_PROFILE_H264_HIGH_444_PREDICTIVE;
         } else {
             av_log(avctx, AV_LOG_FATAL, "Profile \"%s\" is unknown! Supported profiles: high, main, baseline\n", ctx->profile);
@@ -709,21 +751,21 @@ static av_cold int nvenc_setup_h264_config(AVCodecContext *avctx, int lossless)
 
     // force setting profile as high444p if input is AV_PIX_FMT_YUV444P
     if (ctx->data_pix_fmt == AV_PIX_FMT_YUV444P) {
-        ctx->encode_config.profileGUID = NV_ENC_H264_PROFILE_HIGH_444_GUID;
+        cc->profileGUID = NV_ENC_H264_PROFILE_HIGH_444_GUID;
         avctx->profile = FF_PROFILE_H264_HIGH_444_PREDICTIVE;
     }
 
-    ctx->encode_config.encodeCodecConfig.h264Config.chromaFormatIDC = avctx->profile == FF_PROFILE_H264_HIGH_444_PREDICTIVE ? 3 : 1;
+    h264->chromaFormatIDC = avctx->profile == FF_PROFILE_H264_HIGH_444_PREDICTIVE ? 3 : 1;
 
     if (ctx->level) {
-        res = input_string_to_uint32(avctx, nvenc_h264_level_pairs, ctx->level, &ctx->encode_config.encodeCodecConfig.h264Config.level);
+        res = input_string_to_uint32(avctx, nvenc_h264_level_pairs, ctx->level, &h264->level);
 
         if (res) {
             av_log(avctx, AV_LOG_FATAL, "Level \"%s\" is unknown! Supported levels: auto, 1, 1b, 1.1, 1.2, 1.3, 2, 2.1, 2.2, 3, 3.1, 3.2, 4, 4.1, 4.2, 5, 5.1\n", ctx->level);
             return res;
         }
     } else {
-        ctx->encode_config.encodeCodecConfig.h264Config.level = NV_ENC_LEVEL_AUTOSELECT;
+        h264->level = NV_ENC_LEVEL_AUTOSELECT;
     }
 
     return 0;
@@ -731,51 +773,54 @@ static av_cold int nvenc_setup_h264_config(AVCodecContext *avctx, int lossless)
 
 static av_cold int nvenc_setup_hevc_config(AVCodecContext *avctx)
 {
-    NvencContext *ctx = avctx->priv_data;
+    NvencContext *ctx                      = avctx->priv_data;
+    NV_ENC_CONFIG *cc                      = &ctx->encode_config;
+    NV_ENC_CONFIG_HEVC *hevc               = &cc->encodeCodecConfig.hevcConfig;
+    NV_ENC_CONFIG_HEVC_VUI_PARAMETERS *vui = &hevc->hevcVUIParameters;
     int res;
 
-    ctx->encode_config.encodeCodecConfig.hevcConfig.hevcVUIParameters.colourMatrix = avctx->colorspace;
-    ctx->encode_config.encodeCodecConfig.hevcConfig.hevcVUIParameters.colourPrimaries = avctx->color_primaries;
-    ctx->encode_config.encodeCodecConfig.hevcConfig.hevcVUIParameters.transferCharacteristics = avctx->color_trc;
-    ctx->encode_config.encodeCodecConfig.hevcConfig.hevcVUIParameters.videoFullRangeFlag = (avctx->color_range == AVCOL_RANGE_JPEG
+    vui->colourMatrix = avctx->colorspace;
+    vui->colourPrimaries = avctx->color_primaries;
+    vui->transferCharacteristics = avctx->color_trc;
+    vui->videoFullRangeFlag = (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);
 
-    ctx->encode_config.encodeCodecConfig.hevcConfig.hevcVUIParameters.colourDescriptionPresentFlag =
+    vui->colourDescriptionPresentFlag =
         (avctx->colorspace != 2 || avctx->color_primaries != 2 || avctx->color_trc != 2);
 
-    ctx->encode_config.encodeCodecConfig.hevcConfig.hevcVUIParameters.videoSignalTypePresentFlag =
-        (ctx->encode_config.encodeCodecConfig.hevcConfig.hevcVUIParameters.colourDescriptionPresentFlag
-        || ctx->encode_config.encodeCodecConfig.hevcConfig.hevcVUIParameters.videoFormat != 5
-        || ctx->encode_config.encodeCodecConfig.hevcConfig.hevcVUIParameters.videoFullRangeFlag != 0);
+    vui->videoSignalTypePresentFlag =
+        (vui->colourDescriptionPresentFlag
+        || vui->videoFormat != 5
+        || vui->videoFullRangeFlag != 0);
 
-    ctx->encode_config.encodeCodecConfig.hevcConfig.sliceMode = 3;
-    ctx->encode_config.encodeCodecConfig.hevcConfig.sliceModeData = 1;
+    hevc->sliceMode = 3;
+    hevc->sliceModeData = 1;
 
-    ctx->encode_config.encodeCodecConfig.hevcConfig.disableSPSPPS = (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) ? 1 : 0;
-    ctx->encode_config.encodeCodecConfig.hevcConfig.repeatSPSPPS = (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) ? 0 : 1;
+    hevc->disableSPSPPS = (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) ? 1 : 0;
+    hevc->repeatSPSPPS = (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) ? 0 : 1;
 
-    ctx->encode_config.encodeCodecConfig.hevcConfig.outputAUD = 1;
+    hevc->outputAUD = 1;
 
     /* No other profile is supported in the current SDK version 5 */
-    ctx->encode_config.profileGUID = NV_ENC_HEVC_PROFILE_MAIN_GUID;
+    cc->profileGUID = NV_ENC_HEVC_PROFILE_MAIN_GUID;
     avctx->profile = FF_PROFILE_HEVC_MAIN;
 
     if (ctx->level) {
-        res = input_string_to_uint32(avctx, nvenc_hevc_level_pairs, ctx->level, &ctx->encode_config.encodeCodecConfig.hevcConfig.level);
+        res = input_string_to_uint32(avctx, nvenc_hevc_level_pairs, ctx->level, &hevc->level);
 
         if (res) {
             av_log(avctx, AV_LOG_FATAL, "Level \"%s\" is unknown! Supported levels: auto, 1, 2, 2.1, 3, 3.1, 4, 4.1, 5, 5.1, 5.2, 6, 6.1, 6.2\n", ctx->level);
             return res;
         }
     } else {
-        ctx->encode_config.encodeCodecConfig.hevcConfig.level = NV_ENC_LEVEL_AUTOSELECT;
+        hevc->level = NV_ENC_LEVEL_AUTOSELECT;
     }
 
     if (ctx->tier) {
         if (!strcmp(ctx->tier, "main")) {
-            ctx->encode_config.encodeCodecConfig.hevcConfig.tier = NV_ENC_TIER_HEVC_MAIN;
+            hevc->tier = NV_ENC_TIER_HEVC_MAIN;
         } else if (!strcmp(ctx->tier, "high")) {
-            ctx->encode_config.encodeCodecConfig.hevcConfig.tier = NV_ENC_TIER_HEVC_HIGH;
+            hevc->tier = NV_ENC_TIER_HEVC_HIGH;
         } else {
             av_log(avctx, AV_LOG_FATAL, "Tier \"%s\" is unknown! Supported tiers: main, high\n", ctx->tier);
             return AVERROR(EINVAL);
@@ -785,12 +830,12 @@ static av_cold int nvenc_setup_hevc_config(AVCodecContext *avctx)
     return 0;
 }
 
-static av_cold int nvenc_setup_codec_config(AVCodecContext *avctx, int lossless)
+static av_cold int nvenc_setup_codec_config(AVCodecContext *avctx)
 {
     switch (avctx->codec->id) {
     case AV_CODEC_ID_H264:
-        return nvenc_setup_h264_config(avctx, lossless);
-    case AV_CODEC_ID_H265:
+        return nvenc_setup_h264_config(avctx);
+    case AV_CODEC_ID_HEVC:
         return nvenc_setup_hevc_config(avctx);
     /* Earlier switch/case will return if unknown codec is passed. */
     }
@@ -805,13 +850,9 @@ static av_cold int nvenc_setup_encoder(AVCodecContext *avctx)
     NV_ENCODE_API_FUNCTION_LIST *p_nvenc = &dl_fn->nvenc_funcs;
 
     NV_ENC_PRESET_CONFIG preset_config = { 0 };
-    GUID encoder_preset = NV_ENC_PRESET_HQ_GUID;
-    GUID codec;
     NVENCSTATUS nv_status = NV_ENC_SUCCESS;
     AVCPBProperties *cpb_props;
     int num_mbs;
-    int isLL = 0;
-    int lossless = 0;
     int res = 0;
     int dw, dh;
 
@@ -819,72 +860,36 @@ static av_cold int nvenc_setup_encoder(AVCodecContext *avctx)
 
     ctx->encode_config.version = NV_ENC_CONFIG_VER;
     ctx->init_encode_params.version = NV_ENC_INITIALIZE_PARAMS_VER;
-    preset_config.version = NV_ENC_PRESET_CONFIG_VER;
-    preset_config.presetCfg.version = NV_ENC_CONFIG_VER;
 
-    if (ctx->preset) {
-        if (!strcmp(ctx->preset, "slow")) {
-            encoder_preset = NV_ENC_PRESET_HQ_GUID;
-            ctx->twopass = 1;
-        } else if (!strcmp(ctx->preset, "medium")) {
-            encoder_preset = NV_ENC_PRESET_HQ_GUID;
-            ctx->twopass = 0;
-        } else if (!strcmp(ctx->preset, "fast")) {
-            encoder_preset = NV_ENC_PRESET_HP_GUID;
-            ctx->twopass = 0;
-        } else if (!strcmp(ctx->preset, "hq")) {
-            encoder_preset = NV_ENC_PRESET_HQ_GUID;
-        } else if (!strcmp(ctx->preset, "hp")) {
-            encoder_preset = NV_ENC_PRESET_HP_GUID;
-        } else if (!strcmp(ctx->preset, "bd")) {
-            encoder_preset = NV_ENC_PRESET_BD_GUID;
-        } else if (!strcmp(ctx->preset, "ll")) {
-            encoder_preset = NV_ENC_PRESET_LOW_LATENCY_DEFAULT_GUID;
-            isLL = 1;
-        } else if (!strcmp(ctx->preset, "llhp")) {
-            encoder_preset = NV_ENC_PRESET_LOW_LATENCY_HP_GUID;
-            isLL = 1;
-        } else if (!strcmp(ctx->preset, "llhq")) {
-            encoder_preset = NV_ENC_PRESET_LOW_LATENCY_HQ_GUID;
-            isLL = 1;
-        } else if (!strcmp(ctx->preset, "lossless")) {
-            encoder_preset = NV_ENC_PRESET_LOSSLESS_DEFAULT_GUID;
-            lossless = 1;
-        } else if (!strcmp(ctx->preset, "losslesshp")) {
-            encoder_preset = NV_ENC_PRESET_LOSSLESS_HP_GUID;
-            lossless = 1;
-        } else if (!strcmp(ctx->preset, "default")) {
-            encoder_preset = NV_ENC_PRESET_DEFAULT_GUID;
-        } else {
-            av_log(avctx, AV_LOG_FATAL, "Preset \"%s\" is unknown! Supported presets: slow, medium, fast, hp, hq, bd, ll, llhp, llhq, lossless, losslesshp, default\n", ctx->preset);
-            return AVERROR(EINVAL);
-        }
-    }
+    ctx->init_encode_params.encodeHeight = avctx->height;
+    ctx->init_encode_params.encodeWidth = avctx->width;
+
+    ctx->init_encode_params.encodeConfig = &ctx->encode_config;
+
+    nvenc_map_preset(ctx);
+
+    if (ctx->flags & NVENC_ONE_PASS)
+        ctx->twopass = 0;
+    if (ctx->flags & NVENC_TWO_PASSES)
+        ctx->twopass = 1;
 
     if (ctx->twopass < 0) {
-        ctx->twopass = isLL;
+        ctx->twopass = (ctx->flags & NVENC_LOWLATENCY) != 0;
     }
 
-    switch (avctx->codec->id) {
-    case AV_CODEC_ID_H264:
-        codec = NV_ENC_CODEC_H264_GUID;
-        break;
-    case AV_CODEC_ID_H265:
-        codec = NV_ENC_CODEC_HEVC_GUID;
-        break;
-    default:
-        av_log(avctx, AV_LOG_ERROR, "Unknown codec name\n");
-        return AVERROR(EINVAL);
-    }
+    preset_config.version = NV_ENC_PRESET_CONFIG_VER;
+    preset_config.presetCfg.version = NV_ENC_CONFIG_VER;
 
-    nv_status = p_nvenc->nvEncGetEncodePresetConfig(ctx->nvencoder, codec, encoder_preset, &preset_config);
-    if (nv_status != NV_ENC_SUCCESS) {
-        return nvenc_print_error(avctx, nv_status, "GetEncodePresetConfig failed");
-    }
+    nv_status = p_nvenc->nvEncGetEncodePresetConfig(ctx->nvencoder,
+                                                    ctx->init_encode_params.encodeGUID,
+                                                    ctx->init_encode_params.presetGUID,
+                                                    &preset_config);
+    if (nv_status != NV_ENC_SUCCESS)
+        return nvenc_print_error(avctx, nv_status, "Cannot get the preset configuration");
 
-    ctx->init_encode_params.encodeGUID = codec;
-    ctx->init_encode_params.encodeHeight = avctx->height;
-    ctx->init_encode_params.encodeWidth = avctx->width;
+    memcpy(&ctx->encode_config, &preset_config.presetCfg, sizeof(ctx->encode_config));
+
+    ctx->encode_config.version = NV_ENC_CONFIG_VER;
 
     if (avctx->sample_aspect_ratio.num && avctx->sample_aspect_ratio.den &&
         (avctx->sample_aspect_ratio.num != 1 || avctx->sample_aspect_ratio.num != 1)) {
@@ -923,12 +928,6 @@ static av_cold int nvenc_setup_encoder(AVCodecContext *avctx)
     ctx->init_encode_params.enableEncodeAsync = 0;
     ctx->init_encode_params.enablePTD = 1;
 
-    ctx->init_encode_params.presetGUID = encoder_preset;
-
-    ctx->init_encode_params.encodeConfig = &ctx->encode_config;
-    memcpy(&ctx->encode_config, &preset_config.presetCfg, sizeof(ctx->encode_config));
-    ctx->encode_config.version = NV_ENC_CONFIG_VER;
-
     if (avctx->refs >= 0) {
         /* 0 means "let the hardware decide" */
         switch (avctx->codec->id) {
@@ -976,7 +975,7 @@ static av_cold int nvenc_setup_encoder(AVCodecContext *avctx)
     if (ctx->encode_config.frameIntervalP >= 2)
         ctx->last_dts = -2;
 
-    nvenc_setup_rate_control(avctx, lossless);
+    nvenc_setup_rate_control(avctx);
 
     if (avctx->flags & AV_CODEC_FLAG_INTERLACED_DCT) {
         ctx->encode_config.frameFieldMode = NV_ENC_PARAMS_FRAME_FIELD_MODE_FIELD;
@@ -984,7 +983,7 @@ static av_cold int nvenc_setup_encoder(AVCodecContext *avctx)
         ctx->encode_config.frameFieldMode = NV_ENC_PARAMS_FRAME_FIELD_MODE_FRAME;
     }
 
-    res = nvenc_setup_codec_config(avctx, lossless);
+    res = nvenc_setup_codec_config(avctx);
     if (res)
         return res;
 
diff --git a/libavcodec/nvenc.h b/libavcodec/nvenc.h
index fdb6350..5b81fc8 100644
--- a/libavcodec/nvenc.h
+++ b/libavcodec/nvenc.h
@@ -104,6 +104,28 @@ typedef struct NvencDynLoadFunctions
 
 } NvencDynLoadFunctions;
 
+enum {
+    PRESET_DEFAULT = 0,
+    PRESET_SLOW,
+    PRESET_MEDIUM,
+    PRESET_FAST,
+    PRESET_HP,
+    PRESET_HQ,
+    PRESET_BD ,
+    PRESET_LOW_LATENCY_DEFAULT ,
+    PRESET_LOW_LATENCY_HQ ,
+    PRESET_LOW_LATENCY_HP,
+    PRESET_LOSSLESS_DEFAULT, // lossless presets must be the last ones
+    PRESET_LOSSLESS_HP,
+};
+
+enum {
+    NVENC_LOWLATENCY = 1,
+    NVENC_LOSSLESS   = 2,
+    NVENC_ONE_PASS   = 4,
+    NVENC_TWO_PASSES = 8,
+};
+
 typedef struct NvencContext
 {
     AVClass *avclass;
@@ -137,13 +159,14 @@ typedef struct NvencContext
 
     void *nvencoder;
 
-    char *preset;
+    int preset;
     char *profile;
     char *level;
     char *tier;
     int cbr;
     int twopass;
     int gpu;
+    int flags;
     int buffer_delay;
 } NvencContext;
 
diff --git a/libavcodec/nvenc_h264.c b/libavcodec/nvenc_h264.c
index f91cafa..0ed3f7c 100644
--- a/libavcodec/nvenc_h264.c
+++ b/libavcodec/nvenc_h264.c
@@ -26,7 +26,19 @@
 #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 (one of slow = hq 2pass, medium = hq, fast = hp, hq, hp, bd, ll, llhq, llhp, lossless, losslesshp, default)", OFFSET(preset), AV_OPT_TYPE_STRING, { .str = "medium" }, 0, 0, VE },
+    { "preset",   "Set the encoding preset",              OFFSET(preset),      AV_OPT_TYPE_INT,    { .i64 = PRESET_MEDIUM }, PRESET_DEFAULT, PRESET_LOSSLESS_HP, 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" },
+    { "hp",         "",                                   0,                   AV_OPT_TYPE_CONST,  { .i64 = PRESET_HP }, 0, 0, VE, "preset" },
+    { "hq",         "",                                   0,                   AV_OPT_TYPE_CONST,  { .i64 = PRESET_HQ }, 0, 0, VE, "preset" },
+    { "bd",         "",                                   0,                   AV_OPT_TYPE_CONST,  { .i64 = PRESET_BD }, 0, 0, VE, "preset" },
+    { "ll",         "low latency",                        0,                   AV_OPT_TYPE_CONST,  { .i64 = PRESET_LOW_LATENCY_DEFAULT }, 0, 0, VE, "preset" },
+    { "llhq",       "low latency hq",                     0,                   AV_OPT_TYPE_CONST,  { .i64 = PRESET_LOW_LATENCY_HQ }, 0, 0, VE, "preset" },
+    { "llhp",       "low latency hp",                     0,                   AV_OPT_TYPE_CONST,  { .i64 = PRESET_LOW_LATENCY_HP }, 0, 0, VE, "preset" },
+    { "lossless",   NULL,                                 0,                   AV_OPT_TYPE_CONST,  { .i64 = PRESET_LOSSLESS_DEFAULT }, 0, 0, VE, "preset" },
+    { "losslesshp", NULL,                                 0,                   AV_OPT_TYPE_CONST,  { .i64 = PRESET_LOSSLESS_HP }, 0, 0, VE, "preset" },
     { "profile", "Set the encoding profile (high, main, baseline or high444p)", OFFSET(profile), AV_OPT_TYPE_STRING, { .str = "main" }, 0, 0, VE },
     { "level", "Set the encoding level restriction (auto, 1.0, 1.0b, 1.1, 1.2, ..., 4.2, 5.0, 5.1)", OFFSET(level), AV_OPT_TYPE_STRING, { .str = "auto" }, 0, 0, VE },
     { "cbr", "Use cbr encoding mode", OFFSET(cbr), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE },
diff --git a/libavcodec/nvenc_hevc.c b/libavcodec/nvenc_hevc.c
index 5f8d661..28e28b3 100644
--- a/libavcodec/nvenc_hevc.c
+++ b/libavcodec/nvenc_hevc.c
@@ -26,7 +26,19 @@
 #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 (one of slow = hq 2pass, medium = hq, fast = hp, hq, hp, bd, ll, llhq, llhp, lossless, losslesshp, default)", OFFSET(preset), AV_OPT_TYPE_STRING, { .str = "medium" }, 0, 0, VE },
+    { "preset",   "Set the encoding preset",              OFFSET(preset),      AV_OPT_TYPE_INT,    { .i64 = PRESET_MEDIUM }, PRESET_DEFAULT, PRESET_LOSSLESS_HP, 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" },
+    { "hp",         "",                                   0,                   AV_OPT_TYPE_CONST,  { .i64 = PRESET_HP }, 0, 0, VE, "preset" },
+    { "hq",         "",                                   0,                   AV_OPT_TYPE_CONST,  { .i64 = PRESET_HQ }, 0, 0, VE, "preset" },
+    { "bd",         "",                                   0,                   AV_OPT_TYPE_CONST,  { .i64 = PRESET_BD }, 0, 0, VE, "preset" },
+    { "ll",         "low latency",                        0,                   AV_OPT_TYPE_CONST,  { .i64 = PRESET_LOW_LATENCY_DEFAULT }, 0, 0, VE, "preset" },
+    { "llhq",       "low latency hq",                     0,                   AV_OPT_TYPE_CONST,  { .i64 = PRESET_LOW_LATENCY_HQ }, 0, 0, VE, "preset" },
+    { "llhp",       "low latency hp",                     0,                   AV_OPT_TYPE_CONST,  { .i64 = PRESET_LOW_LATENCY_HP }, 0, 0, VE, "preset" },
+    { "lossless",   "lossless",                           0,                   AV_OPT_TYPE_CONST,  { .i64 = PRESET_LOSSLESS_DEFAULT }, 0, 0, VE, "preset" },
+    { "losslesshp", "lossless hp",                        0,                   AV_OPT_TYPE_CONST,  { .i64 = PRESET_LOSSLESS_HP }, 0, 0, VE, "preset" },
     { "profile", "Set the encoding profile (high, main, baseline or high444p)", OFFSET(profile), AV_OPT_TYPE_STRING, { .str = "main" }, 0, 0, VE },
     { "level", "Set the encoding level restriction (auto, 1.0, 1.0b, 1.1, 1.2, ..., 4.2, 5.0, 5.1)", OFFSET(level), AV_OPT_TYPE_STRING, { .str = "auto" }, 0, 0, VE },
     { "tier", "Set the encoding tier (main or high)", OFFSET(tier), AV_OPT_TYPE_STRING, { .str = "main" }, 0, 0, VE },



More information about the ffmpeg-cvslog mailing list