From 58a5b2f5fa970a608c28b738ed5bf040085dda41 Mon Sep 17 00:00:00 2001 From: Andy Wingo Date: Tue, 15 Nov 2005 12:29:07 +0000 Subject: [PATCH] check/gst/gstpipeline.c (test_base_time): New test for buffer timestamps with live capture. Original commit message from CVS: 2005-11-15 Andy Wingo * check/gst/gstpipeline.c (test_base_time): New test for buffer timestamps with live capture. * gst/elements/gstfakesrc.c (gst_fake_src_create): If the datarate is 0 but we are a live source, timestamp the buffers using the element's clock. --- ChangeLog | 9 +++++ check/gst/gstpipeline.c | 88 +++++++++++++++++++++++++++++++++++++++++++ gst/elements/gstfakesrc.c | 15 +++++++- plugins/elements/gstfakesrc.c | 15 +++++++- tests/check/gst/gstpipeline.c | 88 +++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 211 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index d5b3f2e..612319d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2005-11-15 Andy Wingo + + * check/gst/gstpipeline.c (test_base_time): New test for buffer + timestamps with live capture. + + * gst/elements/gstfakesrc.c (gst_fake_src_create): If the datarate + is 0 but we are a live source, timestamp the buffers using the + element's clock. + 2005-11-14 Stefan Kost * docs/gst/gstreamer-sections.txt: diff --git a/check/gst/gstpipeline.c b/check/gst/gstpipeline.c index 514d125..dc54c33 100644 --- a/check/gst/gstpipeline.c +++ b/check/gst/gstpipeline.c @@ -226,6 +226,93 @@ GST_START_TEST (test_bus) GST_END_TEST; +static gboolean +sink_pad_probe (GstPad * pad, GstBuffer * buffer, + GstClockTime * first_timestamp) +{ + gint memory_barrier = 1; + volatile gint foo; + + fail_if (GST_BUFFER_TIMESTAMP (buffer) == GST_CLOCK_TIME_NONE, + "testing if buffer timestamps are right, but got CLOCK_TIME_NONE"); + + if (*first_timestamp == GST_CLOCK_TIME_NONE) + *first_timestamp = GST_BUFFER_TIMESTAMP (buffer); + + /* make sure the other thread sees the update */ + foo = g_atomic_int_get (&memory_barrier); + + return TRUE; +} + +GST_START_TEST (test_base_time) +{ + GstElement *pipeline, *fakesrc, *fakesink; + GstPad *sink; + GstClockTime observed, lower, upper, base; + GstClock *clock; + + pipeline = gst_element_factory_make ("pipeline", "pipeline"); + fakesrc = gst_element_factory_make ("fakesrc", "fakesrc"); + fakesink = gst_element_factory_make ("fakesink", "fakesink"); + + fail_unless (pipeline && fakesrc && fakesink, "couldn't make elements"); + + g_object_set (fakesrc, "is-live", (gboolean) TRUE, NULL); + + gst_bin_add_many (GST_BIN (pipeline), fakesrc, fakesink, NULL); + gst_element_link (fakesrc, fakesink); + + sink = gst_element_get_pad (fakesink, "sink"); + gst_pad_add_buffer_probe (sink, G_CALLBACK (sink_pad_probe), &observed); + + observed = GST_CLOCK_TIME_NONE; + + fail_unless (gst_element_set_state (pipeline, GST_STATE_PAUSED) + == GST_STATE_CHANGE_NO_PREROLL, "expected no-preroll from live pipeline"); + + clock = gst_system_clock_obtain (); + fail_unless (clock && GST_IS_CLOCK (clock), "i want a clock dammit"); + gst_pipeline_use_clock (GST_PIPELINE (pipeline), clock); + + lower = gst_clock_get_time (clock); + + gst_element_set_state (pipeline, GST_STATE_PLAYING); + fail_unless (gst_element_get_state (pipeline, NULL, NULL, GST_CLOCK_TIME_NONE) + == GST_STATE_CHANGE_SUCCESS, "failed state change"); + + /* now something a little more than lower was distributed as the base time, + * and the buffer was timestamped at the base time or a little bit afterwards + */ + + base = gst_element_get_base_time (pipeline); + + upper = gst_clock_get_time (clock); + + /* make sure we don't have other threads running, makes errors nicer */ + gst_element_set_state (pipeline, GST_STATE_NULL); + + fail_if (observed == GST_CLOCK_TIME_NONE, "no timestamp recorded"); + + fail_unless (base >= lower, "early base time: %" GST_TIME_FORMAT " < %" + GST_TIME_FORMAT, GST_TIME_ARGS (base), GST_TIME_ARGS (lower)); + fail_unless (upper >= base, "bogus base time: %" GST_TIME_FORMAT " > %" + GST_TIME_FORMAT, GST_TIME_ARGS (base), GST_TIME_ARGS (upper)); + + fail_unless (observed + base >= lower, + "early timestamp: %" GST_TIME_FORMAT " < %" GST_TIME_FORMAT, + GST_TIME_ARGS (observed), GST_TIME_ARGS (lower)); + fail_unless (observed + base <= upper, + "late timestamp: %" GST_TIME_FORMAT " > %" GST_TIME_FORMAT, + GST_TIME_ARGS (observed), GST_TIME_ARGS (upper)); + + gst_object_unref (sink); + gst_object_unref (clock); + gst_object_unref (pipeline); +} + +GST_END_TEST; + Suite * gst_pipeline_suite (void) { @@ -240,6 +327,7 @@ gst_pipeline_suite (void) tcase_add_test (tc_chain, test_async_state_change_fake); tcase_add_test (tc_chain, test_get_bus); tcase_add_test (tc_chain, test_bus); + tcase_add_test (tc_chain, test_base_time); return s; } diff --git a/gst/elements/gstfakesrc.c b/gst/elements/gstfakesrc.c index 0b5d806..350fd0a 100644 --- a/gst/elements/gstfakesrc.c +++ b/gst/elements/gstfakesrc.c @@ -692,8 +692,6 @@ gst_fake_src_create (GstBaseSrc * basesrc, guint64 offset, guint length, buf = gst_fake_src_create_buffer (src); GST_BUFFER_OFFSET (buf) = src->buffer_count++; - time = GST_CLOCK_TIME_NONE; - if (src->datarate > 0) { time = (src->bytes_sent * GST_SECOND) / src->datarate; if (src->sync) { @@ -702,7 +700,20 @@ gst_fake_src_create (GstBaseSrc * basesrc, guint64 offset, guint length, GST_BUFFER_DURATION (buf) = GST_BUFFER_SIZE (buf) * GST_SECOND / src->datarate; + } else if (gst_base_src_is_live (basesrc)) { + GstClock *clock; + + clock = gst_element_get_clock (GST_ELEMENT (src)); + g_return_val_if_fail (clock != NULL, GST_FLOW_ERROR); + + time = gst_clock_get_time (clock); + time -= gst_element_get_base_time (GST_ELEMENT (src)); + + gst_object_unref (clock); + } else { + time = GST_CLOCK_TIME_NONE; } + GST_BUFFER_TIMESTAMP (buf) = time; if (!src->silent) { diff --git a/plugins/elements/gstfakesrc.c b/plugins/elements/gstfakesrc.c index 0b5d806..350fd0a 100644 --- a/plugins/elements/gstfakesrc.c +++ b/plugins/elements/gstfakesrc.c @@ -692,8 +692,6 @@ gst_fake_src_create (GstBaseSrc * basesrc, guint64 offset, guint length, buf = gst_fake_src_create_buffer (src); GST_BUFFER_OFFSET (buf) = src->buffer_count++; - time = GST_CLOCK_TIME_NONE; - if (src->datarate > 0) { time = (src->bytes_sent * GST_SECOND) / src->datarate; if (src->sync) { @@ -702,7 +700,20 @@ gst_fake_src_create (GstBaseSrc * basesrc, guint64 offset, guint length, GST_BUFFER_DURATION (buf) = GST_BUFFER_SIZE (buf) * GST_SECOND / src->datarate; + } else if (gst_base_src_is_live (basesrc)) { + GstClock *clock; + + clock = gst_element_get_clock (GST_ELEMENT (src)); + g_return_val_if_fail (clock != NULL, GST_FLOW_ERROR); + + time = gst_clock_get_time (clock); + time -= gst_element_get_base_time (GST_ELEMENT (src)); + + gst_object_unref (clock); + } else { + time = GST_CLOCK_TIME_NONE; } + GST_BUFFER_TIMESTAMP (buf) = time; if (!src->silent) { diff --git a/tests/check/gst/gstpipeline.c b/tests/check/gst/gstpipeline.c index 514d125..dc54c33 100644 --- a/tests/check/gst/gstpipeline.c +++ b/tests/check/gst/gstpipeline.c @@ -226,6 +226,93 @@ GST_START_TEST (test_bus) GST_END_TEST; +static gboolean +sink_pad_probe (GstPad * pad, GstBuffer * buffer, + GstClockTime * first_timestamp) +{ + gint memory_barrier = 1; + volatile gint foo; + + fail_if (GST_BUFFER_TIMESTAMP (buffer) == GST_CLOCK_TIME_NONE, + "testing if buffer timestamps are right, but got CLOCK_TIME_NONE"); + + if (*first_timestamp == GST_CLOCK_TIME_NONE) + *first_timestamp = GST_BUFFER_TIMESTAMP (buffer); + + /* make sure the other thread sees the update */ + foo = g_atomic_int_get (&memory_barrier); + + return TRUE; +} + +GST_START_TEST (test_base_time) +{ + GstElement *pipeline, *fakesrc, *fakesink; + GstPad *sink; + GstClockTime observed, lower, upper, base; + GstClock *clock; + + pipeline = gst_element_factory_make ("pipeline", "pipeline"); + fakesrc = gst_element_factory_make ("fakesrc", "fakesrc"); + fakesink = gst_element_factory_make ("fakesink", "fakesink"); + + fail_unless (pipeline && fakesrc && fakesink, "couldn't make elements"); + + g_object_set (fakesrc, "is-live", (gboolean) TRUE, NULL); + + gst_bin_add_many (GST_BIN (pipeline), fakesrc, fakesink, NULL); + gst_element_link (fakesrc, fakesink); + + sink = gst_element_get_pad (fakesink, "sink"); + gst_pad_add_buffer_probe (sink, G_CALLBACK (sink_pad_probe), &observed); + + observed = GST_CLOCK_TIME_NONE; + + fail_unless (gst_element_set_state (pipeline, GST_STATE_PAUSED) + == GST_STATE_CHANGE_NO_PREROLL, "expected no-preroll from live pipeline"); + + clock = gst_system_clock_obtain (); + fail_unless (clock && GST_IS_CLOCK (clock), "i want a clock dammit"); + gst_pipeline_use_clock (GST_PIPELINE (pipeline), clock); + + lower = gst_clock_get_time (clock); + + gst_element_set_state (pipeline, GST_STATE_PLAYING); + fail_unless (gst_element_get_state (pipeline, NULL, NULL, GST_CLOCK_TIME_NONE) + == GST_STATE_CHANGE_SUCCESS, "failed state change"); + + /* now something a little more than lower was distributed as the base time, + * and the buffer was timestamped at the base time or a little bit afterwards + */ + + base = gst_element_get_base_time (pipeline); + + upper = gst_clock_get_time (clock); + + /* make sure we don't have other threads running, makes errors nicer */ + gst_element_set_state (pipeline, GST_STATE_NULL); + + fail_if (observed == GST_CLOCK_TIME_NONE, "no timestamp recorded"); + + fail_unless (base >= lower, "early base time: %" GST_TIME_FORMAT " < %" + GST_TIME_FORMAT, GST_TIME_ARGS (base), GST_TIME_ARGS (lower)); + fail_unless (upper >= base, "bogus base time: %" GST_TIME_FORMAT " > %" + GST_TIME_FORMAT, GST_TIME_ARGS (base), GST_TIME_ARGS (upper)); + + fail_unless (observed + base >= lower, + "early timestamp: %" GST_TIME_FORMAT " < %" GST_TIME_FORMAT, + GST_TIME_ARGS (observed), GST_TIME_ARGS (lower)); + fail_unless (observed + base <= upper, + "late timestamp: %" GST_TIME_FORMAT " > %" GST_TIME_FORMAT, + GST_TIME_ARGS (observed), GST_TIME_ARGS (upper)); + + gst_object_unref (sink); + gst_object_unref (clock); + gst_object_unref (pipeline); +} + +GST_END_TEST; + Suite * gst_pipeline_suite (void) { @@ -240,6 +327,7 @@ gst_pipeline_suite (void) tcase_add_test (tc_chain, test_async_state_change_fake); tcase_add_test (tc_chain, test_get_bus); tcase_add_test (tc_chain, test_bus); + tcase_add_test (tc_chain, test_base_time); return s; } -- 2.7.4