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
gst_rtp_mpa_robust_depay_finalize(GObject * object)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
gst_rtp_mpa_robust_depay_class_init(GstRtpMPARobustDepayClass * klass)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
gst_rtp_mpa_robust_depay_init(GstRtpMPARobustDepay * rtpmpadepay)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
gst_rtp_mpa_robust_depay_setcaps(GstRTPBaseDepayload * depayload,GstCaps * caps)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
mp3_type_frame_length_from_header(GstElement * mp3parse,guint32 header,guint * put_version,guint * put_layer,guint * put_channels,guint * put_bitrate,guint * put_samplerate,guint * put_mode,guint * put_crc)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 *
gst_rtp_mpa_robust_depay_generate_dummy_frame(GstRtpMPARobustDepay * rtpmpadepay,GstADUFrame * frame)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
gst_rtp_mpa_robust_depay_queue_frame(GstRtpMPARobustDepay * rtpmpadepay,GstBuffer * buf)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
gst_rtp_mpa_robust_depay_free_frame(GstADUFrame * frame)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
gst_rtp_mpa_robust_depay_dequeue_frame(GstRtpMPARobustDepay * rtpmpadepay)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
gst_rtp_mpa_robust_depay_deinterleave(GstRtpMPARobustDepay * rtpmpadepay,GstBuffer * buf)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
gst_rtp_mpa_robust_depay_push_mp3_frames(GstRtpMPARobustDepay * rtpmpadepay)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
gst_rtp_mpa_robust_depay_submit_adu(GstRtpMPARobustDepay * rtpmpadepay,GstBuffer * buf)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 *
gst_rtp_mpa_robust_depay_process(GstRTPBaseDepayload * depayload,GstRTPBuffer * rtp)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
gst_rtp_mpa_robust_change_state(GstElement * element,GstStateChange transition)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 }
809