gst-indent
[platform/upstream/gst-plugins-good.git] / gst / law / alaw-decode.c
1 /* GStreamer
2  * Copyright (C) 1999 Erik Walthinsen <omega@cse.ogi.edu>
3  * PCM - A-Law conversion
4  *   Copyright (C) 2000 by Abramo Bagnara <abramo@alsa-project.org>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25 #include <gst/gst.h>
26 #include "alaw-decode.h"
27
28 extern GstPadTemplate *alawdec_src_template, *alawdec_sink_template;
29
30 /* elementfactory information */
31 static GstElementDetails alawdec_details = {
32   "A Law to PCM conversion",
33   "Codec/Decoder/Audio",
34   "Convert 8bit A law to 16bit PCM",
35   "Zaheer Merali <zaheer@bellworldwide.net>"
36 };
37
38 /* Stereo signals and args */
39 enum
40 {
41   /* FILL ME */
42   LAST_SIGNAL
43 };
44
45 enum
46 {
47   ARG_0
48 };
49
50 static void gst_alawdec_class_init (GstALawDecClass * klass);
51 static void gst_alawdec_base_init (GstALawDecClass * klass);
52 static void gst_alawdec_init (GstALawDec * alawdec);
53
54 static void gst_alawdec_set_property (GObject * object, guint prop_id,
55     const GValue * value, GParamSpec * pspec);
56 static void gst_alawdec_get_property (GObject * object, guint prop_id,
57     GValue * value, GParamSpec * pspec);
58
59 static void gst_alawdec_chain (GstPad * pad, GstData * _data);
60
61
62 static GstElementClass *parent_class = NULL;
63
64 /*static guint gst_stereo_signals[LAST_SIGNAL] = { 0 }; */
65
66 /*
67  * alaw_to_s16() - Convert an A-law value to 16-bit linear PCM
68  *
69  */
70 static gint
71 alaw_to_s16 (guint8 a_val)
72 {
73   gint t;
74   gint seg;
75
76   a_val ^= 0x55;
77   t = a_val & 0x7f;
78   if (t < 16)
79     t = (t << 4) + 8;
80   else {
81     seg = (t >> 4) & 0x07;
82     t = ((t & 0x0f) << 4) + 0x108;
83     t <<= seg - 1;
84   }
85   return ((a_val & 0x80) ? t : -t);
86 }
87
88 static GstPadLinkReturn
89 alawdec_link (GstPad * pad, const GstCaps * caps)
90 {
91   GstCaps *tempcaps;
92   gint rate, channels;
93   GstStructure *structure;
94   gboolean ret;
95
96   GstALawDec *alawdec = GST_ALAWDEC (GST_OBJECT_PARENT (pad));
97
98   structure = gst_caps_get_structure (caps, 0);
99
100   ret = gst_structure_get_int (structure, "rate", &rate);
101   ret &= gst_structure_get_int (structure, "channels", &channels);
102   if (!ret)
103     return GST_PAD_LINK_REFUSED;
104
105   tempcaps = gst_caps_new_simple ("audio/x-raw-int",
106       "depth", G_TYPE_INT, 16,
107       "width", G_TYPE_INT, 16,
108       "signed", G_TYPE_BOOLEAN, TRUE,
109       "endianness", G_TYPE_INT, G_BYTE_ORDER,
110       "rate", G_TYPE_INT, rate, "channels", G_TYPE_INT, channels, NULL);
111
112   return gst_pad_try_set_caps (alawdec->srcpad, tempcaps);
113 }
114
115 GType
116 gst_alawdec_get_type (void)
117 {
118   static GType alawdec_type = 0;
119
120   if (!alawdec_type) {
121     static const GTypeInfo alawdec_info = {
122       sizeof (GstALawDecClass),
123       (GBaseInitFunc) gst_alawdec_base_init,
124       NULL,
125       (GClassInitFunc) gst_alawdec_class_init,
126       NULL,
127       NULL,
128       sizeof (GstALawDec),
129       0,
130       (GInstanceInitFunc) gst_alawdec_init,
131     };
132     alawdec_type =
133         g_type_register_static (GST_TYPE_ELEMENT, "GstALawDec", &alawdec_info,
134         0);
135   }
136   return alawdec_type;
137 }
138
139 static void
140 gst_alawdec_base_init (GstALawDecClass * klass)
141 {
142   GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
143
144   gst_element_class_add_pad_template (element_class, alawdec_src_template);
145   gst_element_class_add_pad_template (element_class, alawdec_sink_template);
146   gst_element_class_set_details (element_class, &alawdec_details);
147 }
148
149 static void
150 gst_alawdec_class_init (GstALawDecClass * klass)
151 {
152   GObjectClass *gobject_class;
153   GstElementClass *gstelement_class;
154
155   gobject_class = (GObjectClass *) klass;
156   gstelement_class = (GstElementClass *) klass;
157
158   parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
159
160   gobject_class->set_property = gst_alawdec_set_property;
161   gobject_class->get_property = gst_alawdec_get_property;
162 }
163
164 static void
165 gst_alawdec_init (GstALawDec * alawdec)
166 {
167   alawdec->sinkpad = gst_pad_new_from_template (alawdec_sink_template, "sink");
168   alawdec->srcpad = gst_pad_new_from_template (alawdec_src_template, "src");
169   gst_pad_set_link_function (alawdec->sinkpad, alawdec_link);
170
171   gst_element_add_pad (GST_ELEMENT (alawdec), alawdec->sinkpad);
172   gst_pad_set_chain_function (alawdec->sinkpad, gst_alawdec_chain);
173   gst_element_add_pad (GST_ELEMENT (alawdec), alawdec->srcpad);
174 }
175
176 static void
177 gst_alawdec_chain (GstPad * pad, GstData * _data)
178 {
179   GstBuffer *buf = GST_BUFFER (_data);
180   GstALawDec *alawdec;
181   gint16 *linear_data;
182   guint8 *alaw_data;
183   GstBuffer *outbuf;
184   gint i;
185
186   g_return_if_fail (pad != NULL);
187   g_return_if_fail (GST_IS_PAD (pad));
188   g_return_if_fail (buf != NULL);
189
190   alawdec = GST_ALAWDEC (GST_OBJECT_PARENT (pad));
191   g_return_if_fail (alawdec != NULL);
192   g_return_if_fail (GST_IS_ALAWDEC (alawdec));
193
194   alaw_data = (guint8 *) GST_BUFFER_DATA (buf);
195   outbuf = gst_buffer_new ();
196   GST_BUFFER_DATA (outbuf) = (gchar *) g_new (gint16, GST_BUFFER_SIZE (buf));
197   GST_BUFFER_SIZE (outbuf) = GST_BUFFER_SIZE (buf) * 2;
198
199   linear_data = (gint16 *) GST_BUFFER_DATA (outbuf);
200   for (i = 0; i < GST_BUFFER_SIZE (buf); i++) {
201     *linear_data = alaw_to_s16 (*alaw_data);
202     linear_data++;
203     alaw_data++;
204   }
205
206   gst_buffer_unref (buf);
207   gst_pad_push (alawdec->srcpad, GST_DATA (outbuf));
208 }
209
210 static void
211 gst_alawdec_set_property (GObject * object, guint prop_id, const GValue * value,
212     GParamSpec * pspec)
213 {
214   GstALawDec *alawdec;
215
216   /* it's not null if we got it, but it might not be ours */
217   g_return_if_fail (GST_IS_ALAWDEC (object));
218   alawdec = GST_ALAWDEC (object);
219
220   switch (prop_id) {
221     default:
222       break;
223   }
224 }
225
226 static void
227 gst_alawdec_get_property (GObject * object, guint prop_id, GValue * value,
228     GParamSpec * pspec)
229 {
230   GstALawDec *alawdec;
231
232   /* it's not null if we got it, but it might not be ours */
233   g_return_if_fail (GST_IS_ALAWDEC (object));
234   alawdec = GST_ALAWDEC (object);
235
236   switch (prop_id) {
237     default:
238       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
239       break;
240   }
241 }