]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - glsdk/gst-plugins-ugly0-10.git/blob - ext/amrnb/amrnbdec.c
ext/amrnb/: Core already took the lock.
[glsdk/gst-plugins-ugly0-10.git] / ext / amrnb / amrnbdec.c
1 /* GStreamer Adaptive Multi-Rate Narrow-Band (AMR-NB) plugin
2  * Copyright (C) 2004 Ronald Bultje <rbultje@ronald.bitfreak.net>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
24 #include "amrnbdec.h"
26 static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
27     GST_PAD_SINK,
28     GST_PAD_ALWAYS,
29     GST_STATIC_CAPS ("audio/x-amr-nb, "
30         "rate = (int) 8000, " "channels = (int) 1")
31     );
33 static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
34     GST_PAD_SRC,
35     GST_PAD_ALWAYS,
36     GST_STATIC_CAPS ("audio/x-raw-int, "
37         "width = (int) 16, "
38         "depth = (int) 16, "
39         "signed = (boolean) TRUE, "
40         "endianness = (int) BYTE_ORDER, "
41         "rate = (int) 8000," "channels = (int) 1")
42     );
44 static const gint block_size[16] = { 12, 13, 15, 17, 19, 20, 26, 31, 5,
45   0, 0, 0, 0, 0, 0, 0
46 };
48 static void gst_amrnbdec_base_init (GstAmrnbDecClass * klass);
49 static void gst_amrnbdec_class_init (GstAmrnbDecClass * klass);
50 static void gst_amrnbdec_init (GstAmrnbDec * amrnbdec);
52 static GstFlowReturn gst_amrnbdec_chain (GstPad * pad, GstBuffer * buffer);
53 static gboolean gst_amrnbdec_setcaps (GstPad * pad, GstCaps * caps);
54 static GstElementStateReturn gst_amrnbdec_state_change (GstElement * element);
56 static GstElementClass *parent_class = NULL;
58 GType
59 gst_amrnbdec_get_type (void)
60 {
61   static GType amrnbdec_type = 0;
63   if (!amrnbdec_type) {
64     static const GTypeInfo amrnbdec_info = {
65       sizeof (GstAmrnbDecClass),
66       (GBaseInitFunc) gst_amrnbdec_base_init,
67       NULL,
68       (GClassInitFunc) gst_amrnbdec_class_init,
69       NULL,
70       NULL,
71       sizeof (GstAmrnbDec),
72       0,
73       (GInstanceInitFunc) gst_amrnbdec_init,
74     };
76     amrnbdec_type = g_type_register_static (GST_TYPE_ELEMENT,
77         "GstAmrnbDec", &amrnbdec_info, 0);
78   }
80   return amrnbdec_type;
81 }
83 static void
84 gst_amrnbdec_base_init (GstAmrnbDecClass * klass)
85 {
86   GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
87   GstElementDetails gst_amrnbdec_details = {
88     "AMR-NB decoder",
89     "Codec/Decoder/Audio",
90     "Adaptive Multi-Rate Narrow-Band audio decoder",
91     "Ronald Bultje <rbultje@ronald.bitfreak.net>"
92   };
94   gst_element_class_add_pad_template (element_class,
95       gst_static_pad_template_get (&sink_template));
96   gst_element_class_add_pad_template (element_class,
97       gst_static_pad_template_get (&src_template));
99   gst_element_class_set_details (element_class, &gst_amrnbdec_details);
102 static void
103 gst_amrnbdec_class_init (GstAmrnbDecClass * klass)
105   GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
107   parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
109   element_class->change_state = gst_amrnbdec_state_change;
112 static void
113 gst_amrnbdec_init (GstAmrnbDec * amrnbdec)
115   /* create the sink pad */
116   amrnbdec->sinkpad =
117       gst_pad_new_from_template (gst_static_pad_template_get (&sink_template),
118       "sink");
119   gst_pad_set_setcaps_function (amrnbdec->sinkpad, gst_amrnbdec_setcaps);
120   gst_pad_set_chain_function (amrnbdec->sinkpad, gst_amrnbdec_chain);
121   gst_element_add_pad (GST_ELEMENT (amrnbdec), amrnbdec->sinkpad);
123   /* create the src pad */
124   amrnbdec->srcpad =
125       gst_pad_new_from_template (gst_static_pad_template_get (&src_template),
126       "src");
127   gst_pad_use_fixed_caps (amrnbdec->srcpad);
128   gst_element_add_pad (GST_ELEMENT (amrnbdec), amrnbdec->srcpad);
130   amrnbdec->adapter = gst_adapter_new ();
132   /* init rest */
133   amrnbdec->handle = NULL;
134   amrnbdec->channels = 0;
135   amrnbdec->rate = 0;
136   amrnbdec->ts = 0;
139 static gboolean
140 gst_amrnbdec_setcaps (GstPad * pad, GstCaps * caps)
142   GstStructure *structure;
143   GstAmrnbDec *amrnbdec;
144   GstCaps *copy;
146   amrnbdec = GST_AMRNBDEC (GST_PAD_PARENT (pad));
148   structure = gst_caps_get_structure (caps, 0);
150   /* get channel count */
151   gst_structure_get_int (structure, "channels", &amrnbdec->channels);
152   gst_structure_get_int (structure, "rate", &amrnbdec->rate);
154   /* create reverse caps */
155   copy = gst_caps_new_simple ("audio/x-raw-int",
156       "channels", G_TYPE_INT, amrnbdec->channels,
157       "width", G_TYPE_INT, 16,
158       "depth", G_TYPE_INT, 16,
159       "endianness", G_TYPE_INT, G_BYTE_ORDER,
160       "rate", G_TYPE_INT, amrnbdec->rate, "signed", G_TYPE_BOOLEAN, TRUE, NULL);
162   gst_pad_set_caps (amrnbdec->srcpad, copy);
163   gst_caps_unref (copy);
165   return TRUE;
168 static GstFlowReturn
169 gst_amrnbdec_chain (GstPad * pad, GstBuffer * buffer)
171   GstAmrnbDec *amrnbdec;
172   GstFlowReturn ret;
174   amrnbdec = GST_AMRNBDEC (GST_PAD_PARENT (pad));
176   if (amrnbdec->rate == 0 || amrnbdec->channels == 0)
177     goto not_negotiated;
179   if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer))
180     amrnbdec->ts = GST_BUFFER_TIMESTAMP (buffer);
182   gst_adapter_push (amrnbdec->adapter, buffer);
184   ret = GST_FLOW_OK;
186   while (TRUE) {
187     GstBuffer *out;
188     guint8 *data;
189     gint block, mode;
191     if (gst_adapter_available (amrnbdec->adapter) < 1)
192       break;
193     data = (guint8 *) gst_adapter_peek (amrnbdec->adapter, 1);
195     /* get size */
196     mode = (data[0] >> 3) & 0x0F;
197     block = block_size[mode] + 1;
199     if (gst_adapter_available (amrnbdec->adapter) < block)
200       break;
201     data = (guint8 *) gst_adapter_peek (amrnbdec->adapter, block);
203     /* get output */
204     out = gst_buffer_new_and_alloc (160 * 2);
205     GST_BUFFER_DURATION (out) = GST_SECOND * 160 /
206         (amrnbdec->rate * amrnbdec->channels);
207     GST_BUFFER_TIMESTAMP (out) = amrnbdec->ts;
208     amrnbdec->ts += GST_BUFFER_DURATION (out);
209     gst_buffer_set_caps (out, GST_RPAD_CAPS (amrnbdec->srcpad));
211     /* decode */
212     Decoder_Interface_Decode (amrnbdec->handle, data,
213         (short *) GST_BUFFER_DATA (out), 0);
215     gst_adapter_flush (amrnbdec->adapter, block);
217     /* play */
218     ret = gst_pad_push (amrnbdec->srcpad, out);
219   }
221   return ret;
223 not_negotiated:
224   {
225     return GST_FLOW_NOT_NEGOTIATED;
226   }
229 static GstElementStateReturn
230 gst_amrnbdec_state_change (GstElement * element)
232   GstAmrnbDec *amrnbdec;
233   GstElementStateReturn ret;
234   gint transition;
236   amrnbdec = GST_AMRNBDEC (element);
237   transition = GST_STATE_TRANSITION (element);
239   switch (transition) {
240     case GST_STATE_NULL_TO_READY:
241       if (!(amrnbdec->handle = Decoder_Interface_init ()))
242         return GST_STATE_FAILURE;
243       break;
244     case GST_STATE_READY_TO_PAUSED:
245       gst_adapter_clear (amrnbdec->adapter);
246       amrnbdec->ts = 0;
247       break;
248     default:
249       break;
250   }
252   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element);
254   switch (transition) {
255     case GST_STATE_READY_TO_NULL:
256       Decoder_Interface_exit (amrnbdec->handle);
257       break;
258     default:
259       break;
260   }
262   return ret;