+2007-06-06 Tim-Philipp Müller <tim at centricular dot net>
+
+ * libs/gst/base/gstdataqueue.c:
+ * libs/gst/base/gstdataqueue.h:
+ * plugins/elements/gstmultiqueue.c: (gst_single_queue_push_one),
+ (gst_multi_queue_item_new), (gst_multi_queue_chain),
+ (gst_multi_queue_sink_event):
+ * tests/check/elements/multiqueue.c: (multiqueue_suite):
+ Fix multiqueue leaking buffers and events when downstream or the
+ queue are flushing. Make refcounting assumptions explicit and
+ document them (shouldn't break existing code that uses it other than
+ maybe leak miniobjects, but that already happens anyway). Add unit
+ test for the most common flushing case. Fixes #423700.
+
2007-06-06 Sebastian Dröge <slomo@circular-chaos.org>
* libs/gst/controller/gstcontroller.c:
* available, OR the @queue is set to flushing state.
* MT safe.
*
+ * Note that this function has slightly different semantics than gst_pad_push()
+ * and gst_pad_push_event(): this function only takes ownership of @item and
+ * the #GstMiniObject contained in @item if the push was successful. If FALSE
+ * is returned, the caller is responsible for freeing @item and its contents.
+ *
* Returns: #TRUE if the @item was successfully pushed on the @queue.
*/
gboolean
* @duration: the duration in #GstClockTime of the miniobject. Can not be
* #GST_CLOCK_TIME_NONE.
* @visible: #TRUE if @object should be considered as a visible object.
- * @destroy: The #GDestroyNotify to use to free the #GstDataQueueItem.
+ * @destroy: The #GDestroyNotify function to use to free the #GstDataQueueItem.
+ * This function should also drop the reference to @object the owner of the
+ * #GstDataQueueItem is assumed to hold.
*
* Structure used by #GstDataQueue. You can supply a different structure, as
* long as the top of the structure is identical to this structure.
GstMiniObject * object)
{
if (GST_IS_BUFFER (object)) {
- sq->srcresult = gst_pad_push (sq->srcpad, GST_BUFFER (object));
+ GstBuffer *buf;
+
+ buf = gst_buffer_ref (GST_BUFFER_CAST (object));
+ sq->srcresult = gst_pad_push (sq->srcpad, buf);
if ((sq->srcresult != GST_FLOW_OK)
&& (sq->srcresult != GST_FLOW_NOT_LINKED)) {
gst_pad_pause_task (sq->srcpad);
}
} else if (GST_IS_EVENT (object)) {
- if (GST_EVENT_TYPE (object) == GST_EVENT_EOS) {
+ GstEvent *event;
+
+ event = gst_event_ref (GST_EVENT_CAST (object));
+ if (GST_EVENT_TYPE (event) == GST_EVENT_EOS) {
sq->srcresult = GST_FLOW_UNEXPECTED;
GST_DEBUG_OBJECT (mq, "GstSingleQueue %d : pausing queue, got EOS",
gst_data_queue_set_flushing (sq->queue, TRUE);
gst_pad_pause_task (sq->srcpad);
}
- gst_pad_push_event (sq->srcpad, GST_EVENT (object));
+ gst_pad_push_event (sq->srcpad, event);
} else {
g_warning ("Unexpected object in singlequeue %d (refcounting problem?)",
sq->id);
g_free (item);
}
+/* takes ownership of passed mini object! */
static GstMultiQueueItem *
gst_multi_queue_item_new (GstMiniObject * object)
{
GstMultiQueueItem *item;
item = g_new0 (GstMultiQueueItem, 1);
- item->object = gst_mini_object_ref (object);
+ item->object = object;
item->destroy = (GDestroyNotify) gst_multi_queue_item_destroy;
if (GST_IS_BUFFER (object)) {
GST_LOG_OBJECT (mq, "SingleQueue %d : exit because task paused, reason: %s",
sq->id, gst_flow_get_name (sq->srcresult));
gst_multi_queue_item_destroy (item);
- gst_buffer_unref (buffer);
ret = sq->srcresult;
}
GST_LOG_OBJECT (mq, "SingleQueue %d : exit because task paused, reason: %s",
sq->id, gst_flow_get_name (sq->srcresult));
gst_multi_queue_item_destroy (item);
- gst_event_unref (event);
}
done:
suite_add_tcase (s, tc_chain);
tcase_add_test (tc_chain, test_simple_create_destroy);
tcase_add_test (tc_chain, test_simple_pipeline);
-
- if (0) {
- /* FIXME: this leaks buffers, disabled for now */
- tcase_add_test (tc_chain, test_simple_shutdown_while_running);
- }
+ tcase_add_test (tc_chain, test_simple_shutdown_while_running);
/* FIXME: test_request_pads() needs some more fixes, see comments there */
tcase_add_test (tc_chain, test_request_pads);