summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGuillaume Desmottes <guillaume.desmottes@collabora.co.uk>2018-05-15 11:59:26 +0200
committerGuillaume Desmottes <guillaume.desmottes@collabora.co.uk>2018-08-30 10:59:30 +0200
commit7be54ad091fc185c92ebdb60d470e26a17938779 (patch)
tree81a5ac360c954552eede0cc47e5f90161edc4418
parent34bc02e397d8db72c06d86f7a8734c0d34d78276 (diff)
downloadgst-omx-7be54ad091fc185c92ebdb60d470e26a17938779.tar.gz
omxvideoenc: implement dmabuf export on input buffers
Propose pool upstream so input buffers can be allocated by the port and exported as dmabuf. The actual OMX buffers are allocated when the pool is activated, so we don't end up doing useless allocations if the pool isn't used. https://bugzilla.gnome.org/show_bug.cgi?id=796918
-rw-r--r--omx/gstomx.c35
-rw-r--r--omx/gstomx.h2
-rw-r--r--omx/gstomxbufferpool.c144
-rw-r--r--omx/gstomxvideoenc.c187
-rw-r--r--omx/gstomxvideoenc.h3
5 files changed, 309 insertions, 62 deletions
diff --git a/omx/gstomx.c b/omx/gstomx.c
index 8f99f82..cb9b392 100644
--- a/omx/gstomx.c
+++ b/omx/gstomx.c
@@ -418,7 +418,11 @@ gst_omx_component_handle_messages (GstOMXComponent * comp)
port->eos = TRUE;
}
- g_queue_push_tail (&port->pending_buffers, buf);
+ /* If an input port is managed by a pool, the buffer will be ready to be
+ * filled again once it's been released to the pool. */
+ if (port->port_def.eDir == OMX_DirOutput || !port->using_pool) {
+ g_queue_push_tail (&port->pending_buffers, buf);
+ }
break;
}
@@ -1097,6 +1101,7 @@ gst_omx_component_add_port (GstOMXComponent * comp, guint32 index)
port->enabled_pending = FALSE;
port->disabled_pending = FALSE;
port->eos = FALSE;
+ port->using_pool = FALSE;
if (port->port_def.eDir == OMX_DirInput)
comp->n_in_ports++;
@@ -2631,6 +2636,34 @@ gst_omx_port_ensure_buffer_count_actual (GstOMXPort * port, guint extra)
}
gboolean
+gst_omx_port_update_buffer_count_actual (GstOMXPort * port, guint nb)
+{
+ OMX_PARAM_PORTDEFINITIONTYPE port_def;
+
+ gst_omx_port_get_port_definition (port, &port_def);
+
+ if (nb < port_def.nBufferCountMin) {
+ GST_DEBUG_OBJECT (port->comp->parent,
+ "Requested to use %d buffers on port %d but it's minimum is %d", nb,
+ (guint) port->index, (guint) port_def.nBufferCountMin);
+
+ nb = port_def.nBufferCountMin;
+ }
+
+ if (port_def.nBufferCountActual != nb) {
+ port_def.nBufferCountActual = nb;
+
+ GST_DEBUG_OBJECT (port->comp->parent,
+ "set port %d nBufferCountActual to %d", (guint) port->index, nb);
+
+ if (gst_omx_port_update_port_definition (port, &port_def) != OMX_ErrorNone)
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+gboolean
gst_omx_port_set_dmabuf (GstOMXPort * port, gboolean dmabuf)
{
#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
diff --git a/omx/gstomx.h b/omx/gstomx.h
index c43e2d7..d61303c 100644
--- a/omx/gstomx.h
+++ b/omx/gstomx.h
@@ -324,6 +324,7 @@ struct _GstOMXPort {
gboolean disabled_pending; /* was done until it took effect */
gboolean eos; /* TRUE after a buffer with EOS flag was received */
GstOMXBufferAllocation allocation;
+ gboolean using_pool; /* TRUE if the buffers of this port are managed by a pool */
/* Increased whenever the settings of these port change.
* If settings_cookie != configured_settings_cookie
@@ -467,6 +468,7 @@ OMX_ERRORTYPE gst_omx_port_set_enabled (GstOMXPort * port, gboolean enabled)
OMX_ERRORTYPE gst_omx_port_wait_enabled (GstOMXPort * port, GstClockTime timeout);
gboolean gst_omx_port_is_enabled (GstOMXPort * port);
gboolean gst_omx_port_ensure_buffer_count_actual (GstOMXPort * port, guint extra);
+gboolean gst_omx_port_update_buffer_count_actual (GstOMXPort * port, guint nb);
gboolean gst_omx_port_set_dmabuf (GstOMXPort * port, gboolean dmabuf);
diff --git a/omx/gstomxbufferpool.c b/omx/gstomxbufferpool.c
index f2e6300..7bb31f5 100644
--- a/omx/gstomxbufferpool.c
+++ b/omx/gstomxbufferpool.c
@@ -36,6 +36,14 @@ typedef struct _GstOMXMemory GstOMXMemory;
typedef struct _GstOMXMemoryAllocator GstOMXMemoryAllocator;
typedef struct _GstOMXMemoryAllocatorClass GstOMXMemoryAllocatorClass;
+enum
+{
+ SIG_ALLOCATE,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
struct _GstOMXMemory
{
GstMemory mem;
@@ -171,11 +179,14 @@ gst_omx_memory_allocator_alloc (GstAllocator * allocator, GstMemoryFlags flags,
* pool to the OMX port or provide the OMX buffers directly to other
* elements.
*
- *
- * A buffer is in the pool if it is currently owned by the port,
- * i.e. after OMX_{Fill,Empty}ThisBuffer(). A buffer is outside
+ * An output buffer is in the pool if it is currently owned by the port,
+ * i.e. after OMX_FillThisBuffer(). An output buffer is outside
* the pool after it was taken from the port after it was handled
- * by the port, i.e. {Empty,Fill}BufferDone.
+ * by the port, i.e. FillBufferDone.
+ *
+ * An input buffer is in the pool if it is currently available to be filled
+ * upstream. It will be put back into the pool when it has been processed by
+ * OMX, (EmptyBufferDone).
*
* Buffers can be allocated by us (OMX_AllocateBuffer()) or allocated
* by someone else and (temporarily) passed to this pool
@@ -188,7 +199,7 @@ gst_omx_memory_allocator_alloc (GstAllocator * allocator, GstMemoryFlags flags,
* They correspond 1:1 to the OMX buffers of the port, which are allocated
* before the pool is started.
*
- * Acquiring a buffer from this pool happens after the OMX buffer has
+ * Acquiring an output buffer from this pool happens after the OMX buffer has
* been acquired from the port. gst_buffer_pool_acquire_buffer() is
* supposed to return the buffer that corresponds to the OMX buffer.
*
@@ -217,6 +228,9 @@ static gboolean
gst_omx_buffer_pool_start (GstBufferPool * bpool)
{
GstOMXBufferPool *pool = GST_OMX_BUFFER_POOL (bpool);
+ gboolean has_buffers;
+ GstStructure *config;
+ guint min, max;
/* Only allow to start the pool if we still are attached
* to a component and port */
@@ -225,8 +239,39 @@ gst_omx_buffer_pool_start (GstBufferPool * bpool)
GST_OBJECT_UNLOCK (pool);
return FALSE;
}
+
+ pool->port->using_pool = TRUE;
+
+ has_buffers = (pool->port->buffers != NULL);
GST_OBJECT_UNLOCK (pool);
+ config = gst_buffer_pool_get_config (bpool);
+ gst_buffer_pool_config_get_params (config, NULL, NULL, &min, &max);
+ gst_structure_free (config);
+ if (max > min) {
+ GST_WARNING_OBJECT (bpool,
+ "max (%d) cannot be higher than min (%d) as pool cannot allocate buffers on the fly",
+ max, min);
+ return FALSE;
+ }
+
+ if (!has_buffers) {
+ gboolean result = FALSE;
+
+ GST_DEBUG_OBJECT (bpool, "Buffers not yet allocated on port %d of %s",
+ pool->port->index, pool->component->name);
+
+ g_signal_emit (pool, signals[SIG_ALLOCATE], 0, &result);
+
+ if (!result) {
+ GST_WARNING_OBJECT (bpool,
+ "Element failed to allocate buffers, can't start pool");
+ return FALSE;
+ }
+ }
+
+ g_assert (pool->port->buffers);
+
return
GST_BUFFER_POOL_CLASS (gst_omx_buffer_pool_parent_class)->start (bpool);
}
@@ -237,12 +282,17 @@ gst_omx_buffer_pool_stop (GstBufferPool * bpool)
GstOMXBufferPool *pool = GST_OMX_BUFFER_POOL (bpool);
gint i = 0;
- /* When not using the default GstBufferPool::GstAtomicQueue then
- * GstBufferPool::free_buffer is not called while stopping the pool
- * (because the queue is empty) */
- for (i = 0; i < pool->buffers->len; i++)
- GST_BUFFER_POOL_CLASS (gst_omx_buffer_pool_parent_class)->release_buffer
- (bpool, g_ptr_array_index (pool->buffers, i));
+ if (pool->buffers) {
+ /* When not using the default GstBufferPool::GstAtomicQueue then
+ * GstBufferPool::free_buffer is not called while stopping the pool
+ * (because the queue is empty) */
+ for (i = 0; i < pool->buffers->len; i++)
+ GST_BUFFER_POOL_CLASS (gst_omx_buffer_pool_parent_class)->release_buffer
+ (bpool, g_ptr_array_index (pool->buffers, i));
+
+ /* Remove any buffers that are there */
+ g_ptr_array_set_size (pool->buffers, 0);
+ }
/* Remove any buffers that are there */
g_ptr_array_set_size (pool->buffers, 0);
@@ -255,6 +305,8 @@ gst_omx_buffer_pool_stop (GstBufferPool * bpool)
pool->caps = NULL;
pool->add_videometa = FALSE;
+ pool->deactivated = TRUE;
+ pool->port->using_pool = TRUE;
return GST_BUFFER_POOL_CLASS (gst_omx_buffer_pool_parent_class)->stop (bpool);
}
@@ -284,10 +336,11 @@ gst_omx_buffer_pool_set_config (GstBufferPool * bpool, GstStructure * config)
{
GstOMXBufferPool *pool = GST_OMX_BUFFER_POOL (bpool);
GstCaps *caps;
+ guint size, min;
GST_OBJECT_LOCK (pool);
- if (!gst_buffer_pool_config_get_params (config, &caps, NULL, NULL, NULL))
+ if (!gst_buffer_pool_config_get_params (config, &caps, &size, &min, NULL))
goto wrong_config;
if (caps == NULL)
@@ -314,6 +367,9 @@ gst_omx_buffer_pool_set_config (GstBufferPool * bpool, GstStructure * config)
gst_caps_unref (pool->caps);
pool->caps = gst_caps_ref (caps);
+ /* Ensure max=min as the pool won't be able to allocate more buffers while active */
+ gst_buffer_pool_config_set_params (config, caps, size, min, min);
+
GST_OBJECT_UNLOCK (pool);
return GST_BUFFER_POOL_CLASS (gst_omx_buffer_pool_parent_class)->set_config
@@ -520,6 +576,21 @@ gst_omx_buffer_pool_free_buffer (GstBufferPool * bpool, GstBuffer * buffer)
buffer);
}
+static GstBuffer *
+find_buffer_from_omx_buffer (GstOMXBufferPool * pool, GstOMXBuffer * omx_buf)
+{
+ guint i;
+
+ for (i = 0; i < pool->buffers->len; i++) {
+ GstBuffer *buf = g_ptr_array_index (pool->buffers, i);
+
+ if (gst_omx_buffer_get_omx_buf (buf) == omx_buf)
+ return buf;
+ }
+
+ return NULL;
+}
+
static GstFlowReturn
gst_omx_buffer_pool_acquire_buffer (GstBufferPool * bpool,
GstBuffer ** buffer, GstBufferPoolAcquireParams * params)
@@ -557,9 +628,23 @@ gst_omx_buffer_pool_acquire_buffer (GstBufferPool * bpool,
}
} else {
/* Acquire any buffer that is available to be filled by upstream */
- ret =
- GST_BUFFER_POOL_CLASS (gst_omx_buffer_pool_parent_class)->acquire_buffer
- (bpool, buffer, params);
+ GstOMXBuffer *omx_buf;
+ GstOMXAcquireBufferReturn r;
+ GstOMXWait wait = GST_OMX_WAIT;
+
+ if (params && (params->flags & GST_BUFFER_POOL_ACQUIRE_FLAG_DONTWAIT))
+ wait = GST_OMX_DONT_WAIT;
+
+ r = gst_omx_port_acquire_buffer (pool->port, &omx_buf, wait);
+ if (r == GST_OMX_ACQUIRE_BUFFER_OK) {
+ *buffer = find_buffer_from_omx_buffer (pool, omx_buf);
+ g_return_val_if_fail (*buffer, GST_FLOW_ERROR);
+ return GST_FLOW_OK;
+ } else if (r == GST_OMX_ACQUIRE_BUFFER_FLUSHING) {
+ return GST_FLOW_FLUSHING;
+ } else {
+ return GST_FLOW_ERROR;
+ }
}
return ret;
@@ -574,9 +659,10 @@ gst_omx_buffer_pool_release_buffer (GstBufferPool * bpool, GstBuffer * buffer)
g_assert (pool->component && pool->port);
- if (!pool->allocating && !pool->deactivated) {
+ if (!pool->allocating) {
omx_buf = gst_omx_buffer_get_omx_buf (buffer);
- if (pool->port->port_def.eDir == OMX_DirOutput && !omx_buf->used) {
+ if (pool->port->port_def.eDir == OMX_DirOutput && !omx_buf->used &&
+ !pool->deactivated) {
/* Release back to the port, can be filled again */
err = gst_omx_port_release_buffer (pool->port, omx_buf);
if (err != OMX_ErrorNone) {
@@ -584,24 +670,8 @@ gst_omx_buffer_pool_release_buffer (GstBufferPool * bpool, GstBuffer * buffer)
("Failed to relase output buffer to component: %s (0x%08x)",
gst_omx_error_to_string (err), err));
}
- } else if (!omx_buf->used) {
- /* TODO: Implement.
- *
- * If not used (i.e. was not passed to the component) this should do
- * the same as EmptyBufferDone.
- * If it is used (i.e. was passed to the component) this should do
- * nothing until EmptyBufferDone.
- *
- * EmptyBufferDone should release the buffer to the pool so it can
- * be allocated again
- *
- * Needs something to call back here in EmptyBufferDone, like keeping
- * a ref on the buffer in GstOMXBuffer until EmptyBufferDone... which
- * would ensure that the buffer is always unused when this is called.
- */
- g_assert_not_reached ();
- GST_BUFFER_POOL_CLASS (gst_omx_buffer_pool_parent_class)->release_buffer
- (bpool, buffer);
+ } else if (pool->port->port_def.eDir == OMX_DirInput) {
+ g_queue_push_tail (&pool->port->pending_buffers, omx_buf);
}
}
}
@@ -653,6 +723,10 @@ gst_omx_buffer_pool_class_init (GstOMXBufferPoolClass * klass)
gstbufferpool_class->release_buffer = gst_omx_buffer_pool_release_buffer;
GST_DEBUG_CATEGORY_GET (CAT_PERFORMANCE, "GST_PERFORMANCE");
+
+ signals[SIG_ALLOCATE] = g_signal_new ("allocate",
+ G_TYPE_FROM_CLASS (gobject_class), G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL,
+ G_TYPE_BOOLEAN, 0);
}
static void
diff --git a/omx/gstomxvideoenc.c b/omx/gstomxvideoenc.c
index 6da94a7..9aa3a98 100644
--- a/omx/gstomxvideoenc.c
+++ b/omx/gstomxvideoenc.c
@@ -28,6 +28,7 @@
#include <string.h>
+#include "gstomxbufferpool.h"
#include "gstomxvideo.h"
#include "gstomxvideoenc.h"
@@ -917,7 +918,9 @@ gst_omx_video_enc_open (GstVideoEncoder * encoder)
static gboolean
gst_omx_video_enc_deallocate_in_buffers (GstOMXVideoEnc * self)
{
- if (gst_omx_port_deallocate_buffers (self->enc_in_port) != OMX_ErrorNone)
+ /* Pool will take care of deallocating buffers when deactivated upstream */
+ if (!self->in_pool_used
+ && gst_omx_port_deallocate_buffers (self->enc_in_port) != OMX_ErrorNone)
return FALSE;
return TRUE;
@@ -1659,6 +1662,7 @@ gst_omx_video_enc_start (GstVideoEncoder * encoder)
self->last_upstream_ts = 0;
self->downstream_flow_ret = GST_FLOW_OK;
self->nb_downstream_buffers = 0;
+ self->in_pool_used = FALSE;
return TRUE;
}
@@ -2036,40 +2040,66 @@ gst_omx_video_enc_set_to_idle (GstOMXVideoEnc * self)
}
static gboolean
+buffer_is_from_input_pool (GstOMXVideoEnc * self, GstBuffer * buffer)
+{
+ /* Buffer from our input pool will already have a GstOMXBuffer associated
+ * with our input port. */
+ GstOMXBuffer *buf;
+
+ buf = gst_omx_buffer_get_omx_buf (buffer);
+ if (!buf)
+ return FALSE;
+
+ return buf->port == self->enc_in_port;
+}
+
+static gboolean
gst_omx_video_enc_enable (GstOMXVideoEnc * self, GstBuffer * input)
{
GstOMXVideoEncClass *klass;
klass = GST_OMX_VIDEO_ENC_GET_CLASS (self);
- if (!gst_omx_video_enc_configure_input_buffer (self, input))
- return FALSE;
+ /* Is downstream using our buffer pool? */
+ if (buffer_is_from_input_pool (self, input)) {
+ /* We're done allocating as we received the first buffer from upstream */
+ GST_OMX_BUFFER_POOL (input->pool)->allocating = FALSE;
+ self->in_pool_used = TRUE;
+ }
- self->input_allocation = gst_omx_video_enc_pick_input_allocation_mode (self,
- input);
- self->input_dmabuf = FALSE;
+ if (!self->in_pool_used) {
+ if (!gst_omx_video_enc_configure_input_buffer (self, input))
+ return FALSE;
+
+ 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) {
- GST_DEBUG_OBJECT (self, "Configure encoder input to import dmabuf");
- gst_omx_port_set_dmabuf (self->enc_in_port, TRUE);
- } else {
- GST_DEBUG_OBJECT (self,
- "Wrong input allocation mode (%d); dynamic buffers are required to use dmabuf import",
- self->input_allocation);
- }
+ if (gst_is_dmabuf_memory (gst_buffer_peek_memory (input, 0))) {
+ if (self->input_allocation ==
+ GST_OMX_BUFFER_ALLOCATION_USE_BUFFER_DYNAMIC) {
+ GST_DEBUG_OBJECT (self, "Configure encoder input to import dmabuf");
+ gst_omx_port_set_dmabuf (self->enc_in_port, TRUE);
+ } 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;
- }
+ self->input_dmabuf = TRUE;
+ }
#endif
+ }
GST_DEBUG_OBJECT (self, "Enabling component");
- if (!gst_omx_video_enc_ensure_nb_in_buffers (self))
- return FALSE;
- if (!gst_omx_video_enc_ensure_nb_out_buffers (self))
- return FALSE;
+ if (!self->in_pool_used) {
+ if (!gst_omx_video_enc_ensure_nb_in_buffers (self))
+ return FALSE;
+ if (!gst_omx_video_enc_ensure_nb_out_buffers (self))
+ return FALSE;
+ }
if (self->disabled) {
if (gst_omx_port_set_enabled (self->enc_in_port, TRUE) != OMX_ErrorNone)
@@ -2094,8 +2124,11 @@ gst_omx_video_enc_enable (GstOMXVideoEnc * self, GstBuffer * input)
if (gst_omx_port_mark_reconfigured (self->enc_in_port) != OMX_ErrorNone)
return FALSE;
} else {
- if (!gst_omx_video_enc_set_to_idle (self))
- return FALSE;
+ /* If the input pool is active we already allocated buffers and set the component to Idle. */
+ if (!self->in_pool_used) {
+ if (!gst_omx_video_enc_set_to_idle (self))
+ return FALSE;
+ }
if (gst_omx_component_set_state (self->enc,
OMX_StateExecuting) != OMX_ErrorNone)
@@ -2668,12 +2701,32 @@ gst_omx_video_enc_handle_frame (GstVideoEncoder * encoder,
while (acq_ret != GST_OMX_ACQUIRE_BUFFER_OK) {
GstClockTime timestamp, duration;
+ gboolean fill_buffer = TRUE;
/* Make sure to release the base class stream lock, otherwise
* _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, GST_OMX_WAIT);
+
+ if (buffer_is_from_input_pool (self, frame->input_buffer)) {
+ /* Receiving a buffer from our input pool */
+ buf = gst_omx_buffer_get_omx_buf (frame->input_buffer);
+
+ GST_LOG_OBJECT (self,
+ "Input buffer %p already has a OMX buffer associated: %p",
+ frame->input_buffer, buf);
+
+ g_assert (!buf->input_buffer);
+ /* Prevent the buffer to be released to the pool while it's being
+ * processed by OMX. The reference will be dropped in EmptyBufferDone() */
+ buf->input_buffer = gst_buffer_ref (frame->input_buffer);
+
+ acq_ret = GST_OMX_ACQUIRE_BUFFER_OK;
+ fill_buffer = FALSE;
+ buf->omx_buf->nFilledLen = gst_buffer_get_size (frame->input_buffer);
+ } else {
+ acq_ret = gst_omx_port_acquire_buffer (port, &buf, GST_OMX_WAIT);
+ }
if (acq_ret == GST_OMX_ACQUIRE_BUFFER_ERROR) {
GST_VIDEO_ENCODER_STREAM_LOCK (self);
@@ -2789,7 +2842,8 @@ gst_omx_video_enc_handle_frame (GstVideoEncoder * encoder,
/* Copy the buffer content in chunks of size as requested
* by the port */
- if (!gst_omx_video_enc_fill_buffer (self, frame->input_buffer, buf)) {
+ if (fill_buffer
+ && !gst_omx_video_enc_fill_buffer (self, frame->input_buffer, buf)) {
gst_omx_port_release_buffer (port, buf);
goto buffer_fill_error;
}
@@ -2968,6 +3022,71 @@ gst_omx_video_enc_drain (GstOMXVideoEnc * self)
return GST_FLOW_OK;
}
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+static gboolean
+pool_request_allocate_cb (GstBufferPool * pool, GstOMXVideoEnc * self)
+{
+ GstStructure *config;
+ guint min;
+
+ gst_omx_port_set_dmabuf (self->enc_in_port, TRUE);
+
+ config = gst_buffer_pool_get_config (pool);
+
+ if (!gst_buffer_pool_config_get_params (config, NULL, NULL, &min, NULL)) {
+ gst_structure_free (config);
+ return FALSE;
+ }
+ gst_structure_free (config);
+
+ GST_DEBUG_OBJECT (self,
+ "input pool configured for %d buffers, adjust nBufferCountActual", min);
+
+ if (!gst_omx_port_update_buffer_count_actual (self->enc_in_port, min))
+ return FALSE;
+
+ if (!gst_omx_video_enc_set_to_idle (self))
+ return FALSE;
+
+ self->input_allocation = GST_OMX_BUFFER_ALLOCATION_ALLOCATE_BUFFER;
+ self->input_dmabuf = TRUE;
+
+ /* gst_omx_port_acquire_buffer() will fail if the input port is stil flushing
+ * which will prevent upstream from acquiring buffers. */
+ gst_omx_port_set_flushing (self->enc_in_port, 5 * GST_SECOND, FALSE);
+
+ return TRUE;
+}
+
+static GstBufferPool *
+create_input_pool (GstOMXVideoEnc * self, GstCaps * caps, guint num_buffers)
+{
+ GstBufferPool *pool;
+ GstStructure *config;
+
+ pool =
+ gst_omx_buffer_pool_new (GST_ELEMENT_CAST (self), self->enc,
+ self->enc_in_port, GST_OMX_BUFFER_MODE_DMABUF);
+ GST_OMX_BUFFER_POOL (pool)->allocating = TRUE;
+
+ g_signal_connect_object (pool, "allocate",
+ G_CALLBACK (pool_request_allocate_cb), self, 0);
+
+ config = gst_buffer_pool_get_config (pool);
+
+ gst_buffer_pool_config_set_params (config, caps,
+ self->enc_in_port->port_def.nBufferSize, num_buffers, 0);
+
+ if (!gst_buffer_pool_set_config (pool, config)) {
+ GST_INFO_OBJECT (self, "Failed to set config on input pool");
+ gst_object_unref (pool);
+ return NULL;
+ }
+
+ return pool;
+}
+#endif
+
static gboolean
gst_omx_video_enc_propose_allocation (GstVideoEncoder * encoder,
GstQuery * query)
@@ -2976,6 +3095,7 @@ gst_omx_video_enc_propose_allocation (GstVideoEncoder * encoder,
guint num_buffers;
GstCaps *caps;
GstVideoInfo info;
+ GstBufferPool *pool = NULL;
gst_query_parse_allocation (query, &caps, NULL);
@@ -2992,10 +3112,25 @@ gst_omx_video_enc_propose_allocation (GstVideoEncoder * encoder,
gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL);
num_buffers = self->enc_in_port->port_def.nBufferCountMin + 1;
+
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+ /* dmabuf export is currently only supported on Zynqultrascaleplus */
+ pool = create_input_pool (self, caps, num_buffers);
+ if (!pool) {
+ GST_WARNING_OBJECT (self, "Failed to create and configure pool");
+ return FALSE;
+ }
+#endif
+
GST_DEBUG_OBJECT (self,
"request at least %d buffers of size %" G_GSIZE_FORMAT, num_buffers,
info.size);
- gst_query_add_allocation_pool (query, NULL, info.size, num_buffers, 0);
+ gst_query_add_allocation_pool (query, pool,
+ self->enc_in_port->port_def.nBufferSize, num_buffers, 0);
+
+ self->in_pool_used = FALSE;
+
+ g_clear_object (&pool);
return
GST_VIDEO_ENCODER_CLASS
diff --git a/omx/gstomxvideoenc.h b/omx/gstomxvideoenc.h
index 370b290..c84e62a 100644
--- a/omx/gstomxvideoenc.h
+++ b/omx/gstomxvideoenc.h
@@ -104,6 +104,9 @@ struct _GstOMXVideoEnc
/* Number of buffers requested downstream */
guint nb_downstream_buffers;
+ /* TRUE if input buffers are from the pool we proposed to upstream */
+ gboolean in_pool_used;
+
#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
GEnumClass *alg_roi_quality_enum_class;
#endif