]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - glsdk/gstreamer0-10.git/commitdiff
gst/base/gsttypefindhelper.c (gst_type_find_helper): Unref any remaining buffer.
authorAndy Wingo <wingo@pobox.com>
Mon, 27 Jun 2005 18:35:05 +0000 (18:35 +0000)
committerAndy Wingo <wingo@pobox.com>
Mon, 27 Jun 2005 18:35:05 +0000 (18:35 +0000)
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.

36 files changed:
ChangeLog
check/gst/gstghostpad.c
check/pipelines/simple_launch_lines.c
docs/gst/tmpl/gstfakesrc.sgml
docs/gst/tmpl/gstpad.sgml
gst/base/gstbasesink.c
gst/base/gstbasesrc.c
gst/base/gstbasetransform.c
gst/base/gsttypefindhelper.c
gst/elements/gsttee.c
gst/elements/gsttypefindelement.c
gst/gstbuffer.c
gst/gstbus.c
gst/gstelement.c
gst/gstelement.h
gst/gstevent.c
gst/gstghostpad.c
gst/gstmessage.c
gst/gstminiobject.c
gst/gstminiobject.h
gst/gstpad.c
gst/gstpad.h
gst/gstpipeline.c
gst/gstqueue.c
gst/gsttrace.c
gst/gsttrace.h
libs/gst/base/gstbasesink.c
libs/gst/base/gstbasesrc.c
libs/gst/base/gstbasetransform.c
libs/gst/base/gsttypefindhelper.c
plugins/elements/gstqueue.c
plugins/elements/gsttee.c
plugins/elements/gsttypefindelement.c
tests/check/gst/gstghostpad.c
tests/check/pipelines/simple-launch-lines.c
tools/gst-launch.c

index 891346a42d32fd700d19975b2a4d05dd21f7508c..868d6dbfab0b17705bbf7f55dedde428d4d4dcff 100644 (file)
--- a/ChangeLog
+++ b/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),
index 44f910f96276636ef56522416149ddb3d0ed3364..5ebcdd37a3af51cf4d7106dcc189400787b21a12 100644 (file)
@@ -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)
 {
index 3e3db26b7bb6b0bcbbe2e104ccbc500ce3f3c95c..6ebf387e17c82c3d6b2469a802bca03bb196635e 100644 (file)
@@ -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;
 }
 
index c6dc59bb51e2292b170bb002fde5bfbc505468d4..d67c38132be37f0d2e106101d3fbce638c1288cc 100644 (file)
@@ -63,6 +63,11 @@ GstFakeSrc
 
 </para>
 
+<!-- ##### ARG GstFakeSrc:is-live ##### -->
+<para>
+
+</para>
+
 <!-- ##### ARG GstFakeSrc:last-message ##### -->
 <para>
 
index 6509714450267496bcd2bb8421fdff253bbdafaa..199d841f0e094b27c251588de0c8e8d089eac198 100644 (file)
@@ -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 ##### -->
index 4921178d55e3a6d08ac3bb1af7427fac380b7ff3..081ca45e3241923edff7106782ccef0a1d491dd2 100644 (file)
@@ -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;
-  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);
+  /* 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);
+  /* 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);
+  /* 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;
+  /* 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;
+
+  basesink = GST_BASESINK (GST_OBJECT_PARENT (pad));
+
+  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;
 }
index 6600ade12ae55ff71a262eeef883c013bc3ee2fa..4c3cb8dc18d8fb5ccc2a53aeb4ff0a19475adeb3 100644 (file)
@@ -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);
+error_start:
+  {
+    GST_DEBUG_OBJECT (basesrc, "failed to start");
+    return FALSE;
+  }
+}
 
-      /* step 1, unblock clock sync (if any) */
-      gst_basesrc_unlock (basesrc);
+static gboolean
+gst_basesrc_activate_pull (GstPad * pad, gboolean active)
+{
+  GstBaseSrc *basesrc;
 
-      /* step 2, make sure streaming finishes */
-      result = gst_pad_stop_task (pad);
-      break;
+  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");
index 9bc705a7a29e839d1061f77112aa411a9e5b7ac8..0a29b363329d14bd7ed4eb4653a11cf0c2698f9a 100644 (file)
@@ -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;
 }
 
