From 86e9dba8fa5be26e10a096b675616b9ddb950031 Mon Sep 17 00:00:00 2001 From: Timo Rothenpieler Date: Wed, 11 Apr 2018 14:22:20 +0200 Subject: [PATCH] avcodec/nvenc: add support for B frames as ref --- libavcodec/nvenc.c | 20 ++++++++++++++++++++ libavcodec/nvenc.h | 7 +++++++ libavcodec/nvenc_h264.c | 11 +++++++++++ 3 files changed, 38 insertions(+) diff --git a/libavcodec/nvenc.c b/libavcodec/nvenc.c index 1f601a63bd..e2d1100cc8 100644 --- a/libavcodec/nvenc.c +++ b/libavcodec/nvenc.c @@ -370,6 +370,22 @@ static int nvenc_check_capabilities(AVCodecContext *avctx) return AVERROR(ENOSYS); } +#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) { + av_log(avctx, AV_LOG_VERBOSE, "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) { + av_log(avctx, AV_LOG_VERBOSE, "B frames as references are not supported\n"); + return AVERROR(ENOSYS); + } +#else + if (ctx->b_ref_mode != 0) { + av_log(avctx, AV_LOG_VERBOSE, "B frames as references need SDK 8.1 at build time\n"); + return AVERROR(ENOSYS); + } +#endif + return 0; } @@ -988,6 +1004,10 @@ static av_cold int nvenc_setup_h264_config(AVCodecContext *avctx) if (ctx->coder >= 0) h264->entropyCodingMode = ctx->coder; +#ifdef NVENC_HAVE_BFRAME_REF_MODE + h264->useBFramesAsRef = ctx->b_ref_mode; +#endif + return 0; } diff --git a/libavcodec/nvenc.h b/libavcodec/nvenc.h index bff25dfc3c..2d6e781739 100644 --- a/libavcodec/nvenc.h +++ b/libavcodec/nvenc.h @@ -40,6 +40,12 @@ typedef void ID3D11Device; #define RC_MODE_DEPRECATED 0x800000 #define RCD(rc_mode) ((rc_mode) | RC_MODE_DEPRECATED) +// SDK 8.1 compile time feature checks +#if NVENCAPI_VERSION >= 0x01000008 +#define NVENC_HAVE_BFRAME_REF_MODE +#define NVENC_HAVE_QP_MAP_MODE +#endif + typedef struct NvencSurface { NV_ENC_INPUT_PTR input_surface; @@ -174,6 +180,7 @@ typedef struct NvencContext int cqp; int weighted_pred; int coder; + int b_ref_mode; } NvencContext; int ff_nvenc_encode_init(AVCodecContext *avctx); diff --git a/libavcodec/nvenc_h264.c b/libavcodec/nvenc_h264.c index bc7bbcddeb..d446f9b33c 100644 --- a/libavcodec/nvenc_h264.c +++ b/libavcodec/nvenc_h264.c @@ -126,6 +126,17 @@ static const AVOption options[] = { { "cavlc", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_H264_ENTROPY_CODING_MODE_CAVLC }, 0, 0, VE, "coder" }, { "ac", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_H264_ENTROPY_CODING_MODE_CABAC }, 0, 0, VE, "coder" }, { "vlc", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_H264_ENTROPY_CODING_MODE_CAVLC }, 0, 0, VE, "coder" }, +#ifdef NVENC_HAVE_BFRAME_REF_MODE + { "b_ref_mode", "Use B frames as references", OFFSET(b_ref_mode), AV_OPT_TYPE_INT, { .i64 = NV_ENC_BFRAME_REF_MODE_DISABLED }, NV_ENC_BFRAME_REF_MODE_DISABLED, NV_ENC_BFRAME_REF_MODE_MIDDLE, VE, "b_ref_mode" }, + { "disabled", "B frames will not be used for reference", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_BFRAME_REF_MODE_DISABLED }, 0, 0, VE, "b_ref_mode" }, + { "each", "Each B frame will be used for reference", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_BFRAME_REF_MODE_EACH }, 0, 0, VE, "b_ref_mode" }, + { "middle", "Only (number of B frames)/2 will be used for reference", 0,AV_OPT_TYPE_CONST, { .i64 = NV_ENC_BFRAME_REF_MODE_MIDDLE }, 0, 0, VE, "b_ref_mode" }, +#else + { "b_ref_mode", "(not supported)", OFFSET(b_ref_mode), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, VE, "b_ref_mode" }, + { "disabled", "", 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, 0, 0, VE, "b_ref_mode" }, + { "each", "", 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, 0, 0, VE, "b_ref_mode" }, + { "middle", "", 0, AV_OPT_TYPE_CONST, { .i64 = 2 }, 0, 0, VE, "b_ref_mode" }, +#endif { NULL } };