From f79bbc302bf835e00cead2733b3219231826b30a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Fri, 11 Jan 2013 17:44:13 +0000 Subject: [PATCH] omx: Add methods to set up and close a tunnel between components --- omx/gstomx.c | 141 ++++++++++++++++++++++++++++++++++++++++++++++++--- omx/gstomx.h | 5 ++ 2 files changed, 138 insertions(+), 8 deletions(-) diff --git a/omx/gstomx.c b/omx/gstomx.c index 09786ffa92..84b9b2b2a2 100644 --- a/omx/gstomx.c +++ b/omx/gstomx.c @@ -114,6 +114,9 @@ gst_omx_core_acquire (const gchar * filename) if (!g_module_symbol (core->module, "OMX_FreeHandle", (gpointer *) & core->free_handle)) goto symbol_error; + if (!g_module_symbol (core->module, "OMX_SetupTunnel", + (gpointer *) & core->setup_tunnel)) + goto symbol_error; GST_DEBUG ("Successfully loaded core '%s'", filename); } @@ -288,7 +291,9 @@ gst_omx_component_handle_messages (GstOMXComponent * comp) if (index == OMX_ALL || index == port->index) { port->settings_cookie++; - if (port->port_def.eDir == OMX_DirOutput) + gst_omx_port_update_port_definition (port, NULL); + if (port->port_def.eDir == OMX_DirOutput && !port->tunneled + && port->port_def.bEnabled) outports = g_list_prepend (outports, port); } } @@ -507,6 +512,11 @@ EmptyBufferDone (OMX_HANDLETYPE hComponent, OMX_PTR pAppData, g_assert (buf->omx_buf == pBuffer); + if (buf->port->tunneled) { + GST_ERROR ("EmptyBufferDone on tunneled port"); + return OMX_ErrorBadParameter; + } + comp = buf->port->comp; msg = g_slice_new (GstOMXMessage); @@ -540,6 +550,11 @@ FillBufferDone (OMX_HANDLETYPE hComponent, OMX_PTR pAppData, g_assert (buf->omx_buf == pBuffer); + if (buf->port->tunneled) { + GST_ERROR ("FillBufferDone on tunneled port"); + return OMX_ErrorBadParameter; + } + comp = buf->port->comp; msg = g_slice_new (GstOMXMessage); @@ -854,6 +869,8 @@ gst_omx_component_add_port (GstOMXComponent * comp, guint32 index) port->comp = comp; port->index = index; + port->tunneled = FALSE; + port->port_def = port_def; g_queue_init (&port->pending_buffers); @@ -1032,6 +1049,104 @@ gst_omx_component_set_config (GstOMXComponent * comp, OMX_INDEXTYPE index, return err; } +OMX_ERRORTYPE +gst_omx_component_setup_tunnel (GstOMXComponent * comp1, GstOMXPort * port1, + GstOMXComponent * comp2, GstOMXPort * port2) +{ + OMX_ERRORTYPE err; + + g_return_val_if_fail (comp1 != NULL, OMX_ErrorUndefined); + g_return_val_if_fail (comp1->state == OMX_StateLoaded + || !port1->port_def.bEnabled, OMX_ErrorUndefined); + g_return_val_if_fail (port1 != NULL, OMX_ErrorUndefined); + g_return_val_if_fail (port1->port_def.eDir == OMX_DirOutput, + OMX_ErrorUndefined); + g_return_val_if_fail (comp2 != NULL, OMX_ErrorUndefined); + g_return_val_if_fail (comp2->state == OMX_StateLoaded + || !port2->port_def.bEnabled, OMX_ErrorUndefined); + g_return_val_if_fail (port2 != NULL, OMX_ErrorUndefined); + g_return_val_if_fail (port2->port_def.eDir == OMX_DirInput, + OMX_ErrorUndefined); + g_return_val_if_fail (comp1->core == comp2->core, OMX_ErrorUndefined); + + g_mutex_lock (&comp1->lock); + g_mutex_lock (&comp2->lock); + GST_DEBUG_OBJECT (comp1->parent, + "Setup tunnel between %p port %u and %p port %u", + comp1, port1->index, comp2, port2->index); + + err = comp1->core->setup_tunnel (comp1->handle, port1->index, comp2->handle, + port2->index); + + if (err == OMX_ErrorNone) { + port1->tunneled = TRUE; + port2->tunneled = TRUE; + } + + GST_DEBUG_OBJECT (comp1->parent, + "Setup tunnel between %p port %u and %p port %u: %s (0x%08x)", + comp1, port1->index, + comp2, port2->index, gst_omx_error_to_string (err), err); + + g_mutex_unlock (&comp2->lock); + g_mutex_unlock (&comp1->lock); + + return err; +} + +OMX_ERRORTYPE +gst_omx_component_close_tunnel (GstOMXComponent * comp1, GstOMXPort * port1, + GstOMXComponent * comp2, GstOMXPort * port2) +{ + OMX_ERRORTYPE err; + + g_return_val_if_fail (comp1 != NULL, OMX_ErrorUndefined); + g_return_val_if_fail (comp1->state == OMX_StateLoaded + || !port1->port_def.bEnabled, OMX_ErrorUndefined); + g_return_val_if_fail (port1 != NULL, OMX_ErrorUndefined); + g_return_val_if_fail (port1->port_def.eDir == OMX_DirOutput, + OMX_ErrorUndefined); + g_return_val_if_fail (comp2 != NULL, OMX_ErrorUndefined); + g_return_val_if_fail (comp2->state == OMX_StateLoaded + || !port2->port_def.bEnabled, OMX_ErrorUndefined); + g_return_val_if_fail (port2 != NULL, OMX_ErrorUndefined); + g_return_val_if_fail (port2->port_def.eDir == OMX_DirInput, + OMX_ErrorUndefined); + g_return_val_if_fail (comp1->core == comp2->core, OMX_ErrorUndefined); + g_return_val_if_fail (port1->tunneled && port2->tunneled, OMX_ErrorUndefined); + + g_mutex_lock (&comp1->lock); + g_mutex_lock (&comp2->lock); + GST_DEBUG_OBJECT (comp1->parent, + "Closing tunnel between %p port %u and %p port %u", + comp1, port1->index, comp2, port2->index); + + err = comp1->core->setup_tunnel (comp1->handle, port1->index, 0, 0); + if (err != OMX_ErrorNone) { + GST_ERROR_OBJECT (comp1->parent, + "Failed to close tunnel on output side %s (0x%08x)", + gst_omx_error_to_string (err), err); + } + err = comp2->core->setup_tunnel (0, 0, comp2->handle, port2->index); + if (err != OMX_ErrorNone) { + GST_ERROR_OBJECT (comp2->parent, + "Failed to close tunnel on input side %s (0x%08x)", + gst_omx_error_to_string (err), err); + } + + port1->tunneled = FALSE; + port2->tunneled = FALSE; + + GST_DEBUG_OBJECT (comp1->parent, + "Closed tunnel between %p port %u and %p port %u", + comp1, port1->index, comp2, port2->index); + + g_mutex_unlock (&comp2->lock); + g_mutex_unlock (&comp1->lock); + + return err; +} + void gst_omx_port_get_port_definition (GstOMXPort * port, OMX_PARAM_PORTDEFINITIONTYPE * port_def) @@ -1083,6 +1198,7 @@ gst_omx_port_acquire_buffer (GstOMXPort * port, GstOMXBuffer ** buf) GstOMXBuffer *_buf = NULL; g_return_val_if_fail (port != NULL, GST_OMX_ACQUIRE_BUFFER_ERROR); + g_return_val_if_fail (!port->tunneled, GST_OMX_ACQUIRE_BUFFER_ERROR); g_return_val_if_fail (buf != NULL, GST_OMX_ACQUIRE_BUFFER_ERROR); *buf = NULL; @@ -1226,6 +1342,7 @@ gst_omx_port_release_buffer (GstOMXPort * port, GstOMXBuffer * buf) OMX_ERRORTYPE err = OMX_ErrorNone; g_return_val_if_fail (port != NULL, OMX_ErrorUndefined); + g_return_val_if_fail (!port->tunneled, GST_OMX_ACQUIRE_BUFFER_ERROR); g_return_val_if_fail (buf != NULL, OMX_ErrorUndefined); g_return_val_if_fail (buf->port == port, OMX_ErrorUndefined); @@ -1483,6 +1600,8 @@ gst_omx_port_allocate_buffers_unlocked (GstOMXPort * port) g_assert (!port->buffers || port->buffers->len == 0); + g_return_val_if_fail (!port->tunneled, OMX_ErrorBadParameter); + comp = port->comp; gst_omx_component_handle_messages (port->comp); @@ -1597,6 +1716,8 @@ gst_omx_port_deallocate_buffers_unlocked (GstOMXPort * port) OMX_ERRORTYPE err = OMX_ErrorNone; gint i, n; + g_return_val_if_fail (!port->tunneled, OMX_ErrorBadParameter); + comp = port->comp; GST_DEBUG_OBJECT (comp->parent, "Deallocating buffers of port %u", @@ -1928,7 +2049,7 @@ gst_omx_port_wait_enabled_unlocked (GstOMXPort * port, GstClockTime timeout) /* If everything went fine and we have an output port we * should provide all newly allocated buffers to the port */ - if (enabled && port->port_def.eDir == OMX_DirOutput) { + if (enabled && port->port_def.eDir == OMX_DirOutput && !port->tunneled) { GstOMXBuffer *buf; /* Enqueue all buffers for the component to fill */ @@ -2043,9 +2164,11 @@ gst_omx_port_reconfigure (GstOMXPort * port) if (err != OMX_ErrorNone) goto done; - err = gst_omx_port_deallocate_buffers_unlocked (port); - if (err != OMX_ErrorNone) - goto done; + if (!port->tunneled) { + err = gst_omx_port_deallocate_buffers_unlocked (port); + if (err != OMX_ErrorNone) + goto done; + } err = gst_omx_port_wait_enabled_unlocked (port, 5 * GST_SECOND); if (err != OMX_ErrorNone) @@ -2055,9 +2178,11 @@ gst_omx_port_reconfigure (GstOMXPort * port) if (err != OMX_ErrorNone) goto done; - err = gst_omx_port_allocate_buffers_unlocked (port); - if (err != OMX_ErrorNone) - goto done; + if (!port->tunneled) { + err = gst_omx_port_allocate_buffers_unlocked (port); + if (err != OMX_ErrorNone) + goto done; + } err = gst_omx_port_wait_enabled_unlocked (port, 5 * GST_SECOND); if (err != OMX_ErrorNone) diff --git a/omx/gstomx.h b/omx/gstomx.h index 3337455934..8f9c5b406b 100644 --- a/omx/gstomx.h +++ b/omx/gstomx.h @@ -141,6 +141,7 @@ struct _GstOMXCore { OMX_ERRORTYPE (*get_handle) (OMX_HANDLETYPE * handle, OMX_STRING name, OMX_PTR data, OMX_CALLBACKTYPE * callbacks); OMX_ERRORTYPE (*free_handle) (OMX_HANDLETYPE handle); + OMX_ERRORTYPE (*setup_tunnel) (OMX_HANDLETYPE output, OMX_U32 outport, OMX_HANDLETYPE input, OMX_U32 inport); }; typedef enum { @@ -185,6 +186,8 @@ struct _GstOMXPort { GstOMXComponent *comp; guint32 index; + gboolean tunneled; + OMX_PARAM_PORTDEFINITIONTYPE port_def; GPtrArray *buffers; /* Contains GstOMXBuffer* */ GQueue pending_buffers; /* Contains GstOMXBuffer* */ @@ -288,6 +291,8 @@ OMX_ERRORTYPE gst_omx_component_set_parameter (GstOMXComponent * comp, OMX_I OMX_ERRORTYPE gst_omx_component_get_config (GstOMXComponent * comp, OMX_INDEXTYPE index, gpointer config); OMX_ERRORTYPE gst_omx_component_set_config (GstOMXComponent * comp, OMX_INDEXTYPE index, gpointer config); +OMX_ERRORTYPE gst_omx_component_setup_tunnel (GstOMXComponent * comp1, GstOMXPort * port1, GstOMXComponent * comp2, GstOMXPort * port2); +OMX_ERRORTYPE gst_omx_component_close_tunnel (GstOMXComponent * comp1, GstOMXPort * port1, GstOMXComponent * comp2, GstOMXPort * port2); void gst_omx_port_get_port_definition (GstOMXPort * port, OMX_PARAM_PORTDEFINITIONTYPE * port_def);