Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package gstreamer-plugins-base for 
openSUSE:Factory checked in at 2026-07-12 16:20:41
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/gstreamer-plugins-base (Old)
 and      /work/SRC/openSUSE:Factory/.gstreamer-plugins-base.new.1991 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "gstreamer-plugins-base"

Sun Jul 12 16:20:41 2026 rev:132 rq:1364876 version:1.28.5

Changes:
--------
--- 
/work/SRC/openSUSE:Factory/gstreamer-plugins-base/gstreamer-plugins-base.changes
    2026-06-13 18:47:16.029254136 +0200
+++ 
/work/SRC/openSUSE:Factory/.gstreamer-plugins-base.new.1991/gstreamer-plugins-base.changes
  2026-07-12 16:21:12.408104434 +0200
@@ -1,0 +2,31 @@
+Thu Jul  9 17:18:19 UTC 2026 - Bjørn Lie <[email protected]>
+
+- Update to version 1.28.5:
+  + appsink: Clear local sample storage when flushing
+  + appsrc: Uniformly handle EOS events being pushed
+  + audio-resampler-neon fails to build for targets with neon but
+    without thumb
+  + encoding-target: Validate that encoding profile name is UTF-8
+    before using it
+  + gldownload: fix wrong DRM format negotiation causing R/B
+    channel swap
+  + opusdec: Don't use any channel positions for >64 channels
+  + rtcpbuffer: Fix parsing of SR+SDES compound packets (regression
+    from security fix)
+  + subparse: Don't allow very small framerates for microdvd
+    subtitles
+  + typefind: assorted fixes for the image-rs plugin typefinding
+  + typefindhelper: Drop unnecessary check for factories without a
+    function
+  + WBMP typefinding rejects a valid 1280x800 file
+  + typefinding: detect animation on PNG (and WebP, GIF, AVIF)
+  + typefindfunctions: remove Sun and Andrew raster format
+    typefinders
+  + uridecodebin3: deactivate input_item in erroneous ready->paused
+    transition
+  + vorbistag: Check for enough base64 data before trying to decode
+  + xmptag: Don't allocate -1 bytes of memory if there's only a
+    single tag
+  + xmptag: Handle fractions with 0 denominator as invalid
+
+-------------------------------------------------------------------

Old:
----
  gst-plugins-base-1.28.4.obscpio

New:
----
  gst-plugins-base-1.28.5.obscpio

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ gstreamer-plugins-base.spec ++++++
--- /var/tmp/diff_new_pack.oGsJru/_old  2026-07-12 16:21:13.508142060 +0200
+++ /var/tmp/diff_new_pack.oGsJru/_new  2026-07-12 16:21:13.508142060 +0200
@@ -20,7 +20,7 @@
 %define gst_branch 1.0
 %define gstreamer_req_version %(echo %{version} | sed -e "s/+.*//")
 Name:           gstreamer-plugins-base
-Version:        1.28.4
+Version:        1.28.5
 Release:        0
 Summary:        GStreamer Streaming-Media Framework Plug-Ins
 License:        GPL-2.0-or-later AND LGPL-2.1-or-later

++++++ _service ++++++
--- /var/tmp/diff_new_pack.oGsJru/_old  2026-07-12 16:21:13.544143291 +0200
+++ /var/tmp/diff_new_pack.oGsJru/_new  2026-07-12 16:21:13.560143838 +0200
@@ -5,7 +5,7 @@
     <param 
name="url">https://gitlab.freedesktop.org/gstreamer/gstreamer.git</param>
     <param name="subdir">subprojects/gst-plugins-base</param>
     <param name="filename">gst-plugins-base</param>
-    <param name="revision">1.28.4</param>
+    <param name="revision">1.28.5</param>
     <param name="versionformat">@PARENT_TAG@+@TAG_OFFSET@</param>
     <param name="versionrewrite-pattern">v?(.*)\+0</param>
     <param name="versionrewrite-replacement">\1</param>

