From 58d8ea72ec78cb17cf75c82c67a69e9bd383c3b3 Mon Sep 17 00:00:00 2001 From: Andrey Gusakov Date: Thu, 1 Sep 2016 20:09:03 +0300 Subject: [PATCH 10/10] omxvideodec: support creating buffers using sink Used for zero-copy output to wayland/weston Signed-off-by: Andrey Gusakov --- omx/gstomxbufferpool.c | 107 +++++++++++++++++++++++++++++++++++++++++++++--- omx/gstomxvideodec.c | 11 ++++- 2 files changed, 111 insertions(+), 7 deletions(-) diff --git a/omx/gstomxbufferpool.c b/omx/gstomxbufferpool.c index eb2fe9d..60b25ef 100644 --- a/omx/gstomxbufferpool.c +++ b/omx/gstomxbufferpool.c @@ -372,6 +372,73 @@ GstOMXBuffer *gst_omx_buffer_get_omxbuffer (GstBuffer * buffer) return omx_buf; } +#ifdef HAVE_MMNGRBUF +static GstBuffer * +gst_omx_buffer_pool_request_videosink_buffer_creation (GstOMXBufferPool * pool, + gint dmabuf_fd[GST_VIDEO_MAX_PLANES], gpointer plane_buf[GST_VIDEO_MAX_PLANES], gint stride[GST_VIDEO_MAX_PLANES]) +{ + GstQuery *query; + GValue val = { 0, }; + GstStructure *structure; + const GValue *value; + GstBuffer *buffer; + GArray *dmabuf_array; + GArray *stride_array; + GArray *planebuf_array; + gint n_planes; + gint i; + + g_value_init (&val, G_TYPE_POINTER); + g_value_set_pointer (&val, (gpointer) pool->allocator); + + dmabuf_array = g_array_new (FALSE, FALSE, sizeof (gint)); + stride_array = g_array_new (FALSE, FALSE, sizeof (gint)); + planebuf_array = g_array_new (FALSE, FALSE, sizeof (gpointer)); + + n_planes = GST_VIDEO_INFO_N_PLANES (&pool->video_info); + for (i = 0; i < n_planes; i++) { + g_array_append_val (dmabuf_array, dmabuf_fd[i]); + g_array_append_val (stride_array, stride[i]); + g_array_append_val (planebuf_array, plane_buf[i]); + } + + structure = gst_structure_new ("videosink_buffer_creation_request", + "width", G_TYPE_INT, pool->port->port_def.format.video.nFrameWidth, + "height", G_TYPE_INT, pool->port->port_def.format.video.nFrameHeight, + "stride", G_TYPE_ARRAY, stride_array, + "dmabuf", G_TYPE_ARRAY, dmabuf_array, + "planebuf", G_TYPE_ARRAY, planebuf_array, + "allocator", G_TYPE_POINTER, &val, + "format", G_TYPE_STRING, + gst_video_format_to_string (pool->video_info.finfo->format), + "n_planes", G_TYPE_INT, n_planes, NULL); + + query = gst_query_new_custom (GST_QUERY_CUSTOM, structure); + + GST_DEBUG_OBJECT (pool, "send a videosink_buffer_creation_request query"); + + if (!gst_pad_peer_query (GST_VIDEO_DECODER_SRC_PAD (pool->element), query)) { + GST_ERROR_OBJECT (pool, "videosink_buffer_creation_request query failed"); + return NULL; + } + + value = gst_structure_get_value (structure, "buffer"); + buffer = gst_value_get_buffer (value); + if (buffer == NULL) { + GST_ERROR_OBJECT (pool, + "could not get a buffer from videosink_buffer_creation query"); + return NULL; + } + + gst_query_unref (query); + + g_array_free (dmabuf_array, TRUE); + g_array_free (stride_array, TRUE); + + return buffer; +} +#endif + #if defined (HAVE_MMNGRBUF) && defined (HAVE_VIDEODEC_EXT) static gboolean gst_omx_buffer_pool_export_dmabuf (GstOMXBufferPool * pool, @@ -406,6 +473,7 @@ gst_omx_buffer_pool_create_buffer_contain_dmabuf (GstOMXBufferPool * self, gint plane_size_ext[GST_VIDEO_MAX_PLANES]; gint dmabuf_id[GST_VIDEO_MAX_PLANES]; gint page_offset[GST_VIDEO_MAX_PLANES]; + gint plane_buf[GST_VIDEO_MAX_PLANES]; GstBuffer *new_buf; gint i; gint page_size; @@ -450,6 +518,7 @@ gst_omx_buffer_pool_create_buffer_contain_dmabuf (GstOMXBufferPool * self, else plane_size[i] = stride[i] * GST_VIDEO_INFO_COMP_HEIGHT (&self->video_info, i); + plane_buf[i] = omx_buf->omx_buf->pBuffer + offset[i]; /* When downstream plugins do mapping from dmabuf fd it requires * mapping from boundary page and size align for page size so @@ -472,14 +541,40 @@ gst_omx_buffer_pool_create_buffer_contain_dmabuf (GstOMXBufferPool * self, gst_buffer_append_memory (new_buf, mem); } - g_ptr_array_add (self->buffers, new_buf); - gst_buffer_add_video_meta_full (new_buf, GST_VIDEO_FRAME_FLAG_NONE, - GST_VIDEO_INFO_FORMAT (&self->video_info), - GST_VIDEO_INFO_WIDTH (&self->video_info), - GST_VIDEO_INFO_HEIGHT (&self->video_info), - GST_VIDEO_INFO_N_PLANES (&self->video_info), offset, stride); + if (self->vsink_buf_req_supported) { + new_buf = gst_omx_buffer_pool_request_videosink_buffer_creation (self, + dmabuf_fd, plane_buf, stride); + if (!new_buf) { + GST_ERROR_OBJECT (self, "creating dmabuf using videosink failed"); + goto err; + } + new_buf->pool = self; + } else { + new_buf = gst_buffer_new (); + for (i = 0; i < GST_VIDEO_INFO_N_PLANES (&self->video_info); i++) { + GstMemory *mem; + /* Set offset's information */ + mem = gst_dmabuf_allocator_alloc (self->allocator, dmabuf_fd[i], + plane_size_ext[i]); + mem->offset = page_offset[i]; + mem->size = plane_size[i]; + gst_buffer_append_memory (new_buf, mem); + } + + gst_buffer_add_video_meta_full (new_buf, GST_VIDEO_FRAME_FLAG_NONE, + GST_VIDEO_INFO_FORMAT (&self->video_info), + GST_VIDEO_INFO_WIDTH (&self->video_info), + GST_VIDEO_INFO_HEIGHT (&self->video_info), + GST_VIDEO_INFO_N_PLANES (&self->video_info), offset, stride); + } + GST_ERROR_OBJECT (self, "got buffer %p from pool %p", + new_buf, new_buf->pool); + g_ptr_array_add (self->buffers, new_buf); return new_buf; + +err: + return NULL; } #endif diff --git a/omx/gstomxvideodec.c b/omx/gstomxvideodec.c index 25b6b30..44b706a 100644 --- a/omx/gstomxvideodec.c +++ b/omx/gstomxvideodec.c @@ -2350,6 +2350,8 @@ gst_omx_video_dec_decide_allocation (GstVideoDecoder * bdec, GstQuery * query) &GST_OMX_BUFFER_POOL (self->out_port_pool)->vsink_buf_req_supported); gst_object_unref (pool); update_pool = TRUE; + GST_ERROR_OBJECT (self, "vsink_buf_req_supported %d", + GST_OMX_BUFFER_POOL (self->out_port_pool)->vsink_buf_req_supported); } /* Set pool parameters to our own configuration */ @@ -2372,7 +2374,14 @@ gst_omx_video_dec_decide_allocation (GstVideoDecoder * bdec, GstQuery * query) } GST_OMX_BUFFER_POOL (self->out_port_pool)->allocating = TRUE; - gst_buffer_pool_set_active (self->out_port_pool, TRUE); + /* This now allocates all the buffers */ + if (!gst_buffer_pool_set_active (self->out_port_pool, TRUE)) { + GST_INFO_OBJECT (self, "Failed to activate internal pool"); + gst_object_unref (self->out_port_pool); + self->out_port_pool = NULL; + } else { + GST_OMX_BUFFER_POOL (self->out_port_pool)->allocating = FALSE; + } /* This video buffer pool created below will not be used, just setting to * the gstvideodecoder class through a query, because it is -- 1.7.10.4