From e42b9bc8945f73dbc89ae3b9b7c79550637f7b57 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 12 May 2016 08:23:06 +0200 Subject: [PATCH 01/13] nvenc: fix the rc option definitions --- libavcodec/nvenc_h264.c | 2 +- libavcodec/nvenc_hevc.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/nvenc_h264.c b/libavcodec/nvenc_h264.c index 1f886d1f1a..cd8e367860 100644 --- a/libavcodec/nvenc_h264.c +++ b/libavcodec/nvenc_h264.c @@ -58,7 +58,7 @@ static const AVOption options[] = { { "4.2", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_LEVEL_H264_42 }, 0, 0, VE, "level" }, { "5.0", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_LEVEL_H264_5 }, 0, 0, VE, "level" }, { "5.1", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_LEVEL_H264_51 }, 0, 0, VE, "level" }, - { "rc", "Override the preset rate-control", OFFSET(rc), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 0, VE }, + { "rc", "Override the preset rate-control", OFFSET(rc), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, VE, "rc" }, { "constqp", "Constant QP mode", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_PARAMS_RC_CONSTQP }, 0, 0, VE, "rc" }, { "vbr", "Variable bitrate mode", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_PARAMS_RC_VBR }, 0, 0, VE, "rc" }, { "cbr", "Constant bitrate mode", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_PARAMS_RC_CBR }, 0, 0, VE, "rc" }, diff --git a/libavcodec/nvenc_hevc.c b/libavcodec/nvenc_hevc.c index f0c6d41b83..d49ae62502 100644 --- a/libavcodec/nvenc_hevc.c +++ b/libavcodec/nvenc_hevc.c @@ -56,7 +56,7 @@ static const AVOption options[] = { { "tier", "Set the encoding tier", OFFSET(tier), AV_OPT_TYPE_INT, { .i64 = NV_ENC_TIER_HEVC_MAIN }, NV_ENC_TIER_HEVC_MAIN, NV_ENC_TIER_HEVC_HIGH, VE, "tier"}, { "main", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_TIER_HEVC_MAIN }, 0, 0, VE, "tier" }, { "high", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_TIER_HEVC_HIGH }, 0, 0, VE, "tier" }, - { "rc", "Override the preset rate-control", OFFSET(rc), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 0, VE, "rc" }, + { "rc", "Override the preset rate-control", OFFSET(rc), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, VE, "rc" }, { "constqp", "Constant QP mode", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_PARAMS_RC_CONSTQP }, 0, 0, VE, "rc" }, { "vbr", "Variable bitrate mode", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_PARAMS_RC_VBR }, 0, 0, VE, "rc" }, { "cbr", "Constant bitrate mode", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_PARAMS_RC_CBR }, 0, 0, VE, "rc" }, From 795329dd4c5d100bb7c633b1a5d3145090a7a420 Mon Sep 17 00:00:00 2001 From: Timo Rothenpieler Date: Wed, 30 Mar 2016 12:03:59 +0200 Subject: [PATCH 02/13] nvenc: Generate AUD NAL units for better compatiblity Signed-off-by: Anton Khirnov --- libavcodec/nvenc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavcodec/nvenc.c b/libavcodec/nvenc.c index 54f030baf5..943cfbefba 100644 --- a/libavcodec/nvenc.c +++ b/libavcodec/nvenc.c @@ -586,6 +586,7 @@ static int nvenc_setup_h264_config(AVCodecContext *avctx) h264->disableSPSPPS = (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) ? 1 : 0; h264->repeatSPSPPS = (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) ? 0 : 1; + h264->outputAUD = 1; h264->maxNumRefFrames = avctx->refs; h264->idrPeriod = cc->gopLength; @@ -629,6 +630,7 @@ static int nvenc_setup_hevc_config(AVCodecContext *avctx) hevc->disableSPSPPS = (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) ? 1 : 0; hevc->repeatSPSPPS = (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) ? 0 : 1; + hevc->outputAUD = 1; hevc->maxNumRefFramesInDPB = avctx->refs; hevc->idrPeriod = cc->gopLength; From 9427d92f40d4ab981f0b24e8e1d1cdec1d845ac1 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 11 May 2016 15:38:35 +0200 Subject: [PATCH 03/13] nvenc: add support for lossless encoding Based on a patch by Philip Langdale --- libavcodec/nvenc.c | 13 +++++++++++++ libavcodec/nvenc_h264.c | 2 ++ 2 files changed, 15 insertions(+) diff --git a/libavcodec/nvenc.c b/libavcodec/nvenc.c index 943cfbefba..97922453f7 100644 --- a/libavcodec/nvenc.c +++ b/libavcodec/nvenc.c @@ -494,6 +494,14 @@ static void set_vbr(AVCodecContext *avctx, NV_ENC_RC_PARAMS *rc) } } +static void set_lossless(AVCodecContext *avctx, NV_ENC_RC_PARAMS *rc) +{ + rc->rateControlMode = NV_ENC_PARAMS_RC_CONSTQP; + rc->constQP.qpInterB = 0; + rc->constQP.qpInterP = 0; + rc->constQP.qpIntra = 0; +} + static void nvenc_override_rate_control(AVCodecContext *avctx, NV_ENC_RC_PARAMS *rc) { @@ -554,6 +562,8 @@ static void nvenc_setup_rate_control(AVCodecContext *avctx) if (ctx->rc > 0) { nvenc_override_rate_control(avctx, rc); + } else if (ctx->flags & NVENC_LOSSLESS) { + set_lossless(avctx, rc); } else if (avctx->global_quality > 0) { set_constqp(avctx, rc); } else if (avctx->qmin >= 0 && avctx->qmax >= 0) { @@ -591,6 +601,9 @@ static int nvenc_setup_h264_config(AVCodecContext *avctx) h264->maxNumRefFrames = avctx->refs; h264->idrPeriod = cc->gopLength; + if (ctx->flags & NVENC_LOSSLESS) + h264->qpPrimeYZeroTransformBypassFlag = 1; + if (ctx->profile) avctx->profile = ctx->profile; diff --git a/libavcodec/nvenc_h264.c b/libavcodec/nvenc_h264.c index cd8e367860..829ce90cd6 100644 --- a/libavcodec/nvenc_h264.c +++ b/libavcodec/nvenc_h264.c @@ -35,6 +35,8 @@ static const AVOption options[] = { { "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", OFFSET(profile), AV_OPT_TYPE_INT, { .i64 = NV_ENC_H264_PROFILE_HIGH }, NV_ENC_H264_PROFILE_BASELINE, NV_ENC_H264_PROFILE_CONSTRAINED_HIGH, 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" }, From a1e215ea0157360261e856eea2cd468136a68da0 Mon Sep 17 00:00:00 2001 From: Timo Rothenpieler Date: Sat, 25 Jul 2015 23:20:28 +0200 Subject: [PATCH 04/13] nvenc: Delay frame output to increase encoding speed Signed-off-by: Anton Khirnov --- libavcodec/nvenc.c | 10 +++++++++- libavcodec/nvenc.h | 1 + libavcodec/nvenc_h264.c | 2 ++ libavcodec/nvenc_hevc.c | 2 ++ 4 files changed, 14 insertions(+), 1 deletion(-) diff --git a/libavcodec/nvenc.c b/libavcodec/nvenc.c index 97922453f7..bd704a76ad 100644 --- a/libavcodec/nvenc.c +++ b/libavcodec/nvenc.c @@ -840,6 +840,8 @@ static int nvenc_setup_surfaces(AVCodecContext *avctx) ctx->nb_surfaces = FFMAX(4 + avctx->max_b_frames, ctx->nb_surfaces); + ctx->async_depth = FFMIN(ctx->async_depth, ctx->nb_surfaces - 1); + ctx->frames = av_mallocz_array(ctx->nb_surfaces, sizeof(*ctx->frames)); if (!ctx->frames) @@ -1301,13 +1303,19 @@ FF_ENABLE_DEPRECATION_WARNINGS static int output_ready(AVCodecContext *avctx, int flush) { NVENCContext *ctx = avctx->priv_data; + int nb_ready, nb_pending; /* when B-frames are enabled, we wait for two initial timestamps to * calculate the first dts */ if (!flush && avctx->max_b_frames > 0 && (ctx->initial_pts[0] == AV_NOPTS_VALUE || ctx->initial_pts[1] == AV_NOPTS_VALUE)) return 0; - return av_fifo_size(ctx->ready) > 0; + + nb_ready = av_fifo_size(ctx->ready) / sizeof(NVENCFrame*); + nb_pending = av_fifo_size(ctx->pending) / sizeof(NVENCFrame*); + if (flush) + return nb_ready > 0; + return (nb_ready > 0) && (nb_ready + nb_pending >= ctx->async_depth); } int ff_nvenc_encode_frame(AVCodecContext *avctx, AVPacket *pkt, diff --git a/libavcodec/nvenc.h b/libavcodec/nvenc.h index 866099789c..8cd5991f4c 100644 --- a/libavcodec/nvenc.h +++ b/libavcodec/nvenc.h @@ -142,6 +142,7 @@ typedef struct NVENCContext { int rc; int device; int flags; + int async_depth; } NVENCContext; int ff_nvenc_encode_init(AVCodecContext *avctx); diff --git a/libavcodec/nvenc_h264.c b/libavcodec/nvenc_h264.c index 829ce90cd6..ea91e077c0 100644 --- a/libavcodec/nvenc_h264.c +++ b/libavcodec/nvenc_h264.c @@ -72,6 +72,8 @@ static const AVOption options[] = { { "device", "Select a specific NVENC device", OFFSET(device), AV_OPT_TYPE_INT, { .i64 = -1 }, -2, INT_MAX, VE, "device" }, { "any", "Pick the first device available", 0, AV_OPT_TYPE_CONST, { .i64 = ANY_DEVICE }, 0, 0, VE, "device" }, { "list", "List the available devices", 0, AV_OPT_TYPE_CONST, { .i64 = LIST_DEVICES }, 0, 0, VE, "device" }, + { "async_depth", "Delay frame output by the given amount of frames", OFFSET(async_depth), AV_OPT_TYPE_INT, { .i64 = INT_MAX }, 0, INT_MAX, VE }, + { "delay", "Delay frame output by the given amount of frames", OFFSET(async_depth), AV_OPT_TYPE_INT, { .i64 = INT_MAX }, 0, INT_MAX, VE }, { NULL } }; diff --git a/libavcodec/nvenc_hevc.c b/libavcodec/nvenc_hevc.c index d49ae62502..6ff350698c 100644 --- a/libavcodec/nvenc_hevc.c +++ b/libavcodec/nvenc_hevc.c @@ -68,6 +68,8 @@ static const AVOption options[] = { { "device", "Select a specific NVENC device", OFFSET(device), AV_OPT_TYPE_INT, { .i64 = -1 }, -2, INT_MAX, VE, "device" }, { "any", "Pick the first device available", 0, AV_OPT_TYPE_CONST, { .i64 = ANY_DEVICE }, 0, 0, VE, "device" }, { "list", "List the available devices", 0, AV_OPT_TYPE_CONST, { .i64 = LIST_DEVICES }, 0, 0, VE, "device" }, + { "async_depth", "Delay frame output by the given amount of frames", OFFSET(async_depth), AV_OPT_TYPE_INT, { .i64 = INT_MAX }, 0, INT_MAX, VE }, + { "delay", "Delay frame output by the given amount of frames", OFFSET(async_depth), AV_OPT_TYPE_INT, { .i64 = INT_MAX }, 0, INT_MAX, VE }, { NULL } }; From cea1fb854c26a1d8c8857ec94adeb8a19beb5004 Mon Sep 17 00:00:00 2001 From: Timo Rothenpieler Date: Wed, 11 May 2016 10:34:31 +0200 Subject: [PATCH 05/13] nvenc: Generate bufferingPeriod/pictureTiming SEI For some unknown reason enabling these causes proper CBR padding, so as there are no known downsides just always enable them in CBR mode. Signed-off-by: Anton Khirnov --- libavcodec/nvenc.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/libavcodec/nvenc.c b/libavcodec/nvenc.c index bd704a76ad..283a71c294 100644 --- a/libavcodec/nvenc.c +++ b/libavcodec/nvenc.c @@ -57,6 +57,9 @@ #define NVENC_CAP 0x30 #define BITSTREAM_BUFFER_SIZE 1024 * 1024 +#define IS_CBR(rc) (rc == NV_ENC_PARAMS_RC_CBR || \ + rc == NV_ENC_PARAMS_RC_2_PASS_QUALITY || \ + rc == NV_ENC_PARAMS_RC_2_PASS_FRAMESIZE_CAP) #define LOAD_LIBRARY(l, path) \ do { \ @@ -604,6 +607,11 @@ static int nvenc_setup_h264_config(AVCodecContext *avctx) if (ctx->flags & NVENC_LOSSLESS) h264->qpPrimeYZeroTransformBypassFlag = 1; + if (IS_CBR(cc->rcParams.rateControlMode)) { + h264->outputBufferingPeriodSEI = 1; + h264->outputPictureTimingSEI = 1; + } + if (ctx->profile) avctx->profile = ctx->profile; @@ -648,6 +656,11 @@ static int nvenc_setup_hevc_config(AVCodecContext *avctx) hevc->maxNumRefFramesInDPB = avctx->refs; hevc->idrPeriod = cc->gopLength; + if (IS_CBR(cc->rcParams.rateControlMode)) { + hevc->outputBufferingPeriodSEI = 1; + 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; From a1df7865039b8a7743f9067300c0b367db50a727 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 12 May 2016 09:20:19 +0200 Subject: [PATCH 06/13] nvenc: only write the VUI signal type fields if they are set Based on a patch by Agatha Hu . --- libavcodec/nvenc.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/libavcodec/nvenc.c b/libavcodec/nvenc.c index 283a71c294..d28b347c6b 100644 --- a/libavcodec/nvenc.c +++ b/libavcodec/nvenc.c @@ -588,8 +588,9 @@ static int nvenc_setup_h264_config(AVCodecContext *avctx) NV_ENC_CONFIG_H264 *h264 = &cc->encodeCodecConfig.h264Config; NV_ENC_CONFIG_H264_VUI_PARAMETERS *vui = &h264->h264VUIParameters; - vui->colourDescriptionPresentFlag = 1; - vui->videoSignalTypePresentFlag = 1; + vui->colourDescriptionPresentFlag = avctx->colorspace != AVCOL_SPC_UNSPECIFIED || + avctx->color_primaries != AVCOL_PRI_UNSPECIFIED || + avctx->color_trc != AVCOL_TRC_UNSPECIFIED; vui->colourMatrix = avctx->colorspace; vui->colourPrimaries = avctx->color_primaries; @@ -597,6 +598,9 @@ static int nvenc_setup_h264_config(AVCodecContext *avctx) vui->videoFullRangeFlag = avctx->color_range == AVCOL_RANGE_JPEG; + vui->videoSignalTypePresentFlag = vui->colourDescriptionPresentFlag || + vui->videoFullRangeFlag; + h264->disableSPSPPS = (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) ? 1 : 0; h264->repeatSPSPPS = (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) ? 0 : 1; h264->outputAUD = 1; From 2156c4c300971e490b5ca463d78c87c383c2b9a2 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 12 May 2016 09:22:29 +0200 Subject: [PATCH 07/13] nvenc: write the VUI signal properties for HEVC Bump the API version requirement to 6. Based on a patch by Agatha Hu . --- configure | 4 ++-- libavcodec/nvenc.c | 14 ++++++++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/configure b/configure index 664bfffc55..d99a7c8423 100755 --- a/configure +++ b/configure @@ -4667,8 +4667,8 @@ fi if enabled nvenc; then enabled cuda || check_header cuda.h || die "ERROR: cuda.h not found." check_header nvEncodeAPI.h || die "ERROR: nvEncodeAPI.h not found." - check_cpp_condition nvEncodeAPI.h "NVENCAPI_MAJOR_VERSION >= 5" || - die "ERROR: NVENC API version 4 or older is not supported" + check_cpp_condition nvEncodeAPI.h "NVENCAPI_MAJOR_VERSION >= 6" || + die "ERROR: NVENC API version 5 or older is not supported" fi if check_pkg_config sdl SDL_events.h SDL_PollEvent; then diff --git a/libavcodec/nvenc.c b/libavcodec/nvenc.c index d28b347c6b..ff852b10bb 100644 --- a/libavcodec/nvenc.c +++ b/libavcodec/nvenc.c @@ -652,6 +652,20 @@ static int nvenc_setup_hevc_config(AVCodecContext *avctx) NVENCContext *ctx = avctx->priv_data; NV_ENC_CONFIG *cc = &ctx->config; NV_ENC_CONFIG_HEVC *hevc = &cc->encodeCodecConfig.hevcConfig; + NV_ENC_CONFIG_HEVC_VUI_PARAMETERS *vui = &hevc->hevcVUIParameters; + + vui->colourDescriptionPresentFlag = avctx->colorspace != AVCOL_SPC_UNSPECIFIED || + avctx->color_primaries != AVCOL_PRI_UNSPECIFIED || + avctx->color_trc != AVCOL_TRC_UNSPECIFIED; + + vui->colourMatrix = avctx->colorspace; + vui->colourPrimaries = avctx->color_primaries; + vui->transferCharacteristics = avctx->color_trc; + + vui->videoFullRangeFlag = avctx->color_range == AVCOL_RANGE_JPEG; + + vui->videoSignalTypePresentFlag = vui->colourDescriptionPresentFlag || + vui->videoFullRangeFlag; hevc->disableSPSPPS = (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) ? 1 : 0; hevc->repeatSPSPPS = (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) ? 0 : 1; From f11ec8cee72fd2f1d26c4cbc675597422d106e17 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 13 May 2016 09:05:25 +0200 Subject: [PATCH 08/13] nvenc: only support HW frames when CUDA is enabled hwcontext_cuda.h includes cuda.h, so this will allow building nvenc without depending on cuda.h --- libavcodec/nvenc.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/libavcodec/nvenc.c b/libavcodec/nvenc.c index ff852b10bb..7564985964 100644 --- a/libavcodec/nvenc.c +++ b/libavcodec/nvenc.c @@ -48,13 +48,16 @@ #include "libavutil/common.h" #include "libavutil/hwcontext.h" -#include "libavutil/hwcontext_cuda.h" #include "libavutil/imgutils.h" #include "libavutil/mem.h" #include "avcodec.h" #include "internal.h" #include "nvenc.h" +#if CONFIG_CUDA +#include "libavutil/hwcontext_cuda.h" +#endif + #define NVENC_CAP 0x30 #define BITSTREAM_BUFFER_SIZE 1024 * 1024 #define IS_CBR(rc) (rc == NV_ENC_PARAMS_RC_CBR || \ @@ -85,7 +88,9 @@ const enum AVPixelFormat ff_nvenc_pix_fmts[] = { AV_PIX_FMT_NV12, AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV444P, +#if CONFIG_CUDA AV_PIX_FMT_CUDA, +#endif AV_PIX_FMT_NONE }; @@ -395,6 +400,7 @@ static int nvenc_setup_device(AVCodecContext *avctx) } if (avctx->pix_fmt == AV_PIX_FMT_CUDA) { +#if CONFIG_CUDA AVHWFramesContext *frames_ctx; AVCUDADeviceContext *device_hwctx; int ret; @@ -414,6 +420,9 @@ static int nvenc_setup_device(AVCodecContext *avctx) ret = nvenc_check_capabilities(avctx); if (ret < 0) return ret; +#else + return AVERROR_BUG; +#endif } else { int i, nb_devices = 0; From 6f58b4dc477e22237c4e89f6e2a1435aaa45a4d3 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 13 May 2016 09:13:47 +0200 Subject: [PATCH 09/13] nvenc: drop the hard dependency on CUDA The code needs only a few definitions from cuda.h, so define them directly when CUDA is not enabled. CUDA is still required for accepting HW frames as input. Based on the code by Timo Rothenpieler . --- configure | 1 - libavcodec/nvenc.c | 1 - libavcodec/nvenc.h | 19 ++++++++++++++++++- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/configure b/configure index d99a7c8423..6bab581a00 100755 --- a/configure +++ b/configure @@ -4665,7 +4665,6 @@ if enabled libdc1394; then fi if enabled nvenc; then - enabled cuda || check_header cuda.h || die "ERROR: cuda.h not found." check_header nvEncodeAPI.h || die "ERROR: nvEncodeAPI.h not found." check_cpp_condition nvEncodeAPI.h "NVENCAPI_MAJOR_VERSION >= 6" || die "ERROR: NVENC API version 5 or older is not supported" diff --git a/libavcodec/nvenc.c b/libavcodec/nvenc.c index 7564985964..bdd26bb0ea 100644 --- a/libavcodec/nvenc.c +++ b/libavcodec/nvenc.c @@ -21,7 +21,6 @@ #include "config.h" -#include #include #include diff --git a/libavcodec/nvenc.h b/libavcodec/nvenc.h index 8cd5991f4c..e7e6182196 100644 --- a/libavcodec/nvenc.h +++ b/libavcodec/nvenc.h @@ -19,7 +19,6 @@ #ifndef AVCODEC_NVENC_H #define AVCODEC_NVENC_H -#include #include #include "config.h" @@ -29,6 +28,24 @@ #include "avcodec.h" +#if CONFIG_CUDA +#include +#else + +#if defined(_WIN32) +#define CUDAAPI __stdcall +#else +#define CUDAAPI +#endif + +typedef enum cudaError_enum { + CUDA_SUCCESS = 0 +} CUresult; +typedef int CUdevice; +typedef void* CUcontext; +typedef void* CUdeviceptr; +#endif + #define MAX_REGISTERED_FRAMES 64 typedef struct NVENCFrame { From 09522a303db014b48f844443f0f3aaa00af8f165 Mon Sep 17 00:00:00 2001 From: Timo Rothenpieler Date: Sat, 23 Apr 2016 18:55:51 +0200 Subject: [PATCH 10/13] configure: Don't require nonfree for nvenc As the nvEncodeApi.h header is now MIT licensed, this can be dropped. The loaded CUDA and NVENC libraries are part of the nvidia driver, and thus count as system libraries. Signed-off-by: Anton Khirnov --- configure | 1 - 1 file changed, 1 deletion(-) diff --git a/configure b/configure index 6bab581a00..43c563f16c 100755 --- a/configure +++ b/configure @@ -4076,7 +4076,6 @@ die_license_disabled nonfree cuda die_license_disabled nonfree libfaac die_license_disabled nonfree libfdk_aac die_license_disabled nonfree libnpp -die_license_disabled nonfree nvenc die_license_disabled nonfree openssl die_license_disabled version3 libopencore_amrnb From 9375c97460103684146111203958273761173c3b Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 13 May 2016 09:43:51 +0200 Subject: [PATCH 11/13] nvenc: list the major contributors in the copyright header --- libavcodec/nvenc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavcodec/nvenc.c b/libavcodec/nvenc.c index bdd26bb0ea..8ef3ede89c 100644 --- a/libavcodec/nvenc.c +++ b/libavcodec/nvenc.c @@ -1,6 +1,8 @@ /* * NVIDIA NVENC Support * Copyright (C) 2015 Luca Barbato + * Copyright (C) 2015 Philip Langdale + * Copyright (C) 2014 Timo Rothenpieler * * This file is part of Libav. * From 10545f84b83405ca91bce9f62804e1669d1775fb Mon Sep 17 00:00:00 2001 From: Philip Langdale Date: Wed, 28 Jan 2015 09:05:53 -0800 Subject: [PATCH 12/13] nvenc: De-compensate aspect ratio compensation of DVD-like content. For reasons we are not privy to, nvidia decided that the nvenc encoder should apply aspect ratio compensation to 'DVD like' content, assuming that the content is not BT.601 compliant, but needs to be BT.601 compliant. In this context, that means that they make the following, questionable, assumptions: 1) If the input dimensions are 720x480 or 720x576, assume the content has an active area of 704x480 or 704x576. 2) Assume that whatever the input sample aspect ratio is, it does not account for the difference between 'physical' and 'active' dimensions. From these assumptions, they then conclude that they can 'help', by adjusting the sample aspect ratio by a factor of 45/44. And indeed, if you wanted to display only the 704 wide active area with the same aspect ratio as the full 720 wide image - this would be the correct adjustment factor, but what if you don't? And more importantly, what if you're used to lavc not making this kind of adjustment at encode time - because none of the other encoders do this! And, what if you had already accounted for BT.601 and your input had the correct attributes? Well, it's going to apply the compensation anyway! So, if you take some content, and feed it through nvenc repeatedly, it will keep scaling the aspect ratio every time, stretching your video out more and more and more. So, clearly, regardless of whether you want to apply bt.601 aspect ratio adjustments or not, this is not the way to do it. With any other lavc encoder, you would do it as part of defining your input parameters or do the adjustment at playback time, and there's no reason by nvenc should be any different. This change adds some logic to undo the compensation that nvenc would otherwise do. nvidia engineers have told us that they will work to make this compensation mechanism optional in a future release of the nvenc SDK. At that point, we can adapt accordingly. Signed-off-by: Philip Langdale Reviewed-by: Timo Rothenpieler Signed-off-by: Anton Khirnov --- libavcodec/nvenc.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/libavcodec/nvenc.c b/libavcodec/nvenc.c index 8ef3ede89c..2593ba4cff 100644 --- a/libavcodec/nvenc.c +++ b/libavcodec/nvenc.c @@ -743,6 +743,15 @@ static int nvenc_setup_encoder(AVCodecContext *avctx) ctx->params.darWidth = avctx->width; } + // De-compensate for hardware, dubiously, trying to compensate for + // playback at 704 pixel width. + if (avctx->width == 720 && (avctx->height == 480 || avctx->height == 576)) { + av_reduce(&ctx->params.darWidth, &ctx->params.darHeight, + ctx->params.darWidth * 44, + ctx->params.darHeight * 45, + 1024 * 1024); + } + ctx->params.frameRateNum = avctx->time_base.den; ctx->params.frameRateDen = avctx->time_base.num * avctx->ticks_per_frame; From 3399a26d3f57d462e839c0ee51223ae9aca20852 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 14 May 2016 16:47:55 +0200 Subject: [PATCH 13/13] nvenc: allow setting the number of slices Based on a patch by Agatha Hu --- libavcodec/nvenc.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libavcodec/nvenc.c b/libavcodec/nvenc.c index 2593ba4cff..1ff27a1932 100644 --- a/libavcodec/nvenc.c +++ b/libavcodec/nvenc.c @@ -618,6 +618,9 @@ static int nvenc_setup_h264_config(AVCodecContext *avctx) h264->maxNumRefFrames = avctx->refs; h264->idrPeriod = cc->gopLength; + h264->sliceMode = 3; + h264->sliceModeData = FFMAX(avctx->slices, 1); + if (ctx->flags & NVENC_LOSSLESS) h264->qpPrimeYZeroTransformBypassFlag = 1; @@ -693,6 +696,9 @@ static int nvenc_setup_hevc_config(AVCodecContext *avctx) cc->profileGUID = NV_ENC_HEVC_PROFILE_MAIN_GUID; avctx->profile = FF_PROFILE_HEVC_MAIN; + hevc->sliceMode = 3; + hevc->sliceModeData = FFMAX(avctx->slices, 1); + if (ctx->level) { hevc->level = ctx->level; } else {