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.
This commit is contained in:
Wim Taymans 2005-10-27 13:47:33 +00:00
parent 7f22710f65
commit 67b27a2c01
5 changed files with 208 additions and 80 deletions

View file

@ -1,3 +1,15 @@
2005-10-27 Wim Taymans <wim@fluendo.com>
* 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 <wim@fluendo.com>
* gst/base/gstbasesink.c: (gst_base_sink_handle_object),

View file

@ -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);

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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);