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