1 /* GStreamer H.265 Parser
2 * Copyright (C) 2013 Intel Corporation
3 * Contact:Sreerenj Balachandran <sreerenj.balachandran@intel.com>
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.
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.
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.
25 #include <gst/base/base.h>
26 #include <gst/pbutils/pbutils.h>
27 #include "gstvideoparserselements.h"
28 #include "gsth265parse.h"
32 GST_DEBUG_CATEGORY (h265_parse_debug);
33 #define GST_CAT_DEFAULT h265_parse_debug
35 #define DEFAULT_CONFIG_INTERVAL (0)
45 GST_H265_PARSE_FORMAT_NONE,
46 GST_H265_PARSE_FORMAT_HVC1,
47 GST_H265_PARSE_FORMAT_HEV1,
48 GST_H265_PARSE_FORMAT_BYTE
53 GST_H265_PARSE_ALIGN_NONE = 0,
54 GST_H265_PARSE_ALIGN_NAL,
55 GST_H265_PARSE_ALIGN_AU
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,
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)
73 GST_H265_PARSE_SEI_EXPIRED = 0,
74 GST_H265_PARSE_SEI_ACTIVE = 1,
75 GST_H265_PARSE_SEI_PARSED = 2,
78 #define GST_H265_PARSE_STATE_VALID(parse, expected_state) \
79 (((parse)->state & (expected_state)) == (expected_state))
81 static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
84 GST_STATIC_CAPS ("video/x-h265"));
86 static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
89 GST_STATIC_CAPS ("video/x-h265, parsed = (boolean) true, "
90 "stream-format=(string) { hvc1, hev1, byte-stream }, "
91 "alignment=(string) { au, nal }"));
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));
99 static void gst_h265_parse_finalize (GObject * object);
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);
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);
115 static gboolean gst_h265_parse_set_caps (GstBaseParse * parse, GstCaps * caps);
116 static GstCaps *gst_h265_parse_get_caps (GstBaseParse * parse,
118 static gboolean gst_h265_parse_event (GstBaseParse * parse, GstEvent * event);
119 static gboolean gst_h265_parse_src_event (GstBaseParse * parse,
122 gst_h265_parse_process_sei_user_data (GstH265Parse * h265parse,
123 GstH265RegisteredUserData * rud);
126 gst_h265_parse_class_init (GstH265ParseClass * klass)
128 GObjectClass *gobject_class = (GObjectClass *) klass;
129 GstBaseParseClass *parse_class = GST_BASE_PARSE_CLASS (klass);
130 GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
132 GST_DEBUG_CATEGORY_INIT (h265_parse_debug, "h265parse", 0, "h265 parser");
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;
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);
157 gst_element_class_add_static_pad_template (gstelement_class, &srctemplate);
158 gst_element_class_add_static_pad_template (gstelement_class, &sinktemplate);
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>");
167 gst_h265_parse_init (GstH265Parse * h265parse)
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));
178 gst_h265_parse_finalize (GObject * object)
180 GstH265Parse *h265parse = GST_H265_PARSE (object);
182 g_object_unref (h265parse->frame_out);
184 G_OBJECT_CLASS (parent_class)->finalize (object);
188 gst_h265_parse_reset_frame (GstH265Parse * h265parse)
190 GST_DEBUG_OBJECT (h265parse, "reset frame");
192 /* done parsing; reset state */
193 h265parse->current_off = -1;
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);
209 gst_h265_parse_reset_stream_info (GstH265Parse * h265parse)
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;
229 h265parse->align = GST_H265_PARSE_ALIGN_NONE;
230 h265parse->format = GST_H265_PARSE_FORMAT_NONE;
232 h265parse->transform = FALSE;
233 h265parse->nal_length_size = 4;
234 h265parse->packetized = FALSE;
235 h265parse->push_codec = FALSE;
236 h265parse->first_frame = TRUE;
238 gst_buffer_replace (&h265parse->codec_data, NULL);
239 gst_buffer_replace (&h265parse->codec_data_in, NULL);
241 gst_h265_parse_reset_frame (h265parse);
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);
250 gst_video_mastering_display_info_init (&h265parse->mastering_display_info);
251 h265parse->mastering_display_info_state = GST_H265_PARSE_SEI_EXPIRED;
253 gst_video_content_light_level_init (&h265parse->content_light_level);
254 h265parse->content_light_level_state = GST_H265_PARSE_SEI_EXPIRED;
258 gst_h265_parse_reset (GstH265Parse * h265parse)
260 h265parse->last_report = GST_CLOCK_TIME_NONE;
262 h265parse->pending_key_unit_ts = GST_CLOCK_TIME_NONE;
263 gst_event_replace (&h265parse->force_key_unit_event, NULL);
265 h265parse->discont = FALSE;
266 h265parse->discard_bidirectional = FALSE;
267 h265parse->marker = FALSE;
269 gst_h265_parse_reset_stream_info (h265parse);
273 gst_h265_parse_start (GstBaseParse * parse)
275 GstH265Parse *h265parse = GST_H265_PARSE (parse);
277 GST_DEBUG_OBJECT (parse, "start");
278 gst_h265_parse_reset (h265parse);
280 h265parse->nalparser = gst_h265_parser_new ();
281 h265parse->state = 0;
283 gst_base_parse_set_min_frame_size (parse, 5);
289 gst_h265_parse_stop (GstBaseParse * parse)
291 GstH265Parse *h265parse = GST_H265_PARSE (parse);
293 GST_DEBUG_OBJECT (parse, "stop");
294 gst_h265_parse_reset (h265parse);
296 gst_h265_parser_free (h265parse->nalparser);
302 gst_h265_parse_get_string (GstH265Parse * parse, gboolean format, gint code)
306 case GST_H265_PARSE_FORMAT_HVC1:
308 case GST_H265_PARSE_FORMAT_HEV1:
310 case GST_H265_PARSE_FORMAT_BYTE:
311 return "byte-stream";
317 case GST_H265_PARSE_ALIGN_NAL:
319 case GST_H265_PARSE_ALIGN_AU:
328 gst_h265_parse_format_from_caps (GstCaps * caps, guint * format, guint * align)
330 g_return_if_fail (gst_caps_is_fixed (caps));
332 GST_DEBUG ("parsing caps: %" GST_PTR_FORMAT, caps);
335 *format = GST_H265_PARSE_FORMAT_NONE;
338 *align = GST_H265_PARSE_ALIGN_NONE;
340 if (caps && gst_caps_get_size (caps) > 0) {
341 GstStructure *s = gst_caps_get_structure (caps, 0);
342 const gchar *str = NULL;
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;
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;
366 /* check downstream caps to configure format and alignment */
368 gst_h265_parse_negotiate (GstH265Parse * h265parse, gint in_format,
372 guint format = GST_H265_PARSE_FORMAT_NONE;
373 guint align = GST_H265_PARSE_ALIGN_NONE;
375 g_return_if_fail ((in_caps == NULL) || gst_caps_is_fixed (in_caps));
377 caps = gst_pad_get_allowed_caps (GST_BASE_PARSE_SRC_PAD (h265parse));
378 GST_DEBUG_OBJECT (h265parse, "allowed caps: %" GST_PTR_FORMAT, caps);
380 /* concentrate on leading structure, since decodebin parser
381 * capsfilter always includes parser template caps */
383 caps = gst_caps_truncate (caps);
384 GST_DEBUG_OBJECT (h265parse, "negotiating with caps: %" GST_PTR_FORMAT,
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);
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);
406 format = GST_H265_PARSE_FORMAT_BYTE;
408 align = GST_H265_PARSE_ALIGN_AU;
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));
414 h265parse->format = format;
415 h265parse->align = align;
417 h265parse->transform = in_format != h265parse->format ||
418 align == GST_H265_PARSE_ALIGN_AU;
421 gst_caps_unref (caps);
425 gst_h265_parse_wrap_nal (GstH265Parse * h265parse, guint format, guint8 * data,
429 guint nl = h265parse->nal_length_size;
432 GST_DEBUG_OBJECT (h265parse, "nal length %d", size);
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));
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. */
443 tmp = GUINT32_TO_BE (1);
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);
454 gst_h265_parser_store_nal (GstH265Parse * h265parse, guint id,
455 GstH265NalUnitType naltype, GstH265NalUnit * nalu)
457 GstBuffer *buf, **store;
458 guint size = nalu->size, store_size;
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);
475 if (id >= store_size) {
476 GST_DEBUG_OBJECT (h265parse, "unable to store nal, id out-of-range %d", id);
480 buf = gst_buffer_new_allocate (NULL, size, NULL);
481 gst_buffer_fill (buf, 0, nalu->data + nalu->offset, size);
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);
488 gst_buffer_unref (store[id]);
493 #ifndef GST_DISABLE_GST_DEBUG
494 static const gchar *nal_names[] = {
539 _nal_name (GstH265NalUnitType nal_type)
541 if (nal_type <= GST_H265_NAL_SUFFIX_SEI)
542 return nal_names[nal_type];
548 gst_h265_parse_process_sei (GstH265Parse * h265parse, GstH265NalUnit * nalu)
550 GstH265SEIMessage sei;
551 GstH265Parser *nalparser = h265parse->nalparser;
552 GstH265ParserResult pres;
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");
560 /* Even if pres != GST_H265_PARSER_OK, some message could have been parsed and
561 * stored in messages.
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;
573 case GST_H265_SEI_TIME_CODE:
574 memcpy (&h265parse->time_code, &sei.payload.time_code,
575 sizeof (GstH265TimeCode));
577 case GST_H265_SEI_PIC_TIMING:
578 h265parse->sei_pic_struct = sei.payload.pic_timing.pic_struct;
580 case GST_H265_SEI_REGISTERED_USER_DATA:
581 gst_h265_parse_process_sei_user_data (h265parse,
582 &sei.payload.registered_user_data);
584 case GST_H265_SEI_BUF_PERIOD:
587 case GST_H265_SEI_MASTERING_DISPLAY_COLOUR_VOLUME:
589 /* Precision defined by spec.
590 * See D.3.28 Mastering display colour volume SEI message semantics */
591 GstVideoMasteringDisplayInfo minfo;
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
598 for (j = 0, k = 2; j < G_N_ELEMENTS (minfo.display_primaries); j++, k++) {
599 minfo.display_primaries[j].x =
601 mastering_display_colour_volume.display_primaries_x[k % 3];
602 minfo.display_primaries[j].y =
604 mastering_display_colour_volume.display_primaries_y[k % 3];
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;
618 GST_LOG_OBJECT (h265parse, "mastering display info found: "
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);
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;
640 h265parse->mastering_display_info_state = GST_H265_PARSE_SEI_PARSED;
641 h265parse->mastering_display_info = minfo;
645 case GST_H265_SEI_CONTENT_LIGHT_LEVEL:
647 GstVideoContentLightLevel cll;
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;
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);
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;
667 h265parse->content_light_level_state = GST_H265_PARSE_SEI_PARSED;
668 h265parse->content_light_level = cll;
676 g_array_free (messages, TRUE);
680 gst_h265_parse_process_sei_user_data (GstH265Parse * h265parse,
681 GstH265RegisteredUserData * rud)
683 guint16 provider_code;
685 GstVideoParseUtilsField field = GST_VIDEO_PARSE_UTILS_FIELD_1;
687 /* only US country code is currently supported */
688 switch (rud->country_code) {
689 case ITU_T_T35_COUNTRY_CODE_US:
692 GST_LOG_OBJECT (h265parse, "Unsupported country code %d",
697 if (rud->data == NULL || rud->size < 2)
700 gst_byte_reader_init (&br, rud->data, rud->size);
702 provider_code = gst_byte_reader_get_uint16_be_unchecked (&br);
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);
712 /* caller guarantees 2 bytes of nal payload */
714 gst_h265_parse_process_nal (GstH265Parse * h265parse, GstH265NalUnit * nalu)
716 GstH265PPS pps = { 0, };
717 GstH265SPS sps = { 0, };
718 GstH265VPS vps = { 0, };
720 GstH265Parser *nalparser = h265parse->nalparser;
721 GstH265ParserResult pres = GST_H265_PARSER_ERROR;
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);
729 /* we have a peek as well */
730 nal_type = nalu->type;
732 GST_DEBUG_OBJECT (h265parse, "processing nal of type %u %s, size %u",
733 nal_type, _nal_name (nal_type), nalu->size);
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");
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;
758 gst_h265_parser_store_nal (h265parse, vps.id, nal_type, nalu);
759 h265parse->header = TRUE;
761 case GST_H265_NAL_SPS:
762 /* reset state, everything else is obsolete */
763 h265parse->state &= GST_H265_PARSE_STATE_GOT_PPS;
765 pres = gst_h265_parser_parse_sps (nalparser, nalu, &sps, TRUE);
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;
778 GST_WARNING_OBJECT (h265parse,
779 "failed to parse VUI of SPS, ignore VUI");
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;
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;
799 case GST_H265_NAL_PPS:
800 pres = gst_h265_parser_parse_pps (nalparser, nalu, &pps);
802 /* arranged for a fallback pps.id, so use that one and only warn */
803 if (pres != GST_H265_PARSER_OK) {
804 GST_WARNING_OBJECT (h265parse, "failed to parse PPS:");
805 if (pres != GST_H265_PARSER_BROKEN_LINK)
809 /* parameters might have changed, force caps check */
810 if (!h265parse->have_pps) {
811 GST_DEBUG_OBJECT (h265parse, "triggering src caps check");
812 h265parse->update_caps = TRUE;
814 h265parse->have_pps = TRUE;
815 h265parse->have_pps_in_frame = TRUE;
816 if (h265parse->push_codec && h265parse->have_sps) {
817 /* SPS and PPS found in stream before the first pre_push_frame, no need
818 * to forcibly push at start */
819 GST_INFO_OBJECT (h265parse, "have SPS/PPS in stream");
820 h265parse->push_codec = FALSE;
821 h265parse->have_sps = FALSE;
822 h265parse->have_pps = FALSE;
825 gst_h265_parser_store_nal (h265parse, pps.id, nal_type, nalu);
826 h265parse->header = TRUE;
827 h265parse->state |= GST_H265_PARSE_STATE_GOT_PPS;
829 case GST_H265_NAL_PREFIX_SEI:
830 case GST_H265_NAL_SUFFIX_SEI:
831 /* expected state: got-sps */
832 if (!GST_H265_PARSE_STATE_VALID (h265parse, GST_H265_PARSE_STATE_GOT_SPS))
835 h265parse->header = TRUE;
837 gst_h265_parse_process_sei (h265parse, nalu);
840 if (nal_type == GST_H265_NAL_PREFIX_SEI && h265parse->sei_pos == -1) {
841 if (h265parse->transform)
842 h265parse->sei_pos = gst_adapter_available (h265parse->frame_out);
844 h265parse->sei_pos = nalu->sc_offset;
845 GST_DEBUG_OBJECT (h265parse, "marking SEI in frame at offset %d",
850 case GST_H265_NAL_SLICE_TRAIL_N:
851 case GST_H265_NAL_SLICE_TRAIL_R:
852 case GST_H265_NAL_SLICE_TSA_N:
853 case GST_H265_NAL_SLICE_TSA_R:
854 case GST_H265_NAL_SLICE_STSA_N:
855 case GST_H265_NAL_SLICE_STSA_R:
856 case GST_H265_NAL_SLICE_RADL_N:
857 case GST_H265_NAL_SLICE_RADL_R:
858 case GST_H265_NAL_SLICE_RASL_N:
859 case GST_H265_NAL_SLICE_RASL_R:
860 case GST_H265_NAL_SLICE_BLA_W_LP:
861 case GST_H265_NAL_SLICE_BLA_W_RADL:
862 case GST_H265_NAL_SLICE_BLA_N_LP:
863 case GST_H265_NAL_SLICE_IDR_W_RADL:
864 case GST_H265_NAL_SLICE_IDR_N_LP:
865 case GST_H265_NAL_SLICE_CRA_NUT:
867 GstH265SliceHdr slice;
869 gboolean no_rasl_output_flag = FALSE;
871 /* expected state: got-sps|got-pps (valid picture headers) */
872 h265parse->state &= GST_H265_PARSE_STATE_VALID_PICTURE_HEADERS;
873 if (!GST_H265_PARSE_STATE_VALID (h265parse,
874 GST_H265_PARSE_STATE_VALID_PICTURE_HEADERS))
877 /* This is similar to the GOT_SLICE state, but is only reset when the
878 * AU is complete. This is used to keep track of AU */
879 h265parse->picture_start = TRUE;
881 pres = gst_h265_parser_parse_slice_hdr (nalparser, nalu, &slice);
883 if (pres == GST_H265_PARSER_OK) {
884 if (GST_H265_IS_I_SLICE (&slice))
885 h265parse->keyframe = TRUE;
886 else if (GST_H265_IS_P_SLICE (&slice))
887 h265parse->predicted = TRUE;
888 else if (GST_H265_IS_B_SLICE (&slice))
889 h265parse->bidirectional = TRUE;
891 h265parse->state |= GST_H265_PARSE_STATE_GOT_SLICE;
893 if (slice.first_slice_segment_in_pic_flag == 1)
894 GST_DEBUG_OBJECT (h265parse,
895 "frame start, first_slice_segment_in_pic_flag = 1");
897 GST_DEBUG_OBJECT (h265parse,
898 "parse result %d, first slice_segment: %u, slice type: %u",
899 pres, slice.first_slice_segment_in_pic_flag, slice.type);
901 gst_h265_slice_hdr_free (&slice);
903 /* FIXME: NoRaslOutputFlag can be equal to 1 for CRA if
904 * 1) the first AU in bitstream is CRA
905 * 2) or the first AU following EOS nal is CRA
906 * 3) or it has HandleCraAsBlaFlag equal to 1 */
907 if (GST_H265_IS_NAL_TYPE_IDR (nal_type)) {
908 /* NoRaslOutputFlag is equal to 1 for each IDR */
909 no_rasl_output_flag = TRUE;
910 } else if (GST_H265_IS_NAL_TYPE_BLA (nal_type)) {
911 /* NoRaslOutputFlag is equal to 1 for each BLA */
912 no_rasl_output_flag = TRUE;
915 is_irap = GST_H265_IS_NAL_TYPE_IRAP (nal_type);
917 if (no_rasl_output_flag && is_irap
918 && slice.first_slice_segment_in_pic_flag == 1) {
919 if (h265parse->mastering_display_info_state ==
920 GST_H265_PARSE_SEI_PARSED)
921 h265parse->mastering_display_info_state = GST_H265_PARSE_SEI_ACTIVE;
922 else if (h265parse->mastering_display_info_state ==
923 GST_H265_PARSE_SEI_ACTIVE)
924 h265parse->mastering_display_info_state = GST_H265_PARSE_SEI_EXPIRED;
926 if (h265parse->content_light_level_state == GST_H265_PARSE_SEI_PARSED)
927 h265parse->content_light_level_state = GST_H265_PARSE_SEI_ACTIVE;
928 else if (h265parse->content_light_level_state ==
929 GST_H265_PARSE_SEI_ACTIVE)
930 h265parse->content_light_level_state = GST_H265_PARSE_SEI_EXPIRED;
932 if (G_LIKELY (!is_irap && !h265parse->push_codec))
935 /* if we need to sneak codec NALs into the stream,
936 * this is a good place, so fake it as IDR
937 * (which should be at start anyway) */
938 /* mark where config needs to go if interval expired */
939 /* mind replacement buffer if applicable */
940 if (h265parse->idr_pos == -1) {
941 if (h265parse->transform)
942 h265parse->idr_pos = gst_adapter_available (h265parse->frame_out);
944 h265parse->idr_pos = nalu->sc_offset;
945 GST_DEBUG_OBJECT (h265parse, "marking IDR in frame at offset %d",
948 /* if SEI preceeds (faked) IDR, then we have to insert config there */
949 if (h265parse->sei_pos >= 0 && h265parse->idr_pos > h265parse->sei_pos) {
950 h265parse->idr_pos = h265parse->sei_pos;
951 GST_DEBUG_OBJECT (h265parse, "moved IDR mark to SEI position %d",
956 case GST_H265_NAL_AUD:
958 /* Just accumulate AU Delimiter, whether it's before SPS or not */
959 pres = gst_h265_parser_parse_nal (nalparser, nalu);
960 if (pres != GST_H265_PARSER_OK)
965 /* if HEVC output needed, collect properly prefixed nal in adapter,
966 * and use that to replace outgoing buffer data later on */
967 if (h265parse->transform) {
970 GST_LOG_OBJECT (h265parse, "collecting NAL in HEVC frame");
971 buf = gst_h265_parse_wrap_nal (h265parse, h265parse->format,
972 nalu->data + nalu->offset, nalu->size);
973 gst_adapter_push (h265parse->frame_out, buf);
979 /* caller guarantees at least 3 bytes of nal payload for each nal
980 * returns TRUE if next_nal indicates that nal terminates an AU */
981 static inline gboolean
982 gst_h265_parse_collect_nal (GstH265Parse * h265parse, const guint8 * data,
983 guint size, GstH265NalUnit * nalu)
985 GstH265NalUnitType nal_type = nalu->type;
988 /* determine if AU complete */
989 GST_LOG_OBJECT (h265parse, "next nal type: %d %s (picture started %i)",
990 nal_type, _nal_name (nal_type), h265parse->picture_start);
992 /* consider a coded slices (IRAP or not) to start a picture,
993 * (so ending the previous one) if first_slice_segment_in_pic_flag == 1*/
994 complete = h265parse->picture_start && ((nal_type >= GST_H265_NAL_VPS
995 && nal_type <= GST_H265_NAL_AUD)
996 || nal_type == GST_H265_NAL_PREFIX_SEI || (nal_type >= 41
997 && nal_type <= 44) || (nal_type >= 48 && nal_type <= 55));
999 /* Any VCL Nal unit with first_slice_segment_in_pic_flag == 1 considered start of frame */
1000 if (nalu->size > nalu->header_bytes) {
1001 complete |= h265parse->picture_start
1002 && (((nal_type >= GST_H265_NAL_SLICE_TRAIL_N
1003 && nal_type <= GST_H265_NAL_SLICE_RASL_R)
1004 || GST_H265_IS_NAL_TYPE_IRAP (nal_type))
1005 && (nalu->data[nalu->offset + 2] & 0x80));
1008 GST_LOG_OBJECT (h265parse, "au complete: %d", complete);
1011 h265parse->picture_start = FALSE;
1016 static GstFlowReturn
1017 gst_h265_parse_handle_frame_packetized (GstBaseParse * parse,
1018 GstBaseParseFrame * frame)
1020 GstH265Parse *h265parse = GST_H265_PARSE (parse);
1021 GstBuffer *buffer = frame->buffer;
1022 GstFlowReturn ret = GST_FLOW_OK;
1023 GstH265ParserResult parse_res;
1024 GstH265NalUnit nalu;
1025 const guint nl = h265parse->nal_length_size;
1029 if (nl < 1 || nl > 4) {
1030 GST_DEBUG_OBJECT (h265parse, "insufficient data to split input");
1031 return GST_FLOW_NOT_NEGOTIATED;
1034 /* need to save buffer from invalidation upon _finish_frame */
1035 if (h265parse->split_packetized)
1036 buffer = gst_buffer_copy (frame->buffer);
1038 gst_buffer_map (buffer, &map, GST_MAP_READ);
1042 GST_LOG_OBJECT (h265parse,
1043 "processing packet buffer of size %" G_GSIZE_FORMAT, map.size);
1045 parse_res = gst_h265_parser_identify_nalu_hevc (h265parse->nalparser,
1046 map.data, 0, map.size, nl, &nalu);
1048 while (parse_res == GST_H265_PARSER_OK) {
1049 GST_DEBUG_OBJECT (h265parse, "HEVC nal offset %d", nalu.offset + nalu.size);
1051 /* either way, have a look at it */
1052 gst_h265_parse_process_nal (h265parse, &nalu);
1054 /* dispatch per NALU if needed */
1055 if (h265parse->split_packetized) {
1056 GstBaseParseFrame tmp_frame;
1058 gst_base_parse_frame_init (&tmp_frame);
1059 tmp_frame.flags |= frame->flags;
1060 tmp_frame.offset = frame->offset;
1061 tmp_frame.overhead = frame->overhead;
1062 tmp_frame.buffer = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_ALL,
1063 nalu.offset, nalu.size);
1064 /* Don't lose timestamp when offset is not 0. */
1065 GST_BUFFER_PTS (tmp_frame.buffer) = GST_BUFFER_PTS (buffer);
1066 GST_BUFFER_DTS (tmp_frame.buffer) = GST_BUFFER_DTS (buffer);
1067 GST_BUFFER_DURATION (tmp_frame.buffer) = GST_BUFFER_DURATION (buffer);
1069 /* Set marker on last packet */
1070 if (nl + nalu.size == left) {
1071 if (GST_BUFFER_FLAG_IS_SET (frame->buffer, GST_BUFFER_FLAG_MARKER))
1072 h265parse->marker = TRUE;
1075 /* note we don't need to come up with a sub-buffer, since
1076 * subsequent code only considers input buffer's metadata.
1077 * Real data is either taken from input by baseclass or
1078 * a replacement output buffer is provided anyway. */
1079 gst_h265_parse_parse_frame (parse, &tmp_frame);
1080 ret = gst_base_parse_finish_frame (parse, &tmp_frame, nl + nalu.size);
1081 left -= nl + nalu.size;
1084 parse_res = gst_h265_parser_identify_nalu_hevc (h265parse->nalparser,
1085 map.data, nalu.offset + nalu.size, map.size, nl, &nalu);
1088 gst_buffer_unmap (buffer, &map);
1090 if (!h265parse->split_packetized) {
1091 h265parse->marker = TRUE;
1092 gst_h265_parse_parse_frame (parse, frame);
1093 ret = gst_base_parse_finish_frame (parse, frame, map.size);
1095 gst_buffer_unref (buffer);
1096 if (G_UNLIKELY (left)) {
1097 /* should not be happening for nice HEVC */
1098 GST_WARNING_OBJECT (parse, "skipping leftover HEVC data %d", left);
1099 frame->flags |= GST_BASE_PARSE_FRAME_FLAG_DROP;
1100 ret = gst_base_parse_finish_frame (parse, frame, map.size);
1104 if (parse_res == GST_H265_PARSER_NO_NAL_END ||
1105 parse_res == GST_H265_PARSER_BROKEN_DATA) {
1107 if (h265parse->split_packetized) {
1108 GST_ELEMENT_ERROR (h265parse, STREAM, FAILED, (NULL),
1109 ("invalid HEVC input data"));
1111 return GST_FLOW_ERROR;
1113 /* do not meddle to much in this case */
1114 GST_DEBUG_OBJECT (h265parse, "parsing packet failed");
1121 static GstFlowReturn
1122 gst_h265_parse_handle_frame (GstBaseParse * parse,
1123 GstBaseParseFrame * frame, gint * skipsize)
1125 GstH265Parse *h265parse = GST_H265_PARSE (parse);
1126 GstBuffer *buffer = frame->buffer;
1130 gint current_off = 0;
1131 gboolean drain, nonext;
1132 GstH265Parser *nalparser = h265parse->nalparser;
1133 GstH265NalUnit nalu;
1134 GstH265ParserResult pres;
1137 if (G_UNLIKELY (GST_BUFFER_FLAG_IS_SET (frame->buffer,
1138 GST_BUFFER_FLAG_DISCONT))) {
1139 h265parse->discont = TRUE;
1142 /* delegate in packetized case, no skipping should be needed */
1143 if (h265parse->packetized)
1144 return gst_h265_parse_handle_frame_packetized (parse, frame);
1146 gst_buffer_map (buffer, &map, GST_MAP_READ);
1150 /* expect at least 3 bytes start_code, and 2 bytes NALU header.
1151 * the length of the NALU payload can be zero.
1152 * (e.g. EOS/EOB placed at the end of an AU.) */
1153 if (G_UNLIKELY (size < 5)) {
1154 gst_buffer_unmap (buffer, &map);
1159 /* need to configure aggregation */
1160 if (G_UNLIKELY (h265parse->format == GST_H265_PARSE_FORMAT_NONE))
1161 gst_h265_parse_negotiate (h265parse, GST_H265_PARSE_FORMAT_BYTE, NULL);
1163 /* avoid stale cached parsing state */
1164 if (frame->flags & GST_BASE_PARSE_FRAME_FLAG_NEW_FRAME) {
1165 GST_LOG_OBJECT (h265parse, "parsing new frame");
1166 gst_h265_parse_reset_frame (h265parse);
1168 GST_LOG_OBJECT (h265parse, "resuming frame parsing");
1171 /* Always consume the entire input buffer when in_align == ALIGN_AU */
1172 drain = GST_BASE_PARSE_DRAINING (parse)
1173 || h265parse->in_align == GST_H265_PARSE_ALIGN_AU;
1176 current_off = h265parse->current_off;
1177 if (current_off < 0)
1180 /* The parser is being drain, but no new data was added, just prentend this
1182 if (drain && current_off == size) {
1183 GST_DEBUG_OBJECT (h265parse, "draining with no new data");
1185 nalu.offset = current_off;
1189 g_assert (current_off < size);
1190 GST_DEBUG_OBJECT (h265parse, "last parse position %d", current_off);
1192 /* check for initial skip */
1193 if (h265parse->current_off == -1) {
1195 gst_h265_parser_identify_nalu_unchecked (nalparser, data, current_off,
1198 case GST_H265_PARSER_OK:
1199 if (nalu.sc_offset > 0) {
1200 *skipsize = nalu.sc_offset;
1204 case GST_H265_PARSER_NO_NAL:
1205 /* start code may have up to 4 bytes, and we may also get that return
1206 * value if only one of the two header bytes are present, make sure
1207 * not to skip too much */
1208 *skipsize = size - 5;
1211 /* should not really occur either */
1212 GST_ELEMENT_ERROR (h265parse, STREAM, FORMAT,
1213 ("Error parsing H.265 stream"), ("Invalid H.265 stream"));
1214 goto invalid_stream;
1217 /* Ensure we use the TS of the first NAL. This avoids broken timestamp in
1218 * the case of a miss-placed filler byte. */
1219 gst_base_parse_set_ts_at_offset (parse, nalu.offset);
1224 gst_h265_parser_identify_nalu (nalparser, data, current_off, size,
1228 case GST_H265_PARSER_OK:
1229 GST_DEBUG_OBJECT (h265parse, "complete nal (offset, size): (%u, %u) ",
1230 nalu.offset, nalu.size);
1232 case GST_H265_PARSER_NO_NAL_END:
1233 /* In NAL alignment, assume the NAL is complete */
1234 if (h265parse->in_align == GST_H265_PARSE_ALIGN_NAL ||
1235 h265parse->in_align == GST_H265_PARSE_ALIGN_AU) {
1237 nalu.size = size - nalu.offset;
1240 GST_DEBUG_OBJECT (h265parse, "not a complete nal found at offset %u",
1242 /* if draining, accept it as complete nal */
1245 nalu.size = size - nalu.offset;
1246 GST_DEBUG_OBJECT (h265parse, "draining, accepting with size %u",
1248 /* if it's not too short at least */
1253 /* otherwise need more */
1255 case GST_H265_PARSER_BROKEN_LINK:
1256 GST_ELEMENT_ERROR (h265parse, STREAM, FORMAT,
1257 ("Error parsing H.265 stream"),
1258 ("The link to structure needed for the parsing couldn't be found"));
1259 goto invalid_stream;
1260 case GST_H265_PARSER_ERROR:
1261 /* should not really occur either */
1262 GST_ELEMENT_ERROR (h265parse, STREAM, FORMAT,
1263 ("Error parsing H.265 stream"), ("Invalid H.265 stream"));
1264 goto invalid_stream;
1265 case GST_H265_PARSER_NO_NAL:
1266 GST_ELEMENT_ERROR (h265parse, STREAM, FORMAT,
1267 ("Error parsing H.265 stream"), ("No H.265 NAL unit found"));
1268 goto invalid_stream;
1269 case GST_H265_PARSER_BROKEN_DATA:
1270 GST_WARNING_OBJECT (h265parse, "input stream is corrupt; "
1271 "it contains a NAL unit of length %u", nalu.size);
1273 /* broken nal at start -> arrange to skip it,
1274 * otherwise have it terminate current au
1275 * (and so it will be skipped on next frame round) */
1276 if (current_off == 0) {
1277 GST_DEBUG_OBJECT (h265parse, "skipping broken nal");
1278 *skipsize = nalu.offset;
1281 GST_DEBUG_OBJECT (h265parse, "terminating au");
1283 nalu.offset = nalu.sc_offset;
1287 g_assert_not_reached ();
1291 GST_DEBUG_OBJECT (h265parse, "%p complete nal found. Off: %u, Size: %u",
1292 data, nalu.offset, nalu.size);
1294 if (gst_h265_parse_collect_nal (h265parse, data, size, &nalu)) {
1295 /* complete current frame, if it exist */
1296 if (current_off > 0) {
1298 nalu.offset = nalu.sc_offset;
1299 h265parse->marker = TRUE;
1304 if (!gst_h265_parse_process_nal (h265parse, &nalu)) {
1305 GST_WARNING_OBJECT (h265parse,
1306 "broken/invalid nal Type: %d %s, Size: %u will be dropped",
1307 nalu.type, _nal_name (nalu.type), nalu.size);
1308 *skipsize = nalu.size;
1312 /* Do not push immediatly if we don't have all headers. This ensure that
1313 * our caps are complete, avoiding a renegotiation */
1314 if (h265parse->align == GST_H265_PARSE_ALIGN_NAL &&
1315 !GST_H265_PARSE_STATE_VALID (h265parse,
1316 GST_H265_PARSE_STATE_VALID_PICTURE_HEADERS))
1317 frame->flags |= GST_BASE_PARSE_FRAME_FLAG_QUEUE;
1320 /* If there is a marker flag, or input is AU, we know this is complete */
1321 if (GST_BUFFER_FLAG_IS_SET (frame->buffer, GST_BUFFER_FLAG_MARKER) ||
1322 h265parse->in_align == GST_H265_PARSE_ALIGN_AU) {
1323 h265parse->marker = TRUE;
1327 /* or if we are draining or producing NALs */
1328 if (drain || h265parse->align == GST_H265_PARSE_ALIGN_NAL)
1331 current_off = nalu.offset + nalu.size;
1335 /* If the output is NAL, we are done */
1336 if (h265parse->align == GST_H265_PARSE_ALIGN_NAL)
1339 GST_DEBUG_OBJECT (h265parse, "Looking for more");
1340 current_off = nalu.offset + nalu.size;
1342 /* expect at least 3 bytes start_code, and 2 bytes NALU header.
1343 * the length of the NALU payload can be zero.
1344 * (e.g. EOS/EOB placed at the end of an AU.) */
1345 if (G_UNLIKELY (size - current_off < 5)) {
1346 /* Finish the frame if there is no more data in the stream */
1355 framesize = nalu.offset + nalu.size;
1357 gst_buffer_unmap (buffer, &map);
1359 gst_h265_parse_parse_frame (parse, frame);
1361 return gst_base_parse_finish_frame (parse, frame, framesize);
1366 /* Restart parsing from here next time */
1367 if (current_off > 0)
1368 h265parse->current_off = current_off;
1372 gst_buffer_unmap (buffer, &map);
1376 GST_DEBUG_OBJECT (h265parse, "skipping %d", *skipsize);
1377 /* If we are collecting access units, we need to preserve the initial
1378 * config headers (SPS, PPS et al.) and only reset the frame if another
1379 * slice NAL was received. This means that broken pictures are discarded */
1380 if (h265parse->align != GST_H265_PARSE_ALIGN_AU ||
1381 !(h265parse->state & GST_H265_PARSE_STATE_VALID_PICTURE_HEADERS) ||
1382 (h265parse->state & GST_H265_PARSE_STATE_GOT_SLICE))
1383 gst_h265_parse_reset_frame (h265parse);
1387 gst_buffer_unmap (buffer, &map);
1388 return GST_FLOW_ERROR;
1391 /* byte together hevc codec data based on collected pps and sps so far */
1393 gst_h265_parse_make_codec_data (GstH265Parse * h265parse)
1395 GstBuffer *buf, *nal;
1397 guint vps_size = 0, sps_size = 0, pps_size = 0;
1398 guint num_vps = 0, num_sps = 0, num_pps = 0;
1399 gboolean found = FALSE;
1403 guint8 num_arrays = 0;
1404 GstH265SPS *sps = NULL;
1405 guint16 min_spatial_segmentation_idc = 0;
1406 GstH265ProfileTierLevel *pft;
1408 /* only nal payload in stored nals */
1409 /* Fixme: Current implementation is not embedding SEI in codec_data */
1410 for (i = 0; i < GST_H265_MAX_VPS_COUNT; i++) {
1411 if ((nal = h265parse->vps_nals[i])) {
1413 /* size bytes also count */
1414 vps_size += gst_buffer_get_size (nal) + 2;
1420 for (i = 0; i < GST_H265_MAX_SPS_COUNT; i++) {
1421 if ((nal = h265parse->sps_nals[i])) {
1423 /* size bytes also count */
1424 sps_size += gst_buffer_get_size (nal) + 2;
1431 for (i = 0; i < GST_H265_MAX_PPS_COUNT; i++) {
1432 if ((nal = h265parse->pps_nals[i])) {
1434 /* size bytes also count */
1435 pps_size += gst_buffer_get_size (nal) + 2;
1441 GST_DEBUG_OBJECT (h265parse,
1442 "constructing codec_data: num_vps =%d num_sps=%d, num_pps=%d", num_vps,
1448 sps = h265parse->nalparser->last_sps;
1453 gst_buffer_new_allocate (NULL,
1454 23 + (3 * num_arrays) + vps_size + sps_size + pps_size, NULL);
1455 gst_buffer_map (buf, &map, GST_MAP_WRITE);
1457 memset (data, 0, map.size);
1458 nl = h265parse->nal_length_size;
1460 pft = &sps->profile_tier_level;
1461 if (sps->vui_parameters_present_flag)
1462 min_spatial_segmentation_idc = sps->vui_params.min_spatial_segmentation_idc;
1464 /* HEVCDecoderConfigurationVersion = 1
1465 * profile_space | tier_flat | profile_idc |
1466 * profile_compatibility_flags | constraint_indicator_flags |
1470 (pft->profile_space << 5) | (pft->tier_flag << 5) | pft->profile_idc;
1471 for (i = 2; i < 6; i++) {
1472 for (j = 7; j >= 0; j--) {
1473 data[i] |= (pft->profile_compatibility_flag[k] << j);
1479 (pft->progressive_source_flag << 7) |
1480 (pft->interlaced_source_flag << 6) |
1481 (pft->non_packed_constraint_flag << 5) |
1482 (pft->frame_only_constraint_flag << 4) |
1483 (pft->max_12bit_constraint_flag << 3) |
1484 (pft->max_10bit_constraint_flag << 2) |
1485 (pft->max_8bit_constraint_flag << 1) |
1486 (pft->max_422chroma_constraint_flag);
1489 (pft->max_420chroma_constraint_flag << 7) |
1490 (pft->max_monochrome_constraint_flag << 6) |
1491 (pft->intra_constraint_flag << 5) |
1492 (pft->one_picture_only_constraint_flag << 4) |
1493 (pft->lower_bit_rate_constraint_flag << 3) |
1494 (pft->max_14bit_constraint_flag << 2);
1496 data[12] = pft->level_idc;
1497 /* min_spatial_segmentation_idc */
1498 GST_WRITE_UINT16_BE (data + 13, min_spatial_segmentation_idc);
1500 data[15] = 0xfc; /* keeping parrallelismType as zero (unknown) */
1501 data[16] = 0xfc | sps->chroma_format_idc;
1502 data[17] = 0xf8 | sps->bit_depth_luma_minus8;
1503 data[18] = 0xf8 | sps->bit_depth_chroma_minus8;
1504 data[19] = 0x00; /* keep avgFrameRate as unspecified */
1505 data[20] = 0x00; /* keep avgFrameRate as unspecified */
1506 /* constFrameRate(2 bits): 0, stream may or may not be of constant framerate
1507 * numTemporalLayers (3 bits): number of temporal layers, value from SPS
1508 * TemporalIdNested (1 bit): sps_temporal_id_nesting_flag from SPS
1509 * lengthSizeMinusOne (2 bits): plus 1 indicates the length of the NALUnitLength */
1511 0x00 | ((sps->max_sub_layers_minus1 +
1512 1) << 3) | (sps->temporal_id_nesting_flag << 2) | (nl - 1);
1513 GST_WRITE_UINT8 (data + 22, num_arrays); /* numOfArrays */
1519 /* array_completeness | reserved_zero bit | nal_unit_type */
1520 data[0] = 0x00 | 0x20;
1523 GST_WRITE_UINT16_BE (data, num_vps);
1526 for (i = 0; i < GST_H265_MAX_VPS_COUNT; i++) {
1527 if ((nal = h265parse->vps_nals[i])) {
1528 gsize nal_size = gst_buffer_get_size (nal);
1529 GST_WRITE_UINT16_BE (data, nal_size);
1530 gst_buffer_extract (nal, 0, data + 2, nal_size);
1531 data += 2 + nal_size;
1538 /* array_completeness | reserved_zero bit | nal_unit_type */
1539 data[0] = 0x00 | 0x21;
1542 GST_WRITE_UINT16_BE (data, num_sps);
1545 for (i = 0; i < GST_H265_MAX_SPS_COUNT; i++) {
1546 if ((nal = h265parse->sps_nals[i])) {
1547 gsize nal_size = gst_buffer_get_size (nal);
1548 GST_WRITE_UINT16_BE (data, nal_size);
1549 gst_buffer_extract (nal, 0, data + 2, nal_size);
1550 data += 2 + nal_size;
1557 /* array_completeness | reserved_zero bit | nal_unit_type */
1558 data[0] = 0x00 | 0x22;
1561 GST_WRITE_UINT16_BE (data, num_pps);
1564 for (i = 0; i < GST_H265_MAX_PPS_COUNT; i++) {
1565 if ((nal = h265parse->pps_nals[i])) {
1566 gsize nal_size = gst_buffer_get_size (nal);
1567 GST_WRITE_UINT16_BE (data, nal_size);
1568 gst_buffer_extract (nal, 0, data + 2, nal_size);
1569 data += 2 + nal_size;
1573 gst_buffer_unmap (buf, &map);
1579 gst_h265_parse_get_par (GstH265Parse * h265parse, gint * num, gint * den)
1581 if (h265parse->upstream_par_n != -1 && h265parse->upstream_par_d != -1) {
1582 *num = h265parse->upstream_par_n;
1583 *den = h265parse->upstream_par_d;
1585 *num = h265parse->parsed_par_n;
1586 *den = h265parse->parsed_par_d;
1590 static const gchar *
1591 digit_to_string (guint digit)
1593 static const char itoa[][2] = {
1594 "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"
1597 if (G_LIKELY (digit < 10))
1603 static const gchar *
1604 get_tier_string (guint8 tier_flag)
1606 const gchar *tier = NULL;
1616 static const gchar *
1617 get_level_string (guint8 level_idc)
1621 else if (level_idc % 30 == 0)
1622 return digit_to_string (level_idc / 30);
1624 switch (level_idc) {
1652 static inline guint64
1653 profile_to_flag (GstH265Profile p)
1655 return (guint64) 1 << (guint64) p;
1659 get_compatible_profile_caps (GstH265SPS * sps, GstH265Profile profile)
1661 GstCaps *caps = NULL;
1663 GValue compat_profiles = G_VALUE_INIT;
1664 guint64 profiles = 0;
1666 g_value_init (&compat_profiles, GST_TYPE_LIST);
1668 /* Relaxing profiles condition based on decoder capability specified by spec */
1669 if (sps->profile_tier_level.profile_compatibility_flag[1])
1670 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN);
1672 if (sps->profile_tier_level.profile_compatibility_flag[2])
1673 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_10);
1675 if (sps->profile_tier_level.profile_compatibility_flag[3])
1676 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_STILL_PICTURE);
1679 case GST_H265_PROFILE_MAIN_10:
1682 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_12);
1683 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_422_10);
1684 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_422_12);
1685 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_444_10);
1686 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_444_12);
1689 profiles |= profile_to_flag (GST_H265_PROFILE_SCREEN_EXTENDED_MAIN_10);
1692 profiles |= profile_to_flag (GST_H265_PROFILE_SCALABLE_MAIN_10);
1695 case GST_H265_PROFILE_MAIN:
1698 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_10);
1701 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_12);
1702 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_422_10);
1703 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_422_12);
1704 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_444_10);
1705 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_444_12);
1708 profiles |= profile_to_flag (GST_H265_PROFILE_SCREEN_EXTENDED_MAIN);
1709 profiles |= profile_to_flag (GST_H265_PROFILE_SCREEN_EXTENDED_MAIN_10);
1710 profiles |= profile_to_flag (GST_H265_PROFILE_SCREEN_EXTENDED_MAIN_444);
1712 profile_to_flag (GST_H265_PROFILE_SCREEN_EXTENDED_MAIN_444_10);
1715 (GST_H265_PROFILE_SCREEN_EXTENDED_HIGH_THROUGHPUT_444);
1718 (GST_H265_PROFILE_SCREEN_EXTENDED_HIGH_THROUGHPUT_444_10);
1721 (GST_H265_PROFILE_SCREEN_EXTENDED_HIGH_THROUGHPUT_444_14);
1724 profiles |= profile_to_flag (GST_H265_PROFILE_MULTIVIEW_MAIN);
1727 profiles |= profile_to_flag (GST_H265_PROFILE_SCALABLE_MAIN);
1728 profiles |= profile_to_flag (GST_H265_PROFILE_SCALABLE_MAIN_10);
1731 profiles |= profile_to_flag (GST_H265_PROFILE_3D_MAIN);
1734 case GST_H265_PROFILE_MAIN_STILL_PICTURE:
1737 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN);
1738 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_10);
1741 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_12);
1742 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_422_10);
1743 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_422_12);
1744 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_444_10);
1745 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_444_12);
1747 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_INTRA);
1748 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_10_INTRA);
1749 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_12_INTRA);
1750 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_422_10_INTRA);
1751 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_422_12_INTRA);
1752 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_444_INTRA);
1753 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_444_10_INTRA);
1754 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_444_12_INTRA);
1755 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_444_16_INTRA);
1756 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_444_STILL_PICTURE);
1757 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_444_16_STILL_PICTURE);
1760 profiles |= profile_to_flag (GST_H265_PROFILE_SCREEN_EXTENDED_MAIN);
1761 profiles |= profile_to_flag (GST_H265_PROFILE_SCREEN_EXTENDED_MAIN_10);
1762 profiles |= profile_to_flag (GST_H265_PROFILE_SCREEN_EXTENDED_MAIN_444);
1764 profile_to_flag (GST_H265_PROFILE_SCREEN_EXTENDED_MAIN_444_10);
1767 (GST_H265_PROFILE_SCREEN_EXTENDED_HIGH_THROUGHPUT_444);
1770 (GST_H265_PROFILE_SCREEN_EXTENDED_HIGH_THROUGHPUT_444_10);
1773 (GST_H265_PROFILE_SCREEN_EXTENDED_HIGH_THROUGHPUT_444_14);
1776 case GST_H265_PROFILE_MONOCHROME:
1779 profiles |= profile_to_flag (GST_H265_PROFILE_SCREEN_EXTENDED_MAIN);
1780 profiles |= profile_to_flag (GST_H265_PROFILE_SCREEN_EXTENDED_MAIN_10);
1781 profiles |= profile_to_flag (GST_H265_PROFILE_SCREEN_EXTENDED_MAIN_444);
1783 profile_to_flag (GST_H265_PROFILE_SCREEN_EXTENDED_MAIN_444_10);
1786 (GST_H265_PROFILE_SCREEN_EXTENDED_HIGH_THROUGHPUT_444);
1789 (GST_H265_PROFILE_SCREEN_EXTENDED_HIGH_THROUGHPUT_444_10);
1792 (GST_H265_PROFILE_SCREEN_EXTENDED_HIGH_THROUGHPUT_444_14);
1795 case GST_H265_PROFILE_MAIN_444:
1798 profiles |= profile_to_flag (GST_H265_PROFILE_SCREEN_EXTENDED_MAIN_444);
1800 profile_to_flag (GST_H265_PROFILE_SCREEN_EXTENDED_MAIN_444_10);
1803 case GST_H265_PROFILE_MAIN_444_10:
1807 profile_to_flag (GST_H265_PROFILE_SCREEN_EXTENDED_MAIN_444_10);
1810 case GST_H265_PROFILE_HIGH_THROUGHPUT_444:
1815 (GST_H265_PROFILE_SCREEN_EXTENDED_HIGH_THROUGHPUT_444);
1818 (GST_H265_PROFILE_SCREEN_EXTENDED_HIGH_THROUGHPUT_444_10);
1821 (GST_H265_PROFILE_SCREEN_EXTENDED_HIGH_THROUGHPUT_444_14);
1824 case GST_H265_PROFILE_HIGH_THROUGHPUT_444_10:
1829 (GST_H265_PROFILE_SCREEN_EXTENDED_HIGH_THROUGHPUT_444_10);
1832 (GST_H265_PROFILE_SCREEN_EXTENDED_HIGH_THROUGHPUT_444_14);
1835 case GST_H265_PROFILE_HIGH_THROUGHPUT_444_14:
1840 (GST_H265_PROFILE_SCREEN_EXTENDED_HIGH_THROUGHPUT_444_14);
1843 /* All the -intra profiles can map to non-intra profiles, except
1844 the monochrome case for main and main-10. */
1845 case GST_H265_PROFILE_MAIN_INTRA:
1847 if (sps->chroma_format_idc == 1) {
1848 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN);
1850 /* Add all main compatible profiles without monochrome. */
1852 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_10);
1855 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_444_10);
1856 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_444_12);
1859 profiles |= profile_to_flag (GST_H265_PROFILE_SCREEN_EXTENDED_MAIN);
1860 profiles |= profile_to_flag (GST_H265_PROFILE_SCREEN_EXTENDED_MAIN_10);
1863 (GST_H265_PROFILE_SCREEN_EXTENDED_HIGH_THROUGHPUT_444);
1866 (GST_H265_PROFILE_SCREEN_EXTENDED_HIGH_THROUGHPUT_444_10);
1869 (GST_H265_PROFILE_SCREEN_EXTENDED_HIGH_THROUGHPUT_444_14);
1872 profiles |= profile_to_flag (GST_H265_PROFILE_MULTIVIEW_MAIN);
1875 profiles |= profile_to_flag (GST_H265_PROFILE_SCALABLE_MAIN);
1876 profiles |= profile_to_flag (GST_H265_PROFILE_SCALABLE_MAIN_10);
1879 profiles |= profile_to_flag (GST_H265_PROFILE_3D_MAIN);
1882 /* Add all main compatible profiles with monochrome. */
1883 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_12);
1884 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_422_10);
1885 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_422_12);
1886 profiles |= profile_to_flag (GST_H265_PROFILE_SCREEN_EXTENDED_MAIN_444);
1888 profile_to_flag (GST_H265_PROFILE_SCREEN_EXTENDED_MAIN_444_10);
1891 case GST_H265_PROFILE_MAIN_10_INTRA:
1893 if (sps->chroma_format_idc == 1) {
1894 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_10);
1896 /* Add all main-10 compatible profiles without monochrome. */
1898 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_444_10);
1899 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_444_12);
1902 profiles |= profile_to_flag (GST_H265_PROFILE_SCREEN_EXTENDED_MAIN_10);
1905 profiles |= profile_to_flag (GST_H265_PROFILE_SCALABLE_MAIN_10);
1908 /* Add all main-10 compatible profiles with monochrome. */
1909 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_12);
1910 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_422_10);
1911 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_422_12);
1914 case GST_H265_PROFILE_MAIN_12_INTRA:
1915 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_12);
1917 case GST_H265_PROFILE_MAIN_422_10_INTRA:
1918 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_422_10);
1920 case GST_H265_PROFILE_MAIN_422_12_INTRA:
1921 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_422_12);
1923 case GST_H265_PROFILE_MAIN_444_INTRA:
1924 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_444);
1926 /* Add all main444 compatible profiles. */
1928 profiles |= profile_to_flag (GST_H265_PROFILE_SCREEN_EXTENDED_MAIN_444);
1930 profile_to_flag (GST_H265_PROFILE_SCREEN_EXTENDED_MAIN_444_10);
1932 case GST_H265_PROFILE_MAIN_444_10_INTRA:
1933 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_444_10);
1935 /* Add all main444-10 compatible profiles. */
1938 profile_to_flag (GST_H265_PROFILE_SCREEN_EXTENDED_MAIN_444_10);
1940 case GST_H265_PROFILE_MAIN_444_12_INTRA:
1941 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_444_12);
1948 GValue value = G_VALUE_INIT;
1949 const gchar *profile_str;
1950 caps = gst_caps_new_empty_simple ("video/x-h265");
1952 for (i = GST_H265_PROFILE_MAIN; i < GST_H265_PROFILE_MAX; i++) {
1953 if ((profiles & profile_to_flag (i)) == profile_to_flag (i)) {
1954 profile_str = gst_h265_profile_to_string (i);
1956 if (G_UNLIKELY (profile_str == NULL)) {
1957 GST_FIXME ("Unhandled profile index %d", i);
1961 g_value_init (&value, G_TYPE_STRING);
1962 g_value_set_string (&value, profile_str);
1963 gst_value_list_append_value (&compat_profiles, &value);
1964 g_value_unset (&value);
1968 gst_caps_set_value (caps, "profile", &compat_profiles);
1969 g_value_unset (&compat_profiles);
1976 fix_invalid_profile (GstH265Parse * h265parse, GstCaps * caps, GstH265SPS * sps)
1978 /* HACK: This is a work-around to identify some main profile streams
1979 * having wrong profile_idc. There are some wrongly encoded main profile
1980 * streams which doesn't have any of the profile_idc values mentioned in
1981 * Annex-A. Just assuming them as MAIN profile for now if they meet the
1982 * A.3.2 requirement. */
1983 if (sps->chroma_format_idc == 1 && sps->bit_depth_luma_minus8 == 0 &&
1984 sps->bit_depth_chroma_minus8 == 0 && sps->sps_extension_flag == 0) {
1985 gst_caps_set_simple (caps, "profile", G_TYPE_STRING, "main", NULL);
1986 GST_WARNING_OBJECT (h265parse,
1987 "Wrong profile_idc = 0, setting it as main profile !!");
1991 /* if downstream didn't support the exact profile indicated in sps header,
1992 * check for the compatible profiles also */
1994 ensure_caps_profile (GstH265Parse * h265parse, GstCaps * caps, GstH265SPS * sps,
1995 GstH265Profile profile)
1997 GstCaps *peer_caps, *compat_caps;
1999 if (profile == GST_H265_PROFILE_INVALID)
2000 fix_invalid_profile (h265parse, caps, sps);
2002 peer_caps = gst_pad_get_current_caps (GST_BASE_PARSE_SRC_PAD (h265parse));
2003 if (!peer_caps || !gst_caps_can_intersect (caps, peer_caps)) {
2004 GstCaps *filter_caps = gst_caps_new_empty_simple ("video/x-h265");
2007 gst_caps_unref (peer_caps);
2009 gst_pad_peer_query_caps (GST_BASE_PARSE_SRC_PAD (h265parse),
2012 gst_caps_unref (filter_caps);
2015 if (peer_caps && !gst_caps_can_intersect (caps, peer_caps)) {
2016 GstStructure *structure;
2018 compat_caps = get_compatible_profile_caps (sps, profile);
2019 if (compat_caps != NULL) {
2020 GstCaps *res_caps = NULL;
2022 res_caps = gst_caps_intersect (peer_caps, compat_caps);
2024 if (res_caps && !gst_caps_is_empty (res_caps)) {
2025 const gchar *profile_str = NULL;
2027 res_caps = gst_caps_fixate (res_caps);
2028 structure = gst_caps_get_structure (res_caps, 0);
2029 profile_str = gst_structure_get_string (structure, "profile");
2031 gst_caps_set_simple (caps, "profile", G_TYPE_STRING, profile_str,
2033 GST_DEBUG_OBJECT (h265parse,
2034 "Setting compatible profile %s to the caps", profile_str);
2038 gst_caps_unref (res_caps);
2039 gst_caps_unref (compat_caps);
2043 gst_caps_unref (peer_caps);
2047 gst_h265_parse_is_field_interlaced (GstH265Parse * h265parse)
2049 /* FIXME: The SEI is optional, so theoretically there could be files with
2050 * the interlaced_source_flag set to TRUE but no SEI present, or SEI present
2051 * but no pic_struct. Haven't seen any such files in practice, and we don't
2052 * know how to interpret the data without the pic_struct, so we'll treat
2053 * them as progressive */
2055 switch (h265parse->sei_pic_struct) {
2056 case GST_H265_SEI_PIC_STRUCT_TOP_FIELD:
2057 case GST_H265_SEI_PIC_STRUCT_TOP_PAIRED_PREVIOUS_BOTTOM:
2058 case GST_H265_SEI_PIC_STRUCT_TOP_PAIRED_NEXT_BOTTOM:
2059 case GST_H265_SEI_PIC_STRUCT_BOTTOM_FIELD:
2060 case GST_H265_SEI_PIC_STRUCT_BOTTOM_PAIRED_PREVIOUS_TOP:
2061 case GST_H265_SEI_PIC_STRUCT_BOTTOM_PAIRED_NEXT_TOP:
2072 gst_h265_parse_update_src_caps (GstH265Parse * h265parse, GstCaps * caps)
2074 GstH265SPS *sps = NULL;
2075 GstCaps *sink_caps, *src_caps;
2076 gboolean modified = FALSE;
2077 GstBuffer *buf = NULL;
2078 GstStructure *s = NULL;
2081 if (G_UNLIKELY (!gst_pad_has_current_caps (GST_BASE_PARSE_SRC_PAD
2084 else if (G_UNLIKELY (!h265parse->update_caps))
2087 /* if this is being called from the first _setcaps call, caps on the sinkpad
2088 * aren't set yet and so they need to be passed as an argument */
2090 sink_caps = gst_caps_ref (caps);
2092 sink_caps = gst_pad_get_current_caps (GST_BASE_PARSE_SINK_PAD (h265parse));
2094 /* carry over input caps as much as possible; override with our own stuff */
2096 sink_caps = gst_caps_new_empty_simple ("video/x-h265");
2098 s = gst_caps_get_structure (sink_caps, 0);
2100 sps = h265parse->nalparser->last_sps;
2101 GST_DEBUG_OBJECT (h265parse, "sps: %p", sps);
2103 /* only codec-data for nice-and-clean au aligned packetized hevc format */
2104 if ((h265parse->format == GST_H265_PARSE_FORMAT_HVC1
2105 || h265parse->format == GST_H265_PARSE_FORMAT_HEV1)
2106 && h265parse->align == GST_H265_PARSE_ALIGN_AU) {
2107 buf = gst_h265_parse_make_codec_data (h265parse);
2108 if (buf && h265parse->codec_data) {
2111 gst_buffer_map (buf, &map, GST_MAP_READ);
2112 if (map.size != gst_buffer_get_size (h265parse->codec_data) ||
2113 gst_buffer_memcmp (h265parse->codec_data, 0, map.data, map.size))
2116 gst_buffer_unmap (buf, &map);
2118 if (!buf && h265parse->codec_data_in)
2119 buf = gst_buffer_ref (h265parse->codec_data_in);
2125 if (G_UNLIKELY (!sps)) {
2126 caps = gst_caps_copy (sink_caps);
2128 gint crop_width, crop_height;
2129 const gchar *chroma_format = NULL;
2130 guint bit_depth_chroma;
2131 GstH265VPS *vps = sps->vps;
2132 GstH265VUIParams *vui = &sps->vui_params;
2133 gchar *colorimetry = NULL;
2135 GST_DEBUG_OBJECT (h265parse, "vps: %p", vps);
2137 if (sps->conformance_window_flag) {
2138 crop_width = sps->crop_rect_width;
2139 crop_height = sps->crop_rect_height;
2141 crop_width = sps->width;
2142 crop_height = sps->height;
2144 if (gst_h265_parse_is_field_interlaced (h265parse)) {
2148 if (G_UNLIKELY (h265parse->width != crop_width ||
2149 h265parse->height != crop_height)) {
2150 h265parse->width = crop_width;
2151 h265parse->height = crop_height;
2152 GST_INFO_OBJECT (h265parse, "resolution changed %dx%d",
2153 h265parse->width, h265parse->height);
2157 /* 0/1 is set as the default in the codec parser */
2158 if (vui->timing_info_present_flag) {
2159 gint fps_num = 0, fps_den = 1;
2161 if (!(sps->fps_num == 0 && sps->fps_den == 1)) {
2162 fps_num = sps->fps_num;
2163 fps_den = sps->fps_den;
2164 } else if (!(sps->vui_params.time_scale == 0 &&
2165 sps->vui_params.num_units_in_tick == 1)) {
2166 fps_num = sps->vui_params.time_scale;
2167 fps_den = sps->vui_params.num_units_in_tick;
2169 if (gst_h265_parse_is_field_interlaced (h265parse)
2170 && h265parse->parsed_framerate) {
2171 gint new_fps_num, new_fps_den;
2173 gst_util_fraction_multiply (fps_num, fps_den, 1, 2, &new_fps_num,
2175 fps_num = new_fps_num;
2176 fps_den = new_fps_den;
2177 h265parse->parsed_framerate = FALSE;
2181 if (G_UNLIKELY (h265parse->fps_num != fps_num
2182 || h265parse->fps_den != fps_den)) {
2183 GST_INFO_OBJECT (h265parse, "framerate changed %d/%d",
2185 h265parse->fps_num = fps_num;
2186 h265parse->fps_den = fps_den;
2191 if (vui->aspect_ratio_info_present_flag) {
2192 if (G_UNLIKELY ((h265parse->parsed_par_n != vui->par_n)
2193 && (h265parse->parsed_par_d != sps->vui_params.par_d))) {
2194 h265parse->parsed_par_n = vui->par_n;
2195 h265parse->parsed_par_d = vui->par_d;
2196 GST_INFO_OBJECT (h265parse, "pixel aspect ratio has been changed %d/%d",
2197 h265parse->parsed_par_n, h265parse->parsed_par_d);
2203 if (vui->video_signal_type_present_flag &&
2204 vui->colour_description_present_flag) {
2205 GstVideoColorimetry ci = { 0, };
2206 gchar *old_colorimetry = NULL;
2208 if (vui->video_full_range_flag)
2209 ci.range = GST_VIDEO_COLOR_RANGE_0_255;
2211 ci.range = GST_VIDEO_COLOR_RANGE_16_235;
2213 ci.matrix = gst_video_color_matrix_from_iso (vui->matrix_coefficients);
2215 gst_video_transfer_function_from_iso (vui->transfer_characteristics);
2216 ci.primaries = gst_video_color_primaries_from_iso (vui->colour_primaries);
2219 gst_video_colorimetry_to_string (&h265parse->parsed_colorimetry);
2220 colorimetry = gst_video_colorimetry_to_string (&ci);
2222 if (colorimetry && g_strcmp0 (old_colorimetry, colorimetry)) {
2223 GST_INFO_OBJECT (h265parse,
2224 "colorimetry has been changed from %s to %s",
2225 GST_STR_NULL (old_colorimetry), colorimetry);
2226 h265parse->parsed_colorimetry = ci;
2230 g_free (old_colorimetry);
2233 if (G_UNLIKELY (modified || h265parse->update_caps)) {
2234 gint fps_num = h265parse->fps_num;
2235 gint fps_den = h265parse->fps_den;
2236 GstClockTime latency = 0;
2238 caps = gst_caps_copy (sink_caps);
2240 /* sps should give this but upstream overrides */
2241 if (s && gst_structure_has_field (s, "width"))
2242 gst_structure_get_int (s, "width", &width);
2244 width = h265parse->width;
2246 if (s && gst_structure_has_field (s, "height"))
2247 gst_structure_get_int (s, "height", &height);
2249 height = h265parse->height;
2251 gst_caps_set_simple (caps, "width", G_TYPE_INT, width,
2252 "height", G_TYPE_INT, height, NULL);
2254 h265parse->parsed_framerate = FALSE;
2255 /* upstream overrides */
2256 if (s && gst_structure_has_field (s, "framerate"))
2257 gst_structure_get_fraction (s, "framerate", &fps_num, &fps_den);
2259 /* but not necessarily or reliably this */
2264 GST_INFO_OBJECT (h265parse, "setting framerate in caps");
2265 gst_caps_set_simple (caps, "framerate",
2266 GST_TYPE_FRACTION, fps_num, fps_den, NULL);
2267 s2 = gst_caps_get_structure (caps, 0);
2268 gst_structure_get_fraction (s2, "framerate", &h265parse->parsed_fps_n,
2269 &h265parse->parsed_fps_d);
2270 gst_base_parse_set_frame_rate (GST_BASE_PARSE (h265parse),
2271 fps_num, fps_den, 0, 0);
2272 val = sps->profile_tier_level.interlaced_source_flag ? GST_SECOND / 2 :
2274 h265parse->parsed_framerate = TRUE;
2276 /* If we know the frame duration, and if we are not in one of the zero
2277 * latency pattern, add one frame of latency */
2279 h265parse->in_align != GST_H265_PARSE_ALIGN_AU &&
2280 !(h265parse->in_align == GST_H265_PARSE_ALIGN_NAL &&
2281 h265parse->align == GST_H265_PARSE_ALIGN_NAL))
2282 latency = gst_util_uint64_scale (val, fps_den, fps_num);
2284 gst_base_parse_set_latency (GST_BASE_PARSE (h265parse), latency,
2288 bit_depth_chroma = sps->bit_depth_chroma_minus8 + 8;
2290 switch (sps->chroma_format_idc) {
2292 chroma_format = "4:0:0";
2293 bit_depth_chroma = 0;
2296 chroma_format = "4:2:0";
2299 chroma_format = "4:2:2";
2302 chroma_format = "4:4:4";
2309 gst_caps_set_simple (caps, "chroma-format", G_TYPE_STRING,
2310 chroma_format, "bit-depth-luma", G_TYPE_UINT,
2311 sps->bit_depth_luma_minus8 + 8, "bit-depth-chroma", G_TYPE_UINT,
2312 bit_depth_chroma, NULL);
2314 if (colorimetry && (!s || !gst_structure_has_field (s, "colorimetry"))) {
2315 gst_caps_set_simple (caps, "colorimetry", G_TYPE_STRING, colorimetry,
2320 g_free (colorimetry);
2325 const gchar *mdi_str = NULL;
2326 const gchar *cll_str = NULL;
2327 gboolean codec_data_modified = FALSE;
2330 gst_caps_set_simple (caps, "parsed", G_TYPE_BOOLEAN, TRUE,
2331 "stream-format", G_TYPE_STRING,
2332 gst_h265_parse_get_string (h265parse, TRUE, h265parse->format),
2333 "alignment", G_TYPE_STRING,
2334 gst_h265_parse_get_string (h265parse, FALSE, h265parse->align), NULL);
2336 gst_h265_parse_get_par (h265parse, &par_n, &par_d);
2340 st = gst_caps_get_structure (caps, 0);
2341 gst_structure_get_int (st, "width", &width);
2342 gst_structure_get_int (st, "height", &height);
2344 /* If no resolution info, do not consider aspect ratio */
2345 if (par_n != 0 && par_d != 0 && width > 0 && height > 0 &&
2346 (!s || !gst_structure_has_field (s, "pixel-aspect-ratio"))) {
2347 gint new_par_d = par_d;
2348 /* Special case for some encoders which provide an 1:2 pixel aspect ratio
2349 * for HEVC interlaced content, possibly to work around decoders that don't
2350 * support field-based interlacing. Add some defensive checks to check for
2351 * a "common" aspect ratio. */
2352 if (par_n == 1 && par_d == 2
2353 && gst_h265_parse_is_field_interlaced (h265parse)
2354 && !gst_video_is_common_aspect_ratio (width, height, par_n, par_d)
2355 && gst_video_is_common_aspect_ratio (width, height, 1, 1)) {
2356 GST_WARNING_OBJECT (h265parse, "PAR 1/2 makes the aspect ratio of "
2357 "a %d x %d frame uncommon. Switching to 1/1", width, height);
2360 GST_INFO_OBJECT (h265parse, "PAR %d/%d", par_n, new_par_d);
2361 gst_caps_set_simple (caps, "pixel-aspect-ratio", GST_TYPE_FRACTION,
2362 par_n, new_par_d, NULL);
2365 /* set profile and level in caps */
2367 const gchar *profile, *tier, *level;
2370 p = gst_h265_get_profile_from_sps (sps);
2371 /* gst_h265_get_profile_from_sps() method will determine profile
2372 * as defined in spec, with allowing slightly broken profile-tier-level
2373 * bits, then it might not be able to cover all cases.
2374 * If it's still unknown, do guess again */
2375 if (p == GST_H265_PROFILE_INVALID) {
2376 GST_WARNING_OBJECT (h265parse, "Unknown profile, guessing");
2377 switch (sps->chroma_format_idc) {
2379 if (sps->bit_depth_luma_minus8 == 0) {
2380 p = GST_H265_PROFILE_MONOCHROME;
2381 } else if (sps->bit_depth_luma_minus8 <= 2) {
2382 p = GST_H265_PROFILE_MONOCHROME_10;
2383 } else if (sps->bit_depth_luma_minus8 <= 4) {
2384 p = GST_H265_PROFILE_MONOCHROME_12;
2386 p = GST_H265_PROFILE_MONOCHROME_16;
2390 if (sps->bit_depth_luma_minus8 == 0) {
2391 p = GST_H265_PROFILE_MAIN;
2392 } else if (sps->bit_depth_luma_minus8 <= 2) {
2393 p = GST_H265_PROFILE_MAIN_10;
2394 } else if (sps->bit_depth_luma_minus8 <= 4) {
2395 p = GST_H265_PROFILE_MAIN_12;
2397 p = GST_H265_PROFILE_MAIN_444_16_INTRA;
2401 if (sps->bit_depth_luma_minus8 <= 2) {
2402 p = GST_H265_PROFILE_MAIN_422_10;
2403 } else if (sps->bit_depth_luma_minus8 <= 4) {
2404 p = GST_H265_PROFILE_MAIN_422_12;
2406 p = GST_H265_PROFILE_MAIN_444_16_INTRA;
2410 if (sps->bit_depth_luma_minus8 == 0) {
2411 p = GST_H265_PROFILE_MAIN_444;
2412 } else if (sps->bit_depth_luma_minus8 <= 2) {
2413 p = GST_H265_PROFILE_MAIN_444_10;
2414 } else if (sps->bit_depth_luma_minus8 <= 4) {
2415 p = GST_H265_PROFILE_MAIN_444_12;
2417 p = GST_H265_PROFILE_MAIN_444_16_INTRA;
2425 profile = gst_h265_profile_to_string (p);
2427 if (s && gst_structure_has_field (s, "profile")) {
2428 const gchar *profile_sink = gst_structure_get_string (s, "profile");
2429 GstH265Profile p_sink = gst_h265_profile_from_string (profile_sink);
2432 const gchar *profile_src;
2434 p = MAX (p, p_sink);
2435 profile_src = (p == p_sink) ? profile_sink : profile;
2436 GST_INFO_OBJECT (h265parse,
2437 "Upstream profile (%s) is different than in SPS (%s). "
2438 "Using %s.", profile_sink, profile, profile_src);
2439 profile = profile_src;
2443 if (profile != NULL)
2444 gst_caps_set_simple (caps, "profile", G_TYPE_STRING, profile, NULL);
2446 tier = get_tier_string (sps->profile_tier_level.tier_flag);
2448 gst_caps_set_simple (caps, "tier", G_TYPE_STRING, tier, NULL);
2450 level = get_level_string (sps->profile_tier_level.level_idc);
2452 gst_caps_set_simple (caps, "level", G_TYPE_STRING, level, NULL);
2454 /* relax the profile constraint to find a suitable decoder */
2455 ensure_caps_profile (h265parse, caps, sps, p);
2459 mdi_str = gst_structure_get_string (s, "mastering-display-info");
2461 gst_caps_set_simple (caps, "mastering-display-info", G_TYPE_STRING,
2463 } else if (h265parse->mastering_display_info_state !=
2464 GST_H265_PARSE_SEI_EXPIRED &&
2465 !gst_video_mastering_display_info_add_to_caps
2466 (&h265parse->mastering_display_info, caps)) {
2467 GST_WARNING_OBJECT (h265parse,
2468 "Couldn't set mastering display info to caps");
2472 cll_str = gst_structure_get_string (s, "content-light-level");
2474 gst_caps_set_simple (caps, "content-light-level", G_TYPE_STRING, cll_str,
2476 } else if (h265parse->content_light_level_state !=
2477 GST_H265_PARSE_SEI_EXPIRED &&
2478 !gst_video_content_light_level_add_to_caps
2479 (&h265parse->content_light_level, caps)) {
2480 GST_WARNING_OBJECT (h265parse,
2481 "Couldn't set content light level to caps");
2484 src_caps = gst_pad_get_current_caps (GST_BASE_PARSE_SRC_PAD (h265parse));
2487 GstStructure *src_caps_str = gst_caps_get_structure (src_caps, 0);
2489 /* use codec data from old caps for comparison if we have pushed frame for now.
2490 * we don't want to resend caps if everything is same except codec data.
2491 * However, if the updated sps/pps is not in bitstream, we should put
2492 * it on bitstream */
2493 if (gst_structure_has_field (src_caps_str, "codec_data")) {
2494 const GValue *codec_data_value =
2495 gst_structure_get_value (src_caps_str, "codec_data");
2497 if (!GST_VALUE_HOLDS_BUFFER (codec_data_value)) {
2498 GST_WARNING_OBJECT (h265parse, "codec_data does not hold buffer");
2499 } else if (!h265parse->first_frame) {
2500 /* If there is no pushed frame before, we can update caps without worry.
2501 * But updating codec_data in the middle of frames
2502 * (especially on non-keyframe) might make downstream be confused.
2503 * Therefore we are setting old codec data
2504 * (i.e., was pushed to downstream previously) to new caps candidate
2505 * here for gst_caps_is_strictly_equal() to be returned TRUE if only
2506 * the codec_data is different, and to avoid re-sending caps it
2509 gst_caps_set_value (caps, "codec_data", codec_data_value);
2511 /* check for codec_data update to re-send sps/pps inband data if
2512 * current frame has no sps/pps but upstream codec_data was updated.
2513 * Note that have_vps_in_frame is skipped here since it's optional */
2514 if ((!h265parse->have_sps_in_frame || !h265parse->have_pps_in_frame)
2516 GstBuffer *codec_data_buf = gst_value_get_buffer (codec_data_value);
2519 gst_buffer_map (buf, &map, GST_MAP_READ);
2520 if (map.size != gst_buffer_get_size (codec_data_buf) ||
2521 gst_buffer_memcmp (codec_data_buf, 0, map.data, map.size)) {
2522 codec_data_modified = TRUE;
2525 gst_buffer_unmap (buf, &map);
2530 /* remove any left-over codec-data hanging around */
2531 s = gst_caps_get_structure (caps, 0);
2532 gst_structure_remove_field (s, "codec_data");
2536 if (!(src_caps && gst_caps_is_strictly_equal (src_caps, caps))) {
2537 /* update codec data to new value */
2539 gst_caps_set_simple (caps, "codec_data", GST_TYPE_BUFFER, buf, NULL);
2540 gst_buffer_replace (&h265parse->codec_data, buf);
2541 gst_buffer_unref (buf);
2545 /* remove any left-over codec-data hanging around */
2546 s = gst_caps_get_structure (caps, 0);
2547 gst_structure_remove_field (s, "codec_data");
2548 gst_buffer_replace (&h265parse->codec_data, NULL);
2551 gst_pad_set_caps (GST_BASE_PARSE_SRC_PAD (h265parse), caps);
2552 } else if (codec_data_modified) {
2553 GST_DEBUG_OBJECT (h265parse,
2554 "Only codec_data is different, need inband vps/sps/pps update");
2556 /* this will insert updated codec_data with next idr */
2557 h265parse->push_codec = TRUE;
2561 gst_caps_unref (src_caps);
2562 gst_caps_unref (caps);
2565 gst_caps_unref (sink_caps);
2567 gst_buffer_unref (buf);
2571 static GstFlowReturn
2572 gst_h265_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
2574 GstH265Parse *h265parse;
2578 h265parse = GST_H265_PARSE (parse);
2579 buffer = frame->buffer;
2581 gst_h265_parse_update_src_caps (h265parse, NULL);
2583 if (h265parse->fps_num > 0 && h265parse->fps_den > 0) {
2585 gst_h265_parse_is_field_interlaced (h265parse) ? GST_SECOND /
2588 GST_BUFFER_DURATION (buffer) = gst_util_uint64_scale (val,
2589 h265parse->fps_den, h265parse->fps_num);
2592 if (h265parse->keyframe)
2593 GST_BUFFER_FLAG_UNSET (buffer, GST_BUFFER_FLAG_DELTA_UNIT);
2595 GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT);
2597 if (h265parse->discard_bidirectional && h265parse->bidirectional)
2601 if (h265parse->header)
2602 GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_HEADER);
2604 GST_BUFFER_FLAG_UNSET (buffer, GST_BUFFER_FLAG_HEADER);
2606 if (h265parse->discont) {
2607 GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
2608 h265parse->discont = FALSE;
2611 if (h265parse->marker) {
2612 GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_MARKER);
2613 h265parse->marker = FALSE;
2615 GST_BUFFER_FLAG_UNSET (buffer, GST_BUFFER_FLAG_MARKER);
2618 /* replace with transformed HEVC output if applicable */
2619 av = gst_adapter_available (h265parse->frame_out);
2623 buf = gst_adapter_take_buffer (h265parse->frame_out, av);
2624 gst_buffer_copy_into (buf, buffer, GST_BUFFER_COPY_METADATA, 0, -1);
2625 gst_buffer_replace (&frame->out_buffer, buf);
2626 gst_buffer_unref (buf);
2633 GST_DEBUG_OBJECT (h265parse, "Discarding bidirectional frame");
2634 frame->flags |= GST_BASE_PARSE_FRAME_FLAG_DROP;
2635 gst_h265_parse_reset_frame (h265parse);
2640 /* sends a codec NAL downstream, decorating and transforming as needed.
2641 * No ownership is taken of @nal */
2642 static GstFlowReturn
2643 gst_h265_parse_push_codec_buffer (GstH265Parse * h265parse, GstBuffer * nal,
2648 gst_buffer_map (nal, &map, GST_MAP_READ);
2649 nal = gst_h265_parse_wrap_nal (h265parse, h265parse->format,
2650 map.data, map.size);
2651 gst_buffer_unmap (nal, &map);
2653 if (h265parse->discont) {
2654 GST_BUFFER_FLAG_SET (nal, GST_BUFFER_FLAG_DISCONT);
2655 h265parse->discont = FALSE;
2658 GST_BUFFER_PTS (nal) = GST_BUFFER_PTS (buffer);
2659 GST_BUFFER_DTS (nal) = GST_BUFFER_DTS (buffer);
2660 GST_BUFFER_DURATION (nal) = 0;
2662 return gst_pad_push (GST_BASE_PARSE_SRC_PAD (h265parse), nal);
2666 check_pending_key_unit_event (GstEvent * pending_event, GstSegment * segment,
2667 GstClockTime timestamp, guint flags, GstClockTime pending_key_unit_ts)
2669 GstClockTime running_time, stream_time;
2670 gboolean all_headers;
2672 GstEvent *event = NULL;
2674 g_return_val_if_fail (segment != NULL, NULL);
2676 if (pending_event == NULL)
2679 if (GST_CLOCK_TIME_IS_VALID (pending_key_unit_ts) &&
2680 timestamp == GST_CLOCK_TIME_NONE)
2683 running_time = gst_segment_to_running_time (segment,
2684 GST_FORMAT_TIME, timestamp);
2686 GST_INFO ("now %" GST_TIME_FORMAT " wanted %" GST_TIME_FORMAT,
2687 GST_TIME_ARGS (running_time), GST_TIME_ARGS (pending_key_unit_ts));
2688 if (GST_CLOCK_TIME_IS_VALID (pending_key_unit_ts) &&
2689 running_time < pending_key_unit_ts)
2692 if (flags & GST_BUFFER_FLAG_DELTA_UNIT) {
2693 GST_DEBUG ("pending force key unit, waiting for keyframe");
2697 stream_time = gst_segment_to_stream_time (segment,
2698 GST_FORMAT_TIME, timestamp);
2700 if (!gst_video_event_parse_upstream_force_key_unit (pending_event,
2701 NULL, &all_headers, &count)) {
2702 gst_video_event_parse_downstream_force_key_unit (pending_event, NULL,
2703 NULL, NULL, &all_headers, &count);
2707 gst_video_event_new_downstream_force_key_unit (timestamp, stream_time,
2708 running_time, all_headers, count);
2709 gst_event_set_seqnum (event, gst_event_get_seqnum (pending_event));
2716 gst_h265_parse_prepare_key_unit (GstH265Parse * parse, GstEvent * event)
2718 GstClockTime running_time;
2720 #ifndef GST_DISABLE_GST_DEBUG
2721 gboolean have_vps, have_sps, have_pps;
2725 parse->pending_key_unit_ts = GST_CLOCK_TIME_NONE;
2726 gst_event_replace (&parse->force_key_unit_event, NULL);
2728 gst_video_event_parse_downstream_force_key_unit (event,
2729 NULL, NULL, &running_time, NULL, &count);
2731 GST_INFO_OBJECT (parse, "pushing downstream force-key-unit event %d "
2732 "%" GST_TIME_FORMAT " count %d", gst_event_get_seqnum (event),
2733 GST_TIME_ARGS (running_time), count);
2734 gst_pad_push_event (GST_BASE_PARSE_SRC_PAD (parse), event);
2736 #ifndef GST_DISABLE_GST_DEBUG
2737 have_vps = have_sps = have_pps = FALSE;
2738 for (i = 0; i < GST_H265_MAX_VPS_COUNT; i++) {
2739 if (parse->vps_nals[i] != NULL) {
2744 for (i = 0; i < GST_H265_MAX_SPS_COUNT; i++) {
2745 if (parse->sps_nals[i] != NULL) {
2750 for (i = 0; i < GST_H265_MAX_PPS_COUNT; i++) {
2751 if (parse->pps_nals[i] != NULL) {
2757 GST_INFO_OBJECT (parse,
2758 "preparing key unit, have vps %d have sps %d have pps %d", have_vps,
2759 have_sps, have_pps);
2762 /* set push_codec to TRUE so that pre_push_frame sends VPS/SPS/PPS again */
2763 parse->push_codec = TRUE;
2767 gst_h265_parse_handle_vps_sps_pps_nals (GstH265Parse * h265parse,
2768 GstBuffer * buffer, GstBaseParseFrame * frame)
2770 GstBuffer *codec_nal;
2772 gboolean send_done = FALSE;
2774 if (h265parse->have_vps_in_frame && h265parse->have_sps_in_frame
2775 && h265parse->have_pps_in_frame) {
2776 GST_DEBUG_OBJECT (h265parse, "VPS/SPS/PPS exist in frame, will not insert");
2780 if (h265parse->align == GST_H265_PARSE_ALIGN_NAL) {
2781 /* send separate config NAL buffers */
2782 GST_DEBUG_OBJECT (h265parse, "- sending VPS/SPS/PPS");
2783 for (i = 0; i < GST_H265_MAX_VPS_COUNT; i++) {
2784 if ((codec_nal = h265parse->vps_nals[i])) {
2785 GST_DEBUG_OBJECT (h265parse, "sending VPS nal");
2786 gst_h265_parse_push_codec_buffer (h265parse, codec_nal, buffer);
2790 for (i = 0; i < GST_H265_MAX_SPS_COUNT; i++) {
2791 if ((codec_nal = h265parse->sps_nals[i])) {
2792 GST_DEBUG_OBJECT (h265parse, "sending SPS nal");
2793 gst_h265_parse_push_codec_buffer (h265parse, codec_nal, buffer);
2797 for (i = 0; i < GST_H265_MAX_PPS_COUNT; i++) {
2798 if ((codec_nal = h265parse->pps_nals[i])) {
2799 GST_DEBUG_OBJECT (h265parse, "sending PPS nal");
2800 gst_h265_parse_push_codec_buffer (h265parse, codec_nal, buffer);
2805 /* insert config NALs into AU */
2808 const gboolean bs = h265parse->format == GST_H265_PARSE_FORMAT_BYTE;
2809 const gint nls = 4 - h265parse->nal_length_size;
2812 gst_byte_writer_init_with_size (&bw, gst_buffer_get_size (buffer), FALSE);
2813 ok = gst_byte_writer_put_buffer (&bw, buffer, 0, h265parse->idr_pos);
2814 GST_DEBUG_OBJECT (h265parse, "- inserting VPS/SPS/PPS");
2815 for (i = 0; i < GST_H265_MAX_VPS_COUNT; i++) {
2816 if ((codec_nal = h265parse->vps_nals[i])) {
2817 gsize nal_size = gst_buffer_get_size (codec_nal);
2818 GST_DEBUG_OBJECT (h265parse, "inserting VPS nal");
2820 ok &= gst_byte_writer_put_uint32_be (&bw, 1);
2822 ok &= gst_byte_writer_put_uint32_be (&bw, (nal_size << (nls * 8)));
2823 ok &= gst_byte_writer_set_pos (&bw,
2824 gst_byte_writer_get_pos (&bw) - nls);
2827 ok &= gst_byte_writer_put_buffer (&bw, codec_nal, 0, nal_size);
2831 for (i = 0; i < GST_H265_MAX_SPS_COUNT; i++) {
2832 if ((codec_nal = h265parse->sps_nals[i])) {
2833 gsize nal_size = gst_buffer_get_size (codec_nal);
2834 GST_DEBUG_OBJECT (h265parse, "inserting SPS nal");
2836 ok &= gst_byte_writer_put_uint32_be (&bw, 1);
2838 ok &= gst_byte_writer_put_uint32_be (&bw, (nal_size << (nls * 8)));
2839 ok &= gst_byte_writer_set_pos (&bw,
2840 gst_byte_writer_get_pos (&bw) - nls);
2843 ok &= gst_byte_writer_put_buffer (&bw, codec_nal, 0, nal_size);
2847 for (i = 0; i < GST_H265_MAX_PPS_COUNT; i++) {
2848 if ((codec_nal = h265parse->pps_nals[i])) {
2849 gsize nal_size = gst_buffer_get_size (codec_nal);
2850 GST_DEBUG_OBJECT (h265parse, "inserting PPS nal");
2852 ok &= gst_byte_writer_put_uint32_be (&bw, 1);
2854 ok &= gst_byte_writer_put_uint32_be (&bw, (nal_size << (nls * 8)));
2855 ok &= gst_byte_writer_set_pos (&bw,
2856 gst_byte_writer_get_pos (&bw) - nls);
2858 ok &= gst_byte_writer_put_buffer (&bw, codec_nal, 0, nal_size);
2862 ok &= gst_byte_writer_put_buffer (&bw, buffer, h265parse->idr_pos, -1);
2863 /* collect result and push */
2864 new_buf = gst_byte_writer_reset_and_get_buffer (&bw);
2865 gst_buffer_copy_into (new_buf, buffer, GST_BUFFER_COPY_METADATA, 0, -1);
2866 /* should already be keyframe/IDR, but it may not have been,
2867 * so mark it as such to avoid being discarded by picky decoder */
2868 GST_BUFFER_FLAG_UNSET (new_buf, GST_BUFFER_FLAG_DELTA_UNIT);
2869 gst_buffer_replace (&frame->out_buffer, new_buf);
2870 gst_buffer_unref (new_buf);
2871 /* some result checking seems to make some compilers happy */
2872 if (G_UNLIKELY (!ok)) {
2873 GST_ERROR_OBJECT (h265parse, "failed to insert SPS/PPS");
2880 static GstFlowReturn
2881 gst_h265_parse_pre_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
2883 GstH265Parse *h265parse;
2886 GstBuffer *parse_buffer = NULL;
2888 h265parse = GST_H265_PARSE (parse);
2890 if (h265parse->first_frame) {
2891 GstTagList *taglist;
2895 caps = gst_pad_get_current_caps (GST_BASE_PARSE_SRC_PAD (parse));
2896 if (G_UNLIKELY (caps == NULL)) {
2897 if (GST_PAD_IS_FLUSHING (GST_BASE_PARSE_SRC_PAD (parse))) {
2898 GST_INFO_OBJECT (parse, "Src pad is flushing");
2899 return GST_FLOW_FLUSHING;
2901 GST_INFO_OBJECT (parse, "Src pad is not negotiated!");
2902 return GST_FLOW_NOT_NEGOTIATED;
2906 taglist = gst_tag_list_new_empty ();
2907 gst_pb_utils_add_codec_description_to_tag_list (taglist,
2908 GST_TAG_VIDEO_CODEC, caps);
2909 gst_caps_unref (caps);
2911 gst_base_parse_merge_tags (parse, taglist, GST_TAG_MERGE_REPLACE);
2912 gst_tag_list_unref (taglist);
2914 /* also signals the end of first-frame processing */
2915 h265parse->first_frame = FALSE;
2918 buffer = frame->buffer;
2920 if ((event = check_pending_key_unit_event (h265parse->force_key_unit_event,
2921 &parse->segment, GST_BUFFER_TIMESTAMP (buffer),
2922 GST_BUFFER_FLAGS (buffer), h265parse->pending_key_unit_ts))) {
2923 gst_h265_parse_prepare_key_unit (h265parse, event);
2926 /* periodic VPS/SPS/PPS sending */
2927 if (h265parse->interval > 0 || h265parse->push_codec) {
2928 GstClockTime timestamp = GST_BUFFER_TIMESTAMP (buffer);
2930 gboolean initial_frame = FALSE;
2933 if (!GST_CLOCK_TIME_IS_VALID (h265parse->last_report)) {
2934 h265parse->last_report = timestamp;
2935 initial_frame = TRUE;
2938 if (h265parse->idr_pos >= 0) {
2939 GST_LOG_OBJECT (h265parse, "IDR nal at offset %d", h265parse->idr_pos);
2941 if (timestamp > h265parse->last_report)
2942 diff = timestamp - h265parse->last_report;
2946 GST_LOG_OBJECT (h265parse,
2947 "now %" GST_TIME_FORMAT ", last VPS/SPS/PPS %" GST_TIME_FORMAT,
2948 GST_TIME_ARGS (timestamp), GST_TIME_ARGS (h265parse->last_report));
2950 GST_DEBUG_OBJECT (h265parse,
2951 "interval since last VPS/SPS/PPS %" GST_TIME_FORMAT,
2952 GST_TIME_ARGS (diff));
2954 if (GST_TIME_AS_SECONDS (diff) >= h265parse->interval ||
2955 initial_frame || h265parse->push_codec) {
2956 GstClockTime new_ts;
2958 /* avoid overwriting a perfectly fine timestamp */
2959 new_ts = GST_CLOCK_TIME_IS_VALID (timestamp) ? timestamp :
2960 h265parse->last_report;
2962 if (gst_h265_parse_handle_vps_sps_pps_nals (h265parse, buffer, frame)) {
2963 h265parse->last_report = new_ts;
2967 /* we pushed whatever we had */
2968 h265parse->push_codec = FALSE;
2969 h265parse->have_vps = FALSE;
2970 h265parse->have_sps = FALSE;
2971 h265parse->have_pps = FALSE;
2972 h265parse->state &= GST_H265_PARSE_STATE_VALID_PICTURE_HEADERS;
2974 } else if (h265parse->interval == -1) {
2975 if (h265parse->idr_pos >= 0) {
2976 GST_LOG_OBJECT (h265parse, "IDR nal at offset %d", h265parse->idr_pos);
2978 gst_h265_parse_handle_vps_sps_pps_nals (h265parse, buffer, frame);
2980 /* we pushed whatever we had */
2981 h265parse->push_codec = FALSE;
2982 h265parse->have_vps = FALSE;
2983 h265parse->have_sps = FALSE;
2984 h265parse->have_pps = FALSE;
2985 h265parse->state &= GST_H265_PARSE_STATE_VALID_PICTURE_HEADERS;
2989 if (frame->out_buffer) {
2990 parse_buffer = frame->out_buffer =
2991 gst_buffer_make_writable (frame->out_buffer);
2993 parse_buffer = frame->buffer = gst_buffer_make_writable (frame->buffer);
2996 /* see section D.3.3 of the spec */
2997 switch (h265parse->sei_pic_struct) {
2998 case GST_H265_SEI_PIC_STRUCT_TOP_BOTTOM:
2999 case GST_H265_SEI_PIC_STRUCT_BOTTOM_TOP:
3000 case GST_H265_SEI_PIC_STRUCT_TOP_BOTTOM_TOP:
3001 case GST_H265_SEI_PIC_STRUCT_BOTTOM_TOP_BOTTOM:
3002 GST_BUFFER_FLAG_SET (parse_buffer, GST_VIDEO_BUFFER_FLAG_INTERLACED);
3004 case GST_H265_SEI_PIC_STRUCT_TOP_FIELD:
3005 case GST_H265_SEI_PIC_STRUCT_TOP_PAIRED_NEXT_BOTTOM:
3006 case GST_H265_SEI_PIC_STRUCT_TOP_PAIRED_PREVIOUS_BOTTOM:
3007 GST_BUFFER_FLAG_SET (parse_buffer, GST_VIDEO_BUFFER_FLAG_INTERLACED);
3008 GST_BUFFER_FLAG_SET (parse_buffer, GST_VIDEO_BUFFER_FLAG_TOP_FIELD);
3010 case GST_H265_SEI_PIC_STRUCT_BOTTOM_FIELD:
3011 case GST_H265_SEI_PIC_STRUCT_BOTTOM_PAIRED_PREVIOUS_TOP:
3012 case GST_H265_SEI_PIC_STRUCT_BOTTOM_PAIRED_NEXT_TOP:
3013 GST_BUFFER_FLAG_SET (parse_buffer, GST_VIDEO_BUFFER_FLAG_INTERLACED);
3014 GST_BUFFER_FLAG_SET (parse_buffer, GST_VIDEO_BUFFER_FLAG_BOTTOM_FIELD);
3023 for (i = 0; i < h265parse->time_code.num_clock_ts; i++) {
3024 gint field_count = -1;
3026 GstVideoTimeCodeFlags flags = 0;
3028 if (!h265parse->time_code.clock_timestamp_flag[i])
3031 h265parse->time_code.clock_timestamp_flag[i] = 0;
3034 switch (h265parse->sei_pic_struct) {
3035 case GST_H265_SEI_PIC_STRUCT_FRAME:
3036 case GST_H265_SEI_PIC_STRUCT_TOP_FIELD:
3037 case GST_H265_SEI_PIC_STRUCT_BOTTOM_FIELD:
3038 field_count = h265parse->sei_pic_struct;
3040 case GST_H265_SEI_PIC_STRUCT_TOP_BOTTOM:
3041 case GST_H265_SEI_PIC_STRUCT_TOP_PAIRED_PREVIOUS_BOTTOM:
3042 case GST_H265_SEI_PIC_STRUCT_TOP_PAIRED_NEXT_BOTTOM:
3043 field_count = i + 1;
3045 case GST_H265_SEI_PIC_STRUCT_BOTTOM_TOP:
3046 case GST_H265_SEI_PIC_STRUCT_BOTTOM_PAIRED_PREVIOUS_TOP:
3047 case GST_H265_SEI_PIC_STRUCT_BOTTOM_PAIRED_NEXT_TOP:
3048 field_count = 2 - i;
3050 case GST_H265_SEI_PIC_STRUCT_TOP_BOTTOM_TOP:
3051 field_count = i % 2 ? 2 : 1;
3053 case GST_H265_SEI_PIC_STRUCT_BOTTOM_TOP_BOTTOM:
3054 field_count = i % 2 ? 1 : 2;
3056 case GST_H265_SEI_PIC_STRUCT_FRAME_DOUBLING:
3057 case GST_H265_SEI_PIC_STRUCT_FRAME_TRIPLING:
3062 if (field_count == -1) {
3063 GST_WARNING_OBJECT (parse,
3064 "failed to determine field count for timecode");
3068 /* Dropping of the two lowest (value 0 and 1) n_frames[ i ] counts when
3069 * seconds_value[ i ] is equal to 0 and minutes_value[ i ] is not an integer
3071 if (h265parse->time_code.counting_type[i] == 4)
3072 flags |= GST_VIDEO_TIME_CODE_FLAGS_DROP_FRAME;
3074 if (h265parse->sei_pic_struct != GST_H265_SEI_PIC_STRUCT_FRAME)
3075 flags |= GST_VIDEO_TIME_CODE_FLAGS_INTERLACED;
3078 gst_util_uint64_scale_int (h265parse->time_code.n_frames[i], 1,
3079 2 - h265parse->time_code.units_field_based_flag[i]);
3081 gst_buffer_add_video_time_code_meta_full (parse_buffer,
3082 h265parse->parsed_fps_n,
3083 h265parse->parsed_fps_d,
3086 h265parse->time_code.hours_flag[i] ? h265parse->time_code.
3088 h265parse->time_code.minutes_flag[i] ? h265parse->time_code.
3089 minutes_value[i] : 0,
3090 h265parse->time_code.seconds_flag[i] ? h265parse->time_code.
3091 seconds_value[i] : 0, n_frames, field_count);
3095 gst_video_push_user_data ((GstElement *) h265parse, &h265parse->user_data,
3098 gst_h265_parse_reset_frame (h265parse);
3104 gst_h265_parse_set_caps (GstBaseParse * parse, GstCaps * caps)
3106 GstH265Parse *h265parse;
3108 const GValue *value;
3109 GstBuffer *codec_data = NULL;
3111 guint format, align;
3112 guint num_nals, i, j;
3113 GstH265NalUnit nalu;
3114 GstH265ParserResult parseres;
3117 h265parse = GST_H265_PARSE (parse);
3120 h265parse->push_codec = FALSE;
3122 old_caps = gst_pad_get_current_caps (GST_BASE_PARSE_SINK_PAD (parse));
3124 if (!gst_caps_is_equal (old_caps, caps))
3125 gst_h265_parse_reset_stream_info (h265parse);
3126 gst_caps_unref (old_caps);
3129 str = gst_caps_get_structure (caps, 0);
3131 /* accept upstream info if provided */
3132 gst_structure_get_int (str, "width", &h265parse->width);
3133 gst_structure_get_int (str, "height", &h265parse->height);
3134 gst_structure_get_fraction (str, "framerate", &h265parse->fps_num,
3135 &h265parse->fps_den);
3136 gst_structure_get_fraction (str, "pixel-aspect-ratio",
3137 &h265parse->upstream_par_n, &h265parse->upstream_par_d);
3139 /* get upstream format and align from caps */
3140 gst_h265_parse_format_from_caps (caps, &format, &align);
3142 /* packetized video has a codec_data */
3143 if (format != GST_H265_PARSE_FORMAT_BYTE &&
3144 (value = gst_structure_get_value (str, "codec_data"))) {
3147 guint num_nal_arrays;
3149 GST_DEBUG_OBJECT (h265parse, "have packetized h265");
3150 /* make note for optional split processing */
3151 h265parse->packetized = TRUE;
3153 codec_data = gst_value_get_buffer (value);
3156 gst_buffer_map (codec_data, &map, GST_MAP_READ);
3160 /* parse the hvcC data */
3162 gst_buffer_unmap (codec_data, &map);
3163 goto hvcc_too_small;
3165 /* parse the version, this must be one but
3166 * is zero until the spec is finalized */
3167 if (data[0] != 0 && data[0] != 1) {
3168 gst_buffer_unmap (codec_data, &map);
3172 h265parse->nal_length_size = (data[21] & 0x03) + 1;
3173 GST_DEBUG_OBJECT (h265parse, "nal length size %u",
3174 h265parse->nal_length_size);
3176 num_nal_arrays = data[22];
3179 for (i = 0; i < num_nal_arrays; i++) {
3180 if (off + 3 >= size) {
3181 gst_buffer_unmap (codec_data, &map);
3182 goto hvcc_too_small;
3185 num_nals = GST_READ_UINT16_BE (data + off + 1);
3187 for (j = 0; j < num_nals; j++) {
3188 parseres = gst_h265_parser_identify_nalu_hevc (h265parse->nalparser,
3189 data, off, size, 2, &nalu);
3191 if (parseres != GST_H265_PARSER_OK) {
3192 gst_buffer_unmap (codec_data, &map);
3193 goto hvcc_too_small;
3196 gst_h265_parse_process_nal (h265parse, &nalu);
3197 off = nalu.offset + nalu.size;
3200 gst_buffer_unmap (codec_data, &map);
3202 /* don't confuse codec_data with inband vps/sps/pps */
3203 h265parse->have_vps_in_frame = FALSE;
3204 h265parse->have_sps_in_frame = FALSE;
3205 h265parse->have_pps_in_frame = FALSE;
3207 GST_DEBUG_OBJECT (h265parse, "have bytestream h265");
3208 /* nothing to pre-process */
3209 h265parse->packetized = FALSE;
3210 /* we have 4 sync bytes */
3211 h265parse->nal_length_size = 4;
3213 if (format == GST_H265_PARSE_FORMAT_NONE) {
3214 format = GST_H265_PARSE_FORMAT_BYTE;
3215 align = GST_H265_PARSE_ALIGN_AU;
3222 /* prefer input type determined above */
3223 in_caps = gst_caps_new_simple ("video/x-h265",
3224 "parsed", G_TYPE_BOOLEAN, TRUE,
3225 "stream-format", G_TYPE_STRING,
3226 gst_h265_parse_get_string (h265parse, TRUE, format),
3227 "alignment", G_TYPE_STRING,
3228 gst_h265_parse_get_string (h265parse, FALSE, align), NULL);
3229 /* negotiate with downstream, sets ->format and ->align */
3230 gst_h265_parse_negotiate (h265parse, format, in_caps);
3231 gst_caps_unref (in_caps);
3234 if (format == h265parse->format && align == h265parse->align) {
3235 /* do not set CAPS and passthrough mode if SPS/PPS have not been parsed */
3236 if (h265parse->have_sps && h265parse->have_pps) {
3237 /* Don't enable passthrough here. This element will parse various
3238 * SEI messages which would be very important/useful for downstream
3239 * (HDR, timecode for example)
3242 gst_base_parse_set_passthrough (parse, TRUE);
3245 /* we did parse codec-data and might supplement src caps */
3246 gst_h265_parse_update_src_caps (h265parse, caps);
3248 } else if (format == GST_H265_PARSE_FORMAT_HVC1
3249 || format == GST_H265_PARSE_FORMAT_HEV1) {
3250 /* if input != output, and input is hevc, must split before anything else */
3251 /* arrange to insert codec-data in-stream if needed.
3252 * src caps are only arranged for later on */
3253 h265parse->push_codec = TRUE;
3254 h265parse->have_vps = FALSE;
3255 h265parse->have_sps = FALSE;
3256 h265parse->have_pps = FALSE;
3257 if (h265parse->align == GST_H265_PARSE_ALIGN_NAL)
3258 h265parse->split_packetized = TRUE;
3259 h265parse->packetized = TRUE;
3262 h265parse->in_align = align;
3269 GST_DEBUG_OBJECT (h265parse, "hvcC size %" G_GSIZE_FORMAT " < 23", size);
3274 GST_DEBUG_OBJECT (h265parse, "wrong hvcC version");
3279 GST_DEBUG_OBJECT (h265parse, "wrong codec-data type");
3284 GST_WARNING_OBJECT (h265parse, "refused caps %" GST_PTR_FORMAT, caps);
3290 remove_fields (GstCaps * caps, gboolean all)
3294 n = gst_caps_get_size (caps);
3295 for (i = 0; i < n; i++) {
3296 GstStructure *s = gst_caps_get_structure (caps, i);
3299 gst_structure_remove_field (s, "alignment");
3300 gst_structure_remove_field (s, "stream-format");
3302 gst_structure_remove_field (s, "parsed");
3307 gst_h265_parse_get_caps (GstBaseParse * parse, GstCaps * filter)
3309 GstCaps *peercaps, *templ;
3310 GstCaps *res, *tmp, *pcopy;
3312 templ = gst_pad_get_pad_template_caps (GST_BASE_PARSE_SINK_PAD (parse));
3314 GstCaps *fcopy = gst_caps_copy (filter);
3315 /* Remove the fields we convert */
3316 remove_fields (fcopy, TRUE);
3317 peercaps = gst_pad_peer_query_caps (GST_BASE_PARSE_SRC_PAD (parse), fcopy);
3318 gst_caps_unref (fcopy);
3320 peercaps = gst_pad_peer_query_caps (GST_BASE_PARSE_SRC_PAD (parse), NULL);
3322 pcopy = gst_caps_copy (peercaps);
3323 remove_fields (pcopy, TRUE);
3325 res = gst_caps_intersect_full (pcopy, templ, GST_CAPS_INTERSECT_FIRST);
3326 gst_caps_unref (pcopy);
3327 gst_caps_unref (templ);
3330 GstCaps *tmp = gst_caps_intersect_full (res, filter,
3331 GST_CAPS_INTERSECT_FIRST);
3332 gst_caps_unref (res);
3336 /* Try if we can put the downstream caps first */
3337 pcopy = gst_caps_copy (peercaps);
3338 remove_fields (pcopy, FALSE);
3339 tmp = gst_caps_intersect_full (pcopy, res, GST_CAPS_INTERSECT_FIRST);
3340 gst_caps_unref (pcopy);
3341 if (!gst_caps_is_empty (tmp))
3342 res = gst_caps_merge (tmp, res);
3344 gst_caps_unref (tmp);
3346 gst_caps_unref (peercaps);
3351 gst_h265_parse_event (GstBaseParse * parse, GstEvent * event)
3354 GstH265Parse *h265parse = GST_H265_PARSE (parse);
3356 switch (GST_EVENT_TYPE (event)) {
3357 case GST_EVENT_CUSTOM_DOWNSTREAM:
3359 GstClockTime timestamp, stream_time, running_time;
3360 gboolean all_headers;
3363 if (gst_video_event_is_force_key_unit (event)) {
3364 gst_video_event_parse_downstream_force_key_unit (event,
3365 ×tamp, &stream_time, &running_time, &all_headers, &count);
3367 GST_INFO_OBJECT (h265parse, "received downstream force key unit event, "
3368 "seqnum %d running_time %" GST_TIME_FORMAT
3369 " all_headers %d count %d", gst_event_get_seqnum (event),
3370 GST_TIME_ARGS (running_time), all_headers, count);
3371 if (h265parse->force_key_unit_event) {
3372 GST_INFO_OBJECT (h265parse, "ignoring force key unit event "
3373 "as one is already queued");
3375 h265parse->pending_key_unit_ts = running_time;
3376 gst_event_replace (&h265parse->force_key_unit_event, event);
3378 gst_event_unref (event);
3381 res = GST_BASE_PARSE_CLASS (parent_class)->sink_event (parse, event);
3386 case GST_EVENT_FLUSH_STOP:
3387 case GST_EVENT_SEGMENT_DONE:
3388 h265parse->push_codec = TRUE;
3389 res = GST_BASE_PARSE_CLASS (parent_class)->sink_event (parse, event);
3391 case GST_EVENT_SEGMENT:
3393 const GstSegment *segment = NULL;
3395 gst_event_parse_segment (event, &segment);
3397 h265parse->last_report = GST_CLOCK_TIME_NONE;
3399 if (segment->flags & GST_SEEK_FLAG_TRICKMODE_FORWARD_PREDICTED) {
3400 GST_DEBUG_OBJECT (h265parse, "Will discard bidirectional frames");
3401 h265parse->discard_bidirectional = TRUE;
3404 res = GST_BASE_PARSE_CLASS (parent_class)->sink_event (parse, event);
3408 res = GST_BASE_PARSE_CLASS (parent_class)->sink_event (parse, event);
3415 gst_h265_parse_src_event (GstBaseParse * parse, GstEvent * event)
3418 GstH265Parse *h265parse = GST_H265_PARSE (parse);
3420 switch (GST_EVENT_TYPE (event)) {
3421 case GST_EVENT_CUSTOM_UPSTREAM:
3423 GstClockTime running_time;
3424 gboolean all_headers;
3427 if (gst_video_event_is_force_key_unit (event)) {
3428 gst_video_event_parse_upstream_force_key_unit (event,
3429 &running_time, &all_headers, &count);
3431 GST_INFO_OBJECT (h265parse, "received upstream force-key-unit event, "
3432 "seqnum %d running_time %" GST_TIME_FORMAT
3433 " all_headers %d count %d", gst_event_get_seqnum (event),
3434 GST_TIME_ARGS (running_time), all_headers, count);
3437 h265parse->pending_key_unit_ts = running_time;
3438 gst_event_replace (&h265parse->force_key_unit_event, event);
3441 res = GST_BASE_PARSE_CLASS (parent_class)->src_event (parse, event);
3445 res = GST_BASE_PARSE_CLASS (parent_class)->src_event (parse, event);
3453 gst_h265_parse_set_property (GObject * object, guint prop_id,
3454 const GValue * value, GParamSpec * pspec)
3456 GstH265Parse *parse;
3457 parse = GST_H265_PARSE (object);
3460 case PROP_CONFIG_INTERVAL:
3461 parse->interval = g_value_get_int (value);
3464 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
3470 gst_h265_parse_get_property (GObject * object, guint prop_id, GValue * value,
3473 GstH265Parse *parse;
3474 parse = GST_H265_PARSE (object);
3477 case PROP_CONFIG_INTERVAL:
3478 g_value_set_int (value, parse->interval);
3481 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);