2 * Copyright (C) <2010> Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>
3 * Copyright (C) <2010> Nokia Corporation
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.
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.
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., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
25 #include <gst/rtp/gstrtpbuffer.h>
29 #include "gstrtpmparobustdepay.h"
31 GST_DEBUG_CATEGORY_STATIC (rtpmparobustdepay_debug);
32 #define GST_CAT_DEFAULT (rtpmparobustdepay_debug)
34 static GstStaticPadTemplate gst_rtp_mpa_robust_depay_src_template =
35 GST_STATIC_PAD_TEMPLATE ("src",
38 GST_STATIC_CAPS ("audio/mpeg, " "mpegversion = (int) 1")
41 static GstStaticPadTemplate gst_rtp_mpa_robust_depay_sink_template =
42 GST_STATIC_PAD_TEMPLATE ("sink",
45 GST_STATIC_CAPS ("application/x-rtp, "
46 "media = (string) \"audio\", "
47 "payload = (int) " GST_RTP_PAYLOAD_DYNAMIC_STRING ", "
48 "clock-rate = (int) 90000, "
49 "encoding-name = (string) \"MPA-ROBUST\" " "; "
50 /* draft versions appear still in use out there */
52 "media = (string) \"audio\", "
53 "payload = (int) " GST_RTP_PAYLOAD_DYNAMIC_STRING ", "
54 "clock-rate = (int) [1, MAX], "
55 "encoding-name = (string) { \"X-MP3-DRAFT-00\", \"X-MP3-DRAFT-01\", "
56 " \"X-MP3-DRAFT-02\", \"X-MP3-DRAFT-03\", \"X-MP3-DRAFT-04\", "
57 " \"X-MP3-DRAFT-05\", \"X-MP3-DRAFT-06\" }")
60 typedef struct _GstADUFrame
72 #define gst_rtp_mpa_robust_depay_parent_class parent_class
73 G_DEFINE_TYPE (GstRtpMPARobustDepay, gst_rtp_mpa_robust_depay,
74 GST_TYPE_RTP_BASE_DEPAYLOAD);
76 static GstStateChangeReturn gst_rtp_mpa_robust_change_state (GstElement *
77 element, GstStateChange transition);
79 static gboolean gst_rtp_mpa_robust_depay_setcaps (GstRTPBaseDepayload *
80 depayload, GstCaps * caps);
81 static GstBuffer *gst_rtp_mpa_robust_depay_process (GstRTPBaseDepayload *
82 depayload, GstBuffer * buf);
85 gst_rtp_mpa_robust_depay_finalize (GObject * object)
87 GstRtpMPARobustDepay *rtpmpadepay;
89 rtpmpadepay = (GstRtpMPARobustDepay *) object;
91 g_object_unref (rtpmpadepay->adapter);
92 g_queue_free (rtpmpadepay->adu_frames);
94 G_OBJECT_CLASS (parent_class)->finalize (object);
98 gst_rtp_mpa_robust_depay_class_init (GstRtpMPARobustDepayClass * klass)
100 GObjectClass *gobject_class;
101 GstElementClass *gstelement_class;
102 GstRTPBaseDepayloadClass *gstrtpbasedepayload_class;
104 GST_DEBUG_CATEGORY_INIT (rtpmparobustdepay_debug, "rtpmparobustdepay", 0,
105 "Robust MPEG Audio RTP Depayloader");
107 gobject_class = (GObjectClass *) klass;
108 gstelement_class = (GstElementClass *) klass;
109 gstrtpbasedepayload_class = (GstRTPBaseDepayloadClass *) klass;
111 gobject_class->finalize = gst_rtp_mpa_robust_depay_finalize;
113 gstelement_class->change_state =
114 GST_DEBUG_FUNCPTR (gst_rtp_mpa_robust_change_state);
116 gst_element_class_add_pad_template (gstelement_class,
117 gst_static_pad_template_get (&gst_rtp_mpa_robust_depay_src_template));
118 gst_element_class_add_pad_template (gstelement_class,
119 gst_static_pad_template_get (&gst_rtp_mpa_robust_depay_sink_template));
121 gst_element_class_set_static_metadata (gstelement_class,
122 "RTP MPEG audio depayloader", "Codec/Depayloader/Network/RTP",
123 "Extracts MPEG audio from RTP packets (RFC 5219)",
124 "Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>");
126 gstrtpbasedepayload_class->set_caps = gst_rtp_mpa_robust_depay_setcaps;
127 gstrtpbasedepayload_class->process = gst_rtp_mpa_robust_depay_process;
131 gst_rtp_mpa_robust_depay_init (GstRtpMPARobustDepay * rtpmpadepay)
133 rtpmpadepay->adapter = gst_adapter_new ();
134 rtpmpadepay->adu_frames = g_queue_new ();
138 gst_rtp_mpa_robust_depay_setcaps (GstRTPBaseDepayload * depayload,
141 GstRtpMPARobustDepay *rtpmpadepay;
142 GstStructure *structure;
144 gint clock_rate, draft;
146 const gchar *encoding;
148 rtpmpadepay = GST_RTP_MPA_ROBUST_DEPAY (depayload);
150 structure = gst_caps_get_structure (caps, 0);
152 if (!gst_structure_get_int (structure, "clock-rate", &clock_rate))
154 depayload->clock_rate = clock_rate;
156 rtpmpadepay->has_descriptor = TRUE;
157 if ((encoding = gst_structure_get_string (structure, "encoding-name"))) {
158 if (sscanf (encoding, "X-MP3-DRAFT-%d", &draft) && (draft == 0))
159 rtpmpadepay->has_descriptor = FALSE;
163 gst_caps_new_simple ("audio/mpeg", "mpegversion", G_TYPE_INT, 1, NULL);
164 res = gst_pad_set_caps (depayload->srcpad, outcaps);
165 gst_caps_unref (outcaps);
170 /* thanks again go to mp3parse ... */
172 static const guint mp3types_bitrates[2][3][16] = {
174 {0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448,},
175 {0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384,},
176 {0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320,}
179 {0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256,},
180 {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160,},
181 {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160,}
185 static const guint mp3types_freqs[3][3] = { {44100, 48000, 32000},
186 {22050, 24000, 16000},
191 mp3_type_frame_length_from_header (GstElement * mp3parse, guint32 header,
192 guint * put_version, guint * put_layer, guint * put_channels,
193 guint * put_bitrate, guint * put_samplerate, guint * put_mode,
197 gulong mode, samplerate, bitrate, layer, channels, padding, crc;
201 if (header & (1 << 20)) {
202 lsf = (header & (1 << 19)) ? 0 : 1;
209 version = 1 + lsf + mpg25;
211 layer = 4 - ((header >> 17) & 0x3);
213 crc = (header >> 16) & 0x1;
215 bitrate = (header >> 12) & 0xF;
216 bitrate = mp3types_bitrates[lsf][layer - 1][bitrate] * 1000;
217 /* The caller has ensured we have a valid header, so bitrate can't be
220 GST_DEBUG_OBJECT (mp3parse, "invalid bitrate");
224 samplerate = (header >> 10) & 0x3;
225 samplerate = mp3types_freqs[lsf + mpg25][samplerate];
227 padding = (header >> 9) & 0x1;
229 mode = (header >> 6) & 0x3;
230 channels = (mode == 3) ? 1 : 2;
234 length = 4 * ((bitrate * 12) / samplerate + padding);
237 length = (bitrate * 144) / samplerate + padding;
241 length = (bitrate * 144) / (samplerate << lsf) + padding;
245 GST_LOG_OBJECT (mp3parse, "Calculated mp3 frame length of %u bytes", length);
246 GST_LOG_OBJECT (mp3parse, "samplerate = %lu, bitrate = %lu, version = %lu, "
247 "layer = %lu, channels = %lu, mode = %lu", samplerate, bitrate, version,
248 layer, channels, mode);
251 *put_version = version;
255 *put_channels = channels;
257 *put_bitrate = bitrate;
259 *put_samplerate = samplerate;
265 GST_LOG_OBJECT (mp3parse, "size = %u", length);
269 /* generate empty/silent/dummy frame that mimics @frame,
270 * except for rate, where maximum possible is selected */
272 gst_rtp_mpa_robust_depay_generate_dummy_frame (GstRtpMPARobustDepay *
273 rtpmpadepay, GstADUFrame * frame)
278 dummy = g_slice_dup (GstADUFrame, frame);
280 /* go for maximum bitrate */
281 dummy->header = (frame->header & ~(0xf << 12)) | (0xe << 12);
283 mp3_type_frame_length_from_header (GST_ELEMENT_CAST (rtpmpadepay),
284 dummy->header, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
285 dummy->data_size = dummy->size - 4 - dummy->side_info;
286 dummy->backpointer = 0;
288 dummy->buffer = gst_buffer_new_and_alloc (dummy->side_info + 4);
290 gst_buffer_map (dummy->buffer, &map, GST_MAP_WRITE);
291 memset (map.data, 0, map.size);
292 GST_WRITE_UINT32_BE (map.data, dummy->header);
293 gst_buffer_unmap (dummy->buffer, &map);
295 GST_BUFFER_TIMESTAMP (dummy->buffer) = GST_BUFFER_TIMESTAMP (frame->buffer);
300 /* validates and parses @buf, and queues for further transformation if valid,
301 * otherwise discards @buf
302 * Takes ownership of @buf. */
304 gst_rtp_mpa_robust_depay_queue_frame (GstRtpMPARobustDepay * rtpmpadepay,
307 GstADUFrame *frame = NULL;
308 guint version, layer, channels, size;
312 g_return_val_if_fail (buf != NULL, FALSE);
314 gst_buffer_map (buf, &map, GST_MAP_READ);
319 frame = g_slice_new0 (GstADUFrame);
320 frame->header = GST_READ_UINT32_BE (map.data);
322 size = mp3_type_frame_length_from_header (GST_ELEMENT_CAST (rtpmpadepay),
323 frame->header, &version, &layer, &channels, NULL, NULL, NULL, &crc);
328 frame->layer = layer;
329 if (version == 1 && channels == 2)
330 frame->side_info = 32;
331 else if ((version == 1 && channels == 1) || (version >= 2 && channels == 2))
332 frame->side_info = 17;
333 else if (version >= 2 && channels == 1)
334 frame->side_info = 9;
336 g_assert_not_reached ();
342 frame->backpointer = GST_READ_UINT16_BE (map.data + 4);
343 frame->backpointer >>= 7;
344 GST_LOG_OBJECT (rtpmpadepay, "backpointer: %d", frame->backpointer);
348 frame->side_info += 2;
350 GST_LOG_OBJECT (rtpmpadepay, "side info: %d", frame->side_info);
351 frame->data_size = frame->size - 4 - frame->side_info;
353 /* some size validation checks */
354 if (4 + frame->side_info > map.size)
357 /* ADU data would then extend past MP3 frame,
358 * even using past byte reservoir */
359 if (-frame->backpointer + (gint) (map.size) > frame->size)
362 gst_buffer_unmap (buf, &map);
364 /* ok, take buffer and queue */
366 g_queue_push_tail (rtpmpadepay->adu_frames, frame);
373 GST_DEBUG_OBJECT (rtpmpadepay, "frame is corrupt");
374 gst_buffer_unmap (buf, &map);
375 gst_buffer_unref (buf);
377 g_slice_free (GstADUFrame, frame);
383 gst_rtp_mpa_robust_depay_free_frame (GstADUFrame * frame)
386 gst_buffer_unref (frame->buffer);
387 g_slice_free (GstADUFrame, frame);
391 gst_rtp_mpa_robust_depay_dequeue_frame (GstRtpMPARobustDepay * rtpmpadepay)
395 GST_LOG_OBJECT (rtpmpadepay, "dequeueing ADU frame");
397 if (rtpmpadepay->adu_frames->head == rtpmpadepay->cur_adu_frame)
398 rtpmpadepay->cur_adu_frame = NULL;
400 head = g_queue_pop_head (rtpmpadepay->adu_frames);
401 g_assert (head->buffer);
402 gst_rtp_mpa_robust_depay_free_frame (head);
407 /* returns TRUE if at least one new ADU frame was enqueued for MP3 conversion.
408 * Takes ownership of @buf. */
410 gst_rtp_mpa_robust_depay_deinterleave (GstRtpMPARobustDepay * rtpmpadepay,
413 gboolean ret = FALSE;
415 guint val, iindex, icc;
417 gst_buffer_map (buf, &map, GST_MAP_READ);
418 val = GST_READ_UINT16_BE (map.data) >> 5;
419 gst_buffer_unmap (buf, &map);
424 GST_LOG_OBJECT (rtpmpadepay, "sync: 0x%x, index: %u, cycle count: %u",
427 /* basic case; no interleaving ever seen */
428 if (val == 0x7ff && rtpmpadepay->last_icc < 0) {
429 ret = gst_rtp_mpa_robust_depay_queue_frame (rtpmpadepay, buf);
431 if (G_UNLIKELY (rtpmpadepay->last_icc < 0)) {
432 rtpmpadepay->last_icc = icc;
433 rtpmpadepay->last_ii = iindex;
435 if (icc != rtpmpadepay->last_icc || iindex == rtpmpadepay->last_ii) {
438 for (i = 0; i < 256; ++i) {
439 if (rtpmpadepay->deinter[i] != NULL) {
440 ret |= gst_rtp_mpa_robust_depay_queue_frame (rtpmpadepay,
441 rtpmpadepay->deinter[i]);
442 rtpmpadepay->deinter[i] = NULL;
446 /* rewrite buffer sync header */
447 gst_buffer_map (buf, &map, GST_MAP_READWRITE);
448 val = GST_READ_UINT16_BE (map.data);
449 val = (0x7ff << 5) | val;
450 GST_WRITE_UINT16_BE (map.data, val);
451 gst_buffer_unmap (buf, &map);
452 /* store and keep track of last indices */
453 rtpmpadepay->last_icc = icc;
454 rtpmpadepay->last_ii = iindex;
455 rtpmpadepay->deinter[iindex] = buf;
461 /* Head ADU frame corresponds to mp3_frame (i.e. in header in side-info) that
462 * is currently being written
463 * cur_adu_frame refers to ADU frame whose data should be bytewritten next
464 * (possibly starting from offset rather than start 0) (and is typicall tail
465 * at time of last push round).
466 * If at start, position where it should start writing depends on (data) sizes
467 * of previous mp3 frames (corresponding to foregoing ADU frames) kept in size,
468 * and its backpointer */
470 gst_rtp_mpa_robust_depay_push_mp3_frames (GstRtpMPARobustDepay * rtpmpadepay)
473 GstADUFrame *frame, *head;
475 GstFlowReturn ret = GST_FLOW_OK;
480 if (G_UNLIKELY (!rtpmpadepay->cur_adu_frame)) {
481 rtpmpadepay->cur_adu_frame = rtpmpadepay->adu_frames->head;
482 rtpmpadepay->offset = 0;
483 rtpmpadepay->size = 0;
486 if (G_UNLIKELY (!rtpmpadepay->cur_adu_frame))
489 frame = (GstADUFrame *) rtpmpadepay->cur_adu_frame->data;
490 head = (GstADUFrame *) rtpmpadepay->adu_frames->head->data;
492 /* special case: non-layer III are sent straight through */
493 if (G_UNLIKELY (frame->layer != 3)) {
494 GST_DEBUG_OBJECT (rtpmpadepay, "layer %d frame, sending as-is",
496 gst_rtp_base_depayload_push (GST_RTP_BASE_DEPAYLOAD (rtpmpadepay),
498 frame->buffer = NULL;
499 /* and remove it from any further consideration */
500 g_slice_free (GstADUFrame, frame);
501 g_queue_delete_link (rtpmpadepay->adu_frames, rtpmpadepay->cur_adu_frame);
502 rtpmpadepay->cur_adu_frame = NULL;
506 if (rtpmpadepay->offset == gst_buffer_get_size (frame->buffer)) {
507 if (g_list_next (rtpmpadepay->cur_adu_frame)) {
508 rtpmpadepay->size += frame->data_size;
509 rtpmpadepay->cur_adu_frame = g_list_next (rtpmpadepay->cur_adu_frame);
510 frame = (GstADUFrame *) rtpmpadepay->cur_adu_frame->data;
511 rtpmpadepay->offset = 0;
512 GST_LOG_OBJECT (rtpmpadepay,
513 "moving to next ADU frame, size %d, side_info %d, backpointer %d",
514 frame->size, frame->side_info, frame->backpointer);
515 /* layer I and II packets have no bitreservoir and must be sent as-is;
516 * so flush any pending frame */
517 if (G_UNLIKELY (frame->layer != 3 && rtpmpadepay->mp3_frame))
524 if (G_UNLIKELY (!rtpmpadepay->mp3_frame)) {
525 GST_LOG_OBJECT (rtpmpadepay,
526 "setting up new MP3 frame of size %d, side_info %d",
527 head->size, head->side_info);
528 rtpmpadepay->mp3_frame = gst_byte_writer_new_with_size (head->size, TRUE);
529 /* 0-fill possible gaps */
530 gst_byte_writer_fill_unchecked (rtpmpadepay->mp3_frame, 0, head->size);
531 gst_byte_writer_set_pos (rtpmpadepay->mp3_frame, 0);
532 /* bytewriter corresponds to head frame,
533 * i.e. the header and the side info must match */
534 g_assert (4 + head->side_info <= head->size);
535 gst_buffer_map (head->buffer, &map, GST_MAP_READ);
536 gst_byte_writer_put_data_unchecked (rtpmpadepay->mp3_frame,
537 map.data, 4 + head->side_info);
538 gst_buffer_unmap (head->buffer, &map);
542 av = gst_byte_writer_get_remaining (rtpmpadepay->mp3_frame);
543 GST_LOG_OBJECT (rtpmpadepay, "current mp3 frame remaining: %d", av);
544 GST_LOG_OBJECT (rtpmpadepay, "accumulated ADU frame data_size: %d",
547 if (rtpmpadepay->offset) {
548 gst_buffer_map (buf, &map, GST_MAP_READ);
549 /* no need to position, simply append */
550 g_assert (map.size > rtpmpadepay->offset);
551 av = MIN (av, map.size - rtpmpadepay->offset);
552 GST_LOG_OBJECT (rtpmpadepay,
553 "appending %d bytes from ADU frame at offset %d", av,
554 rtpmpadepay->offset);
555 gst_byte_writer_put_data_unchecked (rtpmpadepay->mp3_frame,
556 map.data + rtpmpadepay->offset, av);
557 rtpmpadepay->offset += av;
558 gst_buffer_unmap (buf, &map);
562 /* position writing according to ADU frame backpointer */
563 pos = gst_byte_writer_get_pos (rtpmpadepay->mp3_frame);
564 tpos = rtpmpadepay->size - frame->backpointer + 4 + head->side_info;
565 GST_LOG_OBJECT (rtpmpadepay, "current MP3 frame at position %d, "
566 "starting new ADU frame data at offset %d", pos, tpos);
570 /* try to insert as few frames as possible,
571 * so go for a reasonably large dummy frame size */
572 GST_LOG_OBJECT (rtpmpadepay,
573 "overlapping previous data; inserting dummy frame");
575 gst_rtp_mpa_robust_depay_generate_dummy_frame (rtpmpadepay, frame);
576 g_queue_insert_before (rtpmpadepay->adu_frames,
577 rtpmpadepay->cur_adu_frame, dummy);
578 /* offset is known to be zero, so we can shift current one */
579 rtpmpadepay->cur_adu_frame = rtpmpadepay->cur_adu_frame->prev;
580 if (!rtpmpadepay->size) {
581 g_assert (rtpmpadepay->cur_adu_frame ==
582 rtpmpadepay->adu_frames->head);
583 GST_LOG_OBJECT (rtpmpadepay, "... which is new head frame");
584 gst_byte_writer_free (rtpmpadepay->mp3_frame);
585 rtpmpadepay->mp3_frame = NULL;
587 /* ... and continue adding that empty one immediately,
588 * and then see if that provided enough extra space */
590 } else if (tpos >= pos + av) {
591 /* ADU frame no longer needs current MP3 frame; move to its end */
592 GST_LOG_OBJECT (rtpmpadepay, "passed current MP3 frame");
593 gst_byte_writer_set_pos (rtpmpadepay->mp3_frame, pos + av);
595 /* position and append */
596 gst_buffer_map (buf, &map, GST_MAP_READ);
597 GST_LOG_OBJECT (rtpmpadepay, "adding to current MP3 frame");
598 gst_byte_writer_set_pos (rtpmpadepay->mp3_frame, tpos);
600 g_assert (map.size >= 4 + frame->side_info);
601 av = MIN (av, map.size - 4 - frame->side_info);
602 gst_byte_writer_put_data_unchecked (rtpmpadepay->mp3_frame,
603 map.data + 4 + frame->side_info, av);
604 rtpmpadepay->offset += av + 4 + frame->side_info;
605 gst_buffer_unmap (buf, &map);
609 /* if mp3 frame filled, send on its way */
610 if (gst_byte_writer_get_remaining (rtpmpadepay->mp3_frame) == 0) {
612 buf = gst_byte_writer_free_and_get_buffer (rtpmpadepay->mp3_frame);
613 rtpmpadepay->mp3_frame = NULL;
614 GST_BUFFER_TIMESTAMP (buf) = GST_BUFFER_TIMESTAMP (head->buffer);
615 /* no longer need head ADU frame header and side info */
616 /* NOTE maybe head == current, then size and offset go off a bit,
617 * but current gets reset to NULL, and then also offset and size */
618 rtpmpadepay->size -= head->data_size;
619 gst_rtp_mpa_robust_depay_dequeue_frame (rtpmpadepay);
621 ret = gst_rtp_base_depayload_push (GST_RTP_BASE_DEPAYLOAD (rtpmpadepay),
629 /* process ADU frame @buf through:
631 * - converting to MP3 frames
632 * Takes ownership of @buf.
635 gst_rtp_mpa_robust_depay_submit_adu (GstRtpMPARobustDepay * rtpmpadepay,
638 if (gst_rtp_mpa_robust_depay_deinterleave (rtpmpadepay, buf))
639 return gst_rtp_mpa_robust_depay_push_mp3_frames (rtpmpadepay);
645 gst_rtp_mpa_robust_depay_process (GstRTPBaseDepayload * depayload,
648 GstRtpMPARobustDepay *rtpmpadepay;
649 gint payload_len, offset;
651 gboolean cont, dtype;
653 GstClockTime timestamp;
654 GstRTPBuffer rtp = { NULL };
656 rtpmpadepay = GST_RTP_MPA_ROBUST_DEPAY (depayload);
658 timestamp = GST_BUFFER_TIMESTAMP (buf);
660 gst_rtp_buffer_map (buf, GST_MAP_READ, &rtp);
662 payload_len = gst_rtp_buffer_get_payload_len (&rtp);
663 if (payload_len <= 1)
666 payload = gst_rtp_buffer_get_payload (&rtp);
668 GST_LOG_OBJECT (rtpmpadepay, "payload_len: %d", payload_len);
670 /* strip off descriptor
673 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6
674 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
676 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
678 * C: if 1, data is continuation
679 * T: if 1, size is 14 bits, otherwise 6 bits
680 * ADU size: size of following packet (not including descriptor)
682 while (payload_len) {
683 if (G_LIKELY (rtpmpadepay->has_descriptor)) {
684 cont = ! !(payload[offset] & 0x80);
685 dtype = ! !(payload[offset] & 0x40);
687 size = (payload[offset] & 0x3f) << 8 | payload[offset + 1];
690 } else if (payload_len >= 2) {
691 size = (payload[offset] & 0x3f);
703 GST_LOG_OBJECT (rtpmpadepay, "offset %d has cont: %d, dtype: %d, size: %d",
704 offset, cont, dtype, size);
706 buf = gst_rtp_buffer_get_payload_subbuffer (&rtp, offset,
707 MIN (size, payload_len));
710 av = gst_adapter_available (rtpmpadepay->adapter);
711 if (G_UNLIKELY (!av)) {
712 GST_DEBUG_OBJECT (rtpmpadepay,
713 "discarding continuation fragment without prior fragment");
714 gst_buffer_unref (buf);
716 av += gst_buffer_get_size (buf);
717 gst_adapter_push (rtpmpadepay->adapter, buf);
719 timestamp = gst_adapter_prev_timestamp (rtpmpadepay->adapter, NULL);
720 buf = gst_adapter_take_buffer (rtpmpadepay->adapter, size);
721 GST_BUFFER_TIMESTAMP (buf) = timestamp;
722 gst_rtp_mpa_robust_depay_submit_adu (rtpmpadepay, buf);
723 } else if (av > size) {
724 GST_DEBUG_OBJECT (rtpmpadepay,
725 "assembled ADU size %d larger than expected %d; discarding",
727 gst_adapter_clear (rtpmpadepay->adapter);
732 /* not continuation, first fragment or whole ADU */
733 if (payload_len == size) {
735 GST_BUFFER_TIMESTAMP (buf) = timestamp;
736 gst_rtp_mpa_robust_depay_submit_adu (rtpmpadepay, buf);
737 } else if (payload_len < size) {
739 gst_adapter_push (rtpmpadepay->adapter, buf);
747 /* timestamp applies to first payload, no idea for subsequent ones */
748 timestamp = GST_CLOCK_TIME_NONE;
750 gst_rtp_buffer_unmap (&rtp);
757 GST_ELEMENT_WARNING (rtpmpadepay, STREAM, DECODE,
758 (NULL), ("Packet contains invalid data"));
759 gst_rtp_buffer_unmap (&rtp);
764 static GstStateChangeReturn
765 gst_rtp_mpa_robust_change_state (GstElement * element,
766 GstStateChange transition)
768 GstStateChangeReturn ret;
769 GstRtpMPARobustDepay *rtpmpadepay;
771 rtpmpadepay = GST_RTP_MPA_ROBUST_DEPAY (element);
773 switch (transition) {
774 case GST_STATE_CHANGE_READY_TO_PAUSED:
775 rtpmpadepay->last_ii = -1;
776 rtpmpadepay->last_icc = -1;
777 rtpmpadepay->size = 0;
778 rtpmpadepay->offset = 0;
783 ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
784 if (ret != GST_STATE_CHANGE_SUCCESS)
787 switch (transition) {
788 case GST_STATE_CHANGE_PAUSED_TO_READY:
792 gst_adapter_clear (rtpmpadepay->adapter);
793 for (i = 0; i < G_N_ELEMENTS (rtpmpadepay->deinter); i++) {
794 gst_buffer_replace (&rtpmpadepay->deinter[i], NULL);
796 rtpmpadepay->cur_adu_frame = NULL;
797 g_queue_foreach (rtpmpadepay->adu_frames,
798 (GFunc) gst_rtp_mpa_robust_depay_free_frame, NULL);
799 g_queue_clear (rtpmpadepay->adu_frames);
800 if (rtpmpadepay->mp3_frame)
801 gst_byte_writer_free (rtpmpadepay->mp3_frame);
812 gst_rtp_mpa_robust_depay_plugin_init (GstPlugin * plugin)
814 return gst_element_register (plugin, "rtpmparobustdepay",
815 GST_RANK_SECONDARY, GST_TYPE_RTP_MPA_ROBUST_DEPAY);