diff --git a/gst/gstquery.c b/gst/gstquery.c index a3d4daed27..61391dd674 100644 --- a/gst/gstquery.c +++ b/gst/gstquery.c @@ -61,6 +61,11 @@ * Last reviewed on 2006-02-14 (0.10.4) */ + +/* FIXME 0.11: suppress warnings for deprecated API such as GValueArray + * with newer GLib versions (>= 2.31.0) */ +#define GLIB_DISABLE_DEPRECATION_WARNINGS + #include "gst_private.h" #include "gstinfo.h" #include "gstquery.h" diff --git a/libs/gst/base/gstcollectpads2.c b/libs/gst/base/gstcollectpads2.c index 4f3ef75016..461ac61350 100644 --- a/libs/gst/base/gstcollectpads2.c +++ b/libs/gst/base/gstcollectpads2.c @@ -1662,8 +1662,8 @@ gst_collect_pads2_event (GstPad * pad, GstObject * parent, GstEvent * event) pads = data->collect; - GST_DEBUG ("Got %s event on pad %s:%s", GST_EVENT_TYPE_NAME (event), - GST_DEBUG_PAD_NAME (data->pad)); + GST_DEBUG_OBJECT (data->pad, "Got %s event on sink pad from %s", + GST_EVENT_TYPE_NAME (event), GST_OBJECT_NAME (GST_EVENT_SRC (event))); GST_OBJECT_LOCK (pads); event_func = pads->priv->event_func; @@ -1675,10 +1675,12 @@ gst_collect_pads2_event (GstPad * pad, GstObject * parent, GstEvent * event) case GST_EVENT_FLUSH_START: { /* forward event to unblock check_collected */ - if (event_func) + if (event_func) { res = event_func (pads, data, event, event_user_data); - else + } else { + GST_DEBUG_OBJECT (pad, "forwarding flush start"); res = gst_pad_event_default (pad, parent, event); + } /* now unblock the chain function. * no cond per pad, so they all unblock, @@ -1810,10 +1812,12 @@ forward_or_default: GST_COLLECT_PADS2_STREAM_LOCK (pads); need_unlock = TRUE; } - if (event_func) + if (event_func) { res = event_func (pads, data, event, event_user_data); - else + } else { + GST_DEBUG_OBJECT (pad, "forwarding %s", GST_EVENT_TYPE_NAME (event)); res = gst_pad_event_default (pad, parent, event); + } if (need_unlock) GST_COLLECT_PADS2_STREAM_UNLOCK (pads); goto done; diff --git a/libs/gst/check/gstconsistencychecker.c b/libs/gst/check/gstconsistencychecker.c index 66291f4ca3..a0a176e8a2 100644 --- a/libs/gst/check/gstconsistencychecker.c +++ b/libs/gst/check/gstconsistencychecker.c @@ -3,6 +3,7 @@ * unit testing helper lib * * Copyright (C) 2009 Edward Hervey + * Copyright (C) 2012 Stefan Sauer * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -34,19 +35,30 @@ struct _GstStreamConsistency { - gboolean flushing; - gboolean segment; - gboolean eos; - gulong probeid; - GstPad *pad; + /* FIXME: do we want to track some states per pad? */ + volatile gboolean flushing; + volatile gboolean newsegment; + volatile gboolean eos; + volatile gboolean expect_flush; + GstObject *parent; + GList *pads; }; +typedef struct _GstStreamConsistencyProbe +{ + GstPad *pad; + gulong probeid; +} GstStreamConsistencyProbe; + static gboolean source_pad_data_cb (GstPad * pad, GstPadProbeInfo * info, GstStreamConsistency * consist) { GstMiniObject *data = GST_PAD_PROBE_INFO_DATA (info); + GST_DEBUG_OBJECT (pad, "%p: %d %d %d %d", consist, consist->flushing, + consist->newsegment, consist->eos, consist->expect_flush); + if (GST_IS_BUFFER (data)) { GST_DEBUG_OBJECT (pad, "Buffer pts %" GST_TIME_FORMAT ", dts %" GST_TIME_FORMAT, @@ -62,6 +74,9 @@ source_pad_data_cb (GstPad * pad, GstPadProbeInfo * info, GST_DEBUG_OBJECT (pad, "%s", GST_EVENT_TYPE_NAME (event)); switch (GST_EVENT_TYPE (event)) { case GST_EVENT_FLUSH_START: + /* FIXME : not 100% sure about whether getting two flush_start in a row + * is valid */ + fail_if (consist->flushing, "Received another FLUSH_START"); consist->flushing = TRUE; break; case GST_EVENT_FLUSH_STOP: @@ -69,9 +84,11 @@ source_pad_data_cb (GstPad * pad, GstPadProbeInfo * info, fail_unless (consist->flushing, "Received a FLUSH_STOP without a FLUSH_START"); fail_if (consist->eos, "Received a FLUSH_STOP after an EOS"); - consist->flushing = FALSE; + consist->flushing = consist->expect_flush = FALSE; break; case GST_EVENT_SEGMENT: + fail_if ((consist->expect_flush && consist->flushing), + "Received SEGMENT while in a flushing seek"); consist->segment = TRUE; consist->eos = FALSE; break; @@ -98,6 +115,75 @@ source_pad_data_cb (GstPad * pad, GstPadProbeInfo * info, return TRUE; } +static gboolean +sink_pad_data_cb (GstPad * pad, GstPadProbeInfo * info, + GstStreamConsistency * consist) +{ + GstMiniObject *data = GST_PAD_PROBE_INFO_DATA (info); + + GST_DEBUG_OBJECT (pad, "%p: %d %d %d %d", consist, consist->flushing, + consist->newsegment, consist->eos, consist->expect_flush); + + if (GST_IS_BUFFER (data)) { + GST_DEBUG_OBJECT (pad, "Buffer %" GST_TIME_FORMAT, + GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (GST_BUFFER (data)))); + /* If an EOS went through, a buffer would be invalid */ + fail_if (consist->eos, "Buffer received after EOS"); + /* Buffers need to be preceded by a newsegment event */ + fail_unless (consist->newsegment, "Buffer received without newsegment"); + } else if (GST_IS_EVENT (data)) { + GstEvent *event = (GstEvent *) data; + + GST_DEBUG_OBJECT (pad, "%s", GST_EVENT_TYPE_NAME (event)); + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_SEEK: + { + GstSeekFlags flags; + + gst_event_parse_seek (event, NULL, NULL, &flags, NULL, NULL, NULL, + NULL); + consist->expect_flush = + ((flags & GST_SEEK_FLAG_FLUSH) == GST_SEEK_FLAG_FLUSH); + break; + } + case GST_EVENT_SEGMENT: + fail_if ((consist->expect_flush && consist->flushing), + "Received SEGMENT while in a flushing seek"); + consist->segment = TRUE; + consist->eos = FALSE; + break; + default: + /* FIXME : Figure out what to do for other events */ + break; + } + } + + return TRUE; +} + +static void +add_pad (GstStreamConsistency * consist, GstPad * pad) +{ + GstStreamConsistencyProbe *p; + GstPadDirection dir; + + p = g_new0 (GstStreamConsistencyProbe, 1); + p->pad = g_object_ref (pad); + dir = gst_pad_get_direction (pad); + if (dir == GST_PAD_SRC) { + + p->probeid = + gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_DATA_DOWNSTREAM, + (GstPadProbeCallback) source_pad_data_cb, consist, NULL); + + } else if (dir == GST_PAD_SINK) { + p->probeid = + gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_DATA_DOWNSTREAM, + (GstPadProbeCallback) sink_pad_data_cb, consist, NULL); + } + consist->pads = g_list_prepend (consist->pads, p); +} + /** * gst_consistency_checker_new: * @pad: The #GstPad on which the dataflow will be checked. @@ -105,13 +191,10 @@ source_pad_data_cb (GstPad * pad, GstPadProbeInfo * info, * Sets up a data probe on the given pad which will raise assertions if the * data flow is inconsistent. * - * Currently only works for source pads. - * * Returns: A #GstStreamConsistency structure used to track data flow. * * Since: 0.10.24 */ - GstStreamConsistency * gst_consistency_checker_new (GstPad * pad) { @@ -120,14 +203,37 @@ gst_consistency_checker_new (GstPad * pad) g_return_val_if_fail (pad != NULL, NULL); consist = g_new0 (GstStreamConsistency, 1); - consist->pad = g_object_ref (pad); - consist->probeid = - gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_DATA_DOWNSTREAM, - (GstPadProbeCallback) source_pad_data_cb, consist, NULL); + if (!consist->pads) { + consist->parent = GST_OBJECT_PARENT (pad); + } + add_pad (consist, pad); return consist; } +/** + * gst_consistency_checker_add_pad: + * @consist: The #GstStreamConsistency handle + * @pad: The #GstPad on which the dataflow will be checked. + * + * Sets up a data probe on the given pad which will raise assertions if the + * data flow is inconsistent. + * + * Returns: %TRUE if the pad was added + * + * Since: 0.10.37 + */ +gboolean +gst_consistency_checker_add_pad (GstStreamConsistency * consist, GstPad * pad) +{ + g_return_val_if_fail (consist != NULL, FALSE); + g_return_val_if_fail (pad != NULL, FALSE); + g_return_val_if_fail (GST_OBJECT_PARENT (pad) == consist->parent, FALSE); + + add_pad (consist, pad); + return TRUE; +} + /** * gst_consistency_checker_reset: * @consist: The #GstStreamConsistency to reset. @@ -149,7 +255,7 @@ gst_consistency_checker_reset (GstStreamConsistency * consist) * gst_consistency_checker_free: * @consist: The #GstStreamConsistency to free. * - * Frees the allocated data and probe associated with @consist. + * Frees the allocated data and probes associated with @consist. * * Since: 0.10.24 */ @@ -157,8 +263,20 @@ gst_consistency_checker_reset (GstStreamConsistency * consist) void gst_consistency_checker_free (GstStreamConsistency * consist) { + GList *node; + GstStreamConsistencyProbe *p; + /* Remove the data probe */ gst_pad_remove_probe (consist->pad, consist->probeid); g_object_unref (consist->pad); + + /* Remove the data probes */ + for (node = consist->pads; node; node = g_list_next (node)) { + p = (GstStreamConsistencyProbe *) node->data; + gst_pad_remove_probe (p->pad, p->probeid); + g_object_unref (p->pad); + g_free (p); + } + g_list_free (consist->pads); g_free (consist); } diff --git a/libs/gst/check/gstconsistencychecker.h b/libs/gst/check/gstconsistencychecker.h index ec88af701e..4cbf3f8bb3 100644 --- a/libs/gst/check/gstconsistencychecker.h +++ b/libs/gst/check/gstconsistencychecker.h @@ -37,11 +37,13 @@ G_BEGIN_DECLS typedef struct _GstStreamConsistency GstStreamConsistency; -GstStreamConsistency * gst_consistency_checker_new (GstPad * pad); +GstStreamConsistency * gst_consistency_checker_new (GstPad * pad); +gboolean gst_consistency_checker_add_pad (GstStreamConsistency * consist, + GstPad * pad); -void gst_consistency_checker_reset (GstStreamConsistency * consist); +void gst_consistency_checker_reset (GstStreamConsistency * consist); -void gst_consistency_checker_free (GstStreamConsistency * consist); +void gst_consistency_checker_free (GstStreamConsistency * consist); G_END_DECLS diff --git a/tests/check/gst/gstdatetime.c b/tests/check/gst/gstdatetime.c index ccc692f8ce..10f1c607f9 100644 --- a/tests/check/gst/gstdatetime.c +++ b/tests/check/gst/gstdatetime.c @@ -24,11 +24,13 @@ #include #include -#define ASSERT_TIME(dt,H,M,S) G_STMT_START { \ - assert_equals_int ((H), gst_date_time_get_hour ((dt))); \ - assert_equals_int ((M), gst_date_time_get_minute ((dt))); \ - assert_equals_int ((S), gst_date_time_get_second ((dt))); \ -} G_STMT_END +#define assert_almost_equals_int(a, b) \ +G_STMT_START { \ + int first = a; \ + int second = b; \ + fail_unless(ABS (first - second) <= 1, \ + "'" #a "' (%d) is not almost equal to '" #b"' (%d)", first, second); \ +} G_STMT_END; GST_START_TEST (test_GstDateTime_now) { @@ -49,7 +51,7 @@ GST_START_TEST (test_GstDateTime_now) assert_equals_int (gst_date_time_get_day (dt), tm.tm_mday); assert_equals_int (gst_date_time_get_hour (dt), tm.tm_hour); assert_equals_int (gst_date_time_get_minute (dt), tm.tm_min); - assert_equals_int (gst_date_time_get_second (dt), tm.tm_sec); + assert_almost_equals_int (gst_date_time_get_second (dt), tm.tm_sec); gst_date_time_unref (dt); } @@ -177,7 +179,7 @@ GST_START_TEST (test_GstDateTime_get_microsecond) g_get_current_time (&tv); dt = gst_date_time_new (0, 2010, 7, 15, 11, 12, 13 + (tv.tv_usec / 1000000.0)); - assert_equals_int (tv.tv_usec, gst_date_time_get_microsecond (dt)); + assert_almost_equals_int (tv.tv_usec, gst_date_time_get_microsecond (dt)); gst_date_time_unref (dt); } @@ -252,7 +254,7 @@ GST_START_TEST (test_GstDateTime_utc_now) assert_equals_int (tm.tm_mday, gst_date_time_get_day (dt)); assert_equals_int (tm.tm_hour, gst_date_time_get_hour (dt)); assert_equals_int (tm.tm_min, gst_date_time_get_minute (dt)); - assert_equals_int (tm.tm_sec, gst_date_time_get_second (dt)); + assert_almost_equals_int (tm.tm_sec, gst_date_time_get_second (dt)); gst_date_time_unref (dt); }