Initial revision

Original commit message from CVS:
Initial revision
This commit is contained in:
Andy Wingo 2001-12-22 23:27:31 +00:00
parent 87dab192cf
commit 185612aae3
54 changed files with 5926 additions and 0 deletions

9
gst/cutter/Makefile.am Normal file
View file

@ -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

38
gst/cutter/README Normal file
View file

@ -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

16
gst/cutter/filter.func Normal file
View file

@ -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);
}

419
gst/cutter/gstcutter.c Normal file
View file

@ -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;
}

84
gst/cutter/gstcutter.h Normal file
View file

@ -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__ */

9
gst/flx/Makefile.am Normal file
View file

@ -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

94
gst/flx/flx_color.c Normal file
View file

@ -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;
}

43
gst/flx/flx_color.h Normal file
View file

@ -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);

136
gst/flx/flx_fmt.h Normal file
View file

@ -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__ */

644
gst/flx/gstflxdec.c Normal file
View file

@ -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
};

79
gst/flx/gstflxdec.h Normal file
View file

@ -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__ */

12
gst/law/Makefile.am Normal file
View file

@ -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

195
gst/law/alaw-conversion.c Normal file
View file

@ -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);
}

12
gst/law/alaw-conversion.h Normal file
View file

@ -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

186
gst/law/alaw-decode.c Normal file
View file

@ -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;
}
}

69
gst/law/alaw-decode.h Normal file
View file

@ -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__ */

182
gst/law/alaw-encode.c Normal file
View file

@ -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;
}
}

69
gst/law/alaw-encode.h Normal file
View file

@ -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__ */

95
gst/law/alaw.c Normal file
View file

@ -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
};

102
gst/law/mulaw-conversion.c Normal file
View file

@ -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;
}
}

View file

@ -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

181
gst/law/mulaw-decode.c Normal file
View file

@ -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;
}
}

69
gst/law/mulaw-decode.h Normal file
View file

@ -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__ */

181
gst/law/mulaw-encode.c Normal file
View file

@ -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;
}
}

69
gst/law/mulaw-encode.h Normal file
View file

@ -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__ */

103
gst/law/mulaw.c Normal file
View file

@ -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
};

10
gst/level/Makefile.am Normal file
View file

@ -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

11
gst/level/README Normal file
View file

@ -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

45
gst/level/filter.func Normal file
View file

@ -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);
}

285
gst/level/gstlevel.c Normal file
View file

@ -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
};

69
gst/level/gstlevel.h Normal file
View file

@ -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__ */

7
gst/median/.gitignore vendored Normal file
View file

@ -0,0 +1,7 @@
Makefile
Makefile.in
*.o
*.lo
*.la
.deps
.libs

9
gst/median/Makefile.am Normal file
View file

@ -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

412
gst/median/gstmedian.c Normal file
View file

@ -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
};

72
gst/median/gstmedian.h Normal file
View file

@ -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__ */

7
gst/spectrum/.gitignore vendored Normal file
View file

@ -0,0 +1,7 @@
Makefile
Makefile.in
*.o
*.lo
*.la
.deps
.libs

10
gst/spectrum/Makefile.am Normal file
View file

@ -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

5
gst/spectrum/README Normal file
View file

@ -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.

242
gst/spectrum/gstspectrum.c Normal file
View file

@ -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
};

View file

@ -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__ */

7
gst/udp/.gitignore vendored Normal file
View file

@ -0,0 +1,7 @@
Makefile
Makefile.in
*.o
*.lo
*.la
.deps
.libs

10
gst/udp/Makefile.am Normal file
View file

@ -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

28
gst/udp/README Normal file
View file

@ -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>

52
gst/udp/gstudp.c Normal file
View file

@ -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
};

301
gst/udp/gstudpsink.c Normal file
View file

@ -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;
}

91
gst/udp/gstudpsink.h Normal file
View file

@ -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__ */

300
gst/udp/gstudpsrc.c Normal file
View file

@ -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;
}

88
gst/udp/gstudpsrc.h Normal file
View file

@ -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__ */

7
gst/wavparse/.gitignore vendored Normal file
View file

@ -0,0 +1,7 @@
Makefile
Makefile.in
*.o
*.lo
*.la
.deps
.libs

8
gst/wavparse/Makefile.am Normal file
View file

@ -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

144
gst/wavparse/gstriff.c Normal file
View file

@ -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)));
*/

67
gst/wavparse/gstriff.h Normal file
View file

@ -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__ */

367
gst/wavparse/gstwavparse.c Normal file
View file

@ -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
};

View file

@ -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__ */