rtp: Update codes based on 1.18.4
[platform/upstream/gst-plugins-good.git] / gst / rtp / gstrtph264pay.c
1 /* ex: set tabstop=2 shiftwidth=2 expandtab: */
2 /* GStreamer
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 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 #include <gst/video/video.h>
30
31 /* Included to not duplicate gst_rtp_h264_add_sps_pps () */
32 #include "gstrtph264depay.h"
33
34 #include "gstrtph264pay.h"
35 #include "gstrtputils.h"
36 #include "gstbuffermemory.h"
37
38
39 #define IDR_TYPE_ID    5
40 #define SPS_TYPE_ID    7
41 #define PPS_TYPE_ID    8
42 #define AUD_TYPE_ID    9
43 #define STAP_A_TYPE_ID 24
44 #define FU_A_TYPE_ID   28
45
46 GST_DEBUG_CATEGORY_STATIC (rtph264pay_debug);
47 #define GST_CAT_DEFAULT (rtph264pay_debug)
48
49 #define GST_TYPE_RTP_H264_AGGREGATE_MODE \
50   (gst_rtp_h264_aggregate_mode_get_type ())
51
52
53 static GType
54 gst_rtp_h264_aggregate_mode_get_type (void)
55 {
56   static GType type = 0;
57   static const GEnumValue values[] = {
58     {GST_RTP_H264_AGGREGATE_NONE, "Do not aggregate NAL units", "none"},
59     {GST_RTP_H264_AGGREGATE_ZERO_LATENCY,
60         "Aggregate NAL units until a VCL unit is included", "zero-latency"},
61     {GST_RTP_H264_AGGREGATE_MAX_STAP,
62         "Aggregate all NAL units with the same timestamp (adds one frame of"
63           " latency)", "max-stap"},
64     {0, NULL, NULL},
65   };
66
67   if (!type) {
68     type = g_enum_register_static ("GstRtpH264AggregateMode", values);
69   }
70   return type;
71 }
72
73
74
75 /* references:
76 *
77  * RFC 3984
78  */
79
80 static GstStaticPadTemplate gst_rtp_h264_pay_sink_template =
81     GST_STATIC_PAD_TEMPLATE ("sink",
82     GST_PAD_SINK,
83     GST_PAD_ALWAYS,
84     GST_STATIC_CAPS ("video/x-h264, "
85         "stream-format = (string) avc, alignment = (string) au;"
86         "video/x-h264, "
87         "stream-format = (string) byte-stream, alignment = (string) { nal, au }")
88     );
89
90 static GstStaticPadTemplate gst_rtp_h264_pay_src_template =
91 GST_STATIC_PAD_TEMPLATE ("src",
92     GST_PAD_SRC,
93     GST_PAD_ALWAYS,
94     GST_STATIC_CAPS ("application/x-rtp, "
95         "media = (string) \"video\", "
96         "payload = (int) " GST_RTP_PAYLOAD_DYNAMIC_STRING ", "
97         "clock-rate = (int) 90000, " "encoding-name = (string) \"H264\"")
98     );
99
100 #define DEFAULT_SPROP_PARAMETER_SETS    NULL
101 #define DEFAULT_CONFIG_INTERVAL         0
102 #define DEFAULT_AGGREGATE_MODE          GST_RTP_H264_AGGREGATE_NONE
103
104 enum
105 {
106   PROP_0,
107   PROP_SPROP_PARAMETER_SETS,
108   PROP_CONFIG_INTERVAL,
109   PROP_AGGREGATE_MODE,
110 };
111
112 static void gst_rtp_h264_pay_finalize (GObject * object);
113
114 static void gst_rtp_h264_pay_set_property (GObject * object, guint prop_id,
115     const GValue * value, GParamSpec * pspec);
116 static void gst_rtp_h264_pay_get_property (GObject * object, guint prop_id,
117     GValue * value, GParamSpec * pspec);
118
119 static GstCaps *gst_rtp_h264_pay_getcaps (GstRTPBasePayload * payload,
120     GstPad * pad, GstCaps * filter);
121 static gboolean gst_rtp_h264_pay_setcaps (GstRTPBasePayload * basepayload,
122     GstCaps * caps);
123 static GstFlowReturn gst_rtp_h264_pay_handle_buffer (GstRTPBasePayload * pad,
124     GstBuffer * buffer);
125 static gboolean gst_rtp_h264_pay_sink_event (GstRTPBasePayload * payload,
126     GstEvent * event);
127 static GstStateChangeReturn gst_rtp_h264_pay_change_state (GstElement *
128     element, GstStateChange transition);
129 static gboolean gst_rtp_h264_pay_src_query (GstPad * pad, GstObject * parent,
130     GstQuery * query);
131
132 static void gst_rtp_h264_pay_reset_bundle (GstRtpH264Pay * rtph264pay);
133
134 #define gst_rtp_h264_pay_parent_class parent_class
135 G_DEFINE_TYPE (GstRtpH264Pay, gst_rtp_h264_pay, GST_TYPE_RTP_BASE_PAYLOAD);
136
137 static void
138 gst_rtp_h264_pay_class_init (GstRtpH264PayClass * klass)
139 {
140   GObjectClass *gobject_class;
141   GstElementClass *gstelement_class;
142   GstRTPBasePayloadClass *gstrtpbasepayload_class;
143
144   gobject_class = (GObjectClass *) klass;
145   gstelement_class = (GstElementClass *) klass;
146   gstrtpbasepayload_class = (GstRTPBasePayloadClass *) klass;
147
148   gobject_class->set_property = gst_rtp_h264_pay_set_property;
149   gobject_class->get_property = gst_rtp_h264_pay_get_property;
150
151   g_object_class_install_property (G_OBJECT_CLASS (klass),
152       PROP_SPROP_PARAMETER_SETS, g_param_spec_string ("sprop-parameter-sets",
153           "sprop-parameter-sets",
154           "The base64 sprop-parameter-sets to set in out caps (set to NULL to "
155           "extract from stream)",
156           DEFAULT_SPROP_PARAMETER_SETS,
157           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_DEPRECATED));
158
159   g_object_class_install_property (G_OBJECT_CLASS (klass),
160       PROP_CONFIG_INTERVAL,
161       g_param_spec_int ("config-interval",
162           "SPS PPS Send Interval",
163           "Send SPS and PPS Insertion Interval in seconds (sprop parameter sets "
164           "will be multiplexed in the data stream when detected.) "
165           "(0 = disabled, -1 = send with every IDR frame)",
166           -1, 3600, DEFAULT_CONFIG_INTERVAL,
167           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)
168       );
169
170   /**
171    * GstRtpH264Pay:aggregate-mode
172    *
173    * Bundle suitable SPS/PPS NAL units into STAP-A aggregate packets.
174    *
175    * This can potentially reduce RTP packetization overhead but not all
176    * RTP implementations handle it correctly.
177    *
178    * For best compatibility, it is recommended to set this to "none" (the
179    * default) for RTSP and for WebRTC to "zero-latency".
180    *
181    * Since: 1.18
182    */
183   g_object_class_install_property (G_OBJECT_CLASS (klass),
184       PROP_AGGREGATE_MODE,
185       g_param_spec_enum ("aggregate-mode",
186           "Attempt to use aggregate packets",
187           "Bundle suitable SPS/PPS NAL units into STAP-A "
188           "aggregate packets",
189           GST_TYPE_RTP_H264_AGGREGATE_MODE,
190           DEFAULT_AGGREGATE_MODE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)
191       );
192
193   gobject_class->finalize = gst_rtp_h264_pay_finalize;
194
195   gst_element_class_add_static_pad_template (gstelement_class,
196       &gst_rtp_h264_pay_src_template);
197   gst_element_class_add_static_pad_template (gstelement_class,
198       &gst_rtp_h264_pay_sink_template);
199
200   gst_element_class_set_static_metadata (gstelement_class, "RTP H264 payloader",
201       "Codec/Payloader/Network/RTP",
202       "Payload-encode H264 video into RTP packets (RFC 3984)",
203       "Laurent Glayal <spglegle@yahoo.fr>");
204
205   gstelement_class->change_state =
206       GST_DEBUG_FUNCPTR (gst_rtp_h264_pay_change_state);
207
208   gstrtpbasepayload_class->get_caps = gst_rtp_h264_pay_getcaps;
209   gstrtpbasepayload_class->set_caps = gst_rtp_h264_pay_setcaps;
210   gstrtpbasepayload_class->handle_buffer = gst_rtp_h264_pay_handle_buffer;
211   gstrtpbasepayload_class->sink_event = gst_rtp_h264_pay_sink_event;
212
213   GST_DEBUG_CATEGORY_INIT (rtph264pay_debug, "rtph264pay", 0,
214       "H264 RTP Payloader");
215 #ifndef TIZEN_FEATURE_GST_UPSTREAM_AVOID_BUILD_BREAK
216   gst_type_mark_as_plugin_api (GST_TYPE_RTP_H264_AGGREGATE_MODE, 0);
217 #endif
218 }
219
220 static void
221 gst_rtp_h264_pay_init (GstRtpH264Pay * rtph264pay)
222 {
223   rtph264pay->queue = g_array_new (FALSE, FALSE, sizeof (guint));
224   rtph264pay->profile = 0;
225   rtph264pay->sps = g_ptr_array_new_with_free_func (
226       (GDestroyNotify) gst_buffer_unref);
227   rtph264pay->pps = g_ptr_array_new_with_free_func (
228       (GDestroyNotify) gst_buffer_unref);
229   rtph264pay->last_spspps = -1;
230   rtph264pay->spspps_interval = DEFAULT_CONFIG_INTERVAL;
231   rtph264pay->aggregate_mode = DEFAULT_AGGREGATE_MODE;
232   rtph264pay->delta_unit = FALSE;
233   rtph264pay->discont = FALSE;
234
235   rtph264pay->adapter = gst_adapter_new ();
236
237   gst_pad_set_query_function (GST_RTP_BASE_PAYLOAD_SRCPAD (rtph264pay),
238       gst_rtp_h264_pay_src_query);
239 }
240
241 static void
242 gst_rtp_h264_pay_clear_sps_pps (GstRtpH264Pay * rtph264pay)
243 {
244   g_ptr_array_set_size (rtph264pay->sps, 0);
245   g_ptr_array_set_size (rtph264pay->pps, 0);
246 }
247
248 static void
249 gst_rtp_h264_pay_finalize (GObject * object)
250 {
251   GstRtpH264Pay *rtph264pay;
252
253   rtph264pay = GST_RTP_H264_PAY (object);
254
255   g_array_free (rtph264pay->queue, TRUE);
256
257   g_ptr_array_free (rtph264pay->sps, TRUE);
258   g_ptr_array_free (rtph264pay->pps, TRUE);
259
260   g_free (rtph264pay->sprop_parameter_sets);
261
262   g_object_unref (rtph264pay->adapter);
263   gst_rtp_h264_pay_reset_bundle (rtph264pay);
264
265   G_OBJECT_CLASS (parent_class)->finalize (object);
266 }
267
268 static const gchar all_levels[][4] = {
269   "1",
270   "1b",
271   "1.1",
272   "1.2",
273   "1.3",
274   "2",
275   "2.1",
276   "2.2",
277   "3",
278   "3.1",
279   "3.2",
280   "4",
281   "4.1",
282   "4.2",
283   "5",
284   "5.1"
285 };
286
287 static GstCaps *
288 gst_rtp_h264_pay_getcaps (GstRTPBasePayload * payload, GstPad * pad,
289     GstCaps * filter)
290 {
291   GstCaps *template_caps;
292   GstCaps *allowed_caps;
293   GstCaps *caps, *icaps;
294   gboolean append_unrestricted;
295   guint i;
296
297   allowed_caps =
298       gst_pad_peer_query_caps (GST_RTP_BASE_PAYLOAD_SRCPAD (payload), NULL);
299
300   if (allowed_caps == NULL)
301     return NULL;
302
303   template_caps =
304       gst_static_pad_template_get_caps (&gst_rtp_h264_pay_sink_template);
305
306   if (gst_caps_is_any (allowed_caps)) {
307     caps = gst_caps_ref (template_caps);
308     goto done;
309   }
310
311   if (gst_caps_is_empty (allowed_caps)) {
312     caps = gst_caps_ref (allowed_caps);
313     goto done;
314   }
315
316   caps = gst_caps_new_empty ();
317
318   append_unrestricted = FALSE;
319   for (i = 0; i < gst_caps_get_size (allowed_caps); i++) {
320     GstStructure *s = gst_caps_get_structure (allowed_caps, i);
321     GstStructure *new_s = gst_structure_new_empty ("video/x-h264");
322     const gchar *profile_level_id;
323
324     profile_level_id = gst_structure_get_string (s, "profile-level-id");
325
326     if (profile_level_id && strlen (profile_level_id) == 6) {
327       const gchar *profile;
328       const gchar *level;
329       long int spsint;
330       guint8 sps[3];
331
332       spsint = strtol (profile_level_id, NULL, 16);
333       sps[0] = spsint >> 16;
334       sps[1] = spsint >> 8;
335       sps[2] = spsint;
336
337       profile = gst_codec_utils_h264_get_profile (sps, 3);
338       level = gst_codec_utils_h264_get_level (sps, 3);
339
340       if (profile && level) {
341         GST_LOG_OBJECT (payload, "In caps, have profile %s and level %s",
342             profile, level);
343
344         if (!strcmp (profile, "constrained-baseline"))
345           gst_structure_set (new_s, "profile", G_TYPE_STRING, profile, NULL);
346         else {
347           GValue val = { 0, };
348           GValue profiles = { 0, };
349
350           g_value_init (&profiles, GST_TYPE_LIST);
351           g_value_init (&val, G_TYPE_STRING);
352
353           g_value_set_static_string (&val, profile);
354           gst_value_list_append_value (&profiles, &val);
355
356           g_value_set_static_string (&val, "constrained-baseline");
357           gst_value_list_append_value (&profiles, &val);
358
359           gst_structure_take_value (new_s, "profile", &profiles);
360         }
361
362         if (!strcmp (level, "1"))
363           gst_structure_set (new_s, "level", G_TYPE_STRING, level, NULL);
364         else {
365           GValue levels = { 0, };
366           GValue val = { 0, };
367           int j;
368
369           g_value_init (&levels, GST_TYPE_LIST);
370           g_value_init (&val, G_TYPE_STRING);
371
372           for (j = 0; j < G_N_ELEMENTS (all_levels); j++) {
373             g_value_set_static_string (&val, all_levels[j]);
374             gst_value_list_prepend_value (&levels, &val);
375             if (!strcmp (level, all_levels[j]))
376               break;
377           }
378           gst_structure_take_value (new_s, "level", &levels);
379         }
380       } else {
381         /* Invalid profile-level-id means baseline */
382
383         gst_structure_set (new_s,
384             "profile", G_TYPE_STRING, "constrained-baseline", NULL);
385       }
386     } else {
387       /* No profile-level-id means baseline or unrestricted */
388
389       gst_structure_set (new_s,
390           "profile", G_TYPE_STRING, "constrained-baseline", NULL);
391       append_unrestricted = TRUE;
392     }
393
394     caps = gst_caps_merge_structure (caps, new_s);
395   }
396
397   if (append_unrestricted) {
398     caps =
399         gst_caps_merge_structure (caps, gst_structure_new ("video/x-h264", NULL,
400             NULL));
401   }
402
403   icaps = gst_caps_intersect (caps, template_caps);
404   gst_caps_unref (caps);
405   caps = icaps;
406
407 done:
408   if (filter) {
409     GST_DEBUG_OBJECT (payload, "Intersect %" GST_PTR_FORMAT " and filter %"
410         GST_PTR_FORMAT, caps, filter);
411     icaps = gst_caps_intersect_full (filter, caps, GST_CAPS_INTERSECT_FIRST);
412     gst_caps_unref (caps);
413     caps = icaps;
414   }
415
416   gst_caps_unref (template_caps);
417   gst_caps_unref (allowed_caps);
418
419   GST_LOG_OBJECT (payload, "returning caps %" GST_PTR_FORMAT, caps);
420   return caps;
421 }
422
423 static gboolean
424 gst_rtp_h264_pay_src_query (GstPad * pad, GstObject * parent, GstQuery * query)
425 {
426   GstRtpH264Pay *rtph264pay = GST_RTP_H264_PAY (parent);
427
428   if (GST_QUERY_TYPE (query) == GST_QUERY_LATENCY) {
429     gboolean retval;
430     gboolean live;
431     GstClockTime min_latency, max_latency;
432
433     retval = gst_pad_query_default (pad, parent, query);
434     if (!retval)
435       return retval;
436
437     if (rtph264pay->stream_format == GST_H264_STREAM_FORMAT_UNKNOWN ||
438         rtph264pay->alignment == GST_H264_ALIGNMENT_UNKNOWN)
439       return FALSE;
440
441     gst_query_parse_latency (query, &live, &min_latency, &max_latency);
442
443     if (rtph264pay->aggregate_mode == GST_RTP_H264_AGGREGATE_MAX_STAP &&
444         rtph264pay->alignment != GST_H264_ALIGNMENT_AU && rtph264pay->fps_num) {
445       GstClockTime one_frame = gst_util_uint64_scale_int (GST_SECOND,
446           rtph264pay->fps_denum, rtph264pay->fps_num);
447
448       min_latency += one_frame;
449       max_latency += one_frame;
450       gst_query_set_latency (query, live, min_latency, max_latency);
451     }
452     return TRUE;
453   }
454
455   return gst_pad_query_default (pad, parent, query);
456 }
457
458
459 /* take the currently configured SPS and PPS lists and set them on the caps as
460  * sprop-parameter-sets */
461 static gboolean
462 gst_rtp_h264_pay_set_sps_pps (GstRTPBasePayload * basepayload)
463 {
464   GstRtpH264Pay *payloader = GST_RTP_H264_PAY (basepayload);
465   gchar *profile;
466   gchar *set;
467   GString *sprops;
468   guint count;
469   gboolean res;
470   GstMapInfo map;
471   guint i;
472
473   sprops = g_string_new ("");
474   count = 0;
475
476   /* build the sprop-parameter-sets */
477   for (i = 0; i < payloader->sps->len; i++) {
478     GstBuffer *sps_buf =
479         GST_BUFFER_CAST (g_ptr_array_index (payloader->sps, i));
480
481     gst_buffer_map (sps_buf, &map, GST_MAP_READ);
482     set = g_base64_encode (map.data, map.size);
483     gst_buffer_unmap (sps_buf, &map);
484
485     g_string_append_printf (sprops, "%s%s", count ? "," : "", set);
486     g_free (set);
487     count++;
488   }
489   for (i = 0; i < payloader->pps->len; i++) {
490     GstBuffer *pps_buf =
491         GST_BUFFER_CAST (g_ptr_array_index (payloader->pps, i));
492
493     gst_buffer_map (pps_buf, &map, GST_MAP_READ);
494     set = g_base64_encode (map.data, map.size);
495     gst_buffer_unmap (pps_buf, &map);
496
497     g_string_append_printf (sprops, "%s%s", count ? "," : "", set);
498     g_free (set);
499     count++;
500   }
501
502   if (G_LIKELY (count)) {
503     if (payloader->profile != 0) {
504       /* profile is 24 bit. Force it to respect the limit */
505       profile = g_strdup_printf ("%06x", payloader->profile & 0xffffff);
506       /* combine into output caps */
507       res = gst_rtp_base_payload_set_outcaps (basepayload,
508           "packetization-mode", G_TYPE_STRING, "1",
509           "profile-level-id", G_TYPE_STRING, profile,
510           "sprop-parameter-sets", G_TYPE_STRING, sprops->str, NULL);
511       g_free (profile);
512     } else {
513       res = gst_rtp_base_payload_set_outcaps (basepayload,
514           "packetization-mode", G_TYPE_STRING, "1",
515           "sprop-parameter-sets", G_TYPE_STRING, sprops->str, NULL);
516     }
517
518   } else {
519     res = gst_rtp_base_payload_set_outcaps (basepayload, NULL);
520   }
521   g_string_free (sprops, TRUE);
522
523   return res;
524 }
525
526
527 static gboolean
528 gst_rtp_h264_pay_setcaps (GstRTPBasePayload * basepayload, GstCaps * caps)
529 {
530   GstRtpH264Pay *rtph264pay;
531   GstStructure *str;
532   const GValue *value;
533   GstMapInfo map;
534   guint8 *data;
535   gsize size;
536   GstBuffer *buffer;
537   const gchar *alignment, *stream_format;
538
539   rtph264pay = GST_RTP_H264_PAY (basepayload);
540
541   str = gst_caps_get_structure (caps, 0);
542
543   /* we can only set the output caps when we found the sprops and profile
544    * NALs */
545   gst_rtp_base_payload_set_options (basepayload, "video", TRUE, "H264", 90000);
546
547   rtph264pay->alignment = GST_H264_ALIGNMENT_UNKNOWN;
548   alignment = gst_structure_get_string (str, "alignment");
549   if (alignment) {
550     if (g_str_equal (alignment, "au"))
551       rtph264pay->alignment = GST_H264_ALIGNMENT_AU;
552     if (g_str_equal (alignment, "nal"))
553       rtph264pay->alignment = GST_H264_ALIGNMENT_NAL;
554   }
555
556   rtph264pay->stream_format = GST_H264_STREAM_FORMAT_UNKNOWN;
557   stream_format = gst_structure_get_string (str, "stream-format");
558   if (stream_format) {
559     if (g_str_equal (stream_format, "avc"))
560       rtph264pay->stream_format = GST_H264_STREAM_FORMAT_AVC;
561     if (g_str_equal (stream_format, "byte-stream"))
562       rtph264pay->stream_format = GST_H264_STREAM_FORMAT_BYTESTREAM;
563   }
564
565   if (!gst_structure_get_fraction (str, "framerate", &rtph264pay->fps_num,
566           &rtph264pay->fps_denum))
567     rtph264pay->fps_num = rtph264pay->fps_denum = 0;
568
569   /* packetized AVC video has a codec_data */
570   if ((value = gst_structure_get_value (str, "codec_data"))) {
571     guint num_sps, num_pps;
572     gint i, nal_size;
573
574     GST_DEBUG_OBJECT (rtph264pay, "have packetized h264");
575
576     buffer = gst_value_get_buffer (value);
577
578     gst_buffer_map (buffer, &map, GST_MAP_READ);
579     data = map.data;
580     size = map.size;
581
582     /* parse the avcC data */
583     if (size < 7)
584       goto avcc_too_small;
585     /* parse the version, this must be 1 */
586     if (data[0] != 1)
587       goto wrong_version;
588
589     /* AVCProfileIndication */
590     /* profile_compat */
591     /* AVCLevelIndication */
592     rtph264pay->profile = (data[1] << 16) | (data[2] << 8) | data[3];
593     GST_DEBUG_OBJECT (rtph264pay, "profile %06x", rtph264pay->profile);
594
595     /* 6 bits reserved | 2 bits lengthSizeMinusOne */
596     /* this is the number of bytes in front of the NAL units to mark their
597      * length */
598     rtph264pay->nal_length_size = (data[4] & 0x03) + 1;
599     GST_DEBUG_OBJECT (rtph264pay, "nal length %u", rtph264pay->nal_length_size);
600     /* 3 bits reserved | 5 bits numOfSequenceParameterSets */
601     num_sps = data[5] & 0x1f;
602     GST_DEBUG_OBJECT (rtph264pay, "num SPS %u", num_sps);
603
604     data += 6;
605     size -= 6;
606
607     /* create the sprop-parameter-sets */
608     for (i = 0; i < num_sps; i++) {
609       GstBuffer *sps_buf;
610
611       if (size < 2)
612         goto avcc_error;
613
614       nal_size = (data[0] << 8) | data[1];
615       data += 2;
616       size -= 2;
617
618       GST_LOG_OBJECT (rtph264pay, "SPS %d size %d", i, nal_size);
619
620       if (size < nal_size)
621         goto avcc_error;
622
623       /* make a buffer out of it and add to SPS list */
624       sps_buf = gst_buffer_new_and_alloc (nal_size);
625       gst_buffer_fill (sps_buf, 0, data, nal_size);
626       gst_rtp_h264_add_sps_pps (GST_ELEMENT (rtph264pay), rtph264pay->sps,
627           rtph264pay->pps, sps_buf);
628       data += nal_size;
629       size -= nal_size;
630     }
631     if (size < 1)
632       goto avcc_error;
633
634     /* 8 bits numOfPictureParameterSets */
635     num_pps = data[0];
636     data += 1;
637     size -= 1;
638
639     GST_DEBUG_OBJECT (rtph264pay, "num PPS %u", num_pps);
640     for (i = 0; i < num_pps; i++) {
641       GstBuffer *pps_buf;
642
643       if (size < 2)
644         goto avcc_error;
645
646       nal_size = (data[0] << 8) | data[1];
647       data += 2;
648       size -= 2;
649
650       GST_LOG_OBJECT (rtph264pay, "PPS %d size %d", i, nal_size);
651
652       if (size < nal_size)
653         goto avcc_error;
654
655       /* make a buffer out of it and add to PPS list */
656       pps_buf = gst_buffer_new_and_alloc (nal_size);
657       gst_buffer_fill (pps_buf, 0, data, nal_size);
658       gst_rtp_h264_add_sps_pps (GST_ELEMENT (rtph264pay), rtph264pay->sps,
659           rtph264pay->pps, pps_buf);
660
661       data += nal_size;
662       size -= nal_size;
663     }
664
665     /* and update the caps with the collected data */
666     if (!gst_rtp_h264_pay_set_sps_pps (basepayload))
667       goto set_sps_pps_failed;
668
669     gst_buffer_unmap (buffer, &map);
670   } else {
671     GST_DEBUG_OBJECT (rtph264pay, "have bytestream h264");
672   }
673
674   return TRUE;
675
676 avcc_too_small:
677   {
678     GST_ERROR_OBJECT (rtph264pay, "avcC size %" G_GSIZE_FORMAT " < 7", size);
679     goto error;
680   }
681 wrong_version:
682   {
683     GST_ERROR_OBJECT (rtph264pay, "wrong avcC version");
684     goto error;
685   }
686 avcc_error:
687   {
688     GST_ERROR_OBJECT (rtph264pay, "avcC too small ");
689     goto error;
690   }
691 set_sps_pps_failed:
692   {
693     GST_ERROR_OBJECT (rtph264pay, "failed to set sps/pps");
694     goto error;
695   }
696 error:
697   {
698     gst_buffer_unmap (buffer, &map);
699     return FALSE;
700   }
701 }
702
703 static void
704 gst_rtp_h264_pay_parse_sprop_parameter_sets (GstRtpH264Pay * rtph264pay)
705 {
706   const gchar *ps;
707   gchar **params;
708   guint len;
709   gint i;
710   GstBuffer *buf;
711
712   ps = rtph264pay->sprop_parameter_sets;
713   if (ps == NULL)
714     return;
715
716   gst_rtp_h264_pay_clear_sps_pps (rtph264pay);
717
718   params = g_strsplit (ps, ",", 0);
719   len = g_strv_length (params);
720
721   GST_DEBUG_OBJECT (rtph264pay, "we have %d params", len);
722
723   for (i = 0; params[i]; i++) {
724     gsize nal_len;
725     GstMapInfo map;
726     guint8 *nalp;
727     guint save = 0;
728     gint state = 0;
729
730     nal_len = strlen (params[i]);
731     buf = gst_buffer_new_and_alloc (nal_len);
732
733     gst_buffer_map (buf, &map, GST_MAP_WRITE);
734     nalp = map.data;
735     nal_len = g_base64_decode_step (params[i], nal_len, nalp, &state, &save);
736     gst_buffer_unmap (buf, &map);
737     gst_buffer_resize (buf, 0, nal_len);
738
739     if (!nal_len) {
740       gst_buffer_unref (buf);
741       continue;
742     }
743
744     gst_rtp_h264_add_sps_pps (GST_ELEMENT (rtph264pay), rtph264pay->sps,
745         rtph264pay->pps, buf);
746   }
747   g_strfreev (params);
748 }
749
750 static guint
751 next_start_code (const guint8 * data, guint size)
752 {
753   /* Boyer-Moore string matching algorithm, in a degenerative
754    * sense because our search 'alphabet' is binary - 0 & 1 only.
755    * This allow us to simplify the general BM algorithm to a very
756    * simple form. */
757   /* assume 1 is in the 3th byte */
758   guint offset = 2;
759
760   while (offset < size) {
761     if (1 == data[offset]) {
762       unsigned int shift = offset;
763
764       if (0 == data[--shift]) {
765         if (0 == data[--shift]) {
766           return shift;
767         }
768       }
769       /* The jump is always 3 because of the 1 previously matched.
770        * All the 0's must be after this '1' matched at offset */
771       offset += 3;
772     } else if (0 == data[offset]) {
773       /* maybe next byte is 1? */
774       offset++;
775     } else {
776       /* can jump 3 bytes forward */
777       offset += 3;
778     }
779     /* at each iteration, we rescan in a backward manner until
780      * we match 0.0.1 in reverse order. Since our search string
781      * has only 2 'alpabets' (i.e. 0 & 1), we know that any
782      * mismatch will force us to shift a fixed number of steps */
783   }
784   GST_DEBUG ("Cannot find next NAL start code. returning %u", size);
785
786   return size;
787 }
788
789 static gboolean
790 gst_rtp_h264_pay_decode_nal (GstRtpH264Pay * payloader,
791     const guint8 * data, guint size, GstClockTime dts, GstClockTime pts)
792 {
793   guint8 header, type;
794   gboolean updated;
795
796   /* default is no update */
797   updated = FALSE;
798
799   GST_DEBUG ("NAL payload len=%u", size);
800
801   header = data[0];
802   type = header & 0x1f;
803
804   /* We record the timestamp of the last SPS/PPS so
805    * that we can insert them at regular intervals and when needed. */
806   if (SPS_TYPE_ID == type || PPS_TYPE_ID == type) {
807     GstBuffer *nal;
808
809     /* trailing 0x0 are not part of the SPS/PPS */
810     while (size > 0 && data[size - 1] == 0x0)
811       size--;
812
813     /* encode the entire SPS NAL in base64 */
814     GST_DEBUG ("Found %s %x %x %x Len=%u", type == SPS_TYPE_ID ? "SPS" : "PPS",
815         (header >> 7), (header >> 5) & 3, type, size);
816
817     nal = gst_buffer_new_allocate (NULL, size, NULL);
818     gst_buffer_fill (nal, 0, data, size);
819
820     updated = gst_rtp_h264_add_sps_pps (GST_ELEMENT (payloader),
821         payloader->sps, payloader->pps, nal);
822
823     /* remember when we last saw SPS */
824     if (pts != -1)
825       payloader->last_spspps =
826           gst_segment_to_running_time (&GST_RTP_BASE_PAYLOAD_CAST
827           (payloader)->segment, GST_FORMAT_TIME, pts);
828   } else {
829     GST_DEBUG ("NAL: %x %x %x Len = %u", (header >> 7),
830         (header >> 5) & 3, type, size);
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     gboolean delta_unit, gboolean discont);
840
841 static GstFlowReturn
842 gst_rtp_h264_pay_payload_nal_single (GstRTPBasePayload * basepayload,
843     GstBuffer * paybuf, GstClockTime dts, GstClockTime pts, gboolean end_of_au,
844     gboolean delta_unit, gboolean discont);
845
846 static GstFlowReturn
847 gst_rtp_h264_pay_payload_nal_fragment (GstRTPBasePayload * basepayload,
848     GstBuffer * paybuf, GstClockTime dts, GstClockTime pts, gboolean end_of_au,
849     gboolean delta_unit, gboolean discont, guint8 nal_header);
850
851 static GstFlowReturn
852 gst_rtp_h264_pay_payload_nal_bundle (GstRTPBasePayload * basepayload,
853     GstBuffer * paybuf, GstClockTime dts, GstClockTime pts, gboolean end_of_au,
854     gboolean delta_unit, gboolean discont, guint8 nal_header);
855
856 static GstFlowReturn
857 gst_rtp_h264_pay_send_sps_pps (GstRTPBasePayload * basepayload,
858     GstClockTime dts, GstClockTime pts, gboolean delta_unit, gboolean discont)
859 {
860   GstRtpH264Pay *rtph264pay = GST_RTP_H264_PAY (basepayload);
861   GstFlowReturn ret = GST_FLOW_OK;
862   gboolean sent_all_sps_pps = TRUE;
863   guint i;
864
865   for (i = 0; i < rtph264pay->sps->len; i++) {
866     GstBuffer *sps_buf =
867         GST_BUFFER_CAST (g_ptr_array_index (rtph264pay->sps, i));
868
869     GST_DEBUG_OBJECT (rtph264pay, "inserting SPS in the stream");
870     /* resend SPS */
871     ret = gst_rtp_h264_pay_payload_nal (basepayload, gst_buffer_ref (sps_buf),
872         dts, pts, FALSE, delta_unit, discont);
873     /* Not critical here; but throw a warning */
874     if (ret != GST_FLOW_OK) {
875       sent_all_sps_pps = FALSE;
876       GST_WARNING_OBJECT (basepayload, "Problem pushing SPS");
877     }
878   }
879   for (i = 0; i < rtph264pay->pps->len; i++) {
880     GstBuffer *pps_buf =
881         GST_BUFFER_CAST (g_ptr_array_index (rtph264pay->pps, i));
882
883     GST_DEBUG_OBJECT (rtph264pay, "inserting PPS in the stream");
884     /* resend PPS */
885     ret = gst_rtp_h264_pay_payload_nal (basepayload, gst_buffer_ref (pps_buf),
886         dts, pts, FALSE, TRUE, FALSE);
887     /* Not critical here; but throw a warning */
888     if (ret != GST_FLOW_OK) {
889       sent_all_sps_pps = FALSE;
890       GST_WARNING_OBJECT (basepayload, "Problem pushing PPS");
891     }
892   }
893
894   if (pts != -1 && sent_all_sps_pps)
895     rtph264pay->last_spspps =
896         gst_segment_to_running_time (&basepayload->segment, GST_FORMAT_TIME,
897         pts);
898
899   return ret;
900 }
901
902 /* @delta_unit: if %FALSE the first packet sent won't have the
903  * GST_BUFFER_FLAG_DELTA_UNIT flag.
904  * @discont: if %TRUE the first packet sent will have the
905  * GST_BUFFER_FLAG_DISCONT flag.
906  */
907 static GstFlowReturn
908 gst_rtp_h264_pay_payload_nal (GstRTPBasePayload * basepayload,
909     GstBuffer * paybuf, GstClockTime dts, GstClockTime pts, gboolean end_of_au,
910     gboolean delta_unit, gboolean discont)
911 {
912   GstRtpH264Pay *rtph264pay;
913   guint8 nal_header, nal_type;
914   gboolean send_spspps;
915   guint size;
916
917   rtph264pay = GST_RTP_H264_PAY (basepayload);
918   size = gst_buffer_get_size (paybuf);
919
920   gst_buffer_extract (paybuf, 0, &nal_header, 1);
921   nal_type = nal_header & 0x1f;
922
923   /* These payload type are reserved for STAP-A, STAP-B, MTAP16, and MTAP24
924    * as internally used NAL types */
925   switch (nal_type) {
926     case 24:
927     case 25:
928     case 26:
929     case 27:
930       GST_WARNING_OBJECT (rtph264pay, "Ignoring reserved NAL TYPE=%d",
931           nal_type);
932       gst_buffer_unref (paybuf);
933       return GST_FLOW_OK;
934     default:
935       break;
936   }
937
938   GST_DEBUG_OBJECT (rtph264pay,
939       "payloading NAL Unit: datasize=%u type=%d pts=%" GST_TIME_FORMAT,
940       size, nal_type, GST_TIME_ARGS (pts));
941
942   /* should set src caps before pushing stuff,
943    * and if we did not see enough SPS/PPS, that may not be the case */
944   if (G_UNLIKELY (!gst_pad_has_current_caps (GST_RTP_BASE_PAYLOAD_SRCPAD
945               (basepayload))))
946     gst_rtp_h264_pay_set_sps_pps (basepayload);
947
948   send_spspps = FALSE;
949
950   /* check if we need to emit an SPS/PPS now */
951   if (nal_type == IDR_TYPE_ID && rtph264pay->spspps_interval > 0) {
952     if (rtph264pay->last_spspps != -1) {
953       guint64 diff;
954       GstClockTime running_time =
955           gst_segment_to_running_time (&basepayload->segment, GST_FORMAT_TIME,
956           pts);
957
958       GST_LOG_OBJECT (rtph264pay,
959           "now %" GST_TIME_FORMAT ", last SPS/PPS %" GST_TIME_FORMAT,
960           GST_TIME_ARGS (running_time),
961           GST_TIME_ARGS (rtph264pay->last_spspps));
962
963       /* calculate diff between last SPS/PPS in milliseconds */
964       if (running_time > rtph264pay->last_spspps)
965         diff = running_time - rtph264pay->last_spspps;
966       else
967         diff = 0;
968
969       GST_DEBUG_OBJECT (rtph264pay,
970           "interval since last SPS/PPS %" GST_TIME_FORMAT,
971           GST_TIME_ARGS (diff));
972
973       /* bigger than interval, queue SPS/PPS */
974       if (GST_TIME_AS_SECONDS (diff) >= rtph264pay->spspps_interval) {
975         GST_DEBUG_OBJECT (rtph264pay, "time to send SPS/PPS");
976         send_spspps = TRUE;
977       }
978     } else {
979       /* no know previous SPS/PPS time, send now */
980       GST_DEBUG_OBJECT (rtph264pay, "no previous SPS/PPS time, send now");
981       send_spspps = TRUE;
982     }
983   } else if (nal_type == IDR_TYPE_ID && rtph264pay->spspps_interval == -1) {
984     GST_DEBUG_OBJECT (rtph264pay, "sending SPS/PPS before current IDR frame");
985     /* send SPS/PPS before every IDR frame */
986     send_spspps = TRUE;
987   }
988
989   if (send_spspps || rtph264pay->send_spspps) {
990     /* we need to send SPS/PPS now first. FIXME, don't use the pts for
991      * checking when we need to send SPS/PPS but convert to running_time first. */
992     GstFlowReturn ret;
993
994     rtph264pay->send_spspps = FALSE;
995
996     ret = gst_rtp_h264_pay_send_sps_pps (basepayload, dts, pts, delta_unit,
997         discont);
998     if (ret != GST_FLOW_OK) {
999       gst_buffer_unref (paybuf);
1000       return ret;
1001     }
1002
1003     delta_unit = TRUE;
1004     discont = FALSE;
1005   }
1006
1007   if (rtph264pay->aggregate_mode != GST_RTP_H264_AGGREGATE_NONE)
1008     return gst_rtp_h264_pay_payload_nal_bundle (basepayload, paybuf, dts, pts,
1009         end_of_au, delta_unit, discont, nal_header);
1010
1011   return gst_rtp_h264_pay_payload_nal_fragment (basepayload, paybuf, dts, pts,
1012       end_of_au, delta_unit, discont, nal_header);
1013 }
1014
1015 static GstFlowReturn
1016 gst_rtp_h264_pay_payload_nal_fragment (GstRTPBasePayload * basepayload,
1017     GstBuffer * paybuf, GstClockTime dts, GstClockTime pts, gboolean end_of_au,
1018     gboolean delta_unit, gboolean discont, guint8 nal_header)
1019 {
1020   GstRtpH264Pay *rtph264pay;
1021   guint mtu, size, max_fragment_size, max_fragments, ii, pos;
1022   GstBuffer *outbuf;
1023   guint8 *payload;
1024   GstBufferList *list = NULL;
1025   GstRTPBuffer rtp = { NULL };
1026
1027   rtph264pay = GST_RTP_H264_PAY (basepayload);
1028   mtu = GST_RTP_BASE_PAYLOAD_MTU (rtph264pay);
1029   size = gst_buffer_get_size (paybuf);
1030
1031   if (gst_rtp_buffer_calc_packet_len (size, 0, 0) <= mtu) {
1032     /* We don't need to fragment this packet */
1033     GST_DEBUG_OBJECT (rtph264pay,
1034         "sending NAL Unit: datasize=%u mtu=%u", size, mtu);
1035     return gst_rtp_h264_pay_payload_nal_single (basepayload, paybuf, dts, pts,
1036         end_of_au, delta_unit, discont);
1037   }
1038
1039   GST_DEBUG_OBJECT (basepayload,
1040       "using FU-A fragmentation for NAL Unit: datasize=%u mtu=%u", size, mtu);
1041
1042   /* We keep 2 bytes for FU indicator and FU Header */
1043   max_fragment_size = gst_rtp_buffer_calc_payload_len (mtu - 2, 0, 0);
1044   max_fragments = (size + max_fragment_size - 2) / max_fragment_size;
1045   list = gst_buffer_list_new_sized (max_fragments);
1046
1047   /* Start at the NALU payload */
1048   for (pos = 1, ii = 0; pos < size; pos += max_fragment_size, ii++) {
1049     guint remaining, fragment_size;
1050     gboolean first_fragment, last_fragment;
1051
1052     remaining = size - pos;
1053     fragment_size = MIN (remaining, max_fragment_size);
1054     first_fragment = (pos == 1);
1055     last_fragment = (remaining <= max_fragment_size);
1056
1057     GST_DEBUG_OBJECT (basepayload,
1058         "creating FU-A packet %u/%u, size %u",
1059         ii + 1, max_fragments, fragment_size);
1060
1061     /* use buffer lists
1062      * create buffer without payload containing only the RTP header
1063      * (memory block at index 0) */
1064     outbuf = gst_rtp_buffer_new_allocate (2, 0, 0);
1065
1066     gst_rtp_buffer_map (outbuf, GST_MAP_WRITE, &rtp);
1067
1068     GST_BUFFER_DTS (outbuf) = dts;
1069     GST_BUFFER_PTS (outbuf) = pts;
1070     payload = gst_rtp_buffer_get_payload (&rtp);
1071
1072     /* If it's the last fragment and the end of this au, mark the end of
1073      * slice */
1074     gst_rtp_buffer_set_marker (&rtp, last_fragment && end_of_au);
1075
1076     /* FU indicator */
1077     payload[0] = (nal_header & 0x60) | FU_A_TYPE_ID;
1078
1079     /* FU Header */
1080     payload[1] = (first_fragment << 7) | (last_fragment << 6) |
1081         (nal_header & 0x1f);
1082
1083     gst_rtp_buffer_unmap (&rtp);
1084
1085     /* insert payload memory block */
1086     gst_rtp_copy_video_meta (rtph264pay, outbuf, paybuf);
1087     gst_buffer_copy_into (outbuf, paybuf, GST_BUFFER_COPY_MEMORY, pos,
1088         fragment_size);
1089
1090     if (!delta_unit)
1091       /* Only the first packet sent should not have the flag */
1092       delta_unit = TRUE;
1093     else
1094       GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DELTA_UNIT);
1095
1096     if (discont) {
1097       GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT);
1098       /* Only the first packet sent should have the flag */
1099       discont = FALSE;
1100     }
1101
1102     /* add the buffer to the buffer list */
1103     gst_buffer_list_add (list, outbuf);
1104   }
1105
1106   GST_DEBUG_OBJECT (rtph264pay,
1107       "sending FU-A fragments: n=%u datasize=%u mtu=%u", ii, size, mtu);
1108
1109   gst_buffer_unref (paybuf);
1110   return gst_rtp_base_payload_push_list (basepayload, list);
1111 }
1112
1113 static GstFlowReturn
1114 gst_rtp_h264_pay_payload_nal_single (GstRTPBasePayload * basepayload,
1115     GstBuffer * paybuf, GstClockTime dts, GstClockTime pts, gboolean end_of_au,
1116     gboolean delta_unit, gboolean discont)
1117 {
1118   GstRtpH264Pay *rtph264pay;
1119   GstBuffer *outbuf;
1120   GstRTPBuffer rtp = { NULL };
1121
1122   rtph264pay = GST_RTP_H264_PAY (basepayload);
1123
1124   /* create buffer without payload containing only the RTP header
1125    * (memory block at index 0) */
1126   outbuf = gst_rtp_buffer_new_allocate (0, 0, 0);
1127
1128   gst_rtp_buffer_map (outbuf, GST_MAP_WRITE, &rtp);
1129
1130   /* Mark the end of a frame */
1131   gst_rtp_buffer_set_marker (&rtp, end_of_au);
1132
1133   /* timestamp the outbuffer */
1134   GST_BUFFER_PTS (outbuf) = pts;
1135   GST_BUFFER_DTS (outbuf) = dts;
1136
1137   if (delta_unit)
1138     GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DELTA_UNIT);
1139
1140   if (discont)
1141     GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT);
1142
1143   gst_rtp_buffer_unmap (&rtp);
1144
1145   /* insert payload memory block */
1146   gst_rtp_copy_video_meta (rtph264pay, outbuf, paybuf);
1147   outbuf = gst_buffer_append (outbuf, paybuf);
1148
1149   /* push the buffer to the next element */
1150   return gst_rtp_base_payload_push (basepayload, outbuf);
1151 }
1152
1153 static void
1154 gst_rtp_h264_pay_reset_bundle (GstRtpH264Pay * rtph264pay)
1155 {
1156   g_clear_pointer (&rtph264pay->bundle, gst_buffer_list_unref);
1157   rtph264pay->bundle_size = 0;
1158   rtph264pay->bundle_contains_vcl = FALSE;
1159 }
1160
1161 static GstFlowReturn
1162 gst_rtp_h264_pay_send_bundle (GstRtpH264Pay * rtph264pay, gboolean end_of_au)
1163 {
1164   GstRTPBasePayload *basepayload;
1165   GstBufferList *bundle;
1166   guint length, bundle_size;
1167   GstBuffer *first, *outbuf;
1168   GstClockTime dts, pts;
1169   gboolean delta, discont;
1170
1171   bundle_size = rtph264pay->bundle_size;
1172
1173   if (bundle_size == 0) {
1174     GST_DEBUG_OBJECT (rtph264pay, "no bundle, nothing to send");
1175     return GST_FLOW_OK;
1176   }
1177
1178   basepayload = GST_RTP_BASE_PAYLOAD (rtph264pay);
1179   bundle = rtph264pay->bundle;
1180   length = gst_buffer_list_length (bundle);
1181
1182   first = gst_buffer_list_get (bundle, 0);
1183   dts = GST_BUFFER_DTS (first);
1184   pts = GST_BUFFER_PTS (first);
1185   delta = GST_BUFFER_FLAG_IS_SET (first, GST_BUFFER_FLAG_DELTA_UNIT);
1186   discont = GST_BUFFER_FLAG_IS_SET (first, GST_BUFFER_FLAG_DISCONT);
1187
1188   if (length == 1) {
1189     /* Push unaggregated NALU */
1190     outbuf = gst_buffer_ref (first);
1191
1192     GST_DEBUG_OBJECT (rtph264pay,
1193         "sending NAL Unit unaggregated: datasize=%u", bundle_size - 2);
1194   } else {
1195     guint8 stap_header;
1196     guint i;
1197
1198     outbuf = gst_buffer_new_allocate (NULL, sizeof stap_header, NULL);
1199     stap_header = STAP_A_TYPE_ID;
1200
1201     for (i = 0; i < length; i++) {
1202       GstBuffer *buf = gst_buffer_list_get (bundle, i);
1203       guint8 nal_header;
1204       GstMemory *size_header;
1205       GstMapInfo map;
1206
1207       gst_buffer_extract (buf, 0, &nal_header, sizeof nal_header);
1208
1209       /* Propagate F bit */
1210       if ((nal_header & 0x80))
1211         stap_header |= 0x80;
1212
1213       /* Select highest nal_ref_idc */
1214       if ((nal_header & 0x60) > (stap_header & 0x60))
1215         stap_header = (stap_header & 0x9f) | (nal_header & 0x60);
1216
1217       /* append NALU size */
1218       size_header = gst_allocator_alloc (NULL, 2, NULL);
1219       gst_memory_map (size_header, &map, GST_MAP_WRITE);
1220       GST_WRITE_UINT16_BE (map.data, gst_buffer_get_size (buf));
1221       gst_memory_unmap (size_header, &map);
1222       gst_buffer_append_memory (outbuf, size_header);
1223
1224       /* append NALU data */
1225       outbuf = gst_buffer_append (outbuf, gst_buffer_ref (buf));
1226     }
1227
1228     gst_buffer_fill (outbuf, 0, &stap_header, sizeof stap_header);
1229
1230     GST_DEBUG_OBJECT (rtph264pay,
1231         "sending STAP-A bundle: n=%u header=%02x datasize=%u",
1232         length, stap_header, bundle_size);
1233   }
1234
1235   gst_rtp_h264_pay_reset_bundle (rtph264pay);
1236   return gst_rtp_h264_pay_payload_nal_single (basepayload, outbuf, dts, pts,
1237       end_of_au, delta, discont);
1238 }
1239
1240 static gboolean
1241 gst_rtp_h264_pay_payload_nal_bundle (GstRTPBasePayload * basepayload,
1242     GstBuffer * paybuf, GstClockTime dts, GstClockTime pts, gboolean end_of_au,
1243     gboolean delta_unit, gboolean discont, guint8 nal_header)
1244 {
1245   GstRtpH264Pay *rtph264pay;
1246   GstFlowReturn ret;
1247   guint mtu, pay_size, bundle_size;
1248   GstBufferList *bundle;
1249   guint8 nal_type;
1250   gboolean start_of_au;
1251
1252   rtph264pay = GST_RTP_H264_PAY (basepayload);
1253   nal_type = nal_header & 0x1f;
1254   mtu = GST_RTP_BASE_PAYLOAD_MTU (rtph264pay);
1255   pay_size = 2 + gst_buffer_get_size (paybuf);
1256   bundle = rtph264pay->bundle;
1257   start_of_au = FALSE;
1258
1259   if (bundle) {
1260     GstBuffer *first = gst_buffer_list_get (bundle, 0);
1261
1262     if (nal_type == AUD_TYPE_ID) {
1263       GST_DEBUG_OBJECT (rtph264pay, "found access delimiter");
1264       start_of_au = TRUE;
1265     } else if (discont) {
1266       GST_DEBUG_OBJECT (rtph264pay, "found discont");
1267       start_of_au = TRUE;
1268     } else if (GST_BUFFER_PTS (first) != pts || GST_BUFFER_DTS (first) != dts) {
1269       GST_DEBUG_OBJECT (rtph264pay, "found timestamp mismatch");
1270       start_of_au = TRUE;
1271     }
1272   }
1273
1274   if (start_of_au) {
1275     GST_DEBUG_OBJECT (rtph264pay, "sending bundle before start of AU");
1276
1277     ret = gst_rtp_h264_pay_send_bundle (rtph264pay, TRUE);
1278     if (ret != GST_FLOW_OK)
1279       goto out;
1280
1281     bundle = NULL;
1282   }
1283
1284   bundle_size = 1 + pay_size;
1285
1286   if (gst_rtp_buffer_calc_packet_len (bundle_size, 0, 0) > mtu) {
1287     GST_DEBUG_OBJECT (rtph264pay, "NAL Unit cannot fit in a bundle");
1288
1289     ret = gst_rtp_h264_pay_send_bundle (rtph264pay, FALSE);
1290     if (ret != GST_FLOW_OK)
1291       goto out;
1292
1293     return gst_rtp_h264_pay_payload_nal_fragment (basepayload, paybuf, dts, pts,
1294         end_of_au, delta_unit, discont, nal_header);
1295   }
1296
1297   bundle_size = rtph264pay->bundle_size + pay_size;
1298
1299   if (gst_rtp_buffer_calc_packet_len (bundle_size, 0, 0) > mtu) {
1300     GST_DEBUG_OBJECT (rtph264pay,
1301         "bundle overflows, sending: bundlesize=%u datasize=2+%u mtu=%u",
1302         rtph264pay->bundle_size, pay_size - 2, mtu);
1303
1304     ret = gst_rtp_h264_pay_send_bundle (rtph264pay, FALSE);
1305     if (ret != GST_FLOW_OK)
1306       goto out;
1307
1308     bundle = NULL;
1309   }
1310
1311   if (!bundle) {
1312     GST_DEBUG_OBJECT (rtph264pay, "creating new STAP-A aggregate");
1313     bundle = rtph264pay->bundle = gst_buffer_list_new ();
1314     bundle_size = rtph264pay->bundle_size = 1;
1315     rtph264pay->bundle_contains_vcl = FALSE;
1316   }
1317
1318   GST_DEBUG_OBJECT (rtph264pay,
1319       "bundling NAL Unit: bundlesize=%u datasize=2+%u mtu=%u",
1320       rtph264pay->bundle_size, pay_size - 2, mtu);
1321
1322   paybuf = gst_buffer_make_writable (paybuf);
1323   GST_BUFFER_PTS (paybuf) = pts;
1324   GST_BUFFER_DTS (paybuf) = dts;
1325
1326   if (delta_unit)
1327     GST_BUFFER_FLAG_SET (paybuf, GST_BUFFER_FLAG_DELTA_UNIT);
1328   else
1329     GST_BUFFER_FLAG_UNSET (paybuf, GST_BUFFER_FLAG_DELTA_UNIT);
1330
1331   if (discont)
1332     GST_BUFFER_FLAG_SET (paybuf, GST_BUFFER_FLAG_DISCONT);
1333   else
1334     GST_BUFFER_FLAG_UNSET (paybuf, GST_BUFFER_FLAG_DISCONT);
1335
1336   gst_buffer_list_add (bundle, gst_buffer_ref (paybuf));
1337   rtph264pay->bundle_size += pay_size;
1338   ret = GST_FLOW_OK;
1339
1340   if ((nal_type >= 1 && nal_type <= 5) || nal_type == 14 ||
1341       (nal_type >= 20 && nal_type <= 23))
1342     rtph264pay->bundle_contains_vcl = TRUE;
1343
1344   if (end_of_au) {
1345     GST_DEBUG_OBJECT (rtph264pay, "sending bundle at end of AU");
1346     ret = gst_rtp_h264_pay_send_bundle (rtph264pay, TRUE);
1347   }
1348
1349 out:
1350   gst_buffer_unref (paybuf);
1351   return ret;
1352 }
1353
1354 static GstFlowReturn
1355 gst_rtp_h264_pay_handle_buffer (GstRTPBasePayload * basepayload,
1356     GstBuffer * buffer)
1357 {
1358   GstRtpH264Pay *rtph264pay;
1359   GstFlowReturn ret;
1360   gsize size;
1361   guint nal_len, i;
1362   const guint8 *data;
1363   GstClockTime dts, pts;
1364   GArray *nal_queue;
1365   gboolean avc;
1366   GstBuffer *paybuf = NULL;
1367   gsize skip;
1368   gboolean delayed_not_delta_unit = FALSE;
1369   gboolean delayed_discont = FALSE;
1370   gboolean marker = FALSE;
1371   gboolean draining = (buffer == NULL);
1372
1373   rtph264pay = GST_RTP_H264_PAY (basepayload);
1374
1375   /* the input buffer contains one or more NAL units */
1376
1377   avc = rtph264pay->stream_format == GST_H264_STREAM_FORMAT_AVC;
1378
1379   if (avc) {
1380     /* In AVC mode, there is no adapter, so nothing to drain */
1381     if (draining)
1382       return GST_FLOW_OK;
1383   } else {
1384     if (buffer) {
1385       if (!GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT)) {
1386         if (gst_adapter_available (rtph264pay->adapter) == 0)
1387           rtph264pay->delta_unit = FALSE;
1388         else
1389           /* This buffer contains a key frame but the adapter isn't empty. So
1390            * we'll purge it first by sending a first packet and then the second
1391            * one won't have the DELTA_UNIT flag. */
1392           delayed_not_delta_unit = TRUE;
1393       }
1394
1395       if (GST_BUFFER_IS_DISCONT (buffer)) {
1396         if (gst_adapter_available (rtph264pay->adapter) == 0)
1397           rtph264pay->discont = TRUE;
1398         else
1399           /* This buffer has the DISCONT flag but the adapter isn't empty. So
1400            * we'll purge it first by sending a first packet and then the second
1401            * one will have the DISCONT flag set. */
1402           delayed_discont = TRUE;
1403       }
1404
1405       marker = GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_MARKER);
1406       gst_adapter_push (rtph264pay->adapter, buffer);
1407       buffer = NULL;
1408     }
1409
1410     /* We want to use the first TS used to construct the following NAL */
1411     dts = gst_adapter_prev_dts (rtph264pay->adapter, NULL);
1412     pts = gst_adapter_prev_pts (rtph264pay->adapter, NULL);
1413
1414     size = gst_adapter_available (rtph264pay->adapter);
1415     /* Nothing to do here if the adapter is empty, e.g. on EOS */
1416     if (size == 0)
1417       return GST_FLOW_OK;
1418     data = gst_adapter_map (rtph264pay->adapter, size);
1419     GST_DEBUG_OBJECT (basepayload, "got %" G_GSIZE_FORMAT " bytes", size);
1420   }
1421
1422   ret = GST_FLOW_OK;
1423
1424   /* now loop over all NAL units and put them in a packet */
1425   if (avc) {
1426     GstBufferMemoryMap memory;
1427     gsize remaining_buffer_size;
1428     guint nal_length_size;
1429     gsize offset = 0;
1430
1431     gst_buffer_memory_map (buffer, &memory);
1432     remaining_buffer_size = gst_buffer_get_size (buffer);
1433
1434     pts = GST_BUFFER_PTS (buffer);
1435     dts = GST_BUFFER_DTS (buffer);
1436     rtph264pay->delta_unit = GST_BUFFER_FLAG_IS_SET (buffer,
1437         GST_BUFFER_FLAG_DELTA_UNIT);
1438     rtph264pay->discont = GST_BUFFER_IS_DISCONT (buffer);
1439     marker = GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_MARKER);
1440     GST_DEBUG_OBJECT (basepayload, "got %" G_GSIZE_FORMAT " bytes",
1441         remaining_buffer_size);
1442
1443     nal_length_size = rtph264pay->nal_length_size;
1444
1445     while (remaining_buffer_size > nal_length_size) {
1446       gint i;
1447       gboolean end_of_au = FALSE;
1448
1449       nal_len = 0;
1450       for (i = 0; i < nal_length_size; i++) {
1451         nal_len = (nal_len << 8) + *memory.data;
1452         if (!gst_buffer_memory_advance_bytes (&memory, 1))
1453           break;
1454       }
1455
1456       offset += nal_length_size;
1457       remaining_buffer_size -= nal_length_size;
1458
1459       if (remaining_buffer_size >= nal_len) {
1460         GST_DEBUG_OBJECT (basepayload, "got NAL of size %u", nal_len);
1461       } else {
1462         nal_len = remaining_buffer_size;
1463         GST_DEBUG_OBJECT (basepayload, "got incomplete NAL of size %u",
1464             nal_len);
1465       }
1466
1467       /* If we're at the end of the buffer, then we're at the end of the
1468        * access unit
1469        */
1470       if (remaining_buffer_size - nal_len <= nal_length_size) {
1471         if (rtph264pay->alignment == GST_H264_ALIGNMENT_AU || marker)
1472           end_of_au = TRUE;
1473       }
1474
1475       paybuf = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_ALL, offset,
1476           nal_len);
1477       ret =
1478           gst_rtp_h264_pay_payload_nal (basepayload, paybuf, dts, pts,
1479           end_of_au, rtph264pay->delta_unit, rtph264pay->discont);
1480
1481       if (!rtph264pay->delta_unit)
1482         /* Only the first outgoing packet doesn't have the DELTA_UNIT flag */
1483         rtph264pay->delta_unit = TRUE;
1484
1485       if (rtph264pay->discont)
1486         /* Only the first outgoing packet have the DISCONT flag */
1487         rtph264pay->discont = FALSE;
1488
1489       if (ret != GST_FLOW_OK)
1490         break;
1491
1492       /* Skip current nal. If it is split over multiple GstMemory
1493        * advance_bytes () will switch to the correct GstMemory. The payloader
1494        * does not access those bytes directly but uses gst_buffer_copy_region ()
1495        * to create a sub-buffer referencing the nal instead */
1496       if (!gst_buffer_memory_advance_bytes (&memory, nal_len))
1497         break;
1498
1499       offset += nal_len;
1500       remaining_buffer_size -= nal_len;
1501     }
1502
1503     gst_buffer_memory_unmap (&memory);
1504     gst_buffer_unref (buffer);
1505   } else {
1506     guint next;
1507     gboolean update = FALSE;
1508
1509     /* get offset of first start code */
1510     next = next_start_code (data, size);
1511
1512     /* skip to start code, if no start code is found, next will be size and we
1513      * will not collect data. */
1514     data += next;
1515     size -= next;
1516     nal_queue = rtph264pay->queue;
1517     skip = next;
1518
1519     /* array must be empty when we get here */
1520     g_assert (nal_queue->len == 0);
1521
1522     GST_DEBUG_OBJECT (basepayload,
1523         "found first start at %u, bytes left %" G_GSIZE_FORMAT, next, size);
1524
1525     /* first pass to locate NALs and parse SPS/PPS */
1526     while (size > 4) {
1527       /* skip start code */
1528       data += 3;
1529       size -= 3;
1530
1531       /* use next_start_code() to scan buffer.
1532        * next_start_code() returns the offset in data,
1533        * starting from zero to the first byte of 0.0.0.1
1534        * If no start code is found, it returns the value of the
1535        * 'size' parameter.
1536        * data is unchanged by the call to next_start_code()
1537        */
1538       next = next_start_code (data, size);
1539
1540       /* nal or au aligned input needs no delaying until next time */
1541       if (next == size && !draining &&
1542           rtph264pay->alignment == GST_H264_ALIGNMENT_UNKNOWN) {
1543         /* Didn't find the start of next NAL and it's not EOS,
1544          * handle it next time */
1545         break;
1546       }
1547
1548       /* nal length is distance to next start code */
1549       nal_len = next;
1550
1551       GST_DEBUG_OBJECT (basepayload, "found next start at %u of size %u", next,
1552           nal_len);
1553
1554       if (rtph264pay->sprop_parameter_sets != NULL) {
1555         /* explicitly set profile and sprop, use those */
1556         if (rtph264pay->update_caps) {
1557           if (!gst_rtp_base_payload_set_outcaps (basepayload,
1558                   "sprop-parameter-sets", G_TYPE_STRING,
1559                   rtph264pay->sprop_parameter_sets, NULL))
1560             goto caps_rejected;
1561
1562           /* parse SPS and PPS from provided parameter set (for insertion) */
1563           gst_rtp_h264_pay_parse_sprop_parameter_sets (rtph264pay);
1564
1565           rtph264pay->update_caps = FALSE;
1566
1567           GST_DEBUG ("outcaps update: sprop-parameter-sets=%s",
1568               rtph264pay->sprop_parameter_sets);
1569         }
1570       } else {
1571         /* We know our stream is a valid H264 NAL packet,
1572          * go parse it for SPS/PPS to enrich the caps */
1573         /* order: make sure to check nal */
1574         update =
1575             gst_rtp_h264_pay_decode_nal (rtph264pay, data, nal_len, dts, pts)
1576             || update;
1577       }
1578       /* move to next NAL packet */
1579       data += nal_len;
1580       size -= nal_len;
1581
1582       g_array_append_val (nal_queue, nal_len);
1583     }
1584
1585     /* if has new SPS & PPS, update the output caps */
1586     if (G_UNLIKELY (update))
1587       if (!gst_rtp_h264_pay_set_sps_pps (basepayload))
1588         goto caps_rejected;
1589
1590     /* second pass to payload and push */
1591
1592     if (nal_queue->len != 0)
1593       gst_adapter_flush (rtph264pay->adapter, skip);
1594
1595     for (i = 0; i < nal_queue->len; i++) {
1596       guint size;
1597       gboolean end_of_au = FALSE;
1598
1599       nal_len = g_array_index (nal_queue, guint, i);
1600       /* skip start code */
1601       gst_adapter_flush (rtph264pay->adapter, 3);
1602
1603       /* Trim the end unless we're the last NAL in the stream.
1604        * In case we're not at the end of the buffer we know the next block
1605        * starts with 0x000001 so all the 0x00 bytes at the end of this one are
1606        * trailing 0x0 that can be discarded */
1607       size = nal_len;
1608       data = gst_adapter_map (rtph264pay->adapter, size);
1609       if (i + 1 != nal_queue->len || !draining)
1610         for (; size > 1 && data[size - 1] == 0x0; size--)
1611           /* skip */ ;
1612
1613
1614       /* If it's the last nal unit we have in non-bytestream mode, we can
1615        * assume it's the end of an access-unit
1616        *
1617        * FIXME: We need to wait until the next packet or EOS to
1618        * actually payload the NAL so we can know if the current NAL is
1619        * the last one of an access unit or not if we are in bytestream mode
1620        */
1621       if (i == nal_queue->len - 1) {
1622         if (rtph264pay->alignment == GST_H264_ALIGNMENT_AU ||
1623             marker || draining)
1624           end_of_au = TRUE;
1625       }
1626       paybuf = gst_adapter_take_buffer (rtph264pay->adapter, size);
1627       g_assert (paybuf);
1628
1629       /* put the data in one or more RTP packets */
1630       ret =
1631           gst_rtp_h264_pay_payload_nal (basepayload, paybuf, dts, pts,
1632           end_of_au, rtph264pay->delta_unit, rtph264pay->discont);
1633
1634       if (delayed_not_delta_unit) {
1635         rtph264pay->delta_unit = FALSE;
1636         delayed_not_delta_unit = FALSE;
1637       } else {
1638         /* Only the first outgoing packet doesn't have the DELTA_UNIT flag */
1639         rtph264pay->delta_unit = TRUE;
1640       }
1641
1642       if (delayed_discont) {
1643         rtph264pay->discont = TRUE;
1644         delayed_discont = FALSE;
1645       } else {
1646         /* Only the first outgoing packet have the DISCONT flag */
1647         rtph264pay->discont = FALSE;
1648       }
1649
1650       if (ret != GST_FLOW_OK) {
1651         break;
1652       }
1653
1654       /* move to next NAL packet */
1655       /* Skips the trailing zeros */
1656       gst_adapter_flush (rtph264pay->adapter, nal_len - size);
1657     }
1658     g_array_set_size (nal_queue, 0);
1659   }
1660
1661   if (ret == GST_FLOW_OK && rtph264pay->bundle_size > 0 &&
1662       rtph264pay->aggregate_mode == GST_RTP_H264_AGGREGATE_ZERO_LATENCY &&
1663       rtph264pay->bundle_contains_vcl) {
1664     GST_DEBUG_OBJECT (rtph264pay, "sending bundle at end incoming packet");
1665     ret = gst_rtp_h264_pay_send_bundle (rtph264pay, FALSE);
1666   }
1667
1668
1669 done:
1670   if (!avc) {
1671     gst_adapter_unmap (rtph264pay->adapter);
1672   }
1673
1674   return ret;
1675
1676 caps_rejected:
1677   {
1678     GST_WARNING_OBJECT (basepayload, "Could not set outcaps");
1679     g_array_set_size (nal_queue, 0);
1680     ret = GST_FLOW_NOT_NEGOTIATED;
1681     goto done;
1682   }
1683 }
1684
1685 static gboolean
1686 gst_rtp_h264_pay_sink_event (GstRTPBasePayload * payload, GstEvent * event)
1687 {
1688   gboolean res;
1689   const GstStructure *s;
1690   GstRtpH264Pay *rtph264pay = GST_RTP_H264_PAY (payload);
1691   GstFlowReturn ret = GST_FLOW_OK;
1692
1693   switch (GST_EVENT_TYPE (event)) {
1694     case GST_EVENT_FLUSH_STOP:
1695       gst_adapter_clear (rtph264pay->adapter);
1696       gst_rtp_h264_pay_reset_bundle (rtph264pay);
1697       break;
1698     case GST_EVENT_CUSTOM_DOWNSTREAM:
1699       s = gst_event_get_structure (event);
1700       if (gst_structure_has_name (s, "GstForceKeyUnit")) {
1701         gboolean resend_codec_data;
1702
1703         if (gst_structure_get_boolean (s, "all-headers",
1704                 &resend_codec_data) && resend_codec_data)
1705           rtph264pay->send_spspps = TRUE;
1706       }
1707       break;
1708     case GST_EVENT_EOS:
1709     {
1710       /* call handle_buffer with NULL to flush last NAL from adapter
1711        * in byte-stream mode
1712        */
1713       gst_rtp_h264_pay_handle_buffer (payload, NULL);
1714       ret = gst_rtp_h264_pay_send_bundle (rtph264pay, TRUE);
1715       break;
1716     }
1717     case GST_EVENT_STREAM_START:
1718       GST_DEBUG_OBJECT (rtph264pay, "New stream detected => Clear SPS and PPS");
1719       gst_rtp_h264_pay_clear_sps_pps (rtph264pay);
1720       ret = gst_rtp_h264_pay_send_bundle (rtph264pay, TRUE);
1721       break;
1722     default:
1723       break;
1724   }
1725
1726   if (ret != GST_FLOW_OK)
1727     return FALSE;
1728
1729   res = GST_RTP_BASE_PAYLOAD_CLASS (parent_class)->sink_event (payload, event);
1730
1731   return res;
1732 }
1733
1734 static GstStateChangeReturn
1735 gst_rtp_h264_pay_change_state (GstElement * element, GstStateChange transition)
1736 {
1737   GstStateChangeReturn ret;
1738   GstRtpH264Pay *rtph264pay = GST_RTP_H264_PAY (element);
1739
1740   switch (transition) {
1741     case GST_STATE_CHANGE_READY_TO_PAUSED:
1742       rtph264pay->send_spspps = FALSE;
1743       gst_adapter_clear (rtph264pay->adapter);
1744       gst_rtp_h264_pay_reset_bundle (rtph264pay);
1745       break;
1746     default:
1747       break;
1748   }
1749
1750   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
1751
1752   switch (transition) {
1753     case GST_STATE_CHANGE_PAUSED_TO_READY:
1754       rtph264pay->last_spspps = -1;
1755       gst_rtp_h264_pay_clear_sps_pps (rtph264pay);
1756       break;
1757     default:
1758       break;
1759   }
1760
1761   return ret;
1762 }
1763
1764 static void
1765 gst_rtp_h264_pay_set_property (GObject * object, guint prop_id,
1766     const GValue * value, GParamSpec * pspec)
1767 {
1768   GstRtpH264Pay *rtph264pay;
1769
1770   rtph264pay = GST_RTP_H264_PAY (object);
1771
1772   switch (prop_id) {
1773     case PROP_SPROP_PARAMETER_SETS:
1774       g_free (rtph264pay->sprop_parameter_sets);
1775       rtph264pay->sprop_parameter_sets = g_value_dup_string (value);
1776       rtph264pay->update_caps = TRUE;
1777       break;
1778     case PROP_CONFIG_INTERVAL:
1779       rtph264pay->spspps_interval = g_value_get_int (value);
1780       break;
1781     case PROP_AGGREGATE_MODE:
1782       rtph264pay->aggregate_mode = g_value_get_enum (value);
1783       break;
1784     default:
1785       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1786       break;
1787   }
1788 }
1789
1790 static void
1791 gst_rtp_h264_pay_get_property (GObject * object, guint prop_id,
1792     GValue * value, GParamSpec * pspec)
1793 {
1794   GstRtpH264Pay *rtph264pay;
1795
1796   rtph264pay = GST_RTP_H264_PAY (object);
1797
1798   switch (prop_id) {
1799     case PROP_SPROP_PARAMETER_SETS:
1800       g_value_set_string (value, rtph264pay->sprop_parameter_sets);
1801       break;
1802     case PROP_CONFIG_INTERVAL:
1803       g_value_set_int (value, rtph264pay->spspps_interval);
1804       break;
1805     case PROP_AGGREGATE_MODE:
1806       g_value_set_enum (value, rtph264pay->aggregate_mode);
1807       break;
1808     default:
1809       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1810       break;
1811   }
1812 }
1813
1814 gboolean
1815 gst_rtp_h264_pay_plugin_init (GstPlugin * plugin)
1816 {
1817   return gst_element_register (plugin, "rtph264pay",
1818       GST_RANK_SECONDARY, GST_TYPE_RTP_H264_PAY);
1819 }