gst/rtp/: Added very simplistic amr payloader. depayloader does not work yet.
[platform/upstream/gst-plugins-good.git] / gst / rtp / gstrtpamrdepay.c
1 /* GStreamer
2  * Copyright (C) <2005> Wim Taymans <wim@fluendo.com>
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 
13  */
14
15 #ifdef HAVE_CONFIG_H
16 #  include "config.h"
17 #endif
18
19 #include <gst/rtp/gstrtpbuffer.h>
20
21 #include <string.h>
22 #include "gstrtpamrdec.h"
23
24 /* elementfactory information */
25 static GstElementDetails gst_rtp_amrdec_details = {
26   "RTP packet parser",
27   "Codec/Parser/Network",
28   "Extracts MPEG audio from RTP packets",
29   "Wim Taymans <wim@fluendo.com>"
30 };
31
32 /* RtpAMRDec signals and args */
33 enum
34 {
35   /* FILL ME */
36   LAST_SIGNAL
37 };
38
39 enum
40 {
41   ARG_0,
42   ARG_FREQUENCY
43 };
44
45 static GstStaticPadTemplate gst_rtpamrdec_src_template =
46 GST_STATIC_PAD_TEMPLATE ("src",
47     GST_PAD_SRC,
48     GST_PAD_ALWAYS,
49     GST_STATIC_CAPS ("audio/mpeg")
50     );
51
52 static GstStaticPadTemplate gst_rtpamrdec_sink_template =
53 GST_STATIC_PAD_TEMPLATE ("sink",
54     GST_PAD_SINK,
55     GST_PAD_ALWAYS,
56     GST_STATIC_CAPS ("application/x-rtp")
57     );
58
59
60 static void gst_rtpamrdec_class_init (GstRtpAMRDecClass * klass);
61 static void gst_rtpamrdec_base_init (GstRtpAMRDecClass * klass);
62 static void gst_rtpamrdec_init (GstRtpAMRDec * rtpamrdec);
63
64 static GstFlowReturn gst_rtpamrdec_chain (GstPad * pad, GstBuffer * buffer);
65
66 static void gst_rtpamrdec_set_property (GObject * object, guint prop_id,
67     const GValue * value, GParamSpec * pspec);
68 static void gst_rtpamrdec_get_property (GObject * object, guint prop_id,
69     GValue * value, GParamSpec * pspec);
70
71 static GstElementStateReturn gst_rtpamrdec_change_state (GstElement * element);
72
73 static GstElementClass *parent_class = NULL;
74
75 static GType
76 gst_rtpamrdec_get_type (void)
77 {
78   static GType rtpamrdec_type = 0;
79
80   if (!rtpamrdec_type) {
81     static const GTypeInfo rtpamrdec_info = {
82       sizeof (GstRtpAMRDecClass),
83       (GBaseInitFunc) gst_rtpamrdec_base_init,
84       NULL,
85       (GClassInitFunc) gst_rtpamrdec_class_init,
86       NULL,
87       NULL,
88       sizeof (GstRtpAMRDec),
89       0,
90       (GInstanceInitFunc) gst_rtpamrdec_init,
91     };
92
93     rtpamrdec_type =
94         g_type_register_static (GST_TYPE_ELEMENT, "GstRtpAMRDec",
95         &rtpamrdec_info, 0);
96   }
97   return rtpamrdec_type;
98 }
99
100 static void
101 gst_rtpamrdec_base_init (GstRtpAMRDecClass * klass)
102 {
103   GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
104
105   gst_element_class_add_pad_template (element_class,
106       gst_static_pad_template_get (&gst_rtpamrdec_src_template));
107   gst_element_class_add_pad_template (element_class,
108       gst_static_pad_template_get (&gst_rtpamrdec_sink_template));
109
110   gst_element_class_set_details (element_class, &gst_rtp_amrdec_details);
111 }
112
113 static void
114 gst_rtpamrdec_class_init (GstRtpAMRDecClass * klass)
115 {
116   GObjectClass *gobject_class;
117   GstElementClass *gstelement_class;
118
119   gobject_class = (GObjectClass *) klass;
120   gstelement_class = (GstElementClass *) klass;
121
122   parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
123
124   gobject_class->set_property = gst_rtpamrdec_set_property;
125   gobject_class->get_property = gst_rtpamrdec_get_property;
126
127   gstelement_class->change_state = gst_rtpamrdec_change_state;
128 }
129
130 static void
131 gst_rtpamrdec_init (GstRtpAMRDec * rtpamrdec)
132 {
133   rtpamrdec->srcpad =
134       gst_pad_new_from_template (gst_static_pad_template_get
135       (&gst_rtpamrdec_src_template), "src");
136   gst_element_add_pad (GST_ELEMENT (rtpamrdec), rtpamrdec->srcpad);
137
138   rtpamrdec->sinkpad =
139       gst_pad_new_from_template (gst_static_pad_template_get
140       (&gst_rtpamrdec_sink_template), "sink");
141   gst_pad_set_chain_function (rtpamrdec->sinkpad, gst_rtpamrdec_chain);
142   gst_element_add_pad (GST_ELEMENT (rtpamrdec), rtpamrdec->sinkpad);
143 }
144
145 static GstFlowReturn
146 gst_rtpamrdec_chain (GstPad * pad, GstBuffer * buf)
147 {
148   GstRtpAMRDec *rtpamrdec;
149   GstBuffer *outbuf;
150   GstFlowReturn ret;
151
152   rtpamrdec = GST_RTP_AMR_DEC (GST_OBJECT_PARENT (pad));
153
154   if (!gst_rtpbuffer_validate (buf))
155     goto bad_packet;
156
157   {
158     gint payload_len;
159     guint8 *payload;
160     guint16 frag_offset;
161     guint32 timestamp;
162
163     payload_len = gst_rtpbuffer_get_payload_len (buf);
164     payload = gst_rtpbuffer_get_payload (buf);
165
166     frag_offset = (payload[2] << 8) | payload[3];
167
168     /* strip off header */
169     payload_len -= 4;
170     payload += 4;
171
172     timestamp = gst_rtpbuffer_get_timestamp (buf);
173
174     outbuf = gst_buffer_new_and_alloc (payload_len);
175
176     //GST_BUFFER_TIMESTAMP (outbuf) = timestamp * GST_SECOND / 90000;
177
178     memcpy (GST_BUFFER_DATA (outbuf), payload, payload_len);
179
180     GST_DEBUG ("gst_rtpamrdec_chain: pushing buffer of size %d",
181         GST_BUFFER_SIZE (outbuf));
182
183     gst_buffer_unref (buf);
184
185     ret = gst_pad_push (rtpamrdec->srcpad, outbuf);
186   }
187
188   return ret;
189
190 bad_packet:
191   {
192     GST_DEBUG ("Packet did not validate");
193     gst_buffer_unref (buf);
194     return GST_FLOW_ERROR;
195   }
196 }
197
198 static void
199 gst_rtpamrdec_set_property (GObject * object, guint prop_id,
200     const GValue * value, GParamSpec * pspec)
201 {
202   GstRtpAMRDec *rtpamrdec;
203
204   rtpamrdec = GST_RTP_AMR_DEC (object);
205
206   switch (prop_id) {
207     default:
208       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
209       break;
210   }
211 }
212
213 static void
214 gst_rtpamrdec_get_property (GObject * object, guint prop_id, GValue * value,
215     GParamSpec * pspec)
216 {
217   GstRtpAMRDec *rtpamrdec;
218
219   rtpamrdec = GST_RTP_AMR_DEC (object);
220
221   switch (prop_id) {
222     default:
223       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
224       break;
225   }
226 }
227
228 static GstElementStateReturn
229 gst_rtpamrdec_change_state (GstElement * element)
230 {
231   GstRtpAMRDec *rtpamrdec;
232   gint transition;
233   GstElementStateReturn ret;
234
235   rtpamrdec = GST_RTP_AMR_DEC (element);
236   transition = GST_STATE_TRANSITION (element);
237
238   switch (transition) {
239     case GST_STATE_NULL_TO_READY:
240       break;
241     default:
242       break;
243   }
244
245   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element);
246
247   switch (transition) {
248     case GST_STATE_READY_TO_NULL:
249       break;
250     default:
251       break;
252   }
253   return ret;
254 }
255
256 gboolean
257 gst_rtpamrdec_plugin_init (GstPlugin * plugin)
258 {
259   return gst_element_register (plugin, "rtpamrdec",
260       GST_RANK_NONE, GST_TYPE_RTP_AMR_DEC);
261 }