From c7e9aba02505aaff1c595e797f14d68524dbb537 Mon Sep 17 00:00:00 2001 From: Carlos Bentzen Date: Fri, 24 Jan 2025 12:21:35 +0100 Subject: [PATCH] h266parse: negotiate before handling codec_data NALs If we find VPS/SPS/PPS in codec_data and call gst_h266_parse_process_nal with them, we need to have negotiated before in order to correctly process them with flags like h266parse->transform set or not depending on the negotiation. This is important because in certain vvc1/vvi1 streams we may have correct codec_data but faulty parameter sets in the stream and we would want to push the parameter sets from codec_data first. Part-of: --- .../gst/videoparsers/gsth266parse.c | 49 +++++++++---------- 1 file changed, 23 insertions(+), 26 deletions(-) diff --git a/subprojects/gst-plugins-bad/gst/videoparsers/gsth266parse.c b/subprojects/gst-plugins-bad/gst/videoparsers/gsth266parse.c index 8b6c2f4d81..30fdbac685 100644 --- a/subprojects/gst-plugins-bad/gst/videoparsers/gsth266parse.c +++ b/subprojects/gst-plugins-bad/gst/videoparsers/gsth266parse.c @@ -3066,6 +3066,29 @@ gst_h266_parse_set_caps (GstBaseParse * parse, GstCaps * caps) /* get upstream format and align from caps */ gst_h266_parse_format_from_caps (h266parse, caps, &format, &align); + if (format == GST_H266_PARSE_FORMAT_NONE) { + format = GST_H266_PARSE_FORMAT_BYTE; + align = GST_H266_PARSE_ALIGN_AU; + } + + /* It is important that we negotiate the src caps before processing NALs from codec data, + because those NALs should come before in-band NALs. It fixes conditions where e.g. codec data + is valid but there are missing parameter sets in-band. */ + { + GstCaps *in_caps; + + /* prefer input type determined above */ + in_caps = gst_caps_new_simple ("video/x-h266", + "parsed", G_TYPE_BOOLEAN, TRUE, + "stream-format", G_TYPE_STRING, + gst_h266_parse_get_string (h266parse, TRUE, format), + "alignment", G_TYPE_STRING, + gst_h266_parse_get_string (h266parse, FALSE, align), NULL); + /* negotiate with downstream, sets ->format and ->align */ + gst_h266_parse_negotiate (h266parse, format, in_caps); + gst_caps_unref (in_caps); + } + /* packetized video has a codec_data */ if (format != GST_H266_PARSE_FORMAT_BYTE && (value = gst_structure_get_value (str, "codec_data"))) { @@ -3105,12 +3128,6 @@ gst_h266_parse_set_caps (GstBaseParse * parse, GstCaps * caps) } } - /* don't confuse codec_data with inband vps/sps/pps */ - h266parse->have_vps_in_frame = FALSE; - h266parse->have_sps_in_frame = FALSE; - h266parse->have_pps_in_frame = FALSE; - h266parse->have_aps_in_frame = FALSE; - gst_h266_decoder_config_record_free (config); gst_buffer_unmap (codec_data, &map); } else { @@ -3119,26 +3136,6 @@ gst_h266_parse_set_caps (GstBaseParse * parse, GstCaps * caps) h266parse->packetized = FALSE; /* we have 4 sync bytes */ h266parse->nal_length_size = 4; - - if (format == GST_H266_PARSE_FORMAT_NONE) { - format = GST_H266_PARSE_FORMAT_BYTE; - align = GST_H266_PARSE_ALIGN_AU; - } - } - - { - GstCaps *in_caps; - - /* prefer input type determined above */ - in_caps = gst_caps_new_simple ("video/x-h266", - "parsed", G_TYPE_BOOLEAN, TRUE, - "stream-format", G_TYPE_STRING, - gst_h266_parse_get_string (h266parse, TRUE, format), - "alignment", G_TYPE_STRING, - gst_h266_parse_get_string (h266parse, FALSE, align), NULL); - /* negotiate with downstream, sets ->format and ->align */ - gst_h266_parse_negotiate (h266parse, format, in_caps); - gst_caps_unref (in_caps); } if (format == h266parse->format && align == h266parse->align) {