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>
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.
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.
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.
26 #include "alaw-decode.h"
28 extern GstPadTemplate *alawdec_src_template, *alawdec_sink_template;
30 /* Stereo signals and args */
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);
46 static GstFlowReturn gst_alawdec_chain (GstPad * pad, GstBuffer * buffer);
48 static GstElementClass *parent_class = NULL;
50 /*static guint gst_stereo_signals[LAST_SIGNAL] = { 0 }; */
53 * alaw_to_s16() - Convert an A-law value to 16-bit linear PCM
57 alaw_to_s16 (guint8 a_val)
67 seg = (t >> 4) & 0x07;
68 t = ((t & 0x0f) << 4) + 0x108;
71 return ((a_val & 0x80) ? t : -t);
75 alawdec_getcaps (GstPad * pad)
79 GstCaps *base_caps, *othercaps;
81 alawdec = GST_ALAWDEC (GST_PAD_PARENT (pad));
83 /* we can do what our template says */
84 base_caps = gst_caps_copy (gst_pad_get_pad_template_caps (pad));
86 if (pad == alawdec->sinkpad) {
87 otherpad = alawdec->srcpad;
89 otherpad = alawdec->sinkpad;
91 /* now intersect rate and channels from peer caps */
92 othercaps = gst_pad_peer_get_caps (otherpad);
94 GstStructure *structure;
95 const GValue *orate, *ochans;
96 const GValue *rate, *chans;
97 GValue irate = { 0 }, ichans = {
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)
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");
112 gst_value_intersect (&irate, orate, rate);
113 gst_value_intersect (&ichans, ochans, chans);
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);
120 gst_caps_unref (othercaps);
128 alawdec_setcaps (GstPad * pad, GstCaps * caps)
132 GstStructure *structure;
133 const GValue *rate, *chans;
136 alawdec = GST_ALAWDEC (GST_PAD_PARENT (pad));
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");
145 if (pad == alawdec->srcpad) {
146 otherpad = alawdec->sinkpad;
148 otherpad = alawdec->srcpad;
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);
157 /* and set on otherpad */
158 gst_pad_set_caps (otherpad, base_caps);
160 gst_caps_unref (base_caps);
166 gst_alawdec_get_type (void)
168 static GType alawdec_type = 0;
171 static const GTypeInfo alawdec_info = {
172 sizeof (GstALawDecClass),
173 (GBaseInitFunc) gst_alawdec_base_init,
175 (GClassInitFunc) gst_alawdec_class_init,
180 (GInstanceInitFunc) gst_alawdec_init,
184 g_type_register_static (GST_TYPE_ELEMENT, "GstALawDec", &alawdec_info,
191 gst_alawdec_base_init (GstALawDecClass * klass)
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>"
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);
207 gst_alawdec_class_init (GstALawDecClass * klass)
209 parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
213 gst_alawdec_init (GstALawDec * alawdec)
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);
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);
228 gst_alawdec_chain (GstPad * pad, GstBuffer * buffer)
236 alawdec = GST_ALAWDEC (GST_OBJECT_PARENT (pad));
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);
245 for (i = 0; i < GST_BUFFER_SIZE (buffer); i++) {
246 *linear_data = alaw_to_s16 (*alaw_data);
251 gst_buffer_unref (buffer);
252 return gst_pad_push (alawdec->srcpad, outbuf);