Merge branch 'master' into 0.11
[platform/upstream/gstreamer.git] / gst / rtp / gstrtph264pay.c
1 /* ex: set tabstop=2 shiftwidth=2 expandtab: */
2 /* GStreamer
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 <string.h>
25 #include <stdlib.h>
26
27 #include <gst/rtp/gstrtpbuffer.h>
28 #include <gst/pbutils/pbutils.h>
29
30 #include "gstrtph264pay.h"
31
32
33 #define IDR_TYPE_ID  5
34 #define SPS_TYPE_ID  7
35 #define PPS_TYPE_ID  8
36 #define USE_MEMCMP
37
38
39 GST_DEBUG_CATEGORY_STATIC (rtph264pay_debug);
40 #define GST_CAT_DEFAULT (rtph264pay_debug)
41
42 /* references:
43  *
44  * RFC 3984
45  */
46
47 static GstStaticPadTemplate gst_rtp_h264_pay_sink_template =
48     GST_STATIC_PAD_TEMPLATE ("sink",
49     GST_PAD_SINK,
50     GST_PAD_ALWAYS,
51     GST_STATIC_CAPS ("video/x-h264, "
52         "stream-format = (string) byte-stream, alignment = (string) { nal, au };"
53         "video/x-h264, "
54         "stream-format = (string) avc, alignment = (string) au")
55     );
56
57 static GstStaticPadTemplate gst_rtp_h264_pay_src_template =
58 GST_STATIC_PAD_TEMPLATE ("src",
59     GST_PAD_SRC,
60     GST_PAD_ALWAYS,
61     GST_STATIC_CAPS ("application/x-rtp, "
62         "media = (string) \"video\", "
63         "payload = (int) " GST_RTP_PAYLOAD_DYNAMIC_STRING ", "
64         "clock-rate = (int) 90000, " "encoding-name = (string) \"H264\"")
65     );
66
67 #define GST_TYPE_H264_SCAN_MODE (gst_h264_scan_mode_get_type())
68 static GType
69 gst_h264_scan_mode_get_type (void)
70 {
71   static GType h264_scan_mode_type = 0;
72   static const GEnumValue h264_scan_modes[] = {
73     {GST_H264_SCAN_MODE_BYTESTREAM,
74           "Scan complete bytestream for NALUs",
75         "bytestream"},
76     {GST_H264_SCAN_MODE_MULTI_NAL, "Buffers contain multiple complete NALUs",
77         "multiple"},
78     {GST_H264_SCAN_MODE_SINGLE_NAL, "Buffers contain a single complete NALU",
79         "single"},
80     {0, NULL, NULL},
81   };
82
83   if (!h264_scan_mode_type) {
84     h264_scan_mode_type =
85         g_enum_register_static ("GstH264PayScanMode", h264_scan_modes);
86   }
87   return h264_scan_mode_type;
88 }
89
90 #define DEFAULT_PROFILE_LEVEL_ID        NULL
91 #define DEFAULT_SPROP_PARAMETER_SETS    NULL
92 #define DEFAULT_SCAN_MODE               GST_H264_SCAN_MODE_MULTI_NAL
93 #define DEFAULT_BUFFER_LIST             FALSE
94 #define DEFAULT_CONFIG_INTERVAL               0
95
96 enum
97 {
98   PROP_0,
99   PROP_PROFILE_LEVEL_ID,
100   PROP_SPROP_PARAMETER_SETS,
101   PROP_SCAN_MODE,
102   PROP_BUFFER_LIST,
103   PROP_CONFIG_INTERVAL,
104   PROP_LAST
105 };
106
107 #define IS_ACCESS_UNIT(x) (((x) > 0x00) && ((x) < 0x06))
108
109 static void gst_rtp_h264_pay_finalize (GObject * object);
110
111 static void gst_rtp_h264_pay_set_property (GObject * object, guint prop_id,
112     const GValue * value, GParamSpec * pspec);
113 static void gst_rtp_h264_pay_get_property (GObject * object, guint prop_id,
114     GValue * value, GParamSpec * pspec);
115
116 static GstCaps *gst_rtp_h264_pay_getcaps (GstRTPBasePayload * payload,
117     GstPad * pad, GstCaps * filter);
118 static gboolean gst_rtp_h264_pay_setcaps (GstRTPBasePayload * basepayload,
119     GstCaps * caps);
120 static GstFlowReturn gst_rtp_h264_pay_handle_buffer (GstRTPBasePayload * pad,
121     GstBuffer * buffer);
122 static gboolean gst_rtp_h264_pay_sink_event (GstRTPBasePayload * payload,
123     GstEvent * event);
124 static GstStateChangeReturn gst_rtp_h264_pay_change_state (GstElement *
125     element, GstStateChange transition);
126
127 #define gst_rtp_h264_pay_parent_class parent_class
128 G_DEFINE_TYPE (GstRtpH264Pay, gst_rtp_h264_pay, GST_TYPE_RTP_BASE_PAYLOAD);
129
130 static void
131 gst_rtp_h264_pay_class_init (GstRtpH264PayClass * klass)
132 {
133   GObjectClass *gobject_class;
134   GstElementClass *gstelement_class;
135   GstRTPBasePayloadClass *gstrtpbasepayload_class;
136
137   gobject_class = (GObjectClass *) klass;
138   gstelement_class = (GstElementClass *) klass;
139   gstrtpbasepayload_class = (GstRTPBasePayloadClass *) klass;
140
141   gobject_class->set_property = gst_rtp_h264_pay_set_property;
142   gobject_class->get_property = gst_rtp_h264_pay_get_property;
143
144   g_object_class_install_property (G_OBJECT_CLASS (klass),
145       PROP_PROFILE_LEVEL_ID, g_param_spec_string ("profile-level-id",
146           "profile-level-id",
147           "The base64 profile-level-id to set in the sink caps (deprecated)",
148           DEFAULT_PROFILE_LEVEL_ID,
149           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
150
151   g_object_class_install_property (G_OBJECT_CLASS (klass),
152       PROP_SPROP_PARAMETER_SETS, g_param_spec_string ("sprop-parameter-sets",
153           "sprop-parameter-sets",
154           "The base64 sprop-parameter-sets to set in out caps (set to NULL to "
155           "extract from stream)",
156           DEFAULT_SPROP_PARAMETER_SETS,
157           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
158
159   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SCAN_MODE,
160       g_param_spec_enum ("scan-mode", "Scan Mode",
161           "How to scan the input buffers for NAL units. Performance can be "
162           "increased when certain assumptions are made about the input buffers",
163           GST_TYPE_H264_SCAN_MODE, DEFAULT_SCAN_MODE,
164           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
165
166   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_BUFFER_LIST,
167       g_param_spec_boolean ("buffer-list", "Buffer List",
168           "Use Buffer Lists",
169           DEFAULT_BUFFER_LIST, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
170
171   g_object_class_install_property (G_OBJECT_CLASS (klass),
172       PROP_CONFIG_INTERVAL,
173       g_param_spec_uint ("config-interval",
174           "SPS PPS Send Interval",
175           "Send SPS and PPS Insertion Interval in seconds (sprop parameter sets "
176           "will be multiplexed in the data stream when detected.) (0 = disabled)",
177           0, 3600, DEFAULT_CONFIG_INTERVAL,
178           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)
179       );
180
181   gobject_class->finalize = gst_rtp_h264_pay_finalize;
182
183   gst_element_class_add_pad_template (gstelement_class,
184       gst_static_pad_template_get (&gst_rtp_h264_pay_src_template));
185   gst_element_class_add_pad_template (gstelement_class,
186       gst_static_pad_template_get (&gst_rtp_h264_pay_sink_template));
187
188   gst_element_class_set_details_simple (gstelement_class, "RTP H264 payloader",
189       "Codec/Payloader/Network/RTP",
190       "Payload-encode H264 video into RTP packets (RFC 3984)",
191       "Laurent Glayal <spglegle@yahoo.fr>");
192
193   gstelement_class->change_state =
194       GST_DEBUG_FUNCPTR (gst_rtp_h264_pay_change_state);
195
196   gstrtpbasepayload_class->get_caps = gst_rtp_h264_pay_getcaps;
197   gstrtpbasepayload_class->set_caps = gst_rtp_h264_pay_setcaps;
198   gstrtpbasepayload_class->handle_buffer = gst_rtp_h264_pay_handle_buffer;
199   gstrtpbasepayload_class->sink_event = gst_rtp_h264_pay_sink_event;
200
201   GST_DEBUG_CATEGORY_INIT (rtph264pay_debug, "rtph264pay", 0,
202       "H264 RTP Payloader");
203 }
204
205 static void
206 gst_rtp_h264_pay_init (GstRtpH264Pay * rtph264pay)
207 {
208   rtph264pay->queue = g_array_new (FALSE, FALSE, sizeof (guint));
209   rtph264pay->profile = 0;
210   rtph264pay->sps = NULL;
211   rtph264pay->pps = NULL;
212   rtph264pay->last_spspps = -1;
213   rtph264pay->scan_mode = GST_H264_SCAN_MODE_MULTI_NAL;
214   rtph264pay->buffer_list = DEFAULT_BUFFER_LIST;
215   rtph264pay->spspps_interval = DEFAULT_CONFIG_INTERVAL;
216
217   rtph264pay->adapter = gst_adapter_new ();
218 }
219
220 static void
221 gst_rtp_h264_pay_clear_sps_pps (GstRtpH264Pay * rtph264pay)
222 {
223   g_list_foreach (rtph264pay->sps, (GFunc) gst_mini_object_unref, NULL);
224   g_list_free (rtph264pay->sps);
225   rtph264pay->sps = NULL;
226   g_list_foreach (rtph264pay->pps, (GFunc) gst_mini_object_unref, NULL);
227   g_list_free (rtph264pay->pps);
228   rtph264pay->pps = NULL;
229 }
230
231 static void
232 gst_rtp_h264_pay_finalize (GObject * object)
233 {
234   GstRtpH264Pay *rtph264pay;
235
236   rtph264pay = GST_RTP_H264_PAY (object);
237
238   g_array_free (rtph264pay->queue, TRUE);
239
240   gst_rtp_h264_pay_clear_sps_pps (rtph264pay);
241
242   g_free (rtph264pay->sprop_parameter_sets);
243
244   g_object_unref (rtph264pay->adapter);
245
246   G_OBJECT_CLASS (parent_class)->finalize (object);
247 }
248
249 static const gchar *all_levels[] = {
250   "1",
251   "1b",
252   "1.1",
253   "1.2",
254   "1.3",
255   "2",
256   "2.1",
257   "2.2",
258   "3",
259   "3.1",
260   "3.2",
261   "4",
262   "4.1",
263   "4.2",
264   "5",
265   "5.1",
266   NULL
267 };
268
269 static GstCaps *
270 gst_rtp_h264_pay_getcaps (GstRTPBasePayload * payload, GstPad * pad,
271     GstCaps * filter)
272 {
273   GstCaps *template_caps;
274   GstCaps *allowed_caps;
275   GstCaps *caps, *icaps;
276   guint i;
277
278   allowed_caps =
279       gst_pad_peer_query_caps (GST_RTP_BASE_PAYLOAD_SRCPAD (payload), filter);
280
281   if (allowed_caps == NULL)
282     return NULL;
283
284   template_caps =
285       gst_static_pad_template_get_caps (&gst_rtp_h264_pay_sink_template);
286
287   if (gst_caps_is_any (allowed_caps)) {
288     caps = gst_caps_ref (template_caps);
289     goto done;
290   }
291
292   if (gst_caps_is_empty (allowed_caps)) {
293     caps = gst_caps_ref (allowed_caps);
294     goto done;
295   }
296
297   caps = gst_caps_new_empty ();
298
299   for (i = 0; i < gst_caps_get_size (allowed_caps); i++) {
300     GstStructure *s = gst_caps_get_structure (allowed_caps, i);
301     GstStructure *new_s = gst_structure_new_empty ("video/x-h264");
302     const gchar *profile_level_id;
303
304     profile_level_id = gst_structure_get_string (s, "profile-level-id");
305
306     if (profile_level_id && strlen (profile_level_id) == 6) {
307       const gchar *profile;
308       const gchar *level;
309       long int spsint;
310       guint8 sps[3];
311
312       spsint = strtol (profile_level_id, NULL, 16);
313       sps[0] = spsint >> 16;
314       sps[1] = spsint >> 8;
315       sps[2] = spsint;
316
317       profile = gst_codec_utils_h264_get_profile (sps, 3);
318       level = gst_codec_utils_h264_get_level (sps, 3);
319
320       if (profile && level) {
321         GST_LOG_OBJECT (payload, "In caps, have profile %s and level %s",
322             profile, level);
323
324         if (!strcmp (profile, "constrained-baseline"))
325           gst_structure_set (new_s, "profile", G_TYPE_STRING, profile, NULL);
326         else {
327           GValue val = { 0, };
328           GValue profiles = { 0, };
329
330           g_value_init (&profiles, GST_TYPE_LIST);
331           g_value_init (&val, G_TYPE_STRING);
332
333           g_value_set_static_string (&val, profile);
334           gst_value_list_append_value (&profiles, &val);
335
336           g_value_set_static_string (&val, "constrained-baseline");
337           gst_value_list_append_value (&profiles, &val);
338
339           gst_structure_take_value (new_s, "profile", &profiles);
340         }
341
342         if (!strcmp (level, "1"))
343           gst_structure_set (new_s, "level", G_TYPE_STRING, level, NULL);
344         else {
345           GValue levels = { 0, };
346           GValue val = { 0, };
347           int j;
348
349           g_value_init (&levels, GST_TYPE_LIST);
350           g_value_init (&val, G_TYPE_STRING);
351
352           for (j = 0; all_levels[j]; j++) {
353             g_value_set_static_string (&val, all_levels[j]);
354             gst_value_list_prepend_value (&levels, &val);
355             if (!strcmp (level, all_levels[j]))
356               break;
357           }
358           gst_structure_take_value (new_s, "level", &levels);
359         }
360       } else {
361         /* Invalid profile-level-id means baseline */
362
363         gst_structure_set (new_s,
364             "profile", G_TYPE_STRING, "constrained-baseline", NULL);
365       }
366     } else {
367       /* No profile-level-id also means baseline */
368
369       gst_structure_set (new_s,
370           "profile", G_TYPE_STRING, "constrained-baseline", NULL);
371     }
372
373     caps = gst_caps_merge_structure (caps, new_s);
374   }
375
376   icaps = gst_caps_intersect (caps, template_caps);
377   gst_caps_unref (caps);
378   caps = icaps;
379
380 done:
381
382   gst_caps_unref (template_caps);
383   gst_caps_unref (allowed_caps);
384
385   GST_LOG_OBJECT (payload, "returning caps %" GST_PTR_FORMAT, caps);
386   return caps;
387 }
388
389 /* take the currently configured SPS and PPS lists and set them on the caps as
390  * sprop-parameter-sets */
391 static gboolean
392 gst_rtp_h264_pay_set_sps_pps (GstRTPBasePayload * basepayload)
393 {
394   GstRtpH264Pay *payloader = GST_RTP_H264_PAY (basepayload);
395   gchar *profile;
396   gchar *set;
397   GList *walk;
398   GString *sprops;
399   guint count;
400   gboolean res;
401   GstMapInfo map;
402
403   sprops = g_string_new ("");
404   count = 0;
405
406   /* build the sprop-parameter-sets */
407   for (walk = payloader->sps; walk; walk = g_list_next (walk)) {
408     GstBuffer *sps_buf = GST_BUFFER_CAST (walk->data);
409
410     gst_buffer_map (sps_buf, &map, GST_MAP_READ);
411     set = g_base64_encode (map.data, map.size);
412     gst_buffer_unmap (sps_buf, &map);
413
414     g_string_append_printf (sprops, "%s%s", count ? "," : "", set);
415     g_free (set);
416     count++;
417   }
418   for (walk = payloader->pps; walk; walk = g_list_next (walk)) {
419     GstBuffer *pps_buf = GST_BUFFER_CAST (walk->data);
420
421     gst_buffer_map (pps_buf, &map, GST_MAP_READ);
422     set = g_base64_encode (map.data, map.size);
423     gst_buffer_unmap (pps_buf, &map);
424
425     g_string_append_printf (sprops, "%s%s", count ? "," : "", set);
426     g_free (set);
427     count++;
428   }
429
430   /* profile is 24 bit. Force it to respect the limit */
431   profile = g_strdup_printf ("%06x", payloader->profile & 0xffffff);
432   /* combine into output caps */
433   res = gst_rtp_base_payload_set_outcaps (basepayload,
434       "sprop-parameter-sets", G_TYPE_STRING, sprops->str, NULL);
435   g_string_free (sprops, TRUE);
436   g_free (profile);
437
438   return res;
439 }
440
441 static gboolean
442 gst_rtp_h264_pay_setcaps (GstRTPBasePayload * basepayload, GstCaps * caps)
443 {
444   GstRtpH264Pay *rtph264pay;
445   GstStructure *str;
446   const GValue *value;
447   GstMapInfo map;
448   guint8 *data;
449   gsize size;
450   GstBuffer *buffer;
451   const gchar *alignment;
452
453   rtph264pay = GST_RTP_H264_PAY (basepayload);
454
455   str = gst_caps_get_structure (caps, 0);
456
457   /* we can only set the output caps when we found the sprops and profile
458    * NALs */
459   gst_rtp_base_payload_set_options (basepayload, "video", TRUE, "H264", 90000);
460
461   alignment = gst_structure_get_string (str, "alignment");
462   if (alignment && !strcmp (alignment, "au"))
463     rtph264pay->au_alignment = TRUE;
464   else
465     rtph264pay->au_alignment = FALSE;
466
467   /* packetized AVC video has a codec_data */
468   if ((value = gst_structure_get_value (str, "codec_data"))) {
469     guint num_sps, num_pps;
470     gint i, nal_size;
471
472     GST_DEBUG_OBJECT (rtph264pay, "have packetized h264");
473     rtph264pay->packetized = TRUE;
474
475     buffer = gst_value_get_buffer (value);
476
477     gst_buffer_map (buffer, &map, GST_MAP_READ);
478     data = map.data;
479     size = map.size;
480
481     /* parse the avcC data */
482     if (size < 7)
483       goto avcc_too_small;
484     /* parse the version, this must be 1 */
485     if (data[0] != 1)
486       goto wrong_version;
487
488     /* AVCProfileIndication */
489     /* profile_compat */
490     /* AVCLevelIndication */
491     rtph264pay->profile = (data[1] << 16) | (data[2] << 8) | data[3];
492     GST_DEBUG_OBJECT (rtph264pay, "profile %06x", rtph264pay->profile);
493
494     /* 6 bits reserved | 2 bits lengthSizeMinusOne */
495     /* this is the number of bytes in front of the NAL units to mark their
496      * length */
497     rtph264pay->nal_length_size = (data[4] & 0x03) + 1;
498     GST_DEBUG_OBJECT (rtph264pay, "nal length %u", rtph264pay->nal_length_size);
499     /* 3 bits reserved | 5 bits numOfSequenceParameterSets */
500     num_sps = data[5] & 0x1f;
501     GST_DEBUG_OBJECT (rtph264pay, "num SPS %u", num_sps);
502
503     data += 6;
504     size -= 6;
505
506     /* create the sprop-parameter-sets */
507     for (i = 0; i < num_sps; i++) {
508       GstBuffer *sps_buf;
509
510       if (size < 2)
511         goto avcc_error;
512
513       nal_size = (data[0] << 8) | data[1];
514       data += 2;
515       size -= 2;
516
517       GST_LOG_OBJECT (rtph264pay, "SPS %d size %d", i, nal_size);
518
519       if (size < nal_size)
520         goto avcc_error;
521
522       /* make a buffer out of it and add to SPS list */
523       sps_buf = gst_buffer_new_and_alloc (nal_size);
524       gst_buffer_fill (sps_buf, 0, data, nal_size);
525       rtph264pay->sps = g_list_append (rtph264pay->sps, sps_buf);
526
527       data += nal_size;
528       size -= nal_size;
529     }
530     if (size < 1)
531       goto avcc_error;
532
533     /* 8 bits numOfPictureParameterSets */
534     num_pps = data[0];
535     data += 1;
536     size -= 1;
537
538     GST_DEBUG_OBJECT (rtph264pay, "num PPS %u", num_pps);
539     for (i = 0; i < num_pps; i++) {
540       GstBuffer *pps_buf;
541
542       if (size < 2)
543         goto avcc_error;
544
545       nal_size = (data[0] << 8) | data[1];
546       data += 2;
547       size -= 2;
548
549       GST_LOG_OBJECT (rtph264pay, "PPS %d size %d", i, nal_size);
550
551       if (size < nal_size)
552         goto avcc_error;
553
554       /* make a buffer out of it and add to PPS list */
555       pps_buf = gst_buffer_new_and_alloc (nal_size);
556       gst_buffer_fill (pps_buf, 0, data, nal_size);
557       rtph264pay->pps = g_list_append (rtph264pay->pps, pps_buf);
558
559       data += nal_size;
560       size -= nal_size;
561     }
562     gst_buffer_unmap (buffer, &map);
563     /* and update the caps with the collected data */
564     if (!gst_rtp_h264_pay_set_sps_pps (basepayload))
565       goto set_sps_pps_failed;
566   } else {
567     GST_DEBUG_OBJECT (rtph264pay, "have bytestream h264");
568     rtph264pay->packetized = FALSE;
569   }
570
571   return TRUE;
572
573 avcc_too_small:
574   {
575     GST_ERROR_OBJECT (rtph264pay, "avcC size %" G_GSIZE_FORMAT " < 7", size);
576     goto error;
577   }
578 wrong_version:
579   {
580     GST_ERROR_OBJECT (rtph264pay, "wrong avcC version");
581     goto error;
582   }
583 avcc_error:
584   {
585     GST_ERROR_OBJECT (rtph264pay, "avcC too small ");
586     goto error;
587   }
588 set_sps_pps_failed:
589   {
590     GST_ERROR_OBJECT (rtph264pay, "failed to set sps/pps");
591     goto error;
592   }
593 error:
594   {
595     gst_buffer_unmap (buffer, &map);
596     return FALSE;
597   }
598 }
599
600 static void
601 gst_rtp_h264_pay_parse_sprop_parameter_sets (GstRtpH264Pay * rtph264pay)
602 {
603   const gchar *ps;
604   gchar **params;
605   guint len, num_sps, num_pps;
606   gint i;
607   GstBuffer *buf;
608
609   ps = rtph264pay->sprop_parameter_sets;
610   if (ps == NULL)
611     return;
612
613   gst_rtp_h264_pay_clear_sps_pps (rtph264pay);
614
615   params = g_strsplit (ps, ",", 0);
616   len = g_strv_length (params);
617
618   GST_DEBUG_OBJECT (rtph264pay, "we have %d params", len);
619
620   num_sps = num_pps = 0;
621
622   for (i = 0; params[i]; i++) {
623     gsize nal_len;
624     GstMapInfo map;
625     guint8 *nalp;
626     guint save = 0;
627     gint state = 0;
628     guint8 nal_type;
629
630     nal_len = strlen (params[i]);
631     buf = gst_buffer_new_and_alloc (nal_len);
632
633     gst_buffer_map (buf, &map, GST_MAP_WRITE);
634     nalp = map.data;
635     nal_len = g_base64_decode_step (params[i], nal_len, nalp, &state, &save);
636     nal_type = nalp[0];
637     gst_buffer_unmap (buf, &map);
638     gst_buffer_resize (buf, 0, nal_len);
639
640     if (!nal_len) {
641       gst_buffer_unref (buf);
642       continue;
643     }
644
645     /* append to the right list */
646     if ((nal_type & 0x1f) == 7) {
647       GST_DEBUG_OBJECT (rtph264pay, "adding param %d as SPS %d", i, num_sps);
648       rtph264pay->sps = g_list_append (rtph264pay->sps, buf);
649       num_sps++;
650     } else {
651       GST_DEBUG_OBJECT (rtph264pay, "adding param %d as PPS %d", i, num_pps);
652       rtph264pay->pps = g_list_append (rtph264pay->pps, buf);
653       num_pps++;
654     }
655   }
656   g_strfreev (params);
657 }
658
659 static guint
660 next_start_code (const guint8 * data, guint size)
661 {
662   /* Boyer-Moore string matching algorithm, in a degenerative
663    * sense because our search 'alphabet' is binary - 0 & 1 only.
664    * This allow us to simplify the general BM algorithm to a very
665    * simple form. */
666   /* assume 1 is in the 3th byte */
667   guint offset = 2;
668
669   while (offset < size) {
670     if (1 == data[offset]) {
671       unsigned int shift = offset;
672
673       if (0 == data[--shift]) {
674         if (0 == data[--shift]) {
675           return shift;
676         }
677       }
678       /* The jump is always 3 because of the 1 previously matched.
679        * All the 0's must be after this '1' matched at offset */
680       offset += 3;
681     } else if (0 == data[offset]) {
682       /* maybe next byte is 1? */
683       offset++;
684     } else {
685       /* can jump 3 bytes forward */
686       offset += 3;
687     }
688     /* at each iteration, we rescan in a backward manner until
689      * we match 0.0.1 in reverse order. Since our search string
690      * has only 2 'alpabets' (i.e. 0 & 1), we know that any
691      * mismatch will force us to shift a fixed number of steps */
692   }
693   GST_DEBUG ("Cannot find next NAL start code. returning %u", size);
694
695   return size;
696 }
697
698 static gboolean
699 gst_rtp_h264_pay_decode_nal (GstRtpH264Pay * payloader,
700     const guint8 * data, guint size, GstClockTime dts, GstClockTime pts)
701 {
702   const guint8 *sps = NULL, *pps = NULL;
703   guint sps_len = 0, pps_len = 0;
704   guint8 header, type;
705   guint len;
706   gboolean updated;
707
708   /* default is no update */
709   updated = FALSE;
710
711   GST_DEBUG ("NAL payload len=%u", size);
712
713   len = size;
714   header = data[0];
715   type = header & 0x1f;
716
717   /* keep sps & pps separately so that we can update either one 
718    * independently. We also record the timestamp of the last SPS/PPS so 
719    * that we can insert them at regular intervals and when needed. */
720   if (SPS_TYPE_ID == type) {
721     /* encode the entire SPS NAL in base64 */
722     GST_DEBUG ("Found SPS %x %x %x Len=%u", (header >> 7),
723         (header >> 5) & 3, type, len);
724
725     sps = data;
726     sps_len = len;
727     /* remember when we last saw SPS */
728     if (pts != -1)
729       payloader->last_spspps = pts;
730   } else if (PPS_TYPE_ID == type) {
731     /* encoder the entire PPS NAL in base64 */
732     GST_DEBUG ("Found PPS %x %x %x Len = %u",
733         (header >> 7), (header >> 5) & 3, type, len);
734
735     pps = data;
736     pps_len = len;
737     /* remember when we last saw PPS */
738     if (pts != -1)
739       payloader->last_spspps = pts;
740   } else {
741     GST_DEBUG ("NAL: %x %x %x Len = %u", (header >> 7),
742         (header >> 5) & 3, type, len);
743   }
744
745   /* If we encountered an SPS and/or a PPS, check if it's the
746    * same as the one we have. If not, update our version and
747    * set updated to TRUE
748    */
749   if (sps_len > 0) {
750     GstBuffer *sps_buf;
751
752     if (payloader->sps != NULL) {
753       sps_buf = GST_BUFFER_CAST (payloader->sps->data);
754
755       if (gst_buffer_memcmp (sps_buf, 0, sps, sps_len)) {
756         /* something changed, update */
757         payloader->profile = (sps[1] << 16) + (sps[2] << 8) + sps[3];
758         GST_DEBUG ("Profile level IDC = %06x", payloader->profile);
759         updated = TRUE;
760       }
761     } else {
762       /* no previous SPS, update */
763       updated = TRUE;
764     }
765
766     if (updated) {
767       sps_buf = gst_buffer_new_and_alloc (sps_len);
768       gst_buffer_fill (sps_buf, 0, sps, sps_len);
769
770       if (payloader->sps) {
771         /* replace old buffer */
772         gst_buffer_unref (payloader->sps->data);
773         payloader->sps->data = sps_buf;
774       } else {
775         /* add new buffer */
776         payloader->sps = g_list_prepend (payloader->sps, sps_buf);
777       }
778     }
779   }
780
781   if (pps_len > 0) {
782     GstBuffer *pps_buf;
783
784     if (payloader->pps != NULL) {
785       pps_buf = GST_BUFFER_CAST (payloader->pps->data);
786
787       if (gst_buffer_memcmp (pps_buf, 0, pps, pps_len)) {
788         /* something changed, update */
789         updated = TRUE;
790       }
791     } else {
792       /* no previous SPS, update */
793       updated = TRUE;
794     }
795
796     if (updated) {
797       pps_buf = gst_buffer_new_and_alloc (pps_len);
798       gst_buffer_fill (pps_buf, 0, pps, pps_len);
799
800       if (payloader->pps) {
801         /* replace old buffer */
802         gst_buffer_unref (payloader->pps->data);
803         payloader->pps->data = pps_buf;
804       } else {
805         /* add new buffer */
806         payloader->pps = g_list_prepend (payloader->pps, pps_buf);
807       }
808     }
809   }
810   return updated;
811 }
812
813 static GstFlowReturn
814 gst_rtp_h264_pay_payload_nal (GstRTPBasePayload * basepayload,
815     const guint8 * data, guint size, GstClockTime dts, GstClockTime pts,
816     GstBuffer * buffer_orig, gboolean end_of_au);
817
818 static GstFlowReturn
819 gst_rtp_h264_pay_send_sps_pps (GstRTPBasePayload * basepayload,
820     GstRtpH264Pay * rtph264pay, GstClockTime dts, GstClockTime pts)
821 {
822   GstFlowReturn ret = GST_FLOW_OK;
823   GList *walk;
824   GstMapInfo map;
825
826   for (walk = rtph264pay->sps; walk; walk = g_list_next (walk)) {
827     GstBuffer *sps_buf = GST_BUFFER_CAST (walk->data);
828
829     GST_DEBUG_OBJECT (rtph264pay, "inserting SPS in the stream");
830     /* resend SPS */
831     gst_buffer_map (sps_buf, &map, GST_MAP_READ);
832     ret = gst_rtp_h264_pay_payload_nal (basepayload,
833         map.data, map.size, dts, pts, sps_buf, FALSE);
834     gst_buffer_unmap (sps_buf, &map);
835     /* Not critical here; but throw a warning */
836     if (ret != GST_FLOW_OK)
837       GST_WARNING ("Problem pushing SPS");
838   }
839   for (walk = rtph264pay->pps; walk; walk = g_list_next (walk)) {
840     GstBuffer *pps_buf = GST_BUFFER_CAST (walk->data);
841
842     GST_DEBUG_OBJECT (rtph264pay, "inserting PPS in the stream");
843     /* resend PPS */
844     gst_buffer_map (pps_buf, &map, GST_MAP_READ);
845     ret = gst_rtp_h264_pay_payload_nal (basepayload,
846         map.data, map.size, dts, pts, pps_buf, FALSE);
847     gst_buffer_unmap (pps_buf, &map);
848     /* Not critical here; but throw a warning */
849     if (ret != GST_FLOW_OK)
850       GST_WARNING ("Problem pushing PPS");
851   }
852
853   if (pts != -1)
854     rtph264pay->last_spspps = pts;
855
856   return ret;
857 }
858
859 static GstFlowReturn
860 gst_rtp_h264_pay_payload_nal (GstRTPBasePayload * basepayload,
861     const guint8 * data, guint size, GstClockTime dts, GstClockTime pts,
862     GstBuffer * buffer_orig, gboolean end_of_au)
863 {
864   GstRtpH264Pay *rtph264pay;
865   GstFlowReturn ret;
866   guint8 nalType;
867   guint packet_len, payload_len, mtu;
868   GstBuffer *outbuf;
869   guint8 *payload;
870 #if 0
871   GstBufferList *list = NULL;
872 #endif
873   gboolean send_spspps;
874   GstRTPBuffer rtp = { NULL };
875
876   rtph264pay = GST_RTP_H264_PAY (basepayload);
877   mtu = GST_RTP_BASE_PAYLOAD_MTU (rtph264pay);
878
879   nalType = data[0] & 0x1f;
880   GST_DEBUG_OBJECT (rtph264pay, "Processing Buffer with NAL TYPE=%d", nalType);
881
882   send_spspps = FALSE;
883
884   /* check if we need to emit an SPS/PPS now */
885   if (nalType == IDR_TYPE_ID && rtph264pay->spspps_interval > 0) {
886     if (rtph264pay->last_spspps != -1) {
887       guint64 diff;
888
889       GST_LOG_OBJECT (rtph264pay,
890           "now %" GST_TIME_FORMAT ", last SPS/PPS %" GST_TIME_FORMAT,
891           GST_TIME_ARGS (pts), GST_TIME_ARGS (rtph264pay->last_spspps));
892
893       /* calculate diff between last SPS/PPS in milliseconds */
894       if (pts > rtph264pay->last_spspps)
895         diff = pts - rtph264pay->last_spspps;
896       else
897         diff = 0;
898
899       GST_DEBUG_OBJECT (rtph264pay,
900           "interval since last SPS/PPS %" GST_TIME_FORMAT,
901           GST_TIME_ARGS (diff));
902
903       /* bigger than interval, queue SPS/PPS */
904       if (GST_TIME_AS_SECONDS (diff) >= rtph264pay->spspps_interval) {
905         GST_DEBUG_OBJECT (rtph264pay, "time to send SPS/PPS");
906         send_spspps = TRUE;
907       }
908     } else {
909       /* no know previous SPS/PPS time, send now */
910       GST_DEBUG_OBJECT (rtph264pay, "no previous SPS/PPS time, send now");
911       send_spspps = TRUE;
912     }
913   }
914
915   if (send_spspps || rtph264pay->send_spspps) {
916     /* we need to send SPS/PPS now first. FIXME, don't use the pts for
917      * checking when we need to send SPS/PPS but convert to running_time first. */
918     rtph264pay->send_spspps = FALSE;
919     ret = gst_rtp_h264_pay_send_sps_pps (basepayload, rtph264pay, dts, pts);
920     if (ret != GST_FLOW_OK)
921       return ret;
922   }
923
924   packet_len = gst_rtp_buffer_calc_packet_len (size, 0, 0);
925
926   if (packet_len < mtu) {
927     GST_DEBUG_OBJECT (basepayload,
928         "NAL Unit fit in one packet datasize=%d mtu=%d", size, mtu);
929     /* will fit in one packet */
930
931 #if 0
932     if (rtph264pay->buffer_list) {
933       /* use buffer lists
934        * first create buffer without payload containing only the RTP header
935        * and then another buffer containing the payload. both buffers will
936        * be then added to the list */
937       outbuf = gst_rtp_buffer_new_allocate (0, 0, 0);
938     } else
939 #endif
940     {
941       /* use the old-fashioned way with a single buffer and memcpy */
942       outbuf = gst_rtp_buffer_new_allocate (size, 0, 0);
943     }
944
945     gst_rtp_buffer_map (outbuf, GST_MAP_WRITE, &rtp);
946
947     /* only set the marker bit on packets containing access units */
948     if (IS_ACCESS_UNIT (nalType) && end_of_au) {
949       gst_rtp_buffer_set_marker (&rtp, 1);
950     }
951
952     /* timestamp the outbuffer */
953     GST_BUFFER_PTS (outbuf) = pts;
954     GST_BUFFER_DTS (outbuf) = dts;
955
956 #if 0
957     if (rtph264pay->buffer_list) {
958       GstBuffer *paybuf;
959
960       /* create another buffer with the payload. */
961       if (buffer_orig)
962         paybuf = gst_buffer_create_sub (buffer_orig, data -
963             GST_BUFFER_DATA (buffer_orig), size);
964       else {
965         paybuf = gst_buffer_new_and_alloc (size);
966         gst_buffer_fill (paybuf, 0, data, size);
967       }
968
969       list = gst_buffer_list_new ();
970
971       /* add both buffers to the buffer list */
972       gst_buffer_list_add (list, outbuf);
973       gst_buffer_list_add (list, paybuf);
974
975       /* push the list to the next element in the pipe */
976       ret = gst_rtp_base_payload_push_list (basepayload, list);
977     } else
978 #endif
979     {
980       payload = gst_rtp_buffer_get_payload (&rtp);
981       GST_DEBUG_OBJECT (basepayload, "Copying %d bytes to outbuf", size);
982       memcpy (payload, data, size);
983       gst_rtp_buffer_unmap (&rtp);
984
985       ret = gst_rtp_base_payload_push (basepayload, outbuf);
986     }
987   } else {
988     /* fragmentation Units FU-A */
989     guint8 nalHeader;
990     guint limitedSize;
991     int ii = 0, start = 1, end = 0, pos = 0;
992
993     GST_DEBUG_OBJECT (basepayload,
994         "NAL Unit DOES NOT fit in one packet datasize=%d mtu=%d", size, mtu);
995
996     nalHeader = *data;
997     pos++;
998     size--;
999
1000     ret = GST_FLOW_OK;
1001
1002     GST_DEBUG_OBJECT (basepayload, "Using FU-A fragmentation for data size=%d",
1003         size);
1004
1005     /* We keep 2 bytes for FU indicator and FU Header */
1006     payload_len = gst_rtp_buffer_calc_payload_len (mtu - 2, 0, 0);
1007
1008 #if 0
1009     if (rtph264pay->buffer_list) {
1010       list = gst_buffer_list_new ();
1011       it = gst_buffer_list_iterate (list);
1012     }
1013 #endif
1014
1015     while (end == 0) {
1016       limitedSize = size < payload_len ? size : payload_len;
1017       GST_DEBUG_OBJECT (basepayload,
1018           "Inside  FU-A fragmentation limitedSize=%d iteration=%d", limitedSize,
1019           ii);
1020
1021 #if 0
1022       if (rtph264pay->buffer_list) {
1023         /* use buffer lists
1024          * first create buffer without payload containing only the RTP header
1025          * and then another buffer containing the payload. both buffers will
1026          * be then added to the list */
1027         outbuf = gst_rtp_buffer_new_allocate (2, 0, 0);
1028       } else
1029 #endif
1030       {
1031         /* use the old-fashioned way with a single buffer and memcpy
1032          * first create buffer to hold the payload */
1033         outbuf = gst_rtp_buffer_new_allocate (limitedSize + 2, 0, 0);
1034       }
1035
1036       gst_rtp_buffer_map (outbuf, GST_MAP_WRITE, &rtp);
1037
1038       GST_BUFFER_DTS (outbuf) = dts;
1039       GST_BUFFER_PTS (outbuf) = pts;
1040       payload = gst_rtp_buffer_get_payload (&rtp);
1041
1042       if (limitedSize == size) {
1043         GST_DEBUG_OBJECT (basepayload, "end size=%d iteration=%d", size, ii);
1044         end = 1;
1045       }
1046       if (IS_ACCESS_UNIT (nalType)) {
1047         gst_rtp_buffer_set_marker (&rtp, end && end_of_au);
1048       }
1049
1050       /* FU indicator */
1051       payload[0] = (nalHeader & 0x60) | 28;
1052
1053       /* FU Header */
1054       payload[1] = (start << 7) | (end << 6) | (nalHeader & 0x1f);
1055
1056 #if 0
1057       if (rtph264pay->buffer_list) {
1058         GstBuffer *paybuf;
1059
1060         /* create another buffer to hold the payload */
1061         if (buffer_orig)
1062           paybuf = gst_buffer_create_sub (buffer_orig, data -
1063               GST_BUFFER_DATA (buffer_orig) + pos, limitedSize);
1064         else {
1065           paybuf = gst_buffer_new_and_alloc (limitedSize);
1066           memcpy (GST_BUFFER_DATA (paybuf), data + pos, limitedSize);
1067         }
1068
1069         /* create a new group to hold the header and the payload */
1070         gst_buffer_list_iterator_add_group (it);
1071
1072         /* add both buffers to the buffer list */
1073         gst_buffer_list_iterator_add (it, outbuf);
1074         gst_buffer_list_iterator_add (it, paybuf);
1075
1076       } else
1077 #endif
1078       {
1079         memcpy (&payload[2], data + pos, limitedSize);
1080         gst_rtp_buffer_unmap (&rtp);
1081         GST_DEBUG_OBJECT (basepayload,
1082             "recorded %d payload bytes into packet iteration=%d",
1083             limitedSize + 2, ii);
1084
1085         ret = gst_rtp_base_payload_push (basepayload, outbuf);
1086         if (ret != GST_FLOW_OK)
1087           break;
1088       }
1089
1090       size -= limitedSize;
1091       pos += limitedSize;
1092       ii++;
1093       start = 0;
1094     }
1095
1096 #if 0
1097     if (rtph264pay->buffer_list) {
1098       /* free iterator and push the whole buffer list at once */
1099       gst_buffer_list_iterator_free (it);
1100       ret = gst_rtp_base_payload_push_list (basepayload, list);
1101     }
1102 #endif
1103   }
1104   return ret;
1105 }
1106
1107 static GstFlowReturn
1108 gst_rtp_h264_pay_handle_buffer (GstRTPBasePayload * basepayload,
1109     GstBuffer * buffer)
1110 {
1111   GstRtpH264Pay *rtph264pay;
1112   GstFlowReturn ret;
1113   gsize size;
1114   guint nal_len, i;
1115   GstMapInfo map;
1116   const guint8 *data, *nal_data;
1117   GstClockTime dts, pts;
1118   GArray *nal_queue;
1119   guint pushed = 0;
1120   gboolean bytestream;
1121
1122   rtph264pay = GST_RTP_H264_PAY (basepayload);
1123
1124   /* the input buffer contains one or more NAL units */
1125
1126   bytestream = (rtph264pay->scan_mode == GST_H264_SCAN_MODE_BYTESTREAM);
1127
1128   if (bytestream) {
1129     dts = gst_adapter_prev_dts (rtph264pay->adapter, NULL);
1130     pts = gst_adapter_prev_pts (rtph264pay->adapter, NULL);
1131     gst_adapter_push (rtph264pay->adapter, buffer);
1132     size = gst_adapter_available (rtph264pay->adapter);
1133     data = gst_adapter_map (rtph264pay->adapter, size);
1134     GST_DEBUG_OBJECT (basepayload,
1135         "got %" G_GSIZE_FORMAT " bytes (%" G_GSIZE_FORMAT ")", size,
1136         gst_buffer_get_size (buffer));
1137
1138     if (!GST_CLOCK_TIME_IS_VALID (dts))
1139       dts = GST_BUFFER_DTS (buffer);
1140     if (!GST_CLOCK_TIME_IS_VALID (pts))
1141       pts = GST_BUFFER_PTS (buffer);
1142   } else {
1143     gst_buffer_map (buffer, &map, GST_MAP_READ);
1144     data = map.data;
1145     size = map.size;
1146     pts = GST_BUFFER_PTS (buffer);
1147     dts = GST_BUFFER_DTS (buffer);
1148     GST_DEBUG_OBJECT (basepayload, "got %" G_GSIZE_FORMAT " bytes", size);
1149   }
1150
1151   ret = GST_FLOW_OK;
1152
1153   /* now loop over all NAL units and put them in a packet
1154    * FIXME, we should really try to pack multiple NAL units into one RTP packet
1155    * if we can, especially for the config packets that wont't cause decoder 
1156    * latency. */
1157   if (rtph264pay->packetized) {
1158     guint nal_length_size;
1159
1160     nal_length_size = rtph264pay->nal_length_size;
1161
1162     while (size > nal_length_size) {
1163       gint i;
1164       gboolean end_of_au = FALSE;
1165
1166       nal_len = 0;
1167       for (i = 0; i < nal_length_size; i++) {
1168         nal_len = ((nal_len << 8) + data[i]);
1169       }
1170
1171       /* skip the length bytes, make sure we don't run past the buffer size */
1172       data += nal_length_size;
1173       size -= nal_length_size;
1174
1175       if (size >= nal_len) {
1176         GST_DEBUG_OBJECT (basepayload, "got NAL of size %u", nal_len);
1177       } else {
1178         nal_len = size;
1179         GST_DEBUG_OBJECT (basepayload, "got incomplete NAL of size %u",
1180             nal_len);
1181       }
1182
1183       /* If we're at the end of the buffer, then we're at the end of the
1184        * access unit
1185        */
1186       if (rtph264pay->au_alignment && size - nal_len <= nal_length_size) {
1187         end_of_au = TRUE;
1188       }
1189
1190       ret =
1191           gst_rtp_h264_pay_payload_nal (basepayload, data, nal_len, dts, pts,
1192           buffer, end_of_au);
1193       if (ret != GST_FLOW_OK)
1194         break;
1195
1196       data += nal_len;
1197       size -= nal_len;
1198     }
1199   } else {
1200     guint next;
1201     gboolean update = FALSE;
1202
1203     /* get offset of first start code */
1204     next = next_start_code (data, size);
1205
1206     /* skip to start code, if no start code is found, next will be size and we
1207      * will not collect data. */
1208     data += next;
1209     size -= next;
1210     nal_data = data;
1211     nal_queue = rtph264pay->queue;
1212
1213     /* array must be empty when we get here */
1214     g_assert (nal_queue->len == 0);
1215
1216     GST_DEBUG_OBJECT (basepayload,
1217         "found first start at %u, bytes left %" G_GSIZE_FORMAT, next, size);
1218
1219     /* first pass to locate NALs and parse SPS/PPS */
1220     while (size > 4) {
1221       /* skip start code */
1222       data += 3;
1223       size -= 3;
1224
1225       if (rtph264pay->scan_mode == GST_H264_SCAN_MODE_SINGLE_NAL) {
1226         /* we are told that there is only a single NAL in this packet so that we
1227          * can avoid scanning for the next NAL. */
1228         next = size;
1229       } else {
1230         /* use next_start_code() to scan buffer.
1231          * next_start_code() returns the offset in data, 
1232          * starting from zero to the first byte of 0.0.0.1
1233          * If no start code is found, it returns the value of the 
1234          * 'size' parameter. 
1235          * data is unchanged by the call to next_start_code()
1236          */
1237         next = next_start_code (data, size);
1238
1239         if (next == size
1240             && rtph264pay->scan_mode == GST_H264_SCAN_MODE_BYTESTREAM) {
1241           /* Didn't find the start of next NAL, handle it next time */
1242           break;
1243         }
1244       }
1245
1246       /* nal length is distance to next start code */
1247       nal_len = next;
1248
1249       GST_DEBUG_OBJECT (basepayload, "found next start at %u of size %u", next,
1250           nal_len);
1251
1252       if (rtph264pay->sprop_parameter_sets != NULL) {
1253         /* explicitly set profile and sprop, use those */
1254         if (rtph264pay->update_caps) {
1255           if (!gst_rtp_base_payload_set_outcaps (basepayload,
1256                   "sprop-parameter-sets", G_TYPE_STRING,
1257                   rtph264pay->sprop_parameter_sets, NULL))
1258             goto caps_rejected;
1259
1260           /* parse SPS and PPS from provided parameter set (for insertion) */
1261           gst_rtp_h264_pay_parse_sprop_parameter_sets (rtph264pay);
1262
1263           rtph264pay->update_caps = FALSE;
1264
1265           GST_DEBUG ("outcaps update: sprop-parameter-sets=%s",
1266               rtph264pay->sprop_parameter_sets);
1267         }
1268       } else {
1269         /* We know our stream is a valid H264 NAL packet,
1270          * go parse it for SPS/PPS to enrich the caps */
1271         /* order: make sure to check nal */
1272         update =
1273             gst_rtp_h264_pay_decode_nal (rtph264pay, data, nal_len, dts, pts)
1274             || update;
1275       }
1276       /* move to next NAL packet */
1277       data += nal_len;
1278       size -= nal_len;
1279
1280       g_array_append_val (nal_queue, nal_len);
1281     }
1282
1283     /* if has new SPS & PPS, update the output caps */
1284     if (G_UNLIKELY (update))
1285       if (!gst_rtp_h264_pay_set_sps_pps (basepayload))
1286         goto caps_rejected;
1287
1288     /* second pass to payload and push */
1289     data = nal_data;
1290     pushed = 0;
1291
1292     for (i = 0; i < nal_queue->len; i++) {
1293       guint size;
1294       gboolean end_of_au = FALSE;
1295
1296       nal_len = g_array_index (nal_queue, guint, i);
1297       /* skip start code */
1298       data += 3;
1299
1300       /* Trim the end unless we're the last NAL in the buffer.
1301        * In case we're not at the end of the buffer we know the next block
1302        * starts with 0x000001 so all the 0x00 bytes at the end of this one are
1303        * trailing 0x0 that can be discarded */
1304       size = nal_len;
1305       if (i + 1 != nal_queue->len
1306           || rtph264pay->scan_mode == GST_H264_SCAN_MODE_BYTESTREAM)
1307         for (; size > 1 && data[size - 1] == 0x0; size--)
1308           /* skip */ ;
1309
1310       /* If it's the last nal unit we have in non-bytestream mode, we can
1311        * assume it's the end of an access-unit
1312        *
1313        * FIXME: We need to wait until the next packet or EOS to
1314        * actually payload the NAL so we can know if the current NAL is
1315        * the last one of an access unit or not if we are in bytestream mode
1316        */
1317       if (rtph264pay->au_alignment &&
1318           rtph264pay->scan_mode != GST_H264_SCAN_MODE_BYTESTREAM &&
1319           i == nal_queue->len - 1)
1320         end_of_au = TRUE;
1321
1322       /* put the data in one or more RTP packets */
1323       ret =
1324           gst_rtp_h264_pay_payload_nal (basepayload, data, size, dts, pts,
1325           buffer, end_of_au);
1326       if (ret != GST_FLOW_OK) {
1327         break;
1328       }
1329
1330       /* move to next NAL packet */
1331       data += nal_len;
1332       size -= nal_len;
1333       pushed += nal_len + 3;
1334     }
1335     g_array_set_size (nal_queue, 0);
1336   }
1337
1338 done:
1339   if (bytestream) {
1340     gst_adapter_unmap (rtph264pay->adapter);
1341     gst_adapter_flush (rtph264pay->adapter, pushed);
1342   } else {
1343     gst_buffer_unmap (buffer, &map);
1344     gst_buffer_unref (buffer);
1345   }
1346
1347   return ret;
1348
1349 caps_rejected:
1350   {
1351     GST_WARNING_OBJECT (basepayload, "Could not set outcaps");
1352     g_array_set_size (nal_queue, 0);
1353     ret = GST_FLOW_NOT_NEGOTIATED;
1354     goto done;
1355   }
1356 }
1357
1358 static gboolean
1359 gst_rtp_h264_pay_sink_event (GstRTPBasePayload * payload, GstEvent * event)
1360 {
1361   gboolean res;
1362   const GstStructure *s;
1363   GstRtpH264Pay *rtph264pay = GST_RTP_H264_PAY (payload);
1364
1365   switch (GST_EVENT_TYPE (event)) {
1366     case GST_EVENT_FLUSH_STOP:
1367       gst_adapter_clear (rtph264pay->adapter);
1368       break;
1369     case GST_EVENT_CUSTOM_DOWNSTREAM:
1370       s = gst_event_get_structure (event);
1371       if (gst_structure_has_name (s, "GstForceKeyUnit")) {
1372         gboolean resend_codec_data;
1373
1374         if (gst_structure_get_boolean (s, "all-headers",
1375                 &resend_codec_data) && resend_codec_data)
1376           rtph264pay->send_spspps = TRUE;
1377       }
1378       break;
1379     default:
1380       break;
1381   }
1382
1383   res = GST_RTP_BASE_PAYLOAD_CLASS (parent_class)->sink_event (payload, event);
1384
1385   return res;
1386 }
1387
1388 static GstStateChangeReturn
1389 gst_rtp_h264_pay_change_state (GstElement * element, GstStateChange transition)
1390 {
1391   GstStateChangeReturn ret;
1392   GstRtpH264Pay *rtph264pay = GST_RTP_H264_PAY (element);
1393
1394   switch (transition) {
1395     case GST_STATE_CHANGE_READY_TO_PAUSED:
1396       rtph264pay->send_spspps = FALSE;
1397       gst_adapter_clear (rtph264pay->adapter);
1398       break;
1399     default:
1400       break;
1401   }
1402
1403   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
1404
1405   return ret;
1406 }
1407
1408 static void
1409 gst_rtp_h264_pay_set_property (GObject * object, guint prop_id,
1410     const GValue * value, GParamSpec * pspec)
1411 {
1412   GstRtpH264Pay *rtph264pay;
1413
1414   rtph264pay = GST_RTP_H264_PAY (object);
1415
1416   switch (prop_id) {
1417     case PROP_PROFILE_LEVEL_ID:
1418       break;
1419     case PROP_SPROP_PARAMETER_SETS:
1420       g_free (rtph264pay->sprop_parameter_sets);
1421       rtph264pay->sprop_parameter_sets = g_value_dup_string (value);
1422       rtph264pay->update_caps = TRUE;
1423       break;
1424     case PROP_SCAN_MODE:
1425       rtph264pay->scan_mode = g_value_get_enum (value);
1426       break;
1427     case PROP_BUFFER_LIST:
1428       rtph264pay->buffer_list = g_value_get_boolean (value);
1429       break;
1430     case PROP_CONFIG_INTERVAL:
1431       rtph264pay->spspps_interval = g_value_get_uint (value);
1432       break;
1433     default:
1434       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1435       break;
1436   }
1437 }
1438
1439 static void
1440 gst_rtp_h264_pay_get_property (GObject * object, guint prop_id,
1441     GValue * value, GParamSpec * pspec)
1442 {
1443   GstRtpH264Pay *rtph264pay;
1444
1445   rtph264pay = GST_RTP_H264_PAY (object);
1446
1447   switch (prop_id) {
1448     case PROP_PROFILE_LEVEL_ID:
1449       break;
1450     case PROP_SPROP_PARAMETER_SETS:
1451       g_value_set_string (value, rtph264pay->sprop_parameter_sets);
1452       break;
1453     case PROP_SCAN_MODE:
1454       g_value_set_enum (value, rtph264pay->scan_mode);
1455       break;
1456     case PROP_BUFFER_LIST:
1457       g_value_set_boolean (value, rtph264pay->buffer_list);
1458       break;
1459     case PROP_CONFIG_INTERVAL:
1460       g_value_set_uint (value, rtph264pay->spspps_interval);
1461       break;
1462     default:
1463       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1464       break;
1465   }
1466 }
1467
1468 gboolean
1469 gst_rtp_h264_pay_plugin_init (GstPlugin * plugin)
1470 {
1471   return gst_element_register (plugin, "rtph264pay",
1472       GST_RANK_SECONDARY, GST_TYPE_RTP_H264_PAY);
1473 }