From 6115f0b56c4db7a85a541dac13f9a98b1affab71 Mon Sep 17 00:00:00 2001 From: Thomas Vander Stichele Date: Fri, 23 Sep 2005 18:15:51 +0000 Subject: convert to using GstClockTime for all time values, finally. Original commit message from CVS: convert to using GstClockTime for all time values, finally. --- ChangeLog | 13 ++++ Makefile.am | 2 +- check/elements/level.c | 2 + common | 2 +- gst/level/Makefile.am | 2 +- gst/level/gstlevel.c | 138 +++++++++++++++++++++++++++---------------- gst/level/gstlevel.h | 5 +- gst/level/level-example.c | 61 +++++++++++-------- tests/check/elements/level.c | 2 + 9 files changed, 148 insertions(+), 79 deletions(-) diff --git a/ChangeLog b/ChangeLog index a7df4f43..74ef22b8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2005-09-23 Thomas Vander Stichele + + * Makefile.am: + * check/elements/level.c: (GST_START_TEST): + * gst/level/Makefile.am: + * gst/level/gstlevel.c: (gst_level_class_init), (gst_level_init), + (gst_level_set_property), (gst_level_get_property), + (gst_level_set_caps), (gst_level_message_new), + (gst_level_transform_ip): + * gst/level/gstlevel.h: + * gst/level/level-example.c: (message_handler), (main): + convert to using GstClockTime for all time values, finally. + 2005-09-23 Thomas Vander Stichele * gst/auparse/Makefile.am: diff --git a/Makefile.am b/Makefile.am index cfe228de..3ff27cbe 100644 --- a/Makefile.am +++ b/Makefile.am @@ -35,4 +35,4 @@ include $(top_srcdir)/common/release.mak # include $(top_srcdir)/common/po.mak check-valgrind: - @true + cd check && make check-valgrind diff --git a/check/elements/level.c b/check/elements/level.c index 79fa8538..88f68ffc 100644 --- a/check/elements/level.c +++ b/check/elements/level.c @@ -97,6 +97,7 @@ GST_START_TEST (test_int16) int i, j; gint16 *data; const GValue *list, *value; + GstClockTime endtime; gdouble dB; level = setup_level (); @@ -137,6 +138,7 @@ GST_START_TEST (test_int16) fail_if (structure == NULL); fail_unless_equals_string ((char *) gst_structure_get_name (structure), "level"); + fail_unless (gst_structure_get_clock_time (structure, "endtime", &endtime)); /* block wave of half amplitude has -5.94 dB for rms, peak and decay */ for (i = 0; i < 2; ++i) { diff --git a/common b/common index 345fd985..c7160d5b 160000 --- a/common +++ b/common @@ -1 +1 @@ -Subproject commit 345fd9851051274dd758a19bbe33dbb561b4d303 +Subproject commit c7160d5b7c76f00609cf7b6e9b782e99f626686c diff --git a/gst/level/Makefile.am b/gst/level/Makefile.am index 6a48efab..ab5b80b8 100644 --- a/gst/level/Makefile.am +++ b/gst/level/Makefile.am @@ -1,7 +1,7 @@ plugin_LTLIBRARIES = libgstlevel.la libgstlevel_la_SOURCES = gstlevel.c -libgstlevel_la_CFLAGS = $(GST_CFLAGS) +libgstlevel_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS) libgstlevel_la_LIBADD = $(GST_BASE_LIBS) libgstlevel_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) diff --git a/gst/level/gstlevel.c b/gst/level/gstlevel.c index 4ce1a8be..f7d22edb 100644 --- a/gst/level/gstlevel.c +++ b/gst/level/gstlevel.c @@ -24,23 +24,47 @@ * * * - * Level analyses incoming audio buffers and generates an application - * message per given interval of time. + * Level analyses incoming audio buffers and, if the + * message property is #TRUE. + * generates an application message named + * "level": + * after each interval of time given by the + * interval property. * The message's structure contains four fields: * * * - * gdouble + * #GstClockTime * "endtime": - * the end time of the buffer that - * triggered the message + * the end time of the buffer that triggered the message + * * * * - * gdouble - * "endtime": - * the end time of the buffer that - * triggered the message + * #GstValueList of #gdouble + * "peak": + * the peak power level in dB for each channel + * + * + * + * + * #GstValueList of #gdouble + * "decay": + * the decaying peak power level in dB for each channel + * the decaying peak level follows the peak level, but starts dropping + * if no new peak is reached after the time given by + * the the time to live. + * When the decaying peak level drops, it does so at the decay rate + * as specified by the + * the peak fallof rate. + * + * + * + * + * #GstValueList of #gdouble + * "rms": + * the Root Mean Square (or average power) level in dB for each channel + * * * * @@ -55,6 +79,7 @@ #include "config.h" #endif #include +#include #include "gstlevel.h" #include "math.h" @@ -143,15 +168,16 @@ gst_level_class_init (GstLevelClass * klass) g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SIGNAL_LEVEL, g_param_spec_boolean ("message", "mesage", - "Post a level message for each interval", TRUE, G_PARAM_READWRITE)); + "Post a level message for each passed interval", + TRUE, G_PARAM_READWRITE)); g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SIGNAL_INTERVAL, - g_param_spec_double ("interval", "Interval", - "Interval between posts (in seconds)", - 0.01, 100.0, 0.1, G_PARAM_READWRITE)); + g_param_spec_uint64 ("interval", "Interval", + "Interval of time between message posts (in nanoseconds)", + 1, G_MAXUINT64, GST_SECOND / 10, G_PARAM_READWRITE)); g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_PEAK_TTL, - g_param_spec_double ("peak_ttl", "Peak TTL", - "Time To Live of decay peak before it falls back", - 0, 100.0, 0.3, G_PARAM_READWRITE)); + g_param_spec_uint64 ("peak_ttl", "Peak TTL", + "Time To Live of decay peak before it falls back (in nanoseconds)", + 0, G_MAXUINT64, GST_SECOND / 10 * 3, G_PARAM_READWRITE)); g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_PEAK_FALLOFF, g_param_spec_double ("peak_falloff", "Peak Falloff", "Decay rate of decay peak after TTL (in dB/sec)", @@ -175,8 +201,8 @@ gst_level_init (GstLevel * filter, GstLevelClass * g_class) filter->width = 0; filter->channels = 0; - filter->interval = 0.1; - filter->decay_peak_ttl = 0.4; + filter->interval = GST_SECOND / 10; + filter->decay_peak_ttl = GST_SECOND / 10 * 3; filter->decay_peak_falloff = 10.0; /* dB falloff (/sec) */ filter->message = TRUE; @@ -193,10 +219,10 @@ gst_level_set_property (GObject * object, guint prop_id, filter->message = g_value_get_boolean (value); break; case PROP_SIGNAL_INTERVAL: - filter->interval = g_value_get_double (value); + filter->interval = g_value_get_uint64 (value); break; case PROP_PEAK_TTL: - filter->decay_peak_ttl = g_value_get_double (value); + filter->decay_peak_ttl = g_value_get_uint64 (value); break; case PROP_PEAK_FALLOFF: filter->decay_peak_falloff = g_value_get_double (value); @@ -217,10 +243,10 @@ gst_level_get_property (GObject * object, guint prop_id, g_value_set_boolean (value, filter->message); break; case PROP_SIGNAL_INTERVAL: - g_value_set_double (value, filter->interval); + g_value_set_uint64 (value, filter->interval); break; case PROP_PEAK_TTL: - g_value_set_double (value, filter->decay_peak_ttl); + g_value_set_uint64 (value, filter->decay_peak_ttl); break; case PROP_PEAK_FALLOFF: g_value_set_double (value, filter->decay_peak_falloff); @@ -251,7 +277,7 @@ gst_level_set_caps (GstBaseTransform * trans, GstCaps * in, GstCaps * out) filter = GST_LEVEL (trans); - filter->num_samples = 0; + filter->num_frames = 0; structure = gst_caps_get_structure (in, 0); filter->rate = structure_get_int (structure, "rate"); @@ -269,13 +295,14 @@ gst_level_set_caps (GstBaseTransform * trans, GstCaps * in, GstCaps * out) filter->peak = g_new (double, filter->channels); filter->last_peak = g_new (double, filter->channels); filter->decay_peak = g_new (double, filter->channels); - filter->decay_peak_age = g_new (double, filter->channels); + + filter->decay_peak_age = g_new (GstClockTime, filter->channels); filter->RMS_dB = g_new (double, filter->channels); for (i = 0; i < filter->channels; ++i) { filter->CS[i] = filter->peak[i] = filter->last_peak[i] = - filter->decay_peak[i] = filter->decay_peak_age[i] = - filter->RMS_dB[i] = 0.0; + filter->decay_peak[i] = filter->RMS_dB[i] = 0.0; + filter->decay_peak_age[i] = 0LL; } return TRUE; @@ -326,14 +353,15 @@ DEFINE_LEVEL_CALCULATOR (gint16); DEFINE_LEVEL_CALCULATOR (gint8); static GstMessage * -gst_level_message_new (GstLevel * l, gdouble endtime) +gst_level_message_new (GstLevel * l, GstClockTime endtime) { GstStructure *s; GValue v = { 0, }; g_value_init (&v, GST_TYPE_LIST); - s = gst_structure_new ("level", "endtime", G_TYPE_DOUBLE, endtime, NULL); + s = gst_structure_new ("level", "endtime", GST_TYPE_CLOCK_TIME, + endtime, NULL); /* will copy-by-value */ gst_structure_set_value (s, "rms", &v); gst_structure_set_value (s, "peak", &v); @@ -373,7 +401,9 @@ gst_level_transform_ip (GstBaseTransform * trans, GstBuffer * in) GstLevel *filter; gpointer in_data; double CS = 0.0; - gint num_int_samples = 0; /* number of samples for all channels combined */ + gint num_frames = 0; + gint num_int_samples = 0; /* number of interleaved samples + * ie. total count for all channels combined */ gint i; filter = GST_LEVEL (trans); @@ -387,6 +417,8 @@ gst_level_transform_ip (GstBaseTransform * trans, GstBuffer * in) g_return_val_if_fail (num_int_samples % filter->channels == 0, GST_FLOW_ERROR); + num_frames = num_int_samples / filter->channels; + for (i = 0; i < filter->channels; ++i) { CS = 0.0; switch (filter->width) { @@ -405,12 +437,14 @@ gst_level_transform_ip (GstBaseTransform * trans, GstBuffer * in) filter->CS[i] += CS; } - filter->num_samples += num_int_samples / filter->channels; + filter->num_frames += num_frames; for (i = 0; i < filter->channels; ++i) { - filter->decay_peak_age[i] += num_int_samples / filter->channels; - GST_LOG_OBJECT (filter, "filter peak info [%d]: peak %f, age %f\n", i, - filter->last_peak[i], filter->decay_peak_age[i]); + filter->decay_peak_age[i] += + GST_FRAMES_TO_CLOCK_TIME (num_frames, filter->rate); + GST_LOG_OBJECT (filter, "filter peak info [%d]: peak %f, age %" + GST_TIME_FORMAT, i, + filter->last_peak[i], GST_TIME_ARGS (filter->decay_peak_age[i])); /* update running peak */ if (filter->peak[i] > filter->last_peak[i]) @@ -418,28 +452,29 @@ gst_level_transform_ip (GstBaseTransform * trans, GstBuffer * in) /* update decay peak */ if (filter->peak[i] >= filter->decay_peak[i]) { - GST_LOG_OBJECT (filter, "new peak, %f\n", filter->peak[i]); + GST_LOG_OBJECT (filter, "new peak, %f", filter->peak[i]); filter->decay_peak[i] = filter->peak[i]; - filter->decay_peak_age[i] = 0; + filter->decay_peak_age[i] = 0LL; } else { /* make decay peak fall off if too old */ - if (filter->decay_peak_age[i] > filter->rate * filter->decay_peak_ttl) { + if (filter->decay_peak_age[i] > filter->decay_peak_ttl) { double falloff_dB; double falloff; double length; /* length of buffer in seconds */ - length = (double) num_int_samples / (filter->channels * filter->rate); + length = (double) num_frames / filter->rate; falloff_dB = filter->decay_peak_falloff * length; falloff = pow (10, falloff_dB / -20.0); GST_LOG_OBJECT (filter, - "falloff: length %f, dB falloff %f, falloff factor %e\n", + "falloff: length %f, dB falloff %f, falloff factor %e", length, falloff_dB, falloff); filter->decay_peak[i] *= falloff; GST_LOG_OBJECT (filter, - "peak is %f samples old, decayed with factor %e to %f\n", - filter->decay_peak_age[i], falloff, filter->decay_peak[i]); + "peak is %" GST_TIME_FORMAT " old, decayed with factor %e to %f", + GST_TIME_ARGS (filter->decay_peak_age[i]), falloff, + filter->decay_peak[i]); } else { GST_LOG_OBJECT (filter, "peak not old enough, not decaying"); } @@ -448,23 +483,25 @@ gst_level_transform_ip (GstBaseTransform * trans, GstBuffer * in) /* do we need to emit ? */ - if (filter->num_samples >= (gint) (filter->interval * filter->rate)) { + if (filter->num_frames >= + (gint) ((gdouble) filter->interval / GST_SECOND * filter->rate)) { if (filter->message) { GstMessage *m; - double endtime, RMS; + GstClockTime endtime; + double RMS; double RMSdB, lastdB, decaydB; /* FIXME: convert to a GstClockTime instead */ - endtime = (double) GST_BUFFER_TIMESTAMP (in) / GST_SECOND - + (double) num_int_samples / (filter->rate * filter->channels); + endtime = GST_BUFFER_TIMESTAMP (in) + + GST_FRAMES_TO_CLOCK_TIME (num_frames, filter->rate); m = gst_level_message_new (filter, endtime); for (i = 0; i < filter->channels; ++i) { - RMS = sqrt (filter->CS[i] / filter->num_samples); + RMS = sqrt (filter->CS[i] / filter->num_frames); GST_LOG_OBJECT (filter, - "CS: %f, num_samples %d, channel %d, RMS %f", - filter->CS[i], filter->num_samples, i, RMS); + "CS: %f, num_frames %d, channel %d, RMS %f", + filter->CS[i], filter->num_frames, i, RMS); /* RMS values are calculated in amplitude, so 20 * log 10 */ RMSdB = 20 * log10 (RMS); /* peak values are square sums, ie. power, so 10 * log 10 */ @@ -472,8 +509,9 @@ gst_level_transform_ip (GstBaseTransform * trans, GstBuffer * in) decaydB = 10 * log10 (filter->decay_peak[i]); GST_LOG_OBJECT (filter, - "time %f, channel %d, RMS %f dB, peak %f dB, decay %f dB", - endtime, i, RMSdB, lastdB, decaydB); + "time %" GST_TIME_FORMAT + ", channel %d, RMS %f dB, peak %f dB, decay %f dB", + GST_TIME_ARGS (endtime), i, RMSdB, lastdB, decaydB); gst_level_message_append_channel (m, RMSdB, lastdB, decaydB); @@ -484,7 +522,7 @@ gst_level_transform_ip (GstBaseTransform * trans, GstBuffer * in) gst_element_post_message (GST_ELEMENT (filter), m); } - filter->num_samples = 0; + filter->num_frames = 0; } return GST_FLOW_OK; diff --git a/gst/level/gstlevel.h b/gst/level/gstlevel.h index ecd10a87..98d7b149 100644 --- a/gst/level/gstlevel.h +++ b/gst/level/gstlevel.h @@ -59,7 +59,8 @@ struct _GstLevel { gdouble decay_peak_ttl; /* time to live for peak in seconds */ gdouble decay_peak_falloff; /* falloff in dB/sec */ - gint num_samples; /* one-channel sample count since last emit */ + gint num_frames; /* frame count (1 sample per channel) + * since last emit */ /* per-channel arrays for intermediate values */ gdouble *CS; /* normalized Cumulative Square */ @@ -68,7 +69,7 @@ struct _GstLevel { gdouble *decay_peak; /* running decaying normalized Peak */ gdouble *MS; /* normalized Mean Square of buffer */ gdouble *RMS_dB; /* RMS in dB to emit */ - gdouble *decay_peak_age; /* age of last peak in one-channel samples */ + GstClockTime *decay_peak_age; /* age of last peak */ }; struct _GstLevelClass { diff --git a/gst/level/level-example.c b/gst/level/level-example.c index 6aac1a5d..3f41f7f1 100644 --- a/gst/level/level-example.c +++ b/gst/level/level-example.c @@ -13,35 +13,41 @@ message_handler (GstBus * bus, GstMessage * message, gpointer data) if (strcmp (name, "level") == 0) { gint channels; - gdouble endtime, rms_dB, peak_dB, decay_dB; + GstClockTime endtime; + gdouble rms_dB, peak_dB, decay_dB; gdouble rms; const GValue *list; const GValue *value; - if (!gst_structure_get_double (s, "endtime", &endtime)) + gint i; + + if (!gst_structure_get_clock_time (s, "endtime", &endtime)) g_warning ("Could not parse endtime"); - list = gst_structure_get_value (s, "rms"); /* we can get the number of channels as the length of any of the value * lists */ + list = gst_structure_get_value (s, "rms"); channels = gst_value_list_get_size (list); - /* we will only get values for the first channel, since we know sinesrc - * is mono */ - value = gst_value_list_get_value (list, 0); - rms_dB = g_value_get_double (value); - list = gst_structure_get_value (s, "peak"); - value = gst_value_list_get_value (list, 0); - peak_dB = g_value_get_double (value); - list = gst_structure_get_value (s, "decay"); - value = gst_value_list_get_value (list, 0); - decay_dB = g_value_get_double (value); - g_print ("endtime: %f, channels: %d\n", endtime, channels); - g_print ("RMS: %f dB, peak: %f dB, decay: %f dB\n", - rms_dB, peak_dB, decay_dB); - - /* converting from dB to normal gives us a value between 0.0 and 1.0 */ - rms = pow (10, rms_dB / 20); - g_print ("normalized rms value: %f\n", rms); + g_print ("endtime: %" GST_TIME_FORMAT ", channels: %d\n", + GST_TIME_ARGS (endtime), channels); + for (i = 0; i < channels; ++i) { + g_print ("channel %d\n", i); + list = gst_structure_get_value (s, "rms"); + value = gst_value_list_get_value (list, i); + rms_dB = g_value_get_double (value); + list = gst_structure_get_value (s, "peak"); + value = gst_value_list_get_value (list, i); + peak_dB = g_value_get_double (value); + list = gst_structure_get_value (s, "decay"); + value = gst_value_list_get_value (list, i); + decay_dB = g_value_get_double (value); + g_print (" RMS: %f dB, peak: %f dB, decay: %f dB\n", + rms_dB, peak_dB, decay_dB); + + /* converting from dB to normal gives us a value between 0.0 and 1.0 */ + rms = pow (10, rms_dB / 20); + g_print (" normalized rms value: %f\n", rms); + } } } /* we handled the message we want, and ignored the ones we didn't want. @@ -52,26 +58,33 @@ message_handler (GstBus * bus, GstMessage * message, gpointer data) int main (int argc, char *argv[]) { - GstElement *sinesrc, *level, *fakesink; + GstElement *sinesrc, *audioconvert, *level, *fakesink; GstElement *pipeline; + GstCaps *caps; GstBus *bus; gint watch_id; GMainLoop *loop; gst_init (&argc, &argv); + caps = gst_caps_from_string ("audio/x-raw-int,channels=2"); + pipeline = gst_pipeline_new (NULL); g_assert (pipeline); sinesrc = gst_element_factory_make ("sinesrc", NULL); g_assert (sinesrc); + audioconvert = gst_element_factory_make ("audioconvert", NULL); + g_assert (audioconvert); level = gst_element_factory_make ("level", NULL); g_assert (level); fakesink = gst_element_factory_make ("fakesink", NULL); g_assert (fakesink); - gst_bin_add_many (GST_BIN (pipeline), sinesrc, level, fakesink, NULL); - gst_element_link (sinesrc, level); - gst_element_link (level, fakesink); + gst_bin_add_many (GST_BIN (pipeline), sinesrc, audioconvert, level, + fakesink, NULL); + g_assert (gst_element_link (sinesrc, audioconvert)); + g_assert (gst_element_link_filtered (audioconvert, level, caps)); + g_assert (gst_element_link (level, fakesink)); /* make sure we'll get messages */ g_object_set (G_OBJECT (level), "message", TRUE, NULL); diff --git a/tests/check/elements/level.c b/tests/check/elements/level.c index 79fa8538..88f68ffc 100644 --- a/tests/check/elements/level.c +++ b/tests/check/elements/level.c @@ -97,6 +97,7 @@ GST_START_TEST (test_int16) int i, j; gint16 *data; const GValue *list, *value; + GstClockTime endtime; gdouble dB; level = setup_level (); @@ -137,6 +138,7 @@ GST_START_TEST (test_int16) fail_if (structure == NULL); fail_unless_equals_string ((char *) gst_structure_get_name (structure), "level"); + fail_unless (gst_structure_get_clock_time (structure, "endtime", &endtime)); /* block wave of half amplitude has -5.94 dB for rms, peak and decay */ for (i = 0; i < 2; ++i) { -- cgit