summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoman Arzumanyan <rarzumanyan@nvidia.com>2020-03-19 11:35:29 +0300
committerTimo Rothenpieler <timo@rothenpieler.org>2020-07-01 16:10:00 +0200
commit9115d7722205590b8601d87146087f3559d29d54 (patch)
tree3b1db327a05c7b9b99db050f27da2ebaece3fa79
parentf3dc38a186b2326ce03e50969897ea703817ddb0 (diff)
avcodec/nvenc: add new Video SDK 10 features
1. new Nvenc presets 2. new multipass encode modes 3. low delay key frame scale Signed-off-by: Timo Rothenpieler <timo@rothenpieler.org>
-rw-r--r--libavcodec/nvenc.c70
-rw-r--r--libavcodec/nvenc.h19
-rw-r--r--libavcodec/nvenc_h264.c30
-rw-r--r--libavcodec/nvenc_hevc.c30
-rw-r--r--libavcodec/version.h2
5 files changed, 145 insertions, 6 deletions
diff --git a/libavcodec/nvenc.c b/libavcodec/nvenc.c
index 0981262491..c6740c1842 100644
--- a/libavcodec/nvenc.c
+++ b/libavcodec/nvenc.c
@@ -42,6 +42,12 @@
rc == NV_ENC_PARAMS_RC_CBR_LOWDELAY_HQ || \
rc == NV_ENC_PARAMS_RC_CBR_HQ)
+#ifdef NVENC_HAVE_NEW_PRESETS
+#define IS_SDK10_PRESET(p) ((p) >= PRESET_P1 && (p) <= PRESET_P7)
+#else
+#define IS_SDK10_PRESET(p) 0
+#endif
+
const enum AVPixelFormat ff_nvenc_pix_fmts[] = {
AV_PIX_FMT_YUV420P,
AV_PIX_FMT_NV12,
@@ -145,8 +151,14 @@ static int nvenc_print_error(AVCodecContext *avctx, NVENCSTATUS err,
static void nvenc_print_driver_requirement(AVCodecContext *avctx, int level)
{
-#if NVENCAPI_CHECK_VERSION(9, 2)
+#if NVENCAPI_CHECK_VERSION(10, 1)
const char *minver = "(unknown)";
+#elif NVENCAPI_CHECK_VERSION(10, 0)
+# if defined(_WIN32) || defined(__CYGWIN__)
+ const char *minver = "450.51";
+# else
+ const char *minver = "445.87";
+# endif
#elif NVENCAPI_CHECK_VERSION(9, 1)
# if defined(_WIN32) || defined(__CYGWIN__)
const char *minver = "436.15";
@@ -650,6 +662,15 @@ static void nvenc_map_preset(NvencContext *ctx)
PRESET(LOW_LATENCY_HQ, NVENC_LOWLATENCY),
PRESET(LOSSLESS_DEFAULT, NVENC_LOSSLESS),
PRESET(LOSSLESS_HP, NVENC_LOSSLESS),
+#ifdef NVENC_HAVE_NEW_PRESETS
+ PRESET(P1),
+ PRESET(P2),
+ PRESET(P3),
+ PRESET(P4),
+ PRESET(P5),
+ PRESET(P6),
+ PRESET(P7),
+#endif
};
GUIDTuple *t = &presets[ctx->preset];
@@ -859,6 +880,12 @@ static av_cold void nvenc_setup_rate_control(AVCodecContext *avctx)
if (avctx->rc_max_rate > 0)
ctx->encode_config.rcParams.maxBitRate = avctx->rc_max_rate;
+#ifdef NVENC_HAVE_MULTIPASS
+ ctx->encode_config.rcParams.multiPass = ctx->multipass;
+ if (ctx->encode_config.rcParams.multiPass != NV_ENC_MULTI_PASS_DISABLED)
+ ctx->flags |= NVENC_TWO_PASSES;
+#endif
+
if (ctx->rc < 0) {
if (ctx->flags & NVENC_ONE_PASS)
ctx->twopass = 0;
@@ -893,6 +920,11 @@ static av_cold void nvenc_setup_rate_control(AVCodecContext *avctx)
ctx->rc &= ~RC_MODE_DEPRECATED;
}
+#ifdef NVENC_HAVE_LDKFS
+ if (ctx->ldkfs)
+ ctx->encode_config.rcParams.lowDelayKeyFrameScale = ctx->ldkfs;
+#endif
+
if (ctx->flags & NVENC_LOSSLESS) {
set_lossless(avctx);
} else if (ctx->rc >= 0) {
@@ -1202,10 +1234,27 @@ static av_cold int nvenc_setup_encoder(AVCodecContext *avctx)
preset_config.version = NV_ENC_PRESET_CONFIG_VER;
preset_config.presetCfg.version = NV_ENC_CONFIG_VER;
- nv_status = p_nvenc->nvEncGetEncodePresetConfig(ctx->nvencoder,
- ctx->init_encode_params.encodeGUID,
- ctx->init_encode_params.presetGUID,
- &preset_config);
+ if (IS_SDK10_PRESET(ctx->preset)) {
+#ifdef NVENC_HAVE_NEW_PRESETS
+ ctx->init_encode_params.tuningInfo = ctx->tuning_info;
+
+ nv_status = p_nvenc->nvEncGetEncodePresetConfigEx(ctx->nvencoder,
+ ctx->init_encode_params.encodeGUID,
+ ctx->init_encode_params.presetGUID,
+ ctx->init_encode_params.tuningInfo,
+ &preset_config);
+#endif
+ } else {
+#ifdef NVENC_HAVE_NEW_PRESETS
+ // Turn off tuning info parameter if older presets are on
+ ctx->init_encode_params.tuningInfo = 0;
+#endif
+
+ 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");
@@ -1228,6 +1277,17 @@ static av_cold int nvenc_setup_encoder(AVCodecContext *avctx)
ctx->init_encode_params.enableEncodeAsync = 0;
ctx->init_encode_params.enablePTD = 1;
+#ifdef NVENC_HAVE_NEW_PRESETS
+ /* If lookahead isn't set from CLI, use value from preset.
+ * P6 & P7 presets may enable lookahead for better quality.
+ * */
+ if (ctx->rc_lookahead == 0 && ctx->encode_config.rcParams.enableLookahead)
+ ctx->rc_lookahead = ctx->encode_config.rcParams.lookaheadDepth;
+
+ if (ctx->init_encode_params.tuningInfo == NV_ENC_TUNING_INFO_LOSSLESS)
+ ctx->flags |= NVENC_LOSSLESS;
+#endif
+
if (ctx->weighted_pred == 1)
ctx->init_encode_params.enableWeightedPrediction = 1;
diff --git a/libavcodec/nvenc.h b/libavcodec/nvenc.h
index df0d9caf9c..8392a51cff 100644
--- a/libavcodec/nvenc.h
+++ b/libavcodec/nvenc.h
@@ -62,6 +62,13 @@ typedef void ID3D11Device;
#define NVENC_HAVE_GETLASTERRORSTRING
#endif
+// SDK 10.0 compile time feature checks
+#if NVENCAPI_CHECK_VERSION(10, 0)
+#define NVENC_HAVE_NEW_PRESETS
+#define NVENC_HAVE_MULTIPASS
+#define NVENC_HAVE_LDKFS
+#endif
+
typedef struct NvencSurface
{
NV_ENC_INPUT_PTR input_surface;
@@ -98,6 +105,15 @@ enum {
PRESET_LOW_LATENCY_HP,
PRESET_LOSSLESS_DEFAULT, // lossless presets must be the last ones
PRESET_LOSSLESS_HP,
+#ifdef NVENC_HAVE_NEW_PRESETS
+ PRESET_P1,
+ PRESET_P2,
+ PRESET_P3,
+ PRESET_P4,
+ PRESET_P5,
+ PRESET_P6,
+ PRESET_P7,
+#endif
};
enum {
@@ -198,6 +214,9 @@ typedef struct NvencContext
int a53_cc;
int s12m_tc;
int dpb_size;
+ int tuning_info;
+ int multipass;
+ int ldkfs;
} NvencContext;
int ff_nvenc_encode_init(AVCodecContext *avctx);
diff --git a/libavcodec/nvenc_h264.c b/libavcodec/nvenc_h264.c
index e973e9ee92..0c1a32178c 100644
--- a/libavcodec/nvenc_h264.c
+++ b/libavcodec/nvenc_h264.c
@@ -26,7 +26,11 @@
#define OFFSET(x) offsetof(NvencContext, x)
#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
static const AVOption options[] = {
+#ifdef NVENC_HAVE_NEW_PRESETS
+ { "preset", "Set the encoding preset", OFFSET(preset), AV_OPT_TYPE_INT, { .i64 = PRESET_P4 }, PRESET_DEFAULT, PRESET_P7, VE, "preset" },
+#else
{ "preset", "Set the encoding preset", OFFSET(preset), AV_OPT_TYPE_INT, { .i64 = PRESET_MEDIUM }, PRESET_DEFAULT, PRESET_LOSSLESS_HP, VE, "preset" },
+#endif
{ "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" },
@@ -39,6 +43,20 @@ static const AVOption options[] = {
{ "llhp", "low latency hp", 0, AV_OPT_TYPE_CONST, { .i64 = PRESET_LOW_LATENCY_HP }, 0, 0, VE, "preset" },
{ "lossless", "", 0, AV_OPT_TYPE_CONST, { .i64 = PRESET_LOSSLESS_DEFAULT }, 0, 0, VE, "preset" },
{ "losslesshp", "", 0, AV_OPT_TYPE_CONST, { .i64 = PRESET_LOSSLESS_HP }, 0, 0, VE, "preset" },
+#ifdef NVENC_HAVE_NEW_PRESETS
+ { "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" },
+#endif
{ "profile", "Set the encoding profile", OFFSET(profile), AV_OPT_TYPE_INT, { .i64 = NV_ENC_H264_PROFILE_MAIN }, NV_ENC_H264_PROFILE_BASELINE, NV_ENC_H264_PROFILE_HIGH_444P, VE, "profile" },
{ "baseline", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_H264_PROFILE_BASELINE }, 0, 0, VE, "profile" },
{ "main", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_H264_PROFILE_MAIN }, 0, 0, VE, "profile" },
@@ -142,6 +160,18 @@ static const AVOption options[] = {
{ "a53cc", "Use A53 Closed Captions (if available)", OFFSET(a53_cc), 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 },
+#ifdef NVENC_HAVE_MULTIPASS
+ { "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" },
+#endif
+#ifdef NVENC_HAVE_LDKFS
+ { "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 },
+#endif
{ NULL }
};
diff --git a/libavcodec/nvenc_hevc.c b/libavcodec/nvenc_hevc.c
index a90dd51f5f..074975f78a 100644
--- a/libavcodec/nvenc_hevc.c
+++ b/libavcodec/nvenc_hevc.c
@@ -26,7 +26,11 @@
#define OFFSET(x) offsetof(NvencContext, x)
#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
static const AVOption options[] = {
+#ifdef NVENC_HAVE_NEW_PRESETS
+ { "preset", "Set the encoding preset", OFFSET(preset), AV_OPT_TYPE_INT, { .i64 = PRESET_P4 }, PRESET_DEFAULT, PRESET_P7, VE, "preset" },
+#else
{ "preset", "Set the encoding preset", OFFSET(preset), AV_OPT_TYPE_INT, { .i64 = PRESET_MEDIUM }, PRESET_DEFAULT, PRESET_LOSSLESS_HP, VE, "preset" },
+#endif
{ "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" },
@@ -39,6 +43,20 @@ static const AVOption options[] = {
{ "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" },
+#ifdef NVENC_HAVE_NEW_PRESETS
+ { "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" },
+#endif
{ "profile", "Set the encoding profile", OFFSET(profile), AV_OPT_TYPE_INT, { .i64 = NV_ENC_HEVC_PROFILE_MAIN }, NV_ENC_HEVC_PROFILE_MAIN, FF_PROFILE_HEVC_REXT, VE, "profile" },
{ "main", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_HEVC_PROFILE_MAIN }, 0, 0, VE, "profile" },
{ "main10", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_HEVC_PROFILE_MAIN_10 }, 0, 0, VE, "profile" },
@@ -133,6 +151,18 @@ static const AVOption options[] = {
{ "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 },
+#ifdef NVENC_HAVE_MULTIPASS
+ { "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" },
+#endif
+#ifdef NVENC_HAVE_LDKFS
+ { "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 },
+#endif
{ NULL }
};
diff --git a/libavcodec/version.h b/libavcodec/version.h
index 05f59901ff..c9ce7981b5 100644
--- a/libavcodec/version.h
+++ b/libavcodec/version.h
@@ -29,7 +29,7 @@
#define LIBAVCODEC_VERSION_MAJOR 58
#define LIBAVCODEC_VERSION_MINOR 93
-#define LIBAVCODEC_VERSION_MICRO 101
+#define LIBAVCODEC_VERSION_MICRO 102
#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
LIBAVCODEC_VERSION_MINOR, \