From 355784d9bc382e173e99f4c35f90af5830b44e7a Mon Sep 17 00:00:00 2001 From: Jeegar Patel Date: Fri, 27 Jan 2017 19:13:52 +0530 Subject: [PATCH 18/24] Fix transcode usecase with dma mode Add logic for mapping decoder's fd to encoder's input fd in playing state as decoder does not provide fd's in circular fashion. Signed-off-by: Jeegar Patel Upstream Status: Pending --- omx/gstomx.c | 172 +++++++++++++++++++++++++++++++++++++++++++++++++-- omx/gstomx.h | 8 +++ omx/gstomxvideodec.c | 6 +- omx/gstomxvideoenc.c | 46 +++++++------- 4 files changed, 204 insertions(+), 28 deletions(-) diff --git a/omx/gstomx.c b/omx/gstomx.c index 9b7f1eb..11eabca 100644 --- a/omx/gstomx.c +++ b/omx/gstomx.c @@ -1218,6 +1218,174 @@ gst_omx_port_update_port_definition (GstOMXPort * port, return err; } +void +find_fd (GstOMXBuffer * buf, GstOMXFdFound * fd_helper) +{ + if (fd_helper->fd == buf->omx_buf->pBuffer) { + fd_helper->index = g_queue_index (fd_helper->pending_buffers, buf); + printf ("fd found index is %d\n", fd_helper->index); + } + return; +} + +/* NOTE: Uses comp->lock and comp->messages_lock */ +GstOMXAcquireBufferReturn +gst_omx_port_acquire_buffer_dma (GstOMXPort * port, GstOMXBuffer ** buf, + gint fd) +{ + GstOMXAcquireBufferReturn ret = GST_OMX_ACQUIRE_BUFFER_ERROR; + GstOMXComponent *comp; + OMX_ERRORTYPE err; + GstOMXBuffer *_buf = NULL; + GstOMXFdFound fd_helper; + + 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; + + comp = port->comp; + + g_mutex_lock (&comp->lock); + GST_DEBUG_OBJECT (comp->parent, "Acquiring %s buffer from port %u", + comp->name, port->index); + +retry: + gst_omx_component_handle_messages (comp); + + /* Check if the component is in an error state */ + if ((err = comp->last_error) != OMX_ErrorNone) { + GST_ERROR_OBJECT (comp->parent, "Component %s is in error state: %s", + comp->name, gst_omx_error_to_string (err)); + ret = GST_OMX_ACQUIRE_BUFFER_ERROR; + goto done; + } + + /* Check if the port is flushing */ + if (port->flushing) { + ret = GST_OMX_ACQUIRE_BUFFER_FLUSHING; + goto done; + } + + /* If this is an input port and at least one of the output ports + * needs to be reconfigured, we wait until all output ports are + * reconfigured. Afterwards this port is reconfigured if required + * or buffers are returned to be filled as usual. + */ + if (port->port_def.eDir == OMX_DirInput) { + if (comp->pending_reconfigure_outports) { + gst_omx_component_handle_messages (comp); + while (comp->pending_reconfigure_outports && + (err = comp->last_error) == OMX_ErrorNone && !port->flushing) { + GST_DEBUG_OBJECT (comp->parent, + "Waiting for %s output ports to reconfigure", comp->name); + gst_omx_component_wait_message (comp, GST_CLOCK_TIME_NONE); + gst_omx_component_handle_messages (comp); + } + goto retry; + } + + /* Only if this port needs to be reconfigured too notify + * the caller about it */ + if (port->settings_cookie != port->configured_settings_cookie) { + ret = GST_OMX_ACQUIRE_BUFFER_RECONFIGURE; + goto done; + } + } + + /* If we have an output port that needs to be reconfigured + * and it still has buffers pending for the old configuration + * we first return them. + * NOTE: If buffers for this configuration arrive later + * we have to drop them... */ + if (port->port_def.eDir == OMX_DirOutput && + port->settings_cookie != port->configured_settings_cookie) { + if (!g_queue_is_empty (&port->pending_buffers)) { + GST_DEBUG_OBJECT (comp->parent, + "%s output port %u needs reconfiguration but has buffers pending", + comp->name, port->index); + _buf = g_queue_pop_head (&port->pending_buffers); + + ret = GST_OMX_ACQUIRE_BUFFER_OK; + goto done; + } + + ret = GST_OMX_ACQUIRE_BUFFER_RECONFIGURE; + goto done; + } + + if (port->port_def.eDir == OMX_DirOutput && port->eos) { + if (!g_queue_is_empty (&port->pending_buffers)) { + GST_DEBUG_OBJECT (comp->parent, "%s output port %u is EOS but has " + "buffers pending", comp->name, port->index); + _buf = g_queue_pop_head (&port->pending_buffers); + + ret = GST_OMX_ACQUIRE_BUFFER_OK; + goto done; + } + + ret = GST_OMX_ACQUIRE_BUFFER_EOS; + goto done; + } + + /* + * At this point we have no error or flushing/eos port + * and a properly configured port. + * + */ + + /* If the queue is empty we wait until a buffer + * arrives, an error happens, the port is flushing + * or the port needs to be reconfigured. + */ + gst_omx_component_handle_messages (comp); + if (g_queue_is_empty (&port->pending_buffers)) { + GST_DEBUG_OBJECT (comp->parent, "Queue of %s port %u is empty", + comp->name, port->index); + gst_omx_component_wait_message (comp, GST_CLOCK_TIME_NONE); + gst_omx_component_handle_messages (comp); + + /* And now check everything again and maybe get a buffer */ + goto retry; + } else { + GST_DEBUG_OBJECT (comp->parent, "%s port %u has pending buffers", + comp->name, port->index); + fd_helper.fd = fd; + fd_helper.pending_buffers = &port->pending_buffers; + fd_helper.index = -1; + g_queue_foreach (&port->pending_buffers, find_fd, &fd_helper); + if (fd_helper.index != -1) + _buf = g_queue_pop_nth (&port->pending_buffers, fd_helper.index); + else { + _buf = g_queue_pop_head (&port->pending_buffers); + printf ("Fd is %d and its not found in queue, Retry...\n", fd); + goto retry; + } + + ret = GST_OMX_ACQUIRE_BUFFER_OK; + goto done; + } + + g_assert_not_reached (); + goto retry; + +done: + g_mutex_unlock (&comp->lock); + + if (_buf) { + g_assert (_buf == _buf->omx_buf->pAppPrivate); + *buf = _buf; + } + + GST_DEBUG_OBJECT (comp->parent, "Acquired buffer %p (%p) from %s port %u: %d", + _buf, (_buf ? _buf->omx_buf->pBuffer : NULL), comp->name, port->index, + ret); + + return ret; +} + + /* NOTE: Uses comp->lock and comp->messages_lock */ GstOMXAcquireBufferReturn gst_omx_port_acquire_buffer (GstOMXPort * port, GstOMXBuffer ** buf) @@ -1637,8 +1805,6 @@ gst_omx_port_allocate_buffers_unlocked (GstOMXPort * port, err = OMX_UseBuffer (comp->handle, &buf->omx_buf, port->index, buf, port->port_def.nBufferSize, l->data); - if (port->index == 0) - printf ("Encoder i/p OMX_Usebuffer %d\n", buf->omx_buf->pBuffer); buf->eglimage = FALSE; } else if (images) { err = @@ -1649,8 +1815,6 @@ gst_omx_port_allocate_buffers_unlocked (GstOMXPort * port, err = OMX_AllocateBuffer (comp->handle, &buf->omx_buf, port->index, buf, port->port_def.nBufferSize); - if (port->index == 1) - printf ("Decoder o/p OMX_AllocateBuffer %d\n", buf->omx_buf->pBuffer); buf->eglimage = FALSE; } diff --git a/omx/gstomx.h b/omx/gstomx.h index 0342e14..c40fae2 100644 --- a/omx/gstomx.h +++ b/omx/gstomx.h @@ -123,6 +123,7 @@ typedef struct _GstOMXComponent GstOMXComponent; typedef struct _GstOMXBuffer GstOMXBuffer; typedef struct _GstOMXClassData GstOMXClassData; typedef struct _GstOMXMessage GstOMXMessage; +typedef struct _GstOMXFdFound GstOMXFdFound; typedef enum { /* Everything good and the buffer is valid */ @@ -291,6 +292,13 @@ struct _GstOMXClassData { GstOmxComponentType type; }; +struct _GstOMXFdFound { + gint fd; + GQueue *pending_buffers; + gint index; +}; + + GKeyFile * gst_omx_get_configuration (void); const gchar * gst_omx_error_to_string (OMX_ERRORTYPE err); diff --git a/omx/gstomxvideodec.c b/omx/gstomxvideodec.c index 7383ab6..809f426 100644 --- a/omx/gstomxvideodec.c +++ b/omx/gstomxvideodec.c @@ -1198,9 +1198,9 @@ enable_port: dmaList); GstPad *newpad = gst_element_get_static_pad (GST_ELEMENT (self), "src"); if (newpad == NULL) - printf ("src pad did not found\n"); - - gst_pad_push_event (newpad, dmaListEvent); + printf ("Decoder: src pad did not found\n"); + else + gst_pad_push_event (newpad, dmaListEvent); err = gst_omx_port_populate (port); diff --git a/omx/gstomxvideoenc.c b/omx/gstomxvideoenc.c index c7fb0db..4097a00 100644 --- a/omx/gstomxvideoenc.c +++ b/omx/gstomxvideoenc.c @@ -1396,17 +1396,11 @@ gst_omx_video_enc_fill_buffer (GstOMXVideoEnc * self, GstBuffer * inbuf, } if (self->input_mode == OMX_Enc_InputMode_DMABufImport) { - //outbuf->omx_buf->pBuffer = - // gst_dmabuf_memory_get_fd (gst_buffer_peek_memory (inbuf, 0)); - //printf ("Stride matches & Passed fd to OMX is %d\n", - // outbuf->omx_buf->pBuffer); - printf ("Stride matches,Decoder o/p FD is %d, Encoder o/p FD is %d\n", + printf ("Stride matches,Decoder o/p FD is %d, Encoder I/P FD is %d\n", gst_dmabuf_memory_get_fd (gst_buffer_peek_memory (inbuf, 0)), outbuf->omx_buf->pBuffer); } - /* Instead of copying GstOMXBuffer to GstBuffer, - Updating data pointer of GstOMXBuffer with GstBuffer data pointer */ if (self->input_mode == OMX_Enc_InputMode_ZeroCopy) { GstMapInfo map = GST_MAP_INFO_INIT; @@ -1423,9 +1417,9 @@ gst_omx_video_enc_fill_buffer (GstOMXVideoEnc * self, GstBuffer * inbuf, /* Different strides */ if (self->input_mode == OMX_Enc_InputMode_DMABufImport) { - outbuf->omx_buf->pBuffer = - gst_dmabuf_memory_get_fd (gst_buffer_peek_memory (inbuf, 0)); - printf ("Stride does not matched,Passed fd to OMX is %d\n", + printf + ("Stride does not matches,Decoder o/p FD is %d, Encoder I/P FD is %d\n", + gst_dmabuf_memory_get_fd (gst_buffer_peek_memory (inbuf, 0)), outbuf->omx_buf->pBuffer); ret = TRUE; goto done; @@ -1650,7 +1644,6 @@ gst_omx_video_enc_handle_frame (GstVideoEncoder * encoder, printf ("Updated OMX Encoder BuffercountActual is %d\n", self->enc_in_port->port_def.nBufferCountActual); - } else { printf ("Bufferpool found by fd tracing, It has %d buffers \n", @@ -1703,7 +1696,13 @@ gst_omx_video_enc_handle_frame (GstVideoEncoder * encoder, * _loop() can't call _finish_frame() and we might block forever * because no input buffers are released */ GST_VIDEO_ENCODER_STREAM_UNLOCK (self); - acq_ret = gst_omx_port_acquire_buffer (port, &buf); + if (self->input_mode == OMX_Enc_InputMode_DMABufImport) { + acq_ret = gst_omx_port_acquire_buffer_dma (port, &buf, + gst_dmabuf_memory_get_fd (gst_buffer_peek_memory (frame->input_buffer, + 0))); + } else { + acq_ret = gst_omx_port_acquire_buffer (port, &buf); + } if (acq_ret == GST_OMX_ACQUIRE_BUFFER_ERROR) { GST_VIDEO_ENCODER_STREAM_LOCK (self); @@ -1972,7 +1971,7 @@ gst_omx_video_enc_drain (GstOMXVideoEnc * self, gboolean at_eos) } static void -test_data (GstOMXBuffer * buf) +fill_dma_data (GstOMXBuffer * buf) { buffer_list = g_list_append (buffer_list, buf->omx_buf->pBuffer); g_dmalist_count++; @@ -1993,16 +1992,21 @@ gst_omx_video_enc_sink_event (GstVideoEncoder * encoder, GstEvent * event) switch (GST_EVENT_TYPE (event)) { case GST_EVENT_CUSTOM_DOWNSTREAM:{ - const GstStructure *structure = gst_event_get_structure (event); - if (gst_structure_has_name (structure, "dmaStruct")) { - p = gst_structure_get_value (structure, "dmaPtrArray"); - buffers = g_value_get_pointer (p); - g_ptr_array_foreach (buffers, test_data, NULL); - bufpool_complete = 1; - printf ("Custom event for DMA list is sucessful, got %d fd \n", - g_dmalist_count); + if (self->input_mode == OMX_Enc_InputMode_DMABufImport) { + + const GstStructure *structure = gst_event_get_structure (event); + + if (gst_structure_has_name (structure, "dmaStruct")) { + p = gst_structure_get_value (structure, "dmaPtrArray"); + buffers = g_value_get_pointer (p); + g_ptr_array_foreach (buffers, fill_dma_data, NULL); + bufpool_complete = 1; + printf ("Custom event for DMA list is sucessful, got %d fd \n", + g_dmalist_count); + } } + return sink_event_backup (encoder, event); break; } -- 2.7.4