diff options
| author | Andy Wingo <wingo@pobox.com> | 2005-07-04 14:02:46 +0000 | 
|---|---|---|
| committer | Andy Wingo <wingo@pobox.com> | 2005-07-04 14:02:46 +0000 | 
| commit | 77a7c4c8fbc7a9fb59039c0f9469923dd651c009 (patch) | |
| tree | 243e22219ac7b5c902681a70a40f5d7d9704b781 | |
| parent | d0516df78a67006fca5cd20295e6237d81470196 (diff) | |
examples/level/: Examples moved out of the source dir. Not updated tho.
Original commit message from CVS:
2005-07-04  Andy Wingo  <wingo@pobox.com>
* examples/level/:
* examples/level/Makefile.am:
* examples/level/README:
* examples/level/demo.c:
* examples/level/plot.c: Examples moved out of the source dir. Not
updated tho.
* configure.ac: Add level to the build.
* gst/level/Makefile.am:
* gst/level/gstlevel.h:
* gst/level/gstlevel.c: Cleaned up, ported to 0.9.
| -rw-r--r-- | ChangeLog | 13 | ||||
| -rw-r--r-- | configure.ac | 7 | ||||
| -rw-r--r-- | examples/Makefile.am | 4 | ||||
| -rw-r--r-- | examples/level/Makefile.am | 11 | ||||
| -rw-r--r-- | examples/level/README (renamed from gst/level/README) | 0 | ||||
| -rw-r--r-- | examples/level/demo.c (renamed from gst/level/demo.c) | 0 | ||||
| -rw-r--r-- | examples/level/plot.c (renamed from gst/level/plot.c) | 0 | ||||
| -rw-r--r-- | gst/level/Makefile.am | 30 | ||||
| -rw-r--r-- | gst/level/filter.func | 41 | ||||
| -rw-r--r-- | gst/level/gstlevel-marshal.list | 1 | ||||
| -rw-r--r-- | gst/level/gstlevel.c | 514 | ||||
| -rw-r--r-- | gst/level/gstlevel.h | 23 | ||||
| -rw-r--r-- | tests/old/examples/Makefile.am | 4 | ||||
| -rw-r--r-- | tests/old/examples/level/Makefile.am | 11 | ||||
| -rw-r--r-- | tests/old/examples/level/README | 39 | ||||
| -rw-r--r-- | tests/old/examples/level/demo.c | 155 | ||||
| -rw-r--r-- | tests/old/examples/level/plot.c | 123 | 
17 files changed, 638 insertions, 338 deletions
| @@ -5,6 +5,19 @@  2005-07-04  Andy Wingo  <wingo@pobox.com> +	* examples/level/: +	* examples/level/Makefile.am: +	* examples/level/README: +	* examples/level/demo.c: +	* examples/level/plot.c: Examples moved out of the source dir. Not +	updated tho. + +	* configure.ac: Add level to the build. + +	* gst/level/Makefile.am: +	* gst/level/gstlevel.h: +	* gst/level/gstlevel.c: Cleaned up, ported to 0.9. +  	* ext/aalib/gstaasink.c (gst_aasink_fixate): Update for newer  	fixate prototype. diff --git a/configure.ac b/configure.ac index c58f654a..6acad339 100644 --- a/configure.ac +++ b/configure.ac @@ -297,15 +297,17 @@ dnl these are all the gst plug-ins, compilable without additional libs  GST_PLUGINS_ALL="\  		alpha \  		avi \ -		videofilter \  		effectv \  		goom \  		law \ +		level \  		realmedia \  		rtp	\  		rtsp	\  		smpte	\ -		udp" +		udp     \ +		videofilter \ +                "  dnl see if we can build C++ plug-ins  if test "x$HAVE_CXX" = "xyes"; then @@ -489,6 +491,7 @@ gst/avi/Makefile  gst/effectv/Makefile  gst/goom/Makefile  gst/law/Makefile +gst/level/Makefile  gst/realmedia/Makefile  gst/rtp/Makefile  gst/rtsp/Makefile diff --git a/examples/Makefile.am b/examples/Makefile.am index 0c8190c7..11f92220 100644 --- a/examples/Makefile.am +++ b/examples/Makefile.am @@ -5,7 +5,7 @@ FT2_SUBDIRS=  endif  if HAVE_GTK -GTK_SUBDIRS=dynparams $(FT2_SUBDIRS) +GTK_SUBDIRS=dynparams level $(FT2_SUBDIRS)  else  GTK_SUBDIRS=  endif @@ -17,4 +17,4 @@ GCONF_SUBDIRS=  endif  SUBDIRS=$(GTK_SUBDIRS) $(GCONF_SUBDIRS) switch -DIST_SUBDIRS=capsfilter dynparams seeking indexing gstplay switch +DIST_SUBDIRS=capsfilter dynparams seeking indexing gstplay switch level diff --git a/examples/level/Makefile.am b/examples/level/Makefile.am new file mode 100644 index 00000000..bf76136f --- /dev/null +++ b/examples/level/Makefile.am @@ -0,0 +1,11 @@ +noinst_PROGRAMS = demo plot + +demo_SOURCES = demo.c +demo_CFLAGS = $(GTK_CFLAGS) $(GST_CFLAGS) +demo_LDFLAGS = $(GTK_LIBS) $(GST_LIBS) + +plot_SOURCES = plot.c +plot_CFLAGS = $(GTK_CFLAGS) $(GST_CFLAGS) +plot_LDFLAGS = $(GTK_LIBS) $(GST_LIBS) + +EXTRA_DIST = README diff --git a/gst/level/README b/examples/level/README index 0ae84188..0ae84188 100644 --- a/gst/level/README +++ b/examples/level/README diff --git a/gst/level/demo.c b/examples/level/demo.c index 502f50f7..502f50f7 100644 --- a/gst/level/demo.c +++ b/examples/level/demo.c diff --git a/gst/level/plot.c b/examples/level/plot.c index 6df01065..6df01065 100644 --- a/gst/level/plot.c +++ b/examples/level/plot.c diff --git a/gst/level/Makefile.am b/gst/level/Makefile.am index 43ef181c..5bed77d8 100644 --- a/gst/level/Makefile.am +++ b/gst/level/Makefile.am @@ -1,34 +1,8 @@  plugin_LTLIBRARIES = libgstlevel.la -# variables used for enum/marshal generation -glib_enum_define = GST_LEVEL -glib_enum_prefix = gst_level - -include $(top_srcdir)/common/glib-gen.mak -                                                                                 -built_sources = gstlevel-marshal.c -built_headers = gstlevel-marshal.h -                                                                                 -BUILT_SOURCES = $(built_sources) $(built_headers) -  libgstlevel_la_SOURCES = gstlevel.c -nodist_libgstlevel_la_SOURCES = $(built_sources)  libgstlevel_la_CFLAGS = $(GST_CFLAGS) -libgstlevel_la_LIBADD = +libgstlevel_la_LIBADD = $(GST_BASE_LIBS)  libgstlevel_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) -noinst_HEADERS = gstlevel.h filter.func - -if HAVE_GTK -noinst_PROGRAMS = demo plot -demo_SOURCES = demo.c -demo_CFLAGS = $(GTK_CFLAGS) $(GST_CFLAGS) -demo_LDFLAGS = $(GTK_LIBS) $(GST_LIBS) -plot_SOURCES = plot.c -plot_CFLAGS = $(GTK_CFLAGS) $(GST_CFLAGS) -plot_LDFLAGS = $(GTK_LIBS) $(GST_LIBS) -endif - -CLEANFILES = $(BUILT_SOURCES) -                                                                         -EXTRA_DIST = README gstlevel-marshal.list +noinst_HEADERS = gstlevel.h diff --git a/gst/level/filter.func b/gst/level/filter.func deleted file mode 100644 index fd82c038..00000000 --- a/gst/level/filter.func +++ /dev/null @@ -1,41 +0,0 @@ -/* -static void inline -gst_level_fast_16bit_chain (gint16 * in, guint num, gint channels, -    gint resolution, double *CS, double *peak) -*/ -/* process one (interleaved) channel of incoming samples - * calculate square sum of samples - * normalize and return normalized Cumulative Square - * caller must assure num is a multiple of channels - * this filter only accepts signed audio data, so mid level is always 0 - */ -{ -  register int j; -  double squaresum = 0.0;	/* square sum of the integer samples */ -  register double square = 0.0;		/* Square */ -  register double PSS = 0.0;		/* Peak Square Sample */ -  gdouble normalizer; - -  *CS = 0.0;      /* Cumulative Square for this block */ - -  normalizer = (double) (1 << resolution); - -  /* -   * process data here   -   * input sample data enters in *in_data as 8 or 16 bit data -   * samples for left and right channel are interleaved -   * returns the Mean Square of the samples as a double between 0 and 1 -   */ - -  for (j = 0; j < num; j += channels) -  { -    //g_print ("ch %d -> smp %d\n", j, in[j]); -    square = (double) (in[j] * in[j]); -    if (square > PSS) PSS = square; -    squaresum += square; -  } -  *peak = PSS / ((double) normalizer * (double) normalizer); -   -  /* return normalized cumulative square */ -  *CS = squaresum / ((double) normalizer * (double) normalizer); -} diff --git a/gst/level/gstlevel-marshal.list b/gst/level/gstlevel-marshal.list deleted file mode 100644 index 9a2455bb..00000000 --- a/gst/level/gstlevel-marshal.list +++ /dev/null @@ -1 +0,0 @@ -VOID:DOUBLE,INT,DOUBLE,DOUBLE,DOUBLE diff --git a/gst/level/gstlevel.c b/gst/level/gstlevel.c index e1a3bb50..12cc8208 100644 --- a/gst/level/gstlevel.c +++ b/gst/level/gstlevel.c @@ -25,14 +25,12 @@  #include "config.h"  #endif  #include <gst/gst.h> -#include <gst/audio/audio.h>  #include "gstlevel.h"  #include "math.h"  GST_DEBUG_CATEGORY (level_debug);  #define GST_CAT_DEFAULT level_debug -/* elementfactory information */  static GstElementDetails level_details = {    "Level",    "Filter/Analyzer/Audio", @@ -40,8 +38,6 @@ static GstElementDetails level_details = {    "Thomas <thomas@apestaart.org>"  }; -/* pad templates */ -  static GstStaticPadTemplate sink_template_factory =  GST_STATIC_PAD_TEMPLATE ("sink",      GST_PAD_SINK, @@ -66,87 +62,170 @@ GST_STATIC_PAD_TEMPLATE ("src",          "depth = (int) { 8, 16 }, " "signed = (boolean) true")      ); -/* Filter signals and args */ -enum -{ -  /* FILL ME */ -  SIGNAL_LEVEL, -  LAST_SIGNAL -};  enum  { -  ARG_0, -  ARG_SIGNAL_LEVEL, -  ARG_SIGNAL_INTERVAL, -  ARG_PEAK_TTL, -  ARG_PEAK_FALLOFF +  PROP_0, +  PROP_SIGNAL_LEVEL, +  PROP_SIGNAL_INTERVAL, +  PROP_PEAK_TTL, +  PROP_PEAK_FALLOFF  }; -static void gst_level_class_init (GstLevelClass * klass); -static void gst_level_base_init (GstLevelClass * klass); -static void gst_level_init (GstLevel * filter); + +GST_BOILERPLATE (GstLevel, gst_level, GstBaseTransform, +    GST_TYPE_BASE_TRANSFORM); +  static void gst_level_set_property (GObject * object, guint prop_id,      const GValue * value, GParamSpec * pspec);  static void gst_level_get_property (GObject * object, guint prop_id,      GValue * value, GParamSpec * pspec); -static void gst_level_chain (GstPad * pad, GstData * _data); +static gboolean gst_level_set_caps (GstBaseTransform * trans, GstCaps * in, +    GstCaps * out); +static GstFlowReturn gst_level_transform (GstBaseTransform * trans, +    GstBuffer * in, GstBuffer ** out); + + +static void +gst_level_base_init (gpointer g_class) +{ +  GstElementClass *element_class = g_class; + +  gst_element_class_add_pad_template (element_class, +      gst_static_pad_template_get (&sink_template_factory)); +  gst_element_class_add_pad_template (element_class, +      gst_static_pad_template_get (&src_template_factory)); +  gst_element_class_set_details (element_class, &level_details); +} + +static void +gst_level_class_init (GstLevelClass * klass) +{ +  GObjectClass *gobject_class; +  GstBaseTransformClass *trans_class; + +  gobject_class = (GObjectClass *) klass; +  trans_class = (GstBaseTransformClass *) klass; + +  gobject_class->set_property = gst_level_set_property; +  gobject_class->get_property = gst_level_get_property; + +  g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SIGNAL_LEVEL, +      g_param_spec_boolean ("signal", "Signal", +          "Emit level signals for each 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 emissions (in seconds)", +          0.01, 100.0, 0.1, 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_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)", +          0.0, G_MAXDOUBLE, 10.0, G_PARAM_READWRITE)); + +  GST_DEBUG_CATEGORY_INIT (level_debug, "level", 0, "Level calculation"); + +  trans_class->set_caps = gst_level_set_caps; +  trans_class->transform = gst_level_transform; +} + +static void +gst_level_init (GstLevel * filter) +{ +  filter->CS = NULL; +  filter->peak = NULL; +  filter->MS = NULL; +  filter->RMS_dB = NULL; + +  filter->rate = 0; +  filter->width = 0; +  filter->channels = 0; + +  filter->interval = 0.1; +  filter->decay_peak_ttl = 0.4; +  filter->decay_peak_falloff = 10.0;    /* dB falloff (/sec) */ +} + +static void +gst_level_set_property (GObject * object, guint prop_id, +    const GValue * value, GParamSpec * pspec) +{ +  GstLevel *filter = GST_LEVEL (object); -static GstElementClass *parent_class = NULL; -static guint gst_filter_signals[LAST_SIGNAL] = { 0 }; +  switch (prop_id) { +    case PROP_SIGNAL_LEVEL: +      filter->signal = g_value_get_boolean (value); +      break; +    case PROP_SIGNAL_INTERVAL: +      filter->interval = g_value_get_double (value); +      break; +    case PROP_PEAK_TTL: +      filter->decay_peak_ttl = g_value_get_double (value); +      break; +    case PROP_PEAK_FALLOFF: +      filter->decay_peak_falloff = g_value_get_double (value); +      break; +    default: +      break; +  } +} -GType -gst_level_get_type (void) +static void +gst_level_get_property (GObject * object, guint prop_id, +    GValue * value, GParamSpec * pspec)  { -  static GType level_type = 0; - -  if (!level_type) { -    static const GTypeInfo level_info = { -      sizeof (GstLevelClass), -      (GBaseInitFunc) gst_level_base_init, NULL, -      (GClassInitFunc) gst_level_class_init, NULL, NULL, -      sizeof (GstLevel), 0, -      (GInstanceInitFunc) gst_level_init -    }; - -    level_type = g_type_register_static (GST_TYPE_ELEMENT, "GstLevel", -        &level_info, 0); +  GstLevel *filter = GST_LEVEL (object); + +  switch (prop_id) { +    case PROP_SIGNAL_LEVEL: +      g_value_set_boolean (value, filter->signal); +      break; +    case PROP_SIGNAL_INTERVAL: +      g_value_set_double (value, filter->interval); +      break; +    case PROP_PEAK_TTL: +      g_value_set_double (value, filter->decay_peak_ttl); +      break; +    case PROP_PEAK_FALLOFF: +      g_value_set_double (value, filter->decay_peak_falloff); +      break; +    default: +      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); +      break;    } -  return level_type;  } -static GstPadLinkReturn -gst_level_link (GstPad * pad, const GstCaps * caps) +static gint +structure_get_int (GstStructure * structure, const gchar * field) +{ +  gint ret; + +  if (!gst_structure_get_int (structure, field, &ret)) +    g_assert_not_reached (); + +  return ret; +} + +static gboolean +gst_level_set_caps (GstBaseTransform * trans, GstCaps * in, GstCaps * out)  {    GstLevel *filter; -  GstPad *otherpad; -  GstPadLinkReturn res;    GstStructure *structure;    int i; -  gboolean ret; -  filter = GST_LEVEL (gst_pad_get_parent (pad)); -  g_return_val_if_fail (filter != NULL, GST_PAD_LINK_REFUSED); -  g_return_val_if_fail (GST_IS_LEVEL (filter), GST_PAD_LINK_REFUSED); -  otherpad = (pad == filter->srcpad ? filter->sinkpad : filter->srcpad); - -  res = gst_pad_try_set_caps (otherpad, caps); -  /* if ok, set filter */ -  if (res != GST_PAD_LINK_OK && res != GST_PAD_LINK_DONE) { -    return res; -  } +  filter = GST_LEVEL (trans);    filter->num_samples = 0; -  structure = gst_caps_get_structure (caps, 0); -  ret = gst_structure_get_int (structure, "rate", &filter->rate); -  ret &= gst_structure_get_int (structure, "width", &filter->width); -  ret &= gst_structure_get_int (structure, "channels", &filter->channels); - -  if (!ret) -    return GST_PAD_LINK_REFUSED; +  structure = gst_caps_get_structure (in, 0); +  filter->rate = structure_get_int (structure, "rate"); +  filter->width = structure_get_int (structure, "width"); +  filter->channels = structure_get_int (structure, "channels");    /* allocate channel variable arrays */    g_free (filter->CS); @@ -170,61 +249,129 @@ gst_level_link (GstPad * pad, const GstCaps * caps)          filter->MS[i] = filter->RMS_dB[i] = 0.0;    } -  return GST_PAD_LINK_OK; +  return TRUE; +} + +#if 0 +#define DEBUG(str,...) g_print (str, ...) +#else +#define DEBUG(str,...)          /*nop */ +#endif + +/* process one (interleaved) channel of incoming samples + * calculate square sum of samples + * normalize and return normalized Cumulative Square + * caller must assure num is a multiple of channels + * this filter only accepts signed audio data, so mid level is always 0 + */ +#define DEFINE_LEVEL_CALCULATOR(TYPE)                                           \ +static void inline                                                              \ +gst_level_calculate_##TYPE (TYPE * in, guint num, gint channels,                \ +                            gint resolution, double *CS, double *peak)          \ +{                                                                               \ +  register int j;                                                               \ +  double squaresum = 0.0;	/* square sum of the integer samples */         \ +  register double square = 0.0;		/* Square */                            \ +  register double PSS = 0.0;		/* Peak Square Sample */                \ +  gdouble normalizer;                                                           \ +                                                                                \ +  *CS = 0.0;      /* Cumulative Square for this block */                        \ +                                                                                \ +  normalizer = (double) (1 << resolution);                                      \ +                                                                                \ +  /*                                                                            \ +   * process data here                                                          \ +   * input sample data enters in *in_data as 8 or 16 bit data                   \ +   * samples for left and right channel are interleaved                         \ +   * returns the Mean Square of the samples as a double between 0 and 1         \ +   */                                                                           \ +                                                                                \ +  for (j = 0; j < num; j += channels)                                           \ +  {                                                                             \ +    DEBUG ("ch %d -> smp %d\n", j, in[j]);                                      \ +    square = (double) (in[j] * in[j]);                                          \ +    if (square > PSS) PSS = square;                                             \ +    squaresum += square;                                                        \ +  }                                                                             \ +  *peak = PSS / ((double) normalizer * (double) normalizer);                    \ +                                                                                \ +  /* return normalized cumulative square */                                     \ +  *CS = squaresum / ((double) normalizer * (double) normalizer);                \  } -static void inline -gst_level_fast_16bit_chain (gint16 * in, guint num, gint channels, -    gint resolution, double *CS, double *peak) -#include "filter.func" -     static void inline -         gst_level_fast_8bit_chain (gint8 * in, guint num, gint channels, -    gint resolution, double *CS, double *peak) -#include "filter.func" -     static void gst_level_chain (GstPad * pad, GstData * _data) +DEFINE_LEVEL_CALCULATOR (gint16); +DEFINE_LEVEL_CALCULATOR (gint8); + +static GstMessage * +gst_level_message_new (GstLevel * l, gdouble endtime)  { -  GstBuffer *buf = GST_BUFFER (_data); -  GstLevel *filter; -  gint16 *in_data; +  GstStructure *s; +  GValue v = { 0, }; + +  g_value_init (&v, GST_TYPE_LIST); + +  s = gst_structure_new ("level", "endtime", G_TYPE_DOUBLE, endtime, NULL); +  /* will copy-by-value */ +  gst_structure_set_value (s, "rms", &v); +  gst_structure_set_value (s, "peak", &v); +  gst_structure_set_value (s, "decay", &v); + +  return gst_message_new_application (GST_OBJECT (l), s); +} +static void +gst_level_message_append_channel (GstMessage * m, gdouble rms, gdouble peak, +    gdouble decay) +{ +  GstStructure *s; +  GValue v = { 0, }; +  GValue *l; + +  g_value_init (&v, G_TYPE_DOUBLE); + +  s = (GstStructure *) gst_message_get_structure (m); + +  l = (GValue *) gst_structure_get_value (s, "rms"); +  g_value_set_double (&v, rms); +  gst_value_list_append_value (l, &v);  /* copies by value */ + +  l = (GValue *) gst_structure_get_value (s, "peak"); +  g_value_set_double (&v, peak); +  gst_value_list_append_value (l, &v);  /* copies by value */ + +  l = (GValue *) gst_structure_get_value (s, "decay"); +  g_value_set_double (&v, decay); +  gst_value_list_append_value (l, &v);  /* copies by value */ +} + +static GstFlowReturn +gst_level_transform (GstBaseTransform * trans, GstBuffer * in, GstBuffer ** out) +{ +  GstLevel *filter; +  gpointer in_data;    double CS = 0.0;    gint num_samples = 0;    gint i; -  g_return_if_fail (pad != NULL); -  g_return_if_fail (GST_IS_PAD (pad)); -  g_return_if_fail (buf != NULL); - -  filter = GST_LEVEL (GST_OBJECT_PARENT (pad)); -  g_return_if_fail (filter != NULL); -  g_return_if_fail (GST_IS_LEVEL (filter)); - -  if (!gst_pad_is_negotiated (pad)) { -    GST_ELEMENT_ERROR (filter, CORE, NEGOTIATION, (NULL), -        ("sinkpad not negotiated")); -    gst_data_unref (_data); -    return; -  } +  filter = GST_LEVEL (trans);    for (i = 0; i < filter->channels; ++i)      filter->CS[i] = filter->peak[i] = filter->MS[i] = filter->RMS_dB[i] = 0.0; -  in_data = (gint16 *) GST_BUFFER_DATA (buf); +  in_data = GST_BUFFER_DATA (in); +  num_samples = GST_BUFFER_SIZE (in) / (filter->width / 8); -  /* total number of interleaved samples */ -  num_samples = GST_BUFFER_SIZE (buf) / (filter->width / 8); -  if (num_samples % filter->channels != 0) -    g_warning -        ("WARNING: level: programming error, data not properly interleaved"); +  g_return_val_if_fail (num_samples % filter->channels == 0, +      GST_FLOW_UNEXPECTED);    for (i = 0; i < filter->channels; ++i) {      switch (filter->width) {        case 16: -        gst_level_fast_16bit_chain (in_data + i, num_samples, +        gst_level_calculate_gint16 (in_data + i, num_samples,              filter->channels, filter->width - 1, &CS, &filter->peak[i]);          break;        case 8: -        gst_level_fast_8bit_chain (((gint8 *) in_data) + i, num_samples, +        gst_level_calculate_gint8 (((gint8 *) in_data) + i, num_samples,              filter->channels, filter->width - 1, &CS, &filter->peak[i]);          break;      } @@ -233,21 +380,20 @@ gst_level_fast_16bit_chain (gint16 * in, guint num, gint channels,      filter->CS[i] += CS;    } -  gst_pad_push (filter->srcpad, GST_DATA (buf));    filter->num_samples += num_samples;    for (i = 0; i < filter->channels; ++i) {      filter->decay_peak_age[i] += num_samples; -    /* g_print ("filter peak info [%d]: peak %f, age %f\n", i, -       filter->last_peak[i], filter->decay_peak_age[i]); */ +    DEBUG ("filter peak info [%d]: peak %f, age %f\n", i, +        filter->last_peak[i], filter->decay_peak_age[i]);      /* update running peak */      if (filter->peak[i] > filter->last_peak[i])        filter->last_peak[i] = filter->peak[i];      /* update decay peak */      if (filter->peak[i] >= filter->decay_peak[i]) { -      /* g_print ("new peak, %f\n", filter->peak[i]); */ +      DEBUG ("new peak, %f\n", filter->peak[i]);        filter->decay_peak[i] = filter->peak[i];        filter->decay_peak_age[i] = 0;      } else { @@ -262,11 +408,11 @@ gst_level_fast_16bit_chain (gint16 * in, guint num, gint channels,          falloff_dB = filter->decay_peak_falloff * length;          falloff = pow (10, falloff_dB / -20.0); -        /* g_print ("falloff: length %f, dB falloff %f, falloff factor %e\n", -           length, falloff_dB, falloff); */ +        DEBUG ("falloff: length %f, dB falloff %f, falloff factor %e\n", +            length, falloff_dB, falloff);          filter->decay_peak[i] *= falloff; -        /* g_print ("peak is %f samples old, decayed with factor %e to %f\n", -           filter->decay_peak_age[i], falloff, filter->decay_peak[i]); */ +        DEBUG ("peak is %f samples old, decayed with factor %e to %f\n", +            filter->decay_peak_age[i], falloff, filter->decay_peak[i]);        }      }    } @@ -275,164 +421,34 @@ gst_level_fast_16bit_chain (gint16 * in, guint num, gint channels,    if (filter->num_samples >= filter->interval * (gdouble) filter->rate) {      if (filter->signal) { -      gdouble RMS, peak, endtime; +      GstMessage *m; +      double endtime, RMS; + +      endtime = (double) GST_BUFFER_TIMESTAMP (in) / GST_SECOND +          + (double) num_samples / (double) filter->rate; + +      m = gst_level_message_new (filter, endtime);        for (i = 0; i < filter->channels; ++i) {          RMS = sqrt (filter->CS[i] / (filter->num_samples / filter->channels)); -        peak = filter->last_peak[i]; -        num_samples = GST_BUFFER_SIZE (buf) / (filter->width / 8); -        endtime = (double) GST_BUFFER_TIMESTAMP (buf) / GST_SECOND -            + (double) num_samples / (double) filter->rate; - -        g_signal_emit (G_OBJECT (filter), gst_filter_signals[SIGNAL_LEVEL], 0, -            endtime, i, -            20 * log10 (RMS), 20 * log10 (filter->last_peak[i]), + +        gst_level_message_append_channel (m, 20 * log10 (RMS), +            20 * log10 (filter->last_peak[i]),              20 * log10 (filter->decay_peak[i])); -        /* we emitted, so reset cumulative and normal peak */ + +        /* reset cumulative and normal peak */          filter->CS[i] = 0.0;          filter->last_peak[i] = 0.0;        } + +      gst_element_post_message (GST_ELEMENT (filter), m);      }      filter->num_samples = 0;    } -} - -static void -gst_level_set_property (GObject * object, guint prop_id, -    const GValue * value, GParamSpec * pspec) -{ -  GstLevel *filter; - -  g_return_if_fail (GST_IS_LEVEL (object)); -  filter = GST_LEVEL (object); - -  switch (prop_id) { -    case ARG_SIGNAL_LEVEL: -      filter->signal = g_value_get_boolean (value); -      break; -    case ARG_SIGNAL_INTERVAL: -      filter->interval = g_value_get_double (value); -      break; -    case ARG_PEAK_TTL: -      filter->decay_peak_ttl = g_value_get_double (value); -      break; -    case ARG_PEAK_FALLOFF: -      filter->decay_peak_falloff = g_value_get_double (value); -      break; -    default: -      break; -  } -} - -static void -gst_level_get_property (GObject * object, guint prop_id, -    GValue * value, GParamSpec * pspec) -{ -  GstLevel *filter; - -  g_return_if_fail (GST_IS_LEVEL (object)); -  filter = GST_LEVEL (object); - -  switch (prop_id) { -    case ARG_SIGNAL_LEVEL: -      g_value_set_boolean (value, filter->signal); -      break; -    case ARG_SIGNAL_INTERVAL: -      g_value_set_double (value, filter->interval); -      break; -    case ARG_PEAK_TTL: -      g_value_set_double (value, filter->decay_peak_ttl); -      break; -    case ARG_PEAK_FALLOFF: -      g_value_set_double (value, filter->decay_peak_falloff); -      break; -    default: -      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); -      break; -  } -} -static void -gst_level_base_init (GstLevelClass * klass) -{ -  GstElementClass *element_class = GST_ELEMENT_CLASS (klass); - -  gst_element_class_add_pad_template (element_class, -      gst_static_pad_template_get (&sink_template_factory)); -  gst_element_class_add_pad_template (element_class, -      gst_static_pad_template_get (&src_template_factory)); -  gst_element_class_set_details (element_class, &level_details); -} +  *out = in; -static void -gst_level_class_init (GstLevelClass * klass) -{ -  GObjectClass *gobject_class; -  GstElementClass *gstelement_class; - -  gobject_class = (GObjectClass *) klass; -  gstelement_class = (GstElementClass *) klass; - -  parent_class = g_type_class_ref (GST_TYPE_ELEMENT); -  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SIGNAL_LEVEL, -      g_param_spec_boolean ("signal", "Signal", -          "Emit level signals for each interval", TRUE, G_PARAM_READWRITE)); -  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SIGNAL_INTERVAL, -      g_param_spec_double ("interval", "Interval", -          "Interval between emissions (in seconds)", -          0.01, 100.0, 0.1, G_PARAM_READWRITE)); -  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_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_object_class_install_property (G_OBJECT_CLASS (klass), ARG_PEAK_FALLOFF, -      g_param_spec_double ("peak_falloff", "Peak Falloff", -          "Decay rate of decay peak after TTL (in dB/sec)", -          0.0, G_MAXDOUBLE, 10.0, G_PARAM_READWRITE)); - -  gobject_class->set_property = gst_level_set_property; -  gobject_class->get_property = gst_level_get_property; - -  gst_filter_signals[SIGNAL_LEVEL] = -      g_signal_new ("level", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, -      G_STRUCT_OFFSET (GstLevelClass, level), NULL, NULL, -      gst_level_marshal_VOID__DOUBLE_INT_DOUBLE_DOUBLE_DOUBLE, -      G_TYPE_NONE, 5, -      G_TYPE_DOUBLE, G_TYPE_INT, G_TYPE_DOUBLE, G_TYPE_DOUBLE, G_TYPE_DOUBLE); - -  GST_DEBUG_CATEGORY_INIT (level_debug, "level", 0, "Level calculation"); -} - -static void -gst_level_init (GstLevel * filter) -{ -  filter->sinkpad = -      gst_pad_new_from_template (gst_static_pad_template_get -      (&sink_template_factory), "sink"); -  gst_pad_set_link_function (filter->sinkpad, gst_level_link); -  gst_pad_set_getcaps_function (filter->sinkpad, gst_pad_proxy_getcaps); -  gst_element_add_pad (GST_ELEMENT (filter), filter->sinkpad); -  gst_pad_set_chain_function (filter->sinkpad, gst_level_chain); - -  filter->srcpad = -      gst_pad_new_from_template (gst_static_pad_template_get -      (&src_template_factory), "src"); -  gst_pad_set_link_function (filter->srcpad, gst_level_link); -  gst_pad_set_getcaps_function (filter->srcpad, gst_pad_proxy_getcaps); -  gst_element_add_pad (GST_ELEMENT (filter), filter->srcpad); - -  filter->CS = NULL; -  filter->peak = NULL; -  filter->MS = NULL; -  filter->RMS_dB = NULL; - -  filter->rate = 0; -  filter->width = 0; -  filter->channels = 0; - -  filter->interval = 0.1; -  filter->decay_peak_ttl = 0.4; -  filter->decay_peak_falloff = 10.0;    /* dB falloff (/sec) */ +  return GST_FLOW_OK;  }  static gboolean diff --git a/gst/level/gstlevel.h b/gst/level/gstlevel.h index 59427c7d..a7072386 100644 --- a/gst/level/gstlevel.h +++ b/gst/level/gstlevel.h @@ -27,12 +27,10 @@  #include <gst/gst.h> +#include <gst/base/gstbasetransform.h> -#include "gstlevel-marshal.h" -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ +G_BEGIN_DECLS  #define GST_TYPE_LEVEL \ @@ -46,13 +44,14 @@ extern "C" {  #define GST_IS_LEVEL_CLASS(obj) \    (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_LEVEL)) +  typedef struct _GstLevel GstLevel;  typedef struct _GstLevelClass GstLevelClass; +  struct _GstLevel { -  GstElement element; +  GstBaseTransform element; -  GstPad *sinkpad, *srcpad;    gboolean signal;		/* whether or not to emit signals */    gdouble interval;		/* how many seconds between emits */ @@ -75,16 +74,14 @@ struct _GstLevel {  };  struct _GstLevelClass { -  GstElementClass parent_class; -  void (*level) (GstElement *element, gdouble time, gint channel, -                 gdouble RMS_dB, gdouble peak_dB, gdouble decay_peak_dB); +  GstBaseTransformClass parent_class;  }; +  GType gst_level_get_type(void); -#ifdef __cplusplus -} -#endif /* __cplusplus */ + +G_END_DECLS -#endif /* __GST_STEREO_H__ */ +#endif /* __GST_LEVEL_H__ */ diff --git a/tests/old/examples/Makefile.am b/tests/old/examples/Makefile.am index 0c8190c7..11f92220 100644 --- a/tests/old/examples/Makefile.am +++ b/tests/old/examples/Makefile.am @@ -5,7 +5,7 @@ FT2_SUBDIRS=  endif  if HAVE_GTK -GTK_SUBDIRS=dynparams $(FT2_SUBDIRS) +GTK_SUBDIRS=dynparams level $(FT2_SUBDIRS)  else  GTK_SUBDIRS=  endif @@ -17,4 +17,4 @@ GCONF_SUBDIRS=  endif  SUBDIRS=$(GTK_SUBDIRS) $(GCONF_SUBDIRS) switch -DIST_SUBDIRS=capsfilter dynparams seeking indexing gstplay switch +DIST_SUBDIRS=capsfilter dynparams seeking indexing gstplay switch level diff --git a/tests/old/examples/level/Makefile.am b/tests/old/examples/level/Makefile.am new file mode 100644 index 00000000..bf76136f --- /dev/null +++ b/tests/old/examples/level/Makefile.am @@ -0,0 +1,11 @@ +noinst_PROGRAMS = demo plot + +demo_SOURCES = demo.c +demo_CFLAGS = $(GTK_CFLAGS) $(GST_CFLAGS) +demo_LDFLAGS = $(GTK_LIBS) $(GST_LIBS) + +plot_SOURCES = plot.c +plot_CFLAGS = $(GTK_CFLAGS) $(GST_CFLAGS) +plot_LDFLAGS = $(GTK_LIBS) $(GST_LIBS) + +EXTRA_DIST = README diff --git a/tests/old/examples/level/README b/tests/old/examples/level/README new file mode 100644 index 00000000..0ae84188 --- /dev/null +++ b/tests/old/examples/level/README @@ -0,0 +1,39 @@ +level plugin by thomas <thomas@apestaart.org> + +this plugin signals: +  - running time since last EOS/start +  - channel +  - RMS level +  - peak level +  - decaying peak level +over the given interval. + +This is useful for a VU meter display and for plotting out the signal graph. +The VU meter can either display RMS, or display immediate peak level and +have the falloff decaying peak level displayed as a line. + +The interval for signal emission, ttl of decay peak, and falloff of decay peak +can all be set. + +The element only takes unsigned data in; it could be extended to signed as +well, if separate fast chain functions are made that displaces the incoming +data to its midpoint (ie, 0,65535 should be mapped to -32768, 32767) + +There are two demo apps, apps and plot.  apps will create some GTK sliders +to display the volume.  plot will output data readable by gnuplot. + +Here is a sample plot script to plot output of the plot command that was +stored to plot.dat + +set xlabel "Seconds" +set ylabel "dB" +set yrange [-60:0] +plot 'plot.dat' using 1:2 title 'L RMS' with lines, \ +     'plot.dat' using 1:3 title 'L peak' with lines, \ +     'plot.dat' using 1:4 title 'L decay' with lines + +plot 'plot.dat' using 1:5 title 'R RMS' with lines, \ +     'plot.dat' using 1:6 title 'R peak' with lines, \ +     'plot.dat' using 1:7 title 'R decay' with lines + + diff --git a/tests/old/examples/level/demo.c b/tests/old/examples/level/demo.c new file mode 100644 index 00000000..502f50f7 --- /dev/null +++ b/tests/old/examples/level/demo.c @@ -0,0 +1,155 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu> + * + * demo.c: sample application to display VU meter-like output of level + * Copyright (C) 2003 + *           Thomas Vander Stichele <thomas at apestaart dot org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gst/gst.h> +#include <gtk/gtk.h> + +/* global array for the scale widgets, we'll assume stereo */ +GtkWidget *elapsed; +GtkWidget *scale[2][3]; + +static void +level_callback (GstElement * element, gdouble time, gint channel, +    gdouble rms, gdouble peak, gdouble decay) +{ +  gchar *label; + +  label = g_strdup_printf ("%.3f", time); +  gtk_label_set (GTK_LABEL (elapsed), label); +  g_free (label); +  gtk_range_set_value (GTK_RANGE (scale[channel][0]), rms); +  gtk_range_set_value (GTK_RANGE (scale[channel][1]), peak); +  gtk_range_set_value (GTK_RANGE (scale[channel][2]), decay); +} + +static gboolean +idler (gpointer data) +{ +  GstElement *pipeline = GST_ELEMENT (data); + +  g_print ("+"); +  if (gst_bin_iterate (GST_BIN (pipeline))) +    return TRUE; +  gtk_main_quit (); +  return FALSE; +} + +static void +setup_gui () +{ +  GtkWidget *window; +  GtkWidget *vbox; +  GtkWidget *label, *hbox; +  int c; + +  window = gtk_window_new (GTK_WINDOW_TOPLEVEL); +  g_signal_connect (window, "destroy", gtk_main_quit, NULL); + +  vbox = gtk_vbox_new (TRUE, 0); +  gtk_container_add (GTK_CONTAINER (window), vbox); + +  /* elapsed widget */ +  hbox = gtk_hbox_new (TRUE, 0); +  label = gtk_label_new ("Elapsed"); +  elapsed = gtk_label_new ("0.000"); +  gtk_container_add (GTK_CONTAINER (hbox), label); +  gtk_container_add (GTK_CONTAINER (hbox), elapsed); +  gtk_container_add (GTK_CONTAINER (vbox), hbox); + +  for (c = 0; c < 2; ++c) { +    /* RMS */ +    hbox = gtk_hbox_new (TRUE, 0); +    label = gtk_label_new ("RMS"); +    gtk_container_add (GTK_CONTAINER (hbox), label); +    scale[c][0] = gtk_hscale_new_with_range (-90.0, 0.0, 0.2); +    gtk_widget_set_size_request (scale[c][0], 100, -1); +    gtk_container_add (GTK_CONTAINER (hbox), scale[c][0]); +    gtk_container_add (GTK_CONTAINER (vbox), hbox); +    /* peak */ +    hbox = gtk_hbox_new (TRUE, 0); +    label = gtk_label_new ("peak"); +    gtk_container_add (GTK_CONTAINER (hbox), label); +    scale[c][1] = gtk_hscale_new_with_range (-90.0, 0.0, 0.2); +    gtk_widget_set_size_request (scale[c][1], 100, -1); +    gtk_container_add (GTK_CONTAINER (hbox), scale[c][1]); +    gtk_container_add (GTK_CONTAINER (vbox), hbox); +    /* decay */ +    hbox = gtk_hbox_new (TRUE, 0); +    label = gtk_label_new ("decaying peek"); +    gtk_container_add (GTK_CONTAINER (hbox), label); +    scale[c][2] = gtk_hscale_new_with_range (-90.0, 0.0, 0.2); +    gtk_widget_set_size_request (scale[c][2], 100, -1); +    gtk_container_add (GTK_CONTAINER (hbox), scale[c][2]); +    gtk_container_add (GTK_CONTAINER (vbox), hbox); +  } + +  gtk_widget_show_all (GTK_WIDGET (window)); +} + +int +main (int argc, char *argv[]) +{ + +  GstElement *pipeline = NULL; +  GError *error = NULL; +  GstElement *level; + +  gst_init (&argc, &argv); +  gtk_init (&argc, &argv); + +  pipeline = gst_parse_launchv ((const gchar **) &argv[1], &error); +  if (error) { +    g_print ("pipeline could not be constructed: %s\n", error->message); +    g_print ("Please give a complete pipeline  with a 'level' element.\n"); +    g_print ("Example: sinesrc ! level ! %s\n", DEFAULT_AUDIOSINK); +    g_error_free (error); +    return 1; +  } + +  level = gst_bin_get_by_name (GST_BIN (pipeline), "level0"); +  if (level == NULL) { +    g_print ("Please give a pipeline with a 'level' element in it\n"); +    return 1; +  } + +  g_object_set (level, "signal", TRUE, NULL); +  g_signal_connect (level, "level", G_CALLBACK (level_callback), NULL); + + +  /* setup GUI */ +  setup_gui (); + +  /* connect level signal */ + +  /* go to main loop */ +  gst_element_set_state (pipeline, GST_STATE_PLAYING); +  g_idle_add (idler, pipeline); + +  gtk_main (); + +  return 0; +} diff --git a/tests/old/examples/level/plot.c b/tests/old/examples/level/plot.c new file mode 100644 index 00000000..6df01065 --- /dev/null +++ b/tests/old/examples/level/plot.c @@ -0,0 +1,123 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu> + * + * plot.c: output data points to be graphed with gnuplot + * Copyright (C) 2003 + *           Thomas Vander Stichele <thomas at apestaart dot org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gst/gst.h> +#include <gtk/gtk.h> + +gboolean got_channel[2] = { FALSE, FALSE };     /* to see if we got the signal for this one yet */ +gint channels = 0;              /* guess at how many channels there are */ +gdouble last_time = 0.0;        /* time of last signal */ +gdouble values[2][3];           /* array of levels from which to print */ + +static void +level_callback (GstElement * element, gdouble time, gint channel, +    gdouble rms, gdouble peak, gdouble decay) +{ +  int i = 0, j = 0; +  gboolean got_all = FALSE; + +  if (channel + 1 > channels) +    channels = channel + 1; + +  /* reset got_channel if this is a new time point */ +  if (time > last_time) { +    for (i = 0; i < channels; ++i) +      got_channel[i] = FALSE; +    last_time = time; +  } + +  /* store values */ +  got_channel[channel] = TRUE; +  values[channel][0] = rms; +  values[channel][1] = peak; +  values[channel][2] = decay; + +  /* check if we have all channels, and output if we do */ +  /* FIXME: this fails on the first, no ? */ +  got_all = TRUE; +  for (i = 0; i < channels; ++i) +    if (!got_channel[i]) +      got_all = FALSE; +  if (got_all) { +    g_print ("%f ", time); +    for (i = 0; i < channels; ++i) +      for (j = 0; j < 3; ++j) +        g_print ("%f ", values[i][j]); +    g_print ("\n"); +  } +} + +static gboolean +idler (gpointer data) +{ +  GstElement *pipeline = GST_ELEMENT (data); + +  if (gst_bin_iterate (GST_BIN (pipeline))) +    return TRUE; + +  gtk_main_quit (); +  return FALSE; +} + +int +main (int argc, char *argv[]) +{ + +  GstElement *pipeline = NULL; +  GError *error = NULL; +  GstElement *level; + +  gst_init (&argc, &argv); +  gtk_init (&argc, &argv); + +  pipeline = gst_parse_launchv ((const gchar **) &argv[1], &error); +  if (error) { +    g_print ("pipeline could not be constructed: %s\n", error->message); +    g_print ("Please give a complete pipeline  with a 'level' element.\n"); +    g_print ("Example: sinesrc ! level ! %s\n", DEFAULT_AUDIOSINK); +    g_error_free (error); +    return 1; +  } + +  level = gst_bin_get_by_name (GST_BIN (pipeline), "level0"); +  if (level == NULL) { +    g_print ("Please give a pipeline with a 'level' element in it\n"); +    return 1; +  } + +  g_object_set (level, "signal", TRUE, NULL); +  g_signal_connect (level, "level", G_CALLBACK (level_callback), NULL); + + +  /* go to main loop */ +  gst_element_set_state (pipeline, GST_STATE_PLAYING); +  g_idle_add (idler, pipeline); + +  gtk_main (); + +  return 0; +} | 