index d0edfba8c2ac1c1cd3bb759e698b3878978a24f3..884d7f9949b440477c31d6f3b9dcd6ab97c1a6ad 100644 (file)
@@ -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;
 }
index 2b70a77032e693a89d8ca6d2715afeb9056dd3c1..9b0bd657b719451de2df42176707b3686b998e50 100644 (file)
@@ -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 = active && GST_ACTIVATE_PUSH;
+
+  if (active) {
+    g_return_val_if_fail (tee->has_chain, FALSE);
   }
-  tee->sink_mode = mode;
 
-  return result;
+  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);
+  }
 }
index 1eb71956fda6d4b26598f1b9c1ee02ca60aafc16..4fa1f3456d35bff940c936bbf6b4146582a6dc2d 100644 (file)
@@ -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;
-    }
+  GstTypeFindElement *typefind;
 
-    gst_object_unref (GST_OBJECT (peer));
-  }
+  typefind = GST_TYPE_FIND_ELEMENT (GST_OBJECT_PARENT (pad));
 
-  return res;
+  return gst_pad_activate_pull (typefind->sink, active);
 }
 
 static gboolean
-gst_type_find_element_activate (GstPad * pad, GstActivateMode mode)
+gst_type_find_element_activate (GstPad * pad)
 {
-  gboolean result;
+  GstCaps *found_caps = NULL;
   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;
+  /* 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:
index 56532e4eff81a109267433650ce0ac9a94d2f09d..322bd21b7486152bbca177c599e9f6080e70b698 100644 (file)
 #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
index f08e5cc4353e061a87fa9c026033a184d767ec37..e53ff6ad98edec56577b68d636fad0789be399fb 100644 (file)
@@ -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 = {
index 77ef5f263e032fa5c4a71d48a433511ecee7872b..25c27f3c4e3a71af28d9d2e15ba7a396eb9cf11c 100644 (file)
@@ -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:
   }
 }
 
-/* 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?
- */
+/* gst_iterator_fold functions for pads_activate */
+
 static gboolean
-gst_element_pads_activate (GstElement * element, gboolean active)
+activate_pads (GstPad * pad, GValue * ret, gboolean * active)
 {
-  GList *pads;
-  gboolean result;
-  guint32 cookie;
+  if (!gst_pad_set_active (pad, *active))
+    g_value_set_boolean (ret, FALSE);
 
-  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;
-
-    pad = GST_PAD (pads->data);
-    gst_object_ref (GST_OBJECT (pad));
-    GST_UNLOCK (element);
-
-    if (active) {
-      pad_get = GST_PAD_IS_SINK (pad) && gst_pad_check_pull_range (pad);
-
-      /* 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_object_unref (GST_OBJECT (pad));
+  return TRUE;
+}
 
-      GST_DEBUG ("pad %s:%s: get: %d, loop: %d",
-          GST_DEBUG_PAD_NAME (pad), pad_get, pad_loop);
+/* 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;
 
-      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));
-      }
+  while (1) {
+    ires = gst_iterator_fold (iter, func, ret, user_data);
 
-      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));
+    switch (ires) {
+      case GST_ITERATOR_RESYNC:
+        break;
+      case GST_ITERATOR_DONE:
+        res = TRUE;
+        goto done;
+      default:
+        res = FALSE;
+        goto done;
+    }
+  }
 
-        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));
+done:
+  return res;
+}
 
-      result &= gst_pad_set_active (pad, GST_ACTIVATE_NONE);
-    }
+/* is called with STATE_LOCK
+ */
+static gboolean
+gst_element_pads_activate (GstElement * element, gboolean active)
+{
+  GValue ret = { 0, };
+  GstIterator *iter;
+  gboolean fold_ok;
+
+  /* no need to unset this later, it's just a boolean */
+  g_value_init (&ret, G_TYPE_BOOLEAN);
+  g_value_set_boolean (&ret, TRUE);
+
+  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;
 
-    gst_object_unref (GST_OBJECT_CAST (pad));
-    GST_LOCK (element);
-    if (cookie != element->pads_cookie)
-      goto restart;
-  }
-  GST_UNLOCK (element);
+  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;
 
-  return result;
+  return TRUE;
 }
 
 /* is called with STATE_LOCK */
index 11c6f70c60502451785c9bc5823fbbdaab821220..0feea438e100480cff8e3babc9e80c18f5d1b09e 100644 (file)
@@ -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);
index 78433a25d7c6e28a08dcafc98f69bac98fb6b4a3..31dcc74ea069d6188e78fbb1b9e194a8db3f89c2 100644 (file)
 #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
index cdad75145851ff54cf42ecd37270d01674bd38b9..9746fd2c975490d5bcded30acd173b3221a461a4 100644 (file)
@@ -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 */
       }
