glmixer: don't hold the object lock while calling into GL

Doing so can deadlock between the GL thread and the object lock e.g.
when performing reconfigure events in glimagesink on a resize event.

https://bugzilla.gnome.org/show_bug.cgi?id=760559
This commit is contained in:
Matthew Waters 2016-01-13 14:41:22 +11:00 committed by Tim-Philipp Müller
parent 745071b5bf
commit 03fdd2fc82

View file

@ -599,46 +599,30 @@ context_error:
} }
} }
gboolean static gboolean
gst_gl_mixer_process_textures (GstGLMixer * mix, GstBuffer * outbuf) _upload_frames (GstAggregator * agg, GstAggregatorPad * agg_pad,
gpointer user_data)
{ {
guint i; GstVideoAggregatorPad *vaggpad = GST_VIDEO_AGGREGATOR_PAD (agg_pad);
GList *walk; GstGLMixerPad *pad = GST_GL_MIXER_PAD (agg_pad);
guint out_tex; GstElement *element = GST_ELEMENT (agg);
gboolean res = TRUE; GstGLMixer *mix = GST_GL_MIXER (agg);
guint array_index = 0; GstGLMixerFrameData *frame;
GstVideoFrame out_frame; guint *array_index, i;
GstElement *element = GST_ELEMENT (mix);
GstVideoAggregator *vagg = GST_VIDEO_AGGREGATOR (mix);
GstGLMixerClass *mix_class = GST_GL_MIXER_GET_CLASS (mix);
GstGLMixerPrivate *priv = mix->priv;
GST_TRACE ("Processing buffers"); array_index = (guint *) user_data;
if (!gst_video_frame_map (&out_frame, &vagg->info, outbuf,
GST_MAP_WRITE | GST_MAP_GL)) {
return FALSE;
}
out_tex = *(guint *) out_frame.data[0];
GST_OBJECT_LOCK (mix);
walk = element->sinkpads;
GST_OBJECT_LOCK (agg);
/* make sure the frames array is big enough */
i = mix->frames->len; i = mix->frames->len;
g_ptr_array_set_size (mix->frames, element->numsinkpads); g_ptr_array_set_size (mix->frames, element->numsinkpads);
for (; i < element->numsinkpads; i++) for (; i < element->numsinkpads; i++)
mix->frames->pdata[i] = g_slice_new0 (GstGLMixerFrameData); mix->frames->pdata[i] = g_new0 (GstGLMixerFrameData, 1);
while (walk) {
GstGLMixerPad *pad = GST_GL_MIXER_PAD (walk->data);
GstVideoAggregatorPad *vaggpad = walk->data;
GstGLMixerFrameData *frame;
frame = g_ptr_array_index (mix->frames, array_index); frame = g_ptr_array_index (mix->frames, *array_index);
frame->pad = pad; frame->pad = pad;
frame->texture = 0; frame->texture = 0;
GST_OBJECT_UNLOCK (agg);
walk = g_list_next (walk);
if (vaggpad->buffer != NULL) { if (vaggpad->buffer != NULL) {
GstVideoInfo gl_info; GstVideoInfo gl_info;
@ -654,16 +638,45 @@ gst_gl_mixer_process_textures (GstGLMixer * mix, GstBuffer * outbuf)
if (sync_meta) if (sync_meta)
gst_gl_sync_meta_wait (sync_meta, GST_GL_BASE_MIXER (mix)->context); gst_gl_sync_meta_wait (sync_meta, GST_GL_BASE_MIXER (mix)->context);
if (gst_video_frame_map (&gl_frame, &gl_info, vaggpad->buffer, if (!gst_video_frame_map (&gl_frame, &gl_info, vaggpad->buffer,
GST_MAP_READ | GST_MAP_GL)) { GST_MAP_READ | GST_MAP_GL)) {
GST_ERROR_OBJECT (agg_pad, "Failed to map input frame");
return FALSE;
}
frame->texture = *(guint *) gl_frame.data[0]; frame->texture = *(guint *) gl_frame.data[0];
gst_video_frame_unmap (&gl_frame); gst_video_frame_unmap (&gl_frame);
} }
(*array_index)++;
return TRUE;
} }
++array_index; gboolean
gst_gl_mixer_process_textures (GstGLMixer * mix, GstBuffer * outbuf)
{
guint out_tex;
gboolean res = TRUE;
guint array_index = 0;
GstVideoFrame out_frame;
GstVideoAggregator *vagg = GST_VIDEO_AGGREGATOR (mix);
GstGLMixerClass *mix_class = GST_GL_MIXER_GET_CLASS (mix);
GstGLMixerPrivate *priv = mix->priv;
GST_TRACE ("Processing buffers");
if (!gst_video_frame_map (&out_frame, &vagg->info, outbuf,
GST_MAP_WRITE | GST_MAP_GL)) {
return FALSE;
} }
out_tex = *(guint *) out_frame.data[0];
if (!gst_aggregator_iterate_sinkpads (GST_AGGREGATOR (mix),
(GstAggregatorPadForeachFunc) _upload_frames, &array_index))
return FALSE;
g_mutex_lock (&priv->gl_resource_lock); g_mutex_lock (&priv->gl_resource_lock);
if (!priv->gl_resource_ready) if (!priv->gl_resource_ready)
g_cond_wait (&priv->gl_resource_cond, &priv->gl_resource_lock); g_cond_wait (&priv->gl_resource_cond, &priv->gl_resource_lock);
@ -681,8 +694,6 @@ gst_gl_mixer_process_textures (GstGLMixer * mix, GstBuffer * outbuf)
g_mutex_unlock (&priv->gl_resource_lock); g_mutex_unlock (&priv->gl_resource_lock);
out: out:
GST_OBJECT_UNLOCK (mix);
gst_video_frame_unmap (&out_frame); gst_video_frame_unmap (&out_frame);
return res; return res;
@ -701,7 +712,7 @@ gst_gl_mixer_process_buffers (GstGLMixer * mix, GstBuffer * outbuf)
i = mix->frames->len; i = mix->frames->len;
g_ptr_array_set_size (mix->frames, element->numsinkpads); g_ptr_array_set_size (mix->frames, element->numsinkpads);
for (; i < element->numsinkpads; i++) for (; i < element->numsinkpads; i++)
mix->frames->pdata[i] = g_slice_new0 (GstGLMixerFrameData); mix->frames->pdata[i] = g_new0 (GstGLMixerFrameData, 1);
while (walk) { /* We walk with this list because it's ordered */ while (walk) { /* We walk with this list because it's ordered */
GstVideoAggregatorPad *vaggpad = walk->data; GstVideoAggregatorPad *vaggpad = walk->data;
@ -761,12 +772,6 @@ gst_gl_mixer_set_property (GObject * object,
} }
} }
static void
_free_glmixer_frame_data (GstGLMixerFrameData * frame)
{
g_slice_free1 (sizeof (GstGLMixerFrameData), frame);
}
static gboolean static gboolean
gst_gl_mixer_start (GstAggregator * agg) gst_gl_mixer_start (GstAggregator * agg)
{ {
@ -777,13 +782,13 @@ gst_gl_mixer_start (GstAggregator * agg)
GST_OBJECT_LOCK (mix); GST_OBJECT_LOCK (mix);
mix->array_buffers = g_ptr_array_new_full (element->numsinkpads, NULL); mix->array_buffers = g_ptr_array_new_full (element->numsinkpads, NULL);
mix->frames = g_ptr_array_new_full (element->numsinkpads, mix->frames = g_ptr_array_new_full (element->numsinkpads,
(GDestroyNotify) _free_glmixer_frame_data); (GDestroyNotify) g_free);
g_ptr_array_set_size (mix->array_buffers, element->numsinkpads); g_ptr_array_set_size (mix->array_buffers, element->numsinkpads);
g_ptr_array_set_size (mix->frames, element->numsinkpads); g_ptr_array_set_size (mix->frames, element->numsinkpads);
for (i = 0; i < element->numsinkpads; i++) for (i = 0; i < element->numsinkpads; i++)
mix->frames->pdata[i] = g_slice_new0 (GstGLMixerFrameData); mix->frames->pdata[i] = g_new0 (GstGLMixerFrameData, 1);
GST_OBJECT_UNLOCK (mix); GST_OBJECT_UNLOCK (mix);