nvenc: Reduce the number of pre-allocated device memory
authorSeungha Yang <seungha.yang@navercorp.com>
Wed, 11 Sep 2019 05:56:00 +0000 (14:56 +0900)
committerMatthew Waters <matthew@centricular.com>
Wed, 11 Sep 2019 11:44:03 +0000 (11:44 +0000)
The hard-coded upper bound 32 (or 48 depending on resolution) might waste
GPU memory and high resolution encoding causes OUT-OF-MEMORY allocation error
quite easily. This commit calculates the number of required pre-allocated
device memory based on encoding options and it can reduce the amount of device memory
used by nvenc.

sys/nvcodec/gstnvbaseenc.c

index 05466eb..f624b74 100644 (file)
@@ -1437,6 +1437,36 @@ gst_nv_base_enc_setup_rate_control (GstNvBaseEnc * nvenc,
   }
 }
 
+static gint
+gst_nv_base_enc_calculate_num_prealloc_buffers (GstNvBaseEnc * enc,
+    NV_ENC_CONFIG * config)
+{
+  gint num_buffers;
+
+  /* At least 4 surfaces are required as documented by Nvidia Encoder guide */
+  num_buffers = 4;
+
+  /* + lookahead depth */
+  num_buffers += config->rcParams.lookaheadDepth;
+
+  /* + GOP size */
+  num_buffers += config->frameIntervalP;
+
+  /* hardcoded upper bound "48"
+   * The worst case
+   *   default num buffers: 4
+   *   maximum allowed lookahead: 32
+   *   max bfraems: 4 -> frameIntervalP: 5
+   * "4 + 32 + 5" < "48" so it seems to sufficiently safe upper bound */
+  num_buffers = MIN (num_buffers, 48);
+
+  GST_DEBUG_OBJECT (enc, "Calculated num buffers: %d "
+      "(lookahead %d, frameIntervalP %d)",
+      num_buffers, config->rcParams.lookaheadDepth, config->frameIntervalP);
+
+  return num_buffers;
+}
+
 /* GstVideoEncoder::set_format or by nvenc self if new properties were set.
  *
  * NvEncReconfigureEncoder with following conditions are not allowed
@@ -1669,15 +1699,15 @@ gst_nv_base_enc_set_format (GstVideoEncoder * enc, GstVideoCodecState * state)
 #if HAVE_NVCODEC_GST_GL
     GstCapsFeatures *features;
 #endif
-    guint num_macroblocks, i;
+    guint i;
     guint input_width, input_height;
 
     input_width = GST_VIDEO_INFO_WIDTH (info);
     input_height = GST_VIDEO_INFO_HEIGHT (info);
 
-    num_macroblocks = (GST_ROUND_UP_16 (input_width) >> 4)
-        * (GST_ROUND_UP_16 (input_height) >> 4);
-    nvenc->n_bufs = (num_macroblocks >= 8160) ? 32 : 48;
+    nvenc->n_bufs =
+        gst_nv_base_enc_calculate_num_prealloc_buffers (nvenc,
+        params->encodeConfig);
 
     /* input buffers */
     g_array_set_size (nvenc->items, nvenc->n_bufs);