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[] = {
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++;
*/
#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;
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);
}
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);
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))
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)
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);
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)
{
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;
}
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) {
#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;
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);