base: 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 7dd38cdcf4
commit e7bf5484c7
2 changed files with 19 additions and 2 deletions

View file

@ -653,6 +653,8 @@ gst_base_sink_pad_buffer_alloc (GstPad * pad, guint64 offset, guint size,
GstFlowReturn result = GST_FLOW_OK; GstFlowReturn result = GST_FLOW_OK;
bsink = GST_BASE_SINK (gst_pad_get_parent (pad)); bsink = GST_BASE_SINK (gst_pad_get_parent (pad));
if (G_UNLIKELY (bsink == NULL))
return GST_FLOW_WRONG_STATE;
bclass = GST_BASE_SINK_GET_CLASS (bsink); bclass = GST_BASE_SINK_GET_CLASS (bsink);
if (bclass->buffer_alloc) if (bclass->buffer_alloc)
@ -3414,6 +3416,10 @@ gst_base_sink_event (GstPad * pad, GstEvent * event)
GstBaseSinkClass *bclass; GstBaseSinkClass *bclass;
basesink = GST_BASE_SINK (gst_pad_get_parent (pad)); basesink = GST_BASE_SINK (gst_pad_get_parent (pad));
if (G_UNLIKELY (basesink == NULL)) {
gst_event_unref (event);
return FALSE;
}
bclass = GST_BASE_SINK_GET_CLASS (basesink); bclass = GST_BASE_SINK_GET_CLASS (basesink);

View file

@ -1225,8 +1225,13 @@ static gboolean
gst_base_transform_query (GstPad * pad, GstQuery * query) gst_base_transform_query (GstPad * pad, GstQuery * query)
{ {
gboolean ret = FALSE; gboolean ret = FALSE;
GstBaseTransform *trans = GST_BASE_TRANSFORM (gst_pad_get_parent (pad)); GstBaseTransform *trans;
GstPad *otherpad = (pad == trans->srcpad) ? trans->sinkpad : trans->srcpad; GstPad *otherpad;
trans = GST_BASE_TRANSFORM (gst_pad_get_parent (pad));
if (G_UNLIKELY (trans == NULL))
return FALSE;
otherpad = (pad == trans->srcpad) ? trans->sinkpad : trans->srcpad;
switch (GST_QUERY_TYPE (query)) { switch (GST_QUERY_TYPE (query)) {
case GST_QUERY_POSITION:{ case GST_QUERY_POSITION:{
@ -1715,6 +1720,8 @@ gst_base_transform_buffer_alloc (GstPad * pad, guint64 offset, guint size,
guint size_suggest; guint size_suggest;
trans = GST_BASE_TRANSFORM (gst_pad_get_parent (pad)); trans = GST_BASE_TRANSFORM (gst_pad_get_parent (pad));
if (G_UNLIKELY (trans == NULL))
return GST_FLOW_WRONG_STATE;
klass = GST_BASE_TRANSFORM_GET_CLASS (trans); klass = GST_BASE_TRANSFORM_GET_CLASS (trans);
priv = trans->priv; priv = trans->priv;
@ -1997,6 +2004,10 @@ gst_base_transform_sink_event (GstPad * pad, GstEvent * event)
gboolean forward = TRUE; gboolean forward = TRUE;
trans = GST_BASE_TRANSFORM (gst_pad_get_parent (pad)); trans = GST_BASE_TRANSFORM (gst_pad_get_parent (pad));
if (G_UNLIKELY (trans == NULL)) {
gst_event_unref (event);
return FALSE;
}
bclass = GST_BASE_TRANSFORM_GET_CLASS (trans); bclass = GST_BASE_TRANSFORM_GET_CLASS (trans);
if (bclass->event) if (bclass->event)