mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-10 17:35:59 +00:00
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
This commit is contained in:
parent
0c5bbbb6ca
commit
9f87b987ef
4 changed files with 98 additions and 15 deletions
35
omx/gstomx.c
35
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) {
|
||||
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;
|
||||
|
@ -1896,6 +1903,32 @@ gst_omx_buffer_map_memory (GstOMXBuffer * buffer, GstMemory * mem)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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,6 +1561,7 @@ gst_omx_video_enc_fill_buffer (GstOMXVideoEnc * self, GstBuffer * inbuf,
|
|||
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)) {
|
||||
|
@ -1545,6 +1578,17 @@ gst_omx_video_enc_fill_buffer (GstOMXVideoEnc * self, GstBuffer * 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;
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue