rtpvorbisdepay: remove dead code
[platform/upstream/gst-plugins-good.git] / gst / rtp / gstrtpsbcdepay.c
1 /*
2  * GStreamer RTP SBC depayloader
3  *
4  * Copyright (C) 2012  Collabora Ltd.
5  *   @author: Arun Raghavan <arun.raghavan@collabora.co.uk>
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
20  * Boston, MA 02110-1301, USA.
21  */
22
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27 #include <gst/rtp/gstrtpbuffer.h>
28 #include <gst/audio/audio.h>
29 #include "gstrtpsbcdepay.h"
30 #include "gstrtputils.h"
31
32 GST_DEBUG_CATEGORY_STATIC (rtpsbcdepay_debug);
33 #define GST_CAT_DEFAULT (rtpsbcdepay_debug)
34
35 static GstStaticPadTemplate gst_rtp_sbc_depay_src_template =
36 GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS,
37     GST_STATIC_CAPS ("audio/x-sbc, "
38         "rate = (int) { 16000, 32000, 44100, 48000 }, "
39         "channels = (int) [ 1, 2 ], "
40         "mode = (string) { mono, dual, stereo, joint }, "
41         "blocks = (int) { 4, 8, 12, 16 }, "
42         "subbands = (int) { 4, 8 }, "
43         "allocation-method = (string) { snr, loudness }, "
44         "bitpool = (int) [ 2, 64 ]")
45     );
46
47 static GstStaticPadTemplate gst_rtp_sbc_depay_sink_template =
48 GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS,
49     GST_STATIC_CAPS ("application/x-rtp, "
50         "media = (string) audio,"
51         "payload = (int) " GST_RTP_PAYLOAD_DYNAMIC_STRING ", "
52         "clock-rate = (int) { 16000, 32000, 44100, 48000 },"
53         "encoding-name = (string) SBC")
54     );
55
56 #define gst_rtp_sbc_depay_parent_class parent_class
57 G_DEFINE_TYPE (GstRtpSbcDepay, gst_rtp_sbc_depay, GST_TYPE_RTP_BASE_DEPAYLOAD);
58
59 static void gst_rtp_sbc_depay_finalize (GObject * object);
60
61 static gboolean gst_rtp_sbc_depay_setcaps (GstRTPBaseDepayload * base,
62     GstCaps * caps);
63 static GstBuffer *gst_rtp_sbc_depay_process (GstRTPBaseDepayload * base,
64     GstRTPBuffer * rtp);
65
66 static void
67 gst_rtp_sbc_depay_class_init (GstRtpSbcDepayClass * klass)
68 {
69   GstRTPBaseDepayloadClass *gstbasertpdepayload_class =
70       GST_RTP_BASE_DEPAYLOAD_CLASS (klass);
71   GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
72   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
73
74   gobject_class->finalize = gst_rtp_sbc_depay_finalize;
75
76   gstbasertpdepayload_class->set_caps = gst_rtp_sbc_depay_setcaps;
77   gstbasertpdepayload_class->process_rtp_packet = gst_rtp_sbc_depay_process;
78
79   gst_element_class_add_static_pad_template (element_class,
80       &gst_rtp_sbc_depay_src_template);
81   gst_element_class_add_static_pad_template (element_class,
82       &gst_rtp_sbc_depay_sink_template);
83
84   GST_DEBUG_CATEGORY_INIT (rtpsbcdepay_debug, "rtpsbcdepay", 0,
85       "SBC Audio RTP Depayloader");
86
87   gst_element_class_set_static_metadata (element_class,
88       "RTP SBC audio depayloader",
89       "Codec/Depayloader/Network/RTP",
90       "Extracts SBC audio from RTP packets",
91       "Arun Raghavan <arun.raghavan@collabora.co.uk>");
92 }
93
94 static void
95 gst_rtp_sbc_depay_init (GstRtpSbcDepay * rtpsbcdepay)
96 {
97   rtpsbcdepay->adapter = gst_adapter_new ();
98 }
99
100 static void
101 gst_rtp_sbc_depay_finalize (GObject * object)
102 {
103   GstRtpSbcDepay *depay = GST_RTP_SBC_DEPAY (object);
104
105   gst_object_unref (depay->adapter);
106
107   G_OBJECT_CLASS (parent_class)->finalize (object);
108 }
109
110 /* FIXME: This duplicates similar functionality rtpsbcpay, but there isn't a
111  * simple way to consolidate the two. This is best done by moving the function
112  * to the codec-utils library in gst-plugins-base when these elements move to
113  * GStreamer. */
114 static int
115 gst_rtp_sbc_depay_get_params (GstRtpSbcDepay * depay, const guint8 * data,
116     gint size, int *framelen, int *samples)
117 {
118   int blocks, channel_mode, channels, subbands, bitpool;
119   int length;
120
121   if (size < 3) {
122     /* Not enough data for the header */
123     return -1;
124   }
125
126   /* Sanity check */
127   if (data[0] != 0x9c) {
128     GST_WARNING_OBJECT (depay, "Bad packet: couldn't find syncword");
129     return -2;
130   }
131
132   blocks = (data[1] >> 4) & 0x3;
133   blocks = (blocks + 1) * 4;
134   channel_mode = (data[1] >> 2) & 0x3;
135   channels = channel_mode ? 2 : 1;
136   subbands = (data[1] & 0x1);
137   subbands = (subbands + 1) * 4;
138   bitpool = data[2];
139
140   length = 4 + ((4 * subbands * channels) / 8);
141
142   if (channel_mode == 0 || channel_mode == 1) {
143     /* Mono || Dual channel */
144     length += ((blocks * channels * bitpool)
145         + 4 /* round up */ ) / 8;
146   } else {
147     /* Stereo || Joint stereo */
148     gboolean joint = (channel_mode == 3);
149
150     length += ((joint * subbands) + (blocks * bitpool)
151         + 4 /* round up */ ) / 8;
152   }
153
154   *framelen = length;
155   *samples = blocks * subbands;
156
157   return 0;
158 }
159
160 static gboolean
161 gst_rtp_sbc_depay_setcaps (GstRTPBaseDepayload * base, GstCaps * caps)
162 {
163   GstRtpSbcDepay *depay = GST_RTP_SBC_DEPAY (base);
164   GstStructure *structure;
165   GstCaps *outcaps, *oldcaps;
166
167   structure = gst_caps_get_structure (caps, 0);
168
169   if (!gst_structure_get_int (structure, "clock-rate", &depay->rate))
170     goto bad_caps;
171
172   outcaps = gst_caps_new_simple ("audio/x-sbc", "rate", G_TYPE_INT,
173       depay->rate, NULL);
174
175   gst_pad_set_caps (GST_RTP_BASE_DEPAYLOAD_SRCPAD (base), outcaps);
176
177   oldcaps = gst_pad_get_current_caps (GST_RTP_BASE_DEPAYLOAD_SINKPAD (base));
178   if (oldcaps && !gst_caps_can_intersect (oldcaps, caps)) {
179     /* Caps have changed, flush old data */
180     gst_adapter_clear (depay->adapter);
181   }
182
183   gst_caps_unref (outcaps);
184
185   return TRUE;
186
187 bad_caps:
188   GST_WARNING_OBJECT (depay, "Can't support the caps we got: %"
189       GST_PTR_FORMAT, caps);
190   return FALSE;
191 }
192
193 static GstBuffer *
194 gst_rtp_sbc_depay_process (GstRTPBaseDepayload * base, GstRTPBuffer * rtp)
195 {
196   GstRtpSbcDepay *depay = GST_RTP_SBC_DEPAY (base);
197   GstBuffer *data = NULL;
198
199   gboolean fragment, start, last;
200   guint8 nframes;
201   guint8 *payload;
202   guint payload_len;
203
204   GST_LOG_OBJECT (depay, "Got %" G_GSIZE_FORMAT " bytes",
205       gst_buffer_get_size (rtp->buffer));
206
207   if (gst_rtp_buffer_get_marker (rtp)) {
208     /* Marker isn't supposed to be set */
209     GST_WARNING_OBJECT (depay, "Marker bit was set");
210     goto bad_packet;
211   }
212
213   payload = gst_rtp_buffer_get_payload (rtp);
214   payload_len = gst_rtp_buffer_get_payload_len (rtp);
215
216   fragment = payload[0] & 0x80;
217   start = payload[0] & 0x40;
218   last = payload[0] & 0x20;
219   nframes = payload[0] & 0x0f;
220
221   payload += 1;
222   payload_len -= 1;
223
224   data = gst_rtp_buffer_get_payload_subbuffer (rtp, 1, -1);
225
226   if (fragment) {
227     /* Got a packet with a fragment */
228     GST_LOG_OBJECT (depay, "Got fragment");
229
230     if (start && gst_adapter_available (depay->adapter)) {
231       GST_WARNING_OBJECT (depay, "Missing last fragment");
232       gst_adapter_clear (depay->adapter);
233
234     } else if (!start && !gst_adapter_available (depay->adapter)) {
235       GST_WARNING_OBJECT (depay, "Missing start fragment");
236       gst_buffer_unref (data);
237       data = NULL;
238       goto out;
239     }
240
241     gst_adapter_push (depay->adapter, data);
242
243     if (last) {
244       data = gst_adapter_take_buffer (depay->adapter,
245           gst_adapter_available (depay->adapter));
246       gst_rtp_drop_meta (GST_ELEMENT_CAST (depay), data,
247           g_quark_from_static_string (GST_META_TAG_AUDIO_STR));
248     } else
249       data = NULL;
250
251   } else {
252     /* !fragment */
253     gint framelen, samples;
254
255     GST_LOG_OBJECT (depay, "Got %d frames", nframes);
256
257     if (gst_rtp_sbc_depay_get_params (depay, payload,
258             payload_len, &framelen, &samples) < 0) {
259       gst_adapter_clear (depay->adapter);
260       goto bad_packet;
261     }
262
263     GST_LOG_OBJECT (depay, "Got payload of %d", payload_len);
264
265     if (nframes * framelen > (gint) payload_len) {
266       GST_WARNING_OBJECT (depay, "Short packet");
267       goto bad_packet;
268     } else if (nframes * framelen < (gint) payload_len) {
269       GST_WARNING_OBJECT (depay, "Junk at end of packet");
270     }
271   }
272
273 out:
274   return data;
275
276 bad_packet:
277   GST_ELEMENT_WARNING (depay, STREAM, DECODE,
278       ("Received invalid RTP payload, dropping"), (NULL));
279   goto out;
280 }
281
282 gboolean
283 gst_rtp_sbc_depay_plugin_init (GstPlugin * plugin)
284 {
285   return gst_element_register (plugin, "rtpsbcdepay", GST_RANK_SECONDARY,
286       GST_TYPE_RTP_SBC_DEPAY);
287 }