From 6a7ccd6f3e96ab3b556cec275f2fe83999360e60 Mon Sep 17 00:00:00 2001 From: Matthew Waters Date: Thu, 12 Jun 2014 12:14:35 +1000 Subject: [PATCH] glmixer: lock the size of mix->frames to the number of pads Fixes a segfault with decodebin ! glmixer where the request pads on both sides were being requested after the state change to PAUSED. Also fixes dynamically adding and removing pads while glmixer is in a state >= PAUSED. --- gst-libs/gst/gl/gstglmixer.c | 117 +++++++++++++++++------------------ 1 file changed, 58 insertions(+), 59 deletions(-) diff --git a/gst-libs/gst/gl/gstglmixer.c b/gst-libs/gst/gl/gstglmixer.c index ef828e078c..c12fc218ea 100644 --- a/gst-libs/gst/gl/gstglmixer.c +++ b/gst-libs/gst/gl/gstglmixer.c @@ -715,6 +715,12 @@ gst_gl_mixer_reset (GstGLMixer * mix) priv->negotiated = FALSE; } +static void +_free_pad_frame_data (gpointer data) +{ + g_slice_free1 (sizeof (GstGLMixerFrameData), data); +} + static void gst_gl_mixer_init (GstGLMixer * mix) { @@ -751,6 +757,9 @@ gst_gl_mixer_init (GstGLMixer * mix) mix->fbo = 0; mix->depthbuffer = 0; + mix->frames = g_ptr_array_new_full (4, _free_pad_frame_data); + mix->array_buffers = g_ptr_array_new_full (4, NULL); + /* initialize variables */ gst_gl_mixer_reset (mix); } @@ -763,6 +772,9 @@ gst_gl_mixer_finalize (GObject * object) gst_object_unref (mix->collect); g_mutex_clear (&mix->lock); + g_ptr_array_free (mix->frames, TRUE); + g_ptr_array_free (mix->array_buffers, TRUE); + G_OBJECT_CLASS (parent_class)->finalize (object); } @@ -1354,50 +1366,47 @@ gst_gl_mixer_request_new_pad (GstElement * element, GstGLMixer *mix; GstGLMixerPad *mixpad; GstElementClass *klass = GST_ELEMENT_GET_CLASS (element); + gint serial = 0; + gchar *name = NULL; + GstGLMixerCollect *mixcol = NULL; mix = GST_GL_MIXER (element); - if (templ == gst_element_class_get_pad_template (klass, "sink_%d")) { - gint serial = 0; - gchar *name = NULL; - GstGLMixerCollect *mixcol = NULL; - - GST_GL_MIXER_LOCK (mix); - if (req_name == NULL || strlen (req_name) < 6 - || !g_str_has_prefix (req_name, "sink_")) { - /* no name given when requesting the pad, use next available int */ - serial = mix->next_sinkpad++; - } else { - /* parse serial number from requested padname */ - serial = g_ascii_strtoull (&req_name[5], NULL, 10); - if (serial >= mix->next_sinkpad) - mix->next_sinkpad = serial + 1; - } - /* create new pad with the name */ - name = g_strdup_printf ("sink_%d", serial); - mixpad = g_object_new (GST_TYPE_GL_MIXER_PAD, "name", name, "direction", - templ->direction, "template", templ, NULL); - g_free (name); - - mixcol = (GstGLMixerCollect *) - gst_collect_pads_add_pad (mix->collect, GST_PAD (mixpad), - sizeof (GstGLMixerCollect), - (GstCollectDataDestroyNotify) gst_gl_mixer_collect_free, TRUE); - - /* Keep track of each other */ - mixcol->mixpad = mixpad; - mixpad->mixcol = mixcol; - - mixcol->start_time = -1; - mixcol->end_time = -1; - - /* Keep an internal list of mixpads for zordering */ - mix->sinkpads = g_slist_append (mix->sinkpads, mixpad); - mix->numpads++; - GST_GL_MIXER_UNLOCK (mix); - } else { + if (templ != gst_element_class_get_pad_template (klass, "sink_%d")) return NULL; + + GST_GL_MIXER_LOCK (mix); + if (req_name == NULL || strlen (req_name) < 6 + || !g_str_has_prefix (req_name, "sink_")) { + /* no name given when requesting the pad, use next available int */ + serial = mix->next_sinkpad++; + } else { + /* parse serial number from requested padname */ + serial = g_ascii_strtoull (&req_name[5], NULL, 10); + if (serial >= mix->next_sinkpad) + mix->next_sinkpad = serial + 1; } + /* create new pad with the name */ + name = g_strdup_printf ("sink_%d", serial); + mixpad = g_object_new (GST_TYPE_GL_MIXER_PAD, "name", name, "direction", + templ->direction, "template", templ, NULL); + g_free (name); + + mixcol = (GstGLMixerCollect *) + gst_collect_pads_add_pad (mix->collect, GST_PAD (mixpad), + sizeof (GstGLMixerCollect), + (GstCollectDataDestroyNotify) gst_gl_mixer_collect_free, TRUE); + + /* Keep track of each other */ + mixcol->mixpad = mixpad; + mixpad->mixcol = mixcol; + + mixcol->start_time = -1; + mixcol->end_time = -1; + + /* Keep an internal list of mixpads for zordering */ + mix->sinkpads = g_slist_append (mix->sinkpads, mixpad); + mix->numpads++; GST_DEBUG_OBJECT (element, "Adding pad %s", GST_PAD_NAME (mixpad)); @@ -1406,6 +1415,13 @@ gst_gl_mixer_request_new_pad (GstElement * element, gst_child_proxy_child_added (GST_CHILD_PROXY (mix), G_OBJECT (mixpad), GST_OBJECT_NAME (mixpad)); + g_ptr_array_set_size (mix->array_buffers, mix->numpads); + g_ptr_array_set_size (mix->frames, mix->numpads); + + mix->frames->pdata[mix->numpads - 1] = g_slice_new0 (GstGLMixerFrameData); + + GST_GL_MIXER_UNLOCK (mix); + return GST_PAD (mixpad); } @@ -1431,6 +1447,9 @@ gst_gl_mixer_release_pad (GstElement * element, GstPad * pad) GST_OBJECT_NAME (mixpad)); mix->numpads--; + g_ptr_array_set_size (mix->array_buffers, mix->numpads); + g_ptr_array_set_size (mix->frames, mix->numpads); + update_caps = GST_VIDEO_INFO_FORMAT (&mix->out_info) != GST_VIDEO_FORMAT_UNKNOWN; GST_GL_MIXER_UNLOCK (mix); @@ -2273,37 +2292,17 @@ gst_gl_mixer_change_state (GstElement * element, GstStateChange transition) switch (transition) { case GST_STATE_CHANGE_READY_TO_PAUSED: { - guint i; - - mix->array_buffers = g_ptr_array_new_full (mix->numpads, NULL); - mix->frames = g_ptr_array_new_full (mix->numpads, NULL); - - g_ptr_array_set_size (mix->array_buffers, mix->numpads); - g_ptr_array_set_size (mix->frames, mix->numpads); - - for (i = 0; i < mix->numpads; i++) { - mix->frames->pdata[i] = g_slice_new0 (GstGLMixerFrameData); - } - GST_LOG_OBJECT (mix, "starting collectpads"); gst_collect_pads_start (mix->collect); break; } case GST_STATE_CHANGE_PAUSED_TO_READY: { - guint i; GSList *walk = mix->sinkpads; GST_LOG_OBJECT (mix, "stopping collectpads"); gst_collect_pads_stop (mix->collect); - for (i = 0; i < mix->numpads; i++) { - g_slice_free1 (sizeof (GstGLMixerFrameData), mix->frames->pdata[i]); - } - - g_ptr_array_free (mix->array_buffers, TRUE); - g_ptr_array_free (mix->frames, TRUE); - if (mixer_class->reset) mixer_class->reset (mix); if (mix->fbo) {