diff options
| -rw-r--r-- | ChangeLog | 13 | ||||
| -rw-r--r-- | Makefile.am | 2 | ||||
| -rw-r--r-- | check/elements/level.c | 2 | ||||
| m--------- | common | 0 | ||||
| -rw-r--r-- | gst/level/Makefile.am | 2 | ||||
| -rw-r--r-- | gst/level/gstlevel.c | 138 | ||||
| -rw-r--r-- | gst/level/gstlevel.h | 5 | ||||
| -rw-r--r-- | gst/level/level-example.c | 61 | ||||
| -rw-r--r-- | tests/check/elements/level.c | 2 | 
9 files changed, 147 insertions, 78 deletions
@@ -1,5 +1,18 @@  2005-09-23  Thomas Vander Stichele  <thomas at apestaart dot org> +	* 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  <thomas at apestaart dot org> +  	* gst/auparse/Makefile.am:  	* gst/auparse/gstauparse.c: (gst_auparse_chain):  	  fix up build 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 -Subproject 345fd9851051274dd758a19bbe33dbb561b4d30 +Subproject c7160d5b7c76f00609cf7b6e9b782e99f626686 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 @@   *   * <refsect2>   * <para> - * Level analyses incoming audio buffers and generates an application - * message per given interval of time. + * Level analyses incoming audio buffers and, if the + * <link linkend="GstLevel--message">message property</link> is #TRUE. + * generates an application message named + * <classname>"level"</classname>: + * after each interval of time given by the + * <link linkend="GstLevel--interval">interval property</link>.   * The message's structure contains four fields:   * <itemizedlist>   * <listitem>   *   <para> - *   <link linkend="gdouble">gdouble</link> + *   #GstClockTime   *   <classname>"endtime"</classname>: - *   the end time of the buffer that - *   triggered the message</para> + *   the end time of the buffer that triggered the message + *   </para>   * </listitem>   * <listitem>   *   <para> - *   <link linkend="gdouble">gdouble</link> - *   <classname>"endtime"</classname>: - *   the end time of the buffer that - *   triggered the message</para> + *   #GstValueList of #gdouble + *   <classname>"peak"</classname>: + *   the peak power level in dB for each channel + *   </para> + * </listitem> + * <listitem> + *   <para> + *   #GstValueList of #gdouble + *   <classname>"decay"</classname>: + *   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 <link linkend="GstLevel--peak-ttl">the time to live</link>. + *   When the decaying peak level drops, it does so at the decay rate + *   as specified by the + *   <link linkend="GstLevel--peak-falloff">the peak fallof rate</link>. + *   </para> + * </listitem> + * <listitem> + *   <para> + *   #GstValueList of #gdouble + *   <classname>"rms"</classname>: + *   the Root Mean Square (or average power) level in dB for each channel + *   </para>   * </listitem>    * </itemizedlist>   * </para> @@ -55,6 +79,7 @@  #include "config.h"  #endif  #include <gst/gst.h> +#include <gst/audio/audio.h>  #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) {  | 