index 95cf52a502cdda4271aa782ba74a674a63259fbf..fd43540344fc12dc90f3c9a4c4312e37dfdb77e7 100644 (file)
 #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
index cdb9e75dbc2571cf560eaee9d0039cf28eda1656..e3c7fcf9618d44df474a6474646f84f1c4c69a73 100644 (file)
 #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
index 7e38a0f7c6e7898e07ac9577492c1753e4321d6f..45cea98114e848afefa5e72b48d0364684858e27 100644 (file)
@@ -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);
index eb934185966768ed492840da30bbd99538608fdf..83137614aaa32b239e894bfaa8cdffd4cdb75714 100644 (file)
@@ -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.
+ * MT safe. Must be called with STATE_LOCK.
  */
 gboolean
-gst_pad_set_active (GstPad * pad, GstActivateMode mode)
+gst_pad_set_active (GstPad * pad, gboolean active)
 {
   GstActivateMode old;
-  GstPadActivateFunction activatefunc;
-  gboolean active, oldactive;
+  gboolean ret;
 
   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))
-    goto was_ok;
+  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;
+    }
+  }
 
-  /* FIXME, no mode switching yet, need more design docs first */
-#if 0
-  if (G_UNLIKELY (old == mode))
+  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_activate_pull (GstPad * pad, gboolean active)
+{
+  GstActivateMode old;
+
+  g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
+
+  GST_LOCK (pad);
+  old = GST_PAD_ACTIVATE_MODE (pad);
+  GST_UNLOCK (pad);
+
+  if ((active && old == GST_ACTIVATE_PULL)
+      || (!active && old == GST_ACTIVATE_NONE))
     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) {
+    g_return_val_if_fail (old == GST_ACTIVATE_NONE, FALSE);
+  } else {
+    g_return_val_if_fail (old == GST_ACTIVATE_PULL, FALSE);
   }
 
-  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;
+  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;
-
-    GST_CAT_DEBUG (GST_CAT_PADS,
-        "calling activate function on pad %s:%s with mode %d",
-        GST_DEBUG_PAD_NAME (pad), mode);
+  pre_activate_switch (pad, active);
 
