mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-23 00:36:51 +00:00
omxvideodec: add dmabuf support for output
The zynqultrascaleplus OMX implementation has a custom extension allowing decoders to output dmabuf and so avoid buffers copy between OMX and GStreamer. Make use of this extension when built on the zynqultrascaleplus. The buffer pool code should be re-usable for other platforms as well. https://bugzilla.gnome.org/show_bug.cgi?id=784847
This commit is contained in:
parent
a9a3087021
commit
136714c6ed
8 changed files with 111 additions and 11 deletions
|
@ -155,6 +155,7 @@ PKG_CHECK_MODULES([GST_GL], [gstreamer-gl-1.0 >= $GST_REQ], [
|
|||
GST_GL=yes
|
||||
], [GST_GL=no])
|
||||
AM_CONDITIONAL(HAVE_GST_GL, test "x$GST_GL" = "xyes")
|
||||
PKG_CHECK_MODULES([GST_ALLOCATORS], [gstreamer-allocators-1.0])
|
||||
|
||||
dnl Check for documentation xrefs
|
||||
GLIB_PREFIX="`$PKG_CONFIG --variable=prefix glib-2.0`"
|
||||
|
|
|
@ -136,6 +136,8 @@ gstbase_dep = dependency('gstreamer-base-1.0', version : gst_req,
|
|||
fallback : ['gstreamer', 'gst_base_dep'])
|
||||
gstcontroller_dep = dependency('gstreamer-controller-1.0', version : gst_req,
|
||||
fallback : ['gstreamer', 'gst_controller_dep'])
|
||||
gstallocators_dep = dependency('gstreamer-allocators-1.0', version : gst_req,
|
||||
fallback : ['gst-plugins-base', 'allocators_dep'])
|
||||
|
||||
gstpbutils_dep = dependency('gstreamer-pbutils-1.0', version : gst_req,
|
||||
fallback : ['gst-plugins-base', 'pbutils_dep'])
|
||||
|
|
|
@ -79,6 +79,7 @@ libgstomx_la_CFLAGS = \
|
|||
$(GST_PLUGINS_BASE_CFLAGS) \
|
||||
$(GST_BASE_CFLAGS) \
|
||||
$(GST_CFLAGS) \
|
||||
$(GST_ALLOCATORS_CFLAGS) \
|
||||
$(GMODULE_NO_EXPORT_CFLAGS)
|
||||
libgstomx_la_LIBADD = \
|
||||
$(GST_GL_LIBS) \
|
||||
|
@ -88,6 +89,7 @@ libgstomx_la_LIBADD = \
|
|||
-lgstvideo-@GST_API_VERSION@ \
|
||||
$(GST_BASE_LIBS) \
|
||||
$(GST_LIBS) \
|
||||
$(GST_ALLOCATORS_LIBS) \
|
||||
$(GMODULE_NO_EXPORT_LIBS)
|
||||
libgstomx_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
|
||||
|
||||
|
|
|
@ -26,6 +26,8 @@
|
|||
|
||||
#include "gstomxbufferpool.h"
|
||||
|
||||
#include <gst/allocators/gstdmabuf.h>
|
||||
|
||||
GST_DEBUG_CATEGORY_STATIC (gst_omx_buffer_pool_debug_category);
|
||||
#define GST_CAT_DEFAULT gst_omx_buffer_pool_debug_category
|
||||
|
||||
|
@ -389,7 +391,32 @@ gst_omx_buffer_pool_alloc_buffer (GstBufferPool * bpool,
|
|||
gsize offset[GST_VIDEO_MAX_PLANES] = { 0, };
|
||||
gint stride[GST_VIDEO_MAX_PLANES] = { nstride, 0, };
|
||||
|
||||
mem = gst_omx_memory_allocator_alloc (pool->allocator, 0, omx_buf);
|
||||
if (pool->output_mode == GST_OMX_BUFFER_MODE_DMABUF) {
|
||||
gint fd;
|
||||
GstMapInfo map;
|
||||
|
||||
fd = GPOINTER_TO_INT (omx_buf->omx_buf->pBuffer);
|
||||
|
||||
mem =
|
||||
gst_dmabuf_allocator_alloc (pool->allocator, fd,
|
||||
omx_buf->omx_buf->nAllocLen);
|
||||
|
||||
if (!gst_caps_features_contains (gst_caps_get_features (pool->caps, 0),
|
||||
GST_CAPS_FEATURE_MEMORY_DMABUF)) {
|
||||
/* Check if the memory is actually mappable */
|
||||
if (!gst_memory_map (mem, &map, GST_MAP_READWRITE)) {
|
||||
GST_ERROR_OBJECT (pool,
|
||||
"dmabuf memory is not mappable but caps does not have the 'memory:DMABuf' feature");
|
||||
gst_memory_unref (mem);
|
||||
return GST_FLOW_ERROR;
|
||||
}
|
||||
|
||||
gst_memory_unmap (mem, &map);
|
||||
}
|
||||
} else {
|
||||
mem = gst_omx_memory_allocator_alloc (pool->allocator, 0, omx_buf);
|
||||
}
|
||||
|
||||
buf = gst_buffer_new ();
|
||||
gst_buffer_append_memory (buf, mem);
|
||||
g_ptr_array_add (pool->buffers, buf);
|
||||
|
@ -505,11 +532,22 @@ gst_omx_buffer_pool_acquire_buffer (GstBufferPool * bpool,
|
|||
/* If it's our own memory we have to set the sizes */
|
||||
if (!pool->other_pool) {
|
||||
GstMemory *mem = gst_buffer_peek_memory (*buffer, 0);
|
||||
GstOMXBuffer *omx_buf;
|
||||
|
||||
g_assert (mem
|
||||
&& g_strcmp0 (mem->allocator->mem_type, GST_OMX_MEMORY_TYPE) == 0);
|
||||
mem->size = ((GstOMXMemory *) mem)->buf->omx_buf->nFilledLen;
|
||||
mem->offset = ((GstOMXMemory *) mem)->buf->omx_buf->nOffset;
|
||||
if (pool->output_mode == GST_OMX_BUFFER_MODE_DMABUF) {
|
||||
omx_buf =
|
||||
gst_mini_object_get_qdata (GST_MINI_OBJECT_CAST (buf),
|
||||
gst_omx_buffer_data_quark);
|
||||
} else {
|
||||
g_assert (mem
|
||||
&& g_strcmp0 (mem->allocator->mem_type, GST_OMX_MEMORY_TYPE) == 0);
|
||||
/* We already have a pointer to the GstOMXBuffer, no need to retrieve it
|
||||
* from the qdata */
|
||||
omx_buf = ((GstOMXMemory *) mem)->buf;
|
||||
}
|
||||
|
||||
mem->size = omx_buf->omx_buf->nFilledLen;
|
||||
mem->offset = omx_buf->omx_buf->nOffset;
|
||||
}
|
||||
} else {
|
||||
/* Acquire any buffer that is available to be filled by upstream */
|
||||
|
@ -615,12 +653,11 @@ static void
|
|||
gst_omx_buffer_pool_init (GstOMXBufferPool * pool)
|
||||
{
|
||||
pool->buffers = g_ptr_array_new ();
|
||||
pool->allocator = g_object_new (gst_omx_memory_allocator_get_type (), NULL);
|
||||
}
|
||||
|
||||
GstBufferPool *
|
||||
gst_omx_buffer_pool_new (GstElement * element, GstOMXComponent * component,
|
||||
GstOMXPort * port)
|
||||
GstOMXPort * port, GstOMXBufferMode output_mode)
|
||||
{
|
||||
GstOMXBufferPool *pool;
|
||||
|
||||
|
@ -628,6 +665,19 @@ gst_omx_buffer_pool_new (GstElement * element, GstOMXComponent * component,
|
|||
pool->element = gst_object_ref (element);
|
||||
pool->component = component;
|
||||
pool->port = port;
|
||||
pool->output_mode = output_mode;
|
||||
|
||||
switch (output_mode) {
|
||||
case GST_OMX_BUFFER_MODE_DMABUF:
|
||||
pool->allocator = gst_dmabuf_allocator_new ();
|
||||
break;
|
||||
case GST_OMX_BUFFER_MODE_SYSTEM_MEMORY:
|
||||
pool->allocator =
|
||||
g_object_new (gst_omx_memory_allocator_get_type (), NULL);
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
||||
return GST_BUFFER_POOL (pool);
|
||||
}
|
||||
|
|
|
@ -43,6 +43,11 @@ G_BEGIN_DECLS
|
|||
typedef struct _GstOMXBufferPool GstOMXBufferPool;
|
||||
typedef struct _GstOMXBufferPoolClass GstOMXBufferPoolClass;
|
||||
|
||||
typedef enum {
|
||||
GST_OMX_BUFFER_MODE_SYSTEM_MEMORY,
|
||||
GST_OMX_BUFFER_MODE_DMABUF,
|
||||
} GstOMXBufferMode;
|
||||
|
||||
struct _GstOMXBufferPool
|
||||
{
|
||||
GstVideoBufferPool parent;
|
||||
|
@ -78,6 +83,9 @@ struct _GstOMXBufferPool
|
|||
* wrapped
|
||||
*/
|
||||
gint current_buffer_index;
|
||||
|
||||
/* The type of buffers produced by the decoder */
|
||||
GstOMXBufferMode output_mode;
|
||||
};
|
||||
|
||||
struct _GstOMXBufferPoolClass
|
||||
|
@ -87,7 +95,7 @@ struct _GstOMXBufferPoolClass
|
|||
|
||||
GType gst_omx_buffer_pool_get_type (void);
|
||||
|
||||
GstBufferPool *gst_omx_buffer_pool_new (GstElement * element, GstOMXComponent * component, GstOMXPort * port);
|
||||
GstBufferPool *gst_omx_buffer_pool_new (GstElement * element, GstOMXComponent * component, GstOMXPort * port, GstOMXBufferMode output_mode);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#endif
|
||||
|
||||
#include <gst/gst.h>
|
||||
#include <gst/allocators/gstdmabuf.h>
|
||||
|
||||
#if defined (USE_OMX_TARGET_RPI) && defined(__GNUC__)
|
||||
#ifndef __VCCOREVER__
|
||||
|
@ -137,6 +138,8 @@ gst_omx_video_dec_class_init (GstOMXVideoDecClass * klass)
|
|||
static void
|
||||
gst_omx_video_dec_init (GstOMXVideoDec * self)
|
||||
{
|
||||
self->dmabuf = FALSE;
|
||||
|
||||
gst_video_decoder_set_packetized (GST_VIDEO_DECODER (self), TRUE);
|
||||
gst_video_decoder_set_use_default_pad_acceptcaps (GST_VIDEO_DECODER_CAST
|
||||
(self), TRUE);
|
||||
|
@ -196,6 +199,29 @@ gst_omx_video_dec_open (GstVideoDecoder * decoder)
|
|||
self->dec_in_port = gst_omx_component_add_port (self->dec, in_port_index);
|
||||
self->dec_out_port = gst_omx_component_add_port (self->dec, out_port_index);
|
||||
|
||||
#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
|
||||
{
|
||||
/* Configure OMX decoder to produce dmabuf */
|
||||
OMX_ALG_PORT_PARAM_BUFFER_MODE buffer_mode;
|
||||
OMX_ERRORTYPE err;
|
||||
|
||||
GST_OMX_INIT_STRUCT (&buffer_mode);
|
||||
buffer_mode.nPortIndex = self->dec_out_port->index;
|
||||
buffer_mode.eMode = OMX_ALG_BUF_DMA;
|
||||
|
||||
GST_DEBUG_OBJECT (self, "Configure decoder to produce dmabuf");
|
||||
|
||||
err =
|
||||
gst_omx_component_set_parameter (self->dec,
|
||||
(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
|
||||
self->dmabuf = TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!self->dec_in_port || !self->dec_out_port)
|
||||
return FALSE;
|
||||
|
||||
|
@ -624,8 +650,8 @@ gst_omx_video_dec_allocate_output_buffers (GstOMXVideoDec * self)
|
|||
|
||||
if (caps)
|
||||
self->out_port_pool =
|
||||
gst_omx_buffer_pool_new (GST_ELEMENT_CAST (self), self->dec, port);
|
||||
|
||||
gst_omx_buffer_pool_new (GST_ELEMENT_CAST (self), self->dec, port,
|
||||
self->dmabuf);
|
||||
#if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL)
|
||||
if (eglimage) {
|
||||
GList *buffers = NULL;
|
||||
|
@ -1942,6 +1968,14 @@ gst_omx_video_dec_set_format (GstVideoDecoder * decoder,
|
|||
|
||||
GST_DEBUG_OBJECT (self, "Setting new caps %" GST_PTR_FORMAT, state->caps);
|
||||
|
||||
if (!self->dmabuf
|
||||
&& gst_caps_features_contains (gst_caps_get_features (state->caps, 0),
|
||||
GST_CAPS_FEATURE_MEMORY_DMABUF)) {
|
||||
GST_WARNING_OBJECT (self,
|
||||
"caps has the 'memory:DMABuf' feature but decoder cannot produce dmabuf");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gst_omx_port_get_port_definition (self->dec_in_port, &port_def);
|
||||
|
||||
/* Check if the caps change is a real format change or if only irrelevant
|
||||
|
|
|
@ -85,6 +85,9 @@ struct _GstOMXVideoDec
|
|||
GstOMXPort *egl_in_port, *egl_out_port;
|
||||
gboolean eglimage;
|
||||
#endif
|
||||
|
||||
/* TRUE if decoder is producing dmabuf */
|
||||
gboolean dmabuf;
|
||||
};
|
||||
|
||||
struct _GstOMXVideoDecClass
|
||||
|
|
|
@ -53,7 +53,7 @@ gstomx = library('gstomx',
|
|||
# link_args : noseh_link_args,
|
||||
include_directories : [configinc] + extra_inc,
|
||||
dependencies : [gstvideo_dep, gstaudio_dep, gstbase_dep, gstcontroller_dep,
|
||||
libm, gmodule_dep] + optional_deps,
|
||||
libm, gmodule_dep, gstallocators_dep] + optional_deps,
|
||||
install : true,
|
||||
install_dir : plugins_install_dir,
|
||||
)
|
||||
|
|
Loading…
Reference in a new issue