Initial revision
authorAndy Wingo <wingo@pobox.com>
Sat, 22 Dec 2001 23:27:31 +0000 (23:27 +0000)
committerAndy Wingo <wingo@pobox.com>
Sat, 22 Dec 2001 23:27:31 +0000 (23:27 +0000)
Original commit message from CVS:
Initial revision

54 files changed:
gst/cutter/Makefile.am [new file with mode: 0644]
gst/cutter/README [new file with mode: 0644]
gst/cutter/filter.func [new file with mode: 0644]
gst/cutter/gstcutter.c [new file with mode: 0644]
gst/cutter/gstcutter.h [new file with mode: 0644]
gst/flx/Makefile.am [new file with mode: 0644]
gst/flx/flx_color.c [new file with mode: 0644]
gst/flx/flx_color.h [new file with mode: 0644]
gst/flx/flx_fmt.h [new file with mode: 0644]
gst/flx/gstflxdec.c [new file with mode: 0644]
gst/flx/gstflxdec.h [new file with mode: 0644]
gst/law/Makefile.am [new file with mode: 0644]
gst/law/alaw-conversion.c [new file with mode: 0644]
gst/law/alaw-conversion.h [new file with mode: 0644]
gst/law/alaw-decode.c [new file with mode: 0644]
gst/law/alaw-decode.h [new file with mode: 0644]
gst/law/alaw-encode.c [new file with mode: 0644]
gst/law/alaw-encode.h [new file with mode: 0644]
gst/law/alaw.c [new file with mode: 0644]
gst/law/mulaw-conversion.c [new file with mode: 0644]
gst/law/mulaw-conversion.h [new file with mode: 0644]
gst/law/mulaw-decode.c [new file with mode: 0644]
gst/law/mulaw-decode.h [new file with mode: 0644]
gst/law/mulaw-encode.c [new file with mode: 0644]
gst/law/mulaw-encode.h [new file with mode: 0644]
gst/law/mulaw.c [new file with mode: 0644]
gst/level/Makefile.am [new file with mode: 0644]
gst/level/README [new file with mode: 0644]
gst/level/filter.func [new file with mode: 0644]
gst/level/gstlevel.c [new file with mode: 0644]
gst/level/gstlevel.h [new file with mode: 0644]
gst/median/.gitignore [new file with mode: 0644]
gst/median/Makefile.am [new file with mode: 0644]
gst/median/gstmedian.c [new file with mode: 0644]
gst/median/gstmedian.h [new file with mode: 0644]
gst/spectrum/.gitignore [new file with mode: 0644]
gst/spectrum/Makefile.am [new file with mode: 0644]
gst/spectrum/README [new file with mode: 0644]
gst/spectrum/gstspectrum.c [new file with mode: 0644]
gst/spectrum/gstspectrum.h [new file with mode: 0644]
gst/udp/.gitignore [new file with mode: 0644]
gst/udp/Makefile.am [new file with mode: 0644]
gst/udp/README [new file with mode: 0644]
gst/udp/gstudp.c [new file with mode: 0644]
gst/udp/gstudpsink.c [new file with mode: 0644]
gst/udp/gstudpsink.h [new file with mode: 0644]
gst/udp/gstudpsrc.c [new file with mode: 0644]
gst/udp/gstudpsrc.h [new file with mode: 0644]
gst/wavparse/.gitignore [new file with mode: 0644]
gst/wavparse/Makefile.am [new file with mode: 0644]
gst/wavparse/gstriff.c [new file with mode: 0644]
gst/wavparse/gstriff.h [new file with mode: 0644]
gst/wavparse/gstwavparse.c [new file with mode: 0644]
gst/wavparse/gstwavparse.h [new file with mode: 0644]

