From 67b27a2c01eec5a5ec71df3578327958f906c599 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Thu, 27 Oct 2005 13:47:33 +0000 Subject: [PATCH] check/gst/gstbin.c: An extra refcount is taken in basesrc. Original commit message from CVS: * check/gst/gstbin.c: (GST_START_TEST): An extra refcount is taken in basesrc. * gst/base/gstbasesrc.c: (gst_base_src_init), (gst_base_src_query), (gst_base_src_get_range), (gst_base_src_pad_get_range), (gst_base_src_loop): Small cleanups, check for flushing after being unlocked from the LIVE_LOCK. take refcounts correctly (not yet everywhere). Don't send out EOS when going to READY. --- ChangeLog | 12 ++++ check/gst/gstbin.c | 11 ++-- gst/base/gstbasesrc.c | 127 ++++++++++++++++++++++++++----------- libs/gst/base/gstbasesrc.c | 127 ++++++++++++++++++++++++++----------- tests/check/gst/gstbin.c | 11 ++-- 5 files changed, 208 insertions(+), 80 deletions(-) diff --git a/ChangeLog b/ChangeLog index 05d2533b08..cd9c067dc4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2005-10-27 Wim Taymans + + * check/gst/gstbin.c: (GST_START_TEST): + An extra refcount is taken in basesrc. + + * gst/base/gstbasesrc.c: (gst_base_src_init), (gst_base_src_query), + (gst_base_src_get_range), (gst_base_src_pad_get_range), + (gst_base_src_loop): + Small cleanups, check for flushing after being unlocked from the + LIVE_LOCK. take refcounts correctly (not yet everywhere). + Don't send out EOS when going to READY. + 2005-10-27 Wim Taymans * gst/base/gstbasesink.c: (gst_base_sink_handle_object), diff --git a/check/gst/gstbin.c b/check/gst/gstbin.c index e3f0667613..46b1fdde75 100644 --- a/check/gst/gstbin.c +++ b/check/gst/gstbin.c @@ -275,9 +275,10 @@ GST_START_TEST (test_message_state_changed_children) THREAD_SWITCH (); /* each object is referenced by a message; + * base_src is blocked in the push and has an extra refcount. * base_sink_chain has taken a refcount on the sink, and is blocked on * preroll */ - ASSERT_OBJECT_REFCOUNT (src, "src", 2); + ASSERT_OBJECT_REFCOUNT (src, "src", 3); ASSERT_OBJECT_REFCOUNT (sink, "sink", 3); ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 2); @@ -285,7 +286,7 @@ GST_START_TEST (test_message_state_changed_children) fail_if ((gst_bus_pop (bus)) != NULL); ASSERT_OBJECT_REFCOUNT (bus, "bus", 2); - ASSERT_OBJECT_REFCOUNT (src, "src", 1); + ASSERT_OBJECT_REFCOUNT (src, "src", 2); ASSERT_OBJECT_REFCOUNT (sink, "sink", 2); ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1); @@ -301,9 +302,10 @@ GST_START_TEST (test_message_state_changed_children) fail_unless (pending == GST_STATE_VOID_PENDING); /* each object is referenced by one message + * src might have an extra reference if it's still pushing * sink might have an extra reference if it's still blocked on preroll * pipeline posted a new-clock message too. */ - ASSERT_OBJECT_REFCOUNT (src, "src", 2); + ASSERT_OBJECT_REFCOUNT_BETWEEN (src, "src", 2, 3); ASSERT_OBJECT_REFCOUNT_BETWEEN (sink, "sink", 2, 3); ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 3); @@ -311,7 +313,8 @@ GST_START_TEST (test_message_state_changed_children) fail_if ((gst_bus_pop (bus)) != NULL); ASSERT_OBJECT_REFCOUNT (bus, "bus", 2); - ASSERT_OBJECT_REFCOUNT (src, "src", 1); + /* src might have an extra reference if it's still pushing */ + ASSERT_OBJECT_REFCOUNT_BETWEEN (src, "src", 1, 2); /* sink might have an extra reference if it's still blocked on preroll */ ASSERT_OBJECT_REFCOUNT_BETWEEN (sink, "sink", 1, 2); ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1); diff --git a/gst/base/gstbasesrc.c b/gst/base/gstbasesrc.c index 7abdfab45e..e690b9d134 100644 --- a/gst/base/gstbasesrc.c +++ b/gst/base/gstbasesrc.c @@ -129,7 +129,9 @@ static GstStateChangeReturn gst_base_src_change_state (GstElement * element, static void gst_base_src_loop (GstPad * pad); static gboolean gst_base_src_check_get_range (GstPad * pad); -static GstFlowReturn gst_base_src_get_range (GstPad * pad, guint64 offset, +static GstFlowReturn gst_base_src_pad_get_range (GstPad * pad, guint64 offset, + guint length, GstBuffer ** buf); +static GstFlowReturn gst_base_src_get_range (GstBaseSrc * src, guint64 offset, guint length, GstBuffer ** buf); static void @@ -203,7 +205,7 @@ gst_base_src_init (GstBaseSrc * basesrc, gpointer g_class) gst_pad_set_checkgetrange_function (pad, GST_DEBUG_FUNCPTR (gst_base_src_check_get_range)); gst_pad_set_getrange_function (pad, - GST_DEBUG_FUNCPTR (gst_base_src_get_range)); + GST_DEBUG_FUNCPTR (gst_base_src_pad_get_range)); gst_pad_set_getcaps_function (pad, GST_DEBUG_FUNCPTR (gst_base_src_getcaps)); gst_pad_set_setcaps_function (pad, GST_DEBUG_FUNCPTR (gst_base_src_setcaps)); @@ -316,12 +318,10 @@ gst_base_src_getcaps (GstPad * pad) static gboolean gst_base_src_query (GstPad * pad, GstQuery * query) { - gboolean b; - guint64 ui64; - gint64 i64; GstBaseSrc *src; + gboolean res; - src = GST_BASE_SRC (GST_PAD_PARENT (pad)); + src = GST_BASE_SRC (gst_pad_get_parent (pad)); switch (GST_QUERY_TYPE (query)) { case GST_QUERY_POSITION: @@ -333,18 +333,28 @@ gst_base_src_query (GstPad * pad, GstQuery * query) case GST_FORMAT_DEFAULT: case GST_FORMAT_BYTES: gst_query_set_position (query, GST_FORMAT_BYTES, src->offset); - return TRUE; + res = TRUE; + break; case GST_FORMAT_PERCENT: + { + gboolean b; + gint64 i64; + guint64 ui64; + b = gst_base_src_get_size (src, &ui64); if (b && src->offset > ui64) i64 = gst_util_uint64_scale (GST_FORMAT_PERCENT_MAX, src->offset, ui64); else i64 = GST_FORMAT_PERCENT_MAX; + gst_query_set_position (query, GST_FORMAT_PERCENT, i64); - return TRUE; + res = TRUE; + break; + } default: - return FALSE; + res = FALSE; + break; } } case GST_QUERY_DURATION: @@ -355,37 +365,52 @@ gst_base_src_query (GstPad * pad, GstQuery * query) switch (format) { case GST_FORMAT_DEFAULT: case GST_FORMAT_BYTES: + { + gboolean b; + gint64 i64; + guint64 ui64; + b = gst_base_src_get_size (src, &ui64); /* better to make get_size take an int64 */ i64 = b ? (gint64) ui64 : -1; gst_query_set_duration (query, GST_FORMAT_BYTES, i64); - return TRUE; + res = TRUE; + break; + } case GST_FORMAT_PERCENT: gst_query_set_duration (query, GST_FORMAT_PERCENT, GST_FORMAT_PERCENT_MAX); - return TRUE; + res = TRUE; + break; default: - return FALSE; + res = FALSE; + break; } } case GST_QUERY_SEEKING: gst_query_set_seeking (query, GST_FORMAT_BYTES, src->seekable, src->segment_start, src->segment_end); - return TRUE; + res = TRUE; + break; case GST_QUERY_FORMATS: gst_query_set_formats (query, 3, GST_FORMAT_DEFAULT, GST_FORMAT_BYTES, GST_FORMAT_PERCENT); - return TRUE; + res = TRUE; + break; case GST_QUERY_LATENCY: case GST_QUERY_JITTER: case GST_QUERY_RATE: case GST_QUERY_CONVERT: default: - return gst_pad_query_default (pad, query); + res = gst_pad_query_default (pad, query); + break; } + + gst_object_unref (src); + return res; } static gboolean @@ -611,14 +636,12 @@ gst_base_src_get_property (GObject * object, guint prop_id, GValue * value, } static GstFlowReturn -gst_base_src_get_range (GstPad * pad, guint64 offset, guint length, +gst_base_src_get_range (GstBaseSrc * src, guint64 offset, guint length, GstBuffer ** buf) { GstFlowReturn ret; - GstBaseSrc *src; GstBaseSrcClass *bclass; - src = GST_BASE_SRC (GST_OBJECT_PARENT (pad)); bclass = GST_BASE_SRC_GET_CLASS (src); GST_LIVE_LOCK (src); @@ -630,18 +653,18 @@ gst_base_src_get_range (GstPad * pad, guint64 offset, guint length, GST_LIVE_WAIT (src); GST_DEBUG ("live source unlocked"); } + /* FIXME, use another variable to signal stopping */ + GST_LOCK (src->srcpad); + if (GST_PAD_IS_FLUSHING (src->srcpad)) + goto flushing; + GST_UNLOCK (src->srcpad); } GST_LIVE_UNLOCK (src); - GST_LOCK (pad); - if (GST_PAD_IS_FLUSHING (pad)) - goto flushing; - GST_UNLOCK (pad); - if (!GST_OBJECT_FLAG_IS_SET (src, GST_BASE_SRC_STARTED)) goto not_started; - if (!bclass->create) + if (G_UNLIKELY (!bclass->create)) goto no_function; GST_DEBUG_OBJECT (src, @@ -680,7 +703,8 @@ gst_base_src_get_range (GstPad * pad, guint64 offset, guint length, flushing: { GST_DEBUG_OBJECT (src, "pad is flushing"); - GST_UNLOCK (pad); + GST_UNLOCK (src->srcpad); + GST_LIVE_UNLOCK (src); return GST_FLOW_WRONG_STATE; } not_started: @@ -706,6 +730,22 @@ reached_num_buffers: } } +static GstFlowReturn +gst_base_src_pad_get_range (GstPad * pad, guint64 offset, guint length, + GstBuffer ** buf) +{ + GstBaseSrc *src; + GstFlowReturn res; + + src = GST_BASE_SRC (gst_pad_get_parent (pad)); + + res = gst_base_src_get_range (src, offset, length, buf); + + gst_object_unref (src); + + return res; +} + static gboolean gst_base_src_check_get_range (GstPad * pad) { @@ -728,29 +768,34 @@ gst_base_src_loop (GstPad * pad) GstBuffer *buf = NULL; GstFlowReturn ret; - src = GST_BASE_SRC (GST_OBJECT_PARENT (pad)); + src = GST_BASE_SRC (gst_pad_get_parent (pad)); - if (src->need_newsegment) { + if (G_UNLIKELY (src->need_newsegment)) { /* now send newsegment */ gst_base_src_newsegment (src); src->need_newsegment = FALSE; } - ret = gst_base_src_get_range (pad, src->offset, src->blocksize, &buf); - if (ret != GST_FLOW_OK) - goto eos; - - if (buf == NULL) + ret = gst_base_src_get_range (src, src->offset, src->blocksize, &buf); + if (G_UNLIKELY (ret != GST_FLOW_OK)) { + if (ret == GST_FLOW_UNEXPECTED) + goto eos; + else + goto pause; + } + if (G_UNLIKELY (buf == NULL)) goto error; src->offset += GST_BUFFER_SIZE (buf); ret = gst_pad_push (pad, buf); - if (ret != GST_FLOW_OK) + if (G_UNLIKELY (ret != GST_FLOW_OK)) goto pause; + gst_object_unref (src); return; + /* special cases */ eos: { GST_DEBUG_OBJECT (src, "going to EOS"); @@ -759,21 +804,29 @@ eos: gst_element_post_message (GST_ELEMENT (src), gst_message_new_segment_done (GST_OBJECT (src), GST_FORMAT_BYTES, src->segment_end)); - } else + } else { gst_pad_push_event (pad, gst_event_new_eos ()); + } + + gst_object_unref (src); return; } pause: { - GST_DEBUG_OBJECT (src, "pausing task"); + const gchar *reason; + + reason = gst_flow_get_name (ret); + + GST_DEBUG_OBJECT (src, "pausing task, reason %s", reason); gst_pad_pause_task (pad); if (GST_FLOW_IS_FATAL (ret) || ret == GST_FLOW_NOT_LINKED) { /* for fatal errors we post an error message */ GST_ELEMENT_ERROR (src, STREAM, FAILED, (_("Internal data flow error.")), - ("streaming task paused, reason %s", gst_flow_get_name (ret))); + ("streaming task paused, reason %s", reason)); gst_pad_push_event (pad, gst_event_new_eos ()); } + gst_object_unref (src); return; } error: @@ -782,6 +835,8 @@ error: (_("Internal data flow error.")), ("element returned NULL buffer")); gst_pad_pause_task (pad); gst_pad_push_event (pad, gst_event_new_eos ()); + + gst_object_unref (src); return; } } diff --git a/libs/gst/base/gstbasesrc.c b/libs/gst/base/gstbasesrc.c index 7abdfab45e..e690b9d134 100644 --- a/libs/gst/base/gstbasesrc.c +++ b/libs/gst/base/gstbasesrc.c @@ -129,7 +129,9 @@ static GstStateChangeReturn gst_base_src_change_state (GstElement * element, static void gst_base_src_loop (GstPad * pad); static gboolean gst_base_src_check_get_range (GstPad * pad); -static GstFlowReturn gst_base_src_get_range (GstPad * pad, guint64 offset, +static GstFlowReturn gst_base_src_pad_get_range (GstPad * pad, guint64 offset, + guint length, GstBuffer ** buf); +static GstFlowReturn gst_base_src_get_range (GstBaseSrc * src, guint64 offset, guint length, GstBuffer ** buf); static void @@ -203,7 +205,7 @@ gst_base_src_init (GstBaseSrc * basesrc, gpointer g_class) gst_pad_set_checkgetrange_function (pad, GST_DEBUG_FUNCPTR (gst_base_src_check_get_range)); gst_pad_set_getrange_function (pad, - GST_DEBUG_FUNCPTR (gst_base_src_get_range)); + GST_DEBUG_FUNCPTR (gst_base_src_pad_get_range)); gst_pad_set_getcaps_function (pad, GST_DEBUG_FUNCPTR (gst_base_src_getcaps)); gst_pad_set_setcaps_function (pad, GST_DEBUG_FUNCPTR (gst_base_src_setcaps)); @@ -316,12 +318,10 @@ gst_base_src_getcaps (GstPad * pad) static gboolean gst_base_src_query (GstPad * pad, GstQuery * query) { - gboolean b; - guint64 ui64; - gint64 i64; GstBaseSrc *src; + gboolean res; - src = GST_BASE_SRC (GST_PAD_PARENT (pad)); + src = GST_BASE_SRC (gst_pad_get_parent (pad)); switch (GST_QUERY_TYPE (query)) { case GST_QUERY_POSITION: @@ -333,18 +333,28 @@ gst_base_src_query (GstPad * pad, GstQuery * query) case GST_FORMAT_DEFAULT: case GST_FORMAT_BYTES: gst_query_set_position (query, GST_FORMAT_BYTES, src->offset); - return TRUE; + res = TRUE; + break; case GST_FORMAT_PERCENT: + { + gboolean b; + gint64 i64; + guint64 ui64; + b = gst_base_src_get_size (src, &ui64); if (b && src->offset > ui64) i64 = gst_util_uint64_scale (GST_FORMAT_PERCENT_MAX, src->offset, ui64); else i64 = GST_FORMAT_PERCENT_MAX; + gst_query_set_position (query, GST_FORMAT_PERCENT, i64); - return TRUE; + res = TRUE; + break; + } default: - return FALSE; + res = FALSE; + break; } } case GST_QUERY_DURATION: @@ -355,37 +365,52 @@ gst_base_src_query (GstPad * pad, GstQuery * query) switch (format) { case GST_FORMAT_DEFAULT: case GST_FORMAT_BYTES: + { + gboolean b; + gint64 i64; + guint64 ui64; + b = gst_base_src_get_size (src, &ui64); /* better to make get_size take an int64 */ i64 = b ? (gint64) ui64 : -1; gst_query_set_duration (query, GST_FORMAT_BYTES, i64); - return TRUE; + res = TRUE; + break; + } case GST_FORMAT_PERCENT: gst_query_set_duration (query, GST_FORMAT_PERCENT, GST_FORMAT_PERCENT_MAX); - return TRUE; + res = TRUE; + break; default: - return FALSE; + res = FALSE; + break; } } case GST_QUERY_SEEKING: gst_query_set_seeking (query, GST_FORMAT_BYTES, src->seekable, src->segment_start, src->segment_end); - return TRUE; + res = TRUE; + break; case GST_QUERY_FORMATS: gst_query_set_formats (query, 3, GST_FORMAT_DEFAULT, GST_FORMAT_BYTES, GST_FORMAT_PERCENT); - return TRUE; + res = TRUE; + break; case GST_QUERY_LATENCY: case GST_QUERY_JITTER: case GST_QUERY_RATE: case GST_QUERY_CONVERT: default: - return gst_pad_query_default (pad, query); + res = gst_pad_query_default (pad, query); + break; } + + gst_object_unref (src); + return res; } static gboolean @@ -611,14 +636,12 @@ gst_base_src_get_property (GObject * object, guint prop_id, GValue * value, } static GstFlowReturn -gst_base_src_get_range (GstPad * pad, guint64 offset, guint length, +gst_base_src_get_range (GstBaseSrc * src, guint64 offset, guint length, GstBuffer ** buf) { GstFlowReturn ret; - GstBaseSrc *src; GstBaseSrcClass *bclass; - src = GST_BASE_SRC (GST_OBJECT_PARENT (pad)); bclass = GST_BASE_SRC_GET_CLASS (src); GST_LIVE_LOCK (src); @@ -630,18 +653,18 @@ gst_base_src_get_range (GstPad * pad, guint64 offset, guint length, GST_LIVE_WAIT (src); GST_DEBUG ("live source unlocked"); } + /* FIXME, use another variable to signal stopping */ + GST_LOCK (src->srcpad); + if (GST_PAD_IS_FLUSHING (src->srcpad)) + goto flushing; + GST_UNLOCK (src->srcpad); } GST_LIVE_UNLOCK (src); - GST_LOCK (pad); - if (GST_PAD_IS_FLUSHING (pad)) - goto flushing; - GST_UNLOCK (pad); - if (!GST_OBJECT_FLAG_IS_SET (src, GST_BASE_SRC_STARTED)) goto not_started; - if (!bclass->create) + if (G_UNLIKELY (!bclass->create)) goto no_function; GST_DEBUG_OBJECT (src, @@ -680,7 +703,8 @@ gst_base_src_get_range (GstPad * pad, guint64 offset, guint length, flushing: { GST_DEBUG_OBJECT (src, "pad is flushing"); - GST_UNLOCK (pad); + GST_UNLOCK (src->srcpad); + GST_LIVE_UNLOCK (src); return GST_FLOW_WRONG_STATE; } not_started: @@ -706,6 +730,22 @@ reached_num_buffers: } } +static GstFlowReturn +gst_base_src_pad_get_range (GstPad * pad, guint64 offset, guint length, + GstBuffer ** buf) +{ + GstBaseSrc *src; + GstFlowReturn res; + + src = GST_BASE_SRC (gst_pad_get_parent (pad)); + + res = gst_base_src_get_range (src, offset, length, buf); + + gst_object_unref (src); + + return res; +} + static gboolean gst_base_src_check_get_range (GstPad * pad) { @@ -728,29 +768,34 @@ gst_base_src_loop (GstPad * pad) GstBuffer *buf = NULL; GstFlowReturn ret; - src = GST_BASE_SRC (GST_OBJECT_PARENT (pad)); + src = GST_BASE_SRC (gst_pad_get_parent (pad)); - if (src->need_newsegment) { + if (G_UNLIKELY (src->need_newsegment)) { /* now send newsegment */ gst_base_src_newsegment (src); src->need_newsegment = FALSE; } - ret = gst_base_src_get_range (pad, src->offset, src->blocksize, &buf); - if (ret != GST_FLOW_OK) - goto eos; - - if (buf == NULL) + ret = gst_base_src_get_range (src, src->offset, src->blocksize, &buf); + if (G_UNLIKELY (ret != GST_FLOW_OK)) { + if (ret == GST_FLOW_UNEXPECTED) + goto eos; + else + goto pause; + } + if (G_UNLIKELY (buf == NULL)) goto error; src->offset += GST_BUFFER_SIZE (buf); ret = gst_pad_push (pad, buf); - if (ret != GST_FLOW_OK) + if (G_UNLIKELY (ret != GST_FLOW_OK)) goto pause; + gst_object_unref (src); return; + /* special cases */ eos: { GST_DEBUG_OBJECT (src, "going to EOS"); @@ -759,21 +804,29 @@ eos: gst_element_post_message (GST_ELEMENT (src), gst_message_new_segment_done (GST_OBJECT (src), GST_FORMAT_BYTES, src->segment_end)); - } else + } else { gst_pad_push_event (pad, gst_event_new_eos ()); + } + + gst_object_unref (src); return; } pause: { - GST_DEBUG_OBJECT (src, "pausing task"); + const gchar *reason; + + reason = gst_flow_get_name (ret); + + GST_DEBUG_OBJECT (src, "pausing task, reason %s", reason); gst_pad_pause_task (pad); if (GST_FLOW_IS_FATAL (ret) || ret == GST_FLOW_NOT_LINKED) { /* for fatal errors we post an error message */ GST_ELEMENT_ERROR (src, STREAM, FAILED, (_("Internal data flow error.")), - ("streaming task paused, reason %s", gst_flow_get_name (ret))); + ("streaming task paused, reason %s", reason)); gst_pad_push_event (pad, gst_event_new_eos ()); } + gst_object_unref (src); return; } error: @@ -782,6 +835,8 @@ error: (_("Internal data flow error.")), ("element returned NULL buffer")); gst_pad_pause_task (pad); gst_pad_push_event (pad, gst_event_new_eos ()); + + gst_object_unref (src); return; } } diff --git a/tests/check/gst/gstbin.c b/tests/check/gst/gstbin.c index e3f0667613..46b1fdde75 100644 --- a/tests/check/gst/gstbin.c +++ b/tests/check/gst/gstbin.c @@ -275,9 +275,10 @@ GST_START_TEST (test_message_state_changed_children) THREAD_SWITCH (); /* each object is referenced by a message; + * base_src is blocked in the push and has an extra refcount. * base_sink_chain has taken a refcount on the sink, and is blocked on * preroll */ - ASSERT_OBJECT_REFCOUNT (src, "src", 2); + ASSERT_OBJECT_REFCOUNT (src, "src", 3); ASSERT_OBJECT_REFCOUNT (sink, "sink", 3); ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 2); @@ -285,7 +286,7 @@ GST_START_TEST (test_message_state_changed_children) fail_if ((gst_bus_pop (bus)) != NULL); ASSERT_OBJECT_REFCOUNT (bus, "bus", 2); - ASSERT_OBJECT_REFCOUNT (src, "src", 1); + ASSERT_OBJECT_REFCOUNT (src, "src", 2); ASSERT_OBJECT_REFCOUNT (sink, "sink", 2); ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1); @@ -301,9 +302,10 @@ GST_START_TEST (test_message_state_changed_children) fail_unless (pending == GST_STATE_VOID_PENDING); /* each object is referenced by one message + * src might have an extra reference if it's still pushing * sink might have an extra reference if it's still blocked on preroll * pipeline posted a new-clock message too. */ - ASSERT_OBJECT_REFCOUNT (src, "src", 2); + ASSERT_OBJECT_REFCOUNT_BETWEEN (src, "src", 2, 3); ASSERT_OBJECT_REFCOUNT_BETWEEN (sink, "sink", 2, 3); ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 3); @@ -311,7 +313,8 @@ GST_START_TEST (test_message_state_changed_children) fail_if ((gst_bus_pop (bus)) != NULL); ASSERT_OBJECT_REFCOUNT (bus, "bus", 2); - ASSERT_OBJECT_REFCOUNT (src, "src", 1); + /* src might have an extra reference if it's still pushing */ + ASSERT_OBJECT_REFCOUNT_BETWEEN (src, "src", 1, 2); /* sink might have an extra reference if it's still blocked on preroll */ ASSERT_OBJECT_REFCOUNT_BETWEEN (sink, "sink", 1, 2); ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);