Projects
home:zaitor:branches:Essentials
gstreamer-plugins-bad-codecs
Sign Up
Log In
Username
Password
We truncated the diff of some files because they were too big. If you want to see the full diff for every file,
click here
.
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
Expand all
Collapse all
Difference Between Revision 6 and
Essentials
/
gstreamer-plugins-bad-codecs
View file
gstreamer-plugins-bad-codecs.changes
Changed
@@ -1,4 +1,10 @@ ------------------------------------------------------------------- +Sun Nov 8 20:17:28 UTC 2026 - Bjørn Lie <zaitor@opensuse.org> + +- Update to version 1.28.9 +- Drop fix-build-new-faac.patch: Fixed upstream. + +------------------------------------------------------------------- Tue Oct 20 21:58:49 UTC 2026 - Bjørn Lie <zaitor@opensuse.org> - Add fix-build-new-faac.patch: Support building with faac 2.0 and
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 @@ -16,7 +16,6 @@ Source: %{url}/src/%{_name}/%{_name}-%{version}.tar.xz Source99: baselibs.conf Patch0: build_what_we_need_only.patch -Patch1: fix-build-new-faac.patch BuildRequires: c++_compiler BuildRequires: faac-devel @@ -53,7 +52,6 @@ %prep %autosetup -n %{_name}-%{version} -N %patch -P 0 -p1 -%patch -P 1 -p3 %build %meson \
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> +
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) {
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; -
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;
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);
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;
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;
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) {
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));
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>
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) {
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; +
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,
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";
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;
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 + };
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;
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 ();
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
.