diff --git a/libavcodec/nvenc.c b/libavcodec/nvenc.c index 984dd3bc3f..5706590334 100644 --- a/libavcodec/nvenc.c +++ b/libavcodec/nvenc.c @@ -76,13 +76,21 @@ const enum AVPixelFormat ff_nvenc_pix_fmts[] = { AV_PIX_FMT_YUV420P, AV_PIX_FMT_NV12, + AV_PIX_FMT_P010, AV_PIX_FMT_YUV444P, + AV_PIX_FMT_YUV444P16, #if CONFIG_CUDA AV_PIX_FMT_CUDA, #endif AV_PIX_FMT_NONE }; +#define IS_10BIT(pix_fmt) (pix_fmt == AV_PIX_FMT_P010 || \ + pix_fmt == AV_PIX_FMT_YUV444P16) + +#define IS_YUV444(pix_fmt) (pix_fmt == AV_PIX_FMT_YUV444P || \ + pix_fmt == AV_PIX_FMT_YUV444P16) + static const struct { NVENCSTATUS nverr; int averr; @@ -273,7 +281,7 @@ static int nvenc_check_capabilities(AVCodecContext *avctx) } ret = nvenc_check_cap(avctx, NV_ENC_CAPS_SUPPORT_YUV444_ENCODE); - if (ctx->data_pix_fmt == AV_PIX_FMT_YUV444P && ret <= 0) { + if (IS_YUV444(ctx->data_pix_fmt) && ret <= 0) { av_log(avctx, AV_LOG_VERBOSE, "YUV444P not supported\n"); return AVERROR(ENOSYS); } @@ -314,6 +322,12 @@ static int nvenc_check_capabilities(AVCodecContext *avctx) return AVERROR(ENOSYS); } + ret = nvenc_check_cap(avctx, NV_ENC_CAPS_SUPPORT_10BIT_ENCODE); + if (IS_10BIT(ctx->data_pix_fmt) && ret <= 0) { + av_log(avctx, AV_LOG_VERBOSE, "10 bit encode not supported\n"); + return AVERROR(ENOSYS); + } + return 0; } @@ -800,9 +814,26 @@ static av_cold int nvenc_setup_hevc_config(AVCodecContext *avctx) hevc->outputPictureTimingSEI = 1; } - /* No other profile is supported in the current SDK version 5 */ - cc->profileGUID = NV_ENC_HEVC_PROFILE_MAIN_GUID; - avctx->profile = FF_PROFILE_HEVC_MAIN; + switch(ctx->profile) { + case NV_ENC_HEVC_PROFILE_MAIN: + cc->profileGUID = NV_ENC_HEVC_PROFILE_MAIN_GUID; + avctx->profile = FF_PROFILE_HEVC_MAIN; + break; + case NV_ENC_HEVC_PROFILE_MAIN_10: + cc->profileGUID = NV_ENC_HEVC_PROFILE_MAIN10_GUID; + avctx->profile = FF_PROFILE_HEVC_MAIN_10; + break; + } + + // force setting profile as main10 if input is 10 bit + if (IS_10BIT(ctx->data_pix_fmt)) { + cc->profileGUID = NV_ENC_HEVC_PROFILE_MAIN10_GUID; + avctx->profile = FF_PROFILE_HEVC_MAIN_10; + } + + hevc->chromaFormatIDC = IS_YUV444(ctx->data_pix_fmt) ? 3 : 1; + + hevc->pixelBitDepthMinus8 = IS_10BIT(ctx->data_pix_fmt) ? 2 : 0; hevc->level = ctx->level; @@ -958,10 +989,18 @@ static av_cold int nvenc_alloc_surface(AVCodecContext *avctx, int idx) ctx->surfaces[idx].format = NV_ENC_BUFFER_FORMAT_NV12_PL; break; + case AV_PIX_FMT_P010: + ctx->surfaces[idx].format = NV_ENC_BUFFER_FORMAT_YUV420_10BIT; + break; + case AV_PIX_FMT_YUV444P: ctx->surfaces[idx].format = NV_ENC_BUFFER_FORMAT_YUV444_PL; break; + case AV_PIX_FMT_YUV444P16: + ctx->surfaces[idx].format = NV_ENC_BUFFER_FORMAT_YUV444_10BIT; + break; + default: av_log(avctx, AV_LOG_FATAL, "Invalid input pixel format\n"); return AVERROR(EINVAL); @@ -1238,6 +1277,16 @@ static int nvenc_copy_frame(AVCodecContext *avctx, NvencSurface *inSurf, av_image_copy_plane(buf, lockBufferParams->pitch, frame->data[1], frame->linesize[1], avctx->width, avctx->height >> 1); + } else if (frame->format == AV_PIX_FMT_P010) { + av_image_copy_plane(buf, lockBufferParams->pitch, + frame->data[0], frame->linesize[0], + avctx->width << 1, avctx->height); + + buf += off; + + av_image_copy_plane(buf, lockBufferParams->pitch, + frame->data[1], frame->linesize[1], + avctx->width << 1, avctx->height >> 1); } else if (frame->format == AV_PIX_FMT_YUV444P) { av_image_copy_plane(buf, lockBufferParams->pitch, frame->data[0], frame->linesize[0], @@ -1254,6 +1303,22 @@ static int nvenc_copy_frame(AVCodecContext *avctx, NvencSurface *inSurf, av_image_copy_plane(buf, lockBufferParams->pitch, frame->data[2], frame->linesize[2], avctx->width, avctx->height); + } else if (frame->format == AV_PIX_FMT_YUV444P16) { + av_image_copy_plane(buf, lockBufferParams->pitch, + frame->data[0], frame->linesize[0], + avctx->width << 1, avctx->height); + + buf += off; + + av_image_copy_plane(buf, lockBufferParams->pitch, + frame->data[1], frame->linesize[1], + avctx->width << 1, avctx->height); + + buf += off; + + av_image_copy_plane(buf, lockBufferParams->pitch, + frame->data[2], frame->linesize[2], + avctx->width << 1, avctx->height); } else { av_log(avctx, AV_LOG_FATAL, "Invalid pixel format!\n"); return AVERROR(EINVAL); diff --git a/libavcodec/nvenc.h b/libavcodec/nvenc.h index c78b81669b..37d41eaa2e 100644 --- a/libavcodec/nvenc.h +++ b/libavcodec/nvenc.h @@ -116,6 +116,11 @@ enum { NV_ENC_H264_PROFILE_HIGH_444P, }; +enum { + NV_ENC_HEVC_PROFILE_MAIN, + NV_ENC_HEVC_PROFILE_MAIN_10, +}; + enum { NVENC_LOWLATENCY = 1, NVENC_LOSSLESS = 2, diff --git a/libavcodec/nvenc_hevc.c b/libavcodec/nvenc_hevc.c index 1ce7c89a4b..d9a4bf6bb9 100644 --- a/libavcodec/nvenc_hevc.c +++ b/libavcodec/nvenc_hevc.c @@ -39,8 +39,9 @@ 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" }, - { "profile", "Set the encoding profile", OFFSET(profile), AV_OPT_TYPE_INT, { .i64 = FF_PROFILE_HEVC_MAIN }, FF_PROFILE_HEVC_MAIN, FF_PROFILE_HEVC_MAIN, VE, "profile" }, - { "main", "", 0, AV_OPT_TYPE_CONST, { .i64 = FF_PROFILE_HEVC_MAIN }, 0, 0, VE, "profile" }, + { "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_MAIN_10, 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" }, { "level", "Set the encoding level restriction", OFFSET(level), AV_OPT_TYPE_INT, { .i64 = NV_ENC_LEVEL_AUTOSELECT }, NV_ENC_LEVEL_AUTOSELECT, NV_ENC_LEVEL_HEVC_62, VE, "level" }, { "auto", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_LEVEL_AUTOSELECT }, 0, 0, VE, "level" }, { "1", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_LEVEL_HEVC_1 }, 0, 0, VE, "level" }, diff --git a/libavcodec/version.h b/libavcodec/version.h index 7ee5b5aa13..f7a7344c62 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -29,7 +29,7 @@ #define LIBAVCODEC_VERSION_MAJOR 57 #define LIBAVCODEC_VERSION_MINOR 54 -#define LIBAVCODEC_VERSION_MICRO 100 +#define LIBAVCODEC_VERSION_MICRO 101 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ LIBAVCODEC_VERSION_MINOR, \