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_PAD_SET_ACCEPT_INTERSECT (GST_BASE_PARSE_SINK_PAD (h265parse));
168 GST_PAD_SET_ACCEPT_TEMPLATE (GST_BASE_PARSE_SINK_PAD (h265parse));
173 gst_h265_parse_finalize (GObject * object)
175 GstH265Parse *h265parse = GST_H265_PARSE (object);
177 g_object_unref (h265parse->frame_out);
179 G_OBJECT_CLASS (parent_class)->finalize (object);
183 gst_h265_parse_reset_frame (GstH265Parse * h265parse)
185 GST_DEBUG_OBJECT (h265parse, "reset frame");
187 /* done parsing; reset state */
188 h265parse->current_off = -1;
190 h265parse->picture_start = FALSE;
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;
233 gst_buffer_replace (&h265parse->codec_data, NULL);
234 gst_buffer_replace (&h265parse->codec_data_in, NULL);
236 gst_h265_parse_reset_frame (h265parse);
238 for (i = 0; i < GST_H265_MAX_VPS_COUNT; i++)
239 gst_buffer_replace (&h265parse->vps_nals[i], NULL);
240 for (i = 0; i < GST_H265_MAX_SPS_COUNT; i++)
241 gst_buffer_replace (&h265parse->sps_nals[i], NULL);
242 for (i = 0; i < GST_H265_MAX_PPS_COUNT; i++)
243 gst_buffer_replace (&h265parse->pps_nals[i], NULL);
245 gst_video_mastering_display_info_init (&h265parse->mastering_display_info);
246 h265parse->mastering_display_info_state = GST_H265_PARSE_SEI_EXPIRED;
248 gst_video_content_light_level_init (&h265parse->content_light_level);
249 h265parse->content_light_level_state = GST_H265_PARSE_SEI_EXPIRED;
253 gst_h265_parse_reset (GstH265Parse * h265parse)
255 h265parse->last_report = GST_CLOCK_TIME_NONE;
257 h265parse->sent_codec_tag = FALSE;
259 h265parse->pending_key_unit_ts = GST_CLOCK_TIME_NONE;
260 gst_event_replace (&h265parse->force_key_unit_event, NULL);
262 h265parse->discont = FALSE;
263 h265parse->discard_bidirectional = 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 immediatly 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 const guint chroma_den = 50000;
588 const guint luma_den = 10000;
589 GstVideoMasteringDisplayInfo minfo;
592 sei.payload.mastering_display_colour_volume.display_primaries_x[0];
594 sei.payload.mastering_display_colour_volume.display_primaries_y[0];
596 sei.payload.mastering_display_colour_volume.display_primaries_x[1];
598 sei.payload.mastering_display_colour_volume.display_primaries_y[1];
600 sei.payload.mastering_display_colour_volume.display_primaries_x[2];
602 sei.payload.mastering_display_colour_volume.display_primaries_y[2];
603 minfo.Wx_n = sei.payload.mastering_display_colour_volume.white_point_x;
604 minfo.Wy_n = sei.payload.mastering_display_colour_volume.white_point_y;
606 sei.payload.mastering_display_colour_volume.
607 max_display_mastering_luminance;
609 sei.payload.mastering_display_colour_volume.
610 min_display_mastering_luminance;
612 minfo.Gx_d = minfo.Gy_d = minfo.Bx_d = minfo.By_d =
613 minfo.Rx_d = minfo.Ry_d = minfo.Wx_d = minfo.Wy_d = chroma_den;
615 minfo.max_luma_d = minfo.min_luma_d = luma_den;
617 GST_LOG_OBJECT (h265parse, "mastering display info found");
618 GST_LOG_OBJECT (h265parse, "\tRed (%u/%u, %u/%u)", minfo.Rx_n,
619 minfo.Rx_d, minfo.Ry_n, minfo.Ry_d);
620 GST_LOG_OBJECT (h265parse, "\tGreen(%u/%u, %u/%u)", minfo.Gx_n,
621 minfo.Gx_d, minfo.Gy_n, minfo.Gy_d);
622 GST_LOG_OBJECT (h265parse, "\tBlue (%u/%u, %u/%u)", minfo.Bx_n,
623 minfo.Bx_d, minfo.By_n, minfo.By_d);
624 GST_LOG_OBJECT (h265parse, "\tWhite(%u/%u, %u/%u)", minfo.Wx_n,
625 minfo.Wx_d, minfo.Wy_n, minfo.Wy_d);
626 GST_LOG_OBJECT (h265parse,
627 "\tmax_luminance:(%u/%u), min_luminance:(%u/%u)",
628 minfo.max_luma_n, minfo.max_luma_d, minfo.min_luma_n,
631 if (h265parse->mastering_display_info_state ==
632 GST_H265_PARSE_SEI_EXPIRED) {
633 h265parse->update_caps = TRUE;
634 } else if (!gst_video_mastering_display_info_is_equal
635 (&h265parse->mastering_display_info, &minfo)) {
636 h265parse->update_caps = TRUE;
639 h265parse->mastering_display_info_state = GST_H265_PARSE_SEI_PARSED;
640 h265parse->mastering_display_info = minfo;
644 case GST_H265_SEI_CONTENT_LIGHT_LEVEL:
646 GstVideoContentLightLevel cll;
648 cll.maxCLL_n = sei.payload.content_light_level.max_content_light_level;
650 sei.payload.content_light_level.max_pic_average_light_level;
652 cll.maxCLL_d = cll.maxFALL_d = 1;
654 GST_LOG_OBJECT (h265parse, "content light level found");
655 GST_LOG_OBJECT (h265parse,
656 "\tmaxCLL:(%u/%u), maxFALL:(%u/%u)", cll.maxCLL_n, cll.maxCLL_d,
657 cll.maxFALL_n, cll.maxFALL_d);
659 if (h265parse->content_light_level_state == GST_H265_PARSE_SEI_EXPIRED) {
660 h265parse->update_caps = TRUE;
661 } else if (gst_util_fraction_compare (cll.maxCLL_n, cll.maxCLL_d,
662 h265parse->content_light_level.maxCLL_n,
663 h265parse->content_light_level.maxCLL_d)
664 || gst_util_fraction_compare (cll.maxFALL_n, cll.maxFALL_d,
665 h265parse->content_light_level.maxFALL_n,
666 h265parse->content_light_level.maxFALL_d)) {
667 h265parse->update_caps = TRUE;
670 h265parse->content_light_level_state = GST_H265_PARSE_SEI_PARSED;
671 h265parse->content_light_level = cll;
679 g_array_free (messages, TRUE);
683 gst_h265_parse_process_sei_user_data (GstH265Parse * h265parse,
684 GstH265RegisteredUserData * rud)
686 guint16 provider_code;
688 GstVideoParseUtilsField field = GST_VIDEO_PARSE_UTILS_FIELD_1;
690 /* only US country code is currently supported */
691 switch (rud->country_code) {
692 case ITU_T_T35_COUNTRY_CODE_US:
695 GST_LOG_OBJECT (h265parse, "Unsupported country code %d",
700 if (rud->data == NULL || rud->size < 2)
703 gst_byte_reader_init (&br, rud->data, rud->size);
705 provider_code = gst_byte_reader_get_uint16_be_unchecked (&br);
707 if (h265parse->sei_pic_struct ==
708 (guint8) GST_H265_SEI_PIC_STRUCT_BOTTOM_FIELD)
709 field = GST_VIDEO_PARSE_UTILS_FIELD_1;
710 gst_video_parse_user_data ((GstElement *) h265parse, &h265parse->user_data,
711 &br, field, provider_code);
715 /* caller guarantees 2 bytes of nal payload */
717 gst_h265_parse_process_nal (GstH265Parse * h265parse, GstH265NalUnit * nalu)
719 GstH265PPS pps = { 0, };
720 GstH265SPS sps = { 0, };
721 GstH265VPS vps = { 0, };
723 GstH265Parser *nalparser = h265parse->nalparser;
724 GstH265ParserResult pres = GST_H265_PARSER_ERROR;
726 /* nothing to do for broken input */
727 if (G_UNLIKELY (nalu->size < 2)) {
728 GST_DEBUG_OBJECT (h265parse, "not processing nal size %u", nalu->size);
732 /* we have a peek as well */
733 nal_type = nalu->type;
735 GST_DEBUG_OBJECT (h265parse, "processing nal of type %u %s, size %u",
736 nal_type, _nal_name (nal_type), nalu->size);
738 case GST_H265_NAL_VPS:
739 /* It is not mandatory to have VPS in the stream. But it might
740 * be needed for other extensions like svc */
741 pres = gst_h265_parser_parse_vps (nalparser, nalu, &vps);
742 if (pres != GST_H265_PARSER_OK) {
743 GST_WARNING_OBJECT (h265parse, "failed to parse VPS");
747 GST_DEBUG_OBJECT (h265parse, "triggering src caps check");
748 h265parse->update_caps = TRUE;
749 h265parse->have_vps = TRUE;
750 h265parse->have_vps_in_frame = TRUE;
751 if (h265parse->push_codec && h265parse->have_pps) {
752 /* VPS/SPS/PPS found in stream before the first pre_push_frame, no need
753 * to forcibly push at start */
754 GST_INFO_OBJECT (h265parse, "have VPS/SPS/PPS in stream");
755 h265parse->push_codec = FALSE;
756 h265parse->have_vps = FALSE;
757 h265parse->have_sps = FALSE;
758 h265parse->have_pps = FALSE;
761 gst_h265_parser_store_nal (h265parse, vps.id, nal_type, nalu);
762 h265parse->header = TRUE;
764 case GST_H265_NAL_SPS:
765 /* reset state, everything else is obsolete */
766 h265parse->state = 0;
768 pres = gst_h265_parser_parse_sps (nalparser, nalu, &sps, TRUE);
771 /* arranged for a fallback sps.id, so use that one and only warn */
772 if (pres != GST_H265_PARSER_OK) {
773 /* try to not parse VUI */
774 pres = gst_h265_parser_parse_sps (nalparser, nalu, &sps, FALSE);
775 if (pres != GST_H265_PARSER_OK) {
776 GST_WARNING_OBJECT (h265parse, "failed to parse SPS:");
777 h265parse->state |= GST_H265_PARSE_STATE_GOT_SPS;
778 h265parse->header = TRUE;
781 GST_WARNING_OBJECT (h265parse,
782 "failed to parse VUI of SPS, ignore VUI");
785 GST_DEBUG_OBJECT (h265parse, "triggering src caps check");
786 h265parse->update_caps = TRUE;
787 h265parse->have_sps = TRUE;
788 h265parse->have_sps_in_frame = TRUE;
789 if (h265parse->push_codec && h265parse->have_pps) {
790 /* SPS and PPS found in stream before the first pre_push_frame, no need
791 * to forcibly push at start */
792 GST_INFO_OBJECT (h265parse, "have SPS/PPS in stream");
793 h265parse->push_codec = FALSE;
794 h265parse->have_sps = FALSE;
795 h265parse->have_pps = FALSE;
798 gst_h265_parser_store_nal (h265parse, sps.id, nal_type, nalu);
799 h265parse->header = TRUE;
800 h265parse->state |= GST_H265_PARSE_STATE_GOT_SPS;
802 case GST_H265_NAL_PPS:
803 /* expected state: got-sps */
804 h265parse->state &= GST_H265_PARSE_STATE_GOT_SPS;
805 if (!GST_H265_PARSE_STATE_VALID (h265parse, GST_H265_PARSE_STATE_GOT_SPS))
808 pres = gst_h265_parser_parse_pps (nalparser, nalu, &pps);
811 /* arranged for a fallback pps.id, so use that one and only warn */
812 if (pres != GST_H265_PARSER_OK) {
813 GST_WARNING_OBJECT (h265parse, "failed to parse PPS:");
814 if (pres != GST_H265_PARSER_BROKEN_LINK)
818 /* parameters might have changed, force caps check */
819 if (!h265parse->have_pps) {
820 GST_DEBUG_OBJECT (h265parse, "triggering src caps check");
821 h265parse->update_caps = TRUE;
823 h265parse->have_pps = TRUE;
824 h265parse->have_pps_in_frame = TRUE;
825 if (h265parse->push_codec && h265parse->have_sps) {
826 /* SPS and PPS found in stream before the first pre_push_frame, no need
827 * to forcibly push at start */
828 GST_INFO_OBJECT (h265parse, "have SPS/PPS in stream");
829 h265parse->push_codec = FALSE;
830 h265parse->have_sps = FALSE;
831 h265parse->have_pps = FALSE;
834 gst_h265_parser_store_nal (h265parse, pps.id, nal_type, nalu);
835 h265parse->header = TRUE;
836 h265parse->state |= GST_H265_PARSE_STATE_GOT_PPS;
838 case GST_H265_NAL_PREFIX_SEI:
839 case GST_H265_NAL_SUFFIX_SEI:
840 /* expected state: got-sps */
841 if (!GST_H265_PARSE_STATE_VALID (h265parse, GST_H265_PARSE_STATE_GOT_SPS))
844 h265parse->header = TRUE;
846 gst_h265_parse_process_sei (h265parse, nalu);
849 if (h265parse->sei_pos == -1) {
850 if (h265parse->transform)
851 h265parse->sei_pos = gst_adapter_available (h265parse->frame_out);
853 h265parse->sei_pos = nalu->sc_offset;
854 GST_DEBUG_OBJECT (h265parse, "marking SEI in frame at offset %d",
859 case GST_H265_NAL_SLICE_TRAIL_N:
860 case GST_H265_NAL_SLICE_TRAIL_R:
861 case GST_H265_NAL_SLICE_TSA_N:
862 case GST_H265_NAL_SLICE_TSA_R:
863 case GST_H265_NAL_SLICE_STSA_N:
864 case GST_H265_NAL_SLICE_STSA_R:
865 case GST_H265_NAL_SLICE_RADL_N:
866 case GST_H265_NAL_SLICE_RADL_R:
867 case GST_H265_NAL_SLICE_RASL_N:
868 case GST_H265_NAL_SLICE_RASL_R:
869 case GST_H265_NAL_SLICE_BLA_W_LP:
870 case GST_H265_NAL_SLICE_BLA_W_RADL:
871 case GST_H265_NAL_SLICE_BLA_N_LP:
872 case GST_H265_NAL_SLICE_IDR_W_RADL:
873 case GST_H265_NAL_SLICE_IDR_N_LP:
874 case GST_H265_NAL_SLICE_CRA_NUT:
876 GstH265SliceHdr slice;
878 gboolean no_rasl_output_flag = FALSE;
880 /* expected state: got-sps|got-pps (valid picture headers) */
881 h265parse->state &= GST_H265_PARSE_STATE_VALID_PICTURE_HEADERS;
882 if (!GST_H265_PARSE_STATE_VALID (h265parse,
883 GST_H265_PARSE_STATE_VALID_PICTURE_HEADERS))
886 pres = gst_h265_parser_parse_slice_hdr (nalparser, nalu, &slice);
888 if (pres == GST_H265_PARSER_OK) {
889 if (GST_H265_IS_I_SLICE (&slice))
890 h265parse->keyframe = TRUE;
891 else if (GST_H265_IS_P_SLICE (&slice))
892 h265parse->predicted = TRUE;
893 else if (GST_H265_IS_B_SLICE (&slice))
894 h265parse->bidirectional = TRUE;
896 h265parse->state |= GST_H265_PARSE_STATE_GOT_SLICE;
898 if (slice.first_slice_segment_in_pic_flag == 1)
899 GST_DEBUG_OBJECT (h265parse,
900 "frame start, first_slice_segment_in_pic_flag = 1");
902 GST_DEBUG_OBJECT (h265parse,
903 "parse result %d, first slice_segment: %u, slice type: %u",
904 pres, slice.first_slice_segment_in_pic_flag, slice.type);
906 gst_h265_slice_hdr_free (&slice);
908 /* FIXME: NoRaslOutputFlag can be equal to 1 for CRA if
909 * 1) the first AU in bitstream is CRA
910 * 2) or the first AU following EOS nal is CRA
911 * 3) or it has HandleCraAsBlaFlag equal to 1 */
912 if (nal_type == GST_H265_NAL_SLICE_IDR_W_RADL ||
913 nal_type == GST_H265_NAL_SLICE_IDR_N_LP) {
914 /* NoRaslOutputFlag is equal to 1 for each IDR */
915 no_rasl_output_flag = TRUE;
916 } else if (nal_type == GST_H265_NAL_SLICE_BLA_W_LP ||
917 nal_type == GST_H265_NAL_SLICE_BLA_W_RADL ||
918 nal_type == GST_H265_NAL_SLICE_BLA_N_LP) {
919 /* NoRaslOutputFlag is equal to 1 for each BLA */
920 no_rasl_output_flag = TRUE;
923 is_irap = ((nal_type >= GST_H265_NAL_SLICE_BLA_W_LP)
924 && (nal_type <= GST_H265_NAL_SLICE_CRA_NUT)) ? TRUE : FALSE;
926 if (h265parse->mastering_display_info_state != GST_H265_PARSE_SEI_EXPIRED
927 && no_rasl_output_flag && is_irap)
928 h265parse->mastering_display_info_state--;
930 if (h265parse->content_light_level_state != GST_H265_PARSE_SEI_EXPIRED &&
931 no_rasl_output_flag && is_irap)
932 h265parse->content_light_level_state--;
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)
996 GstH265ParserResult parse_res;
997 GstH265NalUnitType nal_type = nalu->type;
998 GstH265NalUnit nnalu;
1000 GST_DEBUG_OBJECT (h265parse, "parsing collected nal");
1001 parse_res = gst_h265_parser_identify_nalu_unchecked (h265parse->nalparser,
1002 data, nalu->offset + nalu->size, size, &nnalu);
1004 if (parse_res != GST_H265_PARSER_OK)
1007 /* determine if AU complete */
1008 GST_LOG_OBJECT (h265parse, "nal type: %d %s", nal_type, _nal_name (nal_type));
1009 /* coded slice NAL starts a picture,
1010 * i.e. other types become aggregated in front of it */
1011 h265parse->picture_start |= ((nal_type >= GST_H265_NAL_SLICE_TRAIL_N
1012 && nal_type <= GST_H265_NAL_SLICE_RASL_R)
1013 || (nal_type >= GST_H265_NAL_SLICE_BLA_W_LP
1014 && nal_type <= RESERVED_IRAP_NAL_TYPE_MAX));
1016 /* consider a coded slices (IRAP or not) to start a picture,
1017 * (so ending the previous one) if first_slice_segment_in_pic_flag == 1*/
1018 nal_type = nnalu.type;
1019 complete = h265parse->picture_start && ((nal_type >= GST_H265_NAL_VPS
1020 && nal_type <= GST_H265_NAL_AUD)
1021 || nal_type == GST_H265_NAL_PREFIX_SEI || (nal_type >= 41
1022 && nal_type <= 44) || (nal_type >= 48 && nal_type <= 55));
1024 GST_LOG_OBJECT (h265parse, "next nal type: %d %s", nal_type,
1025 _nal_name (nal_type));
1026 if (nnalu.size > nnalu.header_bytes) {
1027 /* Any VCL Nal unit with first_slice_segment_in_pic_flag == 1 considered start of frame */
1028 complete |= h265parse->picture_start
1029 && (((nal_type >= GST_H265_NAL_SLICE_TRAIL_N
1030 && nal_type <= GST_H265_NAL_SLICE_RASL_R)
1031 || (nal_type >= GST_H265_NAL_SLICE_BLA_W_LP
1032 && nal_type <= RESERVED_IRAP_NAL_TYPE_MAX))
1033 && (nnalu.data[nnalu.offset + 2] & 0x80));
1036 GST_LOG_OBJECT (h265parse, "au complete: %d", complete);
1040 static GstFlowReturn
1041 gst_h265_parse_handle_frame_packetized (GstBaseParse * parse,
1042 GstBaseParseFrame * frame)
1044 GstH265Parse *h265parse = GST_H265_PARSE (parse);
1045 GstBuffer *buffer = frame->buffer;
1046 GstFlowReturn ret = GST_FLOW_OK;
1047 GstH265ParserResult parse_res;
1048 GstH265NalUnit nalu;
1049 const guint nl = h265parse->nal_length_size;
1053 if (nl < 1 || nl > 4) {
1054 GST_DEBUG_OBJECT (h265parse, "insufficient data to split input");
1055 return GST_FLOW_NOT_NEGOTIATED;
1058 /* need to save buffer from invalidation upon _finish_frame */
1059 if (h265parse->split_packetized)
1060 buffer = gst_buffer_copy (frame->buffer);
1062 gst_buffer_map (buffer, &map, GST_MAP_READ);
1066 GST_LOG_OBJECT (h265parse,
1067 "processing packet buffer of size %" G_GSIZE_FORMAT, map.size);
1069 parse_res = gst_h265_parser_identify_nalu_hevc (h265parse->nalparser,
1070 map.data, 0, map.size, nl, &nalu);
1072 while (parse_res == GST_H265_PARSER_OK) {
1073 GST_DEBUG_OBJECT (h265parse, "HEVC nal offset %d", nalu.offset + nalu.size);
1075 /* either way, have a look at it */
1076 gst_h265_parse_process_nal (h265parse, &nalu);
1078 /* dispatch per NALU if needed */
1079 if (h265parse->split_packetized) {
1080 GstBaseParseFrame tmp_frame;
1082 gst_base_parse_frame_init (&tmp_frame);
1083 tmp_frame.flags |= frame->flags;
1084 tmp_frame.offset = frame->offset;
1085 tmp_frame.overhead = frame->overhead;
1086 tmp_frame.buffer = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_ALL,
1087 nalu.offset, nalu.size);
1089 /* note we don't need to come up with a sub-buffer, since
1090 * subsequent code only considers input buffer's metadata.
1091 * Real data is either taken from input by baseclass or
1092 * a replacement output buffer is provided anyway. */
1093 gst_h265_parse_parse_frame (parse, &tmp_frame);
1094 ret = gst_base_parse_finish_frame (parse, &tmp_frame, nl + nalu.size);
1095 left -= nl + nalu.size;
1098 parse_res = gst_h265_parser_identify_nalu_hevc (h265parse->nalparser,
1099 map.data, nalu.offset + nalu.size, map.size, nl, &nalu);
1102 gst_buffer_unmap (buffer, &map);
1104 if (!h265parse->split_packetized) {
1105 gst_h265_parse_parse_frame (parse, frame);
1106 ret = gst_base_parse_finish_frame (parse, frame, map.size);
1108 gst_buffer_unref (buffer);
1109 if (G_UNLIKELY (left)) {
1110 /* should not be happening for nice HEVC */
1111 GST_WARNING_OBJECT (parse, "skipping leftover HEVC data %d", left);
1112 frame->flags |= GST_BASE_PARSE_FRAME_FLAG_DROP;
1113 ret = gst_base_parse_finish_frame (parse, frame, map.size);
1117 if (parse_res == GST_H265_PARSER_NO_NAL_END ||
1118 parse_res == GST_H265_PARSER_BROKEN_DATA) {
1120 if (h265parse->split_packetized) {
1121 GST_ELEMENT_ERROR (h265parse, STREAM, FAILED, (NULL),
1122 ("invalid HEVC input data"));
1124 return GST_FLOW_ERROR;
1126 /* do not meddle to much in this case */
1127 GST_DEBUG_OBJECT (h265parse, "parsing packet failed");
1134 static GstFlowReturn
1135 gst_h265_parse_handle_frame (GstBaseParse * parse,
1136 GstBaseParseFrame * frame, gint * skipsize)
1138 GstH265Parse *h265parse = GST_H265_PARSE (parse);
1139 GstBuffer *buffer = frame->buffer;
1143 gint current_off = 0;
1144 gboolean drain, nonext;
1145 GstH265Parser *nalparser = h265parse->nalparser;
1146 GstH265NalUnit nalu;
1147 GstH265ParserResult pres;
1150 if (G_UNLIKELY (GST_BUFFER_FLAG_IS_SET (frame->buffer,
1151 GST_BUFFER_FLAG_DISCONT))) {
1152 h265parse->discont = TRUE;
1155 /* delegate in packetized case, no skipping should be needed */
1156 if (h265parse->packetized)
1157 return gst_h265_parse_handle_frame_packetized (parse, frame);
1159 gst_buffer_map (buffer, &map, GST_MAP_READ);
1163 /* expect at least 3 bytes start_code, and 2 bytes NALU header.
1164 * the length of the NALU payload can be zero.
1165 * (e.g. EOS/EOB placed at the end of an AU.) */
1166 if (G_UNLIKELY (size < 5)) {
1167 gst_buffer_unmap (buffer, &map);
1172 /* need to configure aggregation */
1173 if (G_UNLIKELY (h265parse->format == GST_H265_PARSE_FORMAT_NONE))
1174 gst_h265_parse_negotiate (h265parse, GST_H265_PARSE_FORMAT_BYTE, NULL);
1176 /* avoid stale cached parsing state */
1177 if (frame->flags & GST_BASE_PARSE_FRAME_FLAG_NEW_FRAME) {
1178 GST_LOG_OBJECT (h265parse, "parsing new frame");
1179 gst_h265_parse_reset_frame (h265parse);
1181 GST_LOG_OBJECT (h265parse, "resuming frame parsing");
1184 drain = GST_BASE_PARSE_DRAINING (parse);
1187 current_off = h265parse->current_off;
1188 if (current_off < 0)
1190 g_assert (current_off < size);
1191 GST_DEBUG_OBJECT (h265parse, "last parse position %d", current_off);
1193 /* check for initial skip */
1194 if (h265parse->current_off == -1) {
1196 gst_h265_parser_identify_nalu_unchecked (nalparser, data, current_off,
1199 case GST_H265_PARSER_OK:
1200 if (nalu.sc_offset > 0) {
1201 *skipsize = nalu.sc_offset;
1205 case GST_H265_PARSER_NO_NAL:
1206 *skipsize = size - 3;
1209 /* should not really occur either */
1210 GST_ELEMENT_ERROR (h265parse, STREAM, FORMAT,
1211 ("Error parsing H.265 stream"), ("Invalid H.265 stream"));
1212 goto invalid_stream;
1218 gst_h265_parser_identify_nalu (nalparser, data, current_off, size,
1222 case GST_H265_PARSER_OK:
1223 GST_DEBUG_OBJECT (h265parse, "complete nal (offset, size): (%u, %u) ",
1224 nalu.offset, nalu.size);
1226 case GST_H265_PARSER_NO_NAL_END:
1227 GST_DEBUG_OBJECT (h265parse, "not a complete nal found at offset %u",
1229 /* if draining, accept it as complete nal */
1232 nalu.size = size - nalu.offset;
1233 GST_DEBUG_OBJECT (h265parse, "draining, accepting with size %u",
1235 /* if it's not too short at least */
1240 /* otherwise need more */
1242 case GST_H265_PARSER_BROKEN_LINK:
1243 GST_ELEMENT_ERROR (h265parse, STREAM, FORMAT,
1244 ("Error parsing H.265 stream"),
1245 ("The link to structure needed for the parsing couldn't be found"));
1246 goto invalid_stream;
1247 case GST_H265_PARSER_ERROR:
1248 /* should not really occur either */
1249 GST_ELEMENT_ERROR (h265parse, STREAM, FORMAT,
1250 ("Error parsing H.265 stream"), ("Invalid H.265 stream"));
1251 goto invalid_stream;
1252 case GST_H265_PARSER_NO_NAL:
1253 GST_ELEMENT_ERROR (h265parse, STREAM, FORMAT,
1254 ("Error parsing H.265 stream"), ("No H.265 NAL unit found"));
1255 goto invalid_stream;
1256 case GST_H265_PARSER_BROKEN_DATA:
1257 GST_WARNING_OBJECT (h265parse, "input stream is corrupt; "
1258 "it contains a NAL unit of length %u", nalu.size);
1260 /* broken nal at start -> arrange to skip it,
1261 * otherwise have it terminate current au
1262 * (and so it will be skipped on next frame round) */
1263 if (current_off == 0) {
1264 GST_DEBUG_OBJECT (h265parse, "skipping broken nal");
1265 *skipsize = nalu.offset;
1268 GST_DEBUG_OBJECT (h265parse, "terminating au");
1270 nalu.offset = nalu.sc_offset;
1274 g_assert_not_reached ();
1278 GST_DEBUG_OBJECT (h265parse, "%p complete nal found. Off: %u, Size: %u",
1279 data, nalu.offset, nalu.size);
1281 /* simulate no next nal if none needed */
1282 nonext = nonext || (h265parse->align == GST_H265_PARSE_ALIGN_NAL);
1285 /* expect at least 3 bytes start_code, and 2 bytes NALU header.
1286 * the length of the NALU payload can be zero.
1287 * (e.g. EOS/EOB placed at the end of an AU.) */
1288 if (nalu.offset + nalu.size + 3 + 2 > size) {
1289 GST_DEBUG_OBJECT (h265parse, "not enough data for next NALU");
1291 GST_DEBUG_OBJECT (h265parse, "but draining anyway");
1299 if (!gst_h265_parse_process_nal (h265parse, &nalu)) {
1300 GST_WARNING_OBJECT (h265parse,
1301 "broken/invalid nal Type: %d %s, Size: %u will be dropped",
1302 nalu.type, _nal_name (nalu.type), nalu.size);
1303 *skipsize = nalu.size;
1310 /* if no next nal, we know it's complete here */
1311 if (gst_h265_parse_collect_nal (h265parse, data, size, &nalu))
1314 GST_DEBUG_OBJECT (h265parse, "Looking for more");
1315 current_off = nalu.offset + nalu.size;
1319 framesize = nalu.offset + nalu.size;
1321 gst_buffer_unmap (buffer, &map);
1323 gst_h265_parse_parse_frame (parse, frame);
1325 return gst_base_parse_finish_frame (parse, frame, framesize);
1330 /* Restart parsing from here next time */
1331 if (current_off > 0)
1332 h265parse->current_off = current_off;
1336 gst_buffer_unmap (buffer, &map);
1340 GST_DEBUG_OBJECT (h265parse, "skipping %d", *skipsize);
1341 /* If we are collecting access units, we need to preserve the initial
1342 * config headers (SPS, PPS et al.) and only reset the frame if another
1343 * slice NAL was received. This means that broken pictures are discarded */
1344 if (h265parse->align != GST_H265_PARSE_ALIGN_AU ||
1345 !(h265parse->state & GST_H265_PARSE_STATE_VALID_PICTURE_HEADERS) ||
1346 (h265parse->state & GST_H265_PARSE_STATE_GOT_SLICE))
1347 gst_h265_parse_reset_frame (h265parse);
1351 gst_buffer_unmap (buffer, &map);
1352 return GST_FLOW_ERROR;
1355 /* byte together hevc codec data based on collected pps and sps so far */
1357 gst_h265_parse_make_codec_data (GstH265Parse * h265parse)
1359 GstBuffer *buf, *nal;
1361 guint vps_size = 0, sps_size = 0, pps_size = 0;
1362 guint num_vps = 0, num_sps = 0, num_pps = 0;
1363 gboolean found = FALSE;
1367 guint8 num_arrays = 0;
1368 GstH265SPS *sps = NULL;
1369 guint16 min_spatial_segmentation_idc = 0;
1370 GstH265ProfileTierLevel *pft;
1372 /* only nal payload in stored nals */
1373 /* Fixme: Current implementation is not embedding SEI in codec_data */
1374 for (i = 0; i < GST_H265_MAX_VPS_COUNT; i++) {
1375 if ((nal = h265parse->vps_nals[i])) {
1377 /* size bytes also count */
1378 vps_size += gst_buffer_get_size (nal) + 2;
1384 for (i = 0; i < GST_H265_MAX_SPS_COUNT; i++) {
1385 if ((nal = h265parse->sps_nals[i])) {
1387 /* size bytes also count */
1388 sps_size += gst_buffer_get_size (nal) + 2;
1395 for (i = 0; i < GST_H265_MAX_PPS_COUNT; i++) {
1396 if ((nal = h265parse->pps_nals[i])) {
1398 /* size bytes also count */
1399 pps_size += gst_buffer_get_size (nal) + 2;
1405 GST_DEBUG_OBJECT (h265parse,
1406 "constructing codec_data: num_vps =%d num_sps=%d, num_pps=%d", num_vps,
1412 sps = h265parse->nalparser->last_sps;
1417 gst_buffer_new_allocate (NULL,
1418 23 + (3 * num_arrays) + vps_size + sps_size + pps_size, NULL);
1419 gst_buffer_map (buf, &map, GST_MAP_WRITE);
1421 memset (data, 0, map.size);
1422 nl = h265parse->nal_length_size;
1424 pft = &sps->profile_tier_level;
1425 if (sps->vui_parameters_present_flag)
1426 min_spatial_segmentation_idc = sps->vui_params.min_spatial_segmentation_idc;
1428 /* HEVCDecoderConfigurationVersion = 1
1429 * profile_space | tier_flat | profile_idc |
1430 * profile_compatibility_flags | constraint_indicator_flags |
1434 (pft->profile_space << 5) | (pft->tier_flag << 5) | pft->profile_idc;
1435 for (i = 2; i < 6; i++) {
1436 for (j = 7; j >= 0; j--) {
1437 data[i] |= (pft->profile_compatibility_flag[k] << j);
1443 (pft->progressive_source_flag << 7) |
1444 (pft->interlaced_source_flag << 6) |
1445 (pft->non_packed_constraint_flag << 5) |
1446 (pft->frame_only_constraint_flag << 4) |
1447 (pft->max_12bit_constraint_flag << 3) |
1448 (pft->max_10bit_constraint_flag << 2) |
1449 (pft->max_8bit_constraint_flag << 1) |
1450 (pft->max_422chroma_constraint_flag);
1453 (pft->max_420chroma_constraint_flag << 7) |
1454 (pft->max_monochrome_constraint_flag << 6) |
1455 (pft->intra_constraint_flag << 5) |
1456 (pft->one_picture_only_constraint_flag << 4) |
1457 (pft->lower_bit_rate_constraint_flag << 3) |
1458 (pft->max_14bit_constraint_flag << 2);
1460 data[12] = pft->level_idc;
1461 /* min_spatial_segmentation_idc */
1462 GST_WRITE_UINT16_BE (data + 13, min_spatial_segmentation_idc);
1464 data[15] = 0xfc; /* keeping parrallelismType as zero (unknown) */
1465 data[16] = 0xfc | sps->chroma_format_idc;
1466 data[17] = 0xf8 | sps->bit_depth_luma_minus8;
1467 data[18] = 0xf8 | sps->bit_depth_chroma_minus8;
1468 data[19] = 0x00; /* keep avgFrameRate as unspecified */
1469 data[20] = 0x00; /* keep avgFrameRate as unspecified */
1470 /* constFrameRate(2 bits): 0, stream may or may not be of constant framerate
1471 * numTemporalLayers (3 bits): number of temporal layers, value from SPS
1472 * TemporalIdNested (1 bit): sps_temporal_id_nesting_flag from SPS
1473 * lengthSizeMinusOne (2 bits): plus 1 indicates the length of the NALUnitLength */
1475 0x00 | ((sps->max_sub_layers_minus1 +
1476 1) << 3) | (sps->temporal_id_nesting_flag << 2) | (nl - 1);
1477 GST_WRITE_UINT8 (data + 22, num_arrays); /* numOfArrays */
1483 /* array_completeness | reserved_zero bit | nal_unit_type */
1484 data[0] = 0x00 | 0x20;
1487 GST_WRITE_UINT16_BE (data, num_vps);
1490 for (i = 0; i < GST_H265_MAX_VPS_COUNT; i++) {
1491 if ((nal = h265parse->vps_nals[i])) {
1492 gsize nal_size = gst_buffer_get_size (nal);
1493 GST_WRITE_UINT16_BE (data, nal_size);
1494 gst_buffer_extract (nal, 0, data + 2, nal_size);
1495 data += 2 + nal_size;
1502 /* array_completeness | reserved_zero bit | nal_unit_type */
1503 data[0] = 0x00 | 0x21;
1506 GST_WRITE_UINT16_BE (data, num_sps);
1509 for (i = 0; i < GST_H265_MAX_SPS_COUNT; i++) {
1510 if ((nal = h265parse->sps_nals[i])) {
1511 gsize nal_size = gst_buffer_get_size (nal);
1512 GST_WRITE_UINT16_BE (data, nal_size);
1513 gst_buffer_extract (nal, 0, data + 2, nal_size);
1514 data += 2 + nal_size;
1521 /* array_completeness | reserved_zero bit | nal_unit_type */
1522 data[0] = 0x00 | 0x22;
1525 GST_WRITE_UINT16_BE (data, num_pps);
1528 for (i = 0; i < GST_H265_MAX_PPS_COUNT; i++) {
1529 if ((nal = h265parse->pps_nals[i])) {
1530 gsize nal_size = gst_buffer_get_size (nal);
1531 GST_WRITE_UINT16_BE (data, nal_size);
1532 gst_buffer_extract (nal, 0, data + 2, nal_size);
1533 data += 2 + nal_size;
1537 gst_buffer_unmap (buf, &map);
1543 gst_h265_parse_get_par (GstH265Parse * h265parse, gint * num, gint * den)
1545 if (h265parse->upstream_par_n != -1 && h265parse->upstream_par_d != -1) {
1546 *num = h265parse->upstream_par_n;
1547 *den = h265parse->upstream_par_d;
1549 *num = h265parse->parsed_par_n;
1550 *den = h265parse->parsed_par_d;
1554 static const gchar *
1555 digit_to_string (guint digit)
1557 static const char itoa[][2] = {
1558 "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"
1561 if (G_LIKELY (digit < 10))
1567 static const gchar *
1568 get_profile_string (GstH265Profile profile)
1571 case GST_H265_PROFILE_MAIN:
1573 case GST_H265_PROFILE_MAIN_10:
1575 case GST_H265_PROFILE_MAIN_STILL_PICTURE:
1576 return "main-still-picture";
1577 case GST_H265_PROFILE_MONOCHROME:
1578 return "monochrome";
1579 case GST_H265_PROFILE_MONOCHROME_10:
1580 return "monochrome-10";
1581 case GST_H265_PROFILE_MONOCHROME_12:
1582 return "monochrome-12";
1583 case GST_H265_PROFILE_MONOCHROME_16:
1584 return "monochrome-16";
1585 case GST_H265_PROFILE_MAIN_12:
1587 case GST_H265_PROFILE_MAIN_422_10:
1588 return "main-422-10";
1589 case GST_H265_PROFILE_MAIN_422_12:
1590 return "main-422-12";
1591 case GST_H265_PROFILE_MAIN_444:
1593 case GST_H265_PROFILE_MAIN_444_10:
1594 return "main-444-10";
1595 case GST_H265_PROFILE_MAIN_444_12:
1596 return "main-444-12";
1597 case GST_H265_PROFILE_MAIN_INTRA:
1598 return "main-intra";
1599 case GST_H265_PROFILE_MAIN_10_INTRA:
1600 return "main-10-intra";
1601 case GST_H265_PROFILE_MAIN_12_INTRA:
1602 return "main-12-intra";
1603 case GST_H265_PROFILE_MAIN_422_10_INTRA:
1604 return "main-422-10-intra";
1605 case GST_H265_PROFILE_MAIN_422_12_INTRA:
1606 return "main-422-12-intra";
1607 case GST_H265_PROFILE_MAIN_444_INTRA:
1608 return "main-444-intra";
1609 case GST_H265_PROFILE_MAIN_444_10_INTRA:
1610 return "main-444-10-intra";
1611 case GST_H265_PROFILE_MAIN_444_12_INTRA:
1612 return "main-444-12-intra";
1613 case GST_H265_PROFILE_MAIN_444_16_INTRA:
1614 return "main-444-16-intra";
1615 case GST_H265_PROFILE_MAIN_444_STILL_PICTURE:
1616 return "main-444-still-picture";
1617 case GST_H265_PROFILE_MAIN_444_16_STILL_PICTURE:
1618 return "main-444-16-still-picture";
1619 case GST_H265_PROFILE_HIGH_THROUGHPUT_444:
1620 return "high-throughput-444";
1621 case GST_H265_PROFILE_HIGH_THROUGHPUT_444_10:
1622 return "high-throughput-444-10";
1623 case GST_H265_PROFILE_HIGH_THROUGHPUT_444_14:
1624 return "high-throughput-444-14";
1625 case GST_H265_PROFILE_HIGH_THROUGHPUT_444_16_INTRA:
1626 return "high-throughput-444-16-intra";
1627 case GST_H265_PROFILE_SCREEN_EXTENDED_MAIN:
1628 return "screen-extended-main";
1629 case GST_H265_PROFILE_SCREEN_EXTENDED_MAIN_10:
1630 return "screen-extended-main-10";
1631 case GST_H265_PROFILE_SCREEN_EXTENDED_MAIN_444:
1632 return "screen-extended-main-444";
1633 case GST_H265_PROFILE_SCREEN_EXTENDED_MAIN_444_10:
1634 return "screen-extended-main-444-10";
1635 case GST_H265_PROFILE_SCREEN_EXTENDED_HIGH_THROUGHPUT_444:
1636 return "screen-extended-high-throughput-444";
1637 case GST_H265_PROFILE_SCREEN_EXTENDED_HIGH_THROUGHPUT_444_10:
1638 return "screen-extended-high-throughput-444-10";
1639 case GST_H265_PROFILE_SCREEN_EXTENDED_HIGH_THROUGHPUT_444_14:
1640 return "screen-extended-high-throughput-444-14";
1641 case GST_H265_PROFILE_MULTIVIEW_MAIN:
1642 return "multiview-main";
1643 case GST_H265_PROFILE_SCALABLE_MAIN:
1644 return "scalable-main";
1645 case GST_H265_PROFILE_SCALABLE_MAIN_10:
1646 return "scalable-main-10";
1647 case GST_H265_PROFILE_SCALABLE_MONOCHROME:
1648 return "scalable-monochrome";
1649 case GST_H265_PROFILE_SCALABLE_MONOCHROME_12:
1650 return "scalable-monochrome-12";
1651 case GST_H265_PROFILE_SCALABLE_MONOCHROME_16:
1652 return "scalable-monochrome-16";
1653 case GST_H265_PROFILE_SCALABLE_MAIN_444:
1654 return "scalable-main-444";
1655 case GST_H265_PROFILE_3D_MAIN:
1664 static const gchar *
1665 get_tier_string (guint8 tier_flag)
1667 const gchar *tier = NULL;
1677 static const gchar *
1678 get_level_string (guint8 level_idc)
1682 else if (level_idc % 30 == 0)
1683 return digit_to_string (level_idc / 30);
1685 switch (level_idc) {
1713 static inline guint64
1714 profile_to_flag (GstH265Profile p)
1716 return (guint64) 1 << (guint64) p;
1720 get_compatible_profile_caps (GstH265SPS * sps, GstH265Profile profile)
1722 GstCaps *caps = NULL;
1724 GValue compat_profiles = G_VALUE_INIT;
1725 guint64 profiles = 0;
1727 g_value_init (&compat_profiles, GST_TYPE_LIST);
1729 /* Relaxing profiles condition based on decoder capability specified by spec */
1730 if (sps->profile_tier_level.profile_compatibility_flag[1])
1731 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN);
1733 if (sps->profile_tier_level.profile_compatibility_flag[2])
1734 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_10);
1736 if (sps->profile_tier_level.profile_compatibility_flag[3])
1737 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_STILL_PICTURE);
1740 case GST_H265_PROFILE_MAIN_10:
1743 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_12);
1744 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_422_10);
1745 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_422_12);
1746 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_444_10);
1747 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_444_12);
1750 profiles |= profile_to_flag (GST_H265_PROFILE_SCREEN_EXTENDED_MAIN_10);
1753 profiles |= profile_to_flag (GST_H265_PROFILE_SCALABLE_MAIN_10);
1756 case GST_H265_PROFILE_MAIN:
1759 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_10);
1762 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_12);
1763 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_422_10);
1764 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_422_12);
1765 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_444_10);
1766 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_444_12);
1769 profiles |= profile_to_flag (GST_H265_PROFILE_SCREEN_EXTENDED_MAIN);
1770 profiles |= profile_to_flag (GST_H265_PROFILE_SCREEN_EXTENDED_MAIN_10);
1771 profiles |= profile_to_flag (GST_H265_PROFILE_SCREEN_EXTENDED_MAIN_444);
1773 profile_to_flag (GST_H265_PROFILE_SCREEN_EXTENDED_MAIN_444_10);
1776 (GST_H265_PROFILE_SCREEN_EXTENDED_HIGH_THROUGHPUT_444);
1779 (GST_H265_PROFILE_SCREEN_EXTENDED_HIGH_THROUGHPUT_444_10);
1782 (GST_H265_PROFILE_SCREEN_EXTENDED_HIGH_THROUGHPUT_444_14);
1785 profiles |= profile_to_flag (GST_H265_PROFILE_MULTIVIEW_MAIN);
1788 profiles |= profile_to_flag (GST_H265_PROFILE_SCALABLE_MAIN);
1789 profiles |= profile_to_flag (GST_H265_PROFILE_SCALABLE_MAIN_10);
1792 profiles |= profile_to_flag (GST_H265_PROFILE_3D_MAIN);
1795 case GST_H265_PROFILE_MAIN_STILL_PICTURE:
1798 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN);
1799 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_10);
1802 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_12);
1803 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_422_10);
1804 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_422_12);
1805 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_444_10);
1806 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_444_12);
1808 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_INTRA);
1809 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_10_INTRA);
1810 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_12_INTRA);
1811 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_422_10_INTRA);
1812 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_422_12_INTRA);
1813 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_444_INTRA);
1814 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_444_10_INTRA);
1815 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_444_12_INTRA);
1816 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_444_16_INTRA);
1817 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_444_STILL_PICTURE);
1818 profiles |= profile_to_flag (GST_H265_PROFILE_MAIN_444_16_STILL_PICTURE);
1821 profiles |= profile_to_flag (GST_H265_PROFILE_SCREEN_EXTENDED_MAIN);
1822 profiles |= profile_to_flag (GST_H265_PROFILE_SCREEN_EXTENDED_MAIN_10);
1823 profiles |= profile_to_flag (GST_H265_PROFILE_SCREEN_EXTENDED_MAIN_444);
1825 profile_to_flag (GST_H265_PROFILE_SCREEN_EXTENDED_MAIN_444_10);
1828 (GST_H265_PROFILE_SCREEN_EXTENDED_HIGH_THROUGHPUT_444);
1831 (GST_H265_PROFILE_SCREEN_EXTENDED_HIGH_THROUGHPUT_444_10);
1834 (GST_H265_PROFILE_SCREEN_EXTENDED_HIGH_THROUGHPUT_444_14);
1837 case GST_H265_PROFILE_MONOCHROME:
1840 profiles |= profile_to_flag (GST_H265_PROFILE_SCREEN_EXTENDED_MAIN);
1841 profiles |= profile_to_flag (GST_H265_PROFILE_SCREEN_EXTENDED_MAIN_10);
1842 profiles |= profile_to_flag (GST_H265_PROFILE_SCREEN_EXTENDED_MAIN_444);
1844 profile_to_flag (GST_H265_PROFILE_SCREEN_EXTENDED_MAIN_444_10);
1847 (GST_H265_PROFILE_SCREEN_EXTENDED_HIGH_THROUGHPUT_444);
1850 (GST_H265_PROFILE_SCREEN_EXTENDED_HIGH_THROUGHPUT_444_10);
1853 (GST_H265_PROFILE_SCREEN_EXTENDED_HIGH_THROUGHPUT_444_14);
1856 case GST_H265_PROFILE_MAIN_444:
1859 profiles |= profile_to_flag (GST_H265_PROFILE_SCREEN_EXTENDED_MAIN_444);
1861 profile_to_flag (GST_H265_PROFILE_SCREEN_EXTENDED_MAIN_444_10);
1864 case GST_H265_PROFILE_MAIN_444_10:
1867 profiles |= profile_to_flag (GST_H265_PROFILE_SCREEN_EXTENDED_MAIN_10);
1870 case GST_H265_PROFILE_HIGH_THROUGHPUT_444:
1875 (GST_H265_PROFILE_SCREEN_EXTENDED_HIGH_THROUGHPUT_444);
1878 (GST_H265_PROFILE_SCREEN_EXTENDED_HIGH_THROUGHPUT_444_10);
1881 (GST_H265_PROFILE_SCREEN_EXTENDED_HIGH_THROUGHPUT_444_14);
1884 case GST_H265_PROFILE_HIGH_THROUGHPUT_444_10:
1889 (GST_H265_PROFILE_SCREEN_EXTENDED_HIGH_THROUGHPUT_444_10);
1892 (GST_H265_PROFILE_SCREEN_EXTENDED_HIGH_THROUGHPUT_444_14);
1895 case GST_H265_PROFILE_HIGH_THROUGHPUT_444_14:
1900 (GST_H265_PROFILE_SCREEN_EXTENDED_HIGH_THROUGHPUT_444_14);
1908 GValue value = G_VALUE_INIT;
1909 const gchar *profile_str;
1910 caps = gst_caps_new_empty_simple ("video/x-h265");
1912 for (i = GST_H265_PROFILE_MAIN; i < GST_H265_PROFILE_MAX; i++) {
1913 if ((profiles & profile_to_flag (i)) == profile_to_flag (i)) {
1914 profile_str = get_profile_string (i);
1916 if (G_UNLIKELY (profile_str == NULL)) {
1917 GST_FIXME ("Unhandled profile index %d", i);
1921 g_value_init (&value, G_TYPE_STRING);
1922 g_value_set_string (&value, profile_str);
1923 gst_value_list_append_value (&compat_profiles, &value);
1924 g_value_unset (&value);
1928 gst_caps_set_value (caps, "profile", &compat_profiles);
1929 g_value_unset (&compat_profiles);
1935 /* if downstream didn't support the exact profile indicated in sps header,
1936 * check for the compatible profiles also */
1938 ensure_caps_profile (GstH265Parse * h265parse, GstCaps * caps, GstH265SPS * sps,
1939 GstH265Profile profile)
1941 GstCaps *peer_caps, *compat_caps;
1943 peer_caps = gst_pad_get_current_caps (GST_BASE_PARSE_SRC_PAD (h265parse));
1944 if (!peer_caps || !gst_caps_can_intersect (caps, peer_caps)) {
1945 GstCaps *filter_caps = gst_caps_new_empty_simple ("video/x-h265");
1948 gst_caps_unref (peer_caps);
1950 gst_pad_peer_query_caps (GST_BASE_PARSE_SRC_PAD (h265parse),
1953 gst_caps_unref (filter_caps);
1956 if (peer_caps && !gst_caps_can_intersect (caps, peer_caps)) {
1957 GstStructure *structure;
1959 compat_caps = get_compatible_profile_caps (sps, profile);
1960 if (compat_caps != NULL) {
1961 GstCaps *res_caps = NULL;
1963 res_caps = gst_caps_intersect (peer_caps, compat_caps);
1965 if (res_caps && !gst_caps_is_empty (res_caps)) {
1966 const gchar *profile_str = NULL;
1968 res_caps = gst_caps_fixate (res_caps);
1969 structure = gst_caps_get_structure (res_caps, 0);
1970 profile_str = gst_structure_get_string (structure, "profile");
1972 gst_caps_set_simple (caps, "profile", G_TYPE_STRING, profile_str,
1974 GST_DEBUG_OBJECT (h265parse,
1975 "Setting compatible profile %s to the caps", profile_str);
1979 gst_caps_unref (res_caps);
1980 gst_caps_unref (compat_caps);
1984 gst_caps_unref (peer_caps);
1988 gst_h265_parse_update_src_caps (GstH265Parse * h265parse, GstCaps * caps)
1990 GstH265SPS *sps = NULL;
1991 GstCaps *sink_caps, *src_caps;
1992 gboolean modified = FALSE;
1993 GstBuffer *buf = NULL;
1994 GstStructure *s = NULL;
1996 if (G_UNLIKELY (!gst_pad_has_current_caps (GST_BASE_PARSE_SRC_PAD
1999 else if (G_UNLIKELY (!h265parse->update_caps))
2002 /* if this is being called from the first _setcaps call, caps on the sinkpad
2003 * aren't set yet and so they need to be passed as an argument */
2005 sink_caps = gst_caps_ref (caps);
2007 sink_caps = gst_pad_get_current_caps (GST_BASE_PARSE_SINK_PAD (h265parse));
2009 /* carry over input caps as much as possible; override with our own stuff */
2011 sink_caps = gst_caps_new_empty_simple ("video/x-h265");
2013 s = gst_caps_get_structure (sink_caps, 0);
2015 sps = h265parse->nalparser->last_sps;
2016 GST_DEBUG_OBJECT (h265parse, "sps: %p", sps);
2018 /* only codec-data for nice-and-clean au aligned packetized hevc format */
2019 if ((h265parse->format == GST_H265_PARSE_FORMAT_HVC1
2020 || h265parse->format == GST_H265_PARSE_FORMAT_HEV1)
2021 && h265parse->align == GST_H265_PARSE_ALIGN_AU) {
2022 buf = gst_h265_parse_make_codec_data (h265parse);
2023 if (buf && h265parse->codec_data) {
2026 gst_buffer_map (buf, &map, GST_MAP_READ);
2027 if (map.size != gst_buffer_get_size (h265parse->codec_data) ||
2028 gst_buffer_memcmp (h265parse->codec_data, 0, map.data, map.size))
2031 gst_buffer_unmap (buf, &map);
2033 if (!buf && h265parse->codec_data_in)
2034 buf = gst_buffer_ref (h265parse->codec_data_in);
2040 if (G_UNLIKELY (!sps)) {
2041 caps = gst_caps_copy (sink_caps);
2043 gint crop_width, crop_height;
2044 const gchar *chroma_format = NULL;
2045 guint bit_depth_chroma;
2046 GstH265VPS *vps = sps->vps;
2047 GstH265VUIParams *vui = &sps->vui_params;
2048 gchar *colorimetry = NULL;
2050 GST_DEBUG_OBJECT (h265parse, "vps: %p", vps);
2052 if (sps->conformance_window_flag) {
2053 crop_width = sps->crop_rect_width;
2054 crop_height = sps->crop_rect_height;
2056 crop_width = sps->width;
2057 crop_height = sps->height;
2060 if (G_UNLIKELY (h265parse->width != crop_width ||
2061 h265parse->height != crop_height)) {
2062 GST_INFO_OBJECT (h265parse, "resolution changed %dx%d",
2063 crop_width, crop_height);
2064 h265parse->width = crop_width;
2065 h265parse->height = crop_height;
2069 /* 0/1 is set as the default in the codec parser */
2070 if ((vui->timing_info_present_flag ||
2071 (vps && vps->timing_info_present_flag)) &&
2072 !(sps->fps_num == 0 && sps->fps_den == 1)) {
2073 if (G_UNLIKELY (h265parse->fps_num != sps->fps_num
2074 || h265parse->fps_den != sps->fps_den)) {
2075 GST_INFO_OBJECT (h265parse, "framerate changed %d/%d",
2076 sps->fps_num, sps->fps_den);
2077 h265parse->fps_num = sps->fps_num;
2078 h265parse->fps_den = sps->fps_den;
2083 if (vui->aspect_ratio_info_present_flag) {
2084 if (G_UNLIKELY ((h265parse->parsed_par_n != vui->par_n)
2085 && (h265parse->parsed_par_d != sps->vui_params.par_d))) {
2086 h265parse->parsed_par_n = vui->par_n;
2087 h265parse->parsed_par_d = vui->par_d;
2088 GST_INFO_OBJECT (h265parse, "pixel aspect ratio has been changed %d/%d",
2089 h265parse->parsed_par_n, h265parse->parsed_par_d);
2095 if (vui->video_signal_type_present_flag &&
2096 vui->colour_description_present_flag) {
2097 GstVideoColorimetry ci = { 0, };
2098 gchar *old_colorimetry = NULL;
2100 if (vui->video_full_range_flag)
2101 ci.range = GST_VIDEO_COLOR_RANGE_0_255;
2103 ci.range = GST_VIDEO_COLOR_RANGE_16_235;
2105 ci.matrix = gst_video_color_matrix_from_iso (vui->matrix_coefficients);
2107 gst_video_color_transfer_from_iso (vui->transfer_characteristics);
2108 ci.primaries = gst_video_color_primaries_from_iso (vui->colour_primaries);
2111 gst_video_colorimetry_to_string (&h265parse->parsed_colorimetry);
2112 colorimetry = gst_video_colorimetry_to_string (&ci);
2114 if (colorimetry && g_strcmp0 (old_colorimetry, colorimetry)) {
2115 GST_INFO_OBJECT (h265parse,
2116 "colorimetry has been changed from %s to %s",
2117 GST_STR_NULL (old_colorimetry), colorimetry);
2118 h265parse->parsed_colorimetry = ci;
2122 g_free (old_colorimetry);
2125 if (G_UNLIKELY (modified || h265parse->update_caps)) {
2126 gint fps_num = h265parse->fps_num;
2127 gint fps_den = h265parse->fps_den;
2129 GstClockTime latency;
2131 caps = gst_caps_copy (sink_caps);
2133 /* sps should give this but upstream overrides */
2134 if (s && gst_structure_has_field (s, "width"))
2135 gst_structure_get_int (s, "width", &width);
2137 width = h265parse->width;
2139 if (s && gst_structure_has_field (s, "height"))
2140 gst_structure_get_int (s, "height", &height);
2142 height = h265parse->height;
2144 gst_caps_set_simple (caps, "width", G_TYPE_INT, width,
2145 "height", G_TYPE_INT, height, NULL);
2147 /* upstream overrides */
2148 if (s && gst_structure_has_field (s, "framerate"))
2149 gst_structure_get_fraction (s, "framerate", &fps_num, &fps_den);
2151 /* but not necessarily or reliably this */
2152 if (fps_num > 0 && fps_den > 0) {
2154 GST_INFO_OBJECT (h265parse, "setting framerate in caps");
2155 gst_caps_set_simple (caps, "framerate",
2156 GST_TYPE_FRACTION, fps_num, fps_den, NULL);
2157 s2 = gst_caps_get_structure (caps, 0);
2158 gst_structure_get_fraction (s2, "framerate", &h265parse->parsed_fps_n,
2159 &h265parse->parsed_fps_d);
2160 gst_base_parse_set_frame_rate (GST_BASE_PARSE (h265parse),
2161 fps_num, fps_den, 0, 0);
2162 latency = gst_util_uint64_scale (GST_SECOND, fps_den, fps_num);
2163 gst_base_parse_set_latency (GST_BASE_PARSE (h265parse), latency,
2167 bit_depth_chroma = sps->bit_depth_chroma_minus8 + 8;
2169 switch (sps->chroma_format_idc) {
2171 chroma_format = "4:0:0";
2172 bit_depth_chroma = 0;
2175 chroma_format = "4:2:0";
2178 chroma_format = "4:2:2";
2181 chroma_format = "4:4:4";
2188 gst_caps_set_simple (caps, "chroma-format", G_TYPE_STRING,
2189 chroma_format, "bit-depth-luma", G_TYPE_UINT,
2190 sps->bit_depth_luma_minus8 + 8, "bit-depth-chroma", G_TYPE_UINT,
2191 bit_depth_chroma, NULL);
2193 if (colorimetry && (!s || !gst_structure_has_field (s, "colorimetry"))) {
2194 gst_caps_set_simple (caps, "colorimetry", G_TYPE_STRING, colorimetry,
2199 g_free (colorimetry);
2204 const gchar *mastering_info_str;
2205 const gchar *cll_str;
2207 gst_caps_set_simple (caps, "parsed", G_TYPE_BOOLEAN, TRUE,
2208 "stream-format", G_TYPE_STRING,
2209 gst_h265_parse_get_string (h265parse, TRUE, h265parse->format),
2210 "alignment", G_TYPE_STRING,
2211 gst_h265_parse_get_string (h265parse, FALSE, h265parse->align), NULL);
2213 gst_h265_parse_get_par (h265parse, &par_n, &par_d);
2214 if (par_n != 0 && par_d != 0 &&
2215 (!s || !gst_structure_has_field (s, "pixel-aspect-ratio"))) {
2216 GST_INFO_OBJECT (h265parse, "PAR %d/%d", par_n, par_d);
2217 gst_caps_set_simple (caps, "pixel-aspect-ratio", GST_TYPE_FRACTION,
2218 par_n, par_d, NULL);
2221 /* set profile and level in caps */
2223 const gchar *profile, *tier, *level;
2226 p = gst_h265_profile_tier_level_get_profile (&sps->profile_tier_level);
2227 profile = get_profile_string (p);
2228 if (profile != NULL)
2229 gst_caps_set_simple (caps, "profile", G_TYPE_STRING, profile, NULL);
2231 tier = get_tier_string (sps->profile_tier_level.tier_flag);
2233 gst_caps_set_simple (caps, "tier", G_TYPE_STRING, tier, NULL);
2235 level = get_level_string (sps->profile_tier_level.level_idc);
2237 gst_caps_set_simple (caps, "level", G_TYPE_STRING, level, NULL);
2239 /* relax the profile constraint to find a suitable decoder */
2240 ensure_caps_profile (h265parse, caps, sps, p);
2244 && (mastering_info_str =
2245 gst_structure_get_string (s, "mastering-display-info"))) {
2246 gst_caps_set_simple (caps, "mastering-display-info", G_TYPE_STRING,
2247 mastering_info_str, NULL);
2248 } else if (h265parse->mastering_display_info_state !=
2249 GST_H265_PARSE_SEI_EXPIRED
2251 !gst_video_mastering_display_info_add_to_caps
2252 (&h265parse->mastering_display_info, caps)) {
2253 GST_WARNING_OBJECT (h265parse,
2254 "Couldn't set mastering display info to caps");
2257 if (s && (cll_str = gst_structure_get_string (s, "content-light-level"))) {
2258 gst_caps_set_simple (caps, "content-light-level", G_TYPE_STRING, cll_str,
2260 } else if (h265parse->content_light_level_state !=
2261 GST_H265_PARSE_SEI_EXPIRED
2263 !gst_video_content_light_level_add_to_caps
2264 (&h265parse->content_light_level, caps)) {
2265 GST_WARNING_OBJECT (h265parse,
2266 "Couldn't set content light level to caps");
2269 src_caps = gst_pad_get_current_caps (GST_BASE_PARSE_SRC_PAD (h265parse));
2272 /* use codec data from old caps for comparison; we don't want to resend caps
2273 if everything is same except codec data; */
2274 if (gst_structure_has_field (gst_caps_get_structure (src_caps, 0),
2276 gst_caps_set_value (caps, "codec_data",
2277 gst_structure_get_value (gst_caps_get_structure (src_caps, 0),
2281 /* remove any left-over codec-data hanging around */
2282 s = gst_caps_get_structure (caps, 0);
2283 gst_structure_remove_field (s, "codec_data");
2287 if (!(src_caps && gst_caps_is_strictly_equal (src_caps, caps))) {
2288 /* update codec data to new value */
2290 gst_caps_set_simple (caps, "codec_data", GST_TYPE_BUFFER, buf, NULL);
2291 gst_buffer_replace (&h265parse->codec_data, buf);
2292 gst_buffer_unref (buf);
2296 /* remove any left-over codec-data hanging around */
2297 s = gst_caps_get_structure (caps, 0);
2298 gst_structure_remove_field (s, "codec_data");
2299 gst_buffer_replace (&h265parse->codec_data, NULL);
2302 gst_pad_set_caps (GST_BASE_PARSE_SRC_PAD (h265parse), caps);
2306 gst_caps_unref (src_caps);
2307 gst_caps_unref (caps);
2310 gst_caps_unref (sink_caps);
2312 gst_buffer_unref (buf);
2316 static GstFlowReturn
2317 gst_h265_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
2319 GstH265Parse *h265parse;
2323 h265parse = GST_H265_PARSE (parse);
2324 buffer = frame->buffer;
2326 gst_h265_parse_update_src_caps (h265parse, NULL);
2328 /* Fixme: Implement timestamp interpolation based on SEI Messagses */
2329 GST_FIXME_OBJECT (h265parse,
2330 "Implement timestamp/duration interpolation based on SEI message");
2332 if (h265parse->keyframe)
2333 GST_BUFFER_FLAG_UNSET (buffer, GST_BUFFER_FLAG_DELTA_UNIT);
2335 GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT);
2337 if (h265parse->discard_bidirectional && h265parse->bidirectional)
2341 if (h265parse->header)
2342 GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_HEADER);
2344 GST_BUFFER_FLAG_UNSET (buffer, GST_BUFFER_FLAG_HEADER);
2346 if (h265parse->discont) {
2347 GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
2348 h265parse->discont = FALSE;
2351 /* replace with transformed HEVC output if applicable */
2352 av = gst_adapter_available (h265parse->frame_out);
2356 buf = gst_adapter_take_buffer (h265parse->frame_out, av);
2357 gst_buffer_copy_into (buf, buffer, GST_BUFFER_COPY_METADATA, 0, -1);
2358 gst_buffer_replace (&frame->out_buffer, buf);
2359 gst_buffer_unref (buf);
2366 GST_DEBUG_OBJECT (h265parse, "Discarding bidirectional frame");
2367 frame->flags |= GST_BASE_PARSE_FRAME_FLAG_DROP;
2368 gst_h265_parse_reset_frame (h265parse);
2373 /* sends a codec NAL downstream, decorating and transforming as needed.
2374 * No ownership is taken of @nal */
2375 static GstFlowReturn
2376 gst_h265_parse_push_codec_buffer (GstH265Parse * h265parse, GstBuffer * nal,
2381 gst_buffer_map (nal, &map, GST_MAP_READ);
2382 nal = gst_h265_parse_wrap_nal (h265parse, h265parse->format,
2383 map.data, map.size);
2384 gst_buffer_unmap (nal, &map);
2386 GST_BUFFER_TIMESTAMP (nal) = ts;
2387 GST_BUFFER_DURATION (nal) = 0;
2389 return gst_pad_push (GST_BASE_PARSE_SRC_PAD (h265parse), nal);
2393 check_pending_key_unit_event (GstEvent * pending_event, GstSegment * segment,
2394 GstClockTime timestamp, guint flags, GstClockTime pending_key_unit_ts)
2396 GstClockTime running_time, stream_time;
2397 gboolean all_headers;
2399 GstEvent *event = NULL;
2401 g_return_val_if_fail (segment != NULL, NULL);
2403 if (pending_event == NULL)
2406 if (GST_CLOCK_TIME_IS_VALID (pending_key_unit_ts) &&
2407 timestamp == GST_CLOCK_TIME_NONE)
2410 running_time = gst_segment_to_running_time (segment,
2411 GST_FORMAT_TIME, timestamp);
2413 GST_INFO ("now %" GST_TIME_FORMAT " wanted %" GST_TIME_FORMAT,
2414 GST_TIME_ARGS (running_time), GST_TIME_ARGS (pending_key_unit_ts));
2415 if (GST_CLOCK_TIME_IS_VALID (pending_key_unit_ts) &&
2416 running_time < pending_key_unit_ts)
2419 if (flags & GST_BUFFER_FLAG_DELTA_UNIT) {
2420 GST_DEBUG ("pending force key unit, waiting for keyframe");
2424 stream_time = gst_segment_to_stream_time (segment,
2425 GST_FORMAT_TIME, timestamp);
2427 if (!gst_video_event_parse_upstream_force_key_unit (pending_event,
2428 NULL, &all_headers, &count)) {
2429 gst_video_event_parse_downstream_force_key_unit (pending_event, NULL,
2430 NULL, NULL, &all_headers, &count);
2434 gst_video_event_new_downstream_force_key_unit (timestamp, stream_time,
2435 running_time, all_headers, count);
2436 gst_event_set_seqnum (event, gst_event_get_seqnum (pending_event));
2443 gst_h265_parse_prepare_key_unit (GstH265Parse * parse, GstEvent * event)
2445 GstClockTime running_time;
2447 #ifndef GST_DISABLE_GST_DEBUG
2448 gboolean have_vps, have_sps, have_pps;
2452 parse->pending_key_unit_ts = GST_CLOCK_TIME_NONE;
2453 gst_event_replace (&parse->force_key_unit_event, NULL);
2455 gst_video_event_parse_downstream_force_key_unit (event,
2456 NULL, NULL, &running_time, NULL, &count);
2458 GST_INFO_OBJECT (parse, "pushing downstream force-key-unit event %d "
2459 "%" GST_TIME_FORMAT " count %d", gst_event_get_seqnum (event),
2460 GST_TIME_ARGS (running_time), count);
2461 gst_pad_push_event (GST_BASE_PARSE_SRC_PAD (parse), event);
2463 #ifndef GST_DISABLE_GST_DEBUG
2464 have_vps = have_sps = have_pps = FALSE;
2465 for (i = 0; i < GST_H265_MAX_VPS_COUNT; i++) {
2466 if (parse->vps_nals[i] != NULL) {
2471 for (i = 0; i < GST_H265_MAX_SPS_COUNT; i++) {
2472 if (parse->sps_nals[i] != NULL) {
2477 for (i = 0; i < GST_H265_MAX_PPS_COUNT; i++) {
2478 if (parse->pps_nals[i] != NULL) {
2484 GST_INFO_OBJECT (parse,
2485 "preparing key unit, have vps %d have sps %d have pps %d", have_vps,
2486 have_sps, have_pps);
2489 /* set push_codec to TRUE so that pre_push_frame sends VPS/SPS/PPS again */
2490 parse->push_codec = TRUE;
2494 gst_h265_parse_handle_vps_sps_pps_nals (GstH265Parse * h265parse,
2495 GstBuffer * buffer, GstBaseParseFrame * frame)
2497 GstBuffer *codec_nal;
2499 gboolean send_done = FALSE;
2500 GstClockTime timestamp = GST_BUFFER_TIMESTAMP (buffer);
2502 if (h265parse->have_vps_in_frame && h265parse->have_sps_in_frame
2503 && h265parse->have_pps_in_frame) {
2504 GST_DEBUG_OBJECT (h265parse, "VPS/SPS/PPS exist in frame, will not insert");
2508 if (h265parse->align == GST_H265_PARSE_ALIGN_NAL) {
2509 /* send separate config NAL buffers */
2510 GST_DEBUG_OBJECT (h265parse, "- sending VPS/SPS/PPS");
2511 for (i = 0; i < GST_H265_MAX_VPS_COUNT; i++) {
2512 if ((codec_nal = h265parse->vps_nals[i])) {
2513 GST_DEBUG_OBJECT (h265parse, "sending VPS nal");
2514 gst_h265_parse_push_codec_buffer (h265parse, codec_nal, timestamp);
2518 for (i = 0; i < GST_H265_MAX_SPS_COUNT; i++) {
2519 if ((codec_nal = h265parse->sps_nals[i])) {
2520 GST_DEBUG_OBJECT (h265parse, "sending SPS nal");
2521 gst_h265_parse_push_codec_buffer (h265parse, codec_nal, timestamp);
2525 for (i = 0; i < GST_H265_MAX_PPS_COUNT; i++) {
2526 if ((codec_nal = h265parse->pps_nals[i])) {
2527 GST_DEBUG_OBJECT (h265parse, "sending PPS nal");
2528 gst_h265_parse_push_codec_buffer (h265parse, codec_nal, timestamp);
2533 /* insert config NALs into AU */
2536 const gboolean bs = h265parse->format == GST_H265_PARSE_FORMAT_BYTE;
2537 const gint nls = 4 - h265parse->nal_length_size;
2540 gst_byte_writer_init_with_size (&bw, gst_buffer_get_size (buffer), FALSE);
2541 ok = gst_byte_writer_put_buffer (&bw, buffer, 0, h265parse->idr_pos);
2542 GST_DEBUG_OBJECT (h265parse, "- inserting VPS/SPS/PPS");
2543 for (i = 0; i < GST_H265_MAX_VPS_COUNT; i++) {
2544 if ((codec_nal = h265parse->vps_nals[i])) {
2545 gsize nal_size = gst_buffer_get_size (codec_nal);
2546 GST_DEBUG_OBJECT (h265parse, "inserting VPS nal");
2548 ok &= gst_byte_writer_put_uint32_be (&bw, 1);
2550 ok &= gst_byte_writer_put_uint32_be (&bw, (nal_size << (nls * 8)));
2551 ok &= gst_byte_writer_set_pos (&bw,
2552 gst_byte_writer_get_pos (&bw) - nls);
2555 ok &= gst_byte_writer_put_buffer (&bw, codec_nal, 0, nal_size);
2559 for (i = 0; i < GST_H265_MAX_SPS_COUNT; i++) {
2560 if ((codec_nal = h265parse->sps_nals[i])) {
2561 gsize nal_size = gst_buffer_get_size (codec_nal);
2562 GST_DEBUG_OBJECT (h265parse, "inserting SPS nal");
2564 ok &= gst_byte_writer_put_uint32_be (&bw, 1);
2566 ok &= gst_byte_writer_put_uint32_be (&bw, (nal_size << (nls * 8)));
2567 ok &= gst_byte_writer_set_pos (&bw,
2568 gst_byte_writer_get_pos (&bw) - nls);
2571 ok &= gst_byte_writer_put_buffer (&bw, codec_nal, 0, nal_size);
2575 for (i = 0; i < GST_H265_MAX_PPS_COUNT; i++) {
2576 if ((codec_nal = h265parse->pps_nals[i])) {
2577 gsize nal_size = gst_buffer_get_size (codec_nal);
2578 GST_DEBUG_OBJECT (h265parse, "inserting PPS 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);
2586 ok &= gst_byte_writer_put_buffer (&bw, codec_nal, 0, nal_size);
2590 ok &= gst_byte_writer_put_buffer (&bw, buffer, h265parse->idr_pos, -1);
2591 /* collect result and push */
2592 new_buf = gst_byte_writer_reset_and_get_buffer (&bw);
2593 gst_buffer_copy_into (new_buf, buffer, GST_BUFFER_COPY_METADATA, 0, -1);
2594 /* should already be keyframe/IDR, but it may not have been,
2595 * so mark it as such to avoid being discarded by picky decoder */
2596 GST_BUFFER_FLAG_UNSET (new_buf, GST_BUFFER_FLAG_DELTA_UNIT);
2597 gst_buffer_replace (&frame->out_buffer, new_buf);
2598 gst_buffer_unref (new_buf);
2599 /* some result checking seems to make some compilers happy */
2600 if (G_UNLIKELY (!ok)) {
2601 GST_ERROR_OBJECT (h265parse, "failed to insert SPS/PPS");
2608 static GstFlowReturn
2609 gst_h265_parse_pre_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
2611 GstH265Parse *h265parse;
2614 GstBuffer *parse_buffer = NULL;
2616 h265parse = GST_H265_PARSE (parse);
2618 if (!h265parse->sent_codec_tag) {
2619 GstTagList *taglist;
2623 caps = gst_pad_get_current_caps (GST_BASE_PARSE_SRC_PAD (parse));
2624 if (G_UNLIKELY (caps == NULL)) {
2625 if (GST_PAD_IS_FLUSHING (GST_BASE_PARSE_SRC_PAD (parse))) {
2626 GST_INFO_OBJECT (parse, "Src pad is flushing");
2627 return GST_FLOW_FLUSHING;
2629 GST_INFO_OBJECT (parse, "Src pad is not negotiated!");
2630 return GST_FLOW_NOT_NEGOTIATED;
2634 taglist = gst_tag_list_new_empty ();
2635 gst_pb_utils_add_codec_description_to_tag_list (taglist,
2636 GST_TAG_VIDEO_CODEC, caps);
2637 gst_caps_unref (caps);
2639 gst_base_parse_merge_tags (parse, taglist, GST_TAG_MERGE_REPLACE);
2640 gst_tag_list_unref (taglist);
2642 /* also signals the end of first-frame processing */
2643 h265parse->sent_codec_tag = TRUE;
2646 buffer = frame->buffer;
2648 if ((event = check_pending_key_unit_event (h265parse->force_key_unit_event,
2649 &parse->segment, GST_BUFFER_TIMESTAMP (buffer),
2650 GST_BUFFER_FLAGS (buffer), h265parse->pending_key_unit_ts))) {
2651 gst_h265_parse_prepare_key_unit (h265parse, event);
2654 /* periodic VPS/SPS/PPS sending */
2655 if (h265parse->interval > 0 || h265parse->push_codec) {
2656 GstClockTime timestamp = GST_BUFFER_TIMESTAMP (buffer);
2658 gboolean initial_frame = FALSE;
2661 if (!GST_CLOCK_TIME_IS_VALID (h265parse->last_report)) {
2662 h265parse->last_report = timestamp;
2663 initial_frame = TRUE;
2666 if (h265parse->idr_pos >= 0) {
2667 GST_LOG_OBJECT (h265parse, "IDR nal at offset %d", h265parse->idr_pos);
2669 if (timestamp > h265parse->last_report)
2670 diff = timestamp - h265parse->last_report;
2674 GST_LOG_OBJECT (h265parse,
2675 "now %" GST_TIME_FORMAT ", last VPS/SPS/PPS %" GST_TIME_FORMAT,
2676 GST_TIME_ARGS (timestamp), GST_TIME_ARGS (h265parse->last_report));
2678 GST_DEBUG_OBJECT (h265parse,
2679 "interval since last VPS/SPS/PPS %" GST_TIME_FORMAT,
2680 GST_TIME_ARGS (diff));
2682 if (GST_TIME_AS_SECONDS (diff) >= h265parse->interval ||
2683 initial_frame || h265parse->push_codec) {
2684 GstClockTime new_ts;
2686 /* avoid overwriting a perfectly fine timestamp */
2687 new_ts = GST_CLOCK_TIME_IS_VALID (timestamp) ? timestamp :
2688 h265parse->last_report;
2690 if (gst_h265_parse_handle_vps_sps_pps_nals (h265parse, buffer, frame)) {
2691 h265parse->last_report = new_ts;
2695 /* we pushed whatever we had */
2696 h265parse->push_codec = FALSE;
2697 h265parse->have_vps = FALSE;
2698 h265parse->have_sps = FALSE;
2699 h265parse->have_pps = FALSE;
2700 h265parse->state &= GST_H265_PARSE_STATE_VALID_PICTURE_HEADERS;
2702 } else if (h265parse->interval == -1) {
2703 if (h265parse->idr_pos >= 0) {
2704 GST_LOG_OBJECT (h265parse, "IDR nal at offset %d", h265parse->idr_pos);
2706 gst_h265_parse_handle_vps_sps_pps_nals (h265parse, buffer, frame);
2708 /* we pushed whatever we had */
2709 h265parse->push_codec = FALSE;
2710 h265parse->have_vps = FALSE;
2711 h265parse->have_sps = FALSE;
2712 h265parse->have_pps = FALSE;
2713 h265parse->state &= GST_H265_PARSE_STATE_VALID_PICTURE_HEADERS;
2720 for (i = 0; i < h265parse->time_code.num_clock_ts; i++) {
2721 gint field_count = -1;
2723 GstVideoTimeCodeFlags flags = 0;
2725 if (!h265parse->time_code.clock_timestamp_flag[i])
2728 h265parse->time_code.clock_timestamp_flag[i] = 0;
2731 switch (h265parse->sei_pic_struct) {
2732 case GST_H265_SEI_PIC_STRUCT_FRAME:
2733 case GST_H265_SEI_PIC_STRUCT_TOP_FIELD:
2734 case GST_H265_SEI_PIC_STRUCT_BOTTOM_FIELD:
2735 field_count = h265parse->sei_pic_struct;
2737 case GST_H265_SEI_PIC_STRUCT_TOP_BOTTOM:
2738 case GST_H265_SEI_PIC_STRUCT_TOP_PAIRED_PREVIOUS_BOTTOM:
2739 case GST_H265_SEI_PIC_STRUCT_TOP_PAIRED_NEXT_BOTTOM:
2740 field_count = i + 1;
2742 case GST_H265_SEI_PIC_STRUCT_BOTTOM_TOP:
2743 case GST_H265_SEI_PIC_STRUCT_BOTTOM_PAIRED_PREVIOUS_TOP:
2744 case GST_H265_SEI_PIC_STRUCT_BOTTOM_PAIRED_NEXT_TOP:
2745 field_count = 2 - i;
2747 case GST_H265_SEI_PIC_STRUCT_TOP_BOTTOM_TOP:
2748 field_count = i % 2 ? 2 : 1;
2750 case GST_H265_SEI_PIC_STRUCT_BOTTOM_TOP_BOTTOM:
2751 field_count = i % 2 ? 1 : 2;
2753 case GST_H265_SEI_PIC_STRUCT_FRAME_DOUBLING:
2754 case GST_H265_SEI_PIC_STRUCT_FRAME_TRIPLING:
2759 if (field_count == -1) {
2760 GST_WARNING_OBJECT (parse,
2761 "failed to determine field count for timecode");
2765 /* Dropping of the two lowest (value 0 and 1) n_frames[ i ] counts when
2766 * seconds_value[ i ] is equal to 0 and minutes_value[ i ] is not an integer
2768 if (h265parse->time_code.counting_type[i] == 4)
2769 flags |= GST_VIDEO_TIME_CODE_FLAGS_DROP_FRAME;
2771 if (h265parse->sei_pic_struct != GST_H265_SEI_PIC_STRUCT_FRAME)
2772 flags |= GST_VIDEO_TIME_CODE_FLAGS_INTERLACED;
2775 gst_util_uint64_scale_int (h265parse->time_code.n_frames[i], 1,
2776 2 - h265parse->time_code.units_field_based_flag[i]);
2778 gst_buffer_add_video_time_code_meta_full (buffer,
2779 h265parse->parsed_fps_n,
2780 h265parse->parsed_fps_d,
2783 h265parse->time_code.hours_flag[i] ? h265parse->time_code.
2785 h265parse->time_code.minutes_flag[i] ? h265parse->time_code.
2786 minutes_value[i] : 0,
2787 h265parse->time_code.seconds_flag[i] ? h265parse->time_code.
2788 seconds_value[i] : 0, n_frames, field_count);
2792 if (frame->out_buffer) {
2793 parse_buffer = frame->out_buffer =
2794 gst_buffer_make_writable (frame->out_buffer);
2796 parse_buffer = frame->buffer = gst_buffer_make_writable (frame->buffer);
2799 if (h265parse->sei_pic_struct != GST_H265_SEI_PIC_STRUCT_FRAME) {
2800 GST_BUFFER_FLAG_SET (parse_buffer, GST_VIDEO_BUFFER_FLAG_INTERLACED);
2801 if (h265parse->sei_pic_struct == GST_H265_SEI_PIC_STRUCT_TOP_FIELD)
2802 GST_BUFFER_FLAG_SET (parse_buffer, GST_VIDEO_BUFFER_FLAG_TFF);
2805 gst_video_push_user_data ((GstElement *) h265parse, &h265parse->user_data,
2808 gst_h265_parse_reset_frame (h265parse);
2814 gst_h265_parse_set_caps (GstBaseParse * parse, GstCaps * caps)
2816 GstH265Parse *h265parse;
2818 const GValue *value;
2819 GstBuffer *codec_data = NULL;
2821 guint format, align;
2822 guint num_nals, i, j;
2823 GstH265NalUnit nalu;
2824 GstH265ParserResult parseres;
2827 h265parse = GST_H265_PARSE (parse);
2830 h265parse->push_codec = FALSE;
2832 old_caps = gst_pad_get_current_caps (GST_BASE_PARSE_SINK_PAD (parse));
2834 if (!gst_caps_is_equal (old_caps, caps))
2835 gst_h265_parse_reset_stream_info (h265parse);
2836 gst_caps_unref (old_caps);
2839 str = gst_caps_get_structure (caps, 0);
2841 /* accept upstream info if provided */
2842 gst_structure_get_int (str, "width", &h265parse->width);
2843 gst_structure_get_int (str, "height", &h265parse->height);
2844 gst_structure_get_fraction (str, "framerate", &h265parse->fps_num,
2845 &h265parse->fps_den);
2846 gst_structure_get_fraction (str, "pixel-aspect-ratio",
2847 &h265parse->upstream_par_n, &h265parse->upstream_par_d);
2849 /* get upstream format and align from caps */
2850 gst_h265_parse_format_from_caps (caps, &format, &align);
2852 /* packetized video has a codec_data */
2853 if (format != GST_H265_PARSE_FORMAT_BYTE &&
2854 (value = gst_structure_get_value (str, "codec_data"))) {
2857 guint num_nal_arrays;
2859 GST_DEBUG_OBJECT (h265parse, "have packetized h265");
2860 /* make note for optional split processing */
2861 h265parse->packetized = TRUE;
2863 codec_data = gst_value_get_buffer (value);
2866 gst_buffer_map (codec_data, &map, GST_MAP_READ);
2870 /* parse the hvcC data */
2872 gst_buffer_unmap (codec_data, &map);
2873 goto hvcc_too_small;
2875 /* parse the version, this must be one but
2876 * is zero until the spec is finalized */
2877 if (data[0] != 0 && data[0] != 1) {
2878 gst_buffer_unmap (codec_data, &map);
2882 h265parse->nal_length_size = (data[21] & 0x03) + 1;
2883 GST_DEBUG_OBJECT (h265parse, "nal length size %u",
2884 h265parse->nal_length_size);
2886 num_nal_arrays = data[22];
2889 for (i = 0; i < num_nal_arrays; i++) {
2890 if (off + 3 >= size) {
2891 gst_buffer_unmap (codec_data, &map);
2892 goto hvcc_too_small;
2895 num_nals = GST_READ_UINT16_BE (data + off + 1);
2897 for (j = 0; j < num_nals; j++) {
2898 parseres = gst_h265_parser_identify_nalu_hevc (h265parse->nalparser,
2899 data, off, size, 2, &nalu);
2901 if (parseres != GST_H265_PARSER_OK) {
2902 gst_buffer_unmap (codec_data, &map);
2903 goto hvcc_too_small;
2906 gst_h265_parse_process_nal (h265parse, &nalu);
2907 off = nalu.offset + nalu.size;
2910 gst_buffer_unmap (codec_data, &map);
2912 /* don't confuse codec_data with inband vps/sps/pps */
2913 h265parse->have_vps_in_frame = FALSE;
2914 h265parse->have_sps_in_frame = FALSE;
2915 h265parse->have_pps_in_frame = FALSE;
2917 GST_DEBUG_OBJECT (h265parse, "have bytestream h265");
2918 /* nothing to pre-process */
2919 h265parse->packetized = FALSE;
2920 /* we have 4 sync bytes */
2921 h265parse->nal_length_size = 4;
2923 if (format == GST_H265_PARSE_FORMAT_NONE) {
2924 format = GST_H265_PARSE_FORMAT_BYTE;
2925 align = GST_H265_PARSE_ALIGN_AU;
2932 /* prefer input type determined above */
2933 in_caps = gst_caps_new_simple ("video/x-h265",
2934 "parsed", G_TYPE_BOOLEAN, TRUE,
2935 "stream-format", G_TYPE_STRING,
2936 gst_h265_parse_get_string (h265parse, TRUE, format),
2937 "alignment", G_TYPE_STRING,
2938 gst_h265_parse_get_string (h265parse, FALSE, align), NULL);
2939 /* negotiate with downstream, sets ->format and ->align */
2940 gst_h265_parse_negotiate (h265parse, format, in_caps);
2941 gst_caps_unref (in_caps);
2944 if (format == h265parse->format && align == h265parse->align) {
2945 /* do not set CAPS and passthrough mode if SPS/PPS have not been parsed */
2946 if (h265parse->have_sps && h265parse->have_pps) {
2947 gst_base_parse_set_passthrough (parse, TRUE);
2949 /* we did parse codec-data and might supplement src caps */
2950 gst_h265_parse_update_src_caps (h265parse, caps);
2952 } else if (format == GST_H265_PARSE_FORMAT_HVC1
2953 || format == GST_H265_PARSE_FORMAT_HEV1) {
2954 /* if input != output, and input is hevc, must split before anything else */
2955 /* arrange to insert codec-data in-stream if needed.
2956 * src caps are only arranged for later on */
2957 h265parse->push_codec = TRUE;
2958 h265parse->have_vps = FALSE;
2959 h265parse->have_sps = FALSE;
2960 h265parse->have_pps = FALSE;
2961 if (h265parse->align == GST_H265_PARSE_ALIGN_NAL)
2962 h265parse->split_packetized = TRUE;
2963 h265parse->packetized = TRUE;
2971 GST_DEBUG_OBJECT (h265parse, "hvcC size %" G_GSIZE_FORMAT " < 23", size);
2976 GST_DEBUG_OBJECT (h265parse, "wrong hvcC version");
2981 GST_DEBUG_OBJECT (h265parse, "wrong codec-data type");
2986 GST_WARNING_OBJECT (h265parse, "refused caps %" GST_PTR_FORMAT, caps);
2992 remove_fields (GstCaps * caps, gboolean all)
2996 n = gst_caps_get_size (caps);
2997 for (i = 0; i < n; i++) {
2998 GstStructure *s = gst_caps_get_structure (caps, i);
3001 gst_structure_remove_field (s, "alignment");
3002 gst_structure_remove_field (s, "stream-format");
3004 gst_structure_remove_field (s, "parsed");
3009 gst_h265_parse_get_caps (GstBaseParse * parse, GstCaps * filter)
3011 GstCaps *peercaps, *templ;
3012 GstCaps *res, *tmp, *pcopy;
3014 templ = gst_pad_get_pad_template_caps (GST_BASE_PARSE_SINK_PAD (parse));
3016 GstCaps *fcopy = gst_caps_copy (filter);
3017 /* Remove the fields we convert */
3018 remove_fields (fcopy, TRUE);
3019 peercaps = gst_pad_peer_query_caps (GST_BASE_PARSE_SRC_PAD (parse), fcopy);
3020 gst_caps_unref (fcopy);
3022 peercaps = gst_pad_peer_query_caps (GST_BASE_PARSE_SRC_PAD (parse), NULL);
3024 pcopy = gst_caps_copy (peercaps);
3025 remove_fields (pcopy, TRUE);
3027 res = gst_caps_intersect_full (pcopy, templ, GST_CAPS_INTERSECT_FIRST);
3028 gst_caps_unref (pcopy);
3029 gst_caps_unref (templ);
3032 GstCaps *tmp = gst_caps_intersect_full (res, filter,
3033 GST_CAPS_INTERSECT_FIRST);
3034 gst_caps_unref (res);
3038 /* Try if we can put the downstream caps first */
3039 pcopy = gst_caps_copy (peercaps);
3040 remove_fields (pcopy, FALSE);
3041 tmp = gst_caps_intersect_full (pcopy, res, GST_CAPS_INTERSECT_FIRST);
3042 gst_caps_unref (pcopy);
3043 if (!gst_caps_is_empty (tmp))
3044 res = gst_caps_merge (tmp, res);
3046 gst_caps_unref (tmp);
3048 gst_caps_unref (peercaps);
3053 gst_h265_parse_event (GstBaseParse * parse, GstEvent * event)
3056 GstH265Parse *h265parse = GST_H265_PARSE (parse);
3058 switch (GST_EVENT_TYPE (event)) {
3059 case GST_EVENT_CUSTOM_DOWNSTREAM:
3061 GstClockTime timestamp, stream_time, running_time;
3062 gboolean all_headers;
3065 if (gst_video_event_is_force_key_unit (event)) {
3066 gst_video_event_parse_downstream_force_key_unit (event,
3067 ×tamp, &stream_time, &running_time, &all_headers, &count);
3069 GST_INFO_OBJECT (h265parse, "received downstream force key unit event, "
3070 "seqnum %d running_time %" GST_TIME_FORMAT
3071 " all_headers %d count %d", gst_event_get_seqnum (event),
3072 GST_TIME_ARGS (running_time), all_headers, count);
3073 if (h265parse->force_key_unit_event) {
3074 GST_INFO_OBJECT (h265parse, "ignoring force key unit event "
3075 "as one is already queued");
3077 h265parse->pending_key_unit_ts = running_time;
3078 gst_event_replace (&h265parse->force_key_unit_event, event);
3080 gst_event_unref (event);
3083 res = GST_BASE_PARSE_CLASS (parent_class)->sink_event (parse, event);
3088 case GST_EVENT_FLUSH_STOP:
3089 h265parse->push_codec = TRUE;
3090 res = GST_BASE_PARSE_CLASS (parent_class)->sink_event (parse, event);
3092 case GST_EVENT_SEGMENT:
3094 const GstSegment *segment = NULL;
3096 gst_event_parse_segment (event, &segment);
3098 h265parse->last_report = GST_CLOCK_TIME_NONE;
3100 if (segment->flags & GST_SEEK_FLAG_TRICKMODE_FORWARD_PREDICTED) {
3101 GST_DEBUG_OBJECT (h265parse, "Will discard bidirectional frames");
3102 h265parse->discard_bidirectional = TRUE;
3105 res = GST_BASE_PARSE_CLASS (parent_class)->sink_event (parse, event);
3109 res = GST_BASE_PARSE_CLASS (parent_class)->sink_event (parse, event);
3116 gst_h265_parse_src_event (GstBaseParse * parse, GstEvent * event)
3119 GstH265Parse *h265parse = GST_H265_PARSE (parse);
3121 switch (GST_EVENT_TYPE (event)) {
3122 case GST_EVENT_CUSTOM_UPSTREAM:
3124 GstClockTime running_time;
3125 gboolean all_headers;
3128 if (gst_video_event_is_force_key_unit (event)) {
3129 gst_video_event_parse_upstream_force_key_unit (event,
3130 &running_time, &all_headers, &count);
3132 GST_INFO_OBJECT (h265parse, "received upstream force-key-unit event, "
3133 "seqnum %d running_time %" GST_TIME_FORMAT
3134 " all_headers %d count %d", gst_event_get_seqnum (event),
3135 GST_TIME_ARGS (running_time), all_headers, count);
3138 h265parse->pending_key_unit_ts = running_time;
3139 gst_event_replace (&h265parse->force_key_unit_event, event);
3142 res = GST_BASE_PARSE_CLASS (parent_class)->src_event (parse, event);
3146 res = GST_BASE_PARSE_CLASS (parent_class)->src_event (parse, event);
3154 gst_h265_parse_set_property (GObject * object, guint prop_id,
3155 const GValue * value, GParamSpec * pspec)
3157 GstH265Parse *parse;
3158 parse = GST_H265_PARSE (object);
3161 case PROP_CONFIG_INTERVAL:
3162 parse->interval = g_value_get_int (value);
3165 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
3171 gst_h265_parse_get_property (GObject * object, guint prop_id, GValue * value,
3174 GstH265Parse *parse;
3175 parse = GST_H265_PARSE (object);
3178 case PROP_CONFIG_INTERVAL:
3179 g_value_set_int (value, parse->interval);
3182 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);