summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGuillaume Desmottes <guillaume.desmottes@collabora.co.uk>2018-04-27 16:26:36 +0200
committerGuillaume Desmottes <guillaume.desmottes@collabora.co.uk>2018-06-08 09:44:49 +0200
commit9a8e863862835d6598cef6fdfb21fea0deeb056b (patch)
tree2b8d2da88764fc97ba58be0058581faba127a21e
parent338ff34e5ea5527475d7e56d71f13a422ad31620 (diff)
downloadgst-omx-9a8e863862835d6598cef6fdfb21fea0deeb056b.tar.gz
omxvideodec/enc: add hack updating nBufferCountActual before allocating
The OMX specs states that the nBufferCountActual of a port has to default to its nBufferCountMin. If we don't change nBufferCountActual we purely rely on this default. But in some cases, OMX may change nBufferCountMin before we allocate buffers. Like for example when configuring the input ports with the actual format, it may decrease the number of minimal buffers required. This method checks this and update nBufferCountActual if needed so we'll use less buffers than the worst case in such scenarios. SetParameter() needs to be called when the port is either disabled or the component in the Loaded state. Don't do this for the decoder output as gst_omx_video_dec_allocate_output_buffers() already check nBufferCountMin when computing the number of output buffers. On some platform, like rpi, the default nBufferCountActual is much higher than nBufferCountMin so only enable this using a specific gst-omx hack. https://bugzilla.gnome.org/show_bug.cgi?id=791211
-rw-r--r--omx/gstomx.c30
-rw-r--r--omx/gstomx.h8
-rw-r--r--omx/gstomxvideodec.c23
-rw-r--r--omx/gstomxvideoenc.c40
4 files changed, 101 insertions, 0 deletions
diff --git a/omx/gstomx.c b/omx/gstomx.c
index 6276fea..94bc014 100644
--- a/omx/gstomx.c
+++ b/omx/gstomx.c
@@ -2543,6 +2543,34 @@ done:
return err;
}
+/* The OMX specs states that the nBufferCountActual of a port has to default
+ * to its nBufferCountMin. If we don't change nBufferCountActual we purely rely
+ * on this default. But in some cases, OMX may change nBufferCountMin before we
+ * allocate buffers. Like for example when configuring the input ports with the
+ * actual format, it may decrease the number of minimal buffers required.
+ * This method checks this and update nBufferCountActual if needed so we'll use
+ * less buffers than the worst case in such scenarios.
+ */
+gboolean
+gst_omx_port_ensure_buffer_count_actual (GstOMXPort * port)
+{
+ OMX_PARAM_PORTDEFINITIONTYPE port_def;
+
+ gst_omx_port_get_port_definition (port, &port_def);
+ if (port_def.nBufferCountActual != port_def.nBufferCountMin) {
+ port_def.nBufferCountActual = port_def.nBufferCountMin;
+
+ GST_DEBUG_OBJECT (port->comp->parent,
+ "set port %d nBufferCountActual to %d",
+ (guint) port->index, (guint) port_def.nBufferCountActual);
+
+ if (gst_omx_port_update_port_definition (port, &port_def) != OMX_ErrorNone)
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
typedef GType (*GGetTypeFunction) (void);
static const GGetTypeFunction types[] = {
@@ -2858,6 +2886,8 @@ gst_omx_parse_hacks (gchar ** hacks)
hacks_flags |= GST_OMX_HACK_PASS_PROFILE_TO_DECODER;
else if (g_str_equal (*hacks, "pass-color-format-to-decoder"))
hacks_flags |= GST_OMX_HACK_PASS_COLOR_FORMAT_TO_DECODER;
+ else if (g_str_equal (*hacks, "ensure-buffer-count-actual"))
+ hacks_flags |= GST_OMX_HACK_ENSURE_BUFFER_COUNT_ACTUAL;
else
GST_WARNING ("Unknown hack: %s", *hacks);
hacks++;
diff --git a/omx/gstomx.h b/omx/gstomx.h
index e1ea76b..4600833 100644
--- a/omx/gstomx.h
+++ b/omx/gstomx.h
@@ -200,6 +200,13 @@ G_BEGIN_DECLS
*/
#define GST_OMX_HACK_PASS_COLOR_FORMAT_TO_DECODER G_GUINT64_CONSTANT (0x0000000000001000)
+/* If set, automatically update nBufferCountActual to nBufferCountMin before
+ * allocating buffers. This can be used on OMX implementation decreasing
+ * nBufferCountMin depending of the format and so can reduce the number
+ * of allocated buffers.
+ */
+#define GST_OMX_HACK_ENSURE_BUFFER_COUNT_ACTUAL G_GUINT64_CONSTANT (0x0000000000002000)
+
typedef struct _GstOMXCore GstOMXCore;
typedef struct _GstOMXPort GstOMXPort;
typedef enum _GstOMXPortDirection GstOMXPortDirection;
@@ -448,6 +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);
/* OMX 1.2.0 dynamic allocation mode */
gboolean gst_omx_is_dynamic_allocation_supported (void);
diff --git a/omx/gstomxvideodec.c b/omx/gstomxvideodec.c
index 1d94cce..1428ef8 100644
--- a/omx/gstomxvideodec.c
+++ b/omx/gstomxvideodec.c
@@ -2341,6 +2341,19 @@ gst_omx_video_dec_pick_input_allocation_mode (GstOMXVideoDec * self,
}
static gboolean
+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))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
gst_omx_video_dec_enable (GstOMXVideoDec * self, GstBuffer * input)
{
GstOMXVideoDecClass *klass = GST_OMX_VIDEO_DEC_GET_CLASS (self);
@@ -2351,6 +2364,8 @@ gst_omx_video_dec_enable (GstOMXVideoDec * self, GstBuffer * input)
input);
if (self->disabled) {
+ if (!gst_omx_video_dec_ensure_nb_in_buffers (self))
+ return FALSE;
if (gst_omx_port_set_enabled (self->dec_in_port, TRUE) != OMX_ErrorNone)
return FALSE;
if (!gst_omx_video_dec_allocate_in_buffers (self))
@@ -2376,6 +2391,9 @@ gst_omx_video_dec_enable (GstOMXVideoDec * self, GstBuffer * input)
if (!gst_omx_video_dec_negotiate (self))
GST_LOG_OBJECT (self, "Negotiation failed, will get output format later");
+ if (!gst_omx_video_dec_ensure_nb_in_buffers (self))
+ return FALSE;
+
if (!(klass->cdata.hacks & GST_OMX_HACK_NO_DISABLE_OUTPORT)) {
/* Disable output port */
if (gst_omx_port_set_enabled (self->dec_out_port, FALSE) != OMX_ErrorNone)
@@ -2802,6 +2820,11 @@ gst_omx_video_dec_handle_frame (GstVideoDecoder * decoder,
goto reconfigure_error;
}
+ if (!gst_omx_video_dec_ensure_nb_in_buffers (self)) {
+ GST_VIDEO_DECODER_STREAM_LOCK (self);
+ goto reconfigure_error;
+ }
+
err = gst_omx_port_set_enabled (port, TRUE);
if (err != OMX_ErrorNone) {
GST_VIDEO_DECODER_STREAM_LOCK (self);
diff --git a/omx/gstomxvideoenc.c b/omx/gstomxvideoenc.c
index 8a0ed3f..56e2651 100644
--- a/omx/gstomxvideoenc.c
+++ b/omx/gstomxvideoenc.c
@@ -1368,6 +1368,19 @@ gst_omx_video_enc_handle_output_frame (GstOMXVideoEnc * self, GstOMXPort * port,
return flow_ret;
}
+static gboolean
+gst_omx_video_enc_ensure_nb_out_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_out_port))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
static void
gst_omx_video_enc_loop (GstOMXVideoEnc * self)
{
@@ -1444,6 +1457,9 @@ gst_omx_video_enc_loop (GstOMXVideoEnc * self)
GST_VIDEO_ENCODER_STREAM_UNLOCK (self);
if (acq_return == GST_OMX_ACQUIRE_BUFFER_RECONFIGURE) {
+ if (!gst_omx_video_enc_ensure_nb_out_buffers (self))
+ goto reconfigure_error;
+
err = gst_omx_port_set_enabled (port, TRUE);
if (err != OMX_ErrorNone)
goto reconfigure_error;
@@ -1875,6 +1891,19 @@ gst_omx_video_enc_configure_input_buffer (GstOMXVideoEnc * self,
}
static gboolean
+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))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
gst_omx_video_enc_allocate_in_buffers (GstOMXVideoEnc * self)
{
switch (self->input_allocation) {
@@ -2008,6 +2037,12 @@ gst_omx_video_enc_enable (GstOMXVideoEnc * self, GstBuffer * input)
#endif
GST_DEBUG_OBJECT (self, "Enabling component");
+
+ if (!gst_omx_video_enc_ensure_nb_in_buffers (self))
+ return FALSE;
+ if (!gst_omx_video_enc_ensure_nb_out_buffers (self))
+ return FALSE;
+
if (self->disabled) {
if (gst_omx_port_set_enabled (self->enc_in_port, TRUE) != OMX_ErrorNone)
return FALSE;
@@ -2650,6 +2685,11 @@ gst_omx_video_enc_handle_frame (GstVideoEncoder * encoder,
goto reconfigure_error;
}
+ if (!gst_omx_video_enc_ensure_nb_in_buffers (self)) {
+ GST_VIDEO_ENCODER_STREAM_LOCK (self);
+ goto reconfigure_error;
+ }
+
err = gst_omx_port_set_enabled (port, TRUE);
if (err != OMX_ErrorNone) {
GST_VIDEO_ENCODER_STREAM_LOCK (self);