gst/rtp/: Add mappings for multichannel support. Does not completely just work becaus...
[platform/upstream/gst-plugins-good.git] / gst / rtp / gstrtpL16depay.c
1 /* GStreamer
2  * Copyright (C) <2007> 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 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  */
19
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23
24 #include <string.h>
25 #include <stdlib.h>
26
27 #include <gst/audio/audio.h>
28 #include <gst/audio/multichannel.h>
29
30 #include "gstrtpL16depay.h"
31 #include "gstrtpchannels.h"
32
33 GST_DEBUG_CATEGORY_STATIC (rtpL16depay_debug);
34 #define GST_CAT_DEFAULT (rtpL16depay_debug)
35
36 /* elementfactory information */
37 static const GstElementDetails gst_rtp_L16_depay_details =
38 GST_ELEMENT_DETAILS ("RTP packet depayloader",
39     "Codec/Depayloader/Network",
40     "Extracts raw audio from RTP packets",
41     "Zeeshan Ali <zak147@yahoo.com>," "Wim Taymans <wim@fluendo.com>");
42
43 static GstStaticPadTemplate gst_rtp_L16_depay_src_template =
44 GST_STATIC_PAD_TEMPLATE ("src",
45     GST_PAD_SRC,
46     GST_PAD_ALWAYS,
47     GST_STATIC_CAPS ("audio/x-raw-int, "
48         "endianness = (int) BIG_ENDIAN, "
49         "signed = (boolean) true, "
50         "width = (int) 16, "
51         "depth = (int) 16, "
52         "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ]")
53     );
54
55 static GstStaticPadTemplate gst_rtp_L16_depay_sink_template =
56     GST_STATIC_PAD_TEMPLATE ("sink",
57     GST_PAD_SINK,
58     GST_PAD_ALWAYS,
59     GST_STATIC_CAPS ("application/x-rtp, "
60         "media = (string) \"audio\", "
61         "payload = (int) " GST_RTP_PAYLOAD_DYNAMIC_STRING ", "
62         "clock-rate = (int) [ 1, MAX ], "
63         /* "channels = (int) [1, MAX]"  */
64         /* "emphasis = (string) ANY" */
65         /* "channel-order = (string) ANY" */
66         "encoding-name = (string) \"L16\";"
67         "application/x-rtp, "
68         "media = (string) \"audio\", "
69         "payload = (int) { " GST_RTP_PAYLOAD_L16_STEREO_STRING ", "
70         GST_RTP_PAYLOAD_L16_MONO_STRING " }," "clock-rate = (int) [ 1, MAX ]"
71         /* "channels = (int) [1, MAX]" */
72         /* "emphasis = (string) ANY" */
73         /* "channel-order = (string) ANY" */
74     )
75     );
76
77 GST_BOILERPLATE (GstRtpL16Depay, gst_rtp_L16_depay, GstBaseRTPDepayload,
78     GST_TYPE_BASE_RTP_DEPAYLOAD);
79
80 static gboolean gst_rtp_L16_depay_setcaps (GstBaseRTPDepayload * depayload,
81     GstCaps * caps);
82 static GstBuffer *gst_rtp_L16_depay_process (GstBaseRTPDepayload * depayload,
83     GstBuffer * buf);
84
85 static GstStateChangeReturn gst_rtp_L16_depay_change_state (GstElement *
86     element, GstStateChange transition);
87
88 static void
89 gst_rtp_L16_depay_base_init (gpointer klass)
90 {
91   GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
92
93   gst_element_class_add_pad_template (element_class,
94       gst_static_pad_template_get (&gst_rtp_L16_depay_src_template));
95   gst_element_class_add_pad_template (element_class,
96       gst_static_pad_template_get (&gst_rtp_L16_depay_sink_template));
97
98   gst_element_class_set_details (element_class, &gst_rtp_L16_depay_details);
99 }
100
101 static void
102 gst_rtp_L16_depay_class_init (GstRtpL16DepayClass * klass)
103 {
104   GstElementClass *gstelement_class;
105   GstBaseRTPDepayloadClass *gstbasertpdepayload_class;
106
107   gstelement_class = (GstElementClass *) klass;
108   gstbasertpdepayload_class = (GstBaseRTPDepayloadClass *) klass;
109
110   parent_class = g_type_class_peek_parent (klass);
111
112   gstelement_class->change_state = gst_rtp_L16_depay_change_state;
113
114   gstbasertpdepayload_class->set_caps = gst_rtp_L16_depay_setcaps;
115   gstbasertpdepayload_class->process = gst_rtp_L16_depay_process;
116
117   GST_DEBUG_CATEGORY_INIT (rtpL16depay_debug, "rtpL16depay", 0,
118       "Raw Audio RTP Depayloader");
119 }
120
121 static void
122 gst_rtp_L16_depay_init (GstRtpL16Depay * rtpL16depay,
123     GstRtpL16DepayClass * klass)
124 {
125   /* needed because of GST_BOILERPLATE */
126 }
127
128 static gint
129 gst_rtp_L16_depay_parse_int (GstStructure * structure, const gchar * field,
130     gint def)
131 {
132   const gchar *str;
133   gint res;
134
135   if ((str = gst_structure_get_string (structure, field)))
136     return atoi (str);
137
138   if (gst_structure_get_int (structure, field, &res))
139     return res;
140
141   return def;
142 }
143
144 static gboolean
145 gst_rtp_L16_depay_setcaps (GstBaseRTPDepayload * depayload, GstCaps * caps)
146 {
147   GstStructure *structure;
148   GstRtpL16Depay *rtpL16depay;
149   gint clock_rate, payload;
150   gint channels;
151   GstCaps *srccaps;
152   gboolean res;
153   const gchar *channel_order;
154   const GstRTPChannelOrder *order;
155
156   rtpL16depay = GST_RTP_L16_DEPAY (depayload);
157
158   structure = gst_caps_get_structure (caps, 0);
159
160   payload = 96;
161   gst_structure_get_int (structure, "payload", &payload);
162   switch (payload) {
163     case GST_RTP_PAYLOAD_L16_STEREO:
164       channels = 2;
165       clock_rate = 44100;
166       break;
167     case GST_RTP_PAYLOAD_L16_MONO:
168       channels = 1;
169       clock_rate = 44100;
170       break;
171     default:
172       /* no fixed mapping, we need channels and clock-rate */
173       channels = 0;
174       clock_rate = 0;
175       break;
176   }
177
178   /* caps can overwrite defaults */
179   clock_rate =
180       gst_rtp_L16_depay_parse_int (structure, "clock-rate", clock_rate);
181   if (clock_rate == 0)
182     goto no_clockrate;
183
184   channels = gst_rtp_L16_depay_parse_int (structure, "channels", channels);
185   if (channels == 0)
186     goto no_channels;
187
188   depayload->clock_rate = clock_rate;
189   rtpL16depay->rate = clock_rate;
190   rtpL16depay->channels = channels;
191
192   srccaps = gst_caps_new_simple ("audio/x-raw-int",
193       "endianness", G_TYPE_INT, G_BIG_ENDIAN,
194       "signed", G_TYPE_BOOLEAN, TRUE,
195       "width", G_TYPE_INT, 16,
196       "depth", G_TYPE_INT, 16,
197       "rate", G_TYPE_INT, clock_rate, "channels", G_TYPE_INT, channels, NULL);
198
199   /* add channel positions */
200   channel_order = gst_structure_get_string (structure, "channel-order");
201
202   order = gst_rtp_channels_get_by_order (channels, channel_order);
203   if (order) {
204     gst_audio_set_channel_positions (gst_caps_get_structure (srccaps, 0),
205         order->pos);
206   } else {
207     GstAudioChannelPosition *pos;
208
209     GST_ELEMENT_WARNING (rtpL16depay, STREAM, DECODE,
210         (NULL), ("Unknown channel order '%s' for %d channels",
211             GST_STR_NULL (channel_order), channels));
212     /* create default NONE layout */
213     pos = gst_rtp_channels_create_default (channels);
214     gst_audio_set_channel_positions (gst_caps_get_structure (srccaps, 0), pos);
215     g_free (pos);
216   }
217
218   res = gst_pad_set_caps (depayload->srcpad, srccaps);
219   gst_caps_unref (srccaps);
220
221   return res;
222
223   /* ERRORS */
224 no_clockrate:
225   {
226     GST_ERROR_OBJECT (depayload, "no clock-rate specified");
227     return FALSE;
228   }
229 no_channels:
230   {
231     GST_ERROR_OBJECT (depayload, "no channels specified");
232     return FALSE;
233   }
234 }
235
236 static GstBuffer *
237 gst_rtp_L16_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf)
238 {
239   GstRtpL16Depay *rtpL16depay;
240   GstBuffer *outbuf;
241   gint payload_len;
242   gboolean marker;
243
244   rtpL16depay = GST_RTP_L16_DEPAY (depayload);
245
246   payload_len = gst_rtp_buffer_get_payload_len (buf);
247
248   if (payload_len <= 0)
249     goto empty_packet;
250
251   GST_DEBUG_OBJECT (rtpL16depay, "got payload of %d bytes", payload_len);
252
253   outbuf = gst_rtp_buffer_get_payload_buffer (buf);
254   marker = gst_rtp_buffer_get_marker (buf);
255
256   if (marker) {
257     /* mark talk spurt with DISCONT */
258     GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT);
259   }
260
261   return outbuf;
262
263   /* ERRORS */
264 empty_packet:
265   {
266     GST_ELEMENT_WARNING (rtpL16depay, STREAM, DECODE,
267         ("Empty Payload."), (NULL));
268     return NULL;
269   }
270 }
271
272 static GstStateChangeReturn
273 gst_rtp_L16_depay_change_state (GstElement * element, GstStateChange transition)
274 {
275   GstRtpL16Depay *rtpL16depay;
276   GstStateChangeReturn ret;
277
278   rtpL16depay = GST_RTP_L16_DEPAY (element);
279
280   /*
281      switch (transition) {
282      case GST_STATE_CHANGE_NULL_TO_READY:
283      break;
284      default:
285      break;
286      }
287    */
288
289   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
290
291   /*
292      switch (transition) {
293      case GST_STATE_CHANGE_READY_TO_NULL:
294      break;
295      default:
296      break;
297      }
298    */
299   return ret;
300 }
301
302 gboolean
303 gst_rtp_L16_depay_plugin_init (GstPlugin * plugin)
304 {
305   return gst_element_register (plugin, "rtpL16depay",
306       GST_RANK_MARGINAL, GST_TYPE_RTP_L16_DEPAY);
307 }