omxvideoenc: implement decide_allocation
authorGuillaume Desmottes <guillaume.desmottes@collabora.co.uk>
Thu, 26 Apr 2018 10:30:47 +0000 (12:30 +0200)
committerGuillaume Desmottes <guillaume.desmottes@collabora.co.uk>
Fri, 8 Jun 2018 07:53:01 +0000 (09:53 +0200)
Increase the number of output buffers by the number of buffers requested
downstream.
Prevent buffers starvation if downstream is going to use dynamic buffer
mode on its input.

https://bugzilla.gnome.org/show_bug.cgi?id=795746

omx/gstomx.c
omx/gstomx.h
omx/gstomxvideodec.c
omx/gstomxvideoenc.c
omx/gstomxvideoenc.h

index 94bc014..52e6d68 100644 (file)
@@ -2552,17 +2552,19 @@ done:
  * less buffers than the worst case in such scenarios.
  */
 gboolean
-gst_omx_port_ensure_buffer_count_actual (GstOMXPort * port)
+gst_omx_port_ensure_buffer_count_actual (GstOMXPort * port, guint extra)
 {
   OMX_PARAM_PORTDEFINITIONTYPE port_def;
+  guint nb;
 
   gst_omx_port_get_port_definition (port, &port_def);
-  if (port_def.nBufferCountActual != port_def.nBufferCountMin) {
-    port_def.nBufferCountActual = port_def.nBufferCountMin;
+
+  nb = port_def.nBufferCountMin + extra;
+  if (port_def.nBufferCountActual != nb) {
+    port_def.nBufferCountActual = nb;
 
     GST_DEBUG_OBJECT (port->comp->parent,
-        "set port %d nBufferCountActual to %d",
-        (guint) port->index, (guint) port_def.nBufferCountActual);
+        "set port %d nBufferCountActual to %d", (guint) port->index, nb);
 
     if (gst_omx_port_update_port_definition (port, &port_def) != OMX_ErrorNone)
       return FALSE;
index 4600833..eab7b7d 100644 (file)
@@ -455,7 +455,7 @@ OMX_ERRORTYPE     gst_omx_port_mark_reconfigured (GstOMXPort * port);
 OMX_ERRORTYPE     gst_omx_port_set_enabled (GstOMXPort * port, gboolean enabled);
 OMX_ERRORTYPE     gst_omx_port_wait_enabled (GstOMXPort * port, GstClockTime timeout);
 gboolean          gst_omx_port_is_enabled (GstOMXPort * port);
-gboolean          gst_omx_port_ensure_buffer_count_actual (GstOMXPort * port);
+gboolean          gst_omx_port_ensure_buffer_count_actual (GstOMXPort * port, guint extra);
 
 /* OMX 1.2.0 dynamic allocation mode */
 gboolean          gst_omx_is_dynamic_allocation_supported (void);
index e885a99..989d185 100644 (file)
@@ -2335,7 +2335,7 @@ gst_omx_video_dec_ensure_nb_in_buffers (GstOMXVideoDec * self)
   GstOMXVideoDecClass *klass = GST_OMX_VIDEO_DEC_GET_CLASS (self);
 
   if ((klass->cdata.hacks & GST_OMX_HACK_ENSURE_BUFFER_COUNT_ACTUAL)) {
-    if (!gst_omx_port_ensure_buffer_count_actual (self->dec_in_port))
+    if (!gst_omx_port_ensure_buffer_count_actual (self->dec_in_port, 0))
       return FALSE;
   }
 
index faba38e..1a630c4 100644 (file)
@@ -226,6 +226,8 @@ static gboolean gst_omx_video_enc_propose_allocation (GstVideoEncoder * encoder,
     GstQuery * query);
 static GstCaps *gst_omx_video_enc_getcaps (GstVideoEncoder * encoder,
     GstCaps * filter);
+static gboolean gst_omx_video_enc_decide_allocation (GstVideoEncoder * encoder,
+    GstQuery * query);
 
 static GstFlowReturn gst_omx_video_enc_drain (GstOMXVideoEnc * self);
 
@@ -481,6 +483,8 @@ gst_omx_video_enc_class_init (GstOMXVideoEncClass * klass)
   video_encoder_class->propose_allocation =
       GST_DEBUG_FUNCPTR (gst_omx_video_enc_propose_allocation);
   video_encoder_class->getcaps = GST_DEBUG_FUNCPTR (gst_omx_video_enc_getcaps);
+  video_encoder_class->decide_allocation =
+      GST_DEBUG_FUNCPTR (gst_omx_video_enc_decide_allocation);
 
   klass->cdata.type = GST_OMX_COMPONENT_TYPE_FILTER;
   klass->cdata.default_sink_template_caps = "video/x-raw, "
@@ -1372,11 +1376,18 @@ static gboolean
 gst_omx_video_enc_ensure_nb_out_buffers (GstOMXVideoEnc * self)
 {
   GstOMXVideoEncClass *klass = GST_OMX_VIDEO_ENC_GET_CLASS (self);
+  guint extra = 0;
 
-  if ((klass->cdata.hacks & GST_OMX_HACK_ENSURE_BUFFER_COUNT_ACTUAL)) {
-    if (!gst_omx_port_ensure_buffer_count_actual (self->enc_out_port))
-      return FALSE;
-  }
+  if (!(klass->cdata.hacks & GST_OMX_HACK_ENSURE_BUFFER_COUNT_ACTUAL))
+    return TRUE;
+
+  /* If dowstream tell us how many buffers it needs allocate as many extra buffers so we won't starve
+   * if it keeps them downstream (like when using dynamic mode). */
+  if (self->nb_downstream_buffers)
+    extra = self->nb_downstream_buffers;
+
+  if (!gst_omx_port_ensure_buffer_count_actual (self->enc_out_port, extra))
+    return FALSE;
 
   return TRUE;
 }
@@ -1641,6 +1652,7 @@ gst_omx_video_enc_start (GstVideoEncoder * encoder)
 
   self->last_upstream_ts = 0;
   self->downstream_flow_ret = GST_FLOW_OK;
+  self->nb_downstream_buffers = 0;
 
   return TRUE;
 }
@@ -1883,7 +1895,7 @@ gst_omx_video_enc_ensure_nb_in_buffers (GstOMXVideoEnc * self)
   GstOMXVideoEncClass *klass = GST_OMX_VIDEO_ENC_GET_CLASS (self);
 
   if ((klass->cdata.hacks & GST_OMX_HACK_ENSURE_BUFFER_COUNT_ACTUAL)) {
-    if (!gst_omx_port_ensure_buffer_count_actual (self->enc_in_port))
+    if (!gst_omx_port_ensure_buffer_count_actual (self->enc_in_port, 0))
       return FALSE;
   }
 
@@ -3030,3 +3042,28 @@ gst_omx_video_enc_getcaps (GstVideoEncoder * encoder, GstCaps * filter)
 
   return ret;
 }
