From: Wim Taymans Date: Thu, 6 Sep 2012 14:23:28 +0000 (+0200) Subject: deinterlace: add support for bufferpool X-Git-Tag: 1.19.3~509^2~6730 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;ds=sidebyside;h=45e5ec29acd270d3bd7dc98e5a261b35b6e628c6;p=platform%2Fupstream%2Fgstreamer.git deinterlace: add support for bufferpool Add bufferpool support to avoid a memcpy in the videosink when actively interlacing. Remove some commented obsolete code. --- diff --git a/gst/deinterlace/gstdeinterlace.c b/gst/deinterlace/gstdeinterlace.c index 1d1da47..9a0e71e 100644 --- a/gst/deinterlace/gstdeinterlace.c +++ b/gst/deinterlace/gstdeinterlace.c @@ -307,6 +307,9 @@ static GstFlowReturn gst_deinterlace_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer); static GstStateChangeReturn gst_deinterlace_change_state (GstElement * element, GstStateChange transition); +static gboolean gst_deinterlace_set_allocation (GstDeinterlace * self, + GstBufferPool * pool, GstAllocator * allocator, + GstAllocationParams * params); static gboolean gst_deinterlace_src_event (GstPad * pad, GstObject * parent, GstEvent * event); @@ -742,6 +745,8 @@ gst_deinterlace_init (GstDeinterlace * self) self->pattern_buf_dur = GST_CLOCK_TIME_NONE; self->still_frame_mode = FALSE; + gst_deinterlace_set_allocation (self, NULL, NULL, NULL); + gst_deinterlace_reset (self); } @@ -1709,28 +1714,9 @@ restart: GST_DEBUG_OBJECT (self, "deinterlacing top field"); /* create new buffer */ - outbuf = gst_buffer_new_allocate (NULL, GST_VIDEO_INFO_SIZE (&self->vinfo), NULL); // FIXME: pad_alloc_buffer - - if (outbuf == NULL) - return GST_FLOW_ERROR; // FIXME: report proper out of mem error? - -#if 0 - if (GST_PAD_CAPS (self->srcpad) != GST_BUFFER_CAPS (outbuf) && - !gst_caps_is_equal (GST_PAD_CAPS (self->srcpad), - GST_BUFFER_CAPS (outbuf))) { - gst_caps_replace (&self->request_caps, GST_BUFFER_CAPS (outbuf)); - GST_DEBUG_OBJECT (self, "Upstream wants new caps %" GST_PTR_FORMAT, - self->request_caps); - - gst_buffer_unref (outbuf); - outbuf = - gst_buffer_new_allocate (NULL, GST_VIDEO_INFO_SIZE (&self->vinfo), - NULL); - - if (!outbuf) - return GST_FLOW_ERROR; - } -#endif + ret = gst_buffer_pool_acquire_buffer (self->pool, &outbuf, NULL); + if (ret != GST_FLOW_OK) + goto no_buffer; g_return_val_if_fail (self->history_count >= 1 + gst_deinterlace_method_get_latency (self->method), GST_FLOW_ERROR); @@ -1864,30 +1850,9 @@ restart: GST_DEBUG_OBJECT (self, "deinterlacing bottom field"); /* create new buffer */ - outbuf = gst_buffer_new_allocate (NULL, GST_VIDEO_INFO_SIZE (&self->vinfo), NULL); // FIXME: pad_alloc_buffer - - if (outbuf == NULL) - return GST_FLOW_ERROR; // FIXME: report out of mem error? - -#if 0 - if (GST_PAD_CAPS (self->srcpad) != GST_BUFFER_CAPS (outbuf) && - !gst_caps_is_equal (GST_PAD_CAPS (self->srcpad), - GST_BUFFER_CAPS (outbuf))) { - gst_caps_replace (&self->request_caps, GST_BUFFER_CAPS (outbuf)); - GST_DEBUG_OBJECT (self, "Upstream wants new caps %" GST_PTR_FORMAT, - self->request_caps); - - gst_buffer_unref (outbuf); - outbuf = - gst_buffer_new_allocate (NULL, GST_VIDEO_INFO_SIZE (&self->vinfo), - NULL); - - if (!outbuf) - return GST_FLOW_ERROR; - - gst_buffer_set_caps (outbuf, GST_PAD_CAPS (self->srcpad)); - } -#endif + ret = gst_buffer_pool_acquire_buffer (self->pool, &outbuf, NULL); + if (ret != GST_FLOW_OK) + goto no_buffer; g_return_val_if_fail (self->history_count - 1 - gst_deinterlace_method_get_latency (self->method) >= 0, GST_FLOW_ERROR); @@ -1993,8 +1958,15 @@ restart: return ret; need_more: - self->need_more = TRUE; - return ret; + { + self->need_more = TRUE; + return ret; + } +no_buffer: + { + GST_DEBUG_OBJECT (self, "could not allocate buffer"); + return ret; + } } static gboolean @@ -2284,6 +2256,111 @@ error: return NULL; } +/* takes ownership of the pool, allocator and query */ +static gboolean +gst_deinterlace_set_allocation (GstDeinterlace * self, + GstBufferPool * pool, GstAllocator * allocator, + GstAllocationParams * params) +{ + GstAllocator *oldalloc; + GstBufferPool *oldpool; + + GST_OBJECT_LOCK (self); + oldpool = self->pool; + self->pool = pool; + + oldalloc = self->allocator; + self->allocator = allocator; + + if (params) + self->params = *params; + else + gst_allocation_params_init (&self->params); + GST_OBJECT_UNLOCK (self); + + if (oldpool) { + GST_DEBUG_OBJECT (self, "deactivating old pool %p", oldpool); + gst_buffer_pool_set_active (oldpool, FALSE); + gst_object_unref (oldpool); + } + if (oldalloc) { + gst_object_unref (oldalloc); + } + if (pool) { + GST_DEBUG_OBJECT (self, "activating new pool %p", pool); + gst_buffer_pool_set_active (pool, TRUE); + } + return TRUE; +} + +static gboolean +gst_deinterlace_do_bufferpool (GstDeinterlace * self, GstCaps * outcaps) +{ + GstQuery *query; + gboolean result = TRUE; + GstBufferPool *pool; + GstAllocator *allocator; + GstAllocationParams params; + GstStructure *config; + guint size, min, max; + + if (self->passthrough) { + /* we are in passthrough, the input buffer is never copied and always passed + * along. We never allocate an output buffer on the srcpad. What we do is + * let the upstream element decide if it wants to use a bufferpool and + * then we will proxy the downstream pool */ + GST_DEBUG_OBJECT (self, "we're passthough, delay bufferpool"); + gst_deinterlace_set_allocation (self, NULL, NULL, NULL); + return TRUE; + } + + /* not passthrough, we need to allocate */ + /* find a pool for the negotiated caps now */ + GST_DEBUG_OBJECT (self, "doing allocation query"); + query = gst_query_new_allocation (outcaps, TRUE); + if (!gst_pad_peer_query (self->srcpad, query)) { + /* not a problem, just debug a little */ + GST_DEBUG_OBJECT (self, "peer ALLOCATION query failed"); + } + + GST_DEBUG_OBJECT (self, "ALLOCATION (%d) params: %" GST_PTR_FORMAT, result, + query); + + /* we got configuration from our peer or the decide_allocation method, + * parse them */ + if (gst_query_get_n_allocation_params (query) > 0) { + gst_query_parse_nth_allocation_param (query, 0, &allocator, ¶ms); + } else { + allocator = NULL; + gst_allocation_params_init (¶ms); + } + + if (gst_query_get_n_allocation_pools (query) > 0) + gst_query_parse_nth_allocation_pool (query, 0, &pool, &size, &min, &max); + else { + pool = NULL; + size = GST_VIDEO_INFO_SIZE (&self->vinfo), min = max = 0; + } + + if (pool == NULL) { + /* no pool, we can make our own */ + GST_DEBUG_OBJECT (self, "no pool, making new pool"); + pool = gst_video_buffer_pool_new (); + } + + /* now configure */ + config = gst_buffer_pool_get_config (pool); + gst_buffer_pool_config_set_params (config, outcaps, size, min, max); + gst_buffer_pool_config_set_allocator (config, allocator, ¶ms); + gst_buffer_pool_set_config (pool, config); + + /* now store */ + result = gst_deinterlace_set_allocation (self, pool, allocator, ¶ms); + + return result; +} + + static gboolean gst_deinterlace_setcaps (GstDeinterlace * self, GstPad * pad, GstCaps * caps) { @@ -2373,6 +2450,9 @@ gst_deinterlace_setcaps (GstDeinterlace * self, GstPad * pad, GstCaps * caps) GST_DEBUG_OBJECT (pad, "Sink caps: %" GST_PTR_FORMAT, caps); GST_DEBUG_OBJECT (pad, "Src caps: %" GST_PTR_FORMAT, srccaps); + if (!gst_deinterlace_do_bufferpool (self, srccaps)) + goto no_bufferpool; + gst_caps_unref (srccaps); return TRUE; @@ -2388,6 +2468,12 @@ caps_not_accepted: gst_caps_unref (srccaps); return FALSE; } +no_bufferpool: + { + GST_ERROR_OBJECT (pad, "could not negotiate bufferpool"); + gst_caps_unref (srccaps); + return FALSE; + } } static gboolean diff --git a/gst/deinterlace/gstdeinterlace.h b/gst/deinterlace/gstdeinterlace.h index 1c6ef1d..3b8a336 100644 --- a/gst/deinterlace/gstdeinterlace.h +++ b/gst/deinterlace/gstdeinterlace.h @@ -24,6 +24,7 @@ #include #include +#include #include #include "gstdeinterlacemethod.h" @@ -131,14 +132,9 @@ struct _GstDeinterlace GstDeinterlaceMethod *method; GstVideoInfo vinfo; - -#if 0 - GstVideoFormat format; - gint width, height; /* frame width & height */ - guint frame_size; /* frame size in bytes */ - gint fps_n, fps_d; /* frame rate */ - gboolean interlaced; /* is input interlaced? */ -#endif + GstBufferPool *pool; + GstAllocator *allocator; + GstAllocationParams params; gboolean passthrough;