1 /* ex: set tabstop=2 shiftwidth=2 expandtab: */
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.
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.
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.
27 #include <gst/rtp/gstrtpbuffer.h>
28 #include <gst/pbutils/pbutils.h>
30 #include "gstrtph264pay.h"
37 GST_DEBUG_CATEGORY_STATIC (rtph264pay_debug);
38 #define GST_CAT_DEFAULT (rtph264pay_debug)
45 static GstStaticPadTemplate gst_rtp_h264_pay_sink_template =
46 GST_STATIC_PAD_TEMPLATE ("sink",
49 GST_STATIC_CAPS ("video/x-h264, "
50 "stream-format = (string) avc, alignment = (string) au, "
51 "width = (int) [ 1, MAX ], height = (int) [ 1, MAX ]; "
53 "stream-format = (string) byte-stream, alignment = (string) { nal, au }, "
54 "width = (int) [ 1, MAX ], height = (int) [ 1, MAX ]")
55 /** optional parameters **/
56 /* "framerate = (fraction) [ 0/1, MAX/1 ] " */
59 static GstStaticPadTemplate gst_rtp_h264_pay_src_template =
60 GST_STATIC_PAD_TEMPLATE ("src",
63 GST_STATIC_CAPS ("application/x-rtp, "
64 "media = (string) \"video\", "
65 "payload = (int) " GST_RTP_PAYLOAD_DYNAMIC_STRING ", "
66 "clock-rate = (int) 90000, "
67 "encoding-name = (string) \"H264\", "
68 "width = (int) [ 1, MAX ], height = (int) [ 1, MAX ]")
69 /** optional parameters **/
70 /* "framerate = (fraction) [ 0/1, MAX/1 ] " */
73 #define DEFAULT_SPROP_PARAMETER_SETS NULL
74 #define DEFAULT_CONFIG_INTERVAL 0
79 PROP_SPROP_PARAMETER_SETS,
84 #define IS_ACCESS_UNIT(x) (((x) > 0x00) && ((x) < 0x06))
86 static void gst_rtp_h264_pay_finalize (GObject * object);
88 static void gst_rtp_h264_pay_set_property (GObject * object, guint prop_id,
89 const GValue * value, GParamSpec * pspec);
90 static void gst_rtp_h264_pay_get_property (GObject * object, guint prop_id,
91 GValue * value, GParamSpec * pspec);
93 static GstCaps *gst_rtp_h264_pay_getcaps (GstRTPBasePayload * payload,
94 GstPad * pad, GstCaps * filter);
95 static gboolean gst_rtp_h264_pay_setcaps (GstRTPBasePayload * basepayload,
97 static GstFlowReturn gst_rtp_h264_pay_handle_buffer (GstRTPBasePayload * pad,
99 static gboolean gst_rtp_h264_pay_sink_event (GstRTPBasePayload * payload,
101 static GstStateChangeReturn gst_rtp_h264_pay_change_state (GstElement *
102 element, GstStateChange transition);
104 #define gst_rtp_h264_pay_parent_class parent_class
105 G_DEFINE_TYPE (GstRtpH264Pay, gst_rtp_h264_pay, GST_TYPE_RTP_BASE_PAYLOAD);
108 gst_rtp_h264_pay_class_init (GstRtpH264PayClass * klass)
110 GObjectClass *gobject_class;
111 GstElementClass *gstelement_class;
112 GstRTPBasePayloadClass *gstrtpbasepayload_class;
114 gobject_class = (GObjectClass *) klass;
115 gstelement_class = (GstElementClass *) klass;
116 gstrtpbasepayload_class = (GstRTPBasePayloadClass *) klass;
118 gobject_class->set_property = gst_rtp_h264_pay_set_property;
119 gobject_class->get_property = gst_rtp_h264_pay_get_property;
121 g_object_class_install_property (G_OBJECT_CLASS (klass),
122 PROP_SPROP_PARAMETER_SETS, g_param_spec_string ("sprop-parameter-sets",
123 "sprop-parameter-sets",
124 "The base64 sprop-parameter-sets to set in out caps (set to NULL to "
125 "extract from stream)",
126 DEFAULT_SPROP_PARAMETER_SETS,
127 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
129 g_object_class_install_property (G_OBJECT_CLASS (klass),
130 PROP_CONFIG_INTERVAL,
131 g_param_spec_uint ("config-interval",
132 "SPS PPS Send Interval",
133 "Send SPS and PPS Insertion Interval in seconds (sprop parameter sets "
134 "will be multiplexed in the data stream when detected.) (0 = disabled)",
135 0, 3600, DEFAULT_CONFIG_INTERVAL,
136 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)
139 gobject_class->finalize = gst_rtp_h264_pay_finalize;
141 gst_element_class_add_pad_template (gstelement_class,
142 gst_static_pad_template_get (&gst_rtp_h264_pay_src_template));
143 gst_element_class_add_pad_template (gstelement_class,
144 gst_static_pad_template_get (&gst_rtp_h264_pay_sink_template));
146 gst_element_class_set_static_metadata (gstelement_class, "RTP H264 payloader",
147 "Codec/Payloader/Network/RTP",
148 "Payload-encode H264 video into RTP packets (RFC 3984)",
149 "Laurent Glayal <spglegle@yahoo.fr>");
151 gstelement_class->change_state =
152 GST_DEBUG_FUNCPTR (gst_rtp_h264_pay_change_state);
154 gstrtpbasepayload_class->get_caps = gst_rtp_h264_pay_getcaps;
155 gstrtpbasepayload_class->set_caps = gst_rtp_h264_pay_setcaps;
156 gstrtpbasepayload_class->handle_buffer = gst_rtp_h264_pay_handle_buffer;
157 gstrtpbasepayload_class->sink_event = gst_rtp_h264_pay_sink_event;
159 GST_DEBUG_CATEGORY_INIT (rtph264pay_debug, "rtph264pay", 0,
160 "H264 RTP Payloader");
164 gst_rtp_h264_pay_init (GstRtpH264Pay * rtph264pay)
166 rtph264pay->queue = g_array_new (FALSE, FALSE, sizeof (guint));
167 rtph264pay->profile = 0;
168 rtph264pay->sps = NULL;
169 rtph264pay->pps = NULL;
170 rtph264pay->last_spspps = -1;
171 rtph264pay->spspps_interval = DEFAULT_CONFIG_INTERVAL;
173 rtph264pay->adapter = gst_adapter_new ();
177 gst_rtp_h264_pay_clear_sps_pps (GstRtpH264Pay * rtph264pay)
179 g_list_foreach (rtph264pay->sps, (GFunc) gst_mini_object_unref, NULL);
180 g_list_free (rtph264pay->sps);
181 rtph264pay->sps = NULL;
182 g_list_foreach (rtph264pay->pps, (GFunc) gst_mini_object_unref, NULL);
183 g_list_free (rtph264pay->pps);
184 rtph264pay->pps = NULL;
188 gst_rtp_h264_pay_finalize (GObject * object)
190 GstRtpH264Pay *rtph264pay;
192 rtph264pay = GST_RTP_H264_PAY (object);
194 g_array_free (rtph264pay->queue, TRUE);
196 gst_rtp_h264_pay_clear_sps_pps (rtph264pay);
198 g_free (rtph264pay->sprop_parameter_sets);
200 g_object_unref (rtph264pay->adapter);
202 G_OBJECT_CLASS (parent_class)->finalize (object);
205 static const gchar all_levels[][4] = {
225 gst_rtp_h264_pay_getcaps (GstRTPBasePayload * payload, GstPad * pad,
228 GstCaps *template_caps;
229 GstCaps *allowed_caps;
230 GstCaps *caps, *icaps;
231 gboolean append_unrestricted;
235 gst_pad_peer_query_caps (GST_RTP_BASE_PAYLOAD_SRCPAD (payload), NULL);
237 if (allowed_caps == NULL)
241 gst_static_pad_template_get_caps (&gst_rtp_h264_pay_sink_template);
243 if (gst_caps_is_any (allowed_caps)) {
244 caps = gst_caps_ref (template_caps);
248 if (gst_caps_is_empty (allowed_caps)) {
249 caps = gst_caps_ref (allowed_caps);
253 caps = gst_caps_new_empty ();
255 append_unrestricted = FALSE;
256 for (i = 0; i < gst_caps_get_size (allowed_caps); i++) {
257 GstStructure *s = gst_caps_get_structure (allowed_caps, i);
258 GstStructure *new_s = gst_structure_new_empty ("video/x-h264");
259 const gchar *profile_level_id;
261 profile_level_id = gst_structure_get_string (s, "profile-level-id");
263 if (profile_level_id && strlen (profile_level_id) == 6) {
264 const gchar *profile;
269 spsint = strtol (profile_level_id, NULL, 16);
270 sps[0] = spsint >> 16;
271 sps[1] = spsint >> 8;
274 profile = gst_codec_utils_h264_get_profile (sps, 3);
275 level = gst_codec_utils_h264_get_level (sps, 3);
277 if (profile && level) {
278 GST_LOG_OBJECT (payload, "In caps, have profile %s and level %s",
281 if (!strcmp (profile, "constrained-baseline"))
282 gst_structure_set (new_s, "profile", G_TYPE_STRING, profile, NULL);
285 GValue profiles = { 0, };
287 g_value_init (&profiles, GST_TYPE_LIST);
288 g_value_init (&val, G_TYPE_STRING);
290 g_value_set_static_string (&val, profile);
291 gst_value_list_append_value (&profiles, &val);
293 g_value_set_static_string (&val, "constrained-baseline");
294 gst_value_list_append_value (&profiles, &val);
296 gst_structure_take_value (new_s, "profile", &profiles);
299 if (!strcmp (level, "1"))
300 gst_structure_set (new_s, "level", G_TYPE_STRING, level, NULL);
302 GValue levels = { 0, };
306 g_value_init (&levels, GST_TYPE_LIST);
307 g_value_init (&val, G_TYPE_STRING);
309 for (j = 0; j < G_N_ELEMENTS (all_levels); j++) {
310 g_value_set_static_string (&val, all_levels[j]);
311 gst_value_list_prepend_value (&levels, &val);
312 if (!strcmp (level, all_levels[j]))
315 gst_structure_take_value (new_s, "level", &levels);
318 /* Invalid profile-level-id means baseline */
320 gst_structure_set (new_s,
321 "profile", G_TYPE_STRING, "constrained-baseline", NULL);
324 /* No profile-level-id means baseline or unrestricted */
326 gst_structure_set (new_s,
327 "profile", G_TYPE_STRING, "constrained-baseline", NULL);
328 append_unrestricted = TRUE;
331 caps = gst_caps_merge_structure (caps, new_s);
334 if (append_unrestricted) {
336 gst_caps_merge_structure (caps, gst_structure_new ("video/x-h264", NULL,
340 icaps = gst_caps_intersect (caps, template_caps);
341 gst_caps_unref (caps);
346 gst_caps_unref (template_caps);
347 gst_caps_unref (allowed_caps);
349 GST_LOG_OBJECT (payload, "returning caps %" GST_PTR_FORMAT, caps);
353 /* take the currently configured SPS and PPS lists and set them on the caps as
354 * sprop-parameter-sets */
356 gst_rtp_h264_pay_set_sps_pps (GstRTPBasePayload * basepayload)
358 GstRtpH264Pay *payloader = GST_RTP_H264_PAY (basepayload);
365 sprops = g_string_new ("");
368 /* build the sprop-parameter-sets */
369 for (walk = payloader->sps; walk; walk = g_list_next (walk)) {
370 GstBuffer *sps_buf = GST_BUFFER_CAST (walk->data);
372 gst_buffer_map (sps_buf, &map, GST_MAP_READ);
373 set = g_base64_encode (map.data, map.size);
374 gst_buffer_unmap (sps_buf, &map);
376 g_string_append_printf (sprops, "%s%s", count ? "," : "", set);
380 for (walk = payloader->pps; walk; walk = g_list_next (walk)) {
381 GstBuffer *pps_buf = GST_BUFFER_CAST (walk->data);
383 gst_buffer_map (pps_buf, &map, GST_MAP_READ);
384 set = g_base64_encode (map.data, map.size);
385 gst_buffer_unmap (pps_buf, &map);
387 g_string_append_printf (sprops, "%s%s", count ? "," : "", set);
392 if (G_UNLIKELY (count == 0)) {
393 g_string_free (sprops, TRUE);
397 return g_string_free (sprops, FALSE);
401 add_sps_pps_without_duplicates (GList * list, GstBuffer * buffer)
406 gst_buffer_map (buffer, &map, GST_MAP_READ);
408 for (walk = list; walk; walk = walk->next) {
409 if (gst_buffer_get_size (walk->data) == map.size &&
410 !gst_buffer_memcmp (walk->data, 0, map.data, map.size)) {
412 gst_buffer_unmap (buffer, &map);
413 gst_buffer_unref (buffer);
418 gst_buffer_unmap (buffer, &map);
419 list = g_list_append (list, buffer);
425 gst_rtp_h264_pay_setcaps (GstRTPBasePayload * basepayload, GstCaps * caps)
427 GstRtpH264Pay *rtph264pay;
434 const gchar *alignment, *stream_format;
438 gint num = 0, denom = 1;
440 rtph264pay = GST_RTP_H264_PAY (basepayload);
442 str = gst_caps_get_structure (caps, 0);
444 /* we can only set the output caps when we found the sprops and profile
446 gst_rtp_base_payload_set_options (basepayload, "video", TRUE, "H264", 90000);
448 rtph264pay->alignment = GST_H264_ALIGNMENT_UNKNOWN;
449 alignment = gst_structure_get_string (str, "alignment");
451 if (g_str_equal (alignment, "au"))
452 rtph264pay->alignment = GST_H264_ALIGNMENT_AU;
453 if (g_str_equal (alignment, "nal"))
454 rtph264pay->alignment = GST_H264_ALIGNMENT_NAL;
457 rtph264pay->stream_format = GST_H264_STREAM_FORMAT_UNKNOWN;
458 stream_format = gst_structure_get_string (str, "stream-format");
460 if (g_str_equal (stream_format, "avc"))
461 rtph264pay->stream_format = GST_H264_STREAM_FORMAT_AVC;
462 if (g_str_equal (stream_format, "byte-stream"))
463 rtph264pay->stream_format = GST_H264_STREAM_FORMAT_BYTESTREAM;
466 if (!gst_structure_get_int (str, "height", &height) || height <= 0) {
467 goto invalid_dimension;
469 if (!gst_structure_get_int (str, "width", &width) || width <= 0) {
470 goto invalid_dimension;
473 if (gst_structure_get_fraction (str, "framerate", &num, &denom) &&
474 (num < 0 || denom <= 0)) {
475 goto invalid_framerate;
478 /* packetized AVC video has a codec_data */
479 if ((value = gst_structure_get_value (str, "codec_data"))) {
480 guint num_sps, num_pps;
483 GST_DEBUG_OBJECT (rtph264pay, "have packetized h264");
485 buffer = gst_value_get_buffer (value);
487 gst_buffer_map (buffer, &map, GST_MAP_READ);
491 /* parse the avcC data */
494 /* parse the version, this must be 1 */
498 /* AVCProfileIndication */
500 /* AVCLevelIndication */
501 rtph264pay->profile = (data[1] << 16) | (data[2] << 8) | data[3];
502 GST_DEBUG_OBJECT (rtph264pay, "profile %06x", rtph264pay->profile);
504 /* 6 bits reserved | 2 bits lengthSizeMinusOne */
505 /* this is the number of bytes in front of the NAL units to mark their
507 rtph264pay->nal_length_size = (data[4] & 0x03) + 1;
508 GST_DEBUG_OBJECT (rtph264pay, "nal length %u", rtph264pay->nal_length_size);
509 /* 3 bits reserved | 5 bits numOfSequenceParameterSets */
510 num_sps = data[5] & 0x1f;
511 GST_DEBUG_OBJECT (rtph264pay, "num SPS %u", num_sps);
516 /* create the sprop-parameter-sets */
517 for (i = 0; i < num_sps; i++) {
523 nal_size = (data[0] << 8) | data[1];
527 GST_LOG_OBJECT (rtph264pay, "SPS %d size %d", i, nal_size);
532 /* make a buffer out of it and add to SPS list */
533 sps_buf = gst_buffer_new_and_alloc (nal_size);
534 gst_buffer_fill (sps_buf, 0, data, nal_size);
535 rtph264pay->sps = add_sps_pps_without_duplicates (rtph264pay->sps,
544 /* 8 bits numOfPictureParameterSets */
549 GST_DEBUG_OBJECT (rtph264pay, "num PPS %u", num_pps);
550 for (i = 0; i < num_pps; i++) {
556 nal_size = (data[0] << 8) | data[1];
560 GST_LOG_OBJECT (rtph264pay, "PPS %d size %d", i, nal_size);
565 /* make a buffer out of it and add to PPS list */
566 pps_buf = gst_buffer_new_and_alloc (nal_size);
567 gst_buffer_fill (pps_buf, 0, data, nal_size);
568 rtph264pay->pps = add_sps_pps_without_duplicates (rtph264pay->pps,
574 gst_buffer_unmap (buffer, &map);
575 /* and update the caps with the collected data */
576 sprops = gst_rtp_h264_pay_set_sps_pps (basepayload);
578 GST_DEBUG_OBJECT (rtph264pay, "have bytestream h264");
582 if (num > 0 && sprops != NULL) {
583 caps_set = gst_rtp_base_payload_set_outcaps (basepayload, "width",
584 G_TYPE_INT, width, "height", G_TYPE_INT, height,
585 "sprop-parameter-sets", G_TYPE_STRING, sprops, "framerate",
586 GST_TYPE_FRACTION, num, denom, NULL);
587 } else if (num <= 0 && sprops != NULL) {
588 caps_set = gst_rtp_base_payload_set_outcaps (basepayload, "width",
589 G_TYPE_INT, width, "height", G_TYPE_INT, height,
590 "sprop-parameter-sets", G_TYPE_STRING, sprops, NULL);
591 } else if (num > 0 && sprops == NULL) {
592 caps_set = gst_rtp_base_payload_set_outcaps (basepayload, "width",
593 G_TYPE_INT, width, "height", G_TYPE_INT, height, "framerate",
594 GST_TYPE_FRACTION, num, denom, NULL);
596 caps_set = gst_rtp_base_payload_set_outcaps (basepayload, "width",
597 G_TYPE_INT, width, "height", G_TYPE_INT, height, NULL);
600 if (sprops != NULL) {
605 goto set_caps_failed;
612 GST_ERROR_OBJECT (rtph264pay, "avcC size %" G_GSIZE_FORMAT " < 7", size);
617 GST_ERROR_OBJECT (rtph264pay, "wrong avcC version");
622 GST_ERROR_OBJECT (rtph264pay, "avcC too small ");
627 GST_ERROR_OBJECT (rtph264pay, "failed to set caps");
632 GST_ERROR_OBJECT (rtph264pay, "invalid width/height from caps");
637 GST_ERROR_OBJECT (rtph264pay, "invalid framerate from caps");
642 gst_buffer_unmap (buffer, &map);
648 gst_rtp_h264_pay_parse_sprop_parameter_sets (GstRtpH264Pay * rtph264pay)
652 guint len, num_sps, num_pps;
656 ps = rtph264pay->sprop_parameter_sets;
660 gst_rtp_h264_pay_clear_sps_pps (rtph264pay);
662 params = g_strsplit (ps, ",", 0);
663 len = g_strv_length (params);
665 GST_DEBUG_OBJECT (rtph264pay, "we have %d params", len);
667 num_sps = num_pps = 0;
669 for (i = 0; params[i]; i++) {
677 nal_len = strlen (params[i]);
678 buf = gst_buffer_new_and_alloc (nal_len);
680 gst_buffer_map (buf, &map, GST_MAP_WRITE);
682 nal_len = g_base64_decode_step (params[i], nal_len, nalp, &state, &save);
684 gst_buffer_unmap (buf, &map);
685 gst_buffer_resize (buf, 0, nal_len);
688 gst_buffer_unref (buf);
692 /* append to the right list */
693 if ((nal_type & 0x1f) == 7) {
694 GST_DEBUG_OBJECT (rtph264pay, "adding param %d as SPS %d", i, num_sps);
695 rtph264pay->sps = add_sps_pps_without_duplicates (rtph264pay->sps, buf);
698 GST_DEBUG_OBJECT (rtph264pay, "adding param %d as PPS %d", i, num_pps);
699 rtph264pay->pps = add_sps_pps_without_duplicates (rtph264pay->pps, buf);
707 next_start_code (const guint8 * data, guint size)
709 /* Boyer-Moore string matching algorithm, in a degenerative
710 * sense because our search 'alphabet' is binary - 0 & 1 only.
711 * This allow us to simplify the general BM algorithm to a very
713 /* assume 1 is in the 3th byte */
716 while (offset < size) {
717 if (1 == data[offset]) {
718 unsigned int shift = offset;
720 if (0 == data[--shift]) {
721 if (0 == data[--shift]) {
725 /* The jump is always 3 because of the 1 previously matched.
726 * All the 0's must be after this '1' matched at offset */
728 } else if (0 == data[offset]) {
729 /* maybe next byte is 1? */
732 /* can jump 3 bytes forward */
735 /* at each iteration, we rescan in a backward manner until
736 * we match 0.0.1 in reverse order. Since our search string
737 * has only 2 'alpabets' (i.e. 0 & 1), we know that any
738 * mismatch will force us to shift a fixed number of steps */
740 GST_DEBUG ("Cannot find next NAL start code. returning %u", size);
746 gst_rtp_h264_pay_decode_nal (GstRtpH264Pay * payloader,
747 const guint8 * data, guint size, GstClockTime dts, GstClockTime pts)
749 const guint8 *sps = NULL, *pps = NULL;
750 guint sps_len = 0, pps_len = 0;
755 /* default is no update */
758 GST_DEBUG ("NAL payload len=%u", size);
762 type = header & 0x1f;
764 /* keep sps & pps separately so that we can update either one
765 * independently. We also record the timestamp of the last SPS/PPS so
766 * that we can insert them at regular intervals and when needed. */
767 if (SPS_TYPE_ID == type) {
768 /* encode the entire SPS NAL in base64 */
769 GST_DEBUG ("Found SPS %x %x %x Len=%u", (header >> 7),
770 (header >> 5) & 3, type, len);
774 /* remember when we last saw SPS */
776 payloader->last_spspps = pts;
777 } else if (PPS_TYPE_ID == type) {
778 /* encoder the entire PPS NAL in base64 */
779 GST_DEBUG ("Found PPS %x %x %x Len = %u",
780 (header >> 7), (header >> 5) & 3, type, len);
784 /* remember when we last saw PPS */
786 payloader->last_spspps = pts;
788 GST_DEBUG ("NAL: %x %x %x Len = %u", (header >> 7),
789 (header >> 5) & 3, type, len);
792 /* If we encountered an SPS and/or a PPS, check if it's the
793 * same as the one we have. If not, update our version and
794 * set updated to TRUE
799 if (payloader->sps != NULL) {
800 sps_buf = GST_BUFFER_CAST (payloader->sps->data);
802 if (gst_buffer_memcmp (sps_buf, 0, sps, sps_len)) {
803 /* something changed, update */
804 payloader->profile = (sps[1] << 16) + (sps[2] << 8) + sps[3];
805 GST_DEBUG ("Profile level IDC = %06x", payloader->profile);
809 /* no previous SPS, update */
814 sps_buf = gst_buffer_new_and_alloc (sps_len);
815 gst_buffer_fill (sps_buf, 0, sps, sps_len);
817 if (payloader->sps) {
818 /* replace old buffer */
819 gst_buffer_unref (payloader->sps->data);
820 payloader->sps->data = sps_buf;
823 payloader->sps = g_list_prepend (payloader->sps, sps_buf);
831 if (payloader->pps != NULL) {
832 pps_buf = GST_BUFFER_CAST (payloader->pps->data);
834 if (gst_buffer_memcmp (pps_buf, 0, pps, pps_len)) {
835 /* something changed, update */
839 /* no previous SPS, update */
844 pps_buf = gst_buffer_new_and_alloc (pps_len);
845 gst_buffer_fill (pps_buf, 0, pps, pps_len);
847 if (payloader->pps) {
848 /* replace old buffer */
849 gst_buffer_unref (payloader->pps->data);
850 payloader->pps->data = pps_buf;
853 payloader->pps = g_list_prepend (payloader->pps, pps_buf);
861 gst_rtp_h264_pay_payload_nal (GstRTPBasePayload * basepayload,
862 GstBuffer * paybuf, GstClockTime dts, GstClockTime pts, gboolean end_of_au);
865 gst_rtp_h264_pay_send_sps_pps (GstRTPBasePayload * basepayload,
866 GstRtpH264Pay * rtph264pay, GstClockTime dts, GstClockTime pts)
868 GstFlowReturn ret = GST_FLOW_OK;
871 for (walk = rtph264pay->sps; walk; walk = g_list_next (walk)) {
872 GstBuffer *sps_buf = GST_BUFFER_CAST (walk->data);
874 GST_DEBUG_OBJECT (rtph264pay, "inserting SPS in the stream");
876 ret = gst_rtp_h264_pay_payload_nal (basepayload, gst_buffer_ref (sps_buf),
878 /* Not critical here; but throw a warning */
879 if (ret != GST_FLOW_OK)
880 GST_WARNING ("Problem pushing SPS");
882 for (walk = rtph264pay->pps; walk; walk = g_list_next (walk)) {
883 GstBuffer *pps_buf = GST_BUFFER_CAST (walk->data);
885 GST_DEBUG_OBJECT (rtph264pay, "inserting PPS in the stream");
887 ret = gst_rtp_h264_pay_payload_nal (basepayload, gst_buffer_ref (pps_buf),
889 /* Not critical here; but throw a warning */
890 if (ret != GST_FLOW_OK)
891 GST_WARNING ("Problem pushing PPS");
895 rtph264pay->last_spspps = pts;
901 gst_rtp_h264_pay_payload_nal (GstRTPBasePayload * basepayload,
902 GstBuffer * paybuf, GstClockTime dts, GstClockTime pts, gboolean end_of_au)
904 GstRtpH264Pay *rtph264pay;
907 guint packet_len, payload_len, mtu;
910 GstBufferList *list = NULL;
911 gboolean send_spspps;
912 GstRTPBuffer rtp = { NULL };
913 guint size = gst_buffer_get_size (paybuf);
915 rtph264pay = GST_RTP_H264_PAY (basepayload);
916 mtu = GST_RTP_BASE_PAYLOAD_MTU (rtph264pay);
918 gst_buffer_extract (paybuf, 0, &nalType, 1);
921 GST_DEBUG_OBJECT (rtph264pay, "Processing Buffer with NAL TYPE=%d", nalType);
923 /* should set src caps before pushing stuff,
924 * and if we did not see enough SPS/PPS, that may not be the case */
925 if (G_UNLIKELY (!gst_pad_has_current_caps (GST_RTP_BASE_PAYLOAD_SRCPAD
927 gst_rtp_h264_pay_set_sps_pps (basepayload);
931 /* check if we need to emit an SPS/PPS now */
932 if (nalType == IDR_TYPE_ID && rtph264pay->spspps_interval > 0) {
933 if (rtph264pay->last_spspps != -1) {
936 GST_LOG_OBJECT (rtph264pay,
937 "now %" GST_TIME_FORMAT ", last SPS/PPS %" GST_TIME_FORMAT,
938 GST_TIME_ARGS (pts), GST_TIME_ARGS (rtph264pay->last_spspps));
940 /* calculate diff between last SPS/PPS in milliseconds */
941 if (pts > rtph264pay->last_spspps)
942 diff = pts - rtph264pay->last_spspps;
946 GST_DEBUG_OBJECT (rtph264pay,
947 "interval since last SPS/PPS %" GST_TIME_FORMAT,
948 GST_TIME_ARGS (diff));
950 /* bigger than interval, queue SPS/PPS */
951 if (GST_TIME_AS_SECONDS (diff) >= rtph264pay->spspps_interval) {
952 GST_DEBUG_OBJECT (rtph264pay, "time to send SPS/PPS");
956 /* no know previous SPS/PPS time, send now */
957 GST_DEBUG_OBJECT (rtph264pay, "no previous SPS/PPS time, send now");
962 if (send_spspps || rtph264pay->send_spspps) {
963 /* we need to send SPS/PPS now first. FIXME, don't use the pts for
964 * checking when we need to send SPS/PPS but convert to running_time first. */
965 rtph264pay->send_spspps = FALSE;
966 ret = gst_rtp_h264_pay_send_sps_pps (basepayload, rtph264pay, dts, pts);
967 if (ret != GST_FLOW_OK)
971 packet_len = gst_rtp_buffer_calc_packet_len (size, 0, 0);
973 if (packet_len < mtu) {
974 GST_DEBUG_OBJECT (basepayload,
975 "NAL Unit fit in one packet datasize=%d mtu=%d", size, mtu);
976 /* will fit in one packet */
979 * create buffer without payload containing only the RTP header
980 * (memory block at index 0) */
981 outbuf = gst_rtp_buffer_new_allocate (0, 0, 0);
983 gst_rtp_buffer_map (outbuf, GST_MAP_WRITE, &rtp);
985 /* only set the marker bit on packets containing access units */
986 if (IS_ACCESS_UNIT (nalType) && end_of_au) {
987 gst_rtp_buffer_set_marker (&rtp, 1);
990 /* timestamp the outbuffer */
991 GST_BUFFER_PTS (outbuf) = pts;
992 GST_BUFFER_DTS (outbuf) = dts;
994 /* insert payload memory block */
995 outbuf = gst_buffer_append (outbuf, paybuf);
997 list = gst_buffer_list_new ();
999 /* add the buffer to the buffer list */
1000 gst_buffer_list_add (list, outbuf);
1002 gst_rtp_buffer_unmap (&rtp);
1004 /* push the list to the next element in the pipe */
1005 ret = gst_rtp_base_payload_push_list (basepayload, list);
1007 /* fragmentation Units FU-A */
1010 int ii = 0, start = 1, end = 0, pos = 0;
1012 GST_DEBUG_OBJECT (basepayload,
1013 "NAL Unit DOES NOT fit in one packet datasize=%d mtu=%d", size, mtu);
1015 gst_buffer_extract (paybuf, 0, &nalHeader, 1);
1021 GST_DEBUG_OBJECT (basepayload, "Using FU-A fragmentation for data size=%d",
1024 /* We keep 2 bytes for FU indicator and FU Header */
1025 payload_len = gst_rtp_buffer_calc_payload_len (mtu - 2, 0, 0);
1027 list = gst_buffer_list_new ();
1030 limitedSize = size < payload_len ? size : payload_len;
1031 GST_DEBUG_OBJECT (basepayload,
1032 "Inside FU-A fragmentation limitedSize=%d iteration=%d", limitedSize,
1036 * create buffer without payload containing only the RTP header
1037 * (memory block at index 0) */
1038 outbuf = gst_rtp_buffer_new_allocate (2, 0, 0);
1040 gst_rtp_buffer_map (outbuf, GST_MAP_WRITE, &rtp);
1042 GST_BUFFER_DTS (outbuf) = dts;
1043 GST_BUFFER_PTS (outbuf) = pts;
1044 payload = gst_rtp_buffer_get_payload (&rtp);
1046 if (limitedSize == size) {
1047 GST_DEBUG_OBJECT (basepayload, "end size=%d iteration=%d", size, ii);
1050 if (IS_ACCESS_UNIT (nalType)) {
1051 gst_rtp_buffer_set_marker (&rtp, end && end_of_au);
1055 payload[0] = (nalHeader & 0x60) | 28;
1058 payload[1] = (start << 7) | (end << 6) | (nalHeader & 0x1f);
1060 gst_rtp_buffer_unmap (&rtp);
1062 /* insert payload memory block */
1063 gst_buffer_append (outbuf,
1064 gst_buffer_copy_region (paybuf, GST_BUFFER_COPY_MEMORY, pos,
1067 /* add the buffer to the buffer list */
1068 gst_buffer_list_add (list, outbuf);
1071 size -= limitedSize;
1077 ret = gst_rtp_base_payload_push_list (basepayload, list);
1078 gst_buffer_unref (paybuf);
1083 static GstFlowReturn
1084 gst_rtp_h264_pay_handle_buffer (GstRTPBasePayload * basepayload,
1087 GstRtpH264Pay *rtph264pay;
1093 GstClockTime dts, pts;
1096 GstBuffer *paybuf = NULL;
1099 rtph264pay = GST_RTP_H264_PAY (basepayload);
1101 /* the input buffer contains one or more NAL units */
1103 avc = rtph264pay->stream_format == GST_H264_STREAM_FORMAT_AVC;
1106 /* In AVC mode, there is no adapter, so nothign to flush */
1109 gst_buffer_map (buffer, &map, GST_MAP_READ);
1112 pts = GST_BUFFER_PTS (buffer);
1113 dts = GST_BUFFER_DTS (buffer);
1114 GST_DEBUG_OBJECT (basepayload, "got %" G_GSIZE_FORMAT " bytes", size);
1116 dts = gst_adapter_prev_dts (rtph264pay->adapter, NULL);
1117 pts = gst_adapter_prev_pts (rtph264pay->adapter, NULL);
1119 if (!GST_CLOCK_TIME_IS_VALID (dts))
1120 dts = GST_BUFFER_DTS (buffer);
1121 if (!GST_CLOCK_TIME_IS_VALID (pts))
1122 pts = GST_BUFFER_PTS (buffer);
1124 gst_adapter_push (rtph264pay->adapter, buffer);
1126 size = gst_adapter_available (rtph264pay->adapter);
1127 /* Nothing to do here if the adapter is empty, e.g. on EOS */
1130 data = gst_adapter_map (rtph264pay->adapter, size);
1131 GST_DEBUG_OBJECT (basepayload,
1132 "got %" G_GSIZE_FORMAT " bytes (%" G_GSIZE_FORMAT ")", size,
1133 buffer ? gst_buffer_get_size (buffer) : 0);
1138 /* now loop over all NAL units and put them in a packet
1139 * FIXME, we should really try to pack multiple NAL units into one RTP packet
1140 * if we can, especially for the config packets that wont't cause decoder
1143 guint nal_length_size;
1146 nal_length_size = rtph264pay->nal_length_size;
1148 while (size > nal_length_size) {
1150 gboolean end_of_au = FALSE;
1153 for (i = 0; i < nal_length_size; i++) {
1154 nal_len = ((nal_len << 8) + data[i]);
1157 /* skip the length bytes, make sure we don't run past the buffer size */
1158 data += nal_length_size;
1159 offset += nal_length_size;
1160 size -= nal_length_size;
1162 if (size >= nal_len) {
1163 GST_DEBUG_OBJECT (basepayload, "got NAL of size %u", nal_len);
1166 GST_DEBUG_OBJECT (basepayload, "got incomplete NAL of size %u",
1170 /* If we're at the end of the buffer, then we're at the end of the
1173 if (rtph264pay->alignment == GST_H264_ALIGNMENT_AU
1174 && size - nal_len <= nal_length_size) {
1178 paybuf = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_MEMORY, offset,
1181 gst_rtp_h264_pay_payload_nal (basepayload, paybuf, dts, pts,
1183 if (ret != GST_FLOW_OK)
1192 gboolean update = FALSE;
1194 /* get offset of first start code */
1195 next = next_start_code (data, size);
1197 /* skip to start code, if no start code is found, next will be size and we
1198 * will not collect data. */
1201 nal_queue = rtph264pay->queue;
1204 /* array must be empty when we get here */
1205 g_assert (nal_queue->len == 0);
1207 GST_DEBUG_OBJECT (basepayload,
1208 "found first start at %u, bytes left %" G_GSIZE_FORMAT, next, size);
1210 /* first pass to locate NALs and parse SPS/PPS */
1212 /* skip start code */
1216 /* use next_start_code() to scan buffer.
1217 * next_start_code() returns the offset in data,
1218 * starting from zero to the first byte of 0.0.0.1
1219 * If no start code is found, it returns the value of the
1221 * data is unchanged by the call to next_start_code()
1223 next = next_start_code (data, size);
1225 if (next == size && buffer != NULL) {
1226 /* Didn't find the start of next NAL and it's not EOS,
1227 * handle it next time */
1231 /* nal length is distance to next start code */
1234 GST_DEBUG_OBJECT (basepayload, "found next start at %u of size %u", next,
1237 if (rtph264pay->sprop_parameter_sets != NULL) {
1238 /* explicitly set profile and sprop, use those */
1239 if (rtph264pay->update_caps) {
1240 if (!gst_rtp_base_payload_set_outcaps (basepayload,
1241 "sprop-parameter-sets", G_TYPE_STRING,
1242 rtph264pay->sprop_parameter_sets, NULL))
1245 /* parse SPS and PPS from provided parameter set (for insertion) */
1246 gst_rtp_h264_pay_parse_sprop_parameter_sets (rtph264pay);
1248 rtph264pay->update_caps = FALSE;
1250 GST_DEBUG ("outcaps update: sprop-parameter-sets=%s",
1251 rtph264pay->sprop_parameter_sets);
1254 /* We know our stream is a valid H264 NAL packet,
1255 * go parse it for SPS/PPS to enrich the caps */
1256 /* order: make sure to check nal */
1258 gst_rtp_h264_pay_decode_nal (rtph264pay, data, nal_len, dts, pts)
1261 /* move to next NAL packet */
1265 g_array_append_val (nal_queue, nal_len);
1268 /* if has new SPS & PPS, update the output caps */
1269 if (G_UNLIKELY (update))
1270 if (!gst_rtp_h264_pay_set_sps_pps (basepayload))
1273 /* second pass to payload and push */
1275 if (nal_queue->len != 0)
1276 gst_adapter_flush (rtph264pay->adapter, skip);
1278 for (i = 0; i < nal_queue->len; i++) {
1280 gboolean end_of_au = FALSE;
1282 nal_len = g_array_index (nal_queue, guint, i);
1283 /* skip start code */
1284 gst_adapter_flush (rtph264pay->adapter, 3);
1286 /* Trim the end unless we're the last NAL in the stream.
1287 * In case we're not at the end of the buffer we know the next block
1288 * starts with 0x000001 so all the 0x00 bytes at the end of this one are
1289 * trailing 0x0 that can be discarded */
1291 data = gst_adapter_map (rtph264pay->adapter, size);
1292 if (i + 1 != nal_queue->len || buffer != NULL)
1293 for (; size > 1 && data[size - 1] == 0x0; size--)
1297 /* If it's the last nal unit we have in non-bytestream mode, we can
1298 * assume it's the end of an access-unit
1300 * FIXME: We need to wait until the next packet or EOS to
1301 * actually payload the NAL so we can know if the current NAL is
1302 * the last one of an access unit or not if we are in bytestream mode
1304 if ((rtph264pay->alignment == GST_H264_ALIGNMENT_AU || buffer == NULL) &&
1305 i == nal_queue->len - 1)
1307 paybuf = gst_adapter_take_buffer (rtph264pay->adapter, size);
1310 /* put the data in one or more RTP packets */
1312 gst_rtp_h264_pay_payload_nal (basepayload, paybuf, dts, pts,
1314 if (ret != GST_FLOW_OK) {
1318 /* move to next NAL packet */
1319 /* Skips the trailing zeros */
1320 gst_adapter_flush (rtph264pay->adapter, nal_len - size);
1322 g_array_set_size (nal_queue, 0);
1327 gst_buffer_unmap (buffer, &map);
1328 gst_buffer_unref (buffer);
1330 gst_adapter_unmap (rtph264pay->adapter);
1337 GST_WARNING_OBJECT (basepayload, "Could not set outcaps");
1338 g_array_set_size (nal_queue, 0);
1339 ret = GST_FLOW_NOT_NEGOTIATED;
1345 gst_rtp_h264_pay_sink_event (GstRTPBasePayload * payload, GstEvent * event)
1348 const GstStructure *s;
1349 GstRtpH264Pay *rtph264pay = GST_RTP_H264_PAY (payload);
1351 switch (GST_EVENT_TYPE (event)) {
1352 case GST_EVENT_FLUSH_STOP:
1353 gst_adapter_clear (rtph264pay->adapter);
1355 case GST_EVENT_CUSTOM_DOWNSTREAM:
1356 s = gst_event_get_structure (event);
1357 if (gst_structure_has_name (s, "GstForceKeyUnit")) {
1358 gboolean resend_codec_data;
1360 if (gst_structure_get_boolean (s, "all-headers",
1361 &resend_codec_data) && resend_codec_data)
1362 rtph264pay->send_spspps = TRUE;
1367 /* call handle_buffer with NULL to flush last NAL from adapter
1368 * in byte-stream mode
1370 gst_rtp_h264_pay_handle_buffer (payload, NULL);
1377 res = GST_RTP_BASE_PAYLOAD_CLASS (parent_class)->sink_event (payload, event);
1382 static GstStateChangeReturn
1383 gst_rtp_h264_pay_change_state (GstElement * element, GstStateChange transition)
1385 GstStateChangeReturn ret;
1386 GstRtpH264Pay *rtph264pay = GST_RTP_H264_PAY (element);
1388 switch (transition) {
1389 case GST_STATE_CHANGE_READY_TO_PAUSED:
1390 rtph264pay->send_spspps = FALSE;
1391 gst_adapter_clear (rtph264pay->adapter);
1397 ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
1403 gst_rtp_h264_pay_set_property (GObject * object, guint prop_id,
1404 const GValue * value, GParamSpec * pspec)
1406 GstRtpH264Pay *rtph264pay;
1408 rtph264pay = GST_RTP_H264_PAY (object);
1411 case PROP_SPROP_PARAMETER_SETS:
1412 g_free (rtph264pay->sprop_parameter_sets);
1413 rtph264pay->sprop_parameter_sets = g_value_dup_string (value);
1414 rtph264pay->update_caps = TRUE;
1416 case PROP_CONFIG_INTERVAL:
1417 rtph264pay->spspps_interval = g_value_get_uint (value);
1420 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1426 gst_rtp_h264_pay_get_property (GObject * object, guint prop_id,
1427 GValue * value, GParamSpec * pspec)
1429 GstRtpH264Pay *rtph264pay;
1431 rtph264pay = GST_RTP_H264_PAY (object);
1434 case PROP_SPROP_PARAMETER_SETS:
1435 g_value_set_string (value, rtph264pay->sprop_parameter_sets);
1437 case PROP_CONFIG_INTERVAL:
1438 g_value_set_uint (value, rtph264pay->spspps_interval);
1441 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1447 gst_rtp_h264_pay_plugin_init (GstPlugin * plugin)
1449 return gst_element_register (plugin, "rtph264pay",
1450 GST_RANK_SECONDARY, GST_TYPE_RTP_H264_PAY);