ghostpad: Fix pad callbacks so they handle when parent goes away

1) We need to lock and get a strong ref to the parent, if still there.
2) If it has gone away, we need to handle that gracefully.

This is necessary in order to safely modify a running pipeline. Has been
observed when a streaming thread is doing a buffer_alloc() while an
application thread sends an event on a pad further downstream, and from
within a pad probe (holding STREAM_LOCK) carries out the pipeline plumbing
while the streaming thread has its buffer_alloc() in progress.
This commit is contained in:
Ole André Vadla Ravnås 2011-01-06 18:11:31 +01:00 committed by Sebastian Dröge
parent b2e6870edc
commit 7dd38cdcf4

View file

@ -73,6 +73,7 @@ struct _GstProxyPadPrivate
G_DEFINE_TYPE (GstProxyPad, gst_proxy_pad, GST_TYPE_PAD);
static GstPad *gst_proxy_pad_get_target (GstPad * pad);
static GstPad *gst_proxy_pad_get_internal (GstPad * pad);
static void gst_proxy_pad_dispose (GObject * object);
static void gst_proxy_pad_finalize (GObject * object);
@ -107,9 +108,12 @@ static gboolean
gst_proxy_pad_do_event (GstPad * pad, GstEvent * event)
{
gboolean res = FALSE;
GstPad *internal = GST_PROXY_PAD_INTERNAL (pad);
GstPad *internal = gst_proxy_pad_get_internal (pad);
res = gst_pad_push_event (internal, event);
if (internal) {
res = gst_pad_push_event (internal, event);
gst_object_unref (internal);
}
return res;
}
@ -147,10 +151,13 @@ static GstFlowReturn
gst_proxy_pad_do_bufferalloc (GstPad * pad, guint64 offset, guint size,
GstCaps * caps, GstBuffer ** buf)
{
GstFlowReturn result;
GstPad *internal = GST_PROXY_PAD_INTERNAL (pad);
GstFlowReturn result = GST_FLOW_WRONG_STATE;
GstPad *internal = gst_proxy_pad_get_internal (pad);
result = gst_pad_alloc_buffer (internal, offset, size, caps, buf);
if (internal) {
result = gst_pad_alloc_buffer (internal, offset, size, caps, buf);
gst_object_unref (internal);
}
return result;
}
@ -357,6 +364,20 @@ gst_proxy_pad_get_target (GstPad * pad)
return target;
}
static GstPad *
gst_proxy_pad_get_internal (GstPad * pad)
{
GstPad *internal;
GST_PROXY_LOCK (pad);
internal = GST_PROXY_PAD_INTERNAL (pad);
if (internal)
gst_object_ref (internal);
GST_PROXY_UNLOCK (pad);
return internal;
}
static void
gst_proxy_pad_do_unlink (GstPad * pad)
{