++++++ gst-plugins-base-1.28.4.obscpio -> gst-plugins-base-1.28.5.obscpio ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/gst-plugins-base-1.28.4/ext/gl/gstgldownloadelement.c 
new/gst-plugins-base-1.28.5/ext/gl/gstgldownloadelement.c
--- old/gst-plugins-base-1.28.4/ext/gl/gstgldownloadelement.c   2026-06-12 
14:19:43.000000000 +0200
+++ new/gst-plugins-base-1.28.5/ext/gl/gstgldownloadelement.c   2026-07-08 
23:42:39.000000000 +0200
@@ -976,7 +976,7 @@
     if (!context) {
       gst_structure_remove_field (s, "drm-format");
     } else if (gst_gl_dma_buf_transform_gst_formats_to_drm_formats (context,
-            fmtval, GST_GL_DRM_FORMAT_DIRECT_IMPORT, &drmfmtval)) {
+            fmtval, GST_GL_DRM_FORMAT_INCLUDE_EMULATED, &drmfmtval)) {
       gst_structure_set_value (s, "drm-format", &drmfmtval);
       g_value_unset (&drmfmtval);
     } else {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gst-plugins-base-1.28.4/ext/opus/gstopusdec.c 
new/gst-plugins-base-1.28.5/ext/opus/gstopusdec.c
--- old/gst-plugins-base-1.28.4/ext/opus/gstopusdec.c   2026-06-12 
14:19:43.000000000 +0200
+++ new/gst-plugins-base-1.28.5/ext/opus/gstopusdec.c   2026-07-08 
23:42:39.000000000 +0200
@@ -364,6 +364,8 @@
     GST_DEBUG_OBJECT (dec, "Using a default of 2 channels");
     dec->n_channels = 2;
     pos = NULL;
+  } else if (dec->n_channels > 64) {
+    pos = NULL;
   }
 
   if (dec->sample_rate == 0) {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/gst-plugins-base-1.28.4/gst/playback/gsturidecodebin3.c 
new/gst-plugins-base-1.28.5/gst/playback/gsturidecodebin3.c
--- old/gst-plugins-base-1.28.4/gst/playback/gsturidecodebin3.c 2026-06-12 
14:19:43.000000000 +0200
+++ new/gst-plugins-base-1.28.5/gst/playback/gsturidecodebin3.c 2026-07-08 
23:42:39.000000000 +0200
@@ -2092,8 +2092,12 @@
   /* ERRORS */
 failure:
   {
-    if (transition == GST_STATE_CHANGE_READY_TO_PAUSED)
+    if (transition == GST_STATE_CHANGE_READY_TO_PAUSED) {
       purge_play_items (uridecodebin);
+      if (uridecodebin->input_item) {
+        uridecodebin->input_item->active = FALSE;
+      }
+    }
     return ret;
   }
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gst-plugins-base-1.28.4/gst/subparse/gstsubparse.c 
new/gst-plugins-base-1.28.5/gst/subparse/gstsubparse.c
--- old/gst-plugins-base-1.28.4/gst/subparse/gstsubparse.c      2026-06-12 
14:19:43.000000000 +0200
+++ new/gst-plugins-base-1.28.5/gst/subparse/gstsubparse.c      2026-07-08 
23:42:39.000000000 +0200
@@ -538,7 +538,7 @@
     rest = g_strdup (line);
     g_strdelimit (rest, ",", '.');
     fps = g_ascii_strtod (rest, &end);
-    if (end != rest && fps > 0.0 && fps <= 240.0) {
+    if (end != rest && fps >= 0.001 && fps <= 1000.0) {
       gst_util_double_to_fraction (fps, &state->fps_n, &state->fps_d);
       GST_INFO ("framerate from file: %d/%d ('%s')", state->fps_n,
           state->fps_d, rest);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/gst-plugins-base-1.28.4/gst/typefind/gsttypefindfunctions.c 
new/gst-plugins-base-1.28.5/gst/typefind/gsttypefindfunctions.c
--- old/gst-plugins-base-1.28.4/gst/typefind/gsttypefindfunctions.c     
2026-06-12 14:19:43.000000000 +0200
+++ new/gst-plugins-base-1.28.5/gst/typefind/gsttypefindfunctions.c     
2026-07-08 23:42:39.000000000 +0200
@@ -3738,7 +3738,7 @@
 done:
   if (tip > 0) {
     if (variant) {
-      GstCaps *caps = gst_caps_copy (QT_CAPS);
+      GstCaps *caps = gst_caps_make_writable (QT_CAPS);
 
       gst_caps_set_simple (caps, "variant", G_TYPE_STRING, variant, NULL);
       gst_type_find_suggest (tf, tip, caps);
@@ -4231,7 +4231,7 @@
   num_markers = 1;
   data_scan_ctx_advance (tf, &c, 2);
 
-  caps = gst_caps_copy (JPEG_CAPS);
+  caps = gst_caps_make_writable (JPEG_CAPS);
 
   while (data_scan_ctx_ensure_data (tf, &c, 4) && c.offset < (200 * 1024)) {
     guint16 len;
@@ -6100,6 +6100,69 @@
     gst_type_find_suggest (tf, GST_TYPE_FIND_MINIMUM, PXSTR_CAPS);
 }
 
+/* image/png (animated=true) */
+
+static GstStaticCaps png_caps = GST_STATIC_CAPS ("image/png");
+#define PNG_CAPS (gst_static_caps_get(&png_caps))
+
+/* how many chunks we check before we give up */
+#define PNG_MAXCHUNKS 25
+
+static void
+png_type_find (GstTypeFind * tf, gpointer unused)
+{
+  DataScanCtx c = { 0, NULL, 0 };
+  gboolean animated = FALSE;
+  GstTypeFindProbability prob = GST_TYPE_FIND_NONE;
+  guint chunks = 0;
+  static const guint8 signature[] =
+      { 0x89, 'P', 'N', 'G', 0x0d, 0x0a, 0x1a, 0x0a };
+
+  if (!data_scan_ctx_ensure_data (tf, &c, 8))
+    return;
+
+  if (memcmp (c.data, signature, sizeof (signature)) != 0)
+    return;
+
+  /* At least we found the right magic */
+  prob = GST_TYPE_FIND_LIKELY;
+  data_scan_ctx_advance (tf, &c, 8);
+
+  while (data_scan_ctx_ensure_data (tf, &c, 8)) {
+    // length: uint32_be
+    // type: fourcc
+    // <data>
+    // <crc32>: uint8[4]
+    const guint32 length = GST_READ_UINT32_BE (&c.data[0]);
+    const guint32 chunk = GST_READ_UINT32_LE (&c.data[4]);
+    // Test for critical chunks and the acTL chunk
+    if (chunk == GST_MAKE_FOURCC ('a', 'c', 'T', 'L')) {
+      animated = TRUE;
+      prob = GST_TYPE_FIND_NEARLY_CERTAIN;
+    } else if (chunk == GST_MAKE_FOURCC ('P', 'L', 'T', 'E')) {
+      prob = GST_TYPE_FIND_NEARLY_CERTAIN;
+    } else if (chunk == GST_MAKE_FOURCC ('I', 'D', 'A', 'T')) {
+      prob = GST_TYPE_FIND_MAXIMUM;
+      break;
+    }
+
+    data_scan_ctx_advance (tf, &c, 4 + 4);
+    data_scan_ctx_advance (tf, &c, length);
+    data_scan_ctx_advance (tf, &c, 4);
+    chunks++;
+
+    if (chunks >= PNG_MAXCHUNKS)
+      break;
+  }
+
+  if (animated) {
+    gst_type_find_suggest_simple (tf, prob, "image/png", "animated",
+        G_TYPE_BOOLEAN, TRUE, NULL);
+  } else {
+    gst_type_find_suggest (tf, prob, PNG_CAPS);
+  }
+}
+
 /*** application/x-smk ***/
 
 static GstStaticCaps smk_caps = GST_STATIC_CAPS ("application/x-smk");
@@ -6485,7 +6548,7 @@
   if (data == NULL)
     return;
 
-  /* want 0x00 0x00 at start */
+  /* want WBMP type 0 + empty FixHeaderField */
   if (*data++ != 0 || *data++ != 0)
     return;
 
@@ -6495,8 +6558,10 @@
   /* let's assume max width/height is 65536 */
   w = *data++;
   if ((w & 0x80)) {
-    w = (w << 8) | *data++;
-    if ((w & 0x80))
+    /* It's a multibyte integer, mask continuation bit and add */
+    w = ((w & 0x7F) << 7) | (*data & 0x7F);
+    /* Block > 65536px images */
+    if ((*data & 0x80))
       return;
     ++size;
     data = gst_type_find_peek (find, 4, 2);
@@ -6505,8 +6570,8 @@
   }
   h = *data++;
   if ((h & 0x80)) {
-    h = (h << 8) | *data++;
-    if ((h & 0x80))
+    h = ((h & 0x7F) << 7) | (*data & 0x7F);
+    if ((*data & 0x80))
       return;
     ++size;
   }
@@ -7058,6 +7123,8 @@
     tiff_type_find, "tif,tiff", TIFF_CAPS, NULL, NULL);
 GST_TYPE_FIND_REGISTER_DEFINE (exr, "image/x-exr", GST_RANK_PRIMARY,
     exr_type_find, "exr", EXR_CAPS, NULL, NULL);
+GST_TYPE_FIND_REGISTER_DEFINE (png, "image/png", GST_RANK_PRIMARY + 14,
+    png_type_find, "png", PNG_CAPS, NULL, NULL);
 GST_TYPE_FIND_REGISTER_DEFINE (pnm, "image/x-portable-pixmap",
     GST_RANK_SECONDARY, pnm_type_find, "pnm,ppm,pgm,pbm", PNM_CAPS, NULL, 
NULL);
 GST_TYPE_FIND_REGISTER_DEFINE (matroska, "video/x-matroska", GST_RANK_PRIMARY,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/gst-plugins-base-1.28.4/gst/typefind/gsttypefindfunctionsplugin.h 
new/gst-plugins-base-1.28.5/gst/typefind/gsttypefindfunctionsplugin.h
--- old/gst-plugins-base-1.28.4/gst/typefind/gsttypefindfunctionsplugin.h       
2026-06-12 14:19:43.000000000 +0200
+++ new/gst-plugins-base-1.28.5/gst/typefind/gsttypefindfunctionsplugin.h       
2026-07-08 23:42:39.000000000 +0200
@@ -69,6 +69,7 @@
 GST_TYPE_FIND_REGISTER_DECLARE (xcf);
 GST_TYPE_FIND_REGISTER_DECLARE (mng);
 GST_TYPE_FIND_REGISTER_DECLARE (jng);
+GST_TYPE_FIND_REGISTER_DECLARE (xbm);
 GST_TYPE_FIND_REGISTER_DECLARE (xpm);
 GST_TYPE_FIND_REGISTER_DECLARE (ras);
 GST_TYPE_FIND_REGISTER_DECLARE (bz2);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/gst-plugins-base-1.28.4/gst/typefind/gsttypefindfunctionsstartwith.c 
new/gst-plugins-base-1.28.5/gst/typefind/gsttypefindfunctionsstartwith.c
--- old/gst-plugins-base-1.28.4/gst/typefind/gsttypefindfunctionsstartwith.c    
2026-06-12 14:19:43.000000000 +0200
+++ new/gst-plugins-base-1.28.5/gst/typefind/gsttypefindfunctionsstartwith.c    
2026-07-08 23:42:39.000000000 +0200
@@ -102,9 +102,6 @@
     GST_RANK_PRIMARY, "rf64", "RF64", 4, GST_TYPE_FIND_MAXIMUM);
 TYPE_FIND_REGISTER_START_WITH_DEFINE (gif, "image/gif", GST_RANK_PRIMARY,
     "gif", "GIF8", 4, GST_TYPE_FIND_MAXIMUM);
-TYPE_FIND_REGISTER_START_WITH_DEFINE (png, "image/png",
-    GST_RANK_PRIMARY + 14, "png", "\211PNG\015\012\032\012", 8,
-    GST_TYPE_FIND_MAXIMUM);
 TYPE_FIND_REGISTER_START_WITH_DEFINE (mve, "video/x-mve",
     GST_RANK_SECONDARY, "mve",
     "Interplay MVE File\032\000\032\000\000\001\063\021", 26,
@@ -123,6 +120,8 @@
 TYPE_FIND_REGISTER_START_WITH_DEFINE (jng, "image/x-jng",
     GST_RANK_SECONDARY, "jng", "\213JNG\015\012\032\012", 8,
     GST_TYPE_FIND_MAXIMUM);
+TYPE_FIND_REGISTER_START_WITH_DEFINE (xbm, "image/x-xbitmap",
+    GST_RANK_SECONDARY, "xbm", "/* XBM */", 9, GST_TYPE_FIND_MAXIMUM);
 TYPE_FIND_REGISTER_START_WITH_DEFINE (xpm, "image/x-xpixmap",
     GST_RANK_SECONDARY, "xpm", "/* XPM */", 9, GST_TYPE_FIND_MAXIMUM);
 TYPE_FIND_REGISTER_START_WITH_DEFINE (ras, "image/x-sun-raster",
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/gst-plugins-base-1.28.4/gst-libs/gst/app/gstappsink.c 
new/gst-plugins-base-1.28.5/gst-libs/gst/app/gstappsink.c
--- old/gst-plugins-base-1.28.4/gst-libs/gst/app/gstappsink.c   2026-06-12 
14:19:43.000000000 +0200
+++ new/gst-plugins-base-1.28.5/gst-libs/gst/app/gstappsink.c   2026-07-08 
23:42:39.000000000 +0200
@@ -991,6 +991,18 @@
 }
 
 static void
+gst_app_sink_clear_sample_contents (GstAppSink * appsink)
+{
+  GstAppSinkPrivate *priv = appsink->priv;
+
+  priv->sample = gst_sample_make_writable (priv->sample);
+  gst_sample_set_buffer (priv->sample, NULL);
+  gst_sample_set_buffer_list (priv->sample, NULL);
+  gst_sample_set_caps (priv->sample, NULL);
+  gst_sample_set_segment (priv->sample, NULL);
+}
+
+static void
 gst_app_sink_flush_unlocked (GstAppSink * appsink)
 {
   GstMiniObject *obj;
@@ -1004,6 +1016,7 @@
 
   gst_queue_status_info_reset (&priv->queue_status_info);
 
+  gst_app_sink_clear_sample_contents (appsink);
   gst_caps_replace (&priv->last_caps, NULL);
   g_cond_signal (&priv->cond);
   priv->in = priv->out = priv->dropped = 0;
@@ -1022,11 +1035,7 @@
   priv->started = TRUE;
   gst_segment_init (&priv->preroll_segment, GST_FORMAT_TIME);
   gst_segment_init (&priv->last_segment, GST_FORMAT_TIME);
-  priv->sample = gst_sample_make_writable (priv->sample);
-  gst_sample_set_buffer (priv->sample, NULL);
-  gst_sample_set_buffer_list (priv->sample, NULL);
-  gst_sample_set_caps (priv->sample, NULL);
-  gst_sample_set_segment (priv->sample, NULL);
+  gst_app_sink_clear_sample_contents (appsink);
   priv->in = priv->out = priv->dropped = 0;
   g_mutex_unlock (&priv->mutex);
 
@@ -1050,11 +1059,7 @@
   gst_caps_replace (&priv->last_caps, NULL);
   gst_segment_init (&priv->preroll_segment, GST_FORMAT_UNDEFINED);
   gst_segment_init (&priv->last_segment, GST_FORMAT_UNDEFINED);
-  priv->sample = gst_sample_make_writable (priv->sample);
-  gst_sample_set_buffer (priv->sample, NULL);
-  gst_sample_set_buffer_list (priv->sample, NULL);
-  gst_sample_set_caps (priv->sample, NULL);
-  gst_sample_set_segment (priv->sample, NULL);
+  gst_app_sink_clear_sample_contents (appsink);
   priv->in = priv->out = priv->dropped = 0;
   g_mutex_unlock (&priv->mutex);
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gst-plugins-base-1.28.4/gst-libs/gst/app/gstappsrc.c 
new/gst-plugins-base-1.28.5/gst-libs/gst/app/gstappsrc.c
--- old/gst-plugins-base-1.28.4/gst-libs/gst/app/gstappsrc.c    2026-06-12 
14:19:43.000000000 +0200
+++ new/gst-plugins-base-1.28.5/gst-libs/gst/app/gstappsrc.c    2026-07-08 
23:42:39.000000000 +0200
@@ -1132,6 +1132,9 @@
         g_object_notify (G_OBJECT (appsrc), "dropped");
       }
       break;
+    case GST_EVENT_EOS:
+      gst_app_src_end_of_stream (appsrc);
+      break;
     default:
       if (GST_EVENT_IS_SERIALIZED (event)) {
         GST_DEBUG_OBJECT (appsrc, "queue event: %" GST_PTR_FORMAT, event);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/gst-plugins-base-1.28.4/gst-libs/gst/pbutils/descriptions.c 
new/gst-plugins-base-1.28.5/gst-libs/gst/pbutils/descriptions.c
--- old/gst-plugins-base-1.28.4/gst-libs/gst/pbutils/descriptions.c     
2026-06-12 14:19:43.000000000 +0200
+++ new/gst-plugins-base-1.28.5/gst-libs/gst/pbutils/descriptions.c     
2026-07-08 23:42:39.000000000 +0200
@@ -258,7 +258,6 @@
   {"image/ppm", "Portable PixMap (PPM)", FLAG_IMAGE, "ppm"},
   {"image/svg+xml", "Scalable Vector Graphics (SVG)", FLAG_IMAGE, "svg"},
   {"image/tiff", "TIFF", FLAG_IMAGE, "tiff"},
-  {"image/x-cmu-raster", "CMU Raster Format", FLAG_IMAGE, ""},
   {"image/x-degas", "DEGAS", FLAG_IMAGE, ""},
   {"image/x-icon", "ICO", FLAG_IMAGE, "ico"},
   {"image/x-j2c", "JPEG 2000", FLAG_VIDEO | FLAG_IMAGE, ""},
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/gst-plugins-base-1.28.4/gst-libs/gst/pbutils/encoding-target.c 
new/gst-plugins-base-1.28.5/gst-libs/gst/pbutils/encoding-target.c
--- old/gst-plugins-base-1.28.4/gst-libs/gst/pbutils/encoding-target.c  
2026-06-12 14:19:43.000000000 +0200
+++ new/gst-plugins-base-1.28.5/gst-libs/gst/pbutils/encoding-target.c  
2026-07-08 23:42:39.000000000 +0200
@@ -919,12 +919,15 @@
     GError ** error)
 {
   gint i;
-  gchar *p, *lname, *lfilename = NULL, *tldir, **encoding_target_dirs;
+  gchar *p, *lname = NULL, *lfilename = NULL, *tldir, **encoding_target_dirs;
   const gchar *envvar;
   GstEncodingTarget *target = NULL;
 
   g_return_val_if_fail (name != NULL, NULL);
 
+  if (!g_utf8_validate (name, -1, NULL))
+    goto invalid_name;
+
   p = lname = g_str_to_ascii (name, NULL);
   for (; *p; ++p)
     *p = g_ascii_tolower (*p);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/gst-plugins-base-1.28.4/gst-libs/gst/rtp/gstrtcpbuffer.c 
new/gst-plugins-base-1.28.5/gst-libs/gst/rtp/gstrtcpbuffer.c
--- old/gst-plugins-base-1.28.4/gst-libs/gst/rtp/gstrtcpbuffer.c        
2026-06-12 14:19:43.000000000 +0200
+++ new/gst-plugins-base-1.28.5/gst-libs/gst/rtp/gstrtcpbuffer.c        
2026-07-08 23:42:39.000000000 +0200
@@ -1272,29 +1272,20 @@
   return TRUE;
 }
 
-/**
- * gst_rtcp_packet_sdes_next_item:
- * @packet: a valid SDES #GstRTCPPacket
- *
- * Move to the next SDES item in @packet.
- *
- * Returns: TRUE if there was a next item.
- */
-gboolean
-gst_rtcp_packet_sdes_next_item (GstRTCPPacket * packet)
+static guint
+find_sdes_next_item_offset (GstRTCPPacket * packet)
 {
   guint8 *data;
   guint offset;
   guint len;
 
-  g_return_val_if_fail (packet != NULL, FALSE);
-  g_return_val_if_fail (packet->type == GST_RTCP_TYPE_SDES, FALSE);
-  g_return_val_if_fail (packet->rtcp != NULL, FALSE);
-  g_return_val_if_fail (packet->rtcp->map.flags & GST_MAP_READ, FALSE);
+  g_return_val_if_fail (packet != NULL, 0);
+  g_return_val_if_fail (packet->type == GST_RTCP_TYPE_SDES, 0);
+  g_return_val_if_fail (packet->rtcp != NULL, 0);
 
   /* if we are at the last item, we are done */
   if (packet->item_count == packet->count)
-    return FALSE;
+    return 0;
 
   /* move to SDES */
   data = packet->rtcp->map.data;
@@ -1304,7 +1295,7 @@
   /* skip SSRC */
   offset += 4;
 
-  /* don't overrun - use total packet size */
+  /* use total packet size */
   len = (packet->length + 1) << 2;
 
   while (offset < len) {
@@ -1314,10 +1305,39 @@
       break;
     }
     if (offset + 1 >= len)
-      return FALSE;
+      return 0;
     offset += data[offset + 1] + 2;
   }
 
+  return offset;
+}
+
+/**
+ * gst_rtcp_packet_sdes_next_item:
+ * @packet: a valid SDES #GstRTCPPacket
+ *
+ * Move to the next SDES item in @packet.
+ *
+ * Returns: TRUE if there was a next item.
+ */
+gboolean
+gst_rtcp_packet_sdes_next_item (GstRTCPPacket * packet)
+{
+  guint offset;
+  guint len;
+
+  g_return_val_if_fail (packet != NULL, FALSE);
+  g_return_val_if_fail (packet->type == GST_RTCP_TYPE_SDES, FALSE);
+  g_return_val_if_fail (packet->rtcp != NULL, FALSE);
+  g_return_val_if_fail (packet->rtcp->map.flags & GST_MAP_READ, FALSE);
+
+  offset = find_sdes_next_item_offset (packet);
+  if (offset == 0)
+    return FALSE;
+
+  /* use total packet size */
+  len = (packet->length + 1) << 2;
+
   /* needs at least SSRC and one item plus padding */
   if (offset + 4 + 4 > len)
     return FALSE;
@@ -1350,18 +1370,16 @@
 
   /* move to SDES */
   data = packet->rtcp->map.data;
-  guint offset = packet->offset;
-  /* move to item */
-  offset += packet->item_offset;
+  data += packet->offset;
 
   /* don't overrun - use total packet size */
   guint len = (packet->length + 1) << 2;
 
   /* needs at least SSRC and one item plus padding */
-  if (offset + 4 + 4 > len)
+  if (packet->item_offset + 4 + 4 > len)
     return 0;
 
-  ssrc = GST_READ_UINT32_BE (data + offset);
+  ssrc = GST_READ_UINT32_BE (data + packet->item_offset);
 
   return ssrc;
 }
@@ -1585,15 +1603,28 @@
   g_return_val_if_fail (packet->rtcp != NULL, FALSE);
   g_return_val_if_fail (packet->rtcp->map.flags & GST_MAP_WRITE, FALSE);
 
+  maxsize = packet->rtcp->map.maxsize;
+
   /* increment item count when possible */
   if (packet->count >= GST_RTCP_MAX_SDES_ITEM_COUNT)
     goto no_space;
 
-  /* pretend there is a next packet for the next call */
-  packet->count++;
+  /* Find the next free slot. The first item always goes at
+   * item_offset=4 (set by read_packet_header). For subsequent items
+   * we must skip past the current item and bail out if the SDES is
+   * too small to hold another one. Otherwise the next add_item()
+   * would silently overwrite the previous one at the previous
+   * item_offset. */
+  if (packet->count > 0) {
+    offset = find_sdes_next_item_offset (packet);
+    if (offset == 0 || packet->offset + offset + 8 > maxsize)
+      goto no_space;
+    packet->item_offset = offset;
+    packet->item_count++;
+    packet->entry_offset = 4;
+  }
 
-  /* jump over current item */
-  gst_rtcp_packet_sdes_next_item (packet);
+  packet->count++;
 
   /* move to SDES */
   data = packet->rtcp->map.data;
@@ -1602,8 +1633,11 @@
   /* move to current item */
   offset = packet->item_offset;
 
-  /* we need 2 free words now */
-  if (offset + 8 >= maxsize)
+  /* we need 2 free words. packet->offset may be non-zero for a SDES
+   * that follows another packet in a compound buffer, so compare
+   * against the absolute write position. Using the relative offset
+   * would allow appending past the buffer's maxsize. */
+  if (packet->offset + offset + 8 >= maxsize)
     goto no_next;
 
   /* write SSRC */
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/gst-plugins-base-1.28.4/gst-libs/gst/tag/gstvorbistag.c 
new/gst-plugins-base-1.28.5/gst-libs/gst/tag/gstvorbistag.c
--- old/gst-plugins-base-1.28.4/gst-libs/gst/tag/gstvorbistag.c 2026-06-12 
14:19:43.000000000 +0200
+++ new/gst-plugins-base-1.28.5/gst-libs/gst/tag/gstvorbistag.c 2026-07-08 
23:42:39.000000000 +0200
@@ -318,7 +318,7 @@
 
 static void
 gst_vorbis_tag_add_coverart (GstTagList * tags, gchar * img_data_base64,
-    gint base64_len)
+    gsize base64_len)
 {
   GstSample *img;
   gsize img_len;
@@ -369,7 +369,7 @@
  */
 static void
 gst_vorbis_tag_add_metadata_block_picture (GstTagList * tags,
-    gchar * value, gint value_len)
+    gchar * value, gsize value_len)
 {
   GstByteReader reader;
   guint32 img_len = 0, img_type = 0;
@@ -377,6 +377,9 @@
   gsize decoded_len;
   const guint8 *data = NULL;
 
+  if (value_len < 2)
+    goto not_enough_data;
+
   /* img_data_base64 points to a temporary copy of the base64 encoded data, so
    * it's safe to do inpace decoding here
    */
@@ -414,13 +417,25 @@
 
   return;
 
+/* ERRORS */
+not_enough_data:
+  {
+    GST_WARNING
+        ("METADATA_BLOCK_PICTURE tag with too little base64-encoded data");
+    return;
+  }
 error:
-  GST_WARNING
-      ("Couldn't extract image or image type from METADATA_BLOCK_PICTURE tag");
-  return;
+  {
+    GST_WARNING
+        ("Couldn't extract image or image type from METADATA_BLOCK_PICTURE 
tag");
+    return;
+  }
 decode_failed:
-  GST_WARNING ("Failed to decode Base64 data from METADATA_BLOCK_PICTURE tag");
-  return;
+  {
+    GST_WARNING
+        ("Failed to decode Base64 data from METADATA_BLOCK_PICTURE tag");
+    return;
+  }
 }
 
 /**
@@ -455,7 +470,7 @@
   gchar *cur, *value;
   guint cur_size;
   guint iterations;
-  guint value_len;
+  gsize value_len;
   GstTagList *list;
 
   g_return_val_if_fail (data != NULL, NULL);
@@ -490,7 +505,8 @@
     *value = '\0';
     value++;
     value_len = strlen (value);
-    if (value_len == 0 || !g_utf8_validate (value, value_len, NULL)) {
+    if (value_len == 0 || value_len > G_MAXSSIZE
+        || !g_utf8_validate (value, value_len, NULL)) {
       g_free (cur);
       continue;
     }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gst-plugins-base-1.28.4/gst-libs/gst/tag/gstxmptag.c 
new/gst-plugins-base-1.28.5/gst-libs/gst/tag/gstxmptag.c
--- old/gst-plugins-base-1.28.4/gst-libs/gst/tag/gstxmptag.c    2026-06-12 
14:19:43.000000000 +0200
+++ new/gst-plugins-base-1.28.5/gst-libs/gst/tag/gstxmptag.c    2026-07-08 
23:42:39.000000000 +0200
@@ -631,7 +631,7 @@
     return;
   }
 
-  if (sscanf (altitude_str, "%d/%d", &frac_n, &frac_d) != 2) {
+  if (sscanf (altitude_str, "%d/%d", &frac_n, &frac_d) != 2 || frac_d == 0) {
     GST_WARNING ("Failed to parse fraction: %s", altitude_str);
     return;
   }
@@ -724,7 +724,7 @@
     return;
   }
 
-  if (sscanf (speed_str, "%d/%d", &frac_n, &frac_d) != 2) {
+  if (sscanf (speed_str, "%d/%d", &frac_n, &frac_d) != 2 || frac_d == 0) {
     GST_WARNING ("Failed to parse fraction: %s", speed_str);
     return;
   }
@@ -819,7 +819,7 @@
     return;
   }
 
-  if (sscanf (dir_str, "%d/%d", &frac_n, &frac_d) != 2) {
+  if (sscanf (dir_str, "%d/%d", &frac_n, &frac_d) != 2 || frac_d == 0) {
     GST_WARNING ("Failed to parse fraction: %s", dir_str);
     return;
   }
@@ -1136,7 +1136,7 @@
       gdouble value = 0;
       gint frac_n, frac_d;
 
-      if (sscanf (v, "%d/%d", &frac_n, &frac_d) == 2) {
+      if (sscanf (v, "%d/%d", &frac_n, &frac_d) == 2 && frac_d != 0) {
         gst_util_fraction_to_double (frac_n, frac_d, &value);
         gst_tag_list_add (list, merge_mode, tag, value, NULL);
       } else {
@@ -1252,6 +1252,9 @@
   while (*xp1 != '<' && xp1 < xpe)
     xp1++;
 
+  if (xp2 < xp1)
+    goto missing_footer;
+
   /* no tag can be longer than the whole buffer */
   part = g_malloc (xp2 - xp1);
   list = gst_tag_list_new_empty ();
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gst-plugins-base-1.28.4/gst-plugins-base.doap 
new/gst-plugins-base-1.28.5/gst-plugins-base.doap
--- old/gst-plugins-base-1.28.4/gst-plugins-base.doap   2026-06-12 
14:19:43.000000000 +0200
+++ new/gst-plugins-base-1.28.5/gst-plugins-base.doap   2026-07-08 
23:42:39.000000000 +0200
@@ -36,6 +36,16 @@
 
  <release>
   <Version>
+   <revision>1.28.5</revision>
+   <branch>1.28</branch>
+   <name></name>
+   <created>2026-07-08</created>
+   <file-release 
rdf:resource="https://gstreamer.freedesktop.org/src/gst-plugins-base/gst-plugins-base-1.28.5.tar.xz";
 />
+  </Version>
+ </release>
+
+ <release>
+  <Version>
    <revision>1.28.4</revision>
    <branch>1.28</branch>
    <name></name>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gst-plugins-base-1.28.4/meson.build 
new/gst-plugins-base-1.28.5/meson.build
--- old/gst-plugins-base-1.28.4/meson.build     2026-06-12 14:19:43.000000000 
+0200
+++ new/gst-plugins-base-1.28.5/meson.build     2026-07-08 23:42:39.000000000 
+0200
@@ -1,5 +1,5 @@
 project('gst-plugins-base', 'c',
-  version : '1.28.4',
+  version : '1.28.5',
   meson_version : '>= 1.4',
   default_options : [ 'warning_level=1',
                       'buildtype=debugoptimized',
@@ -457,9 +457,10 @@
 #include <arm_neon.h>
 int32x4_t testfunc(int16_t *a, int16_t *b) {
   asm volatile ("vmull.s16 q0, d0, d0" : : : "q0");
+  asm volatile ("add.w r1, r0, r0" : : : "r0", "r1");
   return vmull_s16(vld1_s16(a), vld1_s16(b));
 }
-''', name : 'NEON support')
+''', name : 'NEON with 32-bit wide Thumb support')
     core_conf.set('HAVE_ARM_NEON', true)
   endif
 endif
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/gst-plugins-base-1.28.4/tests/check/gst/typefindfunctions.c 
new/gst-plugins-base-1.28.5/tests/check/gst/typefindfunctions.c
--- old/gst-plugins-base-1.28.4/tests/check/gst/typefindfunctions.c     
2026-06-12 14:19:43.000000000 +0200
+++ new/gst-plugins-base-1.28.5/tests/check/gst/typefindfunctions.c     
2026-07-08 23:42:39.000000000 +0200
@@ -535,6 +535,108 @@
 
 GST_END_TEST;
 
+GST_START_TEST (test_typefind_with_wav_dts_caps)
+{
+  GstTypeFindProbability prob;
+  const gchar *type;
+  GstBuffer *buf;
+  GstCaps *caps;
+  GstCaps *query_caps;
+  GList *factories;
+  guint8 *p;
+
+  /* WAV header (44 bytes) followed by two DTS frames (96 bytes each).
+   *
+   * The DTS typefinder scans within DTS_MAX_FRAMESIZE bytes and will
+   * find the DTS sync words after the WAV header. The WAV typefinder
+   * matches the RIFF/WAVE signature at offset 0.
+   *
+   * This tests the _with_caps scenario like in gstwavparse.c: where
+   * given a WAV stream, check if the content is actually DTS.
+   */
+  guint8 wav_dts_data[44 + 96 + 96];
+
+  p = wav_dts_data;
+
+  /* WAV header */
+  memcpy (p, "RIFF", 4);
+  GST_WRITE_UINT32_LE (p + 4, sizeof (wav_dts_data) - 8);       /* file size - 
8 */
+  memcpy (p + 8, "WAVE", 4);
+  memcpy (p + 12, "fmt ", 4);
+  GST_WRITE_UINT32_LE (p + 16, 16);     /* chunk size */
+  GST_WRITE_UINT16_LE (p + 20, 1);      /* PCM */
+  GST_WRITE_UINT16_LE (p + 22, 1);      /* mono */
+  GST_WRITE_UINT32_LE (p + 24, 44100);  /* sample rate */
+  GST_WRITE_UINT32_LE (p + 28, 88200);  /* byte rate */
+  GST_WRITE_UINT16_LE (p + 32, 2);      /* block align */
+  GST_WRITE_UINT16_LE (p + 34, 16);     /* bits per sample */
+  memcpy (p + 36, "data", 4);
+  GST_WRITE_UINT32_LE (p + 40, 96 * 2); /* data size */
+
+  /* Two DTS frames at offset 44 (inside the WAV data chunk) */
+  GST_WRITE_UINT32_BE (p + 44, 0x7FFE8001);     /* sync */
+  GST_WRITE_UINT16_BE (p + 48, 0x0014); /* num_blocks=5, frame_size high=0 */
+  GST_WRITE_UINT16_BE (p + 50, 0x05F0); /* frame_size low: (95<<4)=0x5F0 */
+  GST_WRITE_UINT16_BE (p + 52, 0x340F); /* sample_rate=48kHz */
+  GST_WRITE_UINT16_BE (p + 54, 0x2400); /* channels=6, lfe=0 */
+  memset (p + 56, 0, 96 - 12);
+
+  /* Second DTS frame at offset 140 */
+  GST_WRITE_UINT32_BE (p + 140, 0x7FFE8001);
+  GST_WRITE_UINT16_BE (p + 144, 0x0014);
+  GST_WRITE_UINT16_BE (p + 146, 0x05F0);
+  GST_WRITE_UINT16_BE (p + 148, 0x340F);
+  GST_WRITE_UINT16_BE (p + 150, 0x2400);
+  memset (p + 152, 0, 96 - 12);
+
+  buf = gst_buffer_new ();
+  gst_buffer_append_memory (buf,
+      gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
+          wav_dts_data, sizeof (wav_dts_data), 0, sizeof (wav_dts_data),
+          NULL, NULL));
+  GST_BUFFER_OFFSET (buf) = 0;
+
+  /* list_factories_for_caps with audio/x-wav should return factories */
+  query_caps = gst_caps_from_string ("audio/x-wav");
+  factories = gst_type_find_list_factories_for_caps (NULL, query_caps);
+  fail_unless (factories != NULL);
+  g_list_free_full (factories, (GDestroyNotify) gst_object_unref);
+
+  /* typefind with audio/x-wav should find WAV */
+  prob = 0;
+  caps = gst_type_find_helper_for_buffer_with_caps (NULL, buf,
+      query_caps, &prob);
+  fail_unless (caps != NULL,
+      "WAV+DTS: typefind with audio/x-wav caps should find WAV");
+  type = gst_structure_get_name (gst_caps_get_structure (caps, 0));
+  fail_unless_equals_string (type, "audio/x-wav");
+  fail_unless (prob == GST_TYPE_FIND_MAXIMUM);
+  gst_caps_unref (caps);
+  gst_caps_unref (query_caps);
+
+  /* list_factories_for_caps with audio/x-dts should return factories */
+  query_caps = gst_caps_from_string ("audio/x-dts");
+  factories = gst_type_find_list_factories_for_caps (NULL, query_caps);
+  fail_unless (factories != NULL);
+  g_list_free_full (factories, (GDestroyNotify) gst_object_unref);
+
+  /* typefind with audio/x-dts should find DTS (inside WAV data chunk) */
+  prob = 0;
+  caps = gst_type_find_helper_for_buffer_with_caps (NULL, buf,
+      query_caps, &prob);
+  fail_unless (caps != NULL,
+      "WAV+DTS: typefind with audio/x-dts caps should find DTS");
+  type = gst_structure_get_name (gst_caps_get_structure (caps, 0));
+  fail_unless_equals_string (type, "audio/x-dts");
+  fail_unless (prob == GST_TYPE_FIND_MAXIMUM);
+  gst_caps_unref (caps);
+  gst_caps_unref (query_caps);
+
+  gst_buffer_unref (buf);
+}
+
+GST_END_TEST;
+
 static Suite *
 typefindfunctions_suite (void)
 {
@@ -554,6 +656,7 @@
   tcase_add_test (tc_chain, test_manifest_typefinding);
   tcase_add_test (tc_chain, test_webvtt);
   tcase_add_test (tc_chain, test_subparse);
+  tcase_add_test (tc_chain, test_typefind_with_wav_dts_caps);
 
   return s;
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gst-plugins-base-1.28.4/tests/check/libs/pbutils.c 
new/gst-plugins-base-1.28.5/tests/check/libs/pbutils.c
--- old/gst-plugins-base-1.28.4/tests/check/libs/pbutils.c      2026-06-12 
14:19:43.000000000 +0200
+++ new/gst-plugins-base-1.28.5/tests/check/libs/pbutils.c      2026-07-08 
23:42:39.000000000 +0200
@@ -335,8 +335,8 @@
   "video/x-zlib", "image/bmp", "image/x-bmp",
   "image/x-MS-bmp", "image/gif", "image/jpeg", "image/jng", "image/png",
   "image/pbm", "image/ppm", "image/svg+xml", "image/tiff",
-  "image/x-cmu-raster", "image/x-icon", "image/x-xcf", "image/x-pixmap",
-  "image/x-xpixmap", "image/x-quicktime", "image/x-sun-raster",
+  "image/x-icon", "image/x-xcf", "image/x-pixmap",
+  "image/x-xpixmap", "image/x-quicktime",
   "image/x-tga", "video/x-dv", "video/x-dv",
   /* some RTP formats */
   "application/x-rtp, media=(string)video, encoding-name=(string)TimVCodec",
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gst-plugins-base-1.28.4/tests/check/libs/rtp.c 
new/gst-plugins-base-1.28.5/tests/check/libs/rtp.c
--- old/gst-plugins-base-1.28.4/tests/check/libs/rtp.c  2026-06-12 
14:19:43.000000000 +0200
+++ new/gst-plugins-base-1.28.5/tests/check/libs/rtp.c  2026-07-08 
23:42:39.000000000 +0200
@@ -2671,6 +2671,247 @@
 
 GST_END_TEST;
 
+GST_START_TEST (test_sdes_parsing_valid_in_compound_packet)
+{
+  /* Valid SDES packet as the second packet of an SR+SDES compound packet
+   * (RFC 3550 6.1). Its non-zero offset must not affect SDES parsing. */
+  GstRTCPBuffer rtcp = GST_RTCP_BUFFER_INIT;
+  GstRTCPPacket packet;
+  GstBuffer *buffer;
+  guint8 compound_data[] = {
+    0x80, 0xc8, 0x00, 0x06,     /* V=2, P=0, RC=0, PT=SR, length=6 (28 bytes) 
*/
+    0x12, 0x34, 0x56, 0x78,     /* SSRC */
+    0xed, 0xf2, 0xa1, 0x36,     /* NTP timestamp, most significant word */
+    0x70, 0x42, 0x90, 0x00,     /* NTP timestamp, least significant word */
+    0xcf, 0x35, 0x27, 0x2e,     /* RTP timestamp */
+    0x00, 0x00, 0x14, 0xd9,     /* sender's packet count */
+    0x00, 0x53, 0x72, 0x27,     /* sender's octet count */
+    0x81, 0xca, 0x00, 0x05,     /* V=2, P=0, SC=1, PT=SDES, length=5 (24 
bytes) */
+    0x12, 0x34, 0x56, 0x78,     /* SSRC */
+    0x01, 0x0a,                 /* CNAME, length=10 */
+    't', 'e', 's', 't', '@', 'f', 'o', 'o', '.', 'b',
+    0x00,                       /* End of SDES item list */
+    0x00, 0x00, 0x00            /* Pad chunk to 32-bit boundary (not RTCP 
P-bit padding) */
+  };
+
+  buffer = gst_buffer_new_and_alloc (sizeof (compound_data));
+  gst_buffer_fill (buffer, 0, compound_data, sizeof (compound_data));
+
+  fail_unless (gst_rtcp_buffer_map (buffer, GST_MAP_READ, &rtcp));
+  fail_unless (gst_rtcp_buffer_get_first_packet (&rtcp, &packet));
+  fail_unless_equals_int (gst_rtcp_packet_get_type (&packet), 
GST_RTCP_TYPE_SR);
+
+  /* move to the SDES packet */
+  fail_unless (gst_rtcp_packet_move_to_next (&packet));
+  fail_unless_equals_int (gst_rtcp_packet_get_type (&packet),
+      GST_RTCP_TYPE_SDES);
+
+  /* Get SSRC */
+  fail_unless_equals_int (gst_rtcp_packet_sdes_get_ssrc (&packet), 0x12345678);
+
+  /* Iterate items */
+  fail_unless (gst_rtcp_packet_sdes_first_item (&packet));
+  fail_unless_equals_int (gst_rtcp_packet_sdes_get_ssrc (&packet), 0x12345678);
+
+  /* Iterate entries */
+  fail_unless (gst_rtcp_packet_sdes_first_entry (&packet));
+  {
+    guint8 *data;
+    guint8 len;
+    GstRTCPSDESType type;
+
+    fail_unless (gst_rtcp_packet_sdes_get_entry (&packet, &type, &len, &data));
+    fail_unless_equals_int (type, GST_RTCP_SDES_CNAME);
+    fail_unless_equals_int (len, 10);
+    fail_unless (memcmp (data, "[email protected]", 10) == 0);
+  }
+  /* END marker is not an entry */
+  fail_if (gst_rtcp_packet_sdes_next_entry (&packet));
+  fail_if (gst_rtcp_packet_sdes_next_item (&packet));
+
+  gst_rtcp_buffer_unmap (&rtcp);
+  gst_buffer_unref (buffer);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_sdes_add_item_bounds_check_in_compound_packet)
+{
+  /* Compound SR+SDES where SDES starts at non-zero offset (28) and its
+   * length field (4) claims room for another item at relative offset
+   * 12. Adding that item would write at absolute 28 + 12 + 8 = 48,
+   * i.e. exactly maxsize, so the bounds check must use the absolute
+   * position; using the relative item_offset would silently let the
+   * item be appended past maxsize.
+   *
+   * gst_buffer_new_and_alloc() rounds maxsize up for alignment,
+   * which would mask the bug; gst_buffer_new_wrapped_full() lets us
+   * pin maxsize to exactly the requested size. */
+  GstBuffer *buffer;
+  GstRTCPBuffer rtcp = GST_RTCP_BUFFER_INIT;
+  GstRTCPPacket packet;
+  guint8 *raw_data;
+  const gsize buf_size = 48;
+  guint8 compound_data[] = {
+    /* SR: 7 words = 28 bytes */
+    0x80, 0xc8, 0x00, 0x06,     /* V=2, P=0, RC=0, PT=SR, length=6 */
+    0xaa, 0xaa, 0xaa, 0xaa,     /* SSRC */
+    0x00, 0x00, 0x00, 0x00,     /* NTP timestamp, most significant word */
+    0x00, 0x00, 0x00, 0x00,     /* NTP timestamp, least significant word */
+    0x00, 0x00, 0x00, 0x00,     /* RTP timestamp */
+    0x00, 0x00, 0x00, 0x00,     /* sender's packet count */
+    0x00, 0x00, 0x00, 0x00,     /* sender's octet count */
+
+    /* SDES: 5 words = 20 bytes, SC=1, length=4 */
+    0x81, 0xca, 0x00, 0x04,     /* V=2, P=0, SC=1, PT=SDES, length=4 */
+    0x12, 0x34, 0x56, 0x78,     /* SSRC */
+    0x00, 0x00, 0x00, 0x00,     /* 0 entry (end-of-items) */
+    0x00, 0x00, 0x00, 0x00,     /* unused */
+    0x00, 0x00, 0x00, 0x00,     /* unused */
+  };
+
+  raw_data = g_malloc (buf_size);
+  memcpy (raw_data, compound_data, sizeof (compound_data));
+  buffer = gst_buffer_new_wrapped_full (0, raw_data, buf_size, 0, buf_size,
+      raw_data, g_free);
+
+  fail_unless (gst_rtcp_buffer_map (buffer, GST_MAP_READWRITE, &rtcp));
+
+  fail_unless (gst_rtcp_buffer_get_first_packet (&rtcp, &packet));
+  fail_unless_equals_int (gst_rtcp_packet_get_type (&packet), 
GST_RTCP_TYPE_SR);
+  fail_unless (gst_rtcp_packet_move_to_next (&packet));
+  fail_unless_equals_int (gst_rtcp_packet_get_type (&packet),
+      GST_RTCP_TYPE_SDES);
+  fail_unless_equals_int (gst_rtcp_packet_get_count (&packet), 1);
+  fail_unless_equals_int (gst_rtcp_packet_get_length (&packet), 4);
+  fail_unless_equals_int (rtcp.map.maxsize, buf_size);
+
+  /* Adding the item would push the SDES to absolute position 48,
+   * i.e. the end of the buffer. Must be rejected, and the packet
+   * must remain parseable afterwards. */
+  fail_if (gst_rtcp_packet_sdes_add_item (&packet, 0x87654321));
+  fail_unless (gst_rtcp_buffer_validate (buffer));
+
+  gst_rtcp_buffer_unmap (&rtcp);
+  fail_unless (gst_rtcp_buffer_map (buffer, GST_MAP_READ, &rtcp));
+
+  fail_unless (gst_rtcp_buffer_get_first_packet (&rtcp, &packet));
+  fail_unless_equals_int (gst_rtcp_packet_get_type (&packet), 
GST_RTCP_TYPE_SR);
+  fail_unless (gst_rtcp_packet_move_to_next (&packet));
+  fail_unless_equals_int (gst_rtcp_packet_get_type (&packet),
+      GST_RTCP_TYPE_SDES);
+  fail_unless_equals_int (gst_rtcp_packet_get_count (&packet), 1);
+  fail_unless_equals_int (gst_rtcp_packet_get_length (&packet), 4);
+
+  fail_unless (gst_rtcp_packet_sdes_first_item (&packet));
+  fail_unless_equals_int (gst_rtcp_packet_sdes_get_ssrc (&packet), 0x12345678);
+  fail_if (gst_rtcp_packet_sdes_first_entry (&packet));
+
+  gst_rtcp_buffer_unmap (&rtcp);
+  gst_buffer_unref (buffer);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_sdes_add_item_and_parse)
+{
+  /* Positive test: add multiple SDES items and verify they can be parsed 
back. */
+  GstBuffer *buffer;
+  GstRTCPBuffer rtcp = GST_RTCP_BUFFER_INIT;
+  GstRTCPPacket packet;
+
+  buffer = gst_rtcp_buffer_new (1400);
+  fail_unless (buffer != NULL);
+
+  fail_unless (gst_rtcp_buffer_map (buffer, GST_MAP_READWRITE, &rtcp));
+
+  /* Add an SR packet first so validation passes */
+  fail_unless (gst_rtcp_buffer_add_packet (&rtcp, GST_RTCP_TYPE_SR, &packet));
+  gst_rtcp_packet_sr_set_sender_info (&packet, 0x12345678,
+      G_GUINT64_CONSTANT (0), 0, 0, 0);
+
+  /* Add an SDES packet */
+  fail_unless (gst_rtcp_buffer_add_packet (&rtcp, GST_RTCP_TYPE_SDES, 
&packet));
+
+  /* Add multiple items with entries */
+  fail_unless (gst_rtcp_packet_sdes_add_item (&packet, 0x11111111));
+  fail_unless (gst_rtcp_packet_sdes_add_entry (&packet, GST_RTCP_SDES_CNAME,
+          sizeof ("sender1") - 1, (guint8 *) "sender1"));
+
+  fail_unless (gst_rtcp_packet_sdes_add_item (&packet, 0x22222222));
+  fail_unless (gst_rtcp_packet_sdes_add_entry (&packet, GST_RTCP_SDES_CNAME,
+          sizeof ("sender2") - 1, (guint8 *) "sender2"));
+
+  fail_unless (gst_rtcp_packet_sdes_add_item (&packet, 0x33333333));
+  fail_unless (gst_rtcp_packet_sdes_add_entry (&packet, GST_RTCP_SDES_CNAME,
+          sizeof ("sender3") - 1, (guint8 *) "sender3"));
+
+  gst_rtcp_buffer_unmap (&rtcp);
+  /* Truncate buffer to actual size for validation to check the packets */
+  gst_buffer_set_size (buffer, rtcp.map.size);
+  fail_unless (gst_rtcp_buffer_validate (buffer));
+
+  /* Now parse the packet and verify all items are present */
+  fail_unless (gst_rtcp_buffer_map (buffer, GST_MAP_READ, &rtcp));
+
+  fail_unless (gst_rtcp_buffer_get_first_packet (&rtcp, &packet));
+  fail_unless_equals_int (gst_rtcp_packet_get_type (&packet), 
GST_RTCP_TYPE_SR);
+  fail_unless (gst_rtcp_packet_move_to_next (&packet));
+  fail_unless_equals_int (gst_rtcp_packet_get_type (&packet),
+      GST_RTCP_TYPE_SDES);
+  fail_unless_equals_int (gst_rtcp_packet_get_count (&packet), 3);
+
+  /* Verify first item */
+  fail_unless (gst_rtcp_packet_sdes_first_item (&packet));
+  fail_unless_equals_int (gst_rtcp_packet_sdes_get_ssrc (&packet), 0x11111111);
+  fail_unless (gst_rtcp_packet_sdes_first_entry (&packet));
+  {
+    guint8 *data;
+    guint8 len;
+    GstRTCPSDESType type;
+    fail_unless (gst_rtcp_packet_sdes_get_entry (&packet, &type, &len, &data));
+    fail_unless_equals_int (type, GST_RTCP_SDES_CNAME);
+    fail_unless_equals_int (len, 7);
+    fail_unless (memcmp (data, "sender1", 7) == 0);
+  }
+
+  /* Verify second item */
+  fail_unless (gst_rtcp_packet_sdes_next_item (&packet));
+  fail_unless_equals_int (gst_rtcp_packet_sdes_get_ssrc (&packet), 0x22222222);
+  fail_unless (gst_rtcp_packet_sdes_first_entry (&packet));
+  {
+    guint8 *data;
+    guint8 len;
+    GstRTCPSDESType type;
+    fail_unless (gst_rtcp_packet_sdes_get_entry (&packet, &type, &len, &data));
+    fail_unless_equals_int (type, GST_RTCP_SDES_CNAME);
+    fail_unless_equals_int (len, 7);
+    fail_unless (memcmp (data, "sender2", 7) == 0);
+  }
+
+  /* Verify third item */
+  fail_unless (gst_rtcp_packet_sdes_next_item (&packet));
+  fail_unless_equals_int (gst_rtcp_packet_sdes_get_ssrc (&packet), 0x33333333);
+  fail_unless (gst_rtcp_packet_sdes_first_entry (&packet));
+  {
+    guint8 *data;
+    guint8 len;
+    GstRTCPSDESType type;
+    fail_unless (gst_rtcp_packet_sdes_get_entry (&packet, &type, &len, &data));
+    fail_unless_equals_int (type, GST_RTCP_SDES_CNAME);
+    fail_unless_equals_int (len, 7);
+    fail_unless (memcmp (data, "sender3", 7) == 0);
+  }
+
+  /* No more items */
+  fail_if (gst_rtcp_packet_sdes_next_item (&packet));
+
+  gst_rtcp_buffer_unmap (&rtcp);
+  gst_buffer_unref (buffer);
+}
+
+GST_END_TEST;
+
 GST_START_TEST (test_sdes_parsing_truncated_entry)
 {
   /* SDES item with only SSRC and no entry data at all */
@@ -2889,6 +3130,9 @@
 
   tcase_add_test (tc_chain, test_sdes_parsing_out_of_bounds);
   tcase_add_test (tc_chain, test_sdes_parsing_valid_single_item);
+  tcase_add_test (tc_chain, test_sdes_parsing_valid_in_compound_packet);
+  tcase_add_test (tc_chain, 
test_sdes_add_item_bounds_check_in_compound_packet);
+  tcase_add_test (tc_chain, test_sdes_add_item_and_parse);
   tcase_add_test (tc_chain,
       test_sdes_parsing_valid_single_item_multiple_entries);
   tcase_add_test (tc_chain, test_sdes_parsing_valid_multiple_items);

++++++ gst-plugins-base.obsinfo ++++++
--- /var/tmp/diff_new_pack.oGsJru/_old  2026-07-12 16:21:16.004227436 +0200
+++ /var/tmp/diff_new_pack.oGsJru/_new  2026-07-12 16:21:16.072229762 +0200
@@ -1,5 +1,5 @@
 name: gst-plugins-base
-version: 1.28.4
-mtime: 1781266783
-commit: b46f881eaa8126eddfd21b5ae5512f8d4ff36255
+version: 1.28.5
+mtime: 1783546959
+commit: 727ceb91886862d200f423baf36cde2bb7ce5b4d
 

Reply via email to