summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGuillaume Desmottes <guillaume.desmottes@collabora.co.uk>2017-07-27 11:21:59 +0200
committerNicolas Dufresne <nicolas.dufresne@collabora.com>2018-01-29 15:21:02 +0000
commit9f87b987ef15cf04f573a759a5efe73ac3b8ce2d (patch)
treeb3a320a0d4b3c1665a0f35b02a7c4b8c5d3f5b8a
parent0c5bbbb6ca5ff9c262e8a45f0b7f6be9ed4e4213 (diff)
downloadgst-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.c37
-rw-r--r--omx/gstomx.h2
-rw-r--r--omx/gstomxvideoenc.c72
-rw-r--r--omx/gstomxvideoenc.h2
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