mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-26 19:51:11 +00:00
gst/base/gsttypefindhelper.c (gst_type_find_helper): Unref any remaining buffer.
Original commit message from CVS: 2005-06-27 Andy Wingo <wingo@pobox.com> * gst/base/gsttypefindhelper.c (gst_type_find_helper): Unref any remaining buffer. * gst/gsttrace.c (gst_alloc_trace_list_sorted): New helper, returns a sorted copy of the trace list. (gst_alloc_trace_print_live): New API, only prints traces with live objects. Sort the list. (gst_alloc_trace_print_all): Sort the list. (gst_alloc_trace_print): Align columns. * gst/elements/gstttypefindelement.c: * gst/elements/gsttee.c: * gst/base/gstbasesrc.c: * gst/base/gstbasesink.c: * gst/base/gstbasetransform.c: * gst/gstqueue.c: Adapt for pad activation changes. * gst/gstpipeline.c (gst_pipeline_init): Unref after parenting sched. (gst_pipeline_dispose): Drop ref on sched. * gst/gstpad.c (gst_pad_init): Set the default activate func. (gst_pad_activate_default): Push mode by default. (pre_activate_switch, post_activate_switch): New stubs, things to do before and after switching activation modes on pads. (gst_pad_set_active): Take a boolean and not a mode, dispatch to the pad's activate function to choose which mode to activate. Shortcut on deactivation and call the right function directly. (gst_pad_activate_pull): New API, (de)activates a pad in pull mode. (gst_pad_activate_push): New API, same for push mode. (gst_pad_set_activate_function) (gst_pad_set_activatepull_function) (gst_pad_set_activatepush_function): Setters for new API. * gst/gstminiobject.c (gst_mini_object_new, gst_mini_object_free): Trace all miniobjects. (gst_mini_object_make_writable): Unref the arg if we copy, like gst_caps_make_writable. * gst/gstmessage.c (_gst_message_initialize): No trace init. * gst/gstghostpad.c (gst_proxy_pad_do_activate) (gst_proxy_pad_do_activatepull, gst_proxy_pad_do_activatepush): Adapt for new pad API. * gst/gstevent.c (_gst_event_initialize): Don't initialize trace. * gst/gstelement.h: * gst/gstelement.c (gst_element_iterate_src_pads) (gst_element_iterate_sink_pads): New API functions. * gst/gstelement.c (iterator_fold_with_resync): New utility, should fold into gstiterator.c in some form. (gst_element_pads_activate): Simplified via use of fold and delegation of decisions to gstpad->activate. * gst/gstbus.c (gst_bus_source_finalize): Set the bus to NULL, help in debugging. * gst/gstbuffer.c (_gst_buffer_initialize): Ref the buffer type class once in init, like gstmessage. Didn't run into this issue but it seems correct. Don't initialize a trace, gstminiobject does that. * check/pipelines/simple_launch_lines.c (test_stop_from_app): New test, runs fakesrc ! fakesink, stopping on ::handoff via a message to the bus. (assert_live_count): New util function, uses alloc traces to check cleanup. * check/gst/gstghostpad.c (test_ghost_pads): More refcount checks. To be modified when unlink drops the internal pad.
This commit is contained in:
parent
adbd17c378
commit
f2cf753b17
36 changed files with 1405 additions and 725 deletions
76
ChangeLog
76
ChangeLog
|
@ -1,3 +1,79 @@
|
|||
2005-06-27 Andy Wingo <wingo@pobox.com>
|
||||
|
||||
* gst/base/gsttypefindhelper.c (gst_type_find_helper): Unref any
|
||||
remaining buffer.
|
||||
|
||||
* gst/gsttrace.c (gst_alloc_trace_list_sorted): New helper,
|
||||
returns a sorted copy of the trace list.
|
||||
(gst_alloc_trace_print_live): New API, only prints traces with
|
||||
live objects. Sort the list.
|
||||
(gst_alloc_trace_print_all): Sort the list.
|
||||
(gst_alloc_trace_print): Align columns.
|
||||
|
||||
* gst/elements/gstttypefindelement.c:
|
||||
* gst/elements/gsttee.c:
|
||||
* gst/base/gstbasesrc.c:
|
||||
* gst/base/gstbasesink.c:
|
||||
* gst/base/gstbasetransform.c:
|
||||
* gst/gstqueue.c: Adapt for pad activation changes.
|
||||
|
||||
* gst/gstpipeline.c (gst_pipeline_init): Unref after parenting
|
||||
sched.
|
||||
(gst_pipeline_dispose): Drop ref on sched.
|
||||
|
||||
* gst/gstpad.c (gst_pad_init): Set the default activate func.
|
||||
(gst_pad_activate_default): Push mode by default.
|
||||
(pre_activate_switch, post_activate_switch): New stubs, things to
|
||||
do before and after switching activation modes on pads.
|
||||
(gst_pad_set_active): Take a boolean and not a mode, dispatch to
|
||||
the pad's activate function to choose which mode to activate.
|
||||
Shortcut on deactivation and call the right function directly.
|
||||
(gst_pad_activate_pull): New API, (de)activates a pad in pull
|
||||
mode.
|
||||
(gst_pad_activate_push): New API, same for push mode.
|
||||
(gst_pad_set_activate_function)
|
||||
(gst_pad_set_activatepull_function)
|
||||
(gst_pad_set_activatepush_function): Setters for new API.
|
||||
|
||||
* gst/gstminiobject.c (gst_mini_object_new, gst_mini_object_free):
|
||||
Trace all miniobjects.
|
||||
(gst_mini_object_make_writable): Unref the arg if we copy, like
|
||||
gst_caps_make_writable.
|
||||
|
||||
* gst/gstmessage.c (_gst_message_initialize): No trace init.
|
||||
|
||||
* gst/gstghostpad.c (gst_proxy_pad_do_activate)
|
||||
(gst_proxy_pad_do_activatepull, gst_proxy_pad_do_activatepush):
|
||||
Adapt for new pad API.
|
||||
|
||||
* gst/gstevent.c (_gst_event_initialize): Don't initialize trace.
|
||||
|
||||
* gst/gstelement.h:
|
||||
* gst/gstelement.c (gst_element_iterate_src_pads)
|
||||
(gst_element_iterate_sink_pads): New API functions.
|
||||
|
||||
* gst/gstelement.c (iterator_fold_with_resync): New utility,
|
||||
should fold into gstiterator.c in some form.
|
||||
(gst_element_pads_activate): Simplified via use of fold and
|
||||
delegation of decisions to gstpad->activate.
|
||||
|
||||
* gst/gstbus.c (gst_bus_source_finalize): Set the bus to NULL,
|
||||
help in debugging.
|
||||
|
||||
* gst/gstbuffer.c (_gst_buffer_initialize): Ref the buffer type
|
||||
class once in init, like gstmessage. Didn't run into this issue
|
||||
but it seems correct. Don't initialize a trace, gstminiobject does
|
||||
that.
|
||||
|
||||
* check/pipelines/simple_launch_lines.c (test_stop_from_app): New
|
||||
test, runs fakesrc ! fakesink, stopping on ::handoff via a message
|
||||
to the bus.
|
||||
(assert_live_count): New util function, uses alloc traces to check
|
||||
cleanup.
|
||||
|
||||
* check/gst/gstghostpad.c (test_ghost_pads): More refcount checks.
|
||||
To be modified when unlink drops the internal pad.
|
||||
|
||||
2005-06-27 Wim Taymans <wim@fluendo.com>
|
||||
|
||||
* gst/gstbin.c: (gst_bin_get_state), (gst_bin_iterate_state_order),
|
||||
|
|
|
@ -90,6 +90,39 @@ START_TEST (test_ghost_pads)
|
|||
fail_unless (gst_element_set_state (b1, GST_STATE_NULL) == GST_STATE_SUCCESS);
|
||||
|
||||
gst_object_unref (GST_OBJECT (b1));
|
||||
/* unreffing the bin will unref all elements, which will unlink and unparent
|
||||
* all pads */
|
||||
|
||||
/* FIXME: ghost pads need to drop their internal pad in the unlink function,
|
||||
* but can't right now. So internal pads have a ref from their parent, and the
|
||||
* internal pads' targets have refs from the internals. When we do the last
|
||||
* unref on the ghost pads, these refs should go away.
|
||||
*/
|
||||
|
||||
assert_gstrefcount (fsrc, 2); /* gisrc */
|
||||
assert_gstrefcount (gsink, 1);
|
||||
assert_gstrefcount (gsrc, 1);
|
||||
assert_gstrefcount (fsink, 2); /* gisink */
|
||||
|
||||
assert_gstrefcount (gisrc, 2); /* gsink -- fixme drop ref in unlink */
|
||||
assert_gstrefcount (isink, 2); /* gsink */
|
||||
assert_gstrefcount (gisink, 2); /* gsrc -- fixme drop ref in unlink */
|
||||
assert_gstrefcount (isrc, 2); /* gsrc */
|
||||
|
||||
/* while the fixme isn't fixed, check cleanup */
|
||||
gst_object_unref (GST_OBJECT (gsink));
|
||||
assert_gstrefcount (isink, 1);
|
||||
assert_gstrefcount (gisrc, 1);
|
||||
assert_gstrefcount (fsrc, 2); /* gisrc */
|
||||
gst_object_unref (GST_OBJECT (gisrc));
|
||||
assert_gstrefcount (fsrc, 1);
|
||||
|
||||
gst_object_unref (GST_OBJECT (gsrc));
|
||||
assert_gstrefcount (isrc, 1);
|
||||
assert_gstrefcount (gisink, 1);
|
||||
assert_gstrefcount (fsink, 2); /* gisrc */
|
||||
gst_object_unref (GST_OBJECT (gisink));
|
||||
assert_gstrefcount (fsink, 1);
|
||||
}
|
||||
END_TEST Suite * gst_ghost_pad_suite (void)
|
||||
{
|
||||
|
|
|
@ -99,8 +99,68 @@ START_TEST (test_2_elements)
|
|||
ASSERT_CRITICAL (run_pipeline (setup_pipeline (s), s,
|
||||
GST_MESSAGE_STATE_CHANGED, GST_MESSAGE_UNKNOWN)); */
|
||||
}
|
||||
END_TEST Suite *
|
||||
simple_launch_lines_suite (void)
|
||||
END_TEST static void
|
||||
got_handoff (GstElement * sink, GstBuffer * buf, GstPad * pad, gpointer unused)
|
||||
{
|
||||
gst_element_post_message
|
||||
(sink, gst_message_new_application (gst_structure_new ("foo", NULL)));
|
||||
}
|
||||
|
||||
static void
|
||||
assert_live_count (GType type, gint live)
|
||||
{
|
||||
GstAllocTrace *trace;
|
||||
const gchar *name;
|
||||
|
||||
if (gst_alloc_trace_available ()) {
|
||||
name = g_type_name (type);
|
||||
g_assert (name);
|
||||
trace = gst_alloc_trace_get (name);
|
||||
if (trace) {
|
||||
g_return_if_fail (trace->live == live);
|
||||
}
|
||||
} else {
|
||||
g_print ("\nSkipping live count tests; recompile with traces to enable\n");
|
||||
}
|
||||
}
|
||||
|
||||
START_TEST (test_stop_from_app)
|
||||
{
|
||||
GstElement *fakesrc, *fakesink, *pipeline;
|
||||
GstBus *bus;
|
||||
GstMessageType revent;
|
||||
|
||||
assert_live_count (GST_TYPE_BUFFER, 0);
|
||||
|
||||
fakesrc = gst_element_factory_make ("fakesrc", NULL);
|
||||
fakesink = gst_element_factory_make ("fakesink", NULL);
|
||||
pipeline = gst_element_factory_make ("pipeline", NULL);
|
||||
|
||||
g_return_if_fail (fakesrc && fakesink && pipeline);
|
||||
|
||||
gst_element_link (fakesrc, fakesink);
|
||||
gst_bin_add_many (GST_BIN (pipeline), fakesrc, fakesink, NULL);
|
||||
|
||||
g_object_set (fakesink, "signal-handoffs", (gboolean) TRUE, NULL);
|
||||
g_signal_connect (fakesink, "handoff", G_CALLBACK (got_handoff), NULL);
|
||||
|
||||
gst_element_set_state (pipeline, GST_STATE_PLAYING);
|
||||
|
||||
bus = gst_element_get_bus (pipeline);
|
||||
g_assert (bus);
|
||||
|
||||
/* will time out after half a second */
|
||||
revent = gst_bus_poll (bus, GST_MESSAGE_APPLICATION, GST_SECOND / 2);
|
||||
|
||||
g_return_if_fail (revent == GST_MESSAGE_APPLICATION);
|
||||
gst_message_unref (gst_bus_pop (bus));
|
||||
|
||||
gst_element_set_state (pipeline, GST_STATE_NULL);
|
||||
gst_object_unref (GST_OBJECT (pipeline));
|
||||
|
||||
assert_live_count (GST_TYPE_BUFFER, 0);
|
||||
}
|
||||
END_TEST Suite * simple_launch_lines_suite (void)
|
||||
{
|
||||
Suite *s = suite_create ("Pipelines");
|
||||
TCase *tc_chain = tcase_create ("linear");
|
||||
|
@ -110,6 +170,7 @@ simple_launch_lines_suite (void)
|
|||
|
||||
suite_add_tcase (s, tc_chain);
|
||||
tcase_add_test (tc_chain, test_2_elements);
|
||||
tcase_add_test (tc_chain, test_stop_from_app);
|
||||
return s;
|
||||
}
|
||||
|
||||
|
|
|
@ -63,6 +63,11 @@ GstFakeSrc
|
|||
|
||||
</para>
|
||||
|
||||
<!-- ##### ARG GstFakeSrc:is-live ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
<!-- ##### ARG GstFakeSrc:last-message ##### -->
|
||||
<para>
|
||||
|
||||
|
|
|
@ -75,6 +75,8 @@ Last reviewed on December 13th, 2002 (0.5.0.1)
|
|||
@acceptcapsfunc:
|
||||
@fixatecapsfunc:
|
||||
@activatefunc:
|
||||
@activatepushfunc:
|
||||
@activatepullfunc:
|
||||
@linkfunc:
|
||||
@unlinkfunc:
|
||||
@peer:
|
||||
|
@ -444,10 +446,10 @@ Checks if the pad is a sink pad.
|
|||
</para>
|
||||
|
||||
@pad:
|
||||
@mode:
|
||||
@active:
|
||||
@Returns:
|
||||
<!-- # Unused Parameters # -->
|
||||
@active:
|
||||
@mode:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION gst_pad_is_active ##### -->
|
||||
|
|
|
@ -100,7 +100,8 @@ static GstElementStateReturn gst_basesink_change_state (GstElement * element);
|
|||
static GstFlowReturn gst_basesink_chain (GstPad * pad, GstBuffer * buffer);
|
||||
static void gst_basesink_loop (GstPad * pad);
|
||||
static GstFlowReturn gst_basesink_chain (GstPad * pad, GstBuffer * buffer);
|
||||
static gboolean gst_basesink_activate (GstPad * pad, GstActivateMode mode);
|
||||
static gboolean gst_basesink_activate_push (GstPad * pad, gboolean active);
|
||||
static gboolean gst_basesink_activate_pull (GstPad * pad, gboolean active);
|
||||
static gboolean gst_basesink_event (GstPad * pad, GstEvent * event);
|
||||
static inline GstFlowReturn gst_basesink_handle_buffer (GstBaseSink * basesink,
|
||||
GstBuffer * buf);
|
||||
|
@ -256,8 +257,10 @@ gst_basesink_finalize (GObject * object)
|
|||
static void
|
||||
gst_basesink_set_pad_functions (GstBaseSink * this, GstPad * pad)
|
||||
{
|
||||
gst_pad_set_activate_function (pad,
|
||||
GST_DEBUG_FUNCPTR (gst_basesink_activate));
|
||||
gst_pad_set_activatepush_function (pad,
|
||||
GST_DEBUG_FUNCPTR (gst_basesink_activate_push));
|
||||
gst_pad_set_activatepull_function (pad,
|
||||
GST_DEBUG_FUNCPTR (gst_basesink_activate_pull));
|
||||
gst_pad_set_event_function (pad, GST_DEBUG_FUNCPTR (gst_basesink_event));
|
||||
|
||||
if (this->has_chain)
|
||||
|
@ -824,51 +827,72 @@ paused:
|
|||
}
|
||||
|
||||
static gboolean
|
||||
gst_basesink_activate (GstPad * pad, GstActivateMode mode)
|
||||
gst_basesink_deactivate (GstBaseSink * basesink, GstPad * pad)
|
||||
{
|
||||
gboolean result = FALSE;
|
||||
GstBaseSinkClass *bclass;
|
||||
|
||||
bclass = GST_BASESINK_GET_CLASS (basesink);
|
||||
|
||||
/* step 1, unblock clock sync (if any) or any other blocking thing */
|
||||
GST_PREROLL_LOCK (pad);
|
||||
GST_LOCK (basesink);
|
||||
if (basesink->clock_id) {
|
||||
gst_clock_id_unschedule (basesink->clock_id);
|
||||
}
|
||||
GST_UNLOCK (basesink);
|
||||
|
||||
/* unlock any subclasses */
|
||||
if (bclass->unlock)
|
||||
bclass->unlock (basesink);
|
||||
|
||||
/* flush out the data thread if it's locked in finish_preroll */
|
||||
gst_basesink_preroll_queue_flush (basesink);
|
||||
basesink->need_preroll = FALSE;
|
||||
GST_PREROLL_SIGNAL (pad);
|
||||
GST_PREROLL_UNLOCK (pad);
|
||||
|
||||
/* step 2, make sure streaming finishes */
|
||||
result = gst_pad_stop_task (pad);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_basesink_activate_push (GstPad * pad, gboolean active)
|
||||
{
|
||||
gboolean result = FALSE;
|
||||
GstBaseSink *basesink;
|
||||
GstBaseSinkClass *bclass;
|
||||
|
||||
basesink = GST_BASESINK (GST_OBJECT_PARENT (pad));
|
||||
bclass = GST_BASESINK_GET_CLASS (basesink);
|
||||
|
||||
switch (mode) {
|
||||
case GST_ACTIVATE_PUSH:
|
||||
g_return_val_if_fail (basesink->has_chain, FALSE);
|
||||
result = TRUE;
|
||||
break;
|
||||
case GST_ACTIVATE_PULL:
|
||||
/* if we have a scheduler we can start the task */
|
||||
g_return_val_if_fail (basesink->has_loop, FALSE);
|
||||
gst_pad_peer_set_active (pad, mode);
|
||||
result =
|
||||
gst_pad_start_task (pad, (GstTaskFunction) gst_basesink_loop, pad);
|
||||
break;
|
||||
case GST_ACTIVATE_NONE:
|
||||
/* step 1, unblock clock sync (if any) or any other blocking thing */
|
||||
GST_PREROLL_LOCK (pad);
|
||||
GST_LOCK (basesink);
|
||||
if (basesink->clock_id) {
|
||||
gst_clock_id_unschedule (basesink->clock_id);
|
||||
}
|
||||
GST_UNLOCK (basesink);
|
||||
|
||||
/* unlock any subclasses */
|
||||
if (bclass->unlock)
|
||||
bclass->unlock (basesink);
|
||||
|
||||
/* flush out the data thread if it's locked in finish_preroll */
|
||||
gst_basesink_preroll_queue_flush (basesink);
|
||||
basesink->need_preroll = FALSE;
|
||||
GST_PREROLL_SIGNAL (pad);
|
||||
GST_PREROLL_UNLOCK (pad);
|
||||
|
||||
/* step 2, make sure streaming finishes */
|
||||
result = gst_pad_stop_task (pad);
|
||||
break;
|
||||
if (active) {
|
||||
g_return_val_if_fail (basesink->has_chain, FALSE);
|
||||
result = TRUE;
|
||||
} else {
|
||||
result = gst_basesink_deactivate (basesink, pad);
|
||||
}
|
||||
basesink->pad_mode = GST_ACTIVATE_PUSH;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* this won't get called until we implement an activate function */
|
||||
static gboolean
|
||||
gst_basesink_activate_pull (GstPad * pad, gboolean active)
|
||||
{
|
||||
gboolean result = FALSE;
|
||||
GstBaseSink *basesink;
|
||||
|
||||
basesink = GST_BASESINK (GST_OBJECT_PARENT (pad));
|
||||
|
||||
if (active) {
|
||||
/* if we have a scheduler we can start the task */
|
||||
g_return_val_if_fail (basesink->has_loop, FALSE);
|
||||
result = gst_pad_start_task (pad, (GstTaskFunction) gst_basesink_loop, pad);
|
||||
} else {
|
||||
result = gst_basesink_deactivate (basesink, pad);
|
||||
}
|
||||
basesink->pad_mode = mode;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -82,7 +82,8 @@ gst_basesrc_get_type (void)
|
|||
return basesrc_type;
|
||||
}
|
||||
|
||||
static gboolean gst_basesrc_activate (GstPad * pad, GstActivateMode mode);
|
||||
static gboolean gst_basesrc_activate_push (GstPad * pad, gboolean active);
|
||||
static gboolean gst_basesrc_activate_pull (GstPad * pad, gboolean active);
|
||||
static void gst_basesrc_set_property (GObject * object, guint prop_id,
|
||||
const GValue * value, GParamSpec * pspec);
|
||||
static void gst_basesrc_get_property (GObject * object, guint prop_id,
|
||||
|
@ -158,7 +159,8 @@ gst_basesrc_init (GstBaseSrc * basesrc, gpointer g_class)
|
|||
|
||||
pad = gst_pad_new_from_template (pad_template, "src");
|
||||
|
||||
gst_pad_set_activate_function (pad, gst_basesrc_activate);
|
||||
gst_pad_set_activatepush_function (pad, gst_basesrc_activate_push);
|
||||
gst_pad_set_activatepull_function (pad, gst_basesrc_activate_pull);
|
||||
gst_pad_set_event_function (pad, gst_basesrc_event_handler);
|
||||
gst_pad_set_query_function (pad, gst_basesrc_query);
|
||||
|
||||
|
@ -729,54 +731,70 @@ gst_basesrc_stop (GstBaseSrc * basesrc)
|
|||
}
|
||||
|
||||
static gboolean
|
||||
gst_basesrc_activate (GstPad * pad, GstActivateMode mode)
|
||||
gst_basesrc_deactivate (GstBaseSrc * basesrc, GstPad * pad)
|
||||
{
|
||||
gboolean result;
|
||||
|
||||
GST_LIVE_LOCK (basesrc);
|
||||
basesrc->live_running = TRUE;
|
||||
GST_LIVE_SIGNAL (basesrc);
|
||||
GST_LIVE_UNLOCK (basesrc);
|
||||
|
||||
/* step 1, unblock clock sync (if any) */
|
||||
gst_basesrc_unlock (basesrc);
|
||||
|
||||
/* step 2, make sure streaming finishes */
|
||||
result = gst_pad_stop_task (pad);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_basesrc_activate_push (GstPad * pad, gboolean active)
|
||||
{
|
||||
GstBaseSrc *basesrc;
|
||||
|
||||
basesrc = GST_BASESRC (GST_OBJECT_PARENT (pad));
|
||||
|
||||
/* prepare subclass first */
|
||||
switch (mode) {
|
||||
case GST_ACTIVATE_PUSH:
|
||||
case GST_ACTIVATE_PULL:
|
||||
result = gst_basesrc_start (basesrc);
|
||||
break;
|
||||
default:
|
||||
result = TRUE;
|
||||
break;
|
||||
if (active) {
|
||||
if (!gst_basesrc_start (basesrc))
|
||||
goto error_start;
|
||||
|
||||
return gst_pad_start_task (pad, (GstTaskFunction) gst_basesrc_loop, pad);
|
||||
} else {
|
||||
return gst_basesrc_deactivate (basesrc, pad);
|
||||
}
|
||||
/* if that failed we can stop here */
|
||||
if (!result)
|
||||
goto error_start;
|
||||
|
||||
result = FALSE;
|
||||
switch (mode) {
|
||||
case GST_ACTIVATE_PUSH:
|
||||
result =
|
||||
gst_pad_start_task (pad, (GstTaskFunction) gst_basesrc_loop, pad);
|
||||
break;
|
||||
case GST_ACTIVATE_PULL:
|
||||
result = basesrc->seekable;
|
||||
if (!result)
|
||||
gst_basesrc_stop (basesrc);
|
||||
break;
|
||||
case GST_ACTIVATE_NONE:
|
||||
GST_LIVE_LOCK (basesrc);
|
||||
basesrc->live_running = TRUE;
|
||||
GST_LIVE_SIGNAL (basesrc);
|
||||
GST_LIVE_UNLOCK (basesrc);
|
||||
|
||||
/* step 1, unblock clock sync (if any) */
|
||||
gst_basesrc_unlock (basesrc);
|
||||
|
||||
/* step 2, make sure streaming finishes */
|
||||
result = gst_pad_stop_task (pad);
|
||||
break;
|
||||
error_start:
|
||||
{
|
||||
GST_DEBUG_OBJECT (basesrc, "failed to start");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_basesrc_activate_pull (GstPad * pad, gboolean active)
|
||||
{
|
||||
GstBaseSrc *basesrc;
|
||||
|
||||
basesrc = GST_BASESRC (GST_OBJECT_PARENT (pad));
|
||||
|
||||
/* prepare subclass first */
|
||||
if (active) {
|
||||
if (!gst_basesrc_start (basesrc))
|
||||
goto error_start;
|
||||
|
||||
if (!basesrc->seekable) {
|
||||
gst_basesrc_stop (basesrc);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
} else {
|
||||
return gst_basesrc_deactivate (basesrc, pad);
|
||||
}
|
||||
return result;
|
||||
|
||||
/* ERROR */
|
||||
error_start:
|
||||
{
|
||||
GST_DEBUG_OBJECT (basesrc, "failed to start");
|
||||
|
|
|
@ -84,10 +84,10 @@ static void gst_base_transform_set_property (GObject * object, guint prop_id,
|
|||
const GValue * value, GParamSpec * pspec);
|
||||
static void gst_base_transform_get_property (GObject * object, guint prop_id,
|
||||
GValue * value, GParamSpec * pspec);
|
||||
static gboolean gst_base_transform_src_activate (GstPad * pad,
|
||||
GstActivateMode mode);
|
||||
static gboolean gst_base_transform_sink_activate (GstPad * pad,
|
||||
GstActivateMode mode);
|
||||
static gboolean gst_base_transform_src_activate_pull (GstPad * pad,
|
||||
gboolean active);
|
||||
static gboolean gst_base_transform_sink_activate_push (GstPad * pad,
|
||||
gboolean active);
|
||||
static GstElementStateReturn gst_base_transform_change_state (GstElement *
|
||||
element);
|
||||
|
||||
|
@ -157,8 +157,8 @@ gst_base_transform_init (GstBaseTransform * trans, gpointer g_class)
|
|||
GST_DEBUG_FUNCPTR (gst_base_transform_event));
|
||||
gst_pad_set_chain_function (trans->sinkpad,
|
||||
GST_DEBUG_FUNCPTR (gst_base_transform_chain));
|
||||
gst_pad_set_activate_function (trans->sinkpad,
|
||||
GST_DEBUG_FUNCPTR (gst_base_transform_sink_activate));
|
||||
gst_pad_set_activatepush_function (trans->sinkpad,
|
||||
GST_DEBUG_FUNCPTR (gst_base_transform_sink_activate_push));
|
||||
gst_element_add_pad (GST_ELEMENT (trans), trans->sinkpad);
|
||||
|
||||
pad_template =
|
||||
|
@ -169,8 +169,8 @@ gst_base_transform_init (GstBaseTransform * trans, gpointer g_class)
|
|||
GST_DEBUG_FUNCPTR (gst_base_transform_proxy_getcaps));
|
||||
gst_pad_set_getrange_function (trans->srcpad,
|
||||
GST_DEBUG_FUNCPTR (gst_base_transform_getrange));
|
||||
gst_pad_set_activate_function (trans->srcpad,
|
||||
GST_DEBUG_FUNCPTR (gst_base_transform_src_activate));
|
||||
gst_pad_set_activatepull_function (trans->srcpad,
|
||||
GST_DEBUG_FUNCPTR (gst_base_transform_src_activate_pull));
|
||||
gst_element_add_pad (GST_ELEMENT (trans), trans->srcpad);
|
||||
}
|
||||
|
||||
|
@ -344,7 +344,7 @@ gst_base_transform_get_property (GObject * object, guint prop_id,
|
|||
}
|
||||
|
||||
static gboolean
|
||||
gst_base_transform_sink_activate (GstPad * pad, GstActivateMode mode)
|
||||
gst_base_transform_sink_activate_push (GstPad * pad, gboolean active)
|
||||
{
|
||||
gboolean result = TRUE;
|
||||
GstBaseTransform *trans;
|
||||
|
@ -353,39 +353,31 @@ gst_base_transform_sink_activate (GstPad * pad, GstActivateMode mode)
|
|||
trans = GST_BASE_TRANSFORM (GST_OBJECT_PARENT (pad));
|
||||
bclass = GST_BASE_TRANSFORM_GET_CLASS (trans);
|
||||
|
||||
switch (mode) {
|
||||
case GST_ACTIVATE_PUSH:
|
||||
case GST_ACTIVATE_PULL:
|
||||
if (bclass->start)
|
||||
result = bclass->start (trans);
|
||||
break;
|
||||
case GST_ACTIVATE_NONE:
|
||||
break;
|
||||
if (active) {
|
||||
if (bclass->start)
|
||||
result = bclass->start (trans);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_base_transform_src_activate (GstPad * pad, GstActivateMode mode)
|
||||
gst_base_transform_src_activate_pull (GstPad * pad, gboolean active)
|
||||
{
|
||||
gboolean result = FALSE;
|
||||
GstBaseTransform *trans;
|
||||
GstBaseTransformClass *bclass;
|
||||
|
||||
trans = GST_BASE_TRANSFORM (GST_OBJECT_PARENT (pad));
|
||||
bclass = GST_BASE_TRANSFORM_GET_CLASS (trans);
|
||||
|
||||
switch (mode) {
|
||||
case GST_ACTIVATE_PUSH:
|
||||
result = TRUE;
|
||||
break;
|
||||
case GST_ACTIVATE_PULL:
|
||||
result = gst_pad_set_active (trans->sinkpad, mode);
|
||||
result = gst_pad_peer_set_active (trans->sinkpad, mode);
|
||||
break;
|
||||
case GST_ACTIVATE_NONE:
|
||||
result = TRUE;
|
||||
break;
|
||||
result = gst_pad_activate_pull (trans->sinkpad, active);
|
||||
|
||||
if (active) {
|
||||
if (result && bclass->start)
|
||||
result &= bclass->start (trans);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -130,5 +130,8 @@ gst_type_find_helper (GstPad * src, guint64 size)
|
|||
if (find.best_probability > 0)
|
||||
result = find.caps;
|
||||
|
||||
if (find.buffer)
|
||||
gst_buffer_unref (find.buffer);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -75,7 +75,8 @@ static void gst_tee_get_property (GObject * object, guint prop_id,
|
|||
|
||||
static GstFlowReturn gst_tee_chain (GstPad * pad, GstBuffer * buffer);
|
||||
static void gst_tee_loop (GstPad * pad);
|
||||
static gboolean gst_tee_sink_activate (GstPad * pad, GstActivateMode mode);
|
||||
static gboolean gst_tee_sink_activate_push (GstPad * pad, gboolean active);
|
||||
static gboolean gst_tee_sink_activate_pull (GstPad * pad, gboolean active);
|
||||
|
||||
|
||||
static void
|
||||
|
@ -153,8 +154,10 @@ gst_tee_init (GstTee * tee)
|
|||
static void
|
||||
gst_tee_update_pad_functions (GstTee * tee)
|
||||
{
|
||||
gst_pad_set_activate_function (tee->sinkpad,
|
||||
GST_DEBUG_FUNCPTR (gst_tee_sink_activate));
|
||||
gst_pad_set_activatepush_function (tee->sinkpad,
|
||||
GST_DEBUG_FUNCPTR (gst_tee_sink_activate_push));
|
||||
gst_pad_set_activatepull_function (tee->sinkpad,
|
||||
GST_DEBUG_FUNCPTR (gst_tee_sink_activate_pull));
|
||||
|
||||
if (tee->has_chain)
|
||||
gst_pad_set_chain_function (tee->sinkpad,
|
||||
|
@ -348,27 +351,35 @@ pause_task:
|
|||
}
|
||||
|
||||
static gboolean
|
||||
gst_tee_sink_activate (GstPad * pad, GstActivateMode mode)
|
||||
gst_tee_sink_activate_push (GstPad * pad, gboolean active)
|
||||
{
|
||||
gboolean result = FALSE;
|
||||
GstTee *tee;
|
||||
|
||||
tee = GST_TEE (GST_OBJECT_PARENT (pad));
|
||||
|
||||
switch (mode) {
|
||||
case GST_ACTIVATE_PUSH:
|
||||
g_return_val_if_fail (tee->has_chain, FALSE);
|
||||
result = TRUE;
|
||||
break;
|
||||
case GST_ACTIVATE_PULL:
|
||||
g_return_val_if_fail (tee->has_sink_loop, FALSE);
|
||||
result = gst_pad_start_task (pad, (GstTaskFunction) gst_tee_loop, pad);
|
||||
break;
|
||||
case GST_ACTIVATE_NONE:
|
||||
result = gst_pad_stop_task (pad);
|
||||
break;
|
||||
}
|
||||
tee->sink_mode = mode;
|
||||
tee->sink_mode = active && GST_ACTIVATE_PUSH;
|
||||
|
||||
return result;
|
||||
if (active) {
|
||||
g_return_val_if_fail (tee->has_chain, FALSE);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* won't be called until we implement an activate function */
|
||||
static gboolean
|
||||
gst_tee_sink_activate_pull (GstPad * pad, gboolean active)
|
||||
{
|
||||
GstTee *tee;
|
||||
|
||||
tee = GST_TEE (GST_OBJECT_PARENT (pad));
|
||||
|
||||
tee->sink_mode = active && GST_ACTIVATE_PULL;
|
||||
|
||||
if (active) {
|
||||
g_return_val_if_fail (tee->has_sink_loop, FALSE);
|
||||
return gst_pad_start_task (pad, (GstTaskFunction) gst_tee_loop, pad);
|
||||
} else {
|
||||
return gst_pad_stop_task (pad);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -133,8 +133,9 @@ static gboolean gst_type_find_element_checkgetrange (GstPad * srcpad);
|
|||
|
||||
static GstElementStateReturn
|
||||
gst_type_find_element_change_state (GstElement * element);
|
||||
static gboolean gst_type_find_element_activate (GstPad * pad);
|
||||
static gboolean
|
||||
gst_type_find_element_activate (GstPad * pad, GstActivateMode mode);
|
||||
gst_type_find_element_activate_src_pull (GstPad * pad, gboolean active);
|
||||
|
||||
static guint gst_type_find_element_signals[LAST_SIGNAL] = { 0 };
|
||||
|
||||
|
@ -215,7 +216,8 @@ gst_type_find_element_init (GstTypeFindElement * typefind)
|
|||
typefind->src =
|
||||
gst_pad_new_from_template (gst_static_pad_template_get
|
||||
(&type_find_element_src_template), "src");
|
||||
gst_pad_set_activate_function (typefind->src, gst_type_find_element_activate);
|
||||
gst_pad_set_activatepull_function (typefind->src,
|
||||
gst_type_find_element_activate_src_pull);
|
||||
gst_pad_set_checkgetrange_function (typefind->src,
|
||||
gst_type_find_element_checkgetrange);
|
||||
gst_pad_set_getrange_function (typefind->src, gst_type_find_element_getrange);
|
||||
|
@ -749,56 +751,80 @@ gst_type_find_element_getrange (GstPad * srcpad,
|
|||
}
|
||||
|
||||
static gboolean
|
||||
do_pull_typefind (GstTypeFindElement * typefind)
|
||||
gst_type_find_element_activate_src_pull (GstPad * pad, gboolean active)
|
||||
{
|
||||
GstCaps *caps;
|
||||
GstPad *peer;
|
||||
gboolean res = FALSE;
|
||||
|
||||
peer = gst_pad_get_peer (typefind->sink);
|
||||
if (peer) {
|
||||
if (gst_pad_peer_set_active (typefind->sink, GST_ACTIVATE_PULL)) {
|
||||
gint64 size;
|
||||
GstFormat format = GST_FORMAT_BYTES;
|
||||
|
||||
gst_pad_query_position (peer, &format, NULL, &size);
|
||||
caps = gst_type_find_helper (peer, (guint64) size);
|
||||
if (caps) {
|
||||
g_signal_emit (typefind, gst_type_find_element_signals[HAVE_TYPE],
|
||||
0, 100, caps);
|
||||
typefind->mode = MODE_NORMAL;
|
||||
res = TRUE;
|
||||
}
|
||||
} else {
|
||||
start_typefinding (typefind);
|
||||
res = TRUE;
|
||||
}
|
||||
|
||||
gst_object_unref (GST_OBJECT (peer));
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_type_find_element_activate (GstPad * pad, GstActivateMode mode)
|
||||
{
|
||||
gboolean result;
|
||||
GstTypeFindElement *typefind;
|
||||
|
||||
typefind = GST_TYPE_FIND_ELEMENT (GST_OBJECT_PARENT (pad));
|
||||
|
||||
switch (mode) {
|
||||
case GST_ACTIVATE_PUSH:
|
||||
case GST_ACTIVATE_PULL:
|
||||
result = TRUE;
|
||||
break;
|
||||
default:
|
||||
result = TRUE;
|
||||
break;
|
||||
return gst_pad_activate_pull (typefind->sink, active);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_type_find_element_activate (GstPad * pad)
|
||||
{
|
||||
GstCaps *found_caps = NULL;
|
||||
GstTypeFindElement *typefind;
|
||||
|
||||
typefind = GST_TYPE_FIND_ELEMENT (GST_OBJECT_PARENT (pad));
|
||||
|
||||
/* 1. try to activate in pull mode. if not, switch to push and succeed.
|
||||
2. try to pull type find.
|
||||
3. deactivate pull mode.
|
||||
4. src pad might have been activated push by the state change. deactivate.
|
||||
5. if we didn't find any caps, fail.
|
||||
6. emit have-type; maybe the app connected the source pad to something.
|
||||
7. if the sink pad is activated, we are in pull mode. succeed.
|
||||
otherwise activate both pads in push mode and succeed.
|
||||
*/
|
||||
|
||||
/* 1 */
|
||||
if (!gst_pad_activate_pull (pad, TRUE)) {
|
||||
start_typefinding (typefind);
|
||||
return gst_pad_activate_push (pad, TRUE);
|
||||
}
|
||||
|
||||
return result;
|
||||
/* 2 */
|
||||
{
|
||||
GstPad *peer;
|
||||
|
||||
peer = gst_pad_get_peer (pad);
|
||||
if (peer) {
|
||||
gint64 size;
|
||||
GstFormat format = GST_FORMAT_BYTES;
|
||||
|
||||
gst_pad_query_position (peer, &format, NULL, &size);
|
||||
found_caps = gst_type_find_helper (peer, (guint64) size);
|
||||
gst_object_unref (GST_OBJECT (peer));
|
||||
}
|
||||
}
|
||||
|
||||
/* 3 */
|
||||
gst_pad_activate_pull (pad, FALSE);
|
||||
|
||||
/* 4 */
|
||||
gst_pad_activate_push (typefind->src, FALSE);
|
||||
|
||||
/* 5 */
|
||||
if (!found_caps)
|
||||
return FALSE;
|
||||
|
||||
/* 6 */
|
||||
g_signal_emit (typefind, gst_type_find_element_signals[HAVE_TYPE],
|
||||
0, 100, found_caps);
|
||||
typefind->mode = MODE_NORMAL;
|
||||
/* FIXME see if I can unref the caps here */
|
||||
|
||||
/* 7 */
|
||||
if (gst_pad_is_active (pad))
|
||||
return TRUE;
|
||||
else {
|
||||
gboolean ret;
|
||||
|
||||
ret = gst_pad_activate_push (typefind->src, TRUE);
|
||||
ret &= gst_pad_activate_push (pad, TRUE);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
static GstElementStateReturn
|
||||
|
@ -811,21 +837,11 @@ gst_type_find_element_change_state (GstElement * element)
|
|||
typefind = GST_TYPE_FIND_ELEMENT (element);
|
||||
|
||||
transition = GST_STATE_TRANSITION (element);
|
||||
switch (transition) {
|
||||
case GST_STATE_READY_TO_PAUSED:
|
||||
if (!do_pull_typefind (typefind))
|
||||
return GST_STATE_FAILURE;
|
||||
//start_typefinding (typefind);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ret = GST_ELEMENT_CLASS (parent_class)->change_state (element);
|
||||
|
||||
switch (transition) {
|
||||
case GST_STATE_PAUSED_TO_READY:
|
||||
//stop_typefinding (typefind);
|
||||
gst_caps_replace (&typefind->caps, NULL);
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -27,12 +27,6 @@
|
|||
#include "gstutils.h"
|
||||
#include "gstminiobject.h"
|
||||
|
||||
#ifndef GST_DISABLE_TRACE
|
||||
/* #define GST_WITH_ALLOC_TRACE */
|
||||
#include "gsttrace.h"
|
||||
|
||||
static GstAllocTrace *_gst_buffer_trace;
|
||||
#endif
|
||||
|
||||
static void gst_buffer_init (GTypeInstance * instance, gpointer g_class);
|
||||
static void gst_buffer_class_init (gpointer g_class, gpointer class_data);
|
||||
|
@ -43,11 +37,15 @@ static GstBuffer *_gst_buffer_copy (GstBuffer * buffer);
|
|||
void
|
||||
_gst_buffer_initialize (void)
|
||||
{
|
||||
gpointer ptr;
|
||||
|
||||
gst_buffer_get_type ();
|
||||
|
||||
#ifndef GST_DISABLE_TRACE
|
||||
_gst_buffer_trace = gst_alloc_trace_register (GST_BUFFER_TRACE_NAME);
|
||||
#endif
|
||||
/* the GstMiniObject types need to be class_ref'd once before it can be
|
||||
* done from multiple threads;
|
||||
* see http://bugzilla.gnome.org/show_bug.cgi?id=304551 */
|
||||
ptr = g_type_class_ref (GST_TYPE_BUFFER);
|
||||
g_type_class_unref (ptr);
|
||||
}
|
||||
|
||||
GType
|
||||
|
|
|
@ -434,6 +434,7 @@ gst_bus_source_finalize (GSource * source)
|
|||
GstBusSource *bsource = (GstBusSource *) source;
|
||||
|
||||
gst_object_unref (GST_OBJECT_CAST (bsource->bus));
|
||||
bsource->bus = NULL;
|
||||
}
|
||||
|
||||
static GSourceFuncs gst_bus_source_funcs = {
|
||||
|
|
192
gst/gstelement.c
192
gst/gstelement.c
|
@ -830,7 +830,7 @@ iterate_pad (GstIterator * it, GstPad * pad)
|
|||
*
|
||||
* Retrieves an iterattor of @element's pads.
|
||||
*
|
||||
* Returns: the #GstIterator of #GstPad. unref each pad after usage.
|
||||
* Returns: the #GstIterator of #GstPad. Unref each pad after use.
|
||||
*
|
||||
* MT safe.
|
||||
*/
|
||||
|
@ -854,6 +854,56 @@ gst_element_iterate_pads (GstElement * element)
|
|||
return result;
|
||||
}
|
||||
|
||||
static gint
|
||||
direction_filter (gconstpointer pad, gconstpointer direction)
|
||||
{
|
||||
if (GST_PAD_DIRECTION (pad) == GPOINTER_TO_INT (direction)) {
|
||||
/* pass the ref through */
|
||||
return 0;
|
||||
} else {
|
||||
/* unref */
|
||||
gst_object_unref (GST_OBJECT (pad));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_element_iterate_src_pads:
|
||||
* @element: a #GstElement.
|
||||
*
|
||||
* Retrieves an iterator of @element's source pads.
|
||||
*
|
||||
* Returns: the #GstIterator of #GstPad. Unref each pad after use.
|
||||
*
|
||||
* MT safe.
|
||||
*/
|
||||
GstIterator *
|
||||
gst_element_iterate_src_pads (GstElement * element)
|
||||
{
|
||||
g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
|
||||
|
||||
return gst_iterator_filter (gst_element_iterate_pads (element),
|
||||
direction_filter, GINT_TO_POINTER (GST_PAD_SRC));
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_element_iterate_sink_pads:
|
||||
* @element: a #GstElement.
|
||||
*
|
||||
* Retrieves an iterator of @element's sink pads.
|
||||
*
|
||||
* Returns: the #GstIterator of #GstPad. Unref each pad after use.
|
||||
*
|
||||
* MT safe.
|
||||
*/
|
||||
GstIterator *
|
||||
gst_element_iterate_sink_pads (GstElement * element)
|
||||
{
|
||||
g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
|
||||
|
||||
return gst_iterator_filter (gst_element_iterate_pads (element),
|
||||
direction_filter, GINT_TO_POINTER (GST_PAD_SINK));
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_element_class_add_pad_template:
|
||||
|
@ -1792,97 +1842,73 @@ invalid_return:
|
|||
}
|
||||
}
|
||||
|
||||
/* gst_iterator_fold functions for pads_activate */
|
||||
|
||||
static gboolean
|
||||
activate_pads (GstPad * pad, GValue * ret, gboolean * active)
|
||||
{
|
||||
if (!gst_pad_set_active (pad, *active))
|
||||
g_value_set_boolean (ret, FALSE);
|
||||
|
||||
gst_object_unref (GST_OBJECT (pad));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* returns false on error or early cutout of the fold, true otherwise */
|
||||
static gboolean
|
||||
iterator_fold_with_resync (GstIterator * iter, GstIteratorFoldFunction func,
|
||||
GValue * ret, gpointer user_data)
|
||||
{
|
||||
GstIteratorResult ires;
|
||||
gboolean res = TRUE;
|
||||
|
||||
while (1) {
|
||||
ires = gst_iterator_fold (iter, func, ret, user_data);
|
||||
|
||||
switch (ires) {
|
||||
case GST_ITERATOR_RESYNC:
|
||||
break;
|
||||
case GST_ITERATOR_DONE:
|
||||
res = TRUE;
|
||||
goto done;
|
||||
default:
|
||||
res = FALSE;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* is called with STATE_LOCK
|
||||
*
|
||||
* This function activates the pads of a given element.
|
||||
*
|
||||
* TODO: activate pads from src to sinks?
|
||||
* move pad activate logic to GstPad because we also need this
|
||||
* when pads are added to elements?
|
||||
*/
|
||||
static gboolean
|
||||
gst_element_pads_activate (GstElement * element, gboolean active)
|
||||
{
|
||||
GList *pads;
|
||||
gboolean result;
|
||||
guint32 cookie;
|
||||
GValue ret = { 0, };
|
||||
GstIterator *iter;
|
||||
gboolean fold_ok;
|
||||
|
||||
GST_LOCK (element);
|
||||
restart:
|
||||
result = TRUE;
|
||||
pads = element->pads;
|
||||
cookie = element->pads_cookie;
|
||||
for (; pads && result; pads = g_list_next (pads)) {
|
||||
GstPad *pad, *peer;
|
||||
gboolean pad_loop, pad_get;
|
||||
gboolean done = FALSE;
|
||||
/* no need to unset this later, it's just a boolean */
|
||||
g_value_init (&ret, G_TYPE_BOOLEAN);
|
||||
g_value_set_boolean (&ret, TRUE);
|
||||
|
||||
pad = GST_PAD (pads->data);
|
||||
gst_object_ref (GST_OBJECT (pad));
|
||||
GST_UNLOCK (element);
|
||||
iter = gst_element_iterate_src_pads (element);
|
||||
fold_ok = iterator_fold_with_resync
|
||||
(iter, (GstIteratorFoldFunction) activate_pads, &ret, &active);
|
||||
gst_iterator_free (iter);
|
||||
if (!fold_ok || !g_value_get_boolean (&ret))
|
||||
return FALSE;
|
||||
|
||||
if (active) {
|
||||
pad_get = GST_PAD_IS_SINK (pad) && gst_pad_check_pull_range (pad);
|
||||
iter = gst_element_iterate_sink_pads (element);
|
||||
fold_ok = iterator_fold_with_resync
|
||||
(iter, (GstIteratorFoldFunction) activate_pads, &ret, &active);
|
||||
gst_iterator_free (iter);
|
||||
if (!fold_ok || !g_value_get_boolean (&ret))
|
||||
return FALSE;
|
||||
|
||||
/* see if the pad has a loop function and grab
|
||||
* the peer */
|
||||
GST_LOCK (pad);
|
||||
pad_loop = GST_PAD_LOOPFUNC (pad) != NULL;
|
||||
peer = GST_PAD_PEER (pad);
|
||||
if (peer)
|
||||
gst_object_ref (GST_OBJECT_CAST (peer));
|
||||
GST_UNLOCK (pad);
|
||||
|
||||
GST_DEBUG ("pad %s:%s: get: %d, loop: %d",
|
||||
GST_DEBUG_PAD_NAME (pad), pad_get, pad_loop);
|
||||
|
||||
if (peer) {
|
||||
gboolean peer_loop, peer_get;
|
||||
|
||||
/* see if the peer has a getrange function */
|
||||
peer_get = GST_PAD_IS_SINK (peer)
|
||||
&& gst_pad_check_pull_range (GST_PAD_CAST (peer));
|
||||
/* see if the peer has a loop function */
|
||||
peer_loop = GST_PAD_LOOPFUNC (peer) != NULL;
|
||||
|
||||
GST_DEBUG ("peer %s:%s: get: %d, loop: %d",
|
||||
GST_DEBUG_PAD_NAME (peer), peer_get, peer_loop);
|
||||
|
||||
/* If the pad is a sink with loop and the peer has a get function,
|
||||
* we can activate the sinkpad, FIXME, logic is reversed as
|
||||
* check_pull_range() checks the peer of the given pad. */
|
||||
if ((pad_get && pad_loop) || (peer_get && peer_loop)) {
|
||||
GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
|
||||
"activating pad %s in pull mode", GST_OBJECT_NAME (pad));
|
||||
|
||||
result &= gst_pad_set_active (pad, GST_ACTIVATE_PULL);
|
||||
done = TRUE;
|
||||
}
|
||||
gst_object_unref (GST_OBJECT_CAST (peer));
|
||||
}
|
||||
|
||||
if (!done) {
|
||||
/* all other conditions are just push based pads */
|
||||
GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
|
||||
"activating pad %s in push mode", GST_OBJECT_NAME (pad));
|
||||
|
||||
result &= gst_pad_set_active (pad, GST_ACTIVATE_PUSH);
|
||||
}
|
||||
} else {
|
||||
GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
|
||||
"deactivating pad %s", GST_OBJECT_NAME (pad));
|
||||
|
||||
result &= gst_pad_set_active (pad, GST_ACTIVATE_NONE);
|
||||
}
|
||||
|
||||
gst_object_unref (GST_OBJECT_CAST (pad));
|
||||
GST_LOCK (element);
|
||||
if (cookie != element->pads_cookie)
|
||||
goto restart;
|
||||
}
|
||||
GST_UNLOCK (element);
|
||||
|
||||
return result;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* is called with STATE_LOCK */
|
||||
|
|
|
@ -305,7 +305,9 @@ GstPad* gst_element_get_static_pad (GstElement *element, const gchar *name);
|
|||
GstPad* gst_element_get_request_pad (GstElement *element, const gchar *name);
|
||||
void gst_element_release_request_pad (GstElement *element, GstPad *pad);
|
||||
|
||||
GstIterator * gst_element_iterate_pads (GstElement * element);
|
||||
GstIterator * gst_element_iterate_pads (GstElement * element);
|
||||
GstIterator * gst_element_iterate_src_pads (GstElement * element);
|
||||
GstIterator * gst_element_iterate_sink_pads (GstElement * element);
|
||||
|
||||
/* event/query/format stuff */
|
||||
gboolean gst_element_send_event (GstElement *element, GstEvent *event);
|
||||
|
|
|
@ -30,11 +30,6 @@
|
|||
#include "gsttag.h"
|
||||
#include "gstutils.h"
|
||||
|
||||
#ifndef GST_DISABLE_TRACE
|
||||
/* #define GST_WITH_ALLOC_TRACE */
|
||||
#include "gsttrace.h"
|
||||
static GstAllocTrace *_event_trace;
|
||||
#endif
|
||||
|
||||
static void gst_event_init (GTypeInstance * instance, gpointer g_class);
|
||||
static void gst_event_class_init (gpointer g_class, gpointer class_data);
|
||||
|
@ -45,10 +40,6 @@ void
|
|||
_gst_event_initialize (void)
|
||||
{
|
||||
gst_event_get_type ();
|
||||
|
||||
#ifndef GST_DISABLE_TRACE
|
||||
_event_trace = gst_alloc_trace_register (GST_EVENT_TRACE_NAME);
|
||||
#endif
|
||||
}
|
||||
|
||||
GType
|
||||
|
|
|
@ -160,13 +160,51 @@ gst_proxy_pad_do_bufferalloc (GstPad * pad, guint64 offset, guint size,
|
|||
}
|
||||
|
||||
static gboolean
|
||||
gst_proxy_pad_do_activate (GstPad * pad, GstActivateMode mode)
|
||||
gst_proxy_pad_do_activate (GstPad * pad)
|
||||
{
|
||||
GstPad *target = GST_PROXY_PAD_TARGET (pad);
|
||||
|
||||
g_return_val_if_fail (target != NULL, FALSE);
|
||||
|
||||
return gst_pad_set_active (target, mode);
|
||||
return target->activatefunc (pad);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_proxy_pad_do_activatepull (GstPad * pad, gboolean active)
|
||||
{
|
||||
GstActivateMode old;
|
||||
GstPad *target = GST_PROXY_PAD_TARGET (pad);
|
||||
|
||||
g_return_val_if_fail (target != NULL, FALSE);
|
||||
|
||||
GST_LOCK (target);
|
||||
old = GST_PAD_ACTIVATE_MODE (target);
|
||||
GST_UNLOCK (target);
|
||||
|
||||
if ((active && old == GST_ACTIVATE_PULL)
|
||||
|| (!active && old == GST_ACTIVATE_NONE))
|
||||
return TRUE;
|
||||
else
|
||||
return gst_pad_activate_pull (target, active);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_proxy_pad_do_activatepush (GstPad * pad, gboolean active)
|
||||
{
|
||||
GstActivateMode old;
|
||||
GstPad *target = GST_PROXY_PAD_TARGET (pad);
|
||||
|
||||
g_return_val_if_fail (target != NULL, FALSE);
|
||||
|
||||
GST_LOCK (target);
|
||||
old = GST_PAD_ACTIVATE_MODE (target);
|
||||
GST_UNLOCK (target);
|
||||
|
||||
if ((active && old == GST_ACTIVATE_PUSH)
|
||||
|| (!active && old == GST_ACTIVATE_NONE))
|
||||
return TRUE;
|
||||
else
|
||||
return gst_pad_activate_push (target, active);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -275,6 +313,8 @@ gst_proxy_pad_set_property (GObject * object, guint prop_id,
|
|||
SETFUNC (queryfunc, query);
|
||||
SETFUNC (intlinkfunc, internal_link);
|
||||
SETFUNC (activatefunc, activate);
|
||||
SETFUNC (activatepullfunc, activatepull);
|
||||
SETFUNC (activatepushfunc, activatepush);
|
||||
SETFUNC (loopfunc, loop);
|
||||
SETFUNC (getcapsfunc, getcaps);
|
||||
SETFUNC (acceptcapsfunc, acceptcaps);
|
||||
|
@ -437,6 +477,25 @@ gst_ghost_pad_class_init (GstGhostPadClass * klass)
|
|||
"The ghost pad's internal pad", GST_TYPE_PAD, G_PARAM_READWRITE));
|
||||
}
|
||||
|
||||
/* will only be called for src pads (afaict) */
|
||||
static gboolean
|
||||
gst_ghost_proxy_pad_do_activate_pull (GstPad * pad, gboolean active)
|
||||
{
|
||||
GstObject *parent;
|
||||
gboolean ret = FALSE;
|
||||
|
||||
parent = gst_object_get_parent (GST_OBJECT (pad));
|
||||
if (parent) {
|
||||
/* hacky hacky!!! */
|
||||
if (GST_IS_GHOST_PAD (parent))
|
||||
ret = gst_pad_activate_pull (GST_PAD (parent), active);
|
||||
|
||||
gst_object_unref (parent);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static GstPadLinkReturn
|
||||
gst_ghost_pad_do_link (GstPad * pad, GstPad * peer)
|
||||
{
|
||||
|
@ -474,7 +533,7 @@ gst_ghost_pad_do_unlink (GstPad * pad)
|
|||
if (target->unlinkfunc)
|
||||
target->unlinkfunc (target);
|
||||
|
||||
/* doesn't work with the object locks in the properties dispatcher... */
|
||||
/* FIXME: should do this here, but locks in deep_notify prevent it */
|
||||
/* g_object_set (pad, "internal", NULL, NULL); */
|
||||
}
|
||||
|
||||
|
@ -509,6 +568,8 @@ gst_ghost_pad_set_property (GObject * object, guint prop_id,
|
|||
if (pad->internal) {
|
||||
GstPad *intpeer;
|
||||
|
||||
gst_pad_set_activatepull_function (pad->internal, NULL);
|
||||
|
||||
g_signal_handler_disconnect (pad->internal, pad->notify_id);
|
||||
|
||||
intpeer = gst_pad_get_peer (pad->internal);
|
||||
|
@ -521,11 +582,6 @@ gst_ghost_pad_set_property (GObject * object, guint prop_id,
|
|||
gst_object_unref (GST_OBJECT (intpeer));
|
||||
}
|
||||
|
||||
/* delete me, only here for testing... */
|
||||
if (GST_OBJECT_REFCOUNT_VALUE (pad->internal) != 1) {
|
||||
gst_critical ("Refcounting problem: %" GST_PTR_FORMAT, pad->internal);
|
||||
}
|
||||
|
||||
/* should dispose it */
|
||||
gst_object_unparent (GST_OBJECT_CAST (pad->internal));
|
||||
}
|
||||
|
@ -546,6 +602,8 @@ gst_ghost_pad_set_property (GObject * object, guint prop_id,
|
|||
pad->notify_id = g_signal_connect (internal, "notify::caps",
|
||||
G_CALLBACK (on_int_notify), pad);
|
||||
on_int_notify (internal, NULL, pad);
|
||||
gst_pad_set_activatepull_function (internal,
|
||||
gst_ghost_proxy_pad_do_activate_pull);
|
||||
|
||||
/* a ref was taken by set_parent */
|
||||
}
|
||||
|
|
|
@ -29,17 +29,13 @@
|
|||
#include "gsttag.h"
|
||||
#include "gstutils.h"
|
||||
|
||||
#ifndef GST_DISABLE_TRACE
|
||||
/* #define GST_WITH_ALLOC_TRACE */
|
||||
#include "gsttrace.h"
|
||||
static GstAllocTrace *_message_trace;
|
||||
#endif
|
||||
|
||||
static void gst_message_init (GTypeInstance * instance, gpointer g_class);
|
||||
static void gst_message_class_init (gpointer g_class, gpointer class_data);
|
||||
static void gst_message_finalize (GstMessage * message);
|
||||
static GstMessage *_gst_message_copy (GstMessage * message);
|
||||
|
||||
|
||||
void
|
||||
_gst_message_initialize (void)
|
||||
{
|
||||
|
@ -54,10 +50,6 @@ _gst_message_initialize (void)
|
|||
* see http://bugzilla.gnome.org/show_bug.cgi?id=304551 */
|
||||
ptr = g_type_class_ref (GST_TYPE_MESSAGE);
|
||||
g_type_class_unref (ptr);
|
||||
|
||||
#ifndef GST_DISABLE_TRACE
|
||||
_message_trace = gst_alloc_trace_register (GST_MESSAGE_TRACE_NAME);
|
||||
#endif
|
||||
}
|
||||
|
||||
GType
|
||||
|
|
|
@ -23,6 +23,10 @@
|
|||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#ifndef GST_DISABLE_TRACE
|
||||
#include "gsttrace.h"
|
||||
#endif
|
||||
|
||||
#include "gst/gstminiobject.h"
|
||||
#include "gst/gstinfo.h"
|
||||
#include "gst/gst_private.h"
|
||||
|
@ -130,6 +134,21 @@ gst_mini_object_new (GType type)
|
|||
|
||||
mini_object = (GstMiniObject *) g_type_create_instance (type);
|
||||
|
||||
#ifndef GST_DISABLE_TRACE
|
||||
{
|
||||
const gchar *name;
|
||||
GstAllocTrace *trace;
|
||||
|
||||
name = g_type_name (type);
|
||||
|
||||
trace = gst_alloc_trace_get (name);
|
||||
if (!trace) {
|
||||
trace = gst_alloc_trace_register (name);
|
||||
}
|
||||
gst_alloc_trace_new (trace, mini_object);
|
||||
}
|
||||
#endif
|
||||
|
||||
return mini_object;
|
||||
}
|
||||
|
||||
|
@ -151,12 +170,18 @@ gst_mini_object_is_writable (const GstMiniObject * mini_object)
|
|||
}
|
||||
|
||||
GstMiniObject *
|
||||
gst_mini_object_make_writable (const GstMiniObject * mini_object)
|
||||
gst_mini_object_make_writable (GstMiniObject * mini_object)
|
||||
{
|
||||
GstMiniObject *ret;
|
||||
|
||||
if (gst_mini_object_is_writable (mini_object)) {
|
||||
return (GstMiniObject *) mini_object;
|
||||
ret = (GstMiniObject *) mini_object;
|
||||
} else {
|
||||
ret = gst_mini_object_copy (mini_object);
|
||||
gst_mini_object_unref ((GstMiniObject *) mini_object);
|
||||
}
|
||||
return gst_mini_object_copy (mini_object);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
GstMiniObject *
|
||||
|
@ -180,8 +205,24 @@ gst_mini_object_free (GstMiniObject * mini_object)
|
|||
|
||||
/* if the refcount is still 0 we can really free the
|
||||
* object, else the finalize method recycled the object */
|
||||
if (g_atomic_int_get (&mini_object->refcount) == 0)
|
||||
if (g_atomic_int_get (&mini_object->refcount) == 0) {
|
||||
#ifndef GST_DISABLE_TRACE
|
||||
{
|
||||
const gchar *name;
|
||||
GstAllocTrace *trace;
|
||||
|
||||
name = g_type_name (G_TYPE_FROM_CLASS (mo_class));
|
||||
|
||||
trace = gst_alloc_trace_get (name);
|
||||
if (G_LIKELY (trace)) {
|
||||
gst_alloc_trace_free (trace, mini_object);
|
||||
} else {
|
||||
g_warning ("Untraced miniobject: (%s)%p", name, mini_object);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
g_type_free_instance ((GTypeInstance *) mini_object);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -81,7 +81,7 @@ GType gst_mini_object_get_type (void);
|
|||
GstMiniObject * gst_mini_object_new (GType type);
|
||||
GstMiniObject * gst_mini_object_copy (const GstMiniObject *mini_object);
|
||||
gboolean gst_mini_object_is_writable (const GstMiniObject *mini_object);
|
||||
GstMiniObject * gst_mini_object_make_writable (const GstMiniObject *mini_object);
|
||||
GstMiniObject * gst_mini_object_make_writable (GstMiniObject *mini_object);
|
||||
|
||||
GstMiniObject * gst_mini_object_ref (GstMiniObject *mini_object);
|
||||
void gst_mini_object_unref (GstMiniObject *mini_object);
|
||||
|
|
359
gst/gstpad.c
359
gst/gstpad.c
|
@ -90,6 +90,7 @@ static void gst_pad_get_property (GObject * object, guint prop_id,
|
|||
|
||||
static GstCaps *gst_pad_get_caps_unlocked (GstPad * pad);
|
||||
static void gst_pad_set_pad_template (GstPad * pad, GstPadTemplate * templ);
|
||||
static gboolean gst_pad_activate_default (GstPad * pad);
|
||||
|
||||
#ifndef GST_DISABLE_LOADSAVE
|
||||
static xmlNodePtr gst_pad_save_thyself (GstObject * object, xmlNodePtr parent);
|
||||
|
@ -181,6 +182,7 @@ gst_pad_init (GstPad * pad)
|
|||
pad->linkfunc = NULL;
|
||||
pad->getcapsfunc = NULL;
|
||||
|
||||
pad->activatefunc = gst_pad_activate_default;
|
||||
pad->eventfunc = gst_pad_event_default;
|
||||
pad->querytypefunc = gst_pad_get_query_types_default;
|
||||
pad->queryfunc = gst_pad_query_default;
|
||||
|
@ -394,172 +396,265 @@ gst_pad_get_direction (GstPad * pad)
|
|||
return result;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_pad_activate_default (GstPad * pad)
|
||||
{
|
||||
return gst_pad_activate_push (pad, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
pre_activate_switch (GstPad * pad, gboolean new_active)
|
||||
{
|
||||
if (new_active) {
|
||||
return;
|
||||
} else {
|
||||
GST_LOCK (pad);
|
||||
GST_PAD_SET_FLUSHING (pad);
|
||||
/* unlock blocked pads so element can resume and stop */
|
||||
GST_PAD_BLOCK_SIGNAL (pad);
|
||||
GST_UNLOCK (pad);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
post_activate_switch (GstPad * pad, gboolean new_active)
|
||||
{
|
||||
if (new_active) {
|
||||
GST_LOCK (pad);
|
||||
GST_PAD_UNSET_FLUSHING (pad);
|
||||
GST_UNLOCK (pad);
|
||||
} else {
|
||||
/* make streaming stop */
|
||||
GST_STREAM_LOCK (pad);
|
||||
GST_STREAM_UNLOCK (pad);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_pad_set_active:
|
||||
* @pad: the #GstPad to activate or deactivate.
|
||||
* @mode: the mode of the pad.
|
||||
* @active: whether or not the pad should be active.
|
||||
*
|
||||
* Activates or deactivates the given pad in the given mode.
|
||||
* Activates or deactivates the given pad. Must be called with the STATE_LOCK.
|
||||
* Normally called from within core state change functions.
|
||||
*
|
||||
* For a source pad: PULL mode will call the getrange function,
|
||||
* PUSH mode will require the element to call _push() on the pad.
|
||||
* If @active, makes sure the pad is active. If it is already active, either in
|
||||
* push or pull mode, just return. Otherwise dispatches to the pad's activate
|
||||
* function to perform the actual activation.
|
||||
*
|
||||
* For a sink pad: PULL mode will require the element to call
|
||||
* the _pull_range() function, PUSH mode will call the chain function.
|
||||
* If not @active, checks the pad's current mode and calls
|
||||
* gst_pad_activate_push() or gst_pad_activate_pull(), as appropriate, with a
|
||||
* FALSE argument.
|
||||
*
|
||||
* Returns: TRUE if the operation was successfull.
|
||||
*
|
||||
* MT safe. Must be called with STATE_LOCK.
|
||||
*/
|
||||
gboolean
|
||||
gst_pad_set_active (GstPad * pad, gboolean active)
|
||||
{
|
||||
GstActivateMode old;
|
||||
gboolean ret;
|
||||
|
||||
g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
|
||||
|
||||
GST_LOCK (pad);
|
||||
old = GST_PAD_ACTIVATE_MODE (pad);
|
||||
GST_UNLOCK (pad);
|
||||
|
||||
if (active) {
|
||||
switch (old) {
|
||||
case GST_ACTIVATE_PUSH:
|
||||
case GST_ACTIVATE_PULL:
|
||||
ret = TRUE;
|
||||
break;
|
||||
case GST_ACTIVATE_NONE:
|
||||
ret = (GST_PAD_ACTIVATEFUNC (pad)) (pad);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (old) {
|
||||
case GST_ACTIVATE_PUSH:
|
||||
ret = gst_pad_activate_push (pad, FALSE);
|
||||
break;
|
||||
case GST_ACTIVATE_PULL:
|
||||
ret = gst_pad_activate_pull (pad, FALSE);
|
||||
break;
|
||||
case GST_ACTIVATE_NONE:
|
||||
ret = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_pad_activate_pull:
|
||||
* @pad: the #GstPad to activate or deactivate.
|
||||
* @active: whether or not the pad should be active.
|
||||
*
|
||||
* Activates or deactivates the given pad in pull mode via dispatching to the
|
||||
* pad's activatepullfunc. For use from within pad activation functions only.
|
||||
* When called on sink pads, will first proxy the call to the peer pad, which is
|
||||
* expected to activate its internally linked pads from within its activate_pull
|
||||
* function.
|
||||
*
|
||||
* If you don't know what this is, you probably don't want to call it.
|
||||
*
|
||||
* Returns: TRUE if the operation was successfull.
|
||||
*
|
||||
* MT safe.
|
||||
*/
|
||||
gboolean
|
||||
gst_pad_set_active (GstPad * pad, GstActivateMode mode)
|
||||
gst_pad_activate_pull (GstPad * pad, gboolean active)
|
||||
{
|
||||
GstActivateMode old;
|
||||
GstPadActivateFunction activatefunc;
|
||||
gboolean active, oldactive;
|
||||
|
||||
g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
|
||||
|
||||
GST_LOCK (pad);
|
||||
|
||||
active = GST_PAD_MODE_ACTIVATE (mode);
|
||||
old = GST_PAD_ACTIVATE_MODE (pad);
|
||||
oldactive = GST_PAD_MODE_ACTIVATE (old);
|
||||
GST_UNLOCK (pad);
|
||||
|
||||
/* if nothing changed, we can just exit */
|
||||
if (G_UNLIKELY (oldactive == active && old == mode))
|
||||
if ((active && old == GST_ACTIVATE_PULL)
|
||||
|| (!active && old == GST_ACTIVATE_NONE))
|
||||
goto was_ok;
|
||||
|
||||
/* FIXME, no mode switching yet, need more design docs first */
|
||||
#if 0
|
||||
if (G_UNLIKELY (old == mode))
|
||||
goto was_ok;
|
||||
#endif
|
||||
|
||||
/* make sure data is disallowed when going inactive or changing
|
||||
* mode
|
||||
*/
|
||||
if (!active || oldactive) {
|
||||
GST_CAT_DEBUG (GST_CAT_PADS, "de-activating pad %s:%s",
|
||||
GST_DEBUG_PAD_NAME (pad));
|
||||
GST_PAD_SET_FLUSHING (pad);
|
||||
/* unlock blocked pads so element can resume and stop */
|
||||
GST_PAD_BLOCK_SIGNAL (pad);
|
||||
}
|
||||
|
||||
if (active) {
|
||||
if (GST_PAD_DIRECTION (pad) == GST_PAD_SRC) {
|
||||
if (mode == GST_ACTIVATE_PULL) {
|
||||
if (!pad->getrangefunc)
|
||||
goto wrong_mode;
|
||||
} else {
|
||||
/* we can push if driven by a chain or loop on the sink pad.
|
||||
* peer pad is assumed to be active now. */
|
||||
}
|
||||
} else {
|
||||
/* sink pads */
|
||||
if (mode == GST_ACTIVATE_PULL) {
|
||||
/* the src can drive us with getrange */
|
||||
} else {
|
||||
if (!pad->chainfunc)
|
||||
goto wrong_mode;
|
||||
g_return_val_if_fail (old == GST_ACTIVATE_NONE, FALSE);
|
||||
} else {
|
||||
g_return_val_if_fail (old == GST_ACTIVATE_PULL, FALSE);
|
||||
}
|
||||
|
||||
if (gst_pad_get_direction (pad) == GST_PAD_SINK) {
|
||||
GstPad *peer = gst_pad_get_peer (pad);
|
||||
|
||||
if (peer) {
|
||||
if (!gst_pad_activate_pull (peer, active)) {
|
||||
GST_LOCK (peer);
|
||||
GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad,
|
||||
"activate_pull on peer (%s:%s) failed", GST_DEBUG_PAD_NAME (peer));
|
||||
GST_UNLOCK (peer);
|
||||
gst_object_unref (GST_OBJECT (peer));
|
||||
goto failure;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
activatefunc = pad->activatefunc;
|
||||
if (activatefunc) {
|
||||
gboolean result;
|
||||
pre_activate_switch (pad, active);
|
||||
|
||||
GST_CAT_DEBUG (GST_CAT_PADS,
|
||||
"calling activate function on pad %s:%s with mode %d",
|
||||
GST_DEBUG_PAD_NAME (pad), mode);
|
||||
|
||||
/* unlock so element can sync */
|
||||
GST_UNLOCK (pad);
|
||||
result = activatefunc (pad, mode);
|
||||
/* and lock again */
|
||||
GST_LOCK (pad);
|
||||
if (result == FALSE)
|
||||
goto activate_error;
|
||||
}
|
||||
/* store the mode */
|
||||
GST_PAD_ACTIVATE_MODE (pad) = mode;
|
||||
|
||||
/* when going to active allow data passing now */
|
||||
if (active) {
|
||||
GST_CAT_DEBUG (GST_CAT_PADS, "activating pad %s:%s in mode %d",
|
||||
GST_DEBUG_PAD_NAME (pad), mode);
|
||||
GST_PAD_UNSET_FLUSHING (pad);
|
||||
GST_UNLOCK (pad);
|
||||
if (GST_PAD_ACTIVATEPULLFUNC (pad)) {
|
||||
if (GST_PAD_ACTIVATEPULLFUNC (pad) (pad, active)) {
|
||||
goto success;
|
||||
} else {
|
||||
goto failure;
|
||||
}
|
||||
} else {
|
||||
GST_UNLOCK (pad);
|
||||
|
||||
/* and make streaming finish */
|
||||
GST_STREAM_LOCK (pad);
|
||||
GST_STREAM_UNLOCK (pad);
|
||||
/* can happen for sinks of passthrough elements */
|
||||
goto success;
|
||||
}
|
||||
return TRUE;
|
||||
|
||||
was_ok:
|
||||
{
|
||||
GST_CAT_DEBUG (GST_CAT_PADS,
|
||||
"pad %s:%s was active, old %d, new %d",
|
||||
GST_DEBUG_PAD_NAME (pad), old, mode);
|
||||
GST_UNLOCK (pad);
|
||||
GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "already %s in pull mode",
|
||||
active ? "activated" : "deactivated");
|
||||
return TRUE;
|
||||
}
|
||||
/* errors */
|
||||
wrong_mode:
|
||||
|
||||
success:
|
||||
{
|
||||
GST_CAT_DEBUG (GST_CAT_PADS,
|
||||
"pad %s:%s lacks functions to be active in mode %d",
|
||||
GST_DEBUG_PAD_NAME (pad), mode);
|
||||
GST_LOCK (pad);
|
||||
GST_PAD_ACTIVATE_MODE (pad) =
|
||||
active ? GST_ACTIVATE_PULL : GST_ACTIVATE_NONE;
|
||||
GST_UNLOCK (pad);
|
||||
return FALSE;
|
||||
post_activate_switch (pad, active);
|
||||
|
||||
GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "%s in pull mode",
|
||||
active ? "activated" : "deactivated");
|
||||
return TRUE;
|
||||
}
|
||||
activate_error:
|
||||
|
||||
failure:
|
||||
{
|
||||
GST_CAT_DEBUG (GST_CAT_PADS,
|
||||
"activate function returned FALSE for pad %s:%s",
|
||||
GST_DEBUG_PAD_NAME (pad));
|
||||
GST_UNLOCK (pad);
|
||||
GST_CAT_INFO_OBJECT (GST_CAT_PADS, pad, "failed to %s in pull mode",
|
||||
active ? "activate" : "deactivate");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_pad_peer_set_active:
|
||||
* @pad: the #GstPad to activate or deactivate the peer of.
|
||||
* @mode: the mode of the pad.
|
||||
* gst_pad_activate_push:
|
||||
* @pad: the #GstPad to activate or deactivate.
|
||||
* @active: whether or not the pad should be active.
|
||||
*
|
||||
* Activates or deactivates the given peer of a pad. Elements
|
||||
* that will perform a _pull_range() on their sinkpads need
|
||||
* to call this function when the sinkpad is activated or when
|
||||
* an internally linked source pad is activated in pull mode.
|
||||
* Activates or deactivates the given pad in push mode via dispatching to the
|
||||
* pad's activatepushfunc. For use from within pad activation functions only.
|
||||
*
|
||||
* If you don't know what this is, you probably don't want to call it.
|
||||
*
|
||||
* Returns: TRUE if the operation was successfull.
|
||||
*
|
||||
* MT safe.
|
||||
*/
|
||||
gboolean
|
||||
gst_pad_peer_set_active (GstPad * pad, GstActivateMode mode)
|
||||
gst_pad_activate_push (GstPad * pad, gboolean active)
|
||||
{
|
||||
GstPad *peer;
|
||||
gboolean result = FALSE;
|
||||
GstActivateMode old;
|
||||
|
||||
peer = gst_pad_get_peer (pad);
|
||||
if (!peer)
|
||||
goto no_peer;
|
||||
g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
|
||||
|
||||
result = gst_pad_set_active (peer, mode);
|
||||
gst_object_unref (GST_OBJECT_CAST (peer));
|
||||
GST_LOCK (pad);
|
||||
old = GST_PAD_ACTIVATE_MODE (pad);
|
||||
GST_UNLOCK (pad);
|
||||
|
||||
return result;
|
||||
if ((active && old == GST_ACTIVATE_PUSH)
|
||||
|| (!active && old == GST_ACTIVATE_NONE))
|
||||
goto was_ok;
|
||||
|
||||
/* errors */
|
||||
no_peer:
|
||||
if (active) {
|
||||
g_return_val_if_fail (old == GST_ACTIVATE_NONE, FALSE);
|
||||
} else {
|
||||
g_return_val_if_fail (old == GST_ACTIVATE_PUSH, FALSE);
|
||||
}
|
||||
|
||||
pre_activate_switch (pad, active);
|
||||
|
||||
if (GST_PAD_ACTIVATEPUSHFUNC (pad)) {
|
||||
if (GST_PAD_ACTIVATEPUSHFUNC (pad) (pad, active)) {
|
||||
goto success;
|
||||
} else {
|
||||
goto failure;
|
||||
}
|
||||
} else {
|
||||
/* quite ok, element relies on state change func to prepare itself */
|
||||
goto success;
|
||||
}
|
||||
|
||||
was_ok:
|
||||
{
|
||||
GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "already %s in push mode",
|
||||
active ? "activated" : "deactivated");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
success:
|
||||
{
|
||||
GST_LOCK (pad);
|
||||
GST_PAD_ACTIVATE_MODE (pad) =
|
||||
active ? GST_ACTIVATE_PUSH : GST_ACTIVATE_NONE;
|
||||
GST_UNLOCK (pad);
|
||||
post_activate_switch (pad, active);
|
||||
|
||||
GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "%s in push mode",
|
||||
active ? "activated" : "deactivated");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
failure:
|
||||
{
|
||||
GST_CAT_INFO_OBJECT (GST_CAT_PADS, pad, "failed to %s in push mode",
|
||||
active ? "activate" : "deactivate");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
@ -721,8 +816,11 @@ gst_pad_is_blocked (GstPad * pad)
|
|||
* @pad: a sink #GstPad.
|
||||
* @chain: the #GstPadActivateFunction to set.
|
||||
*
|
||||
* Sets the given activate function for the pad. The activate function is called to
|
||||
* start or stop dataflow on a pad.
|
||||
* Sets the given activate function for the pad. The activate function will
|
||||
* dispatch to activate_push or activate_pull to perform the actual activation.
|
||||
* Only makes sense to set on sink pads.
|
||||
*
|
||||
* Call this function if your sink pad can start a pull-based task.
|
||||
*/
|
||||
void
|
||||
gst_pad_set_activate_function (GstPad * pad, GstPadActivateFunction activate)
|
||||
|
@ -734,6 +832,45 @@ gst_pad_set_activate_function (GstPad * pad, GstPadActivateFunction activate)
|
|||
GST_DEBUG_PAD_NAME (pad), GST_DEBUG_FUNCPTR_NAME (activate));
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_pad_set_activatepull_function:
|
||||
* @pad: a sink #GstPad.
|
||||
* @chain: the #GstPadActivateModeFunction to set.
|
||||
*
|
||||
* Sets the given activate_pull function for the pad. An activate_pull function
|
||||
* prepares the element and any upstream connections for pulling. See XXX
|
||||
* part-activation.txt for details.
|
||||
*/
|
||||
void
|
||||
gst_pad_set_activatepull_function (GstPad * pad,
|
||||
GstPadActivateModeFunction activatepull)
|
||||
{
|
||||
g_return_if_fail (GST_IS_PAD (pad));
|
||||
|
||||
GST_PAD_ACTIVATEPULLFUNC (pad) = activatepull;
|
||||
GST_CAT_DEBUG (GST_CAT_PADS, "activatepullfunc for %s:%s set to %s",
|
||||
GST_DEBUG_PAD_NAME (pad), GST_DEBUG_FUNCPTR_NAME (activatepull));
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_pad_set_activatepush_function:
|
||||
* @pad: a sink #GstPad.
|
||||
* @chain: the #GstPadActivateModeFunction to set.
|
||||
*
|
||||
* Sets the given activate_push function for the pad. An activate_push function
|
||||
* prepares the element for pushing. See XXX part-activation.txt for details.
|
||||
*/
|
||||
void
|
||||
gst_pad_set_activatepush_function (GstPad * pad,
|
||||
GstPadActivateModeFunction activatepush)
|
||||
{
|
||||
g_return_if_fail (GST_IS_PAD (pad));
|
||||
|
||||
GST_PAD_ACTIVATEPUSHFUNC (pad) = activatepush;
|
||||
GST_CAT_DEBUG (GST_CAT_PADS, "activatepushfunc for %s:%s set to %s",
|
||||
GST_DEBUG_PAD_NAME (pad), GST_DEBUG_FUNCPTR_NAME (activatepush));
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_pad_set_loop_function:
|
||||
* @pad: a sink #GstPad.
|
||||
|
|
15
gst/gstpad.h
15
gst/gstpad.h
|
@ -91,7 +91,8 @@ typedef enum {
|
|||
#define GST_PAD_MODE_ACTIVATE(mode) ((mode) != GST_ACTIVATE_NONE)
|
||||
|
||||
/* pad states */
|
||||
typedef gboolean (*GstPadActivateFunction) (GstPad *pad, GstActivateMode mode);
|
||||
typedef gboolean (*GstPadActivateFunction) (GstPad *pad);
|
||||
typedef gboolean (*GstPadActivateModeFunction) (GstPad *pad, gboolean active);
|
||||
|
||||
/* data passing */
|
||||
typedef GstFlowReturn (*GstPadChainFunction) (GstPad *pad, GstBuffer *buffer);
|
||||
|
@ -173,6 +174,8 @@ struct _GstPad {
|
|||
GstPadFixateCapsFunction fixatecapsfunc;
|
||||
|
||||
GstPadActivateFunction activatefunc;
|
||||
GstPadActivateModeFunction activatepushfunc;
|
||||
GstPadActivateModeFunction activatepullfunc;
|
||||
|
||||
/* pad link */
|
||||
GstPadLinkFunction linkfunc;
|
||||
|
@ -229,6 +232,8 @@ struct _GstPadClass {
|
|||
#define GST_PAD_ACTIVATE_MODE(pad) (GST_PAD_CAST(pad)->mode)
|
||||
|
||||
#define GST_PAD_ACTIVATEFUNC(pad) (GST_PAD_CAST(pad)->activatefunc)
|
||||
#define GST_PAD_ACTIVATEPUSHFUNC(pad) (GST_PAD_CAST(pad)->activatepushfunc)
|
||||
#define GST_PAD_ACTIVATEPULLFUNC(pad) (GST_PAD_CAST(pad)->activatepullfunc)
|
||||
#define GST_PAD_LOOPFUNC(pad) (GST_PAD_CAST(pad)->loopfunc)
|
||||
#define GST_PAD_CHAINFUNC(pad) (GST_PAD_CAST(pad)->chainfunc)
|
||||
#define GST_PAD_CHECKGETRANGEFUNC(pad) (GST_PAD_CAST(pad)->checkgetrangefunc)
|
||||
|
@ -358,9 +363,11 @@ GstElement* gst_pad_get_parent (GstPad *pad);
|
|||
|
||||
GstPadDirection gst_pad_get_direction (GstPad *pad);
|
||||
|
||||
gboolean gst_pad_set_active (GstPad *pad, GstActivateMode mode);
|
||||
gboolean gst_pad_peer_set_active (GstPad *pad, GstActivateMode mode);
|
||||
gboolean gst_pad_set_active (GstPad *pad, gboolean active);
|
||||
gboolean gst_pad_is_active (GstPad *pad);
|
||||
gboolean gst_pad_activate_pull (GstPad *pad, gboolean active);
|
||||
gboolean gst_pad_activate_push (GstPad *pad, gboolean active);
|
||||
|
||||
gboolean gst_pad_set_blocked (GstPad *pad, gboolean blocked);
|
||||
gboolean gst_pad_set_blocked_async (GstPad *pad, gboolean blocked,
|
||||
GstPadBlockCallback callback, gpointer user_data);
|
||||
|
@ -377,6 +384,8 @@ GstFlowReturn gst_pad_alloc_buffer (GstPad *pad, guint64 offset, gint size,
|
|||
|
||||
/* data passing setup functions */
|
||||
void gst_pad_set_activate_function (GstPad *pad, GstPadActivateFunction activate);
|
||||
void gst_pad_set_activatepull_function (GstPad *pad, GstPadActivateModeFunction activatepull);
|
||||
void gst_pad_set_activatepush_function (GstPad *pad, GstPadActivateModeFunction activatepush);
|
||||
void gst_pad_set_loop_function (GstPad *pad, GstPadLoopFunction loop);
|
||||
void gst_pad_set_chain_function (GstPad *pad, GstPadChainFunction chain);
|
||||
void gst_pad_set_getrange_function (GstPad *pad, GstPadGetRangeFunction get);
|
||||
|
|
|
@ -125,7 +125,7 @@ gst_pipeline_class_init (gpointer g_class, gpointer class_data)
|
|||
G_PARAM_READWRITE));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_PLAY_TIMEOUT,
|
||||
g_param_spec_uint64 ("play-timeout", "Play Timeout",
|
||||
"Max timeout for going " "to PLAYING in nanoseconds", 0, G_MAXUINT64,
|
||||
"Max timeout for going to PLAYING in nanoseconds", 0, G_MAXUINT64,
|
||||
DEFAULT_PLAY_TIMEOUT, G_PARAM_READWRITE));
|
||||
|
||||
gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_pipeline_dispose);
|
||||
|
@ -153,19 +153,24 @@ gst_pipeline_init (GTypeInstance * instance, gpointer g_class)
|
|||
g_error ("Critical error: could not get scheduler \"%s\"\n"
|
||||
"Are you sure you have a registry ?\n"
|
||||
"Run gst-register as root if you haven't done so yet.", name);
|
||||
} else {
|
||||
gst_element_set_scheduler (GST_ELEMENT (pipeline), scheduler);
|
||||
/* set_scheduler refs the bus via gst_object_replace, we drop our ref */
|
||||
gst_object_unref ((GstObject *) scheduler);
|
||||
}
|
||||
bus = g_object_new (gst_bus_get_type (), NULL);
|
||||
gst_bus_set_sync_handler (bus,
|
||||
(GstBusSyncHandler) pipeline_bus_handler, pipeline);
|
||||
|
||||
pipeline->eosed = NULL;
|
||||
pipeline->delay = DEFAULT_DELAY;
|
||||
pipeline->play_timeout = DEFAULT_PLAY_TIMEOUT;
|
||||
/* we are our own manager */
|
||||
GST_ELEMENT_MANAGER (pipeline) = pipeline;
|
||||
|
||||
bus = g_object_new (gst_bus_get_type (), NULL);
|
||||
gst_bus_set_sync_handler (bus,
|
||||
(GstBusSyncHandler) pipeline_bus_handler, pipeline);
|
||||
gst_element_set_bus (GST_ELEMENT (pipeline), bus);
|
||||
/* set_bus refs the bus via gst_object_replace, we drop our ref */
|
||||
gst_object_unref ((GstObject *) bus);
|
||||
gst_element_set_scheduler (GST_ELEMENT (pipeline), scheduler);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -175,6 +180,7 @@ gst_pipeline_dispose (GObject * object)
|
|||
|
||||
gst_element_set_bus (GST_ELEMENT (pipeline), NULL);
|
||||
gst_scheduler_reset (GST_ELEMENT_SCHEDULER (object));
|
||||
gst_element_set_scheduler (GST_ELEMENT (pipeline), NULL);
|
||||
gst_object_replace ((GstObject **) & pipeline->fixed_clock, NULL);
|
||||
|
||||
G_OBJECT_CLASS (parent_class)->dispose (object);
|
||||
|
|
|
@ -140,8 +140,8 @@ static GstPadLinkReturn gst_queue_link_sink (GstPad * pad, GstPad * peer);
|
|||
static GstPadLinkReturn gst_queue_link_src (GstPad * pad, GstPad * peer);
|
||||
static void gst_queue_locked_flush (GstQueue * queue);
|
||||
|
||||
static gboolean gst_queue_src_activate (GstPad * pad, GstActivateMode mode);
|
||||
static gboolean gst_queue_sink_activate (GstPad * pad, GstActivateMode mode);
|
||||
static gboolean gst_queue_src_activate_push (GstPad * pad, gboolean active);
|
||||
static gboolean gst_queue_sink_activate_push (GstPad * pad, gboolean active);
|
||||
static GstElementStateReturn gst_queue_change_state (GstElement * element);
|
||||
|
||||
|
||||
|
@ -300,8 +300,8 @@ gst_queue_init (GstQueue * queue)
|
|||
"sink");
|
||||
gst_pad_set_chain_function (queue->sinkpad,
|
||||
GST_DEBUG_FUNCPTR (gst_queue_chain));
|
||||
gst_pad_set_activate_function (queue->sinkpad,
|
||||
GST_DEBUG_FUNCPTR (gst_queue_sink_activate));
|
||||
gst_pad_set_activatepush_function (queue->sinkpad,
|
||||
GST_DEBUG_FUNCPTR (gst_queue_sink_activate_push));
|
||||
gst_pad_set_event_function (queue->sinkpad,
|
||||
GST_DEBUG_FUNCPTR (gst_queue_handle_sink_event));
|
||||
gst_pad_set_link_function (queue->sinkpad,
|
||||
|
@ -316,8 +316,8 @@ gst_queue_init (GstQueue * queue)
|
|||
gst_pad_new_from_template (gst_static_pad_template_get (&srctemplate),
|
||||
"src");
|
||||
gst_pad_set_loop_function (queue->srcpad, GST_DEBUG_FUNCPTR (gst_queue_loop));
|
||||
gst_pad_set_activate_function (queue->srcpad,
|
||||
GST_DEBUG_FUNCPTR (gst_queue_src_activate));
|
||||
gst_pad_set_activatepush_function (queue->srcpad,
|
||||
GST_DEBUG_FUNCPTR (gst_queue_src_activate_push));
|
||||
gst_pad_set_link_function (queue->srcpad,
|
||||
GST_DEBUG_FUNCPTR (gst_queue_link_src));
|
||||
gst_pad_set_getcaps_function (queue->srcpad,
|
||||
|
@ -819,65 +819,55 @@ gst_queue_handle_src_query (GstPad * pad, GstQuery * query)
|
|||
}
|
||||
|
||||
static gboolean
|
||||
gst_queue_sink_activate (GstPad * pad, GstActivateMode mode)
|
||||
gst_queue_sink_activate_push (GstPad * pad, gboolean active)
|
||||
{
|
||||
gboolean result = FALSE;
|
||||
GstQueue *queue;
|
||||
|
||||
queue = GST_QUEUE (GST_OBJECT_PARENT (pad));
|
||||
|
||||
switch (mode) {
|
||||
case GST_ACTIVATE_PUSH:
|
||||
queue->flushing = FALSE;
|
||||
result = TRUE;
|
||||
break;
|
||||
case GST_ACTIVATE_PULL:
|
||||
result = FALSE;
|
||||
break;
|
||||
case GST_ACTIVATE_NONE:
|
||||
/* step 1, unblock chain and loop functions */
|
||||
GST_QUEUE_MUTEX_LOCK;
|
||||
queue->flushing = TRUE;
|
||||
gst_queue_locked_flush (queue);
|
||||
g_cond_signal (queue->item_del);
|
||||
GST_QUEUE_MUTEX_UNLOCK;
|
||||
if (active) {
|
||||
queue->flushing = FALSE;
|
||||
result = TRUE;
|
||||
} else {
|
||||
/* step 1, unblock chain and loop functions */
|
||||
GST_QUEUE_MUTEX_LOCK;
|
||||
queue->flushing = TRUE;
|
||||
gst_queue_locked_flush (queue);
|
||||
g_cond_signal (queue->item_del);
|
||||
GST_QUEUE_MUTEX_UNLOCK;
|
||||
|
||||
/* step 2, make sure streaming finishes */
|
||||
result = gst_pad_stop_task (pad);
|
||||
break;
|
||||
/* step 2, make sure streaming finishes */
|
||||
result = gst_pad_stop_task (pad);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_queue_src_activate (GstPad * pad, GstActivateMode mode)
|
||||
gst_queue_src_activate_push (GstPad * pad, gboolean active)
|
||||
{
|
||||
gboolean result = FALSE;
|
||||
GstQueue *queue;
|
||||
|
||||
queue = GST_QUEUE (GST_OBJECT_PARENT (pad));
|
||||
|
||||
switch (mode) {
|
||||
case GST_ACTIVATE_PUSH:
|
||||
GST_QUEUE_MUTEX_LOCK;
|
||||
queue->flushing = FALSE;
|
||||
result = gst_pad_start_task (pad, (GstTaskFunction) gst_queue_loop, pad);
|
||||
GST_QUEUE_MUTEX_UNLOCK;
|
||||
break;
|
||||
case GST_ACTIVATE_PULL:
|
||||
result = FALSE;
|
||||
break;
|
||||
case GST_ACTIVATE_NONE:
|
||||
/* step 1, unblock chain and loop functions */
|
||||
GST_QUEUE_MUTEX_LOCK;
|
||||
queue->flushing = TRUE;
|
||||
g_cond_signal (queue->item_add);
|
||||
GST_QUEUE_MUTEX_UNLOCK;
|
||||
if (active) {
|
||||
GST_QUEUE_MUTEX_LOCK;
|
||||
queue->flushing = FALSE;
|
||||
result = gst_pad_start_task (pad, (GstTaskFunction) gst_queue_loop, pad);
|
||||
GST_QUEUE_MUTEX_UNLOCK;
|
||||
} else {
|
||||
/* step 1, unblock chain and loop functions */
|
||||
GST_QUEUE_MUTEX_LOCK;
|
||||
queue->flushing = TRUE;
|
||||
g_cond_signal (queue->item_add);
|
||||
GST_QUEUE_MUTEX_UNLOCK;
|
||||
|
||||
/* step 2, make sure streaming finishes */
|
||||
result = gst_pad_stop_task (pad);
|
||||
break;
|
||||
/* step 2, make sure streaming finishes */
|
||||
result = gst_pad_stop_task (pad);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -254,15 +254,34 @@ gst_alloc_trace_live_all (void)
|
|||
return num;
|
||||
}
|
||||
|
||||
static gint
|
||||
compare_func (GstAllocTrace * a, GstAllocTrace * b)
|
||||
{
|
||||
return strcmp (a->name, b->name);
|
||||
}
|
||||
|
||||
static GList *
|
||||
gst_alloc_trace_list_sorted (void)
|
||||
{
|
||||
GList *ret;
|
||||
|
||||
ret = g_list_sort (g_list_copy (_gst_alloc_tracers),
|
||||
(GCompareFunc) compare_func);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_alloc_trace_print_all:
|
||||
*
|
||||
* Print the status of all registered alloc trace objectes.
|
||||
* Print the status of all registered alloc trace objects.
|
||||
*/
|
||||
void
|
||||
gst_alloc_trace_print_all (void)
|
||||
{
|
||||
GList *walk = _gst_alloc_tracers;
|
||||
GList *orig, *walk;
|
||||
|
||||
orig = walk = gst_alloc_trace_list_sorted ();
|
||||
|
||||
while (walk) {
|
||||
GstAllocTrace *trace = (GstAllocTrace *) walk->data;
|
||||
|
@ -271,6 +290,33 @@ gst_alloc_trace_print_all (void)
|
|||
|
||||
walk = g_list_next (walk);
|
||||
}
|
||||
|
||||
g_list_free (orig);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_alloc_trace_print_live:
|
||||
*
|
||||
* Print the status of all registered alloc trace objects, ignoring those
|
||||
* without live objects.
|
||||
*/
|
||||
void
|
||||
gst_alloc_trace_print_live (void)
|
||||
{
|
||||
GList *orig, *walk;
|
||||
|
||||
orig = walk = gst_alloc_trace_list_sorted ();
|
||||
|
||||
while (walk) {
|
||||
GstAllocTrace *trace = (GstAllocTrace *) walk->data;
|
||||
|
||||
if (trace->live)
|
||||
gst_alloc_trace_print (trace);
|
||||
|
||||
walk = g_list_next (walk);
|
||||
}
|
||||
|
||||
g_list_free (orig);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -336,27 +382,20 @@ gst_alloc_trace_print (const GstAllocTrace * trace)
|
|||
|
||||
g_return_if_fail (trace != NULL);
|
||||
|
||||
g_print ("%s (%p): flags %d", trace->name, trace, trace->flags);
|
||||
|
||||
if (trace->flags & GST_ALLOC_TRACE_LIVE) {
|
||||
g_print (", live %d", trace->live);
|
||||
g_print ("%-22.22s : %d\n", trace->name, trace->live);
|
||||
} else {
|
||||
g_print ("%-22.22s : (no live count)\n", trace->name);
|
||||
}
|
||||
|
||||
if (trace->flags & GST_ALLOC_TRACE_MEM_LIVE) {
|
||||
mem_live = trace->mem_live;
|
||||
|
||||
if (!mem_live) {
|
||||
g_print (", no live memory");
|
||||
} else {
|
||||
g_print (", dumping live memory: ");
|
||||
|
||||
while (mem_live) {
|
||||
g_print ("%p ", mem_live->data);
|
||||
mem_live = g_slist_next (mem_live);
|
||||
}
|
||||
g_print ("\ntotal %d", g_slist_length (trace->mem_live));
|
||||
while (mem_live) {
|
||||
g_print ("%-22.22s : %p\n", "", mem_live->data);
|
||||
mem_live = mem_live->next;
|
||||
}
|
||||
}
|
||||
g_print ("\n");
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -91,6 +91,7 @@ GstAllocTrace* _gst_alloc_trace_register (const gchar *name);
|
|||
|
||||
int gst_alloc_trace_live_all (void);
|
||||
void gst_alloc_trace_print_all (void);
|
||||
void gst_alloc_trace_print_live (void);
|
||||
void gst_alloc_trace_set_flags_all (GstAllocTraceFlags flags);
|
||||
|
||||
GstAllocTrace* gst_alloc_trace_get (const gchar *name);
|
||||
|
|
|
@ -100,7 +100,8 @@ static GstElementStateReturn gst_basesink_change_state (GstElement * element);
|
|||
static GstFlowReturn gst_basesink_chain (GstPad * pad, GstBuffer * buffer);
|
||||
static void gst_basesink_loop (GstPad * pad);
|
||||
static GstFlowReturn gst_basesink_chain (GstPad * pad, GstBuffer * buffer);
|
||||
static gboolean gst_basesink_activate (GstPad * pad, GstActivateMode mode);
|
||||
static gboolean gst_basesink_activate_push (GstPad * pad, gboolean active);
|
||||
static gboolean gst_basesink_activate_pull (GstPad * pad, gboolean active);
|
||||
static gboolean gst_basesink_event (GstPad * pad, GstEvent * event);
|
||||
static inline GstFlowReturn gst_basesink_handle_buffer (GstBaseSink * basesink,
|
||||
GstBuffer * buf);
|
||||
|
@ -256,8 +257,10 @@ gst_basesink_finalize (GObject * object)
|
|||
static void
|
||||
gst_basesink_set_pad_functions (GstBaseSink * this, GstPad * pad)
|
||||
{
|
||||
gst_pad_set_activate_function (pad,
|
||||
GST_DEBUG_FUNCPTR (gst_basesink_activate));
|
||||
gst_pad_set_activatepush_function (pad,
|
||||
GST_DEBUG_FUNCPTR (gst_basesink_activate_push));
|
||||
gst_pad_set_activatepull_function (pad,
|
||||
GST_DEBUG_FUNCPTR (gst_basesink_activate_pull));
|
||||
gst_pad_set_event_function (pad, GST_DEBUG_FUNCPTR (gst_basesink_event));
|
||||
|
||||
if (this->has_chain)
|
||||
|
@ -824,51 +827,72 @@ paused:
|
|||
}
|
||||
|
||||
static gboolean
|
||||
gst_basesink_activate (GstPad * pad, GstActivateMode mode)
|
||||
gst_basesink_deactivate (GstBaseSink * basesink, GstPad * pad)
|
||||
{
|
||||
gboolean result = FALSE;
|
||||
GstBaseSinkClass *bclass;
|
||||
|
||||
bclass = GST_BASESINK_GET_CLASS (basesink);
|
||||
|
||||
/* step 1, unblock clock sync (if any) or any other blocking thing */
|
||||
GST_PREROLL_LOCK (pad);
|
||||
GST_LOCK (basesink);
|
||||
if (basesink->clock_id) {
|
||||
gst_clock_id_unschedule (basesink->clock_id);
|
||||
}
|
||||
GST_UNLOCK (basesink);
|
||||
|
||||
/* unlock any subclasses */
|
||||
if (bclass->unlock)
|
||||
bclass->unlock (basesink);
|
||||
|
||||
/* flush out the data thread if it's locked in finish_preroll */
|
||||
gst_basesink_preroll_queue_flush (basesink);
|
||||
basesink->need_preroll = FALSE;
|
||||
GST_PREROLL_SIGNAL (pad);
|
||||
GST_PREROLL_UNLOCK (pad);
|
||||
|
||||
/* step 2, make sure streaming finishes */
|
||||
result = gst_pad_stop_task (pad);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_basesink_activate_push (GstPad * pad, gboolean active)
|
||||
{
|
||||
gboolean result = FALSE;
|
||||
GstBaseSink *basesink;
|
||||
GstBaseSinkClass *bclass;
|
||||
|
||||
basesink = GST_BASESINK (GST_OBJECT_PARENT (pad));
|
||||
bclass = GST_BASESINK_GET_CLASS (basesink);
|
||||
|
||||
switch (mode) {
|
||||
case GST_ACTIVATE_PUSH:
|
||||
g_return_val_if_fail (basesink->has_chain, FALSE);
|
||||
result = TRUE;
|
||||
break;
|
||||
case GST_ACTIVATE_PULL:
|
||||
/* if we have a scheduler we can start the task */
|
||||
g_return_val_if_fail (basesink->has_loop, FALSE);
|
||||
gst_pad_peer_set_active (pad, mode);
|
||||
result =
|
||||
gst_pad_start_task (pad, (GstTaskFunction) gst_basesink_loop, pad);
|
||||
break;
|
||||
case GST_ACTIVATE_NONE:
|
||||
/* step 1, unblock clock sync (if any) or any other blocking thing */
|
||||
GST_PREROLL_LOCK (pad);
|
||||
GST_LOCK (basesink);
|
||||
if (basesink->clock_id) {
|
||||
gst_clock_id_unschedule (basesink->clock_id);
|
||||
}
|
||||
GST_UNLOCK (basesink);
|
||||
|
||||
/* unlock any subclasses */
|
||||
if (bclass->unlock)
|
||||
bclass->unlock (basesink);
|
||||
|
||||
/* flush out the data thread if it's locked in finish_preroll */
|
||||
gst_basesink_preroll_queue_flush (basesink);
|
||||
basesink->need_preroll = FALSE;
|
||||
GST_PREROLL_SIGNAL (pad);
|
||||
GST_PREROLL_UNLOCK (pad);
|
||||
|
||||
/* step 2, make sure streaming finishes */
|
||||
result = gst_pad_stop_task (pad);
|
||||
break;
|
||||
if (active) {
|
||||
g_return_val_if_fail (basesink->has_chain, FALSE);
|
||||
result = TRUE;
|
||||
} else {
|
||||
result = gst_basesink_deactivate (basesink, pad);
|
||||
}
|
||||
basesink->pad_mode = GST_ACTIVATE_PUSH;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* this won't get called until we implement an activate function */
|
||||
static gboolean
|
||||
gst_basesink_activate_pull (GstPad * pad, gboolean active)
|
||||
{
|
||||
gboolean result = FALSE;
|
||||
GstBaseSink *basesink;
|
||||
|
||||
basesink = GST_BASESINK (GST_OBJECT_PARENT (pad));
|
||||
|
||||
if (active) {
|
||||
/* if we have a scheduler we can start the task */
|
||||
g_return_val_if_fail (basesink->has_loop, FALSE);
|
||||
result = gst_pad_start_task (pad, (GstTaskFunction) gst_basesink_loop, pad);
|
||||
} else {
|
||||
result = gst_basesink_deactivate (basesink, pad);
|
||||
}
|
||||
basesink->pad_mode = mode;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -82,7 +82,8 @@ gst_basesrc_get_type (void)
|
|||
return basesrc_type;
|
||||
}
|
||||
|
||||
static gboolean gst_basesrc_activate (GstPad * pad, GstActivateMode mode);
|
||||
static gboolean gst_basesrc_activate_push (GstPad * pad, gboolean active);
|
||||
static gboolean gst_basesrc_activate_pull (GstPad * pad, gboolean active);
|
||||
static void gst_basesrc_set_property (GObject * object, guint prop_id,
|
||||
const GValue * value, GParamSpec * pspec);
|
||||
static void gst_basesrc_get_property (GObject * object, guint prop_id,
|
||||
|
@ -158,7 +159,8 @@ gst_basesrc_init (GstBaseSrc * basesrc, gpointer g_class)
|
|||
|
||||
pad = gst_pad_new_from_template (pad_template, "src");
|
||||
|
||||
gst_pad_set_activate_function (pad, gst_basesrc_activate);
|
||||
gst_pad_set_activatepush_function (pad, gst_basesrc_activate_push);
|
||||
gst_pad_set_activatepull_function (pad, gst_basesrc_activate_pull);
|
||||
gst_pad_set_event_function (pad, gst_basesrc_event_handler);
|
||||
gst_pad_set_query_function (pad, gst_basesrc_query);
|
||||
|
||||
|
@ -729,54 +731,70 @@ gst_basesrc_stop (GstBaseSrc * basesrc)
|
|||
}
|
||||
|
||||
static gboolean
|
||||
gst_basesrc_activate (GstPad * pad, GstActivateMode mode)
|
||||
gst_basesrc_deactivate (GstBaseSrc * basesrc, GstPad * pad)
|
||||
{
|
||||
gboolean result;
|
||||
|
||||
GST_LIVE_LOCK (basesrc);
|
||||
basesrc->live_running = TRUE;
|
||||
GST_LIVE_SIGNAL (basesrc);
|
||||
GST_LIVE_UNLOCK (basesrc);
|
||||
|
||||
/* step 1, unblock clock sync (if any) */
|
||||
gst_basesrc_unlock (basesrc);
|
||||
|
||||
/* step 2, make sure streaming finishes */
|
||||
result = gst_pad_stop_task (pad);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_basesrc_activate_push (GstPad * pad, gboolean active)
|
||||
{
|
||||
GstBaseSrc *basesrc;
|
||||
|
||||
basesrc = GST_BASESRC (GST_OBJECT_PARENT (pad));
|
||||
|
||||
/* prepare subclass first */
|
||||
switch (mode) {
|
||||
case GST_ACTIVATE_PUSH:
|
||||
case GST_ACTIVATE_PULL:
|
||||
result = gst_basesrc_start (basesrc);
|
||||
break;
|
||||
default:
|
||||
result = TRUE;
|
||||
break;
|
||||
if (active) {
|
||||
if (!gst_basesrc_start (basesrc))
|
||||
goto error_start;
|
||||
|
||||
return gst_pad_start_task (pad, (GstTaskFunction) gst_basesrc_loop, pad);
|
||||
} else {
|
||||
return gst_basesrc_deactivate (basesrc, pad);
|
||||
}
|
||||
/* if that failed we can stop here */
|
||||
if (!result)
|
||||
goto error_start;
|
||||
|
||||
result = FALSE;
|
||||
switch (mode) {
|
||||
case GST_ACTIVATE_PUSH:
|
||||
result =
|
||||
gst_pad_start_task (pad, (GstTaskFunction) gst_basesrc_loop, pad);
|
||||
break;
|
||||
case GST_ACTIVATE_PULL:
|
||||
result = basesrc->seekable;
|
||||
if (!result)
|
||||
gst_basesrc_stop (basesrc);
|
||||
break;
|
||||
case GST_ACTIVATE_NONE:
|
||||
GST_LIVE_LOCK (basesrc);
|
||||
basesrc->live_running = TRUE;
|
||||
GST_LIVE_SIGNAL (basesrc);
|
||||
GST_LIVE_UNLOCK (basesrc);
|
||||
|
||||
/* step 1, unblock clock sync (if any) */
|
||||
gst_basesrc_unlock (basesrc);
|
||||
|
||||
/* step 2, make sure streaming finishes */
|
||||
result = gst_pad_stop_task (pad);
|
||||
break;
|
||||
error_start:
|
||||
{
|
||||
GST_DEBUG_OBJECT (basesrc, "failed to start");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_basesrc_activate_pull (GstPad * pad, gboolean active)
|
||||
{
|
||||
GstBaseSrc *basesrc;
|
||||
|
||||
basesrc = GST_BASESRC (GST_OBJECT_PARENT (pad));
|
||||
|
||||
/* prepare subclass first */
|
||||
if (active) {
|
||||
if (!gst_basesrc_start (basesrc))
|
||||
goto error_start;
|
||||
|
||||
if (!basesrc->seekable) {
|
||||
gst_basesrc_stop (basesrc);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
} else {
|
||||
return gst_basesrc_deactivate (basesrc, pad);
|
||||
}
|
||||
return result;
|
||||
|
||||
/* ERROR */
|
||||
error_start:
|
||||
{
|
||||
GST_DEBUG_OBJECT (basesrc, "failed to start");
|
||||
|
|
|
@ -84,10 +84,10 @@ static void gst_base_transform_set_property (GObject * object, guint prop_id,
|
|||
const GValue * value, GParamSpec * pspec);
|
||||
static void gst_base_transform_get_property (GObject * object, guint prop_id,
|
||||
GValue * value, GParamSpec * pspec);
|
||||
static gboolean gst_base_transform_src_activate (GstPad * pad,
|
||||
GstActivateMode mode);
|
||||
static gboolean gst_base_transform_sink_activate (GstPad * pad,
|
||||
GstActivateMode mode);
|
||||
static gboolean gst_base_transform_src_activate_pull (GstPad * pad,
|
||||
gboolean active);
|
||||
static gboolean gst_base_transform_sink_activate_push (GstPad * pad,
|
||||
gboolean active);
|
||||
static GstElementStateReturn gst_base_transform_change_state (GstElement *
|
||||
element);
|
||||
|
||||
|
@ -157,8 +157,8 @@ gst_base_transform_init (GstBaseTransform * trans, gpointer g_class)
|
|||
GST_DEBUG_FUNCPTR (gst_base_transform_event));
|
||||
gst_pad_set_chain_function (trans->sinkpad,
|
||||
GST_DEBUG_FUNCPTR (gst_base_transform_chain));
|
||||
gst_pad_set_activate_function (trans->sinkpad,
|
||||
GST_DEBUG_FUNCPTR (gst_base_transform_sink_activate));
|
||||
gst_pad_set_activatepush_function (trans->sinkpad,
|
||||
GST_DEBUG_FUNCPTR (gst_base_transform_sink_activate_push));
|
||||
gst_element_add_pad (GST_ELEMENT (trans), trans->sinkpad);
|
||||
|
||||
pad_template =
|
||||
|
@ -169,8 +169,8 @@ gst_base_transform_init (GstBaseTransform * trans, gpointer g_class)
|
|||
GST_DEBUG_FUNCPTR (gst_base_transform_proxy_getcaps));
|
||||
gst_pad_set_getrange_function (trans->srcpad,
|
||||
GST_DEBUG_FUNCPTR (gst_base_transform_getrange));
|
||||
gst_pad_set_activate_function (trans->srcpad,
|
||||
GST_DEBUG_FUNCPTR (gst_base_transform_src_activate));
|
||||
gst_pad_set_activatepull_function (trans->srcpad,
|
||||
GST_DEBUG_FUNCPTR (gst_base_transform_src_activate_pull));
|
||||
gst_element_add_pad (GST_ELEMENT (trans), trans->srcpad);
|
||||
}
|
||||
|
||||
|
@ -344,7 +344,7 @@ gst_base_transform_get_property (GObject * object, guint prop_id,
|
|||
}
|
||||
|
||||
static gboolean
|
||||
gst_base_transform_sink_activate (GstPad * pad, GstActivateMode mode)
|
||||
gst_base_transform_sink_activate_push (GstPad * pad, gboolean active)
|
||||
{
|
||||
gboolean result = TRUE;
|
||||
GstBaseTransform *trans;
|
||||
|
@ -353,39 +353,31 @@ gst_base_transform_sink_activate (GstPad * pad, GstActivateMode mode)
|
|||
trans = GST_BASE_TRANSFORM (GST_OBJECT_PARENT (pad));
|
||||
bclass = GST_BASE_TRANSFORM_GET_CLASS (trans);
|
||||
|
||||
switch (mode) {
|
||||
case GST_ACTIVATE_PUSH:
|
||||
case GST_ACTIVATE_PULL:
|
||||
if (bclass->start)
|
||||
result = bclass->start (trans);
|
||||
break;
|
||||
case GST_ACTIVATE_NONE:
|
||||
break;
|
||||
if (active) {
|
||||
if (bclass->start)
|
||||
result = bclass->start (trans);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_base_transform_src_activate (GstPad * pad, GstActivateMode mode)
|
||||
gst_base_transform_src_activate_pull (GstPad * pad, gboolean active)
|
||||
{
|
||||
gboolean result = FALSE;
|
||||
GstBaseTransform *trans;
|
||||
GstBaseTransformClass *bclass;
|
||||
|
||||
trans = GST_BASE_TRANSFORM (GST_OBJECT_PARENT (pad));
|
||||
bclass = GST_BASE_TRANSFORM_GET_CLASS (trans);
|
||||
|
||||
switch (mode) {
|
||||
case GST_ACTIVATE_PUSH:
|
||||
result = TRUE;
|
||||
break;
|
||||
case GST_ACTIVATE_PULL:
|
||||
result = gst_pad_set_active (trans->sinkpad, mode);
|
||||
result = gst_pad_peer_set_active (trans->sinkpad, mode);
|
||||
break;
|
||||
case GST_ACTIVATE_NONE:
|
||||
result = TRUE;
|
||||
break;
|
||||
result = gst_pad_activate_pull (trans->sinkpad, active);
|
||||
|
||||
if (active) {
|
||||
if (result && bclass->start)
|
||||
result &= bclass->start (trans);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -130,5 +130,8 @@ gst_type_find_helper (GstPad * src, guint64 size)
|
|||
if (find.best_probability > 0)
|
||||
result = find.caps;
|
||||
|
||||
if (find.buffer)
|
||||
gst_buffer_unref (find.buffer);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -140,8 +140,8 @@ static GstPadLinkReturn gst_queue_link_sink (GstPad * pad, GstPad * peer);
|
|||
static GstPadLinkReturn gst_queue_link_src (GstPad * pad, GstPad * peer);
|
||||
static void gst_queue_locked_flush (GstQueue * queue);
|
||||
|
||||
static gboolean gst_queue_src_activate (GstPad * pad, GstActivateMode mode);
|
||||
static gboolean gst_queue_sink_activate (GstPad * pad, GstActivateMode mode);
|
||||
static gboolean gst_queue_src_activate_push (GstPad * pad, gboolean active);
|
||||
static gboolean gst_queue_sink_activate_push (GstPad * pad, gboolean active);
|
||||
static GstElementStateReturn gst_queue_change_state (GstElement * element);
|
||||
|
||||
|
||||
|
@ -300,8 +300,8 @@ gst_queue_init (GstQueue * queue)
|
|||
"sink");
|
||||
gst_pad_set_chain_function (queue->sinkpad,
|
||||
GST_DEBUG_FUNCPTR (gst_queue_chain));
|
||||
gst_pad_set_activate_function (queue->sinkpad,
|
||||
GST_DEBUG_FUNCPTR (gst_queue_sink_activate));
|
||||
gst_pad_set_activatepush_function (queue->sinkpad,
|
||||
GST_DEBUG_FUNCPTR (gst_queue_sink_activate_push));
|
||||
gst_pad_set_event_function (queue->sinkpad,
|
||||
GST_DEBUG_FUNCPTR (gst_queue_handle_sink_event));
|
||||
gst_pad_set_link_function (queue->sinkpad,
|
||||
|
@ -316,8 +316,8 @@ gst_queue_init (GstQueue * queue)
|
|||
gst_pad_new_from_template (gst_static_pad_template_get (&srctemplate),
|
||||
"src");
|
||||
gst_pad_set_loop_function (queue->srcpad, GST_DEBUG_FUNCPTR (gst_queue_loop));
|
||||
gst_pad_set_activate_function (queue->srcpad,
|
||||
GST_DEBUG_FUNCPTR (gst_queue_src_activate));
|
||||
gst_pad_set_activatepush_function (queue->srcpad,
|
||||
GST_DEBUG_FUNCPTR (gst_queue_src_activate_push));
|
||||
gst_pad_set_link_function (queue->srcpad,
|
||||
GST_DEBUG_FUNCPTR (gst_queue_link_src));
|
||||
gst_pad_set_getcaps_function (queue->srcpad,
|
||||
|
@ -819,65 +819,55 @@ gst_queue_handle_src_query (GstPad * pad, GstQuery * query)
|
|||
}
|
||||
|
||||
static gboolean
|
||||
gst_queue_sink_activate (GstPad * pad, GstActivateMode mode)
|
||||
gst_queue_sink_activate_push (GstPad * pad, gboolean active)
|
||||
{
|
||||
gboolean result = FALSE;
|
||||
GstQueue *queue;
|
||||
|
||||
queue = GST_QUEUE (GST_OBJECT_PARENT (pad));
|
||||
|
||||
switch (mode) {
|
||||
case GST_ACTIVATE_PUSH:
|
||||
queue->flushing = FALSE;
|
||||
result = TRUE;
|
||||
break;
|
||||
case GST_ACTIVATE_PULL:
|
||||
result = FALSE;
|
||||
break;
|
||||
case GST_ACTIVATE_NONE:
|
||||
/* step 1, unblock chain and loop functions */
|
||||
GST_QUEUE_MUTEX_LOCK;
|
||||
queue->flushing = TRUE;
|
||||
gst_queue_locked_flush (queue);
|
||||
g_cond_signal (queue->item_del);
|
||||
GST_QUEUE_MUTEX_UNLOCK;
|
||||
if (active) {
|
||||
queue->flushing = FALSE;
|
||||
result = TRUE;
|
||||
} else {
|
||||
/* step 1, unblock chain and loop functions */
|
||||
GST_QUEUE_MUTEX_LOCK;
|
||||
queue->flushing = TRUE;
|
||||
gst_queue_locked_flush (queue);
|
||||
g_cond_signal (queue->item_del);
|
||||
GST_QUEUE_MUTEX_UNLOCK;
|
||||
|
||||
/* step 2, make sure streaming finishes */
|
||||
result = gst_pad_stop_task (pad);
|
||||
break;
|
||||
/* step 2, make sure streaming finishes */
|
||||
result = gst_pad_stop_task (pad);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_queue_src_activate (GstPad * pad, GstActivateMode mode)
|
||||
gst_queue_src_activate_push (GstPad * pad, gboolean active)
|
||||
{
|
||||
gboolean result = FALSE;
|
||||
GstQueue *queue;
|
||||
|
||||
queue = GST_QUEUE (GST_OBJECT_PARENT (pad));
|
||||
|
||||
switch (mode) {
|
||||
case GST_ACTIVATE_PUSH:
|
||||
GST_QUEUE_MUTEX_LOCK;
|
||||
queue->flushing = FALSE;
|
||||
result = gst_pad_start_task (pad, (GstTaskFunction) gst_queue_loop, pad);
|
||||
GST_QUEUE_MUTEX_UNLOCK;
|
||||
break;
|
||||
case GST_ACTIVATE_PULL:
|
||||
result = FALSE;
|
||||
break;
|
||||
case GST_ACTIVATE_NONE:
|
||||
/* step 1, unblock chain and loop functions */
|
||||
GST_QUEUE_MUTEX_LOCK;
|
||||
queue->flushing = TRUE;
|
||||
g_cond_signal (queue->item_add);
|
||||
GST_QUEUE_MUTEX_UNLOCK;
|
||||
if (active) {
|
||||
GST_QUEUE_MUTEX_LOCK;
|
||||
queue->flushing = FALSE;
|
||||
result = gst_pad_start_task (pad, (GstTaskFunction) gst_queue_loop, pad);
|
||||
GST_QUEUE_MUTEX_UNLOCK;
|
||||
} else {
|
||||
/* step 1, unblock chain and loop functions */
|
||||
GST_QUEUE_MUTEX_LOCK;
|
||||
queue->flushing = TRUE;
|
||||
g_cond_signal (queue->item_add);
|
||||
GST_QUEUE_MUTEX_UNLOCK;
|
||||
|
||||
/* step 2, make sure streaming finishes */
|
||||
result = gst_pad_stop_task (pad);
|
||||
break;
|
||||
/* step 2, make sure streaming finishes */
|
||||
result = gst_pad_stop_task (pad);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -75,7 +75,8 @@ static void gst_tee_get_property (GObject * object, guint prop_id,
|
|||
|
||||
static GstFlowReturn gst_tee_chain (GstPad * pad, GstBuffer * buffer);
|
||||
static void gst_tee_loop (GstPad * pad);
|
||||
static gboolean gst_tee_sink_activate (GstPad * pad, GstActivateMode mode);
|
||||
static gboolean gst_tee_sink_activate_push (GstPad * pad, gboolean active);
|
||||
static gboolean gst_tee_sink_activate_pull (GstPad * pad, gboolean active);
|
||||
|
||||
|
||||
static void
|
||||
|
@ -153,8 +154,10 @@ gst_tee_init (GstTee * tee)
|
|||
static void
|
||||
gst_tee_update_pad_functions (GstTee * tee)
|
||||
{
|
||||
gst_pad_set_activate_function (tee->sinkpad,
|
||||
GST_DEBUG_FUNCPTR (gst_tee_sink_activate));
|
||||
gst_pad_set_activatepush_function (tee->sinkpad,
|
||||
GST_DEBUG_FUNCPTR (gst_tee_sink_activate_push));
|
||||
gst_pad_set_activatepull_function (tee->sinkpad,
|
||||
GST_DEBUG_FUNCPTR (gst_tee_sink_activate_pull));
|
||||
|
||||
if (tee->has_chain)
|
||||
gst_pad_set_chain_function (tee->sinkpad,
|
||||
|
@ -348,27 +351,35 @@ pause_task:
|
|||
}
|
||||
|
||||
static gboolean
|
||||
gst_tee_sink_activate (GstPad * pad, GstActivateMode mode)
|
||||
gst_tee_sink_activate_push (GstPad * pad, gboolean active)
|
||||
{
|
||||
gboolean result = FALSE;
|
||||
GstTee *tee;
|
||||
|
||||
tee = GST_TEE (GST_OBJECT_PARENT (pad));
|
||||
|
||||
switch (mode) {
|
||||
case GST_ACTIVATE_PUSH:
|
||||
g_return_val_if_fail (tee->has_chain, FALSE);
|
||||
result = TRUE;
|
||||
break;
|
||||
case GST_ACTIVATE_PULL:
|
||||
g_return_val_if_fail (tee->has_sink_loop, FALSE);
|
||||
result = gst_pad_start_task (pad, (GstTaskFunction) gst_tee_loop, pad);
|
||||
break;
|
||||
case GST_ACTIVATE_NONE:
|
||||
result = gst_pad_stop_task (pad);
|
||||
break;
|
||||
}
|
||||
tee->sink_mode = mode;
|
||||
tee->sink_mode = active && GST_ACTIVATE_PUSH;
|
||||
|
||||
return result;
|
||||
if (active) {
|
||||
g_return_val_if_fail (tee->has_chain, FALSE);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* won't be called until we implement an activate function */
|
||||
static gboolean
|
||||
gst_tee_sink_activate_pull (GstPad * pad, gboolean active)
|
||||
{
|
||||
GstTee *tee;
|
||||
|
||||
tee = GST_TEE (GST_OBJECT_PARENT (pad));
|
||||
|
||||
tee->sink_mode = active && GST_ACTIVATE_PULL;
|
||||
|
||||
if (active) {
|
||||
g_return_val_if_fail (tee->has_sink_loop, FALSE);
|
||||
return gst_pad_start_task (pad, (GstTaskFunction) gst_tee_loop, pad);
|
||||
} else {
|
||||
return gst_pad_stop_task (pad);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -133,8 +133,9 @@ static gboolean gst_type_find_element_checkgetrange (GstPad * srcpad);
|
|||
|
||||
static GstElementStateReturn
|
||||
gst_type_find_element_change_state (GstElement * element);
|
||||
static gboolean gst_type_find_element_activate (GstPad * pad);
|
||||
static gboolean
|
||||
gst_type_find_element_activate (GstPad * pad, GstActivateMode mode);
|
||||
gst_type_find_element_activate_src_pull (GstPad * pad, gboolean active);
|
||||
|
||||
static guint gst_type_find_element_signals[LAST_SIGNAL] = { 0 };
|
||||
|
||||
|
@ -215,7 +216,8 @@ gst_type_find_element_init (GstTypeFindElement * typefind)
|
|||
typefind->src =
|
||||
gst_pad_new_from_template (gst_static_pad_template_get
|
||||
(&type_find_element_src_template), "src");
|
||||
gst_pad_set_activate_function (typefind->src, gst_type_find_element_activate);
|
||||
gst_pad_set_activatepull_function (typefind->src,
|
||||
gst_type_find_element_activate_src_pull);
|
||||
gst_pad_set_checkgetrange_function (typefind->src,
|
||||
gst_type_find_element_checkgetrange);
|
||||
gst_pad_set_getrange_function (typefind->src, gst_type_find_element_getrange);
|
||||
|
@ -749,56 +751,80 @@ gst_type_find_element_getrange (GstPad * srcpad,
|
|||
}
|
||||
|
||||
static gboolean
|
||||
do_pull_typefind (GstTypeFindElement * typefind)
|
||||
gst_type_find_element_activate_src_pull (GstPad * pad, gboolean active)
|
||||
{
|
||||
GstCaps *caps;
|
||||
GstPad *peer;
|
||||
gboolean res = FALSE;
|
||||
|
||||
peer = gst_pad_get_peer (typefind->sink);
|
||||
if (peer) {
|
||||
if (gst_pad_peer_set_active (typefind->sink, GST_ACTIVATE_PULL)) {
|
||||
gint64 size;
|
||||
GstFormat format = GST_FORMAT_BYTES;
|
||||
|
||||
gst_pad_query_position (peer, &format, NULL, &size);
|
||||
caps = gst_type_find_helper (peer, (guint64) size);
|
||||
if (caps) {
|
||||
g_signal_emit (typefind, gst_type_find_element_signals[HAVE_TYPE],
|
||||
0, 100, caps);
|
||||
typefind->mode = MODE_NORMAL;
|
||||
res = TRUE;
|
||||
}
|
||||
} else {
|
||||
start_typefinding (typefind);
|
||||
res = TRUE;
|
||||
}
|
||||
|
||||
gst_object_unref (GST_OBJECT (peer));
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_type_find_element_activate (GstPad * pad, GstActivateMode mode)
|
||||
{
|
||||
gboolean result;
|
||||
GstTypeFindElement *typefind;
|
||||
|
||||
typefind = GST_TYPE_FIND_ELEMENT (GST_OBJECT_PARENT (pad));
|
||||
|
||||
switch (mode) {
|
||||
case GST_ACTIVATE_PUSH:
|
||||
case GST_ACTIVATE_PULL:
|
||||
result = TRUE;
|
||||
break;
|
||||
default:
|
||||
result = TRUE;
|
||||
break;
|
||||
return gst_pad_activate_pull (typefind->sink, active);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_type_find_element_activate (GstPad * pad)
|
||||
{
|
||||
GstCaps *found_caps = NULL;
|
||||
GstTypeFindElement *typefind;
|
||||
|
||||
typefind = GST_TYPE_FIND_ELEMENT (GST_OBJECT_PARENT (pad));
|
||||
|
||||
/* 1. try to activate in pull mode. if not, switch to push and succeed.
|
||||
2. try to pull type find.
|
||||
3. deactivate pull mode.
|
||||
4. src pad might have been activated push by the state change. deactivate.
|
||||
5. if we didn't find any caps, fail.
|
||||
6. emit have-type; maybe the app connected the source pad to something.
|
||||
7. if the sink pad is activated, we are in pull mode. succeed.
|
||||
otherwise activate both pads in push mode and succeed.
|
||||
*/
|
||||
|
||||
/* 1 */
|
||||
if (!gst_pad_activate_pull (pad, TRUE)) {
|
||||
start_typefinding (typefind);
|
||||
return gst_pad_activate_push (pad, TRUE);
|
||||
}
|
||||
|
||||
return result;
|
||||
/* 2 */
|
||||
{
|
||||
GstPad *peer;
|
||||
|
||||
peer = gst_pad_get_peer (pad);
|
||||
if (peer) {
|
||||
gint64 size;
|
||||
GstFormat format = GST_FORMAT_BYTES;
|
||||
|
||||
gst_pad_query_position (peer, &format, NULL, &size);
|
||||
found_caps = gst_type_find_helper (peer, (guint64) size);
|
||||
gst_object_unref (GST_OBJECT (peer));
|
||||
}
|
||||
}
|
||||
|
||||
/* 3 */
|
||||
gst_pad_activate_pull (pad, FALSE);
|
||||
|
||||
/* 4 */
|
||||
gst_pad_activate_push (typefind->src, FALSE);
|
||||
|
||||
/* 5 */
|
||||
if (!found_caps)
|
||||
return FALSE;
|
||||
|
||||
/* 6 */
|
||||
g_signal_emit (typefind, gst_type_find_element_signals[HAVE_TYPE],
|
||||
0, 100, found_caps);
|
||||
typefind->mode = MODE_NORMAL;
|
||||
/* FIXME see if I can unref the caps here */
|
||||
|
||||
/* 7 */
|
||||
if (gst_pad_is_active (pad))
|
||||
return TRUE;
|
||||
else {
|
||||
gboolean ret;
|
||||
|
||||
ret = gst_pad_activate_push (typefind->src, TRUE);
|
||||
ret &= gst_pad_activate_push (pad, TRUE);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
static GstElementStateReturn
|
||||
|
@ -811,21 +837,11 @@ gst_type_find_element_change_state (GstElement * element)
|
|||
typefind = GST_TYPE_FIND_ELEMENT (element);
|
||||
|
||||
transition = GST_STATE_TRANSITION (element);
|
||||
switch (transition) {
|
||||
case GST_STATE_READY_TO_PAUSED:
|
||||
if (!do_pull_typefind (typefind))
|
||||
return GST_STATE_FAILURE;
|
||||
//start_typefinding (typefind);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ret = GST_ELEMENT_CLASS (parent_class)->change_state (element);
|
||||
|
||||
switch (transition) {
|
||||
case GST_STATE_PAUSED_TO_READY:
|
||||
//stop_typefinding (typefind);
|
||||
gst_caps_replace (&typefind->caps, NULL);
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -90,6 +90,39 @@ START_TEST (test_ghost_pads)
|
|||
fail_unless (gst_element_set_state (b1, GST_STATE_NULL) == GST_STATE_SUCCESS);
|
||||
|
||||
gst_object_unref (GST_OBJECT (b1));
|
||||
/* unreffing the bin will unref all elements, which will unlink and unparent
|
||||
* all pads */
|
||||
|
||||
/* FIXME: ghost pads need to drop their internal pad in the unlink function,
|
||||
* but can't right now. So internal pads have a ref from their parent, and the
|
||||
* internal pads' targets have refs from the internals. When we do the last
|
||||
* unref on the ghost pads, these refs should go away.
|
||||
*/
|
||||
|
||||
assert_gstrefcount (fsrc, 2); /* gisrc */
|
||||
assert_gstrefcount (gsink, 1);
|
||||
assert_gstrefcount (gsrc, 1);
|
||||
assert_gstrefcount (fsink, 2); /* gisink */
|
||||
|
||||
assert_gstrefcount (gisrc, 2); /* gsink -- fixme drop ref in unlink */
|
||||
assert_gstrefcount (isink, 2); /* gsink */
|
||||
assert_gstrefcount (gisink, 2); /* gsrc -- fixme drop ref in unlink */
|
||||
assert_gstrefcount (isrc, 2); /* gsrc */
|
||||
|
||||
/* while the fixme isn't fixed, check cleanup */
|
||||
gst_object_unref (GST_OBJECT (gsink));
|
||||
assert_gstrefcount (isink, 1);
|
||||
assert_gstrefcount (gisrc, 1);
|
||||
assert_gstrefcount (fsrc, 2); /* gisrc */
|
||||
gst_object_unref (GST_OBJECT (gisrc));
|
||||
assert_gstrefcount (fsrc, 1);
|
||||
|
||||
gst_object_unref (GST_OBJECT (gsrc));
|
||||
assert_gstrefcount (isrc, 1);
|
||||
assert_gstrefcount (gisink, 1);
|
||||
assert_gstrefcount (fsink, 2); /* gisrc */
|
||||
gst_object_unref (GST_OBJECT (gisink));
|
||||
assert_gstrefcount (fsink, 1);
|
||||
}
|
||||
END_TEST Suite * gst_ghost_pad_suite (void)
|
||||
{
|
||||
|
|
|
@ -99,8 +99,68 @@ START_TEST (test_2_elements)
|
|||
ASSERT_CRITICAL (run_pipeline (setup_pipeline (s), s,
|
||||
GST_MESSAGE_STATE_CHANGED, GST_MESSAGE_UNKNOWN)); */
|
||||
}
|
||||
END_TEST Suite *
|
||||
simple_launch_lines_suite (void)
|
||||
END_TEST static void
|
||||
got_handoff (GstElement * sink, GstBuffer * buf, GstPad * pad, gpointer unused)
|
||||
{
|
||||
gst_element_post_message
|
||||
(sink, gst_message_new_application (gst_structure_new ("foo", NULL)));
|
||||
}
|
||||
|
||||
static void
|
||||
assert_live_count (GType type, gint live)
|
||||
{
|
||||
GstAllocTrace *trace;
|
||||
const gchar *name;
|
||||
|
||||
if (gst_alloc_trace_available ()) {
|
||||
name = g_type_name (type);
|
||||
g_assert (name);
|
||||
trace = gst_alloc_trace_get (name);
|
||||
if (trace) {
|
||||
g_return_if_fail (trace->live == live);
|
||||
}
|
||||
} else {
|
||||
g_print ("\nSkipping live count tests; recompile with traces to enable\n");
|
||||
}
|
||||
}
|
||||
|
||||
START_TEST (test_stop_from_app)
|
||||
{
|
||||
GstElement *fakesrc, *fakesink, *pipeline;
|
||||
GstBus *bus;
|
||||
GstMessageType revent;
|
||||
|
||||
assert_live_count (GST_TYPE_BUFFER, 0);
|
||||
|
||||
fakesrc = gst_element_factory_make ("fakesrc", NULL);
|
||||
fakesink = gst_element_factory_make ("fakesink", NULL);
|
||||
pipeline = gst_element_factory_make ("pipeline", NULL);
|
||||
|
||||
g_return_if_fail (fakesrc && fakesink && pipeline);
|
||||
|
||||
gst_element_link (fakesrc, fakesink);
|
||||
gst_bin_add_many (GST_BIN (pipeline), fakesrc, fakesink, NULL);
|
||||
|
||||
g_object_set (fakesink, "signal-handoffs", (gboolean) TRUE, NULL);
|
||||
g_signal_connect (fakesink, "handoff", G_CALLBACK (got_handoff), NULL);
|
||||
|
||||
gst_element_set_state (pipeline, GST_STATE_PLAYING);
|
||||
|
||||
bus = gst_element_get_bus (pipeline);
|
||||
g_assert (bus);
|
||||
|
||||
/* will time out after half a second */
|
||||
revent = gst_bus_poll (bus, GST_MESSAGE_APPLICATION, GST_SECOND / 2);
|
||||
|
||||
g_return_if_fail (revent == GST_MESSAGE_APPLICATION);
|
||||
gst_message_unref (gst_bus_pop (bus));
|
||||
|
||||
gst_element_set_state (pipeline, GST_STATE_NULL);
|
||||
gst_object_unref (GST_OBJECT (pipeline));
|
||||
|
||||
assert_live_count (GST_TYPE_BUFFER, 0);
|
||||
}
|
||||
END_TEST Suite * simple_launch_lines_suite (void)
|
||||
{
|
||||
Suite *s = suite_create ("Pipelines");
|
||||
TCase *tc_chain = tcase_create ("linear");
|
||||
|
@ -110,6 +170,7 @@ simple_launch_lines_suite (void)
|
|||
|
||||
suite_add_tcase (s, tc_chain);
|
||||
tcase_add_test (tc_chain, test_2_elements);
|
||||
tcase_add_test (tc_chain, test_stop_from_app);
|
||||
return s;
|
||||
}
|
||||
|
||||
|
|
|
@ -523,7 +523,7 @@ main (int argc, char *argv[])
|
|||
if (!gst_alloc_trace_available ()) {
|
||||
g_warning ("Trace not available (recompile with trace enabled).");
|
||||
}
|
||||
gst_alloc_trace_print_all ();
|
||||
gst_alloc_trace_print_live ();
|
||||
}
|
||||
|
||||
/* make a null-terminated version of argv */
|
||||
|
@ -643,7 +643,7 @@ end:
|
|||
gst_object_unref (GST_OBJECT (pipeline));
|
||||
|
||||
if (trace)
|
||||
gst_alloc_trace_print_all ();
|
||||
gst_alloc_trace_print_live ();
|
||||
|
||||
return res;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue