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 <gst/video/video.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 #define GST_H265_PARSE_STATE_VALID(parse, expected_state) \
72   (((parse)->state & (expected_state)) == (expected_state))
73 
74 static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
75     GST_PAD_SINK,
76     GST_PAD_ALWAYS,
77     GST_STATIC_CAPS ("video/x-h265"));
78 
79 static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
80     GST_PAD_SRC,
81     GST_PAD_ALWAYS,
82     GST_STATIC_CAPS ("video/x-h265, parsed = (boolean) true, "
83         "stream-format=(string) { hvc1, hev1, byte-stream }, "
84         "alignment=(string) { au, nal }"));
85 
86 #define parent_class gst_h265_parse_parent_class
87 G_DEFINE_TYPE (GstH265Parse, gst_h265_parse, GST_TYPE_BASE_PARSE);
88 
89 static void gst_h265_parse_finalize (GObject * object);
90 
91 static gboolean gst_h265_parse_start (GstBaseParse * parse);
92 static gboolean gst_h265_parse_stop (GstBaseParse * parse);
93 static GstFlowReturn gst_h265_parse_handle_frame (GstBaseParse * parse,
94     GstBaseParseFrame * frame, gint * skipsize);
95 static GstFlowReturn gst_h265_parse_parse_frame (GstBaseParse * parse,
96     GstBaseParseFrame * frame);
97 static GstFlowReturn gst_h265_parse_pre_push_frame (GstBaseParse * parse,
98     GstBaseParseFrame * frame);
99 
100 static void gst_h265_parse_set_property (GObject * object, guint prop_id,
101     const GValue * value, GParamSpec * pspec);
102 static void gst_h265_parse_get_property (GObject * object, guint prop_id,
103     GValue * value, GParamSpec * pspec);
104 
105 static gboolean gst_h265_parse_set_caps (GstBaseParse * parse, GstCaps * caps);
106 static GstCaps *gst_h265_parse_get_caps (GstBaseParse * parse,
107     GstCaps * filter);
108 static gboolean gst_h265_parse_event (GstBaseParse * parse, GstEvent * event);
109 static gboolean gst_h265_parse_src_event (GstBaseParse * parse,
110     GstEvent * event);
111 
112 static void
gst_h265_parse_class_init(GstH265ParseClass * klass)113 gst_h265_parse_class_init (GstH265ParseClass * klass)
114 {
115   GObjectClass *gobject_class = (GObjectClass *) klass;
116   GstBaseParseClass *parse_class = GST_BASE_PARSE_CLASS (klass);
117   GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
118 
119   GST_DEBUG_CATEGORY_INIT (h265_parse_debug, "h265parse", 0, "h265 parser");
120 
121   gobject_class->finalize = gst_h265_parse_finalize;
122   gobject_class->set_property = gst_h265_parse_set_property;
123   gobject_class->get_property = gst_h265_parse_get_property;
124 
125   g_object_class_install_property (gobject_class, PROP_CONFIG_INTERVAL,
126       g_param_spec_int ("config-interval",
127           "VPS SPS PPS Send Interval",
128           "Send VPS, SPS and PPS Insertion Interval in seconds (sprop parameter sets "
129           "will be multiplexed in the data stream when detected.) "
130           "(0 = disabled, -1 = send with every IDR frame)",
131           -1, 3600, DEFAULT_CONFIG_INTERVAL,
132           G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
133   /* Override BaseParse vfuncs */
134   parse_class->start = GST_DEBUG_FUNCPTR (gst_h265_parse_start);
135   parse_class->stop = GST_DEBUG_FUNCPTR (gst_h265_parse_stop);
136   parse_class->handle_frame = GST_DEBUG_FUNCPTR (gst_h265_parse_handle_frame);
137   parse_class->pre_push_frame =
138       GST_DEBUG_FUNCPTR (gst_h265_parse_pre_push_frame);
139   parse_class->set_sink_caps = GST_DEBUG_FUNCPTR (gst_h265_parse_set_caps);
140   parse_class->get_sink_caps = GST_DEBUG_FUNCPTR (gst_h265_parse_get_caps);
141   parse_class->sink_event = GST_DEBUG_FUNCPTR (gst_h265_parse_event);
142   parse_class->src_event = GST_DEBUG_FUNCPTR (gst_h265_parse_src_event);
143 
144   gst_element_class_add_static_pad_template (gstelement_class, &srctemplate);
145   gst_element_class_add_static_pad_template (gstelement_class, &sinktemplate);
146 
147   gst_element_class_set_static_metadata (gstelement_class, "H.265 parser",
148       "Codec/Parser/Converter/Video",
149       "Parses H.265 streams",
150       "Sreerenj Balachandran <sreerenj.balachandran@intel.com>");
151 }
152 
153 static void
gst_h265_parse_init(GstH265Parse * h265parse)154 gst_h265_parse_init (GstH265Parse * h265parse)
155 {
156   h265parse->frame_out = gst_adapter_new ();
157   gst_base_parse_set_pts_interpolation (GST_BASE_PARSE (h265parse), FALSE);
158   GST_PAD_SET_ACCEPT_INTERSECT (GST_BASE_PARSE_SINK_PAD (h265parse));
159   GST_PAD_SET_ACCEPT_TEMPLATE (GST_BASE_PARSE_SINK_PAD (h265parse));
160 }
161 
162 
163 static void
gst_h265_parse_finalize(GObject * object)164 gst_h265_parse_finalize (GObject * object)
165 {
166   GstH265Parse *h265parse = GST_H265_PARSE (object);
167 
168   g_object_unref (h265parse->frame_out);
169 
170   G_OBJECT_CLASS (parent_class)->finalize (object);
171 }
172 
173 static void
gst_h265_parse_reset_frame(GstH265Parse * h265parse)174 gst_h265_parse_reset_frame (GstH265Parse * h265parse)
175 {
176   GST_DEBUG_OBJECT (h265parse, "reset frame");
177 
178   /* done parsing; reset state */
179   h265parse->current_off = -1;
180 
181   h265parse->picture_start = FALSE;
182   h265parse->update_caps = FALSE;
183   h265parse->idr_pos = -1;
184   h265parse->sei_pos = -1;
185   h265parse->keyframe = FALSE;
186   h265parse->header = FALSE;
187   h265parse->have_vps_in_frame = FALSE;
188   h265parse->have_sps_in_frame = FALSE;
189   h265parse->have_pps_in_frame = FALSE;
190   gst_adapter_clear (h265parse->frame_out);
191 }
192 
193 static void
gst_h265_parse_reset_stream_info(GstH265Parse * h265parse)194 gst_h265_parse_reset_stream_info (GstH265Parse * h265parse)
195 {
196   gint i;
197 
198   h265parse->width = 0;
199   h265parse->height = 0;
200   h265parse->fps_num = 0;
201   h265parse->fps_den = 0;
202   h265parse->upstream_par_n = -1;
203   h265parse->upstream_par_d = -1;
204   h265parse->parsed_par_n = 0;
205   h265parse->parsed_par_n = 0;
206   h265parse->have_pps = FALSE;
207   h265parse->have_sps = FALSE;
208   h265parse->have_vps = FALSE;
209 
210   h265parse->align = GST_H265_PARSE_ALIGN_NONE;
211   h265parse->format = GST_H265_PARSE_FORMAT_NONE;
212 
213   h265parse->transform = FALSE;
214   h265parse->nal_length_size = 4;
215   h265parse->packetized = FALSE;
216   h265parse->push_codec = FALSE;
217 
218   gst_buffer_replace (&h265parse->codec_data, NULL);
219   gst_buffer_replace (&h265parse->codec_data_in, NULL);
220 
221   gst_h265_parse_reset_frame (h265parse);
222 
223   for (i = 0; i < GST_H265_MAX_VPS_COUNT; i++)
224     gst_buffer_replace (&h265parse->vps_nals[i], NULL);
225   for (i = 0; i < GST_H265_MAX_SPS_COUNT; i++)
226     gst_buffer_replace (&h265parse->sps_nals[i], NULL);
227   for (i = 0; i < GST_H265_MAX_PPS_COUNT; i++)
228     gst_buffer_replace (&h265parse->pps_nals[i], NULL);
229 }
230 
231 static void
gst_h265_parse_reset(GstH265Parse * h265parse)232 gst_h265_parse_reset (GstH265Parse * h265parse)
233 {
234   h265parse->last_report = GST_CLOCK_TIME_NONE;
235 
236   h265parse->sent_codec_tag = FALSE;
237 
238   h265parse->pending_key_unit_ts = GST_CLOCK_TIME_NONE;
239   gst_event_replace (&h265parse->force_key_unit_event, NULL);
240 
241   h265parse->discont = FALSE;
242 
243   gst_h265_parse_reset_stream_info (h265parse);
244 }
245 
246 static gboolean
gst_h265_parse_start(GstBaseParse * parse)247 gst_h265_parse_start (GstBaseParse * parse)
248 {
249   GstH265Parse *h265parse = GST_H265_PARSE (parse);
250 
251   GST_DEBUG_OBJECT (parse, "start");
252   gst_h265_parse_reset (h265parse);
253 
254   h265parse->nalparser = gst_h265_parser_new ();
255   h265parse->state = 0;
256 
257   gst_base_parse_set_min_frame_size (parse, 7);
258 
259   return TRUE;
260 }
261 
262 static gboolean
gst_h265_parse_stop(GstBaseParse * parse)263 gst_h265_parse_stop (GstBaseParse * parse)
264 {
265   GstH265Parse *h265parse = GST_H265_PARSE (parse);
266 
267   GST_DEBUG_OBJECT (parse, "stop");
268   gst_h265_parse_reset (h265parse);
269 
270   gst_h265_parser_free (h265parse->nalparser);
271 
272   return TRUE;
273 }
274 
275 static const gchar *
gst_h265_parse_get_string(GstH265Parse * parse,gboolean format,gint code)276 gst_h265_parse_get_string (GstH265Parse * parse, gboolean format, gint code)
277 {
278   if (format) {
279     switch (code) {
280       case GST_H265_PARSE_FORMAT_HVC1:
281         return "hvc1";
282       case GST_H265_PARSE_FORMAT_HEV1:
283         return "hev1";
284       case GST_H265_PARSE_FORMAT_BYTE:
285         return "byte-stream";
286       default:
287         return "none";
288     }
289   } else {
290     switch (code) {
291       case GST_H265_PARSE_ALIGN_NAL:
292         return "nal";
293       case GST_H265_PARSE_ALIGN_AU:
294         return "au";
295       default:
296         return "none";
297     }
298   }
299 }
300 
301 static void
gst_h265_parse_format_from_caps(GstCaps * caps,guint * format,guint * align)302 gst_h265_parse_format_from_caps (GstCaps * caps, guint * format, guint * align)
303 {
304   g_return_if_fail (gst_caps_is_fixed (caps));
305 
306   GST_DEBUG ("parsing caps: %" GST_PTR_FORMAT, caps);
307 
308   if (format)
309     *format = GST_H265_PARSE_FORMAT_NONE;
310 
311   if (align)
312     *align = GST_H265_PARSE_ALIGN_NONE;
313 
314   if (caps && gst_caps_get_size (caps) > 0) {
315     GstStructure *s = gst_caps_get_structure (caps, 0);
316     const gchar *str = NULL;
317 
318     if (format) {
319       if ((str = gst_structure_get_string (s, "stream-format"))) {
320         if (strcmp (str, "hvc1") == 0)
321           *format = GST_H265_PARSE_FORMAT_HVC1;
322         else if (strcmp (str, "hev1") == 0)
323           *format = GST_H265_PARSE_FORMAT_HEV1;
324         else if (strcmp (str, "byte-stream") == 0)
325           *format = GST_H265_PARSE_FORMAT_BYTE;
326       }
327     }
328 
329     if (align) {
330       if ((str = gst_structure_get_string (s, "alignment"))) {
331         if (strcmp (str, "au") == 0)
332           *align = GST_H265_PARSE_ALIGN_AU;
333         else if (strcmp (str, "nal") == 0)
334           *align = GST_H265_PARSE_ALIGN_NAL;
335       }
336     }
337   }
338 }
339 
340 /* check downstream caps to configure format and alignment */
341 static void
gst_h265_parse_negotiate(GstH265Parse * h265parse,gint in_format,GstCaps * in_caps)342 gst_h265_parse_negotiate (GstH265Parse * h265parse, gint in_format,
343     GstCaps * in_caps)
344 {
345   GstCaps *caps;
346   guint format = GST_H265_PARSE_FORMAT_NONE;
347   guint align = GST_H265_PARSE_ALIGN_NONE;
348 
349   g_return_if_fail ((in_caps == NULL) || gst_caps_is_fixed (in_caps));
350 
351   caps = gst_pad_get_allowed_caps (GST_BASE_PARSE_SRC_PAD (h265parse));
352   GST_DEBUG_OBJECT (h265parse, "allowed caps: %" GST_PTR_FORMAT, caps);
353 
354   /* concentrate on leading structure, since decodebin parser
355    * capsfilter always includes parser template caps */
356   if (caps) {
357     caps = gst_caps_truncate (caps);
358     GST_DEBUG_OBJECT (h265parse, "negotiating with caps: %" GST_PTR_FORMAT,
359         caps);
360   }
361 
362   if (in_caps && caps) {
363     if (gst_caps_can_intersect (in_caps, caps)) {
364       GST_DEBUG_OBJECT (h265parse, "downstream accepts upstream caps");
365       gst_h265_parse_format_from_caps (in_caps, &format, &align);
366       gst_caps_unref (caps);
367       caps = NULL;
368     }
369   }
370 
371   /* FIXME We could fail the negotiation immediatly if caps are empty */
372   if (caps && !gst_caps_is_empty (caps)) {
373     /* fixate to avoid ambiguity with lists when parsing */
374     caps = gst_caps_fixate (caps);
375     gst_h265_parse_format_from_caps (caps, &format, &align);
376   }
377 
378   /* default */
379   if (!format)
380     format = GST_H265_PARSE_FORMAT_BYTE;
381   if (!align)
382     align = GST_H265_PARSE_ALIGN_AU;
383 
384   GST_DEBUG_OBJECT (h265parse, "selected format %s, alignment %s",
385       gst_h265_parse_get_string (h265parse, TRUE, format),
386       gst_h265_parse_get_string (h265parse, FALSE, align));
387 
388   h265parse->format = format;
389   h265parse->align = align;
390 
391   h265parse->transform = in_format != h265parse->format ||
392       align == GST_H265_PARSE_ALIGN_AU;
393 
394   if (caps)
395     gst_caps_unref (caps);
396 }
397 
398 static GstBuffer *
gst_h265_parse_wrap_nal(GstH265Parse * h265parse,guint format,guint8 * data,guint size)399 gst_h265_parse_wrap_nal (GstH265Parse * h265parse, guint format, guint8 * data,
400     guint size)
401 {
402   GstBuffer *buf;
403   guint nl = h265parse->nal_length_size;
404   guint32 tmp;
405 
406   GST_DEBUG_OBJECT (h265parse, "nal length %d", size);
407 
408   buf = gst_buffer_new_allocate (NULL, 4 + size, NULL);
409   if (format == GST_H265_PARSE_FORMAT_HVC1
410       || format == GST_H265_PARSE_FORMAT_HEV1) {
411     tmp = GUINT32_TO_BE (size << (32 - 8 * nl));
412   } else {
413     /* HACK: nl should always be 4 here, otherwise this won't work.
414      * There are legit cases where nl in hevc stream is 2, but byte-stream
415      * SC is still always 4 bytes. */
416     nl = 4;
417     tmp = GUINT32_TO_BE (1);
418   }
419 
420   gst_buffer_fill (buf, 0, &tmp, sizeof (guint32));
421   gst_buffer_fill (buf, nl, data, size);
422   gst_buffer_set_size (buf, size + nl);
423 
424   return buf;
425 }
426 
427 static void
gst_h265_parser_store_nal(GstH265Parse * h265parse,guint id,GstH265NalUnitType naltype,GstH265NalUnit * nalu)428 gst_h265_parser_store_nal (GstH265Parse * h265parse, guint id,
429     GstH265NalUnitType naltype, GstH265NalUnit * nalu)
430 {
431   GstBuffer *buf, **store;
432   guint size = nalu->size, store_size;
433 
434   if (naltype == GST_H265_NAL_VPS) {
435     store_size = GST_H265_MAX_VPS_COUNT;
436     store = h265parse->vps_nals;
437     GST_DEBUG_OBJECT (h265parse, "storing vps %u", id);
438   } else if (naltype == GST_H265_NAL_SPS) {
439     store_size = GST_H265_MAX_SPS_COUNT;
440     store = h265parse->sps_nals;
441     GST_DEBUG_OBJECT (h265parse, "storing sps %u", id);
442   } else if (naltype == GST_H265_NAL_PPS) {
443     store_size = GST_H265_MAX_PPS_COUNT;
444     store = h265parse->pps_nals;
445     GST_DEBUG_OBJECT (h265parse, "storing pps %u", id);
446   } else
447     return;
448 
449   if (id >= store_size) {
450     GST_DEBUG_OBJECT (h265parse, "unable to store nal, id out-of-range %d", id);
451     return;
452   }
453 
454   buf = gst_buffer_new_allocate (NULL, size, NULL);
455   gst_buffer_fill (buf, 0, nalu->data + nalu->offset, size);
456 
457   /* Indicate that buffer contain a header needed for decoding */
458   if (naltype >= GST_H265_NAL_VPS && naltype <= GST_H265_NAL_PPS)
459     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_HEADER);
460 
461   if (store[id])
462     gst_buffer_unref (store[id]);
463 
464   store[id] = buf;
465 }
466 
467 #ifndef GST_DISABLE_GST_DEBUG
468 static const gchar *nal_names[] = {
469   "Slice_TRAIL_N",
470   "Slice_TRAIL_R",
471   "Slice_TSA_N",
472   "Slice_TSA_R",
473   "Slice_STSA_N",
474   "Slice_STSA_R",
475   "Slice_RADL_N",
476   "Slice_RADL_R",
477   "SLICE_RASL_N",
478   "SLICE_RASL_R",
479   "Invalid (10)",
480   "Invalid (11)",
481   "Invalid (12)",
482   "Invalid (13)",
483   "Invalid (14)",
484   "Invalid (15)",
485   "SLICE_BLA_W_LP",
486   "SLICE_BLA_W_RADL",
487   "SLICE_BLA_N_LP",
488   "SLICE_IDR_W_RADL",
489   "SLICE_IDR_N_LP",
490   "SLICE_CRA_NUT",
491   "Invalid (22)",
492   "Invalid (23)",
493   "Invalid (24)",
494   "Invalid (25)",
495   "Invalid (26)",
496   "Invalid (27)",
497   "Invalid (28)",
498   "Invalid (29)",
499   "Invalid (30)",
500   "Invalid (31)",
501   "VPS",
502   "SPS",
503   "PPS",
504   "AUD",
505   "EOS",
506   "EOB",
507   "FD",
508   "PREFIX_SEI",
509   "SUFFIX_SEI"
510 };
511 
512 static const gchar *
_nal_name(GstH265NalUnitType nal_type)513 _nal_name (GstH265NalUnitType nal_type)
514 {
515   if (nal_type <= GST_H265_NAL_SUFFIX_SEI)
516     return nal_names[nal_type];
517   return "Invalid";
518 }
519 #endif
520 
521 static void
gst_h265_parse_process_sei(GstH265Parse * h265parse,GstH265NalUnit * nalu)522 gst_h265_parse_process_sei (GstH265Parse * h265parse, GstH265NalUnit * nalu)
523 {
524   GstH265SEIMessage sei;
525   GstH265Parser *nalparser = h265parse->nalparser;
526   GstH265ParserResult pres;
527   GArray *messages;
528   guint i;
529 
530   pres = gst_h265_parser_parse_sei (nalparser, nalu, &messages);
531   if (pres != GST_H265_PARSER_OK)
532     GST_WARNING_OBJECT (h265parse, "failed to parse one or more SEI message");
533 
534   /* Even if pres != GST_H265_PARSER_OK, some message could have been parsed and
535    * stored in messages.
536    */
537   for (i = 0; i < messages->len; i++) {
538     sei = g_array_index (messages, GstH265SEIMessage, i);
539     switch (sei.payloadType) {
540       case GST_H265_SEI_RECOVERY_POINT:
541         GST_LOG_OBJECT (h265parse, "recovery point found: %u %u %u",
542             sei.payload.recovery_point.recovery_poc_cnt,
543             sei.payload.recovery_point.exact_match_flag,
544             sei.payload.recovery_point.broken_link_flag);
545         h265parse->keyframe = TRUE;
546         break;
547       case GST_H265_SEI_TIME_CODE:
548         memcpy (&h265parse->time_code, &sei.payload.time_code,
549             sizeof (GstH265TimeCode));
550         break;
551       case GST_H265_SEI_PIC_TIMING:
552         h265parse->sei_pic_struct = sei.payload.pic_timing.pic_struct;
553         break;
554       case GST_H265_SEI_BUF_PERIOD:
555         /* FIXME */
556         break;
557     }
558   }
559   g_array_free (messages, TRUE);
560 }
561 
562 /* caller guarantees 2 bytes of nal payload */
563 static gboolean
gst_h265_parse_process_nal(GstH265Parse * h265parse,GstH265NalUnit * nalu)564 gst_h265_parse_process_nal (GstH265Parse * h265parse, GstH265NalUnit * nalu)
565 {
566   GstH265PPS pps = { 0, };
567   GstH265SPS sps = { 0, };
568   GstH265VPS vps = { 0, };
569   gboolean is_irap;
570   guint nal_type;
571   GstH265Parser *nalparser = h265parse->nalparser;
572   GstH265ParserResult pres = GST_H265_PARSER_ERROR;
573 
574   /* nothing to do for broken input */
575   if (G_UNLIKELY (nalu->size < 2)) {
576     GST_DEBUG_OBJECT (h265parse, "not processing nal size %u", nalu->size);
577     return TRUE;
578   }
579 
580   /* we have a peek as well */
581   nal_type = nalu->type;
582 
583   GST_DEBUG_OBJECT (h265parse, "processing nal of type %u %s, size %u",
584       nal_type, _nal_name (nal_type), nalu->size);
585   switch (nal_type) {
586     case GST_H265_NAL_VPS:
587       /* It is not mandatory to have VPS in the stream. But it might
588        * be needed for other extensions like svc */
589       pres = gst_h265_parser_parse_vps (nalparser, nalu, &vps);
590       if (pres != GST_H265_PARSER_OK) {
591         GST_WARNING_OBJECT (h265parse, "failed to parse VPS");
592         return FALSE;
593       }
594 
595       GST_DEBUG_OBJECT (h265parse, "triggering src caps check");
596       h265parse->update_caps = TRUE;
597       h265parse->have_vps = TRUE;
598       h265parse->have_vps_in_frame = TRUE;
599       if (h265parse->push_codec && h265parse->have_pps) {
600         /* VPS/SPS/PPS found in stream before the first pre_push_frame, no need
601          * to forcibly push at start */
602         GST_INFO_OBJECT (h265parse, "have VPS/SPS/PPS in stream");
603         h265parse->push_codec = FALSE;
604         h265parse->have_vps = FALSE;
605         h265parse->have_sps = FALSE;
606         h265parse->have_pps = FALSE;
607       }
608 
609       gst_h265_parser_store_nal (h265parse, vps.id, nal_type, nalu);
610       h265parse->header |= TRUE;
611       break;
612     case GST_H265_NAL_SPS:
613       /* reset state, everything else is obsolete */
614       h265parse->state = 0;
615 
616       pres = gst_h265_parser_parse_sps (nalparser, nalu, &sps, TRUE);
617 
618 
619       /* arranged for a fallback sps.id, so use that one and only warn */
620       if (pres != GST_H265_PARSER_OK) {
621         /* try to not parse VUI */
622         pres = gst_h265_parser_parse_sps (nalparser, nalu, &sps, FALSE);
623         if (pres != GST_H265_PARSER_OK) {
624           GST_WARNING_OBJECT (h265parse, "failed to parse SPS:");
625           return FALSE;
626         }
627         GST_WARNING_OBJECT (h265parse,
628             "failed to parse VUI of SPS, ignore VUI");
629       }
630 
631       GST_DEBUG_OBJECT (h265parse, "triggering src caps check");
632       h265parse->update_caps = TRUE;
633       h265parse->have_sps = TRUE;
634       h265parse->have_sps_in_frame = TRUE;
635       if (h265parse->push_codec && h265parse->have_pps) {
636         /* SPS and PPS found in stream before the first pre_push_frame, no need
637          * to forcibly push at start */
638         GST_INFO_OBJECT (h265parse, "have SPS/PPS in stream");
639         h265parse->push_codec = FALSE;
640         h265parse->have_sps = FALSE;
641         h265parse->have_pps = FALSE;
642       }
643 
644       gst_h265_parser_store_nal (h265parse, sps.id, nal_type, nalu);
645       h265parse->header |= TRUE;
646       h265parse->state |= GST_H265_PARSE_STATE_GOT_SPS;
647       break;
648     case GST_H265_NAL_PPS:
649       /* expected state: got-sps */
650       h265parse->state &= GST_H265_PARSE_STATE_GOT_SPS;
651       if (!GST_H265_PARSE_STATE_VALID (h265parse, GST_H265_PARSE_STATE_GOT_SPS))
652         return FALSE;
653 
654       pres = gst_h265_parser_parse_pps (nalparser, nalu, &pps);
655 
656 
657       /* arranged for a fallback pps.id, so use that one and only warn */
658       if (pres != GST_H265_PARSER_OK) {
659         GST_WARNING_OBJECT (h265parse, "failed to parse PPS:");
660         if (pres != GST_H265_PARSER_BROKEN_LINK)
661           return FALSE;
662       }
663 
664       /* parameters might have changed, force caps check */
665       if (!h265parse->have_pps) {
666         GST_DEBUG_OBJECT (h265parse, "triggering src caps check");
667         h265parse->update_caps = TRUE;
668       }
669       h265parse->have_pps = TRUE;
670       h265parse->have_pps_in_frame = TRUE;
671       if (h265parse->push_codec && h265parse->have_sps) {
672         /* SPS and PPS found in stream before the first pre_push_frame, no need
673          * to forcibly push at start */
674         GST_INFO_OBJECT (h265parse, "have SPS/PPS in stream");
675         h265parse->push_codec = FALSE;
676         h265parse->have_sps = FALSE;
677         h265parse->have_pps = FALSE;
678       }
679 
680       gst_h265_parser_store_nal (h265parse, pps.id, nal_type, nalu);
681       h265parse->header |= TRUE;
682       h265parse->state |= GST_H265_PARSE_STATE_GOT_PPS;
683       break;
684     case GST_H265_NAL_PREFIX_SEI:
685     case GST_H265_NAL_SUFFIX_SEI:
686       /* expected state: got-sps */
687       if (!GST_H265_PARSE_STATE_VALID (h265parse, GST_H265_PARSE_STATE_GOT_SPS))
688         return FALSE;
689 
690       h265parse->header |= TRUE;
691 
692       gst_h265_parse_process_sei (h265parse, nalu);
693 
694       /* mark SEI pos */
695       if (h265parse->sei_pos == -1) {
696         if (h265parse->transform)
697           h265parse->sei_pos = gst_adapter_available (h265parse->frame_out);
698         else
699           h265parse->sei_pos = nalu->sc_offset;
700         GST_DEBUG_OBJECT (h265parse, "marking SEI in frame at offset %d",
701             h265parse->sei_pos);
702       }
703       break;
704 
705     case GST_H265_NAL_SLICE_TRAIL_N:
706     case GST_H265_NAL_SLICE_TRAIL_R:
707     case GST_H265_NAL_SLICE_TSA_N:
708     case GST_H265_NAL_SLICE_TSA_R:
709     case GST_H265_NAL_SLICE_STSA_N:
710     case GST_H265_NAL_SLICE_STSA_R:
711     case GST_H265_NAL_SLICE_RADL_N:
712     case GST_H265_NAL_SLICE_RADL_R:
713     case GST_H265_NAL_SLICE_RASL_N:
714     case GST_H265_NAL_SLICE_RASL_R:
715     case GST_H265_NAL_SLICE_BLA_W_LP:
716     case GST_H265_NAL_SLICE_BLA_W_RADL:
717     case GST_H265_NAL_SLICE_BLA_N_LP:
718     case GST_H265_NAL_SLICE_IDR_W_RADL:
719     case GST_H265_NAL_SLICE_IDR_N_LP:
720     case GST_H265_NAL_SLICE_CRA_NUT:
721     {
722       GstH265SliceHdr slice;
723 
724       /* expected state: got-sps|got-pps (valid picture headers) */
725       h265parse->state &= GST_H265_PARSE_STATE_VALID_PICTURE_HEADERS;
726       if (!GST_H265_PARSE_STATE_VALID (h265parse,
727               GST_H265_PARSE_STATE_VALID_PICTURE_HEADERS))
728         return FALSE;
729 
730       pres = gst_h265_parser_parse_slice_hdr (nalparser, nalu, &slice);
731 
732       if (pres == GST_H265_PARSER_OK) {
733         if (GST_H265_IS_I_SLICE (&slice))
734           h265parse->keyframe |= TRUE;
735 
736         h265parse->state |= GST_H265_PARSE_STATE_GOT_SLICE;
737       }
738       if (slice.first_slice_segment_in_pic_flag == 1)
739         GST_DEBUG_OBJECT (h265parse,
740             "frame start, first_slice_segment_in_pic_flag = 1");
741 
742       GST_DEBUG_OBJECT (h265parse,
743           "parse result %d, first slice_segment: %u, slice type: %u",
744           pres, slice.first_slice_segment_in_pic_flag, slice.type);
745 
746       gst_h265_slice_hdr_free (&slice);
747     }
748 
749       is_irap = ((nal_type >= GST_H265_NAL_SLICE_BLA_W_LP)
750           && (nal_type <= GST_H265_NAL_SLICE_CRA_NUT)) ? TRUE : FALSE;
751       if (G_LIKELY (!is_irap && !h265parse->push_codec))
752         break;
753 
754       /* if we need to sneak codec NALs into the stream,
755        * this is a good place, so fake it as IDR
756        * (which should be at start anyway) */
757       /* mark where config needs to go if interval expired */
758       /* mind replacement buffer if applicable */
759       if (h265parse->idr_pos == -1) {
760         if (h265parse->transform)
761           h265parse->idr_pos = gst_adapter_available (h265parse->frame_out);
762         else
763           h265parse->idr_pos = nalu->sc_offset;
764         GST_DEBUG_OBJECT (h265parse, "marking IDR in frame at offset %d",
765             h265parse->idr_pos);
766       }
767       /* if SEI preceeds (faked) IDR, then we have to insert config there */
768       if (h265parse->sei_pos >= 0 && h265parse->idr_pos > h265parse->sei_pos) {
769         h265parse->idr_pos = h265parse->sei_pos;
770         GST_DEBUG_OBJECT (h265parse, "moved IDR mark to SEI position %d",
771             h265parse->idr_pos);
772       }
773       break;
774     case GST_H265_NAL_AUD:
775       /* Just accumulate AU Delimiter, whether it's before SPS or not */
776       pres = gst_h265_parser_parse_nal (nalparser, nalu);
777       if (pres != GST_H265_PARSER_OK)
778         return FALSE;
779       break;
780     default:
781       /* drop anything before the initial SPS */
782       if (!GST_H265_PARSE_STATE_VALID (h265parse, GST_H265_PARSE_STATE_GOT_SPS))
783         return FALSE;
784 
785       pres = gst_h265_parser_parse_nal (nalparser, nalu);
786       if (pres != GST_H265_PARSER_OK)
787         return FALSE;
788       break;
789   }
790 
791   /* if HEVC output needed, collect properly prefixed nal in adapter,
792    * and use that to replace outgoing buffer data later on */
793   if (h265parse->transform) {
794     GstBuffer *buf;
795 
796     GST_LOG_OBJECT (h265parse, "collecting NAL in HEVC frame");
797     buf = gst_h265_parse_wrap_nal (h265parse, h265parse->format,
798         nalu->data + nalu->offset, nalu->size);
799     gst_adapter_push (h265parse->frame_out, buf);
800   }
801 
802   return TRUE;
803 }
804 
805 /* caller guarantees at least 3 bytes of nal payload for each nal
806  * returns TRUE if next_nal indicates that nal terminates an AU */
807 static inline gboolean
gst_h265_parse_collect_nal(GstH265Parse * h265parse,const guint8 * data,guint size,GstH265NalUnit * nalu)808 gst_h265_parse_collect_nal (GstH265Parse * h265parse, const guint8 * data,
809     guint size, GstH265NalUnit * nalu)
810 {
811   gboolean complete;
812   GstH265ParserResult parse_res;
813   GstH265NalUnitType nal_type = nalu->type;
814   GstH265NalUnit nnalu;
815 
816   GST_DEBUG_OBJECT (h265parse, "parsing collected nal");
817   parse_res = gst_h265_parser_identify_nalu_unchecked (h265parse->nalparser,
818       data, nalu->offset + nalu->size, size, &nnalu);
819 
820   if (parse_res != GST_H265_PARSER_OK)
821     return FALSE;
822 
823   /* determine if AU complete */
824   GST_LOG_OBJECT (h265parse, "nal type: %d %s", nal_type, _nal_name (nal_type));
825   /* coded slice NAL starts a picture,
826    * i.e. other types become aggregated in front of it */
827   h265parse->picture_start |= ((nal_type >= GST_H265_NAL_SLICE_TRAIL_N
828           && nal_type <= GST_H265_NAL_SLICE_RASL_R)
829       || (nal_type >= GST_H265_NAL_SLICE_BLA_W_LP
830           && nal_type <= RESERVED_IRAP_NAL_TYPE_MAX));
831 
832   /* consider a coded slices (IRAP or not) to start a picture,
833    * (so ending the previous one) if first_slice_segment_in_pic_flag == 1*/
834   nal_type = nnalu.type;
835   complete = h265parse->picture_start && ((nal_type >= GST_H265_NAL_VPS
836           && nal_type <= GST_H265_NAL_AUD)
837       || nal_type == GST_H265_NAL_PREFIX_SEI || (nal_type >= 41
838           && nal_type <= 44) || (nal_type >= 48 && nal_type <= 55));
839 
840   GST_LOG_OBJECT (h265parse, "next nal type: %d %s", nal_type,
841       _nal_name (nal_type));
842 
843   /* Any VCL Nal unit with first_slice_segment_in_pic_flag == 1 considered start of frame */
844   complete |= h265parse->picture_start
845       && (((nal_type >= GST_H265_NAL_SLICE_TRAIL_N
846               && nal_type <= GST_H265_NAL_SLICE_RASL_R)
847           || (nal_type >= GST_H265_NAL_SLICE_BLA_W_LP
848               && nal_type <= RESERVED_IRAP_NAL_TYPE_MAX))
849       && (nnalu.data[nnalu.offset + 2] & 0x80));
850 
851   GST_LOG_OBJECT (h265parse, "au complete: %d", complete);
852   return complete;
853 }
854 
855 static GstFlowReturn
gst_h265_parse_handle_frame_packetized(GstBaseParse * parse,GstBaseParseFrame * frame)856 gst_h265_parse_handle_frame_packetized (GstBaseParse * parse,
857     GstBaseParseFrame * frame)
858 {
859   GstH265Parse *h265parse = GST_H265_PARSE (parse);
860   GstBuffer *buffer = frame->buffer;
861   GstFlowReturn ret = GST_FLOW_OK;
862   GstH265ParserResult parse_res;
863   GstH265NalUnit nalu;
864   const guint nl = h265parse->nal_length_size;
865   GstMapInfo map;
866   gint left;
867 
868   if (nl < 1 || nl > 4) {
869     GST_DEBUG_OBJECT (h265parse, "insufficient data to split input");
870     return GST_FLOW_NOT_NEGOTIATED;
871   }
872 
873   /* need to save buffer from invalidation upon _finish_frame */
874   if (h265parse->split_packetized)
875     buffer = gst_buffer_copy (frame->buffer);
876 
877   gst_buffer_map (buffer, &map, GST_MAP_READ);
878 
879   left = map.size;
880 
881   GST_LOG_OBJECT (h265parse,
882       "processing packet buffer of size %" G_GSIZE_FORMAT, map.size);
883 
884   parse_res = gst_h265_parser_identify_nalu_hevc (h265parse->nalparser,
885       map.data, 0, map.size, nl, &nalu);
886 
887   while (parse_res == GST_H265_PARSER_OK) {
888     GST_DEBUG_OBJECT (h265parse, "HEVC nal offset %d", nalu.offset + nalu.size);
889 
890     /* either way, have a look at it */
891     gst_h265_parse_process_nal (h265parse, &nalu);
892 
893     /* dispatch per NALU if needed */
894     if (h265parse->split_packetized) {
895       GstBaseParseFrame tmp_frame;
896 
897       gst_base_parse_frame_init (&tmp_frame);
898       tmp_frame.flags |= frame->flags;
899       tmp_frame.offset = frame->offset;
900       tmp_frame.overhead = frame->overhead;
901       tmp_frame.buffer = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_ALL,
902           nalu.offset, nalu.size);
903 
904       /* note we don't need to come up with a sub-buffer, since
905        * subsequent code only considers input buffer's metadata.
906        * Real data is either taken from input by baseclass or
907        * a replacement output buffer is provided anyway. */
908       gst_h265_parse_parse_frame (parse, &tmp_frame);
909       ret = gst_base_parse_finish_frame (parse, &tmp_frame, nl + nalu.size);
910       left -= nl + nalu.size;
911     }
912 
913     parse_res = gst_h265_parser_identify_nalu_hevc (h265parse->nalparser,
914         map.data, nalu.offset + nalu.size, map.size, nl, &nalu);
915   }
916 
917   gst_buffer_unmap (buffer, &map);
918 
919   if (!h265parse->split_packetized) {
920     gst_h265_parse_parse_frame (parse, frame);
921     ret = gst_base_parse_finish_frame (parse, frame, map.size);
922   } else {
923     gst_buffer_unref (buffer);
924     if (G_UNLIKELY (left)) {
925       /* should not be happening for nice HEVC */
926       GST_WARNING_OBJECT (parse, "skipping leftover HEVC data %d", left);
927       frame->flags |= GST_BASE_PARSE_FRAME_FLAG_DROP;
928       ret = gst_base_parse_finish_frame (parse, frame, map.size);
929     }
930   }
931 
932   if (parse_res == GST_H265_PARSER_NO_NAL_END ||
933       parse_res == GST_H265_PARSER_BROKEN_DATA) {
934 
935     if (h265parse->split_packetized) {
936       GST_ELEMENT_ERROR (h265parse, STREAM, FAILED, (NULL),
937           ("invalid HEVC input data"));
938 
939       return GST_FLOW_ERROR;
940     } else {
941       /* do not meddle to much in this case */
942       GST_DEBUG_OBJECT (h265parse, "parsing packet failed");
943     }
944   }
945 
946   return ret;
947 }
948 
949 static GstFlowReturn
gst_h265_parse_handle_frame(GstBaseParse * parse,GstBaseParseFrame * frame,gint * skipsize)950 gst_h265_parse_handle_frame (GstBaseParse * parse,
951     GstBaseParseFrame * frame, gint * skipsize)
952 {
953   GstH265Parse *h265parse = GST_H265_PARSE (parse);
954   GstBuffer *buffer = frame->buffer;
955   GstMapInfo map;
956   guint8 *data;
957   gsize size;
958   gint current_off = 0;
959   gboolean drain, nonext;
960   GstH265Parser *nalparser = h265parse->nalparser;
961   GstH265NalUnit nalu;
962   GstH265ParserResult pres;
963   gint framesize;
964 
965   if (G_UNLIKELY (GST_BUFFER_FLAG_IS_SET (frame->buffer,
966               GST_BUFFER_FLAG_DISCONT))) {
967     h265parse->discont = TRUE;
968   }
969 
970   /* delegate in packetized case, no skipping should be needed */
971   if (h265parse->packetized)
972     return gst_h265_parse_handle_frame_packetized (parse, frame);
973 
974   gst_buffer_map (buffer, &map, GST_MAP_READ);
975   data = map.data;
976   size = map.size;
977 
978   /* expect at least 3 bytes startcode == sc, and 3 bytes NALU payload */
979   if (G_UNLIKELY (size < 6)) {
980     gst_buffer_unmap (buffer, &map);
981     *skipsize = 1;
982     return GST_FLOW_OK;
983   }
984 
985   /* need to configure aggregation */
986   if (G_UNLIKELY (h265parse->format == GST_H265_PARSE_FORMAT_NONE))
987     gst_h265_parse_negotiate (h265parse, GST_H265_PARSE_FORMAT_BYTE, NULL);
988 
989   /* avoid stale cached parsing state */
990   if (frame->flags & GST_BASE_PARSE_FRAME_FLAG_NEW_FRAME) {
991     GST_LOG_OBJECT (h265parse, "parsing new frame");
992     gst_h265_parse_reset_frame (h265parse);
993   } else {
994     GST_LOG_OBJECT (h265parse, "resuming frame parsing");
995   }
996 
997   drain = GST_BASE_PARSE_DRAINING (parse);
998   nonext = FALSE;
999 
1000   current_off = h265parse->current_off;
1001   if (current_off < 0)
1002     current_off = 0;
1003   g_assert (current_off < size);
1004   GST_DEBUG_OBJECT (h265parse, "last parse position %d", current_off);
1005 
1006   /* check for initial skip */
1007   if (h265parse->current_off == -1) {
1008     pres =
1009         gst_h265_parser_identify_nalu_unchecked (nalparser, data, current_off,
1010         size, &nalu);
1011     switch (pres) {
1012       case GST_H265_PARSER_OK:
1013         if (nalu.sc_offset > 0) {
1014           *skipsize = nalu.sc_offset;
1015           goto skip;
1016         }
1017         break;
1018       case GST_H265_PARSER_NO_NAL:
1019         *skipsize = size - 3;
1020         goto skip;
1021       default:
1022         /* should not really occur either */
1023         GST_ELEMENT_ERROR (h265parse, STREAM, FORMAT,
1024             ("Error parsing H.265 stream"), ("Invalid H.265 stream"));
1025         goto invalid_stream;
1026     }
1027   }
1028 
1029   while (TRUE) {
1030     pres =
1031         gst_h265_parser_identify_nalu (nalparser, data, current_off, size,
1032         &nalu);
1033 
1034     switch (pres) {
1035       case GST_H265_PARSER_OK:
1036         GST_DEBUG_OBJECT (h265parse, "complete nal (offset, size): (%u, %u) ",
1037             nalu.offset, nalu.size);
1038         break;
1039       case GST_H265_PARSER_NO_NAL_END:
1040         GST_DEBUG_OBJECT (h265parse, "not a complete nal found at offset %u",
1041             nalu.offset);
1042         /* if draining, accept it as complete nal */
1043         if (drain) {
1044           nonext = TRUE;
1045           nalu.size = size - nalu.offset;
1046           GST_DEBUG_OBJECT (h265parse, "draining, accepting with size %u",
1047               nalu.size);
1048           /* if it's not too short at least */
1049           if (nalu.size < 3)
1050             goto broken;
1051           break;
1052         }
1053         /* otherwise need more */
1054         goto more;
1055       case GST_H265_PARSER_BROKEN_LINK:
1056         GST_ELEMENT_ERROR (h265parse, STREAM, FORMAT,
1057             ("Error parsing H.265 stream"),
1058             ("The link to structure needed for the parsing couldn't be found"));
1059         goto invalid_stream;
1060       case GST_H265_PARSER_ERROR:
1061         /* should not really occur either */
1062         GST_ELEMENT_ERROR (h265parse, STREAM, FORMAT,
1063             ("Error parsing H.265 stream"), ("Invalid H.265 stream"));
1064         goto invalid_stream;
1065       case GST_H265_PARSER_NO_NAL:
1066         GST_ELEMENT_ERROR (h265parse, STREAM, FORMAT,
1067             ("Error parsing H.265 stream"), ("No H.265 NAL unit found"));
1068         goto invalid_stream;
1069       case GST_H265_PARSER_BROKEN_DATA:
1070         GST_WARNING_OBJECT (h265parse, "input stream is corrupt; "
1071             "it contains a NAL unit of length %u", nalu.size);
1072       broken:
1073         /* broken nal at start -> arrange to skip it,
1074          * otherwise have it terminate current au
1075          * (and so it will be skipped on next frame round) */
1076         if (current_off == 0) {
1077           GST_DEBUG_OBJECT (h265parse, "skipping broken nal");
1078           *skipsize = nalu.offset;
1079           goto skip;
1080         } else {
1081           GST_DEBUG_OBJECT (h265parse, "terminating au");
1082           nalu.size = 0;
1083           nalu.offset = nalu.sc_offset;
1084           goto end;
1085         }
1086       default:
1087         g_assert_not_reached ();
1088         break;
1089     }
1090 
1091     GST_DEBUG_OBJECT (h265parse, "%p complete nal found. Off: %u, Size: %u",
1092         data, nalu.offset, nalu.size);
1093 
1094     /* simulate no next nal if none needed */
1095     nonext = nonext || (h265parse->align == GST_H265_PARSE_ALIGN_NAL);
1096 
1097     if (!nonext) {
1098       if (nalu.offset + nalu.size + 5 + 2 > size) {
1099         GST_DEBUG_OBJECT (h265parse, "not enough data for next NALU");
1100         if (drain) {
1101           GST_DEBUG_OBJECT (h265parse, "but draining anyway");
1102           nonext = TRUE;
1103         } else {
1104           goto more;
1105         }
1106       }
1107     }
1108 
1109     if (!gst_h265_parse_process_nal (h265parse, &nalu)) {
1110       GST_WARNING_OBJECT (h265parse,
1111           "broken/invalid nal Type: %d %s, Size: %u will be dropped",
1112           nalu.type, _nal_name (nalu.type), nalu.size);
1113       *skipsize = nalu.size;
1114       goto skip;
1115     }
1116 
1117     if (nonext)
1118       break;
1119 
1120     /* if no next nal, we know it's complete here */
1121     if (gst_h265_parse_collect_nal (h265parse, data, size, &nalu))
1122       break;
1123 
1124     GST_DEBUG_OBJECT (h265parse, "Looking for more");
1125     current_off = nalu.offset + nalu.size;
1126   }
1127 
1128 end:
1129   framesize = nalu.offset + nalu.size;
1130 
1131   gst_buffer_unmap (buffer, &map);
1132 
1133   gst_h265_parse_parse_frame (parse, frame);
1134 
1135   return gst_base_parse_finish_frame (parse, frame, framesize);
1136 
1137 more:
1138   *skipsize = 0;
1139 
1140   /* Restart parsing from here next time */
1141   if (current_off > 0)
1142     h265parse->current_off = current_off;
1143 
1144   /* Fall-through. */
1145 out:
1146   gst_buffer_unmap (buffer, &map);
1147   return GST_FLOW_OK;
1148 
1149 skip:
1150   GST_DEBUG_OBJECT (h265parse, "skipping %d", *skipsize);
1151   /* If we are collecting access units, we need to preserve the initial
1152    * config headers (SPS, PPS et al.) and only reset the frame if another
1153    * slice NAL was received. This means that broken pictures are discarded */
1154   if (h265parse->align != GST_H265_PARSE_ALIGN_AU ||
1155       !(h265parse->state & GST_H265_PARSE_STATE_VALID_PICTURE_HEADERS) ||
1156       (h265parse->state & GST_H265_PARSE_STATE_GOT_SLICE))
1157     gst_h265_parse_reset_frame (h265parse);
1158   goto out;
1159 
1160 invalid_stream:
1161   gst_buffer_unmap (buffer, &map);
1162   return GST_FLOW_ERROR;
1163 }
1164 
1165 /* byte together hevc codec data based on collected pps and sps so far */
1166 static GstBuffer *
gst_h265_parse_make_codec_data(GstH265Parse * h265parse)1167 gst_h265_parse_make_codec_data (GstH265Parse * h265parse)
1168 {
1169   GstBuffer *buf, *nal;
1170   gint i, j, k = 0;
1171   guint vps_size = 0, sps_size = 0, pps_size = 0;
1172   guint num_vps = 0, num_sps = 0, num_pps = 0;
1173   gboolean found = FALSE;
1174   GstMapInfo map;
1175   guint8 *data;
1176   gint nl;
1177   guint8 num_arrays = 0;
1178   GstH265SPS *sps = NULL;
1179   guint16 min_spatial_segmentation_idc = 0;
1180   GstH265ProfileTierLevel *pft;
1181 
1182   /* only nal payload in stored nals */
1183   /* Fixme: Current implementation is not embedding SEI in codec_data */
1184   for (i = 0; i < GST_H265_MAX_VPS_COUNT; i++) {
1185     if ((nal = h265parse->vps_nals[i])) {
1186       num_vps++;
1187       /* size bytes also count */
1188       vps_size += gst_buffer_get_size (nal) + 2;
1189     }
1190   }
1191   if (num_vps > 0)
1192     num_arrays++;
1193 
1194   for (i = 0; i < GST_H265_MAX_SPS_COUNT; i++) {
1195     if ((nal = h265parse->sps_nals[i])) {
1196       num_sps++;
1197       /* size bytes also count */
1198       sps_size += gst_buffer_get_size (nal) + 2;
1199       found = TRUE;
1200     }
1201   }
1202   if (num_sps > 0)
1203     num_arrays++;
1204 
1205   for (i = 0; i < GST_H265_MAX_PPS_COUNT; i++) {
1206     if ((nal = h265parse->pps_nals[i])) {
1207       num_pps++;
1208       /* size bytes also count */
1209       pps_size += gst_buffer_get_size (nal) + 2;
1210     }
1211   }
1212   if (num_pps > 0)
1213     num_arrays++;
1214 
1215   GST_DEBUG_OBJECT (h265parse,
1216       "constructing codec_data: num_vps =%d num_sps=%d, num_pps=%d", num_vps,
1217       num_sps, num_pps);
1218 
1219   if (!found)
1220     return NULL;
1221 
1222   sps = h265parse->nalparser->last_sps;
1223   if (!sps)
1224     return NULL;
1225 
1226   buf =
1227       gst_buffer_new_allocate (NULL,
1228       23 + (3 * num_arrays) + vps_size + sps_size + pps_size, NULL);
1229   gst_buffer_map (buf, &map, GST_MAP_WRITE);
1230   data = map.data;
1231   memset (data, 0, map.size);
1232   nl = h265parse->nal_length_size;
1233 
1234   pft = &sps->profile_tier_level;
1235   if (sps->vui_parameters_present_flag)
1236     min_spatial_segmentation_idc = sps->vui_params.min_spatial_segmentation_idc;
1237 
1238   /* HEVCDecoderConfigurationVersion = 1
1239    * profile_space | tier_flat | profile_idc |
1240    * profile_compatibility_flags | constraint_indicator_flags |
1241    * level_idc */
1242   data[0] = 1;
1243   data[1] =
1244       (pft->profile_space << 5) | (pft->tier_flag << 5) | pft->profile_idc;
1245   for (i = 2; i < 6; i++) {
1246     for (j = 7; j >= 0; j--) {
1247       data[i] |= (pft->profile_compatibility_flag[k] << j);
1248       k++;
1249     }
1250   }
1251   data[6] |=
1252       (pft->progressive_source_flag << 7) | (pft->interlaced_source_flag << 6) |
1253       (pft->non_packed_constraint_flag << 5) | (pft->
1254       frame_only_constraint_flag << 4);
1255   data[12] = pft->level_idc;
1256   /* min_spatial_segmentation_idc */
1257   GST_WRITE_UINT16_BE (data + 13, min_spatial_segmentation_idc);
1258   data[13] |= 0xf0;
1259   data[15] = 0xfc;              /* keeping parrallelismType as zero (unknown) */
1260   data[16] = 0xfc | sps->chroma_format_idc;
1261   data[17] = 0xf8 | sps->bit_depth_luma_minus8;
1262   data[18] = 0xf8 | sps->bit_depth_chroma_minus8;
1263   data[19] = 0x00;              /* keep avgFrameRate as unspecified */
1264   data[20] = 0x00;              /* keep avgFrameRate as unspecified */
1265   /* constFrameRate(2 bits): 0, stream may or may not be of constant framerate
1266    * numTemporalLayers (3 bits): number of temporal layers, value from SPS
1267    * TemporalIdNested (1 bit): sps_temporal_id_nesting_flag from SPS
1268    * lengthSizeMinusOne (2 bits): plus 1 indicates the length of the NALUnitLength */
1269   data[21] =
1270       0x00 | ((sps->max_sub_layers_minus1 +
1271           1) << 3) | (sps->temporal_id_nesting_flag << 2) | (nl - 1);
1272   GST_WRITE_UINT8 (data + 22, num_arrays);      /* numOfArrays */
1273 
1274   data += 23;
1275 
1276   /* VPS */
1277   if (num_vps > 0) {
1278     /* array_completeness | reserved_zero bit | nal_unit_type */
1279     data[0] = 0x00 | 0x20;
1280     data++;
1281 
1282     GST_WRITE_UINT16_BE (data, num_vps);
1283     data += 2;
1284 
1285     for (i = 0; i < GST_H265_MAX_VPS_COUNT; i++) {
1286       if ((nal = h265parse->vps_nals[i])) {
1287         gsize nal_size = gst_buffer_get_size (nal);
1288         GST_WRITE_UINT16_BE (data, nal_size);
1289         gst_buffer_extract (nal, 0, data + 2, nal_size);
1290         data += 2 + nal_size;
1291       }
1292     }
1293   }
1294 
1295   /* SPS */
1296   if (num_sps > 0) {
1297     /* array_completeness | reserved_zero bit | nal_unit_type */
1298     data[0] = 0x00 | 0x21;
1299     data++;
1300 
1301     GST_WRITE_UINT16_BE (data, num_sps);
1302     data += 2;
1303 
1304     for (i = 0; i < GST_H265_MAX_SPS_COUNT; i++) {
1305       if ((nal = h265parse->sps_nals[i])) {
1306         gsize nal_size = gst_buffer_get_size (nal);
1307         GST_WRITE_UINT16_BE (data, nal_size);
1308         gst_buffer_extract (nal, 0, data + 2, nal_size);
1309         data += 2 + nal_size;
1310       }
1311     }
1312   }
1313 
1314   /* PPS */
1315   if (num_pps > 0) {
1316     /* array_completeness | reserved_zero bit | nal_unit_type */
1317     data[0] = 0x00 | 0x22;
1318     data++;
1319 
1320     GST_WRITE_UINT16_BE (data, num_pps);
1321     data += 2;
1322 
1323     for (i = 0; i < GST_H265_MAX_PPS_COUNT; i++) {
1324       if ((nal = h265parse->pps_nals[i])) {
1325         gsize nal_size = gst_buffer_get_size (nal);
1326         GST_WRITE_UINT16_BE (data, nal_size);
1327         gst_buffer_extract (nal, 0, data + 2, nal_size);
1328         data += 2 + nal_size;
1329       }
1330     }
1331   }
1332   gst_buffer_unmap (buf, &map);
1333 
1334   return buf;
1335 }
1336 
1337 static void
gst_h265_parse_get_par(GstH265Parse * h265parse,gint * num,gint * den)1338 gst_h265_parse_get_par (GstH265Parse * h265parse, gint * num, gint * den)
1339 {
1340   if (h265parse->upstream_par_n != -1 && h265parse->upstream_par_d != -1) {
1341     *num = h265parse->upstream_par_n;
1342     *den = h265parse->upstream_par_d;
1343   } else {
1344     *num = h265parse->parsed_par_n;
1345     *den = h265parse->parsed_par_d;
1346   }
1347 }
1348 
1349 static const gchar *
digit_to_string(guint digit)1350 digit_to_string (guint digit)
1351 {
1352   static const char itoa[][2] = {
1353     "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"
1354   };
1355 
1356   if (G_LIKELY (digit < 10))
1357     return itoa[digit];
1358   else
1359     return NULL;
1360 }
1361 
1362 static const gchar *
get_profile_string(GstH265Profile profile)1363 get_profile_string (GstH265Profile profile)
1364 {
1365   switch (profile) {
1366     case GST_H265_PROFILE_MAIN:
1367       return "main";
1368     case GST_H265_PROFILE_MAIN_10:
1369       return "main-10";
1370     case GST_H265_PROFILE_MAIN_STILL_PICTURE:
1371       return "main-still-picture";
1372     case GST_H265_PROFILE_MONOCHROME:
1373       return "monochrome";
1374     case GST_H265_PROFILE_MONOCHROME_12:
1375       return "monochrome-12";
1376     case GST_H265_PROFILE_MONOCHROME_16:
1377       return "monochrome-16";
1378     case GST_H265_PROFILE_MAIN_12:
1379       return "main-12";
1380     case GST_H265_PROFILE_MAIN_422_10:
1381       return "main-422-10";
1382     case GST_H265_PROFILE_MAIN_422_12:
1383       return "main-422-12";
1384     case GST_H265_PROFILE_MAIN_444:
1385       return "main-444";
1386     case GST_H265_PROFILE_MAIN_444_10:
1387       return "main-444-10";
1388     case GST_H265_PROFILE_MAIN_444_12:
1389       return "main-444-12";
1390     case GST_H265_PROFILE_MAIN_INTRA:
1391       return "main-intra";
1392     case GST_H265_PROFILE_MAIN_10_INTRA:
1393       return "main-10-intra";
1394     case GST_H265_PROFILE_MAIN_12_INTRA:
1395       return "main-12-intra";
1396     case GST_H265_PROFILE_MAIN_422_10_INTRA:
1397       return "main-422-10-intra";
1398     case GST_H265_PROFILE_MAIN_422_12_INTRA:
1399       return "main-422-12-intra";
1400     case GST_H265_PROFILE_MAIN_444_INTRA:
1401       return "main-444-intra";
1402     case GST_H265_PROFILE_MAIN_444_10_INTRA:
1403       return "main-444-10-intra";
1404     case GST_H265_PROFILE_MAIN_444_12_INTRA:
1405       return "main-444-12-intra";
1406     case GST_H265_PROFILE_MAIN_444_16_INTRA:
1407       return "main-444-16-intra";
1408     case GST_H265_PROFILE_MAIN_444_STILL_PICTURE:
1409       return "main-444-still-picture";
1410     case GST_H265_PROFILE_MAIN_444_16_STILL_PICTURE:
1411       return "main-444-16-still-picture";
1412     default:
1413       break;
1414   }
1415 
1416   return NULL;
1417 }
1418 
1419 static const gchar *
get_tier_string(guint8 tier_flag)1420 get_tier_string (guint8 tier_flag)
1421 {
1422   const gchar *tier = NULL;
1423 
1424   if (tier_flag)
1425     tier = "high";
1426   else
1427     tier = "main";
1428 
1429   return tier;
1430 }
1431 
1432 static const gchar *
get_level_string(guint8 level_idc)1433 get_level_string (guint8 level_idc)
1434 {
1435   if (level_idc == 0)
1436     return NULL;
1437   else if (level_idc % 30 == 0)
1438     return digit_to_string (level_idc / 30);
1439   else {
1440     switch (level_idc) {
1441       case 63:
1442         return "2.1";
1443         break;
1444       case 93:
1445         return "3.1";
1446         break;
1447       case 123:
1448         return "4.1";
1449         break;
1450       case 153:
1451         return "5.1";
1452         break;
1453       case 156:
1454         return "5.2";
1455         break;
1456       case 183:
1457         return "6.1";
1458         break;
1459       case 186:
1460         return "6.2";
1461         break;
1462       default:
1463         return NULL;
1464     }
1465   }
1466 }
1467 
1468 static GstCaps *
get_compatible_profile_caps(GstH265SPS * sps)1469 get_compatible_profile_caps (GstH265SPS * sps)
1470 {
1471   GstCaps *caps = NULL;
1472   const gchar **profiles = NULL;
1473   gint i;
1474   GValue compat_profiles = G_VALUE_INIT;
1475   g_value_init (&compat_profiles, GST_TYPE_LIST);
1476 
1477   switch (sps->profile_tier_level.profile_idc) {
1478     case GST_H265_PROFILE_IDC_MAIN_10:
1479       if (sps->profile_tier_level.profile_compatibility_flag[1]) {
1480         if (sps->profile_tier_level.profile_compatibility_flag[3]) {
1481           static const gchar *profile_array[] =
1482               { "main", "main-still-picture", NULL };
1483           profiles = profile_array;
1484         } else {
1485           static const gchar *profile_array[] = { "main", NULL };
1486           profiles = profile_array;
1487         }
1488       }
1489       break;
1490     case GST_H265_PROFILE_IDC_MAIN:
1491       if (sps->profile_tier_level.profile_compatibility_flag[3]) {
1492         static const gchar *profile_array[] =
1493             { "main-still-picture", "main-10", NULL
1494         };
1495         profiles = profile_array;
1496       } else {
1497         static const gchar *profile_array[] = { "main-10", NULL };
1498         profiles = profile_array;
1499       }
1500       break;
1501     case GST_H265_PROFILE_IDC_MAIN_STILL_PICTURE:
1502     {
1503       static const gchar *profile_array[] = { "main", "main-10", NULL
1504       };
1505       profiles = profile_array;
1506     }
1507       break;
1508     default:
1509       break;
1510   }
1511 
1512   if (profiles) {
1513     GValue value = G_VALUE_INIT;
1514     caps = gst_caps_new_empty_simple ("video/x-h265");
1515     for (i = 0; profiles[i]; i++) {
1516       g_value_init (&value, G_TYPE_STRING);
1517       g_value_set_string (&value, profiles[i]);
1518       gst_value_list_append_value (&compat_profiles, &value);
1519       g_value_unset (&value);
1520     }
1521     gst_caps_set_value (caps, "profile", &compat_profiles);
1522     g_value_unset (&compat_profiles);
1523   }
1524 
1525   return caps;
1526 }
1527 
1528 /* if downstream didn't support the exact profile indicated in sps header,
1529  * check for the compatible profiles also */
1530 static void
ensure_caps_profile(GstH265Parse * h265parse,GstCaps * caps,GstH265SPS * sps)1531 ensure_caps_profile (GstH265Parse * h265parse, GstCaps * caps, GstH265SPS * sps)
1532 {
1533   GstCaps *peer_caps, *compat_caps;
1534 
1535   peer_caps = gst_pad_get_current_caps (GST_BASE_PARSE_SRC_PAD (h265parse));
1536   if (!peer_caps || !gst_caps_can_intersect (caps, peer_caps)) {
1537     GstCaps *filter_caps = gst_caps_new_empty_simple ("video/x-h265");
1538 
1539     if (peer_caps)
1540       gst_caps_unref (peer_caps);
1541     peer_caps =
1542         gst_pad_peer_query_caps (GST_BASE_PARSE_SRC_PAD (h265parse),
1543         filter_caps);
1544 
1545     gst_caps_unref (filter_caps);
1546   }
1547 
1548   if (peer_caps && !gst_caps_can_intersect (caps, peer_caps)) {
1549     GstStructure *structure;
1550 
1551     compat_caps = get_compatible_profile_caps (sps);
1552     if (compat_caps != NULL) {
1553       GstCaps *res_caps = NULL;
1554 
1555       res_caps = gst_caps_intersect (peer_caps, compat_caps);
1556 
1557       if (res_caps && !gst_caps_is_empty (res_caps)) {
1558         const gchar *profile_str = NULL;
1559 
1560         res_caps = gst_caps_fixate (res_caps);
1561         structure = gst_caps_get_structure (res_caps, 0);
1562         profile_str = gst_structure_get_string (structure, "profile");
1563         if (profile_str) {
1564           gst_caps_set_simple (caps, "profile", G_TYPE_STRING, profile_str,
1565               NULL);
1566           GST_DEBUG_OBJECT (h265parse,
1567               "Setting compatible profile %s to the caps", profile_str);
1568         }
1569       }
1570       if (res_caps)
1571         gst_caps_unref (res_caps);
1572       gst_caps_unref (compat_caps);
1573     }
1574   }
1575   if (peer_caps)
1576     gst_caps_unref (peer_caps);
1577 }
1578 
1579 static void
gst_h265_parse_update_src_caps(GstH265Parse * h265parse,GstCaps * caps)1580 gst_h265_parse_update_src_caps (GstH265Parse * h265parse, GstCaps * caps)
1581 {
1582   GstH265SPS *sps;
1583   GstCaps *sink_caps, *src_caps;
1584   gboolean modified = FALSE;
1585   GstBuffer *buf = NULL;
1586   GstStructure *s = NULL;
1587 
1588   if (G_UNLIKELY (!gst_pad_has_current_caps (GST_BASE_PARSE_SRC_PAD
1589               (h265parse))))
1590     modified = TRUE;
1591   else if (G_UNLIKELY (!h265parse->update_caps))
1592     return;
1593 
1594   /* if this is being called from the first _setcaps call, caps on the sinkpad
1595    * aren't set yet and so they need to be passed as an argument */
1596   if (caps)
1597     sink_caps = gst_caps_ref (caps);
1598   else
1599     sink_caps = gst_pad_get_current_caps (GST_BASE_PARSE_SINK_PAD (h265parse));
1600 
1601   /* carry over input caps as much as possible; override with our own stuff */
1602   if (!sink_caps)
1603     sink_caps = gst_caps_new_empty_simple ("video/x-h265");
1604   else
1605     s = gst_caps_get_structure (sink_caps, 0);
1606 
1607   sps = h265parse->nalparser->last_sps;
1608   GST_DEBUG_OBJECT (h265parse, "sps: %p", sps);
1609 
1610   /* only codec-data for nice-and-clean au aligned packetized hevc format */
1611   if ((h265parse->format == GST_H265_PARSE_FORMAT_HVC1
1612           || h265parse->format == GST_H265_PARSE_FORMAT_HEV1)
1613       && h265parse->align == GST_H265_PARSE_ALIGN_AU) {
1614     buf = gst_h265_parse_make_codec_data (h265parse);
1615     if (buf && h265parse->codec_data) {
1616       GstMapInfo map;
1617 
1618       gst_buffer_map (buf, &map, GST_MAP_READ);
1619       if (map.size != gst_buffer_get_size (h265parse->codec_data) ||
1620           gst_buffer_memcmp (h265parse->codec_data, 0, map.data, map.size))
1621         modified = TRUE;
1622 
1623       gst_buffer_unmap (buf, &map);
1624     } else {
1625       if (!buf && h265parse->codec_data_in)
1626         buf = gst_buffer_ref (h265parse->codec_data_in);
1627       modified = TRUE;
1628     }
1629   }
1630 
1631   caps = NULL;
1632   if (G_UNLIKELY (!sps)) {
1633     caps = gst_caps_copy (sink_caps);
1634   } else {
1635     gint crop_width, crop_height;
1636     const gchar *chroma_format = NULL;
1637     guint bit_depth_chroma;
1638 
1639     if (sps->conformance_window_flag) {
1640       crop_width = sps->crop_rect_width;
1641       crop_height = sps->crop_rect_height;
1642     } else {
1643       crop_width = sps->width;
1644       crop_height = sps->height;
1645     }
1646 
1647     if (G_UNLIKELY (h265parse->width != crop_width ||
1648             h265parse->height != crop_height)) {
1649       GST_INFO_OBJECT (h265parse, "resolution changed %dx%d",
1650           crop_width, crop_height);
1651       h265parse->width = crop_width;
1652       h265parse->height = crop_height;
1653       modified = TRUE;
1654     }
1655 
1656     /* 0/1 is set as the default in the codec parser */
1657     if (sps->vui_params.timing_info_present_flag &&
1658         !(sps->fps_num == 0 && sps->fps_den == 1)) {
1659       if (G_UNLIKELY (h265parse->fps_num != sps->fps_num
1660               || h265parse->fps_den != sps->fps_den)) {
1661         GST_INFO_OBJECT (h265parse, "framerate changed %d/%d",
1662             sps->fps_num, sps->fps_den);
1663         h265parse->fps_num = sps->fps_num;
1664         h265parse->fps_den = sps->fps_den;
1665         modified = TRUE;
1666       }
1667     }
1668 
1669     if (sps->vui_params.aspect_ratio_info_present_flag) {
1670       if (G_UNLIKELY ((h265parse->parsed_par_n != sps->vui_params.par_n)
1671               && (h265parse->parsed_par_d != sps->vui_params.par_d))) {
1672         h265parse->parsed_par_n = sps->vui_params.par_n;
1673         h265parse->parsed_par_d = sps->vui_params.par_d;
1674         GST_INFO_OBJECT (h265parse, "pixel aspect ratio has been changed %d/%d",
1675             h265parse->parsed_par_n, h265parse->parsed_par_d);
1676         modified = TRUE;
1677       }
1678 
1679     }
1680 
1681     if (G_UNLIKELY (modified || h265parse->update_caps)) {
1682       gint fps_num = h265parse->fps_num;
1683       gint fps_den = h265parse->fps_den;
1684       gint width, height;
1685       GstClockTime latency;
1686 
1687       caps = gst_caps_copy (sink_caps);
1688 
1689       /* sps should give this but upstream overrides */
1690       if (s && gst_structure_has_field (s, "width"))
1691         gst_structure_get_int (s, "width", &width);
1692       else
1693         width = h265parse->width;
1694 
1695       if (s && gst_structure_has_field (s, "height"))
1696         gst_structure_get_int (s, "height", &height);
1697       else
1698         height = h265parse->height;
1699 
1700       gst_caps_set_simple (caps, "width", G_TYPE_INT, width,
1701           "height", G_TYPE_INT, height, NULL);
1702 
1703       /* upstream overrides */
1704       if (s && gst_structure_has_field (s, "framerate"))
1705         gst_structure_get_fraction (s, "framerate", &fps_num, &fps_den);
1706 
1707       /* but not necessarily or reliably this */
1708       if (fps_num > 0 && fps_den > 0) {
1709         GstStructure *s2;
1710         GST_INFO_OBJECT (h265parse, "setting framerate in caps");
1711         gst_caps_set_simple (caps, "framerate",
1712             GST_TYPE_FRACTION, fps_num, fps_den, NULL);
1713         s2 = gst_caps_get_structure (caps, 0);
1714         gst_structure_get_fraction (s2, "framerate", &h265parse->parsed_fps_n,
1715             &h265parse->parsed_fps_d);
1716         gst_base_parse_set_frame_rate (GST_BASE_PARSE (h265parse),
1717             fps_num, fps_den, 0, 0);
1718         latency = gst_util_uint64_scale (GST_SECOND, fps_den, fps_num);
1719         gst_base_parse_set_latency (GST_BASE_PARSE (h265parse), latency,
1720             latency);
1721       }
1722 
1723       bit_depth_chroma = sps->bit_depth_chroma_minus8 + 8;
1724 
1725       switch (sps->chroma_format_idc) {
1726         case 0:
1727           chroma_format = "4:0:0";
1728           bit_depth_chroma = 0;
1729           break;
1730         case 1:
1731           chroma_format = "4:2:0";
1732           break;
1733         case 2:
1734           chroma_format = "4:2:2";
1735           break;
1736         case 3:
1737           chroma_format = "4:4:4";
1738           break;
1739         default:
1740           break;
1741       }
1742 
1743       if (chroma_format)
1744         gst_caps_set_simple (caps, "chroma-format", G_TYPE_STRING,
1745             chroma_format, "bit-depth-luma", G_TYPE_UINT,
1746             sps->bit_depth_luma_minus8 + 8, "bit-depth-chroma", G_TYPE_UINT,
1747             bit_depth_chroma, NULL);
1748     }
1749   }
1750 
1751   if (caps) {
1752     gint par_n, par_d;
1753 
1754     gst_caps_set_simple (caps, "parsed", G_TYPE_BOOLEAN, TRUE,
1755         "stream-format", G_TYPE_STRING,
1756         gst_h265_parse_get_string (h265parse, TRUE, h265parse->format),
1757         "alignment", G_TYPE_STRING,
1758         gst_h265_parse_get_string (h265parse, FALSE, h265parse->align), NULL);
1759 
1760     gst_h265_parse_get_par (h265parse, &par_n, &par_d);
1761     if (par_n != 0 && par_d != 0 &&
1762         (!s || !gst_structure_has_field (s, "pixel-aspect-ratio"))) {
1763       GST_INFO_OBJECT (h265parse, "PAR %d/%d", par_n, par_d);
1764       gst_caps_set_simple (caps, "pixel-aspect-ratio", GST_TYPE_FRACTION,
1765           par_n, par_d, NULL);
1766     }
1767 
1768     /* set profile and level in caps */
1769     if (sps) {
1770       const gchar *profile, *tier, *level;
1771       GstH265Profile p;
1772 
1773       p = gst_h265_profile_tier_level_get_profile (&sps->profile_tier_level);
1774       profile = get_profile_string (p);
1775       if (profile != NULL)
1776         gst_caps_set_simple (caps, "profile", G_TYPE_STRING, profile, NULL);
1777 
1778       tier = get_tier_string (sps->profile_tier_level.tier_flag);
1779       if (tier != NULL)
1780         gst_caps_set_simple (caps, "tier", G_TYPE_STRING, tier, NULL);
1781 
1782       level = get_level_string (sps->profile_tier_level.level_idc);
1783       if (level != NULL)
1784         gst_caps_set_simple (caps, "level", G_TYPE_STRING, level, NULL);
1785 
1786       /* relax the profile constraint to find a suitable decoder */
1787       ensure_caps_profile (h265parse, caps, sps);
1788     }
1789 
1790     src_caps = gst_pad_get_current_caps (GST_BASE_PARSE_SRC_PAD (h265parse));
1791 
1792     if (src_caps) {
1793       /* use codec data from old caps for comparison; we don't want to resend caps
1794          if everything is same except codec data; */
1795       if (gst_structure_has_field (gst_caps_get_structure (src_caps, 0),
1796               "codec_data")) {
1797         gst_caps_set_value (caps, "codec_data",
1798             gst_structure_get_value (gst_caps_get_structure (src_caps, 0),
1799                 "codec_data"));
1800       } else if (!buf) {
1801         GstStructure *s;
1802         /* remove any left-over codec-data hanging around */
1803         s = gst_caps_get_structure (caps, 0);
1804         gst_structure_remove_field (s, "codec_data");
1805       }
1806     }
1807 
1808     if (!(src_caps && gst_caps_is_strictly_equal (src_caps, caps))) {
1809       /* update codec data to new value */
1810       if (buf) {
1811         gst_caps_set_simple (caps, "codec_data", GST_TYPE_BUFFER, buf, NULL);
1812         gst_buffer_replace (&h265parse->codec_data, buf);
1813         gst_buffer_unref (buf);
1814         buf = NULL;
1815       } else {
1816         GstStructure *s;
1817         /* remove any left-over codec-data hanging around */
1818         s = gst_caps_get_structure (caps, 0);
1819         gst_structure_remove_field (s, "codec_data");
1820         gst_buffer_replace (&h265parse->codec_data, NULL);
1821       }
1822 
1823       gst_pad_set_caps (GST_BASE_PARSE_SRC_PAD (h265parse), caps);
1824     }
1825 
1826     if (src_caps)
1827       gst_caps_unref (src_caps);
1828     gst_caps_unref (caps);
1829   }
1830 
1831   gst_caps_unref (sink_caps);
1832   if (buf)
1833     gst_buffer_unref (buf);
1834 
1835 }
1836 
1837 static GstFlowReturn
gst_h265_parse_parse_frame(GstBaseParse * parse,GstBaseParseFrame * frame)1838 gst_h265_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
1839 {
1840   GstH265Parse *h265parse;
1841   GstBuffer *buffer;
1842   guint av;
1843 
1844   h265parse = GST_H265_PARSE (parse);
1845   buffer = frame->buffer;
1846 
1847   gst_h265_parse_update_src_caps (h265parse, NULL);
1848 
1849   /* Fixme: Implement timestamp interpolation based on SEI Messagses */
1850   GST_FIXME_OBJECT (h265parse,
1851       "Implement timestamp/duration interpolation based on SEI message");
1852 
1853   if (h265parse->keyframe)
1854     GST_BUFFER_FLAG_UNSET (buffer, GST_BUFFER_FLAG_DELTA_UNIT);
1855   else
1856     GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT);
1857 
1858   if (h265parse->header)
1859     GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_HEADER);
1860   else
1861     GST_BUFFER_FLAG_UNSET (buffer, GST_BUFFER_FLAG_HEADER);
1862 
1863   if (h265parse->discont) {
1864     GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
1865     h265parse->discont = FALSE;
1866   }
1867 
1868   /* replace with transformed HEVC output if applicable */
1869   av = gst_adapter_available (h265parse->frame_out);
1870   if (av) {
1871     GstBuffer *buf;
1872 
1873     buf = gst_adapter_take_buffer (h265parse->frame_out, av);
1874     gst_buffer_copy_into (buf, buffer, GST_BUFFER_COPY_METADATA, 0, -1);
1875     gst_buffer_replace (&frame->out_buffer, buf);
1876     gst_buffer_unref (buf);
1877   }
1878 
1879   return GST_FLOW_OK;
1880 }
1881 
1882 /* sends a codec NAL downstream, decorating and transforming as needed.
1883  * No ownership is taken of @nal */
1884 static GstFlowReturn
gst_h265_parse_push_codec_buffer(GstH265Parse * h265parse,GstBuffer * nal,GstClockTime ts)1885 gst_h265_parse_push_codec_buffer (GstH265Parse * h265parse, GstBuffer * nal,
1886     GstClockTime ts)
1887 {
1888   GstMapInfo map;
1889 
1890   gst_buffer_map (nal, &map, GST_MAP_READ);
1891   nal = gst_h265_parse_wrap_nal (h265parse, h265parse->format,
1892       map.data, map.size);
1893   gst_buffer_unmap (nal, &map);
1894 
1895   GST_BUFFER_TIMESTAMP (nal) = ts;
1896   GST_BUFFER_DURATION (nal) = 0;
1897 
1898   return gst_pad_push (GST_BASE_PARSE_SRC_PAD (h265parse), nal);
1899 }
1900 
1901 static GstEvent *
check_pending_key_unit_event(GstEvent * pending_event,GstSegment * segment,GstClockTime timestamp,guint flags,GstClockTime pending_key_unit_ts)1902 check_pending_key_unit_event (GstEvent * pending_event, GstSegment * segment,
1903     GstClockTime timestamp, guint flags, GstClockTime pending_key_unit_ts)
1904 {
1905   GstClockTime running_time, stream_time;
1906   gboolean all_headers;
1907   guint count;
1908   GstEvent *event = NULL;
1909 
1910   g_return_val_if_fail (segment != NULL, NULL);
1911 
1912   if (pending_event == NULL)
1913     goto out;
1914 
1915   if (GST_CLOCK_TIME_IS_VALID (pending_key_unit_ts) &&
1916       timestamp == GST_CLOCK_TIME_NONE)
1917     goto out;
1918 
1919   running_time = gst_segment_to_running_time (segment,
1920       GST_FORMAT_TIME, timestamp);
1921 
1922   GST_INFO ("now %" GST_TIME_FORMAT " wanted %" GST_TIME_FORMAT,
1923       GST_TIME_ARGS (running_time), GST_TIME_ARGS (pending_key_unit_ts));
1924   if (GST_CLOCK_TIME_IS_VALID (pending_key_unit_ts) &&
1925       running_time < pending_key_unit_ts)
1926     goto out;
1927 
1928   if (flags & GST_BUFFER_FLAG_DELTA_UNIT) {
1929     GST_DEBUG ("pending force key unit, waiting for keyframe");
1930     goto out;
1931   }
1932 
1933   stream_time = gst_segment_to_stream_time (segment,
1934       GST_FORMAT_TIME, timestamp);
1935 
1936   if (!gst_video_event_parse_upstream_force_key_unit (pending_event,
1937           NULL, &all_headers, &count)) {
1938     gst_video_event_parse_downstream_force_key_unit (pending_event, NULL,
1939         NULL, NULL, &all_headers, &count);
1940   }
1941 
1942   event =
1943       gst_video_event_new_downstream_force_key_unit (timestamp, stream_time,
1944       running_time, all_headers, count);
1945   gst_event_set_seqnum (event, gst_event_get_seqnum (pending_event));
1946 
1947 out:
1948   return event;
1949 }
1950 
1951 static void
gst_h265_parse_prepare_key_unit(GstH265Parse * parse,GstEvent * event)1952 gst_h265_parse_prepare_key_unit (GstH265Parse * parse, GstEvent * event)
1953 {
1954   GstClockTime running_time;
1955   guint count;
1956 #ifndef GST_DISABLE_GST_DEBUG
1957   gboolean have_vps, have_sps, have_pps;
1958   gint i;
1959 #endif
1960 
1961   parse->pending_key_unit_ts = GST_CLOCK_TIME_NONE;
1962   gst_event_replace (&parse->force_key_unit_event, NULL);
1963 
1964   gst_video_event_parse_downstream_force_key_unit (event,
1965       NULL, NULL, &running_time, NULL, &count);
1966 
1967   GST_INFO_OBJECT (parse, "pushing downstream force-key-unit event %d "
1968       "%" GST_TIME_FORMAT " count %d", gst_event_get_seqnum (event),
1969       GST_TIME_ARGS (running_time), count);
1970   gst_pad_push_event (GST_BASE_PARSE_SRC_PAD (parse), event);
1971 
1972 #ifndef GST_DISABLE_GST_DEBUG
1973   have_vps = have_sps = have_pps = FALSE;
1974   for (i = 0; i < GST_H265_MAX_VPS_COUNT; i++) {
1975     if (parse->vps_nals[i] != NULL) {
1976       have_vps = TRUE;
1977       break;
1978     }
1979   }
1980   for (i = 0; i < GST_H265_MAX_SPS_COUNT; i++) {
1981     if (parse->sps_nals[i] != NULL) {
1982       have_sps = TRUE;
1983       break;
1984     }
1985   }
1986   for (i = 0; i < GST_H265_MAX_PPS_COUNT; i++) {
1987     if (parse->pps_nals[i] != NULL) {
1988       have_pps = TRUE;
1989       break;
1990     }
1991   }
1992 
1993   GST_INFO_OBJECT (parse,
1994       "preparing key unit, have vps %d have sps %d have pps %d", have_vps,
1995       have_sps, have_pps);
1996 #endif
1997 
1998   /* set push_codec to TRUE so that pre_push_frame sends VPS/SPS/PPS again */
1999   parse->push_codec = TRUE;
2000 }
2001 
2002 static gboolean
gst_h265_parse_handle_vps_sps_pps_nals(GstH265Parse * h265parse,GstBuffer * buffer,GstBaseParseFrame * frame)2003 gst_h265_parse_handle_vps_sps_pps_nals (GstH265Parse * h265parse,
2004     GstBuffer * buffer, GstBaseParseFrame * frame)
2005 {
2006   GstBuffer *codec_nal;
2007   gint i;
2008   gboolean send_done = FALSE;
2009   GstClockTime timestamp = GST_BUFFER_TIMESTAMP (buffer);
2010 
2011   if (h265parse->have_vps_in_frame && h265parse->have_sps_in_frame
2012       && h265parse->have_pps_in_frame) {
2013     GST_DEBUG_OBJECT (h265parse, "VPS/SPS/PPS exist in frame, will not insert");
2014     return TRUE;
2015   }
2016 
2017   if (h265parse->align == GST_H265_PARSE_ALIGN_NAL) {
2018     /* send separate config NAL buffers */
2019     GST_DEBUG_OBJECT (h265parse, "- sending VPS/SPS/PPS");
2020     for (i = 0; i < GST_H265_MAX_VPS_COUNT; i++) {
2021       if ((codec_nal = h265parse->vps_nals[i])) {
2022         GST_DEBUG_OBJECT (h265parse, "sending VPS nal");
2023         gst_h265_parse_push_codec_buffer (h265parse, codec_nal, timestamp);
2024         send_done = TRUE;
2025       }
2026     }
2027     for (i = 0; i < GST_H265_MAX_SPS_COUNT; i++) {
2028       if ((codec_nal = h265parse->sps_nals[i])) {
2029         GST_DEBUG_OBJECT (h265parse, "sending SPS nal");
2030         gst_h265_parse_push_codec_buffer (h265parse, codec_nal, timestamp);
2031         send_done = TRUE;
2032       }
2033     }
2034     for (i = 0; i < GST_H265_MAX_PPS_COUNT; i++) {
2035       if ((codec_nal = h265parse->pps_nals[i])) {
2036         GST_DEBUG_OBJECT (h265parse, "sending PPS nal");
2037         gst_h265_parse_push_codec_buffer (h265parse, codec_nal, timestamp);
2038         send_done = TRUE;
2039       }
2040     }
2041   } else {
2042     /* insert config NALs into AU */
2043     GstByteWriter bw;
2044     GstBuffer *new_buf;
2045     const gboolean bs = h265parse->format == GST_H265_PARSE_FORMAT_BYTE;
2046     const gint nls = 4 - h265parse->nal_length_size;
2047     gboolean ok;
2048 
2049     gst_byte_writer_init_with_size (&bw, gst_buffer_get_size (buffer), FALSE);
2050     ok = gst_byte_writer_put_buffer (&bw, buffer, 0, h265parse->idr_pos);
2051     GST_DEBUG_OBJECT (h265parse, "- inserting VPS/SPS/PPS");
2052     for (i = 0; i < GST_H265_MAX_VPS_COUNT; i++) {
2053       if ((codec_nal = h265parse->vps_nals[i])) {
2054         gsize nal_size = gst_buffer_get_size (codec_nal);
2055         GST_DEBUG_OBJECT (h265parse, "inserting VPS nal");
2056         if (bs) {
2057           ok &= gst_byte_writer_put_uint32_be (&bw, 1);
2058         } else {
2059           ok &= gst_byte_writer_put_uint32_be (&bw, (nal_size << (nls * 8)));
2060           ok &= gst_byte_writer_set_pos (&bw,
2061               gst_byte_writer_get_pos (&bw) - nls);
2062         }
2063 
2064         ok &= gst_byte_writer_put_buffer (&bw, codec_nal, 0, nal_size);
2065         send_done = TRUE;
2066       }
2067     }
2068     for (i = 0; i < GST_H265_MAX_SPS_COUNT; i++) {
2069       if ((codec_nal = h265parse->sps_nals[i])) {
2070         gsize nal_size = gst_buffer_get_size (codec_nal);
2071         GST_DEBUG_OBJECT (h265parse, "inserting SPS nal");
2072         if (bs) {
2073           ok &= gst_byte_writer_put_uint32_be (&bw, 1);
2074         } else {
2075           ok &= gst_byte_writer_put_uint32_be (&bw, (nal_size << (nls * 8)));
2076           ok &= gst_byte_writer_set_pos (&bw,
2077               gst_byte_writer_get_pos (&bw) - nls);
2078         }
2079 
2080         ok &= gst_byte_writer_put_buffer (&bw, codec_nal, 0, nal_size);
2081         send_done = TRUE;
2082       }
2083     }
2084     for (i = 0; i < GST_H265_MAX_PPS_COUNT; i++) {
2085       if ((codec_nal = h265parse->pps_nals[i])) {
2086         gsize nal_size = gst_buffer_get_size (codec_nal);
2087         GST_DEBUG_OBJECT (h265parse, "inserting PPS nal");
2088         if (bs) {
2089           ok &= gst_byte_writer_put_uint32_be (&bw, 1);
2090         } else {
2091           ok &= gst_byte_writer_put_uint32_be (&bw, (nal_size << (nls * 8)));
2092           ok &= gst_byte_writer_set_pos (&bw,
2093               gst_byte_writer_get_pos (&bw) - nls);
2094         }
2095         ok &= gst_byte_writer_put_buffer (&bw, codec_nal, 0, nal_size);
2096         send_done = TRUE;
2097       }
2098     }
2099     ok &= gst_byte_writer_put_buffer (&bw, buffer, h265parse->idr_pos, -1);
2100     /* collect result and push */
2101     new_buf = gst_byte_writer_reset_and_get_buffer (&bw);
2102     gst_buffer_copy_into (new_buf, buffer, GST_BUFFER_COPY_METADATA, 0, -1);
2103     /* should already be keyframe/IDR, but it may not have been,
2104      * so mark it as such to avoid being discarded by picky decoder */
2105     GST_BUFFER_FLAG_UNSET (new_buf, GST_BUFFER_FLAG_DELTA_UNIT);
2106     gst_buffer_replace (&frame->out_buffer, new_buf);
2107     gst_buffer_unref (new_buf);
2108     /* some result checking seems to make some compilers happy */
2109     if (G_UNLIKELY (!ok)) {
2110       GST_ERROR_OBJECT (h265parse, "failed to insert SPS/PPS");
2111     }
2112   }
2113 
2114   return send_done;
2115 }
2116 
2117 static GstFlowReturn
gst_h265_parse_pre_push_frame(GstBaseParse * parse,GstBaseParseFrame * frame)2118 gst_h265_parse_pre_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
2119 {
2120   GstH265Parse *h265parse;
2121   GstBuffer *buffer;
2122   GstEvent *event;
2123 
2124   h265parse = GST_H265_PARSE (parse);
2125 
2126   if (!h265parse->sent_codec_tag) {
2127     GstTagList *taglist;
2128     GstCaps *caps;
2129 
2130     /* codec tag */
2131     caps = gst_pad_get_current_caps (GST_BASE_PARSE_SRC_PAD (parse));
2132     if (G_UNLIKELY (caps == NULL)) {
2133       if (GST_PAD_IS_FLUSHING (GST_BASE_PARSE_SRC_PAD (parse))) {
2134         GST_INFO_OBJECT (parse, "Src pad is flushing");
2135         return GST_FLOW_FLUSHING;
2136       } else {
2137         GST_INFO_OBJECT (parse, "Src pad is not negotiated!");
2138         return GST_FLOW_NOT_NEGOTIATED;
2139       }
2140     }
2141 
2142     taglist = gst_tag_list_new_empty ();
2143     gst_pb_utils_add_codec_description_to_tag_list (taglist,
2144         GST_TAG_VIDEO_CODEC, caps);
2145     gst_caps_unref (caps);
2146 
2147     gst_base_parse_merge_tags (parse, taglist, GST_TAG_MERGE_REPLACE);
2148     gst_tag_list_unref (taglist);
2149 
2150     /* also signals the end of first-frame processing */
2151     h265parse->sent_codec_tag = TRUE;
2152   }
2153 
2154   buffer = frame->buffer;
2155 
2156   if ((event = check_pending_key_unit_event (h265parse->force_key_unit_event,
2157               &parse->segment, GST_BUFFER_TIMESTAMP (buffer),
2158               GST_BUFFER_FLAGS (buffer), h265parse->pending_key_unit_ts))) {
2159     gst_h265_parse_prepare_key_unit (h265parse, event);
2160   }
2161 
2162   /* periodic VPS/SPS/PPS sending */
2163   if (h265parse->interval > 0 || h265parse->push_codec) {
2164     GstClockTime timestamp = GST_BUFFER_TIMESTAMP (buffer);
2165     guint64 diff;
2166     gboolean initial_frame = FALSE;
2167 
2168     /* init */
2169     if (!GST_CLOCK_TIME_IS_VALID (h265parse->last_report)) {
2170       h265parse->last_report = timestamp;
2171       initial_frame = TRUE;
2172     }
2173 
2174     if (h265parse->idr_pos >= 0) {
2175       GST_LOG_OBJECT (h265parse, "IDR nal at offset %d", h265parse->idr_pos);
2176 
2177       if (timestamp > h265parse->last_report)
2178         diff = timestamp - h265parse->last_report;
2179       else
2180         diff = 0;
2181 
2182       GST_LOG_OBJECT (h265parse,
2183           "now %" GST_TIME_FORMAT ", last VPS/SPS/PPS %" GST_TIME_FORMAT,
2184           GST_TIME_ARGS (timestamp), GST_TIME_ARGS (h265parse->last_report));
2185 
2186       GST_DEBUG_OBJECT (h265parse,
2187           "interval since last VPS/SPS/PPS %" GST_TIME_FORMAT,
2188           GST_TIME_ARGS (diff));
2189 
2190       if (GST_TIME_AS_SECONDS (diff) >= h265parse->interval ||
2191           initial_frame || h265parse->push_codec) {
2192         GstClockTime new_ts;
2193 
2194         /* avoid overwriting a perfectly fine timestamp */
2195         new_ts = GST_CLOCK_TIME_IS_VALID (timestamp) ? timestamp :
2196             h265parse->last_report;
2197 
2198         if (gst_h265_parse_handle_vps_sps_pps_nals (h265parse, buffer, frame)) {
2199           h265parse->last_report = new_ts;
2200         }
2201       }
2202 
2203       /* we pushed whatever we had */
2204       h265parse->push_codec = FALSE;
2205       h265parse->have_vps = FALSE;
2206       h265parse->have_sps = FALSE;
2207       h265parse->have_pps = FALSE;
2208       h265parse->state &= GST_H265_PARSE_STATE_VALID_PICTURE_HEADERS;
2209     }
2210   } else if (h265parse->interval == -1) {
2211     if (h265parse->idr_pos >= 0) {
2212       GST_LOG_OBJECT (h265parse, "IDR nal at offset %d", h265parse->idr_pos);
2213 
2214       gst_h265_parse_handle_vps_sps_pps_nals (h265parse, buffer, frame);
2215 
2216       /* we pushed whatever we had */
2217       h265parse->push_codec = FALSE;
2218       h265parse->have_vps = FALSE;
2219       h265parse->have_sps = FALSE;
2220       h265parse->have_pps = FALSE;
2221       h265parse->state &= GST_H265_PARSE_STATE_VALID_PICTURE_HEADERS;
2222     }
2223   }
2224 
2225   {
2226     guint i = 0;
2227 
2228     for (i = 0; i < h265parse->time_code.num_clock_ts; i++) {
2229       GstVideoTimeCodeFlags flags = 0;
2230       gint field_count = -1;
2231       guint n_frames;
2232 
2233       if (!h265parse->time_code.clock_timestamp_flag[i])
2234         break;
2235 
2236       h265parse->time_code.clock_timestamp_flag[i] = 0;
2237 
2238       /* Table D.2 */
2239       switch (h265parse->sei_pic_struct) {
2240         case GST_H265_SEI_PIC_STRUCT_FRAME:
2241         case GST_H265_SEI_PIC_STRUCT_TOP_FIELD:
2242         case GST_H265_SEI_PIC_STRUCT_BOTTOM_FIELD:
2243           field_count = h265parse->sei_pic_struct;
2244           break;
2245         case GST_H265_SEI_PIC_STRUCT_TOP_BOTTOM:
2246         case GST_H265_SEI_PIC_STRUCT_TOP_PAIRED_PREVIOUS_BOTTOM:
2247         case GST_H265_SEI_PIC_STRUCT_TOP_PAIRED_NEXT_BOTTOM:
2248           field_count = i + 1;
2249           break;
2250         case GST_H265_SEI_PIC_STRUCT_BOTTOM_TOP:
2251         case GST_H265_SEI_PIC_STRUCT_BOTTOM_PAIRED_PREVIOUS_TOP:
2252         case GST_H265_SEI_PIC_STRUCT_BOTTOM_PAIRED_NEXT_TOP:
2253           field_count = 2 - i;
2254           break;
2255         case GST_H265_SEI_PIC_STRUCT_TOP_BOTTOM_TOP:
2256           field_count = i % 2 ? 2 : 1;
2257           break;
2258         case GST_H265_SEI_PIC_STRUCT_BOTTOM_TOP_BOTTOM:
2259           field_count = i % 2 ? 1 : 2;
2260           break;
2261         case GST_H265_SEI_PIC_STRUCT_FRAME_DOUBLING:
2262         case GST_H265_SEI_PIC_STRUCT_FRAME_TRIPLING:
2263           field_count = 0;
2264           break;
2265       }
2266 
2267       if (field_count == -1) {
2268         GST_WARNING_OBJECT (parse,
2269             "failed to determine field count for timecode");
2270         field_count = 0;
2271       }
2272 
2273       /* Dropping of the two lowest (value 0 and 1) n_frames[ i ] counts when
2274        * seconds_value[ i ] is equal to 0 and minutes_value[ i ] is not an integer
2275        * multiple of 10 */
2276       if (h265parse->time_code.counting_type[i] == 4)
2277         flags |= GST_VIDEO_TIME_CODE_FLAGS_DROP_FRAME;
2278 
2279       if (h265parse->sei_pic_struct != GST_H265_SEI_PIC_STRUCT_FRAME)
2280         flags |= GST_VIDEO_TIME_CODE_FLAGS_INTERLACED;
2281 
2282       n_frames =
2283           gst_util_uint64_scale_int (h265parse->time_code.n_frames[i], 1,
2284           2 - h265parse->time_code.units_field_based_flag[i]);
2285 
2286       gst_buffer_add_video_time_code_meta_full (buffer,
2287           h265parse->parsed_fps_n,
2288           h265parse->parsed_fps_d,
2289           NULL,
2290           flags,
2291           h265parse->time_code.hours_flag[i] ? h265parse->
2292           time_code.hours_value[i] : 0,
2293           h265parse->time_code.minutes_flag[i] ? h265parse->
2294           time_code.minutes_value[i] : 0,
2295           h265parse->time_code.seconds_flag[i] ? h265parse->
2296           time_code.seconds_value[i] : 0, n_frames, field_count);
2297     }
2298   }
2299 
2300   gst_h265_parse_reset_frame (h265parse);
2301 
2302   return GST_FLOW_OK;
2303 }
2304 
2305 static gboolean
gst_h265_parse_set_caps(GstBaseParse * parse,GstCaps * caps)2306 gst_h265_parse_set_caps (GstBaseParse * parse, GstCaps * caps)
2307 {
2308   GstH265Parse *h265parse;
2309   GstStructure *str;
2310   const GValue *value;
2311   GstBuffer *codec_data = NULL;
2312   gsize off, size;
2313   guint format, align;
2314   guint num_nals, i, j;
2315   GstH265NalUnit nalu;
2316   GstH265ParserResult parseres;
2317   GstCaps *old_caps;
2318 
2319   h265parse = GST_H265_PARSE (parse);
2320 
2321   /* reset */
2322   h265parse->push_codec = FALSE;
2323 
2324   old_caps = gst_pad_get_current_caps (GST_BASE_PARSE_SINK_PAD (parse));
2325   if (old_caps) {
2326     if (!gst_caps_is_equal (old_caps, caps))
2327       gst_h265_parse_reset_stream_info (h265parse);
2328     gst_caps_unref (old_caps);
2329   }
2330 
2331   str = gst_caps_get_structure (caps, 0);
2332 
2333   /* accept upstream info if provided */
2334   gst_structure_get_int (str, "width", &h265parse->width);
2335   gst_structure_get_int (str, "height", &h265parse->height);
2336   gst_structure_get_fraction (str, "framerate", &h265parse->fps_num,
2337       &h265parse->fps_den);
2338   gst_structure_get_fraction (str, "pixel-aspect-ratio",
2339       &h265parse->upstream_par_n, &h265parse->upstream_par_d);
2340 
2341   /* get upstream format and align from caps */
2342   gst_h265_parse_format_from_caps (caps, &format, &align);
2343 
2344   /* packetized video has a codec_data */
2345   if (format != GST_H265_PARSE_FORMAT_BYTE &&
2346       (value = gst_structure_get_value (str, "codec_data"))) {
2347     GstMapInfo map;
2348     guint8 *data;
2349     guint num_nal_arrays;
2350 
2351     GST_DEBUG_OBJECT (h265parse, "have packetized h265");
2352     /* make note for optional split processing */
2353     h265parse->packetized = TRUE;
2354 
2355     codec_data = gst_value_get_buffer (value);
2356     if (!codec_data)
2357       goto wrong_type;
2358     gst_buffer_map (codec_data, &map, GST_MAP_READ);
2359     data = map.data;
2360     size = map.size;
2361 
2362     /* parse the hvcC data */
2363     if (size < 23) {
2364       gst_buffer_unmap (codec_data, &map);
2365       goto hvcc_too_small;
2366     }
2367     /* parse the version, this must be one but
2368      * is zero until the spec is finalized */
2369     if (data[0] != 0 && data[0] != 1) {
2370       gst_buffer_unmap (codec_data, &map);
2371       goto wrong_version;
2372     }
2373 
2374     h265parse->nal_length_size = (data[21] & 0x03) + 1;
2375     GST_DEBUG_OBJECT (h265parse, "nal length size %u",
2376         h265parse->nal_length_size);
2377 
2378     num_nal_arrays = data[22];
2379     off = 23;
2380 
2381     for (i = 0; i < num_nal_arrays; i++) {
2382       if (off + 3 >= size) {
2383         gst_buffer_unmap (codec_data, &map);
2384         goto hvcc_too_small;
2385       }
2386 
2387       num_nals = GST_READ_UINT16_BE (data + off + 1);
2388       off += 3;
2389       for (j = 0; j < num_nals; j++) {
2390         parseres = gst_h265_parser_identify_nalu_hevc (h265parse->nalparser,
2391             data, off, size, 2, &nalu);
2392 
2393         if (parseres != GST_H265_PARSER_OK) {
2394           gst_buffer_unmap (codec_data, &map);
2395           goto hvcc_too_small;
2396         }
2397 
2398         gst_h265_parse_process_nal (h265parse, &nalu);
2399         off = nalu.offset + nalu.size;
2400       }
2401     }
2402     gst_buffer_unmap (codec_data, &map);
2403 
2404     /* don't confuse codec_data with inband vps/sps/pps */
2405     h265parse->have_vps_in_frame = FALSE;
2406     h265parse->have_sps_in_frame = FALSE;
2407     h265parse->have_pps_in_frame = FALSE;
2408   } else {
2409     GST_DEBUG_OBJECT (h265parse, "have bytestream h265");
2410     /* nothing to pre-process */
2411     h265parse->packetized = FALSE;
2412     /* we have 4 sync bytes */
2413     h265parse->nal_length_size = 4;
2414 
2415     if (format == GST_H265_PARSE_FORMAT_NONE) {
2416       format = GST_H265_PARSE_FORMAT_BYTE;
2417       align = GST_H265_PARSE_ALIGN_AU;
2418     }
2419   }
2420 
2421   {
2422     GstCaps *in_caps;
2423 
2424     /* prefer input type determined above */
2425     in_caps = gst_caps_new_simple ("video/x-h265",
2426         "parsed", G_TYPE_BOOLEAN, TRUE,
2427         "stream-format", G_TYPE_STRING,
2428         gst_h265_parse_get_string (h265parse, TRUE, format),
2429         "alignment", G_TYPE_STRING,
2430         gst_h265_parse_get_string (h265parse, FALSE, align), NULL);
2431     /* negotiate with downstream, sets ->format and ->align */
2432     gst_h265_parse_negotiate (h265parse, format, in_caps);
2433     gst_caps_unref (in_caps);
2434   }
2435 
2436   if (format == h265parse->format && align == h265parse->align) {
2437     /* do not set CAPS and passthrough mode if SPS/PPS have not been parsed */
2438     if (h265parse->have_sps && h265parse->have_pps) {
2439       gst_base_parse_set_passthrough (parse, TRUE);
2440 
2441       /* we did parse codec-data and might supplement src caps */
2442       gst_h265_parse_update_src_caps (h265parse, caps);
2443     }
2444   } else if (format == GST_H265_PARSE_FORMAT_HVC1
2445       || format == GST_H265_PARSE_FORMAT_HEV1) {
2446     /* if input != output, and input is hevc, must split before anything else */
2447     /* arrange to insert codec-data in-stream if needed.
2448      * src caps are only arranged for later on */
2449     h265parse->push_codec = TRUE;
2450     h265parse->have_vps = FALSE;
2451     h265parse->have_sps = FALSE;
2452     h265parse->have_pps = FALSE;
2453     if (h265parse->align == GST_H265_PARSE_ALIGN_NAL)
2454       h265parse->split_packetized = TRUE;
2455     h265parse->packetized = TRUE;
2456   }
2457 
2458   return TRUE;
2459 
2460   /* ERRORS */
2461 hvcc_too_small:
2462   {
2463     GST_DEBUG_OBJECT (h265parse, "hvcC size %" G_GSIZE_FORMAT " < 23", size);
2464     goto refuse_caps;
2465   }
2466 wrong_version:
2467   {
2468     GST_DEBUG_OBJECT (h265parse, "wrong hvcC version");
2469     goto refuse_caps;
2470   }
2471 wrong_type:
2472   {
2473     GST_DEBUG_OBJECT (h265parse, "wrong codec-data type");
2474     goto refuse_caps;
2475   }
2476 refuse_caps:
2477   {
2478     GST_WARNING_OBJECT (h265parse, "refused caps %" GST_PTR_FORMAT, caps);
2479     return FALSE;
2480   }
2481 }
2482 
2483 static void
remove_fields(GstCaps * caps,gboolean all)2484 remove_fields (GstCaps * caps, gboolean all)
2485 {
2486   guint i, n;
2487 
2488   n = gst_caps_get_size (caps);
2489   for (i = 0; i < n; i++) {
2490     GstStructure *s = gst_caps_get_structure (caps, i);
2491 
2492     if (all) {
2493       gst_structure_remove_field (s, "alignment");
2494       gst_structure_remove_field (s, "stream-format");
2495     }
2496     gst_structure_remove_field (s, "parsed");
2497   }
2498 }
2499 
2500 static GstCaps *
gst_h265_parse_get_caps(GstBaseParse * parse,GstCaps * filter)2501 gst_h265_parse_get_caps (GstBaseParse * parse, GstCaps * filter)
2502 {
2503   GstCaps *peercaps, *templ;
2504   GstCaps *res, *tmp, *pcopy;
2505 
2506   templ = gst_pad_get_pad_template_caps (GST_BASE_PARSE_SINK_PAD (parse));
2507   if (filter) {
2508     GstCaps *fcopy = gst_caps_copy (filter);
2509     /* Remove the fields we convert */
2510     remove_fields (fcopy, TRUE);
2511     peercaps = gst_pad_peer_query_caps (GST_BASE_PARSE_SRC_PAD (parse), fcopy);
2512     gst_caps_unref (fcopy);
2513   } else
2514     peercaps = gst_pad_peer_query_caps (GST_BASE_PARSE_SRC_PAD (parse), NULL);
2515 
2516   pcopy = gst_caps_copy (peercaps);
2517   remove_fields (pcopy, TRUE);
2518 
2519   res = gst_caps_intersect_full (pcopy, templ, GST_CAPS_INTERSECT_FIRST);
2520   gst_caps_unref (pcopy);
2521   gst_caps_unref (templ);
2522 
2523   if (filter) {
2524     GstCaps *tmp = gst_caps_intersect_full (res, filter,
2525         GST_CAPS_INTERSECT_FIRST);
2526     gst_caps_unref (res);
2527     res = tmp;
2528   }
2529 
2530   /* Try if we can put the downstream caps first */
2531   pcopy = gst_caps_copy (peercaps);
2532   remove_fields (pcopy, FALSE);
2533   tmp = gst_caps_intersect_full (pcopy, res, GST_CAPS_INTERSECT_FIRST);
2534   gst_caps_unref (pcopy);
2535   if (!gst_caps_is_empty (tmp))
2536     res = gst_caps_merge (tmp, res);
2537   else
2538     gst_caps_unref (tmp);
2539 
2540   gst_caps_unref (peercaps);
2541   return res;
2542 }
2543 
2544 static gboolean
gst_h265_parse_event(GstBaseParse * parse,GstEvent * event)2545 gst_h265_parse_event (GstBaseParse * parse, GstEvent * event)
2546 {
2547   gboolean res;
2548   GstH265Parse *h265parse = GST_H265_PARSE (parse);
2549 
2550   switch (GST_EVENT_TYPE (event)) {
2551     case GST_EVENT_CUSTOM_DOWNSTREAM:
2552     {
2553       GstClockTime timestamp, stream_time, running_time;
2554       gboolean all_headers;
2555       guint count;
2556 
2557       if (gst_video_event_is_force_key_unit (event)) {
2558         gst_video_event_parse_downstream_force_key_unit (event,
2559             &timestamp, &stream_time, &running_time, &all_headers, &count);
2560 
2561         GST_INFO_OBJECT (h265parse, "received downstream force key unit event, "
2562             "seqnum %d running_time %" GST_TIME_FORMAT
2563             " all_headers %d count %d", gst_event_get_seqnum (event),
2564             GST_TIME_ARGS (running_time), all_headers, count);
2565         if (h265parse->force_key_unit_event) {
2566           GST_INFO_OBJECT (h265parse, "ignoring force key unit event "
2567               "as one is already queued");
2568         } else {
2569           h265parse->pending_key_unit_ts = running_time;
2570           gst_event_replace (&h265parse->force_key_unit_event, event);
2571         }
2572         gst_event_unref (event);
2573         res = TRUE;
2574       } else {
2575         res = GST_BASE_PARSE_CLASS (parent_class)->sink_event (parse, event);
2576         break;
2577       }
2578       break;
2579     }
2580     case GST_EVENT_FLUSH_STOP:
2581       h265parse->push_codec = TRUE;
2582       res = GST_BASE_PARSE_CLASS (parent_class)->sink_event (parse, event);
2583       break;
2584     case GST_EVENT_SEGMENT:
2585     {
2586       h265parse->last_report = GST_CLOCK_TIME_NONE;
2587 
2588       res = GST_BASE_PARSE_CLASS (parent_class)->sink_event (parse, event);
2589       break;
2590     }
2591     default:
2592       res = GST_BASE_PARSE_CLASS (parent_class)->sink_event (parse, event);
2593       break;
2594   }
2595   return res;
2596 }
2597 
2598 static gboolean
gst_h265_parse_src_event(GstBaseParse * parse,GstEvent * event)2599 gst_h265_parse_src_event (GstBaseParse * parse, GstEvent * event)
2600 {
2601   gboolean res;
2602   GstH265Parse *h265parse = GST_H265_PARSE (parse);
2603 
2604   switch (GST_EVENT_TYPE (event)) {
2605     case GST_EVENT_CUSTOM_UPSTREAM:
2606     {
2607       GstClockTime running_time;
2608       gboolean all_headers;
2609       guint count;
2610 
2611       if (gst_video_event_is_force_key_unit (event)) {
2612         gst_video_event_parse_upstream_force_key_unit (event,
2613             &running_time, &all_headers, &count);
2614 
2615         GST_INFO_OBJECT (h265parse, "received upstream force-key-unit event, "
2616             "seqnum %d running_time %" GST_TIME_FORMAT
2617             " all_headers %d count %d", gst_event_get_seqnum (event),
2618             GST_TIME_ARGS (running_time), all_headers, count);
2619 
2620         if (all_headers) {
2621           h265parse->pending_key_unit_ts = running_time;
2622           gst_event_replace (&h265parse->force_key_unit_event, event);
2623         }
2624       }
2625       res = GST_BASE_PARSE_CLASS (parent_class)->src_event (parse, event);
2626       break;
2627     }
2628     default:
2629       res = GST_BASE_PARSE_CLASS (parent_class)->src_event (parse, event);
2630       break;
2631   }
2632 
2633   return res;
2634 }
2635 
2636 static void
gst_h265_parse_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)2637 gst_h265_parse_set_property (GObject * object, guint prop_id,
2638     const GValue * value, GParamSpec * pspec)
2639 {
2640   GstH265Parse *parse;
2641   parse = GST_H265_PARSE (object);
2642 
2643   switch (prop_id) {
2644     case PROP_CONFIG_INTERVAL:
2645       parse->interval = g_value_get_int (value);
2646       break;
2647     default:
2648       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
2649       break;
2650   }
2651 }
2652 
2653 static void
gst_h265_parse_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)2654 gst_h265_parse_get_property (GObject * object, guint prop_id, GValue * value,
2655     GParamSpec * pspec)
2656 {
2657   GstH265Parse *parse;
2658   parse = GST_H265_PARSE (object);
2659 
2660   switch (prop_id) {
2661     case PROP_CONFIG_INTERVAL:
2662       g_value_set_int (value, parse->interval);
2663       break;
2664     default:
2665       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
2666       break;
2667   }
2668 }
2669