_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);
- return FALSE;
- }
+ gboolean ret = g_value_get_boolean (handler_return);
- return TRUE;
+ GST_DEBUG ("accumulated %d", ret);
+ g_value_set_boolean (return_accu, ret);
+
+ return ret;
}
static gboolean
-silly_return_true_function (GstPad * pad, GstMiniObject * o)
+default_have_data (GstPad * pad, GstMiniObject * o)
{
return TRUE;
}
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);
+ NULL, gst_marshal_BOOLEAN__POINTER, G_TYPE_BOOLEAN, 1,
+ GST_TYPE_MINI_OBJECT);
g_object_class_install_property (G_OBJECT_CLASS (klass), PAD_PROP_CAPS,
g_param_spec_boxed ("caps", "Caps", "The capabilities of the pad",
gstobject_class->save_thyself = GST_DEBUG_FUNCPTR (gst_pad_save_thyself);
#endif
gstobject_class->path_string_separator = ".";
- klass->have_data = silly_return_true_function;
+
+ klass->have_data = default_have_data;
}
static void
pad->queryfunc = gst_pad_query_default;
pad->intlinkfunc = gst_pad_get_internal_links_default;
- pad->emit_buffer_signals = pad->emit_event_signals = 0;
+ pad->do_buffer_signals = 0;
+ pad->do_event_signals = 0;
GST_PAD_UNSET_FLUSHING (pad);
gst_pad_chain (GstPad * pad, GstBuffer * buffer)
{
GstCaps *caps;
- gboolean caps_changed, do_pass = TRUE;
+ gboolean caps_changed;
GstPadChainFunction chainfunc;
GstFlowReturn ret;
+ gboolean emit_signal;
g_return_val_if_fail (GST_IS_PAD (pad), GST_FLOW_ERROR);
g_return_val_if_fail (GST_PAD_DIRECTION (pad) == GST_PAD_SINK,
caps = GST_BUFFER_CAPS (buffer);
caps_changed = caps && caps != GST_PAD_CAPS (pad);
+
+ emit_signal = GST_PAD_DO_BUFFER_SIGNALS (pad) > 0;
GST_UNLOCK (pad);
+ /* see if the signal should be emited, we emit before caps nego as
+ * we might drop the buffer and do capsnego for nothing. */
+ if (G_UNLIKELY (emit_signal)) {
+ if (!gst_pad_emit_have_data_signal (pad, GST_MINI_OBJECT (buffer)))
+ goto dropping;
+ }
+
/* we got a new datatype on the pad, see if it can handle it */
if (G_UNLIKELY (caps_changed)) {
GST_DEBUG ("caps changed to %" GST_PTR_FORMAT, caps);
if (G_UNLIKELY ((chainfunc = GST_PAD_CHAINFUNC (pad)) == NULL))
goto no_function;
- if (g_atomic_int_get (&pad->emit_buffer_signals) >= 1) {
- do_pass = gst_pad_emit_have_data_signal (pad, GST_MINI_OBJECT (buffer));
- }
+ 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 (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);
GST_STREAM_UNLOCK (pad);
return GST_FLOW_UNEXPECTED;
}
+dropping:
+ {
+ gst_buffer_unref (buffer);
+ GST_DEBUG ("Dropping buffer due to FALSE probe return");
+ GST_STREAM_UNLOCK (pad);
+ /* FIXME, failure? */
+ return GST_FLOW_UNEXPECTED;
+ }
not_negotiated:
{
gst_buffer_unref (buffer);
{
GstPad *peer;
GstFlowReturn ret;
- gboolean do_pass = TRUE;
+ gboolean emit_signal;
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);
if (G_UNLIKELY ((peer = GST_PAD_PEER (pad)) == NULL))
goto not_linked;
+ /* we emit signals on the pad areg, the peer will have a chance to
+ * emit in the _chain() function */
+ emit_signal = GST_PAD_DO_BUFFER_SIGNALS (pad) > 0;
+
gst_object_ref (peer);
GST_UNLOCK (pad);
- if (g_atomic_int_get (&pad->emit_buffer_signals) >= 1) {
- do_pass = gst_pad_emit_have_data_signal (pad, GST_MINI_OBJECT (buffer));
+ if (G_UNLIKELY (emit_signal)) {
+ if (!gst_pad_emit_have_data_signal (pad, GST_MINI_OBJECT (buffer)))
+ goto dropping;
}
- 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;
- }
+ ret = gst_pad_chain (peer, buffer);
gst_object_unref (peer);
GST_UNLOCK (pad);
return GST_FLOW_NOT_LINKED;
}
+dropping:
+ {
+ gst_buffer_unref (buffer);
+ gst_object_unref (peer);
+ GST_DEBUG ("Dropping buffer due to FALSE probe return");
+ /* FIXME, failure? */
+ return GST_FLOW_UNEXPECTED;
+ }
}
/**
/* see note in above function */
if (G_LIKELY ((checkgetrangefunc = peer->checkgetrangefunc) == NULL)) {
+ /* FIXME, kindoff ghetto */
ret = GST_PAD_GETRANGEFUNC (peer) != NULL;
} else {
GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
{
GstFlowReturn ret;
GstPadGetRangeFunction getrangefunc;
+ gboolean emit_signal;
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_LOCK (pad);
if (G_UNLIKELY (GST_PAD_IS_FLUSHING (pad)))
goto flushing;
+
+ emit_signal = GST_PAD_DO_BUFFER_SIGNALS (pad) > 0;
GST_UNLOCK (pad);
if (G_UNLIKELY ((getrangefunc = GST_PAD_GETRANGEFUNC (pad)) == NULL))
ret = getrangefunc (pad, offset, size, buffer);
- GST_STREAM_UNLOCK (pad);
-
- if (ret == GST_FLOW_OK && g_atomic_int_get (&pad->emit_buffer_signals) >= 1) {
- gboolean do_pass = TRUE;
-
- do_pass = gst_pad_emit_have_data_signal (pad, GST_MINI_OBJECT (*buffer));
- if (!do_pass) {
- GST_DEBUG ("Dropping data after FALSE probe return");
- gst_buffer_unref (*buffer);
- *buffer = NULL;
- ret = GST_FLOW_UNEXPECTED;
- }
+ /* can only fire the signal if we have a valid buffer */
+ if (G_UNLIKELY (emit_signal) && (ret == GST_FLOW_OK)) {
+ if (!gst_pad_emit_have_data_signal (pad, GST_MINI_OBJECT (*buffer)))
+ goto dropping;
}
+ GST_STREAM_UNLOCK (pad);
+
return ret;
/* ERRORS */
GST_STREAM_UNLOCK (pad);
return GST_FLOW_ERROR;
}
+dropping:
+ {
+ GST_DEBUG ("Dropping data after FALSE probe return");
+ GST_STREAM_UNLOCK (pad);
+ gst_buffer_unref (*buffer);
+ *buffer = NULL;
+ return GST_FLOW_UNEXPECTED;
+ }
}
{
GstPad *peer;
GstFlowReturn ret;
+ gboolean emit_signal;
g_return_val_if_fail (GST_IS_PAD (pad), GST_FLOW_ERROR);
g_return_val_if_fail (GST_PAD_DIRECTION (pad) == GST_PAD_SINK,
if (G_UNLIKELY ((peer = GST_PAD_PEER (pad)) == NULL))
goto not_connected;
+ /* signal emision for the pad, peer has chance to emit when
+ * we call _get_range() */
+ emit_signal = GST_PAD_DO_BUFFER_SIGNALS (pad) > 0;
+
gst_object_ref (peer);
GST_UNLOCK (pad);
gst_object_unref (peer);
- if (ret == GST_FLOW_OK && g_atomic_int_get (&pad->emit_buffer_signals) >= 1) {
- gboolean do_pass = TRUE;
-
- do_pass = gst_pad_emit_have_data_signal (pad, GST_MINI_OBJECT (*buffer));
- if (!do_pass) {
- GST_DEBUG ("Dropping data after FALSE probe return");
- gst_buffer_unref (*buffer);
- *buffer = NULL;
- ret = GST_FLOW_UNEXPECTED;
- }
+ /* can only fire the signal if we have a valid buffer */
+ if (G_UNLIKELY (emit_signal) && (ret == GST_FLOW_OK)) {
+ if (!gst_pad_emit_have_data_signal (pad, GST_MINI_OBJECT (*buffer)))
+ goto dropping;
}
-
return ret;
/* ERROR recovery here */
GST_UNLOCK (pad);
return GST_FLOW_NOT_LINKED;
}
+dropping:
+ {
+ GST_DEBUG ("Dropping data after FALSE probe return");
+ gst_buffer_unref (*buffer);
+ *buffer = NULL;
+ return GST_FLOW_UNEXPECTED;
+ }
}
/**
gst_pad_push_event (GstPad * pad, GstEvent * event)
{
GstPad *peerpad;
- gboolean result, do_pass = TRUE;
+ gboolean result;
+ gboolean emit_signal;
g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
g_return_val_if_fail (event != NULL, FALSE);
if (peerpad == NULL)
goto not_linked;
+ emit_signal = GST_PAD_DO_EVENT_SIGNALS (pad) > 0;
+
gst_object_ref (peerpad);
GST_UNLOCK (pad);
- if (g_atomic_int_get (&pad->emit_event_signals) >= 1) {
- do_pass = gst_pad_emit_have_data_signal (pad, GST_MINI_OBJECT (event));
+ if (G_UNLIKELY (emit_signal)) {
+ if (!gst_pad_emit_have_data_signal (pad, GST_MINI_OBJECT (event)))
+ goto dropping;
}
- 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;
- }
+ result = gst_pad_send_event (peerpad, event);
gst_object_unref (peerpad);
GST_UNLOCK (pad);
return FALSE;
}
+dropping:
+ {
+ GST_DEBUG ("Dropping event after FALSE probe return");
+ gst_object_unref (peerpad);
+ gst_event_unref (event);
+ return FALSE;
+ }
}
/**
gboolean
gst_pad_send_event (GstPad * pad, GstEvent * event)
{
- gboolean result = FALSE, do_pass = TRUE;
+ gboolean result = FALSE;
GstPadEventFunction eventfunc;
+ gboolean emit_signal;
g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
g_return_val_if_fail (event != NULL, FALSE);
if ((eventfunc = GST_PAD_EVENTFUNC (pad)) == NULL)
goto no_function;
+ emit_signal = GST_PAD_DO_EVENT_SIGNALS (pad) > 0;
+
gst_object_ref (pad);
GST_UNLOCK (pad);
- if (g_atomic_int_get (&pad->emit_event_signals) >= 1) {
- do_pass = gst_pad_emit_have_data_signal (pad, GST_MINI_OBJECT (event));
+ if (G_UNLIKELY (emit_signal)) {
+ if (!gst_pad_emit_have_data_signal (pad, GST_MINI_OBJECT (event)))
+ goto dropping;
}
- 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;
- }
+ result = eventfunc (GST_PAD_CAST (pad), event);
gst_object_unref (pad);
gst_event_unref (event);
return FALSE;
}
+dropping:
+ {
+ GST_DEBUG ("Dropping event after FALSE probe return");
+ gst_object_unref (pad);
+ gst_event_unref (event);
+ return FALSE;
+ }
}
/************************************************************************
}
/**
- * gst_buffer_merge:
- * @buf1: a first source #GstBuffer to merge.
- * @buf2: the second source #GstBuffer to merge.
+ * gst_buffer_join:
+ * @buf1: a first source #GstBuffer to join.
+ * @buf2: the second source #GstBuffer to join.
*
* Create a new buffer that is the concatenation of the two source
* buffers, and takes ownership of the original source buffers.
int ignore;
*atomic_int = value;
+ /* read acts as a memory barrier */
ignore = g_atomic_int_get (atomic_int);
}
* @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
+ * the do_{buffer,event}_signals number on the pads so that those
* signals are actually fired.
*/
g_return_if_fail (GST_IS_PAD (pad));
g_return_if_fail (handler != NULL);
+ GST_LOCK (pad);
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_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",
+ GST_DEBUG_PAD_NAME (pad),
+ GST_PAD_DO_BUFFER_SIGNALS (pad), GST_PAD_DO_EVENT_SIGNALS (pad));
+ GST_UNLOCK (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
+ * the do_event_signals number on the pads so that this signal
* is actually fired.
*/
g_return_if_fail (GST_IS_PAD (pad));
g_return_if_fail (handler != NULL);
+ GST_LOCK (pad);
g_signal_connect (pad, "have-data", handler, data);
- g_atomic_int_inc (&pad->emit_event_signals);
+ 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));
+ GST_UNLOCK (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
+ * the do_buffer_signals number on the pads so that this signal
* is actually fired.
*/
g_return_if_fail (GST_IS_PAD (pad));
g_return_if_fail (handler != NULL);
+ GST_LOCK (pad);
g_signal_connect (pad, "have-data", handler, data);
- g_atomic_int_inc (&pad->emit_buffer_signals);
+ 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));
+ GST_UNLOCK (pad);
}
-#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
* @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
+ * the do_{buffer,event}_signals 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)
{
+ guint count;
+
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_LOCK (pad);
+ count = g_signal_handlers_disconnect_by_func (pad, handler, data);
+ GST_PAD_DO_BUFFER_SIGNALS (pad) -= count;
+ GST_PAD_DO_EVENT_SIGNALS (pad) -= count;
+ GST_DEBUG
+ ("removing %d data probes from pad %s:%s, now %d event, %d buffer probes",
+ count, GST_DEBUG_PAD_NAME (pad), GST_PAD_DO_EVENT_SIGNALS (pad),
+ GST_PAD_DO_BUFFER_SIGNALS (pad));
+ GST_UNLOCK (pad);
}
/**
* @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
+ * the do_event_signals 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)
{
+ guint count;
+
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_LOCK (pad);
+ count = g_signal_handlers_disconnect_by_func (pad, handler, data);
+ GST_PAD_DO_EVENT_SIGNALS (pad) -= count;
+ GST_DEBUG ("removing %d event probes from pad %s:%s, now %d event probes",
+ count, GST_DEBUG_PAD_NAME (pad), GST_PAD_DO_EVENT_SIGNALS (pad));
+ GST_UNLOCK (pad);
}
/**
* @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
+ * the emit_buffer_signals 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)
{
+ guint count;
+
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);
+ GST_LOCK (pad);
+ count = g_signal_handlers_disconnect_by_func (pad, handler, data);
+ GST_PAD_DO_BUFFER_SIGNALS (pad) -= count;
+ GST_DEBUG ("removing %d buffer probes from pad %s:%s, now %d buffer probes",
+ count, GST_DEBUG_PAD_NAME (pad), GST_PAD_DO_BUFFER_SIGNALS (pad));
+ GST_UNLOCK (pad);
}