• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* GStreamer
2  * Copyright (C) <2006> Wim Taymans <wim.taymans@gmail.com>
3  * Copyright (C) <2014> Jurgen Slowack <jurgenslowack@gmail.com>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
18  * Boston, MA 02110-1301, USA.
19  */
20 
21 #ifdef HAVE_CONFIG_H
22 #  include "config.h"
23 #endif
24 
25 #include <string.h>
26 #include <stdlib.h>
27 
28 #include <gst/rtp/gstrtpbuffer.h>
29 #include <gst/pbutils/pbutils.h>
30 #include <gst/video/video.h>
31 
32 /* Included to not duplicate gst_rtp_h265_add_vps_sps_pps () */
33 #include "gstrtph265depay.h"
34 
35 #include "gstrtpelements.h"
36 #include "gstrtph265pay.h"
37 #include "gstrtputils.h"
38 #include "gstbuffermemory.h"
39 
40 #define AP_TYPE_ID  48
41 #define FU_TYPE_ID  49
42 
43 GST_DEBUG_CATEGORY_STATIC (rtph265pay_debug);
44 #define GST_CAT_DEFAULT (rtph265pay_debug)
45 
46 #define GST_TYPE_RTP_H265_AGGREGATE_MODE \
47   (gst_rtp_h265_aggregate_mode_get_type ())
48 
49 
50 static GType
gst_rtp_h265_aggregate_mode_get_type(void)51 gst_rtp_h265_aggregate_mode_get_type (void)
52 {
53   static GType type = 0;
54   static const GEnumValue values[] = {
55     {GST_RTP_H265_AGGREGATE_NONE, "Do not aggregate NAL units", "none"},
56     {GST_RTP_H265_AGGREGATE_ZERO_LATENCY,
57           "Aggregate NAL units until a VCL or suffix unit is included",
58         "zero-latency"},
59     {GST_RTP_H265_AGGREGATE_MAX,
60         "Aggregate all NAL units with the same timestamp (adds one frame of"
61           " latency)", "max"},
62     {0, NULL, NULL},
63   };
64 
65   if (!type) {
66     type = g_enum_register_static ("GstRtpH265AggregateMode", values);
67   }
68   return type;
69 }
70 
71 
72 
73 /* references:
74  *
75  * Internet Draft RTP Payload Format for High Efficiency Video Coding
76  *
77  *                   draft-ietf-payload-rtp-h265-03.txt
78  *
79  * This draft will be replaced with an RFC, so some details may change.
80  *
81  */
82 
83 static GstStaticPadTemplate gst_rtp_h265_pay_sink_template =
84     GST_STATIC_PAD_TEMPLATE ("sink",
85     GST_PAD_SINK,
86     GST_PAD_ALWAYS,
87     GST_STATIC_CAPS (
88         /* only hvc1 and byte-stream formats supported for now */
89         "video/x-h265, stream-format = (string) hvc1, alignment = (string) au; "
90         /* "video/x-h265, "
91            "stream-format = (string) hev1, alignment = (string) au; " */
92         "video/x-h265, stream-format = (string) byte-stream, "
93         "alignment = (string) { nal, au }")
94     );
95 
96 static GstStaticPadTemplate gst_rtp_h265_pay_src_template =
97 GST_STATIC_PAD_TEMPLATE ("src",
98     GST_PAD_SRC,
99     GST_PAD_ALWAYS,
100     GST_STATIC_CAPS ("application/x-rtp, "
101         "media = (string) \"video\", "
102         "payload = (int) " GST_RTP_PAYLOAD_DYNAMIC_STRING ", "
103         "clock-rate = (int) 90000, " "encoding-name = (string) \"H265\"")
104     /* optional parameters */
105     /* "profile-space = (int) [ 0, 3 ], " */
106     /* "profile-id = (int) [ 0, 31 ], " */
107     /* "tier-flag = (int) [ 0, 1 ], " */
108     /* "level-id = (int) [ 0, 255 ], " */
109     /* "interop-constraints = (string) ANY, " */
110     /* "profile-compatibility-indicator = (string) ANY, " */
111     /* "sprop-sub-layer-id = (int) [ 0, 6 ], " */
112     /* "recv-sub-layer-id = (int) [ 0, 6 ], " */
113     /* "max-recv-level-id = (int) [ 0, 255 ], " */
114     /* "tx-mode = (string) {MST , SST}, " */
115     /* "sprop-vps = (string) ANY, " */
116     /* "sprop-sps = (string) ANY, " */
117     /* "sprop-pps = (string) ANY, " */
118     /* "sprop-sei = (string) ANY, " */
119     /* "max-lsr = (int) ANY, " *//* MUST be in the range of MaxLumaSR to 16 * MaxLumaSR, inclusive */
120     /* "max-lps = (int) ANY, " *//* MUST be in the range of MaxLumaPS to 16 * MaxLumaPS, inclusive */
121     /* "max-cpb = (int) ANY, " *//* MUST be in the range of MaxCPB to 16 * MaxCPB, inclusive */
122     /* "max-dpb = (int) [1, 16], " */
123     /* "max-br = (int) ANY, " *//* MUST be in the range of MaxBR to 16 * MaxBR, inclusive, for the highest level */
124     /* "max-tr = (int) ANY, " *//* MUST be in the range of MaxTileRows to 16 * MaxTileRows, inclusive, for the highest level */
125     /* "max-tc = (int) ANY, " *//* MUST be in the range of MaxTileCols to 16 * MaxTileCols, inclusive, for the highest level */
126     /* "max-fps = (int) ANY, " */
127     /* "sprop-max-don-diff = (int) [0, 32767], " */
128     /* "sprop-depack-buf-nalus = (int) [0, 32767], " */
129     /* "sprop-depack-buf-nalus = (int) [0, 4294967295], " */
130     /* "depack-buf-cap = (int) [1, 4294967295], " */
131     /* "sprop-segmentation-id = (int) [0, 3], " */
132     /* "sprop-spatial-segmentation-idc = (string) ANY, " */
133     /* "dec-parallel-cap = (string) ANY, " */
134     );
135 
136 #define DEFAULT_CONFIG_INTERVAL         0
137 #define DEFAULT_AGGREGATE_MODE          GST_RTP_H265_AGGREGATE_NONE
138 
139 enum
140 {
141   PROP_0,
142   PROP_CONFIG_INTERVAL,
143   PROP_AGGREGATE_MODE,
144 };
145 
146 static void gst_rtp_h265_pay_finalize (GObject * object);
147 
148 static void gst_rtp_h265_pay_set_property (GObject * object, guint prop_id,
149     const GValue * value, GParamSpec * pspec);
150 static void gst_rtp_h265_pay_get_property (GObject * object, guint prop_id,
151     GValue * value, GParamSpec * pspec);
152 
153 static GstCaps *gst_rtp_h265_pay_getcaps (GstRTPBasePayload * payload,
154     GstPad * pad, GstCaps * filter);
155 static gboolean gst_rtp_h265_pay_setcaps (GstRTPBasePayload * basepayload,
156     GstCaps * caps);
157 static GstFlowReturn gst_rtp_h265_pay_handle_buffer (GstRTPBasePayload * pad,
158     GstBuffer * buffer);
159 static gboolean gst_rtp_h265_pay_sink_event (GstRTPBasePayload * payload,
160     GstEvent * event);
161 static GstStateChangeReturn gst_rtp_h265_pay_change_state (GstElement *
162     element, GstStateChange transition);
163 static gboolean gst_rtp_h265_pay_src_query (GstPad * pad, GstObject * parent,
164     GstQuery * query);
165 
166 static void gst_rtp_h265_pay_reset_bundle (GstRtpH265Pay * rtph265pay);
167 
168 #define gst_rtp_h265_pay_parent_class parent_class
169 G_DEFINE_TYPE (GstRtpH265Pay, gst_rtp_h265_pay, GST_TYPE_RTP_BASE_PAYLOAD);
170 GST_ELEMENT_REGISTER_DEFINE_WITH_CODE (rtph265pay, "rtph265pay",
171     GST_RANK_SECONDARY, GST_TYPE_RTP_H265_PAY, rtp_element_init (plugin));
172 
173 static void
gst_rtp_h265_pay_class_init(GstRtpH265PayClass * klass)174 gst_rtp_h265_pay_class_init (GstRtpH265PayClass * klass)
175 {
176   GObjectClass *gobject_class;
177   GstElementClass *gstelement_class;
178   GstRTPBasePayloadClass *gstrtpbasepayload_class;
179 
180   gobject_class = (GObjectClass *) klass;
181   gstelement_class = (GstElementClass *) klass;
182   gstrtpbasepayload_class = (GstRTPBasePayloadClass *) klass;
183 
184   gobject_class->set_property = gst_rtp_h265_pay_set_property;
185   gobject_class->get_property = gst_rtp_h265_pay_get_property;
186 
187   g_object_class_install_property (G_OBJECT_CLASS (klass),
188       PROP_CONFIG_INTERVAL,
189       g_param_spec_int ("config-interval",
190           "VPS SPS PPS Send Interval",
191           "Send VPS, SPS and PPS Insertion Interval in seconds (sprop parameter sets "
192           "will be multiplexed in the data stream when detected.) "
193           "(0 = disabled, -1 = send with every IDR frame)",
194           -1, 3600, DEFAULT_CONFIG_INTERVAL,
195           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)
196       );
197 
198   /**
199    * GstRtpH265Pay:aggregate-mode
200    *
201    * Bundle suitable SPS/PPS NAL units into STAP-A aggregate packets.
202    *
203    * This can potentially reduce RTP packetization overhead but not all
204    * RTP implementations handle it correctly.
205    *
206    * For best compatibility, it is recommended to set this to "none" (the
207    * default) for RTSP and for WebRTC to "zero-latency".
208    *
209    * Since: 1.18
210    */
211   g_object_class_install_property (G_OBJECT_CLASS (klass),
212       PROP_AGGREGATE_MODE,
213       g_param_spec_enum ("aggregate-mode",
214           "Attempt to use aggregate packets",
215           "Bundle suitable SPS/PPS NAL units into aggregate packets.",
216           GST_TYPE_RTP_H265_AGGREGATE_MODE,
217           DEFAULT_AGGREGATE_MODE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)
218       );
219 
220   gobject_class->finalize = gst_rtp_h265_pay_finalize;
221 
222   gst_element_class_add_static_pad_template (gstelement_class,
223       &gst_rtp_h265_pay_src_template);
224   gst_element_class_add_static_pad_template (gstelement_class,
225       &gst_rtp_h265_pay_sink_template);
226 
227   gst_element_class_set_static_metadata (gstelement_class, "RTP H265 payloader",
228       "Codec/Payloader/Network/RTP",
229       "Payload-encode H265 video into RTP packets (RFC 7798)",
230       "Jurgen Slowack <jurgenslowack@gmail.com>");
231 
232   gstelement_class->change_state =
233       GST_DEBUG_FUNCPTR (gst_rtp_h265_pay_change_state);
234 
235   gstrtpbasepayload_class->get_caps = gst_rtp_h265_pay_getcaps;
236   gstrtpbasepayload_class->set_caps = gst_rtp_h265_pay_setcaps;
237   gstrtpbasepayload_class->handle_buffer = gst_rtp_h265_pay_handle_buffer;
238   gstrtpbasepayload_class->sink_event = gst_rtp_h265_pay_sink_event;
239 
240   GST_DEBUG_CATEGORY_INIT (rtph265pay_debug, "rtph265pay", 0,
241       "H265 RTP Payloader");
242 
243   gst_type_mark_as_plugin_api (GST_TYPE_RTP_H265_AGGREGATE_MODE, 0);
244 }
245 
246 static void
gst_rtp_h265_pay_init(GstRtpH265Pay * rtph265pay)247 gst_rtp_h265_pay_init (GstRtpH265Pay * rtph265pay)
248 {
249   rtph265pay->queue = g_array_new (FALSE, FALSE, sizeof (guint));
250   rtph265pay->sps = g_ptr_array_new_with_free_func (
251       (GDestroyNotify) gst_buffer_unref);
252   rtph265pay->pps = g_ptr_array_new_with_free_func (
253       (GDestroyNotify) gst_buffer_unref);
254   rtph265pay->vps = g_ptr_array_new_with_free_func (
255       (GDestroyNotify) gst_buffer_unref);
256   rtph265pay->last_vps_sps_pps = -1;
257   rtph265pay->vps_sps_pps_interval = DEFAULT_CONFIG_INTERVAL;
258   rtph265pay->aggregate_mode = DEFAULT_AGGREGATE_MODE;
259 
260   rtph265pay->adapter = gst_adapter_new ();
261 
262   gst_pad_set_query_function (GST_RTP_BASE_PAYLOAD_SRCPAD (rtph265pay),
263       gst_rtp_h265_pay_src_query);
264 }
265 
266 static void
gst_rtp_h265_pay_clear_vps_sps_pps(GstRtpH265Pay * rtph265pay)267 gst_rtp_h265_pay_clear_vps_sps_pps (GstRtpH265Pay * rtph265pay)
268 {
269   g_ptr_array_set_size (rtph265pay->vps, 0);
270   g_ptr_array_set_size (rtph265pay->sps, 0);
271   g_ptr_array_set_size (rtph265pay->pps, 0);
272 }
273 
274 static void
gst_rtp_h265_pay_finalize(GObject * object)275 gst_rtp_h265_pay_finalize (GObject * object)
276 {
277   GstRtpH265Pay *rtph265pay;
278 
279   rtph265pay = GST_RTP_H265_PAY (object);
280 
281   g_array_free (rtph265pay->queue, TRUE);
282 
283   g_ptr_array_free (rtph265pay->sps, TRUE);
284   g_ptr_array_free (rtph265pay->pps, TRUE);
285   g_ptr_array_free (rtph265pay->vps, TRUE);
286 
287   g_object_unref (rtph265pay->adapter);
288 
289   gst_rtp_h265_pay_reset_bundle (rtph265pay);
290 
291   G_OBJECT_CLASS (parent_class)->finalize (object);
292 }
293 
294 static gboolean
gst_rtp_h265_pay_src_query(GstPad * pad,GstObject * parent,GstQuery * query)295 gst_rtp_h265_pay_src_query (GstPad * pad, GstObject * parent, GstQuery * query)
296 {
297   GstRtpH265Pay *rtph265pay = GST_RTP_H265_PAY (parent);
298 
299   if (GST_QUERY_TYPE (query) == GST_QUERY_LATENCY) {
300     gboolean retval;
301     gboolean live;
302     GstClockTime min_latency, max_latency;
303 
304     retval = gst_pad_query_default (pad, parent, query);
305     if (!retval)
306       return retval;
307 
308     if (rtph265pay->stream_format == GST_H265_STREAM_FORMAT_UNKNOWN ||
309         rtph265pay->alignment == GST_H265_ALIGNMENT_UNKNOWN)
310       return FALSE;
311 
312     gst_query_parse_latency (query, &live, &min_latency, &max_latency);
313 
314     if (rtph265pay->aggregate_mode == GST_RTP_H265_AGGREGATE_MAX &&
315         rtph265pay->alignment != GST_H265_ALIGNMENT_AU && rtph265pay->fps_num) {
316       GstClockTime one_frame = gst_util_uint64_scale_int (GST_SECOND,
317           rtph265pay->fps_denum, rtph265pay->fps_num);
318 
319       min_latency += one_frame;
320       max_latency += one_frame;
321       gst_query_set_latency (query, live, min_latency, max_latency);
322     }
323     return TRUE;
324   }
325 
326   return gst_pad_query_default (pad, parent, query);
327 }
328 
329 
330 static const gchar all_levels[][4] = {
331   "1",
332   "2",
333   "2.1",
334   "3",
335   "3.1",
336   "4",
337   "4.1",
338   "5",
339   "5.1",
340   "5.2",
341   "6",
342   "6.1",
343   "6.2"
344 };
345 
346 static gboolean
parse_field(GstStructure * s,const gchar * field,gulong min,gulong max,guint8 * result)347 parse_field (GstStructure * s, const gchar * field, gulong min, gulong max,
348     guint8 * result)
349 {
350   const gchar *str;
351 
352   g_assert (result != NULL);
353 
354   str = gst_structure_get_string (s, field);
355   if (str != NULL && *str != '\0') {
356     gulong value;
357     gchar *end;
358 
359     value = strtoul (str, &end, 10);
360     if (*end == '\0' && value >= min && value <= max) {
361       *result = (guint8) value;
362     } else {
363       return FALSE;
364     }
365   } else {
366     return FALSE;
367   }
368 
369   return TRUE;
370 }
371 
372 static GstCaps *
gst_rtp_h265_pay_getcaps(GstRTPBasePayload * payload,GstPad * pad,GstCaps * filter)373 gst_rtp_h265_pay_getcaps (GstRTPBasePayload * payload, GstPad * pad,
374     GstCaps * filter)
375 {
376   GstCaps *template_caps;
377   GstCaps *allowed_caps;
378   GstCaps *caps;
379   GstCaps *icaps;
380   guint i;
381 
382   allowed_caps =
383       gst_pad_peer_query_caps (GST_RTP_BASE_PAYLOAD_SRCPAD (payload), NULL);
384 
385   if (allowed_caps == NULL)
386     return NULL;
387 
388   template_caps =
389       gst_static_pad_template_get_caps (&gst_rtp_h265_pay_sink_template);
390 
391   if (gst_caps_is_any (allowed_caps)) {
392     caps = gst_caps_ref (template_caps);
393     goto done;
394   }
395 
396   if (gst_caps_is_empty (allowed_caps)) {
397     caps = gst_caps_ref (allowed_caps);
398     goto done;
399   }
400 
401   caps = gst_caps_new_empty ();
402   for (i = 0; i < gst_caps_get_size (allowed_caps); i++) {
403     GstStructure *s = gst_caps_get_structure (allowed_caps, i);
404     GstStructure *new_s = gst_structure_new_empty ("video/x-h265");
405     guint8 ptl[12] = { 0, };
406     guint8 value;
407 
408     if (parse_field (s, "profile-id", 0, 31, &value)) {
409       const gchar *profile;
410 
411       ptl[0] = value;
412       profile = gst_codec_utils_h265_get_profile (ptl, sizeof (ptl));
413       if (profile != NULL) {
414         GST_DEBUG_OBJECT (payload, "profile %s", profile);
415         gst_structure_set (new_s, "profile", G_TYPE_STRING, profile, NULL);
416       } else {
417         GST_WARNING_OBJECT (payload, "invalid profile-id %d in caps", value);
418       }
419     } else {
420       GST_DEBUG_OBJECT (payload, "no valid profile-id in caps");
421     }
422 
423     if (parse_field (s, "tier-flag", 0, 1, &value)) {
424       const gchar *tier;
425 
426       ptl[0] |= value << 5;
427       tier = gst_codec_utils_h265_get_tier (ptl, sizeof (ptl));
428       GST_DEBUG_OBJECT (payload, "tier %s", tier);
429       gst_structure_set (new_s, "tier", G_TYPE_STRING, tier, NULL);
430     } else {
431       GST_DEBUG_OBJECT (payload, "no valid tier-flag in caps");
432     }
433 
434     if (parse_field (s, "level-id", 0, 255, &value)) {
435       const gchar *level;
436 
437       ptl[11] = value;
438       level = gst_codec_utils_h265_get_level (ptl, sizeof (ptl));
439       if (level != NULL) {
440         GST_DEBUG_OBJECT (payload, "level %s", level);
441         if (strcmp (level, "1") == 0) {
442           gst_structure_set (new_s, "level", G_TYPE_STRING, level, NULL);
443         } else {
444           GValue levels = { 0, };
445           GValue val = { 0, };
446           int j;
447 
448           g_value_init (&levels, GST_TYPE_LIST);
449           g_value_init (&val, G_TYPE_STRING);
450 
451           for (j = 0; j < G_N_ELEMENTS (all_levels); j++) {
452             g_value_set_static_string (&val, all_levels[j]);
453             gst_value_list_prepend_value (&levels, &val);
454             if (!strcmp (level, all_levels[j]))
455               break;
456           }
457           gst_structure_take_value (new_s, "level", &levels);
458         }
459       } else {
460         GST_WARNING_OBJECT (payload, "invalid level-id %d in caps", value);
461       }
462     } else {
463       GST_DEBUG_OBJECT (payload, "no valid level-id in caps");
464     }
465 
466     caps = gst_caps_merge_structure (caps, new_s);
467   }
468 
469   icaps = gst_caps_intersect (caps, template_caps);
470   gst_caps_unref (caps);
471   caps = icaps;
472 
473 done:
474 
475   if (filter) {
476     GstCaps *tmp;
477 
478     GST_DEBUG_OBJECT (payload, "Intersect %" GST_PTR_FORMAT " and filter %"
479         GST_PTR_FORMAT, caps, filter);
480     tmp = gst_caps_intersect_full (filter, caps, GST_CAPS_INTERSECT_FIRST);
481     gst_caps_unref (caps);
482     caps = tmp;
483   }
484 
485   gst_caps_unref (template_caps);
486   gst_caps_unref (allowed_caps);
487 
488   GST_LOG_OBJECT (payload, "returning caps %" GST_PTR_FORMAT, caps);
489   return caps;
490 }
491 
492 /* take the currently configured VPS, SPS and PPS lists and set them on the
493  * caps */
494 static gboolean
gst_rtp_h265_pay_set_vps_sps_pps(GstRTPBasePayload * basepayload)495 gst_rtp_h265_pay_set_vps_sps_pps (GstRTPBasePayload * basepayload)
496 {
497   GstRtpH265Pay *payloader = GST_RTP_H265_PAY (basepayload);
498   gchar *set;
499   GString *vps;
500   GString *sps;
501   GString *pps;
502   guint count;
503   gboolean res;
504   GstMapInfo map;
505   guint i;
506 
507   vps = g_string_new ("");
508   sps = g_string_new ("");
509   pps = g_string_new ("");
510   count = 0;
511 
512   for (i = 0; i < payloader->vps->len; i++) {
513     GstBuffer *vps_buf =
514         GST_BUFFER_CAST (g_ptr_array_index (payloader->vps, i));
515 
516     gst_buffer_map (vps_buf, &map, GST_MAP_READ);
517     set = g_base64_encode (map.data, map.size);
518     gst_buffer_unmap (vps_buf, &map);
519 
520     g_string_append_printf (vps, "%s%s", i ? "," : "", set);
521     g_free (set);
522     count++;
523   }
524   for (i = 0; i < payloader->sps->len; i++) {
525     GstBuffer *sps_buf =
526         GST_BUFFER_CAST (g_ptr_array_index (payloader->sps, i));
527 
528     gst_buffer_map (sps_buf, &map, GST_MAP_READ);
529     set = g_base64_encode (map.data, map.size);
530     gst_buffer_unmap (sps_buf, &map);
531 
532     g_string_append_printf (sps, "%s%s", i ? "," : "", set);
533     g_free (set);
534     count++;
535   }
536   for (i = 0; i < payloader->pps->len; i++) {
537     GstBuffer *pps_buf =
538         GST_BUFFER_CAST (g_ptr_array_index (payloader->pps, i));
539 
540     gst_buffer_map (pps_buf, &map, GST_MAP_READ);
541     set = g_base64_encode (map.data, map.size);
542     gst_buffer_unmap (pps_buf, &map);
543 
544     g_string_append_printf (pps, "%s%s", i ? "," : "", set);
545     g_free (set);
546     count++;
547   }
548 
549   if (G_LIKELY (count)) {
550     /* combine into output caps */
551     res = gst_rtp_base_payload_set_outcaps (basepayload,
552         "sprop-vps", G_TYPE_STRING, vps->str,
553         "sprop-sps", G_TYPE_STRING, sps->str,
554         "sprop-pps", G_TYPE_STRING, pps->str, NULL);
555   } else {
556     res = gst_rtp_base_payload_set_outcaps (basepayload, NULL);
557   }
558   g_string_free (vps, TRUE);
559   g_string_free (sps, TRUE);
560   g_string_free (pps, TRUE);
561 
562   return res;
563 }
564 
565 
566 static gboolean
gst_rtp_h265_pay_setcaps(GstRTPBasePayload * basepayload,GstCaps * caps)567 gst_rtp_h265_pay_setcaps (GstRTPBasePayload * basepayload, GstCaps * caps)
568 {
569   GstRtpH265Pay *rtph265pay;
570   GstStructure *str;
571   const GValue *value;
572   GstMapInfo map;
573   guint8 *data;
574   gsize size;
575   GstBuffer *buffer;
576   const gchar *alignment, *stream_format;
577   guint8 num_arrays;
578 
579   rtph265pay = GST_RTP_H265_PAY (basepayload);
580 
581   str = gst_caps_get_structure (caps, 0);
582 
583   /* we can only set the output caps when we found the sprops and profile
584    * NALs */
585   gst_rtp_base_payload_set_options (basepayload, "video", TRUE, "H265", 90000);
586 
587   rtph265pay->alignment = GST_H265_ALIGNMENT_UNKNOWN;
588   alignment = gst_structure_get_string (str, "alignment");
589   if (alignment) {
590     if (g_str_equal (alignment, "au"))
591       rtph265pay->alignment = GST_H265_ALIGNMENT_AU;
592     if (g_str_equal (alignment, "nal"))
593       rtph265pay->alignment = GST_H265_ALIGNMENT_NAL;
594   }
595 
596   rtph265pay->stream_format = GST_H265_STREAM_FORMAT_UNKNOWN;
597   stream_format = gst_structure_get_string (str, "stream-format");
598   if (stream_format) {
599     if (g_str_equal (stream_format, "hvc1"))
600       rtph265pay->stream_format = GST_H265_STREAM_FORMAT_HVC1;
601     if (g_str_equal (stream_format, "hev1"))
602       rtph265pay->stream_format = GST_H265_STREAM_FORMAT_HEV1;
603     if (g_str_equal (stream_format, "byte-stream"))
604       rtph265pay->stream_format = GST_H265_STREAM_FORMAT_BYTESTREAM;
605   }
606 
607   if (!gst_structure_get_fraction (str, "framerate", &rtph265pay->fps_num,
608           &rtph265pay->fps_denum))
609     rtph265pay->fps_num = rtph265pay->fps_denum = 0;
610 
611 
612   /* packetized HEVC video has a codec_data */
613   if ((value = gst_structure_get_value (str, "codec_data"))) {
614     guint num_vps, num_sps, num_pps;
615     gint i, j, nal_size;
616 
617     GST_DEBUG_OBJECT (rtph265pay, "have packetized h265");
618 
619     buffer = gst_value_get_buffer (value);
620 
621     gst_buffer_map (buffer, &map, GST_MAP_READ);
622     data = map.data;
623     size = map.size;
624 
625     /* parse the hevcC data */
626     if (size < 23)
627       goto hevcc_too_small;
628     /* HEVCDecoderConfigurationVersion (must be 1) */
629     if (data[0] != 1)
630       goto wrong_version;
631 
632     /* profile_space | tier_flag | profile_idc */
633     GST_DEBUG_OBJECT (rtph265pay, "profile %06x", data[1]);
634 
635     /* profile_compatibility_flags */
636     for (i = 2; i < 6; i++) {
637       for (j = 7; j >= 0; j--) {
638         GST_DEBUG_OBJECT (rtph265pay, "profile_compatibility_flag %06x",
639             (data[i] >> j) & 1);
640       }
641     }
642 
643     GST_DEBUG_OBJECT (rtph265pay, "progressive_source_flag %06x",
644         (data[6] >> 7) & 1);
645     GST_DEBUG_OBJECT (rtph265pay, "interlaced_source_flag %06x",
646         (data[6] >> 6) & 1);
647     GST_DEBUG_OBJECT (rtph265pay, "non_packed_constraint_flag %06x",
648         (data[6] >> 5) & 1);
649     GST_DEBUG_OBJECT (rtph265pay, "frame_only_constraint_flag %06x",
650         (data[6] >> 4) & 1);
651 
652     GST_DEBUG_OBJECT (rtph265pay, "level_idc %06x", data[12]);
653 
654     GST_DEBUG_OBJECT (rtph265pay, "min_spatial_segmentation_idc %06x",
655         ((data[13] ^ 0xf0) << 8) + data[14]);
656     GST_DEBUG_OBJECT (rtph265pay, "parrallelismType %06x (ignored by paloader)",
657         data[15]);
658 
659     GST_DEBUG_OBJECT (rtph265pay, "sps_chroma_format_idc %06x",
660         data[16] ^ 0xfc);
661     GST_DEBUG_OBJECT (rtph265pay, "bit_depth_luma_minus8 %06x",
662         data[17] ^ 0xf8);
663     GST_DEBUG_OBJECT (rtph265pay, "bit_depth_chroma_minus8 %06x",
664         data[18] ^ 0xf8);
665     GST_DEBUG_OBJECT (rtph265pay, "avgFrameRate %06x", data[19]);
666     GST_DEBUG_OBJECT (rtph265pay, "avgFrameRate %06x", data[20]);
667 
668     /* constFrameRate(2 bits): 0, stream may or may not be of constant framerate
669      * numTemporalLayers (3 bits): number of temporal layers, value from SPS
670      * TemporalIdNested (1 bit): sps_temporal_id_nesting_flag from SPS
671      * lengthSizeMinusOne (2 bits): plus 1 indicates the length of the NALUnitLength */
672     GST_DEBUG_OBJECT (rtph265pay, "constFrameRate %06x",
673         (data[21] >> 6) & 0x03);
674     GST_DEBUG_OBJECT (rtph265pay, "numTemporalLayers %06x",
675         (data[21] >> 3) & 0x07);
676     GST_DEBUG_OBJECT (rtph265pay, "temporal_id_nesting_flag %06x",
677         (data[21] >> 2) & 0x01);
678 
679     rtph265pay->nal_length_size = (data[21] & 0x3) + 1;
680     GST_DEBUG_OBJECT (rtph265pay, "nal length %u", rtph265pay->nal_length_size);
681 
682     num_arrays = GST_READ_UINT8 (data + 22);
683 
684     data += 23;
685     size -= 23;
686 
687     if (num_arrays > 0) {
688       if ((data[0] & 0x3f) == 0x20) {   /* VPS */
689 
690         data++;
691         num_vps = data[0] << 8 | data[1];
692         data += 2;
693         size -= 2;
694 
695         for (i = 0; i < num_vps; i++) {
696 
697           GstBuffer *vps_buf;
698 
699           if (size < 2)
700             goto hevcc_error;
701 
702           nal_size = (data[0] << 8) | data[1];
703           data += 2;
704           size -= 2;
705 
706           GST_LOG_OBJECT (rtph265pay, "VPS %d size %d", i, nal_size);
707 
708           if (size < nal_size)
709             goto hevcc_error;
710 
711           /* make a buffer out of it and add to VPS list */
712           vps_buf = gst_buffer_new_and_alloc (nal_size);
713           gst_buffer_fill (vps_buf, 0, data, nal_size);
714           gst_rtp_h265_add_vps_sps_pps (GST_ELEMENT (rtph265pay),
715               rtph265pay->vps, rtph265pay->sps, rtph265pay->pps, vps_buf);
716           data += nal_size;
717           size -= nal_size;
718         }
719       }
720 
721       --num_arrays;
722     }
723 
724     if (num_arrays > 0) {
725       if ((data[0] & 0x3f) == 0x21) {   /* SPS */
726 
727         data++;
728         num_sps = data[0] << 8 | data[1];
729         data += 2;
730         size -= 2;
731 
732         for (i = 0; i < num_sps; i++) {
733 
734           GstBuffer *sps_buf;
735 
736           if (size < 2)
737             goto hevcc_error;
738 
739           nal_size = (data[0] << 8) | data[1];
740           data += 2;
741           size -= 2;
742 
743           GST_LOG_OBJECT (rtph265pay, "SPS %d size %d", i, nal_size);
744 
745           if (size < nal_size)
746             goto hevcc_error;
747 
748           /* make a buffer out of it and add to SPS list */
749           sps_buf = gst_buffer_new_and_alloc (nal_size);
750           gst_buffer_fill (sps_buf, 0, data, nal_size);
751           gst_rtp_h265_add_vps_sps_pps (GST_ELEMENT (rtph265pay),
752               rtph265pay->vps, rtph265pay->sps, rtph265pay->pps, sps_buf);
753           data += nal_size;
754           size -= nal_size;
755         }
756       }
757 
758       --num_arrays;
759     }
760 
761     if (num_arrays > 0) {
762       if ((data[0] & 0x3f) == 0x22) {   /* PPS */
763 
764         data++;
765         num_pps = data[0] << 8 | data[1];
766         data += 2;
767         size -= 2;
768 
769         for (i = 0; i < num_pps; i++) {
770 
771           GstBuffer *pps_buf;
772 
773           if (size < 2)
774             goto hevcc_error;
775 
776           nal_size = (data[0] << 8) | data[1];
777           data += 2;
778           size -= 2;
779 
780           GST_LOG_OBJECT (rtph265pay, "PPS %d size %d", i, nal_size);
781 
782           if (size < nal_size)
783             goto hevcc_error;
784 
785           /* make a buffer out of it and add to PPS list */
786           pps_buf = gst_buffer_new_and_alloc (nal_size);
787           gst_buffer_fill (pps_buf, 0, data, nal_size);
788           gst_rtp_h265_add_vps_sps_pps (GST_ELEMENT (rtph265pay),
789               rtph265pay->vps, rtph265pay->sps, rtph265pay->pps, pps_buf);
790           data += nal_size;
791           size -= nal_size;
792         }
793       }
794 
795       --num_arrays;
796     }
797 
798     /* and update the caps with the collected data */
799     if (!gst_rtp_h265_pay_set_vps_sps_pps (basepayload))
800       goto set_vps_sps_pps_failed;
801 
802     GST_DEBUG_OBJECT (rtph265pay, "Caps have been set");
803 
804     gst_buffer_unmap (buffer, &map);
805   } else {
806     GST_DEBUG_OBJECT (rtph265pay, "have bytestream h265");
807   }
808 
809   return TRUE;
810 
811 hevcc_too_small:
812   {
813     GST_ERROR_OBJECT (rtph265pay, "hevcC size %" G_GSIZE_FORMAT " < 7", size);
814     goto error;
815   }
816 wrong_version:
817   {
818     GST_ERROR_OBJECT (rtph265pay, "wrong hevcC version");
819     goto error;
820   }
821 hevcc_error:
822   {
823     GST_ERROR_OBJECT (rtph265pay, "hevcC too small ");
824     goto error;
825   }
826 set_vps_sps_pps_failed:
827   {
828     GST_ERROR_OBJECT (rtph265pay, "failed to set vps/sps/pps");
829     goto error;
830   }
831 error:
832   {
833     gst_buffer_unmap (buffer, &map);
834     return FALSE;
835   }
836 }
837 
838 static guint
next_start_code(const guint8 * data,guint size)839 next_start_code (const guint8 * data, guint size)
840 {
841   /* Boyer-Moore string matching algorithm, in a degenerative
842    * sense because our search 'alphabet' is binary - 0 & 1 only.
843    * This allow us to simplify the general BM algorithm to a very
844    * simple form. */
845   /* assume 1 is in the 3rd byte */
846   guint offset = 2;
847 
848   while (offset < size) {
849     if (1 == data[offset]) {
850       unsigned int shift = offset;
851 
852       if (0 == data[--shift]) {
853         if (0 == data[--shift]) {
854           return shift;
855         }
856       }
857       /* The jump is always 3 because of the 1 previously matched.
858        * All the 0's must be after this '1' matched at offset */
859       offset += 3;
860     } else if (0 == data[offset]) {
861       /* maybe next byte is 1? */
862       offset++;
863     } else {
864       /* can jump 3 bytes forward */
865       offset += 3;
866     }
867     /* at each iteration, we rescan in a backward manner until
868      * we match 0.0.1 in reverse order. Since our search string
869      * has only 2 'alpabets' (i.e. 0 & 1), we know that any
870      * mismatch will force us to shift a fixed number of steps */
871   }
872   GST_DEBUG ("Cannot find next NAL start code. returning %u", size);
873 
874   return size;
875 }
876 
877 static gboolean
gst_rtp_h265_pay_decode_nal(GstRtpH265Pay * payloader,const guint8 * data,guint size,GstClockTime dts,GstClockTime pts)878 gst_rtp_h265_pay_decode_nal (GstRtpH265Pay * payloader,
879     const guint8 * data, guint size, GstClockTime dts, GstClockTime pts)
880 {
881   guint8 type;
882   gboolean updated;
883 
884   /* default is no update */
885   updated = FALSE;
886 
887   GST_DEBUG_OBJECT (payloader, "NAL payload size %u", size);
888 
889   type = (data[0] >> 1) & 0x3f;
890 
891   /* We record the timestamp of the last SPS/PPS so
892    * that we can insert them at regular intervals and when needed. */
893   if (GST_H265_NAL_VPS == type || GST_H265_NAL_SPS == type
894       || GST_H265_NAL_PPS == type) {
895     GstBuffer *nal;
896 
897     /* trailing 0x0 are not part of the VPS/SPS/PPS */
898     while (size > 0 && data[size - 1] == 0x0)
899       size--;
900 
901     /* encode the entire NAL in base64 */
902     GST_DEBUG_OBJECT (payloader, "found %s (type 0x%x), size %u",
903         type == GST_H265_NAL_VPS ? "VPS" : type == GST_H265_NAL_SPS ?
904         "SPS" : "PPS", type, size);
905 
906     nal = gst_buffer_new_allocate (NULL, size, NULL);
907     gst_buffer_fill (nal, 0, data, size);
908 
909     updated = gst_rtp_h265_add_vps_sps_pps (GST_ELEMENT (payloader),
910         payloader->vps, payloader->sps, payloader->pps, nal);
911 
912     /* remember when we last saw VPS */
913     if (pts != -1)
914       payloader->last_vps_sps_pps =
915           gst_segment_to_running_time (&GST_RTP_BASE_PAYLOAD_CAST
916           (payloader)->segment, GST_FORMAT_TIME, pts);
917   } else {
918     GST_DEBUG_OBJECT (payloader, "NALU type 0x%x, size %u", type, size);
919   }
920 
921   return updated;
922 }
923 
924 static GstFlowReturn gst_rtp_h265_pay_payload_nal (GstRTPBasePayload *
925     basepayload, GPtrArray * paybufs, GstClockTime dts, GstClockTime pts);
926 static GstFlowReturn gst_rtp_h265_pay_payload_nal_single (GstRTPBasePayload *
927     basepayload, GstBuffer * paybuf, GstClockTime dts, GstClockTime pts,
928     gboolean marker);
929 static GstFlowReturn gst_rtp_h265_pay_payload_nal_fragment (GstRTPBasePayload *
930     basepayload, GstBuffer * paybuf, GstClockTime dts, GstClockTime pts,
931     gboolean marker, guint mtu, guint8 nal_type, const guint8 * nal_header,
932     int size);
933 static GstFlowReturn gst_rtp_h265_pay_payload_nal_bundle (GstRTPBasePayload *
934     basepayload, GstBuffer * paybuf, GstClockTime dts, GstClockTime pts,
935     gboolean marker, guint8 nal_type, const guint8 * nal_header, int size);
936 
937 static GstFlowReturn
gst_rtp_h265_pay_send_vps_sps_pps(GstRTPBasePayload * basepayload,GstRtpH265Pay * rtph265pay,GstClockTime dts,GstClockTime pts)938 gst_rtp_h265_pay_send_vps_sps_pps (GstRTPBasePayload * basepayload,
939     GstRtpH265Pay * rtph265pay, GstClockTime dts, GstClockTime pts)
940 {
941   GstFlowReturn ret = GST_FLOW_OK;
942   gboolean sent_all_vps_sps_pps = TRUE;
943   guint i;
944   GPtrArray *bufs;
945 
946   bufs = g_ptr_array_new ();
947 
948   for (i = 0; i < rtph265pay->vps->len; i++) {
949     GstBuffer *vps_buf =
950         GST_BUFFER_CAST (g_ptr_array_index (rtph265pay->vps, i));
951 
952     GST_DEBUG_OBJECT (rtph265pay, "inserting VPS in the stream");
953     g_ptr_array_add (bufs, gst_buffer_ref (vps_buf));
954   }
955   for (i = 0; i < rtph265pay->sps->len; i++) {
956     GstBuffer *sps_buf =
957         GST_BUFFER_CAST (g_ptr_array_index (rtph265pay->sps, i));
958 
959     GST_DEBUG_OBJECT (rtph265pay, "inserting SPS in the stream");
960     g_ptr_array_add (bufs, gst_buffer_ref (sps_buf));
961   }
962   for (i = 0; i < rtph265pay->pps->len; i++) {
963     GstBuffer *pps_buf =
964         GST_BUFFER_CAST (g_ptr_array_index (rtph265pay->pps, i));
965 
966     GST_DEBUG_OBJECT (rtph265pay, "inserting PPS in the stream");
967     g_ptr_array_add (bufs, gst_buffer_ref (pps_buf));
968   }
969 
970   ret = gst_rtp_h265_pay_payload_nal (basepayload, bufs, dts, pts);
971   if (ret != GST_FLOW_OK) {
972     /* not critical but warn */
973     GST_WARNING_OBJECT (basepayload, "failed pushing VPS/SPS/PPS");
974 
975     sent_all_vps_sps_pps = FALSE;
976   }
977 
978   if (pts != -1 && sent_all_vps_sps_pps)
979     rtph265pay->last_vps_sps_pps =
980         gst_segment_to_running_time (&basepayload->segment, GST_FORMAT_TIME,
981         pts);
982 
983   return ret;
984 }
985 
986 static void
gst_rtp_h265_pay_reset_bundle(GstRtpH265Pay * rtph265pay)987 gst_rtp_h265_pay_reset_bundle (GstRtpH265Pay * rtph265pay)
988 {
989   g_clear_pointer (&rtph265pay->bundle, gst_buffer_list_unref);
990   rtph265pay->bundle_size = 0;
991   rtph265pay->bundle_contains_vcl_or_suffix = FALSE;
992 }
993 
994 static GstFlowReturn
gst_rtp_h265_pay_payload_nal(GstRTPBasePayload * basepayload,GPtrArray * paybufs,GstClockTime dts,GstClockTime pts)995 gst_rtp_h265_pay_payload_nal (GstRTPBasePayload * basepayload,
996     GPtrArray * paybufs, GstClockTime dts, GstClockTime pts)
997 {
998   GstRtpH265Pay *rtph265pay;
999   guint mtu;
1000   GstFlowReturn ret;
1001   gint i;
1002   gboolean sent_ps;
1003 
1004   rtph265pay = GST_RTP_H265_PAY (basepayload);
1005   mtu = GST_RTP_BASE_PAYLOAD_MTU (rtph265pay);
1006 
1007   /* should set src caps before pushing stuff,
1008    * and if we did not see enough VPS/SPS/PPS, that may not be the case */
1009   if (G_UNLIKELY (!gst_pad_has_current_caps (GST_RTP_BASE_PAYLOAD_SRCPAD
1010               (basepayload))))
1011     gst_rtp_h265_pay_set_vps_sps_pps (basepayload);
1012 
1013   ret = GST_FLOW_OK;
1014   sent_ps = FALSE;
1015   for (i = 0; i < paybufs->len; i++) {
1016     guint8 nal_header[2];
1017     guint8 nal_type;
1018     GstBuffer *paybuf;
1019     gboolean send_ps;
1020     guint size;
1021     gboolean marker;
1022 
1023     paybuf = g_ptr_array_index (paybufs, i);
1024 
1025     if (ret != GST_FLOW_OK) {
1026       /* unref buffers that will not be payloaded after a flow error */
1027       gst_buffer_unref (paybuf);
1028       continue;
1029     }
1030 
1031     marker = GST_BUFFER_FLAG_IS_SET (paybuf, GST_BUFFER_FLAG_MARKER);
1032 
1033     size = gst_buffer_get_size (paybuf);
1034     gst_buffer_extract (paybuf, 0, nal_header, 2);
1035     nal_type = (nal_header[0] >> 1) & 0x3f;
1036 
1037     GST_DEBUG_OBJECT (rtph265pay, "payloading NAL Unit: datasize=%u type=%d"
1038         " pts=%" GST_TIME_FORMAT, size, nal_type, GST_TIME_ARGS (pts));
1039 
1040     send_ps = FALSE;
1041 
1042     /* check if we need to emit an VPS/SPS/PPS now */
1043     if ((nal_type == GST_H265_NAL_SLICE_TRAIL_N)
1044         || (nal_type == GST_H265_NAL_SLICE_TRAIL_R)
1045         || (nal_type == GST_H265_NAL_SLICE_TSA_N)
1046         || (nal_type == GST_H265_NAL_SLICE_TSA_R)
1047         || (nal_type == GST_H265_NAL_SLICE_STSA_N)
1048         || (nal_type == GST_H265_NAL_SLICE_STSA_R)
1049         || (nal_type == GST_H265_NAL_SLICE_RASL_N)
1050         || (nal_type == GST_H265_NAL_SLICE_RASL_R)
1051         || (nal_type == GST_H265_NAL_SLICE_BLA_W_LP)
1052         || (nal_type == GST_H265_NAL_SLICE_BLA_W_RADL)
1053         || (nal_type == GST_H265_NAL_SLICE_BLA_N_LP)
1054         || (nal_type == GST_H265_NAL_SLICE_IDR_W_RADL)
1055         || (nal_type == GST_H265_NAL_SLICE_IDR_N_LP)
1056         || (nal_type == GST_H265_NAL_SLICE_CRA_NUT)) {
1057       if (rtph265pay->vps_sps_pps_interval > 0) {
1058         if (rtph265pay->last_vps_sps_pps != -1) {
1059           guint64 diff;
1060           GstClockTime running_time =
1061               gst_segment_to_running_time (&basepayload->segment,
1062               GST_FORMAT_TIME, pts);
1063 
1064           GST_LOG_OBJECT (rtph265pay,
1065               "now %" GST_TIME_FORMAT ", last VPS/SPS/PPS %" GST_TIME_FORMAT,
1066               GST_TIME_ARGS (running_time),
1067               GST_TIME_ARGS (rtph265pay->last_vps_sps_pps));
1068 
1069           /* calculate diff between last SPS/PPS in milliseconds */
1070           if (running_time > rtph265pay->last_vps_sps_pps)
1071             diff = running_time - rtph265pay->last_vps_sps_pps;
1072           else
1073             diff = 0;
1074 
1075           GST_DEBUG_OBJECT (rtph265pay,
1076               "interval since last VPS/SPS/PPS %" GST_TIME_FORMAT,
1077               GST_TIME_ARGS (diff));
1078 
1079           /* bigger than interval, queue SPS/PPS */
1080           if (GST_TIME_AS_SECONDS (diff) >= rtph265pay->vps_sps_pps_interval) {
1081             GST_DEBUG_OBJECT (rtph265pay, "time to send VPS/SPS/PPS");
1082             send_ps = TRUE;
1083           }
1084         } else {
1085           /* no known previous SPS/PPS time, send now */
1086           GST_DEBUG_OBJECT (rtph265pay,
1087               "no previous VPS/SPS/PPS time, send now");
1088           send_ps = TRUE;
1089         }
1090       } else if (rtph265pay->vps_sps_pps_interval == -1
1091           && (nal_type == GST_H265_NAL_SLICE_IDR_W_RADL
1092               || nal_type == GST_H265_NAL_SLICE_IDR_N_LP)) {
1093         /* send VPS/SPS/PPS before every IDR frame */
1094         send_ps = TRUE;
1095       }
1096     }
1097 
1098     if (!sent_ps && (send_ps || rtph265pay->send_vps_sps_pps)) {
1099       /* we need to send SPS/PPS now first. FIXME, don't use the pts for
1100        * checking when we need to send SPS/PPS but convert to running_time
1101        * first */
1102       rtph265pay->send_vps_sps_pps = FALSE;
1103       sent_ps = TRUE;
1104       GST_DEBUG_OBJECT (rtph265pay, "sending VPS/SPS/PPS before current frame");
1105       ret =
1106           gst_rtp_h265_pay_send_vps_sps_pps (basepayload, rtph265pay, dts, pts);
1107       if (ret != GST_FLOW_OK) {
1108         gst_buffer_unref (paybuf);
1109         continue;
1110       }
1111     }
1112 
1113     if (rtph265pay->aggregate_mode != GST_RTP_H265_AGGREGATE_NONE)
1114       ret = gst_rtp_h265_pay_payload_nal_bundle (basepayload, paybuf, dts, pts,
1115           marker, nal_type, nal_header, size);
1116     else
1117       ret = gst_rtp_h265_pay_payload_nal_fragment (basepayload, paybuf, dts,
1118           pts, marker, mtu, nal_type, nal_header, size);
1119   }
1120 
1121   g_ptr_array_free (paybufs, TRUE);
1122 
1123   return ret;
1124 }
1125 
1126 static GstFlowReturn
gst_rtp_h265_pay_payload_nal_single(GstRTPBasePayload * basepayload,GstBuffer * paybuf,GstClockTime dts,GstClockTime pts,gboolean marker)1127 gst_rtp_h265_pay_payload_nal_single (GstRTPBasePayload * basepayload,
1128     GstBuffer * paybuf, GstClockTime dts, GstClockTime pts, gboolean marker)
1129 {
1130   GstBufferList *outlist;
1131   GstBuffer *outbuf;
1132   GstRTPBuffer rtp = GST_RTP_BUFFER_INIT;
1133 
1134   /* use buffer lists
1135    * create buffer without payload containing only the RTP header
1136    * (memory block at index 0) */
1137   outbuf = gst_rtp_base_payload_allocate_output_buffer (basepayload, 0, 0, 0);
1138 
1139   gst_rtp_buffer_map (outbuf, GST_MAP_WRITE, &rtp);
1140 
1141   /* Mark the end of a frame */
1142   gst_rtp_buffer_set_marker (&rtp, marker);
1143 
1144   /* timestamp the outbuffer */
1145   GST_BUFFER_PTS (outbuf) = pts;
1146   GST_BUFFER_DTS (outbuf) = dts;
1147 
1148   /* insert payload memory block */
1149   gst_rtp_copy_video_meta (basepayload, outbuf, paybuf);
1150   outbuf = gst_buffer_append (outbuf, paybuf);
1151 
1152   outlist = gst_buffer_list_new ();
1153 
1154   /* add the buffer to the buffer list */
1155   gst_buffer_list_add (outlist, outbuf);
1156 
1157   gst_rtp_buffer_unmap (&rtp);
1158 
1159   /* push the list to the next element in the pipe */
1160   return gst_rtp_base_payload_push_list (basepayload, outlist);
1161 }
1162 
1163 static GstFlowReturn
gst_rtp_h265_pay_payload_nal_fragment(GstRTPBasePayload * basepayload,GstBuffer * paybuf,GstClockTime dts,GstClockTime pts,gboolean marker,guint mtu,guint8 nal_type,const guint8 * nal_header,int size)1164 gst_rtp_h265_pay_payload_nal_fragment (GstRTPBasePayload * basepayload,
1165     GstBuffer * paybuf, GstClockTime dts, GstClockTime pts, gboolean marker,
1166     guint mtu, guint8 nal_type, const guint8 * nal_header, int size)
1167 {
1168   GstRtpH265Pay *rtph265pay = (GstRtpH265Pay *) basepayload;
1169   GstFlowReturn ret;
1170   guint max_fragment_size, ii, pos;
1171   GstBuffer *outbuf;
1172   GstBufferList *outlist = NULL;
1173   GstRTPBuffer rtp = GST_RTP_BUFFER_INIT;
1174   guint8 *payload;
1175 
1176   if (gst_rtp_buffer_calc_packet_len (size, 0, 0) < mtu) {
1177     GST_DEBUG_OBJECT (rtph265pay,
1178         "NAL Unit fit in one packet datasize=%d mtu=%d", size, mtu);
1179     /* will fit in one packet */
1180     return gst_rtp_h265_pay_payload_nal_single (basepayload, paybuf, dts, pts,
1181         marker);
1182   }
1183 
1184   GST_DEBUG_OBJECT (basepayload,
1185       "NAL Unit DOES NOT fit in one packet datasize=%d mtu=%d", size, mtu);
1186 
1187   GST_DEBUG_OBJECT (basepayload, "Using FU fragmentation for data size=%d",
1188       size - 2);
1189 
1190   /* We keep 3 bytes for PayloadHdr and FU Header */
1191   max_fragment_size = gst_rtp_buffer_calc_payload_len (mtu - 3, 0, 0);
1192 
1193   outlist = gst_buffer_list_new ();
1194 
1195   for (pos = 2, ii = 0; pos < size; pos += max_fragment_size, ii++) {
1196     guint remaining, fragment_size;
1197     gboolean first_fragment, last_fragment;
1198 
1199     remaining = size - pos;
1200     fragment_size = MIN (remaining, max_fragment_size);
1201     first_fragment = (pos == 2);
1202     last_fragment = (remaining <= max_fragment_size);
1203 
1204     GST_DEBUG_OBJECT (basepayload,
1205         "Inside  FU fragmentation fragment_size=%u iteration=%d %s%s",
1206         fragment_size, ii, first_fragment ? "first" : "",
1207         last_fragment ? "last" : "");
1208 
1209     /* use buffer lists
1210      * create buffer without payload containing only the RTP header
1211      * (memory block at index 0), and with space for PayloadHdr and FU header */
1212     outbuf = gst_rtp_base_payload_allocate_output_buffer (basepayload, 3, 0, 0);
1213 
1214     gst_rtp_buffer_map (outbuf, GST_MAP_WRITE, &rtp);
1215 
1216     GST_BUFFER_DTS (outbuf) = dts;
1217     GST_BUFFER_PTS (outbuf) = pts;
1218     payload = gst_rtp_buffer_get_payload (&rtp);
1219 
1220     /* PayloadHdr (type = FU_TYPE_ID (49)) */
1221     payload[0] = (nal_header[0] & 0x81) | (FU_TYPE_ID << 1);
1222     payload[1] = nal_header[1];
1223 
1224     /* If it's the last fragment and the end of this au, mark the end of
1225      * slice */
1226     gst_rtp_buffer_set_marker (&rtp, last_fragment && marker);
1227 
1228     /* FU Header */
1229     payload[2] = (first_fragment << 7) | (last_fragment << 6) |
1230         (nal_type & 0x3f);
1231 
1232     gst_rtp_buffer_unmap (&rtp);
1233 
1234     /* insert payload memory block */
1235     gst_rtp_copy_video_meta (rtph265pay, outbuf, paybuf);
1236     gst_buffer_copy_into (outbuf, paybuf, GST_BUFFER_COPY_MEMORY, pos,
1237         fragment_size);
1238     /* add the buffer to the buffer list */
1239     gst_buffer_list_add (outlist, outbuf);
1240   }
1241 
1242   ret = gst_rtp_base_payload_push_list (basepayload, outlist);
1243   gst_buffer_unref (paybuf);
1244 
1245   return ret;
1246 }
1247 
1248 static GstFlowReturn
gst_rtp_h265_pay_send_bundle(GstRtpH265Pay * rtph265pay,gboolean marker)1249 gst_rtp_h265_pay_send_bundle (GstRtpH265Pay * rtph265pay, gboolean marker)
1250 {
1251   GstRTPBasePayload *basepayload;
1252   GstBufferList *bundle;
1253   guint length, bundle_size;
1254   GstBuffer *first, *outbuf;
1255   GstClockTime dts, pts;
1256 
1257   bundle_size = rtph265pay->bundle_size;
1258 
1259   if (bundle_size == 0) {
1260     GST_DEBUG_OBJECT (rtph265pay, "no bundle, nothing to send");
1261     return GST_FLOW_OK;
1262   }
1263 
1264   basepayload = GST_RTP_BASE_PAYLOAD (rtph265pay);
1265   bundle = rtph265pay->bundle;
1266   length = gst_buffer_list_length (bundle);
1267 
1268   first = gst_buffer_list_get (bundle, 0);
1269   dts = GST_BUFFER_DTS (first);
1270   pts = GST_BUFFER_PTS (first);
1271 
1272   if (length == 1) {
1273     /* Push unaggregated NALU */
1274     outbuf = gst_buffer_ref (first);
1275 
1276     GST_DEBUG_OBJECT (rtph265pay,
1277         "sending NAL Unit unaggregated: datasize=%u", bundle_size - 2);
1278   } else {
1279     guint8 ap_header[2];
1280     guint i;
1281     guint8 layer_id = 0xFF;
1282     guint8 temporal_id = 0xFF;
1283 
1284     outbuf = gst_buffer_new_allocate (NULL, sizeof ap_header, NULL);
1285 
1286     for (i = 0; i < length; i++) {
1287       GstBuffer *buf = gst_buffer_list_get (bundle, i);
1288       guint8 nal_header[2];
1289       GstMemory *size_header;
1290       GstMapInfo map;
1291       guint8 nal_layer_id;
1292       guint8 nal_temporal_id;
1293 
1294       gst_buffer_extract (buf, 0, &nal_header, sizeof nal_header);
1295 
1296       /* Propagate F bit */
1297       if ((nal_header[0] & 0x80))
1298         ap_header[0] |= 0x80;
1299 
1300       /* Select lowest layer_id & temporal_id */
1301       nal_layer_id = ((nal_header[0] & 0x01) << 5) |
1302           ((nal_header[1] >> 3) & 0x1F);
1303       nal_temporal_id = nal_header[1] & 0x7;
1304       layer_id = MIN (layer_id, nal_layer_id);
1305       temporal_id = MIN (temporal_id, nal_temporal_id);
1306 
1307       /* append NALU size */
1308       size_header = gst_allocator_alloc (NULL, 2, NULL);
1309       gst_memory_map (size_header, &map, GST_MAP_WRITE);
1310       GST_WRITE_UINT16_BE (map.data, gst_buffer_get_size (buf));
1311       gst_memory_unmap (size_header, &map);
1312       gst_buffer_append_memory (outbuf, size_header);
1313 
1314       /* append NALU data */
1315       outbuf = gst_buffer_append (outbuf, gst_buffer_ref (buf));
1316     }
1317 
1318     ap_header[0] = (AP_TYPE_ID << 1) | (layer_id & 0x20);
1319     ap_header[1] = ((layer_id & 0x1F) << 3) | (temporal_id & 0x07);
1320 
1321     gst_buffer_fill (outbuf, 0, &ap_header, sizeof ap_header);
1322 
1323     GST_DEBUG_OBJECT (rtph265pay,
1324         "sending AP bundle: n=%u header=%02x%02x datasize=%u",
1325         length, ap_header[0], ap_header[1], bundle_size);
1326   }
1327 
1328   gst_rtp_h265_pay_reset_bundle (rtph265pay);
1329   return gst_rtp_h265_pay_payload_nal_single (basepayload, outbuf, dts, pts,
1330       marker);
1331 }
1332 
1333 static gboolean
gst_rtp_h265_pay_payload_nal_bundle(GstRTPBasePayload * basepayload,GstBuffer * paybuf,GstClockTime dts,GstClockTime pts,gboolean marker,guint8 nal_type,const guint8 * nal_header,int size)1334 gst_rtp_h265_pay_payload_nal_bundle (GstRTPBasePayload * basepayload,
1335     GstBuffer * paybuf, GstClockTime dts, GstClockTime pts,
1336     gboolean marker, guint8 nal_type, const guint8 * nal_header, int size)
1337 {
1338   GstRtpH265Pay *rtph265pay;
1339   GstFlowReturn ret;
1340   guint pay_size, bundle_size;
1341   GstBufferList *bundle;
1342   gboolean start_of_au;
1343   guint mtu;
1344 
1345   rtph265pay = GST_RTP_H265_PAY (basepayload);
1346   mtu = GST_RTP_BASE_PAYLOAD_MTU (rtph265pay);
1347   pay_size = 2 + gst_buffer_get_size (paybuf);
1348   bundle = rtph265pay->bundle;
1349   start_of_au = FALSE;
1350 
1351   if (bundle) {
1352     GstBuffer *first = gst_buffer_list_get (bundle, 0);
1353 
1354     if (nal_type == GST_H265_NAL_AUD) {
1355       GST_DEBUG_OBJECT (rtph265pay, "found access delimiter");
1356       start_of_au = TRUE;
1357     } else if (GST_BUFFER_IS_DISCONT (paybuf)) {
1358       GST_DEBUG_OBJECT (rtph265pay, "found discont");
1359       start_of_au = TRUE;
1360     } else if (GST_BUFFER_PTS (first) != pts || GST_BUFFER_DTS (first) != dts) {
1361       GST_DEBUG_OBJECT (rtph265pay, "found timestamp mismatch");
1362       start_of_au = TRUE;
1363     }
1364   }
1365 
1366   if (start_of_au) {
1367     GST_DEBUG_OBJECT (rtph265pay, "sending bundle before start of AU");
1368 
1369     ret = gst_rtp_h265_pay_send_bundle (rtph265pay, TRUE);
1370     if (ret != GST_FLOW_OK)
1371       goto out;
1372 
1373     bundle = NULL;
1374   }
1375 
1376   bundle_size = 2 + pay_size;
1377 
1378   if (gst_rtp_buffer_calc_packet_len (bundle_size, 0, 0) > mtu) {
1379     GST_DEBUG_OBJECT (rtph265pay, "NAL Unit cannot fit in a bundle");
1380 
1381     ret = gst_rtp_h265_pay_send_bundle (rtph265pay, FALSE);
1382     if (ret != GST_FLOW_OK)
1383       goto out;
1384 
1385     return gst_rtp_h265_pay_payload_nal_fragment (basepayload, paybuf, dts, pts,
1386         marker, mtu, nal_type, nal_header, size);
1387   }
1388 
1389   bundle_size = rtph265pay->bundle_size + pay_size;
1390 
1391   if (gst_rtp_buffer_calc_packet_len (bundle_size, 0, 0) > mtu) {
1392     GST_DEBUG_OBJECT (rtph265pay,
1393         "bundle overflows, sending: bundlesize=%u datasize=2+%u mtu=%u",
1394         rtph265pay->bundle_size, pay_size - 2, mtu);
1395 
1396     ret = gst_rtp_h265_pay_send_bundle (rtph265pay, FALSE);
1397     if (ret != GST_FLOW_OK)
1398       goto out;
1399 
1400     bundle = NULL;
1401   }
1402 
1403   if (!bundle) {
1404     GST_DEBUG_OBJECT (rtph265pay, "creating new AP aggregate");
1405     bundle = rtph265pay->bundle = gst_buffer_list_new ();
1406     bundle_size = rtph265pay->bundle_size = 2;
1407     rtph265pay->bundle_contains_vcl_or_suffix = FALSE;
1408   }
1409 
1410   GST_DEBUG_OBJECT (rtph265pay,
1411       "bundling NAL Unit: bundlesize=%u datasize=2+%u mtu=%u",
1412       rtph265pay->bundle_size, pay_size - 2, mtu);
1413 
1414   paybuf = gst_buffer_make_writable (paybuf);
1415   GST_BUFFER_PTS (paybuf) = pts;
1416   GST_BUFFER_DTS (paybuf) = dts;
1417 
1418   gst_buffer_list_add (bundle, gst_buffer_ref (paybuf));
1419   rtph265pay->bundle_size += pay_size;
1420   ret = GST_FLOW_OK;
1421 
1422   /* In H.265, all VCL NAL units are < 32 */
1423   if (nal_type < 32 || nal_type == GST_H265_NAL_EOS ||
1424       nal_type == GST_H265_NAL_EOB || nal_type == GST_H265_NAL_SUFFIX_SEI ||
1425       (nal_type >= 45 && nal_type <= 47) || (nal_type >= 56 && nal_type < 63))
1426     rtph265pay->bundle_contains_vcl_or_suffix = TRUE;
1427 
1428   if (marker) {
1429     GST_DEBUG_OBJECT (rtph265pay, "sending bundle at marker");
1430     ret = gst_rtp_h265_pay_send_bundle (rtph265pay, TRUE);
1431   }
1432 
1433 out:
1434   gst_buffer_unref (paybuf);
1435   return ret;
1436 }
1437 
1438 static GstFlowReturn
gst_rtp_h265_pay_handle_buffer(GstRTPBasePayload * basepayload,GstBuffer * buffer)1439 gst_rtp_h265_pay_handle_buffer (GstRTPBasePayload * basepayload,
1440     GstBuffer * buffer)
1441 {
1442   GstRtpH265Pay *rtph265pay;
1443   GstFlowReturn ret;
1444   gsize size;
1445   guint nal_len, i;
1446   const guint8 *data;
1447   GstClockTime dts, pts;
1448   GArray *nal_queue;
1449   gboolean hevc;
1450   GstBuffer *paybuf = NULL;
1451   gsize skip;
1452   gboolean marker = FALSE;
1453   gboolean discont = FALSE;
1454   gboolean draining = (buffer == NULL);
1455 
1456   rtph265pay = GST_RTP_H265_PAY (basepayload);
1457 
1458   /* the input buffer contains one or more NAL units */
1459 
1460   hevc = (rtph265pay->stream_format == GST_H265_STREAM_FORMAT_HEV1)
1461       || (rtph265pay->stream_format == GST_H265_STREAM_FORMAT_HVC1);
1462 
1463   if (hevc) {
1464     /* In hevc mode, there is no adapter, so nothing to drain */
1465     if (draining)
1466       return GST_FLOW_OK;
1467   } else {
1468     if (buffer) {
1469       if (gst_adapter_available (rtph265pay->adapter) == 0)
1470         discont = GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DISCONT);
1471       marker = GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_MARKER);
1472       gst_adapter_push (rtph265pay->adapter, buffer);
1473       buffer = NULL;
1474     }
1475 
1476     /* We want to use the first TS used to construct the following NAL */
1477     dts = gst_adapter_prev_dts (rtph265pay->adapter, NULL);
1478     pts = gst_adapter_prev_pts (rtph265pay->adapter, NULL);
1479 
1480     size = gst_adapter_available (rtph265pay->adapter);
1481     /* Nothing to do here if the adapter is empty, e.g. on EOS */
1482     if (size == 0)
1483       return GST_FLOW_OK;
1484     data = gst_adapter_map (rtph265pay->adapter, size);
1485     GST_DEBUG_OBJECT (basepayload, "got %" G_GSIZE_FORMAT " bytes", size);
1486   }
1487 
1488   ret = GST_FLOW_OK;
1489 
1490   /* now loop over all NAL units and put them in a packet */
1491   if (hevc) {
1492     GstBufferMemoryMap memory;
1493     gsize remaining_buffer_size;
1494     guint nal_length_size;
1495     gsize offset = 0;
1496     GPtrArray *paybufs;
1497 
1498     paybufs = g_ptr_array_new ();
1499     nal_length_size = rtph265pay->nal_length_size;
1500 
1501     gst_buffer_memory_map (buffer, &memory);
1502     remaining_buffer_size = gst_buffer_get_size (buffer);
1503 
1504     pts = GST_BUFFER_PTS (buffer);
1505     dts = GST_BUFFER_DTS (buffer);
1506     marker = GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_MARKER);
1507     GST_DEBUG_OBJECT (basepayload, "got %" G_GSIZE_FORMAT " bytes",
1508         remaining_buffer_size);
1509 
1510     while (remaining_buffer_size > nal_length_size) {
1511       gint i;
1512 
1513       nal_len = 0;
1514       for (i = 0; i < nal_length_size; i++) {
1515         nal_len = (nal_len << 8) + *memory.data;
1516         if (!gst_buffer_memory_advance_bytes (&memory, 1))
1517           break;
1518       }
1519 
1520       offset += nal_length_size;
1521       remaining_buffer_size -= nal_length_size;
1522 
1523       if (remaining_buffer_size >= nal_len) {
1524         GST_DEBUG_OBJECT (basepayload, "got NAL of size %u", nal_len);
1525       } else {
1526         nal_len = remaining_buffer_size;
1527         GST_DEBUG_OBJECT (basepayload, "got incomplete NAL of size %u",
1528             nal_len);
1529       }
1530 
1531       paybuf = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_ALL, offset,
1532           nal_len);
1533       g_ptr_array_add (paybufs, paybuf);
1534 
1535       /* If we're at the end of the buffer, then we're at the end of the
1536        * access unit
1537        */
1538       GST_BUFFER_FLAG_UNSET (paybuf, GST_BUFFER_FLAG_MARKER);
1539       if (remaining_buffer_size - nal_len <= nal_length_size) {
1540         if (rtph265pay->alignment == GST_H265_ALIGNMENT_AU || marker)
1541           GST_BUFFER_FLAG_SET (paybuf, GST_BUFFER_FLAG_MARKER);
1542       }
1543 
1544       GST_BUFFER_FLAG_UNSET (paybuf, GST_BUFFER_FLAG_DISCONT);
1545       if (discont) {
1546         GST_BUFFER_FLAG_SET (paybuf, GST_BUFFER_FLAG_DISCONT);
1547         discont = FALSE;
1548       }
1549 
1550       /* Skip current nal. If it is split over multiple GstMemory
1551        * advance_bytes () will switch to the correct GstMemory. The payloader
1552        * does not access those bytes directly but uses gst_buffer_copy_region ()
1553        * to create a sub-buffer referencing the nal instead */
1554       if (!gst_buffer_memory_advance_bytes (&memory, nal_len))
1555         break;
1556       offset += nal_len;
1557       remaining_buffer_size -= nal_len;
1558     }
1559     ret = gst_rtp_h265_pay_payload_nal (basepayload, paybufs, dts, pts);
1560 
1561     gst_buffer_memory_unmap (&memory);
1562     gst_buffer_unref (buffer);
1563   } else {
1564     guint next;
1565     gboolean update = FALSE;
1566     GPtrArray *paybufs;
1567 
1568     /* get offset of first start code */
1569     next = next_start_code (data, size);
1570 
1571     /* skip to start code, if no start code is found, next will be size and we
1572      * will not collect data. */
1573     data += next;
1574     size -= next;
1575     nal_queue = rtph265pay->queue;
1576     skip = next;
1577 
1578     /* array must be empty when we get here */
1579     g_assert (nal_queue->len == 0);
1580 
1581     GST_DEBUG_OBJECT (basepayload,
1582         "found first start at %u, bytes left %" G_GSIZE_FORMAT, next, size);
1583 
1584     paybufs = g_ptr_array_new ();
1585 
1586     /* first pass to locate NALs and parse VPS/SPS/PPS */
1587     while (size > 4) {
1588       /* skip start code */
1589       data += 3;
1590       size -= 3;
1591 
1592       /* use next_start_code() to scan buffer.
1593        * next_start_code() returns the offset in data,
1594        * starting from zero to the first byte of 0.0.0.1
1595        * If no start code is found, it returns the value of the
1596        * 'size' parameter.
1597        * data is unchanged by the call to next_start_code()
1598        */
1599       next = next_start_code (data, size);
1600 
1601       /* nal or au aligned input needs no delaying until next time */
1602       if (next == size && !draining &&
1603           rtph265pay->alignment == GST_H265_ALIGNMENT_UNKNOWN) {
1604         /* Didn't find the start of next NAL and it's not EOS,
1605          * handle it next time */
1606         break;
1607       }
1608 
1609       /* nal length is distance to next start code */
1610       nal_len = next;
1611 
1612       GST_DEBUG_OBJECT (basepayload, "found next start at %u of size %u", next,
1613           nal_len);
1614 
1615       /* We know our stream is a valid H265 NAL packet,
1616        * go parse it for VPS/SPS/PPS to enrich the caps */
1617       /* order: make sure to check nal */
1618       update = gst_rtp_h265_pay_decode_nal (rtph265pay, data, nal_len, dts, pts)
1619           || update;
1620 
1621       /* move to next NAL packet */
1622       data += nal_len;
1623       size -= nal_len;
1624 
1625       g_array_append_val (nal_queue, nal_len);
1626     }
1627 
1628     /* if has new VPS, SPS & PPS, update the output caps */
1629     if (G_UNLIKELY (update))
1630       if (!gst_rtp_h265_pay_set_vps_sps_pps (basepayload))
1631         goto caps_rejected;
1632 
1633     /* second pass to payload and push */
1634 
1635     if (nal_queue->len != 0)
1636       gst_adapter_flush (rtph265pay->adapter, skip);
1637 
1638     for (i = 0; i < nal_queue->len; i++) {
1639       guint size;
1640 
1641       nal_len = g_array_index (nal_queue, guint, i);
1642       /* skip start code */
1643       gst_adapter_flush (rtph265pay->adapter, 3);
1644 
1645       /* Trim the end unless we're the last NAL in the stream.
1646        * In case we're not at the end of the buffer we know the next block
1647        * starts with 0x000001 so all the 0x00 bytes at the end of this one are
1648        * trailing 0x0 that can be discarded */
1649       size = nal_len;
1650       data = gst_adapter_map (rtph265pay->adapter, size);
1651       if (i + 1 != nal_queue->len || !draining)
1652         for (; size > 2 && data[size - 1] == 0x0; size--)
1653           /* skip */ ;
1654 
1655       paybuf = gst_adapter_take_buffer (rtph265pay->adapter, size);
1656       g_assert (paybuf);
1657       g_ptr_array_add (paybufs, paybuf);
1658 
1659       /* If it's the last nal unit we have in non-bytestream mode, we can
1660        * assume it's the end of an access-unit */
1661       GST_BUFFER_FLAG_UNSET (paybuf, GST_BUFFER_FLAG_MARKER);
1662       if (i == nal_queue->len - 1) {
1663         if (rtph265pay->alignment == GST_H265_ALIGNMENT_AU ||
1664             marker || draining)
1665           GST_BUFFER_FLAG_SET (paybuf, GST_BUFFER_FLAG_MARKER);
1666       }
1667 
1668       GST_BUFFER_FLAG_UNSET (paybuf, GST_BUFFER_FLAG_DISCONT);
1669       if (discont) {
1670         GST_BUFFER_FLAG_SET (paybuf, GST_BUFFER_FLAG_DISCONT);
1671         discont = FALSE;
1672       }
1673 
1674       /* move to next NAL packet */
1675       /* Skips the trailing zeros */
1676       gst_adapter_flush (rtph265pay->adapter, nal_len - size);
1677     }
1678     /* put the data in one or more RTP packets */
1679     ret = gst_rtp_h265_pay_payload_nal (basepayload, paybufs, dts, pts);
1680     g_array_set_size (nal_queue, 0);
1681   }
1682 
1683   if (ret == GST_FLOW_OK && rtph265pay->bundle_size > 0 &&
1684       rtph265pay->aggregate_mode == GST_RTP_H265_AGGREGATE_ZERO_LATENCY &&
1685       rtph265pay->bundle_contains_vcl_or_suffix) {
1686     GST_DEBUG_OBJECT (rtph265pay, "sending bundle at end incoming packet");
1687     ret = gst_rtp_h265_pay_send_bundle (rtph265pay, FALSE);
1688   }
1689 
1690 done:
1691   if (!hevc) {
1692     gst_adapter_unmap (rtph265pay->adapter);
1693   }
1694 
1695   return ret;
1696 
1697 caps_rejected:
1698   {
1699     GST_WARNING_OBJECT (basepayload, "Could not set outcaps");
1700     g_array_set_size (nal_queue, 0);
1701     ret = GST_FLOW_NOT_NEGOTIATED;
1702     goto done;
1703   }
1704 }
1705 
1706 static gboolean
gst_rtp_h265_pay_sink_event(GstRTPBasePayload * payload,GstEvent * event)1707 gst_rtp_h265_pay_sink_event (GstRTPBasePayload * payload, GstEvent * event)
1708 {
1709   gboolean res;
1710   const GstStructure *s;
1711   GstRtpH265Pay *rtph265pay = GST_RTP_H265_PAY (payload);
1712   GstFlowReturn ret = GST_FLOW_OK;
1713 
1714   switch (GST_EVENT_TYPE (event)) {
1715     case GST_EVENT_FLUSH_STOP:
1716       gst_adapter_clear (rtph265pay->adapter);
1717       gst_rtp_h265_pay_reset_bundle (rtph265pay);
1718       break;
1719     case GST_EVENT_CUSTOM_DOWNSTREAM:
1720       s = gst_event_get_structure (event);
1721       if (gst_structure_has_name (s, "GstForceKeyUnit")) {
1722         gboolean resend_codec_data;
1723 
1724         if (gst_structure_get_boolean (s, "all-headers",
1725                 &resend_codec_data) && resend_codec_data)
1726           rtph265pay->send_vps_sps_pps = TRUE;
1727       }
1728       break;
1729     case GST_EVENT_EOS:
1730     {
1731       /* call handle_buffer with NULL to flush last NAL from adapter
1732        * in byte-stream mode
1733        */
1734       gst_rtp_h265_pay_handle_buffer (payload, NULL);
1735       ret = gst_rtp_h265_pay_send_bundle (rtph265pay, TRUE);
1736 
1737       break;
1738     }
1739     case GST_EVENT_STREAM_START:
1740       GST_DEBUG_OBJECT (rtph265pay,
1741           "New stream detected => Clear VPS, SPS and PPS");
1742       gst_rtp_h265_pay_clear_vps_sps_pps (rtph265pay);
1743       break;
1744     default:
1745       break;
1746   }
1747 
1748   if (ret != GST_FLOW_OK)
1749     return FALSE;
1750 
1751   res = GST_RTP_BASE_PAYLOAD_CLASS (parent_class)->sink_event (payload, event);
1752 
1753   return res;
1754 }
1755 
1756 static GstStateChangeReturn
gst_rtp_h265_pay_change_state(GstElement * element,GstStateChange transition)1757 gst_rtp_h265_pay_change_state (GstElement * element, GstStateChange transition)
1758 {
1759   GstStateChangeReturn ret;
1760   GstRtpH265Pay *rtph265pay = GST_RTP_H265_PAY (element);
1761 
1762   switch (transition) {
1763     case GST_STATE_CHANGE_READY_TO_PAUSED:
1764       rtph265pay->send_vps_sps_pps = FALSE;
1765       gst_adapter_clear (rtph265pay->adapter);
1766       gst_rtp_h265_pay_reset_bundle (rtph265pay);
1767       break;
1768     default:
1769       break;
1770   }
1771 
1772   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
1773 
1774   switch (transition) {
1775     case GST_STATE_CHANGE_PAUSED_TO_READY:
1776       rtph265pay->last_vps_sps_pps = -1;
1777       gst_rtp_h265_pay_clear_vps_sps_pps (rtph265pay);
1778       break;
1779     default:
1780       break;
1781   }
1782 
1783   return ret;
1784 }
1785 
1786 static void
gst_rtp_h265_pay_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)1787 gst_rtp_h265_pay_set_property (GObject * object, guint prop_id,
1788     const GValue * value, GParamSpec * pspec)
1789 {
1790   GstRtpH265Pay *rtph265pay;
1791 
1792   rtph265pay = GST_RTP_H265_PAY (object);
1793 
1794   switch (prop_id) {
1795     case PROP_CONFIG_INTERVAL:
1796       rtph265pay->vps_sps_pps_interval = g_value_get_int (value);
1797       break;
1798     case PROP_AGGREGATE_MODE:
1799       rtph265pay->aggregate_mode = g_value_get_enum (value);
1800       break;
1801     default:
1802       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1803       break;
1804   }
1805 }
1806 
1807 static void
gst_rtp_h265_pay_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)1808 gst_rtp_h265_pay_get_property (GObject * object, guint prop_id,
1809     GValue * value, GParamSpec * pspec)
1810 {
1811   GstRtpH265Pay *rtph265pay;
1812 
1813   rtph265pay = GST_RTP_H265_PAY (object);
1814 
1815   switch (prop_id) {
1816     case PROP_CONFIG_INTERVAL:
1817       g_value_set_int (value, rtph265pay->vps_sps_pps_interval);
1818       break;
1819     case PROP_AGGREGATE_MODE:
1820       g_value_set_enum (value, rtph265pay->aggregate_mode);
1821       break;
1822     default:
1823       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1824       break;
1825   }
1826 }
1827