Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package gstreamer for openSUSE:Factory 
checked in at 2026-09-11 19:00:31
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/gstreamer (Old)
 and      /work/SRC/openSUSE:Factory/.gstreamer.new.1265 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "gstreamer"

Fri Sep 11 19:00:31 2026 rev:126 rq:1376925 version:1.28.7

Changes:
--------
--- /work/SRC/openSUSE:Factory/gstreamer/gstreamer.changes      2026-08-06 
16:19:27.390698353 +0200
+++ /work/SRC/openSUSE:Factory/.gstreamer.new.1265/gstreamer.changes    
2026-09-11 19:01:04.954996372 +0200
@@ -1,0 +2,37 @@
+Tue Sep  8 06:46:28 UTC 2026 - Bjørn Lie <[email protected]>
+
+- Update to version 1.28.7:
+  +  Highlighted bugfixes:
+     - Various security fixes and playback fixes
+     - appsrc EOS handling regression fix for applications pushing
+       EOS into a blocked appsrc
+     - glcolorconvert fixes for older OpenGL/GLSL versions
+     - mxfdemux: Fix keyframe detection regression and possible
+       artefacts after seeking
+     - QML6 GL Overlay output texture lifetime handling fixes
+     - opencv: Add support for building against OpenCV 5
+     - hip: Add missing API version suffix in HIP support library
+       filename and fix hipcc detection on Windows with HIP SDK 7.x
+     - analytics: fix classes off-by-one in ssdtensordec leading to
+       mislabelling of objects in the examples
+     - isobmff: Fix min_display_mastering_luminance in mdcv box
+     - rtpbin2: rtprecv: limit the number of remote sources being
+       tracked
+     - st2038anc: parity bit handling fixes for ST 291 ADF words
+     - video converter and videoconvertscale fixes
+     - mpegdemux: restore gap event sending in MPEG-PS demuxer
+     - typefinding: fix typefinding regressions for ogg and text
+       files
+     - Fix x264enc high bit depth support in binary packages
+     - Various bug fixes, build fixes, memory leak fixes, and other
+       stability and reliability improvements
+  + gstreamer:
+    - cpuid: Clean up NEON and ASIMD getauxval detection + port
+      Orc's elf_aux_info support
+    - dataurisrc: Fix empty payloads and unsupported charset
+      conversion
+    - pipeline: Avoid lock inversion when handling
+      GST_MESSAGE_RESET_TIME
+    - validate: Use a single value type in configs lists
+
+-------------------------------------------------------------------

Old:
----
  gstreamer-1.28.6.obscpio

New:
----
  gstreamer-1.28.7.obscpio

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

Other differences:
------------------
++++++ gstreamer.spec ++++++
--- /var/tmp/diff_new_pack.Y57pUO/_old  2026-09-11 19:01:06.390056178 +0200
+++ /var/tmp/diff_new_pack.Y57pUO/_new  2026-09-11 19:01:06.392056261 +0200
@@ -19,7 +19,7 @@
 %define gst_branch 1.0
 
 Name:           gstreamer
-Version:        1.28.6
+Version:        1.28.7
 Release:        0
 Summary:        Streaming-Media Framework Runtime
 License:        LGPL-2.1-or-later

++++++ _service ++++++
--- /var/tmp/diff_new_pack.Y57pUO/_old  2026-09-11 19:01:06.434058012 +0200
+++ /var/tmp/diff_new_pack.Y57pUO/_new  2026-09-11 19:01:06.439058220 +0200
@@ -5,7 +5,7 @@
     <param 
name="url">https://gitlab.freedesktop.org/gstreamer/gstreamer.git</param>
     <param name="subdir">subprojects/gstreamer</param>
     <param name="filename">gstreamer</param>
-    <param name="revision">1.28.6</param>
+    <param name="revision">1.28.7</param>
     <param name="versionformat">@PARENT_TAG@+@TAG_OFFSET@</param>
     <param name="versionrewrite-pattern">v?(.*)\+0</param>
     <param name="versionrewrite-replacement">\1</param>

