• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* GStreamer H.265 Parser
2  * Copyright (C) 2013 Intel Corporation
3  *  Contact:Sreerenj Balachandran <sreerenj.balachandran@intel.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 <gst/base/base.h>
26 #include <gst/pbutils/pbutils.h>
27 #include "gstvideoparserselements.h"
28 #include "gsth265parse.h"
29 
30 #include <string.h>
31 
32 GST_DEBUG_CATEGORY (h265_parse_debug);
33 #define GST_CAT_DEFAULT h265_parse_debug
34 
35 #define DEFAULT_CONFIG_INTERVAL      (0)
36 
37 enum
38 {
39   PROP_0,
40   PROP_CONFIG_INTERVAL
41 };
42 
43 enum
44 {
45   GST_H265_PARSE_FORMAT_NONE,
46   GST_H265_PARSE_FORMAT_HVC1,
47   GST_H265_PARSE_FORMAT_HEV1,
48   GST_H265_PARSE_FORMAT_BYTE
49 };
50 
51 enum
52 {
53   GST_H265_PARSE_ALIGN_NONE = 0,
54   GST_H265_PARSE_ALIGN_NAL,
55   GST_H265_PARSE_ALIGN_AU
56 };
57 
58 enum
59 {
60   GST_H265_PARSE_STATE_GOT_SPS = 1 << 0,
61   GST_H265_PARSE_STATE_GOT_PPS = 1 << 1,
62   GST_H265_PARSE_STATE_GOT_SLICE = 1 << 2,
63 
64   GST_H265_PARSE_STATE_VALID_PICTURE_HEADERS = (GST_H265_PARSE_STATE_GOT_SPS |
65       GST_H265_PARSE_STATE_GOT_PPS),
66   GST_H265_PARSE_STATE_VALID_PICTURE =
67       (GST_H265_PARSE_STATE_VALID_PICTURE_HEADERS |
68       GST_H265_PARSE_STATE_GOT_SLICE)
69 };
70 
71 enum
72 {
73   GST_H265_PARSE_SEI_EXPIRED = 0,
74   GST_H265_PARSE_SEI_ACTIVE = 1,
75   GST_H265_PARSE_SEI_PARSED = 2,
76 };
77 
78 #define GST_H265_PARSE_STATE_VALID(parse, expected_state) \
79   (((parse)->state & (expected_state)) == (expected_state))
80 
81 static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
82     GST_PAD_SINK,
83     GST_PAD_ALWAYS,
84     GST_STATIC_CAPS ("video/x-h265"));
85 
86 static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
87     GST_PAD_SRC,
88     GST_PAD_ALWAYS,
89     GST_STATIC_CAPS ("video/x-h265, parsed = (boolean) true, "
90         "stream-format=(string) { hvc1, hev1, byte-stream }, "
91         "alignment=(string) { au, nal }"));
92 
93 #define parent_class gst_h265_parse_parent_class
94 G_DEFINE_TYPE (GstH265Parse, gst_h265_parse, GST_TYPE_BASE_PARSE);
95 GST_ELEMENT_REGISTER_DEFINE_WITH_CODE (h265parse, "h265parse",
96     GST_RANK_SECONDARY, GST_TYPE_H265_PARSE,
97     videoparsers_element_init (plugin));
98 
99 static void gst_h265_parse_finalize (GObject * object);
100 
101 static gboolean gst_h265_parse_start (GstBaseParse * parse);
102 static gboolean gst_h265_parse_stop (GstBaseParse * parse);
103 static GstFlowReturn gst_h265_parse_handle_frame (GstBaseParse * parse,
104     GstBaseParseFrame * frame, gint * skipsize);
105 static GstFlowReturn gst_h265_parse_parse_frame (GstBaseParse * parse,
106     GstBaseParseFrame * frame);
107 static GstFlowReturn gst_h265_parse_pre_push_frame (GstBaseParse * parse,
108     GstBaseParseFrame * frame);
109 
110 static void gst_h265_parse_set_property (GObject * object, guint prop_id,
111     const GValue * value, GParamSpec * pspec);
112 static void gst_h265_parse_get_property (GObject * object, guint prop_id,
113     GValue * value, GParamSpec * pspec);
114 
115 static gboolean gst_h265_parse_set_caps (GstBaseParse * parse, GstCaps * caps);
116 static GstCaps *gst_h265_parse_get_caps (GstBaseParse * parse,
117     GstCaps * filter);
118 static gboolean gst_h265_parse_event (GstBaseParse * parse, GstEvent * event);
119 static gboolean gst_h265_parse_src_event (GstBaseParse * parse,
120     GstEvent * event);
121 static void
122 gst_h265_parse_process_sei_user_data (GstH265Parse * h265parse,
123     GstH265RegisteredUserData * rud);
124 
125 static void
gst_h265_parse_class_init(GstH265ParseClass * klass)126 gst_h265_parse_class_init (GstH265ParseClass * klass)
127 {
128   GObjectClass *gobject_class = (GObjectClass *) klass;
129   GstBaseParseClass *parse_class = GST_BASE_PARSE_CLASS (klass);
130   GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
131 
132   GST_DEBUG_CATEGORY_INIT (h265_parse_debug, "h265parse", 0, "h265 parser");
133 
134   gobject_class->finalize = gst_h265_parse_finalize;
135   gobject_class->set_property = gst_h265_parse_set_property;
136   gobject_class->get_property = gst_h265_parse_get_property;
137 
138   g_object_class_install_property (gobject_class, PROP_CONFIG_INTERVAL,
139       g_param_spec_int ("config-interval",
140           "VPS SPS PPS Send Interval",
141           "Send VPS, SPS and PPS Insertion Interval in seconds (sprop parameter sets "
142           "will be multiplexed in the data stream when detected.) "
143           "(0 = disabled, -1 = send with every IDR frame)",
144           -1, 3600, DEFAULT_CONFIG_INTERVAL,
145           G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
146   /* Override BaseParse vfuncs */
147   parse_class->start = GST_DEBUG_FUNCPTR (gst_h265_parse_start);
148   parse_class->stop = GST_DEBUG_FUNCPTR (gst_h265_parse_stop);
149   parse_class->handle_frame = GST_DEBUG_FUNCPTR (gst_h265_parse_handle_frame);
150   parse_class->pre_push_frame =
151       GST_DEBUG_FUNCPTR (gst_h265_parse_pre_push_frame);
152   parse_class->set_sink_caps = GST_DEBUG_FUNCPTR (gst_h265_parse_set_caps);
153   parse_class->get_sink_caps = GST_DEBUG_FUNCPTR (gst_h265_parse_get_caps);
154   parse_class->sink_event = GST_DEBUG_FUNCPTR (gst_h265_parse_event);
155   parse_class->src_event = GST_DEBUG_FUNCPTR (gst_h265_parse_src_event);
156 
157   gst_element_class_add_static_pad_template (gstelement_class, &srctemplate);
158   gst_element_class_add_static_pad_template (gstelement_class, &sinktemplate);
159 
160   gst_element_class_set_static_metadata (gstelement_class, "H.265 parser",
161       "Codec/Parser/Converter/Video",
162       "Parses H.265 streams",
163       "Sreerenj Balachandran <sreerenj.balachandran@intel.com>");
164 }
165 
166 static void
gst_h265_parse_init(GstH265Parse * h265parse)167 gst_h265_parse_init (GstH265Parse * h265parse)
168 {
169   h265parse->frame_out = gst_adapter_new ();
170   gst_base_parse_set_pts_interpolation (GST_BASE_PARSE (h265parse), FALSE);
171   gst_base_parse_set_infer_ts (GST_BASE_PARSE (h265parse), FALSE);
172   GST_PAD_SET_ACCEPT_INTERSECT (GST_BASE_PARSE_SINK_PAD (h265parse));
173   GST_PAD_SET_ACCEPT_TEMPLATE (GST_BASE_PARSE_SINK_PAD (h265parse));
174 }
175 
176 
177 static void
gst_h265_parse_finalize(GObject * object)178 gst_h265_parse_finalize (GObject * object)
179 {
180   GstH265Parse *h265parse = GST_H265_PARSE (object);
181 
182   g_object_unref (h265parse->frame_out);
183 
184   G_OBJECT_CLASS (parent_class)->finalize (object);
185 }
186 
187 static void
gst_h265_parse_reset_frame(GstH265Parse * h265parse)188 gst_h265_parse_reset_frame (GstH265Parse * h265parse)
189 {
190   GST_DEBUG_OBJECT (h265parse, "reset frame");
191 
192   /* done parsing; reset state */
193   h265parse->current_off = -1;
194 
195   h265parse->update_caps = FALSE;
196   h265parse->idr_pos = -1;
197   h265parse->sei_pos = -1;
198   h265parse->keyframe = FALSE;
199   h265parse->predicted = FALSE;
200   h265parse->bidirectional = FALSE;
201   h265parse->header = FALSE;
202   h265parse->have_vps_in_frame = FALSE;
203   h265parse->have_sps_in_frame = FALSE;
204   h265parse->have_pps_in_frame = FALSE;
205   gst_adapter_clear (h265parse->frame_out);
206 }
207 
208 static void
gst_h265_parse_reset_stream_info(GstH265Parse * h265parse)209 gst_h265_parse_reset_stream_info (GstH265Parse * h265parse)
210 {
211   gint i;
212 
213   h265parse->width = 0;
214   h265parse->height = 0;
215   h265parse->fps_num = 0;
216   h265parse->fps_den = 0;
217   h265parse->upstream_par_n = -1;
218   h265parse->upstream_par_d = -1;
219   h265parse->parsed_par_n = 0;
220   h265parse->parsed_par_n = 0;
221   h265parse->parsed_colorimetry.range = GST_VIDEO_COLOR_RANGE_UNKNOWN;
222   h265parse->parsed_colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_UNKNOWN;
223   h265parse->parsed_colorimetry.transfer = GST_VIDEO_TRANSFER_UNKNOWN;
224   h265parse->parsed_colorimetry.primaries = GST_VIDEO_COLOR_PRIMARIES_UNKNOWN;
225   h265parse->have_pps = FALSE;
226   h265parse->have_sps = FALSE;
227   h265parse->have_vps = FALSE;
228 
229   h265parse->align = GST_H265_PARSE_ALIGN_NONE;
230   h265parse->format = GST_H265_PARSE_FORMAT_NONE;
231 
232   h265parse->transform = FALSE;
233   h265parse->nal_length_size = 4;
234   h265parse->packetized = FALSE;
235   h265parse->push_codec = FALSE;
236   h265parse->first_frame = TRUE;
237 
238   gst_buffer_replace (&h265parse->codec_data, NULL);
239   gst_buffer_replace (&h265parse->codec_data_in, NULL);
240 
241   gst_h265_parse_reset_frame (h265parse);
242 
243   for (i = 0; i < GST_H265_MAX_VPS_COUNT; i++)
244     gst_buffer_replace (&h265parse->vps_nals[i], NULL);
245   for (i = 0; i < GST_H265_MAX_SPS_COUNT; i++)
246     gst_buffer_replace (&h265parse->sps_nals[i], NULL);
247   for (i = 0; i < GST_H265_MAX_PPS_COUNT; i++)
248     gst_buffer_replace (&h265parse->pps_nals[i], NULL);
249 
250   gst_video_mastering_display_info_init (&h265parse->mastering_display_info);
251   h265parse->mastering_display_info_state = GST_H265_PARSE_SEI_EXPIRED;
252 
253   gst_video_content_light_level_init (&h265parse->content_light_level);
254   h265parse->content_light_level_state = GST_H265_PARSE_SEI_EXPIRED;
255 }
256 
257 static void
gst_h265_parse_reset(GstH265Parse * h265parse)258 gst_h265_parse_reset (GstH265Parse * h265parse)
259 {
260   h265parse->last_report = GST_CLOCK_TIME_NONE;
261 
262   h265parse->pending_key_unit_ts = GST_CLOCK_TIME_NONE;
263   gst_event_replace (&h265parse->force_key_unit_event, NULL);
264 
265   h265parse->discont = FALSE;
266   h265parse->discard_bidirectional = FALSE;
267   h265parse->marker = FALSE;
268 
269   gst_h265_parse_reset_stream_info (h265parse);
270 }
271 
272 static gboolean
gst_h265_parse_start(GstBaseParse * parse)273 gst_h265_parse_start (GstBaseParse * parse)
274 {
275   GstH265Parse *h265parse = GST_H265_PARSE (parse);
276 
277   GST_DEBUG_OBJECT (parse, "start");
278   gst_h265_parse_reset (h265parse);
279 
280   h265parse->nalparser = gst_h265_parser_new ();
281   h265parse->state = 0;
282 
283   gst_base_parse_set_min_frame_size (parse, 5);
284 
285   return TRUE;
286 }
287 
288 static gboolean
gst_h265_parse_stop(GstBaseParse * parse)289 gst_h265_parse_stop (GstBaseParse * parse)
290 {
291   GstH265Parse *h265parse = GST_H265_PARSE (parse);
292 
293   GST_DEBUG_OBJECT (parse, "stop");
294   gst_h265_parse_reset (h265parse);
295 
296   gst_h265_parser_free (h265parse->nalparser);
297 
298   return TRUE;
299 }
300 
301 static const gchar *
gst_h265_parse_get_string(GstH265Parse * parse,gboolean format,gint code)302 gst_h265_parse_get_string (GstH265Parse * parse, gboolean format, gint code)
303 {
304   if (format) {
305     switch (code) {
306       case GST_H265_PARSE_FORMAT_HVC1:
307         return "hvc1";
308       case GST_H265_PARSE_FORMAT_HEV1:
309         return "hev1";
310       case GST_H265_PARSE_FORMAT_BYTE:
311         return "byte-stream";
312       default:
313         return "none";
314     }
315   } else {
316     switch (code) {
317       case GST_H265_PARSE_ALIGN_NAL:
318         return "nal";
319       case GST_H265_PARSE_ALIGN_AU:
320         return "au";
321       default:
322         return "none";
323     }
324   }
325 }
326 
327 static void
gst_h265_parse_format_from_caps(GstCaps * caps,guint * format,guint * align)328 gst_h265_parse_format_from_caps (GstCaps * caps, guint * format, guint * align)
329 {
330   g_return_if_fail (gst_caps_is_fixed (caps));
331 
332   GST_DEBUG ("parsing caps: %" GST_PTR_FORMAT, caps);
333 
334   if (format)
335     *format = GST_H265_PARSE_FORMAT_NONE;
336 
337   if (align)
338     *align = GST_H265_PARSE_ALIGN_NONE;
339 
340   if (caps && gst_caps_get_size (caps) > 0) {
341     GstStructure *s = gst_caps_get_structure (caps, 0);
342     const gchar *str = NULL;
343 
344     if (format) {
345       if ((str = gst_structure_get_string (s, "stream-format"))) {
346         if (strcmp (str, "hvc1") == 0)
347           *format = GST_H265_PARSE_FORMAT_HVC1;
348         else if (strcmp (str, "hev1") == 0)
349           *format = GST_H265_PARSE_FORMAT_HEV1;
350         else if (strcmp (str, "byte-stream") == 0)
351           *format = GST_H265_PARSE_FORMAT_BYTE;
352       }
353     }
354 
355     if (align) {
356       if ((str = gst_structure_get_string (s, "alignment"))) {
357         if (strcmp (str, "au") == 0)
358           *align = GST_H265_PARSE_ALIGN_AU;
359         else if (strcmp (str, "nal") == 0)
360           *align = GST_H265_PARSE_ALIGN_NAL;
361       }
362     }
363   }
364 }
365 
366 /* check downstream caps to configure format and alignment */
367 static void
gst_h265_parse_negotiate(GstH265Parse * h265parse,gint in_format,GstCaps * in_caps)368 gst_h265_parse_negotiate (GstH265Parse * h265parse, gint in_format,
369     GstCaps * in_caps)
370 {
371   GstCaps *caps;
372   guint format = GST_H265_PARSE_FORMAT_NONE;
373   guint align = GST_H265_PARSE_ALIGN_NONE;
374 
375   g_return_if_fail ((in_caps == NULL) || gst_caps_is_fixed (in_caps));
376 
377   caps = gst_pad_get_allowed_caps (GST_BASE_PARSE_SRC_PAD (h265parse));
378   GST_DEBUG_OBJECT (h265parse, "allowed caps: %" GST_PTR_FORMAT, caps);
379 
380   /* concentrate on leading structure, since decodebin parser
381    * capsfilter always includes parser template caps */
382   if (caps) {
383     caps = gst_caps_truncate (caps);
384     GST_DEBUG_OBJECT (h265parse, "negotiating with caps: %" GST_PTR_FORMAT,
385         caps);
386   }
387 
388   if (in_caps && caps) {
389     if (gst_caps_can_intersect (in_caps, caps)) {
390       GST_DEBUG_OBJECT (h265parse, "downstream accepts upstream caps");
391       gst_h265_parse_format_from_caps (in_caps, &format, &align);
392       gst_caps_unref (caps);
393       caps = NULL;
394     }
395   }
396 
397   /* FIXME We could fail the negotiation immediately if caps are empty */
398   if (caps && !gst_caps_is_empty (caps)) {
399     /* fixate to avoid ambiguity with lists when parsing */
400     caps = gst_caps_fixate (caps);
401     gst_h265_parse_format_from_caps (caps, &format, &align);
402   }
403 
404   /* default */
405   if (!format)
406     format = GST_H265_PARSE_FORMAT_BYTE;
407   if (!align)
408     align = GST_H265_PARSE_ALIGN_AU;
409 
410   GST_DEBUG_OBJECT (h265parse, "selected format %s, alignment %s",
411       gst_h265_parse_get_string (h265parse, TRUE, format),
412       gst_h265_parse_get_string (h265parse, FALSE, align));
413 
414   h265parse->format = format;
415   h265parse->align = align;
416 
417   h265parse->transform = in_format != h265parse->format ||
418       align == GST_H265_PARSE_ALIGN_AU;
419 
420   if (caps)
421     gst_caps_unref (caps);
422 }
423 
424 static GstBuffer *
gst_h265_parse_wrap_nal(GstH265Parse * h265parse,guint format,guint8 * data,guint size)425 gst_h265_parse_wrap_nal (GstH265Parse * h265parse, guint format, guint8 * data,
426     guint size)
427 {
428   GstBuffer *buf;
429   guint nl = h265parse->nal_length_size;
430   guint32 tmp;
431 
432   GST_DEBUG_OBJECT (h265parse, "nal length %d", size);
433 
434   buf = gst_buffer_new_allocate (NULL, 4 + size, NULL);
435   if (format == GST_H265_PARSE_FORMAT_HVC1
436       || format == GST_H265_PARSE_FORMAT_HEV1) {
437     tmp = GUINT32_TO_BE (size << (32 - 8 * nl));
438   } else {
439     /* HACK: nl should always be 4 here, otherwise this won't work.
440      * There are legit cases where nl in hevc stream is 2, but byte-stream
441      * SC is still always 4 bytes. */
442     nl = 4;
443     tmp = GUINT32_TO_BE (1);
444   }
445 
446   gst_buffer_fill (buf, 0, &tmp, sizeof (guint32));
447   gst_buffer_fill (buf, nl, data, size);
448   gst_buffer_set_size (buf, size + nl);
449 
450   return buf;
451 }
452 
453 static void
gst_h265_parser_store_nal(GstH265Parse * h265parse,guint id,GstH265NalUnitType naltype,GstH265NalUnit * nalu)454 gst_h265_parser_store_nal (GstH265Parse * h265parse, guint id,
455     GstH265NalUnitType naltype, GstH265NalUnit * nalu)
456 {
457   GstBuffer *buf, **store;
458   guint size = nalu->size, store_size;
459 
460   if (naltype == GST_H265_NAL_VPS) {
461     store_size = GST_H265_MAX_VPS_COUNT;
462     store = h265parse->vps_nals;
463     GST_DEBUG_OBJECT (h265parse, "storing vps %u", id);
464   } else if (naltype == GST_H265_NAL_SPS) {
465     store_size = GST_H265_MAX_SPS_COUNT;
466     store = h265parse->sps_nals;
467     GST_DEBUG_OBJECT (h265parse, "storing sps %u", id);
468   } else if (naltype == GST_H265_NAL_PPS) {
469     store_size = GST_H265_MAX_PPS_COUNT;
470     store = h265parse->pps_nals;
471     GST_DEBUG_OBJECT (h265parse, "storing pps %u", id);
472   } else
473     return;
474 
475   if (id >= store_size) {
476     GST_DEBUG_OBJECT (h265parse, "unable to store nal, id out-of-range %d", id);
477     return;
478   }
479 
480   buf = gst_buffer_new_allocate (NULL, size, NULL);
481   gst_buffer_fill (buf, 0, nalu->data + nalu->offset, size);
482 
483   /* Indicate that buffer contain a header needed for decoding */
484   if (naltype >= GST_H265_NAL_VPS && naltype <= GST_H265_NAL_PPS)
485     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_HEADER);
486 
487   if (store[id])
488     gst_buffer_unref (store[id]);
489 
490   store[id] = buf;
491 }
492 
493 #ifndef GST_DISABLE_GST_DEBUG
494 static const gchar *nal_names[] = {
495   "Slice_TRAIL_N",
496   "Slice_TRAIL_R",
497   "Slice_TSA_N",
498   "Slice_TSA_R",
499   "Slice_STSA_N",
500   "Slice_STSA_R",
501   "Slice_RADL_N",
502   "Slice_RADL_R",
503   "SLICE_RASL_N",
504   "SLICE_RASL_R",
505   "Invalid (10)",
506   "Invalid (11)",
507   "Invalid (12)",
508   "Invalid (13)",
509   "Invalid (14)",
510   "Invalid (15)",
511   "SLICE_BLA_W_LP",
512   "SLICE_BLA_W_RADL",
513   "SLICE_BLA_N_LP",
514   "SLICE_IDR_W_RADL",
515   "SLICE_IDR_N_LP",
516   "SLICE_CRA_NUT",
517   "Invalid (22)",
518   "Invalid (23)",
519   "Invalid (24)",
520   "Invalid (25)",
521   "Invalid (26)",
522   "Invalid (27)",
523   "Invalid (28)",
524   "Invalid (29)",
525   "Invalid (30)",
526   "Invalid (31)",
527   "VPS",
528   "SPS",
529   "PPS",
530   "AUD",
531   "EOS",
532   "EOB",
533   "FD",
534   "PREFIX_SEI",
535   "SUFFIX_SEI"
536 };
537 
538 static const gchar *
_nal_name(GstH265NalUnitType nal_type)539 _nal_name (GstH265NalUnitType nal_type)
540 {
541   if (nal_type <= GST_H265_NAL_SUFFIX_SEI)
542     return nal_names[nal_type];
543   return "Invalid";
544 }
545 #endif
546 
547 static void
gst_h265_parse_process_sei(GstH265Parse * h265parse,GstH265NalUnit * nalu)548 gst_h265_parse_process_sei (GstH265Parse * h265parse, GstH265NalUnit * nalu)
549 {
550   GstH265SEIMessage sei;
551   GstH265Parser *nalparser = h265parse->nalparser;
552   GstH265ParserResult pres;
553   GArray *messages;
554   guint i;
555 
556   pres = gst_h265_parser_parse_sei (nalparser, nalu, &messages);
557   if (pres != GST_H265_PARSER_OK)
558     GST_WARNING_OBJECT (h265parse, "failed to parse one or more SEI message");
559 
560   /* Even if pres != GST_H265_PARSER_OK, some message could have been parsed and
561    * stored in messages.
562    */
563   for (i = 0; i < messages->len; i++) {
564     sei = g_array_index (messages, GstH265SEIMessage, i);
565     switch (sei.payloadType) {
566       case GST_H265_SEI_RECOVERY_POINT:
567         GST_LOG_OBJECT (h265parse, "recovery point found: %u %u %u",
568             sei.payload.recovery_point.recovery_poc_cnt,
569             sei.payload.recovery_point.exact_match_flag,
570             sei.payload.recovery_point.broken_link_flag);
571         h265parse->keyframe = TRUE;
572         break;
573       case GST_H265_SEI_TIME_CODE:
574         memcpy (&h265parse->time_code, &sei.payload.time_code,
575             sizeof (GstH265TimeCode));
576         break;
577       case GST_H265_SEI_PIC_TIMING:
578         h265parse->sei_pic_struct = sei.payload.pic_timing.pic_struct;
579         break;
580       case GST_H265_SEI_REGISTERED_USER_DATA:
581         gst_h265_parse_process_sei_user_data (h265parse,
582             &sei.payload.registered_user_data);
583         break;
584       case GST_H265_SEI_BUF_PERIOD:
585         /* FIXME */
586         break;
587       case GST_H265_SEI_MASTERING_DISPLAY_COLOUR_VOLUME:
588       {
589         /* Precision defined by spec.
590          * See D.3.28 Mastering display colour volume SEI message semantics */
591         GstVideoMasteringDisplayInfo minfo;
592         gint j, k;
593 
594         /* GstVideoMasteringDisplayInfo::display_primaries is rgb order but
595          * HEVC uses gbr order
596          * See spec D.3.28 display_primaries_x and display_primaries_y
597          */
598         for (j = 0, k = 2; j < G_N_ELEMENTS (minfo.display_primaries); j++, k++) {
599           minfo.display_primaries[j].x =
600               sei.payload.
601               mastering_display_colour_volume.display_primaries_x[k % 3];
602           minfo.display_primaries[j].y =
603               sei.payload.
604               mastering_display_colour_volume.display_primaries_y[k % 3];
605         }
606 
607         minfo.white_point.x =
608             sei.payload.mastering_display_colour_volume.white_point_x;
609         minfo.white_point.y =
610             sei.payload.mastering_display_colour_volume.white_point_y;
611         minfo.max_display_mastering_luminance =
612             sei.payload.mastering_display_colour_volume.
613             max_display_mastering_luminance;
614         minfo.min_display_mastering_luminance =
615             sei.payload.mastering_display_colour_volume.
616             min_display_mastering_luminance;
617 
618         GST_LOG_OBJECT (h265parse, "mastering display info found: "
619             "Red(%u, %u) "
620             "Green(%u, %u) "
621             "Blue(%u, %u) "
622             "White(%u, %u) "
623             "max_luminance(%u) "
624             "min_luminance(%u) ",
625             minfo.display_primaries[0].x, minfo.display_primaries[0].y,
626             minfo.display_primaries[1].x, minfo.display_primaries[1].y,
627             minfo.display_primaries[2].x, minfo.display_primaries[2].y,
628             minfo.white_point.x, minfo.white_point.y,
629             minfo.max_display_mastering_luminance,
630             minfo.min_display_mastering_luminance);
631 
632         if (h265parse->mastering_display_info_state ==
633             GST_H265_PARSE_SEI_EXPIRED) {
634           h265parse->update_caps = TRUE;
635         } else if (!gst_video_mastering_display_info_is_equal
636             (&h265parse->mastering_display_info, &minfo)) {
637           h265parse->update_caps = TRUE;
638         }
639 
640         h265parse->mastering_display_info_state = GST_H265_PARSE_SEI_PARSED;
641         h265parse->mastering_display_info = minfo;
642 
643         break;
644       }
645       case GST_H265_SEI_CONTENT_LIGHT_LEVEL:
646       {
647         GstVideoContentLightLevel cll;
648 
649         cll.max_content_light_level =
650             sei.payload.content_light_level.max_content_light_level;
651         cll.max_frame_average_light_level =
652             sei.payload.content_light_level.max_pic_average_light_level;
653 
654         GST_LOG_OBJECT (h265parse, "content light level found: "
655             "maxCLL:(%u), maxFALL:(%u)", cll.max_content_light_level,
656             cll.max_frame_average_light_level);
657 
658         if (h265parse->content_light_level_state == GST_H265_PARSE_SEI_EXPIRED) {
659           h265parse->update_caps = TRUE;
660         } else if (cll.max_content_light_level !=
661             h265parse->content_light_level.max_content_light_level ||
662             cll.max_frame_average_light_level !=
663             h265parse->content_light_level.max_frame_average_light_level) {
664           h265parse->update_caps = TRUE;
665         }
666 
667         h265parse->content_light_level_state = GST_H265_PARSE_SEI_PARSED;
668         h265parse->content_light_level = cll;
669 
670         break;
671       }
672       default:
673         break;
674     }
675   }
676   g_array_free (messages, TRUE);
677 }
678 
679 static void
gst_h265_parse_process_sei_user_data(GstH265Parse * h265parse,GstH265RegisteredUserData * rud)680 gst_h265_parse_process_sei_user_data (GstH265Parse * h265parse,
681     GstH265RegisteredUserData * rud)
682 {
683   guint16 provider_code;
684   GstByteReader br;
685   GstVideoParseUtilsField field = GST_VIDEO_PARSE_UTILS_FIELD_1;
686 
687   /* only US country code is currently supported */
688   switch (rud->country_code) {
689     case ITU_T_T35_COUNTRY_CODE_US:
690       break;
691     default:
692       GST_LOG_OBJECT (h265parse, "Unsupported country code %d",
693           rud->country_code);
694       return;
695   }
696 
697   if (rud->data == NULL || rud->size < 2)
698     return;
699 
700   gst_byte_reader_init (&br, rud->data, rud->size);
701 
702   provider_code = gst_byte_reader_get_uint16_be_unchecked (&br);
703 
704   if (h265parse->sei_pic_struct ==
705       (guint8) GST_H265_SEI_PIC_STRUCT_BOTTOM_FIELD)
706     field = GST_VIDEO_PARSE_UTILS_FIELD_1;
707   gst_video_parse_user_data ((GstElement *) h265parse, &h265parse->user_data,
708       &br, field, provider_code);
709 
710 }
711 
712 /* caller guarantees 2 bytes of nal payload */
713 static gboolean
gst_h265_parse_process_nal(GstH265Parse * h265parse,GstH265NalUnit * nalu)714 gst_h265_parse_process_nal (GstH265Parse * h265parse, GstH265NalUnit * nalu)
715 {
716   GstH265PPS pps = { 0, };
717   GstH265SPS sps = { 0, };
718   GstH265VPS vps = { 0, };
719   guint nal_type;
720   GstH265Parser *nalparser = h265parse->nalparser;
721   GstH265ParserResult pres = GST_H265_PARSER_ERROR;
722 
723   /* nothing to do for broken input */
724   if (G_UNLIKELY (nalu->size < 2)) {
725     GST_DEBUG_OBJECT (h265parse, "not processing nal size %u", nalu->size);
726     return TRUE;
727   }
728 
729   /* we have a peek as well */
730   nal_type = nalu->type;
731 
732   GST_DEBUG_OBJECT (h265parse, "processing nal of type %u %s, size %u",
733       nal_type, _nal_name (nal_type), nalu->size);
734   switch (nal_type) {
735     case GST_H265_NAL_VPS:
736       /* It is not mandatory to have VPS in the stream. But it might
737        * be needed for other extensions like svc */
738       pres = gst_h265_parser_parse_vps (nalparser, nalu, &vps);
739       if (pres != GST_H265_PARSER_OK) {
740         GST_WARNING_OBJECT (h265parse, "failed to parse VPS");
741         return FALSE;
742       }
743 
744       GST_DEBUG_OBJECT (h265parse, "triggering src caps check");
745       h265parse->update_caps = TRUE;
746       h265parse->have_vps = TRUE;
747       h265parse->have_vps_in_frame = TRUE;
748       if (h265parse->push_codec && h265parse->have_pps) {
749         /* VPS/SPS/PPS found in stream before the first pre_push_frame, no need
750          * to forcibly push at start */
751         GST_INFO_OBJECT (h265parse, "have VPS/SPS/PPS in stream");
752         h265parse->push_codec = FALSE;
753         h265parse->have_vps = FALSE;
754         h265parse->have_sps = FALSE;
755         h265parse->have_pps = FALSE;
756       }
757 
758       gst_h265_parser_store_nal (h265parse, vps.id, nal_type, nalu);
759       h265parse->header = TRUE;
760       break;
761     case GST_H265_NAL_SPS:
762       /* reset state, everything else is obsolete */
763       h265parse->state &= GST_H265_PARSE_STATE_GOT_PPS;
764 
765       pres = gst_h265_parser_parse_sps (nalparser, nalu, &sps, TRUE);
766 
767 
768       /* arranged for a fallback sps.id, so use that one and only warn */
769       if (pres != GST_H265_PARSER_OK) {
770         /* try to not parse VUI */
771         pres = gst_h265_parser_parse_sps (nalparser, nalu, &sps, FALSE);
772         if (pres != GST_H265_PARSER_OK) {
773           GST_WARNING_OBJECT (h265parse, "failed to parse SPS:");
774           h265parse->state |= GST_H265_PARSE_STATE_GOT_SPS;
775           h265parse->header = TRUE;
776           return FALSE;
777         }
778         GST_WARNING_OBJECT (h265parse,
779             "failed to parse VUI of SPS, ignore VUI");
780       }
781 
782       GST_DEBUG_OBJECT (h265parse, "triggering src caps check");
783       h265parse->update_caps = TRUE;
784       h265parse->have_sps = TRUE;
785       h265parse->have_sps_in_frame = TRUE;
786       if (h265parse->push_codec && h265parse->have_pps) {
787         /* SPS and PPS found in stream before the first pre_push_frame, no need
788          * to forcibly push at start */
789         GST_INFO_OBJECT (h265parse, "have SPS/PPS in stream");
790         h265parse->push_codec = FALSE;
791         h265parse->have_sps = FALSE;
792         h265parse->have_pps = FALSE;
793       }
794 
795       gst_h265_parser_store_nal (h265parse, sps.id, nal_type, nalu);
796       h265parse->header = TRUE;
797       h265parse->state |= GST_H265_PARSE_STATE_GOT_SPS;
798       break;
799     case GST_H265_NAL_PPS:
800       /* expected state: got-sps */
801       h265parse->state &= GST_H265_PARSE_STATE_GOT_SPS;
802       if (!GST_H265_PARSE_STATE_VALID (h265parse, GST_H265_PARSE_STATE_GOT_SPS))
803         return FALSE;
804 
805       pres = gst_h265_parser_parse_pps (nalparser, nalu, &pps);
806 
807 
808       /* arranged for a fallback pps.id, so use that one and only warn */
809       if (pres != GST_H265_PARSER_OK) {
810         GST_WARNING_OBJECT (h265parse, "failed to parse PPS:");
811         if (pres != GST_H265_PARSER_BROKEN_LINK)
812           return FALSE;
813       }
814 
815       /* parameters might have changed, force caps check */
816       if (!h265parse->have_pps) {
817         GST_DEBUG_OBJECT (h265parse, "triggering src caps check");
818         h265parse->update_caps = TRUE;
819       }
820       h265parse->have_pps = TRUE;
821       h265parse->have_pps_in_frame = TRUE;
822       if (h265parse->push_codec && h265parse->have_sps) {
823         /* SPS and PPS found in stream before the first pre_push_frame, no need
824          * to forcibly push at start */
825         GST_INFO_OBJECT (h265parse, "have SPS/PPS in stream");
826         h265parse->push_codec = FALSE;
827         h265parse->have_sps = FALSE;
828         h265parse->have_pps = FALSE;
829       }
830 
831       gst_h265_parser_store_nal (h265parse, pps.id, nal_type, nalu);
832       h265parse->header = TRUE;
833       h265parse->state |= GST_H265_PARSE_STATE_GOT_PPS;
834       break;
835     case GST_H265_NAL_PREFIX_SEI:
836     case GST_H265_NAL_SUFFIX_SEI:
837       /* expected state: got-sps */
838       if (!GST_H265_PARSE_STATE_VALID (h265parse, GST_H265_PARSE_STATE_GOT_SPS))
839         return FALSE;
840 
841       h265parse->header = TRUE;
842 
843       gst_h265_parse_process_sei (h265parse, nalu);
844 
845       /* mark SEI pos */
846       if (nal_type == GST_H265_NAL_PREFIX_SEI && h265parse->sei_pos == -1) {
847         if (h265parse->transform)
848           h265parse->sei_pos = gst_adapter_available (h265parse->frame_out);
849         else
850           h265parse->sei_pos = nalu->sc_offset;
851         GST_DEBUG_OBJECT (h265parse, "marking SEI in frame at offset %d",
852             h265parse->sei_pos);
853       }
854       break;
855 
856     case GST_H265_NAL_SLICE_TRAIL_N:
857     case GST_H265_NAL_SLICE_TRAIL_R:
858     case GST_H265_NAL_SLICE_TSA_N:
859     case GST_H265_NAL_SLICE_TSA_R:
860     case GST_H265_NAL_SLICE_STSA_N:
861     case GST_H265_NAL_SLICE_STSA_R:
862     case GST_H265_NAL_SLICE_RADL_N:
863     case GST_H265_NAL_SLICE_RADL_R:
864     case GST_H265_NAL_SLICE_RASL_N:
865     case GST_H265_NAL_SLICE_RASL_R:
866     case GST_H265_NAL_SLICE_BLA_W_LP:
867     case GST_H265_NAL_SLICE_BLA_W_RADL:
868     case GST_H265_NAL_SLICE_BLA_N_LP:
869     case GST_H265_NAL_SLICE_IDR_W_RADL:
870     case GST_H265_NAL_SLICE_IDR_N_LP:
871     case GST_H265_NAL_SLICE_CRA_NUT:
872     {
873       GstH265SliceHdr slice;
874       gboolean is_irap;
875       gboolean no_rasl_output_flag = FALSE;
876 
877       /* expected state: got-sps|got-pps (valid picture headers) */
878       h265parse->state &= GST_H265_PARSE_STATE_VALID_PICTURE_HEADERS;
879       if (!GST_H265_PARSE_STATE_VALID (h265parse,
880               GST_H265_PARSE_STATE_VALID_PICTURE_HEADERS))
881         return FALSE;
882 
883       /* This is similar to the GOT_SLICE state, but is only reset when the
884        * AU is complete. This is used to keep track of AU */
885       h265parse->picture_start = TRUE;
886 
887       pres = gst_h265_parser_parse_slice_hdr (nalparser, nalu, &slice);
888 
889       if (pres == GST_H265_PARSER_OK) {
890         if (GST_H265_IS_I_SLICE (&slice))
891           h265parse->keyframe = TRUE;
892         else if (GST_H265_IS_P_SLICE (&slice))
893           h265parse->predicted = TRUE;
894         else if (GST_H265_IS_B_SLICE (&slice))
895           h265parse->bidirectional = TRUE;
896 
897         h265parse->state |= GST_H265_PARSE_STATE_GOT_SLICE;
898       }
899       if (slice.first_slice_segment_in_pic_flag == 1)
900         GST_DEBUG_OBJECT (h265parse,
901             "frame start, first_slice_segment_in_pic_flag = 1");
902 
903       GST_DEBUG_OBJECT (h265parse,
904           "parse result %d, first slice_segment: %u, slice type: %u",
905           pres, slice.first_slice_segment_in_pic_flag, slice.type);
906 
907       gst_h265_slice_hdr_free (&slice);
908 
909       /* FIXME: NoRaslOutputFlag can be equal to 1 for CRA if
910        * 1) the first AU in bitstream is CRA
911        * 2) or the first AU following EOS nal is CRA
912        * 3) or it has HandleCraAsBlaFlag equal to 1 */
913       if (GST_H265_IS_NAL_TYPE_IDR (nal_type)) {
914         /* NoRaslOutputFlag is equal to 1 for each IDR */
915         no_rasl_output_flag = TRUE;
916       } else if (GST_H265_IS_NAL_TYPE_BLA (nal_type)) {
917         /* NoRaslOutputFlag is equal to 1 for each BLA */
918         no_rasl_output_flag = TRUE;
919       }
920 
921       is_irap = GST_H265_IS_NAL_TYPE_IRAP (nal_type);
922 
923       if (no_rasl_output_flag && is_irap
924           && slice.first_slice_segment_in_pic_flag == 1) {
925         if (h265parse->mastering_display_info_state ==
926             GST_H265_PARSE_SEI_PARSED)
927           h265parse->mastering_display_info_state = GST_H265_PARSE_SEI_ACTIVE;
928         else if (h265parse->mastering_display_info_state ==
929             GST_H265_PARSE_SEI_ACTIVE)
930           h265parse->mastering_display_info_state = GST_H265_PARSE_SEI_EXPIRED;
931 
932         if (h265parse->content_light_level_state == GST_H265_PARSE_SEI_PARSED)
933           h265parse->content_light_level_state = GST_H265_PARSE_SEI_ACTIVE;
934         else if (h265parse->content_light_level_state ==
935             GST_H265_PARSE_SEI_ACTIVE)
936           h265parse->content_light_level_state = GST_H265_PARSE_SEI_EXPIRED;
937       }
938       if (G_LIKELY (!is_irap && !h265parse->push_codec))
939         break;
940 
941       /* if we need to sneak codec NALs into the stream,
942        * this is a good place, so fake it as IDR
943        * (which should be at start anyway) */
944       /* mark where config needs to go if interval expired */
945       /* mind replacement buffer if applicable */
946       if (h265parse->idr_pos == -1) {
947         if (h265parse->transform)
948           h265parse->idr_pos = gst_adapter_available (h265parse->frame_out);
949         else
950           h265parse->idr_pos = nalu->sc_offset;
951         GST_DEBUG_OBJECT (h265parse, "marking IDR in frame at offset %d",
952             h265parse->idr_pos);
953       }
954       /* if SEI preceeds (faked) IDR, then we have to insert config there */
955       if (h265parse->sei_pos >= 0 && h265parse->idr_pos > h265parse->sei_pos) {
956         h265parse->idr_pos = h265parse->sei_pos;
957         GST_DEBUG_OBJECT (h265parse, "moved IDR mark to SEI position %d",
958             h265parse->idr_pos);
959       }
960       break;
961     }
962     case GST_H265_NAL_AUD:
963       /* Just accumulate AU Delimiter, whether it's before SPS or not */
964       pres = gst_h265_parser_parse_nal (nalparser, nalu);
965       if (pres != GST_H265_PARSER_OK)
966         return FALSE;
967       break;
968     default:
969       /* drop anything before the initial SPS */
970       if (!GST_H265_PARSE_STATE_VALID (h265parse, GST_H265_PARSE_STATE_GOT_SPS))
971         return FALSE;
972 
973       pres = gst_h265_parser_parse_nal (nalparser, nalu);
974       if (pres != GST_H265_PARSER_OK)
975         return FALSE;
976       break;
977   }
978 
979   /* if HEVC output needed, collect properly prefixed nal in adapter,
980    * and use that to replace outgoing buffer data later on */
981   if (h265parse->transform) {
982     GstBuffer *buf;
983 
984     GST_LOG_OBJECT (h265parse, "collecting NAL in HEVC frame");
985     buf = gst_h265_parse_wrap_nal (h265parse, h265parse->format,
986         nalu->data + nalu->offset, nalu->size);
987     gst_adapter_push (h265parse->frame_out, buf);
988   }
989 
990   return TRUE;
991 }
992 
993 /* caller guarantees at least 3 bytes of nal payload for each nal
994  * returns TRUE if next_nal indicates that nal terminates an AU */
995 static inline gboolean
gst_h265_parse_collect_nal(GstH265Parse * h265parse,const guint8 * data,guint size,GstH265NalUnit * nalu)996 gst_h265_parse_collect_nal (GstH265Parse * h265parse, const guint8 * data,
997     guint size, GstH265NalUnit * nalu)
998 {
999   GstH265NalUnitType nal_type = nalu->type;
1000   gboolean complete;
1001 
1002   /* determine if AU complete */
1003   GST_LOG_OBJECT (h265parse, "next nal type: %d %s (picture started %i)",
1004       nal_type, _nal_name (nal_type), h265parse->picture_start);
1005 
1006   /* consider a coded slices (IRAP or not) to start a picture,
1007    * (so ending the previous one) if first_slice_segment_in_pic_flag == 1*/
1008   complete = h265parse->picture_start && ((nal_type >= GST_H265_NAL_VPS
1009           && nal_type <= GST_H265_NAL_AUD)
1010       || nal_type == GST_H265_NAL_PREFIX_SEI || (nal_type >= 41
1011           && nal_type <= 44) || (nal_type >= 48 && nal_type <= 55));
1012 
1013   /* Any VCL Nal unit with first_slice_segment_in_pic_flag == 1 considered start of frame */
1014   if (nalu->size > nalu->header_bytes) {
1015     complete |= h265parse->picture_start
1016         && (((nal_type >= GST_H265_NAL_SLICE_TRAIL_N
1017                 && nal_type <= GST_H265_NAL_SLICE_RASL_R)
1018             || GST_H265_IS_NAL_TYPE_IRAP (nal_type))
1019         && (nalu->data[nalu->offset + 2] & 0x80));
1020   }
1021 
1022   GST_LOG_OBJECT (h265parse, "au complete: %d", complete);
1023 
1024   if (complete)
1025     h265parse->picture_start = FALSE;
1026 
1027   return complete;
1028 }
1029 
1030 static GstFlowReturn
gst_h265_parse_handle_frame_packetized(GstBaseParse * parse,GstBaseParseFrame * frame)1031 gst_h265_parse_handle_frame_packetized (GstBaseParse * parse,
1032     GstBaseParseFrame * frame)
1033 {
1034   GstH265Parse *h265parse = GST_H265_PARSE (parse);
1035   GstBuffer *buffer = frame->buffer;
1036   GstFlowReturn ret = GST_FLOW_OK;
1037   GstH265ParserResult parse_res;
1038   GstH265NalUnit nalu;
1039   const guint nl = h265parse->nal_length_size;
1040   GstMapInfo map;
1041   gint left;
1042 
1043   if (nl < 1 || nl > 4) {
1044     GST_DEBUG_OBJECT (h265parse, "insufficient data to split input");
1045     return GST_FLOW_NOT_NEGOTIATED;
1046   }
1047 
1048   /* need to save buffer from invalidation upon _finish_frame */
1049   if (h265parse->split_packetized)
1050     buffer = gst_buffer_copy (frame->buffer);
1051 
1052   gst_buffer_map (buffer, &map, GST_MAP_READ);
1053 
1054   left = map.size;
1055 
1056   GST_LOG_OBJECT (h265parse,
1057       "processing packet buffer of size %" G_GSIZE_FORMAT, map.size);
1058 
1059   parse_res = gst_h265_parser_identify_nalu_hevc (h265parse->nalparser,
1060       map.data, 0, map.size, nl, &nalu);
1061 
1062   while (parse_res == GST_H265_PARSER_OK) {
1063     GST_DEBUG_OBJECT (h265parse, "HEVC nal offset %d", nalu.offset + nalu.size);
1064 
1065     /* either way, have a look at it */
1066     gst_h265_parse_process_nal (h265parse, &nalu);
1067 
1068     /* dispatch per NALU if needed */
1069     if (h265parse->split_packetized) {
1070       GstBaseParseFrame tmp_frame;
1071 
1072       gst_base_parse_frame_init (&tmp_frame);
1073       tmp_frame.flags |= frame->flags;
1074       tmp_frame.offset = frame->offset;
1075       tmp_frame.overhead = frame->overhead;
1076       tmp_frame.buffer = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_ALL,
1077           nalu.offset, nalu.size);
1078 
1079       /* Set marker on last packet */
1080       if (nl + nalu.size == left) {
1081         if (GST_BUFFER_FLAG_IS_SET (frame->buffer, GST_BUFFER_FLAG_MARKER))
1082           h265parse->marker = TRUE;
1083       }
1084 
1085       /* note we don't need to come up with a sub-buffer, since
1086        * subsequent code only considers input buffer's metadata.
1087        * Real data is either taken from input by baseclass or
1088        * a replacement output buffer is provided anyway. */
1089       gst_h265_parse_parse_frame (parse, &tmp_frame);
1090       ret = gst_base_parse_finish_frame (parse, &tmp_frame, nl + nalu.size);
1091       left -= nl + nalu.size;
1092     }
1093 
1094     parse_res = gst_h265_parser_identify_nalu_hevc (h265parse->nalparser,
1095         map.data, nalu.offset + nalu.size, map.size, nl, &nalu);
1096   }
1097 
1098   gst_buffer_unmap (buffer, &map);
1099 
1100   if (!h265parse->split_packetized) {
1101     h265parse->marker = TRUE;
1102     gst_h265_parse_parse_frame (parse, frame);
1103     ret = gst_base_parse_finish_frame (parse, frame, map.size);
1104   } else {
1105     gst_buffer_unref (buffer);
1106     if (G_UNLIKELY (left)) {
1107       /* should not be happening for nice HEVC */
1108       GST_WARNING_OBJECT (parse, "skipping leftover HEVC data %d", left);
1109       frame->flags |= GST_BASE_PARSE_FRAME_FLAG_DROP;
1110       ret = gst_base_parse_finish_frame (parse, frame, map.size);
1111     }
1112   }
1113 
1114   if (parse_res == GST_H265_PARSER_NO_NAL_END ||
1115       parse_res == GST_H265_PARSER_BROKEN_DATA) {
1116 
1117     if (h265parse->split_packetized) {
1118       GST_ELEMENT_ERROR (h265parse, STREAM, FAILED, (NULL),
1119           ("invalid HEVC input data"));
1120 
1121       return GST_FLOW_ERROR;
1122     } else {
1123       /* do not meddle to much in this case */
1124       GST_DEBUG_OBJECT (h265parse, "parsing packet failed");
1125     }
1126   }
1127 
1128   return ret;
1129 }
1130 
1131 static GstFlowReturn
gst_h265_parse_handle_frame(GstBaseParse * parse,GstBaseParseFrame * frame,gint * skipsize)1132 gst_h265_parse_handle_frame (GstBaseParse * parse,
1133     GstBaseParseFrame * frame, gint * skipsize)
1134 {
1135   GstH265Parse *h265parse = GST_H265_PARSE (parse);
1136   GstBuffer *buffer = frame->buffer;
1137   GstMapInfo map;
1138   guint8 *data;
1139   gsize size;
1140   gint current_off = 0;
1141   gboolean drain, nonext;
1142   GstH265Parser *nalparser = h265parse->nalparser;
1143   GstH265NalUnit nalu;
1144   GstH265ParserResult pres;
1145   gint framesize;
1146 
1147   if (G_UNLIKELY (GST_BUFFER_FLAG_IS_SET (frame->buffer,
1148               GST_BUFFER_FLAG_DISCONT))) {
1149     h265parse->discont = TRUE;
1150   }
1151 
1152   /* delegate in packetized case, no skipping should be needed */
1153   if (h265parse->packetized)
1154     return gst_h265_parse_handle_frame_packetized (parse, frame);
1155 
1156   gst_buffer_map (buffer, &map, GST_MAP_READ);
1157   data = map.data;
1158   size = map.size;
1159 
1160   /* expect at least 3 bytes start_code, and 2 bytes NALU header.
1161    * the length of the NALU payload can be zero.
1162    * (e.g. EOS/EOB placed at the end of an AU.) */
1163   if (G_UNLIKELY (size < 5)) {
1164     gst_buffer_unmap (buffer, &map);
1165     *skipsize = 1;
1166     return GST_FLOW_OK;
1167   }
1168 
1169   /* need to configure aggregation */
1170   if (G_UNLIKELY (h265parse->format == GST_H265_PARSE_FORMAT_NONE))
1171     gst_h265_parse_negotiate (h265parse, GST_H265_PARSE_FORMAT_BYTE, NULL);
1172 
1173   /* avoid stale cached parsing state */
1174   if (frame->flags & GST_BASE_PARSE_FRAME_FLAG_NEW_FRAME) {
1175     GST_LOG_OBJECT (h265parse, "parsing new frame");
1176     gst_h265_parse_reset_frame (h265parse);
1177   } else {
1178     GST_LOG_OBJECT (h265parse, "resuming frame parsing");
1179   }
1180 
1181   /* Always consume the entire input buffer when in_align == ALIGN_AU */
1182   drain = GST_BASE_PARSE_DRAINING (parse)
1183       || h265parse->in_align == GST_H265_PARSE_ALIGN_AU;
1184   nonext = FALSE;
1185 
1186   current_off = h265parse->current_off;
1187   if (current_off < 0)
1188     current_off = 0;
1189 
1190   /* The parser is being drain, but no new data was added, just prentend this
1191    * AU is complete */
1192   if (drain && current_off == size) {
1193     GST_DEBUG_OBJECT (h265parse, "draining with no new data");
1194     nalu.size = 0;
1195     nalu.offset = current_off;
1196     goto end;
1197   }
1198 
1199   g_assert (current_off < size);
1200   GST_DEBUG_OBJECT (h265parse, "last parse position %d", current_off);
1201 
1202   /* check for initial skip */
1203   if (h265parse->current_off == -1) {
1204     pres =
1205         gst_h265_parser_identify_nalu_unchecked (nalparser, data, current_off,
1206         size, &nalu);
1207     switch (pres) {
1208       case GST_H265_PARSER_OK:
1209         if (nalu.sc_offset > 0) {
1210           *skipsize = nalu.sc_offset;
1211           goto skip;
1212         }
1213         break;
1214       case GST_H265_PARSER_NO_NAL:
1215         /* start code may have up to 4 bytes, and we may also get that return
1216          * value if only one of the two header bytes are present, make sure
1217          * not to skip too much */
1218         *skipsize = size - 5;
1219         goto skip;
1220       default:
1221         /* should not really occur either */
1222         GST_ELEMENT_ERROR (h265parse, STREAM, FORMAT,
1223             ("Error parsing H.265 stream"), ("Invalid H.265 stream"));
1224         goto invalid_stream;
1225     }
1226 
1227     /* Ensure we use the TS of the first NAL. This avoids broken timestamp in
1228      * the case of a miss-placed filler byte. */
1229     gst_base_parse_set_ts_at_offset (parse, nalu.offset);
1230   }
1231 
1232   while (TRUE) {
1233     pres =
1234         gst_h265_parser_identify_nalu (nalparser, data, current_off, size,
1235         &nalu);
1236 
1237     switch (pres) {
1238       case GST_H265_PARSER_OK:
1239         GST_DEBUG_OBJECT (h265parse, "complete nal (offset, size): (%u, %u) ",
1240             nalu.offset, nalu.size);
1241         break;
1242       case GST_H265_PARSER_NO_NAL_END:
1243         /* In NAL alignment, assume the NAL is complete */
1244         if (h265parse->in_align == GST_H265_PARSE_ALIGN_NAL ||
1245             h265parse->in_align == GST_H265_PARSE_ALIGN_AU) {
1246           nonext = TRUE;
1247           nalu.size = size - nalu.offset;
1248           break;
1249         }
1250         GST_DEBUG_OBJECT (h265parse, "not a complete nal found at offset %u",
1251             nalu.offset);
1252         /* if draining, accept it as complete nal */
1253         if (drain) {
1254           nonext = TRUE;
1255           nalu.size = size - nalu.offset;
1256           GST_DEBUG_OBJECT (h265parse, "draining, accepting with size %u",
1257               nalu.size);
1258           /* if it's not too short at least */
1259           if (nalu.size < 3)
1260             goto broken;
1261           break;
1262         }
1263         /* otherwise need more */
1264         goto more;
1265       case GST_H265_PARSER_BROKEN_LINK:
1266         GST_ELEMENT_ERROR (h265parse, STREAM, FORMAT,
1267             ("Error parsing H.265 stream"),
1268             ("The link to structure needed for the parsing couldn't be found"));
1269         goto invalid_stream;
1270       case GST_H265_PARSER_ERROR:
1271         /* should not really occur either */
1272         GST_ELEMENT_ERROR (h265parse, STREAM, FORMAT,
1273             ("Error parsing H.265 stream"), ("Invalid H.265 stream"));
1274         goto invalid_stream;
1275       case GST_H265_PARSER_NO_NAL:
1276         GST_ELEMENT_ERROR (h265parse, STREAM, FORMAT,
1277             ("Error parsing H.265 stream"), ("No H.265 NAL unit found"));
1278         goto invalid_stream;
1279       case GST_H265_PARSER_BROKEN_DATA:
1280         GST_WARNING_OBJECT (h265parse, "input stream is corrupt; "
1281             "it contains a NAL unit of length %u", nalu.size);
1282       broken:
1283         /* broken nal at start -> arrange to skip it,
1284          * otherwise have it terminate current au
1285          * (and so it will be skipped on next frame round) */
1286         if (current_off == 0) {
1287           GST_DEBUG_OBJECT (h265parse, "skipping broken nal");
1288           *skipsize = nalu.offset;
1289           goto skip;
1290         } else {
1291           GST_DEBUG_OBJECT (h265parse, "terminating au");
1292           nalu.size = 0;
1293           nalu.offset = nalu.sc_offset;
1294           goto end;
1295         }
1296       default:
1297         g_assert_not_reached ();
1298         break;
1299     }
1300 
1301     GST_DEBUG_OBJECT (h265parse, "%p complete nal found. Off: %u, Size: %u",
1302         data, nalu.offset, nalu.size);
1303 
1304     if (gst_h265_parse_collect_nal (h265parse, data, size, &nalu)) {
1305       /* complete current frame, if it exist */
1306       if (current_off > 0) {
1307         nalu.size = 0;
1308         nalu.offset = nalu.sc_offset;
1309         h265parse->marker = TRUE;
1310         break;
1311       }
1312     }
1313 
1314     if (!gst_h265_parse_process_nal (h265parse, &nalu)) {
1315       GST_WARNING_OBJECT (h265parse,
1316           "broken/invalid nal Type: %d %s, Size: %u will be dropped",
1317           nalu.type, _nal_name (nalu.type), nalu.size);
1318       *skipsize = nalu.size;
1319       goto skip;
1320     }
1321 
1322     /* Do not push immediatly if we don't have all headers. This ensure that
1323      * our caps are complete, avoiding a renegotiation */
1324     if (h265parse->align == GST_H265_PARSE_ALIGN_NAL &&
1325         !GST_H265_PARSE_STATE_VALID (h265parse,
1326             GST_H265_PARSE_STATE_VALID_PICTURE_HEADERS))
1327       frame->flags |= GST_BASE_PARSE_FRAME_FLAG_QUEUE;
1328 
1329     if (nonext) {
1330       /* If there is a marker flag, or input is AU, we know this is complete */
1331       if (GST_BUFFER_FLAG_IS_SET (frame->buffer, GST_BUFFER_FLAG_MARKER) ||
1332           h265parse->in_align == GST_H265_PARSE_ALIGN_AU) {
1333         h265parse->marker = TRUE;
1334         break;
1335       }
1336 
1337       /* or if we are draining or producing NALs */
1338       if (drain || h265parse->align == GST_H265_PARSE_ALIGN_NAL)
1339         break;
1340 
1341       current_off = nalu.offset + nalu.size;
1342       goto more;
1343     }
1344 
1345     /* If the output is NAL, we are done */
1346     if (h265parse->align == GST_H265_PARSE_ALIGN_NAL)
1347       break;
1348 
1349     GST_DEBUG_OBJECT (h265parse, "Looking for more");
1350     current_off = nalu.offset + nalu.size;
1351 
1352     /* expect at least 3 bytes start_code, and 2 bytes NALU header.
1353      * the length of the NALU payload can be zero.
1354      * (e.g. EOS/EOB placed at the end of an AU.) */
1355     if (G_UNLIKELY (size - current_off < 5)) {
1356       /* Finish the frame if there is no more data in the stream */
1357       if (drain)
1358         break;
1359 
1360       goto more;
1361     }
1362   }
1363 
1364 end:
1365   framesize = nalu.offset + nalu.size;
1366 
1367   gst_buffer_unmap (buffer, &map);
1368 
1369   gst_h265_parse_parse_frame (parse, frame);
1370 
1371   return gst_base_parse_finish_frame (parse, frame, framesize);
1372 
1373 more:
1374   *skipsize = 0;
1375 
1376   /* Restart parsing from here next time */
1377   if (current_off > 0)
1378     h265parse->current_off = current_off;
1379 
1380   /* Fall-through. */
1381 out:
1382   gst_buffer_unmap (buffer, &map);
1383   return GST_FLOW_OK;
1384 
1385 skip:
1386   GST_DEBUG_OBJECT (h265parse, "skipping %d", *skipsize);
1387   /* If we are collecting access units, we need to preserve the initial
1388    * config headers (SPS, PPS et al.) and only reset the frame if another
1389    * slice NAL was received. This means that broken pictures are discarded */
1390   if (h265parse->align != GST_H265_PARSE_ALIGN_AU ||
1391       !(h265parse->state & GST_H265_PARSE_STATE_VALID_PICTURE_HEADERS) ||
1392       (h265parse->state & GST_H265_PARSE_STATE_GOT_SLICE))
1393     gst_h265_parse_reset_frame (h265parse);
1394   goto out;
1395 
1396 invalid_stream:
1397   gst_buffer_unmap (buffer, &map);
1398   return GST_FLOW_ERROR;
1399 }
1400 
1401 /* byte together hevc codec data based on collected pps and sps so far */
1402 static GstBuffer *
gst_h265_parse_make_codec_data(GstH265Parse * h265parse)1403 gst_h265_parse_make_codec_data (GstH265Parse * h265parse)
1404 {
1405   GstBuffer *buf, *nal;
1406   gint i, j, k = 0;
1407   guint vps_size = 0, sps_size = 0, pps_size = 0;
1408   guint num_vps = 0, num_sps = 0, num_pps = 0;
1409   gboolean found = FALSE;
1410   GstMapInfo map;
1411   guint8 *data;
1412   gint nl;
1413   guint8 num_arrays = 0;
1414   GstH265SPS *sps = NULL;
1415   guint16 min_spatial_segmentation_idc = 0;
1416   GstH265ProfileTierLevel *pft;
1417 
1418   /* only nal payload in stored nals */
1419   /* Fixme: Current implementation is not embedding SEI in codec_data */
1420   for (i = 0; i < GST_H265_MAX_VPS_COUNT; i++) {
1421     if ((nal = h265parse->vps_nals[i])) {
1422       num_vps++;
1423       /* size bytes also count */
1424       vps_size += gst_buffer_get_size (nal) + 2;
1425     }
1426   }
1427   if (num_vps > 0)
1428     num_arrays++;
1429 
1430   for (i = 0; i < GST_H265_MAX_SPS_COUNT; i++) {
1431     if ((nal = h265parse->sps_nals[i])) {
1432       num_sps++;
1433       /* size bytes also count */
1434       sps_size += gst_buffer_get_size (nal) + 2;
1435       found = TRUE;
1436     }
1437   }
1438   if (num_sps > 0)
1439     num_arrays++;
1440 
1441   for (i = 0; i < GST_H265_MAX_PPS_COUNT; i++) {
1442     if ((nal = h265parse->pps_nals[i])) {
1443       num_pps++;
1444       /* size bytes also count */
1445       pps_size += gst_buffer_get_size (nal) + 2;
1446     }
1447   }
1448   if (num_pps > 0)
1449     num_arrays++;
1450 
1451   GST_DEBUG_OBJECT (h265parse,
1452       "constructing codec_data: num_vps =%d num_sps=%d, num_pps=%d", num_vps,
1453       num_sps, num_pps);
1454 
1455   if (!found)
1456     return NULL;
1457 
1458   sps = h265parse->nalparser->last_sps;
1459   if (!sps)
1460     return NULL;
1461 
1462   buf =
1463       gst_buffer_new_allocate (NULL,
1464       23 + (3 * num_arrays) + vps_size + sps_size + pps_size, NULL);
1465   gst_buffer_map (buf, &map, GST_MAP_WRITE);
1466   data = map.data;
1467   memset (data, 0, map.size);
1468   nl = h265parse->nal_length_size;
1469 
1470   pft = &sps->profile_tier_level;
1471   if (sps->vui_parameters_present_flag)
1472     min_spatial_segmentation_idc = sps->vui_params.min_spatial_segmentation_idc;
1473 
1474   /* HEVCDecoderConfigurationVersion = 1
1475    * profile_space | tier_flat | profile_idc |
1476    * profile_compatibility_flags | constraint_indicator_flags |
1477    * level_idc */
1478   data[0] = 1;
1479   data[1] =
1480       (pft->profile_space << 5) | (pft->tier_flag << 5) | pft->profile_idc;
1481   for (i = 2; i < 6; i++) {
1482     for (j = 7; j >= 0; j--) {
1483       data[i] |= (pft->profile_compatibility_flag[k] << j);
1484       k++;
1485     }
1486   }
1487 
1488   data[6] =
1489       (pft->progressive_source_flag << 7) |
1490       (pft->interlaced_source_flag << 6) |
1491       (pft->non_packed_constraint_flag << 5) |
1492       (pft->frame_only_constraint_flag << 4) |
1493       (pft->max_12bit_constraint_flag << 3) |
1494       (pft->max_10bit_constraint_flag << 2) |
1495       (pft->max_8bit_constraint_flag << 1) |
1496       (pft->max_422chroma_constraint_flag);
1497 
1498   data[7] =
1499       (pft->max_420chroma_constraint_flag << 7) |
1500       (pft->max_monochrome_constraint_flag << 6) |
1501       (pft->intra_constraint_flag << 5) |
1502       (pft->one_picture_only_constraint_flag << 4) |
1503       (pft->lower_bit_rate_constraint_flag << 3) |
1504       (pft->max_14bit_constraint_flag << 2);
1505 
1506   data[12] = pft->level_idc;
1507   /* min_spatial_segmentation_idc */
1508   GST_WRITE_UINT16_BE (data + 13, min_spatial_segmentation_idc);
1509   data[13] |= 0xf0;
1510   data[15] = 0xfc;              /* keeping parrallelismType as zero (unknown) */
1511   data[16] = 0xfc | sps->chroma_format_idc;
1512   data[17] = 0xf8 | sps->bit_depth_luma_minus8;
1513   data[18] = 0xf8 | sps->bit_depth_chroma_minus8;
1514   data[19] = 0x00;              /* keep avgFrameRate as unspecified */
1515   data[20] = 0x00;              /* keep avgFrameRate as unspecified */
1516   /* constFrameRate(2 bits): 0, stream may or may not be of constant framerate
1517    * numTemporalLayers (3 bits): number of temporal layers, value from SPS
1518    * TemporalIdNested (1 bit): sps_temporal_id_nesting_flag from SPS
1519    * lengthSizeMinusOne (2 bits): plus 1 indicates the length of the NALUnitLength */
1520   data[21] =
1521       0x00 | ((sps->max_sub_layers_minus1 +
1522           1) << 3) | (sps->temporal_id_nesting_flag << 2) | (nl - 1);
1523   GST_WRITE_UINT8 (data + 22, num_arrays);      /* numOfArrays */
1524 
1525   data += 23;
1526 
1527   /* VPS */
1528   if (num_vps > 0) {
1529     /* array_completeness | reserved_zero bit | nal_unit_type */
1530     data[0] = 0x00 | 0x20;
1531     data++;
1532 
1533     GST_WRITE_UINT16_BE (data, num_vps);
1534     data += 2;
1535 
1536     for (i = 0; i < GST_H265_MAX_VPS_COUNT; i++) {
1537       if ((nal = h265parse->vps_nals[i])) {
1538         gsize nal_size = gst_buffer_get_size (nal);
1539         GST_WRITE_UINT16_BE (data, nal_size);
1540         gst_buffer_extract (nal, 0, data + 2, nal_size);
1541         data += 2 + nal_size;
1542       }
1543     }
1544   }
1545 
1546   /* SPS */
1547   if (num_sps > 0) {
1548     /* array_completeness | reserved_zero bit | nal_unit_type */
1549     data[0] = 0x00 | 0x21;
1550     data++;
1551 
1552     GST_WRITE_UINT16_BE (data, num_sps);
1553     data += 2;
1554 
1555     for (i = 0; i < GST_H265_MAX_SPS_COUNT; i++) {
1556       if ((nal = h265parse->sps_nals[i])) {
1557         gsize nal_size = gst_buffer_get_size (nal);
1558         GST_WRITE_UINT16_BE (data, nal_size);
1559         gst_buffer_extract (nal, 0, data + 2, nal_size);
1560         data += 2 + nal_size;
1561       }
1562     }
1563   }
1564 
1565   /* PPS */
1566   if (num_pps > 0) {
1567     /* array_completeness | reserved_zero bit | nal_unit_type */
1568     data[0] = 0x00 | 0x22;
1569     data++;
1570 
1571     GST_WRITE_UINT16_BE (data, num_pps);
1572     data += 2;
1573 
1574     for (i = 0; i < GST_H265_MAX_PPS_COUNT; i++) {
1575       if ((nal = h265parse->pps_nals[i])) {
1576         gsize nal_size = gst_buffer_get_size (nal);
1577         GST_WRITE_UINT16_BE (data, nal_size);
1578         gst_buffer_extract (nal, 0, data + 2, nal_size);
1579         data += 2 + nal_size;
1580       }
1581     }
1582   }
1583   gst_buffer_unmap (buf, &map);
1584 
1585   return buf;
1586 }
1587 
1588 static void
gst_h265_parse_get_par(GstH265Parse * h265parse,gint * num,gint * den)1589 gst_h265_parse_get_par (GstH265Parse * h265parse, gint * num, gint * den)
1590 {
1591   if (h265parse->upstream_par_n != -1 && h265parse->upstream_par_d != -1) {
1592     *num = h265parse->upstream_par_n;
1593     *den = h265parse->upstream_par_d;
1594   } else {
1595     *num = h265parse->parsed_par_n;
1596     *den = h265parse->parsed_par_d;
1597   }
1598 }
1599 
1600 static const gchar *
digit_to_string(guint digit)1601 digit_to_string (guint digit)
1602 {
1603   static const char itoa[][2] = {
1604     "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"
1605   };
1606 
1607   if (G_LIKELY (digit < 10))
1608     return itoa[digit];
1609   else
1610     return NULL;
1611 }
1612 
1613 static const gchar *
get_tier_string(guint8 tier_flag)1614 get_tier_string (guint8 tier_flag)
1615 {
1616   const gchar *tier = NULL;
1617 
1618   if (tier_flag)
1619     tier = "high";
1620   else
1621     tier = "main";
1622 
1623   return tier;
1624 }
1625 
1626 static const gchar *
get_level_string(guint8 level_idc)1627 get_level_string (guint8 level_idc)
1628 {
1629   if (level_idc == 0)
1630     return NULL;
1631   else if (level_idc % 30 == 0)
1632     return digit_to_string (level_idc / 30);
1633   else {
1634     switch (level_idc) {
1635       case 63:
1636         return "2.1";
1637         break;
1638       case 93:
1639         return "3.1";
1640         break;
1641       case 123:
1642         return "4.1";
1643         break;
1644       case 153:
1645         return "5.1";
1646         break;
1647       case 156:
1648         return "5.2";
1649         break;
1650       case 183:
1651         return "6.1";
1652         break;
1653       case 186:
1654         return "6.2";
1655         break;
1656       default:
1657         return NULL;
1658     }
1659   }
1660 }
1661 
1662 static inline guint64
profile_to_flag(GstH265Profile p)1663 profile_to_flag (GstH265Profile p)
1664 {
1665   return (guint64) 1 << (guint64) p;
1666 }
1667 
1668 static GstCaps *
get_compatible_profile_caps(GstH265SPS * sps,GstH265Profile profile)1669 get_compatible_profile_caps (GstH265SPS * sps, GstH265Profile profile)
1670 {
1671   GstCaps *caps = NULL;
1672   gint i;
1673   GValue compat_profiles = G_VALUE_INIT;
1674   guint64 profiles = 0;
1675 
1676   g_value_init (&compat_profiles, GST_TYPE_LIST);
1677 
1678   /* Relaxing profiles condition based on decoder capability specified by spec */
1679   if (sps->profile_tier_level.profile_compatibility_flag[1])
1680     profiles |= profile_to_flag (GST_H265_PROFILE_MAIN);
1681 
1682   if (sps->profile_tier_level.profile_compatibility_flag[2])
1683     profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_10);
1684 
1685   if (sps->profile_tier_level.profile_compatibility_flag[3])
1686     profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_STILL_PICTURE);
1687 
1688   switch (profile) {
1689     case GST_H265_PROFILE_MAIN_10:
1690     {
1691       /* A.3.5 */
1692       profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_12);
1693       profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_422_10);
1694       profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_422_12);
1695       profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_444_10);
1696       profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_444_12);
1697 
1698       /* A.3.7 */
1699       profiles |= profile_to_flag (GST_H265_PROFILE_SCREEN_EXTENDED_MAIN_10);
1700 
1701       /* H.11.1.1 */
1702       profiles |= profile_to_flag (GST_H265_PROFILE_SCALABLE_MAIN_10);
1703       break;
1704     }
1705     case GST_H265_PROFILE_MAIN:
1706     {
1707       /* A.3.3 */
1708       profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_10);
1709 
1710       /* A.3.5 */
1711       profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_12);
1712       profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_422_10);
1713       profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_422_12);
1714       profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_444_10);
1715       profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_444_12);
1716 
1717       /* A.3.7 */
1718       profiles |= profile_to_flag (GST_H265_PROFILE_SCREEN_EXTENDED_MAIN);
1719       profiles |= profile_to_flag (GST_H265_PROFILE_SCREEN_EXTENDED_MAIN_10);
1720       profiles |= profile_to_flag (GST_H265_PROFILE_SCREEN_EXTENDED_MAIN_444);
1721       profiles |=
1722           profile_to_flag (GST_H265_PROFILE_SCREEN_EXTENDED_MAIN_444_10);
1723       profiles |=
1724           profile_to_flag
1725           (GST_H265_PROFILE_SCREEN_EXTENDED_HIGH_THROUGHPUT_444);
1726       profiles |=
1727           profile_to_flag
1728           (GST_H265_PROFILE_SCREEN_EXTENDED_HIGH_THROUGHPUT_444_10);
1729       profiles |=
1730           profile_to_flag
1731           (GST_H265_PROFILE_SCREEN_EXTENDED_HIGH_THROUGHPUT_444_14);
1732 
1733       /* G.11.1.1 */
1734       profiles |= profile_to_flag (GST_H265_PROFILE_MULTIVIEW_MAIN);
1735 
1736       /* H.11.1.1 */
1737       profiles |= profile_to_flag (GST_H265_PROFILE_SCALABLE_MAIN);
1738       profiles |= profile_to_flag (GST_H265_PROFILE_SCALABLE_MAIN_10);
1739 
1740       /* I.11.1.1 */
1741       profiles |= profile_to_flag (GST_H265_PROFILE_3D_MAIN);
1742       break;
1743     }
1744     case GST_H265_PROFILE_MAIN_STILL_PICTURE:
1745     {
1746       /* A.3.2, A.3.4 */
1747       profiles |= profile_to_flag (GST_H265_PROFILE_MAIN);
1748       profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_10);
1749 
1750       /* A.3.5 */
1751       profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_12);
1752       profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_422_10);
1753       profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_422_12);
1754       profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_444_10);
1755       profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_444_12);
1756 
1757       profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_INTRA);
1758       profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_10_INTRA);
1759       profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_12_INTRA);
1760       profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_422_10_INTRA);
1761       profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_422_12_INTRA);
1762       profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_444_INTRA);
1763       profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_444_10_INTRA);
1764       profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_444_12_INTRA);
1765       profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_444_16_INTRA);
1766       profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_444_STILL_PICTURE);
1767       profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_444_16_STILL_PICTURE);
1768 
1769       /* A.3.7 */
1770       profiles |= profile_to_flag (GST_H265_PROFILE_SCREEN_EXTENDED_MAIN);
1771       profiles |= profile_to_flag (GST_H265_PROFILE_SCREEN_EXTENDED_MAIN_10);
1772       profiles |= profile_to_flag (GST_H265_PROFILE_SCREEN_EXTENDED_MAIN_444);
1773       profiles |=
1774           profile_to_flag (GST_H265_PROFILE_SCREEN_EXTENDED_MAIN_444_10);
1775       profiles |=
1776           profile_to_flag
1777           (GST_H265_PROFILE_SCREEN_EXTENDED_HIGH_THROUGHPUT_444);
1778       profiles |=
1779           profile_to_flag
1780           (GST_H265_PROFILE_SCREEN_EXTENDED_HIGH_THROUGHPUT_444_10);
1781       profiles |=
1782           profile_to_flag
1783           (GST_H265_PROFILE_SCREEN_EXTENDED_HIGH_THROUGHPUT_444_14);
1784       break;
1785     }
1786     case GST_H265_PROFILE_MONOCHROME:
1787     {
1788       /* A.3.7 */
1789       profiles |= profile_to_flag (GST_H265_PROFILE_SCREEN_EXTENDED_MAIN);
1790       profiles |= profile_to_flag (GST_H265_PROFILE_SCREEN_EXTENDED_MAIN_10);
1791       profiles |= profile_to_flag (GST_H265_PROFILE_SCREEN_EXTENDED_MAIN_444);
1792       profiles |=
1793           profile_to_flag (GST_H265_PROFILE_SCREEN_EXTENDED_MAIN_444_10);
1794       profiles |=
1795           profile_to_flag
1796           (GST_H265_PROFILE_SCREEN_EXTENDED_HIGH_THROUGHPUT_444);
1797       profiles |=
1798           profile_to_flag
1799           (GST_H265_PROFILE_SCREEN_EXTENDED_HIGH_THROUGHPUT_444_10);
1800       profiles |=
1801           profile_to_flag
1802           (GST_H265_PROFILE_SCREEN_EXTENDED_HIGH_THROUGHPUT_444_14);
1803       break;
1804     }
1805     case GST_H265_PROFILE_MAIN_444:
1806     {
1807       /* A.3.7 */
1808       profiles |= profile_to_flag (GST_H265_PROFILE_SCREEN_EXTENDED_MAIN_444);
1809       profiles |=
1810           profile_to_flag (GST_H265_PROFILE_SCREEN_EXTENDED_MAIN_444_10);
1811       break;
1812     }
1813     case GST_H265_PROFILE_MAIN_444_10:
1814     {
1815       /* A.3.7 */
1816       profiles |=
1817           profile_to_flag (GST_H265_PROFILE_SCREEN_EXTENDED_MAIN_444_10);
1818       break;
1819     }
1820     case GST_H265_PROFILE_HIGH_THROUGHPUT_444:
1821     {
1822       /* A.3.7 */
1823       profiles |=
1824           profile_to_flag
1825           (GST_H265_PROFILE_SCREEN_EXTENDED_HIGH_THROUGHPUT_444);
1826       profiles |=
1827           profile_to_flag
1828           (GST_H265_PROFILE_SCREEN_EXTENDED_HIGH_THROUGHPUT_444_10);
1829       profiles |=
1830           profile_to_flag
1831           (GST_H265_PROFILE_SCREEN_EXTENDED_HIGH_THROUGHPUT_444_14);
1832       break;
1833     }
1834     case GST_H265_PROFILE_HIGH_THROUGHPUT_444_10:
1835     {
1836       /* A.3.7 */
1837       profiles |=
1838           profile_to_flag
1839           (GST_H265_PROFILE_SCREEN_EXTENDED_HIGH_THROUGHPUT_444_10);
1840       profiles |=
1841           profile_to_flag
1842           (GST_H265_PROFILE_SCREEN_EXTENDED_HIGH_THROUGHPUT_444_14);
1843       break;
1844     }
1845     case GST_H265_PROFILE_HIGH_THROUGHPUT_444_14:
1846     {
1847       /* A.3.7 */
1848       profiles |=
1849           profile_to_flag
1850           (GST_H265_PROFILE_SCREEN_EXTENDED_HIGH_THROUGHPUT_444_14);
1851       break;
1852     }
1853       /* All the -intra profiles can map to non-intra profiles, except
1854          the monochrome case for main and main-10. */
1855     case GST_H265_PROFILE_MAIN_INTRA:
1856     {
1857       if (sps->chroma_format_idc == 1) {
1858         profiles |= profile_to_flag (GST_H265_PROFILE_MAIN);
1859 
1860         /* Add all main compatible profiles without monochrome. */
1861         /* A.3.3 */
1862         profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_10);
1863 
1864         /* A.3.5 */
1865         profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_444_10);
1866         profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_444_12);
1867 
1868         /* A.3.7 */
1869         profiles |= profile_to_flag (GST_H265_PROFILE_SCREEN_EXTENDED_MAIN);
1870         profiles |= profile_to_flag (GST_H265_PROFILE_SCREEN_EXTENDED_MAIN_10);
1871         profiles |=
1872             profile_to_flag
1873             (GST_H265_PROFILE_SCREEN_EXTENDED_HIGH_THROUGHPUT_444);
1874         profiles |=
1875             profile_to_flag
1876             (GST_H265_PROFILE_SCREEN_EXTENDED_HIGH_THROUGHPUT_444_10);
1877         profiles |=
1878             profile_to_flag
1879             (GST_H265_PROFILE_SCREEN_EXTENDED_HIGH_THROUGHPUT_444_14);
1880 
1881         /* G.11.1.1 */
1882         profiles |= profile_to_flag (GST_H265_PROFILE_MULTIVIEW_MAIN);
1883 
1884         /* H.11.1.1 */
1885         profiles |= profile_to_flag (GST_H265_PROFILE_SCALABLE_MAIN);
1886         profiles |= profile_to_flag (GST_H265_PROFILE_SCALABLE_MAIN_10);
1887 
1888         /* I.11.1.1 */
1889         profiles |= profile_to_flag (GST_H265_PROFILE_3D_MAIN);
1890       }
1891 
1892       /* Add all main compatible profiles with monochrome. */
1893       profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_12);
1894       profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_422_10);
1895       profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_422_12);
1896       profiles |= profile_to_flag (GST_H265_PROFILE_SCREEN_EXTENDED_MAIN_444);
1897       profiles |=
1898           profile_to_flag (GST_H265_PROFILE_SCREEN_EXTENDED_MAIN_444_10);
1899       break;
1900     }
1901     case GST_H265_PROFILE_MAIN_10_INTRA:
1902     {
1903       if (sps->chroma_format_idc == 1) {
1904         profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_10);
1905 
1906         /* Add all main-10 compatible profiles without monochrome. */
1907         /* A.3.5 */
1908         profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_444_10);
1909         profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_444_12);
1910 
1911         /* A.3.7 */
1912         profiles |= profile_to_flag (GST_H265_PROFILE_SCREEN_EXTENDED_MAIN_10);
1913 
1914         /* H.11.1.1 */
1915         profiles |= profile_to_flag (GST_H265_PROFILE_SCALABLE_MAIN_10);
1916       }
1917 
1918       /* Add all main-10 compatible profiles with monochrome. */
1919       profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_12);
1920       profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_422_10);
1921       profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_422_12);
1922       break;
1923     }
1924     case GST_H265_PROFILE_MAIN_12_INTRA:
1925       profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_12);
1926       break;
1927     case GST_H265_PROFILE_MAIN_422_10_INTRA:
1928       profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_422_10);
1929       break;
1930     case GST_H265_PROFILE_MAIN_422_12_INTRA:
1931       profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_422_12);
1932       break;
1933     case GST_H265_PROFILE_MAIN_444_INTRA:
1934       profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_444);
1935 
1936       /* Add all main444 compatible profiles. */
1937       /* A.3.7 */
1938       profiles |= profile_to_flag (GST_H265_PROFILE_SCREEN_EXTENDED_MAIN_444);
1939       profiles |=
1940           profile_to_flag (GST_H265_PROFILE_SCREEN_EXTENDED_MAIN_444_10);
1941       break;
1942     case GST_H265_PROFILE_MAIN_444_10_INTRA:
1943       profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_444_10);
1944 
1945       /* Add all main444-10 compatible profiles. */
1946       /* A.3.7 */
1947       profiles |=
1948           profile_to_flag (GST_H265_PROFILE_SCREEN_EXTENDED_MAIN_444_10);
1949       break;
1950     case GST_H265_PROFILE_MAIN_444_12_INTRA:
1951       profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_444_12);
1952       break;
1953     default:
1954       break;
1955   }
1956 
1957   if (profiles) {
1958     GValue value = G_VALUE_INIT;
1959     const gchar *profile_str;
1960     caps = gst_caps_new_empty_simple ("video/x-h265");
1961 
1962     for (i = GST_H265_PROFILE_MAIN; i < GST_H265_PROFILE_MAX; i++) {
1963       if ((profiles & profile_to_flag (i)) == profile_to_flag (i)) {
1964         profile_str = gst_h265_profile_to_string (i);
1965 
1966         if (G_UNLIKELY (profile_str == NULL)) {
1967           GST_FIXME ("Unhandled profile index %d", i);
1968           continue;
1969         }
1970 
1971         g_value_init (&value, G_TYPE_STRING);
1972         g_value_set_string (&value, profile_str);
1973         gst_value_list_append_value (&compat_profiles, &value);
1974         g_value_unset (&value);
1975       }
1976     }
1977 
1978     gst_caps_set_value (caps, "profile", &compat_profiles);
1979     g_value_unset (&compat_profiles);
1980   }
1981 
1982   return caps;
1983 }
1984 
1985 static void
fix_invalid_profile(GstH265Parse * h265parse,GstCaps * caps,GstH265SPS * sps)1986 fix_invalid_profile (GstH265Parse * h265parse, GstCaps * caps, GstH265SPS * sps)
1987 {
1988   /* HACK: This is a work-around to identify some main profile streams
1989    * having wrong profile_idc. There are some wrongly encoded main profile
1990    * streams which doesn't have any of the profile_idc values mentioned in
1991    * Annex-A. Just assuming them as MAIN profile for now if they meet the
1992    * A.3.2 requirement. */
1993   if (sps->chroma_format_idc == 1 && sps->bit_depth_luma_minus8 == 0 &&
1994       sps->bit_depth_chroma_minus8 == 0 && sps->sps_extension_flag == 0) {
1995     gst_caps_set_simple (caps, "profile", G_TYPE_STRING, "main", NULL);
1996     GST_WARNING_OBJECT (h265parse,
1997         "Wrong profile_idc = 0, setting it as main profile !!");
1998   }
1999 }
2000 
2001 /* if downstream didn't support the exact profile indicated in sps header,
2002  * check for the compatible profiles also */
2003 static void
ensure_caps_profile(GstH265Parse * h265parse,GstCaps * caps,GstH265SPS * sps,GstH265Profile profile)2004 ensure_caps_profile (GstH265Parse * h265parse, GstCaps * caps, GstH265SPS * sps,
2005     GstH265Profile profile)
2006 {
2007   GstCaps *peer_caps, *compat_caps;
2008 
2009   if (profile == GST_H265_PROFILE_INVALID)
2010     fix_invalid_profile (h265parse, caps, sps);
2011 
2012   peer_caps = gst_pad_get_current_caps (GST_BASE_PARSE_SRC_PAD (h265parse));
2013   if (!peer_caps || !gst_caps_can_intersect (caps, peer_caps)) {
2014     GstCaps *filter_caps = gst_caps_new_empty_simple ("video/x-h265");
2015 
2016     if (peer_caps)
2017       gst_caps_unref (peer_caps);
2018     peer_caps =
2019         gst_pad_peer_query_caps (GST_BASE_PARSE_SRC_PAD (h265parse),
2020         filter_caps);
2021 
2022     gst_caps_unref (filter_caps);
2023   }
2024 
2025   if (peer_caps && !gst_caps_can_intersect (caps, peer_caps)) {
2026     GstStructure *structure;
2027 
2028     compat_caps = get_compatible_profile_caps (sps, profile);
2029     if (compat_caps != NULL) {
2030       GstCaps *res_caps = NULL;
2031 
2032       res_caps = gst_caps_intersect (peer_caps, compat_caps);
2033 
2034       if (res_caps && !gst_caps_is_empty (res_caps)) {
2035         const gchar *profile_str = NULL;
2036 
2037         res_caps = gst_caps_fixate (res_caps);
2038         structure = gst_caps_get_structure (res_caps, 0);
2039         profile_str = gst_structure_get_string (structure, "profile");
2040         if (profile_str) {
2041           gst_caps_set_simple (caps, "profile", G_TYPE_STRING, profile_str,
2042               NULL);
2043           GST_DEBUG_OBJECT (h265parse,
2044               "Setting compatible profile %s to the caps", profile_str);
2045         }
2046       }
2047       if (res_caps)
2048         gst_caps_unref (res_caps);
2049       gst_caps_unref (compat_caps);
2050     }
2051   }
2052   if (peer_caps)
2053     gst_caps_unref (peer_caps);
2054 }
2055 
2056 static gboolean
gst_h265_parse_is_field_interlaced(GstH265Parse * h265parse)2057 gst_h265_parse_is_field_interlaced (GstH265Parse * h265parse)
2058 {
2059   /* FIXME: The SEI is optional, so theoretically there could be files with
2060    * the interlaced_source_flag set to TRUE but no SEI present, or SEI present
2061    * but no pic_struct. Haven't seen any such files in practice, and we don't
2062    * know how to interpret the data without the pic_struct, so we'll treat
2063    * them as progressive */
2064 
2065   switch (h265parse->sei_pic_struct) {
2066     case GST_H265_SEI_PIC_STRUCT_TOP_FIELD:
2067     case GST_H265_SEI_PIC_STRUCT_TOP_PAIRED_PREVIOUS_BOTTOM:
2068     case GST_H265_SEI_PIC_STRUCT_TOP_PAIRED_NEXT_BOTTOM:
2069     case GST_H265_SEI_PIC_STRUCT_BOTTOM_FIELD:
2070     case GST_H265_SEI_PIC_STRUCT_BOTTOM_PAIRED_PREVIOUS_TOP:
2071     case GST_H265_SEI_PIC_STRUCT_BOTTOM_PAIRED_NEXT_TOP:
2072       return TRUE;
2073       break;
2074     default:
2075       break;
2076   }
2077 
2078   return FALSE;
2079 }
2080 
2081 static void
gst_h265_parse_update_src_caps(GstH265Parse * h265parse,GstCaps * caps)2082 gst_h265_parse_update_src_caps (GstH265Parse * h265parse, GstCaps * caps)
2083 {
2084   GstH265SPS *sps = NULL;
2085   GstCaps *sink_caps, *src_caps;
2086   gboolean modified = FALSE;
2087   GstBuffer *buf = NULL;
2088   GstStructure *s = NULL;
2089 
2090   if (G_UNLIKELY (!gst_pad_has_current_caps (GST_BASE_PARSE_SRC_PAD
2091               (h265parse))))
2092     modified = TRUE;
2093   else if (G_UNLIKELY (!h265parse->update_caps))
2094     return;
2095 
2096   /* if this is being called from the first _setcaps call, caps on the sinkpad
2097    * aren't set yet and so they need to be passed as an argument */
2098   if (caps)
2099     sink_caps = gst_caps_ref (caps);
2100   else
2101     sink_caps = gst_pad_get_current_caps (GST_BASE_PARSE_SINK_PAD (h265parse));
2102 
2103   /* carry over input caps as much as possible; override with our own stuff */
2104   if (!sink_caps)
2105     sink_caps = gst_caps_new_empty_simple ("video/x-h265");
2106   else
2107     s = gst_caps_get_structure (sink_caps, 0);
2108 
2109   sps = h265parse->nalparser->last_sps;
2110   GST_DEBUG_OBJECT (h265parse, "sps: %p", sps);
2111 
2112   /* only codec-data for nice-and-clean au aligned packetized hevc format */
2113   if ((h265parse->format == GST_H265_PARSE_FORMAT_HVC1
2114           || h265parse->format == GST_H265_PARSE_FORMAT_HEV1)
2115       && h265parse->align == GST_H265_PARSE_ALIGN_AU) {
2116     buf = gst_h265_parse_make_codec_data (h265parse);
2117     if (buf && h265parse->codec_data) {
2118       GstMapInfo map;
2119 
2120       gst_buffer_map (buf, &map, GST_MAP_READ);
2121       if (map.size != gst_buffer_get_size (h265parse->codec_data) ||
2122           gst_buffer_memcmp (h265parse->codec_data, 0, map.data, map.size))
2123         modified = TRUE;
2124 
2125       gst_buffer_unmap (buf, &map);
2126     } else {
2127       if (!buf && h265parse->codec_data_in)
2128         buf = gst_buffer_ref (h265parse->codec_data_in);
2129       modified = TRUE;
2130     }
2131   }
2132 
2133   caps = NULL;
2134   if (G_UNLIKELY (!sps)) {
2135     caps = gst_caps_copy (sink_caps);
2136   } else {
2137     gint crop_width, crop_height;
2138     const gchar *chroma_format = NULL;
2139     guint bit_depth_chroma;
2140     GstH265VPS *vps = sps->vps;
2141     GstH265VUIParams *vui = &sps->vui_params;
2142     gchar *colorimetry = NULL;
2143 
2144     GST_DEBUG_OBJECT (h265parse, "vps: %p", vps);
2145 
2146     if (sps->conformance_window_flag) {
2147       crop_width = sps->crop_rect_width;
2148       crop_height = sps->crop_rect_height;
2149     } else {
2150       crop_width = sps->width;
2151       crop_height = sps->height;
2152     }
2153     if (gst_h265_parse_is_field_interlaced (h265parse)) {
2154       crop_height *= 2;
2155     }
2156 
2157     if (G_UNLIKELY (h265parse->width != crop_width ||
2158             h265parse->height != crop_height)) {
2159       h265parse->width = crop_width;
2160       h265parse->height = crop_height;
2161       GST_INFO_OBJECT (h265parse, "resolution changed %dx%d",
2162           h265parse->width, h265parse->height);
2163       modified = TRUE;
2164     }
2165 
2166     /* 0/1 is set as the default in the codec parser */
2167     if (vui->timing_info_present_flag) {
2168       gint fps_num = 0, fps_den = 1;
2169 
2170       if (!(sps->fps_num == 0 && sps->fps_den == 1)) {
2171         fps_num = sps->fps_num;
2172         fps_den = sps->fps_den;
2173       } else if (!(sps->vui_params.time_scale == 0 &&
2174               sps->vui_params.num_units_in_tick == 1)) {
2175         fps_num = sps->vui_params.time_scale;
2176         fps_den = sps->vui_params.num_units_in_tick;
2177 
2178         if (gst_h265_parse_is_field_interlaced (h265parse)
2179             && h265parse->parsed_framerate) {
2180           gint new_fps_num, new_fps_den;
2181 
2182           gst_util_fraction_multiply (fps_num, fps_den, 1, 2, &new_fps_num,
2183               &new_fps_den);
2184           fps_num = new_fps_num;
2185           fps_den = new_fps_den;
2186           h265parse->parsed_framerate = FALSE;
2187         }
2188       }
2189 
2190       if (G_UNLIKELY (h265parse->fps_num != fps_num
2191               || h265parse->fps_den != fps_den)) {
2192         GST_INFO_OBJECT (h265parse, "framerate changed %d/%d",
2193             fps_num, fps_den);
2194         h265parse->fps_num = fps_num;
2195         h265parse->fps_den = fps_den;
2196         modified = TRUE;
2197       }
2198     }
2199 
2200     if (vui->aspect_ratio_info_present_flag) {
2201       if (G_UNLIKELY ((h265parse->parsed_par_n != vui->par_n)
2202               && (h265parse->parsed_par_d != sps->vui_params.par_d))) {
2203         h265parse->parsed_par_n = vui->par_n;
2204         h265parse->parsed_par_d = vui->par_d;
2205         GST_INFO_OBJECT (h265parse, "pixel aspect ratio has been changed %d/%d",
2206             h265parse->parsed_par_n, h265parse->parsed_par_d);
2207         modified = TRUE;
2208       }
2209 
2210     }
2211 
2212     if (vui->video_signal_type_present_flag &&
2213         vui->colour_description_present_flag) {
2214       GstVideoColorimetry ci = { 0, };
2215       gchar *old_colorimetry = NULL;
2216 
2217       if (vui->video_full_range_flag)
2218         ci.range = GST_VIDEO_COLOR_RANGE_0_255;
2219       else
2220         ci.range = GST_VIDEO_COLOR_RANGE_16_235;
2221 
2222       ci.matrix = gst_video_color_matrix_from_iso (vui->matrix_coefficients);
2223       ci.transfer =
2224           gst_video_transfer_function_from_iso (vui->transfer_characteristics);
2225       ci.primaries = gst_video_color_primaries_from_iso (vui->colour_primaries);
2226 
2227       old_colorimetry =
2228           gst_video_colorimetry_to_string (&h265parse->parsed_colorimetry);
2229       colorimetry = gst_video_colorimetry_to_string (&ci);
2230 
2231       if (colorimetry && g_strcmp0 (old_colorimetry, colorimetry)) {
2232         GST_INFO_OBJECT (h265parse,
2233             "colorimetry has been changed from %s to %s",
2234             GST_STR_NULL (old_colorimetry), colorimetry);
2235         h265parse->parsed_colorimetry = ci;
2236         modified = TRUE;
2237       }
2238 
2239       g_free (old_colorimetry);
2240     }
2241 
2242     if (G_UNLIKELY (modified || h265parse->update_caps)) {
2243       gint fps_num = h265parse->fps_num;
2244       gint fps_den = h265parse->fps_den;
2245       gint width, height;
2246       GstClockTime latency = 0;
2247 
2248       caps = gst_caps_copy (sink_caps);
2249 
2250       /* sps should give this but upstream overrides */
2251       if (s && gst_structure_has_field (s, "width"))
2252         gst_structure_get_int (s, "width", &width);
2253       else
2254         width = h265parse->width;
2255 
2256       if (s && gst_structure_has_field (s, "height"))
2257         gst_structure_get_int (s, "height", &height);
2258       else
2259         height = h265parse->height;
2260 
2261       gst_caps_set_simple (caps, "width", G_TYPE_INT, width,
2262           "height", G_TYPE_INT, height, NULL);
2263 
2264       h265parse->parsed_framerate = FALSE;
2265       /* upstream overrides */
2266       if (s && gst_structure_has_field (s, "framerate"))
2267         gst_structure_get_fraction (s, "framerate", &fps_num, &fps_den);
2268 
2269       /* but not necessarily or reliably this */
2270       if (fps_den > 0) {
2271         GstStructure *s2;
2272         GstClockTime val;
2273 
2274         GST_INFO_OBJECT (h265parse, "setting framerate in caps");
2275         gst_caps_set_simple (caps, "framerate",
2276             GST_TYPE_FRACTION, fps_num, fps_den, NULL);
2277         s2 = gst_caps_get_structure (caps, 0);
2278         gst_structure_get_fraction (s2, "framerate", &h265parse->parsed_fps_n,
2279             &h265parse->parsed_fps_d);
2280         gst_base_parse_set_frame_rate (GST_BASE_PARSE (h265parse),
2281             fps_num, fps_den, 0, 0);
2282         val = sps->profile_tier_level.interlaced_source_flag ? GST_SECOND / 2 :
2283             GST_SECOND;
2284         h265parse->parsed_framerate = TRUE;
2285 
2286         /* If we know the frame duration, and if we are not in one of the zero
2287          * latency pattern, add one frame of latency */
2288         if (fps_num > 0 &&
2289             h265parse->in_align != GST_H265_PARSE_ALIGN_AU &&
2290             !(h265parse->in_align == GST_H265_PARSE_ALIGN_NAL &&
2291                 h265parse->align == GST_H265_PARSE_ALIGN_NAL))
2292           latency = gst_util_uint64_scale (val, fps_den, fps_num);
2293 
2294         gst_base_parse_set_latency (GST_BASE_PARSE (h265parse), latency,
2295             latency);
2296       }
2297 
2298       bit_depth_chroma = sps->bit_depth_chroma_minus8 + 8;
2299 
2300       switch (sps->chroma_format_idc) {
2301         case 0:
2302           chroma_format = "4:0:0";
2303           bit_depth_chroma = 0;
2304           break;
2305         case 1:
2306           chroma_format = "4:2:0";
2307           break;
2308         case 2:
2309           chroma_format = "4:2:2";
2310           break;
2311         case 3:
2312           chroma_format = "4:4:4";
2313           break;
2314         default:
2315           break;
2316       }
2317 
2318       if (chroma_format)
2319         gst_caps_set_simple (caps, "chroma-format", G_TYPE_STRING,
2320             chroma_format, "bit-depth-luma", G_TYPE_UINT,
2321             sps->bit_depth_luma_minus8 + 8, "bit-depth-chroma", G_TYPE_UINT,
2322             bit_depth_chroma, NULL);
2323 
2324       if (colorimetry && (!s || !gst_structure_has_field (s, "colorimetry"))) {
2325         gst_caps_set_simple (caps, "colorimetry", G_TYPE_STRING, colorimetry,
2326             NULL);
2327       }
2328     }
2329 
2330     g_free (colorimetry);
2331   }
2332 
2333   if (caps) {
2334     gint par_n, par_d;
2335     const gchar *mdi_str = NULL;
2336     const gchar *cll_str = NULL;
2337     gboolean codec_data_modified = FALSE;
2338 
2339     gst_caps_set_simple (caps, "parsed", G_TYPE_BOOLEAN, TRUE,
2340         "stream-format", G_TYPE_STRING,
2341         gst_h265_parse_get_string (h265parse, TRUE, h265parse->format),
2342         "alignment", G_TYPE_STRING,
2343         gst_h265_parse_get_string (h265parse, FALSE, h265parse->align), NULL);
2344 
2345     gst_h265_parse_get_par (h265parse, &par_n, &par_d);
2346     if (par_n != 0 && par_d != 0 &&
2347         (!s || !gst_structure_has_field (s, "pixel-aspect-ratio"))) {
2348       GST_INFO_OBJECT (h265parse, "PAR %d/%d", par_n, par_d);
2349       gst_caps_set_simple (caps, "pixel-aspect-ratio", GST_TYPE_FRACTION,
2350           par_n, par_d, NULL);
2351     }
2352 
2353     /* set profile and level in caps */
2354     if (sps) {
2355       const gchar *profile, *tier, *level;
2356       GstH265Profile p;
2357 
2358       p = gst_h265_get_profile_from_sps (sps);
2359       profile = gst_h265_profile_to_string (p);
2360 
2361       if (s && gst_structure_has_field (s, "profile")) {
2362         const gchar *profile_sink = gst_structure_get_string (s, "profile");
2363         GstH265Profile p_sink = gst_h265_profile_from_string (profile_sink);
2364 
2365         if (p != p_sink) {
2366           const gchar *profile_src;
2367 
2368           p = MAX (p, p_sink);
2369           profile_src = (p == p_sink) ? profile_sink : profile;
2370           GST_INFO_OBJECT (h265parse,
2371               "Upstream profile (%s) is different than in SPS (%s). "
2372               "Using %s.", profile_sink, profile, profile_src);
2373           profile = profile_src;
2374         }
2375       }
2376 
2377       if (profile != NULL)
2378         gst_caps_set_simple (caps, "profile", G_TYPE_STRING, profile, NULL);
2379 
2380       tier = get_tier_string (sps->profile_tier_level.tier_flag);
2381       if (tier != NULL)
2382         gst_caps_set_simple (caps, "tier", G_TYPE_STRING, tier, NULL);
2383 
2384       level = get_level_string (sps->profile_tier_level.level_idc);
2385       if (level != NULL)
2386         gst_caps_set_simple (caps, "level", G_TYPE_STRING, level, NULL);
2387 
2388       /* relax the profile constraint to find a suitable decoder */
2389       ensure_caps_profile (h265parse, caps, sps, p);
2390     }
2391 
2392     if (s)
2393       mdi_str = gst_structure_get_string (s, "mastering-display-info");
2394     if (mdi_str) {
2395       gst_caps_set_simple (caps, "mastering-display-info", G_TYPE_STRING,
2396           mdi_str, NULL);
2397     } else if (h265parse->mastering_display_info_state !=
2398         GST_H265_PARSE_SEI_EXPIRED &&
2399         !gst_video_mastering_display_info_add_to_caps
2400         (&h265parse->mastering_display_info, caps)) {
2401       GST_WARNING_OBJECT (h265parse,
2402           "Couldn't set mastering display info to caps");
2403     }
2404 
2405     if (s)
2406       cll_str = gst_structure_get_string (s, "content-light-level");
2407     if (cll_str) {
2408       gst_caps_set_simple (caps, "content-light-level", G_TYPE_STRING, cll_str,
2409           NULL);
2410     } else if (h265parse->content_light_level_state !=
2411         GST_H265_PARSE_SEI_EXPIRED &&
2412         !gst_video_content_light_level_add_to_caps
2413         (&h265parse->content_light_level, caps)) {
2414       GST_WARNING_OBJECT (h265parse,
2415           "Couldn't set content light level to caps");
2416     }
2417 
2418     src_caps = gst_pad_get_current_caps (GST_BASE_PARSE_SRC_PAD (h265parse));
2419 
2420     if (src_caps) {
2421       GstStructure *src_caps_str = gst_caps_get_structure (src_caps, 0);
2422 
2423       /* use codec data from old caps for comparison if we have pushed frame for now.
2424        * we don't want to resend caps if everything is same except codec data.
2425        * However, if the updated sps/pps is not in bitstream, we should put
2426        * it on bitstream */
2427       if (gst_structure_has_field (src_caps_str, "codec_data")) {
2428         const GValue *codec_data_value =
2429             gst_structure_get_value (src_caps_str, "codec_data");
2430 
2431         if (!GST_VALUE_HOLDS_BUFFER (codec_data_value)) {
2432           GST_WARNING_OBJECT (h265parse, "codec_data does not hold buffer");
2433         } else if (!h265parse->first_frame) {
2434           /* If there is no pushed frame before, we can update caps without worry.
2435            * But updating codec_data in the middle of frames
2436            * (especially on non-keyframe) might make downstream be confused.
2437            * Therefore we are setting old codec data
2438            * (i.e., was pushed to downstream previously) to new caps candidate
2439            * here for gst_caps_is_strictly_equal() to be returned TRUE if only
2440            * the codec_data is different, and to avoid re-sending caps it
2441            * that case.
2442            */
2443           gst_caps_set_value (caps, "codec_data", codec_data_value);
2444 
2445           /* check for codec_data update to re-send sps/pps inband data if
2446            * current frame has no sps/pps but upstream codec_data was updated.
2447            * Note that have_vps_in_frame is skipped here since it's optional  */
2448           if ((!h265parse->have_sps_in_frame || !h265parse->have_pps_in_frame)
2449               && buf) {
2450             GstBuffer *codec_data_buf = gst_value_get_buffer (codec_data_value);
2451             GstMapInfo map;
2452 
2453             gst_buffer_map (buf, &map, GST_MAP_READ);
2454             if (map.size != gst_buffer_get_size (codec_data_buf) ||
2455                 gst_buffer_memcmp (codec_data_buf, 0, map.data, map.size)) {
2456               codec_data_modified = TRUE;
2457             }
2458 
2459             gst_buffer_unmap (buf, &map);
2460           }
2461         }
2462       } else if (!buf) {
2463         GstStructure *s;
2464         /* remove any left-over codec-data hanging around */
2465         s = gst_caps_get_structure (caps, 0);
2466         gst_structure_remove_field (s, "codec_data");
2467       }
2468     }
2469 
2470     if (!(src_caps && gst_caps_is_strictly_equal (src_caps, caps))) {
2471       /* update codec data to new value */
2472       if (buf) {
2473         gst_caps_set_simple (caps, "codec_data", GST_TYPE_BUFFER, buf, NULL);
2474         gst_buffer_replace (&h265parse->codec_data, buf);
2475         gst_buffer_unref (buf);
2476         buf = NULL;
2477       } else {
2478         GstStructure *s;
2479         /* remove any left-over codec-data hanging around */
2480         s = gst_caps_get_structure (caps, 0);
2481         gst_structure_remove_field (s, "codec_data");
2482         gst_buffer_replace (&h265parse->codec_data, NULL);
2483       }
2484 
2485       gst_pad_set_caps (GST_BASE_PARSE_SRC_PAD (h265parse), caps);
2486     } else if (codec_data_modified) {
2487       GST_DEBUG_OBJECT (h265parse,
2488           "Only codec_data is different, need inband vps/sps/pps update");
2489 
2490       /* this will insert updated codec_data with next idr */
2491       h265parse->push_codec = TRUE;
2492     }
2493 
2494     if (src_caps)
2495       gst_caps_unref (src_caps);
2496     gst_caps_unref (caps);
2497   }
2498 
2499   gst_caps_unref (sink_caps);
2500   if (buf)
2501     gst_buffer_unref (buf);
2502 
2503 }
2504 
2505 static GstFlowReturn
gst_h265_parse_parse_frame(GstBaseParse * parse,GstBaseParseFrame * frame)2506 gst_h265_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
2507 {
2508   GstH265Parse *h265parse;
2509   GstBuffer *buffer;
2510   guint av;
2511 
2512   h265parse = GST_H265_PARSE (parse);
2513   buffer = frame->buffer;
2514 
2515   gst_h265_parse_update_src_caps (h265parse, NULL);
2516 
2517   if (h265parse->fps_num > 0 && h265parse->fps_den > 0) {
2518     GstClockTime val =
2519         gst_h265_parse_is_field_interlaced (h265parse) ? GST_SECOND /
2520         2 : GST_SECOND;
2521 
2522     GST_BUFFER_DURATION (buffer) = gst_util_uint64_scale (val,
2523         h265parse->fps_den, h265parse->fps_num);
2524   }
2525 
2526   if (h265parse->keyframe)
2527     GST_BUFFER_FLAG_UNSET (buffer, GST_BUFFER_FLAG_DELTA_UNIT);
2528   else
2529     GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT);
2530 
2531   if (h265parse->discard_bidirectional && h265parse->bidirectional)
2532     goto discard;
2533 
2534 
2535   if (h265parse->header)
2536     GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_HEADER);
2537   else
2538     GST_BUFFER_FLAG_UNSET (buffer, GST_BUFFER_FLAG_HEADER);
2539 
2540   if (h265parse->discont) {
2541     GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
2542     h265parse->discont = FALSE;
2543   }
2544 
2545   if (h265parse->marker) {
2546     GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_MARKER);
2547     h265parse->marker = FALSE;
2548   } else {
2549     GST_BUFFER_FLAG_UNSET (buffer, GST_BUFFER_FLAG_MARKER);
2550   }
2551 
2552   /* replace with transformed HEVC output if applicable */
2553   av = gst_adapter_available (h265parse->frame_out);
2554   if (av) {
2555     GstBuffer *buf;
2556 
2557     buf = gst_adapter_take_buffer (h265parse->frame_out, av);
2558     gst_buffer_copy_into (buf, buffer, GST_BUFFER_COPY_METADATA, 0, -1);
2559     gst_buffer_replace (&frame->out_buffer, buf);
2560     gst_buffer_unref (buf);
2561   }
2562 
2563 done:
2564   return GST_FLOW_OK;
2565 
2566 discard:
2567   GST_DEBUG_OBJECT (h265parse, "Discarding bidirectional frame");
2568   frame->flags |= GST_BASE_PARSE_FRAME_FLAG_DROP;
2569   gst_h265_parse_reset_frame (h265parse);
2570   goto done;
2571 
2572 }
2573 
2574 /* sends a codec NAL downstream, decorating and transforming as needed.
2575  * No ownership is taken of @nal */
2576 static GstFlowReturn
gst_h265_parse_push_codec_buffer(GstH265Parse * h265parse,GstBuffer * nal,GstBuffer * buffer)2577 gst_h265_parse_push_codec_buffer (GstH265Parse * h265parse, GstBuffer * nal,
2578     GstBuffer * buffer)
2579 {
2580   GstMapInfo map;
2581 
2582   gst_buffer_map (nal, &map, GST_MAP_READ);
2583   nal = gst_h265_parse_wrap_nal (h265parse, h265parse->format,
2584       map.data, map.size);
2585   gst_buffer_unmap (nal, &map);
2586 
2587   if (h265parse->discont) {
2588     GST_BUFFER_FLAG_SET (nal, GST_BUFFER_FLAG_DISCONT);
2589     h265parse->discont = FALSE;
2590   }
2591 
2592   GST_BUFFER_PTS (nal) = GST_BUFFER_PTS (buffer);
2593   GST_BUFFER_DTS (nal) = GST_BUFFER_DTS (buffer);
2594   GST_BUFFER_DURATION (nal) = 0;
2595 
2596   return gst_pad_push (GST_BASE_PARSE_SRC_PAD (h265parse), nal);
2597 }
2598 
2599 static GstEvent *
check_pending_key_unit_event(GstEvent * pending_event,GstSegment * segment,GstClockTime timestamp,guint flags,GstClockTime pending_key_unit_ts)2600 check_pending_key_unit_event (GstEvent * pending_event, GstSegment * segment,
2601     GstClockTime timestamp, guint flags, GstClockTime pending_key_unit_ts)
2602 {
2603   GstClockTime running_time, stream_time;
2604   gboolean all_headers;
2605   guint count;
2606   GstEvent *event = NULL;
2607 
2608   g_return_val_if_fail (segment != NULL, NULL);
2609 
2610   if (pending_event == NULL)
2611     goto out;
2612 
2613   if (GST_CLOCK_TIME_IS_VALID (pending_key_unit_ts) &&
2614       timestamp == GST_CLOCK_TIME_NONE)
2615     goto out;
2616 
2617   running_time = gst_segment_to_running_time (segment,
2618       GST_FORMAT_TIME, timestamp);
2619 
2620   GST_INFO ("now %" GST_TIME_FORMAT " wanted %" GST_TIME_FORMAT,
2621       GST_TIME_ARGS (running_time), GST_TIME_ARGS (pending_key_unit_ts));
2622   if (GST_CLOCK_TIME_IS_VALID (pending_key_unit_ts) &&
2623       running_time < pending_key_unit_ts)
2624     goto out;
2625 
2626   if (flags & GST_BUFFER_FLAG_DELTA_UNIT) {
2627     GST_DEBUG ("pending force key unit, waiting for keyframe");
2628     goto out;
2629   }
2630 
2631   stream_time = gst_segment_to_stream_time (segment,
2632       GST_FORMAT_TIME, timestamp);
2633 
2634   if (!gst_video_event_parse_upstream_force_key_unit (pending_event,
2635           NULL, &all_headers, &count)) {
2636     gst_video_event_parse_downstream_force_key_unit (pending_event, NULL,
2637         NULL, NULL, &all_headers, &count);
2638   }
2639 
2640   event =
2641       gst_video_event_new_downstream_force_key_unit (timestamp, stream_time,
2642       running_time, all_headers, count);
2643   gst_event_set_seqnum (event, gst_event_get_seqnum (pending_event));
2644 
2645 out:
2646   return event;
2647 }
2648 
2649 static void
gst_h265_parse_prepare_key_unit(GstH265Parse * parse,GstEvent * event)2650 gst_h265_parse_prepare_key_unit (GstH265Parse * parse, GstEvent * event)
2651 {
2652   GstClockTime running_time;
2653   guint count;
2654 #ifndef GST_DISABLE_GST_DEBUG
2655   gboolean have_vps, have_sps, have_pps;
2656   gint i;
2657 #endif
2658 
2659   parse->pending_key_unit_ts = GST_CLOCK_TIME_NONE;
2660   gst_event_replace (&parse->force_key_unit_event, NULL);
2661 
2662   gst_video_event_parse_downstream_force_key_unit (event,
2663       NULL, NULL, &running_time, NULL, &count);
2664 
2665   GST_INFO_OBJECT (parse, "pushing downstream force-key-unit event %d "
2666       "%" GST_TIME_FORMAT " count %d", gst_event_get_seqnum (event),
2667       GST_TIME_ARGS (running_time), count);
2668   gst_pad_push_event (GST_BASE_PARSE_SRC_PAD (parse), event);
2669 
2670 #ifndef GST_DISABLE_GST_DEBUG
2671   have_vps = have_sps = have_pps = FALSE;
2672   for (i = 0; i < GST_H265_MAX_VPS_COUNT; i++) {
2673     if (parse->vps_nals[i] != NULL) {
2674       have_vps = TRUE;
2675       break;
2676     }
2677   }
2678   for (i = 0; i < GST_H265_MAX_SPS_COUNT; i++) {
2679     if (parse->sps_nals[i] != NULL) {
2680       have_sps = TRUE;
2681       break;
2682     }
2683   }
2684   for (i = 0; i < GST_H265_MAX_PPS_COUNT; i++) {
2685     if (parse->pps_nals[i] != NULL) {
2686       have_pps = TRUE;
2687       break;
2688     }
2689   }
2690 
2691   GST_INFO_OBJECT (parse,
2692       "preparing key unit, have vps %d have sps %d have pps %d", have_vps,
2693       have_sps, have_pps);
2694 #endif
2695 
2696   /* set push_codec to TRUE so that pre_push_frame sends VPS/SPS/PPS again */
2697   parse->push_codec = TRUE;
2698 }
2699 
2700 static gboolean
gst_h265_parse_handle_vps_sps_pps_nals(GstH265Parse * h265parse,GstBuffer * buffer,GstBaseParseFrame * frame)2701 gst_h265_parse_handle_vps_sps_pps_nals (GstH265Parse * h265parse,
2702     GstBuffer * buffer, GstBaseParseFrame * frame)
2703 {
2704   GstBuffer *codec_nal;
2705   gint i;
2706   gboolean send_done = FALSE;
2707 
2708   if (h265parse->have_vps_in_frame && h265parse->have_sps_in_frame
2709       && h265parse->have_pps_in_frame) {
2710     GST_DEBUG_OBJECT (h265parse, "VPS/SPS/PPS exist in frame, will not insert");
2711     return TRUE;
2712   }
2713 
2714   if (h265parse->align == GST_H265_PARSE_ALIGN_NAL) {
2715     /* send separate config NAL buffers */
2716     GST_DEBUG_OBJECT (h265parse, "- sending VPS/SPS/PPS");
2717     for (i = 0; i < GST_H265_MAX_VPS_COUNT; i++) {
2718       if ((codec_nal = h265parse->vps_nals[i])) {
2719         GST_DEBUG_OBJECT (h265parse, "sending VPS nal");
2720         gst_h265_parse_push_codec_buffer (h265parse, codec_nal, buffer);
2721         send_done = TRUE;
2722       }
2723     }
2724     for (i = 0; i < GST_H265_MAX_SPS_COUNT; i++) {
2725       if ((codec_nal = h265parse->sps_nals[i])) {
2726         GST_DEBUG_OBJECT (h265parse, "sending SPS nal");
2727         gst_h265_parse_push_codec_buffer (h265parse, codec_nal, buffer);
2728         send_done = TRUE;
2729       }
2730     }
2731     for (i = 0; i < GST_H265_MAX_PPS_COUNT; i++) {
2732       if ((codec_nal = h265parse->pps_nals[i])) {
2733         GST_DEBUG_OBJECT (h265parse, "sending PPS nal");
2734         gst_h265_parse_push_codec_buffer (h265parse, codec_nal, buffer);
2735         send_done = TRUE;
2736       }
2737     }
2738   } else {
2739     /* insert config NALs into AU */
2740     GstByteWriter bw;
2741     GstBuffer *new_buf;
2742     const gboolean bs = h265parse->format == GST_H265_PARSE_FORMAT_BYTE;
2743     const gint nls = 4 - h265parse->nal_length_size;
2744     gboolean ok;
2745 
2746     gst_byte_writer_init_with_size (&bw, gst_buffer_get_size (buffer), FALSE);
2747     ok = gst_byte_writer_put_buffer (&bw, buffer, 0, h265parse->idr_pos);
2748     GST_DEBUG_OBJECT (h265parse, "- inserting VPS/SPS/PPS");
2749     for (i = 0; i < GST_H265_MAX_VPS_COUNT; i++) {
2750       if ((codec_nal = h265parse->vps_nals[i])) {
2751         gsize nal_size = gst_buffer_get_size (codec_nal);
2752         GST_DEBUG_OBJECT (h265parse, "inserting VPS nal");
2753         if (bs) {
2754           ok &= gst_byte_writer_put_uint32_be (&bw, 1);
2755         } else {
2756           ok &= gst_byte_writer_put_uint32_be (&bw, (nal_size << (nls * 8)));
2757           ok &= gst_byte_writer_set_pos (&bw,
2758               gst_byte_writer_get_pos (&bw) - nls);
2759         }
2760 
2761         ok &= gst_byte_writer_put_buffer (&bw, codec_nal, 0, nal_size);
2762         send_done = TRUE;
2763       }
2764     }
2765     for (i = 0; i < GST_H265_MAX_SPS_COUNT; i++) {
2766       if ((codec_nal = h265parse->sps_nals[i])) {
2767         gsize nal_size = gst_buffer_get_size (codec_nal);
2768         GST_DEBUG_OBJECT (h265parse, "inserting SPS nal");
2769         if (bs) {
2770           ok &= gst_byte_writer_put_uint32_be (&bw, 1);
2771         } else {
2772           ok &= gst_byte_writer_put_uint32_be (&bw, (nal_size << (nls * 8)));
2773           ok &= gst_byte_writer_set_pos (&bw,
2774               gst_byte_writer_get_pos (&bw) - nls);
2775         }
2776 
2777         ok &= gst_byte_writer_put_buffer (&bw, codec_nal, 0, nal_size);
2778         send_done = TRUE;
2779       }
2780     }
2781     for (i = 0; i < GST_H265_MAX_PPS_COUNT; i++) {
2782       if ((codec_nal = h265parse->pps_nals[i])) {
2783         gsize nal_size = gst_buffer_get_size (codec_nal);
2784         GST_DEBUG_OBJECT (h265parse, "inserting PPS nal");
2785         if (bs) {
2786           ok &= gst_byte_writer_put_uint32_be (&bw, 1);
2787         } else {
2788           ok &= gst_byte_writer_put_uint32_be (&bw, (nal_size << (nls * 8)));
2789           ok &= gst_byte_writer_set_pos (&bw,
2790               gst_byte_writer_get_pos (&bw) - nls);
2791         }
2792         ok &= gst_byte_writer_put_buffer (&bw, codec_nal, 0, nal_size);
2793         send_done = TRUE;
2794       }
2795     }
2796     ok &= gst_byte_writer_put_buffer (&bw, buffer, h265parse->idr_pos, -1);
2797     /* collect result and push */
2798     new_buf = gst_byte_writer_reset_and_get_buffer (&bw);
2799     gst_buffer_copy_into (new_buf, buffer, GST_BUFFER_COPY_METADATA, 0, -1);
2800     /* should already be keyframe/IDR, but it may not have been,
2801      * so mark it as such to avoid being discarded by picky decoder */
2802     GST_BUFFER_FLAG_UNSET (new_buf, GST_BUFFER_FLAG_DELTA_UNIT);
2803     gst_buffer_replace (&frame->out_buffer, new_buf);
2804     gst_buffer_unref (new_buf);
2805     /* some result checking seems to make some compilers happy */
2806     if (G_UNLIKELY (!ok)) {
2807       GST_ERROR_OBJECT (h265parse, "failed to insert SPS/PPS");
2808     }
2809   }
2810 
2811   return send_done;
2812 }
2813 
2814 static GstFlowReturn
gst_h265_parse_pre_push_frame(GstBaseParse * parse,GstBaseParseFrame * frame)2815 gst_h265_parse_pre_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
2816 {
2817   GstH265Parse *h265parse;
2818   GstBuffer *buffer;
2819   GstEvent *event;
2820   GstBuffer *parse_buffer = NULL;
2821 
2822   h265parse = GST_H265_PARSE (parse);
2823 
2824   if (h265parse->first_frame) {
2825     GstTagList *taglist;
2826     GstCaps *caps;
2827 
2828     /* codec tag */
2829     caps = gst_pad_get_current_caps (GST_BASE_PARSE_SRC_PAD (parse));
2830     if (G_UNLIKELY (caps == NULL)) {
2831       if (GST_PAD_IS_FLUSHING (GST_BASE_PARSE_SRC_PAD (parse))) {
2832         GST_INFO_OBJECT (parse, "Src pad is flushing");
2833         return GST_FLOW_FLUSHING;
2834       } else {
2835         GST_INFO_OBJECT (parse, "Src pad is not negotiated!");
2836         return GST_FLOW_NOT_NEGOTIATED;
2837       }
2838     }
2839 
2840     taglist = gst_tag_list_new_empty ();
2841     gst_pb_utils_add_codec_description_to_tag_list (taglist,
2842         GST_TAG_VIDEO_CODEC, caps);
2843     gst_caps_unref (caps);
2844 
2845     gst_base_parse_merge_tags (parse, taglist, GST_TAG_MERGE_REPLACE);
2846     gst_tag_list_unref (taglist);
2847 
2848     /* also signals the end of first-frame processing */
2849     h265parse->first_frame = FALSE;
2850   }
2851 
2852   buffer = frame->buffer;
2853 
2854   if ((event = check_pending_key_unit_event (h265parse->force_key_unit_event,
2855               &parse->segment, GST_BUFFER_TIMESTAMP (buffer),
2856               GST_BUFFER_FLAGS (buffer), h265parse->pending_key_unit_ts))) {
2857     gst_h265_parse_prepare_key_unit (h265parse, event);
2858   }
2859 
2860   /* periodic VPS/SPS/PPS sending */
2861   if (h265parse->interval > 0 || h265parse->push_codec) {
2862     GstClockTime timestamp = GST_BUFFER_TIMESTAMP (buffer);
2863     guint64 diff;
2864     gboolean initial_frame = FALSE;
2865 
2866     /* init */
2867     if (!GST_CLOCK_TIME_IS_VALID (h265parse->last_report)) {
2868       h265parse->last_report = timestamp;
2869       initial_frame = TRUE;
2870     }
2871 
2872     if (h265parse->idr_pos >= 0) {
2873       GST_LOG_OBJECT (h265parse, "IDR nal at offset %d", h265parse->idr_pos);
2874 
2875       if (timestamp > h265parse->last_report)
2876         diff = timestamp - h265parse->last_report;
2877       else
2878         diff = 0;
2879 
2880       GST_LOG_OBJECT (h265parse,
2881           "now %" GST_TIME_FORMAT ", last VPS/SPS/PPS %" GST_TIME_FORMAT,
2882           GST_TIME_ARGS (timestamp), GST_TIME_ARGS (h265parse->last_report));
2883 
2884       GST_DEBUG_OBJECT (h265parse,
2885           "interval since last VPS/SPS/PPS %" GST_TIME_FORMAT,
2886           GST_TIME_ARGS (diff));
2887 
2888       if (GST_TIME_AS_SECONDS (diff) >= h265parse->interval ||
2889           initial_frame || h265parse->push_codec) {
2890         GstClockTime new_ts;
2891 
2892         /* avoid overwriting a perfectly fine timestamp */
2893         new_ts = GST_CLOCK_TIME_IS_VALID (timestamp) ? timestamp :
2894             h265parse->last_report;
2895 
2896         if (gst_h265_parse_handle_vps_sps_pps_nals (h265parse, buffer, frame)) {
2897           h265parse->last_report = new_ts;
2898         }
2899       }
2900 
2901       /* we pushed whatever we had */
2902       h265parse->push_codec = FALSE;
2903       h265parse->have_vps = FALSE;
2904       h265parse->have_sps = FALSE;
2905       h265parse->have_pps = FALSE;
2906       h265parse->state &= GST_H265_PARSE_STATE_VALID_PICTURE_HEADERS;
2907     }
2908   } else if (h265parse->interval == -1) {
2909     if (h265parse->idr_pos >= 0) {
2910       GST_LOG_OBJECT (h265parse, "IDR nal at offset %d", h265parse->idr_pos);
2911 
2912       gst_h265_parse_handle_vps_sps_pps_nals (h265parse, buffer, frame);
2913 
2914       /* we pushed whatever we had */
2915       h265parse->push_codec = FALSE;
2916       h265parse->have_vps = FALSE;
2917       h265parse->have_sps = FALSE;
2918       h265parse->have_pps = FALSE;
2919       h265parse->state &= GST_H265_PARSE_STATE_VALID_PICTURE_HEADERS;
2920     }
2921   }
2922 
2923   if (frame->out_buffer) {
2924     parse_buffer = frame->out_buffer =
2925         gst_buffer_make_writable (frame->out_buffer);
2926   } else {
2927     parse_buffer = frame->buffer = gst_buffer_make_writable (frame->buffer);
2928   }
2929 
2930   /* see section D.3.3 of the spec */
2931   switch (h265parse->sei_pic_struct) {
2932     case GST_H265_SEI_PIC_STRUCT_TOP_BOTTOM:
2933     case GST_H265_SEI_PIC_STRUCT_BOTTOM_TOP:
2934     case GST_H265_SEI_PIC_STRUCT_TOP_BOTTOM_TOP:
2935     case GST_H265_SEI_PIC_STRUCT_BOTTOM_TOP_BOTTOM:
2936       GST_BUFFER_FLAG_SET (parse_buffer, GST_VIDEO_BUFFER_FLAG_INTERLACED);
2937       break;
2938     case GST_H265_SEI_PIC_STRUCT_TOP_FIELD:
2939     case GST_H265_SEI_PIC_STRUCT_TOP_PAIRED_NEXT_BOTTOM:
2940     case GST_H265_SEI_PIC_STRUCT_TOP_PAIRED_PREVIOUS_BOTTOM:
2941       GST_BUFFER_FLAG_SET (parse_buffer, GST_VIDEO_BUFFER_FLAG_INTERLACED);
2942       GST_BUFFER_FLAG_SET (parse_buffer, GST_VIDEO_BUFFER_FLAG_TOP_FIELD);
2943       break;
2944     case GST_H265_SEI_PIC_STRUCT_BOTTOM_FIELD:
2945     case GST_H265_SEI_PIC_STRUCT_BOTTOM_PAIRED_PREVIOUS_TOP:
2946     case GST_H265_SEI_PIC_STRUCT_BOTTOM_PAIRED_NEXT_TOP:
2947       GST_BUFFER_FLAG_SET (parse_buffer, GST_VIDEO_BUFFER_FLAG_INTERLACED);
2948       GST_BUFFER_FLAG_SET (parse_buffer, GST_VIDEO_BUFFER_FLAG_BOTTOM_FIELD);
2949       break;
2950     default:
2951       break;
2952   }
2953 
2954   {
2955     guint i = 0;
2956 
2957     for (i = 0; i < h265parse->time_code.num_clock_ts; i++) {
2958       gint field_count = -1;
2959       guint n_frames;
2960       GstVideoTimeCodeFlags flags = 0;
2961 
2962       if (!h265parse->time_code.clock_timestamp_flag[i])
2963         break;
2964 
2965       h265parse->time_code.clock_timestamp_flag[i] = 0;
2966 
2967       /* Table D.2 */
2968       switch (h265parse->sei_pic_struct) {
2969         case GST_H265_SEI_PIC_STRUCT_FRAME:
2970         case GST_H265_SEI_PIC_STRUCT_TOP_FIELD:
2971         case GST_H265_SEI_PIC_STRUCT_BOTTOM_FIELD:
2972           field_count = h265parse->sei_pic_struct;
2973           break;
2974         case GST_H265_SEI_PIC_STRUCT_TOP_BOTTOM:
2975         case GST_H265_SEI_PIC_STRUCT_TOP_PAIRED_PREVIOUS_BOTTOM:
2976         case GST_H265_SEI_PIC_STRUCT_TOP_PAIRED_NEXT_BOTTOM:
2977           field_count = i + 1;
2978           break;
2979         case GST_H265_SEI_PIC_STRUCT_BOTTOM_TOP:
2980         case GST_H265_SEI_PIC_STRUCT_BOTTOM_PAIRED_PREVIOUS_TOP:
2981         case GST_H265_SEI_PIC_STRUCT_BOTTOM_PAIRED_NEXT_TOP:
2982           field_count = 2 - i;
2983           break;
2984         case GST_H265_SEI_PIC_STRUCT_TOP_BOTTOM_TOP:
2985           field_count = i % 2 ? 2 : 1;
2986           break;
2987         case GST_H265_SEI_PIC_STRUCT_BOTTOM_TOP_BOTTOM:
2988           field_count = i % 2 ? 1 : 2;
2989           break;
2990         case GST_H265_SEI_PIC_STRUCT_FRAME_DOUBLING:
2991         case GST_H265_SEI_PIC_STRUCT_FRAME_TRIPLING:
2992           field_count = 0;
2993           break;
2994       }
2995 
2996       if (field_count == -1) {
2997         GST_WARNING_OBJECT (parse,
2998             "failed to determine field count for timecode");
2999         field_count = 0;
3000       }
3001 
3002       /* Dropping of the two lowest (value 0 and 1) n_frames[ i ] counts when
3003        * seconds_value[ i ] is equal to 0 and minutes_value[ i ] is not an integer
3004        * multiple of 10 */
3005       if (h265parse->time_code.counting_type[i] == 4)
3006         flags |= GST_VIDEO_TIME_CODE_FLAGS_DROP_FRAME;
3007 
3008       if (h265parse->sei_pic_struct != GST_H265_SEI_PIC_STRUCT_FRAME)
3009         flags |= GST_VIDEO_TIME_CODE_FLAGS_INTERLACED;
3010 
3011       n_frames =
3012           gst_util_uint64_scale_int (h265parse->time_code.n_frames[i], 1,
3013           2 - h265parse->time_code.units_field_based_flag[i]);
3014 
3015       gst_buffer_add_video_time_code_meta_full (parse_buffer,
3016           h265parse->parsed_fps_n,
3017           h265parse->parsed_fps_d,
3018           NULL,
3019           flags,
3020           h265parse->time_code.hours_flag[i] ? h265parse->time_code.
3021           hours_value[i] : 0,
3022           h265parse->time_code.minutes_flag[i] ? h265parse->time_code.
3023           minutes_value[i] : 0,
3024           h265parse->time_code.seconds_flag[i] ? h265parse->time_code.
3025           seconds_value[i] : 0, n_frames, field_count);
3026     }
3027   }
3028 
3029   gst_video_push_user_data ((GstElement *) h265parse, &h265parse->user_data,
3030       parse_buffer);
3031 
3032   gst_h265_parse_reset_frame (h265parse);
3033 
3034   return GST_FLOW_OK;
3035 }
3036 
3037 static gboolean
gst_h265_parse_set_caps(GstBaseParse * parse,GstCaps * caps)3038 gst_h265_parse_set_caps (GstBaseParse * parse, GstCaps * caps)
3039 {
3040   GstH265Parse *h265parse;
3041   GstStructure *str;
3042   const GValue *value;
3043   GstBuffer *codec_data = NULL;
3044   gsize off, size;
3045   guint format, align;
3046   guint num_nals, i, j;
3047   GstH265NalUnit nalu;
3048   GstH265ParserResult parseres;
3049   GstCaps *old_caps;
3050 
3051   h265parse = GST_H265_PARSE (parse);
3052 
3053   /* reset */
3054   h265parse->push_codec = FALSE;
3055 
3056   old_caps = gst_pad_get_current_caps (GST_BASE_PARSE_SINK_PAD (parse));
3057   if (old_caps) {
3058     if (!gst_caps_is_equal (old_caps, caps))
3059       gst_h265_parse_reset_stream_info (h265parse);
3060     gst_caps_unref (old_caps);
3061   }
3062 
3063   str = gst_caps_get_structure (caps, 0);
3064 
3065   /* accept upstream info if provided */
3066   gst_structure_get_int (str, "width", &h265parse->width);
3067   gst_structure_get_int (str, "height", &h265parse->height);
3068   gst_structure_get_fraction (str, "framerate", &h265parse->fps_num,
3069       &h265parse->fps_den);
3070   gst_structure_get_fraction (str, "pixel-aspect-ratio",
3071       &h265parse->upstream_par_n, &h265parse->upstream_par_d);
3072 
3073   /* get upstream format and align from caps */
3074   gst_h265_parse_format_from_caps (caps, &format, &align);
3075 
3076   /* packetized video has a codec_data */
3077   if (format != GST_H265_PARSE_FORMAT_BYTE &&
3078       (value = gst_structure_get_value (str, "codec_data"))) {
3079     GstMapInfo map;
3080     guint8 *data;
3081     guint num_nal_arrays;
3082 
3083     GST_DEBUG_OBJECT (h265parse, "have packetized h265");
3084     /* make note for optional split processing */
3085     h265parse->packetized = TRUE;
3086 
3087     codec_data = gst_value_get_buffer (value);
3088     if (!codec_data)
3089       goto wrong_type;
3090     gst_buffer_map (codec_data, &map, GST_MAP_READ);
3091     data = map.data;
3092     size = map.size;
3093 
3094     /* parse the hvcC data */
3095     if (size < 23) {
3096       gst_buffer_unmap (codec_data, &map);
3097       goto hvcc_too_small;
3098     }
3099     /* parse the version, this must be one but
3100      * is zero until the spec is finalized */
3101     if (data[0] != 0 && data[0] != 1) {
3102       gst_buffer_unmap (codec_data, &map);
3103       goto wrong_version;
3104     }
3105 
3106     h265parse->nal_length_size = (data[21] & 0x03) + 1;
3107     GST_DEBUG_OBJECT (h265parse, "nal length size %u",
3108         h265parse->nal_length_size);
3109 
3110     num_nal_arrays = data[22];
3111     off = 23;
3112 
3113     for (i = 0; i < num_nal_arrays; i++) {
3114       if (off + 3 >= size) {
3115         gst_buffer_unmap (codec_data, &map);
3116         goto hvcc_too_small;
3117       }
3118 
3119       num_nals = GST_READ_UINT16_BE (data + off + 1);
3120       off += 3;
3121       for (j = 0; j < num_nals; j++) {
3122         parseres = gst_h265_parser_identify_nalu_hevc (h265parse->nalparser,
3123             data, off, size, 2, &nalu);
3124 
3125         if (parseres != GST_H265_PARSER_OK) {
3126           gst_buffer_unmap (codec_data, &map);
3127           goto hvcc_too_small;
3128         }
3129 
3130         gst_h265_parse_process_nal (h265parse, &nalu);
3131         off = nalu.offset + nalu.size;
3132       }
3133     }
3134     gst_buffer_unmap (codec_data, &map);
3135 
3136     /* don't confuse codec_data with inband vps/sps/pps */
3137     h265parse->have_vps_in_frame = FALSE;
3138     h265parse->have_sps_in_frame = FALSE;
3139     h265parse->have_pps_in_frame = FALSE;
3140   } else {
3141     GST_DEBUG_OBJECT (h265parse, "have bytestream h265");
3142     /* nothing to pre-process */
3143     h265parse->packetized = FALSE;
3144     /* we have 4 sync bytes */
3145     h265parse->nal_length_size = 4;
3146 
3147     if (format == GST_H265_PARSE_FORMAT_NONE) {
3148       format = GST_H265_PARSE_FORMAT_BYTE;
3149       align = GST_H265_PARSE_ALIGN_AU;
3150     }
3151   }
3152 
3153   {
3154     GstCaps *in_caps;
3155 
3156     /* prefer input type determined above */
3157     in_caps = gst_caps_new_simple ("video/x-h265",
3158         "parsed", G_TYPE_BOOLEAN, TRUE,
3159         "stream-format", G_TYPE_STRING,
3160         gst_h265_parse_get_string (h265parse, TRUE, format),
3161         "alignment", G_TYPE_STRING,
3162         gst_h265_parse_get_string (h265parse, FALSE, align), NULL);
3163     /* negotiate with downstream, sets ->format and ->align */
3164     gst_h265_parse_negotiate (h265parse, format, in_caps);
3165     gst_caps_unref (in_caps);
3166   }
3167 
3168   if (format == h265parse->format && align == h265parse->align) {
3169     /* do not set CAPS and passthrough mode if SPS/PPS have not been parsed */
3170     if (h265parse->have_sps && h265parse->have_pps) {
3171       /* Don't enable passthrough here. This element will parse various
3172        * SEI messages which would be very important/useful for downstream
3173        * (HDR, timecode for example)
3174        */
3175 #if 0
3176       gst_base_parse_set_passthrough (parse, TRUE);
3177 #endif
3178 
3179       /* we did parse codec-data and might supplement src caps */
3180       gst_h265_parse_update_src_caps (h265parse, caps);
3181     }
3182   } else if (format == GST_H265_PARSE_FORMAT_HVC1
3183       || format == GST_H265_PARSE_FORMAT_HEV1) {
3184     /* if input != output, and input is hevc, must split before anything else */
3185     /* arrange to insert codec-data in-stream if needed.
3186      * src caps are only arranged for later on */
3187     h265parse->push_codec = TRUE;
3188     h265parse->have_vps = FALSE;
3189     h265parse->have_sps = FALSE;
3190     h265parse->have_pps = FALSE;
3191     if (h265parse->align == GST_H265_PARSE_ALIGN_NAL)
3192       h265parse->split_packetized = TRUE;
3193     h265parse->packetized = TRUE;
3194   }
3195 
3196   h265parse->in_align = align;
3197 
3198   return TRUE;
3199 
3200   /* ERRORS */
3201 hvcc_too_small:
3202   {
3203     GST_DEBUG_OBJECT (h265parse, "hvcC size %" G_GSIZE_FORMAT " < 23", size);
3204     goto refuse_caps;
3205   }
3206 wrong_version:
3207   {
3208     GST_DEBUG_OBJECT (h265parse, "wrong hvcC version");
3209     goto refuse_caps;
3210   }
3211 wrong_type:
3212   {
3213     GST_DEBUG_OBJECT (h265parse, "wrong codec-data type");
3214     goto refuse_caps;
3215   }
3216 refuse_caps:
3217   {
3218     GST_WARNING_OBJECT (h265parse, "refused caps %" GST_PTR_FORMAT, caps);
3219     return FALSE;
3220   }
3221 }
3222 
3223 static void
remove_fields(GstCaps * caps,gboolean all)3224 remove_fields (GstCaps * caps, gboolean all)
3225 {
3226   guint i, n;
3227 
3228   n = gst_caps_get_size (caps);
3229   for (i = 0; i < n; i++) {
3230     GstStructure *s = gst_caps_get_structure (caps, i);
3231 
3232     if (all) {
3233       gst_structure_remove_field (s, "alignment");
3234       gst_structure_remove_field (s, "stream-format");
3235     }
3236     gst_structure_remove_field (s, "parsed");
3237   }
3238 }
3239 
3240 static GstCaps *
gst_h265_parse_get_caps(GstBaseParse * parse,GstCaps * filter)3241 gst_h265_parse_get_caps (GstBaseParse * parse, GstCaps * filter)
3242 {
3243   GstCaps *peercaps, *templ;
3244   GstCaps *res, *tmp, *pcopy;
3245 
3246   templ = gst_pad_get_pad_template_caps (GST_BASE_PARSE_SINK_PAD (parse));
3247   if (filter) {
3248     GstCaps *fcopy = gst_caps_copy (filter);
3249     /* Remove the fields we convert */
3250     remove_fields (fcopy, TRUE);
3251     peercaps = gst_pad_peer_query_caps (GST_BASE_PARSE_SRC_PAD (parse), fcopy);
3252     gst_caps_unref (fcopy);
3253   } else
3254     peercaps = gst_pad_peer_query_caps (GST_BASE_PARSE_SRC_PAD (parse), NULL);
3255 
3256   pcopy = gst_caps_copy (peercaps);
3257   remove_fields (pcopy, TRUE);
3258 
3259   res = gst_caps_intersect_full (pcopy, templ, GST_CAPS_INTERSECT_FIRST);
3260   gst_caps_unref (pcopy);
3261   gst_caps_unref (templ);
3262 
3263   if (filter) {
3264     GstCaps *tmp = gst_caps_intersect_full (res, filter,
3265         GST_CAPS_INTERSECT_FIRST);
3266     gst_caps_unref (res);
3267     res = tmp;
3268   }
3269 
3270   /* Try if we can put the downstream caps first */
3271   pcopy = gst_caps_copy (peercaps);
3272   remove_fields (pcopy, FALSE);
3273   tmp = gst_caps_intersect_full (pcopy, res, GST_CAPS_INTERSECT_FIRST);
3274   gst_caps_unref (pcopy);
3275   if (!gst_caps_is_empty (tmp))
3276     res = gst_caps_merge (tmp, res);
3277   else
3278     gst_caps_unref (tmp);
3279 
3280   gst_caps_unref (peercaps);
3281   return res;
3282 }
3283 
3284 static gboolean
gst_h265_parse_event(GstBaseParse * parse,GstEvent * event)3285 gst_h265_parse_event (GstBaseParse * parse, GstEvent * event)
3286 {
3287   gboolean res;
3288   GstH265Parse *h265parse = GST_H265_PARSE (parse);
3289 
3290   switch (GST_EVENT_TYPE (event)) {
3291     case GST_EVENT_CUSTOM_DOWNSTREAM:
3292     {
3293       GstClockTime timestamp, stream_time, running_time;
3294       gboolean all_headers;
3295       guint count;
3296 
3297       if (gst_video_event_is_force_key_unit (event)) {
3298         gst_video_event_parse_downstream_force_key_unit (event,
3299             &timestamp, &stream_time, &running_time, &all_headers, &count);
3300 
3301         GST_INFO_OBJECT (h265parse, "received downstream force key unit event, "
3302             "seqnum %d running_time %" GST_TIME_FORMAT
3303             " all_headers %d count %d", gst_event_get_seqnum (event),
3304             GST_TIME_ARGS (running_time), all_headers, count);
3305         if (h265parse->force_key_unit_event) {
3306           GST_INFO_OBJECT (h265parse, "ignoring force key unit event "
3307               "as one is already queued");
3308         } else {
3309           h265parse->pending_key_unit_ts = running_time;
3310           gst_event_replace (&h265parse->force_key_unit_event, event);
3311         }
3312         gst_event_unref (event);
3313         res = TRUE;
3314       } else {
3315         res = GST_BASE_PARSE_CLASS (parent_class)->sink_event (parse, event);
3316         break;
3317       }
3318       break;
3319     }
3320     case GST_EVENT_FLUSH_STOP:
3321     case GST_EVENT_SEGMENT_DONE:
3322       h265parse->push_codec = TRUE;
3323       res = GST_BASE_PARSE_CLASS (parent_class)->sink_event (parse, event);
3324       break;
3325     case GST_EVENT_SEGMENT:
3326     {
3327       const GstSegment *segment = NULL;
3328 
3329       gst_event_parse_segment (event, &segment);
3330 
3331       h265parse->last_report = GST_CLOCK_TIME_NONE;
3332 
3333       if (segment->flags & GST_SEEK_FLAG_TRICKMODE_FORWARD_PREDICTED) {
3334         GST_DEBUG_OBJECT (h265parse, "Will discard bidirectional frames");
3335         h265parse->discard_bidirectional = TRUE;
3336       }
3337 
3338       res = GST_BASE_PARSE_CLASS (parent_class)->sink_event (parse, event);
3339       break;
3340     }
3341     default:
3342       res = GST_BASE_PARSE_CLASS (parent_class)->sink_event (parse, event);
3343       break;
3344   }
3345   return res;
3346 }
3347 
3348 static gboolean
gst_h265_parse_src_event(GstBaseParse * parse,GstEvent * event)3349 gst_h265_parse_src_event (GstBaseParse * parse, GstEvent * event)
3350 {
3351   gboolean res;
3352   GstH265Parse *h265parse = GST_H265_PARSE (parse);
3353 
3354   switch (GST_EVENT_TYPE (event)) {
3355     case GST_EVENT_CUSTOM_UPSTREAM:
3356     {
3357       GstClockTime running_time;
3358       gboolean all_headers;
3359       guint count;
3360 
3361       if (gst_video_event_is_force_key_unit (event)) {
3362         gst_video_event_parse_upstream_force_key_unit (event,
3363             &running_time, &all_headers, &count);
3364 
3365         GST_INFO_OBJECT (h265parse, "received upstream force-key-unit event, "
3366             "seqnum %d running_time %" GST_TIME_FORMAT
3367             " all_headers %d count %d", gst_event_get_seqnum (event),
3368             GST_TIME_ARGS (running_time), all_headers, count);
3369 
3370         if (all_headers) {
3371           h265parse->pending_key_unit_ts = running_time;
3372           gst_event_replace (&h265parse->force_key_unit_event, event);
3373         }
3374       }
3375       res = GST_BASE_PARSE_CLASS (parent_class)->src_event (parse, event);
3376       break;
3377     }
3378     default:
3379       res = GST_BASE_PARSE_CLASS (parent_class)->src_event (parse, event);
3380       break;
3381   }
3382 
3383   return res;
3384 }
3385 
3386 static void
gst_h265_parse_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)3387 gst_h265_parse_set_property (GObject * object, guint prop_id,
3388     const GValue * value, GParamSpec * pspec)
3389 {
3390   GstH265Parse *parse;
3391   parse = GST_H265_PARSE (object);
3392 
3393   switch (prop_id) {
3394     case PROP_CONFIG_INTERVAL:
3395       parse->interval = g_value_get_int (value);
3396       break;
3397     default:
3398       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
3399       break;
3400   }
3401 }
3402 
3403 static void
gst_h265_parse_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)3404 gst_h265_parse_get_property (GObject * object, guint prop_id, GValue * value,
3405     GParamSpec * pspec)
3406 {
3407   GstH265Parse *parse;
3408   parse = GST_H265_PARSE (object);
3409 
3410   switch (prop_id) {
3411     case PROP_CONFIG_INTERVAL:
3412       g_value_set_int (value, parse->interval);
3413       break;
3414     default:
3415       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
3416       break;
3417   }
3418 }
3419