-    /* 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 pad in push mode via dispatching to the
+ * pad's activatepushfunc. For use from within pad activation functions only.
  *
- * 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.
+ * 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.
index c77910bee0cb73331250cbb0bb10ac809b56fa03..908adc12a4b24ef443d68b499ab3d7e792c4ec46 100644 (file)
@@ -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);
index 30c9600d20a28080aa02de043d85f2254e87ae36..89d39045c60d4f2004ef55ae11c3c1027f927827 100644 (file)
@@ -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);
index 43645c550b06b424e883ab9369e33668a6c906cb..dd17a3d686f4f357c3e8699feafa00538f847180 100644 (file)
@@ -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;
 }
 
index 15e64efc5394ee2ec555ba63c97c9e3ccb751175..794e4bba698d45d0ce55379504d30309381a694d 100644 (file)
@@ -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");
 }
 
 /**
index 5a0cde31d779628765d711fca0df7a686771e42e..c32dbbcc960700b98265dbf016ec1c9c9a80fefe 100644 (file)
@@ -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);
index 4921178d55e3a6d08ac3bb1af7427fac380b7ff3..081ca45e3241923edff7106782ccef0a1d491dd2 100644 (file)
@@ -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;
-  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);
+  /* 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);
+  /* 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);
+  /* 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;
+  /* 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;
+
+  basesink = GST_BASESINK (GST_OBJECT_PARENT (pad));
+
+  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;
 }
index 6600ade12ae55ff71a262eeef883c013bc3ee2fa..4c3cb8dc18d8fb5ccc2a53aeb4ff0a19475adeb3 100644 (file)
@@ -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);
+error_start:
+  {
+    GST_DEBUG_OBJECT (basesrc, "failed to start");
+    return FALSE;
+  }
+}
 
-      /* step 1, unblock clock sync (if any) */
-      gst_basesrc_unlock (basesrc);
+static gboolean
+gst_basesrc_activate_pull (GstPad * pad, gboolean active)
+{
+  GstBaseSrc *basesrc;
 
-      /* step 2, make sure streaming finishes */
-      result = gst_pad_stop_task (pad);
-      break;
+  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");
index 9bc705a7a29e839d1061f77112aa411a9e5b7ac8..0a29b363329d14bd7ed4eb4653a11cf0c2698f9a 100644 (file)
@@ -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;
 }
 
index d0edfba8c2ac1c1cd3bb759e698b3878978a24f3..884d7f9949b440477c31d6f3b9dcd6ab97c1a6ad 100644 (file)
@@ -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;
 }
index 43645c550b06b424e883ab9369e33668a6c906cb..dd17a3d686f4f357c3e8699feafa00538f847180 100644 (file)
@@ -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;
 }
 
index 2b70a77032e693a89d8ca6d2715afeb9056dd3c1..9b0bd657b719451de2df42176707b3686b998e50 100644 (file)
@@ -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 = active && GST_ACTIVATE_PUSH;
+
+  if (active) {
+    g_return_val_if_fail (tee->has_chain, FALSE);
   }
-  tee->sink_mode = mode;
 
-  return result;
+  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);
+  }
 }
index 1eb71956fda6d4b26598f1b9c1ee02ca60aafc16..4fa1f3456d35bff940c936bbf6b4146582a6dc2d 100644 (file)
@@ -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;
-    }
+  GstTypeFindElement *typefind;
 
-    gst_object_unref (GST_OBJECT (peer));
-  }
+  typefind = GST_TYPE_FIND_ELEMENT (GST_OBJECT_PARENT (pad));
 
-  return res;
+  return gst_pad_activate_pull (typefind->sink, active);
 }
 
 static gboolean
-gst_type_find_element_activate (GstPad * pad, GstActivateMode mode)
+gst_type_find_element_activate (GstPad * pad)
 {
-  gboolean result;
+  GstCaps *found_caps = NULL;
   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;
+  /* 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:
index 44f910f96276636ef56522416149ddb3d0ed3364..5ebcdd37a3af51cf4d7106dcc189400787b21a12 100644 (file)
@@ -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)
 {
index 3e3db26b7bb6b0bcbbe2e104ccbc500ce3f3c95c..6ebf387e17c82c3d6b2469a802bca03bb196635e 100644 (file)
@@ -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;
 }
 
index b2199f39ba3261e48cf59166c3c6c538aef99475..7206de8da2ae5deb2ec44294eae490f29f00bcf1 100644 (file)
@@ -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;
 }