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