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