tizen 2.0 init
[framework/multimedia/gst-plugins-good0.10.git] / gst / isomp4 / gstrtpxqtdepay.c
1 /* GStreamer
2  * Copyright (C) <2006> Wim Taymans <wim@fluendo.com>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 /*
21  * based on http://developer.apple.com/quicktime/icefloe/dispatch026.html
22  */
23 #ifdef HAVE_CONFIG_H
24 #  include "config.h"
25 #endif
26
27 #include <gst/rtp/gstrtpbuffer.h>
28
29 #include <string.h>
30 #include "gstrtpxqtdepay.h"
31
32 #define MAKE_TLV(a,b)  (((a)<<8)|(b))
33
34 #define TLV_sd  MAKE_TLV ('s','d')
35 #define TLV_qt  MAKE_TLV ('q','t')
36 #define TLV_ti  MAKE_TLV ('t','i')
37 #define TLV_ly  MAKE_TLV ('l','y')
38 #define TLV_vo  MAKE_TLV ('v','o')
39 #define TLV_mx  MAKE_TLV ('m','x')
40 #define TLV_tr  MAKE_TLV ('t','r')
41 #define TLV_tw  MAKE_TLV ('t','w')
42 #define TLV_th  MAKE_TLV ('t','h')
43 #define TLV_la  MAKE_TLV ('l','a')
44 #define TLV_rt  MAKE_TLV ('r','t')
45 #define TLV_gm  MAKE_TLV ('g','m')
46 #define TLV_oc  MAKE_TLV ('o','c')
47 #define TLV_cr  MAKE_TLV ('c','r')
48 #define TLV_du  MAKE_TLV ('d','u')
49 #define TLV_po  MAKE_TLV ('p','o')
50
51 #define QT_UINT32(a)  (GST_READ_UINT32_BE(a))
52 #define QT_UINT24(a)  (GST_READ_UINT32_BE(a) >> 8)
53 #define QT_UINT16(a)  (GST_READ_UINT16_BE(a))
54 #define QT_UINT8(a)   (GST_READ_UINT8(a))
55 #define QT_FP32(a)    ((GST_READ_UINT32_BE(a))/65536.0)
56 #define QT_FP16(a)    ((GST_READ_UINT16_BE(a))/256.0)
57 #define QT_FOURCC(a)  (GST_READ_UINT32_LE(a))
58 #define QT_UINT64(a)  ((((guint64)QT_UINT32(a))<<32)|QT_UINT32(((guint8 *)a)+4))
59
60 #define FOURCC_avc1     GST_MAKE_FOURCC('a','v','c','1')
61 #define FOURCC_avcC     GST_MAKE_FOURCC('a','v','c','C')
62
63 GST_DEBUG_CATEGORY_STATIC (rtpxqtdepay_debug);
64 #define GST_CAT_DEFAULT (rtpxqtdepay_debug)
65
66 /* RtpXQTDepay signals and args */
67 enum
68 {
69   /* FILL ME */
70   LAST_SIGNAL
71 };
72
73 enum
74 {
75   ARG_0,
76 };
77
78 static GstStaticPadTemplate gst_rtp_xqt_depay_src_template =
79 GST_STATIC_PAD_TEMPLATE ("src",
80     GST_PAD_SRC,
81     GST_PAD_ALWAYS,
82     GST_STATIC_CAPS_ANY);
83
84 static GstStaticPadTemplate gst_rtp_xqt_depay_sink_template =
85 GST_STATIC_PAD_TEMPLATE ("sink",
86     GST_PAD_SINK,
87     GST_PAD_ALWAYS,
88     GST_STATIC_CAPS ("application/x-rtp, "
89         "payload = (int) " GST_RTP_PAYLOAD_DYNAMIC_STRING ", "
90         "media = (string) { \"audio\", \"video\" }, clock-rate = (int) [1, MAX], "
91         "encoding-name = (string) { \"X-QT\", \"X-QUICKTIME\" }")
92     );
93
94 GST_BOILERPLATE (GstRtpXQTDepay, gst_rtp_xqt_depay, GstBaseRTPDepayload,
95     GST_TYPE_BASE_RTP_DEPAYLOAD);
96
97 static void gst_rtp_xqt_depay_finalize (GObject * object);
98
99 static gboolean gst_rtp_xqt_depay_setcaps (GstBaseRTPDepayload * depayload,
100     GstCaps * caps);
101 static GstBuffer *gst_rtp_xqt_depay_process (GstBaseRTPDepayload * depayload,
102     GstBuffer * buf);
103
104 static GstStateChangeReturn gst_rtp_xqt_depay_change_state (GstElement *
105     element, GstStateChange transition);
106
107 static void
108 gst_rtp_xqt_depay_base_init (gpointer klass)
109 {
110   GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
111
112   gst_element_class_add_static_pad_template (element_class,
113       &gst_rtp_xqt_depay_src_template);
114   gst_element_class_add_static_pad_template (element_class,
115       &gst_rtp_xqt_depay_sink_template);
116
117   gst_element_class_set_details_simple (element_class, "RTP packet depayloader",
118       "Codec/Depayloader/Network",
119       "Extracts Quicktime audio/video from RTP packets",
120       "Wim Taymans <wim@fluendo.com>");
121 }
122
123 static void
124 gst_rtp_xqt_depay_class_init (GstRtpXQTDepayClass * klass)
125 {
126   GObjectClass *gobject_class;
127   GstElementClass *gstelement_class;
128   GstBaseRTPDepayloadClass *gstbasertpdepayload_class;
129
130   gobject_class = (GObjectClass *) klass;
131   gstelement_class = (GstElementClass *) klass;
132   gstbasertpdepayload_class = (GstBaseRTPDepayloadClass *) klass;
133
134   parent_class = g_type_class_peek_parent (klass);
135
136   gobject_class->finalize = gst_rtp_xqt_depay_finalize;
137
138   gstelement_class->change_state = gst_rtp_xqt_depay_change_state;
139
140   gstbasertpdepayload_class->set_caps = gst_rtp_xqt_depay_setcaps;
141   gstbasertpdepayload_class->process = gst_rtp_xqt_depay_process;
142
143   GST_DEBUG_CATEGORY_INIT (rtpxqtdepay_debug, "rtpxqtdepay", 0,
144       "QT Media RTP Depayloader");
145 }
146
147 static void
148 gst_rtp_xqt_depay_init (GstRtpXQTDepay * rtpxqtdepay,
149     GstRtpXQTDepayClass * klass)
150 {
151   rtpxqtdepay->adapter = gst_adapter_new ();
152 }
153
154 static void
155 gst_rtp_xqt_depay_finalize (GObject * object)
156 {
157   GstRtpXQTDepay *rtpxqtdepay;
158
159   rtpxqtdepay = GST_RTP_XQT_DEPAY (object);
160
161   g_object_unref (rtpxqtdepay->adapter);
162   rtpxqtdepay->adapter = NULL;
163
164   G_OBJECT_CLASS (parent_class)->finalize (object);
165 }
166
167 static gboolean
168 gst_rtp_quicktime_parse_sd (GstRtpXQTDepay * rtpxqtdepay, guint8 * data,
169     guint data_len)
170 {
171   gint len;
172   guint32 fourcc;
173
174   if (data_len < 8)
175     goto too_short;
176
177   len = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3];
178   if (len > data_len)
179     goto too_short;
180
181   fourcc = QT_FOURCC (data + 4);
182
183   GST_DEBUG_OBJECT (rtpxqtdepay, "parsing %" GST_FOURCC_FORMAT,
184       GST_FOURCC_ARGS (fourcc));
185
186   switch (fourcc) {
187     case FOURCC_avc1:
188     {
189       guint32 chlen;
190
191       if (len < 0x56)
192         goto too_short;
193       len -= 0x56;
194       data += 0x56;
195
196       /* find avcC */
197       while (len >= 8) {
198         chlen = QT_UINT32 (data);
199         fourcc = QT_FOURCC (data + 4);
200         if (fourcc == FOURCC_avcC) {
201           GstBuffer *buf;
202           gint size;
203           GstCaps *caps;
204
205           GST_DEBUG_OBJECT (rtpxqtdepay, "found avcC codec_data in sd, %u",
206               chlen);
207
208           /* parse, if found */
209           if (chlen < len)
210             size = chlen - 8;
211           else
212             size = len - 8;
213
214           buf = gst_buffer_new_and_alloc (size);
215           memcpy (GST_BUFFER_DATA (buf), data + 8, size);
216           caps = gst_caps_new_simple ("video/x-h264",
217               "codec_data", GST_TYPE_BUFFER, buf, NULL);
218           gst_buffer_unref (buf);
219           gst_pad_set_caps (GST_BASE_RTP_DEPAYLOAD (rtpxqtdepay)->srcpad, caps);
220           gst_caps_unref (caps);
221           break;
222         }
223         len -= chlen;
224         data += chlen;
225       }
226       break;
227     }
228     default:
229       break;
230   }
231   return TRUE;
232
233   /* ERRORS */
234 too_short:
235   {
236     return FALSE;
237   }
238 }
239
240 static gboolean
241 gst_rtp_xqt_depay_setcaps (GstBaseRTPDepayload * depayload, GstCaps * caps)
242 {
243   GstStructure *structure;
244   gint clock_rate = 90000;      /* default */
245
246   structure = gst_caps_get_structure (caps, 0);
247
248   gst_structure_get_int (structure, "clock-rate", &clock_rate);
249   depayload->clock_rate = clock_rate;
250
251   return TRUE;
252 }
253
254 static GstBuffer *
255 gst_rtp_xqt_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf)
256 {
257   GstRtpXQTDepay *rtpxqtdepay;
258   GstBuffer *outbuf;
259   gboolean m;
260
261   rtpxqtdepay = GST_RTP_XQT_DEPAY (depayload);
262
263   if (!gst_rtp_buffer_validate (buf))
264     goto bad_packet;
265
266   if (GST_BUFFER_IS_DISCONT (buf)) {
267     /* discont, clear adapter and try to find a new packet start */
268     gst_adapter_clear (rtpxqtdepay->adapter);
269     rtpxqtdepay->need_resync = TRUE;
270     GST_DEBUG_OBJECT (rtpxqtdepay, "we need resync");
271   }
272
273   m = gst_rtp_buffer_get_marker (buf);
274   GST_LOG_OBJECT (rtpxqtdepay, "marker: %d", m);
275
276   {
277     gint payload_len;
278     guint avail;
279     guint8 *payload;
280     guint8 ver, pck;
281     gboolean s, q, l, d;
282
283     payload_len = gst_rtp_buffer_get_payload_len (buf);
284     payload = gst_rtp_buffer_get_payload (buf);
285
286     /*                      1                   2                   3 
287      *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
288      * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
289      * | VER   |PCK|S|Q|L| RES         |D| QuickTime Payload ID        |
290      * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
291      */
292     if (payload_len <= 4)
293       goto wrong_length;
294
295     ver = (payload[0] & 0xf0) >> 4;
296     if (ver > 1)
297       goto wrong_version;
298
299     pck = (payload[0] & 0x0c) >> 2;
300     if (pck == 0)
301       goto pck_reserved;
302
303     s = (payload[0] & 0x02) != 0;       /* contains sync sample */
304     q = (payload[0] & 0x01) != 0;       /* has payload description */
305     l = (payload[1] & 0x80) != 0;       /* has packet specific information description */
306     d = (payload[2] & 0x80) != 0;       /* don't cache info for payload id */
307     /* id used for caching info */
308     rtpxqtdepay->current_id = ((payload[2] & 0x7f) << 8) | payload[3];
309
310     GST_LOG_OBJECT (rtpxqtdepay,
311         "VER: %d, PCK: %d, S: %d, Q: %d, L: %d, D: %d, ID: %d", ver, pck, s, q,
312         l, d, rtpxqtdepay->current_id);
313
314     if (rtpxqtdepay->need_resync) {
315       /* we need to find the boundary of a new packet after a DISCONT */
316       if (pck != 3 || q) {
317         /* non-fragmented packet or payload description present, packet starts
318          * here. */
319         rtpxqtdepay->need_resync = FALSE;
320       } else {
321         /* fragmented packet without description */
322         if (m) {
323           /* marker bit set, next packet is start of new one */
324           rtpxqtdepay->need_resync = FALSE;
325         }
326         goto need_resync;
327       }
328     }
329
330     payload += 4;
331     payload_len -= 4;
332
333     if (q) {
334       gboolean k, f, a, z;
335       guint pdlen, pdpadded;
336       gint padding;
337       /* media_type only used for printing */
338       guint32 G_GNUC_UNUSED media_type;
339       guint32 timescale;
340
341       /*                      1                   2                   3
342        *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
343        * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
344        * |K|F|A|Z| RES                   | QuickTime Payload Desc Length |
345        * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
346        * . QuickTime Payload Desc Data ... . 
347        * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
348        */
349       if (payload_len <= 4)
350         goto wrong_length;
351
352       k = (payload[0] & 0x80) != 0;     /* keyframe */
353       f = (payload[0] & 0x40) != 0;     /* sparse */
354       a = (payload[0] & 0x20) != 0;     /* start of payload */
355       z = (payload[0] & 0x10) != 0;     /* end of payload */
356       pdlen = (payload[2] << 8) | payload[3];
357
358       if (pdlen < 12)
359         goto wrong_length;
360
361       /* calc padding */
362       pdpadded = pdlen + 3;
363       pdpadded -= pdpadded % 4;
364       if (payload_len < pdpadded)
365         goto wrong_length;
366
367       padding = pdpadded - pdlen;
368       GST_LOG_OBJECT (rtpxqtdepay,
369           "K: %d, F: %d, A: %d, Z: %d, len: %d, padding %d", k, f, a, z, pdlen,
370           padding);
371
372       payload += 4;
373       payload_len -= 4;
374       /*                      1                   2                   3
375        *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
376        * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
377        * | QuickTime Media Type                                          |
378        * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
379        * | Timescale                                                     |
380        * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
381        * . QuickTime TLVs ... .
382        * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
383        */
384       media_type =
385           (payload[0] << 24) | (payload[1] << 16) | (payload[2] << 8) |
386           payload[3];
387       timescale =
388           (payload[4] << 24) | (payload[5] << 16) | (payload[6] << 8) |
389           payload[7];
390
391       GST_LOG_OBJECT (rtpxqtdepay, "media_type: %c%c%c%c, timescale %u",
392           payload[0], payload[1], payload[2], payload[3], timescale);
393
394       payload += 8;
395       payload_len -= 8;
396       pdlen -= 12;
397
398       /* parse TLV (type-length-value triplets */
399       while (pdlen > 3) {
400         guint16 tlv_len, tlv_type;
401
402         /*                      1                   2                   3
403          *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
404          * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
405          * | QuickTime TLV Length          | QuickTime TLV Type            |
406          * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
407          * . QuickTime TLV Value ... .
408          * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
409          */
410         tlv_len = (payload[0] << 8) | payload[1];
411         tlv_type = (payload[2] << 8) | payload[3];
412         pdlen -= 4;
413         if (tlv_len > pdlen)
414           goto wrong_length;
415
416         GST_LOG_OBJECT (rtpxqtdepay, "TLV '%c%c', len %d", payload[2],
417             payload[3], tlv_len);
418
419         payload += 4;
420         payload_len -= 4;
421
422         switch (tlv_type) {
423           case TLV_sd:
424             /* Session description */
425             if (!gst_rtp_quicktime_parse_sd (rtpxqtdepay, payload, tlv_len))
426               goto unknown_format;
427             rtpxqtdepay->have_sd = TRUE;
428             break;
429           case TLV_qt:
430           case TLV_ti:
431           case TLV_ly:
432           case TLV_vo:
433           case TLV_mx:
434           case TLV_tr:
435           case TLV_tw:
436           case TLV_th:
437           case TLV_la:
438           case TLV_rt:
439           case TLV_gm:
440           case TLV_oc:
441           case TLV_cr:
442           case TLV_du:
443           case TLV_po:
444           default:
445             break;
446         }
447
448         pdlen -= tlv_len;
449         payload += tlv_len;
450         payload_len -= tlv_len;
451       }
452       payload += padding;
453       payload_len -= padding;
454     }
455
456     if (l) {
457       guint ssilen, ssipadded;
458       gint padding;
459
460       /*                      1                   2                   3
461        *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
462        * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
463        * | RES                           | Sample-Specific Info Length   |
464        * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
465        * . QuickTime TLVs ... 
466        * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
467        */
468       if (payload_len <= 4)
469         goto wrong_length;
470
471       ssilen = (payload[2] << 8) | payload[3];
472       if (ssilen < 4)
473         goto wrong_length;
474
475       /* calc padding */
476       ssipadded = ssilen + 3;
477       ssipadded -= ssipadded % 4;
478       if (payload_len < ssipadded)
479         goto wrong_length;
480
481       padding = ssipadded - ssilen;
482       GST_LOG_OBJECT (rtpxqtdepay, "len: %d, padding %d", ssilen, padding);
483
484       payload += 4;
485       payload_len -= 4;
486       ssilen -= 4;
487
488       /* parse TLV (type-length-value triplets */
489       while (ssilen > 3) {
490         guint16 tlv_len, tlv_type;
491
492         /*                      1                   2                   3
493          *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
494          * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
495          * | QuickTime TLV Length          | QuickTime TLV Type            |
496          * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
497          * . QuickTime TLV Value ... .
498          * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
499          */
500         tlv_len = (payload[0] << 8) | payload[1];
501         tlv_type = (payload[2] << 8) | payload[3];
502         ssilen -= 4;
503         if (tlv_len > ssilen)
504           goto wrong_length;
505
506         GST_LOG_OBJECT (rtpxqtdepay, "TLV '%c%c', len %d", payload[2],
507             payload[3], tlv_len);
508
509         payload += 4;
510         payload_len -= 4;
511
512         switch (tlv_type) {
513           case TLV_sd:
514           case TLV_qt:
515           case TLV_ti:
516           case TLV_ly:
517           case TLV_vo:
518           case TLV_mx:
519           case TLV_tr:
520           case TLV_tw:
521           case TLV_th:
522           case TLV_la:
523           case TLV_rt:
524           case TLV_gm:
525           case TLV_oc:
526           case TLV_cr:
527           case TLV_du:
528           case TLV_po:
529           default:
530             break;
531         }
532
533         ssilen -= tlv_len;
534         payload += tlv_len;
535         payload_len -= tlv_len;
536       }
537       payload += padding;
538       payload_len -= padding;
539     }
540
541     rtpxqtdepay->previous_id = rtpxqtdepay->current_id;
542
543     switch (pck) {
544       case 1:
545       {
546         /* multiple samples per packet. */
547         outbuf = gst_buffer_new_and_alloc (payload_len);
548         memcpy (GST_BUFFER_DATA (outbuf), payload, payload_len);
549         return outbuf;
550       }
551       case 2:
552       {
553         guint slen;
554
555         /* multiple samples per packet. 
556          *                      1                   2                   3
557          *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
558          * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
559          * |S| Reserved                    | Sample Length                 |
560          * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
561          * | Sample Timestamp                                              |
562          * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
563          * . Sample Data ...                                               .
564          * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
565          * |S| Reserved                    | Sample Length                 |
566          * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
567          * | Sample Timestamp                                              |
568          * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
569          * . Sample Data ...                                               .
570          * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
571          * . ......                                                        .
572          * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
573          */
574         while (payload_len > 8) {
575           s = (payload[0] & 0x80) != 0; /* contains sync sample */
576           slen = (payload[2] << 8) | payload[3];
577           /* timestamp =
578            *    (payload[4] << 24) | (payload[5] << 16) | (payload[6] << 8) |
579            *    payload[7];
580            */
581
582           payload += 8;
583           payload_len -= 8;
584
585           if (slen > payload_len)
586             slen = payload_len;
587
588           outbuf = gst_buffer_new_and_alloc (slen);
589           memcpy (GST_BUFFER_DATA (outbuf), payload, slen);
590           if (!s)
591             GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DELTA_UNIT);
592
593           gst_base_rtp_depayload_push (depayload, outbuf);
594
595           /* aligned on 32 bit boundary */
596           slen = GST_ROUND_UP_4 (slen);
597
598           payload += slen;
599           payload_len -= slen;
600         }
601         break;
602       }
603       case 3:
604       {
605         /* one sample per packet, use adapter to combine based on marker bit. */
606         outbuf = gst_buffer_new_and_alloc (payload_len);
607         memcpy (GST_BUFFER_DATA (outbuf), payload, payload_len);
608
609         gst_adapter_push (rtpxqtdepay->adapter, outbuf);
610
611         if (!m)
612           goto done;
613
614         avail = gst_adapter_available (rtpxqtdepay->adapter);
615         outbuf = gst_adapter_take_buffer (rtpxqtdepay->adapter, avail);
616
617         GST_DEBUG_OBJECT (rtpxqtdepay,
618             "gst_rtp_xqt_depay_chain: pushing buffer of size %u", avail);
619
620         return outbuf;
621       }
622     }
623   }
624
625 done:
626   return NULL;
627
628 bad_packet:
629   {
630     GST_ELEMENT_WARNING (rtpxqtdepay, STREAM, DECODE,
631         ("Packet did not validate."), (NULL));
632     return NULL;
633   }
634 need_resync:
635   {
636     GST_DEBUG_OBJECT (rtpxqtdepay, "waiting for marker");
637     return NULL;
638   }
639 wrong_version:
640   {
641     GST_ELEMENT_WARNING (rtpxqtdepay, STREAM, DECODE,
642         ("Unknown payload version."), (NULL));
643     return NULL;
644   }
645 pck_reserved:
646   {
647     GST_ELEMENT_WARNING (rtpxqtdepay, STREAM, DECODE,
648         ("PCK reserved 0."), (NULL));
649     return NULL;
650   }
651 wrong_length:
652   {
653     GST_ELEMENT_WARNING (rtpxqtdepay, STREAM, DECODE,
654         ("Wrong payload length."), (NULL));
655     return NULL;
656   }
657 unknown_format:
658   {
659     GST_ELEMENT_WARNING (rtpxqtdepay, STREAM, DECODE,
660         ("Unknown payload format."), (NULL));
661     return NULL;
662   }
663 }
664
665 static GstStateChangeReturn
666 gst_rtp_xqt_depay_change_state (GstElement * element, GstStateChange transition)
667 {
668   GstRtpXQTDepay *rtpxqtdepay;
669   GstStateChangeReturn ret;
670
671   rtpxqtdepay = GST_RTP_XQT_DEPAY (element);
672
673   switch (transition) {
674     case GST_STATE_CHANGE_READY_TO_PAUSED:
675       gst_adapter_clear (rtpxqtdepay->adapter);
676       rtpxqtdepay->previous_id = -1;
677       rtpxqtdepay->current_id = -1;
678       rtpxqtdepay->need_resync = TRUE;
679       rtpxqtdepay->have_sd = FALSE;
680       break;
681     default:
682       break;
683   }
684
685   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
686
687   switch (transition) {
688     case GST_STATE_CHANGE_PAUSED_TO_READY:
689       gst_adapter_clear (rtpxqtdepay->adapter);
690     default:
691       break;
692   }
693   return ret;
694 }