#include "config.h"
#include "nvenc.h"
+#include "hevc_sei.h"
#include "libavutil/hwcontext_cuda.h"
#include "libavutil/hwcontext.h"
#include "libavutil/avassert.h"
#include "libavutil/mem.h"
#include "libavutil/pixdesc.h"
+#include "atsc_a53.h"
#include "encode.h"
#include "internal.h"
#include "packet_internal.h"
AV_PIX_FMT_NONE
};
-const AVCodecHWConfigInternal *ff_nvenc_hw_configs[] = {
+const AVCodecHWConfigInternal *const ff_nvenc_hw_configs[] = {
HW_CONFIG_ENCODER_FRAMES(CUDA, CUDA),
HW_CONFIG_ENCODER_DEVICE(NONE, CUDA),
#if CONFIG_D3D11VA
static void nvenc_print_driver_requirement(AVCodecContext *avctx, int level)
{
-#if NVENCAPI_CHECK_VERSION(9, 2)
+#if NVENCAPI_CHECK_VERSION(11, 1)
const char *minver = "(unknown)";
+#elif NVENCAPI_CHECK_VERSION(11, 0)
+# if defined(_WIN32) || defined(__CYGWIN__)
+ const char *minver = "456.71";
+# else
+ const char *minver = "455.28";
+# endif
+#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";
#ifdef NVENC_HAVE_BFRAME_REF_MODE
ret = nvenc_check_cap(avctx, NV_ENC_CAPS_SUPPORT_BFRAME_REF_MODE);
- if (ctx->b_ref_mode == NV_ENC_BFRAME_REF_MODE_EACH && ret != 1) {
+ if (ctx->b_ref_mode == NV_ENC_BFRAME_REF_MODE_EACH && ret != 1 && ret != 3) {
av_log(avctx, AV_LOG_WARNING, "Each B frame as reference is not supported\n");
return AVERROR(ENOSYS);
} else if (ctx->b_ref_mode != NV_ENC_BFRAME_REF_MODE_DISABLED && ret == 0) {
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(LOW_LATENCY_HQ, NVENC_LOWLATENCY),
PRESET(LOSSLESS_DEFAULT, NVENC_LOSSLESS),
PRESET(LOSSLESS_HP, NVENC_LOSSLESS),
+#endif
};
GUIDTuple *t = &presets[ctx->preset];
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->flags & NVENC_ONE_PASS)
+ ctx->encode_config.rcParams.multiPass = NV_ENC_MULTI_PASS_DISABLED;
+ if (ctx->flags & NVENC_TWO_PASSES || ctx->twopass > 0)
+ ctx->encode_config.rcParams.multiPass = NV_ENC_TWO_PASS_FULL_RESOLUTION;
+
+ if (ctx->rc < 0) {
+ if (ctx->cbr) {
+ ctx->rc = NV_ENC_PARAMS_RC_CBR;
+ } else if (ctx->cqp >= 0) {
+ ctx->rc = NV_ENC_PARAMS_RC_CONSTQP;
+ } else if (ctx->quality >= 0.0f) {
+ ctx->rc = NV_ENC_PARAMS_RC_VBR;
+ }
+ }
+#else
if (ctx->rc < 0) {
if (ctx->flags & NVENC_ONE_PASS)
ctx->twopass = 0;
ctx->rc = NV_ENC_PARAMS_RC_VBR_MINQP;
}
}
+#endif
if (ctx->rc >= 0 && ctx->rc & RC_MODE_DEPRECATED) {
av_log(avctx, AV_LOG_WARNING, "Specified rc mode is deprecated.\n");
- av_log(avctx, AV_LOG_WARNING, "\tll_2pass_quality -> cbr_ld_hq\n");
- av_log(avctx, AV_LOG_WARNING, "\tll_2pass_size -> cbr_hq\n");
- av_log(avctx, AV_LOG_WARNING, "\tvbr_2pass -> vbr_hq\n");
- av_log(avctx, AV_LOG_WARNING, "\tvbr_minqp -> (no replacement)\n");
+ av_log(avctx, AV_LOG_WARNING, "Use -rc constqp/cbr/vbr, -tune and -multipass instead.\n");
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) {
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)
+ ctx->init_encode_params.tuningInfo = NV_ENC_TUNING_INFO_LOW_LATENCY;
+
+ nv_status = p_nvenc->nvEncGetEncodePresetConfigEx(ctx->nvencoder,
+ ctx->init_encode_params.encodeGUID,
+ ctx->init_encode_params.presetGUID,
+ ctx->init_encode_params.tuningInfo,
+ &preset_config);
+#else
nv_status = p_nvenc->nvEncGetEncodePresetConfig(ctx->nvencoder,
- ctx->init_encode_params.encodeGUID,
- ctx->init_encode_params.presetGUID,
- &preset_config);
+ ctx->init_encode_params.encodeGUID,
+ ctx->init_encode_params.presetGUID,
+ &preset_config);
+#endif
if (nv_status != NV_ENC_SUCCESS)
return nvenc_print_error(avctx, nv_status, "Cannot get the preset configuration");
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;
}
ctx->surfaces[idx].output_surface = allocOut.bitstreamBuffer;
- ctx->surfaces[idx].size = allocOut.size;
av_fifo_generic_write(ctx->unused_surface_queue, &tmp_surface, sizeof(tmp_surface), NULL);
}
}
+ if (ctx->s12m_tc && av_frame_get_side_data(frame, AV_FRAME_DATA_S12M_TIMECODE)) {
+ void *tc_data = NULL;
+ size_t tc_size = 0;
+
+ if (ff_alloc_timecode_sei(frame, avctx->framerate, 0, (void**)&tc_data, &tc_size) < 0) {
+ av_log(ctx, AV_LOG_ERROR, "Not enough memory for timecode sei, skipping\n");
+ }
+
+ if (tc_data) {
+ sei_data[sei_count].payloadSize = (uint32_t)tc_size;
+ sei_data[sei_count].payloadType = HEVC_SEI_TYPE_TIME_CODE;
+ sei_data[sei_count].payload = (uint8_t*)tc_data;
+ sei_count ++;
+ }
+ }
+
nvenc_codec_specific_pic_params(avctx, &pic_params, sei_data, sei_count);
} else {
pic_params.encodePicFlags = NV_ENC_PIC_FLAG_EOS;