summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTimo Rothenpieler <timo@rothenpieler.org>2021-04-18 11:17:54 +0200
committerTimo Rothenpieler <timo@rothenpieler.org>2021-04-18 11:39:45 +0200
commit988f2e9eb063db7c1a678729f58aab6eba59a55b (patch)
treeef537b2c8ef60a5389adfdfe52063e12604a32cd
parentd43b26b30dabc6004142b86a87c1d6730735b11c (diff)
avcodec/nvenc: fix lossless tuning logic
Relying on the order of the enum is bad. It clashes with the new presets having to sit at the end of the list, so that they can be properly filtered out by the options parser on builds with older SDKs. So this refactors nvenc.c to instead rely on the internal NVENC_LOSSLESS flag. For this, the preset mapping has to happen much earlier, so it's moved from nvenc_setup_encoder to nvenc_setup_device and thus runs before the device capability check.
-rw-r--r--libavcodec/nvenc.c142
-rw-r--r--libavcodec/nvenc.h2
2 files changed, 74 insertions, 70 deletions
diff --git a/libavcodec/nvenc.c b/libavcodec/nvenc.c
index 60006dc88f..d33ee489d0 100644
--- a/libavcodec/nvenc.c
+++ b/libavcodec/nvenc.c
@@ -152,6 +152,70 @@ static int nvenc_print_error(AVCodecContext *avctx, NVENCSTATUS err,
return ret;
}
+typedef struct GUIDTuple {
+ const GUID guid;
+ int flags;
+} GUIDTuple;
+
+#define PRESET_ALIAS(alias, name, ...) \
+ [PRESET_ ## alias] = { NV_ENC_PRESET_ ## name ## _GUID, __VA_ARGS__ }
+
+#define PRESET(name, ...) PRESET_ALIAS(name, name, __VA_ARGS__)
+
+static void nvenc_map_preset(NvencContext *ctx)
+{
+ GUIDTuple presets[] = {
+#ifdef NVENC_HAVE_NEW_PRESETS
+ PRESET(P1),
+ PRESET(P2),
+ PRESET(P3),
+ PRESET(P4),
+ PRESET(P5),
+ PRESET(P6),
+ PRESET(P7),
+ PRESET_ALIAS(SLOW, P7, NVENC_TWO_PASSES),
+ PRESET_ALIAS(MEDIUM, P4, NVENC_ONE_PASS),
+ PRESET_ALIAS(FAST, P1, NVENC_ONE_PASS),
+ // Compat aliases
+ PRESET_ALIAS(DEFAULT, P4, NVENC_DEPRECATED_PRESET),
+ PRESET_ALIAS(HP, P1, NVENC_DEPRECATED_PRESET),
+ PRESET_ALIAS(HQ, P7, NVENC_DEPRECATED_PRESET),
+ PRESET_ALIAS(BD, P5, NVENC_DEPRECATED_PRESET),
+ PRESET_ALIAS(LOW_LATENCY_DEFAULT, P4, NVENC_DEPRECATED_PRESET | NVENC_LOWLATENCY),
+ PRESET_ALIAS(LOW_LATENCY_HP, P1, NVENC_DEPRECATED_PRESET | NVENC_LOWLATENCY),
+ PRESET_ALIAS(LOW_LATENCY_HQ, P7, NVENC_DEPRECATED_PRESET | NVENC_LOWLATENCY),
+ PRESET_ALIAS(LOSSLESS_DEFAULT, P4, NVENC_DEPRECATED_PRESET | NVENC_LOSSLESS),
+ PRESET_ALIAS(LOSSLESS_HP, P1, NVENC_DEPRECATED_PRESET | NVENC_LOSSLESS),
+#else
+ PRESET(DEFAULT),
+ PRESET(HP),
+ PRESET(HQ),
+ PRESET(BD),
+ PRESET_ALIAS(SLOW, HQ, NVENC_TWO_PASSES),
+ PRESET_ALIAS(MEDIUM, HQ, NVENC_ONE_PASS),
+ PRESET_ALIAS(FAST, HP, NVENC_ONE_PASS),
+ PRESET(LOW_LATENCY_DEFAULT, NVENC_LOWLATENCY),
+ PRESET(LOW_LATENCY_HP, NVENC_LOWLATENCY),
+ PRESET(LOW_LATENCY_HQ, NVENC_LOWLATENCY),
+ PRESET(LOSSLESS_DEFAULT, NVENC_LOSSLESS),
+ PRESET(LOSSLESS_HP, NVENC_LOSSLESS),
+#endif
+ };
+
+ GUIDTuple *t = &presets[ctx->preset];
+
+ ctx->init_encode_params.presetGUID = t->guid;
+ ctx->flags = t->flags;
+
+#ifdef NVENC_HAVE_NEW_PRESETS
+ if (ctx->tuning_info == NV_ENC_TUNING_INFO_LOSSLESS)
+ ctx->flags |= NVENC_LOSSLESS;
+#endif
+}
+
+#undef PRESET
+#undef PRESET_ALIAS
+
static void nvenc_print_driver_requirement(AVCodecContext *avctx, int level)
{
#if NVENCAPI_CHECK_VERSION(11, 1)
@@ -366,7 +430,7 @@ static int nvenc_check_capabilities(AVCodecContext *avctx)
}
ret = nvenc_check_cap(avctx, NV_ENC_CAPS_SUPPORT_LOSSLESS_ENCODE);
- if (ctx->preset >= PRESET_LOSSLESS_DEFAULT && ret <= 0) {
+ if (ctx->flags & NVENC_LOSSLESS && ret <= 0) {
av_log(avctx, AV_LOG_WARNING, "Lossless encoding not supported\n");
return AVERROR(ENOSYS);
}
@@ -556,6 +620,11 @@ static av_cold int nvenc_setup_device(AVCodecContext *avctx)
return AVERROR_BUG;
}
+ nvenc_map_preset(ctx);
+
+ if (ctx->flags & NVENC_DEPRECATED_PRESET)
+ av_log(avctx, AV_LOG_WARNING, "The selected preset is deprecated. Use p1 to p7 + -tune or fast/medium/slow.\n");
+
if (avctx->pix_fmt == AV_PIX_FMT_CUDA || avctx->pix_fmt == AV_PIX_FMT_D3D11 || avctx->hw_frames_ctx || avctx->hw_device_ctx) {
AVHWFramesContext *frames_ctx;
AVHWDeviceContext *hwdev_ctx;
@@ -646,65 +715,6 @@ static av_cold int nvenc_setup_device(AVCodecContext *avctx)
return 0;
}
-typedef struct GUIDTuple {
- const GUID guid;
- int flags;
-} GUIDTuple;
-
-#define PRESET_ALIAS(alias, name, ...) \
- [PRESET_ ## alias] = { NV_ENC_PRESET_ ## name ## _GUID, __VA_ARGS__ }
-
-#define PRESET(name, ...) PRESET_ALIAS(name, name, __VA_ARGS__)
-
-static void nvenc_map_preset(NvencContext *ctx)
-{
- GUIDTuple presets[] = {
-#ifdef NVENC_HAVE_NEW_PRESETS
- PRESET(P1),
- PRESET(P2),
- PRESET(P3),
- PRESET(P4),
- PRESET(P5),
- PRESET(P6),
- PRESET(P7),
- PRESET_ALIAS(SLOW, P7, NVENC_TWO_PASSES),
- PRESET_ALIAS(MEDIUM, P4, NVENC_ONE_PASS),
- PRESET_ALIAS(FAST, P1, NVENC_ONE_PASS),
- // Compat aliases
- PRESET_ALIAS(DEFAULT, P4, NVENC_DEPRECATED_PRESET),
- PRESET_ALIAS(HP, P1, NVENC_DEPRECATED_PRESET),
- PRESET_ALIAS(HQ, P7, NVENC_DEPRECATED_PRESET),
- PRESET_ALIAS(BD, P5, NVENC_DEPRECATED_PRESET),
- PRESET_ALIAS(LOW_LATENCY_DEFAULT, P4, NVENC_DEPRECATED_PRESET | NVENC_LOWLATENCY),
- PRESET_ALIAS(LOW_LATENCY_HP, P1, NVENC_DEPRECATED_PRESET | NVENC_LOWLATENCY),
- PRESET_ALIAS(LOW_LATENCY_HQ, P7, NVENC_DEPRECATED_PRESET | NVENC_LOWLATENCY),
- PRESET_ALIAS(LOSSLESS_DEFAULT, P4, NVENC_DEPRECATED_PRESET | NVENC_LOSSLESS),
- PRESET_ALIAS(LOSSLESS_HP, P1, NVENC_DEPRECATED_PRESET | NVENC_LOSSLESS),
-#else
- PRESET(DEFAULT),
- PRESET(HP),
- PRESET(HQ),
- PRESET(BD),
- PRESET_ALIAS(SLOW, HQ, NVENC_TWO_PASSES),
- PRESET_ALIAS(MEDIUM, HQ, NVENC_ONE_PASS),
- PRESET_ALIAS(FAST, HP, NVENC_ONE_PASS),
- PRESET(LOW_LATENCY_DEFAULT, NVENC_LOWLATENCY),
- PRESET(LOW_LATENCY_HP, NVENC_LOWLATENCY),
- PRESET(LOW_LATENCY_HQ, NVENC_LOWLATENCY),
- PRESET(LOSSLESS_DEFAULT, NVENC_LOSSLESS),
- PRESET(LOSSLESS_HP, NVENC_LOSSLESS),
-#endif
- };
-
- GUIDTuple *t = &presets[ctx->preset];
-
- ctx->init_encode_params.presetGUID = t->guid;
- ctx->flags = t->flags;
-}
-
-#undef PRESET
-#undef PRESET_ALIAS
-
static av_cold void set_constqp(AVCodecContext *avctx)
{
NvencContext *ctx = avctx->priv_data;
@@ -1262,18 +1272,15 @@ static av_cold int nvenc_setup_encoder(AVCodecContext *avctx)
ctx->init_encode_params.encodeConfig = &ctx->encode_config;
- nvenc_map_preset(ctx);
-
- if (ctx->flags & NVENC_DEPRECATED_PRESET)
- av_log(avctx, AV_LOG_WARNING, "The selected preset is deprecated. Use p1 to p7 + -tune or fast/medium/slow.\n");
-
preset_config.version = NV_ENC_PRESET_CONFIG_VER;
preset_config.presetCfg.version = NV_ENC_CONFIG_VER;
#ifdef NVENC_HAVE_NEW_PRESETS
ctx->init_encode_params.tuningInfo = ctx->tuning_info;
- if (ctx->flags & NVENC_LOWLATENCY)
+ if (ctx->flags & NVENC_LOSSLESS)
+ ctx->init_encode_params.tuningInfo = NV_ENC_TUNING_INFO_LOSSLESS;
+ else if (ctx->flags & NVENC_LOWLATENCY)
ctx->init_encode_params.tuningInfo = NV_ENC_TUNING_INFO_LOW_LATENCY;
nv_status = p_nvenc->nvEncGetEncodePresetConfigEx(ctx->nvencoder,
@@ -1315,9 +1322,6 @@ static av_cold int nvenc_setup_encoder(AVCodecContext *avctx)
* */
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)
diff --git a/libavcodec/nvenc.h b/libavcodec/nvenc.h
index fefc5f7f0b..314c270e74 100644
--- a/libavcodec/nvenc.h
+++ b/libavcodec/nvenc.h
@@ -103,7 +103,7 @@ enum {
PRESET_LOW_LATENCY_DEFAULT ,
PRESET_LOW_LATENCY_HQ ,
PRESET_LOW_LATENCY_HP,
- PRESET_LOSSLESS_DEFAULT, // lossless presets must be the last ones
+ PRESET_LOSSLESS_DEFAULT,
PRESET_LOSSLESS_HP,
#ifdef NVENC_HAVE_NEW_PRESETS
PRESET_P1,