++++++ gstreamer-1.28.6.obscpio -> gstreamer-1.28.7.obscpio ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gstreamer-1.28.6/gst/gstcpuid.c 
new/gstreamer-1.28.7/gst/gstcpuid.c
--- old/gstreamer-1.28.6/gst/gstcpuid.c 2026-08-05 13:59:39.000000000 +0200
+++ new/gstreamer-1.28.7/gst/gstcpuid.c 2026-09-07 21:11:13.000000000 +0200
@@ -15,6 +15,10 @@
  * The full license is in the file LICENSE, distributed with this software. *
  ****************************************************************************/
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include "gstcpuid.h"
 
 // define G_ALWAYS_INLINE to force MSVC to get rid of the interstitial
@@ -39,7 +43,12 @@
 
 #if defined(__linux__) && defined(__ARM_ARCH)
 #include <asm/hwcap.h>
+#endif
+#if defined(__linux__) || defined(HAVE_ELF_AUX_INFO)
 #include <sys/auxv.h>
+#endif
+
+#if defined(GST_CPUID_CHECK_ARM)
 #if defined(__aarch64__)
 #ifndef HWCAP_ASIMD
 #define HWCAP_ASIMD (1 << 1)
@@ -157,16 +166,26 @@
   // See 
https://gitlab.freedesktop.org/gstreamer/orc/-/commit/7a60e2074d425b7ad1192ff48ac87af4246a04c4
   cpuid.neon = TRUE;
   cpuid.neon64 = TRUE;
-#elif defined(__ARM_ARCH)
-  // If Linux, rely on getauxval; otherwise search Arm macros
-  // 
https://developer.arm.com/documentation/dui0774/b/other-compiler-specific-features/predefined-macros
+#elif defined(GST_CPUID_CHECK_ARM)
+  // If Linux, rely on getauxval; otherwise try elf_aux_info
 #if defined(__linux__) && (!defined(__ANDROID_API__) || __ANDROID_API__ >= 18)
 #if defined(__aarch64__)
   cpuid.neon = (getauxval (AT_HWCAP) & HWCAP_ASIMD) != 0 ? TRUE : FALSE;
 #else
   cpuid.neon = (getauxval (AT_HWCAP) & HWCAP_NEON) != 0 ? TRUE : FALSE;
 #endif
-#elif defined(__ARM_NEON) || defined(__aarch64__)
+#elif defined(HAVE_ELF_AUX_INFO)
+  unsigned long auxv = 0;
+  elf_aux_info (AT_HWCAP, &auxv, sizeof (auxv));
+#if defined(__aarch64__)
+  cpuid.neon = (auxv & HWCAP_ASIMD) != 0 ? TRUE : FALSE;
+#else
+  cpuid.neon = (auxv & HWCAP_NEON) != 0 ? TRUE : FALSE;
+#endif
+#elif defined(__ARM_NEON) || defined (__aarch64__)
+  // If enabled unconditionally by compiler, use it
+  // 
https://support.arm.com/documentation/102474/0100/Fundamentals-of-Armv8-Neon-technology
+  // 
https://developer.arm.com/documentation/dui0774/b/other-compiler-specific-features/predefined-macros
   cpuid.neon = TRUE;
 #endif
 #if defined(__aarch64__)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gstreamer-1.28.6/gst/gstpipeline.c 
new/gstreamer-1.28.7/gst/gstpipeline.c
--- old/gstreamer-1.28.6/gst/gstpipeline.c      2026-08-05 13:59:39.000000000 
+0200
+++ new/gstreamer-1.28.7/gst/gstpipeline.c      2026-09-07 21:11:13.000000000 
+0200
@@ -394,6 +394,105 @@
   GST_OBJECT_UNLOCK (element);
 }
 
