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