You've already forked FFmpeg
mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2025-08-15 14:13:16 +02:00
avcodec/nvenc: use AVOptions to select presets
Signed-off-by: Timo Rothenpieler <timo@rothenpieler.org>
This commit is contained in:
committed by
Timo Rothenpieler
parent
e1de62c5be
commit
faffff88c2
@@ -302,7 +302,7 @@ static av_cold int nvenc_check_cuda(AVCodecContext *avctx)
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!strncmp(ctx->preset, "lossless", 8))
|
if (ctx->preset >= PRESET_LOSSLESS_DEFAULT)
|
||||||
target_smver = 0x52;
|
target_smver = 0x52;
|
||||||
|
|
||||||
if (!nvenc_dyload_cuda(avctx))
|
if (!nvenc_dyload_cuda(avctx))
|
||||||
@@ -444,6 +444,17 @@ static av_cold int nvenc_setup_device(AVCodecContext *avctx)
|
|||||||
CUresult cu_res;
|
CUresult cu_res;
|
||||||
CUcontext cu_context_curr;
|
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;
|
ctx->data_pix_fmt = avctx->pix_fmt;
|
||||||
|
|
||||||
#if CONFIG_CUDA
|
#if CONFIG_CUDA
|
||||||
@@ -512,6 +523,34 @@ static av_cold int nvenc_open_session(AVCodecContext *avctx)
|
|||||||
return 0;
|
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)
|
static av_cold void set_constqp(AVCodecContext *avctx)
|
||||||
{
|
{
|
||||||
NvencContext *ctx = avctx->priv_data;
|
NvencContext *ctx = avctx->priv_data;
|
||||||
@@ -548,7 +587,7 @@ static av_cold void set_lossless(AVCodecContext *avctx)
|
|||||||
ctx->encode_config.rcParams.constQP.qpIntra = 0;
|
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;
|
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)
|
if (avctx->rc_max_rate > 0)
|
||||||
ctx->encode_config.rcParams.maxBitRate = avctx->rc_max_rate;
|
ctx->encode_config.rcParams.maxBitRate = avctx->rc_max_rate;
|
||||||
|
|
||||||
if (lossless) {
|
if (ctx->flags & NVENC_LOSSLESS) {
|
||||||
if (avctx->codec->id == AV_CODEC_ID_H264)
|
if (avctx->codec->id == AV_CODEC_ID_H264)
|
||||||
ctx->encode_config.encodeCodecConfig.h264Config.qpPrimeYZeroTransformBypassFlag = 1;
|
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;
|
int res;
|
||||||
|
|
||||||
ctx->encode_config.encodeCodecConfig.h264Config.h264VUIParameters.colourMatrix = avctx->colorspace;
|
vui->colourMatrix = avctx->colorspace;
|
||||||
ctx->encode_config.encodeCodecConfig.h264Config.h264VUIParameters.colourPrimaries = avctx->color_primaries;
|
vui->colourPrimaries = avctx->color_primaries;
|
||||||
ctx->encode_config.encodeCodecConfig.h264Config.h264VUIParameters.transferCharacteristics = avctx->color_trc;
|
vui->transferCharacteristics = avctx->color_trc;
|
||||||
ctx->encode_config.encodeCodecConfig.h264Config.h264VUIParameters.videoFullRangeFlag = (avctx->color_range == AVCOL_RANGE_JPEG
|
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->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);
|
(avctx->colorspace != 2 || avctx->color_primaries != 2 || avctx->color_trc != 2);
|
||||||
|
|
||||||
ctx->encode_config.encodeCodecConfig.h264Config.h264VUIParameters.videoSignalTypePresentFlag =
|
vui->videoSignalTypePresentFlag =
|
||||||
(ctx->encode_config.encodeCodecConfig.h264Config.h264VUIParameters.colourDescriptionPresentFlag
|
(vui->colourDescriptionPresentFlag
|
||||||
|| ctx->encode_config.encodeCodecConfig.h264Config.h264VUIParameters.videoFormat != 5
|
|| vui->videoFormat != 5
|
||||||
|| ctx->encode_config.encodeCodecConfig.h264Config.h264VUIParameters.videoFullRangeFlag != 0);
|
|| vui->videoFullRangeFlag != 0);
|
||||||
|
|
||||||
ctx->encode_config.encodeCodecConfig.h264Config.sliceMode = 3;
|
h264->sliceMode = 3;
|
||||||
ctx->encode_config.encodeCodecConfig.h264Config.sliceModeData = 1;
|
h264->sliceModeData = 1;
|
||||||
|
|
||||||
ctx->encode_config.encodeCodecConfig.h264Config.disableSPSPPS = (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) ? 1 : 0;
|
h264->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->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) {
|
switch (avctx->profile) {
|
||||||
case FF_PROFILE_H264_HIGH_444_PREDICTIVE:
|
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;
|
break;
|
||||||
case FF_PROFILE_H264_BASELINE:
|
case FF_PROFILE_H264_BASELINE:
|
||||||
ctx->encode_config.profileGUID = NV_ENC_H264_PROFILE_BASELINE_GUID;
|
cc->profileGUID = NV_ENC_H264_PROFILE_BASELINE_GUID;
|
||||||
break;
|
break;
|
||||||
case FF_PROFILE_H264_MAIN:
|
case FF_PROFILE_H264_MAIN:
|
||||||
ctx->encode_config.profileGUID = NV_ENC_H264_PROFILE_MAIN_GUID;
|
cc->profileGUID = NV_ENC_H264_PROFILE_MAIN_GUID;
|
||||||
break;
|
break;
|
||||||
case FF_PROFILE_H264_HIGH:
|
case FF_PROFILE_H264_HIGH:
|
||||||
case FF_PROFILE_UNKNOWN:
|
case FF_PROFILE_UNKNOWN:
|
||||||
ctx->encode_config.profileGUID = NV_ENC_H264_PROFILE_HIGH_GUID;
|
cc->profileGUID = NV_ENC_H264_PROFILE_HIGH_GUID;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
av_log(avctx, AV_LOG_WARNING, "Unsupported profile requested, falling back to high\n");
|
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;
|
break;
|
||||||
}
|
}
|
||||||
} else if (!lossless) {
|
} else if (!(ctx->flags & NVENC_LOSSLESS)) {
|
||||||
if (!strcmp(ctx->profile, "high")) {
|
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;
|
avctx->profile = FF_PROFILE_H264_HIGH;
|
||||||
} else if (!strcmp(ctx->profile, "main")) {
|
} 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;
|
avctx->profile = FF_PROFILE_H264_MAIN;
|
||||||
} else if (!strcmp(ctx->profile, "baseline")) {
|
} 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;
|
avctx->profile = FF_PROFILE_H264_BASELINE;
|
||||||
} else if (!strcmp(ctx->profile, "high444p")) {
|
} 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;
|
avctx->profile = FF_PROFILE_H264_HIGH_444_PREDICTIVE;
|
||||||
} else {
|
} else {
|
||||||
av_log(avctx, AV_LOG_FATAL, "Profile \"%s\" is unknown! Supported profiles: high, main, baseline\n", ctx->profile);
|
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
|
// force setting profile as high444p if input is AV_PIX_FMT_YUV444P
|
||||||
if (ctx->data_pix_fmt == 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;
|
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) {
|
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) {
|
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);
|
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;
|
return res;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ctx->encode_config.encodeCodecConfig.h264Config.level = NV_ENC_LEVEL_AUTOSELECT;
|
h264->level = NV_ENC_LEVEL_AUTOSELECT;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -732,50 +774,53 @@ static av_cold int nvenc_setup_h264_config(AVCodecContext *avctx, int lossless)
|
|||||||
static av_cold int nvenc_setup_hevc_config(AVCodecContext *avctx)
|
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;
|
int res;
|
||||||
|
|
||||||
ctx->encode_config.encodeCodecConfig.hevcConfig.hevcVUIParameters.colourMatrix = avctx->colorspace;
|
vui->colourMatrix = avctx->colorspace;
|
||||||
ctx->encode_config.encodeCodecConfig.hevcConfig.hevcVUIParameters.colourPrimaries = avctx->color_primaries;
|
vui->colourPrimaries = avctx->color_primaries;
|
||||||
ctx->encode_config.encodeCodecConfig.hevcConfig.hevcVUIParameters.transferCharacteristics = avctx->color_trc;
|
vui->transferCharacteristics = avctx->color_trc;
|
||||||
ctx->encode_config.encodeCodecConfig.hevcConfig.hevcVUIParameters.videoFullRangeFlag = (avctx->color_range == AVCOL_RANGE_JPEG
|
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->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);
|
(avctx->colorspace != 2 || avctx->color_primaries != 2 || avctx->color_trc != 2);
|
||||||
|
|
||||||
ctx->encode_config.encodeCodecConfig.hevcConfig.hevcVUIParameters.videoSignalTypePresentFlag =
|
vui->videoSignalTypePresentFlag =
|
||||||
(ctx->encode_config.encodeCodecConfig.hevcConfig.hevcVUIParameters.colourDescriptionPresentFlag
|
(vui->colourDescriptionPresentFlag
|
||||||
|| ctx->encode_config.encodeCodecConfig.hevcConfig.hevcVUIParameters.videoFormat != 5
|
|| vui->videoFormat != 5
|
||||||
|| ctx->encode_config.encodeCodecConfig.hevcConfig.hevcVUIParameters.videoFullRangeFlag != 0);
|
|| vui->videoFullRangeFlag != 0);
|
||||||
|
|
||||||
ctx->encode_config.encodeCodecConfig.hevcConfig.sliceMode = 3;
|
hevc->sliceMode = 3;
|
||||||
ctx->encode_config.encodeCodecConfig.hevcConfig.sliceModeData = 1;
|
hevc->sliceModeData = 1;
|
||||||
|
|
||||||
ctx->encode_config.encodeCodecConfig.hevcConfig.disableSPSPPS = (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) ? 1 : 0;
|
hevc->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->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 */
|
/* 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;
|
avctx->profile = FF_PROFILE_HEVC_MAIN;
|
||||||
|
|
||||||
if (ctx->level) {
|
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) {
|
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);
|
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;
|
return res;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ctx->encode_config.encodeCodecConfig.hevcConfig.level = NV_ENC_LEVEL_AUTOSELECT;
|
hevc->level = NV_ENC_LEVEL_AUTOSELECT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctx->tier) {
|
if (ctx->tier) {
|
||||||
if (!strcmp(ctx->tier, "main")) {
|
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")) {
|
} 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 {
|
} else {
|
||||||
av_log(avctx, AV_LOG_FATAL, "Tier \"%s\" is unknown! Supported tiers: main, high\n", ctx->tier);
|
av_log(avctx, AV_LOG_FATAL, "Tier \"%s\" is unknown! Supported tiers: main, high\n", ctx->tier);
|
||||||
return AVERROR(EINVAL);
|
return AVERROR(EINVAL);
|
||||||
@@ -785,12 +830,12 @@ static av_cold int nvenc_setup_hevc_config(AVCodecContext *avctx)
|
|||||||
return 0;
|
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) {
|
switch (avctx->codec->id) {
|
||||||
case AV_CODEC_ID_H264:
|
case AV_CODEC_ID_H264:
|
||||||
return nvenc_setup_h264_config(avctx, lossless);
|
return nvenc_setup_h264_config(avctx);
|
||||||
case AV_CODEC_ID_H265:
|
case AV_CODEC_ID_HEVC:
|
||||||
return nvenc_setup_hevc_config(avctx);
|
return nvenc_setup_hevc_config(avctx);
|
||||||
/* Earlier switch/case will return if unknown codec is passed. */
|
/* 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_ENCODE_API_FUNCTION_LIST *p_nvenc = &dl_fn->nvenc_funcs;
|
||||||
|
|
||||||
NV_ENC_PRESET_CONFIG preset_config = { 0 };
|
NV_ENC_PRESET_CONFIG preset_config = { 0 };
|
||||||
GUID encoder_preset = NV_ENC_PRESET_HQ_GUID;
|
|
||||||
GUID codec;
|
|
||||||
NVENCSTATUS nv_status = NV_ENC_SUCCESS;
|
NVENCSTATUS nv_status = NV_ENC_SUCCESS;
|
||||||
AVCPBProperties *cpb_props;
|
AVCPBProperties *cpb_props;
|
||||||
int num_mbs;
|
int num_mbs;
|
||||||
int isLL = 0;
|
|
||||||
int lossless = 0;
|
|
||||||
int res = 0;
|
int res = 0;
|
||||||
int dw, dh;
|
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->encode_config.version = NV_ENC_CONFIG_VER;
|
||||||
ctx->init_encode_params.version = NV_ENC_INITIALIZE_PARAMS_VER;
|
ctx->init_encode_params.version = NV_ENC_INITIALIZE_PARAMS_VER;
|
||||||
|
|
||||||
|
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 = (ctx->flags & NVENC_LOWLATENCY) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
preset_config.version = NV_ENC_PRESET_CONFIG_VER;
|
preset_config.version = NV_ENC_PRESET_CONFIG_VER;
|
||||||
preset_config.presetCfg.version = NV_ENC_CONFIG_VER;
|
preset_config.presetCfg.version = NV_ENC_CONFIG_VER;
|
||||||
|
|
||||||
if (ctx->preset) {
|
nv_status = p_nvenc->nvEncGetEncodePresetConfig(ctx->nvencoder,
|
||||||
if (!strcmp(ctx->preset, "slow")) {
|
ctx->init_encode_params.encodeGUID,
|
||||||
encoder_preset = NV_ENC_PRESET_HQ_GUID;
|
ctx->init_encode_params.presetGUID,
|
||||||
ctx->twopass = 1;
|
&preset_config);
|
||||||
} else if (!strcmp(ctx->preset, "medium")) {
|
if (nv_status != NV_ENC_SUCCESS)
|
||||||
encoder_preset = NV_ENC_PRESET_HQ_GUID;
|
return nvenc_print_error(avctx, nv_status, "Cannot get the preset configuration");
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ctx->twopass < 0) {
|
memcpy(&ctx->encode_config, &preset_config.presetCfg, sizeof(ctx->encode_config));
|
||||||
ctx->twopass = isLL;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (avctx->codec->id) {
|
ctx->encode_config.version = NV_ENC_CONFIG_VER;
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
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");
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx->init_encode_params.encodeGUID = codec;
|
|
||||||
ctx->init_encode_params.encodeHeight = avctx->height;
|
|
||||||
ctx->init_encode_params.encodeWidth = avctx->width;
|
|
||||||
|
|
||||||
if (avctx->sample_aspect_ratio.num && avctx->sample_aspect_ratio.den &&
|
if (avctx->sample_aspect_ratio.num && avctx->sample_aspect_ratio.den &&
|
||||||
(avctx->sample_aspect_ratio.num != 1 || avctx->sample_aspect_ratio.num != 1)) {
|
(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.enableEncodeAsync = 0;
|
||||||
ctx->init_encode_params.enablePTD = 1;
|
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) {
|
if (avctx->refs >= 0) {
|
||||||
/* 0 means "let the hardware decide" */
|
/* 0 means "let the hardware decide" */
|
||||||
switch (avctx->codec->id) {
|
switch (avctx->codec->id) {
|
||||||
@@ -976,7 +975,7 @@ static av_cold int nvenc_setup_encoder(AVCodecContext *avctx)
|
|||||||
if (ctx->encode_config.frameIntervalP >= 2)
|
if (ctx->encode_config.frameIntervalP >= 2)
|
||||||
ctx->last_dts = -2;
|
ctx->last_dts = -2;
|
||||||
|
|
||||||
nvenc_setup_rate_control(avctx, lossless);
|
nvenc_setup_rate_control(avctx);
|
||||||
|
|
||||||
if (avctx->flags & AV_CODEC_FLAG_INTERLACED_DCT) {
|
if (avctx->flags & AV_CODEC_FLAG_INTERLACED_DCT) {
|
||||||
ctx->encode_config.frameFieldMode = NV_ENC_PARAMS_FRAME_FIELD_MODE_FIELD;
|
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;
|
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)
|
if (res)
|
||||||
return res;
|
return res;
|
||||||
|
|
||||||
|
@@ -104,6 +104,28 @@ typedef struct NvencDynLoadFunctions
|
|||||||
|
|
||||||
} 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
|
typedef struct NvencContext
|
||||||
{
|
{
|
||||||
AVClass *avclass;
|
AVClass *avclass;
|
||||||
@@ -137,13 +159,14 @@ typedef struct NvencContext
|
|||||||
|
|
||||||
void *nvencoder;
|
void *nvencoder;
|
||||||
|
|
||||||
char *preset;
|
int preset;
|
||||||
char *profile;
|
char *profile;
|
||||||
char *level;
|
char *level;
|
||||||
char *tier;
|
char *tier;
|
||||||
int cbr;
|
int cbr;
|
||||||
int twopass;
|
int twopass;
|
||||||
int gpu;
|
int gpu;
|
||||||
|
int flags;
|
||||||
int buffer_delay;
|
int buffer_delay;
|
||||||
} NvencContext;
|
} NvencContext;
|
||||||
|
|
||||||
|
@@ -26,7 +26,19 @@
|
|||||||
#define OFFSET(x) offsetof(NvencContext, x)
|
#define OFFSET(x) offsetof(NvencContext, x)
|
||||||
#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
|
#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
|
||||||
static const AVOption options[] = {
|
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 },
|
{ "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 },
|
{ "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 },
|
{ "cbr", "Use cbr encoding mode", OFFSET(cbr), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE },
|
||||||
|
@@ -26,7 +26,19 @@
|
|||||||
#define OFFSET(x) offsetof(NvencContext, x)
|
#define OFFSET(x) offsetof(NvencContext, x)
|
||||||
#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
|
#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
|
||||||
static const AVOption options[] = {
|
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 },
|
{ "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 },
|
{ "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 },
|
{ "tier", "Set the encoding tier (main or high)", OFFSET(tier), AV_OPT_TYPE_STRING, { .str = "main" }, 0, 0, VE },
|
||||||
|
Reference in New Issue
Block a user