rtpvrawpay: Add missing break
[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   guint i;
715
716   for (i = 0; i < rtph264pay->sps->len; i++) {
717     GstBuffer *sps_buf =
718         GST_BUFFER_CAST (g_ptr_array_index (rtph264pay->sps, i));
719
720     GST_DEBUG_OBJECT (rtph264pay, "inserting SPS in the stream");
721     /* resend SPS */
722     ret = gst_rtp_h264_pay_payload_nal (basepayload, gst_buffer_ref (sps_buf),
723         dts, pts, FALSE);
724     /* Not critical here; but throw a warning */
725     if (ret != GST_FLOW_OK)
726       GST_WARNING ("Problem pushing SPS");
727   }
728   for (i = 0; i < rtph264pay->pps->len; i++) {
729     GstBuffer *pps_buf =
730         GST_BUFFER_CAST (g_ptr_array_index (rtph264pay->pps, i));
731
732     GST_DEBUG_OBJECT (rtph264pay, "inserting PPS in the stream");
733     /* resend PPS */
734     ret = gst_rtp_h264_pay_payload_nal (basepayload, gst_buffer_ref (pps_buf),
735         dts, pts, FALSE);
736     /* Not critical here; but throw a warning */
737     if (ret != GST_FLOW_OK)
738       GST_WARNING ("Problem pushing PPS");
739   }
740
741   if (pts != -1)
742     rtph264pay->last_spspps = pts;
743
744   return ret;
745 }
746
747 static GstFlowReturn
748 gst_rtp_h264_pay_payload_nal (GstRTPBasePayload * basepayload,
749     GstBuffer * paybuf, GstClockTime dts, GstClockTime pts, gboolean end_of_au)
750 {
751   GstRtpH264Pay *rtph264pay;
752   GstFlowReturn ret;
753   guint8 nalHeader;
754   guint8 nalType;
755   guint packet_len, payload_len, mtu;
756   GstBuffer *outbuf;
757   guint8 *payload;
758   GstBufferList *list = NULL;
759   gboolean send_spspps;
760   GstRTPBuffer rtp = { NULL };
761   guint size = gst_buffer_get_size (paybuf);
762
763   rtph264pay = GST_RTP_H264_PAY (basepayload);
764   mtu = GST_RTP_BASE_PAYLOAD_MTU (rtph264pay);
765
766   gst_buffer_extract (paybuf, 0, &nalHeader, 1);
767   nalType = nalHeader & 0x1f;
768
769   GST_DEBUG_OBJECT (rtph264pay, "Processing Buffer with NAL TYPE=%d", nalType);
770
771   /* should set src caps before pushing stuff,
772    * and if we did not see enough SPS/PPS, that may not be the case */
773   if (G_UNLIKELY (!gst_pad_has_current_caps (GST_RTP_BASE_PAYLOAD_SRCPAD
774               (basepayload))))
775     gst_rtp_h264_pay_set_sps_pps (basepayload);
776
777   send_spspps = FALSE;
778
779   /* check if we need to emit an SPS/PPS now */
780   if (nalType == IDR_TYPE_ID && rtph264pay->spspps_interval > 0) {
781     if (rtph264pay->last_spspps != -1) {
782       guint64 diff;
783
784       GST_LOG_OBJECT (rtph264pay,
785           "now %" GST_TIME_FORMAT ", last SPS/PPS %" GST_TIME_FORMAT,
786           GST_TIME_ARGS (pts), GST_TIME_ARGS (rtph264pay->last_spspps));
787
788       /* calculate diff between last SPS/PPS in milliseconds */
789       if (pts > rtph264pay->last_spspps)
790         diff = pts - rtph264pay->last_spspps;
791       else
792         diff = 0;
793
794       GST_DEBUG_OBJECT (rtph264pay,
795           "interval since last SPS/PPS %" GST_TIME_FORMAT,
796           GST_TIME_ARGS (diff));
797
798       /* bigger than interval, queue SPS/PPS */
799       if (GST_TIME_AS_SECONDS (diff) >= rtph264pay->spspps_interval) {
800         GST_DEBUG_OBJECT (rtph264pay, "time to send SPS/PPS");
801         send_spspps = TRUE;
802       }
803     } else {
804       /* no know previous SPS/PPS time, send now */
805       GST_DEBUG_OBJECT (rtph264pay, "no previous SPS/PPS time, send now");
806       send_spspps = TRUE;
807     }
808   }
809
810   if (send_spspps || rtph264pay->send_spspps) {
811     /* we need to send SPS/PPS now first. FIXME, don't use the pts for
812      * checking when we need to send SPS/PPS but convert to running_time first. */
813     rtph264pay->send_spspps = FALSE;
814     ret = gst_rtp_h264_pay_send_sps_pps (basepayload, rtph264pay, dts, pts);
815     if (ret != GST_FLOW_OK)
816       return ret;
817   }
818
819   packet_len = gst_rtp_buffer_calc_packet_len (size, 0, 0);
820
821   if (packet_len < mtu) {
822     GST_DEBUG_OBJECT (basepayload,
823         "NAL Unit fit in one packet datasize=%d mtu=%d", size, mtu);
824     /* will fit in one packet */
825
826     /* use buffer lists
827      * create buffer without payload containing only the RTP header
828      * (memory block at index 0) */
829     outbuf = gst_rtp_buffer_new_allocate (0, 0, 0);
830
831     gst_rtp_buffer_map (outbuf, GST_MAP_WRITE, &rtp);
832
833     /* only set the marker bit on packets containing access units */
834     if (IS_ACCESS_UNIT (nalType) && end_of_au) {
835       gst_rtp_buffer_set_marker (&rtp, 1);
836     }
837
838     /* timestamp the outbuffer */
839     GST_BUFFER_PTS (outbuf) = pts;
840     GST_BUFFER_DTS (outbuf) = dts;
841
842     /* insert payload memory block */
843     outbuf = gst_buffer_append (outbuf, paybuf);
844
845     list = gst_buffer_list_new ();
846
847     /* add the buffer to the buffer list */
848     gst_buffer_list_add (list, outbuf);
849
850     gst_rtp_buffer_unmap (&rtp);
851
852     /* push the list to the next element in the pipe */
853     ret = gst_rtp_base_payload_push_list (basepayload, list);
854   } else {
855     /* fragmentation Units FU-A */
856     guint limitedSize;
857     int ii = 0, start = 1, end = 0, pos = 0;
858
859     GST_DEBUG_OBJECT (basepayload,
860         "NAL Unit DOES NOT fit in one packet datasize=%d mtu=%d", size, mtu);
861
862     pos++;
863     size--;
864
865     ret = GST_FLOW_OK;
866
867     GST_DEBUG_OBJECT (basepayload, "Using FU-A fragmentation for data size=%d",
868         size);
869
870     /* We keep 2 bytes for FU indicator and FU Header */
871     payload_len = gst_rtp_buffer_calc_payload_len (mtu - 2, 0, 0);
872
873     list = gst_buffer_list_new ();
874
875     while (end == 0) {
876       limitedSize = size < payload_len ? size : payload_len;
877       GST_DEBUG_OBJECT (basepayload,
878           "Inside  FU-A fragmentation limitedSize=%d iteration=%d", limitedSize,
879           ii);
880
881       /* use buffer lists
882        * create buffer without payload containing only the RTP header
883        * (memory block at index 0) */
884       outbuf = gst_rtp_buffer_new_allocate (2, 0, 0);
885
886       gst_rtp_buffer_map (outbuf, GST_MAP_WRITE, &rtp);
887
888       GST_BUFFER_DTS (outbuf) = dts;
889       GST_BUFFER_PTS (outbuf) = pts;
890       payload = gst_rtp_buffer_get_payload (&rtp);
891
892       if (limitedSize == size) {
893         GST_DEBUG_OBJECT (basepayload, "end size=%d iteration=%d", size, ii);
894         end = 1;
895       }
896       if (IS_ACCESS_UNIT (nalType)) {
897         gst_rtp_buffer_set_marker (&rtp, end && end_of_au);
898       }
899
900       /* FU indicator */
901       payload[0] = (nalHeader & 0x60) | 28;
902
903       /* FU Header */
904       payload[1] = (start << 7) | (end << 6) | (nalHeader & 0x1f);
905
906       gst_rtp_buffer_unmap (&rtp);
907
908       /* insert payload memory block */
909       gst_buffer_append (outbuf,
910           gst_buffer_copy_region (paybuf, GST_BUFFER_COPY_MEMORY, pos,
911               limitedSize));
912
913       /* add the buffer to the buffer list */
914       gst_buffer_list_add (list, outbuf);
915
916
917       size -= limitedSize;
918       pos += limitedSize;
919       ii++;
920       start = 0;
921     }
922
923     ret = gst_rtp_base_payload_push_list (basepayload, list);
924     gst_buffer_unref (paybuf);
925   }
926   return ret;
927 }
928
929 static GstFlowReturn
930 gst_rtp_h264_pay_handle_buffer (GstRTPBasePayload * basepayload,
931     GstBuffer * buffer)
932 {
933   GstRtpH264Pay *rtph264pay;
934   GstFlowReturn ret;
935   gsize size;
936   guint nal_len, i;
937   GstMapInfo map;
938   const guint8 *data;
939   GstClockTime dts, pts;
940   GArray *nal_queue;
941   gboolean avc;
942   GstBuffer *paybuf = NULL;
943   gsize skip;
944
945   rtph264pay = GST_RTP_H264_PAY (basepayload);
946
947   /* the input buffer contains one or more NAL units */
948
949   avc = rtph264pay->stream_format == GST_H264_STREAM_FORMAT_AVC;
950
951   if (avc) {
952     /* In AVC mode, there is no adapter, so nothign to flush */
953     if (buffer == NULL)
954       return GST_FLOW_OK;
955     gst_buffer_map (buffer, &map, GST_MAP_READ);
956     data = map.data;
957     size = map.size;
958     pts = GST_BUFFER_PTS (buffer);
959     dts = GST_BUFFER_DTS (buffer);
960     GST_DEBUG_OBJECT (basepayload, "got %" G_GSIZE_FORMAT " bytes", size);
961   } else {
962     dts = gst_adapter_prev_dts (rtph264pay->adapter, NULL);
963     pts = gst_adapter_prev_pts (rtph264pay->adapter, NULL);
964     if (buffer) {
965       if (!GST_CLOCK_TIME_IS_VALID (dts))
966         dts = GST_BUFFER_DTS (buffer);
967       if (!GST_CLOCK_TIME_IS_VALID (pts))
968         pts = GST_BUFFER_PTS (buffer);
969
970       gst_adapter_push (rtph264pay->adapter, buffer);
971     }
972     size = gst_adapter_available (rtph264pay->adapter);
973     /* Nothing to do here if the adapter is empty, e.g. on EOS */
974     if (size == 0)
975       return GST_FLOW_OK;
976     data = gst_adapter_map (rtph264pay->adapter, size);
977     GST_DEBUG_OBJECT (basepayload,
978         "got %" G_GSIZE_FORMAT " bytes (%" G_GSIZE_FORMAT ")", size,
979         buffer ? gst_buffer_get_size (buffer) : 0);
980   }
981
982   ret = GST_FLOW_OK;
983
984   /* now loop over all NAL units and put them in a packet
985    * FIXME, we should really try to pack multiple NAL units into one RTP packet
986    * if we can, especially for the config packets that wont't cause decoder 
987    * latency. */
988   if (avc) {
989     guint nal_length_size;
990     gsize offset = 0;
991
992     nal_length_size = rtph264pay->nal_length_size;
993
994     while (size > nal_length_size) {
995       gint i;
996       gboolean end_of_au = FALSE;
997
998       nal_len = 0;
999       for (i = 0; i < nal_length_size; i++) {
1000         nal_len = ((nal_len << 8) + data[i]);
1001       }
1002
1003       /* skip the length bytes, make sure we don't run past the buffer size */
1004       data += nal_length_size;
1005       offset += nal_length_size;
1006       size -= nal_length_size;
1007
1008       if (size >= nal_len) {
1009         GST_DEBUG_OBJECT (basepayload, "got NAL of size %u", nal_len);
1010       } else {
1011         nal_len = size;
1012         GST_DEBUG_OBJECT (basepayload, "got incomplete NAL of size %u",
1013             nal_len);
1014       }
1015
1016       /* If we're at the end of the buffer, then we're at the end of the
1017        * access unit
1018        */
1019       if (rtph264pay->alignment == GST_H264_ALIGNMENT_AU
1020           && size - nal_len <= nal_length_size) {
1021         end_of_au = TRUE;
1022       }
1023
1024       paybuf = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_MEMORY, offset,
1025           nal_len);
1026       ret =
1027           gst_rtp_h264_pay_payload_nal (basepayload, paybuf, dts, pts,
1028           end_of_au);
1029       if (ret != GST_FLOW_OK)
1030         break;
1031
1032       data += nal_len;
1033       offset += nal_len;
1034       size -= nal_len;
1035     }
1036   } else {
1037     guint next;
1038     gboolean update = FALSE;
1039
1040     /* get offset of first start code */
1041     next = next_start_code (data, size);
1042
1043     /* skip to start code, if no start code is found, next will be size and we
1044      * will not collect data. */
1045     data += next;
1046     size -= next;
1047     nal_queue = rtph264pay->queue;
1048     skip = next;
1049
1050     /* array must be empty when we get here */
1051     g_assert (nal_queue->len == 0);
1052
1053     GST_DEBUG_OBJECT (basepayload,
1054         "found first start at %u, bytes left %" G_GSIZE_FORMAT, next, size);
1055
1056     /* first pass to locate NALs and parse SPS/PPS */
1057     while (size > 4) {
1058       /* skip start code */
1059       data += 3;
1060       size -= 3;
1061
1062       /* use next_start_code() to scan buffer.
1063        * next_start_code() returns the offset in data, 
1064        * starting from zero to the first byte of 0.0.0.1
1065        * If no start code is found, it returns the value of the 
1066        * 'size' parameter. 
1067        * data is unchanged by the call to next_start_code()
1068        */
1069       next = next_start_code (data, size);
1070
1071       if (next == size && buffer != NULL) {
1072         /* Didn't find the start of next NAL and it's not EOS,
1073          * handle it next time */
1074         break;
1075       }
1076
1077       /* nal length is distance to next start code */
1078       nal_len = next;
1079
1080       GST_DEBUG_OBJECT (basepayload, "found next start at %u of size %u", next,
1081           nal_len);
1082
1083       if (rtph264pay->sprop_parameter_sets != NULL) {
1084         /* explicitly set profile and sprop, use those */
1085         if (rtph264pay->update_caps) {
1086           if (!gst_rtp_base_payload_set_outcaps (basepayload,
1087                   "sprop-parameter-sets", G_TYPE_STRING,
1088                   rtph264pay->sprop_parameter_sets, NULL))
1089             goto caps_rejected;
1090
1091           /* parse SPS and PPS from provided parameter set (for insertion) */
1092           gst_rtp_h264_pay_parse_sprop_parameter_sets (rtph264pay);
1093
1094           rtph264pay->update_caps = FALSE;
1095
1096           GST_DEBUG ("outcaps update: sprop-parameter-sets=%s",
1097               rtph264pay->sprop_parameter_sets);
1098         }
1099       } else {
1100         /* We know our stream is a valid H264 NAL packet,
1101          * go parse it for SPS/PPS to enrich the caps */
1102         /* order: make sure to check nal */
1103         update =
1104             gst_rtp_h264_pay_decode_nal (rtph264pay, data, nal_len, dts, pts)
1105             || update;
1106       }
1107       /* move to next NAL packet */
1108       data += nal_len;
1109       size -= nal_len;
1110
1111       g_array_append_val (nal_queue, nal_len);
1112     }
1113
1114     /* if has new SPS & PPS, update the output caps */
1115     if (G_UNLIKELY (update))
1116       if (!gst_rtp_h264_pay_set_sps_pps (basepayload))
1117         goto caps_rejected;
1118
1119     /* second pass to payload and push */
1120
1121     if (nal_queue->len != 0)
1122       gst_adapter_flush (rtph264pay->adapter, skip);
1123
1124     for (i = 0; i < nal_queue->len; i++) {
1125       guint size;
1126       gboolean end_of_au = FALSE;
1127
1128       nal_len = g_array_index (nal_queue, guint, i);
1129       /* skip start code */
1130       gst_adapter_flush (rtph264pay->adapter, 3);
1131
1132       /* Trim the end unless we're the last NAL in the stream.
1133        * In case we're not at the end of the buffer we know the next block
1134        * starts with 0x000001 so all the 0x00 bytes at the end of this one are
1135        * trailing 0x0 that can be discarded */
1136       size = nal_len;
1137       data = gst_adapter_map (rtph264pay->adapter, size);
1138       if (i + 1 != nal_queue->len || buffer != NULL)
1139         for (; size > 1 && data[size - 1] == 0x0; size--)
1140           /* skip */ ;
1141
1142
1143       /* If it's the last nal unit we have in non-bytestream mode, we can
1144        * assume it's the end of an access-unit
1145        *
1146        * FIXME: We need to wait until the next packet or EOS to
1147        * actually payload the NAL so we can know if the current NAL is
1148        * the last one of an access unit or not if we are in bytestream mode
1149        */
1150       if ((rtph264pay->alignment == GST_H264_ALIGNMENT_AU || buffer == NULL) &&
1151           i == nal_queue->len - 1)
1152         end_of_au = TRUE;
1153       paybuf = gst_adapter_take_buffer (rtph264pay->adapter, size);
1154       g_assert (paybuf);
1155
1156       /* put the data in one or more RTP packets */
1157       ret =
1158           gst_rtp_h264_pay_payload_nal (basepayload, paybuf, dts, pts,
1159           end_of_au);
1160       if (ret != GST_FLOW_OK) {
1161         break;
1162       }
1163
1164       /* move to next NAL packet */
1165       /* Skips the trailing zeros */
1166       gst_adapter_flush (rtph264pay->adapter, nal_len - size);
1167     }
1168     g_array_set_size (nal_queue, 0);
1169   }
1170
1171 done:
1172   if (avc) {
1173     gst_buffer_unmap (buffer, &map);
1174     gst_buffer_unref (buffer);
1175   } else {
1176     gst_adapter_unmap (rtph264pay->adapter);
1177   }
1178
1179   return ret;
1180
1181 caps_rejected:
1182   {
1183     GST_WARNING_OBJECT (basepayload, "Could not set outcaps");
1184     g_array_set_size (nal_queue, 0);
1185     ret = GST_FLOW_NOT_NEGOTIATED;
1186     goto done;
1187   }
1188 }
1189
1190 static gboolean
1191 gst_rtp_h264_pay_sink_event (GstRTPBasePayload * payload, GstEvent * event)
1192 {
1193   gboolean res;
1194   const GstStructure *s;
1195   GstRtpH264Pay *rtph264pay = GST_RTP_H264_PAY (payload);
1196
1197   switch (GST_EVENT_TYPE (event)) {
1198     case GST_EVENT_FLUSH_STOP:
1199       gst_adapter_clear (rtph264pay->adapter);
1200       break;
1201     case GST_EVENT_CUSTOM_DOWNSTREAM:
1202       s = gst_event_get_structure (event);
1203       if (gst_structure_has_name (s, "GstForceKeyUnit")) {
1204         gboolean resend_codec_data;
1205
1206         if (gst_structure_get_boolean (s, "all-headers",
1207                 &resend_codec_data) && resend_codec_data)
1208           rtph264pay->send_spspps = TRUE;
1209       }
1210       break;
1211     case GST_EVENT_EOS:
1212     {
1213       /* call handle_buffer with NULL to flush last NAL from adapter
1214        * in byte-stream mode
1215        */
1216       gst_rtp_h264_pay_handle_buffer (payload, NULL);
1217       break;
1218     }
1219     case GST_EVENT_STREAM_START:
1220       GST_DEBUG_OBJECT (rtph264pay, "New stream detected => Clear SPS and PPS");
1221       gst_rtp_h264_pay_clear_sps_pps (rtph264pay);
1222       break;
1223     default:
1224       break;
1225   }
1226
1227   res = GST_RTP_BASE_PAYLOAD_CLASS (parent_class)->sink_event (payload, event);
1228
1229   return res;
1230 }
1231
1232 static GstStateChangeReturn
1233 gst_rtp_h264_pay_change_state (GstElement * element, GstStateChange transition)
1234 {
1235   GstStateChangeReturn ret;
1236   GstRtpH264Pay *rtph264pay = GST_RTP_H264_PAY (element);
1237
1238   switch (transition) {
1239     case GST_STATE_CHANGE_READY_TO_PAUSED:
1240       rtph264pay->send_spspps = FALSE;
1241       gst_adapter_clear (rtph264pay->adapter);
1242       break;
1243     default:
1244       break;
1245   }
1246
1247   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
1248
1249   return ret;
1250 }
1251
1252 static void
1253 gst_rtp_h264_pay_set_property (GObject * object, guint prop_id,
1254     const GValue * value, GParamSpec * pspec)
1255 {
1256   GstRtpH264Pay *rtph264pay;
1257
1258   rtph264pay = GST_RTP_H264_PAY (object);
1259
1260   switch (prop_id) {
1261     case PROP_SPROP_PARAMETER_SETS:
1262       g_free (rtph264pay->sprop_parameter_sets);
1263       rtph264pay->sprop_parameter_sets = g_value_dup_string (value);
1264       rtph264pay->update_caps = TRUE;
1265       break;
1266     case PROP_CONFIG_INTERVAL:
1267       rtph264pay->spspps_interval = g_value_get_uint (value);
1268       break;
1269     default:
1270       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1271       break;
1272   }
1273 }
1274
1275 static void
1276 gst_rtp_h264_pay_get_property (GObject * object, guint prop_id,
1277     GValue * value, GParamSpec * pspec)
1278 {
1279   GstRtpH264Pay *rtph264pay;
1280
1281   rtph264pay = GST_RTP_H264_PAY (object);
1282
1283   switch (prop_id) {
1284     case PROP_SPROP_PARAMETER_SETS:
1285       g_value_set_string (value, rtph264pay->sprop_parameter_sets);
1286       break;
1287     case PROP_CONFIG_INTERVAL:
1288       g_value_set_uint (value, rtph264pay->spspps_interval);
1289       break;
1290     default:
1291       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1292       break;
1293   }
1294 }
1295
1296 gboolean
1297 gst_rtp_h264_pay_plugin_init (GstPlugin * plugin)
1298 {
1299   return gst_element_register (plugin, "rtph264pay",
1300       GST_RANK_SECONDARY, GST_TYPE_RTP_H264_PAY);
1301 }