From ee7190bbf6264c5a711b3e79d441ee6f6c16cd95 Mon Sep 17 00:00:00 2001
From: Roman Arzumanyan <rarzumanyan@nvidia.com>
Date: Thu, 26 Sep 2019 14:31:41 +0300
Subject: [PATCH] avcodec/nvenc: adding multiple reference frames

---
 libavcodec/nvenc.c      | 12 ++++++++++++
 libavcodec/nvenc.h      |  1 +
 libavcodec/nvenc_h264.c |  6 ++++++
 libavcodec/nvenc_hevc.c |  6 ++++++
 4 files changed, 25 insertions(+)

diff --git a/libavcodec/nvenc.c b/libavcodec/nvenc.c
index 316e4a3679..3334b43c6d 100644
--- a/libavcodec/nvenc.c
+++ b/libavcodec/nvenc.c
@@ -387,6 +387,12 @@ static int nvenc_check_capabilities(AVCodecContext *avctx)
         return AVERROR(ENOSYS);
     }
 
+    ret = nvenc_check_cap(avctx, NV_ENC_CAPS_SUPPORT_MULTIPLE_REF_FRAMES);
+    if(ctx->nb_ref_frames != NV_ENC_NUM_REF_FRAMES_AUTOSELECT && ret <= 0) {
+        av_log(avctx, AV_LOG_VERBOSE, "Given reference frames number is not supported\n");
+        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) {
@@ -1010,6 +1016,9 @@ static av_cold int nvenc_setup_h264_config(AVCodecContext *avctx)
     h264->useBFramesAsRef = ctx->b_ref_mode;
 #endif
 
+    h264->numRefL0 = ctx->nb_ref_frames;
+    h264->numRefL1 = ctx->nb_ref_frames;
+
     return 0;
 }
 
@@ -1094,6 +1103,9 @@ static av_cold int nvenc_setup_hevc_config(AVCodecContext *avctx)
     hevc->useBFramesAsRef = ctx->b_ref_mode;
 #endif
 
+    hevc->numRefL0 = ctx->nb_ref_frames;
+    hevc->numRefL1 = ctx->nb_ref_frames;
+
     return 0;
 }
 
diff --git a/libavcodec/nvenc.h b/libavcodec/nvenc.h
index ddd6168409..28ea1b854f 100644
--- a/libavcodec/nvenc.h
+++ b/libavcodec/nvenc.h
@@ -192,6 +192,7 @@ typedef struct NvencContext
     int coder;
     int b_ref_mode;
     int a53_cc;
+    int nb_ref_frames;
 } NvencContext;
 
 int ff_nvenc_encode_init(AVCodecContext *avctx);
diff --git a/libavcodec/nvenc_h264.c b/libavcodec/nvenc_h264.c
index a6623f5f35..264b0da867 100644
--- a/libavcodec/nvenc_h264.c
+++ b/libavcodec/nvenc_h264.c
@@ -138,6 +138,12 @@ static const AVOption options[] = {
     { "middle",       "",                                   0,                    AV_OPT_TYPE_CONST, { .i64 = 2 }, 0, 0,       VE, "b_ref_mode" },
 #endif
     { "a53cc",        "Use A53 Closed Captions (if available)", OFFSET(a53_cc),   AV_OPT_TYPE_BOOL,  { .i64 = 1 }, 0, 1, VE },
+    { "nb_ref_frames", 
+                      "Use multiple reference frames: ('auto' to let HW decide, integer number to set by hand",      
+                                                            OFFSET(nb_ref_frames),  
+                                                                                  AV_OPT_TYPE_INT,   { .i64 = NV_ENC_NUM_REF_FRAMES_AUTOSELECT }, NV_ENC_NUM_REF_FRAMES_AUTOSELECT, NV_ENC_NUM_REF_FRAMES_7, VE, "nb_ref_frames" },
+    { "auto",         "Number of reference frames is auto selected by the encoder driver",
+                                                            0,                    AV_OPT_TYPE_CONST, { .i64 = NV_ENC_NUM_REF_FRAMES_AUTOSELECT }, 0,                                0,                       VE, "nb_ref_frames" },
     { NULL }
 };
 
diff --git a/libavcodec/nvenc_hevc.c b/libavcodec/nvenc_hevc.c
index d567d960ba..29fee69792 100644
--- a/libavcodec/nvenc_hevc.c
+++ b/libavcodec/nvenc_hevc.c
@@ -127,6 +127,12 @@ static const AVOption options[] = {
     { "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
+    { "nb_ref_frames", 
+                      "Use multiple reference frames: ('auto' to let HW decide, integer number to set by hand",      
+                                                            OFFSET(nb_ref_frames),  
+                                                                                  AV_OPT_TYPE_INT,   { .i64 = NV_ENC_NUM_REF_FRAMES_AUTOSELECT }, NV_ENC_NUM_REF_FRAMES_AUTOSELECT, NV_ENC_NUM_REF_FRAMES_7, VE, "nb_ref_frames" },
+    { "auto",         "Number of reference frames is auto selected by the encoder driver",
+                                                            0,                    AV_OPT_TYPE_CONST, { .i64 = NV_ENC_NUM_REF_FRAMES_AUTOSELECT }, 0,                                0,                       VE, "nb_ref_frames" },
     { NULL }
 };
 
-- 
2.16.1.windows.4

