mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-06-07 16:08:51 +00:00
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:
parent
7f22710f65
commit
67b27a2c01
5 changed files with 208 additions and 80 deletions
12
ChangeLog
12
ChangeLog
|
@ -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>
|
2005-10-27 Wim Taymans <wim@fluendo.com>
|
||||||
|
|
||||||
* gst/base/gstbasesink.c: (gst_base_sink_handle_object),
|
* gst/base/gstbasesink.c: (gst_base_sink_handle_object),
|
||||||
|
|
|
@ -275,9 +275,10 @@ GST_START_TEST (test_message_state_changed_children)
|
||||||
THREAD_SWITCH ();
|
THREAD_SWITCH ();
|
||||||
|
|
||||||
/* each object is referenced by a message;
|
/* 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
|
* base_sink_chain has taken a refcount on the sink, and is blocked on
|
||||||
* preroll */
|
* preroll */
|
||||||
ASSERT_OBJECT_REFCOUNT (src, "src", 2);
|
ASSERT_OBJECT_REFCOUNT (src, "src", 3);
|
||||||
ASSERT_OBJECT_REFCOUNT (sink, "sink", 3);
|
ASSERT_OBJECT_REFCOUNT (sink, "sink", 3);
|
||||||
ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 2);
|
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);
|
fail_if ((gst_bus_pop (bus)) != NULL);
|
||||||
|
|
||||||
ASSERT_OBJECT_REFCOUNT (bus, "bus", 2);
|
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 (sink, "sink", 2);
|
||||||
ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
|
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);
|
fail_unless (pending == GST_STATE_VOID_PENDING);
|
||||||
|
|
||||||
/* each object is referenced by one message
|
/* 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
|
* sink might have an extra reference if it's still blocked on preroll
|
||||||
* pipeline posted a new-clock message too. */
|
* 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_BETWEEN (sink, "sink", 2, 3);
|
||||||
ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 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);
|
fail_if ((gst_bus_pop (bus)) != NULL);
|
||||||
|
|
||||||
ASSERT_OBJECT_REFCOUNT (bus, "bus", 2);
|
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 */
|
/* sink might have an extra reference if it's still blocked on preroll */
|
||||||
ASSERT_OBJECT_REFCOUNT_BETWEEN (sink, "sink", 1, 2);
|
ASSERT_OBJECT_REFCOUNT_BETWEEN (sink, "sink", 1, 2);
|
||||||
ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
|
ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
|
||||||
|
|
|
@ -129,7 +129,9 @@ static GstStateChangeReturn gst_base_src_change_state (GstElement * element,
|
||||||
|
|
||||||
static void gst_base_src_loop (GstPad * pad);
|
static void gst_base_src_loop (GstPad * pad);
|
||||||
static gboolean gst_base_src_check_get_range (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);
|
guint length, GstBuffer ** buf);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -203,7 +205,7 @@ gst_base_src_init (GstBaseSrc * basesrc, gpointer g_class)
|
||||||
gst_pad_set_checkgetrange_function (pad,
|
gst_pad_set_checkgetrange_function (pad,
|
||||||
GST_DEBUG_FUNCPTR (gst_base_src_check_get_range));
|
GST_DEBUG_FUNCPTR (gst_base_src_check_get_range));
|
||||||
gst_pad_set_getrange_function (pad,
|
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_getcaps_function (pad, GST_DEBUG_FUNCPTR (gst_base_src_getcaps));
|
||||||
gst_pad_set_setcaps_function (pad, GST_DEBUG_FUNCPTR (gst_base_src_setcaps));
|
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
|
static gboolean
|
||||||
gst_base_src_query (GstPad * pad, GstQuery * query)
|
gst_base_src_query (GstPad * pad, GstQuery * query)
|
||||||
{
|
{
|
||||||
gboolean b;
|
|
||||||
guint64 ui64;
|
|
||||||
gint64 i64;
|
|
||||||
GstBaseSrc *src;
|
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)) {
|
switch (GST_QUERY_TYPE (query)) {
|
||||||
case GST_QUERY_POSITION:
|
case GST_QUERY_POSITION:
|
||||||
|
@ -333,18 +333,28 @@ gst_base_src_query (GstPad * pad, GstQuery * query)
|
||||||
case GST_FORMAT_DEFAULT:
|
case GST_FORMAT_DEFAULT:
|
||||||
case GST_FORMAT_BYTES:
|
case GST_FORMAT_BYTES:
|
||||||
gst_query_set_position (query, GST_FORMAT_BYTES, src->offset);
|
gst_query_set_position (query, GST_FORMAT_BYTES, src->offset);
|
||||||
return TRUE;
|
res = TRUE;
|
||||||
|
break;
|
||||||
case GST_FORMAT_PERCENT:
|
case GST_FORMAT_PERCENT:
|
||||||
|
{
|
||||||
|
gboolean b;
|
||||||
|
gint64 i64;
|
||||||
|
guint64 ui64;
|
||||||
|
|
||||||
b = gst_base_src_get_size (src, &ui64);
|
b = gst_base_src_get_size (src, &ui64);
|
||||||
if (b && src->offset > ui64)
|
if (b && src->offset > ui64)
|
||||||
i64 = gst_util_uint64_scale (GST_FORMAT_PERCENT_MAX, src->offset,
|
i64 = gst_util_uint64_scale (GST_FORMAT_PERCENT_MAX, src->offset,
|
||||||
ui64);
|
ui64);
|
||||||
else
|
else
|
||||||
i64 = GST_FORMAT_PERCENT_MAX;
|
i64 = GST_FORMAT_PERCENT_MAX;
|
||||||
|
|
||||||
gst_query_set_position (query, GST_FORMAT_PERCENT, i64);
|
gst_query_set_position (query, GST_FORMAT_PERCENT, i64);
|
||||||
return TRUE;
|
res = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return FALSE;
|
res = FALSE;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case GST_QUERY_DURATION:
|
case GST_QUERY_DURATION:
|
||||||
|
@ -355,37 +365,52 @@ gst_base_src_query (GstPad * pad, GstQuery * query)
|
||||||
switch (format) {
|
switch (format) {
|
||||||
case GST_FORMAT_DEFAULT:
|
case GST_FORMAT_DEFAULT:
|
||||||
case GST_FORMAT_BYTES:
|
case GST_FORMAT_BYTES:
|
||||||
|
{
|
||||||
|
gboolean b;
|
||||||
|
gint64 i64;
|
||||||
|
guint64 ui64;
|
||||||
|
|
||||||
b = gst_base_src_get_size (src, &ui64);
|
b = gst_base_src_get_size (src, &ui64);
|
||||||
/* better to make get_size take an int64 */
|
/* better to make get_size take an int64 */
|
||||||
i64 = b ? (gint64) ui64 : -1;
|
i64 = b ? (gint64) ui64 : -1;
|
||||||
gst_query_set_duration (query, GST_FORMAT_BYTES, i64);
|
gst_query_set_duration (query, GST_FORMAT_BYTES, i64);
|
||||||
return TRUE;
|
res = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
case GST_FORMAT_PERCENT:
|
case GST_FORMAT_PERCENT:
|
||||||
gst_query_set_duration (query, GST_FORMAT_PERCENT,
|
gst_query_set_duration (query, GST_FORMAT_PERCENT,
|
||||||
GST_FORMAT_PERCENT_MAX);
|
GST_FORMAT_PERCENT_MAX);
|
||||||
return TRUE;
|
res = TRUE;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return FALSE;
|
res = FALSE;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
case GST_QUERY_SEEKING:
|
case GST_QUERY_SEEKING:
|
||||||
gst_query_set_seeking (query, GST_FORMAT_BYTES,
|
gst_query_set_seeking (query, GST_FORMAT_BYTES,
|
||||||
src->seekable, src->segment_start, src->segment_end);
|
src->seekable, src->segment_start, src->segment_end);
|
||||||
return TRUE;
|
res = TRUE;
|
||||||
|
break;
|
||||||
|
|
||||||
case GST_QUERY_FORMATS:
|
case GST_QUERY_FORMATS:
|
||||||
gst_query_set_formats (query, 3, GST_FORMAT_DEFAULT,
|
gst_query_set_formats (query, 3, GST_FORMAT_DEFAULT,
|
||||||
GST_FORMAT_BYTES, GST_FORMAT_PERCENT);
|
GST_FORMAT_BYTES, GST_FORMAT_PERCENT);
|
||||||
return TRUE;
|
res = TRUE;
|
||||||
|
break;
|
||||||
|
|
||||||
case GST_QUERY_LATENCY:
|
case GST_QUERY_LATENCY:
|
||||||
case GST_QUERY_JITTER:
|
case GST_QUERY_JITTER:
|
||||||
case GST_QUERY_RATE:
|
case GST_QUERY_RATE:
|
||||||
case GST_QUERY_CONVERT:
|
case GST_QUERY_CONVERT:
|
||||||
default:
|
default:
|
||||||
return gst_pad_query_default (pad, query);
|
res = gst_pad_query_default (pad, query);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gst_object_unref (src);
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
|
@ -611,14 +636,12 @@ gst_base_src_get_property (GObject * object, guint prop_id, GValue * value,
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstFlowReturn
|
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)
|
GstBuffer ** buf)
|
||||||
{
|
{
|
||||||
GstFlowReturn ret;
|
GstFlowReturn ret;
|
||||||
GstBaseSrc *src;
|
|
||||||
GstBaseSrcClass *bclass;
|
GstBaseSrcClass *bclass;
|
||||||
|
|
||||||
src = GST_BASE_SRC (GST_OBJECT_PARENT (pad));
|
|
||||||
bclass = GST_BASE_SRC_GET_CLASS (src);
|
bclass = GST_BASE_SRC_GET_CLASS (src);
|
||||||
|
|
||||||
GST_LIVE_LOCK (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_LIVE_WAIT (src);
|
||||||
GST_DEBUG ("live source unlocked");
|
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_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))
|
if (!GST_OBJECT_FLAG_IS_SET (src, GST_BASE_SRC_STARTED))
|
||||||
goto not_started;
|
goto not_started;
|
||||||
|
|
||||||
if (!bclass->create)
|
if (G_UNLIKELY (!bclass->create))
|
||||||
goto no_function;
|
goto no_function;
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (src,
|
GST_DEBUG_OBJECT (src,
|
||||||
|
@ -680,7 +703,8 @@ gst_base_src_get_range (GstPad * pad, guint64 offset, guint length,
|
||||||
flushing:
|
flushing:
|
||||||
{
|
{
|
||||||
GST_DEBUG_OBJECT (src, "pad is flushing");
|
GST_DEBUG_OBJECT (src, "pad is flushing");
|
||||||
GST_UNLOCK (pad);
|
GST_UNLOCK (src->srcpad);
|
||||||
|
GST_LIVE_UNLOCK (src);
|
||||||
return GST_FLOW_WRONG_STATE;
|
return GST_FLOW_WRONG_STATE;
|
||||||
}
|
}
|
||||||
not_started:
|
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
|
static gboolean
|
||||||
gst_base_src_check_get_range (GstPad * pad)
|
gst_base_src_check_get_range (GstPad * pad)
|
||||||
{
|
{
|
||||||
|
@ -728,29 +768,34 @@ gst_base_src_loop (GstPad * pad)
|
||||||
GstBuffer *buf = NULL;
|
GstBuffer *buf = NULL;
|
||||||
GstFlowReturn ret;
|
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 */
|
/* now send newsegment */
|
||||||
gst_base_src_newsegment (src);
|
gst_base_src_newsegment (src);
|
||||||
src->need_newsegment = FALSE;
|
src->need_newsegment = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = gst_base_src_get_range (pad, src->offset, src->blocksize, &buf);
|
ret = gst_base_src_get_range (src, src->offset, src->blocksize, &buf);
|
||||||
if (ret != GST_FLOW_OK)
|
if (G_UNLIKELY (ret != GST_FLOW_OK)) {
|
||||||
|
if (ret == GST_FLOW_UNEXPECTED)
|
||||||
goto eos;
|
goto eos;
|
||||||
|
else
|
||||||
if (buf == NULL)
|
goto pause;
|
||||||
|
}
|
||||||
|
if (G_UNLIKELY (buf == NULL))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
src->offset += GST_BUFFER_SIZE (buf);
|
src->offset += GST_BUFFER_SIZE (buf);
|
||||||
|
|
||||||
ret = gst_pad_push (pad, buf);
|
ret = gst_pad_push (pad, buf);
|
||||||
if (ret != GST_FLOW_OK)
|
if (G_UNLIKELY (ret != GST_FLOW_OK))
|
||||||
goto pause;
|
goto pause;
|
||||||
|
|
||||||
|
gst_object_unref (src);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
/* special cases */
|
||||||
eos:
|
eos:
|
||||||
{
|
{
|
||||||
GST_DEBUG_OBJECT (src, "going to EOS");
|
GST_DEBUG_OBJECT (src, "going to EOS");
|
||||||
|
@ -759,21 +804,29 @@ eos:
|
||||||
gst_element_post_message (GST_ELEMENT (src),
|
gst_element_post_message (GST_ELEMENT (src),
|
||||||
gst_message_new_segment_done (GST_OBJECT (src),
|
gst_message_new_segment_done (GST_OBJECT (src),
|
||||||
GST_FORMAT_BYTES, src->segment_end));
|
GST_FORMAT_BYTES, src->segment_end));
|
||||||
} else
|
} else {
|
||||||
gst_pad_push_event (pad, gst_event_new_eos ());
|
gst_pad_push_event (pad, gst_event_new_eos ());
|
||||||
|
}
|
||||||
|
|
||||||
|
gst_object_unref (src);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
pause:
|
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);
|
gst_pad_pause_task (pad);
|
||||||
if (GST_FLOW_IS_FATAL (ret) || ret == GST_FLOW_NOT_LINKED) {
|
if (GST_FLOW_IS_FATAL (ret) || ret == GST_FLOW_NOT_LINKED) {
|
||||||
/* for fatal errors we post an error message */
|
/* for fatal errors we post an error message */
|
||||||
GST_ELEMENT_ERROR (src, STREAM, FAILED,
|
GST_ELEMENT_ERROR (src, STREAM, FAILED,
|
||||||
(_("Internal data flow error.")),
|
(_("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_pad_push_event (pad, gst_event_new_eos ());
|
||||||
}
|
}
|
||||||
|
gst_object_unref (src);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
error:
|
error:
|
||||||
|
@ -782,6 +835,8 @@ error:
|
||||||
(_("Internal data flow error.")), ("element returned NULL buffer"));
|
(_("Internal data flow error.")), ("element returned NULL buffer"));
|
||||||
gst_pad_pause_task (pad);
|
gst_pad_pause_task (pad);
|
||||||
gst_pad_push_event (pad, gst_event_new_eos ());
|
gst_pad_push_event (pad, gst_event_new_eos ());
|
||||||
|
|
||||||
|
gst_object_unref (src);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -129,7 +129,9 @@ static GstStateChangeReturn gst_base_src_change_state (GstElement * element,
|
||||||
|
|
||||||
static void gst_base_src_loop (GstPad * pad);
|
static void gst_base_src_loop (GstPad * pad);
|
||||||
static gboolean gst_base_src_check_get_range (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);
|
guint length, GstBuffer ** buf);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -203,7 +205,7 @@ gst_base_src_init (GstBaseSrc * basesrc, gpointer g_class)
|
||||||
gst_pad_set_checkgetrange_function (pad,
|
gst_pad_set_checkgetrange_function (pad,
|
||||||
GST_DEBUG_FUNCPTR (gst_base_src_check_get_range));
|
GST_DEBUG_FUNCPTR (gst_base_src_check_get_range));
|
||||||
gst_pad_set_getrange_function (pad,
|
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_getcaps_function (pad, GST_DEBUG_FUNCPTR (gst_base_src_getcaps));
|
||||||
gst_pad_set_setcaps_function (pad, GST_DEBUG_FUNCPTR (gst_base_src_setcaps));
|
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
|
static gboolean
|
||||||
gst_base_src_query (GstPad * pad, GstQuery * query)
|
gst_base_src_query (GstPad * pad, GstQuery * query)
|
||||||
{
|
{
|
||||||
gboolean b;
|
|
||||||
guint64 ui64;
|
|
||||||
gint64 i64;
|
|
||||||
GstBaseSrc *src;
|
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)) {
|
switch (GST_QUERY_TYPE (query)) {
|
||||||
case GST_QUERY_POSITION:
|
case GST_QUERY_POSITION:
|
||||||
|
@ -333,18 +333,28 @@ gst_base_src_query (GstPad * pad, GstQuery * query)
|
||||||
case GST_FORMAT_DEFAULT:
|
case GST_FORMAT_DEFAULT:
|
||||||
case GST_FORMAT_BYTES:
|
case GST_FORMAT_BYTES:
|
||||||
gst_query_set_position (query, GST_FORMAT_BYTES, src->offset);
|
gst_query_set_position (query, GST_FORMAT_BYTES, src->offset);
|
||||||
return TRUE;
|
res = TRUE;
|
||||||
|
break;
|
||||||
case GST_FORMAT_PERCENT:
|
case GST_FORMAT_PERCENT:
|
||||||
|
{
|
||||||
|
gboolean b;
|
||||||
|
gint64 i64;
|
||||||
|
guint64 ui64;
|
||||||
|
|
||||||
b = gst_base_src_get_size (src, &ui64);
|
b = gst_base_src_get_size (src, &ui64);
|
||||||
if (b && src->offset > ui64)
|
if (b && src->offset > ui64)
|
||||||
i64 = gst_util_uint64_scale (GST_FORMAT_PERCENT_MAX, src->offset,
|
i64 = gst_util_uint64_scale (GST_FORMAT_PERCENT_MAX, src->offset,
|
||||||
ui64);
|
ui64);
|
||||||
else
|
else
|
||||||
i64 = GST_FORMAT_PERCENT_MAX;
|
i64 = GST_FORMAT_PERCENT_MAX;
|
||||||
|
|
||||||
gst_query_set_position (query, GST_FORMAT_PERCENT, i64);
|
gst_query_set_position (query, GST_FORMAT_PERCENT, i64);
|
||||||
return TRUE;
|
res = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return FALSE;
|
res = FALSE;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case GST_QUERY_DURATION:
|
case GST_QUERY_DURATION:
|
||||||
|
@ -355,37 +365,52 @@ gst_base_src_query (GstPad * pad, GstQuery * query)
|
||||||
switch (format) {
|
switch (format) {
|
||||||
case GST_FORMAT_DEFAULT:
|
case GST_FORMAT_DEFAULT:
|
||||||
case GST_FORMAT_BYTES:
|
case GST_FORMAT_BYTES:
|
||||||
|
{
|
||||||
|
gboolean b;
|
||||||
|
gint64 i64;
|
||||||
|
guint64 ui64;
|
||||||
|
|
||||||
b = gst_base_src_get_size (src, &ui64);
|
b = gst_base_src_get_size (src, &ui64);
|
||||||
/* better to make get_size take an int64 */
|
/* better to make get_size take an int64 */
|
||||||
i64 = b ? (gint64) ui64 : -1;
|
i64 = b ? (gint64) ui64 : -1;
|
||||||
gst_query_set_duration (query, GST_FORMAT_BYTES, i64);
|
gst_query_set_duration (query, GST_FORMAT_BYTES, i64);
|
||||||
return TRUE;
|
res = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
case GST_FORMAT_PERCENT:
|
case GST_FORMAT_PERCENT:
|
||||||
gst_query_set_duration (query, GST_FORMAT_PERCENT,
|
gst_query_set_duration (query, GST_FORMAT_PERCENT,
|
||||||
GST_FORMAT_PERCENT_MAX);
|
GST_FORMAT_PERCENT_MAX);
|
||||||
return TRUE;
|
res = TRUE;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return FALSE;
|
res = FALSE;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
case GST_QUERY_SEEKING:
|
case GST_QUERY_SEEKING:
|
||||||
gst_query_set_seeking (query, GST_FORMAT_BYTES,
|
gst_query_set_seeking (query, GST_FORMAT_BYTES,
|
||||||
src->seekable, src->segment_start, src->segment_end);
|
src->seekable, src->segment_start, src->segment_end);
|
||||||
return TRUE;
|
res = TRUE;
|
||||||
|
break;
|
||||||
|
|
||||||
case GST_QUERY_FORMATS:
|
case GST_QUERY_FORMATS:
|
||||||
gst_query_set_formats (query, 3, GST_FORMAT_DEFAULT,
|
gst_query_set_formats (query, 3, GST_FORMAT_DEFAULT,
|
||||||
GST_FORMAT_BYTES, GST_FORMAT_PERCENT);
|
GST_FORMAT_BYTES, GST_FORMAT_PERCENT);
|
||||||
return TRUE;
|
res = TRUE;
|
||||||
|
break;
|
||||||
|
|
||||||
case GST_QUERY_LATENCY:
|
case GST_QUERY_LATENCY:
|
||||||
case GST_QUERY_JITTER:
|
case GST_QUERY_JITTER:
|
||||||
case GST_QUERY_RATE:
|
case GST_QUERY_RATE:
|
||||||
case GST_QUERY_CONVERT:
|
case GST_QUERY_CONVERT:
|
||||||
default:
|
default:
|
||||||
return gst_pad_query_default (pad, query);
|
res = gst_pad_query_default (pad, query);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gst_object_unref (src);
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
|
@ -611,14 +636,12 @@ gst_base_src_get_property (GObject * object, guint prop_id, GValue * value,
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstFlowReturn
|
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)
|
GstBuffer ** buf)
|
||||||
{
|
{
|
||||||
GstFlowReturn ret;
|
GstFlowReturn ret;
|
||||||
GstBaseSrc *src;
|
|
||||||
GstBaseSrcClass *bclass;
|
GstBaseSrcClass *bclass;
|
||||||
|
|
||||||
src = GST_BASE_SRC (GST_OBJECT_PARENT (pad));
|
|
||||||
bclass = GST_BASE_SRC_GET_CLASS (src);
|
bclass = GST_BASE_SRC_GET_CLASS (src);
|
||||||
|
|
||||||
GST_LIVE_LOCK (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_LIVE_WAIT (src);
|
||||||
GST_DEBUG ("live source unlocked");
|
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_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))
|
if (!GST_OBJECT_FLAG_IS_SET (src, GST_BASE_SRC_STARTED))
|
||||||
goto not_started;
|
goto not_started;
|
||||||
|
|
||||||
if (!bclass->create)
|
if (G_UNLIKELY (!bclass->create))
|
||||||
goto no_function;
|
goto no_function;
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (src,
|
GST_DEBUG_OBJECT (src,
|
||||||
|
@ -680,7 +703,8 @@ gst_base_src_get_range (GstPad * pad, guint64 offset, guint length,
|
||||||
flushing:
|
flushing:
|
||||||
{
|
{
|
||||||
GST_DEBUG_OBJECT (src, "pad is flushing");
|
GST_DEBUG_OBJECT (src, "pad is flushing");
|
||||||
GST_UNLOCK (pad);
|
GST_UNLOCK (src->srcpad);
|
||||||
|
GST_LIVE_UNLOCK (src);
|
||||||
return GST_FLOW_WRONG_STATE;
|
return GST_FLOW_WRONG_STATE;
|
||||||
}
|
}
|
||||||
not_started:
|
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
|
static gboolean
|
||||||
gst_base_src_check_get_range (GstPad * pad)
|
gst_base_src_check_get_range (GstPad * pad)
|
||||||
{
|
{
|
||||||
|
@ -728,29 +768,34 @@ gst_base_src_loop (GstPad * pad)
|
||||||
GstBuffer *buf = NULL;
|
GstBuffer *buf = NULL;
|
||||||
GstFlowReturn ret;
|
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 */
|
/* now send newsegment */
|
||||||
gst_base_src_newsegment (src);
|
gst_base_src_newsegment (src);
|
||||||
src->need_newsegment = FALSE;
|
src->need_newsegment = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = gst_base_src_get_range (pad, src->offset, src->blocksize, &buf);
|
ret = gst_base_src_get_range (src, src->offset, src->blocksize, &buf);
|
||||||
if (ret != GST_FLOW_OK)
|
if (G_UNLIKELY (ret != GST_FLOW_OK)) {
|
||||||
|
if (ret == GST_FLOW_UNEXPECTED)
|
||||||
goto eos;
|
goto eos;
|
||||||
|
else
|
||||||
if (buf == NULL)
|
goto pause;
|
||||||
|
}
|
||||||
|
if (G_UNLIKELY (buf == NULL))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
src->offset += GST_BUFFER_SIZE (buf);
|
src->offset += GST_BUFFER_SIZE (buf);
|
||||||
|
|
||||||
ret = gst_pad_push (pad, buf);
|
ret = gst_pad_push (pad, buf);
|
||||||
if (ret != GST_FLOW_OK)
|
if (G_UNLIKELY (ret != GST_FLOW_OK))
|
||||||
goto pause;
|
goto pause;
|
||||||
|
|
||||||
|
gst_object_unref (src);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
/* special cases */
|
||||||
eos:
|
eos:
|
||||||
{
|
{
|
||||||
GST_DEBUG_OBJECT (src, "going to EOS");
|
GST_DEBUG_OBJECT (src, "going to EOS");
|
||||||
|
@ -759,21 +804,29 @@ eos:
|
||||||
gst_element_post_message (GST_ELEMENT (src),
|
gst_element_post_message (GST_ELEMENT (src),
|
||||||
gst_message_new_segment_done (GST_OBJECT (src),
|
gst_message_new_segment_done (GST_OBJECT (src),
|
||||||
GST_FORMAT_BYTES, src->segment_end));
|
GST_FORMAT_BYTES, src->segment_end));
|
||||||
} else
|
} else {
|
||||||
gst_pad_push_event (pad, gst_event_new_eos ());
|
gst_pad_push_event (pad, gst_event_new_eos ());
|
||||||
|
}
|
||||||
|
|
||||||
|
gst_object_unref (src);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
pause:
|
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);
|
gst_pad_pause_task (pad);
|
||||||
if (GST_FLOW_IS_FATAL (ret) || ret == GST_FLOW_NOT_LINKED) {
|
if (GST_FLOW_IS_FATAL (ret) || ret == GST_FLOW_NOT_LINKED) {
|
||||||
/* for fatal errors we post an error message */
|
/* for fatal errors we post an error message */
|
||||||
GST_ELEMENT_ERROR (src, STREAM, FAILED,
|
GST_ELEMENT_ERROR (src, STREAM, FAILED,
|
||||||
(_("Internal data flow error.")),
|
(_("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_pad_push_event (pad, gst_event_new_eos ());
|
||||||
}
|
}
|
||||||
|
gst_object_unref (src);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
error:
|
error:
|
||||||
|
@ -782,6 +835,8 @@ error:
|
||||||
(_("Internal data flow error.")), ("element returned NULL buffer"));
|
(_("Internal data flow error.")), ("element returned NULL buffer"));
|
||||||
gst_pad_pause_task (pad);
|
gst_pad_pause_task (pad);
|
||||||
gst_pad_push_event (pad, gst_event_new_eos ());
|
gst_pad_push_event (pad, gst_event_new_eos ());
|
||||||
|
|
||||||
|
gst_object_unref (src);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -275,9 +275,10 @@ GST_START_TEST (test_message_state_changed_children)
|
||||||
THREAD_SWITCH ();
|
THREAD_SWITCH ();
|
||||||
|
|
||||||
/* each object is referenced by a message;
|
/* 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
|
* base_sink_chain has taken a refcount on the sink, and is blocked on
|
||||||
* preroll */
|
* preroll */
|
||||||
ASSERT_OBJECT_REFCOUNT (src, "src", 2);
|
ASSERT_OBJECT_REFCOUNT (src, "src", 3);
|
||||||
ASSERT_OBJECT_REFCOUNT (sink, "sink", 3);
|
ASSERT_OBJECT_REFCOUNT (sink, "sink", 3);
|
||||||
ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 2);
|
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);
|
fail_if ((gst_bus_pop (bus)) != NULL);
|
||||||
|
|
||||||
ASSERT_OBJECT_REFCOUNT (bus, "bus", 2);
|
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 (sink, "sink", 2);
|
||||||
ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
|
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);
|
fail_unless (pending == GST_STATE_VOID_PENDING);
|
||||||
|
|
||||||
/* each object is referenced by one message
|
/* 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
|
* sink might have an extra reference if it's still blocked on preroll
|
||||||
* pipeline posted a new-clock message too. */
|
* 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_BETWEEN (sink, "sink", 2, 3);
|
||||||
ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 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);
|
fail_if ((gst_bus_pop (bus)) != NULL);
|
||||||
|
|
||||||
ASSERT_OBJECT_REFCOUNT (bus, "bus", 2);
|
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 */
|
/* sink might have an extra reference if it's still blocked on preroll */
|
||||||
ASSERT_OBJECT_REFCOUNT_BETWEEN (sink, "sink", 1, 2);
|
ASSERT_OBJECT_REFCOUNT_BETWEEN (sink, "sink", 1, 2);
|
||||||
ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
|
ASSERT_OBJECT_REFCOUNT (pipeline, "pipeline", 1);
|
||||||
|
|
Loading…
Reference in a new issue