webrtc/nice: Support domain name as connection-address of ICE candidate
[platform/upstream/gstreamer.git] / subprojects / gst-plugins-good / gst / rtp / gstrtpmparobustdepay.c
1 /* GStreamer
2  * Copyright (C) <2010> Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>
3  * Copyright (C) <2010> Nokia Corporation
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
18  * Boston, MA 02110-1301, USA.
19  */
20
21 #ifdef HAVE_CONFIG_H
22 #  include "config.h"
23 #endif
24
25 #include <gst/rtp/gstrtpbuffer.h>
26
27 #include <stdio.h>
28 #include <string.h>
29 #include "gstrtpelements.h"
30 #include "gstrtpmparobustdepay.h"
31
32 GST_DEBUG_CATEGORY_STATIC (rtpmparobustdepay_debug);
33 #define GST_CAT_DEFAULT (rtpmparobustdepay_debug)
34
35 static GstStaticPadTemplate gst_rtp_mpa_robust_depay_src_template =
36 GST_STATIC_PAD_TEMPLATE ("src",
37     GST_PAD_SRC,
38     GST_PAD_ALWAYS,
39     GST_STATIC_CAPS ("audio/mpeg, " "mpegversion = (int) 1")
40     );
41
42 static GstStaticPadTemplate gst_rtp_mpa_robust_depay_sink_template =
43     GST_STATIC_PAD_TEMPLATE ("sink",
44     GST_PAD_SINK,
45     GST_PAD_ALWAYS,
46     GST_STATIC_CAPS ("application/x-rtp, "
47         "media = (string) \"audio\", "
48         "clock-rate = (int) 90000, "
49         "encoding-name = (string) \"MPA-ROBUST\" " "; "
50         /* draft versions appear still in use out there */
51         "application/x-rtp, "
52         "media = (string) \"audio\", "
53         "clock-rate = (int) [1, MAX], "
54         "encoding-name = (string) { \"X-MP3-DRAFT-00\", \"X-MP3-DRAFT-01\", "
55         " \"X-MP3-DRAFT-02\", \"X-MP3-DRAFT-03\", \"X-MP3-DRAFT-04\", "
56         " \"X-MP3-DRAFT-05\", \"X-MP3-DRAFT-06\" }")
57     );
58
59 typedef struct _GstADUFrame
60 {
61   guint32 header;
62   gint size;
63   gint side_info;
64   gint data_size;
65   gint layer;
66   gint backpointer;
67
68   GstBuffer *buffer;
69 } GstADUFrame;
70
71 #define gst_rtp_mpa_robust_depay_parent_class parent_class
72 G_DEFINE_TYPE (GstRtpMPARobustDepay, gst_rtp_mpa_robust_depay,
73     GST_TYPE_RTP_BASE_DEPAYLOAD);
74 GST_ELEMENT_REGISTER_DEFINE_WITH_CODE (rtpmparobustdepay, "rtpmparobustdepay",
75     GST_RANK_SECONDARY, GST_TYPE_RTP_MPA_ROBUST_DEPAY,
76     rtp_element_init (plugin));
77
78 static GstStateChangeReturn gst_rtp_mpa_robust_change_state (GstElement *
79     element, GstStateChange transition);
80
81 static gboolean gst_rtp_mpa_robust_depay_setcaps (GstRTPBaseDepayload *
82     depayload, GstCaps * caps);
83 static GstBuffer *gst_rtp_mpa_robust_depay_process (GstRTPBaseDepayload *
84     depayload, GstRTPBuffer * rtp);
85
86 static void
87 gst_rtp_mpa_robust_depay_finalize (GObject * object)
88 {
89   GstRtpMPARobustDepay *rtpmpadepay;
90
91   rtpmpadepay = (GstRtpMPARobustDepay *) object;
92
93   g_object_unref (rtpmpadepay->adapter);
94   g_queue_free (rtpmpadepay->adu_frames);
95
96   G_OBJECT_CLASS (parent_class)->finalize (object);
97 }
98
99 static void
100 gst_rtp_mpa_robust_depay_class_init (GstRtpMPARobustDepayClass * klass)
101 {
102   GObjectClass *gobject_class;
103   GstElementClass *gstelement_class;
104   GstRTPBaseDepayloadClass *gstrtpbasedepayload_class;
105
106   GST_DEBUG_CATEGORY_INIT (rtpmparobustdepay_debug, "rtpmparobustdepay", 0,
107       "Robust MPEG Audio RTP Depayloader");
108
109   gobject_class = (GObjectClass *) klass;
110   gstelement_class = (GstElementClass *) klass;
111   gstrtpbasedepayload_class = (GstRTPBaseDepayloadClass *) klass;
112
113   gobject_class->finalize = gst_rtp_mpa_robust_depay_finalize;
114
115   gstelement_class->change_state =
116       GST_DEBUG_FUNCPTR (gst_rtp_mpa_robust_change_state);
117
118   gst_element_class_add_static_pad_template (gstelement_class,
119       &gst_rtp_mpa_robust_depay_src_template);
120   gst_element_class_add_static_pad_template (gstelement_class,
121       &gst_rtp_mpa_robust_depay_sink_template);
122
123   gst_element_class_set_static_metadata (gstelement_class,
124       "RTP MPEG audio depayloader", "Codec/Depayloader/Network/RTP",
125       "Extracts MPEG audio from RTP packets (RFC 5219)",
126       "Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>");
127
128   gstrtpbasedepayload_class->set_caps = gst_rtp_mpa_robust_depay_setcaps;
129   gstrtpbasedepayload_class->process_rtp_packet =
130       gst_rtp_mpa_robust_depay_process;
131 }
132
133 static void
134 gst_rtp_mpa_robust_depay_init (GstRtpMPARobustDepay * rtpmpadepay)
135 {
136   rtpmpadepay->adapter = gst_adapter_new ();
137   rtpmpadepay->adu_frames = g_queue_new ();
138 }
139
140 static gboolean
141 gst_rtp_mpa_robust_depay_setcaps (GstRTPBaseDepayload * depayload,
142     GstCaps * caps)
143 {
144   GstRtpMPARobustDepay *rtpmpadepay;
145   GstStructure *structure;
146   GstCaps *outcaps;
147   gint clock_rate, draft;
148   gboolean res;
149   const gchar *encoding;
150
151   rtpmpadepay = GST_RTP_MPA_ROBUST_DEPAY (depayload);
152
153   structure = gst_caps_get_structure (caps, 0);
154
155   if (!gst_structure_get_int (structure, "clock-rate", &clock_rate))
156     clock_rate = 90000;
157   depayload->clock_rate = clock_rate;
158
159   rtpmpadepay->has_descriptor = TRUE;
160   if ((encoding = gst_structure_get_string (structure, "encoding-name"))) {
161     if (sscanf (encoding, "X-MP3-DRAFT-%d", &draft) && (draft == 0))
162       rtpmpadepay->has_descriptor = FALSE;
163   }
164
165   outcaps =
166       gst_caps_new_simple ("audio/mpeg", "mpegversion", G_TYPE_INT, 1, NULL);
167   res = gst_pad_set_caps (depayload->srcpad, outcaps);
168   gst_caps_unref (outcaps);
169
170   return res;
171 }
172
173 /* thanks again go to mp3parse ... */
174
175 static const guint mp3types_bitrates[2][3][16] = {
176   {
177         {0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448,},
178         {0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384,},
179         {0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320,}
180       },
181   {
182         {0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256,},
183         {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160,},
184         {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160,}
185       },
186 };
187
188 static const guint mp3types_freqs[3][3] = { {44100, 48000, 32000},
189 {22050, 24000, 16000},
190 {11025, 12000, 8000}
191 };
192
193 static inline guint
194 mp3_type_frame_length_from_header (GstElement * mp3parse, guint32 header,
195     guint * put_version, guint * put_layer, guint * put_channels,
196     guint * put_bitrate, guint * put_samplerate, guint * put_mode,
197     guint * put_crc)
198 {
199   guint length;
200   gulong mode, samplerate, bitrate, layer, channels, padding, crc;
201   gulong version;
202   gint lsf, mpg25;
203
204   if (header & (1 << 20)) {
205     lsf = (header & (1 << 19)) ? 0 : 1;
206     mpg25 = 0;
207   } else {
208     lsf = 1;
209     mpg25 = 1;
210   }
211
212   version = 1 + lsf + mpg25;
213
214   layer = 4 - ((header >> 17) & 0x3);
215
216   crc = (header >> 16) & 0x1;
217
218   bitrate = (header >> 12) & 0xF;
219   bitrate = mp3types_bitrates[lsf][layer - 1][bitrate] * 1000;
220   /* The caller has ensured we have a valid header, so bitrate can't be
221      zero here. */
222   if (bitrate == 0) {
223     GST_DEBUG_OBJECT (mp3parse, "invalid bitrate");
224     return 0;
225   }
226
227   samplerate = (header >> 10) & 0x3;
228   samplerate = mp3types_freqs[lsf + mpg25][samplerate];
229
230   padding = (header >> 9) & 0x1;
231
232   mode = (header >> 6) & 0x3;
233   channels = (mode == 3) ? 1 : 2;
234
235   switch (layer) {
236     case 1:
237       length = 4 * ((bitrate * 12) / samplerate + padding);
238       break;
239     case 2:
240       length = (bitrate * 144) / samplerate + padding;
241       break;
242     default:
243     case 3:
244       length = (bitrate * 144) / (samplerate << lsf) + padding;
245       break;
246   }
247
248   GST_LOG_OBJECT (mp3parse, "Calculated mp3 frame length of %u bytes", length);
249   GST_LOG_OBJECT (mp3parse, "samplerate = %lu, bitrate = %lu, version = %lu, "
250       "layer = %lu, channels = %lu, mode = %lu", samplerate, bitrate, version,
251       layer, channels, mode);
252
253   if (put_version)
254     *put_version = version;
255   if (put_layer)
256     *put_layer = layer;
257   if (put_channels)
258     *put_channels = channels;
259   if (put_bitrate)
260     *put_bitrate = bitrate;
261   if (put_samplerate)
262     *put_samplerate = samplerate;
263   if (put_mode)
264     *put_mode = mode;
265   if (put_crc)
266     *put_crc = crc;
267
268   GST_LOG_OBJECT (mp3parse, "size = %u", length);
269   return length;
270 }
271
272 /* generate empty/silent/dummy frame that mimics @frame,
273  * except for rate, where maximum possible is selected */
274 static GstADUFrame *
275 gst_rtp_mpa_robust_depay_generate_dummy_frame (GstRtpMPARobustDepay *
276     rtpmpadepay, GstADUFrame * frame)
277 {
278   GstADUFrame *dummy;
279   GstMapInfo map;
280
281   dummy = g_slice_dup (GstADUFrame, frame);
282
283   /* go for maximum bitrate */
284   dummy->header = (frame->header & ~(0xf << 12)) | (0xe << 12);
285   dummy->size =
286       mp3_type_frame_length_from_header (GST_ELEMENT_CAST (rtpmpadepay),
287       dummy->header, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
288   dummy->data_size = dummy->size - 4 - dummy->side_info;
289   dummy->backpointer = 0;
290
291   dummy->buffer = gst_buffer_new_and_alloc (dummy->side_info + 4);
292
293   gst_buffer_map (dummy->buffer, &map, GST_MAP_WRITE);
294   memset (map.data, 0, map.size);
295   GST_WRITE_UINT32_BE (map.data, dummy->header);
296   gst_buffer_unmap (dummy->buffer, &map);
297
298   GST_BUFFER_PTS (dummy->buffer) = GST_BUFFER_PTS (frame->buffer);
299
300   return dummy;
301 }
302
303 /* validates and parses @buf, and queues for further transformation if valid,
304  * otherwise discards @buf
305  * Takes ownership of @buf. */
306 static gboolean
307 gst_rtp_mpa_robust_depay_queue_frame (GstRtpMPARobustDepay * rtpmpadepay,
308     GstBuffer * buf)
309 {
310   GstADUFrame *frame = NULL;
311   guint version, layer, channels, size;
312   guint crc;
313   GstMapInfo map;
314
315   g_return_val_if_fail (buf != NULL, FALSE);
316
317   gst_buffer_map (buf, &map, GST_MAP_READ);
318
319   if (map.size < 6)
320     goto corrupt_frame;
321
322   frame = g_slice_new0 (GstADUFrame);
323   frame->header = GST_READ_UINT32_BE (map.data);
324
325   size = mp3_type_frame_length_from_header (GST_ELEMENT_CAST (rtpmpadepay),
326       frame->header, &version, &layer, &channels, NULL, NULL, NULL, &crc);
327   if (!size)
328     goto corrupt_frame;
329
330   frame->size = size;
331   frame->layer = layer;
332   if (version == 1 && channels == 2)
333     frame->side_info = 32;
334   else if ((version == 1 && channels == 1) || (version >= 2 && channels == 2))
335     frame->side_info = 17;
336   else if (version >= 2 && channels == 1)
337     frame->side_info = 9;
338   else {
339     g_assert_not_reached ();
340     goto corrupt_frame;
341   }
342
343   /* backpointer */
344   if (layer == 3) {
345     frame->backpointer = GST_READ_UINT16_BE (map.data + 4);
346     frame->backpointer >>= 7;
347     GST_LOG_OBJECT (rtpmpadepay, "backpointer: %d", frame->backpointer);
348   }
349
350   if (!crc)
351     frame->side_info += 2;
352
353   GST_LOG_OBJECT (rtpmpadepay, "side info: %d", frame->side_info);
354   frame->data_size = frame->size - 4 - frame->side_info;
355
356   /* some size validation checks */
357   if (4 + frame->side_info > map.size)
358     goto corrupt_frame;
359
360   /* ADU data would then extend past MP3 frame,
361    * even using past byte reservoir */
362   if (-frame->backpointer + (gint) (map.size) > frame->size)
363     goto corrupt_frame;
364
365   gst_buffer_unmap (buf, &map);
366
367   /* ok, take buffer and queue */
368   frame->buffer = buf;
369   g_queue_push_tail (rtpmpadepay->adu_frames, frame);
370
371   return TRUE;
372
373   /* ERRORS */
374 corrupt_frame:
375   {
376     GST_DEBUG_OBJECT (rtpmpadepay, "frame is corrupt");
377     gst_buffer_unmap (buf, &map);
378     gst_buffer_unref (buf);
379     if (frame)
380       g_slice_free (GstADUFrame, frame);
381     return FALSE;
382   }
383 }
384
385 static inline void
386 gst_rtp_mpa_robust_depay_free_frame (GstADUFrame * frame)
387 {
388   if (frame->buffer)
389     gst_buffer_unref (frame->buffer);
390   g_slice_free (GstADUFrame, frame);
391 }
392
393 static inline void
394 gst_rtp_mpa_robust_depay_dequeue_frame (GstRtpMPARobustDepay * rtpmpadepay)
395 {
396   GstADUFrame *head;
397
398   GST_LOG_OBJECT (rtpmpadepay, "dequeueing ADU frame");
399
400   if (rtpmpadepay->adu_frames->head == rtpmpadepay->cur_adu_frame)
401     rtpmpadepay->cur_adu_frame = NULL;
402
403   head = g_queue_pop_head (rtpmpadepay->adu_frames);
404   g_assert (head->buffer);
405   gst_rtp_mpa_robust_depay_free_frame (head);
406
407   return;
408 }
409
410 /* returns TRUE if at least one new ADU frame was enqueued for MP3 conversion.
411  * Takes ownership of @buf. */
412 static gboolean
413 gst_rtp_mpa_robust_depay_deinterleave (GstRtpMPARobustDepay * rtpmpadepay,
414     GstBuffer * buf)
415 {
416   gboolean ret = FALSE;
417   GstMapInfo map;
418   guint val, iindex, icc;
419
420   gst_buffer_map (buf, &map, GST_MAP_READ);
421   val = GST_READ_UINT16_BE (map.data) >> 5;
422   gst_buffer_unmap (buf, &map);
423
424   iindex = val >> 3;
425   icc = val & 0x7;
426
427   GST_LOG_OBJECT (rtpmpadepay, "sync: 0x%x, index: %u, cycle count: %u",
428       val, iindex, icc);
429
430   /* basic case; no interleaving ever seen */
431   if (val == 0x7ff && rtpmpadepay->last_icc < 0) {
432     ret = gst_rtp_mpa_robust_depay_queue_frame (rtpmpadepay, buf);
433   } else {
434     if (G_UNLIKELY (rtpmpadepay->last_icc < 0)) {
435       rtpmpadepay->last_icc = icc;
436       rtpmpadepay->last_ii = iindex;
437     }
438     if (icc != rtpmpadepay->last_icc || iindex == rtpmpadepay->last_ii) {
439       gint i;
440
441       for (i = 0; i < 256; ++i) {
442         if (rtpmpadepay->deinter[i] != NULL) {
443           ret |= gst_rtp_mpa_robust_depay_queue_frame (rtpmpadepay,
444               rtpmpadepay->deinter[i]);
445           rtpmpadepay->deinter[i] = NULL;
446         }
447       }
448     }
449     /* rewrite buffer sync header */
450     gst_buffer_map (buf, &map, GST_MAP_READWRITE);
451     val = GST_READ_UINT16_BE (map.data);
452     val = (0x7ff << 5) | val;
453     GST_WRITE_UINT16_BE (map.data, val);
454     gst_buffer_unmap (buf, &map);
455     /* store and keep track of last indices */
456     rtpmpadepay->last_icc = icc;
457     rtpmpadepay->last_ii = iindex;
458     rtpmpadepay->deinter[iindex] = buf;
459   }
460
461   return ret;
462 }
463
464 /* Head ADU frame corresponds to mp3_frame (i.e. in header in side-info) that
465  * is currently being written
466  * cur_adu_frame refers to ADU frame whose data should be bytewritten next
467  * (possibly starting from offset rather than start 0) (and is typicall tail
468  * at time of last push round).
469  * If at start, position where it should start writing depends on (data) sizes
470  * of previous mp3 frames (corresponding to foregoing ADU frames) kept in size,
471  * and its backpointer */
472 static GstFlowReturn
473 gst_rtp_mpa_robust_depay_push_mp3_frames (GstRtpMPARobustDepay * rtpmpadepay)
474 {
475   GstBuffer *buf;
476   GstADUFrame *frame, *head;
477   gint av;
478   GstFlowReturn ret = GST_FLOW_OK;
479
480   while (1) {
481     GstMapInfo map;
482
483     if (G_UNLIKELY (!rtpmpadepay->cur_adu_frame)) {
484       rtpmpadepay->cur_adu_frame = rtpmpadepay->adu_frames->head;
485       rtpmpadepay->offset = 0;
486       rtpmpadepay->size = 0;
487     }
488
489     if (G_UNLIKELY (!rtpmpadepay->cur_adu_frame))
490       break;
491
492     frame = (GstADUFrame *) rtpmpadepay->cur_adu_frame->data;
493     head = (GstADUFrame *) rtpmpadepay->adu_frames->head->data;
494
495     /* special case: non-layer III are sent straight through */
496     if (G_UNLIKELY (frame->layer != 3)) {
497       GST_DEBUG_OBJECT (rtpmpadepay, "layer %d frame, sending as-is",
498           frame->layer);
499       gst_rtp_base_depayload_push (GST_RTP_BASE_DEPAYLOAD (rtpmpadepay),
500           frame->buffer);
501       frame->buffer = NULL;
502       /* and remove it from any further consideration */
503       g_slice_free (GstADUFrame, frame);
504       g_queue_delete_link (rtpmpadepay->adu_frames, rtpmpadepay->cur_adu_frame);
505       rtpmpadepay->cur_adu_frame = NULL;
506       continue;
507     }
508
509     if (rtpmpadepay->offset == gst_buffer_get_size (frame->buffer)) {
510       if (g_list_next (rtpmpadepay->cur_adu_frame)) {
511         rtpmpadepay->size += frame->data_size;
512         rtpmpadepay->cur_adu_frame = g_list_next (rtpmpadepay->cur_adu_frame);
513         frame = (GstADUFrame *) rtpmpadepay->cur_adu_frame->data;
514         rtpmpadepay->offset = 0;
515         GST_LOG_OBJECT (rtpmpadepay,
516             "moving to next ADU frame, size %d, side_info %d, backpointer %d",
517             frame->size, frame->side_info, frame->backpointer);
518         /* layer I and II packets have no bitreservoir and must be sent as-is;
519          * so flush any pending frame */
520         if (G_UNLIKELY (frame->layer != 3 && rtpmpadepay->mp3_frame))
521           goto flush;
522       } else {
523         break;
524       }
525     }
526
527     if (G_UNLIKELY (!rtpmpadepay->mp3_frame)) {
528       GST_LOG_OBJECT (rtpmpadepay,
529           "setting up new MP3 frame of size %d, side_info %d",
530           head->size, head->side_info);
531       rtpmpadepay->mp3_frame = gst_byte_writer_new_with_size (head->size, TRUE);
532       /* 0-fill possible gaps */
533       gst_byte_writer_fill_unchecked (rtpmpadepay->mp3_frame, 0, head->size);
534       gst_byte_writer_set_pos (rtpmpadepay->mp3_frame, 0);
535       /* bytewriter corresponds to head frame,
536        * i.e. the header and the side info must match */
537       g_assert (4 + head->side_info <= head->size);
538       gst_buffer_map (head->buffer, &map, GST_MAP_READ);
539       gst_byte_writer_put_data_unchecked (rtpmpadepay->mp3_frame,
540           map.data, 4 + head->side_info);
541       gst_buffer_unmap (head->buffer, &map);
542     }
543
544     buf = frame->buffer;
545     av = gst_byte_writer_get_remaining (rtpmpadepay->mp3_frame);
546     GST_LOG_OBJECT (rtpmpadepay, "current mp3 frame remaining: %d", av);
547     GST_LOG_OBJECT (rtpmpadepay, "accumulated ADU frame data_size: %d",
548         rtpmpadepay->size);
549
550     if (rtpmpadepay->offset) {
551       gst_buffer_map (buf, &map, GST_MAP_READ);
552       /* no need to position, simply append */
553       g_assert (map.size > rtpmpadepay->offset);
554       av = MIN (av, map.size - rtpmpadepay->offset);
555       GST_LOG_OBJECT (rtpmpadepay,
556           "appending %d bytes from ADU frame at offset %d", av,
557           rtpmpadepay->offset);
558       gst_byte_writer_put_data_unchecked (rtpmpadepay->mp3_frame,
559           map.data + rtpmpadepay->offset, av);
560       rtpmpadepay->offset += av;
561       gst_buffer_unmap (buf, &map);
562     } else {
563       gint pos, tpos;
564
565       /* position writing according to ADU frame backpointer */
566       pos = gst_byte_writer_get_pos (rtpmpadepay->mp3_frame);
567       tpos = rtpmpadepay->size - frame->backpointer + 4 + head->side_info;
568       GST_LOG_OBJECT (rtpmpadepay, "current MP3 frame at position %d, "
569           "starting new ADU frame data at offset %d", pos, tpos);
570       if (tpos < pos) {
571         GstADUFrame *dummy;
572
573         /* try to insert as few frames as possible,
574          * so go for a reasonably large dummy frame size */
575         GST_LOG_OBJECT (rtpmpadepay,
576             "overlapping previous data; inserting dummy frame");
577         dummy =
578             gst_rtp_mpa_robust_depay_generate_dummy_frame (rtpmpadepay, frame);
579         g_queue_insert_before (rtpmpadepay->adu_frames,
580             rtpmpadepay->cur_adu_frame, dummy);
581         /* offset is known to be zero, so we can shift current one */
582         rtpmpadepay->cur_adu_frame = rtpmpadepay->cur_adu_frame->prev;
583         if (!rtpmpadepay->size) {
584           g_assert (rtpmpadepay->cur_adu_frame ==
585               rtpmpadepay->adu_frames->head);
586           GST_LOG_OBJECT (rtpmpadepay, "... which is new head frame");
587           gst_byte_writer_free (rtpmpadepay->mp3_frame);
588           rtpmpadepay->mp3_frame = NULL;
589         }
590         /* ... and continue adding that empty one immediately,
591          * and then see if that provided enough extra space */
592         continue;
593       } else if (tpos >= pos + av) {
594         /* ADU frame no longer needs current MP3 frame; move to its end */
595         GST_LOG_OBJECT (rtpmpadepay, "passed current MP3 frame");
596         gst_byte_writer_set_pos (rtpmpadepay->mp3_frame, pos + av);
597       } else {
598         /* position and append */
599         gst_buffer_map (buf, &map, GST_MAP_READ);
600         GST_LOG_OBJECT (rtpmpadepay, "adding to current MP3 frame");
601         gst_byte_writer_set_pos (rtpmpadepay->mp3_frame, tpos);
602         av -= (tpos - pos);
603         g_assert (map.size >= 4 + frame->side_info);
604         av = MIN (av, map.size - 4 - frame->side_info);
605         gst_byte_writer_put_data_unchecked (rtpmpadepay->mp3_frame,
606             map.data + 4 + frame->side_info, av);
607         rtpmpadepay->offset += av + 4 + frame->side_info;
608         gst_buffer_unmap (buf, &map);
609       }
610     }
611
612     /* if mp3 frame filled, send on its way */
613     if (gst_byte_writer_get_remaining (rtpmpadepay->mp3_frame) == 0) {
614     flush:
615       buf = gst_byte_writer_free_and_get_buffer (rtpmpadepay->mp3_frame);
616       rtpmpadepay->mp3_frame = NULL;
617       GST_BUFFER_PTS (buf) = GST_BUFFER_PTS (head->buffer);
618       /* no longer need head ADU frame header and side info */
619       /* NOTE maybe head == current, then size and offset go off a bit,
620        * but current gets reset to NULL, and then also offset and size */
621       rtpmpadepay->size -= head->data_size;
622       gst_rtp_mpa_robust_depay_dequeue_frame (rtpmpadepay);
623       /* send */
624       ret = gst_rtp_base_depayload_push (GST_RTP_BASE_DEPAYLOAD (rtpmpadepay),
625           buf);
626     }
627   }
628
629   return ret;
630 }
631
632 /* process ADU frame @buf through:
633  * - deinterleaving
634  * - converting to MP3 frames
635  * Takes ownership of @buf.
636  */
637 static GstFlowReturn
638 gst_rtp_mpa_robust_depay_submit_adu (GstRtpMPARobustDepay * rtpmpadepay,
639     GstBuffer * buf)
640 {
641   if (gst_rtp_mpa_robust_depay_deinterleave (rtpmpadepay, buf))
642     return gst_rtp_mpa_robust_depay_push_mp3_frames (rtpmpadepay);
643
644   return GST_FLOW_OK;
645 }
646
647 static GstBuffer *
648 gst_rtp_mpa_robust_depay_process (GstRTPBaseDepayload * depayload,
649     GstRTPBuffer * rtp)
650 {
651   GstRtpMPARobustDepay *rtpmpadepay;
652   gint payload_len, offset;
653   guint8 *payload;
654   gboolean cont, dtype;
655   guint av, size;
656   GstClockTime timestamp;
657   GstBuffer *buf;
658
659   rtpmpadepay = GST_RTP_MPA_ROBUST_DEPAY (depayload);
660
661   timestamp = GST_BUFFER_PTS (rtp->buffer);
662
663   payload_len = gst_rtp_buffer_get_payload_len (rtp);
664   if (payload_len <= 1)
665     goto short_read;
666
667   payload = gst_rtp_buffer_get_payload (rtp);
668   offset = 0;
669   GST_LOG_OBJECT (rtpmpadepay, "payload_len: %d", payload_len);
670
671   /* strip off descriptor
672    *
673    *  0                   1
674    *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6
675    * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
676    * |C|T|            ADU size         |
677    * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
678    *
679    * C: if 1, data is continuation
680    * T: if 1, size is 14 bits, otherwise 6 bits
681    * ADU size: size of following packet (not including descriptor)
682    */
683   while (payload_len) {
684     if (G_LIKELY (rtpmpadepay->has_descriptor)) {
685       cont = ! !(payload[offset] & 0x80);
686       dtype = ! !(payload[offset] & 0x40);
687       if (dtype) {
688         size = (payload[offset] & 0x3f) << 8 | payload[offset + 1];
689         payload_len--;
690         offset++;
691       } else if (payload_len >= 2) {
692         size = (payload[offset] & 0x3f);
693         payload_len -= 2;
694         offset += 2;
695       } else {
696         goto short_read;
697       }
698     } else {
699       cont = FALSE;
700       dtype = -1;
701       size = payload_len;
702     }
703
704     GST_LOG_OBJECT (rtpmpadepay, "offset %d has cont: %d, dtype: %d, size: %d",
705         offset, cont, dtype, size);
706
707     buf = gst_rtp_buffer_get_payload_subbuffer (rtp, offset,
708         MIN (size, payload_len));
709
710     if (cont) {
711       av = gst_adapter_available (rtpmpadepay->adapter);
712       if (G_UNLIKELY (!av)) {
713         GST_DEBUG_OBJECT (rtpmpadepay,
714             "discarding continuation fragment without prior fragment");
715         gst_buffer_unref (buf);
716       } else {
717         av += gst_buffer_get_size (buf);
718         gst_adapter_push (rtpmpadepay->adapter, buf);
719         if (av == size) {
720           timestamp = gst_adapter_prev_pts (rtpmpadepay->adapter, NULL);
721           buf = gst_adapter_take_buffer (rtpmpadepay->adapter, size);
722           GST_BUFFER_PTS (buf) = timestamp;
723           gst_rtp_mpa_robust_depay_submit_adu (rtpmpadepay, buf);
724         } else if (av > size) {
725           GST_DEBUG_OBJECT (rtpmpadepay,
726               "assembled ADU size %d larger than expected %d; discarding",
727               av, size);
728           gst_adapter_clear (rtpmpadepay->adapter);
729         }
730       }
731       size = payload_len;
732     } else {
733       /* not continuation, first fragment or whole ADU */
734       if (payload_len == size) {
735         /* whole ADU */
736         GST_BUFFER_PTS (buf) = timestamp;
737         gst_rtp_mpa_robust_depay_submit_adu (rtpmpadepay, buf);
738       } else if (payload_len < size) {
739         /* first fragment */
740         gst_adapter_push (rtpmpadepay->adapter, buf);
741         size = payload_len;
742       }
743     }
744
745     offset += size;
746     payload_len -= size;
747
748     /* timestamp applies to first payload, no idea for subsequent ones */
749     timestamp = GST_CLOCK_TIME_NONE;
750   }
751
752   return NULL;
753
754   /* ERRORS */
755 short_read:
756   {
757     GST_ELEMENT_WARNING (rtpmpadepay, STREAM, DECODE,
758         (NULL), ("Packet contains invalid data"));
759     return NULL;
760   }
761 }
762
763 static GstStateChangeReturn
764 gst_rtp_mpa_robust_change_state (GstElement * element,
765     GstStateChange transition)
766 {
767   GstStateChangeReturn ret;
768   GstRtpMPARobustDepay *rtpmpadepay;
769
770   rtpmpadepay = GST_RTP_MPA_ROBUST_DEPAY (element);
771
772   switch (transition) {
773     case GST_STATE_CHANGE_READY_TO_PAUSED:
774       rtpmpadepay->last_ii = -1;
775       rtpmpadepay->last_icc = -1;
776       rtpmpadepay->size = 0;
777       rtpmpadepay->offset = 0;
778     default:
779       break;
780   }
781
782   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
783   if (ret != GST_STATE_CHANGE_SUCCESS)
784     return ret;
785
786   switch (transition) {
787     case GST_STATE_CHANGE_PAUSED_TO_READY:
788     {
789       gint i;
790
791       gst_adapter_clear (rtpmpadepay->adapter);
792       for (i = 0; i < G_N_ELEMENTS (rtpmpadepay->deinter); i++) {
793         gst_buffer_replace (&rtpmpadepay->deinter[i], NULL);
794       }
795       rtpmpadepay->cur_adu_frame = NULL;
796       g_queue_foreach (rtpmpadepay->adu_frames,
797           (GFunc) gst_rtp_mpa_robust_depay_free_frame, NULL);
798       g_queue_clear (rtpmpadepay->adu_frames);
799       if (rtpmpadepay->mp3_frame)
800         gst_byte_writer_free (rtpmpadepay->mp3_frame);
801       break;
802     }
803     default:
804       break;
805   }
806
807   return ret;
808 }