From 05d4a2022e35836a1abf4569b609195d6f0af522 Mon Sep 17 00:00:00 2001 From: Carlos Bentzen <cadubentzen@igalia.com> Date: Fri, 24 Jan 2025 12:07:21 +0100 Subject: [PATCH] h266parse: handle packetized frames Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8359> --- .../gst/videoparsers/gsth266parse.c | 102 +++++++++++++++++- 1 file changed, 101 insertions(+), 1 deletion(-) diff --git a/subprojects/gst-plugins-bad/gst/videoparsers/gsth266parse.c b/subprojects/gst-plugins-bad/gst/videoparsers/gsth266parse.c index b9fe2c400e..78094cacd9 100644 --- a/subprojects/gst-plugins-bad/gst/videoparsers/gsth266parse.c +++ b/subprojects/gst-plugins-bad/gst/videoparsers/gsth266parse.c @@ -1008,7 +1008,107 @@ static GstFlowReturn gst_h266_parse_handle_frame_packetized (GstBaseParse * parse, GstBaseParseFrame * frame) { - return GST_FLOW_NOT_SUPPORTED; + GstH266Parse *h266parse = GST_H266_PARSE (parse); + GstBuffer *buffer = frame->buffer; + GstFlowReturn ret = GST_FLOW_OK; + GstH266ParserResult parse_res; + GstH266NalUnit nalu; + const guint nl = h266parse->nal_length_size; + GstMapInfo map; + gint left; + + GST_TRACE_OBJECT (h266parse, "Handling packetized frame"); + + if (nl < 1 || nl > 4) { + GST_DEBUG_OBJECT (h266parse, "Unsupported NAL length size %d", nl); + return GST_FLOW_NOT_NEGOTIATED; + } + + /* need to save buffer from invalidation upon _finish_frame */ + if (h266parse->split_packetized) + buffer = gst_buffer_copy (frame->buffer); + + gst_buffer_map (buffer, &map, GST_MAP_READ); + + left = map.size; + + GST_LOG_OBJECT (h266parse, + "processing packet buffer of size %" G_GSIZE_FORMAT, map.size); + + parse_res = gst_h266_parser_identify_nalu_vvc (h266parse->nalparser, + map.data, 0, map.size, nl, &nalu); + + while (parse_res == GST_H266_PARSER_OK) { + GST_DEBUG_OBJECT (h266parse, "VVC nal offset %d", nalu.offset + nalu.size); + + /* either way, have a look at it */ + gst_h266_parse_process_nal (h266parse, &nalu); + + /* dispatch per NALU if needed */ + if (h266parse->split_packetized) { + GstBaseParseFrame tmp_frame; + + gst_base_parse_frame_init (&tmp_frame); + tmp_frame.flags |= frame->flags; + tmp_frame.offset = frame->offset; + tmp_frame.overhead = frame->overhead; + tmp_frame.buffer = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_ALL, + nalu.offset, nalu.size); + /* Don't lose timestamp when offset is not 0. */ + GST_BUFFER_PTS (tmp_frame.buffer) = GST_BUFFER_PTS (buffer); + GST_BUFFER_DTS (tmp_frame.buffer) = GST_BUFFER_DTS (buffer); + GST_BUFFER_DURATION (tmp_frame.buffer) = GST_BUFFER_DURATION (buffer); + + /* Set marker on last packet */ + if (nl + nalu.size == left) { + if (GST_BUFFER_FLAG_IS_SET (frame->buffer, GST_BUFFER_FLAG_MARKER)) + h266parse->marker = TRUE; + } + + /* note we don't need to come up with a sub-buffer, since + * subsequent code only considers input buffer's metadata. + * Real data is either taken from input by baseclass or + * a replacement output buffer is provided anyway. */ + gst_h266_parse_parse_frame (parse, &tmp_frame); + ret = gst_base_parse_finish_frame (parse, &tmp_frame, nl + nalu.size); + left -= nl + nalu.size; + } + + parse_res = gst_h266_parser_identify_nalu_vvc (h266parse->nalparser, + map.data, nalu.offset + nalu.size, map.size, nl, &nalu); + } + + gst_buffer_unmap (buffer, &map); + + if (!h266parse->split_packetized) { + h266parse->marker = TRUE; + gst_h266_parse_parse_frame (parse, frame); + ret = gst_base_parse_finish_frame (parse, frame, map.size); + } else { + gst_buffer_unref (buffer); + if (G_UNLIKELY (left)) { + /* should not be happening for nice VVC */ + GST_WARNING_OBJECT (parse, "skipping leftover VVC data %d", left); + frame->flags |= GST_BASE_PARSE_FRAME_FLAG_DROP; + ret = gst_base_parse_finish_frame (parse, frame, map.size); + } + } + + if (parse_res == GST_H266_PARSER_NO_NAL_END || + parse_res == GST_H266_PARSER_BROKEN_DATA) { + + if (h266parse->split_packetized) { + GST_ELEMENT_ERROR (h266parse, STREAM, FAILED, (NULL), + ("invalid VVC input data")); + + return GST_FLOW_ERROR; + } else { + /* do not meddle to much in this case */ + GST_DEBUG_OBJECT (h266parse, "parsing packet failed"); + } + } + + return ret; } static GstFlowReturn