configure.ac (GST_CFLAGS): GCC strikes back!!! Let the build breakage ensue!!!
[platform/upstream/gstreamer.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 /* Stereo signals and args */
31 enum
32 {
33   /* FILL ME */
34   LAST_SIGNAL
35 };
36
37 enum
38 {
39   ARG_0
40 };
41
42 static void gst_alawdec_class_init (GstALawDecClass * klass);
43 static void gst_alawdec_base_init (GstALawDecClass * klass);
44 static void gst_alawdec_init (GstALawDec * alawdec);
45
46 static GstFlowReturn gst_alawdec_chain (GstPad * pad, GstBuffer * buffer);
47
48 static GstElementClass *parent_class = NULL;
49
50 /*static guint gst_stereo_signals[LAST_SIGNAL] = { 0 }; */
51
52 /*
53  * alaw_to_s16() - Convert an A-law value to 16-bit linear PCM
54  *
55  */
56 static gint
57 alaw_to_s16 (guint8 a_val)
58 {
59   gint t;
60   gint seg;
61
62   a_val ^= 0x55;
63   t = a_val & 0x7f;
64   if (t < 16)
65     t = (t << 4) + 8;
66   else {
67     seg = (t >> 4) & 0x07;
68     t = ((t & 0x0f) << 4) + 0x108;
69     t <<= seg - 1;
70   }
71   return ((a_val & 0x80) ? t : -t);
72 }
73
74 static GstCaps *
75 alawdec_getcaps (GstPad * pad)
76 {
77   GstALawDec *alawdec;
78   GstPad *otherpad;
79   GstCaps *base_caps, *othercaps;
80
81   alawdec = GST_ALAWDEC (GST_PAD_PARENT (pad));
82
83   /*  we can do what our template says */
84   base_caps = gst_caps_copy (gst_pad_get_pad_template_caps (pad));
85
86   if (pad == alawdec->sinkpad) {
87     otherpad = alawdec->srcpad;
88   } else {
89     otherpad = alawdec->sinkpad;
90   }
91   /* now intersect rate and channels from peer caps */
92   othercaps = gst_pad_peer_get_caps (otherpad);
93   if (othercaps) {
94     GstStructure *structure;
95     const GValue *orate, *ochans;
96     const GValue *rate, *chans;
97     GValue irate = { 0 }, ichans = {
98     0};
99
100     structure = gst_caps_get_structure (othercaps, 0);
101     orate = gst_structure_get_value (structure, "rate");
102     ochans = gst_structure_get_value (structure, "channels");
103     if (!orate || !ochans)
104       goto done;
105
106     structure = gst_caps_get_structure (base_caps, 0);
107     rate = gst_structure_get_value (structure, "rate");
108     chans = gst_structure_get_value (structure, "channels");
109     if (!rate || !chans)
110       goto done;
111
112     gst_value_intersect (&irate, orate, rate);
113     gst_value_intersect (&ichans, ochans, chans);
114
115     /* Set the samplerate/channels on the to-be-returned caps */
116     structure = gst_caps_get_structure (base_caps, 0);
117     gst_structure_set_value (structure, "rate", &irate);
118     gst_structure_set_value (structure, "channels", &ichans);
119
120     gst_caps_unref (othercaps);
121   }
122
123 done:
124   return base_caps;
125 }
126
127 static gboolean
128 alawdec_setcaps (GstPad * pad, GstCaps * caps)
129 {
130   GstALawDec *alawdec;
131   GstPad *otherpad;
132   GstStructure *structure;
133   const GValue *rate, *chans;
134   GstCaps *base_caps;
135
136   alawdec = GST_ALAWDEC (GST_PAD_PARENT (pad));
137
138   /* take rate and channels */
139   structure = gst_caps_get_structure (caps, 0);
140   rate = gst_structure_get_value (structure, "rate");
141   chans = gst_structure_get_value (structure, "channels");
142   if (!rate || !chans)
143     return FALSE;
144
145   if (pad == alawdec->srcpad) {
146     otherpad = alawdec->sinkpad;
147   } else {
148     otherpad = alawdec->srcpad;
149   }
150
151   /* fill in values for otherpad */
152   base_caps = gst_caps_copy (gst_pad_get_pad_template_caps (otherpad));
153   structure = gst_caps_get_structure (base_caps, 0);
154   gst_structure_set_value (structure, "rate", rate);
155   gst_structure_set_value (structure, "channels", chans);
156
157   /* and set on otherpad */
158   gst_pad_set_caps (otherpad, base_caps);
159
160   gst_caps_unref (base_caps);
161
162   return TRUE;
163 }
164
165 GType
166 gst_alawdec_get_type (void)
167 {
168   static GType alawdec_type = 0;
169
170   if (!alawdec_type) {
171     static const GTypeInfo alawdec_info = {
172       sizeof (GstALawDecClass),
173       (GBaseInitFunc) gst_alawdec_base_init,
174       NULL,
175       (GClassInitFunc) gst_alawdec_class_init,
176       NULL,
177       NULL,
178       sizeof (GstALawDec),
179       0,
180       (GInstanceInitFunc) gst_alawdec_init,
181     };
182
183     alawdec_type =
184         g_type_register_static (GST_TYPE_ELEMENT, "GstALawDec", &alawdec_info,
185         0);
186   }
187   return alawdec_type;
188 }
189
190 static void
191 gst_alawdec_base_init (GstALawDecClass * klass)
192 {
193   GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
194   GstElementDetails alawdec_details = {
195     "A Law to PCM conversion",
196     "Codec/Decoder/Audio",
197     "Convert 8bit A law to 16bit PCM",
198     "Zaheer Abbas Merali <zaheerabbas at merali dot org>"
199   };
200
201   gst_element_class_add_pad_template (element_class, alawdec_src_template);
202   gst_element_class_add_pad_template (element_class, alawdec_sink_template);
203   gst_element_class_set_details (element_class, &alawdec_details);
204 }
205
206 static void
207 gst_alawdec_class_init (GstALawDecClass * klass)
208 {
209   parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
210 }
211
212 static void
213 gst_alawdec_init (GstALawDec * alawdec)
214 {
215   alawdec->sinkpad = gst_pad_new_from_template (alawdec_sink_template, "sink");
216   gst_pad_set_setcaps_function (alawdec->sinkpad, alawdec_setcaps);
217   gst_pad_set_getcaps_function (alawdec->sinkpad, alawdec_getcaps);
218   gst_pad_set_chain_function (alawdec->sinkpad, gst_alawdec_chain);
219   gst_element_add_pad (GST_ELEMENT (alawdec), alawdec->sinkpad);
220
221   alawdec->srcpad = gst_pad_new_from_template (alawdec_src_template, "src");
222   gst_pad_set_setcaps_function (alawdec->srcpad, alawdec_setcaps);
223   gst_pad_set_getcaps_function (alawdec->srcpad, alawdec_getcaps);
224   gst_element_add_pad (GST_ELEMENT (alawdec), alawdec->srcpad);
225 }
226
227 static GstFlowReturn
228 gst_alawdec_chain (GstPad * pad, GstBuffer * buffer)
229 {
230   GstALawDec *alawdec;
231   gint16 *linear_data;
232   guint8 *alaw_data;
233   GstBuffer *outbuf;
234   gint i;
235
236   alawdec = GST_ALAWDEC (GST_OBJECT_PARENT (pad));
237
238   alaw_data = (guint8 *) GST_BUFFER_DATA (buffer);
239   outbuf = gst_buffer_new_and_alloc (GST_BUFFER_SIZE (buffer) * 2);
240   GST_BUFFER_TIMESTAMP (outbuf) = GST_BUFFER_TIMESTAMP (buffer);
241   GST_BUFFER_DURATION (outbuf) = GST_BUFFER_DURATION (buffer);
242   gst_buffer_set_caps (outbuf, GST_PAD_CAPS (alawdec->srcpad));
243   linear_data = (gint16 *) GST_BUFFER_DATA (outbuf);
244
245   for (i = 0; i < GST_BUFFER_SIZE (buffer); i++) {
246     *linear_data = alaw_to_s16 (*alaw_data);
247     linear_data++;
248     alaw_data++;
249   }
250
251   gst_buffer_unref (buffer);
252   return gst_pad_push (alawdec->srcpad, outbuf);
253 }