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