Projects
home:zaitor:branches:Essentials
gstreamer-plugins-bad-codecs
Sign Up
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
Expand all
Collapse all
Changes of Revision 3
View file
gstreamer-plugins-bad-codecs.spec
Changed
@@ -7,7 +7,7 @@ %define _version 1.28.0 Name: gstreamer-plugins-bad-codecs -Version: 1.28.8 +Version: 1.28.9 Release: 0 Summary: Codecs/plugins for gstreamer-plugins-bad License: LGPL-2.1-or-later
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/ChangeLog -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/ChangeLog
Changed
@@ -1,3 +1,1767 @@ +=== release 1.28.9 === + +2026-11-06 12:54:37 +0000 Tim-Philipp Müller <tim@centricular.com> + + * gst-plugins-bad.doap: + * meson.build: + Release 1.28.9 + +2026-11-06 10:56:54 +0000 Tim-Philipp Müller <tim@centricular.com> + + * scripts/dist-common-files.py: + scripts: dist-common-files: update for new release notes formatting + +2026-10-29 10:42:48 +0200 Sebastian Dröge <sebastian@centricular.com> + + * gst-libs/gst/mpegts/gstmpegtssection.c: + mpegtssection: Fix potential under-read when reading the section CRC + +2026-10-29 10:38:30 +0200 Sebastian Dröge <sebastian@centricular.com> + + * gst-libs/gst/mpegts/gst-dvb-section.c: + dvb-section: Fix transport_stream_loop_length underflow in NIT/BAT + +2026-10-29 01:09:39 +0200 Sebastian Dröge <sebastian@centricular.com> + + * gst-libs/gst/mpegts/gst-scte-section.c: + scte-section: Fix out of bounds reads in splice_info_section parsing + Adds missing and fixes wrong bounds checks. + +2026-10-29 01:09:38 +0200 Sebastian Dröge <sebastian@centricular.com> + + * gst-libs/gst/mpegts/gst-atsc-section.c: + atsc-section: Validate RRT and MGT lengths against the section end + +2026-10-29 01:09:30 +0200 Sebastian Dröge <sebastian@centricular.com> + + * gst-libs/gst/mpegts/gst-dvb-section.c: + dvb-section: Validate descriptor loop lengths in EIT/TOT/SIT + +2026-10-29 01:09:29 +0200 Sebastian Dröge <sebastian@centricular.com> + + * gst-libs/gst/mpegts/gstmpegtsdescriptor.c: + mpegtsdescriptor: Fix out of bounds reads when parsing descriptors + Various places trusted the advertised payload size without checking + that enough data is actually available. + +2026-10-29 01:09:06 +0200 Sebastian Dröge <sebastian@centricular.com> + + * gst-libs/gst/mpegts/gst-dvb-descriptor.c: + dvb-descriptor: Fix out of bounds reads on truncated descriptors + Add bounds checks for truncated DVB descriptors where the payload size was + previously trusted blindly. + Also make sure to initialize out parameters in all conditions. + Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/5312 + +2026-10-30 17:34:25 +0200 Sebastian Dröge <sebastian@centricular.com> + + * gst/mpegtsmux/gstbasetsmux.c: + basetsmux: Clear the pts_adjustment high bit before setting it + The highest pts_adjustment bit is OR-ed into the copied section data + instead of replacing the original bit, so a section whose original + adjustment had that bit set kept it whenever the computed adjustment + had it cleared, adding a spurious 2^32 to the splice times. Replace + the bit instead, leaving the surrounding flags untouched. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12919> + +2026-10-29 18:57:05 +0200 Sebastian Dröge <sebastian@centricular.com> + + * gst/mpegtsmux/gstbasetsmux.c: + basetsmux: Packetize manually created SCTE sections + handle_scte35_section() assumed that any section that is not in the + running-time domain comes from tsdemux and has a serialized + representation, and asserted on section->data otherwise. Applications + are free to clear is_running_time to feed their splice times already + expressed in the MPEG time domain though, and manually created + sections from gst_mpegts_section_from_scte_sit() have no serialized + representation, which made the muxer abort on them. + Packetize such sections instead and use the result as if it came from + the demuxer, its splice times are in the right domain already and + only the PTS adjustment is missing. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12919> + +2026-10-29 11:13:46 +0200 Sebastian Dröge <sebastian@centricular.com> + + * gst-libs/gst/mpegts/gst-atsc-section.c: + atsc-section: Copy compressed data when parsing string segments + Let's avoid double frees. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12919> + +2026-10-29 10:42:49 +0200 Sebastian Dröge <sebastian@centricular.com> + + * gst-libs/gst/mpegts/gst-scte-section.c: + scte-section: Fix critical on early splice event parse errors + Don't unref NULL pointer arrays. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12919> + +2026-10-30 17:02:29 +0200 Sebastian Dröge <sebastian@centricular.com> + + * gst-libs/gst/mpegts/gstmpegtssection.c: + mpegtssection: Require long sections to be at least 12 bytes long + A long section consists of 3 header bytes, the 5 bytes for subtable + extension, version, section number and last section number, and the + 4 byte CRC. That makes 12 bytes, which is also what the comment said, + while the check only required 11. Align the check and the warning + message with the comment. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12919> + +2026-10-29 12:45:54 +0200 Sebastian Dröge <sebastian@centricular.com> + + * gst-libs/gst/mpegts/gst-dvb-section.h: + dvb-section: Use the correct boxed GType for BAT streams + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12919> + +2026-10-29 12:45:22 +0200 Sebastian Dröge <sebastian@centricular.com> + + * gst-libs/gst/mpegts/gst-dvb-descriptor.c: + dvb-descriptor: Deep copy members of the extended event descriptor copy + Let's avoid double frees. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12919> + +2026-10-29 11:14:10 +0200 Sebastian Dröge <sebastian@centricular.com> + + * gst-libs/gst/mpegts/gst-scte-section.c: + scte-section: Write splice_count in serialized schedule commands + The splice_schedule command starts with a splice_count byte that + the parser consumes before reading that many splice events, but + _packetize_sit() never wrote it. Serializing a schedule section + with a number of events other than one and parsing it back + therefore lost or corrupted the events. Count and emit the byte + for the schedule command. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12919> + +2026-10-29 11:13:41 +0200 Sebastian Dröge <sebastian@centricular.com> + + * gst-libs/gst/mpegts/gstmpegtsdescriptor.c: + mpegtsdescriptor: Escape control codes as bytes in EUC-KR + EUC-KR is not a fixed-width encoding: iconv() emits characters as + either single US-ASCII bytes or two KS X 1001 bytes >= 0xA1. The + control code escaping ran the fixed-width 16-bit BE pass over the + converted text, which read one byte past the end for odd sizes and + never escaped an unaligned LF. + Handle EUC-KR separately: EN 300 468 (annex A, table A.2) requires + CR/LF in two byte character tables to be transmitted as the control + code 0xE0 0x8A, and since a LF byte cannot occur within a KS X 1001 + double byte, replace each LF with the escape sequence while + widening the buffer as needed. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12919> + +2026-10-29 10:42:21 +0200 Sebastian Dröge <sebastian@centricular.com> + + * gst-libs/gst/mpegts/gst-atsc-section.c: + atsc-section: Deep copy owned members in boxed copy functions + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12919> + +2026-10-29 10:42:08 +0200 Sebastian Dröge <sebastian@centricular.com> + + * gst-libs/gst/mpegts/gst-atsc-section.c: + atsc-section: Fix MGT and RRT packetization + _packetize_mgt() indexed the tables array with a literal 1 instead of + the loop variable, dereferencing an uninitialized GPtrArray slot when + the table array held less than two entries, and it reserved 11 bytes + per table in the output buffer but only wrote 7, emitting + uninitialized heap memory in place of the never written + table_type_number_bytes field. + _packetize_rrt() counted the packetized size of each dimension's names + but serialized the top-level region names instead, overflowing the + output buffer whenever the region names were larger, and the + dimensions_defined field was counted but never written. + Also make the multi string helpers tolerate NULL string arrays and + multi strings without a segments array instead of dereferencing them: + there is no public constructor for the nested multi string types, so + applications have to build them with NULL arrays. + _parse_rrt() read dimensions_defined together with its 3 reserved bits + which are set on the wire and by the packetizer, inflating the parsed + count past the end of the section data; mask them out. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12919> + +2026-10-29 10:37:52 +0200 Sebastian Dröge <sebastian@centricular.com> + + * gst-libs/gst/mpegts/gst-dvb-descriptor.c: + * gst-libs/gst/mpegts/gstmpegtsdescriptor.c: + mpegtsdescriptor: Validate payload sizes in descriptor creation functions + The internal descriptor constructors take a guint8 length while the + public creators take a gsize, silently truncating it before the + allocation but not before the payload memcpy. + Also initialize the size variable in gst_mpegts_descriptor_from_dvb_network_name(), + it was read uninitialized when encoding failed. + Also reject a NULL struct in gst_mpegts_descriptor_from_jpeg_xs(), + which dereferenced it immediately. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12919> + +2026-10-18 09:23:21 -0400 Nicolas Dufresne <nicolas.dufresne@collabora.com> + + * gst-libs/gst/codecparsers/gsth265parser.c: + h265parser: Initialize sps_ext structure + The parsed data is being discarded in both cases. There is no visible side + effect of initializing these structure, but the path is rather complex. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/13000> + +2026-10-16 15:45:52 -0400 Nicolas Dufresne <nicolas.dufresne@collabora.com> + + * gst-libs/gst/codecparsers/gsth265parser.c: + h265parser: Fix use of uninitialized HRD parameters + This issue causes undefined behaviour that can be detected with specific + stream and valgrind. Avoid this by clearing the entire structure before + filling it. + Fixes #5332 + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/13000> + +2026-10-29 00:27:33 +0200 Sebastian Dröge <sebastian@centricular.com> + + * gst/mxf/mxfdemux.c: + mxfdemux: use the demuxer as logging object for a warning + Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/-/work_items/5392 + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12998> + +2026-10-21 20:23:40 +0200 François Laignel <francois@centricular.com> + + * gst/mxf/mxfdemux.c: + mxfdemux: check slice index before reading slice offset + The slice index in a delta entry comes from a potentially malicious source, it + can be out of range and can't be checked beforehand. Add bounds checks before + indexing into the slice offset array. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12998> + +2026-10-27 12:21:24 +0200 Sebastian Dröge <sebastian@centricular.com> + + * gst/mxf/mxfdemux.c: + * gst/mxf/mxfdemux.h: + mxfdemux: only use delta entries of a consistent index search domain + The delta lookup table is a property of a single index segment, but the + position of a track in that table is stored on the track and used with + every segment of the index search domain. This only works if all segments + of the domain use the same delta table, which is not guaranteed for + malicious files. + Drop the delta entries of a domain as soon as one of its segments uses a + different table, so that tracks fall back to ignoring delta entries + instead of applying entries taken from an unrelated table. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12998> + +2026-10-16 18:19:54 +0200 François Laignel <francois@centricular.com> + + * gst/mxf/mxfdemux.c: + * gst/mxf/mxfdemux.h: + mxfdemux: fix out-of-bounds read when looking up delta entry by delta_id + etrack->delta_id uses negative values to encode UNKNOWN or IGNORE. All reads + into the segment->delta_entries array using etrack->delta_id must ensure + delta_id refers to an entry of the segment read from. + fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/-/work_items/5352 + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12998> + +2026-11-05 09:47:32 +0200 Sebastian Dröge <sebastian@centricular.com> + + * gst/asfmux/gstasfparse.c: + asfparse: Clamp object sizes to G_MAXUINT32 + The minimum frame size API of baseparse takes a guint32. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/13006> + +2026-11-05 09:46:55 +0200 Sebastian Dröge <sebastian@centricular.com> + + * gst/asfmux/gstasfobjects.c: + * gst/asfmux/gstasfobjects.h: + asfmux: asfobjects: Reject packet sizes below the smallest possible packet + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/13006> + +2026-11-05 09:38:13 +0200 Sebastian Dröge <sebastian@centricular.com> + + * gst/asfmux/gstasfobjects.c: + asfmux: asfobjects: Reject header child objects smaller than the object header + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/13006> + +2026-11-05 09:37:14 +0200 Sebastian Dröge <sebastian@centricular.com> + + * gst/asfmux/gstrtpasfpay.c: + rtpasfpay: Add bounds check against the overall packet size + The packet size comes from the packet data. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/13006> + +2026-11-05 09:36:23 +0200 Sebastian Dröge <sebastian@centricular.com> + + * gst/asfmux/gstrtpasfpay.c: + rtpasfpay: Reject packets whose padding is bigger or equal to the packet size + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/13006> + +2026-11-05 09:34:46 +0200 Sebastian Dröge <sebastian@centricular.com> + + * gst/asfmux/gstasfmux.c: + asfmux: Fix header size calculation for non-BMP characters in string tags + The size reserved for string tag values was computed as + 2 * (1 + g_utf8_strlen (text, -1)), which assumes every code point is + 2 bytes in UTF-16. Characters outside the Basic Multilingual Plane are + encoded as surrogate pairs (4 bytes), so the header buffer was + under-allocated by 2 bytes per such character, and + gst_asf_mux_write_string_with_size() then wrote past its end. + Compute the size with the same g_convert() call used by the write path + so that both always agree. + Patch provided by Bruno Fournier. + Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/5321 + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/13006> + +2026-11-04 18:08:28 +0100 Mathieu Duponchelle <mathieu@centricular.com> + + * gst/festival/gstfestival.c: + festival: cap waveform size + The element stores the entire waveform for a single input cue in memory + before outputting it. This can easily result in OOM with malicious + input, for instance a text cue that would cause the festival server to + generate one day's worth of audio samples. + This commit simply puts a 128 MB cap on the maximum waveform size, or + about one hour worth of samples. This value should be more than enough + for legitimate inputs. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/13004> + +2026-10-29 13:51:35 +0100 Mathieu Duponchelle <mathieu@centricular.com> + + * gst/festival/gstfestival.c: + festival: check read return value + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/13004> + +2026-10-22 10:00:37 +0300 Sebastian Dröge <sebastian@centricular.com> + + * gst/vmnc/vmncdec.c: + vmnc: Use the correct stride for the output frames + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/13001> + +2026-10-22 10:00:20 +0300 Sebastian Dröge <sebastian@centricular.com> + + * gst/vmnc/vmncdec.c: + vmnc: Only remember the format descriptor when decoding + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/13001> + +2026-10-22 00:50:27 +0300 Sebastian Dröge <sebastian@centricular.com> + + * gst/vmnc/vmncdec.c: + vmnc: Use unaligned-safe accessors for pixel data + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/13001> + +2026-10-22 00:01:53 +0300 Sebastian Dröge <sebastian@centricular.com> + + * gst/vmnc/vmncdec.c: + vmnc: Use a lower bound for WMVi screen dimensions + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/13001> + +2026-10-21 18:32:27 +0300 Sebastian Dröge <sebastian@centricular.com> + + * gst/vmnc/vmncdec.c: + vmnc: Drop colour cursor on pixel format change + The cursor buffers are allocated with the bytes_per_pixel that were in + use when they were allocated, but render_colour_cursor() indexes them + with the current bytes_per_pixel. We have to drop the cursors until a + new WMVd arrives. + Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/-/work_items/5308 + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/13001> + +2026-11-04 14:57:07 +0100 Piotr Brzeziński <piotr@centricular.com> + + * sys/androidmedia/gstamcaudiodec.c: + * sys/androidmedia/gstamcvideodec.c: + androidmedia: Don't wait for input buffers after the srcpad loop stopped + If the loop stopped with EOS or an error while the codec's input was + full, handle_frame waited for an input buffer forever. It now bails out + and returns the last downstream result. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12996> + +2026-11-04 13:36:57 +0100 Piotr Brzeziński <piotr@centricular.com> + + * sys/androidmedia/gstamcaudiodec.c: + * sys/androidmedia/gstamcvideodec.c: + androidmedia: Fix drain deadlock when the srcpad loop stops + If the srcpad loop stopped before a drain started waiting for it, + draining would then get stuck. It held the upstream stream lock, so if + the upstream was a queue, that queue couldn't then pause for the flush + start, locking everything up. This simply adds a check before we start + waiting and returns the actual downstream push result instead of always + OK. Also added a missing save of the downstream ret value after a failed + frame allocation in the video dec. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12996> + +2026-10-04 16:42:25 +0900 Daeho Ro <email@daeho.ro> + + * ext/faac/gstfaac.h: + * ext/faac/meson.build: + * tests/check/meson.build: + faac: detect libfaac via pkg-config first + faac has installed a faac.pc since 1.31. Use it when available and only + fall back to the faac.h symbol check plus cc.find_library() for older + releases without one. Like other plugins, skip all dependency checks + when the plugin is disabled. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12985> + +2026-09-29 21:36:28 +0900 Daeho Ro <email@daeho.ro> + + * ext/faac/gstfaac.c: + faac: pass caller_size to faac_params_init() for faac >= 2.2 + faac 2.2 bumped FAAC_VERSION_MAJOR and the library SONAME to 2 and + added a caller_size argument to faac_params_init(). Pass sizeof(params) + when FAAC_VERSION_MAJOR >= 2 and keep the one-argument call for faac + 2.0 and 2.1. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12985> + +2026-07-20 20:50:06 +0900 Daeho Ro <email@daeho.ro> + + * ext/faac/gstfaac.c: + * ext/faac/gstfaac.h: + * ext/faac/meson.build: + faac: support faac >= 2.0 (faac_* API) + faac 2.0 removed the legacy faacEnc* API and bumped the library SONAME + to 1. Detect the new API via FAAC_VERSION_MAJOR and use it when + available, keeping the faacEnc* path for faac 1.x. + With the new API the pad templates only offer the lc profile: faac 2.0 + dropped the MAIN/SSR/LTP object types, which were never actually + implemented by libfaac. The AudioSpecificConfig buffer is library-owned + in the new API and must not be freed. The meson header check now accepts + either faacEncOpen (1.x) or faac_encoder_open (2.0). + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12985> + +2026-11-05 09:39:22 +0200 Sebastian Dröge <sebastian@centricular.com> + + * gst/asfmux/gstasfobjects.c: + asfmux: asfobjects: Fix gboolean / GstFlowReturn confusion + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12983> + +2026-11-05 09:37:52 +0200 Sebastian Dröge <sebastian@centricular.com> + + * gst/asfmux/gstasfparse.c: + asfparse: Unmap buffer on parsing errors + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12983> + +2026-02-02 20:57:20 +0530 Nirbheek Chauhan <nirbheek@centricular.com> + + * gst-libs/gst/vulkan/ios/gstvkwindow_ios.m: + vulkan/ios: Remove internal_view from the superview when closing + Otherwise we will leave a dangling pointer in the UIView hierarchy, + and any code that encounters it will crash. This allows the iOS app to + reuse the UIView across pipeline instances. + Same fix as eagl. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12975> + +2026-10-22 10:29:15 +0300 Sebastian Dröge <sebastian@centricular.com> + + * gst/librfb/rfbdecoder.c: + rfbsrc: Guard against missing previous frame buffer in update requests + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12972> + +2026-10-22 10:16:57 +0300 Sebastian Dröge <sebastian@centricular.com> + + * gst/librfb/rfbdecoder.c: + rfbsrc: Treat unknown server messages as a fatal error + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12972> + +2026-10-22 10:10:23 +0300 Sebastian Dröge <sebastian@centricular.com> + + * gst/librfb/rfbdecoder.c: + rfbsrc: Reset the decoder state when disconnecting + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12972> + +2026-10-22 10:04:07 +0300 Sebastian Dröge <sebastian@centricular.com> + + * gst/librfb/gstrfbsrc.c: + * gst/librfb/rfbdecoder.c: + rfbsrc: Validate the framebuffer pixel format + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12972> + +2026-10-22 00:47:43 +0300 Sebastian Dröge <sebastian@centricular.com> + + * gst/librfb/rfbdecoder.c: + rfbsrc: Avoid unaligned writes when filling rectangles + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12972> + +2026-10-22 00:20:16 +0300 Sebastian Dröge <sebastian@centricular.com> + + * gst/librfb/rfbdecoder.c: + rfbsrc: Bound the framebuffer dimensions + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12972> + +2026-10-22 00:05:13 +0300 Sebastian Dröge <sebastian@centricular.com> + + * gst/librfb/rfbdecoder.c: + rfbsrc: Do not decode rectangles larger than the framebuffer + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12972> + +2026-10-21 21:51:40 +0300 Sebastian Dröge <sebastian@centricular.com> + + * gst/librfb/rfbdecoder.c: + rfbsrc: Handle 3 bytes per pixel formats when filling rectangles + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12972> + +2026-10-21 21:48:14 +0300 Sebastian Dröge <sebastian@centricular.com> + + * gst/librfb/rfbdecoder.c: + rfbsrc: Bound the length of server provided strings + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12972> + +2026-10-21 21:24:01 +0300 Sebastian Dröge <sebastian@centricular.com> + + * gst/librfb/rfbdecoder.c: + rfbsrc: Reject invalid colour shifts from the server + The pixel format shifts from the server are applied directly to a + guint32 later on; values >= 32 are undefined. Reject such handshakes + instead of producing a bogus video format. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12972> + +2026-10-21 18:57:01 +0300 Sebastian Dröge <sebastian@centricular.com> + + * gst/librfb/gstrfbsrc.c: + * gst/librfb/rfbdecoder.c: + rfbsrc: Write pixels with the stride of the output format + The decoder wrote rows packed at rect_width * bytespp while the + frames and the negotiated caps use the padded stride of the output + format, shifting all rows for formats like RGB with a padded stride. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12972> + +2026-10-21 18:46:16 +0300 Sebastian Dröge <sebastian@centricular.com> + + * gst/librfb/gstrfbsrc.c: + rfbsrc: Reinitialize decoder state on stop + With inited left set, start() skipped the reconnect and handshake and + fill() copied from the freed frame buffer after a state cycle. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12972> + +2026-10-21 18:46:08 +0300 Sebastian Dröge <sebastian@centricular.com> + + * gst/librfb/gstrfbsrc.c: + rfbsrc: Zero the frame buffers + Frame areas not covered by the server updates and the stride padding + of the output format were never written, leaking uninitialized heap + memory into the output buffers. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12972> + +2026-10-21 18:45:50 +0300 Sebastian Dröge <sebastian@centricular.com> + + * gst/librfb/rfbdecoder.c: + rfbsrc: Do not read subrectangles when there are none + A hextile tile may legitimately contain zero subrectangles. Passing 0 + to rfb_decoder_read() failed its length assertion and tore down the + connection. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12972> + +2026-10-21 18:45:25 +0300 Sebastian Dröge <sebastian@centricular.com> + + * gst/librfb/rfbdecoder.c: + rfbsrc: Handle framebuffer updates with zero rectangles + n_rects is only tested after being decremented, so an update with no + rectangles would keep the state machine from ever completing the frame, + letting a server stall the source task indefinitely. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12972> + +2026-10-21 18:45:09 +0300 Sebastian Dröge <sebastian@centricular.com> + + * gst/librfb/rfbdecoder.c: + rfbsrc: Do not use server strings without termination + The reason and ServerCutText strings sent by the server are not + NUL-terminated on the wire. Copying them with g_strndup() before + printing avoids out-of-bounds reads when formatting the warning and + GError messages, and negative lengths are now rejected. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12972> + +2026-10-21 18:44:44 +0300 Sebastian Dröge <sebastian@centricular.com> + + * gst/librfb/rfbdecoder.c: + rfbsrc: Do not decode CopyRect when it was not negotiated + A malicious server can send CopyRect-encoded rectangles although the + encoding was never requested. The prev_frame backup buffer is only + allocated when the use-copyrect property is set, so decoding such a + rectangle reads through a NULL base pointer. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12972> + +2026-10-22 10:56:04 -0700 Xavier Claessens <xclaessens@netflix.com> + + * gst/videoparsers/gsth265parse.c: + h265parse: Fix have_vcl_in_frame flag + In the packetized path, have_vcl_in_frame was being set after + gst_h265_parse_parse_frame() had already used it and reset it, and from + the previous frame's last NAL. and the first frame always got duration + 0. The flag is now set inside the loop for each NAL, right after + gst_h265_parse_process_nal(), which is how h266parse already does it. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12733> + +2026-04-16 12:02:01 -0400 Detlev Casanova <detlev.casanova@collabora.com> + + * tests/check/elements/h264parse.c: + tests: h264parse: Add test to ensure non-VCL NALs have a DTS of 0 + Some non-VCL NALs can have invalid duration values, which could make + gstreamer drop future VCL NALs. + Make sure non-VCL always have a 0 duration. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12733> + +2026-04-16 10:30:20 -0400 Detlev Casanova <detlev.casanova@collabora.com> + + * tests/check/elements/h266parse.c: + tests: h266parse: Add test to ensure non-VCL NALs have a DTS of 0 + Some non-VCL NALs can have invalid duration values, which could make + gstreamer drop future VCL NALs. + Make sure non-VCL always have a 0 duration. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12733> + +2026-04-16 10:28:20 -0400 Detlev Casanova <detlev.casanova@collabora.com> + + * gst/videoparsers/gsth266parse.c: + * gst/videoparsers/gsth266parse.h: + h266parse: only extrapolate duration for vcl nal + Without this change we're extrapolating nal duration even for non-vcl nal, which + lead to incorrect duration, incorrect dts and incorrect pts and cause + frame-drop. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12733> + +2026-03-24 11:18:03 -0400 Detlev Casanova <detlev.casanova@collabora.com> + + * tests/check/elements/h265parse.c: + tests: h265parse: Add test to ensure non-VCL NALs have a DTS of 0 + Some non-VCL NALs can have invalid duration values, which could make + gstreamer drop future VCL NALs. + Make sure non-VCL always have a 0 duration. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12733> + +2025-02-07 16:17:12 -0500 Daniel Morin <daniel.morin@collabora.com> + + * gst/videoparsers/gsth265parse.c: + * gst/videoparsers/gsth265parse.h: + h265parse: only extrapolate duration for vcl nal + - Without this change we're extrapolating nal duration even for non-vcl nal, which + lead to incorrect duration, incorrect dts and incorrect pts and cause + frame-drop. + Fixes: #4099 + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12733> + +2026-10-30 20:03:00 +0530 Nirbheek Chauhan <nirbheek.chauhan@coram.ai> + + * gst-libs/gst/codecparsers/gsth264parser.c: + * gst-libs/gst/codecparsers/gsth265parser.c: + * gst-libs/gst/codecparsers/gsth266parser.c: + * gst/videoparsers/gsth264parse.c: + * gst/videoparsers/gsth265parse.c: + * gst/videoparsers/gsth266parse.c: + * tests/check/elements/h264parse.c: + * tests/check/libs/h264parser.c: + * tests/check/libs/h265parser.c: + * tests/check/libs/h266parser.c: + codecparsers: h26x: Reject NALs with forbidden_zero_bit set + Reject forbidden headers in H.264, H.265 and H.266 NAL identification. + When splitting packetized input, skip invalid chunks while preserving + valid NALs before and after them. + Reject forbidden headers in direct H.264 subset SPS parsing as well. + Otherwise, camera metadata can be accepted as a parameter set and + corrupt the stream dimensions. Add regression coverage for these paths. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12962> + +2026-11-03 07:14:05 +0100 Edward Hervey <edward@centricular.com> + + * gst-libs/gst/codecparsers/gsth265parser.c: + * tests/check/libs/h265parser.c: + codecparsers: h265: Free SEI payload when parsing fails + gst_h265_parser_parse_sei_message() returns the payload parser result + directly, bypassing the error label that frees the message. A malformed + picture timing SEI that fails after the decoding unit arrays were + allocated leaked them: the failed message is never appended to the + array, so its clear function never runs. + Take the error path when a payload parser fails. + The decoding unit arrays are also allocated for a single decoding unit, + but the free and copy functions keyed off num_decoding_units_minus1 and + skipped them. Free them unconditionally, and copy them based on whether + the source has them. + oss-fuzz: 5916135967752192 (issue 580193202) + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12959> + +2026-09-19 15:55:56 +0200 Mark Nauwelaerts <mnauw@users.sourceforge.net> + + * gst/mpegdemux/gstmpegdemux.c: + mpegdemux: increase gap thresholds + Fixes #5317 + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12946> + +2026-09-19 15:55:38 +0200 Mark Nauwelaerts <mnauw@users.sourceforge.net> + + * gst/mpegdemux/gstmpegdemux.c: + mpegdemux: compare to segment position for sending gap updates + Fixes #5317 + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12946> + +2026-11-01 09:54:58 +0000 Daniel Golle <daniel@makrotopia.org> + + * sys/v4l2codecs/gstv4l2codech264dec.c: + * sys/v4l2codecs/gstv4l2codech265dec.c: + v4l2codecs: h264, h265: negotiate with the first picture + When the caps carry codec data, the sequence is parsed while decodebin + pushes the sticky events into the new decoder, before it exposes the + decoder's src pad. Negotiating right there sends the allocation query + to a pad nothing answers, so DMABuf caps are found without GstVideoMeta + and the caps event fails with not-negotiated. Record that negotiation + is needed and do it when the first picture starts, as the AV1 decoder + already does; by then the pad is exposed and linked to the sink. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12940> + +2026-10-31 21:17:31 +0200 Sebastian Dröge <sebastian@centricular.com> + + * gst-libs/gst/codecparsers/gsth266parser.c: + * gst-libs/gst/codecparsers/gsth266parser.h: + h266parser: Fix out-of-bounds write when parsing DCI + The corresponding API is currently not called by anything in-tree. + Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/5323 + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12926> + +2026-05-20 13:24:18 +0200 Benjamin Gaignard <benjamin.gaignard@collabora.com> + + * sys/v4l2codecs/gstv4l2codecmpeg2dec.c: + v4l2codecs: mpeg2: Reset pool size when discarding source pool + When releasing the source pool, reset pool minimum size to avoid + allocating too much buffers on an other session. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12922> + +2026-05-20 13:23:23 +0200 Benjamin Gaignard <benjamin.gaignard@collabora.com> + + * sys/v4l2codecs/gstv4l2codecav1dec.c: + v4l2codecs: av1: Reset pool size when discarding source pool + When releasing the source pool, reset pool minimum size to avoid + allocating too much buffers on an other session. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12922> + +2026-05-20 13:22:34 +0200 Benjamin Gaignard <benjamin.gaignard@collabora.com> + + * sys/v4l2codecs/gstv4l2codech265dec.c: + v4l2codecs: h265: Reset pool size when discarding source pool + When releasing the source pool, reset pool minimum size to avoid + allocating too much buffers on an other session. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12922> + +2026-05-19 10:25:46 +0200 Benjamin Gaignard <benjamin.gaignard@collabora.com> + + * sys/v4l2codecs/gstv4l2codech264dec.c: + v4l2codecs: h264: Minimize memory allocation + Be smarter when allocating sink and source memory pools to reduce the + memory footprint. Use gst_v4l2_decoder_get_render_delay() to know the + need number of buffers for downstream element. + Reset minimum pool size when discarding the source pool to be sure that + an other session won't use a wrong buffer pool size. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12922> + +2026-05-19 09:03:35 +0200 Benjamin Gaignard <benjamin.gaignard@collabora.com> + + * sys/v4l2codecs/gstv4l2codecvp8dec.c: + v4l2codecs: vp8: Minimize memory allocation + Be smarter when allocating sink and source memory pools to reduce the + memory footprint. Use gst_v4l2_decoder_get_render_delay() to know the + need number of buffers for downstream element. + Reset minimum pool size when discarding the source pool to be sure that + an other session doesn't use a wrong buffer pool size. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12922> + +2026-05-13 16:28:00 +0200 Benjamin Gaignard <benjamin.gaignard@collabora.com> + + * sys/v4l2codecs/gstv4l2codecvp9dec.c: + v4l2codecs: vp9: Minimize memory allocation + Be smarter when allocating sink and source memory pools to reduce the + memory footprint. Use gst_v4l2_decoder_get_render_delay() to know the + need number of buffers for downstream element. + Reset minimum pool size when discarding the source pool to be sure + that an other session doesn't use a wrong buffer pool size. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12922> + +2026-10-09 01:30:12 +0530 Nirbheek Chauhan <nirbheek.chauhan@coram.ai> + + * gst/videoparsers/gsth264parse.c: + * gst/videoparsers/gsth265parse.c: + * gst/videoparsers/gsth266parse.c: + * tests/check/elements/h264parse.c: + * tests/check/elements/h265parse.c: + * tests/check/elements/h266parse.c: + h26*parse: Reject malformed NALs with forbidden_zero_bit set + Some cameras by "MULTITECH SYSTEMS, INC." append custom metadata as + a valid-seeming NAL unit which will pass through the depayloader, and + is expected to be dropped by standards-compliant parsers because the + forbidden_zero_bit is set instead of being unset. + We need to drop such NALs, or we will interpret it as a PPS causing + a resolution change to an absurd value like 16×16 / 16×32 / 48×32. + This was reproduced with an H264 RTSP stream, but the same change + makes sense for H265 and H266 as well. + (cherry picked from commit 07f8674039ebd06708b9e0dc463991d92cbd1173) + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12767> + +2026-10-30 09:30:53 +0100 Edward Hervey <edward@centricular.com> + + * gst/ivfparse/gstivfparse.c: + ivfparse: Reject frame sizes that overflow the size check + frame_size is read from the stream and added to the frame header size as + a guint32 to check that the buffer holds the whole frame. A value close + to G_MAXUINT32 wraps that sum, the check passes, and the frame is then + copied with a size larger than the buffer, tripping a critical in + gst_buffer_copy_region and over-reading when checks are disabled. + Reject frame sizes that do not fit in the sum. + oss-fuzz: 6030072591745024 (issue 578103620) + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12907> + +2026-10-22 16:22:25 +0200 Edward Hervey <edward@centricular.com> + + * gst-libs/gst/codecparsers/gsth265parser.c: + * tests/check/libs/h265parser.c: + codecparsers: h265: Do not overflow conformance window size + The conf_win_*_offset fields are unbounded ue() values. The cropped + size is computed from them in 32-bit arithmetic and stored in gint + fields, so an oversized conformance window wraps around and a + negative crop rectangle width or height is accepted and handed to + decoders. + Sum the offsets in unsigned 64 bit arithmetic, which cannot wrap, and + reject a conformance window that does not leave a non-empty picture. + The h266 parser already bounds these offsets and checks the + conformance window, so only h265 needs the treatment already applied + to h264. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12899> + +2026-10-21 17:22:48 +0300 Sebastian Dröge <sebastian@centricular.com> + + * gst-libs/gst/codecparsers/gsth266parser.c: + h266parser: Validate that rectangular slices fit into the tile grid + The maximum values of slice_{width,height}_in_tiles_minus1 were only checked + against the size of the whole tile grid and ignored the slice's start position. + Because of this, a slice starting at a non-zero tile column or row could extend + past the grid, which could cause out-of-bounds reads of the tile boundary and + size arrays in gst_h266_parser_generate_ctb_map(). + Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/-/work_items/5269 + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12883> + +2026-10-26 16:34:53 +0100 Edward Hervey <edward@centricular.com> + + * gst-libs/gst/codecparsers/gsth266parser.c: + codecparsers: h266: Reject VPS when multi-layer OLS count is zero + num_dpb_params_minus1 and num_ols_timing_hrd_params_minus1 are read with + an upper bound of num_multi_layer_olss - 1. When num_multi_layer_olss is + 0 that bound underflows to G_MAXUINT, so an unbounded value is accepted + and then drives the dpb and ols-hrd parse loops past the end of their + arrays. The spec range for both elements is empty in that case, so + reject the VPS instead. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12874> + +2026-10-24 09:34:46 +0200 Edward Hervey <edward@centricular.com> + + * gst/videoparsers/h263parse.c: + * tests/check/elements/h263parse.c: + videoparsers: h263: Reject zero custom picture clock frequency code + The custom_pc_clock_freq code in the CPCFC is 7 bits and the value 0 + is reserved (valid range 1..127), but the parser fed it straight to + gst_util_uint64_scale_int() as the denominator of the frame rate. + A stream carrying code 0 therefore tripped the + _gst_util_uint64_scale_int() assertion. Reject the header instead, as + for the other corrupt header fields, and let the element fall back to + passthrough. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12874> + +2026-10-23 16:40:55 +0200 Edward Hervey <edward@centricular.com> + + * gst-libs/gst/codecparsers/gstav1parser.c: + * tests/check/elements/av1parse.c: + codecparsers: av1: Do not left-shift a negative global motion value + The global motion parameters scale the decoded sub-exponential value + to the warp model precision by left-shifting it. The decoded value is + signed, and left-shifting a negative int is undefined behaviour. + Check the parse status before using the value, then scale it by + multiplication; the product fits a gint for every warp model type. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12874> + +2026-10-23 15:35:10 +0200 Edward Hervey <edward@centricular.com> + + * gst/videoparsers/gsth265parse.c: + * tests/check/elements/h265parse.c: + videoparsers: h265: Skip timecode meta when VUI time_scale is zero + The timecode SEI scales the frame count by + fps_n * num_units_in_tick / (fps_d * time_scale). time_scale is + parsed from the VUI without a range check; a zero value makes the + denominator zero and trips the assertion in gst_util_uint64_scale(). + Warn and skip the timecode meta when the scale denominator is zero. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12874> + +2026-10-23 15:35:09 +0200 Edward Hervey <edward@centricular.com> + + * gst-libs/gst/codecparsers/gstav1parser.c: + * tests/check/elements/av1parse.c: + codecparsers: av1: Fail parse on frame size reference to an unfilled slot + A frame header can derive its size from a reference frame slot. The + slot only carries a meaningful size once a frame using it has been + parsed; a stream can reference a slot that was never filled, which + holds a zero frame size. The zero size propagated into the tile grid + computation, which divides by the width of the widest tile in + superblocks; with a zero-sized frame no tile width is read and that + divisor stays zero. + Fail the parse with a missing-reference error when the referenced slot + has no known size. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12874> + +2026-10-23 14:20:40 +0200 Edward Hervey <edward@centricular.com> + + * gst-libs/gst/codecparsers/gsth266parser.c: + * tests/check/elements/h266parse.c: + codecparsers: h266: Do not assert on SPS/PPS state in slice parsing + gst_h266_parser_set_active_sps_pps() asserted that the active SPS + has a VPS and that the SPS and PPS are valid. A crafted stream can + reach it with an SPS that was parsed without a VPS: the slice header + parse only checks that the referenced SPS and PPS exist. The assert + then aborts the process instead of failing the parse. + Turn the asserts into a parse failure; the only caller already + handles the error return. + oss-fuzz: 5808758765453312 (issue 577715859) + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12874> + +2026-10-23 13:38:14 +0200 Edward Hervey <edward@centricular.com> + + * gst-libs/gst/codecparsers/gstav1parser.c: + * tests/check/elements/av1parse.c: + codecparsers: av1: Fix integer overflow in av1_bitstreamfn_le + av1_bitstreamfn_le() assembles an n-byte little-endian number by + shifting each byte by i * 8. The bytes are promoted to int, so a + value whose top byte is 0x80 or greater, such as tg_size_minus_1 of + a tile group with explicit sizes, caused a signed left shift + overflow, which is undefined behaviour. + Cast the byte to guint before shifting. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12874> + +2026-10-23 13:25:35 +0200 Edward Hervey <edward@centricular.com> + + * gst-libs/gst/codecparsers/gsth266parser.c: + * tests/check/elements/h266parse.c: + codecparsers: h266: Replace asserts in ref_pic_lists parsing + gst_h266_ref_pic_lists() asserted that the SPS holds at least one + reference picture list for each list signalled with rpl_sps_flag, + and that num_long_term_pic matches the number of long term pictures + read from the bitstream. Crafted streams can violate both: with + rpl1_idx_present_flag equal to 0 the second list copies the flags + of the first one even when the SPS has no lists, and the long term + count is read independently of the entries that follow it. + Turn both asserts into a parse failure so that malformed streams are + rejected instead of aborting the process. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12874> + +2026-10-26 16:38:02 +0100 Edward Hervey <edward@centricular.com> + + * gst-libs/gst/codecparsers/gsth266parser.c: + * tests/check/elements/h266parse.c: + codecparsers: h266: Check HRD parameter parse return values + gst_h266_parse_sps() ignored the return value of + gst_h266_parse_general_timing_hrd_parameters() and + gst_h266_parse_ols_timing_hrd_parameters(). With a truncated HRD + parameter structure either call can fail partway through, leaving + partially filled state that parsing then continued on. + Propagate the failure and abort SPS parsing when either call fails. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12874> + +2026-10-23 10:51:25 +0200 Edward Hervey <edward@centricular.com> + + * gst-libs/gst/codecparsers/gsth266parser.c: + * tests/check/libs/h266parser.c: + codecparsers: h266: Fix off-by-one bound for scalable nesting layer count + num_layers_minus1 was allowed up to GST_H266_MAX_LAYERS (64), but the + layer_id array is indexed from 1 up to num_layers_minus1, so the last + iteration wrote one entry past the end of the array. The spec limits + the value to vps_max_layers_minus1 - 1 (63). + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12874> + +2026-10-23 10:51:25 +0200 Edward Hervey <edward@centricular.com> + + * gst-libs/gst/codecparsers/gsth266parser.c: + * tests/check/elements/h266parse.c: + codecparsers: h266: Bound num_tiles_in_slice_minus1 by the remaining tiles + The spec requires num_tiles_in_slice_minus1 to be in the range + 0 to NumTilesInPic - SliceAddress - 1. The parser only bounded it by + NumTilesInPic - 1, so the loop summing the CTU counts of the slice + tiles could index past the PPS tile_row_height_minus1 array. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12874> + +2026-10-23 10:44:29 +0200 Edward Hervey <edward@centricular.com> + + * gst-libs/gst/codecparsers/gstav1parser.c: + * tests/check/elements/av1parse.c: + codecparsers: av1: Validate tile group extent against the tile count + tg_start and tg_end are read with tile_cols_log2 + tile_rows_log2 bits + into guint8 fields and only tg_end < tg_start was checked. A tg_end + beyond the tile count made the per-tile loop index past mi_row_starts, + reading past the parser allocation; the values are also returned to + callers. The spec requires tg_end to be at most num_tiles - 1. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12874> + +2026-10-23 10:44:29 +0200 Edward Hervey <edward@centricular.com> + + * gst-libs/gst/codecparsers/gsth265parser.c: + * tests/check/elements/h265parse.c: + codecparsers: h265: Reject SCC SPS with empty palette predictor range + When palette_max_size and delta_palette_max_predictor_size are both 0 + the bound for sps_num_palette_predictor_initializer_minus1 + (palette_max_size + delta_palette_max_predictor_size - 1) becomes + negative, which turns into G_MAXUINT32 in the unsigned comparison and + so accepted any value. The fill loop could then write up to 512 bytes + past the initializer arrays. The spec range is empty in that case, so + reject the SPS. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12874> + +2026-10-23 07:32:51 +0200 Edward Hervey <edward@centricular.com> + + * gst-libs/gst/codecparsers/gstav1parser.c: + * tests/check/elements/av1parse.c: + codecparsers: av1: Fix insufficient remaining-bits checks in sequence header + Several reads in gst_av1_parser_parse_sequence_header_obu() were not + covered by the preceding remaining-bits checks: + - the seq_level_idx read in the reduced_still_picture_header path + - the seq_tier and decoder_model_present_for_this_op reads in the + operating points loop + - the frame size reads, whose guard used the pre-read (zero) values of + frame_width_bits_minus_1 and frame_height_bits_minus_1 instead of + the values just parsed + A truncated sequence header OBU could therefore read past the end of + the OBU data. Use checked reads and re-check the remaining bits after + the bit widths are parsed. + oss-fuzz: 6553136995827712 (issue 576802229) + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12874> + +2026-10-23 07:32:51 +0200 Edward Hervey <edward@centricular.com> + + * gst-libs/gst/codecparsers/gsth266parser.c: + * tests/check/elements/h266parse.c: + codecparsers: h266: Clamp chroma QP table generation to the table size + The fill loop writes entries up to index 63 + qp_bd_offset. With + bitdepth_minus8 = 8 that is index 111, one past the end of the + 111-entry table (heap OOB write). + Clamp the loop to the table size. The table is intentionally kept at + 111 entries: the VA-API driver interface (VaPictureDecodeVVC's + ChromaQpTable) and FFmpeg both use 111. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12874> + +2026-10-23 07:32:50 +0200 Edward Hervey <edward@centricular.com> + + * gst-libs/gst/codecparsers/gstav1parser.c: + * tests/check/elements/av1parse.c: + codecparsers: av1: Fix undefined shift in uvlc parsing + Shifting the signed literal 1 left by 31 is undefined behaviour. + Use an unsigned literal instead; the value range is unchanged. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12874> + +2026-10-23 07:32:49 +0200 Edward Hervey <edward@centricular.com> + + * gst/videoparsers/gstav1parse.c: + * tests/check/elements/av1parse.c: + videoparsers: av1: Calculate framerate without gint overflow + The framerate is derived from 32-bit unsigned timing fields whose + product can overflow a gint, leading to undefined behaviour (SIGFPE) + in gst_util_greatest_common_divisor(). + Compute the fraction in 64 bits, reduce it with + gst_util_greatest_common_divisor_int64() and only then check that the + resulting fraction fits a positive gint; fall back to 0/1 otherwise. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12874> + +2026-10-23 07:24:14 +0200 Edward Hervey <edward@centricular.com> + + * gst/videoparsers/gsth266parse.c: + * tests/check/elements/h266parse.c: + videoparsers: h266: Guard against invalid framerate from HRD timing + Same class of undefined behaviour as for h265parse: the field rate + computed from the SPS general timing information can overflow a gint + and trigger SIGFPE inside gst_util_greatest_common_divisor(). + Ignore the timing information and use 0/1 (unknown framerate) when the + parsed values do not form a fraction that fits a positive gint. + See also https://gitlab.freedesktop.org/gstreamer/gstreamer/-/work_items/4959 + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12874> + +2026-10-23 07:24:13 +0200 Edward Hervey <edward@centricular.com> + + * gst/videoparsers/gsth265parse.c: + * tests/check/elements/h265parse.c: + videoparsers: h265: Guard against invalid framerate from VUI timing + The framerate derived from the SPS VUI timing information is fed to + gst_util_fraction_multiply() and gst_util_greatest_common_divisor() + when the field rate is computed. With extreme values (e.g. + time_scale = 0x80000000 and num_units_in_tick = 0xFFFFFFFF) the + intermediate results overflow a gint and the modulo operation inside + gst_util_greatest_common_divisor() triggers undefined behaviour + (SIGFPE from G_MININT % -1). + Ignore the timing information and use 0/1 (unknown framerate) when the + parsed values do not form a fraction that fits a positive gint. + Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/-/work_items/5378 + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12874> + +2026-10-22 23:12:07 +0200 Víctor Manuel Jáquez Leal <vjaquez@igalia.com> + + * gst-libs/gst/vulkan/gstvkdecoder-private.c: + vulkan: decoder: reuse DPB pool when only irrelevant caps change + The DPB pool allocation only depends on the video format and the frame size: + other fields in the caps, e.g. the framerate, do not affect the allocated + images. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12878> + +2026-10-22 20:00:57 +0200 Víctor Manuel Jáquez Leal <vjaquez@igalia.com> + + * gst-libs/gst/vulkan/gstvkdecoder-private.c: + vulkan: decoder: clear layered DPB buffer before acquiring + gst_vulkan_decoder_create_dpb_pool() can be called again when the DPB pool is + recreated. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12878> + +2026-10-22 20:01:00 +0200 Víctor Manuel Jáquez Leal <vjaquez@igalia.com> + + * gst-libs/gst/vulkan/gstvkdecoder-private.c: + vulkan: decoder: log errors in DPB pool creation + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12878> + +2026-10-23 20:05:58 +0200 Víctor Manuel Jáquez Leal <vjaquez@igalia.com> + + * ext/vulkan/meson.build: + vulkan: add vkav1dec.h to the vulkan_headers list + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12878> + +2026-10-22 23:00:16 +0200 Víctor Manuel Jáquez Leal <vjaquez@igalia.com> + + * ext/vulkan/vkav1dec.c: + * ext/vulkan/vkvp9dec.c: + vulkan{av1,vp9}dec: clear class data caps + The class_init() of AV1 and VP9 decoders never released the codec and raw caps + references from the class data, leaking them for the lifetime of the process at + plugin_init, hidden by the GST_MINI_OBJECT_FLAG_MAY_BE_LEAKED flag. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12878> + +2026-10-22 19:01:47 +0200 Víctor Manuel Jáquez Leal <vjaquez@igalia.com> + + * ext/vulkan/vkav1dec.c: + vulkanav1dec: clear output_state reference in stop() + stop() unref'd output_state without NULLing it, so after a stop/start cycle + negotiate() unref'd the dangling pointer again. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12878> + +2026-10-22 19:01:16 +0200 Víctor Manuel Jáquez Leal <vjaquez@igalia.com> + + * ext/vulkan/vkh264dec.c: + * ext/vulkan/vkh265dec.c: + vulkan{h264,h265}dec: fail allocation if DPB pool creation fails + h264 and h265 ignored the return value of gst_vulkan_decoder_create_dpb_pool() + and continued without a DPB pool, unlike av1 and vp9 which fail + decide_allocation(). create_dpb_pool() fails for example when the decoding + session could not be started; continuing without a DPB pool only moves the + failure to the first decode submission. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12878> + +2026-10-22 19:00:36 +0200 Víctor Manuel Jáquez Leal <vjaquez@igalia.com> + + * ext/vulkan/vkav1dec.c: + * ext/vulkan/vkvp9dec.c: + vulkan{av1,vp9}dec: remove buffer pool double unref + av1 and vp9 unref'd the output pool right after handing it to the allocation + query and then jumped to bail when gst_vulkan_decoder_create_dpb_pool() failed, + where gst_clear_object() dropped the query's reference a second time. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12878> + +2026-10-22 18:39:08 +0200 Víctor Manuel Jáquez Leal <vjaquez@igalia.com> + + * ext/vulkan/vkh264dec.c: + * ext/vulkan/vkh265dec.c: + * ext/vulkan/vkvp9dec.c: + vulkan{vp9,h264,h265}dec: fix new_caps ownership in decide_allocation + h264 and h265 unref'd new_caps before gst_buffer_pool_set_config() and then + passed the no-longer-owned pointer to gst_vulkan_decoder_create_dpb_pool() on + success; on the set_config() failure path, bail: unref'd new_caps a second time. + vp9 unref'd new_caps early, which was only safe on the success path: + create_dpb_pool() gets dpb_caps there; its set_config() failure path + double-unref'd new_caps at bail. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12878> + +2026-10-23 14:14:26 +0300 Sebastian Dröge <sebastian@centricular.com> + + * gst-libs/gst/codecparsers/gstvc1parser.c: + vc1parser: Add missing sanity checks on arguments + Add g_return_val_if_fail() guards for the structure arguments of + the public parse functions. + Also annotate parameters with `(out)`. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12876> + +2026-10-23 16:56:31 +0300 Sebastian Dröge <sebastian@centricular.com> + + * gst/videoparsers/gstvc1parse.c: + vc1parse: Remove redundant structure zeroing + The vc1 parser now fully initializes its output structures, so + zeroing them before every call is redundant. Clear the parsed + structures in reset() together with their buffers. Keep the memsets + in set_caps() so headers do not leak across caps changes that + happen without a stop/start cycle. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12876> + +2026-10-23 15:42:41 +0300 Sebastian Dröge <sebastian@centricular.com> + + * gst-libs/gst/codecparsers/gstvc1parser.c: + * gst-libs/gst/codecparsers/gstvc1parser.h: + * tests/check/libs/vc1parser.c: + vc1parser: Zero-initialize parsed structures + Parse functions only write the fields selected by bitstream flags, and + parse_sequence_header_struct_c() returns early for the advanced profile after + reading just the profile, leaving parts of the caller-provided output structures + untouched. This causes callers passing uninitialized stack variables to read + garbage, e.g. the MB geometry computed from coded_width/coded_height for + simple/main streams without WMVP. + Zero-initialize all output structures at the parse function entry points, as the + h264 and h265 parsers do, and document that the structures need no caller + initialization. This fixes no actual bug right now. All callers happen to work + by accident, either by zero-initializing themselves or by only reading + unconditionally written fields. + coded_width and coded_height in GstVC1SeqStructC are now only filled for WMVP + streams. No caller used the documented pre-filling and this was another chance + of reading uninitialized data. + Fix up unit tests. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12876> + +2026-10-21 21:23:05 +0300 Sebastian Dröge <sebastian@centricular.com> + + * gst/vmnc/vmncdec.c: + vmnc: Reject invalid color shifts in the format descriptor + The WMVi color shifts are used directly to shift a guint32. + Values >= 32 are undefined and their result was just directly passed into + gst_video_format_from_masks(). Reject them directly instead. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12870> + +2026-10-21 19:09:50 +0300 Sebastian Dröge <sebastian@centricular.com> + + * gst/vmnc/vmncdec.c: + vmnc: Render the correct cursor part when clipped + render_cursor() computes the offset into the cursor to start rendering + at, but render_colour_cursor() never applied the horizontal one to the + source pointers. This shifted the rendered image when the cursor is clipped + at the left edge. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12870> + +2026-10-27 10:56:17 +0100 Edward Hervey <edward@centricular.com> + + * gst-libs/gst/codecparsers/gsth264parser.c: + * gst-libs/gst/codecparsers/gsth265parser.c: + codecparsers: guard zero-size user data when writing SEI + Writing an unregistered user data SEI whose payload is only the UUID + passes a NULL data pointer and a zero size to nal_writer_put_bytes. + With checks enabled this logs a warning and the SEI is dropped; with + checks disabled it is undefined behaviour (memcpy with a NULL + argument). A parsed SEI with an empty payload has data NULL and + reaches these write functions through the public insert_sei() entry + points. Skip the data write when the size is zero. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12867> + +2026-10-27 10:56:00 +0100 Edward Hervey <edward@centricular.com> + + * gst/videoparsers/gstvideoparseutils.c: + videoparsers: fix undefined behaviour on empty user data SEI + An unregistered user data SEI whose payload is exactly the 16-byte + UUID carries no data. gst_video_parse_user_data_unregistered() still + duplicated the remaining bytes: gst_byte_reader_dup_data() with a zero + size memcpy()s from a NULL reader buffer, which is undefined + behaviour. Skip the copy for an empty payload; the empty message is + still recorded (meta data NULL, size 0, as the h264parse test + expects). + Read the payload size with gst_byte_reader_get_remaining() instead of + gst_byte_reader_get_size(): the readers are freshly initialised at all + call sites today, but get_size() returns the total size, so a caller + passing a partially consumed reader would make the duplication fail. + Report that failure with GST_ERROR_OBJECT and drop the message: + g_return_if_reached() compiles to a silent return when checks are + disabled, losing the SEI without a trace. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12867> + +2026-10-23 18:37:20 +0000 Daniel Morin <daniel.morin@collabora.com> + + * gst/tensordecoders/gstclassifiertensordecoder.c: + tensordecoders: fix leaks in classifiertensordec + Free leaks on set_caps, state_changes, load_labels, set_property and re-generate + labels, when no label file available, and class_count changed on re-negociation. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12860> + +2026-10-22 15:20:54 +0200 Edward Hervey <edward@centricular.com> + + * gst-libs/gst/codecparsers/gsth264parser.c: + * tests/check/libs/h264parser.c: + codecparsers: h264: Do not overflow SPS width and height + pic_width_in_mbs_minus1 and pic_height_in_map_units_minus1 are + unbounded ue() values. Multiplying them by 16, and by 2 more for + interlaced video, in a gint overflows for large values, which is + undefined behaviour. The width < 0 check that follows runs after + the overflow already happened. + Compute the sizes in unsigned 64 bit arithmetic, which cannot + overflow, and reject what does not fit a gint, including the + product of the two dimensions, which callers multiply as gint + values. An oversized crop wraps the unsigned size around and the + same range check rejects it. Found by fuzzing mutated SPS + bitstreams under UBSan. + Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/-/work_items/5372 + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12854> + +2026-10-22 15:20:43 +0200 Edward Hervey <edward@centricular.com> + + * gst-libs/gst/codecparsers/gsth264parser.c: + * tests/check/libs/h264parser.c: + codecparsers: h264: Fix the frame packing arrangement skip + gst_h264_parser_parse_frame_packing() skips the rest of the message + when frame_packing_arrangement_extension_flag is set, but it ignores + the result of nal_reader_skip_long() and computes the amount to skip + as payload_size - consumed without checking that consumed does not + exceed payload_size. The fields can consume more bits than the + message advertises, such as a large ue() frame_packing_id, which + wraps the difference around to a huge value. The skip then consumes + the rest of the NAL unit and fails, yet the parser returns OK and + gst_h264_parser_parse_sei_message() continues with a reader + positioned past the message. + Reject a payload overrun and a failed skip instead, like the other + SEI payload parsers do. Add tests for the overrun and for the frame + packing message from issue 5375. + See https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/5375 + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12854> + +2026-10-22 15:20:29 +0200 Edward Hervey <edward@centricular.com> + + * gst-libs/gst/codecparsers/nalutils.c: + * tests/check/libs/nalutils.c: + codecparsers: nalutils: Keep the reader intact when a read fails + nal_reader_read() checks whether enough raw bytes are left, but raw + bytes include emulation prevention bytes, which carry no data. If the + refill loop skips an emulation prevention byte and then runs out of + data, it returns FALSE after having already added whole bytes to the + cache. bits_in_cache is then above the 7 bits callers expect to find + between two calls. The next nal_reader_get_bits_uint8() computes a + shift of 8 - (bits_in_cache - nbits); the subtraction wraps around + and the shift is undefined behaviour. + This is the root cause of the UBSan report in issue 5375: a parser + that keeps using a reader damaged by a failed read shifts by an + out-of-range amount. + Snapshot the reader before refilling and restore it when the refill + fails, so a failed read leaves the reader unchanged. Do the same in + nal_reader_skip_long() so a partially skipped amount is rolled back + too. + Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/5375 + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12854> + +2026-10-26 15:59:29 -0400 Dominique Leroux <dominique.p.leroux@gmail.com> + + * gst/mxf/mxfmetadata.c: + mxf: Fix metadata creation by using g_object_new, not g_type_create_instance + As per GLib's doc for g_type_create_instance, this should only be used by + implementers of fundamental types. More specifically, GObject-derived types, + such as MXFMetadata and MXFDescriptiveMetadata, should be created with + g_object_new. + Found this while investigating failure in the elements_mxfdemux test, which + reported: + Unexpected critical/warning: object MXFMetadataSourceClip 0x7b8d6d400 finalized while still in-construction + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12852> + +2026-10-26 18:09:19 +0000 Michael Krasnow <mkrasnow@netflix.com> + + * sys/va/gstvaav1enc.c: + * sys/va/gstvavp8enc.c: + * sys/va/gstvavp9enc.c: + va: {vp8,vp9,av1}enc: check the result of gst_va_encode_picture_new() + gst_va_encode_picture_new() returns NULL when the reconstruct pool is + empty (it acquires with GST_BUFFER_POOL_ACQUIRE_FLAG_DONTWAIT) or when + vaCreateBuffer() fails. vah264enc, vah265enc and vajpegenc already return + GST_FLOW_ERROR in that case, but vavp8enc, vavp9enc and vaav1enc carried + on and dereferenced the NULL picture, e.g. in _vp8_fill_frame_param(). + Return GST_FLOW_ERROR the same way, so running out of surfaces is a + pipeline error instead of a segfault. The frame's picture is released + with g_clear_pointer(), so leaving it NULL is safe. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12845> + +2026-10-25 14:15:19 +0200 Sebastian Dröge <sebastian@centricular.com> + + * gst-libs/gst/codecs/gsth264decoder.c: + h264decoder: Fix division by zero on bogus SPS dimensions + sps->width/height can be 0 for invalid streams, reject those instead of + dividing by zero when calculating the DPB size. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12841> + +2026-06-02 13:18:05 +0200 Michael Olbrich <m.olbrich@pengutronix.de> + + * gst-libs/gst/wayland/gstwloutput.c: + wayland: output: return the correct global id + The documentation for gst_wl_output_get_id() says, it returns + "the Waylandnd object global id". + This is currently incorrect. wl_proxy_get_id() returns the id of the local proxy + object. As a result, GstWlDisplay fails to delete the local object of the output + when it is removed. + Return the actual global id so that the code matches the documentation and the + currently only user of this function. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12821> + +2026-06-02 13:07:59 +0200 Michael Olbrich <m.olbrich@pengutronix.de> + + * gst-libs/gst/wayland/gstwldisplay.c: + * gst-libs/gst/wayland/gstwloutput-private.h: + * gst-libs/gst/wayland/gstwloutput.c: + wayland: display: don't crash when a compositor sents output property updates + The output_done event is sent, not just after binding the output, but also + whenever properties are updated. + For any subsequent calls, 'self' is NULL because it is removed from the output + object with g_object_steal_data(). This causes a segfault while trying to add + the output to the hashmap. + So keep one GstWlOutput object attached to the wl_output object and create a + copy with the full state whenever the 'done' callback is executed. The user + visible object is then replaced atomically. + As a side-effect, the fixes leaking the GstWlOutput object when the display is + destroyed before 'done' is called for the first time + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12821> + +2026-10-21 18:28:54 +0200 Edward Hervey <edward@centricular.com> + + * gst/videoparsers/gstvp9parse.c: + vp9parse: Check superframe frame sizes against the buffer size + The frame sizes of a superframe index are parsed from the stream and + were passed to the frame header parser as sizes without checking that + they fit in the mapped buffer. A crafted index then made the parser + read past the end of the frame data. Reject the superframe in that + case, as is already done for an unparseable index. + Found while fuzzing the element parsing sequence with libFuzzer/ASan. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12806> + +2026-10-20 18:32:49 +0200 Edward Hervey <edward@centricular.com> + + * gst-libs/gst/codecparsers/gstvp9parser.c: + * tests/check/libs/vp9parser.c: + codecparsers: vp9: Do not read past the end of the frame data + The frame header syntax is data-dependent: how many bits to read + depends on the values read, so a truncated buffer cannot be caught + with an upfront size check. All reads were unchecked, so a 1-byte + frame read past the end of the buffer. + Switch to checked bit reads. Instead of an early return in each of + the 14 helpers, the first failed read is recorded in the reader + wrapper and the two public entry points bail out when it is set. + This is safe because a failed read returns 0 and no parsed value is + used as an index or loop bound, so parsing can continue until the + entry point is reached. + Reported by OSS-Fuzz testcase 4903539546324992, issue 575516020. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12806> + +2026-10-20 15:29:26 +0200 Edward Hervey <edward@centricular.com> + + * gst/videoparsers/gstmpeg4videoparse.c: + mpeg4videoparse: Clamp VO length when parsing codec_data + Same G_MAXUINT sentinel issue as the VOS case: when the visual + object packet has no terminating start code, MIN (packet.size, size) + clamps to the buffer size instead of the remaining size, letting the + bit reader read past the end of the mapped codec_data. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12802> + +2026-10-20 12:44:35 +0200 Edward Hervey <edward@centricular.com> + + * gst/videoparsers/gstmpeg4videoparse.c: + mpeg4videoparse: Clamp VOS length when no terminating start code + packet->size is G_MAXUINT when the packet is not terminated inside the + buffer, so the "packet->size > 1" guard does not reject it and + packet->size - 1 is passed as a huge length, reading past the buffer. + Found by OSS-Fuzz testcase 5492471254286336 (incomplete fix follow-up + to GST-SA-2026-0049). + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12802> + +2026-10-22 10:26:23 +0200 Edward Hervey <edward@centricular.com> + + * gst-libs/gst/codecparsers/gsth266parser.c: + h266parser: Fix infinite loop parsing picture timing SEI + The loop that fills du_cpb_removal_delay_increment_minus1 for the + sublayers below TemporalId reused the loop variable of the loop + enclosing it. It reset that variable on every iteration, so for + TemporalId >= 2 the enclosing loop never advanced and parsing never + terminated; for TemporalId == 1 it re-read bits and stored wrong + values. Use a separate loop variable for the fill. + Found while fuzzing gst-discoverer with libFuzzer. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12792> + +2026-10-19 12:24:18 +0200 David Maseda Neira <david.masedan@gmail.com> + + * sys/nvcodec/gstcudaconverter.cpp: + cuda: Correctly save alpha and blend on property change + Currently, on alpha or blend changes, the priv field is not saved, so + once alpha is set below 1.0 or blend is set to TRUE, cudacompositor pads + can't return to alpha=1.0 or to operator=source. Use the same code as + other properties already do. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12778> + +2026-10-04 12:30:45 +0000 Yannis Güdel <me@yannisguedel.ch> + + * sys/asio/gstasioobject.cpp: + asio: fix stopping asio element causing crashes + Before the fix stopping an asio element could stop another asio element causing crashes as resources of + other elements were cleanup and later still accessed. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12777> + +2026-10-21 09:27:43 -0700 Xavier Claessens <xclaessens@netflix.com> + + * gst/unixfd/gstunixfdsink.c: + unixfdsink: Fix race when starting and stopping quickly + Fixes: #5371 + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12784> + +2026-10-20 17:39:44 +0200 Edward Hervey <edward@centricular.com> + + * gst-libs/gst/codecparsers/gsth264parser.c: + codecparsers: h264: Do not use the reader after a failed SEI payload parse + gst_h264_parser_parse_sei_message() kept reading from the NalReader + after the payload parser failed. A failed nal_reader_read() can leave + bits_in_cache larger than the cache, so the following byte alignment + reads shift by a wrapped amount. Bail out instead, as the skip_long() + failure already does. BROKEN_LINK is passed through unchanged so the + message can be retried once the parameter set arrives. + Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/5333 + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12771> + +2026-10-20 13:01:41 +0200 Edward Hervey <edward@centricular.com> + + * gst-libs/gst/codecparsers/nalutils.c: + codecparsers: Fix undefined shift in nal_reader_get_ue + nal_reader_get_ue checked for i > 31 and then evaluated (1 << i), so + i == 31 shifted 1 into the sign bit of int. Use an unsigned literal. + See https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/5333 + OSS-Fuzz testcase 5825658253803520. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12771> + +2026-09-30 13:18:30 +0300 Sebastian Dröge <sebastian@centricular.com> + + * gst-libs/gst/codecparsers/gsth264parser.c: + * gst-libs/gst/codecparsers/gsth265parser.c: + * gst-libs/gst/codecparsers/gsth266parser.c: + * gst-libs/gst/codecparsers/nalutils.c: + * gst-libs/gst/codecparsers/nalutils.h: + h264parser: h266parser: Handle oversized SEI payloads + The same way as it's handled for H265 already. + (cherry picked from commit e8bf98d3785ae6cbf1f02ee9548c5dbd4636bb56) + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12748> + +2026-09-28 03:15:21 +0530 Nirbheek Chauhan <nirbheek.chauhan@coram.ai> + + * gst-libs/gst/codecparsers/gsth265parser.c: + * tests/check/libs/h265parser.c: + h265parser: Handle oversized SEI payloads + Avoids warnings every buffer about being unable to parse SEI data. + (cherry picked from commit f82e6fe29ba034467652bdbe4512a76ac28f06e2) + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12748> + +2026-09-30 13:03:35 +0300 Sebastian Dröge <sebastian@centricular.com> + + * gst/videoparsers/gsth265parse.c: + * gst/videoparsers/gsth266parse.c: + h265parse: h266parse: Don't error out on trailing garbage data after a NAL + Instead handle it the same way as h264parse and skip over the garbage data. + (cherry picked from commit f715230652d9f7b97476e5a593ea61aa3d0ffb15) + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12746> + +2026-09-28 03:25:36 +0530 Nirbheek Chauhan <nirbheek.chauhan@coram.ai> + + * gst/videoparsers/gsth264parse.c: + * tests/check/elements/h264parse.c: + h264parse: Don't finish a zero-sized frame when no start code follows + In NAL/AU alignment a GST_H264_PARSER_NO_NAL result is treated as a + broken NAL. gst_h264_parser_identify_nalu() clears the GstH264NalUnit + before it searches, so after NO_NAL every field is 0. With current_off + greater than 0 the "broken" path then terminates the current AU at + nalu.sc_offset == 0, i.e. it calls gst_base_parse_finish_frame() with + size 0. + If a NAL was already collected into frame_out in this round (transform + mode, which byte-stream AU input always uses), frame->out_buffer is set, + the size check in finish_frame() passes, the frame is pushed with + nothing flushed, and baseparse dereferences the consumed frame->buffer: + gst_base_parse_handle_buffer -> GST_BUFFER_IS_DISCONT (frame->buffer) + This was seen on ACTi cameras which append a 44-byte metadata trailer to + every slice NAL, for example + 00 00 01 b2 05 00 00 00 01 4a 00 00 46 c5 ea 64 ... 00 00 00 00 + The AU is finished at the first bogus start code and the trailer is + (incorrectly) detected as the next frame. "b2 05" (type 18) is + collected, "4a" (type 10) is accepted as a 1-byte NAL, and the + remaining bytes contain no start code, so NO_NAL leads to a zero-sized + finish_frame() and a SIGSEGV. + Also add a test for this, so this doesn't break again. + (cherry picked from commit 38287b5e589d3fda8fb3842b9c42aa0d46435ad9) + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12746> + +2026-10-19 20:23:02 +0900 Seungha Yang <seungha@centricular.com> + + * sys/nvcodec/gstcudaipcserver_unix.cpp: + cudaipc: Release Unix socket server resources on teardown + The pending async accept holds a reference to the service, so unrefing + the service alone does not release its resources. Stop the service + explicitly and iterate the main context to complete cancelled operations + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12758> + +2026-10-12 12:03:39 +0530 Nirbheek Chauhan <nirbheek.chauhan@coram.ai> + + * sys/v4l2codecs/gstv4l2codech265dec.c: + v4l2codecs: Preserve color range when cropping H.265 output + Cropping must preserve decoded pixel values. The source range is + unknown while the default destination range is limited. Since !12593, + the converter changes those values and fails CONFWIN_A_Sony_1 in the + fluster tests. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12718> + +2026-03-11 13:49:27 -0300 L. E. Segovia <amy@centricular.com> + + * gst-libs/gst/d3d11/meson.build: + winrt: fix MSYS build by checking for XAML headers on egl and d3d11 + MSYS2 has switched to a default WINVER corresponding to Windows 10. This + unintentionally kept WinRT working because the default WINVER made the + tests involving WINAPI_PARTITION_APP etc. fail early. + The headers involved in gluing D3D11 are not available on the MinGW CRT. + See https://github.com/msys2/MINGW-packages/commit/496bb7651c8168c5ad2f1ac1b88ef12c6633e395 + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12757> + +2026-10-19 18:29:52 +0900 Seungha Yang <seungha@centricular.com> + + * sys/d3d11/meson.build: + * sys/d3d12/meson.build: + d3d11, d3d12: Check required WRL types when detecting WGC support + MinGW provided ones are incomplete for us. Check more types + with WRL implementations + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12757> + +2026-10-18 20:28:11 +0530 Sanchayan Maity <sanchayan@centricular.com> + + * sys/qsv/libmfx/dispatcher/windows/mfx_dispatcher_defs.h: + qsv: Only define wcscpy_s/wcscat_s fallbacks for old MSVC + The _MSC_VER < 1400 guard is true when _MSC_VER is undefined, so fallback + macros were defined for MinGW too and collided with the real UCRT functions + used by <stralign.h> in expression context. + This was dormant until mingw-w64 fixed a _WConst_Return typo that kept + ua_wcscpy_s as dead code, activating it in the MSYS2 toolchain: + https://github.com/mingw-w64/mingw-w64/commit/9dff64a5101937c377575a5de7b446ef32f6b206 + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12757> + +2026-10-16 15:59:49 +0900 Haihua Hu <jared.hu@nxp.com> + + * ext/hls/gsthlsdemux.c: + hlsdemux: Validate PKCS7 padding before unpadding decrypted fragments + The padding byte comes from the decrypted ciphertext, which is + attacker-controlled. If it is 0, or larger than the AES block size + or the buffer itself, the unpadded size computation can underflow + and corrupt the heap when gst_buffer_resize() is called with a bogus + size. + Validate the padding byte before trusting it, and reject the + fragment with a warning if it looks invalid. + Co-authored-by: Sebastian Dröge <sebastian@centricular.com> + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12753> + +2026-10-19 11:46:24 +0200 François Laignel <francois@centricular.com> + + * gst/mxf/mxfdemux.c: + mxfdemux: fix a typo and improve log + Minor but found looking at something else. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12745> + +2026-10-18 09:42:10 +0100 Philippe Normand <philn@igalia.com> + + * docs/plugins/gst_plugins_cache.json: + * ext/analyticsoverlay/gstobjectdetectionoverlay.c: + * ext/analyticsoverlay/gstsegmentationoverlay.c: + analyticsoverlay: Remove Visualization classifier + The Visualization classifier is meant for audio visualization elements. + Fixes #5361 + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12741> + +2026-10-16 10:18:59 +0200 Vincent <vin.legrand11@gmail.com> + + * ext/vulkan/vkh265dec.c: + vulkanh265dec: use sps_scaling_list_data_present_flag from the SPS + Use the proper data_present_flag field from the parsed sps. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12732> + +2026-10-13 12:49:49 +0200 Philippe Normand <philn@igalia.com> + + * ext/wpe2/gstwpethreadedview.cpp: + wpe2: Fix mouse pointer buttons mismatch + The middle and secondary buttons were inverted, middle reported as secondary and + secondary reported as middle. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12731> + +2026-10-14 16:52:24 +0200 Azat Nurgaliev <azat.nurg@gmail.com> + + * sys/amfcodec/gstamfav1enc.cpp: + * sys/amfcodec/gstamfh265enc.cpp: + amfcodec: set rate_control(h265, av1) and gop_size (h265) property before Init() call + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12723> + +2026-10-13 10:46:40 +0200 Edward Hervey <edward@centricular.com> + + * gst/mpegtsdemux/tsdemux.c: + tsdemux: Check AC-3 descriptor length before reading its fields + The AC-3 audio stream descriptor macros index the descriptor data with + offsets computed from the descriptor itself. GstMpegtsDescriptor.data is + allocated with length + 2 bytes, so a truncated or malformed descriptor + could make the language code lookup read past the end of the buffer. + Bound the textlen-derived offsets before using them, and check that the + bsid byte is present before reading it. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12707> + +2026-10-12 08:03:51 -0400 Xavier Claessens <xclaessens@netflix.com> + + * sys/va/gstvavp9enc.c: + va: skip RGB formats from vp9 encoder + Intel driver claims to support it, but it hangs after a few frames. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12706> + +2026-10-12 08:03:22 -0400 Xavier Claessens <xclaessens@netflix.com> + + * sys/va/gstvacaps.c: + * sys/va/gstvacaps.h: + * sys/va/gstvajpegenc.c: + va: move code to filter supported format into API + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12706> + +2026-10-12 07:36:01 -0400 Xavier Claessens <xclaessens@netflix.com> + + * sys/va/gstvacaps.c: + va: do not advertise unsupported formats in caps + For example Y412_LE was present in caps template, but not supported by + my vp9 encoder. + Fixes: #5288 + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12706> + +2026-10-12 00:25:28 +0900 Seungha Yang <seungha@centricular.com> + + * sys/d3d12/gstd3d12encoder.cpp: + d3d12encoder: Port to gst_d3d12_buffer_copy_into() + ... and remove duplicated upload code + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12682> + +2026-10-11 23:48:31 +0900 Seungha Yang <seungha@centricular.com> + + * sys/d3d12/gstd3d12h264enc.cpp: + d3d12h264enc: Separate target resolution from bitstream alignment + Align PictureTargetResolution to the device requirements and apply + codec-specific alignment separately when generating SPS dimensions. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12682> + +2026-10-11 22:58:18 +0900 Seungha Yang <seungha@centricular.com> + + * sys/d3d12/gstd3d12h264enc.cpp: + d3d12h264enc: Insert all PPS before IDR + Insert all PPS before IDR frames instead of inserting updated + PPS before P frames. This can avoid caps changes caused by codec_data + updates when downstream converts from byte-stream to AVC format. + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12682> + +2026-10-11 22:38:43 +0900 Seungha Yang <seungha@centricular.com> + + * sys/d3d12/gstd3d12h264enc.cpp: + d3d12h264enc: Rebuild SPS/PPS when level is updated + The updated level information should be specified in the new SPS + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12682> + +2026-10-11 22:33:01 +0900 Seungha Yang <seungha@centricular.com> + + * sys/d3d12/gstd3d12h264enc.cpp: + d3d12h264enc: Fix QVBR rate-control update checking + Compare the QVBR configuration instead of the CBR configuration + when checking for rate-control changes + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12682> + +2026-10-11 22:27:47 +0900 Seungha Yang <seungha@centricular.com> + + * sys/d3d12/gstd3d12h264enc.cpp: + d3d12h264enc: Add missing slice_partition setting + Pass user requested slice partition setting to driver when + slice-mode=bytes + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12682> + +2026-10-11 22:22:33 +0900 Seungha Yang <seungha@centricular.com> + + * sys/d3d12/gstd3d12encoder.cpp: + d3d12: Fix encoder bitstream copy with subregion padding + Exclude the leading padding from the copied bitstream size + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12682> + +2026-10-08 17:42:50 +0200 Tim-Philipp Müller <tim@centricular.com> + + * meson.build: + Back to development after 1.28.8 + Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12673> + === release 1.28.8 === 2026-10-08 17:20:32 +0200 Tim-Philipp Müller <tim@centricular.com>
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/RELEASE -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/RELEASE
Changed
@@ -1,4 +1,4 @@ -This is GStreamer gst-plugins-bad 1.28.8 +This is GStreamer gst-plugins-bad 1.28.9 The GStreamer team is thrilled to announce a new major feature release of your favourite cross-platform multimedia framework!
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/docs/plugins/gst_plugins_cache.json -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/docs/plugins/gst_plugins_cache.json
Changed
@@ -3498,7 +3498,7 @@ "GInitiallyUnowned", "GObject" , - "klass": "Analyzer/Visualization/Video", + "klass": "Analyzer/Video/Overlay", "pad-templates": { "sink": { "caps": "video/x-raw:\n format: { A444_16LE, A444_16BE, Y416_LE, AYUV64, RGBA64_LE, ARGB64, ARGB64_LE, BGRA64_LE, ABGR64_LE, Y416_BE, RGBA64_BE, ARGB64_BE, BGRA64_BE, ABGR64_BE, A422_16LE, A422_16BE, A420_16LE, A420_16BE, A444_12LE, GBRA_12LE, A444_12BE, GBRA_12BE, Y412_LE, Y412_BE, A422_12LE, A422_12BE, A420_12LE, A420_12BE, A444_10LE, GBRA_10LE, A444_10BE, GBRA_10BE, A422_10LE, A422_10BE, A420_10LE, A420_10BE, BGR10A2_LE, RGB10A2_LE, Y410, A444, GBRA, AYUV, VUYA, RGBA, RBGA, ARGB, BGRA, ABGR, A422, A420, AV12, Y444_16LE, GBR_16LE, Y444_16BE, GBR_16BE, Y216_LE, Y216_BE, v216, P016_LE, P016_BE, Y444_12LE, GBR_12LE, Y444_12BE, GBR_12BE, I422_12LE, I422_12BE, Y212_LE, Y212_BE, I420_12LE, I420_12BE, P012_LE, P012_BE, Y444_10LE, GBR_10LE, Y444_10BE, GBR_10BE, BGR10x2_LE, RGB10x2_LE, r210, I422_10LE, I422_10BE, NV16_10LE40, NV16_10LE32, Y210, UYVP, v210, I420_10LE, I420_10BE, P010_10LE, NV12_10LE40, NV12_10LE32, P010_10BE, MT2110R, MT2110T, NV12_10BE_8L128, NV12_10LE40_4L4, Y444, BGRP, GBR, RGBP, NV24, v308, IYU2, RGBx, xRGB, BGRx, xBGR, RGB, BGR, Y42B, NV16, NV61, YUY2, YVYU, UYVY, VYUY, I420, YV12, NV12, NV21, NV12_16L32S, NV12_32L32, NV12_4L4, NV12_64Z32, NV12_8L128, Y41B, IYU1, YUV9, YVU9, BGR16, RGB16, BGR15, RGB15, RGB8P, GRAY16_LE, GRAY16_BE, GRAY10_LE16, GRAY10_LE32, GRAY8 }\n width: 1, 2147483647 \n height: 1, 2147483647 \n framerate: 0/1, 2147483647/1 \n", @@ -3617,7 +3617,7 @@ "GInitiallyUnowned", "GObject" , - "klass": "Visualization/Video", + "klass": "Analyzer/Video/Overlay", "pad-templates": { "sink": { "caps": "video/x-raw:\n format: { A444_16LE, A444_16BE, Y416_LE, AYUV64, RGBA64_LE, ARGB64, ARGB64_LE, BGRA64_LE, ABGR64_LE, Y416_BE, RGBA64_BE, ARGB64_BE, BGRA64_BE, ABGR64_BE, A422_16LE, A422_16BE, A420_16LE, A420_16BE, A444_12LE, GBRA_12LE, A444_12BE, GBRA_12BE, Y412_LE, Y412_BE, A422_12LE, A422_12BE, A420_12LE, A420_12BE, A444_10LE, GBRA_10LE, A444_10BE, GBRA_10BE, A422_10LE, A422_10BE, A420_10LE, A420_10BE, BGR10A2_LE, RGB10A2_LE, Y410, A444, GBRA, AYUV, VUYA, RGBA, RBGA, ARGB, BGRA, ABGR, A422, A420, AV12, Y444_16LE, GBR_16LE, Y444_16BE, GBR_16BE, Y216_LE, Y216_BE, v216, P016_LE, P016_BE, Y444_12LE, GBR_12LE, Y444_12BE, GBR_12BE, I422_12LE, I422_12BE, Y212_LE, Y212_BE, I420_12LE, I420_12BE, P012_LE, P012_BE, Y444_10LE, GBR_10LE, Y444_10BE, GBR_10BE, BGR10x2_LE, RGB10x2_LE, r210, I422_10LE, I422_10BE, NV16_10LE40, NV16_10LE32, Y210, UYVP, v210, I420_10LE, I420_10BE, P010_10LE, NV12_10LE40, NV12_10LE32, P010_10BE, MT2110R, MT2110T, NV12_10BE_8L128, NV12_10LE40_4L4, Y444, BGRP, GBR, RGBP, NV24, v308, IYU2, RGBx, xRGB, BGRx, xBGR, RGB, BGR, Y42B, NV16, NV61, YUY2, YVYU, UYVY, VYUY, I420, YV12, NV12, NV21, NV12_16L32S, NV12_32L32, NV12_4L4, NV12_64Z32, NV12_8L128, Y41B, IYU1, YUV9, YVU9, BGR16, RGB16, BGR15, RGB15, RGB8P, GRAY16_LE, GRAY16_BE, GRAY10_LE16, GRAY10_LE32, GRAY8 }\n width: 1, 2147483647 \n height: 1, 2147483647 \n framerate: 0/1, 2147483647/1 \n",
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/ext/analyticsoverlay/gstobjectdetectionoverlay.c -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/ext/analyticsoverlay/gstobjectdetectionoverlay.c
Changed
@@ -309,7 +309,7 @@ gst_element_class_add_static_pad_template (element_class, &src_template); gst_element_class_set_static_metadata (element_class, "Object Detection Overlay", - "Analyzer/Visualization/Video", + "Analyzer/Video/Overlay", "Overlay a visual representation of analytics metadata on the video", "Daniel Morin");
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/ext/analyticsoverlay/gstsegmentationoverlay.c -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/ext/analyticsoverlay/gstsegmentationoverlay.c
Changed
@@ -184,7 +184,7 @@ gst_element_class_add_static_pad_template (element_class, &src_template); gst_element_class_set_static_metadata (element_class, "Segmentation Overlay", - "Visualization/Video", + "Analyzer/Video/Overlay", "Overlay a visual representation of segmentation metadata on the video", "Daniel Morin");
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/ext/faac/gstfaac.c -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/ext/faac/gstfaac.c
Changed
@@ -43,6 +43,39 @@ #include "gstfaac.h" +#if FAAC_VERSION_MAJOR >= 1 +/* Legacy constant names for the faac >= 2.0 enums (same numeric values); + * MAIN/SSR/LTP only remain so the mpegversion=2 profile switch compiles. */ +#define MAIN 1 +#define LOW FAAC_OBJ_LOW +#define SSR 3 +#define LTP 4 +#define MPEG4 FAAC_MPEG4 +#define MPEG2 FAAC_MPEG2 +#define SHORTCTL_NORMAL FAAC_SHORTCTL_NORMAL +#define SHORTCTL_NOSHORT FAAC_SHORTCTL_NOSHORT +#define SHORTCTL_NOLONG FAAC_SHORTCTL_NOLONG + +/* Minimal wrappers keeping the faacEnc* call shape used below */ +static int +faacEncEncode (faac_encoder * handle, gint32 * input, unsigned int samples, + unsigned char *output, unsigned int output_size) +{ + guint32 bytes_written = 0; + + if (faac_encoder_encode (handle, input, samples, output, output_size, + &bytes_written) < 0) + return -1; + return bytes_written; +} + +static void +faacEncClose (faac_encoder * handle) +{ + faac_encoder_close (&handle); +} +#endif /* FAAC_VERSION_MAJOR >= 1 */ + #define SAMPLE_RATES " 8000, " \ "11025, " \ "12000, " \ @@ -70,20 +103,28 @@ "width = (int) 32, " "rate = (int) 8000, 96000, " "channels = (int) 1, 6" #endif +#if FAAC_VERSION_MAJOR >= 1 +/* faac >= 2.0 only implements the LC object type */ +#define MPEG4_PROFILES "lc" +#define MPEG2_PROFILES "lc" +#else +#define MPEG4_PROFILES "{ main, lc, ssr, ltp }" +#define MPEG2_PROFILES "{ main, lc }" +#endif #define SRC_CAPS \ "audio/mpeg, " \ "mpegversion = (int) 4, " \ "channels = (int) 1, 6 , " \ "rate = (int) {" SAMPLE_RATES "}, " \ "stream-format = (string) { adts, raw }, " \ - "base-profile = (string) { main, lc, ssr, ltp }, " \ + "base-profile = (string) " MPEG4_PROFILES ", " \ "framed = (boolean) true; " \ "audio/mpeg, " \ "mpegversion = (int) 2, " \ "channels = (int) 1, 6 , " \ "rate = (int) {" SAMPLE_RATES "}, " \ "stream-format = (string) { adts, raw }, " \ - "profile = (string) { main, lc }," \ + "profile = (string) " MPEG2_PROFILES "," \ "framed = (boolean) true; " static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, @@ -466,6 +507,82 @@ static gboolean gst_faac_open_encoder (GstFaac * faac, GstAudioInfo * info) { +#if FAAC_VERSION_MAJOR >= 1 + faac_encoder *handle = NULL; + faac_params params; + faac_encoder_info enc_info; + guint maxbitrate; + + g_return_val_if_fail (info->rate != 0 && info->channels != 0, FALSE); + + /* clean up in case of re-configure */ + gst_faac_close_encoder (faac); + +#if FAAC_VERSION_MAJOR >= 2 + if (faac_params_init (¶ms, sizeof (params)) < 0) +#else + if (faac_params_init (¶ms) < 0) +#endif + goto setup_failed; + + params.sample_rate = info->rate; + params.num_channels = info->channels; + params.mpeg_version = (faac->mpegversion == 4) ? FAAC_MPEG4 : FAAC_MPEG2; + params.object_type = FAAC_OBJ_LOW; + params.joint_mode = faac->midside ? FAAC_JOINT_MS : FAAC_JOINT_NONE; + params.use_lfe = FALSE; + params.use_tns = faac->tns; + params.input_format = (enum faac_input_format) faac->format; + params.output_format = + faac->outputformat ? FAAC_STREAM_ADTS : FAAC_STREAM_RAW; + params.short_control = (enum faac_shortctl_mode) faac->shortctl; + /* default 0 to start with, libfaac chooses based on bitrate */ + params.bandwidth = 0; + + if (faac->brtype == VBR) { + params.bit_rate = 0; + params.quant_quality = faac->quality; + } else if (faac->brtype == ABR) { + params.bit_rate = faac->bitrate / info->channels; + params.quant_quality = 0; + + /* check, warn and correct if the max bitrate for the given samplerate is + * exceeded. Maximum of 6144 bit for a channel */ + maxbitrate = + (unsigned int) (6144.0 * (double) info->rate / (double) 1024.0 + .5); + if (params.bit_rate > maxbitrate) { + GST_ELEMENT_WARNING (faac, RESOURCE, SETTINGS, (NULL), + ("bitrate %u exceeds maximum allowed bitrate of %u for samplerate %d. " + "Setting bitrate to %u", params.bit_rate, maxbitrate, + info->rate, maxbitrate)); + params.bit_rate = maxbitrate; + } + } + + if (faac_encoder_open (¶ms, &handle) < 0) + goto setup_failed; + + faac->handle = handle; + + enc_info.struct_size = sizeof (enc_info); + if (faac_encoder_get_info (handle, &enc_info) < 0) + goto setup_failed; + + faac->samples = enc_info.frame_samples; + faac->bytes = enc_info.max_output_bytes; + + GST_DEBUG_OBJECT (faac, "faac needs samples %d, output size %d", + faac->samples, faac->bytes); + + /* let's see what really happened, + * note that this may not really match desired rate */ + GST_DEBUG_OBJECT (faac, "average bitrate: %u kbps", + (enc_info.bit_rate + 500) / 1000 * info->channels); + GST_DEBUG_OBJECT (faac, "quantization quality: %u", enc_info.quant_quality); + GST_DEBUG_OBJECT (faac, "bandwidth: %u Hz", enc_info.bandwidth); + + return TRUE; +#else faacEncHandle *handle; faacEncConfiguration *conf; guint maxbitrate; @@ -534,6 +651,7 @@ GST_DEBUG_OBJECT (faac, "bandwidth: %d Hz", conf->bandWidth); return TRUE; +#endif /* FAAC_VERSION_MAJOR >= 1 */ /* ERRORS */ setup_failed: @@ -570,11 +688,28 @@ /* get the config string */ GST_DEBUG_OBJECT (faac, "retrieving decoder info"); +#if FAAC_VERSION_MAJOR >= 1 + { + /* library-owned buffer, valid until close; must not be freed */ + const guint8 *asc = NULL; + guint32 asc_len = 0; + + if (faac_encoder_asc (faac->handle, &asc, &asc_len) < 0) { + gst_caps_unref (srccaps); + goto invalid_codec_data; + } + config = (guint8 *) asc; + config_len = asc_len; + } +#else faacEncGetDecoderSpecificInfo (faac->handle, &config, &config_len); +#endif if (!gst_codec_utils_aac_caps_set_level_and_profile (srccaps, config, config_len)) { +#if FAAC_VERSION_MAJOR < 1 free (config); +#endif gst_caps_unref (srccaps); goto invalid_codec_data; } @@ -593,7 +728,9 @@ gst_buffer_unref (codec_data); } +#if FAAC_VERSION_MAJOR < 1 free (config); +#endif } else { const gchar *profile;
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/ext/faac/gstfaac.h -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/ext/faac/gstfaac.h
Changed
@@ -25,6 +25,15 @@ #include <faac.h> +/* FAAC_VERSION_MAJOR is the faac API version, not the release version: + * faac < 2.0: not defined (legacy faacEnc* API), treated as 0 + * faac 2.0 - 2.1: 1 (faac_* API) + * faac >= 2.2: 2 (faac_params_init() takes a caller_size argument) + */ +#ifndef FAAC_VERSION_MAJOR +#define FAAC_VERSION_MAJOR 0 +#endif + G_BEGIN_DECLS #define GST_TYPE_FAAC \ @@ -64,7 +73,11 @@ midside; /* FAAC object */ +#if FAAC_VERSION_MAJOR >= 1 + faac_encoder *handle; +#else faacEncHandle handle; +#endif }; struct _GstFaacClass {
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/ext/faac/meson.build -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/ext/faac/meson.build
Changed
@@ -15,13 +15,21 @@ 'faac': pathsep.join(doc_sources) } -faac_dep = cc.find_library('faac', required : get_option('faac')) -have_faac_h = cc.has_header_symbol('faac.h', 'faacEncOpen') -if not have_faac_h and get_option('faac').enabled() - error('faac plugin enabled: found libfaac, but not faac.h') +if get_option('faac').disabled() + faac_dep = dependency('', required: false) + subdir_done() endif -if faac_dep.found() and have_faac_h +# faac >= 1.31 ships a pkg-config file, so try that first +faac_dep = dependency('faac', required : false) +if not faac_dep.found() and (cc.has_header_symbol('faac.h', 'faacEncOpen') or cc.has_header_symbol('faac.h', 'faac_encoder_open')) + faac_dep = cc.find_library('faac', required : false) +endif +if not faac_dep.found() and get_option('faac').enabled() + error('faac plugin enabled, but libfaac not found') +endif + +if faac_dep.found() gstfaac = library('gstfaac', faac_sources, c_args : gst_plugins_bad_args,
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/ext/hls/gsthlsdemux.c -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/ext/hls/gsthlsdemux.c
Changed
@@ -1073,16 +1073,29 @@ if (hls_stream->pending_decrypted_buffer) { if (hls_stream->current_key) { GstMapInfo info; - gssize unpadded_size; + guint pad; /* Handle pkcs7 unpadding here */ gst_buffer_map (hls_stream->pending_decrypted_buffer, &info, GST_MAP_READ); - unpadded_size = info.size - info.datainfo.size - 1; - gst_buffer_unmap (hls_stream->pending_decrypted_buffer, &info); + /* The padding byte comes from the (attacker-controlled) ciphertext, so + * it must be validated before use: a value of 0, or one larger than + * the AES block size or the buffer itself, would make the unpadded + * size computation below wrap around and corrupt the heap in the + * gst_buffer_resize() call. */ + pad = info.size > 0 ? info.datainfo.size - 1 : 0; + if (pad == 0 || pad > 16 || pad > info.size) { + GST_WARNING_OBJECT (hls_stream, + "Invalid PKCS7 padding, rejecting fragment"); + gst_buffer_unmap (hls_stream->pending_decrypted_buffer, &info); + gst_buffer_replace (&hls_stream->pending_decrypted_buffer, NULL); + return GST_FLOW_ERROR; + } + + gst_buffer_unmap (hls_stream->pending_decrypted_buffer, &info); gst_buffer_resize (hls_stream->pending_decrypted_buffer, 0, - unpadded_size); + info.size - pad); } ret =
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/ext/vulkan/meson.build -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/ext/vulkan/meson.build
Changed
@@ -13,6 +13,7 @@ 'vkcolorconvert.h', 'vkdeviceprovider.h', 'vkdownload.h', + 'vkav1dec.h', 'vkh264dec.h', 'vkh265dec.h', 'vkvp9dec.h',
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/ext/vulkan/vkav1dec.c -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/ext/vulkan/vkav1dec.c
Changed
@@ -275,8 +275,7 @@ if (self->decoder) gst_vulkan_decoder_stop (self->decoder); - if (self->output_state) - gst_video_codec_state_unref (self->output_state); + g_clear_pointer (&self->output_state, gst_video_codec_state_unref); return GST_VIDEO_DECODER_CLASS (parent_class)->stop (decoder); } @@ -397,7 +396,7 @@ else gst_query_add_allocation_pool (query, pool, size, min, max); - gst_object_unref (pool); + gst_clear_object (&pool); dpb_caps = gst_caps_copy (caps); gst_caps_set_simple (dpb_caps, "width", G_TYPE_INT, @@ -1430,6 +1429,8 @@ g_free (long_name); g_free (cdata->description); + gst_clear_caps (&cdata->codec); + gst_clear_caps (&cdata->raw); g_free (cdata); }
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/ext/vulkan/vkh264dec.c -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/ext/vulkan/vkh264dec.c
Changed
@@ -398,7 +398,6 @@ gst_vulkan_image_buffer_pool_config_set_decode_caps (config, profile_caps); gst_caps_unref (profile_caps); - gst_caps_unref (new_caps); if (!gst_buffer_pool_set_config (pool, config)) goto bail; @@ -408,9 +407,11 @@ else gst_query_add_allocation_pool (query, pool, size, min, max); - gst_object_unref (pool); + gst_clear_object (&pool); - gst_vulkan_decoder_create_dpb_pool (self->decoder, new_caps); + if (!gst_vulkan_decoder_create_dpb_pool (self->decoder, new_caps)) + goto bail; + gst_caps_unref (new_caps); return TRUE;
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/ext/vulkan/vkh265dec.c -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/ext/vulkan/vkh265dec.c
Changed
@@ -416,7 +416,6 @@ gst_vulkan_image_buffer_pool_config_set_decode_caps (config, profile_caps); gst_caps_unref (profile_caps); - gst_caps_unref (new_caps); if (!gst_buffer_pool_set_config (pool, config)) goto bail; @@ -426,9 +425,11 @@ else gst_query_add_allocation_pool (query, pool, size, min, max); - gst_object_unref (pool); + gst_clear_object (&pool); - gst_vulkan_decoder_create_dpb_pool (self->decoder, new_caps); + if (!gst_vulkan_decoder_create_dpb_pool (self->decoder, new_caps)) + goto bail; + gst_caps_unref (new_caps); return TRUE; @@ -997,7 +998,7 @@ .sps_sub_layer_ordering_info_present_flag = sps->sub_layer_ordering_info_present_flag, .scaling_list_enabled_flag = sps->scaling_list_enabled_flag, - .sps_scaling_list_data_present_flag = sps->scaling_list_enabled_flag, + .sps_scaling_list_data_present_flag = sps->scaling_list_data_present_flag, .amp_enabled_flag = sps->amp_enabled_flag, .sample_adaptive_offset_enabled_flag = sps->sample_adaptive_offset_enabled_flag,
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/ext/vulkan/vkvp9dec.c -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/ext/vulkan/vkvp9dec.c
Changed
@@ -387,7 +387,6 @@ gst_vulkan_image_buffer_pool_config_set_decode_caps (config, profile_caps); gst_caps_unref (profile_caps); - gst_caps_unref (new_caps); if (!gst_buffer_pool_set_config (pool, config)) goto bail; @@ -397,7 +396,7 @@ else gst_query_add_allocation_pool (query, pool, size, min, max); - gst_object_unref (pool); + gst_clear_object (&pool); /* * When the pool is destroyed during resolution changes, previously decoded @@ -415,6 +414,7 @@ if (!gst_vulkan_decoder_create_dpb_pool (self->decoder, dpb_caps)) goto bail; gst_caps_unref (dpb_caps); + gst_caps_unref (new_caps); return TRUE; @@ -1146,6 +1146,8 @@ g_free (long_name); g_free (cdata->description); + gst_clear_caps (&cdata->codec); + gst_clear_caps (&cdata->raw); g_free (cdata); }
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/ext/wpe2/gstwpethreadedview.cpp -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/ext/wpe2/gstwpethreadedview.cpp
Changed
@@ -854,9 +854,9 @@ if (gst_navigation_event_parse_modifier_state (event, &modifier_state)) { if (modifier_state & GST_NAVIGATION_MODIFIER_BUTTON1_MASK) wpe_button = WPE_BUTTON_PRIMARY; - else if (modifier_state & GST_NAVIGATION_MODIFIER_BUTTON2_MASK) - wpe_button = WPE_BUTTON_MIDDLE; else if (modifier_state & GST_NAVIGATION_MODIFIER_BUTTON3_MASK) + wpe_button = WPE_BUTTON_MIDDLE; + else if (modifier_state & GST_NAVIGATION_MODIFIER_BUTTON2_MASK) wpe_button = WPE_BUTTON_SECONDARY; }
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/gst-libs/gst/codecparsers/gstav1parser.c -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/gst-libs/gst/codecparsers/gstav1parser.c
Changed
@@ -349,7 +349,7 @@ return 0; } - value = readv + (1 << leadingZero) - 1; + value = readv + (1U << leadingZero) - 1; return value; } @@ -414,7 +414,7 @@ if (*retval != GST_AV1_PARSER_OK) return 0; - t += (byte << (i * 8)); + t += ((guint) byte << (i * 8)); } return t; } @@ -1171,7 +1171,10 @@ seq_header->initial_display_delay_present_flag = 0; seq_header->operating_points_cnt_minus_1 = 0; seq_header->operating_points0.idc = 0; - seq_header->operating_points0.seq_level_idx = AV1_READ_BITS (br, 5); + seq_header->operating_points0.seq_level_idx = + AV1_READ_BITS_CHECKED (br, 5, &retval); + if (retval != GST_AV1_PARSER_OK) + goto error; if (!av1_seq_level_idx_is_valid (seq_header->operating_points0.seq_level_idx)) { GST_INFO ("The seq_level_idx is unsupported"); @@ -1234,13 +1237,18 @@ goto error; } if (seq_header->operating_pointsi.seq_level_idx > GST_AV1_SEQ_LEVEL_3_3) { - seq_header->operating_pointsi.seq_tier = AV1_READ_BIT (br); + seq_header->operating_pointsi.seq_tier = + AV1_READ_BIT_CHECKED (br, &retval); + if (retval != GST_AV1_PARSER_OK) + goto error; } else { seq_header->operating_pointsi.seq_tier = 0; } if (seq_header->decoder_model_info_present_flag) { seq_header->operating_pointsi.decoder_model_present_for_this_op = - AV1_READ_BIT (br); + AV1_READ_BIT_CHECKED (br, &retval); + if (retval != GST_AV1_PARSER_OK) + goto error; if (seq_header->operating_pointsi.decoder_model_present_for_this_op) retval = gst_av1_parse_operating_parameters_info (parser, br, seq_header, @@ -1287,15 +1295,23 @@ operatingPoint = choose_operating_point( ) operating_point_idc = operating_point_idc operatingPoint */ - if (AV1_REMAINING_BITS (br) < 4 + 4 + - (seq_header->frame_width_bits_minus_1 + 1) + - (seq_header->frame_height_bits_minus_1 + 1)) { + if (AV1_REMAINING_BITS (br) < 4 + 4) { retval = GST_AV1_PARSER_NO_MORE_DATA; goto error; } seq_header->frame_width_bits_minus_1 = AV1_READ_BITS (br, 4); seq_header->frame_height_bits_minus_1 = AV1_READ_BITS (br, 4); + + /* The frame sizes are encoded relative to the bit widths just read, + * so the remaining bits can only be checked after those fields have + * been parsed. */ + if (AV1_REMAINING_BITS (br) < (seq_header->frame_width_bits_minus_1 + 1) + + (seq_header->frame_height_bits_minus_1 + 1)) { + retval = GST_AV1_PARSER_NO_MORE_DATA; + goto error; + } + seq_header->max_frame_width_minus_1 = AV1_READ_BITS (br, seq_header->frame_width_bits_minus_1 + 1); seq_header->max_frame_height_minus_1 = @@ -1924,6 +1940,16 @@ if (found_ref == 1) { gint ref_idx = frame_header->ref_frame_idxi; + + /* The reference slot may never have been filled by a parsed + * frame, in which case it carries a zero size; a zero frame size + * would propagate into the tile grid and divide by zero there. */ + if (G_UNLIKELY (ref_info->entryref_idx.ref_frame_width == 0 || + ref_info->entryref_idx.ref_frame_height == 0)) { + GST_WARNING ("Frame size reference %d has no known size", ref_idx); + return GST_AV1_PARSER_MISSING_OBU_REFERENCE; + } + parser->state.upscaled_width = ref_info->entryref_idx.ref_upscaled_width; parser->state.frame_width = parser->state.upscaled_width; @@ -2886,7 +2912,7 @@ gint32 prev_gm_paramsGST_AV1_NUM_REF_FRAMES6, gint ref, gint idx) { GstAV1ParserResult retval; - gint prec_diff /* precDiff */ , wm_round, mx, r; + gint prec_diff /* precDiff */ , wm_round, mx, r, val; gint abs_bits /* absBits */ = GST_AV1_GM_ABS_ALPHA_BITS; gint prec_bits /* precBits */ = GST_AV1_GM_ALPHA_PREC_BITS; gint sub; @@ -2910,11 +2936,13 @@ sub = (idx % 3) == 2 ? (1 << prec_bits) : 0; mx = (1 << abs_bits); r = (prev_gm_paramsrefidx >> prec_diff) - sub; - gm_params->gm_paramsrefidx = - (gst_av1_decode_signed_subexp_with_ref (br, -mx, mx + 1, r, - &retval) << prec_diff) + wm_round; + val = gst_av1_decode_signed_subexp_with_ref (br, -mx, mx + 1, r, &retval); if (retval != GST_AV1_PARSER_OK) return retval; + /* The decoded value is signed; scale it by multiplication, as + * left-shifting a negative value is undefined. The product fits a + * gint: |val| <= 2^12 + 1 and prec_diff <= 14. */ + gm_params->gm_paramsrefidx = val * (1 << prec_diff) + wm_round; return GST_AV1_PARSER_OK; } @@ -4418,7 +4446,8 @@ goto error; } - if (tile_group->tg_end < tile_group->tg_start) { + if (tile_group->tg_end < tile_group->tg_start || + tile_group->tg_end >= tile_group->num_tiles) { retval = GST_AV1_PARSER_NO_MORE_DATA; goto error; }
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/gst-libs/gst/codecparsers/gsth264parser.c -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/gst-libs/gst/codecparsers/gsth264parser.c
Changed
@@ -206,6 +206,9 @@ if (nalu->size < 1) return FALSE; + if (data0 & 0x80) + return FALSE; + nalu->type = (data0 & 0x1f); nalu->ref_idc = (data0 & 0x60) >> 5; nalu->idr_pic_flag = (nalu->type == 5 ? 1 : 0); @@ -1219,8 +1222,11 @@ after the value 1 for frame_packing_arrangement_extension_flag shall be ignored (D.2.25) */ if (frame_packing_extension_flag) { - nal_reader_skip_long (nr, - payload_size - (nal_reader_get_pos (nr) - start_pos)); + guint consumed = nal_reader_get_pos (nr) - start_pos; + + if (consumed > payload_size || + !nal_reader_skip_long (nr, payload_size - consumed)) + goto error; } return GST_H264_PARSER_OK; @@ -1323,7 +1329,11 @@ } while (payload_size_byte == 0xff); - remaining = nal_reader_get_remaining (nr); + /* nal_reader_get_remaining() includes emulation prevention bytes, but + * payloadSize counts RBSP bytes. Also tolerate broken streams which count + * emulation prevention bytes in payloadSize by limiting the payload to the + * RBSP data that is actually available. */ + remaining = nal_reader_get_remaining_payload_bits (nr); payload_size = payloadSize * 8 < remaining ? payloadSize * 8 : remaining; next = nal_reader_get_pos (nr) + payload_size; @@ -1377,6 +1387,14 @@ break; } + /* A failed payload parse can leave the reader in an inconsistent + * state; reading from it any further is undefined. BROKEN_LINK is + * returned before the payload is consumed, so the message can still + * be skipped over and reported for retry. */ + if (G_UNLIKELY (res != GST_H264_PARSER_OK + && res != GST_H264_PARSER_BROKEN_LINK)) + goto error; + /* When SEI message doesn't end at byte boundary, * check remaining bits fit the specification. */ @@ -1498,6 +1516,13 @@ nalu->data = (guint8 *) data; nalu->size = size - nalu->offset; + /* An invalid header cannot become valid by appending more data. */ + if (datanalu->offset & 0x80) { + GST_WARNING ("NAL has forbidden_zero_bit set"); + nalu->size = 0; + return GST_H264_PARSER_BROKEN_DATA; + } + if (!gst_h264_parse_nalu_header (nalu)) { GST_DEBUG ("not enough data to parse \"NAL unit header\""); nalu->size = 0; @@ -1767,8 +1792,8 @@ nalu.data = (guint8 *) data; nalu.valid = TRUE; - gst_h264_parse_nalu_header (&nalu); - g_array_append_val (nalus, nalu); + if (gst_h264_parse_nalu_header (&nalu)) + g_array_append_val (nalus, nalu); } break; } else if ((sc_offset == 2 && dataoff + sc_offset - 1 != 0) @@ -1787,8 +1812,8 @@ nalu.data = (guint8 *) data; nalu.valid = TRUE; - gst_h264_parse_nalu_header (&nalu); - g_array_append_val (nalus, nalu); + if (gst_h264_parse_nalu_header (&nalu)) + g_array_append_val (nalus, nalu); } else { /* CONDITION-C */ /* startcode located at beginning of this chunk without actual nal data. @@ -1882,7 +1907,7 @@ static gboolean gst_h264_parse_sps_data (NalReader * nr, GstH264SPS * sps) { - gint width, height; + guint64 width, height; guint subwc = { 1, 2, 2, 1 }; guint subhc = { 1, 2, 1, 1 }; @@ -1985,36 +2010,50 @@ if (!sps->separate_colour_plane_flag) sps->chroma_array_type = sps->chroma_format_idc; - /* Calculate width and height */ - width = (sps->pic_width_in_mbs_minus1 + 1); - width *= 16; - height = (sps->pic_height_in_map_units_minus1 + 1); - height *= 16 * (2 - sps->frame_mbs_only_flag); - GST_LOG ("initial width=%d, height=%d", width, height); - if (width < 0 || height < 0) { + /* Calculate width and height. The ue() values are unbounded, so + * compute in unsigned 64 bit arithmetic, which cannot overflow, and + * convert to gint only after the range checks. */ + width = (guint64) (sps->pic_width_in_mbs_minus1 + 1) * 16; + height = (guint64) (sps->pic_height_in_map_units_minus1 + 1) * 16 * + (2 - sps->frame_mbs_only_flag); + GST_LOG ("initial width=%" G_GUINT64_FORMAT ", height=%" G_GUINT64_FORMAT, + width, height); + /* Reject sizes whose product does not fit a gint as well: callers + * multiply the two dimensions as gint values. The product cannot + * overflow here, as the first two comparisons short-circuit for + * values larger than G_MAXINT. */ + if (width > G_MAXINT || height > G_MAXINT || width * height > G_MAXINT) { GST_WARNING ("invalid width/height in SPS"); goto error; } - sps->width = width; - sps->height = height; + sps->width = (gint) width; + sps->height = (gint) height; if (sps->frame_cropping_flag) { const guint crop_unit_x = subwcsps->chroma_format_idc; const guint crop_unit_y = subhcsps->chroma_format_idc * (2 - sps->frame_mbs_only_flag); - width -= (sps->frame_crop_left_offset + sps->frame_crop_right_offset) - * crop_unit_x; - height -= (sps->frame_crop_top_offset + sps->frame_crop_bottom_offset) - * crop_unit_y; + /* A crop larger than the frame wraps around and is rejected by + * the same range check. */ + width -= ((guint64) sps->frame_crop_left_offset + + sps->frame_crop_right_offset) * crop_unit_x; + height -= ((guint64) sps->frame_crop_top_offset + + sps->frame_crop_bottom_offset) * crop_unit_y; + + if (width == 0 || width > G_MAXINT || height == 0 || height > G_MAXINT) { + GST_WARNING ("invalid cropped width/height in SPS"); + goto error; + } - sps->crop_rect_width = width; - sps->crop_rect_height = height; + sps->crop_rect_width = (gint) width; + sps->crop_rect_height = (gint) height; sps->crop_rect_x = sps->frame_crop_left_offset * crop_unit_x; sps->crop_rect_y = sps->frame_crop_top_offset * crop_unit_y; - GST_LOG ("crop_rectangle x=%u y=%u width=%u, height=%u", sps->crop_rect_x, + GST_LOG ("crop_rectangle x=%u y=%u width=%" G_GUINT64_FORMAT + ", height=%" G_GUINT64_FORMAT, sps->crop_rect_x, sps->crop_rect_y, width, height); } @@ -2209,6 +2248,11 @@ { NalReader nr; + if (nalu->size < 1 || (nalu->datanalu->offset & 0x80)) { + memset (sps, 0, sizeof (*sps)); + return GST_H264_PARSER_BROKEN_DATA; + } + GST_DEBUG ("parsing Subset SPS"); nal_reader_init (&nr, nalu->data + nalu->offset + nalu->header_bytes, @@ -3024,7 +3068,9 @@ GstH264UserDataUnregistered * udu) { WRITE_BYTES (nw, udu->uuid, 16); - WRITE_BYTES (nw, udu->data, udu->size); + if (udu->size > 0) { + WRITE_BYTES (nw, udu->data, udu->size); + } return TRUE;
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/gst-libs/gst/codecparsers/gsth265parser.c -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/gst-libs/gst/codecparsers/gsth265parser.c
Changed
@@ -241,6 +241,9 @@ if (nalu->size < 2) return FALSE; + if (data0 & 0x80) + return FALSE; + gst_bit_reader_init (&br, data, nalu->size - nalu->offset); /* skip the forbidden_zero_bit */ @@ -1791,8 +1794,8 @@ nalu.data = (guint8 *) data; nalu.valid = TRUE; - gst_h265_parse_nalu_header (&nalu); - g_array_append_val (nalus, nalu); + if (gst_h265_parse_nalu_header (&nalu)) + g_array_append_val (nalus, nalu); } break; } else if ((sc_offset == 2 && dataoff + sc_offset - 1 != 0) @@ -1811,8 +1814,8 @@ nalu.data = (guint8 *) data; nalu.valid = TRUE; - gst_h265_parse_nalu_header (&nalu); - g_array_append_val (nalus, nalu); + if (gst_h265_parse_nalu_header (&nalu)) + g_array_append_val (nalus, nalu); } else { /* CONDITION-C */ /* startcode located at beginning of this chunk without actual nal data. @@ -2018,7 +2021,7 @@ for (i = 1; i < vps->num_hrd_parameters; i++) { guint16 hrd_layer_set_idx; guint8 cprms_present_flag; - GstH265HRDParams hrd_params; + GstH265HRDParams hrd_params = { 0 }; READ_UE_MAX (&nr, hrd_layer_set_idx, 1023); CHECK_ALLOWED_MAX (hrd_layer_set_idx, vps->num_layer_sets_minus1); @@ -2088,7 +2091,7 @@ gst_h265_parser_parse_sps (GstH265Parser * parser, GstH265NalUnit * nalu, GstH265SPS * sps, gboolean parse_vui_params) { - GstH265SPSEXT sps_ext; + GstH265SPSEXT sps_ext = { 0 }; return gst_h265_parser_parse_sps_ext (parser, nalu, sps, &sps_ext, parse_vui_params); @@ -2288,6 +2291,16 @@ sps_scc_extension_params.sps_palette_predictor_initializers_present_flag) { guint comp; + + /* The spec range for sps_num_palette_predictor_initializer_minus1 + * is 0 to palette_max_size + delta_palette_max_predictor_size - 1. + * When that sum is 0 the range is empty, and the -1 would turn the + * bound negative, i.e. huge in the unsigned comparison, accepting + * any value and overflowing the initializer arrays. */ + if (sps->sps_scc_extension_params.palette_max_size + + sps->sps_scc_extension_params.delta_palette_max_predictor_size == 0) + goto error; + READ_UE_MAX (&nr, sps-> sps_scc_extension_params.sps_num_palette_predictor_initializer_minus1, @@ -2335,15 +2348,27 @@ if (sps->conformance_window_flag) { const guint crop_unit_x = subwcsps->chroma_format_idc; const guint crop_unit_y = subhcsps->chroma_format_idc; + guint64 crop_w, crop_h; - sps->crop_rect_width = sps->width - - (sps->conf_win_left_offset + sps->conf_win_right_offset) * crop_unit_x; - sps->crop_rect_height = sps->height - - (sps->conf_win_top_offset + sps->conf_win_bottom_offset) * crop_unit_y; + /* The conf_win offsets are unbounded ue() values; sum them in 64 + * bit so the products cannot wrap, and require the crop to leave + * a non-empty picture. */ + crop_w = ((guint64) sps->conf_win_left_offset + + sps->conf_win_right_offset) * crop_unit_x; + crop_h = ((guint64) sps->conf_win_top_offset + + sps->conf_win_bottom_offset) * crop_unit_y; + + if (crop_w >= (guint64) sps->width || crop_h >= (guint64) sps->height) { + GST_WARNING ("conformance window crops the whole picture in SPS"); + goto error; + } + + sps->crop_rect_width = (gint) ((guint64) sps->width - crop_w); + sps->crop_rect_height = (gint) ((guint64) sps->height - crop_h); sps->crop_rect_x = sps->conf_win_left_offset * crop_unit_x; sps->crop_rect_y = sps->conf_win_top_offset * crop_unit_y; - GST_LOG ("crop_rectangle x=%u y=%u width=%u, height=%u", sps->crop_rect_x, + GST_LOG ("crop_rectangle x=%u y=%u width=%d, height=%d", sps->crop_rect_x, sps->crop_rect_y, sps->crop_rect_width, sps->crop_rect_height); } @@ -3191,7 +3216,7 @@ gst_h265_parser_parse_slice_hdr (GstH265Parser * parser, GstH265NalUnit * nalu, GstH265SliceHdr * slice) { - GstH265SPSEXT sps_ext; + GstH265SPSEXT sps_ext = { 0 }; return gst_h265_parser_parse_slice_hdr_ext (parser, nalu, slice, &sps_ext); } @@ -3232,7 +3257,11 @@ } while (payload_size_byte == 0xff); - remaining = nal_reader_get_remaining (nr); + /* nal_reader_get_remaining() includes emulation prevention bytes, but + * payloadSize counts RBSP bytes. Also tolerate broken streams which count + * emulation prevention bytes in payloadSize by limiting the payload to the + * RBSP data that is actually available. */ + remaining = nal_reader_get_remaining_payload_bits (nr); payload_size = payloadSize * 8 < remaining ? payloadSize * 8 : remaining; payload_start_pos_bit = nal_reader_get_pos (nr); @@ -3296,6 +3325,10 @@ } } + /* A failed message may still own allocations, drop them before returning. */ + if (res != GST_H265_PARSER_OK) + goto error; + /* Not parsing the reserved_payload_extension, but it shouldn't be * an issue because of 1: There shall not be any reserved_payload_extension * present in bitstreams conforming to the specification.2. Even though @@ -3400,7 +3433,9 @@ GstH265PicTiming *dst_pic_timing = &dst_sei->payload.pic_timing; const GstH265PicTiming *src_pic_timing = &src_sei->payload.pic_timing; - if (dst_pic_timing->num_decoding_units_minus1 > 0) { + /* The arrays are allocated for a single decoding unit too, so their + * presence, not num_decoding_units_minus1, tells whether to copy them. */ + if (src_pic_timing->num_nalus_in_du_minus1) { dst_pic_timing->num_nalus_in_du_minus1 = g_new0 (guint32, (dst_pic_timing->num_decoding_units_minus1 + 1)); dst_pic_timing->du_cpb_removal_delay_increment_minus1 = @@ -3450,12 +3485,11 @@ if (sei->payloadType == GST_H265_SEI_PIC_TIMING) { GstH265PicTiming *pic_timing = &sei->payload.pic_timing; - if (pic_timing->num_decoding_units_minus1 > 0) { - g_free (pic_timing->num_nalus_in_du_minus1); - g_free (pic_timing->du_cpb_removal_delay_increment_minus1); - } - pic_timing->num_nalus_in_du_minus1 = 0; - pic_timing->du_cpb_removal_delay_increment_minus1 = 0; + + g_free (pic_timing->num_nalus_in_du_minus1); + g_free (pic_timing->du_cpb_removal_delay_increment_minus1); + pic_timing->num_nalus_in_du_minus1 = NULL; + pic_timing->du_cpb_removal_delay_increment_minus1 = NULL; } else if (sei->payloadType == GST_H265_SEI_REGISTERED_USER_DATA) { GstH265RegisteredUserData *rud = &sei->payload.registered_user_data; g_free ((guint8 *) rud->data); @@ -4310,7 +4344,9 @@ GstH265UserDataUnregistered * udu) { WRITE_BYTES (nw, udu->uuid, 16); - WRITE_BYTES (nw, udu->data, udu->size); + if (udu->size > 0) { + WRITE_BYTES (nw, udu->data, udu->size); + } return TRUE;
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/gst-libs/gst/codecparsers/gsth266parser.c -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/gst-libs/gst/codecparsers/gsth266parser.c
Changed
@@ -196,6 +196,9 @@ if (nalu->size < 2) return FALSE; + if (data0 & 0x80) + return FALSE; + gst_bit_reader_init (&br, data, nalu->size - nalu->offset); /* skip the forbidden_zero_bit and nuh_reserved_zero_bit */ @@ -680,7 +683,7 @@ const GstH266SPS * sps, const GstH266PPS * pps) { const GstH266RefPicListStruct *ref_list; - gint i, j, num_ltrp_entries GST_UNUSED_ASSERT; + gint i, j, num_ltrp_entries; GST_LOG ("parsing \"ref_pic_lists\""); @@ -696,7 +699,11 @@ } if (rpls->rpl_sps_flagi) { - g_assert (sps->num_ref_pic_listsi > 0); + if (G_UNLIKELY (sps->num_ref_pic_listsi == 0)) { + GST_WARNING ("rpl_sps_flag set for list %d but SPS has no " + "ref_pic_lists", i); + goto error; + } if (sps->num_ref_pic_listsi == 1) { rpls->rpl_idxi = 0; @@ -737,7 +744,12 @@ num_ltrp_entries++; } - g_assert (num_ltrp_entries == ref_list->num_long_term_pic); + if (num_ltrp_entries != ref_list->num_long_term_pic) { + GST_WARNING ("num_long_term_pic (%u) does not match the number of " + "long term reference pictures counted (%d)", + ref_list->num_long_term_pic, num_ltrp_entries); + goto error; + } } return TRUE; @@ -1268,7 +1280,10 @@ GST_WARNING ("Invalid qp index %d", k); goto error; } - for (; k <= 63 + qp_bd_offset; k++) { + /* The spec would require 64 + qp_bd_offset table entries (up to 112) + * for the last QP value, but the table is sized 111 to match the + * VA-API ChromaQpTable layout, so stop at the end of the table. */ + for (; k <= 63 + qp_bd_offset && k < GST_H266_MAX_POINTS_IN_QP_TABLE; k++) { sps->chroma_qp_tableik = MAX (sps->chroma_qp_tableik - 1 + 1, -qp_bd_offset); sps->chroma_qp_tableik = MIN (sps->chroma_qp_tableik, 63); @@ -1392,7 +1407,7 @@ gst_h266_parser_parse_pic_timing (GstH266PicTiming * pt, NalReader * nr, const GstH266BufferingPeriod * bp, guint8 TemporalId) { - guint i, j; + guint i, j, k; GST_LOG ("parsing \"Picture timing\""); @@ -1497,8 +1512,8 @@ bp->max_sublayers_minus1; } - for (j = 0; j < TemporalId; j++) - pt->du_cpb_removal_delay_increment_minus1ij = + for (k = 0; k < TemporalId; k++) + pt->du_cpb_removal_delay_increment_minus1ik = pt->du_cpb_removal_delay_increment_minus1i bp->max_sublayers_minus1; } @@ -1629,7 +1644,8 @@ } else { READ_UINT8 (nr, sn->all_layers_flag, 1); if (!sn->all_layers_flag) { - READ_UE_MAX (nr, sn->num_layers_minus1, GST_H266_MAX_LAYERS); + /* layer_id is indexed from 1 up to num_layers_minus1 */ + READ_UE_MAX (nr, sn->num_layers_minus1, GST_H266_MAX_LAYERS - 1); for (i = 1; i <= sn->num_layers_minus1; i++) READ_UINT8 (nr, sn->layer_idi, 6); } @@ -2108,8 +2124,8 @@ nalu.data = (guint8 *) data; nalu.valid = TRUE; - gst_h266_parse_nalu_header (&nalu); - g_array_append_val (nalus, nalu); + if (gst_h266_parse_nalu_header (&nalu)) + g_array_append_val (nalus, nalu); } break; } else if ((sc_offset == 2 && dataoff + sc_offset - 1 != 0) @@ -2128,8 +2144,8 @@ nalu.data = (guint8 *) data; nalu.valid = TRUE; - gst_h266_parse_nalu_header (&nalu); - g_array_append_val (nalus, nalu); + if (gst_h266_parse_nalu_header (&nalu)) + g_array_append_val (nalus, nalu); } else { /* CONDITION-C */ /* startcode located at beginning of this chunk without actual nal data. @@ -2657,6 +2673,8 @@ } if (!vps->each_layer_is_an_ols_flag) { + if (vps->num_multi_layer_olss == 0) + goto error; READ_UE_MAX (&nr, vps->num_dpb_params_minus1, vps->num_multi_layer_olss - 1); @@ -2733,6 +2751,8 @@ } else vps->sublayer_cpb_params_present_flag = 0; + if (vps->num_multi_layer_olss == 0) + goto error; READ_UE_MAX (&nr, vps->num_ols_timing_hrd_params_minus1, vps->num_multi_layer_olss - 1); for (i = 0; i <= vps->num_ols_timing_hrd_params_minus1; i++) { @@ -3489,16 +3509,19 @@ if (sps->timing_hrd_params_present_flag) { guint8 firstSubLayer; - gst_h266_parse_general_timing_hrd_parameters (&sps->general_hrd_params, - &nr); + if (!gst_h266_parse_general_timing_hrd_parameters + (&sps->general_hrd_params, &nr)) + goto error; if (sps->max_sublayers_minus1 > 0) READ_UINT8 (&nr, sps->sublayer_cpb_params_present_flag, 1); firstSubLayer = sps->sublayer_cpb_params_present_flag ? 0 : sps->max_sublayers_minus1; - gst_h266_parse_ols_timing_hrd_parameters (&sps->ols_hrd_params, &nr, - &sps->general_hrd_params, firstSubLayer, sps->max_sublayers_minus1); + if (!gst_h266_parse_ols_timing_hrd_parameters (&sps->ols_hrd_params, &nr, + &sps->general_hrd_params, firstSubLayer, + sps->max_sublayers_minus1)) + goto error; } } @@ -3728,8 +3751,9 @@ tile_y = tile_idx / pps->num_tile_columns; if (tile_x != pps->num_tile_columns - 1) { + /* VVC requires each slice rectangle to fit inside the tile grid */ READ_UE_MAX (nr, pps->slice_width_in_tiles_minus1i, - pps->num_tile_columns - 1); + pps->num_tile_columns - 1 - tile_x); } else { pps->slice_width_in_tiles_minus1i = 0; } @@ -3737,7 +3761,7 @@ if (tile_y != pps->num_tile_rows - 1 && (pps->tile_idx_delta_present_flag || tile_x == 0)) { READ_UE_MAX (nr, pps->slice_height_in_tiles_minus1i, - pps->num_tile_rows - 1); + pps->num_tile_rows - 1 - tile_y); } else { if (tile_y == pps->num_tile_rows - 1) { pps->slice_height_in_tiles_minus1i = 0; @@ -4141,9 +4165,11 @@ { gboolean need_update = FALSE; - g_assert (sps->vps); - g_assert (sps->valid); - g_assert (pps->valid); + if (G_UNLIKELY (sps->vps == NULL || !sps->valid || !pps->valid)) { + GST_WARNING ("Unusable SPS/PPS state: vps %p, sps valid %d, pps valid %d", + sps->vps, sps->valid, pps->valid); + return FALSE; + } if (sps->vps != parser->active_vps) { parser->active_vps = (GstH266VPS *) sps->vps; @@ -4787,7 +4813,7 @@ READ_UINT8 (&nr, dci_reserved_zero_4bits, 4); READ_UINT8 (&nr, dci->num_ptls_minus1, 4); - CHECK_ALLOWED_MAX (dci->num_ptls_minus1, 15); + CHECK_ALLOWED_MAX (dci->num_ptls_minus1, GST_H266_MAX_DCI_PTLS - 1); for (i = 0; i <= dci->num_ptls_minus1; i++) { if (!gst_h266_parse_profile_tier_level (&dci->profile_tier_leveli, &nr, 1, 0)) @@ -5450,8 +5476,10 @@ 1); if (pps->num_tiles_in_pic - sh->slice_address > 1) { + /* Spec: num_tiles_in_slice_minus1 shall be in the range + * 0 to NumTilesInPic - SliceAddress - 1. */ READ_UE_MAX (nr, sh->num_tiles_in_slice_minus1, - pps->num_tiles_in_pic - 1); + pps->num_tiles_in_pic - sh->slice_address - 1); } else { sh->num_tiles_in_slice_minus1 = 0; } @@ -6066,7 +6094,11 @@ payloadSize += payload_size_byte; } while (payload_size_byte == 0xff); - remaining = nal_reader_get_remaining (nr); + /* nal_reader_get_remaining() includes emulation prevention bytes, but + * payloadSize counts RBSP bytes. Also tolerate broken streams which count + * emulation prevention bytes in payloadSize by limiting the payload to the + * RBSP data that is actually available. */ + remaining = nal_reader_get_remaining_payload_bits (nr); payload_size = payloadSize * 8 < remaining ? payloadSize * 8 : remaining; payload_start_pos_bit = nal_reader_get_pos (nr);
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/gst-libs/gst/codecparsers/gsth266parser.h -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/gst-libs/gst/codecparsers/gsth266parser.h
Changed
@@ -50,6 +50,16 @@ /* 7.4.3.3 vps_num_ptls_minus1 shall be less than TotalNumOlss, * which is MAX(GST_H266_MAX_LAYERS, GST_H266_MAX_TOTAL_NUM_OLSS) */ #define GST_H266_MAX_PTLS GST_H266_MAX_TOTAL_NUM_OLSS +/** + * GST_H266_MAX_DCI_PTLS: + * + * Maximum number of profile tier level structures in a DCI. 7.4.3.5: The + * value of dci_num_ptls_minus1 shall be in the range of 0 to 14, inclusive + * (15 is reserved) + * + * Since: 1.28.9 + */ +#define GST_H266_MAX_DCI_PTLS 15 /* 7.3.2.3: vps_video_parameter_set_id is u(4). */ #define GST_H266_MAX_VPS_COUNT 16 /* 7.3.2.4: sps_seq_parameter_set_id is u(4) */ @@ -2838,7 +2848,7 @@ */ struct _GstH266DCI { guint8 num_ptls_minus1; - GstH266ProfileTierLevel profile_tier_level15; + GstH266ProfileTierLevel profile_tier_levelGST_H266_MAX_DCI_PTLS; guint8 extension_flag; guint8 extension_data_flag;
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/gst-libs/gst/codecparsers/gstvc1parser.c -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/gst-libs/gst/codecparsers/gstvc1parser.c
Changed
@@ -747,6 +747,8 @@ { guint i; + memset (hrd_param, 0, sizeof (*hrd_param)); + GST_DEBUG ("Parsing Hrd param flag"); @@ -784,6 +786,8 @@ GstVC1AdvancedSeqHdr *advanced = &seqhdr->advanced; guint8 tmp; + memset (advanced, 0, sizeof (*advanced)); + GST_DEBUG ("Parsing sequence header in advanced mode"); READ_UINT8 (br, tmp, 3); @@ -1326,6 +1330,8 @@ GstVC1PicSimpleMain *pic = &framehdr->pic.simple; GstVC1SeqStructC *structc = &seqhdr->struct_c; + memset (framehdr, 0, sizeof (GstVC1FrameHdr)); + GST_DEBUG ("Parsing frame header in simple or main mode"); /* Set the conveninence fields */ @@ -1538,6 +1544,8 @@ static GstVC1ParserResult parse_sequence_header_struct_a (GstBitReader * br, GstVC1SeqStructA * structa) { + memset (structa, 0, sizeof (GstVC1SeqStructA)); + if (gst_bit_reader_get_remaining (br) < 64) { GST_WARNING ("Failed to parse struct A"); @@ -1553,6 +1561,8 @@ static GstVC1ParserResult parse_sequence_header_struct_b (GstBitReader * br, GstVC1SeqStructB * structb) { + memset (structb, 0, sizeof (GstVC1SeqStructB)); + if (gst_bit_reader_get_remaining (br) < 96) { GST_WARNING ("Failed to parse sequence header"); @@ -1577,6 +1587,8 @@ { guint8 old_interlaced_mode, tmp; + memset (structc, 0, sizeof (GstVC1SeqStructC)); + READ_UINT8 (br, tmp, 2); structc->profile = tmp; @@ -1721,10 +1733,12 @@ * gst_vc1_parse_sequence_layer: * @data: The data to parse * @size: the size of @data - * @seqlayer: The #GstVC1SeqLayer to set. + * @seqlayer: (out): The #GstVC1SeqLayer to set. * * Parses @data, and fills @seqlayer fields. * + * The @seqlayer struct does not need to be initialized by the caller. + * * Returns: a #GstVC1ParserResult */ GstVC1ParserResult @@ -1741,6 +1755,8 @@ g_return_val_if_fail (seqlayer != NULL, GST_VC1_PARSER_ERROR); + memset (seqlayer, 0, sizeof (*seqlayer)); + /* Thanks to the specification, structA and structB fields are defined * as unisgned integer msb first. * But in sequence-layer there are serialized in little-endian byte order, @@ -1820,10 +1836,12 @@ * gst_vc1_parse_sequence_header_struct_a: * @data: The data to parse * @size: the size of @data - * @structa: The #GstVC1SeqStructA to set. + * @structa: (out): The #GstVC1SeqStructA to set. * * Parses @data, and fills @structa fields. * + * The @structa struct does not need to be initialized by the caller. + * * Returns: a #GstVC1ParserResult */ GstVC1ParserResult @@ -1841,10 +1859,12 @@ * gst_vc1_parse_sequence_header_struct_b: * @data: The data to parse * @size: the size of @data - * @structb: The #GstVC1SeqStructB to set. + * @structb: (out): The #GstVC1SeqStructB to set. * * Parses @data, and fills @structb fields. * + * The @structb struct does not need to be initialized by the caller. + * * Returns: a #GstVC1ParserResult */ GstVC1ParserResult @@ -1862,10 +1882,12 @@ * gst_vc1_parse_sequence_header_struct_c: * @data: The data to parse * @size: the size of @data - * @structc: The #GstVC1SeqStructC to set. + * @structc: (out): The #GstVC1SeqStructC to set. * * Parses @data, and fills @structc fields. * + * The @structc struct does not need to be initialized by the caller. + * * Returns: a #GstVC1ParserResult */ GstVC1ParserResult @@ -1883,10 +1905,12 @@ * gst_vc1_parse_sequence_header: * @data: The data to parse * @size: the size of @data -* @seqhdr: The #GstVC1SeqHdr to set. +* @seqhdr: (out): The #GstVC1SeqHdr to set. * * Parses @data, and fills @seqhdr fields. * + * The @seqhdr struct does not need to be initialized by the caller. + * * Returns: a #GstVC1ParserResult */ GstVC1ParserResult @@ -1897,6 +1921,8 @@ g_return_val_if_fail (seqhdr != NULL, GST_VC1_PARSER_ERROR); + memset (seqhdr, 0, sizeof (GstVC1SeqHdr)); + if (parse_sequence_header_struct_c (&br, &seqhdr->struct_c) == GST_VC1_PARSER_ERROR) goto failed; @@ -1928,7 +1954,9 @@ * * Parses @data, and sets @entrypoint fields. * - * Returns: a #GstVC1EntryPointHdr + * The @entrypoint struct does not need to be initialized by the caller. + * + * Returns: a #GstVC1ParserResult */ GstVC1ParserResult gst_vc1_parse_entry_point_header (const guint8 * data, gsize size, @@ -1936,9 +1964,14 @@ { GstBitReader br; guint8 i; - GstVC1AdvancedSeqHdr *advanced = &seqhdr->advanced; + GstVC1AdvancedSeqHdr *advanced; g_return_val_if_fail (entrypoint != NULL, GST_VC1_PARSER_ERROR); + g_return_val_if_fail (seqhdr != NULL, GST_VC1_PARSER_ERROR); + + memset (entrypoint, 0, sizeof (GstVC1EntryPointHdr)); + + advanced = &seqhdr->advanced; gst_bit_reader_init (&br, data, size); @@ -2005,10 +2038,12 @@ * gst_vc1_parse_frame_layer: * @data: The data to parse * @size: the size of @data - * @framelayer: The #GstVC1FrameLayer to fill. + * @framelayer: (out): The #GstVC1FrameLayer to fill. * * Parses @data, and fills @framelayer fields. * + * The @framelayer struct does not need to be initialized by the caller. + * * Returns: a #GstVC1ParserResult */ GstVC1ParserResult @@ -2017,15 +2052,16 @@ { GstBitReader br = GST_BIT_READER_INIT (data, size); + g_return_val_if_fail (framelayer != NULL, GST_VC1_PARSER_ERROR); + + memset (framelayer, 0, sizeof (*framelayer)); + if (gst_bit_reader_get_remaining (&br) < 64) { GST_WARNING ("Could not parse frame layer"); return GST_VC1_PARSER_ERROR; } - /* set default values */ - framelayer->skiped_p_frame = 0; - framelayer->key = gst_bit_reader_get_bits_uint8_unchecked (&br, 1); gst_bit_reader_skip_unchecked (&br, 7); @@ -2046,11 +2082,13 @@ * gst_vc1_parse_frame_header: * @data: The data to parse * @size: the size of @data - * @framehdr: The #GstVC1FrameHdr to fill. + * @framehdr: (out): The #GstVC1FrameHdr to fill. * @seqhdr: The #GstVC1SeqHdr currently being parsed * @bitplanes: The #GstVC1BitPlanes to store bitplanes in or %NULL * - * Parses @data, and fills @entrypoint fields. + * Parses @data, and fills @framehdr fields. + * + * The @framehdr struct does not need to be initialized by the caller. * * Returns: a #GstVC1ParserResult */ @@ -2062,6 +2100,9 @@ GstBitReader br; GstVC1ParserResult result; + g_return_val_if_fail (framehdr != NULL, GST_VC1_PARSER_ERROR); + g_return_val_if_fail (seqhdr != NULL, GST_VC1_PARSER_ERROR); + gst_bit_reader_init (&br, data, size); if (seqhdr->profile == GST_VC1_PROFILE_ADVANCED) @@ -2078,12 +2119,14 @@ * gst_vc1_parse_field_header: * @data: The data to parse * @size: the size of @data - * @fieldhdr: The #GstVC1FrameHdr to fill. + * @fieldhdr: (out): The #GstVC1FrameHdr to fill. * @seqhdr: The #GstVC1SeqHdr currently being parsed * @bitplanes: The #GstVC1BitPlanes to store bitplanes in or %NULL * * Parses @data, and fills @fieldhdr fields. * + * The @fieldhdr struct does not need to be initialized by the caller. + * * Returns: a #GstVC1ParserResult */ GstVC1ParserResult @@ -2094,6 +2137,9 @@ GstBitReader br; GstVC1ParserResult result; + g_return_val_if_fail (fieldhdr != NULL, GST_VC1_PARSER_ERROR); + g_return_val_if_fail (seqhdr != NULL, GST_VC1_PARSER_ERROR); + gst_bit_reader_init (&br, data, size); result = parse_frame_header_advanced (&br, fieldhdr, seqhdr, bitplanes, TRUE); @@ -2105,11 +2151,13 @@ * gst_vc1_parse_slice_header: * @data: The data to parse * @size: The size of @data - * @slicehdr: The #GstVC1SliceHdr to fill + * @slicehdr: (out): The #GstVC1SliceHdr to fill * @seqhdr: The #GstVC1SeqHdr that was previously parsed * * Parses @data, and fills @slicehdr fields. * + * The @slicehdr struct does not need to be initialized by the caller. + * * Returns: a #GstVC1ParserResult * * Since: 1.2 @@ -2125,6 +2173,11 @@ GST_DEBUG ("Parsing slice header"); + g_return_val_if_fail (slicehdr != NULL, GST_VC1_PARSER_ERROR); + g_return_val_if_fail (seqhdr != NULL, GST_VC1_PARSER_ERROR); + + memset (slicehdr, 0, sizeof (*slicehdr)); + if (seqhdr->profile != GST_VC1_PROFILE_ADVANCED) return GST_VC1_PARSER_BROKEN_DATA;
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/gst-libs/gst/codecparsers/gstvc1parser.h -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/gst-libs/gst/codecparsers/gstvc1parser.h
Changed
@@ -298,9 +298,9 @@ guint framerate; /* Around in fps, 0 if unknown*/ guint bitrate; /* Around in kpbs, 0 if unknown*/ - /* This should be filled by user if previously known */ + /* Only filled for WMVP streams */ guint16 coded_width; - /* This should be filled by user if previously known */ + /* Only filled for WMVP streams */ guint16 coded_height; /* Wmvp specific */
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/gst-libs/gst/codecparsers/gstvp9parser.c -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/gst-libs/gst/codecparsers/gstvp9parser.c
Changed
@@ -56,8 +56,32 @@ initialized = TRUE; \ } -#define gst_vp9_read_bit(br) gst_bit_reader_get_bits_uint8_unchecked(br, 1) -#define gst_vp9_read_bits(br, bits) gst_bit_reader_get_bits_uint32_unchecked(br, bits) +/* The VP9 frame header syntax is data-dependent, so a truncated buffer can + * be detected only after the whole header was walked. Reads past the end of + * the buffer are therefore not checked at each call site; the wrapper below + * records the first failure instead and the parsing entry points bail out + * when it is set. */ +typedef struct +{ + GstBitReader br; + gboolean failed; +} GstVp9BitReader; + +static guint32 +gst_vp9_read_bits_ (GstVp9BitReader * br, guint nbits) +{ + guint32 val = 0; + + if (G_UNLIKELY (!gst_bit_reader_get_bits_uint32 (&br->br, &val, nbits))) { + br->failed = TRUE; + return 0; + } + + return val; +} + +#define gst_vp9_read_bit(br) gst_vp9_read_bits_ (br, 1) +#define gst_vp9_read_bits(br, bits) gst_vp9_read_bits_ (br, bits) #define GST_VP9_PARSER_GET_PRIVATE(parser) ((GstVp9ParserPrivate *)(parser)) @@ -85,14 +109,14 @@ } GstVp9ParserPrivate; static gint32 -gst_vp9_read_signed_bits (GstBitReader * br, int bits) +gst_vp9_read_signed_bits (GstVp9BitReader * br, int bits) { const gint32 value = gst_vp9_read_bits (br, bits); return gst_vp9_read_bit (br) ? -value : value; } static gboolean -verify_frame_marker (GstBitReader * br) +verify_frame_marker (GstVp9BitReader * br) { guint8 frame_marker = gst_vp9_read_bits (br, 2); if (frame_marker != GST_VP9_FRAME_MARKER) { @@ -103,20 +127,20 @@ } static gboolean -verify_sync_code (GstBitReader * const br) +verify_sync_code (GstVp9BitReader * const br) { return (gst_vp9_read_bits (br, 24) == GST_VP9_SYNC_CODE); } static gboolean -verify_superframe_marker (GstBitReader * br) +verify_superframe_marker (GstVp9BitReader * br) { return gst_vp9_read_bits (br, 3) == GST_VP9_SUPERFRAME_MARKER; } static gboolean parse_bitdepth_colorspace_sampling (GstVp9Parser * parser, - GstBitReader * const br, GstVp9FrameHdr * frame_hdr) + GstVp9BitReader * const br, GstVp9FrameHdr * frame_hdr) { if (frame_hdr->profile > GST_VP9_PROFILE_1) parser->bit_depth = @@ -169,7 +193,7 @@ } static guint -parse_profile (GstBitReader * br) +parse_profile (GstVp9BitReader * br) { guint8 profile = gst_vp9_read_bit (br); profile |= gst_vp9_read_bit (br) << 1; @@ -179,7 +203,7 @@ } static void -parse_frame_size (GstBitReader * br, guint32 * width, guint32 * height) +parse_frame_size (GstVp9BitReader * br, guint32 * width, guint32 * height) { const guint32 w = gst_vp9_read_bits (br, 16) + 1; const guint32 h = gst_vp9_read_bits (br, 16) + 1; @@ -188,7 +212,7 @@ } static void -parse_display_frame_size (GstBitReader * br, GstVp9FrameHdr * frame_hdr) +parse_display_frame_size (GstVp9BitReader * br, GstVp9FrameHdr * frame_hdr) { frame_hdr->display_size_enabled = gst_vp9_read_bit (br); if (frame_hdr->display_size_enabled) @@ -198,7 +222,7 @@ static void parse_frame_size_from_refs (const GstVp9Parser * parser, - GstVp9FrameHdr * frame_hdr, GstBitReader * br) + GstVp9FrameHdr * frame_hdr, GstVp9BitReader * br) { gboolean found = FALSE; int i; @@ -219,7 +243,7 @@ } static GstVp9InterpolationFilter -parse_interp_filter (GstBitReader * br) +parse_interp_filter (GstVp9BitReader * br) { static const GstVp9InterpolationFilter filter_map = { GST_VP9_INTERPOLATION_FILTER_EIGHTTAP_SMOOTH, @@ -233,7 +257,7 @@ } static void -parse_loopfilter (GstVp9LoopFilter * lf, GstBitReader * br) +parse_loopfilter (GstVp9LoopFilter * lf, GstVp9BitReader * br) { lf->filter_level = gst_vp9_read_bits (br, 6); lf->sharpness_level = gst_vp9_read_bits (br, 3); @@ -261,13 +285,13 @@ } static gint8 -parse_delta_q (GstBitReader * br) +parse_delta_q (GstVp9BitReader * br) { return gst_vp9_read_bit (br) ? gst_vp9_read_signed_bits (br, 4) : 0; } static void -parse_quantization (GstVp9QuantIndices * quant_indices, GstBitReader * br) +parse_quantization (GstVp9QuantIndices * quant_indices, GstVp9BitReader * br) { quant_indices->y_ac_qi = gst_vp9_read_bits (br, QINDEX_BITS); quant_indices->y_dc_delta = parse_delta_q (br); @@ -276,7 +300,7 @@ } static void -parse_segmentation (GstVp9SegmentationInfo * seg, GstBitReader * br) +parse_segmentation (GstVp9SegmentationInfo * seg, GstVp9BitReader * br) { int i; @@ -366,7 +390,7 @@ } static gboolean -parse_tile_info (GstVp9FrameHdr * frame_hdr, GstBitReader * br) +parse_tile_info (GstVp9FrameHdr * frame_hdr, GstVp9BitReader * br) { guint32 max_ones; const guint32 sb_cols = ALIGN_SB64 (frame_hdr->width); @@ -686,10 +710,11 @@ gst_vp9_parser_parse_frame_header (GstVp9Parser * parser, GstVp9FrameHdr * frame_hdr, const guint8 * data, gsize size) { - GstBitReader bit_reader; - GstBitReader *br = &bit_reader; + GstVp9BitReader bit_reader; + GstVp9BitReader *br = &bit_reader; - gst_bit_reader_init (br, data, size); + gst_bit_reader_init (&br->br, data, size); + br->failed = FALSE; memset (frame_hdr, 0, sizeof (*frame_hdr)); /* Parsing Uncompressed Data Chunk */ @@ -706,6 +731,8 @@ frame_hdr->show_existing_frame = gst_vp9_read_bit (br); if (frame_hdr->show_existing_frame) { frame_hdr->frame_to_show = gst_vp9_read_bits (br, GST_VP9_REF_FRAMES_LOG2); + if (G_UNLIKELY (br->failed)) + goto error; return GST_VP9_PARSER_OK; } @@ -811,8 +838,13 @@ goto error; } + if (G_UNLIKELY (br->failed)) { + GST_ERROR ("Frame header extends past the end of the frame data !"); + goto error; + } + frame_hdr->frame_header_length_in_bytes = - (gst_bit_reader_get_pos (br) + 7) / 8; + (gst_bit_reader_get_pos (&br->br) + 7) / 8; return gst_vp9_parser_update (parser, frame_hdr); error: @@ -841,8 +873,8 @@ gst_vp9_parser_parse_superframe_info (GstVp9Parser * parser, GstVp9SuperframeInfo * superframe_info, const guint8 * data, gsize size) { - GstBitReader header_bit_reader, index_bit_reader; - GstBitReader *hbr = &header_bit_reader, *ibr = &index_bit_reader; + GstVp9BitReader header_bit_reader, index_bit_reader; + GstVp9BitReader *hbr = &header_bit_reader, *ibr = &index_bit_reader; guint i, j; g_return_val_if_fail (parser != NULL, GST_VP9_PARSER_ERROR); @@ -850,7 +882,9 @@ g_return_val_if_fail (data != NULL, GST_VP9_PARSER_ERROR); g_return_val_if_fail (size > 0, GST_VP9_PARSER_ERROR); - gst_bit_reader_init (hbr, data + size - 1, 1); + gst_bit_reader_init (&hbr->br, data + size - 1, 1); + hbr->failed = FALSE; + ibr->failed = FALSE; memset (superframe_info, 0, sizeof (GstVp9SuperframeInfo)); /* Parsing Superframe Data Chunk */ @@ -877,7 +911,7 @@ if (size < superframe_info->superframe_index_size) goto error; - gst_bit_reader_init (ibr, + gst_bit_reader_init (&ibr->br, data + size - superframe_info->superframe_index_size, superframe_info->superframe_index_size); @@ -890,6 +924,9 @@ superframe_info->frame_sizesi |= gst_vp9_read_bits (ibr, 8) << (j * 8); } + if (G_UNLIKELY (hbr->failed || ibr->failed)) + goto error; + return GST_VP9_PARSER_OK; error:
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/gst-libs/gst/codecparsers/nalutils.c -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/gst-libs/gst/codecparsers/nalutils.c
Changed
@@ -57,18 +57,28 @@ gboolean nal_reader_read (NalReader * nr, guint nbits) { + NalReader saved; + if (G_UNLIKELY (nr->byte * 8 + (nbits - nr->bits_in_cache) > nr->size * 8)) { GST_DEBUG ("Can not read %u bits, bits in cache %u, Byte * 8 %u, size in " "bits %u", nbits, nr->bits_in_cache, nr->byte * 8, nr->size * 8); return FALSE; } + /* A failed refill must leave the reader exactly as it was: callers rely + * on bits_in_cache holding at most 7 bits between calls, and skipping + * emulation prevention bytes can make the refill run out of data after + * it has already cached whole bytes. */ + saved = *nr; + while (nr->bits_in_cache < nbits) { guint8 byte; next_byte: - if (G_UNLIKELY (nr->byte >= nr->size)) + if (G_UNLIKELY (nr->byte >= nr->size)) { + *nr = saved; return FALSE; + } byte = nr->datanr->byte++; nr->epb_cache = (nr->epb_cache << 8) | byte; @@ -108,11 +118,14 @@ /* Leave out enough bits in the cache once we are finished */ const guint skip_size = 4 * sizeof (nr->cache); guint remaining = nbits; + NalReader saved = *nr; nbits %= skip_size; while (remaining > 0) { - if (!nal_reader_skip (nr, nbits)) + if (!nal_reader_skip (nr, nbits)) { + *nr = saved; return FALSE; + } remaining -= nbits; nbits = skip_size; } @@ -131,6 +144,23 @@ return (nr->size - nr->byte) * 8 + nr->bits_in_cache; } +/* Like nal_reader_get_remaining() but only counts the remaining RBSP payload + * bits, i.e. skips emulation prevention bytes and any RBSP trailing bits. */ +guint +nal_reader_get_remaining_payload_bits (NalReader * nr) +{ + NalReader tmp = *nr; + guint remaining = 0; + + while (nal_reader_has_more_data (&tmp)) { + if (!nal_reader_skip (&tmp, 8)) + break; + remaining += 8; + } + + return remaining; +} + guint nal_reader_get_epb_count (const NalReader * nr) { @@ -198,7 +228,7 @@ if (G_UNLIKELY (!nal_reader_get_bits_uint32 (nr, &value, i))) return FALSE; - *val = (1 << i) - 1 + value; + *val = (1U << i) - 1 + value; return TRUE; }
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/gst-libs/gst/codecparsers/nalutils.h -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/gst-libs/gst/codecparsers/nalutils.h
Changed
@@ -79,6 +79,9 @@ guint nal_reader_get_remaining (const NalReader * nr); G_GNUC_INTERNAL +guint nal_reader_get_remaining_payload_bits (NalReader * nr); + +G_GNUC_INTERNAL guint nal_reader_get_epb_count (const NalReader * nr); G_GNUC_INTERNAL
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/gst-libs/gst/codecs/gsth264decoder.c -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/gst-libs/gst/codecs/gsth264decoder.c
Changed
@@ -2493,6 +2493,12 @@ width_mb = sps->width / 16; height_mb = sps->height / 16; + if (width_mb <= 0 || height_mb <= 0) { + GST_WARNING_OBJECT (self, "Invalid SPS dimensions %dx%d", sps->width, + sps->height); + return GST_FLOW_ERROR; + } + max_dpb_frames = MIN (max_dpb_mbs / (width_mb * height_mb), GST_H264_DPB_MAX_SIZE);
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/gst-libs/gst/d3d11/meson.build -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/gst-libs/gst/d3d11/meson.build
Changed
@@ -83,6 +83,10 @@ dependencies: d3d11_lib, dxgi_lib, name: 'building for Win32') + +windows_ui_xaml_h = cc.has_header('windows.ui.xaml.h') +windows_ui_xaml_media_dxinterop_h = cc.has_header('windows.ui.xaml.media.dxinterop.h') + if runtimeobject_lib.found() and d3dcompiler_lib.found() d3d11_winapi_app = cxx.compiles('''#include <winapifamily.h> #include <windows.applicationmodel.core.h> @@ -97,7 +101,7 @@ #error "Windows 10 API is not guaranteed" #endif''', dependencies: d3d11_lib, dxgi_lib, runtimeobject_lib, - name: 'building for WinRT') + name: 'building for WinRT') and windows_ui_xaml_h and windows_ui_xaml_media_dxinterop_h endif if not d3d11_winapi_desktop and not d3d11_winapi_app
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/gst-libs/gst/mpegts/gst-atsc-section.c -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/gst-libs/gst/mpegts/gst-atsc-section.c
Changed
@@ -88,6 +88,7 @@ GstMpegtsAtscVCTSource *copy; copy = g_memdup2 (source, sizeof (GstMpegtsAtscVCTSource)); + copy->short_name = g_strdup (source->short_name); copy->descriptors = g_ptr_array_ref (source->descriptors); return copy; @@ -399,6 +400,10 @@ data += descriptors_loop_length; } + if (end - data < 2) { + GST_WARNING ("MGT data too short to parse descriptors"); + goto error; + } descriptors_loop_length = GST_READ_UINT16_BE (data) & 0xFFF; data += 2; if (data + descriptors_loop_length >= end) { @@ -441,7 +446,7 @@ length = 17; for (i = 0; i < mgt->tables->len; i++) { - GstMpegtsAtscMGTTable *mgt_table = g_ptr_array_index (mgt->tables, 1); + GstMpegtsAtscMGTTable *mgt_table = g_ptr_array_index (mgt->tables, i); /* 2 byte table_type * 2 byte reserved / table_type_PID * 1 byte reserved / table_type_version_number @@ -479,7 +484,7 @@ data += 2; for (i = 0; i < mgt->tables_defined; i++) { - GstMpegtsAtscMGTTable *mgt_table = g_ptr_array_index (mgt->tables, 1); + GstMpegtsAtscMGTTable *mgt_table = g_ptr_array_index (mgt->tables, i); /* table_type - 16 bit uimsbf */ GST_WRITE_UINT16_BE (data, mgt_table->table_type); @@ -493,6 +498,10 @@ GST_WRITE_UINT8 (data, mgt_table->version_number | 0xe0); data += 1; + /* 32 bit table_type_number_bytes uimsbf */ + GST_WRITE_UINT32_BE (data, mgt_table->number_bytes); + data += 4; + /* 4 bit reserved, 12 bit table_type_descriptor_length uimsbf */ pos = data; *data++ = 0xF0; @@ -596,6 +605,9 @@ GstMpegtsAtscStringSegment *copy; copy = g_memdup2 (seg, sizeof (GstMpegtsAtscStringSegment)); + copy->cached_string = g_strdup (seg->cached_string); + copy->compressed_data = + g_memdup2 (seg->compressed_data, seg->compressed_data_size); return copy; } @@ -604,6 +616,7 @@ _gst_mpegts_atsc_string_segment_free (GstMpegtsAtscStringSegment * seg) { g_free (seg->cached_string); + g_free (seg->compressed_data); g_free (seg); } @@ -667,6 +680,9 @@ GError *err = NULL; unsigned long len; + g_return_val_if_fail (seg != NULL, FALSE); + g_return_val_if_fail (string != NULL, FALSE); + if (compression_type) { GST_FIXME ("Compressed strings not yet supported"); goto done; @@ -680,11 +696,9 @@ break; } - if (seg->cached_string) - g_free (seg->cached_string); - - if (seg->compressed_data) - g_free (seg->compressed_data); + g_clear_pointer (&seg->cached_string, g_free); + g_clear_pointer (&seg->compressed_data, g_free); + seg->compressed_data_size = 0; seg->cached_string = g_strdup (string); seg->compression_type = compression_type; @@ -812,7 +826,7 @@ } if (seg->compressed_data_size) - seg->compressed_data = data; + seg->compressed_data = g_memdup2 (data, seg->compressed_data_size); data += seg->compressed_data_size; } @@ -852,9 +866,12 @@ GST_WRITE_UINT8 (*data, string->iso_639_langcode2); *data += 1; /* 8 bit number_segments */ - GST_WRITE_UINT8 (*data, string->segments->len); + GST_WRITE_UINT8 (*data, string->segments ? string->segments->len : 0); *data += 1; + if (string->segments == NULL) + continue; + for (j = 0; j < string->segments->len; j++) { GstMpegtsAtscStringSegment *seg; @@ -882,6 +899,9 @@ gsize length = 1; guint i; + if (strings == NULL) + return 0; + for (i = 0; i < strings->len; i++) { GstMpegtsAtscMultString *string; guint j; @@ -890,6 +910,9 @@ length += 4; + if (string->segments == NULL) + continue; + for (j = 0; j < string->segments->len; j++) { GstMpegtsAtscStringSegment *seg; @@ -1161,6 +1184,8 @@ copy = g_memdup2 (stt, sizeof (GstMpegtsAtscSTT)); copy->descriptors = g_ptr_array_ref (stt->descriptors); + if (stt->utc_datetime) + copy->utc_datetime = gst_date_time_ref (stt->utc_datetime); return copy; } @@ -1455,13 +1480,14 @@ { GstMpegtsAtscRRT *rrt = NULL; guint i = 0; - guint8 *data; + guint8 *data, *end; guint16 descriptors_loop_length; guint8 text_length; rrt = g_new0 (GstMpegtsAtscRRT, 1); data = section->data; + end = data + section->section_length; /* Skip already parsed data */ data += 8; @@ -1471,10 +1497,14 @@ text_length = GST_READ_UINT8 (data); data += 1; + if (text_length > (gsize) (end - 4 - data)) + goto error; rrt->names = _parse_atsc_mult_string (data, text_length); data += text_length; - rrt->dimensions_defined = GST_READ_UINT8 (data); + if (end - 4 - data < 1) + goto error; + rrt->dimensions_defined = GST_READ_UINT8 (data) & 0x1f; data += 1; rrt->dimensions = g_ptr_array_new_full (rrt->dimensions_defined, @@ -1488,11 +1518,17 @@ dim = g_new0 (GstMpegtsAtscRRTDimension, 1); g_ptr_array_add (rrt->dimensions, dim); + if (end - 4 - data < 1) + goto error; text_length = GST_READ_UINT8 (data); data += 1; + if (text_length > (gsize) (end - 4 - data)) + goto error; dim->names = _parse_atsc_mult_string (data, text_length); data += text_length; + if (end - 4 - data < 1) + goto error; tmp = GST_READ_UINT8 (data); data += 1; @@ -1508,24 +1544,42 @@ val = g_new0 (GstMpegtsAtscRRTDimensionValue, 1); g_ptr_array_add (dim->values, val); + if (end - 4 - data < 1) + goto error; text_length = GST_READ_UINT8 (data); data += 1; + if (text_length > (gsize) (end - 4 - data)) + goto error; val->abbrev_ratings = _parse_atsc_mult_string (data, text_length); data += text_length; + if (end - 4 - data < 1) + goto error; text_length = GST_READ_UINT8 (data); data += 1; + if (text_length > (gsize) (end - 4 - data)) + goto error; val->ratings = _parse_atsc_mult_string (data, text_length); data += text_length; } } + if (end - 4 - data < 2) + goto error; descriptors_loop_length = GST_READ_UINT16_BE (data) & 0x3FF; data += 2; + if (descriptors_loop_length > (gsize) (end - 4 - data)) + goto error; rrt->descriptors = gst_mpegts_parse_descriptors (data, descriptors_loop_length); return (gpointer) rrt; + +error: + GST_WARNING ("Invalid RRT section, aborting parsing"); + _gst_mpegts_atsc_rrt_free (rrt); + + return NULL; } static gboolean @@ -1600,6 +1654,10 @@ _packetize_atsc_mult_string (rrt->names, &data); + /* 3 bit reserved / 5 bit dimensions_defined uimsbf */ + GST_WRITE_UINT8 (data, 0xe0 | (rrt->dimensions_defined & 0x1f)); + data += 1; + for (i = 0; i < rrt->dimensions->len; i++) { GstMpegtsAtscRRTDimension *dim = g_ptr_array_index (rrt->dimensions, i); @@ -1608,7 +1666,7 @@ _get_atsc_mult_string_packetized_length (dim->names)); data += 1; - _packetize_atsc_mult_string (rrt->names, &data); + _packetize_atsc_mult_string (dim->names, &data); /* 3 bit reserved / 1 bit graduated_scale / 4 bit values_defined */ GST_WRITE_UINT8 (data,
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/gst-libs/gst/mpegts/gst-dvb-descriptor.c -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/gst-libs/gst/mpegts/gst-dvb-descriptor.c
Changed
@@ -108,7 +108,7 @@ { GstMpegtsDescriptor *descriptor; guint8 *converted_name; - gsize size; + gsize size = 0; g_return_val_if_fail (name != NULL, NULL); @@ -482,23 +482,48 @@ gchar ** provider_name) { guint8 *data; + const guint8 *end; + guint8 provider_length, service_length; g_return_val_if_fail (descriptor != NULL, FALSE); /* Need at least 3 bytes (type and 2 bytes for the string length) */ __common_desc_checks (descriptor, GST_MTS_DESC_DVB_SERVICE, 3, FALSE); data = (guint8 *) descriptor->data + 2; + end = data + descriptor->length; + + if (service_name) + *service_name = NULL; + if (provider_name) + *provider_name = NULL; if (service_type) *service_type = *data; data += 1; + + provider_length = *data++; + if (provider_length > (guint) (end - data)) + return FALSE; if (provider_name) - *provider_name = get_encoding_and_convert ((const gchar *) data + 1, *data); - data += *data + 1; + *provider_name = + get_encoding_and_convert ((const gchar *) data, provider_length); + data += provider_length; + + if (end - data < 1) + return TRUE; + service_length = *data++; + if (service_length > (guint) (end - data)) + goto fail; if (service_name) - *service_name = get_encoding_and_convert ((const gchar *) data + 1, *data); + *service_name = + get_encoding_and_convert ((const gchar *) data, service_length); return TRUE; + +fail: + if (provider_name) + g_clear_pointer (provider_name, g_free); + return FALSE; } /** @@ -555,6 +580,13 @@ goto beach; } + if (provider_size + service_size + 3 > 255) { + GST_WARNING + ("Service provider and name strings too big (%" G_GSIZE_FORMAT " + %" + G_GSIZE_FORMAT " > 252)", provider_size, service_size); + goto beach; + } + descriptor = _new_descriptor (GST_MTS_DESC_DVB_SERVICE, 3 + provider_size + service_size); @@ -758,12 +790,17 @@ } case GST_MPEGTS_DVB_LINKAGE_EXTENDED_EVENT:{ GPtrArray *ext_events; + guint8 event_loop_length; ext_events = g_ptr_array_new_with_free_func ((GDestroyNotify) _gst_mpegts_dvb_linkage_extended_event_free); res->linkage_data = (gpointer) ext_events; - for (i = 0; i < *data++;) { + if (end - data < 1) + goto fail; + event_loop_length = *data++; + + for (i = 0; i < event_loop_length;) { GstMpegtsDVBLinkageExtendedEvent *ext_event; if (end - data < 3) @@ -909,23 +946,51 @@ descriptor, gchar ** language_code, gchar ** event_name, gchar ** text) { guint8 *data; + const guint8 *end; + guint8 event_name_length, text_length; g_return_val_if_fail (descriptor != NULL, FALSE); /* Need at least 5 bytes (3 for language code, 2 for each string length) */ __common_desc_checks (descriptor, GST_MTS_DESC_DVB_SHORT_EVENT, 5, FALSE); data = (guint8 *) descriptor->data + 2; + end = data + descriptor->length; + + if (language_code) + *language_code = NULL; + if (event_name) + *event_name = NULL; + if (text) + *text = NULL; if (language_code) *language_code = convert_lang_code (data); data += 3; + + event_name_length = *data++; + if (event_name_length > (guint) (end - data)) + goto fail; if (event_name) - *event_name = get_encoding_and_convert ((const gchar *) data + 1, *data); - data += *data + 1; + *event_name = + get_encoding_and_convert ((const gchar *) data, event_name_length); + data += event_name_length; + + if (end - data < 1) + return TRUE; + text_length = *data++; + if (text_length > (guint) (end - data)) + goto fail; if (text) - *text = get_encoding_and_convert ((const gchar *) data + 1, *data); + *text = get_encoding_and_convert ((const gchar *) data, text_length); return TRUE; + +fail: + if (language_code) + g_clear_pointer (language_code, g_free); + if (event_name) + g_clear_pointer (event_name, g_free); + return FALSE; } /* GST_MTS_DESC_DVB_TELETEXT (0x56) */ @@ -1091,6 +1156,11 @@ } /* GST_MTS_DESC_DVB_EXTENDED_EVENT (0x4E) */ +static GstMpegtsExtendedEventItem *_gst_mpegts_extended_event_item_copy + (GstMpegtsExtendedEventItem * source); +static void _gst_mpegts_extended_event_item_free (GstMpegtsExtendedEventItem * + item); + static GstMpegtsExtendedEventDescriptor * _gst_mpegts_extended_event_descriptor_copy (GstMpegtsExtendedEventDescriptor * source) @@ -1098,9 +1168,22 @@ GstMpegtsExtendedEventDescriptor *copy; copy = g_memdup2 (source, sizeof (GstMpegtsExtendedEventDescriptor)); - copy->items = g_ptr_array_ref (source->items); + copy->language_code = g_strdup (source->language_code); copy->text = g_strdup (source->text); + copy->items = NULL; + if (source->items) { + guint i; + + copy->items = g_ptr_array_new_full (source->items->len, + (GDestroyNotify) _gst_mpegts_extended_event_item_free); + for (i = 0; i < source->items->len; i++) { + g_ptr_array_add (copy->items, + _gst_mpegts_extended_event_item_copy (g_ptr_array_index + (source->items, i))); + } + } + return copy; } @@ -1156,7 +1239,8 @@ * descriptor, GstMpegtsExtendedEventDescriptor ** desc) { guint8 *data, *pdata; - guint8 tmp, len_item; + const guint8 *end; + guint8 tmp, len_item, text_length; GstMpegtsExtendedEventItem *item; GstMpegtsExtendedEventDescriptor *res; @@ -1167,6 +1251,7 @@ res = g_new0 (GstMpegtsExtendedEventDescriptor, 1); data = (guint8 *) descriptor->data + 2; + end = data + descriptor->length; tmp = *data; res->descriptor_number = tmp >> 4; @@ -1190,27 +1275,44 @@ pdata = data + len_item; while (data < pdata) { - item = g_new0 (GstMpegtsExtendedEventItem, 1); - item->item_description = - get_encoding_and_convert ((const gchar *) data + 1, *data); + guint8 description_length, item_length; - data += *data + 1; - - item->item = get_encoding_and_convert ((const gchar *) data + 1, *data); + item = g_new0 (GstMpegtsExtendedEventItem, 1); + g_ptr_array_add (res->items, item); - data += *data + 1; + description_length = *data++; + if (description_length > (guint) (pdata - data)) + goto fail; - g_ptr_array_add (res->items, item); - } - if (pdata != data) { - gst_mpegts_extended_event_descriptor_free (res); - return FALSE; + item->item_description = + get_encoding_and_convert ((const gchar *) data, description_length); + data += description_length; + + if (pdata - data < 1) + goto fail; + item_length = *data++; + if (item_length > (guint) (pdata - data)) + goto fail; + item->item = get_encoding_and_convert ((const gchar *) data, item_length); + data += item_length; } - res->text = get_encoding_and_convert ((const gchar *) data + 1, *data); + if (pdata != data) + goto fail; + + if (end - data < 1) + goto fail; + text_length = *data++; + if (text_length > (guint) (end - data)) + goto fail; + res->text = get_encoding_and_convert ((const gchar *) data, text_length); *desc = res; return TRUE; + +fail: + gst_mpegts_extended_event_descriptor_free (res); + return FALSE; } /* GST_MTS_DESC_DVB_COMPONENT (0x50) */ @@ -1386,7 +1488,7 @@ *content = g_ptr_array_new_with_free_func ((GDestroyNotify) _gst_mpegts_content_free); - for (i = 0; i < len;) { + for (i = 0; i + 1 < len; i += 2) { GstMpegtsContent *cont = g_new0 (GstMpegtsContent, 1); tmp = *data; cont->content_nibble_1 = (tmp & 0xf0) >> 4; @@ -1394,7 +1496,6 @@ data += 1; cont->user_byte = *data; data += 1; - i += 2; g_ptr_array_add (*content, cont); } @@ -1452,7 +1553,7 @@ *rating = g_ptr_array_new_with_free_func ((GDestroyNotify) _gst_mpegts_dvb_parental_rating_item_free); - for (i = 0; i < descriptor->length - 3; i += 4) { + for (i = 0; i + 4 <= (guint) descriptor->length; i += 4) { GstMpegtsDVBParentalRatingItem *item = g_new0 (GstMpegtsDVBParentalRatingItem, 1); g_ptr_array_add (*rating, item); @@ -1726,7 +1827,8 @@ gst_mpegts_descriptor_parse_dvb_multilingual_network_name (const GstMpegtsDescriptor * descriptor, GPtrArray ** network_name_items) { - guint8 *data, i, len; + guint8 *data, len; + const guint8 *end; GstMpegtsDvbMultilingualNetworkNameItem *item; g_return_val_if_fail (descriptor != NULL && network_name_items != NULL, @@ -1735,22 +1837,26 @@ 5, FALSE); data = (guint8 *) descriptor->data + 2; + end = data + descriptor->length; *network_name_items = g_ptr_array_new_with_free_func ((GDestroyNotify) _gst_mpegts_dvb_multilingual_network_name_item_free); - for (i = 0; i < descriptor->length - 3;) { + while (end - data >= 4) { item = g_new0 (GstMpegtsDvbMultilingualNetworkNameItem, 1); - g_ptr_array_add (*network_name_items, item); item->language_code = convert_lang_code (data); data += 3; - i += 3; - len = *data; - item->network_name = - get_encoding_and_convert ((const gchar *) data + 1, len); - data += len + 1; - i += len + 1; + len = *data++; + if (len > (guint) (end - data)) { + _gst_mpegts_dvb_multilingual_network_name_item_free (item); + g_clear_pointer (network_name_items, g_ptr_array_unref); + return FALSE; + } + item->network_name = get_encoding_and_convert ((const gchar *) data, len); + data += len; + + g_ptr_array_add (*network_name_items, item); } return TRUE; @@ -1798,7 +1904,8 @@ gst_mpegts_descriptor_parse_dvb_multilingual_bouquet_name (const GstMpegtsDescriptor * descriptor, GPtrArray ** bouquet_name_items) { - guint8 *data, i, len; + guint8 *data, len; + const guint8 *end; GstMpegtsDvbMultilingualBouquetNameItem *item; g_return_val_if_fail (descriptor != NULL && bouquet_name_items != NULL, @@ -1807,22 +1914,26 @@ 5, FALSE); data = (guint8 *) descriptor->data + 2; + end = data + descriptor->length; *bouquet_name_items = g_ptr_array_new_with_free_func ((GDestroyNotify) _gst_mpegts_dvb_multilingual_bouquet_name_item_free); - for (i = 0; i < descriptor->length - 3;) { + while (end - data >= 4) { item = g_new0 (GstMpegtsDvbMultilingualBouquetNameItem, 1); - g_ptr_array_add (*bouquet_name_items, item); item->language_code = convert_lang_code (data); data += 3; - i += 3; - len = *data; - item->bouquet_name = - get_encoding_and_convert ((const gchar *) data + 1, len); - data += len + 1; - i += len + 1; + len = *data++; + if (len > (guint) (end - data)) { + _gst_mpegts_dvb_multilingual_bouquet_name_item_free (item); + g_clear_pointer (bouquet_name_items, g_ptr_array_unref); + return FALSE; + } + item->bouquet_name = get_encoding_and_convert ((const gchar *) data, len); + data += len; + + g_ptr_array_add (*bouquet_name_items, item); } return TRUE; @@ -1872,7 +1983,8 @@ gst_mpegts_descriptor_parse_dvb_multilingual_service_name (const GstMpegtsDescriptor * descriptor, GPtrArray ** service_name_items) { - guint8 *data, i, len; + guint8 *data, len; + const guint8 *end; GstMpegtsDvbMultilingualServiceNameItem *item; g_return_val_if_fail (descriptor != NULL && service_name_items != NULL, @@ -1881,28 +1993,35 @@ 7, FALSE); data = (guint8 *) descriptor->data + 2; + end = data + descriptor->length; *service_name_items = g_ptr_array_new_with_free_func ((GDestroyNotify) _gst_mpegts_dvb_multilingual_service_name_item_free); - for (i = 0; i < descriptor->length - 3;) { + while (end - data >= 5) { item = g_new0 (GstMpegtsDvbMultilingualServiceNameItem, 1); - g_ptr_array_add (*service_name_items, item); item->language_code = convert_lang_code (data); data += 3; - i += 3; - - len = *data; - item->provider_name = - get_encoding_and_convert ((const gchar *) data + 1, len); - data += len + 1; - i += len + 1; - - len = *data; - item->service_name = - get_encoding_and_convert ((const gchar *) data + 1, len); - data += len + 1; - i += len + 1; + + len = *data++; + if (len > (guint) (end - data) || end - data - len < 1) { + _gst_mpegts_dvb_multilingual_service_name_item_free (item); + g_clear_pointer (service_name_items, g_ptr_array_unref); + return FALSE; + } + item->provider_name = get_encoding_and_convert ((const gchar *) data, len); + data += len; + + len = *data++; + if (len > (guint) (end - data)) { + _gst_mpegts_dvb_multilingual_service_name_item_free (item); + g_clear_pointer (service_name_items, g_ptr_array_unref); + return FALSE; + } + item->service_name = get_encoding_and_convert ((const gchar *) data, len); + data += len; + + g_ptr_array_add (*service_name_items, item); } return TRUE; @@ -1952,7 +2071,8 @@ GstMpegtsDescriptor * descriptor, guint8 * component_tag, GPtrArray ** component_description_items) { - guint8 *data, i, len; + guint8 *data, len; + const guint8 *end; GstMpegtsDvbMultilingualComponentItem *item; g_return_val_if_fail (descriptor != NULL @@ -1961,6 +2081,7 @@ FALSE); data = (guint8 *) descriptor->data + 2; + end = data + descriptor->length; *component_tag = *data; data += 1; @@ -1969,18 +2090,21 @@ g_ptr_array_new_with_free_func ((GDestroyNotify) _gst_mpegts_dvb_multilingual_component_item_free); - for (i = 0; i < descriptor->length - 3;) { + while (end - data >= 4) { item = g_new0 (GstMpegtsDvbMultilingualComponentItem, 1); - g_ptr_array_add (*component_description_items, item); item->language_code = convert_lang_code (data); data += 3; - i += 3; - len = *data; - item->description = - get_encoding_and_convert ((const gchar *) data + 1, len); - data += len + 1; - i += len + 1; + len = *data++; + if (len > (guint) (end - data)) { + _gst_mpegts_dvb_multilingual_component_item_free (item); + g_clear_pointer (component_description_items, g_ptr_array_unref); + return FALSE; + } + item->description = get_encoding_and_convert ((const gchar *) data, len); + data += len; + + g_ptr_array_add (*component_description_items, item); } return TRUE; @@ -2132,12 +2256,14 @@ * descriptor, GstMpegtsDataBroadcastDescriptor ** desc) { guint8 *data; + const guint8 *end; GstMpegtsDataBroadcastDescriptor *res; g_return_val_if_fail (descriptor != NULL && desc != NULL, FALSE); __common_desc_checks (descriptor, GST_MTS_DESC_DVB_DATA_BROADCAST, 8, FALSE); data = (guint8 *) descriptor->data + 2; + end = data + descriptor->length; res = g_new0 (GstMpegtsDataBroadcastDescriptor, 1); @@ -2150,17 +2276,30 @@ res->length = *data; data += 1; + if (res->length > (guint) (end - data)) + goto fail; + res->selector_bytes = g_memdup2 (data, res->length); data += res->length; + if (end - data < 4) + goto fail; + res->language_code = convert_lang_code (data); data += 3; + if (*data > (guint) (end - data - 1)) + goto fail; + res->text = get_encoding_and_convert ((const gchar *) data + 1, *data); *desc = res; return TRUE; + +fail: + gst_mpegts_dvb_data_broadcast_descriptor_free (res); + return FALSE; } /* GST_MTS_DESC_DVB_SCRAMBLING (0x65) */ @@ -2304,9 +2443,9 @@ * descriptor, GstMpegtsT2DeliverySystemDescriptor ** desc) { guint8 *data; - guint8 len, freq_len, sub_cell_len; + const guint8 *end; + guint8 freq_len, sub_cell_len; guint32 tmp_freq; - guint8 i; GstMpegtsT2DeliverySystemDescriptor *res; g_return_val_if_fail (descriptor != NULL && desc != NULL, FALSE); @@ -2314,8 +2453,11 @@ 4, FALSE); data = (guint8 *) descriptor->data + 3; + end = data + descriptor->length - 1; res = g_new0 (GstMpegtsT2DeliverySystemDescriptor, 1); + res->cells = g_ptr_array_new_with_free_func ((GDestroyNotify) + _gst_mpegts_t2_delivery_system_cell_free); res->plp_id = *data; data += 1; @@ -2323,7 +2465,7 @@ res->t2_system_id = GST_READ_UINT16_BE (data); data += 2; - if (descriptor->length > 4) { + if (descriptor->length >= 6) { // FIXME: siso / miso res->siso_miso = (*data >> 6) & 0x03; switch ((*data >> 2) & 0x0f) { @@ -2403,12 +2545,7 @@ res->tfs = (*data) & 0x01; data += 1; - len = descriptor->length - 6; - - res->cells = g_ptr_array_new_with_free_func ((GDestroyNotify) - _gst_mpegts_t2_delivery_system_cell_free); - - for (i = 0; i < len;) { + while (end - data >= 2) { GstMpegtsT2DeliverySystemCell *cell; guint8 j, k; @@ -2417,37 +2554,42 @@ cell->cell_id = GST_READ_UINT16_BE (data); data += 2; - i += 2; cell->centre_frequencies = g_array_new (FALSE, FALSE, sizeof (guint32)); if (res->tfs == TRUE) { - freq_len = *data; - data += 1; - i += 1; + if (end - data < 1) + goto fail; + freq_len = *data++; for (j = 0; j < freq_len;) { + if (end - data < 4) + goto fail; tmp_freq = GST_READ_UINT32_BE (data) * 10; g_array_append_val (cell->centre_frequencies, tmp_freq); data += 4; j += 4; - i += 4; } } else { + if (end - data < 4) + goto fail; tmp_freq = GST_READ_UINT32_BE (data) * 10; g_array_append_val (cell->centre_frequencies, tmp_freq); data += 4; - i += 4; } - sub_cell_len = (*data); - data += 1; - i += 1; + if (end - data < 1) + goto fail; + sub_cell_len = *data++; cell->sub_cells = g_ptr_array_new_with_free_func ((GDestroyNotify) _gst_mpegts_t2_delivery_system_cell_extension_free); for (k = 0; k < sub_cell_len;) { GstMpegtsT2DeliverySystemCellExtension *cell_ext; + + if (end - data < 5) + goto fail; + cell_ext = g_new0 (GstMpegtsT2DeliverySystemCellExtension, 1); g_ptr_array_add (cell->sub_cells, cell_ext); @@ -2456,7 +2598,6 @@ cell_ext->transposer_frequency = GST_READ_UINT32_BE (data) * 10; data += 4; - i += 5; k += 5; } } @@ -2464,6 +2605,10 @@ *desc = res; return TRUE; + +fail: + gst_mpegts_t2_delivery_system_descriptor_free (res); + return FALSE; } /** @@ -2484,16 +2629,19 @@ { guint8 *data; guint8 i, num_preselections, num_aux_components, future_extension_length; + const guint8 *end; GstMpegtsAudioPreselectionDescriptor *item; g_return_val_if_fail (descriptor != NULL && list != NULL, FALSE); - __common_desc_ext_check_base (descriptor, - GST_MTS_DESC_EXT_DVB_AUDIO_PRESELECTION, FALSE); + __common_desc_ext_checks (descriptor, GST_MTS_DESC_EXT_DVB_AUDIO_PRESELECTION, + 2, FALSE); *list = g_ptr_array_new_with_free_func ((GDestroyNotify) gst_mpegts_descriptor_parse_audio_preselection_free); data = (guint8 *) descriptor->data + 3; + end = data + descriptor->length - 1; + num_preselections = (guint8) ((*data & 0xF8) >> 3); data += 1; @@ -2501,6 +2649,9 @@ item = g_new0 (GstMpegtsAudioPreselectionDescriptor, 1); g_ptr_array_add (*list, item); + if (end - data < 2) + goto fail; + item->preselection_id = (*data & 0xF8) >> 3; item->audio_rendering_indication = *data & 0x7; data += 1; @@ -2516,33 +2667,45 @@ data += 1; if (item->language_code_present == 1) { + if (end - data < 3) + goto fail; item->language_code = convert_lang_code (data); data += 3; } if (item->text_label_present == 1) { + if (end - data < 1) + goto fail; item->message_id = *data; data += 1; } if (item->multi_stream_info_present == 1) { + if (end - data < 1) + goto fail; num_aux_components = (*data & 0xE0) >> 5; data += 1; - for (i = 0; i < num_aux_components; i++) { - data += 1; - } + if (num_aux_components > (guint) (end - data)) + goto fail; + data += num_aux_components; } if (item->future_extension == 1) { + if (end - data < 1) + goto fail; future_extension_length = *data & 0x1F; data += 1; - for (i = 0; i < future_extension_length; i++) { - data += 1; - } + if (future_extension_length > (guint) (end - data)) + goto fail; + data += future_extension_length; } } return TRUE; + +fail: + g_clear_pointer (list, g_ptr_array_unref); + return FALSE; } void gst_mpegts_descriptor_parse_audio_preselection_free
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/gst-libs/gst/mpegts/gst-dvb-section.c -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/gst-libs/gst/mpegts/gst-dvb-section.c
Changed
@@ -262,6 +262,12 @@ descriptors_loop_length = GST_READ_UINT16_BE (data) & 0x0FFF; data += 2; + if (end - 4 - data < descriptors_loop_length) { + GST_WARNING ("PID %d invalid EIT entry descriptors loop length %d", + section->pid, descriptors_loop_length); + goto error; + } + event->descriptors = gst_mpegts_parse_descriptors (data, descriptors_loop_length); if (event->descriptors == NULL) @@ -428,11 +434,11 @@ GST_DEBUG ("descriptors_loop_length %d", descriptors_loop_length); - if (descriptors_loop_length && (data + descriptors_loop_length > end - 4)) { + if (descriptors_loop_length > transport_stream_loop_length - 6) { GST_WARNING - ("PID %d invalid BAT entry %d descriptors loop length %d (only have %" - G_GSIZE_FORMAT ")", section->pid, section->subtable_extension, - descriptors_loop_length, (gsize) (end - 4 - data)); + ("PID %d invalid BAT entry %d descriptors loop length %d (remaining %d)", + section->pid, section->subtable_extension, descriptors_loop_length, + transport_stream_loop_length - 6); goto error; } stream->descriptors = @@ -608,11 +614,11 @@ GST_DEBUG ("descriptors_loop_length %d", descriptors_loop_length); - if (descriptors_loop_length && (data + descriptors_loop_length > end - 4)) { + if (descriptors_loop_length > transport_stream_loop_length - 6) { GST_WARNING - ("PID %d invalid NIT entry %d descriptors loop length %d (only have %" - G_GSIZE_FORMAT ")", section->pid, section->subtable_extension, - descriptors_loop_length, (gsize) (end - 4 - data)); + ("PID %d invalid NIT entry %d descriptors loop length %d (remaining %d)", + section->pid, section->subtable_extension, descriptors_loop_length, + transport_stream_loop_length - 6); goto error; } stream->descriptors = @@ -1215,11 +1221,14 @@ _parse_tot (GstMpegtsSection * section) { guint8 *data; + const guint8 *end; GstMpegtsTOT *tot; guint16 desc_len; GST_DEBUG ("TOT"); + end = section->data + section->section_length; + tot = g_new0 (GstMpegtsTOT, 1); tot->utc_time = _parse_utc_time (section->data + 3); @@ -1229,6 +1238,14 @@ desc_len = GST_READ_UINT16_BE (data) & 0xFFF; data += 2; + + if (end - 4 - data < desc_len) { + GST_WARNING ("PID %d invalid TOT descriptors loop length %d", + section->pid, desc_len); + _gst_mpegts_tot_free (tot); + return NULL; + } + tot->descriptors = gst_mpegts_parse_descriptors (data, desc_len); return (gpointer) tot; @@ -1328,6 +1345,13 @@ descriptors_loop_length = GST_READ_UINT16_BE (data) & 0x0fff; data += 2; + + if (end - 4 - data < descriptors_loop_length) { + GST_WARNING ("PID %d invalid SIT descriptors loop length %d", + section->pid, descriptors_loop_length); + goto error; + } + sit->descriptors = gst_mpegts_parse_descriptors (data, descriptors_loop_length); if (sit->descriptors == NULL)
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/gst-libs/gst/mpegts/gst-dvb-section.h -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/gst-libs/gst/mpegts/gst-dvb-section.h
Changed
@@ -249,7 +249,7 @@ typedef struct _GstMpegtsBAT GstMpegtsBAT; #define GST_TYPE_MPEGTS_BAT (gst_mpegts_bat_get_type()) -#define GST_TYPE_MPEGTS_BAT_STREAM (gst_mpegts_bat_get_type()) +#define GST_TYPE_MPEGTS_BAT_STREAM (gst_mpegts_bat_stream_get_type()) struct _GstMpegtsBATStream {
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/gst-libs/gst/mpegts/gst-scte-section.c -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/gst-libs/gst/mpegts/gst-scte-section.c
Changed
@@ -134,13 +134,13 @@ GstMpegtsSCTESpliceEvent *event = g_new0 (GstMpegtsSCTESpliceEvent, 1); guint8 *data = *orig_data; + event->components = g_ptr_array_new_with_free_func ((GDestroyNotify) + _gst_mpegts_scte_splice_component_free); + /* Note : +6 is because of the final descriptor_loop_length and CRC */ if (data + 5 + 6 > end) goto error; - event->components = g_ptr_array_new_with_free_func ((GDestroyNotify) - _gst_mpegts_scte_splice_component_free); - event->insert_event = insert_event; event->splice_event_id = GST_READ_UINT32_BE (data); GST_LOG ("splice_event_id: 0x%08x", event->splice_event_id); @@ -153,7 +153,7 @@ GST_DEBUG ("data %p", data); if (event->splice_event_cancel_indicator == 0) { - if (data + 5 + 6 > end) + if (data + 1 + 6 > end) goto error; event->out_of_network_indicator = *data >> 7; event->program_splice_flag = (*data >> 6) & 0x01; @@ -186,8 +186,12 @@ } } else { if (insert_event && event->splice_immediate_flag == 0) { + if (data + 1 + 6 > end) + goto error; event->program_splice_time_specified = *data >> 7; if (event->program_splice_time_specified) { + if (data + 5 + 6 > end) + goto error; event->program_splice_time = ((guint64) (*data & 0x01)) << 32; data += 1; event->program_splice_time += GST_READ_UINT32_BE (data); @@ -198,6 +202,8 @@ } else data += 1; } else if (!insert_event) { + if (data + 4 + 6 > end) + goto error; event->utc_splice_time = GST_READ_UINT32_BE (data); GST_LOG ("utc_splice_time %u", event->utc_splice_time); data += 4; @@ -205,6 +211,8 @@ } if (event->duration_flag) { + if (data + 5 + 6 > end) + goto error; event->break_duration_auto_return = *data >> 7; event->break_duration = ((guint64) (*data & 0x01)) << 32; data += 1; @@ -217,6 +225,8 @@ GST_TIME_ARGS (MPEGTIME_TO_GSTTIME (event->break_duration))); } + if (data + 4 + 6 > end) + goto error; event->unique_program_id = GST_READ_UINT16_BE (data); GST_LOG ("unique_program_id:%" G_GUINT16_FORMAT, event->unique_program_id); data += 2; @@ -342,8 +352,12 @@ break; case GST_MTS_SCTE_SPLICE_COMMAND_TIME: { + if (end - data < 1) + goto error; sit->splice_time_specified = (*data >> 7); if (sit->splice_time_specified) { + if (end - data < 5) + goto error; sit->splice_time = ((guint64) (*data & 0x01)) << 32; data += 1; sit->splice_time += GST_READ_UINT32_BE (data); @@ -355,7 +369,11 @@ case GST_MTS_SCTE_SPLICE_COMMAND_SCHEDULE: { guint i; - guint splice_count = *data; + guint splice_count; + + if (end - data < 1) + goto error; + splice_count = *data; data += 1; for (i = 0; i < splice_count; i++) { @@ -388,8 +406,18 @@ } /* descriptors */ - tmp = GST_READ_UINT16_BE (data); + if (end - data < 2) { + GST_WARNING ("PID %d SCTE SIT too short for descriptor loop length", + section->pid); + goto error; + } + tmp = GST_READ_UINT16_BE (data) & 0xFFF; data += 2; + if ((gssize) tmp > end - 4 - data) { + GST_WARNING ("PID %d invalid SCTE SIT descriptors loop length %d", + section->pid, tmp); + goto error; + } GST_MEMDUMP ("desc ?", data, tmp); sit->descriptors = gst_mpegts_parse_descriptors (data, tmp); if (!sit->descriptors) { @@ -678,6 +706,10 @@ length = 20; command_length = 0; + if (sit->splice_command_type == GST_MTS_SCTE_SPLICE_COMMAND_SCHEDULE) { + /* splice_count */ + command_length += 1; + } /* Add the size of splices */ for (i = 0; i < sit->splices->len; i++) { GstMpegtsSCTESpliceEvent *event = g_ptr_array_index (sit->splices, i); @@ -782,6 +814,10 @@ } } + /* splice_count : 8 bit */ + if (sit->splice_command_type == GST_MTS_SCTE_SPLICE_COMMAND_SCHEDULE) + *data++ = sit->splices->len & 0xff; + /* Write the events */ for (i = 0; i < sit->splices->len; i++) { GstMpegtsSCTESpliceEvent *event = g_ptr_array_index (sit->splices, i);
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/gst-libs/gst/mpegts/gstmpegtsdescriptor.c -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/gst-libs/gst/mpegts/gstmpegtsdescriptor.c
Changed
@@ -145,13 +145,15 @@ /* * @text: The text you want to get the encoding from + * @length: The length of @text in bytes * @start_text: Location where the beginning of the actual text is stored * @is_multibyte: Location where information whether it's a multibyte encoding * or not is stored * @returns: GIconv for conversion or NULL */ static LocalIconvCode -get_encoding (const gchar * text, guint * start_text, gboolean * is_multibyte) +get_encoding (const gchar * text, guint length, guint * start_text, + gboolean * is_multibyte) { LocalIconvCode encoding; guint8 firstbyte; @@ -184,6 +186,11 @@ { guint16 table; + if (length < 3) { + encoding = _ICONV_UNKNOWN; + break; + } + table = GST_READ_UINT16_BE (text + 1); if (table < 17) @@ -380,8 +387,37 @@ *out_size += 1; g_free (out_text); return out_buffer; - case _ICONV_UCS_2BE: case _ICONV_EUC_KR: + { + /* LF arrives as a single byte from iconv() but must be escaped + * as the control code 0xE0 0x8A (EN 300 468, annex A, table + * A.2). EUC-KR is not fixed width (KS X 1001 double bytes are + * both >= 0xA1), so unlike UCS-2/UTF-16 the escape can grow + * the text. */ + gsize i, escapes = 0; + guint8 *d; + + for (i = 0; i < *out_size; i++) { + if (out_texti == 0x0A) + escapes++; + } + + out_buffer = g_malloc (*out_size + escapes + 1); + out_buffer0 = encoding - _ICONV_UCS_2BE + 0x11; + d = out_buffer + 1; + for (i = 0; i < *out_size; i++) { + if (out_texti == 0x0A) { + *d++ = 0xE0; + *d++ = 0x8A; + } else { + *d++ = (guint8) out_texti; + } + } + *out_size += escapes + 1; + g_free (out_text); + return out_buffer; + } + case _ICONV_UCS_2BE: case _ICONV_UTF_16BE: /* These character sets requires 1 selection byte */ _encode_control_codes (out_text, *out_size, TRUE); @@ -456,7 +492,7 @@ text += 2; } } else { - for (i = 0; i < length; i += 2) { + for (i = 0; i + 1 < length; i += 2) { guint16 code = GST_READ_UINT16_BE (text); switch (code) { @@ -555,7 +591,7 @@ if (text == NULL || length == 0) return g_strdup (""); - encoding = get_encoding (text, &start_text, &is_multibyte); + encoding = get_encoding (text, length, &start_text, &is_multibyte); if (encoding > _ICONV_UNKNOWN && encoding < _ICONV_MAX) { GST_DEBUG ("Encoding %s", iconvtablenameencoding); @@ -580,7 +616,8 @@ giconv = _get_iconv (_ICONV_ISO8859_1, _ICONV_UTF8); GST_INFO ("Trying encoding ISO 8859-1"); - converted_str = convert_to_utf8 (text, length, 1, giconv, FALSE, &error); + converted_str = convert_to_utf8 (text, length - 1, 1, giconv, FALSE, + &error); if (error != NULL) { GST_WARNING ("Could not convert string while assuming encoding ISO 8859-1: %s", @@ -765,10 +802,15 @@ GST_MEMDUMP ("Full descriptor array", buffer, buf_len); while (data - buffer < buf_len) { + if (buf_len - (gsize) (data - buffer) < 2) { + GST_WARNING ("Not enough data for a descriptor header: %" G_GSIZE_FORMAT + " of %" G_GSIZE_FORMAT, (gsize) (data - buffer), buf_len); + return NULL; + } data++; /* skip tag */ length = *data++; - if (data - buffer > buf_len) { + if (length > buf_len - (gsize) (data - buffer)) { GST_WARNING ("invalid descriptor length %d now at %d max %" G_GSIZE_FORMAT, length, (gint) (data - buffer), buf_len); return NULL; @@ -805,8 +847,13 @@ GST_MEMDUMP ("descriptor", desc->data + 2, desc->length); /* extended descriptors */ if (G_UNLIKELY (desc->tag == GST_MTS_DESC_DVB_EXTENSION - || desc->tag == GST_MTS_DESC_EXTENSION)) - desc->tag_extension = *data; + || desc->tag == GST_MTS_DESC_EXTENSION)) { + if (G_UNLIKELY (desc->length < 1)) { + GST_WARNING ("Extended descriptor 0x%02x has no payload", desc->tag); + } else { + desc->tag_extension = *data; + } + } data += desc->length; @@ -902,6 +949,12 @@ g_return_val_if_fail (format_identifier != NULL, NULL); g_return_val_if_fail (additional_info_length > 0 || !additional_info, NULL); + if (G_UNLIKELY (additional_info_length > G_MAXUINT8 - 4)) { + GST_WARNING ("Additional info too big (%" G_GSIZE_FORMAT " > 251)", + additional_info_length); + return NULL; + } + descriptor = _new_descriptor (GST_MTS_DESC_REGISTRATION, 4 + additional_info_length); @@ -1228,6 +1281,11 @@ g_return_val_if_fail (length > 0 || !data, NULL); + if (G_UNLIKELY (length > G_MAXUINT8)) { + GST_WARNING ("Descriptor data too big (%" G_GSIZE_FORMAT " > 255)", length); + return NULL; + } + descriptor = _new_descriptor (tag, length); if (data && (length > 0)) @@ -1245,7 +1303,8 @@ * * Creates a #GstMpegtsDescriptor with custom @tag, @tag_extension and @data * - * Returns: (transfer full): #GstMpegtsDescriptor + * Returns: (transfer full) (nullable): #GstMpegtsDescriptor, or %NULL if input + * is invalid * * Since: 1.20 */ @@ -1255,6 +1314,11 @@ { GstMpegtsDescriptor *descriptor; + if (G_UNLIKELY (length > G_MAXUINT8 - 1)) { + GST_WARNING ("Descriptor data too big (%" G_GSIZE_FORMAT " > 254)", length); + return NULL; + } + descriptor = _new_descriptor_with_extension (tag, tag_extension, length); if (data && (length > 0)) @@ -1342,6 +1406,7 @@ GstMpegtsMetadataDescriptor ** desc) { guint8 *data; + const guint8 *end; guint8 flag; GstMpegtsMetadataDescriptor *res; @@ -1349,6 +1414,7 @@ __common_desc_checks (descriptor, GST_MTS_DESC_METADATA, 5, FALSE); data = (guint8 *) descriptor->data + 2; + end = data + descriptor->length; res = g_new0 (GstMpegtsMetadataDescriptor, 1); @@ -1356,15 +1422,23 @@ data += 2; if (res->metadata_application_format == GST_MPEGTS_METADATA_APPLICATION_FORMAT_IDENTIFIER_FIELD) { + if (end - data < 4) + goto fail; // skip over metadata_application_format_identifier if it is provided data += 4; } + if (end - data < 1) + goto fail; res->metadata_format = *data; data += 1; if (res->metadata_format == GST_MPEGTS_METADATA_FORMAT_IDENTIFIER_FIELD) { + if (end - data < 4) + goto fail; res->metadata_format_identifier = GST_READ_UINT32_BE (data); data += 4; } + if (end - data < 2) + goto fail; res->metadata_service_id = *data; data += 1; flag = *data; @@ -1376,6 +1450,10 @@ *desc = res; return TRUE; + +fail: + g_free (res); + return FALSE; } /** @@ -1659,6 +1737,8 @@ guint8 *desc_data; GstMpegtsDescriptor *descriptor; + g_return_val_if_fail (jpegxs != NULL, NULL); + gst_byte_writer_init_with_size (&writer, desc_size, FALSE); /* descriptor version: 0 */
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/gst-libs/gst/mpegts/gstmpegtssection.c -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/gst-libs/gst/mpegts/gstmpegtssection.c
Changed
@@ -1233,11 +1233,11 @@ /* section_length (already parsed) : 12 bit */ res->section_length = section_length + 3; if (!res->short_section) { - /* A long packet needs to be at least 11 bytes long + /* A long packet needs to be at least 12 bytes long * _ 3 for the bytes above * _ 5 for the bytes below * _ 4 for the CRC */ - if (G_UNLIKELY (data_size < 11)) + if (G_UNLIKELY (data_size < 12) || G_UNLIKELY (res->section_length < 12)) goto bad_long_packet; /* CRC is after section_length (-4 for the size of the CRC) */ @@ -1272,7 +1272,7 @@ bad_long_packet: { GST_WARNING ("PID 0x%04x long section is too short (%" G_GSIZE_FORMAT - " bytes, need at least 11)", pid, data_size); + " bytes, need at least 12)", pid, data_size); gst_mpegts_section_unref (res); return NULL; }
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/gst-libs/gst/vulkan/gstvkdecoder-private.c -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/gst-libs/gst/vulkan/gstvkdecoder-private.c
Changed
@@ -493,6 +493,31 @@ return ret; } +static gboolean +dpb_caps_is_equal (const GstCaps * a, const GstCaps * b) +{ + const GstStructure *sa, *sb; + const gchar *afmt, *bfmt; + gint aw, ah, bw, bh; + + if (gst_caps_get_size (a) != 1 || gst_caps_get_size (b) != 1) + return FALSE; + + sa = gst_caps_get_structure (a, 0); + sb = gst_caps_get_structure (b, 0); + + if (!gst_structure_get_int (sa, "width", &aw) + || !gst_structure_get_int (sa, "height", &ah) + || !gst_structure_get_int (sb, "width", &bw) + || !gst_structure_get_int (sb, "height", &bh)) + return FALSE; + + afmt = gst_structure_get_string (sa, "format"); + bfmt = gst_structure_get_string (sb, "format"); + + return aw == bw && ah == bh && g_strcmp0 (afmt, bfmt) == 0; +} + /** * gst_vulkan_decoder_create_dpb_pool: * @self: a #GstVulkanDecoder @@ -517,8 +542,10 @@ priv = gst_vulkan_decoder_get_instance_private (self); - if (!priv->started) + if (!priv->started) { + GST_ERROR_OBJECT (self, "Decoder not started"); return FALSE; + } if (!self->dedicated_dpb) return TRUE; @@ -536,7 +563,7 @@ config = gst_buffer_pool_get_config (priv->dpb_pool); gst_buffer_pool_config_get_params (config, &old_caps, NULL, NULL, NULL); - keep_pool = gst_caps_is_strictly_equal (caps, old_caps); + keep_pool = old_caps != NULL && dpb_caps_is_equal (caps, old_caps); gst_structure_free (config); if (keep_pool) { @@ -564,16 +591,25 @@ gst_vulkan_image_buffer_pool_config_set_decode_caps (config, priv->profile_caps); - if (!gst_buffer_pool_set_config (priv->dpb_pool, config)) + if (!gst_buffer_pool_set_config (priv->dpb_pool, config)) { + GST_ERROR_OBJECT (self, "Failed to set config on DPB pool"); goto bail; - if (!gst_buffer_pool_set_active (priv->dpb_pool, TRUE)) + } + if (!gst_buffer_pool_set_active (priv->dpb_pool, TRUE)) { + GST_ERROR_OBJECT (self, "Failed to activate DPB pool"); goto bail; + } if (self->layered_dpb) { + gst_clear_buffer (&self->layered_buffer); + ret = gst_buffer_pool_acquire_buffer (priv->dpb_pool, &self->layered_buffer, NULL); - if (ret != GST_FLOW_OK) + if (ret != GST_FLOW_OK) { + GST_ERROR_OBJECT (self, "Failed to acquire layered DPB buffer (%s)", + gst_flow_get_name (ret)); goto bail; + } } return TRUE;
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/gst-libs/gst/vulkan/ios/gstvkwindow_ios.m -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/gst-libs/gst/vulkan/ios/gstvkwindow_ios.m
Changed
@@ -253,13 +253,27 @@ { GstVulkanWindowIos *window_ios = GST_VULKAN_WINDOW_IOS (window); GstVulkanWindowIosPrivate *priv = GET_PRIV (window_ios); - GstVulkanUIView *view = (__bridge GstVulkanUIView *) priv->internal_view; - view setGstWindow:NULL; - CFBridgingRelease (priv->internal_view); - priv->internal_view = NULL; - CFBridgingRelease (priv->internal_layer); - priv->internal_layer = NULL; + if (priv->internal_view) { + GstVulkanUIView *view = (__bridge GstVulkanUIView *) priv->internal_view; + /* UIKit teardown must run on the main thread. The block retains the view + * until removal, and its weak window reference makes callbacks safe. */ + if (NSThread isMainThread) { + view setGstWindow:NULL; + view removeFromSuperview; + } else { + dispatch_async (dispatch_get_main_queue (), ^{ + view setGstWindow:NULL; + view removeFromSuperview; + }); + } + CFBridgingRelease (priv->internal_view); + priv->internal_view = NULL; + } + if (priv->internal_layer) { + CFBridgingRelease (priv->internal_layer); + priv->internal_layer = NULL; + } GST_VULKAN_WINDOW_CLASS (parent_class)->close (window); } @@ -283,7 +297,7 @@ } @implementation GstVulkanUIView { - GstVulkanWindowIos * window_ios; + GWeakRef window_ios; guint width; guint height; @@ -294,9 +308,22 @@ return CAMetalLayer class; } +-(instancetype) initWithFrame:(CGRect) frame +{ + self = super initWithFrame:frame; + if (self) + g_weak_ref_init (&window_ios, NULL); + return self; +} + +-(void) dealloc +{ + g_weak_ref_clear (&window_ios); +} + -(void) setGstWindow:(GstVulkanWindowIos *) window { - window_ios = window; + g_weak_ref_set (&window_ios, window); } -(void) didMoveToWindow @@ -337,9 +364,12 @@ self->width = pixel_width; self->height = pixel_height; - if (resize && self->window_ios) { - gst_vulkan_window_resize (GST_VULKAN_WINDOW (self->window_ios), - pixel_width, pixel_height); + if (resize) { + GstVulkanWindow *window = g_weak_ref_get (&window_ios); + if (window) { + gst_vulkan_window_resize (window, pixel_width, pixel_height); + gst_object_unref (window); + } } }
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/gst-libs/gst/wayland/gstwldisplay.c -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/gst-libs/gst/wayland/gstwldisplay.c
Changed
@@ -78,6 +78,7 @@ gboolean own_display; GThread *thread; GstPoll *wl_fd_poll; + GHashTable *pending_outputs; GRecMutex sync_mutex; @@ -124,6 +125,8 @@ g_mutex_init (&priv->outputs_mutex); priv->outputs = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_object_unref); + priv->pending_outputs = g_hash_table_new_full (NULL, NULL, NULL, + (GDestroyNotify) g_object_unref); gst_wl_linux_dmabuf_init_once (); gst_wl_shm_init_once (); @@ -175,6 +178,7 @@ g_mutex_clear (&priv->outputs_mutex); g_hash_table_unref (priv->outputs); + g_hash_table_unref (priv->pending_outputs); if (priv->color) wp_color_manager_v1_destroy (priv->color); @@ -429,9 +433,10 @@ static void output_done (void *data, struct wl_output *wl_output) { - GstWlOutput *output = GST_WL_OUTPUT (data); - GstWlDisplay *self = g_object_steal_data (G_OBJECT (output), "display"); + GstWlOutput *shared_output = GST_WL_OUTPUT (data); + GstWlDisplay *self = g_object_get_data (G_OBJECT (shared_output), "display"); GstWlDisplayPrivate *priv = gst_wl_display_get_instance_private (self); + GstWlOutput *output = gst_wl_output_clone (shared_output); const gchar *name = gst_wl_output_get_name (output); GST_INFO ("Adding output %s (%p):", name, wl_output); @@ -582,6 +587,7 @@ GstWlOutput *output = gst_wl_output_new (wl_output, id); g_object_set_data (G_OBJECT (output), "display", self); wl_output_add_listener (wl_output, &output_listener, output); + g_hash_table_replace (priv->pending_outputs, GINT_TO_POINTER (id), output); } } @@ -596,13 +602,15 @@ GHashTableIter iter; gpointer key, value; - g_hash_table_iter_init (&iter, priv->outputs); - while (g_hash_table_iter_next (&iter, &key, &value)) { - GstWlOutput *output = value; + if (g_hash_table_remove (priv->pending_outputs, GINT_TO_POINTER (name))) { + g_hash_table_iter_init (&iter, priv->outputs); + while (g_hash_table_iter_next (&iter, &key, &value)) { + GstWlOutput *output = value; - if (gst_wl_output_get_id (output) == name) { - g_hash_table_iter_remove (&iter); - break; + if (gst_wl_output_get_id (output) == name) { + g_hash_table_iter_remove (&iter); + break; + } } }
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/gst-libs/gst/wayland/gstwloutput-private.h -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/gst-libs/gst/wayland/gstwloutput-private.h
Changed
@@ -27,6 +27,8 @@ /* <private> */ GstWlOutput *gst_wl_output_new (struct wl_output *output, guint32 id); +GstWlOutput *gst_wl_output_clone (GstWlOutput * self); + void gst_wl_output_set_name (GstWlOutput * self, const gchar *name); void gst_wl_output_set_description (GstWlOutput * self, const gchar *description);
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/gst-libs/gst/wayland/gstwloutput.c -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/gst-libs/gst/wayland/gstwloutput.c
Changed
@@ -29,6 +29,7 @@ { GObject parent; + GstWlOutput *shared; struct wl_output *output; guint32 global_id; @@ -69,7 +70,10 @@ g_free (self->geometry.make); g_free (self->geometry.model); - wl_output_destroy (self->output); + if (self->shared) + g_object_unref (self->shared); + if (self->output) + wl_output_destroy (self->output); G_OBJECT_CLASS (gst_wl_output_parent_class)->finalize (object); } @@ -105,6 +109,28 @@ return self; } +GstWlOutput * +gst_wl_output_clone (GstWlOutput * self) +{ + GstWlOutput *clone = GST_WL_OUTPUT (g_object_new (GST_TYPE_WL_OUTPUT, NULL)); + + clone->shared = g_object_ref_sink (self); + clone->global_id = self->global_id; + + clone->name = g_strdup (self->name); + clone->description = g_strdup (self->description); + + clone->scale_factor = self->scale_factor; + + clone->geometry = self->geometry; + clone->geometry.make = g_strdup (self->geometry.make); + clone->geometry.model = g_strdup (self->geometry.model); + + clone->mode = self->mode; + + return clone; +} + /** * gst_wl_output_set_name: (skip): * @self: the #GstWlOutput @@ -222,7 +248,10 @@ struct wl_output * gst_wl_output_get_wl_output (GstWlOutput * self) { - return self->output; + if (self->shared) + return self->shared->output; + else + return self->output; } /** @@ -236,7 +265,7 @@ guint32 gst_wl_output_get_id (GstWlOutput * self) { - return wl_proxy_get_id ((struct wl_proxy *) self->output); + return self->global_id; } /**
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/gst-plugins-bad.doap -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/gst-plugins-bad.doap
Changed
@@ -35,6 +35,16 @@ <release> <Version> + <revision>1.28.9</revision> + <branch>1.28</branch> + <name></name> + <created>2026-11-06</created> + <file-release rdf:resource="https://gstreamer.freedesktop.org/src/gst-plugins-bad/gst-plugins-bad-1.28.9.tar.xz" /> + </Version> + </release> + + <release> + <Version> <revision>1.28.8</revision> <branch>1.28</branch> <name></name>
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/gst/asfmux/gstasfmux.c -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/gst/asfmux/gstasfmux.c
Changed
@@ -387,6 +387,20 @@ return ret; } +/* Returns the number of bytes gst_asf_mux_write_string_with_size() will + * write for @text: its UTF-16LE length plus a 2-byte NUL terminator. */ +static guint +gst_asf_mux_utf16_size (const gchar * text) +{ + gsize utf16_len = 0; + gchar *utf16; + + utf16 = g_convert (text, -1, "UTF-16LE", "UTF-8", NULL, &utf16_len, NULL); + g_free (utf16); + + return utf16_len + 2; +} + /** * content_description_calc_size_for_tag: * @taglist: the #GstTagList that contains the tag @@ -423,10 +437,9 @@ const gchar *text; text = g_value_get_string (&value); - /* +1 -> because of the \0 at the end - * 2* -> because we have uft8, and asf demands utf16 - */ - content_size = 2 * (1 + g_utf8_strlen (text, -1)); + /* UTF-16LE size including the NUL terminator; characters outside + * the BMP take 4 bytes in UTF-16, not 2 */ + content_size = gst_asf_mux_utf16_size (text); if (gst_asf_tag_present_in_content_description (tag)) { asftags->cont_desc_size += content_size; @@ -533,10 +546,9 @@ const gchar *text; text = g_value_get_string (&value); - /* +1 -> because of the \0 at the end - * 2* -> because we have uft8, and asf demands utf16 - */ - content_size = 2 * (1 + g_utf8_strlen (text, -1)); + /* UTF-16LE size including the NUL terminator; characters outside + * the BMP take 4 bytes in UTF-16, not 2 */ + content_size = gst_asf_mux_utf16_size (text); } break; case ASF_TAG_TYPE_DWORD:
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/gst/asfmux/gstasfobjects.c -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/gst/asfmux/gstasfobjects.c
Changed
@@ -528,7 +528,7 @@ { guint8 stream_num = 0; if (!gst_byte_reader_get_uint8 (reader, &stream_num)) - return GST_FLOW_ERROR; + return FALSE; *has_keyframe = (stream_num & 0x80) != 0; /* we do not skip the rest of the payload bytes as @@ -740,13 +740,13 @@ return FALSE; if (!gst_byte_reader_get_uint32_le (reader, &flags)) - return GST_FLOW_ERROR; + return FALSE; asfinfo->broadcast = (flags & 0x1) == 1; GST_DEBUG ("ASF: broadcast flag: %s", asfinfo->broadcast ? "true" : "false"); if (!gst_byte_reader_get_uint32_le (reader, &min_ps)) - return GST_FLOW_ERROR; + return FALSE; if (!gst_byte_reader_get_uint32_le (reader, &max_ps)) - return GST_FLOW_ERROR; + return FALSE; if (min_ps != max_ps) { GST_WARNING ("Minimum and maximum packet size differ " @@ -755,6 +755,12 @@ return FALSE; } + if (min_ps < ASF_MIN_PACKET_SIZE) { + GST_WARNING ("ASF: Packet size %u is smaller than the smallest " + "packet that can carry any data", min_ps); + return FALSE; + } + GST_DEBUG ("ASF: Packet size: %" G_GUINT32_FORMAT, min_ps); asfinfo->packet_size = min_ps; if (!gst_byte_reader_skip (reader, 4)) @@ -815,6 +821,11 @@ goto error; if (!gst_byte_reader_get_uint64_le (&reader, &obj_size)) goto error; + if (obj_size < ASF_GUID_OBJSIZE_SIZE) { + GST_WARNING ("ASF: Child object size %" G_GUINT64_FORMAT + " is smaller than the object header", obj_size); + goto error; + } if (gst_asf_match_guid (guid, &guidsASF_FILE_PROPERTIES_OBJECT_INDEX)) { ret = gst_asf_parse_file_properties_obj (&reader, file_info);
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/gst/asfmux/gstasfobjects.h -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/gst/asfmux/gstasfobjects.h
Changed
@@ -154,6 +154,15 @@ #define ASF_DATA_OBJECT_SIZE 50 #define ASF_SINGLE_PAYLOAD_HEADER_SIZE 15 #define ASF_MULTIPLE_PAYLOAD_HEADER_SIZE 17 +/* Payload parsing info header of a data packet with all its variable size + * fields set to none: two flag bytes, presentation time and duration */ +#define ASF_PAYLOAD_PARSING_INFO_MIN_SIZE 8 +/* Smallest ASF data packet that can carry any payload data: single payload + * packets have an implicit payload size and their header is the most + * compact. Smaller packets would need non-standard payload parsing info + * field sizes, which we do not support anyway */ +#define ASF_MIN_PACKET_SIZE (ASF_PAYLOAD_PARSING_INFO_MIN_SIZE + \ + ASF_SINGLE_PAYLOAD_HEADER_SIZE + 1) #define ASF_EXTENDED_STREAM_PROPERTIES_OBJECT_SIZE 88 #define ASF_CONTENT_DESCRIPTION_OBJECT_SIZE 34 #define ASF_EXT_CONTENT_DESCRIPTION_OBJECT_SIZE 26
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/gst/asfmux/gstasfparse.c -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/gst/asfmux/gstasfparse.c
Changed
@@ -170,6 +170,14 @@ goto end; } + if (size > G_MAXUINT32) { + GST_ERROR_OBJECT (asfparse, "Object size %" G_GUINT64_FORMAT + " is larger than the largest supported object", size); + ret = GST_FLOW_ERROR; + gst_buffer_unmap (buffer, &map); + goto end; + } + if (size > map.size) { /* request all the obj data */ gst_base_parse_set_min_frame_size (GST_BASE_PARSE_CAST (asfparse), size); @@ -213,6 +221,14 @@ goto end; } + if (size > G_MAXUINT32) { + GST_ERROR_OBJECT (asfparse, "Object size %" G_GUINT64_FORMAT + " is larger than the largest supported object", size); + ret = GST_FLOW_ERROR; + gst_buffer_unmap (buffer, &map); + goto end; + } + if (size > map.size) { /* request all the obj data */ gst_base_parse_set_min_frame_size (GST_BASE_PARSE_CAST (asfparse), size); @@ -278,17 +294,22 @@ } if (gst_asf_parse_parse_data_object (asfparse, map.data, - map.size) == GST_FLOW_OK) { - GST_DEBUG_OBJECT (asfparse, "Successfully parsed data object"); - asfparse->parse_state = ASF_PARSING_PACKETS; + map.size) != GST_FLOW_OK) { + GST_ERROR_OBJECT (asfparse, "Failed to parse data object"); gst_buffer_unmap (buffer, &map); + ret = GST_FLOW_ERROR; + goto end; + } - gst_base_parse_set_min_frame_size (GST_BASE_PARSE_CAST (asfparse), - asfparse->asfinfo->packet_size); + GST_DEBUG_OBJECT (asfparse, "Successfully parsed data object"); + asfparse->parse_state = ASF_PARSING_PACKETS; + gst_buffer_unmap (buffer, &map); - gst_base_parse_finish_frame (GST_BASE_PARSE_CAST (asfparse), frame, - ASF_DATA_OBJECT_SIZE); - } + gst_base_parse_set_min_frame_size (GST_BASE_PARSE_CAST (asfparse), + asfparse->asfinfo->packet_size); + + gst_base_parse_finish_frame (GST_BASE_PARSE_CAST (asfparse), frame, + ASF_DATA_OBJECT_SIZE); } else { gst_buffer_unmap (buffer, &map); *skipsize = 0;
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/gst/asfmux/gstrtpasfpay.c -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/gst/asfmux/gstrtpasfpay.c
Changed
@@ -174,10 +174,27 @@ gst_asf_parse_packet (buffer, &info, FALSE, 0); } - if (packetinfo->padding != 0) + if (packetinfo->padding != 0) { + if (packetinfo->padding >= rtpasfpay->asfinfo.packet_size) { + GST_ERROR_OBJECT (rtpasfpay, "Padding size %" G_GUINT32_FORMAT + " is not smaller than the packet size %" G_GUINT32_FORMAT, + packetinfo->padding, rtpasfpay->asfinfo.packet_size); + gst_buffer_unref (buffer); + return GST_FLOW_ERROR; + } packet_util_size = rtpasfpay->asfinfo.packet_size - packetinfo->padding; - else + } else { packet_util_size = packetinfo->packet_size; + } + + if (packet_util_size > gst_buffer_get_size (buffer)) { + GST_ERROR_OBJECT (rtpasfpay, "Packet payload size %" G_GUINT32_FORMAT + " is larger than the buffer size %" G_GSIZE_FORMAT, + packet_util_size, gst_buffer_get_size (buffer)); + gst_buffer_unref (buffer); + return GST_FLOW_ERROR; + } + packet_offset = 0; while (packet_util_size > 0) { /* Even if we don't fill completely an output buffer we @@ -231,7 +248,7 @@ rtpasfpay->ts = packetinfo->send_time; } - if (size_left >= packet_util_size + 8) { + if (packet_util_size <= size_left - 8) { /* enough space for the rest of the packet */ if (packet_offset == 0) { flags = flags | 0x40;
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/gst/festival/gstfestival.c -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/gst/festival/gstfestival.c
Changed
@@ -110,6 +110,8 @@ GST_DEBUG_CATEGORY_STATIC (festival_debug); #define GST_CAT_DEFAULT festival_debug +#define MAX_WAVEFORM_SIZE_BYTES (128 * 1024 * 1024) /* 128 MB, or about an hour worth of samples */ + static void gst_festival_finalize (GObject * object); static GstFlowReturn gst_festival_chain (GstPad * pad, GstObject * parent, @@ -120,8 +122,9 @@ GstStateChange transition); static FT_Info *festival_default_info (void); -static char *socket_receive_file_to_buff (int fd, int *size); -static char *client_accept_s_expr (int fd); +static char *socket_receive_file_to_buff (GstFestival * festival, int fd, + int *size); +static char *client_accept_s_expr (GstFestival * festival, int fd); static GstStaticPadTemplate sink_template_factory = GST_STATIC_PAD_TEMPLATE ("sink", @@ -221,15 +224,45 @@ fd = festival->info->server_fd; do { - for (n = 0; n < 3;) - n += read (fd, ack + n, 3 - n); + for (n = 0; n < 3;) { + gssize read_bytes = read (fd, ack + n, 3 - n); + + if (read_bytes == 0) { + GST_ELEMENT_ERROR (festival, + LIBRARY, + FAILED, + ("Incomplete response on EOF"), ("Incomplete response on EOF")); + ret = FALSE; + goto done; + } else if (read_bytes < 0) { + if (errno == EAGAIN || errno == EINTR) { + continue; + } + + GST_ELEMENT_ERROR (festival, + LIBRARY, + FAILED, + ("Failed to read from server"), ("Error: %s", strerror (errno))); + ret = FALSE; + goto done; + } + + n += read_bytes; + } + ack3 = '\0'; GST_DEBUG_OBJECT (festival, "got response %s", ack); if (strcmp (ack, "WV\n") == 0) { GstBuffer *buffer; /* receive a waveform */ - data = socket_receive_file_to_buff (fd, &filesize); + data = socket_receive_file_to_buff (festival, fd, &filesize); + + if (!data) { + ret = FALSE; + break; + } + GST_DEBUG_OBJECT (festival, "received %d bytes of waveform data", filesize); @@ -240,7 +273,13 @@ } else if (strcmp (ack, "LP\n") == 0) { /* receive an s-expr */ - data = client_accept_s_expr (fd); + data = client_accept_s_expr (festival, fd); + + if (!data) { + ret = FALSE; + break; + } + GST_DEBUG_OBJECT (festival, "received s-expression: %s", data); g_free (data); } else if (strcmp (ack, "ER\n") == 0) { @@ -256,6 +295,7 @@ } while (strcmp (ack, "OK\n") != 0); +done: return ret; } @@ -386,20 +426,23 @@ } static char * -client_accept_s_expr (int fd) +client_accept_s_expr (GstFestival * festival, int fd) { /* Read s-expression from server, as a char * */ char *expr; int filesize; - expr = socket_receive_file_to_buff (fd, &filesize); - exprfilesize = '\0'; + expr = socket_receive_file_to_buff (festival, fd, &filesize); + + if (expr) { + exprfilesize = '\0'; + } return expr; } static char * -socket_receive_file_to_buff (int fd, int *size) +socket_receive_file_to_buff (GstFestival * festival, int fd, int *size) { /* Receive file (probably a waveform file) from socket using */ /* Festival key stuff technique, but long winded I know, sorry */ @@ -420,9 +463,52 @@ if (n == 0) break; /* hit stream eof before end of file */ + if (n < 0) { + if (errno == EAGAIN || errno == EINTR) { + continue; + } + + GST_ELEMENT_ERROR (festival, + LIBRARY, + FAILED, + ("Failed to read from server"), ("Error: %s", strerror (errno))); + + g_free (buff); + + return NULL; + } + if ((*size) + k + 1 >= bufflen) { + if (bufflen == MAX_WAVEFORM_SIZE_BYTES) { + GST_ELEMENT_ERROR (festival, + LIBRARY, + FAILED, + ("Maximum waveform size exceeded"), + ("Maximum waveform size exceeded")); + + g_free (buff); + return NULL; + } + /* +1 so you can add a NULL if you want */ bufflen += bufflen / 4; + + if (bufflen > MAX_WAVEFORM_SIZE_BYTES) { + bufflen = MAX_WAVEFORM_SIZE_BYTES; + + /* Sanity check as we just capped the reallocation size */ + if ((*size) + k + 1 >= bufflen) { + GST_ELEMENT_ERROR (festival, + LIBRARY, + FAILED, + ("Maximum waveform size exceeded"), + ("Maximum waveform size exceeded")); + + g_free (buff); + return NULL; + } + } + buff = (char *) g_realloc (buff, bufflen); } if (file_stuff_keyk == c)
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/gst/ivfparse/gstivfparse.c -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/gst/ivfparse/gstivfparse.c
Changed
@@ -315,6 +315,17 @@ "Read frame header: size %u, pts %" G_GUINT64_FORMAT, frame_size, frame_pts); + /* frame_size is read from the stream. Reject values that would overflow + * the guint32 sum with the header size used below; no valid IVF frame is + * anywhere near that large. */ + if (frame_size > G_MAXUINT32 - IVF_FRAME_HEADER_SIZE) { + GST_ERROR_OBJECT (ivf, "Invalid frame size %u", frame_size); + gst_buffer_unmap (buffer, &map); + ret = GST_FLOW_ERROR; + *skipsize = 0; + goto end; + } + if (map.size < IVF_FRAME_HEADER_SIZE + frame_size) { gst_base_parse_set_min_frame_size (GST_BASE_PARSE_CAST (ivf), IVF_FRAME_HEADER_SIZE + frame_size);
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/gst/librfb/gstrfbsrc.c -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/gst/librfb/gstrfbsrc.c
Changed
@@ -503,7 +503,6 @@ /* calculate some many used values */ decoder->bytespp = decoder->bpp / 8; - decoder->line_size = decoder->rect_width * decoder->bytespp; GST_DEBUG_OBJECT (src, "setting caps width to %d and height to %d", decoder->rect_width, decoder->rect_height); @@ -518,12 +517,23 @@ gst_video_info_init (&vinfo); - gst_video_info_set_format (&vinfo, vformat, decoder->rect_width, - decoder->rect_height); + if (vformat == GST_VIDEO_FORMAT_UNKNOWN || + !gst_video_info_set_format (&vinfo, vformat, decoder->rect_width, + decoder->rect_height)) { + GST_ELEMENT_ERROR (src, STREAM, WRONG_TYPE, + ("Unsupported VNC pixel format (depth %u, %u bits per pixel, " + "masks %08x %08x %08x)", decoder->depth, decoder->bpp, red_mask, + green_mask, blue_mask), (NULL)); + return FALSE; + } - decoder->frame = g_malloc (vinfo.size); + decoder->line_size = vinfo.stride0; + + /* Zero the frames: stride padding is never written to, and prev_frame is + * read before first fill */ + decoder->frame = g_malloc0 (vinfo.size); if (decoder->use_copyrect) - decoder->prev_frame = g_malloc (vinfo.size); + decoder->prev_frame = g_malloc0 (vinfo.size); caps = gst_video_info_to_caps (&vinfo); @@ -551,6 +561,9 @@ src->decoder->prev_frame = NULL; } + /* Force a full reconnect and handshake on the next start() */ + src->decoder->inited = FALSE; + return TRUE; }
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/gst/librfb/rfbdecoder.c -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/gst/librfb/rfbdecoder.c
Changed
@@ -20,6 +20,16 @@ GST_DEBUG_CATEGORY_EXTERN (rfbdecoder_debug); #define GST_CAT_DEFAULT rfbdecoder_debug +/* Upper bounds for server declared string lengths, so that a malicious + * server cannot make us allocate huge buffers */ + +/* Upper bound for the framebuffer dimensions, so that a malicious server + * cannot make us allocate huge buffers */ +#define RFB_MAX_FRAMEBUFFER_DIMENSION 8192 +#define RFB_MAX_NAME_LENGTH (4 * 1024) +#define RFB_MAX_REASON_LENGTH (1024 * 1024) +#define RFB_MAX_CUT_TEXT_LENGTH (1024 * 1024) + static gboolean rfb_decoder_state_wait_for_protocol_version (RfbDecoder * decoder); @@ -150,6 +160,11 @@ g_clear_object (&decoder->connection); g_clear_error (&decoder->error); g_clear_pointer (&decoder->data, g_free); + g_clear_pointer (&decoder->name, g_free); + decoder->data_len = 0; + + /* Start over from the protocol handshake on the next connection */ + decoder->state = NULL; g_mutex_unlock (&decoder->write_lock); } @@ -297,10 +312,11 @@ rfb_decoder_send (decoder, data, 10); - /* create a backup of the prev frame for copyrect encoding */ - if (decoder->use_copyrect) { + /* create a backup of the prev frame for copyrect encoding, but the buffer + * is only allocated if copyrect was enabled before negotiation */ + if (decoder->use_copyrect && decoder->prev_frame) { memcpy (decoder->prev_frame, decoder->frame, - decoder->rect_width * decoder->rect_height * decoder->bpp / 8); + decoder->rect_height * decoder->line_size); } decoder->state = rfb_decoder_state_normal; @@ -397,22 +413,32 @@ static gboolean rfb_decoder_state_reason (RfbDecoder * decoder) { - gint reason_length; + guint32 reason_length; + gchar *reason; if (!rfb_decoder_read (decoder, 4)) return FALSE; reason_length = RFB_GET_UINT32 (decoder->data); + if (reason_length > RFB_MAX_REASON_LENGTH) { + GST_WARNING ("Invalid reason length %u", reason_length); + return FALSE; + } - if (!rfb_decoder_read (decoder, reason_length)) + if (reason_length > 0 && !rfb_decoder_read (decoder, reason_length)) return FALSE; - GST_WARNING ("Reason by server: %s", decoder->data); + /* The reason string is not NUL-terminated on the wire */ + reason = reason_length > 0 ? g_strndup ((const gchar *) decoder->data, + reason_length) : g_strdup (""); + + GST_WARNING ("Reason by server: %s", reason); if (decoder->error == NULL) { decoder->error = g_error_new (GST_RESOURCE_ERROR, GST_RESOURCE_ERROR_READ, - "VNC server error: %s", decoder->data); + "VNC server error: %s", reason); } + g_free (reason); return FALSE; } @@ -680,6 +706,59 @@ decoder->green_shift = RFB_GET_UINT8 (decoder->data + 15); decoder->blue_shift = RFB_GET_UINT8 (decoder->data + 16); + if (decoder->width == 0 || decoder->height == 0 || + decoder->width > RFB_MAX_FRAMEBUFFER_DIMENSION || + decoder->height > RFB_MAX_FRAMEBUFFER_DIMENSION) { + GST_WARNING ("Invalid framebuffer dimensions %ux%u", decoder->width, + decoder->height); + if (decoder->error == NULL) { + decoder->error = g_error_new (GST_RESOURCE_ERROR, + GST_RESOURCE_ERROR_READ, + "VNC server error: invalid framebuffer dimensions"); + } + return FALSE; + } + + if (decoder->bpp != 8 && decoder->bpp != 16 && decoder->bpp != 24 && + decoder->bpp != 32) { + GST_WARNING ("Invalid bits per pixel %u from server", decoder->bpp); + if (decoder->error == NULL) { + decoder->error = g_error_new (GST_RESOURCE_ERROR, + GST_RESOURCE_ERROR_READ, "VNC server error: invalid bits per pixel"); + } + return FALSE; + } + + if (decoder->depth == 0 || decoder->depth > decoder->bpp) { + GST_WARNING ("Invalid colour depth %u for %u bits per pixel", + decoder->depth, decoder->bpp); + if (decoder->error == NULL) { + decoder->error = g_error_new (GST_RESOURCE_ERROR, + GST_RESOURCE_ERROR_READ, "VNC server error: invalid colour depth"); + } + return FALSE; + } + + if (!decoder->true_colour) { + GST_WARNING ("Pseudo-colour (colour map) framebuffers are not supported"); + if (decoder->error == NULL) { + decoder->error = g_error_new (GST_RESOURCE_ERROR, + GST_RESOURCE_ERROR_READ, + "VNC server error: colour map not supported"); + } + return FALSE; + } + + if (decoder->red_shift >= 32 || decoder->green_shift >= 32 || + decoder->blue_shift >= 32) { + GST_WARNING ("Invalid colour shifts from server"); + if (decoder->error == NULL) { + decoder->error = g_error_new (GST_RESOURCE_ERROR, + GST_RESOURCE_ERROR_READ, "VNC server error: invalid colour shifts"); + } + return FALSE; + } + GST_DEBUG ("Server Initialization"); GST_DEBUG ("width = %d", decoder->width); GST_DEBUG ("height = %d", decoder->height); @@ -696,10 +775,18 @@ name_length = RFB_GET_UINT32 (decoder->data + 20); - if (!rfb_decoder_read (decoder, name_length)) + if (name_length > RFB_MAX_NAME_LENGTH) { + GST_WARNING ("Invalid name length %u", name_length); return FALSE; + } - decoder->name = g_strndup ((gchar *) (decoder->data), name_length); + if (name_length > 0) { + if (!rfb_decoder_read (decoder, name_length)) + return FALSE; + decoder->name = g_strndup ((gchar *) (decoder->data), name_length); + } else { + decoder->name = g_strdup (""); + } GST_DEBUG ("name = %s", decoder->name); /* check if we need cropping */ @@ -775,7 +862,12 @@ decoder->state = rfb_decoder_state_server_cut_text; break; default: - g_critical ("unknown message type %d", message_type); + GST_WARNING ("Unknown message type %d from server", message_type); + if (decoder->error == NULL) { + decoder->error = g_error_new (GST_RESOURCE_ERROR, + GST_RESOURCE_ERROR_READ, "VNC server error: unknown message type"); + } + return FALSE; } return TRUE; @@ -791,6 +883,12 @@ decoder->n_rects = RFB_GET_UINT16 (decoder->data + 1); GST_DEBUG ("Number of rectangles : %d", decoder->n_rects); + if (G_UNLIKELY (decoder->n_rects == 0)) { + /* The frame is already complete */ + decoder->state = NULL; + return TRUE; + } + decoder->state = rfb_decoder_state_framebuffer_update_rectangle; return TRUE; @@ -820,11 +918,21 @@ GST_DEBUG ("w:%d h:%d", w, h); GST_DEBUG ("encoding: %d", encoding); + if (G_UNLIKELY (w > (gint) decoder->width || h > (gint) decoder->height)) { + GST_WARNING ("Rectangle %dx%d bigger than the framebuffer %dx%d", + w, h, decoder->width, decoder->height); + return FALSE; + } + switch (encoding) { case ENCODING_TYPE_RAW: ret = rfb_decoder_raw_encoding (decoder, x, y, w, h); break; case ENCODING_TYPE_COPYRECT: + if (G_UNLIKELY (!decoder->use_copyrect || decoder->prev_frame == NULL)) { + GST_WARNING ("Server sent CopyRect although it was not negotiated"); + break; + } ret = rfb_decoder_copyrect_encoding (decoder, x, y, w, h); break; case ENCODING_TYPE_RRE: @@ -888,9 +996,8 @@ &skip_x, &skip_y)) return TRUE; - frame = - decoder->frame + (((copy_y * decoder->rect_width) + - copy_x) * decoder->bytespp); + frame = decoder->frame + (copy_y * decoder->line_size) + + (copy_x * decoder->bytespp); p = decoder->data + (skip_y * raw_line_size) + (skip_x * decoder->bytespp); copy_line_size = copy_w * decoder->bytespp; @@ -930,12 +1037,10 @@ copyrect_width = copy_w * decoder->bytespp; line_width = decoder->line_size; - src = - decoder->prev_frame + ((src_y * decoder->rect_width) + - src_x) * decoder->bytespp; - dst = - decoder->frame + ((copy_y * decoder->rect_width) + - copy_x) * decoder->bytespp; + src = decoder->prev_frame + (src_y * decoder->line_size) + + (src_x * decoder->bytespp); + dst = decoder->frame + (copy_y * decoder->line_size) + + (copy_x * decoder->bytespp); while (copy_h--) { memcpy (dst, src, copyrect_width); @@ -958,9 +1063,8 @@ return; for (i = 0; i < h; i++) { - guint8 *offset = - decoder->frame + ((x + (y + - i) * decoder->rect_width)) * decoder->bytespp; + guint8 *offset = decoder->frame + ((y + i) * decoder->line_size) + + (x * decoder->bytespp); for (j = 0; j < w; j++) { switch (decoder->bytespp) { @@ -968,10 +1072,15 @@ *(guint8 *) offset = (guint8) color; break; case 2: - *(guint16 *) offset = (guint16) color; + GST_WRITE_UINT16_LE (offset, (guint16) color); + break; + case 3: + offset0 = (guint8) (color >> 16); + offset1 = (guint8) (color >> 8); + offset2 = (guint8) color; break; case 4: - *(guint32 *) offset = color; + GST_WRITE_UINT32_LE (offset, color); break; default: /* reject unsupported format */ @@ -990,6 +1099,8 @@ return RFB_GET_UINT8 (data); case 2: return GUINT16_SWAP_LE_BE (RFB_GET_UINT16 (data)); + case 3: + return ((guint32) data0 << 16) | ((guint32) data1 << 8) | data2; case 4: return GUINT32_SWAP_LE_BE (RFB_GET_UINT32 (data)); default: @@ -1128,6 +1239,9 @@ continue; } + if (nr_subrect == 0) + continue; + if (subencoding & SUBENCODING_SUBRECTSCOLORED) { guint offset = 0; @@ -1234,19 +1348,29 @@ static gboolean rfb_decoder_state_server_cut_text (RfbDecoder * decoder) { - gint cut_text_length; + guint32 cut_text_length; /* 3 bytes padding, 4 bytes cut_text_length */ if (!rfb_decoder_read (decoder, 7)) return FALSE; cut_text_length = RFB_GET_UINT32 (decoder->data + 3); - - if (!rfb_decoder_read (decoder, cut_text_length)) + if (cut_text_length > RFB_MAX_CUT_TEXT_LENGTH) { + GST_WARNING ("Invalid cut text length %u", cut_text_length); return FALSE; + } + + if (cut_text_length > 0) { + gchar *text; - GST_DEBUG ("rfb_decoder_state_server_cut_text: throw away '%s'", - decoder->data); + if (!rfb_decoder_read (decoder, cut_text_length)) + return FALSE; + + /* The text is not NUL-terminated on the wire */ + text = g_strndup ((const gchar *) decoder->data, cut_text_length); + GST_DEBUG ("rfb_decoder_state_server_cut_text: throw away '%s'", text); + g_free (text); + } decoder->state = rfb_decoder_state_normal;
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/gst/mpegdemux/gstmpegdemux.c -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/gst/mpegdemux/gstmpegdemux.c
Changed
@@ -59,8 +59,12 @@ #define SCAN_SCR_SZ 12 #define SCAN_PTS_SZ 80 -#define DEFAULT_GAP_THRESHOLD (300*GST_MSECOND) -#define VIDEO_GAP_THRESHOLD (500*GST_MSECOND) +/* align a bit more with e.g. matroskademux, + * as they more affect and relate to downstream queues etc than source material + */ +#define DEFAULT_GAP_THRESHOLD (2000*GST_MSECOND) +#define VIDEO_GAP_THRESHOLD (2000*GST_MSECOND) +#define SUB_GAP_THRESHOLD (500*GST_MSECOND) #define DURATION_SCAN_LIMIT 4 * 1024 * 1024 @@ -174,8 +178,7 @@ static inline gboolean gst_ps_demux_scan_backward_ts (GstPsDemux * demux, guint64 * pos, SCAN_MODE mode, guint64 * rts, gint limit); -static inline void gst_ps_demux_send_gap_updates (GstPsDemux * demux, - GstClockTime new_time); +static inline void gst_ps_demux_send_gap_updates (GstPsDemux * demux); static inline void gst_ps_demux_clear_times (GstPsDemux * demux); static void gst_ps_demux_reset_psm (GstPsDemux * demux); @@ -517,6 +520,7 @@ template = klass->subpicture_template; name = g_strdup_printf ("subpicture_%02x", id); caps = gst_caps_new_empty_simple ("subpicture/x-dvd"); + gap_threshold = SUB_GAP_THRESHOLD; break; case ST_GST_AUDIO_RAWA52: template = klass->audio_template; @@ -1007,11 +1011,13 @@ } static inline void -gst_ps_demux_send_gap_updates (GstPsDemux * demux, GstClockTime time) +gst_ps_demux_send_gap_updates (GstPsDemux * demux) { GstClockTime base_time, stop; gint i, count = demux->found_count; GstEvent *event = NULL; + /* use a time in same timeline as buffer timestamps (as opposed to SCR) */ + GstClockTime time = demux->src_segment.position; if (time == GST_CLOCK_TIME_NONE) return; @@ -1039,16 +1045,17 @@ if (stream->last_ts + stream->gap_threshold < time && stream->nb_out_buffers == stream->gap_ref_buffers && stream->gap_ref_pts != stream->last_ts) { + guint64 stop = time - stream->gap_threshold; /* should send segment info before gap event */ gst_ps_demux_send_segment (demux, stream, GST_CLOCK_TIME_NONE); GST_LOG_OBJECT (demux, "Sending gap update to pad %s from time %" GST_TIME_FORMAT " to %" GST_TIME_FORMAT, GST_PAD_NAME (stream->pad), - GST_TIME_ARGS (stream->last_ts), GST_TIME_ARGS (time)); - event = gst_event_new_gap (stream->last_ts, time - stream->last_ts); + GST_TIME_ARGS (stream->last_ts), GST_TIME_ARGS (stop)); + event = gst_event_new_gap (stream->last_ts, stop - stream->last_ts); gst_pad_push_event (stream->pad, event); - stream->last_ts = time; + stream->last_ts = stop; } /* Update GAP tracking vars so we don't re-check this stream for a while */ @@ -1969,10 +1976,12 @@ * adapter */ demux->bytes_since_scr = avail; - /* Now check for all streams if they're behind the new SCR and if - * they are then move them forward to the SCR position */ - gst_ps_demux_send_gap_updates (demux, - MPEGTIME_TO_GSTTIME (demux->current_scr - demux->first_scr)); + /* Now check for all streams if they're behind the common PTS/DTS position + * and if they are then move them forward. + * Could alternatively do this in send_data() after every PES, but this + * probably suffices. + */ + gst_ps_demux_send_gap_updates (demux); out: gst_adapter_unmap (demux->adapter);
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/gst/mpegtsdemux/tsdemux.c -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/gst/mpegtsdemux/tsdemux.c
Changed
@@ -1260,13 +1260,19 @@ const GstMpegtsDescriptor *ac3_desc = mpegts_get_descriptor_from_stream (bstream, GST_MTS_DESC_AC3_AUDIO_STREAM); - if (ac3_desc && ac3_desc->length >= 8 - && DESC_AC_AUDIO_STREAM_has_lang1 (ac3_desc->data)) { - gchar lang_code4; - - memcpy (lang_code, DESC_AC_AUDIO_STREAM_lang1_code (ac3_desc->data), 3); - lang_code3 = '\0'; - add_iso639_language_to_tags (stream, lang_code); + /* ac3_desc->data holds length + 2 bytes, and textlen is read from the + * descriptor itself, so bound the offsets it selects before using them */ + if (ac3_desc && ac3_desc->length >= 8) { + guint textlen = DESC_AC_AUDIO_STREAM_textlen (ac3_desc->data); + + if (ac3_desc->length >= 10 + textlen + && DESC_AC_AUDIO_STREAM_has_lang1 (ac3_desc->data)) { + gchar lang_code4; + + memcpy (lang_code, DESC_AC_AUDIO_STREAM_lang1_code (ac3_desc->data), 3); + lang_code3 = '\0'; + add_iso639_language_to_tags (stream, lang_code); + } } } @@ -1369,7 +1375,8 @@ ac3_desc = mpegts_get_descriptor_from_stream (bstream, GST_MTS_DESC_AC3_AUDIO_STREAM); - if (ac3_desc && DESC_AC_AUDIO_STREAM_bsid (ac3_desc->data) != 16) { + if (ac3_desc && ac3_desc->length >= 1 + && DESC_AC_AUDIO_STREAM_bsid (ac3_desc->data) != 16) { GST_LOG_OBJECT (demux, "ac3 audio"); is_audio = TRUE; caps = gst_caps_new_empty_simple ("audio/x-ac3");
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/gst/mpegtsmux/gstbasetsmux.c -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/gst/mpegtsmux/gstbasetsmux.c
Changed
@@ -2216,7 +2216,26 @@ } if (!translate) { - g_assert (section->data); + gsize section_data_size; + + if (!section->data) { + /* Manually constructed sections have no binary representation, + * packetize them to get one. Their splice times are already + * expressed in the MPEG time domain. */ + guint8 *packetized; + + packetized = gst_mpegts_section_packetize (section, §ion_data_size); + if (G_UNLIKELY (!packetized)) { + GST_WARNING_OBJECT (mux, + "Could not packetize SCTE section, dropping it"); + gst_mpegts_section_unref (section); + return; + } + section_data = g_memdup2 (packetized, section_data_size); + } else { + section_data = g_memdup2 (section->data, section->section_length); + section_data_size = section->section_length; + } /* Calculate the final adjustment, as a sum of: * - The adjustment in the original packet * - The offset introduced between the original local PTS @@ -2230,15 +2249,14 @@ GSTTIMEDIFF_TO_MPEGTIME (gst_event_get_running_time_offset (event)); pts_adjust &= 0x1ffffffff; - section_data = g_memdup2 (section->data, section->section_length); - section_data4 |= pts_adjust >> 32; + section_data4 = (section_data4 & 0xfe) | ((pts_adjust >> 32) & 0x01); section_data5 = pts_adjust >> 24; section_data6 = pts_adjust >> 16; section_data7 = pts_adjust >> 8; section_data8 = pts_adjust; /* Now rewrite our checksum */ - crc = section_data + section->section_length - 4; + crc = section_data + section_data_size - 4; GST_WRITE_UINT32_BE (crc, _calc_crc32 (section_data, crc - section_data)); GST_OBJECT_LOCK (mux); @@ -2247,7 +2265,7 @@ gst_mpegts_section_unref (mux->pending_scte35_section); mux->pending_scte35_section = gst_mpegts_section_new (mux->scte35_pid, section_data, - section->section_length); + section_data_size); GST_OBJECT_UNLOCK (mux); gst_mpegts_section_unref (section);
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/gst/mxf/mxfdemux.c -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/gst/mxf/mxfdemux.c
Changed
@@ -220,7 +220,7 @@ g_ptr_array_index (demux->essence_tracks, i); track->source_package = NULL; - track->delta_id = -1; + track->delta_id = MXF_INDEX_DELTA_ID_UNKNOWN; track->source_track = NULL; } @@ -942,7 +942,7 @@ etrack->source_package = NULL; etrack->source_track = NULL; - etrack->delta_id = -1; + etrack->delta_id = MXF_INDEX_DELTA_ID_UNKNOWN; if (!track->parent.sequence) { GST_WARNING_OBJECT (demux, "Source track has no sequence"); @@ -1052,7 +1052,7 @@ etrack->min_edit_units = gst_util_uint64_scale (25 * GST_MSECOND, track->edit_rate.n, track->edit_rate.d * GST_SECOND); - GST_DEBUG_OBJECT (demux, "Seting miminum number of edit units to %u", + GST_DEBUG_OBJECT (demux, "Setting minimum number of edit units to %u", etrack->min_edit_units); } } @@ -1066,7 +1066,7 @@ if (package->is_interleaved) { GST_DEBUG_OBJECT (demux, - "track comes from interleaved source package with %u track(s), setting delta_id to -1", + "track comes from interleaved source package with %u track(s), setting delta_id to UNKNOWN", package->parent.n_tracks); if (etrack->wrapping != MXF_ESSENCE_WRAPPING_FRAME_WRAPPING) { GST_ELEMENT_ERROR (demux, STREAM, WRONG_TYPE, (NULL), @@ -2217,6 +2217,17 @@ g_array_insert_val (etrack->offsets, position, *entry); } +/* @delta_id might come from a segment with more delta entries than @segment */ +static MXFDeltaEntry * +get_delta_entry (MXFIndexTableSegment * segment, gint32 delta_id) +{ + if (G_UNLIKELY (delta_id < 0 + || delta_id >= (gint32) segment->n_delta_entries)) + return NULL; + + return &segment->delta_entriesdelta_id; +} + /** * find_edit_entry: * @demux: The demuxer @@ -2377,10 +2388,12 @@ /* Figure out the stream offset (also called "body offset" in specification) */ if (segment->edit_unit_byte_count && !segment->n_index_entries) { + MXFDeltaEntry *delta_entry; + /* Constant entry table. */ stream_offset = position * segment->edit_unit_byte_count; - if (etrack->delta_id >= 0) { - MXFDeltaEntry *delta_entry = &segment->delta_entriesetrack->delta_id; + delta_entry = get_delta_entry (segment, etrack->delta_id); + if (delta_entry) { GST_LOG_OBJECT (demux, "Using delta %d pos_table_index:%d slice:%u element_delta:%u", etrack->delta_id, delta_entry->pos_table_index, delta_entry->slice, @@ -2415,8 +2428,7 @@ &segment->index_entriesposition - segment->index_start_position; stream_offset = segment_index_entry->stream_offset; - if (segment->n_delta_entries > 0) - delta_entry = &segment->delta_entriesetrack->delta_id; + delta_entry = get_delta_entry (segment, etrack->delta_id); if (delta_entry) { GST_LOG_OBJECT (demux, @@ -2425,7 +2437,7 @@ delta_entry->element_delta); /* Apply offset from slice/delta if needed */ - if (delta_entry->slice) { + if (delta_entry->slice > 0 && delta_entry->slice <= segment->slice_count) { stream_offset += segment_index_entry->slice_offsetdelta_entry->slice - 1; } @@ -2435,7 +2447,7 @@ } /* Apply reverse temporal reordering if present */ - if (index_table->reordered_delta_entry == etrack->delta_id) { + if (delta_entry && index_table->reordered_delta_entry == etrack->delta_id) { if (demux->temporal_order_misuse) { GST_DEBUG_OBJECT (demux, "Handling temporal order misuse"); entry->pts = position + segment_index_entry->temporal_offset; @@ -2451,8 +2463,9 @@ "Applied temporal offset. dts:%" G_GUINT64_FORMAT " pts:%" G_GUINT64_FORMAT, position, entry->pts); } - } else + } else { entry->pts = position; + } } else { /* Note : This should have been handled in the parser */ GST_WARNING_OBJECT (demux, @@ -2689,11 +2702,11 @@ } else { for (delta = 0; delta < index_segment->n_delta_entries; delta++) { guint64 delta_offs = 0; + guint8 slice = index_segment->delta_entriesdelta.slice; /* If we are not in the first slice, take that offset into account */ - if (index_segment->delta_entriesdelta.slice) - delta_offs = - index_entry->slice_offsetindex_segment-> - delta_entriesdelta.slice - 1; + if (slice > 0 && slice <= index_segment->slice_count) { + delta_offs = index_entry->slice_offsetslice - 1; + } /* Add the offset for this delta */ delta_offs += index_segment->delta_entriesdelta.element_delta; if (cp_offset == delta_offs) { @@ -2711,8 +2724,8 @@ "Couldn't match delta id, ignoring it from now on"); etrack->delta_id = MXF_INDEX_DELTA_ID_IGNORE; } - } else if (index_segment->n_delta_entries > 0) { - delta_entry = &index_segment->delta_entriesetrack->delta_id; + } else { + delta_entry = get_delta_entry (index_segment, etrack->delta_id); } if (index_entry && delta_entry && delta_entry->pos_table_index == -1) { @@ -4998,6 +5011,72 @@ } } +static gboolean +delta_entries_equal (const MXFDeltaEntry * a, const MXFDeltaEntry * b) +{ + return a->slice == b->slice && a->pos_table_index == b->pos_table_index + && a->element_delta == b->element_delta; +} + +static void +drop_delta_entries (MXFIndexTableSegment * segment) +{ + g_free (segment->delta_entries); + segment->delta_entries = NULL; + segment->n_delta_entries = 0; +} + +/* The delta lookup table belongs to a single index segment, but a track uses + * one delta id in all segments of the index search domain, so all of them have + * to agree on it. Drop the delta entries of the whole domain if they don't. + */ +static void +ensure_common_delta_entries (GstMXFDemux * demux, GstMXFDemuxIndexTable * t, + MXFIndexTableSegment * segment) +{ + MXFIndexTableSegment *ref = NULL; + guint i, j; + + if (t->delta_entries_inconsistent) { + drop_delta_entries (segment); + return; + } + + /* No table to compare against */ + if (segment->n_delta_entries == 0) + return; + + for (i = 0; i < t->segments->len; i++) { + MXFIndexTableSegment *s = + &g_array_index (t->segments, MXFIndexTableSegment, i); + if (s->n_delta_entries == 0) + continue; + ref = s; + break; + } + + if (ref) { + gboolean equal = ref->n_delta_entries == segment->n_delta_entries; + for (j = 0; equal && j < segment->n_delta_entries; j++) + equal = delta_entries_equal (&ref->delta_entriesj, + &segment->delta_entriesj); + if (equal) + return; + } + + GST_WARNING_OBJECT (demux, + "bodySID:%u indexSID:%u index search domain uses different delta tables, " + "ignoring delta entries", segment->body_sid, segment->index_sid); + + t->delta_entries_inconsistent = TRUE; + t->reordered_delta_entry = -1; + for (i = 0; i < t->segments->len; i++) { + drop_delta_entries (&g_array_index (t->segments, MXFIndexTableSegment, i)); + } + + drop_delta_entries (segment); +} + static void collect_index_table_segments (GstMXFDemux * demux) { @@ -5068,6 +5147,8 @@ t->reordered_delta_entry = -1; t->reverse_temporal_offsets = g_array_new (FALSE, TRUE, 1); demux->index_tables = g_list_prepend (demux->index_tables, t); + } else { + ensure_common_delta_entries (demux, t, segment); } /* Store index segment */ @@ -5084,7 +5165,7 @@ else t->reordered_delta_entry = didx; } else if (delta->pos_table_index > 0) - GST_WARNING_OBJECT (delta, + GST_WARNING_OBJECT (demux, "Index Table uses fractional offset, please file a bug"); }
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/gst/mxf/mxfdemux.h -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/gst/mxf/mxfdemux.h
Changed
@@ -112,6 +112,9 @@ * Special values: * * -1 Not discovered yet * * -2 Ignore delta entry (if index table is not present or not complete) + * + * Values >= 0 are an index into the delta entries of the segment it was + * resolved from, which has to be checked before using it with another one. */ gint32 delta_id; @@ -177,6 +180,9 @@ /* Delta entry to which reordering should be applied (-1 == no reordering) */ gint reordered_delta_entry; + /* Delta entries were dropped because the segments use different tables */ + gboolean delta_entries_inconsistent; + /* Array of gint8 reverse temporal offsets. * Contains the shift to apply to an entry DTS to get the PTS *
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/gst/mxf/mxfmetadata.c -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/gst/mxf/mxfmetadata.c
Changed
@@ -491,7 +491,7 @@ GST_DEBUG ("Metadata type 0x%04x is handled by type %s", type, g_type_name (t)); - ret = (MXFMetadata *) g_type_create_instance (t); + ret = (MXFMetadata *) g_object_new (t, NULL); if (!mxf_metadata_base_parse (MXF_METADATA_BASE (ret), primer, data, size)) { GST_ERROR ("Parsing metadata failed"); g_object_unref (ret); @@ -6527,7 +6527,7 @@ GST_DEBUG ("DM scheme 0x%02x type 0x%06x is handled by type %s", scheme, type, g_type_name (t)); - ret = (MXFDescriptiveMetadata *) g_type_create_instance (t); + ret = (MXFDescriptiveMetadata *) g_object_new (t, NULL); if (!mxf_metadata_base_parse (MXF_METADATA_BASE (ret), primer, data, size)) { GST_ERROR ("Parsing metadata failed"); g_object_unref (ret);
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/gst/tensordecoders/gstclassifiertensordecoder.c -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/gst/tensordecoders/gstclassifiertensordecoder.c
Changed
@@ -285,6 +285,8 @@ GstClassifierTensorDecoder *self = GST_CLASSIFIER_TENSOR_DECODER (object); g_free (self->labels_file); + g_clear_pointer (&self->class_quark, g_array_unref); + g_clear_pointer (&self->postproc_result, g_array_unref); G_OBJECT_CLASS (gst_classifier_tensor_decoder_parent_class)->finalize (object); } @@ -301,6 +303,7 @@ self->threshold = g_value_get_float (value); break; case PROP_LABEL_FILE: + g_free (self->labels_file); self->labels_file = g_strdup (g_value_get_string (value)); if (self->labels_file) { @@ -367,25 +370,25 @@ tokens = g_strsplit (content, "\n", 0); g_free (content); - if (tokens0 != NULL) { - class_quark = - g_array_sized_new (FALSE, FALSE, sizeof (GQuark), self->class_count); - } - - self->class_quark = g_array_new (FALSE, FALSE, sizeof (GQuark)); + class_quark = g_array_new (FALSE, FALSE, sizeof (GQuark)); for (int i = 0; tokensi != NULL && tokensi0 != '\0'; i++) { val = g_quark_from_string (tokensi); g_array_append_val (class_quark, val); } - if (class_quark == NULL) - GST_WARNING_OBJECT (self, "Label %s file does not contain any labels", + g_strfreev (tokens); + + if (class_quark->len == 0) { + GST_ERROR_OBJECT (self, "Labels file %s does not contain any labels", self->labels_file); + g_array_unref (class_quark); + return 0; + } + g_clear_pointer (&self->class_quark, g_array_unref); self->class_quark = class_quark; - g_strfreev (tokens); return self->class_quark->len; } @@ -411,10 +414,8 @@ switch (transition) { case GST_STATE_CHANGE_READY_TO_NULL: - if (self->class_quark) - g_array_free (self->class_quark, FALSE); - if (self->postproc_result) - g_array_free (self->postproc_result, TRUE); + g_clear_pointer (&self->class_quark, g_array_unref); + g_clear_pointer (&self->postproc_result, g_array_unref); break; default: break; @@ -672,14 +673,22 @@ self->class_count = g_value_get_int (dim_v); /* Allocate postproc_result buffer for softmax or uint8->float conversion */ + g_clear_pointer (&self->postproc_result, g_array_unref); self->postproc_result = g_array_sized_new (FALSE, TRUE, sizeof (gfloat), self->class_count); + /* Labels generated for previous caps, regenerate them if the class count + * changed */ + if (self->labels_file == NULL && self->class_quark != NULL && + self->class_count != self->class_quark->len) + g_clear_pointer (&self->class_quark, g_array_unref); + if (self->class_quark != NULL && self->class_count != self->class_quark->len) { GST_ELEMENT_ERROR (GST_BASE_TRANSFORM (self), STREAM, FAILED, ("Label-file/Tensor mismatch"), ("Class count from tensor mismatch class count from label file")); + g_clear_pointer (&self->postproc_result, g_array_unref); return FALSE; } @@ -689,8 +698,8 @@ self->class_count); for (gsize i = 0; i < self->class_count; i++) { if (g_snprintf (buffer, sizeof (buffer), "%zu", i) >= sizeof (buffer)) { - g_array_free (self->postproc_result, FALSE); - self->postproc_result = NULL; + g_clear_pointer (&self->class_quark, g_array_unref); + g_clear_pointer (&self->postproc_result, g_array_unref); return FALSE; } val = g_quark_from_string (buffer);
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/gst/unixfd/gstunixfdsink.c -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/gst/unixfd/gstunixfdsink.c
Changed
@@ -484,11 +484,19 @@ } static gboolean +quit_main_loop_cb (gpointer user_data) +{ + GMainLoop *loop = user_data; + g_main_loop_quit (loop); + return G_SOURCE_REMOVE; +} + +static gboolean gst_unix_fd_sink_stop (GstBaseSink * bsink) { GstUnixFdSink *self = (GstUnixFdSink *) bsink; - g_main_loop_quit (self->loop); + g_main_context_invoke (self->context, quit_main_loop_cb, self->loop); g_thread_join (self->thread); g_source_destroy (self->source);
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/gst/videoparsers/gstav1parse.c -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/gst/videoparsers/gstav1parse.c
Changed
@@ -1362,16 +1362,28 @@ * num_units_in_display_tick num_ticks_per_picture_minus_1 + 1 */ if (ti->equal_picture_interval) { - gint gcd; - - *fps_n = ti->time_scale; - *fps_d = ti->num_units_in_display_tick * - (ti->num_ticks_per_picture_minus_1 + 1); + gint64 n64, d64, gcd; + + /* The timing information values are 32-bit unsigned in the bitstream + * and their product can overflow, so compute in 64 bits. Reduce the + * fraction first, then reject anything that does not fit a positive + * gint fraction. */ + n64 = ti->time_scale; + d64 = (gint64) ti->num_units_in_display_tick * + ((gint64) ti->num_ticks_per_picture_minus_1 + 1); + + if (n64 <= 0 || d64 <= 0) { + gcd = 0; + } else { + gcd = gst_util_greatest_common_divisor_int64 (n64, d64); + } - gcd = gst_util_greatest_common_divisor (*fps_n, *fps_d); - if (gcd) { - *fps_n /= gcd; - *fps_d /= gcd; + if (gcd == 0 || (n64 / gcd) > G_MAXINT || (d64 / gcd) > G_MAXINT) { + *fps_n = 0; + *fps_d = 1; + } else { + *fps_n = (gint) (n64 / gcd); + *fps_d = (gint) (d64 / gcd); } } else { *fps_n = 0;
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/gst/videoparsers/gsth264parse.c -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/gst/videoparsers/gsth264parse.c
Changed
@@ -978,6 +978,11 @@ return TRUE; } + if (G_UNLIKELY (nalu->datanalu->offset & 0x80)) { + GST_WARNING_OBJECT (h264parse, "NAL has forbidden_zero_bit set"); + return FALSE; + } + /* we have a peek as well */ nal_type = nalu->type; @@ -1475,6 +1480,8 @@ goto skip; } break; + case GST_H264_PARSER_BROKEN_DATA: + goto broken; case GST_H264_PARSER_NO_NAL: /* we don't have enough bytes to make any decisions yet */ goto more; @@ -1505,6 +1512,18 @@ /* In NAL alignment, assume the NAL is broken */ if (h264parse->in_align == GST_H264_PARSE_ALIGN_NAL || h264parse->in_align == GST_H264_PARSE_ALIGN_AU) { + /* There is no start code between current_off and the end of the + * buffer. gst_h264_parser_identify_nalu() leaves nalu zeroed in + * that case, so it still describes the previous NAL (or nothing at + * all when this is the first iteration of a resumed parse). Make it + * describe the unparseable tail instead, so that "broken" below + * skips all of it at the start of a frame, or terminates the AU + * right after the last good NAL. Terminating at a stale sc_offset + * of 0 finishes a zero-sized frame, which leaves baseparse with a + * consumed frame->buffer leading to a crash. */ + nalu.sc_offset = current_off; + nalu.offset = size; + nalu.size = 0; goto broken; } goto more; @@ -1569,6 +1588,12 @@ GST_DEBUG_OBJECT (h264parse, "%p complete nal found. Off: %u, Size: %u", data, nalu.offset, nalu.size); + if (G_UNLIKELY (nalu.datanalu.offset & 0x80)) { + GST_WARNING_OBJECT (h264parse, "NAL has forbidden_zero_bit set"); + /* Keep any complete NALs collected before this malformed one. */ + goto broken; + } + if (gst_h264_parse_collect_nal (h264parse, &nalu)) { h264parse->aud_needed = TRUE; /* complete current frame, if it exist */
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/gst/videoparsers/gsth265parse.c -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/gst/videoparsers/gsth265parse.c
Changed
@@ -212,6 +212,7 @@ h265parse->have_sps_in_frame = FALSE; h265parse->have_pps_in_frame = FALSE; h265parse->have_aud_in_frame = FALSE; + h265parse->have_vcl_in_frame = FALSE; h265parse->layer_id = 0; h265parse->temporal_id_plus1 = 0; gst_adapter_clear (h265parse->frame_out); @@ -624,11 +625,11 @@ */ for (j = 0, k = 2; j < G_N_ELEMENTS (minfo.display_primaries); j++, k++) { minfo.display_primariesj.x = - sei.payload. - mastering_display_colour_volume.display_primaries_xk % 3; + sei.payload.mastering_display_colour_volume. + display_primaries_xk % 3; minfo.display_primariesj.y = - sei.payload. - mastering_display_colour_volume.display_primaries_yk % 3; + sei.payload.mastering_display_colour_volume. + display_primaries_yk % 3; } minfo.white_point.x = @@ -636,11 +637,11 @@ minfo.white_point.y = sei.payload.mastering_display_colour_volume.white_point_y; minfo.max_display_mastering_luminance = - sei.payload.mastering_display_colour_volume. - max_display_mastering_luminance; + sei.payload. + mastering_display_colour_volume.max_display_mastering_luminance; minfo.min_display_mastering_luminance = - sei.payload.mastering_display_colour_volume. - min_display_mastering_luminance; + sei.payload. + mastering_display_colour_volume.min_display_mastering_luminance; GST_LOG_OBJECT (h265parse, "mastering display info found: " "Red(%u, %u) " @@ -768,6 +769,11 @@ return TRUE; } + if (G_UNLIKELY (nalu->datanalu->offset & 0x80)) { + GST_WARNING_OBJECT (h265parse, "NAL has forbidden_zero_bit set"); + return FALSE; + } + /* we have a peek as well */ nal_type = nalu->type; @@ -1076,6 +1082,12 @@ return complete; } +static gboolean +gst_h265_parse_nal_is_vcl (const GstH265NalUnit * nalu) +{ + return (nalu->type <= GST_H265_NAL_SLICE_CRA_NUT); +} + static GstFlowReturn gst_h265_parse_handle_frame_packetized (GstBaseParse * parse, GstBaseParseFrame * frame) @@ -1115,6 +1127,8 @@ /* either way, have a look at it */ gst_h265_parse_process_nal (h265parse, &nalu); + h265parse->have_vcl_in_frame |= gst_h265_parse_nal_is_vcl (&nalu); + /* dispatch per NALU if needed */ if (h265parse->split_packetized) { GstBaseParseFrame tmp_frame; @@ -1302,6 +1316,8 @@ goto skip; } break; + case GST_H265_PARSER_BROKEN_DATA: + goto broken; case GST_H265_PARSER_NO_NAL: /* start code may have up to 4 bytes, and we may also get that return * value if only one of the two header bytes are present, make sure @@ -1364,9 +1380,24 @@ ("Error parsing H.265 stream"), ("Invalid H.265 stream")); goto invalid_stream; case GST_H265_PARSER_NO_NAL: - GST_ELEMENT_ERROR (h265parse, STREAM, FORMAT, - ("Error parsing H.265 stream"), ("No H.265 NAL unit found")); - goto invalid_stream; + /* In NAL alignment, assume the NAL is broken */ + if (h265parse->in_align == GST_H265_PARSE_ALIGN_NAL || + h265parse->in_align == GST_H265_PARSE_ALIGN_AU) { + /* There is no start code between current_off and the end of the + * buffer. gst_h265_parser_identify_nalu() leaves nalu zeroed in + * that case, so it still describes the previous NAL (or nothing at + * all when this is the first iteration of a resumed parse). Make it + * describe the unparseable tail instead, so that "broken" below + * skips all of it at the start of a frame, or terminates the AU + * right after the last good NAL. Terminating at a stale sc_offset + * of 0 finishes a zero-sized frame, which leaves baseparse with a + * consumed frame->buffer leading to a crash. */ + nalu.sc_offset = current_off; + nalu.offset = size; + nalu.size = 0; + goto broken; + } + goto more; case GST_H265_PARSER_BROKEN_DATA: GST_WARNING_OBJECT (h265parse, "input stream is corrupt; " "it contains a NAL unit of length %u", nalu.size); @@ -1392,6 +1423,14 @@ GST_DEBUG_OBJECT (h265parse, "%p complete nal found. Off: %u, Size: %u", data, nalu.offset, nalu.size); + if (G_UNLIKELY (nalu.datanalu.offset & 0x80)) { + GST_WARNING_OBJECT (h265parse, "NAL has forbidden_zero_bit set"); + /* Keep any complete NALs collected before this malformed one. */ + goto broken; + } + + h265parse->have_vcl_in_frame |= gst_h265_parse_nal_is_vcl (&nalu); + if (gst_h265_parse_collect_nal (h265parse, data, size, &nalu)) { h265parse->aud_needed = TRUE; /* complete current frame, if it exist */ @@ -2285,7 +2324,8 @@ fps_num = sps->vui_params.time_scale; fps_den = sps->vui_params.num_units_in_tick; - if (gst_h265_parse_is_field_interlaced (h265parse)) { + if (fps_num > 0 && fps_den > 0 && + gst_h265_parse_is_field_interlaced (h265parse)) { gint new_fps_num, new_fps_den; if (!gst_util_fraction_multiply (fps_num, fps_den, 1, 2, &new_fps_num, @@ -2301,6 +2341,19 @@ } } + /* time_scale and num_units_in_tick are 32-bit unsigned in the + * bitstream, so they can exceed the range of the gint used for the + * framerate. Such values are not a valid framerate and the fraction + * maths has undefined behaviour for them; treat them as unknown. */ + if (fps_num <= 0 || fps_den <= 0) { + if (fps_num != 0 || fps_den != 1) { + GST_INFO_OBJECT (h265parse, "Invalid framerate %d/%d from timing " + "information; using 0/1", fps_num, fps_den); + } + fps_num = 0; + fps_den = 1; + } + if (G_UNLIKELY (h265parse->fps_num != fps_num || h265parse->fps_den != fps_den)) { GST_INFO_OBJECT (h265parse, "framerate changed %d/%d", @@ -2709,15 +2762,18 @@ gst_h265_parse_update_src_caps (h265parse, NULL); - if (h265parse->fps_num > 0 && h265parse->fps_den > 0 && - !GST_BUFFER_DURATION_IS_VALID (buffer)) { - GstClockTime val = - gst_h265_parse_is_field_interlaced (h265parse) ? GST_SECOND / - 2 : GST_SECOND; + if (h265parse->have_vcl_in_frame) { + if (h265parse->fps_num > 0 && h265parse->fps_den > 0 && + !GST_BUFFER_DURATION_IS_VALID (buffer)) { + GstClockTime val = + gst_h265_parse_is_field_interlaced (h265parse) ? GST_SECOND / + 2 : GST_SECOND; - GST_BUFFER_DURATION (buffer) = gst_util_uint64_scale (val, - h265parse->fps_den, h265parse->fps_num); - } + GST_BUFFER_DURATION (buffer) = gst_util_uint64_scale (val, + h265parse->fps_den, h265parse->fps_num); + } + } else + GST_BUFFER_DURATION (buffer) = 0; if (h265parse->keyframe) GST_BUFFER_FLAG_UNSET (buffer, GST_BUFFER_FLAG_DELTA_UNIT); @@ -3310,6 +3366,12 @@ if (h265parse->time_code.units_field_based_flagi) scale_n *= 2; + if (G_UNLIKELY (scale_d == 0)) { + GST_WARNING_OBJECT (h265parse, + "VUI time_scale is 0, cannot scale timecode; skipping meta"); + continue; + } + n_frames = gst_util_uint64_scale (h265parse->time_code.n_framesi, scale_n, scale_d);
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/gst/videoparsers/gsth265parse.h -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/gst/videoparsers/gsth265parse.h
Changed
@@ -87,6 +87,7 @@ gboolean have_sps_in_frame; gboolean have_pps_in_frame; gboolean have_aud_in_frame; + gboolean have_vcl_in_frame; gboolean first_frame;
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/gst/videoparsers/gsth266parse.c -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/gst/videoparsers/gsth266parse.c
Changed
@@ -256,6 +256,7 @@ h266parse->have_vps_in_frame = FALSE; h266parse->have_sps_in_frame = FALSE; h266parse->have_pps_in_frame = FALSE; + h266parse->have_vcl_in_frame = FALSE; gst_adapter_clear (h266parse->frame_out); } @@ -676,6 +677,11 @@ return TRUE; } + if (G_UNLIKELY (nalu->datanalu->offset & 0x80)) { + GST_WARNING_OBJECT (h266parse, "NAL has forbidden_zero_bit set"); + return FALSE; + } + /* we have a peek as well */ nal_type = nalu->type; @@ -992,6 +998,12 @@ return complete; } +static gboolean +gst_h266_parse_nal_is_vcl (const GstH266NalUnit * nalu) +{ + return nalu->type <= GST_H266_NAL_SLICE_GDR; +} + static GstFlowReturn gst_h266_parse_handle_frame_packetized (GstBaseParse * parse, GstBaseParseFrame * frame) @@ -1028,6 +1040,8 @@ /* either way, have a look at it */ gst_h266_parse_process_nal (h266parse, &nalu); + h266parse->have_vcl_in_frame |= gst_h266_parse_nal_is_vcl (&nalu); + /* dispatch per NALU if needed */ if (h266parse->split_packetized) { GstBaseParseFrame tmp_frame; @@ -1214,6 +1228,8 @@ goto skip; } break; + case GST_H266_PARSER_BROKEN_DATA: + goto broken; case GST_H266_PARSER_NO_NAL: /* start code may have up to 4 bytes, and we may also get that return * value if only one of the two header bytes are present, make sure @@ -1282,9 +1298,24 @@ ("Error parsing H.266 stream"), ("Invalid H.266 stream")); goto invalid_stream; case GST_H266_PARSER_NO_NAL: - GST_ELEMENT_ERROR (h266parse, STREAM, FORMAT, - ("Error parsing H.266 stream"), ("No H.266 NAL unit found")); - goto invalid_stream; + /* In NAL alignment, assume the NAL is broken */ + if (h266parse->in_align == GST_H266_PARSE_ALIGN_NAL || + h266parse->in_align == GST_H266_PARSE_ALIGN_AU) { + /* There is no start code between current_off and the end of the + * buffer. gst_h266_parser_identify_nalu() leaves nalu zeroed in + * that case, so it still describes the previous NAL (or nothing at + * all when this is the first iteration of a resumed parse). Make it + * describe the unparseable tail instead, so that "broken" below + * skips all of it at the start of a frame, or terminates the AU + * right after the last good NAL. Terminating at a stale sc_offset + * of 0 finishes a zero-sized frame, which leaves baseparse with a + * consumed frame->buffer leading to a crash. */ + nalu.sc_offset = current_off; + nalu.offset = size; + nalu.size = 0; + goto broken; + } + goto more; case GST_H266_PARSER_BROKEN_DATA: GST_WARNING_OBJECT (h266parse, "input stream is corrupt; " "it contains a NAL unit of length %u", nalu.size); @@ -1310,6 +1341,14 @@ GST_LOG_OBJECT (h266parse, "%p complete nal found. Off: %u, Size: %u", data, nalu.offset, nalu.size); + if (G_UNLIKELY (nalu.datanalu.offset & 0x80)) { + GST_WARNING_OBJECT (h266parse, "NAL has forbidden_zero_bit set"); + /* Keep any complete NALs collected before this malformed one. */ + goto broken; + } + + h266parse->have_vcl_in_frame |= gst_h266_parse_nal_is_vcl (&nalu); + if (gst_h266_parse_collect_nal (h266parse, data, size, &nalu)) { /* complete current frame, if it exist */ if (current_off > 0) { @@ -2286,7 +2325,18 @@ fps_den = sps->fps_den; } - if (interlaced_mode == GST_H266_PARSE_INTERLACED_ONLY) { + /* The timing information values are 32-bit unsigned in the bitstream, + * so they can exceed the range of the gint used for the framerate. + * Such values are not a valid framerate and the fraction maths has + * undefined behaviour for them; treat them as unknown. */ + if (fps_num <= 0 || fps_den <= 0) { + if (fps_num != 0 || fps_den != 1) { + GST_INFO_OBJECT (h266parse, "Invalid framerate %d/%d from timing " + "information; using 0/1", fps_num, fps_den); + } + fps_num = 0; + fps_den = 1; + } else if (interlaced_mode == GST_H266_PARSE_INTERLACED_ONLY) { gint new_fps_num, new_fps_den; if (!gst_util_fraction_multiply (fps_num, fps_den, 1, 2, &new_fps_num, @@ -3076,6 +3126,9 @@ gst_h266_parse_update_src_caps (h266parse, NULL); + if (!h266parse->have_vcl_in_frame) + GST_BUFFER_DURATION (buffer) = 0; + if (h266parse->keyframe) GST_BUFFER_FLAG_UNSET (buffer, GST_BUFFER_FLAG_DELTA_UNIT); else
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/gst/videoparsers/gsth266parse.h -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/gst/videoparsers/gsth266parse.h
Changed
@@ -96,6 +96,7 @@ gboolean have_vps_in_frame; gboolean have_sps_in_frame; gboolean have_pps_in_frame; + gboolean have_vcl_in_frame; gboolean first_frame;
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/gst/videoparsers/gstmpeg4videoparse.c -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/gst/videoparsers/gstmpeg4videoparse.c
Changed
@@ -362,16 +362,25 @@ case GST_MPEG4_VISUAL_OBJ_SEQ_START: GST_LOG_OBJECT (mp4vparse, "Visual Sequence Start"); mp4vparse->config_found = TRUE; - if (packet->size > 1) { - mp4vparse->profile = - gst_codec_utils_mpeg4video_get_profile (packet->data + - packet->offset + 1, packet->size - 1); - mp4vparse->level = - gst_codec_utils_mpeg4video_get_level (packet->data + - packet->offset + 1, packet->size - 1); - } else { - GST_WARNING_OBJECT (mp4vparse, - "VOS packet too short to extract profile/level"); + { + /* packet->size is G_MAXUINT when no terminating start code was + * found, meaning the packet data runs to the end of the buffer. + * Clamp to what is actually readable: packet->offset is always + * <= size - 1, so avail cannot wrap. */ + gsize avail = size - packet->offset - 1; + gsize len = + packet->size == G_MAXUINT ? avail : MIN (avail, packet->size - 1); + if (len > 0) { + mp4vparse->profile = + gst_codec_utils_mpeg4video_get_profile (packet->data + + packet->offset + 1, len); + mp4vparse->level = + gst_codec_utils_mpeg4video_get_level (packet->data + + packet->offset + 1, len); + } else { + GST_WARNING_OBJECT (mp4vparse, + "VOS packet too short to extract profile/level"); + } } break; case GST_MPEG4_VISUAL_OBJ: @@ -876,8 +885,14 @@ mp4vparse->vol_offset = packet.offset; else if (packet.type == GST_MPEG4_VISUAL_OBJ) { + /* packet.size is G_MAXUINT when no terminating start code was + * found, meaning the packet data runs to the end of the buffer. + * Clamp to what is actually readable: packet.offset is always + * <= size - 1, so avail cannot wrap. */ + gsize avail = size - packet.offset; + gsize len = packet.size == G_MAXUINT ? avail : MIN (avail, packet.size); gst_mpeg4_parse_visual_object (&mp4vparse->vo, NULL, - data + packet.offset, MIN (packet.size, size)); + data + packet.offset, len); mp4vparse->vo_found = TRUE; }
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/gst/videoparsers/gstvc1parse.c -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/gst/videoparsers/gstvc1parse.c
Changed
@@ -289,6 +289,8 @@ gst_buffer_replace (&vc1parse->seq_layer_buffer, NULL); gst_buffer_replace (&vc1parse->seq_hdr_buffer, NULL); gst_buffer_replace (&vc1parse->entrypoint_buffer, NULL); + memset (&vc1parse->seq_layer, 0, sizeof (vc1parse->seq_layer)); + memset (&vc1parse->seq_hdr, 0, sizeof (vc1parse->seq_hdr)); vc1parse->seq_layer_sent = FALSE; vc1parse->frame_layer_first_frame_sent = FALSE; @@ -1468,8 +1470,6 @@ goto done; } - memset (&flayer, 0, sizeof (flayer)); - pres = gst_vc1_parse_frame_layer (data, size, &flayer); if (pres != GST_VC1_PARSER_OK) { @@ -2075,7 +2075,6 @@ g_assert (gst_buffer_get_size (buf) >= offset + size); gst_buffer_replace (&vc1parse->seq_hdr_buffer, NULL); - memset (&vc1parse->seq_hdr, 0, sizeof (vc1parse->seq_hdr)); gst_buffer_map (buf, &minfo, GST_MAP_READ); pres = @@ -2207,7 +2206,6 @@ g_assert (gst_buffer_get_size (buf) >= offset + size); gst_buffer_replace (&vc1parse->seq_layer_buffer, NULL); - memset (&vc1parse->seq_layer, 0, sizeof (vc1parse->seq_layer)); gst_buffer_map (buf, &minfo, GST_MAP_READ); pres =
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/gst/videoparsers/gstvideoparseutils.c -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/gst/videoparsers/gstvideoparseutils.c
Changed
@@ -505,9 +505,14 @@ memcpy (&msg.uuid, uuid, 16); - msg.size = gst_byte_reader_get_size (br); - if (!gst_byte_reader_dup_data (br, msg.size, &msg.data)) { - g_return_if_reached (); + msg.size = gst_byte_reader_get_remaining (br); + msg.data = NULL; + /* An empty payload must still be recorded (with NULL data); calling + * dup_data() on it would memcpy from a NULL pointer. */ + if (msg.size > 0 && !gst_byte_reader_dup_data (br, msg.size, &msg.data)) { + GST_ERROR_OBJECT (elt, + "Failed to duplicate user data of size %" G_GSIZE_FORMAT, msg.size); + return; } if (user_data->messages == NULL) {
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/gst/videoparsers/gstvp9parse.c -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/gst/videoparsers/gstvp9parse.c
Changed
@@ -542,6 +542,12 @@ guint32 frame_size; frame_size = superframe_info.frame_sizesi; + if (G_UNLIKELY (frame_size > map.size - offset)) { + GST_WARNING_OBJECT (self, + "Superframe index claims a frame past the end of the buffer"); + parse_res = GST_VP9_PARSER_ERROR; + break; + } parse_res = gst_vp9_parser_parse_frame_header (self->parser, &frame_hdr, map.data + offset, frame_size);
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/gst/videoparsers/h263parse.c -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/gst/videoparsers/h263parse.c
Changed
@@ -319,6 +319,10 @@ if (!gst_bit_reader_get_bits_uint8 (&br, &temp8, 8)) goto more; GST_DEBUG (" Custom PCF is present (%d)", (int) temp8); + if ((temp8 & 0x7f) == 0) { + GST_WARNING ("Invalid custom PCF code 0"); + goto beach; + } params->pcfnum = gst_util_uint64_scale_int (1800000, 1, temp8 & 0x7f); params->pcfdenom = (temp8 & 0x80) ? 1001 : 1000; /* 5.1.8 ETR : Extended Temp8oral Reference (2bits) */
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/gst/vmnc/vmncdec.c -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/gst/vmnc/vmncdec.c
Changed
@@ -45,6 +45,10 @@ GstEvent * event); #define GST_CAT_DEFAULT vmnc_debug + +/* Maximum screen size we allow for the screen dimensions to avoid allocating + * too much memory with malicious streams. */ +#define VMNC_MAX_DIMENSION 8192 GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT); #define RFB_GET_UINT32(ptr) GST_READ_UINT32_BE(ptr) @@ -185,14 +189,24 @@ return ERROR_INSUFFICIENT_DATA; } + /* This function is called twice per rectangle: first while parsing the + * stream to determine the packet boundaries and then again with the + * same bytes to actually decode them. Most of the format state below + * is updated in both passes on purpose, because rectangles later in + * the same packet are validated against it. */ + /* We only compare 13 bytes; ignoring the 3 padding bytes at the end */ if (dec->have_format && memcmp (data, dec->format.descriptor, 13) == 0) { /* Nothing changed, so just exit */ return 16; } - /* Store the whole block for simple comparison later */ - memcpy (dec->format.descriptor, data, 16); + /* Store the whole block for simple comparison later. Only the decode + * pass actually commits it: committing while parsing would make the later + * decode pass skip the initialisation below and leave the image data + * unallocated. */ + if (decode) + memcpy (dec->format.descriptor, data, 16); if (rect->x != 0 || rect->y != 0) { GST_WARNING_OBJECT (dec, "Bad WMVi rect: wrong coordinates"); @@ -215,6 +229,12 @@ return ERROR_INVALID; } + if (data10 >= 32 || data11 >= 32 || data12 >= 32) { + GST_WARNING_OBJECT (dec, "Bad color shift values: %d/%d/%d", + data10, data11, data12); + return ERROR_INVALID; + } + dec->format.bytes_per_pixel = bpp / 8; dec->format.width = rect->width; dec->format.height = rect->height; @@ -264,6 +284,21 @@ return ERROR_INVALID; } + if (decode) { + if (dec->have_format) { + /* The cursor buffers are allocated with the bytes_per_pixel that were in + * use when they were allocated, but render_colour_cursor() indexes them + * with the current bytes_per_pixel. We have to drop the cursors until a + * new WMVd arrives. */ + GST_DEBUG_OBJECT (dec, "Format changed, dropping cursor"); + g_free (dec->cursor.cursordata); + g_free (dec->cursor.cursormask); + dec->cursor.cursordata = NULL; + dec->cursor.cursormask = NULL; + } + dec->cursor.visible = FALSE; + } + dec->have_format = TRUE; if (!decode) { GST_LOG_OBJECT (dec, "Parsing, not setting caps"); @@ -275,13 +310,12 @@ rect->width, rect->height, dec->input_state); gst_video_codec_state_unref (state); + dec->format.stride = + GST_ROUND_UP_4 (dec->format.width * dec->format.bytes_per_pixel); g_free (dec->imagedata); - dec->imagedata = g_malloc0 (dec->format.width * dec->format.height * - dec->format.bytes_per_pixel); + dec->imagedata = g_malloc0 (dec->format.stride * dec->format.height); GST_DEBUG_OBJECT (dec, "Allocated image data at %p", dec->imagedata); - dec->format.stride = dec->format.width * dec->format.bytes_per_pixel; - return 16; } @@ -293,9 +327,11 @@ guint8 *dstraw = data + dec->format.stride * y + dec->format.bytes_per_pixel * x; guint8 *srcraw = dec->cursor.cursordata + - dec->cursor.width * dec->format.bytes_per_pixel * off_y; + dec->cursor.width * dec->format.bytes_per_pixel * off_y + + dec->format.bytes_per_pixel * off_x; guint8 *maskraw = dec->cursor.cursormask + - dec->cursor.width * dec->format.bytes_per_pixel * off_y; + dec->cursor.width * dec->format.bytes_per_pixel * off_y + + dec->format.bytes_per_pixel * off_x; /* Boundchecking done by caller; this is just the renderer inner loop */ if (dec->format.bytes_per_pixel == 1) { @@ -307,7 +343,7 @@ for (j = 0; j < width; j++) { dstj = (dstj & srcj) ^ maskj; } - dst += dec->format.width; + dst += dec->format.stride; src += dec->cursor.width; mask += dec->cursor.width; } @@ -320,7 +356,7 @@ for (j = 0; j < width; j++) { dstj = (dstj & srcj) ^ maskj; } - dst += dec->format.width; + dst += dec->format.stride / 2; src += dec->cursor.width; mask += dec->cursor.width; } @@ -333,7 +369,7 @@ for (j = 0; j < width; j++) { dstj = (dstj & srcj) ^ maskj; } - dst += dec->format.width; + dst += dec->format.stride / 4; src += dec->cursor.width; mask += dec->cursor.width; } @@ -481,7 +517,7 @@ return 2; flags = RFB_GET_UINT16 (data); - dec->cursor.visible = flags & 0x01; + dec->cursor.visible = (flags & 0x01) && dec->cursor.cursordata != NULL; return 2; } @@ -567,7 +603,12 @@ dst = dec->imagedata + dec->format.stride * (y + i) + dec->format.bytes_per_pixel * x; for (j = 0; j < width; j++) { - memcpy (dst, &colour, dec->format.bytes_per_pixel); + if (dec->format.bytes_per_pixel == 1) + dst0 = colour; + else if (dec->format.bytes_per_pixel == 2) + GST_WRITE_UINT16_LE (dst, (guint16) colour); + else + GST_WRITE_UINT32_LE (dst, colour); dst += dec->format.bytes_per_pixel; } } @@ -642,7 +683,6 @@ return 4; } -/* FIXME: data+off might not be properly aligned */ #define READ_PIXEL(pixel, data, off, len) \ if (dec->format.bytes_per_pixel == 1) { \ if (off >= len) \ @@ -651,12 +691,12 @@ } else if (dec->format.bytes_per_pixel == 2) { \ if (off+2 > len) \ return ERROR_INSUFFICIENT_DATA; \ - pixel = (*(guint16 *)(data + off)); \ + pixel = GST_READ_UINT16_LE (data + off); \ off += 2; \ } else { \ if (off+4 > len) \ return ERROR_INSUFFICIENT_DATA; \ - pixel = (*(guint32 *)(data + off)); \ + pixel = GST_READ_UINT32_LE (data + off); \ off += 4; \ } @@ -817,8 +857,9 @@ GST_WARNING_OBJECT (dec, "Rectangle out of range, type %d", r.type); return ERROR_INVALID; } - } else if (r.width > 16384 || r.height > 16384) { - GST_WARNING_OBJECT (dec, "Width or height too high: %ux%u", r.width, + } else if (r.width == 0 || r.height == 0 || + r.width > VMNC_MAX_DIMENSION || r.height > VMNC_MAX_DIMENSION) { + GST_WARNING_OBJECT (dec, "Invalid WMVi dimensions: %ux%u", r.width, r.height); return ERROR_INVALID; }
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/meson.build -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/meson.build
Changed
@@ -1,5 +1,5 @@ project('gst-plugins-bad', 'c', 'cpp', - version : '1.28.8', + version : '1.28.9', meson_version : '>= 1.4', default_options : 'warning_level=1', 'buildtype=debugoptimized',
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/po/gst-plugins-bad-1.0.pot -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/po/gst-plugins-bad-1.0.pot
Changed
@@ -6,9 +6,9 @@ #, fuzzy msgid "" msgstr "" -"Project-Id-Version: gst-plugins-bad-1.28.8\n" +"Project-Id-Version: gst-plugins-bad-1.28.9\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2026-10-08 17:20+0200\n" +"POT-Creation-Date: 2026-11-06 12:54+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" @@ -57,7 +57,7 @@ msgid "Could not open sndfile stream for reading." msgstr "" -#: gst/asfmux/gstasfmux.c:1834 +#: gst/asfmux/gstasfmux.c:1846 msgid "Generated file has a larger preroll time than its streams duration" msgstr ""
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/po/gst-plugins-bad.pot -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/po/gst-plugins-bad.pot
Changed
@@ -6,9 +6,9 @@ #, fuzzy msgid "" msgstr "" -"Project-Id-Version: gst-plugins-bad-1.28.8\n" +"Project-Id-Version: gst-plugins-bad-1.28.9\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2026-10-08 17:20+0200\n" +"POT-Creation-Date: 2026-11-06 12:54+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" @@ -57,7 +57,7 @@ msgid "Could not open sndfile stream for reading." msgstr "" -#: gst/asfmux/gstasfmux.c:1834 +#: gst/asfmux/gstasfmux.c:1846 msgid "Generated file has a larger preroll time than its streams duration" msgstr ""
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/release-notes-1.28.md -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/release-notes-1.28.md
Changed
@@ -1,26 +1,55 @@ -# GStreamer 1.28 Release Notes +--- +title: "GStreamer 1.28 release notes" +series: "1.28" +aliases: + - /releases/1.28/release-notes-1.28.html +status: stable +weight: 972 +date: 2026-11-06 +first_release: 2026-01-27 +last_release: 2026-11-06 +versions: + - version: "1.28.9" + date: 2026-11-06 + - version: "1.28.8" + date: 2026-10-08 + - version: "1.28.7" + date: 2026-09-07 + - version: "1.28.6" + date: 2026-08-05 + - version: "1.28.5" + date: 2026-07-08 + - version: "1.28.4" + date: 2026-06-12 + - version: "1.28.3" + date: 2026-05-11 + - version: "1.28.2" + date: 2026-04-07 + - version: "1.28.1" + date: 2026-02-26 + - version: "1.28.0" + date: 2026-01-27 +--- GStreamer 1.28.0 was originally released on 27 January 2026. -The latest bug-fix release in the stable 1.28 series is 1.28.8(#1.28.8) and was released on 08 October 2026. +The latest bug-fix release in the stable 1.28 series is 1.28.9(#1.28.9) and was released on 06 November 2026. See https://gstreamer.freedesktop.org/releases/1.28/latest for the latest version of this document. -*Last updated: Thursday 08 October 2026, 17:00 UTC (log)gitlog* +*Last updated: Friday 06 November 2026, 10:00 UTC (log)gitlog* latest: https://gstreamer.freedesktop.org/releases/1.28/ -gitlog: https://gitlab.freedesktop.org/gstreamer/www/commits/main/src/htdocs/releases/1.28/release-notes-1.28.md +gitlog: https://gitlab.freedesktop.org/gstreamer/www/commits/main/content/releases/1.28/_index.md -<a id="introduction"></a> -## Introduction +## Introduction {#introduction} The GStreamer team is proud to announce a new major feature release in the stable 1.x API series of your favourite cross-platform multimedia framework! As always, this release is again packed with many new features, bug fixes, and other improvements. -<a id="highlights"></a> -## Highlights +## Highlights {#highlights} - AMD HIP plugin and integration helper library - Vulkan Video AV1 and VP9 decoding, H.264 encoding, and 10-bit support for H.265 decoder @@ -71,11 +100,9 @@ - Lots of new plugins, features, performance improvements and bug fixes - Countless bug fixes, build fixes, memory leak fixes, and other stability and reliability improvements -<a id="major-changes"></a> -## Major new features and changes +## Major new features and changes {#major-changes} -<a id="hip"></a> -### AMD HIP plugin and integration library +### AMD HIP plugin and integration library {#hip} - HIP (formerly known as Heterogeneous-computing Interface for Portability) is AMD’s GPU programming API that enables portable, CUDA-like development across both AMD and @@ -105,8 +132,7 @@ gstconf-hip: https://gstconf.ubicast.tv/videos/bringing-amd-hip-into-gstreamer/ devlog-hip: https://centricular.com/devlog/2025-07/amd-hip-integration/ -<a id="lvecv"></a> -### Low Complexity Enhancement Video Coding (LCEVC) support for H.265 and H.266 +### Low Complexity Enhancement Video Coding (LCEVC) support for H.265 and H.266 {#lvecv} - LCEVClcevc is a codec that provides an enhancement layer on top of another codec such as H.264 for example. It is standardised as MPEG-5 Part 2. @@ -119,8 +145,7 @@ lcevc: https://www.lcevc.org -<a id="closedcaptions"></a> -### Closed captions and text handling improvements +### Closed captions and text handling improvements {#closedcaptions} - **cea708overlay**: suport non-relative positioning for streams with CCs that do not have relative positions. Instead of displaying them at the @@ -139,8 +164,7 @@ - Also see SMPTE ST-2038 metadata section below. -<a id="stt-translations-and-speech-synthesis"></a> -### Speech to Text, Translation and Speech Synthesis +### Speech to Text, Translation and Speech Synthesis {#stt-translations-and-speech-synthesis} - New **audio source separation element based on demucs** in Rust. This is useful to separate speech from background audio before running speech to text transcription, @@ -175,8 +199,7 @@ can be used to accumulate words and punctuation into complete sentences (or sentence fragments) for synthesis and / or translation by further elements downstream. -<a id="adaptive-streaming"></a> -### HLS DASH adaptive streaming improvements +### HLS DASH adaptive streaming improvements {#adaptive-streaming} - Reverse playback, seeking and stream selection fixes in the HLS/DASH clients. @@ -186,15 +209,13 @@ in which case the media playlist will use byte range tags for each chunk whilst always referencing the same single media file. This can be useful for VOD use cases. -<a id="playback"></a> -### decodebin3 and playbin3 improvements +### decodebin3 and playbin3 improvements {#playback} - **decodebin3** now has a separate pad template for **metadata streams** and considers KLV, ID3 PES streams and ST-2038 ancillary streams as raw formats for meta streams. This comes also with a new dedicated `GST_STREAM_TYPE_METADATA` stream type in the stream collection. -<a id="eflv"></a> -### Enhanced RTMP and multitrack audio/video support in FLV +### Enhanced RTMP and multitrack audio/video support in FLV {#eflv} - The FLV container used for RTMP streaming is fairly old and limited in terms of features: It only supports one audio and one video track, and also only a very limited number of @@ -213,8 +234,7 @@ eflvmux: https://gstreamer.freedesktop.org/documentation/flv/eflvmux.html?gi-language=c#eflvmux-page eflv-devlog: https://centricular.com/devlog/2025-11/Multitrack-Audio-Capability-in-FLV/ -<a id="mpeg-ts"></a> -### MPEG-TS container format improvements +### MPEG-TS container format improvements {#mpeg-ts} - The **MPEG-TS demuxer** gained a "skew-corrections" **property that allows disabling of skew corrections**, which are done by default for live inputs to make sure @@ -240,16 +260,14 @@ apple-timed-metadata-spec: https://developer.apple.com/library/archive/documentation/AudioVideo/Conceptual/HTTP_Live_Streaming_Metadata_Spec/2/2.html -<a id="matroska"></a> -### Matroska container format improvements +### Matroska container format improvements {#matroska} - **matroskademux** now supports relative position cues in the seek table and also had its maximum block size restrictions updated so that it can support uncompressed video frames also in 4k UHD resolution and higher bit depths. -<a id="isomp4"></a> -### ISO MP4 container format improvements +### ISO MP4 container format improvements {#isomp4} - **mp4mux** now supports E-AC3 muxing @@ -262,8 +280,7 @@ - The **isomp4mux**, **isofmp4mux** and related elements were merged into a single **isobmff** plugin, which allows sharing more code. As part of this, codec support was consolidated between the two. -<a id="mxf"></a> -### MXF container format improvements +### MXF container format improvements {#mxf} - The MXF muxer and demuxer gained **support for non-closed-caption VANC ancillary metdata**: @@ -282,8 +299,7 @@ We also now support both 8 and 10-bit VANC data when reading from MXF. -<a id="mpeg-h"></a> -### MPEG-H audio support +### MPEG-H audio support {#mpeg-h} - New **MPEG-H audio decoding** plugin based on the Fraunhofer MPEG-H decoder implementation plus MP4 demuxing support @@ -301,8 +317,7 @@ - decodebin3 now treats ST-2038 metadata streams as a "raw metadata format" and exposes those streams as `GST_STREAM_TYPE_METADATA`. -<a id="analytics"></a> -### Analytics +### Analytics {#analytics} This release introduces a major improvement in how analytics pipelines are built, moving away from manual configuration toward a fully negotiated analytics pipeline. @@ -351,8 +366,7 @@ burnyoloxinference: https://gstreamer.freedesktop.org/documentation/burn/index.html?gi-language=c#burnyoloxinference-page yoloxtensordec: https://gstreamer.freedesktop.org/documentation/rsanalytics/yoloxtensordec.html?gi-language=c#yoloxtensordec-page -<a id="vulkan"></a> -### Vulkan integration enhancements +### Vulkan integration enhancements {#vulkan} - The Vulkan Video encoders and decoders now dynamically generate their pad template caps at runtime instead of hardcoding them, so they more @@ -364,8 +378,7 @@ - The **Vulkan H.265 decoder** now also supports **10-bit** depth -<a id="opengl"></a> -### OpenGL integration enhancements +### OpenGL integration enhancements {#opengl} - Implement keyboard, mouse, and scroll wheel navigation event handling for the OpenGL Cocoa backend. @@ -373,8 +386,7 @@ - Added support for the `NV24` and `Y444_12` pixel formats. The latter is used by certain HEVC decoders for 12-bit non-subsampled profiles. -<a id="udmabuf"></a> -### udmabuf allocator with glupload support +### udmabuf allocator with glupload support {#udmabuf} - Implement a **udmabuf-based memory allocator for user-space mappable dmabufs**. @@ -385,8 +397,7 @@ - **gtk4paintablesink**: Similar to `glupload`, this now proposes the udmabuf memory allocator to upstream which can reduce memory copies and improve performance with certain software decoders. -<a id="wayland"></a> -### Wayland integration +### Wayland integration {#wayland} - Added **basic colorimetry support** @@ -400,15 +411,13 @@ - New **"fullscreen-output"** and **"force-aspect-ratio" properties** -<a id="qt"></a> -### Qt5 + Qt6 QML integration improvements +### Qt5 + Qt6 QML integration improvements {#qt} - New **Qt6 QML qml6 render source element** - **qml6gloverlay**: support directly passing a QQuickItem for QML the render tree -<a id="gtk"></a> -### GTK4 integration improvements +### GTK4 integration improvements {#gtk} - **gtk4paintablesink**: Added YCbCr memory texture formats and improve color-state fallbacks. The sink will also propose a **udmabuf** buffer pool @@ -416,8 +425,7 @@ memory by GL/Vulkan or the compositor. Plus many other improvements which have also been backported into the 0.14 branch. -<a id="cuda-nvcodec"></a> -### CUDA / NVCODEC integration and feature additions +### CUDA / NVCODEC integration and feature additions {#cuda-nvcodec} - **cudacompositor**, **cudaconvert** and its variants gained **crop meta support** @@ -433,13 +441,11 @@ - **nvdsdewarp**: performance improvements and support for output resizing support, along with a new "add-borders" property. -<a id="aja-decklink"></a> -### Capture and playout cards support +### Capture and playout cards support {#aja-decklink} - **Blackmagic Decklink** elements gained support for **capturing and outputting all types of VANC via GstAncillaryMeta** -<a id="rtp"></a> -### RTP and RTSP stack improvements +### RTP and RTSP stack improvements {#rtp} - **rtspsrc** now sends RTSP keepalives also in TCP/interleaved modes. This fixes problems with some cameras that don't see the RTCP traffic as sufficient proof of liveness, @@ -459,8 +465,7 @@ - Support for "multi-time aggregation packets" (MTAP) in the H264 RTP depayloader `rtph264depay`. -<a id="webrtc"></a> -### WebRTC improvements +### WebRTC improvements {#webrtc} - **webrtcbin** and **GstWebRTC library** improvements: @@ -484,8 +489,7 @@ widely used in browsers and SFUs, and some servers such as the ones using BouncyCastle only accept certificates signed with ECDSA. -<a id="new-cplusplus-bindings"></a> -### New GStreamer C++ bindings +### New GStreamer C++ bindings {#new-cplusplus-bindings} The old GStreamer C++ bindings (gstreamermm and qt-gstreamer) have been unmaintained for a long time, leaving C++ developers only with the option to use the GStreamer C API. @@ -507,8 +511,7 @@ peel-examples: https://gitlab.freedesktop.org/slomo/gstreamer-peel-examples -<a id="new-plugins"></a> -## New elements and plugins +## New elements and plugins {#new-plugins} - Many exciting **new Rust elements**, see Rust section below. @@ -521,8 +524,7 @@ - Many other new elements mentioned in other sections (e.g. CUDA, NVCODEC, D3D12, Speech, AMD HIP, Rust etc.) -<a id="new-element-features"></a> -## New element features and additions +## New element features and additions {#new-element-features} - The **AWS S3 sink and source** elements now support S3 compatible URI schemes. @@ -570,8 +572,7 @@ - **videorate**'s formerly defunct "new-pref" property was revived for better control which frame to prefer for output in case of caps changes. -<a id="plugin-library-moves"></a> -## Plugin and library moves and renames +## Plugin and library moves and renames {#plugin-library-moves} - The `y4mdec` plugin moved from gst-plugins-bad into gst-plugins-good and was merged with the existing `y4menc` there into a single `y4m` plugin @@ -580,8 +581,7 @@ - The `fmp4` and `mp4` plugins in the Rust plugins set were merged into a single `isobmff` plugin. -<a id="plugin-element-deprecations"></a> -## Plugin and element deprecations +## Plugin and element deprecations {#plugin-element-deprecations} - The old librtmp-based **rtmpsrc** and **rtmpsink** elements are deprecated are scheduled for removal in the next release cycle. Use the **rtmp2src** @@ -599,8 +599,7 @@ distros that also ship the FFmpeg-based decoder out of the box stop shipping the mpeg2dec plugin now or reduce its rank to `GST_RANK_NONE`. -<a id="plugin-element-removals"></a> -## Plugin and element removals +## Plugin and element removals {#plugin-element-removals} - The **cc708overlay** element has been removed. It is replaced by the cea708overlaycea708overlay element from the `rsclosedcaption` plugin @@ -613,11 +612,9 @@ to awss3src and awss3sink in 2022, but had been kept around for a while so applications had time to move to the new name space. -<a id="new-api"></a> -## Miscellaneous API additions +## Miscellaneous API additions {#new-api} -<a id="core-api"></a> -### GStreamer Core +### GStreamer Core {#core-api} - `gst_call_async()`gst-call-async and `gst_object_call_async()`gst-object-call-async are more generic and convenient replacements for `gst_element_call_async()` @@ -681,8 +678,7 @@ gst_object_get_toplevel: https://gstreamer.freedesktop.org/documentation/gstreamer/gstobject.html?gi-language=c#gst_object_get_toplevel gst_value_hash: https://gstreamer.freedesktop.org/documentation/gstreamer/gstvalue.html?gi-language=c#gst_value_hash -<a id="meta-factory"></a> -#### GstMetaFactory to dynamically register metas +#### GstMetaFactory to dynamically register metas {#meta-factory} - `gst_meta_factory_register()`meta-factory-register allows to dynamically register metas and store them in the registry by name. This is useful in combination with the `GstMeta` @@ -700,31 +696,26 @@ meta-factory-register: https://gstreamer.freedesktop.org/documentation/gstreamer/gstmetafactory.html?gi-language=c#gst_meta_factory_register -<a id="gstapp"></a> -### App Sink and Source Library +### App Sink and Source Library {#gstapp} - **appsrc** and **appsink** gained support for a more bindings-friendly "simple callbacks" API that can be used instead of GObject signals (which have considerable overhead) or the normal callbacks API (which couldn't be used from most bindings). -<a id="gstaudio"></a> -### Audio Library +### Audio Library {#gstaudio} - added **support for 20-bit PCM audio stored in 32-bit containers**, both signed (**`S20_32`**) and unsigned (**`U20_32`**), each in little-endian and big-endian variants. -<a id="gstpbutils"></a> -### Plugins Base Utils Library +### Plugins Base Utils Library {#gstpbutils} - Many minor improvements. -<a id="gsttag"></a> -### Tag Library +### Tag Library {#gsttag} - Vorbis comments: parse EBU R128 tags -<a id="gstvideo"></a> -### Video Library and OpenGL Library +### Video Library and OpenGL Library {#gstvideo} - Add DRM equivalents for various 10/12/16 bit SW-decoders formats @@ -750,13 +741,11 @@ - Add 10-bit 4:2:2 **`NV16_10LE40`** format, which is a fully-packed variant of `NV16_10LE32` and also known as `NV20` and is produced by Rockchip `rkvdec` decoders. -<a id="gstplay"></a> -### GstPlay Library +### GstPlay Library {#gstplay} - GstPlay: Add **support for gapless looping** -<a id="optimisations"></a> -## Miscellaneous performance, latency and memory optimisations +## Miscellaneous performance, latency and memory optimisations {#optimisations} - New **task pool GstContext to share a thread pool amongst elements in a pipeline for better resource management and performance**, especially for video conversion and compositing. This is currently only @@ -780,15 +769,13 @@ - As always there have been plenty of performance, latency and memory optimisations all over the place. -<a id="misc-changes"></a> -## Miscellaneous other changes and enhancements +## Miscellaneous other changes and enhancements {#misc-changes} - The **ALSA device provider** now supports enumerating virtual PCM sinks - The **ASIO** device monitor can now detect dynamically added and removed devices by monitoring USB events. -<a id="tracing"></a> -## Tracing framework and debugging improvements +## Tracing framework and debugging improvements {#tracing} - There are **new hooks to track when buffers are queued or dequeued from** **buffer pools** in the tracing system. @@ -831,20 +818,17 @@ spammy, please feel free to file an issue in GitLab so we can see if it would make sense to use the new API there. -<a id="tools"></a> -## Tools +## Tools {#tools} - **gst-inspect-1.0** now shows the type of each field when it prints caps and also pretty-prints tensor caps. -<a id="ffmpeg"></a> -## GStreamer FFmpeg wrapper +## GStreamer FFmpeg wrapper {#ffmpeg} - The avdec video decoders have seen many improvements and fixes for their buffer pool and allocation query handling. -<a id="rtsp"></a> -## GStreamer RTSP server +## GStreamer RTSP server {#rtsp} - rtsp-client: Add a "pre-closed" signal which provides a way for an application to be notified when a connection is closed, before the client's sessions are @@ -858,8 +842,7 @@ - **rtspclientsink** now errors out on timeout. -<a id="vaapi"></a> -## VA-API integration +## VA-API integration {#vaapi} ### VA plugin for Hardware-Accelerated Video Encoding and Decoding on Intel/AMD @@ -876,15 +859,13 @@ <!-- -<a id="v4l2"></a> -## GStreamer Video4Linux2 support +## GStreamer Video4Linux2 support {#v4l2} - Nothing major? --> -<a id="ges"></a> -## GStreamer Editing Services and NLE +## GStreamer Editing Services and NLE {#ges} - **Task Pool Context Support**: GESPipeline now supports task pool context handling for better resource management. It automatically creates and manages @@ -921,9 +902,7 @@ non-square pixel aspect ratios, and control binding handling. -<a id="validate"></a> - -## GStreamer validate +## GStreamer validate {#validate} - **New `check-last-frame-qrcode` action type**: New action type (from the Rust validate plugin) to validate QR code content in video frames. Supports exact @@ -953,8 +932,7 @@ - Various bug fixes for scenario handling, memory leaks, and improved backward compatibility with GLib 2.64. -<a id="python"></a> -## GStreamer Python Bindings +## GStreamer Python Bindings {#python} gst-python is an extension of the regular GStreamer Python bindings based on gobject-introspection information and PyGObject, and provides "syntactic sugar" @@ -976,13 +954,11 @@ - Breaking change: `Gst.ElementFactory.make` and `Gst.Bin.make_and_add` now raise `Gst.MissingPluginError` exception when the element is not found. -<a id="csharp"></a> -## GStreamer C# Bindings +## GStreamer C# Bindings {#csharp} - The C# bindings have been updated for the latest GStreamer 1.28 APIs. -<a id="rust"></a> -## GStreamer Rust Bindings and Rust Plugins +## GStreamer Rust Bindings and Rust Plugins {#rust} The GStreamer Rust bindings and plugins are released separately with a different release cadence that's tied to the gtk-rs release cycle. @@ -1001,8 +977,7 @@ Rust plugins can be used from any programming language. To applications, they look just like a plugin written in C or C++. -<a id="rust-elements"></a> -### New Rust elements +### New Rust elements {#rust-elements} - New **icecastsink element with AAC support** that is similar in functionality to the existing shout2send element but also supports AAC, which upstream @@ -1012,7 +987,7 @@ - New **Deepgram speech-to-text transcription** plugin, **ElevenLabs voice cloning element** and **textaccumulate** element. See - <a href="#stt-translations-and-speech-synthesis">Speech to Text, Translation and Speech Synthesis</a> + Speech to Text, Translation and Speech Synthesis(#stt-translations-and-speech-synthesis) section above. - New **analytics combiner and splitter elements** for batch metas (see above). @@ -1030,8 +1005,7 @@ - New **Rust validate plugin** with a **check-last-frame-qrcode action**. <!-- -<a id="rust-other-improvements"></a> -### Other improvements +### Other improvements {#rust-other-improvements} - to be filled in --> @@ -1046,8 +1020,7 @@ rs-changelog: https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/-/blob/main/CHANGELOG.md -<a id="build-and-deps"></a> -## Build and Dependencies +## Build and Dependencies {#build-and-deps} - Meson >= 1.4 is now required for all modules @@ -1099,11 +1072,9 @@ to use. This will be picked up by the `gst-python` and `gst-editing-sevices` subprojects. -<a id="platform-specific"></a> -## Platform-specific changes and improvements +## Platform-specific changes and improvements {#platform-specific} -<a id="android"></a> -### Android +### Android {#android} - **Overhaul hw-accelerated video codecs detection**: @@ -1118,8 +1089,7 @@ a fallback and also rank as `PRIMARY+1` the `c2.android`, `c2.exynos` and `c2.amlogic` audio codecs alongside `OMX.google`, because they are known-good. -<a id="apple"></a> -### Apple macOS and iOS +### Apple macOS and iOS {#apple} - **VP9 and AV1 hardware-accelerated video decoding** support @@ -1128,11 +1098,9 @@ - Implement keyboard, mouse, and scroll wheel navigation event handling for the OpenGL Cocoa backend. -<a id="windows"></a> -### Windows +### Windows {#windows} -<a id="d3d12"></a> -#### GStreamer Direct3D12 integration +#### GStreamer Direct3D12 integration {#d3d12} - New elements: - d3d12interlaced3d12interlace: A Direct3D12 based **interlacing** element @@ -1151,15 +1119,13 @@ d3d12fisheyedewarp: https://gstreamer.freedesktop.org/documentation/d3d12/d3d12fisheyedewarp.html?gi-language=c d3d12remap: https://gstreamer.freedesktop.org/documentation/d3d12/d3d12remap.html?gi-language=c -<a id="win32ipc"></a> -#### Windows inter process communication +#### Windows inter process communication {#win32ipc} - The **Windows IPC plugin gained support for passing generic data** in addition to raw audio/video, and various new properties. It also serialises metas now where that is supported. -<a id="wasapi2"></a> -#### Windows audio +#### Windows audio {#wasapi2} - **wasapi2**: add **support for dynamic audio device switching, exclusive mode and format negotiation**, in addition to device provider improvements and latency enhancements. @@ -1171,16 +1137,14 @@ <!-- -<a id="linux"></a> -### Linux +### Linux {#linux} - Many improvements which are described in other sections. --> -<a id="cerbero"></a> -### Cerbero +### Cerbero {#cerbero} Cerbero is a meta build system used to build GStreamer plus dependencies on platforms where dependencies are not readily available, such as Windows, Android, iOS, and macOS. It is also used to create the GStreamer Python Wheels. @@ -1245,8 +1209,7 @@ - cerbero: Android devices with API level >= 30 cannot play tutorials 4 or 5(https://gitlab.freedesktop.org/gstreamer/cerbero/-/issues/529) -- Fix aimed for 1.28.1 - cerbero: Missing pkg-config for macOS in the Android release(https://gitlab.freedesktop.org/gstreamer/cerbero/-/issues/522) -<a id="docs"></a> -## Documentation improvements +## Documentation improvements {#docs} - Added a **Windows section** to "building from source" page @@ -1256,8 +1219,7 @@ - Updates of the **Machine Learning and Analytics design documentation** and the **GstMeta design docs** -<a id="breaking-changes"></a> -## Possibly Breaking Changes +## Possibly Breaking Changes {#breaking-changes} - The MXF muxer and demuxer used to have direct support for standalone closed caption streams (`closedcaption/x-cea-708`) as ancillary data, but that was removed in favour of more generic @@ -1277,8 +1239,7 @@ raise `Gst.MissingPluginError` exception when the element is not found. -<a id="known-issues"></a> -## Known Issues +## Known Issues {#known-issues} - There are some open issues with the Apple hardware-accelerated AV1 decodingvtdec-av1-issues, which we hope will be fixed in due course. Please let us know if you run into them and can @@ -1293,8 +1254,7 @@ lcevc-issue: https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/4870 -<a id="statistics"></a> -## Statistics +## Statistics {#statistics} - 3548 commits - 1765 Merge requests merged @@ -1308,9 +1268,7 @@ - 249844 lines deleted - 146012 lines added (net) -<a id="contributors"></a> - -## Contributors +## Contributors {#contributors} Aaron Boxer, Abd Razak, Adrian Perez de Castro, Adrien Plazas, Albert Sjolund, Aleix Pol, Alexander Slobodeniuk, Alicia Boya García, @@ -1369,9 +1327,7 @@ usually. The 1.28.x bug-fix releases will be made from the git 1.28 branch, which is a stable release series branch. -<a id="1.28.1"></a> - -### 1.28.1 +### 1.28.1 {#1.28.1} The first 1.28 bug-fix release (1.28.1) was released on 26 February 2026. @@ -1667,9 +1623,7 @@ - List of Merge Requests applied in 1.28.1(https://gitlab.freedesktop.org/groups/gstreamer/-/merge_requests?scope=all&utf8=%E2%9C%93&state=merged&milestone_title=1.28.1) - List of Issues fixed in 1.28.1(https://gitlab.freedesktop.org/groups/gstreamer/-/issues?scope=all&utf8=%E2%9C%93&state=closed&milestone_title=1.28.1) -<a id="1.28.2"></a> - -### 1.28.2 +### 1.28.2 {#1.28.2} The second 1.28 bug-fix release (1.28.2) was released on 07 April 2026. @@ -1944,9 +1898,7 @@ - List of Merge Requests applied in 1.28.2(https://gitlab.freedesktop.org/groups/gstreamer/-/merge_requests?scope=all&utf8=%E2%9C%93&state=merged&milestone_title=1.28.2) - List of Issues fixed in 1.28.2(https://gitlab.freedesktop.org/groups/gstreamer/-/work_items?sort=created_date&state=closed&milestone_title=1.28.2) -<a id="1.28.3"></a> - -### 1.28.3 +### 1.28.3 {#1.28.3} The third 1.28 bug-fix release (1.28.3) was released on 11 May 2026. @@ -2188,9 +2140,7 @@ - List of Merge Requests applied in 1.28.3(https://gitlab.freedesktop.org/groups/gstreamer/-/merge_requests?scope=all&utf8=%E2%9C%93&state=merged&milestone_title=1.28.3) - List of Issues fixed in 1.28.3(https://gitlab.freedesktop.org/groups/gstreamer/-/work_items?scope=all&utf8=%E2%9C%93&state=closed&milestone_title=1.28.3) -<a id="1.28.4"></a> - -### 1.28.4 +### 1.28.4 {#1.28.4} The fourth 1.28 bug-fix release (1.28.4) was released on 12 June 2026. @@ -2384,9 +2334,7 @@ - List of Merge Requests applied in 1.28.4(https://gitlab.freedesktop.org/groups/gstreamer/-/merge_requests?scope=all&utf8=%E2%9C%93&state=merged&milestone_title=1.28.4) - List of Issues fixed in 1.28.4(https://gitlab.freedesktop.org/groups/gstreamer/-/work_items?scope=all&utf8=%E2%9C%93&state=closed&milestone_title=1.28.4) -<a id="1.28.5"></a> - -### 1.28.5 +### 1.28.5 {#1.28.5} The fifth 1.28 bug-fix release (1.28.5) was released on 08 July 2026. @@ -2590,9 +2538,7 @@ - List of Merge Requests applied in 1.28.5(https://gitlab.freedesktop.org/groups/gstreamer/-/merge_requests?scope=all&utf8=%E2%9C%93&state=merged&milestone_title=1.28.5) - List of Issues fixed in 1.28.5(https://gitlab.freedesktop.org/groups/gstreamer/-/work_items?scope=all&utf8=%E2%9C%93&state=closed&milestone_title=1.28.5) -<a id="1.28.6"></a> - -### 1.28.6 +### 1.28.6 {#1.28.6} The sixth 1.28 bug-fix release (1.28.6) was released on 05 August 2026. @@ -2774,9 +2720,7 @@ - List of Merge Requests applied in 1.28.6(https://gitlab.freedesktop.org/groups/gstreamer/-/merge_requests?scope=all&utf8=%E2%9C%93&state=merged&milestone_title=1.28.6) - List of Issues fixed in 1.28.6(https://gitlab.freedesktop.org/groups/gstreamer/-/work_items?scope=all&utf8=%E2%9C%93&state=closed&milestone_title=1.28.6) -<a id="1.28.7"></a> - -### 1.28.7 +### 1.28.7 {#1.28.7} The seventh 1.28 bug-fix release (1.28.7) was released on 07 September 2026. @@ -2941,9 +2885,7 @@ - List of Merge Requests applied in 1.28.7(https://gitlab.freedesktop.org/groups/gstreamer/-/merge_requests?scope=all&utf8=%E2%9C%93&state=merged&milestone_title=1.28.7) - List of Issues fixed in 1.28.7(https://gitlab.freedesktop.org/groups/gstreamer/-/work_items?scope=all&utf8=%E2%9C%93&state=closed&milestone_title=1.28.7) -<a id="1.28.8"></a> - -### 1.28.8 +### 1.28.8 {#1.28.8} The eight 1.28 bug-fix release (1.28.8) was released on 08 October 2026. @@ -3124,6 +3066,256 @@ - List of Merge Requests applied in 1.28.8(https://gitlab.freedesktop.org/groups/gstreamer/-/merge_requests?scope=all&utf8=%E2%9C%93&state=merged&milestone_title=1.28.8) - List of Issues fixed in 1.28.8(https://gitlab.freedesktop.org/groups/gstreamer/-/work_items?scope=all&utf8=%E2%9C%93&state=closed&milestone_title=1.28.8) +### 1.28.9 {#1.28.9} + +The ninth 1.28 bug-fix release (1.28.9) was released on 06 November 2026. + +This release only contains bugfixes and important security fixessecurity. +It *should* be safe to update from 1.28.x and we recommend you do so at your +earliest convenience. + +security: https://gstreamer.freedesktop.org/security/ + +#### Highlighted bugfixes in 1.28.9 + + - Various security fixessecurity and playback fixes + - decodebin3, playbin3: fix assertion that would crash music players with certain files and sources + - qtdemux: fix seeking beyond the end of file in push mode + - flvdemux: don't prematurely EOS on AVC/audio sequence end + - rtspsrc: Reuse non-compliant URL fallback across tracks + - H.264 and H.265 RTP depayloader header extension tracking fixes + - level: Add 24 bits support + - gtk4paintablesink: Mark EGL display as foreign to not terminate it + - amfcodec: fix rate_control (H.265, AV1) and gop_size (H.265) properties + - asio: fix stopping asio element causing crashes + - cuda: Correctly save alpha and blend on property change + - HLS: fix awss3hlssink EXT-X-PROGRAM-DATE-TIME moving at twice the speed of the target duration + - hlssink3: Fix stream writing regression for CMAF and WebVTT sinks + - isobmff: Fix NTP seconds roll-over past 2036 + - Fix gap event regression in MPEG-PS demuxer with certain subtitle streams + - qsv, d3d11, d3d12: Build fixes on latest msys2 environment + - va: do not advertise unsupported formats in encoder caps + - v4l2 video decoder fixes including delay negotiation for H.264 and H.265 for better decodebin2 compatibility + - wayland: output hotplug fixes + - webrtcsink: add support of mpph264enc encoder (rockchip) + - Rust plugins: enable cross-compilation with sysroot in Meson build + - cerbero: update ca-certificates and pip, and fix issue with rolling distro versions + - Various bug fixes, build fixes, memory leak fixes, and other stability and reliability improvements + +#### gstreamer + + - paramspecs: Fix GType name mess with GstParamSpecArray/Fraction(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12915) + - taglist: don't critical when parsing random strings(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12819) + - value: Skip the caps attempt when a bracketed value can't be caps(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12810) + - value: unset the GValue when parsing a value token fails(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12912) + - value: validate int/double/fraction ranges when parsing(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12864) + - doc: Passing size=-1 to gst_buffer_extract_dup() returns all data(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12754) + - baseparse: Don't dereference frame->buffer after a zero-sized finish_frame() and explicitly forbid negative skip values from handle_frame()(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12746) + - base: Avoid memcpy()/memset() with NULL pointers and zero size(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12872) + - ptp: Make sure the ptp-helper tests are compiled and running unless tests are disabled(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12973) + +#### gst-plugins-base + + - appsink: keep queued sticky events across a flush(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12986) + - eagl and vulkan: Remove internal_view from the superview when finalizing(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12975) + - decodebin3 aborts on giostreamsrc + parsebin with ID3-tagged MP3(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/work_items/5181) + - decodebin3: Crash in GstPad playing a MP3 file(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/work_items/4972) + - decodebin3: mq_slot_handle_stream_start: assertion failed: (collection)(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/work_items/4756) + - decodebin3: Null-deref crash in `gst_decodebin_input_link_to_slot` with Strawberry player(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/work_items/4626) + - discoverer: Fix use-after-free when a stream reuses its parent(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12906) + - parsebin: Handle lazy stream-id generation(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12716) + - qsv,d3d11,d3d12: Build fixes on latest msys2 environment(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12757) + - samiparse: Drop already parsed text from the HTML context buffer(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12820) + - samiparse: Fix when encountering unclosed tags to prevent slowdown(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12880) + - udmabuf: Allow disabling via env var(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12843) + - video: fix undefined behaviour on empty unregistered user data meta(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12867) + - video: vbi: reject pixel widths narrower than one conversion group(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12911) + - videoconvertscale: Don't scale in the padding described by GstVideoMeta(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12718) + +#### gst-plugins-good + + - adaptivedemux2: Ensure period stream access is protected by the right mutexes everywhere / Fix recursive scheduler lock double unlocks on stream preparation interruption(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12974) + - adaptivedemux2: Restrict URI schemes in the download helper(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/13002) + - flvdemux: Don't report EOS on AVC/audio sequence end(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12751) + - hlsdemux: Validate PKCS7 padding before unpadding decrypted fragments(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12753) + - imagefreeze: keep the caps across a flush(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12925) + - level: Add 24bits support(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12816) + - mpegaudioparse: Avoid OOB read when looking for Xing header(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12774) + - qml6glsrc: Qt6GLWindow destructor abort due to active render thread callback(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12850) + - qml6glsrc: fix possible race with Qt6GLWindow::onSceneGraphInvalidated(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12795) + - qtdemux: Harden CENC parsing against crafted sample_count(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12781) + - qtdemux: fix seek beyond the end of file in push mode(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12808) + - rtph264depay: Fix out of bounds read in MTAP16/MTAP24 depayloading(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/13003) + - rtph264depay: rtph265depay: Various delayed header extension tracking fixes(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12826) + - rtpsession: fix source use-after-free on DoS protection(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12981) + - rtpvrawdepay: Validate caps before using them(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/13005) + - rtsp: unset response even on error path(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12756) + - rtspsrc: Reuse non-compliant URL fallback across tracks(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12813) + - scaletempo: drop empty buffer instead of outputting 0-sized with no GAP(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12817) + - v4l2: fix non-constant initializer in colorspace_variants(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12920) + - v4l2bufferpool: deactivate other pool on start failure(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12865) + - v4l2bufferpool: fix buffer leak on streamon failure(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12698) + - v4l2dec: fix POLLERR from dec loop(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12921) + - v4l2object: accept any colorimetry on coded OUTPUT caps(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12699) + - v4l2object: providing aligned size when propose allocation(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12935) + - v4l2videodec: Don't cancel pending source change when draining(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12769) + - v4l2videodec: fix codec_data leak(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12823) + - v4l2videodec: race condition between drain and source change(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/work_items/3522) + - v4l2h265dec fails negotiation with H.265 stream using colorimetry=2:3:0:1(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/work_items/5142) + - vpxdec: Implement no-op drain callback(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12768) + +#### gst-plugins-bad + + - amfcodec: fix rate_control(h265, av1) and gop_size (h265) properties(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12723) + - analyticsoverlay: Remove Visualization classifier(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12741) + - androidmedia: Fix drain deadlock when the srcpad loop stops(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12996) + - asfmux: Fix header size calculation for non-BMP characters in string tags(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/13006) + - asfmux: Minor fixes(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12983) + - asio: fix stopping asio element causing crashes(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12777) + - codecparsers, videoparsers: Fix OOB accesses and undefined behaviour found by fuzzing(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12874) + - codecparsers: Fix undefined shift in nal_reader_get_ue(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12771) + - codecparsers: h265: Do not overflow conformance window size(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12899) + - codecparsers: h265: Free SEI payload when parsing fails(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12959) + - codecparsers: h26x: Reject NALs with forbidden_zero_bit set(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12962) + - codecparsers: vp9: Do not read past the end of the frame data(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12806) + - cuda: Correctly save alpha and blend on property change(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12778) + - cudaipc: Release Unix socket server resources on teardown(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12758) + - d3d12h264enc: Various fixes and enhancement(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12682) + - eagl and vulkan: Remove internal_view from the superview when finalizing(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12975) + - faac: support faac >= 2.0 (faac_* API)(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12985) + - festival: check read return value(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/13004) + - h26*parse: Reject malformed NALs with forbidden_zero_bit set(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12767) + - h264 parsing : UB fixes(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12854) + - h264decoder: Fix division by zero on bogus SPS dimensions(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12841) + - h264parse: Don't finish a zero-sized frame when no start code follows(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12746) + - h265parse: only extrapolate duration for vcl nal(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12733) + - h265parse: Fix use of uninitialized HRD parameters(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/13000) + - h265parser: Handle oversized SEI payloads(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12748) + - h266parser: Fix infinite loop parsing picture timing SEI(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12792) + - h266parser: Fix out-of-bounds write when parsing DCI(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12926) + - h266parser: Validate that rectangular slices fit into the tile grid(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12883) + - hlsdemux: Validate PKCS7 padding before unpadding decrypted fragments(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12753) + - ivfparse: Reject frame sizes that overflow the size check(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12907) + - mpeg4videoparse: Clamp VOS length when no terminating start code(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12802) + - mpegdemux: compare to segment position for sending gap updates(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12946) + - mpegts: Various OOB reads and similar(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/13007) + - mpegts: Various fixes(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12919) + - mxf: Fix metadata creation by using g_object_new, not g_type_create_instance(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12852) + - mxfdemux: fix a typo and improve log(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12745) + - mxfdemux: fix out-of-bounds read when looking up delta entry by delta_id(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12998) + - qsv,d3d11,d3d12: Build fixes on latest msys2 environment(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12757) + - rfbsrc: Various fixes(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12972) + - tensordecoders: fix leaks in classifiertensordec(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12860) + - tsdemux: Check AC-3 descriptor length before reading its fields(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12707) + - unixfdsink: Fix race when starting and stopping quickly(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12784) + - v4l2codecs: h264, h265: negotiate with the first picture(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12940) + - v4l2codecs: vp9: Minimize memory allocation(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12922) + - va: do not advertise unsupported formats in encoder caps(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12706) + - va: {vp8,vp9,av1}enc: check the result of gst_va_encode_picture_new()(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12845) + - vc1parser: Zero-initialize parsed structures(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12876) + - video: fix undefined behaviour on empty unregistered user data meta(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12867) + - videoconvertscale: Don't scale in the padding described by GstVideoMeta(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12718) + - vmnc: Drop colour cursor on pixel format change and various other crash fixes(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/13001) + - vmnc: Render the correct cursor part when clipped & don't produce invalid RGB shift masks(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12870) + - vulkan: fix memory leaks in decoders(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12878) + - vulkanh265dec: pass sps_scaling_list_data_present_flag from the SPS(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12732) + - wayland: output hotplug fixes(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12821) + - wpe2: Fix mouse pointer buttons mismatch(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12731) + +#### gst-plugins-ugly + + - No changes + +#### GStreamer Rust plugins + + - aws: Update BehaviorVersion(https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/-/merge_requests/3311) + - aws: putobjectsink: Fix missing content/header properties on the request(https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/-/merge_requests/3376) + - awskvssignaller: fix missing Tokio runtime in start()(https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/-/merge_requests/3315) + - basedepay: fix off-by-one two-byte extension parsing(https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/-/merge_requests/3378) + - deepgram, spotify, webrtc: update webpki-roots to 1.0.10(https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/-/merge_requests/3336) + - gtk4paintablesink: Mark EGL display as foreign to not terminate it(https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/-/merge_requests/3322) + - hlsbasesink: Fix incorrect PDT values with system as PDT reference(https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/-/merge_requests/3320) + - hlssink3: Fix stream write regression for CMAF and WebVTT sinks(https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/-/merge_requests/3345) + - isobmff: Fix NTP seconds roll-over past 2036(https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/-/merge_requests/3288) + - isobmff: elst box must be inside an edts box(https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/-/merge_requests/3342) + - livesync: Avoid subtle timing problems around repeating buffers(https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/-/merge_requests/3343) + - rtpbin2: Couple of minor fixes(https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/-/merge_requests/3367) + - rtspsrc2: Fix UDP receive timeouts(https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/-/merge_requests/3339) + - rtspsrc2: Update mykey(https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/-/merge_requests/3314) + - rtspsrc2: Various SDP related fixes(https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/-/merge_requests/3331) + - transcriberbin: Support older errorignore element(https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/-/merge_requests/3353) + - webrtcsink: add support of mpph264enc (rockchip)(https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/-/merge_requests/3341) + - webrtcsrc: fix deadlock when the ICE connection fails(https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/-/merge_requests/3347) + - update mp4-atom to 0.17(https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/-/merge_requests/3365) + - meson build: Enable cross-compilation with sysroot(https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/-/merge_requests/3375) + +#### gst-libav + + - avviddec: honor decode-only flag from buffers upstream(https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/12879) + +#### gst-rtsp-server + + - No changes + +#### gstreamer-sharp + + - No changes + +#### gst-python + + - No changes + +#### gst-editing-services + + - No changes + +#### gst-devtools, gst-validate + gst-integration-testsuites + + - No changes + +#### gst-examples + + - No changes + +#### gstreamer-docs + + - No changes + +#### Development build environment + + - No changes + +#### Cerbero build tool and packaging changes in 1.28.9 + + - bootstrap: update pip(https://gitlab.freedesktop.org/gstreamer/cerbero/-/merge_requests/2377) + - build-tools: fix break for rolling release(https://gitlab.freedesktop.org/gstreamer/cerbero/-/merge_requests/2375) + - build: Fix symbolication_options changes applying to class instead of instance(https://gitlab.freedesktop.org/gstreamer/cerbero/-/merge_requests/2381) + - ca-certificates: Update to 2026-10-20(https://gitlab.freedesktop.org/gstreamer/cerbero/-/merge_requests/2371) + - cerbero: cache: write cerbero-deps-uploader ssh private key file with unix newlines(https://gitlab.freedesktop.org/gstreamer/cerbero/-/merge_requests/2388) + - openjpeg: don't copy the MSVC redistributables to the Cerbero dist folder(https://gitlab.freedesktop.org/gstreamer/cerbero/-/merge_requests/2384) + +#### Contributors to 1.28.9 + +Albert Sjölund, Alicia Boya García, Amyspark, Andreas Cord-Landwehr, +Azat Nurgaliev, Ben Ashby, Bartel Wilhelm, Benjamin Gaignard, Daeho Ro, +Daniel Golle, Daniel Morin, David Maseda Neira, Detlev Casanova, +Dominique Leroux, Edward Hervey, Fabien Danieau, François Laignel, Haihua Hu, +Ignacio Casal Quinteiro, Jakub Adam, Jan Schmidt, Jens Kleintje, Kushal Arora, +Leo Zhen, L. E. Segovia, Mark Nauwelaerts, Mathieu Duponchelle, Matthew Waters, +Michael Krasnow, Michael Olbrich, Nicolas Dufresne, Nirbheek Chauhan, +Patrick Gansterer, Philippe Normand, Piotr Brzeziński, Qian Hu (胡骞), +Qi Hou, Robert Mader, Ruben Gonzalez, Sanchayan Maity, Sebastian Dröge, +Seungha Yang, Thibault Saunier, Tim-Philipp Müller, Víctor Manuel Jáquez Leal, +Vincent Legrand, Xavier Claessens, Yannis Güdel, + +... and many others who have contributed bug reports, translations, sent +suggestions or helped testing. Thank you all! + +#### List of merge requests and issues fixed in 1.28.9 + +- List of Merge Requests applied in 1.28.9(https://gitlab.freedesktop.org/groups/gstreamer/-/merge_requests?scope=all&utf8=%E2%9C%93&state=merged&milestone_title=1.28.9) +- List of Issues fixed in 1.28.9(https://gitlab.freedesktop.org/groups/gstreamer/-/work_items?scope=all&utf8=%E2%9C%93&state=closed&milestone_title=1.28.9) + ## Schedule for 1.30 Our next major feature release will be 1.30, and 1.29 will be the unstable @@ -3134,6 +3326,8 @@ The schedule for 1.30 is still to be determined, but it will likely be in Q4/2026. +Feature freeze for 1.30 is planned around 1 December 2026. + 1.30 will be backwards-compatible to the stable 1.28, 1.26, 1.24, 1.22, 1.20, 1.18, 1.16, 1.14, 1.12, 1.10, 1.8, 1.6, 1.4, 1.2 and 1.0 release series.
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/scripts/dist-common-files.py -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/scripts/dist-common-files.py
Changed
@@ -42,10 +42,14 @@ # Release notes (instead of NEWS) - could also write it out as NEWS.md print('Copying release notes into dist staging directory ..') - relnotes_src = os.path.join(source_root, '..', '..', 'release-notes', major_minor, f'release-notes-{major_minor}.md') + relnotes_src = os.path.join(source_root, '..', '..', 'release-notes', + major_minor, f'release-notes-{major_minor}.md') with open(relnotes_src, 'r') as f: lines = f.readlines() - if not f'### {project_version}\n' in lines: + if not f' - version: "{project_version}"\n' in lines: + sys.exit( + f'Update {relnotes_src} first, must contain a header entry for {project_version}') + if not f'### {project_version} {{#{project_version}}}\n' in lines: sys.exit(f'Update {relnotes_src} first, must contain a section for {project_version}') if not project_version.endswith('.0'): found = False
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/sys/amfcodec/gstamfav1enc.cpp -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/sys/amfcodec/gstamfav1enc.cpp
Changed
@@ -1288,13 +1288,6 @@ } } - result = comp->Init (surface_format, info->width, info->height); - if (result != AMF_OK) { - GST_ERROR_OBJECT (self, "Failed to init component, result %" - GST_AMF_RESULT_FORMAT, GST_AMF_RESULT_ARGS (result)); - goto error; - } - if (self->rate_control != AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_UNKNOWN) { result = comp->SetProperty (AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD, (amf_int64) self->rate_control); @@ -1305,6 +1298,14 @@ } } + result = comp->Init (surface_format, info->width, info->height); + if (result != AMF_OK) { + GST_ERROR_OBJECT (self, "Failed to init component, result %" + GST_AMF_RESULT_FORMAT, GST_AMF_RESULT_ARGS (result)); + goto error; + } + + /* dynamic properties */ result = comp->GetProperty (AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD, &int64_val); if (result != AMF_OK) {
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/sys/amfcodec/gstamfh265enc.cpp -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/sys/amfcodec/gstamfh265enc.cpp
Changed
@@ -1451,13 +1451,6 @@ } } - result = comp->Init (surface_format, info->width, info->height); - if (result != AMF_OK) { - GST_ERROR_OBJECT (self, "Failed to init component, result %" - GST_AMF_RESULT_FORMAT, GST_AMF_RESULT_ARGS (result)); - goto error; - } - if (self->rate_control != AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_UNKNOWN) { result = comp->SetProperty (AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD, (amf_int64) self->rate_control); @@ -1468,6 +1461,22 @@ } } + result = comp->SetProperty (AMF_VIDEO_ENCODER_HEVC_GOP_SIZE, + (amf_int64) self->gop_size); + if (result != AMF_OK) { + GST_ERROR_OBJECT (self, "Failed to set gop-size, result %" + GST_AMF_RESULT_FORMAT, GST_AMF_RESULT_ARGS (result)); + goto error; + } + + result = comp->Init (surface_format, info->width, info->height); + if (result != AMF_OK) { + GST_ERROR_OBJECT (self, "Failed to init component, result %" + GST_AMF_RESULT_FORMAT, GST_AMF_RESULT_ARGS (result)); + goto error; + } + + /* dynamic properties */ result = comp->GetProperty (AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD, &int64_val); if (result != AMF_OK) { @@ -1544,14 +1553,6 @@ goto error; } - result = comp->SetProperty (AMF_VIDEO_ENCODER_HEVC_GOP_SIZE, - (amf_int64) self->gop_size); - if (result != AMF_OK) { - GST_ERROR_OBJECT (self, "Failed to set gop-size, result %" - GST_AMF_RESULT_FORMAT, GST_AMF_RESULT_ARGS (result)); - goto error; - } - self->property_updated = FALSE; g_mutex_unlock (&self->prop_lock);
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/sys/androidmedia/gstamcaudiodec.c -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/sys/androidmedia/gstamcaudiodec.c
Changed
@@ -1121,6 +1121,11 @@ goto flushing; } + if (self->downstream_flow_ret != GST_FLOW_OK) { + g_clear_error (&err); + goto downstream_error; + } + switch (idx) { case INFO_TRY_AGAIN_LATER: GST_DEBUG_OBJECT (self, "Dequeueing input buffer timed out"); @@ -1329,9 +1334,17 @@ if (gst_amc_codec_queue_input_buffer (self->codec, idx, &buffer_info, &err)) { GST_DEBUG_OBJECT (self, "Waiting until codec is drained"); - g_cond_wait (&self->drain_cond, &self->drain_lock); - GST_DEBUG_OBJECT (self, "Drained codec"); - ret = GST_FLOW_OK; + while (self->draining && self->downstream_flow_ret == GST_FLOW_OK) + g_cond_wait (&self->drain_cond, &self->drain_lock); + + ret = self->downstream_flow_ret; + + if (ret == GST_FLOW_OK) + GST_DEBUG_OBJECT (self, "Drained codec"); + else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) + GST_ERROR_OBJECT (self, "Not drained: %s", gst_flow_get_name (ret)); + else + GST_DEBUG_OBJECT (self, "Not drained: %s", gst_flow_get_name (ret)); } else { GST_ERROR_OBJECT (self, "Failed to queue input buffer"); if (self->flushing) {
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/sys/androidmedia/gstamcvideodec.c -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/sys/androidmedia/gstamcvideodec.c
Changed
@@ -1551,6 +1551,7 @@ g_clear_error (&err); gst_amc_buffer_free (buf); buf = NULL; + self->downstream_flow_ret = flow_ret; goto flow_error; } @@ -2162,6 +2163,11 @@ goto flushing; } + if (self->downstream_flow_ret != GST_FLOW_OK) { + g_clear_error (&err); + goto downstream_error; + } + switch (idx) { case INFO_TRY_AGAIN_LATER: GST_DEBUG_OBJECT (self, "Dequeueing input buffer timed out"); @@ -2379,9 +2385,17 @@ if (gst_amc_codec_queue_input_buffer (self->codec, idx, &buffer_info, &err)) { GST_DEBUG_OBJECT (self, "Waiting until codec is drained"); - g_cond_wait (&self->drain_cond, &self->drain_lock); - GST_DEBUG_OBJECT (self, "Drained codec"); - ret = GST_FLOW_OK; + while (self->draining && self->downstream_flow_ret == GST_FLOW_OK) + g_cond_wait (&self->drain_cond, &self->drain_lock); + + ret = self->downstream_flow_ret; + + if (ret == GST_FLOW_OK) + GST_DEBUG_OBJECT (self, "Drained codec"); + else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) + GST_ERROR_OBJECT (self, "Not drained: %s", gst_flow_get_name (ret)); + else + GST_DEBUG_OBJECT (self, "Not drained: %s", gst_flow_get_name (ret)); } else { GST_ERROR_OBJECT (self, "Failed to queue input buffer"); if (self->flushing) {
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/sys/asio/gstasioobject.cpp -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/sys/asio/gstasioobject.cpp
Changed
@@ -1811,7 +1811,7 @@ g_mutex_lock (&obj->api_lock); cb = g_new0 (GstAsioObjectCallbacksPrivate, 1); cb->callbacks = *callbacks; - cb->callback_id = obj->next_callback_id; + cb->callback_id = obj->next_callback_id++; switch (type) { case GST_ASIO_DEVICE_CLASS_CAPTURE:
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/sys/d3d11/meson.build -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/sys/d3d11/meson.build
Changed
@@ -126,7 +126,7 @@ #include<windows.h> #include<winstring.h> #include<roapi.h> - #include<windows.graphics.capture.h>, + #include<windows.graphics.capture.h> #include<windows.graphics.capture.interop.h> #include<windows.graphics.directx.direct3d11.h> #include<windows.graphics.directx.direct3d11.interop.h> @@ -139,6 +139,14 @@ ComPtr<IGraphicsCaptureSession> session; ComPtr<IGraphicsCaptureSession2> session2; ComPtr<IGraphicsCaptureSession3> session3; + typedef ABI::Windows::Foundation::__FITypedEventHandler_2_Windows__CGraphics__CCapture__CDirect3D11CaptureFramePool_IInspectable_t + IFrameArrivedHandler; + typedef ABI::Windows::Foundation::__FITypedEventHandler_2_Windows__CGraphics__CCapture__CGraphicsCaptureItem_IInspectable_t + IItemClosedHandler; + class WgcHandler : public RuntimeClass<RuntimeClassFlags<ClassicCom>, + FtmBase, IFrameArrivedHandler, IItemClosedHandler> + { + }; ''', name: 'Windows Graphics Capture support in Windows SDK')
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/sys/d3d12/gstd3d12encoder.cpp -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/sys/d3d12/gstd3d12encoder.cpp
Changed
@@ -693,7 +693,6 @@ auto priv = self->priv; const auto info = &priv->input_state->info; GstBuffer *upload = nullptr; - gboolean d3d12_copy = FALSE; auto mem = gst_buffer_peek_memory (buffer, 0); if (gst_is_d3d12_memory (mem)) { @@ -713,8 +712,6 @@ desc.Height >= priv->config.resolution.Height) { return gst_buffer_ref (buffer); } - - d3d12_copy = TRUE; } } @@ -724,113 +721,23 @@ return nullptr; } - if (d3d12_copy) { - std::vector < GstD3D12CopyTextureRegionArgs > copy_args; - auto dmem = GST_D3D12_MEMORY_CAST (mem); - auto src_resource = gst_d3d12_memory_get_resource_handle (dmem); - ComPtr < ID3D12Fence > fence_to_wait; - guint64 fence_val_to_wait = 0; - - gst_d3d12_memory_get_fence (dmem, &fence_to_wait, &fence_val_to_wait); - - dmem = (GstD3D12Memory *) gst_buffer_peek_memory (upload, 0); - auto dst_resource = gst_d3d12_memory_get_resource_handle (dmem); - D3D12_BOX src_box2; - - auto desc = GetDesc (src_resource); - - UINT width = MIN ((UINT) desc.Width, priv->config.resolution.Width); - UINT height = MIN ((UINT) desc.Height, priv->config.resolution.Height); - - for (guint i = 0; i < 2; i++) { - GstD3D12CopyTextureRegionArgs args; - memset (&args, 0, sizeof (args)); - - args.src = CD3DX12_TEXTURE_COPY_LOCATION (src_resource, i); - args.dst = CD3DX12_TEXTURE_COPY_LOCATION (dst_resource, i); - - src_boxi.left = 0; - src_boxi.top = 0; - src_boxi.front = 0; - src_boxi.back = 1; - - if (i == 0) { - src_boxi.right = width; - src_boxi.bottom = height; - } else { - src_boxi.right = width / 2; - src_boxi.bottom = height / 2; - } - - args.src_box = &src_boxi; - copy_args.push_back (args); - } - - guint64 fence_val = 0; - guint num_fences_to_wait = 0; - ID3D12Fence *fences_to_wait = { fence_to_wait.Get () }; - guint64 fence_values_to_wait = { fence_val_to_wait }; - if (fence_to_wait) - num_fences_to_wait++; - - gst_d3d12_device_copy_texture_region (self->device, copy_args.size (), - copy_args.data (), nullptr, num_fences_to_wait, fences_to_wait, - fence_values_to_wait, D3D12_COMMAND_LIST_TYPE_DIRECT, &fence_val); - gst_d3d12_buffer_set_fence (upload, - gst_d3d12_device_get_fence_handle (self->device, - D3D12_COMMAND_LIST_TYPE_DIRECT), fence_val, FALSE); - } else { - GstVideoFrame src_frame, dst_frame; - if (!gst_video_frame_map (&src_frame, info, buffer, GST_MAP_READ)) { - GST_ERROR_OBJECT (self, "Couldn't map frame"); - gst_buffer_unref (upload); - return nullptr; - } - - if (!gst_video_frame_map (&dst_frame, info, upload, GST_MAP_WRITE)) { - GST_ERROR_OBJECT (self, "Couldn't map frame"); - gst_video_frame_unmap (&src_frame); - gst_buffer_unref (upload); - return nullptr; - } - - for (guint i = 0; i < GST_VIDEO_FRAME_N_PLANES (&src_frame); i++) { - auto src_width_in_bytes = GST_VIDEO_FRAME_COMP_WIDTH (&src_frame, i) * - GST_VIDEO_FRAME_COMP_PSTRIDE (&src_frame, i); - auto src_height = GST_VIDEO_FRAME_COMP_HEIGHT (&src_frame, i); - auto src_stride = GST_VIDEO_FRAME_PLANE_STRIDE (&src_frame, i); - - auto dst_width_in_bytes = GST_VIDEO_FRAME_COMP_WIDTH (&dst_frame, i) * - GST_VIDEO_FRAME_COMP_PSTRIDE (&dst_frame, i); - auto dst_height = GST_VIDEO_FRAME_COMP_HEIGHT (&dst_frame, i); - auto dst_stride = GST_VIDEO_FRAME_PLANE_STRIDE (&dst_frame, i); - - auto width_in_bytes = MIN (src_width_in_bytes, dst_width_in_bytes); - auto height = MIN (src_height, dst_height); - auto src_data = (guint8 *) GST_VIDEO_FRAME_PLANE_DATA (&src_frame, i); - auto dst_data = (guint8 *) GST_VIDEO_FRAME_PLANE_DATA (&dst_frame, i); - - for (gint j = 0; j < height; j++) { - memcpy (dst_data, src_data, width_in_bytes); - dst_data += dst_stride; - src_data += src_stride; - } - } - - gst_video_frame_unmap (&dst_frame); - gst_video_frame_unmap (&src_frame); - - GstMapInfo map_info; - mem = gst_buffer_peek_memory (upload, 0); - if (!gst_memory_map (mem, &map_info, GST_MAP_READ_D3D12)) { - GST_ERROR_OBJECT (self, "Couldn't map memory"); - gst_buffer_unref (upload); - return nullptr; - } + if (!gst_d3d12_buffer_copy_into (upload, buffer, info)) { + GST_ERROR_OBJECT (self, "Couldn't copy input buffer"); + gst_buffer_unref (upload); + return nullptr; + } - gst_memory_unmap (mem, &map_info); + /* Upload data written by the system memory fallback. */ + GstMapInfo map_info; + mem = gst_buffer_peek_memory (upload, 0); + if (!gst_memory_map (mem, &map_info, GST_MAP_READ_D3D12)) { + GST_ERROR_OBJECT (self, "Couldn't map memory"); + gst_buffer_unref (upload); + return nullptr; } + gst_memory_unmap (mem, &map_info); + return upload; } @@ -1088,6 +995,7 @@ map_data += sizeof (D3D12_VIDEO_ENCODER_OUTPUT_METADATA); priv->subregions.clear (); UINT64 total_subregion_size = 0; + UINT64 source_offset = 0; for (guint i = 0; i < output_meta.WrittenSubregionsCount; i++) { auto subregion = *((D3D12_VIDEO_ENCODER_FRAME_SUBREGION_METADATA *) map_data); @@ -1096,7 +1004,16 @@ "bStartOffset: %" G_GUINT64_FORMAT ", bHeaderSize: %" G_GUINT64_FORMAT, i, subregion.bSize, subregion.bStartOffset, subregion.bHeaderSize); - subregion.bStartOffset += total_subregion_size; + if (subregion.bStartOffset > subregion.bSize) { + GST_ERROR_OBJECT (self, "Subregion padding exceeds subregion size"); + resolved_metadata->Unmap (0, &zero_range); + return FALSE; + } + + auto padded_size = subregion.bSize; + subregion.bSize -= subregion.bStartOffset; + subregion.bStartOffset += source_offset; + source_offset += padded_size; priv->subregions.push_back (subregion); total_subregion_size += subregion.bSize;
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/sys/d3d12/gstd3d12h264enc.cpp -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/sys/d3d12/gstd3d12h264enc.cpp
Changed
@@ -96,6 +96,8 @@ GstCaps *src_caps; guint rc_support; guint slice_mode_support; + guint width_multiple; + guint height_multiple; }; /* *INDENT-OFF* */ @@ -399,7 +401,6 @@ GstH264Profile selected_profile; GstD3D12H264EncGop gop; std::unique_ptr<GstD3D12H264EncDpb> dpb; - guint last_pps_id = 0; guint64 display_order = 0; GArray *cc_sei; @@ -1006,6 +1007,8 @@ { auto priv = self->priv; guint8 sps_buf4096 = { 0, }; + guint coded_width = GST_ROUND_UP_16 (resolution->Width); + guint coded_height = GST_ROUND_UP_16 (resolution->Height); /* *INDENT-OFF* */ static const std::unordered_map<D3D12_VIDEO_ENCODER_LEVELS_H264, guint8> level_map = { @@ -1086,20 +1089,19 @@ priv->gop_struct_h264.log2_max_pic_order_cnt_lsb_minus4; sps.num_ref_frames = num_ref; sps.gaps_in_frame_num_value_allowed_flag = 0; - sps.pic_width_in_mbs_minus1 = (resolution->Width / 16) - 1; - sps.pic_height_in_map_units_minus1 = (resolution->Height / 16) - 1; + sps.pic_width_in_mbs_minus1 = (coded_width / 16) - 1; + sps.pic_height_in_map_units_minus1 = (coded_height / 16) - 1; sps.frame_mbs_only_flag = 1; if (sps.profile_idc != GST_H264_PROFILE_BASELINE) sps.direct_8x8_inference_flag = 1; - if (resolution->Width != (UINT) info->width || - resolution->Height != (UINT) info->height) { + if (coded_width != (UINT) info->width || coded_height != (UINT) info->height) { sps.frame_cropping_flag = 1; sps.frame_crop_left_offset = 0; - sps.frame_crop_right_offset = (resolution->Width - info->width) / 2; + sps.frame_crop_right_offset = (coded_width - info->width) / 2; sps.frame_crop_top_offset = 0; - sps.frame_crop_bottom_offset = (resolution->Height - info->height) / 2; + sps.frame_crop_bottom_offset = (coded_height - info->height) / 2; } sps.vui_parameters_present_flag = 1; @@ -1287,8 +1289,6 @@ if (ref_frames == 0) gop_size = 1; - priv->last_pps_id = 0; - auto prev_gop_struct = priv->gop.GetGopStruct (); auto prev_ref_frames = priv->selected_ref_frames; @@ -1459,7 +1459,7 @@ break; case D3D12_VIDEO_ENCODER_RATE_CONTROL_MODE_QVBR: prev = &prev_config.qvbr; - cur = &config->cbr; + cur = &config->qvbr; break; default: g_assert_not_reached (); @@ -1549,6 +1549,7 @@ case D3D12_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE_BYTES_PER_SUBREGION: priv->selected_slice_mode = priv->slice_mode; + priv->layout_slices.MaxBytesPerSlice = priv->slice_partition; /* Don't know how many slices would be generated */ config->max_subregions = limits.MaxSubregionsNumber; *support_flags = support.SupportFlags; @@ -1556,8 +1557,10 @@ case D3D12_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE_SQUARE_UNITS_PER_SUBREGION_ROW_UNALIGNED: { auto total_mbs = - (config->resolution.Width / limits.SubregionBlockPixelsSize) * - (config->resolution.Height / limits.SubregionBlockPixelsSize); + ((config->resolution.Width + limits.SubregionBlockPixelsSize - + 1) / limits.SubregionBlockPixelsSize) * + ((config->resolution.Height + limits.SubregionBlockPixelsSize - + 1) / limits.SubregionBlockPixelsSize); if (priv->slice_partition >= total_mbs) { GST_DEBUG_OBJECT (self, "Requested MBs per slice exceeds total MBs per frame"); @@ -1585,7 +1588,8 @@ } case D3D12_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE_UNIFORM_PARTITIONING_ROWS_PER_SUBREGION: { - auto total_rows = config->resolution.Height / + auto total_rows = (config->resolution.Height + + limits.SubregionBlockPixelsSize - 1) / limits.SubregionBlockPixelsSize; if (priv->slice_partition >= total_rows) { GST_DEBUG_OBJECT (self, @@ -1659,6 +1663,7 @@ auto encoder = GST_D3D12_ENCODER (self); auto priv = self->priv; auto prev_config = *config; + auto prev_level = priv->level_h264; if (!gst_d3d12_h264_enc_update_gop (self, video_device, config, seq_flags)) return FALSE; @@ -1767,14 +1772,18 @@ config->support_flags = support.SupportFlags; - if (!seq_flags || + bool gop_updated = !seq_flags || (*seq_flags & - D3D12_VIDEO_ENCODER_SEQUENCE_CONTROL_FLAG_GOP_SEQUENCE_CHANGE) != 0) { + D3D12_VIDEO_ENCODER_SEQUENCE_CONTROL_FLAG_GOP_SEQUENCE_CHANGE) != 0; + + if (gop_updated || priv->level_h264 != prev_level) { priv->gop.ForceKeyUnit (); gst_d3d12_h264_enc_build_sps (self, &priv->info, &config->resolution, priv->selected_ref_frames); gst_d3d12_h264_enc_build_pps (self, priv->selected_ref_frames); + } + if (gop_updated) { bool array_of_textures = !CHECK_SUPPORT_FLAG (config->support_flags, RECONSTRUCTED_FRAMES_REQUIRE_TEXTURE_ARRAYS); auto dpb = std::make_unique < GstD3D12H264EncDpb > (encoder->device, @@ -1801,6 +1810,8 @@ GstD3D12EncoderConfig * config) { auto self = GST_D3D12_H264_ENC (encoder); + auto klass = GST_D3D12_H264_ENC_GET_CLASS (self); + auto cdata = klass->cdata; auto priv = self->priv; auto info = &state->info; @@ -1828,8 +1839,10 @@ sizeof (D3D12_VIDEO_ENCODER_SEQUENCE_GOP_STRUCTURE_H264); config->gop_struct.pH264GroupOfPictures = &priv->gop_struct_h264; - config->resolution.Width = GST_ROUND_UP_16 (info->width); - config->resolution.Height = GST_ROUND_UP_16 (info->height); + config->resolution.Width = ((info->width + cdata->width_multiple - 1) / + cdata->width_multiple) * cdata->width_multiple; + config->resolution.Height = ((info->height + cdata->height_multiple - 1) / + cdata->height_multiple) * cdata->height_multiple; priv->selected_profile = GST_H264_PROFILE_MAIN; priv->profile_h264 = D3D12_VIDEO_ENCODER_PROFILE_H264_MAIN; @@ -2063,7 +2076,10 @@ if (priv->pic_control_h264.FrameType == D3D12_VIDEO_ENCODER_FRAME_TYPE_H264_IDR_FRAME) { - auto buf_size = priv->sps.bytes.size () + priv->pps0.bytes.size (); + auto buf_size = priv->sps.bytes.size (); + for (size_t i = 0; i < priv->pps.size (); i++) + buf_size += priv->ppsi.bytes.size (); + if (priv->aud) buf_size += sizeof (aud_data); @@ -2080,34 +2096,12 @@ memcpy (data, priv->sps.bytes.data (), priv->sps.bytes.size ()); data += priv->sps.bytes.size (); - memcpy (data, priv->pps0.bytes.data (), priv->pps0.bytes.size ()); - gst_buffer_unmap (output_buf, &map_info); - frame->output_buffer = output_buf; - - priv->last_pps_id = 0; - } else if (priv->pic_control_h264.pic_parameter_set_id != priv->last_pps_id) { - const auto & cur_pps = - priv->ppspriv->pic_control_h264.pic_parameter_set_id; - auto buf_size = cur_pps.bytes.size (); - - if (priv->aud) - buf_size += sizeof (aud_data); - - auto output_buf = gst_buffer_new_and_alloc (buf_size); - GstMapInfo map_info; - gst_buffer_map (output_buf, &map_info, GST_MAP_WRITE); - auto data = (guint8 *) map_info.data; - - if (priv->aud) { - memcpy (data, aud_data, sizeof (aud_data)); - data += sizeof (aud_data); + for (size_t i = 0; i < priv->pps.size (); i++) { + memcpy (data, priv->ppsi.bytes.data (), priv->ppsi.bytes.size ()); + data += priv->ppsi.bytes.size (); } - - memcpy (data, cur_pps.bytes.data (), cur_pps.bytes.size ()); gst_buffer_unmap (output_buf, &map_info); frame->output_buffer = output_buf; - - priv->last_pps_id = priv->pic_control_h264.pic_parameter_set_id; } else if (priv->aud) { auto buf_size = sizeof (aud_data); auto output_buf = gst_buffer_new_and_alloc (buf_size); @@ -2433,6 +2427,16 @@ cdata->src_caps = src_caps; cdata->rc_support = rc_support; cdata->slice_mode_support = slice_mode_support; + cdata->width_multiple = + MAX (1, feature_resolution.ResolutionWidthMultipleRequirement); + cdata->height_multiple = + MAX (1, feature_resolution.ResolutionHeightMultipleRequirement); + + /* Ensure even numbers for subsampled formats */ + if (cdata->width_multiple % 2) + cdata->width_multiple *= 2; + if (cdata->height_multiple % 2) + cdata->height_multiple *= 2; GType type; gchar *type_name;
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/sys/d3d12/meson.build -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/sys/d3d12/meson.build
Changed
@@ -162,7 +162,7 @@ #include<windows.h> #include<winstring.h> #include<roapi.h> - #include<windows.graphics.capture.h>, + #include<windows.graphics.capture.h> #include<windows.graphics.capture.interop.h> #include<windows.graphics.directx.direct3d11.h> #include<windows.graphics.directx.direct3d11.interop.h> @@ -174,6 +174,14 @@ ComPtr<IGraphicsCaptureSession> session; ComPtr<IGraphicsCaptureSession2> session2; ComPtr<IGraphicsCaptureSession3> session3; + typedef ABI::Windows::Foundation::__FITypedEventHandler_2_Windows__CGraphics__CCapture__CDirect3D11CaptureFramePool_IInspectable_t + IFrameArrivedHandler; + typedef ABI::Windows::Foundation::__FITypedEventHandler_2_Windows__CGraphics__CCapture__CGraphicsCaptureItem_IInspectable_t + IItemClosedHandler; + class WgcHandler : public RuntimeClass<RuntimeClassFlags<ClassicCom>, + FtmBase, IFrameArrivedHandler, IItemClosedHandler> + { + }; ''', name: 'Windows Graphics Capture support in Windows SDK')
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/sys/nvcodec/gstcudaconverter.cpp -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/sys/nvcodec/gstcudaconverter.cpp
Changed
@@ -1038,6 +1038,7 @@ if (priv->alpha != alpha) { priv->update_const_buf = TRUE; priv->const_buf->alpha = (float) alpha; + priv->alpha = alpha; } break; } @@ -1047,6 +1048,7 @@ if (priv->blend != blend) { priv->update_const_buf = TRUE; priv->const_buf->do_blend = blend; + priv->blend = blend; } break; }
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/sys/nvcodec/gstcudaipcserver_unix.cpp -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/sys/nvcodec/gstcudaipcserver_unix.cpp
Changed
@@ -372,9 +372,15 @@ GST_DEBUG_OBJECT (self, "Loop stopped"); if (service) { + g_signal_handlers_disconnect_by_data (service, self); + g_socket_service_stop (service); + g_socket_listener_close (G_SOCKET_LISTENER (service)); g_cancellable_cancel (priv->cancellable); g_unlink (priv->address.c_str ()); g_clear_object (&service); + + while (g_main_context_pending (priv->main_context)) + g_main_context_iteration (priv->main_context, FALSE); } g_main_context_pop_thread_default (priv->main_context);
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/sys/qsv/libmfx/dispatcher/windows/mfx_dispatcher_defs.h -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/sys/qsv/libmfx/dispatcher/windows/mfx_dispatcher_defs.h
Changed
@@ -17,7 +17,7 @@ #define MAX_PLUGIN_PATH 4096 #define MAX_PLUGIN_NAME 4096 -#if _MSC_VER < 1400 +#if defined(_MSC_VER) && _MSC_VER < 1400 #define wcscpy_s(to, to_size, from) \ (void)(to_size); \ wcscpy(to, from)
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/sys/v4l2codecs/gstv4l2codecav1dec.c -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/sys/v4l2codecs/gstv4l2codecav1dec.c
Changed
@@ -287,6 +287,8 @@ gst_v4l2_codec_av1_dec_reset_allocation (self); + self->min_pool_size = 0; + if (self->output_state) gst_video_codec_state_unref (self->output_state); self->output_state = NULL;
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/sys/v4l2codecs/gstv4l2codech264dec.c -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/sys/v4l2codecs/gstv4l2codech264dec.c
Changed
@@ -112,6 +112,7 @@ gboolean streaming; gboolean interlaced; gboolean need_sequence; + gboolean need_negotiation; gboolean copy_frames; gboolean scaling_matrix_present; @@ -286,6 +287,7 @@ gst_v4l2_codec_allocator_detach (self->src_allocator); g_clear_object (&self->src_allocator); g_clear_object (&self->src_pool); + self->min_pool_size = 0; } } @@ -518,7 +520,7 @@ } self->src_allocator = gst_v4l2_codec_allocator_new (self->decoder, - GST_PAD_SRC, self->min_pool_size + min + 4); + GST_PAD_SRC, self->min_pool_size + min); if (!self->src_allocator) { GST_ELEMENT_ERROR (self, RESOURCE, NO_SPACE_LEFT, ("Not enough memory to allocate source buffers."), (NULL)); @@ -982,12 +984,10 @@ gst_v4l2_codec_h264_dec_fill_sequence (self, sps); self->need_sequence = TRUE; + /* downstream may not be linked yet when the sequence comes from caps */ if (negotiation_needed) { gst_v4l2_codec_h264_dec_streamoff (self); - if (!gst_video_decoder_negotiate (GST_VIDEO_DECODER (self))) { - GST_ERROR_OBJECT (self, "Failed to negotiate with downstream"); - return GST_FLOW_NOT_NEGOTIATED; - } + self->need_negotiation = TRUE; } return GST_FLOW_OK; @@ -1027,6 +1027,14 @@ { GstV4l2CodecH264Dec *self = GST_V4L2_CODEC_H264_DEC (decoder); + if (self->need_negotiation) { + if (!gst_video_decoder_negotiate (GST_VIDEO_DECODER (self))) { + GST_ERROR_OBJECT (self, "Failed to negotiate with downstream"); + return GST_FLOW_NOT_NEGOTIATED; + } + self->need_negotiation = FALSE; + } + /* FIXME base class should not call us if negotiation failed */ if (!self->sink_allocator) return GST_FLOW_NOT_NEGOTIATED;
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/sys/v4l2codecs/gstv4l2codech265dec.c -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/sys/v4l2codecs/gstv4l2codech265dec.c
Changed
@@ -112,6 +112,7 @@ gboolean streaming; gboolean copy_frames; gboolean need_sequence; + gboolean need_negotiation; struct v4l2_ctrl_hevc_sps sps; struct v4l2_ctrl_hevc_pps pps; @@ -357,6 +358,8 @@ gst_v4l2_codec_h265_dec_streamoff (self); gst_v4l2_codec_h265_dec_reset_allocation (self); + self->min_pool_size = 0; + if (self->output_state) gst_video_codec_state_unref (self->output_state); self->output_state = NULL; @@ -1096,12 +1099,10 @@ gst_v4l2_codec_h265_dec_fill_sequence (self, sps); gst_v4l2_codec_h265_dec_fill_ext_sps_rps (self, sps); + /* downstream may not be linked yet when the sequence comes from caps */ if (negotiation_needed) { gst_v4l2_codec_h265_dec_streamoff (self); - if (!gst_video_decoder_negotiate (GST_VIDEO_DECODER (self))) { - GST_ERROR_OBJECT (self, "Failed to negotiate with downstream"); - return GST_FLOW_NOT_NEGOTIATED; - } + self->need_negotiation = TRUE; } return GST_FLOW_OK; @@ -1198,6 +1199,14 @@ { GstV4l2CodecH265Dec *self = GST_V4L2_CODEC_H265_DEC (decoder); + if (self->need_negotiation) { + if (!gst_video_decoder_negotiate (GST_VIDEO_DECODER (self))) { + GST_ERROR_OBJECT (self, "Failed to negotiate with downstream"); + return GST_FLOW_NOT_NEGOTIATED; + } + self->need_negotiation = FALSE; + } + /* FIXME base class should not call us if negotiation failed */ if (!self->sink_allocator) return GST_FLOW_NOT_NEGOTIATED; @@ -1231,6 +1240,7 @@ dst_info.fps_n = src_frame->info.fps_n; dst_info.fps_d = src_frame->info.fps_d; + dst_info.colorimetry = src_frame->info.colorimetry; if (self->convert) { gboolean new_convert = FALSE;
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/sys/v4l2codecs/gstv4l2codecmpeg2dec.c -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/sys/v4l2codecs/gstv4l2codecmpeg2dec.c
Changed
@@ -214,6 +214,8 @@ gst_v4l2_codec_mpeg2_dec_streamoff (self); gst_v4l2_codec_mpeg2_dec_reset_allocation (self); + self->min_pool_size = 0; + if (self->output_state) gst_video_codec_state_unref (self->output_state); self->output_state = NULL;
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/sys/v4l2codecs/gstv4l2codecvp8dec.c -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/sys/v4l2codecs/gstv4l2codecvp8dec.c
Changed
@@ -216,6 +216,8 @@ gst_v4l2_codec_vp8_dec_streamoff (self); gst_v4l2_codec_vp8_dec_reset_allocation (self); + self->min_pool_size = 0; + if (self->output_state) gst_video_codec_state_unref (self->output_state); self->output_state = NULL; @@ -401,7 +403,7 @@ } self->src_allocator = gst_v4l2_codec_allocator_new (self->decoder, - GST_PAD_SRC, self->min_pool_size + min + 4); + GST_PAD_SRC, self->min_pool_size + min); if (!self->src_allocator) { GST_ELEMENT_ERROR (self, RESOURCE, NO_SPACE_LEFT, ("Not enough memory to allocate source buffers."), (NULL)); @@ -565,6 +567,11 @@ GstV4l2CodecVp8Dec *self = GST_V4L2_CODEC_VP8_DEC (decoder); gboolean negotiation_needed = FALSE; + if (self->min_pool_size < max_dpb_size) { + self->min_pool_size = max_dpb_size; + negotiation_needed = TRUE; + } + if (self->vinfo_drm.vinfo.finfo->format == GST_VIDEO_FORMAT_UNKNOWN) negotiation_needed = TRUE;
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/sys/v4l2codecs/gstv4l2codecvp9dec.c -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/sys/v4l2codecs/gstv4l2codecvp9dec.c
Changed
@@ -123,6 +123,7 @@ GstV4l2CodecAllocator *sink_allocator; GstV4l2CodecAllocator *src_allocator; GstV4l2CodecPool *src_pool; + gint min_pool_size; gboolean streaming; gboolean copy_frames; gboolean need_negotiation; @@ -486,6 +487,8 @@ gst_v4l2_codec_vp9_dec_reset_allocation (self); + self->min_pool_size = 0; + if (self->output_state) gst_video_codec_state_unref (self->output_state); self->output_state = NULL; @@ -669,7 +672,7 @@ } self->src_allocator = gst_v4l2_codec_allocator_new (self->decoder, - GST_PAD_SRC, GST_VP9_REF_FRAMES + min + 4); + GST_PAD_SRC, self->min_pool_size + min); if (!self->src_allocator) { GST_ELEMENT_ERROR (self, RESOURCE, NO_SPACE_LEFT, ("Not enough memory to allocate source buffers."), (NULL)); @@ -781,6 +784,11 @@ gst_v4l2_codec_vp9_dec_fill_dec_params (self, frame_hdr, NULL); + if (self->min_pool_size != max_dpb_size) { + self->min_pool_size = max_dpb_size; + self->need_negotiation = TRUE; + } + if (decoder->parse_compressed_headers) gst_v4l2_codec_vp9_dec_fill_prob_updates (self, frame_hdr);
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/sys/va/gstvaav1enc.c -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/sys/va/gstvaav1enc.c
Changed
@@ -3899,6 +3899,11 @@ va_frame->base.picture = gst_va_encode_picture_new (base->encoder, gst_frame->input_buffer); + if (!va_frame->base.picture) { + GST_ERROR_OBJECT (self, "Failed to create the encode picture"); + return GST_FLOW_ERROR; + } + _av1_find_ref_to_update (base, gst_frame); if (!self->inside_tu &&
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/sys/va/gstvacaps.c -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/sys/va/gstvacaps.c
Changed
@@ -100,6 +100,152 @@ g_value_unset (&item); } +static void +_generate_supported_formats (GPtrArray * supported_formats, + GValue * supported_value) +{ + guint i; + + if (supported_formats->len == 1) { + g_value_init (supported_value, G_TYPE_STRING); + g_value_set_string (supported_value, + g_ptr_array_index (supported_formats, 0)); + } else { + GValue item = G_VALUE_INIT; + + gst_value_list_init (supported_value, supported_formats->len); + + for (i = 0; i < supported_formats->len; i++) { + g_value_init (&item, G_TYPE_STRING); + g_value_set_string (&item, g_ptr_array_index (supported_formats, i)); + gst_value_list_append_value (supported_value, &item); + g_value_unset (&item); + } + } +} + +/* Returns a copy of @sinkcaps keeping only the formats, and DMA formats, + * for which @is_supported returns TRUE, or NULL if none is left. */ +GstCaps * +gst_va_caps_filter_formats (GstCaps * sinkcaps, + GstVaFormatFilterFunc is_supported) +{ + GPtrArray *supported_formats; + const gchar *format_str; + GstVideoFormat gst_format; + const GValue *val; + GValue supported_value = G_VALUE_INIT; + GstCaps *ret; + guint num_structures; + guint i, j; + + supported_formats = g_ptr_array_new (); + ret = gst_caps_new_empty (); + + num_structures = gst_caps_get_size (sinkcaps); + + for (i = 0; i < num_structures; i++) { + GstStructure *st; + GstCapsFeatures *features; + + g_ptr_array_set_size (supported_formats, 0); + + st = gst_caps_get_structure (sinkcaps, i); + st = gst_structure_copy (st); + + features = gst_caps_get_features (sinkcaps, i); + + if (gst_caps_features_contains (features, GST_CAPS_FEATURE_MEMORY_DMABUF)) { + guint32 fourcc; + + val = gst_structure_get_value (st, "drm-format"); + if (!val) { + gst_structure_free (st); + continue; + } + + if (G_VALUE_HOLDS_STRING (val)) { + format_str = g_value_get_string (val); + fourcc = gst_video_dma_drm_fourcc_from_string (format_str, NULL); + gst_format = gst_va_video_format_from_drm_fourcc (fourcc); + + if (is_supported (gst_format)) + g_ptr_array_add (supported_formats, (gpointer) format_str); + } else if (GST_VALUE_HOLDS_LIST (val)) { + guint num_values = gst_value_list_get_size (val); + + for (j = 0; j < num_values; j++) { + const GValue *v = gst_value_list_get_value (val, j); + + format_str = g_value_get_string (v); + fourcc = gst_video_dma_drm_fourcc_from_string (format_str, NULL); + gst_format = gst_va_video_format_from_drm_fourcc (fourcc); + + if (is_supported (gst_format)) + g_ptr_array_add (supported_formats, (gpointer) format_str); + } + } + + if (!supported_formats->len) { + gst_structure_free (st); + continue; + } + + _generate_supported_formats (supported_formats, &supported_value); + gst_structure_take_value (st, "drm-format", &supported_value); + + gst_caps_append_structure_full (ret, st, + gst_caps_features_copy (features)); + } else { + val = gst_structure_get_value (st, "format"); + if (!val) { + gst_structure_free (st); + continue; + } + + if (G_VALUE_HOLDS_STRING (val)) { + format_str = g_value_get_string (val); + gst_format = gst_video_format_from_string (format_str); + + if (is_supported (gst_format)) + g_ptr_array_add (supported_formats, (gpointer) format_str); + } else if (GST_VALUE_HOLDS_LIST (val)) { + guint num_values = gst_value_list_get_size (val); + + for (j = 0; j < num_values; j++) { + const GValue *v = gst_value_list_get_value (val, j); + + format_str = g_value_get_string (v); + gst_format = gst_video_format_from_string (format_str); + + if (is_supported (gst_format)) + g_ptr_array_add (supported_formats, (gpointer) format_str); + } + } + + if (!supported_formats->len) { + gst_structure_free (st); + continue; + } + + _generate_supported_formats (supported_formats, &supported_value); + gst_structure_take_value (st, "format", &supported_value); + + gst_caps_append_structure_full (ret, st, + gst_caps_features_copy (features)); + } + } + + g_ptr_array_unref (supported_formats); + + if (gst_caps_is_empty (ret)) { + gst_caps_unref (ret); + ret = NULL; + } + + return ret; +} + gboolean gst_caps_set_format_array (GstCaps * caps, GArray * formats) { @@ -264,7 +410,8 @@ static gboolean _get_entrypoint_from_config (GstVaDisplay * display, VAConfigID config, - VAProfile * profile_out, VAEntrypoint * entrypoint_out) + VAProfile * profile_out, VAEntrypoint * entrypoint_out, + VAConfigAttrib ** attribs_out, int *num_attribs_out) { VADisplay dpy; VAStatus status; @@ -278,11 +425,10 @@ attribs = g_new (VAConfigAttrib, vaMaxNumConfigAttributes (dpy)); status = vaQueryConfigAttributes (dpy, config, &profile, &entrypoint, attribs, &num_attribs); - g_free (attribs); - if (status != VA_STATUS_SUCCESS) { GST_ERROR_OBJECT (display, "vaQueryConfigAttributes: %s", vaErrorStr (status)); + g_free (attribs); return FALSE; } @@ -290,6 +436,12 @@ *profile_out = profile; if (entrypoint_out) *entrypoint_out = entrypoint; + if (attribs_out) + *attribs_out = attribs; + else + g_free (attribs); + if (num_attribs_out) + *num_attribs_out = num_attribs; return TRUE; } @@ -304,16 +456,33 @@ VASurfaceAttrib *attribs; VAEntrypoint entrypoint; VAProfile profile; - guint i, attrib_count, mem_type = 0; + guint i, attrib_count, mem_type = 0, rt_format = 0; gint min_width = 1, max_width = G_MAXINT; gint min_height = 1, max_height = G_MAXINT; + VAConfigAttrib *config_attribs; + int config_attrib_count; + + if (!_get_entrypoint_from_config (display, config, &profile, &entrypoint, + &config_attribs, &config_attrib_count)) + return NULL; - if (!_get_entrypoint_from_config (display, config, &profile, &entrypoint)) + for (int i = 0; i < config_attrib_count; i++) { + if (config_attribsi.type == VAConfigAttribRTFormat) { + rt_format = config_attribsi.value; + break; + } + } + if (rt_format == 0) { + g_free (config_attribs); return NULL; + } attribs = gst_va_get_surface_attribs (display, config, &attrib_count); - if (!attribs) + if (!attribs) { + g_free (config_attribs); return NULL; + } + formats = g_array_new (FALSE, FALSE, sizeof (GstVideoFormat)); for (i = 0; i < attrib_count; i++) { @@ -322,7 +491,8 @@ switch (attribsi.type) { case VASurfaceAttribPixelFormat: format = gst_va_video_format_from_va_fourcc (attribsi.value.value.i); - if (format != GST_VIDEO_FORMAT_UNKNOWN) + if (format != GST_VIDEO_FORMAT_UNKNOWN + && gst_va_chroma_from_video_format (format) & rt_format) g_array_append_val (formats, format); break; case VASurfaceAttribMinWidth: @@ -391,6 +561,7 @@ bail: g_array_unref (formats); g_free (attribs); + g_free (config_attribs); return caps; }
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/sys/va/gstvacaps.h -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/sys/va/gstvacaps.h
Changed
@@ -25,6 +25,8 @@ G_BEGIN_DECLS +typedef gboolean (*GstVaFormatFilterFunc) (GstVideoFormat format); + gboolean gst_va_caps_from_profiles (GstVaDisplay * display, GArray * profiles, VAEntrypoint entrypoint, @@ -54,6 +56,9 @@ GstCaps * gst_va_video_info_to_dma_caps (GstVideoInfo * info, guint64 modifier); +GstCaps * gst_va_caps_filter_formats (GstCaps * sinkcaps, + GstVaFormatFilterFunc is_supported); + gboolean gst_caps_set_format_array (GstCaps * caps, GArray * formats);
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/sys/va/gstvajpegenc.c -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/sys/va/gstvajpegenc.c
Changed
@@ -52,6 +52,7 @@ #include "vacompat.h" #include "gstvabaseenc.h" +#include "gstvacaps.h" #include "gstvadisplay_priv.h" #include "gstvaencoder.h" #include "gstvaprofile.h" @@ -1127,149 +1128,6 @@ return FALSE; } -static void -_generate_supported_formats (GPtrArray * supported_formats, - GValue * supported_value) -{ - guint i; - - if (supported_formats->len == 1) { - g_value_init (supported_value, G_TYPE_STRING); - g_value_set_string (supported_value, - g_ptr_array_index (supported_formats, 0)); - } else { - GValue item = G_VALUE_INIT; - - gst_value_list_init (supported_value, supported_formats->len); - - for (i = 0; i < supported_formats->len; i++) { - g_value_init (&item, G_TYPE_STRING); - g_value_set_string (&item, g_ptr_array_index (supported_formats, i)); - gst_value_list_append_value (supported_value, &item); - g_value_unset (&item); - } - } -} - -static GstCaps * -_filter_sink_caps (GstCaps * sinkcaps) -{ - GPtrArray *supported_formats; - const gchar *format_str; - GstVideoFormat gst_format; - const GValue *val; - GValue supported_value = G_VALUE_INIT; - GstCaps *ret; - guint num_structures; - guint i, j; - - supported_formats = g_ptr_array_new (); - ret = gst_caps_new_empty (); - - num_structures = gst_caps_get_size (sinkcaps); - - for (i = 0; i < num_structures; i++) { - GstStructure *st; - GstCapsFeatures *features; - - g_ptr_array_set_size (supported_formats, 0); - - st = gst_caps_get_structure (sinkcaps, i); - st = gst_structure_copy (st); - - features = gst_caps_get_features (sinkcaps, i); - - if (gst_caps_features_contains (features, GST_CAPS_FEATURE_MEMORY_DMABUF)) { - guint32 fourcc; - - val = gst_structure_get_value (st, "drm-format"); - if (!val) { - gst_structure_free (st); - continue; - } - - if (G_VALUE_HOLDS_STRING (val)) { - format_str = g_value_get_string (val); - fourcc = gst_video_dma_drm_fourcc_from_string (format_str, NULL); - gst_format = gst_va_video_format_from_drm_fourcc (fourcc); - - if (_is_supported_format (gst_format)) - g_ptr_array_add (supported_formats, (gpointer) format_str); - } else if (GST_VALUE_HOLDS_LIST (val)) { - guint num_values = gst_value_list_get_size (val); - - for (j = 0; j < num_values; j++) { - const GValue *v = gst_value_list_get_value (val, j); - - format_str = g_value_get_string (v); - fourcc = gst_video_dma_drm_fourcc_from_string (format_str, NULL); - gst_format = gst_va_video_format_from_drm_fourcc (fourcc); - - if (_is_supported_format (gst_format)) - g_ptr_array_add (supported_formats, (gpointer) format_str); - } - } - - if (!supported_formats->len) { - gst_structure_free (st); - continue; - } - - _generate_supported_formats (supported_formats, &supported_value); - gst_structure_take_value (st, "drm-format", &supported_value); - - gst_caps_append_structure_full (ret, st, - gst_caps_features_copy (features)); - } else { - val = gst_structure_get_value (st, "format"); - if (!val) { - gst_structure_free (st); - continue; - } - - if (G_VALUE_HOLDS_STRING (val)) { - format_str = g_value_get_string (val); - gst_format = gst_video_format_from_string (format_str); - - if (_is_supported_format (gst_format)) - g_ptr_array_add (supported_formats, (gpointer) format_str); - } else if (GST_VALUE_HOLDS_LIST (val)) { - guint num_values = gst_value_list_get_size (val); - - for (j = 0; j < num_values; j++) { - const GValue *v = gst_value_list_get_value (val, j); - - format_str = g_value_get_string (v); - gst_format = gst_video_format_from_string (format_str); - - if (_is_supported_format (gst_format)) - g_ptr_array_add (supported_formats, (gpointer) format_str); - } - } - - if (!supported_formats->len) { - gst_structure_free (st); - continue; - } - - _generate_supported_formats (supported_formats, &supported_value); - gst_structure_take_value (st, "format", &supported_value); - - gst_caps_append_structure_full (ret, st, - gst_caps_features_copy (features)); - } - } - - g_ptr_array_unref (supported_formats); - - if (gst_caps_is_empty (ret)) { - gst_caps_unref (ret); - ret = NULL; - } - - return ret; -} - gboolean gst_va_jpeg_enc_register (GstPlugin * plugin, GstVaDevice * device, GstCaps * sink_caps, GstCaps * src_caps, guint rank, @@ -1293,7 +1151,7 @@ g_return_val_if_fail (GST_IS_CAPS (src_caps), FALSE); g_return_val_if_fail (entrypoint == VAEntrypointEncPicture, FALSE); - sink_caps = _filter_sink_caps (sink_caps); + sink_caps = gst_va_caps_filter_formats (sink_caps, _is_supported_format); cdata = g_new (struct CData, 1); cdata->entrypoint = entrypoint;
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/sys/va/gstvavp8enc.c -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/sys/va/gstvavp8enc.c
Changed
@@ -896,6 +896,11 @@ va_frame->base.picture = gst_va_encode_picture_new (base->encoder, gst_frame->input_buffer); + if (!va_frame->base.picture) { + GST_ERROR_OBJECT (self, "Failed to create the encode picture"); + return GST_FLOW_ERROR; + } + if (va_frame->frame_num == 0) { _vp8_fill_sequence_param (self, &seq_param); if (!_vp8_add_sequence_param (self, va_frame->base.picture, &seq_param))
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/sys/va/gstvavp9enc.c -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/sys/va/gstvavp9enc.c
Changed
@@ -53,6 +53,7 @@ #include "vacompat.h" #include "gstvabaseenc.h" +#include "gstvacaps.h" #include "gstvadisplay_priv.h" #include "gstvaencoder.h" #include "gstvaprofile.h" @@ -2507,6 +2508,11 @@ va_frame->base.picture = gst_va_encode_picture_new (base->encoder, gst_frame->input_buffer); + if (!va_frame->base.picture) { + GST_ERROR_OBJECT (self, "Failed to create the encode picture"); + return GST_FLOW_ERROR; + } + _vp9_find_ref_to_update (base, gst_frame); /* Repeat the sequence for each key. */ @@ -3216,6 +3222,14 @@ g_object_class_install_properties (object_class, n_props, properties); } +static gboolean +_is_supported_format (GstVideoFormat format) +{ + /* drivers may report RGB input, but it isn't implemented and it hangs + * the GPU with Intel iHD */ + return !GST_VIDEO_FORMAT_INFO_IS_RGB (gst_video_format_get_info (format)); +} + static GstCaps * _complete_src_caps (GstCaps * srccaps) { @@ -3254,11 +3268,15 @@ g_return_val_if_fail (entrypoint == VAEntrypointEncSlice || entrypoint == VAEntrypointEncSliceLP, FALSE); + sink_caps = gst_va_caps_filter_formats (sink_caps, _is_supported_format); + if (!sink_caps) + return FALSE; + cdata = g_new (struct CData, 1); cdata->entrypoint = entrypoint; cdata->description = NULL; cdata->render_device_path = g_strdup (device->render_device_path); - cdata->sink_caps = gst_caps_ref (sink_caps); + cdata->sink_caps = sink_caps; cdata->src_caps = _complete_src_caps (src_caps); /* class data will be leaked if the element never gets instantiated */
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/tests/check/elements/av1parse.c -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/tests/check/elements/av1parse.c
Changed
@@ -355,6 +355,356 @@ GST_END_TEST; +GST_START_TEST (test_timing_info_invalid_framerate) +{ + GstHarness *h; + GstBuffer *buf; + GstEvent *event; + gboolean seen = FALSE; + /* Sequence header OBU with timing_info time_scale = 0x80000000 and + * num_units_in_display_tick = 0xFFFFFFFF. The values do not fit the + * gint framerate and used to trigger undefined behaviour + * (G_MININT % -1 inside gst_util_greatest_common_divisor) when + * reducing the fraction. */ + const guint8 stream = { + 0x0a, 0x11, 0x07, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x03, 0x00, + 0x00, 0x05, 0x33, 0xff, 0x00, 0x68, 0x02 + }; + + h = gst_harness_new_parse ("av1parse"); + gst_harness_set_src_caps_str (h, "video/x-av1"); + + buf = gst_buffer_new_and_alloc (sizeof (stream)); + gst_buffer_fill (buf, 0, stream, sizeof (stream)); + fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK); + + gst_harness_push_event (h, gst_event_new_eos ()); + + while ((event = gst_harness_pull_event (h)) != NULL) { + GstCaps *caps; + const GstStructure *s; + gint n = 0, d = 1; + + if (GST_EVENT_TYPE (event) != GST_EVENT_CAPS) { + gst_event_unref (event); + continue; + } + + seen = TRUE; + gst_event_parse_caps (event, &caps); + s = gst_caps_get_structure (caps, 0); + if (gst_structure_get_fraction (s, "framerate", &n, &d)) + fail_unless (n >= 0 && d > 0); + + gst_event_unref (event); + break; + } + fail_unless (seen); + + gst_harness_teardown (h); +} + +GST_END_TEST; + +GST_START_TEST (test_timing_info_framerate) +{ + /* Two sequence headers, both yielding a 30/1 framerate: the first + * with time_scale = 30000 and num_units_in_display_tick = 1000, the + * second with time_scale = 4294967280 and num_units_in_display_tick = + * 143165576, whose unreduced numerator does not fit a gint but whose + * fraction reduces to 30/1. */ + static const guint8 stream = { + 0x0a, 0x11, 0x04, 0x00, 0x00, 0x0f, 0xa0, 0x00, 0x01, 0xd4, 0xc3, 0x00, + 0x00, 0x05, 0x33, 0xff, 0x00, 0x68, 0x02 + }; + static const guint8 big_stream = { + 0x0a, 0x11, 0x04, 0x22, 0x22, 0x22, 0x23, 0xff, 0xff, 0xff, 0xc3, 0x00, + 0x00, 0x05, 0x33, 0xff, 0x00, 0x68, 0x02 + }; + const guint8 *streams = { stream, big_stream }; + gsize stream_sizes = { sizeof (stream), sizeof (big_stream) }; + GstHarness *h; + GstBuffer *buf; + GstEvent *event; + gboolean seen; + guint i; + + for (i = 0; i < G_N_ELEMENTS (streams); i++) { + seen = FALSE; + + h = gst_harness_new_parse ("av1parse"); + gst_harness_set_src_caps_str (h, "video/x-av1"); + + buf = gst_buffer_new_and_alloc (stream_sizesi); + gst_buffer_fill (buf, 0, streamsi, stream_sizesi); + fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK); + + gst_harness_push_event (h, gst_event_new_eos ()); + + while ((event = gst_harness_pull_event (h)) != NULL) { + GstCaps *caps; + const GstStructure *s; + gint n = 0, d = 1; + + if (GST_EVENT_TYPE (event) != GST_EVENT_CAPS) { + gst_event_unref (event); + continue; + } + + gst_event_parse_caps (event, &caps); + s = gst_caps_get_structure (caps, 0); + if (gst_structure_get_fraction (s, "framerate", &n, &d)) { + fail_unless_equals_int (n, 30); + fail_unless_equals_int (d, 1); + seen = TRUE; + } + + gst_event_unref (event); + break; + } + + fail_unless (seen); + + gst_harness_teardown (h); + } +} + +GST_END_TEST; + +GST_START_TEST (test_uvlc_invalid) +{ + GstHarness *h; + GstBuffer *buf; + /* Sequence header OBU with timing information whose uvlc-encoded + * num_ticks_per_picture_minus_1 used to trigger a 1 << 31 shift, + * which is undefined behaviour for a signed literal. */ + const guint8 stream = { + 0x0a, 0x11, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x3d, 0x01, 0xa2, 0x00, + 0x00, 0x00, 0x02, 0x33, 0xff, 0x00, 0x68, 0x02 + }; + + h = gst_harness_new_parse ("av1parse"); + gst_harness_set_src_caps_str (h, "video/x-av1"); + + buf = gst_buffer_new_and_alloc (sizeof (stream)); + gst_buffer_fill (buf, 0, stream, sizeof (stream)); + fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK); + + gst_harness_push_event (h, gst_event_new_eos ()); + + gst_harness_teardown (h); +} + +GST_END_TEST; + +GST_START_TEST (test_sequence_header_truncated) +{ + GstHarness *h; + GstBuffer *buf; + /* Sequence header OBU declaring frame_width_bits_minus_1 = 15 and + * frame_height_bits_minus_1 = 13 while the OBU data ends before both + * frame sizes are encoded. This used to read past the end of the OBU + * data. */ + const guint8 stream = { + 0x0a, 0x07, 0x00, 0x07, 0x00, 0xfd, 0xfd, 0xff, 0x02 + }; + + h = gst_harness_new_parse ("av1parse"); + gst_harness_set_src_caps_str (h, "video/x-av1"); + + buf = gst_buffer_new_and_alloc (sizeof (stream)); + gst_buffer_fill (buf, 0, stream, sizeof (stream)); + fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK); + + gst_harness_push_event (h, gst_event_new_eos ()); + + gst_harness_teardown (h); +} + +GST_END_TEST; + +GST_START_TEST (test_tile_group_extent) +{ + GstHarness *h; + GstBuffer *buf; + /* Frame OBU with a tile group whose tg_end (255) exceeds the tile + * count (192). The tile rows derived from tg_end used to index past + * the parser mi_row_starts table. */ + const guint8 bytestream = { + 0x0a, 0x0b, 0x00, 0x00, 0x00, 0x3c, 0x5c, 0xff, 0xff, 0xc0, 0x1a, 0x00, + 0x80, 0x32, 0x97, 0x04, 0x10, 0x77, 0xe0, 0x00, 0x00, 0x00, 0x80, 0x7f, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }; + + h = gst_harness_new_parse ("av1parse"); + gst_harness_set_src_caps_str (h, "video/x-av1"); + + buf = gst_buffer_new_and_alloc (sizeof (bytestream)); + gst_buffer_fill (buf, 0, bytestream, sizeof (bytestream)); + fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK); + + gst_harness_push_event (h, gst_event_new_eos ()); + + gst_harness_teardown (h); +} + +GST_END_TEST; + +GST_START_TEST (test_tile_group_tg_size_large) +{ + GstHarness *h; + GstBuffer *buf; + /* Frame OBU with a tile group using explicit (non-uniform) tile + * sizes. tg_size_minus_1 is a 4-byte little-endian value; the parser + * assembled it by shifting bytes as int, so a value with the top + * byte >= 0x80 caused a signed integer overflow. */ + const guint8 bytestream = { + 0x0a, 0x0b, 0x00, 0x00, 0x00, 0x3c, 0x5c, 0xff, 0xff, 0xc0, 0x1a, 0x00, + 0x80, 0x32, 0x67, 0x00, 0x00, 0x00, 0x00, 0x2f, 0x74, 0x61, 0x72, 0x67, + 0x65, 0x74, 0x2f, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xba, 0x21, 0x1a, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x6d, 0x69, 0x6e, 0x73, 0x69, 0x7a, 0x65, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x70, 0x65, 0x6e, 0x64, 0x2d, 0x73, 0x00, 0x00, 0xfe, 0xff, 0xff, + 0xff, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0x00, 0x00, + }; + + h = gst_harness_new_parse ("av1parse"); + gst_harness_set_src_caps_str (h, "video/x-av1"); + + buf = gst_buffer_new_and_alloc (sizeof (bytestream)); + gst_buffer_fill (buf, 0, bytestream, sizeof (bytestream)); + fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK); + + gst_harness_push_event (h, gst_event_new_eos ()); + + gst_harness_teardown (h); +} + +GST_END_TEST; + +/* Frame header taking its size from a reference frame slot that was + * never filled. The zero size propagated into the tile grid and divided + * by zero computing the maximum tile height. */ +GST_START_TEST (test_frame_size_ref_unavailable) +{ + GstHarness *h; + GstBuffer *buf; + const guint8 bytestream = { + 0x0a, 0x0b, 0x00, 0x00, 0x00, 0x3c, 0x5c, 0xff, 0xff, 0xc0, 0x1a, 0x00, + 0x80, 0x32, 0x97, 0x00, 0x00, 0x04, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, + 0x32, 0x32, 0xf5, 0x1a, 0x0d, 0xff, 0xc0, 0x1a, 0x00, 0x80, 0x32, 0x97, + 0x00, 0x00, 0x04, 0x32, 0x32, 0x32, 0xf5, 0x0d, 0xff, 0xc0, 0x1a, 0x00, + 0x09, 0x03, 0x00, 0x00, 0x01, 0x33, 0xff, 0x00, 0x00, 0x01, 0x02, 0x74, + 0x74, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x79, 0x00, 0x0d, 0x02, 0x00, + 0x00, 0x00, 0x79, 0x00, 0x11, 0x41, 0x40, 0x32, 0x32, 0x00, 0x00, 0x32, + 0x32, 0x32, 0x32, 0xf5, 0x03, 0x1a, 0x01, + }; + + h = gst_harness_new_parse ("av1parse"); + gst_harness_set_src_caps_str (h, "video/x-av1"); + + buf = gst_buffer_new_and_alloc (sizeof (bytestream)); + gst_buffer_fill (buf, 0, bytestream, sizeof (bytestream)); + fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK); + + fail_unless (gst_harness_push_event (h, gst_event_new_eos ())); + + gst_harness_teardown (h); +} + +GST_END_TEST; + +/* Frame header with global motion parameters whose decoded + * sub-exponential value is negative; the parser shifted that value as + * int to scale it to the warp model precision, which is undefined + * behaviour. The stream is pushed chunked the way the fuzzer harness + * splits it. */ +GST_START_TEST (test_global_motion_negative_shift) +{ + GstHarness *h; + GstBuffer *buf; + const guint8 bytestream = { + 0x0a, 0x0b, 0x00, 0x00, 0x00, 0x3c, 0x5c, 0xff, 0xff, 0xc0, 0x1a, 0x00, + 0x80, 0x32, 0x97, 0x00, 0x00, 0x04, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, + 0x32, 0x32, 0xf5, 0x1a, 0x0d, 0xff, 0xc0, 0x1a, 0x00, 0x80, 0x32, 0x97, + 0x00, 0x00, 0x04, 0x32, 0x32, 0x32, 0xf5, 0x00, 0x00, 0x01, 0x00, 0x3d, + 0x09, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0xa0, 0x01, 0x68, 0x79, 0x00, + 0x0d, 0x02, 0x00, 0x00, 0x1a, 0x0d, 0xff, 0xc0, 0x1a, 0x00, 0x09, 0x03, + 0x00, 0x3f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0x61, 0x72, + 0x93, 0xa2, 0xba, 0x56, 0xa2, 0x00, 0x01, + }; + const guint chunk_count = bytestream0 % 4 + 1; + gsize remaining = sizeof (bytestream); + gsize offset = 0; + guint i; + + h = gst_harness_new_parse ("av1parse"); + gst_harness_set_src_caps_str (h, "video/x-av1"); + + for (i = 0; i < chunk_count; i++) { + gsize chunk_size = + (i == chunk_count - 1) ? remaining : remaining / (chunk_count - i); + + buf = gst_buffer_new_and_alloc (chunk_size); + gst_buffer_fill (buf, 0, bytestream + offset, chunk_size); + fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK); + offset += chunk_size; + remaining -= chunk_size; + } + + fail_unless (gst_harness_push_event (h, gst_event_new_eos ())); + + gst_harness_teardown (h); +} + +GST_END_TEST; + static Suite * av1parse_suite (void) { @@ -372,6 +722,16 @@ tcase_add_test (tc_chain, test_annexb_to_obu); tcase_add_test (tc_chain, test_byte_to_obu); + tcase_add_test (tc_chain, test_timing_info_invalid_framerate); + tcase_add_test (tc_chain, test_timing_info_framerate); + tcase_add_test (tc_chain, test_uvlc_invalid); + tcase_add_test (tc_chain, test_sequence_header_truncated); + tcase_add_test (tc_chain, test_tile_group_extent); + tcase_add_test (tc_chain, test_tile_group_tg_size_large); + tcase_add_test (tc_chain, test_frame_size_ref_unavailable); + + tcase_add_test (tc_chain, test_global_motion_negative_shift); + return s; }
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/tests/check/elements/h263parse.c -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/tests/check/elements/h263parse.c
Changed
@@ -24,6 +24,7 @@ */ #include <gst/check/gstcheck.h> +#include <gst/check/gstharness.h> #include "parser.h" #define SRC_CAPS_TMPL "video/x-h263, variant=(string)itu, parsed=(boolean)false" @@ -127,6 +128,33 @@ GST_END_TEST; +GST_START_TEST (test_parse_custom_pcf_zero) +{ + GstHarness *h; + GstBuffer *buf; + /* PSC with a custom picture clock frequency code of 0. The code is + * 7 bits with a valid range of 1..127; the parser used it directly as + * a framerate denominator, so a zero code tripped the + * _gst_util_uint64_scale_int() assertion instead of failing the + * parse. */ + const guint8 bytestream = { + 0x00, 0x00, 0x82, 0x82, 0xbc, 0xfb, 0x01, 0x03, 0x10, 0x00, + }; + + h = gst_harness_new_parse ("h263parse"); + gst_harness_set_src_caps_str (h, "video/x-h263"); + + buf = gst_buffer_new_and_alloc (sizeof (bytestream)); + gst_buffer_fill (buf, 0, bytestream, sizeof (bytestream)); + fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK); + + gst_harness_push_event (h, gst_event_new_eos ()); + + gst_harness_teardown (h); +} + +GST_END_TEST; + static Suite * h263parse_suite (void) @@ -146,6 +174,7 @@ tcase_add_test (tc_chain, test_parse_drain_single); tcase_add_test (tc_chain, test_parse_split); tcase_add_test (tc_chain, test_parse_detect_stream); + tcase_add_test (tc_chain, test_parse_custom_pcf_zero); return s; }
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/tests/check/elements/h264parse.c -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/tests/check/elements/h264parse.c
Changed
@@ -374,6 +374,57 @@ GST_END_TEST; +GST_START_TEST (test_parse_reject_forbidden_nal_header) +{ + const guint8 bogus_subset_sps = { + 0x00, 0x00, 0x00, 0x01, 0xaf, 0x49, 0x00, 0xf0, + 0xae, 0x49, 0x00 + }; + guint8 ausizeof (h264_sps) + sizeof (h264_pps) + sizeof (h264_idrframe); + GstHarness *h = gst_harness_new ("h264parse"); + GstCaps *caps; + const GstStructure *s; + gint width, height, new_width, new_height; + + gst_harness_set_caps_str (h, + "video/x-h264,stream-format=byte-stream,alignment=au", + "video/x-h264,stream-format=byte-stream,alignment=au"); + + memcpy (au, h264_sps, sizeof (h264_sps)); + memcpy (au + sizeof (h264_sps), h264_pps, sizeof (h264_pps)); + memcpy (au + sizeof (h264_sps) + sizeof (h264_pps), h264_idrframe, + sizeof (h264_idrframe)); + fail_unless_equals_int (gst_harness_push (h, + gst_buffer_new_memdup (au, sizeof (au))), GST_FLOW_OK); + + caps = gst_pad_get_current_caps (h->sinkpad); + fail_unless (caps != NULL); + s = gst_caps_get_structure (caps, 0); + fail_unless (gst_structure_get_int (s, "width", &width)); + fail_unless (gst_structure_get_int (s, "height", &height)); + gst_caps_unref (caps); + + fail_unless_equals_int (gst_harness_push (h, + gst_buffer_new_memdup (bogus_subset_sps, + sizeof (bogus_subset_sps))), GST_FLOW_OK); + fail_unless_equals_int (gst_harness_push (h, + gst_buffer_new_memdup (h264_idrframe, + sizeof (h264_idrframe))), GST_FLOW_OK); + + caps = gst_pad_get_current_caps (h->sinkpad); + fail_unless (caps != NULL); + s = gst_caps_get_structure (caps, 0); + fail_unless (gst_structure_get_int (s, "width", &new_width)); + fail_unless (gst_structure_get_int (s, "height", &new_height)); + fail_unless_equals_int (width, new_width); + fail_unless_equals_int (height, new_height); + gst_caps_unref (caps); + + gst_harness_teardown (h); +} + +GST_END_TEST; + GST_START_TEST (test_parse_drain_single) { @@ -700,6 +751,8 @@ suite_add_tcase (s, tc_chain); tcase_add_test (tc_chain, test_parse_normal); + if (ctx_sink_template == &sinktemplate_bs_au) + tcase_add_test (tc_chain, test_parse_reject_forbidden_nal_header); tcase_add_test (tc_chain, test_parse_drain_single); tcase_add_test (tc_chain, test_parse_drain_garbage); tcase_add_test (tc_chain, test_parse_split); @@ -1200,6 +1253,57 @@ } +GST_START_TEST (test_parse_forbidden_nal_progress) +{ + static const guint8 forbidden = { 0x00, 0x00, 0x00, 0x01, 0xb2, 0x05 }; + GstHarness *h = gst_harness_new ("h264parse"); + GstBuffer *buf; + guint pictures = 0; + + gst_harness_set_caps_str (h, + (__i__ & 1) ? "video/x-h264, stream-format=byte-stream" : + "video/x-h264, stream-format=byte-stream, alignment=au", + "video/x-h264, stream-format=byte-stream, alignment=au"); + + buf = composite_buffer (0, 0, 4, + h264_aud, sizeof (h264_aud), + h264_slicing_sps, sizeof (h264_slicing_sps), + h264_slicing_pps, sizeof (h264_slicing_pps), + h264_idr_slice_1, sizeof (h264_idr_slice_1)); + fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK); + + /* Exercise a forbidden NAL both at the start of a buffer and after an AUD. */ + if (__i__ & 2) + buf = composite_buffer (GST_SECOND, 0, 2, + h264_aud, sizeof (h264_aud), forbidden, sizeof (forbidden)); + else + buf = composite_buffer (GST_SECOND, 0, 1, forbidden, sizeof (forbidden)); + fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK); + + buf = composite_buffer (2 * GST_SECOND, 0, 2, + h264_aud, sizeof (h264_aud), h264_idr_slice_1, sizeof (h264_idr_slice_1)); + fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK); + /* A following start code completes the delimiter in unaligned input. */ + buf = composite_buffer (3 * GST_SECOND, 0, 2, + h264_aud, sizeof (h264_aud), h264_aud, sizeof (h264_aud)); + fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK); + + /* Both pictures must arrive before EOS, rather than waiting behind metadata. */ + while ((buf = gst_harness_try_pull (h))) { + gsize size = gst_buffer_get_size (buf); + + if (size >= sizeof (h264_idr_slice_1) && + gst_buffer_memcmp (buf, size - sizeof (h264_idr_slice_1), + h264_idr_slice_1, sizeof (h264_idr_slice_1)) == 0) + pictures++; + gst_buffer_unref (buf); + } + fail_unless_equals_int (pictures, 2); + gst_harness_teardown (h); +} + +GST_END_TEST; + GST_START_TEST (test_parse_sei_closedcaptions) { GstVideoCaptionMeta *cc; @@ -1696,6 +1800,127 @@ GST_END_TEST; +/* Some cameras (seen with ACTi) append a metadata trailer to every slice + * NAL. It starts with an MPEG start code and, depending on the counter it + * carries, can contain a real 4-byte start code as well: + * + * 00 00 01 b2 05 00 00 00 01 4a 00 00 46 ... 00 00 00 00 + * + * In AU alignment the parser ends the AU at the first bogus start code and + * the trailer becomes the next frame: "b2 05" is collected, "4a" is a + * 1-byte NAL, and the rest holds no start code at all. That NO_NAL result + * used to finish a zero-sized frame and crash baseparse. */ +static const guint8 h264_acti_trailer = { + 0x00, 0x00, 0x01, 0xb2, 0x05, 0x00, 0x00, 0x00, 0x01, 0x4a, 0x00, 0x00, + 0x46, 0xc5, 0xea, 0x64, 0x0c, 0x01, 0x00, 0x03, 0xd3, 0x0a, 0x04, 0x00, + 0x45, 0x12, 0x00, 0x1e, 0x46, 0xc5, 0xea, 0x64, 0x8a, 0x4f, 0x0a, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +GST_START_TEST (test_parse_bytestream_junk_after_au) +{ + GstHarness *h; + GstBuffer *buf; + gsize au_size; + + h = gst_harness_new ("h264parse"); + gst_harness_set_caps_str (h, + "video/x-h264, stream-format=byte-stream, alignment=au", + "video/x-h264, stream-format=byte-stream, alignment=au"); + + /* One AU (SPS, PPS, IDR) followed by the trailer, as a depayloader in AU + * alignment would deliver it */ + au_size = sizeof (h264_sps) + sizeof (h264_pps) + sizeof (h264_idrframe); + buf = composite_buffer (100, 0, 4, h264_sps, sizeof (h264_sps), + h264_pps, sizeof (h264_pps), h264_idrframe, sizeof (h264_idrframe), + h264_acti_trailer, sizeof (h264_acti_trailer)); + fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK); + + /* Draining what is left of the trailer must not crash either */ + fail_unless (gst_harness_push_event (h, gst_event_new_eos ())); + + /* The real AU comes out intact (with the AUD the parser inserts in AU + * alignment), before anything made of the trailer */ + fail_unless (gst_harness_buffers_in_queue (h) >= 1); + buf = gst_harness_pull (h); + fail_unless_equals_int (gst_buffer_get_size (buf), + sizeof (h264_aud) + au_size); + fail_unless (gst_buffer_memcmp (buf, 0, h264_aud, sizeof (h264_aud)) == 0); + fail_unless (gst_buffer_memcmp (buf, sizeof (h264_aud), h264_sps, + sizeof (h264_sps)) == 0); + fail_unless (gst_buffer_memcmp (buf, sizeof (h264_aud) + sizeof (h264_sps), + h264_pps, sizeof (h264_pps)) == 0); + fail_unless (gst_buffer_memcmp (buf, + sizeof (h264_aud) + sizeof (h264_sps) + sizeof (h264_pps), + h264_idrframe, sizeof (h264_idrframe)) == 0); + gst_buffer_unref (buf); + + gst_harness_teardown (h); +} + +GST_END_TEST; + +GST_START_TEST (test_non_vcl_nal_duration) +{ + GstCaps *in_caps, *out_caps; + GstBuffer *buf_in, *buf_out; + GstClockTime expected_duration; + GstHarness *h = gst_harness_new ("h264parse"); + const GstClockTime fake_duration = 12345 * GST_MSECOND; + + const gchar *in_caps_str = + "video/x-h264, alignment=(string)nal, framerate=30/1"; + const gchar *out_caps_str = "video/x-h264, alignment=(string)nal"; + + in_caps = gst_caps_from_string (in_caps_str); + out_caps = gst_caps_from_string (out_caps_str); + gst_harness_set_caps (h, in_caps, out_caps); + + /* Push SPS, PPS with an arbitrary non-zero duration */ + buf_in = wrap_buffer (h264_sps, sizeof (h264_sps), 0, 0); + GST_BUFFER_DURATION (buf_in) = fake_duration; + fail_unless_equals_int (gst_harness_push (h, buf_in), GST_FLOW_OK); + + buf_in = wrap_buffer (h264_pps, sizeof (h264_pps), 0, 0); + GST_BUFFER_DURATION (buf_in) = fake_duration; + fail_unless_equals_int (gst_harness_push (h, buf_in), GST_FLOW_OK); + + /* Push an IDR slice (VCL) to complete the AU */ + buf_in = wrap_buffer (h264_idrframe, sizeof (h264_idrframe), 0, 0); + fail_unless_equals_int (gst_harness_push (h, buf_in), GST_FLOW_OK); + + /* With framerate=30/1, a VCL frame should get duration = 1/30 s */ + expected_duration = gst_util_uint64_scale (GST_SECOND, 1, 30); + + /* First AU produces: AUD + SPS + PPS + slice = 4 buffers + * (h264parse inserts an AUD at the start of each AU) */ + fail_unless_equals_int (gst_harness_buffers_in_queue (h), 4); + + /* AUD - non-VCL, must have duration=0 */ + buf_out = gst_harness_pull (h); + fail_unless_equals_clocktime (GST_BUFFER_DURATION (buf_out), 0); + gst_buffer_unref (buf_out); + + /* SPS - non-VCL, must have duration=0 */ + buf_out = gst_harness_pull (h); + fail_unless_equals_clocktime (GST_BUFFER_DURATION (buf_out), 0); + gst_buffer_unref (buf_out); + + /* PPS - non-VCL, must have duration=0 */ + buf_out = gst_harness_pull (h); + fail_unless_equals_clocktime (GST_BUFFER_DURATION (buf_out), 0); + gst_buffer_unref (buf_out); + + /* IDR slice - VCL, must have the fps-based duration */ + buf_out = gst_harness_pull (h); + fail_unless_equals_clocktime (GST_BUFFER_DURATION (buf_out), + expected_duration); + gst_buffer_unref (buf_out); + + gst_harness_teardown (h); +} + +GST_END_TEST; /* * TODO: @@ -1805,6 +2030,7 @@ s = suite_create ("h264parse"); suite_add_tcase (s, tc_chain); + tcase_add_loop_test (tc_chain, test_parse_forbidden_nal_progress, 0, 4); tcase_add_test (tc_chain, test_parse_sei_closedcaptions); tcase_add_test (tc_chain, test_parse_compatible_caps); tcase_add_test (tc_chain, test_parse_skip_to_4bytes_sc); @@ -1812,6 +2038,8 @@ tcase_add_test (tc_chain, test_parse_sei_userdefinedunregistered); tcase_add_test (tc_chain, test_parse_to_avc3_without_sps); tcase_add_test (tc_chain, test_packetized_avc_drop_corrupt); + tcase_add_test (tc_chain, test_parse_bytestream_junk_after_au); + tcase_add_test (tc_chain, test_non_vcl_nal_duration); nf += gst_check_run_suite (s, "h264parse", __FILE__); }
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/tests/check/elements/h265parse.c -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/tests/check/elements/h265parse.c
Changed
@@ -1033,6 +1033,74 @@ GST_END_TEST; +GST_START_TEST (test_parse_reject_forbidden_nal_header) +{ + GstHarness *h = gst_harness_new ("h265parse"); + guint8 bad_spssizeof (h265_sps); + GstBuffer *buf; + GstMapInfo map; + guint count = 0; + gboolean seen_idr = FALSE; + + memcpy (bad_sps, h265_sps, sizeof (bad_sps)); + bad_sps4 |= 0x80; + + gst_harness_set_caps_str (h, + "video/x-h265,stream-format=byte-stream,alignment=nal", + "video/x-h265,stream-format=byte-stream,alignment=nal"); + buf = composite_buffer (100, 0, 5, h265_vps, sizeof (h265_vps), + h265_sps, sizeof (h265_sps), h265_pps, sizeof (h265_pps), + bad_sps, sizeof (bad_sps), h265_idr, sizeof (h265_idr)); + fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK); + gst_harness_push_event (h, gst_event_new_eos ()); + + while (gst_harness_buffers_in_queue (h)) { + buf = gst_harness_pull (h); + fail_unless (gst_buffer_map (buf, &map, GST_MAP_READ)); + fail_unless (map.size >= 6); + fail_unless_equals_int (map.data4 & 0x80, 0); + if (map.data4 == h265_idr4 && map.data5 == h265_idr5) + seen_idr = TRUE; + gst_buffer_unmap (buf, &map); + gst_buffer_unref (buf); + count++; + } + fail_unless (count >= 3); + fail_unless (seen_idr); + + gst_harness_teardown (h); +} + +GST_END_TEST; + +GST_START_TEST (test_parse_preserve_au_before_forbidden_nal) +{ + GstHarness *h = gst_harness_new ("h265parse"); + guint8 bad_spssizeof (h265_sps); + GstBuffer *buf; + + memcpy (bad_sps, h265_sps, sizeof (bad_sps)); + bad_sps4 |= 0x80; + + gst_harness_set_caps_str (h, + "video/x-h265,stream-format=byte-stream,alignment=au", + "video/x-h265,stream-format=byte-stream,alignment=au"); + buf = composite_buffer (100, 0, 5, h265_vps, sizeof (h265_vps), + h265_sps, sizeof (h265_sps), h265_pps, sizeof (h265_pps), + h265_idr, sizeof (h265_idr), bad_sps, sizeof (bad_sps)); + fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK); + fail_unless (gst_harness_push_event (h, gst_event_new_eos ())); + + fail_unless (gst_harness_buffers_in_queue (h) >= 1); + pull_and_check_composite (h, 100, 0, 5, h265_aud, sizeof (h265_aud), + h265_vps, sizeof (h265_vps), h265_sps, sizeof (h265_sps), + h265_pps, sizeof (h265_pps), h265_idr, sizeof (h265_idr)); + + gst_harness_teardown (h); +} + +GST_END_TEST; + GST_START_TEST (test_parse_sc_with_half_header) { GstHarness *h; @@ -1315,6 +1383,59 @@ GST_END_TEST; +GST_START_TEST (test_parse_vui_invalid_framerate) +{ + GstHarness *h; + GstBuffer *buf; + GstEvent *event; + gboolean seen = FALSE; + /* SPS with VUI timing time_scale = 0x80000000 and + * num_units_in_tick = 0xFFFFFFFF plus a picture timing SEI marking field + * pictures. The timing values do not fit the gint framerate and used to + * trigger undefined behaviour (G_MININT % -1 inside + * gst_util_greatest_common_divisor) in the field-rate calculation. */ + const guint8 bytestream = { + 0x00, 0x00, 0x01, 0x42, 0x01, 0x01, 0x01, 0x80, 0x00, 0x03, 0x74, 0x61, + 0x72, 0x67, 0x65, 0x74, 0x2f, 0x1e, 0xa0, 0x81, 0x05, 0xff, 0xf0, 0x88, + 0x17, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, + 0x01, 0x4e, 0x01, 0x01, 0x01, 0x10, + }; + + h = gst_harness_new_parse ("h265parse"); + gst_harness_set_src_caps_str (h, "video/x-h265"); + + buf = gst_buffer_new_and_alloc (sizeof (bytestream)); + gst_buffer_fill (buf, 0, bytestream, sizeof (bytestream)); + fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK); + + gst_harness_push_event (h, gst_event_new_eos ()); + + while ((event = gst_harness_pull_event (h)) != NULL) { + GstCaps *caps; + const GstStructure *s; + gint n = 0, d = 1; + + if (GST_EVENT_TYPE (event) != GST_EVENT_CAPS) { + gst_event_unref (event); + continue; + } + + seen = TRUE; + gst_event_parse_caps (event, &caps); + s = gst_caps_get_structure (caps, 0); + if (gst_structure_get_fraction (s, "framerate", &n, &d)) + fail_unless (n >= 0 && d > 0); + + gst_event_unref (event); + break; + } + fail_unless (seen); + + gst_harness_teardown (h); +} + +GST_END_TEST; + GST_START_TEST (test_packetized_hvcc_drop_corrupt) { GstBuffer *cdata; @@ -1418,6 +1539,181 @@ GST_END_TEST; +GST_START_TEST (test_parse_scc_palette_empty_range) +{ + GstHarness *h; + GstBuffer *buf; + GstCaps *caps; + /* SPS with an SCC extension enabling the palette mode with + * palette_max_size = delta_palette_max_predictor_size = 0 while + * predictor initializers are present. The bound for + * sps_num_palette_predictor_initializer_minus1 then underflows, which + * used to accept any value and write past the initializer arrays. + * The SPS must be rejected. */ + const guint8 bytestream = { + 0x00, 0x00, 0x01, 0x42, 0x01, 0x01, 0x01, 0x80, 0x00, 0x03, 0x00, 0x80, + 0x00, 0x03, 0x00, 0x03, 0x00, 0x1e, 0x08, 0x20, 0x20, 0x81, 0x05, 0xff, + 0xf0, 0x84, 0x41, 0xe0, 0x10, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7b, 0x00, + 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf1, 0x85, 0xb9, 0xd2, + 0xb7, 0x7b, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xf1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf1, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xf1, 0xf1, + }; + + h = gst_harness_new_parse ("h265parse"); + gst_harness_set_src_caps_str (h, "video/x-h265"); + + buf = gst_buffer_new_and_alloc (sizeof (bytestream)); + gst_buffer_fill (buf, 0, bytestream, sizeof (bytestream)); + fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK); + + gst_harness_push_event (h, gst_event_new_eos ()); + + /* The SPS is rejected, so the element must not have pushed caps + * describing it. */ + caps = gst_pad_get_current_caps (h->srcpad); + if (caps != NULL) { + const GstStructure *s = gst_caps_get_structure (caps, 0); + fail_unless (!gst_structure_has_field (s, "width"), + "SPS with empty palette predictor range must be rejected"); + gst_caps_unref (caps); + } + + gst_harness_teardown (h); +} + +GST_END_TEST; + +/* Picture with a timecode SEI while the VUI timing signals + * time_scale = 0. Scaling the timecode frame count divides by + * fps_d * time_scale, which trips a critical inside + * gst_util_uint64_scale(). The timecode is only processed when the + * stream arrives in several buffers, so push the stream chunked the + * same way the fuzzer harness splits it. */ +GST_START_TEST (test_timecode_zero_time_scale) +{ + GstHarness *h; + GstBuffer *buf; + const guint8 bytestream = { + 0x65, 0x72, 0x61, 0x6d, 0x68, 0x18, 0x00, 0x00, 0x00, 0x72, 0x00, 0xfe, + 0xff, 0xff, 0xff, 0x28, 0xfe, 0x07, 0xd0, 0x00, 0x00, 0x01, 0x4e, 0x85, + 0x88, 0x04, 0xff, 0xff, 0xff, 0x00, 0x67, 0x61, 0x01, 0x00, 0x00, 0x00, + 0x67, 0x65, 0x74, 0x00, 0x00, 0x7f, 0xb1, 0xee, 0x00, 0x00, 0x01, 0x42, + 0x01, 0x01, 0x80, 0x00, 0x03, 0x00, 0x80, 0x00, 0x8d, 0x00, 0x00, 0x74, + 0x01, 0x5c, 0x72, 0x81, 0x05, 0xff, 0xf0, 0x88, 0x2f, 0x74, 0x61, 0x72, + 0x67, 0x65, 0x74, 0x2f, 0x00, 0x40, 0x00, 0x00, 0x01, 0x00, 0x72, 0x2f, + 0x00, 0x00, 0x01, 0x5c, 0x72, + }; + + h = gst_harness_new_parse ("h265parse"); + gst_harness_set_src_caps_str (h, "video/x-h265"); + + { + const guint chunk_count = bytestream0 % 4 + 1; + gsize remaining = sizeof (bytestream); + gsize offset = 0; + guint i; + + for (i = 0; i < chunk_count; i++) { + gsize chunk_size = + (i == chunk_count - 1) ? remaining : remaining / (chunk_count - i); + + buf = gst_buffer_new_and_alloc (chunk_size); + gst_buffer_fill (buf, 0, bytestream + offset, chunk_size); + fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK); + offset += chunk_size; + remaining -= chunk_size; + } + } + + fail_unless (gst_harness_push_event (h, gst_event_new_eos ())); + + gst_harness_teardown (h); +} + +GST_END_TEST; + +GST_START_TEST (test_non_vcl_nal_duration) +{ + /* Verify that non-VCL NALs (VPS, SPS, PPS) get duration=0 while + * VCL NALs (slices) get the proper fps-based duration. + * Regression test for: "h265parse: only extrapolate duration for vcl nal" + * + * Push non-VCL NALs with an arbitrary non-zero PTS to make it clear + * that the resulting duration=0 is a deliberate parser decision, not + * an artifact of the input timestamps. + */ + + GstCaps *in_caps, *out_caps; + GstBuffer *buf_in, *buf_out; + GstClockTime expected_duration; + GstHarness *h = gst_harness_new ("h265parse"); + const GstClockTime fake_dts = 12345 * GST_MSECOND; + + const gchar *in_caps_str = "video/x-h265, alignment=(string)nal"; + const gchar *out_caps_str = "video/x-h265, alignment=(string)nal"; + + in_caps = gst_caps_from_string (in_caps_str); + out_caps = gst_caps_from_string (out_caps_str); + gst_harness_set_caps (h, in_caps, out_caps); + + /* Push VPS, SPS, PPS with an arbitrary non-zero PTS */ + buf_in = wrap_buffer (h265_128x128_vps, sizeof (h265_128x128_vps), 0, 0); + GST_BUFFER_DURATION (buf_in) = fake_dts; + fail_unless_equals_int (gst_harness_push (h, buf_in), GST_FLOW_OK); + + buf_in = wrap_buffer (h265_128x128_sps, sizeof (h265_128x128_sps), 0, 0); + GST_BUFFER_DURATION (buf_in) = fake_dts; + fail_unless_equals_int (gst_harness_push (h, buf_in), GST_FLOW_OK); + + buf_in = wrap_buffer (h265_128x128_pps, sizeof (h265_128x128_pps), 0, 0); + GST_BUFFER_DURATION (buf_in) = fake_dts; + fail_unless_equals_int (gst_harness_push (h, buf_in), GST_FLOW_OK); + + /* Push an IDR slice (VCL) to complete the AU */ + buf_in = wrap_buffer (h265_128x128_slice_idr_n_lp, + sizeof (h265_128x128_slice_idr_n_lp), 0, 0); + fail_unless_equals_int (gst_harness_push (h, buf_in), GST_FLOW_OK); + + /* With framerate=30/1, a VCL frame should get duration = 1/30 s */ + expected_duration = gst_util_uint64_scale (GST_SECOND, 1, 30); + + /* First AU produces: VPS + SPS + PPS + slice = 4 buffers */ + fail_unless_equals_int (gst_harness_buffers_in_queue (h), 4); + + /* VPS - non-VCL, must have duration=0 */ + buf_out = gst_harness_pull (h); + fail_unless_equals_clocktime (GST_BUFFER_DURATION (buf_out), 0); + gst_buffer_unref (buf_out); + + /* SPS - non-VCL, must have duration=0 */ + buf_out = gst_harness_pull (h); + fail_unless_equals_clocktime (GST_BUFFER_DURATION (buf_out), 0); + gst_buffer_unref (buf_out); + + /* PPS - non-VCL, must have duration=0 */ + buf_out = gst_harness_pull (h); + fail_unless_equals_clocktime (GST_BUFFER_DURATION (buf_out), 0); + gst_buffer_unref (buf_out); + + /* IDR slice - VCL, must have the fps-based duration */ + buf_out = gst_harness_pull (h); + fail_unless_equals_clocktime (GST_BUFFER_DURATION (buf_out), + expected_duration); + gst_buffer_unref (buf_out); + + gst_harness_teardown (h); +} + +GST_END_TEST; + static Suite * h265parse_harnessed_suite (void) { @@ -1449,6 +1745,8 @@ tcase_add_test (tc_chain, test_sliced_au_au); tcase_add_test (tc_chain, test_parse_skip_to_4bytes_sc); + tcase_add_test (tc_chain, test_parse_reject_forbidden_nal_header); + tcase_add_test (tc_chain, test_parse_preserve_au_before_forbidden_nal); tcase_add_test (tc_chain, test_parse_sc_with_half_header); tcase_add_test (tc_chain, test_drain); @@ -1457,7 +1755,13 @@ tcase_add_test (tc_chain, test_invalid_sei_in_hvcc); tcase_add_test (tc_chain, test_parse_fallback_profile); + tcase_add_test (tc_chain, test_parse_vui_invalid_framerate); tcase_add_test (tc_chain, test_packetized_hvcc_drop_corrupt); + tcase_add_test (tc_chain, test_non_vcl_nal_duration); + + tcase_add_test (tc_chain, test_parse_scc_palette_empty_range); + + tcase_add_test (tc_chain, test_timecode_zero_time_scale); return s; }
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/tests/check/elements/h266parse.c -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/tests/check/elements/h266parse.c
Changed
@@ -1177,6 +1177,76 @@ GST_END_TEST; +GST_START_TEST (test_parse_reject_forbidden_nal_header) +{ + GstHarness *h = gst_harness_new ("h266parse"); + guint8 bad_spssizeof (h266_sps); + GstBuffer *buf; + GstMapInfo map; + guint count = 0; + gboolean seen_idr = FALSE; + + memcpy (bad_sps, h266_sps, sizeof (bad_sps)); + bad_sps4 |= 0x80; + + gst_harness_set_caps_str (h, + "video/x-h266,stream-format=byte-stream,alignment=nal", + "video/x-h266,stream-format=byte-stream,alignment=nal"); + buf = composite_buffer (100, 0, 6, h266_vps, sizeof (h266_vps), + h266_sps, sizeof (h266_sps), h266_pps, sizeof (h266_pps), + h266_prefix_aps, sizeof (h266_prefix_aps), bad_sps, sizeof (bad_sps), + h266_idr, sizeof (h266_idr)); + fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK); + gst_harness_push_event (h, gst_event_new_eos ()); + + while (gst_harness_buffers_in_queue (h)) { + buf = gst_harness_pull (h); + fail_unless (gst_buffer_map (buf, &map, GST_MAP_READ)); + fail_unless (map.size >= 6); + fail_unless_equals_int (map.data4 & 0x80, 0); + if (map.data4 == h266_idr4 && map.data5 == h266_idr5) + seen_idr = TRUE; + gst_buffer_unmap (buf, &map); + gst_buffer_unref (buf); + count++; + } + fail_unless (count >= 4); + fail_unless (seen_idr); + + gst_harness_teardown (h); +} + +GST_END_TEST; + +GST_START_TEST (test_parse_preserve_au_before_forbidden_nal) +{ + GstHarness *h = gst_harness_new ("h266parse"); + guint8 bad_spssizeof (h266_sps); + GstBuffer *buf; + + memcpy (bad_sps, h266_sps, sizeof (bad_sps)); + bad_sps4 |= 0x80; + + gst_harness_set_caps_str (h, + "video/x-h266,stream-format=byte-stream,alignment=au", + "video/x-h266,stream-format=byte-stream,alignment=au"); + buf = composite_buffer (100, 0, 6, h266_vps, sizeof (h266_vps), + h266_sps, sizeof (h266_sps), h266_pps, sizeof (h266_pps), + h266_prefix_aps, sizeof (h266_prefix_aps), h266_idr, sizeof (h266_idr), + bad_sps, sizeof (bad_sps)); + fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK); + fail_unless (gst_harness_push_event (h, gst_event_new_eos ())); + + fail_unless (gst_harness_buffers_in_queue (h) >= 1); + pull_and_check_composite (h, 100, 0, 5, h266_vps, sizeof (h266_vps), + h266_sps, sizeof (h266_sps), h266_pps, sizeof (h266_pps), + h266_prefix_aps, sizeof (h266_prefix_aps), h266_idr, sizeof (h266_idr)); + + gst_harness_teardown (h); +} + +GST_END_TEST; + GST_START_TEST (test_parse_sc_with_half_nal) { GstHarness *h; @@ -1336,6 +1406,326 @@ GST_END_TEST; + +GST_START_TEST (test_sps_invalid_framerate) +{ + GstHarness *h; + GstBuffer *buf; + GstEvent *event; + gboolean seen = FALSE; + /* SPS with general timing HRD parameters time_scale = 0x80000000 and + * num_units_in_tick = 0xFFFFFFFF and field_seq_flag = 1. The timing + * values do not fit the gint framerate and used to trigger undefined + * behaviour (G_MININT % -1 inside gst_util_greatest_common_divisor) + * in the field-rate calculation. */ + const guint8 bytestream = { + 0x00, 0x00, 0x01, 0x00, 0x79, 0x00, 0x09, 0x02, 0x40, 0x00, 0x00, 0x00, + 0x40, 0x80, 0x81, 0x18, 0x00, 0x55, 0x6c, 0x3e, 0x03, 0x01, 0x04, 0x30, + 0x1f, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x0a, 0x00, 0xfa, 0x40, + }; + + h = gst_harness_new_parse ("h266parse"); + gst_harness_set_src_caps_str (h, "video/x-h266"); + + buf = gst_buffer_new_and_alloc (sizeof (bytestream)); + gst_buffer_fill (buf, 0, bytestream, sizeof (bytestream)); + fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK); + + gst_harness_push_event (h, gst_event_new_eos ()); + + while ((event = gst_harness_pull_event (h)) != NULL) { + GstCaps *caps; + const GstStructure *s; + gint n = 0, d = 1; + + if (GST_EVENT_TYPE (event) != GST_EVENT_CAPS) { + gst_event_unref (event); + continue; + } + + seen = TRUE; + gst_event_parse_caps (event, &caps); + s = gst_caps_get_structure (caps, 0); + if (gst_structure_get_fraction (s, "framerate", &n, &d)) + fail_unless (n >= 0 && d > 0); + + gst_event_unref (event); + break; + } + fail_unless (seen); + + gst_harness_teardown (h); +} + +GST_END_TEST; + +GST_START_TEST (test_sps_hrd_framerate) +{ + GstHarness *h; + GstBuffer *buf; + GstEvent *event; + /* Same SPS as test_sps_invalid_framerate but with time_scale = 30000 + * and num_units_in_tick = 1000, i.e. a 30 Hz field rate halved to a + * 15 Hz frame rate. */ + const guint8 bytestream = { + 0x00, 0x00, 0x01, 0x00, 0x79, 0x00, 0x09, 0x02, 0x40, 0x00, 0x00, 0x03, + 0x00, 0x40, 0x80, 0x81, 0x18, 0x00, 0x55, 0x6c, 0x3e, 0x03, 0x01, 0x04, + 0x30, 0x10, 0x00, 0x00, 0x3e, 0x80, 0x00, 0x07, 0x53, 0x0a, 0x00, 0xfa, + 0x40 + }; + gboolean seen = FALSE; + + h = gst_harness_new_parse ("h266parse"); + gst_harness_set_src_caps_str (h, "video/x-h266"); + + buf = gst_buffer_new_and_alloc (sizeof (bytestream)); + gst_buffer_fill (buf, 0, bytestream, sizeof (bytestream)); + fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK); + + gst_harness_push_event (h, gst_event_new_eos ()); + + while ((event = gst_harness_pull_event (h)) != NULL) { + GstCaps *caps; + const GstStructure *s; + gint n = 0, d = 1; + + if (GST_EVENT_TYPE (event) != GST_EVENT_CAPS) { + gst_event_unref (event); + continue; + } + + gst_event_parse_caps (event, &caps); + s = gst_caps_get_structure (caps, 0); + if (gst_structure_get_fraction (s, "framerate", &n, &d)) { + fail_unless_equals_int (n, 15); + fail_unless_equals_int (d, 1); + seen = TRUE; + } + + gst_event_unref (event); + break; + } + + fail_unless (seen); + + gst_harness_teardown (h); +} + +GST_END_TEST; + +GST_START_TEST (test_chroma_qp_table_bitdepth) +{ + GstHarness *h; + GstBuffer *buf; + /* SPS with bitdepth_minus8 = 8. Generating the chroma QP table used + * to write one entry past the end of the 111-entry table. */ + const guint8 bytestream = { + 0x00, 0x00, 0x00, 0x01, 0x00, 0x79, 0x00, 0x0d, 0x02, 0x00, 0x80, 0x00, + 0x40, 0x20, 0x40, 0x40, 0xd9, 0x3f, 0x09, 0x1b, 0xa4, 0xba, 0x21, 0x1a, + 0x21, 0x49, 0x91, 0xb8, 0x4d, 0x4d, 0x8a, 0x31, 0x03, 0x50, 0xc1, 0xbe, + 0x15, 0x71, 0xfc, 0x1f, 0x8c, 0x40, 0x80 + }; + + h = gst_harness_new_parse ("h266parse"); + gst_harness_set_src_caps_str (h, "video/x-h266"); + + buf = gst_buffer_new_and_alloc (sizeof (bytestream)); + gst_buffer_fill (buf, 0, bytestream, sizeof (bytestream)); + fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK); + + gst_harness_push_event (h, gst_event_new_eos ()); + + gst_harness_teardown (h); +} + +GST_END_TEST; + +GST_START_TEST (test_sh_num_tiles_in_slice) +{ + GstHarness *h; + GstBuffer *buf; + /* Slice header of a picture with non-rectangular slices where + * num_tiles_in_slice_minus1 extends past the last tile of the + * picture. The tile index used to index past the PPS tile row + * array. */ + const guint8 bytestream = { + 0x00, 0x00, 0x01, 0x00, 0x79, 0x00, 0x11, 0x02, 0x40, 0x00, 0x00, 0x03, + 0x01, 0x08, 0x00, 0x37, 0x01, 0x18, 0x00, 0x55, 0x6c, 0x3e, 0x03, 0x01, + 0x04, 0x30, 0x10, 0x00, 0x00, 0x01, 0x00, 0x81, 0x00, 0x00, 0x84, 0x00, + 0x1b, 0x80, 0x80, 0xaf, 0x18, 0x44, 0x88, 0x00, 0x00, 0x01, 0x00, 0x99, + 0xf0, 0x00, 0x00, 0x01, 0x00, 0x01, 0x6d, 0x80, 0x37, 0x10, + }; + + h = gst_harness_new_parse ("h266parse"); + gst_harness_set_src_caps_str (h, "video/x-h266"); + + buf = gst_buffer_new_and_alloc (sizeof (bytestream)); + gst_buffer_fill (buf, 0, bytestream, sizeof (bytestream)); + fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK); + + gst_harness_push_event (h, gst_event_new_eos ()); + + gst_harness_teardown (h); +} + +GST_END_TEST; + + +GST_START_TEST (test_sps_hrd_truncated) +{ + GstHarness *h; + GstBuffer *buf; + /* SPS with timing/HRD parameters where emulation prevention bytes + * consume the remaining data while a 32-bit field is being filled. + * The failed read used to leave the bit reader with a partially + * filled cache, and the next read shifted by a negative amount. */ + const guint8 bytestream = { + 0x00, 0x00, 0x01, 0x00, 0x79, 0x00, 0x8d, 0x02, 0x43, 0x80, 0x00, 0x00, + 0xc0, 0x07, 0x81, 0x00, 0x21, 0xc8, 0xd4, 0x00, 0xc5, 0xff, 0xff, 0x1f, + 0x7c, 0xdd, 0x59, 0xe9, 0x7b, 0xff, 0xfb, 0xfe, 0x00, 0x00, 0x03, 0x00, + 0x04, 0x20, + }; + + h = gst_harness_new_parse ("h266parse"); + gst_harness_set_src_caps_str (h, "video/x-h266"); + + buf = gst_buffer_new_and_alloc (sizeof (bytestream)); + gst_buffer_fill (buf, 0, bytestream, sizeof (bytestream)); + fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK); + + gst_harness_push_event (h, gst_event_new_eos ()); + + gst_harness_teardown (h); +} + +GST_END_TEST; + +GST_START_TEST (test_ref_pic_lists_ltrp_count) +{ + GstHarness *h; + GstBuffer *buf; + /* Slice header ref_pic_lists where the long term reference pictures + * signalled in the header do not match the count from the referenced + * list. The mismatch used to hit an assertion. */ + const guint8 bytestream = { + 0x00, 0x00, 0x01, 0x00, 0x79, 0x00, 0x11, 0x02, 0x40, 0x00, 0x00, 0x03, + 0x01, 0x08, 0x00, 0x37, 0x01, 0x18, 0x00, 0x55, 0x6c, 0x3e, 0x03, 0x01, + 0x04, 0x30, 0x10, 0x00, 0x00, 0x01, 0x00, 0x81, 0x00, 0x00, 0x84, 0x00, + 0x1b, 0x80, 0x80, 0xaf, 0x18, 0x03, 0x00, 0x74, 0x00, 0x00, 0x01, 0x00, + 0x99, 0x10, 0x00, 0x00, 0x01, 0x42, 0x01, 0x01, 0x01, 0x80, 0x80, 0x00, + 0x80, + }; + + h = gst_harness_new_parse ("h266parse"); + gst_harness_set_src_caps_str (h, "video/x-h266"); + + buf = gst_buffer_new_and_alloc (sizeof (bytestream)); + gst_buffer_fill (buf, 0, bytestream, sizeof (bytestream)); + fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK); + + gst_harness_push_event (h, gst_event_new_eos ()); + + gst_harness_teardown (h); +} + +GST_END_TEST; + +GST_START_TEST (test_slice_without_vps) +{ + GstHarness *h; + GstBuffer *buf; + /* Slice header referencing an SPS that was parsed without a VPS. + * gst_h266_parser_set_active_sps_pps() asserted that the SPS has a + * VPS instead of failing the slice header parse. */ + const guint8 bytestream = { + 0x00, 0x00, 0x01, 0x00, 0x79, 0x00, 0x11, 0x02, 0x40, 0x00, 0x00, 0x03, + 0x01, 0x08, 0x00, 0x37, 0x01, 0x18, 0x00, 0x55, 0x6c, 0x3e, 0x03, 0x01, + 0x04, 0x30, 0x10, 0x00, 0x00, 0x01, 0x00, 0x81, 0x00, 0x00, 0x84, 0x00, + 0x1b, 0x80, 0x80, 0xaf, 0x18, 0x44, 0x88, 0x00, 0x00, 0x01, 0x10, 0x79, + 0x02, 0x09, 0x02, 0x40, 0x00, 0x00, 0x00, 0x40, 0x80, 0x81, 0x18, 0x00, + 0x55, 0x6c, 0x3e, 0x80, 0x6c, 0x18, 0x55, 0x00, 0x81, 0x00, 0x00, 0x01, + 0x00, 0x01, 0x80, + }; + + h = gst_harness_new_parse ("h266parse"); + gst_harness_set_src_caps_str (h, "video/x-h266"); + + buf = gst_buffer_new_and_alloc (sizeof (bytestream)); + gst_buffer_fill (buf, 0, bytestream, sizeof (bytestream)); + fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK); + + gst_harness_push_event (h, gst_event_new_eos ()); + + gst_harness_teardown (h); +} + +GST_END_TEST; + +GST_START_TEST (test_non_vcl_nal_duration) +{ + GstCaps *in_caps, *out_caps; + GstBuffer *buf_in, *buf_out; + GstClockTime expected_duration; + GstHarness *h = gst_harness_new ("h266parse"); + const GstClockTime fake_duration = 12345 * GST_MSECOND; + + const gchar *in_caps_str = + "video/x-h266, alignment=(string)nal, framerate=30/1"; + const gchar *out_caps_str = "video/x-h266, alignment=(string)nal"; + + in_caps = gst_caps_from_string (in_caps_str); + out_caps = gst_caps_from_string (out_caps_str); + gst_harness_set_caps (h, in_caps, out_caps); + + /* Push VPS, SPS, PPS with an arbitrary non-zero duration */ + buf_in = wrap_buffer (h266_vps, sizeof (h266_vps), 0, 0); + GST_BUFFER_DURATION (buf_in) = fake_duration; + fail_unless_equals_int (gst_harness_push (h, buf_in), GST_FLOW_OK); + + buf_in = wrap_buffer (h266_sps, sizeof (h266_sps), 0, 0); + GST_BUFFER_DURATION (buf_in) = fake_duration; + fail_unless_equals_int (gst_harness_push (h, buf_in), GST_FLOW_OK); + + buf_in = wrap_buffer (h266_pps, sizeof (h266_pps), 0, 0); + GST_BUFFER_DURATION (buf_in) = fake_duration; + fail_unless_equals_int (gst_harness_push (h, buf_in), GST_FLOW_OK); + + /* Push an IDR slice (VCL) to complete the AU */ + buf_in = wrap_buffer (h266_idr, sizeof (h266_idr), 0, 0); + fail_unless_equals_int (gst_harness_push (h, buf_in), GST_FLOW_OK); + + /* With framerate=30/1, a VCL frame should get duration = 1/30 s */ + expected_duration = gst_util_uint64_scale (GST_SECOND, 1, 30); + + /* First AU produces: VPS + SPS + PPS + slice = 4 buffers */ + fail_unless_equals_int (gst_harness_buffers_in_queue (h), 4); + + /* VPS - non-VCL, must have duration=0 */ + buf_out = gst_harness_pull (h); + fail_unless_equals_clocktime (GST_BUFFER_DURATION (buf_out), 0); + gst_buffer_unref (buf_out); + + /* SPS - non-VCL, must have duration=0 */ + buf_out = gst_harness_pull (h); + fail_unless_equals_clocktime (GST_BUFFER_DURATION (buf_out), 0); + gst_buffer_unref (buf_out); + + /* PPS - non-VCL, must have duration=0 */ + buf_out = gst_harness_pull (h); + fail_unless_equals_clocktime (GST_BUFFER_DURATION (buf_out), 0); + gst_buffer_unref (buf_out); + + /* IDR slice - VCL, must have the fps-based duration */ + buf_out = gst_harness_pull (h); + fail_unless_equals_clocktime (GST_BUFFER_DURATION (buf_out), + expected_duration); + gst_buffer_unref (buf_out); + + gst_harness_teardown (h); +} + +GST_END_TEST; + static Suite * h266parse_harnessed_suite (void) { @@ -1363,6 +1753,8 @@ tcase_add_test (tc_chain, test_discont_au_au); tcase_add_test (tc_chain, test_parse_skip_to_4bytes_sc); + tcase_add_test (tc_chain, test_parse_reject_forbidden_nal_header); + tcase_add_test (tc_chain, test_parse_preserve_au_before_forbidden_nal); tcase_add_test (tc_chain, test_parse_sc_with_half_nal); tcase_add_test (tc_chain, test_transform_bytestream_vvc1); @@ -1376,6 +1768,20 @@ tcase_add_test (tc_chain, test_packetized_vvc1_drop_corrupt); + tcase_add_test (tc_chain, test_sps_invalid_framerate); + tcase_add_test (tc_chain, test_sps_hrd_framerate); + tcase_add_test (tc_chain, test_chroma_qp_table_bitdepth); + + tcase_add_test (tc_chain, test_sh_num_tiles_in_slice); + + tcase_add_test (tc_chain, test_sps_hrd_truncated); + + tcase_add_test (tc_chain, test_ref_pic_lists_ltrp_count); + + tcase_add_test (tc_chain, test_slice_without_vps); + + tcase_add_test (tc_chain, test_non_vcl_nal_duration); + return s; }
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/tests/check/libs/h264parser.c -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/tests/check/libs/h264parser.c
Changed
@@ -1125,6 +1125,223 @@ GST_END_TEST; +/* https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/5375 + * Frame packing arrangement SEI advertising more payload than the NAL + * unit holds, ending in an emulation prevention byte. The payload is + * clamped to the data that is really there and must parse cleanly. */ +static const guint8 nalu_sei_frame_packing_epb = { + 0x00, 0x00, 0x01, /* start code */ + 0x06, /* NAL header */ + 0x2d, /* payloadType 45 */ + 0x05, /* payloadSize 5 */ + 0xe0, /* payload */ + 0x00, 0x00, 0x03, 0x01 +}; + +GST_START_TEST (test_h264_parse_sei_frame_packing_epb) +{ + GstH264ParserResult res; + GstH264NalUnit nalu; + GArray *seis = NULL; + GstH264NalParser *const parser = gst_h264_nal_parser_new (); + + res = gst_h264_parser_identify_nalu_unchecked (parser, + nalu_sei_frame_packing_epb, 0, sizeof (nalu_sei_frame_packing_epb), + &nalu); + assert_equals_int (res, GST_H264_PARSER_OK); + assert_equals_int (nalu.type, GST_H264_NAL_SEI); + + res = gst_h264_parser_parse_sei (parser, &nalu, &seis); + assert_equals_int (res, GST_H264_PARSER_OK); + fail_unless (seis != NULL); + assert_equals_int (seis->len, 1); + assert_equals_int (g_array_index (seis, GstH264SEIMessage, 0).payloadType, + GST_H264_SEI_FRAME_PACKING); + + g_array_free (seis, TRUE); + gst_h264_nal_parser_free (parser); +} + +GST_END_TEST; + +/* Frame packing arrangement SEI whose fields consume more bits than + * the advertised payload size (large ue(frame_packing_id) with + * cancel_flag set). The overrun must be detected instead of wrapping + * the remaining-skip amount around to a huge value. */ +static const guint8 nalu_sei_frame_packing_overrun = { + 0x00, 0x00, 0x01, /* start code */ + 0x06, /* NAL header */ + 0x2d, /* payloadType 45 */ + 0x05, /* payloadSize 5 */ + /* ue(id) = 2^30-1 (61 bits), cancel_flag = 1, extension_flag = 1 */ + 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x06, + /* tail with emulation prevention byte */ + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x03, + 0x00 +}; + +GST_START_TEST (test_h264_parse_sei_frame_packing_overrun) +{ + GstH264ParserResult res; + GstH264NalUnit nalu; + GArray *seis = NULL; + GstH264NalParser *const parser = gst_h264_nal_parser_new (); + + res = gst_h264_parser_identify_nalu_unchecked (parser, + nalu_sei_frame_packing_overrun, 0, + sizeof (nalu_sei_frame_packing_overrun), &nalu); + assert_equals_int (res, GST_H264_PARSER_OK); + assert_equals_int (nalu.type, GST_H264_NAL_SEI); + + res = gst_h264_parser_parse_sei (parser, &nalu, &seis); + assert_equals_int (res, GST_H264_PARSER_ERROR); + + if (seis) + g_array_free (seis, TRUE); + gst_h264_nal_parser_free (parser); +} + +GST_END_TEST; + +/* SPS with a huge pic_width_in_mbs_minus1 (ue value 2^28-1): the + * width computation must not overflow the gint fields. */ +static const guint8 nalu_sps_huge_width = { + 0x00, 0x00, 0x01, /* start code */ + 0x67, /* NAL header */ + 0x42, /* profile_idc 66 */ + 0x00, /* constraints */ + 0x1E, /* level_idc */ + /* id, log2_max_frame_num_minus4, pic_order_cnt_type, + * log2_max_pic_order_cnt_lsb_minus4, num_ref_frames: ue 0 each; + * gaps: 0; pic_width_in_mbs_minus1: ue 2^28-1 (28 zero bits, + * a 1 bit, 28 zero bits); pic_height_in_map_units_minus1: ue 0; + * frame_mbs_only: 1, direct_8x8: 1, cropping: 0, vui: 0 */ + 0xF8, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x01, 0xC0 +}; + +GST_START_TEST (test_h264_parse_sps_huge_width) +{ + GstH264ParserResult res; + GstH264NalUnit nalu; + GstH264NalParser *const parser = gst_h264_nal_parser_new (); + + res = gst_h264_parser_identify_nalu_unchecked (parser, + nalu_sps_huge_width, 0, sizeof (nalu_sps_huge_width), &nalu); + assert_equals_int (res, GST_H264_PARSER_OK); + assert_equals_int (nalu.type, GST_H264_NAL_SPS); + + res = gst_h264_parser_parse_nal (parser, &nalu); + assert_equals_int (res, GST_H264_PARSER_ERROR); + + gst_h264_nal_parser_free (parser); +} + +GST_END_TEST; + +/* SPS with huge width and height (65536x65536): each dimension fits + * a gint, but their product (2^32) does not. Callers multiply the + * dimensions as gint values, so such an SPS must be rejected. */ +static const guint8 nalu_sps_huge_width_height = { + 0x00, 0x00, 0x01, /* start code */ + 0x67, /* NAL header */ + 0x42, /* profile_idc 66 */ + 0x00, /* constraints */ + 0x1E, /* level_idc */ + /* id, log2_max_frame_num_minus4, pic_order_cnt_type, + * log2_max_pic_order_cnt_lsb_minus4, num_ref_frames: ue 0 each; + * gaps: 0; pic_width_in_mbs_minus1: ue 4095 (12 zero bits, a 1 + * bit, 12 zero bits); pic_height_in_map_units_minus1: ue 4095; + * frame_mbs_only: 1, direct_8x8: 1, cropping: 0, vui: 0 */ + 0xF8, 0x00, 0x20, 0x00, 0x00, 0x10, 0x00, 0xC8 +}; + +GST_START_TEST (test_h264_parse_sps_huge_width_height) +{ + GstH264ParserResult res; + GstH264NalUnit nalu; + GstH264NalParser *const parser = gst_h264_nal_parser_new (); + + res = gst_h264_parser_identify_nalu_unchecked (parser, + nalu_sps_huge_width_height, 0, sizeof (nalu_sps_huge_width_height), + &nalu); + assert_equals_int (res, GST_H264_PARSER_OK); + assert_equals_int (nalu.type, GST_H264_NAL_SPS); + + res = gst_h264_parser_parse_nal (parser, &nalu); + assert_equals_int (res, GST_H264_PARSER_ERROR); + + gst_h264_nal_parser_free (parser); +} + +GST_END_TEST; + +GST_START_TEST (test_h264_forbidden_trailer) +{ + /* Camera metadata which used to parse as a 32x96 subset SPS. */ + guint8 trailer = { + 0xef, 0x00, 0x00, 0xc7, 0x6a, 0xe4, 0x6a, 0x06, + 0x01, 0x00, 0x0f, 0xdc, 0xa5, 0x6a, 0x00, 0x45, + 0x12, 0x00, 0x07, 0xc7, 0x6a, 0xe4, 0x6a, 0x0a, + 0xe6, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00 + }; + guint8 packet = { + 0x00, 0x00, 0x00, 0x12, + 0x09, 0xf0, + 0x00, 0x00, 0x01, 0xb2, 0x05, + 0x00, 0x00, 0x01, 0xe1, 0x00, + 0x00, 0x00, 0x01, 0x0a, 0x80, + 0x00, 0x00, 0x01, 0xef + }; + GstH264NalParser *parser = gst_h264_nal_parser_new (); + GstH264NalUnit nalu = { 0, }; + GstH264SPS sps = { 0, }; + GArray *nalus = g_array_new (FALSE, FALSE, sizeof (GstH264NalUnit)); + gsize consumed; + + { + GstH264NalUnit forbidden_nalu; + const guint8 annexb = { + 0x00, 0x00, 0x01, 0xb2, 0x05, 0x00, 0x00, 0x01, 0x09, 0xf0 + }; + + fail_unless_equals_int (gst_h264_parser_identify_nalu_unchecked (parser, + annexb, 0, sizeof (annexb), &forbidden_nalu), + GST_H264_PARSER_BROKEN_DATA); + fail_if (forbidden_nalu.valid); + fail_unless_equals_int (forbidden_nalu.offset, 3); + fail_unless_equals_int (gst_h264_parser_identify_nalu (parser, + annexb, 0, sizeof (annexb), &forbidden_nalu), + GST_H264_PARSER_BROKEN_DATA); + fail_if (forbidden_nalu.valid); + } + + nalu.data = trailer; + nalu.size = sizeof (trailer); + nalu.header_bytes = 1; + fail_unless_equals_int (gst_h264_parser_parse_subset_sps (parser, &nalu, + &sps), GST_H264_PARSER_BROKEN_DATA); + fail_if (sps.valid); + fail_unless (parser->last_sps == NULL); + + GST_WRITE_UINT32_BE (packet, sizeof (packet) - 4); + fail_unless_equals_int (gst_h264_parser_identify_and_split_nalu_avc (parser, + packet, 0, sizeof (packet), 4, nalus, &consumed), GST_H264_PARSER_OK); + fail_unless_equals_int (consumed, sizeof (packet)); + fail_unless_equals_int (nalus->len, 2); + fail_unless_equals_int (g_array_index (nalus, GstH264NalUnit, 0).type, + GST_H264_NAL_AU_DELIMITER); + fail_unless_equals_int (g_array_index (nalus, GstH264NalUnit, 1).type, + GST_H264_NAL_SEQ_END); + + g_array_unref (nalus); + gst_h264_nal_parser_free (parser); +} + +GST_END_TEST; + static Suite * h264parser_suite (void) { @@ -1142,7 +1359,12 @@ tcase_add_test (tc_chain, test_h264_decoder_config_record); tcase_add_test (tc_chain, test_h264_parse_partial_nal_header); tcase_add_test (tc_chain, test_h264_split_avc); + tcase_add_test (tc_chain, test_h264_forbidden_trailer); tcase_add_test (tc_chain, test_h264_parse_overflow_framerate); + tcase_add_test (tc_chain, test_h264_parse_sei_frame_packing_epb); + tcase_add_test (tc_chain, test_h264_parse_sei_frame_packing_overrun); + tcase_add_test (tc_chain, test_h264_parse_sps_huge_width); + tcase_add_test (tc_chain, test_h264_parse_sps_huge_width_height); return s; }
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/tests/check/libs/h265parser.c -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/tests/check/libs/h265parser.c
Changed
@@ -113,6 +113,13 @@ 0xff, 0xfe, 0x80 }; +/* Same picture timing SEI, but the payload ends while the decoding unit loop + * is still running. The decoding unit arrays have been allocated by then. */ +static guint8 h265_sei_pic_timing_truncated = { + 0x00, 0x00, 0x00, 0x01, 0x4e, 0x01, 0x01, 0x10, 0x04, 0x00, 0x00, 0x03, 0x00, + 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x08, 0xaf +}; + /* hdr10plus dynamic metadata */ static guint8 h265_sei_user_data_registered = { 0x00, 0x00, 0x00, 0x01, 0x4e, 0x01, 0x04, 0x40, 0xb5, 0x00, 0x3c, 0x00, 0x01, @@ -133,6 +140,17 @@ 0x80 }; +/* Broken stream where payloadSize includes the emulation_prevention_three_byte + * in the UUID. */ +static guint8 h265_sei_user_data_unregistered_ebsp_size = { + 0x00, 0x00, 0x00, 0x01, 0x4e, 0x01, + 0x05, 0x18, + 0x01, 0x00, 0x00, 0x03, 0x00, 0x02, 0x03, 0x04, + 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, + 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x80 +}; + static guint8 h265_sei_time_code = { 0x00, 0x00, 0x00, 0x01, 0x4e, 0x01, 0x88, 0x06, 0x60, 0x40, 0x00, 0x00, 0x03, 0x00, 0x10, 0x80 @@ -197,6 +215,46 @@ GST_END_TEST; +GST_START_TEST (test_h265_sei_user_data_unregistered_ebsp_size) +{ + static const guint8 expected_uuid = { + 0x01, 0x00, 0x00, 0x00, 0x02, 0x03, 0x04, 0x05, + 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d + }; + static const guint8 expected_data = { + 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17 + }; + GstH265Parser *parser = gst_h265_parser_new (); + GstH265ParserResult res; + GstH265NalUnit nalu; + GArray *messages = NULL; + GstH265SEIMessage *sei; + GstH265UserDataUnregistered *user_data; + + res = gst_h265_parser_identify_nalu_unchecked (parser, + h265_sei_user_data_unregistered_ebsp_size, 0, + G_N_ELEMENTS (h265_sei_user_data_unregistered_ebsp_size), &nalu); + assert_equals_int (res, GST_H265_PARSER_OK); + + res = gst_h265_parser_parse_sei (parser, &nalu, &messages); + assert_equals_int (res, GST_H265_PARSER_OK); + assert_equals_int (messages->len, 1); + + sei = &g_array_index (messages, GstH265SEIMessage, 0); + assert_equals_int (sei->payloadType, GST_H265_SEI_USER_DATA_UNREGISTERED); + user_data = &sei->payload.user_data_unregistered; + fail_unless (memcmp (user_data->uuid, expected_uuid, + sizeof (expected_uuid)) == 0); + assert_equals_int (user_data->size, sizeof (expected_data)); + fail_unless (memcmp (user_data->data, expected_data, + sizeof (expected_data)) == 0); + + g_array_unref (messages); + gst_h265_parser_free (parser); +} + +GST_END_TEST; + GST_START_TEST (test_h265_parse_pic_timing) { GstH265NalUnit nalu; @@ -247,6 +305,71 @@ GST_END_TEST; +GST_START_TEST (test_h265_parse_pic_timing_truncated) +{ + GstH265NalUnit nalu; + GstH265Parser *parser = gst_h265_parser_new (); + const guint8 *buf = h265_sps; + guint buf_size = sizeof (h265_sps); + GArray *messages; + GstH265SPS sps; + + assert_equals_int (gst_h265_parser_identify_nalu (parser, buf, 0, buf_size, + &nalu), GST_H265_PARSER_NO_NAL_END); + assert_equals_int (gst_h265_parser_parse_sps (parser, &nalu, &sps, TRUE), + GST_H265_PARSER_OK); + + buf = h265_sei_pic_timing_truncated; + buf_size = sizeof (h265_sei_pic_timing_truncated); + + assert_equals_int (gst_h265_parser_identify_nalu (parser, buf, 0, buf_size, + &nalu), GST_H265_PARSER_NO_NAL_END); + assert_equals_int (nalu.type, GST_H265_NAL_PREFIX_SEI); + + /* The message must be rejected, and the arrays allocated for its decoding + * units must not be leaked. */ + assert_equals_int (gst_h265_parser_parse_sei (parser, &nalu, &messages), + GST_H265_PARSER_ERROR); + assert_equals_int (messages->len, 0); + + g_array_free (messages, TRUE); + gst_h265_parser_free (parser); +} + +GST_END_TEST; + +GST_START_TEST (test_h265_sei_free_pic_timing_single_du) +{ + GstH265SEIMessage sei = { 0, }; + GstH265SEIMessage copy = { 0, }; + + /* A single decoding unit still gets arrays allocated by the parser. */ + sei.payloadType = GST_H265_SEI_PIC_TIMING; + sei.payload.pic_timing.num_decoding_units_minus1 = 0; + sei.payload.pic_timing.num_nalus_in_du_minus1 = g_new0 (guint32, 1); + sei.payload.pic_timing.du_cpb_removal_delay_increment_minus1 = + g_new0 (guint8, 1); + + /* The copy must own its own arrays, not alias the source ones. */ + fail_unless (gst_h265_sei_copy (©, &sei)); + fail_unless (copy.payload.pic_timing.num_nalus_in_du_minus1 != NULL); + fail_unless (copy.payload.pic_timing.num_nalus_in_du_minus1 != + sei.payload.pic_timing.num_nalus_in_du_minus1); + fail_unless (copy.payload.pic_timing.du_cpb_removal_delay_increment_minus1 != + NULL); + fail_unless (copy.payload.pic_timing.du_cpb_removal_delay_increment_minus1 != + sei.payload.pic_timing.du_cpb_removal_delay_increment_minus1); + + gst_h265_sei_free (©); + gst_h265_sei_free (&sei); + + fail_unless (sei.payload.pic_timing.num_nalus_in_du_minus1 == NULL); + fail_unless (sei.payload.pic_timing.du_cpb_removal_delay_increment_minus1 == + NULL); +} + +GST_END_TEST; + GST_START_TEST (test_h265_parse_slice_6bytes) { GstH265ParserResult res; @@ -1492,6 +1615,86 @@ GST_END_TEST; +/* SPS with a conformance window cropping more than the whole picture. + * The conf_win offsets are unbounded ue() values; the resulting + * cropped width used to wrap around and be accepted as a negative + * gint. */ +static guint8 h265_sps_oversized_conformance_window = { + 0x00, 0x00, 0x00, 0x01, 0x42, 0x01, 0x01, 0x01, 0x80, 0x00, 0x00, 0x03, + 0x00, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x1e, 0xa0, 0x20, + 0x81, 0x06, 0x06, 0x5f, 0xff, 0xf0, 0x82 +}; + +GST_START_TEST (test_h265_parse_sps_oversized_conformance_window) +{ + GstH265Parser *parser; + GstH265NalUnit nalu; + GstH265SPS sps; + GstH265ParserResult res; + + parser = gst_h265_parser_new (); + + res = gst_h265_parser_identify_nalu (parser, + h265_sps_oversized_conformance_window, 0, + sizeof (h265_sps_oversized_conformance_window), &nalu); + assert_equals_int (res, GST_H265_PARSER_NO_NAL_END); + assert_equals_int (nalu.type, GST_H265_NAL_SPS); + + res = gst_h265_parser_parse_sps (parser, &nalu, &sps, TRUE); + assert_equals_int (res, GST_H265_PARSER_ERROR); + + gst_h265_parser_free (parser); +} + +GST_END_TEST; + +GST_START_TEST (test_h265_reject_forbidden_nals) +{ + const guint8 annexb = { 0x00, 0x00, 0x01, 0xc6, 0x01, 0x80 }; + const guint8 single = { 0x00, 0x00, 0x00, 0x02, 0xc6, 0x01 }; + guint8 packet = { + 0x00, 0x00, 0x00, 0x11, + 0x46, 0x01, + 0x00, 0x00, 0x01, 0xc6, 0x01, + 0x00, 0x00, 0x01, 0x48, 0x01, + 0x00, 0x00, 0x01, 0xc8, 0x01 + }; + GstH265Parser *parser = gst_h265_parser_new (); + GstH265NalUnit nalu = { 0, }; + GArray *nalus = g_array_new (FALSE, FALSE, sizeof (GstH265NalUnit)); + gsize consumed; + + fail_unless_equals_int (gst_h265_parser_identify_nalu (parser, + annexb, 0, sizeof (annexb), &nalu), GST_H265_PARSER_BROKEN_DATA); + fail_unless_equals_int (gst_h265_parser_identify_nalu_hevc (parser, + single, 0, sizeof (single), 4, &nalu), GST_H265_PARSER_BROKEN_DATA); + + /* Keep valid NALs before and after a forbidden chunk, including when + * the last chunk is forbidden. */ + fail_unless_equals_int (gst_h265_parser_identify_and_split_nalu_hevc (parser, + packet, 0, sizeof (packet), 4, nalus, &consumed), GST_H265_PARSER_OK); + fail_unless_equals_int (consumed, sizeof (packet)); + fail_unless_equals_int (nalus->len, 2); + fail_unless_equals_int (g_array_index (nalus, GstH265NalUnit, 0).type, + GST_H265_NAL_AUD); + fail_unless_equals_int (g_array_index (nalus, GstH265NalUnit, 1).type, + GST_H265_NAL_EOS); + + /* An entirely forbidden packet must not produce any usable NALs. */ + packet4 |= 0x80; + packet14 |= 0x80; + fail_unless_equals_int (gst_h265_parser_identify_and_split_nalu_hevc (parser, + packet, 0, sizeof (packet), 4, nalus, &consumed), + GST_H265_PARSER_BROKEN_DATA); + fail_unless_equals_int (consumed, sizeof (packet)); + fail_unless_equals_int (nalus->len, 0); + + g_array_unref (nalus); + gst_h265_parser_free (parser); +} + +GST_END_TEST; + static Suite * h265parser_suite (void) { @@ -1500,8 +1703,11 @@ TCase *tc_chain = tcase_create ("general"); suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_h265_reject_forbidden_nals); tcase_add_test (tc_chain, test_h265_parse_slice_eos_slice_eob); tcase_add_test (tc_chain, test_h265_parse_pic_timing); + tcase_add_test (tc_chain, test_h265_parse_pic_timing_truncated); + tcase_add_test (tc_chain, test_h265_sei_free_pic_timing_single_du); tcase_add_test (tc_chain, test_h265_parse_slice_6bytes); tcase_add_test (tc_chain, test_h265_parse_identify_nalu_hevc); tcase_add_test (tc_chain, test_h265_base_profiles); @@ -1513,10 +1719,12 @@ tcase_add_test (tc_chain, test_h265_parse_scc); tcase_add_test (tc_chain, test_h265_nal_type_classification); tcase_add_test (tc_chain, test_h265_sei_registered_user_data); + tcase_add_test (tc_chain, test_h265_sei_user_data_unregistered_ebsp_size); tcase_add_test (tc_chain, test_h265_create_sei); tcase_add_test (tc_chain, test_h265_split_hevc); tcase_add_test (tc_chain, test_h265_decoder_config_record); tcase_add_test (tc_chain, test_h265_parse_partial_nal); + tcase_add_test (tc_chain, test_h265_parse_sps_oversized_conformance_window); return s; }
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/tests/check/libs/h266parser.c -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/tests/check/libs/h266parser.c
Changed
@@ -525,6 +525,98 @@ GST_END_TEST; +GST_START_TEST (test_h266_sei_scalable_nesting_layers) +{ + GstH266Parser *parser = gst_h266_parser_new (); + GstH266NalUnit nalu; + GstH266ParserResult res; + GArray *messages = NULL; + /* An SPS followed by a suffix SEI carrying a scalable nesting message + * with num_layers_minus1 = 64. The layer_id loop used to run one + * iteration past the layer_id64 array; the value is out of range + * (the spec maximum is 63) and must be rejected. */ + const guint8 sps_nal = { + 0x00, 0x00, 0x01, 0x00, 0x79, 0x00, 0x09, 0x02, 0x40, 0x00, 0x00, 0x03, + 0x00, 0x40, 0x80, 0x81, 0x18, 0x00, 0x55, 0x6c, 0x3e, 0x03, 0x01, 0x04, + 0x30, 0x10, 0x00, 0x00, 0x3e, 0x80, 0x00, 0x07, 0x53, 0x0a, 0x00, 0xfa, + 0x40, + }; + const guint8 sei_nal = { + 0x00, 0x00, 0x01, 0x00, 0xc1, 0x85, 0x33, 0x00, 0x41, 0x04, 0x20, 0xc4, + 0x14, 0x61, 0xc8, 0x24, 0xa2, 0xcc, 0x34, 0xe3, 0xd0, 0x45, 0x24, 0xd4, + 0x55, 0x65, 0xd8, 0x65, 0xa6, 0xdc, 0x75, 0xe7, 0xe0, 0x86, 0x28, 0xe4, + 0x96, 0x69, 0xe8, 0xa6, 0xaa, 0xec, 0xb6, 0xeb, 0xf0, 0xc7, 0x2c, 0xf4, + 0xd7, 0x6d, 0xf8, 0xe7, 0xae, 0xfc, 0xf7, 0xef, 0xc0, 0xc0, 0x80, + }; + + res = gst_h266_parser_identify_nalu_unchecked (parser, sps_nal, 0, + sizeof (sps_nal), &nalu); + assert_equals_int (res, GST_H266_PARSER_OK); + res = gst_h266_parser_parse_nal (parser, &nalu); + assert_equals_int (res, GST_H266_PARSER_OK); + + res = gst_h266_parser_identify_nalu_unchecked (parser, sei_nal, 0, + sizeof (sei_nal), &nalu); + assert_equals_int (res, GST_H266_PARSER_OK); + assert_equals_int (nalu.type, GST_H266_NAL_SUFFIX_SEI); + + res = gst_h266_parser_parse_sei (parser, &nalu, &messages); + fail_if (res == GST_H266_PARSER_OK); + + if (messages) + g_array_unref (messages); + gst_h266_parser_free (parser); +} + +GST_END_TEST; + +GST_START_TEST (test_h266_reject_forbidden_nals) +{ + const guint8 annexb = { 0x00, 0x00, 0x01, 0x80, 0xa1, 0x80 }; + const guint8 single = { 0x00, 0x00, 0x00, 0x02, 0x80, 0xa1 }; + guint8 packet = { + 0x00, 0x00, 0x00, 0x11, + 0x00, 0xa1, + 0x00, 0x00, 0x01, 0x80, 0xa1, + 0x00, 0x00, 0x01, 0x00, 0xa9, + 0x00, 0x00, 0x01, 0x80, 0xa9 + }; + GstH266Parser *parser = gst_h266_parser_new (); + GstH266NalUnit nalu = { 0, }; + GArray *nalus = g_array_new (FALSE, FALSE, sizeof (GstH266NalUnit)); + gsize consumed; + + fail_unless_equals_int (gst_h266_parser_identify_nalu (parser, + annexb, 0, sizeof (annexb), &nalu), GST_H266_PARSER_BROKEN_DATA); + fail_unless_equals_int (gst_h266_parser_identify_nalu_vvc (parser, + single, 0, sizeof (single), 4, &nalu), GST_H266_PARSER_BROKEN_DATA); + + /* Keep valid NALs before and after a forbidden chunk, including when + * the last chunk is forbidden. */ + fail_unless_equals_int (gst_h266_parser_identify_and_split_nalu_vvc (parser, + packet, 0, sizeof (packet), 4, nalus, &consumed), GST_H266_PARSER_OK); + fail_unless_equals_int (consumed, sizeof (packet)); + fail_unless_equals_int (nalus->len, 2); + fail_unless_equals_int (g_array_index (nalus, GstH266NalUnit, 0).type, + GST_H266_NAL_AUD); + fail_unless_equals_int (g_array_index (nalus, GstH266NalUnit, 1).type, + GST_H266_NAL_EOS); + + /* An entirely forbidden packet must not produce any usable NALs. */ + packet4 |= 0x80; + packet14 |= 0x80; + fail_unless_equals_int (gst_h266_parser_identify_and_split_nalu_vvc (parser, + packet, 0, sizeof (packet), 4, nalus, &consumed), + GST_H266_PARSER_BROKEN_DATA); + fail_unless_equals_int (consumed, sizeof (packet)); + fail_unless_equals_int (nalus->len, 0); + + g_array_unref (nalus); + gst_h266_parser_free (parser); +} + +GST_END_TEST; + static Suite * h266parser_suite (void) { @@ -533,6 +625,7 @@ TCase *tc_chain = tcase_create ("general"); suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_h266_reject_forbidden_nals); tcase_add_test (tc_chain, test_h266_parse_rasl_eos_rasl_eob); tcase_add_test (tc_chain, test_h266_parse_vps); tcase_add_test (tc_chain, test_h266_parse_sps); @@ -541,6 +634,8 @@ tcase_add_test (tc_chain, test_h266_parse_decoder_config_record); tcase_add_test (tc_chain, test_h266_parse_decoder_config_record_gci); + tcase_add_test (tc_chain, test_h266_sei_scalable_nesting_layers); + return s; }
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/tests/check/libs/nalutils.c -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/tests/check/libs/nalutils.c
Changed
@@ -102,6 +102,68 @@ GST_END_TEST; +GST_START_TEST (test_nal_reader_read_epb) +{ + /* 00 00 03 is an emulation prevention sequence: the 03 carries no + * data, so a 32-bit read over these 5 raw bytes only finds 3 data + * bytes and must fail. */ + const guint8 data = { 0xaa, 0x00, 0x00, 0x03, 0xbb }; + NalReader nr; + guint8 val; + + nal_reader_init (&nr, data, sizeof (data)); + fail_unless (nal_reader_get_bits_uint8 (&nr, &val, 8)); + assert_equals_int (val, 0xaa); + + fail_if (nal_reader_get_bits_uint8 (&nr, &val, 32)); + + /* the failed read must not have consumed or corrupted anything */ + fail_unless (nal_reader_is_byte_aligned (&nr)); + assert_equals_int (nal_reader_get_remaining (&nr), 32); + fail_unless (nal_reader_get_bits_uint8 (&nr, &val, 8)); + assert_equals_int (val, 0x00); +} + +GST_END_TEST; + +GST_START_TEST (test_nal_reader_read_epb_success) +{ + /* the emulation prevention byte must be skipped transparently */ + const guint8 data = { 0x11, 0x22, 0x00, 0x00, 0x03, 0x33, 0x44 }; + NalReader nr; + guint32 val32; + guint8 val8; + + nal_reader_init (&nr, data, sizeof (data)); + fail_unless (nal_reader_get_bits_uint32 (&nr, &val32, 32)); + assert_equals_int (val32, 0x11220000); + fail_unless (nal_reader_get_bits_uint8 (&nr, &val8, 8)); + assert_equals_int (val8, 0x33); + fail_unless (nal_reader_get_bits_uint8 (&nr, &val8, 8)); + assert_equals_int (val8, 0x44); +} + +GST_END_TEST; + +GST_START_TEST (test_nal_reader_skip_long_epb) +{ + /* 4 data bytes (01 02 00 00) plus one emulation prevention byte: + * skipping 40 bits runs out of data and must leave the reader + * untouched. */ + const guint8 data = { 0x01, 0x02, 0x00, 0x00, 0x03 }; + NalReader nr; + guint8 val; + + nal_reader_init (&nr, data, sizeof (data)); + fail_if (nal_reader_skip_long (&nr, 40)); + + assert_equals_int (nal_reader_get_pos (&nr), 0); + fail_unless (nal_reader_get_bits_uint8 (&nr, &val, 8)); + assert_equals_int (val, 0x01); +} + +GST_END_TEST; + static Suite * nalutils_suite (void) { @@ -112,6 +174,9 @@ suite_add_tcase (s, tc_chain); tcase_add_test (tc_chain, test_nal_writer_init); tcase_add_test (tc_chain, test_nal_writer_emulation_preventation); + tcase_add_test (tc_chain, test_nal_reader_read_epb); + tcase_add_test (tc_chain, test_nal_reader_read_epb_success); + tcase_add_test (tc_chain, test_nal_reader_skip_long_epb); return s; }
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/tests/check/libs/vc1parser.c -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/tests/check/libs/vc1parser.c
Changed
@@ -803,6 +803,9 @@ GstVC1SeqHdr hdr; GstVC1EntryPointHdr entrypt; + memset (&hdr, 0xAA, sizeof (hdr)); + memset (&entrypt, 0xAA, sizeof (entrypt)); + res = gst_vc1_identify_next_bdu (sequence_fullframe, sizeof (sequence_fullframe), &bdu); @@ -813,6 +816,13 @@ assert_equals_int (res, GST_VC1_PARSER_OK); assert_equals_int (hdr.profile, GST_VC1_PROFILE_ADVANCED); + assert_equals_int (hdr.struct_c.profile, GST_VC1_PROFILE_ADVANCED); + assert_equals_int (hdr.struct_c.rangered, 0); + assert_equals_int (hdr.struct_c.maxbframes, 0); + assert_equals_int (hdr.struct_c.coded_width, 0); + assert_equals_int (hdr.struct_c.coded_height, 0); + assert_equals_int (hdr.mb_width, (hdr.advanced.max_coded_width + 15) >> 4); + assert_equals_int (hdr.advanced.level, GST_VC1_LEVEL_L1); assert_equals_int (hdr.advanced.colordiff_format, 1); @@ -837,9 +847,6 @@ GstVC1SeqStructC *structc = &seqhdr.struct_c; GstVC1PicSimpleMain *pic = &framehdr.pic.simple; - structc->coded_height = 240; - structc->coded_width = 320; - assert_equals_int (gst_vc1_parse_sequence_header (pframe_header_main, sizeof (pframe_header_main), &seqhdr), GST_VC1_PARSER_OK); @@ -882,15 +889,16 @@ GstVC1SeqStructC *structc = &seqhdr.struct_c; GstVC1PicSimpleMain *pic = &framehdr.pic.simple; - structc->coded_height = 240; - structc->coded_width = 320; - assert_equals_int (gst_vc1_parse_sequence_header (bframe_header_main, sizeof (bframe_header_main), &seqhdr), GST_VC1_PARSER_OK); assert_equals_int (seqhdr.profile, GST_VC1_PROFILE_MAIN); - assert_equals_int (seqhdr.mb_height, 15); - assert_equals_int (seqhdr.mb_width, 20); + assert_equals_int (structc->wmvp, 0); + structc->coded_width = 320; + structc->coded_height = 240; + seqhdr.mb_width = 20; + seqhdr.mb_height = 15; + seqhdr.mb_stride = 21; gst_vc1_bitplanes_ensure_size (&b, &seqhdr); @@ -937,9 +945,6 @@ GstVC1SeqStructC *structc = &seqhdr.struct_c; GstVC1PicSimpleMain *pic = &framehdr.pic.simple; - structc->coded_height = 240; - structc->coded_width = 320; - assert_equals_int (gst_vc1_parse_sequence_header (i_bi_frame_header, sizeof (i_bi_frame_header), &seqhdr), GST_VC1_PARSER_OK); @@ -980,9 +985,6 @@ GstVC1SeqStructC *structc = &seqhdr.struct_c; GstVC1PicSimpleMain *pic = &framehdr.pic.simple; - structc->coded_height = 240; - structc->coded_width = 320; - assert_equals_int (gst_vc1_parse_sequence_header (i_bi_frame_header, sizeof (i_bi_frame_header), &seqhdr), GST_VC1_PARSER_OK); @@ -1234,6 +1236,9 @@ assert_equals_int (seq_layer.struct_b.hrd_rate, 0); assert_equals_int (seq_layer.struct_c.profile, GST_VC1_PROFILE_MAIN); + assert_equals_int (seq_layer.struct_c.wmvp, 0); + assert_equals_int (seq_layer.struct_c.coded_width, 0); + assert_equals_int (seq_layer.struct_c.coded_height, 0); assert_equals_int (seq_layer.struct_c.frmrtq_postproc, 0); assert_equals_int (seq_layer.struct_c.bitrtq_postproc, 31); assert_equals_int (seq_layer.struct_c.loop_filter, 1);
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/tests/check/libs/vp9parser.c -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/tests/check/libs/vp9parser.c
Changed
@@ -179,6 +179,36 @@ GST_END_TEST; +GST_START_TEST (test_vp9_parse_truncated_frame_header) +{ + /* 1-byte frames whose header parse runs past the buffer + * (OSS-Fuzz testcase 4903539546324992): 0x96 reaches the key-frame sync + * code, 0xB4 takes the show_existing_frame path after a profile 3 + * prefix. */ + const guint8 tc_sync_code = { 0x96 }; + const guint8 tc_show_existing = { 0xB4 }; + GstVp9Parser *parser; + GstVp9FrameHdr frame_hdr; + + parser = gst_vp9_parser_new (); + + assert_equals_int (gst_vp9_parser_parse_frame_header (parser, &frame_hdr, + tc_sync_code, sizeof (tc_sync_code)), GST_VP9_PARSER_ERROR); + assert_equals_int (gst_vp9_parser_parse_frame_header (parser, &frame_hdr, + tc_show_existing, sizeof (tc_show_existing)), GST_VP9_PARSER_ERROR); + + /* Truncations of vp9_frame_data shorter than its complete frame header + * (15 bytes) must be rejected instead of reading past the end. */ + for (gsize size = 1; size < 15; size++) { + assert_equals_int (gst_vp9_parser_parse_frame_header (parser, &frame_hdr, + vp9_frame_data, size), GST_VP9_PARSER_ERROR); + } + + gst_vp9_parser_free (parser); +} + +GST_END_TEST; + static Suite * vp9parsers_suite (void) { @@ -188,6 +218,7 @@ suite_add_tcase (s, tc_chain); tcase_add_test (tc_chain, test_vp9_parse_superframe); + tcase_add_test (tc_chain, test_vp9_parse_truncated_frame_header); return s; }
View file
_service:download_files:gst-plugins-bad-1.28.8.tar.xz/tests/check/meson.build -> _service:download_files:gst-plugins-bad-1.28.9.tar.xz/tests/check/meson.build
Changed
@@ -163,7 +163,7 @@ 'elements/dash_mpd.c', not xml2_dep.found(), xml2_dep, 'elements/dtls.c', not libcrypto_dep.found() or not openssl_dep.found (), libcrypto_dep, 'elements/faac.c', - not faac_dep.found() or not cc.has_header_symbol('faac.h', 'faacEncOpen') or not cdata.has('HAVE_UNISTD_H'), + not faac_dep.found() or not cdata.has('HAVE_UNISTD_H'), faac_dep, 'elements/faad.c', not faad_dep.found() or not have_faad_2_7 or not cdata.has('HAVE_UNISTD_H'),
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.