+
+static gboolean
+gst_omx_video_enc_decide_allocation (GstVideoEncoder * encoder,
+    GstQuery * query)
+{
+  GstOMXVideoEnc *self = GST_OMX_VIDEO_ENC (encoder);
+  guint min = 1;
+
+  if (!GST_VIDEO_ENCODER_CLASS
+      (gst_omx_video_enc_parent_class)->decide_allocation (encoder, query))
+    return FALSE;
+
+  if (gst_query_get_n_allocation_pools (query)) {
+    gst_query_parse_nth_allocation_pool (query, 0, NULL, NULL, &min, NULL);
+    GST_DEBUG_OBJECT (self,
+        "Downstream requested %d buffers, adjust number of output buffers accordingly",
+        min);
+  } else {
+    GST_DEBUG_OBJECT (self, "Downstream didn't set any allocation pool info");
+  }
+
+  self->nb_downstream_buffers = min;
+
+  return TRUE;
+}
index 53a008e..370b290 100644 (file)
@@ -101,6 +101,8 @@ struct _GstOMXVideoEnc
   GstOMXBufferAllocation input_allocation;
   /* TRUE if encoder is passing dmabuf's fd directly to the OMX component */
   gboolean input_dmabuf;
+  /* Number of buffers requested downstream */
+  guint nb_downstream_buffers;
 
 #ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
   GEnumClass *alg_roi_quality_enum_class;