+static gboolean
+pipeline_update_clock_and_base_time (GstPipeline * pipeline)
+{
+  GstElement *element = GST_ELEMENT_CAST (pipeline);
+  GstClockTime now, start_time, last_start_time, delay;
+  gboolean update_clock;
+  GstClock *cur_clock;
+
+  GST_DEBUG_OBJECT (element, "selecting clock and base_time");
+
+  GST_OBJECT_LOCK (element);
+  cur_clock = element->clock;
+  if (cur_clock)
+    gst_object_ref (cur_clock);
+  /* get the desired running_time of the first buffer aka the start_time */
+  start_time = GST_ELEMENT_START_TIME (pipeline);
+  last_start_time = pipeline->priv->last_start_time;
+  pipeline->priv->last_start_time = start_time;
+  /* see if we need to update the clock */
+  update_clock = pipeline->priv->update_clock;
+  pipeline->priv->update_clock = FALSE;
+  delay = pipeline->delay;
+  GST_OBJECT_UNLOCK (element);
+
+  /* running time changed, either with a PAUSED or a flush, we need to check
+   * if there is a new clock & update the base time */
+  /* only do this for top-level, however */
+  if (GST_OBJECT_PARENT (element) == NULL &&
+      (update_clock || last_start_time != start_time)) {
+    GstClock *clock = NULL;
+    GST_DEBUG_OBJECT (pipeline, "Need to update start_time");
+
+    /* when going to PLAYING, select a clock when needed. If we just got
+     * flushed, we don't reselect the clock. */
+    if (update_clock) {
+      GST_DEBUG_OBJECT (pipeline, "Need to update clock.");
+      clock = gst_element_provide_clock (element);
+    } else {
+      GST_DEBUG_OBJECT (pipeline,
+          "Don't need to update clock, using old clock.");
+      /* only try to ref if cur_clock is not NULL */
+      if (cur_clock)
+        clock = gst_object_ref (cur_clock);
+    }
+
+    if (clock) {
+      now = gst_clock_get_time (clock);
+    } else {
+      GST_DEBUG_OBJECT (pipeline, "no clock, using base time of NONE");
+      now = GST_CLOCK_TIME_NONE;
+    }
+
+    if (clock != cur_clock) {
+      /* now distribute the clock (which could be NULL). If some
+       * element refuses the clock, this will return FALSE and
+       * we effectively fail the state change. */
+      if (!gst_element_set_clock (element, clock)) {
+        /* selected clock was not accepted by some element */
+        GST_ELEMENT_ERROR (pipeline, CORE, CLOCK,
+            (_("Selected clock cannot be used in pipeline.")),
+            ("Pipeline cannot operate with selected clock"));
+        GST_DEBUG_OBJECT (pipeline,
+            "Pipeline cannot operate with selected clock %p", clock);
+        gst_clear_object (&clock);
+        gst_clear_object (&cur_clock);
+        return FALSE;
+      }
+
+      /* if we selected and distributed a new clock, let the app
+       * know about it */
+      gst_element_post_message (element,
+          gst_message_new_new_clock (GST_OBJECT_CAST (element), clock));
+    }
+
+    gst_clear_object (&clock);
+
+    if (start_time != GST_CLOCK_TIME_NONE && now != GST_CLOCK_TIME_NONE) {
+      GstClockTime new_base_time = now - start_time + delay;
+      GST_DEBUG_OBJECT (element,
+          "start_time=%" GST_TIME_FORMAT ", now=%" GST_TIME_FORMAT
+          ", base_time %" GST_TIME_FORMAT,
+          GST_TIME_ARGS (start_time), GST_TIME_ARGS (now),
+          GST_TIME_ARGS (new_base_time));
+
+      gst_element_set_base_time (element, new_base_time);
+    } else {
+      GST_DEBUG_OBJECT (pipeline,
+          "NOT adjusting base_time because start_time is NONE");
+    }
+  } else {
+    GST_DEBUG_OBJECT (pipeline,
+        "NOT adjusting base_time because we selected one before");
+  }
+
+  gst_clear_object (&cur_clock);
+
+  return TRUE;
+}
+
 /* MT safe */
 static GstStateChangeReturn
 gst_pipeline_change_state (GstElement * element, GstStateChange transition)
@@ -425,100 +524,9 @@
       reset_start_time (pipeline, 0);
       break;
     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
