+2005-06-29 Ronald S. Bultje <rbultje@ronald.bitfreak.net>
+
+ * docs/gst/gstreamer-sections.txt:
+ * docs/gst/tmpl/gstpad.sgml:
+ * docs/gst/tmpl/gstprobe.sgml:
+ * gst/Makefile.am:
+ * gst/gstpad.c: (_gst_do_pass_data_accumulator),
+ (gst_pad_class_init), (gst_pad_init), (gst_pad_chain),
+ (gst_pad_push), (gst_pad_get_range), (gst_pad_pull_range),
+ (gst_pad_push_event), (gst_pad_send_event):
+ * gst/gstpad.h:
+ * gst/gstutils.c: (gst_pad_add_data_probe),
+ (gst_pad_add_event_probe), (gst_pad_add_buffer_probe),
+ (gst_pad_remove_data_probe), (gst_pad_remove_event_probe),
+ (gst_pad_remove_buffer_probe):
+ * gst/gstutils.h:
+ Remove old probes, add new g-signal-based probes and some utility
+ functions.
+
2005-06-29 Edward Hervey <edward@fluendo.com>
* gst/gstelementfactory.c:
gst_pad_get_internal_links
gst_pad_get_internal_links_default
gst_pad_dispatcher
-gst_pad_add_probe
-gst_pad_remove_probe
gst_pad_load_and_link
+gst_pad_add_data_probe
+gst_pad_add_buffer_probe
+gst_pad_add_event_probe
+gst_pad_remove_data_probe
+gst_pad_remove_buffer_probe
+gst_pad_remove_event_probe
<SUBSECTION Standard>
GstPadClass
GST_PAD
</SECTION>
<SECTION>
-<FILE>gstprobe</FILE>
-<TITLE>GstProbe</TITLE>
-GstProbe
-GstProbeCallback
-gst_probe_new
-gst_probe_destroy
-gst_probe_perform
-GstProbeDispatcher
-gst_probe_dispatcher_new
-gst_probe_dispatcher_destroy
-gst_probe_dispatcher_init
-gst_probe_dispatcher_set_active
-gst_probe_dispatcher_add_probe
-gst_probe_dispatcher_remove_probe
-gst_probe_dispatcher_dispatch
-<SUBSECTION Standard>
-GST_PROBE
-GST_TYPE_PROBE
-<SUBSECTION Private>
-gst_probe_get_type
-</SECTION>
-
-<SECTION>
<FILE>gstquery</FILE>
<TITLE>GstQuery</TITLE>
GstQueryType
@queryfunc:
@intlinkfunc:
@bufferallocfunc:
-@probedisp:
+@emit_buffer_signals:
+@emit_event_signals:
+
+<!-- ##### SIGNAL GstPad::have-data ##### -->
+<para>
+
+</para>
+
+@gstpad: the object which received the signal.
+@arg1:
+@Returns:
<!-- ##### SIGNAL GstPad::linked ##### -->
<para>
@Returns:
-<!-- ##### MACRO gst_pad_add_probe ##### -->
+<!-- ##### FUNCTION gst_pad_load_and_link ##### -->
+<para>
+
+</para>
+
+@self:
+@parent:
+
+
+<!-- ##### FUNCTION gst_pad_add_data_probe ##### -->
<para>
-Adds the probe to the given pad
+
</para>
-@pad: The pad to add the probe to
-@probe: The probe to add to the pad
+@pad:
+@handler:
+@data:
-<!-- ##### MACRO gst_pad_remove_probe ##### -->
+<!-- ##### FUNCTION gst_pad_add_buffer_probe ##### -->
<para>
-Remove the probe from the pad
+
</para>
-@pad: The pad to remove the probe of
-@probe: The probe to remove
+@pad:
+@handler:
+@data:
-<!-- ##### FUNCTION gst_pad_load_and_link ##### -->
+<!-- ##### FUNCTION gst_pad_add_event_probe ##### -->
<para>
</para>
-@self:
-@parent:
+@pad:
+@handler:
+@data:
+
+
+<!-- ##### FUNCTION gst_pad_remove_data_probe ##### -->
+<para>
+
+</para>
+
+@pad:
+@handler:
+@data:
+
+
+<!-- ##### FUNCTION gst_pad_remove_buffer_probe ##### -->
+<para>
+
+</para>
+
+@pad:
+@handler:
+@data:
+
+
+<!-- ##### FUNCTION gst_pad_remove_event_probe ##### -->
+<para>
+
+</para>
+
+@pad:
+@handler:
+@data:
+++ /dev/null
-<!-- ##### SECTION Title ##### -->
-GstProbe
-
-<!-- ##### SECTION Short_Description ##### -->
-Receive callbacks of data passing
-
-<!-- ##### SECTION Long_Description ##### -->
-<para>
-PadProbes are used to be signalled with a callback when certain GstData
-passes through pads.
-</para>
-<para>
-Probes are usually used in combination with a probe dispatcher that will
-enumerate all registered probes to signal them.
-</para>
-
-<!-- ##### SECTION See_Also ##### -->
-<para>
-
-</para>
-
-<!-- ##### STRUCT GstProbe ##### -->
-<para>
-The probe structure
-</para>
-
-@single_shot:
-@callback:
-@user_data:
-
-<!-- ##### USER_FUNCTION GstProbeCallback ##### -->
-<para>
-The function that will be called when a probe is activated.
-</para>
-
-@probe: The probe that signalled the callback
-@data: The GstData that triggered the probe
-@user_data: user data
-@Returns: FALSE if the GstData should be removed from the stream.
-
-
-<!-- ##### FUNCTION gst_probe_new ##### -->
-<para>
-
-</para>
-
-@single_shot:
-@callback:
-@user_data:
-@Returns:
-
-
-<!-- ##### FUNCTION gst_probe_destroy ##### -->
-<para>
-
-</para>
-
-@probe:
-
-
-<!-- ##### FUNCTION gst_probe_perform ##### -->
-<para>
-
-</para>
-
-@probe:
-@data:
-@Returns:
-
-
-<!-- ##### STRUCT GstProbeDispatcher ##### -->
-<para>
-The structure of the probe dispatcher
-</para>
-
-@active:
-@probes:
-
-<!-- ##### FUNCTION gst_probe_dispatcher_new ##### -->
-<para>
-
-</para>
-
-@Returns:
-
-
-<!-- ##### FUNCTION gst_probe_dispatcher_destroy ##### -->
-<para>
-
-</para>
-
-@disp:
-
-
-<!-- ##### FUNCTION gst_probe_dispatcher_init ##### -->
-<para>
-
-</para>
-
-@disp:
-
-
-<!-- ##### FUNCTION gst_probe_dispatcher_set_active ##### -->
-<para>
-
-</para>
-
-@disp:
-@active:
-
-
-<!-- ##### FUNCTION gst_probe_dispatcher_add_probe ##### -->
-<para>
-
-</para>
-
-@disp:
-@probe:
-
-
-<!-- ##### FUNCTION gst_probe_dispatcher_remove_probe ##### -->
-<para>
-
-</para>
-
-@disp:
-@probe:
-
-
-<!-- ##### FUNCTION gst_probe_dispatcher_dispatch ##### -->
-<para>
-
-</para>
-
-@disp:
-@data:
-@Returns:
-
-
gstpipeline.c \
gstplugin.c \
gstpluginfeature.c \
- gstprobe.c \
gstquery.c \
gstqueryutils.c \
gstqueue.c \
gstpipeline.h \
gstplugin.h \
gstpluginfeature.h \
- gstprobe.h \
gstquery.h \
gstqueryutils.h \
gstqueue.h \
PAD_LINKED,
PAD_UNLINKED,
PAD_REQUEST_LINK,
+ PAD_HAVE_DATA,
/* FILL ME */
PAD_LAST_SIGNAL
};
return _gst_pad_type;
}
+static gboolean
+_gst_do_pass_data_accumulator (GSignalInvocationHint * ihint,
+ GValue * return_accu, const GValue * handler_return, gpointer dummy)
+{
+ if (!g_value_get_boolean (handler_return)) {
+ g_value_set_boolean (return_accu, FALSE);
+
+ /* stop emission here */
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
static void
gst_pad_class_init (GstPadClass * klass)
{
G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstPadClass, request_link), NULL,
NULL, gst_marshal_VOID__OBJECT, G_TYPE_NONE, 0);
+ gst_pad_signals[PAD_HAVE_DATA] =
+ g_signal_new ("have-data", G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstPadClass, have_data),
+ _gst_do_pass_data_accumulator,
+ NULL, gst_marshal_BOOLEAN__POINTER, G_TYPE_BOOLEAN, 1, G_TYPE_POINTER);
+
g_object_class_install_property (G_OBJECT_CLASS (klass), PAD_PROP_CAPS,
g_param_spec_boxed ("caps", "Caps", "The capabilities of the pad",
GST_TYPE_CAPS, G_PARAM_READABLE));
pad->queryfunc = gst_pad_query_default;
pad->intlinkfunc = gst_pad_get_internal_links_default;
+ pad->emit_buffer_signals = pad->emit_event_signals = 0;
+
GST_PAD_UNSET_FLUSHING (pad);
pad->preroll_lock = g_mutex_new ();
gst_pad_chain (GstPad * pad, GstBuffer * buffer)
{
GstCaps *caps;
- gboolean caps_changed;
+ gboolean caps_changed, do_pass = TRUE;
GstPadChainFunction chainfunc;
GstFlowReturn ret;
if (G_UNLIKELY ((chainfunc = GST_PAD_CHAINFUNC (pad)) == NULL))
goto no_function;
- GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
- "calling chainfunction &%s of pad %s:%s",
- GST_DEBUG_FUNCPTR_NAME (chainfunc), GST_DEBUG_PAD_NAME (pad));
+ if (g_atomic_int_get (&pad->emit_buffer_signals) >= 1) {
+ g_signal_emit (pad, gst_pad_signals[PAD_HAVE_DATA], 0, buffer, &do_pass);
+ }
+
+ if (do_pass) {
+ GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
+ "calling chainfunction &%s of pad %s:%s",
+ GST_DEBUG_FUNCPTR_NAME (chainfunc), GST_DEBUG_PAD_NAME (pad));
+
+ ret = chainfunc (pad, buffer);
+ } else {
+ GST_DEBUG ("Dropping buffer due to FALSE probe return");
+ gst_buffer_unref (buffer);
+ ret = GST_FLOW_UNEXPECTED;
+ }
- ret = chainfunc (pad, buffer);
GST_STREAM_UNLOCK (pad);
return ret;
{
GstPad *peer;
GstFlowReturn ret;
+ gboolean do_pass = TRUE;
g_return_val_if_fail (GST_IS_PAD (pad), GST_FLOW_ERROR);
g_return_val_if_fail (GST_PAD_DIRECTION (pad) == GST_PAD_SRC, GST_FLOW_ERROR);
gst_object_ref (peer);
GST_UNLOCK (pad);
- ret = gst_pad_chain (peer, buffer);
+ if (g_atomic_int_get (&pad->emit_buffer_signals) >= 1) {
+ g_signal_emit (pad, gst_pad_signals[PAD_HAVE_DATA], 0, buffer, &do_pass);
+ }
+
+ if (do_pass) {
+ ret = gst_pad_chain (peer, buffer);
+ } else {
+ GST_DEBUG ("Dropping buffer due to FALSE probe return");
+ gst_buffer_unref (buffer);
+ ret = GST_FLOW_UNEXPECTED;
+ }
gst_object_unref (peer);
GST_STREAM_UNLOCK (pad);
+ if (ret == GST_FLOW_OK && g_atomic_int_get (&pad->emit_buffer_signals) >= 1) {
+ gboolean do_pass = TRUE;
+
+ g_signal_emit (pad, gst_pad_signals[PAD_HAVE_DATA], 0, *buffer, &do_pass);
+ if (!do_pass) {
+ GST_DEBUG ("Dropping data after FALSE probe return");
+ gst_buffer_unref (*buffer);
+ *buffer = NULL;
+ ret = GST_FLOW_UNEXPECTED;
+ }
+ }
+
return ret;
/* ERRORS */
gst_object_unref (peer);
+ if (ret == GST_FLOW_OK && g_atomic_int_get (&pad->emit_buffer_signals) >= 1) {
+ gboolean do_pass = TRUE;
+
+ g_signal_emit (pad, gst_pad_signals[PAD_HAVE_DATA], 0, *buffer, &do_pass);
+ if (!do_pass) {
+ GST_DEBUG ("Dropping data after FALSE probe return");
+ gst_buffer_unref (*buffer);
+ *buffer = NULL;
+ ret = GST_FLOW_UNEXPECTED;
+ }
+ }
+
return ret;
/* ERROR recovery here */
gst_pad_push_event (GstPad * pad, GstEvent * event)
{
GstPad *peerpad;
- gboolean result;
+ gboolean result, do_pass = TRUE;
g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
g_return_val_if_fail (event != NULL, FALSE);
gst_object_ref (peerpad);
GST_UNLOCK (pad);
- result = gst_pad_send_event (peerpad, event);
+ if (g_atomic_int_get (&pad->emit_event_signals) >= 1) {
+ g_signal_emit (pad, gst_pad_signals[PAD_HAVE_DATA], 0, event, &do_pass);
+ }
+
+ if (do_pass) {
+ result = gst_pad_send_event (peerpad, event);
+ } else {
+ GST_DEBUG ("Dropping event after FALSE probe return");
+ gst_event_unref (event);
+ result = FALSE;
+ }
gst_object_unref (peerpad);
gboolean
gst_pad_send_event (GstPad * pad, GstEvent * event)
{
- gboolean result = FALSE;
+ gboolean result = FALSE, do_pass = TRUE;
GstPadEventFunction eventfunc;
g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
gst_object_ref (pad);
GST_UNLOCK (pad);
- result = eventfunc (GST_PAD_CAST (pad), event);
+ if (g_atomic_int_get (&pad->emit_event_signals) >= 1) {
+ g_signal_emit (pad, gst_pad_signals[PAD_HAVE_DATA], 0, event, &do_pass);
+ }
+
+ if (do_pass) {
+ result = eventfunc (GST_PAD_CAST (pad), event);
+ } else {
+ GST_DEBUG ("Dropping event after FALSE probe return");
+ gst_event_unref (event);
+ result = FALSE;
+ }
gst_object_unref (pad);
#include <gst/gstbuffer.h>
#include <gst/gstcaps.h>
#include <gst/gstevent.h>
-#include <gst/gstprobe.h>
#include <gst/gstquery.h>
#include <gst/gstqueryutils.h>
#include <gst/gsttask.h>
GstPadBufferAllocFunction bufferallocfunc;
- GstProbeDispatcher probedisp;
+ /* whether to emit signals for have-data */
+ gint emit_buffer_signals, emit_event_signals;
/*< private >*/
gpointer _gst_reserved[GST_PADDING];
void (*linked) (GstPad *pad, GstPad *peer);
void (*unlinked) (GstPad *pad, GstPad *peer);
void (*request_link) (GstPad *pad);
+ gboolean (*have_data) (GstPad *pad, GstMiniObject *data);
/*< private >*/
gpointer _gst_reserved[GST_PADDING];
/* misc helper functions */
gboolean gst_pad_dispatcher (GstPad *pad, GstPadDispatcherFunction dispatch,
gpointer data);
-/* probes */
-#define gst_pad_add_probe(pad, probe) \
- (gst_probe_dispatcher_add_probe (&(GST_PAD_CAST (pad)->probedisp), probe))
-#define gst_pad_remove_probe(pad, probe) \
- (gst_probe_dispatcher_remove_probe (&(GST_PAD_CAST (pad)->probedisp), probe))
#ifndef GST_DISABLE_LOADSAVE
void gst_pad_load_and_link (xmlNodePtr self, GstObject *parent);
*atomic_int = value;
ignore = g_atomic_int_get (atomic_int);
}
+
+/**
+ * gst_pad_add_data_probe:
+ * @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
+ *
+ * Connects a signal handler to the pad's have-data signal, and increases
+ * the emit_{buffer,event}_signals atomic number on the pads so that those
+ * signals are actually fired.
+ */
+
+void
+gst_pad_add_data_probe (GstPad * pad, GCallback handler, gpointer data)
+{
+ g_return_if_fail (GST_IS_PAD (pad));
+ g_return_if_fail (handler != NULL);
+
+ g_signal_connect (pad, "have-data", handler, data);
+ g_atomic_int_inc (&pad->emit_event_signals);
+ g_atomic_int_inc (&pad->emit_buffer_signals);
+}
+
+/**
+ * gst_pad_add_event_probe:
+ * @pad: pad to add the event probe handler to
+ * @handler: function to call when data is passed over pad
+ * @data: data to pass along with the handler
+ *
+ * Connects a signal handler to the pad's have-data signal, and increases
+ * the emit_event_signals atomic number on the pads so that this signal
+ * is actually fired.
+ */
+
+void
+gst_pad_add_event_probe (GstPad * pad, GCallback handler, gpointer data)
+{
+ g_return_if_fail (GST_IS_PAD (pad));
+ g_return_if_fail (handler != NULL);
+
+ g_signal_connect (pad, "have-data", handler, data);
+ g_atomic_int_inc (&pad->emit_event_signals);
+}
+
+/**
+ * gst_pad_add_buffer_probe:
+ * @pad: pad to add the buffer probe handler to
+ * @handler: function to call when data is passed over pad
+ * @data: data to pass along with the handler
+ *
+ * Connects a signal handler to the pad's have-data signal, and increases
+ * the emit_buffer_signals atomic number on the pads so that this signal
+ * is actually fired.
+ */
+
+void
+gst_pad_add_buffer_probe (GstPad * pad, GCallback handler, gpointer data)
+{
+ g_return_if_fail (GST_IS_PAD (pad));
+ g_return_if_fail (handler != NULL);
+
+ g_signal_connect (pad, "have-data", handler, data);
+ g_atomic_int_inc (&pad->emit_buffer_signals);
+}
+
+#define g_atomic_int_dec(atomic) (g_atomic_int_add ((atomic), -1))
+
+/**
+ * gst_pad_remove_data_probe:
+ * @pad: pad to remove the data probe handler from
+ * @handler: function that was assigned to the signal
+ * @data: data that was assigned to the signal handler
+ *
+ * Unconnects a signal handler to the pad's have-data signal, and decreases
+ * the emit_{buffer,event}_signals atomic number on the pads so that those
+ * signals are actually no more fired if no signals are connected.
+ */
+
+void
+gst_pad_remove_data_probe (GstPad * pad, GCallback handler, gpointer data)
+{
+ g_return_if_fail (GST_IS_PAD (pad));
+ g_return_if_fail (handler != NULL);
+
+ g_signal_handlers_disconnect_by_func (pad, handler, data);
+ g_atomic_int_dec (&pad->emit_event_signals);
+ g_atomic_int_dec (&pad->emit_buffer_signals);
+}
+
+/**
+ * gst_pad_remove_event_probe:
+ * @pad: pad to remove the event probe handler from
+ * @handler: function that was assigned to the signal
+ * @data: data that was assigned to the signal handler
+ *
+ * Unconnects a signal handler to the pad's have-data signal, and decreases
+ * the emit_event_signals atomic number on the pads so that this signal is
+ * actually no more fired if no signals are connected.
+ */
+
+void
+gst_pad_remove_event_probe (GstPad * pad, GCallback handler, gpointer data)
+{
+ g_return_if_fail (GST_IS_PAD (pad));
+ g_return_if_fail (handler != NULL);
+
+ g_signal_handlers_disconnect_by_func (pad, handler, data);
+ g_atomic_int_dec (&pad->emit_event_signals);
+}
+
+/**
+ * gst_pad_remove_buffer_probe:
+ * @pad: pad to remove the buffer probe handler from
+ * @handler: function that was assigned to the signal
+ * @data: data that was assigned to the signal handler
+ *
+ * Unconnects a signal handler to the pad's have-data signal, and decreases
+ * the emit_buffer_signals atomic number on the pads so that this signal is
+ * actually no more fired if no signals are connected.
+ */
+
+void
+gst_pad_remove_buffer_probe (GstPad * pad, GCallback handler, gpointer data)
+{
+ g_return_if_fail (GST_IS_PAD (pad));
+ g_return_if_fail (handler != NULL);
+
+ g_signal_handlers_disconnect_by_func (pad, handler, data);
+ g_atomic_int_dec (&pad->emit_buffer_signals);
+}
/* atomic functions */
void gst_atomic_int_set (gint * atomic_int, gint value);
+/* probes */
+void gst_pad_add_data_probe (GstPad * pad,
+ GCallback handler,
+ gpointer data);
+void gst_pad_remove_data_probe (GstPad * pad,
+ GCallback handler,
+ gpointer data);
+void gst_pad_add_event_probe (GstPad * pad,
+ GCallback handler,
+ gpointer data);
+void gst_pad_remove_event_probe (GstPad * pad,
+ GCallback handler,
+ gpointer data);
+void gst_pad_add_buffer_probe (GstPad * pad,
+ GCallback handler,
+ gpointer data);
+void gst_pad_remove_buffer_probe (GstPad * pad,
+ GCallback handler,
+ gpointer data);
+
G_END_DECLS
#endif /* __GST_UTILS_H__ */