Merge remote-tracking branch 'origin/master' into 0.11
[platform/upstream/gst-plugins-good.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       }
361     }
362
363     gst_caps_merge_structure (caps, new_s);
364   }
365
366   icaps = gst_caps_intersect (caps, template_caps);
367   gst_caps_unref (caps);
368   caps = icaps;
369
370 done:
371
372   gst_caps_unref (template_caps);
373   gst_caps_unref (allowed_caps);
374
375   GST_LOG_OBJECT (payload, "returning caps %" GST_PTR_FORMAT, caps);
376   return caps;
377 }
378
379 /* take the currently configured SPS and PPS lists and set them on the caps as
380  * sprop-parameter-sets */
381 static gboolean
382 gst_rtp_h264_pay_set_sps_pps (GstRTPBasePayload * basepayload)
383 {
384   GstRtpH264Pay *payloader = GST_RTP_H264_PAY (basepayload);
385   gchar *profile;
386   gchar *set;
387   GList *walk;
388   GString *sprops;
389   guint count;
390   gboolean res;
391   GstMapInfo map;
392
393   sprops = g_string_new ("");
394   count = 0;
395
396   /* build the sprop-parameter-sets */
397   for (walk = payloader->sps; walk; walk = g_list_next (walk)) {
398     GstBuffer *sps_buf = GST_BUFFER_CAST (walk->data);
399
400     gst_buffer_map (sps_buf, &map, GST_MAP_READ);
401     set = g_base64_encode (map.data, map.size);
402     gst_buffer_unmap (sps_buf, &map);
403
404     g_string_append_printf (sprops, "%s%s", count ? "," : "", set);
405     g_free (set);
406     count++;
407   }
408   for (walk = payloader->pps; walk; walk = g_list_next (walk)) {
409     GstBuffer *pps_buf = GST_BUFFER_CAST (walk->data);
410
411     gst_buffer_map (pps_buf, &map, GST_MAP_READ);
412     set = g_base64_encode (map.data, map.size);
413     gst_buffer_unmap (pps_buf, &map);
414
415     g_string_append_printf (sprops, "%s%s", count ? "," : "", set);
416     g_free (set);
417     count++;
418   }
419
420   /* profile is 24 bit. Force it to respect the limit */
421   profile = g_strdup_printf ("%06x", payloader->profile & 0xffffff);
422   /* combine into output caps */
423   res = gst_rtp_base_payload_set_outcaps (basepayload,
424       "sprop-parameter-sets", G_TYPE_STRING, sprops->str, NULL);
425   g_string_free (sprops, TRUE);
426   g_free (profile);
427
428   return res;
429 }
430
431 static gboolean
432 gst_rtp_h264_pay_setcaps (GstRTPBasePayload * basepayload, GstCaps * caps)
433 {
434   GstRtpH264Pay *rtph264pay;
435   GstStructure *str;
436   const GValue *value;
437   GstMapInfo map;
438   guint8 *data;
439   gsize size;
440   GstBuffer *buffer;
441   const gchar *alignment;
442
443   rtph264pay = GST_RTP_H264_PAY (basepayload);
444
445   str = gst_caps_get_structure (caps, 0);
446
447   /* we can only set the output caps when we found the sprops and profile
448    * NALs */
449   gst_rtp_base_payload_set_options (basepayload, "video", TRUE, "H264", 90000);
450
451   alignment = gst_structure_get_string (str, "alignment");
452   if (alignment && !strcmp (alignment, "au"))
453     rtph264pay->au_alignment = TRUE;
454   else
455     rtph264pay->au_alignment = FALSE;
456
457   /* packetized AVC video has a codec_data */
458   if ((value = gst_structure_get_value (str, "codec_data"))) {
459     guint num_sps, num_pps;
460     gint i, nal_size;
461
462     GST_DEBUG_OBJECT (rtph264pay, "have packetized h264");
463     rtph264pay->packetized = TRUE;
464
465     buffer = gst_value_get_buffer (value);
466
467     gst_buffer_map (buffer, &map, GST_MAP_READ);
468     data = map.data;
469     size = map.size;
470
471     /* parse the avcC data */
472     if (size < 7)
473       goto avcc_too_small;
474     /* parse the version, this must be 1 */
475     if (data[0] != 1)
476       goto wrong_version;
477
478     /* AVCProfileIndication */
479     /* profile_compat */
480     /* AVCLevelIndication */
481     rtph264pay->profile = (data[1] << 16) | (data[2] << 8) | data[3];
482     GST_DEBUG_OBJECT (rtph264pay, "profile %06x", rtph264pay->profile);
483
484     /* 6 bits reserved | 2 bits lengthSizeMinusOne */
485     /* this is the number of bytes in front of the NAL units to mark their
486      * length */
487     rtph264pay->nal_length_size = (data[4] & 0x03) + 1;
488     GST_DEBUG_OBJECT (rtph264pay, "nal length %u", rtph264pay->nal_length_size);
489     /* 3 bits reserved | 5 bits numOfSequenceParameterSets */
490     num_sps = data[5] & 0x1f;
491     GST_DEBUG_OBJECT (rtph264pay, "num SPS %u", num_sps);
492
493     data += 6;
494     size -= 6;
495
496     /* create the sprop-parameter-sets */
497     for (i = 0; i < num_sps; i++) {
498       GstBuffer *sps_buf;
499
500       if (size < 2)
501         goto avcc_error;
502
503       nal_size = (data[0] << 8) | data[1];
504       data += 2;
505       size -= 2;
506
507       GST_LOG_OBJECT (rtph264pay, "SPS %d size %d", i, nal_size);
508
509       if (size < nal_size)
510         goto avcc_error;
511
512       /* make a buffer out of it and add to SPS list */
513       sps_buf = gst_buffer_new_and_alloc (nal_size);
514       gst_buffer_fill (sps_buf, 0, data, nal_size);
515       rtph264pay->sps = g_list_append (rtph264pay->sps, sps_buf);
516
517       data += nal_size;
518       size -= nal_size;
519     }
520     if (size < 1)
521       goto avcc_error;
522
523     /* 8 bits numOfPictureParameterSets */
524     num_pps = data[0];
525     data += 1;
526     size -= 1;
527
528     GST_DEBUG_OBJECT (rtph264pay, "num PPS %u", num_pps);
529     for (i = 0; i < num_pps; i++) {
530       GstBuffer *pps_buf;
531
532       if (size < 2)
533         goto avcc_error;
534
535       nal_size = (data[0] << 8) | data[1];
536       data += 2;
537       size -= 2;
538
539       GST_LOG_OBJECT (rtph264pay, "PPS %d size %d", i, nal_size);
540
541       if (size < nal_size)
542         goto avcc_error;
543
544       /* make a buffer out of it and add to PPS list */
545       pps_buf = gst_buffer_new_and_alloc (nal_size);
546       gst_buffer_fill (pps_buf, 0, data, nal_size);
547       rtph264pay->pps = g_list_append (rtph264pay->pps, pps_buf);
548
549       data += nal_size;
550       size -= nal_size;
551     }
552     gst_buffer_unmap (buffer, &map);
553     /* and update the caps with the collected data */
554     if (!gst_rtp_h264_pay_set_sps_pps (basepayload))
555       goto set_sps_pps_failed;
556   } else {
557     GST_DEBUG_OBJECT (rtph264pay, "have bytestream h264");
558     rtph264pay->packetized = FALSE;
559   }
560
561   return TRUE;
562
563 avcc_too_small:
564   {
565     GST_ERROR_OBJECT (rtph264pay, "avcC size %" G_GSIZE_FORMAT " < 7", size);
566     goto error;
567   }
568 wrong_version:
569   {
570     GST_ERROR_OBJECT (rtph264pay, "wrong avcC version");
571     goto error;
572   }
573 avcc_error:
574   {
575     GST_ERROR_OBJECT (rtph264pay, "avcC too small ");
576     goto error;
577   }
578 set_sps_pps_failed:
579   {
580     GST_ERROR_OBJECT (rtph264pay, "failed to set sps/pps");
581     goto error;
582   }
583 error:
584   {
585     gst_buffer_unmap (buffer, &map);
586     return FALSE;
587   }
588 }
589
590 static void
591 gst_rtp_h264_pay_parse_sprop_parameter_sets (GstRtpH264Pay * rtph264pay)
592 {
593   const gchar *ps;
594   gchar **params;
595   guint len, num_sps, num_pps;
596   gint i;
597   GstBuffer *buf;
598
599   ps = rtph264pay->sprop_parameter_sets;
600   if (ps == NULL)
601     return;
602
603   gst_rtp_h264_pay_clear_sps_pps (rtph264pay);
604
605   params = g_strsplit (ps, ",", 0);
606   len = g_strv_length (params);
607
608   GST_DEBUG_OBJECT (rtph264pay, "we have %d params", len);
609
610   num_sps = num_pps = 0;
611
612   for (i = 0; params[i]; i++) {
613     gsize nal_len;
614     GstMapInfo map;
615     guint8 *nalp;
616     guint save = 0;
617     gint state = 0;
618     guint8 nal_type;
619
620     nal_len = strlen (params[i]);
621     buf = gst_buffer_new_and_alloc (nal_len);
622
623     gst_buffer_map (buf, &map, GST_MAP_WRITE);
624     nalp = map.data;
625     nal_len = g_base64_decode_step (params[i], nal_len, nalp, &state, &save);
626     nal_type = nalp[0];
627     gst_buffer_unmap (buf, &map);
628     gst_buffer_resize (buf, 0, nal_len);
629
630     if (!nal_len) {
631       gst_buffer_unref (buf);
632       continue;
633     }
634
635     /* append to the right list */
636     if ((nal_type & 0x1f) == 7) {
637       GST_DEBUG_OBJECT (rtph264pay, "adding param %d as SPS %d", i, num_sps);
638       rtph264pay->sps = g_list_append (rtph264pay->sps, buf);
639       num_sps++;
640     } else {
641       GST_DEBUG_OBJECT (rtph264pay, "adding param %d as PPS %d", i, num_pps);
642       rtph264pay->pps = g_list_append (rtph264pay->pps, buf);
643       num_pps++;
644     }
645   }
646   g_strfreev (params);
647 }
648
649 static guint
650 next_start_code (const guint8 * data, guint size)
651 {
652   /* Boyer-Moore string matching algorithm, in a degenerative
653    * sense because our search 'alphabet' is binary - 0 & 1 only.
654    * This allow us to simplify the general BM algorithm to a very
655    * simple form. */
656   /* assume 1 is in the 3th byte */
657   guint offset = 2;
658
659   while (offset < size) {
660     if (1 == data[offset]) {
661       unsigned int shift = offset;
662
663       if (0 == data[--shift]) {
664         if (0 == data[--shift]) {
665           return shift;
666         }
667       }
668       /* The jump is always 3 because of the 1 previously matched.
669        * All the 0's must be after this '1' matched at offset */
670       offset += 3;
671     } else if (0 == data[offset]) {
672       /* maybe next byte is 1? */
673       offset++;
674     } else {
675       /* can jump 3 bytes forward */
676       offset += 3;
677     }
678     /* at each iteration, we rescan in a backward manner until
679      * we match 0.0.1 in reverse order. Since our search string
680      * has only 2 'alpabets' (i.e. 0 & 1), we know that any
681      * mismatch will force us to shift a fixed number of steps */
682   }
683   GST_DEBUG ("Cannot find next NAL start code. returning %u", size);
684
685   return size;
686 }
687
688 static gboolean
689 gst_rtp_h264_pay_decode_nal (GstRtpH264Pay * payloader,
690     const guint8 * data, guint size, GstClockTime timestamp)
691 {
692   const guint8 *sps = NULL, *pps = NULL;
693   guint sps_len = 0, pps_len = 0;
694   guint8 header, type;
695   guint len;
696   gboolean updated;
697
698   /* default is no update */
699   updated = FALSE;
700
701   GST_DEBUG ("NAL payload len=%u", size);
702
703   len = size;
704   header = data[0];
705   type = header & 0x1f;
706
707   /* keep sps & pps separately so that we can update either one 
708    * independently. We also record the timestamp of the last SPS/PPS so 
709    * that we can insert them at regular intervals and when needed. */
710   if (SPS_TYPE_ID == type) {
711     /* encode the entire SPS NAL in base64 */
712     GST_DEBUG ("Found SPS %x %x %x Len=%u", (header >> 7),
713         (header >> 5) & 3, type, len);
714
715     sps = data;
716     sps_len = len;
717     /* remember when we last saw SPS */
718     if (timestamp != -1)
719       payloader->last_spspps = timestamp;
720   } else if (PPS_TYPE_ID == type) {
721     /* encoder the entire PPS NAL in base64 */
722     GST_DEBUG ("Found PPS %x %x %x Len = %u",
723         (header >> 7), (header >> 5) & 3, type, len);
724
725     pps = data;
726     pps_len = len;
727     /* remember when we last saw PPS */
728     if (timestamp != -1)
729       payloader->last_spspps = timestamp;
730   } else {
731     GST_DEBUG ("NAL: %x %x %x Len = %u", (header >> 7),
732         (header >> 5) & 3, type, len);
733   }
734
735   /* If we encountered an SPS and/or a PPS, check if it's the
736    * same as the one we have. If not, update our version and
737    * set updated to TRUE
738    */
739   if (sps_len > 0) {
740     GstBuffer *sps_buf;
741
742     if (payloader->sps != NULL) {
743       sps_buf = GST_BUFFER_CAST (payloader->sps->data);
744
745       if (gst_buffer_memcmp (sps_buf, 0, sps, sps_len)) {
746         /* something changed, update */
747         payloader->profile = (sps[1] << 16) + (sps[2] << 8) + sps[3];
748         GST_DEBUG ("Profile level IDC = %06x", payloader->profile);
749         updated = TRUE;
750       }
751     } else {
752       /* no previous SPS, update */
753       updated = TRUE;
754     }
755
756     if (updated) {
757       sps_buf = gst_buffer_new_and_alloc (sps_len);
758       gst_buffer_fill (sps_buf, 0, sps, sps_len);
759
760       if (payloader->sps) {
761         /* replace old buffer */
762         gst_buffer_unref (payloader->sps->data);
763         payloader->sps->data = sps_buf;
764       } else {
765         /* add new buffer */
766         payloader->sps = g_list_prepend (payloader->sps, sps_buf);
767       }
768     }
769   }
770
771   if (pps_len > 0) {
772     GstBuffer *pps_buf;
773
774     if (payloader->pps != NULL) {
775       pps_buf = GST_BUFFER_CAST (payloader->pps->data);
776
777       if (gst_buffer_memcmp (pps_buf, 0, pps, pps_len)) {
778         /* something changed, update */
779         updated = TRUE;
780       }
781     } else {
782       /* no previous SPS, update */
783       updated = TRUE;
784     }
785
786     if (updated) {
787       pps_buf = gst_buffer_new_and_alloc (pps_len);
788       gst_buffer_fill (pps_buf, 0, pps, pps_len);
789
790       if (payloader->pps) {
791         /* replace old buffer */
792         gst_buffer_unref (payloader->pps->data);
793         payloader->pps->data = pps_buf;
794       } else {
795         /* add new buffer */
796         payloader->pps = g_list_prepend (payloader->pps, pps_buf);
797       }
798     }
799   }
800   return updated;
801 }
802
803 static GstFlowReturn
804 gst_rtp_h264_pay_payload_nal (GstRTPBasePayload * basepayload,
805     const guint8 * data, guint size, GstClockTime timestamp,
806     GstBuffer * buffer_orig, gboolean end_of_au);
807
808 static GstFlowReturn
809 gst_rtp_h264_pay_send_sps_pps (GstRTPBasePayload * basepayload,
810     GstRtpH264Pay * rtph264pay, GstClockTime timestamp)
811 {
812   GstFlowReturn ret = GST_FLOW_OK;
813   GList *walk;
814   GstMapInfo map;
815
816   for (walk = rtph264pay->sps; walk; walk = g_list_next (walk)) {
817     GstBuffer *sps_buf = GST_BUFFER_CAST (walk->data);
818
819     GST_DEBUG_OBJECT (rtph264pay, "inserting SPS in the stream");
820     /* resend SPS */
821     gst_buffer_map (sps_buf, &map, GST_MAP_READ);
822     ret = gst_rtp_h264_pay_payload_nal (basepayload,
823         map.data, map.size, timestamp, sps_buf, FALSE);
824     gst_buffer_unmap (sps_buf, &map);
825     /* Not critical here; but throw a warning */
826     if (ret != GST_FLOW_OK)
827       GST_WARNING ("Problem pushing SPS");
828   }
829   for (walk = rtph264pay->pps; walk; walk = g_list_next (walk)) {
830     GstBuffer *pps_buf = GST_BUFFER_CAST (walk->data);
831
832     GST_DEBUG_OBJECT (rtph264pay, "inserting PPS in the stream");
833     /* resend PPS */
834     gst_buffer_map (pps_buf, &map, GST_MAP_READ);
835     ret = gst_rtp_h264_pay_payload_nal (basepayload,
836         map.data, map.size, timestamp, pps_buf, FALSE);
837     gst_buffer_unmap (pps_buf, &map);
838     /* Not critical here; but throw a warning */
839     if (ret != GST_FLOW_OK)
840       GST_WARNING ("Problem pushing PPS");
841   }
842
843   if (timestamp != -1)
844     rtph264pay->last_spspps = timestamp;
845
846   return ret;
847 }
848
849 static GstFlowReturn
850 gst_rtp_h264_pay_payload_nal (GstRTPBasePayload * basepayload,
851     const guint8 * data, guint size, GstClockTime timestamp,
852     GstBuffer * buffer_orig, gboolean end_of_au)
853 {
854   GstRtpH264Pay *rtph264pay;
855   GstFlowReturn ret;
856   guint8 nalType;
857   guint packet_len, payload_len, mtu;
858   GstBuffer *outbuf;
859   guint8 *payload;
860 #if 0
861   GstBufferList *list = NULL;
862 #endif
863   gboolean send_spspps;
864   GstRTPBuffer rtp = { NULL };
865
866   rtph264pay = GST_RTP_H264_PAY (basepayload);
867   mtu = GST_RTP_BASE_PAYLOAD_MTU (rtph264pay);
868
869   nalType = data[0] & 0x1f;
870   GST_DEBUG_OBJECT (rtph264pay, "Processing Buffer with NAL TYPE=%d", nalType);
871
872   send_spspps = FALSE;
873
874   /* check if we need to emit an SPS/PPS now */
875   if (nalType == IDR_TYPE_ID && rtph264pay->spspps_interval > 0) {
876     if (rtph264pay->last_spspps != -1) {
877       guint64 diff;
878
879       GST_LOG_OBJECT (rtph264pay,
880           "now %" GST_TIME_FORMAT ", last SPS/PPS %" GST_TIME_FORMAT,
881           GST_TIME_ARGS (timestamp), GST_TIME_ARGS (rtph264pay->last_spspps));
882
883       /* calculate diff between last SPS/PPS in milliseconds */
884       if (timestamp > rtph264pay->last_spspps)
885         diff = timestamp - rtph264pay->last_spspps;
886       else
887         diff = 0;
888
889       GST_DEBUG_OBJECT (rtph264pay,
890           "interval since last SPS/PPS %" GST_TIME_FORMAT,
891           GST_TIME_ARGS (diff));
892
893       /* bigger than interval, queue SPS/PPS */
894       if (GST_TIME_AS_SECONDS (diff) >= rtph264pay->spspps_interval) {
895         GST_DEBUG_OBJECT (rtph264pay, "time to send SPS/PPS");
896         send_spspps = TRUE;
897       }
898     } else {
899       /* no know previous SPS/PPS time, send now */
900       GST_DEBUG_OBJECT (rtph264pay, "no previous SPS/PPS time, send now");
901       send_spspps = TRUE;
902     }
903   }
904
905   if (send_spspps || rtph264pay->send_spspps) {
906     /* we need to send SPS/PPS now first. FIXME, don't use the timestamp for
907      * checking when we need to send SPS/PPS but convert to running_time first. */
908     rtph264pay->send_spspps = FALSE;
909     ret = gst_rtp_h264_pay_send_sps_pps (basepayload, rtph264pay, timestamp);
910     if (ret != GST_FLOW_OK)
911       return ret;
912   }
913
914   packet_len = gst_rtp_buffer_calc_packet_len (size, 0, 0);
915
916   if (packet_len < mtu) {
917     GST_DEBUG_OBJECT (basepayload,
918         "NAL Unit fit in one packet datasize=%d mtu=%d", size, mtu);
919     /* will fit in one packet */
920
921 #if 0
922     if (rtph264pay->buffer_list) {
923       /* use buffer lists
924        * first create buffer without payload containing only the RTP header
925        * and then another buffer containing the payload. both buffers will
926        * be then added to the list */
927       outbuf = gst_rtp_buffer_new_allocate (0, 0, 0);
928     } else
929 #endif
930     {
931       /* use the old-fashioned way with a single buffer and memcpy */
932       outbuf = gst_rtp_buffer_new_allocate (size, 0, 0);
933     }
934
935     gst_rtp_buffer_map (outbuf, GST_MAP_WRITE, &rtp);
936
937     /* only set the marker bit on packets containing access units */
938     if (IS_ACCESS_UNIT (nalType) && end_of_au) {
939       gst_rtp_buffer_set_marker (&rtp, 1);
940     }
941
942     /* timestamp the outbuffer */
943     GST_BUFFER_TIMESTAMP (outbuf) = timestamp;
944
945 #if 0
946     if (rtph264pay->buffer_list) {
947       GstBuffer *paybuf;
948
949       /* create another buffer with the payload. */
950       if (buffer_orig)
951         paybuf = gst_buffer_create_sub (buffer_orig, data -
952             GST_BUFFER_DATA (buffer_orig), size);
953       else {
954         paybuf = gst_buffer_new_and_alloc (size);
955         gst_buffer_fill (paybuf, 0, data, size);
956       }
957
958       list = gst_buffer_list_new ();
959
960       /* add both buffers to the buffer list */
961       gst_buffer_list_add (list, outbuf);
962       gst_buffer_list_add (list, paybuf);
963
964       /* push the list to the next element in the pipe */
965       ret = gst_rtp_base_payload_push_list (basepayload, list);
966     } else
967 #endif
968     {
969       payload = gst_rtp_buffer_get_payload (&rtp);
970       GST_DEBUG_OBJECT (basepayload, "Copying %d bytes to outbuf", size);
971       memcpy (payload, data, size);
972       gst_rtp_buffer_unmap (&rtp);
973
974       ret = gst_rtp_base_payload_push (basepayload, outbuf);
975     }
976   } else {
977     /* fragmentation Units FU-A */
978     guint8 nalHeader;
979     guint limitedSize;
980     int ii = 0, start = 1, end = 0, pos = 0;
981
982     GST_DEBUG_OBJECT (basepayload,
983         "NAL Unit DOES NOT fit in one packet datasize=%d mtu=%d", size, mtu);
984
985     nalHeader = *data;
986     pos++;
987     size--;
988
989     ret = GST_FLOW_OK;
990
991     GST_DEBUG_OBJECT (basepayload, "Using FU-A fragmentation for data size=%d",
992         size);
993
994     /* We keep 2 bytes for FU indicator and FU Header */
995     payload_len = gst_rtp_buffer_calc_payload_len (mtu - 2, 0, 0);
996
997 #if 0
998     if (rtph264pay->buffer_list) {
999       list = gst_buffer_list_new ();
1000       it = gst_buffer_list_iterate (list);
1001     }
1002 #endif
1003
1004     while (end == 0) {
1005       limitedSize = size < payload_len ? size : payload_len;
1006       GST_DEBUG_OBJECT (basepayload,
1007           "Inside  FU-A fragmentation limitedSize=%d iteration=%d", limitedSize,
1008           ii);
1009
1010 #if 0
1011       if (rtph264pay->buffer_list) {
1012         /* use buffer lists
1013          * first create buffer without payload containing only the RTP header
1014          * and then another buffer containing the payload. both buffers will
1015          * be then added to the list */
1016         outbuf = gst_rtp_buffer_new_allocate (2, 0, 0);
1017       } else
1018 #endif
1019       {
1020         /* use the old-fashioned way with a single buffer and memcpy
1021          * first create buffer to hold the payload */
1022         outbuf = gst_rtp_buffer_new_allocate (limitedSize + 2, 0, 0);
1023       }
1024
1025       gst_rtp_buffer_map (outbuf, GST_MAP_WRITE, &rtp);
1026
1027       GST_BUFFER_TIMESTAMP (outbuf) = timestamp;
1028       payload = gst_rtp_buffer_get_payload (&rtp);
1029
1030       if (limitedSize == size) {
1031         GST_DEBUG_OBJECT (basepayload, "end size=%d iteration=%d", size, ii);
1032         end = 1;
1033       }
1034       if (IS_ACCESS_UNIT (nalType)) {
1035         gst_rtp_buffer_set_marker (&rtp, end && end_of_au);
1036       }
1037
1038       /* FU indicator */
1039       payload[0] = (nalHeader & 0x60) | 28;
1040
1041       /* FU Header */
1042       payload[1] = (start << 7) | (end << 6) | (nalHeader & 0x1f);
1043
1044 #if 0
1045       if (rtph264pay->buffer_list) {
1046         GstBuffer *paybuf;
1047
1048         /* create another buffer to hold the payload */
1049         if (buffer_orig)
1050           paybuf = gst_buffer_create_sub (buffer_orig, data -
1051               GST_BUFFER_DATA (buffer_orig) + pos, limitedSize);
1052         else {
1053           paybuf = gst_buffer_new_and_alloc (limitedSize);
1054           memcpy (GST_BUFFER_DATA (paybuf), data + pos, limitedSize);
1055         }
1056
1057         /* create a new group to hold the header and the payload */
1058         gst_buffer_list_iterator_add_group (it);
1059
1060         /* add both buffers to the buffer list */
1061         gst_buffer_list_iterator_add (it, outbuf);
1062         gst_buffer_list_iterator_add (it, paybuf);
1063
1064       } else
1065 #endif
1066       {
1067         memcpy (&payload[2], data + pos, limitedSize);
1068         gst_rtp_buffer_unmap (&rtp);
1069         GST_DEBUG_OBJECT (basepayload,
1070             "recorded %d payload bytes into packet iteration=%d",
1071             limitedSize + 2, ii);
1072
1073         ret = gst_rtp_base_payload_push (basepayload, outbuf);
1074         if (ret != GST_FLOW_OK)
1075           break;
1076       }
1077
1078       size -= limitedSize;
1079       pos += limitedSize;
1080       ii++;
1081       start = 0;
1082     }
1083
1084 #if 0
1085     if (rtph264pay->buffer_list) {
1086       /* free iterator and push the whole buffer list at once */
1087       gst_buffer_list_iterator_free (it);
1088       ret = gst_rtp_base_payload_push_list (basepayload, list);
1089     }
1090 #endif
1091   }
1092   return ret;
1093 }
1094
1095 static GstFlowReturn
1096 gst_rtp_h264_pay_handle_buffer (GstRTPBasePayload * basepayload,
1097     GstBuffer * buffer)
1098 {
1099   GstRtpH264Pay *rtph264pay;
1100   GstFlowReturn ret;
1101   gsize size;
1102   guint nal_len, i;
1103   GstMapInfo map;
1104   const guint8 *data, *nal_data;
1105   GstClockTime timestamp;
1106   GArray *nal_queue;
1107   guint pushed = 0;
1108   gboolean bytestream;
1109
1110   rtph264pay = GST_RTP_H264_PAY (basepayload);
1111
1112   /* the input buffer contains one or more NAL units */
1113
1114   bytestream = (rtph264pay->scan_mode == GST_H264_SCAN_MODE_BYTESTREAM);
1115
1116   if (bytestream) {
1117     timestamp = gst_adapter_prev_timestamp (rtph264pay->adapter, NULL);
1118     gst_adapter_push (rtph264pay->adapter, buffer);
1119     size = gst_adapter_available (rtph264pay->adapter);
1120     data = gst_adapter_map (rtph264pay->adapter, size);
1121     GST_DEBUG_OBJECT (basepayload,
1122         "got %" G_GSIZE_FORMAT " bytes (%" G_GSIZE_FORMAT ")", size,
1123         gst_buffer_get_size (buffer));
1124
1125     if (!GST_CLOCK_TIME_IS_VALID (timestamp))
1126       timestamp = GST_BUFFER_TIMESTAMP (buffer);
1127   } else {
1128     gst_buffer_map (buffer, &map, GST_MAP_READ);
1129     data = map.data;
1130     size = map.size;
1131     timestamp = GST_BUFFER_TIMESTAMP (buffer);
1132     GST_DEBUG_OBJECT (basepayload, "got %" G_GSIZE_FORMAT " bytes", size);
1133   }
1134
1135   ret = GST_FLOW_OK;
1136
1137   /* now loop over all NAL units and put them in a packet
1138    * FIXME, we should really try to pack multiple NAL units into one RTP packet
1139    * if we can, especially for the config packets that wont't cause decoder 
1140    * latency. */
1141   if (rtph264pay->packetized) {
1142     guint nal_length_size;
1143
1144     nal_length_size = rtph264pay->nal_length_size;
1145
1146     while (size > nal_length_size) {
1147       gint i;
1148       gboolean end_of_au = FALSE;
1149
1150       nal_len = 0;
1151       for (i = 0; i < nal_length_size; i++) {
1152         nal_len = ((nal_len << 8) + data[i]);
1153       }
1154
1155       /* skip the length bytes, make sure we don't run past the buffer size */
1156       data += nal_length_size;
1157       size -= nal_length_size;
1158
1159       if (size >= nal_len) {
1160         GST_DEBUG_OBJECT (basepayload, "got NAL of size %u", nal_len);
1161       } else {
1162         nal_len = size;
1163         GST_DEBUG_OBJECT (basepayload, "got incomplete NAL of size %u",
1164             nal_len);
1165       }
1166
1167       /* If we're at the end of the buffer, then we're at the end of the
1168        * access unit
1169        */
1170       if (rtph264pay->au_alignment && size - nal_len <= nal_length_size) {
1171         end_of_au = TRUE;
1172       }
1173
1174       ret =
1175           gst_rtp_h264_pay_payload_nal (basepayload, data, nal_len, timestamp,
1176           buffer, end_of_au);
1177       if (ret != GST_FLOW_OK)
1178         break;
1179
1180       data += nal_len;
1181       size -= nal_len;
1182     }
1183   } else {
1184     guint next;
1185     gboolean update = FALSE;
1186
1187     /* get offset of first start code */
1188     next = next_start_code (data, size);
1189
1190     /* skip to start code, if no start code is found, next will be size and we
1191      * will not collect data. */
1192     data += next;
1193     size -= next;
1194     nal_data = data;
1195     nal_queue = rtph264pay->queue;
1196
1197     /* array must be empty when we get here */
1198     g_assert (nal_queue->len == 0);
1199
1200     GST_DEBUG_OBJECT (basepayload,
1201         "found first start at %u, bytes left %" G_GSIZE_FORMAT, next, size);
1202
1203     /* first pass to locate NALs and parse SPS/PPS */
1204     while (size > 4) {
1205       /* skip start code */
1206       data += 3;
1207       size -= 3;
1208
1209       if (rtph264pay->scan_mode == GST_H264_SCAN_MODE_SINGLE_NAL) {
1210         /* we are told that there is only a single NAL in this packet so that we
1211          * can avoid scanning for the next NAL. */
1212         next = size;
1213       } else {
1214         /* use next_start_code() to scan buffer.
1215          * next_start_code() returns the offset in data, 
1216          * starting from zero to the first byte of 0.0.0.1
1217          * If no start code is found, it returns the value of the 
1218          * 'size' parameter. 
1219          * data is unchanged by the call to next_start_code()
1220          */
1221         next = next_start_code (data, size);
1222
1223         if (next == size
1224             && rtph264pay->scan_mode == GST_H264_SCAN_MODE_BYTESTREAM) {
1225           /* Didn't find the start of next NAL, handle it next time */
1226           break;
1227         }
1228       }
1229
1230       /* nal length is distance to next start code */
1231       nal_len = next;
1232
1233       GST_DEBUG_OBJECT (basepayload, "found next start at %u of size %u", next,
1234           nal_len);
1235
1236       if (rtph264pay->sprop_parameter_sets != NULL) {
1237         /* explicitly set profile and sprop, use those */
1238         if (rtph264pay->update_caps) {
1239           if (!gst_rtp_base_payload_set_outcaps (basepayload,
1240                   "sprop-parameter-sets", G_TYPE_STRING,
1241                   rtph264pay->sprop_parameter_sets, NULL))
1242             goto caps_rejected;
1243
1244           /* parse SPS and PPS from provided parameter set (for insertion) */
1245           gst_rtp_h264_pay_parse_sprop_parameter_sets (rtph264pay);
1246
1247           rtph264pay->update_caps = FALSE;
1248
1249           GST_DEBUG ("outcaps update: sprop-parameter-sets=%s",
1250               rtph264pay->sprop_parameter_sets);
1251         }
1252       } else {
1253         /* We know our stream is a valid H264 NAL packet,
1254          * go parse it for SPS/PPS to enrich the caps */
1255         /* order: make sure to check nal */
1256         update =
1257             gst_rtp_h264_pay_decode_nal (rtph264pay, data, nal_len, timestamp)
1258             || update;
1259       }
1260       /* move to next NAL packet */
1261       data += nal_len;
1262       size -= nal_len;
1263
1264       g_array_append_val (nal_queue, nal_len);
1265     }
1266
1267     /* if has new SPS & PPS, update the output caps */
1268     if (G_UNLIKELY (update))
1269       if (!gst_rtp_h264_pay_set_sps_pps (basepayload))
1270         goto caps_rejected;
1271
1272     /* second pass to payload and push */
1273     data = nal_data;
1274     pushed = 0;
1275
1276     for (i = 0; i < nal_queue->len; i++) {
1277       guint size;
1278       gboolean end_of_au = FALSE;
1279
1280       nal_len = g_array_index (nal_queue, guint, i);
1281       /* skip start code */
1282       data += 3;
1283
1284       /* Trim the end unless we're the last NAL in the buffer.
1285        * In case we're not at the end of the buffer we know the next block
1286        * starts with 0x000001 so all the 0x00 bytes at the end of this one are
1287        * trailing 0x0 that can be discarded */
1288       size = nal_len;
1289       if (i + 1 != nal_queue->len
1290           || rtph264pay->scan_mode == GST_H264_SCAN_MODE_BYTESTREAM)
1291         for (; size > 1 && data[size - 1] == 0x0; size--)
1292           /* skip */ ;
1293
1294       /* If it's the last nal unit we have in non-bytestream mode, we can
1295        * assume it's the end of an access-unit
1296        *
1297        * FIXME: We need to wait until the next packet or EOS to
1298        * actually payload the NAL so we can know if the current NAL is
1299        * the last one of an access unit or not if we are in bytestream mode
1300        */
1301       if (rtph264pay->au_alignment &&
1302           rtph264pay->scan_mode != GST_H264_SCAN_MODE_BYTESTREAM &&
1303           i == nal_queue->len - 1)
1304         end_of_au = TRUE;
1305
1306       /* put the data in one or more RTP packets */
1307       ret =
1308           gst_rtp_h264_pay_payload_nal (basepayload, data, size, timestamp,
1309           buffer, end_of_au);
1310       if (ret != GST_FLOW_OK) {
1311         break;
1312       }
1313
1314       /* move to next NAL packet */
1315       data += nal_len;
1316       size -= nal_len;
1317       pushed += nal_len + 3;
1318     }
1319     g_array_set_size (nal_queue, 0);
1320   }
1321
1322 done:
1323   if (bytestream) {
1324     gst_adapter_unmap (rtph264pay->adapter);
1325     gst_adapter_flush (rtph264pay->adapter, pushed);
1326   } else {
1327     gst_buffer_unmap (buffer, &map);
1328     gst_buffer_unref (buffer);
1329   }
1330
1331   return ret;
1332
1333 caps_rejected:
1334   {
1335     GST_WARNING_OBJECT (basepayload, "Could not set outcaps");
1336     g_array_set_size (nal_queue, 0);
1337     ret = GST_FLOW_NOT_NEGOTIATED;
1338     goto done;
1339   }
1340 }
1341
1342 static gboolean
1343 gst_rtp_h264_pay_sink_event (GstRTPBasePayload * payload, GstEvent * event)
1344 {
1345   gboolean res;
1346   const GstStructure *s;
1347   GstRtpH264Pay *rtph264pay = GST_RTP_H264_PAY (payload);
1348
1349   switch (GST_EVENT_TYPE (event)) {
1350     case GST_EVENT_FLUSH_STOP:
1351       gst_adapter_clear (rtph264pay->adapter);
1352       break;
1353     case GST_EVENT_CUSTOM_DOWNSTREAM:
1354       s = gst_event_get_structure (event);
1355       if (gst_structure_has_name (s, "GstForceKeyUnit")) {
1356         gboolean resend_codec_data;
1357
1358         if (gst_structure_get_boolean (s, "all-headers",
1359                 &resend_codec_data) && resend_codec_data)
1360           rtph264pay->send_spspps = TRUE;
1361       }
1362       break;
1363     default:
1364       break;
1365   }
1366
1367   res = GST_RTP_BASE_PAYLOAD_CLASS (parent_class)->sink_event (payload, event);
1368
1369   return res;
1370 }
1371
1372 static GstStateChangeReturn
1373 gst_rtp_h264_pay_change_state (GstElement * element, GstStateChange transition)
1374 {
1375   GstStateChangeReturn ret;
1376   GstRtpH264Pay *rtph264pay = GST_RTP_H264_PAY (element);
1377
1378   switch (transition) {
1379     case GST_STATE_CHANGE_READY_TO_PAUSED:
1380       rtph264pay->send_spspps = FALSE;
1381       gst_adapter_clear (rtph264pay->adapter);
1382       break;
1383     default:
1384       break;
1385   }
1386
1387   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
1388
1389   return ret;
1390 }
1391
1392 static void
1393 gst_rtp_h264_pay_set_property (GObject * object, guint prop_id,
1394     const GValue * value, GParamSpec * pspec)
1395 {
1396   GstRtpH264Pay *rtph264pay;
1397
1398   rtph264pay = GST_RTP_H264_PAY (object);
1399
1400   switch (prop_id) {
1401     case PROP_PROFILE_LEVEL_ID:
1402       break;
1403     case PROP_SPROP_PARAMETER_SETS:
1404       g_free (rtph264pay->sprop_parameter_sets);
1405       rtph264pay->sprop_parameter_sets = g_value_dup_string (value);
1406       rtph264pay->update_caps = TRUE;
1407       break;
1408     case PROP_SCAN_MODE:
1409       rtph264pay->scan_mode = g_value_get_enum (value);
1410       break;
1411     case PROP_BUFFER_LIST:
1412       rtph264pay->buffer_list = g_value_get_boolean (value);
1413       break;
1414     case PROP_CONFIG_INTERVAL:
1415       rtph264pay->spspps_interval = g_value_get_uint (value);
1416       break;
1417     default:
1418       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1419       break;
1420   }
1421 }
1422
1423 static void
1424 gst_rtp_h264_pay_get_property (GObject * object, guint prop_id,
1425     GValue * value, GParamSpec * pspec)
1426 {
1427   GstRtpH264Pay *rtph264pay;
1428
1429   rtph264pay = GST_RTP_H264_PAY (object);
1430
1431   switch (prop_id) {
1432     case PROP_PROFILE_LEVEL_ID:
1433       break;
1434     case PROP_SPROP_PARAMETER_SETS:
1435       g_value_set_string (value, rtph264pay->sprop_parameter_sets);
1436       break;
1437     case PROP_SCAN_MODE:
1438       g_value_set_enum (value, rtph264pay->scan_mode);
1439       break;
1440     case PROP_BUFFER_LIST:
1441       g_value_set_boolean (value, rtph264pay->buffer_list);
1442       break;
1443     case PROP_CONFIG_INTERVAL:
1444       g_value_set_uint (value, rtph264pay->spspps_interval);
1445       break;
1446     default:
1447       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1448       break;
1449   }
1450 }
1451
1452 gboolean
1453 gst_rtp_h264_pay_plugin_init (GstPlugin * plugin)
1454 {
1455   return gst_element_register (plugin, "rtph264pay",
1456       GST_RANK_SECONDARY, GST_TYPE_RTP_H264_PAY);
1457 }