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