From fe1ce6a7ffdfb3e207e07488a0cc169488e8d8ac Mon Sep 17 00:00:00 2001 From: Matthew Waters Date: Thu, 12 Jul 2012 18:19:44 +1000 Subject: [PATCH] [542/906] GstGLMixer: add allocation and bufferpool methods based off GstBaseTransform --- gst-libs/gst/gl/gstglmixer.c | 204 +++++++++++++++++++++++++++++++++++++++++-- gst-libs/gst/gl/gstglmixer.h | 5 ++ 2 files changed, 201 insertions(+), 8 deletions(-) diff --git a/gst-libs/gst/gl/gstglmixer.c b/gst-libs/gst/gl/gstglmixer.c index 5a0d1bc..d666005 100644 --- a/gst-libs/gst/gl/gstglmixer.c +++ b/gst-libs/gst/gl/gstglmixer.c @@ -66,6 +66,20 @@ enum PROP_PAD_0 }; +#define GST_GL_MIXER_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_GL_MIXER, GstGLMixerPrivate)) + +struct _GstGLMixerPrivate +{ + gboolean negotiated; + + GstBufferPool *pool; + gboolean pool_active; + GstAllocator *allocator; + GstAllocationParams params; + GstQuery *query; +}; + G_DEFINE_TYPE (GstGLMixerPad, gst_gl_mixer_pad, GST_TYPE_PAD); static void @@ -207,6 +221,7 @@ gst_gl_mixer_update_src_caps (GstGLMixer * mix) GST_GL_MIXER_UNLOCK (mix); ret = gst_gl_mixer_src_setcaps (mix->srcpad, mix, caps); +// ret = gst_pad_set_caps (mix->srcpad, caps); gst_caps_unref (caps); } else { GST_GL_MIXER_UNLOCK (mix); @@ -334,6 +349,8 @@ gst_gl_mixer_pad_sink_query (GstPad * pad, GstObject * parent, GstQuery * query) { gboolean ret = FALSE; + GST_TRACE ("QUERY %d", GST_QUERY_TYPE (query)); + switch (GST_QUERY_TYPE (query)) { case GST_QUERY_CAPS: { @@ -360,6 +377,7 @@ gst_gl_mixer_pad_sink_query (GstPad * pad, GstObject * parent, GstQuery * query) ret = gst_pad_query_default (pad, parent, query); break; } + return ret; } @@ -422,6 +440,14 @@ static gboolean gst_gl_mixer_query_duration (GstGLMixer * mix, GstQuery * query); static gboolean gst_gl_mixer_query_latency (GstGLMixer * mix, GstQuery * query); +static gboolean gst_gl_mixer_do_bufferpool (GstGLMixer * mix, + GstCaps * outcaps); +static gboolean gst_gl_mixer_decide_allocation (GstGLMixer * mix, + GstQuery * query); +static gboolean gst_gl_mixer_set_allocation (GstGLMixer * mix, + GstBufferPool * pool, GstAllocator * allocator, + GstAllocationParams * params, GstQuery * query); + static gint64 gst_gl_mixer_do_qos (GstGLMixer * mix, GstClockTime timestamp); static void gst_gl_mixer_update_qos (GstGLMixer * mix, gdouble proportion, GstClockTimeDiff diff, GstClockTime timestamp); @@ -484,6 +510,8 @@ gst_gl_mixer_class_init (GstGLMixerClass * klass) gobject_class = (GObjectClass *) klass; element_class = GST_ELEMENT_CLASS (klass); + g_type_class_add_private (klass, sizeof (GstGLMixerPrivate)); + gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_gl_mixer_finalize); gobject_class->get_property = gst_gl_mixer_get_property; @@ -517,6 +545,7 @@ gst_gl_mixer_collect_free (GstGLMixerCollect * mixcol) static void gst_gl_mixer_reset (GstGLMixer * mix) { + GstGLMixerPrivate *priv = mix->priv; GSList *l; gst_video_info_init (&mix->info); @@ -540,6 +569,8 @@ gst_gl_mixer_reset (GstGLMixer * mix) mix->newseg_pending = TRUE; mix->flush_stop_pending = FALSE; + + priv->negotiated = FALSE; } static void @@ -547,6 +578,8 @@ gst_gl_mixer_init (GstGLMixer * mix) { GstElementClass *klass = GST_ELEMENT_GET_CLASS (mix); + mix->priv = GST_GL_MIXER_GET_PRIVATE (mix); + mix->srcpad = gst_pad_new_from_template (gst_element_class_get_pad_template (klass, "src"), "src"); @@ -928,11 +961,151 @@ gst_gl_mixer_src_query (GstPad * pad, GstObject * parent, GstQuery * query) } static gboolean +gst_gl_mixer_decide_allocation (GstGLMixer * mix, GstQuery * query) +{ + GstBufferPool *pool = NULL; + GstStructure *config; + GstCaps *caps; + guint min, max, size; + gboolean update_pool; + + gst_query_parse_allocation (query, &caps, NULL); + + if (gst_query_get_n_allocation_pools (query) > 0) { + gst_query_parse_nth_allocation_pool (query, 0, &pool, &size, &min, &max); + + update_pool = TRUE; + } else { + GstVideoInfo vinfo; + + gst_video_info_init (&vinfo); + gst_video_info_from_caps (&vinfo, caps); + size = vinfo.size; + min = max = 0; + update_pool = FALSE; + } + + if (!pool) + pool = gst_gl_buffer_pool_new (mix->display); + + config = gst_buffer_pool_get_config (pool); + gst_buffer_pool_config_set_params (config, caps, size, min, max); + gst_buffer_pool_config_add_option (config, GST_BUFFER_POOL_OPTION_VIDEO_META); + gst_buffer_pool_config_add_option (config, GST_BUFFER_POOL_OPTION_GL_META); + gst_buffer_pool_set_config (pool, config); + + if (update_pool) + gst_query_set_nth_allocation_pool (query, 0, pool, size, min, max); + else + gst_query_add_allocation_pool (query, pool, size, min, max); + + gst_object_unref (pool); + + return TRUE; +} + +/* takes ownership of the pool, allocator and query */ +static gboolean +gst_gl_mixer_set_allocation (GstGLMixer * mix, + GstBufferPool * pool, GstAllocator * allocator, + GstAllocationParams * params, GstQuery * query) +{ + GstAllocator *oldalloc; + GstBufferPool *oldpool; + GstQuery *oldquery; + GstGLMixerPrivate *priv = mix->priv; + + GST_OBJECT_LOCK (mix); + oldpool = priv->pool; + priv->pool = pool; + priv->pool_active = FALSE; + + oldalloc = priv->allocator; + priv->allocator = allocator; + + oldquery = priv->query; + priv->query = query; + + if (params) + priv->params = *params; + else + gst_allocation_params_init (&priv->params); + GST_OBJECT_UNLOCK (mix); + + if (oldpool) { + GST_DEBUG_OBJECT (mix, "deactivating old pool %p", oldpool); + gst_buffer_pool_set_active (oldpool, FALSE); + gst_object_unref (oldpool); + } + if (oldalloc) { + gst_allocator_unref (oldalloc); + } + if (oldquery) { + gst_query_unref (oldquery); + } + return TRUE; +} + +static gboolean +gst_gl_mixer_do_bufferpool (GstGLMixer * mix, GstCaps * outcaps) +{ + GstQuery *query; + gboolean result = TRUE; + GstBufferPool *pool = NULL; + GstAllocator *allocator; + GstAllocationParams params; + + /* find a pool for the negotiated caps now */ + GST_DEBUG_OBJECT (mix, "doing allocation query"); + query = gst_query_new_allocation (outcaps, TRUE); + if (!gst_pad_peer_query (mix->srcpad, query)) { + /* not a problem, just debug a little */ + GST_DEBUG_OBJECT (mix, "peer ALLOCATION query failed"); + } + + GST_DEBUG_OBJECT (mix, "calling decide_allocation"); + result = gst_gl_mixer_decide_allocation (mix, query); + + GST_DEBUG_OBJECT (mix, "ALLOCATION (%d) params: %" GST_PTR_FORMAT, result, + query); + + if (!result) + goto no_decide_allocation; + + /* 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, NULL, NULL, NULL); + + /* now store */ + result = gst_gl_mixer_set_allocation (mix, pool, allocator, ¶ms, query); + + return result; + + /* Errors */ +no_decide_allocation: + { + GST_WARNING_OBJECT (mix, "Failed to decide allocation"); + gst_query_unref (query); + + return result; + } +} + +static gboolean gst_gl_mixer_src_setcaps (GstPad * pad, GstGLMixer * mix, GstCaps * caps) { GstGLMixerClass *mixer_class = GST_GL_MIXER_GET_CLASS (mix); + GstGLMixerPrivate *priv = mix->priv; GstVideoInfo info; - gboolean ret; + gboolean ret = TRUE; GST_INFO_OBJECT (mix, "set src caps: %" GST_PTR_FORMAT, caps); @@ -967,8 +1140,12 @@ gst_gl_mixer_src_setcaps (GstPad * pad, GstGLMixer * mix, GstCaps * caps) if (mixer_class->set_caps) mixer_class->set_caps (mix, caps); - ret = TRUE; + ret = gst_pad_set_caps (mix->srcpad, caps); + + if (ret) + ret = gst_gl_mixer_do_bufferpool (mix, caps); done: + priv->negotiated = ret; return ret; } @@ -1243,6 +1420,8 @@ gst_gl_mixer_process_buffers (GstGLMixer * mix, GstBuffer * outbuf) GSList *walk = mix->sinkpads; gint array_index = 0; + GST_TRACE ("Processing buffers"); + while (walk) { /* We walk with this list because it's ordered */ GstGLMixerPad *pad = GST_GL_MIXER_PAD (walk->data); GstGLMixerCollect *mixcol = pad->mixcol; @@ -1401,14 +1580,23 @@ gst_gl_mixer_collected (GstCollectPads * pads, GstGLMixer * mix) jitter = gst_gl_mixer_do_qos (mix, output_start_time); if (jitter <= 0) { - /* FIXME: Use GstGLMeta */ - /* Calculating out buffer size from input size */ - /*ret = gst_gl_buffer_parse_caps (GST_PAD_CAPS (mix->srcpad), &width, &height); - gl_outbuf = gst_gl_buffer_new (mix->display, mix->width, mix->height); + if (!mix->priv->pool_active) { + if (!gst_buffer_pool_set_active (mix->priv->pool, TRUE)) { + GST_ELEMENT_ERROR (mix, RESOURCE, SETTINGS, + ("failed to activate bufferpool"), + ("failed to activate bufferpool")); + ret = GST_FLOW_ERROR; + goto error; + } + mix->priv->pool_active = TRUE; + } + + ret = gst_buffer_pool_acquire_buffer (mix->priv->pool, &outbuf, NULL); - outbuf = GST_BUFFER (gl_outbuf); - gst_buffer_set_caps (outbuf, GST_PAD_CAPS (mix->srcpad)); */ + gst_buffer_add_video_meta (outbuf, 0, GST_VIDEO_INFO_FORMAT (&mix->info), + GST_VIDEO_INFO_WIDTH (&mix->info), GST_VIDEO_INFO_HEIGHT (&mix->info)); + gst_buffer_add_gl_meta (outbuf, mix->display); gst_gl_mixer_process_buffers (mix, outbuf); mix->qos_processed++; diff --git a/gst-libs/gst/gl/gstglmixer.h b/gst-libs/gst/gl/gstglmixer.h index 47f1402..5823c6e 100644 --- a/gst-libs/gst/gl/gstglmixer.h +++ b/gst-libs/gst/gl/gstglmixer.h @@ -25,6 +25,8 @@ #include #include "gstglmixerpad.h" +#include "gstglbufferpool.h" + G_BEGIN_DECLS #define GST_TYPE_GL_MIXER (gst_gl_mixer_get_type()) @@ -41,6 +43,7 @@ G_BEGIN_DECLS typedef struct _GstGLMixer GstGLMixer; typedef struct _GstGLMixerClass GstGLMixerClass; +typedef struct _GstGLMixerPrivate GstGLMixerPrivate; typedef gboolean (*GstGLMixerSetCaps) (GstGLMixer* mixer, GstCaps* outcaps); @@ -52,6 +55,8 @@ struct _GstGLMixer { GstElement element; + GstGLMixerPrivate *priv; + /* pad */ GstPad *srcpad; -- 2.7.4