mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-17 03:35:21 +00:00
Initial revision
Original commit message from CVS: Initial revision
This commit is contained in:
parent
87dab192cf
commit
185612aae3
54 changed files with 5926 additions and 0 deletions
9
gst/cutter/Makefile.am
Normal file
9
gst/cutter/Makefile.am
Normal 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
38
gst/cutter/README
Normal 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
16
gst/cutter/filter.func
Normal 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
419
gst/cutter/gstcutter.c
Normal 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
84
gst/cutter/gstcutter.h
Normal 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
9
gst/flx/Makefile.am
Normal 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
94
gst/flx/flx_color.c
Normal 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
43
gst/flx/flx_color.h
Normal 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
136
gst/flx/flx_fmt.h
Normal 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
644
gst/flx/gstflxdec.c
Normal 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
79
gst/flx/gstflxdec.h
Normal 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
12
gst/law/Makefile.am
Normal 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
195
gst/law/alaw-conversion.c
Normal 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
12
gst/law/alaw-conversion.h
Normal 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
186
gst/law/alaw-decode.c
Normal 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
69
gst/law/alaw-decode.h
Normal 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
182
gst/law/alaw-encode.c
Normal 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
69
gst/law/alaw-encode.h
Normal 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
95
gst/law/alaw.c
Normal 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
102
gst/law/mulaw-conversion.c
Normal 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;
|
||||
}
|
||||
}
|
10
gst/law/mulaw-conversion.h
Normal file
10
gst/law/mulaw-conversion.h
Normal 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
181
gst/law/mulaw-decode.c
Normal 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
69
gst/law/mulaw-decode.h
Normal 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
181
gst/law/mulaw-encode.c
Normal 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
69
gst/law/mulaw-encode.h
Normal 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
103
gst/law/mulaw.c
Normal 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
10
gst/level/Makefile.am
Normal 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
11
gst/level/README
Normal 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
45
gst/level/filter.func
Normal 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
285
gst/level/gstlevel.c
Normal 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
69
gst/level/gstlevel.h
Normal 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
7
gst/median/.gitignore
vendored
Normal file
|
@ -0,0 +1,7 @@
|
|||
Makefile
|
||||
Makefile.in
|
||||
*.o
|
||||
*.lo
|
||||
*.la
|
||||
.deps
|
||||
.libs
|
9
gst/median/Makefile.am
Normal file
9
gst/median/Makefile.am
Normal 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
412
gst/median/gstmedian.c
Normal 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
72
gst/median/gstmedian.h
Normal 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
7
gst/spectrum/.gitignore
vendored
Normal file
|
@ -0,0 +1,7 @@
|
|||
Makefile
|
||||
Makefile.in
|
||||
*.o
|
||||
*.lo
|
||||
*.la
|
||||
.deps
|
||||
.libs
|
10
gst/spectrum/Makefile.am
Normal file
10
gst/spectrum/Makefile.am
Normal 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
5
gst/spectrum/README
Normal 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
242
gst/spectrum/gstspectrum.c
Normal 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
|
||||
};
|
67
gst/spectrum/gstspectrum.h
Normal file
67
gst/spectrum/gstspectrum.h
Normal 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
7
gst/udp/.gitignore
vendored
Normal file
|
@ -0,0 +1,7 @@
|
|||
Makefile
|
||||
Makefile.in
|
||||
*.o
|
||||
*.lo
|
||||
*.la
|
||||
.deps
|
||||
.libs
|
10
gst/udp/Makefile.am
Normal file
10
gst/udp/Makefile.am
Normal 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
28
gst/udp/README
Normal 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
52
gst/udp/gstudp.c
Normal 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
301
gst/udp/gstudpsink.c
Normal 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
91
gst/udp/gstudpsink.h
Normal 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
300
gst/udp/gstudpsrc.c
Normal 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
88
gst/udp/gstudpsrc.h
Normal 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
7
gst/wavparse/.gitignore
vendored
Normal file
|
@ -0,0 +1,7 @@
|
|||
Makefile
|
||||
Makefile.in
|
||||
*.o
|
||||
*.lo
|
||||
*.la
|
||||
.deps
|
||||
.libs
|
8
gst/wavparse/Makefile.am
Normal file
8
gst/wavparse/Makefile.am
Normal 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
144
gst/wavparse/gstriff.c
Normal 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
67
gst/wavparse/gstriff.h
Normal 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
367
gst/wavparse/gstwavparse.c
Normal 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
|
||||
};
|
99
gst/wavparse/gstwavparse.h
Normal file
99
gst/wavparse/gstwavparse.h
Normal 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__ */
|
Loading…
Reference in a new issue