diff options
author | Guillaume Desmottes <guillaume.desmottes@collabora.co.uk> | 2017-07-27 11:21:59 +0200 |
---|---|---|
committer | Nicolas Dufresne <nicolas.dufresne@collabora.com> | 2018-01-29 15:21:02 +0000 |
commit | 9f87b987ef15cf04f573a759a5efe73ac3b8ce2d (patch) | |
tree | b3a320a0d4b3c1665a0f35b02a7c4b8c5d3f5b8a | |
parent | 0c5bbbb6ca5ff9c262e8a45f0b7f6be9ed4e4213 (diff) | |
download | gst-omx-9f87b987ef15cf04f573a759a5efe73ac3b8ce2d.tar.gz |
omxvideoenc: implement dmabuf import on zynqultrascaleplus
The Zynq UltraScale+ encoder implements a custom OMX extension to
directly import dmabuf saving the need of mapping input buffers.
This can be use with either 'v4l2src io-mode=dmabuf' or an OMX video
decoder upstream.
https://bugzilla.gnome.org/show_bug.cgi?id=792361
-rw-r--r-- | omx/gstomx.c | 37 | ||||
-rw-r--r-- | omx/gstomx.h | 2 | ||||
-rw-r--r-- | omx/gstomxvideoenc.c | 72 | ||||
-rw-r--r-- | omx/gstomxvideoenc.h | 2 |
4 files changed, 98 insertions, 15 deletions
diff --git a/omx/gstomx.c b/omx/gstomx.c index 8754599..01718de 100644 --- a/omx/gstomx.c +++ b/omx/gstomx.c @@ -25,6 +25,7 @@ #endif #include <gst/gst.h> +#include <gst/allocators/gstdmabuf.h> #include <string.h> #include "gstomx.h" @@ -617,14 +618,18 @@ gst_omx_buffer_unmap (GstOMXBuffer * buffer) if (buffer->input_frame_mapped) { g_assert (!buffer->input_mem); g_assert (!buffer->input_buffer); + g_assert (!buffer->input_buffer_mapped); gst_video_frame_unmap (&buffer->input_frame); buffer->input_frame_mapped = FALSE; } else if (buffer->input_mem) { g_assert (!buffer->input_buffer); + g_assert (!buffer->input_buffer_mapped); gst_memory_unmap (buffer->input_mem, &buffer->map); g_clear_pointer (&buffer->input_mem, gst_memory_unref); } else if (buffer->input_buffer) { - gst_buffer_unmap (buffer->input_buffer, &buffer->map); + if (buffer->input_buffer_mapped) + gst_buffer_unmap (buffer->input_buffer, &buffer->map); + buffer->input_buffer_mapped = FALSE; g_clear_pointer (&buffer->input_buffer, gst_buffer_unref); } } @@ -1863,6 +1868,7 @@ gst_omx_buffer_map_frame (GstOMXBuffer * buffer, GstBuffer * input, g_return_val_if_fail (!buffer->input_frame_mapped, FALSE); g_return_val_if_fail (!buffer->input_mem, FALSE); g_return_val_if_fail (!buffer->input_buffer, FALSE); + g_return_val_if_fail (!buffer->input_buffer_mapped, FALSE); if (!gst_video_frame_map (&buffer->input_frame, info, input, GST_MAP_READ)) return FALSE; @@ -1884,6 +1890,7 @@ gst_omx_buffer_map_memory (GstOMXBuffer * buffer, GstMemory * mem) g_return_val_if_fail (!buffer->input_frame_mapped, FALSE); g_return_val_if_fail (!buffer->input_mem, FALSE); g_return_val_if_fail (!buffer->input_buffer, FALSE); + g_return_val_if_fail (!buffer->input_buffer_mapped, FALSE); if (!gst_memory_map (mem, &buffer->map, GST_MAP_READ)) return FALSE; @@ -1897,6 +1904,32 @@ gst_omx_buffer_map_memory (GstOMXBuffer * buffer, GstMemory * mem) } gboolean +gst_omx_buffer_import_fd (GstOMXBuffer * buffer, GstBuffer * input) +{ + gint fd; + GstMemory *mem; + + g_return_val_if_fail (buffer != NULL, FALSE); + g_return_val_if_fail (input != NULL, FALSE); + g_return_val_if_fail (!buffer->input_frame_mapped, FALSE); + g_return_val_if_fail (!buffer->input_mem, FALSE); + g_return_val_if_fail (!buffer->input_buffer, FALSE); + g_return_val_if_fail (!buffer->input_buffer_mapped, FALSE); + + mem = gst_buffer_peek_memory (input, 0); + g_return_val_if_fail (gst_is_dmabuf_memory (mem), FALSE); + + fd = gst_dmabuf_memory_get_fd (mem); + + buffer->input_buffer = gst_buffer_ref (input); + buffer->omx_buf->pBuffer = GUINT_TO_POINTER (fd); + buffer->omx_buf->nAllocLen = gst_memory_get_sizes (mem, NULL, NULL); + buffer->omx_buf->nFilledLen = buffer->omx_buf->nAllocLen; + + return TRUE; +} + +gboolean gst_omx_buffer_map_buffer (GstOMXBuffer * buffer, GstBuffer * input) { g_return_val_if_fail (buffer != NULL, FALSE); @@ -1904,10 +1937,12 @@ gst_omx_buffer_map_buffer (GstOMXBuffer * buffer, GstBuffer * input) g_return_val_if_fail (!buffer->input_frame_mapped, FALSE); g_return_val_if_fail (!buffer->input_mem, FALSE); g_return_val_if_fail (!buffer->input_buffer, FALSE); + g_return_val_if_fail (!buffer->input_buffer_mapped, FALSE); if (!gst_buffer_map (input, &buffer->map, GST_MAP_READ)) return FALSE; + buffer->input_buffer_mapped = TRUE; buffer->input_buffer = gst_buffer_ref (input); buffer->omx_buf->pBuffer = buffer->map.data; buffer->omx_buf->nAllocLen = buffer->map.size; diff --git a/omx/gstomx.h b/omx/gstomx.h index e197c96..bf53444 100644 --- a/omx/gstomx.h +++ b/omx/gstomx.h @@ -339,6 +339,7 @@ struct _GstOMXBuffer { gboolean input_frame_mapped; /* TRUE if input_frame is valid */ GstMemory *input_mem; GstBuffer *input_buffer; + gboolean input_buffer_mapped; GstMapInfo map; }; @@ -420,6 +421,7 @@ OMX_ERRORTYPE gst_omx_port_use_dynamic_buffers (GstOMXPort * port); gboolean gst_omx_buffer_map_frame (GstOMXBuffer * buffer, GstBuffer * input, GstVideoInfo * info); gboolean gst_omx_buffer_map_memory (GstOMXBuffer * buffer, GstMemory * mem); gboolean gst_omx_buffer_map_buffer (GstOMXBuffer * buffer, GstBuffer * input); +gboolean gst_omx_buffer_import_fd (GstOMXBuffer * buffer, GstBuffer * input); void gst_omx_set_default_role (GstOMXClassData *class_data, const gchar *default_role); diff --git a/omx/gstomxvideoenc.c b/omx/gstomxvideoenc.c index 7a55feb..5f8046d 100644 --- a/omx/gstomxvideoenc.c +++ b/omx/gstomxvideoenc.c @@ -24,6 +24,8 @@ #include <gst/gst.h> #include <gst/video/gstvideometa.h> +#include <gst/allocators/gstdmabuf.h> + #include <string.h> #include "gstomxvideo.h" @@ -1222,6 +1224,36 @@ gst_omx_video_enc_enable (GstOMXVideoEnc * self, GstBuffer * input) self->input_allocation = gst_omx_video_enc_pick_input_allocation_mode (self, input); + self->input_dmabuf = FALSE; + +#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS + if (gst_is_dmabuf_memory (gst_buffer_peek_memory (input, 0))) { + if (self->input_allocation == GST_OMX_BUFFER_ALLOCATION_USE_BUFFER_DYNAMIC) { + OMX_ALG_PORT_PARAM_BUFFER_MODE buffer_mode; + OMX_ERRORTYPE err; + + GST_OMX_INIT_STRUCT (&buffer_mode); + buffer_mode.nPortIndex = self->enc_in_port->index; + buffer_mode.eMode = OMX_ALG_BUF_DMA; + + GST_DEBUG_OBJECT (self, "Configure encoder to import dmabuf"); + + err = + gst_omx_component_set_parameter (self->enc, + (OMX_INDEXTYPE) OMX_ALG_IndexPortParamBufferMode, &buffer_mode); + if (err != OMX_ErrorNone) + GST_WARNING_OBJECT (self, + "Failed to set output buffer mode: %s (0x%08x)", + gst_omx_error_to_string (err), err); + } else { + GST_DEBUG_OBJECT (self, + "Wrong input allocation mode (%d); dynamic buffers are required to use dmabuf import", + self->input_allocation); + } + + self->input_dmabuf = TRUE; + } +#endif GST_DEBUG_OBJECT (self, "Enabling component"); if (self->disabled) { @@ -1529,22 +1561,34 @@ gst_omx_video_enc_fill_buffer (GstOMXVideoEnc * self, GstBuffer * inbuf, return FALSE; } - /* Map and keep a ref on the buffer while it's being processed - * by the OMX component. */ - if (!gst_omx_buffer_map_frame (outbuf, inbuf, info)) { - GST_ELEMENT_ERROR (self, STREAM, FORMAT, (NULL), - ("failed to map input buffer")); - return FALSE; - } + if (!self->input_dmabuf) { + /* Map and keep a ref on the buffer while it's being processed + * by the OMX component. */ + if (!gst_omx_buffer_map_frame (outbuf, inbuf, info)) { + GST_ELEMENT_ERROR (self, STREAM, FORMAT, (NULL), + ("failed to map input buffer")); + return FALSE; + } - if (!check_input_alignment (self, &outbuf->input_frame.map[0])) { - GST_ELEMENT_ERROR (self, STREAM, FORMAT, (NULL), - ("input buffer now has wrong alignment/stride, can't use dynamic allocation any more")); - return FALSE; - } + if (!check_input_alignment (self, &outbuf->input_frame.map[0])) { + GST_ELEMENT_ERROR (self, STREAM, FORMAT, (NULL), + ("input buffer now has wrong alignment/stride, can't use dynamic allocation any more")); + return FALSE; + } - GST_LOG_OBJECT (self, "Transfer buffer of %" G_GSIZE_FORMAT " bytes", - gst_buffer_get_size (inbuf)); + GST_LOG_OBJECT (self, "Transfer buffer of %" G_GSIZE_FORMAT " bytes", + gst_buffer_get_size (inbuf)); + } else { + /* dmabuf input */ + if (!gst_omx_buffer_import_fd (outbuf, inbuf)) { + GST_ELEMENT_ERROR (self, STREAM, FORMAT, (NULL), + ("failed to import dmabuf")); + return FALSE; + } + + GST_LOG_OBJECT (self, "Import dmabuf of %" G_GSIZE_FORMAT " bytes", + gst_buffer_get_size (inbuf)); + } ret = TRUE; goto done; diff --git a/omx/gstomxvideoenc.h b/omx/gstomxvideoenc.h index 345b9d1..705441e 100644 --- a/omx/gstomxvideoenc.h +++ b/omx/gstomxvideoenc.h @@ -79,6 +79,8 @@ struct _GstOMXVideoEnc GstFlowReturn downstream_flow_ret; GstOMXBufferAllocation input_allocation; + /* TRUE if encoder is passing dmabuf's fd directly to the OMX component */ + gboolean input_dmabuf; }; struct _GstOMXVideoEncClass |