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