From 6939f83e7512ef856ea5f308e1ac594d3d6d6732 Mon Sep 17 00:00:00 2001 From: Wim Taymans <wim.taymans@gmail.com> Date: Fri, 28 Jul 2006 14:09:10 +0000 Subject: [PATCH] libs/gst/base/gstcollectpads.c: When flushing a pad, also clear the queued buffer so that we don't accidentally use i... Original commit message from CVS: * libs/gst/base/gstcollectpads.c: (gst_collect_pads_set_flushing_unlocked), (gst_collect_pads_pop), (gst_collect_pads_clear), (gst_collect_pads_flush), (gst_collect_pads_event), (gst_collect_pads_chain): When flushing a pad, also clear the queued buffer so that we don't accidentally use it when we shouldn't. Fix leaks by inreffing incomming buffer. Flush out queued buffers in case of errors. Fixes #347452. --- ChangeLog | 12 +++++++ libs/gst/base/gstcollectpads.c | 57 +++++++++++++++++++++------------- 2 files changed, 48 insertions(+), 21 deletions(-) diff --git a/ChangeLog b/ChangeLog index c6557c55b9..d9b0bb2b77 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2006-07-28 Wim Taymans <wim@fluendo.com> + + * libs/gst/base/gstcollectpads.c: + (gst_collect_pads_set_flushing_unlocked), (gst_collect_pads_pop), + (gst_collect_pads_clear), (gst_collect_pads_flush), + (gst_collect_pads_event), (gst_collect_pads_chain): + When flushing a pad, also clear the queued buffer so that we don't + accidentally use it when we shouldn't. + Fix leaks by inreffing incomming buffer. + Flush out queued buffers in case of errors. + Fixes #347452. + 2006-07-28 Wim Taymans <wim@fluendo.com> * docs/random/phonon-gst: diff --git a/libs/gst/base/gstcollectpads.c b/libs/gst/base/gstcollectpads.c index 702518e72c..b8c36a94db 100644 --- a/libs/gst/base/gstcollectpads.c +++ b/libs/gst/base/gstcollectpads.c @@ -79,6 +79,8 @@ GST_DEBUG_CATEGORY_STATIC (collect_pads_debug); GST_BOILERPLATE (GstCollectPads, gst_collect_pads, GstObject, GST_TYPE_OBJECT); +static void gst_collect_pads_clear (GstCollectPads * pads, + GstCollectData * data); static GstFlowReturn gst_collect_pads_chain (GstPad * pad, GstBuffer * buffer); static gboolean gst_collect_pads_event (GstPad * pad, GstEvent * event); static void gst_collect_pads_finalize (GObject * object); @@ -417,6 +419,7 @@ gst_collect_pads_set_flushing_unlocked (GstCollectPads * pads, else GST_PAD_UNSET_FLUSHING (cdata->pad); cdata->abidata.ABI.flushing = flushing; + gst_collect_pads_clear (pads, cdata); GST_OBJECT_UNLOCK (cdata->pad); } } @@ -590,15 +593,13 @@ GstBuffer * gst_collect_pads_pop (GstCollectPads * pads, GstCollectData * data) { GstBuffer *result; - GstBuffer **buffer_p; g_return_val_if_fail (pads != NULL, NULL); g_return_val_if_fail (GST_IS_COLLECT_PADS (pads), NULL); g_return_val_if_fail (data != NULL, NULL); if ((result = data->buffer)) { - buffer_p = &data->buffer; - gst_buffer_replace (buffer_p, NULL); + data->buffer = NULL; data->pos = 0; /* one less pad with queued data now */ pads->queuedpads--; @@ -612,6 +613,17 @@ gst_collect_pads_pop (GstCollectPads * pads, GstCollectData * data) return result; } +/* pop and unref the currently queued buffer, should e called with the LOCK + * helt. */ +static void +gst_collect_pads_clear (GstCollectPads * pads, GstCollectData * data) +{ + GstBuffer *buf; + + if ((buf = gst_collect_pads_pop (pads, data))) + gst_buffer_unref (buf); +} + /** * gst_collect_pads_available: * @pads: the collectspads to query @@ -755,13 +767,9 @@ gst_collect_pads_flush (GstCollectPads * pads, GstCollectData * data, data->pos += size; - if (data->pos >= GST_BUFFER_SIZE (buffer)) { - GstBuffer *buf; - - /* _pop will also reset data->pos to 0 */ - buf = gst_collect_pads_pop (pads, data); - gst_buffer_unref (buf); - } + if (data->pos >= GST_BUFFER_SIZE (buffer)) + /* _clear will also reset data->pos to 0 */ + gst_collect_pads_clear (pads, data); return flushsize; } @@ -894,7 +902,7 @@ gst_collect_pads_event (GstPad * pad, GstEvent * event) * non-flushing block again */ GST_OBJECT_LOCK (pads); data->abidata.ABI.flushing = TRUE; - GST_COLLECT_PADS_BROADCAST (pads); + gst_collect_pads_clear (pads, data); GST_OBJECT_UNLOCK (pads); /* event already cleaned up by forwarding */ @@ -905,7 +913,7 @@ gst_collect_pads_event (GstPad * pad, GstEvent * event) /* flush the 1 buffer queue */ GST_OBJECT_LOCK (pads); data->abidata.ABI.flushing = FALSE; - gst_collect_pads_pop (pads, data); + gst_collect_pads_clear (pads, data); /* we need new segment info after the flush */ gst_segment_init (&data->segment, GST_FORMAT_UNDEFINED); data->abidata.ABI.new_segment = FALSE; @@ -1079,8 +1087,12 @@ gst_collect_pads_chain (GstPad * pad, GstBuffer * buffer) } while (data->buffer != NULL); +unlock_done: GST_OBJECT_UNLOCK (pads); +done: + gst_buffer_unref (buffer); + return ret; /* ERRORS */ @@ -1088,34 +1100,37 @@ not_ours: { /* pretty fatal this one, can't post an error though... */ GST_WARNING ("not our pad"); - return GST_FLOW_ERROR; + ret = GST_FLOW_ERROR; + goto done; } not_started: { - GST_OBJECT_UNLOCK (pads); GST_DEBUG ("not started"); - return GST_FLOW_WRONG_STATE; + gst_collect_pads_clear (pads, data); + ret = GST_FLOW_WRONG_STATE; + goto unlock_done; } flushing: { - GST_OBJECT_UNLOCK (pads); GST_DEBUG ("pad %s:%s is flushing", GST_DEBUG_PAD_NAME (pad)); - return GST_FLOW_WRONG_STATE; + gst_collect_pads_clear (pads, data); + ret = GST_FLOW_WRONG_STATE; + goto unlock_done; } unexpected: { - GST_OBJECT_UNLOCK (pads); /* we should not post an error for this, just inform upstream that * we don't expect anything anymore */ GST_DEBUG ("pad %s:%s is eos", GST_DEBUG_PAD_NAME (pad)); - return GST_FLOW_UNEXPECTED; + ret = GST_FLOW_UNEXPECTED; + goto unlock_done; } error: { - GST_OBJECT_UNLOCK (pads); /* we print the error, the element should post a reasonable error * message for fatal errors */ GST_DEBUG ("collect failed, reason %d (%s)", ret, gst_flow_get_name (ret)); - return ret; + gst_collect_pads_clear (pads, data); + goto unlock_done; } }