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 "gsth265parse.h"
31 GST_DEBUG_CATEGORY (h265_parse_debug);
32 #define GST_CAT_DEFAULT h265_parse_debug
34 #define DEFAULT_CONFIG_INTERVAL (0)
44 GST_H265_PARSE_FORMAT_NONE,
45 GST_H265_PARSE_FORMAT_HVC1,
46 GST_H265_PARSE_FORMAT_HEV1,
47 GST_H265_PARSE_FORMAT_BYTE
52 GST_H265_PARSE_ALIGN_NONE = 0,
53 GST_H265_PARSE_ALIGN_NAL,
54 GST_H265_PARSE_ALIGN_AU
59 GST_H265_PARSE_STATE_GOT_SPS = 1 << 0,
60 GST_H265_PARSE_STATE_GOT_PPS = 1 << 1,
61 GST_H265_PARSE_STATE_GOT_SLICE = 1 << 2,
63 GST_H265_PARSE_STATE_VALID_PICTURE_HEADERS = (GST_H265_PARSE_STATE_GOT_SPS |
64 GST_H265_PARSE_STATE_GOT_PPS),
65 GST_H265_PARSE_STATE_VALID_PICTURE =
66 (GST_H265_PARSE_STATE_VALID_PICTURE_HEADERS |
67 GST_H265_PARSE_STATE_GOT_SLICE)
72 GST_H265_PARSE_SEI_EXPIRED = 0,
73 GST_H265_PARSE_SEI_ACTIVE = 1,
74 GST_H265_PARSE_SEI_PARSED = 2,
77 #define GST_H265_PARSE_STATE_VALID(parse, expected_state) \
78 (((parse)->state & (expected_state)) == (expected_state))
80 static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
83 GST_STATIC_CAPS ("video/x-h265"));
85 static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
88 GST_STATIC_CAPS ("video/x-h265, parsed = (boolean) true, "
89 "stream-format=(string) { hvc1, hev1, byte-stream }, "
90 "alignment=(string) { au, nal }"));
92 #define parent_class gst_h265_parse_parent_class
93 G_DEFINE_TYPE (GstH265Parse, gst_h265_parse, GST_TYPE_BASE_PARSE);
95 static void gst_h265_parse_finalize (GObject * object);
97 static gboolean gst_h265_parse_start (GstBaseParse * parse);
98 static gboolean gst_h265_parse_stop (GstBaseParse * parse);
99 static GstFlowReturn gst_h265_parse_handle_frame (GstBaseParse * parse,
100 GstBaseParseFrame * frame, gint * skipsize);
101 static GstFlowReturn gst_h265_parse_parse_frame (GstBaseParse * parse,
102 GstBaseParseFrame * frame);
103 static GstFlowReturn gst_h265_parse_pre_push_frame (GstBaseParse * parse,
104 GstBaseParseFrame * frame);
106 static void gst_h265_parse_set_property (GObject * object, guint prop_id,
107 const GValue * value, GParamSpec * pspec);
108 static void gst_h265_parse_get_property (GObject * object, guint prop_id,
109 GValue * value, GParamSpec * pspec);
111 static gboolean gst_h265_parse_set_caps (GstBaseParse * parse, GstCaps * caps);
112 static GstCaps *gst_h265_parse_get_caps (GstBaseParse * parse,
114 static gboolean gst_h265_parse_event (GstBaseParse * parse, GstEvent * event);
115 static gboolean gst_h265_parse_src_event (GstBaseParse * parse,
118 gst_h265_parse_process_sei_user_data (GstH265Parse * h265parse,
119 GstH265RegisteredUserData * rud);
122 gst_h265_parse_class_init (GstH265ParseClass * klass)
124 GObjectClass *gobject_class = (GObjectClass *) klass;
125 GstBaseParseClass *parse_class = GST_BASE_PARSE_CLASS (klass);
126 GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
128 GST_DEBUG_CATEGORY_INIT (h265_parse_debug, "h265parse", 0, "h265 parser");
130 gobject_class->finalize = gst_h265_parse_finalize;
131 gobject_class->set_property = gst_h265_parse_set_property;
132 gobject_class->get_property = gst_h265_parse_get_property;
134 g_object_class_install_property (gobject_class, PROP_CONFIG_INTERVAL,
135 g_param_spec_int ("config-interval",
136 "VPS SPS PPS Send Interval",
137 "Send VPS, SPS and PPS Insertion Interval in seconds (sprop parameter sets "
138 "will be multiplexed in the data stream when detected.) "
139 "(0 = disabled, -1 = send with every IDR frame)",
140 -1, 3600, DEFAULT_CONFIG_INTERVAL,
141 G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
142 /* Override BaseParse vfuncs */
143 parse_class->start = GST_DEBUG_FUNCPTR (gst_h265_parse_start);
144 parse_class->stop = GST_DEBUG_FUNCPTR (gst_h265_parse_stop);
145 parse_class->handle_frame = GST_DEBUG_FUNCPTR (gst_h265_parse_handle_frame);
146 parse_class->pre_push_frame =
147 GST_DEBUG_FUNCPTR (gst_h265_parse_pre_push_frame);
148 parse_class->set_sink_caps = GST_DEBUG_FUNCPTR (gst_h265_parse_set_caps);
149 parse_class->get_sink_caps = GST_DEBUG_FUNCPTR (gst_h265_parse_get_caps);
150 parse_class->sink_event = GST_DEBUG_FUNCPTR (gst_h265_parse_event);
151 parse_class->src_event = GST_DEBUG_FUNCPTR (gst_h265_parse_src_event);
153 gst_element_class_add_static_pad_template (gstelement_class, &srctemplate);
154 gst_element_class_add_static_pad_template (gstelement_class, &sinktemplate);
156 gst_element_class_set_static_metadata (gstelement_class, "H.265 parser",
157 "Codec/Parser/Converter/Video",
158 "Parses H.265 streams",
159 "Sreerenj Balachandran <sreerenj.balachandran@intel.com>");
163 gst_h265_parse_init (GstH265Parse * h265parse)
165 h265parse->frame_out = gst_adapter_new ();
166 gst_base_parse_set_pts_interpolation (GST_BASE_PARSE (h265parse), FALSE);
167 gst_base_parse_set_infer_ts (GST_BASE_PARSE (h265parse), FALSE);
168 GST_PAD_SET_ACCEPT_INTERSECT (GST_BASE_PARSE_SINK_PAD (h265parse));
169 GST_PAD_SET_ACCEPT_TEMPLATE (GST_BASE_PARSE_SINK_PAD (h265parse));
174 gst_h265_parse_finalize (GObject * object)
176 GstH265Parse *h265parse = GST_H265_PARSE (object);
178 g_object_unref (h265parse->frame_out);
180 G_OBJECT_CLASS (parent_class)->finalize (object);
184 gst_h265_parse_reset_frame (GstH265Parse * h265parse)
186 GST_DEBUG_OBJECT (h265parse, "reset frame");
188 /* done parsing; reset state */
189 h265parse->current_off = -1;
191 h265parse->update_caps = FALSE;
192 h265parse->idr_pos = -1;
193 h265parse->sei_pos = -1;
194 h265parse->keyframe = FALSE;
195 h265parse->predicted = FALSE;
196 h265parse->bidirectional = FALSE;
197 h265parse->header = FALSE;
198 h265parse->have_vps_in_frame = FALSE;
199 h265parse->have_sps_in_frame = FALSE;
200 h265parse->have_pps_in_frame = FALSE;
201 gst_adapter_clear (h265parse->frame_out);
205 gst_h265_parse_reset_stream_info (GstH265Parse * h265parse)
209 h265parse->width = 0;
210 h265parse->height = 0;
211 h265parse->fps_num = 0;
212 h265parse->fps_den = 0;
213 h265parse->upstream_par_n = -1;
214 h265parse->upstream_par_d = -1;
215 h265parse->parsed_par_n = 0;
216 h265parse->parsed_par_n = 0;
217 h265parse->parsed_colorimetry.range = GST_VIDEO_COLOR_RANGE_UNKNOWN;
218 h265parse->parsed_colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_UNKNOWN;
219 h265parse->parsed_colorimetry.transfer = GST_VIDEO_TRANSFER_UNKNOWN;
220 h265parse->parsed_colorimetry.primaries = GST_VIDEO_COLOR_PRIMARIES_UNKNOWN;
221 h265parse->have_pps = FALSE;
222 h265parse->have_sps = FALSE;
223 h265parse->have_vps = FALSE;
225 h265parse->align = GST_H265_PARSE_ALIGN_NONE;
226 h265parse->format = GST_H265_PARSE_FORMAT_NONE;
228 h265parse->transform = FALSE;
229 h265parse->nal_length_size = 4;
230 h265parse->packetized = FALSE;
231 h265parse->push_codec = FALSE;
232 h265parse->first_frame = TRUE;
234 gst_buffer_replace (&h265parse->codec_data, NULL);
235 gst_buffer_replace (&h265parse->codec_data_in, NULL);
237 gst_h265_parse_reset_frame (h265parse);
239 for (i = 0; i < GST_H265_MAX_VPS_COUNT; i++)
240 gst_buffer_replace (&h265parse->vps_nals[i], NULL);
241 for (i = 0; i < GST_H265_MAX_SPS_COUNT; i++)
242 gst_buffer_replace (&h265parse->sps_nals[i], NULL);
243 for (i = 0; i < GST_H265_MAX_PPS_COUNT; i++)
244 gst_buffer_replace (&h265parse->pps_nals[i], NULL);
246 gst_video_mastering_display_info_init (&h265parse->mastering_display_info);
247 h265parse->mastering_display_info_state = GST_H265_PARSE_SEI_EXPIRED;
249 gst_video_content_light_level_init (&h265parse->content_light_level);
250 h265parse->content_light_level_state = GST_H265_PARSE_SEI_EXPIRED;
254 gst_h265_parse_reset (GstH265Parse * h265parse)
256 h265parse->last_report = GST_CLOCK_TIME_NONE;
258 h265parse->pending_key_unit_ts = GST_CLOCK_TIME_NONE;
259 gst_event_replace (&h265parse->force_key_unit_event, NULL);
261 h265parse->discont = FALSE;
262 h265parse->discard_bidirectional = FALSE;
263 h265parse->marker = FALSE;
265 gst_h265_parse_reset_stream_info (h265parse);
269 gst_h265_parse_start (GstBaseParse * parse)
271 GstH265Parse *h265parse = GST_H265_PARSE (parse);
273 GST_DEBUG_OBJECT (parse, "start");
274 gst_h265_parse_reset (h265parse);
276 h265parse->nalparser = gst_h265_parser_new ();
277 h265parse->state = 0;
279 gst_base_parse_set_min_frame_size (parse, 5);
285 gst_h265_parse_stop (GstBaseParse * parse)
287 GstH265Parse *h265parse = GST_H265_PARSE (parse);
289 GST_DEBUG_OBJECT (parse, "stop");
290 gst_h265_parse_reset (h265parse);
292 gst_h265_parser_free (h265parse->nalparser);
298 gst_h265_parse_get_string (GstH265Parse * parse, gboolean format, gint code)
302 case GST_H265_PARSE_FORMAT_HVC1:
304 case GST_H265_PARSE_FORMAT_HEV1:
306 case GST_H265_PARSE_FORMAT_BYTE:
307 return "byte-stream";
313 case GST_H265_PARSE_ALIGN_NAL:
315 case GST_H265_PARSE_ALIGN_AU:
324 gst_h265_parse_format_from_caps (GstCaps * caps, guint * format, guint * align)
326 g_return_if_fail (gst_caps_is_fixed (caps));
328 GST_DEBUG ("parsing caps: %" GST_PTR_FORMAT, caps);
331 *format = GST_H265_PARSE_FORMAT_NONE;
334 *align = GST_H265_PARSE_ALIGN_NONE;
336 if (caps && gst_caps_get_size (caps) > 0) {
337 GstStructure *s = gst_caps_get_structure (caps, 0);
338 const gchar *str = NULL;
341 if ((str = gst_structure_get_string (s, "stream-format"))) {
342 if (strcmp (str, "hvc1") == 0)
343 *format = GST_H265_PARSE_FORMAT_HVC1;
344 else if (strcmp (str, "hev1") == 0)
345 *format = GST_H265_PARSE_FORMAT_HEV1;
346 else if (strcmp (str, "byte-stream") == 0)
347 *format = GST_H265_PARSE_FORMAT_BYTE;
352 if ((str = gst_structure_get_string (s, "alignment"))) {
353 if (strcmp (str, "au") == 0)
354 *align = GST_H265_PARSE_ALIGN_AU;
355 else if (strcmp (str, "nal") == 0)
356 *align = GST_H265_PARSE_ALIGN_NAL;
362 /* check downstream caps to configure format and alignment */
364 gst_h265_parse_negotiate (GstH265Parse * h265parse, gint in_format,
368 guint format = GST_H265_PARSE_FORMAT_NONE;
369 guint align = GST_H265_PARSE_ALIGN_NONE;
371 g_return_if_fail ((in_caps == NULL) || gst_caps_is_fixed (in_caps));
373 caps = gst_pad_get_allowed_caps (GST_BASE_PARSE_SRC_PAD (h265parse));
374 GST_DEBUG_OBJECT (h265parse, "allowed caps: %" GST_PTR_FORMAT, caps);
376 /* concentrate on leading structure, since decodebin parser
377 * capsfilter always includes parser template caps */
379 caps = gst_caps_truncate (caps);
380 GST_DEBUG_OBJECT (h265parse, "negotiating with caps: %" GST_PTR_FORMAT,
384 if (in_caps && caps) {
385 if (gst_caps_can_intersect (in_caps, caps)) {
386 GST_DEBUG_OBJECT (h265parse, "downstream accepts upstream caps");
387 gst_h265_parse_format_from_caps (in_caps, &format, &align);
388 gst_caps_unref (caps);
393 /* FIXME We could fail the negotiation immediately if caps are empty */
394 if (caps && !gst_caps_is_empty (caps)) {
395 /* fixate to avoid ambiguity with lists when parsing */
396 caps = gst_caps_fixate (caps);
397 gst_h265_parse_format_from_caps (caps, &format, &align);
402 format = GST_H265_PARSE_FORMAT_BYTE;
404 align = GST_H265_PARSE_ALIGN_AU;
406 GST_DEBUG_OBJECT (h265parse, "selected format %s, alignment %s",
407 gst_h265_parse_get_string (h265parse, TRUE, format),
408 gst_h265_parse_get_string (h265parse, FALSE, align));
410 h265parse->format = format;
411 h265parse->align = align;
413 h265parse->transform = in_format != h265parse->format ||
414 align == GST_H265_PARSE_ALIGN_AU;
417 gst_caps_unref (caps);
421 gst_h265_parse_wrap_nal (GstH265Parse * h265parse, guint format, guint8 * data,
425 guint nl = h265parse->nal_length_size;
428 GST_DEBUG_OBJECT (h265parse, "nal length %d", size);
430 buf = gst_buffer_new_allocate (NULL, 4 + size, NULL);
431 if (format == GST_H265_PARSE_FORMAT_HVC1
432 || format == GST_H265_PARSE_FORMAT_HEV1) {
433 tmp = GUINT32_TO_BE (size << (32 - 8 * nl));
435 /* HACK: nl should always be 4 here, otherwise this won't work.
436 * There are legit cases where nl in hevc stream is 2, but byte-stream
437 * SC is still always 4 bytes. */
439 tmp = GUINT32_TO_BE (1);
442 gst_buffer_fill (buf, 0, &tmp, sizeof (guint32));
443 gst_buffer_fill (buf, nl, data, size);
444 gst_buffer_set_size (buf, size + nl);
450 gst_h265_parser_store_nal (GstH265Parse * h265parse, guint id,
451 GstH265NalUnitType naltype, GstH265NalUnit * nalu)
453 GstBuffer *buf, **store;
454 guint size = nalu->size, store_size;
456 if (naltype == GST_H265_NAL_VPS) {
457 store_size = GST_H265_MAX_VPS_COUNT;
458 store = h265parse->vps_nals;
459 GST_DEBUG_OBJECT (h265parse, "storing vps %u", id);
460 } else if (naltype == GST_H265_NAL_SPS) {
461 store_size = GST_H265_MAX_SPS_COUNT;
462 store = h265parse->sps_nals;
463 GST_DEBUG_OBJECT (h265parse, "storing sps %u", id);
464 } else if (naltype == GST_H265_NAL_PPS) {
465 store_size = GST_H265_MAX_PPS_COUNT;
466 store = h265parse->pps_nals;
467 GST_DEBUG_OBJECT (h265parse, "storing pps %u", id);
471 if (id >= store_size) {
472 GST_DEBUG_OBJECT (h265parse, "unable to store nal, id out-of-range %d", id);
476 buf = gst_buffer_new_allocate (NULL, size, NULL);
477 gst_buffer_fill (buf, 0, nalu->data + nalu->offset, size);
479 /* Indicate that buffer contain a header needed for decoding */
480 if (naltype >= GST_H265_NAL_VPS && naltype <= GST_H265_NAL_PPS)
481 GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_HEADER);
484 gst_buffer_unref (store[id]);
489 #ifndef GST_DISABLE_GST_DEBUG
490 static const gchar *nal_names[] = {
535 _nal_name (GstH265NalUnitType nal_type)
537 if (nal_type <= GST_H265_NAL_SUFFIX_SEI)
538 return nal_names[nal_type];
544 gst_h265_parse_process_sei (GstH265Parse * h265parse, GstH265NalUnit * nalu)
546 GstH265SEIMessage sei;
547 GstH265Parser *nalparser = h265parse->nalparser;
548 GstH265ParserResult pres;
552 pres = gst_h265_parser_parse_sei (nalparser, nalu, &messages);
553 if (pres != GST_H265_PARSER_OK)
554 GST_WARNING_OBJECT (h265parse, "failed to parse one or more SEI message");
556 /* Even if pres != GST_H265_PARSER_OK, some message could have been parsed and
557 * stored in messages.
559 for (i = 0; i < messages->len; i++) {
560 sei = g_array_index (messages, GstH265SEIMessage, i);
561 switch (sei.payloadType) {
562 case GST_H265_SEI_RECOVERY_POINT:
563 GST_LOG_OBJECT (h265parse, "recovery point found: %u %u %u",
564 sei.payload.recovery_point.recovery_poc_cnt,
565 sei.payload.recovery_point.exact_match_flag,
566 sei.payload.recovery_point.broken_link_flag);
567 h265parse->keyframe = TRUE;
569 case GST_H265_SEI_TIME_CODE:
570 memcpy (&h265parse->time_code, &sei.payload.time_code,
571 sizeof (GstH265TimeCode));
573 case GST_H265_SEI_PIC_TIMING:
574 h265parse->sei_pic_struct = sei.payload.pic_timing.pic_struct;
576 case GST_H265_SEI_REGISTERED_USER_DATA:
577 gst_h265_parse_process_sei_user_data (h265parse,
578 &sei.payload.registered_user_data);
580 case GST_H265_SEI_BUF_PERIOD:
583 case GST_H265_SEI_MASTERING_DISPLAY_COLOUR_VOLUME:
585 /* Precision defined by spec.
586 * See D.3.28 Mastering display colour volume SEI message semantics */
587 GstVideoMasteringDisplayInfo minfo;
590 /* GstVideoMasteringDisplayInfo::display_primaries is rgb order but
591 * HEVC uses gbr order
592 * See spec D.3.28 display_primaries_x and display_primaries_y
594 for (j = 0, k = 2; j < G_N_ELEMENTS (minfo.display_primaries); j++, k++) {
595 minfo.display_primaries[j].x =
597 mastering_display_colour_volume.display_primaries_x[k % 3];
598 minfo.display_primaries[j].y =
600 mastering_display_colour_volume.display_primaries_y[k % 3];
603 minfo.white_point.x =
604 sei.payload.mastering_display_colour_volume.white_point_x;
605 minfo.white_point.y =
606 sei.payload.mastering_display_colour_volume.white_point_y;
607 minfo.max_display_mastering_luminance =
608 sei.payload.mastering_display_colour_volume.
609 max_display_mastering_luminance;
610 minfo.min_display_mastering_luminance =
611 sei.payload.mastering_display_colour_volume.
612 min_display_mastering_luminance;
614 GST_LOG_OBJECT (h265parse, "mastering display info found: "
620 "min_luminance(%u) ",
621 minfo.display_primaries[0].x, minfo.display_primaries[0].y,
622 minfo.display_primaries[1].x, minfo.display_primaries[1].y,
623 minfo.display_primaries[2].x, minfo.display_primaries[2].y,
624 minfo.white_point.x, minfo.white_point.y,
625 minfo.max_display_mastering_luminance,
626 minfo.min_display_mastering_luminance);
628 if (h265parse->mastering_display_info_state ==
629 GST_H265_PARSE_SEI_EXPIRED) {
630 h265parse->update_caps = TRUE;
631 } else if (!gst_video_mastering_display_info_is_equal
632 (&h265parse->mastering_display_info, &minfo)) {
633 h265parse->update_caps = TRUE;
636 h265parse->mastering_display_info_state = GST_H265_PARSE_SEI_PARSED;
637 h265parse->mastering_display_info = minfo;
641 case GST_H265_SEI_CONTENT_LIGHT_LEVEL:
643 GstVideoContentLightLevel cll;
645 cll.max_content_light_level =
646 sei.payload.content_light_level.max_content_light_level;
647 cll.max_frame_average_light_level =
648 sei.payload.content_light_level.max_pic_average_light_level;
650 GST_LOG_OBJECT (h265parse, "content light level found: "
651 "maxCLL:(%u), maxFALL:(%u)", cll.max_content_light_level,
652 cll.max_frame_average_light_level);
654 if (h265parse->content_light_level_state == GST_H265_PARSE_SEI_EXPIRED) {
655 h265parse->update_caps = TRUE;
656 } else if (cll.max_content_light_level !=
657 h265parse->content_light_level.max_content_light_level ||
658 cll.max_frame_average_light_level !=
659 h265parse->content_light_level.max_frame_average_light_level) {
660 h265parse->update_caps = TRUE;
663 h265parse->content_light_level_state = GST_H265_PARSE_SEI_PARSED;
664 h265parse->content_light_level = cll;
672 g_array_free (messages, TRUE);
676 gst_h265_parse_process_sei_user_data (GstH265Parse * h265parse,
677 GstH265RegisteredUserData * rud)
679 guint16 provider_code;
681 GstVideoParseUtilsField field = GST_VIDEO_PARSE_UTILS_FIELD_1;
683 /* only US country code is currently supported */
684 switch (rud->country_code) {
685 case ITU_T_T35_COUNTRY_CODE_US:
688 GST_LOG_OBJECT (h265parse, "Unsupported country code %d",
693 if (rud->data == NULL || rud->size < 2)
696 gst_byte_reader_init (&br, rud->data, rud->size);
698 provider_code = gst_byte_reader_get_uint16_be_unchecked (&br);
700 if (h265parse->sei_pic_struct ==
701 (guint8) GST_H265_SEI_PIC_STRUCT_BOTTOM_FIELD)
702 field = GST_VIDEO_PARSE_UTILS_FIELD_1;
703 gst_video_parse_user_data ((GstElement *) h265parse, &h265parse->user_data,
704 &br, field, provider_code);
708 /* caller guarantees 2 bytes of nal payload */
710 gst_h265_parse_process_nal (GstH265Parse * h265parse, GstH265NalUnit * nalu)
712 GstH265PPS pps = { 0, };
713 GstH265SPS sps = { 0, };
714 GstH265VPS vps = { 0, };
716 GstH265Parser *nalparser = h265parse->nalparser;
717 GstH265ParserResult pres = GST_H265_PARSER_ERROR;
719 /* nothing to do for broken input */
720 if (G_UNLIKELY (nalu->size < 2)) {
721 GST_DEBUG_OBJECT (h265parse, "not processing nal size %u", nalu->size);
725 /* we have a peek as well */
726 nal_type = nalu->type;
728 GST_DEBUG_OBJECT (h265parse, "processing nal of type %u %s, size %u",
729 nal_type, _nal_name (nal_type), nalu->size);
731 case GST_H265_NAL_VPS:
732 /* It is not mandatory to have VPS in the stream. But it might
733 * be needed for other extensions like svc */
734 pres = gst_h265_parser_parse_vps (nalparser, nalu, &vps);
735 if (pres != GST_H265_PARSER_OK) {
736 GST_WARNING_OBJECT (h265parse, "failed to parse VPS");
740 GST_DEBUG_OBJECT (h265parse, "triggering src caps check");
741 h265parse->update_caps = TRUE;
742 h265parse->have_vps = TRUE;
743 h265parse->have_vps_in_frame = TRUE;
744 if (h265parse->push_codec && h265parse->have_pps) {
745 /* VPS/SPS/PPS found in stream before the first pre_push_frame, no need
746 * to forcibly push at start */
747 GST_INFO_OBJECT (h265parse, "have VPS/SPS/PPS in stream");
748 h265parse->push_codec = FALSE;
749 h265parse->have_vps = FALSE;
750 h265parse->have_sps = FALSE;
751 h265parse->have_pps = FALSE;
754 gst_h265_parser_store_nal (h265parse, vps.id, nal_type, nalu);
755 h265parse->header = TRUE;
757 case GST_H265_NAL_SPS:
758 /* reset state, everything else is obsolete */
759 h265parse->state = 0;
761 pres = gst_h265_parser_parse_sps (nalparser, nalu, &sps, TRUE);
764 /* arranged for a fallback sps.id, so use that one and only warn */
765 if (pres != GST_H265_PARSER_OK) {
766 /* try to not parse VUI */
767 pres = gst_h265_parser_parse_sps (nalparser, nalu, &sps, FALSE);
768 if (pres != GST_H265_PARSER_OK) {
769 GST_WARNING_OBJECT (h265parse, "failed to parse SPS:");
770 h265parse->state |= GST_H265_PARSE_STATE_GOT_SPS;
771 h265parse->header = TRUE;
774 GST_WARNING_OBJECT (h265parse,
775 "failed to parse VUI of SPS, ignore VUI");
778 GST_DEBUG_OBJECT (h265parse, "triggering src caps check");
779 h265parse->update_caps = TRUE;
780 h265parse->have_sps = TRUE;
781 h265parse->have_sps_in_frame = TRUE;
782 if (h265parse->push_codec && h265parse->have_pps) {
783 /* SPS and PPS found in stream before the first pre_push_frame, no need
784 * to forcibly push at start */
785 GST_INFO_OBJECT (h265parse, "have SPS/PPS in stream");
786 h265parse->push_codec = FALSE;
787 h265parse->have_sps = FALSE;
788 h265parse->have_pps = FALSE;
791 gst_h265_parser_store_nal (h265parse, sps.id, nal_type, nalu);
792 h265parse->header = TRUE;
793 h265parse->state |= GST_H265_PARSE_STATE_GOT_SPS;
795 case GST_H265_NAL_PPS:
796 /* expected state: got-sps */
797 h265parse->state &= GST_H265_PARSE_STATE_GOT_SPS;
798 if (!GST_H265_PARSE_STATE_VALID (h265parse, GST_H265_PARSE_STATE_GOT_SPS))
801 pres = gst_h265_parser_parse_pps (nalparser, nalu, &pps);
804 /* arranged for a fallback pps.id, so use that one and only warn */
805 if (pres != GST_H265_PARSER_OK) {
806 GST_WARNING_OBJECT (h265parse, "failed to parse PPS:");
807 if (pres != GST_H265_PARSER_BROKEN_LINK)
811 /* parameters might have changed, force caps check */
812 if (!h265parse->have_pps) {
813 GST_DEBUG_OBJECT (h265parse, "triggering src caps check");
814 h265parse->update_caps = TRUE;
816 h265parse->have_pps = TRUE;
817 h265parse->have_pps_in_frame = TRUE;
818 if (h265parse->push_codec && h265parse->have_sps) {
819 /* SPS and PPS found in stream before the first pre_push_frame, no need
820 * to forcibly push at start */
821 GST_INFO_OBJECT (h265parse, "have SPS/PPS in stream");
822 h265parse->push_codec = FALSE;
823 h265parse->have_sps = FALSE;
824 h265parse->have_pps = FALSE;
827 gst_h265_parser_store_nal (h265parse, pps.id, nal_type, nalu);
828 h265parse->header = TRUE;
829 h265parse->state |= GST_H265_PARSE_STATE_GOT_PPS;
831 case GST_H265_NAL_PREFIX_SEI:
832 case GST_H265_NAL_SUFFIX_SEI:
833 /* expected state: got-sps */
834 if (!GST_H265_PARSE_STATE_VALID (h265parse, GST_H265_PARSE_STATE_GOT_SPS))
837 h265parse->header = TRUE;
839 gst_h265_parse_process_sei (h265parse, nalu);
842 if (nal_type == GST_H265_NAL_PREFIX_SEI && h265parse->sei_pos == -1) {
843 if (h265parse->transform)
844 h265parse->sei_pos = gst_adapter_available (h265parse->frame_out);
846 h265parse->sei_pos = nalu->sc_offset;
847 GST_DEBUG_OBJECT (h265parse, "marking SEI in frame at offset %d",
852 case GST_H265_NAL_SLICE_TRAIL_N:
853 case GST_H265_NAL_SLICE_TRAIL_R:
854 case GST_H265_NAL_SLICE_TSA_N:
855 case GST_H265_NAL_SLICE_TSA_R:
856 case GST_H265_NAL_SLICE_STSA_N:
857 case GST_H265_NAL_SLICE_STSA_R:
858 case GST_H265_NAL_SLICE_RADL_N:
859 case GST_H265_NAL_SLICE_RADL_R:
860 case GST_H265_NAL_SLICE_RASL_N:
861 case GST_H265_NAL_SLICE_RASL_R:
862 case GST_H265_NAL_SLICE_BLA_W_LP:
863 case GST_H265_NAL_SLICE_BLA_W_RADL:
864 case GST_H265_NAL_SLICE_BLA_N_LP:
865 case GST_H265_NAL_SLICE_IDR_W_RADL:
866 case GST_H265_NAL_SLICE_IDR_N_LP:
867 case GST_H265_NAL_SLICE_CRA_NUT:
869 GstH265SliceHdr slice;
871 gboolean no_rasl_output_flag = FALSE;
873 /* expected state: got-sps|got-pps (valid picture headers) */
874 h265parse->state &= GST_H265_PARSE_STATE_VALID_PICTURE_HEADERS;
875 if (!GST_H265_PARSE_STATE_VALID (h265parse,
876 GST_H265_PARSE_STATE_VALID_PICTURE_HEADERS))
879 /* This is similar to the GOT_SLICE state, but is only reset when the
880 * AU is complete. This is used to keep track of AU */
881 h265parse->picture_start = TRUE;
883 pres = gst_h265_parser_parse_slice_hdr (nalparser, nalu, &slice);
885 if (pres == GST_H265_PARSER_OK) {
886 if (GST_H265_IS_I_SLICE (&slice))
887 h265parse->keyframe = TRUE;
888 else if (GST_H265_IS_P_SLICE (&slice))
889 h265parse->predicted = TRUE;
890 else if (GST_H265_IS_B_SLICE (&slice))
891 h265parse->bidirectional = TRUE;
893 h265parse->state |= GST_H265_PARSE_STATE_GOT_SLICE;
895 if (slice.first_slice_segment_in_pic_flag == 1)
896 GST_DEBUG_OBJECT (h265parse,
897 "frame start, first_slice_segment_in_pic_flag = 1");
899 GST_DEBUG_OBJECT (h265parse,
900 "parse result %d, first slice_segment: %u, slice type: %u",
901 pres, slice.first_slice_segment_in_pic_flag, slice.type);
903 gst_h265_slice_hdr_free (&slice);
905 /* FIXME: NoRaslOutputFlag can be equal to 1 for CRA if
906 * 1) the first AU in bitstream is CRA
907 * 2) or the first AU following EOS nal is CRA
908 * 3) or it has HandleCraAsBlaFlag equal to 1 */
909 if (GST_H265_IS_NAL_TYPE_IDR (nal_type)) {
910 /* NoRaslOutputFlag is equal to 1 for each IDR */
911 no_rasl_output_flag = TRUE;
912 } else if (GST_H265_IS_NAL_TYPE_BLA (nal_type)) {
913 /* NoRaslOutputFlag is equal to 1 for each BLA */
914 no_rasl_output_flag = TRUE;
917 is_irap = GST_H265_IS_NAL_TYPE_IRAP (nal_type);
919 if (no_rasl_output_flag && is_irap
920 && slice.first_slice_segment_in_pic_flag == 1) {
921 if (h265parse->mastering_display_info_state ==
922 GST_H265_PARSE_SEI_PARSED)
923 h265parse->mastering_display_info_state = GST_H265_PARSE_SEI_ACTIVE;
924 else if (h265parse->mastering_display_info_state ==
925 GST_H265_PARSE_SEI_ACTIVE)
926 h265parse->mastering_display_info_state = GST_H265_PARSE_SEI_EXPIRED;
928 if (h265parse->content_light_level_state == GST_H265_PARSE_SEI_PARSED)
929 h265parse->content_light_level_state = GST_H265_PARSE_SEI_ACTIVE;
930 else if (h265parse->content_light_level_state ==
931 GST_H265_PARSE_SEI_ACTIVE)
932 h265parse->content_light_level_state = GST_H265_PARSE_SEI_EXPIRED;
934 if (G_LIKELY (!is_irap && !h265parse->push_codec))
937 /* if we need to sneak codec NALs into the stream,
938 * this is a good place, so fake it as IDR
939 * (which should be at start anyway) */
940 /* mark where config needs to go if interval expired */
941 /* mind replacement buffer if applicable */
942 if (h265parse->idr_pos == -1) {
943 if (h265parse->transform)
944 h265parse->idr_pos = gst_adapter_available (h265parse->frame_out);
946 h265parse->idr_pos = nalu->sc_offset;
947 GST_DEBUG_OBJECT (h265parse, "marking IDR in frame at offset %d",
950 /* if SEI preceeds (faked) IDR, then we have to insert config there */
951 if (h265parse->sei_pos >= 0 && h265parse->idr_pos > h265parse->sei_pos) {
952 h265parse->idr_pos = h265parse->sei_pos;
953 GST_DEBUG_OBJECT (h265parse, "moved IDR mark to SEI position %d",
958 case GST_H265_NAL_AUD:
959 /* Just accumulate AU Delimiter, whether it's before SPS or not */
960 pres = gst_h265_parser_parse_nal (nalparser, nalu);
961 if (pres != GST_H265_PARSER_OK)
965 /* drop anything before the initial SPS */
966 if (!GST_H265_PARSE_STATE_VALID (h265parse, GST_H265_PARSE_STATE_GOT_SPS))
969 pres = gst_h265_parser_parse_nal (nalparser, nalu);
970 if (pres != GST_H265_PARSER_OK)
975 /* if HEVC output needed, collect properly prefixed nal in adapter,
976 * and use that to replace outgoing buffer data later on */
977 if (h265parse->transform) {
980 GST_LOG_OBJECT (h265parse, "collecting NAL in HEVC frame");
981 buf = gst_h265_parse_wrap_nal (h265parse, h265parse->format,
982 nalu->data + nalu->offset, nalu->size);
983 gst_adapter_push (h265parse->frame_out, buf);
989 /* caller guarantees at least 3 bytes of nal payload for each nal
990 * returns TRUE if next_nal indicates that nal terminates an AU */
991 static inline gboolean
992 gst_h265_parse_collect_nal (GstH265Parse * h265parse, const guint8 * data,
993 guint size, GstH265NalUnit * nalu)
995 GstH265NalUnitType nal_type = nalu->type;
998 /* determine if AU complete */
999 GST_LOG_OBJECT (h265parse, "next nal type: %d %s (picture started %i)",
1000 nal_type, _nal_name (nal_type), h265parse->picture_start);
1002 /* consider a coded slices (IRAP or not) to start a picture,
1003 * (so ending the previous one) if first_slice_segment_in_pic_flag == 1*/
1004 complete = h265parse->picture_start && ((nal_type >= GST_H265_NAL_VPS
1005 && nal_type <= GST_H265_NAL_AUD)
1006 || nal_type == GST_H265_NAL_PREFIX_SEI || (nal_type >= 41
1007 && nal_type <= 44) || (nal_type >= 48 && nal_type <= 55));
1009 /* Any VCL Nal unit with first_slice_segment_in_pic_flag == 1 considered start of frame */
1010 if (nalu->size > nalu->header_bytes) {
1011 complete |= h265parse->picture_start
1012 && (((nal_type >= GST_H265_NAL_SLICE_TRAIL_N
1013 && nal_type <= GST_H265_NAL_SLICE_RASL_R)
1014 || GST_H265_IS_NAL_TYPE_IRAP (nal_type))
1015 && (nalu->data[nalu->offset + 2] & 0x80));
1018 GST_LOG_OBJECT (h265parse, "au complete: %d", complete);
1021 h265parse->picture_start = FALSE;
1026 static GstFlowReturn
1027 gst_h265_parse_handle_frame_packetized (GstBaseParse * parse,
1028 GstBaseParseFrame * frame)
1030 GstH265Parse *h265parse = GST_H265_PARSE (parse);
1031 GstBuffer *buffer = frame->buffer;
1032 GstFlowReturn ret = GST_FLOW_OK;
1033 GstH265ParserResult parse_res;
1034 GstH265NalUnit nalu;
1035 const guint nl = h265parse->nal_length_size;
1039 if (nl < 1 || nl > 4) {
1040 GST_DEBUG_OBJECT (h265parse, "insufficient data to split input");
1041 return GST_FLOW_NOT_NEGOTIATED;
1044 /* need to save buffer from invalidation upon _finish_frame */
1045 if (h265parse->split_packetized)
1046 buffer = gst_buffer_copy (frame->buffer);
1048 gst_buffer_map (buffer, &map, GST_MAP_READ);
1052 GST_LOG_OBJECT (h265parse,
1053 "processing packet buffer of size %" G_GSIZE_FORMAT, map.size);
1055 parse_res = gst_h265_parser_identify_nalu_hevc (h265parse->nalparser,
1056 map.data, 0, map.size, nl, &nalu);
1058 while (parse_res == GST_H265_PARSER_OK) {
1059 GST_DEBUG_OBJECT (h265parse, "HEVC nal offset %d", nalu.offset + nalu.size);
1061 /* either way, have a look at it */
1062 gst_h265_parse_process_nal (h265parse, &nalu);
1064 /* dispatch per NALU if needed */
1065 if (h265parse->split_packetized) {
1066 GstBaseParseFrame tmp_frame;
1068 gst_base_parse_frame_init (&tmp_frame);
1069 tmp_frame.flags |= frame->flags;
1070 tmp_frame.offset = frame->offset;
1071 tmp_frame.overhead = frame->overhead;
1072 tmp_frame.buffer = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_ALL,
1073 nalu.offset, nalu.size);
1075 /* Set marker on last packet */
1076 if (nl + nalu.size == left) {
1077 if (GST_BUFFER_FLAG_IS_SET (frame->buffer, GST_BUFFER_FLAG_MARKER))
1078 h265parse->marker = TRUE;
1081 /* note we don't need to come up with a sub-buffer, since
1082 * subsequent code only considers input buffer's metadata.
1083 * Real data is either taken from input by baseclass or
1084 * a replacement output buffer is provided anyway. */
1085 gst_h265_parse_parse_frame (parse, &tmp_frame);
1086 ret = gst_base_parse_finish_frame (parse, &tmp_frame, nl + nalu.size);
1087 left -= nl + nalu.size;
1090 parse_res = gst_h265_parser_identify_nalu_hevc (h265parse->nalparser,
1091 map.data, nalu.offset + nalu.size, map.size, nl, &nalu);
1094 gst_buffer_unmap (buffer, &map);
1096 if (!h265parse->split_packetized) {
1097 h265parse->marker = TRUE;
1098 gst_h265_parse_parse_frame (parse, frame);
1099 ret = gst_base_parse_finish_frame (parse, frame, map.size);
1101 gst_buffer_unref (buffer);
1102 if (G_UNLIKELY (left)) {
1103 /* should not be happening for nice HEVC */
1104 GST_WARNING_OBJECT (parse, "skipping leftover HEVC data %d", left);
1105 frame->flags |= GST_BASE_PARSE_FRAME_FLAG_DROP;
1106 ret = gst_base_parse_finish_frame (parse, frame, map.size);
1110 if (parse_res == GST_H265_PARSER_NO_NAL_END ||
1111 parse_res == GST_H265_PARSER_BROKEN_DATA) {
1113 if (h265parse->split_packetized) {
1114 GST_ELEMENT_ERROR (h265parse, STREAM, FAILED, (NULL),
1115 ("invalid HEVC input data"));
1117 return GST_FLOW_ERROR;
1119 /* do not meddle to much in this case */
1120 GST_DEBUG_OBJECT (h265parse, "parsing packet failed");
1127 static GstFlowReturn
1128 gst_h265_parse_handle_frame (GstBaseParse * parse,
1129 GstBaseParseFrame * frame, gint * skipsize)
1131 GstH265Parse *h265parse = GST_H265_PARSE (parse);
1132 GstBuffer *buffer = frame->buffer;
1136 gint current_off = 0;
1137 gboolean drain, nonext;
1138 GstH265Parser *nalparser = h265parse->nalparser;
1139 GstH265NalUnit nalu;
1140 GstH265ParserResult pres;
1143 if (G_UNLIKELY (GST_BUFFER_FLAG_IS_SET (frame->buffer,
1144 GST_BUFFER_FLAG_DISCONT))) {
1145 h265parse->discont = TRUE;
1148 /* delegate in packetized case, no skipping should be needed */
1149 if (h265parse->packetized)
1150 return gst_h265_parse_handle_frame_packetized (parse, frame);
1152 gst_buffer_map (buffer, &map, GST_MAP_READ);
1156 /* expect at least 3 bytes start_code, and 2 bytes NALU header.
1157 * the length of the NALU payload can be zero.
1158 * (e.g. EOS/EOB placed at the end of an AU.) */
1159 if (G_UNLIKELY (size < 5)) {
1160 gst_buffer_unmap (buffer, &map);
1165 /* need to configure aggregation */
1166 if (G_UNLIKELY (h265parse->format == GST_H265_PARSE_FORMAT_NONE))
1167 gst_h265_parse_negotiate (h265parse, GST_H265_PARSE_FORMAT_BYTE, NULL);
1169 /* avoid stale cached parsing state */
1170 if (frame->flags & GST_BASE_PARSE_FRAME_FLAG_NEW_FRAME) {
1171 GST_LOG_OBJECT (h265parse, "parsing new frame");
1172 gst_h265_parse_reset_frame (h265parse);
1174 GST_LOG_OBJECT (h265parse, "resuming frame parsing");
1177 /* Always consume the entire input buffer when in_align == ALIGN_AU */
1178 drain = GST_BASE_PARSE_DRAINING (parse)
1179 || h265parse->in_align == GST_H265_PARSE_ALIGN_AU;
1182 current_off = h265parse->current_off;
1183 if (current_off < 0)
1186 /* The parser is being drain, but no new data was added, just prentend this
1188 if (drain && current_off == size) {
1189 GST_DEBUG_OBJECT (h265parse, "draining with no new data");
1191 nalu.offset = current_off;
1195 g_assert (current_off < size);
1196 GST_DEBUG_OBJECT (h265parse, "last parse position %d", current_off);
1198 /* check for initial skip */
1199 if (h265parse->current_off == -1) {
1201 gst_h265_parser_identify_nalu_unchecked (nalparser, data, current_off,
1204 case GST_H265_PARSER_OK:
1205 if (nalu.sc_offset > 0) {
1206 *skipsize = nalu.sc_offset;
1210 case GST_H265_PARSER_NO_NAL:
1211 /* start code may have up to 4 bytes, and we may also get that return
1212 * value if only one of the two header bytes are present, make sure
1213 * not to skip too much */
1214 *skipsize = size - 5;
1217 /* should not really occur either */
1218 GST_ELEMENT_ERROR (h265parse, STREAM, FORMAT,
1219 ("Error parsing H.265 stream"), ("Invalid H.265 stream"));
1220 goto invalid_stream;
1223 /* Ensure we use the TS of the first NAL. This avoids broken timestamp in
1224 * the case of a miss-placed filler byte. */
1225 gst_base_parse_set_ts_at_offset (parse, nalu.offset);
1230 gst_h265_parser_identify_nalu (nalparser, data, current_off, size,
1234 case GST_H265_PARSER_OK:
1235 GST_DEBUG_OBJECT (h265parse, "complete nal (offset, size): (%u, %u) ",
1236 nalu.offset, nalu.size);
1238 case GST_H265_PARSER_NO_NAL_END:
1239 /* In NAL alignment, assume the NAL is complete */
1240 if (h265parse->in_align == GST_H265_PARSE_ALIGN_NAL ||
1241 h265parse->in_align == GST_H265_PARSE_ALIGN_AU) {
1243 nalu.size = size - nalu.offset;
1246 GST_DEBUG_OBJECT (h265parse, "not a complete nal found at offset %u",
1248 /* if draining, accept it as complete nal */
1251 nalu.size = size - nalu.offset;
1252 GST_DEBUG_OBJECT (h265parse, "draining, accepting with size %u",
1254 /* if it's not too short at least */
1259 /* otherwise need more */
1261 case GST_H265_PARSER_BROKEN_LINK:
1262 GST_ELEMENT_ERROR (h265parse, STREAM, FORMAT,
1263 ("Error parsing H.265 stream"),
1264 ("The link to structure needed for the parsing couldn't be found"));
1265 goto invalid_stream;
1266 case GST_H265_PARSER_ERROR:
1267 /* should not really occur either */
1268 GST_ELEMENT_ERROR (h265parse, STREAM, FORMAT,
1269 ("Error parsing H.265 stream"), ("Invalid H.265 stream"));
1270 goto invalid_stream;
1271 case GST_H265_PARSER_NO_NAL:
1272 GST_ELEMENT_ERROR (h265parse, STREAM, FORMAT,
1273 ("Error parsing H.265 stream"), ("No H.265 NAL unit found"));
1274 goto invalid_stream;
1275 case GST_H265_PARSER_BROKEN_DATA:
1276 GST_WARNING_OBJECT (h265parse, "input stream is corrupt; "
1277 "it contains a NAL unit of length %u", nalu.size);
1279 /* broken nal at start -> arrange to skip it,
1280 * otherwise have it terminate current au
1281 * (and so it will be skipped on next frame round) */
1282 if (current_off == 0) {
1283 GST_DEBUG_OBJECT (h265parse, "skipping broken nal");
1284 *skipsize = nalu.offset;
1287 GST_DEBUG_OBJECT (h265parse, "terminating au");
1289 nalu.offset = nalu.sc_offset;
1293 g_assert_not_reached ();
1297 GST_DEBUG_OBJECT (h265parse, "%p complete nal found. Off: %u, Size: %u",
1298 data, nalu.offset, nalu.size);
1300 if (gst_h265_parse_collect_nal (h265parse, data, size, &nalu)) {
1301 /* complete current frame, if it exist */
1302 if (current_off > 0) {
1304 nalu.offset = nalu.sc_offset;
1305 h265parse->marker = TRUE;
1310 if (!gst_h265_parse_process_nal (h265parse, &nalu)) {
1311 GST_WARNING_OBJECT (h265parse,
1312 "broken/invalid nal Type: %d %s, Size: %u will be dropped",
1313 nalu.type, _nal_name (nalu.type), nalu.size);
1314 *skipsize = nalu.size;
1318 /* Do not push immediatly if we don't have all headers. This ensure that
1319 * our caps are complete, avoiding a renegotiation */
1320 if (h265parse->align == GST_H265_PARSE_ALIGN_NAL &&
1321 !GST_H265_PARSE_STATE_VALID (h265parse,
1322 GST_H265_PARSE_STATE_VALID_PICTURE_HEADERS))
1323 frame->flags |= GST_BASE_PARSE_FRAME_FLAG_QUEUE;
1326 /* If there is a marker flag, or input is AU, we know this is complete */
1327 if (GST_BUFFER_FLAG_IS_SET (frame->buffer, GST_BUFFER_FLAG_MARKER) ||
1328 h265parse->in_align == GST_H265_PARSE_ALIGN_AU) {
1329 h265parse->marker = TRUE;
1333 /* or if we are draining or producing NALs */
1334 if (drain || h265parse->align == GST_H265_PARSE_ALIGN_NAL)
1337 current_off = nalu.offset + nalu.size;
1341 /* If the output is NAL, we are done */
1342 if (h265parse->align == GST_H265_PARSE_ALIGN_NAL)
1345 GST_DEBUG_OBJECT (h265parse, "Looking for more");
1346 current_off = nalu.offset + nalu.size;
1348 /* expect at least 3 bytes start_code, and 2 bytes NALU header.
1349 * the length of the NALU payload can be zero.
1350 * (e.g. EOS/EOB placed at the end of an AU.) */
1351 if (G_UNLIKELY (size - current_off < 5)) {
1352 /* Finish the frame if there is no more data in the stream */
1361 framesize = nalu.offset + nalu.size;
1363 gst_buffer_unmap (buffer, &map);
1365 gst_h265_parse_parse_frame (parse, frame);
1367 return gst_base_parse_finish_frame (parse, frame, framesize);
1372 /* Restart parsing from here next time */
1373 if (current_off > 0)
1374 h265parse->current_off = current_off;
1378 gst_buffer_unmap (buffer, &map);
1382 GST_DEBUG_OBJECT (h265parse, "skipping %d", *skipsize);
1383 /* If we are collecting access units, we need to preserve the initial
1384 * config headers (SPS, PPS et al.) and only reset the frame if another
1385 * slice NAL was received. This means that broken pictures are discarded */
1386 if (h265parse->align != GST_H265_PARSE_ALIGN_AU ||
1387 !(h265parse->state & GST_H265_PARSE_STATE_VALID_PICTURE_HEADERS) ||
1388 (h265parse->state & GST_H265_PARSE_STATE_GOT_SLICE))
1389 gst_h265_parse_reset_frame (h265parse);
1393 gst_buffer_unmap (buffer, &map);
1394 return GST_FLOW_ERROR;
1397 /* byte together hevc codec data based on collected pps and sps so far */
1399 gst_h265_parse_make_codec_data (GstH265Parse * h265parse)
1401 GstBuffer *buf, *nal;
1403 guint vps_size = 0, sps_size = 0, pps_size = 0;
1404 guint num_vps = 0, num_sps = 0, num_pps = 0;
1405 gboolean found = FALSE;
1409 guint8 num_arrays = 0;
1410 GstH265SPS *sps = NULL;
1411 guint16 min_spatial_segmentation_idc = 0;
1412 GstH265ProfileTierLevel *pft;
1414 /* only nal payload in stored nals */
1415 /* Fixme: Current implementation is not embedding SEI in codec_data */
1416 for (i = 0; i < GST_H265_MAX_VPS_COUNT; i++) {
1417 if ((nal = h265parse->vps_nals[i])) {
1419 /* size bytes also count */
1420 vps_size += gst_buffer_get_size (nal) + 2;
1426 for (i = 0; i < GST_H265_MAX_SPS_COUNT; i++) {
1427 if ((nal = h265parse->sps_nals[i])) {
1429 /* size bytes also count */
1430 sps_size += gst_buffer_get_size (nal) + 2;
1437 for (i = 0; i < GST_H265_MAX_PPS_COUNT; i++) {
1438 if ((nal = h265parse->pps_nals[i])) {
1440 /* size bytes also count */
1441 pps_size += gst_buffer_get_size (nal) + 2;
1447 GST_DEBUG_OBJECT (h265parse,
1448 "constructing codec_data: num_vps =%d num_sps=%d, num_pps=%d", num_vps,
1454 sps = h265parse->nalparser->last_sps;
1459 gst_buffer_new_allocate (NULL,
1460 23 + (3 * num_arrays) + vps_size + sps_size + pps_size, NULL);
1461 gst_buffer_map (buf, &map, GST_MAP_WRITE);
1463 memset (data, 0, map.size);
1464 nl = h265parse->nal_length_size;
1466 pft = &sps->profile_tier_level;
1467 if (sps->vui_parameters_present_flag)
1468 min_spatial_segmentation_idc = sps->vui_params.min_spatial_segmentation_idc;
1470 /* HEVCDecoderConfigurationVersion = 1
1471 * profile_space | tier_flat | profile_idc |
1472 * profile_compatibility_flags | constraint_indicator_flags |
1476 (pft->profile_space << 5) | (pft->tier_flag << 5) | pft->profile_idc;
1477 for (i = 2; i < 6; i++) {
1478 for (j = 7; j >= 0; j--) {
1479 data[i] |= (pft->profile_compatibility_flag[k] << j);
1485 (pft->progressive_source_flag << 7) |
1486 (pft->interlaced_source_flag << 6) |
1487 (pft->non_packed_constraint_flag << 5) |
1488 (pft->frame_only_constraint_flag << 4) |
1489 (pft->max_12bit_constraint_flag << 3) |
1490 (pft->max_10bit_constraint_flag << 2) |
1491 (pft->max_8bit_constraint_flag << 1) |
1492 (pft->max_422chroma_constraint_flag);
1495 (pft->max_420chroma_constraint_flag << 7) |
1496 (pft->max_monochrome_constraint_flag << 6) |
1497 (pft->intra_constraint_flag << 5) |
1498 (pft->one_picture_only_constraint_flag << 4) |
1499 (pft->lower_bit_rate_constraint_flag << 3) |
1500 (pft->max_14bit_constraint_flag << 2);
1502 data[12] = pft->level_idc;
1503 /* min_spatial_segmentation_idc */
1504 GST_WRITE_UINT16_BE (data + 13, min_spatial_segmentation_idc);
1506 data[15] = 0xfc; /* keeping parrallelismType as zero (unknown) */
1507 data[16] = 0xfc | sps->chroma_format_idc;
1508 data[17] = 0xf8 | sps->bit_depth_luma_minus8;
1509 data[18] = 0xf8 | sps->bit_depth_chroma_minus8;
1510 data[19] = 0x00; /* keep avgFrameRate as unspecified */
1511 data[20] = 0x00; /* keep avgFrameRate as unspecified */
1512 /* constFrameRate(2 bits): 0, stream may or may not be of constant framerate
1513 * numTemporalLayers (3 bits): number of temporal layers, value from SPS
1514 * TemporalIdNested (1 bit): sps_temporal_id_nesting_flag from SPS
1515 * lengthSizeMinusOne (2 bits): plus 1 indicates the length of the NALUnitLength */
1517 0x00 | ((sps->max_sub_layers_minus1 +
1518 1) << 3) | (sps->temporal_id_nesting_flag << 2) | (nl - 1);
1519 GST_WRITE_UINT8 (data + 22, num_arrays); /* numOfArrays */
1525 /* array_completeness | reserved_zero bit | nal_unit_type */
1526 data[0] = 0x00 | 0x20;
1529 GST_WRITE_UINT16_BE (data, num_vps);
1532 for (i = 0; i < GST_H265_MAX_VPS_COUNT; i++) {
1533 if ((nal = h265parse->vps_nals[i])) {
1534 gsize nal_size = gst_buffer_get_size (nal);
1535 GST_WRITE_UINT16_BE (data, nal_size);
1536 gst_buffer_extract (nal, 0, data + 2, nal_size);
1537 data += 2 + nal_size;
1544 /* array_completeness | reserved_zero bit | nal_unit_type */
1545 data[0] = 0x00 | 0x21;
1548 GST_WRITE_UINT16_BE (data, num_sps);
1551 for (i = 0; i < GST_H265_MAX_SPS_COUNT; i++) {
1552 if ((nal = h265parse->sps_nals[i])) {
1553 gsize nal_size = gst_buffer_get_size (nal);
1554 GST_WRITE_UINT16_BE (data, nal_size);
1555 gst_buffer_extract (nal, 0, data + 2, nal_size);
1556 data += 2 + nal_size;
1563 /* array_completeness | reserved_zero bit | nal_unit_type */
1564 data[0] = 0x00 | 0x22;
1567 GST_WRITE_UINT16_BE (data, num_pps);
1570 for (i = 0; i < GST_H265_MAX_PPS_COUNT; i++) {
1571 if ((nal = h265parse->pps_nals[i])) {
1572 gsize nal_size = gst_buffer_get_size (nal);
1573 GST_WRITE_UINT16_BE (data, nal_size);
1574 gst_buffer_extract (nal, 0, data + 2, nal_size);
1575 data += 2 + nal_size;
1579 gst_buffer_unmap (buf, &map);
1585 gst_h265_parse_get_par (GstH265Parse * h265parse, gint * num, gint * den)
1587 if (h265parse->upstream_par_n != -1 && h265parse->upstream_par_d != -1) {
1588 *num = h265parse->upstream_par_n;
1589 *den = h265parse->upstream_par_d;
1591 *num = h265parse->parsed_par_n;
1592 *den = h265parse->parsed_par_d;
1596 static const gchar *
1597 digit_to_string (guint digit)
1599 static const char itoa[][2] = {
1600 "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"
1603 if (G_LIKELY (digit < 10))
1609 static const gchar *
1610 get_tier_string (guint8 tier_flag)
1612 const gchar *tier = NULL;
1622 static const gchar *
1623 get_level_string (guint8 level_idc)
1627 else if (level_idc % 30 == 0)
1628 return digit_to_string (level_idc / 30);
1630 switch (level_idc) {
1658 static inline guint64
1659 profile_to_flag (GstH265Profile p)
1661 return (guint64) 1 << (guint64) p;
1665 get_compatible_profile_caps (GstH265SPS * sps, GstH265Profile profile)
1667 GstCaps *caps = NULL;
1669 GValue compat_profiles = G_VALUE_INIT;
1670 guint64 profiles = 0;
1672 g_value_init (&compat_profiles, GST_TYPE_LIST);
1674 /* Relaxing profiles condition based on decoder capability specified by spec */
1675 if (sps->profile_tier_level.profile_compatibility_flag[1])
1676 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN);
1678 if (sps->profile_tier_level.profile_compatibility_flag[2])
1679 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_10);
1681 if (sps->profile_tier_level.profile_compatibility_flag[3])
1682 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_STILL_PICTURE);
1685 case GST_H265_PROFILE_MAIN_10:
1688 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_12);
1689 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_422_10);
1690 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_422_12);
1691 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_444_10);
1692 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_444_12);
1695 profiles |= profile_to_flag (GST_H265_PROFILE_SCREEN_EXTENDED_MAIN_10);
1698 profiles |= profile_to_flag (GST_H265_PROFILE_SCALABLE_MAIN_10);
1701 case GST_H265_PROFILE_MAIN:
1704 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_10);
1707 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_12);
1708 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_422_10);
1709 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_422_12);
1710 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_444_10);
1711 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_444_12);
1714 profiles |= profile_to_flag (GST_H265_PROFILE_SCREEN_EXTENDED_MAIN);
1715 profiles |= profile_to_flag (GST_H265_PROFILE_SCREEN_EXTENDED_MAIN_10);
1716 profiles |= profile_to_flag (GST_H265_PROFILE_SCREEN_EXTENDED_MAIN_444);
1718 profile_to_flag (GST_H265_PROFILE_SCREEN_EXTENDED_MAIN_444_10);
1721 (GST_H265_PROFILE_SCREEN_EXTENDED_HIGH_THROUGHPUT_444);
1724 (GST_H265_PROFILE_SCREEN_EXTENDED_HIGH_THROUGHPUT_444_10);
1727 (GST_H265_PROFILE_SCREEN_EXTENDED_HIGH_THROUGHPUT_444_14);
1730 profiles |= profile_to_flag (GST_H265_PROFILE_MULTIVIEW_MAIN);
1733 profiles |= profile_to_flag (GST_H265_PROFILE_SCALABLE_MAIN);
1734 profiles |= profile_to_flag (GST_H265_PROFILE_SCALABLE_MAIN_10);
1737 profiles |= profile_to_flag (GST_H265_PROFILE_3D_MAIN);
1740 case GST_H265_PROFILE_MAIN_STILL_PICTURE:
1743 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN);
1744 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_10);
1747 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_12);
1748 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_422_10);
1749 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_422_12);
1750 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_444_10);
1751 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_444_12);
1753 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_INTRA);
1754 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_10_INTRA);
1755 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_12_INTRA);
1756 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_422_10_INTRA);
1757 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_422_12_INTRA);
1758 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_444_INTRA);
1759 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_444_10_INTRA);
1760 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_444_12_INTRA);
1761 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_444_16_INTRA);
1762 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_444_STILL_PICTURE);
1763 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_444_16_STILL_PICTURE);
1766 profiles |= profile_to_flag (GST_H265_PROFILE_SCREEN_EXTENDED_MAIN);
1767 profiles |= profile_to_flag (GST_H265_PROFILE_SCREEN_EXTENDED_MAIN_10);
1768 profiles |= profile_to_flag (GST_H265_PROFILE_SCREEN_EXTENDED_MAIN_444);
1770 profile_to_flag (GST_H265_PROFILE_SCREEN_EXTENDED_MAIN_444_10);
1773 (GST_H265_PROFILE_SCREEN_EXTENDED_HIGH_THROUGHPUT_444);
1776 (GST_H265_PROFILE_SCREEN_EXTENDED_HIGH_THROUGHPUT_444_10);
1779 (GST_H265_PROFILE_SCREEN_EXTENDED_HIGH_THROUGHPUT_444_14);
1782 case GST_H265_PROFILE_MONOCHROME:
1785 profiles |= profile_to_flag (GST_H265_PROFILE_SCREEN_EXTENDED_MAIN);
1786 profiles |= profile_to_flag (GST_H265_PROFILE_SCREEN_EXTENDED_MAIN_10);
1787 profiles |= profile_to_flag (GST_H265_PROFILE_SCREEN_EXTENDED_MAIN_444);
1789 profile_to_flag (GST_H265_PROFILE_SCREEN_EXTENDED_MAIN_444_10);
1792 (GST_H265_PROFILE_SCREEN_EXTENDED_HIGH_THROUGHPUT_444);
1795 (GST_H265_PROFILE_SCREEN_EXTENDED_HIGH_THROUGHPUT_444_10);
1798 (GST_H265_PROFILE_SCREEN_EXTENDED_HIGH_THROUGHPUT_444_14);
1801 case GST_H265_PROFILE_MAIN_444:
1804 profiles |= profile_to_flag (GST_H265_PROFILE_SCREEN_EXTENDED_MAIN_444);
1806 profile_to_flag (GST_H265_PROFILE_SCREEN_EXTENDED_MAIN_444_10);
1809 case GST_H265_PROFILE_MAIN_444_10:
1812 profiles |= profile_to_flag (GST_H265_PROFILE_SCREEN_EXTENDED_MAIN_10);
1815 case GST_H265_PROFILE_HIGH_THROUGHPUT_444:
1820 (GST_H265_PROFILE_SCREEN_EXTENDED_HIGH_THROUGHPUT_444);
1823 (GST_H265_PROFILE_SCREEN_EXTENDED_HIGH_THROUGHPUT_444_10);
1826 (GST_H265_PROFILE_SCREEN_EXTENDED_HIGH_THROUGHPUT_444_14);
1829 case GST_H265_PROFILE_HIGH_THROUGHPUT_444_10:
1834 (GST_H265_PROFILE_SCREEN_EXTENDED_HIGH_THROUGHPUT_444_10);
1837 (GST_H265_PROFILE_SCREEN_EXTENDED_HIGH_THROUGHPUT_444_14);
1840 case GST_H265_PROFILE_HIGH_THROUGHPUT_444_14:
1845 (GST_H265_PROFILE_SCREEN_EXTENDED_HIGH_THROUGHPUT_444_14);
1853 GValue value = G_VALUE_INIT;
1854 const gchar *profile_str;
1855 caps = gst_caps_new_empty_simple ("video/x-h265");
1857 for (i = GST_H265_PROFILE_MAIN; i < GST_H265_PROFILE_MAX; i++) {
1858 if ((profiles & profile_to_flag (i)) == profile_to_flag (i)) {
1859 profile_str = gst_h265_profile_to_string (i);
1861 if (G_UNLIKELY (profile_str == NULL)) {
1862 GST_FIXME ("Unhandled profile index %d", i);
1866 g_value_init (&value, G_TYPE_STRING);
1867 g_value_set_string (&value, profile_str);
1868 gst_value_list_append_value (&compat_profiles, &value);
1869 g_value_unset (&value);
1873 gst_caps_set_value (caps, "profile", &compat_profiles);
1874 g_value_unset (&compat_profiles);
1880 /* if downstream didn't support the exact profile indicated in sps header,
1881 * check for the compatible profiles also */
1883 ensure_caps_profile (GstH265Parse * h265parse, GstCaps * caps, GstH265SPS * sps,
1884 GstH265Profile profile)
1886 GstCaps *peer_caps, *compat_caps;
1888 peer_caps = gst_pad_get_current_caps (GST_BASE_PARSE_SRC_PAD (h265parse));
1889 if (!peer_caps || !gst_caps_can_intersect (caps, peer_caps)) {
1890 GstCaps *filter_caps = gst_caps_new_empty_simple ("video/x-h265");
1893 gst_caps_unref (peer_caps);
1895 gst_pad_peer_query_caps (GST_BASE_PARSE_SRC_PAD (h265parse),
1898 gst_caps_unref (filter_caps);
1901 if (peer_caps && !gst_caps_can_intersect (caps, peer_caps)) {
1902 GstStructure *structure;
1904 compat_caps = get_compatible_profile_caps (sps, profile);
1905 if (compat_caps != NULL) {
1906 GstCaps *res_caps = NULL;
1908 res_caps = gst_caps_intersect (peer_caps, compat_caps);
1910 if (res_caps && !gst_caps_is_empty (res_caps)) {
1911 const gchar *profile_str = NULL;
1913 res_caps = gst_caps_fixate (res_caps);
1914 structure = gst_caps_get_structure (res_caps, 0);
1915 profile_str = gst_structure_get_string (structure, "profile");
1917 gst_caps_set_simple (caps, "profile", G_TYPE_STRING, profile_str,
1919 GST_DEBUG_OBJECT (h265parse,
1920 "Setting compatible profile %s to the caps", profile_str);
1924 gst_caps_unref (res_caps);
1925 gst_caps_unref (compat_caps);
1929 gst_caps_unref (peer_caps);
1933 gst_h265_parse_update_src_caps (GstH265Parse * h265parse, GstCaps * caps)
1935 GstH265SPS *sps = NULL;
1936 GstCaps *sink_caps, *src_caps;
1937 gboolean modified = FALSE;
1938 GstBuffer *buf = NULL;
1939 GstStructure *s = NULL;
1941 if (G_UNLIKELY (!gst_pad_has_current_caps (GST_BASE_PARSE_SRC_PAD
1944 else if (G_UNLIKELY (!h265parse->update_caps))
1947 /* if this is being called from the first _setcaps call, caps on the sinkpad
1948 * aren't set yet and so they need to be passed as an argument */
1950 sink_caps = gst_caps_ref (caps);
1952 sink_caps = gst_pad_get_current_caps (GST_BASE_PARSE_SINK_PAD (h265parse));
1954 /* carry over input caps as much as possible; override with our own stuff */
1956 sink_caps = gst_caps_new_empty_simple ("video/x-h265");
1958 s = gst_caps_get_structure (sink_caps, 0);
1960 sps = h265parse->nalparser->last_sps;
1961 GST_DEBUG_OBJECT (h265parse, "sps: %p", sps);
1963 /* only codec-data for nice-and-clean au aligned packetized hevc format */
1964 if ((h265parse->format == GST_H265_PARSE_FORMAT_HVC1
1965 || h265parse->format == GST_H265_PARSE_FORMAT_HEV1)
1966 && h265parse->align == GST_H265_PARSE_ALIGN_AU) {
1967 buf = gst_h265_parse_make_codec_data (h265parse);
1968 if (buf && h265parse->codec_data) {
1971 gst_buffer_map (buf, &map, GST_MAP_READ);
1972 if (map.size != gst_buffer_get_size (h265parse->codec_data) ||
1973 gst_buffer_memcmp (h265parse->codec_data, 0, map.data, map.size))
1976 gst_buffer_unmap (buf, &map);
1978 if (!buf && h265parse->codec_data_in)
1979 buf = gst_buffer_ref (h265parse->codec_data_in);
1985 if (G_UNLIKELY (!sps)) {
1986 caps = gst_caps_copy (sink_caps);
1988 gint crop_width, crop_height;
1989 const gchar *chroma_format = NULL;
1990 guint bit_depth_chroma;
1991 GstH265VPS *vps = sps->vps;
1992 GstH265VUIParams *vui = &sps->vui_params;
1993 gchar *colorimetry = NULL;
1995 GST_DEBUG_OBJECT (h265parse, "vps: %p", vps);
1997 if (sps->conformance_window_flag) {
1998 crop_width = sps->crop_rect_width;
1999 crop_height = sps->crop_rect_height;
2001 crop_width = sps->width;
2002 crop_height = sps->height;
2005 if (G_UNLIKELY (h265parse->width != crop_width ||
2006 h265parse->height != crop_height)) {
2007 h265parse->width = crop_width;
2008 h265parse->height = sps->profile_tier_level.interlaced_source_flag ?
2009 crop_height * 2 : crop_height;
2010 GST_INFO_OBJECT (h265parse, "resolution changed %dx%d",
2011 h265parse->width, h265parse->height);
2015 /* 0/1 is set as the default in the codec parser */
2016 if (vui->timing_info_present_flag) {
2017 gint fps_num = 0, fps_den = 1;
2019 if (!(sps->fps_num == 0 && sps->fps_den == 1)) {
2020 fps_num = sps->fps_num;
2021 fps_den = sps->fps_den;
2022 } else if (!(sps->vui_params.time_scale == 0 &&
2023 sps->vui_params.num_units_in_tick == 1)) {
2024 fps_num = sps->vui_params.time_scale;
2025 fps_den = sps->vui_params.num_units_in_tick;
2027 if (sps->profile_tier_level.interlaced_source_flag)
2031 if (G_UNLIKELY (h265parse->fps_num != fps_num
2032 || h265parse->fps_den != fps_den)) {
2033 GST_INFO_OBJECT (h265parse, "framerate changed %d/%d",
2035 h265parse->fps_num = fps_num;
2036 h265parse->fps_den = fps_den;
2041 if (vui->aspect_ratio_info_present_flag) {
2042 if (G_UNLIKELY ((h265parse->parsed_par_n != vui->par_n)
2043 && (h265parse->parsed_par_d != sps->vui_params.par_d))) {
2044 h265parse->parsed_par_n = vui->par_n;
2045 h265parse->parsed_par_d = vui->par_d;
2046 GST_INFO_OBJECT (h265parse, "pixel aspect ratio has been changed %d/%d",
2047 h265parse->parsed_par_n, h265parse->parsed_par_d);
2053 if (vui->video_signal_type_present_flag &&
2054 vui->colour_description_present_flag) {
2055 GstVideoColorimetry ci = { 0, };
2056 gchar *old_colorimetry = NULL;
2058 if (vui->video_full_range_flag)
2059 ci.range = GST_VIDEO_COLOR_RANGE_0_255;
2061 ci.range = GST_VIDEO_COLOR_RANGE_16_235;
2063 ci.matrix = gst_video_color_matrix_from_iso (vui->matrix_coefficients);
2065 gst_video_transfer_function_from_iso (vui->transfer_characteristics);
2066 ci.primaries = gst_video_color_primaries_from_iso (vui->colour_primaries);
2069 gst_video_colorimetry_to_string (&h265parse->parsed_colorimetry);
2070 colorimetry = gst_video_colorimetry_to_string (&ci);
2072 if (colorimetry && g_strcmp0 (old_colorimetry, colorimetry)) {
2073 GST_INFO_OBJECT (h265parse,
2074 "colorimetry has been changed from %s to %s",
2075 GST_STR_NULL (old_colorimetry), colorimetry);
2076 h265parse->parsed_colorimetry = ci;
2080 g_free (old_colorimetry);
2083 if (G_UNLIKELY (modified || h265parse->update_caps)) {
2084 gint fps_num = h265parse->fps_num;
2085 gint fps_den = h265parse->fps_den;
2087 GstClockTime latency = 0;
2089 caps = gst_caps_copy (sink_caps);
2091 /* sps should give this but upstream overrides */
2092 if (s && gst_structure_has_field (s, "width"))
2093 gst_structure_get_int (s, "width", &width);
2095 width = h265parse->width;
2097 if (s && gst_structure_has_field (s, "height"))
2098 gst_structure_get_int (s, "height", &height);
2100 height = h265parse->height;
2102 gst_caps_set_simple (caps, "width", G_TYPE_INT, width,
2103 "height", G_TYPE_INT, height, NULL);
2105 h265parse->parsed_framerate = FALSE;
2106 /* upstream overrides */
2107 if (s && gst_structure_has_field (s, "framerate"))
2108 gst_structure_get_fraction (s, "framerate", &fps_num, &fps_den);
2110 /* but not necessarily or reliably this */
2115 GST_INFO_OBJECT (h265parse, "setting framerate in caps");
2116 gst_caps_set_simple (caps, "framerate",
2117 GST_TYPE_FRACTION, fps_num, fps_den, NULL);
2118 s2 = gst_caps_get_structure (caps, 0);
2119 gst_structure_get_fraction (s2, "framerate", &h265parse->parsed_fps_n,
2120 &h265parse->parsed_fps_d);
2121 gst_base_parse_set_frame_rate (GST_BASE_PARSE (h265parse),
2122 fps_num, fps_den, 0, 0);
2123 val = sps->profile_tier_level.interlaced_source_flag ? GST_SECOND / 2 :
2125 h265parse->parsed_framerate = TRUE;
2127 /* If we know the frame duration, and if we are not in one of the zero
2128 * latency pattern, add one frame of latency */
2130 h265parse->in_align != GST_H265_PARSE_ALIGN_AU &&
2131 !(h265parse->in_align == GST_H265_PARSE_ALIGN_NAL &&
2132 h265parse->align == GST_H265_PARSE_ALIGN_NAL))
2133 latency = gst_util_uint64_scale (val, fps_den, fps_num);
2135 gst_base_parse_set_latency (GST_BASE_PARSE (h265parse), latency,
2139 bit_depth_chroma = sps->bit_depth_chroma_minus8 + 8;
2141 switch (sps->chroma_format_idc) {
2143 chroma_format = "4:0:0";
2144 bit_depth_chroma = 0;
2147 chroma_format = "4:2:0";
2150 chroma_format = "4:2:2";
2153 chroma_format = "4:4:4";
2160 gst_caps_set_simple (caps, "chroma-format", G_TYPE_STRING,
2161 chroma_format, "bit-depth-luma", G_TYPE_UINT,
2162 sps->bit_depth_luma_minus8 + 8, "bit-depth-chroma", G_TYPE_UINT,
2163 bit_depth_chroma, NULL);
2165 if (colorimetry && (!s || !gst_structure_has_field (s, "colorimetry"))) {
2166 gst_caps_set_simple (caps, "colorimetry", G_TYPE_STRING, colorimetry,
2171 g_free (colorimetry);
2176 const gchar *mdi_str = NULL;
2177 const gchar *cll_str = NULL;
2178 gboolean codec_data_modified = FALSE;
2180 gst_caps_set_simple (caps, "parsed", G_TYPE_BOOLEAN, TRUE,
2181 "stream-format", G_TYPE_STRING,
2182 gst_h265_parse_get_string (h265parse, TRUE, h265parse->format),
2183 "alignment", G_TYPE_STRING,
2184 gst_h265_parse_get_string (h265parse, FALSE, h265parse->align), NULL);
2186 gst_h265_parse_get_par (h265parse, &par_n, &par_d);
2187 if (par_n != 0 && par_d != 0 &&
2188 (!s || !gst_structure_has_field (s, "pixel-aspect-ratio"))) {
2189 GST_INFO_OBJECT (h265parse, "PAR %d/%d", par_n, par_d);
2190 gst_caps_set_simple (caps, "pixel-aspect-ratio", GST_TYPE_FRACTION,
2191 par_n, par_d, NULL);
2194 /* set profile and level in caps */
2196 const gchar *profile, *tier, *level;
2199 p = gst_h265_get_profile_from_sps (sps);
2201 profile = gst_h265_profile_to_string (p);
2202 if (profile != NULL)
2203 gst_caps_set_simple (caps, "profile", G_TYPE_STRING, profile, NULL);
2205 tier = get_tier_string (sps->profile_tier_level.tier_flag);
2207 gst_caps_set_simple (caps, "tier", G_TYPE_STRING, tier, NULL);
2209 level = get_level_string (sps->profile_tier_level.level_idc);
2211 gst_caps_set_simple (caps, "level", G_TYPE_STRING, level, NULL);
2213 /* relax the profile constraint to find a suitable decoder */
2214 ensure_caps_profile (h265parse, caps, sps, p);
2218 mdi_str = gst_structure_get_string (s, "mastering-display-info");
2220 gst_caps_set_simple (caps, "mastering-display-info", G_TYPE_STRING,
2222 } else if (h265parse->mastering_display_info_state !=
2223 GST_H265_PARSE_SEI_EXPIRED &&
2224 !gst_video_mastering_display_info_add_to_caps
2225 (&h265parse->mastering_display_info, caps)) {
2226 GST_WARNING_OBJECT (h265parse,
2227 "Couldn't set mastering display info to caps");
2231 cll_str = gst_structure_get_string (s, "content-light-level");
2233 gst_caps_set_simple (caps, "content-light-level", G_TYPE_STRING, cll_str,
2235 } else if (h265parse->content_light_level_state !=
2236 GST_H265_PARSE_SEI_EXPIRED &&
2237 !gst_video_content_light_level_add_to_caps
2238 (&h265parse->content_light_level, caps)) {
2239 GST_WARNING_OBJECT (h265parse,
2240 "Couldn't set content light level to caps");
2243 src_caps = gst_pad_get_current_caps (GST_BASE_PARSE_SRC_PAD (h265parse));
2246 GstStructure *src_caps_str = gst_caps_get_structure (src_caps, 0);
2248 /* use codec data from old caps for comparison if we have pushed frame for now.
2249 * we don't want to resend caps if everything is same except codec data.
2250 * However, if the updated sps/pps is not in bitstream, we should put
2251 * it on bitstream */
2252 if (gst_structure_has_field (src_caps_str, "codec_data")) {
2253 const GValue *codec_data_value =
2254 gst_structure_get_value (src_caps_str, "codec_data");
2256 if (!GST_VALUE_HOLDS_BUFFER (codec_data_value)) {
2257 GST_WARNING_OBJECT (h265parse, "codec_data does not hold buffer");
2258 } else if (!h265parse->first_frame) {
2259 /* If there is no pushed frame before, we can update caps without worry.
2260 * But updating codec_data in the middle of frames
2261 * (especially on non-keyframe) might make downstream be confused.
2262 * Therefore we are setting old codec data
2263 * (i.e., was pushed to downstream previously) to new caps candidate
2264 * here for gst_caps_is_strictly_equal() to be returned TRUE if only
2265 * the codec_data is different, and to avoid re-sending caps it
2268 gst_caps_set_value (caps, "codec_data", codec_data_value);
2270 /* check for codec_data update to re-send sps/pps inband data if
2271 * current frame has no sps/pps but upstream codec_data was updated.
2272 * Note that have_vps_in_frame is skipped here since it's optional */
2273 if ((!h265parse->have_sps_in_frame || !h265parse->have_pps_in_frame)
2275 GstBuffer *codec_data_buf = gst_value_get_buffer (codec_data_value);
2278 gst_buffer_map (buf, &map, GST_MAP_READ);
2279 if (map.size != gst_buffer_get_size (codec_data_buf) ||
2280 gst_buffer_memcmp (codec_data_buf, 0, map.data, map.size)) {
2281 codec_data_modified = TRUE;
2284 gst_buffer_unmap (buf, &map);
2289 /* remove any left-over codec-data hanging around */
2290 s = gst_caps_get_structure (caps, 0);
2291 gst_structure_remove_field (s, "codec_data");
2295 if (!(src_caps && gst_caps_is_strictly_equal (src_caps, caps))) {
2296 /* update codec data to new value */
2298 gst_caps_set_simple (caps, "codec_data", GST_TYPE_BUFFER, buf, NULL);
2299 gst_buffer_replace (&h265parse->codec_data, buf);
2300 gst_buffer_unref (buf);
2304 /* remove any left-over codec-data hanging around */
2305 s = gst_caps_get_structure (caps, 0);
2306 gst_structure_remove_field (s, "codec_data");
2307 gst_buffer_replace (&h265parse->codec_data, NULL);
2310 gst_pad_set_caps (GST_BASE_PARSE_SRC_PAD (h265parse), caps);
2311 } else if (codec_data_modified) {
2312 GST_DEBUG_OBJECT (h265parse,
2313 "Only codec_data is different, need inband vps/sps/pps update");
2315 /* this will insert updated codec_data with next idr */
2316 h265parse->push_codec = TRUE;
2320 gst_caps_unref (src_caps);
2321 gst_caps_unref (caps);
2324 gst_caps_unref (sink_caps);
2326 gst_buffer_unref (buf);
2330 static GstFlowReturn
2331 gst_h265_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
2333 GstH265Parse *h265parse;
2337 h265parse = GST_H265_PARSE (parse);
2338 buffer = frame->buffer;
2340 gst_h265_parse_update_src_caps (h265parse, NULL);
2342 if (h265parse->fps_num > 0 && h265parse->fps_den > 0) {
2343 GstH265SPS *sps = h265parse->nalparser->last_sps;
2346 val = (sps != NULL && sps->profile_tier_level.interlaced_source_flag) ?
2347 GST_SECOND / 2 : GST_SECOND;
2348 GST_BUFFER_DURATION (buffer) = gst_util_uint64_scale (val,
2349 h265parse->fps_den, h265parse->fps_num);
2352 if (h265parse->keyframe)
2353 GST_BUFFER_FLAG_UNSET (buffer, GST_BUFFER_FLAG_DELTA_UNIT);
2355 GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT);
2357 if (h265parse->discard_bidirectional && h265parse->bidirectional)
2361 if (h265parse->header)
2362 GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_HEADER);
2364 GST_BUFFER_FLAG_UNSET (buffer, GST_BUFFER_FLAG_HEADER);
2366 if (h265parse->discont) {
2367 GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
2368 h265parse->discont = FALSE;
2371 if (h265parse->marker) {
2372 GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_MARKER);
2373 h265parse->marker = FALSE;
2375 GST_BUFFER_FLAG_UNSET (buffer, GST_BUFFER_FLAG_MARKER);
2378 /* replace with transformed HEVC output if applicable */
2379 av = gst_adapter_available (h265parse->frame_out);
2383 buf = gst_adapter_take_buffer (h265parse->frame_out, av);
2384 gst_buffer_copy_into (buf, buffer, GST_BUFFER_COPY_METADATA, 0, -1);
2385 gst_buffer_replace (&frame->out_buffer, buf);
2386 gst_buffer_unref (buf);
2393 GST_DEBUG_OBJECT (h265parse, "Discarding bidirectional frame");
2394 frame->flags |= GST_BASE_PARSE_FRAME_FLAG_DROP;
2395 gst_h265_parse_reset_frame (h265parse);
2400 /* sends a codec NAL downstream, decorating and transforming as needed.
2401 * No ownership is taken of @nal */
2402 static GstFlowReturn
2403 gst_h265_parse_push_codec_buffer (GstH265Parse * h265parse, GstBuffer * nal,
2408 gst_buffer_map (nal, &map, GST_MAP_READ);
2409 nal = gst_h265_parse_wrap_nal (h265parse, h265parse->format,
2410 map.data, map.size);
2411 gst_buffer_unmap (nal, &map);
2413 if (h265parse->discont) {
2414 GST_BUFFER_FLAG_SET (nal, GST_BUFFER_FLAG_DISCONT);
2415 h265parse->discont = FALSE;
2418 GST_BUFFER_PTS (nal) = GST_BUFFER_PTS (buffer);
2419 GST_BUFFER_DTS (nal) = GST_BUFFER_DTS (buffer);
2420 GST_BUFFER_DURATION (nal) = 0;
2422 return gst_pad_push (GST_BASE_PARSE_SRC_PAD (h265parse), nal);
2426 check_pending_key_unit_event (GstEvent * pending_event, GstSegment * segment,
2427 GstClockTime timestamp, guint flags, GstClockTime pending_key_unit_ts)
2429 GstClockTime running_time, stream_time;
2430 gboolean all_headers;
2432 GstEvent *event = NULL;
2434 g_return_val_if_fail (segment != NULL, NULL);
2436 if (pending_event == NULL)
2439 if (GST_CLOCK_TIME_IS_VALID (pending_key_unit_ts) &&
2440 timestamp == GST_CLOCK_TIME_NONE)
2443 running_time = gst_segment_to_running_time (segment,
2444 GST_FORMAT_TIME, timestamp);
2446 GST_INFO ("now %" GST_TIME_FORMAT " wanted %" GST_TIME_FORMAT,
2447 GST_TIME_ARGS (running_time), GST_TIME_ARGS (pending_key_unit_ts));
2448 if (GST_CLOCK_TIME_IS_VALID (pending_key_unit_ts) &&
2449 running_time < pending_key_unit_ts)
2452 if (flags & GST_BUFFER_FLAG_DELTA_UNIT) {
2453 GST_DEBUG ("pending force key unit, waiting for keyframe");
2457 stream_time = gst_segment_to_stream_time (segment,
2458 GST_FORMAT_TIME, timestamp);
2460 if (!gst_video_event_parse_upstream_force_key_unit (pending_event,
2461 NULL, &all_headers, &count)) {
2462 gst_video_event_parse_downstream_force_key_unit (pending_event, NULL,
2463 NULL, NULL, &all_headers, &count);
2467 gst_video_event_new_downstream_force_key_unit (timestamp, stream_time,
2468 running_time, all_headers, count);
2469 gst_event_set_seqnum (event, gst_event_get_seqnum (pending_event));
2476 gst_h265_parse_prepare_key_unit (GstH265Parse * parse, GstEvent * event)
2478 GstClockTime running_time;
2480 #ifndef GST_DISABLE_GST_DEBUG
2481 gboolean have_vps, have_sps, have_pps;
2485 parse->pending_key_unit_ts = GST_CLOCK_TIME_NONE;
2486 gst_event_replace (&parse->force_key_unit_event, NULL);
2488 gst_video_event_parse_downstream_force_key_unit (event,
2489 NULL, NULL, &running_time, NULL, &count);
2491 GST_INFO_OBJECT (parse, "pushing downstream force-key-unit event %d "
2492 "%" GST_TIME_FORMAT " count %d", gst_event_get_seqnum (event),
2493 GST_TIME_ARGS (running_time), count);
2494 gst_pad_push_event (GST_BASE_PARSE_SRC_PAD (parse), event);
2496 #ifndef GST_DISABLE_GST_DEBUG
2497 have_vps = have_sps = have_pps = FALSE;
2498 for (i = 0; i < GST_H265_MAX_VPS_COUNT; i++) {
2499 if (parse->vps_nals[i] != NULL) {
2504 for (i = 0; i < GST_H265_MAX_SPS_COUNT; i++) {
2505 if (parse->sps_nals[i] != NULL) {
2510 for (i = 0; i < GST_H265_MAX_PPS_COUNT; i++) {
2511 if (parse->pps_nals[i] != NULL) {
2517 GST_INFO_OBJECT (parse,
2518 "preparing key unit, have vps %d have sps %d have pps %d", have_vps,
2519 have_sps, have_pps);
2522 /* set push_codec to TRUE so that pre_push_frame sends VPS/SPS/PPS again */
2523 parse->push_codec = TRUE;
2527 gst_h265_parse_handle_vps_sps_pps_nals (GstH265Parse * h265parse,
2528 GstBuffer * buffer, GstBaseParseFrame * frame)
2530 GstBuffer *codec_nal;
2532 gboolean send_done = FALSE;
2534 if (h265parse->have_vps_in_frame && h265parse->have_sps_in_frame
2535 && h265parse->have_pps_in_frame) {
2536 GST_DEBUG_OBJECT (h265parse, "VPS/SPS/PPS exist in frame, will not insert");
2540 if (h265parse->align == GST_H265_PARSE_ALIGN_NAL) {
2541 /* send separate config NAL buffers */
2542 GST_DEBUG_OBJECT (h265parse, "- sending VPS/SPS/PPS");
2543 for (i = 0; i < GST_H265_MAX_VPS_COUNT; i++) {
2544 if ((codec_nal = h265parse->vps_nals[i])) {
2545 GST_DEBUG_OBJECT (h265parse, "sending VPS nal");
2546 gst_h265_parse_push_codec_buffer (h265parse, codec_nal, buffer);
2550 for (i = 0; i < GST_H265_MAX_SPS_COUNT; i++) {
2551 if ((codec_nal = h265parse->sps_nals[i])) {
2552 GST_DEBUG_OBJECT (h265parse, "sending SPS nal");
2553 gst_h265_parse_push_codec_buffer (h265parse, codec_nal, buffer);
2557 for (i = 0; i < GST_H265_MAX_PPS_COUNT; i++) {
2558 if ((codec_nal = h265parse->pps_nals[i])) {
2559 GST_DEBUG_OBJECT (h265parse, "sending PPS nal");
2560 gst_h265_parse_push_codec_buffer (h265parse, codec_nal, buffer);
2565 /* insert config NALs into AU */
2568 const gboolean bs = h265parse->format == GST_H265_PARSE_FORMAT_BYTE;
2569 const gint nls = 4 - h265parse->nal_length_size;
2572 gst_byte_writer_init_with_size (&bw, gst_buffer_get_size (buffer), FALSE);
2573 ok = gst_byte_writer_put_buffer (&bw, buffer, 0, h265parse->idr_pos);
2574 GST_DEBUG_OBJECT (h265parse, "- inserting VPS/SPS/PPS");
2575 for (i = 0; i < GST_H265_MAX_VPS_COUNT; i++) {
2576 if ((codec_nal = h265parse->vps_nals[i])) {
2577 gsize nal_size = gst_buffer_get_size (codec_nal);
2578 GST_DEBUG_OBJECT (h265parse, "inserting VPS nal");
2580 ok &= gst_byte_writer_put_uint32_be (&bw, 1);
2582 ok &= gst_byte_writer_put_uint32_be (&bw, (nal_size << (nls * 8)));
2583 ok &= gst_byte_writer_set_pos (&bw,
2584 gst_byte_writer_get_pos (&bw) - nls);
2587 ok &= gst_byte_writer_put_buffer (&bw, codec_nal, 0, nal_size);
2591 for (i = 0; i < GST_H265_MAX_SPS_COUNT; i++) {
2592 if ((codec_nal = h265parse->sps_nals[i])) {
2593 gsize nal_size = gst_buffer_get_size (codec_nal);
2594 GST_DEBUG_OBJECT (h265parse, "inserting SPS nal");
2596 ok &= gst_byte_writer_put_uint32_be (&bw, 1);
2598 ok &= gst_byte_writer_put_uint32_be (&bw, (nal_size << (nls * 8)));
2599 ok &= gst_byte_writer_set_pos (&bw,
2600 gst_byte_writer_get_pos (&bw) - nls);
2603 ok &= gst_byte_writer_put_buffer (&bw, codec_nal, 0, nal_size);
2607 for (i = 0; i < GST_H265_MAX_PPS_COUNT; i++) {
2608 if ((codec_nal = h265parse->pps_nals[i])) {
2609 gsize nal_size = gst_buffer_get_size (codec_nal);
2610 GST_DEBUG_OBJECT (h265parse, "inserting PPS nal");
2612 ok &= gst_byte_writer_put_uint32_be (&bw, 1);
2614 ok &= gst_byte_writer_put_uint32_be (&bw, (nal_size << (nls * 8)));
2615 ok &= gst_byte_writer_set_pos (&bw,
2616 gst_byte_writer_get_pos (&bw) - nls);
2618 ok &= gst_byte_writer_put_buffer (&bw, codec_nal, 0, nal_size);
2622 ok &= gst_byte_writer_put_buffer (&bw, buffer, h265parse->idr_pos, -1);
2623 /* collect result and push */
2624 new_buf = gst_byte_writer_reset_and_get_buffer (&bw);
2625 gst_buffer_copy_into (new_buf, buffer, GST_BUFFER_COPY_METADATA, 0, -1);
2626 /* should already be keyframe/IDR, but it may not have been,
2627 * so mark it as such to avoid being discarded by picky decoder */
2628 GST_BUFFER_FLAG_UNSET (new_buf, GST_BUFFER_FLAG_DELTA_UNIT);
2629 gst_buffer_replace (&frame->out_buffer, new_buf);
2630 gst_buffer_unref (new_buf);
2631 /* some result checking seems to make some compilers happy */
2632 if (G_UNLIKELY (!ok)) {
2633 GST_ERROR_OBJECT (h265parse, "failed to insert SPS/PPS");
2640 static GstFlowReturn
2641 gst_h265_parse_pre_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
2643 GstH265Parse *h265parse;
2646 GstBuffer *parse_buffer = NULL;
2648 h265parse = GST_H265_PARSE (parse);
2650 if (h265parse->first_frame) {
2651 GstTagList *taglist;
2655 caps = gst_pad_get_current_caps (GST_BASE_PARSE_SRC_PAD (parse));
2656 if (G_UNLIKELY (caps == NULL)) {
2657 if (GST_PAD_IS_FLUSHING (GST_BASE_PARSE_SRC_PAD (parse))) {
2658 GST_INFO_OBJECT (parse, "Src pad is flushing");
2659 return GST_FLOW_FLUSHING;
2661 GST_INFO_OBJECT (parse, "Src pad is not negotiated!");
2662 return GST_FLOW_NOT_NEGOTIATED;
2666 taglist = gst_tag_list_new_empty ();
2667 gst_pb_utils_add_codec_description_to_tag_list (taglist,
2668 GST_TAG_VIDEO_CODEC, caps);
2669 gst_caps_unref (caps);
2671 gst_base_parse_merge_tags (parse, taglist, GST_TAG_MERGE_REPLACE);
2672 gst_tag_list_unref (taglist);
2674 /* also signals the end of first-frame processing */
2675 h265parse->first_frame = FALSE;
2678 buffer = frame->buffer;
2680 if ((event = check_pending_key_unit_event (h265parse->force_key_unit_event,
2681 &parse->segment, GST_BUFFER_TIMESTAMP (buffer),
2682 GST_BUFFER_FLAGS (buffer), h265parse->pending_key_unit_ts))) {
2683 gst_h265_parse_prepare_key_unit (h265parse, event);
2686 /* periodic VPS/SPS/PPS sending */
2687 if (h265parse->interval > 0 || h265parse->push_codec) {
2688 GstClockTime timestamp = GST_BUFFER_TIMESTAMP (buffer);
2690 gboolean initial_frame = FALSE;
2693 if (!GST_CLOCK_TIME_IS_VALID (h265parse->last_report)) {
2694 h265parse->last_report = timestamp;
2695 initial_frame = TRUE;
2698 if (h265parse->idr_pos >= 0) {
2699 GST_LOG_OBJECT (h265parse, "IDR nal at offset %d", h265parse->idr_pos);
2701 if (timestamp > h265parse->last_report)
2702 diff = timestamp - h265parse->last_report;
2706 GST_LOG_OBJECT (h265parse,
2707 "now %" GST_TIME_FORMAT ", last VPS/SPS/PPS %" GST_TIME_FORMAT,
2708 GST_TIME_ARGS (timestamp), GST_TIME_ARGS (h265parse->last_report));
2710 GST_DEBUG_OBJECT (h265parse,
2711 "interval since last VPS/SPS/PPS %" GST_TIME_FORMAT,
2712 GST_TIME_ARGS (diff));
2714 if (GST_TIME_AS_SECONDS (diff) >= h265parse->interval ||
2715 initial_frame || h265parse->push_codec) {
2716 GstClockTime new_ts;
2718 /* avoid overwriting a perfectly fine timestamp */
2719 new_ts = GST_CLOCK_TIME_IS_VALID (timestamp) ? timestamp :
2720 h265parse->last_report;
2722 if (gst_h265_parse_handle_vps_sps_pps_nals (h265parse, buffer, frame)) {
2723 h265parse->last_report = new_ts;
2727 /* we pushed whatever we had */
2728 h265parse->push_codec = FALSE;
2729 h265parse->have_vps = FALSE;
2730 h265parse->have_sps = FALSE;
2731 h265parse->have_pps = FALSE;
2732 h265parse->state &= GST_H265_PARSE_STATE_VALID_PICTURE_HEADERS;
2734 } else if (h265parse->interval == -1) {
2735 if (h265parse->idr_pos >= 0) {
2736 GST_LOG_OBJECT (h265parse, "IDR nal at offset %d", h265parse->idr_pos);
2738 gst_h265_parse_handle_vps_sps_pps_nals (h265parse, buffer, frame);
2740 /* we pushed whatever we had */
2741 h265parse->push_codec = FALSE;
2742 h265parse->have_vps = FALSE;
2743 h265parse->have_sps = FALSE;
2744 h265parse->have_pps = FALSE;
2745 h265parse->state &= GST_H265_PARSE_STATE_VALID_PICTURE_HEADERS;
2749 if (frame->out_buffer) {
2750 parse_buffer = frame->out_buffer =
2751 gst_buffer_make_writable (frame->out_buffer);
2753 parse_buffer = frame->buffer = gst_buffer_make_writable (frame->buffer);
2756 if (h265parse->sei_pic_struct != GST_H265_SEI_PIC_STRUCT_FRAME) {
2757 if (h265parse->parsed_framerate) {
2758 /* If the frame rate doesn't come from upstream (e.g. a muxer), it means
2759 * we must double it, because it's now fields per second */
2760 gint new_fps_n, new_fps_d;
2762 gst_util_fraction_multiply (h265parse->fps_num, h265parse->fps_den, 2, 1,
2763 &new_fps_n, &new_fps_d);
2764 h265parse->fps_num = new_fps_n;
2765 h265parse->fps_den = new_fps_d;
2766 h265parse->parsed_framerate = FALSE;
2767 /* We need to fix the duration of the first frame */
2768 GST_BUFFER_DURATION (parse_buffer) /= 2;
2770 GST_BUFFER_FLAG_SET (parse_buffer, GST_VIDEO_BUFFER_FLAG_INTERLACED);
2771 /* h265 doesn't support interleaved */
2772 switch (h265parse->sei_pic_struct) {
2773 case GST_H265_SEI_PIC_STRUCT_TOP_FIELD:
2774 case GST_H265_SEI_PIC_STRUCT_TOP_PAIRED_NEXT_BOTTOM:
2775 case GST_H265_SEI_PIC_STRUCT_TOP_PAIRED_PREVIOUS_BOTTOM:
2776 GST_BUFFER_FLAG_SET (parse_buffer, GST_VIDEO_BUFFER_FLAG_TOP_FIELD);
2778 case GST_H265_SEI_PIC_STRUCT_BOTTOM_FIELD:
2779 case GST_H265_SEI_PIC_STRUCT_BOTTOM_PAIRED_PREVIOUS_TOP:
2780 case GST_H265_SEI_PIC_STRUCT_BOTTOM_PAIRED_NEXT_TOP:
2781 GST_BUFFER_FLAG_SET (parse_buffer, GST_VIDEO_BUFFER_FLAG_BOTTOM_FIELD);
2791 for (i = 0; i < h265parse->time_code.num_clock_ts; i++) {
2792 gint field_count = -1;
2794 GstVideoTimeCodeFlags flags = 0;
2796 if (!h265parse->time_code.clock_timestamp_flag[i])
2799 h265parse->time_code.clock_timestamp_flag[i] = 0;
2802 switch (h265parse->sei_pic_struct) {
2803 case GST_H265_SEI_PIC_STRUCT_FRAME:
2804 case GST_H265_SEI_PIC_STRUCT_TOP_FIELD:
2805 case GST_H265_SEI_PIC_STRUCT_BOTTOM_FIELD:
2806 field_count = h265parse->sei_pic_struct;
2808 case GST_H265_SEI_PIC_STRUCT_TOP_BOTTOM:
2809 case GST_H265_SEI_PIC_STRUCT_TOP_PAIRED_PREVIOUS_BOTTOM:
2810 case GST_H265_SEI_PIC_STRUCT_TOP_PAIRED_NEXT_BOTTOM:
2811 field_count = i + 1;
2813 case GST_H265_SEI_PIC_STRUCT_BOTTOM_TOP:
2814 case GST_H265_SEI_PIC_STRUCT_BOTTOM_PAIRED_PREVIOUS_TOP:
2815 case GST_H265_SEI_PIC_STRUCT_BOTTOM_PAIRED_NEXT_TOP:
2816 field_count = 2 - i;
2818 case GST_H265_SEI_PIC_STRUCT_TOP_BOTTOM_TOP:
2819 field_count = i % 2 ? 2 : 1;
2821 case GST_H265_SEI_PIC_STRUCT_BOTTOM_TOP_BOTTOM:
2822 field_count = i % 2 ? 1 : 2;
2824 case GST_H265_SEI_PIC_STRUCT_FRAME_DOUBLING:
2825 case GST_H265_SEI_PIC_STRUCT_FRAME_TRIPLING:
2830 if (field_count == -1) {
2831 GST_WARNING_OBJECT (parse,
2832 "failed to determine field count for timecode");
2836 /* Dropping of the two lowest (value 0 and 1) n_frames[ i ] counts when
2837 * seconds_value[ i ] is equal to 0 and minutes_value[ i ] is not an integer
2839 if (h265parse->time_code.counting_type[i] == 4)
2840 flags |= GST_VIDEO_TIME_CODE_FLAGS_DROP_FRAME;
2842 if (h265parse->sei_pic_struct != GST_H265_SEI_PIC_STRUCT_FRAME)
2843 flags |= GST_VIDEO_TIME_CODE_FLAGS_INTERLACED;
2846 gst_util_uint64_scale_int (h265parse->time_code.n_frames[i], 1,
2847 2 - h265parse->time_code.units_field_based_flag[i]);
2849 gst_buffer_add_video_time_code_meta_full (parse_buffer,
2850 h265parse->parsed_fps_n,
2851 h265parse->parsed_fps_d,
2854 h265parse->time_code.hours_flag[i] ? h265parse->time_code.
2856 h265parse->time_code.minutes_flag[i] ? h265parse->time_code.
2857 minutes_value[i] : 0,
2858 h265parse->time_code.seconds_flag[i] ? h265parse->time_code.
2859 seconds_value[i] : 0, n_frames, field_count);
2863 if (h265parse->sei_pic_struct != GST_H265_SEI_PIC_STRUCT_FRAME) {
2864 GST_BUFFER_FLAG_SET (parse_buffer, GST_VIDEO_BUFFER_FLAG_INTERLACED);
2865 if (h265parse->sei_pic_struct == GST_H265_SEI_PIC_STRUCT_TOP_FIELD)
2866 GST_BUFFER_FLAG_SET (parse_buffer, GST_VIDEO_BUFFER_FLAG_TFF);
2869 gst_video_push_user_data ((GstElement *) h265parse, &h265parse->user_data,
2872 gst_h265_parse_reset_frame (h265parse);
2878 gst_h265_parse_set_caps (GstBaseParse * parse, GstCaps * caps)
2880 GstH265Parse *h265parse;
2882 const GValue *value;
2883 GstBuffer *codec_data = NULL;
2885 guint format, align;
2886 guint num_nals, i, j;
2887 GstH265NalUnit nalu;
2888 GstH265ParserResult parseres;
2891 h265parse = GST_H265_PARSE (parse);
2894 h265parse->push_codec = FALSE;
2896 old_caps = gst_pad_get_current_caps (GST_BASE_PARSE_SINK_PAD (parse));
2898 if (!gst_caps_is_equal (old_caps, caps))
2899 gst_h265_parse_reset_stream_info (h265parse);
2900 gst_caps_unref (old_caps);
2903 str = gst_caps_get_structure (caps, 0);
2905 /* accept upstream info if provided */
2906 gst_structure_get_int (str, "width", &h265parse->width);
2907 gst_structure_get_int (str, "height", &h265parse->height);
2908 gst_structure_get_fraction (str, "framerate", &h265parse->fps_num,
2909 &h265parse->fps_den);
2910 gst_structure_get_fraction (str, "pixel-aspect-ratio",
2911 &h265parse->upstream_par_n, &h265parse->upstream_par_d);
2913 /* get upstream format and align from caps */
2914 gst_h265_parse_format_from_caps (caps, &format, &align);
2916 /* packetized video has a codec_data */
2917 if (format != GST_H265_PARSE_FORMAT_BYTE &&
2918 (value = gst_structure_get_value (str, "codec_data"))) {
2921 guint num_nal_arrays;
2923 GST_DEBUG_OBJECT (h265parse, "have packetized h265");
2924 /* make note for optional split processing */
2925 h265parse->packetized = TRUE;
2927 codec_data = gst_value_get_buffer (value);
2930 gst_buffer_map (codec_data, &map, GST_MAP_READ);
2934 /* parse the hvcC data */
2936 gst_buffer_unmap (codec_data, &map);
2937 goto hvcc_too_small;
2939 /* parse the version, this must be one but
2940 * is zero until the spec is finalized */
2941 if (data[0] != 0 && data[0] != 1) {
2942 gst_buffer_unmap (codec_data, &map);
2946 h265parse->nal_length_size = (data[21] & 0x03) + 1;
2947 GST_DEBUG_OBJECT (h265parse, "nal length size %u",
2948 h265parse->nal_length_size);
2950 num_nal_arrays = data[22];
2953 for (i = 0; i < num_nal_arrays; i++) {
2954 if (off + 3 >= size) {
2955 gst_buffer_unmap (codec_data, &map);
2956 goto hvcc_too_small;
2959 num_nals = GST_READ_UINT16_BE (data + off + 1);
2961 for (j = 0; j < num_nals; j++) {
2962 parseres = gst_h265_parser_identify_nalu_hevc (h265parse->nalparser,
2963 data, off, size, 2, &nalu);
2965 if (parseres != GST_H265_PARSER_OK) {
2966 gst_buffer_unmap (codec_data, &map);
2967 goto hvcc_too_small;
2970 gst_h265_parse_process_nal (h265parse, &nalu);
2971 off = nalu.offset + nalu.size;
2974 gst_buffer_unmap (codec_data, &map);
2976 /* don't confuse codec_data with inband vps/sps/pps */
2977 h265parse->have_vps_in_frame = FALSE;
2978 h265parse->have_sps_in_frame = FALSE;
2979 h265parse->have_pps_in_frame = FALSE;
2981 GST_DEBUG_OBJECT (h265parse, "have bytestream h265");
2982 /* nothing to pre-process */
2983 h265parse->packetized = FALSE;
2984 /* we have 4 sync bytes */
2985 h265parse->nal_length_size = 4;
2987 if (format == GST_H265_PARSE_FORMAT_NONE) {
2988 format = GST_H265_PARSE_FORMAT_BYTE;
2989 align = GST_H265_PARSE_ALIGN_AU;
2996 /* prefer input type determined above */
2997 in_caps = gst_caps_new_simple ("video/x-h265",
2998 "parsed", G_TYPE_BOOLEAN, TRUE,
2999 "stream-format", G_TYPE_STRING,
3000 gst_h265_parse_get_string (h265parse, TRUE, format),
3001 "alignment", G_TYPE_STRING,
3002 gst_h265_parse_get_string (h265parse, FALSE, align), NULL);
3003 /* negotiate with downstream, sets ->format and ->align */
3004 gst_h265_parse_negotiate (h265parse, format, in_caps);
3005 gst_caps_unref (in_caps);
3008 if (format == h265parse->format && align == h265parse->align) {
3009 /* do not set CAPS and passthrough mode if SPS/PPS have not been parsed */
3010 if (h265parse->have_sps && h265parse->have_pps) {
3011 /* Don't enable passthrough here. This element will parse various
3012 * SEI messages which would be very important/useful for downstream
3013 * (HDR, timecode for example)
3016 gst_base_parse_set_passthrough (parse, TRUE);
3019 /* we did parse codec-data and might supplement src caps */
3020 gst_h265_parse_update_src_caps (h265parse, caps);
3022 } else if (format == GST_H265_PARSE_FORMAT_HVC1
3023 || format == GST_H265_PARSE_FORMAT_HEV1) {
3024 /* if input != output, and input is hevc, must split before anything else */
3025 /* arrange to insert codec-data in-stream if needed.
3026 * src caps are only arranged for later on */
3027 h265parse->push_codec = TRUE;
3028 h265parse->have_vps = FALSE;
3029 h265parse->have_sps = FALSE;
3030 h265parse->have_pps = FALSE;
3031 if (h265parse->align == GST_H265_PARSE_ALIGN_NAL)
3032 h265parse->split_packetized = TRUE;
3033 h265parse->packetized = TRUE;
3036 h265parse->in_align = align;
3043 GST_DEBUG_OBJECT (h265parse, "hvcC size %" G_GSIZE_FORMAT " < 23", size);
3048 GST_DEBUG_OBJECT (h265parse, "wrong hvcC version");
3053 GST_DEBUG_OBJECT (h265parse, "wrong codec-data type");
3058 GST_WARNING_OBJECT (h265parse, "refused caps %" GST_PTR_FORMAT, caps);
3064 remove_fields (GstCaps * caps, gboolean all)
3068 n = gst_caps_get_size (caps);
3069 for (i = 0; i < n; i++) {
3070 GstStructure *s = gst_caps_get_structure (caps, i);
3073 gst_structure_remove_field (s, "alignment");
3074 gst_structure_remove_field (s, "stream-format");
3076 gst_structure_remove_field (s, "parsed");
3081 gst_h265_parse_get_caps (GstBaseParse * parse, GstCaps * filter)
3083 GstCaps *peercaps, *templ;
3084 GstCaps *res, *tmp, *pcopy;
3086 templ = gst_pad_get_pad_template_caps (GST_BASE_PARSE_SINK_PAD (parse));
3088 GstCaps *fcopy = gst_caps_copy (filter);
3089 /* Remove the fields we convert */
3090 remove_fields (fcopy, TRUE);
3091 peercaps = gst_pad_peer_query_caps (GST_BASE_PARSE_SRC_PAD (parse), fcopy);
3092 gst_caps_unref (fcopy);
3094 peercaps = gst_pad_peer_query_caps (GST_BASE_PARSE_SRC_PAD (parse), NULL);
3096 pcopy = gst_caps_copy (peercaps);
3097 remove_fields (pcopy, TRUE);
3099 res = gst_caps_intersect_full (pcopy, templ, GST_CAPS_INTERSECT_FIRST);
3100 gst_caps_unref (pcopy);
3101 gst_caps_unref (templ);
3104 GstCaps *tmp = gst_caps_intersect_full (res, filter,
3105 GST_CAPS_INTERSECT_FIRST);
3106 gst_caps_unref (res);
3110 /* Try if we can put the downstream caps first */
3111 pcopy = gst_caps_copy (peercaps);
3112 remove_fields (pcopy, FALSE);
3113 tmp = gst_caps_intersect_full (pcopy, res, GST_CAPS_INTERSECT_FIRST);
3114 gst_caps_unref (pcopy);
3115 if (!gst_caps_is_empty (tmp))
3116 res = gst_caps_merge (tmp, res);
3118 gst_caps_unref (tmp);
3120 gst_caps_unref (peercaps);
3125 gst_h265_parse_event (GstBaseParse * parse, GstEvent * event)
3128 GstH265Parse *h265parse = GST_H265_PARSE (parse);
3130 switch (GST_EVENT_TYPE (event)) {
3131 case GST_EVENT_CUSTOM_DOWNSTREAM:
3133 GstClockTime timestamp, stream_time, running_time;
3134 gboolean all_headers;
3137 if (gst_video_event_is_force_key_unit (event)) {
3138 gst_video_event_parse_downstream_force_key_unit (event,
3139 ×tamp, &stream_time, &running_time, &all_headers, &count);
3141 GST_INFO_OBJECT (h265parse, "received downstream force key unit event, "
3142 "seqnum %d running_time %" GST_TIME_FORMAT
3143 " all_headers %d count %d", gst_event_get_seqnum (event),
3144 GST_TIME_ARGS (running_time), all_headers, count);
3145 if (h265parse->force_key_unit_event) {
3146 GST_INFO_OBJECT (h265parse, "ignoring force key unit event "
3147 "as one is already queued");
3149 h265parse->pending_key_unit_ts = running_time;
3150 gst_event_replace (&h265parse->force_key_unit_event, event);
3152 gst_event_unref (event);
3155 res = GST_BASE_PARSE_CLASS (parent_class)->sink_event (parse, event);
3160 case GST_EVENT_FLUSH_STOP:
3161 h265parse->push_codec = TRUE;
3162 res = GST_BASE_PARSE_CLASS (parent_class)->sink_event (parse, event);
3164 case GST_EVENT_SEGMENT:
3166 const GstSegment *segment = NULL;
3168 gst_event_parse_segment (event, &segment);
3170 h265parse->last_report = GST_CLOCK_TIME_NONE;
3172 if (segment->flags & GST_SEEK_FLAG_TRICKMODE_FORWARD_PREDICTED) {
3173 GST_DEBUG_OBJECT (h265parse, "Will discard bidirectional frames");
3174 h265parse->discard_bidirectional = TRUE;
3177 res = GST_BASE_PARSE_CLASS (parent_class)->sink_event (parse, event);
3181 res = GST_BASE_PARSE_CLASS (parent_class)->sink_event (parse, event);
3188 gst_h265_parse_src_event (GstBaseParse * parse, GstEvent * event)
3191 GstH265Parse *h265parse = GST_H265_PARSE (parse);
3193 switch (GST_EVENT_TYPE (event)) {
3194 case GST_EVENT_CUSTOM_UPSTREAM:
3196 GstClockTime running_time;
3197 gboolean all_headers;
3200 if (gst_video_event_is_force_key_unit (event)) {
3201 gst_video_event_parse_upstream_force_key_unit (event,
3202 &running_time, &all_headers, &count);
3204 GST_INFO_OBJECT (h265parse, "received upstream force-key-unit event, "
3205 "seqnum %d running_time %" GST_TIME_FORMAT
3206 " all_headers %d count %d", gst_event_get_seqnum (event),
3207 GST_TIME_ARGS (running_time), all_headers, count);
3210 h265parse->pending_key_unit_ts = running_time;
3211 gst_event_replace (&h265parse->force_key_unit_event, event);
3214 res = GST_BASE_PARSE_CLASS (parent_class)->src_event (parse, event);
3218 res = GST_BASE_PARSE_CLASS (parent_class)->src_event (parse, event);
3226 gst_h265_parse_set_property (GObject * object, guint prop_id,
3227 const GValue * value, GParamSpec * pspec)
3229 GstH265Parse *parse;
3230 parse = GST_H265_PARSE (object);
3233 case PROP_CONFIG_INTERVAL:
3234 parse->interval = g_value_get_int (value);
3237 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
3243 gst_h265_parse_get_property (GObject * object, guint prop_id, GValue * value,
3246 GstH265Parse *parse;
3247 parse = GST_H265_PARSE (object);
3250 case PROP_CONFIG_INTERVAL:
3251 g_value_set_int (value, parse->interval);
3254 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);