-    {
-      GstClockTime now, start_time, last_start_time, delay;
-      gboolean update_clock;
-      GstClock *cur_clock;
-
-      GST_DEBUG_OBJECT (element, "selecting clock and base_time");
-
-      GST_OBJECT_LOCK (element);
-      cur_clock = element->clock;
-      if (cur_clock)
-        gst_object_ref (cur_clock);
-      /* get the desired running_time of the first buffer aka the start_time */
-      start_time = GST_ELEMENT_START_TIME (pipeline);
-      last_start_time = pipeline->priv->last_start_time;
-      pipeline->priv->last_start_time = start_time;
-      /* see if we need to update the clock */
-      update_clock = pipeline->priv->update_clock;
-      pipeline->priv->update_clock = FALSE;
-      delay = pipeline->delay;
-      GST_OBJECT_UNLOCK (element);
-
-      /* running time changed, either with a PAUSED or a flush, we need to 
check
-       * if there is a new clock & update the base time */
-      /* only do this for top-level, however */
-      if (GST_OBJECT_PARENT (element) == NULL &&
-          (update_clock || last_start_time != start_time)) {
-        GstClock *clock = NULL;
-        GST_DEBUG_OBJECT (pipeline, "Need to update start_time");
-
-        /* when going to PLAYING, select a clock when needed. If we just got
-         * flushed, we don't reselect the clock. */
-        if (update_clock) {
-          GST_DEBUG_OBJECT (pipeline, "Need to update clock.");
-          clock = gst_element_provide_clock (element);
-        } else {
-          GST_DEBUG_OBJECT (pipeline,
-              "Don't need to update clock, using old clock.");
-          /* only try to ref if cur_clock is not NULL */
-          if (cur_clock)
-            clock = gst_object_ref (cur_clock);
-        }
-
-        if (clock) {
-          now = gst_clock_get_time (clock);
-        } else {
-          GST_DEBUG_OBJECT (pipeline, "no clock, using base time of NONE");
-          now = GST_CLOCK_TIME_NONE;
-        }
-
-        if (clock != cur_clock) {
-          /* now distribute the clock (which could be NULL). If some
-           * element refuses the clock, this will return FALSE and
-           * we effectively fail the state change. */
-          if (!gst_element_set_clock (element, clock)) {
-            /* selected clock was not accepted by some element */
-            GST_ELEMENT_ERROR (pipeline, CORE, CLOCK,
-                (_("Selected clock cannot be used in pipeline.")),
-                ("Pipeline cannot operate with selected clock"));
-            GST_DEBUG_OBJECT (pipeline,
-                "Pipeline cannot operate with selected clock %p", clock);
-            gst_clear_object (&clock);
-            gst_clear_object (&cur_clock);
-            return GST_STATE_CHANGE_FAILURE;
-          }
-
-          /* if we selected and distributed a new clock, let the app
-           * know about it */
-          gst_element_post_message (element,
-              gst_message_new_new_clock (GST_OBJECT_CAST (element), clock));
-        }
-
-        gst_clear_object (&clock);
-
-        if (start_time != GST_CLOCK_TIME_NONE && now != GST_CLOCK_TIME_NONE) {
-          GstClockTime new_base_time = now - start_time + delay;
-          GST_DEBUG_OBJECT (element,
-              "start_time=%" GST_TIME_FORMAT ", now=%" GST_TIME_FORMAT
-              ", base_time %" GST_TIME_FORMAT,
-              GST_TIME_ARGS (start_time), GST_TIME_ARGS (now),
-              GST_TIME_ARGS (new_base_time));
-
-          gst_element_set_base_time (element, new_base_time);
-        } else {
-          GST_DEBUG_OBJECT (pipeline,
-              "NOT adjusting base_time because start_time is NONE");
-        }
-      } else {
-        GST_DEBUG_OBJECT (pipeline,
-            "NOT adjusting base_time because we selected one before");
-      }
-
-      gst_clear_object (&cur_clock);
+      if (!pipeline_update_clock_and_base_time (pipeline))
+        return GST_STATE_CHANGE_FAILURE;
       break;
-    }
     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
     {
       /* we take a start_time snapshot before calling the children state 
changes
@@ -633,8 +641,7 @@
 
       /* If we are live, sample a new base_time immediately */
       if (is_live && GST_STATE_TARGET (pipeline) == GST_STATE_PLAYING) {
-        gst_pipeline_change_state (GST_ELEMENT (pipeline),
-            GST_STATE_CHANGE_PAUSED_TO_PLAYING);
+        pipeline_update_clock_and_base_time (pipeline);
       }
 
       break;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gstreamer-1.28.6/gstreamer.doap 
new/gstreamer-1.28.7/gstreamer.doap
--- old/gstreamer-1.28.6/gstreamer.doap 2026-08-05 13:59:39.000000000 +0200
+++ new/gstreamer-1.28.7/gstreamer.doap 2026-09-07 21:11:13.000000000 +0200
@@ -40,6 +40,16 @@
 
  <release>
   <Version>
+   <revision>1.28.7</revision>
+   <branch>1.28</branch>
+   <name></name>
+   <created>2026-09-07</created>
+   <file-release 
rdf:resource="https://gstreamer.freedesktop.org/src/gstreamer/gstreamer-1.28.7.tar.xz";
 />
+  </Version>
+ </release>
+
+ <release>
+  <Version>
    <revision>1.28.6</revision>
    <branch>1.28</branch>
    <name></name>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gstreamer-1.28.6/libs/gst/base/gsttypefindhelper.c 
new/gstreamer-1.28.7/libs/gst/base/gsttypefindhelper.c
--- old/gstreamer-1.28.6/libs/gst/base/gsttypefindhelper.c      2026-08-05 
13:59:39.000000000 +0200
+++ new/gstreamer-1.28.7/libs/gst/base/gsttypefindhelper.c      2026-09-07 
21:11:13.000000000 +0200
@@ -964,6 +964,10 @@
 
     factory = GST_TYPE_FIND_FACTORY (l->data);
 
+    /* we only want to check those factories without a function */
+    if (gst_type_find_factory_has_function (factory))
+      continue;
+
     /* get the extension that this typefind factory can handle */
     ext = gst_type_find_factory_get_extensions (factory);
     if (ext == NULL)
@@ -1026,6 +1030,10 @@
 
     factory = GST_TYPE_FIND_FACTORY (l->data);
 
+    /* We only want to check those factories without a function */
+    if (gst_type_find_factory_has_function (factory))
+      continue;
+
     /* Get the caps that this typefind factory can handle */
     factory_caps = gst_type_find_factory_get_caps (factory);
     if (!factory_caps)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gstreamer-1.28.6/meson.build 
new/gstreamer-1.28.7/meson.build
--- old/gstreamer-1.28.6/meson.build    2026-08-05 13:59:39.000000000 +0200
+++ new/gstreamer-1.28.7/meson.build    2026-09-07 21:11:13.000000000 +0200
@@ -1,5 +1,5 @@
 project('gstreamer', 'c',
-  version : '1.28.6',
+  version : '1.28.7',
   meson_version : '>= 1.4',
   default_options : [ 'warning_level=1',
                       'buildtype=debugoptimized',
@@ -402,6 +402,9 @@
 elif cc.has_function('_pipe', prefix : '#include <io.h>')
   cdata.set('HAVE_PIPE', 1)
 endif
+if cc.has_function('elf_aux_info', prefix : '#include <sys/auxv.h>')
+  cdata.set('HAVE_ELF_AUX_INFO', 1)
+endif
 
 # Platform deps; only ws2_32 and execinfo for now
 platform_deps = []
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gstreamer-1.28.6/plugins/elements/gstdataurisrc.c 
new/gstreamer-1.28.7/plugins/elements/gstdataurisrc.c
--- old/gstreamer-1.28.6/plugins/elements/gstdataurisrc.c       2026-08-05 
13:59:39.000000000 +0200
+++ new/gstreamer-1.28.7/plugins/elements/gstdataurisrc.c       2026-09-07 
21:11:13.000000000 +0200
@@ -405,13 +405,23 @@
         g_convert_with_fallback (bdata, bsize, "UTF-8", charset, (char *) "*",
         &read, &written, NULL);
     g_free (bdata);
+    if (data == NULL)
+      goto invalid_uri_encoded_data;
 
     bdata = data;
     bsize = written;
   }
-  buffer = gst_buffer_new_wrapped (bdata, bsize);
+  if (bsize == 0) {
+    g_free (bdata);
+    buffer = gst_buffer_new ();
+  } else {
+    buffer = gst_buffer_new_wrapped (bdata, bsize);
+  }
 
-  caps = gst_type_find_helper_for_buffer (GST_OBJECT (src), buffer, NULL);
+  if (bsize > 0)
+    caps = gst_type_find_helper_for_buffer (GST_OBJECT (src), buffer, NULL);
+  else
+    caps = NULL;
   if (!caps)
     caps = gst_caps_new_empty_simple (mimetype);
   gst_base_src_set_caps (GST_BASE_SRC_CAST (src), caps);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gstreamer-1.28.6/tests/check/elements/dataurisrc.c 
new/gstreamer-1.28.7/tests/check/elements/dataurisrc.c
--- old/gstreamer-1.28.6/tests/check/elements/dataurisrc.c      2026-08-05 
13:59:39.000000000 +0200
+++ new/gstreamer-1.28.7/tests/check/elements/dataurisrc.c      2026-09-07 
21:11:13.000000000 +0200
@@ -517,6 +517,25 @@
 
 GST_END_TEST;
 
+static gboolean
+can_convert_iso_8859_5_to_utf8 (void)
+{
+  const gchar iso_8859_5_sample[] = { (gchar) 0xc0, 0 };
+  GError *error = NULL;
+  gchar *converted;
+
+  converted =
+      g_convert_with_fallback (iso_8859_5_sample, 1, "UTF-8", "ISO-8859-5",
+      (gchar *) "*", NULL, NULL, &error);
+  if (converted == NULL) {
+    g_clear_error (&error);
+    return FALSE;
+  }
+
+  g_free (converted);
+  return TRUE;
+}
+
 GST_START_TEST (test_dataurisrc_uris)
 {
 #define STRING_CONTENT(s) s, sizeof(s) - 1
@@ -548,6 +567,10 @@
     GstElement *src;
     GstBuffer *buf;
 
+    if (g_str_equal (tests[i].name, "charset_base64") &&
+        !can_convert_iso_8859_5_to_utf8 ())
+      continue;
+
     src = gst_element_factory_make ("dataurisrc", NULL);
     g_object_set (src, "uri", tests[i].uri, NULL);
     h = gst_harness_new_with_element (src, NULL, "src");
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gstreamer-1.28.6/tests/check/gst/gstpipeline.c 
new/gstreamer-1.28.7/tests/check/gst/gstpipeline.c
--- old/gstreamer-1.28.6/tests/check/gst/gstpipeline.c  2026-08-05 
13:59:39.000000000 +0200
+++ new/gstreamer-1.28.7/tests/check/gst/gstpipeline.c  2026-09-07 
21:11:13.000000000 +0200
@@ -43,6 +43,157 @@
 
 GST_END_TEST;
 
+typedef struct
+{
+  GstElement *pipeline;
+  GstElement *sink;
+  GstPad *sinkpad;
+  GMutex lock;
+  GCond cond;
+  gboolean stream_locked;
+  gboolean post_reset_time;
+  gboolean message_posted;
+  gboolean do_latency_called;
+  gboolean state_lock_contended;
+  GstClockTime reset_running_time;
+} ResetTimeLockData;
+
+static gboolean
+reset_time_do_latency (G_GNUC_UNUSED GstBin * bin, gpointer user_data)
+{
+  ResetTimeLockData *data = user_data;
+  gboolean state_lock_acquired = GST_STATE_TRYLOCK (data->pipeline);
+
+  if (state_lock_acquired)
+    GST_STATE_UNLOCK (data->pipeline);
+
+  data->do_latency_called = TRUE;
+  data->state_lock_contended = !state_lock_acquired;
+
+  /* Do not run the default handler, whose latency event would eventually
+   * wait for the state lock. */
+  return TRUE;
+}
+
+static gpointer
+post_reset_time_with_stream_lock (gpointer user_data)
+{
+  ResetTimeLockData *data = user_data;
+
+  GST_PAD_STREAM_LOCK (data->sinkpad);
+
+  g_mutex_lock (&data->lock);
+  data->stream_locked = TRUE;
+  g_cond_broadcast (&data->cond);
+  while (!data->post_reset_time)
+    g_cond_wait (&data->cond, &data->lock);
+  g_mutex_unlock (&data->lock);
+
+  gst_element_post_message (data->sink,
+      gst_message_new_reset_time (GST_OBJECT (data->sink),
+          data->reset_running_time));
+
+  g_mutex_lock (&data->lock);
+  data->message_posted = TRUE;
+  g_cond_broadcast (&data->cond);
+  g_mutex_unlock (&data->lock);
+
+  GST_PAD_STREAM_UNLOCK (data->sinkpad);
+
+  return NULL;
+}
+
+/* Check that RESET_TIME updates the base time without running the parent bin's
+ * state transition. Model the lock inversion seen when a streaming thread
+ * posts RESET_TIME while holding a sink-pad stream lock and a state-change
+ * thread holds the pipeline state lock while waiting for that stream lock. The
+ * custom do-latency handler uses trylock to detect the inverse state-lock
+ * contention and suppresses the default handler so the test reports the
+ * condition rather than deadlocking. */
+GST_START_TEST (test_reset_time_during_state_change)
+{
+  ResetTimeLockData data = { 0, };
+  GstElement *pipeline = gst_pipeline_new (NULL);
+  GstElement *src = gst_element_factory_make ("fakesrc", NULL);
+  GstElement *sink = gst_element_factory_make ("fakesink", NULL);
+  GstClock *clock = gst_test_clock_new ();
+  gboolean stream_lock_contended;
+  GstClockTime base_time;
+  gulong signal_id;
+  GThread *thread;
+
+  fail_unless (pipeline && src && sink);
+
+  gst_test_clock_set_time (GST_TEST_CLOCK (clock), 100 * GST_SECOND);
+  gst_pipeline_use_clock (GST_PIPELINE (pipeline), clock);
+  g_object_set (src, "is-live", TRUE, NULL);
+  g_object_set (sink, "async", FALSE, "sync", FALSE, NULL);
+  gst_bin_add_many (GST_BIN (pipeline), src, sink, NULL);
+  fail_unless (gst_element_link (src, sink));
+  fail_unless (gst_element_set_state (pipeline, GST_STATE_PLAYING) !=
+      GST_STATE_CHANGE_FAILURE);
+  fail_unless (gst_element_get_state (pipeline, NULL, NULL,
+          GST_CLOCK_TIME_NONE) != GST_STATE_CHANGE_FAILURE);
+  fail_unless_equals_uint64 (gst_element_get_base_time (pipeline),
+      100 * GST_SECOND);
+
+  data.pipeline = pipeline;
+  data.sink = sink;
+  data.sinkpad = gst_element_get_static_pad (sink, "sink");
+  data.reset_running_time = 10 * GST_SECOND;
+  g_mutex_init (&data.lock);
+  g_cond_init (&data.cond);
+
+  signal_id = g_signal_connect (pipeline, "do-latency",
+      G_CALLBACK (reset_time_do_latency), &data);
+  thread = g_thread_new ("reset-time", post_reset_time_with_stream_lock, 
&data);
+
+  g_mutex_lock (&data.lock);
+  while (!data.stream_locked) {
+    g_printerr ("Waiting for worker to acquire stream lock\n");
+    mark_point ();
+    g_cond_wait (&data.cond, &data.lock);
+  }
+  g_mutex_unlock (&data.lock);
+
+  GST_STATE_LOCK (pipeline);
+  stream_lock_contended = !GST_PAD_STREAM_TRYLOCK (data.sinkpad);
+  if (!stream_lock_contended)
+    GST_PAD_STREAM_UNLOCK (data.sinkpad);
+
+  g_mutex_lock (&data.lock);
+  data.post_reset_time = TRUE;
+  g_cond_broadcast (&data.cond);
+  while (!data.message_posted) {
+    g_printerr ("Waiting for worker to post RESET_TIME\n");
+    mark_point ();
+    g_cond_wait (&data.cond, &data.lock);
+  }
+  g_mutex_unlock (&data.lock);
+  GST_STATE_UNLOCK (pipeline);
+
+  g_thread_join (thread);
+  g_signal_handler_disconnect (pipeline, signal_id);
+  base_time = gst_element_get_base_time (pipeline);
+  gst_element_set_state (pipeline, GST_STATE_NULL);
+  gst_object_unref (data.sinkpad);
+  gst_object_unref (pipeline);
+  gst_object_unref (clock);
+  g_cond_clear (&data.cond);
+  g_mutex_clear (&data.lock);
+
+  fail_unless (data.stream_locked, "Worker did not acquire the stream lock");
+  fail_unless (stream_lock_contended,
+      "Stream lock was unexpectedly available to the state-change thread");
+  fail_unless (data.message_posted, "RESET_TIME message was not posted");
+  fail_unless_equals_uint64 (base_time, 90 * GST_SECOND);
+  fail_if (data.do_latency_called && data.state_lock_contended,
+      "RESET_TIME synchronously recalculated latency while another thread "
+      "held the pipeline state lock");
+}
+
+GST_END_TEST;
+
 GST_START_TEST (test_async_state_change_fake_ready)
 {
   GstPipeline *pipeline;
@@ -748,6 +899,7 @@
 
   suite_add_tcase (s, tc_chain);
   tcase_add_test (tc_chain, test_async_state_change_empty);
+  tcase_add_test (tc_chain, test_reset_time_during_state_change);
   tcase_add_test (tc_chain, test_async_state_change_fake_ready);
   tcase_add_test (tc_chain, test_async_state_change_fake);
   tcase_add_test (tc_chain, test_get_bus);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/gstreamer-1.28.6/tests/validate/simplest.validatetest 
new/gstreamer-1.28.7/tests/validate/simplest.validatetest
--- old/gstreamer-1.28.6/tests/validate/simplest.validatetest   2026-08-05 
13:59:39.000000000 +0200
+++ new/gstreamer-1.28.7/tests/validate/simplest.validatetest   2026-09-07 
21:11:13.000000000 +0200
@@ -1,12 +1,12 @@
 meta,
     handles-states=true,
     ignore-eos=true,
-    args = {
+    args={
         "fakesrc num-buffers=5 ! fakesink sync=true name=sink",
     },
-    configs = {
-        "core, fail-on-missing-plugin=true",
-        "$(validateflow), pad=sink:sink, buffers-checksum=true",
+    configs={
+        [core, fail-on-missing-plugin=true],
+        [validateflow, pad=sink:sink, buffers-checksum=true],
     }
 
 play
@@ -14,4 +14,3 @@
 crank-clock, repeat=5, expected-elapsed-time=0.0
 
 stop, on-message=eos
-

++++++ gstreamer.obsinfo ++++++
--- /var/tmp/diff_new_pack.Y57pUO/_old  2026-09-11 19:01:07.413098813 +0200
+++ /var/tmp/diff_new_pack.Y57pUO/_new  2026-09-11 19:01:07.421099147 +0200
@@ -1,5 +1,5 @@
 name: gstreamer
-version: 1.28.6
-mtime: 1785931179
-commit: 2d3e05cbdad68e47d645f548899b432dc9fb4473
+version: 1.28.7
+mtime: 1788808273
+commit: 070125524a8422e29d3b69a372ed4f62fd343ffa
 

Reply via email to