From b69e24cfa09c4482f496e7b5c69f1fb54edfccb6 Mon Sep 17 00:00:00 2001 From: Thomas Vander Stichele Date: Sun, 23 Dec 2001 14:29:43 +0000 Subject: added hermes Original commit message from CVS: added hermes --- ext/gsm/gstgsmenc.c | 191 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 191 insertions(+) create mode 100644 ext/gsm/gstgsmenc.c (limited to 'ext/gsm/gstgsmenc.c') diff --git a/ext/gsm/gstgsmenc.c b/ext/gsm/gstgsmenc.c new file mode 100644 index 00000000..73058a66 --- /dev/null +++ b/ext/gsm/gstgsmenc.c @@ -0,0 +1,191 @@ +/* Gnome-Streamer + * Copyright (C) <1999> Erik Walthinsen + * + * 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 + +#include "gstgsmenc.h" + +extern GstPadTemplate *gsmenc_src_template, *gsmenc_sink_template; + +/* elementfactory information */ +GstElementDetails gst_gsmenc_details = { + "gsm audio encoder", + "Filter/Encoder/Audio", + ".gsm", + VERSION, + "Wim Taymans ", + "(C) 2000", +}; + +/* GSMEnc signals and args */ +enum { + FRAME_ENCODED, + /* FILL ME */ + LAST_SIGNAL +}; + +enum { + ARG_0, + /* FILL ME */ +}; + +static void gst_gsmenc_class_init (GstGSMEnc *klass); +static void gst_gsmenc_init (GstGSMEnc *gsmenc); + +static void gst_gsmenc_chain (GstPad *pad,GstBuffer *buf); +static void gst_gsmenc_newcaps (GstPad *pad, GstCaps *caps); + +static GstElementClass *parent_class = NULL; +static guint gst_gsmenc_signals[LAST_SIGNAL] = { 0 }; + +GType +gst_gsmenc_get_type (void) +{ + static GType gsmenc_type = 0; + + if (!gsmenc_type) { + static const GTypeInfo gsmenc_info = { + sizeof (GstGSMEncClass), + NULL, + NULL, + (GClassInitFunc) gst_gsmenc_class_init, + NULL, + NULL, + sizeof (GstGSMEnc), + 0, + (GInstanceInitFunc) gst_gsmenc_init, + }; + gsmenc_type = g_type_register_static (GST_TYPE_ELEMENT, "GstGSMEnc", &gsmenc_info, 0); + } + return gsmenc_type; +} + +static void +gst_gsmenc_class_init (GstGSMEnc *klass) +{ + GObjectClass *gobject_class; + GstElementClass *gstelement_class; + + gobject_class = (GObjectClass*) klass; + gstelement_class = (GstElementClass*) klass; + + parent_class = g_type_class_ref (GST_TYPE_ELEMENT); + + gst_gsmenc_signals[FRAME_ENCODED] = + g_signal_new ("frame_encoded", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GstGSMEncClass, frame_encoded), NULL, NULL, + g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); +} + + +static void +gst_gsmenc_init (GstGSMEnc *gsmenc) +{ + /* create the sink and src pads */ + gsmenc->sinkpad = gst_pad_new_from_template (gsmenc_sink_template, "sink"); + gst_element_add_pad (GST_ELEMENT (gsmenc), gsmenc->sinkpad); + gst_pad_set_chain_function (gsmenc->sinkpad, gst_gsmenc_chain); + gst_pad_set_newcaps_function (gsmenc->sinkpad, gst_gsmenc_newcaps); + + gsmenc->srcpad = gst_pad_new_from_template (gsmenc_src_template, "src"); + gst_element_add_pad (GST_ELEMENT (gsmenc), gsmenc->srcpad); + + gsmenc->state = gsm_create (); + gsmenc->bufsize = 0; + gsmenc->next_ts = 0; + gsmenc->rate = 8000; +} + +static void +gst_gsmenc_newcaps (GstPad *pad, GstCaps *caps) +{ + GstGSMEnc *gsmenc; + + gsmenc = GST_GSMENC (gst_pad_get_parent (pad)); + + gsmenc->rate = gst_caps_get_int (caps, "rate"); + + gst_pad_set_caps (gsmenc->srcpad, GST_CAPS_NEW ( + "gsm_gsm", + "audio/x-gsm", + "rate", GST_PROPS_INT (gsmenc->rate) + )); +} + +static void +gst_gsmenc_chain (GstPad *pad, GstBuffer *buf) +{ + GstGSMEnc *gsmenc; + gsm_signal *data; + guint size; + + g_return_if_fail (pad != NULL); + g_return_if_fail (GST_IS_PAD (pad)); + g_return_if_fail (buf != NULL); + + gsmenc = GST_GSMENC (GST_OBJECT_PARENT (pad)); + + data = (gsm_signal*) GST_BUFFER_DATA (buf); + size = GST_BUFFER_SIZE (buf) / sizeof (gsm_signal); + + if (gsmenc->bufsize && (gsmenc->bufsize + size >= 160)) { + GstBuffer *outbuf; + + memcpy (gsmenc->buffer + gsmenc->bufsize, data, (160 - gsmenc->bufsize) * sizeof (gsm_signal)); + + outbuf = gst_buffer_new (); + GST_BUFFER_DATA (outbuf) = g_malloc (33 * sizeof (gsm_byte)); + GST_BUFFER_SIZE (outbuf) = 33 * sizeof (gsm_byte); + + gsm_encode (gsmenc->state, gsmenc->buffer, (gsm_byte *) GST_BUFFER_DATA (outbuf)); + + GST_BUFFER_TIMESTAMP (outbuf) = gsmenc->next_ts; + gst_pad_push (gsmenc->srcpad, outbuf); + gsmenc->next_ts += (160.0 / gsmenc->rate) * 1000000; + + size -= (160 - gsmenc->bufsize); + data += (160 - gsmenc->bufsize); + gsmenc->bufsize = 0; + } + + while (size >= 160) { + GstBuffer *outbuf; + + outbuf = gst_buffer_new (); + GST_BUFFER_DATA (outbuf) = g_malloc (33 * sizeof (gsm_byte)); + GST_BUFFER_SIZE (outbuf) = 33 * sizeof (gsm_byte); + + gsm_encode (gsmenc->state, data, (gsm_byte *) GST_BUFFER_DATA (outbuf)); + + GST_BUFFER_TIMESTAMP (outbuf) = gsmenc->next_ts; + gst_pad_push (gsmenc->srcpad, outbuf); + gsmenc->next_ts += (160.0 / gsmenc->rate) * 1000000; + + size -= 160; + data += 160; + } + + if (size) { + memcpy (gsmenc->buffer + gsmenc->bufsize, data, size * sizeof (gsm_signal)); + gsmenc->bufsize += size; + } + + gst_buffer_unref(buf); +} -- cgit v1.2.1