upload tizen1.0 source
[framework/multimedia/gst-plugins-good0.10.git] / gst / rtp / gstrtph264depay.c
1 /* GStreamer
2  * Copyright (C) <2006> Wim Taymans <wim.taymans@gmail.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 #ifdef HAVE_CONFIG_H
21 #  include "config.h"
22 #endif
23
24 #include <stdio.h>
25 #include <string.h>
26
27 #include <gst/rtp/gstrtpbuffer.h>
28 #include "gstrtph264depay.h"
29
30 GST_DEBUG_CATEGORY_STATIC (rtph264depay_debug);
31 #define GST_CAT_DEFAULT (rtph264depay_debug)
32
33 #define DEFAULT_BYTE_STREAM     TRUE
34 #define DEFAULT_ACCESS_UNIT     FALSE
35
36 enum
37 {
38   PROP_0,
39   PROP_BYTE_STREAM,
40   PROP_ACCESS_UNIT,
41   PROP_LAST
42 };
43
44
45 /* 3 zero bytes syncword */
46 static const guint8 sync_bytes[] = { 0, 0, 0, 1 };
47
48 static GstStaticPadTemplate gst_rtp_h264_depay_src_template =
49 GST_STATIC_PAD_TEMPLATE ("src",
50     GST_PAD_SRC,
51     GST_PAD_ALWAYS,
52     GST_STATIC_CAPS ("video/x-h264")
53     );
54
55 static GstStaticPadTemplate gst_rtp_h264_depay_sink_template =
56 GST_STATIC_PAD_TEMPLATE ("sink",
57     GST_PAD_SINK,
58     GST_PAD_ALWAYS,
59     GST_STATIC_CAPS ("application/x-rtp, "
60         "media = (string) \"video\", "
61         "payload = (int) " GST_RTP_PAYLOAD_DYNAMIC_STRING ", "
62         "clock-rate = (int) 90000, " "encoding-name = (string) \"H264\"")
63         /** optional parameters **/
64     /* "profile-level-id = (string) ANY, " */
65     /* "max-mbps = (string) ANY, " */
66     /* "max-fs = (string) ANY, " */
67     /* "max-cpb = (string) ANY, " */
68     /* "max-dpb = (string) ANY, " */
69     /* "max-br = (string) ANY, " */
70     /* "redundant-pic-cap = (string) { \"0\", \"1\" }, " */
71     /* "sprop-parameter-sets = (string) ANY, " */
72     /* "parameter-add = (string) { \"0\", \"1\" }, " */
73     /* "packetization-mode = (string) { \"0\", \"1\", \"2\" }, " */
74     /* "sprop-interleaving-depth = (string) ANY, " */
75     /* "sprop-deint-buf-req = (string) ANY, " */
76     /* "deint-buf-cap = (string) ANY, " */
77     /* "sprop-init-buf-time = (string) ANY, " */
78     /* "sprop-max-don-diff = (string) ANY, " */
79     /* "max-rcmd-nalu-size = (string) ANY " */
80     );
81
82 GST_BOILERPLATE (GstRtpH264Depay, gst_rtp_h264_depay, GstBaseRTPDepayload,
83     GST_TYPE_BASE_RTP_DEPAYLOAD);
84
85 static void gst_rtp_h264_depay_finalize (GObject * object);
86 static void gst_rtp_h264_depay_set_property (GObject * object, guint prop_id,
87     const GValue * value, GParamSpec * pspec);
88 static void gst_rtp_h264_depay_get_property (GObject * object, guint prop_id,
89     GValue * value, GParamSpec * pspec);
90
91 static GstStateChangeReturn gst_rtp_h264_depay_change_state (GstElement *
92     element, GstStateChange transition);
93
94 static GstBuffer *gst_rtp_h264_depay_process (GstBaseRTPDepayload * depayload,
95     GstBuffer * buf);
96 static gboolean gst_rtp_h264_depay_setcaps (GstBaseRTPDepayload * filter,
97     GstCaps * caps);
98
99 static void
100 gst_rtp_h264_depay_base_init (gpointer klass)
101 {
102   GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
103
104   gst_element_class_add_pad_template (element_class,
105       gst_static_pad_template_get (&gst_rtp_h264_depay_src_template));
106   gst_element_class_add_pad_template (element_class,
107       gst_static_pad_template_get (&gst_rtp_h264_depay_sink_template));
108
109   gst_element_class_set_details_simple (element_class, "RTP H264 depayloader",
110       "Codec/Depayloader/Network/RTP",
111       "Extracts H264 video from RTP packets (RFC 3984)",
112       "Wim Taymans <wim.taymans@gmail.com>");
113 }
114
115 static void
116 gst_rtp_h264_depay_class_init (GstRtpH264DepayClass * klass)
117 {
118   GObjectClass *gobject_class;
119   GstElementClass *gstelement_class;
120   GstBaseRTPDepayloadClass *gstbasertpdepayload_class;
121
122   gobject_class = (GObjectClass *) klass;
123   gstelement_class = (GstElementClass *) klass;
124   gstbasertpdepayload_class = (GstBaseRTPDepayloadClass *) klass;
125
126   gobject_class->finalize = gst_rtp_h264_depay_finalize;
127
128   gobject_class->set_property = gst_rtp_h264_depay_set_property;
129   gobject_class->get_property = gst_rtp_h264_depay_get_property;
130
131   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_BYTE_STREAM,
132       g_param_spec_boolean ("byte-stream", "Byte Stream",
133           "Generate byte stream format of NALU (deprecated; use caps)",
134           DEFAULT_BYTE_STREAM, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
135   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_ACCESS_UNIT,
136       g_param_spec_boolean ("access-unit", "Access Unit",
137           "Merge NALU into AU (picture) (deprecated; use caps)",
138           DEFAULT_ACCESS_UNIT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
139
140   gstelement_class->change_state = gst_rtp_h264_depay_change_state;
141
142   gstbasertpdepayload_class->process = gst_rtp_h264_depay_process;
143   gstbasertpdepayload_class->set_caps = gst_rtp_h264_depay_setcaps;
144
145   GST_DEBUG_CATEGORY_INIT (rtph264depay_debug, "rtph264depay", 0,
146       "H264 Video RTP Depayloader");
147 }
148
149 static void
150 gst_rtp_h264_depay_init (GstRtpH264Depay * rtph264depay,
151     GstRtpH264DepayClass * klass)
152 {
153   rtph264depay->adapter = gst_adapter_new ();
154   rtph264depay->picture_adapter = gst_adapter_new ();
155   rtph264depay->byte_stream = DEFAULT_BYTE_STREAM;
156   rtph264depay->merge = DEFAULT_ACCESS_UNIT;
157 }
158
159 static void
160 gst_rtp_h264_depay_finalize (GObject * object)
161 {
162   GstRtpH264Depay *rtph264depay;
163
164   rtph264depay = GST_RTP_H264_DEPAY (object);
165
166   if (rtph264depay->codec_data)
167     gst_buffer_unref (rtph264depay->codec_data);
168
169   g_object_unref (rtph264depay->adapter);
170   g_object_unref (rtph264depay->picture_adapter);
171
172   G_OBJECT_CLASS (parent_class)->finalize (object);
173 }
174
175 static void
176 gst_rtp_h264_depay_set_property (GObject * object, guint prop_id,
177     const GValue * value, GParamSpec * pspec)
178 {
179   GstRtpH264Depay *rtph264depay;
180
181   rtph264depay = GST_RTP_H264_DEPAY (object);
182
183   switch (prop_id) {
184     case PROP_BYTE_STREAM:
185       rtph264depay->byte_stream = g_value_get_boolean (value);
186       break;
187     case PROP_ACCESS_UNIT:
188       rtph264depay->merge = g_value_get_boolean (value);
189       break;
190     default:
191       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
192       break;
193   }
194 }
195
196 static void
197 gst_rtp_h264_depay_get_property (GObject * object, guint prop_id,
198     GValue * value, GParamSpec * pspec)
199 {
200   GstRtpH264Depay *rtph264depay;
201
202   rtph264depay = GST_RTP_H264_DEPAY (object);
203
204   switch (prop_id) {
205     case PROP_BYTE_STREAM:
206       g_value_set_boolean (value, rtph264depay->byte_stream);
207       break;
208     case PROP_ACCESS_UNIT:
209       g_value_set_boolean (value, rtph264depay->merge);
210       break;
211     default:
212       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
213       break;
214   }
215 }
216
217 static void
218 gst_rtp_h264_depay_negotiate (GstRtpH264Depay * rtph264depay)
219 {
220   GstCaps *caps;
221   gint byte_stream = -1;
222   gint merge = -1;
223
224   caps =
225       gst_pad_get_allowed_caps (GST_BASE_RTP_DEPAYLOAD_SRCPAD (rtph264depay));
226
227   GST_DEBUG_OBJECT (rtph264depay, "allowed caps: %" GST_PTR_FORMAT, caps);
228
229   if (caps) {
230     if (gst_caps_get_size (caps) > 0) {
231       GstStructure *s = gst_caps_get_structure (caps, 0);
232       const gchar *str = NULL;
233
234       if ((str = gst_structure_get_string (s, "stream-format"))) {
235         if (strcmp (str, "avc") == 0) {
236           byte_stream = FALSE;
237         } else if (strcmp (str, "byte-stream") == 0) {
238           byte_stream = TRUE;
239         } else {
240           GST_DEBUG_OBJECT (rtph264depay, "unknown stream-format: %s", str);
241         }
242       }
243
244       if ((str = gst_structure_get_string (s, "alignment"))) {
245         if (strcmp (str, "au") == 0) {
246           merge = TRUE;
247         } else if (strcmp (str, "nal") == 0) {
248           merge = FALSE;
249         } else {
250           GST_DEBUG_OBJECT (rtph264depay, "unknown alignment: %s", str);
251         }
252       }
253     }
254     gst_caps_unref (caps);
255   }
256
257   if (byte_stream >= 0) {
258     GST_DEBUG_OBJECT (rtph264depay, "downstream requires byte-stream %d",
259         byte_stream);
260     if (rtph264depay->byte_stream != byte_stream) {
261       GST_WARNING_OBJECT (rtph264depay,
262           "overriding property setting based on caps");
263       rtph264depay->byte_stream = byte_stream;
264     }
265   }
266   if (merge >= 0) {
267     GST_DEBUG_OBJECT (rtph264depay, "downstream requires merge %d", merge);
268     if (rtph264depay->merge != merge) {
269       GST_WARNING_OBJECT (rtph264depay,
270           "overriding property setting based on caps");
271       rtph264depay->merge = merge;
272     }
273   }
274 }
275
276 static gboolean
277 gst_rtp_h264_depay_setcaps (GstBaseRTPDepayload * depayload, GstCaps * caps)
278 {
279   GstCaps *srccaps;
280   gint clock_rate;
281   GstStructure *structure = gst_caps_get_structure (caps, 0);
282   GstRtpH264Depay *rtph264depay;
283   const gchar *ps, *profile;
284   GstBuffer *codec_data;
285   guint8 *b64;
286   gboolean res;
287
288   rtph264depay = GST_RTP_H264_DEPAY (depayload);
289
290   if (!gst_structure_get_int (structure, "clock-rate", &clock_rate))
291     clock_rate = 90000;
292   depayload->clock_rate = clock_rate;
293
294   srccaps = gst_caps_new_simple ("video/x-h264", NULL);
295
296   /* Base64 encoded, comma separated config NALs */
297   ps = gst_structure_get_string (structure, "sprop-parameter-sets");
298   /* hex: AVCProfileIndication:8 | profile_compat:8 | AVCLevelIndication:8 */
299   profile = gst_structure_get_string (structure, "profile-level-id");
300
301   /* negotiate with downstream w.r.t. output format and alignment */
302   gst_rtp_h264_depay_negotiate (rtph264depay);
303
304   if (rtph264depay->byte_stream && ps != NULL) {
305     /* for bytestream we only need the parameter sets but we don't error out
306      * when they are not there, we assume they are in the stream. */
307     gchar **params;
308     guint len, total;
309     gint i;
310
311     params = g_strsplit (ps, ",", 0);
312
313     /* count total number of bytes in base64. Also include the sync bytes in
314      * front of the params. */
315     len = 0;
316     for (i = 0; params[i]; i++) {
317       len += strlen (params[i]);
318       len += sizeof (sync_bytes);
319     }
320     /* we seriously overshoot the length, but it's fine. */
321     codec_data = gst_buffer_new_and_alloc (len);
322     b64 = GST_BUFFER_DATA (codec_data);
323     total = 0;
324     for (i = 0; params[i]; i++) {
325       guint save = 0;
326       gint state = 0;
327
328       GST_DEBUG_OBJECT (depayload, "decoding param %d (%s)", i, params[i]);
329       memcpy (b64, sync_bytes, sizeof (sync_bytes));
330       b64 += sizeof (sync_bytes);
331       len =
332           g_base64_decode_step (params[i], strlen (params[i]), b64, &state,
333           &save);
334       GST_DEBUG_OBJECT (depayload, "decoded %d bytes", len);
335       total += len + sizeof (sync_bytes);
336       b64 += len;
337     }
338     GST_BUFFER_SIZE (codec_data) = total;
339     g_strfreev (params);
340
341     /* keep the codec_data, we need to send it as the first buffer. We cannot
342      * push it in the adapter because the adapter might be flushed on discont.
343      */
344     if (rtph264depay->codec_data)
345       gst_buffer_unref (rtph264depay->codec_data);
346     rtph264depay->codec_data = codec_data;
347   } else if (!rtph264depay->byte_stream) {
348     gchar **params;
349     guint8 **sps, **pps;
350     guint len, num_sps, num_pps;
351     gint i;
352     guint8 *data;
353
354     if (ps == NULL)
355       goto incomplete_caps;
356
357     params = g_strsplit (ps, ",", 0);
358     len = g_strv_length (params);
359
360     GST_DEBUG_OBJECT (depayload, "we have %d params", len);
361
362     sps = g_new0 (guint8 *, len + 1);
363     pps = g_new0 (guint8 *, len + 1);
364     num_sps = num_pps = 0;
365
366     /* start with 7 bytes header */
367     len = 7;
368     for (i = 0; params[i]; i++) {
369       gsize nal_len;
370       guint8 *nalp;
371       guint save = 0;
372       gint state = 0;
373
374       nal_len = strlen (params[i]);
375       nalp = g_malloc (nal_len + 2);
376
377       nal_len =
378           g_base64_decode_step (params[i], nal_len, nalp + 2, &state, &save);
379       nalp[0] = (nal_len >> 8) & 0xff;
380       nalp[1] = nal_len & 0xff;
381       len += nal_len + 2;
382
383       /* copy to the right list */
384       if ((nalp[2] & 0x1f) == 7) {
385         GST_DEBUG_OBJECT (depayload, "adding param %d as SPS %d", i, num_sps);
386         sps[num_sps++] = nalp;
387       } else {
388         GST_DEBUG_OBJECT (depayload, "adding param %d as PPS %d", i, num_pps);
389         pps[num_pps++] = nalp;
390       }
391     }
392     g_strfreev (params);
393
394     if (num_sps == 0 || (GST_READ_UINT16_BE (sps[0]) < 3) || num_pps == 0) {
395       g_strfreev ((gchar **) pps);
396       g_strfreev ((gchar **) sps);
397       goto incomplete_caps;
398     }
399
400     codec_data = gst_buffer_new_and_alloc (len);
401     data = GST_BUFFER_DATA (codec_data);
402
403     /* 8 bits version == 1 */
404     *data++ = 1;
405     if (profile) {
406       guint32 profile_id;
407
408       /* hex: AVCProfileIndication:8 | profile_compat:8 | AVCLevelIndication:8 */
409       sscanf (profile, "%6x", &profile_id);
410       *data++ = (profile_id >> 16) & 0xff;
411       *data++ = (profile_id >> 8) & 0xff;
412       *data++ = profile_id & 0xff;
413     } else {
414       /* extract from SPS */
415       *data++ = sps[0][3];
416       *data++ = sps[0][4];
417       *data++ = sps[0][5];
418     }
419     /* 6 bits reserved | 2 bits lengthSizeMinusOn */
420     *data++ = 0xff;
421     /* 3 bits reserved | 5 bits numOfSequenceParameterSets */
422     *data++ = 0xe0 | (num_sps & 0x1f);
423
424     /* copy all SPS */
425     for (i = 0; sps[i]; i++) {
426       len = ((sps[i][0] << 8) | sps[i][1]) + 2;
427       GST_DEBUG_OBJECT (depayload, "copy SPS %d of length %d", i, len);
428       memcpy (data, sps[i], len);
429       g_free (sps[i]);
430       data += len;
431     }
432     g_free (sps);
433     /* 8 bits numOfPictureParameterSets */
434     *data++ = num_pps;
435     /* copy all PPS */
436     for (i = 0; pps[i]; i++) {
437       len = ((pps[i][0] << 8) | pps[i][1]) + 2;
438       GST_DEBUG_OBJECT (depayload, "copy PPS %d of length %d", i, len);
439       memcpy (data, pps[i], len);
440       g_free (pps[i]);
441       data += len;
442     }
443     g_free (pps);
444     GST_BUFFER_SIZE (codec_data) = data - GST_BUFFER_DATA (codec_data);
445
446     gst_caps_set_simple (srccaps,
447         "codec_data", GST_TYPE_BUFFER, codec_data, NULL);
448     gst_buffer_unref (codec_data);
449   }
450
451   gst_caps_set_simple (srccaps, "stream-format", G_TYPE_STRING,
452       rtph264depay->byte_stream ? "byte-stream" : "avc",
453       "alignment", G_TYPE_STRING, rtph264depay->merge ? "au" : "nal", NULL);
454
455   res = gst_pad_set_caps (depayload->srcpad, srccaps);
456   gst_caps_unref (srccaps);
457
458   return res;
459
460   /* ERRORS */
461 incomplete_caps:
462   {
463     GST_DEBUG_OBJECT (depayload, "we have incomplete caps");
464     gst_caps_unref (srccaps);
465     return FALSE;
466   }
467 }
468
469 /* SPS/PPS/IDR considered key, all others DELTA;
470  * so downstream waiting for keyframe can pick up at SPS/PPS/IDR */
471 #define NAL_TYPE_IS_KEY(nt) (((nt) == 5) || ((nt) == 7) || ((nt) == 8))
472
473 static gboolean
474 gst_rtp_h264_depay_handle_nal (GstRtpH264Depay * rtph264depay, GstBuffer * nal,
475     GstClockTime in_timestamp)
476 {
477   GstBaseRTPDepayload *depayload = GST_BASE_RTP_DEPAYLOAD (rtph264depay);
478   gint nal_type;
479   guint size;
480   guint8 *data;
481   GstBuffer *outbuf = NULL;
482   GstClockTime out_timestamp;
483   gboolean keyframe, out_keyframe;
484
485   size = GST_BUFFER_SIZE (nal);
486   if (G_UNLIKELY (size < 5))
487     goto short_nal;
488
489   data = GST_BUFFER_DATA (nal);
490
491   nal_type = data[4] & 0x1f;
492   GST_DEBUG_OBJECT (rtph264depay, "handle NAL type %d", nal_type);
493
494   keyframe = NAL_TYPE_IS_KEY (nal_type);
495
496   out_keyframe = keyframe;
497   out_timestamp = in_timestamp;
498
499   if (rtph264depay->merge) {
500     gboolean start = FALSE, complete = FALSE;
501
502     /* consider a coded slices (IDR or not) to start a picture,
503      * (so ending the previous one) if first_mb_in_slice == 0
504      * (non-0 is part of previous one) */
505     /* NOTE this is not entirely according to Access Unit specs in 7.4.1.2.4,
506      * but in practice it works in sane cases, needs not much parsing,
507      * and also works with broken frame_num in NAL (where spec-wise would fail) */
508     if (nal_type == 1 || nal_type == 2 || nal_type == 5) {
509       /* we have a picture start */
510       start = TRUE;
511       if (data[5] & 0x80) {
512         /* first_mb_in_slice == 0 completes a picture */
513         complete = TRUE;
514       }
515     } else if (nal_type >= 6 && nal_type <= 9) {
516       /* SEI, SPS, PPS, AU terminate picture */
517       complete = TRUE;
518     }
519     GST_DEBUG_OBJECT (depayload, "start %d, complete %d", start, complete);
520
521     if (complete && rtph264depay->picture_start) {
522       guint outsize;
523
524       /* we had a picture in the adapter and we completed it */
525       GST_DEBUG_OBJECT (depayload, "taking completed AU");
526       outsize = gst_adapter_available (rtph264depay->picture_adapter);
527       outbuf = gst_adapter_take_buffer (rtph264depay->picture_adapter, outsize);
528
529       out_timestamp = rtph264depay->last_ts;
530       out_keyframe = rtph264depay->last_keyframe;
531
532       rtph264depay->last_keyframe = FALSE;
533       rtph264depay->picture_start = FALSE;
534     }
535
536     /* add to adapter */
537     GST_DEBUG_OBJECT (depayload, "adding NAL to picture adapter");
538     gst_adapter_push (rtph264depay->picture_adapter, nal);
539     rtph264depay->last_ts = in_timestamp;
540     rtph264depay->last_keyframe |= keyframe;
541     rtph264depay->picture_start |= start;
542   } else {
543     /* no merge, output is input nal */
544     GST_DEBUG_OBJECT (depayload, "using NAL as output");
545     outbuf = nal;
546   }
547
548   if (outbuf) {
549     /* prepend codec_data */
550     if (rtph264depay->codec_data) {
551       GST_DEBUG_OBJECT (depayload, "prepending codec_data");
552       outbuf = gst_buffer_join (rtph264depay->codec_data, outbuf);
553       rtph264depay->codec_data = NULL;
554       out_keyframe = TRUE;
555     }
556     outbuf = gst_buffer_make_metadata_writable (outbuf);
557
558     GST_BUFFER_TIMESTAMP (outbuf) = out_timestamp;
559
560     if (out_keyframe)
561       GST_BUFFER_FLAG_UNSET (outbuf, GST_BUFFER_FLAG_DELTA_UNIT);
562     else
563       GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DELTA_UNIT);
564
565     gst_buffer_set_caps (outbuf, GST_PAD_CAPS (depayload->srcpad));
566
567     gst_base_rtp_depayload_push (depayload, outbuf);
568   }
569
570   return TRUE;
571
572   /* ERRORS */
573 short_nal:
574   {
575     GST_WARNING_OBJECT (depayload, "dropping short NAL");
576     gst_buffer_unref (nal);
577     return FALSE;
578   }
579 }
580
581 static GstBuffer *
582 gst_rtp_h264_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf)
583 {
584   GstRtpH264Depay *rtph264depay;
585   GstBuffer *outbuf;
586   guint8 nal_unit_type;
587
588   rtph264depay = GST_RTP_H264_DEPAY (depayload);
589
590   /* flush remaining data on discont */
591   if (GST_BUFFER_IS_DISCONT (buf)) {
592     gst_adapter_clear (rtph264depay->adapter);
593     rtph264depay->wait_start = TRUE;
594   }
595
596   {
597     gint payload_len;
598     guint8 *payload;
599     guint header_len;
600     guint8 nal_ref_idc;
601     guint8 *outdata;
602     guint outsize, nalu_size;
603     GstClockTime timestamp;
604
605     timestamp = GST_BUFFER_TIMESTAMP (buf);
606
607     payload_len = gst_rtp_buffer_get_payload_len (buf);
608     payload = gst_rtp_buffer_get_payload (buf);
609
610     GST_DEBUG_OBJECT (rtph264depay, "receiving %d bytes", payload_len);
611
612     if (payload_len == 0)
613       return NULL;
614
615     /* +---------------+
616      * |0|1|2|3|4|5|6|7|
617      * +-+-+-+-+-+-+-+-+
618      * |F|NRI|  Type   |
619      * +---------------+
620      *
621      * F must be 0.
622      */
623     nal_ref_idc = (payload[0] & 0x60) >> 5;
624     nal_unit_type = payload[0] & 0x1f;
625
626     /* at least one byte header with type */
627     header_len = 1;
628
629     GST_DEBUG_OBJECT (rtph264depay, "NRI %d, Type %d", nal_ref_idc,
630         nal_unit_type);
631
632     switch (nal_unit_type) {
633       case 0:
634       case 30:
635       case 31:
636         /* undefined */
637         goto undefined_type;
638       case 25:
639         /* STAP-B    Single-time aggregation packet     5.7.1 */
640         /* 2 byte extra header for DON */
641         header_len += 2;
642         /* fallthrough */
643       case 24:
644       {
645         /* strip headers */
646         payload += header_len;
647         payload_len -= header_len;
648
649         rtph264depay->wait_start = FALSE;
650
651
652         /* STAP-A    Single-time aggregation packet     5.7.1 */
653         while (payload_len > 2) {
654           /*                      1          
655            *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 
656            * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
657            * |         NALU Size             |
658            * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
659            */
660           nalu_size = (payload[0] << 8) | payload[1];
661
662           if (nalu_size > payload_len)
663             nalu_size = payload_len;
664
665           outsize = nalu_size + sizeof (sync_bytes);
666           outbuf = gst_buffer_new_and_alloc (outsize);
667           outdata = GST_BUFFER_DATA (outbuf);
668           if (rtph264depay->byte_stream) {
669             memcpy (outdata, sync_bytes, sizeof (sync_bytes));
670           } else {
671             outdata[0] = outdata[1] = 0;
672             outdata[2] = payload[0];
673             outdata[3] = payload[1];
674           }
675
676           /* strip NALU size */
677           payload += 2;
678           payload_len -= 2;
679
680           outdata += sizeof (sync_bytes);
681           memcpy (outdata, payload, nalu_size);
682
683           gst_adapter_push (rtph264depay->adapter, outbuf);
684
685           payload += nalu_size;
686           payload_len -= nalu_size;
687         }
688
689         outsize = gst_adapter_available (rtph264depay->adapter);
690         outbuf = gst_adapter_take_buffer (rtph264depay->adapter, outsize);
691
692         gst_rtp_h264_depay_handle_nal (rtph264depay, outbuf, timestamp);
693         break;
694       }
695       case 26:
696         /* MTAP16    Multi-time aggregation packet      5.7.2 */
697         header_len = 5;
698         /* fallthrough, not implemented */
699       case 27:
700         /* MTAP24    Multi-time aggregation packet      5.7.2 */
701         header_len = 6;
702         goto not_implemented;
703         break;
704       case 28:
705       case 29:
706       {
707         /* FU-A      Fragmentation unit                 5.8 */
708         /* FU-B      Fragmentation unit                 5.8 */
709         gboolean S, E;
710
711         /* +---------------+
712          * |0|1|2|3|4|5|6|7|
713          * +-+-+-+-+-+-+-+-+
714          * |S|E|R|  Type   |
715          * +---------------+
716          *
717          * R is reserved and always 0
718          */
719         S = (payload[1] & 0x80) == 0x80;
720         E = (payload[1] & 0x40) == 0x40;
721
722         GST_DEBUG_OBJECT (rtph264depay, "S %d, E %d", S, E);
723
724         if (rtph264depay->wait_start && !S)
725           goto waiting_start;
726
727         if (S) {
728           /* NAL unit starts here */
729           guint8 nal_header;
730
731           rtph264depay->wait_start = FALSE;
732
733           /* reconstruct NAL header */
734           nal_header = (payload[0] & 0xe0) | (payload[1] & 0x1f);
735
736           /* strip type header, keep FU header, we'll reuse it to reconstruct
737            * the NAL header. */
738           payload += 1;
739           payload_len -= 1;
740
741           nalu_size = payload_len;
742           outsize = nalu_size + sizeof (sync_bytes);
743           outbuf = gst_buffer_new_and_alloc (outsize);
744           outdata = GST_BUFFER_DATA (outbuf);
745           outdata += sizeof (sync_bytes);
746           memcpy (outdata, payload, nalu_size);
747           outdata[0] = nal_header;
748
749           GST_DEBUG_OBJECT (rtph264depay, "queueing %d bytes", outsize);
750
751           /* and assemble in the adapter */
752           gst_adapter_push (rtph264depay->adapter, outbuf);
753         } else {
754           /* strip off FU indicator and FU header bytes */
755           payload += 2;
756           payload_len -= 2;
757
758           outsize = payload_len;
759           outbuf = gst_buffer_new_and_alloc (outsize);
760           outdata = GST_BUFFER_DATA (outbuf);
761           memcpy (outdata, payload, outsize);
762
763           GST_DEBUG_OBJECT (rtph264depay, "queueing %d bytes", outsize);
764
765           /* and assemble in the adapter */
766           gst_adapter_push (rtph264depay->adapter, outbuf);
767         }
768
769         /* if NAL unit ends, flush the adapter */
770         if (E) {
771           GST_DEBUG_OBJECT (rtph264depay, "output %d bytes", outsize);
772
773           outsize = gst_adapter_available (rtph264depay->adapter);
774           outbuf = gst_adapter_take_buffer (rtph264depay->adapter, outsize);
775           outdata = GST_BUFFER_DATA (outbuf);
776
777           if (rtph264depay->byte_stream) {
778             memcpy (outdata, sync_bytes, sizeof (sync_bytes));
779           } else {
780             outsize -= 4;
781             outdata[0] = (outsize >> 24);
782             outdata[1] = (outsize >> 16);
783             outdata[2] = (outsize >> 8);
784             outdata[3] = (outsize);
785           }
786           gst_rtp_h264_depay_handle_nal (rtph264depay, outbuf, timestamp);
787         }
788         break;
789       }
790       default:
791       {
792         rtph264depay->wait_start = FALSE;
793
794         /* 1-23   NAL unit  Single NAL unit packet per H.264   5.6 */
795         /* the entire payload is the output buffer */
796         nalu_size = payload_len;
797         outsize = nalu_size + sizeof (sync_bytes);
798         outbuf = gst_buffer_new_and_alloc (outsize);
799         outdata = GST_BUFFER_DATA (outbuf);
800         if (rtph264depay->byte_stream) {
801           memcpy (outdata, sync_bytes, sizeof (sync_bytes));
802         } else {
803           outdata[0] = outdata[1] = 0;
804           outdata[2] = nalu_size >> 8;
805           outdata[3] = nalu_size & 0xff;
806         }
807         outdata += sizeof (sync_bytes);
808         memcpy (outdata, payload, nalu_size);
809
810         gst_rtp_h264_depay_handle_nal (rtph264depay, outbuf, timestamp);
811         break;
812       }
813     }
814   }
815
816   return NULL;
817
818   /* ERRORS */
819 undefined_type:
820   {
821     GST_ELEMENT_WARNING (rtph264depay, STREAM, DECODE,
822         (NULL), ("Undefined packet type"));
823     return NULL;
824   }
825 waiting_start:
826   {
827     GST_DEBUG_OBJECT (rtph264depay, "waiting for start");
828     return NULL;
829   }
830 not_implemented:
831   {
832     GST_ELEMENT_ERROR (rtph264depay, STREAM, FORMAT,
833         (NULL), ("NAL unit type %d not supported yet", nal_unit_type));
834     return NULL;
835   }
836 }
837
838 static GstStateChangeReturn
839 gst_rtp_h264_depay_change_state (GstElement * element,
840     GstStateChange transition)
841 {
842   GstRtpH264Depay *rtph264depay;
843   GstStateChangeReturn ret;
844
845   rtph264depay = GST_RTP_H264_DEPAY (element);
846
847   switch (transition) {
848     case GST_STATE_CHANGE_NULL_TO_READY:
849       break;
850     case GST_STATE_CHANGE_READY_TO_PAUSED:
851       gst_adapter_clear (rtph264depay->adapter);
852       rtph264depay->wait_start = TRUE;
853       gst_adapter_clear (rtph264depay->picture_adapter);
854       rtph264depay->picture_start = FALSE;
855       rtph264depay->last_keyframe = FALSE;
856       break;
857     default:
858       break;
859   }
860
861   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
862
863   switch (transition) {
864     case GST_STATE_CHANGE_READY_TO_NULL:
865       break;
866     default:
867       break;
868   }
869   return ret;
870 }
871
872 gboolean
873 gst_rtp_h264_depay_plugin_init (GstPlugin * plugin)
874 {
875   return gst_element_register (plugin, "rtph264depay",
876       GST_RANK_SECONDARY, GST_TYPE_RTP_H264_DEPAY);
877 }