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,
119 gst_h265_parse_class_init (GstH265ParseClass * klass)
121 GObjectClass *gobject_class = (GObjectClass *) klass;
122 GstBaseParseClass *parse_class = GST_BASE_PARSE_CLASS (klass);
123 GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
125 GST_DEBUG_CATEGORY_INIT (h265_parse_debug, "h265parse", 0, "h265 parser");
127 gobject_class->finalize = gst_h265_parse_finalize;
128 gobject_class->set_property = gst_h265_parse_set_property;
129 gobject_class->get_property = gst_h265_parse_get_property;
131 g_object_class_install_property (gobject_class, PROP_CONFIG_INTERVAL,
132 g_param_spec_int ("config-interval",
133 "VPS SPS PPS Send Interval",
134 "Send VPS, SPS and PPS Insertion Interval in seconds (sprop parameter sets "
135 "will be multiplexed in the data stream when detected.) "
136 "(0 = disabled, -1 = send with every IDR frame)",
137 -1, 3600, DEFAULT_CONFIG_INTERVAL,
138 G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
139 /* Override BaseParse vfuncs */
140 parse_class->start = GST_DEBUG_FUNCPTR (gst_h265_parse_start);
141 parse_class->stop = GST_DEBUG_FUNCPTR (gst_h265_parse_stop);
142 parse_class->handle_frame = GST_DEBUG_FUNCPTR (gst_h265_parse_handle_frame);
143 parse_class->pre_push_frame =
144 GST_DEBUG_FUNCPTR (gst_h265_parse_pre_push_frame);
145 parse_class->set_sink_caps = GST_DEBUG_FUNCPTR (gst_h265_parse_set_caps);
146 parse_class->get_sink_caps = GST_DEBUG_FUNCPTR (gst_h265_parse_get_caps);
147 parse_class->sink_event = GST_DEBUG_FUNCPTR (gst_h265_parse_event);
148 parse_class->src_event = GST_DEBUG_FUNCPTR (gst_h265_parse_src_event);
150 gst_element_class_add_static_pad_template (gstelement_class, &srctemplate);
151 gst_element_class_add_static_pad_template (gstelement_class, &sinktemplate);
153 gst_element_class_set_static_metadata (gstelement_class, "H.265 parser",
154 "Codec/Parser/Converter/Video",
155 "Parses H.265 streams",
156 "Sreerenj Balachandran <sreerenj.balachandran@intel.com>");
160 gst_h265_parse_init (GstH265Parse * h265parse)
162 h265parse->frame_out = gst_adapter_new ();
163 gst_base_parse_set_pts_interpolation (GST_BASE_PARSE (h265parse), FALSE);
164 GST_PAD_SET_ACCEPT_INTERSECT (GST_BASE_PARSE_SINK_PAD (h265parse));
165 GST_PAD_SET_ACCEPT_TEMPLATE (GST_BASE_PARSE_SINK_PAD (h265parse));
170 gst_h265_parse_finalize (GObject * object)
172 GstH265Parse *h265parse = GST_H265_PARSE (object);
174 g_object_unref (h265parse->frame_out);
176 G_OBJECT_CLASS (parent_class)->finalize (object);
180 gst_h265_parse_reset_frame (GstH265Parse * h265parse)
182 GST_DEBUG_OBJECT (h265parse, "reset frame");
184 /* done parsing; reset state */
185 h265parse->current_off = -1;
187 h265parse->picture_start = FALSE;
188 h265parse->update_caps = FALSE;
189 h265parse->idr_pos = -1;
190 h265parse->sei_pos = -1;
191 h265parse->keyframe = FALSE;
192 h265parse->header = FALSE;
193 h265parse->have_vps_in_frame = FALSE;
194 h265parse->have_sps_in_frame = FALSE;
195 h265parse->have_pps_in_frame = FALSE;
196 gst_adapter_clear (h265parse->frame_out);
200 gst_h265_parse_reset_stream_info (GstH265Parse * h265parse)
204 h265parse->width = 0;
205 h265parse->height = 0;
206 h265parse->fps_num = 0;
207 h265parse->fps_den = 0;
208 h265parse->upstream_par_n = -1;
209 h265parse->upstream_par_d = -1;
210 h265parse->parsed_par_n = 0;
211 h265parse->parsed_par_n = 0;
212 h265parse->have_pps = FALSE;
213 h265parse->have_sps = FALSE;
214 h265parse->have_vps = FALSE;
216 h265parse->align = GST_H265_PARSE_ALIGN_NONE;
217 h265parse->format = GST_H265_PARSE_FORMAT_NONE;
219 h265parse->transform = FALSE;
220 h265parse->nal_length_size = 4;
221 h265parse->packetized = FALSE;
222 h265parse->push_codec = FALSE;
224 gst_buffer_replace (&h265parse->codec_data, NULL);
225 gst_buffer_replace (&h265parse->codec_data_in, NULL);
227 gst_h265_parse_reset_frame (h265parse);
229 for (i = 0; i < GST_H265_MAX_VPS_COUNT; i++)
230 gst_buffer_replace (&h265parse->vps_nals[i], NULL);
231 for (i = 0; i < GST_H265_MAX_SPS_COUNT; i++)
232 gst_buffer_replace (&h265parse->sps_nals[i], NULL);
233 for (i = 0; i < GST_H265_MAX_PPS_COUNT; i++)
234 gst_buffer_replace (&h265parse->pps_nals[i], NULL);
236 gst_video_mastering_display_info_init (&h265parse->mastering_display_info);
237 h265parse->mastering_display_info_state = GST_H265_PARSE_SEI_EXPIRED;
239 gst_video_content_light_level_init (&h265parse->content_light_level);
240 h265parse->content_light_level_state = GST_H265_PARSE_SEI_EXPIRED;
244 gst_h265_parse_reset (GstH265Parse * h265parse)
246 h265parse->last_report = GST_CLOCK_TIME_NONE;
248 h265parse->sent_codec_tag = FALSE;
250 h265parse->pending_key_unit_ts = GST_CLOCK_TIME_NONE;
251 gst_event_replace (&h265parse->force_key_unit_event, NULL);
253 h265parse->discont = FALSE;
255 gst_h265_parse_reset_stream_info (h265parse);
259 gst_h265_parse_start (GstBaseParse * parse)
261 GstH265Parse *h265parse = GST_H265_PARSE (parse);
263 GST_DEBUG_OBJECT (parse, "start");
264 gst_h265_parse_reset (h265parse);
266 h265parse->nalparser = gst_h265_parser_new ();
267 h265parse->state = 0;
269 gst_base_parse_set_min_frame_size (parse, 7);
275 gst_h265_parse_stop (GstBaseParse * parse)
277 GstH265Parse *h265parse = GST_H265_PARSE (parse);
279 GST_DEBUG_OBJECT (parse, "stop");
280 gst_h265_parse_reset (h265parse);
282 gst_h265_parser_free (h265parse->nalparser);
288 gst_h265_parse_get_string (GstH265Parse * parse, gboolean format, gint code)
292 case GST_H265_PARSE_FORMAT_HVC1:
294 case GST_H265_PARSE_FORMAT_HEV1:
296 case GST_H265_PARSE_FORMAT_BYTE:
297 return "byte-stream";
303 case GST_H265_PARSE_ALIGN_NAL:
305 case GST_H265_PARSE_ALIGN_AU:
314 gst_h265_parse_format_from_caps (GstCaps * caps, guint * format, guint * align)
316 g_return_if_fail (gst_caps_is_fixed (caps));
318 GST_DEBUG ("parsing caps: %" GST_PTR_FORMAT, caps);
321 *format = GST_H265_PARSE_FORMAT_NONE;
324 *align = GST_H265_PARSE_ALIGN_NONE;
326 if (caps && gst_caps_get_size (caps) > 0) {
327 GstStructure *s = gst_caps_get_structure (caps, 0);
328 const gchar *str = NULL;
331 if ((str = gst_structure_get_string (s, "stream-format"))) {
332 if (strcmp (str, "hvc1") == 0)
333 *format = GST_H265_PARSE_FORMAT_HVC1;
334 else if (strcmp (str, "hev1") == 0)
335 *format = GST_H265_PARSE_FORMAT_HEV1;
336 else if (strcmp (str, "byte-stream") == 0)
337 *format = GST_H265_PARSE_FORMAT_BYTE;
342 if ((str = gst_structure_get_string (s, "alignment"))) {
343 if (strcmp (str, "au") == 0)
344 *align = GST_H265_PARSE_ALIGN_AU;
345 else if (strcmp (str, "nal") == 0)
346 *align = GST_H265_PARSE_ALIGN_NAL;
352 /* check downstream caps to configure format and alignment */
354 gst_h265_parse_negotiate (GstH265Parse * h265parse, gint in_format,
358 guint format = GST_H265_PARSE_FORMAT_NONE;
359 guint align = GST_H265_PARSE_ALIGN_NONE;
361 g_return_if_fail ((in_caps == NULL) || gst_caps_is_fixed (in_caps));
363 caps = gst_pad_get_allowed_caps (GST_BASE_PARSE_SRC_PAD (h265parse));
364 GST_DEBUG_OBJECT (h265parse, "allowed caps: %" GST_PTR_FORMAT, caps);
366 /* concentrate on leading structure, since decodebin parser
367 * capsfilter always includes parser template caps */
369 caps = gst_caps_truncate (caps);
370 GST_DEBUG_OBJECT (h265parse, "negotiating with caps: %" GST_PTR_FORMAT,
374 if (in_caps && caps) {
375 if (gst_caps_can_intersect (in_caps, caps)) {
376 GST_DEBUG_OBJECT (h265parse, "downstream accepts upstream caps");
377 gst_h265_parse_format_from_caps (in_caps, &format, &align);
378 gst_caps_unref (caps);
383 /* FIXME We could fail the negotiation immediatly if caps are empty */
384 if (caps && !gst_caps_is_empty (caps)) {
385 /* fixate to avoid ambiguity with lists when parsing */
386 caps = gst_caps_fixate (caps);
387 gst_h265_parse_format_from_caps (caps, &format, &align);
392 format = GST_H265_PARSE_FORMAT_BYTE;
394 align = GST_H265_PARSE_ALIGN_AU;
396 GST_DEBUG_OBJECT (h265parse, "selected format %s, alignment %s",
397 gst_h265_parse_get_string (h265parse, TRUE, format),
398 gst_h265_parse_get_string (h265parse, FALSE, align));
400 h265parse->format = format;
401 h265parse->align = align;
403 h265parse->transform = in_format != h265parse->format ||
404 align == GST_H265_PARSE_ALIGN_AU;
407 gst_caps_unref (caps);
411 gst_h265_parse_wrap_nal (GstH265Parse * h265parse, guint format, guint8 * data,
415 guint nl = h265parse->nal_length_size;
418 GST_DEBUG_OBJECT (h265parse, "nal length %d", size);
420 buf = gst_buffer_new_allocate (NULL, 4 + size, NULL);
421 if (format == GST_H265_PARSE_FORMAT_HVC1
422 || format == GST_H265_PARSE_FORMAT_HEV1) {
423 tmp = GUINT32_TO_BE (size << (32 - 8 * nl));
425 /* HACK: nl should always be 4 here, otherwise this won't work.
426 * There are legit cases where nl in hevc stream is 2, but byte-stream
427 * SC is still always 4 bytes. */
429 tmp = GUINT32_TO_BE (1);
432 gst_buffer_fill (buf, 0, &tmp, sizeof (guint32));
433 gst_buffer_fill (buf, nl, data, size);
434 gst_buffer_set_size (buf, size + nl);
440 gst_h265_parser_store_nal (GstH265Parse * h265parse, guint id,
441 GstH265NalUnitType naltype, GstH265NalUnit * nalu)
443 GstBuffer *buf, **store;
444 guint size = nalu->size, store_size;
446 if (naltype == GST_H265_NAL_VPS) {
447 store_size = GST_H265_MAX_VPS_COUNT;
448 store = h265parse->vps_nals;
449 GST_DEBUG_OBJECT (h265parse, "storing vps %u", id);
450 } else if (naltype == GST_H265_NAL_SPS) {
451 store_size = GST_H265_MAX_SPS_COUNT;
452 store = h265parse->sps_nals;
453 GST_DEBUG_OBJECT (h265parse, "storing sps %u", id);
454 } else if (naltype == GST_H265_NAL_PPS) {
455 store_size = GST_H265_MAX_PPS_COUNT;
456 store = h265parse->pps_nals;
457 GST_DEBUG_OBJECT (h265parse, "storing pps %u", id);
461 if (id >= store_size) {
462 GST_DEBUG_OBJECT (h265parse, "unable to store nal, id out-of-range %d", id);
466 buf = gst_buffer_new_allocate (NULL, size, NULL);
467 gst_buffer_fill (buf, 0, nalu->data + nalu->offset, size);
469 /* Indicate that buffer contain a header needed for decoding */
470 if (naltype >= GST_H265_NAL_VPS && naltype <= GST_H265_NAL_PPS)
471 GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_HEADER);
474 gst_buffer_unref (store[id]);
479 #ifndef GST_DISABLE_GST_DEBUG
480 static const gchar *nal_names[] = {
525 _nal_name (GstH265NalUnitType nal_type)
527 if (nal_type <= GST_H265_NAL_SUFFIX_SEI)
528 return nal_names[nal_type];
534 gst_h265_parse_process_sei (GstH265Parse * h265parse, GstH265NalUnit * nalu)
536 GstH265SEIMessage sei;
537 GstH265Parser *nalparser = h265parse->nalparser;
538 GstH265ParserResult pres;
542 pres = gst_h265_parser_parse_sei (nalparser, nalu, &messages);
543 if (pres != GST_H265_PARSER_OK)
544 GST_WARNING_OBJECT (h265parse, "failed to parse one or more SEI message");
546 /* Even if pres != GST_H265_PARSER_OK, some message could have been parsed and
547 * stored in messages.
549 for (i = 0; i < messages->len; i++) {
550 sei = g_array_index (messages, GstH265SEIMessage, i);
551 switch (sei.payloadType) {
552 case GST_H265_SEI_RECOVERY_POINT:
553 GST_LOG_OBJECT (h265parse, "recovery point found: %u %u %u",
554 sei.payload.recovery_point.recovery_poc_cnt,
555 sei.payload.recovery_point.exact_match_flag,
556 sei.payload.recovery_point.broken_link_flag);
557 h265parse->keyframe = TRUE;
559 case GST_H265_SEI_TIME_CODE:
560 memcpy (&h265parse->time_code, &sei.payload.time_code,
561 sizeof (GstH265TimeCode));
563 case GST_H265_SEI_PIC_TIMING:
564 h265parse->sei_pic_struct = sei.payload.pic_timing.pic_struct;
566 case GST_H265_SEI_BUF_PERIOD:
569 case GST_H265_SEI_MASTERING_DISPLAY_COLOUR_VOLUME:
571 /* Precision defined by spec.
572 * See D.3.28 Mastering display colour volume SEI message semantics */
573 const guint chroma_den = 50000;
574 const guint luma_den = 10000;
575 GstVideoMasteringDisplayInfo minfo;
578 sei.payload.mastering_display_colour_volume.display_primaries_x[0];
580 sei.payload.mastering_display_colour_volume.display_primaries_y[0];
582 sei.payload.mastering_display_colour_volume.display_primaries_x[1];
584 sei.payload.mastering_display_colour_volume.display_primaries_y[1];
586 sei.payload.mastering_display_colour_volume.display_primaries_x[2];
588 sei.payload.mastering_display_colour_volume.display_primaries_x[2];
589 minfo.Wx_n = sei.payload.mastering_display_colour_volume.white_point_x;
590 minfo.Wy_n = sei.payload.mastering_display_colour_volume.white_point_y;
593 mastering_display_colour_volume.max_display_mastering_luminance;
596 mastering_display_colour_volume.min_display_mastering_luminance;
598 minfo.Gx_d = minfo.Gy_d = minfo.Bx_d = minfo.By_d =
599 minfo.Rx_d = minfo.Ry_d = minfo.Wx_d = minfo.Wy_d = chroma_den;
601 minfo.max_luma_d = minfo.min_luma_d = luma_den;
603 GST_LOG_OBJECT (h265parse, "mastering display info found");
604 GST_LOG_OBJECT (h265parse, "\tRed (%u/%u, %u/%u)", minfo.Rx_n,
605 minfo.Rx_d, minfo.Ry_n, minfo.Ry_d);
606 GST_LOG_OBJECT (h265parse, "\tGreen(%u/%u, %u/%u)", minfo.Gx_n,
607 minfo.Gx_d, minfo.Gy_n, minfo.Gy_d);
608 GST_LOG_OBJECT (h265parse, "\tBlue (%u/%u, %u/%u)", minfo.Bx_n,
609 minfo.Bx_d, minfo.By_n, minfo.By_d);
610 GST_LOG_OBJECT (h265parse, "\tWhite(%u/%u, %u/%u)", minfo.Wx_n,
611 minfo.Wx_d, minfo.Wy_n, minfo.Wy_d);
612 GST_LOG_OBJECT (h265parse,
613 "\tmax_luminance:(%u/%u), min_luminance:(%u/%u)",
614 minfo.max_luma_n, minfo.max_luma_d, minfo.min_luma_n,
617 if (h265parse->mastering_display_info_state ==
618 GST_H265_PARSE_SEI_EXPIRED) {
619 h265parse->update_caps = TRUE;
620 } else if (!gst_video_mastering_display_info_is_equal
621 (&h265parse->mastering_display_info, &minfo)) {
622 h265parse->update_caps = TRUE;
625 h265parse->mastering_display_info_state = GST_H265_PARSE_SEI_PARSED;
626 h265parse->mastering_display_info = minfo;
630 case GST_H265_SEI_CONTENT_LIGHT_LEVEL:
632 GstVideoContentLightLevel cll;
634 cll.maxCLL_n = sei.payload.content_light_level.max_content_light_level;
636 sei.payload.content_light_level.max_pic_average_light_level;
638 cll.maxCLL_d = cll.maxFALL_d = 1;
640 GST_LOG_OBJECT (h265parse, "content light level found");
641 GST_LOG_OBJECT (h265parse,
642 "\tmaxCLL:(%u/%u), maxFALL:(%u/%u)", cll.maxCLL_n, cll.maxCLL_d,
643 cll.maxFALL_n, cll.maxFALL_d);
645 if (h265parse->content_light_level_state == GST_H265_PARSE_SEI_EXPIRED) {
646 h265parse->update_caps = TRUE;
647 } else if (gst_util_fraction_compare (cll.maxCLL_n, cll.maxCLL_d,
648 h265parse->content_light_level.maxCLL_n,
649 h265parse->content_light_level.maxCLL_d)
650 || gst_util_fraction_compare (cll.maxFALL_n, cll.maxFALL_d,
651 h265parse->content_light_level.maxFALL_n,
652 h265parse->content_light_level.maxFALL_d)) {
653 h265parse->update_caps = TRUE;
656 h265parse->content_light_level_state = GST_H265_PARSE_SEI_PARSED;
657 h265parse->content_light_level = cll;
665 g_array_free (messages, TRUE);
668 /* caller guarantees 2 bytes of nal payload */
670 gst_h265_parse_process_nal (GstH265Parse * h265parse, GstH265NalUnit * nalu)
672 GstH265PPS pps = { 0, };
673 GstH265SPS sps = { 0, };
674 GstH265VPS vps = { 0, };
676 GstH265Parser *nalparser = h265parse->nalparser;
677 GstH265ParserResult pres = GST_H265_PARSER_ERROR;
679 /* nothing to do for broken input */
680 if (G_UNLIKELY (nalu->size < 2)) {
681 GST_DEBUG_OBJECT (h265parse, "not processing nal size %u", nalu->size);
685 /* we have a peek as well */
686 nal_type = nalu->type;
688 GST_DEBUG_OBJECT (h265parse, "processing nal of type %u %s, size %u",
689 nal_type, _nal_name (nal_type), nalu->size);
691 case GST_H265_NAL_VPS:
692 /* It is not mandatory to have VPS in the stream. But it might
693 * be needed for other extensions like svc */
694 pres = gst_h265_parser_parse_vps (nalparser, nalu, &vps);
695 if (pres != GST_H265_PARSER_OK) {
696 GST_WARNING_OBJECT (h265parse, "failed to parse VPS");
700 GST_DEBUG_OBJECT (h265parse, "triggering src caps check");
701 h265parse->update_caps = TRUE;
702 h265parse->have_vps = TRUE;
703 h265parse->have_vps_in_frame = TRUE;
704 if (h265parse->push_codec && h265parse->have_pps) {
705 /* VPS/SPS/PPS found in stream before the first pre_push_frame, no need
706 * to forcibly push at start */
707 GST_INFO_OBJECT (h265parse, "have VPS/SPS/PPS in stream");
708 h265parse->push_codec = FALSE;
709 h265parse->have_vps = FALSE;
710 h265parse->have_sps = FALSE;
711 h265parse->have_pps = FALSE;
714 gst_h265_parser_store_nal (h265parse, vps.id, nal_type, nalu);
715 h265parse->header |= TRUE;
717 case GST_H265_NAL_SPS:
718 /* reset state, everything else is obsolete */
719 h265parse->state = 0;
721 pres = gst_h265_parser_parse_sps (nalparser, nalu, &sps, TRUE);
724 /* arranged for a fallback sps.id, so use that one and only warn */
725 if (pres != GST_H265_PARSER_OK) {
726 /* try to not parse VUI */
727 pres = gst_h265_parser_parse_sps (nalparser, nalu, &sps, FALSE);
728 if (pres != GST_H265_PARSER_OK) {
729 GST_WARNING_OBJECT (h265parse, "failed to parse SPS:");
730 h265parse->state |= GST_H265_PARSE_STATE_GOT_SPS;
731 h265parse->header |= TRUE;
734 GST_WARNING_OBJECT (h265parse,
735 "failed to parse VUI of SPS, ignore VUI");
738 GST_DEBUG_OBJECT (h265parse, "triggering src caps check");
739 h265parse->update_caps = TRUE;
740 h265parse->have_sps = TRUE;
741 h265parse->have_sps_in_frame = TRUE;
742 if (h265parse->push_codec && h265parse->have_pps) {
743 /* SPS and PPS found in stream before the first pre_push_frame, no need
744 * to forcibly push at start */
745 GST_INFO_OBJECT (h265parse, "have SPS/PPS in stream");
746 h265parse->push_codec = FALSE;
747 h265parse->have_sps = FALSE;
748 h265parse->have_pps = FALSE;
751 gst_h265_parser_store_nal (h265parse, sps.id, nal_type, nalu);
752 h265parse->header |= TRUE;
753 h265parse->state |= GST_H265_PARSE_STATE_GOT_SPS;
755 case GST_H265_NAL_PPS:
756 /* expected state: got-sps */
757 h265parse->state &= GST_H265_PARSE_STATE_GOT_SPS;
758 if (!GST_H265_PARSE_STATE_VALID (h265parse, GST_H265_PARSE_STATE_GOT_SPS))
761 pres = gst_h265_parser_parse_pps (nalparser, nalu, &pps);
764 /* arranged for a fallback pps.id, so use that one and only warn */
765 if (pres != GST_H265_PARSER_OK) {
766 GST_WARNING_OBJECT (h265parse, "failed to parse PPS:");
767 if (pres != GST_H265_PARSER_BROKEN_LINK)
771 /* parameters might have changed, force caps check */
772 if (!h265parse->have_pps) {
773 GST_DEBUG_OBJECT (h265parse, "triggering src caps check");
774 h265parse->update_caps = TRUE;
776 h265parse->have_pps = TRUE;
777 h265parse->have_pps_in_frame = TRUE;
778 if (h265parse->push_codec && h265parse->have_sps) {
779 /* SPS and PPS found in stream before the first pre_push_frame, no need
780 * to forcibly push at start */
781 GST_INFO_OBJECT (h265parse, "have SPS/PPS in stream");
782 h265parse->push_codec = FALSE;
783 h265parse->have_sps = FALSE;
784 h265parse->have_pps = FALSE;
787 gst_h265_parser_store_nal (h265parse, pps.id, nal_type, nalu);
788 h265parse->header |= TRUE;
789 h265parse->state |= GST_H265_PARSE_STATE_GOT_PPS;
791 case GST_H265_NAL_PREFIX_SEI:
792 case GST_H265_NAL_SUFFIX_SEI:
793 /* expected state: got-sps */
794 if (!GST_H265_PARSE_STATE_VALID (h265parse, GST_H265_PARSE_STATE_GOT_SPS))
797 h265parse->header |= TRUE;
799 gst_h265_parse_process_sei (h265parse, nalu);
802 if (h265parse->sei_pos == -1) {
803 if (h265parse->transform)
804 h265parse->sei_pos = gst_adapter_available (h265parse->frame_out);
806 h265parse->sei_pos = nalu->sc_offset;
807 GST_DEBUG_OBJECT (h265parse, "marking SEI in frame at offset %d",
812 case GST_H265_NAL_SLICE_TRAIL_N:
813 case GST_H265_NAL_SLICE_TRAIL_R:
814 case GST_H265_NAL_SLICE_TSA_N:
815 case GST_H265_NAL_SLICE_TSA_R:
816 case GST_H265_NAL_SLICE_STSA_N:
817 case GST_H265_NAL_SLICE_STSA_R:
818 case GST_H265_NAL_SLICE_RADL_N:
819 case GST_H265_NAL_SLICE_RADL_R:
820 case GST_H265_NAL_SLICE_RASL_N:
821 case GST_H265_NAL_SLICE_RASL_R:
822 case GST_H265_NAL_SLICE_BLA_W_LP:
823 case GST_H265_NAL_SLICE_BLA_W_RADL:
824 case GST_H265_NAL_SLICE_BLA_N_LP:
825 case GST_H265_NAL_SLICE_IDR_W_RADL:
826 case GST_H265_NAL_SLICE_IDR_N_LP:
827 case GST_H265_NAL_SLICE_CRA_NUT:
829 GstH265SliceHdr slice;
831 gboolean no_rasl_output_flag = FALSE;
833 /* expected state: got-sps|got-pps (valid picture headers) */
834 h265parse->state &= GST_H265_PARSE_STATE_VALID_PICTURE_HEADERS;
835 if (!GST_H265_PARSE_STATE_VALID (h265parse,
836 GST_H265_PARSE_STATE_VALID_PICTURE_HEADERS))
839 pres = gst_h265_parser_parse_slice_hdr (nalparser, nalu, &slice);
841 if (pres == GST_H265_PARSER_OK) {
842 if (GST_H265_IS_I_SLICE (&slice))
843 h265parse->keyframe |= TRUE;
845 h265parse->state |= GST_H265_PARSE_STATE_GOT_SLICE;
847 if (slice.first_slice_segment_in_pic_flag == 1)
848 GST_DEBUG_OBJECT (h265parse,
849 "frame start, first_slice_segment_in_pic_flag = 1");
851 GST_DEBUG_OBJECT (h265parse,
852 "parse result %d, first slice_segment: %u, slice type: %u",
853 pres, slice.first_slice_segment_in_pic_flag, slice.type);
855 gst_h265_slice_hdr_free (&slice);
857 /* FIXME: NoRaslOutputFlag can be equal to 1 for CRA if
858 * 1) the first AU in bitstream is CRA
859 * 2) or the first AU following EOS nal is CRA
860 * 3) or it has HandleCraAsBlaFlag equal to 1 */
861 if (nal_type == GST_H265_NAL_SLICE_IDR_W_RADL ||
862 nal_type == GST_H265_NAL_SLICE_IDR_N_LP) {
863 /* NoRaslOutputFlag is equal to 1 for each IDR */
864 no_rasl_output_flag = TRUE;
865 } else if (nal_type == GST_H265_NAL_SLICE_BLA_W_LP ||
866 nal_type == GST_H265_NAL_SLICE_BLA_W_RADL ||
867 nal_type == GST_H265_NAL_SLICE_BLA_N_LP) {
868 /* NoRaslOutputFlag is equal to 1 for each BLA */
869 no_rasl_output_flag = TRUE;
872 is_irap = ((nal_type >= GST_H265_NAL_SLICE_BLA_W_LP)
873 && (nal_type <= GST_H265_NAL_SLICE_CRA_NUT)) ? TRUE : FALSE;
875 if (h265parse->mastering_display_info_state != GST_H265_PARSE_SEI_EXPIRED
876 && no_rasl_output_flag && is_irap)
877 h265parse->mastering_display_info_state--;
879 if (h265parse->content_light_level_state != GST_H265_PARSE_SEI_EXPIRED &&
880 no_rasl_output_flag && is_irap)
881 h265parse->content_light_level_state--;
883 if (G_LIKELY (!is_irap && !h265parse->push_codec))
886 /* if we need to sneak codec NALs into the stream,
887 * this is a good place, so fake it as IDR
888 * (which should be at start anyway) */
889 /* mark where config needs to go if interval expired */
890 /* mind replacement buffer if applicable */
891 if (h265parse->idr_pos == -1) {
892 if (h265parse->transform)
893 h265parse->idr_pos = gst_adapter_available (h265parse->frame_out);
895 h265parse->idr_pos = nalu->sc_offset;
896 GST_DEBUG_OBJECT (h265parse, "marking IDR in frame at offset %d",
899 /* if SEI preceeds (faked) IDR, then we have to insert config there */
900 if (h265parse->sei_pos >= 0 && h265parse->idr_pos > h265parse->sei_pos) {
901 h265parse->idr_pos = h265parse->sei_pos;
902 GST_DEBUG_OBJECT (h265parse, "moved IDR mark to SEI position %d",
907 case GST_H265_NAL_AUD:
908 /* Just accumulate AU Delimiter, whether it's before SPS or not */
909 pres = gst_h265_parser_parse_nal (nalparser, nalu);
910 if (pres != GST_H265_PARSER_OK)
914 /* drop anything before the initial SPS */
915 if (!GST_H265_PARSE_STATE_VALID (h265parse, GST_H265_PARSE_STATE_GOT_SPS))
918 pres = gst_h265_parser_parse_nal (nalparser, nalu);
919 if (pres != GST_H265_PARSER_OK)
924 /* if HEVC output needed, collect properly prefixed nal in adapter,
925 * and use that to replace outgoing buffer data later on */
926 if (h265parse->transform) {
929 GST_LOG_OBJECT (h265parse, "collecting NAL in HEVC frame");
930 buf = gst_h265_parse_wrap_nal (h265parse, h265parse->format,
931 nalu->data + nalu->offset, nalu->size);
932 gst_adapter_push (h265parse->frame_out, buf);
938 /* caller guarantees at least 3 bytes of nal payload for each nal
939 * returns TRUE if next_nal indicates that nal terminates an AU */
940 static inline gboolean
941 gst_h265_parse_collect_nal (GstH265Parse * h265parse, const guint8 * data,
942 guint size, GstH265NalUnit * nalu)
945 GstH265ParserResult parse_res;
946 GstH265NalUnitType nal_type = nalu->type;
947 GstH265NalUnit nnalu;
949 GST_DEBUG_OBJECT (h265parse, "parsing collected nal");
950 parse_res = gst_h265_parser_identify_nalu_unchecked (h265parse->nalparser,
951 data, nalu->offset + nalu->size, size, &nnalu);
953 if (parse_res != GST_H265_PARSER_OK)
956 /* determine if AU complete */
957 GST_LOG_OBJECT (h265parse, "nal type: %d %s", nal_type, _nal_name (nal_type));
958 /* coded slice NAL starts a picture,
959 * i.e. other types become aggregated in front of it */
960 h265parse->picture_start |= ((nal_type >= GST_H265_NAL_SLICE_TRAIL_N
961 && nal_type <= GST_H265_NAL_SLICE_RASL_R)
962 || (nal_type >= GST_H265_NAL_SLICE_BLA_W_LP
963 && nal_type <= RESERVED_IRAP_NAL_TYPE_MAX));
965 /* consider a coded slices (IRAP or not) to start a picture,
966 * (so ending the previous one) if first_slice_segment_in_pic_flag == 1*/
967 nal_type = nnalu.type;
968 complete = h265parse->picture_start && ((nal_type >= GST_H265_NAL_VPS
969 && nal_type <= GST_H265_NAL_AUD)
970 || nal_type == GST_H265_NAL_PREFIX_SEI || (nal_type >= 41
971 && nal_type <= 44) || (nal_type >= 48 && nal_type <= 55));
973 GST_LOG_OBJECT (h265parse, "next nal type: %d %s", nal_type,
974 _nal_name (nal_type));
976 /* Any VCL Nal unit with first_slice_segment_in_pic_flag == 1 considered start of frame */
977 complete |= h265parse->picture_start
978 && (((nal_type >= GST_H265_NAL_SLICE_TRAIL_N
979 && nal_type <= GST_H265_NAL_SLICE_RASL_R)
980 || (nal_type >= GST_H265_NAL_SLICE_BLA_W_LP
981 && nal_type <= RESERVED_IRAP_NAL_TYPE_MAX))
982 && (nnalu.data[nnalu.offset + 2] & 0x80));
984 GST_LOG_OBJECT (h265parse, "au complete: %d", complete);
989 gst_h265_parse_handle_frame_packetized (GstBaseParse * parse,
990 GstBaseParseFrame * frame)
992 GstH265Parse *h265parse = GST_H265_PARSE (parse);
993 GstBuffer *buffer = frame->buffer;
994 GstFlowReturn ret = GST_FLOW_OK;
995 GstH265ParserResult parse_res;
997 const guint nl = h265parse->nal_length_size;
1001 if (nl < 1 || nl > 4) {
1002 GST_DEBUG_OBJECT (h265parse, "insufficient data to split input");
1003 return GST_FLOW_NOT_NEGOTIATED;
1006 /* need to save buffer from invalidation upon _finish_frame */
1007 if (h265parse->split_packetized)
1008 buffer = gst_buffer_copy (frame->buffer);
1010 gst_buffer_map (buffer, &map, GST_MAP_READ);
1014 GST_LOG_OBJECT (h265parse,
1015 "processing packet buffer of size %" G_GSIZE_FORMAT, map.size);
1017 parse_res = gst_h265_parser_identify_nalu_hevc (h265parse->nalparser,
1018 map.data, 0, map.size, nl, &nalu);
1020 while (parse_res == GST_H265_PARSER_OK) {
1021 GST_DEBUG_OBJECT (h265parse, "HEVC nal offset %d", nalu.offset + nalu.size);
1023 /* either way, have a look at it */
1024 gst_h265_parse_process_nal (h265parse, &nalu);
1026 /* dispatch per NALU if needed */
1027 if (h265parse->split_packetized) {
1028 GstBaseParseFrame tmp_frame;
1030 gst_base_parse_frame_init (&tmp_frame);
1031 tmp_frame.flags |= frame->flags;
1032 tmp_frame.offset = frame->offset;
1033 tmp_frame.overhead = frame->overhead;
1034 tmp_frame.buffer = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_ALL,
1035 nalu.offset, nalu.size);
1037 /* note we don't need to come up with a sub-buffer, since
1038 * subsequent code only considers input buffer's metadata.
1039 * Real data is either taken from input by baseclass or
1040 * a replacement output buffer is provided anyway. */
1041 gst_h265_parse_parse_frame (parse, &tmp_frame);
1042 ret = gst_base_parse_finish_frame (parse, &tmp_frame, nl + nalu.size);
1043 left -= nl + nalu.size;
1046 parse_res = gst_h265_parser_identify_nalu_hevc (h265parse->nalparser,
1047 map.data, nalu.offset + nalu.size, map.size, nl, &nalu);
1050 gst_buffer_unmap (buffer, &map);
1052 if (!h265parse->split_packetized) {
1053 gst_h265_parse_parse_frame (parse, frame);
1054 ret = gst_base_parse_finish_frame (parse, frame, map.size);
1056 gst_buffer_unref (buffer);
1057 if (G_UNLIKELY (left)) {
1058 /* should not be happening for nice HEVC */
1059 GST_WARNING_OBJECT (parse, "skipping leftover HEVC data %d", left);
1060 frame->flags |= GST_BASE_PARSE_FRAME_FLAG_DROP;
1061 ret = gst_base_parse_finish_frame (parse, frame, map.size);
1065 if (parse_res == GST_H265_PARSER_NO_NAL_END ||
1066 parse_res == GST_H265_PARSER_BROKEN_DATA) {
1068 if (h265parse->split_packetized) {
1069 GST_ELEMENT_ERROR (h265parse, STREAM, FAILED, (NULL),
1070 ("invalid HEVC input data"));
1072 return GST_FLOW_ERROR;
1074 /* do not meddle to much in this case */
1075 GST_DEBUG_OBJECT (h265parse, "parsing packet failed");
1082 static GstFlowReturn
1083 gst_h265_parse_handle_frame (GstBaseParse * parse,
1084 GstBaseParseFrame * frame, gint * skipsize)
1086 GstH265Parse *h265parse = GST_H265_PARSE (parse);
1087 GstBuffer *buffer = frame->buffer;
1091 gint current_off = 0;
1092 gboolean drain, nonext;
1093 GstH265Parser *nalparser = h265parse->nalparser;
1094 GstH265NalUnit nalu;
1095 GstH265ParserResult pres;
1098 if (G_UNLIKELY (GST_BUFFER_FLAG_IS_SET (frame->buffer,
1099 GST_BUFFER_FLAG_DISCONT))) {
1100 h265parse->discont = TRUE;
1103 /* delegate in packetized case, no skipping should be needed */
1104 if (h265parse->packetized)
1105 return gst_h265_parse_handle_frame_packetized (parse, frame);
1107 gst_buffer_map (buffer, &map, GST_MAP_READ);
1111 /* expect at least 3 bytes startcode == sc, and 3 bytes NALU payload */
1112 if (G_UNLIKELY (size < 6)) {
1113 gst_buffer_unmap (buffer, &map);
1118 /* need to configure aggregation */
1119 if (G_UNLIKELY (h265parse->format == GST_H265_PARSE_FORMAT_NONE))
1120 gst_h265_parse_negotiate (h265parse, GST_H265_PARSE_FORMAT_BYTE, NULL);
1122 /* avoid stale cached parsing state */
1123 if (frame->flags & GST_BASE_PARSE_FRAME_FLAG_NEW_FRAME) {
1124 GST_LOG_OBJECT (h265parse, "parsing new frame");
1125 gst_h265_parse_reset_frame (h265parse);
1127 GST_LOG_OBJECT (h265parse, "resuming frame parsing");
1130 drain = GST_BASE_PARSE_DRAINING (parse);
1133 current_off = h265parse->current_off;
1134 if (current_off < 0)
1136 g_assert (current_off < size);
1137 GST_DEBUG_OBJECT (h265parse, "last parse position %d", current_off);
1139 /* check for initial skip */
1140 if (h265parse->current_off == -1) {
1142 gst_h265_parser_identify_nalu_unchecked (nalparser, data, current_off,
1145 case GST_H265_PARSER_OK:
1146 if (nalu.sc_offset > 0) {
1147 *skipsize = nalu.sc_offset;
1151 case GST_H265_PARSER_NO_NAL:
1152 *skipsize = size - 3;
1155 /* should not really occur either */
1156 GST_ELEMENT_ERROR (h265parse, STREAM, FORMAT,
1157 ("Error parsing H.265 stream"), ("Invalid H.265 stream"));
1158 goto invalid_stream;
1164 gst_h265_parser_identify_nalu (nalparser, data, current_off, size,
1168 case GST_H265_PARSER_OK:
1169 GST_DEBUG_OBJECT (h265parse, "complete nal (offset, size): (%u, %u) ",
1170 nalu.offset, nalu.size);
1172 case GST_H265_PARSER_NO_NAL_END:
1173 GST_DEBUG_OBJECT (h265parse, "not a complete nal found at offset %u",
1175 /* if draining, accept it as complete nal */
1178 nalu.size = size - nalu.offset;
1179 GST_DEBUG_OBJECT (h265parse, "draining, accepting with size %u",
1181 /* if it's not too short at least */
1186 /* otherwise need more */
1188 case GST_H265_PARSER_BROKEN_LINK:
1189 GST_ELEMENT_ERROR (h265parse, STREAM, FORMAT,
1190 ("Error parsing H.265 stream"),
1191 ("The link to structure needed for the parsing couldn't be found"));
1192 goto invalid_stream;
1193 case GST_H265_PARSER_ERROR:
1194 /* should not really occur either */
1195 GST_ELEMENT_ERROR (h265parse, STREAM, FORMAT,
1196 ("Error parsing H.265 stream"), ("Invalid H.265 stream"));
1197 goto invalid_stream;
1198 case GST_H265_PARSER_NO_NAL:
1199 GST_ELEMENT_ERROR (h265parse, STREAM, FORMAT,
1200 ("Error parsing H.265 stream"), ("No H.265 NAL unit found"));
1201 goto invalid_stream;
1202 case GST_H265_PARSER_BROKEN_DATA:
1203 GST_WARNING_OBJECT (h265parse, "input stream is corrupt; "
1204 "it contains a NAL unit of length %u", nalu.size);
1206 /* broken nal at start -> arrange to skip it,
1207 * otherwise have it terminate current au
1208 * (and so it will be skipped on next frame round) */
1209 if (current_off == 0) {
1210 GST_DEBUG_OBJECT (h265parse, "skipping broken nal");
1211 *skipsize = nalu.offset;
1214 GST_DEBUG_OBJECT (h265parse, "terminating au");
1216 nalu.offset = nalu.sc_offset;
1220 g_assert_not_reached ();
1224 GST_DEBUG_OBJECT (h265parse, "%p complete nal found. Off: %u, Size: %u",
1225 data, nalu.offset, nalu.size);
1227 /* simulate no next nal if none needed */
1228 nonext = nonext || (h265parse->align == GST_H265_PARSE_ALIGN_NAL);
1231 if (nalu.offset + nalu.size + 5 + 2 > size) {
1232 GST_DEBUG_OBJECT (h265parse, "not enough data for next NALU");
1234 GST_DEBUG_OBJECT (h265parse, "but draining anyway");
1242 if (!gst_h265_parse_process_nal (h265parse, &nalu)) {
1243 GST_WARNING_OBJECT (h265parse,
1244 "broken/invalid nal Type: %d %s, Size: %u will be dropped",
1245 nalu.type, _nal_name (nalu.type), nalu.size);
1246 *skipsize = nalu.size;
1253 /* if no next nal, we know it's complete here */
1254 if (gst_h265_parse_collect_nal (h265parse, data, size, &nalu))
1257 GST_DEBUG_OBJECT (h265parse, "Looking for more");
1258 current_off = nalu.offset + nalu.size;
1262 framesize = nalu.offset + nalu.size;
1264 gst_buffer_unmap (buffer, &map);
1266 gst_h265_parse_parse_frame (parse, frame);
1268 return gst_base_parse_finish_frame (parse, frame, framesize);
1273 /* Restart parsing from here next time */
1274 if (current_off > 0)
1275 h265parse->current_off = current_off;
1279 gst_buffer_unmap (buffer, &map);
1283 GST_DEBUG_OBJECT (h265parse, "skipping %d", *skipsize);
1284 /* If we are collecting access units, we need to preserve the initial
1285 * config headers (SPS, PPS et al.) and only reset the frame if another
1286 * slice NAL was received. This means that broken pictures are discarded */
1287 if (h265parse->align != GST_H265_PARSE_ALIGN_AU ||
1288 !(h265parse->state & GST_H265_PARSE_STATE_VALID_PICTURE_HEADERS) ||
1289 (h265parse->state & GST_H265_PARSE_STATE_GOT_SLICE))
1290 gst_h265_parse_reset_frame (h265parse);
1294 gst_buffer_unmap (buffer, &map);
1295 return GST_FLOW_ERROR;
1298 /* byte together hevc codec data based on collected pps and sps so far */
1300 gst_h265_parse_make_codec_data (GstH265Parse * h265parse)
1302 GstBuffer *buf, *nal;
1304 guint vps_size = 0, sps_size = 0, pps_size = 0;
1305 guint num_vps = 0, num_sps = 0, num_pps = 0;
1306 gboolean found = FALSE;
1310 guint8 num_arrays = 0;
1311 GstH265SPS *sps = NULL;
1312 guint16 min_spatial_segmentation_idc = 0;
1313 GstH265ProfileTierLevel *pft;
1315 /* only nal payload in stored nals */
1316 /* Fixme: Current implementation is not embedding SEI in codec_data */
1317 for (i = 0; i < GST_H265_MAX_VPS_COUNT; i++) {
1318 if ((nal = h265parse->vps_nals[i])) {
1320 /* size bytes also count */
1321 vps_size += gst_buffer_get_size (nal) + 2;
1327 for (i = 0; i < GST_H265_MAX_SPS_COUNT; i++) {
1328 if ((nal = h265parse->sps_nals[i])) {
1330 /* size bytes also count */
1331 sps_size += gst_buffer_get_size (nal) + 2;
1338 for (i = 0; i < GST_H265_MAX_PPS_COUNT; i++) {
1339 if ((nal = h265parse->pps_nals[i])) {
1341 /* size bytes also count */
1342 pps_size += gst_buffer_get_size (nal) + 2;
1348 GST_DEBUG_OBJECT (h265parse,
1349 "constructing codec_data: num_vps =%d num_sps=%d, num_pps=%d", num_vps,
1355 sps = h265parse->nalparser->last_sps;
1360 gst_buffer_new_allocate (NULL,
1361 23 + (3 * num_arrays) + vps_size + sps_size + pps_size, NULL);
1362 gst_buffer_map (buf, &map, GST_MAP_WRITE);
1364 memset (data, 0, map.size);
1365 nl = h265parse->nal_length_size;
1367 pft = &sps->profile_tier_level;
1368 if (sps->vui_parameters_present_flag)
1369 min_spatial_segmentation_idc = sps->vui_params.min_spatial_segmentation_idc;
1371 /* HEVCDecoderConfigurationVersion = 1
1372 * profile_space | tier_flat | profile_idc |
1373 * profile_compatibility_flags | constraint_indicator_flags |
1377 (pft->profile_space << 5) | (pft->tier_flag << 5) | pft->profile_idc;
1378 for (i = 2; i < 6; i++) {
1379 for (j = 7; j >= 0; j--) {
1380 data[i] |= (pft->profile_compatibility_flag[k] << j);
1386 (pft->progressive_source_flag << 7) |
1387 (pft->interlaced_source_flag << 6) |
1388 (pft->non_packed_constraint_flag << 5) |
1389 (pft->frame_only_constraint_flag << 4) |
1390 (pft->max_12bit_constraint_flag << 3) |
1391 (pft->max_10bit_constraint_flag << 2) |
1392 (pft->max_8bit_constraint_flag << 1) |
1393 (pft->max_422chroma_constraint_flag);
1396 (pft->max_420chroma_constraint_flag << 7) |
1397 (pft->max_monochrome_constraint_flag << 6) |
1398 (pft->intra_constraint_flag << 5) |
1399 (pft->one_picture_only_constraint_flag << 4) |
1400 (pft->lower_bit_rate_constraint_flag << 3) |
1401 (pft->max_14bit_constraint_flag << 2);
1403 data[12] = pft->level_idc;
1404 /* min_spatial_segmentation_idc */
1405 GST_WRITE_UINT16_BE (data + 13, min_spatial_segmentation_idc);
1407 data[15] = 0xfc; /* keeping parrallelismType as zero (unknown) */
1408 data[16] = 0xfc | sps->chroma_format_idc;
1409 data[17] = 0xf8 | sps->bit_depth_luma_minus8;
1410 data[18] = 0xf8 | sps->bit_depth_chroma_minus8;
1411 data[19] = 0x00; /* keep avgFrameRate as unspecified */
1412 data[20] = 0x00; /* keep avgFrameRate as unspecified */
1413 /* constFrameRate(2 bits): 0, stream may or may not be of constant framerate
1414 * numTemporalLayers (3 bits): number of temporal layers, value from SPS
1415 * TemporalIdNested (1 bit): sps_temporal_id_nesting_flag from SPS
1416 * lengthSizeMinusOne (2 bits): plus 1 indicates the length of the NALUnitLength */
1418 0x00 | ((sps->max_sub_layers_minus1 +
1419 1) << 3) | (sps->temporal_id_nesting_flag << 2) | (nl - 1);
1420 GST_WRITE_UINT8 (data + 22, num_arrays); /* numOfArrays */
1426 /* array_completeness | reserved_zero bit | nal_unit_type */
1427 data[0] = 0x00 | 0x20;
1430 GST_WRITE_UINT16_BE (data, num_vps);
1433 for (i = 0; i < GST_H265_MAX_VPS_COUNT; i++) {
1434 if ((nal = h265parse->vps_nals[i])) {
1435 gsize nal_size = gst_buffer_get_size (nal);
1436 GST_WRITE_UINT16_BE (data, nal_size);
1437 gst_buffer_extract (nal, 0, data + 2, nal_size);
1438 data += 2 + nal_size;
1445 /* array_completeness | reserved_zero bit | nal_unit_type */
1446 data[0] = 0x00 | 0x21;
1449 GST_WRITE_UINT16_BE (data, num_sps);
1452 for (i = 0; i < GST_H265_MAX_SPS_COUNT; i++) {
1453 if ((nal = h265parse->sps_nals[i])) {
1454 gsize nal_size = gst_buffer_get_size (nal);
1455 GST_WRITE_UINT16_BE (data, nal_size);
1456 gst_buffer_extract (nal, 0, data + 2, nal_size);
1457 data += 2 + nal_size;
1464 /* array_completeness | reserved_zero bit | nal_unit_type */
1465 data[0] = 0x00 | 0x22;
1468 GST_WRITE_UINT16_BE (data, num_pps);
1471 for (i = 0; i < GST_H265_MAX_PPS_COUNT; i++) {
1472 if ((nal = h265parse->pps_nals[i])) {
1473 gsize nal_size = gst_buffer_get_size (nal);
1474 GST_WRITE_UINT16_BE (data, nal_size);
1475 gst_buffer_extract (nal, 0, data + 2, nal_size);
1476 data += 2 + nal_size;
1480 gst_buffer_unmap (buf, &map);
1486 gst_h265_parse_get_par (GstH265Parse * h265parse, gint * num, gint * den)
1488 if (h265parse->upstream_par_n != -1 && h265parse->upstream_par_d != -1) {
1489 *num = h265parse->upstream_par_n;
1490 *den = h265parse->upstream_par_d;
1492 *num = h265parse->parsed_par_n;
1493 *den = h265parse->parsed_par_d;
1497 static const gchar *
1498 digit_to_string (guint digit)
1500 static const char itoa[][2] = {
1501 "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"
1504 if (G_LIKELY (digit < 10))
1510 static const gchar *
1511 get_profile_string (GstH265Profile profile)
1514 case GST_H265_PROFILE_MAIN:
1516 case GST_H265_PROFILE_MAIN_10:
1518 case GST_H265_PROFILE_MAIN_STILL_PICTURE:
1519 return "main-still-picture";
1520 case GST_H265_PROFILE_MONOCHROME:
1521 return "monochrome";
1522 case GST_H265_PROFILE_MONOCHROME_10:
1523 return "monochrome-10";
1524 case GST_H265_PROFILE_MONOCHROME_12:
1525 return "monochrome-12";
1526 case GST_H265_PROFILE_MONOCHROME_16:
1527 return "monochrome-16";
1528 case GST_H265_PROFILE_MAIN_12:
1530 case GST_H265_PROFILE_MAIN_422_10:
1531 return "main-422-10";
1532 case GST_H265_PROFILE_MAIN_422_12:
1533 return "main-422-12";
1534 case GST_H265_PROFILE_MAIN_444:
1536 case GST_H265_PROFILE_MAIN_444_10:
1537 return "main-444-10";
1538 case GST_H265_PROFILE_MAIN_444_12:
1539 return "main-444-12";
1540 case GST_H265_PROFILE_MAIN_INTRA:
1541 return "main-intra";
1542 case GST_H265_PROFILE_MAIN_10_INTRA:
1543 return "main-10-intra";
1544 case GST_H265_PROFILE_MAIN_12_INTRA:
1545 return "main-12-intra";
1546 case GST_H265_PROFILE_MAIN_422_10_INTRA:
1547 return "main-422-10-intra";
1548 case GST_H265_PROFILE_MAIN_422_12_INTRA:
1549 return "main-422-12-intra";
1550 case GST_H265_PROFILE_MAIN_444_INTRA:
1551 return "main-444-intra";
1552 case GST_H265_PROFILE_MAIN_444_10_INTRA:
1553 return "main-444-10-intra";
1554 case GST_H265_PROFILE_MAIN_444_12_INTRA:
1555 return "main-444-12-intra";
1556 case GST_H265_PROFILE_MAIN_444_16_INTRA:
1557 return "main-444-16-intra";
1558 case GST_H265_PROFILE_MAIN_444_STILL_PICTURE:
1559 return "main-444-still-picture";
1560 case GST_H265_PROFILE_MAIN_444_16_STILL_PICTURE:
1561 return "main-444-16-still-picture";
1562 case GST_H265_PROFILE_HIGH_THROUGHPUT_444:
1563 return "high-throughput-444";
1564 case GST_H265_PROFILE_HIGH_THROUGHPUT_444_10:
1565 return "high-throughput-444-10";
1566 case GST_H265_PROFILE_HIGH_THROUGHPUT_444_14:
1567 return "high-throughput-444-14";
1568 case GST_H265_PROFILE_HIGH_THROUGHPUT_444_16_INTRA:
1569 return "high-throughput-444-16-intra";
1570 case GST_H265_PROFILE_SCREEN_EXTENDED_MAIN:
1571 return "screen-extended-main";
1572 case GST_H265_PROFILE_SCREEN_EXTENDED_MAIN_10:
1573 return "screen-extended-main-10";
1574 case GST_H265_PROFILE_SCREEN_EXTENDED_MAIN_444:
1575 return "screen-extended-main-444";
1576 case GST_H265_PROFILE_SCREEN_EXTENDED_MAIN_444_10:
1577 return "screen-extended-main-444-10";
1578 case GST_H265_PROFILE_SCREEN_EXTENDED_HIGH_THROUGHPUT_444:
1579 return "screen-extended-high-throughput-444";
1580 case GST_H265_PROFILE_SCREEN_EXTENDED_HIGH_THROUGHPUT_444_10:
1581 return "screen-extended-high-throughput-444-10";
1582 case GST_H265_PROFILE_SCREEN_EXTENDED_HIGH_THROUGHPUT_444_14:
1583 return "screen-extended-high-throughput-444-14";
1584 case GST_H265_PROFILE_MULTIVIEW_MAIN:
1585 return "multiview-main";
1586 case GST_H265_PROFILE_SCALABLE_MAIN:
1587 return "scalable-main";
1588 case GST_H265_PROFILE_SCALABLE_MAIN_10:
1589 return "scalable-main-10";
1590 case GST_H265_PROFILE_SCALABLE_MONOCHROME:
1591 return "scalable-monochrome";
1592 case GST_H265_PROFILE_SCALABLE_MONOCHROME_12:
1593 return "scalable-monochrome-12";
1594 case GST_H265_PROFILE_SCALABLE_MONOCHROME_16:
1595 return "scalable-monochrome-16";
1596 case GST_H265_PROFILE_SCALABLE_MAIN_444:
1597 return "scalable-main-444";
1598 case GST_H265_PROFILE_3D_MAIN:
1607 static const gchar *
1608 get_tier_string (guint8 tier_flag)
1610 const gchar *tier = NULL;
1620 static const gchar *
1621 get_level_string (guint8 level_idc)
1625 else if (level_idc % 30 == 0)
1626 return digit_to_string (level_idc / 30);
1628 switch (level_idc) {
1657 get_compatible_profile_caps (GstH265SPS * sps)
1659 GstCaps *caps = NULL;
1660 const gchar **profiles = NULL;
1662 GValue compat_profiles = G_VALUE_INIT;
1663 g_value_init (&compat_profiles, GST_TYPE_LIST);
1665 switch (sps->profile_tier_level.profile_idc) {
1666 case GST_H265_PROFILE_IDC_MAIN_10:
1667 if (sps->profile_tier_level.profile_compatibility_flag[1]) {
1668 if (sps->profile_tier_level.profile_compatibility_flag[3]) {
1669 static const gchar *profile_array[] =
1670 { "main", "main-still-picture", NULL };
1671 profiles = profile_array;
1673 static const gchar *profile_array[] = { "main", NULL };
1674 profiles = profile_array;
1678 case GST_H265_PROFILE_IDC_MAIN:
1679 if (sps->profile_tier_level.profile_compatibility_flag[3]) {
1680 static const gchar *profile_array[] =
1681 { "main-still-picture", "main-10", NULL
1683 profiles = profile_array;
1685 static const gchar *profile_array[] = { "main-10", NULL };
1686 profiles = profile_array;
1689 case GST_H265_PROFILE_IDC_MAIN_STILL_PICTURE:
1691 static const gchar *profile_array[] = { "main", "main-10", NULL
1693 profiles = profile_array;
1701 GValue value = G_VALUE_INIT;
1702 caps = gst_caps_new_empty_simple ("video/x-h265");
1703 for (i = 0; profiles[i]; i++) {
1704 g_value_init (&value, G_TYPE_STRING);
1705 g_value_set_string (&value, profiles[i]);
1706 gst_value_list_append_value (&compat_profiles, &value);
1707 g_value_unset (&value);
1709 gst_caps_set_value (caps, "profile", &compat_profiles);
1710 g_value_unset (&compat_profiles);
1716 /* if downstream didn't support the exact profile indicated in sps header,
1717 * check for the compatible profiles also */
1719 ensure_caps_profile (GstH265Parse * h265parse, GstCaps * caps, GstH265SPS * sps)
1721 GstCaps *peer_caps, *compat_caps;
1723 peer_caps = gst_pad_get_current_caps (GST_BASE_PARSE_SRC_PAD (h265parse));
1724 if (!peer_caps || !gst_caps_can_intersect (caps, peer_caps)) {
1725 GstCaps *filter_caps = gst_caps_new_empty_simple ("video/x-h265");
1728 gst_caps_unref (peer_caps);
1730 gst_pad_peer_query_caps (GST_BASE_PARSE_SRC_PAD (h265parse),
1733 gst_caps_unref (filter_caps);
1736 if (peer_caps && !gst_caps_can_intersect (caps, peer_caps)) {
1737 GstStructure *structure;
1739 compat_caps = get_compatible_profile_caps (sps);
1740 if (compat_caps != NULL) {
1741 GstCaps *res_caps = NULL;
1743 res_caps = gst_caps_intersect (peer_caps, compat_caps);
1745 if (res_caps && !gst_caps_is_empty (res_caps)) {
1746 const gchar *profile_str = NULL;
1748 res_caps = gst_caps_fixate (res_caps);
1749 structure = gst_caps_get_structure (res_caps, 0);
1750 profile_str = gst_structure_get_string (structure, "profile");
1752 gst_caps_set_simple (caps, "profile", G_TYPE_STRING, profile_str,
1754 GST_DEBUG_OBJECT (h265parse,
1755 "Setting compatible profile %s to the caps", profile_str);
1759 gst_caps_unref (res_caps);
1760 gst_caps_unref (compat_caps);
1764 gst_caps_unref (peer_caps);
1768 gst_h265_parse_update_src_caps (GstH265Parse * h265parse, GstCaps * caps)
1772 GstCaps *sink_caps, *src_caps;
1773 gboolean modified = FALSE;
1774 GstBuffer *buf = NULL;
1775 GstStructure *s = NULL;
1777 if (G_UNLIKELY (!gst_pad_has_current_caps (GST_BASE_PARSE_SRC_PAD
1780 else if (G_UNLIKELY (!h265parse->update_caps))
1783 /* if this is being called from the first _setcaps call, caps on the sinkpad
1784 * aren't set yet and so they need to be passed as an argument */
1786 sink_caps = gst_caps_ref (caps);
1788 sink_caps = gst_pad_get_current_caps (GST_BASE_PARSE_SINK_PAD (h265parse));
1790 /* carry over input caps as much as possible; override with our own stuff */
1792 sink_caps = gst_caps_new_empty_simple ("video/x-h265");
1794 s = gst_caps_get_structure (sink_caps, 0);
1796 sps = h265parse->nalparser->last_sps;
1797 GST_DEBUG_OBJECT (h265parse, "sps: %p", sps);
1799 GST_DEBUG_OBJECT (h265parse, "vps: %p", vps);
1801 /* only codec-data for nice-and-clean au aligned packetized hevc format */
1802 if ((h265parse->format == GST_H265_PARSE_FORMAT_HVC1
1803 || h265parse->format == GST_H265_PARSE_FORMAT_HEV1)
1804 && h265parse->align == GST_H265_PARSE_ALIGN_AU) {
1805 buf = gst_h265_parse_make_codec_data (h265parse);
1806 if (buf && h265parse->codec_data) {
1809 gst_buffer_map (buf, &map, GST_MAP_READ);
1810 if (map.size != gst_buffer_get_size (h265parse->codec_data) ||
1811 gst_buffer_memcmp (h265parse->codec_data, 0, map.data, map.size))
1814 gst_buffer_unmap (buf, &map);
1816 if (!buf && h265parse->codec_data_in)
1817 buf = gst_buffer_ref (h265parse->codec_data_in);
1823 if (G_UNLIKELY (!sps)) {
1824 caps = gst_caps_copy (sink_caps);
1826 gint crop_width, crop_height;
1827 const gchar *chroma_format = NULL;
1828 guint bit_depth_chroma;
1830 if (sps->conformance_window_flag) {
1831 crop_width = sps->crop_rect_width;
1832 crop_height = sps->crop_rect_height;
1834 crop_width = sps->width;
1835 crop_height = sps->height;
1838 if (G_UNLIKELY (h265parse->width != crop_width ||
1839 h265parse->height != crop_height)) {
1840 GST_INFO_OBJECT (h265parse, "resolution changed %dx%d",
1841 crop_width, crop_height);
1842 h265parse->width = crop_width;
1843 h265parse->height = crop_height;
1847 /* 0/1 is set as the default in the codec parser */
1848 if ((sps->vui_params.timing_info_present_flag ||
1849 (vps && vps->timing_info_present_flag)) &&
1850 !(sps->fps_num == 0 && sps->fps_den == 1)) {
1851 if (G_UNLIKELY (h265parse->fps_num != sps->fps_num
1852 || h265parse->fps_den != sps->fps_den)) {
1853 GST_INFO_OBJECT (h265parse, "framerate changed %d/%d",
1854 sps->fps_num, sps->fps_den);
1855 h265parse->fps_num = sps->fps_num;
1856 h265parse->fps_den = sps->fps_den;
1861 if (sps->vui_params.aspect_ratio_info_present_flag) {
1862 if (G_UNLIKELY ((h265parse->parsed_par_n != sps->vui_params.par_n)
1863 && (h265parse->parsed_par_d != sps->vui_params.par_d))) {
1864 h265parse->parsed_par_n = sps->vui_params.par_n;
1865 h265parse->parsed_par_d = sps->vui_params.par_d;
1866 GST_INFO_OBJECT (h265parse, "pixel aspect ratio has been changed %d/%d",
1867 h265parse->parsed_par_n, h265parse->parsed_par_d);
1873 if (G_UNLIKELY (modified || h265parse->update_caps)) {
1874 gint fps_num = h265parse->fps_num;
1875 gint fps_den = h265parse->fps_den;
1877 GstClockTime latency;
1879 caps = gst_caps_copy (sink_caps);
1881 /* sps should give this but upstream overrides */
1882 if (s && gst_structure_has_field (s, "width"))
1883 gst_structure_get_int (s, "width", &width);
1885 width = h265parse->width;
1887 if (s && gst_structure_has_field (s, "height"))
1888 gst_structure_get_int (s, "height", &height);
1890 height = h265parse->height;
1892 gst_caps_set_simple (caps, "width", G_TYPE_INT, width,
1893 "height", G_TYPE_INT, height, NULL);
1895 /* upstream overrides */
1896 if (s && gst_structure_has_field (s, "framerate"))
1897 gst_structure_get_fraction (s, "framerate", &fps_num, &fps_den);
1899 /* but not necessarily or reliably this */
1900 if (fps_num > 0 && fps_den > 0) {
1902 GST_INFO_OBJECT (h265parse, "setting framerate in caps");
1903 gst_caps_set_simple (caps, "framerate",
1904 GST_TYPE_FRACTION, fps_num, fps_den, NULL);
1905 s2 = gst_caps_get_structure (caps, 0);
1906 gst_structure_get_fraction (s2, "framerate", &h265parse->parsed_fps_n,
1907 &h265parse->parsed_fps_d);
1908 gst_base_parse_set_frame_rate (GST_BASE_PARSE (h265parse),
1909 fps_num, fps_den, 0, 0);
1910 latency = gst_util_uint64_scale (GST_SECOND, fps_den, fps_num);
1911 gst_base_parse_set_latency (GST_BASE_PARSE (h265parse), latency,
1915 bit_depth_chroma = sps->bit_depth_chroma_minus8 + 8;
1917 switch (sps->chroma_format_idc) {
1919 chroma_format = "4:0:0";
1920 bit_depth_chroma = 0;
1923 chroma_format = "4:2:0";
1926 chroma_format = "4:2:2";
1929 chroma_format = "4:4:4";
1936 gst_caps_set_simple (caps, "chroma-format", G_TYPE_STRING,
1937 chroma_format, "bit-depth-luma", G_TYPE_UINT,
1938 sps->bit_depth_luma_minus8 + 8, "bit-depth-chroma", G_TYPE_UINT,
1939 bit_depth_chroma, NULL);
1945 const gchar *mastering_info_str;
1946 const gchar *cll_str;
1948 gst_caps_set_simple (caps, "parsed", G_TYPE_BOOLEAN, TRUE,
1949 "stream-format", G_TYPE_STRING,
1950 gst_h265_parse_get_string (h265parse, TRUE, h265parse->format),
1951 "alignment", G_TYPE_STRING,
1952 gst_h265_parse_get_string (h265parse, FALSE, h265parse->align), NULL);
1954 gst_h265_parse_get_par (h265parse, &par_n, &par_d);
1955 if (par_n != 0 && par_d != 0 &&
1956 (!s || !gst_structure_has_field (s, "pixel-aspect-ratio"))) {
1957 GST_INFO_OBJECT (h265parse, "PAR %d/%d", par_n, par_d);
1958 gst_caps_set_simple (caps, "pixel-aspect-ratio", GST_TYPE_FRACTION,
1959 par_n, par_d, NULL);
1962 /* set profile and level in caps */
1964 const gchar *profile, *tier, *level;
1967 p = gst_h265_profile_tier_level_get_profile (&sps->profile_tier_level);
1968 profile = get_profile_string (p);
1969 if (profile != NULL)
1970 gst_caps_set_simple (caps, "profile", G_TYPE_STRING, profile, NULL);
1972 tier = get_tier_string (sps->profile_tier_level.tier_flag);
1974 gst_caps_set_simple (caps, "tier", G_TYPE_STRING, tier, NULL);
1976 level = get_level_string (sps->profile_tier_level.level_idc);
1978 gst_caps_set_simple (caps, "level", G_TYPE_STRING, level, NULL);
1980 /* relax the profile constraint to find a suitable decoder */
1981 ensure_caps_profile (h265parse, caps, sps);
1985 && (mastering_info_str =
1986 gst_structure_get_string (s, "mastering-display-info"))) {
1987 gst_caps_set_simple (caps, "mastering-display-info", G_TYPE_STRING,
1988 mastering_info_str, NULL);
1989 } else if (h265parse->mastering_display_info_state !=
1990 GST_H265_PARSE_SEI_EXPIRED
1992 !gst_video_mastering_display_info_add_to_caps
1993 (&h265parse->mastering_display_info, caps)) {
1994 GST_WARNING_OBJECT (h265parse,
1995 "Couldn't set mastering display info to caps");
1998 if (s && (cll_str = gst_structure_get_string (s, "content-light-level"))) {
1999 gst_caps_set_simple (caps, "content-light-level", G_TYPE_STRING, cll_str,
2001 } else if (h265parse->content_light_level_state !=
2002 GST_H265_PARSE_SEI_EXPIRED
2004 !gst_video_content_light_level_add_to_caps
2005 (&h265parse->content_light_level, caps)) {
2006 GST_WARNING_OBJECT (h265parse,
2007 "Couldn't set content light level to caps");
2010 src_caps = gst_pad_get_current_caps (GST_BASE_PARSE_SRC_PAD (h265parse));
2013 /* use codec data from old caps for comparison; we don't want to resend caps
2014 if everything is same except codec data; */
2015 if (gst_structure_has_field (gst_caps_get_structure (src_caps, 0),
2017 gst_caps_set_value (caps, "codec_data",
2018 gst_structure_get_value (gst_caps_get_structure (src_caps, 0),
2022 /* remove any left-over codec-data hanging around */
2023 s = gst_caps_get_structure (caps, 0);
2024 gst_structure_remove_field (s, "codec_data");
2028 if (!(src_caps && gst_caps_is_strictly_equal (src_caps, caps))) {
2029 /* update codec data to new value */
2031 gst_caps_set_simple (caps, "codec_data", GST_TYPE_BUFFER, buf, NULL);
2032 gst_buffer_replace (&h265parse->codec_data, buf);
2033 gst_buffer_unref (buf);
2037 /* remove any left-over codec-data hanging around */
2038 s = gst_caps_get_structure (caps, 0);
2039 gst_structure_remove_field (s, "codec_data");
2040 gst_buffer_replace (&h265parse->codec_data, NULL);
2043 gst_pad_set_caps (GST_BASE_PARSE_SRC_PAD (h265parse), caps);
2047 gst_caps_unref (src_caps);
2048 gst_caps_unref (caps);
2051 gst_caps_unref (sink_caps);
2053 gst_buffer_unref (buf);
2057 static GstFlowReturn
2058 gst_h265_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
2060 GstH265Parse *h265parse;
2064 h265parse = GST_H265_PARSE (parse);
2065 buffer = frame->buffer;
2067 gst_h265_parse_update_src_caps (h265parse, NULL);
2069 /* Fixme: Implement timestamp interpolation based on SEI Messagses */
2070 GST_FIXME_OBJECT (h265parse,
2071 "Implement timestamp/duration interpolation based on SEI message");
2073 if (h265parse->keyframe)
2074 GST_BUFFER_FLAG_UNSET (buffer, GST_BUFFER_FLAG_DELTA_UNIT);
2076 GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT);
2078 if (h265parse->header)
2079 GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_HEADER);
2081 GST_BUFFER_FLAG_UNSET (buffer, GST_BUFFER_FLAG_HEADER);
2083 if (h265parse->discont) {
2084 GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
2085 h265parse->discont = FALSE;
2088 /* replace with transformed HEVC output if applicable */
2089 av = gst_adapter_available (h265parse->frame_out);
2093 buf = gst_adapter_take_buffer (h265parse->frame_out, av);
2094 gst_buffer_copy_into (buf, buffer, GST_BUFFER_COPY_METADATA, 0, -1);
2095 gst_buffer_replace (&frame->out_buffer, buf);
2096 gst_buffer_unref (buf);
2102 /* sends a codec NAL downstream, decorating and transforming as needed.
2103 * No ownership is taken of @nal */
2104 static GstFlowReturn
2105 gst_h265_parse_push_codec_buffer (GstH265Parse * h265parse, GstBuffer * nal,
2110 gst_buffer_map (nal, &map, GST_MAP_READ);
2111 nal = gst_h265_parse_wrap_nal (h265parse, h265parse->format,
2112 map.data, map.size);
2113 gst_buffer_unmap (nal, &map);
2115 GST_BUFFER_TIMESTAMP (nal) = ts;
2116 GST_BUFFER_DURATION (nal) = 0;
2118 return gst_pad_push (GST_BASE_PARSE_SRC_PAD (h265parse), nal);
2122 check_pending_key_unit_event (GstEvent * pending_event, GstSegment * segment,
2123 GstClockTime timestamp, guint flags, GstClockTime pending_key_unit_ts)
2125 GstClockTime running_time, stream_time;
2126 gboolean all_headers;
2128 GstEvent *event = NULL;
2130 g_return_val_if_fail (segment != NULL, NULL);
2132 if (pending_event == NULL)
2135 if (GST_CLOCK_TIME_IS_VALID (pending_key_unit_ts) &&
2136 timestamp == GST_CLOCK_TIME_NONE)
2139 running_time = gst_segment_to_running_time (segment,
2140 GST_FORMAT_TIME, timestamp);
2142 GST_INFO ("now %" GST_TIME_FORMAT " wanted %" GST_TIME_FORMAT,
2143 GST_TIME_ARGS (running_time), GST_TIME_ARGS (pending_key_unit_ts));
2144 if (GST_CLOCK_TIME_IS_VALID (pending_key_unit_ts) &&
2145 running_time < pending_key_unit_ts)
2148 if (flags & GST_BUFFER_FLAG_DELTA_UNIT) {
2149 GST_DEBUG ("pending force key unit, waiting for keyframe");
2153 stream_time = gst_segment_to_stream_time (segment,
2154 GST_FORMAT_TIME, timestamp);
2156 if (!gst_video_event_parse_upstream_force_key_unit (pending_event,
2157 NULL, &all_headers, &count)) {
2158 gst_video_event_parse_downstream_force_key_unit (pending_event, NULL,
2159 NULL, NULL, &all_headers, &count);
2163 gst_video_event_new_downstream_force_key_unit (timestamp, stream_time,
2164 running_time, all_headers, count);
2165 gst_event_set_seqnum (event, gst_event_get_seqnum (pending_event));
2172 gst_h265_parse_prepare_key_unit (GstH265Parse * parse, GstEvent * event)
2174 GstClockTime running_time;
2176 #ifndef GST_DISABLE_GST_DEBUG
2177 gboolean have_vps, have_sps, have_pps;
2181 parse->pending_key_unit_ts = GST_CLOCK_TIME_NONE;
2182 gst_event_replace (&parse->force_key_unit_event, NULL);
2184 gst_video_event_parse_downstream_force_key_unit (event,
2185 NULL, NULL, &running_time, NULL, &count);
2187 GST_INFO_OBJECT (parse, "pushing downstream force-key-unit event %d "
2188 "%" GST_TIME_FORMAT " count %d", gst_event_get_seqnum (event),
2189 GST_TIME_ARGS (running_time), count);
2190 gst_pad_push_event (GST_BASE_PARSE_SRC_PAD (parse), event);
2192 #ifndef GST_DISABLE_GST_DEBUG
2193 have_vps = have_sps = have_pps = FALSE;
2194 for (i = 0; i < GST_H265_MAX_VPS_COUNT; i++) {
2195 if (parse->vps_nals[i] != NULL) {
2200 for (i = 0; i < GST_H265_MAX_SPS_COUNT; i++) {
2201 if (parse->sps_nals[i] != NULL) {
2206 for (i = 0; i < GST_H265_MAX_PPS_COUNT; i++) {
2207 if (parse->pps_nals[i] != NULL) {
2213 GST_INFO_OBJECT (parse,
2214 "preparing key unit, have vps %d have sps %d have pps %d", have_vps,
2215 have_sps, have_pps);
2218 /* set push_codec to TRUE so that pre_push_frame sends VPS/SPS/PPS again */
2219 parse->push_codec = TRUE;
2223 gst_h265_parse_handle_vps_sps_pps_nals (GstH265Parse * h265parse,
2224 GstBuffer * buffer, GstBaseParseFrame * frame)
2226 GstBuffer *codec_nal;
2228 gboolean send_done = FALSE;
2229 GstClockTime timestamp = GST_BUFFER_TIMESTAMP (buffer);
2231 if (h265parse->have_vps_in_frame && h265parse->have_sps_in_frame
2232 && h265parse->have_pps_in_frame) {
2233 GST_DEBUG_OBJECT (h265parse, "VPS/SPS/PPS exist in frame, will not insert");
2237 if (h265parse->align == GST_H265_PARSE_ALIGN_NAL) {
2238 /* send separate config NAL buffers */
2239 GST_DEBUG_OBJECT (h265parse, "- sending VPS/SPS/PPS");
2240 for (i = 0; i < GST_H265_MAX_VPS_COUNT; i++) {
2241 if ((codec_nal = h265parse->vps_nals[i])) {
2242 GST_DEBUG_OBJECT (h265parse, "sending VPS nal");
2243 gst_h265_parse_push_codec_buffer (h265parse, codec_nal, timestamp);
2247 for (i = 0; i < GST_H265_MAX_SPS_COUNT; i++) {
2248 if ((codec_nal = h265parse->sps_nals[i])) {
2249 GST_DEBUG_OBJECT (h265parse, "sending SPS nal");
2250 gst_h265_parse_push_codec_buffer (h265parse, codec_nal, timestamp);
2254 for (i = 0; i < GST_H265_MAX_PPS_COUNT; i++) {
2255 if ((codec_nal = h265parse->pps_nals[i])) {
2256 GST_DEBUG_OBJECT (h265parse, "sending PPS nal");
2257 gst_h265_parse_push_codec_buffer (h265parse, codec_nal, timestamp);
2262 /* insert config NALs into AU */
2265 const gboolean bs = h265parse->format == GST_H265_PARSE_FORMAT_BYTE;
2266 const gint nls = 4 - h265parse->nal_length_size;
2269 gst_byte_writer_init_with_size (&bw, gst_buffer_get_size (buffer), FALSE);
2270 ok = gst_byte_writer_put_buffer (&bw, buffer, 0, h265parse->idr_pos);
2271 GST_DEBUG_OBJECT (h265parse, "- inserting VPS/SPS/PPS");
2272 for (i = 0; i < GST_H265_MAX_VPS_COUNT; i++) {
2273 if ((codec_nal = h265parse->vps_nals[i])) {
2274 gsize nal_size = gst_buffer_get_size (codec_nal);
2275 GST_DEBUG_OBJECT (h265parse, "inserting VPS nal");
2277 ok &= gst_byte_writer_put_uint32_be (&bw, 1);
2279 ok &= gst_byte_writer_put_uint32_be (&bw, (nal_size << (nls * 8)));
2280 ok &= gst_byte_writer_set_pos (&bw,
2281 gst_byte_writer_get_pos (&bw) - nls);
2284 ok &= gst_byte_writer_put_buffer (&bw, codec_nal, 0, nal_size);
2288 for (i = 0; i < GST_H265_MAX_SPS_COUNT; i++) {
2289 if ((codec_nal = h265parse->sps_nals[i])) {
2290 gsize nal_size = gst_buffer_get_size (codec_nal);
2291 GST_DEBUG_OBJECT (h265parse, "inserting SPS nal");
2293 ok &= gst_byte_writer_put_uint32_be (&bw, 1);
2295 ok &= gst_byte_writer_put_uint32_be (&bw, (nal_size << (nls * 8)));
2296 ok &= gst_byte_writer_set_pos (&bw,
2297 gst_byte_writer_get_pos (&bw) - nls);
2300 ok &= gst_byte_writer_put_buffer (&bw, codec_nal, 0, nal_size);
2304 for (i = 0; i < GST_H265_MAX_PPS_COUNT; i++) {
2305 if ((codec_nal = h265parse->pps_nals[i])) {
2306 gsize nal_size = gst_buffer_get_size (codec_nal);
2307 GST_DEBUG_OBJECT (h265parse, "inserting PPS nal");
2309 ok &= gst_byte_writer_put_uint32_be (&bw, 1);
2311 ok &= gst_byte_writer_put_uint32_be (&bw, (nal_size << (nls * 8)));
2312 ok &= gst_byte_writer_set_pos (&bw,
2313 gst_byte_writer_get_pos (&bw) - nls);
2315 ok &= gst_byte_writer_put_buffer (&bw, codec_nal, 0, nal_size);
2319 ok &= gst_byte_writer_put_buffer (&bw, buffer, h265parse->idr_pos, -1);
2320 /* collect result and push */
2321 new_buf = gst_byte_writer_reset_and_get_buffer (&bw);
2322 gst_buffer_copy_into (new_buf, buffer, GST_BUFFER_COPY_METADATA, 0, -1);
2323 /* should already be keyframe/IDR, but it may not have been,
2324 * so mark it as such to avoid being discarded by picky decoder */
2325 GST_BUFFER_FLAG_UNSET (new_buf, GST_BUFFER_FLAG_DELTA_UNIT);
2326 gst_buffer_replace (&frame->out_buffer, new_buf);
2327 gst_buffer_unref (new_buf);
2328 /* some result checking seems to make some compilers happy */
2329 if (G_UNLIKELY (!ok)) {
2330 GST_ERROR_OBJECT (h265parse, "failed to insert SPS/PPS");
2337 static GstFlowReturn
2338 gst_h265_parse_pre_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
2340 GstH265Parse *h265parse;
2344 h265parse = GST_H265_PARSE (parse);
2346 if (!h265parse->sent_codec_tag) {
2347 GstTagList *taglist;
2351 caps = gst_pad_get_current_caps (GST_BASE_PARSE_SRC_PAD (parse));
2352 if (G_UNLIKELY (caps == NULL)) {
2353 if (GST_PAD_IS_FLUSHING (GST_BASE_PARSE_SRC_PAD (parse))) {
2354 GST_INFO_OBJECT (parse, "Src pad is flushing");
2355 return GST_FLOW_FLUSHING;
2357 GST_INFO_OBJECT (parse, "Src pad is not negotiated!");
2358 return GST_FLOW_NOT_NEGOTIATED;
2362 taglist = gst_tag_list_new_empty ();
2363 gst_pb_utils_add_codec_description_to_tag_list (taglist,
2364 GST_TAG_VIDEO_CODEC, caps);
2365 gst_caps_unref (caps);
2367 gst_base_parse_merge_tags (parse, taglist, GST_TAG_MERGE_REPLACE);
2368 gst_tag_list_unref (taglist);
2370 /* also signals the end of first-frame processing */
2371 h265parse->sent_codec_tag = TRUE;
2374 buffer = frame->buffer;
2376 if ((event = check_pending_key_unit_event (h265parse->force_key_unit_event,
2377 &parse->segment, GST_BUFFER_TIMESTAMP (buffer),
2378 GST_BUFFER_FLAGS (buffer), h265parse->pending_key_unit_ts))) {
2379 gst_h265_parse_prepare_key_unit (h265parse, event);
2382 /* periodic VPS/SPS/PPS sending */
2383 if (h265parse->interval > 0 || h265parse->push_codec) {
2384 GstClockTime timestamp = GST_BUFFER_TIMESTAMP (buffer);
2386 gboolean initial_frame = FALSE;
2389 if (!GST_CLOCK_TIME_IS_VALID (h265parse->last_report)) {
2390 h265parse->last_report = timestamp;
2391 initial_frame = TRUE;
2394 if (h265parse->idr_pos >= 0) {
2395 GST_LOG_OBJECT (h265parse, "IDR nal at offset %d", h265parse->idr_pos);
2397 if (timestamp > h265parse->last_report)
2398 diff = timestamp - h265parse->last_report;
2402 GST_LOG_OBJECT (h265parse,
2403 "now %" GST_TIME_FORMAT ", last VPS/SPS/PPS %" GST_TIME_FORMAT,
2404 GST_TIME_ARGS (timestamp), GST_TIME_ARGS (h265parse->last_report));
2406 GST_DEBUG_OBJECT (h265parse,
2407 "interval since last VPS/SPS/PPS %" GST_TIME_FORMAT,
2408 GST_TIME_ARGS (diff));
2410 if (GST_TIME_AS_SECONDS (diff) >= h265parse->interval ||
2411 initial_frame || h265parse->push_codec) {
2412 GstClockTime new_ts;
2414 /* avoid overwriting a perfectly fine timestamp */
2415 new_ts = GST_CLOCK_TIME_IS_VALID (timestamp) ? timestamp :
2416 h265parse->last_report;
2418 if (gst_h265_parse_handle_vps_sps_pps_nals (h265parse, buffer, frame)) {
2419 h265parse->last_report = new_ts;
2423 /* we pushed whatever we had */
2424 h265parse->push_codec = FALSE;
2425 h265parse->have_vps = FALSE;
2426 h265parse->have_sps = FALSE;
2427 h265parse->have_pps = FALSE;
2428 h265parse->state &= GST_H265_PARSE_STATE_VALID_PICTURE_HEADERS;
2430 } else if (h265parse->interval == -1) {
2431 if (h265parse->idr_pos >= 0) {
2432 GST_LOG_OBJECT (h265parse, "IDR nal at offset %d", h265parse->idr_pos);
2434 gst_h265_parse_handle_vps_sps_pps_nals (h265parse, buffer, frame);
2436 /* we pushed whatever we had */
2437 h265parse->push_codec = FALSE;
2438 h265parse->have_vps = FALSE;
2439 h265parse->have_sps = FALSE;
2440 h265parse->have_pps = FALSE;
2441 h265parse->state &= GST_H265_PARSE_STATE_VALID_PICTURE_HEADERS;
2448 for (i = 0; i < h265parse->time_code.num_clock_ts; i++) {
2449 GstVideoTimeCodeFlags flags = 0;
2450 gint field_count = -1;
2453 if (!h265parse->time_code.clock_timestamp_flag[i])
2456 h265parse->time_code.clock_timestamp_flag[i] = 0;
2459 switch (h265parse->sei_pic_struct) {
2460 case GST_H265_SEI_PIC_STRUCT_FRAME:
2461 case GST_H265_SEI_PIC_STRUCT_TOP_FIELD:
2462 case GST_H265_SEI_PIC_STRUCT_BOTTOM_FIELD:
2463 field_count = h265parse->sei_pic_struct;
2465 case GST_H265_SEI_PIC_STRUCT_TOP_BOTTOM:
2466 case GST_H265_SEI_PIC_STRUCT_TOP_PAIRED_PREVIOUS_BOTTOM:
2467 case GST_H265_SEI_PIC_STRUCT_TOP_PAIRED_NEXT_BOTTOM:
2468 field_count = i + 1;
2470 case GST_H265_SEI_PIC_STRUCT_BOTTOM_TOP:
2471 case GST_H265_SEI_PIC_STRUCT_BOTTOM_PAIRED_PREVIOUS_TOP:
2472 case GST_H265_SEI_PIC_STRUCT_BOTTOM_PAIRED_NEXT_TOP:
2473 field_count = 2 - i;
2475 case GST_H265_SEI_PIC_STRUCT_TOP_BOTTOM_TOP:
2476 field_count = i % 2 ? 2 : 1;
2478 case GST_H265_SEI_PIC_STRUCT_BOTTOM_TOP_BOTTOM:
2479 field_count = i % 2 ? 1 : 2;
2481 case GST_H265_SEI_PIC_STRUCT_FRAME_DOUBLING:
2482 case GST_H265_SEI_PIC_STRUCT_FRAME_TRIPLING:
2487 if (field_count == -1) {
2488 GST_WARNING_OBJECT (parse,
2489 "failed to determine field count for timecode");
2493 /* Dropping of the two lowest (value 0 and 1) n_frames[ i ] counts when
2494 * seconds_value[ i ] is equal to 0 and minutes_value[ i ] is not an integer
2496 if (h265parse->time_code.counting_type[i] == 4)
2497 flags |= GST_VIDEO_TIME_CODE_FLAGS_DROP_FRAME;
2499 if (h265parse->sei_pic_struct != GST_H265_SEI_PIC_STRUCT_FRAME)
2500 flags |= GST_VIDEO_TIME_CODE_FLAGS_INTERLACED;
2503 gst_util_uint64_scale_int (h265parse->time_code.n_frames[i], 1,
2504 2 - h265parse->time_code.units_field_based_flag[i]);
2506 gst_buffer_add_video_time_code_meta_full (buffer,
2507 h265parse->parsed_fps_n,
2508 h265parse->parsed_fps_d,
2511 h265parse->time_code.hours_flag[i] ? h265parse->
2512 time_code.hours_value[i] : 0,
2513 h265parse->time_code.minutes_flag[i] ? h265parse->
2514 time_code.minutes_value[i] : 0,
2515 h265parse->time_code.seconds_flag[i] ? h265parse->
2516 time_code.seconds_value[i] : 0, n_frames, field_count);
2520 gst_h265_parse_reset_frame (h265parse);
2526 gst_h265_parse_set_caps (GstBaseParse * parse, GstCaps * caps)
2528 GstH265Parse *h265parse;
2530 const GValue *value;
2531 GstBuffer *codec_data = NULL;
2533 guint format, align;
2534 guint num_nals, i, j;
2535 GstH265NalUnit nalu;
2536 GstH265ParserResult parseres;
2539 h265parse = GST_H265_PARSE (parse);
2542 h265parse->push_codec = FALSE;
2544 old_caps = gst_pad_get_current_caps (GST_BASE_PARSE_SINK_PAD (parse));
2546 if (!gst_caps_is_equal (old_caps, caps))
2547 gst_h265_parse_reset_stream_info (h265parse);
2548 gst_caps_unref (old_caps);
2551 str = gst_caps_get_structure (caps, 0);
2553 /* accept upstream info if provided */
2554 gst_structure_get_int (str, "width", &h265parse->width);
2555 gst_structure_get_int (str, "height", &h265parse->height);
2556 gst_structure_get_fraction (str, "framerate", &h265parse->fps_num,
2557 &h265parse->fps_den);
2558 gst_structure_get_fraction (str, "pixel-aspect-ratio",
2559 &h265parse->upstream_par_n, &h265parse->upstream_par_d);
2561 /* get upstream format and align from caps */
2562 gst_h265_parse_format_from_caps (caps, &format, &align);
2564 /* packetized video has a codec_data */
2565 if (format != GST_H265_PARSE_FORMAT_BYTE &&
2566 (value = gst_structure_get_value (str, "codec_data"))) {
2569 guint num_nal_arrays;
2571 GST_DEBUG_OBJECT (h265parse, "have packetized h265");
2572 /* make note for optional split processing */
2573 h265parse->packetized = TRUE;
2575 codec_data = gst_value_get_buffer (value);
2578 gst_buffer_map (codec_data, &map, GST_MAP_READ);
2582 /* parse the hvcC data */
2584 gst_buffer_unmap (codec_data, &map);
2585 goto hvcc_too_small;
2587 /* parse the version, this must be one but
2588 * is zero until the spec is finalized */
2589 if (data[0] != 0 && data[0] != 1) {
2590 gst_buffer_unmap (codec_data, &map);
2594 h265parse->nal_length_size = (data[21] & 0x03) + 1;
2595 GST_DEBUG_OBJECT (h265parse, "nal length size %u",
2596 h265parse->nal_length_size);
2598 num_nal_arrays = data[22];
2601 for (i = 0; i < num_nal_arrays; i++) {
2602 if (off + 3 >= size) {
2603 gst_buffer_unmap (codec_data, &map);
2604 goto hvcc_too_small;
2607 num_nals = GST_READ_UINT16_BE (data + off + 1);
2609 for (j = 0; j < num_nals; j++) {
2610 parseres = gst_h265_parser_identify_nalu_hevc (h265parse->nalparser,
2611 data, off, size, 2, &nalu);
2613 if (parseres != GST_H265_PARSER_OK) {
2614 gst_buffer_unmap (codec_data, &map);
2615 goto hvcc_too_small;
2618 gst_h265_parse_process_nal (h265parse, &nalu);
2619 off = nalu.offset + nalu.size;
2622 gst_buffer_unmap (codec_data, &map);
2624 /* don't confuse codec_data with inband vps/sps/pps */
2625 h265parse->have_vps_in_frame = FALSE;
2626 h265parse->have_sps_in_frame = FALSE;
2627 h265parse->have_pps_in_frame = FALSE;
2629 GST_DEBUG_OBJECT (h265parse, "have bytestream h265");
2630 /* nothing to pre-process */
2631 h265parse->packetized = FALSE;
2632 /* we have 4 sync bytes */
2633 h265parse->nal_length_size = 4;
2635 if (format == GST_H265_PARSE_FORMAT_NONE) {
2636 format = GST_H265_PARSE_FORMAT_BYTE;
2637 align = GST_H265_PARSE_ALIGN_AU;
2644 /* prefer input type determined above */
2645 in_caps = gst_caps_new_simple ("video/x-h265",
2646 "parsed", G_TYPE_BOOLEAN, TRUE,
2647 "stream-format", G_TYPE_STRING,
2648 gst_h265_parse_get_string (h265parse, TRUE, format),
2649 "alignment", G_TYPE_STRING,
2650 gst_h265_parse_get_string (h265parse, FALSE, align), NULL);
2651 /* negotiate with downstream, sets ->format and ->align */
2652 gst_h265_parse_negotiate (h265parse, format, in_caps);
2653 gst_caps_unref (in_caps);
2656 if (format == h265parse->format && align == h265parse->align) {
2657 /* do not set CAPS and passthrough mode if SPS/PPS have not been parsed */
2658 if (h265parse->have_sps && h265parse->have_pps) {
2659 gst_base_parse_set_passthrough (parse, TRUE);
2661 /* we did parse codec-data and might supplement src caps */
2662 gst_h265_parse_update_src_caps (h265parse, caps);
2664 } else if (format == GST_H265_PARSE_FORMAT_HVC1
2665 || format == GST_H265_PARSE_FORMAT_HEV1) {
2666 /* if input != output, and input is hevc, must split before anything else */
2667 /* arrange to insert codec-data in-stream if needed.
2668 * src caps are only arranged for later on */
2669 h265parse->push_codec = TRUE;
2670 h265parse->have_vps = FALSE;
2671 h265parse->have_sps = FALSE;
2672 h265parse->have_pps = FALSE;
2673 if (h265parse->align == GST_H265_PARSE_ALIGN_NAL)
2674 h265parse->split_packetized = TRUE;
2675 h265parse->packetized = TRUE;
2683 GST_DEBUG_OBJECT (h265parse, "hvcC size %" G_GSIZE_FORMAT " < 23", size);
2688 GST_DEBUG_OBJECT (h265parse, "wrong hvcC version");
2693 GST_DEBUG_OBJECT (h265parse, "wrong codec-data type");
2698 GST_WARNING_OBJECT (h265parse, "refused caps %" GST_PTR_FORMAT, caps);
2704 remove_fields (GstCaps * caps, gboolean all)
2708 n = gst_caps_get_size (caps);
2709 for (i = 0; i < n; i++) {
2710 GstStructure *s = gst_caps_get_structure (caps, i);
2713 gst_structure_remove_field (s, "alignment");
2714 gst_structure_remove_field (s, "stream-format");
2716 gst_structure_remove_field (s, "parsed");
2721 gst_h265_parse_get_caps (GstBaseParse * parse, GstCaps * filter)
2723 GstCaps *peercaps, *templ;
2724 GstCaps *res, *tmp, *pcopy;
2726 templ = gst_pad_get_pad_template_caps (GST_BASE_PARSE_SINK_PAD (parse));
2728 GstCaps *fcopy = gst_caps_copy (filter);
2729 /* Remove the fields we convert */
2730 remove_fields (fcopy, TRUE);
2731 peercaps = gst_pad_peer_query_caps (GST_BASE_PARSE_SRC_PAD (parse), fcopy);
2732 gst_caps_unref (fcopy);
2734 peercaps = gst_pad_peer_query_caps (GST_BASE_PARSE_SRC_PAD (parse), NULL);
2736 pcopy = gst_caps_copy (peercaps);
2737 remove_fields (pcopy, TRUE);
2739 res = gst_caps_intersect_full (pcopy, templ, GST_CAPS_INTERSECT_FIRST);
2740 gst_caps_unref (pcopy);
2741 gst_caps_unref (templ);
2744 GstCaps *tmp = gst_caps_intersect_full (res, filter,
2745 GST_CAPS_INTERSECT_FIRST);
2746 gst_caps_unref (res);
2750 /* Try if we can put the downstream caps first */
2751 pcopy = gst_caps_copy (peercaps);
2752 remove_fields (pcopy, FALSE);
2753 tmp = gst_caps_intersect_full (pcopy, res, GST_CAPS_INTERSECT_FIRST);
2754 gst_caps_unref (pcopy);
2755 if (!gst_caps_is_empty (tmp))
2756 res = gst_caps_merge (tmp, res);
2758 gst_caps_unref (tmp);
2760 gst_caps_unref (peercaps);
2765 gst_h265_parse_event (GstBaseParse * parse, GstEvent * event)
2768 GstH265Parse *h265parse = GST_H265_PARSE (parse);
2770 switch (GST_EVENT_TYPE (event)) {
2771 case GST_EVENT_CUSTOM_DOWNSTREAM:
2773 GstClockTime timestamp, stream_time, running_time;
2774 gboolean all_headers;
2777 if (gst_video_event_is_force_key_unit (event)) {
2778 gst_video_event_parse_downstream_force_key_unit (event,
2779 ×tamp, &stream_time, &running_time, &all_headers, &count);
2781 GST_INFO_OBJECT (h265parse, "received downstream force key unit event, "
2782 "seqnum %d running_time %" GST_TIME_FORMAT
2783 " all_headers %d count %d", gst_event_get_seqnum (event),
2784 GST_TIME_ARGS (running_time), all_headers, count);
2785 if (h265parse->force_key_unit_event) {
2786 GST_INFO_OBJECT (h265parse, "ignoring force key unit event "
2787 "as one is already queued");
2789 h265parse->pending_key_unit_ts = running_time;
2790 gst_event_replace (&h265parse->force_key_unit_event, event);
2792 gst_event_unref (event);
2795 res = GST_BASE_PARSE_CLASS (parent_class)->sink_event (parse, event);
2800 case GST_EVENT_FLUSH_STOP:
2801 h265parse->push_codec = TRUE;
2802 res = GST_BASE_PARSE_CLASS (parent_class)->sink_event (parse, event);
2804 case GST_EVENT_SEGMENT:
2806 h265parse->last_report = GST_CLOCK_TIME_NONE;
2808 res = GST_BASE_PARSE_CLASS (parent_class)->sink_event (parse, event);
2812 res = GST_BASE_PARSE_CLASS (parent_class)->sink_event (parse, event);
2819 gst_h265_parse_src_event (GstBaseParse * parse, GstEvent * event)
2822 GstH265Parse *h265parse = GST_H265_PARSE (parse);
2824 switch (GST_EVENT_TYPE (event)) {
2825 case GST_EVENT_CUSTOM_UPSTREAM:
2827 GstClockTime running_time;
2828 gboolean all_headers;
2831 if (gst_video_event_is_force_key_unit (event)) {
2832 gst_video_event_parse_upstream_force_key_unit (event,
2833 &running_time, &all_headers, &count);
2835 GST_INFO_OBJECT (h265parse, "received upstream force-key-unit event, "
2836 "seqnum %d running_time %" GST_TIME_FORMAT
2837 " all_headers %d count %d", gst_event_get_seqnum (event),
2838 GST_TIME_ARGS (running_time), all_headers, count);
2841 h265parse->pending_key_unit_ts = running_time;
2842 gst_event_replace (&h265parse->force_key_unit_event, event);
2845 res = GST_BASE_PARSE_CLASS (parent_class)->src_event (parse, event);
2849 res = GST_BASE_PARSE_CLASS (parent_class)->src_event (parse, event);
2857 gst_h265_parse_set_property (GObject * object, guint prop_id,
2858 const GValue * value, GParamSpec * pspec)
2860 GstH265Parse *parse;
2861 parse = GST_H265_PARSE (object);
2864 case PROP_CONFIG_INTERVAL:
2865 parse->interval = g_value_get_int (value);
2868 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
2874 gst_h265_parse_get_property (GObject * object, guint prop_id, GValue * value,
2877 GstH265Parse *parse;
2878 parse = GST_H265_PARSE (object);
2881 case PROP_CONFIG_INTERVAL:
2882 g_value_set_int (value, parse->interval);
2885 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);