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