diff --git a/ChangeLog b/ChangeLog index 68e2b280c7..f2049f1710 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,28 @@ +2008-04-10 Tim-Philipp Müller + + Based on patch by: José Alburquerque + + * gst/gstutils.c: (gst_pad_add_data_probe), + (gst_pad_add_data_probe_full), (gst_pad_add_event_probe), + (gst_pad_add_event_probe_full), (gst_pad_add_buffer_probe), + (gst_pad_add_buffer_probe_full): + * gst/gstutils.h: + * docs/gst/gstreamer-sections.txt: + * win32/common/libgstreamer.def: + Add gst_pad_add_*_probe_full() functions with a notify callback that + lets the caller free the data it passes to the probe functions. This + is useful for bindings such as gst-python or gstreamermm (#526814). + API: gst_pad_add_data_probe_full + API: gst_pad_add_buffer_probe_full + API: gst_pad_add_event_probe_full + + * tests/check/gst/gstutils.c: + Add minimal unit test to make sure freeing the data actually works + as expected. + + * tests/benchmarks/.cvsignore: + Random cvsignore addendum. + 2008-04-10 Tim-Philipp Müller * gst/gstdebugutils.h: (GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS), diff --git a/docs/gst/gstreamer-sections.txt b/docs/gst/gstreamer-sections.txt index e29d214de5..3998f80b2f 100644 --- a/docs/gst/gstreamer-sections.txt +++ b/docs/gst/gstreamer-sections.txt @@ -1236,8 +1236,11 @@ gst_pad_is_blocked gst_pad_is_blocking gst_pad_add_data_probe +gst_pad_add_data_probe_full gst_pad_add_buffer_probe +gst_pad_add_buffer_probe_full gst_pad_add_event_probe +gst_pad_add_event_probe_full gst_pad_remove_data_probe gst_pad_remove_buffer_probe gst_pad_remove_event_probe diff --git a/gst/gstutils.c b/gst/gstutils.c index dd2a407d7c..7998c213c6 100644 --- a/gst/gstutils.c +++ b/gst/gstutils.c @@ -2871,6 +2871,49 @@ gst_atomic_int_set (gint * atomic_int, gint value) */ gulong gst_pad_add_data_probe (GstPad * pad, GCallback handler, gpointer data) +{ + return gst_pad_add_data_probe_full (pad, handler, data, NULL); +} + +/** + * gst_pad_add_data_probe_full: + * @pad: pad to add the data probe handler to + * @handler: function to call when data is passed over pad + * @data: data to pass along with the handler + * @notify: function to call when the probe is disconnected, or NULL + * + * Adds a "data probe" to a pad. This function will be called whenever data + * passes through a pad. In this case data means both events and buffers. The + * probe will be called with the data as an argument, meaning @handler should + * have the same callback signature as the #GstPad::have-data signal. + * Note that the data will have a reference count greater than 1, so it will + * be immutable -- you must not change it. + * + * For source pads, the probe will be called after the blocking function, if any + * (see gst_pad_set_blocked_async()), but before looking up the peer to chain + * to. For sink pads, the probe function will be called before configuring the + * sink with new caps, if any, and before calling the pad's chain function. + * + * Your data probe should return TRUE to let the data continue to flow, or FALSE + * to drop it. Dropping data is rarely useful, but occasionally comes in handy + * with events. + * + * Although probes are implemented internally by connecting @handler to the + * have-data signal on the pad, if you want to remove a probe it is insufficient + * to only call g_signal_handler_disconnect on the returned handler id. To + * remove a probe, use the appropriate function, such as + * gst_pad_remove_data_probe(). + * + * The @notify function is called when the probe is disconnected and usually + * used to free @data. + * + * Returns: The handler id. + * + * Since: 0.10.20 + */ +gulong +gst_pad_add_data_probe_full (GstPad * pad, GCallback handler, + gpointer data, GDestroyNotify notify) { gulong sigid; @@ -2878,7 +2921,11 @@ gst_pad_add_data_probe (GstPad * pad, GCallback handler, gpointer data) g_return_val_if_fail (handler != NULL, 0); GST_OBJECT_LOCK (pad); - sigid = g_signal_connect (pad, "have-data", handler, data); + + /* we only expose a GDestroyNotify in our API because that's less confusing */ + sigid = g_signal_connect_data (pad, "have-data", handler, data, + (GClosureNotify) notify, 0); + GST_PAD_DO_EVENT_SIGNALS (pad)++; GST_PAD_DO_BUFFER_SIGNALS (pad)++; GST_DEBUG ("adding data probe to pad %s:%s, now %d data, %d event probes", @@ -2902,6 +2949,30 @@ gst_pad_add_data_probe (GstPad * pad, GCallback handler, gpointer data) */ gulong gst_pad_add_event_probe (GstPad * pad, GCallback handler, gpointer data) +{ + return gst_pad_add_event_probe_full (pad, handler, data, NULL); +} + +/** + * gst_pad_add_event_probe_full: + * @pad: pad to add the event probe handler to + * @handler: function to call when events are passed over pad + * @data: data to pass along with the handler, or NULL + * @notify: function to call when probe is disconnected, or NULL + * + * Adds a probe that will be called for all events passing through a pad. See + * gst_pad_add_data_probe() for more information. + * + * The @notify function is called when the probe is disconnected and usually + * used to free @data. + * + * Returns: The handler id + * + * Since: 0.10.20 + */ +gulong +gst_pad_add_event_probe_full (GstPad * pad, GCallback handler, + gpointer data, GDestroyNotify notify) { gulong sigid; @@ -2909,7 +2980,11 @@ gst_pad_add_event_probe (GstPad * pad, GCallback handler, gpointer data) g_return_val_if_fail (handler != NULL, 0); GST_OBJECT_LOCK (pad); - sigid = g_signal_connect (pad, "have-data::event", handler, data); + + /* we only expose a GDestroyNotify in our API because that's less confusing */ + sigid = g_signal_connect_data (pad, "have-data::event", handler, data, + (GClosureNotify) notify, 0); + GST_PAD_DO_EVENT_SIGNALS (pad)++; GST_DEBUG ("adding event probe to pad %s:%s, now %d probes", GST_DEBUG_PAD_NAME (pad), GST_PAD_DO_EVENT_SIGNALS (pad)); @@ -2931,6 +3006,30 @@ gst_pad_add_event_probe (GstPad * pad, GCallback handler, gpointer data) */ gulong gst_pad_add_buffer_probe (GstPad * pad, GCallback handler, gpointer data) +{ + return gst_pad_add_buffer_probe_full (pad, handler, data, NULL); +} + +/** + * gst_pad_add_buffer_probe_full: + * @pad: pad to add the buffer probe handler to + * @handler: function to call when buffer are passed over pad + * @data: data to pass along with the handler + * @notify: function to call when the probe is disconnected, or NULL + * + * Adds a probe that will be called for all buffers passing through a pad. See + * gst_pad_add_data_probe() for more information. + * + * The @notify function is called when the probe is disconnected and usually + * used to free @data. + * + * Returns: The handler id + * + * Since: 0.10.20 + */ +gulong +gst_pad_add_buffer_probe_full (GstPad * pad, GCallback handler, + gpointer data, GDestroyNotify notify) { gulong sigid; @@ -2938,7 +3037,11 @@ gst_pad_add_buffer_probe (GstPad * pad, GCallback handler, gpointer data) g_return_val_if_fail (handler != NULL, 0); GST_OBJECT_LOCK (pad); - sigid = g_signal_connect (pad, "have-data::buffer", handler, data); + + /* we only expose a GDestroyNotify in our API because that's less confusing */ + sigid = g_signal_connect_data (pad, "have-data::buffer", handler, data, + (GClosureNotify) notify, 0); + GST_PAD_DO_BUFFER_SIGNALS (pad)++; GST_DEBUG ("adding buffer probe to pad %s:%s, now %d probes", GST_DEBUG_PAD_NAME (pad), GST_PAD_DO_BUFFER_SIGNALS (pad)); diff --git a/gst/gstutils.h b/gst/gstutils.h index cf1aded022..368570936f 100644 --- a/gst/gstutils.h +++ b/gst/gstutils.h @@ -664,17 +664,37 @@ void gst_buffer_stamp (GstBuffer * dest, const GstBuffer * src); void gst_atomic_int_set (gint * atomic_int, gint value); /* probes */ -gulong gst_pad_add_data_probe (GstPad * pad, - GCallback handler, - gpointer data); +gulong gst_pad_add_data_probe (GstPad * pad, + GCallback handler, + gpointer data); + +gulong gst_pad_add_data_probe_full (GstPad * pad, + GCallback handler, + gpointer data, + GDestroyNotify notify); + void gst_pad_remove_data_probe (GstPad * pad, guint handler_id); -gulong gst_pad_add_event_probe (GstPad * pad, - GCallback handler, - gpointer data); + +gulong gst_pad_add_event_probe (GstPad * pad, + GCallback handler, + gpointer data); + +gulong gst_pad_add_event_probe_full (GstPad * pad, + GCallback handler, + gpointer data, + GDestroyNotify notify); + void gst_pad_remove_event_probe (GstPad * pad, guint handler_id); -gulong gst_pad_add_buffer_probe (GstPad * pad, - GCallback handler, - gpointer data); + +gulong gst_pad_add_buffer_probe (GstPad * pad, + GCallback handler, + gpointer data); + +gulong gst_pad_add_buffer_probe_full (GstPad * pad, + GCallback handler, + gpointer data, + GDestroyNotify notify); + void gst_pad_remove_buffer_probe (GstPad * pad, guint handler_id); /* tag emission utility functions */ diff --git a/tests/benchmarks/.gitignore b/tests/benchmarks/.gitignore index 8e9eceddac..710923c678 100644 --- a/tests/benchmarks/.gitignore +++ b/tests/benchmarks/.gitignore @@ -2,5 +2,6 @@ Makefile Makefile.in caps complexity +gstpollstress mass-elements *.gcno diff --git a/tests/check/gst/gstutils.c b/tests/check/gst/gstutils.c index 933a5674bc..e1aebb2b0e 100644 --- a/tests/check/gst/gstutils.c +++ b/tests/check/gst/gstutils.c @@ -28,6 +28,12 @@ static int n_data_probes = 0; static int n_buffer_probes = 0; static int n_event_probes = 0; +static gboolean +probe_do_nothing (GstPad * pad, GstMiniObject * obj, gpointer data) +{ + return TRUE; +} + static gboolean data_probe (GstPad * pad, GstMiniObject * obj, gpointer data) { @@ -75,10 +81,22 @@ GST_START_TEST (test_buffer_probe_n_times) gst_element_link (fakesrc, fakesink); pad = gst_element_get_pad (fakesink, "sink"); + + /* add the probes we need for the test */ gst_pad_add_data_probe (pad, G_CALLBACK (data_probe), SPECIAL_POINTER (0)); gst_pad_add_buffer_probe (pad, G_CALLBACK (buffer_probe), SPECIAL_POINTER (1)); gst_pad_add_event_probe (pad, G_CALLBACK (event_probe), SPECIAL_POINTER (2)); + + /* add some probes just to test that _full works and the data is free'd + * properly as it should be */ + gst_pad_add_data_probe_full (pad, G_CALLBACK (probe_do_nothing), + g_strdup ("data probe string"), (GDestroyNotify) g_free); + gst_pad_add_buffer_probe_full (pad, G_CALLBACK (probe_do_nothing), + g_strdup ("buffer probe string"), (GDestroyNotify) g_free); + gst_pad_add_event_probe_full (pad, G_CALLBACK (probe_do_nothing), + g_strdup ("event probe string"), (GDestroyNotify) g_free); + gst_object_unref (pad); gst_element_set_state (pipeline, GST_STATE_PLAYING); diff --git a/win32/common/libgstreamer.def b/win32/common/libgstreamer.def index b3bc93f054..0121c32043 100644 --- a/win32/common/libgstreamer.def +++ b/win32/common/libgstreamer.def @@ -509,8 +509,11 @@ EXPORTS gst_pad_activate_pull gst_pad_activate_push gst_pad_add_buffer_probe + gst_pad_add_buffer_probe_full gst_pad_add_data_probe + gst_pad_add_data_probe_full gst_pad_add_event_probe + gst_pad_add_event_probe_full gst_pad_alloc_buffer gst_pad_alloc_buffer_and_set_caps gst_pad_can_link