diff --git a/gst/cutter/Makefile.am b/gst/cutter/Makefile.am
new file mode 100644 (file)
index 0000000..d31d6f1
--- /dev/null
@@ -0,0 +1,9 @@
+filterdir = $(libdir)/gst
+
+filter_LTLIBRARIES = libgstcutter.la
+
+libgstcutter_la_SOURCES = gstcutter.c
+
+noinst_HEADERS = gstcutter.h filter.func
+
+EXTRA_DIST = README
diff --git a/gst/cutter/README b/gst/cutter/README
new file mode 100644 (file)
index 0000000..fc0975e
--- /dev/null
@@ -0,0 +1,38 @@
+cutter plugin by thomas <thomas@apestaart.org>
+
+SYNOPSIS
+
+This plugin emits signals when RMS level of audio signal crosses a
+threshold for a given amount of time.  
+
+As soon as the buffer's RMS is greater than the threshold value, the plugin fires a CUT_START signal.
+
+When the buffer's RMS level drops below the threshold value for a consecutive run length longer than the given runlength, it sends a CUT_STOP signal.
+
+When a pre-recording buffer is used, the plugin will delay throughput of data when it's in "silent" mode for a maximum length equal to the pre-recording buffer length.  As soon as the input level crosses the threshold level, this pre-recorded buffer is flushed to the src pad (so you can actually record the audio just before the threshold crossing) after sending the signal.
+
+ARGUMENTS
+
+GstCutter::threshold
+       level (between 0 and 1) of threshold
+GstCutter::threshold_dB
+       level of threshold in dB (between -inf and 0)
+GstCutter::runlength
+       minimum length (in seconds) before plugin sends cut_stop signal
+GstCutter::prelength
+        length of pre-recording buffer
+        
+SIGNALS
+
+       CUT_START
+       gets sent when the level of the signal goes above threshold level
+       CUT_STOP
+       gets sent when the level of the signal has been below the
+       threshold level for a number of consecutive iterations of which
+       the cumulative length is more than the runlength
+
+LIMITATIONS
+
+       * RMS value is calculated over the whole data buffer, so
+         the time resolution is limited to the buffer length
+       * RMS value is calculated over all of the channels combined
diff --git a/gst/cutter/filter.func b/gst/cutter/filter.func
new file mode 100644 (file)
index 0000000..bdbe566
--- /dev/null
@@ -0,0 +1,16 @@
+{
+  guint j;
+  register double squaresum = 0.0;
+
+  /*
+   * process data here  
+   * input sample data enters in *in_data as 8 or 16 bit data
+   * samples for left and right channel are interleaved
+   */
+
+  for (j = 0; j < num_samples; j++) 
+     squaresum += data[j] * data[j];
+
+  return (squaresum / (float) num_samples);
+}
+
diff --git a/gst/cutter/gstcutter.c b/gst/cutter/gstcutter.c
new file mode 100644 (file)
index 0000000..8161d50
--- /dev/null
@@ -0,0 +1,419 @@
+/* Gnome-Streamer
+ * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
+ *
+ * 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.
+ */
+
+#include <gst/gst.h>
+#include <libs/audio/gstaudio.h>
+#include "cutter.h"
+#include "math.h"
+
+
+static GstElementDetails cutter_details = {
+  "Cutter",
+  "Filter/Effect",
+  "Audio Cutter to split audio into non-silent bits",
+  VERSION,
+  "Thomas <thomas@apestaart.org>",
+  "(C) 2001",
+};
+
+
+/* Filter signals and args */
+enum {
+  /* FILL ME */
+  CUT_START,
+  CUT_STOP,
+  LAST_SIGNAL
+};
+
+enum {
+  ARG_0,
+  ARG_THRESHOLD,
+  ARG_THRESHOLD_DB,
+  ARG_RUN_LENGTH,
+  ARG_PRE_LENGTH
+};
+
+GST_PADTEMPLATE_FACTORY (cutter_src_factory,
+  "src",
+  GST_PAD_SRC,
+  GST_PAD_ALWAYS,
+  GST_CAPS_NEW (
+    "test_src",
+    "audio/raw",
+      "channels", GST_PROPS_INT_RANGE (1, 2)
+  )
+);
+
+GST_PADTEMPLATE_FACTORY (cutter_sink_factory,
+  "sink",
+  GST_PAD_SINK,
+  GST_PAD_ALWAYS,
+  GST_CAPS_NEW (
+    "test_src",
+    "audio/raw",
+      "channels", GST_PROPS_INT_RANGE (1, 2)
+  )
+);
+
+static void            gst_cutter_class_init           (GstCutterClass *klass);
+static void            gst_cutter_init                 (GstCutter *filter);
+
+static void            gst_cutter_set_property         (GObject *object, guint prop_id, 
+                                                        const GValue *value, GParamSpec *pspec);
+static void            gst_cutter_get_property         (GObject *object, guint prop_id, 
+                                                        GValue *value, GParamSpec *pspec);
+
+static void            gst_cutter_chain                (GstPad *pad, GstBuffer *buf);
+static double inline   gst_cutter_16bit_ms             (gint16* data, guint numsamples);
+static double inline   gst_cutter_8bit_ms              (gint8* data, guint numsamples);
+
+void                   gst_cutter_get_caps             (GstPad *pad, GstCutter* filter);
+
+static GstElementClass *parent_class = NULL;
+static guint gst_cutter_signals[LAST_SIGNAL] = { 0 };
+
+static GstPadNegotiateReturn
+cutter_negotiate_src (GstPad *pad, GstCaps **caps, gpointer *data)
+{
+  GstCutter* filter = GST_CUTTER (gst_pad_get_parent (pad));
+  
+  if (*caps==NULL) 
+    return GST_PAD_NEGOTIATE_FAIL;
+  
+  return gst_pad_negotiate_proxy(pad,filter->sinkpad,caps);
+}
+
+static GstPadNegotiateReturn
+cutter_negotiate_sink (GstPad *pad, GstCaps **caps, gpointer *data)
+{
+  GstCutter* filter = GST_CUTTER (gst_pad_get_parent (pad));
+  
+  if (*caps==NULL) 
+    return GST_PAD_NEGOTIATE_FAIL;
+  
+  return gst_pad_negotiate_proxy(pad,filter->srcpad,caps);
+}              
+
+GType
+gst_cutter_get_type(void) {
+  static GType cutter_type = 0;
+
+  if (!cutter_type) {
+    static const GTypeInfo cutter_info = {
+      sizeof(GstCutterClass),      NULL,      NULL,      (GClassInitFunc)gst_cutter_class_init,
+      NULL,
+      NULL,
+      sizeof(GstCutter),
+      0,
+      (GInstanceInitFunc)gst_cutter_init,
+    };
+    cutter_type = g_type_register_static(GST_TYPE_ELEMENT, "GstCutter", &cutter_info, 0);
+  }
+  return cutter_type;
+}
+
+static void
+gst_cutter_class_init (GstCutterClass *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_THRESHOLD,
+    g_param_spec_double ("threshold", "threshold", "threshold",
+                         G_MINDOUBLE, G_MAXDOUBLE, 0, G_PARAM_READWRITE)); // CHECKME
+  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_THRESHOLD_DB,
+    g_param_spec_double ("threshold_dB", "threshold_dB", "threshold_dB",
+                         G_MINDOUBLE, G_MAXDOUBLE, 0, G_PARAM_READWRITE)); // CHECKME
+  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_RUN_LENGTH,
+    g_param_spec_double ("runlength", "runlength", "runlength",
+                        G_MINDOUBLE, G_MAXDOUBLE, 0, G_PARAM_READWRITE)); // CHECKME
+
+  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_PRE_LENGTH,
+    g_param_spec_double ("prelength", "prelength", "prelength",
+                        G_MINDOUBLE, G_MAXDOUBLE, 0, G_PARAM_READWRITE)); // CHECKME
+  gst_cutter_signals[CUT_START] = 
+       g_signal_new ("cut_start", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_FIRST,
+                       G_STRUCT_OFFSET (GstCutterClass, cut_start), NULL, NULL,
+                       g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
+  gst_cutter_signals[CUT_STOP] = 
+       g_signal_new ("cut_stop", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_FIRST,
+                       G_STRUCT_OFFSET (GstCutterClass, cut_stop), NULL, NULL,
+                       g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
+
+
+  gobject_class->set_property = gst_cutter_set_property;
+  gobject_class->get_property = gst_cutter_get_property;
+}
+
+static void
+gst_cutter_init (GstCutter *filter)
+{
+  filter->sinkpad = gst_pad_new_from_template (cutter_sink_factory (),"sink");
+  filter->srcpad = gst_pad_new_from_template (cutter_src_factory (),"src");
+
+  filter->threshold_level = 0.1;
+  filter->threshold_length = 0.5;
+  filter->silent_run_length = 0.0;
+  filter->silent = TRUE;
+
+  filter->pre_length = 0.2;
+  filter->pre_run_length = 0.0;
+  filter->pre_buffer = NULL;
+  
+  gst_pad_set_negotiate_function (filter->sinkpad,cutter_negotiate_sink);
+  gst_pad_set_negotiate_function (filter->srcpad,cutter_negotiate_src);
+
+  gst_element_add_pad (GST_ELEMENT (filter), filter->sinkpad);
+  gst_pad_set_chain_function (filter->sinkpad, gst_cutter_chain);
+  filter->srcpad = gst_pad_new ("src", GST_PAD_SRC);
+  gst_element_add_pad (GST_ELEMENT (filter), filter->srcpad);
+}
+
+static void
+gst_cutter_chain (GstPad *pad, GstBuffer *buf)
+{
+  GstCutter *filter;
+  gint16 *in_data;
+  double RMS = 0.0;                    /* RMS of signal in buffer */
+  double ms = 0.0;                     /* mean square value of buffer */
+  static gboolean silent_prev = FALSE;  /* previous value of silent */
+  GstBuffer* prebuf;                    /* pointer to a prebuffer element */
+  g_return_if_fail (pad != NULL);
+  g_return_if_fail (GST_IS_PAD (pad));
+  g_return_if_fail (buf != NULL);
+
+  filter = GST_CUTTER (GST_OBJECT_PARENT (pad));
+  g_return_if_fail (filter != NULL);
+  g_return_if_fail (GST_IS_CUTTER (filter));
+
+  g_return_if_fail (gst_audio_is_buffer_framed (pad, buf) == TRUE);
+
+  if (!filter->have_caps) gst_cutter_get_caps (pad, filter);
+
+  in_data = (gint16 *) GST_BUFFER_DATA (buf);
+  g_print ("DEBUG: cutter: length of prerec buffer: %.3f sec\n",
+           filter->pre_run_length);
+
+  /* calculate mean square value on buffer */
+  switch (filter->width) 
+  {
+    case 16:
+      ms = gst_cutter_16bit_ms (in_data, GST_BUFFER_SIZE (buf) / 2);
+      break;
+    case 8:
+      ms = gst_cutter_8bit_ms ((gint8 *) in_data, GST_BUFFER_SIZE (buf));
+      break;
+    default:
+      /* this shouldn't happen */
+      g_print ("WARNING: no mean square function for width %d\n",
+               filter->width);
+      break;
+  }
+
+  silent_prev = filter->silent;
+
+  RMS = sqrt (ms) / (double) filter->max_sample;
+  /* if RMS below threshold, add buffer length to silent run length count 
+   * if not, reset
+   */
+  //g_print ("DEBUG: cutter: ms %f, RMS %f\n", ms, RMS);
+  if (RMS < filter->threshold_level)
+    filter->silent_run_length += gst_audio_length (filter->srcpad, buf);
+  else
+  {  
+    filter->silent_run_length = 0.0;
+    filter->silent = FALSE;
+  }
+
+  if (filter->silent_run_length > filter->threshold_length)
+    /* it has been silent long enough, flag it */
+    filter->silent = TRUE;
+
+  /* has the silent status changed ? if so, send right signal 
+   * and, if from silent -> not silent, flush pre_record buffer 
+   */
+  if (filter->silent != silent_prev)
+  {
+    if (filter->silent)
+    {
+//      g_print ("DEBUG: cutter: cut to here, turning off out\n");
+      gtk_signal_emit (G_OBJECT (filter), gst_cutter_signals[CUT_STOP]);
+    }
+    else
+    {
+//      g_print ("DEBUG: cutter: start from here, turning on out\n");
+      /* first of all, flush current buffer */
+      gtk_signal_emit (G_OBJECT (filter), gst_cutter_signals[CUT_START]);
+      g_print ("DEBUG: cutter: flushing buffer ");
+      while (filter->pre_buffer)
+      {
+        g_print (".");
+        prebuf = (g_list_first (filter->pre_buffer))->data;
+        filter->pre_buffer = g_list_remove (filter->pre_buffer, prebuf);
+        gst_pad_push (filter->srcpad, prebuf);
+        filter->pre_run_length = 0.0;
+      }
+      g_print ("\n");
+    } 
+  }
+  /* now check if we have to add the new buffer to the cache or to the pad */
+  if (filter->silent)
+  {
+      filter->pre_buffer = g_list_append (filter->pre_buffer, buf);
+      filter->pre_run_length += gst_audio_length (filter->srcpad, buf);
+      while (filter->pre_run_length > filter->pre_length)
+      {
+        prebuf = (g_list_first (filter->pre_buffer))->data;
+        filter->pre_buffer = g_list_remove (filter->pre_buffer, prebuf);
+        gst_pad_push (filter->srcpad, prebuf);
+        filter->pre_run_length -= gst_audio_length (filter->srcpad, prebuf);
+      }
+  }
+  else
+    gst_pad_push (filter->srcpad, buf);
+}
+
+static double inline
+gst_cutter_16bit_ms (gint16* data, guint num_samples)
+#include "filter.func"
+
+static double inline
+gst_cutter_8bit_ms (gint8* data, guint num_samples)
+#include "filter.func"
+
+static void
+gst_cutter_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
+{
+  GstCutter *filter;
+
+  /* it's not null if we got it, but it might not be ours */
+  g_return_if_fail(GST_IS_CUTTER (object));
+  filter = GST_CUTTER (object);
+
+  switch (prop_id)
+  {
+    case ARG_THRESHOLD:
+       /* set the level */
+      filter->threshold_level = g_value_get_double (value);
+      g_print ("DEBUG: cutter: set threshold level to %f\n",
+               filter->threshold_level);
+      break;
+    case ARG_THRESHOLD_DB:
+      /* set the level given in dB 
+       * value in dB = 20 * log (value) 
+       * values in dB < 0 result in values between 0 and 1
+       */
+      filter->threshold_level = pow (10, g_value_get_double (value) / 20);
+      g_print ("DEBUG: cutter: set threshold level to %f\n",
+               filter->threshold_level);
+      break;
+    case ARG_RUN_LENGTH:
+      /* set the minimum length of the silent run required */
+      filter->threshold_length = g_value_get_double (value);
+      break;   
+    case ARG_PRE_LENGTH:
+      /* set the length of the pre-record block */
+      filter->pre_length = g_value_get_double (value);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void
+gst_cutter_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
+{
+  GstCutter *filter;
+
+  /* it's not null if we got it, but it might not be ours */
+  g_return_if_fail (GST_IS_CUTTER(object));
+  filter = GST_CUTTER (object);
+
+  switch (prop_id)
+  {
+    case ARG_RUN_LENGTH:
+     g_value_set_double (value, filter->threshold_length);
+     break;
+    case ARG_THRESHOLD:
+     g_value_set_double (value, filter->threshold_level);
+     break;
+    case ARG_THRESHOLD_DB:
+     g_value_set_double (value, 20 * log (filter->threshold_level));
+     break;
+    case ARG_PRE_LENGTH:
+      g_value_set_double (value, filter->pre_length);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static gboolean
+plugin_init (GModule *module, GstPlugin *plugin)
+{
+  GstElementFactory *factory;
+
+  factory = gst_elementfactory_new("cutter",GST_TYPE_CUTTER,
+                                   &cutter_details);
+  g_return_val_if_fail(factory != NULL, FALSE);
+  
+  gst_elementfactory_add_padtemplate (factory, GST_PADTEMPLATE_GET (cutter_src_factory));
+  gst_elementfactory_add_padtemplate (factory, GST_PADTEMPLATE_GET (cutter_sink_factory));
+
+  gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (factory));
+
+  /* load audio support library */
+  if (!gst_library_load ("gstaudio"))
+  {
+    gst_info ("cutter: could not load support library: 'gstaudio'\n");
+    return FALSE;
+  }
+
+  return TRUE;
+}
+
+GstPluginDesc plugin_desc = 
+{
+  GST_VERSION_MAJOR,
+  GST_VERSION_MINOR,
+  "cutter",
+  plugin_init
+};
+
+void
+gst_cutter_get_caps (GstPad *pad, GstCutter* filter)
+{
+  GstCaps *caps = NULL;
+
+  caps = GST_PAD_CAPS (pad);
+    // FIXME : Please change this to a better warning method !
+  if (caps == NULL)
+    printf ("WARNING: cutter: get_caps: Could not get caps of pad !\n");
+  filter->width = gst_caps_get_int (caps, "width");
+  filter->max_sample = gst_audio_highest_sample_value (pad);
+  filter->have_caps = TRUE;
+}
diff --git a/gst/cutter/gstcutter.h b/gst/cutter/gstcutter.h
new file mode 100644 (file)
index 0000000..18de878
--- /dev/null
@@ -0,0 +1,84 @@
+/* Gnome-Streamer
+ * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
+ *
+ * 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.
+ */
+
+
+#ifndef __GST_CUTTER_H__
+#define __GST_CUTTER_H__
+
+
+#include <config.h>
+#include <gst/gst.h>
+// #include <gst/meta/audioraw.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define GST_TYPE_CUTTER \
+  (gst_cutter_get_type())
+#define GST_CUTTER(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_CUTTER,GstCutter))
+#define GST_CUTTER_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_ULAW,GstCutter))
+#define GST_IS_CUTTER(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_CUTTER))
+#define GST_IS_CUTTER_CLASS(obj) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_CUTTER))
+
+typedef struct _GstCutter GstCutter;
+typedef struct _GstCutterClass GstCutterClass;
+
+struct _GstCutter 
+{
+  GstElement element;
+
+  GstPad *sinkpad, *srcpad;
+
+  double threshold_level;      /* level below which to cut */
+  double threshold_length;     /* how long signal has to remain
+                                * below this level before cutting
+                                 */
+  double silent_run_length;    /* how long has it been below threshold ? */
+  gboolean silent;
+
+  double pre_length;           /* how long can the pre-record buffer be ? */
+  double pre_run_length;        /* how long is it currently ? */
+  GList *pre_buffer;
+  
+  gboolean have_caps;          /* did we get the needed caps yet ? */
+  gint width;                  /* bit width of data */
+  long max_sample;             /* maximum sample value */
+};
+
+struct _GstCutterClass {
+  GstElementClass parent_class;
+  void (*cut_start) (GstCutter* filter);
+  void (*cut_stop) (GstCutter* filter);
+};
+
+GType gst_cutter_get_type(void);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GST_STEREO_H__ */
diff --git a/gst/flx/Makefile.am b/gst/flx/Makefile.am
new file mode 100644 (file)
index 0000000..79a6fba
--- /dev/null
@@ -0,0 +1,9 @@
+filterdir = $(libdir)/gst
+
+filter_LTLIBRARIES = libgstflxdec.la
+
+libgstflxdec_la_SOURCES = gstflxdec.c flx_color.c
+libgstflxdec_la_CFLAGS = $(GST_CFLAGS)
+
+noinst_HEADERS = flx_fmt.h flx_color.h gstflxdec.h
+
diff --git a/gst/flx/flx_color.c b/gst/flx/flx_color.c
new file mode 100644 (file)
index 0000000..c61052d
--- /dev/null
@@ -0,0 +1,94 @@
+/* Gnome-Streamer
+ * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
+ *
+ * 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.
+ */
+
+#include <string.h>
+#include <gst/gst.h>
+
+
+#include "flx_color.h"
+
+FlxColorSpaceConverter *
+flx_colorspace_converter_new(gint width, gint height)
+{
+  FlxColorSpaceConverter *new = g_malloc(sizeof(FlxColorSpaceConverter));
+
+  new->width = width;
+  new->height = height;
+
+  memset(new->palvec, 0, sizeof(new->palvec));  
+  return new;
+}
+
+void
+flx_colorspace_converter_destroy(FlxColorSpaceConverter *flxpal)
+{
+  g_return_if_fail(flxpal != NULL);
+
+  g_free(flxpal);
+}
+
+void
+flx_colorspace_convert(FlxColorSpaceConverter *flxpal, guchar *src, guchar *dest)
+{
+  guint size, col;
+
+  g_return_if_fail(flxpal != NULL);
+  g_return_if_fail(src != dest);
+
+
+  size = flxpal->width * flxpal->height;
+
+  while(size--) {
+    col     = (*src++ * 3);
+    *dest++ = flxpal->palvec[col+2];
+    *dest++ = flxpal->palvec[col+1];
+    *dest++ = flxpal->palvec[col];
+    *dest++ = 0;
+  }
+
+}
+
+
+void 
+flx_set_palette_vector(FlxColorSpaceConverter *flxpal, guint start, guint num, guchar *newpal)
+{
+  guint  grab;
+  
+  g_return_if_fail(flxpal != NULL);
+  g_return_if_fail(start < 0x100);
+
+  grab = ((start + num) > 0x100 ? 0x100 - start : num);
+
+  memcpy(&flxpal->palvec[start * 3], newpal, grab*3);
+
+}
+
+void
+flx_set_color(FlxColorSpaceConverter *flxpal, guint colr, guint red, guint green, guint blue)
+{
+  
+  g_return_if_fail(flxpal != NULL);
+  g_return_if_fail(colr < 0x100);
+
+  flxpal->palvec[(colr * 3)]     = red;
+  flxpal->palvec[(colr * 3) + 1] = green;
+  flxpal->palvec[(colr * 3) + 2] = blue;
+}
+
+
diff --git a/gst/flx/flx_color.h b/gst/flx/flx_color.h
new file mode 100644 (file)
index 0000000..5676c87
--- /dev/null
@@ -0,0 +1,43 @@
+/* Gnome-Streamer
+ * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
+ *
+ * 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.
+ */
+
+typedef enum {
+  FLX_COLORSPACE_RGB8,
+  FLX_COLORSPACE_RGB32,
+} FlxColorSpaceType;
+
+
+typedef struct _FlxColorSpaceConverter FlxColorSpaceConverter;
+
+struct _FlxColorSpaceConverter {
+  guint      width;
+  guint      height;
+  guchar      palvec[768];
+};
+
+
+void flx_colorspace_converter_destroy(FlxColorSpaceConverter *flxpal);
+void flx_colorspace_convert(FlxColorSpaceConverter *flxpal, guchar *src, guchar *dest);
+FlxColorSpaceConverter * flx_colorspace_converter_new(gint width, gint height);
+
+void flx_set_palette_vector(FlxColorSpaceConverter *flxpal, guint start, guint num, 
+          guchar *newpal);
+void flx_set_color(FlxColorSpaceConverter *flxpal, guint colr, guint red, guint green,
+          guint blue);
+
diff --git a/gst/flx/flx_fmt.h b/gst/flx/flx_fmt.h
new file mode 100644 (file)
index 0000000..5323de6
--- /dev/null
@@ -0,0 +1,136 @@
+/* Gnome-Streamer
+ * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
+ *
+ * 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.
+ */
+
+
+#ifndef __GST_FLX_FMT__H__
+#define __GST_FLX_FMT_H__
+
+#include <gst/gst.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+enum Flx_TypeChunk
+{
+       /* frame chunks */
+       FLX_PREFIX_TYPE = 0xf100,
+       FLX_SCRIPT_CHUNK        = 0xf1e0,
+       FLX_FRAME_TYPE          = 0xf1fa,
+       FLX_SEGMENT_TABLE       = 0xf1fb,
+       FLX_HUFFMAN_TABLE       = 0xf1fc,
+
+       /* sub chunks */
+       FLX_CEL_DATA            = 3,
+       FLX_COLOR256            = 4,
+       FLX_SS2                 = 7,
+        FLX_COLOR64            = 11,
+        FLX_LC                 = 12,
+        FLX_BLACK              = 13,
+        FLX_BRUN               = 15,
+        FLX_COPY               = 16,
+        FLX_MINI               = 18,
+       FLX_DTA_RUN             = 25,
+       FLX_DTA_COPY            = 26,
+       FLX_DTA_LC              = 27,
+       FLX_LABEL               = 31,
+       FLX_BMP_MASK            = 32,
+       FLX_MLEV_MASK           = 33,
+       FLX_SEGMENT             = 34,
+       FLX_KEY_IMAGE           = 35,
+       FLX_KEY_PAL             = 36,
+       FLX_REGION              = 37,
+       FLX_WAVE                = 38,
+       FLX_USERSTRING          = 39,
+       FLX_RGN_MASK            = 40,
+
+};
+
+enum Flx_MagicHdr
+{
+       FLX_MAGICHDR_FLI        = 0xaf11,
+       FLX_MAGICHDR_FLC        = 0xaf12,
+       FLX_MAGICHDR_FLX        = 0xaf44,
+       FLX_MAGICHDR_HUFFBWT    = 0xaf30,
+};
+
+
+
+typedef struct _FlxHeader 
+{
+       guint32 size;
+       guint16 type;
+       guint16 frames;
+       guint16 width,height,depth,flags;
+       guint32 speed;
+       guint16 reserved1;
+       /* FLC */ 
+       guint32 created,creator,updated,updater;
+       guint16 aspect_dx, aspect_dy;
+       /* EGI */
+       guint16 ext_flags,keyframes,totalframes;
+       guint32 req_memory;
+       guint16 max_regions,transp_num;
+       guchar  reserved2[24];
+       /* FLC */
+       guint32 oframe1,oframe2;
+       guchar  reserved3[40];
+} FlxHeader;
+#define FlxHeaderSize 128
+
+typedef struct _FlxFrameChunk
+{
+       guint32 size;
+       guint16 id;
+} FlxFrameChunk;
+#define FlxFrameChunkSize 6
+
+typedef struct _FlxPrefixChunk
+{
+       guint16 chunks;
+       guchar  reserved[8];
+} FlxPrefixChunk;
+
+typedef struct _FlxSegmentTable
+{
+       guint16 segments;
+} FlxSegmentTable;
+
+typedef struct _FlxHuffmanTable
+{
+       guint16 codelength;
+       guint16 numcodes;
+       guchar  reserved[6];
+} FlxHuffmanTable;
+
+typedef struct _FlxFrameType
+{
+       guint16 chunks;
+       guint16 delay;
+       guchar  reserved[6];
+} FlxFrameType;
+#define FlxFrameTypeSize 10
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GST_FLX_FMT_H__ */
diff --git a/gst/flx/gstflxdec.c b/gst/flx/gstflxdec.c
new file mode 100644 (file)
index 0000000..d6052bb
--- /dev/null
@@ -0,0 +1,644 @@
+/* Gnome-Streamer
+ * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
+ *
+ * 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.
+ */
+
+#include <string.h>
+
+#include "flx_fmt.h"
+#include "gstflxdec.h"
+
+static GstCaps* flxdec_typefind(GstBuffer *buf, gpointer private);
+
+/* flx element information */
+static GstElementDetails flxdec_details = {
+  "FLX Decoder",
+  "flxdec",
+  "FLX decoder",
+  VERSION,
+  "Sepp Wijnands <mrrazz@garbage-coderz.net>"
+  "(C) 2001",
+};
+
+static GstTypeDefinition flxdec_definition = {
+  "flxdec_video/fli",
+  "video/fli",
+  ".flc .fli",
+  flxdec_typefind,
+};
+
+/* Flx signals and args */
+enum {
+  /* FILL ME */
+  LAST_SIGNAL
+};
+
+enum {
+  ARG_0
+};
+
+/* input */
+GST_PADTEMPLATE_FACTORY (sink_factory,
+  "sink",          
+  GST_PAD_SINK, 
+  GST_PAD_ALWAYS,
+  GST_CAPS_NEW (
+    "flxdec_sink",         
+    "video/fli",
+     NULL
+  )
+)
+
+/* output */
+GST_PADTEMPLATE_FACTORY (src_video_factory,
+  "src",
+  GST_PAD_SRC,
+  GST_PAD_ALWAYS,
+  GST_CAPS_NEW (
+    "src_video",
+    "video/raw",
+      "format",       GST_PROPS_FOURCC (GST_MAKE_FOURCC ('R', 'G', 'B', ' ')),
+        "bpp",        GST_PROPS_INT (32),
+        "depth",      GST_PROPS_INT (32),
+        "endianness", GST_PROPS_INT (G_LITTLE_ENDIAN),
+        "red_mask",   GST_PROPS_INT (0x00ff0000),
+        "green_mask", GST_PROPS_INT (0x0000ff00),
+        "blue_mask",  GST_PROPS_INT (0x000000ff),
+        "width",      GST_PROPS_INT_RANGE(320, 1280), 
+        "height",     GST_PROPS_INT_RANGE(200, 1024)
+  )
+)
+
+
+static void    gst_flxdec_class_init   (GstFlxDecClass *klass);
+static void    gst_flxdec_init         (GstFlxDec *flxdec);
+
+static void    gst_flxdec_loop         (GstElement *element);
+
+static void    gst_flxdec_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
+static void    gst_flxdec_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
+
+
+static void flx_decode_color(GstFlxDec *, guchar *, guchar *);
+static void flx_decode_brun(GstFlxDec *, guchar *, guchar *);
+static void flx_decode_delta_fli(GstFlxDec *, guchar *, guchar *);
+static void flx_decode_delta_flc(GstFlxDec *, guchar *, guchar *);
+
+#define rndalign(off) ((off) + ((off) % 2))
+
+static GstElementClass *parent_class = NULL;
+
+static GstCaps* 
+flxdec_typefind (GstBuffer *buf, gpointer private)
+{
+  guchar *data = GST_BUFFER_DATA(buf);
+  GstCaps *new;
+
+  // check magic 
+  if ((data[4] == 0x11 || data[4] == 0x12
+       || data[4] == 0x30 || data[4] == 0x44) && data[5] == 0xaf) {
+      // check the frame type of the first frame
+      if ((data[132] == 0x00 || data[132] == 0xfa) && data[133] == 0xf1) {
+        g_print("GstFlxDec: found supported flx format\n");
+        new = gst_caps_new("flxdec_typefind","video/fli", NULL);
+        return new;
+      }
+  }
+  
+  return NULL; 
+}
+
+
+GType
+gst_flxdec_get_type(void) 
+{
+  static GType flxdec_type = 0;
+
+  if (!flxdec_type) {
+    static const GTypeInfo flxdec_info = {
+      sizeof(GstFlxDecClass),      NULL,
+      NULL,
+      (GClassInitFunc)gst_flxdec_class_init,
+      NULL,
+      NULL,
+      sizeof(GstFlxDec),
+      0,
+      (GInstanceInitFunc)gst_flxdec_init,
+    };
+    flxdec_type = g_type_register_static(GST_TYPE_ELEMENT, "GstFlxDec", &flxdec_info, 0);
+  }
+  return flxdec_type;
+}
+
+static void 
+gst_flxdec_class_init (GstFlxDecClass *klass) 
+{
+  GObjectClass *gobject_class;
+  GstElementClass *gstelement_class;
+
+  gobject_class = (GObjectClass*)klass;
+  gstelement_class = (GstElementClass*)klass;
+
+  parent_class = g_type_class_ref(GST_TYPE_ELEMENT);
+
+  gobject_class->set_property = NULL;  
+  gobject_class->get_property = NULL;
+
+}
+
+
+  
+static void 
+gst_flxdec_init(GstFlxDec *flxdec) 
+{
+  flxdec->sinkpad = gst_pad_new_from_template (
+                 GST_PADTEMPLATE_GET (sink_factory), "sink");
+  gst_element_add_pad(GST_ELEMENT(flxdec),flxdec->sinkpad);
+  gst_element_set_loop_function(GST_ELEMENT(flxdec),gst_flxdec_loop);
+
+  flxdec->srcpad = gst_pad_new_from_template (
+                 GST_PADTEMPLATE_GET (src_video_factory), "src");
+  gst_element_add_pad(GST_ELEMENT(flxdec),flxdec->srcpad);
+
+  flxdec->buf = NULL;
+  flxdec->offset = 0;
+  flxdec->new_buf = TRUE;
+
+}
+
+static void
+flx_decode_chunks (GstFlxDec *flxdec , gulong count, gchar *data, gchar *dest)
+{
+  FlxFrameChunk  *hdr;
+
+  g_return_if_fail(data != NULL);
+
+  while (count--) {
+    hdr  = (FlxFrameChunk *) data;
+    data += FlxFrameChunkSize;
+
+    switch(hdr->id) 
+    {
+      case FLX_COLOR64:
+      case FLX_COLOR256:
+        flx_decode_color(flxdec, data, dest);
+        data += rndalign(hdr->size) - FlxFrameChunkSize;
+        break;
+
+      case FLX_BRUN:
+        flx_decode_brun(flxdec, data, dest);
+        data += rndalign(hdr->size) - FlxFrameChunkSize;
+        break;
+
+      case FLX_LC:
+        flx_decode_delta_fli(flxdec, data, dest);
+        data += rndalign(hdr->size) - FlxFrameChunkSize;
+        break;
+
+      case FLX_SS2:
+        flx_decode_delta_flc(flxdec, data, dest);
+        data += rndalign(hdr->size) - FlxFrameChunkSize;
+        break;
+
+      case FLX_BLACK:
+        memset(dest, 0, flxdec->size);
+        break;
+
+      case FLX_MINI:
+        data += rndalign(hdr->size) - FlxFrameChunkSize;
+        break;
+
+      default:
+        g_print("GstFlxDec: Unimplented chunk type: 0x%02x size: %d\n",
+                 hdr->id, hdr->size);
+        g_print("GstFlxDec: Skipping...\n");
+        data += rndalign(hdr->size) - FlxFrameChunkSize;
+        break;
+    }
+  }
+}
+
+
+static void
+flx_decode_color(GstFlxDec *flxdec, guchar *data, guchar *dest)
+{
+  guint packs, count, indx;
+
+  g_return_if_fail(flxdec != NULL);
+
+  packs = (data[0] + (data[1] << 8));
+
+  data += 2;
+  indx  = 0;
+
+  g_print("GstFlxDec: cmap packs: %d\n", packs);
+  while (packs--) {
+    /* color map index + skip count */
+    indx += *data++;
+
+    /* number of rgb triplets */
+    count = *data++ & 0xff;
+    if (count == 0)
+      count = 256;
+
+    g_print("GstFlxDec: cmap count: %d (indx: %d)\n", count, indx);
+    flx_set_palette_vector(flxdec->converter, indx, count, data);
+
+    data += (count * 3);
+  }
+}
+
+static void 
+flx_decode_brun(GstFlxDec *flxdec, guchar *data, guchar *dest)
+{
+  gulong  count, lines, row;
+  guchar  x;
+  
+  g_return_if_fail(flxdec != NULL);
+
+  lines = flxdec->hdr.height;
+  while(lines--) {
+    /* packet count.  
+     * should not be used anymore, since the flc format can
+     * contain more then 255 RLE packets. we use the frame 
+     * width instead. 
+     */
+    data++;
+
+    row = flxdec->hdr.width;
+    while(row) {
+      count = *data++;
+
+      if (count > 0x7f) { 
+        /* literal run */
+        count = 0x100 - count;
+        row -= count;
+
+        while(count--) 
+          *dest++ = *data++;
+        
+      } else {
+        /* replicate run */
+        row -= count;
+        x = *data++;
+
+        while(count--) 
+          *dest++ = x;
+      }
+    }
+  }
+}
+
+static void 
+flx_decode_delta_fli(GstFlxDec *flxdec, guchar *data, guchar *dest)
+{
+  gulong  count, packets, lines, start_line, start_l;
+  guchar  *start_p,  x;
+  
+  g_return_if_fail(flxdec != NULL);
+  g_return_if_fail(flxdec->delta != NULL);
+
+
+  /* use last frame for delta */
+  memcpy(dest, GST_BUFFER_DATA(flxdec->delta), 
+         GST_BUFFER_SIZE(flxdec->delta));
+
+  start_line = (data[0] + (data[1] << 8));
+  lines      = (data[2] + (data[3] << 8));
+  data    += 4;
+
+  /* start position of delta */
+  dest += (flxdec->hdr.width * start_line);
+  start_p = dest;
+  start_l = lines;
+
+  while(lines--) {
+    /* packet count */
+    packets = *data++;
+
+    dest = start_p + (flxdec->hdr.width * (start_l - lines));
+
+    while(packets--) {
+      /* skip count */
+      dest += *data++;
+
+      /* RLE count */
+      count = *data++;
+
+      if (count > 0x7f) { 
+        /* literal run */
+        count = 0x100 - count;
+        x = *data++;
+
+        while (count--)
+          *dest++ = x;
+
+      } else {
+        /* replicate run */
+        while (count--) 
+          *dest++ = *data++;
+      }
+    }
+  }                  
+}
+
+static void 
+flx_decode_delta_flc(GstFlxDec *flxdec, guchar *data, guchar *dest)
+{
+  gulong  count, lines, start_l, opcode;
+  guchar  *start_p;
+  
+  g_return_if_fail(flxdec != NULL);
+  g_return_if_fail(flxdec->delta != NULL);
+
+
+  /* use last frame for delta */
+  memcpy(dest, GST_BUFFER_DATA(flxdec->delta), 
+         GST_BUFFER_SIZE(flxdec->delta));
+
+  lines      = (data[0] + (data[1] << 8));
+  data    += 2;
+
+  start_p    = dest;
+  start_l    = lines;
+
+  while(lines--) {
+    dest = start_p + (flxdec->hdr.width * (start_l - lines));
+
+    /* process opcode(s) */
+    while ((opcode = (data[0] + (data[1] << 8))) & 0xc000) {
+      data += 2;
+      if ((opcode & 0xc000) == 0xc000) {
+        /* skip count */
+        start_l += (0x10000 - opcode);  
+        dest    += flxdec->hdr.width * (0x10000 - opcode);
+      } else {
+        /* last pixel */
+        dest    += flxdec->hdr.width;
+        *dest++  = (opcode & 0xff);
+      }        
+    }
+    data += 2;
+
+    /* last opcode is the packet count */
+    while(opcode--) {
+      /* skip count */
+      dest += *data++;
+  
+      /* RLE count */
+      count = *data++;
+      
+      if (count > 0x7f) {
+        /* replicate word run */
+        count = 0x100 - count;
+        while (count--) {
+          *dest++ = data[0];
+          *dest++ = data[1];
+        }
+        data += 2;
+      } else {
+        /* literal word run */
+        while (count--) {
+          *dest++ = *data++;
+          *dest++ = *data++;
+        }
+      }
+    }
+  }
+}
+          
+static GstBuffer*
+flx_get_data(GstFlxDec *flxdec, gulong size)
+{
+  GstBuffer *retbuf;
+
+  g_return_val_if_fail (flxdec != NULL, NULL);
+
+  if (flxdec->new_buf) {
+    retbuf = gst_pad_pullregion(flxdec->sinkpad, 
+        GST_REGION_OFFSET_LEN, 0, size);
+    flxdec->new_buf = FALSE;
+    flxdec->offset = size;
+  } else {
+    retbuf = gst_pad_pullregion(flxdec->sinkpad, GST_REGION_OFFSET_LEN, 
+        flxdec->offset, size);
+    flxdec->offset += size;
+  }
+
+  return retbuf;
+}
+
+
+static void 
+gst_flxdec_loop (GstElement *element) 
+{
+  GstBuffer  *buf;  
+  GstBuffer  *databuf;
+  guchar     *data, *chunk;
+
+  GstFlxDec         *flxdec;  
+  FlxHeader      *flxh;
+  FlxFrameChunk  *flxfh;
+  
+  g_return_if_fail (element != NULL);
+  g_return_if_fail (GST_IS_FLXDEC(element));
+
+  GST_DEBUG (0, "entering loop function\n");
+  
+  flxdec = GST_FLXDEC(element);
+
+  databuf = flx_get_data(flxdec, FlxHeaderSize);
+
+  g_return_if_fail (databuf != NULL);
+
+  data = GST_BUFFER_DATA(databuf);
+
+  memcpy((char *) &flxdec->hdr, data, sizeof(FlxHeader));
+
+  gst_buffer_unref (databuf);
+
+  flxh = &flxdec->hdr;
+
+  // check header
+  if (flxh->type != FLX_MAGICHDR_FLI &&
+      flxh->type != FLX_MAGICHDR_FLC &&
+      flxh->type != FLX_MAGICHDR_FLX) 
+      return;
+  
+  
+  g_print("GstFlxDec:       size      :  %d\n", flxh->size);
+  g_print("GstFlxDec:       frames    :  %d\n", flxh->frames);
+  g_print("GstFlxDec:       width     :  %d\n", flxh->width);
+  g_print("GstFlxDec:       height    :  %d\n", flxh->height);
+  g_print("GstFlxDec:       depth     :  %d\n", flxh->depth);
+  g_print("GstFlxDec:       speed     :  %d\n", flxh->speed);
+
+  gst_pad_set_caps (flxdec->srcpad,
+               gst_caps_new (
+                 "src_video",
+                 "video/raw",
+                 gst_props_new (
+                   "format",       GST_PROPS_FOURCC (GST_MAKE_FOURCC ('R', 'G', 'B', ' ')),
+                     "bpp",        GST_PROPS_INT (32),
+                     "depth",      GST_PROPS_INT (32),
+                     "endianness", GST_PROPS_INT (G_LITTLE_ENDIAN),
+                     "red_mask",   GST_PROPS_INT (0x00ff0000),
+                     "green_mask", GST_PROPS_INT (0x0000ff00),
+                     "blue_mask",  GST_PROPS_INT (0x000000ff),
+                     "width",      GST_PROPS_INT (flxh->width), 
+                     "height",     GST_PROPS_INT (flxh->height),
+                   NULL)));
+
+  if (flxh->depth <= 8) 
+    flxdec->converter = flx_colorspace_converter_new(flxh->width, flxh->height);
+
+  if (flxh->type == FLX_MAGICHDR_FLC || 
+      flxh->type == FLX_MAGICHDR_FLX) {
+    g_print("GstFlxDec: (FLC) aspect_dx :  %d\n", 
+      flxh->aspect_dx);
+    g_print("GstFlxDec: (FLC) aspect_dy :  %d\n", 
+      flxh->aspect_dy);
+    g_print("GstFlxDec: (FLC) oframe1   :  0x%08x\n", 
+      flxh->oframe1);
+    g_print("GstFlxDec: (FLC) oframe2   :  0x%08x\n", 
+      flxh->oframe2);
+  }
+
+  
+  flxdec->size = (flxh->width * flxh->height);
+  
+  // create delta and output frame 
+  flxdec->frame = gst_buffer_new();
+  flxdec->delta = gst_buffer_new();
+  GST_BUFFER_DATA(flxdec->frame) = g_malloc(flxdec->size);
+  GST_BUFFER_SIZE(flxdec->frame) = flxdec->size;
+  GST_BUFFER_DATA(flxdec->delta) = g_malloc(flxdec->size);
+  GST_BUFFER_SIZE(flxdec->delta) = flxdec->size;
+
+  do
+  {
+
+    databuf = flx_get_data(flxdec, FlxFrameChunkSize);
+
+    flxfh = (FlxFrameChunk *) GST_BUFFER_DATA(databuf);
+    
+    switch(flxfh->id)
+    {
+      case FLX_FRAME_TYPE:
+        buf = flx_get_data(flxdec, flxfh->size-FlxFrameChunkSize);
+        chunk = GST_BUFFER_DATA(buf);
+        if (((FlxFrameType *)chunk)->chunks == 0)
+          break;
+
+        // create 32 bits output frame
+        flxdec->out = gst_buffer_new();
+        GST_BUFFER_DATA(flxdec->out) = g_malloc(flxdec->size * 4);
+        GST_BUFFER_SIZE(flxdec->out) = flxdec->size * 4;
+
+
+        // decode chunks 
+        flx_decode_chunks(flxdec, 
+                         ((FlxFrameType *)chunk)->chunks, 
+                         GST_BUFFER_DATA(buf) + FlxFrameTypeSize,
+                         GST_BUFFER_DATA(flxdec->frame));
+        // destroy input buffer
+        gst_buffer_unref(buf);
+    
+        // save copy of the current frame for possible delta.
+        memcpy(GST_BUFFER_DATA(flxdec->delta), 
+               GST_BUFFER_DATA(flxdec->frame), 
+               GST_BUFFER_SIZE(flxdec->delta));
+
+        // convert current frame.
+        flx_colorspace_convert(flxdec->converter,
+             GST_BUFFER_DATA(flxdec->frame),
+             GST_BUFFER_DATA(flxdec->out));
+
+        //GST_BUFFER_FLAG_SET(flxdec->out, GST_BUFFER_FLUSH);
+        gst_pad_push(flxdec->srcpad, flxdec->out);
+        
+        break;
+    }
+
+    // destroy header buffer 
+    gst_buffer_unref(databuf);
+
+  }
+  while (!GST_ELEMENT_IS_COTHREAD_STOPPING (element));
+
+}
+
+static void 
+gst_flxdec_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) 
+{
+  GstFlxDec *flxdec;
+
+  /* it's not null if we got it, but it might not be ours */
+  g_return_if_fail(GST_IS_FLXDEC(object));
+  flxdec = GST_FLXDEC(object);
+
+  switch (prop_id) {
+    default:
+      break;
+  }
+}
+
+static void 
+gst_flxdec_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) 
+{
+  GstFlxDec *flxdec;
+
+  /* it's not null if we got it, but it might not be ours */
+  g_return_if_fail(GST_IS_FLXDEC(object));
+  flxdec = GST_FLXDEC(object);
+
+  switch (prop_id) {
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static gboolean
+plugin_init (GModule *module, GstPlugin *plugin)
+{
+  GstElementFactory *factory;
+  GstTypeFactory *type;
+
+  factory = gst_elementfactory_new("flxdec", GST_TYPE_FLXDEC, &flxdec_details);
+  g_return_val_if_fail(factory != NULL, FALSE);
+
+  gst_elementfactory_add_padtemplate (factory, GST_PADTEMPLATE_GET (sink_factory));
+  gst_elementfactory_add_padtemplate (factory, GST_PADTEMPLATE_GET (src_video_factory));
+
+  gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (factory));
+
+  type = gst_typefactory_new (&flxdec_definition);
+  gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (type));
+
+  return TRUE;
+}
+
+GstPluginDesc plugin_desc = {
+  GST_VERSION_MAJOR,
+  GST_VERSION_MINOR,
+  "flxdec",
+  plugin_init
+};
diff --git a/gst/flx/gstflxdec.h b/gst/flx/gstflxdec.h
new file mode 100644 (file)
index 0000000..cc4c94d
--- /dev/null
@@ -0,0 +1,79 @@
+/* Gnome-Streamer
+ * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
+ *
+ * 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.
+ */
+
+#ifndef __GST_FLX_DECODER_H__
+#define __GST_FLX_DECODER_H__
+
+#include <gst/gst.h>
+
+#include "flx_color.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+/* Definition of structure storing data for this element. */
+typedef struct _GstFlxDec  GstFlxDec;
+struct _GstFlxDec {
+  GstElement element;
+
+  GstPad *sinkpad,*srcpad;
+
+  gboolean active, new_meta, new_buf;
+
+  GstBuffer *buf, *out, *delta, *frame;
+  gulong offset, size;
+
+  FlxColorSpaceConverter *converter;
+
+  FlxHeader hdr;
+};
+
+/* Standard definition defining a class for this element. */
+typedef struct _GstFlxDecClass GstFlxDecClass;
+struct _GstFlxDecClass {
+  GstElementClass parent_class;
+};
+
+/* Standard macros for defining types for this element.  */
+#define GST_TYPE_FLXDEC \
+  (gst_flxdec_get_type())
+#define GST_FLXDEC(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_FLXDEC,GstFlxDec))
+#define GST_FLXDEC_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_FLXDEC,GstFlxDec))
+#define GST_IS_FLXDEC(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_FLXDEC))
+#define GST_IS_FLXDEC_CLASS(obj) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_FLXDEC))
+
+#define FLXDEC_BUFSIZE(buf, offset) \
+  ((GST_BUFFER_OFFSET(buf) + GST_BUFFER_SIZE(buf)) - offset)
+
+/* Standard function returning type information. */
+GType gst_flxdec_get_type(void);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GST_FLX_DECODER_H__ */
diff --git a/gst/law/Makefile.am b/gst/law/Makefile.am
new file mode 100644 (file)
index 0000000..76a73f7
--- /dev/null
@@ -0,0 +1,12 @@
+filterdir = $(libdir)/gst
+
+filter_LTLIBRARIES = libgstalaw.la libgstmulaw.la
+
+libgstalaw_la_SOURCES = alaw-encode.c mulaw-conversion.c alaw-conversion.c alaw-decode.c alaw.c
+libgstalaw_la_CFLAGS = $(GST_CFLAGS)
+
+libgstmulaw_la_SOURCES = mulaw-encode.c mulaw-conversion.c mulaw-decode.c mulaw.c
+libgstmulaw_la_CFLAGS = $(GST_CFLAGS)
+
+noinst_HEADERS = mulaw-conversion.h alaw-encode.h alaw-decode.h alaw-conversion.h mulaw-encode.h mulaw-decode.h
+filterdir = $(libdir)/gst
diff --git a/gst/law/alaw-conversion.c b/gst/law/alaw-conversion.c
new file mode 100644 (file)
index 0000000..cb3be3e
--- /dev/null
@@ -0,0 +1,195 @@
+/* $Id$
+
+ * Linux ISDN subsystem, audio conversion and compression (linklevel).
+ *
+ * Copyright 1994-1999 by Fritz Elfert (fritz@isdn4linux.de)
+ * DTMF code (c) 1996 by Christian Mock (cm@kukuruz.ping.at)
+ * Silence detection (c) 1998 by Armin Schindler (mac@gismo.telekom.de)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <glib.h>
+/*
+ * Misc. lookup-tables.
+ */
+
+/* ulaw -> signed 16-bit */
+static gint16 isdn_audio_ulaw_to_s16[] =
+{
+       0x8284, 0x8684, 0x8a84, 0x8e84, 0x9284, 0x9684, 0x9a84, 0x9e84,
+       0xa284, 0xa684, 0xaa84, 0xae84, 0xb284, 0xb684, 0xba84, 0xbe84,
+       0xc184, 0xc384, 0xc584, 0xc784, 0xc984, 0xcb84, 0xcd84, 0xcf84,
+       0xd184, 0xd384, 0xd584, 0xd784, 0xd984, 0xdb84, 0xdd84, 0xdf84,
+       0xe104, 0xe204, 0xe304, 0xe404, 0xe504, 0xe604, 0xe704, 0xe804,
+       0xe904, 0xea04, 0xeb04, 0xec04, 0xed04, 0xee04, 0xef04, 0xf004,
+       0xf0c4, 0xf144, 0xf1c4, 0xf244, 0xf2c4, 0xf344, 0xf3c4, 0xf444,
+       0xf4c4, 0xf544, 0xf5c4, 0xf644, 0xf6c4, 0xf744, 0xf7c4, 0xf844,
+       0xf8a4, 0xf8e4, 0xf924, 0xf964, 0xf9a4, 0xf9e4, 0xfa24, 0xfa64,
+       0xfaa4, 0xfae4, 0xfb24, 0xfb64, 0xfba4, 0xfbe4, 0xfc24, 0xfc64,
+       0xfc94, 0xfcb4, 0xfcd4, 0xfcf4, 0xfd14, 0xfd34, 0xfd54, 0xfd74,
+       0xfd94, 0xfdb4, 0xfdd4, 0xfdf4, 0xfe14, 0xfe34, 0xfe54, 0xfe74,
+       0xfe8c, 0xfe9c, 0xfeac, 0xfebc, 0xfecc, 0xfedc, 0xfeec, 0xfefc,
+       0xff0c, 0xff1c, 0xff2c, 0xff3c, 0xff4c, 0xff5c, 0xff6c, 0xff7c,
+       0xff88, 0xff90, 0xff98, 0xffa0, 0xffa8, 0xffb0, 0xffb8, 0xffc0,
+       0xffc8, 0xffd0, 0xffd8, 0xffe0, 0xffe8, 0xfff0, 0xfff8, 0x0000,
+       0x7d7c, 0x797c, 0x757c, 0x717c, 0x6d7c, 0x697c, 0x657c, 0x617c,
+       0x5d7c, 0x597c, 0x557c, 0x517c, 0x4d7c, 0x497c, 0x457c, 0x417c,
+       0x3e7c, 0x3c7c, 0x3a7c, 0x387c, 0x367c, 0x347c, 0x327c, 0x307c,
+       0x2e7c, 0x2c7c, 0x2a7c, 0x287c, 0x267c, 0x247c, 0x227c, 0x207c,
+       0x1efc, 0x1dfc, 0x1cfc, 0x1bfc, 0x1afc, 0x19fc, 0x18fc, 0x17fc,
+       0x16fc, 0x15fc, 0x14fc, 0x13fc, 0x12fc, 0x11fc, 0x10fc, 0x0ffc,
+       0x0f3c, 0x0ebc, 0x0e3c, 0x0dbc, 0x0d3c, 0x0cbc, 0x0c3c, 0x0bbc,
+       0x0b3c, 0x0abc, 0x0a3c, 0x09bc, 0x093c, 0x08bc, 0x083c, 0x07bc,
+       0x075c, 0x071c, 0x06dc, 0x069c, 0x065c, 0x061c, 0x05dc, 0x059c,
+       0x055c, 0x051c, 0x04dc, 0x049c, 0x045c, 0x041c, 0x03dc, 0x039c,
+       0x036c, 0x034c, 0x032c, 0x030c, 0x02ec, 0x02cc, 0x02ac, 0x028c,
+       0x026c, 0x024c, 0x022c, 0x020c, 0x01ec, 0x01cc, 0x01ac, 0x018c,
+       0x0174, 0x0164, 0x0154, 0x0144, 0x0134, 0x0124, 0x0114, 0x0104,
+       0x00f4, 0x00e4, 0x00d4, 0x00c4, 0x00b4, 0x00a4, 0x0094, 0x0084,
+       0x0078, 0x0070, 0x0068, 0x0060, 0x0058, 0x0050, 0x0048, 0x0040,
+       0x0038, 0x0030, 0x0028, 0x0020, 0x0018, 0x0010, 0x0008, 0x0000
+};
+
+/* alaw -> signed 16-bit */
+static gint16 isdn_audio_alaw_to_s16[] =
+{
+       0x13fc, 0xec04, 0x0144, 0xfebc, 0x517c, 0xae84, 0x051c, 0xfae4,
+       0x0a3c, 0xf5c4, 0x0048, 0xffb8, 0x287c, 0xd784, 0x028c, 0xfd74,
+       0x1bfc, 0xe404, 0x01cc, 0xfe34, 0x717c, 0x8e84, 0x071c, 0xf8e4,
+       0x0e3c, 0xf1c4, 0x00c4, 0xff3c, 0x387c, 0xc784, 0x039c, 0xfc64,
+       0x0ffc, 0xf004, 0x0104, 0xfefc, 0x417c, 0xbe84, 0x041c, 0xfbe4,
+       0x083c, 0xf7c4, 0x0008, 0xfff8, 0x207c, 0xdf84, 0x020c, 0xfdf4,
+       0x17fc, 0xe804, 0x018c, 0xfe74, 0x617c, 0x9e84, 0x061c, 0xf9e4,
+       0x0c3c, 0xf3c4, 0x0084, 0xff7c, 0x307c, 0xcf84, 0x030c, 0xfcf4,
+       0x15fc, 0xea04, 0x0164, 0xfe9c, 0x597c, 0xa684, 0x059c, 0xfa64,
+       0x0b3c, 0xf4c4, 0x0068, 0xff98, 0x2c7c, 0xd384, 0x02cc, 0xfd34,
+       0x1dfc, 0xe204, 0x01ec, 0xfe14, 0x797c, 0x8684, 0x07bc, 0xf844,
+       0x0f3c, 0xf0c4, 0x00e4, 0xff1c, 0x3c7c, 0xc384, 0x03dc, 0xfc24,
+       0x11fc, 0xee04, 0x0124, 0xfedc, 0x497c, 0xb684, 0x049c, 0xfb64,
+       0x093c, 0xf6c4, 0x0028, 0xffd8, 0x247c, 0xdb84, 0x024c, 0xfdb4,
+       0x19fc, 0xe604, 0x01ac, 0xfe54, 0x697c, 0x9684, 0x069c, 0xf964,
+       0x0d3c, 0xf2c4, 0x00a4, 0xff5c, 0x347c, 0xcb84, 0x034c, 0xfcb4,
+       0x12fc, 0xed04, 0x0134, 0xfecc, 0x4d7c, 0xb284, 0x04dc, 0xfb24,
+       0x09bc, 0xf644, 0x0038, 0xffc8, 0x267c, 0xd984, 0x026c, 0xfd94,
+       0x1afc, 0xe504, 0x01ac, 0xfe54, 0x6d7c, 0x9284, 0x06dc, 0xf924,
+       0x0dbc, 0xf244, 0x00b4, 0xff4c, 0x367c, 0xc984, 0x036c, 0xfc94,
+       0x0f3c, 0xf0c4, 0x00f4, 0xff0c, 0x3e7c, 0xc184, 0x03dc, 0xfc24,
+       0x07bc, 0xf844, 0x0008, 0xfff8, 0x1efc, 0xe104, 0x01ec, 0xfe14,
+       0x16fc, 0xe904, 0x0174, 0xfe8c, 0x5d7c, 0xa284, 0x05dc, 0xfa24,
+       0x0bbc, 0xf444, 0x0078, 0xff88, 0x2e7c, 0xd184, 0x02ec, 0xfd14,
+       0x14fc, 0xeb04, 0x0154, 0xfeac, 0x557c, 0xaa84, 0x055c, 0xfaa4,
+       0x0abc, 0xf544, 0x0058, 0xffa8, 0x2a7c, 0xd584, 0x02ac, 0xfd54,
+       0x1cfc, 0xe304, 0x01cc, 0xfe34, 0x757c, 0x8a84, 0x075c, 0xf8a4,
+       0x0ebc, 0xf144, 0x00d4, 0xff2c, 0x3a7c, 0xc584, 0x039c, 0xfc64,
+       0x10fc, 0xef04, 0x0114, 0xfeec, 0x457c, 0xba84, 0x045c, 0xfba4,
+       0x08bc, 0xf744, 0x0018, 0xffe8, 0x227c, 0xdd84, 0x022c, 0xfdd4,
+       0x18fc, 0xe704, 0x018c, 0xfe74, 0x657c, 0x9a84, 0x065c, 0xf9a4,
+       0x0cbc, 0xf344, 0x0094, 0xff6c, 0x327c, 0xcd84, 0x032c, 0xfcd4
+};
+
+/* alaw -> ulaw */
+static guint8 isdn_audio_alaw_to_ulaw[] =
+{
+       0xab, 0x2b, 0xe3, 0x63, 0x8b, 0x0b, 0xc9, 0x49,
+       0xba, 0x3a, 0xf6, 0x76, 0x9b, 0x1b, 0xd7, 0x57,
+       0xa3, 0x23, 0xdd, 0x5d, 0x83, 0x03, 0xc1, 0x41,
+       0xb2, 0x32, 0xeb, 0x6b, 0x93, 0x13, 0xcf, 0x4f,
+       0xaf, 0x2f, 0xe7, 0x67, 0x8f, 0x0f, 0xcd, 0x4d,
+       0xbe, 0x3e, 0xfe, 0x7e, 0x9f, 0x1f, 0xdb, 0x5b,
+       0xa7, 0x27, 0xdf, 0x5f, 0x87, 0x07, 0xc5, 0x45,
+       0xb6, 0x36, 0xef, 0x6f, 0x97, 0x17, 0xd3, 0x53,
+       0xa9, 0x29, 0xe1, 0x61, 0x89, 0x09, 0xc7, 0x47,
+       0xb8, 0x38, 0xf2, 0x72, 0x99, 0x19, 0xd5, 0x55,
+       0xa1, 0x21, 0xdc, 0x5c, 0x81, 0x01, 0xbf, 0x3f,
+       0xb0, 0x30, 0xe9, 0x69, 0x91, 0x11, 0xce, 0x4e,
+       0xad, 0x2d, 0xe5, 0x65, 0x8d, 0x0d, 0xcb, 0x4b,
+       0xbc, 0x3c, 0xfa, 0x7a, 0x9d, 0x1d, 0xd9, 0x59,
+       0xa5, 0x25, 0xde, 0x5e, 0x85, 0x05, 0xc3, 0x43,
+       0xb4, 0x34, 0xed, 0x6d, 0x95, 0x15, 0xd1, 0x51,
+       0xac, 0x2c, 0xe4, 0x64, 0x8c, 0x0c, 0xca, 0x4a,
+       0xbb, 0x3b, 0xf8, 0x78, 0x9c, 0x1c, 0xd8, 0x58,
+       0xa4, 0x24, 0xde, 0x5e, 0x84, 0x04, 0xc2, 0x42,
+       0xb3, 0x33, 0xec, 0x6c, 0x94, 0x14, 0xd0, 0x50,
+       0xb0, 0x30, 0xe8, 0x68, 0x90, 0x10, 0xce, 0x4e,
+       0xbf, 0x3f, 0xfe, 0x7e, 0xa0, 0x20, 0xdc, 0x5c,
+       0xa8, 0x28, 0xe0, 0x60, 0x88, 0x08, 0xc6, 0x46,
+       0xb7, 0x37, 0xf0, 0x70, 0x98, 0x18, 0xd4, 0x54,
+       0xaa, 0x2a, 0xe2, 0x62, 0x8a, 0x0a, 0xc8, 0x48,
+       0xb9, 0x39, 0xf4, 0x74, 0x9a, 0x1a, 0xd6, 0x56,
+       0xa2, 0x22, 0xdd, 0x5d, 0x82, 0x02, 0xc0, 0x40,
+       0xb1, 0x31, 0xea, 0x6a, 0x92, 0x12, 0xcf, 0x4f,
+       0xae, 0x2e, 0xe6, 0x66, 0x8e, 0x0e, 0xcc, 0x4c,
+       0xbd, 0x3d, 0xfc, 0x7c, 0x9e, 0x1e, 0xda, 0x5a,
+       0xa6, 0x26, 0xdf, 0x5f, 0x86, 0x06, 0xc4, 0x44,
+       0xb5, 0x35, 0xee, 0x6e, 0x96, 0x16, 0xd2, 0x52
+};
+
+/* ulaw -> alaw */
+static guint8 isdn_audio_ulaw_to_alaw[] =
+{
+       0xab, 0x55, 0xd5, 0x15, 0x95, 0x75, 0xf5, 0x35,
+       0xb5, 0x45, 0xc5, 0x05, 0x85, 0x65, 0xe5, 0x25,
+       0xa5, 0x5d, 0xdd, 0x1d, 0x9d, 0x7d, 0xfd, 0x3d,
+       0xbd, 0x4d, 0xcd, 0x0d, 0x8d, 0x6d, 0xed, 0x2d,
+       0xad, 0x51, 0xd1, 0x11, 0x91, 0x71, 0xf1, 0x31,
+       0xb1, 0x41, 0xc1, 0x01, 0x81, 0x61, 0xe1, 0x21,
+       0x59, 0xd9, 0x19, 0x99, 0x79, 0xf9, 0x39, 0xb9,
+       0x49, 0xc9, 0x09, 0x89, 0x69, 0xe9, 0x29, 0xa9,
+       0xd7, 0x17, 0x97, 0x77, 0xf7, 0x37, 0xb7, 0x47,
+       0xc7, 0x07, 0x87, 0x67, 0xe7, 0x27, 0xa7, 0xdf,
+       0x9f, 0x7f, 0xff, 0x3f, 0xbf, 0x4f, 0xcf, 0x0f,
+       0x8f, 0x6f, 0xef, 0x2f, 0x53, 0x13, 0x73, 0x33,
+       0xb3, 0x43, 0xc3, 0x03, 0x83, 0x63, 0xe3, 0x23,
+       0xa3, 0x5b, 0xdb, 0x1b, 0x9b, 0x7b, 0xfb, 0x3b,
+       0xbb, 0xbb, 0x4b, 0x4b, 0xcb, 0xcb, 0x0b, 0x0b,
+       0x8b, 0x8b, 0x6b, 0x6b, 0xeb, 0xeb, 0x2b, 0x2b,
+       0xab, 0x54, 0xd4, 0x14, 0x94, 0x74, 0xf4, 0x34,
+       0xb4, 0x44, 0xc4, 0x04, 0x84, 0x64, 0xe4, 0x24,
+       0xa4, 0x5c, 0xdc, 0x1c, 0x9c, 0x7c, 0xfc, 0x3c,
+       0xbc, 0x4c, 0xcc, 0x0c, 0x8c, 0x6c, 0xec, 0x2c,
+       0xac, 0x50, 0xd0, 0x10, 0x90, 0x70, 0xf0, 0x30,
+       0xb0, 0x40, 0xc0, 0x00, 0x80, 0x60, 0xe0, 0x20,
+       0x58, 0xd8, 0x18, 0x98, 0x78, 0xf8, 0x38, 0xb8,
+       0x48, 0xc8, 0x08, 0x88, 0x68, 0xe8, 0x28, 0xa8,
+       0xd6, 0x16, 0x96, 0x76, 0xf6, 0x36, 0xb6, 0x46,
+       0xc6, 0x06, 0x86, 0x66, 0xe6, 0x26, 0xa6, 0xde,
+       0x9e, 0x7e, 0xfe, 0x3e, 0xbe, 0x4e, 0xce, 0x0e,
+       0x8e, 0x6e, 0xee, 0x2e, 0x52, 0x12, 0x72, 0x32,
+       0xb2, 0x42, 0xc2, 0x02, 0x82, 0x62, 0xe2, 0x22,
+       0xa2, 0x5a, 0xda, 0x1a, 0x9a, 0x7a, 0xfa, 0x3a,
+       0xba, 0xba, 0x4a, 0x4a, 0xca, 0xca, 0x0a, 0x0a,
+       0x8a, 0x8a, 0x6a, 0x6a, 0xea, 0xea, 0x2a, 0x2a
+};
+
+static inline void
+isdn_audio_tlookup(const guint8 *table, guint8 *buff, gulong n)
+{
+       while (n--)
+               *buff++ = table[*(unsigned char *)buff];
+}
+
+void
+isdn_audio_ulaw2alaw(guint8 *buff, gulong len)
+{
+       isdn_audio_tlookup(isdn_audio_ulaw_to_alaw, buff, len);
+}
+
+void
+isdn_audio_alaw2ulaw(guint8 *buff, gulong len)
+{
+       isdn_audio_tlookup(isdn_audio_alaw_to_ulaw, buff, len);
+}
diff --git a/gst/law/alaw-conversion.h b/gst/law/alaw-conversion.h
new file mode 100644 (file)
index 0000000..b7d1297
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef _GST_ALAW_CONVERSION_H
+#define _GST_ALAW_CONVERSION_H
+
+#include <glib.h>
+
+void
+isdn_audio_ulaw2alaw(guint8 *buff, gulong len);
+
+void
+isdn_audio_alaw2ulaw(guint8 *buff, gulong len);
+
+#endif
diff --git a/gst/law/alaw-decode.c b/gst/law/alaw-decode.c
new file mode 100644 (file)
index 0000000..872d533
--- /dev/null
@@ -0,0 +1,186 @@
+/* Gnome-Streamer
+ * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
+ *
+ * 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.
+ */
+
+#include <gst/gst.h>
+#include "alaw-decode.h"
+#include "mulaw-conversion.h"
+#include "alaw-conversion.h"
+
+extern GstPadTemplate *alawdec_src_template, *alawdec_sink_template;
+
+
+/* Stereo signals and args */
+enum {
+  /* FILL ME */
+  LAST_SIGNAL
+};
+
+enum {
+  ARG_0
+};
+
+static void            gst_alawdec_class_init          (GstALawDecClass *klass);
+static void            gst_alawdec_init                        (GstALawDec *alawdec);
+
+static void            gst_alawdec_set_property                        (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
+static void            gst_alawdec_get_property                        (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
+
+static void            gst_alawdec_chain                       (GstPad *pad, GstBuffer *buf);
+
+
+static GstElementClass *parent_class = NULL;
+//static guint gst_stereo_signals[LAST_SIGNAL] = { 0 };
+
+static GstPadNegotiateReturn
+alawdec_negotiate_sink (GstPad *pad, GstCaps **caps, gint counter)
+{
+  GstCaps* tempcaps;
+  
+  GstALawDec* alawdec=GST_ALAWDEC (GST_OBJECT_PARENT (pad));
+  
+  if (*caps==NULL) 
+    return GST_PAD_NEGOTIATE_FAIL;
+
+  tempcaps = gst_caps_copy(*caps);
+
+  gst_caps_set(tempcaps,"format",GST_PROPS_STRING("int"));
+  gst_caps_set(tempcaps,"law",GST_PROPS_INT(0));
+  gst_caps_set(tempcaps,"depth",GST_PROPS_INT(16));
+  gst_caps_set(tempcaps,"width",GST_PROPS_INT(16));
+  gst_caps_set(tempcaps,"signed",GST_PROPS_BOOLEAN(TRUE));
+
+  if (gst_pad_set_caps (alawdec->srcpad, tempcaps))
+  {
+    return GST_PAD_NEGOTIATE_AGREE;
+  }
+  else {
+    gst_caps_unref (tempcaps);
+    return GST_PAD_NEGOTIATE_FAIL;
+  }
+}              
+
+GType
+gst_alawdec_get_type(void) {
+  static GType alawdec_type = 0;
+
+  if (!alawdec_type) {
+    static const GTypeInfo alawdec_info = {
+      sizeof(GstALawDecClass),      NULL,
+      NULL,
+      (GClassInitFunc)gst_alawdec_class_init,
+      NULL,
+      NULL,
+      sizeof(GstALawDec),
+      0,
+      (GInstanceInitFunc)gst_alawdec_init,
+    };
+    alawdec_type = g_type_register_static(GST_TYPE_ELEMENT, "GstALawDec", &alawdec_info, 0);
+  }
+  return alawdec_type;
+}
+
+static void
+gst_alawdec_class_init (GstALawDecClass *klass)
+{
+  GObjectClass *gobject_class;
+  GstElementClass *gstelement_class;
+
+  gobject_class = (GObjectClass*)klass;
+  gstelement_class = (GstElementClass*)klass;
+
+  parent_class = g_type_class_ref(GST_TYPE_ELEMENT);
+
+  gobject_class->set_property = gst_alawdec_set_property;
+  gobject_class->get_property = gst_alawdec_get_property;
+}
+
+static void
+gst_alawdec_init (GstALawDec *alawdec)
+{
+  alawdec->sinkpad = gst_pad_new_from_template(alawdec_sink_template,"sink");
+  alawdec->srcpad = gst_pad_new_from_template(alawdec_src_template,"src");
+  gst_pad_set_negotiate_function(alawdec->sinkpad, alawdec_negotiate_sink);
+
+  gst_element_add_pad(GST_ELEMENT(alawdec),alawdec->sinkpad);
+  gst_pad_set_chain_function(alawdec->sinkpad,gst_alawdec_chain);
+  gst_element_add_pad(GST_ELEMENT(alawdec),alawdec->srcpad);
+}
+
+static void
+gst_alawdec_chain (GstPad *pad,GstBuffer *buf)
+{
+  GstALawDec *alawdec;
+  gint16 *linear_data;
+  guint8 *alaw_data;
+  GstBuffer* outbuf;
+
+  g_return_if_fail(pad != NULL);
+  g_return_if_fail(GST_IS_PAD(pad));
+  g_return_if_fail(buf != NULL);
+
+  alawdec = GST_ALAWDEC(GST_OBJECT_PARENT (pad));
+  g_return_if_fail(alawdec != NULL);
+  g_return_if_fail(GST_IS_ALAWDEC(alawdec));
+
+  alaw_data = (guint8 *)GST_BUFFER_DATA(buf);
+  outbuf=gst_buffer_new();
+  GST_BUFFER_DATA(outbuf) = (gchar*)g_new(gint16,GST_BUFFER_SIZE(buf));
+  GST_BUFFER_SIZE(outbuf) = GST_BUFFER_SIZE(buf)*2;
+
+  linear_data = (gint16*)GST_BUFFER_DATA(outbuf);
+
+  isdn_audio_alaw2ulaw(alaw_data,GST_BUFFER_SIZE(buf));
+  mulaw_decode(alaw_data,linear_data,GST_BUFFER_SIZE(buf));
+  
+  gst_buffer_unref(buf);
+  gst_pad_push(alawdec->srcpad,outbuf);
+}
+
+static void
+gst_alawdec_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
+{
+  GstALawDec *alawdec;
+
+  /* it's not null if we got it, but it might not be ours */
+  g_return_if_fail(GST_IS_ALAWDEC(object));
+  alawdec = GST_ALAWDEC(object);
+
+  switch (prop_id) {
+    default:
+      break;
+  }
+}
+
+static void
+gst_alawdec_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
+{
+  GstALawDec *alawdec;
+
+  /* it's not null if we got it, but it might not be ours */
+  g_return_if_fail(GST_IS_ALAWDEC(object));
+  alawdec = GST_ALAWDEC(object);
+
+  switch (prop_id) {
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+
diff --git a/gst/law/alaw-decode.h b/gst/law/alaw-decode.h
new file mode 100644 (file)
index 0000000..f487009
--- /dev/null
@@ -0,0 +1,69 @@
+/* Gnome-Streamer
+ * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
+ *
+ * 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.
+ */
+
+
+#ifndef __GST_ALAWDECODE_H__
+#define __GST_ALAWDECODE_H__
+
+
+#include <config.h>
+#include <gst/gst.h>
+// #include <gst/meta/audioraw.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define GST_TYPE_ALAWDEC \
+  (gst_alawdec_get_type())
+#define GST_ALAWDEC(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_ALAWDEC,GstALawDec))
+#define GST_ALAWDEC_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_ALAWDEC,GstALawDec))
+#define GST_IS_ALAWDEC(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_ALAWDEC))
+#define GST_IS_ALAWDEC_CLASS(obj) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_ALAWDEC))
+
+typedef struct _GstALawDec GstALawDec;
+typedef struct _GstALawDecClass GstALawDecClass;
+
+struct _GstALawDec {
+  GstElement element;
+
+  GstPad *sinkpad,*srcpad;
+
+  //MetaAudioRaw meta;
+
+};
+
+struct _GstALawDecClass {
+  GstElementClass parent_class;
+};
+
+GType gst_alawdec_get_type(void);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GST_STEREO_H__ */
diff --git a/gst/law/alaw-encode.c b/gst/law/alaw-encode.c
new file mode 100644 (file)
index 0000000..ab54bd1
--- /dev/null
@@ -0,0 +1,182 @@
+/* Gnome-Streamer
+ * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
+ *
+ * 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.
+ */
+
+#include <gst/gst.h>
+#include "alaw-encode.h"
+#include "mulaw-conversion.h"
+#include "alaw-conversion.h"
+
+extern GstPadTemplate *alawenc_src_template, *alawenc_sink_template;
+
+
+/* Stereo signals and args */
+enum {
+  /* FILL ME */
+  LAST_SIGNAL
+};
+
+enum {
+  ARG_0
+};
+
+static void            gst_alawenc_class_init          (GstALawEncClass *klass);
+static void            gst_alawenc_init                        (GstALawEnc *alawenc);
+
+static void            gst_alawenc_set_property                        (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
+static void            gst_alawenc_get_property                        (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
+
+static void            gst_alawenc_chain                       (GstPad *pad, GstBuffer *buf);
+
+
+static GstElementClass *parent_class = NULL;
+//static guint gst_stereo_signals[LAST_SIGNAL] = { 0 };
+
+static GstPadNegotiateReturn
+alawenc_negotiate_sink (GstPad *pad, GstCaps **caps, gint counter)
+{
+  GstCaps* tempcaps;
+  
+  GstALawEnc* alawenc=GST_ALAWENC (GST_OBJECT_PARENT (pad));
+  
+  if (*caps==NULL) 
+    return GST_PAD_NEGOTIATE_FAIL;
+
+  tempcaps = gst_caps_copy(*caps);
+
+  gst_caps_set(tempcaps,"format",GST_PROPS_STRING("int"));
+  gst_caps_set(tempcaps,"law",GST_PROPS_INT(2));
+  gst_caps_set(tempcaps,"depth",GST_PROPS_INT(8));
+  gst_caps_set(tempcaps,"width",GST_PROPS_INT(8));
+  gst_caps_set(tempcaps,"signed",GST_PROPS_BOOLEAN(FALSE));
+
+  if (gst_pad_set_caps (alawenc->srcpad, tempcaps))
+  {
+    return GST_PAD_NEGOTIATE_AGREE;
+  }
+  else {
+    gst_caps_unref (tempcaps);
+    return GST_PAD_NEGOTIATE_FAIL;
+  }
+}              
+
+GType
+gst_alawenc_get_type(void) {
+  static GType alawenc_type = 0;
+
+  if (!alawenc_type) {
+    static const GTypeInfo alawenc_info = {
+      sizeof(GstALawEncClass),      NULL,
+      NULL,
+      (GClassInitFunc)gst_alawenc_class_init,
+      NULL,
+      NULL,
+      sizeof(GstALawEnc),
+      0,
+      (GInstanceInitFunc)gst_alawenc_init,
+    };
+    alawenc_type = g_type_register_static(GST_TYPE_ELEMENT, "GstALawEnc", &alawenc_info, 0);
+  }
+  return alawenc_type;
+}
+
+static void
+gst_alawenc_class_init (GstALawEncClass *klass)
+{
+  GObjectClass *gobject_class;
+  GstElementClass *gstelement_class;
+
+  gobject_class = (GObjectClass*)klass;
+  gstelement_class = (GstElementClass*)klass;
+
+  parent_class = g_type_class_ref(GST_TYPE_ELEMENT);
+
+  gobject_class->set_property = gst_alawenc_set_property;
+  gobject_class->get_property = gst_alawenc_get_property;
+}
+
+static void
+gst_alawenc_init (GstALawEnc *alawenc)
+{
+  alawenc->sinkpad = gst_pad_new_from_template(alawenc_sink_template,"sink");
+  alawenc->srcpad = gst_pad_new_from_template(alawenc_src_template,"src");
+  gst_pad_set_negotiate_function(alawenc->sinkpad, alawenc_negotiate_sink);
+
+  gst_element_add_pad(GST_ELEMENT(alawenc),alawenc->sinkpad);
+  gst_pad_set_chain_function(alawenc->sinkpad,gst_alawenc_chain);
+  gst_element_add_pad(GST_ELEMENT(alawenc),alawenc->srcpad);
+}
+
+static void
+gst_alawenc_chain (GstPad *pad,GstBuffer *buf)
+{
+  GstALawEnc *alawenc;
+  gint16 *linear_data;
+  guint8 *alaw_data;
+  GstBuffer* outbuf;
+
+  g_return_if_fail(pad != NULL);
+  g_return_if_fail(GST_IS_PAD(pad));
+  g_return_if_fail(buf != NULL);
+
+  alawenc = GST_ALAWENC(GST_OBJECT_PARENT (pad));
+  g_return_if_fail(alawenc != NULL);
+  g_return_if_fail(GST_IS_ALAWENC(alawenc));
+
+  linear_data = (gint16 *)GST_BUFFER_DATA(buf);
+  outbuf=gst_buffer_new();
+  GST_BUFFER_DATA(outbuf) = (gchar*)g_new(gint16,GST_BUFFER_SIZE(buf)/4);
+  GST_BUFFER_SIZE(outbuf) = GST_BUFFER_SIZE(buf)/2;
+
+  alaw_data = (guint8*)GST_BUFFER_DATA(outbuf);
+  mulaw_encode(linear_data,alaw_data,GST_BUFFER_SIZE(outbuf));
+  isdn_audio_ulaw2alaw(alaw_data,GST_BUFFER_SIZE(outbuf));
+  gst_buffer_unref(buf);
+  gst_pad_push(alawenc->srcpad,outbuf);
+}
+
+static void
+gst_alawenc_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
+{
+  GstALawEnc *alawenc;
+
+  /* it's not null if we got it, but it might not be ours */
+  g_return_if_fail(GST_IS_ALAWENC(object));
+  alawenc = GST_ALAWENC(object);
+
+  switch (prop_id) {
+    default:
+      break;
+  }
+}
+
+static void
+gst_alawenc_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
+{
+  GstALawEnc *alawenc;
+
+  /* it's not null if we got it, but it might not be ours */
+  g_return_if_fail(GST_IS_ALAWENC(object));
+  alawenc = GST_ALAWENC(object);
+
+  switch (prop_id) {
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
diff --git a/gst/law/alaw-encode.h b/gst/law/alaw-encode.h
new file mode 100644 (file)
index 0000000..023d063
--- /dev/null
@@ -0,0 +1,69 @@
+/* Gnome-Streamer
+ * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
+ *
+ * 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.
+ */
+
+
+#ifndef __GST_ALAWENCODE_H__
+#define __GST_ALAWENCODE_H__
+
+
+#include <config.h>
+#include <gst/gst.h>
+// #include <gst/meta/audioraw.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define GST_TYPE_ALAWENC \
+  (gst_alawenc_get_type())
+#define GST_ALAWENC(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_ALAWENC,GstALawEnc))
+#define GST_ALAWENC_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_ALAWENC,GstALawEnc))
+#define GST_IS_ALAWENC(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_ALAWENC))
+#define GST_IS_ALAWENC_CLASS(obj) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_ALAWENC))
+
+typedef struct _GstALawEnc GstALawEnc;
+typedef struct _GstALawEncClass GstALawEncClass;
+
+struct _GstALawEnc {
+  GstElement element;
+
+  GstPad *sinkpad,*srcpad;
+
+  //MetaAudioRaw meta;
+
+};
+
+struct _GstALawEncClass {
+  GstElementClass parent_class;
+};
+
+GType gst_alawenc_get_type(void);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GST_STEREO_H__ */
diff --git a/gst/law/alaw.c b/gst/law/alaw.c
new file mode 100644 (file)
index 0000000..1b9afb5
--- /dev/null
@@ -0,0 +1,95 @@
+#include "alaw-encode.h"
+#include "alaw-decode.h"
+
+static GstElementDetails alawenc_details = {
+  "PCM to A Law conversion",
+  "Filter/Effect",
+  "Convert 16bit PCM to 8bit A law",
+  VERSION,
+  "Zaheer Merali <zaheer@bellworldwide.net>",
+  "(C) 2001"
+};
+
+static GstElementDetails alawdec_details = {
+  "A Law to PCM conversion",
+  "Filter/Effect",
+  "Convert 8bit A law to 16bit PCM",
+  VERSION,
+  "Zaheer Merali <zaheer@bellworldwide.net>",
+  "(C) 2001"
+};
+
+static GstCaps*
+alaw_factory (void)
+{
+  return
+   gst_caps_new (
+       "test_src",
+       "audio/raw",
+       gst_props_new (
+         "format",  GST_PROPS_STRING ("int"),
+           "law",   GST_PROPS_INT (2),
+           "width", GST_PROPS_INT(8),
+           "depth", GST_PROPS_INT(8),
+           "signed", GST_PROPS_BOOLEAN(FALSE),
+           NULL));
+}
+
+static GstCaps*
+linear_factory (void)
+{
+  return
+   gst_caps_new (
+       "test_sink",
+       "audio/raw",
+       gst_props_new (
+         "format",     GST_PROPS_STRING ("int"),
+           "law",      GST_PROPS_INT(0),
+           "width",    GST_PROPS_INT(16),
+           "depth",    GST_PROPS_INT(16),
+           "signed",   GST_PROPS_BOOLEAN(TRUE),
+           NULL));
+}
+
+GstPadTemplate *alawenc_src_template, *alawenc_sink_template; 
+GstPadTemplate *alawdec_src_template, *alawdec_sink_template;
+
+static gboolean
+plugin_init (GModule *module, GstPlugin *plugin)
+{
+  GstElementFactory *alawenc_factory, *alawdec_factory;
+  GstCaps* alaw_caps, *linear_caps;
+
+  alawenc_factory = gst_elementfactory_new("alawencode",GST_TYPE_ALAWENC,
+                                            &alawenc_details);
+  g_return_val_if_fail(alawenc_factory != NULL, FALSE);
+  alawdec_factory = gst_elementfactory_new("alawdecode",GST_TYPE_ALAWDEC,
+                                           &alawdec_details);
+  g_return_val_if_fail(alawdec_factory != NULL, FALSE);
+
+  alaw_caps = alaw_factory ();
+  linear_caps = linear_factory ();
+  alawenc_src_template = gst_padtemplate_new ("src",GST_PAD_SRC,GST_PAD_ALWAYS,alaw_caps, NULL);
+  alawenc_sink_template = gst_padtemplate_new ("sink",GST_PAD_SINK,GST_PAD_ALWAYS,linear_caps, NULL);
+  gst_elementfactory_add_padtemplate (alawenc_factory, alawenc_src_template);
+  gst_elementfactory_add_padtemplate (alawenc_factory, alawenc_sink_template);
+
+  alawdec_src_template = gst_padtemplate_new ("src",GST_PAD_SRC,GST_PAD_ALWAYS,linear_caps, NULL);
+  alawdec_sink_template = gst_padtemplate_new ("sink",GST_PAD_SINK,GST_PAD_ALWAYS,alaw_caps, NULL);
+  
+  gst_elementfactory_add_padtemplate (alawdec_factory, alawdec_src_template);
+  gst_elementfactory_add_padtemplate (alawdec_factory, alawdec_sink_template);
+  gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (alawenc_factory));
+  gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (alawdec_factory));
+
+  return TRUE;
+}
+
+GstPluginDesc plugin_desc = {
+  GST_VERSION_MAJOR,
+  GST_VERSION_MINOR,
+  "alaw",
+  plugin_init
+};
+
diff --git a/gst/law/mulaw-conversion.c b/gst/law/mulaw-conversion.c
new file mode 100644 (file)
index 0000000..ad3fcce
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * This routine converts from linear to ulaw
+ * 29 September 1989
+ *
+ * Craig Reese: IDA/Supercomputing Research Center
+ * Joe Campbell: Department of Defense
+ *
+ * References:
+ * 1) CCITT Recommendation G.711  (very difficult to follow)
+ * 2) "A New Digital Technique for Implementation of Any 
+ *     Continuous PCM Companding Law," Villeret, Michel,
+ *     et al. 1973 IEEE Int. Conf. on Communications, Vol 1,
+ *     1973, pg. 11.12-11.17
+ * 3) MIL-STD-188-113,"Interoperability and Performance Standards
+ *     for Analog-to_Digital Conversion Techniques,"
+ *     17 February 1987
+ *
+ * Input: Signed 16 bit linear sample
+ * Output: 8 bit ulaw sample
+ */
+
+#include <glib.h>
+
+#define ZEROTRAP    /* turn on the trap as per the MIL-STD */
+#define BIAS 0x84   /* define the add-in bias for 16 bit samples */
+#define CLIP 32635
+
+void
+mulaw_encode(gint16* in, guint8* out, gint numsamples)
+{
+    static gint16 exp_lut[256] = {0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
+                               4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
+                               5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
+                               5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
+                               6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
+                               6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
+                               6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
+                               6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
+                               7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+                               7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+                               7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+                               7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+                               7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+                               7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+                               7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+                               7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7};
+    gint16 sign, exponent, mantissa,i;
+    gint16 sample;
+    guint8 ulawbyte;
+
+    for(i=0;i<numsamples;i++) {
+      sample=in[i];
+      /** get the sample into sign-magnitude **/
+      sign = (sample >> 8) & 0x80;        /* set aside the sign */
+      if (sign != 0) sample = -sample;    /* get magnitude */
+      if (sample > CLIP) sample = CLIP;   /* clip the magnitude */
+      /** convert from 16 bit linear to ulaw **/
+      sample = sample + BIAS;
+      exponent = exp_lut[(sample>>7) & 0xFF];
+      mantissa = (sample >> (exponent+3)) & 0x0F;
+      ulawbyte = ~(sign | (exponent << 4) | mantissa);
+#ifdef ZEROTRAP
+      if (ulawbyte == 0 ) ulawbyte = 0x02;  /* optional CCITT trap */
+#endif
+      out[i]=ulawbyte;
+    }
+}
+
+/*
+ * This routine converts from ulaw to 16 bit linear
+ * 29 September 1989
+ *
+ * Craig Reese: IDA/Supercomputing Research Center
+ *
+ * References:
+ * 1) CCITT Recommendation G.711  (very difficult to follow)
+ * 2) MIL-STD-188-113,"Interoperability and Performance Standards
+ *     for Analog-to_Digital Conversion Techniques,"
+ *     17 February 1987
+ *
+ * Input: 8 bit ulaw sample
+ * Output: signed 16 bit linear sample
+ */
+
+void
+mulaw_decode(guint8* in,gint16* out,gint numsamples)
+{
+    static gint16 exp_lut[8]={0,132,396,924,1980,4092,8316,16764};
+    gint16 sign, exponent, mantissa;
+    guint8 ulawbyte;
+    gint16 linear,i;
+    for(i=0;i<numsamples;i++) {
+      ulawbyte=in[i];
+      ulawbyte = ~ulawbyte;
+      sign = (ulawbyte & 0x80);
+      exponent = (ulawbyte >> 4) & 0x07;
+      mantissa = ulawbyte & 0x0F;
+      linear = exp_lut[exponent] + (mantissa << (exponent+3));
+      if (sign != 0) linear = -linear;
+      out[i]=linear;
+    }
+}
diff --git a/gst/law/mulaw-conversion.h b/gst/law/mulaw-conversion.h
new file mode 100644 (file)
index 0000000..5518012
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef _GST_ULAWDECODE_H
+#define _GST_ULAWDECODE_H
+
+#include <glib.h>
+
+void
+mulaw_encode(gint16* in, guint8* out, gint numsamples);
+void
+mulaw_decode(guint8* in,gint16* out,gint numsamples);
+#endif
diff --git a/gst/law/mulaw-decode.c b/gst/law/mulaw-decode.c
new file mode 100644 (file)
index 0000000..d93c690
--- /dev/null
@@ -0,0 +1,181 @@
+/* Gnome-Streamer
+ * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
+ *
+ * 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.
+ */
+
+#include <gst/gst.h>
+#include "mulaw-decode.h"
+#include "mulaw-conversion.h"
+
+extern GstPadTemplate *mulawdec_src_template, *mulawdec_sink_template;
+
+
+/* Stereo signals and args */
+enum {
+  /* FILL ME */
+  LAST_SIGNAL
+};
+
+enum {
+  ARG_0
+};
+
+static void            gst_mulawdec_class_init         (GstMuLawDecClass *klass);
+static void            gst_mulawdec_init                       (GstMuLawDec *mulawdec);
+
+static void            gst_mulawdec_set_property                       (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
+static void            gst_mulawdec_get_property                       (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
+
+static void            gst_mulawdec_chain                      (GstPad *pad, GstBuffer *buf);
+
+
+static GstElementClass *parent_class = NULL;
+//static guint gst_stereo_signals[LAST_SIGNAL] = { 0 };
+
+static GstPadNegotiateReturn
+mulawdec_negotiate_sink (GstPad *pad, GstCaps **caps, gint counter)
+{
+  GstCaps* tempcaps;
+  
+  GstMuLawDec* mulawdec=GST_MULAWDEC (GST_OBJECT_PARENT (pad));
+  
+  if (*caps==NULL) 
+    return GST_PAD_NEGOTIATE_FAIL;
+
+  tempcaps = gst_caps_copy(*caps);
+
+  gst_caps_set(tempcaps,"format",GST_PROPS_STRING("int"));
+  gst_caps_set(tempcaps,"law",GST_PROPS_INT(0));
+  gst_caps_set(tempcaps,"depth",GST_PROPS_INT(16));
+  gst_caps_set(tempcaps,"width",GST_PROPS_INT(16));
+  gst_caps_set(tempcaps,"signed",GST_PROPS_BOOLEAN(TRUE));
+
+  if (gst_pad_set_caps (mulawdec->srcpad, tempcaps))
+  {
+    return GST_PAD_NEGOTIATE_AGREE;
+  }
+  else {
+    gst_caps_unref (tempcaps);
+    return GST_PAD_NEGOTIATE_FAIL;
+  }
+}              
+
+GType
+gst_mulawdec_get_type(void) {
+  static GType mulawdec_type = 0;
+
+  if (!mulawdec_type) {
+    static const GTypeInfo mulawdec_info = {
+      sizeof(GstMuLawDecClass),      NULL,
+      NULL,
+      (GClassInitFunc)gst_mulawdec_class_init,
+      NULL,
+      NULL,
+      sizeof(GstMuLawDec),
+      0,
+      (GInstanceInitFunc)gst_mulawdec_init,
+    };
+    mulawdec_type = g_type_register_static(GST_TYPE_ELEMENT, "GstMuLawDec", &mulawdec_info, 0);
+  }
+  return mulawdec_type;
+}
+
+static void
+gst_mulawdec_class_init (GstMuLawDecClass *klass)
+{
+  GObjectClass *gobject_class;
+  GstElementClass *gstelement_class;
+
+  gobject_class = (GObjectClass*)klass;
+  gstelement_class = (GstElementClass*)klass;
+
+  parent_class = g_type_class_ref(GST_TYPE_ELEMENT);
+
+  gobject_class->set_property = gst_mulawdec_set_property;
+  gobject_class->get_property = gst_mulawdec_get_property;
+}
+
+static void
+gst_mulawdec_init (GstMuLawDec *mulawdec)
+{
+  mulawdec->sinkpad = gst_pad_new_from_template(mulawdec_sink_template,"sink");
+  mulawdec->srcpad = gst_pad_new_from_template(mulawdec_src_template,"src");
+  gst_pad_set_negotiate_function(mulawdec->sinkpad, mulawdec_negotiate_sink);
+
+  gst_element_add_pad(GST_ELEMENT(mulawdec),mulawdec->sinkpad);
+  gst_pad_set_chain_function(mulawdec->sinkpad,gst_mulawdec_chain);
+  gst_element_add_pad(GST_ELEMENT(mulawdec),mulawdec->srcpad);
+}
+
+static void
+gst_mulawdec_chain (GstPad *pad,GstBuffer *buf)
+{
+  GstMuLawDec *mulawdec;
+  gint16 *linear_data;
+  guint8 *mulaw_data;
+  GstBuffer* outbuf;
+
+  g_return_if_fail(pad != NULL);
+  g_return_if_fail(GST_IS_PAD(pad));
+  g_return_if_fail(buf != NULL);
+
+  mulawdec = GST_MULAWDEC(GST_OBJECT_PARENT (pad));
+  g_return_if_fail(mulawdec != NULL);
+  g_return_if_fail(GST_IS_MULAWDEC(mulawdec));
+
+  mulaw_data = (guint8 *)GST_BUFFER_DATA(buf);
+  outbuf=gst_buffer_new();
+  GST_BUFFER_DATA(outbuf) = (gchar*)g_new(gint16,GST_BUFFER_SIZE(buf));
+  GST_BUFFER_SIZE(outbuf) = GST_BUFFER_SIZE(buf)*2;
+
+  linear_data = (gint16*)GST_BUFFER_DATA(outbuf);
+  mulaw_decode(mulaw_data,linear_data,GST_BUFFER_SIZE(buf));
+
+  gst_buffer_unref(buf);
+  gst_pad_push(mulawdec->srcpad,outbuf);
+}
+
+static void
+gst_mulawdec_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
+{
+  GstMuLawDec *mulawdec;
+
+  /* it's not null if we got it, but it might not be ours */
+  g_return_if_fail(GST_IS_MULAWDEC(object));
+  mulawdec = GST_MULAWDEC(object);
+
+  switch (prop_id) {
+    default:
+      break;
+  }
+}
+
+static void
+gst_mulawdec_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
+{
+  GstMuLawDec *mulawdec;
+
+  /* it's not null if we got it, but it might not be ours */
+  g_return_if_fail(GST_IS_MULAWDEC(object));
+  mulawdec = GST_MULAWDEC(object);
+
+  switch (prop_id) {
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
diff --git a/gst/law/mulaw-decode.h b/gst/law/mulaw-decode.h
new file mode 100644 (file)
index 0000000..431b1bd
--- /dev/null
@@ -0,0 +1,69 @@
+/* Gnome-Streamer
+ * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
+ *
+ * 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.
+ */
+
+
+#ifndef __GST_MULAWDECODE_H__
+#define __GST_MULAWDECODE_H__
+
+
+#include <config.h>
+#include <gst/gst.h>
+// #include <gst/meta/audioraw.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define GST_TYPE_MULAWDEC \
+  (gst_mulawdec_get_type())
+#define GST_MULAWDEC(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_MULAWDEC,GstMuLawDec))
+#define GST_MULAWDEC_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_MULAWDEC,GstMuLawDec))
+#define GST_IS_MULAWDEC(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_MULAWDEC))
+#define GST_IS_MULAWDEC_CLASS(obj) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_MULAWDEC))
+
+typedef struct _GstMuLawDec GstMuLawDec;
+typedef struct _GstMuLawDecClass GstMuLawDecClass;
+
+struct _GstMuLawDec {
+  GstElement element;
+
+  GstPad *sinkpad,*srcpad;
+
+  //MetaAudioRaw meta;
+
+};
+
+struct _GstMuLawDecClass {
+  GstElementClass parent_class;
+};
+
+GType gst_mulawdec_get_type(void);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GST_STEREO_H__ */
diff --git a/gst/law/mulaw-encode.c b/gst/law/mulaw-encode.c
new file mode 100644 (file)
index 0000000..40d868d
--- /dev/null
@@ -0,0 +1,181 @@
+/* Gnome-Streamer
+ * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
+ *
+ * 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.
+ */
+
+#include <gst/gst.h>
+#include "mulaw-encode.h"
+#include "mulaw-conversion.h"
+
+extern GstPadTemplate *mulawenc_src_template, *mulawenc_sink_template;
+
+
+/* Stereo signals and args */
+enum {
+  /* FILL ME */
+  LAST_SIGNAL
+};
+
+enum {
+  ARG_0
+};
+
+static void            gst_mulawenc_class_init         (GstMuLawEncClass *klass);
+static void            gst_mulawenc_init                       (GstMuLawEnc *mulawenc);
+
+static void            gst_mulawenc_set_property                       (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
+static void            gst_mulawenc_get_property                       (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
+
+static void            gst_mulawenc_chain                      (GstPad *pad, GstBuffer *buf);
+
+
+static GstElementClass *parent_class = NULL;
+//static guint gst_stereo_signals[LAST_SIGNAL] = { 0 };
+
+static GstPadNegotiateReturn
+mulawenc_negotiate_sink (GstPad *pad, GstCaps **caps, gint counter)
+{
+  GstCaps* tempcaps;
+  
+  GstMuLawEnc* mulawenc=GST_MULAWENC (GST_OBJECT_PARENT (pad));
+  
+  if (*caps==NULL) 
+    return GST_PAD_NEGOTIATE_FAIL;
+
+  tempcaps = gst_caps_copy(*caps);
+
+  gst_caps_set(tempcaps,"format",GST_PROPS_STRING("int"));
+  gst_caps_set(tempcaps,"law",GST_PROPS_INT(1));
+  gst_caps_set(tempcaps,"depth",GST_PROPS_INT(8));
+  gst_caps_set(tempcaps,"width",GST_PROPS_INT(8));
+  gst_caps_set(tempcaps,"signed",GST_PROPS_BOOLEAN(FALSE));
+
+  if (gst_pad_set_caps (mulawenc->srcpad, tempcaps))
+  {
+    return GST_PAD_NEGOTIATE_AGREE;
+  }
+  else {
+    gst_caps_unref (tempcaps);
+    return GST_PAD_NEGOTIATE_FAIL;
+  }
+}              
+
+GType
+gst_mulawenc_get_type(void) {
+  static GType mulawenc_type = 0;
+
+  if (!mulawenc_type) {
+    static const GTypeInfo mulawenc_info = {
+      sizeof(GstMuLawEncClass),      NULL,
+      NULL,
+      (GClassInitFunc)gst_mulawenc_class_init,
+      NULL,
+      NULL,
+      sizeof(GstMuLawEnc),
+      0,
+      (GInstanceInitFunc)gst_mulawenc_init,
+    };
+    mulawenc_type = g_type_register_static(GST_TYPE_ELEMENT, "GstMuLawEnc", &mulawenc_info, 0);
+  }
+  return mulawenc_type;
+}
+
+static void
+gst_mulawenc_class_init (GstMuLawEncClass *klass)
+{
+  GObjectClass *gobject_class;
+  GstElementClass *gstelement_class;
+
+  gobject_class = (GObjectClass*)klass;
+  gstelement_class = (GstElementClass*)klass;
+
+  parent_class = g_type_class_ref(GST_TYPE_ELEMENT);
+
+  gobject_class->set_property = gst_mulawenc_set_property;
+  gobject_class->get_property = gst_mulawenc_get_property;
+}
+
+static void
+gst_mulawenc_init (GstMuLawEnc *mulawenc)
+{
+  mulawenc->sinkpad = gst_pad_new_from_template(mulawenc_sink_template,"sink");
+  mulawenc->srcpad = gst_pad_new_from_template(mulawenc_src_template,"src");
+  gst_pad_set_negotiate_function(mulawenc->sinkpad, mulawenc_negotiate_sink);
+
+  gst_element_add_pad(GST_ELEMENT(mulawenc),mulawenc->sinkpad);
+  gst_pad_set_chain_function(mulawenc->sinkpad,gst_mulawenc_chain);
+  gst_element_add_pad(GST_ELEMENT(mulawenc),mulawenc->srcpad);
+}
+
+static void
+gst_mulawenc_chain (GstPad *pad,GstBuffer *buf)
+{
+  GstMuLawEnc *mulawenc;
+  gint16 *linear_data;
+  guint8 *mulaw_data;
+  GstBuffer* outbuf;
+
+  g_return_if_fail(pad != NULL);
+  g_return_if_fail(GST_IS_PAD(pad));
+  g_return_if_fail(buf != NULL);
+
+  mulawenc = GST_MULAWENC(GST_OBJECT_PARENT (pad));
+  g_return_if_fail(mulawenc != NULL);
+  g_return_if_fail(GST_IS_MULAWENC(mulawenc));
+
+  linear_data = (gint16 *)GST_BUFFER_DATA(buf);
+  outbuf=gst_buffer_new();
+  GST_BUFFER_DATA(outbuf) = (gchar*)g_new(gint16,GST_BUFFER_SIZE(buf)/4);
+  GST_BUFFER_SIZE(outbuf) = GST_BUFFER_SIZE(buf)/2;
+
+  mulaw_data = (gint8*)GST_BUFFER_DATA(outbuf);
+  mulaw_encode(linear_data,mulaw_data,GST_BUFFER_SIZE(outbuf));
+
+  gst_buffer_unref(buf);
+  gst_pad_push(mulawenc->srcpad,outbuf);
+}
+
+static void
+gst_mulawenc_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
+{
+  GstMuLawEnc *mulawenc;
+
+  /* it's not null if we got it, but it might not be ours */
+  g_return_if_fail(GST_IS_MULAWENC(object));
+  mulawenc = GST_MULAWENC(object);
+
+  switch (prop_id) {
+    default:
+      break;
+  }
+}
+
+static void
+gst_mulawenc_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
+{
+  GstMuLawEnc *mulawenc;
+
+  /* it's not null if we got it, but it might not be ours */
+  g_return_if_fail(GST_IS_MULAWENC(object));
+  mulawenc = GST_MULAWENC(object);
+
+  switch (prop_id) {
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
diff --git a/gst/law/mulaw-encode.h b/gst/law/mulaw-encode.h
new file mode 100644 (file)
index 0000000..009b470
--- /dev/null
@@ -0,0 +1,69 @@
+/* Gnome-Streamer
+ * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
+ *
+ * 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.
+ */
+
+
+#ifndef __GST_MULAWENCODE_H__
+#define __GST_MULAWENCODE_H__
+
+
+#include <config.h>
+#include <gst/gst.h>
+// #include <gst/meta/audioraw.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define GST_TYPE_MULAWENC \
+  (gst_mulawenc_get_type())
+#define GST_MULAWENC(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_MULAWENC,GstMuLawEnc))
+#define GST_MULAWENC_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_MULAWENC,GstMuLawEnc))
+#define GST_IS_MULAWENC(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_MULAWENC))
+#define GST_IS_MULAWENC_CLASS(obj) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_MULAWENC))
+
+typedef struct _GstMuLawEnc GstMuLawEnc;
+typedef struct _GstMuLawEncClass GstMuLawEncClass;
+
+struct _GstMuLawEnc {
+  GstElement element;
+
+  GstPad *sinkpad,*srcpad;
+
+  //MetaAudioRaw meta;
+
+};
+
+struct _GstMuLawEncClass {
+  GstElementClass parent_class;
+};
+
+GType gst_mulawenc_get_type(void);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GST_STEREO_H__ */
diff --git a/gst/law/mulaw.c b/gst/law/mulaw.c
new file mode 100644 (file)
index 0000000..5b97eca
--- /dev/null
@@ -0,0 +1,103 @@
+#include "mulaw-encode.h"
+#include "mulaw-decode.h"
+
+static GstElementDetails mulawenc_details = {
+  "PCM to Mu Law conversion",
+  "Filter/Effect",
+  "Convert 16bit PCM to 8bit mu law",
+  VERSION,
+  "Zaheer Merali <zaheer@bellworldwide.net>",
+  "(C) 2001"
+};
+
+static GstElementDetails mulawdec_details = {
+  "Mu Law to PCM conversion",
+  "Filter/Effect",
+  "Convert 8bit mu law to 16bit PCM",
+  VERSION,
+  "Zaheer Merali <zaheer@bellworldwide.net>",
+  "(C) 2001"
+};
+
+static GstCaps*
+mulaw_factory (void)
+{
+  return 
+    gst_caps_new (
+       "test_src",
+       "audio/raw",
+       gst_props_new (
+         "format",   GST_PROPS_STRING ("int"),
+           "law",    GST_PROPS_INT (1),
+           "width",  GST_PROPS_INT(8),
+           "depth",  GST_PROPS_INT(8),
+           "signed", GST_PROPS_BOOLEAN(FALSE),
+           NULL));
+}
+
+static GstCaps*
+linear_factory (void)
+{
+  return 
+    gst_caps_new (
+       "test_sink",
+       "audio/raw",
+       gst_props_new (
+         "format",     GST_PROPS_STRING ("int"),
+           "law",      GST_PROPS_INT(0),
+           "width",    GST_PROPS_INT(16),
+           "depth",    GST_PROPS_INT(16),
+           "signed",   GST_PROPS_BOOLEAN(TRUE),
+           NULL));
+}
+
+GstPadTemplate *mulawenc_src_template, *mulawenc_sink_template; 
+GstPadTemplate *mulawdec_src_template, *mulawdec_sink_template;
+
+static gboolean
+plugin_init (GModule *module, GstPlugin *plugin)
+{
+  GstElementFactory *mulawenc_factory, *mulawdec_factory;
+  GstCaps* mulaw_caps, *linear_caps;
+
+  mulawenc_factory = gst_elementfactory_new("mulawencode",GST_TYPE_MULAWENC,
+                                            &mulawenc_details);
+  g_return_val_if_fail(mulawenc_factory != NULL, FALSE);
+  mulawdec_factory = gst_elementfactory_new("mulawdecode",GST_TYPE_MULAWDEC,
+                                           &mulawdec_details);
+  g_return_val_if_fail(mulawdec_factory != NULL, FALSE);
+
+  mulaw_caps = mulaw_factory ();
+  linear_caps = linear_factory ();
+  mulawenc_src_template = gst_padtemplate_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS,
+                                              mulaw_caps, NULL);
+  mulawenc_sink_template = gst_padtemplate_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS,
+                                               linear_caps, NULL);
+
+  gst_elementfactory_add_padtemplate (mulawenc_factory, mulawenc_src_template);
+  gst_elementfactory_add_padtemplate (mulawenc_factory, mulawenc_sink_template);
+
+  mulawdec_src_template = gst_padtemplate_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS,
+                                               linear_caps, NULL);
+  mulawdec_sink_template = gst_padtemplate_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS,
+                                               mulaw_caps, NULL);
+  
+  gst_elementfactory_add_padtemplate (mulawdec_factory, mulawdec_src_template);
+  gst_elementfactory_add_padtemplate (mulawdec_factory, mulawdec_sink_template);
+
+  gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (mulawenc_factory));
+  gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (mulawdec_factory));
+
+    
+
+  return TRUE;
+}
+
+GstPluginDesc plugin_desc = {
+  GST_VERSION_MAJOR,
+  GST_VERSION_MINOR,
+  "mulaw",
+  plugin_init
+};
+
diff --git a/gst/level/Makefile.am b/gst/level/Makefile.am
new file mode 100644 (file)
index 0000000..df87d6c
--- /dev/null
@@ -0,0 +1,10 @@
+filterdir = $(libdir)/gst
+
+filter_LTLIBRARIES = libgstlevel.la
+
+libgstlevel_la_SOURCES = gstlevel.c
+libgstlevel_la_CFLAGS = $(GST_CFLAGS)
+
+noinst_HEADERS = gstlevel.h filter.func
+
+EXTRA_DIST = README
diff --git a/gst/level/README b/gst/level/README
new file mode 100644 (file)
index 0000000..c7dbf4c
--- /dev/null
@@ -0,0 +1,11 @@
+level plugin by thomas <thomas@apestaart.org>
+
+basic level indicator; prints out RMS values averaged over the buffer of
+one iteration.  Insert this into an audio/raw chain.
+
+You can plot the level envelope of the track using gnuplot, example :
+
+tools/gstreamer-launch disksrc location=foo.wav ! parsewav ! level ! \
+  fakesink silent=true > foo.level
+graph -T gif foo.level > foo.gif
+xview dark.gif
diff --git a/gst/level/filter.func b/gst/level/filter.func
new file mode 100644 (file)
index 0000000..ccdaf61
--- /dev/null
@@ -0,0 +1,45 @@
+{
+  guint j;
+  double squaresum = 0.0;
+  double RMS = 0.0;
+  double RMS_dB = 0.0;
+  static int threshold_dB = -80;
+  static long int sample = 0;
+  double timepoint;
+
+  /*
+   * process data here  
+   * input sample data enters in *in_data as 8 or 16 bit data
+   * samples for left and right channel are interleaved
+   */
+/*
+  for(j = 0; j < num_samples; j++) {
+     (*out_data)[j] = in_data[j];
+     squaresum += in_data[j] * in_data[j];
+  }
+  RMS = sqrt (squaresum / (float) num_samples);
+  printf ("RMS for this block : %f\n", RMS);
+  RMS_dB = 20 * log (RMS / 32767);
+  printf ("RMS in dB (for 16bit) : %f\n", RMS_dB);
+*/
+
+  for(j = 0; j < num_samples; j++) {
+     (*out_data)[j] = in_data[j];
+     squaresum += pow ((double) in_data[j] / 32767.0, 2);
+  }
+  RMS = sqrt (squaresum / (float) num_samples);
+  RMS_dB = 10 * log (RMS);
+  sample += num_samples;
+  timepoint = sample / (44100.0 * 2);
+
+  if (RMS_dB > (double) threshold_dB)
+  {
+/*    printf ("Reached %d dB at %f sec (%f dB)\n", 
+           threshold_dB, timepoint, RMS_dB);
+*/
+    threshold_dB += 1;
+  }
+/*  printf ("RMS in dB (for 16bit) : %f\n", RMS_dB); */
+    printf ("%f %f\n", timepoint, RMS_dB);
+}
+
diff --git a/gst/level/gstlevel.c b/gst/level/gstlevel.c
new file mode 100644 (file)
index 0000000..cd839a3
--- /dev/null
@@ -0,0 +1,285 @@
+/* Gnome-Streamer
+ * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
+ *
+ * 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.
+ */
+
+#include <gst/gst.h>
+#include "gstlevel.h"
+#include "math.h"
+
+
+static GstElementDetails level_details = {
+  "Level",
+  "Filter/Effect",
+  "RMS Level indicator for audio/raw",
+  VERSION,
+  "Thomas <thomas@apestaart.org>",
+  "(C) 2001",
+};
+
+
+/* Filter signals and args */
+enum {
+  /* FILL ME */
+  LAST_SIGNAL
+};
+
+enum {
+  ARG_0
+};
+
+static GstPadTemplate*
+level_src_factory (void)
+{
+  static GstPadTemplate *template = NULL;
+
+  if (!template) {
+    template = gst_padtemplate_new (
+      "src",
+      GST_PAD_SRC,
+      GST_PAD_ALWAYS,
+      gst_caps_new (
+        "test_src",
+        "audio/raw",
+       gst_props_new (
+          "channels", GST_PROPS_INT_RANGE (1, 2),
+         NULL)),
+      NULL);
+  }
+  return template;
+}
+
+static GstPadTemplate*
+level_sink_factory (void)
+{
+  static GstPadTemplate *template = NULL;
+
+  if (!template) {
+    template = gst_padtemplate_new (
+      "sink",
+      GST_PAD_SINK,
+      GST_PAD_ALWAYS,
+      gst_caps_new (
+        "test_src",
+        "audio/raw",
+       gst_props_new (
+          "channels", GST_PROPS_INT_RANGE (1, 2),
+         NULL)),
+      NULL);
+  }
+  return template;
+}
+
+static void            gst_level_class_init            (GstLevelClass *klass);
+static void            gst_level_init                  (GstLevel *filter);
+
+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, GstBuffer *buf);
+static void inline     gst_level_fast_16bit_chain      (gint16* data, gint16** out_data, 
+                                                                guint numsamples);
+static void inline     gst_level_fast_8bit_chain               (gint8* data, gint8** out_data,
+                                                                guint numsamples);
+
+static GstElementClass *parent_class = NULL;
+//static guint gst_filter_signals[LAST_SIGNAL] = { 0 };
+
+static GstPadNegotiateReturn
+level_negotiate_src (GstPad *pad, GstCaps **caps, gpointer *data)
+{
+  GstLevel* filter = GST_LEVEL (gst_pad_get_parent (pad));
+  
+  if (*caps==NULL) 
+    return GST_PAD_NEGOTIATE_FAIL;
+  
+  return gst_pad_negotiate_proxy(pad,filter->sinkpad,caps);
+}
+
+static GstPadNegotiateReturn
+level_negotiate_sink (GstPad *pad, GstCaps **caps, gpointer *data)
+{
+  GstLevel* filter = GST_LEVEL (gst_pad_get_parent (pad));
+  
+  if (*caps==NULL) 
+    return GST_PAD_NEGOTIATE_FAIL;
+  
+  return gst_pad_negotiate_proxy(pad,filter->srcpad,caps);
+}              
+
+GType
+gst_level_get_type(void) {
+  static GType level_type = 0;
+
+  if (!level_type) {
+    static const GTypeInfo level_info = {
+      sizeof(GstLevelClass),      NULL,
+      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);
+  }
+  return level_type;
+}
+
+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);
+
+  gobject_class->set_property = gst_level_set_property;
+  gobject_class->get_property = gst_level_get_property;
+}
+
+static void
+gst_level_init (GstLevel *filter)
+{
+  filter->sinkpad = gst_pad_new_from_template(level_sink_factory (),"sink");
+  filter->srcpad = gst_pad_new_from_template(level_src_factory (),"src");
+
+  gst_pad_set_negotiate_function(filter->sinkpad,level_negotiate_sink);
+  gst_pad_set_negotiate_function(filter->srcpad,level_negotiate_src);
+
+  gst_element_add_pad(GST_ELEMENT(filter),filter->sinkpad);
+  gst_pad_set_chain_function(filter->sinkpad,gst_level_chain);
+  filter->srcpad = gst_pad_new("src",GST_PAD_SRC);
+  gst_element_add_pad(GST_ELEMENT(filter),filter->srcpad);
+}
+
+static void
+gst_level_chain (GstPad *pad,GstBuffer *buf)
+{
+  GstLevel *filter;
+  gint16 *in_data;
+  gint16 *out_data;
+  GstBuffer* outbuf;
+  gint width;
+
+  GstCaps *caps;
+
+  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));
+
+  caps = NULL;
+  caps = GST_PAD_CAPS(pad);
+  if (caps == NULL)
+  {
+    // FIXME : Please change this to a better warning method !
+    printf ("WARNING : chain : Could not get caps of pad !\n");
+  }
+
+  width = gst_caps_get_int(caps, "width");
+
+  in_data = (gint16 *)GST_BUFFER_DATA(buf);
+  outbuf=gst_buffer_new();
+  GST_BUFFER_DATA(outbuf) = (gchar*)g_new(gint16,GST_BUFFER_SIZE(buf)/2);
+  GST_BUFFER_SIZE(outbuf) = GST_BUFFER_SIZE(buf);
+
+  out_data = (gint16*)GST_BUFFER_DATA(outbuf);
+  
+  switch (width) {
+    case 16:
+       gst_level_fast_16bit_chain(in_data,&out_data,GST_BUFFER_SIZE(buf)/2);
+       break;
+    case 8:
+       gst_level_fast_8bit_chain((gint8*)in_data,(gint8**)&out_data,GST_BUFFER_SIZE(buf));
+       break;
+  }
+  gst_buffer_unref(buf);
+  gst_pad_push(filter->srcpad,outbuf);
+}
+
+static void inline
+gst_level_fast_16bit_chain(gint16* in_data, gint16** out_data, 
+                                guint num_samples)
+#include "filter.func"
+
+static void inline
+gst_level_fast_8bit_chain(gint8* in_data, gint8** out_data,
+                                guint num_samples)
+#include "filter.func"
+
+static void
+gst_level_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
+{
+  GstLevel *filter;
+
+  /* it's not null if we got it, but it might not be ours */
+  g_return_if_fail(GST_IS_LEVEL(object));
+  filter = GST_LEVEL(object);
+
+  switch (prop_id) {
+    default:
+      break;
+  }
+}
+
+static void
+gst_level_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
+{
+  GstLevel *filter;
+
+  /* it's not null if we got it, but it might not be ours */
+  g_return_if_fail(GST_IS_LEVEL(object));
+  filter = GST_LEVEL(object);
+
+  switch (prop_id) {
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static gboolean
+plugin_init (GModule *module, GstPlugin *plugin)
+{
+  GstElementFactory *factory;
+
+  factory = gst_elementfactory_new("level",GST_TYPE_LEVEL,
+                                   &level_details);
+  g_return_val_if_fail(factory != NULL, FALSE);
+  
+  gst_elementfactory_add_padtemplate (factory, level_src_factory ());
+  gst_elementfactory_add_padtemplate (factory, level_sink_factory ());
+
+  gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (factory));
+
+  return TRUE;
+}
+
+GstPluginDesc plugin_desc = {
+  GST_VERSION_MAJOR,
+  GST_VERSION_MINOR,
+  "level",
+  plugin_init
+};
diff --git a/gst/level/gstlevel.h b/gst/level/gstlevel.h
new file mode 100644 (file)
index 0000000..f9dade0
--- /dev/null
@@ -0,0 +1,69 @@
+/* Gnome-Streamer
+ * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
+ *
+ * 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.
+ */
+
+
+#ifndef __GST_LEVEL_H__
+#define __GST_LEVEL_H__
+
+
+#include <config.h>
+#include <gst/gst.h>
+// #include <gst/meta/audioraw.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define GST_TYPE_LEVEL \
+  (gst_level_get_type())
+#define GST_LEVEL(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_LEVEL,GstLevel))
+#define GST_LEVEL_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_ULAW,GstLevel))
+#define GST_IS_LEVEL(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_LEVEL))
+#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;
+
+  GstPad *sinkpad,*srcpad;
+
+  //MetaAudioRaw meta;
+
+};
+
+struct _GstLevelClass {
+  GstElementClass parent_class;
+};
+
+GType gst_level_get_type(void);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GST_STEREO_H__ */
diff --git a/gst/median/.gitignore b/gst/median/.gitignore
new file mode 100644 (file)
index 0000000..08f5ed3
--- /dev/null
@@ -0,0 +1,7 @@
+Makefile
+Makefile.in
+*.o
+*.lo
+*.la
+.deps
+.libs
diff --git a/gst/median/Makefile.am b/gst/median/Makefile.am
new file mode 100644 (file)
index 0000000..cf75f34
--- /dev/null
@@ -0,0 +1,9 @@
+filterdir = $(libdir)/gst
+
+filter_LTLIBRARIES = libgstmedian.la
+
+libgstmedian_la_SOURCES = gstmedian.c
+
+libgstmedian_la_CFLAGS = -O3 $(FOMIT_FRAME_POINTER) -funroll-all-loops -finline-functions -ffast-math $(GST_CFLAGS)
+
+noinst_HEADERS = gstmedian.h
diff --git a/gst/median/gstmedian.c b/gst/median/gstmedian.c
new file mode 100644 (file)
index 0000000..f0e836a
--- /dev/null
@@ -0,0 +1,412 @@
+/* Gnome-Streamer
+ * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
+ *
+ * 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.
+ */
+
+#include <string.h>
+#include <gstmedian.h>
+
+
+static GstElementDetails median_details = {
+  "Median effect",
+  "Filter/Effect",
+  "apply a median filter to an image",
+  VERSION,
+  "Wim Taymans <wim.taymans@chello.be>",
+  "(C) 2000",
+};
+
+GST_PADTEMPLATE_FACTORY (median_src_factory,
+  "src",
+  GST_PAD_SRC,
+  GST_PAD_ALWAYS,
+  GST_CAPS_NEW (
+   "median_src",
+   "video/raw",
+     "format",   GST_PROPS_FOURCC (GST_STR_FOURCC ("I420"))
+  )
+)
+
+GST_PADTEMPLATE_FACTORY (median_sink_factory,
+  "sink",
+  GST_PAD_SINK,
+  GST_PAD_ALWAYS,
+  GST_CAPS_NEW (
+   "median_src",
+   "video/raw",
+     "format",   GST_PROPS_FOURCC (GST_STR_FOURCC ("I420"))
+  )
+)
+
+
+/* Median signals and args */
+enum {
+  /* FILL ME */
+  LAST_SIGNAL
+};
+
+enum {
+  ARG_0,
+  ARG_ACTIVE,
+  ARG_FILTERSIZE,
+  ARG_LUM_ONLY
+};
+
+static GType   gst_median_get_type     (void);
+static void    gst_median_class_init   (GstMedianClass *klass);
+static void    gst_median_init         (GstMedian *median);
+
+static void    median_5                (unsigned char *src, unsigned char *dest, int height, int width);
+static void    median_9                (unsigned char *src, unsigned char *dest, int height, int width);
+static void    gst_median_chain        (GstPad *pad, GstBuffer *buf);
+
+static void    gst_median_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
+static void    gst_median_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
+
+static GstElementClass *parent_class = NULL;
+//static guint gst_median_signals[LAST_SIGNAL] = { 0 };
+
+static GstPadNegotiateReturn
+median_negotiate_src (GstPad *pad, GstCaps **caps, gpointer *data)
+{
+  GstMedian* filter = GST_MEDIAN (gst_pad_get_parent (pad));
+
+  if (*caps==NULL)
+    return GST_PAD_NEGOTIATE_FAIL;
+
+  return gst_pad_negotiate_proxy (pad, filter->sinkpad, caps);
+}
+
+static GstPadNegotiateReturn
+median_negotiate_sink (GstPad *pad, GstCaps **caps, gpointer *data)
+{
+  GstMedian* filter = GST_MEDIAN (gst_pad_get_parent (pad));
+
+  if (*caps==NULL)
+    return GST_PAD_NEGOTIATE_FAIL;
+
+  return gst_pad_negotiate_proxy (pad, filter->srcpad, caps);
+}
+
+GType
+gst_median_get_type (void)
+{
+  static GType median_type = 0;
+
+  if (!median_type) {
+    static const GTypeInfo median_info = {
+      sizeof(GstMedianClass),      NULL,      NULL,      (GClassInitFunc)gst_median_class_init,
+      NULL,
+      NULL,
+      sizeof(GstMedian),
+      0,
+      (GInstanceInitFunc)gst_median_init,
+    };
+    median_type = g_type_register_static(GST_TYPE_ELEMENT, "GstMedian", &median_info, 0);
+  }
+  return median_type;
+}
+
+static void
+gst_median_class_init (GstMedianClass *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_ACTIVE,
+    g_param_spec_boolean("active","active","active",
+                         TRUE,G_PARAM_READWRITE)); // CHECKME
+  g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_FILTERSIZE,
+    g_param_spec_int("filtersize","filtersize","filtersize",
+                     G_MININT,G_MAXINT,0,G_PARAM_READWRITE)); // CHECKME
+  g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_LUM_ONLY,
+    g_param_spec_boolean("lum_only","lum_only","lum_only",
+                         TRUE,G_PARAM_READWRITE)); // CHECKME
+
+  gobject_class->set_property = gst_median_set_property;
+  gobject_class->get_property = gst_median_get_property;
+}
+
+static void
+gst_median_newcaps (GstPad *pad, GstCaps *caps)
+{
+  GstMedian *filter;
+
+  filter = GST_MEDIAN (gst_pad_get_parent (pad));
+
+  filter->width = gst_caps_get_int (caps, "width");
+  filter->height = gst_caps_get_int (caps, "height");
+}
+
+void gst_median_init (GstMedian *median)
+{
+  median->sinkpad = gst_pad_new_from_template (
+                 GST_PADTEMPLATE_GET (median_sink_factory), "sink");
+  gst_pad_set_negotiate_function (median->sinkpad, median_negotiate_sink);
+  gst_pad_set_newcaps_function (median->sinkpad, gst_median_newcaps);
+  gst_pad_set_chain_function (median->sinkpad, gst_median_chain);
+  gst_element_add_pad (GST_ELEMENT (median), median->sinkpad);
+
+  median->srcpad = gst_pad_new_from_template (
+                 GST_PADTEMPLATE_GET (median_src_factory), "src");
+  gst_pad_set_negotiate_function (median->srcpad, median_negotiate_src);
+  gst_element_add_pad (GST_ELEMENT (median), median->srcpad);
+
+  median->filtersize = 5;
+  median->lum_only = TRUE;
+  median->active = TRUE;
+}
+
+#define PIX_SORT(a,b) { if ((a)>(b)) PIX_SWAP((a),(b)); }
+#define PIX_SWAP(a,b) { unsigned char temp=(a);(a)=(b);(b)=temp; }
+
+static void
+median_5 (unsigned char *src, unsigned char *dest, int width, int height)
+{
+  int nLastRow;
+  int nLastCol;
+  unsigned char p[9];
+  int i, j, k;
+
+  nLastCol = width - 1;
+  nLastRow = height - 1;
+
+  //copy the top and bottom rows into the result array
+  for (i=0; i<width; i++) {
+    dest[i] = src[i];
+    dest[nLastRow * width + i] = src[nLastRow * width + i];
+  }
+  dest[i] = src[i];
+
+  nLastCol--;
+  nLastRow--;
+
+  /* process the interior pixels */
+  i = width + 1;
+  for (k=0; k < nLastRow; k++) {
+    for (j=0; j < nLastCol; j++, i++) {
+      p[0] = src[i-width];
+      p[1] = src[i-1];
+      p[2] = src[i];
+      p[3] = src[i+1];
+      p[4] = src[i+width];
+      PIX_SORT(p[0],p[1]) ; PIX_SORT(p[3],p[4]) ; PIX_SORT(p[0],p[3]) ;
+      PIX_SORT(p[1],p[4]) ; PIX_SORT(p[1],p[2]) ; PIX_SORT(p[2],p[3]) ;
+      PIX_SORT(p[1],p[2]) ;
+      dest[i] = p[2];
+    }
+    dest[i] = src[i++];
+    dest[i] = src[i++];
+  }
+  dest[i] = src[i++];
+}
+
+static void
+median_9 (unsigned char *src, unsigned char *dest, int width, int height)
+{
+  int nLastRow;
+  int nLastCol;
+  unsigned char p[9];
+  int i, j, k;
+
+  nLastCol = width - 1;
+  nLastRow = height - 1;
+
+  //copy the top and bottom rows into the result array
+  for (i=0; i<width; i++) {
+    dest[i] = src[i];
+    dest[nLastRow * width + i] = src[nLastRow * width + i];
+  }
+  dest[i] = src[i];
+
+  nLastCol--;
+  nLastRow--;
+
+  /* process the interior pixels */
+  i = width + 1;
+  for (k=0; k < nLastRow; k++) {
+    for (j=0; j < nLastCol; j++, i++) {
+      p[0] = src[i-width-1];
+      p[1] = src[i-width];
+      p[2] = src[i-width+1];
+      p[3] = src[i-1];
+      p[4] = src[i];
+      p[5] = src[i+1];
+      p[6] = src[i+width-1];
+      p[7] = src[i+width];
+      p[8] = src[i+width+1];
+      PIX_SORT(p[1], p[2]) ; PIX_SORT(p[4], p[5]) ; PIX_SORT(p[7], p[8]) ; 
+      PIX_SORT(p[0], p[1]) ; PIX_SORT(p[3], p[4]) ; PIX_SORT(p[6], p[7]) ; 
+      PIX_SORT(p[1], p[2]) ; PIX_SORT(p[4], p[5]) ; PIX_SORT(p[7], p[8]) ; 
+      PIX_SORT(p[0], p[3]) ; PIX_SORT(p[5], p[8]) ; PIX_SORT(p[4], p[7]) ; 
+      PIX_SORT(p[3], p[6]) ; PIX_SORT(p[1], p[4]) ; PIX_SORT(p[2], p[5]) ; 
+      PIX_SORT(p[4], p[7]) ; PIX_SORT(p[4], p[2]) ; PIX_SORT(p[6], p[4]) ; 
+      PIX_SORT(p[4], p[2]) ;
+      dest[i] = p[4];
+    }
+    dest[i] = src[i++];
+    dest[i] = src[i++];
+  }
+  dest[i] = src[i++];
+}
+
+static void
+gst_median_chain (GstPad *pad, GstBuffer *buf)
+{
+  GstMedian *median;
+  guchar *data;
+  gulong size;
+  GstBuffer *outbuf;
+//  GstMeta *meta;
+  int lumsize, chromsize;
+
+  g_return_if_fail(pad != NULL);
+  g_return_if_fail(GST_IS_PAD(pad));
+  g_return_if_fail(buf != NULL);
+
+  median = GST_MEDIAN (GST_OBJECT_PARENT (pad));
+
+  if (!median->active) {
+    gst_pad_push(median->srcpad,buf);
+    return;
+  }
+
+  data = GST_BUFFER_DATA(buf);
+  size = GST_BUFFER_SIZE(buf);
+
+  GST_DEBUG (0,"median: have buffer of %d\n", GST_BUFFER_SIZE(buf));
+
+  outbuf = gst_buffer_new();
+  GST_BUFFER_DATA(outbuf) = g_malloc(GST_BUFFER_SIZE(buf));
+  GST_BUFFER_SIZE(outbuf) = GST_BUFFER_SIZE(buf);
+
+  lumsize = median->width * median->height;
+  chromsize = lumsize/4;
+
+  if (median->filtersize == 5) {
+    median_5(data, GST_BUFFER_DATA(outbuf), median->width, median->height);
+    if (!median->lum_only) {
+      median_5(data+lumsize, GST_BUFFER_DATA(outbuf)+lumsize, median->width/2, median->height/2);
+      median_5(data+lumsize+chromsize, GST_BUFFER_DATA(outbuf)+lumsize+chromsize, median->width/2, median->height/2);
+    }
+    else {
+      memcpy (GST_BUFFER_DATA (outbuf)+lumsize, data+lumsize, chromsize*2);
+    }
+  }
+  else {
+    median_9(data, GST_BUFFER_DATA(outbuf), median->width, median->height);
+    if (!median->lum_only) {
+      median_9(data+lumsize, GST_BUFFER_DATA(outbuf)+lumsize, median->width/2, median->height/2);
+      median_9(data+lumsize+chromsize, GST_BUFFER_DATA(outbuf)+lumsize+chromsize, median->width/2, median->height/2);
+    }
+    else {
+      memcpy (GST_BUFFER_DATA (outbuf)+lumsize, data+lumsize, chromsize*2);
+    }
+  }
+  GST_BUFFER_TIMESTAMP (outbuf) = GST_BUFFER_TIMESTAMP (buf);
+
+  gst_buffer_unref(buf);
+
+  gst_pad_push(median->srcpad,outbuf);
+}
+
+static void
+gst_median_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
+{
+  GstMedian *median;
+  gint argvalue;
+
+  /* it's not null if we got it, but it might not be ours */
+  g_return_if_fail(GST_IS_MEDIAN(object));
+  median = GST_MEDIAN(object);
+
+  switch (prop_id) {
+    case ARG_FILTERSIZE:
+      argvalue = g_value_get_int (value);
+      if (argvalue != 5 && argvalue != 9) {
+       g_warning ("median: invalid filtersize (%d), must be 5 or 9\n", argvalue);
+      }
+      else {
+       median->filtersize = argvalue;
+      }
+      break;
+    case ARG_ACTIVE:
+      median->active = g_value_get_boolean (value);
+      break;
+    case ARG_LUM_ONLY:
+      median->lum_only = g_value_get_boolean (value);
+      break;
+    default:
+      break;
+  }
+}
+
+static void
+gst_median_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
+{
+  GstMedian *median;
+
+  /* it's not null if we got it, but it might not be ours */
+  g_return_if_fail(GST_IS_MEDIAN(object));
+  median = GST_MEDIAN(object);
+
+  switch (prop_id) {
+    case ARG_FILTERSIZE:
+      g_value_set_int (value, median->filtersize);
+      break;
+    case ARG_ACTIVE:
+      g_value_set_boolean (value, median->active);
+      break;
+    case ARG_LUM_ONLY:
+      g_value_set_boolean (value, median->lum_only);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+
+static gboolean
+plugin_init (GModule *module, GstPlugin *plugin)
+{
+  GstElementFactory *factory;
+
+  factory = gst_elementfactory_new("median",GST_TYPE_MEDIAN,
+                                   &median_details);
+  g_return_val_if_fail(factory != NULL, FALSE);
+
+  gst_elementfactory_add_padtemplate (factory, GST_PADTEMPLATE_GET (median_sink_factory));
+  gst_elementfactory_add_padtemplate (factory, GST_PADTEMPLATE_GET (median_src_factory));
+
+  gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (factory));
+
+  return TRUE;
+}
+
+GstPluginDesc plugin_desc = {
+  GST_VERSION_MAJOR,
+  GST_VERSION_MINOR,
+  "median",
+  plugin_init
+};
+
diff --git a/gst/median/gstmedian.h b/gst/median/gstmedian.h
new file mode 100644 (file)
index 0000000..17c7d04
--- /dev/null
@@ -0,0 +1,72 @@
+/* Gnome-Streamer
+ * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
+ *
+ * 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.
+ */
+
+
+#ifndef __GST_MEDIAN_H__
+#define __GST_MEDIAN_H__
+
+
+#include <config.h>
+#include <gst/gst.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define GST_TYPE_MEDIAN \
+  (gst_median_get_type())
+#define GST_MEDIAN(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_MEDIAN,GstMedian))
+#define GST_MEDIAN_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_MEDIAN,GstMedian))
+#define GST_IS_MEDIAN(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_MEDIAN))
+#define GST_IS_MEDIAN_CLASS(obj) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_MEDIAN))
+
+typedef struct _GstMedian GstMedian;
+typedef struct _GstMedianClass GstMedianClass;
+
+struct _GstMedian {
+  GstElement element;
+
+  int format;
+  int width;
+  int height;
+
+  int filtersize;
+
+  gboolean active;
+  gboolean lum_only;
+
+  GstPad *sinkpad,*srcpad;
+};
+
+struct _GstMedianClass {
+  GstElementClass parent_class;
+};
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GST_MEDIAN_H__ */
diff --git a/gst/spectrum/.gitignore b/gst/spectrum/.gitignore
new file mode 100644 (file)
index 0000000..08f5ed3
--- /dev/null
@@ -0,0 +1,7 @@
+Makefile
+Makefile.in
+*.o
+*.lo
+*.la
+.deps
+.libs
diff --git a/gst/spectrum/Makefile.am b/gst/spectrum/Makefile.am
new file mode 100644 (file)
index 0000000..476c3fd
--- /dev/null
@@ -0,0 +1,10 @@
+filterdir = $(libdir)/gst
+
+filter_LTLIBRARIES = libgstspectrum.la
+
+libgstspectrum_la_SOURCES = gstspectrum.c fix_fft.c
+libgstspectrum_la_CFLAGS = $(GST_CFLAGS)
+
+noinst_HEADERS = gstspectrum.h
+
+EXTRA_DIST = README
diff --git a/gst/spectrum/README b/gst/spectrum/README
new file mode 100644 (file)
index 0000000..8755571
--- /dev/null
@@ -0,0 +1,5 @@
+This is a simple, rather lame spectrum analyzer made from the fix_fft.c
+code, as found I think in xmms-0.9.1 (the 75-wide output sounds like xmms
+to me), which is actually written by other people (see fix_fft.c for
+credits).  It worked last time I had GiST working, which was a while ago.
+Yes, GiST is not included here yet, it will be in 0.1.0.
diff --git a/gst/spectrum/gstspectrum.c b/gst/spectrum/gstspectrum.c
new file mode 100644 (file)
index 0000000..0821545
--- /dev/null
@@ -0,0 +1,242 @@
+/* Gnome-Streamer
+ * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
+ *
+ * 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.
+ */
+
+#include <string.h>
+
+#include "gstspectrum.h"
+
+static GstElementDetails gst_spectrum_details = {
+  "Spectrum analyzer",
+  "Filter/Analysis",
+  "Run an FFT on the audio signal, output spectrum data",
+  VERSION,
+  "Erik Walthinsen <omega@cse.ogi.edu>",
+  "(C) 1999",
+};
+
+
+static GstTypeDefinition spectrumdefinition = {
+  "spectrum_spectrum_raw",
+  "spectrum/raw",
+  NULL,
+  NULL,
+};
+
+
+/* Spectrum signals and args */
+enum {
+  /* FILL ME */
+  LAST_SIGNAL
+};
+
+enum {
+  ARG_0,
+  ARG_WIDTH,
+};
+
+
+static void    gst_spectrum_class_init (GstSpectrumClass *klass);
+static void    gst_spectrum_init       (GstSpectrum *spectrum);
+
+static void    gst_spectrum_set_property       (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
+
+static void    gst_spectrum_chain      (GstPad *pad, GstBuffer *buf);
+
+#define fixed short
+int gst_spectrum_fix_fft(fixed fr[], fixed fi[], int m, int inverse);
+void gst_spectrum_fix_loud(fixed loud[], fixed fr[], fixed fi[], int n, int scale_shift);
+void gst_spectrum_window(fixed fr[], int n);
+
+
+static GstElementClass *parent_class = NULL;
+//static guint gst_spectrum_signals[LAST_SIGNAL] = { 0 };
+
+GType
+gst_spectrum_get_type (void)
+{
+  static GType spectrum_type = 0;
+
+  if (!spectrum_type) {
+    static const GTypeInfo spectrum_info = {
+      sizeof(GstSpectrumClass),      NULL,
+      NULL,
+      (GClassInitFunc)gst_spectrum_class_init,
+      NULL,
+      NULL,
+      sizeof(GstSpectrum),
+      0,
+      (GInstanceInitFunc)gst_spectrum_init,
+    };
+    spectrum_type = g_type_register_static(GST_TYPE_ELEMENT, "GstSpectrum", &spectrum_info, 0);
+  }
+  return spectrum_type;
+}
+
+static void
+gst_spectrum_class_init (GstSpectrumClass *klass)
+{
+  GObjectClass *gobject_class;
+
+  gobject_class = (GObjectClass*)klass;
+
+  parent_class = g_type_class_ref(GST_TYPE_ELEMENT);
+
+  g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_WIDTH,
+    g_param_spec_int("width","width","width",
+                     G_MININT,G_MAXINT,0,G_PARAM_WRITABLE)); // CHECKME
+
+  gobject_class->set_property = gst_spectrum_set_property;
+}
+
+static void
+gst_spectrum_init (GstSpectrum *spectrum)
+{
+  spectrum->sinkpad = gst_pad_new("sink",GST_PAD_SINK);
+  gst_element_add_pad(GST_ELEMENT(spectrum),spectrum->sinkpad);
+  gst_pad_set_chain_function(spectrum->sinkpad,gst_spectrum_chain);
+  spectrum->srcpad = gst_pad_new("src",GST_PAD_SRC);
+  gst_element_add_pad(GST_ELEMENT(spectrum),spectrum->srcpad);
+
+  spectrum->width = 75;
+}
+
+static void
+gst_spectrum_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
+{
+  GstSpectrum *spectrum;
+
+  /* it's not null if we got it, but it might not be ours */
+  g_return_if_fail(GST_IS_SPECTRUM(object));
+  spectrum = GST_SPECTRUM(object);
+
+  switch (prop_id) {
+    case ARG_WIDTH:
+      spectrum->width = g_value_get_int (value);
+      break;
+    default:
+      break;
+  }
+}
+
+static void
+gst_spectrum_chain (GstPad *pad, GstBuffer *buf)
+{
+  GstSpectrum *spectrum;
+  gint spec_base, spec_len;
+  gint16 *re, *im, *loud;
+  gint16 *samples;
+  gint samplecount,step,pos,i;
+  guchar *spect;
+  GstBuffer *newbuf;
+
+  g_return_if_fail(pad != NULL);
+  g_return_if_fail(GST_IS_PAD(pad));
+  g_return_if_fail(buf != NULL);
+
+  spectrum = GST_SPECTRUM (GST_OBJECT_PARENT (pad));
+
+  /* first deal with audio metadata */
+//  FIXME
+//  if (buf->meta) {
+//    if (spectrum->meta != NULL) {
+//      /* FIXME: need to unref the old metadata so it goes away */
+//    }
+//    /* we just make a copy of the pointer */
+//    spectrum->meta = (MetaAudioRaw *)(buf->data);
+//    /* FIXME: now we have to ref the metadata so it does go away */
+//  }
+
+  //g_return_if_fail(spectrum->meta != NULL);
+
+  //samplecount = GST_BUFFER_SIZE(buf) /
+  //              (spectrum->meta->channels * sizeof(gint16));
+//  samples = (gint16 *)g_malloc(buf->datasize);
+//  g_return_if_fail(samples != NULL);
+//  memcpy(samples,(gint16
+//*)GST_BUFFER_DATA(buf),GST_BUFFER_DATASIZE(buf));
+//  gst_buffer_unref(buf);
+  samples = (gint16 *)GST_BUFFER_DATA(buf);
+
+//  return;
+//  spec_base = (gint) (log(samplecount) / log(2));
+//  if (spec_base > 10) spec_base = 10;
+//  spec_len = (gint) pow(2, spec_base);
+  spec_base = 8;
+  spec_len = 1024;
+
+  im = g_malloc(spec_len * sizeof(gint16));
+  g_return_if_fail(im != NULL);
+  loud = g_malloc(spec_len * sizeof(gint16));
+  g_return_if_fail(loud != NULL);
+
+  memset(im,0,spec_len * sizeof(gint16));
+  //if (spectrum->meta->channels == 2) {
+    re = g_malloc(spec_len * sizeof(gint16));
+    for (i=0;i<spec_len;i++)
+      re[i] = (samples[(i*2)] + samples[(i*2)+1]) >> 1;
+  //} else
+  //  re = samples;
+  gst_spectrum_window(re,spec_len);
+  gst_spectrum_fix_fft(re,im,spec_base,FALSE);
+  gst_spectrum_fix_loud(loud,re,im,spec_len,0);
+  if (re != samples) g_free(re);
+  g_free(im);
+  step = spec_len / (spectrum->width*2);
+  spect = (guchar *)g_malloc(spectrum->width);
+  for (i=0,pos=0;i<spectrum->width;i++,pos += step) {
+    if (loud[pos] > -60)
+      spect[i] = (loud[pos] + 60) / 2;
+    else
+      spect[i] = 0;
+//    if (spect[i] > 15);
+//      spect[i] = 15;
+  }
+  g_free(loud);
+  gst_buffer_unref(buf);
+//  g_free(samples);
+
+  newbuf = gst_buffer_new();
+  g_return_if_fail(newbuf != NULL);
+  GST_BUFFER_DATA(newbuf) = spect;
+  GST_BUFFER_SIZE(newbuf) = spectrum->width;
+
+  gst_pad_push(spectrum->srcpad,newbuf);
+}
+
+static gboolean
+plugin_init (GModule *module, GstPlugin *plugin)
+{
+  GstElementFactory *factory;
+
+  /* create an elementfactory for the spectrum element */
+  factory = gst_elementfactory_new ("spectrum",GST_TYPE_SPECTRUM,
+                                    &gst_spectrum_details);
+  g_return_val_if_fail (factory != NULL, FALSE);
+
+  gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (factory));
+
+  return TRUE;
+}
+
+GstPluginDesc plugin_desc = {
+  GST_VERSION_MAJOR,
+  GST_VERSION_MINOR,
+  "spectrum",
+  plugin_init
+};
diff --git a/gst/spectrum/gstspectrum.h b/gst/spectrum/gstspectrum.h
new file mode 100644 (file)
index 0000000..f7a395e
--- /dev/null
@@ -0,0 +1,67 @@
+/* Gnome-Streamer
+ * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
+ *
+ * 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.
+ */
+
+
+#ifndef __GST_SPECTRUM_H__
+#define __GST_SPECTRUM_H__
+
+
+#include <gst/gst.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define GST_TYPE_SPECTRUM \
+  (gst_spectrum_get_type())
+#define GST_SPECTRUM(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_SPECTRUM,GstSpectrum))
+#define GST_SPECTRUM_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_SPECTRUM,GstSpectrum))
+#define GST_IS_SPECTRUM(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_SPECTRUM))
+#define GST_IS_SPECTRUM_CLASS(obj) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_SPECTRUM))
+
+typedef struct _GstSpectrum GstSpectrum;
+typedef struct _GstSpectrumClass GstSpectrumClass;
+
+struct _GstSpectrum {
+  GstElement element;
+
+  GstPad *sinkpad,*srcpad;
+
+  gint width;
+};
+
+struct _GstSpectrumClass {
+  GstElementClass parent_class;
+};
+
+GType gst_spectrum_get_type(void);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GST_SPECTRUM_H__ */
diff --git a/gst/udp/.gitignore b/gst/udp/.gitignore
new file mode 100644 (file)
index 0000000..08f5ed3
--- /dev/null
@@ -0,0 +1,7 @@
+Makefile
+Makefile.in
+*.o
+*.lo
+*.la
+.deps
+.libs
diff --git a/gst/udp/Makefile.am b/gst/udp/Makefile.am
new file mode 100644 (file)
index 0000000..0cd25aa
--- /dev/null
@@ -0,0 +1,10 @@
+filterdir = $(libdir)/gst
+
+filter_LTLIBRARIES = libgstudp.la
+
+libgstudp_la_SOURCES = gstudp.c gstudpsrc.c gstudpsink.c
+libgstudp_la_CFLAGS = $(GST_CFLAGS)
+
+noinst_HEADERS = gstudpsink.h gstudpsrc.h 
+
+EXTRA_DIST = README
diff --git a/gst/udp/README b/gst/udp/README
new file mode 100644 (file)
index 0000000..e032e74
--- /dev/null
@@ -0,0 +1,28 @@
+* What is UDP src/sink?
+
+This plugin is *not* meant to be a professional stream broadcast
+solution, like icecast or realaudio or whatever.
+
+This plugin is basically for testing and simple hacks: raw audio
+or packetized gsm should be fine.
+
+
+* Shortcomings
+
+Even given our modest ambitions, the current code is doesn't handle
+caps negotiation robustly.
+
+
+* Todo
+
+This plugin should offer different modes for caps negotiation: none,
+udp, or tcp.  The udp mode should include the caps every five packets
+(approx).  The tcp mode can do bi-directional negotiation.
+
+Perhaps this plugin can be the example of how to do caps negotiation
+via a point-to-point protocol.
+
+
+12 Sep 2001
+Wim Taymans <wim.taymans@chello.be>
+Joshua N Pritikin <vishnu@pobox.com>
diff --git a/gst/udp/gstudp.c b/gst/udp/gstudp.c
new file mode 100644 (file)
index 0000000..8bea987
--- /dev/null
@@ -0,0 +1,52 @@
+/* Gnome-Streamer
+ * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
+ *
+ * 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.
+ */
+
+
+#include "gstudpsrc.h"
+#include "gstudpsink.h"
+
+/* elementfactory information */
+extern GstElementDetails gst_udpsrc_details;
+extern GstElementDetails gst_udpsink_details;
+
+static gboolean
+plugin_init (GModule *module, GstPlugin *plugin)
+{
+  GstElementFactory *src, *sink;
+
+  /* create an elementfactory for the udpsrc element */
+  sink = gst_elementfactory_new ("udpsink",GST_TYPE_UDPSINK,
+                                   &gst_udpsink_details);
+  g_return_val_if_fail (sink != NULL, FALSE);
+  gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (sink));
+
+  src = gst_elementfactory_new ("udpsrc",GST_TYPE_UDPSRC,
+                                   &gst_udpsrc_details);
+  g_return_val_if_fail (src != NULL, FALSE);
+  gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (src));
+
+  return TRUE;
+}
+
+GstPluginDesc plugin_desc = {
+  GST_VERSION_MAJOR,
+  GST_VERSION_MINOR,
+  "udp",
+  plugin_init
+};
diff --git a/gst/udp/gstudpsink.c b/gst/udp/gstudpsink.c
new file mode 100644 (file)
index 0000000..81d7a95
--- /dev/null
@@ -0,0 +1,301 @@
+/* Gnome-Streamer
+ * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
+ *
+ * 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.
+ */
+
+
+#include "gstudpsink.h"
+
+#define UDP_DEFAULT_HOST       "localhost"
+#define UDP_DEFAULT_PORT       4951
+
+/* elementfactory information */
+GstElementDetails gst_udpsink_details = {
+  "UDP packet sender",
+  "Transport/",
+  "",
+  VERSION,
+  "Wim Taymans <wim.taymans@chello.be>",
+  "(C) 2001",
+};
+
+/* UDPSink signals and args */
+enum {
+  FRAME_ENCODED,
+  /* FILL ME */
+  LAST_SIGNAL
+};
+
+enum {
+  ARG_0,
+  ARG_HOST,
+  ARG_PORT,
+  /* FILL ME */
+};
+
+static void            gst_udpsink_class_init          (GstUDPSink *klass);
+static void            gst_udpsink_init                (GstUDPSink *udpsink);
+
+static void            gst_udpsink_chain               (GstPad *pad,GstBuffer *buf);
+static GstElementStateReturn gst_udpsink_change_state  (GstElement *element);
+
+static void            gst_udpsink_set_property        (GObject *object, guint prop_id, 
+                                                        const GValue *value, GParamSpec *pspec);
+static void            gst_udpsink_get_property        (GObject *object, guint prop_id, 
+                                                        GValue *value, GParamSpec *pspec);
+
+
+static GstElementClass *parent_class = NULL;
+//static guint gst_udpsink_signals[LAST_SIGNAL] = { 0 };
+
+GType
+gst_udpsink_get_type (void)
+{
+  static GType udpsink_type = 0;
+
+
+  if (!udpsink_type) {
+    static const GTypeInfo udpsink_info = {
+      sizeof(GstUDPSinkClass),
+      NULL,
+      NULL,
+      (GClassInitFunc)gst_udpsink_class_init,
+      NULL,
+      NULL,
+      sizeof(GstUDPSink),
+      0,
+      (GInstanceInitFunc)gst_udpsink_init,
+      NULL
+    };
+    udpsink_type = g_type_register_static (GST_TYPE_ELEMENT, "GstUDPSink", &udpsink_info, 0);
+  }
+  return udpsink_type;
+}
+
+static void
+gst_udpsink_class_init (GstUDPSink *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_HOST,
+    g_param_spec_string ("host", "nost", "The host to send the packets to",
+                         UDP_DEFAULT_HOST, G_PARAM_READWRITE)); 
+  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_PORT,
+    g_param_spec_int ("port", "port", "The port to send the packets to",
+                       0, 32768, UDP_DEFAULT_PORT, G_PARAM_READWRITE)); 
+
+  gobject_class->set_property = gst_udpsink_set_property;
+  gobject_class->get_property = gst_udpsink_get_property;
+
+  gstelement_class->change_state = gst_udpsink_change_state;
+}
+
+
+static void
+gst_udpsink_newcaps (GstPad *pad, GstCaps *caps)
+{
+  GstUDPSink *udpsink;
+  struct sockaddr_in serv_addr;
+  struct hostent *serverhost;
+  int fd;
+  FILE *f;
+#ifndef GST_DISABLE_LOADSAVE
+  xmlDocPtr doc;
+#endif
+
+  udpsink = GST_UDPSINK (gst_pad_get_parent (pad));
+
+  fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+  if (fd < 0) {
+     perror("socket");
+     return;
+  }
+  memset(&serv_addr, 0, sizeof(serv_addr));
+  /* its a name rather than an ipnum */
+  serverhost = gethostbyname(udpsink->host);
+  if (serverhost == (struct hostent *)0) {
+    perror("gethostbyname");
+    return;
+  }
+  memmove(&serv_addr.sin_addr,serverhost->h_addr, serverhost->h_length);
+
+  serv_addr.sin_family = AF_INET;
+  serv_addr.sin_port = htons(udpsink->port);
+
+  if (connect(fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) != 0) {
+    g_printerr ("udpsink: connect to %s port %d failed: %s\n",
+               udpsink->host, udpsink->port, sys_errlist[errno]);
+    return;
+  }
+  f = fdopen (dup (fd), "wb");
+
+#ifndef GST_DISABLE_LOADSAVE
+  doc = xmlNewDoc ("1.0");
+  doc->xmlRootNode = xmlNewDocNode (doc, NULL, "NewCaps", NULL);
+
+  gst_caps_save_thyself (caps, doc->xmlRootNode);
+  xmlDocDump(f, doc);
+#endif
+
+  fclose (f);
+  close (fd);
+}
+
+static void
+gst_udpsink_init (GstUDPSink *udpsink)
+{
+  /* create the sink and src pads */
+  udpsink->sinkpad = gst_pad_new ("sink", GST_PAD_SINK);
+  gst_element_add_pad (GST_ELEMENT (udpsink), udpsink->sinkpad);
+  gst_pad_set_chain_function (udpsink->sinkpad, gst_udpsink_chain);
+  gst_pad_set_newcaps_function (udpsink->sinkpad, gst_udpsink_newcaps);
+
+  udpsink->host = g_strdup (UDP_DEFAULT_HOST);
+  udpsink->port = UDP_DEFAULT_PORT;
+}
+
+static void
+gst_udpsink_chain (GstPad *pad, GstBuffer *buf)
+{
+  GstUDPSink *udpsink;
+  int tolen;
+
+  g_return_if_fail (pad != NULL);
+  g_return_if_fail (GST_IS_PAD (pad));
+  g_return_if_fail (buf != NULL);
+
+  udpsink = GST_UDPSINK (GST_OBJECT_PARENT (pad));
+
+  tolen = sizeof(udpsink->theiraddr);
+
+  if (sendto (udpsink->sock, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf), 0, 
+                         (struct sockaddr *) &udpsink->theiraddr, tolen) == -1)
+  {
+    perror("sending");
+  } 
+
+  gst_buffer_unref(buf);
+}
+
+static void
+gst_udpsink_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
+{
+  GstUDPSink *udpsink;
+
+  /* it's not null if we got it, but it might not be ours */
+  g_return_if_fail(GST_IS_UDPSINK(object));
+  udpsink = GST_UDPSINK(object);
+
+  switch (prop_id) {
+    case ARG_HOST:
+      if (udpsink->host != NULL) g_free(udpsink->host);
+      if (g_value_get_string (value) == NULL)
+        udpsink->host = NULL;
+      else
+        udpsink->host = g_strdup (g_value_get_string (value));
+      break;
+    case ARG_PORT:
+        udpsink->port = g_value_get_int (value);
+      break;
+    default:
+      break;
+  }
+}
+
+static void
+gst_udpsink_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
+{
+  GstUDPSink *udpsink;
+
+  /* it's not null if we got it, but it might not be ours */
+  g_return_if_fail(GST_IS_UDPSINK(object));
+  udpsink = GST_UDPSINK(object);
+
+  switch (prop_id) {
+    case ARG_HOST:
+      g_value_set_string (value, udpsink->host);
+      break;
+    case ARG_PORT:
+      g_value_set_int (value, udpsink->port);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+
+// create a socket for sending to remote machine
+static gboolean
+gst_udpsink_init_send (GstUDPSink *sink)
+{
+  struct hostent *he;
+
+  bzero (&sink->theiraddr, sizeof (sink->theiraddr));
+  sink->theiraddr.sin_family = AF_INET;         // host byte order
+  sink->theiraddr.sin_port = htons (sink->port);     // short, network byte order
+  if ((he = gethostbyname (sink->host)) == NULL) {
+    perror("gethostbyname");
+    return FALSE;
+  }
+  sink->theiraddr.sin_addr = *((struct in_addr *) he->h_addr);
+
+  if ((sink->sock = socket (AF_INET, SOCK_DGRAM, 0)) == -1) {
+    perror("socket");
+    return FALSE;
+  }
+
+  GST_FLAG_SET (sink, GST_UDPSINK_OPEN);
+
+  return TRUE;
+}
+
+static void
+gst_udpsink_close (GstUDPSink *sink)
+{
+  close (sink->sock);
+
+  GST_FLAG_UNSET (sink, GST_UDPSINK_OPEN);
+}
+
+static GstElementStateReturn
+gst_udpsink_change_state (GstElement *element)
+{
+  g_return_val_if_fail (GST_IS_UDPSINK (element), GST_STATE_FAILURE);
+
+  if (GST_STATE_PENDING (element) == GST_STATE_NULL) {
+    if (GST_FLAG_IS_SET (element, GST_UDPSINK_OPEN))
+      gst_udpsink_close (GST_UDPSINK (element));
+  } else {
+    if (!GST_FLAG_IS_SET (element, GST_UDPSINK_OPEN)) {
+      if (!gst_udpsink_init_send (GST_UDPSINK (element)))
+        return GST_STATE_FAILURE;
+    }
+  }
+
+  if (GST_ELEMENT_CLASS (parent_class)->change_state)
+    return GST_ELEMENT_CLASS (parent_class)->change_state (element);
+
+  return GST_STATE_SUCCESS;
+}
+
diff --git a/gst/udp/gstudpsink.h b/gst/udp/gstudpsink.h
new file mode 100644 (file)
index 0000000..4a7c335
--- /dev/null
@@ -0,0 +1,91 @@
+/* Gnome-Streamer
+ * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
+ *
+ * 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.
+ */
+
+
+#ifndef __GST_UDPSINK_H__
+#define __GST_UDPSINK_H__
+
+
+#include <config.h>
+#include <gst/gst.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <sys/socket.h>
+#include <sys/wait.h>
+#include <fcntl.h>
+
+#define GST_TYPE_UDPSINK \
+  (gst_udpsink_get_type())
+#define GST_UDPSINK(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_UDPSINK,GstUDPSink))
+#define GST_UDPSINK_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_UDPSINK,GstUDPSink))
+#define GST_IS_UDPSINK(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_UDPSINK))
+#define GST_IS_UDPSINK_CLASS(obj) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_UDPSINK))
+
+typedef struct _GstUDPSink GstUDPSink;
+typedef struct _GstUDPSinkClass GstUDPSinkClass;
+
+typedef enum {
+  GST_UDPSINK_OPEN             = GST_ELEMENT_FLAG_LAST,
+
+  GST_UDPSINK_FLAG_LAST        = GST_ELEMENT_FLAG_LAST + 2,
+} GstUDPSinkFlags;
+
+struct _GstUDPSink {
+  GstElement element;
+
+  /* pads */
+  GstPad *sinkpad,*srcpad;
+
+  int sock;
+  struct sockaddr_in theiraddr;
+
+  gint port;
+  gchar *host;
+};
+
+struct _GstUDPSinkClass {
+  GstElementClass parent_class;
+
+};
+
+GType gst_udpsink_get_type(void);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GST_UDPSINK_H__ */
diff --git a/gst/udp/gstudpsrc.c b/gst/udp/gstudpsrc.c
new file mode 100644 (file)
index 0000000..4400a06
--- /dev/null
@@ -0,0 +1,300 @@
+/* Gnome-Streamer
+ * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
+ *
+ * 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.
+ */
+
+
+#include "gstudpsrc.h"
+
+#define UDP_DEFAULT_PORT       4951
+
+/* elementfactory information */
+GstElementDetails gst_udpsrc_details = {
+  "UDP packet receiver",
+  "Transport/",
+  "",
+  VERSION,
+  "Wim Taymans <wim.taymans@chello.be>",
+  "(C) 2001",
+};
+
+/* UDPSrc signals and args */
+enum {
+  /* FILL ME */
+  LAST_SIGNAL
+};
+
+enum {
+  ARG_0,
+  ARG_PORT,
+  /* FILL ME */
+};
+
+static void            gst_udpsrc_class_init           (GstUDPSrc *klass);
+static void            gst_udpsrc_init                 (GstUDPSrc *udpsrc);
+
+static GstBuffer*      gst_udpsrc_get                  (GstPad *pad);
+static GstElementStateReturn
+                       gst_udpsrc_change_state         (GstElement *element);
+
+static void            gst_udpsrc_set_property         (GObject *object, guint prop_id, 
+                                                        const GValue *value, GParamSpec *pspec);
+static void            gst_udpsrc_get_property         (GObject *object, guint prop_id, 
+                                                        GValue *value, GParamSpec *pspec);
+
+static GstElementClass *parent_class = NULL;
+//static guint gst_udpsrc_signals[LAST_SIGNAL] = { 0 };
+
+GType
+gst_udpsrc_get_type (void)
+{
+  static GType udpsrc_type = 0;
+
+
+  if (!udpsrc_type) {
+    static const GTypeInfo udpsrc_info = {
+      sizeof(GstUDPSrcClass),
+      NULL,
+      NULL,
+      (GClassInitFunc)gst_udpsrc_class_init,
+      NULL,
+      NULL,
+      sizeof(GstUDPSrc),
+      0,
+      (GInstanceInitFunc)gst_udpsrc_init,
+      NULL
+    };
+    udpsrc_type = g_type_register_static (GST_TYPE_ELEMENT, "GstUDPSrc", &udpsrc_info, 0);
+  }
+  return udpsrc_type;
+}
+
+static void
+gst_udpsrc_class_init (GstUDPSrc *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_PORT,
+    g_param_spec_int ("port", "port", "The port to receive the packets from",
+                       0, 32768, UDP_DEFAULT_PORT, G_PARAM_READWRITE)); 
+
+  gobject_class->set_property = gst_udpsrc_set_property;
+  gobject_class->get_property = gst_udpsrc_get_property;
+
+  gstelement_class->change_state = gst_udpsrc_change_state;
+}
+
+
+static void
+gst_udpsrc_init (GstUDPSrc *udpsrc)
+{
+  /* create the src and src pads */
+  udpsrc->srcpad = gst_pad_new ("src", GST_PAD_SRC);
+  gst_element_add_pad (GST_ELEMENT (udpsrc), udpsrc->srcpad);
+  gst_pad_set_get_function (udpsrc->srcpad, gst_udpsrc_get);
+
+  udpsrc->port = UDP_DEFAULT_PORT;
+}
+
+static GstBuffer*
+gst_udpsrc_get (GstPad *pad)
+{
+  GstUDPSrc *udpsrc;
+  GstBuffer *outbuf;
+  struct sockaddr_in tmpaddr;
+  int len, numbytes;
+  fd_set read_fds;
+
+  g_return_val_if_fail (pad != NULL, NULL);
+  g_return_val_if_fail (GST_IS_PAD (pad), NULL);
+
+  udpsrc = GST_UDPSRC (GST_OBJECT_PARENT (pad));
+
+  FD_ZERO (&read_fds);
+  FD_SET (udpsrc->control_sock, &read_fds);
+  FD_SET (udpsrc->sock, &read_fds);
+
+  if (select (udpsrc->control_sock+1, &read_fds, NULL, NULL, NULL) > 0) {
+    if (FD_ISSET (udpsrc->control_sock, &read_fds)) {
+#ifndef GST_DISABLE_LOADSAVE
+      guchar *buf;
+      int ret;
+      int fdread;
+      struct sockaddr addr;
+      socklen_t len;
+      xmlDocPtr doc;
+      GstCaps *caps;
+
+      buf = g_malloc (1024*10);
+
+      len = sizeof (struct sockaddr);
+      fdread = accept (udpsrc->control_sock, &addr, &len);
+      if (fdread < 0) {
+       perror ("accept");
+      }
+      
+      ret = read (fdread, buf, 1024*10);
+      if (ret < 0) {
+       perror ("read");
+      }
+      buf[ret] = '\0';
+      doc = xmlParseMemory(buf, ret);
+      caps = gst_caps_load_thyself(doc->xmlRootNode);
+      
+      gst_pad_set_caps (udpsrc->srcpad, caps);
+
+#endif
+      outbuf = NULL;
+    }
+    else {
+      outbuf = gst_buffer_new ();
+      GST_BUFFER_DATA (outbuf) = g_malloc (24000);
+      GST_BUFFER_SIZE (outbuf) = 24000;
+
+      numbytes = recvfrom (udpsrc->sock, GST_BUFFER_DATA (outbuf),
+                 GST_BUFFER_SIZE (outbuf), 0, (struct sockaddr *)&tmpaddr, &len);
+
+      if (numbytes != -1) {
+        GST_BUFFER_SIZE (outbuf) = numbytes;
+      }
+      else {
+       perror ("recvfrom");
+        gst_buffer_unref (outbuf);
+        outbuf = NULL;
+      }
+  
+    }
+  }
+  else {
+    perror ("select");
+    outbuf = NULL;
+  }
+  return outbuf;
+}
+
+
+static void
+gst_udpsrc_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
+{
+  GstUDPSrc *udpsrc;
+
+  /* it's not null if we got it, but it might not be ours */
+  g_return_if_fail(GST_IS_UDPSRC(object));
+  udpsrc = GST_UDPSRC(object);
+
+  switch (prop_id) {
+    case ARG_PORT:
+        udpsrc->port = g_value_get_int (value);
+      break;
+    default:
+      break;
+  }
+}
+
+static void
+gst_udpsrc_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
+{
+  GstUDPSrc *udpsrc;
+
+  /* it's not null if we got it, but it might not be ours */
+  g_return_if_fail(GST_IS_UDPSRC(object));
+  udpsrc = GST_UDPSRC(object);
+
+  switch (prop_id) {
+    case ARG_PORT:
+      g_value_set_int (value, udpsrc->port);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+// create a socket for sending to remote machine
+static gboolean
+gst_udpsrc_init_receive (GstUDPSrc *src)
+{
+  bzero (&src->myaddr, sizeof (src->myaddr));
+  src->myaddr.sin_family = AF_INET;         // host byte order
+  src->myaddr.sin_port = htons (src->port);     // short, network byte order
+  src->myaddr.sin_addr.s_addr = INADDR_ANY;
+
+  if ((src->sock = socket (AF_INET, SOCK_DGRAM, 0)) == -1) {
+    perror("socket");
+    return FALSE;
+  }
+
+  if (bind (src->sock, (struct sockaddr *) &src->myaddr, sizeof (src->myaddr)) == -1) {
+    perror("bind");
+    return FALSE;
+  }
+
+  if ((src->control_sock = socket (AF_INET, SOCK_STREAM, 0)) == -1) {
+    perror("control_socket");
+    return FALSE;
+  }
+
+  if (bind (src->control_sock, (struct sockaddr *) &src->myaddr, sizeof (src->myaddr)) == -1) {
+    perror("control_bind");
+    return FALSE;
+  }
+  if (listen (src->control_sock, 5) == -1) {
+    perror("listen");
+    return FALSE;
+  }
+  fcntl (src->control_sock, F_SETFL, O_NONBLOCK);
+
+  GST_FLAG_SET (src, GST_UDPSRC_OPEN);
+
+  return TRUE;
+}
+
+static void
+gst_udpsrc_close (GstUDPSrc *src)
+{
+  close (src->sock);
+
+  GST_FLAG_UNSET (src, GST_UDPSRC_OPEN);
+}
+
+static GstElementStateReturn
+gst_udpsrc_change_state (GstElement *element)
+{
+  g_return_val_if_fail (GST_IS_UDPSRC (element), GST_STATE_FAILURE);
+
+  if (GST_STATE_PENDING (element) == GST_STATE_NULL) {
+    if (GST_FLAG_IS_SET (element, GST_UDPSRC_OPEN))
+      gst_udpsrc_close (GST_UDPSRC (element));
+  } else {
+    if (!GST_FLAG_IS_SET (element, GST_UDPSRC_OPEN)) {
+      if (!gst_udpsrc_init_receive (GST_UDPSRC (element)))
+        return GST_STATE_FAILURE;
+    }
+  }
+
+  if (GST_ELEMENT_CLASS (parent_class)->change_state)
+    return GST_ELEMENT_CLASS (parent_class)->change_state (element);
+
+  return GST_STATE_SUCCESS;
+}
+
diff --git a/gst/udp/gstudpsrc.h b/gst/udp/gstudpsrc.h
new file mode 100644 (file)
index 0000000..cf0d1d3
--- /dev/null
@@ -0,0 +1,88 @@
+/* Gnome-Streamer
+ * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
+ *
+ * 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.
+ */
+
+
+#ifndef __GST_UDPSRC_H__
+#define __GST_UDPSRC_H__
+
+#include <config.h>
+#include <gst/gst.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <sys/socket.h>
+#include <sys/wait.h>
+#include <fcntl.h>
+
+#define GST_TYPE_UDPSRC \
+  (gst_udpsrc_get_type())
+#define GST_UDPSRC(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_UDPSRC,GstUDPSrc))
+#define GST_UDPSRC_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_UDPSRC,GstUDPSrc))
+#define GST_IS_UDPSRC(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_UDPSRC))
+#define GST_IS_UDPSRC_CLASS(obj) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_UDPSRC))
+
+typedef struct _GstUDPSrc GstUDPSrc;
+typedef struct _GstUDPSrcClass GstUDPSrcClass;
+
+typedef enum {
+  GST_UDPSRC_OPEN             = GST_ELEMENT_FLAG_LAST,
+
+  GST_UDPSRC_FLAG_LAST        = GST_ELEMENT_FLAG_LAST + 2,
+} GstUDPSrcFlags;
+
+struct _GstUDPSrc {
+  GstElement element;
+
+  /* pads */
+  GstPad *sinkpad,*srcpad;
+
+  int port;
+  int sock;
+  int control_sock;
+  struct sockaddr_in myaddr;
+};
+
+struct _GstUDPSrcClass {
+  GstElementClass parent_class;
+};
+
+GType gst_udpsrc_get_type(void);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GST_UDPSRC_H__ */
diff --git a/gst/wavparse/.gitignore b/gst/wavparse/.gitignore
new file mode 100644 (file)
index 0000000..08f5ed3
--- /dev/null
@@ -0,0 +1,7 @@
+Makefile
+Makefile.in
+*.o
+*.lo
+*.la
+.deps
+.libs
diff --git a/gst/wavparse/Makefile.am b/gst/wavparse/Makefile.am
new file mode 100644 (file)
index 0000000..d9c8e4d
--- /dev/null
@@ -0,0 +1,8 @@
+filterdir = $(libdir)/gst
+
+filter_LTLIBRARIES = libgstwavparse.la
+
+libgstwavparse_la_SOURCES = gstwavparse.c gstriff.c
+libgstwavparse_la_CFLAGS = $(GST_CFLAGS)
+
+noinst_HEADERS = gstwavparse.h gstriff.h
diff --git a/gst/wavparse/gstriff.c b/gst/wavparse/gstriff.c
new file mode 100644 (file)
index 0000000..d343568
--- /dev/null
@@ -0,0 +1,144 @@
+/* Gnome-Streamer
+ * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
+ *
+ * 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.
+ */
+
+
+#include <stdlib.h>
+#include <gstriff.h>
+
+
+GstRiff *gst_riff_new() {
+  GstRiff *riff;
+
+  riff = (GstRiff *)malloc(sizeof(GstRiff));
+  g_return_val_if_fail(riff != NULL, NULL);
+
+  riff->form = 0;
+  riff->chunks = NULL;
+  riff->state = 0;
+  riff->curoffset = 0;
+  riff->nextlikely = 0;
+
+  return riff;
+}
+
+gint gst_riff_next_buffer(GstRiff *riff,GstBuffer *buf,gulong off) {
+  gulong last;
+  GstRiffChunk *chunk;
+
+  g_return_val_if_fail(riff != NULL, 0);
+  g_return_val_if_fail(buf != NULL, 0);
+  g_return_val_if_fail(GST_BUFFER_DATA(buf) != NULL, 0);
+
+  last = off + GST_BUFFER_SIZE(buf);
+
+  if (off == 0) {
+    gulong *words = (gulong *)GST_BUFFER_DATA(buf);
+
+    /* verify this is a valid RIFF file, first of all */
+    if (words[0] != gst_riff_fourcc_to_id("RIFF")) {
+      riff->state = GST_RIFF_ENOTRIFF;
+      return riff->state;
+    }
+    riff->form = words[2];
+//    g_print("form is 0x%08x '%s'\n",words[2],gst_riff_id_to_fourcc(words[2]));
+    riff->nextlikely = 12;     /* skip 'RIFF', length, and form */
+  }
+
+  /* loop while the next likely chunk header is in this buffer */
+  while ((riff->nextlikely+8) < last) {
+    gulong *words = (gulong *)((guchar *)GST_BUFFER_DATA(buf) + riff->nextlikely);
+
+//    g_print("next likely chunk is at offset 0x%08x\n",riff->nextlikely);
+    chunk = (GstRiffChunk *)malloc(sizeof(GstRiffChunk));
+    g_return_val_if_fail(chunk != NULL,0);
+    chunk->offset = riff->nextlikely+8;        /* point to the actual data */
+    chunk->id = words[0];
+    chunk->size = words[1];
+//    g_print("chunk id is 0x%08x '%s' and is 0x%08x long\n",words[0],
+//            gst_riff_id_to_fourcc(words[0]),words[1]);
+    riff->nextlikely += 8 + chunk->size;       /* doesn't include hdr */
+    riff->chunks = g_list_prepend(riff->chunks,chunk);
+  }
+
+  return 0;
+}
+
+
+gulong gst_riff_fourcc_to_id(gchar *fourcc) {
+  g_return_val_if_fail(fourcc != NULL,0);
+
+  return (fourcc[0] << 0) | (fourcc[1] << 8) |
+         (fourcc[2] << 16) | (fourcc[3] << 24);
+}
+
+gchar *gst_riff_id_to_fourcc(gulong id) {
+  gchar *fourcc = (gchar *)malloc(5);
+
+  g_return_val_if_fail(fourcc != NULL, NULL);
+
+  fourcc[0] = (id >> 0) & 0xff;
+  fourcc[1] = (id >> 8) & 0xff;
+  fourcc[2] = (id >> 16) & 0xff;
+  fourcc[3] = (id >> 24) & 0xff;
+  fourcc[4] = 0;
+
+  return fourcc;
+}
+
+GList *gst_riff_get_chunk_list(GstRiff *riff) {
+  g_return_val_if_fail(riff != NULL, NULL);
+
+  return riff->chunks;
+}
+
+GstRiffChunk *gst_riff_get_chunk(GstRiff *riff,gchar *fourcc) {
+  GList *chunk;
+
+  g_return_val_if_fail(riff != NULL, NULL);
+  g_return_val_if_fail(fourcc != NULL, NULL);
+
+  chunk = riff->chunks;
+  while (chunk) {
+    if (((GstRiffChunk *)(chunk->data))->id == gst_riff_fourcc_to_id(fourcc))
+      return (GstRiffChunk *)(chunk->data);
+    chunk = g_list_next(chunk);
+  }
+
+  return NULL;
+}
+
+gulong gst_riff_get_nextlikely(GstRiff *riff) {
+  g_return_val_if_fail(riff != NULL, 0);
+
+  return riff->nextlikely;
+}
+
+/*
+    guchar *hchar = (guchar *)(buf->data);
+    gulong hlong = *(gulong *)(buf->data);
+
+    g_print("header is 0x%08x native, %02x %02x %02x %02x, '%c%c%c%c'\n",
+            hlong,
+            hchar[0],hchar[1],hchar[2],hchar[3],
+            hchar[0],hchar[1],hchar[2],hchar[3]);
+    g_print("header 0x%08x translates to '%s'\n",hlong,
+            gst_riff_id_to_fourcc(hlong));
+    g_print("header 0x%08x trancodes to 0x%08x\n",hlong,
+            gst_riff_fourcc_to_id(gst_riff_id_to_fourcc(hlong)));
+*/
diff --git a/gst/wavparse/gstriff.h b/gst/wavparse/gstriff.h
new file mode 100644 (file)
index 0000000..de959fd
--- /dev/null
@@ -0,0 +1,67 @@
+/* Gnome-Streamer
+ * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
+ *
+ * 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.
+ */
+
+
+#ifndef __GST_RIFF_H__
+#define __GST_RIFF_H__
+
+
+#include <gst/gstbuffer.h>
+#include <gst/gstplugin.h>
+
+
+#define GST_RIFF_ENOTRIFF -1           /* not a RIFF file */
+
+
+typedef struct _GstRiff GstRiff;
+typedef struct _GstRiffChunk GstRiffChunk;
+
+struct _GstRiff {
+  guint32 form;
+
+  /* list of chunks, most recent at the head */
+  GList *chunks;
+
+  /* parse state */
+  gint state;
+  guint32 curoffset;
+  guint32 nextlikely;
+};
+
+struct _GstRiffChunk {
+  gulong offset;
+
+  guint32 id;
+  guint32 size;
+};
+
+
+GstRiff *gst_riff_new();
+gint gst_riff_next_buffer(GstRiff *riff,GstBuffer *buf,gulong off);
+GList *gst_riff_get_chunk_list(GstRiff *riff);
+GstRiffChunk *gst_riff_get_chunk(GstRiff *riff,gchar *fourcc);
+GstRiffChunk *gst_riff_get_chunk_number(GstRiff *riff,gint number);
+
+gulong gst_riff_get_nextlikely(GstRiff *riff);
+
+gulong gst_riff_fourcc_to_id(gchar *fourcc);
+gchar *gst_riff_id_to_fourcc(gulong id);
+
+
+#endif /* __GST_RIFF_H__ */
diff --git a/gst/wavparse/gstwavparse.c b/gst/wavparse/gstwavparse.c
new file mode 100644 (file)
index 0000000..2e57da8
--- /dev/null
@@ -0,0 +1,367 @@
+/* Gnome-Streamer
+ * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
+ *
+ * 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.
+ */
+
+
+#include <string.h>
+
+#include <gstwavparse.h>
+
+static void            gst_parsewav_class_init (GstParseWavClass *klass);
+static void            gst_parsewav_init       (GstParseWav *parsewav);
+
+static GstCaps*                wav_typefind            (GstBuffer *buf, gpointer private);
+
+static void            gst_parsewav_chain      (GstPad *pad, GstBuffer *buf);
+
+/* elementfactory information */
+static GstElementDetails gst_parsewav_details = {
+  ".wav parser",
+  "Parser/Audio",
+  "Parse a .wav file into raw audio",
+  VERSION,
+  "Erik Walthinsen <omega@cse.ogi.edu>",
+  "(C) 1999",
+};
+
+GST_PADTEMPLATE_FACTORY (sink_template_factory,
+  "parsewav_sink",
+  GST_PAD_SINK,
+  GST_PAD_ALWAYS,
+  GST_CAPS_NEW (
+    "parsewav_wav",   
+    "audio/wav",  
+    NULL
+  )
+)
+
+GST_PADTEMPLATE_FACTORY (src_template_factory,
+  "parsewav_src",
+  GST_PAD_SRC,
+  GST_PAD_ALWAYS,
+  GST_CAPS_NEW (
+    "parsewav_raw",   
+    "audio/raw",  
+      "format",            GST_PROPS_STRING ("int"),
+       "law",              GST_PROPS_INT (0),
+       "endianness",       GST_PROPS_INT (G_BYTE_ORDER),
+       "signed",           GST_PROPS_BOOLEAN (TRUE),
+       "width",            GST_PROPS_LIST (
+                            GST_PROPS_INT (8),
+                            GST_PROPS_INT (16)
+                          ),
+       "depth",            GST_PROPS_LIST (
+                            GST_PROPS_INT (8),
+                            GST_PROPS_INT (16)
+                          ),
+       "rate",             GST_PROPS_INT_RANGE (8000, 48000), 
+       "channels",         GST_PROPS_INT_RANGE (1, 2)
+  )
+)
+
+/* typefactory for 'wav' */
+static GstTypeDefinition 
+wavdefinition = 
+{
+  "parsewav_audio/wav",
+  "audio/wav",
+  ".wav",
+  wav_typefind,
+};
+
+
+/* ParseWav signals and args */
+enum {
+  /* FILL ME */
+  LAST_SIGNAL
+};
+
+enum {
+  ARG_0,
+  /* FILL ME */
+};
+
+static GstElementClass *parent_class = NULL;
+//static guint gst_parsewav_signals[LAST_SIGNAL] = { 0 };
+
+GType
+gst_parsewav_get_type (void) 
+{
+  static GType parsewav_type = 0;
+
+  if (!parsewav_type) {
+    static const GTypeInfo parsewav_info = {
+      sizeof(GstParseWavClass),      NULL,
+      NULL,
+      (GClassInitFunc) gst_parsewav_class_init,
+      NULL,
+      NULL,
+      sizeof(GstParseWav),
+      0,
+      (GInstanceInitFunc) gst_parsewav_init,
+    };
+    parsewav_type = g_type_register_static (GST_TYPE_ELEMENT, "GstParseWav", &parsewav_info, 0);
+  }
+  return parsewav_type;
+}
+
+static void
+gst_parsewav_class_init (GstParseWavClass *klass) 
+{
+  GstElementClass *gstelement_class;
+
+  gstelement_class = (GstElementClass*) klass;
+
+  parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
+}
+
+static void 
+gst_parsewav_init (GstParseWav *parsewav) 
+{
+  parsewav->sinkpad = gst_pad_new_from_template (GST_PADTEMPLATE_GET (sink_template_factory), "sink");
+  gst_element_add_pad (GST_ELEMENT (parsewav), parsewav->sinkpad);
+  gst_pad_set_chain_function (parsewav->sinkpad, gst_parsewav_chain);
+
+  parsewav->srcpad = gst_pad_new_from_template (GST_PADTEMPLATE_GET (src_template_factory), "src");
+  gst_element_add_pad (GST_ELEMENT (parsewav), parsewav->srcpad);
+
+  parsewav->riff = NULL;
+
+  parsewav->state = GST_PARSEWAV_UNKNOWN;
+  parsewav->riff = NULL;
+  parsewav->riff_nextlikely = 0;
+  parsewav->size = 0;
+  parsewav->bps = 0;
+}
+
+static GstCaps*
+wav_typefind (GstBuffer *buf, gpointer private)
+{
+  gchar *data = GST_BUFFER_DATA (buf);
+
+  if (strncmp (&data[0], "RIFF", 4)) return NULL;
+  if (strncmp (&data[8], "WAVE", 4)) return NULL;
+
+  return gst_caps_new ("wav_typefind", "audio/wav", NULL);
+}
+
+
+static void
+gst_parsewav_chain (GstPad *pad, GstBuffer *buf)
+{
+  GstParseWav *parsewav;
+  gboolean buffer_riffed = FALSE;      /* so we don't parse twice */
+  gchar *data;
+  gulong size;
+
+  g_return_if_fail (pad != NULL);
+  g_return_if_fail (GST_IS_PAD (pad));
+  g_return_if_fail (buf != NULL);
+  g_return_if_fail (GST_BUFFER_DATA (buf) != NULL);
+
+  parsewav = GST_PARSEWAV (gst_pad_get_parent (pad));
+  GST_DEBUG (0, "gst_parsewav_chain: got buffer in '%s'\n",
+          gst_object_get_name (GST_OBJECT (parsewav)));
+  data = (guchar *) GST_BUFFER_DATA (buf);
+  size = GST_BUFFER_SIZE (buf);
+
+  /* walk through the states in priority order */
+  /* we're in the data region */
+  if (parsewav->state == GST_PARSEWAV_DATA) {
+    /* if we're expected to see a new chunk in this buffer */
+    if ((parsewav->riff_nextlikely - GST_BUFFER_OFFSET (buf)) < GST_BUFFER_SIZE (buf)) {
+           
+      GST_BUFFER_SIZE (buf) = parsewav->riff_nextlikely - GST_BUFFER_OFFSET (buf);
+      
+      parsewav->state = GST_PARSEWAV_OTHER;
+      /* I suppose we could signal an EOF at this point, but that may be
+         premature.  We've stopped data flow, that's the main thing. */
+    } 
+    gst_pad_push (parsewav->srcpad, buf);
+    return;
+  }
+
+  if (parsewav->state == GST_PARSEWAV_OTHER) {
+    GST_DEBUG (0, "we're in unknown territory here, not passing on\n");
+    return;
+  }
+
+
+  /* here we deal with parsing out the primary state */
+  /* these are sequenced such that in the normal case each (RIFF/WAVE,
+     fmt, data) will fire in sequence, as they should */
+
+  /* we're in null state now, look for the RIFF header, start parsing */
+  if (parsewav->state == GST_PARSEWAV_UNKNOWN) {
+    gint retval;
+
+    GST_DEBUG (0, "GstParseWav: checking for RIFF format\n");
+
+    /* create a new RIFF parser */
+    parsewav->riff = gst_riff_new ();
+    
+    /* give it the current buffer to start parsing */
+    retval = gst_riff_next_buffer (parsewav->riff, buf, 0);
+    buffer_riffed = TRUE;
+    if (retval < 0) {
+      GST_DEBUG (0, "sorry, isn't RIFF\n");
+      return;
+    }
+
+    /* this has to be a file of form WAVE for us to deal with it */
+    if (parsewav->riff->form != gst_riff_fourcc_to_id ("WAVE")) {
+      GST_DEBUG (0, "sorry, isn't WAVE\n");
+      return;
+    }
+
+    /* at this point we're waiting for the 'fmt ' chunk */
+    parsewav->state = GST_PARSEWAV_CHUNK_FMT;
+  }
+
+  /* we're now looking for the 'fmt ' chunk to get the audio info */
+  if (parsewav->state == GST_PARSEWAV_CHUNK_FMT) {
+    GstRiffChunk *fmt;
+    GstParseWavFormat *format;
+
+    GST_DEBUG (0, "GstParseWav: looking for fmt chunk\n");
+
+    /* there's a good possibility we may not have parsed this buffer */
+    if (buffer_riffed == FALSE) {
+      gst_riff_next_buffer (parsewav->riff, buf, GST_BUFFER_OFFSET (buf));
+      buffer_riffed = TRUE;
+    }
+
+    /* see if the fmt chunk is available yet */
+    fmt = gst_riff_get_chunk (parsewav->riff, "fmt ");
+
+    /* if we've got something, deal with it */
+    if (fmt != NULL) {
+
+      /* we can gather format information now */
+      format = (GstParseWavFormat *)((guchar *) GST_BUFFER_DATA (buf) + fmt->offset);
+
+      /* set the caps on the src pad */
+      gst_pad_set_caps (parsewav->srcpad, gst_caps_new (
+       "parsewav_src",
+       "audio/raw",
+       gst_props_new (
+       "format",       GST_PROPS_STRING ("int"),
+         "law",        GST_PROPS_INT (0),              //FIXME
+         "endianness", GST_PROPS_INT (G_BYTE_ORDER),
+          "signed",     GST_PROPS_BOOLEAN (TRUE), //FIXME
+         "width",      GST_PROPS_INT (format->wBitsPerSample),
+         "depth",      GST_PROPS_INT (format->wBitsPerSample),
+         "rate",       GST_PROPS_INT (format->dwSamplesPerSec),
+         "channels",   GST_PROPS_INT (format->wChannels),
+         NULL
+       )
+      ));
+
+      parsewav->bps = format->wBlockAlign;
+      GST_DEBUG (0, "frequency %d, channels %d\n",
+                format->dwSamplesPerSec, format->wChannels); 
+
+      /* we're now looking for the data chunk */
+      parsewav->state = GST_PARSEWAV_CHUNK_DATA;
+    } else {
+      /* otherwise we just sort of give up for this buffer */
+      gst_buffer_unref (buf);
+      return;
+    }
+  }
+
+  /* now we look for the data chunk */
+  if (parsewav->state == GST_PARSEWAV_CHUNK_DATA) {
+    GstBuffer *newbuf;
+    GstRiffChunk *datachunk;
+
+    GST_DEBUG (0, "GstParseWav: looking for data chunk\n");
+
+    /* again, we might need to parse the buffer */
+    if (buffer_riffed == FALSE) {
+      gst_riff_next_buffer (parsewav->riff, buf, GST_BUFFER_OFFSET (buf));
+      buffer_riffed = TRUE;
+    }
+
+    datachunk = gst_riff_get_chunk (parsewav->riff, "data");
+
+    if (datachunk != NULL) {
+      gulong subsize;
+
+      GST_DEBUG (0, "data begins at %ld\n", datachunk->offset);
+
+      /* at this point we can ACK that we have data */
+      parsewav->state = GST_PARSEWAV_DATA;
+
+      /* now we construct a new buffer for the remainder */
+      subsize = size - datachunk->offset;
+      GST_DEBUG (0, "sending last %ld bytes along as audio\n", subsize);
+      
+      newbuf = gst_buffer_new ();
+      GST_BUFFER_DATA (newbuf) = g_malloc (subsize);
+      GST_BUFFER_SIZE (newbuf) = subsize;
+      
+      memcpy (GST_BUFFER_DATA (newbuf), GST_BUFFER_DATA (buf) + datachunk->offset, subsize);
+
+      gst_buffer_unref (buf);
+
+      gst_pad_push (parsewav->srcpad, newbuf);
+
+      /* now we're ready to go, the next buffer should start data */
+      parsewav->state = GST_PARSEWAV_DATA;
+
+      /* however, we may be expecting another chunk at some point */
+      parsewav->riff_nextlikely = gst_riff_get_nextlikely (parsewav->riff);
+    } else {
+      /* otherwise we just sort of give up for this buffer */
+      gst_buffer_unref (buf);
+      return;
+    }
+  }
+}
+
+
+static gboolean
+plugin_init (GModule *module, GstPlugin *plugin)
+{
+  GstElementFactory *factory;
+  GstTypeFactory *type;
+
+  /* create an elementfactory for the parsewav element */
+  factory = gst_elementfactory_new ("parsewav", GST_TYPE_PARSEWAV,
+                                    &gst_parsewav_details);
+  g_return_val_if_fail(factory != NULL, FALSE);
+
+  /* register src pads */
+  gst_elementfactory_add_padtemplate (factory, GST_PADTEMPLATE_GET (sink_template_factory));
+  gst_elementfactory_add_padtemplate (factory, GST_PADTEMPLATE_GET (src_template_factory));
+
+  gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (factory));
+
+  type = gst_typefactory_new (&wavdefinition);
+  gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (type));
+
+  return TRUE;
+}
+
+GstPluginDesc plugin_desc = {
+  GST_VERSION_MAJOR,
+  GST_VERSION_MINOR,
+  "parsewav",
+  plugin_init
+};
diff --git a/gst/wavparse/gstwavparse.h b/gst/wavparse/gstwavparse.h
new file mode 100644 (file)
index 0000000..55cb491
--- /dev/null
@@ -0,0 +1,99 @@
+/* Gnome-Streamer
+ * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
+ *
+ * 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.
+ */
+
+
+#ifndef __GST_PARSEWAV_H__
+#define __GST_PARSEWAV_H__
+
+
+#include <config.h>
+#include <gst/gst.h>
+#include <gstriff.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define GST_TYPE_PARSEWAV \
+  (gst_parsewav_get_type())
+#define GST_PARSEWAV(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_PARSEWAV,GstParseWav))
+#define GST_PARSEWAV_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_PARSEWAV,GstParseWav))
+#define GST_IS_PARSEWAV(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_PARSEWAV))
+#define GST_IS_PARSEWAV_CLASS(obj) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_PARSEWAV))
+
+
+#define GST_PARSEWAV_UNKNOWN   0       /* initialized state */
+#define GST_PARSEWAV_CHUNK_FMT 1       /* searching for fmt */
+#define GST_PARSEWAV_CHUNK_DATA        2       /* searching for data */
+#define GST_PARSEWAV_DATA      3       /* in data region */
+#define GST_PARSEWAV_OTHER     4       /* in unknown region */
+
+typedef struct _GstParseWav GstParseWav;
+typedef struct _GstParseWavClass GstParseWavClass;
+
+struct _GstParseWav {
+  GstElement element;
+
+  /* pads */
+  GstPad *sinkpad,*srcpad;
+
+  /* WAVE decoding state */
+  gint state;
+
+  /* RIFF decoding state */
+  GstRiff *riff;
+  gulong riff_nextlikely;
+
+  /* expected length of audio */
+  gulong size;
+
+  /* useful audio data */
+  gint bps;
+
+};
+
+struct _GstParseWavClass {
+  GstElementClass parent_class;
+};
+
+GType gst_parsewav_get_type(void);
+
+typedef struct _GstParseWavFormat GstParseWavFormat;
+
+struct _GstParseWavFormat {
+  gint16 wFormatTag;
+  guint16 wChannels;
+  guint32 dwSamplesPerSec;
+  guint32 dwAvgBytesPerSec;
+  guint16 wBlockAlign;
+  guint16 wBitsPerSample;
+};
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GST_PARSEAU_H__ */