From fd0b1fd3bac7f8f80cc595d7f469ab62bea691a1 Mon Sep 17 00:00:00 2001
From: Apertis CI <devel@lists.apertis.org>
Date: Wed, 19 Mar 2025 10:56:33 +0000
Subject: [PATCH 1/4] Import Upstream version 1.26.0

---
 ChangeLog                                | 4738 ++++++++--------------
 NEWS                                     | 3488 ++++------------
 README.md                                |    2 +-
 RELEASE                                  |    6 +-
 cmake/FindGStreamer.cmake                |  456 +++
 cmake/meson.build                        |    9 +
 data/bash-completion/helpers/meson.build |    2 +-
 docs/gst-hotdoc-plugins-scanner.c        |   22 +-
 docs/gst-plugins-doc-cache-generator.py  |  260 +-
 docs/index.md                            |  338 --
 docs/libs/index.md                       |    1 -
 docs/meson.build                         |  193 +-
 docs/plugins/gst_plugins_cache.json      |  209 +-
 gst/glib-compat-private.h                |   20 +
 gst/gst.c                                |    7 +-
 gst/gst.h                                |    2 +
 gst/gst_private.h                        |   10 +-
 gst/gstbuffer.c                          |   35 +-
 gst/gstbufferlist.c                      |   14 +-
 gst/gstbufferpool.c                      |  180 +-
 gst/gstbufferpool.h                      |    3 +
 gst/gstbus.c                             |   35 +-
 gst/gstcaps.c                            |  414 +-
 gst/gstcaps.h                            |   36 +
 gst/gstcapsfeatures.c                    |  416 +-
 gst/gstcapsfeatures.h                    |   41 +-
 gst/gstclock.c                           |   71 +-
 gst/gstclock.h                           |   22 +-
 gst/gstcontext.c                         |    3 +-
 gst/gstdebugutils.c                      |   30 +-
 gst/gstdeviceprovider.c                  |   19 +-
 gst/gstdynamictypefactory.h              |    4 +
 gst/gstelement.c                         |   31 +-
 gst/gstevent.c                           |  323 +-
 gst/gstevent.h                           |    2 +-
 gst/gstidstr-private.h                   |  288 ++
 gst/gstidstr.c                           |  331 ++
 gst/gstidstr.h                           |  114 +
 gst/gstinfo.c                            |  128 +-
 gst/gstinfo.h                            |    7 +
 gst/gstiterator.c                        |   14 +-
 gst/gstmemory.c                          |    3 +
 gst/gstmessage.c                         |  735 ++--
 gst/gstmessage.h                         |   19 +
 gst/gstmeta.c                            |   70 +-
 gst/gstmeta.h                            |   28 +
 gst/gstpad.c                             |  136 +-
 gst/gstplugin.c                          |    4 +
 gst/gstpluginloader-win32.c              |    3 +-
 gst/gstpreset.c                          |    4 +-
 gst/gstpromise.c                         |    4 +-
 gst/gstquark.c                           |  100 -
 gst/gstquark.h                           |  243 --
 gst/gstquery.c                           |  441 +-
 gst/gstregistry.c                        |    8 +-
 gst/gststructure.c                       | 1463 ++++++-
 gst/gststructure.h                       |  186 +-
 gst/gstsystemclock.c                     |    4 +-
 gst/gsttaglist.c                         |   49 +-
 gst/gsttaskpool.c                        |    4 +-
 gst/gsttoc.c                             |    1 -
 gst/gsttracer.c                          |   59 +-
 gst/gsttracer.h                          |    6 +
 gst/gsttracerfactory.c                   |    1 +
 gst/gsttracerfactory.h                   |    1 +
 gst/gsttracerrecord.c                    |   24 +-
 gst/gsttracerutils.c                     |  185 +-
 gst/gsttracerutils.h                     |  151 +-
 gst/gsturi.c                             |    3 +-
 gst/gstutils.c                           |  144 +-
 gst/gstutils.h                           |    6 +
 gst/gstvalue.c                           |  280 +-
 gst/gstvecdeque.c                        |  996 +++++
 gst/gstvecdeque.h                        |  129 +
 gst/meson.build                          |   24 +-
 gst/parse/grammar.y.in                   |  231 +-
 gst/parse/types.h                        |   10 +
 gst/printf/vasnprintf.c                  |    2 +-
 gstreamer.doap                           |  112 +-
 libs/gst/base/base-prelude.h             |   12 +
 libs/gst/base/gstadapter.c               |   89 +-
 libs/gst/base/gstaggregator.c            |  102 +-
 libs/gst/base/gstaggregator.h            |    4 +
 libs/gst/base/gstbaseparse.c             |   25 +-
 libs/gst/base/gstbasesink.c              |    4 -
 libs/gst/base/gstbasesrc.c               |   20 +-
 libs/gst/base/gstcollectpads.c           |    8 +-
 libs/gst/base/gstdataqueue.c             |   26 +-
 libs/gst/base/gstqueuearray.c            |  588 +--
 libs/gst/base/gstqueuearray.h            |   54 +-
 libs/gst/base/gsttypefindhelper.c        |   10 +-
 libs/gst/base/meson.build                |   20 +-
 libs/gst/check/gstcheck.h                |   31 +
 libs/gst/check/libcheck/README.txt       |    2 +-
 libs/gst/check/meson.build               |   13 +-
 libs/gst/controller/meson.build          |   14 +-
 libs/gst/helpers/gst-plugin-scanner.c    |    2 +
 libs/gst/helpers/meson.build             |    6 +-
 libs/gst/helpers/ptp/main.rs             |   13 +-
 libs/gst/net/gstnetclientclock.c         |   21 +-
 libs/gst/net/gstptpclock.c               |   14 +-
 libs/gst/net/meson.build                 |   13 +-
 libs/meson.build                         |    2 +
 meson.build                              |   58 +-
 meson_options.txt                        |   24 +-
 plugins/elements/gstfakesrc.c            |    1 +
 plugins/elements/gstfdsrc.c              |   19 +
 plugins/elements/gstfilesrc.c            |    6 +-
 plugins/elements/gstoutputselector.c     |    2 +-
 plugins/elements/gstqueue.c              |  204 +-
 plugins/elements/gstqueue.h              |    5 +-
 plugins/elements/gstqueue2.c             |   18 +-
 plugins/elements/gstqueue2.h             |    2 +-
 plugins/elements/gsttee.c                |   13 +-
 plugins/elements/gsttypefindelement.c    |    2 +-
 plugins/elements/meson.build             |   37 +
 plugins/meson.build                      |    5 +-
 plugins/tracers/gstdots.c                |  291 ++
 plugins/tracers/gstlatency.c             |  197 +-
 plugins/tracers/gstlatency.h             |    7 +
 plugins/tracers/gstleaks.c               |  285 +-
 plugins/tracers/gstleaks.h               |   16 +-
 plugins/tracers/gstlog.c                 |  120 +-
 plugins/tracers/gstrusage.c              |   30 +-
 plugins/tracers/gststats.c               |    8 +
 plugins/tracers/gsttracers.c             |    5 +
 plugins/tracers/meson.build              |   49 +-
 po/be.po                                 |    6 +-
 po/cs.po                                 |    6 +-
 po/da.po                                 |    6 +-
 po/de.po                                 |    6 +-
 po/eo.po                                 |    6 +-
 po/eu.po                                 |   10 +-
 po/fr.po                                 |    6 +-
 po/gl.po                                 |    6 +-
 po/gstreamer-1.0.pot                     |  131 +-
 po/gstreamer.pot                         |  131 +-
 po/hr.po                                 |   98 +-
 po/id.po                                 |    6 +-
 po/lt.po                                 |    6 +-
 po/lv.po                                 |   23 +-
 po/pl.po                                 |    6 +-
 po/pt_BR.po                              |   14 +-
 po/ro.po                                 |    6 +-
 po/ru.po                                 |   23 +-
 po/sk.po                                 |    6 +-
 po/sq.po                                 |    6 +-
 po/uk.po                                 |   10 +-
 po/zh_CN.po                              |    6 +-
 tests/check/elements/filesink.c          |   10 +-
 tests/check/gst/gstbuffer.c              |    5 +-
 tests/check/gst/gstcaps.c                |  136 +-
 tests/check/gst/gstcapsfeatures.c        |    2 +-
 tests/check/gst/gstidstr-noinline.c      |   22 +
 tests/check/gst/gstidstr.c               |  208 +
 tests/check/gst/gstmessage.c             |   58 +
 tests/check/gst/gstpad.c                 |   80 +
 tests/check/gst/gststructure.c           |  146 +-
 tests/check/gst/gsturi.c                 |  107 +-
 tests/check/gst/gstutils.c               |    1 +
 tests/check/gst/gstvalue.c               |   65 +-
 tests/check/gst/gstvecdeque.c            |  639 +++
 tests/check/gstreamer.supp               |   28 +
 tests/check/libs/gstlibscpp.cc           |    4 +
 tests/check/libs/queuearray.c            |    4 +
 tests/check/meson.build                  |    3 +
 tests/validate/meson.build               |    4 +-
 tools/gst-inspect.c                      |   52 +-
 tools/gst-launch-1.0.1                   |  102 +-
 tools/meson.build                        |    2 +-
 170 files changed, 13325 insertions(+), 9567 deletions(-)
 create mode 100644 cmake/FindGStreamer.cmake
 create mode 100644 cmake/meson.build
 delete mode 100644 docs/index.md
 delete mode 100644 docs/libs/index.md
 create mode 100644 gst/gstidstr-private.h
 create mode 100644 gst/gstidstr.c
 create mode 100644 gst/gstidstr.h
 delete mode 100644 gst/gstquark.c
 delete mode 100644 gst/gstquark.h
 create mode 100644 gst/gstvecdeque.c
 create mode 100644 gst/gstvecdeque.h
 create mode 100644 plugins/tracers/gstdots.c
 create mode 100644 tests/check/gst/gstidstr-noinline.c
 create mode 100644 tests/check/gst/gstidstr.c
 create mode 100644 tests/check/gst/gstvecdeque.c

diff --git a/ChangeLog b/ChangeLog
index 8228fb4..026f2f2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,12 +1,370 @@
-=== release 1.24.12 ===
+=== release 1.26.0 ===
 
-2025-01-29 20:12:29 +0000  Tim-Philipp Müller <tim@centricular.com>
+2025-03-11 20:14:44 +0000  Tim-Philipp Müller <tim@centricular.com>
+
+	* NEWS:
+	* README.md:
+	* RELEASE:
+	* gstreamer.doap:
+	* meson.build:
+	  Release 1.26.0
+
+2025-02-12 17:10:30 +0000  L. E. Segovia <amy@centricular.com>
+
+	* cmake/FindGStreamer.cmake:
+	  cmake: Memoize include checks
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8478>
+
+2025-02-24 09:34:09 -0300  Thibault Saunier <tsaunier@igalia.com>
+
+	* docs/gst-plugins-doc-cache-generator.py:
+	  docs: Add a way to specify extra_assets path for plugins doc
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8545>
+
+2025-02-24 12:17:55 -0300  Thibault Saunier <tsaunier@igalia.com>
+
+	* plugins/tracers/gstdots.c:
+	  tracer: dots: Check that `pipeline-snapshot::dots-viewer-ws-url` exists
+	  It is a very new property and the tracer should still be usable if that
+	  property doesn't exist
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8547>
+
+2025-02-23 23:52:57 +0000  Tim-Philipp Müller <tim@centricular.com>
+
+	* meson.build:
+	  Back to development after 1.25.90
+
+=== release 1.25.90 ===
+
+2025-02-23 23:44:10 +0000  Tim-Philipp Müller <tim@centricular.com>
+
+	* NEWS:
+	* RELEASE:
+	* gstreamer.doap:
+	* meson.build:
+	  Release 1.25.90
+
+2025-02-23 16:55:40 +0000  Tim-Philipp Müller <tim@centricular.com>
+
+	* po/be.po:
+	* po/cs.po:
+	* po/da.po:
+	* po/de.po:
+	* po/eo.po:
+	* po/eu.po:
+	* po/fr.po:
+	* po/gl.po:
+	* po/hr.po:
+	* po/id.po:
+	* po/lt.po:
+	* po/lv.po:
+	* po/pl.po:
+	* po/pt_BR.po:
+	* po/ro.po:
+	* po/ru.po:
+	* po/sk.po:
+	* po/sq.po:
+	* po/uk.po:
+	* po/zh_CN.po:
+	  gstreamer: update translations
+
+2025-02-19 11:26:36 -0300  Thibault Saunier <tsaunier@igalia.com>
+
+	* plugins/tracers/gstdots.c:
+	  tracers: dots: Simplify the way we check dot file to be removed
+	  Fixing removing dot files that are in the root directory.
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8521>
+
+2024-11-06 17:53:51 -0300  Thibault Saunier <tsaunier@igalia.com>
+
+	* gst/gstmemory.c:
+	* gst/gsttracerutils.c:
+	* gst/gsttracerutils.h:
+	  tracer: Add memory init/free hooks
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8510>
+
+2025-02-19 10:53:34 +0100  Guillaume Desmottes <guillaume.desmottes@onestream.live>
+
+	* gst/gstvalue.c:
+	  gstvalue: fix leak in gst_value_deserialize_bytes()
+	  The GValue needs to take ownership.
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8515>
+
+2025-02-19 10:52:09 +0100  Guillaume Desmottes <guillaume.desmottes@onestream.live>
+
+	* gst/gstvalue.c:
+	  gstvalue: fix leak in gst_value_deserialize_g_date_time()
+	  gst_date_time_to_g_date_time() does not take ownership.
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8515>
+
+2025-02-17 19:16:32 +0200  Sebastian Dröge <sebastian@centricular.com>
+
+	* gst/gstiterator.c:
+	* gst/gstmeta.c:
+	* gst/gsttracer.c:
+	* gst/gstutils.h:
+	  gstreamer: Fix various gobject-introspection warnings
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8501>
+
+2025-02-17 13:22:29 +0200  Sebastian Dröge <sebastian@centricular.com>
+
+	* gst/gstbuffer.c:
+	  buffer: Mark gst_buffer_extract() size parameter as in-parameter
+	  Otherwise it's considered an out-parameter because of its relationship with
+	  the dest array pointer.
+	  Suggested-by: Sergey Bugaev <bugaevc@gmail.com>
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8494>
+
+2025-02-13 09:54:43 -0500  Xavier Claessens <xclaessens@netflix.com>
+
+	* gst/gststructure.c:
+	* gst/gstvalue.c:
+	* tests/check/gst/gststructure.c:
+	  gststructure: Fix deserialization of GStrv
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8438>
+
+2025-02-10 11:54:18 -0500  Xavier Claessens <xclaessens@netflix.com>
+
+	* gst/gstvalue.c:
+	* tests/check/gst/gstvalue.c:
+	  gstvalue: Add (de)serialize of G_TYPE_STRV
+	  This allows setting strv properties from gst-launch-1.0, such as uris in
+	  uriplaylistbin.
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8438>
+
+2025-02-11 22:34:30 -0300  Thibault Saunier <tsaunier@igalia.com>
+
+	* gst/gst.c:
+	  gst: Allow tracers to set the GST_DEBUG_DUMP_DOT_DIR
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7999>
+
+2025-02-11 22:33:03 -0300  Thibault Saunier <tsaunier@igalia.com>
+
+	* docs/plugins/gst_plugins_cache.json:
+	* plugins/tracers/gstdots.c:
+	* plugins/tracers/gsttracers.c:
+	* plugins/tracers/meson.build:
+	  tracers: Add a `dots` tracer which is meant to be used with `gst-dots-viewer`
+	  See documentation
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7999>
+
+2025-01-09 20:23:08 -0300  Thibault Saunier <tsaunier@igalia.com>
+
+	* gst/gstdebugutils.c:
+	  core: debugutils: Write dot files atomically
+	  Replace fopen/fputs with g_file_set_contents() to ensure dot files are written
+	  atomically. This prevents tools like gst-dots-viewer from reading partially
+	  written files when watching the dot folder.
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7999>
+
+2025-02-05 20:25:48 +0100  Alicia Boya García <aboya@igalia.com>
+
+	* gst/parse/grammar.y.in:
+	* gst/parse/types.h:
+	  gstreamer: parse: Log bus error messages during construction
+	  Suppose you invoke gst-launch with this invalid pipeline:
+	  ```
+	  $ gst-launch-1.0  videotestsrc num-buffers=10 ! x264enc name=enc ! mux.sink_0 \
+	  mpegtsmux name=mux ! fakesink
+	  0:00:00.018631594 351169      0xb523090 ERROR           GST_PIPELINE
+	  subprojects/gstreamer/gst/parse/grammar.y:1151:gst_parse_perform_link:
+	  could not link enc to mux
+	  WARNING: erroneous pipeline: could not link enc to mux
+	  ```
+	  The error message you get is not very helpful. This is a pity, because
+	  this is where the error comes from:
+	  ```c
+	  static GstPad *
+	  gst_base_ts_mux_request_new_pad (GstElement * element, GstPadTemplate * templ,
+	  const gchar * name, const GstCaps * caps)
+	  { // [...]
+	  GST_ELEMENT_ERROR (element, STREAM, MUX,
+	  ("Invalid Elementary stream PID (0x%02u < 0x40)", pid), (NULL));
+	  return NULL;
+	  ```
+	  mpegtsmux posted an error with an explanation of why the linking failed.
+	  However, since the error ocurred within gst_parse_launchv(), gst-launch
+	  could not have set a bus handler, and the error message got discarded.
+	  This patch attempts to make gst-launch more user-friendly by setting a
+	  temporary bus handler during early bin construction to catch error
+	  messages like this.
+	  The errors are logged as ERROR level in the GST_PIPELINE category.
+	  However, this is not enough, as GST_LEVEL_DEFAULT defaults to
+	  GST_LEVEL_NONE in releases. In other words, outside of the dev
+	  environment, GStreamer won't print ERROR logs by default.
+	  To make sure the errors can reach users of packaged versions of
+	  GStreamer, a new AtomicRcBox-based struct is added: reason_receiver_t.
+	  graph_t owns a reference to reason_receiver_t and so does the temporary
+	  bus handler.
+	  When the temporary bus handler receives an error message, the `reason`
+	  field of `reason_receiver_t` is filled with the error message.
+	  Later, when SET_ERROR() is called as a consequence of the operation that
+	  posted the error having returned failure, the reason message is
+	  extracted and added to the GError message.
+	  This is how the resulting error would look in the example from above:
+	  WARNING: erroneous pipeline: could not link enc to mux --
+	  GstMpegTsMux <mux> posted an error message: Invalid Elementary
+	  stream PID (0x00 < 0x40)
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8417>
+
+2025-02-11 00:03:20 +0100  Alexander Slobodeniuk <aslobodeniuk@fluendo.com>
+
+	* gst/gsttracerrecord.c:
+	  tracerrecord: fix missing GObject vtable chainups
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8452>
+
+2025-02-11 00:03:08 +0100  Alexander Slobodeniuk <aslobodeniuk@fluendo.com>
+
+	* gst/gsttracer.c:
+	  tracer: fix missing GObject vtable chainups
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8452>
+
+2025-02-06 11:40:26 +0100  Alexander Slobodeniuk <aslobodeniuk@fluendo.com>
+
+	* plugins/tracers/gstlatency.c:
+	* plugins/tracers/gstlog.c:
+	* plugins/tracers/gststats.c:
+	  tracers: fix chaining up GObject's constructed virtual method
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8416>
+
+2025-02-05 21:02:16 +0100  Alexander Slobodeniuk <aslobodeniuk@fluendo.com>
+
+	* libs/gst/base/gstaggregator.c:
+	  aggregator: fix chaining up in GObject "constructed" virtual methods
+	  This doesn't always bring visible issue, but is formally incorrect:
+	  not chaining up means that the code doesn't trigger GstObject and
+	  GstElement "constructed" implementations.
+	  In particular both GstElement's and GstObject's classes in
+	  "constructed" may sign up this object for tracing and
+	  GstObject's class sets GST_OBJECT_FLAG_CONSTRUCTED flag.
+	  If we don't chain up none of this is going to be executed.
+	  For example, before the fix leaks tracer couldn't detect this leak:
+	  ```c
+	  int main (int argc, char **argv) {
+	  g_setenv ("GST_TRACERS", "leaks(name=all-leaks)", TRUE);
+	  g_setenv ("GST_DEBUG", "GST_TRACER:7", TRUE);
+	  g_setenv ("G_DEBUG", "fatal-warnings", TRUE);
+	  gst_init (&argc, &argv);
+	  // leak audiomixer: doesn't detect because it's based on the aggregator
+	  gst_element_factory_make ("audiomixer", "Jerry");
+	  // leak videoconvert: this one is detected fine because it's not
+	  // based on the aggregator
+	  //gst_element_factory_make ("videoconvert", "Tom");
+	  gst_deinit ();
+	  return 0;
+	  }
+	  // $ cc tst.c $(pkg-config --cflags --libs gstreamer-1.0) -o tst && ./tst
+	  ```
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8416>
+
+2025-02-09 17:47:32 +0000  Tim-Philipp Müller <tim@centricular.com>
+
+	* meson.build:
+	  Back to development after 1.25.50
+
+=== release 1.25.50 ===
+
+2025-02-09 17:35:17 +0000  Tim-Philipp Müller <tim@centricular.com>
 
 	* NEWS:
 	* RELEASE:
 	* gstreamer.doap:
 	* meson.build:
-	  Release 1.24.12
+	  Release 1.25.50
+
+2025-02-07 05:10:39 +0530  Nirbheek Chauhan <nirbheek@centricular.com>
+
+	* docs/gst-plugins-doc-cache-generator.py:
+	  docs: Fix opencv pkgconfig file name
+	  Most distros ship OpenCV 4.x, and the pkgconfig file for that is
+	  `opencv4`. OpenCV 3.x uses `opencv`, and Fedora ships both files with
+	  OpenCV 4.x for backwards compat.
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8403>
+
+2025-02-05 17:42:31 +0100  Alicia Boya García <aboya@igalia.com>
+
+	* plugins/tracers/gstlog.c:
+	  log tracer: Use strings instead of integer codes
+	  In many places in the log tracer %d was used for data types we have
+	  string format functions. This is especially problematic when the data
+	  type is not immediately obvious to the reader (e.g. gboolean vs
+	  GstFlowRet, where TRUE==1 but GST_FLOW_OK==0) or the values are not easy
+	  to memorize (GST_STATE_CHANGE_PLAYING_TO_PAUSED==35).
+	  This patch replaces all the integer codes with string representations so
+	  that the logs are easier to understand by humans.
+	  The formatting of GstBufferList by the log tracer is also updated to use
+	  GST_PTR_FORMAT instead of a raw pointer, so the user can see the
+	  timestamps, size and number of buffers.
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8414>
+
+2025-02-05 18:53:33 +0100  Alicia Boya García <aboya@igalia.com>
+
+	* gst/parse/grammar.y.in:
+	  gstreamer: parse: Fix log in gst_parse_perform_link
+	  Suppose you're trying to debug why this pipeline doesn't work:
+	  ```
+	  $ GST_DEBUG=GST_PIPELINE:DEBUG gst-launch-1.0 \
+	  videotestsrc num-buffers=10 ! x264enc name=enc ! mux.sink_0  \
+	  mpegtsmux name=mux ! fakesink
+	  ```
+	  You will encounter this line in the logs:
+	  > gst_parse_perform_link: linking some pad of GstX264Enc named enc to
+	  > pad  mux of GstMpegTsMux named mux (0/1) with caps "(NULL)"
+	  It would seem that the element name is being read as a pad name as well,
+	  and that made me wonder if the parsing was not working. However, it was
+	  just a bug in the code printing that log. This patch fixes that bug.
+	  Note that it is possible to specify more than one pad name for each side
+	  of the link. For instance, the following is a valid pipeline that will
+	  remux the video and audio of an MP4 file into MKV:
+	  ```
+	  $ GST_DEBUG=GST_PIPELINE:DEBUG gst-launch \
+	  filesrc location=input.mp4 ! qtdemux name=demux  \
+	  multiqueue name=mq  \
+	  matroskamux name=mux ! filesink location=output.mkv  \
+	  demux.video_0,audio_0 ! mq.sink_0,sink_1  \
+	  mq.src_0,src_1 ! mux.video_0,audio_0
+	  ```
+	  The new logging accomodates this by using a new utility function to join
+	  strings of pad name lists instead of `PRETTY_PAD_NAME_FMT` (which only
+	  supports one pad name). For example:
+	  > linking pads {video_0, audio_0} of GstQTDemux named demux to pads
+	  > {sink_0, sink_1} of GstMultiQueue named mq with caps "(NULL)"
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8415>
+
+2025-02-04 15:52:08 +0100  Patricia Muscalu <patricia@axis.com>
+
+	* gst/gsttracerutils.h:
+	  tracers: Fix build problem when tracer hooks are disabled
+	  "undefined reference to `GST_TRACER_PAD_SEND_EVENT_PRE'
+	  undefined reference to `GST_TRACER_PAD_SEND_EVENT_POST'"
+	  errors are generated when trying to build GStreamer with
+	  the following build configuration:
+	  meson setup -Dgstreamer:tracer_hooks=false build
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8419>
+
+2025-01-30 14:57:15 +0100  Corentin Damman <c.damman@intopix.com>
+
+	* gst/gstpluginloader-win32.c:
+	  pluginloader-win32: create no window
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8387>
+
+2023-08-15 21:22:19 -0300  L. E. Segovia <amy@centricular.com>
+
+	* libs/gst/check/libcheck/README.txt:
+	  gst-indent: build our own indent tool and make it available in the devenv
+	  No more formatting mismatches owing to different GNU indent
+	  versions shipped by different distro versions.
+	  See #340
+	  Co-authored-by: L. E. Segovia <amy@centricular.com>
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5192>
+
+2025-01-28 23:08:01 +0800  Zhao, Gang <gang.zhao.42@gmail.com>
+
+	* docs/plugins/gst_plugins_cache.json:
+	* plugins/elements/gstfdsrc.c:
+	  fdsrc: Add property is-live
+	  Fixed #4184
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8372>
 
 2025-01-27 07:45:22 -0700  Jordan Yelloz <jordan.yelloz@collabora.com>
 
@@ -16,14 +374,77 @@
 	  Otherwise, if the underlying iterator returns GST_ITERATOR_ERROR, the filtered
 	  iterator will crash.
 	  With this change, the filtered iterator propagates the error back to the caller.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8370>
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8367>
+
+2025-01-27 13:58:50 +0100  Alicia Boya García <aboya@igalia.com>
+
+	* plugins/tracers/gstlog.c:
+	  docs: Fix log category names in the log tracer
+	  The documentation was incorrectly referring to `GST_QUERY` and `GST_BIN`
+	  as GstDebug category names.  These two don't follow the pattern of the
+	  rest, and instead are named `query` and `bin` respectively.
+	  This can be verified from the source code of the _do_init macro in the
+	  same gstlog.c file, and from gstbin.c and gstquery.c calls to
+	  GST_DEBUG_CATEGORY_INIT().
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8365>
+
+2025-01-27 14:44:02 +0100  Alicia Boya García <aboya@igalia.com>
+
+	* plugins/tracers/gstlog.c:
+	  tracers: log: Fix wrong argument in do_chain_buffer_pre()
+	  The third argument of the pad-chain-pre and pad-chain-post hooks are of type GstBuffer* and GstBufferList* respectively.
+	  However, when I added do_chain_buffer_pre() and do_chain_buffer_post()
+	  to gstlog.c I accidentally make them take GstFlowReturn -- almost
+	  certainly as an artifact from duplicating the code of the _post()
+	  variants, leading to erroneous log lines like this:
+	  ```
+	  do_chain_buffer_pre:<vp9parse0:sink> 0:00:01.615378540, pad=<vp9parse0:sink>, res=-1073639680
+	  ```
+	  This patch fixes that.
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8366>
+
+2025-01-20 19:42:02 +0100  Alicia Boya García <aboya@igalia.com>
+
+	* gst/gstpad.c:
+	* gst/gsttracerutils.c:
+	* gst/gsttracerutils.h:
+	* plugins/tracers/gstlog.c:
+	  tracing: add hooks for gst_pad_send_event_unchecked()
+	  Similar to de30de865cd, this allows to follow the flow of events as they
+	  arrive to a pad rather than only when they are pushed to a peer.
+	  The hook is installed in gst_pad_send_event_unchecked() instead of
+	  gst_pad_send_event() because the latter is often omitted: that is the
+	  case especifically in gst_pad_push_event_unchecked(), where most event
+	  propagation occurs.
+	  This patch also makes use of the new hooks in the log tracer to log the
+	  begining and end of the send_event processing.
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8330>
+
+2025-01-22 18:30:07 +0100  Alicia Boya García <aboya@igalia.com>
+
+	* gst/gstpad.c:
+	* gst/gsttracerutils.h:
+	  tracers: signal pad-push-event when pushing sticky events
+	  Previously, the tracer pad-push-event was only signalled on
+	  gst_pad_push_event().  However, the sticky event handling code in
+	  GStreamer uses gst_pad_push_event_unchecked() instead, which meant those
+	  events were not logged.
+	  This patch extends the definition of the pad-push-event tracer to cover
+	  both calls to gst_pad_push_event() and any direct calls to
+	  gst_pad_push_event_unchecked() that skip the former inside GstPad
+	  private code.
+	  gst_pad_push_event_unchecked() returns GstFlowReturn instead of
+	  gboolean like gst_pad_push_event(). To maintain API compatibility, the
+	  GstFlowReturn is converted to gboolean.
+	  Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/4182
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8342>
 
 2025-01-22 12:34:31 +0200  Sebastian Dröge <sebastian@centricular.com>
 
 	* libs/gst/net/gstnetclientclock.c:
 	  netclientclock: Don't stop searching the clock cache when the first corrupted clock is found
 	  The clock we're looking for might be working fine and be available afterwards.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8364>
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8334>
 
 2025-01-22 12:32:24 +0200  Sebastian Dröge <sebastian@centricular.com>
 
@@ -34,19 +455,45 @@
 	  Not storing it allows the application to simply create a new one at a later time
 	  and have starting it retried.
 	  Also signal to the application that such a clock is not synced.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8364>
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8334>
 
 2025-01-23 19:48:28 +0000  Rares Branici <rares.branici@senstar.com>
 
 	* gst/gstpluginloader-win32.c:
 	  pluginloader-win32: create no window
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8357>
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8354>
 
 2025-01-23 16:52:30 +0100  Silvio Lazzeretti <silviola@amazon.it>
 
 	* gst/gstpluginloader-win32.c:
 	  gstpluginloader-win32: fix use after free in find_helper_bin_location
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8356>
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8352>
+
+2025-01-20 18:48:11 +0100  Alicia Boya García <aboya@igalia.com>
+
+	* plugins/tracers/gstlog.c:
+	  tracers: log: Log buffer-chain
+	  Commit de30de865cd added a hook for pad-chain-{pre,post} and
+	  pad-chain-list-{pre,post}. As explained in that commit, hooking the
+	  chain is helpful because it allows you to hook to buffer propagation in
+	  both srcpads (pad-push) and sinkpads (pad-chain).
+	  This patch uses the new hooks to log pad-chain in the log tracer.
+	  Before, only pad-push was logged, so you could only follow the flow of
+	  buffers through the srcpads.
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8329>
+
+2025-01-20 13:26:18 -0300  Thibault Saunier <tsaunier@igalia.com>
+
+	* docs/gst-plugins-doc-cache-generator.py:
+	  docs: doc-cache-generator: Pass the full os.environ so `pkg-config` can be found
+	  We want to pass the `PATH` from the current environment.
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8327>
+
+2025-01-20 13:25:45 -0300  Thibault Saunier <tsaunier@igalia.com>
+
+	* docs/gst-plugins-doc-cache-generator.py:
+	  docs: Make autopep8 happy for gst-plugins-doc-cache-generator.py
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8327>
 
 2025-01-20 10:48:04 +0100  Guillaume Desmottes <guillaume.desmottes@onestream.live>
 
@@ -59,13 +506,30 @@
 	  I'm not totally sure when this happens as I debugged this from a post
 	  mortem crash but returning a generic error here seems the safe thing to
 	  do.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8331>
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8321>
 
 2025-01-20 10:47:34 +0100  Guillaume Desmottes <guillaume.desmottes@onestream.live>
 
 	* plugins/elements/gstsparsefile.c:
 	  sparsefile: fix typo in doc
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8331>
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8321>
+
+2025-01-20 13:23:50 +0100  Mathieu Duponchelle <mathieu@centricular.com>
+
+	* docs/meson.build:
+	  docs: explicitly list gir files as depends for generating configs
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8324>
+
+2025-01-20 13:20:17 +0100  Mathieu Duponchelle <mathieu@centricular.com>
+
+	* docs/gst-plugins-doc-cache-generator.py:
+	  docs: only add configuration files to sitemap once generated
+	  The generation script can fail to generate a configuration for the four
+	  libraries where the documentation is not generated from gir, as it needs
+	  to run pkg-config.
+	  Only add the path to the configuration file to the sitemap once it has
+	  successfully been dumped.
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8324>
 
 2025-01-15 03:36:07 +0530  Nirbheek Chauhan <nirbheek@centricular.com>
 
@@ -97,157 +561,523 @@
 	  AudioToolboxCore!__AudioComponentInstanceNew_block_invoke (Unknown Source:0)
 	  AudioToolboxCore!Synchronously (Unknown Source:0)
 	  ```
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8323>
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8320>
 
-2024-08-20 00:40:06 +0900  Andrew Yooeun Chun <aychun00@gmail.com>
+2025-01-15 17:36:00 +0100  Mathieu Duponchelle <mathieu@centricular.com>
 
-	* libs/gst/base/gstbasetransform.c:
-	  basetransform: fix incorrect logging inside gst_base_transform_query_caps
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8289>
+	* docs/gst-plugins-doc-cache-generator.py:
+	* docs/meson.build:
+	* gst/meson.build:
+	* libs/gst/base/meson.build:
+	* libs/gst/check/meson.build:
+	* libs/gst/controller/meson.build:
+	* libs/gst/net/meson.build:
+	* libs/meson.build:
+	  docs: generate hotdoc configs for libraries with our helper script
+	  With this patch, configure time is identical no matter whether doc is
+	  enabled or not.
+	  The configuration files also now contain explicitly-listed sources with
+	  no wildcards.
+	  For the four libraries where hotdoc needs to use clang to generate the
+	  documentation (as opposed to the rest of the libraries where hotdoc uses
+	  the gir), the script will call pkg-config to determine the appropriate
+	  C flags.
+	  This means a side effect of this patch is that pkg-config files are now
+	  generated for the gstadaptivedemux and gstopencv libraries.
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8312>
+
+2025-01-17 16:51:22 +0100  Mathieu Duponchelle <mathieu@centricular.com>
 
-2024-09-19 14:06:51 -0700  Alan Coopersmith <alan.coopersmith@oracle.com>
+	* meson.build:
+	  meson: bump minimum version to 1.4 in every subprojects
+	  36c01d05797ad9c7778939c54870f979bdcbba1f bumped to 1.4 for gst-devtools
+	  and the root project, but we usually keep those in sync everywhere.
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8312>
 
-	* tests/misc/meson.build:
-	  gstreamer: netclock-replay: use gst_c_args when building
-	  Need HAVE_CONFIG_H to avoid build failure on Solaris 11.4 with gcc 14.1:
-	  ../subprojects/gstreamer/tests/misc/../../libs/gst/net/gstnetutils.c:71:7:
-	  error: implicit declaration of function ‘setsockopt’
-	  [-Wimplicit-function-declaration]
-	  71 |   if (setsockopt (fd, IPPROTO_IP, IP_TOS, &tos, sizeof (tos)) < 0) {
-	  |       ^~~~~~~~~~
-	  Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8264>
+2025-01-15 17:35:21 +0100  Mathieu Duponchelle <mathieu@centricular.com>
+
+	* docs/libs/index.md:
+	  docs: remove useless index.md in libs/ subdirectory
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8312>
+
+2025-01-15 17:16:27 +0100  Mathieu Duponchelle <mathieu@centricular.com>
+
+	* docs/index.md:
+	  docs: remove unused index.md file
+	  It is a bit hard to track its origin as `git log --follow` leads all the
+	  way to a 2001 Wim commit of a TODO file, but it was not used in the
+	  documentation and the contained information appears in other places.
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8312>
+
+2025-01-08 15:01:32 -0300  Thibault Saunier <tsaunier@igalia.com>
 
-2025-01-06 20:11:58 +0000  Tim-Philipp Müller <tim@centricular.com>
+	* gst/gstutils.c:
+	* gst/gstutils.h:
+	  gst: utils: Add a multiply_int64 variant
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8262>
+
+2025-01-14 15:00:43 +0000  Tim-Philipp Müller <tim@centricular.com>
 
 	* meson.build:
-	  Back to development after 1.24.11
+	  Back to development after 1.25.1
 
-=== release 1.24.11 ===
+=== release 1.25.1 ===
 
-2025-01-06 19:48:08 +0000  Tim-Philipp Müller <tim@centricular.com>
+2025-01-14 14:52:48 +0000  Tim-Philipp Müller <tim@centricular.com>
 
 	* NEWS:
 	* RELEASE:
 	* gstreamer.doap:
 	* meson.build:
-	  Release 1.24.11
+	  Release 1.25.1
 
-2024-12-03 23:39:54 +0000  Tim-Philipp Müller <tim@centricular.com>
+2025-01-13 18:10:31 +0100  Mathieu Duponchelle <mathieu@centricular.com>
 
-	* meson.build:
-	  Back to development after 1.24.10
+	* docs/meson.build:
+	* plugins/meson.build:
+	* plugins/tracers/meson.build:
+	  docs: port plugins to explicit sources
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8273>
 
-=== release 1.24.10 ===
+2025-01-03 15:44:11 +0100  Edward Hervey <edward@centricular.com>
 
-2024-12-03 23:29:07 +0000  Tim-Philipp Müller <tim@centricular.com>
+	* plugins/elements/gstfilesrc.c:
+	  filesrc: Properly handle lseek return value
+	  On windows we use _lseeki64 which returns a guint64.
+	  The only error code lseek and _lseeki64 return is a casted -1, therefore just do
+	  that to handle all platforms
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8229>
+
+2025-01-03 15:22:04 +0100  Edward Hervey <edward@centricular.com>
+
+	* tests/check/gst/gstbuffer.c:
+	  test: Remove always-true assertion
+	  The offset is not deterministic
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8229>
+
+2025-01-03 14:30:55 +0100  Edward Hervey <edward@centricular.com>
+
+	* tests/check/elements/filesink.c:
+	  test: Avoid type-limit issue
+	  ```
+	  ../subprojects/gstreamer/tests/check/elements/filesink.c: In function ‘test_seeking’:
+	  ../subprojects/gstreamer/tests/check/elements/filesink.c:92:23: warning: comparison of unsigned expression in ‘< 0’ is
+	  always false [-Wtype-limits]
+	  92 |         for (i = 0; i < num_bytes; ++i)                                 \
+	  |                       ^
+	  ../subprojects/gstreamer/tests/check/elements/filesink.c:266:3: note: in expansion of macro ‘PUSH_BYTES’
+	  266 |   PUSH_BYTES (0);
+	  |   ^~~~~~~~~~
+	  ```
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8229>
+
+2025-01-02 12:14:37 +0100  Edward Hervey <edward@centricular.com>
 
-	* NEWS:
-	* RELEASE:
-	* gstreamer.doap:
 	* meson.build:
-	  Release 1.24.10
+	  gstreamer: Add more warning flags
+	  See https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/4123
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8229>
 
-2024-08-30 13:21:30 +0200  Stéphane Cerveau <scerveau@igalia.com>
+2025-01-02 12:14:13 +0100  Edward Hervey <edward@centricular.com>
 
-	* gst/gstutils.c:
+	* libs/gst/net/gstptpclock.c:
+	  gstptpclock: Fix GST_STIME_ARGS usage
+	  It requires a signed value
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8229>
+
+2025-01-02 12:13:42 +0100  Edward Hervey <edward@centricular.com>
+
+	* gst/printf/vasnprintf.c:
+	* plugins/elements/gstfakesrc.c:
+	* plugins/elements/gstoutputselector.c:
+	* plugins/elements/gstqueue2.c:
+	* plugins/elements/gsttypefindelement.c:
+	* tests/check/gst/gstpad.c:
 	* tests/check/gst/gstutils.c:
-	  utils: improve gst_util_ceil_log2
-	  According to the following comparison of algorithms, the value
-	  for 0 and 1 was giving an incorrect result.
-	  https://gist.github.com/ceyusa/6061b33ac109a68bcd222f6919968c9a
-	  More information here:
-	  https://github.com/rofrol/codeforces/blob/master/ceil_log2.c
-	  Use a different algorithm which offers better result and keep the
-	  performance.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7905>
+	  gstreamer: Make switch passthrough as such
+	  vasnprintf requires special handling since the following 'case' is #ifdef'ed
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8229>
 
-2024-09-26 22:07:22 +0300  Sebastian Dröge <sebastian@centricular.com>
+2024-08-20 00:40:06 +0900  Andrew Yooeun Chun <aychun00@gmail.com>
 
-	* gst/gstallocator.c:
-	  allocator: Avoid integer overflow when allocating sysmem
-	  Thanks to Antonio Morales for finding and reporting the issue.
-	  Fixes GHSL-2024-166
-	  Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/3851
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8044>
+	* libs/gst/base/gstbasetransform.c:
+	  basetransform: fix incorrect logging inside gst_base_transform_query_caps
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7381>
 
-2024-11-28 16:06:17 +0200  Sebastian Dröge <sebastian@centricular.com>
+2025-01-06 18:28:18 +0100  Mathieu Duponchelle <mathieu@centricular.com>
 
-	* gst/gstsystemclock.c:
-	  systemclock: Don't keep the clock entry locked while getting the time from the clock
-	  gst_clock_get_time() will take the clock mutex, which would then result in a lock
-	  order violation and possible deadlocks. If both mutexes are to be locked, the
-	  clock must always be locked first.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8019>
+	* docs/gst-plugins-doc-cache-generator.py:
+	* docs/meson.build:
+	  doc: store path to dynamic library in plugin configuration
+	  This can then be used by the pre-commit hook to avoid rebuilding
+	  complete plugin caches to check a change, thus minimizing the potential
+	  diff and making analysis of completely-unrelated cache diffs much less
+	  likely.
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8231>
 
-2024-11-28 15:49:24 +0200  Sebastian Dröge <sebastian@centricular.com>
+2025-01-03 18:49:39 +0100  Mathieu Duponchelle <mathieu@centricular.com>
 
-	* gst/gstsystemclock.c:
-	  systemclock: Get rid of conditional unlocking of the clock entries
-	  At every point it is known whether the entry needs to be unlocked or not.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8019>
+	* docs/gst-plugins-doc-cache-generator.py:
+	* docs/meson.build:
+	  docs: start using custom_target instead of run_command for sitemap
+	  Intead of passing around the output of the config generator program,
+	  which consists of paths joined by a separator we can have the generator
+	  simply produce an extra file containing those paths.
+	  This commit only implements the new approach for the core plugins, as
+	  this was needed to avoid spurious meson rebuilds when the pre-commit
+	  hook regenerates the core plugins_cache.
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8231>
 
-2024-11-28 15:43:08 +0200  Sebastian Dröge <sebastian@centricular.com>
+2025-01-02 14:29:48 +0100  Mathieu Duponchelle <mathieu@centricular.com>
 
-	* gst/gstsystemclock.c:
-	  systemclock: Remove confusing conditional unlock
-	  At this point the entry is always locked and needs to be unlocked.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8019>
+	* docs/meson.build:
+	  docs: list doc sources explicitly for GStreamer core
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8231>
 
-2024-11-28 15:25:47 +0200  Sebastian Dröge <sebastian@centricular.com>
+2025-01-02 14:07:00 +0100  Mathieu Duponchelle <mathieu@centricular.com>
 
-	* gst/gstsystemclock.c:
-	  systemclock: Use a flag while waiting for the async thread to start
-	  Otherwise there can be spurious wakeups.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8019>
+	* docs/gst-plugins-doc-cache-generator.py:
+	* docs/meson.build:
+	* meson.build:
+	* plugins/elements/meson.build:
+	* plugins/meson.build:
+	* plugins/tracers/meson.build:
+	  docs: start listing sources explicitly in hotdoc configuration files
+	  A JSON configuration file is generated for core plugins, which maps
+	  plugin names with sources to parse for docstrings.
+	  The file is then opened by the configuration generator script, which
+	  will now favor explicitly listed files to (usually wildcarded) paths
+	  passed on its command line.
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8231>
+
+2025-01-06 20:29:00 +0100  Ruben Gonzalez <rgonzalez@fluendo.com>
 
-2024-10-09 13:35:33 -0400  Alicia Boya García <aboya@igalia.com>
+	* gst/gsttracerutils.c:
+	  tracers: Fix issue in the BC layer added in refactor to simplify params handling
+	  Issue added in refactor done in commit 5e18499372, which includes a
+	  logic to not break the backward compatibility. Issue found with Rust
+	  pcap-writer tracer, fixes https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/-/issues/644
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8248>
+
+2025-01-03 14:16:25 +0200  Sebastian Dröge <sebastian@centricular.com>
+
+	* gst/gstmessage.c:
+	  message: Remove nullable annotation from gst_message_writable_details()
+	  This function can never return NULL as the details are created for the message
+	  if there are none yet.
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8235>
+
+2024-12-31 10:50:58 +0200  Sebastian Dröge <sebastian@centricular.com>
 
 	* gst/gstpad.c:
-	  pad: Never push sticky events in response to a FLUSH_STOP
-	  FLUSH_STOP is meant to clear the flushing state of pads and elements
-	  downstream, not to process data. Hence, a FLUSH_STOP should not
-	  propagate sticky events. This is also consistent with how flushes are a
-	  special case for probes.
-	  Currently this is almost always the case, since a FLUSH_STOP is
-	  __usually__ preceded by a FLUSH_START, and events (sticky or not) are
-	  discarded while a pad has the FLUSHING flag active (set by FLUSH_START).
-	  However, it is currently assumed that a FLUSH_STOP not preceded by a
-	  FLUSH_START is correct behavior, and this will occur while autoplugging
-	  pipelines are constructed. This leaves us with an unhandled edge case!
-	  This patch explicitly disables sending sticky events when pushing a
-	  FLUSH_STOP, instead of relying on the flushing flag of the pad, which
-	  will break in the edge case of a FLUSH_STOP not preceded by a
-	  FLUSH_START.
-	  If sticky events are propagated in response to a FLUSH_STOP, the
-	  flushing thread can end up deadlocked in blocking code of a downstream
-	  pad, such as a blocking probe. Instead, those events should be
-	  propagated from the streaming thread of the pad when handling a
-	  non-flushing synchronized event or buffer.
-	  This fixes a deadlock found in WebKit with playbin3 when seeks occur
-	  before preroll, where the seeking thread ended up stuck in the blocking
-	  probe of playsink:
-	  https://github.com/WebPlatformForEmbedded/WPEWebKit/issues/1367
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8003>
+	  pad: Reset not-linked last flow return on reconfigure events
+	  The pad might actually be linked now and we'd only find out by actually pushing
+	  a buffer downstream again.
+	  The last flow return is used by GstFlowCombiner to detect if all pads are not
+	  linked, and not resetting this when re-linking creates a race condition when
+	  switching between pads where all pads are temporarily considered not linked.
+	  Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/3836
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8224>
+
+2024-12-16 11:41:40 +0200  Sebastian Dröge <sebastian@centricular.com>
+
+	* libs/gst/base/gstbaseparse.c:
+	  baseparse: Add bitrate tags to empty taglists too
+	  It's unclear why empty taglists should be handled in a special way. If the
+	  subclass or upstream did not provide any tags at all then we can still provide
+	  bitrate tags at least.
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8157>
+
+2024-12-18 17:11:33 -0300  Thibault Saunier <tsaunier@igalia.com>
+
+	* data/bash-completion/helpers/meson.build:
+	* docs/meson.build:
+	* gst/meson.build:
+	* libs/gst/base/meson.build:
+	* libs/gst/check/meson.build:
+	* libs/gst/controller/meson.build:
+	* libs/gst/helpers/meson.build:
+	* libs/gst/net/meson.build:
+	* meson.build:
+	* tests/validate/meson.build:
+	* tools/meson.build:
+	  meson: Give the same name for api_version in all modules
+	  There were 2 version of it, apiversion and api_version, I chose the one
+	  with most occurencies: `api_version`
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8178>
+
+2024-12-12 10:50:30 +0200  Sebastian Dröge <sebastian@centricular.com>
+
+	* gst/gstpad.c:
+	  pad: Only remove TAG events on STREAM_START if the stream-id actually changes
+	  Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/4097
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8135>
+
+2024-07-09 11:42:03 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+	* gst/gstinfo.c:
+	  info: Use an RW lock to protect the log functions and their list
+	  Previously the code tried to be thread-safe by only locking when modifying the
+	  list and leaking the old list, but this was not sufficient. When removing a log
+	  function, its user_data would be freed but this log function and its user_data
+	  might afterwards still be used during logging which then could lead to memory
+	  corruption.
+	  To avoid that, use an RW lock: get a write lock whenever modifying the list and
+	  get a read lock whenever only using the list of log functions for logging.
+	  Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/3660
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7151>
+
+2024-12-10 12:52:33 +0000  Tim-Philipp Müller <tim@centricular.com>
+
+	* meson.build:
+	  meson: unset GST_TRACERS for g-ir-scanner to avoid warnings
+	  People might have GST_TRACERS=leaks set in their environment
+	  by default, which will now trigger criticals during the build
+	  when calling g-ir-scanner, because we unset GST_PLUGIN_SYSTEM_PATH
+	  so that the scanner doesn't load any plugins.
+	  Fixes #4093
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8121>
+
+2024-12-09 18:32:34 -0300  Thibault Saunier <tsaunier@igalia.com>
+
+	* plugins/tracers/gstlatency.h:
+	* plugins/tracers/gstleaks.h:
+	* plugins/tracers/gststats.c:
+	  doc: Add some missing doc strings
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8086>
+
+2024-12-06 22:49:05 -0300  Thibault Saunier <tsaunier@igalia.com>
+
+	* plugins/tracers/gstleaks.c:
+	  tracers: leak: Fix some docstrings
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8086>
+
+2024-12-06 11:38:26 -0300  Thibault Saunier <tsaunier@igalia.com>
+
+	* docs/gst-hotdoc-plugins-scanner.c:
+	* docs/plugins/gst_plugins_cache.json:
+	  doc: Add tracer objects information
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8086>
+
+2024-12-06 11:20:43 -0300  Thibault Saunier <tsaunier@igalia.com>
+
+	* plugins/tracers/gstlatency.c:
+	  tracers: latency: Port to using property based configuration
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8086>
+
+2024-12-06 11:13:52 -0300  Thibault Saunier <tsaunier@igalia.com>
+
+	* tools/gst-inspect.c:
+	  gst-inspect: Document tracer properties
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8086>
+
+2024-12-06 09:17:50 -0300  Thibault Saunier <tsaunier@igalia.com>
+
+	* plugins/tracers/gstrusage.c:
+	  tracers: rusage: Mark as set_use_structure_params
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8086>
+
+2024-12-06 09:16:57 -0300  Thibault Saunier <tsaunier@igalia.com>
+
+	* libs/gst/helpers/gst-plugin-scanner.c:
+	  gst-plugin-scanner: Do not create tracers when inspecting plugins
+	  Ensuring that GST_TRACERS is not set in that process
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8086>
+
+2024-12-05 18:57:10 -0300  Thibault Saunier <tsaunier@igalia.com>
+
+	* plugins/tracers/gstleaks.c:
+	* plugins/tracers/gstleaks.h:
+	  leaks: Port to using object property based parameters
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8086>
+
+2024-12-05 18:52:31 -0300  Thibault Saunier <tsaunier@igalia.com>
+
+	* gst/gsttracer.c:
+	* gst/gsttracer.h:
+	* gst/gsttracerfactory.c:
+	* gst/gsttracerfactory.h:
+	* gst/gsttracerutils.c:
+	  tracers: Simplify params handling using GstStructure and object properties
+	  Instead of having each tracer implement its own parameter parsing,
+	  centralize the handling in the tracer subsystem using GstStructure.
+	  This simplifies tracer implementations and provides a consistent way
+	  to handle properties.
+	  It also allows for much better documentation by forcing tracer object
+	  to expose properties
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8086>
+
+2024-12-09 22:12:21 +0900  Seungha Yang <seungha@centricular.com>
+
+	* gst/gstvecdeque.c:
+	  vecdeque: Fix documentation of push_tail_struct()
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8111>
+
+2024-11-22 21:23:10 +0800  Qian Hu (胡骞) <qian.hu@mediatek.com>
+
+	* gst/gstvalue.c:
+	  gstvalue: fix crash in transform allocation params to string
+	  when gst_buffer_pool_config_set_allocator (config, alloc, NULL);
+	  gst_structure_to_string or GST_DEBUG (pool, "config %" GST_PTR_FORMAT,
+	  config) will crash. this patch fix that
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7943>
+
+2024-09-26 22:07:22 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+	* gst/gstallocator.c:
+	  allocator: Avoid integer overflow when allocating sysmem
+	  Thanks to Antonio Morales for finding and reporting the issue.
+	  Fixes GHSL-2024-166
+	  Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/3851
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8032>
+
+2024-11-28 16:06:17 +0200  Sebastian Dröge <sebastian@centricular.com>
+
+	* gst/gstsystemclock.c:
+	  systemclock: Don't keep the clock entry locked while getting the time from the clock
+	  gst_clock_get_time() will take the clock mutex, which would then result in a lock
+	  order violation and possible deadlocks. If both mutexes are to be locked, the
+	  clock must always be locked first.
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7994>
+
+2024-11-28 15:49:24 +0200  Sebastian Dröge <sebastian@centricular.com>
+
+	* gst/gstsystemclock.c:
+	  systemclock: Get rid of conditional unlocking of the clock entries
+	  At every point it is known whether the entry needs to be unlocked or not.
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7994>
+
+2024-11-28 15:43:08 +0200  Sebastian Dröge <sebastian@centricular.com>
+
+	* gst/gstsystemclock.c:
+	  systemclock: Remove confusing conditional unlock
+	  At this point the entry is always locked and needs to be unlocked.
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7994>
+
+2024-11-28 15:25:47 +0200  Sebastian Dröge <sebastian@centricular.com>
+
+	* gst/gstsystemclock.c:
+	  systemclock: Use a flag while waiting for the async thread to start
+	  Otherwise there can be spurious wakeups.
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7994>
 
 2024-11-27 11:19:02 +0100  wbartel <wilhelm.bartel@streamonkey.de>
 
 	* gst/gstdebugutils.c:
 	  gstreamer: prefix debug dot node names to prevent splitting
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7998>
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7979>
 
 2024-11-25 16:28:51 +0100  wbartel <wilhelm.bartel@streamonkey.de>
 
 	* plugins/tracers/gstleaks.c:
 	  tracers: unlock leaks tracer if already tracking
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7960>
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7954>
+
+2024-11-20 15:02:19 +0800  He Junyan <junyan.he@intel.com>
+
+	* gst/gstutils.c:
+	* gst/gstutils.h:
+	  utils: Add gst_util_floor_log2 helper function
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5003>
+
+2024-11-20 12:24:34 +0000  L. E. Segovia <amy@amyspark.me>
+
+	* cmake/FindGStreamer.cmake:
+	  cmake: Add Android libvulkan to the ignored system libraries
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7861>
+
+2024-08-19 13:50:48 +0800  Qian Hu (胡骞) <qian.hu@mediatek.com>
+
+	* gst/gstmeta.c:
+	* gst/gstmeta.h:
+	* plugins/elements/gsttee.c:
+	  meta: add aggregation function for allocation meta api params
+	  since tee do allocation query for each downstream element, and
+	  get allocation query params from them. this function will aggregate
+	  all params, and propose it for upstream element of tee
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7201>
+
+2024-11-15 11:02:20 +0100  Albert Sjolund <alberts@axis.com>
+
+	* gst/gstpad.c:
+	* tests/check/gst/gstpad.c:
+	  gstpad: specialize gst_pad_chain_list_default
+	  In the case where the bufferlist is writable, send the
+	  buffers immediately without adding to the refcount. This
+	  allows writable buffers to maintain their writability, even
+	  without implementing a chain_list function on the element.
+	  Adds a test to verify this property, where a writable list
+	  maintains refcount 1, but a readonly list increases it.
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7894>
 
 2024-11-18 08:47:12 +0100  Robert Rosengren <robertr@axis.com>
 
 	* gst/gstdeviceprovider.c:
 	  gstdeviceprovider: fix leaking hidden providers
 	  Free list of hidden providers upon stop and dispose.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7915>
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7912>
+
+2024-11-13 16:00:25 +1100  Matthew Waters <matthew@centricular.com>
+
+	* gst/gstvalue.c:
+	  value: silence a maybe-unitialized warning
+	  gstvalue.c:376:8: error: ‘s_val’ may be used uninitialized [-Werror=maybe-uninitialized]
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7875>
+
+2024-11-15 11:46:14 -0300  Thibault Saunier <tsaunier@igalia.com>
+
+	* meson.build:
+	  meson: Bump minimum version to 1.3
+	  Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/4025
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7899>
+
+2024-08-30 13:21:30 +0200  Stéphane Cerveau <scerveau@igalia.com>
+
+	* gst/gstutils.c:
+	* tests/check/gst/gstutils.c:
+	  utils: improve gst_util_ceil_log2
+	  According to the following comparison of algorithms, the value
+	  for 0 and 1 was giving an incorrect result.
+	  https://gist.github.com/ceyusa/6061b33ac109a68bcd222f6919968c9a
+	  More information here:
+	  https://github.com/rofrol/codeforces/blob/master/ceil_log2.c
+	  Use a different algorithm which offers better result and keep the
+	  performance.
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7429>
+
+2024-11-11 12:23:22 +0200  Sebastian Dröge <sebastian@centricular.com>
+
+	* gst/gstidstr.c:
+	  idstr: Fix docs of set_static_str_with_len()
+	  The passed string must be NUL-terminated because otherwise a copy would be
+	  necessary to make it NUL-terminated, which defeats the whole purpose of the
+	  set_static() functions.
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7863>
+
+2024-11-10 11:44:57 -0300  Thibault Saunier <tsaunier@igalia.com>
+
+	* gst/meson.build:
+	  meson: gst: Make `GST_FULL_STATIC_COMPILATION` a static only arg
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7874>
+
+2018-01-29 19:46:26 +0100  Alicia Boya García <aboya@igalia.com>
+
+	* libs/gst/base/gstadapter.c:
+	  adapter: Improve documentation for gst_adapter_available()
+	  When I first read the documentation of gst_adapter_available() and
+	  gst_adapter_available_fast() I got quite confused as it seemed that
+	  both performed the same purpose but one was slower than the other.
+	  I shared it with other people and found they also arrived at the same
+	  wrong conclusion.
+	  Hopefully this patch will make the actual purpose clearer.
+	  Fixes https://gitlab.freedesktop.org/gstreamer/gst-docs/-/issues/12
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7859>
+
+2024-11-07 20:06:37 +0000  Tim-Philipp Müller <tim@centricular.com>
+
+	* tools/gst-launch-1.0.1:
+	  gst-launch-1.0: update man page a little
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7859>
 
 2024-11-07 15:44:25 +0530  Taruntej Kanakamalla <taruntej@asymptotic.io>
 
@@ -261,7 +1091,7 @@
 	  This is similar to the fix in the glib for multicast join/leave
 	  operation on macOS
 	  https://gitlab.gnome.org/GNOME/glib/-/merge_requests/4333
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7864>
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7851>
 
 2024-11-03 17:36:22 +0000  Tim-Philipp Müller <tim@centricular.com>
 
@@ -310,22 +1140,33 @@
 	* po/zh_CN.po:
 	* po/zh_TW.po:
 	  gstreamer: update translations
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7820>
-
-2024-10-30 20:40:12 +0000  Tim-Philipp Müller <tim@centricular.com>
-
-	* meson.build:
-	  Back to development after 1.24.9
-
-=== release 1.24.9 ===
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7819>
 
-2024-10-30 20:33:30 +0000  Tim-Philipp Müller <tim@centricular.com>
+2024-05-20 11:46:13 -0300  L. E. Segovia <amy@centricular.com>
 
-	* NEWS:
-	* RELEASE:
-	* gstreamer.doap:
+	* cmake/FindGStreamer.cmake:
+	* cmake/meson.build:
 	* meson.build:
-	  Release 1.24.9
+	  cmake: Add Find Module to support Android and iOS consumers
+	  This commit adds a Find Module implementing the necessary logic to link
+	  against GStreamer, while implementing some extra bits to enhance the
+	  compatibility.
+	  The first addition is the `mobile` target, which implements the
+	  monolithic `gstreamer_android` library, and which here gains
+	  compatibility with Apple's operating systems.
+	  The second addition is the handling of the basic GStreamer libraries as
+	  `--whole-archive` when statically linked, which was ported from the
+	  ndk-build project in Cerbero. This is not easy to do, as CMake suffers
+	  from several issues that impede its proper usage of pkg-config:
+	  - It cannot differentiate between system/compiler specific libraries
+	  e.g. `-lm`, `-ldl`, but especially `-framework Cocoa`.
+	  - It does not support `--whole-archive` natively until 3.27
+	  - It attempts to reorder flags blindly by separating them with spaces,
+	  thus requiring the use of `-Wl,` wrapping or (in the case of Apple
+	  frameworks) manual framework lookup
+	  The third addition is the port of the Fontconfig and ca-certificates
+	  bundling logic.
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6881>
 
 2024-10-28 10:41:08 -0300  Thibault Saunier <tsaunier@igalia.com>
 
@@ -335,7 +1176,7 @@
 	  If we end up processing the query from the streaming thread, it means that it was
 	  a serialized query, and the query is being waited to be processed on the sinkpad
 	  streaming thread, thread which owns the reference.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7796>
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7767>
 
 2024-10-25 19:12:17 +0200  Mathieu Duponchelle <mathieu@centricular.com>
 
@@ -344,7 +1185,74 @@
 	  When force-live is true, we don't want to wait for a first buffer
 	  to select a start time.
 	  Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/1783
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7778>
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7752>
+
+2024-09-09 19:11:33 -0300  Thibault Saunier <tsaunier@igalia.com>
+
+	* docs/plugins/gst_plugins_cache.json:
+	* plugins/elements/gstqueue.c:
+	* plugins/elements/gstqueue.h:
+	  queue: Send the `notify` signals on queue level changes
+	  This is documented as:
+	  > you can query how many buffers are queued by reading the
+	  > #gstqueue:current-level-buffers property. you can track changes
+	  > by connecting to the notify::current-level-buffers signal (which
+	  > like all signals will be emitted from the streaming thread). the same
+	  > applies to the #gstqueue:current-level-time and
+	  > #gstqueue:current-level-bytes properties.
+	  ... but was not implemented.
+	  This also respects the `notify::silent` property for the notify signals
+	  to be less intrusive.
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7486>
+
+2024-09-09 19:00:57 -0300  Thibault Saunier <tsaunier@igalia.com>
+
+	* plugins/elements/gstqueue.c:
+	  queue: Cleanup properties are installed caching the pspecs in an array
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7486>
+
+2024-10-25 17:41:46 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+	* gst/gstbuffer.c:
+	  buffer: Don't copy reference timestamp meta if the destination buffer already has the same
+	  GstRtpBaseDepayload and other places already had such de-duplication code, so
+	  it's probably better to solve this at the root.
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7747>
+
+2024-07-26 11:47:00 +0200  Edward Hervey <edward@centricular.com>
+
+	* tests/check/gstreamer.supp:
+	  gstreamer: Make dlopen leak suppression more generic
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7455>
+
+2024-06-27 22:17:56 +0300  Jordan Petridis <jordan@centricular.com>
+
+	* tests/check/gstreamer.supp:
+	  gstreamer: add duktape suppression
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7455>
+
+2024-10-24 09:17:54 +0200  Edward Hervey <edward@centricular.com>
+
+	* gst/gstbuffer.c:
+	* gst/gstbufferlist.c:
+	* gst/gstcaps.c:
+	* gst/gstelement.c:
+	* gst/gstiterator.c:
+	* gst/gstmeta.c:
+	* gst/gstpad.c:
+	* gst/gstpromise.c:
+	* gst/gstregistry.c:
+	* gst/gststructure.c:
+	* gst/gsttaglist.c:
+	* gst/gsttaskpool.c:
+	* gst/gstutils.c:
+	* libs/gst/base/gstcollectpads.c:
+	  all: Fix closure annotations
+	  This was misused almost everywhere.
+	  See
+	  https://gi.readthedocs.io/en/latest/annotations/giannotations.html#support-for-gobject-closures
+	  and: https://www.bassi.io/articles/2023/02/20/bindable-api-2023/
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7725>
 
 2024-10-23 16:14:45 +0200  Mathieu Duponchelle <mathieu@centricular.com>
 
@@ -355,119 +1263,480 @@
 	  live to TRUE on the latency query.
 	  Fix this by or'ing force_live into the result.
 	  Also improve debug
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7723>
-
-2024-10-01 12:26:40 +0000  Corentin Damman <c.damman@intopix.com>
-
-	* gst/gstmacos.m:
-	  macos: Fix race conditions
-	  This commit fixes two issues:
-	  - The event must be posted *after* calling stop, otherwise a race condition can occur and the app never stops
-	  - isFinishedLaunching and applicationDidFinishLaunching are not always synchronized, causing sometimes
-	  a deadlock on the g_cond_wait never catching the g_cond_signal
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7608>
-
-2024-09-16 08:48:47 -0400  Arun Raghavan <arun@asymptotic.io>
-
-	* gst/parse/grammar.y.in:
-	  gstreamer: parse: Use child proxy for deferred property setting
-	  We use that mechanism for the non-deferred path, and this makes sure we are
-	  consistent for deferred set too.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7561>
-
-2024-09-15 06:39:40 -0400  Arun Raghavan <arun@asymptotic.io>
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7718>
 
-	* gst/parse/grammar.y.in:
-	  gstreamer: parse: Minor whitespace fixups
-	  Mostly replacing some tabs with spaces.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7561>
+2024-10-14 14:46:53 +0200  Robert Rosengren <robertr@axis.com>
 
-2024-09-13 13:55:27 -0400  Arun Raghavan <arun@asymptotic.io>
+	* libs/gst/net/gstnetclientclock.c:
+	  Revert "gstnetclockclient: signal lost sync if remote time resets"
+	  This reverts commit 779e715b6cee4f7793c43a0e78c6106ab66f1032.
+	  Since the introduced corrupt clock state for when discovering a time
+	  server restart, this resulted in previous similar check as done in
+	  this patch became ignored/jumped over (in case of the corrupt state
+	  has been noticed).
+	  Reference: df41d11a7d7f844e593a10f6a6a0858333fbf7ec
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7664>
 
-	* gst/parse/grammar.y.in:
-	  gstreamer: parse: Make sure children are bins before recursing in
-	  A deferred set of the form parentbin::childelement::pad works in the
-	  non-deferred property setting path, but the deferred path assumes that all
-	  non-root non-leaf children specify bins. We already have a bin check on the
-	  root, so let's add one for other non-leaves to avoid a critical.
-	  Fixes: https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/3806
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7561>
+2024-10-14 15:06:11 +0200  Robert Rosengren <robertr@axis.com>
 
-2024-09-19 12:12:53 +0200  Tim-Philipp Müller <tim@centricular.com>
+	* libs/gst/net/gstnetclientclock.c:
+	  netclientclock: send clock sync signal upon corrupted
+	  Clients that already gotten a signal for synced clock, may rely on
+	  getting the same when marked as corrupted to take appropriate action. So
+	  send clock signal indicating no sync at identified corrupted state.
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7664>
 
-	* meson.build:
-	  Back to development after 1.24.8
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7549>
+2024-10-17 20:21:53 +0300  Sebastian Dröge <sebastian@centricular.com>
 
-=== release 1.24.8 ===
+	* libs/gst/helpers/ptp/main.rs:
+	  ptp-helper: Silence deprecation warning
+	  The new API is only available since Rust 1.81.
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7678>
 
-2024-09-19 12:01:21 +0200  Tim-Philipp Müller <tim@centricular.com>
+2024-10-10 11:19:26 -0400  François Laignel <francois@centricular.com>
 
-	* NEWS:
-	* RELEASE:
-	* gstreamer.doap:
-	* meson.build:
-	  Release 1.24.8
+	* gst/gstcaps.c:
+	* gst/gstcaps.h:
+	* gst/gststructure.c:
+	* gst/gststructure.h:
+	  gst: add more GstIdStr functions to Caps & Structure
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7644>
 
-2024-09-14 04:01:42 +0200  Peter Kjellerstedt <pkj@axis.com>
+2024-10-09 15:45:34 -0400  François Laignel <francois@centricular.com>
 
-	* gst/gstmeta.h:
-	  meta: Add missing include of gststructure.h
-	  This avoids the following error when only including gstmeta.h:
-	  /usr/include/gstreamer-1.0/gst/gstmeta.h:146:3: error: unknown type
-	  name 'GstStructure'
-	  146 |   GstStructure *structure;
-	  |   ^~~~~~~~~~~~
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7525>
+	* gst/gstcaps.c:
+	* gst/gstcaps.h:
+	  gst: hamonise recent Caps function names with Structure counterparts
+	  These functions were introduced as part of the GstIdStr MR:
+	  https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7432
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7644>
 
-2024-09-13 10:58:27 +0300  Sebastian Dröge <sebastian@centricular.com>
+2024-10-14 22:08:19 +0200  Jakub Adam <jakub.adam@collabora.com>
 
 	* libs/gst/base/gstaggregator.c:
-	  aggregator: Immediately return NONE from simple_get_next_time() on non-TIME segments
-	  Otherwise this gives critical warnings.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7514>
+	  aggregator: Fix handling NEED_DATA return from update_src_caps()
+	  Since GST_AGGREGATOR_FLOW_NEED_DATA == GST_FLOW_CUSTOM_ERROR == -100,
+	  in order to print the right debug message, we have to check that
+	  condition first before comparing ret with GST_FLOW_OK.
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7663>
 
-2024-09-10 16:03:05 -0400  Arun Raghavan <arun@asymptotic.io>
+2024-10-09 13:35:33 -0400  Alicia Boya García <aboya@igalia.com>
 
 	* gst/gstpad.c:
-	  pad: Check data NULL-ness when probes are stopped
-	  We were correctly handling this for buffers, but not events and queries.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7506>
-
-2024-08-26 19:13:11 +0300  Sebastian Dröge <sebastian@centricular.com>
-
-	* gst/gstutils.c:
-	  clock: Fix calculation for number of bits needed to store a 64 bit value
-	  It was using log2(n) but what actually is needed is log2(n) + 1. Also add a
-	  fast-path that uses __builtin_clzll() on gcc/clang.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7431>
-
-2024-08-23 15:56:41 +0300  Sebastian Dröge <sebastian@centricular.com>
-
-	* gst/gstutils.c:
-	* tests/check/gst/gstutils.c:
-	  clock: Fix unchecked overflows in linear regression code
+	  pad: Never push sticky events in response to a FLUSH_STOP
+	  FLUSH_STOP is meant to clear the flushing state of pads and elements
+	  downstream, not to process data. Hence, a FLUSH_STOP should not
+	  propagate sticky events. This is also consistent with how flushes are a
+	  special case for probes.
+	  Currently this is almost always the case, since a FLUSH_STOP is
+	  __usually__ preceded by a FLUSH_START, and events (sticky or not) are
+	  discarded while a pad has the FLUSHING flag active (set by FLUSH_START).
+	  However, it is currently assumed that a FLUSH_STOP not preceded by a
+	  FLUSH_START is correct behavior, and this will occur while autoplugging
+	  pipelines are constructed. This leaves us with an unhandled edge case!
+	  This patch explicitly disables sending sticky events when pushing a
+	  FLUSH_STOP, instead of relying on the flushing flag of the pad, which
+	  will break in the edge case of a FLUSH_STOP not preceded by a
+	  FLUSH_START.
+	  If sticky events are propagated in response to a FLUSH_STOP, the
+	  flushing thread can end up deadlocked in blocking code of a downstream
+	  pad, such as a blocking probe. Instead, those events should be
+	  propagated from the streaming thread of the pad when handling a
+	  non-flushing synchronized event or buffer.
+	  This fixes a deadlock found in WebKit with playbin3 when seeks occur
+	  before preroll, where the seeking thread ended up stuck in the blocking
+	  probe of playsink:
+	  https://github.com/WebPlatformForEmbedded/WPEWebKit/issues/1367
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7632>
+
+2024-10-10 08:53:19 -0400  Guillaume Desmottes <guillaume.desmottes@onestream.live>
+
+	* tools/gst-inspect.c:
+	  inspect: display element flags
+	  I wanted to check if an element had the SINK flag and realized it was
+	  not displayed in gst-inspect.
+	  The clock flags were already reported as part of the "clocking
+	  capabilities" info but best to have them explicitly listed here as well.
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7641>
+
+2024-10-12 19:10:46 -0300  L. E. Segovia <amy@centricular.com>
+
+	* meson.build:
+	  meson: Undefine any WINVER and _WIN32_WINNT entries before redefining them
+	  Fixes Cerbero build with MinGW GCC 14, where specifying -DWINVER=0x0601 -DWINVER=0x0A00 is a hard -Werror.
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7658>
+
+2024-10-04 11:19:46 +0200  François Laignel <francois@centricular.com>
+
+	* gst/gststructure.c:
+	* gst/gststructure.h:
+	  gst: structure: add more GstIdStr methods
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7613>
+
+2024-10-03 19:56:06 +0200  François Laignel <francois@centricular.com>
+
+	* gst/gststructure.c:
+	  gst: structure: fix some GstIdStr documentation
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7613>
+
+2024-10-01 12:26:40 +0000  Corentin Damman <c.damman@intopix.com>
+
+	* gst/gstmacos.m:
+	  macos: Fix race conditions
+	  This commit fixes two issues:
+	  - The event must be posted *after* calling stop, otherwise a race condition can occur and the app never stops
+	  - isFinishedLaunching and applicationDidFinishLaunching are not always synchronized, causing sometimes
+	  a deadlock on the g_cond_wait never catching the g_cond_signal
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7593>
+
+2024-09-20 21:44:40 -0400  Daniel Morin <daniel.morin@collabora.com>
+
+	* tests/check/gst/gstcaps.c:
+	  test: Add more nested caps-in-caps (and likes)
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7572>
+
+2024-09-22 19:09:32 -0400  Daniel Morin <daniel.morin@collabora.com>
+
+	* gst/gstvalue.c:
+	  value: Fix nested caps intersection
+	  Without this change intersection operand containing caps-in-caps need
+	  to be equal for the intersection to work.
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7572>
+
+2024-09-30 23:07:40 +0900  Seungha Yang <seungha@centricular.com>
+
+	* gst/gstcapsfeatures.c:
+	* gst/gststructure.c:
+	  structure,capsfeatures: Fix MSVC build warnings
+	  Fixing warning "warning C4068: unknown pragma 'GCC'"
+	  Use portable GLib macro instead
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7589>
+
+2024-09-03 12:47:07 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+	* gst/gstcaps.c:
+	* gst/gstcaps.h:
+	  gst: caps: Add API for creating caps / setting caps fields from static strings
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7432>
+
+2024-09-02 14:22:52 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+	* gst/gst.c:
+	* gst/gst_private.h:
+	* gst/gstbufferpool.c:
+	* gst/gstcontext.c:
+	* gst/gstdeviceprovider.c:
+	* gst/gstelement.c:
+	* gst/gstinfo.c:
+	* gst/gstmeta.c:
+	* gst/gstplugin.c:
+	* gst/gstquark.c:
+	* gst/gstquark.h:
+	* gst/gsttoc.c:
+	* gst/gstutils.c:
+	* gst/gstvalue.c:
+	* gst/meson.build:
+	  gst: Remove gstquark.c / gstquark.h
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7432>
+
+2024-09-03 12:16:19 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+	* tests/check/gst/gstcaps.c:
+	* tests/check/gst/gstcapsfeatures.c:
+	* tests/check/gst/gstvalue.c:
+	  common: Use more efficient versions of GstCapsFeatures API where possible
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7432>
+
+2024-08-30 18:49:44 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+	* gst/gstcapsfeatures.c:
+	* gst/gstcapsfeatures.h:
+	  gst: capsfeatures: Use GstIdStr for caps features
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7432>
+
+2024-08-29 20:09:52 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+	* docs/gst-hotdoc-plugins-scanner.c:
+	* gst/gstbufferpool.c:
+	* gst/gstcaps.c:
+	* gst/gstdebugutils.c:
+	* gst/gstdeviceprovider.c:
+	* gst/gstelement.c:
+	* gst/gstevent.c:
+	* gst/gstmessage.c:
+	* gst/gstquery.c:
+	* gst/gsttaglist.c:
+	* gst/gsttracerrecord.c:
+	* gst/gstvalue.c:
+	* libs/gst/base/gstbaseparse.c:
+	* plugins/tracers/gstlatency.c:
+	* tests/check/gst/gstcaps.c:
+	* tests/check/gst/gststructure.c:
+	* tools/gst-inspect.c:
+	  common: Stop using GQuark-based GstStructure field name API
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7432>
+
+2024-08-29 20:07:13 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+	* gst/gst_private.h:
+	* gst/gststructure.c:
+	* gst/gststructure.h:
+	* gst/gsttracerrecord.c:
+	  gst: structure: Use GstIdStr for structure field names
+	  And add corresponding API with GstIdStr parameters, static string parameters and
+	  deprecate the old GQuark based API.
+	  Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/3567
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7432>
+
+2024-08-09 10:41:57 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+	* gst/gstbufferpool.c:
+	* gst/gstcaps.c:
+	* gst/gstcontext.c:
+	* gst/gstevent.c:
+	* gst/gstevent.h:
+	* gst/gstinfo.c:
+	* gst/gstmessage.c:
+	* gst/gstpad.c:
+	* gst/gstquark.c:
+	* gst/gstquery.c:
+	* gst/gstvalue.c:
+	* plugins/tracers/gstlatency.c:
+	  common: Stop using GQuark-based GstStructure name API
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7432>
+
+2024-08-09 10:41:45 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+	* gst/gststructure.c:
+	* gst/gststructure.h:
+	* gst/gsttaglist.c:
+	  gst: structure: Use GstIdStr for structure names
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7432>
+
+2024-05-23 18:32:51 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+	* gst/gst.h:
+	* gst/gstidstr-private.h:
+	* gst/gstidstr.c:
+	* gst/gstidstr.h:
+	* gst/meson.build:
+	* tests/check/gst/gstidstr-noinline.c:
+	* tests/check/gst/gstidstr.c:
+	* tests/check/meson.build:
+	  gst: Add GstIdStr for holding structure names and field names
+	  This is an efficient string storage for short strings without heap allocations,
+	  and falling back to the heap for bigger allocations. Almost all structure fields
+	  and structure names in use nowadays are short enough to not require a heap
+	  allocation.
+	  As structure names and fields are sometimes dynamically created, storing them in
+	  a GQuark can create a memory leak and potentially a DoS attack by continously
+	  triggering creating of new quarks.
+	  Thanks to Tim for coming up with the name!
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7432>
+
+2024-07-05 19:40:35 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+	* gst/gstevent.c:
+	* gst/gstinfo.c:
+	* gst/gsttracerrecord.c:
+	  gst: structure: Stop using private structure name quark field
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7432>
+
+2024-09-16 08:48:47 -0400  Arun Raghavan <arun@asymptotic.io>
+
+	* gst/parse/grammar.y.in:
+	  gstreamer: parse: Use child proxy for deferred property setting
+	  We use that mechanism for the non-deferred path, and this makes sure we are
+	  consistent for deferred set too.
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7519>
+
+2024-09-15 06:39:40 -0400  Arun Raghavan <arun@asymptotic.io>
+
+	* gst/parse/grammar.y.in:
+	  gstreamer: parse: Minor whitespace fixups
+	  Mostly replacing some tabs with spaces.
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7519>
+
+2024-09-13 13:55:27 -0400  Arun Raghavan <arun@asymptotic.io>
+
+	* gst/parse/grammar.y.in:
+	  gstreamer: parse: Make sure children are bins before recursing in
+	  A deferred set of the form parentbin::childelement::pad works in the
+	  non-deferred property setting path, but the deferred path assumes that all
+	  non-root non-leaf children specify bins. We already have a bin check on the
+	  root, so let's add one for other non-leaves to avoid a critical.
+	  Fixes: https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/3806
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7519>
+
+2024-09-18 10:23:31 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+	* gst/gstdynamictypefactory.h:
+	  dynamictypefactory: Fix name of the class cast macro
+	  And deprecate the old name.
+	  Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/3814
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7541>
+
+2024-09-19 14:06:51 -0700  Alan Coopersmith <alan.coopersmith@oracle.com>
+
+	* tests/misc/meson.build:
+	  gstreamer: netclock-replay: use gst_c_args when building
+	  Need HAVE_CONFIG_H to avoid build failure on Solaris 11.4 with gcc 14.1:
+	  ../subprojects/gstreamer/tests/misc/../../libs/gst/net/gstnetutils.c:71:7:
+	  error: implicit declaration of function ‘setsockopt’
+	  [-Wimplicit-function-declaration]
+	  71 |   if (setsockopt (fd, IPPROTO_IP, IP_TOS, &tos, sizeof (tos)) < 0) {
+	  |       ^~~~~~~~~~
+	  Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7553>
+
+2024-09-18 16:09:13 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+	* libs/gst/base/gstaggregator.c:
+	* libs/gst/base/gstaggregator.h:
+	  aggregator: Add gst_aggregator_push_src_event()
+	  This ensures that any pending events are pushed before pushing the new event.
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7542>
+
+2024-09-18 16:08:17 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+	* libs/gst/base/gstaggregator.c:
+	  aggregator: Remove unused tag handling code
+	  If this becomes API it would now have to be implemented differently because
+	  various elements are implementing tag handling themselves now and this would
+	  conflict.
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7542>
+
+2024-09-14 04:01:42 +0200  Peter Kjellerstedt <pkj@axis.com>
+
+	* gst/gstmeta.h:
+	  meta: Add missing include of gststructure.h
+	  This avoids the following error when only including gstmeta.h:
+	  /usr/include/gstreamer-1.0/gst/gstmeta.h:146:3: error: unknown type
+	  name 'GstStructure'
+	  146 |   GstStructure *structure;
+	  |   ^~~~~~~~~~~~
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7520>
+
+2024-09-13 10:58:27 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+	* libs/gst/base/gstaggregator.c:
+	  aggregator: Immediately return NONE from simple_get_next_time() on non-TIME segments
+	  Otherwise this gives critical warnings.
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7511>
+
+2024-09-10 16:03:05 -0400  Arun Raghavan <arun@asymptotic.io>
+
+	* gst/gstpad.c:
+	  pad: Check data NULL-ness when probes are stopped
+	  We were correctly handling this for buffers, but not events and queries.
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7493>
+
+2024-09-05 12:49:11 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+	* gst/gstclock.c:
+	* gst/gstclock.h:
+	  clock: Use external / internal as term for the two clock bases everywhere
+	  It was confusing that some functions were using master for the external time and
+	  slave for the internal time. This is not consistently using external / internal
+	  when talking about concrete clock times.
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7456>
+
+2024-09-05 12:40:32 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+	* gst/gstclock.c:
+	  clock: Use `nullable` / `optional` annotations instead of ambiguous `allow-none`
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7456>
+
+2024-08-20 01:29:56 +0100  Tim-Philipp Müller <tim@centricular.com>
+
+	* gst/glib-compat-private.h:
+	* gst/gstpreset.c:
+	* gst/gstvecdeque.c:
+	* libs/gst/net/gstnetclientclock.c:
+	* libs/gst/net/gstptpclock.c:
+	* tools/gst-inspect.c:
+	  gstreamer: use g_sort_array() instead of deprecated g_qsort_with_data()
+	  Fixes compiler warnings with the latest GLib versions.
+	  See https://gitlab.gnome.org/GNOME/glib/-/merge_requests/4127
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7384>
+
+2024-04-18 17:45:37 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+	* gst/gstbus.c:
+	  bus: Switch from GstAtomicQueue to GstVecDeque
+	  All accesses to it were protected either by a mutex already, or at least
+	  used yet another mutex for gst_poll_read_control() / gst_poll_write_control().
+	  The usage of GstPoll has to stay for backwards compatibility as it is
+	  used to manage the (public) fd that can be used to wait for the bus to
+	  be ready, but this switch at least simplifies the implementation a bit
+	  and results in fewer atomic operations.
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6684>
+
+2024-04-18 17:08:36 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+	* gst/gstbufferpool.c:
+	  bufferpool: Switch from GstAtomicQueue to GstVecDeque and a mutex/cond
+	  While the atomic queue itself is lock-free, all its usage had to be
+	  synchronized externally via a GstPoll and gst_poll_read_control() /
+	  gst_poll_write_control(). Both functions were always taking a mutex
+	  internally since cd06aea1, so the implementation was just very
+	  complicated but not lock-free at all.
+	  Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/2714
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6684>
+
+2024-08-28 10:25:18 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+	* gst/gststructure.c:
+	  structure: Remove quadratic behaviour from gst_structure_fixate()
+	  It was iterating over each field and after fixating its value was again
+	  iterating over every field to find where to store the value.
+	  Instead directly overwrite the value after validating it.
+	  Also actually check that the structure is writable before modifying its fields
+	  by using gst_structure_map_in_place() instead of gst_structure_fixate().
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7420>
+
+2024-08-26 19:13:11 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+	* gst/gstutils.c:
+	  clock: Fix calculation for number of bits needed to store a 64 bit value
+	  It was using log2(n) but what actually is needed is log2(n) + 1. Also add a
+	  fast-path that uses __builtin_clzll() on gcc/clang.
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7406>
+
+2024-08-23 15:56:41 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+	* gst/gstutils.c:
+	* tests/check/gst/gstutils.c:
+	  clock: Fix unchecked overflows in linear regression code
 	  The initial calculation for the precision shift was wrong and would allow for
 	  overflows during the calculations which were not detected and lead to wrong
 	  results.
 	  Also add a test for a case where overflows where previously not detected and
 	  caused a completely wrong result.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7431>
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7406>
 
-2024-08-21 12:33:28 +0100  Tim-Philipp Müller <tim@centricular.com>
+2024-08-27 14:50:56 -0400  Daniel Morin <daniel.morin@collabora.com>
 
-	* meson.build:
-	  Back to development after 1.24.7
+	* gst/gststructure.c:
+	  doc: correct delimiters documentation
+	  - "<>" are delimiters for GST_TYPE_ARRAY and "{}" are delimiters for
+	  GST_TYPE_LIST.
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7419>
 
-=== release 1.24.7 ===
+2024-07-26 11:47:00 +0200  Edward Hervey <edward@centricular.com>
 
-2024-08-21 12:25:15 +0100  Tim-Philipp Müller <tim@centricular.com>
+	* tests/check/gstreamer.supp:
+	  gstreamer: Make dlopen leak suppression more generic
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7415>
 
-	* NEWS:
-	* RELEASE:
-	* gstreamer.doap:
-	* meson.build:
-	  Release 1.24.7
+2024-08-16 08:53:39 +1000  Jan Schmidt <jan@centricular.com>
+
+	* libs/gst/check/gstcheck.h:
+	  check: Add fail_unless_matches_string() and assert macros
+	  Add string check macros for checking expected strings against
+	  a regular expression instead of just a direct literal match
+	  as provided by the existing fail_unless_equals_string()
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7365>
 
 2024-05-28 16:27:39 +0300  Jan Schmidt <jan@centricular.com>
 
@@ -475,7 +1744,7 @@
 	  core: Log pad name, not just the pointer
 	  Change a debug statement that was just logging a pad pointer where
 	  it could log the pad name more usefully.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7336>
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6943>
 
 2024-08-05 17:34:15 +0300  Sebastian Dröge <sebastian@centricular.com>
 
@@ -483,22 +1752,22 @@
 	  bin: Don't keep the object lock while setting a GstContext when handling NEED_CONTEXT
 	  This can potentially deadlock.
 	  Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/3707
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7310>
-
-2024-07-29 16:48:02 +0100  Tim-Philipp Müller <tim@centricular.com>
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7305>
 
-	* meson.build:
-	  Back to development after 1.24.6
+2024-05-29 16:33:48 +0300  Jan Schmidt <jan@centricular.com>
 
-=== release 1.24.6 ===
+	* gst/gsturi.c:
+	* tests/check/gst/gsturi.c:
+	  gsturi: Ensure file:// URIs retain //
+	  Add the // back after the scheme for file URIs so 'file:///path/to/file'
+	  doesn't become 'file:/path/to/file' in gst_uri_to_string()
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6969>
 
-2024-07-29 16:41:37 +0100  Tim-Philipp Müller <tim@centricular.com>
+2024-04-02 09:14:59 -0300  L. E. Segovia <amy@centricular.com>
 
-	* NEWS:
-	* RELEASE:
-	* gstreamer.doap:
-	* meson.build:
-	  Release 1.24.6
+	* gst/gstsystemclock.c:
+	  gst: clock: Move Android OS check to the __ANDROID__ macro
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6510>
 
 2024-07-03 09:05:06 +0200  Guillaume Desmottes <guillaume.desmottes@onestream.live>
 
@@ -507,7 +1776,7 @@
 	  gst_download_buffer_read_buffer() returns FLOW_EOS but it was not
 	  handled in the 'out_flushing' goto block which uses srcresult,
 	  so EOS was not sent downstream.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7140>
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7128>
 
 2024-07-03 09:16:47 +0200  Guillaume Desmottes <guillaume.desmottes@onestream.live>
 
@@ -515,7 +1784,7 @@
 	  downloadbuffer: initialize upstream_size when activated in push mode
 	  Push mode flow relies on upstream_size but it was not initialized when
 	  activated as it is when activated in pull mode.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7140>
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7128>
 
 2024-07-03 09:13:27 +0200  Guillaume Desmottes <guillaume.desmottes@onestream.live>
 
@@ -523,33 +1792,61 @@
 	  downloadbuffer: init upstream_size to -1
 	  Code in check_upstream_size() is checking for -1 to check if
 	  upstream_size has been set or not.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7140>
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7128>
 
 2024-07-03 09:03:59 +0200  Guillaume Desmottes <guillaume.desmottes@onestream.live>
 
 	* plugins/elements/gstdownloadbuffer.c:
 	  downloadbuffer: properly log when receiving events
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7140>
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7128>
 
 2024-07-02 15:56:12 +0100  Tim-Philipp Müller <tim@centricular.com>
 
 	* gst/gstinfo.c:
 	  info: remove unused valgrind header include
 	  Follow-up to commit a2cbf75523cdf8a4df1baa7007d86ef455972245.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7129>
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7126>
+
+2024-07-01 20:53:35 +0300  Vivia Nikolaidou <vivia@ahiru.eu>
+
+	* libs/gst/net/gstptpclock.c:
+	  ptpclock: Fix typo in comments
+	  s/continous/continuous/
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7121>
 
 2024-07-01 09:24:28 +0200  Edward Hervey <edward@centricular.com>
 
 	* tests/validate/gst-tester.c:
 	  gstreamer/gst-tester: Don't leak thread
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7123>
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7115>
 
 2024-06-29 17:12:12 +0200  Edward Hervey <edward@centricular.com>
 
 	* tools/gst-inspect.c:
 	  gst-inspect: Fix leak of plugin/feature
 	  Reordering changes the initial list head
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7123>
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7115>
+
+2020-04-08 10:40:42 -0400  Xavier Claessens <xavier.claessens@collabora.com>
+
+	* gst/meson.build:
+	* meson.build:
+	* meson_options.txt:
+	  build: Add missing common options that are yielding in subprojects
+	  - Align `glib_debug`, `glib_assert` and `glib_checks` options with GLib,
+	  otherwise glib subproject won't inherit their value. Previous names
+	  and values are preserved using Meson's deprecation mechanism.
+	  - Add `extra-checks` and `benchmarks` options in the main project so it
+	  can be inherited in GStreamer subprojects.
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/1165>
+
+2024-06-21 09:29:13 +0200  Edward Hervey <edward@centricular.com>
+
+	* libs/gst/base/gstbasesink.c:
+	  basesink: Remove field not used
+	  It was never actually used since it was introduced as part of the commit
+	  introducing support for instant rate
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7077>
 
 2024-06-20 15:13:27 +0300  Sebastian Dröge <sebastian@centricular.com>
 
@@ -559,7 +1856,7 @@
 	  queue, queue2, multiqueue: Timestamps of gap events must be valid
 	  This is checked in gst_event_new_gap() so doesn't have to be checked again here,
 	  but simply can be asserted with a g_return_if_fail().
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7075>
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7071>
 
 2024-06-20 15:10:07 +0300  Sebastian Dröge <sebastian@centricular.com>
 
@@ -578,22 +1875,23 @@
 	  Instead, simply don't update the times from buffers without timestamps and
 	  assume whatever was set before is still valid, i.e. the buffer has the same
 	  timestamp as the previous one.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7075>
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7071>
 
-2024-06-20 13:02:19 +0100  Tim-Philipp Müller <tim@centricular.com>
+2024-03-12 01:22:03 +0900  Seungha Yang <seungha@centricular.com>
 
-	* meson.build:
-	  Back to development after 1.24.5
+	* gst/gstbufferpool.h:
+	  bufferpool: Clarify GstBufferPoolClass::start() usage
+	  Make it clear that chaining up to the default implementation
+	  is optional if subclasses do not want preallocation.
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6328>
 
-=== release 1.24.5 ===
+2024-05-27 15:32:10 +0200  Guillaume Desmottes <guillaume.desmottes@onestream.live>
 
-2024-06-20 12:54:15 +0100  Tim-Philipp Müller <tim@centricular.com>
-
-	* NEWS:
-	* RELEASE:
-	* gstreamer.doap:
-	* meson.build:
-	  Release 1.24.5
+	* libs/gst/base/gsttypefindhelper.c:
+	  typefindhelper: implement get_length on GstTypeFindBufHelper
+	  Some typefind code may rely on gst_type_find_get_length() which was not
+	  working when using the helper.
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6937>
 
 2024-06-05 10:38:57 +0200  Edward Hervey <edward@centricular.com>
 
@@ -602,7 +1900,7 @@
 	  gstpromise: Don't use g_return_* for internal checks
 	  If assertion/checks are disabled bad things will happen and the function won't
 	  return as expected
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6998>
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6993>
 
 2024-05-30 12:08:57 +0200  Martin Nordholts <martn@axis.com>
 
@@ -612,7 +1910,7 @@
 	  gst_debug_log_id_literal() is simply missing, which can
 	  cause link errors for project using gstreamer with
 	  gst_debug=false.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6979>
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6972>
 
 2024-05-30 01:07:30 +0200  Samuel Thibault <samuel.thibault@ens-lyon.org>
 
@@ -621,22 +1919,18 @@
 	* libs/gst/helpers/ptp/meson.build:
 	* libs/gst/helpers/ptp/net.rs:
 	  ptp-helper: Add GNU/Hurd support
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6974>
-
-2024-05-29 13:51:27 +0300  Tim-Philipp Müller <tim@centricular.com>
-
-	* meson.build:
-	  Back to development after 1.24.4
-
-=== release 1.24.4 ===
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6970>
 
-2024-05-29 13:44:50 +0300  Tim-Philipp Müller <tim@centricular.com>
+2024-05-21 11:31:34 +0200  Edward Hervey <edward@centricular.com>
 
-	* NEWS:
-	* RELEASE:
-	* gstreamer.doap:
-	* meson.build:
-	  Release 1.24.4
+	* gst/gstmessage.c:
+	* gst/gstmessage.h:
+	* tests/check/gst/gstmessage.c:
+	  gstmessage: Allow retrieving and setting details on messages
+	  This was only available on warning/error/info messages creator/parsers. These
+	  new functions make it more generic and also add a writable variant for users who
+	  want to add/extend the details
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6929>
 
 2024-05-28 13:17:39 +0300  Sebastian Dröge <sebastian@centricular.com>
 
@@ -646,7 +1940,7 @@
 	  to be retrieved again via GstObject API, which would crash on other
 	  GObjects. Child proxy child objects can be any kind of GObject and the
 	  code here otherwise handles this correctly already.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6951>
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6938>
 
 2024-05-28 09:06:57 +0300  Sebastian Dröge <sebastian@centricular.com>
 
@@ -654,7 +1948,16 @@
 	  gstreamer: ptp-helper: Use u64 instead of c_ulong for ifa_flags on Solaris/Illumos
 	  See https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/3553#note_2429400
 	  Patch by Marcel Telka <marcel@telka.sk>.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6950>
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6934>
+
+2024-05-09 10:17:39 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+	* gst/gstinfo.c:
+	* gst/gstinfo.h:
+	  info: Make gst_debug_print_object() and gst_debug_print_segment() public
+	  It can be useful in custom logging code to easily get string
+	  representations of all kinds of objects or a segment.
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6820>
 
 2024-05-26 12:33:02 +0300  Sebastian Dröge <sebastian@centricular.com>
 
@@ -662,7 +1965,7 @@
 	  gstreamer: ptp-helper: Use `if_nametoindex` and `setsockopt` on Solaris / Illumos too
 	  Patch by Marcel Telka <marcel@telka.sk>.
 	  Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/3552
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6947>
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6925>
 
 2024-05-26 12:31:33 +0300  Sebastian Dröge <sebastian@centricular.com>
 
@@ -671,7 +1974,7 @@
 	  This only affected the Solaris / Illumos code path.
 	  Patch by Marcel Telka <marcel@telka.sk>.
 	  Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/3551
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6947>
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6925>
 
 2024-05-26 12:27:54 +0300  Sebastian Dröge <sebastian@centricular.com>
 
@@ -680,7 +1983,7 @@
 	  gstreamer: ptp-helper: Use `c_ulong` for `ifa_flags` on Solaris/Illumos
 	  Based on a patch by Marcel Telka <marcel@telka.sk>.
 	  Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/3553
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6947>
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6925>
 
 2024-05-26 12:24:33 +0300  Sebastian Dröge <sebastian@centricular.com>
 
@@ -691,7 +1994,7 @@
 	* tests/misc/meson.build:
 	  gstreamer: Solaris/Illumos require linking to libnsl / libsocket for various socket APIs
 	  Patch by Tim Mooney <Tim.Mooney@ndsu.edu> from OpenIndiana/oi-userland
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6947>
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6925>
 
 2024-05-17 11:03:51 +0300  Sebastian Dröge <sebastian@centricular.com>
 
@@ -705,7 +2008,16 @@
 	  compiled with -D_TIME_BITS=64.
 	  Also statically assert that time_t is either 32 or 64 bits. Other values
 	  might need adjustments in the macro.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6919>
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6869>
+
+2024-05-21 08:24:51 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+	* gst/gstbufferlist.c:
+	  bufferlist: get() is not actually nullable in its return value
+	  Passing an out of bounds index is the only way to get a NULL buffer but
+	  this causes an assertion so is not to be considered for the
+	  annotations.
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6884>
 
 2024-05-21 21:50:47 +0300  Jordan Petridis <jordan@centricular.com>
 
@@ -716,7 +2028,7 @@
 	  As such, having variables named "bool" causes issues
 	  since it conflicts with the symbol defined in stdbool.h
 	  [1] https://gitlab.gnome.org/GNOME/glib/-/merge_requests/4001
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6896>
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6893>
 
 2024-05-17 23:03:19 +0900  Seungha Yang <seungha@centricular.com>
 
@@ -729,7 +2041,13 @@
 	  we open a file. To avoid it, our own exception
 	  handler must be installed so that _get_osfhandle() can return
 	  INVALID_HANDLE_VALUE if fd is invalid.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6879>
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6877>
+
+2024-05-15 09:27:26 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+	* gst/gstbuffer.c:
+	  buffer: Use C11 atomics if available for 64 bit atomic operations
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6740>
 
 2024-05-14 23:30:56 +0200  Alexander Slobodeniuk <aslobodeniuk@fluendo.com>
 
@@ -739,23 +2057,97 @@
 	  I've found that sets any of those is msvc, but it sets
 	  __STDC_NO_ATOMICS__, not __STDC_NO_ATOMICS.
 	  __STDC_NO_ATOMICS__ is the one documented by C11 standard.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6856>
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6848>
 
-2024-04-30 00:36:59 +0100  Tim-Philipp Müller <tim@centricular.com>
+2024-05-01 11:36:07 +0300  Sebastian Dröge <sebastian@centricular.com>
 
-	* meson.build:
-	  Back to development after 1.24.3
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6772>
+	* gst/gstinfo.c:
+	  info: Use GstVecDeque for the ringbuffer logger instead of GQueue
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6779>
+
+2024-04-18 17:07:25 +0300  Sebastian Dröge <sebastian@centricular.com>
+
+	* gst/gst.h:
+	* gst/gstvecdeque.c:
+	* gst/gstvecdeque.h:
+	* gst/meson.build:
+	* libs/gst/base/base-prelude.h:
+	* libs/gst/base/gstadapter.c:
+	* libs/gst/base/gstdataqueue.c:
+	* libs/gst/base/gstqueuearray.c:
+	* libs/gst/base/gstqueuearray.h:
+	* plugins/elements/gstqueue.c:
+	* plugins/elements/gstqueue.h:
+	* plugins/elements/gstqueue2.c:
+	* plugins/elements/gstqueue2.h:
+	* tests/check/gst/gstvecdeque.c:
+	* tests/check/libs/gstlibscpp.cc:
+	* tests/check/libs/queuearray.c:
+	* tests/check/meson.build:
+	  gst: Move GstQueueArray as GstVecDeque to core
+	  And change lengths and indices from guint to gsize for a more correct type.
+	  Also deprecate GstQueueArray and implement it in terms of GstVecDeque.
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6779>
 
-=== release 1.24.3 ===
+2024-04-23 10:58:39 +0200  Edward Hervey <edward@centricular.com>
 
-2024-04-30 00:15:23 +0100  Tim-Philipp Müller <tim@centricular.com>
+	* gst/gstquark.c:
+	* gst/gstquark.h:
+	* gst/gstvalue.c:
+	  gstvalue: Add a GstAllocationParams to String conversion
+	  Avoids ending up with plenty of warnings when serializing GstStructure
+	  containing GstAllocationParams
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6714>
 
-	* NEWS:
-	* RELEASE:
-	* gstreamer.doap:
-	* meson.build:
-	  Release 1.24.3
+2024-04-19 09:34:12 +0200  Edward Hervey <edward@centricular.com>
+
+	* gst/gststructure.c:
+	  structure: Add a serialization for GArray in GstStructure
+	  Instead of constantly spurting out warnings in the log files
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6691>
+
+2024-03-27 13:41:38 -0400  Xavier Claessens <xavier.claessens@collabora.com>
+
+	* gst/gstpad.c:
+	  pad: gst_pad_set_offset is only reliable on source pads
+	  Setting an offset on sink pads won't repush segment event which means
+	  buffer running time won't be adjusted. Better warn about this than being
+	  silently not working.
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6464>
+
+2024-04-18 11:09:46 +0200  Johan Sternerup <johast@axis.com>
+
+	* libs/gst/base/gstbasesrc.c:
+	  basesrc: protect segment_seqnum/pending with object lock
+	  In a few places the object lock was not taken when writing to
+	  segment_pending and segment_seqnum.
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6671>
+
+2024-04-16 14:30:24 +0200  Johan Sternerup <johast@axis.com>
+
+	* libs/gst/base/gstbasesrc.c:
+	  gstbasesrc: Do not hold LIVE_LOCK while sending events
+	  An application that triggers a state transition from PLAYING to PAUSED
+	  needs to acquire the LIVE_LOCK. Consequently the LIVE_LOCK must not be
+	  taken while pushing anything on the pads because this operation might
+	  get blocked by something that cannot be unblocked without the
+	  application being able to proceed with the state transitions for other
+	  elements in the pipeline. This commit extends the previous behaviour
+	  where the live lock was released before pushing buffers (indirectly
+	  through the unlock before subclass->create) to now also include
+	  unlocking before pushing events.
+	  The issue was discovered in a case for WebRTC where the application
+	  tried to shut down a pipeline but an event originating from a video
+	  source element (based on basesrc) was in the process of being pushed
+	  down the pipeline when it got stuck on the STREAM_LOCK for the pad after
+	  the rtpgccbwe element. This lock in turn was held by the rtcpgccbwe
+	  element as it was in the process of pushing data down the pipeline but
+	  was stuck on the blocking probes installed on dtlssrtpenc to prevent
+	  data from flowing before dtls keys had been negotiated. What should have
+	  happened here is that the blocking probes should be removed, but that
+	  can only happen if the application may continue driving the state
+	  transitions.
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6671>
 
 2024-04-10 16:29:15 +0300  Sebastian Dröge <sebastian@centricular.com>
 
@@ -763,28 +2155,19 @@
 	  ptp: Silence warning about some unused trait methods
 	  These are not used yet but will likely be useful in the future.
 	  Rust 1.79 (nightly) is warning about them being unused.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6606>
-
-2024-04-10 00:04:02 +0100  Tim-Philipp Müller <tim@centricular.com>
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6601>
 
-	* meson.build:
-	  Back to development after 1.24.2
-
-=== release 1.24.2 ===
+2024-04-03 20:56:57 +0200  Mark Nauwelaerts <mnauw@users.sourceforge.net>
 
-2024-04-09 21:48:55 +0100  Tim-Philipp Müller <tim@centricular.com>
-
-	* NEWS:
-	* RELEASE:
-	* gstreamer.doap:
-	* meson.build:
-	  Release 1.24.2
+	* libs/gst/base/gstadapter.c:
+	  adapter: align documentation to actual behavior
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6535>
 
 2024-04-02 11:54:52 -0400  Xavier Claessens <xavier.claessens@collabora.com>
 
 	* plugins/elements/gstclocksync.c:
 	  clocksync: Proxy allocation queries
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6525>
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6515>
 
 2024-03-27 16:55:10 +0000  L. E. Segovia <amy@centricular.com>
 
@@ -796,17 +2179,7 @@
 	  While at it, also fix all direct tests on __NR_futex_time64 and
 	  __NR_futex so that they refer to the results available in
 	  config.h.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6518>
-
-2024-03-26 19:40:04 +0530  Taruntej Kanakamalla <taruntej@asymptotic.io>
-
-	* libs/gst/net/gstptpclock.c:
-	  net/gstptpclock: fix double free of domain data during deinit
-	  The attempt to free the domain data is happeing twice during the ptp deinit.
-	  Once while iterating through the list domain_data and second while iterating
-	  through the list domain_clocks, so this is crashing the application
-	  trying to gst_ptp_deinit
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6457>
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6477>
 
 2024-03-27 17:05:09 +0200  Sebastian Dröge <sebastian@centricular.com>
 
@@ -816,7 +2189,17 @@
 	  valid as long as a buffer list is returned instead. Previously this
 	  would cause an assertion because of calling gst_buffer_unref() with
 	  NULL.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6463>
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6460>
+
+2024-03-26 19:40:04 +0530  Taruntej Kanakamalla <taruntej@asymptotic.io>
+
+	* libs/gst/net/gstptpclock.c:
+	  net/gstptpclock: fix double free of domain data during deinit
+	  The attempt to free the domain data is happeing twice during the ptp deinit.
+	  Once while iterating through the list domain_data and second while iterating
+	  through the list domain_clocks, so this is crashing the application
+	  trying to gst_ptp_deinit
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6443>
 
 2024-03-26 14:28:28 +0100  Arnaud Vrac <avrac@freebox.fr>
 
@@ -824,22 +2207,7 @@
 	  inputselector: fix possible clock leak on shutdown
 	  Avoid leaking a GstClock object on shutdown, bail out before taking the ref when
 	  not playing.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6455>
-
-2024-03-22 01:38:06 +0100  Tim-Philipp Müller <tim@centricular.com>
-
-	* meson.build:
-	  Back to development
-
-=== release 1.24.1 ===
-
-2024-03-21 21:47:53 +0100  Tim-Philipp Müller <tim@centricular.com>
-
-	* NEWS:
-	* RELEASE:
-	* gstreamer.doap:
-	* meson.build:
-	  Release 1.24.1
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6442>
 
 2024-03-19 08:57:43 -0400  Thomas Goodwin <thomas.goodwin@laerdal.com>
 
@@ -859,7 +2227,7 @@
 	  return code of '2' is used to uniquely identify the failure.
 	  Fixes #3246
 	  Signed-off-by: Thomas Goodwin <thomas.goodwin@laerdal.com>
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6414>
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6191>
 
 2024-03-13 19:12:48 +0200  Sebastian Dröge <sebastian@centricular.com>
 
@@ -872,7 +2240,7 @@
 	  would've been wrongly associated to the very first pending sync because
 	  of the seqnum.
 	  Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/3383
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6365>
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6361>
 
 2024-03-11 15:10:25 +0100  Antonio Larrosa <alarrosa@suse.com>
 
@@ -889,7 +2257,7 @@
 	  is found correctly under
 	  /usr/lib64/../libexec/gstreamer-1.0/gst-plugin-scanner
 	  Similar change applied to gstreamer/libs/gst/net/gstptpclock.c
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6343>
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6322>
 
 2024-02-27 18:59:41 +0530  Nirbheek Chauhan <nirbheek@centricular.com>
 
@@ -900,7 +2268,7 @@
 	  registered, which is mostly dependent on the order in which readdir()
 	  returns items.
 	  So let's make it predictable.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6342>
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6227>
 
 2024-03-08 17:05:34 +1100  Jan Schmidt <jan@centricular.com>
 
@@ -911,7 +2279,7 @@
 	  other seek behaviour by refusing (for example) instant-rate change
 	  seeks.
 	  Fixes: #3363
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6314>
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6299>
 
 2024-02-25 04:26:21 +1100  Jan Schmidt <jan@centricular.com>
 
@@ -922,2697 +2290,47 @@
 	  gst_segment_to_running_time_full()
 	  g_return_val_if_fail() is for programmer errors,
 	  and can be compiled out with a flag.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6275>
-
-2024-03-05 15:10:45 +0200  Sebastian Dröge <sebastian@centricular.com>
-
-	* libs/gst/helpers/ptp/meson.build:
-	  ptp: Don't install test executable
-	  And handle it like all our other test executables.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6268>
-
-2024-03-05 13:45:27 +0000  Tim-Philipp Müller <tim@centricular.com>
-
-	* meson.build:
-	  Back to development
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6264>
-
-=== release 1.24.0 ===
-
-2024-03-04 23:51:42 +0000  Tim-Philipp Müller <tim@centricular.com>
-
-	* NEWS:
-	* README.md:
-	* RELEASE:
-	* gstreamer.doap:
-	* meson.build:
-	  Release 1.24.0
-
-2024-02-26 09:27:40 +0100  Edward Hervey <edward@centricular.com>
-
-	* README.md:
-	* RELEASE:
-	  docs: Use Discourse and Matrix as prefered communication channels
-	  Part of: https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6220
-
-2024-02-26 09:26:44 +0100  Edward Hervey <edward@centricular.com>
-
-	* .gitlab/issue_templates/Bug.md:
-	  gitlab_template: Remove duplicate entry and remove mention of IRC
-	  Part of: https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6220
-
-2024-02-21 12:20:19 +0100  Arnaud Vrac <avrac@freebox.fr>
-
-	* plugins/elements/gstqueue2.c:
-	  queue2: post 100% buffering message even when waiting for space to be freed
-	  In the case where the queue shrinks due to a property change and the queue
-	  becomes full, we would set the waiting_del flag, which would prevent posting the
-	  100% buffering message on the bus. Since the pipeline is not aware of the new
-	  buffering value, in the common case where the pipeline is paused during
-	  buffering, it would never resume.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6165>
-
-2024-02-21 12:17:45 +0100  Arnaud Vrac <avrac@freebox.fr>
-
-	* plugins/elements/gstqueue2.c:
-	  queue2: move gst_queue2_get_buffering_message code to the only call site
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6165>
-
-2024-02-21 12:05:18 +0100  Arnaud Vrac <avrac@freebox.fr>
-
-	* plugins/elements/gstqueue2.c:
-	* plugins/elements/gstqueue2.h:
-	  queue2: remove redundant check to avoid posting the same buffering value twice
-	  Remove the percent_changed check to determine whether a buffering message should
-	  be posted. The check on the last posted buffering value is sufficient, and the
-	  removal doesn't introduce additional complexity.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6165>
-
-2024-02-21 11:41:32 +0100  Arnaud Vrac <avrac@freebox.fr>
-
-	* plugins/elements/gstqueue2.c:
-	  queue2: consolidate buffering message posting code
-	  No need to copy paste the code, simply call the common gst_queue2_post_buffering
-	  function.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6165>
-
-2024-02-21 11:17:13 +0100  Arnaud Vrac <avrac@freebox.fr>
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6219>
 
-	* plugins/elements/gstqueue2.c:
-	  queue2: make sure update_buffering is called with the lock taken
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6165>
-
-=== release 1.23.90 ===
+2024-03-06 12:22:26 +0100  François Laignel <francois@centricular.com>
 
-2024-02-23 18:20:11 +0000  Tim-Philipp Müller <tim@centricular.com>
-
-	* NEWS:
-	* RELEASE:
-	* gstreamer.doap:
-	* meson.build:
-	  Release 1.23.90
+	* libs/gst/net/gstptpclock.c:
+	  ptp clock: fix annotations for gst_ptp_clock_new
+	  * Set `name` as `nullable` same as for gst_ntp_clock_new.
+	  * Set return value as nullable as the constructor can fail.
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6251>
 
-2024-02-21 16:56:48 +0100  Jochen Henneberg <jh@henneberg-systemdesign.com>
+2024-02-29 15:44:43 +0200  Sebastian Dröge <sebastian@centricular.com>
 
 	* libs/gst/helpers/ptp/main.rs:
-	  ptp-helper: Allow sync to master clock on same host
-	  If we drop all messages with the same clock id as ours we will also
-	  drop all messages coming from a PTP clock on our host since both clock
-	  ids are build from the same MAC address.
-	  At least for Linux we do not see our own messages anyway since the
-	  network stack can well distinguish between multicast send from our
-	  socket or from another socket on the same machine. To make sure that
-	  this works for all supported platforms just drop delay requests since
-	  this is the only message that is sent from the GStreamer PTP clock.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6172>
-
-2023-01-28 01:11:45 +0000  Tim-Philipp Müller <tim@centricular.com>
-
-	* tools/gst-inspect.c:
-	  gst-inspect: print plugin error/warning/info status messages
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3832>
-
-2023-01-27 19:08:37 +0000  Tim-Philipp Müller <tim@centricular.com>
-
-	* gst/gst_private.h:
-	* gst/gstplugin.c:
-	* gst/gstplugin.h:
-	* gst/gstregistrybinary.h:
-	* gst/gstregistrychunks.c:
-	* tests/check/gst/gstplugin.c:
-	  plugin: add API for plugins to provide status info messages
-	  This can be used to store informational messages, errors or
-	  warnings which can later be shown to the user in gst-inspect-1.0,
-	  which can be useful for plugins that expose elements dynamically
-	  based on external libraries or hardware capabilities.
-	  Status messages can then provide an indication as to why a
-	  plugin doesn't have any elements listed, for example.
-	  Plus unit test to make sure code paths are exercised a little.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3832>
-
-2024-01-29 19:47:11 +0000  Tim-Philipp Müller <tim@centricular.com>
-
-	* gst/gstobject.c:
-	* gst/gstobject.h:
-	* tests/check/gst/gstbin.c:
-	  gstobject: add CONSTRUCTED flag
-	  This can be used later by base class APIs to know whether they're
-	  called from a subclass instance init function (where the object
-	  isn't properly constructed yet and one should only really poke
-	  at the instance structure but not much else) or after object
-	  construction has been finished.
-	  Fix up GstBin unit test for CONSTRUCTED flag addition.
-	  See https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/2794
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6150>
-
-2024-02-20 08:54:11 +0100  Edward Hervey <edward@centricular.com>
-
-	* gst/gstmeta.c:
-	  meta: Skip gst_meta_info_new in gir
-	  ```
-	  gstmeta.c:500: Warning: Gst: gst_meta_info_new: return value: Invalid
-	  non-constant return of bare structure or union; register as boxed type or (skip)
-	  ```
-	  Skip this for now
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6147>
-
-2024-02-19 12:25:01 +0000  Philippe Normand <philn@igalia.com>
-
-	* gst/gstprotection.c:
-	  protection: Document `original-media-type` caps field
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6142>
-
-2024-02-16 17:06:52 +0100  Guillaume Desmottes <guillaume.desmottes@onestream.live>
-
-	* docs/gst-hotdoc-plugins-scanner.c:
-	  docs: initialize values when GST_PLUGIN_API_FLAG_IGNORE_ENUM_MEMBERS is set
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5491>
-
-2024-02-15 09:21:15 -0500  Xavier Claessens <xavier.claessens@collabora.com>
-
-	* gst/gstbus.c:
-	  bus: do not leak message on invalid handler return value
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6124>
-
-2024-02-15 09:15:50 -0500  Xavier Claessens <xavier.claessens@collabora.com>
-
-	* gst/gstbus.c:
-	  bus: do not leak messages if there is no async handler
-	  This does not typically happen because "enable-async" property is TRUE
-	  by default. The only place where it is set to FALSE is in GstBin where a
-	  sync handler is used and always returns GST_BUS_DROP.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6124>
-
-2024-02-15 09:18:20 -0500  Xavier Claessens <xavier.claessens@collabora.com>
-
-	* gst/gstbus.c:
-	  bus: warn when message queue grows too much
-	  It usually means application is not handling messages causing memory
-	  consumption to grow infinitely.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3313>
+	  ptp-helper: Fix clippy warning and simplify code a bit
+	  warning: you seem to be trying to use `match` for an equality check. Consider using `if`
+	  --> ../subprojects/gstreamer/libs/gst/helpers/ptp/main.rs:246:17
+	  |
+	  246 | /                 match ptp_message.message_type {
+	  247 | |                     PtpMessageType::DELAY_REQ => {
+	  248 | |                         if args.verbose {
+	  249 | |                             trace!("Ignoring our own PTP message");
+	  ...   |
+	  253 | |                     _ => (),
+	  254 | |                 }
+	  | |_________________^
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6245>
 
-2024-02-15 16:38:53 +0000  Tim-Philipp Müller <tim@centricular.com>
-
-	* meson.build:
-	  Back to development
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6126>
+2024-03-05 15:10:45 +0200  Sebastian Dröge <sebastian@centricular.com>
 
-=== release 1.23.2 ===
+	* libs/gst/helpers/ptp/meson.build:
+	  ptp: Don't install test executable
+	  And handle it like all our other test executables.
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6262>
 
-2024-02-15 15:37:17 +0000  Tim-Philipp Müller <tim@centricular.com>
+2024-03-05 12:58:57 +0000  Tim-Philipp Müller <tim@centricular.com>
 
-	* NEWS:
+	* README.md:
 	* RELEASE:
-	* gstreamer.doap:
-	* meson.build:
-	  Release 1.23.2
-
-2024-02-14 00:35:55 +0000  Tim-Philipp Müller <tim@centricular.com>
-
-	* po/LINGUAS:
-	* po/fr.po:
-	* po/lv.po:
-	* po/nl.po:
-	* po/sv.po:
-	* po/tr.po:
-	  gstreamer: update translations
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6113>
-
-2024-02-03 11:51:27 +0000  Philippe Normand <philn@igalia.com>
-
-	* gst/gsttaglist.c:
-	* gst/gsttaglist.h:
-	  taglist: Register new tag for container specific track ID
-	  Unique identifier for the audio, video or text track this tag is associated
-	  with. The mappings for several container formats are defined in the [Sourcing
-	  In-band Media Resource Tracks from Media Containers into HTML
-	  specification](https://dev.w3.org/html5/html-sourcing-inband-tracks).
-	  Based on previous patch by Brendan Long.
-	  Fixes #45
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6041>
-
-2024-02-10 00:34:18 +0900  Seungha Yang <seungha@centricular.com>
-
-	* gst/gstpluginloader-win32.c:
-	  pluginloader-win32: Early terminate if plugin loader binary is not installed
-	  External plugin loader support for Windows is introduced
-	  in this dev cycle. Since helper binary was not required (useless)
-	  before this version, people may not ship the binary
-	  with new GStreamer version, then they will observe warning message.
-	  Instead of displaying the warning at plugin loading time,
-	  checks helper bin earlier and disable external plugin loader
-	  if helper binary is not installed.
-	  Fixes: https://gitlab.freedesktop.org/gstreamer/cerbero/-/issues/448
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6083>
-
-2023-12-18 15:39:07 -0500  Xavier Claessens <xavier.claessens@collabora.com>
-
-	* gst/gstmeta.c:
-	* gst/gststructure.c:
-	* gst/gststructure.h:
-	* gst/gstvalue.c:
-	* tests/check/gst/gststructure.c:
-	  structure: Allow STRICT flag only in _serialize_full()
-	  The STRICT flag makes _serialize() nullable which is an API break for
-	  bindings. Forbid it and add _serialize_full() that accepts it and is
-	  properly annotated.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5829>
-
-2021-11-10 13:26:33 +0100  Guillaume Desmottes <guillaume.desmottes@onestream.live>
-
-	* libs/gst/base/gstbasesrc.c:
-	  basesrc: add FIXME 2.0 about automatic_eos
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/1334>
-
-2024-02-06 18:09:02 +0000  Tim-Philipp Müller <tim@centricular.com>
-
 	* meson.build:
 	  Back to development
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6066>
-
-=== release 1.23.1 ===
-
-2024-02-06 16:37:19 +0000  Tim-Philipp Müller <tim@centricular.com>
-
-	* NEWS:
-	* RELEASE:
-	* gstreamer.doap:
-	* meson.build:
-	  Release 1.23.1
-
-2024-02-05 09:27:54 +0100  Tim-Philipp Müller <tim@centricular.com>
-
-	* meson_options.txt:
-	  meson_options.txt: fix meson warning about default bool values being a string
-
-2024-02-05 18:37:59 +0200  Sebastian Dröge <sebastian@centricular.com>
-
-	* gst/gstpad.c:
-	  pad: Copy over seqnum when creating a new segment event for applying pad offset
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6057>
-
-2024-02-06 10:02:03 +0200  Sebastian Dröge <sebastian@centricular.com>
-
-	* gst/gstutils.c:
-	  utils: Remove unnecessary const-removal casts from gst_util_filename_compare()
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6063>
-
-2024-02-06 09:48:17 +0200  Sebastian Dröge <sebastian@centricular.com>
-
-	* gst/gstutils.c:
-	  utils: Annotate gst_util_filename_compare() parameters as filenames
-	  They're not UTF-8 strings.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6063>
-
-2024-01-26 19:12:18 +0100  Piotr Brzeziński <piotr@centricular.com>
-
-	* gst/gstmacos.m:
-	  macos: Fix gst_macos_main() terminating whole process before returning a value
-	  Removes the usage of [NSApp terminate] to avoid killing the process and thus never actually returning a value.
-	  The new way is just to use [NSApp stop] and send an event, since stop only happens after an event is processed.
-	  Unlike terminate, stop will only halt the event loop, not the whole process.
-	  This uses an NSApplicationDelegate to listen for NSApp finishing the launch process, and then signals the 'main' thread
-	  to proceed. That makes sure to never call [NSApp stop] before NSApp is actually running, which could happen if the
-	  provided 'main' function finished quickly enough.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6005>
-
-2024-01-29 16:10:38 -0300  Thibault Saunier <tsaunier@igalia.com>
-
-	* libs/gst/base/gstbasesrc.c:
-	  basesrc: Lower verbosity  of often happening warning
-	  decodebin(3) runs a scheduling query before pads are activated which
-	  ultimately triggers basesrc->start which will automatically call
-	  `gst_base_src_start_complete` for any source that is not marked as
-	  'async'. This calls will harmlessly bail out in `not_activated_yet`
-	  so we should not warn in that case.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6011>
-
-2024-01-23 15:28:50 +0100  Guillaume Desmottes <guillaume.desmottes@onestream.live>
-
-	* gst/gstpad.c:
-	  core: pad: call tracer query-post hook after probes
-	  Tracers are likely interested about the end result of the query, so
-	  after probes have been caled.
-	  Fix a bug where the buffer-lateness tracer was reporting a wrong latency
-	  when pad probes increased the latency.
-	  Also call the tracer hook if the pad has no query function.
-	  Fix https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/-/issues/486
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5963>
-
-2023-11-21 19:54:32 -0300  Thibault Saunier <tsaunier@igalia.com>
+	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6261>
 
-	* libs/gst/base/gstbasesink.c:
-	  basesink: Preroll on out of segment buffers when not dropping them
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5980>
-
-2024-01-28 11:15:01 +0000  Tim-Philipp Müller <tim@centricular.com>
-
-	* meson.build:
-	  meson: bump Meson requirement to >= 1.1 for all modules
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6002>
-
-2023-08-31 18:55:58 -0400  Thibault Saunier <tsaunier@igalia.com>
-
-	* libs/gst/helpers/gst_gdb.py:
-	  gdb: Fix the way we wrap segments
-	  Without that we end up with a reference to a GBoxed instead of the actual segment making the rest of the code fail
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5986>
-
-2023-08-31 18:55:14 -0400  Thibault Saunier <tsaunier@igalia.com>
-
-	* libs/gst/helpers/gst_gdb.py:
-	  gdb: Fix issue with undeclared variable
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5986>
-
-2023-08-31 18:53:46 -0400  Thibault Saunier <tsaunier@igalia.com>
-
-	* libs/gst/helpers/glib_gobject_helper.py:
-	* libs/gst/helpers/gst_gdb.py:
-	  gdb: Handle the case where the fundamental type table is optimized out
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5986>
-
-2023-08-31 18:52:58 -0400  Thibault Saunier <tsaunier@igalia.com>
-
-	* libs/gst/helpers/glib_gobject_helper.py:
-	* libs/gst/helpers/gst_gdb.py:
-	  gdb: Fix python style
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5986>
-
-2023-08-31 18:43:46 -0400  Thibault Saunier <tsaunier@igalia.com>
-
-	* libs/gst/helpers/glib_gobject_helper.py:
-	  gdb: Workaround optimized out quark_seq_id
-	  On fedora 38 (and it was the case in previous releases), the
-	  quark_seq_id is optimized out so getting quarks from the
-	  global variable always failed. This patch works around that by assuming
-	  it is a valid quark whenever the quark_seq_id is not accessible.
-	  This issue often manifested as Python Exception <class 'TypeError'>:
-	  can only concatenate str (not "NoneType") to str when debugging as
-	  other parts of the code assume that getting the quark for a GType name
-	  will work.
-	  Same as https://gitlab.gnome.org/GNOME/glib/-/merge_requests/3559
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5986>
-
-2024-01-17 15:57:43 +0100  Jonas K Danielsson <jonas.danielsson@spiideo.com>
-
-	* gst/gstutils.c:
-	* gst/gstutils.h:
-	  gstutils: Add g_util_filename_compare
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4491>
-
-2023-04-24 09:28:22 +0200  Guillaume Desmottes <guillaume.desmottes@onestream.live>
-
-	* gst/gstpipeline.c:
-	* gst/gstpipeline.h:
-	  core: pipeline: add gst_pipeline_get_configured_latency()
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4472>
-
-2023-04-21 17:49:50 +0200  Guillaume Desmottes <guillaume.desmottes@onestream.live>
-
-	* gst/gstpipeline.c:
-	* gst/gstpipeline.h:
-	  core: pipeline: add gst_pipeline_is_live()
-	  Convenient API for applications wanting to check if a pipeline is live
-	  or not. Save them from checking the change_state return value or sending
-	  latency queries.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4472>
-
-2023-04-21 17:44:43 +0200  Guillaume Desmottes <guillaume.desmottes@onestream.live>
-
-	* gst/gstpipeline.c:
-	  core: pipeline: protect priv->is_live with object lock
-	  It's supposed to be according to the comment where it's defined.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4472>
-
-2023-08-30 10:56:19 -0600  Scott Moreau <oreaus@gmail.com>
-
-	* tools/gst-launch.c:
-	  gst-launch: accept option to set program name
-	  The option --prog-name="PROGRAM-NAME" can be passed to set the program name.
-	  The program name is used by gtk and gstreamer to set the class or app-id.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5263>
-
-2023-04-05 08:48:36 -0400  Xavier Claessens <xavier.claessens@collabora.com>
-
-	* gst/gstobject.h:
-	* gst/gstpad.h:
-	* tests/check/gst/gstobject.c:
-	  gstpad, gstobject: Add GMutexLocker helper
-	  Add GST_OBJECT_AUTO_LOCK() and GST_PAD_STREAM_AUTO_LOCK() to simplify
-	  g_autoptr(GMutexLocker) usage.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4300>
-
-2024-01-05 14:32:00 +0100  Stéphane Cerveau <scerveau@igalia.com>
-
-	* gst/gstutils.c:
-	* gst/gstutils.h:
-	  gstutils: add gst_util_ceil_log2
-	  Move ceil_log2 from nalutils.* to gstutils.*
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5888>
-
-2023-12-29 10:15:49 +0200  Sebastian Dröge <sebastian@centricular.com>
-
-	* libs/gst/helpers/ptp/io.rs:
-	  ptp-helper: Allow unused `Stderr` export
-	  It's not used when building tests and would otherwise cause a warning.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5872>
-
-2023-12-18 16:33:07 -0500  Olivier Crête <olivier.crete@collabora.com>
-
-	* gst/gstbuffer.c:
-	* gst/gstmeta.c:
-	* gst/gstmeta.h:
-	  meta: Add API to register metas in two steps
-	  And also remove the specific registration APIs for
-	  serializable meta.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5830>
-
-2023-12-18 13:40:53 -0500  Olivier Crête <olivier.crete@collabora.com>
-
-	* gst/gstbufferpool.c:
-	* gst/gstmeta.c:
-	* gst/gstmeta.h:
-	  meta: Move the clear operation to its own vfunc
-	  Some transforms always assumed that the transformation was some kind
-	  of copy. So adding a "clear" operation didn't work out in practice.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5830>
-
-2023-12-01 12:10:36 -0500  Nicolas Dufresne <nicolas.dufresne@collabora.com>
-
-	* libs/gst/base/gstbaseparse.c:
-	  doc: baseparse: Clarify consumed vs output size
-	  When we finish a frame, we pass a size which semantic can easily be confused.
-	  Improve the documentation to clarify that the parameter size is the amount of
-	  input data being consumed and, if set, the output_buffer size can differ.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5754>
-
-2023-12-15 17:47:02 -0500  Xavier Claessens <xavier.claessens@collabora.com>
-
-	* gst/gstmeta.c:
-	  meta: gst_meta_serialize() is not introspectable
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5355>
-
-2023-09-18 19:24:35 -0400  Xavier Claessens <xavier.claessens@collabora.com>
-
-	* gst/gst.h:
-	* gst/gstbuffer.c:
-	* gst/gstbuffer.h:
-	* gst/gstbytearrayinterface.h:
-	* gst/gstmeta.c:
-	* gst/gstmeta.h:
-	* gst/meson.build:
-	* tests/check/gst/gstbuffer.c:
-	* tests/check/gst/gstmeta.c:
-	  meta: Add serialize/deserialize API
-	  This allows metas to be serialized to be transmitted or stored. This is
-	  intended to be used for example by gdppay or unixfdsink.
-	  Implemented on GstCustomMeta, GstVideoMeta, GstReferenceTimestampMeta,
-	  and GstAudioMeta.
-	  Sponsored-by: Netflix Inc.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5355>
-
-2023-09-20 15:34:40 -0400  Xavier Claessens <xavier.claessens@collabora.com>
-
-	* gst/gststructure.c:
-	* gst/gststructure.h:
-	* tests/check/gst/gststructure.c:
-	  structure: Add GST_SERIALIZE_FLAG_STRICT
-	  It makes serialization succeed only if all values have a type that can
-	  be deserialized.
-	  Sponsored-by: Netflix Inc.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5355>
-
-2023-09-24 14:48:36 -0400  Xavier Claessens <xavier.claessens@collabora.com>
-
-	* gst/gstbuffer.c:
-	  buffer: Remove trailing space
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5355>
-
-2023-12-01 08:21:03 -0500  Xavier Claessens <xavier.claessens@collabora.com>
-
-	* gst/gstplugin.c:
-	  devenv: Whitelist all plugins to be able to run tests
-	  Meson devenv already overrides GST_PLUGIN_PATH and
-	  GST_PLUGIN_SYSTEM_PATH so only built plugins can be found. That means
-	  unit tests are allowed to use every plugins.
-	  This makes easier to run some unit tests under devenv instead of through
-	  "meson test".
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5748>
-
-2023-12-05 14:01:50 +0200  Vivia Nikolaidou <vivia@ahiru.eu>
-
-	* plugins/elements/gstmultiqueue.c:
-	  multiqueue: Don't stop dropping when an internal queue is empty
-	  It is racy and may cause us to accidentally keep forwarding data past
-	  the EOS. The only reason to stop dropping would be when we encounter a
-	  stream-start, segment, or segment-done event, either in push_one
-	  (already queued) or in the sink pad's event function.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5766>
-
-2023-12-10 03:25:57 +1100  Jan Schmidt <jan@centricular.com>
-
-	* plugins/elements/gstmultiqueue.c:
-	  multiqueue: Ignore queue fullness for most events
-	  Use gst_data_queue_push_force() for most events so they
-	  are immediately enqueued. Only gap events and actual buffer
-	  data will now block when the queue is full.
-	  This fixes a problem with non-flushing seek handling
-	  where events following a segment-done event would block
-	  if they precede the SEGMENT event, since only SEGMENT
-	  events would clear the 'eos' state of the multiqueue
-	  queue.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5801>
-
-2023-12-12 23:55:04 +0100  Alexander Slobodeniuk <aslobodeniuk@fluendo.com>
-
-	* libs/gst/base/gstaggregator.c:
-	* tests/check/libs/aggregator.c:
-	  aggregator: fix use-after-free in queries processing
-	  Test included.
-	  The problem appears when aggregator drops the query while
-	  it's being proccessed by the klass->sink_query handler.
-	  This can happen on FLUSH_START event. If the query is still
-	  in the queue, it can be safely dropped, but if it's already
-	  in the klass->sink_query() handler, then sink pad has no
-	  choice and has to wait for the proccessing to complete.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5765>
-
-2023-11-28 15:47:38 -0300  Thibault Saunier <tsaunier@igalia.com>
-
-	* libs/gst/base/gstbasesrc.c:
-	  basesrc: Expose automatic-eos as a property
-	  It is useful for appsrc for example and no good reason to not expose it as a property
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5725>
-
-2023-11-29 10:53:15 -0700  Jordan Yelloz <jordan.yelloz@collabora.com>
-
-	* gst/gstcontext.c:
-	* gst/gstcontext.h:
-	  gstcontext: Added gst_clear_context()
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5756>
-
-2023-11-29 08:46:49 -0700  Jordan Yelloz <jordan.yelloz@collabora.com>
-
-	* gst/gstpromise.c:
-	* gst/gstpromise.h:
-	  gstpromise: Added gst_clear_promise()
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5756>
-
-2023-11-28 14:43:13 -0700  Jordan Yelloz <jordan.yelloz@collabora.com>
-
-	* gst/gstpromise.h:
-	  gstpromise: Added GST_IS_PROMISE() macro
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5728>
-
-2023-07-25 14:16:09 +0100  Stéphane Cerveau <scerveau@igalia.com>
-
-	* gst/gst.c:
-	* gst/meson.build:
-	* meson_options.txt:
-	  meson: fix gstreamer-full static mode on win32
-	  Win32 was expecting the symbol gst_init_static_plugins in gstreamer-full
-	  dynamic mode.
-	  Add mode in gstreamer gstreamer-full options to tell if its a
-	  gstreamer-full static or shared mode.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5098>
-
-2023-11-27 13:16:47 +0100  Jan Alexander Steffens (heftig) <jan.steffens@ltnglobal.com>
-
-	* libs/gst/base/gstbaseparse.c:
-	  baseparse: Reset metadata for reverse playback fragment buffers
-	  Don't let the adapter leak uncontrollable values.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5718>
-
-2023-11-27 12:29:08 +0100  Jan Alexander Steffens (heftig) <jan.steffens@ltnglobal.com>
-
-	* libs/gst/base/gstbaseparse.c:
-	  baseparse: Add missing gst_buffer_make_writable
-	  When the subclass attempts to finish without an explicit `out_buffer`,
-	  we take a buffer from our adapter. We need to make this buffer writable
-	  before copying the metadata.
-	  This led to data races such as in the following pipeline, which randomly
-	  messed up the buffer PTS:
-	  gst-launch-1.0 -e audiotestsrc timestamp-offset=5555 num-buffers=100 \
-	  ! opusenc ! tee name=t ! queue ! opusparse ! fakesink silent=0 \
-	  t. ! queue ! opusparse ! fakesink silent=0 -v | grep '0000, dur'
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5718>
-
-2023-09-01 17:29:50 -0400  Olivier Crête <olivier.crete@collabora.com>
-
-	* gst/gstbufferpool.c:
-	* gst/gstmeta.c:
-	* gst/gstmeta.h:
-	  meta: Add a new "clear" transform to avoid re-allocations
-	  In the buffer pool, try to clear metas before freeing them so we
-	  avoid constant reallocations on every frame.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4962>
-
-2023-08-03 17:05:17 -0600  Jordan Yelloz <jordan.yelloz@collabora.com>
-
-	* libs/gst/check/gstcheck.c:
-	  bad: Added W3C Media Source Extensions library
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/2992>
-
-2023-11-17 14:32:37 -0500  Nicolas Dufresne <nicolas.dufresne@collabora.com>
-
-	* tests/check/gstreamer.supp:
-	  valgrind: Supress racy cancellable source leak
-	  Creating a socket source, creates a cancellable source internally. This
-	  mechanism is racy and in order to workaround the race, the final unref
-	  can be delayed. Unfortunatly, it seams that this is randomly leaked.
-	  This affects users of glib 2.65 and up. Add a suppression on our side
-	  in order to avoid this leak showing up randomly in our CI.
-	  See https://gitlab.gnome.org/GNOME/glib/-/merge_requests/1400 for more
-	  about the glib implementation detail. And follow this link for an
-	  example of failing CI pipeline:
-	  https://gitlab.freedesktop.org/gstreamer/gstreamer/-/jobs/51694889
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5688>
-
-2023-11-13 16:27:48 +0200  Sebastian Dröge <sebastian@centricular.com>
-
-	* libs/gst/helpers/ptp/args.rs:
-	* libs/gst/helpers/ptp/main.rs:
-	* libs/gst/net/gstptpclock.c:
-	  ptp: Add `ttl` configuration to gst_ptp_init_full()
-	  This allows configuring the TTL that is used for multicast packets sent
-	  out on the sockets, and is defaulting to 1 as before. The default might
-	  change at some point.
-	  In some networks multiple hops are needed to reach the PTP clock and
-	  this allows to configure GStreamer in a way that works in such networks.
-	  At a later time, per-domain or per-interface TTL configurations might be
-	  added when needed.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5649>
-
-2023-11-13 16:14:07 +0200  Sebastian Dröge <sebastian@centricular.com>
-
-	* libs/gst/net/gstptpclock.c:
-	* libs/gst/net/gstptpclock.h:
-	  ptp: Add new gst_ptp_init_full()
-	  This takes a free-form GstStructure as parameter that allows to easily
-	  extend it with new configuration at a later time without having to add
-	  new API.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5649>
-
-2023-11-15 10:03:52 +0000  Daniel Moberg <daniemob@axis.com>
-
-	* gst/gstpad.c:
-	  gstpad: Recheck pads when linking after temporary unlock
-	  This commit makes sure that pads are valid for linking
-	  after the pads has been temporarily unlocked in the linking process.
-	  Not doing this opens up for a race condition where
-	  pads potentially can be linked twice.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5670>
-
-2023-10-31 16:22:20 +0000  Philippe Normand <philn@igalia.com>
-
-	* gst/gststreamcollection.c:
-	  streamcollection: Fixup doc blurbs
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5605>
-
-2023-11-05 16:13:10 +0100  Fabian Orccon <cfoch.fabian@gmail.com>
-
-	* tools/gst-inspect.c:
-	  gst-inspect: Remove current caps print
-	  At GST_STATE_NULL, all pads are deactivated and have no caps.
-	  It can be observed with `gst-inspect-1.0 -a` that no element
-	  is reaching this removed code.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5604>
-
-2023-09-18 14:38:23 -0400  Xavier Claessens <xavier.claessens@collabora.com>
-
-	* gst/gstallocator.c:
-	* gst/gstallocator.h:
-	  GstAllocator: Add GST_ALLOCATOR_FLAG_NO_COPY flag
-	  Detail a bit the intention behind GST_ALLOCATOR_FLAG_CUSTOM_ALLOC, even
-	  if implementation does not currently fully follow that usage. Introduce
-	  a new flag specifically for copying memories using the default system
-	  allocator.
-	  Sponsored-by: Netflix Inc.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5328>
-
-2023-11-02 00:03:28 +0900  Seungha Yang <seungha@centricular.com>
-
-	* meson.build:
-	  meson: Fix MSVC build with GST_DISABLE_GST_DEBUG
-	  MSVC does not understand Wno-unused
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5585>
-
-2023-11-01 16:24:21 +0200  Sebastian Dröge <sebastian@centricular.com>
-
-	* libs/gst/helpers/ptp/ffi.rs:
-	* libs/gst/helpers/ptp/main.rs:
-	* libs/gst/helpers/ptp/net.rs:
-	  ptp: Use SO_BINDTOIFINDEX / SO_BINDTODEVICE on Linux
-	  This makes sure we really really really only get packets from the
-	  desired interface as passing a device to IP_ADD_MEMBERSHIP apparently
-	  does not have this effect alone.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5584>
-
-2023-10-28 08:10:48 +0200  Fabian Orccon <cfoch.fabian@gmail.com>
-
-	* tools/gst-inspect.c:
-	  gst-inspect: Do not check for element clock
-	  Clock is only set at GST_PLAYING state, not the case for gst-inspect
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5570>
-
-2023-11-01 14:21:05 +0200  Sebastian Dröge <sebastian@centricular.com>
-
-	* libs/gst/net/gstptpclock.c:
-	  ptp: Check once a second for timeouts
-	  While the minimum timeout duration is 5s, checking only every 5s means
-	  that we would notice this 4.9s too late in the worst case.
-	  Checking once a second reduces this considerably while keeping the
-	  number of wakeups still low.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5520>
-
-2023-10-30 16:24:23 +0200  Sebastian Dröge <sebastian@centricular.com>
-
-	* libs/gst/net/gstptpclock.c:
-	  ptp: Only warn if the clock id and interface of a timed out matches the current one
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5520>
-
-2023-10-25 13:33:39 +0300  Sebastian Dröge <sebastian@centricular.com>
-
-	* libs/gst/net/gstptpclock.c:
-	  ptp: Only time out SYNCs if we're actually waiting for a FOLLOW_UP
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5520>
-
-2023-10-20 14:25:27 +0300  Sebastian Dröge <sebastian@centricular.com>
-
-	* libs/gst/net/gstptpclock.c:
-	  ptp: Downgrade clocks that don't send FOLLOW_UPs / DELAY_RESPs
-	  This allows to select a different clock if there is one that is
-	  for the same grandmaster clock and has fewer timeouts.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5520>
-
-2023-10-20 14:20:45 +0300  Sebastian Dröge <sebastian@centricular.com>
-
-	* libs/gst/net/gstptpclock.c:
-	  ptp: Don't switch domain's master clock if it is equivalent to the previous one
-	  Otherwise it can happen that we regularly switch back and forth between
-	  clocks under certain circumstances for no good reason.
-	  Also remove redundant comparison when comparing the steps removed between two
-	  clocks.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5520>
-
-2023-10-16 20:53:49 +0000  robert <robert.ayrapetyan@gmail.com>
-
-	* docs/gst/running.md:
-	  ximagesrc: fix compile-time warning and XInitThreads()
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5493>
-
-2023-10-27 09:59:03 -0400  Nicolas Dufresne <nicolas.dufresne@collabora.com>
-
-	* tests/check/gstreamer.supp:
-	  valgrind: Use frame-level widlcard for getaddrinfo leak
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5565>
-
-2023-10-26 15:03:22 +0100  Tim-Philipp Müller <tim@centricular.com>
-
-	* tests/misc/network-clock-utils.scm:
-	* tests/misc/network-clock.scm:
-	  gstreamer: misc: relicense network-clock scheme files to LGPL v2.1+
-	  Permission to relicense granted by author by e-mail:
-	  Message-Id: <155C6D51-7F74-4C40-814A-2ADDED7707FD@pobox.com>
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5559>
-
-2023-10-26 14:35:33 -0400  Nicolas Dufresne <nicolas.dufresne@collabora.com>
-
-	* tests/check/gstreamer.supp:
-	  valgrind: Add getaddrinfo leak suppression
-	  With Fedora 34 in our CI, we start seeing a sometime leak in getaddrinfo. At
-	  first sight it looks like some TLS context being leaked. Could be a thread
-	  teardown leak, just suppress it for now.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5562>
-
-2023-10-25 13:58:55 +0100  Philippe Normand <philn@igalia.com>
-
-	* gst/gstdebugutils.c:
-	  debugutils: Ensure we always expose a bin_to_dot_data implementation
-	  Fixes a linking issue when building with `-Dgst_debug=false`.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5550>
-
-2023-10-25 00:40:22 +0900  Seungha Yang <seungha@centricular.com>
-
-	* gst/gstpluginloader-win32.c:
-	  pluginloader-win32: Increase plugin loading timeout
-	  Some hardware plugin loading might take more than 10sec under
-	  full CPU load condition
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5545>
-
-2023-10-19 19:44:21 +0300  Sebastian Dröge <sebastian@centricular.com>
-
-	* libs/gst/base/gstaggregator.c:
-	  aggregator: Allow passing unparented pads to gst_aggregator_pad_is_inactive()
-	  It's very difficult to ensure that a pad is still child of the
-	  aggregator during aggregation, so simply consider unparented pads as
-	  inactive instead of asserting.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5510>
-
-2023-10-19 19:43:26 +0300  Sebastian Dröge <sebastian@centricular.com>
-
-	* libs/gst/base/gstaggregator.c:
-	  aggregator: Also release clipped buffer when releasing an aggregator pad
-	  Instead of waiting until the pad is actually finalized.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5510>
-
-2023-10-19 19:43:26 +0300  Sebastian Dröge <sebastian@centricular.com>
-
-	* libs/gst/base/gstaggregator.c:
-	  aggregator: Take pad lock while releasing buffers when removing pads
-	  Accessing the buffers in all other places requires the pad lock and not
-	  taking it here can cause access to already freed buffers if there's
-	  concurrent access from another thread.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5510>
-
-2022-04-06 12:56:30 +0100  Tim-Philipp Müller <tim@centricular.com>
-
-	* gst/gstbus.c:
-	* meson.build:
-	  meson: Bump GLib requirement to >= 2.64
-	  This includes fixes to make GstBus watches non-racy.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/2126>
-
-2023-10-19 14:10:16 +0200  Loïc Le Page <llepage@igalia.com>
-
-	* docs/gst/running.md:
-	* docs/index.md:
-	  gl: add support for surfaceless display in GstGL
-	  Use of the EGL_MESA_platform_surfaceless EGL extension to create an EGL
-	  display that is not depending on any kind of windowing system.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5511>
-
-2023-10-05 23:18:53 +0900  Seungha Yang <seungha@centricular.com>
-
-	* tests/check/elements/multiqueue.c:
-	  tests: multiqueue: Add overrun test case
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5430>
-
-2023-10-05 22:40:43 +0900  Seungha Yang <seungha@centricular.com>
-
-	* plugins/elements/gstmultiqueue.c:
-	  multiqueue: Do not update time level on segment
-	  Update time level decision logic to be identical to the queue/queue2
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5430>
-
-2023-10-03 17:38:18 +0900  Seungha Yang <seungha@centricular.com>
-
-	* tests/check/elements/queue.c:
-	* tests/check/elements/queue2.c:
-	  tests: queue, queue2: Add more timelevel test
-	  ... and update existing testcases for new timelevel measuring logic
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5430>
-
-2023-10-03 02:05:23 +0900  Seungha Yang <seungha@centricular.com>
-
-	* plugins/elements/gstqueue.c:
-	* plugins/elements/gstqueue.h:
-	* plugins/elements/gstqueue2.c:
-	* plugins/elements/gstqueue2.h:
-	  queue, queue2: Fix current-level-time report
-	  Do not update timelevel on segment. Segment itself does not tell
-	  anything about the amount of buffered time duration in the element
-	  but buffer timestamp/duration is required to measure actual bufferred time.
-	  Moreover, at the time when new segment is applied to sink/srcpad,
-	  segment.position would point to random value.
-	  Therefore calculating running time using the random value does not
-	  make sense and it will result in wrong timelevel report.
-	  This patch updates queue/queue2's timelevel measuring logic so that
-	  it can be updated only on buffer/buffer-list/gap-event flow.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5430>
-
-2023-10-06 13:39:34 +0300  Sebastian Dröge <sebastian@centricular.com>
-
-	* libs/gst/helpers/ptp/io.rs:
-	  ptp: Fix a couple of stylistic clippy warnings
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5441>
-
-2023-09-04 14:02:25 +0200  Alexander Slobodeniuk <aslobodeniuk@fluendo.com>
-
-	* libs/gst/base/gstaggregator.c:
-	  aggregator: fix start-time-selection=first on negative rate
-	  When the property "start-time-selection" is set to "first", it
-	  calculates the start time of the output from the buffer pts
-	  (converting it to running time of the segment), but if the
-	  rate is negative, the real start is not the pts, but the
-	  pts + duration, because it plays from the end of the buffer
-	  to it's start.
-	  As a result of this bug, in the negative rate, when the
-	  start-time-selection=first, the first frame is dropped
-	  by the videoaggregator (reproduced on d3d11compositor).
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5276>
-
-2023-09-27 16:59:34 +0200  François Laignel <francois@centricular.com>
-
-	* tools/gst-inspect.c:
-	  tools: gst-inspect: add specific messages for CONSTRUCT_ONLY params
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5407>
-
-2023-09-27 08:46:35 -0400  Xavier Claessens <xavier.claessens@collabora.com>
-
-	* libs/gst/base/gstaggregator.c:
-	  GstCustomMeta: Use simplified API where possible
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5385>
-
-2023-09-23 13:12:57 -0400  Xavier Claessens <xavier.claessens@collabora.com>
-
-	* gst/gstmeta.c:
-	* gst/gstmeta.h:
-	  GstCustomMeta: simplify API
-	  Move the GstStructure field into public struct for direct access, that's
-	  easier than having to call a function to get it. It is not an API/ABI
-	  breakage to extend the public structure of a GstMeta because they are
-	  always allocated by inside GStreamer. The structure is exposed already
-	  by gst_custom_meta_get_structure() which does not return a copy/ref, so
-	  it is locked into holding a GstStructure forever anyway.
-	  Also add gst_meta_register_custom_simple() because most of the time only
-	  a name is required, tags and transform functions are more niche
-	  use-case.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5385>
-
-2023-09-20 09:49:27 +0200  Ruben Gonzalez <rgonzalez@fluendo.com>
-
-	* gst/gstutils.h:
-	  gstutils: Delete extra semicolon
-	  Warning reported by GCC with -Wpedantic: ISO C does not allow extra
-	  ‘;’ outside of a function.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5359>
-
-2023-08-01 17:08:39 -0400  Nicolas Dufresne <nicolas.dufresne@collabora.com>
-
-	* libs/gst/base/gstbasesrc.c:
-	  basesrc: Delay unlocking so we can hold the STREAM_LOCK
-	  unlock_stop() is expected to be run while the streaming thread is idle. To
-	  guaranty this is the case, we should take the streamlock, but its not
-	  possible to take this lock during state transitions from PAUSED to
-	  PLAYING as the wait function that we want to terminate is holding it.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4961>
-
-2023-08-01 16:52:28 -0400  Nicolas Dufresne <nicolas.dufresne@collabora.com>
-
-	* libs/gst/base/gstbasesrc.c:
-	  basesrc: Retry create() if we are back from pause
-	  After a create() call, which may have returned FLUSHING or a filled buffer,
-	  if it possible that we detect that we are now in pause. As live sourced
-	  don't produce data in pause, drop the buffer is any and later retry creating
-	  a buffer. This will ensure that we resume from pause while avoiding displaying
-	  ancient frame.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4961>
-
-2023-07-03 11:48:57 -0400  soak <oakasanj@yahoo.com>
-
-	* libs/gst/base/gstbasesrc.c:
-	  basesrc: Restore pause/resume in derived classes
-	  When the pipeline goes from Playing to Paused, this change will invoke
-	  unlock in the derived class. When the pipeline goes from Paused to
-	  Playing, this change will invoke unlock_stop in the derived class.
-	  This feature was removed in commit 523de1a9 and is now being restored.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4961>
-
-2023-07-12 02:43:18 +0900  Seungha Yang <seungha@centricular.com>
-
-	* plugins/elements/gstqueue.c:
-	* plugins/elements/gstqueue2.c:
-	* tests/check/elements/queue.c:
-	* tests/check/elements/queue2.c:
-	  queue, queue2: Flush internal queue on flow error
-	  This is to fix an infinitely blocked upstream streaming thread if
-	  * upstream has fixed-size buffer pool, some H/W decoders for example
-	  * downstream returned flow error without releasing buffer
-	  When the fixed-size buffer pool hits its configured max-buffers and
-	  also downstream of queue returned flow error without releasing corresponding
-	  buffer, upstream has no chance to run the next processing loop
-	  because it will be blocked by acquire_buffer(), and therefore
-	  downstream flow will not be propagated to upstream.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5023>
-
-2023-08-31 09:04:05 +0300  Sebastian Dröge <sebastian@centricular.com>
-
-	* libs/gst/helpers/ptp/io.rs:
-	* libs/gst/helpers/ptp/main.rs:
-	  ptp: Fix compilation with rustc 1.48
-	  That's currently the minimum version we declare in meson.build but the
-	  latest changes introduced some usage of 1.62 features.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5265>
-
-2023-08-23 19:21:37 +0300  Sebastian Dröge <sebastian@centricular.com>
-
-	* libs/gst/helpers/ptp/ffi.rs:
-	* libs/gst/helpers/ptp/io.rs:
-	* libs/gst/helpers/ptp/main.rs:
-	* libs/gst/helpers/ptp/net.rs:
-	* libs/gst/net/gstptpclock.c:
-	  ptp: Listen with different sockets on individual interfaces
-	  This allows us to portably know on which interface a multicast packet
-	  arrived, and to send back any packets for that clock on the correct
-	  interface.
-	  Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/2728
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5232>
-
-2023-02-10 13:04:26 -0500  Olivier Crête <olivier.crete@collabora.com>
-
-	* tools/gst-stats.c:
-	  gst-stats: Add argument for a custom regexp
-	  This is to use gst-stats against GStreamer logs that went through
-	  some other logging system.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3935>
-
-2023-08-15 16:01:28 +0200  Piotr Brzeziński <piotr@centricular.com>
-
-	* tools/gst-launch.c:
-	  tools: Disable fault signal handlers in gst-launch/gst-validate on macOS
-	  By default, macOS attempts to run lldb against a misbehaving process to handle the crash. This does not play well
-	  with the SISEGV/SIGQUIT handler we add in gst-launch/gst-validate. The 'spinning' mechanism causes the lldb
-	  and debugserver processes ran by macOS to misbehave, taking 100% CPU and rendering both themselves and the GStreamer
-	  instance frozen and very hard to effectively kill. macOS's Activity Monitor is also unusable while this is happening.
-	  This patch takes the quickest possible solution of just disabling those signal handlers entirely on macOS.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5190>
-
-2023-07-27 13:32:48 +0200  Piotr Brzeziński <piotr@centricular.com>
-
-	* libs/gst/base/gstqueuearray.c:
-	* libs/gst/base/gstqueuearray.h:
-	* tests/check/libs/queuearray.c:
-	  queuearray: Add sorting and sorted pushing
-	  Adds gst_queue_array_sort for sorting and gst_queue_array_push_sorted{,struct} for pushing in a sorted order.
-	  All three functions accept a comparison GCompareDataFunc along with optional user_data to pass to it.
-	  In gst_queue_array_sort a small workaround was needed to correctly sort non-struct arrays. Like what _find() already
-	  does, we need to dereference our pointers first, to make sure we can use the same comparison functions everywhere.
-	  This is done via a small wrapper around the provided comparison function.
-	  The array can also wrap around (tail ends up 'before' the head), in which case we have to reorder the array (similar to
-	  what do_expand() does) to then be able to use an existing sorting function, like g_qsort_with_data().
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5112>
-
-2023-07-27 16:42:51 +1000  Matthew Waters <matthew@centricular.com>
-
-	* gst/parse/grammar.y.in:
-	  parse: avoid -Werror=unused-but-set-variable
-	  bison seems to generate a yyparse() with one unsed but set variable in it.
-	  Avoid that.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5110>
-
-2023-07-17 15:18:39 +0100  Philippe Normand <philn@igalia.com>
-
-	* gst/gstquery.c:
-	  query: Add a quark for SELECTABLE query type
-	  So that `gst_query_type_get_name()` won't return "unknown" for this type.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5048>
-
-2023-07-05 18:46:25 -0600  Olivier Crête <olivier.crete@collabora.com>
-
-	* scripts/gen-changelog.py:
-	* scripts/git-version.sh:
-	  gst-omx: Retire the whole package
-	  The OpenMAX standard is long dead and even the Raspberry Pi OS
-	  no longer supports it.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4976>
-
-2023-07-12 09:27:22 +0530  Nirbheek Chauhan <nirbheek@centricular.com>
-
-	* tests/check/meson.build:
-	  meson: Always use forward slashes in defines with paths
-	  Fixes the following build failure on MSYS2:
-	  ```
-	  ../subprojects/gstreamer/tests/check/elements/filesrc.c: In function 'test_seeking':
-	  ../subprojects/gstreamer/tests/check/elements/filesrc.c:107:53: error: incomplete universal character name \U
-	  107 |   g_object_set (G_OBJECT (src), "location", TESTFILE, NULL);
-	  |                                                     ^
-	  ../subprojects/gstreamer/tests/check/elements/filesrc.c:107:53: warning: unknown escape sequence: '\A'
-	  ../subprojects/gstreamer/tests/check/elements/filesrc.c:107:53: warning: unknown escape sequence: '\g'
-	  ../subprojects/gstreamer/tests/check/elements/filesrc.c:107:53: warning: unknown escape sequence: '\s'
-	  ../subprojects/gstreamer/tests/check/elements/filesrc.c:107:53: warning: unknown escape sequence: '\g'
-	  ../subprojects/gstreamer/tests/check/elements/filesrc.c:107:53: warning: unknown escape sequence: '\c'
-	  ```
-	  Due to: `-DTESTFILE=\"C:\\Users\\Administrator\[...]`
-	  https://gitlab.freedesktop.org/nirbheek/gstreamer/-/jobs/45317733
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5018>
-
-2023-07-11 23:24:41 +0200  Alicia Boya García <aboya@igalia.com>
-
-	* docs/meson.build:
-	* libs/gst/check/gstharness.c:
-	* libs/gst/check/gstharnesslink.c:
-	* libs/gst/check/gstharnesslink.h:
-	* libs/gst/check/meson.build:
-	  harness: Fix race condition when torn down during the handling of a non-serialized query or event
-	  It's possible and normal to tear down a harness while the pipeline is
-	  running. At the same time, it's desired for the
-	  `gst_harness_pad_link_tear_down()` function to be synchronous.
-	  This has created the conflict where the main thread may request a
-	  harness to be torn down while it's in use or about to be used by a pad
-	  in the streaming thread.
-	  The previous implementation of `gst_harness_pad_link_tear_down()` tried
-	  to handle this by taking the stream lock of the harnessed pad and
-	  resetting all the pad functions while holding it. That approach was
-	  however insufficient to handle the case where a non-serialized event
-	  or query is being handled or about to be handled in a different thread.
-	  This edge case was one race condition behind the flakes in the flvmux
-	  check tests -- the rest being covered by https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/2803.
-	  This patch fixes the problem by adding an intermediate ref-counted
-	  object, GstHarnessLink, which replaces the usage of the HARNESS_KEY
-	  association. GstHarnessLink allows the pad functions such as event,
-	  query and chain to borrow a reference to GstHarness and more
-	  importantly, to lock the GstHarnessLink during their usage to block
-	  (delay) its destruction until no users are left, and guarantee that any
-	  future user will not receive an invalid GstHarness handle past its
-	  destruction.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5017>
-
-2023-07-06 18:08:57 +0200  Théo Maillart <tmaillart@freebox.fr>
-
-	* plugins/elements/gstinputselector.c:
-	  inputselector: fix playing variable is never set
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4983>
-
-2023-07-05 16:50:07 +0200  Andoni Morales Alastruey <ylatuya@gmail.com>
-
-	* plugins/tracers/gstleaks.c:
-	  leaks: add unix signals documentation
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4973>
-
-2023-07-01 00:33:56 +1000  Jan Schmidt <jan@centricular.com>
-
-	* libs/gst/base/gstbasesrc.c:
-	  basesrc: Don't hold the object lock while pushing an event
-	  Release the object lock before pushing a segment event.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4951>
-
-2023-06-26 11:53:47 +0200  Alicia Boya García <aboya@igalia.com>
-
-	* tests/validate/meson.build:
-	  validate tests: include debugutilsbad to be able to use testsrcbin
-	  Fixes test: validate.uridecodebin.expose_raw_pad_caps
-	  testsrcbin (currently part of debugutilsbad) is an useful element for
-	  validate tests.
-	  validate.uridecodebin.expose_raw_pad_caps makes use of it.
-	  Unfortunately, because validate tests with GStreamer only run with
-	  whitelisted plugins and `debugutilsbad` wasn't in the whitelist, the
-	  test was failing and being auto-skipped.
-	  This patch adds debugutilsbad to the whitelists used by validate tests
-	  in subprojects with a validate/meson.build.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4931>
-
-2023-06-26 12:56:26 +0200  Víctor Manuel Jáquez Leal <vjaquez@igalia.com>
-
-	* gst/gstcaps.c:
-	  caps: Fix documentation
-	  Fix gst_caps_filter_and_map_in_place() documentation, aiming to
-	  gst_caps_maps_in_place() to express their difference.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4933>
-
-2023-06-22 15:39:20 +0200  Alicia Boya García <aboya@igalia.com>
-
-	* gst/gsttask.c:
-	  task: Log task states as string
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4913>
-
-2023-06-21 13:44:40 +0200  Edward Hervey <edward@centricular.com>
-
-	* gst/gststreamcollection.c:
-	  streamcollection: Use upstream-id as name
-	  It is more coherent, in the same vein as  08dc5d29
-	  Fixes #2640
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4911>
-
-2023-06-21 01:20:18 +0900  Seungha Yang <seungha@centricular.com>
-
-	* gst/gst.c:
-	* libs/gst/net/gstptpclock.c:
-	  gst: Don't use DllMain in case of static build
-	  That might cause duplicated symbol linking error if app has its own
-	  DllMain
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4905>
-
-2023-06-13 21:53:29 +0900  Seungha Yang <seungha@centricular.com>
-
-	* libs/gst/base/gstaggregator.c:
-	  aggregator: Resume srcpad task on stream-start only when running
-	  Race condition without this patch:
-	  - srcpad task is being stopped in gst_aggregator_stop_srcpad_task()
-	  - at that moment, in pre-queue event handler, gst_pad_get_task_state()
-	  returned GST_TASK_PAUSED
-	  - then in srcpad task got stopped in gst_aggregator_stop_srcpad_task()
-	  - finally srcpad task got resumed in pre-queue event handler
-	  To address it, checks "running" flag in pre-queue event handler.
-	  Both pre-queue stream-start event handler and "running" flag
-	  are protected by SRC_LOCK already.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4847>
-
-2023-06-09 17:51:28 +0800  Elliot Chen <elliot.chen@nxp.com>
-
-	* libs/gst/base/gsttypefindhelper.c:
-	  typefindhelper: avoid printing error log
-	  some plugins such as wavparse may need find if type of media
-	  contained in the given data and will print error log if there
-	  is no matching factory.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4814>
-
-2023-06-08 09:35:44 +0200  Jochen Henneberg <jh@henneberg-systemdesign.com>
-
-	* libs/gst/net/gstnetclientclock.c:
-	  netclientclock: Handle time server reset correctly
-	  If the time server is restarted with a time in the past the net client
-	  clock will not report the new time anymore as this would mean that the
-	  clock moves back in time which it does not do.
-	  Now the clock will be kept alive but marked as corrupted and will not
-	  be re-used from the cache.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4802>
-
-2023-02-16 13:44:50 +0100  Guillaume Desmottes <guillaume.desmottes@onestream.live>
-
-	* gst/gsttracerutils.c:
-	  tracerutils: allow casting parameters types
-	  It was impossible to have an u32 parameter such as
-	  'max-buffer-size=(uint)5' because the parentheses were not properly
-	  parsed.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3981>
-
-2023-03-13 19:42:23 +0100  Ruben Gonzalez <rgonzalez@fluendo.com>
-
-	* docs/gst/running.md:
-	* docs/index.md:
-	  doc: Add %p and %r patters for GST_DEBUG_FILE
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4166>
-
-2023-06-05 12:21:22 -0400  Nicolas Dufresne <nicolas.dufresne@collabora.com>
-
-	* gst/gstvalue.c:
-	* tests/check/gst/gstvalue.c:
-	  flagset: Fail parsing on overflowing hex strings
-	  This adds code to detect when the hex form of the string we are to
-	  parse exceeds the number of bytes that would form a 32bit flag. This will
-	  avoid treating as flagset anything above then the expected 32 bits and also
-	  stop treading DRM format with modifiers as flagset (like
-	  drm-format=AB24:0x0100000000000002).
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4775>
-
-2023-06-06 03:03:07 +0900  Seungha Yang <seungha@centricular.com>
-
-	* libs/gst/base/gstaggregator.c:
-	  aggregator: Restart srcpad task on stream-start
-	  Re-start srcpad task on stream-start in addition to flush event
-	  so that subclass can process data when new pad is added
-	  after EOS or an input stream is started again with stream-start event
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4783>
-
-2023-06-08 20:52:21 +0900  Seungha Yang <seungha@centricular.com>
-
-	* plugins/elements/gstelements_private.c:
-	* tests/check/elements/filesink.c:
-	  filesink: Fix buffered mode writing
-	  Fixing miscalculated buffer index when a buffer holds multiple
-	  memories and it's not aligned to the vector size 16
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4809>
-
-2023-06-08 13:40:47 +0300  Sebastian Dröge <sebastian@centricular.com>
-
-	* libs/gst/helpers/ptp/ffi.rs:
-	* libs/gst/helpers/ptp/main.rs:
-	* libs/gst/helpers/ptp/net.rs:
-	  ptp: Set port-reuse socket options before binding the socket
-	  Otherwise it only works if GStreamer is binding the first socket on this
-	  port.
-	  Unfortunately this requires duplicating a bit more of Rust std because
-	  `UdpSocket` can only be created already bound without allowing to set
-	  any options between socket creation and binding.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4807>
-
-2023-06-08 13:51:57 +0300  Sebastian Dröge <sebastian@centricular.com>
-
-	* libs/gst/helpers/ptp/args.rs:
-	  ptp: Correctly parse clock ID from the commandline parameters in the helper
-	  Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/2652
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4806>
-
-2023-06-07 08:51:09 +0200  Philippe Normand <philn@igalia.com>
-
-	* gst/gstutils.c:
-	  utils: Fix doc warnings in gst_utils_simplify_fraction
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4793>
-
-2023-06-07 23:10:47 +0900  Seungha Yang <seungha@centricular.com>
-
-	* gst/gstsystemclock.c:
-	  systemclock: Use Windows interlocked APIs
-	  MSVC most likely does not support C11 atomic operations
-	  with given compile options
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4794>
-
-2023-06-07 20:24:43 +0900  Seungha Yang <seungha@centricular.com>
-
-	* gst/gst.c:
-	* gst/gstutils.c:
-	  gst: Call priv_gst_clock_init() on DllMain
-	  Can avoid atomic read per gst_util_get_timestamp() call
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4794>
-
-2023-06-06 20:44:02 +0900  Seungha Yang <seungha@centricular.com>
-
-	* tests/check/libs/basesink.c:
-	  tests: basesink: Add STREAM-START after EOS test
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4782>
-
-2023-06-06 04:42:05 +0900  Seungha Yang <seungha@centricular.com>
-
-	* libs/gst/base/gstbasesink.c:
-	  basesink: Clear EOS flag on STREAM-START event
-	  EOS -> STREAM-START -> new data flow is valid scenario
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4782>
-
-2023-06-06 10:54:36 +0200  Stéphane Cerveau <scerveau@igalia.com>
-
-	* gst/gst.c:
-	  gstreamer-full: keep g_module_symbol to init plugins
-	  In Android use case, the flag GST_FULL_COMPILATION
-	  is not defined whereas the plugins need to be
-	  initialized using 'gst_init_static_plugins'
-	  method.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4777>
-
-2023-06-05 20:17:40 +0900  Seungha Yang <seungha@centricular.com>
-
-	* plugins/elements/gstclocksync.c:
-	  clocksync: Fix deadlock because of taken stream lock on flush-start
-	  Deadlock happens when streaming thread is already blocked by downstream
-	  and clocksync is trying to take stream lock on flush-start.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4772>
-
-2023-06-01 14:49:06 +0530  Nirbheek Chauhan <nirbheek@centricular.com>
-
-	* gst/gstinfo.c:
-	  docs: Use backticks to escape * in markdown
-	  Otherwise it's interpreted as emphasis.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4753>
-
-2023-03-08 01:09:42 +0100  Michael Grzeschik <m.grzeschik@pengutronix.de>
-
-	* gst/gstutils.c:
-	* gst/gstutils.h:
-	  gstreamer: gst-utils: add gst_util_simplify_fraction
-	  We add the gst_util_simplify_fraction function to be able to convert
-	  fractions such as 333333/10000000 to 1/30.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/1304>
-
-2023-03-23 13:03:18 +0100  Stéphane Cerveau <scerveau@igalia.com>
-
-	* gst/meson.build:
-	  gstreamer-full: add GST_STATIC_COMPILATION for Windows
-	  In the case of a gstreamer-full target type to static,
-	  the GST_STATIC_COMPILATION is necessary on Windows to avoid
-	  a different mangling from the external project using the
-	  gstreamer-full libraries (ie dllimport).
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4128>
-
-2023-03-16 09:39:27 +0100  Stéphane Cerveau <scerveau@igalia.com>
-
-	* libs/gst/helpers/meson.build:
-	  gstreamer-full: helpers built as tools
-	  gst-plugin-scanner and gst-completion-helper
-	  are now built part of the helpers as tools.
-	  Add libraries to the summary to know
-	  what library will be built and can be exposed
-	  by gstreamer-full
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4128>
-
-2023-03-07 14:05:54 +0100  Stéphane Cerveau <scerveau@igalia.com>
-
-	* gst/gst.c:
-	* gst/meson.build:
-	* meson.build:
-	* meson_options.txt:
-	* tests/meson.build:
-	* tools/meson.build:
-	  gstreamer-full: add full static support
-	  Allow a project to use gstreamer-full as a static library
-	  and link to create a binary without dependencies.
-	  Introduce the option 'gst-full-target-type' to
-	  select the build type, dynamic(default) or static.
-	  In gstreamer-full/static build configuration gstreamer (gst.c)
-	  needs the symbol gst_init_static_plugins which is defined
-	  in gstreamer-full.
-	  All the tests and examples are linking with gstreamer but the
-	  symbol gst_init_static_plugins is only defined in the gstreamer-full
-	  library. gstreamer-full can not be built first as it needs to know what plugins
-	  will be built.
-	  One option would be to build all the examples and tests after
-	  gstreamer-full as the tools.
-	  Disable tools build in subprojects too as it will be built at the end of
-	  build process.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4128>
-
-2023-05-31 13:15:13 +0300  Sebastian Dröge <sebastian@centricular.com>
-
-	* libs/gst/helpers/ptp/io.rs:
-	  ptp: On Windows handle socket polls that result in no error but also no FD_READ event
-	  According to the documentation this should never happen but apparently
-	  does under certain circumstances. As the sockets are set non-blocking,
-	  trying to read from them regardless should not cause any problems.
-	  In all cases that were observed so far, the socket in question actually
-	  has a packet queued up for reading.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4748>
-
-2023-05-19 09:49:17 +0300  Sebastian Dröge <sebastian@centricular.com>
-
-	* libs/gst/helpers/ptp/main.rs:
-	* libs/gst/helpers/ptp/parse.rs:
-	  ptp: Parse PTP messages in the helper process and filter earlier
-	  This drops invalid, unknown or uninteresting PTP messages in the helper
-	  process already instead of forwarding them to the main process.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4665>
-
-2023-05-21 12:45:50 +0300  Sebastian Dröge <sebastian@centricular.com>
-
-	* libs/gst/net/gstptpclock.c:
-	  ptp: Ignore DELAY_RESP messages not for us earlier in the main process
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4665>
-
-2023-05-21 12:45:14 +0300  Sebastian Dröge <sebastian@centricular.com>
-
-	* libs/gst/helpers/ptp/main.rs:
-	  ptp: Set UDP sockets as non-blocking
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4665>
-
-2023-05-18 13:59:10 +0300  Sebastian Dröge <sebastian@centricular.com>
-
-	* libs/gst/helpers/ptp/clock.rs:
-	* libs/gst/helpers/ptp/ffi.rs:
-	* libs/gst/helpers/ptp/main.rs:
-	* libs/gst/net/gstptpclock.c:
-	  ptp: Capture actual send/receive times in the helper process
-	  While this doesn't yet use any OS provided times from the actual network
-	  stack, this still gets rid of any IPC jitter between the helper process
-	  and the main process as part of the PTP time calculations and should
-	  improve accuracy.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4665>
-
-2023-05-17 14:44:24 +0300  Sebastian Dröge <sebastian@centricular.com>
-
-	* gst/gst.c:
-	* gst/gst_private.h:
-	* gst/gstsystemclock.c:
-	* gst/gstutils.c:
-	  gst: clock: Clean up code to get the monotonic / realtime clock a bit
-	  On Windows and macOS always use the proper monotonic clock, including
-	  for gst_util_get_timestamp(), and initialize its state only once.
-	  Also on macOS use clock_gettime() for the realtime clock, if available
-	  instead of always falling back to GLib.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4658>
-
-2023-05-17 10:01:30 +0300  Sebastian Dröge <sebastian@centricular.com>
-
-	* libs/gst/net/gstptpclock.c:
-	  ptp: Work around bug in ptpd in default configuration
-	  ptpd is defaulting to the hybrid mode, and was sending invalid multicast
-	  PTP messages in that configuration until ce96c742a88792a8d92deebaf03927e1b367f4a9.
-	  While this commit was made in 2015 there was no release in the meantime.
-	  Work around this by detecting this case and defaulting to the default
-	  values for the given intervals as given by the PTP standard.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4654>
-
-2023-05-19 09:47:06 +0300  Sebastian Dröge <sebastian@centricular.com>
-
-	* libs/gst/helpers/ptp/rand.rs:
-	  ptp: Fix compilation with Rust 1.48
-	  Use `ErrorKind::NotFound` instead of `ErrorKind::Unsupported` if the
-	  `getrandom` syscall is not available. `Unsupported` was added in 1.53.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4647>
-
-2023-05-16 14:53:24 +0300  Sebastian Dröge <sebastian@centricular.com>
-
-	* libs/gst/helpers/ptp/args.rs:
-	* libs/gst/helpers/ptp/ffi.rs:
-	* libs/gst/helpers/ptp/io.rs:
-	* libs/gst/helpers/ptp/log.rs:
-	* libs/gst/helpers/ptp/main.rs:
-	* libs/gst/helpers/ptp/net.rs:
-	* libs/gst/net/gstptpclock.c:
-	  ptp: Add logging between the helper process and the main process via stderr
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4647>
-
-2023-05-15 17:52:20 +0300  Sebastian Dröge <sebastian@centricular.com>
-
-	* libs/gst/net/gstptpclock.c:
-	  ptp: Add a working default branch to the message type switch
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4647>
-
-2023-05-15 17:44:31 +0300  Sebastian Dröge <sebastian@centricular.com>
-
-	* libs/gst/helpers/ptp/main.rs:
-	* libs/gst/net/gstptp_private.h:
-	* libs/gst/net/gstptpclock.c:
-	  ptp: Get rid of struct padding in the messages with the helper process
-	  Also remove the now unnecessary private header file.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4647>
-
-2023-05-17 22:58:46 +0200  Ruben Gonzalez <rgonzalez@fluendo.com>
-
-	* README.md:
-	  README.md: fix current version
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4662>
-
-2023-05-12 18:35:48 +0200  Mathieu Duponchelle <mathieu@centricular.com>
-
-	* gst/parse/grammar.y.in:
-	  parse/grammar: fix missing unref of looked up child
-	  the target parameter of gst_child_proxy_lookup() is (transfer full)
-	  Fixes: https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/2560
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4622>
-
-2023-04-20 10:32:43 +0300  Sebastian Dröge <sebastian@centricular.com>
-
-	* libs/gst/helpers/ptp/ffi.rs:
-	* libs/gst/helpers/ptp/io.rs:
-	* libs/gst/helpers/ptp/meson.build:
-	* libs/gst/helpers/ptp/net.rs:
-	* libs/gst/helpers/ptp/privileges.rs:
-	* libs/gst/helpers/ptp/rand.rs:
-	  ptp-helper: Add some tests for functionality and memory safety of unsafe code
-	  These tests are mostly for ensuring that the calls to system APIs are
-	  done correctly and that there are no memory bugs (that would be caught
-	  by valgrind) in the unsafe code.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4458>
-
-2023-04-03 13:51:38 +0100  Lukas Geiger <lukas.geiger94@gmail.com>
-
-	* gst/gstmacos.m:
-	  macos: Set activation policy in `gst_macos_main`
-	  Setting the policy to NSApplicationActivationPolicyAccessory by default makes
-	  sure that we can activate windows programmatically or by clicking on them.
-	  Without that, windows would disappear if you clicked outside them and there
-	  would be no way to bring them to front again. This change also allows osxvideosink
-	  to receive navigation events correctly.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4573>
-
-2023-05-07 01:06:26 +0200  Maxim P. DEMENTYEV <mdementyev@fluendo.com>
-
-	* gst/gstplugin.c:
-	  plugin ext dep INFO: Adding var name and value part number
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4570>
-
-2023-05-05 23:21:22 +0900  Seungha Yang <seungha@centricular.com>
-
-	* gst/gstpluginloader-win32.c:
-	* gst/meson.build:
-	  pluginloader-win32: Use UWP compatible Windows API
-	  CreateFile2 API should be used in case of UWP
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4556>
-
-2023-05-04 00:19:32 +0300  Sebastian Dröge <sebastian@centricular.com>
-
-	* gst/gstpluginloader.c:
-	  gstreamer: pluginloader: Remove unnecessary Windows special cases
-	  The Windows plugin loader is in a separate file.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4541>
-
-2023-05-04 00:17:47 +0300  Sebastian Dröge <sebastian@centricular.com>
-
-	* gst/gstpluginloader-win32.c:
-	* gst/gstpluginloader.c:
-	* libs/gst/net/gstptpclock.c:
-	  gstreamer: #undef a few local #defines after usage
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4541>
-
-2023-05-04 00:15:33 +0300  Sebastian Dröge <sebastian@centricular.com>
-
-	* libs/gst/net/gstptpclock.c:
-	  gstreamer: ptpclock: Remove unnecessary empty line
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4541>
-
-2023-05-04 00:14:29 +0300  Sebastian Dröge <sebastian@centricular.com>
-
-	* gst/gstregistry.c:
-	* libs/gst/net/gstptpclock.c:
-	  gstreamer: Fix minor memory leak in error path for internal path depth helper function
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4541>
-
-2023-05-03 19:15:53 +0300  Sebastian Dröge <sebastian@centricular.com>
-
-	* libs/gst/net/gstptpclock.c:
-	* libs/gst/net/meson.build:
-	* meson.build:
-	  ptp: Allow relocation of GStreamer installation for finding PTP helper process
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4538>
-
-2023-05-03 18:47:33 +0300  Sebastian Dröge <sebastian@centricular.com>
-
-	* gst/gst_private.h:
-	* gst/gstpluginloader-win32.c:
-	* gst/gstpluginloader.c:
-	* gst/gstregistry.c:
-	  gst: pluginloader: De-duplicate count_directories() private function
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4538>
-
-2023-04-29 12:16:09 +0100  Tim-Philipp Müller <tim@centricular.com>
-
-	* gst/gstpluginfeature.c:
-	* tests/check/gst/gstplugin.c:
-	  pluginfeature: fix unexpected version check behaviour for git versions
-	  check_version(1.23.1) would return TRUE for a git development version
-	  like 1.23.0.1, which is quite confusing and somewhat unexpected.
-	  We fixed this up in the version check macros already in !2501, so this
-	  updates the run-time check accordingly as well.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4513>
-
-2023-04-22 04:27:54 +0900  Seungha Yang <seungha@centricular.com>
-
-	* gst/gstsample.c:
-	* gst/gstsample.h:
-	  sample: Add gst_clear_sample() method
-	  Similar to other GstMiniObject clear helper methods like
-	  gst_clear_buffer().
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4473>
-
-2023-04-22 04:11:40 +0900  Seungha Yang <seungha@centricular.com>
-
-	* gst/gstsample.c:
-	* gst/gstsample.h:
-	  sample: Fix typo around gst_sample_copy() method
-	  It's sample, not buffer
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4473>
-
-2023-04-26 15:55:05 +0200  Guillaume Desmottes <guillaume.desmottes@onestream.live>
-
-	* gst/gstpad.c:
-	  core: pad: fully log event being pushed
-	  It's useful when debugging to check the details of the event being sent,
-	  like the segment for example.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4493>
-
-2023-03-19 15:35:29 -0300  Thibault Saunier <tsaunier@igalia.com>
-
-	* docs/gst-plugins-doc-cache-generator.py:
-	* docs/meson.build:
-	  doc: Avoid shelling out to hotdoc to generate plugins config files
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4479>
-
-2023-04-04 22:03:18 +0300  Jordan Petridis <jordan@centricular.com>
-
-	* tests/check/gst/gstinfo.c:
-	  build: appease clang warning
-	  Clang complains about these variables being (possibly) unitialized, even
-	  when they are assigned to NULL or proper value inside the macro.
-	  Might as well initialize them to avoid the warning.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4281>
-
-2022-08-31 14:15:16 -0400  Thibault Saunier <tsaunier@igalia.com>
-
-	* gst/meson.build:
-	* libs/gst/base/meson.build:
-	* libs/gst/check/meson.build:
-	* libs/gst/controller/meson.build:
-	* libs/gst/net/meson.build:
-	  gir: Checkout all .gir files and check that they are updated on the CI
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3010>
-
-2023-04-19 14:12:31 +0200  Ruben Gonzalez <rgonzalez@fluendo.com>
-
-	* gst/gst.c:
-	* po/it.po:
-	* tools/gst-inspect-1.0.1:
-	* tools/gst-launch-1.0.1:
-	* tools/gst-typefind-1.0.1:
-	  gst: Delete inoperative ARG_PLUGIN_SPEW
-	  Logic related with the option was deleted 20 years ago in commit:
-	  086de421dc
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4452>
-
-2023-04-11 21:23:00 +0200  badcel <33569-badcel@users.noreply.gitlab.gnome.org>
-
-	* libs/gst/base/gstadapter.c:
-	  base: adapter: Explicitly mark size parameter as input
-	  The generated gir file marks the size parameter as "out" by default.
-	  This is wrong in the context of a caller allocated buffer with a given size.
-	  Explicitly marking the size parameter as (in) fixes the issue.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4399>
-
-2023-04-13 15:38:54 +0300  Sebastian Dröge <sebastian@centricular.com>
-
-	* libs/gst/helpers/ptp/meson.build:
-	* meson_options.txt:
-	  ptp-helper: Add a feature option for the PTP support
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4410>
-
-2023-04-13 15:22:23 +0300  Sebastian Dröge <sebastian@centricular.com>
-
-	* libs/gst/helpers/ptp/meson.build:
-	  ptp-helper: Convert various meson message() to warning()
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4410>
-
-2023-04-13 15:21:20 +0300  Sebastian Dröge <sebastian@centricular.com>
-
-	* libs/gst/helpers/ptp/meson.build:
-	  ptp-helper: Don't check for a Rust compiler on unsupported platforms
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4410>
-
-2023-04-13 14:46:43 +0300  Sebastian Dröge <sebastian@centricular.com>
-
-	* libs/gst/helpers/ptp/meson.build:
-	  ptp-helper: Check for the required Rust toolchain version via meson
-	  If an older version is found that gives a more useful output than a
-	  compiler error at a later time.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4410>
-
-2023-04-12 22:39:58 +0900  Seungha Yang <seungha@centricular.com>
-
-	* gst/gstpluginloader-win32.c:
-	  pluginloader-win32: Fix for pipe connection error
-	  Don't error out on WAIT_IO_COMPLETION. It means queued APC job
-	  was executed but the job may not be our callback.
-	  For example, user or system might be able to schedule APC on
-	  gst_init() thread or so.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4405>
-
-2023-04-12 10:58:31 +0300  Sebastian Dröge <sebastian@centricular.com>
-
-	* gst/gst.c:
-	  gst: tracer: Initialize tracing infrastructure even if the debug system is not compiled in
-	  There is a separate #define for the tracing infrastructure.
-	  Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/2467
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4402>
-
-2023-04-10 13:49:41 +0100  Tim-Philipp Müller <tim@centricular.com>
-
-	* po/sr.po:
-	  gstreamer: update translations
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4388>
-
-2023-04-11 07:23:48 +0200  Edward Hervey <edward@centricular.com>
-
-	* libs/gst/base/gsttypefindhelper.c:
-	  typefindhelper: Avoid dead assignment
-	  Move variables within the loop (where they are actually used)
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4387>
-
-2023-03-31 23:15:30 +0300  Sebastian Dröge <sebastian@centricular.com>
-
-	* libs/gst/helpers/ptp/ffi.rs:
-	* libs/gst/helpers/ptp/ptp_helper_post_install.sh:
-	* libs/gst/helpers/ptp/thread.rs:
-	  ptp-helper: Set a process priority / nice value of -5 on UNIX platforms
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3889>
-
-2023-03-30 21:58:12 +0300  Sebastian Dröge <sebastian@centricular.com>
-
-	* libs/gst/helpers/ptp/ffi.rs:
-	* libs/gst/helpers/ptp/main.rs:
-	* libs/gst/helpers/ptp/thread.rs:
-	  ptp-helper: Set thread priority to time-critical on Windows
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3889>
-
-2023-02-04 00:55:39 +0200  Sebastian Dröge <sebastian@centricular.com>
-
-	* libs/gst/helpers/gst-ptp-helper.c:
-	* libs/gst/helpers/meson.build:
-	* libs/gst/helpers/ptp/args.rs:
-	* libs/gst/helpers/ptp/conf_lib.rs.in:
-	* libs/gst/helpers/ptp/error.rs:
-	* libs/gst/helpers/ptp/ffi.rs:
-	* libs/gst/helpers/ptp/io.rs:
-	* libs/gst/helpers/ptp/main.rs:
-	* libs/gst/helpers/ptp/meson.build:
-	* libs/gst/helpers/ptp/net.rs:
-	* libs/gst/helpers/ptp/privileges.rs:
-	* libs/gst/helpers/ptp/ptp_helper_post_install.sh:
-	* libs/gst/helpers/ptp/rand.rs:
-	  ptp-helper: Rewrite in Rust for portability and security
-	  This works on Linux, Android, Windows, macOS, FreeBSD, NetBSD, OpenBSD,
-	  DragonFlyBSD, Solaris and Illumos.
-	  Newly supported compared to the C version is Windows.
-	  Compared to the C version various error paths are handled more correctly
-	  and a couple of memory leaks are fixed. Otherwise it should work identically.
-	  The minimum required Rust version for compiling this is 1.48, i.e. the
-	  version currently in Debian stable. On Windows, Rust 1.54 is needed at
-	  least.
-	  Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/1259
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3889>
-
-2023-04-03 11:24:42 +0200  Guillaume Desmottes <guillaume.desmottes@onestream.live>
-
-	* libs/gst/base/gstbasesrc.c:
-	* libs/gst/base/gstbasesrc.h:
-	  basesrc: add gst_base_src_push_segment()
-	  gst_base_src_new_segment() does not send the segment right away, which
-	  may break events ordering if subclass sends other events after
-	  calling it.
-	  Introducing a variant pushing the segment right away to preserve
-	  ordering in such cases.
-	  Will be used by appsrc which has its own internal queue where we need to
-	  preserve events order.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4297>
-
-2021-05-06 14:07:35 +0200  Jan Alexander Steffens (heftig) <jan.steffens@ltnglobal.com>
-
-	* plugins/elements/gstmultiqueue.c:
-	  multiqueue: Simplify gst_multi_queue_iterate_internal_links
-	  We don't need to obtain the mutex to ensure that `sq` is non-NULL. `sq`
-	  is assigned immediately after the pads are created and not destroyed
-	  until the pads are finalized.
-	  Use the pad direction to determine which internal peer we need.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/888>
-
-2023-02-28 11:48:27 -0600  Michael Gruner <michael.gruner@ridgerun.com>
-
-	* gst/gstelement.c:
-	  gstelement: protect async state changes against spurious wake ups
-	  When a pipeline is pre-rolling, it waits for all sink elements to report
-	  they have received a buffer before completing the transition to paused.
-	  This async wait is done using a state condition variable. The way this
-	  waits are currently implemented do not protect against spurious conditional
-	  wake ups, which may happen due to external factors in the kernel.
-	  This change implements the wait within a loop that iterates over the protected
-	  variable to reinitiates the wait if the wakeup was spurious. More details in
-	  the [GCond docs](https://docs.gtk.org/glib/struct.Cond.html).
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4086>
-
-2023-03-28 19:58:30 +0100  Tim-Philipp Müller <tim@centricular.com>
-
-	* tools/gst-inspect.c:
-	  tools: gst-inspect: print action signals as emit_by_name() invocations
-	  It's quite confusing to print a function callback signature for
-	  action signals when people need to do a g_signal_by_name() invocation
-	  in order to use this feature. Requires too much background knowledge
-	  about how GObject works under the hood to make sense of that.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4299>
-
-2023-03-29 16:46:43 +0100  Tim-Philipp Müller <tim@centricular.com>
-
-	* tools/gst-inspect.c:
-	  tools: gst-inspect: prettify type names for strings
-	  'gchararray' and 'GStrv' are not types used anywhere else
-	  and are just confusing. Map that to 'const gchar *' and 'gchar *'
-	  etc. depending on context.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4299>
-
-2023-03-28 19:56:14 +0100  Tim-Philipp Müller <tim@centricular.com>
-
-	* tools/gst-inspect.c:
-	  tools: gst-inspect: add vertical spacing between properties and signals
-	  Makes it easier to read and less squashed.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4299>
-
-2023-03-31 04:40:58 +0900  Seungha Yang <seungha@centricular.com>
-
-	* tools/gst-inspect.c:
-	* tools/gst-launch.c:
-	* tools/gst-stats.c:
-	* tools/gst-typefind.c:
-	  tools: Count argc after parsing GOption on Windows
-	  Existing codes rely on modified argc value by g_option_context_parse()
-	  but g_option_context_parse_strv() is used in case of Windows.
-	  Count arguments after the option parsing manually.
-	  Fixing command "gst-inspect-1.0.exe -b"
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4313>
-
-2023-03-28 16:13:51 +0200  Juan Navarro <juan.navarro@gmx.es>
-
-	* gst/gstutils.c:
-	  gstutils: Add category and object to most logging messages
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4291>
-
-2023-03-24 18:34:36 +0200  Sebastian Dröge <sebastian@centricular.com>
-
-	* gst/gstdatetime.c:
-	  datetime: Return G_MAXFLOAT instead of G_MAXDOUBLE for no timezone offset
-	  Returning G_MAXDOUBLE from a function returning a float is not going to
-	  work well and MSVC also correctly warns about this.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4264>
-
-2023-03-26 16:40:28 +0100  Tim-Philipp Müller <tim@centricular.com>
-
-	* gst/gsttaglist.c:
-	  taglist, plugins: fix compiler warnings with GLib >= 2.76
-	  Fix compiler warnings about not using the return value when
-	  freeing the GString segment with g_string_free(.., FALSE):
-	  ignoring return value of ‘g_string_free_and_steal’ declared with attribute ‘warn_unused_result’
-	  which we get with newer GLib versions. These were all harmless.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4273>
-
-2023-03-22 14:40:32 +0100  Aleksandr Slobodeniuk <aslobodeniuk@fluendo.com>
-
-	* gst/gstbin.c:
-	  bin: fix documentation about event forwarding
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4249>
-
-2023-03-15 18:51:03 +0000  Tim-Philipp Müller <tim@centricular.com>
-
-	* docs/gst-hotdoc-plugins-scanner.c:
-	* gst/gstandroid.c:
-	* gst/gstclock.c:
-	* gst/gstcontrolbinding.c:
-	* gst/gstplugin.c:
-	* gst/gsttask.c:
-	* gst/gstutils.c:
-	* gst/printf/asnprintf.c:
-	* gst/printf/vasnprintf.c:
-	* libs/gst/base/gstcollectpads.c:
-	* libs/gst/check/libcheck/check_run.c:
-	* libs/gst/check/libcheck/libcompat/getline.c:
-	* libs/gst/controller/gstinterpolationcontrolsource.c:
-	* libs/gst/controller/gstlfocontrolsource.c:
-	* plugins/elements/gstinputselector.c:
-	* plugins/elements/gstqueue2.c:
-	* plugins/elements/gsttypefindelement.c:
-	* tests/check/elements/tee.c:
-	* tests/check/gst/gstdevice.c:
-	* tests/check/gst/gstutils.c:
-	* tests/check/gst/gstvalue.c:
-	* tools/gst-inspect.c:
-	  gstreamer: re-indent with GNU indent 2.2.12
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4182>
-
-2023-03-16 12:38:23 +0200  Vivia Nikolaidou <vivia@ahiru.eu>
-
-	* plugins/elements/gstinputselector.c:
-	  inputselector: Wake up streaming thread before PLAYING_TO_PAUSED transition
-	  Also take object lock before iterating the pads.
-	  https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/1772
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4190>
-
-2023-03-16 10:56:13 +0200  Sebastian Dröge <sebastian@centricular.com>
-
-	* tests/check/pipelines/parse-launch.c:
-	  parse: Add unit test for array parsing in capsfilters
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4181>
-
-2023-03-15 19:13:33 +0100  Mathieu Duponchelle <mathieu@centricular.com>
-
-	* gst/parse/grammar.y.in:
-	  parse: fix parsing arrays in caps for "implicit" capsfilters
-	  When using such a launch line:
-	  fakesrc ! "audio/x-opus, channel-mapping=(int)<0, 1>" ! fakesink
-	  the caps string, with spaces escaped but no quotes gets passed to
-	  gst_caps_from_string(), which then fails to parse the array because it
-	  contains spaces.
-	  When using an explicit capsfilter instead:
-	  fakesrc ! capsfilter caps="audio/x-opus, channel-mapping=(int)<0, 1>" ! fakesink
-	  the caps string, with spaces escaped and quotes gets passed through
-	  gst_value_deserialize, which first calls gst_str_unwrap() on it and only
-	  then gst_caps_from_string() on the result.
-	  This fixes the inconsistency by using a custom version of str_unwrap()
-	  in the parser, which doesn't expect a quoted string.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4181>
-
-2023-03-15 09:11:51 -0400  Xavier Claessens <xavier.claessens@collabora.com>
-
-	* gst/gstbuffer.c:
-	* tests/check/gst/gstbufferpool.c:
-	  gstbuffer: Add parent meta when a copy shares memory with parent
-	  When copying a buffer, for example with gst_buffer_make_writable(), the
-	  new buffer might reference the same GstMemory as the src buffer,
-	  making those memories not writable. If the src buffer gets disposed
-	  first it should return to its buffer pool, but since some of its
-	  memories are not writable it gets discarded and new buffer/memory gets
-	  allocated.
-	  Solves this by making the new buffer keep a reference to the src buffer,
-	  that ensures that by the time the src buffer gets disposed no other
-	  buffer are referencing its memories and it can thus return safely to its
-	  pool.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4176>
-
-2023-03-09 22:18:12 -0800  Xavier Claessens <xavier.claessens@collabora.com>
-
-	* gst/gstbuffer.c:
-	* tests/check/gst/gstbufferpool.c:
-	  gstbuffer: Unref memories before metas
-	  gst_buffer_add_parent_buffer_meta() is used when a GstBuffer uses
-	  GstMemory from another buffer that was allocated from a pool. In that
-	  case we want to make sure the buffer returns to the pool when the memory
-	  is writable again, otherwise a copy of the memory is created. That means
-	  the child buffer must drop its ref to the memory first, then drop the
-	  ref to parent buffer so it can return to the pool when it is the only
-	  owner of the memory.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4176>
-
-2023-02-15 13:10:25 -0500  Nicolas Dufresne <nicolas.dufresne@collabora.com>
-
-	* libs/gst/base/gstbasesink.c:
-	* libs/gst/base/gstbasesink.h:
-	  basesink: Add GST_BASE_SINK_FLOW_DROPPED return value
-	  This new flow return value can be used in ::render virtual method
-	  to signal that a frame is not being rendered.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3801>
-
-2023-03-10 20:45:35 +0100  Alicia Boya García <ntrrgc@gmail.com>
-
-	* plugins/tracers/gstlog.c:
-	  tracers: Document the 'log' tracer
-	  This patch adds documentation to the 'log' tracer and amends the design
-	  document of Tracers to replace a misleading example of the 'log' tracer
-	  with a different example that uses tracer arguments with tracers that do
-	  actually handle said arguments.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4153>
-
-2023-03-09 22:18:12 -0800  Xavier Claessens <xavier.claessens@collabora.com>
-
-	* gst/gstallocator.c:
-	  gstallocator: Use the right allocator instance to free memory
-	  In the case GST_ALLOCATOR_FLAG_CUSTOM_ALLOC is set, `copy` is allocated
-	  by the default allocator and not mem->allocator.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4144>
-
-2023-03-09 08:46:17 +0530  Nirbheek Chauhan <nirbheek@centricular.com>
-
-	* gst/gstvalue.c:
-	* tests/check/gst/gstvalue.c:
-	  gstvalue: Implement union for GstFractionRange
-	  This fixes simplification of caps with GstFractionRange structures,
-	  for example, this caps:
-	  video/x-raw, framerate=(fraction)5/1; video/x-raw, framerate=(fraction)[ 5/1, 30/1 ]
-	  can now be simplified to:
-	  video/x-raw, framerate=(fraction)[ 5/1, 30/1 ]
-	  instead of:
-	  video/x-raw, framerate=(fraction){ 5/1, [ 5/1, 30/1 ] }
-	  And this:
-	  video/x-raw, framerate=(fraction)[ 2/1, 5/1 ]; video/x-raw, framerate=(fraction)[ 5/1, 30/1 ]
-	  can be simplified to:
-	  video/x-raw, framerate=(fraction)[ 2/1, 30/1 ]
-	  instead of
-	  video/x-raw, framerate=(fraction){ [ 2/1, 5/1 ], [ 5/1, 30/1 ] }
-	  This fixes overly-complicated GL caps set by avfvideosrc on macOS and
-	  iOS when capturing from a webcam.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4132>
-
-2022-11-29 18:32:09 +0800  Chao Guo <chao.guo@nxp.com>
-
-	* gst/gstbin.c:
-	  bin: Fix bin won't post async done message to parent while nothing pending in state changing
-	  When we run Cheese 41.1 on our imx platform, Cheese preview freeze
-	  at first frame.
-	  During pipeline state changing from NULL to PLAYING, if there are
-	  both elements that state change asynchronously and state change
-	  with no preroll in the bin, the element inside may send ASYNC_DONE
-	  message to it, while the bin's pending state is VOID_PENDING.
-	  In this case, the bin will not post ASYNC_DONE message to parent
-	  bin, which makes parent bin thinks that there are still elements
-	  in it that haven't completed state changing, causing the pipeline
-	  freeze in an intermediate state.
-	  This commit modifies the bin_handle_async_done() function. When the
-	  bin, whose pending state is VOIDING_PENDING, receives the ASYNC_DONE
-	  message, it will also post this message to its parent bin.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3490>
-
-2022-11-26 13:36:32 +0100  Alicia Boya García <ntrrgc@gmail.com>
-
-	* libs/gst/base/gstbasesink.c:
-	* tests/check/elements/fakesink.c:
-	  basesink: Support position queries after non-resetting flushes
-	  A flush is resetting or not depending on the reset_time argument in the
-	  FLUSH_STOP event is set.
-	  Resetting flushes reset the running time to zero and clear any existing
-	  segment. These are the kind of flushes used by flushing seeks, and by far the
-	  most common. Non-resetting flushes are much more niche, used for instance for
-	  quality changes in adaptivedemux2 and MediaSource Extensions in WebKit.
-	  A key difference between the seek use case and the quality change use case is
-	  that the latter is much more removed from the player. Seeks generally occur
-	  because an user request it, whereas quality changes can be automatic.
-	  Currently, there are three notable cases where position queries fail:
-	  (a) before pre-roll, as there is no segment yet. This is one is understandable,
-	  as for at least some time before pre-roll, we cannot know if a media stream
-	  would start at 0 or any other position, or the duration of the stream for that
-	  matter.
-	  (b) after a resetting flush caused by a seek. This kind of flush resets the
-	  segment, so it's not surprising position queries fail. This is inconvenient for
-	  applications, as it means they always need to handle position reporting (e.g.
-	  in UI) separately every time they request a seek, e.g. by caching the seek
-	  target and using it when the position query fail. I'm not fond of this
-	  behavior, as it's unintuitive and makes GStreamer harder to use, but at this
-	  point could be difficult to change and it's not within the scope of this
-	  proposal.
-	  (c) after a non-resetting flush, e.g. caused by a quality change. The segment
-	  is not reset in this case. Position queries work until a FLUSH_STOP is sent.
-	  Querying position after a FLUSH_START but before a FLUSH_STOP works, and
-	  returns the position the sink was at the moment the FLUSH_START was received.
-	  **This in fact the only reliable way (short of adding probes to the sink
-	  element) to get this position**, as FLUSH_START receival is asynchronous with
-	  playback.
-	  In the case (c), as of currently, position queries fail once the FLUSH_STOP is
-	  received. But unlike in (b), the application has no position to fall back to,
-	  as the FLUSH_START was initiated by elements inside the pipeline that are in a
-	  lower layer of abstraction. Specific applications that have control of both the
-	  player and the internal element doing the flushing -- such as WebKit -- can
-	  still work around this problem through layer violations (lucky!), but this
-	  still puts in question this behavior in GStreamer.
-	  This patch fixes this case by amending the position query handler of basesink,
-	  which was previously erroneously returning early with "wrong state", even
-	  though the flush occurs in PAUSED or PLAYING.
-	  A unit test checking this behavior has also been added.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3471>
-
-2023-03-02 15:51:08 +0200  Vivia Nikolaidou <vivia@ahiru.eu>
-
-	* plugins/elements/gstinputselector.c:
-	* plugins/elements/gstinputselector.h:
-	  inputselector: Avoid deadlock when shutting down
-	  Transition from PLAYING to PAUSED unschedules any pending clock wait,
-	  but there was no guard that prevented another input buffer then waiting
-	  again while in PAUSED before dataflow stops. Use a new `playing` flag to
-	  avoid this, and exit the chain function if instead of playing we're now
-	  flushing. Basically the same as the clocksync element.
-	  Closes https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/1772
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4098>
-
-2022-01-13 00:45:25 +0100  Mathieu Duponchelle <mathieu@centricular.com>
-
-	* libs/gst/base/gstaggregator.c:
-	  aggregator: improve parsing in create_new_pad
-	  The previous implementation was a bit primitive, assuming the subclass
-	  had registered a template name starting with sink_ . Instead make
-	  the effort of parsing the actual template name, and use that to generate
-	  the final pad name.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4032>
-
-2022-01-29 19:36:16 +0100  Stefan Brüns <stefan.bruens@rwth-aachen.de>
-
-	* tools/gst-inspect.c:
-	  gst-inspect: Enhance auto-install-info output for De/Encryptor class
-	  Without this it is not possible to lookup which plugin handles a specific
-	  encrypted mimetype (e.g. application/x-cenc or application/x-aavd).
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/1604>
-
-2023-02-22 11:51:58 +0000  Tim-Philipp Müller <tim@centricular.com>
-
-	* po/fur.po:
-	  gstreamer: update translations
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4040>
-
-2023-02-21 20:13:57 -0700  James Hilliard <james.hilliard1@gmail.com>
-
-	* gst/gstbuffer.c:
-	  buffer: fix copy meta reference debug log formatting
-	  Fixes the following valgrind error:
-	  ==616== Conditional jump or move depends on uninitialised value(s)
-	  ==616==    at 0x4900E34: gst_debug_print_object (gstinfo.c:1143)
-	  ==616==    by 0x49010B6: gst_info_printf_pointer_extension_func (gstinfo.c:1215)
-	  ==616==    by 0x4959FDB: __gst_printf_pointer_extension_serialize (printf-extension.c:47)
-	  ==616==    by 0x495A487: printf_postprocess_args (vasnprintf.c:258)
-	  ==616==    by 0x495A52C: __gst_vasnprintf (vasnprintf.c:290)
-	  ==616==    by 0x4959F8F: __gst_vasprintf (printf.c:154)
-	  ==616==    by 0x4901C1F: gst_debug_message_get (gstinfo.c:791)
-	  ==616==    by 0x4901C75: _gst_debug_log_preamble (gstinfo.c:1431)
-	  ==616==    by 0x4903208: gst_debug_log_default (gstinfo.c:1575)
-	  ==616==    by 0x49020BA: gst_debug_log_full_valist (gstinfo.c:624)
-	  ==616==    by 0x490211D: gst_debug_log_valist (gstinfo.c:656)
-	  ==616==    by 0x49021AD: gst_debug_log (gstinfo.c:533)
-	  ==616==    by 0x48DDC11: gst_buffer_copy_into (gstbuffer.c:693)
-	  ==616==    by 0x48DF5F1: gst_buffer_copy_with_flags (gstbuffer.c:727)
-	  ==616==    by 0x48DF640: gst_buffer_copy_deep (gstbuffer.c:756)
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4034>
-
-2023-02-09 13:53:48 +0100  Jan Alexander Steffens (heftig) <jan.steffens@ltnglobal.com>
-
-	* gst/gstpad.c:
-	  pad: Don't leak user_data in gst_pad_start_task
-	  When the task already exists, we forgot to free the passed `user_data`.
-	  This wasn't an issue for most C code, which doesn't pass a
-	  `GDestroyNotify`, but bindings such as gstreamer-rs do!
-	  That said, allocating a trampoline in gstreamer-rs just for it to get
-	  thrown away again is awkward. Maybe we need a `gst_pad_resume_task`?
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3920>
-
-2023-01-30 23:49:25 -0300  Thibault Saunier <tsaunier@igalia.com>
-
-	* gst/gstbin.c:
-	  bin: Do not deactivate pad in NULL_TO_READY
-	  Since https://gitlab.freedesktop.org/gstreamer/gstreamer/-/commit/b76d3365497ded1fd4d536f0da2b9702f614b806
-	  pads are deactivated when going to READY but in `uridecodebin(3)`, the
-	  sources source pads are activated while in NULL state (when PULL mode is
-	  supported), meaning that we are ending up deactivating those pads in
-	  NULL_TO_READY, breaking the pipeline.
-	  The intent of the commit mentioned above is to ensure that the pads are
-	  deactivated either in PAUSED_TO_READY or READY_TO_READY, so it should
-	  be safe to avoid deactivating in NULL_TO_READY.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3849>
-
-2023-02-07 13:43:06 +0000  medithe <medithe@gmx.at>
-
-	* gst/gstbin.c:
-	  gstreamer: bin: Don't unlock unlocked mutex in gst_bin_remove_func()
-	  Calling `g_mutex_unlock(mutex)` leads to an undefined behavior if the
-	  mutex is not locked by the current thread.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3903>
-
-2023-02-03 14:29:10 +0200  Sebastian Dröge <sebastian@centricular.com>
-
-	* libs/gst/net/gstptpclock.c:
-	  net: ptp: Use GSubprocess instead of lower-level GLib APIs that don't work on Windows
-	  libgstnet depends on GIO already anyway so we can as well make use of it
-	  instead of a half-baked Windows implementation that doesn't actually
-	  work.
-	  As a next step, the helper process also needs to be made usable on
-	  Windows.
-	  See https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/1259
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3887>
-
-2023-01-28 02:32:13 +0900  Seungha Yang <seungha@centricular.com>
-
-	* tools/gst-inspect.c:
-	* tools/gst-launch.c:
-	* tools/gst-stats.c:
-	* tools/gst-typefind.c:
-	  tools: Make sure UTF-8 encoded command line arguments on Windows
-	  On Windows, arguments passed in main() are system codepage
-	  encoded and might not be valid UTF-8 string.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3828>
-
-2023-02-03 04:02:26 +0900  Seungha Yang <seungha@centricular.com>
-
-	* gst/gstpluginloader-win32.c:
-	  pluginloader-win32: Prepend gstreamer-1.0-0.dll directory to PATH env for child process
-	  Usually gst-plugin-scanner.exe will be located under libexec/gstreamer-1.0
-	  or even somewhere user specified location via GST_PLUGIN_SCANNER
-	  environment. So, in order for child process to be able to load
-	  GStreamer DLLs, parent process will need to update PATH env
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3886>
-
-2022-11-26 02:49:33 +1100  Jan Schmidt <jan@centricular.com>
-
-	* gst/gsturi.c:
-	* gst/gsturi.h:
-	* tests/check/gst/gsturi.c:
-	  gsturi: Add API to order query strings
-	  Add gst_uri_get_query_string_ordered() and gst_uri_to_string_with_keys() that
-	  allow constructing the URI string with query arguments in a specific order.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3803>
-
-2022-10-03 15:09:31 -0300  Thibault Saunier <tsaunier@igalia.com>
-
-	* gst/gstutils.c:
-	* gst/gstutils.h:
-	  gstutils: Add a utility to create a stream-id without a pad
-	  We already have functions to generate a stream-id from pads but in the
-	  end those pads are not even used in most cases. This adds functions to
-	  generate a stream-id even before creating the source pads for the
-	  element that is going to use it. For example a demuxer that is properly
-	  implements the GstStream/GstStreamCollection API will not have a Pad but
-	  already needs to generate a stream-id.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3160>
-
-2023-02-02 00:25:53 +0900  Seungha Yang <seungha@centricular.com>
-
-	* gst/gstpluginloader-win32.c:
-	  pluginloader-win32: Watch child process handle on connection
-	  ... so that parent can avoid waiting if child process got terminated
-	  unexpectedly
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3863>
-
-2023-02-02 00:19:55 +0900  Seungha Yang <seungha@centricular.com>
-
-	* gst/gstpluginloader-win32.c:
-	  pluginloader-win32: Check pipe state in child process
-	  Retry if server is not ready for the connection
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3863>
-
-2023-02-01 23:14:17 +0900  Seungha Yang <seungha@centricular.com>
-
-	* gst/gstpluginloader-win32.c:
-	  pluginloader-win32: Enhance debug log
-	  Change log level to ERROR if it's unexpected, and print error reasons
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3863>
-
-2023-02-01 23:08:03 +0900  Seungha Yang <seungha@centricular.com>
-
-	* gst/gstpluginloader-win32.c:
-	  pluginloader-win32: Zero initialize overlapped struct before use
-	  Helper child process might be spawned multiple times for some reason
-	  then overlapped struct can hold garbage data. Always clear the struct.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3863>
-
-2022-04-18 16:33:40 +0000  Thibault Saunier <tsaunier@igalia.com>
-
-	* docs/plugins/gst_plugins_cache.json:
-	* plugins/elements/gstclocksync.c:
-	* plugins/elements/gstclocksync.h:
-	  clocksync: Add "QoS" support
-	  When ClockSync synchronizes the data stream on the clock, it should also
-	  push `QoS` events if the user wants to do it as, as stated in [the QoS
-	  design doc] "Elements that synchronize buffers on the pipeline clock
-	  will usually measure the current QoS".
-	  The logic has been replicated from `GstBaseSink`.
-	  [the QoS design doc]: https://gstreamer.freedesktop.org/documentation/plugin-development/advanced/qos.html
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/2225>
-
-2023-01-27 19:29:24 +0100  Mathieu Duponchelle <mathieu@centricular.com>
-
-	* libs/gst/base/gstbasesrc.h:
-	  BaseSrc: fix transfer annotation for fixate virtual method
-	  The fixate virtual method has the same semantics as gst_caps_fixate(),
-	  so the caps parameter must be marked as (transfer full).
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3830>
-
-2023-01-26 15:42:18 +0100  Mathieu Duponchelle <mathieu@centricular.com>
-
-	* libs/gst/base/gstbasesrc.h:
-	* libs/gst/base/gstpushsrc.h:
-	  BaseSrc, PushSrc: add nullable annotations to virtual methods
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3806>
-
-2023-01-26 10:33:26 +0100  Jan Alexander Steffens (heftig) <jan.steffens@ltnglobal.com>
-
-	* libs/gst/base/gstaggregator.c:
-	  aggregator: Warn about the right segment's format
-	  We were checking the head segment here, not the current segment.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/611>
-
-2020-09-02 17:59:30 +0200  Jan Alexander Steffens (heftig) <jan.steffens@ltnglobal.com>
-
-	* libs/gst/base/gstaggregator.c:
-	  aggregator: Always lock aggpad around update_time_level
-	  `aggpad->segment` is protected by the `aggpad`'s object lock. We need to
-	  take the lock before calling `update_time_level`.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/611>
-
-2022-12-20 10:01:12 -0800  Daniel Ulery <dan.ulery@gmail.com>
-
-	* docs/plugins/gst_plugins_cache.json:
-	* plugins/elements/gstfilesink.c:
-	* plugins/elements/gstfilesink.h:
-	  filesink: Adds rb+ file mode
-	  Adds rb+ file mode to filesink so that files can be pre-allocated. This
-	  can be use to keep reduce fragmentation over time with splitmuxsink.
-	  Fixes  #955
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/1532>
-
-2022-12-02 23:48:45 +0900  Seungha Yang <seungha@centricular.com>
-
-	* gst/gst_private.h:
-	* gst/gstpluginloader-win32.c:
-	* gst/gstpluginloader.c:
-	* gst/gstregistry.c:
-	* gst/meson.build:
-	* libs/gst/helpers/gst-plugin-scanner.c:
-	  gst-plugin-scanner: Add support for Windows
-	  Adding Win32 specific plugin loader implementation.
-	  Fixes: https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/11
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3512>
-
-2023-01-25 13:26:08 +0200  Sebastian Dröge <sebastian@centricular.com>
-
-	* gst/gsttypefind.c:
-	  gst: Fix gst_type_find_peek() return value annotation
-	  It's not possible to annotate a in-parameter for a return value array as
-	  the array length. Both are assumed to have the same direction and the
-	  current annotation causes the size parameter to be considered an out
-	  parameter.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3787>
-
-2023-01-23 17:26:07 +0100  Edward Hervey <edward@centricular.com>
-
-	* plugins/elements/gstmultiqueue.c:
-	  multiqueue: Handle use-interleave latency live pipelines
-	  Due to the dynamic nature of multiqueue, when `use-interleave` is used we can't
-	  report a maximum tolerated latency (when queried) since it is calculated
-	  dynamically.
-	  When in such live pipelines, we need to make sure multiqueue can handle the
-	  lowest global latency (provided by this event). Failure to do that would
-	  result in not providing enough buffering for a realtime pipeline.
-	  Fixes #1732
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3772>
-
-2023-01-24 09:24:03 -0300  Thibault Saunier <tsaunier@igalia.com>
-
-	* gst/gstelementfactory.c:
-	* gst/gstelementfactory.h:
-	  factory: Add "Timestamper" as new factory type
-	  This will be used by elements that correct timestamps (like the
-	  h264timestamper for example)
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3779>
-
-2023-01-08 02:02:53 +0000  Tim-Philipp Müller <tim@centricular.com>
-
-	* libs/gst/base/gstbitwriter.c:
-	  base: bitwriter: drop use of GSlice
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3695>
-
-2023-01-08 01:32:50 +0000  Tim-Philipp Müller <tim@centricular.com>
-
-	* plugins/elements/gstinputselector.c:
-	  inputselector: drop use of GSlice
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3695>
-
-2023-01-08 01:32:32 +0000  Tim-Philipp Müller <tim@centricular.com>
-
-	* plugins/elements/gstmultiqueue.c:
-	  multiqueue: drop use of GSlice
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3695>
-
-2023-01-08 01:32:13 +0000  Tim-Philipp Müller <tim@centricular.com>
-
-	* plugins/elements/gstqueue2.c:
-	* plugins/elements/gstsparsefile.c:
-	  queue2: drop use of GSlice
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3695>
-
-2023-01-08 01:31:21 +0000  Tim-Philipp Müller <tim@centricular.com>
-
-	* plugins/tracers/gstrusage.c:
-	* plugins/tracers/gststats.c:
-	* tools/gst-stats.c:
-	  tracers: drop use of GSlice
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3695>
-
-2023-01-08 01:30:36 +0000  Tim-Philipp Müller <tim@centricular.com>
-
-	* libs/gst/base/gstbitreader.c:
-	* libs/gst/base/gstbytereader.c:
-	* libs/gst/base/gstbytewriter.c:
-	* libs/gst/base/gstflowcombiner.c:
-	* libs/gst/base/gstqueuearray.c:
-	* libs/gst/base/gsttypefindhelper.c:
-	  libs: base: drop use of GSlice
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3695>
-
-2023-01-08 01:30:20 +0000  Tim-Philipp Müller <tim@centricular.com>
-
-	* gst/parse/grammar.y.in:
-	* libs/gst/base/gstbaseparse.c:
-	* libs/gst/base/gstindex.c:
-	* libs/gst/base/gstmemindex.c:
-	  baseparse: drop use of GSlice
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3695>
-
-2023-01-08 01:28:43 +0000  Tim-Philipp Müller <tim@centricular.com>
-
-	* libs/gst/check/gstcheck.c:
-	* libs/gst/check/gstharness.c:
-	* libs/gst/check/gsttestclock.c:
-	  gstcheck: drop use of GSlice
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3695>
-
-2023-01-08 01:27:54 +0000  Tim-Philipp Müller <tim@centricular.com>
-
-	* libs/gst/controller/gsttimedvaluecontrolsource.c:
-	  controller: drop use of GSlice
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3695>
-
-2023-01-08 00:57:25 +0000  Tim-Philipp Müller <tim@centricular.com>
-
-	* gst/gsttracerutils.c:
-	  tracerutils: drop use of GSlice
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3695>
-
-2023-01-08 00:57:01 +0000  Tim-Philipp Müller <tim@centricular.com>
-
-	* gst/gsttaskpool.c:
-	  taskpool: drop use of GSlice
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3695>
-
-2023-01-08 00:56:41 +0000  Tim-Philipp Müller <tim@centricular.com>
-
-	* gst/gstsegment.c:
-	  segment: drop use of GSlice
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3695>
-
-2023-01-08 00:56:23 +0000  Tim-Philipp Müller <tim@centricular.com>
-
-	* gst/gstsample.c:
-	  sample: drop use of GSlice
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3695>
-
-2023-01-08 00:55:27 +0000  Tim-Philipp Müller <tim@centricular.com>
-
-	* gst/gstquery.c:
-	  query: drop use of GSlice
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3695>
-
-2023-01-08 00:55:04 +0000  Tim-Philipp Müller <tim@centricular.com>
-
-	* gst/gstiterator.c:
-	  iterator: drop use of GSlice
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3695>
-
-2023-01-08 00:54:41 +0000  Tim-Philipp Müller <tim@centricular.com>
-
-	* gst/gstevent.c:
-	  event: drop use of GSlice
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3695>
-
-2023-01-08 00:54:03 +0000  Tim-Philipp Müller <tim@centricular.com>
-
-	* gst/gstinfo.c:
-	  info: drop use of GSlice
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3695>
-
-2023-01-08 00:49:19 +0000  Tim-Philipp Müller <tim@centricular.com>
-
-	* gst/gstdevicemonitor.c:
-	  devicemonitor: drop use of GSlice
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3695>
-
-2023-01-08 00:49:00 +0000  Tim-Philipp Müller <tim@centricular.com>
-
-	* gst/gstdatetime.c:
-	  datetime: drop use of GSlice
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3695>
-
-2023-01-08 00:48:46 +0000  Tim-Philipp Müller <tim@centricular.com>
-
-	* gst/gstclock.c:
-	  clockentry: drop use of GSlice
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3695>
-
-2023-01-08 00:48:07 +0000  Tim-Philipp Müller <tim@centricular.com>
-
-	* gst/gstcontext.c:
-	  context: drop use of GSlice
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3695>
-
-2023-01-08 00:47:38 +0000  Tim-Philipp Müller <tim@centricular.com>
-
-	* gst/gsturi.c:
-	  uri: drop use of GSlice
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3695>
-
-2023-01-08 00:46:42 +0000  Tim-Philipp Müller <tim@centricular.com>
-
-	* gst/gstformat.c:
-	* gst/gstmeta.c:
-	  meta: drop use of GSlice
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3695>
-
-2023-01-08 00:41:38 +0000  Tim-Philipp Müller <tim@centricular.com>
-
-	* gst/gstmessage.c:
-	  message: drop use of GSlice
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3695>
-
-2023-01-08 00:19:23 +0000  Tim-Philipp Müller <tim@centricular.com>
-
-	* gst/gstvalue.c:
-	  gstvalue: drop use of GSlice
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3695>
-
-2023-01-07 19:43:02 +0000  Tim-Philipp Müller <tim@centricular.com>
-
-	* gst/gstcaps.c:
-	* gst/gstcapsfeatures.c:
-	  caps, capsfeatures: drop use of GSlice
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3695>
-
-2023-01-07 19:42:29 +0000  Tim-Philipp Müller <tim@centricular.com>
-
-	* gst/gstbus.c:
-	* gst/gstpoll.c:
-	  bus, poll: drop use of GSlice
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3695>
-
-2023-01-07 19:41:31 +0000  Tim-Philipp Müller <tim@centricular.com>
-
-	* gst/gstbin.c:
-	  bin: drop use of GSlice
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3695>
-
-2023-01-07 19:40:42 +0000  Tim-Philipp Müller <tim@centricular.com>
-
-	* gst/gsttaglist.c:
-	* gst/gsttagsetter.c:
-	  taglist, tagsetter: drop use of GSlice
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3695>
-
-2023-01-07 19:40:16 +0000  Tim-Philipp Müller <tim@centricular.com>
-
-	* gst/gsttoc.c:
-	* gst/gsttocsetter.c:
-	  toc, tocsetter: drop use of GSlice
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3695>
-
-2023-01-07 19:37:52 +0000  Tim-Philipp Müller <tim@centricular.com>
-
-	* gst/gstallocator.c:
-	* gst/gstbuffer.c:
-	* gst/gstbufferlist.c:
-	  allocator, buffer, bufferlist: drop use of GSlice
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3695>
-
-2023-01-07 19:27:30 +0000  Tim-Philipp Müller <tim@centricular.com>
-
-	* gst/gstregistrychunks.c:
-	* gst/gstregistrychunks.h:
-	  registrychunks: get rid of internal GST_REGISTRY_CHUNK_FLAG_MALLOC
-	  Not actually needed.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3695>
-
-2023-01-07 19:20:41 +0000  Tim-Philipp Müller <tim@centricular.com>
-
-	* gst/gstelementfactory.c:
-	* gst/gstplugin.c:
-	* gst/gstpluginloader.c:
-	* gst/gstregistrybinary.c:
-	* gst/gstregistrychunks.c:
-	* gst/gstregistrychunks.h:
-	* tests/check/gst/gstelementfactory.c:
-	  registry: drop use of GSlice
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3695>
-
-2023-01-06 01:40:08 +0000  Tim-Philipp Müller <tim@centricular.com>
-
-	* gst/gstparse.c:
-	* gst/parse/grammar.y.in:
-	* gst/parse/types.h:
-	  gstparse: drop use of GSlice allocator
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3695>
-
-2023-01-06 01:37:39 +0000  Tim-Philipp Müller <tim@centricular.com>
-
-	* tests/examples/memory/my-memory.c:
-	* tests/examples/memory/my-vidmem.c:
-	* tests/examples/streams/testrtpool.c:
-	  core: examples: drop use of GSlice
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3695>
-
-2023-01-04 17:58:13 +0000  Tim-Philipp Müller <tim@centricular.com>
-
-	* tests/check/gst/gstelementfactory.c:
-	* tests/check/gst/gstmemory.c:
-	* tests/check/libs/gsttestclock.c:
-	  core: tests: drop use of GSlice allocator
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3695>
-
-2023-01-04 17:57:05 +0000  Tim-Philipp Müller <tim@centricular.com>
-
-	* tools/gst-stats.c:
-	  tools: gst-stats: drop use of GSlice allocator
-	  https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/291
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3695>
-
-2019-07-23 17:53:18 +0200  Alicia Boya García <aboya@igalia.com>
-
-	* libs/gst/base/gstaggregator.c:
-	* plugins/elements/gstconcat.c:
-	* plugins/elements/gstfunnel.c:
-	* plugins/elements/gstinputselector.c:
-	  Use automatic pad activation in elements that can take advantage of it
-	  Pads are activated automatically when they are added if the element
-	  state is >=PAUSED, so it's not necessary to activate them manually
-	  anymore.
-	  This patch removes manual pad activation from gstaggregator, gstconcat,
-	  gstfunnel, and gstinputselector.
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3636>
-
-2023-01-23 23:04:53 +0000  Tim-Philipp Müller <tim@centricular.com>
-
-	* meson.build:
-	  Back to development
-	  Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3775>
-
-=== release 1.22.0 ===
+=== release 1.24.0 ===
 
diff --git a/NEWS b/NEWS
index ddf0da3..c374d71 100644
--- a/NEWS
+++ b/NEWS
@@ -1,895 +1,922 @@
-GStreamer 1.24 Release Notes
+GStreamer 1.26 Release Notes
 
-GStreamer 1.24.0 was originally released on 4 March 2024.
+GStreamer 1.26.0 was originally released on 11 March 2025.
 
-The latest bug-fix release in the stable 1.24 series is 1.24.10 and was released on 06 January 2025.
+See https://gstreamer.freedesktop.org/releases/1.26/ for the latest version of this document.
 
-See https://gstreamer.freedesktop.org/releases/1.24/ for the latest version of this document.
-
-Last updated: Tuesday 06 January 2025, 19:30 UTC (log)
+Last updated: Tuesday 11 March 2025, 20:00 UTC (log)
 
 ## 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.
+As always, this release is again packed with many new features, bug fixes, and other improvements.
 
 ## Highlights
 
--   New Discourse forum and Matrix chat space
--   New Analytics and Machine Learning abstractions and elements
--   Playbin3 and decodebin3 are now stable and the default in gst-play-1.0, GstPlay/GstPlayer
--   The va plugin is now preferred over gst-vaapi and has higher ranks
--   GstMeta serialization/deserialization and other GstMeta improvements
--   New GstMeta for SMPTE ST-291M HANC/VANC Ancillary Data
--   New unixfd plugin for efficient 1:N inter-process communication on Linux
--   cudaipc source and sink for zero-copy CUDA memory sharing between processes
--   New intersink and intersrc elements for 1:N pipeline decoupling within the same process
--   Qt5 + Qt6 QML integration improvements including qml6glsrc, qml6glmixer, qml6gloverlay, and qml6d3d11sink elements
--   DRM Modifier Support for dmabufs on Linux
--   OpenGL, Vulkan and CUDA integration enhancements
--   Vulkan H.264 and H.265 video decoders
--   RTP stack improvements including new RFC7273 modes and more correct header extension handling in depayloaders
--   WebRTC improvements such as support for ICE consent freshness, and a new webrtcsrc element to complement webrtcsink
--   WebRTC signallers and webrtcsink implementations for LiveKit and AWS Kinesis Video Streams
--   WHIP server source and client sink, and a WHEP source
--   Precision Time Protocol (PTP) clock support for Windows and other additions
--   Low-Latency HLS (LL-HLS) support and many other HLS and DASH enhancements
--   New W3C Media Source Extensions library
--   Countless closed caption handling improvements including new cea608mux and cea608tocea708 elements
--   Translation support for awstranscriber
--   Bayer 10/12/14/16-bit depth support
--   MPEG-TS support for asynchronous KLV demuxing and segment seeking, plus various new muxer features
--   Capture source and sink for AJA capture and playout cards
--   SVT-AV1 and VA-API AV1 encoders, stateless AV1 video decoder
--   New uvcsink element for exporting streams as UVC camera
--   DirectWrite text rendering plugin for windows
--   Direct3D12-based video decoding, conversion, composition, and rendering
--   AMD Advanced Media Framework AV1 + H.265 video encoders with 10-bit and HDR support
--   AVX/AVX2 support and NEON support on macOS on Apple ARM64 CPUs via new liborc
--   GStreamer C# bindings have been updated
--   Rust bindings improvements and many new and improved Rust plugins
--   Rust plugins now shipped in packages for all major platforms including Android and iOS
+-   H.266 Versatile Video Coding (VVC) codec support
+-   Low Complexity Enhancement Video Coding (LCEVC) support
+-   Closed captions: H.264/H.265 extractor/inserter, cea708overlay, cea708mux, tttocea708 and more
+-   New hlscmafsink, hlssink3, and hlsmultivariantsink; HLS/DASH client and dashsink improvements
+-   New AWS and Speechmatics transcription, translation and TTS services elements, plus translationbin
+-   Splitmux lazy loading and dynamic fragment addition support
+-   Matroska: H.266 video and rotation tag support, defined latency muxing
+-   MPEG-TS: support for H.266, JPEG XS, AV1, VP9 codecs and SMPTE ST-2038 and ID3 meta; mpegtslivesrc
+-   ISO MP4: support for H.266, Hap, Lagarith lossless codecs; raw video support; rotation tags
+-   SMPTE 2038 ancillary data streams support
+-   JPEG XS image codec support
+-   Analytics: New TensorMeta; N-to-N relationships; Mtd to carry segmentation masks
+-   ONVIF metadata extractor and conversion to/from relation metas
+-   New originalbuffer element that can restore buffers again after transformation steps for analytics
+-   Improved Python bindings for analytics API
+-   Lots of Vulkan integration and Vulkan Video decoder/encoder improvements
+-   OpenGL integration improvements, esp. in glcolorconvert, gldownload, glupload
+-   Qt5/Qt6 QML GL sinks now support direct DMABuf import from hardware decoders
+-   CUDA: New compositor, Jetson NVMM memory support, stream-ordered allocator
+-   NVCODEC AV1 video encoder element, and ndsdewarp
+-   New Direct3D12 integration support library
+-   New d3d12swapchainsink and d3d12deinterlace elements and D3D12 sink/source for zero-copy IPC
+-   Decklink HDR support (PQ + HLG) and frame scheduling enhancements
+-   AJA capture source clock handling and signal loss recovery improvements
+-   RTP and RTSP: New rtpbin sync modes, client-side MIKEY support in rtspsrc
+-   New Rust rtpbin2, rtprecv, rtpsend, and many new Rust RTP payloaders and depayloaders
+-   webrtcbin support for basic rollbacks and other improvements
+-   webrtcsink: support for more encoders, SDP munging, and a built-in web/signalling server
+-   webrtcsrc/sink: support for uncompressed audio/video and NTP & PTP clock signalling and synchronization
+-   rtmp2: server authentication improvements incl. Limelight CDN (llnw) authentication
+-   New Microsoft WebView2 based web browser source element
+-   The GTK3 plugin has gained support for OpenGL/WGL on Windows
+-   Many GTK4 paintable sink improvements
+-   GstPlay: id-based stream selection and message API improvements
+-   Real-time pipeline visualization in a browser using a new dots tracer and viewer
+-   New tracers for tracking memory usage, pad push timings, and buffer flow as pcap files
+-   VA hardware-acclerated H.266/VVC decoder, VP8 and JPEG encoders, VP9/VP8 alpha decodebins
+-   Video4Linux2 elements support DMA_DRM caps negotiation now
+-   V4L2 stateless decoders implement inter-frame resolution changes for AV1 and VP9
+-   Editing services: support for reverse playback and audio channel reordering
+-   New QUIC-based elements for working with raw QUIC streams, RTP-over-QUIC (RoQ) and WebTransport
+-   Apple AAC audio encoder and multi-channel support for the Apple audio decoders
+-   cerbero: Python bindings and introspection support; improved Windows installer based on WiX5
 -   Lots of new plugins, features, performance improvements and bug fixes
 
 ## Major new features and changes
 
-### Discourse forum and Matrix chat space
+### H.266 Versatile Video Coding (VVC) codec support
 
--   The new Discourse forum and Matrix chat space are now our preferred communication channels for support and developer chat.
+-   The H.266 / VVC video codec is a successor to H.265 / HEVC and is standardised in ISO/IEC 23090-3.
 
--   The mailing lists and IRC channel are on their way to being phased out, but Discourse can be used via e-mail as well.
+-   A new h266parse element was added, along with parsing API, typefinding support and some codec utility functions in the
+    gst-plugins-base utility library.
 
--   For release announcements please subscribe to the News + Announcements category on Discourse, although we will continue to
-    also send announcements to the mailing list for the time being.
+-   A H.266 decoder base class for hardware-accelerated decoders was added and used to implement a VA-API-based
+    hardware-accelerated H.266 decoder.
 
-### Playbin3, decodebin3 now stable and default
+-   The FFmpeg H.266 decoder is exposed now (from FFmpeg 7.0 onwards).
 
--   After a year of stability, testing and more improvements, playbin3, and its various components (uridecodebin3, decodebin3
-    and urisourcebin), are now the recommended playback components.
+-   H.266 / VVC muxing and demuxing support was implemented for MP4, Matroska and MPEG-TS containers.
 
--   Some playback components have now switched to defaulting to playbin3: gst-play-1.0 and the GstPlay / GstPlayer libraries.
-    Application developers are strongly recommended to switch to using those components instead of the legacy playbin and
-    (uri)decodebin.
+-   A VVdeC-based H.266 decoder element was added to the Rust plugins, based on the Fraunhofer Versatile Video Decoder library.
 
-Improvements in this cycle:
+### JPEG XS image codec support
 
--   Better support missing/faulty decoders, attempt to use another one or gracefully un-select the stream.
+-   JPEG XS is a visually lossless, low-latency, intra-only video codec for video production workflows, standardised in ISO/IEC
+    21122.
 
--   Many fixes for more complex gapless and instant-switching scenarios
+-   JPEG XS encoder and decoder elements based on the SVT JPEG XS library were added, including support for muxing JPEG XS into
+    MPEG-TS and demuxing it. Both interlaced and progressive modes are supported.
 
--   Lower latency for live pipelines
+### Low Complexity Enhancement Video Coding (LCEVC) support
 
--   Fix for “chained” streams (ex: Ogg, or PMT update in MPEG-TS)
+-   LCEVC 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.
 
--   Fixes for hardware-accelerated playback with subtitles (provided the sink can handle offloading composition). This was also
-    partly due to a historical confusion between subtitle “decoders” (which decode the format to text and “parsers” (which only
-    do timing detection and optional seeking).
+-   LCEVC encoder and decoder elements based on V-Nova’s SDK libraries were added, including support in h264parse for extracting
+    the enhancement layer from H.264 and decoding it via a lcevch264decodebin element.
 
-### GstMeta serialization/deserialization and other GstMeta improvements
+### Closed captions improvements
 
--   GstMeta serialization/deserialization allows metas to be transmitted or stored. This is used by the unixfd and cudaipc
-    plugins for inter-process communication (IPC). Implemented so far for GstCustomMeta, GstVideoMeta, GstAudioMeta and
-    GstReferenceTimestampMeta.
+-   New H.264 and H.265 closed captions extractor and inserter elements.
 
--   Simplified GstCustomMeta registration with gst_meta_register_custom_simple() for the simple case where tags and transform
-    functions are not needed.
+    -   These extractor elements don’t actually extract captions from the bitstream, but rely on parser elements to do that and
+        add them to buffers in form of caption metas. The problem is that streams might contain B-frames, in which case the
+        captions in the bitstream will not be in presentation order and extracting them requires frame-reordering in the same
+        way that a decoder would do. These new elements will do exactly that and allow you to extract captions in presentation
+        order without having to decode the stream.
 
--   GstMetaClearFunction clears the content of the meta. This will be called by buffer pools when a pooled buffer is returned to
-    the pool.
+    -   The inserter elements do something similar and insert caption SEIs into the H.264 or H.265 bitstream, taking into
+        account frame ordering.
 
--   Add gst_meta_info_new() and gst_meta_info_register() to register a GstMeta in two steps for easier extensibility.
+    -   This is useful if one wants to extract, process and re-insert captions into an existing video bitstream without decoding
+        and re-encoding it (in which case the decoder and encoder would handle the caption reordering).
 
-### New unixfd plugin for efficient 1:N inter-process communication on Linux
+-   cdpserviceinject: New element for injecting a CDP service descriptor into closed caption CDP packets
 
--   unixfdsink and unixfdsrc are elements that, inspired by shmsink andn shmsrc, send UNIX file descriptors (e.g. memfd, dmabuf)
-    from one sink to multiple source elements in other processes on Linux.
+-   cea708overlay: New element for overlaying CEA608 / CEA708 closed captions over video streams.
 
--   The unixfdsink proposes a memfd/shm allocator to upstream elements which allows for example videotestsrc to write directly
-    into memory that can be transfered to other processes without copying.
+-   The cc708overlay element has been deprecated in favour of the cea708overlay element from the Rust plugins set.
 
-### New GstMeta for SMPTE ST-291M HANC/VANC Ancillary Data
+-   cea608mux gained a "force-live" property to make it always in live mode and aggregate on timeout regardless of whether any
+    live sources are linked upstream.
 
--   Previously only various specific GstMeta for ancillary data were provided, such as GstVideoCaptionMeta and GstVideoAFDMeta.
-    The new GstAncillaryMeta allows passing arbitrary ancillary data between elements, including custom and non-standard
-    ancillary data. See GstAncillaryMeta for details.
+-   cea708mux: New element that allows to mux multiple CEA708 services into a single stream.
 
--   Add with gst_buffer_add_ancillary_meta() and retrieve with gst_buffer_get_ancillary_meta() or
-    gst_buffer_iterate_ancillary_meta().
+-   cccombiner has two new properties:
 
--   Supported by the newly added AJA sink and source elements
+    -   "input-meta-processing" controls how input closed caption metas are processed and can be used to e.g. discard closed
+        captions from the input pad if the matching video buffer already has closed caption on it.
 
-### DSD audio support
+    -   "schedule-timeout" to support timing out captions without EOS
 
--   DSD audio is a non-PCM raw audio format representation and the GstAudio library gained support for this in form of new
-    GstDsdInfo and GstDsdFormat API.
+-   tttocea708: New element for converting timed-text to CEA708 closed captions
 
--   Support for DSD audio has been implemented in alsasink as well as the GstAudioSink and GstAudioRingBuffer base classes, and
-    the gst-libav plugin to enable FFmpeg-based DSD elements and functionality.
+-   Miscellaneous improvements and spec compliance fixes
 
-### Analytics and Machine Learning
+### Speech to Text, Translation and Speech Synthesis
 
--   A new library, GstAnalytics, has been added. It defines a GstAnalyticsRelationMeta that can efficiently hold a large number
-    of observations from a data analysis process, for example from machine learning. It also contains a matrix of the
-    relationship between those observations.
+-   awstranscriber2, awstranslate: New elements around the AWS transcription and translation services.
 
--   Three types of metadata are already defined in the library: object detection, classification and tracking.
+-   polly: New element around the AWS text-to-speech polly services
 
--   A new objectdetectionoverlay element has been merged that draws the bounding boxes and the classes from the object detection
-    and classification metadata types.
+-   speechmatics: New transcriber / speech-to-text and translation element
 
--   The onnxinference element has been split into two parts. The first part works with the ONNX Runtime library to do the actual
-    inference, while the second part called ssdobjectdetector interprets the produced tensor. This new element creates
-    GstAnalyticsRelationMeta.
+-   translationbin: Helper bin around translation elements, similar to the already existing transcriberbin for transcriptions.
 
--   The onnxinference element now accepts video frames without transformation if the module declares that it accepts the “Image”
-    type and the format is something that GStreamer knows.
+### HLS DASH adaptive streaming improvements
 
--   In the next release, tensor decoders such as ssdobjectdetector will live outside of the ONNX plugin so they can be used with
-    other machine learning acceleration frameworks.
+-   The adaptivedemux2 client implementation gained support for file:// URIs and as such the ability to play HLS and DASH from
+    local files. It also no longer sends spurious flush events when it loses sync in live streams, as that is unexpected and
+    will be handled poorly in non-playback scenarios. Lastly, support for HTTP request retries was added via the "max-retries"
+    property, along with some exponential backoff logic which can be fine-tuned via properties.
 
-### Qt5 + Qt6 QML integration improvements
+-   dashsink has received period duration fixes for dynamic MPDs and some memory leak fixes.
 
--   The Qt5 qmlglsink, qmlgloverlay, qmlglmixer received support for directly consuming BGRA and YV12 video frames without a
-    prior glcolorconvert.
+-   hlscmafsink, hlssink3: New single-variant HLS sink elements that can output CMAF (fMP4) or MPEG-TS fragments.
 
--   New qml6glsrc, qml6glmixer, and qml6gloverlay elements as Qt6 counterparts to the existing Qt5 elements, also with support
-    for directly consuming BGRA and YV12 video frames without a prior glcolorconvert.
+-   hlsmultivariantsink: New sink element that can output an HLS stream with multiple variants
 
--   qml6d3d11sink is a new Direct3D11 Qt6 QML sink for Windows as an alternative to the existing qml6glsink.
+### splitmuxsrc, splitmuxsink: lazy loading and dynamic fragment addition
 
-### DRM Modifier Support for dmabufs on Linux
+-   splitmuxsrc and splitmuxsink were originally designed to handle a small number of large file fragments, e.g. for situations
+    where one doesn’t want to exceed a certain file size when recording to legacy file systems. It was also designed for playing
+    back a static set of file fragments that have been created by an earlier recording session and no longer changes. Over time
+    people have found more applications and use cases for the splitmux elements and have been deploying them in different
+    scenarios, exposing the limits of the current implementation.
 
-The Linux dmabuf subsystem provides buffer sharing across different hardware device drivers and subsystems, and is used
-extensively by the DRM subsystem to exchange buffers between processes, contexts, and library APIs within the same process, and
-also to exchange buffers with other subsystems such as Linux Media.
+-   In this release, splitmuxsink and splitmuxsrc gained new abilities aimed at improving support for recordings with a large
+    number of files, and for adding fragments on the fly to allow playback of ongoing recordings:
 
-In GStreamer, it’s used on the capture side (v4l2src, pipewire), hardware-accelerated video decoders and encoders, OpenGL
-integration, Wayland renderers, etc.
+    -   You can now add fragments directly to splitmuxsrc and provide the offset and duration in the stream:
 
-GStreamer has had support for dmabufs for a long time and was able to negotiate “zero-copy” paths between different components,
-however it only supported and assumed simple linear formats and was not able to negotiate complex non-linear formats. This meant
-that dmabuf support actually had to be disabled in many scenarios to avoid “garbled video”.
+        -   Providing offset and duration means splitmuxsrc doesn’t need to scan the file to measure it and calculate it. That
+            makes for much faster startup.
 
-With GStreamer 1.24 there is now full DRM modifier support and complex non-linear formats can be supported and negotiated
-between components.
+        -   The new "add-fragment" signal can be used to add files to the set dynamically - allowing to be playing an ongoing
+            recording and adding files to the playback set as they are finished.
 
-This is achieved with an extra drm_format field in video/x-raw(memory:DMABuf), format=(string)DMA_DRM caps, e.g.
-drm-format=(string)NV12:0x0x0100000000000001.
+    -   splitmuxsrc no longer keeps all files open, but instead only keeps 100 files open by default, configurable with the
+        "num-open-fragments" property.
 
-See the GStreamer DMA buffers design documentation for more details.
+    -   There is a new "num-lookahead" property on splitmuxsrc to trigger (re)opening files a certain distance ahead of the play
+        position.
 
-This is used in the VA-API va plugin, waylandsink, the MSDK plugin, and the OpenGL integration. Video4Linux support is expected
-to land in one of the next minor releases.
+    -   splitmuxsink will report fragment offset and fragment duration via a message on the bus when closing a file. This
+        information can then be used to add the new fragment to a splitmuxsrc.
 
-New API has been added for easy handling of these new caps:
+### MPEG-TS container format improvements
 
--   GstVideoInfoDmaDrm plus associated functions, similar to GstVideoInfo, including conversion to and from GstVideoInfo with
-    gst_video_info_dma_drm_from_video_info() and gst_video_info_dma_drm_to_video_info()
+-   The MPEG-TS muxer and demuxer gained support for
 
--   GST_VIDEO_DMA_DRM_CAPS_MAKE
+    -   H.266 / VVC video muxing and demuxing
+    -   JPEG-XS video muxing and demuxing
+    -   VP9 video muxing and demuxing (using a custom mapping)
+    -   AV1 video muxing and demuxing (using a custom mapping, since the work-in-progress specification effort doesn’t seem to
+        be going anywhere anytime soon)
+    -   SMPTE ST-2038 ancillary metadata streams (see section above)
 
--   GST_VIDEO_FORMAT_DMA_DRM
+-   mpegtsmux gained support for muxing ID3 metadata into the TS stream, as well as SMPTE 302M audio.
 
-### OpenGL integration enhancements
+-   It’s also possible to disable sending SCTE-35 null (heartbeat) packets now in mpegtsmux by setting the
+    "scte-35-null-interval" to 0.
 
--   When using EGL, if both OpenGL ES and OpenGL are available, OpenGL ES is preferred over OpenGL. OpenGL ES supports some
-    necessary features required for dmabuf support. This does not apply if an external library/application chooses an OpenGL API
-    first.
+-   tsparse now handles 192-byte M2TS packets
 
--   Improved support for dmabuf use cases. The glupload element now supports the new and improved dmabuf negotiation with
-    explicit modifiers.
+-   mpegtslivesrc: New source element that can wrap a live MPEG-TS source (e.g. SRT or UDP source) and provides a clock based on
+    the PCR.
 
--   Base classes for mixing with OpenGL are now public API. GstGLBaseMixer and GstGLMixer are exposed matching the existing
-    filter-based GstGLBaseFilter and GstGLFilter base classes. The new OpenGL mixer base classes are based on
-    GstVideoAggregator.
+### Matroska container format improvements
 
--   Add support for a ‘surfaceless’ EGL context using EGL_MESA_platform_surfaceless.
+-   H.266 / VVC video muxing and demuxing support
 
--   Expose Vivante Framebuffer build-related files (pkg-config, gir) as public API
+-   matroskamux
 
--   Add support for more video formats:
+    -   was ported to the GstAggregator base class, ensuring defined-latency muxing in live streaming pipelines.
+    -   gained rotation tag support
 
-    -   A420 8/10/12/16-bit.
-    -   A422 8/10/12/16-bit.
-    -   A444 8/10/12/16-bit.
-    -   I420 10/12 bit.
-    -   RBGA.
+-   matroskademux now also supports seeks with a stop position in push mode.
 
--   Add support for tiled video formats
+### ISO MP4 container format improvements
 
-    -   NV12_16L32S (Mediatek format)
-    -   NV12_4L4 (Verisilicon Hantro format)
+-   can mux and demux H.266 / VVC in MP4 now
 
--   glcolorconvert now has API for retrieving shader strings for:
+-   can demux Hap video now, as well as Lagarith lossless video and ISO/IEC 23003-5 raw PCM audio.
 
-    -   swizzling (reordering components).
-    -   YUV->RGB conversion.
-    -   RGB->YUV conversion.
+-   qtdemux handles keyunit-only trick mode also in push mode now
 
--   Add more helpers for information about a particular video and/or GL format e.g. number of components, bytes used, or pixel
-    ordering.
+-   support for ISO/IEC 23001-17 raw video in MP4 in qtdemux and isomp4mux.
 
--   glvideomixer has new sink pad properties sizing-policy, xalign, yalign matching compositor.
+-   support for rotation tags in the muxers and demuxers was improved to correctly handle per-media and per-track rotations, and
+    support for flips was added as well.
 
--   GstGLBufferPool now has a configuration option for allowing a number of buffers to be always outstanding allowing for
-    reducing the potential synchronisation delay when reusing OpenGL memory backed buffers.
+SMPTE 2038 ancillary data streams
 
-### Vulkan integration enhancements
+-   SMPTE 2038 (pdf) is a generic system to put VBI-style ancillary data into an MPEG-TS container. This could include all kinds
+    of metadata such as scoreboard data or game clocks, and of course also closed captions, in this case in form of a distinct
+    stream completely separate from any video bitstream.
 
--   Add support for the Vulkan H.264 and H.265 decoders.
+-   A number of new elements in the GStreamer Rust closedcaption plugin add support for this, along with mappings for it in the
+    MPEG-TS muxer and demuxer. The new elements are:
 
--   Add support for timeline semaphores.
+    -   st2038ancdemux: splits SMPTE ST-2038 ancillary metadata (as received from tsdemux) into separate streams per DID/SDID
+        and line/horizontal_offset. Will add a sometimes pad with details for each ancillary stream. Also has an always source
+        pad that just outputs all ancillary streams for easy forwarding or remuxing, in case none of the ancillary streams need
+        to be modified or dropped.
 
--   Optionally use newer Vulkan functions for format selection.
+    -   st2038ancmux: muxes SMPTE ST-2038 ancillary metadata streams into a single stream for muxing into MPEG-TS with
+        mpegtsmux. Combines ancillary data on the same line if needed, as is required for MPEG-TS muxing. Can accept individual
+        ancillary metadata streams as inputs and/or the combined stream from st2038ancdemux.
 
--   Add support for GPU-assisted validation.
+        If the video framerate is known, it can be signalled to the ancillary data muxer via the output caps by adding a
+        capsfilter behind it, with e.g. meta/x-st-2038,framerate=30/1.
 
--   Vulkan/Wayland: add support for xdg_wm_base protocol for creating a visible debug window. Required as the previous wl_shell
-    interface is being removed from compositors.
+        This allows the muxer to bundle all packets belonging to the same frame (with the same timestamp), but that is not
+        required. In case there are multiple streams with the same DID/SDID that have an ST-2038 packet for the same frame, it
+        will prioritise the one from more recently created request pads over those from earlier created request pads (which
+        might contain a combined stream for example if that’s fed first).
 
-### CUDA / NVCODEC integration and feature additions
+    -   st2038anctocc: extracts closed captions (CEA-608 and/or CEA-708) from SMPTE ST-2038 ancillary metadata streams and
+        outputs them on the respective sometimes source pad (src_cea608 or src_cea708). The data is output as a closed caption
+        stream with caps closedcaption/x-cea-608,format=s334-1a or closedcaption/x-cea-708,format=cdp for further processing by
+        other GStreamer closed caption processing elements.
+
+    -   cctost2038anc: takes closed captions (CEA-608 and/or CEA-708) as produced by other GStreamer closed caption processing
+        elements and converts them into SMPTE ST-2038 ancillary data that can be fed to st2038ancmux and then to mpegtsmux for
+        splicing/muxing into an MPEG-TS container. The line-number and horizontal-offset properties should be set to the desired
+        line number and horizontal offset.
 
--   New cudaipcsrc and cudaipcsink elements for zero-copy CUDA memory sharing between processes
+### Analytics
 
--   New nvJPEG library based nvjpegenc JPEG encoder element
+-   Added a GstTensorMeta: This meta is designed to carry tensors from the inference element to the model-specific tensor
+    decoder. This also includes a basic GstTensor class containing a single tensor. The actual tensor data is a GstBuffer.
 
--   The NVIDIA desktop GPU decoder nvh264sldec, nvh265sldec, nvvp8sldec, and nvvp9sldec elements were renamed to nvh264dec,
-    nvh265dec, nvvp8dec, and nvvp9dec, respectively.
+-   Add N_TO_N relationship to GstAnalyticsRelationMeta: This makes it possible to describe N-to-N relationships. For example,
+    between classes and regions in an instance segmentation.
 
--   GStreamer NVIDIA H.264 and H.265 encoders except for nvh264enc and nvh265enc gained support for CEA708 Closed Caption
-    inserting.
+-   Add a new analytics Mtd to carry segmentation masks: Being part of the GstAnalyticsMeta, it can be in relationship with the
+    other Mtd, such as the classification and object detection bounding boxes.
 
--   OpenGL memory support is added to nv{cuda,autogpu}h264enc and nv{cuda,autogpu}h265enc elements
+-   onvifmetadataextractor: New element that can extract ONVIF metadata from GstMetas into a separate stream
 
--   CUDA stream integration: As of 1.24, CUDA stream synchronization is an application’s responsibility, and GStreamer will not
-    execute unnecessary synchronization operations. If an application needs direct access to CUDA memory via GST_MAP_CUDA map
-    flag, cuStreamSynchronize() or gst_cuda_memory_sync() call is required unless application-side CUDA operation is executed
-    with the GstCudaMemory’s associated CUDA stream.
+-   originalbuffer: New plugin with originalbuffersave / originalbufferrestore elements that allow saving an original buffer,
+    modifying it for analytics, and then restoring the original buffer content while keeping any additional metadata that was
+    added.
 
-### RTP stack improvements
+-   relationmeta: New plugin with elements converting between GstRelationMeta and ONVIF XML metadata.
 
--   New rtppassthroughpay element which just passes RTP packets through unchanged, but appears like an RTP payloader element.
-    This is useful for relaying an RTP stream as-is through gst-rtsp-server, which expects an RTP payloader with certain
-    properties at the end of an RTSP media sub-pipeline.
+-   Improved Python bindings for a more Pythonic interface when iterating over GstRelationMeta’s mtd
 
--   New “timeout-inactive-rtp-sources” property on rtpbin, sdpdemux and rtpsession to allow applications to disable automatic
-    timeout of sources from which no data has been received for a while.
+### Vulkan integration enhancements
 
--   rtpvp8pay, rtpvp9pay: expose “picture-id” as a property, and add a “picture-id-offset” property to the VP9 payloader to
-    bring it in line with the VP8 payloader.
+-   Vulkan Integration Improvements:
 
--   rtpjitterbuffer has seen improved media clock handling (clock equality and clock setting/resetting), as well as two new
-    properties that allow reconstruction of absolute PTP timestamps without actually syncing to the PTP clock, which can be
-    useful in scenarios where one wants to reconstruct the absolute PTP clock timestamps on a machine that doesn’t have access
-    to the network of the PTP clock provider. The two new properties are:
+    -   Memory Management: Non-coherent memory is now invalidated when mapping for read in vkmemory.
 
-    -   “rfc7273-use-system-clock”: allows the jitter buffer to assume that the system clock is synced sufficiently close to the
-        media clock used by an RFC7273 stream. By default the property is disabled and the jitter buffer will create a media
-        clock and try to sync to it, but this is only required to determine in which wraparound period from the media clock’s
-        Epoch the current RTP timestamps refer to (and thus to reconstruct absolute time stamps from them). If the property is
-        enabled the wraparound period and current offset from the Epoch will be determined based on the local system clock,
-        which means that no direct network connection to the media clock provider is needed to reconstruct absolute timestamps.
-        There is also no start-up delay, because there’s no clock sync that needs to be established first.
+    -   Color Space Selection: The vkswapper component now chooses the correct color space based on the format.
 
-    -   “rfc7273-reference-timestamp-meta-only”: If this property is enabled then the jitter buffer will do the normal timestamp
-        calculations for the output buffers according to the configured mode instead of making use of the RFC7273 media clock
-        for that. It will still calculate RFC7273 media clock timestamps, but only attach them to the output buffers in form of
-        a clock reference meta.
+    -   Vulkan Plugin Compatibility: Support added for cases where glslc is not available for building Vulkan plugins, along
+        with GLSL compiler support for glslang.
 
--   RTP payloaders and depayloaders now have an “extensions” property for retrieving the list of currently enabled RTP header
-    extensions.
+    -   Fullscreen Quad Updates: Improved support for setting NULL input/output buffers and added checks for unset video info.
 
--   rtpbin and webrtcbin no longer blindly set properties on the jitter buffer assuming it’s a standard rtpjitterbuffer, but
-    instead check if the property is available first, to better support non-standard jitterbuffers or even an identity element
-    in lieu of a jitter buffer.
+    -   Vulkan Buffer Pool Enhancements: Buffer pool access flags and usage configurations have been refined, offering better
+        performance for video decoding and encoding.
 
--   RTP header extension handling fixes for depayloaders that aggregate multiple input buffers into a single output buffer.
-    Before, only the last RTP input buffer was checked for header extensions. Now the depayloader remembers all RTP packets
-    pushed before an output buffer is produced and checks all RTP input buffers for header extensions.
+-   Decoder/Encoder Improvements:
 
-    -   Affected depayloaders: rtph264depay, rtph265depay, rtpvp8depay, rtpvp9depay, rtpxqtdepay, rtpasfdepay, rtpmp4gdepay,
-        rtpsbcdepay, rtpvorbisdepay, rtpmp4vdepay, rtptheoradepay, rtpsv3vdepay, rtpmp4adepay, rtpklvdepay, rtpjpegdepay,
-        rtpj2kdepay, rtph263pdepay, rtph263depay, rtph261depay. rtpgstdepay.
+    -   H264 Decoder: Enhancements to the vkh264dec component for better support of extended profiles and interlaced content
+        decoding.
 
-### WebRTC improvements
+    -   H265 Decoder fixes: vkh265dec updated for proper handling of VPS/SPS on demand, along with fixes to PicOrderCntVal.
 
--   Add support for ICE consent freshness (RFC 7675). This requires libnice >= 0.1.22.
+    -   Encoder Performance: Various internal optimizations to the Vulkan encoder, including removal of redundant references and
+        better management of the DPB view.
 
--   Advertise the local side of an end-of-candidates with an empty candidate string.
+-   Vulkan Instance and Device Management:
 
--   Add the number of Data Channels opened and closed to webrtcbin’s statistics.
+    -   Device Handling: Added new utility functions for managing Vulkan device instances, including
+        gst_vulkan_instance_create_device_with_index and gst_vulkan_ensure_element_device.
 
--   Various improvements and feature additions in the Rust webrtc plugin, which provides webrtcsrc and webrtcsink elements as
-    well as specific elements for different WebRTC signalling protocols. See the Rust plugins section below for more details.
+    -   Device Context Management: Updates to manage Vulkan context handling more effectively within the application.
 
-### Adaptive Streaming improvements and Low-Latency HLS (LL-HLS) support
+### OpenGL integration enhancements
 
--   hlsdemux2 now supports Low-Latency HLS (LL-HLS)
+-   glcolorconvert gained support for more formats and conversions:
 
--   hlsdemux2 asynchronous playlist download and update improves responsiveness and bandwith usage.
+    -   Planar YUV <-> planar YUV conversions
+    -   Converting to and from v210 in general
+    -   v210 <-> planar YUV
+    -   UYVY and YUY2 <-> planar YUV
+    -   v210 <-> UYVY and YUY2
+    -   Support for Y444_10, Y444_16, I422_10, I422_12 pixel formats (both little endian and big endian variants)
 
--   hlsdemux2 handles fallback variant URLs.
+-   gldownload can import DMABufs from a downstream pool
 
--   hlsdemux2 is more responsive and accurate when handling seeks.
+-   glupload gained a DRM raw uploader
 
--   dashdemux2 and hlsdemux2 have a new “start-bitrate” property, improving the decision for which initial stream variant that
-    will be used.
+### Qt5 + Qt6 QML integration improvements
 
--   dashdemux2, hlsdemux2, mssdemux2 have received many improvements regarding seeking, along with support for “early-seek”
-    which allows playback to start immediately from the requested position without any previous download.
+-   qmlglsink, qml6glsink now support external-oes textures, which allows direct DMABuf import from hardware decoders. Both also
+    support NV12 as an input format now.
 
--   dashdemux2, hlsdemux2, mssdemux2 better handle errors on or near the live edge.
+-   qmlglsink gained support for RGB16/BGR16 as input format
 
--   dashsink can now use the dashmp4mux muxer from the Rust plugins and will also produce better and RFC 6381-compatible codec
-    strings. The “suggested-presentation-delay” property allows to set the suggested presentation delay in the MPD.
+-   qmlgl6src can now use a downstream buffer pool when available
 
--   No development took place on the legacy demuxers (dashdemux, hlsdemux, mssdemux). Application developers are reminded to use
-    the new demuxers instead. They are automatically picked up when using urisourcebin, uridecodebin3 or playbin3.
+-   qmlgloverlay make the depth/stencil buffer optional, which reduces memory bandwidth on Windows.
 
-### W3C Media Source Extensions library
+### CUDA / NVCODEC integration and feature additions
 
--   A new GStreamer library (mse) implementing the W3C Media Source Extensions specification was added.
+-   Added AV1 video encoder nvav1enc
 
--   Applications can embed this library along with GStreamer in order to integrate software that uses the Media Source APIs
-    without relying on a web browser engine. Typically an application consuming this library will wrap the C API with JavaScript
-    bindings that match the Media Source API so their existing code can integrate with this library.
+-   CUDA mode nvcuda{CODEC}enc encode elements are renamed to nv{CODEC}enc and old nv{CODEC}enc implementations are removed
 
-### Closed Caption handling improvements
+-   Added support for CUDA Stream-Ordered allocator
 
--   ccconverter supports converting between the two CEA-608 fields.
+-   Added cudacompositor element which is equivalent to the software compositor element but uses CUDA
 
--   New cea608mux element for muxing multiple CEA-608 streams together.
+-   Added support for CUDA kernel precompile at plugin build time using nvcc and NVCODEC plugin can cache/reuse compiled CUDA
+    CUBIN/PTX
 
--   Various improvements and feature additions in the Rust-based closed caption elements. Check out the Rust plugins section
-    below for more details.
+-   cudaupload and cudadownload elements can support Jetson platform’s NVMM memory in addition to already supported desktop NVMM
+    memory
 
-### Precision Time Protocol (PTP) clock improvements
+-   Introduced nvdswrapper plugin which uses NVIDIA DeepStream SDK APIs with gst-cuda in an integrated way:
 
--   Many fixes and compatibility/interoperability improvements.
+    -   nvdsdewarp: NVIDIA NVWarp360 API based dewarping element
 
--   Better support for running on devices with multiple network interfaces.
+### GStreamer Direct3D12 integration
 
--   Allow sync to master clock on same host.
+-   New gst-d3d12 public library. The following elements are integrated with the gst-d3d12 library:
 
--   PTP clock support is now also available on Windows.
+    -   NVIDIA NVCODEC decoders and encoders can support D3D12 memory
+    -   Intel QSV encoders can accept D3D12 memory
+    -   All elements in dwrite plugin can support D3D12 memory
 
--   The standalone ptp-helper binary has been rewritten in Rust for portability and security. This works on Linux, Android,
-    Windows, macOS, FreeBSD, NetBSD, OpenBSD, DragonFlyBSD, Solaris and Illumos. Newly supported compared to the C version is
-    Windows. Compared to the C version various error paths are handled more correctly and a couple of memory leaks are fixed.
-    Otherwise it should work identically. The minimum required Rust version for compiling this is 1.48, i.e. the version
-    currently in Debian oldstable. On Windows, Rust 1.54 is needed at least.
+-   The d3d12 library and plugin can be built with MinGW toolchain now (in addition to MSVC)
 
--   New ptp-helper Meson build option so PTP support can be disabled or required.
+-   D3D12 video decoders and d3d12videosink are promoted to have higher rank than D3D11 elements
 
--   gst_ptp_init_full() allows for a more fine-grained and extensible configuration and initialization of the GStreamer PTP
-    subsystem, including TTL configuration.
+-   Added support for multiple mip-levels D3D12 textures:
 
-### Bayer 10/12/14/16-bit depth support
+    -   Newly added d3d12mipmapping element can generate D3D12 textures with multiple mip-levels
 
--   bayer2rgb and rgb2bayer now support bayer with 10/12/14/16 bit depths
+    -   max-mip-levels property is added to d3d12convert, d3d12videosink, and d3d12swapchainsink element, so that the elements
+        can generate an intermediate texture with multiple mip-levels in order to reduce downscale aliasing artifacts
 
--   v4l2src and videotestsrc now support bayer with 10/12/14/16 bit depths
+-   d3d12convert, d3d12videosink, and d3d12swapchainsink support the GstColorBalanceInterface to offer color balancing functions
+    such as hue, saturation, and brightness adjustment
 
--   imagefreeze gained bayer support as well
+-   Added d3d12ipcsink and d3d12ipcsrc elements for zero-copy GPU memory sharing between processes
 
-### MPEG-TS improvements
+-   d3d12upload and d3d12download support direct GPU memory copy between D3D12 and D3D12 resources
 
--   mpegtsdemux gained support for
-    -   segment seeking for seamless non-flushing looping, and
-    -   synchronous KLV
--   mpegtsmux now
-    -   allows attaching PCR to non-PES streams
-    -   allows setting of the PES stream number for AAC audio and AVC video streams via a new “stream-number” property on the
-        muxer sink pads. Currently the PES stream number is hard-coded to zero for these stream types.
-    -   allows writing arbitrary Opus channel mapping families and up to 255 channels
-    -   separate handling of DVB and ATSC AC3 descriptors
+-   Added d3d12swapchainsink element to support DirectComposition or UWP/WinUI3 SwapChainPanel based applications
 
-## New elements and plugins
+-   Added d3d12deinterlace element which performs deinterlacing using a GPU vendor agnostic compute shader.
 
--   analyticsoverlay visualises object-detection metas on a video stream.
+-   d3d12screencapturesrc element can capture HDR enabled desktop correctly in DDA mode (DXGI Desktop Duplication API)
 
--   autovideoflip and autodeinterlace are two new auto elements.
+### Capture and playout cards support
 
--   AJA source and sink elements plus device provider for AJA capture and playout cards, including support for HANC/VANC
-    ancillary data.
+-   ajasrc: Improve clock handling, frame counting, capture timestamping, and signal loss recovery
 
--   New cea608mux element for muxing multiple CEA-608 streams together.
+-   The Blackmagic Decklink plugin gained support
 
--   The codec2json plugin adds av12json, h2642json, h2652json and vp82json elements which convert AV1, H.264, H.265 and VP8
-    frame parameters into human readable JSON data, which is useful for debugging and testing purposes.
+    -   for HDR output and input (PQ + HLG static metadata)
 
--   New lc3 plugin with a decoder and encoder for the Bluetooth LC3 audio codec.
+    -   all modes of Quad HDMI recorder
 
--   New onnxinference element to run ONNX inference models on video buffers.
+    -   scheduling frames before they need to be displayed in decklinkvideosink
 
--   New rtppassthroughpay element which just passes RTP packets through unchanged, but appears like an RTP payloader element.
-    This is mostly useful for medias that simply pass through an existing RTP stream in gst-rtsp-server.
+### RTP and RTSP stack improvements
 
--   Qt6: qml6glsrc, qml6glmixer, qml6gloverlay, and qml6d3d11sink
+-   rtspsrc now supports client-managed MIKEY key management. Some RTSP servers (e.g. Axis cameras) expect the client to propose
+    the encryption key(s) to be used for SRTP / SRTCP. This is required to allow re-keying. This mode can be enabled by enabling
+    the "client-managed-mikey-mode" property and comes with a number of new signals ("request-rtp-key" and "request-rtcp-key"),
+    action signals ("set-mikey-parameter" and "remove-key") and properties ("hard-limit" and "soft-limit").
 
--   New SVT-AV1 encoder plugin, imported from SVT-AV1 but with many fixes.
+-   rtpbin: Add new “never” and “ntp” RTCP sync modes
 
--   Many exciting new Rust elements, see Rust section below.
+    -   Never is useful for some RTSP servers that report plain garbage both via RTCP SR and RTP-Info, for example.
+    -   NTP is useful if synchronization should only ever happen based on RTCP SR or NTP-64 RTP header extensions.
 
--   New DirectWrite text rendering and Direct3D12 plugins (see Windows section below).
+    This is part of a bigger refactoring of the synchronization / offsetting code in rtpbin, which also makes it regularly emit
+    the sync signal even if no new synchronisation information is available, controlled by the new "min-sync-interval" property.
 
--   New vaav1enc element for encoding video in AV1 (See VA-API section)
+-   rtpjitterbuffer: add RFC7273 active status to jitterbuffer stats so applications can easily check whether RFC7273 sync is
+    active.
 
--   New uvcsink element for exporting streams as UVC camera
+-   rtph265depay: Add "wait-for-keyframe" "request-keyframe" properties and improve request keyframe logic
 
-## New element features and additions
+-   rtppassthroughpay gained the ability to regenerate RTP timestamps from buffer timestamps via the new "retimestamp-mode"
+    property. This is useful in a relay RTSP server if one wants to do full drift compensation and ensure that the stream coming
+    out of gst-rtsp-server is not drifting compared to the pipeline clock and also not compared to the RTCP NTP times.
 
--   alphacombine supports I420_10LE now for 10-bit WebM/alpha support.
+-   New Rust RTP payloaders and depayloaders for AC3, AMR, JPEG, KLV, MPEG-TS (MP2T), MPEG-4 (MP4A, MP4G), Opus, PCMU (uLaw),
+    PCMA (aLaw), VP8, VP9.
 
--   The amfcodec for hardware-accelerated video encoding using the Advanced Media Framework (AMF) SDK for AMD GPUs gained some
-    new features:
+-   New rtpbin2 based on separate rtprecv and rtpsend elements
+
+### WebRTC improvements
 
-    -   10-bit and HDR support for H.265 / HEVC and AV1 video encoders
-    -   B-frame support in the H.264 encoder
-    -   Initial support of pre-analysis and pre-encoding
-    -   Initial support of Smart Access Video for optimal distribution amongst multiple AMD hardware instances.
+-   webrtcbin improvements
 
--   appsink: new “propose-allocation” signal so applications can provide a buffer pool or allocators to the upstream elements,
-    as well as “max-time” and “max-buffers” properties to configure the maximum size of the appsink-internal queue in addition
-    to the existing “max-bytes” property.
+    -   Make basic rollbacks work
 
--   autovideoconvert exposes colorspace and scaler elements for well know elements
+    -   Add "reuse-source-pads" property: When set to FALSE, if a transceiver becomes send-only or inactive then pre-existing
+        source pads will receive an EOS event and no further traffic even after further renegotiation. When TRUE, pads will
+        simply not receive any output when the negotiated transceiver state doesn’t have incoming traffic. If renegotiated
+        later, the pad will receive data again.
 
--   avtp: add AVTP Raw Video Format payload and de-payload support.
+    -   Early CNAME support (RFC5576): Have CNAME available to the jitterbuffer before the the first RTCP SR is received, for
+        rapid synchronization.
 
--   cacasink’s output driver can now be selected via the “driver” property.
+    -   New "post-rtp-aux-sender" signal to allow for placement of an object after rtpbin, before sendbin. This is useful for
+        objects such as congestion control elements, that don’t want to be burdened by the synchronization requirements of
+        rtpsession.
 
--   camerabin: various fixes and stability improvements
+    -   Create and associate transceivers earlier in negotiation, and other spec compliance improvements
 
--   clocksync: “QoS” property to optionally send QoS events upstream like a synchronising sink would.
+    -   Statistics generation improvements for bundled streams
 
--   cutter: can add GstAudioLevelMeta on output buffers, which can be enabled via the new “audio-level-meta” property.
+-   webrtcsink improvements:
 
--   dashdemux2 has a new “start-bitrate” property.
+    -   Support for more encoders: nvv4l2av1enc, vpuenc_h264 (for imx8mp), nvav1enc, av1enc, rav1enc and nvh265enc.
 
--   dashsink can now use the dashmp4mux muxer from the Rust plugins and will also produce better and RFC 6381-compatible codec
-    strings. The “suggested-presentation-delay” property allows to set the suggested presentation delay in the MPD.
+    -   The new "define-encoder-bitrates" signal allows applications to fine-tune the bitrate allocation for individual streams
+        in cases where there are multiple encoders. By default the bitrate is split equally between encoders.
 
--   deinterlace: Add support for 10/12/16-bit planar YUV formats
+    -   A generic mechanism was implemented to forward metas over the control channel.
 
--   The dvdspu subpicture overlay now implements GstVideoOverlayComposition support to make it work better with hardware
-    decoders where the video data should ideally stay on the GPU/VPU and the overlay blitting be delegated to the renderer.
+    -   Added a mechanism for SDP munging to handle server-specific quirks.
 
--   encodebin now automatically autoplugs timestamper elements such as h264timestamper or h265timestamper, based on new
-    “Timestamper” element factory type and rank.
+    -   Can expose a built-in web server and signalling server for prototyping and debugging purposes.
 
--   New fakevideodec element (see debugging section below).
+-   webrtcsink and webrtcsrc enhancements:
 
--   filesink: “file-mode” property to allow the ability to specify rb+ file mode, which overwrites an existing file. This is
-    useful in combination with splitmuxsink so that files can be pre-allocated which can be useful to reduce disk fragmentation
-    over time.
+    -   Support for raw payloads, i.e. uncompressed audio and video
 
--   flvmux: add “enforce-increasing-timestamps” property to allow disabling a hack that was added back in the day because
-    librtmp as used in rtmpsink would get confused by timestamps going backwards, but this is no longer required with rtmpsink2.
-    If set to true (still the default, for backwards compatibility), flvmux will modify buffers timestamps to ensure they are
-    always strictly increasing, inside one stream and also between the audio and video streams.
+    -   NTP & PTP clock signalling and synchronization support (RFC 7273)
 
--   giostreamsink: Add a property to close the stream on stop().
+    -   Generic data channel control mechanism for sending upstream events back to the sender (webrtcsink)
 
--   h264parse improved its AU boundary detection.
+-   webrtcsrc now has support for multiple producers
 
--   h264parse, h265parse, mpegvideoparse now support multiple unregistered user data SEI messages.
+## New elements and plugins
 
--   insertbin is now a registered element and available via the registry, so can be constructed via parse-launch and not just
-    via the insertbin API.
+-   Many exciting new Rust elements, see Rust section below.
 
--   jack: libjack is now loaded dynamically at runtime instead of linking it at build time. This means the plugin can be shipped
-    on Windows and macOS and will work if there’s a user-installed JACK server/library setup.
+-   webview2src: new Microsoft WebView2 based web browser source element
 
--   jpegparse now has a rank so it will be autoplugged if needed.
+-   h264ccextractor, h264ccinserter: H.264 closed caption extractor / inserter
 
--   kmssink: Add auto-detection for NXP i.MX8M Plus LCDIFv3, ST STM32 LTDC, and Texas Instruments TIDSS display controllers.
+-   h265ccextractor, h265ccinserter: H.265 closed caption extractor / inserter
 
--   matroskademux and matroskamux gained support for more raw video formats, namely RGBA64_LE, BGRA64_LE, GRAY10_BE32, GRAY16_LE
+-   h266parse
 
--   mpg123audiodec’s rank was changed from MARGINAL to PRIMARY so it’s now higher than avdec_mp3, as it works better with
-    “freeformat” MP3s.
+-   lcevch264decodebin
 
--   msdk:
+-   New VA elements (see below): vah266dec, vavp8enc, vajpegenc, vavp8alphadecodebin, vavp9alphadecodebin
 
-    -   DRM modifier support on Linux
+-   svtjpegxsdec, svtjpegxsenc: SVT JPEG XS decoder/encoder
 
-    -   only expose codecs and capabilities actually supported by the platform
+-   Many other new elements mentioned in other sections (e.g. CUDA, NVCODEC, etc.)
 
-    -   msdkvpp video post-processing:
+## New element features and additions
 
-        -   new “hdr-tone-mapping” property to enable HDR-to-SDR tone mapping
-        -   new compute scaling mode
+-   audioconvert enhancements:
 
-    -   Decoders sport D3D11 and VA integration, and the VP9 decoder supports certain resolution changes.
+    -   Add possibility to reorder input channels when audioconvert has unpositionned audio channels as input. It can now use
+        reordering configurations to automatically position those channels via the new "input-channels-reorder" and
+        "input-channels-reorder-mode" properties.
 
-    -   Encoders:
+    -   Better handling of setting of the mix matrix at run time
 
-        -   msdkh264enc, msdkh265enc**: “pic-timing-sei” property to insert pic timing SEI
-        -   msdkh264enc, msdkh265enc**: Add properties to allow different max/min-qp values for I/P/B frames
-        -   msdkh264enc: Added BGRx format DMABuf support
-        -   Advertise special image formats in low power mode
+    -   handles new GstRequestMixMatrix custom upstream event
 
--   mxfdemux gained support for FFV1 demuxing
+-   audiorate: Take the tolerance into account when filling gaps; better accounting of the number of samples added or dropped.
 
--   opusenc, opusdec now support decoding and encoding more than 8 channels, and can also handle unknown/unpositioned channel
-    layouts.
+-   av1enc: Add "timebase" property to allow configuring a specific time base, in line with what exists for vp8enc and vp9enc
+    already.
 
--   The oss plugin gained a device provider for audio device discovery
+-   av1parse can parse annexb streams now, and typefinding support has been added for annexb streams as well.
 
--   pcapparse learned how to handle the Linux “cooked” capture encapsulation v2
+-   The GTK3 plugin has gained support for OpenGL/WGL on Windows
 
--   Intel Quick Sync plugin improvements:
+-   fdsrc has a new "is-live" property to make it act like a live source and timestamp the received data with the clock running
+    time.
 
-    -   qsvh264enc gained more encoding options
-    -   qsvh265dec now supports GBR decoding and HEVC RExt profiles
+-   imagefreeze: Add support for JPEG and PNG
 
--   qtdemux now adds audio clipping meta when playing gapless m4a content, supports CENC sample grouping, as well as the SpeedHQ
-    video codec.
+-   kmssink: Extended the functionality to support buffers with DRM formats along with non-linear buffers
 
--   ristsrc gained support for dynamic payloads via the new “caps” and “encoding-name” properties. These can be used to make the
-    ristsrc receive other payload types than MPEG-TS.
+-   pitch now supports reverse playback
 
--   rtmp2src: a new “no-eof-is-error” property was added: There is currently no way for applications to know if the stream has
-    been properly terminated by the server or if the network connection was disconnected, as an EOS is sent in both cases. With
-    the property set, connection errors will be reported as errors, allowing applications to distinguish between both scenarios.
+-   queue can emit the notify signal on queue level changes if the "notify-levels" property has been set.
 
--   rtspsrc: new “extra-http-request-headers” property for adding custom http request headers when using http tunnelling.
+-   qroverlay: the "pixel-size" property has been removed in favour of a new "size" property with slightly different semantics,
+    where the size of the square is expressed in percent of the smallest of width and height.
 
--   sdpdemux now supports SDP source filters as per RFC 4570; audio-only or video-only streaming can be selected via the new
-    “media” property, and RTCP feedback can be disabled via the “rtcp-mode” property.
+-   rsvgdec: Negotiate resolution with downstream and scale accordingly
 
--   splitmuxsrc uses natural ordering to sort globbed filenames now, i.e. 0, 1, 2, 10, 11 instead of 0, 1, 10, 11, 2, …
+-   rtmp2: server authentication improvements
 
--   srt: Add more fields to the statistics to see how many packets were retransmitted and how many were dropped.
+    -   Mimic librtmp’s behaviour and support additional connection parameters for the connect packet, which are commonly used
+        for authentication, via the new "extra-connect-args" property.
 
--   switchbin: many improvements, especially for caps handling and passthrough.
+    -   Add support for Limelight CDN (llnw) authentication
 
--   taginject: a “scope” property was added to allow injection of global tags in addition to the current default which is stream
-    tags.
+-   scaletempo has gained support for a “fit-down” mode: In fit-down mode only 1.0 rates are supported, and the element will fit
+    audio data in buffers to their advertised duration. This is useful in speech synthesis cases, where elements such as
+    awspolly will generate audio data from text, and assign the duration of the input text buffers to their output buffers.
+    Translated or synthesised audio might be longer than the original inputs, so this makes sure the audio will be sped up to
+    fit the original duration, so it doesn’t go out of sync.
 
--   timeoverlay: add buffer-count and buffer-offset time modes.
+-   souphttpsrc: Add the notion of "retry-backoff" and retry on 503 (service unavailable) and 500 (internal server error) http
+    errors.
 
--   udpsrc: new “multicast-source” property to support IGMPv3 Source Specific Muliticast (SSM) as per RFC 4604.
+-   taginject now modifies existing tag events of the selected scope, with the new "merge-mode" property allowing finer control.
 
--   videoconvertscale, videoconvert: add a “converter-config” property to allow fine-tuning conversion parameters that are not
-    exposed directly as property.
+-   timecodestamper gained a new running-time source mode that converts the buffer running time into timecodes.
 
--   videoflip: many orientation tag handling fixes and improvements
+-   playbin3, uridecodebin3, parsebin
 
--   videorate: add “drop-out-of-segment” property to force dropping of out-of-segment buffers.
+    -   lots of stream-collection handling and stability/reliability fixes
+    -   error/warning/info message now include the URI (if known) and stream-id
+    -   missing plugin messages include the stream-id
 
--   volume now supports arbitrarily-large positive gains via a new “volume-full-range” property (it was not possibly to just
-    allow a bigger maximum value for the existing “volume” property for GstController-related backwards-compatibility reasons).
+-   videocodectestsink gained support for GBR_10LE, GRAY8 and GRAY10_LE{16,32} pixel formats
 
--   waylandsink, gtkwaylandsink: improved frame scheduling reducing frame drops and improve throughput.
+-   videoflip gained support for the Y444_16LE and Y444_16BE pixel formats
 
--   webpenc now has support for animated WebP which can be enabled via the new “animated” property. By default it will just
-    output a stand-alone WebP image for each input buffer, just like before.
+-   videoconvertscale:
 
--   wpe: added a WebProcess crash handler; gained WPEWebKit 2.0 API support.
+    -   Handle pixel aspect ratios with large numerators or denominators
+    -   Explicitly handle the overlaycomposition meta caps feature, so it doesn’t get dropped unnecessarily
 
--   x264enc gained support for 8-bit monochrome video (GRAY8).
+-   waylandsink prefers DMABuf over system memory now
 
--   ximagesrc gained navigation support (mouse and keyboard events).
+-   x264enc has a new "nal-hrd" property to make the encoder signal HRD information, which is required for Blu-ray streams,
+    television broadcast and a few other specialist areas. It can also be used to force true CBR, and will cause the encoder to
+    output null padding packets.
 
--   y4mdec now parses extended headers to support high bit depth video.
+-   zbar: add support for binary mode and getting symbols as raw bytes instead of a text string.
 
 ## Plugin and library moves
 
--   The AMR-NB and AMR-WB plugins have been moved from -ugly to -good.
+-   macOS: atdec was moved from the applemedia plugin in -bad to the osxaudio plugin in -good, in order to be able to share
+    audio-related helper methods.
 
 ## Plugin and element removals
 
--   The entire gst-omx package and plugin has been retired. See the OMX section below for more details.
-
--   The RealServer RTSP extension, RDT handling and PNM source have been removed from the realmedia plugin.
-
--   The kate subtitle plugin has been removed.
+-   None in this cycle
 
 ## Miscellaneous API additions
 
-GStreamer Core
-
--   gst_pipeline_get_configured_latency() and gst_pipeline_is_live() convenience functions to query liveness and configured
-    latency of a pipeline.
+### GStreamer Core
 
--   Plugins can now provide status info messages for plugins that will be displayed in gst-inspect-1.0 and is useful for dynamic
-    plugins that register features at runtime. They are now able to provide information to the user why features might not be
-    available. This is now used in the amfcodec, nvcodec, qsv, and va plugins.
+-   gst_meta_api_type_set_params_aggregator() allows setting an GstAllocationMetaParamsAggregator function for metas, which has
+    been implemented for GstVideoMeta and is used to aggregate alignment requirements of multiple tee branches.
 
--   GST_OBJECT_AUTO_LOCK() and GST_PAD_STREAM_AUTO_LOCK() are g_autoptr(GMutexLocker)-based helpers for GstPad and GstObject
-    that unlock the mutex automatically when the helper goes out of scope. This is not portable so should not be used in
-    GStreamer code that needs to be portable to e.g. Windows with MSVC.
+-   gst_debug_print_object() and gst_debug_print_segment() have been made public API. The can be used to easily get string
+    representations of various types of (mini)objects in custom log handlers.
 
--   gst_clear_context(), gst_clear_promise(), gst_clear_sample()
+-   Added gst_aggregator_push_src_event(), so subclasses don’t just push events directly onto the source pad bypassing the base
+    class without giving it the chance to send out any pending serialised events that should be sent out before.
 
--   gst_util_ceil_log2() and gst_util_simplify_fraction() utility functions
+-   GstMessage has gained APIs to generically add “details” to messages:
 
--   New TAG_CONTAINER_SPECIFIC_TRACK_ID tag for container specific track ID as used in an HTML5 context, plus basic support in
-    matroskademux, qtdemux, dashdemux and dashdemux2
+    -   gst_message_set_details()
+    -   gst_message_get_details()
+    -   gst_message_writable_details()
+    -   gst_message_parse_error_writable_details()
+    -   gst_message_parse_warning_writable_details()
+    -   gst_message_parse_info_writable_details() This is used in uridecodebin3 to add the triggering URI to any INFO, WARNING
+        or ERROR messages posted on the bus, and in decodebin3 to add the stream ID to any missing plugin messages posted on the
+        bus.
 
--   New utility functions to create a stream-id without a pad for elements:
+-   gst_util_floor_log2() returns smallest integral value not bigger than log2(v).
 
-    -   gst_element_decorate_stream_id()
-    -   gst_element_decorate_stream_id_printf_valist()
-    -   gst_element_decorate_stream_id_printf()
+-   gst_util_fraction_multiply_int64() is a 64-bit variant of gst_util_fraction_multiply().
 
--   GstQueueArray gained API for sorting and sorted insertion
+#### GstIdStr replaces GQuark in structure and caps APIs
 
--   Add strict GstStructure serialisation with gst_structure_serialize_full() in combination with GST_SERIALIZE_FLAG_STRICT
-    which only succeeds if the result can later be fully deserialised again.
+-   GQuarks are integer identifiers for strings that are inserted into a global hash table, allowing in theory for cheap
+    equality comparisons. In GStreamer they have been used to represent GstStructure names and field names. The problem is that
+    these strings once added to the global string table can never be freed again, which can lead to ever-increasing memory usage
+    for processes where such name identifiers are created based on external input or on locally-created random identifiers.
 
--   GstBaseSrc enhancements: the “automatic-eos” property can be used to do the equivalent to gst_base_src_set_automatic_eos().
-    gst_base_src_push_segment() sends a segment event right away which can be useful for subclasses like appsrc which have their
-    own internal queuing.
+-   GstIdStr is a new data structure made to replace quarks in our APIs. It can hold a short string inline, a static string, or
+    a reference to a heap-allocated longer string, and allows for cheap storage of short strings and cheap comparisons. It does
+    not involve access to a global hash table protected by a global lock, and as most strings used in GStreamer structures are
+    very short, it is actually more performant than quarks in many scenarios.
 
--   GstBaseSink gained a new custom GST_BASE_SINK_FLOW_DROPPED flow return which can be used by subclasses from the virtual
-    ::render method to signal to the base class that a frame is not being rendered. This is used in e.g. waylandsink and ensures
-    that elements such as fpsdisplaysink will correctly report the rate of frames rendered and dropped.
+-   GQuark-using APIs in GstStructure or GstCaps have been deprecated and equivalent APIs using GstIdStr have been added
+    instead. For more details about this change watch Sebastian’s GStreamer Conference presentation “GQuark in GStreamer
+    structures - what nonsense!”.
 
-GstDiscoverer
+-   Most applications and plugins will have been using the plain string-based APIs which are not affected by this change.
 
--   New “load-serialized-info” signal to retrieve a serialized GstDiscovererInfo
+#### GstVecDeque
 
-GstSDP
+-   Moved GstQueueArray as GstVecDeque into core for use in GstBus, the ringbuffer logger and in GstBufferPool, where an overly
+    complicated signaling mechanism using GstAtomicQueue and GstPoll was replaced with GstVecDeque and a simple mutex/cond.
 
--   Add gst_sdp_message_remove_media()
+-   GstQueueArray in libgstbase was deprecated in favour of GstVecDeque.
 
-Video Library
+-   GstAtomicQueue will be deprecated once all users in GStreamer have been moved over to GstVecDeque.
 
-DRM Modifier Support for dmabufs on Linux
+### Audio Library
 
-See section above.
+-   Added gst_audio_reorder_channels_with_reorder_map() which allows reordering the samples with a pre-calculated reorder map
+    instead of re-calculating the reorder map every time.
 
-List of Video Formats for Passthrough
+-   Add top-surround-left and top-surround-right channel positions
 
-New helper API was added to get a list of all supported video formats, including DMA_DRM formats, and can be used to advertise
-all supported formats for passthrough purposes:
+-   GstAudioConverter now supports more numerical types for the mix matrix, namely double, int, int64, uint, and uint64 in
+    addition to plain floats.
 
--   GST_VIDEO_FORMATS_ANY_STR, GST_VIDEO_FORMATS_ANY
--   gst_video_formats_any() which can be used by bindings or for code that prefers GstVideoFormat values instead of strings.
+### Plugins Base Utils Library
 
-New Video Formats
+-   New AV1 caps utility functions for AV1 Codec Configuration Record codec_data handling
 
--   12-bit and 16-bit A420 / A422 / A444 (YUV with alpha channel) variants:
+-   The GstEncodingProfile (de)serialization functions are now public
 
-    -   A444_12BE, A444_12LE
-    -   A422_12BE, A422_12LE
-    -   A420_12BE, A420_12LE
-    -   A444_16BE, A444_16LE
-    -   A422_16BE, A422_16LE
-    -   A420_16BE, A420_16LE
+-   GstEncodingProfile gained a way to specify a factory-name when specifying caps. In some cases you want to ensure that a
+    specific element factory is used while requiring some specific caps, but this was not possible so far. You can now do
+    e.g. qtmux:video/x-prores,variant=standard|factory-name=avenc_prores_ks to ensure that the avenc_prores_ks factory is used
+    to produce the variant of prores video stream.
 
--   8-bit A422 / A444 (YUV with alpha channel) variant:
+### Tag Library
 
-    -   A422
-    -   A444
+-   EXIF handling now support the CAPTURING_LIGHT_SOURCE tag
 
--   Planar 16-bit 4:4:4 RGB formats:
+-   Vorbis tag handling gained support for the LYRICS tag
 
-    -   GBR_16BE
-    -   GBR_16LE
+### Video Library and OpenGL Library
 
--   RBGA, intended to be used by hardware decoders where VUYA is only supported 4:4:4 decoding surface but the stream is encoded
-    with GBR color space, such as HEVC and VP9 GBR streams for example.
+-   gst_video_convert_sample(), gst_video_convert_sample_async() gained support for D3D12 conversion.
 
--   Two tiled Mediatek 10-bit formats:
+-   GstVideoEncoder: gst_video_encoder_release_frame() and gst_video_encoder_drop_frame() have been made available as public
+    API.
 
-    -   MT2110T
-    -   MT2110R
+-   Navigation: gained mouse double click event support
 
--   Tiled 10-bit NV12 format NV12_10LE40_4L4 (Verisilicon Hantro)
+-   Video element QoS handling was improved so as to not overshoot the QoS earliest time by a factor of 2. This was fixed in the
+    video decoder, encoder, aggregator and audiovisualizer base classes, as well as in the adaptivedemux, deinterlace,
+    monoscope, shapewipe, and (old) videomixer elements.
 
-## Miscellaneous performance, latency and memory optimisations
+-   GstVideoConverter gained fast paths for v210 to/from I420_10 / I422_10
 
--   liborc 0.4.35 (latest: 0.4.38) adds support for AVX/AVX2 and contains improvements for the SSE backend.
+-   New gst_video_dma_drm_format_from_gst_format() helper function that converts a video format into a dma drm fourcc / modifier
+    pair, plus gst_video_dma_drm_format_to_gst_format() which will do the reverse.
 
--   liborc 0.4.37 adds support for NEON on macOS on Apple ARM64 CPUs.
+-   In the same vein gst_gl_dma_buf_transform_gst_formats_to_drm_formats() and
+    gst_gl_dma_buf_transform_drm_formats_to_gst_formats() have been added to the GStreamer OpenGL support library.
 
--   Most direct use of the GLib GSLice allocator has been removed, as there is little evidence that it actually still provides
-    much advantage over the standard system allocator on Linux or Windows in 2024. There is strong evidence however that it
-    causes memory fragmentation for standard GStreamer workloads such as RTSP/RTP/WebRTC streaming.
+-   GLDisplay/EGL: Add API (gst_gl_display_egl_set_foreign()) for overriding foreign-ness of the EGLDisplay in order to control
+    whether GStreamer should call eglTerminate() or not.
 
--   As always there have been plenty of performance, latency and memory optimisations all over the place.
+-   Additional DMA DRM format definitions/mappings:
 
-## Tracing framework and debugging improvements
+    -   NV15, NV20, NV30
+    -   NV12_16L32S, MT2110T, MT2110R as used on Meditek SoCs
+    -   NV12_10LE40
+    -   RGB15, GRAY8, GRAY16_LE, GRAY16_BE
+    -   plus support for big endian DRM formats and DRM vendor modifiers
 
--   The gst-stats tool can now be passed a custom regular expression
+New Raw Video Formats
 
--   gst-debug-viewer from the devtools module has seen minor improvements and fixes
+-   Packed 4:2:2 YUV with 16 bits per channel:
+    -   Y216_LE, Y216_BE
+-   Packed 4:4:4:4 YUV with alpha, with 16 bits per channel:
+    -   Y416_LE, Y416_BE
+-   10-bit grayscale, packed into 16-bit words with left padding:
+    -   GRAY10_LE16
 
-New tracers
+### GstPlay Library
 
--   None in this release.
+-   Add stream-id based selection of streams to better match playbin3’s API:
+    -   Add accessors for the stream ID and selection API based on the stream ID:
+        -   gst_play_stream_info_get_stream_id()
+        -   gst_play_set_audio_track_id()
+        -   gst_play_set_video_track_id()
+        -   gst_play_set_subtitle_track_id()
+        -   gst_play_set_track_ids()
+    -   Deprecate the old index-based APIs:
+        -   gst_play_stream_info_get_index()
+        -   gst_play_set_audio_track()
+        -   gst_play_set_video_track()
+        -   gst_play_set_subtitle_track()
+    -   Remove old playbin support
+    -   Implement the track enable API based on stream selection
+-   Distinguish missing plugin errors and include more details (uri, and stream-id if available) in error/warning messages:
+    -   gst_play_message_get_uri()
+    -   gst_play_message_get_stream_id()
+    -   GST_PLAY_ERROR_MISSING_PLUGIN
+    -   gst_play_message_parse_error_missing_plugin()
+    -   gst_play_message_parse_warning_missing_plugin()
+-   Improve play message API inconsistencies:
+    -   Consistently name parse functions according to their message type:
+        -   gst_play_message_parse_duration_changed()
+        -   gst_play_message_parse_buffering()
+    -   Deprecate the misnamed functions:
+        -   gst_play_message_parse_duration_updated()
+        -   gst_play_message_parse_buffering_percent()
+    -   Add missing parse functions:
+        -   gst_play_message_parse_uri_loaded()
+        -   gst_play_message_parse_seek_done()
+-   Support disabling the selected track at startup
 
-Debug logging system improvements
+## Miscellaneous performance, latency and memory optimisations
 
--   Nothing major in this cycle.
+-   dvdspu: use multiple minimal sized PGS overlay rectangles instead of a single large one to minimise the total blitting
+    surface in case of disjointed rectangles.
 
-Fake video decoder
+-   video-frame: reduce number of memcpy() calls on frame copies if possible
 
--   The new fakevideodec element does not decode the input bitstream, it only reads video width, height and framerate from the
-    caps and then pushes out raw video frames of the expected size in RGB format.
+-   video-converter: added fast path conversions between v210 and I420_10 / I422_10
 
--   It draws a snake moving from left to right in the middle of the frame, which is reasonably light weight and still provides
-    an idea about how smooth the rendering is.
+-   As always there have been plenty of performance, latency and memory optimisations all over the place.
 
-## Tools
+## Miscellaneous other changes and enhancements
 
--   gst-launch-1.0 gained a new --prog-name command line option to set the program name, which will be used by GTK and GStreamer
-    to set the class or app-id.
+-   netclientclock: now also emits the clock synced signal when corrupted to signal that sync has been lost.
 
--   gst-play-1.0 now defaults to using playbin3, but can still be made to use the old playbin by passing the --use-playbin2
-    command line argument.
+-   GstValue, GstStructure: can now (de)serialize string arrays (G_TYPE_STRV)
 
-## GStreamer FFmpeg wrapper
+## Tracing framework and debugging improvements
 
--   New avvideocompare element to compare two incoming video buffers using a specified comparison method (e.g. SSIM or PSNR).
+-   dot files (pipeline graph dumps) are now written to disk atomically
 
--   Prefer using FFmpeg Musepack decoder/demuxer over musepackdec as they work better with decodebin3 and playbin3 which likes
-    to have parsers and decoders separate.
+-   tracing: add hooks for gst_pad_send_event_unchecked() and GstMemory init/free
 
--   Added codec mappings for AV1, MxPEG, FFVHuff video
+-   tracers: Simplify params handling using GstStructure and object properties and move tracers over to property-based
+    configuration (leaks, latency).
 
--   Added raw video format support for P010, VUYA, Y410, P012, Y212 and Y412.
+-   textoverlay, clockoverlay, timeoverlay: new "response-time-compensation" property that makes the element render the text or
+    timestamp twice: Once in the normal location and once in a different sequentially predictable location for every frame. This
+    is useful when measuring video latency by taking a photo with a camera of two screens showing the test video overlayed with
+    timeoverlay or clockoverlay. In these cases, you will often see ghosting if the display’s pixel response time is not great,
+    which makes it difficult to discern what the current timestamp being shown is. Rendering in a different location for each
+    frame makes it easy to tell what the latest timestamp is. In addition, you can also use the fade-time of the previous frame
+    to measure with sub-framerate accuracy when the photo was taken, not just clamped to the framerate, giving you a higher
+    precision latency value.
 
--   Newer, non-deprecated APIs are used by the plugin when built with FFmpeg 6.0 or newer.
+New tracers
 
--   The FFmpeg meson subproject wrap has been updated to v6.1
+-   memory-tracer: New tracer that can track memory usage over time
 
--   Note: see Known Issues section below for known issues with FFmpeg 6.0.0 and the latest FFmpeg 7.x release
+-   pad-push-timings: New tracer for tracing pad push timings
 
-## GStreamer RTSP server
+-   pcap-writer: New tracer that can store the buffers flowing through a pad as PCAP file
 
--   New “ensure-keyunit-on-start” property: While the suspend modes NONE and PAUSED provided a low startup latency for
-    connecting clients, it did not ensure that streams started on fresh data. With this new property it is possible to maintain
-    the low startup latency of those suspend modes while also ensuring that a stream starts on a key unit. Furthermore, by
-    setting the new “ensure-keyunit-on-start-timeout” property it is also possible to accept a key unit of a certain age, but
-    discard it if too much time has passed and instead force a new key unit.
+Dot tracer/viewer
 
--   rtspclientsink: apply “port-range” property for RTCP port selection as well
+-   New dots tracer that simplifies the pipeline visualization workflow:
+    -   Automatically configures dot file directory and cleanup
+    -   Integrates with the pipeline-snapshotS tracer to allow dumping pipeline on demand from the gst-dots-viewer web interface
+    -   Uses GST_DEBUG_DUMP_DOT_DIR or falls back to $XDG_CACHE_HOME/gstreamer-dots
+-   New gst-dots-viewer web tool for real-time pipeline visualization
+    -   Provides interface to browse and visualize pipeline dot files
+    -   Features on-demand pipeline snapshots via “Dump Pipelines” button
+    -   WebSocket integration for live updates
+    -   Uses GST_DEBUG_DUMP_DOT_DIR or falls back to $XDG_CACHE_HOME/gstreamer-dots
+-   Simple usage:
+    -   gst-dots-viewer (starts server)
+    -   GST_TRACERS=dots gst-launch-1.0 videotestsrc ! autovideosink (runs with tracer)
+    -   View at http://localhost:3000
 
-## GStreamer VA-API support
+Debug logging system improvements
 
-GstVA
+-   Nothing major in this cycle.
 
--   vah264dec, vah265dec, vavp8dec, vavp9dec, vampeg2dec and vaav1dec were promoted to rank PRIMARY+1 on Linux
+## Tools
 
--   Improved support for dmabuf use cases. All va elements now negotiate the new and improved dmabuf capabilities with explicit
-    modifiers. This supports both import and export of dmabufs.
+-   gst-inspect-1.0 documents tracer properties now and shows element flags
 
--   Added vaav1enc element, available in recent Intel and AMD GPUs
+-   gst-launch-1.0 will show error messages posted during pipeline construction
 
--   Added support for the experimental VA-Win32 backend. It needs at least libva 1.18
+## GStreamer FFmpeg wrapper
 
--   Improved handling of multi-GPU systems. Still, sharing buffers among them is not advised.
+-   Add support for H.266/VVC decoder
 
--   Bumped minimum libva version to 1.12
+-   Add mappings for the Hap video codec, the Quite OK Image codec (QOI) and the M101 Matrox uncompressed SD video codec.
 
--   Enhanced support for RadeonSI Mesa driver for 10bit decoding
+-   Don’t register elements for which we have no caps and which were non-functional as a result (showing unknown/unknown caps).
 
--   Register elements only for allowed drivers (Intel and Mesa, for the moment)
+-   The S302M audio encoder now supports up to 8 channels.
 
-GStreamer-VAAPI
+-   Various tag handling improvements in the avdemux wrappers, especially when there are both upstream tags and additional local
+    tags.
 
--   The new GstVA elements (see above) should be preferred when possible.
+-   Support for 10-bit grayscale formats
 
--   Ranks of decoders were demoted to NONE so they won’t be used automatically by playbin and similar elements anymore.
+## GStreamer RTSP server
 
--   Clean-ups and minimal fixes.
+-   GstRTSPOnvifMediaFactoryClass gained a ::create_backchannel_stream() vfunc. This allows subclasses to delay creation of the
+    backchannel to later in the sequence, which is useful in scenarios where the RTSP server acts as a relay and the supported
+    caps depend on the upstream camera, for example.
 
--   gstreamer-vaapi should be considered deprecated and may be discontinued as soon as the va plugin is fully feature
-    equivalent. Users who rely on gstreamer-vaapi are encouraged to migrate and test the va elements at the earliest
-    opportunity.
+-   The ONVIF backchannel example now features support for different codecs, including AAC.
 
-## GStreamer Video4Linux2 support
+## VA-API integration
 
--   New uvcsink element, based on v4l2sink allow streaming your pipeline as a UVC camera using Linux UVC Gadget driver.
+VA plugin
 
--   v4l2src now supports 10/12/14/16-bit bayer formats.
+-   New VA elements:
 
--   Stateful decoders now pass too large encoded frames over multiple buffers.
+    -   H.266 / VVC video decoder
+    -   VP8 video encoder
+    -   JPEG encoder
+    -   VP9 + VP8 alpha decodebin
 
--   AV1 Stateless video decoder.
+    Remember that the availability of these elements depends on your platform and driver.
 
--   Stateless decoders now tested using Virtual driver (visl), making it possible to run the tests in the cloud based CI
+-   There are a lot of improvements and bug fixes, to hightlight some of them:
 
-## GStreamer OMX
+    -   Improved B pyramid mode for both H264 and HEVC encoding when reference frame count exceeds 2, optimizing pyramid level
+        handling.
+    -   Enabled ICQ and QVBR modes for several encoders, including H264, H265, VP9 and AV1.
+    -   Updated rate control features by setting the quality factor parameter, while improving bitrate change handling.
+    -   Improved VP9 encoder’s ability to avoid reopening or renegotiating encoder settings when parameters remain stable.
+    -   Added functionality to adjust the trellis parameter in encoders.
+    -   Optimize encoders throughput with the introduction of output delay.
+    -   Added support for new interpolation methods for scaling and improvements for handling interlace modes.
 
--   The gst-omx module has been removed. The OpenMAX standard is long dead and even the Raspberry Pi OS no longer supports it.
-    There has not been any development since 1.22 was released. Users of these elements should switch to the Video4Linux-based
-    video encoders and decoders which have been the standard on embedded Linux for quite some time now.
+GStreamer-VAAPI is now deprecated
 
--   Hardware vendors which still use OpenMAX are known to have non-standard forks and it is recommended that they maintain it
-    while planning their move to the Video4Linux API.
+-   gstreamer-vaapi has been deprecated and is no longer actively maintained. Users who rely on gstreamer-vaapi are encouraged
+    to migrate to the va plugin’s elements at the earliest opportunity.
 
-## GStreamer Editing Services and NLE
+-   vaapi*enc encoders have been demoted to a rank of None, so will no longer be autoplugged in encodebin. They have also no
+    longer advertise dmabuf caps or unusual pixel formats on their input pad template caps.
 
--   Implement a gesvideoscale effect which gives user the ability to chooses where a clip has to be scaled in the chain of
-    effects. By default scaling is done in the compositor.
+## GStreamer Video4Linux2 support
 
--   Add support for gessrc as sub-timeline element so third party can implement their own formatters and use their timelines as
-    sub-timelines. Before that, only timelines serialized as files on the filesystem could be loaded as sub-timelines (using
-    gesdemux).
+-   Implemented DMA_DRM caps negotiation
 
--   Implement a new GESDiscovererManager singleton object making management of the discoverers used to discoverer media files
-    cleaner and allowing to expose the following APIs:
+-   Framerate negotiation improvements
 
-    -   load-serialize-info signal so GstDiscovererInfo can be serialized by users the way they like and load them without
-        requiring discovering the file when reloading a project.
-    -   source-setup signal so user can tweak source elements during discovery
+-   Support for P010 and BGR10A2_LE pixel formats
 
--   Expose GESFrameCompositionMeta in public API so user can implement their own effects targetting GES which take into account
-    that meta.
+-   The V4L2 stateless decoders now support inter-frame resolution changes for AV1 and VP9
 
--   Expose audioconvert:mix-matrix property in audio sources
+-   The V4L2 stateful encoders can now handle dynamic frame rates (0/1), and colorimetry negotiation was also improved.
 
--   Port GESPipeline rendering to use encodebin2. This allows rendering timelines directly with a muxing sink (like hlssinkX
-    etc..) and leverage all new features of that new element.
+## GStreamer Editing Services and NLE
 
-ges-launch
+-   Added support for reverse playback with a new reverse property on nlesource which is exposed child property on GESClip
 
--   Fix setting keyframes
+-   Input channels reordering for flexible audio channel mapping
 
--   Add an ignore-eos option
+-   Added support for transition in the ges-launch-1.0 timeline description format
 
--   Allow overriding container profile so that the user can build encoding profiles following the media format of a specific
-    media file, for example, but ensuring it is muxed using a specific format
+-   Added support for GstContext sharing in GESTimeline
 
--   Ensure sink elements are inside a GstBin and never in a GstPipeline
+-   Added basic support for duplicated children property in GESTimelineElement
 
--   Move +effect stack effects from source to last effect added, so it feels more natural to user as adding them at the
-    beginning of the chain while the syntax is +effect felt wrong
+-   validate: Add an action type to group clips
 
 ## GStreamer validate
 
--   In action types, add a way to avoid checking property value after setting it, in case elements do it async for example.
-
--   Add a vmethod to free GstValidateActionParameters to be more binding friendly.
+-   Added new action types:
 
--   Allow scenarios to define the pipeline state target in the metadata instead of assuming PLAYING state.
+    -   start-http-server: Start a new instance of our HTTP test server
+    -   http-requests: Send an HTTP request to a server, designed to work with our test http server
 
--   Add support to run sub-pipelines/scenarios
+-   HTTP server control endpoints to allow scenarios to control the server behavior, allowing simulating server failures from
+    tests
 
-    -   Added support to forward buffers from appsink to appsrc
+-   Improved the select-streams action type, adding support for selecting the same streams several times
 
--   Add a way to set pipeline base-time, start-time and force using the system clock.
+-   Added support for forcing monitoring of all pipelines in validatetest files
 
--   Add a ‘fill-mode’ to the appsrc-push action type so we can create some type of streams easily using an appsrc, giving
-    control when writing scenarios without requiring files with the content.
+-   Enhanced support for expected Error messages on the bus
 
--   Add a “select-streams” action type to test “stream aware” elements.
+-   Added ways to retrieve HTTP server port in .validatetest files
 
--   Add a way to wait for a property to reach a specified value before executing an action. For example it is possible to wait
-    for a pad to get some specific caps set before executing an action.
-
--   validate: Add support to replace variables in deeply nested structures in particular for more complex action types where
-    some of the properties are inside structures.
-
--   Fixed compatibility with Python 3.12.
+-   Added support for lldb in the gst-validate-launcher
 
 ## GStreamer Python Bindings
 
@@ -898,2292 +925,391 @@ and provides “syntactic sugar” in form of overrides for various GStreamer AP
 pythonic; as well as support for APIs that aren’t available through the regular gobject-introspection based bindings, such as
 e.g. GStreamer’s fundamental GLib types such as Gst.Fraction, Gst.IntRange etc.
 
--   Added a GstTagList override that makes a tag list act like a dict
+-   The python Meson build option has been renamed to python-exe (and will yield to the monorepo build option of the same name
+    if set, in a monorepo build context).
 
--   Fix build and usage in Windows
+-   Added an iterator for AnalyticsRelationMeta
 
--   Various fixes for Python >= 3.12
+-   Implement __eq__ for Mtd classes
 
--   Rework libpython loading to be relocatable
-
--   Fix libpython dlopen on macOS
+-   Various build fixes and Windows-related fixes.
 
 ## GStreamer C# Bindings
 
--   The GStreamer C# bindings have been updated to a more recent version of GtkSharp and the bindings have been regenerated with
-    that version.
-
--   GStreamer API added in recent GStreamer releases is now available
-
--   GstRtspServer bindings have been added, plus an RTSP server example
+-   The C# bindings have been updated for the latest GStreamer 1.26 API
 
 ## GStreamer Rust Bindings and Rust Plugins
 
-The GStreamer Rust bindings and plugins are released separately with a different release cadence that’s tied to the twice-a-year
-GNOME release cycle.
+The GStreamer Rust bindings and plugins are released separately with a different release cadence that’s tied to the gtk-rs
+release cycle.
 
-The latest release of the bindings (0.22) has already been updated for the new GStreamer 1.24 APIs, and works with any GStreamer
+The latest release of the bindings (0.23) has already been updated for the new GStreamer 1.26 APIs, and works with any GStreamer
 version starting at 1.14.
 
 gst-plugins-rs, the module containing GStreamer plugins written in Rust, has also seen lots of activity with many new elements
-and plugins. The GStreamer 1.24 binaries track the 0.12 release series of gst-plugins-rs, and fixes from newer versions will be
-backported as needed to the 0.12 brach for future 1.24.x bugfix releases.
+and plugins. The GStreamer 1.26 binaries will be tracking the main branch of gst-plugins-rs for starters and then track the 0.14
+branch once that has been released (around summer 2025). After that, fixes from newer versions will be backported as needed to
+the 0.14 branch for future 1.26.x bugfix releases.
 
 Rust plugins can be used from any programming language. To applications they look just like a plugin written in C or C++.
 
-### WebRTC
-
--   New element webrtcsrc that can act as a recvonly WebRTC client. Just like the opposite direction, webrtcsink, this can
-    support various different WebRTC signalling protocols. Some are included with the plugin and provide their own element
-    factory for easier usage but it is also possible for applications to provide new signalling protocol implementations.
-
--   webrtcsink now exposes the signaller as property and allows implementing a custom signaller by connecting signal handlers to
-    the default signaller.
-
--   A new signaller and webrtcsink implementation for Janus’ VideoRoom implementation. The corresponding webrtcsrc signaller
-    implementation is currently in a merge request in GitLab.
-
--   New whepsrc element that can receive WHEP WebRTC streams. This is currently not based on webrtcsrc but in the future a new
-    element around webrtcsrc will be added.
-
--   New whipserversrc element around webrtcsrc for ingesting WHIP WebRTC streams in GStreamer.
-
--   New whipclientsink element around webrtcsink for publishing WHIP WebRTC streams from GStreamer. This deprecates the old
-    whipsink element.
-
--   A new signaller and webrtcsink implementation for LiveKit. The corresponding webrtcsrc signaller implementation was merged
-    into the git repository recently.
-
--   A new signaller and webrtcsink implementation for AWS Kinesis Video Streams
-
--   webrtcsink has a new payloader-setup signal to allow the application more fine grained control over the RTP payloader
-    configuration, similar to the already existing encoder-setup signal for encoders.
-
--   webrtcsrc gained support for a custom navigation event protocol over the data channel, which is compatible with the
-    navigation event protocol supported by webrtcsink.
-
--   webrtcsink supports encoded streams as input. Using encoded streams will disable webrtcsinks congestion control changing any
-    encoded stream parameters.
+### New Rust elements
 
--   webrtcsink and webrtcsrc have a new signal ‘request-encoded-filter’ to allow transformations of the encoded stream. This can
-    be used, for example, for the same use-cases as the WebRTC Insertable Streams API.
+-   awstranscriber2, awstranslate: New elements around the AWS transcription and translation services.
 
--   gstwebrtc-api: JavaScript API for interacting with the default signalling protocol used by webrtcsink / webrtcsrc.
+-   cea708mux: New element that allows to mux multiple CEA708 services into a single stream.
 
-… and various other smaller improvements!
+-   cdpserviceinject: New element for injecting a CDP service descriptor into closed caption CDP packets
 
-### RTSP
+-   cea708overlay: New element for overlaying CEA608 / CEA708 closed captions over video streams.
 
--   New rtspsrc2 element. Only a subset of RTSP features are implemented so far:
-    -   RTSP 1.0 support
-    -   TCP, UDP, UDP-Multicast lower transports
-    -   RTCP SR, RTCP RR, RTCP-based A/V sync
-        -   Tested for correctness in multicast cases too
-    -   Lower transport selection and order (NEW!)
-        -   The existing rtspsrc has a hard-coded order list for lower transports
-    -   Many advanced features are not implemented yet, such as non-live support. See the README for the current status.
+-   gopbuffer: New element that can buffer a minimum duration of data delimited by discrete GOPs (Group of Picture)
 
-### GTK4
+-   hlscmafsink, hlssink3: New single-variant HLS sink elements that can output CMAF (fMP4) or MPEG-TS fragments.
 
--   Support for rendering GL textures on X11/EGL, X11/GLX, Wayland, macOS, and WGL/EGL on Windows.
+-   hlsmultivariantsink: New sink element that can output an HLS stream with multiple variants
 
--   Create a window for testing purposes when running in gst-launch-1.0 or if GST_GTK4_WINDOW=1 is set.
+-   mpegtslivesrc: New source element that can wrap a live MPEG-TS source (e.g. SRT or UDP source) and provides a clock based on
+    the PCR.
 
--   New background-color property for setting the color of the background of the frame and the borders, if any. This also allows
-    setting a fully transparent background.
+-   onvifmetadataextractor: New element that can extract ONVIF metadata from GstMetas into a separate stream
 
--   New scale-filter property for defining how to scale the frames.
+-   originalbuffer: New plugin with originalbuffersave / originalbufferrestore elements that allow saving an original buffer,
+    modifying it for analytics, and then restoring the original buffer content while keeping any additional metadata that was
+    added.
 
--   Add Python example application to the repository.
+-   polly: New element around the AWS text-to-speech polly services
 
--   Various bugfixes, including support for the new GTK 4.14 GL renderer. The plugin needs to be built with at least the
-    gtk_v4_10 feature to work with the new GTK 4.14 GL renderer, and will work best if built with the gtk_v4_14 feature.
+-   quinn: New plugin that contains various QUIC-based elements for working with raw QUIC streams, RTP-over-QUIC (RoQ) and
+    WebTransport.
 
-### Closed Caption
+-   relationmeta: New plugin with elements converting between GstRelationMeta and ONVIF XML metadata.
 
--   Add cea608tocea708 element for upconverting CEA-608 captions to their CEA-708 representation.
+-   New Rust RTP payloaders and depayloaders for AC3, AMR, JPEG, KLV, MPEG-TS (MP2T), MPEG-4 (MP4A, MP4G), Opus, PCMU (uLaw),
+    PCMA (aLaw), VP8, VP9.
 
--   Add support for translations within transcriberbin.
+-   New rtpbin2 based on rtprecv / rtpsend elements
 
--   awstranscriber supports translating the transcribed text into different languages, including multiple languages at the same
-    time.
-
--   awstranscriber is using the new HTTP/2-based API now instead of the WebSocket-based one.
-
-### Other new elements
-
--   New awss3putobjectsink that works similar to awss3sink but with a different upload strategy.
+-   speechmatics: New transcriber / speech-to-text and translation element
 
--   New hlscmafsink element for writing HLS streams with CMAF/ISOBMFF fragments.
+-   New spotifylyricssrc element for grabbing lyrics from Spotify.
 
--   New inter plugin with new intersink and intersrc elements that allow to 1:N connect different pipelines in the same process.
-    This is implemented around the appsrc / appsink-based StreamProducer API that is provided as part of the GStreamer Rust
-    bindings, and is also used inside webrtcsrc and webrtcsink.
+-   streamgrouper: New element that takes any number of streams as input and adjusts their stream-start events in such a way
+    that they all belong to the same stream group.
 
--   New livesync element that allows maintaining a contiguous live stream without gaps from a potentially unstable source.
+-   translationbin: Helper bin around translation elements, similar to the already existing transcriberbin for transcriptions.
 
--   New isomp4mux non-fragmented MP4 muxer element.
+-   tttocea708: New element for converting timed-text to CEA708 closed captions
 
-### Other improvements
+-   A VVdeC-based H.266 decoder element was added to the Rust plugins, based on the Fraunhofer Versatile Video Decoder library.
 
--   audiornnoise
-    -   Attach audio level meta to output buffers.
-    -   Add voice detection threshold property
--   fmp4mux
-    -   Add support for CMAF-style chunking, e.g. low-latency / LL HLS and DASH
-    -   Add support for muxing Opus, VP8, VP9 and AV1 streams
-    -   Add ‘offset-to-zero’ property and make media/track timescales configurable
--   hlssink3
-    -   Allow adding EXT-X-PROGRAM-DATE-TIME tag to the manifest.
-    -   Allow generating I-frame-only playlist
--   ndi
-    -   Closed Caption support in ndisrc / ndisink
-    -   Zero-copy output support in ndisrc for raw video and audio
--   spotifyaudiosrc: Support configurable bitrate
+For a full list of changes in the Rust plugins see the gst-plugins-rs ChangeLog between versions 0.12 (shipped with GStreamer
+1.24) and 0.14.x (shipped with GStreamer 1.26).
 
-For a full list of changes in the Rust plugins see the gst-plugins-rs ChangeLog between versions 0.9 (shipped with GStreamer
-1.22) and 0.12 (shipped with GStreamer 1.24).
-
-## Cerbero Rust support
-
--   As of GStreamer 1.24, the GStreamer Rust plugins are shipped as part of our binary packages on all major platforms. This
-    includes Android and iOS now in addition to macOS and Windows/MSVC.
+Note that at the time of GStreamer 1.26.0 gst-plugins-rs 0.14 was not released yet and the git main branch was included instead
+(see above). As such, the ChangeLog also did not contain the changes between the latest 0.13 release and 0.14.0.
 
 ## Build and Dependencies
 
--   Meson >= 1.1 is now required for all modules
+-   Meson >= 1.4 is now required for all modules
 
--   The GLib requirement has been bumped to >= 2.64
-
--   liborc >= 0.4.38 is strongly recommended
+-   liborc >= 0.4.41 is strongly recommended
 
 -   libnice >= 0.1.22 is strongly recommended, as it is required for WebRTC ICE consent freshness (RFC 7675).
 
--   gst-libav was updated for FFmpeg API deprecations and removals
-
--   libwebpmux is required for the animated WebP support
+-   The ASIO plugin dropped its external SDK header dependency, so it can always be built and shipped more easily.
 
--   The wpe plugin gained support for the WPEWebKit 2.0 API version
+-   Require tinyalsa >= 1.1.0 when building the tinyalsa plugin
 
--   Bumped minimum libva version to 1.12 for the va plugin.
+-   The srtp plugin now requires libsrtp2, support for libsrtp1 was dropped.
 
--   zxing: added support for the zxing-c++ 2.0 API
+Monorepo build
 
--   The ptp-helper for Precision Time Protocol (PTP) support in GStreamer core has been rewritten in Rust, and the minimum
-    required Rust version for building this is 1.48, i.e. the version currently in Debian oldstable. On Windows, at least Rust
-    1.54 is needed. There is a new ptp-helper Meson feature option that can be used to make sure everything needed for PTP
-    support is available (if set to ptp-helper=enabled). cargo is not required for building.
+-   The FFmpeg subproject wrap was updated to 7.1
 
--   gst-plugins-rs requires Rust 1.70 or newer.
-
--   Link to libsoup at build time in all cases on non-Linux, and only load it dynamically on Linux systems where we might need
-    to support a mix of applications with dependencies that might be using libsoup2 or libsoup3. A “soup-version” meson build
-    option was added to prefer a specific version. Distros should make sure that libsoup is still a package dependency, since
-    it’s still required at runtime for the soup and adaptivedemux2 plugins to function.
-
--   libjack is now dynamically loaded at runtime by the JACK audio plugin, and no longer a hard build dependency. However, it
-    still is a runtime dependency, so distros should make sure it remains a package dependency.
-
-Monorepo build (née gst-build)
-
--   There is now a top-level meson build option to enable/require webrtc
-
--   The FFmpeg subproject wrap was udpated to 6.1
-
--   A libvpx wrap was added (for VP8/VP9 software encoding/decoding)
+-   Many other wrap updates
 
 gstreamer-full
 
--   Add full static build support, including on Windows: Allow a project to use gstreamer-full as a static library and link to
-    create a binary without dependencies. Introduce the meson build option gst-full-target-type to select the build type:
-    dynamic (default) or static.
-
--   Registers all full features in a plugin now to offer the possibility to get information at the plugin level and get it from
-    the registry. All the full features are now registered in a fullstaticfeatures meta plugin instead of having a NULL plugin.
+-   No major changes
 
 Development environment
 
--   add VSCode IDE integration
+-   Local pre-commit checks via git hooks have been moved over to pre-commit, including the code indentation check.
 
--   gst-env.py: Output a setting for the prompt with --only-environment
+-   Code indentation checking no longer relies on a locally installed copy of GNU indent (which had different outcomes depending
+    on the exact version installed). Instead pre-commit will automatically install the gst-indent-1.0 indentation tool through
+    pip, which also works on Windows and macOS.
 
-### Cerbero
+-   A pre-commit hook has been added to check documentation cache updates and since tags.
 
-Cerbero is a meta build system used to build GStreamer plus dependencies on platforms where dependencies are not readily
-available, such as Windows, Android, iOS, and macOS.
+-   Many meson wrap updates, including to FFmpeg 7.1
 
-General improvements
+-   The uninstalled development environment should work better on macOS now, also in combination with homebrew (e.g. when
+    libsoup comes from homebrew).
 
--   New plugins have been added
-    -   codecalpha dvbsubenc rtponvif switchbin videosignal isac ivfparse inter rtspsrc2
--   JACK plugin is now available all platforms (previously only Linux), and will be loaded if the JACK library is found at
-    plugin load time
--   Several recipes were ported to meson, leading to faster builds and better MSVC support
-    -   ffmpeg, gperf, lame, libvpx, ogg, opencore-amr, sbc, speex, tiff, webrtc-audio-processing
-    -   For more information, please see the tracker issue
--   Some recipes are now outdated or unnecessary and have been removed:
-    -   intltool, libkate
--   Various recipe updated to their latest versions
--   Rust toolchain updated to 1.76.0 (latest as of writing)
--   Rust plugins are now stripped and debug info split out correctly, reducing their size
--   Fix several spurious build issues, especially with the Rust toolchain
--   CMake is picked up from the system if available
--   Cerbero will no longer OOM or consume excessive resources on low-end systems
--   Python recipes have been moved from setuptools to virtualenv
--   Fixed support for Python 3.12+
-
-macOS
-
--   Minimum macOS version has been increased to 10.13 (High Sierra)
-    -   Released 5½ years ago, >95% marketshare
--   Fix macOS app store validation issue caused by absolute RPATHs
--   Rosetta is automatically installed if required for universal builds on Apple Silicon
--   The official macOS binaries now also include static libs for the GStreamer Rust plugins
-
-iOS
-
--   Minimum iOS version has been increased to 12.0
--   The iOS binary packages now include the GStreamer Rust plugins
--   tremor and ivorbisdec plugins are no longer shipped on iOS
-
-Windows
-
--   New features shipped with the official binaries:
-    -   plugins: dwrite d3d12 (MSVC) soundtouch (MSVC) taglib (MSVC) webrtcdsp (MSVC)
-    -   plugin features: d3d11-wgc (Windows Graphics Capture Support)
-    -   libraries: gstdxva-1.0
--   New qml6 plugin can be built on Windows with the qt6 variant enabled
-    -   Similar to qt5, this plugin cannot be included in the official binaries
--   GLib process handling helpers for Windows are now shipped
--   Windows 11 SDK is now required for builds
-    -   Visual Studio 2019 and newer ship this SDK
--   MSYS is now deprecated for building Windows binaries, will be removed in the next release
-    -   MSYS2 is required, and the bootstrap script tools/bootstrap-windows.ps can install it for you
--   Windows bootstrap script tools/bootstrap-windows.ps1 is much more interactive and user-friendly now
--   Fixed Pango crash on 32-bit Windows
--   WiX packaging now works with cross-windows builds from linux
-
-Linux
-
--   Linux packages will now also include static libs for the GStreamer Rust plugins
--   Add Python support for multiarch distributions
--   Build fixes for various recipes on multiarch distributions
--   Use arch-specific libdir correctly on multiarch distributions
--   gst-omx was removed from gstreamer, and hence is no longer shipped
--   Fixed Gentoo support
--   Added support for RHEL 9
--   Added support for Rocky Linux
--   Added support for Manjaro Linux
-
-Android
-
--   Android NDK has been updated to r25c
-    -   Only the Clang toolchain is used from the NDK now (both target and host)
-    -   gnustl has been completely removed
--   The Android binary packages now include the GStreamer Rust plugins
--   tremor and ivorbisdec plugins are no longer shipped on Android
--   openh264 plugin no longer enables ASM optimizations on Android x86 due to relocation errors
+-   New python-exe Meson build option to override the target Python installation to use. This will be picked up by the
+    gst-python and gst-editing-sevices subprojects.
 
 ## Platform-specific changes and improvements
 
 ### Android
 
--   Add NDK implementation of Android MediaCodec. This reduces the amount of Java <-> native calls, which should reduce
-    overhead.
-
--   Add support for AV1 to the androidmedia video encoder and decoder.
+-   The recommended mechanism to build Android apps has changed from Android.mk to CMake-in-Gradle using
+    FindGStreamerMobile.cmake. Android.mk support has been deprecated and will be removed in the next stable release. For more
+    information, see below, in the Cerbero section.
+-   More H.264/H.265 profiles and levels have been added to the androidmedia hardware-accelerated video encoder and decoder
+    elements, along with mappings for a number of additional pixel formats for P010, packed 4:2:0 variants and RGBA layouts,
+    which fixes problems with android decoders refusing to output raw video frames with decoders that announce support for these
+    common pixel formats and only allow the ‘hardware surfaces output’ path.
 
 ### Apple macOS and iOS
 
--   osxaudio: audio clock improvements (interpolate based on system time)
-
--   Set activation policy in gst_macos_main() and in osxvideosink and glimagesink. Setting the policy to
-    NSApplicationActivationPolicyAccessory by default makes sure that we can activate windows programmatically or by clicking on
-    them. Without that, windows would disappear if you clicked outside them and there would be no way to bring them to front
-    again. This change also allows osxvideosink to receive navigation events correctly.
-
-### Windows
-
--   New DirectWrite text rendering plugin with dwriteclockoverlay, dwritetimeoverlay, dwritetextoverlay, dwritesubtitlemux, and
-    dwritesubtitleoverlay elements, including closed caption overlay support in dwritetextoverlay.
-
--   PTP clock support is now also available on Windows
-
--   qml6d3d11sink is a new Direct3D11 Qt6 QML sink for Windows as an alternative to the existing qml6glsink.
-
--   wasapi2 audio plugin:
-
-    -   Added an option to monitor a loopback device’s mute state
-    -   Allows process loopback capture on Windows 10
-
--   win32ipc supports zero-copy rendering now through a shared bufferpool.
-
--   Add a Windows-specific plugin loader implementation (gst-plugin-scanner), so plugin loading during registry updates happens
-    in an external process on Windows as well.
-
--   gst_video_convert_sample() which is often used for thumbnailing gained a D3D11 specific conversion path.
-
--   d3d11 plugin:
-
-    -   d3d11mpeg2dec element is promoted to PRIMARY + 1 rank
-    -   Added d3d11ipcsrc and d3d11ipcsink elements for zero-copy GPU memory sharing between multiple processes.
-    -   Added HLSL shader pre-compilation (at binary build time) support in MSVC build.
-    -   d3d11videosink and d3d11convert elements support 3D transform, MSAA (MultiSampling Anti-Aliasing) and anisotropic
-        sampling method.
-    -   Added support for more raw video formats by using compute shader. A list of supported raw video formats can be found in
-        the d3d11videosink plugin documentation.
-    -   Added d3d11overlay element for applications to be able to draw/blend an overlay image on Direct3D11 texture directly.
-
--   New Direct3D12 plugin: From a video decoding, conversion, composition, and rendering point of view, this new d3d12 plugin is
-    feature-wise near equivalent to the d3d11 plugin. Notable differences between d3d12 and d3d11 are:
-    -   The GStreamer Direct3D12 integration layer is not exposed as a GStreamer API yet. Thus, other plugins such as amfcodec,
-        nvcodec, qsv, and dwrite are not integrated with d3d12 yet.
-    -   H.264 video encoding support via d3d12h264enc element.
-        -   Direct3D12 video encoding API requires Windows 11 or DirectX 12 Agility SDK
-    -   IPC, overlay, and deinterlace elements are not implemented in d3d12
-    -   Windows Graphics Capture API based screen capturing is not implemented in d3d12
-    -   In this release, MSVC is the only officially supported toolchain for the d3d12 plugin build.
-    -   All d3d12 elements are zero ranked for now. Users will need to adjust rank of each d3d12 element via GST_PLUGIN_RANK
-        environment or appropriate plugin feature APIs if they want these elements autoplugged.
-
-## Documentation improvements
-
--   hotdoc has been updated to the latest version, and the theme has also been updated, which should fix various usability
-    issues.
-
-## Possibly Breaking Changes
-
--   gst_plugin_feature_check_version() has been updated to fix unexpected version check behaviour for git versions. It would
-    return TRUE if the plugin version is for a git development version (e.g. 1.24.0.1) and the check is for the “next” micro
-    version (1.24.1). Now it no longer does this. This just brings the runtime version check in line with the build time version
-    checks which have been fixed some time ago.
-
--   GstAudioAggregator and subclasses such as audiomixer now sync property values to output timestamp, which is what
-    GstVideoAggregator has been doing already since 2019, and which makes sense, as the properties need to change at every
-    output frame based on the output time because they may change even though the input frame is not changing.
-
--   rtpac3depay now outputs audio/x-ac3 instead of audio/ac3 as that is the canonical media format in GStreamer. audio/ac3 is
-    still sometimes accepted as input format for backwards compatibility (e.g. in rtpac3pay or ac3parse), but shouldn’t be
-    output.
-
--   timecodestamper: The “drop-frame” property now defaults to TRUE
-
--   The NVIDIA desktop GPU decoders nvh264sldec, nvh265sldec, nvvp8sldec and nvvp9sldec were renamed to nvh264dec, nvh265dec,
-    nvvp8dec and nvvp9dec, respectively.
-
-## Known Issues
-
--   There are known issues with FFmpeg version 6.0.0 due to opaque passing being broken in that version. This affects at least
-    avdec_h264, but may affect other decoders as well. Versions before 6.0.0, and 6.0.1 or higher are not affected.
-
--   gst-libav < 1.24.6 didn’t build against the latest FFmpeg 7.0 release. This has been worked on and tracked in this “libav:
-    Fix compatibility with ffmpeg 7” Merge Request.
-
-## Statistics
-
--   4643 commits
-
--   2405 Merge Requests
-
--   850 Issues
-
--   290+ Contributors
-
--   ~25% of all commits and Merge Requests were in Rust modules
-
--   4747 files changed
-
--   469633 lines added
-
--   209842 lines deleted
-
--   259791 lines added (net)
-
-## Contributors
-
-Aaron Boxer, Aaron Huang, Acky Xu, adixonn, Adrian Fiergolski, Adrien De Coninck, Akihiro Sagawa, Albert Sjölund, Alessandro
-Bono, Alexande B, Alexander Slobodeniuk, Alicia Boya García, amindfv, Amir Naghdinezhad, anaghdin, Anders Hellerup Madsen,
-Andoni Morales Alastruey, Antonio Kevo, Antonio Rojas, Arnaud Rebillout, Arnaud Vrac, Arun Raghavan, badcel, Balló György, Bart
-Van Severen, Bastien Nocera, Benjamin Gaignard, Bilal Elmoussaoui, Brad Hards, Camilo Celis Guzman, Carlo Cabrera, Carlos
-Falgueras García, Carlos Rafael Giani, Célestin Marot, Chao Guo, Charlie Blevins, Cheah, Vincent Beng Keat, Chris Degawa, Chris
-Spencer, Christian Curtis Veng, Christian Meissl, Christopher Degawa, Chris Wiggins, Cidana-Developers, Colin Kinloch, Damian
-Hobson-Garcia, Daniel Almeida, Daniel Knobe, Daniel Moberg, Daniel Morin, Daniel Pendse, Daniel Stone, Daniel Ulery, Dan
-Searles, Dario Marino Saccavino, Dave Patrick Caberto, David Craven, David Revay, David Rosca, David Svensson Fors, Detlev
-Casanova, Diego Nieto, Dominique Leroux, Dongyun Seo, Doug Nazar, Edward Hervey, Ekwang Lee, elenril, Elliot Chen, Enrique Ocaña
-González, Erik Fröbrant, Eva Pace, Evgeny Pavlov, Fabian Orccon, Felix Yan, Fernando Jiménez Moreno, Florian Zwoch, François
-Laignel, Frank Dana, Georges Basile Stavracas Neto, Guillaume Desmottes, Guillaume Gomez, Gwyn Ciesla, Haihua Hu, Hassene Tmar,
-hassount, Heiko Becker, He Junyan, hguermaz, Hiero32, Hosang Lee, Hou Qi, Hugo Svirak, Hugues Fruchet, Hu Qian, Hyung Song,
-Ignazio Pillai, Ilie Halip, Itamar Marom, Ivan Molodetskikh, Ivan Tishchenko, JackZhouVCD, Jacob Johnsson, jainl28patel, Jakub
-Adam, James Cowgill, James Hilliard, James Oliver, Jan Alexander Steffens (heftig), Jan Beich, Jan Schmidt, Jan Vermaete, Jayson
-Reis, Jeff Wilson, Jeongki Kim, Jeri Li, Jimmi Holst Christensen, Jimmy Ohn, Jochen Henneberg, Johan Adam Nilsson, Johan
-Sternerup, John King, Jonas Danielsson, Jonas K Danielsson, Jonas Kvinge, Jordan Petridis, Jordan Yelloz, Josef Kolář, Juan
-Navarro, Julien Isorce, Jun Zhao, Jurijs Satcs, Kalev Lember, Kamal Mostafa, kelvinhu325, Kevin Song, Khem Raj, Kourosh
-Firoozbakht, Leander Schulten, Leif Andersen, L. E. Segovia, Lieven Paulissen, lijing0010, Lily Foster, Link Mauve, Li Yuanheng,
-Loïc Le Page, Loïc Molinari, Lukas Geiger, Luke McGartland, Maksym Khomenko, Ma, Mingyang, Manel J, Marcin Kolny, Marc Leeman,
-Marc Solsona, Marc Wiblishauser, Marek Vasut, Marijn Suijten, Mark Hymers, Markus Ebner, Martin Nordholts, Martin Robinson, Mart
-Raudsepp, Marvin Schmidt, Mathieu Duponchelle, Matt Feury, Matthew Waters, Matthias Fuchs, Matthieu Volat, Maxim P. Dementyev,
-medithe, Mengkejiergeli Ba, Michael Bunk, Michael Gruner, Michael Grzeschik, Michael Olbrich, Michael Tretter, Michiel
-Westerbeek, Mihail Ivanchev, Ming Qian, Nader Mahdi, naglis, Nick Steel, Nicolas Beland, Nicolas Dufresne, Nirbheek Chauhan,
-Olivier Babasse, Olivier Blin, Olivier Crête, Omar Khlif, Onur Demiralay, Patricia Muscalu, Paul Fee, Pawel Stawicki, Peter
-Stensson, Philippe Normand, Philipp Zabel, PhoenixWorthVCD, Piotr Brzeziński, Priit Laes, Qian Hu, Rabindra Harlalka, Rafał
-Dzięgiel, Rahul T R, rajneeshksoni, Ratchanan Srirattanamet, renjun wang, Rhythm Narula, Robert Ayrapetyan, Robert Mader, Robert
-Rosengren, Robin Gustavsson, Roman Lebedev, Rouven Czerwinski, Ruben Gonzalez, Ruslan Khamidullin, Ryan Pavlik, Sanchayan Maity,
-Sangchul Lee, Scott Kanowitz, Scott Moreau, SeaDve, Sean DuBois, Sebastian Dröge, Sebastian Szczepaniak, Sergey Radionov,
-Seungha Yang, Shengqi Yu, Simon Himmelbauer, Slava Andrejev, Slawomir Pawlowski, soak, Stefan Brüns, Stéphane Cerveau, Stephan
-Seitz, Stijn Last, Talha Khan, Taruntej Kanakamalla, Jin Chung Teng, Théo Maillart, Thibault Saunier, Thomas Schneider,
-Tim-Philipp Müller, Tobias Rapp, Tong Wu, Tristan van Berkom, ttrigui, U. Artie Eoff, utzcoz, Víctor Manuel Jáquez Leal, Vivia
-Nikolaidou, Wang Chuan, William Manley, Wojciech Kapsa, Xabier Rodriguez Calvar, Xavier Claessens, Xuchen Yang, Yatin Maan,
-Yinhang Liu, Yorick Smilda, Yuri Fedoseev, Gang Zhao, Jack Zhou, …
-
-… and many others who have contributed bug reports, translations, sent suggestions or helped testing. Thank you all!
-
-Stable 1.24 branch
-
-After the 1.24.0 release there will be several 1.24.x bug-fix releases which will contain bug fixes which have been deemed
-suitable for a stable branch, but no new features or intrusive changes will be added to a bug-fix release usually. The 1.24.x
-bug-fix releases will be made from the git 1.24 branch, which will be a stable branch.
-
-1.24.0
-
-GStreamer 1.24.0 was released on 4 March 2024.
-
-1.24.1
-
-The first 1.24 bug-fix release (1.24.1) was released on 21 March 2024.
-
-This release only contains bugfixes and it should be safe to update from 1.24.0.
-
-Highlighted bugfixes in 1.24.1
-
--   Fix instant-EOS regression in audio sinks in some cases when volume is 0
--   rtspsrc: server compatibility improvements and ONVIF trick mode fixes
--   rtsp-server: fix issues if RTSP media was set to be both shared and reusable
--   (uri)decodebin3 and playbin3 fixes
--   adaptivdemux2/hlsdemux2: Fix issues with failure updating playlists
--   mpeg123 audio decoder fixes
--   v4l2codecs: DMA_DRM caps support for decoders
--   va: various AV1 / H.264 / H.265 video encoder fixes
--   vtdec: fix potential deadlock regression with ProRes playback
--   gst-libav: fixes for video decoder frame handling, interlaced mode detection
--   avenc_aac: support for 7.1 and 16 channel modes
--   glimagesink: Fix the sink not always respecting preferred size on macOS
--   gtk4paintablesink: Fix scaling of texture position
--   webrtc: Allow resolution and framerate changes, and many other improvements
--   webrtc: Add new LiveKit source element
--   Fix usability of binary packages on arm64 iOS
--   various bug fixes, memory leak fixes, and other stability and reliability improvements
-
-gstreamer
-
--   registry, ptp: Canonicalize the library path returned by dladdr
--   segment: Don’t use g_return_val_if_fail() in gst_segment_to_running_time_full()
--   uri: Sort uri protocol sources/sinks by feature name to break a feature rank tie
--   ptp: Initialize expected DELAY_REQ seqnum to an invalid value
--   ptp: Don’t install test executable
--   gst-inspect: fix –exists for plugins with versions other than GStreamer’s version, like the Rust plugins
--   identity: Don’t refuse seeks unless single-segment=true
-
-gst-plugins-base
+-   atenc: added an Apple AAC audio encoder
 
--   audiobasesink: Don’t wait on gap events
--   audioencoder: Avoid using temporarily mapped memory as base for input buffers
--   decodebin3: Be more specific when sending missing plugin messages
--   decodebin3: Fix re-usability issues
--   decodebin3: Provide clear error message if no decoders present
--   playbin3: Remove un-needed URI NULL check
--   uridecodebin3: Don’t hold lock when posting messages or signals
--   uridecodebin3: Handle potential double redirection errors
--   glimagesink: Fix the sink not always respecting preferred size on macOS
--   glupload: Do not propose allocators with sysmem, fixes warning when playing VP9 with alpha
--   shmallocator: fix build on Illumos
--   meson: Fix the condition to skip theoradec test
+-   atdec can now decode audio with more than two channels
 
-gst-plugins-good
+-   vtenc has received various bug fixes as well as a number of new features:
 
--   adaptivdemux/hlsdemux2: Fix issues with failure updating playlists
--   mpg123audiodec: Correctly handle the case of clipping all decoded samples
--   mpg123audiodec: gst_audio_decoder_allocate_output_buffer: assertion ‘size > 0’ failed
--   qt: Fix description in meson build options
--   qtdemux: Do not set channel-mask to zero
--   rtspsrc: remove ‘deprecated’ flag from the ‘push-backchannel-sample’ signal
--   rtspsrc: Consider 503 Service Not Available when handling broken control urls
--   rtspsrc, rtponviftimestamp: ONVIF mode fixes
--   rtspsrc: Don’t invoke close when stopping if we’ve started cleanup, fixing potential crash on shutdown
--   rtpgstpay: Delay pushing of event packets until the next buffer
+    -   Support for HEVC with alpha encoding via the new vtenc_h265a element
+    -   additional rate control options for constant bitrate encoding (only supported on macOS 13.0+ and iOS 16.0+ on Apple
+        Silicon), setting data rate limits, and emulating CBR mode via data rate limits where CBR is not supported.
+    -   HLG color transfer support
+    -   new "max-frame-delay" property (for ProRes)
 
-gst-plugins-bad
+-   Better macOS support for gst-validate tools which now use gst_macos_main() and support lldb
 
--   asio: Fix {input,output}-channels property handling
--   cuda,d3d11,d3d12bufferpool: Disable preallocation
--   d3d11device: Fix adapter LUID comparison in wrapped device mode
--   d3d12device: Fix IDXGIFactory2 leak
--   d3d12: Fix SDK debug layer activation
--   dvbsubenc: Fix bottom field size calculation
--   dvdspu: avoid null dereference
--   GstPlay: Fix a critical warning in error callback
--   v4l2codecs: decoders: Add DMA_DRM caps support
--   vaav1enc: Init the output_frame_num when resetting gf group
--   vah264enc, vah265enc, vaav1enc: fix potential crash on devices without rate control
--   vah265enc: checking surface alignment
--   videoparsers: Don’t verbosely warn about CEA_708_PROCESS_EM_DATA_FLAG not being set
--   vtdec: Fix a deadlock during ProRes playback, handle non-linked gracefully
+-   The osxaudio device provider exposes more properties including a unique id
 
-gst-plugins-ugly
+-   osxaudio will automatically set up AVAudioSession on iOS and always expose the maximum number of channels a device supports
+    with an unpositioned layout.
 
--   No changes
+-   The monorepo development environment should work better on macOS now
 
-GStreamer Rust plugins
+-   CMake apps that build macOS and iOS apps can consume GStreamer more easily now, using FindGStreamer.cmake or
+    FindGStreamerMobile.cmake respectively.
 
--   gtk4paintablesink: Fix scaling of texture position
--   janusvrwebrtcsink: Handle 64 bit numerical room ids
--   janusvrwebrtcsink: Don’t include deprecated audio/video fields in publish messages
--   janusvrwebrtcsink: Handle various other messages to avoid printing errors
--   livekitwebrtc: Fix shutdown behaviour
--   rtpgccbwe: Don’t forward buffer lists with buffers from different SSRCs to avoid breaking assumptions in rtpsession
--   sccparse: Ignore invalid timecodes during seeking
--   webrtcsink: Don’t try parsing audio caps as video caps
--   webrtc: Allow resolution and framerate changes
--   webrtcsrc: Make producer-peer-id optional
--   livekitwebrtcsrc: Add new LiveKit source element
--   regex: Add support for configuring regex behaviour
--   spotifyaudiosrc: Document how to use with non-Facebook accounts
--   webrtcsrc: Add do-retransmission property
+-   In the near future, CMake in Xcode will be the preferred way of building the iOS tutorials. See below, in the Cerbero
+    section.
 
-gst-libav
-
--   avcodecmap: Increase max AAC channels to 16
--   avviddec: Fix how we get back the codec frame
--   avviddec: Fix interlaced mode detection
--   avviddec: Double check if AV_CODEC_FLAG_COPY_OPAQUE port is safe for our scenario
-
-gst-rtsp-server
-
--   media: gst_rtsp_media_set_reusable() and gst_rtsp_media_set_shared() have become incompatible
--   rtsp-stream: clear sockets when leaving bin
-
-gstreamer-vaapi
-
--   No changes
-
-gstreamer-sharp
-
--   No changes
-
-gst-omx
-
--   No changes
-
-gst-python
-
--   No changes
-
-gst-editing-services
-
--   ges: Fix critical warning
-
-gst-validate + gst-integration-testsuites
-
--   No changes
-
-gst-examples
-
--   No changes
-
-Development build environment
-
--   No changes
-
-Cerbero build tool and packaging changes in 1.24.1
-
--   gstreamer: Enable ptp helper explicitly
--   gst-plugins-bad: Package new insertbin plugin
--   gst-plugins-rs: Adjust parallel architecture build blocks
--   libnice: update to 0.1.22
--   pixman: Bump to 0.43.4
--   orc: disable JIT code generation on arm64 on iOS again, fixing crashes
-
-Contributors to 1.24.1
-
-Alexander Slobodeniuk, Antonio Larrosa, Edward Hervey, Elizabeth Figura, François Laignel, Guillaume Desmottes, He Junyan, Jan
-Schmidt, Jordan Yelloz, L. E. Segovia, Mark Nauwelaerts, Mathieu Duponchelle, Michael Tretter, Mikhail Rudenko, Nicolas
-Dufresne, Nirbheek Chauhan, Philippe Normand, Piotr Brzeziński, Robert Mader, Ruijing Dong, Sebastian Dröge, Seungha Yang,
-Thomas Goodwin, Thomas Klausner, Tim-Philipp Müller, Xi Ruoyao,
-
-… and many others who have contributed bug reports, translations, sent suggestions or helped testing. Thank you all!
-
-List of merge requests and issues fixed in 1.24.1
-
--   List of Merge Requests applied in 1.24.1
--   List of Issues fixed in 1.24.1
-
-1.24.2
-
-The second 1.24 bug-fix release (1.24.2) was released on 9 April 2024.
-
-This release only contains bugfixes and it should be safe to update from 1.24.x.
-
-Highlighted bugfixes in 1.24.2
-
--   H.264 parsing regression fixes
--   WavPack typefinding improvements
--   Video4linux fixes and improvements
--   Android build and runtime fixes
--   macOS OpenGL memory leak and robustness fixes
--   Qt/QML video sink fixes
--   Package new analytics and mse libraries in binary packages
--   Windows MSVC binary packages: fix libvpx avx/avx2/avx512 instruction set detection
--   various bug fixes, memory leak fixes, and other stability and reliability improvements
-
-gstreamer
-
--   clock: Block futex_time64 usage on Android API level < 30
--   basesrc: Clear submitted buffer lists consistently with buffers
--   ptpclock: fix double free of domain data during deinit
--   clocksync: Proxy allocation queries
--   inputselector: fix possible clock leak on shutdown
--   typefind: Handle WavPack block sizes > 131072
-
-gst-plugins-base
-
--   glcolorconvert: Ensure glcolorconvert does not miss supported RGB formats
--   gl/macos: a couple of race/reference count fixes
--   pbutils: descriptions: Don’t warn on MPEG-1 audio caps without layer field
--   encodebin: Add the parser before timestamper to tosync list
--   videorate: Reset last_ts when a new segment is received
-
-gst-plugins-good
-
--   qml6glsink: fix destruction of underlying texture
--   qt/qt6: Fixup for dummy textures
--   rtpjitterbuffer: Don’t use estimated_dts to do default skew adjustment
--   rtpjitterbuffer: Use an extended RTP timestamp for the clock-base
--   rtpmp4adepay: Set duration on outgoing buffers
--   tests: rtpred: fix out-of-bound writes
--   v4l2: allocator: Fix unref log/trace on memory release
--   v4l2: Also set max_width/max_width if enum framesize fail
--   v4l2: enforce a pixel aspect ratio of 1/1 if no data are available
--   v4l2: fix error in calculating padding bottom for tile format
--   v4l2src: need maintain the caps order in caps compare when fixate
--   vpxenc: Include vpx error details in errors and warnings
-
-gst-plugins-bad
-
--   h264parse: element hangs with some video streams (regression)
--   h264parse: Revert “AU boundary detection changes”
--   alphadecodebin: Explicitly pass 64 bit integers as such through varargs
--   atdec: Set a channel mask for channel counts greater than 2
--   ccconverter: Fix caps leak and remove unnecessary code
--   d3d11videosink: disconnect signals before releasing the window
--   d3d11: meson: Add support for MinGW DirectXMath package and update directxmath wrap to 3.1.9
--   d3d11: meson: Disable library build if DirectXMath header was not found
--   dwrite: Fix crash on device update
--   GstPlay: Update video_snapshot to support playbin3
--   jpegparse: avi1 tag can be progressive
--   jpegparse: turn some bus warnings into object ones
--   qsvdecoder: Release too old frames
--   ristsrc: Only free caps if needed
--   va: av1enc: Correct the reference number and improve the reference setting
--   va: {vp9, av1}enc: Avoid reopen encoder or renegotiate
--   videoparsers: Demote CC warning message
--   vkbufferpool: correct usage flags type
--   vkh26xdec: a couple decoding fixes
--   vtdec: Fix caps criticals during negotiation
--   wpe: avoid crash with G_DEBUG=fatal_criticals and static build
--   Sink missing floating references
-
-gst-plugins-ugly
-
--   No changes
-
-GStreamer Rust plugins
-
--   aws: use fixed BehaviorVersion
--   aws: improve error message logs
--   fmp4: Update to dash-mpd 0.16
--   fmp4mux: Require gstreamer-pbutils 1.20 for the examples
--   onvifmetadataparse: Reset state in PAUSED->READY after pad deactivation, fixing occasional deadlock on shutdown
--   reqwest: Update to reqwest 0.12
--   webrtcsink: set perfect-timestamp=true on audio encoders
--   webrtcsink: improve panic message on unexpected caps during discovery
--   webrtchttp: Update to reqwest 0.12
--   webrtc: fix inconsistencies in documentation of object names
--   Fix clippy warnings after upgrade to Rust 1.77
-
-gst-libav
-
--   avviddec: Fix AVPacket leak
-
-gst-rtsp-server
-
--   No changes
-
-gstreamer-vaapi
-
--   No changes
-
-gstreamer-sharp
-
--   No changes
-
-gst-omx
-
--   No changes
-
-gst-python
-
--   No changes
-
-gst-editing-services
-
--   ges: frame-composition-meta: Stop using keyword ‘operator’ for field in C++
-
-gst-validate + gst-integration-testsuites
-
--   No changes
-
-gst-examples
-
--   webrtc examples: set perfect-timestamp=true on opusenc for better Chrome interoperability
-
-Development build environment
-
--   flac: Add subproject wrap and allow falling back to it in the flac plugin
--   libnice: bump subproject wrap to v0.1.22 (needed for ICE consent freshness support in gstwebrtc)
-
-Cerbero build tool and packaging changes in 1.24.2
-
--   glib: Block futex_time64 usage on Android API level < 30
--   libvpx: Fix build with Python 3.8
--   libvpx: Fix errors with avx* instruction set detection for x86* builds and MSVC
--   openjpeg: Update to 2.5.2
--   directxmath: Update to 3.1.9
--   gst-plugins-rs: Fix superstripping for ELF breaking all plugins
--   Rust-based plugin initialization hangs on Android with GStreamer 1.24.0
-
-Contributors to 1.24.2
-
-Alexander Slobodeniuk, Arnaud Vrac, Chao Guo, Chris Spencer, Daniel Morin, Edward Hervey, Elizabeth Figura, Elliot Chen, eri,
-François Laignel, Guillaume Desmottes, Haihua Hu, He Junyan, Hou Qi, Jan Schmidt, Jochen Henneberg, L. E. Segovia, Martin
-Nordholts, Matthew Waters, Nicolas Dufresne, Philippe Normand, Philipp Zabel, Piotr Brzeziński, Robert Guziolowski, Robert
-Mader, Ruben Gonzalez, Sebastian Dröge, Seungha Yang, Taruntej Kanakamalla, Thibault Saunier, Tim Blechmann, Tim-Philipp Müller,
-Víctor Manuel Jáquez Leal, Wojciech Kapsa, Xavier Claessens,
-
-… and many others who have contributed bug reports, translations, sent suggestions or helped testing. Thank you all!
-
-List of merge requests and issues fixed in 1.24.2
-
--   List of Merge Requests applied in 1.24.2
--   List of Issues fixed in 1.24.2
-
-1.24.3
-
-The third 1.24 bug-fix release (1.24.3) was released on 30 April 2024.
-
-This release only contains bugfixes and it should be safe to update from 1.24.x.
-
-Highlighted bugfixes in 1.24.3
-
--   EXIF image tag parsing security fixes
--   Subtitle handling improvements in parsebin
--   Fix issues with HLS streams that contain VTT subtitles
--   Qt6 QML sink re-render and re-sizing fixes
--   unixfd ipc plugin timestamp and segment handling fixes
--   vah264enc, vah265enc: Do not touch the PTS of the output frame
--   vah264dec and vapostproc fixes and improvements
--   v4l2: multiple fixes and improvements, incl. for mediatek JPEG decoder and v4l2 loopback
--   v4l2: fix hang after seek with some v4l2 decoders
--   Wayland sink fixes
--   ximagesink: fix regression on RPi/aarch64
--   fmp4mux, mp4mux gained FLAC audio support
--   D3D11, D3D12: reliablity improvements and memory leak fixes
--   Media Foundation device provider fixes
--   GTK4 paintable sink improvements including support for directly importing dmabufs with GTK 4.14
--   WebRTC sink/source fixes and improvements
--   AWS s3sink, s3src, s3hlssink now support path-style addressing
--   MPEG-TS demuxer fixes
--   Python bindings fixes
--   various bug fixes, memory leak fixes, and other stability and reliability improvements
-
-gstreamer
-
--   ptp: Silence Rust compiler warning about some unused trait methods
-
-gst-plugins-base
-
--   EXIF image tag parsing security fixes
--   glcolorconvert: remove some dead code
--   parsebin: Ensure non-time subtitle streams get “parsed”
--   playbin3: Handle combiner update in case of errors
--   ximagesink: initialize mask for XISelectEvents
-
-gst-plugins-good
-
--   adaptivedemux2: Playback hangs with VTT fragments
--   adaptivedemux2: Avoid double usage of parsebin
--   pulsedeviceprovider: Add compare_device_type_name function and missing lock
--   qml6glsink: Notify that the returned QSGNode node has changes
--   qml6glsink: video content resizes to new item size
--   qtdemux: fix wrong full_range offset when parsing colr box
--   soup: fix thread name
--   v4l2: add multiplane y42b (yuv422m) support (for mediatek v4l2 jpeg decoder)
--   v4l2: bufferpool: Drop writable check on output pool process
--   v4l2: bufferpool: Ensure freshly created buffers are not marked as queued, fixing issues with v4l2sink on a v4l2loopback
-    device
--   v4l2: bufferpool: queue back the buffer flagged LAST but empty, fixes hangs after seek with some decoders
--   v4l2: silence valgrind warning
--   vpx: Include vpx error details in errors and warnings
-
-gst-plugins-bad
-
--   d3d11device: protect device_lock vs device_new
--   d3d11decoder, d3d12decoder: Fix potential use after free
--   d3d11videosink: Fix rendering on keyed mutex enabled handle
--   d3d12decoder: Fix d3d12 resource copy
--   d3d12encoder: Fix buffer pool leak
--   d3d12videosink: HWND event handling related fixes
--   d3d12vp9dec: Fix Intel GPU crash occurred when decoding VP9 SVC
--   dvbsubenc: fixed some memory leaks and a crash
--   GstPlay: fix read duration failure issue for some type rtsp streams which have valid duration
--   mediafoundation: Fix device enumeration
--   mediafoundation: Fix infinite loop in device provider
--   tests: fix possible libscpp build failure in gst-plugins-bad
--   tsdemux, tsparse: Fix Program equality check
--   tsdemux: Disable smart program update
--   unixfdsink: Take segment into account when converting timestamps
--   va: videoformat: use video library to get DRM fourcc
--   va: radeonsi: DRM RGB formats doesn’t look correctly mapped to VA formats
--   vah264enc, vah265enc: Do not touch the PTS of output frame
--   vaav1enc: Change the alignment of output to “tu”
--   vaallocator: disable derived all together for Mesa <23.3
--   waylandsink: free staged buffer when do gst_wl_window_finalize
--   wlwindow: clear configure mutex and cond when finalize
--   waylandsink: config buffer pool with query size when propose_allocation
--   v4l2codecs: Don’t unref allocation query caps
-
-gst-plugins-ugly
-
--   No changes
-
-GStreamer Rust plugins
-
-Fixed:
-
--   hrtfrender: Use a bitmask instead of an int in the caps for the channel-mask
--   rtpgccbwe: Don’t log an error when pushing a buffer list fails while stopping
--   webrtcsink: Don’t panic in bitrate handling with unsupported encoders
--   webrtcsink: Don’t panic if unsupported input caps are used
--   webrtcsrc: Allow a None producer-id in request-encoded-filter signal
-
-Added:
-
--   aws: New property to support path-style addressing
--   fmp4mux / mp4mux: Support FLAC inside (f)MP4
--   gtk4: Support directly importing dmabufs with GTK 4.14
--   gtk4: Add force-aspect-ratio property similar to other video sinks
-
-gst-libav
-
--   libav: guard some recently dropped APIs
-
-gst-rtsp-server
-
--   No changes
-
-gstreamer-vaapi
-
--   No changes
-
-gstreamer-sharp
-
--   No changes
-
-gst-omx
-
--   No changes
-
-gst-python
-
--   Fix Python library name fetching and library searching on Windows
--   Don’t link to python for the gi overrides module
-
-gst-editing-services
-
--   ges-launcher: Fix for forcing container profiles
-
-gst-devtools, gst-validate + gst-integration-testsuites
-
--   debug-viewer: Fix plugin loading machinery
--   validate/flvdemux: Stop spamming audio/video on test
-
-gst-examples
-
--   No changes
-
-Development build environment
-
--   No changes
-
-Cerbero build tool and packaging changes in 1.24.3
-
--   No changes
-
-Contributors to 1.24.3
-
-Alexander Slobodeniuk, Edward Hervey, Elliot Chen, F. Duncanh, François Laignel, Haihua Hu, He Junyan, Hou Qi, Jan Schmidt,
-Jimmy Ohn, Maksym Khomenko, Matthew Waters, Nicolas Dufresne, Nirbheek Chauhan, Philippe Normand, Philipp Zabel, Qian Hu (胡骞),
-Sanchayan Maity, Sebastian Dröge, Seungha Yang, Simonas Kazlauskas, Taruntej Kanakamalla, Tim Blechmann, Tim-Philipp Müller, U.
-Artie Eoff, Víctor Manuel Jáquez Leal, William Wedler, Xavier Claessens,
-
-… and many others who have contributed bug reports, translations, sent suggestions or helped testing. Thank you all!
-
-List of merge requests and issues fixed in 1.24.3
-
--   List of Merge Requests applied in 1.24.3
--   List of Issues fixed in 1.24.3
-
-1.24.4
-
-The fourth 1.24 bug-fix release (1.24.4) was released on 29 May 2024.
-
-This release only contains bugfixes and it should be safe to update from 1.24.x.
-
-Highlighted bugfixes in 1.24.4
-
--   audioconvert: support more than 64 audio channels
--   avvidec: fix dropped frames when doing multi-threaded decoding of I-frame codecs such as DV Video
--   mpegtsmux: Correctly time out in live pipelines, esp. for sparse streams like KLV and DVB subtitles
--   vtdec deadlock fixes on shutdown and format/resolution changes (as might happen with e.g. HLS/DASH)
--   fmp4mux, isomp4mux: Add support for adding AV1 header OBUs into the MP4 headers, and add language from tags
--   gtk4paintablesink improvements: fullscreen mode and gst-play-1.0 support
--   webrtcsink: add support for insecure TLS and improve error handling and VP9 handling
--   v4l2codecs: decoder: Reorder caps to prefer DMA_DRM ones, fixes issues with playbin3
--   vah264enc, vah265enc: timestamp handling fixes; generate IDR frames on force-keyunit-requests, not I frames
--   Visualizer plugins fixes
--   Avoid using private APIs on iOS
--   Various bug fixes, memory leak fixes, and other stability and reliability improvements
-
-gstreamer
-
--   clock: Fix 32 bit assertions in GST_TIME_TO_TIMEVAL and GST_TIME_TO_TIMESPEC
--   systemclock: fix usage of __STDC_NO_ATOMICS__
--   filesrc: Don’t abort on _get_osfhandle() on Windows
--   tests: Avoid using “bool” for the variable name
--   Various Solaris / Illumos fixes
--   parse: Don’t assume that child proxy child objects are GstObjects
-
-gst-plugins-base
-
--   audioconvert: Support converting >64 channels
--   decodebin3: Fix caps and stream leaks
--   playbin(3), streamsynchronizer: Fix deadlock when streams have been flushed before others start
--   videotestsrc: fix race condition when clearing cached buffer
--   Fix visualization plugins
--   GstDiscoverer hangs when processing media file containing mebx on MacOS
--   glmixer: Add GL_SYNC_META option to buffer pool
--   typefinding: Fix ID_ODD_SIZE handling regression in WavPack typefinder
-
-gst-plugins-good
-
--   osxaudio: Avoid using private APIs on iOS
--   qtdemux: unit test fixes for 32-bit platforms
-
-gst-plugins-bad
-
--   cudamemory: Fix offset of subsampled planar formats
--   d3d11: Revert “d3d11device: protect device_lock vs device_new
--   d3dshader: Fix gamma and primaries conversion pixel shader
--   dtlsconnection: Fix overflow in timeout calculation on systems with 32 bit time_t
--   GstPlay: Initialize debug category and error quark in class_init
--   kmssink: Do not close the DRM prime handle twice
--   mpegtsmux: Correctly time out and mux anyway in live pipelines
--   nvcodec: Accept progressive-high profiles for h264
--   nvencoder: Fix maximum QP value setting
--   qsvh264dec, qsvh265dec: Fix nalu leaks
--   v4l2codecs: decoder: Reorder caps to prefer DMA_DRM ones
--   vah264enc, vah265enc: Let FORCE_KEYFRAME be IDR frame rather than just I frame
--   vah264enc, vah265enc: Set DTS offset before PTS
--   vkh26xdec: Fix stop memory leak
--   vtdec: Fix deadlock when negotiating format change
--   vtdec: Fix PAUSED->READY deadlock when output loop is running
--   wayland: Use wl_display_create_queue_with_name
--   webrtc: request-aux-sender, only sink floating refs
--   webrtcbin: Allow session level setup attribute in SDP
-
-gst-plugins-ugly
+### Windows
 
--   No changes
+-   webview2src: new Microsoft WebView2 based web browser source element
 
-GStreamer Rust plugins
+-   The mediafoundation plugin can also be built with MinGW now.
 
--   fmp4mux, isomp4mux: Add support for adding AV1 header OBUs into the MP4 headers
--   fmp4mux, isomp4mux: Add language from tags
--   gtk4paintablesink: Also create own window for gst-play-1.0
--   gtk4paintablesink: Add GST_GTK4_WINDOW_FULLSCREEN environment variable to fullscreen window for testing with
-    e.g. gst-launch-1.0
--   gtk4: Fix plugin description and update python examples
--   rtpgccbwe: Log effective bitrate in more places, and log delay and loss target bitrates separately
--   webrtcsink: Improve error when no encoder was found or RTP plugins were missing
--   webrtcsink: Add VP9 parser after the encoder for VP9 too
--   webrtc: Add support for insecure TLS connections
+-   The GTK3 plugin has gained support for OpenGL/WGL on Windows
 
-gst-libav
+-   qsv: Add support for d3d12 interop in encoder, via D3D11 textures
 
--   avvidec: Fix dropping wrong “ghost” frames - fixing multi-threaded decoding of I-frame codecs such as DV Video
+### Cerbero
 
-gst-rtsp-server
+Cerbero is a meta build system used to build GStreamer plus dependencies on platforms where dependencies are not readily
+available, such as Windows, Android, iOS, and macOS.
 
--   No changes
+General improvements
 
-gstreamer-vaapi
+-   New features:
 
--   No changes
+    -   Python bindings support has been re-introduced and now supports Linux, Windows (MSVC) and macOS. Simply downloading the
+        official binaries and setting PYTHONPATH to the appropriate directory is sufficient.
 
-gstreamer-sharp
+        -   This should make it easier for macOS and Windows users to use Python libraries, frameworks, and projects that use
+            GStreamer such as Pitivi and gst-python-ml.
 
--   No changes
+    -   Introspection support has been re-introduced on Linux, Windows (MSVC), and macOS.
 
-gst-omx
+    -   New variants assert and checks to disable GLib assertions and runtime checks for performance reasons. Please note that
+        these are not recommended because they have significant behavioural side-effects, make debugging harder, and should only
+        be enabled when targeting extremely resource-constrained platforms.
 
--   No changes
+-   API/ABI changes:
 
-gst-python
+    -   Libsoup has been upgraded from 2.74 to 3.6, which is an API and ABI breaking change. The soup and adaptivedemux2 plugins
+        are unchanged, but your applications may need updating since libsoup-2.4 and libsoup-3.0 cannot co-exist in the same
+        process.
 
--   No changes
+    -   OpenSSL has been updated from 1.1.1 to 3.4, which is an ABI and API breaking change. Plugins are unchanged, but your
+        applications may need updating.
 
-gst-editing-services
+-   Plugins added:
 
--   ges-pipeline: Configure encodebin before linking
+    -   The svt-av1 plugin is now shipped in the binary releases for all platforms.
 
-gst-devtools, gst-validate + gst-integration-testsuites
+    -   The svt-jpeg-xs plugin is now shipped in the binary releases for all platforms.
 
--   No changes
+    -   The x265 plugin is now shipped in the binary releases for all platforms.
 
-gst-examples
+    -   All gst-plugins-rs elements are now shipped in the binary releases for all platforms, except those that have C/C++
+        system-deps like GTK4. For a full list, see the Rust section above.
 
--   No changes
+-   Plugins changed:
 
-Development build environment
+    -   The rsvg plugin now uses librsvg written in Rust. The only side-effects of this should be better SVG rendering and
+        slightly larger plugin size.
 
--   No changes
+    -   The webrtc Rust plugin now also supports aws and livekit integrations .
 
-Cerbero build tool and packaging changes in 1.24.4
+-   Plugins removed:
 
--   Add Fedora 40 support
--   srt: bump version to 1.5.3
--   pango: Fix leaks on Windows (textoverlay plugins)
--   windows runtime installer has empty qt6 msm
--   WiX: assorted fixes
+    -   webrtc-audio-processing has been updated to 2.0, which means the isac plugin is no longer shipped.
 
-Contributors to 1.24.4
+-   Development improvements:
 
-Alexander Slobodeniuk, Bill Nottingham, Brad Reitmeyer, Chris Del Guercio, Daniel Stone, Edward Hervey, Emil Pettersson, He
-Junyan, Jordan Petridis, Joshua Breeden, L. E. Segovia, Martin Nordholts, Mathieu Duponchelle, Matthew Waters, Nirbheek Chauhan,
-Philippe Normand, Piotr Brzeziński, Rafael Carício, Robert Ayrapetyan, Robert Mader, Sebastian Dröge, Seungha Yang, Shengqi Yu,
-Stéphane Cerveau, Tim-Philipp Müller,
+    -   Support for the shell command has been added to cross-macos-universal, since the prefix is executable despite being a
+        cross-compile target
 
-… and many others who have contributed bug reports, translations, sent suggestions or helped testing. Thank you all!
+    -   More recipes have been ported away from Autotools to Meson and CMake, speeding up the build and increasing platform
+        support.
 
-List of merge requests and issues fixed in 1.24.4
+#### macOS
 
--   List of Merge Requests applied in 1.24.4
--   List of Issues fixed in 1.24.4
+-   Python bindings support on macOS only supports using the Xcode-provided Python 3
 
-1.24.5
+-   MoltenVK support in the applemedia plugin now also works on arm64 when doing a cross-universal build.
 
-The fifth 1.24 bug-fix release (1.24.5) was released on 20 June 2024.
+#### iOS
 
-This release only contains bugfixes and it should be safe to update from 1.24.x.
+-   CMake inside Xcode will soon be the recommended way to consume GStreamer when building iOS apps, similar to Android apps.
 
-Highlighted bugfixes in 1.24.5
+    -   FindGStreamerMobile.cmake is the recommended way to consume GStreamer now
 
--   webrtcsink: Support for AV1 via nvav1enc, av1enc or rav1enc encoders
--   AV1 RTP payloader/depayloader fixes to work correctly with Chrome and Pion WebRTC
--   av1parse, av1dec error handling/robustness improvements
--   av1enc: Handle force-keyunit events properly for WebRTC
--   decodebin3: selection and collection handling improvements
--   hlsdemux2: Various fixes for discontinuities, variant switching, playlist updates
--   qml6glsink: fix RGB format support
--   rtspsrc: more control URL handling fixes
--   v4l2src: Interpret V4L2 report of sync loss as video signal loss
--   d3d12 encoder, memory and videosink fixes
--   vtdec: more robust error handling, fix regression
--   ndi: support for NDI SDK v6
--   Various bug fixes, memory leak fixes, and other stability and reliability improvements
+    -   Tutorials and examples still use Xcode project files, but CMake support will be the active focus going forward
 
-gstreamer
+#### Windows
 
--   promise: Don’t use g_return_* for internal checks
--   debug: Add missing gst_debug_log_id_literal() dummy with gst_debug=false
--   ptp-helper: Add GNU/Hurd support
+-   The minimum supported OS version is now Windows 10.
 
-gst-plugins-base
+    -   GStreamer itself can still be built for an older Windows, so if your project is majorly impacted by this, please open an
+        issue with details.
 
--   uridecodebin3: Don’t hold PLAY_ITEMS lock when activating them
--   decodebin3: Always ensure we end up with parsebin or identity
--   decodebin3: Properly support changing input collections
--   decodebin3: Avoid usage of parsebin even more
--   decodebin3: Fix dealing with input without caps
--   video-info: Don’t crash in gst_video_info_is_equal() if one videoinfo is zero-initialized
+-   The Windows MSI installers are now based on WiX v5, with several improvements including a much faster MSI creation process,
+    improved naming in Add/Remove Programs, and more.
 
-gst-plugins-good
+    -   Windows installer packages: Starting with 1.26, due to security reasons, the default installation directory has changed
+        from C:\gstreamer to the Program Files folder, e.g. C:\Program Files (x86)\gstreamer for the 32-bit package on 64-bit
+        Windows. If you upgrade from 1.24 or older versions, the 1.26 installers will NOT keep using the existing folder.
+        Nevertheless if you were using C:\gstreamer we strongly recommend you double-check the install location.
 
--   flacparse: fix buffer overflow
--   hlsdemux2: Various fixes for discontinuities, variant switching, playlist updates
--   qml6glsink: fix RGB format support
--   rtpdtmfdepay: fix caps negotiation with audioconvert
--   rtpdtmfsrc: fix leak when shutting down mid-event
--   rtspsrc: fix invalid seqnum assertions
--   rtspsrc: Various control URL handling fixes
--   v4l2src: Interpret V4L2 report of sync loss as video signal loss
+    -   Note for MSI packagers: Starting with 1.26, the installers were ported to WiX 5.0. As part of this, the property for
+        setting the installation directory has been changed to INSTALLDIR, and it now requires a full path to the desired
+        directory, e.g. C:\gstreamer instead of C:\.
 
-gst-plugins-bad
+    -   Cross-MinGW build no longer supports the creation of MSIs. Please use tarballs.
 
--   av1parse: Do not return error when expectedFrameId mismatch
--   av1dec: Don’t treat decoding errors as fatal and print more error details
--   av1enc: Handle force-keyunit events properly by requesting keyframes
--   codectimestamper: never set DTS to NONE
--   d3d12encoder: Do not print error log for not-supported feature
--   d3d12memory: Fix staging buffer alignment
--   d3d12videosink: Disconnect window signal handler on dispose as intended
--   dtlssrtpenc: Don’t crash if no pad name is provided when requesting a new pad
--   glcolorconvert: update existing sync meta if outbuf has one
--   pcapparse: Parsing code assumes unaligned memory accesses are OK
--   pcapparse: Avoid unaligned memory access
--   tsdemux: Fix maximum PCR/DTS values
--   vtdec: Improve error handling in edge cases
--   vtdec, qtdemux: regression in 1.24.3 - internal data stream error
--   uvcgadget: Use g_path_get_basename instead of libc basename
+-   MinGW:
 
-gst-plugins-ugly
+    -   MinGW toolchain has been updated from GCC 8.2 → 14.2 and MinGW 6.0 → 12.0
 
--   No changes
+    -   The mediafoundation plugin is also shipped in the MinGW packages now.
 
-GStreamer Rust plugins
+    -   The d3d12 plugin is also shipped in the MinGW packages now.
 
--   gtk4: update flatpak integration code
--   ndi: Add support for loading NDI SDK v6
--   reqwesthttpsrc: Fix race condition when unlocking
--   rtp: Don’t restrict payload types for payloaders
--   rtp: av1pay: Correctly use N flag for marking keyframes
--   rtp: av1depay: Parse internal size fields of OBUs and handle them
--   webrtcsink: Refactor value retrieval to avoid lock poisoning
--   webrtcsink: Add support for AV1
--   webrtc: Update to async-tungstenite 0.26
--   Fix various new clippy 1.79 warnings
--   meson: Fix various issues in dependency management, feature detection, some regressions, and add logging
+    -   Rust support has been enabled on MinGW 64-bit. Rust support cannot work on 32-bit MinGW due to differences in exception
+        handling between our 32-bit MinGW toolchain and that used by the Rust project
 
-gst-libav
+-   The asio plugin is shipped now, since it no longer has a build-time dependency on the ASIO SDK.
 
--   No changes
+-   The new plugin webview2 is shipped with MSVC. It requires the relevant component shipped with Windows.
 
-gst-rtsp-server
+#### Linux
 
--   No changes
+-   Preliminary support for Alma Linux has been added.
 
-gstreamer-vaapi
+-   RHEL distro support has been improved.
 
--   No changes
+-   Cerbero CI now tests the build on Ubuntu 24.04 LTS.
 
-gstreamer-sharp
+-   curl is used for downloading sources on Fedora instead of wget, since they have moved to wget2 despite show-stopper
+    regressions such as returning a success error code on download failure.
 
--   No changes
+#### Android
 
-gst-omx
+-   CMake inside Gradle is now the recommended way to consume GStreamer when building Android apps
 
--   No changes
+    -   FindGStreamerMobile.cmake is the recommended way to consume GStreamer now
 
-gst-python
+    -   1.26 will support both CMake and Make inside Gradle, but the Make support will likely be removed in 1.28
 
--   No changes
+    -   Documentation updates are still a work-in-progress, help is appreciated
 
-gst-editing-services
+-   Android tutorials and examples are now built with gradle + cmake instead of gradle + make on the CI
 
--   No changes
+## Documentation improvements
 
-gst-devtools, gst-validate + gst-integration-testsuites
+-   Tracer objects information is now included in the documentation
 
--   No changes
+## Possibly Breaking Changes
 
-gst-examples
+-   qroverlay: the "pixel-size" property has been removed in favour of a new "size" property with slightly different semantics,
+    where the size of the square is expressed in percent of the smallest of width and height.
 
--   No changes
+-   svtav1enc: The SVT-AV1 3.0.0 API exposes a different mechanism to configure the level of parallelism when encoding, which
+    has been exposed as a new "level-of-parallelism" property. The old "logical-processors" property is no longer functional if
+    the plugin has been compiled against the new API, which might affect encoder performance if application code setting it is
+    not updated.
 
-Development build environment
+-   udpsrc: now disables allocated port reuse for unicast to avoid unexpected side-effects of SO_REUSEADDR where the kernel
+    allocates the same listening port for multiple udpsrc.
 
--   No changes
+-   uridecodebin3 remove non-functional "source" property that doesn’t make sense and always returned NULL anyway.
 
-Cerbero build tool and packaging changes in 1.24.5
-
--   osxrelocator: Fix RPATHs in deeply nested libraries
-
-Contributors to 1.24.5
-
-Angelo Verlain, Chris Del Guercio, Corentin Damman, Edward Hervey, Francisco Javier Velázquez-García, He Junyan, Jakub Adam,
-Jakub Vaněk, Khem Raj, L. E. Segovia, Martin Nordholts, Mathieu Duponchelle, Nirbheek Chauhan, Piotr Brzeziński, Samuel
-Thibault, Sebastian Dröge, Sergey Krivohatskiy, Seungha Yang, Tim-Philipp Müller, Zach van Rijn,
-
-… and many others who have contributed bug reports, translations, sent suggestions or helped testing. Thank you all!
-
-List of merge requests and issues fixed in 1.24.5
-
--   List of Merge Requests applied in 1.24.5
--   List of Issues fixed in 1.24.5
-
-1.24.6
-
-The sixth 1.24 bug-fix release (1.24.6) was released on 29 July 2024.
-
-This release only contains bugfixes and it should be safe to update from 1.24.x.
-
-Highlighted bugfixes in 1.24.6
-
--   Fix compatibility with FFmpeg 7.0
--   qmlglsink: Fix failure to display content on recent Android devices
--   adaptivedemux: Fix handling of closed caption streams
--   cuda: Fix runtime compiler loading with old CUDA tookit
--   decodebin3 stream selection handling fixes
--   d3d11compositor, d3d12compositor: Fix transparent background mode with YUV output
--   d3d12converter: Make gamma remap work as intended
--   h264decoder: Update output frame duration for interlaced video when second field frame is discarded
--   macOS audio device provider now listens to audio devices being added/removed at runtime
--   Rust plugins: audioloudnorm, s3hlssink, gtk4paintablesink, livesync and webrtcsink fixes
--   videoaggregator: preserve features in non-alpha caps for subclasses with non-system memory sink caps
--   vtenc: Fix redistribute latency spam
--   v4l2: fixes for complex video formats
--   va: Fix strides when importing DMABUFs, dmabuf handle leaks, and blocklist unmaintained Intel i965 driver for encoding
--   waylandsink: Fix surface cropping for rotated streams
--   webrtcdsp: Enable multi_channel processing to fix handling of stereo streams
--   Various bug fixes, memory leak fixes, and other stability and reliability improvements
-
-gstreamer
-
--   downloadbuffer: fix push mode
--   queue: queue2: multiqueue: Don’t work with segment.position if buffers have no timestamps
--   gst-inspect-1.0: Fix leak of plugin/feature
-
-gst-plugins-base
-
--   decodebin3: Fix detection of selection done
--   glvideomixer: Fix critical when setting start-time-selection
--   parsebin: accept-caps handling for elements with unusual sink pad names
--   subparse: Don’t use jit for regular expressions when running in valgrind
--   subparse: put valgrind header availability define into config.h for subparse
--   videoaggregator: preserve features in non-alpha caps
--   videoscale: correct classification error
--   meson: Fix invalid include flag in uninstalled gl pc file
--   Fix various memory leaks
-
-gst-plugins-good
-
--   adaptivedemux: Fix handling closed caption streams
--   qml/glsink: also support GLES2 needing shader ‘precision’ directives
--   v4l2object: use v4l2 reported width for padded_width when complex video formats
--   v4l2: meson: fix SIZEOF_OFF_T when cross-compiling with Meson >= 1.3.0
-
-gst-plugins-bad
-
--   svtav1enc: Fix segfault when flushing
--   avfdeviceprovider: Fix debug category initialization
--   osxaudiodeviceprovider: Listen for audio devices being added/removed
--   avtp: Fixed Linux/Alpine 3.20 build
--   cuda: Fix runtime compiler loading with old CUDA tookit
--   d3d11compositor, d3d12compositor: Fix transparent background mode with YUV output
--   d3d11converter: Fix runtime compiled shader code
--   d3d12converter: Make gamma remap work as intended
--   h264decoder: Update output frame duration when second field frame is discarded
--   isac: Work around upstream having no shared library support for MSVC
--   lc3: remove bitstream comparison in the tests
--   qroverlay: redraw overlay when caps changes
--   qsv: Fix critical warnings
--   rtmp2: guard against calling gst_amf_node_get_type() with NULL
--   srtsrc: fix case fallthrough of authentication param
--   va: Blocklist unmaintained i965 driver for encoding
--   va: Fix strides when importing DMABUFs
--   va: Fix dmabuf handle leaks
--   vadisplay: fix minor version check
--   vkh265dec: Fix H.264 ref in logs
--   vulkan: fix wrong stages or access in barriers
--   vtenc: Fix redistribute latency spam
--   waylandsink: Fix surface cropping for rotated streams
--   webrtcdsp: Enable multi_channel processing
-
-gst-plugins-ugly
-
--   asfdemux: Be more lenient towards malformed header, fixes playback of files written by VLC
-
-GStreamer Rust plugins
-
--   audioloudnorm: Fix limiter buffer index wraparound off-by-one for the last buffer
--   aws: s3hlssink: Do not call abort before finishing uploads
--   gtk4paintablesink: Support RGBx formats in SW paths
--   gtk4paintablesink: default to force-aspect-ratio=false for Paintable
--   livesync: Use the actual output buffer duration of gap filler buffers
--   livesync: Allow queueing up to latency buffers, also sync on the first buffer and add sync property
--   webrtcsink: fix property types for rav1enc AV1 encoder
-
-gst-libav
-
--   Fix compatibility with ffmpeg 7
--   avauddec: Fix crash on stop()
--   avmux: Fix crash when muxer doesn’t get codecid
-
-gst-rtsp-server
-
--   No changes
-
-gstreamer-vaapi
-
--   No changes
-
-gstreamer-sharp
-
--   No changes
-
-gst-omx
-
--   No changes
-
-gst-python
-
--   No changes
-
-gst-editing-services
-
--   ges: Various leak fixes
-
-gst-devtools, gst-validate + gst-integration-testsuites
-
--   validate: Remove G_REGEX_OPTIMIZE usage, helps avoid valgrind issues
-
-gst-examples
-
--   No changes
-
-Development build environment
-
--   libgudev wrap: add fallback uri
--   liblc3 wrap: update to v1.1.1
-
-Cerbero build tool and packaging changes in 1.24.6
-
--   meson: Backport fix for Glib including a GCC-only flag in the pkg-config file
--   libsoup: Workaround build error with GCC 14
--   libltc: Fix Windows build
--   webrtc-audio-processing: Fix MinGW build
--   libvpx: Also build a shared lib on macOS
--   glib: Fix Windows build
--   osxrelocator: Fix framework entrypoints being unable to load dylibs
--   gobject-introspection, recipe: Fix more fallout from the Meson dylib ID fixes
--   cargo-c.recipe: Ensure that we can change the id and rpath
-
-Contributors to 1.24.6
-
-Chris Spoelstra, Edward Hervey, François Laignel, Guillaume Desmottes, Jakub Adam, Jan Schmidt, Jordan Petridis, L. E. Segovia,
-Loïc Yhuel, Matthew Waters, Nirbheek Chauhan, Piotr Brzeziński, Robert Mader, Ruben Gonzalez, Sanchayan Maity, Sebastian Dröge,
-Sebastian Gross, Seungha Yang, Shengqi Yu, Taruntej Kanakamalla, Tim-Philipp Müller, tomaszmi, Víctor Manuel Jáquez Leal,
-
-… and many others who have contributed bug reports, translations, sent suggestions or helped testing. Thank you all!
-
-List of merge requests and issues fixed in 1.24.6
-
--   List of Merge Requests applied in 1.24.6
--   List of Issues fixed in 1.24.6
-
-1.24.7
-
-The seventh 1.24 bug-fix release (1.24.7) was released on 21 August 2024.
-
-This release only contains bugfixes and it should be safe to update from 1.24.x.
-
-Highlighted bugfixes in 1.24.7
-
--   Fix APE and Musepack audio file and GIF playback with FFmpeg 7.0
--   playbin3: Fix potential deadlock with multiple playbin3s with glimagesink used in parallel
--   qt6: various qmlgl6src and qmlgl6sink fixes and improvements
--   rtspsrc: expose property to force usage of non-compliant setup URLs for RTSP servers where the automatic fallback doesn’t
-    work
--   urisourcebin: gapless playback and program switching fixes
--   v4l2: various fixes
--   va: Fix potential deadlock with multiple va elements used in parallel
--   meson: option to disable gst-full for static-library build configurations that do not need this
--   cerbero: libvpx updated to 1.14.1; map 2022Server to Windows11; disable rust variant on Linux if binutils is too old
--   Various bug fixes, memory leak fixes, and other stability and reliability improvements
-
-gstreamer
-
--   bin: Don’t keep the object lock while setting a GstContext when handling NEED_CONTEXT
--   core: Log pad name, not just the pointer
-
-gst-plugins-base
-
--   pbutils: descriptions: use subsampling factor to get YUV subsampling
--   rtspconnection: Handle invalid argument properly
--   urisourcebin: Actually drop EOS on old-school pad switch
--   urisourcebin: Don’t hold lock when emitting about-to-finish
--   gst-launch deadlock with two playbin3s
--   xvimagesink: Fix crash in pool on error
-
-gst-plugins-good
-
--   qmlgl6src: Fix crash when use-default-fbo is not set
--   qt6glwindow: Fallback to GL_RGB on CopyTexImage2D error, fixing usage with eglfs backend
--   qt6glwindow: Only use GL_READ_FRAMEBUFFER when we do blits
--   qt6: glwindow: Don’t leak previously rendered buffer
--   rtspsrc: expose property for forcing usage of non-compliant URLs
--   v4l2object: fix ARIB_STD_B67 colorimetry unmatch issue
--   v4l2: Fix colorimetry mismatch for encoded format with RGB color-matrix
-
-gst-plugins-bad
-
--   aom: av1enc: restrict allowed input width and height
--   h264parse: bypass check for length_size_minus_one
--   h265parse: Reject FD received before SPS
--   msdk: replace strcmp with g_strcmp0
--   msdkvc1dec crashes (segfault)
--   rsvgoverlay: add debug category
--   va: don’t use GST_ELEMENT_WARNING in set_context() vmethod to fix potential deadlock
--   va: deadlock when playing two videos at once
--   webrtc: Add missing G_BEGIN/END_DECLS in header for C++
--   wpe: initialize threading.ready before reading it
-
-gst-plugins-ugly
-
--   No changes
-
-GStreamer Rust plugins
-
--   gtk4: Move the dmabuf cfg to the correct bracket level
-
-gst-libav
-
--   avdemux: Fix deadlock with FFmpeg 7.x when serialized events are received from upstream while opening, such as e.g. APE
-    files with tags
--   libav: return EOF when stream is out of data
--   avdemux: Never return 0 from read function, which would lead to infinite loops
-
-gst-rtsp-server
-
--   No changes
-
-gstreamer-vaapi
-
--   vaapi: Fix sps_max_dec_pic_buffering_minus1 value in h265 decoder
-
-gstreamer-sharp
-
--   No changes
-
-gst-omx
-
--   No changes
-
-gst-python
-
--   No changes
-
-gst-editing-services
-
--   nlecomposition: Don’t leak QoS events
-
-gst-devtools, gst-validate + gst-integration-testsuites
-
--   validate: Fix copying of action name
-
-gst-examples
-
--   No changes
-
-Development build environment
-
--   Add a meson option to disable gst-full for static-library build configurations that do not need this
-
-Cerbero build tool and packaging changes in 1.24.7
-
--   Disable rust variant on Linux if binutils is too old
--   Added 2022Server to the Windows platform distro map as Windows11
--   libvpx: Update to 1.14.1
-
-Contributors to 1.24.7
-
-David Rosca, Edward Hervey, Guillaume Desmottes, Hou Qi, Jan Schmidt, Jesper Jensen, Jordan Petridis, Jordan Yelloz, L. E.
-Segovia, Lyra McMillan, Mathieu Duponchelle, Max Romanov, Nicolas Dufresne, Nirbheek Chauhan, Qian Hu (胡骞), Sebastian Dröge,
-Tim-Philipp Müller, Víctor Manuel Jáquez Leal,
-
-… and many others who have contributed bug reports, translations, sent suggestions or helped testing. Thank you all!
-
-List of merge requests and issues fixed in 1.24.7
-
--   List of Merge Requests applied in 1.24.7
--   List of Issues fixed in 1.24.7
-
-1.24.8
-
-The eigth 1.24 bug-fix release (1.24.8) was released on 19 September 2024.
-
-This release only contains bugfixes and it should be safe to update from 1.24.x.
-
-Highlighted bugfixes in 1.24.8
-
--   decodebin3: collection handling fixes
--   encodebin: Fix pad removal (and smart rendering in gst-editing-services)
--   glimagesink: Fix cannot resize viewport when video size changed in caps
--   matroskamux, webmmux: fix firefox compatibility issue with Opus audio streams
--   mpegtsmux: Wait for data on all pads before deciding on a best pad unless timing out
--   splitmuxsink: Override LATENCY query to pretend to downstream that we’re not live
--   video: QoS event handling improvements
--   voamrwbenc: fix list of bitrates
--   vtenc: Restart encoding session when certain errors are detected
--   wayland: Fix ABI break in WL context type name
--   webrtcbin: Prevent crash when attempting to set answer on invalid SDP
--   cerbero: ship vp8/vp9 software encoders again, which went missing in 1.24.7; ship transcode plugin
--   Various bug fixes, memory leak fixes, and other stability and reliability improvements
-
-gstreamer
-
--   clock: Fix unchecked overflows in linear regression code
--   meta: Add missing include of gststructure.h
--   pad: Check data NULL-ness when probes are stopped
--   aggregator: Immediately return NONE from simple_get_next_time() on non-TIME segments
-
-gst-plugins-base
-
--   decodebin3: Fix collection identity check
--   encodebin: Fix pad removal
--   glimagesink: Fix cannot resize viewport when video size changed in caps
--   video: Don’t overshoot QoS earliest time by a factor of 2
--   meson: gst-play: link to libm
-
-gst-plugins-good
-
--   jackaudiosrc: actually use the queried ports from JACK
--   matroskamux: Include end padding in the block duration for Opus streams, fixing firefox compatibility
--   osxaudio: Avoid dangling pointer on shutdown
--   splitmuxsink: Override LATENCY query to pretend to downstream that we’re not live
--   v4l2bufferpool: actually queue back the empty buffer flagged LAST
--   v4l2videoenc: unref buffer pool after usage properly
--   v4l2: encoder: Add dynamic framerate support
-
-gst-plugins-bad
-
--   GstPlay: Name the different bus
--   GstPlay: check whether stream is seekable before seeking when state change
--   GstPlayer: Check GstPlayerSignalDispatcher type
--   mpegtsmux: Wait for data on all pads before deciding on a best pad unless timing out
--   mpegtsmux: Fix refcounting issue when selecting the best pad
--   uvcsink: fix caps event handling
--   v4l2codecs: h265: Minimize memory allocation
--   voamrwbenc: fix list of bitrates
--   vtenc: Restart encoding session when certain errors are detected
--   wayland: Fix ABI break in WL context type name
--   webrtcbin: Prevent crash when attempting to set answer on invalid SDP
--   wpe: fix gst-launch example
-
-gst-plugins-ugly
-
--   No changes
-
-GStreamer Rust plugins
-
--   No changes
-
-gst-libav
-
--   No changes
-
-gst-rtsp-server
-
--   No changes
-
-gstreamer-vaapi
-
--   No changes
-
-gstreamer-sharp
-
--   No changes
-
-gst-omx
-
--   No changes
-
-gst-python
-
--   No changes
-
-gst-editing-services
-
--   discoverer-manager: Fix race leading to assertion when stopping
--   structured-interface: Fix memory leak of invalid fields GList
-
-gst-devtools, gst-validate + gst-integration-testsuites
-
--   pad-monitor: Fix remaining pad function data handling
--   pad-monitor: Fix pad function data properly
-
-gst-examples
-
--   No changes
-
-Development build environment
-
--   meson: Update openjpeg wrap to 2.5.2, fixes a warning
-
-Cerbero build tool and packaging changes in 1.24.8
-
--   No vp8 / vp9 encoders packaged (regression)
--   libvpx: Fix codec detection to fix vp8enc/vp9enc elements not being shipped
--   gst-plugins-bad: Add missing transcode plugin
-
-Contributors to 1.24.8
-
-Andoni Morales Alastruey, Arun Raghavan, Benjamin Gaignard, Carlos Bentzen, Chao Guo, Edward Hervey, Francis Quiers, Guillaume
-Desmottes, Hou Qi, Jan Schmidt,, L. E. Segovia, Michael Tretter, Nicolas Dufresne, Nirbheek Chauhan, Peter Kjellerstedt,
-Philippe Normand, Piotr Brzeziński, Randy Li (ayaka), Sebastian Dröge, Thibault Saunier, Tim-Philipp Müller, Wim Taymans,
-
-… and many others who have contributed bug reports, translations, sent suggestions or helped testing. Thank you all!
-
-List of merge requests and issues fixed in 1.24.8
-
--   List of Merge Requests applied in 1.24.8
--   List of Issues fixed in 1.24.8
-
-1.24.9
-
-The ninth 1.24 bug-fix release (1.24.9) was released on 30 October 2024.
-
-This release only contains bugfixes and a security fix and it should be safe to update from 1.24.x.
-
-Highlighted bugfixes in 1.24.9
-
--   gst-rtsp-server security fix
--   GstAggregator start time selection and latency query fixes for force-live mode
--   audioconvert: fix dynamic handling of mix matrix, and accept custom upstream event for setting one
--   encodebin: fix parser selection for encoders that support multiple codecs
--   flvmux improvments for pipelines where timestamps don’t start at 0
--   glcontext: egl: Unrestrict the support base DRM formats
--   kms: Add IMX-DCSS auto-detection in sink and fix stride with planar formats in allocator
--   macOS main application event loop fixes
--   mpegtsdemux: Handle PTS/DTS wraparound with ignore-pcr=true
--   playbin3, decodebin3, parsebin, urisourcebin: fix races, and improve stability and stream-collection handling
--   rtpmanager: fix early RTCP SR generation for sparse streams like metadata
--   qml6glsrc: Reduce capture delay
--   qtdemux: fix parsing of rotation matrix with 180 degree rotation
--   rtpav1depay: added wait-for-keyframe and request-keyframe properties
--   srt: make work with newer libsrt versions and don’t re-connect on authentication failure
--   v4l2 fixes and improvement
--   webrtcsink, webrtcbin and whepsrc fixes
--   cerbero: fix Python 3.13 compatibility, g-i with newer setuptools, bootstrap on Arch Linux; iOS build fixes
--   Ship qroverlay plugin in binary packages - Various bug fixes, memory leak fixes, and other stability and reliability
-    improvements
--   Various bug fixes, build fixes, memory leak fixes, and other stability and reliability improvements
-
-gstreamer
-
--   aggregator: fix start time selection first with force-live
--   aggregator: fix live query when force-live is TRUE
--   parse-launch: Make sure children are bins before recursing in
--   macos: Fix race conditions in cocoa/application main event loop
--   multiqueue: Do not unref the query we get in pad->query
-
-gst-plugins-base
-
--   audioconvert: fix dynamic handling of mix matrix, accept custom upstream event for setting one
--   playback: Fix a variety of decodebin3/parsebin/urisourcebin races
--   playbin3: prevent crashing trying to play a corrupted mp4 file (WARNING : HIGH PITCHED CORRUPTED SOUND)
--   urisourcebin: Ensure all stream-start are handled
--   urisourcebin: Allow more cases for posting stream-collection
--   decodebin3: Make update/posting of collection messages atomic
--   decodebin3: send selected stream message as long as not all the tracks can’t select decoders
--   urisourcebin/parsebin: Improve collection creation and handling
--   encodebasebin: Miscellaneous fixes
--   allocators: drmdumb: Fix bpp value for P010
--   gldownload: use gst_gl_sync_meta_wait_cpu()
--   Revert “meson: Fix invalid include flag in uninstalled gl pc file”
--   gl: Fix configure error when libdrm is a subproject
--   glcontext: egl: Unrestrict the support base DRM formats
--   exiftag: Check the result of gst_date_time_new_local_time(), fixes criticals with malformed EXIF tags
-
-gst-plugins-good
-
--   flvmux: Use first running time on the initial header instead of 0
--   rtpmanager: skip RTPSources which are not ready in the RTCP generation
--   rtppassthroughpay: Fix reading clock-rate and payload type from caps
--   qml6glsrc: Reduce capture delay
--   qtdemux: fix parsing of matrix with 180 rotation
--   qtdemux: Check fourcc of a second CEA608 atom instead of assuming it’s cdt2
--   qtdemux: Skip zero-sized boxes instead of stopping to look at further boxes
--   twcc: Handle wrapping of reference time
--   v4l2object: append non colorimetry structure to probed caps
--   v4l2: Various fixes and improvement
-
-gst-plugins-bad
-
--   avfdeviceprovider: Fix leak from the GstCaps
--   codecparsers: add debug categories to bitwriters
--   codectimestamper: Fix gint wraparound in pts_compare_func
--   dvxa: Explicitly use cpp_std=c++11
--   GstPlay: message parsing and documentation improvements
--   h26xbitwriter: false have_space if aligning fails on aud
--   kmsallocator: fix stride with planar formats
--   kmssink: Add IMX-DCSS auto-detection
--   mpegtsdemux: Handle PTS/DTS wraparound with ignore-pcr=true
--   rtmp2sink: Initialize base_ts / last_ts with the actual first observed timestamp
--   scenechange: fix memory leak
--   srtsink: Register SRT listen callback before binding socket
--   srt: Don’t attempt to reconnect on authentication failures
--   tests: va: fix vapostproc test for DMABuf
--   tests: lc3: Allocate the same size for the buffer and the data
--   va: Fix libdrm include, plus meson and wrap changes
--   vaav1enc: Do not enable palette mode by default
--   vp8decoder: Fix resolution change handling
--   vtdec: add support for level 6 6.1 and 6.2
--   wayland: Add NV15 support
--   webrtcbin: Clean up bin elements when datachannel is removed
-
-gst-plugins-ugly
-
--   No changes
-
-GStreamer Rust plugins
-
--   Build: turn lto off for dev profile for faster dev builds
--   fmp4 hls_live example: Don’t set header-update-mode=update, no need to update the header in live mode
--   gtk4paintablesink: Don’t check for a GL context when filtering dmabuf caps
--   livesync: Log latency query results when handling latency query too
--   onvifmetadatapay: Set output caps earlier, so upstream can send gap events earlier
--   rtpav1depay: Add wait-for-keyframe and request-keyframe properties
--   spotify: tweak dependencies
--   transcriberbin: fix panic during gst-inspect-1.0 -u
--   webrtcsink: fix segment format mismatch with remote offer
--   webrtcsink: fix assertions when finalizing
--   webrtcsink: Fix typo in “turn-servers” property description
--   whepsrc: Fix incorrect default caps
-
-gst-libav
-
--   avviddec: Unlock video decoder stream lock temporarily while finishing frames
-
-gst-rtsp-server
-
--   rtsp-server: Remove pointless assertions that can happen if client provides invalid rates (security fix)
-
-gstreamer-vaapi
-
--   No changes
-
-gstreamer-sharp
-
--   No changes
-
-gst-omx
-
--   No changes
-
-gst-python
-
--   No changes
-
-gst-editing-services
-
--   ges: Fix name of GESFrameCompositionMeta API type (which caused gobject-introspection failures at build time)
-
-gst-devtools, gst-validate + gst-integration-testsuites
-
--   validate: Ignore flaky dash playbin3 issue
--   validate: Blacklist more netsim tests
-
-gst-examples
-
--   No changes
-
-Development build environment
-
--   No changes
-
-Cerbero build tool and packaging changes in 1.24.9
-
--   Fix Python 3.13 compatibility
--   gobject-introspection: Import patch to build against newer setuptools
--   Switch from wget to curl on Fedora 40 and newer
--   bootstrap: Add missing dependencies on Arch Linux
--   harfbuzz: Add CXXFLAGS to fix broken build on iOS
--   openssl.recipe: Stop using non-existent domain in primary tarball url
--   gst-plugins-bad: ship qroverlay plugin
-
-Contributors to 1.24.9
-
-Andoni Morales Alastruey, Arun Raghavan, Benjamin Gaignard, Corentin Damman, Dave Lucia, Edward Hervey, Elliot Chen, eri,
-Francisco Javier Velázquez-García, Guillaume Desmottes, He Junyan, Hugues Fruchet, Jakub Adam, James Cowgill, Jan Alexander
-Steffens (heftig), Jan Schmidt, Johan Sternerup, Jordan Petridis, L. E. Segovia, Mathieu Duponchelle, Nick Steel, Nicolas
-Dufresne, Nirbheek Chauhan, Ognyan Tonchev, Olivier Crête, Peter Stensson, Philippe Normand, Piotr Brzeziński, Sanchayan Maity,
-Sebastian Dröge, Shengqi Yu, Stéphane Cerveau, Théo Maillart, Thibault Saunier, Tim-Philipp Müller, Víctor Manuel Jáquez Leal,
-Weijian Pan, Xavier Claessens,
-
-… and many others who have contributed bug reports, translations, sent suggestions or helped testing. Thank you all!
-
-List of merge requests and issues fixed in 1.24.9
-
--   List of Merge Requests applied in 1.24.9
--   List of Issues fixed in 1.24.9
-
-1.24.10
-
-The tenth 1.24 bug-fix release (1.24.10) was released on 03 December 2024.
-
-This release only contains bugfixes and security fixes. It should be safe to update from 1.24.x and we would recommend you
-update at your earliest convenience.
-
-Highlighted bugfixes in 1.24.10
-
--   More than 40 security fixes across a wide range of elements following an audit by the GitHub Security Lab, including the
-    MP4, Matroska, Ogg and WAV demuxers, subtitle parsers, image decoders, audio decoders and the id3v2 tag parser.
--   avviddec: Fix regression that could trigger assertions about width/height mismatches
--   appsink and appsrc fixes
--   closed caption handling fixes
--   decodebin3 and urisourcebin fixes
--   glupload: dmabuf: Fix emulated tiled import
--   level: fix LevelMeta values outside of the stated range
--   mpegtsmux, flvmux: fix potential busy looping with high cpu usage in live mode
--   pipeline dot file graph generation improvements
--   qt(6): fix criticals with multiple qml(6)gl{src,sink}
--   rtspsrc: Optionally timestamp RTP packets with their receive times in TCP/HTTP mode to enable clock drift handling
--   splitmuxsrc: reduce number of file descriptors used
--   systemclock: locking order fixes
--   v4l2: fix possible v4l2videodec deadlock on shutdown; 8-bit bayer format fixes
--   x265: Fix build with libx265 version >= 4.1 after masteringDisplayColorVolume API change
--   macOS: fix rendering artifacts in retina displays, plus ptp clock fixes
--   cargo: Default to thin lto for the release profile (for faster builds with lower memory requirements)
--   Various bug fixes, build fixes, memory leak fixes, and other stability and reliability improvements
--   Translation updates
-
-gstreamer
-
--   allocator: Avoid integer overflow when allocating sysmem and avoid integer overflow in qtdemux theora extension parsing
--   deviceprovider: fix leaking hidden providers
--   gstreamer: prefix debug dot node names to prevent splitting
--   pad: Never push sticky events in response to a FLUSH_STOP
--   systemclock: Fix lock order violation and some cleanup
--   utils: improve gst_util_ceil_log2()
--   ptp: use ip_mreq instead of ip_mreqn for macos
--   tracers: unlock leaks tracer if already tracking
-
-gst-plugins-base
-
--   appsink: fix timeout logic for gst_app_sink_try_pull_sample()
--   appsrc: Fix use-after-free when making buffer / buffer-lists writable
--   audiostreamalign: Don’t report disconts for every buffer if alignment-threshold is too small
--   decodebin3: Unify collection switching checks
--   discoverer: Don’t print channel layout for more than 64 channels
--   discoverer: Make sure the missing elements details array is NULL-terminated in a thread-safe way
--   discoverer: fix segfault in race condition adding a new uri
--   id3v2: Don’t try parsing extended header if not enough data is available
--   glupload: dmabuf: Fix emulated tiled import
--   gl: cocoa: fix rendering artifacts in retina displays
--   gl: meson: Don’t use libdrm_dep in cc.has_header()
--   oggstream: fix invalid ogg_packet->packet accesses, address invalid writes CVE
--   opusdec: Set at most 64 channels to NONE position
--   playbin: Fix caps leak in get_n_common_capsfeatures()
--   playbin3: ERROR when setting new HLS URI with instant-uri=true
--   sdp: Add debug categories for message and mikey modules
--   ssaparse: Search for closing brace after opening brace
--   splitmuxsrc: Convert part reader to a bin with a non-async bus
--   subparse: Check for NULL return of strchr() when parsing LRC subtitles
--   streamsynchronizer: Only send GAP events out of source pads
--   urisourcebin: Also use event probe for HLS use-cases
--   video-converter: Set TIME segment format on appsrc
--   vorbisdec: Set at most 64 channels to NONE position
--   Translation for gst-plugins-base 1.24.0 not sync-ed with Translation Project
--   Update translations
-
-gst-plugins-good
-
--   avisubtitle: Fix size checks and avoid overflows when checking sizes
--   flvmux: Don’t time out in live mode if no timestamped next buffer is available
--   gdkpixbufdec: Check if initializing the video info actually succeeded
--   jpegdec: Directly error out on negotiation failures
--   level: Fix integer overflow when filling LevelMeta
--   level: produces level value outside of Stated Range
--   matroskademux: header parsing fixes
--   qtdemux: header and sample table parsing fixes
--   qtdemux: avoid integer overflow in theora extension parsing
--   qt(6)/material: ensure that we always update the context in setBuffer()
--   rtspsrc: Optionally timestamp RTP packets with their receive times in TCP/HTTP mode
--   rtp: Fix precision loss in gst_rtcp_ntp_to_unix()
--   rtpfunnel: Ensure segment events are forwarded after flushs
--   rtpmanager: don’t map READWRITE in twcc header ext
--   rtph264depay, rtph265depay: Fix various OOB reads / NULL pointer dereferences in parameter-set string handling
--   shout2send: Unref event at the end of the event function
--   udpsrc: protect cancellable from unlock/unlock_stop race
--   v4l2object: Fixed incorrect maximum value for int range
--   v4l2object: Remove little endian marker on 8 bit bayer format names
--   v4l2videodec: fix freeze race condition
--   wavparse: Fix various (missing) size checks and other parsing problems
-
-gst-plugins-bad
-
--   ccconverter: Don’t override in_fps_entry when trying to take output
--   ccutils fixes
--   kmssink: Add mediatek auto-detection
--   mpegtsmux: Don’t time out in live mode if no timestamped next buffer is available (fixes busy loop with high cpu usage)
--   mpegvideoparse: do not set delta unit flag on unknown frame type
--   mxfmux: Fix off-by-one in the month when generating a timestamp for now
--   timecodestamper: Don’t fail the latency query in LTC mode if we have no framerate
--   webrtc: don’t crash on invalid bundle id
--   x265: Allow building with x265-4.1 (after masteringDisplayColorVolume API change)
--   meson: Don’t unconditionally invoke the libsoup subproject for tests
-
-gst-plugins-ugly
-
--   No changes
-
-GStreamer Rust plugins
-
--   cargo: Default to thin lto for the release profile (for faster builds with lower memory requirements)
-
-gst-libav
-
--   avcodecmap: Use avcodec_get_supported_config() instead of struct fields
--   libav: viddec: provide details if meta has the wrong resolution
--   avviddec: Unlock video decoder stream lock temporarily while finishing frames
-
-gst-rtsp-server
-
--   No changes
-
-gstreamer-vaapi
-
--   No changes
-
-gstreamer-sharp
-
--   No changes
-
-gst-omx
-
--   No changes
-
-gst-python
-
--   No changes
-
-gst-editing-services
-
--   No changes
-
-gst-devtools, gst-validate + gst-integration-testsuites
-
--   validate: Fix leaks in ssim components
-
-gst-examples
-
--   No changes
-
-Development build environment
-
--   meson: Fix failing libva wrap file build
-
-Cerbero build tool and packaging changes in 1.24.10
-
--   shell: fix TemporaryDirectory error with the with statement when ZSH
--   ci: update macos CI to 15 Sequoia
-
-Contributors to 1.24.10
-
-Albert Sjolund, Alicia Boya García, Andoni Morales Alastruey, Antonio Morales, Edward Hervey, Guillaume Desmottes, Jan Alexander
-Steffens (heftig), Jan Schmidt, Jonas Rebmann, Jordan Petridis, Mathieu Duponchelle, Matthew Waters, Nicolas Dufresne, Nirbheek
-Chauhan, Pablo Sun, Philippe Normand, Robert Rosengren, Ruben Gonzalez, Sebastian Dröge, Seungmin Kim, Stefan Riedmüller,
-Stéphane Cerveau, Taruntej Kanakamalla, Théo Maillart, Thibault Saunier, Tim-Philipp Müller, Tomáš Polomský, Wilhelm Bartel, Xi
-Ruoyao,
-
-… and many others who have contributed bug reports, translations, sent suggestions or helped testing. Thank you all!
-
-List of merge requests and issues fixed in 1.24.10
-
--   List of Merge Requests applied in 1.24.10
--   List of Issues fixed in 1.24.10
-
-1.24.11
-
-The eleventh 1.24 bug-fix release (1.24.11) was released on 06 January 2025.
-
-This release only contains bugfixes and it should be safe to update from 1.24.x.
-
-Highlighted bugfixes in 1.24.11
-
--   playback: Fix SSA/ASS subtitles with embedded fonts
--   decklink: add missing video modes and fix 8K video modes
--   matroskamux: spec compliance fixes for audio-only files
--   onnx: disable onnxruntime telemetry
--   qtdemux: Fix base offset update when doing segment seeks
--   srtpdec: Fix a use-after-free issue
--   (uri)decodebin3: Fix stream change scenarios, possible deadlock on shutdown
--   video: fix missing alpha flag in AV12 format description
--   avcodecmap: Add some more channel position mappings
--   cerbero bootstrap fixes for Windows 11
--   Various bug fixes, build fixes, memory leak fixes, and other stability and reliability improvements
-
-gstreamer
-
--   No changes
-
-gst-plugins-base
-
--   appsrc: Decrease log level for item drop
--   gl: raise WARNING instead of ERROR when no connector is connected
--   decodebin3: Free main input even if it is not part of the list of inputs
--   urisourcebin: Avoid deadlock on shutdown
--   urisourcebin: Only rewrite stream-start event once
--   urisourcebin/(uri)decodebin3: Fix stream change scenarios
--   urisourcebin: Reference counting leak
--   playbin3: leak detected with A/V playback and window closed
--   videodecoder: Gracefully handle missing data without prior input segment
--   videodecoder: set decode only flag by decode only buffer
--   video: fix AV12 format lacking the GST_VIDEO_FORMAT_FLAG_ALPHA flag.
--   Fix SSA/ASS subtitles with embedded fonts
-
-gst-plugins-good
-
--   matroskamux: Fix audio-only stream conditions and consider audio buffers as keyframes when writing out simpleblocks
--   qtdemux: fix accumulated base offset in segment seeks
--   rtppassthroughpay: ensure buffer is writable before mapping writable
--   rtpsession: Fix twcc stats structure leak
--   v4l2: object: Add P010 format
--   v4l2videodec: release decode only frame in input list
-
-gst-plugins-bad
-
--   decklink: add missing video modes, fix 8K video modes
--   onnx: disable onnxruntime telemetry
--   srtpdec: fix build when libsrtp1 is being used
--   srtpdec: Fix a use-after-free buffer issue
--   va: display: Optimize out some property indirection
--   vp9parse/av1parse: Add video codec tag to the tag list
--   webrtc: Simplify fmtp handling in codec stats
--   webrtcbin: Fix potential deadlock on bin elements cleanup
--   zxing: Replace deprecated DecodeHints with ReaderOptions
--   meson: Also disable drm on GNU/Hurd
-
-gst-plugins-ugly
-
--   No changes
-
-GStreamer Rust plugins
-
--   No changes
-
-gst-libav
-
--   avcodecmap: Add some more channel position mappings
-
-gst-rtsp-server
-
--   No changes
-
-gstreamer-vaapi
-
--   meson: Re-added required: lines accidentally removed
-
-gstreamer-sharp
-
--   No changes
-
-gst-omx
-
--   No changes
-
-gst-python
-
--   No changes
-
-gst-editing-services
-
--   ges: Fix some reference counting and error handling
--   ges-meta-container: Fix the GET_INTERFACE macro
-
-gst-devtools, gst-validate + gst-integration-testsuites
-
--   No changes
-
-gst-examples
-
--   No changes
-
-Development build environment
-
--   No changes
-
-Cerbero build tool and packaging changes in 1.24.11
-
--   Fix bootstrap on Windows 11: Install WMIC when missing
-
-Contributors to 1.24.11
-
-Armin Begovic, Benjamin Gräf, Cheung Yik Pang, Christian Meissl, Daniel Morin, Dean Zhang (张安迪), Edward Hervey, Emil
-Ljungdahl, Francisco Javier Velázquez-García, Guillaume Desmottes, Jan Alexander Steffens (heftig), L. E. Segovia, Matthew
-Waters, Max Romanov, Nicolas Dufresne, Philippe Normand, Robert Mader, Samuel Thibault, Sebastian Dröge, Stéphane Cerveau,
-Thibault Saunier, Tim-Philipp Müller,
-
-… and many others who have contributed bug reports, translations, sent suggestions or helped testing. Thank you all!
-
-List of merge requests and issues fixed in 1.24.11
-
--   List of Merge Requests applied in 1.24.11
--   List of Issues fixed in 1.24.11
-
-1.24.12
-
-The twelfth 1.24 bug-fix release (1.24.12) was released on 29 January 2025.
-
-This release only contains bugfixes and it should be safe to update from 1.24.x.
-
-Highlighted bugfixes in 1.24.12
-
--   d3d12: Fix shaders failing to compile with newer dxc versions
--   decklinkvideosink: Fix handling of caps framerate in auto mode; also a decklinkaudiosink fix
--   devicemonitor: Fix potential crash macOS when a device is unplugged
--   gst-libav: Fix crash in audio encoders like avenc_ac3 if input data has insufficient alignment
--   gst-libav: Fix build against FFmpeg 4.2 as in Ubuntu 20.04
--   gst-editing-services: Fix Python library name fetching on Windows
--   netclientclock: Don’t store failed internal clocks in the cache, so applications can re-try later
--   oggdemux: Seeking and duration handling fixes
--   osxaudiosrc: Fixes for failing init/no output on recent iOS versions
--   qtdemux: Use mvhd transform matrix and support for flipping
--   rtpvp9pay: Fix profile parsing
--   splitmuxsrc: Fix use with decodebin3 which would occasionally fail with an assertion when seeking
--   tsdemux: Fix backwards PTS wraparound detection with ignore-pcr=true
--   video-overlay-composition: Declare the video/size/orientation tags for the meta and implement scale transformations
--   vtdec: Fix seeks occasionally hanging on macOS due to a race condition when draining
--   webrtc: Fix duplicate payload types with RTX and multiple video codecs
--   win32-pluginloader: Make sure not to create any windows when inspecting plugins
--   wpe: Various fixes for re-negotiation, latency reporting, progress messages on startup
--   x264enc: Add missing data to AvcDecoderConfigurationRecord in codec_data for high profile variants
--   cerbero: Support using ccache with cmake if enabled
--   Various bug fixes, build fixes, memory leak fixes, and other stability and reliability improvements
-
-gstreamer
-
--   device: Fix racy nullptr deref on macOS when a device is unplugged
--   iterator: Added error handling to filtered iterators
--   netclientclock: Don’t ever store failed internal clocks in the cache
--   netclock-replay: use gst_c_args when building, fixing build failure on Solaris
--   pluginloader-win32: create no window
--   pluginloader-win32: fix use after free in find_helper_bin_location
--   sparsefile: ensure error is set when read_buffer() returns 0
--   basetransform: fix incorrect logging inside gst_base_transform_query_caps
-
-gst-plugins-base
-
--   oggdemux: fixes seeking in some cases by not overwriting a valid duration with CLOCK_TIME_NONE
--   video-overlay-composition: Declare the video/size/orientation tags for the meta & implement scale transformation
--   Various fixes found from adding extra warning flags
-
-gst-plugins-good
-
--   osxaudiosrc: Fixes for failing init/no output on recent iOS versions
--   qtdemux: Use mvhd transform matrix and support for flipping
--   qtmux: fix critical warnings on negotiation error
--   rtpvp9pay: fix profile parsing
--   splitmuxsrc: Ensure only a single stream-start event is pushed
--   splitmuxsrc: decodebin3 Fails with assertion in mq_slot_handle_stream_start when seeking
--   Various fixes found from adding extra warning flags
-
-gst-plugins-bad
-
--   decklinkvideosink: Fix handling of caps framerate in auto mode
--   decklinkaudiosink: Don’t crash if started without corresponding video sink
--   d3d12: Fix shaders failing to compile with newer dxc versions
--   tsdemux: Fix backwards PTS wraparound detection with ignore-pcr=true
--   vtdec: fix seeks hangs due to a race condition draining
--   vtdec: seeks freeze the pipeline
--   wayland: Print table split when DMABuf format changes
--   webrtc: fix duplicate payload types with RTX and multiple video codecs
--   wpevideosrc: Clear cached SHM buffers after caps re-negotiation
--   wpe: Report latency and start-up progress messages
--   wpe: remove glFlush() when filling buffer
--   Fix build with gtk3 but not wayland
--   Various fixes found from adding extra warning flags
-
-gst-plugins-ugly
-
--   x264enc: add missing data to AvcDecoderConfigurationRecord, and switch to GstByteWriter
-
-GStreamer Rust plugins
-
--   No changes
-
-gst-libav
-
--   avaudenc: fix crash in avenc_ac3 if input buffers are insufficiently aligned
--   avcodecmap: Only use new channel positions when compiling against new enough ffmpeg
--   gst-libav: 1.24.11: Fails to build with minimum supported ffmpeg version
-
-gst-rtsp-server
-
--   No changes
-
-gstreamer-vaapi
-
--   No changes
-
-gstreamer-sharp
-
--   No changes
-
-gst-omx
-
--   No changes
-
-gst-python
-
--   No changes
-
-gst-editing-services
-
--   ges: Fix Python library name fetching on Windows
-
-gst-devtools, gst-validate + gst-integration-testsuites
-
--   No changes
-
-gst-examples
-
--   No changes
-
-Development build environment
-
--   No changes
-
-Cerbero build tool and packaging changes in 1.24.12
-
--   cmake: Support using ccache if enabled
-
-Contributors to 1.24.12
+## Known Issues
 
-Adrian Perez de Castro, Alan Coopersmith, Alexander Slobodeniuk, Andoni Morales Alastruey, Andrew Yooeun Chun, Brad Hards,
-Carlos Bentzen, Colin Kinloch, Edward Hervey, François Laignel, Guillaume Desmottes, Jochen Henneberg, Jordan Yelloz, L. E.
-Segovia, Monty C, Nirbheek Chauhan, Philippe Normand, Piotr Brzeziński, Rares Branici, Samuel Thibault, Sebastian Dröge, Silvio
-Lazzeretti, Tim-Philipp Müller, Tomas Granath, Will Miller,
+-   GstBuffer now uses C11 atomics for 64 bit atomic operations if available, which may require linking to libatomic on some
+    systems, but this is not done automatically yet, see issue #4177.
+
+Contributors
+
+Aaron Boxer, Adrian Perez de Castro, Adrien De Coninck, Alan Coopersmith, Albert Sjolund, Alexander Slobodeniuk, Alex Ashley,
+Alicia Boya García, Andoni Morales Alastruey, Andreas Wittmann, Andrew Yooeun Chun, Angelo Verlain, Aniket Hande, Antonio
+Larrosa, Antonio Morales, Armin Begovic, Arnaud Vrac, Artem Martus, Arun Raghavan, Benjamin Gaignard, Benjamin Gräf, Bill
+Nottingham, Brad Hards, Brad Reitmeyer, Branko Subasic, Carlo Caione, Carlos Bentzen, Carlos Falgueras García, cdelguercio, Chao
+Guo, Cheah, Cheung Yik Pang, chitao1234, Chris Bainbridge, Chris Spencer, Chris Spoelstra, Christian Meissl, Christopher Degawa,
+Chun-wei Fan, Colin Kinloch, Corentin Damman, Daniel Morin, Daniel Pendse, Daniel Stone, Dan Yeaw, Dave Lucia, David Rosca, Dean
+Zhang (张安迪), Denis Yuji Shimizu, Detlev Casanova, Devon Sookhoo, Diego Nieto, Dongyun Seo, dukesook, Edward Hervey, eipachte,
+Eli Mallon, Elizabeth Figura, Elliot Chen, Emil Ljungdahl, Emil Pettersson, eri, F. Duncanh, Fotis Xenakis, Francisco Javier
+Velázquez-García, Francis Quiers, François Laignel, George Hazan, Glyn Davies, Guillaume Desmottes, Guillermo E. Martinez,
+Haihua Hu, Håvard Graff, He Junyan, Hosang Lee, Hou Qi, Hugues Fruchet, Hyunwoo, iodar, jadarve, Jakub Adam, Jakub Vaněk, James
+Cowgill, James Oliver, Jan Alexander Steffens (heftig), Jan Schmidt, Jeffery Wilson, Jendrik Weise, Jerome Colle, Jesper Jensen,
+Jimmy Ohn, Jochen Henneberg, Johan Sternerup, Jonas K Danielsson, Jonas Rebmann, Jordan Petridis, Jordan PetridÑ–s, Jordan
+Yelloz, Jorge Zapata, Joshua Breeden, Julian Bouzas, Jurijs Satcs, Kévin Commaille, Kevin Wang, Khem Raj, kingosticks, Leonardo
+Salvatore, L. E. Segovia, Liam, Lim, Loïc Le Page, Loïc Yhuel, Lyra McMillan, Maksym Khomenko, Marc-André Lureau, Marek Olejnik,
+Marek Vasut, Marianna Smidth Buschle, Marijn Suijten, Mark-André Schadow, Mark Nauwelaerts, Markus Ebner, Martin Nordholts, Mart
+Raudsepp, Mathieu Duponchelle, Matthew Waters, Maxim P. DEMENTYEV, Max Romanov, Mengkejiergeli Ba, Michael Grzeschik, Michael
+Olbrich, Michael Scherle, Michael Tretter, Michiel Westerbeek, Mikhail Rudenko, Nacho Garcia, Nick Steel, Nicolas Dufresne,
+Niklas Jang, Nirbheek Chauhan, Ognyan Tonchev, Olivier Crête, Oskar Fiedot, Pablo García, Pablo Sun, Patricia Muscalu, Paweł
+Kotiuk, Peter Kjellerstedt, Peter Stensson, pgarciasancho, Philippe Normand, Philipp Zabel, Piotr Brzeziński, Qian Hu (胡骞),
+Rafael Caricio, Randy Li (ayaka), Rares Branici, Ray Tiley, Robert Ayrapetyan, Robert Guziolowski, Robert Mader, Roberto Viola,
+Robert Rosengren, RSWilli,Ruben González, Ruijing Dong, Sachin Gadag, Sam James, Samuel Thibault, Sanchayan Maity, Scott Moreau,
+Sebastian Dröge, Sebastian Gross, Sebastien Cote, Sergey Krivohatskiy, Sergey Radionov, Seungha Yang, Seungmin Kim, Shengqi Yu,
+Sid Sethupathi, Silvio Lazzeretti, Simonas Kazlauskas, Stefan Riedmüller, Stéphane Cerveau, Tamas Levai, Taruntej Kanakamalla,
+Théo Maillart, Thibault Saunier, Thomas Goodwin, Thomas Klausner, Tihran Katolikian, Tim Blechmann, Tim-Philipp Müller, Tjitte
+de Wert, Tomas Granath, Tomáš Polomský, tomaszmi, Tom Schuring, U. Artie Eoff, valadaptive, Víctor Manuel Jáquez Leal, Vivia
+Nikolaidou, W. Bartel, Weijian Pan, William Wedler, Will Miller, Wim Taymans, Wojciech Kapsa, Xavier Claessens, Xi Ruoyao,
+Xizhen, Yaakov Selkowitz, Yacine Bandou, Zach van Rijn, Zeno Endemann, Zhao, Zhong Hongcheng,
 
 … and many others who have contributed bug reports, translations, sent suggestions or helped testing. Thank you all!
 
-List of merge requests and issues fixed in 1.24.12
+Stable 1.26 branch
 
--   List of Merge Requests applied in 1.24.12
--   List of Issues fixed in 1.24.12
+After the 1.26.0 release there will be several 1.26.x bug-fix releases which will contain bug fixes which have been deemed
+suitable for a stable branch, but no new features or intrusive changes will be added to a bug-fix release usually. The 1.26.x
+bug-fix releases will be made from the git 1.26 branch, which is a stable release series branch.
 
-Schedule for 1.26
+Schedule for 1.28
 
-Our next major feature release will be 1.26, and 1.25 will be the unstable development version leading up to the stable 1.26
-release. The development of 1.25/1.25 will happen in the git main branch of the GStreamer mono repository.
+Our next major feature release will be 1.28, and 1.27 will be the unstable development version leading up to the stable 1.28
+release. The development of 1.27/1.28 will happen in the git main branch of the GStreamer mono repository.
 
-The schedule for 1.26 is yet to be decided.
+The schedule for 1.28 is yet to be decided.
 
-1.26 will be backwards-compatible to the stable 1.24, 1.22, 1.20, 1.18, 1.16, 1.14, 1.12, 1.10, 1.8, 1.6, 1.4, 1.2 and 1.0
+1.28 will be backwards-compatible to the stable 1.26, 1.24, 1.22, 1.20, 1.18, 1.16, 1.14, 1.12, 1.10, 1.8, 1.6, 1.4, 1.2 and 1.0
 release series.
 
 --------------------------------------------------------------------------------------------------------------------------------
 
-These release notes have been prepared by Tim-Philipp Müller with contributions from Edward Hervey, Matthew Waters, Nicolas
-Dufresne, Nirbheek Chauhan, Olivier Crête, Sebastian Dröge, Seungha Yang, Thibault Saunier, and Víctor Manuel Jáquez Leal.
+These release notes have been prepared by Tim-Philipp Müller with contributions from Arun Raghavan, Daniel Morin, Nirbheek
+Chauhan, Olivier Crête, Philippe Normand, Sebastian Dröge, Seungha Yang, Thibault Saunier, and Víctor Manuel Jáquez Leal.
 
 License: CC BY-SA 4.0
diff --git a/README.md b/README.md
index eb6c080..4e6bf1a 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-GStreamer 1.24.x stable series
+GStreamer 1.26.x stable series
 
 WHAT IT IS
 ----------
diff --git a/RELEASE b/RELEASE
index f08efd3..d111e4e 100644
--- a/RELEASE
+++ b/RELEASE
@@ -1,4 +1,4 @@
-This is GStreamer core 1.24.12.
+This is GStreamer core 1.26.0.
 
 The GStreamer team is thrilled to announce a new major feature release
 of your favourite cross-platform multimedia framework!
@@ -6,12 +6,12 @@ of your favourite cross-platform multimedia framework!
 As always, this release is again packed with new features, bug fixes and
 other improvements.
  
-The 1.24 release series adds new features on top of the 1.22 series and is
+The 1.26 release series adds new features on top of the 1.24 series and is
 part of the API and ABI-stable 1.x release series.
 
 Full release notes can be found at:
 
-  https://gstreamer.freedesktop.org/releases/1.24/
+  https://gstreamer.freedesktop.org/releases/1.26/
 
 Binaries for Android, iOS, Mac OS X and Windows will usually be provided
 shortly after the release.
diff --git a/cmake/FindGStreamer.cmake b/cmake/FindGStreamer.cmake
new file mode 100644
index 0000000..8d858be
--- /dev/null
+++ b/cmake/FindGStreamer.cmake
@@ -0,0 +1,456 @@
+# SPDX-FileCopyrightText: 2024 L. E. Segovia <amy@centricular.com>
+# SPDX-License-Ref: LGPL-2.1-or-later
+
+#[=======================================================================[.rst:
+FindGStreamer
+-------
+
+Finds the GStreamer library. Requires ``pkg-config`` to be installed.
+
+Configuration
+^^^^^^^^^^^^^
+
+This module can be configured with the following variables:
+
+``GStreamer_STATIC``
+  Link against GStreamer statically (see below).
+
+Imported Targets
+^^^^^^^^^^^^^^^^
+
+This module defines the following :prop_tgt:`IMPORTED` targets:
+
+``GStreamer::GStreamer``
+  The GStreamer library.
+
+Result Variables
+^^^^^^^^^^^^^^^^
+
+This will define the following variables:
+
+``GStreamer_FOUND``
+  True if the system has the GStreamer library.
+``GStreamer_VERSION``
+  The version of the GStreamer library which was found.
+``GStreamer_INCLUDE_DIRS``
+  Include directories needed to use GStreamer.
+``GStreamer_LIBRARIES``
+  Libraries needed to link to GStreamer.
+
+Cache Variables
+^^^^^^^^^^^^^^^
+
+The following cache variables may also be set:
+
+``GStreamer_INCLUDE_DIR``
+  The directory containing ``gst/gstversion.h``.
+``GStreamer_LIBRARY``
+  The path to the GStreamer library.
+
+Configuration Variables
+^^^^^^^^^^^^^^^
+
+Setting the following variables is required, depending on the operating system:
+
+``GStreamer_ROOT_DIR``
+  Installation prefix of the GStreamer SDK.
+
+``GStreamer_USE_STATIC_LIBS`
+  Set to ON to force the use of the static libraries. Default is OFF.
+
+``GStreamer_EXTRA_DEPS``
+  pkg-config names of the extra dependencies that will be included whenever linking against GStreamer.
+
+#]=======================================================================]
+
+if (GStreamer_FOUND)
+    return()
+endif()
+
+#####################
+#  Setup variables  #
+#####################
+
+if (NOT DEFINED GStreamer_ROOT_DIR AND DEFINED GSTREAMER_ROOT)
+    set(GStreamer_ROOT_DIR ${GSTREAMER_ROOT})
+endif()
+
+if (NOT GStreamer_ROOT_DIR)
+    set(GStreamer_ROOT_DIR "${CMAKE_CURRENT_LIST_DIR}/../../")
+endif()
+
+if (NOT EXISTS "${GStreamer_ROOT_DIR}")
+    message(FATAL_ERROR "The directory GStreamer_ROOT_DIR=${GStreamer_ROOT_DIR} does not exist")
+endif()
+
+if (NOT DEFINED GStreamer_USE_STATIC_LIBS)
+set(GStreamer_USE_STATIC_LIBS OFF)
+endif()
+
+# Set the environment for pkg-config
+if (WIN32)
+    set(ENV{PKG_CONFIG_PATH} "${GStreamer_ROOT_DIR}/lib/pkgconfig;${GStreamer_ROOT_DIR}/lib/gstreamer-1.0/pkgconfig;${GStreamer_ROOT_DIR}/lib/gio/modules/pkgconfig")
+else()
+    set(ENV{PKG_CONFIG_PATH} "${GStreamer_ROOT_DIR}/lib/pkgconfig:${GStreamer_ROOT_DIR}/lib/gstreamer-1.0/pkgconfig:${GStreamer_ROOT_DIR}/lib/gio/modules/pkgconfig")
+endif()
+
+# Set the list of extra dependencies
+if (NOT DEFINED GStreamer_EXTRA_DEPS)
+    set(GStreamer_EXTRA_DEPS)
+    if (DEFINED GSTREAMER_EXTRA_DEPS)
+        set(GStreamer_EXTRA_DEPS ${GSTREAMER_EXTRA_DEPS})
+    endif()
+endif()
+
+# Find libraries. This is meant to be used with static libraries
+# (hence the reprioritization) but I've added a fallback to shared libraries
+# and stub modules in case any are non-existent.
+function(_gst_find_library LOCAL_LIB GST_LOCAL_LIB)
+    if (DEFINED ${GST_LOCAL_LIB})
+        return()
+    endif()
+
+    set(_gst_suffixes ${CMAKE_FIND_LIBRARY_SUFFIXES})
+    set(_gst_prefixes ${CMAKE_FIND_LIBRARY_PREFIXES})
+    if (APPLE)
+        set(CMAKE_FIND_LIBRARY_SUFFIXES ".a" ".dylib" ".so" ".tbd")
+        set(CMAKE_FIND_LIBRARY_PREFIXES "" "lib")
+    elseif (UNIX)
+        set(CMAKE_FIND_LIBRARY_SUFFIXES ".a" ".so")
+        set(CMAKE_FIND_LIBRARY_PREFIXES "" "lib")
+    else()
+        set(CMAKE_FIND_LIBRARY_SUFFIXES ".a" ".lib")
+        set(CMAKE_FIND_LIBRARY_PREFIXES "" "lib")
+    endif()
+
+    if ("${LOCAL_LIB}" IN_LIST _gst_IGNORED_SYSTEM_LIBRARIES)
+        set(${GST_LOCAL_LIB} ${LOCAL_LIB} PARENT_SCOPE)
+    else()
+        find_library(${GST_LOCAL_LIB}
+            ${LOCAL_LIB}
+            HINTS ${ARGN}
+            NO_DEFAULT_PATH
+            NO_CMAKE_FIND_ROOT_PATH
+            REQUIRED
+        )
+        set(${GST_LOCAL_LIB} "${${GST_LOCAL_LIB}}" PARENT_SCOPE)
+        if (NOT ${GST_LOCAL_LIB})
+            message(FATAL_ERROR "${LOCAL_LIB} was unexpectedly not found.")
+        endif()
+    endif()
+
+    set(CMAKE_FIND_LIBRARY_SUFFIXES ${_gst_suffixes})
+    set(CMAKE_FIND_LIBRARY_PREFIXES ${_gst_prefixes})
+endfunction()
+
+macro(_gst_apply_link_libraries HIDE PC_LIBRARIES PC_HINTS GST_TARGET)
+    if (APPLE AND ${HIDE})
+        target_link_directories(${GST_TARGET} INTERFACE
+            ${${PC_HINTS}}
+        )
+    endif()
+    foreach(LOCAL_LIB IN LISTS ${PC_LIBRARIES})
+        if (LOCAL_LIB MATCHES "${_gst_SRT_REGEX_PATCH}")
+            string(REGEX REPLACE "${_gst_SRT_REGEX_PATCH}" "\\1" LOCAL_LIB "${LOCAL_LIB}")
+        endif()
+        string(MAKE_C_IDENTIFIER "_gst_${LOCAL_LIB}" GST_LOCAL_LIB)
+        if (NOT ${GST_LOCAL_LIB})
+            _gst_find_library(${LOCAL_LIB} ${GST_LOCAL_LIB} ${${PC_HINTS}})
+        endif()
+        if ("${${GST_LOCAL_LIB}}" IN_LIST _gst_IGNORED_SYSTEM_LIBRARIES)
+            target_link_libraries(${GST_TARGET} INTERFACE
+                ${${GST_LOCAL_LIB}})
+        elseif (APPLE AND ${HIDE})
+            set(LOCAL_FILE)
+            get_filename_component(LOCAL_FILE ${${GST_LOCAL_LIB}} NAME)
+            target_link_libraries(${GST_TARGET} INTERFACE
+                "-hidden-l${LOCAL_FILE}")
+        elseif((UNIX OR ANDROID) AND ${HIDE})
+            target_link_libraries(${GST_TARGET} INTERFACE
+                -Wl,--exclude-libs,${${GST_LOCAL_LIB}})
+        else()
+            target_link_libraries(${GST_TARGET} INTERFACE
+                ${${GST_LOCAL_LIB}})
+        endif()
+    endforeach()
+endmacro()
+
+macro(_gst_filter_missing_directories GST_INCLUDE_DIRS)
+    set(_gst_include_dirs)
+    foreach(DIR IN LISTS ${GST_INCLUDE_DIRS})
+        string(MAKE_C_IDENTIFIER "${DIR}" _gst_dir_id)
+        if (DEFINED _gst_exists_${_gst_dir_id})
+            if (_gst_exists_${_gst_dir_id})
+                list(APPEND _gst_include_dirs "${DIR}")
+            endif()
+        elseif (EXISTS "${DIR}")
+            list(APPEND _gst_include_dirs "${DIR}")
+            set(_gst_exists_${_gst_dir_id} TRUE)
+        else()
+            message(WARNING "Skipping missing include folder ${DIR}.")
+            set(_gst_exists_${_gst_dir_id} FALSE)
+        endif()
+    endforeach()
+    set(${GST_INCLUDE_DIRS} "${_gst_include_dirs}")
+endmacro()
+
+macro(_gst_apply_frameworks PC_STATIC_LDFLAGS_OTHER GST_TARGET)
+    if (APPLE)
+        # LDFLAGS_OTHER may include framework linkage. Because CMake
+        # iterates over arguments separated by spaces, it doesn't realise
+        # that those arguments must not be split.
+        set(new_ldflags)
+        set(assemble_framework FALSE)
+        foreach(_arg IN LISTS ${PC_STATIC_LDFLAGS_OTHER})
+            if (assemble_framework)
+                set(assemble_framework FALSE)
+                find_library(GST_${_arg}_LIB ${_arg} REQUIRED)
+                target_link_libraries(${GST_TARGET}
+                    INTERFACE
+                        "${GST_${_arg}_LIB}"
+                )
+            elseif (_arg STREQUAL "-framework")
+                set(assemble_framework TRUE)
+            else()
+                set(assemble_framework FALSE)
+                list(APPEND new_ldflags "${_arg}")
+            endif()
+        endforeach()
+        set_target_properties(${GST_TARGET} PROPERTIES
+            INTERFACE_LINK_OPTIONS "${new_ldflags}"
+        )
+    else()
+        set_target_properties(${TARGET} PROPERTIES
+            INTERFACE_LINK_OPTIONS "${${PC_STATIC_LDFLAGS_OTHER}}"
+        )
+    endif()
+endmacro()
+
+################################
+#      Set up the targets      #
+################################
+
+find_package(PkgConfig REQUIRED)
+
+# GStreamer's pkg-config modules are a MUST -- but we'll test them below
+pkg_check_modules(PC_GStreamer gstreamer-1.0 ${GStreamer_EXTRA_DEPS})
+# Simulate the list that'll be wholearchive'd.
+# Unfortunately, this uses an option only available with pkgconf.
+# set(_old_pkg_config_executable "${PKG_CONFIG_EXECUTABLE}")
+# set(PKG_CONFIG_EXECUTABLE ${PKG_CONFIG_EXECUTABLE} --maximum-traverse-depth=1)
+# pkg_check_modules(PC_GStreamer_NoDeps QUIET REQUIRED gstreamer-1.0 ${GStreamer_EXTRA_DEPS})
+# set(PKG_CONFIG_EXECUTABLE "${_old_pkg_config_executable}")
+
+set(GStreamer_VERSION "${PC_GStreamer_VERSION}")
+
+# Test validity of the paths
+# NOTE: only paths that must be considered are those provided by pkg-config
+# NOTE 2: also exclude sysroots
+find_path(GStreamer_INCLUDE_DIR
+    NAMES gst/gstversion.h
+    PATHS ${PC_GStreamer_INCLUDE_DIRS}
+    PATH_SUFFIXES gstreamer-1.0
+    NO_DEFAULT_PATH
+    NO_CMAKE_FIND_ROOT_PATH
+    REQUIRED
+)
+
+find_library(GStreamer_LIBRARY
+    NAMES gstreamer-1.0
+    PATHS ${PC_GStreamer_LIBRARY_DIRS}
+    NO_DEFAULT_PATH
+    NO_CMAKE_FIND_ROOT_PATH
+    REQUIRED
+)
+
+# Android: Ignore these libraries when constructing the IMPORTED_LOCATION
+set(_gst_IGNORED_SYSTEM_LIBRARIES c c++ unwind m dl atomic)
+if (ANDROID)
+    list(APPEND _gst_IGNORED_SYSTEM_LIBRARIES log GLESv2 EGL OpenSLES android vulkan)
+elseif(APPLE)
+    list(APPEND _gst_IGNORED_SYSTEM_LIBRARIES iconv resolv System)
+endif()
+
+# Normalize library flags coming from srt/haisrt
+# https://github.com/Haivision/srt/commit/b90b64d26f850fb0efcc4cdd8b31cbf74bd4db0c
+set(_gst_SRT_REGEX_PATCH "^:lib(.+)\\.(a|so|lib|dylib)$")
+
+if(PC_GStreamer_FOUND AND (NOT TARGET GStreamer::GStreamer))
+    # This is not UNKNOWN but INTERFACE, as we only intend to
+    # make a target suitable for downstream consumption.
+    # FindPkgConfig already takes care of things, however it is totally unable
+    # to discern between shared and static libraries when populating
+    # xxx_STATIC_LINK_LIBRARIES, so we need to populate them manually.
+    add_library(GStreamer::GStreamer INTERFACE IMPORTED)
+
+    if (GStreamer_USE_STATIC_LIBS)
+        _gst_filter_missing_directories(PC_GStreamer_STATIC_INCLUDE_DIRS)
+        set_target_properties(GStreamer::GStreamer PROPERTIES
+            INTERFACE_COMPILE_OPTIONS "${PC_GStreamer_STATIC_CFLAGS_OTHER}"
+        )
+        if (PC_GStreamer_STATIC_INCLUDE_DIRS)
+            set_target_properties(GStreamer::GStreamer PROPERTIES
+                INTERFACE_INCLUDE_DIRECTORIES "${PC_GStreamer_STATIC_INCLUDE_DIRS}"
+            )
+        endif()
+        _gst_apply_frameworks(PC_GStreamer_STATIC_LDFLAGS_OTHER GStreamer::GStreamer)
+    else()
+        set_target_properties(GStreamer::GStreamer PROPERTIES
+            INTERFACE_COMPILE_OPTIONS "${PC_GStreamer_CFLAGS_OTHER}"
+            INTERFACE_INCLUDE_DIRECTORIES "${PC_GStreamer_INCLUDE_DIRS}"
+            INTERFACE_LINK_OPTIONS "${PC_GStreamer_LDFLAGS_OTHER}"
+        )
+    endif()
+
+    add_library(GStreamer::deps INTERFACE IMPORTED)
+
+    if (NOT GStreamer_USE_STATIC_LIBS)
+        set_target_properties(GStreamer::deps PROPERTIES
+            INTERFACE_LINK_LIBRARIES "${PC_GStreamer_LINK_LIBRARIES}"
+        )
+        # We're done
+    else()
+        # Handle all libraries, even those specified with -l:libfoo.a (srt)
+        # Due to the unavailability of pkgconf's `--maximum-traverse-depth`
+        # on stock pkg-config, I attempt to simulate it through the shared
+        # libraries listing.
+        # If pkgconf is available, replace all PC_GStreamer_ entries with
+        # PC_GStreamer_NoDeps and uncomment the code block above.
+        foreach(LOCAL_LIB IN LISTS PC_GStreamer_LIBRARIES)
+            # list(TRANSFORM REPLACE) is of no use here
+            # https://gitlab.kitware.com/cmake/cmake/-/issues/16899
+            if (LOCAL_LIB MATCHES "${_gst_SRT_REGEX_PATCH}")
+                string(REGEX REPLACE "${_gst_SRT_REGEX_PATCH}" "\\1" LOCAL_LIB "${LOCAL_LIB}")
+            endif()
+            string(MAKE_C_IDENTIFIER "_gst_${LOCAL_LIB}" GST_LOCAL_LIB)
+            if (NOT ${GST_LOCAL_LIB})
+                _gst_find_library(${LOCAL_LIB} ${GST_LOCAL_LIB} ${PC_GStreamer_STATIC_LIBRARY_DIRS})
+            endif()
+            target_link_libraries(GStreamer::GStreamer INTERFACE
+                "${${GST_LOCAL_LIB}}"
+            )
+        endforeach()
+
+        _gst_apply_link_libraries(ON PC_GStreamer_STATIC_LIBRARIES PC_GStreamer_STATIC_LIBRARY_DIRS GStreamer::deps)
+    endif()
+
+    target_link_libraries(GStreamer::GStreamer
+        INTERFACE
+            GStreamer::deps
+    )
+endif()
+
+foreach(_gst_PLUGIN IN LISTS GSTREAMER_PLUGINS)
+    # Safety valve for the custom targets above
+    if ("${_gst_plugin}" IN_LIST _gst_CUSTOM_TARGETS)
+        continue()
+    endif()
+
+    if (TARGET GStreamer::${_gst_PLUGIN})
+        continue()
+    endif()
+
+    if (GStreamer_FIND_REQUIRED_${_gst_PLUGIN})
+        set(_gst_PLUGIN_REQUIRED REQUIRED)
+    else()
+        set(_gst_PLUGIN_REQUIRED)
+    endif()
+
+    pkg_check_modules(PC_GStreamer_${_gst_PLUGIN} "gst${_gst_PLUGIN}")
+
+    set(GStreamer_${_gst_PLUGIN}_FOUND "${PC_GStreamer_${_gst_PLUGIN}_FOUND}")
+    if (NOT GStreamer_${_gst_PLUGIN}_FOUND)
+        continue()
+    endif()
+
+    add_library(GStreamer::${_gst_PLUGIN} INTERFACE IMPORTED)
+    _gst_filter_missing_directories(PC_GStreamer_${_gst_PLUGIN}_INCLUDE_DIRS)
+    set_target_properties(GStreamer::${_gst_PLUGIN} PROPERTIES
+        INTERFACE_COMPILE_OPTIONS "${PC_GStreamer_${_gst_PLUGIN}_CFLAGS_OTHER}"
+    )
+    if (PC_GStreamer_${_gst_PLUGIN}_INCLUDE_DIRS)
+        set_target_properties(GStreamer::${_gst_PLUGIN} PROPERTIES
+            INTERFACE_INCLUDE_DIRECTORIES "${PC_GStreamer_${_gst_PLUGIN}_INCLUDE_DIRS}"
+        )
+    endif()
+    if (GStreamer_USE_STATIC_LIBS)
+        _gst_apply_frameworks(PC_GStreamer_${_gst_PLUGIN}_STATIC_LDFLAGS_OTHER GStreamer::${_gst_PLUGIN})
+    else()
+        set_target_properties(GStreamer::${_gst_PLUGIN} PROPERTIES
+            INTERFACE_LINK_OPTIONS "${PC_GStreamer_${_gst_PLUGIN}_LDFLAGS_OTHER}"
+            INTERFACE_LINK_LIBRARIES "${PC_GStreamer_${_gst_PLUGIN}_LINK_LIBRARIES}"
+        )
+        # We're done
+        continue()
+    endif()
+
+    # Handle all libraries, even those specified with -l:libfoo.a (srt)
+    _gst_apply_link_libraries(OFF PC_GStreamer_${_gst_PLUGIN}_STATIC_LIBRARIES PC_GStreamer_${_gst_PLUGIN}_STATIC_LIBRARY_DIRS GStreamer::${_gst_PLUGIN})
+endforeach()
+
+foreach(_gst_PLUGIN IN LISTS GSTREAMER_APIS)
+    # Safety valve for the custom targets above
+    if ("${_gst_plugin}" IN_LIST _gst_CUSTOM_TARGETS)
+        continue()
+    endif()
+
+    if (TARGET GStreamer::${_gst_PLUGIN})
+        continue()
+    endif()
+
+    if (GStreamer_FIND_REQUIRED_${_gst_PLUGIN})
+        set(_gst_PLUGIN_REQUIRED REQUIRED)
+    else()
+        set(_gst_PLUGIN_REQUIRED)
+    endif()
+
+    string(REGEX REPLACE "^api_(.+)" "\\1" _gst_PLUGIN_PC "${_gst_PLUGIN}")
+    string(REPLACE "_" "-" _gst_PLUGIN_PC "${_gst_PLUGIN_PC}")
+
+    pkg_check_modules(PC_GStreamer_${_gst_PLUGIN} "gstreamer-${_gst_PLUGIN_PC}-1.0")
+
+    set(GStreamer_${_gst_PLUGIN}_FOUND "${PC_GStreamer_${_gst_PLUGIN}_FOUND}")
+    if (NOT GStreamer_${_gst_PLUGIN}_FOUND)
+        continue()
+    endif()
+
+    add_library(GStreamer::${_gst_PLUGIN} INTERFACE IMPORTED)
+    _gst_filter_missing_directories(PC_GStreamer_${_gst_PLUGIN}_INCLUDE_DIRS)
+    set_target_properties(GStreamer::${_gst_PLUGIN} PROPERTIES
+        INTERFACE_COMPILE_OPTIONS "${PC_GStreamer_${_gst_PLUGIN}_CFLAGS_OTHER}"
+        INTERFACE_LINK_OPTIONS "${PC_GStreamer_${_gst_PLUGIN}_LDFLAGS_OTHER}"
+    )
+    if (PC_GStreamer_${_gst_PLUGIN}_INCLUDE_DIRS)
+        set_target_properties(GStreamer::${_gst_PLUGIN} PROPERTIES
+            INTERFACE_INCLUDE_DIRECTORIES "${PC_GStreamer_${_gst_PLUGIN}_INCLUDE_DIRS}"
+        )
+    endif()
+    if (GStreamer_USE_STATIC_LIBS)
+        _gst_apply_frameworks(PC_GStreamer_${_gst_PLUGIN}_STATIC_LDFLAGS_OTHER GStreamer::${_gst_PLUGIN})
+    else()
+        set_target_properties(GStreamer::${_gst_PLUGIN} PROPERTIES
+            INTERFACE_LINK_OPTIONS "${PC_GStreamer_${_gst_PLUGIN}_LDFLAGS_OTHER}"
+            INTERFACE_LINK_LIBRARIES "${PC_GStreamer_${_gst_PLUGIN}_LINK_LIBRARIES}"
+        )
+        # We're done
+        continue()
+    endif()
+
+    # Handle all libraries, even those specified with -l:libfoo.a (srt)
+    _gst_apply_link_libraries(OFF PC_GStreamer_${_gst_PLUGIN}_STATIC_LIBRARIES PC_GStreamer_${_gst_PLUGIN}_STATIC_LIBRARY_DIRS GStreamer::${_gst_PLUGIN})
+endforeach()
+
+# Perform final validation
+include(FindPackageHandleStandardArgs)
+set(_gst_handle_version_range)
+if (CMAKE_VERSION VERSION_GREATER_EQUAL "3.19.0")
+    set(_gst_handle_version_range "HANDLE_VERSION_RANGE")
+endif()
+find_package_handle_standard_args(GStreamer
+    REQUIRED_VARS
+        GStreamer_LIBRARY
+        GStreamer_INCLUDE_DIR
+    VERSION_VAR GStreamer_VERSION
+    ${_gst_handle_version_range}
+    HANDLE_COMPONENTS
+)
diff --git a/cmake/meson.build b/cmake/meson.build
new file mode 100644
index 0000000..7b63d5a
--- /dev/null
+++ b/cmake/meson.build
@@ -0,0 +1,9 @@
+find_module = files(
+    'FindGStreamer.cmake',
+)
+
+install_data(
+    find_module,
+    install_dir: get_option('datadir') / 'cmake'
+)
+
diff --git a/data/bash-completion/helpers/meson.build b/data/bash-completion/helpers/meson.build
index 160b2e5..5651e80 100644
--- a/data/bash-completion/helpers/meson.build
+++ b/data/bash-completion/helpers/meson.build
@@ -1,7 +1,7 @@
 bash_helper_conf = configuration_data()
 bash_helper_conf.set('GST_COMPLETION_HELPER_INSTALLED',
     join_paths(prefix, helpers_install_dir, 'gst-completion-helper'))
-bash_helper_conf.set('GST_API_VERSION', apiversion)
+bash_helper_conf.set('GST_API_VERSION', api_version)
 
 configure_file(input : 'gst.in',
     output : 'gst',
diff --git a/docs/gst-hotdoc-plugins-scanner.c b/docs/gst-hotdoc-plugins-scanner.c
index ebe8c9d..195dccd 100644
--- a/docs/gst-hotdoc-plugins-scanner.c
+++ b/docs/gst-hotdoc-plugins-scanner.c
@@ -593,12 +593,12 @@ _add_properties (GString * json, GString * other_types,
 }
 
 static gboolean
-print_field (GQuark field, const GValue * value, GString * jcaps)
+print_field (const GstIdStr * fieldname, const GValue * value, GString * jcaps)
 {
   gchar *tmp, *str = gst_value_serialize (value);
 
-  if (!g_strcmp0 (g_quark_to_string (field), "format") ||
-      !g_strcmp0 (g_quark_to_string (field), "rate")) {
+  if (!g_strcmp0 (gst_id_str_as_str (fieldname), "format") ||
+      !g_strcmp0 (gst_id_str_as_str (fieldname), "rate")) {
     if (!cleanup_caps_field)
       cleanup_caps_field = g_regex_new ("\\(string\\)|\\(rate\\)", 0, 0, NULL);
 
@@ -607,7 +607,8 @@ print_field (GQuark field, const GValue * value, GString * jcaps)
     g_free (tmp);
   }
 
-  g_string_append_printf (jcaps, "%15s: %s\n", g_quark_to_string (field), str);
+  g_string_append_printf (jcaps, "%15s: %s\n", gst_id_str_as_str (fieldname),
+      str);
   g_free (str);
   return TRUE;
 }
@@ -645,8 +646,8 @@ _build_caps (const GstCaps * caps)
       g_string_append_printf (jcaps, "%s:\n",
           gst_structure_get_name (structure));
     }
-    gst_structure_foreach (structure, (GstStructureForeachFunc) print_field,
-        jcaps);
+    gst_structure_foreach_id_str (structure,
+        (GstStructureForeachIdStrFunc) print_field, jcaps);
   }
 
   res = json_strescape (jcaps->str);
@@ -953,7 +954,14 @@ main (int argc, char *argv[])
       if (GST_IS_TRACER_FACTORY (feature)) {
         if (!f)
           g_string_append_printf (json, ",");
-        g_string_append_printf (json, "\"%s\": {}", GST_OBJECT_NAME (feature));
+
+        GstTracer *tracer =
+            g_object_new (gst_tracer_factory_get_tracer_type (GST_TRACER_FACTORY
+                (feature)), NULL);;
+        g_string_append_printf (json, "\"%s\": {", GST_OBJECT_NAME (feature));
+        _add_object_details (json, other_types, seen_other_types,
+            G_OBJECT (tracer), G_OBJECT_TYPE (tracer), G_OBJECT_TYPE (tracer));
+        g_string_append (json, "}");
         f = FALSE;
       }
     }
diff --git a/docs/gst-plugins-doc-cache-generator.py b/docs/gst-plugins-doc-cache-generator.py
index e947fb1..9be7d68 100755
--- a/docs/gst-plugins-doc-cache-generator.py
+++ b/docs/gst-plugins-doc-cache-generator.py
@@ -22,7 +22,6 @@ import os
 import sys
 import re
 import subprocess
-import tempfile
 from pathlib import Path as P
 from argparse import ArgumentParser
 
@@ -32,6 +31,204 @@ try:
 except ImportError:  # python <3.3
     from collections import Mapping
 
+# Some project names need to be amended, to avoid conflicts with plugins.
+# We also map gst to gstreamer to preserve existing links
+PROJECT_NAME_MAP = {
+    'gst': 'gstreamer',
+    'app': 'applib',
+    'rtp': 'rtplib',
+    'rtsp': 'rtsplib',
+    'webrtc': 'webrtclib',
+    'mse': 'mselib',
+    'va': 'valib',
+    'vulkan': 'vulkanlib',
+    'rtspserver': 'gst-rtsp-server',
+    'validate': 'gst-devtools',
+    'ges': 'gst-editing-services',
+    'opencv': 'opencvlib',
+}
+
+
+def get_c_flags(deps, buildroot, uninstalled=True):
+    if isinstance(deps, str):
+        deps = [deps]
+    env = os.environ.copy()
+    if uninstalled:
+        env['PKG_CONFIG_PATH'] = os.path.join(buildroot, 'meson-uninstalled')
+    for dep in deps:
+        res = subprocess.run(['pkg-config', '--cflags', dep], env=env, capture_output=True)
+        if res.returncode == 0:
+            return [res.stdout.decode().strip()]
+    print("Failed to get cflags for:", ", ".join(deps), ", ignoring")
+    return ''
+
+
+
+class GstLibsHotdocConfGen:
+    def __init__(self):
+        parser = ArgumentParser()
+        parser.add_argument('--srcdir', type=P)
+        parser.add_argument('--builddir', type=P)
+        parser.add_argument('--buildroot', type=P)
+        parser.add_argument('--source_root', type=P)
+        parser.add_argument('--gi_source_file', type=P)
+        parser.add_argument('--gi_c_source_file', type=P)
+        parser.add_argument('--gi_source_root', type=P)
+        parser.add_argument('--c_source_file', type=P)
+        parser.add_argument('--project_version')
+        parser.add_argument('--gi_c_source_filters', nargs='*', default=[])
+        parser.add_argument('--c_source_filters', nargs='*', default=[])
+        parser.add_argument('--output', type=P)
+
+        parser.parse_args(namespace=self, args=sys.argv[2:])
+
+    def generate_libs_configs(self):
+        conf_files = []
+
+        with self.gi_c_source_file.open() as fd:
+            gi_c_source_map = json.load(fd)
+
+        with self.gi_source_file.open() as fd:
+            gi_source_map = json.load(fd)
+
+        if self.c_source_file is not None:
+            with self.c_source_file.open() as fd:
+                c_source_map = json.load(fd)
+        else:
+            c_source_map = {}
+
+        for libname in gi_source_map.keys():
+            gi_c_sources = gi_c_source_map[libname].split(os.pathsep)
+            gi_sources = gi_source_map[libname].split(os.pathsep)
+
+            project_name = PROJECT_NAME_MAP.get(libname, libname)
+
+            if project_name == 'audio' and gi_sources[0].endswith('GstBadAudio-1.0.gir'):
+                project_name = 'bad-audio'
+
+            conf_path = self.builddir / f'{project_name}-doc.json'
+            conf_files.append(str(conf_path))
+
+            index_path = os.path.join(self.source_root, 'index.md')
+            if not os.path.exists(index_path):
+                index_path = os.path.join(self.source_root, libname, 'index.md')
+                sitemap_path = os.path.join(self.source_root, libname, 'sitemap.txt')
+                gi_index_path = os.path.join(self.source_root, libname, 'gi-index.md')
+            else:
+                sitemap_path = os.path.join(self.source_root, 'sitemap.txt')
+                gi_index_path = os.path.join(self.source_root, 'gi-index.md')
+
+            assert (os.path.exists(index_path))
+            assert (os.path.exists(sitemap_path))
+            if not os.path.exists(gi_index_path):
+                gi_index_path = index_path
+
+            gi_source_root = os.path.join(self.gi_source_root, libname)
+            if not os.path.exists(gi_source_root):
+                gi_source_root = os.path.join(self.gi_source_root)
+
+            conf = {
+                'sitemap': sitemap_path,
+                'index': index_path,
+                'gi_index': gi_index_path,
+                'output': f'{project_name}-doc',
+                'conf_file': str(conf_path),
+                'project_name': project_name,
+                'project_version': self.project_version,
+                'gi_smart_index': True,
+                'gi_order_generated_subpages': True,
+                'gi_c_sources': gi_c_sources,
+                'gi_c_source_roots': [
+                    os.path.abspath(gi_source_root),
+                    os.path.abspath(os.path.join(self.srcdir, '..',)),
+                    os.path.abspath(os.path.join(self.builddir, '..',)),
+                ],
+                'include_paths': [
+                    os.path.join(self.builddir),
+                    os.path.join(self.srcdir),
+                ],
+                'gi_sources': gi_sources,
+                'gi_c_source_filters': [str(s) for s in self.gi_c_source_filters],
+                'extra_assets': os.path.join(self.srcdir, 'images'),
+            }
+
+            with conf_path.open('w') as f:
+                json.dump(conf, f, indent=4)
+
+        for libname in c_source_map.keys():
+            c_sources = c_source_map[libname].split(os.pathsep)
+
+            project_name = PROJECT_NAME_MAP.get(libname, libname)
+
+            conf_path = self.builddir / f'{project_name}-doc.json'
+
+            index_path = os.path.join(self.source_root, 'index.md')
+            if not os.path.exists(index_path):
+                index_path = os.path.join(self.source_root, libname, 'index.md')
+                sitemap_path = os.path.join(self.source_root, libname, 'sitemap.txt')
+                c_index_path = os.path.join(self.source_root, libname, 'c-index.md')
+            else:
+                sitemap_path = os.path.join(self.source_root, 'sitemap.txt')
+                c_index_path = os.path.join(self.source_root, 'c-index.md')
+
+            assert (os.path.exists(index_path))
+            assert (os.path.exists(sitemap_path))
+            if not os.path.exists(c_index_path):
+                c_index_path = index_path
+
+            try:
+                if libname == 'adaptivedemux':
+                    c_flags = get_c_flags(f'gstreamer-base-{self.project_version}', self.buildroot)
+                    c_flags += [f'-I{self.srcdir}/../gst-libs']
+                elif libname == 'opencv':
+                    c_flags = get_c_flags(f'gstreamer-base-{self.project_version}', self.buildroot)
+                    c_flags += get_c_flags(f'gstreamer-video-{self.project_version}', self.buildroot)
+                    c_flags += get_c_flags(['opencv4', 'opencv'], self.buildroot, uninstalled=True)
+                    c_flags += [f'-I{self.srcdir}/../gst-libs']
+                else:
+                    c_flags = get_c_flags(f'gstreamer-{libname}-{self.project_version}', self.buildroot)
+            except Exception as e:
+                print(f'Cannot document {libname}')
+                print(e)
+                continue
+
+            c_flags += ['-DGST_USE_UNSTABLE_API']
+
+            if libname == 'opencv':
+                c_flags += ['-x c++']
+
+            conf = {
+                'sitemap': sitemap_path,
+                'index': index_path,
+                'c_index': c_index_path,
+                'output': f'{project_name}-doc',
+                'conf_file': str(conf_path),
+                'project_name': project_name,
+                'project_version': self.project_version,
+                'c_smart_index': True,
+                'c_order_generated_subpages': True,
+                'c_sources': c_sources,
+                'include_paths': [
+                    os.path.join(self.builddir),
+                    os.path.join(self.srcdir),
+                ],
+                'c_source_filters': [str(s) for s in self.c_source_filters],
+                'extra_assets': os.path.join(self.srcdir, 'images'),
+                'extra_c_flags': c_flags
+            }
+
+            with conf_path.open('w') as f:
+                json.dump(conf, f, indent=4)
+
+            conf_files.append(str(conf_path))
+
+
+        if self.output is not None:
+            with self.output.open('w') as f:
+                json.dump(conf_files, f, indent=4)
+
+        return conf_files
+
 
 class GstPluginsHotdocConfGen:
     def __init__(self):
@@ -47,17 +244,41 @@ class GstPluginsHotdocConfGen:
         parser.add_argument('--project_version')
         parser.add_argument('--include_paths', nargs='*', default=[])
         parser.add_argument('--gst_c_source_filters', nargs='*', default=[])
+        parser.add_argument('--gst_c_source_file', type=P)
+        parser.add_argument('--gst_plugin_libraries_file', type=P)
+        parser.add_argument('--extra_assets', nargs='*', default=[])
+        parser.add_argument('--output', type=P)
 
         parser.parse_args(namespace=self, args=sys.argv[2:])
 
     def generate_plugins_configs(self):
         plugin_files = []
+
+        if self.gst_c_source_file is not None:
+            with self.gst_c_source_file.open() as fd:
+                gst_c_source_map = json.load(fd)
+        else:
+            gst_c_source_map = {}
+
+        if self.gst_plugin_libraries_file is not None:
+            with self.gst_plugin_libraries_file.open() as fd:
+                gst_plugin_libraries_map = json.load(fd)
+        else:
+            gst_plugin_libraries_map = {}
+
         with self.gst_cache_file.open() as fd:
             all_plugins = json.load(fd)
 
             for plugin_name in all_plugins.keys():
                 conf = self.builddir / f'plugin-{plugin_name}.json'
                 plugin_files.append(str(conf))
+
+                # New-style, sources are explicitly provided, as opposed to using wildcards
+                if plugin_name in gst_c_source_map:
+                    gst_c_sources = gst_c_source_map[plugin_name].split(os.pathsep)
+                else:
+                    gst_c_sources = self.gst_c_sources
+
                 with conf.open('w') as f:
                     json.dump({
                         'sitemap': str(self.sitemap),
@@ -71,12 +292,18 @@ class GstPluginsHotdocConfGen:
                         'gst_plugin_name': plugin_name,
                         'c_flags': self.c_flags,
                         'gst_smart_index': True,
-                        'gst_c_sources': self.gst_c_sources,
+                        'gst_c_sources': gst_c_sources,
                         'gst_c_source_filters': [str(s) for s in self.gst_c_source_filters],
                         'include_paths': self.include_paths,
                         'gst_order_generated_subpages': True,
+                        'gst_plugin_library': gst_plugin_libraries_map.get(plugin_name),
+                        'extra_assets': self.extra_assets
                     }, f, indent=4)
 
+        if self.output is not None:
+            with self.output.open('w') as f:
+                json.dump(plugin_files, f, indent=4)
+
         return plugin_files
 
 
@@ -88,7 +315,6 @@ class GstPluginsHotdocConfGen:
 UNSTABLE_VALUE = "unstable-values"
 
 
-
 def dict_recursive_update(d, u):
     modified = False
     unstable_values = d.get(UNSTABLE_VALUE, [])
@@ -109,28 +335,32 @@ def dict_recursive_update(d, u):
 
 
 def test_unstable_values():
-    current_cache = { "v1": "yes", "unstable-values": "v1"}
-    new_cache = { "v1": "no" }
+    current_cache = {"v1": "yes", "unstable-values": "v1"}
+    new_cache = {"v1": "no"}
+
+    assert (dict_recursive_update(current_cache, new_cache) is False)
 
-    assert(dict_recursive_update(current_cache, new_cache) == False)
+    new_cache = {"v1": "no", "unstable-values": "v2"}
+    assert (dict_recursive_update(current_cache, new_cache) is True)
 
-    new_cache = { "v1": "no", "unstable-values": "v2" }
-    assert(dict_recursive_update(current_cache, new_cache) == True)
+    current_cache = {"v1": "yes", "v2": "yay", "unstable-values": "v1", }
+    new_cache = {"v1": "no"}
+    assert (dict_recursive_update(current_cache, new_cache) is False)
 
-    current_cache = { "v1": "yes", "v2": "yay", "unstable-values": "v1",}
-    new_cache = { "v1": "no" }
-    assert(dict_recursive_update(current_cache, new_cache) == False)
+    current_cache = {"v1": "yes", "v2": "yay", "unstable-values": "v2"}
+    new_cache = {"v1": "no", "v2": "unstable"}
+    assert (dict_recursive_update(current_cache, new_cache) is True)
+    assert (current_cache == {"v1": "no", "v2": "yay", "unstable-values": "v2"})
 
-    current_cache = { "v1": "yes", "v2": "yay", "unstable-values": "v2"}
-    new_cache = { "v1": "no", "v2": "unstable" }
-    assert (dict_recursive_update(current_cache, new_cache) == True)
-    assert (current_cache == { "v1": "no", "v2": "yay", "unstable-values": "v2" })
 
 if __name__ == "__main__":
     if sys.argv[1] == "hotdoc-config":
         fs = GstPluginsHotdocConfGen().generate_plugins_configs()
         print(os.pathsep.join(fs))
         sys.exit(0)
+    elif sys.argv[1] == "hotdoc-lib-config":
+        fs = GstLibsHotdocConfGen().generate_libs_configs()
+        sys.exit(0)
 
     cache_filename = sys.argv[1]
     output_filename = sys.argv[2]
diff --git a/docs/index.md b/docs/index.md
deleted file mode 100644
index 72bf530..0000000
--- a/docs/index.md
+++ /dev/null
@@ -1,338 +0,0 @@
----
-short-description:  GStreamer core API reference.
-...
-
-# GStreamer Core
-
-GStreamer is a streaming media framework. It uses graphs of elements
-which operate on data. The functionality to process media is provided by
-plug-ins which provide features like elements, typefinding, and so on.
-This allows new functionality to be added simply by installing new
-plug-ins.
-
-GStreamer is cross-platform and works on most UNIX-like platforms as
-well as Windows. It is released under the GNU Library General Public
-License (GNU LGPL).
-
-![ Relation between gstreamer core objects. ]
-
-  [ Relation between gstreamer core objects. ]: images/gst-universe.svg
-
-## Building on UNIX
-
-On UNIX, GStreamer uses the standard GNU build system, using autoconf
-for package configuration and resolving portability issues, automake for
-building makefiles that comply with the GNU Coding Standards, and
-libtool for building shared libraries on multiple platforms. The normal
-sequence for compiling and installing the GStreamer library is thus:
-`./configure` `make` `make install`
-
-The standard options provided by GNU autoconf may be passed to the
-`configure` script. Please see the autoconf documentation or run
-`./configure --help` for information about the standard options.
-
-In addition there are several options to activate or deactivate
-features. E.g. passing `--disable-gst-debug` to `configure` will turn
-the debugging subsystem into a non-functional stub and remove all macro
-based invocations from within the library (and anything compiled against
-the library afterwards.)
-
-If library size matters and one builds in a controlled environment, it
-is also possible to totally remove subsystem code. This is intentionally
-not offered as a configure option as it causes an ABI break. Code built
-against a version of GStreamer without these modifications needs to be
-recompiled.
-
-`make CFLAGS="-DGST_REMOVE_DEPRECATED -DGST_REMOVE_DISABLED"`
-
--   `GST_REMOVE_DEPRECATED` - Omit deprecated functions from the
-    library.
-
--   `GST_REMOVE_DISABLED` - Omit stubs for disabled subsystems from the
-    library.
-
-## Building GStreamer Applications
-
-Applications and libraries can use `pkg-config` to get all the needed
-compiler and linker flags to build against GStreamer. Please note that
-GStreamer is split into several libraries itself.
-`pkg-config --list-all | grep gstreamer` will list the available
-libraries.
-
-## Running and debugging GStreamer Applications
-
-### Environment variables
-
-GStreamer inspects a few of environment variables in addition to
-standard variables like LANG, PATH or HOME.
-
-**GST_PLUGIN_SYSTEM_PATH, GST_PLUGIN_SYSTEM_PATH_1_0.**
-
-This environment variable can be set to a colon-separated list of paths
-(or semicolon-separated list on Windows). If this variable is not set,
-GStreamer will fill in this list for you with
-
--   plug-ins in the user's home directory, or rather the user's "data
-    home" directory according to the xdg base dir specification. Usually
-    this will be a directory called `plugins` inside the
-    `.local/share/gstreamer-GST_API_VERSION` directory in the user's
-    home directory by default, though this search path may change if the
-    XDG_DATA_HOME environment variable is set.
-
--   plug-ins installed system-wide. On this system, they are stored in
-    `GST_PLUGINS_DIR`.
-
-GStreamer will scan these paths for GStreamer plug-ins. These plug-ins
-will be loaded after the plug-ins in the GST_PLUGIN_PATH variable
-below. The paths are scanned in the given order. This allows a user to
-override system-installed plug-ins with his own versions.
-
-The GST_PLUGIN_SYSTEM_PATH_1_0 variant is useful if both the old
-GStreamer 0.10 version and the new GStreamer 1.0 version need to be
-pointed to new plugin paths. The latter will use the _1_0 variant over
-the non-versioned one if it is set.
-
-Setting this variable to an empty string will cause GStreamer not to
-scan any system paths at all for plug-ins. This can be useful if you're
-running a development environment (for development purposes) or while running
-testsuites.
-
-**GST_PLUGIN_PATH, GST_PLUGIN_PATH_1_0.**
-
-This environment variable can be set to a colon-separated list of paths
-(or a semicolon-separated list on Windows). GStreamer will scan these
-paths for GStreamer plug-ins. These plug-ins will be loaded in addition
-to, and before, the plug-ins in the system paths.
-
-The GST_PLUGIN_PATH_1_0 variant is useful if both the old GStreamer
-0.10 version and the new GStreamer 1.0 version need to be pointed to new
-plugin paths. The latter will use the _1_0 variant over the
-non-versioned one if it is set.
-
-**GST_DEBUG.**
-
-If GStreamer has been configured with `--enable-gst-debug=yes`, this
-variable can be set to a list of debug options, which cause GStreamer to
-print out different types of debugging information to stderr.
-
-The variable takes a comma-separated list of "category_name:level"
-pairs to set specific levels for the individual categories. The level
-value ranges from 0 (nothing) to 9 (MEMDUMP).
-
-* 1 - `ERROR`: Logs all fatal errors. These are errors that do not allow the core
-    or elements to perform the requested action. The application can
-    still recover if programmed to handle the conditions that triggered
-    the error.
-* 2 - `WARNING`: Logs all warnings. Typically these are non-fatal, but user-visible
-    problems are expected to happen.
-* 3 - `FIXME`: Logs all fixme messages. Fixme messages are messages that indicate
-    that something in the executed code path is not fully implemented or
-    handled yet. The purpose of this message is to make it easier to
-    spot incomplete/unfinished pieces of code when reading the debug
-    log.
-* 4 - `INFO`: Logs all informational messages. These are typically used for events
-    in the system that only happen once, or are important and rare
-    enough to be logged at this level.
-* 5 - `DEBUG`: Logs all debug messages. These are general debug messages for events
-    that happen only a limited number of times during an object's
-    lifetime; these include setup, teardown, change of parameters, ...
-* 6 - `LOG`: Logs all log messages. These are messages for events that happen
-    repeatedly during an object's lifetime; these include streaming and
-    steady-state conditions.
-* 7 - `TRACE`: Logs all trace messages. These messages for events that happen
-    repeatedly during an object's lifetime such as the ref/unref cycles.
-* 9 - `MEMDUMP`: Log all memory dump messages. Memory dump messages are used to log
-    (small) chunks of data as memory dumps in the log. They will be
-    displayed as hexdump with ASCII characters.
-
-The category_name can contain "`*"` as a wildcard.
-
-For example, setting GST_DEBUG to `GST_AUTOPLUG:6,GST_ELEMENT_*:4`,
-will cause the `GST_AUTOPLUG` category to be logged at full `LOG` level,
-while all categories starting with `GST_ELEMENT_` will be logged at
-`INFO` level.
-
-To get all possible debug output, set GST_DEBUG to `*:9`. For debugging
-purposes a `*:6` debug log is usually the most useful, as it contains
-all important information, but hides a lot of noise such as refs/unrefs.
-For bug reporting purposes, a `*:6` log is also what will be requested
-usually. It's often also worth running with `*:3` to see if there are
-any non-fatal errors or warnings that might be related to the problem at
-hand.
-
-Since GStreamer 1.2 it is also possible to specify debug levels by name,
-e.g. GST_DEBUG=*:WARNING,*audio*:LOG
-
-**GST_DEBUG_NO_COLOR.**
-
-Set this environment variable to any value ("1" typically) to switch off
-colouring in GST_DEBUG output. This has the same effect as specifying
-the `--gst-debug-no-color` or `--gst-debug-color-mode`=off command line
-option to well-behaved GStreamer applications (ie. those that pass
-command-line options correctly to GStreamer). This is particularly
-useful to reduce the size of debug output and also allows for the output
-to be compressed much better than with colours turned on.
-
-Has the same effect as setting GST_DEBUG_COLOR_MODE environment
-variable to "off".
-
-**GST_DEBUG_COLOR_MODE.**
-
-Set this environment variable to change log colouring in GST_DEBUG
-output. Possible values:
-
-* `on`: Enables debug log output coloring. Uses default coloring method for
-  current platform. This is the default.
-* `off`: Disables debug log output coloring. This has the same effect as
-  specifying the `--gst-debug-color-mode`=off command line option to
-  well-behaved GStreamer applications (ie. those that pass
-  command-line options correctly to GStreamer). This is particularly
-  useful to reduce the size of debug output and also allows for the
-  output to be compressed much better than with colours turned on.
-
-  Has the same effect as setting GST_DEBUG_NO_COLOR environment
-  variable to any value.
-* `auto`: Same as `on`.
-* `disable`: Same as `off`.
-* `unix`: Enables debug log output coloring and forces the use of UNIX termial
-  codes for coloring, even if this method is not normally used on
-  current platform. This has the same effect as specifying the
-  `--gst-debug-color-mode`=unix command line option to well-behaved
-  GStreamer applications (ie. those that pass command-line options
-  correctly to GStreamer). This is particularly useful to dump debug
-  output into a file on non-UNIX platforms to be sent to developers
-  who have viewers that support UNIX terminal codes.
-
-**GST_DEBUG_OPTIONS.**
-
-This environment variable can be used to tweak the behaviour of the
-debugging system. Currently the only options supported are "pretty-tags"
-and "full-tags". In "pretty-tags" mode (the default), taglists in the
-debug log will be serialized so that only the first few and last few
-bytes of a buffer-type tag will be serialized into the log, to avoid
-dumping hundreds of lines of useless output into the log in case of
-large image tags and the like.
-
-**GST_DEBUG_DUMP_DOT_DIR.**
-
-Set this environment variable to a path to turn on all
-#GST_DEBUG_BIN_TO_DOT_FILE or
-#GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS calls and have the dot files
-in that location.
-
-This will only work if the application in question makes these calls in
-strategic places (like when the pipeline state changes or an error
-occurs). gst-launch-GST_API_VERSION is one such application.
-
-These .dot files can then be turned into images using the 'dot' utility
-from the graphviz set of tools, like this:
-`dot foo.dot -Tsvg -o foo.svg` or `dot foo.dot -Tpng -o foo.png` or
-`dot foo.dot -Tjpg -o foo.jpg`.
-
-There is also a utility called `xdot` which allows you to view the dot
-file directly without converting it first.
-
-**GST_REGISTRY, GST_REGISTRY_1_0.**
-
-Set this environment variable to make GStreamer use a different file for
-the plugin cache / registry than the default one. This is useful when
-operating in a separate environment which should not affect the default
-cache in the user's home directory.
-
-**GST_REGISTRY_FORK.**
-
-Set this environment variable to "no" to prevent GStreamer from forking
-on startup in order to update the plugin registry. This is useful for
-debugging purposes, but should not be used under normal circumstances,
-since it means that plugins may be loaded into memory even if they are
-not needed by the application.
-
-**GST_REGISTRY_UPDATE.**
-
-Set this environment variable to "no" to prevent GStreamer from updating
-the plugin registry. This is useful for embedded device which is not
-updating the plugins frequently, it will save time when doing
-gst_init().
-
-**GST_TRACE.**
-
-Enable memory allocation tracing. Most GStreamer objects have support
-for tracing the number of unfreed objects and their memory pointers.
-
-The variable takes a comma-separated list of tracing options to enable.
-
-* live: Counts all live objects and dumps an overview of the number of
-    unfreed objects at program exit.
-
-* mem-live: Keep track of the unfreed memory pointers and dump an overview of
-    all unfreed memory at program exit. Together with a level 9 debug
-    log this can be used to follow the lifecycle of leaked objects in
-    order to track down where they are leaked. This can be useful for
-    debugging memory leaks in situations where tools such as valgrind
-    are not available, or not an option.
-
-Use `all` to enable all tracing flags.
-
-**GST_DEBUG_FILE.**
-
-Set this variable to a file path to redirect all GStreamer debug
-messages to this file. If left unset, debug messages with be output unto
-the standard error. The %p pattern is replaced with the PID and the
-%r with a random number.
-
-
-**ORC_CODE.**
-
-Useful Orc environment variable. Set ORC_CODE=debug to enable debuggers
-such as gdb to create useful backtraces from Orc-generated code. Set
-ORC_CODE=backup or ORC_CODE=emulate if you suspect Orc's SIMD code
-generator is producing incorrect code (Quite a few important GStreamer
-plugins like videotestsrc, audioconvert or audioresample use Orc). One
-can also combine flags like ORC_CODE=backup,debug.
-
-**G_DEBUG.**
-
-Useful GLib environment variable. Set G_DEBUG=fatal_warnings to make
-GStreamer programs abort when a critical warning such as an assertion
-failure occurs. This is useful if you want to find out which part of the
-code caused that warning to be triggered and under what circumstances.
-Simply set G_DEBUG as mentioned above and run the program in gdb (or
-let it core dump). Then get a stack trace in the usual way.
-
-**G_SLICE.**
-
-Useful GLib environment variable. Set G_SLICE=always-malloc when
-running GStreamer programs in valgrind, or debugging memory leaks with
-other tools. See the GLib API reference for more details.
-
-**GST_TAG_ENCODING.**
-
-Try this character encoding first for tag-related strings where the
-encoding is not defined and which are not UTF-8 already. By default the
-current locale will be tried (if not UTF-8).
-
-**GST_TAG_ID3_ENCODING.**
-
-Try this character encoding first for ID3 tag-related strings where the
-encoding is not defined and which are not UTF-8 already. By default the
-current locale will be tried (if not UTF-8).
-
-**GST_TAG_ID3V1_ENCODING.**
-
-Try this character encoding first for ID3v1 tag-related strings where
-the encoding does not look like UTF-8.
-
-**GST_GL_WINDOW.**
-
-Influences the window system to use by the GStreamer OpenGL library.
-Common values are 'x11', 'wayland', 'surfaceless', 'win32' or 'cocoa'.
-
-**GST_GL_PLATFORM.**
-
-Influences the OpenGL platform to use by the GStreamer OpenGL library.
-Common values are 'egl', 'glx', 'wgl' or 'cgl'.
-
-**GST_GL_API.**
-
-Influences the OpenGL API requested by the OpenGL platform. Common
-values are 'opengl' or 'gles2'.
diff --git a/docs/libs/index.md b/docs/libs/index.md
deleted file mode 100644
index c51c1e8..0000000
--- a/docs/libs/index.md
+++ /dev/null
@@ -1 +0,0 @@
-# GStreamer core libraries API
diff --git a/docs/meson.build b/docs/meson.build
index a93e957..1bcdf80 100644
--- a/docs/meson.build
+++ b/docs/meson.build
@@ -44,36 +44,6 @@ gst_plugins_doc_dep = custom_target('build-doc-cache',
     build_always_stale: true,
 )
 
-hotdoc_p = find_program('hotdoc', required: get_option('doc'))
-if not hotdoc_p.found()
-    message('Hotdoc not found, not building the documentation')
-    subdir_done()
-endif
-
-hotdoc_req = '>= 0.11.0'
-hotdoc_version = run_command(hotdoc_p, '--version', check: false).stdout()
-if not hotdoc_version.version_compare(hotdoc_req)
-    if get_option('doc').enabled()
-        error('Hotdoc version @0@ not found, got @1@'.format(hotdoc_req, hotdoc_version))
-    else
-        message('Hotdoc version @0@ not found, got @1@'.format(hotdoc_req, hotdoc_version))
-        subdir_done()
-    endif
-endif
-
-hotdoc = import('hotdoc')
-required_hotdoc_extensions = ['gi-extension', 'gst-extension']
-foreach extension: required_hotdoc_extensions
-    if not hotdoc.has_extensions(extension)
-        if get_option('doc').enabled()
-            error('Documentation enabled but @0@ missing'.format(extension))
-        endif
-
-        message('@0@ extension not found, not building documentation'.format(extension))
-        subdir_done()
-    endif
-endforeach
-
 if static_build
     if get_option('doc').enabled()
         error('Documentation enabled but not supported when building statically.')
@@ -99,7 +69,7 @@ endforeach
 
 build_hotdoc = true
 docconf = configuration_data()
-docconf.set('GST_API_VERSION', apiversion)
+docconf.set('GST_API_VERSION', api_version)
 
 version_entities = configure_file(input : 'version.in',
     output : 'gst_api_version.md',
@@ -121,66 +91,117 @@ foreach h: ['gettext.h', 'glib-compat-private.h', 'glib-compat.h',
     gst_excludes += [join_paths(meson.current_source_dir(), '..', 'gst', h)]
 endforeach
 
-libs_doc = [hotdoc.generate_doc('gstreamer',
-    project_version: apiversion,
-    gi_c_sources: '../gst/*.[hc]',
-    gi_sources: [gst_gir[0].full_path()],
-    gi_c_source_filters: gst_excludes,
-    sitemap: 'gst/sitemap.txt',
-    index: 'gst/index.md',
-    gi_index: 'gst/gi-index.md',
-    gi_smart_index: true,
-    gi_c_source_roots: [join_paths(meson.current_source_dir(), '../gst/'), ],
-    dependencies: [gst_dep, gmodule_dep],
-    extra_assets: [join_paths(meson.current_source_dir(), 'images')],
-    depends: gst_gir[0],
-)]
-
-libs = [
-  ['base', gst_base_gir, gst_base_dep],
-  ['controller', gst_controller_gir, gst_controller_dep,],
-  ['net', gst_net_gir, gst_net_dep],
-  ['check', gst_check_gir, gst_check_dep],
-]
-
-foreach lib: libs
-  name = lib[0]
-  gir = lib[1]
-  deps = [lib[2], gir]
-  libs_doc += [hotdoc.generate_doc(name,
-      project_version: apiversion,
-      gi_c_sources: ['../libs/gst/' + name + '/*.[hc]'],
-      gi_c_source_filters: gst_excludes,
-      gi_sources: gir[0].full_path(),
-      gi_c_source_roots: [join_paths(meson.current_source_dir(), '../libs/gst/' + name), ],
-      sitemap: join_paths('libs', name, 'sitemap.txt'),
-      index: join_paths('libs/', name, 'index.md'),
-      gi_index: join_paths('libs/', name, 'index.md'),
-      gi_smart_index: true,
-      gi_order_generated_subpages: true,
-      dependencies: deps,
-      install: false,
-      depends: gir[0],
-  )]
+cdir = meson.current_source_dir()
+
+doc_sources = []
+foreach s: gst_sources + gst_headers
+  doc_sources += s.full_path()
 endforeach
 
-cdir = meson.current_source_dir()
-if host_machine.system() == 'windows'
-  pathsep = ';'
-else
-  pathsep = ':'
-endif
-gst_plugins_doc = run_command(
+lib_sources = {
+  'gst': pathsep.join(doc_sources)
+}
+
+gst_doc_source_file = configure_file(
+  output: 'gst_doc_sources.json',
+  configuration: lib_sources,
+  output_format: 'json')
+
+gst_doc_gi_source_file = configure_file(
+  output: 'gst_doc_gi_sources.json',
+  configuration: {'gst': gst_gir[0].full_path()},
+  output_format: 'json'
+)
+
+lib_hotdoc_config = custom_target(
+  'build-gst-hotdoc-configs',
+  command: [
+    plugins_cache_generator,
+    'hotdoc-lib-config',
+    '--srcdir', cdir,
+    '--builddir', meson.current_build_dir(),
+    '--buildroot', meson.global_build_root(),
+    '--project_version', api_version,
+    '--gi_source_file', gst_doc_gi_source_file,
+    '--gi_c_source_file', gst_doc_source_file,
+    '--gi_c_source_filters', gst_excludes,
+    '--source_root', cdir / 'gst',
+    '--gi_source_root', cdir / '..' / 'gst',
+    '--output', '@OUTPUT@',
+  ],
+  output: 'hotdoc-gst-configs.json',
+  depends: [gst_gir[0]],
+)
+
+libs_doc_source_file = configure_file(
+  output: 'libs_doc_sources.json',
+  configuration: libs_sources,
+  output_format: 'json')
+
+libs_doc_gi_source_file = configure_file(
+  output: 'libs_doc_gi_sources.json',
+  configuration: {
+    'base': gst_base_gir[0].full_path(),
+    'controller': gst_controller_gir[0].full_path(),
+    'net': gst_net_gir[0].full_path(),
+    'check': gst_check_gir[0].full_path(),
+  },
+  output_format: 'json')
+
+libs_hotdoc_configs = custom_target(
+  'build-libs-hotdoc-configs',
+  command: [
+    plugins_cache_generator,
+    'hotdoc-lib-config',
+    '--srcdir', cdir,
+    '--builddir', meson.current_build_dir(),
+    '--buildroot', meson.global_build_root(),
+    '--project_version', api_version,
+    '--gi_source_file', libs_doc_gi_source_file,
+    '--gi_c_source_file', libs_doc_source_file,
+    '--gi_c_source_filters', gst_excludes,
+    '--source_root', cdir / 'libs',
+    '--gi_source_root', cdir / '..' / 'libs' / 'gst',
+    '--output', '@OUTPUT@',
+  ],
+  output: 'hotdoc-libs-configs.json',
+  depends: [gst_base_gir[0], gst_controller_gir[0], gst_net_gir[0], gst_check_gir[0]],
+)
+
+doc_source_file = configure_file(output: 'doc_sources.json', configuration: plugin_sources, output_format: 'json')
+
+plugin_libraries = {}
+
+foreach plugin: plugins
+  if plugin.name().startswith('gst')
+    plugin_name = plugin.name().substring(3)
+  else
+    plugin_name = plugin.name()
+  endif
+
+  plugin_libraries += {
+    plugin_name: plugin.full_path()
+  }
+endforeach
+
+doc_plugin_libs_file = configure_file(output: 'doc_plugin_libs.json', configuration: plugin_libraries, output_format: 'json')
+
+plugin_hotdoc_configs = custom_target(
+  'build-hotdoc-configs',
+  command: [
     plugins_cache_generator,
     'hotdoc-config',
     '--builddir', meson.current_build_dir(),
-    '--project_version', apiversion,
+    '--project_version', api_version,
     '--sitemap', cdir / 'plugins/sitemap.txt',
     '--index', cdir / 'plugins/index.md',
     '--gst_index', cdir / 'plugins/index.md',
-    '--gst_c_sources',
-        cdir / '../plugins/*/*.c',
-        cdir / '../plugins/*/*.h',
-    '--gst_cache_file', plugins_cache,
-    check: true,
-).stdout().split(pathsep)
+    '--gst_c_source_file', doc_source_file,
+    '--gst_plugin_libraries_file', doc_plugin_libs_file,
+    '--gst_cache_file', '@INPUT@',
+    '--output', '@OUTPUT@',
+  ],
+  input: plugins_cache,
+  output: 'hotdoc-configs.json',
+  depends: [hotdoc_plugin_scanner],
+)
diff --git a/docs/plugins/gst_plugins_cache.json b/docs/plugins/gst_plugins_cache.json
index 33f8baa..4743ed7 100644
--- a/docs/plugins/gst_plugins_cache.json
+++ b/docs/plugins/gst_plugins_cache.json
@@ -839,6 +839,18 @@
                         "type": "gint",
                         "writable": true
                     },
+                    "is-live": {
+                        "blurb": "Act like a live source",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "false",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "gboolean",
+                        "writable": true
+                    },
                     "timeout": {
                         "blurb": "Post a message after timeout microseconds (0 = disabled)",
                         "conditionally-available": false,
@@ -1905,6 +1917,18 @@
                         "type": "guint64",
                         "writable": true
                     },
+                    "notify-levels": {
+                        "blurb": "Whether to emit `notify` signals on levels changes or not",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "false",
+                        "mutable": "playing",
+                        "readable": true,
+                        "type": "gboolean",
+                        "writable": true
+                    },
                     "silent": {
                         "blurb": "Don't emit queue signals",
                         "conditionally-available": false,
@@ -2924,12 +2948,185 @@
         "package": "GStreamer",
         "source": "gstreamer",
         "tracers": {
-            "factories": {},
-            "latency": {},
-            "leaks": {},
-            "log": {},
-            "rusage": {},
-            "stats": {}
+            "dots": {
+                "hierarchy": [
+                    "GstDotsTracer",
+                    "GstTracer",
+                    "GstObject",
+                    "GInitiallyUnowned",
+                    "GObject"
+                ],
+                "properties": {
+                    "no-delete": {
+                        "blurb": "Don't delete existing .dot files on startup",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": false,
+                        "controllable": false,
+                        "default": "false",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "gboolean",
+                        "writable": true
+                    }
+                }
+            },
+            "factories": {
+                "hierarchy": [
+                    "GstFactoriesTracer",
+                    "GstTracer",
+                    "GstObject",
+                    "GInitiallyUnowned",
+                    "GObject"
+                ]
+            },
+            "latency": {
+                "hierarchy": [
+                    "GstLatencyTracer",
+                    "GstTracer",
+                    "GstObject",
+                    "GInitiallyUnowned",
+                    "GObject"
+                ],
+                "properties": {
+                    "flags": {
+                        "blurb": "Flags to control what latency measurements to perform",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": true,
+                        "controllable": false,
+                        "default": "pipeline",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "GstLatencyTracerFlags",
+                        "writable": true
+                    }
+                }
+            },
+            "leaks": {
+                "hierarchy": [
+                    "GstLeaksTracer",
+                    "GstTracer",
+                    "GstObject",
+                    "GInitiallyUnowned",
+                    "GObject"
+                ],
+                "properties": {
+                    "check-refs": {
+                        "blurb": "Whether to track ref/unref operations",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": true,
+                        "controllable": false,
+                        "default": "false",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "gboolean",
+                        "writable": true
+                    },
+                    "filters": {
+                        "blurb": "Comma-separated list of GObject types to track",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": true,
+                        "controllable": false,
+                        "default": "",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "gchararray",
+                        "writable": true
+                    },
+                    "log-leaks-on-deinit": {
+                        "blurb": "Whether to log leaks on shutdown",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": true,
+                        "controllable": false,
+                        "default": "true",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "gboolean",
+                        "writable": true
+                    },
+                    "stack-traces-flags": {
+                        "blurb": "Stack trace collection mode",
+                        "conditionally-available": false,
+                        "construct": false,
+                        "construct-only": true,
+                        "controllable": false,
+                        "default": "disabled",
+                        "mutable": "null",
+                        "readable": true,
+                        "type": "GstLeaksStackTraceFlags",
+                        "writable": true
+                    }
+                },
+                "signals": {
+                    "activity-get-checkpoint": {
+                        "action": true,
+                        "args": [],
+                        "return-type": "GstStructure",
+                        "when": "last"
+                    },
+                    "activity-log-checkpoint": {
+                        "action": true,
+                        "args": [],
+                        "return-type": "void",
+                        "when": "last"
+                    },
+                    "activity-start-tracking": {
+                        "action": true,
+                        "args": [],
+                        "return-type": "void",
+                        "when": "last"
+                    },
+                    "activity-stop-tracking": {
+                        "action": true,
+                        "args": [],
+                        "return-type": "void",
+                        "when": "last"
+                    },
+                    "get-live-objects": {
+                        "action": true,
+                        "args": [],
+                        "return-type": "GstStructure",
+                        "when": "last"
+                    },
+                    "log-live-objects": {
+                        "action": true,
+                        "args": [],
+                        "return-type": "void",
+                        "when": "last"
+                    }
+                }
+            },
+            "log": {
+                "hierarchy": [
+                    "GstLogTracer",
+                    "GstTracer",
+                    "GstObject",
+                    "GInitiallyUnowned",
+                    "GObject"
+                ]
+            },
+            "rusage": {
+                "hierarchy": [
+                    "GstRUsageTracer",
+                    "GstTracer",
+                    "GstObject",
+                    "GInitiallyUnowned",
+                    "GObject"
+                ]
+            },
+            "stats": {
+                "hierarchy": [
+                    "GstStatsTracer",
+                    "GstTracer",
+                    "GstObject",
+                    "GInitiallyUnowned",
+                    "GObject"
+                ]
+            }
         },
         "url": "Unknown package origin"
     }
diff --git a/gst/glib-compat-private.h b/gst/glib-compat-private.h
index 617a50e..18f6424 100644
--- a/gst/glib-compat-private.h
+++ b/gst/glib-compat-private.h
@@ -34,6 +34,26 @@ G_BEGIN_DECLS
 #define g_memdup2(ptr,sz) ((G_LIKELY(((guint64)(sz)) < G_MAXUINT)) ? g_memdup(ptr,sz) : (g_abort(),NULL))
 #endif
 
+#if !GLIB_CHECK_VERSION(2, 81, 1)
+#define g_sort_array(a,n,s,f,udata) gst_g_sort_array(a,n,s,f,udata)
+
+// Don't need to maintain ABI compat here (n_elements), since we never pass
+// the function as pointer but always call it directly ourselves.
+static inline void
+gst_g_sort_array (const void       *array,
+                  gssize            n_elements,
+                  size_t            element_size,
+                  GCompareDataFunc  compare_func,
+                  void             *user_data)
+{
+  if (n_elements >= 0 && n_elements <= G_MAXINT) {
+    g_qsort_with_data (array, n_elements, element_size, compare_func, user_data);
+  } else {
+    g_abort ();
+  }
+}
+#endif
+
 G_END_DECLS
 
 #endif
diff --git a/gst/gst.c b/gst/gst.c
index d766d16..c4e4d8c 100644
--- a/gst/gst.c
+++ b/gst/gst.c
@@ -662,7 +662,6 @@ init_post (GOptionContext * context, GOptionGroup * group, gpointer data,
   }
 
   _priv_gst_mini_object_initialize ();
-  _priv_gst_quarks_initialize ();
   _priv_gst_allocator_initialize ();
   _priv_gst_memory_initialize ();
   _priv_gst_format_initialize ();
@@ -816,6 +815,12 @@ init_post (GOptionContext * context, GOptionGroup * group, gpointer data,
 
 #ifndef GST_DISABLE_GST_TRACER_HOOKS
   _priv_gst_tracing_init ();
+  /* Allow the `dots` tracer to set the `GST_DEBUG_DUMP_DOT_DIR` variable if it
+   * was not set before */
+#ifndef GST_DISABLE_GST_DEBUG
+  if (!priv_gst_dump_dot_dir)
+    priv_gst_dump_dot_dir = g_getenv ("GST_DEBUG_DUMP_DOT_DIR");
+#endif
 #endif
 
   return TRUE;
diff --git a/gst/gst.h b/gst/gst.h
index 25010b3..7cb55a0 100644
--- a/gst/gst.h
+++ b/gst/gst.h
@@ -53,6 +53,7 @@
 #include <gst/gsterror.h>
 #include <gst/gstevent.h>
 #include <gst/gstghostpad.h>
+#include <gst/gstidstr.h>
 #include <gst/gstinfo.h>
 #include <gst/gstiterator.h>
 #include <gst/gstmessage.h>
@@ -90,6 +91,7 @@
 #include <gst/gsturi.h>
 #include <gst/gstutils.h>
 #include <gst/gstvalue.h>
+#include <gst/gstvecdeque.h>
 
 #include <gst/gstparse.h>
 
diff --git a/gst/gst_private.h b/gst/gst_private.h
index 8166a45..cc05f87 100644
--- a/gst/gst_private.h
+++ b/gst/gst_private.h
@@ -114,7 +114,6 @@ G_GNUC_INTERNAL  gboolean _priv_plugin_deps_env_vars_changed (GstPlugin * plugin
 G_GNUC_INTERNAL  gboolean _priv_plugin_deps_files_changed (GstPlugin * plugin);
 
 /* init functions called from gst_init(). */
-G_GNUC_INTERNAL  void  _priv_gst_quarks_initialize (void);
 G_GNUC_INTERNAL  void  _priv_gst_mini_object_initialize (void);
 G_GNUC_INTERNAL  void  _priv_gst_memory_initialize (void);
 G_GNUC_INTERNAL  void  _priv_gst_allocator_initialize (void);
@@ -183,7 +182,7 @@ gboolean  priv_gst_structure_append_to_gstring (const GstStructure * structure,
                                                 GString            * s,
                                                 GstSerializeFlags flags);
 G_GNUC_INTERNAL
-gboolean priv__gst_structure_append_template_to_gstring (GQuark field_id,
+gboolean priv__gst_structure_append_template_to_gstring (const gchar * field,
                                                         const GValue *value,
                                                         gpointer user_data);
 
@@ -244,6 +243,13 @@ GST_API gboolean _gst_disable_registry_cache;
  * as the main application in order to determine dependencies */
 GST_API gchar *_gst_executable_path;
 
+/* Internal variables used in gstutils.c and initialized in
+ * _priv_gst_plugin_initialize(). */
+G_GNUC_INTERNAL
+extern GQuark _priv_gst_plugin_api_quark;
+G_GNUC_INTERNAL
+extern GQuark _priv_gst_plugin_api_flags_quark;
+
 /* provide inline gst_g_value_get_foo_unchecked(), used in gststructure.c */
 #define DEFINE_INLINE_G_VALUE_GET_UNCHECKED(ret_type,name_type,v_field) \
 static inline ret_type                                                  \
diff --git a/gst/gstbuffer.c b/gst/gstbuffer.c
index 52ce8e5..c41189f 100644
--- a/gst/gstbuffer.c
+++ b/gst/gstbuffer.c
@@ -172,7 +172,14 @@ typedef struct
 static gint64 meta_seq;         /* 0 *//* ATOMIC */
 
 /* TODO: use GLib's once https://gitlab.gnome.org/GNOME/glib/issues/1076 lands */
-#if defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8)
+#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L && !defined(__STDC_NO_ATOMICS__)
+#include <stdatomic.h>
+static inline gint64
+gst_atomic_int64_inc (gint64 * atomic)
+{
+  return atomic_fetch_add ((_Atomic gint64 *) atomic, 1);
+}
+#elif defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8)
 static inline gint64
 gst_atomic_int64_inc (gint64 * atomic)
 {
@@ -1979,7 +1986,7 @@ gst_buffer_fill (GstBuffer * buffer, gsize offset, gconstpointer src,
  * @offset: the offset to extract
  * @dest: (out caller-allocates) (array length=size) (element-type guint8):
  *     the destination address
- * @size: the size to extract
+ * @size: (in): the size to extract
  *
  * Copies @size bytes starting from @offset in @buffer to @dest.
  *
@@ -2483,8 +2490,8 @@ gst_buffer_iterate_meta_filtered (GstBuffer * buffer, gpointer * state,
 /**
  * gst_buffer_foreach_meta:
  * @buffer: a #GstBuffer
- * @func: (scope call): a #GstBufferForeachMetaFunc to call
- * @user_data: (closure): user data passed to @func
+ * @func: (scope call) (closure user_data): a #GstBufferForeachMetaFunc to call
+ * @user_data: user data passed to @func
  *
  * Calls @func with @user_data for each meta in @buffer.
  *
@@ -2797,12 +2804,28 @@ static gboolean
 _gst_reference_timestamp_meta_transform (GstBuffer * dest, GstMeta * meta,
     GstBuffer * buffer, GQuark type, gpointer data)
 {
-  GstReferenceTimestampMeta *dmeta, *smeta;
+  const GstReferenceTimestampMeta *smeta, *ometa;
+  GstReferenceTimestampMeta *dmeta;
+  gpointer iter = NULL;
 
   /* we copy over the reference timestamp meta, independent of transformation
    * that happens. If it applied to the original buffer, it still applies to
    * the new buffer as it refers to the time when the media was captured */
-  smeta = (GstReferenceTimestampMeta *) meta;
+  smeta = (const GstReferenceTimestampMeta *) meta;
+
+  while ((ometa = (const GstReferenceTimestampMeta *)
+          gst_buffer_iterate_meta_filtered (dest, &iter,
+              GST_REFERENCE_TIMESTAMP_META_API_TYPE))) {
+    if (ometa->timestamp == smeta->timestamp
+        && ometa->duration == smeta->duration
+        && gst_caps_is_equal (ometa->reference, smeta->reference)) {
+      GST_CAT_TRACE (gst_reference_timestamp_meta_debug,
+          "Not copying reference timestamp metadata from buffer %p to %p because equal meta already exists",
+          buffer, dest);
+      return TRUE;
+    }
+  }
+
   dmeta =
       gst_buffer_add_reference_timestamp_meta (dest, smeta->reference,
       smeta->timestamp, smeta->duration);
diff --git a/gst/gstbufferlist.c b/gst/gstbufferlist.c
index 140c9cf..a75fc3c 100644
--- a/gst/gstbufferlist.c
+++ b/gst/gstbufferlist.c
@@ -223,8 +223,8 @@ gst_buffer_list_remove_range_internal (GstBufferList * list, guint idx,
 /**
  * gst_buffer_list_foreach:
  * @list: a #GstBufferList
- * @func: (scope call): a #GstBufferListFunc to call
- * @user_data: (closure): user data passed to @func
+ * @func: (scope call) (closure user_data): a #GstBufferListFunc to call
+ * @user_data: user data passed to @func
  *
  * Calls @func with @data for each buffer in @list.
  *
@@ -332,9 +332,9 @@ gst_buffer_list_foreach (GstBufferList * list, GstBufferListFunc func,
  * You must make sure that @idx does not exceed the number of
  * buffers available.
  *
- * Returns: (transfer none) (nullable): the buffer at @idx in @group
- *     or %NULL when there is no buffer. The buffer remains valid as
- *     long as @list is valid and buffer is not removed from the list.
+ * Returns: (transfer none): the buffer at @idx in @group.
+ *     The returned buffer remains valid as long as @list is valid and
+ *     buffer is not removed from the list.
  */
 GstBuffer *
 gst_buffer_list_get (GstBufferList * list, guint idx)
@@ -355,8 +355,8 @@ gst_buffer_list_get (GstBufferList * list, guint idx)
  * You must make sure that @idx does not exceed the number of
  * buffers available.
  *
- * Returns: (transfer none) (nullable): the buffer at @idx in @group.
- *     The returned  buffer remains valid as long as @list is valid and
+ * Returns: (transfer none): the buffer at @idx in @group.
+ *     The returned buffer remains valid as long as @list is valid and
  *     the buffer is not removed from the list.
  *
  * Since: 1.14
diff --git a/gst/gstbufferpool.c b/gst/gstbufferpool.c
index d7da0cd..9deef6c 100644
--- a/gst/gstbufferpool.c
+++ b/gst/gstbufferpool.c
@@ -70,10 +70,8 @@
 #endif
 #include <sys/types.h>
 
-#include "gstatomicqueue.h"
-#include "gstpoll.h"
+#include "gstvecdeque.h"
 #include "gstinfo.h"
-#include "gstquark.h"
 #include "gstvalue.h"
 
 #include "gstbufferpool.h"
@@ -92,8 +90,9 @@ GST_DEBUG_CATEGORY_STATIC (gst_buffer_pool_debug);
 
 struct _GstBufferPoolPrivate
 {
-  GstAtomicQueue *queue;
-  GstPoll *poll;
+  GMutex queue_lock;
+  GCond queue_cond;
+  GstVecDeque *queue;
 
   GRecMutex rec_lock;
 
@@ -159,22 +158,20 @@ gst_buffer_pool_init (GstBufferPool * pool)
 
   g_rec_mutex_init (&priv->rec_lock);
 
-  priv->poll = gst_poll_new_timer ();
-  priv->queue = gst_atomic_queue_new (16);
+  priv->queue = gst_vec_deque_new (16);
+  g_mutex_init (&priv->queue_lock);
+  g_cond_init (&priv->queue_cond);
+
   pool->flushing = 1;
   priv->active = FALSE;
   priv->configured = FALSE;
   priv->started = FALSE;
-  priv->config = gst_structure_new_id_empty (GST_QUARK (BUFFER_POOL_CONFIG));
+  priv->config = gst_structure_new_static_str_empty ("GstBufferPoolConfig");
   gst_buffer_pool_config_set_params (priv->config, NULL, 0, 0, 0);
   priv->allocator = NULL;
   gst_allocation_params_init (&priv->params);
   gst_buffer_pool_config_set_allocator (priv->config, priv->allocator,
       &priv->params);
-  /* 1 control write for flushing - the flush token */
-  gst_poll_write_control (priv->poll);
-  /* 1 control write for marking that we are not waiting for poll - the wait token */
-  gst_poll_write_control (priv->poll);
 
   GST_DEBUG_OBJECT (pool, "created");
 }
@@ -207,8 +204,9 @@ gst_buffer_pool_finalize (GObject * object)
 
   GST_DEBUG_OBJECT (pool, "%p finalize", pool);
 
-  gst_atomic_queue_unref (priv->queue);
-  gst_poll_free (priv->poll);
+  gst_vec_deque_free (priv->queue);
+  g_mutex_clear (&priv->queue_lock);
+  g_cond_clear (&priv->queue_cond);
   gst_structure_free (priv->config);
   g_rec_mutex_clear (&priv->rec_lock);
 
@@ -397,6 +395,10 @@ do_free_buffer (GstBufferPool * pool, GstBuffer * buffer)
 
   if (G_LIKELY (pclass->free_buffer))
     pclass->free_buffer (pool, buffer);
+
+  g_mutex_lock (&priv->queue_lock);
+  g_cond_signal (&priv->queue_cond);
+  g_mutex_unlock (&priv->queue_lock);
 }
 
 /* must be called with the lock */
@@ -405,23 +407,18 @@ default_stop (GstBufferPool * pool)
 {
   GstBufferPoolPrivate *priv = pool->priv;
   GstBuffer *buffer;
+  gboolean cleared;
 
   /* clear the pool */
-  while ((buffer = gst_atomic_queue_pop (priv->queue))) {
-    while (!gst_poll_read_control (priv->poll)) {
-      if (errno == EWOULDBLOCK) {
-        /* We put the buffer into the queue but did not finish writing control
-         * yet, let's wait a bit and retry */
-        g_thread_yield ();
-        continue;
-      } else {
-        /* Critical error but GstPoll already complained */
-        break;
-      }
-    }
+  g_mutex_lock (&priv->queue_lock);
+  while ((buffer = gst_vec_deque_pop_head (priv->queue))) {
+    g_mutex_unlock (&priv->queue_lock);
     do_free_buffer (pool, buffer);
+    g_mutex_lock (&priv->queue_lock);
   }
-  return priv->cur_buffers == 0;
+  cleared = priv->cur_buffers == 0;
+  g_mutex_unlock (&priv->queue_lock);
+  return cleared;
 }
 
 /* must be called with the lock */
@@ -458,9 +455,11 @@ do_set_flushing (GstBufferPool * pool, gboolean flushing)
     return;
 
   if (flushing) {
+    /* Wake up any waiters */
+    g_mutex_lock (&priv->queue_lock);
     g_atomic_int_set (&pool->flushing, 1);
-    /* Write the flush token to wake up any waiters */
-    gst_poll_write_control (priv->poll);
+    g_cond_broadcast (&priv->queue_cond);
+    g_mutex_unlock (&priv->queue_lock);
 
     if (pclass->flush_start)
       pclass->flush_start (pool);
@@ -468,19 +467,6 @@ do_set_flushing (GstBufferPool * pool, gboolean flushing)
     if (pclass->flush_stop)
       pclass->flush_stop (pool);
 
-    while (!gst_poll_read_control (priv->poll)) {
-      if (errno == EWOULDBLOCK) {
-        /* This should not really happen unless flushing and unflushing
-         * happens on different threads. Let's wait a bit to get back flush
-         * token from the thread that was setting it to flushing */
-        g_thread_yield ();
-        continue;
-      } else {
-        /* Critical error but GstPoll already complained */
-        break;
-      }
-    }
-
     g_atomic_int_set (&pool->flushing, 0);
   }
 }
@@ -843,11 +829,11 @@ gst_buffer_pool_config_set_params (GstStructure * config, GstCaps * caps,
   g_return_if_fail (max_buffers == 0 || min_buffers <= max_buffers);
   g_return_if_fail (caps == NULL || gst_caps_is_fixed (caps));
 
-  gst_structure_id_set (config,
-      GST_QUARK (CAPS), GST_TYPE_CAPS, caps,
-      GST_QUARK (SIZE), G_TYPE_UINT, size,
-      GST_QUARK (MIN_BUFFERS), G_TYPE_UINT, min_buffers,
-      GST_QUARK (MAX_BUFFERS), G_TYPE_UINT, max_buffers, NULL);
+  gst_structure_set_static_str (config,
+      "caps", GST_TYPE_CAPS, caps,
+      "size", G_TYPE_UINT, size,
+      "min-buffers", G_TYPE_UINT, min_buffers,
+      "max-buffers", G_TYPE_UINT, max_buffers, NULL);
 }
 
 /**
@@ -876,9 +862,9 @@ gst_buffer_pool_config_set_allocator (GstStructure * config,
   g_return_if_fail (config != NULL);
   g_return_if_fail (allocator != NULL || params != NULL);
 
-  gst_structure_id_set (config,
-      GST_QUARK (ALLOCATOR), GST_TYPE_ALLOCATOR, allocator,
-      GST_QUARK (PARAMS), GST_TYPE_ALLOCATION_PARAMS, params, NULL);
+  gst_structure_set_static_str (config,
+      "allocator", GST_TYPE_ALLOCATOR, allocator,
+      "params", GST_TYPE_ALLOCATION_PARAMS, params, NULL);
 }
 
 /**
@@ -900,7 +886,7 @@ gst_buffer_pool_config_add_option (GstStructure * config, const gchar * option)
 
   g_return_if_fail (config != NULL);
 
-  value = gst_structure_id_get_value (config, GST_QUARK (OPTIONS));
+  value = gst_structure_get_value (config, "options");
   if (value) {
     len = gst_value_array_get_size (value);
     for (i = 0; i < len; ++i) {
@@ -913,8 +899,8 @@ gst_buffer_pool_config_add_option (GstStructure * config, const gchar * option)
     GValue new_array_val = { 0, };
 
     g_value_init (&new_array_val, GST_TYPE_ARRAY);
-    gst_structure_id_take_value (config, GST_QUARK (OPTIONS), &new_array_val);
-    value = gst_structure_id_get_value (config, GST_QUARK (OPTIONS));
+    gst_structure_take_value_static_str (config, "options", &new_array_val);
+    value = gst_structure_get_value (config, "options");
   }
   g_value_init (&option_value, G_TYPE_STRING);
   g_value_set_string (&option_value, option);
@@ -938,7 +924,7 @@ gst_buffer_pool_config_n_options (GstStructure * config)
 
   g_return_val_if_fail (config != NULL, 0);
 
-  value = gst_structure_id_get_value (config, GST_QUARK (OPTIONS));
+  value = gst_structure_get_value (config, "options");
   if (value) {
     size = gst_value_array_get_size (value);
   }
@@ -963,7 +949,7 @@ gst_buffer_pool_config_get_option (GstStructure * config, guint index)
 
   g_return_val_if_fail (config != NULL, 0);
 
-  value = gst_structure_id_get_value (config, GST_QUARK (OPTIONS));
+  value = gst_structure_get_value (config, "options");
   if (value) {
     const GValue *option_value;
 
@@ -991,7 +977,7 @@ gst_buffer_pool_config_has_option (GstStructure * config, const gchar * option)
 
   g_return_val_if_fail (config != NULL, 0);
 
-  value = gst_structure_id_get_value (config, GST_QUARK (OPTIONS));
+  value = gst_structure_get_value (config, "options");
   if (value) {
     len = gst_value_array_get_size (value);
     for (i = 0; i < len; ++i) {
@@ -1023,13 +1009,12 @@ gst_buffer_pool_config_get_params (GstStructure * config, GstCaps ** caps,
   g_return_val_if_fail (config != NULL, FALSE);
 
   if (caps) {
-    *caps = g_value_get_boxed (gst_structure_id_get_value (config,
-            GST_QUARK (CAPS)));
+    *caps = g_value_get_boxed (gst_structure_get_value (config, "caps"));
   }
-  return gst_structure_id_get (config,
-      GST_QUARK (SIZE), G_TYPE_UINT, size,
-      GST_QUARK (MIN_BUFFERS), G_TYPE_UINT, min_buffers,
-      GST_QUARK (MAX_BUFFERS), G_TYPE_UINT, max_buffers, NULL);
+  return gst_structure_get (config,
+      "size", G_TYPE_UINT, size,
+      "min-buffers", G_TYPE_UINT, min_buffers,
+      "max-buffers", G_TYPE_UINT, max_buffers, NULL);
 }
 
 /**
@@ -1049,13 +1034,12 @@ gst_buffer_pool_config_get_allocator (GstStructure * config,
   g_return_val_if_fail (config != NULL, FALSE);
 
   if (allocator)
-    *allocator = g_value_get_object (gst_structure_id_get_value (config,
-            GST_QUARK (ALLOCATOR)));
+    *allocator = g_value_get_object (gst_structure_get_value (config,
+            "allocator"));
   if (params) {
     GstAllocationParams *p;
 
-    p = g_value_get_boxed (gst_structure_id_get_value (config,
-            GST_QUARK (PARAMS)));
+    p = g_value_get_boxed (gst_structure_get_value (config, "params"));
     if (p) {
       *params = *p;
     } else {
@@ -1112,24 +1096,16 @@ default_acquire_buffer (GstBufferPool * pool, GstBuffer ** buffer,
   GstFlowReturn result;
   GstBufferPoolPrivate *priv = pool->priv;
 
+  g_mutex_lock (&priv->queue_lock);
   while (TRUE) {
     if (G_UNLIKELY (GST_BUFFER_POOL_IS_FLUSHING (pool)))
       goto flushing;
 
     /* try to get a buffer from the queue */
-    *buffer = gst_atomic_queue_pop (priv->queue);
+    *buffer = gst_vec_deque_pop_head (priv->queue);
+    g_mutex_unlock (&priv->queue_lock);
+
     if (G_LIKELY (*buffer)) {
-      while (!gst_poll_read_control (priv->poll)) {
-        if (errno == EWOULDBLOCK) {
-          /* We put the buffer into the queue but did not finish writing control
-           * yet, let's wait a bit and retry */
-          g_thread_yield ();
-          continue;
-        } else {
-          /* Critical error but GstPoll already complained */
-          break;
-        }
-      }
       result = GST_FLOW_OK;
       GST_LOG_OBJECT (pool, "acquired buffer %p", *buffer);
       break;
@@ -1152,34 +1128,14 @@ default_acquire_buffer (GstBufferPool * pool, GstBuffer ** buffer,
       break;
     }
 
-    /* now we release the control socket, we wait for a buffer release or
-     * flushing */
-    if (!gst_poll_read_control (pool->priv->poll)) {
-      if (errno == EWOULDBLOCK) {
-        /* This means that we have two threads trying to allocate buffers
-         * already, and the other one already got the wait token. This
-         * means that we only have to wait for the poll now and not write the
-         * token afterwards: we will be woken up once the other thread is
-         * woken up and that one will write the wait token it removed */
-        GST_LOG_OBJECT (pool, "waiting for free buffers or flushing");
-        gst_poll_wait (priv->poll, GST_CLOCK_TIME_NONE);
-      } else {
-        /* This is a critical error, GstPoll already gave a warning */
-        result = GST_FLOW_ERROR;
-        break;
-      }
-    } else {
-      /* We're the first thread waiting, we got the wait token and have to
-       * write it again later
-       * OR
-       * We're a second thread and just consumed the flush token and block all
-       * other threads, in which case we must not wait and give it back
-       * immediately */
-      if (!GST_BUFFER_POOL_IS_FLUSHING (pool)) {
-        GST_LOG_OBJECT (pool, "waiting for free buffers or flushing");
-        gst_poll_wait (priv->poll, GST_CLOCK_TIME_NONE);
-      }
-      gst_poll_write_control (pool->priv->poll);
+    /* now we wait for a buffer release or flushing */
+    g_mutex_lock (&priv->queue_lock);
+    while (gst_vec_deque_get_length (priv->queue) == 0
+        && !GST_BUFFER_POOL_IS_FLUSHING (pool)
+        && g_atomic_int_get (&priv->cur_buffers) >= priv->max_buffers) {
+      GST_LOG_OBJECT (pool, "waiting for free buffers or flushing");
+      g_cond_wait (&priv->queue_cond, &priv->queue_lock);
+      GST_LOG_OBJECT (pool, "waited for free buffers or flushing");
     }
   }
 
@@ -1188,6 +1144,7 @@ default_acquire_buffer (GstBufferPool * pool, GstBuffer ** buffer,
   /* ERRORS */
 flushing:
   {
+    g_mutex_unlock (&priv->queue_lock);
     GST_DEBUG_OBJECT (pool, "we are flushing");
     return GST_FLOW_FLUSHING;
   }
@@ -1331,8 +1288,10 @@ default_release_buffer (GstBufferPool * pool, GstBuffer * buffer)
     goto not_writable;
 
   /* keep it around in our queue */
-  gst_atomic_queue_push (pool->priv->queue, buffer);
-  gst_poll_write_control (pool->priv->poll);
+  g_mutex_lock (&pool->priv->queue_lock);
+  gst_vec_deque_push_tail (pool->priv->queue, buffer);
+  g_cond_signal (&pool->priv->queue_cond);
+  g_mutex_unlock (&pool->priv->queue_lock);
 
   return;
 
@@ -1358,7 +1317,10 @@ not_writable:
 discard:
   {
     do_free_buffer (pool, buffer);
-    gst_poll_write_control (pool->priv->poll);
+
+    g_mutex_lock (&pool->priv->queue_lock);
+    g_cond_signal (&pool->priv->queue_cond);
+    g_mutex_unlock (&pool->priv->queue_lock);
     return;
   }
 }
diff --git a/gst/gstbufferpool.h b/gst/gstbufferpool.h
index 5d69fa7..22ec29e 100644
--- a/gst/gstbufferpool.h
+++ b/gst/gstbufferpool.h
@@ -157,6 +157,9 @@ struct _GstBufferPoolClass {
    * Start the bufferpool. The default implementation will preallocate
    * min-buffers buffers and put them in the queue.
    *
+   * Subclasses do not need to chain up to the parent's default implementation
+   * if they don't want min-buffers based preallocation.
+   *
    * Returns: whether the pool could be started.
    */
   gboolean       (*start)          (GstBufferPool *pool);
diff --git a/gst/gstbus.c b/gst/gstbus.c
index 3f6eb23..aaa32e8 100644
--- a/gst/gstbus.c
+++ b/gst/gstbus.c
@@ -73,7 +73,7 @@
 #endif
 #include <sys/types.h>
 
-#include "gstatomicqueue.h"
+#include "gstvecdeque.h"
 #include "gstinfo.h"
 #include "gstpoll.h"
 
@@ -140,8 +140,8 @@ sync_handler_unref (SyncHandler * handler)
 
 struct _GstBusPrivate
 {
-  GstAtomicQueue *queue;
   GMutex queue_lock;
+  GstVecDeque *queue;
 
   SyncHandler *sync_handler;
 
@@ -252,7 +252,7 @@ gst_bus_init (GstBus * bus)
   bus->priv = gst_bus_get_instance_private (bus);
   bus->priv->enable_async = DEFAULT_ENABLE_ASYNC;
   g_mutex_init (&bus->priv->queue_lock);
-  bus->priv->queue = gst_atomic_queue_new (32);
+  bus->priv->queue = gst_vec_deque_new (32);
 
   GST_DEBUG_OBJECT (bus, "created");
 }
@@ -267,11 +267,11 @@ gst_bus_dispose (GObject * object)
 
     g_mutex_lock (&bus->priv->queue_lock);
     do {
-      message = gst_atomic_queue_pop (bus->priv->queue);
+      message = gst_vec_deque_pop_head (bus->priv->queue);
       if (message)
         gst_message_unref (message);
     } while (message != NULL);
-    gst_atomic_queue_unref (bus->priv->queue);
+    gst_vec_deque_free (bus->priv->queue);
     bus->priv->queue = NULL;
     g_mutex_unlock (&bus->priv->queue_lock);
     g_mutex_clear (&bus->priv->queue_lock);
@@ -381,18 +381,21 @@ gst_bus_post (GstBus * bus, GstMessage * message)
       GST_DEBUG_OBJECT (bus, "[msg %p] dropped", message);
       break;
     case GST_BUS_PASS:{
-      guint length = gst_atomic_queue_length (bus->priv->queue);
+      g_mutex_lock (&bus->priv->queue_lock);
+      gsize length = gst_vec_deque_get_length (bus->priv->queue);
       if (G_UNLIKELY (length > 0 && length % WARN_QUEUE_SIZE == 0)) {
-        GST_WARNING_OBJECT (bus, "queue overflows with %d messages. "
+        GST_WARNING_OBJECT (bus,
+            "queue overflows with %" G_GSIZE_FORMAT " messages. "
             "Application is too slow or is not handling messages. "
             "Please add a message handler, otherwise the queue will grow "
             "infinitely.", length);
       }
       /* pass the message to the async queue, refcount passed in the queue */
       GST_DEBUG_OBJECT (bus, "[msg %p] pushing on async queue", message);
-      gst_atomic_queue_push (bus->priv->queue, message);
+      gst_vec_deque_push_tail (bus->priv->queue, message);
       gst_poll_write_control (bus->priv->poll);
       GST_DEBUG_OBJECT (bus, "[msg %p] pushed on async queue", message);
+      g_mutex_unlock (&bus->priv->queue_lock);
 
       break;
     }
@@ -415,8 +418,10 @@ gst_bus_post (GstBus * bus, GstMessage * message)
        * the cond will be signalled and we can continue */
       g_mutex_lock (lock);
 
-      gst_atomic_queue_push (bus->priv->queue, message);
+      g_mutex_lock (&bus->priv->queue_lock);
+      gst_vec_deque_push_tail (bus->priv->queue, message);
       gst_poll_write_control (bus->priv->poll);
+      g_mutex_unlock (&bus->priv->queue_lock);
 
       /* now block till the message is freed */
       g_cond_wait (cond, lock);
@@ -470,7 +475,9 @@ gst_bus_have_pending (GstBus * bus)
   g_return_val_if_fail (GST_IS_BUS (bus), FALSE);
 
   /* see if there is a message on the bus */
-  result = gst_atomic_queue_length (bus->priv->queue) != 0;
+  g_mutex_lock (&bus->priv->queue_lock);
+  result = gst_vec_deque_get_length (bus->priv->queue) != 0;
+  g_mutex_unlock (&bus->priv->queue_lock);
 
   return result;
 }
@@ -547,10 +554,10 @@ gst_bus_timed_pop_filtered (GstBus * bus, GstClockTime timeout,
   while (TRUE) {
     gint ret;
 
-    GST_LOG_OBJECT (bus, "have %d messages",
-        gst_atomic_queue_length (bus->priv->queue));
+    GST_LOG_OBJECT (bus, "have %" G_GSIZE_FORMAT " messages",
+        gst_vec_deque_get_length (bus->priv->queue));
 
-    while ((message = gst_atomic_queue_pop (bus->priv->queue))) {
+    while ((message = gst_vec_deque_pop_head (bus->priv->queue))) {
       if (bus->priv->poll) {
         while (!gst_poll_read_control (bus->priv->poll)) {
           if (errno == EWOULDBLOCK) {
@@ -710,7 +717,7 @@ gst_bus_peek (GstBus * bus)
   g_return_val_if_fail (GST_IS_BUS (bus), NULL);
 
   g_mutex_lock (&bus->priv->queue_lock);
-  message = gst_atomic_queue_peek (bus->priv->queue);
+  message = gst_vec_deque_peek_head (bus->priv->queue);
   if (message)
     gst_message_ref (message);
   g_mutex_unlock (&bus->priv->queue_lock);
diff --git a/gst/gstcaps.c b/gst/gstcaps.c
index 373e2b4..19861da 100644
--- a/gst/gstcaps.c
+++ b/gst/gstcaps.c
@@ -68,6 +68,7 @@
 
 #define GST_DISABLE_MINIOBJECT_INLINE_FUNCTIONS
 #include "gst_private.h"
+#include "gstidstr-private.h"
 #include <gst/gst.h>
 #include <gobject/gvaluecollector.h>
 
@@ -284,6 +285,42 @@ gst_caps_new_any (void)
   return caps;
 }
 
+/**
+ * gst_caps_new_id_str_empty_simple:
+ * @media_type: the media type of the structure
+ *
+ * Creates a new #GstCaps that contains one #GstStructure with name
+ * @media_type.
+ *
+ * Returns: (transfer full): the new #GstCaps
+ *
+ * Since: 1.26
+ */
+GstCaps *
+gst_caps_new_id_str_empty_simple (const GstIdStr * media_type)
+{
+  GstCaps *caps;
+  GstStructure *structure;
+
+  caps = gst_caps_new_empty ();
+  if (gst_id_str_is_equal_to_str (media_type, "ANY")) {
+    g_warning
+        ("media_type should not be ANY. Please consider using `gst_caps_new_any` or `gst_caps_from_string`.");
+  }
+  if (gst_id_str_get_len (media_type) == 0
+      || gst_id_str_is_equal_to_str (media_type, "EMPTY")
+      || gst_id_str_is_equal_to_str (media_type, "NONE")) {
+    g_warning
+        ("media_type should not be `%s`. Please consider using `gst_caps_new_empty` or `gst_caps_from_string`.",
+        gst_id_str_as_str (media_type));
+  }
+  structure = gst_structure_new_id_str_empty (media_type);
+  if (structure)
+    gst_caps_append_structure_unchecked (caps, structure, NULL);
+
+  return caps;
+}
+
 /**
  * gst_caps_new_empty_simple:
  * @media_type: the media type of the structure
@@ -317,6 +354,80 @@ gst_caps_new_empty_simple (const char *media_type)
   return caps;
 }
 
+/**
+ * gst_caps_new_static_str_empty_simple:
+ * @media_type: the media type of the structure
+ *
+ * Creates a new #GstCaps that contains one #GstStructure with name
+ * @media_type.
+ *
+ * @media_type needs to be valid for the remaining lifetime of the process, e.g.
+ * has to be a static string.
+ *
+ * Returns: (transfer full): the new #GstCaps
+ *
+ * Since: 1.26
+ */
+GstCaps *
+gst_caps_new_static_str_empty_simple (const char *media_type)
+{
+  GstCaps *caps;
+  GstStructure *structure;
+
+  caps = gst_caps_new_empty ();
+  if (strcmp ("ANY", media_type) == 0) {
+    g_warning
+        ("media_type should not be ANY. Please consider using `gst_caps_new_any` or `gst_caps_from_string`.");
+  }
+  if (strcmp ("", media_type) == 0 || strcmp ("EMPTY", media_type) == 0
+      || strcmp ("NONE", media_type) == 0) {
+    g_warning
+        ("media_type should not be `%s`. Please consider using `gst_caps_new_empty` or `gst_caps_from_string`.",
+        media_type);
+  }
+  structure = gst_structure_new_static_str_empty (media_type);
+  if (structure)
+    gst_caps_append_structure_unchecked (caps, structure, NULL);
+
+  return caps;
+}
+
+/**
+ * gst_caps_new_id_str_simple:
+ * @media_type: the media type of the structure
+ * @fieldname: first field to set
+ * @...: additional arguments
+ *
+ * Creates a new #GstCaps that contains one #GstStructure.  The
+ * structure is defined by the arguments, which have the same format
+ * as gst_structure_new().
+ *
+ * Returns: (transfer full): the new #GstCaps
+ *
+ * Since: 1.26
+ */
+GstCaps *
+gst_caps_new_id_str_simple (const GstIdStr * media_type,
+    const GstIdStr * fieldname, ...)
+{
+  GstCaps *caps;
+  GstStructure *structure;
+  va_list var_args;
+
+  caps = gst_caps_new_empty ();
+
+  va_start (var_args, fieldname);
+  structure = gst_structure_new_id_str_valist (media_type, fieldname, var_args);
+  va_end (var_args);
+
+  if (structure)
+    gst_caps_append_structure_unchecked (caps, structure, NULL);
+  else
+    gst_caps_replace (&caps, NULL);
+
+  return caps;
+}
+
 /**
  * gst_caps_new_simple:
  * @media_type: the media type of the structure
@@ -350,6 +461,46 @@ gst_caps_new_simple (const char *media_type, const char *fieldname, ...)
   return caps;
 }
 
+/**
+ * gst_caps_new_static_str_simple:
+ * @media_type: the media type of the structure
+ * @fieldname: first field to set
+ * @...: additional arguments
+ *
+ * Creates a new #GstCaps that contains one #GstStructure.  The
+ * structure is defined by the arguments, which have the same format
+ * as gst_structure_new().
+ *
+ * @media_type, @fieldname and all other fieldnames need to be valid for the
+ * remaining lifetime of the process, e.g. have to be static strings.
+ *
+ * Returns: (transfer full): the new #GstCaps
+ *
+ * Since: 1.26
+ */
+GstCaps *
+gst_caps_new_static_str_simple (const char *media_type, const char *fieldname,
+    ...)
+{
+  GstCaps *caps;
+  GstStructure *structure;
+  va_list var_args;
+
+  caps = gst_caps_new_empty ();
+
+  va_start (var_args, fieldname);
+  structure =
+      gst_structure_new_static_str_valist (media_type, fieldname, var_args);
+  va_end (var_args);
+
+  if (structure)
+    gst_caps_append_structure_unchecked (caps, structure, NULL);
+  else
+    gst_caps_replace (&caps, NULL);
+
+  return caps;
+}
+
 /**
  * gst_caps_new_full:
  * @struct1: the first structure to add
@@ -1092,6 +1243,36 @@ gst_caps_truncate (GstCaps * caps)
   return caps;
 }
 
+/**
+ * gst_caps_id_str_set_value:
+ * @caps: a writable caps
+ * @field: name of the field to set
+ * @value: value to set the field to
+ *
+ * Sets the given @field on all structures of @caps to the given @value.
+ * This is a convenience function for calling gst_structure_set_value() on
+ * all structures of @caps.
+ *
+ * Since: 1.26
+ **/
+void
+gst_caps_id_str_set_value (GstCaps * caps, const GstIdStr * field,
+    const GValue * value)
+{
+  guint i, len;
+
+  g_return_if_fail (GST_IS_CAPS (caps));
+  g_return_if_fail (IS_WRITABLE (caps));
+  g_return_if_fail (field != NULL);
+  g_return_if_fail (G_IS_VALUE (value));
+
+  len = GST_CAPS_LEN (caps);
+  for (i = 0; i < len; i++) {
+    GstStructure *structure = gst_caps_get_structure_unchecked (caps, i);
+    gst_structure_id_str_set_value (structure, field, value);
+  }
+}
+
 /**
  * gst_caps_set_value:
  * @caps: a writable caps
@@ -1119,6 +1300,80 @@ gst_caps_set_value (GstCaps * caps, const char *field, const GValue * value)
   }
 }
 
+/**
+ * gst_caps_set_value_static_str:
+ * @caps: a writable caps
+ * @field: name of the field to set
+ * @value: value to set the field to
+ *
+ * Sets the given @field on all structures of @caps to the given @value.
+ * This is a convenience function for calling gst_structure_set_value() on
+ * all structures of @caps.
+ *
+ * @field needs to be valid for the remaining lifetime of the process, e.g.
+ * has to be a static string.
+ *
+ * Since: 1.26
+ **/
+void
+gst_caps_set_value_static_str (GstCaps * caps, const char *field,
+    const GValue * value)
+{
+  guint i, len;
+
+  g_return_if_fail (GST_IS_CAPS (caps));
+  g_return_if_fail (IS_WRITABLE (caps));
+  g_return_if_fail (field != NULL);
+  g_return_if_fail (G_IS_VALUE (value));
+
+  len = GST_CAPS_LEN (caps);
+  for (i = 0; i < len; i++) {
+    GstStructure *structure = gst_caps_get_structure_unchecked (caps, i);
+    gst_structure_set_value_static_str (structure, field, value);
+  }
+}
+
+/**
+ * gst_caps_id_str_set_simple_valist:
+ * @caps: the #GstCaps to set
+ * @field: first field to set
+ * @varargs: additional parameters
+ *
+ * Sets fields in a #GstCaps.  The arguments must be passed in the same
+ * manner as gst_structure_id_str_set(), and be %NULL-terminated.
+ *
+ * Since: 1.26
+ */
+void
+gst_caps_id_str_set_simple_valist (GstCaps * caps, const GstIdStr * field,
+    va_list varargs)
+{
+  GValue value = { 0, };
+
+  g_return_if_fail (GST_IS_CAPS (caps));
+  g_return_if_fail (IS_WRITABLE (caps));
+
+  while (field) {
+    GType type;
+    char *err;
+
+    type = va_arg (varargs, GType);
+
+    G_VALUE_COLLECT_INIT (&value, type, varargs, 0, &err);
+    if (G_UNLIKELY (err)) {
+      g_critical ("%s", err);
+      g_free (err);
+      return;
+    }
+
+    gst_caps_id_str_set_value (caps, field, &value);
+
+    g_value_unset (&value);
+
+    field = va_arg (varargs, const GstIdStr *);
+  }
+}
+
 /**
  * gst_caps_set_simple_valist:
  * @caps: the #GstCaps to set
@@ -1157,6 +1412,74 @@ gst_caps_set_simple_valist (GstCaps * caps, const char *field, va_list varargs)
   }
 }
 
+/**
+ * gst_caps_set_simple_static_str_valist:
+ * @caps: the #GstCaps to set
+ * @field: first field to set
+ * @varargs: additional parameters
+ *
+ * Sets fields in a #GstCaps.  The arguments must be passed in the same
+ * manner as gst_structure_set(), and be %NULL-terminated.
+ *
+ * @field and all other field names need to be valid for the remaining lifetime
+ * of the process, e.g. have to be static strings.
+ *
+ * Since: 1.26
+ */
+void
+gst_caps_set_simple_static_str_valist (GstCaps * caps, const char *field,
+    va_list varargs)
+{
+  GValue value = { 0, };
+
+  g_return_if_fail (GST_IS_CAPS (caps));
+  g_return_if_fail (IS_WRITABLE (caps));
+
+  while (field) {
+    GType type;
+    char *err;
+
+    type = va_arg (varargs, GType);
+
+    G_VALUE_COLLECT_INIT (&value, type, varargs, 0, &err);
+    if (G_UNLIKELY (err)) {
+      g_critical ("%s", err);
+      g_free (err);
+      return;
+    }
+
+    gst_caps_set_value_static_str (caps, field, &value);
+
+    g_value_unset (&value);
+
+    field = va_arg (varargs, const gchar *);
+  }
+}
+
+/**
+ * gst_caps_id_str_set_simple:
+ * @caps: the #GstCaps to set
+ * @field: first field to set
+ * @...: additional parameters
+ *
+ * Sets fields in a #GstCaps.  The arguments must be passed in the same
+ * manner as gst_structure_id_str_set(), and be %NULL-terminated.
+ *
+ * Since: 1.26
+ */
+void
+gst_caps_id_str_set_simple (GstCaps * caps, const GstIdStr * field, ...)
+{
+  va_list var_args;
+
+  g_return_if_fail (GST_IS_CAPS (caps));
+  g_return_if_fail (IS_WRITABLE (caps));
+
+  va_start (var_args, field);
+  gst_caps_id_str_set_simple_valist (caps, field, var_args);
+  va_end (var_args);
+}
+
 /**
  * gst_caps_set_simple:
  * @caps: the #GstCaps to set
@@ -1179,6 +1502,33 @@ gst_caps_set_simple (GstCaps * caps, const char *field, ...)
   va_end (var_args);
 }
 
+/**
+ * gst_caps_set_simple_static_str:
+ * @caps: the #GstCaps to set
+ * @field: first field to set
+ * @...: additional parameters
+ *
+ * Sets fields in a #GstCaps.  The arguments must be passed in the same
+ * manner as gst_structure_set(), and be %NULL-terminated.
+ *
+ * @field and all other field names need to be valid for the remaining lifetime
+ * of the process, e.g. have to be static strings.
+ *
+ * Since: 1.26
+ */
+void
+gst_caps_set_simple_static_str (GstCaps * caps, const char *field, ...)
+{
+  va_list var_args;
+
+  g_return_if_fail (GST_IS_CAPS (caps));
+  g_return_if_fail (IS_WRITABLE (caps));
+
+  va_start (var_args, field);
+  gst_caps_set_simple_static_str_valist (caps, field, var_args);
+  va_end (var_args);
+}
+
 /* tests */
 
 /**
@@ -1217,7 +1567,7 @@ gst_caps_is_empty (const GstCaps * caps)
 }
 
 static gboolean
-gst_caps_is_fixed_foreach (GQuark field_id, const GValue * value,
+gst_caps_is_fixed_foreach (const GstIdStr * field, const GValue * value,
     gpointer unused)
 {
   return gst_value_is_fixed (value);
@@ -1254,7 +1604,8 @@ gst_caps_is_fixed (const GstCaps * caps)
 
   structure = gst_caps_get_structure_unchecked (caps, 0);
 
-  return gst_structure_foreach (structure, gst_caps_is_fixed_foreach, NULL);
+  return gst_structure_foreach_id_str (structure, gst_caps_is_fixed_foreach,
+      NULL);
 }
 
 /**
@@ -1810,7 +2161,7 @@ typedef struct
 } SubtractionEntry;
 
 static gboolean
-gst_caps_structure_subtract_field (GQuark field_id, const GValue * value,
+gst_caps_structure_subtract_field (const GstIdStr * field, const GValue * value,
     gpointer user_data)
 {
   SubtractionEntry *e = user_data;
@@ -1818,7 +2169,7 @@ gst_caps_structure_subtract_field (GQuark field_id, const GValue * value,
   const GValue *other;
   GstStructure *structure;
 
-  other = gst_structure_id_get_value (e->subtract_from, field_id);
+  other = gst_structure_id_str_get_value (e->subtract_from, field);
 
   if (!other) {
     return FALSE;
@@ -1832,7 +2183,7 @@ gst_caps_structure_subtract_field (GQuark field_id, const GValue * value,
     return FALSE;
   } else {
     structure = gst_structure_copy (e->subtract_from);
-    gst_structure_id_take_value (structure, field_id, &subtraction);
+    gst_structure_id_str_take_value (structure, field, &subtraction);
     e->put_into = g_slist_prepend (e->put_into, structure);
     return TRUE;
   }
@@ -1847,7 +2198,7 @@ gst_caps_structure_subtract (GSList ** into, const GstStructure * minuend,
 
   e.subtract_from = minuend;
   e.put_into = NULL;
-  ret = gst_structure_foreach ((GstStructure *) subtrahend,
+  ret = gst_structure_foreach_id_str ((GstStructure *) subtrahend,
       gst_caps_structure_subtract_field, &e);
 
   if (ret) {
@@ -1927,7 +2278,7 @@ gst_caps_subtract (GstCaps * minuend, GstCaps * subtrahend)
       /* Same reason as above for ANY caps */
       g_return_val_if_fail (!gst_caps_features_is_any (min_f), NULL);
 
-      if (gst_structure_get_name_id (min) == gst_structure_get_name_id (sub) &&
+      if (gst_structure_has_name (min, gst_structure_get_name (sub)) &&
           gst_caps_features_is_equal (min_f, sub_f)) {
         GSList *list;
 
@@ -1972,7 +2323,8 @@ typedef struct _NormalizeForeach
 } NormalizeForeach;
 
 static gboolean
-gst_caps_normalize_foreach (GQuark field_id, const GValue * value, gpointer ptr)
+gst_caps_normalize_foreach (const GstIdStr * field, const GValue * value,
+    gpointer ptr)
 {
   NormalizeForeach *nf = (NormalizeForeach *) ptr;
   GValue val = { 0 };
@@ -1985,13 +2337,13 @@ gst_caps_normalize_foreach (GQuark field_id, const GValue * value, gpointer ptr)
       const GValue *v = gst_value_list_get_value (value, i);
       GstStructure *structure = gst_structure_copy (nf->structure);
 
-      gst_structure_id_set_value (structure, field_id, v);
+      gst_structure_id_str_set_value (structure, field, v);
       gst_caps_append_structure_unchecked (nf->caps, structure,
           gst_caps_features_copy_conditional (nf->features));
     }
 
     gst_value_init_and_copy (&val, gst_value_list_get_value (value, 0));
-    gst_structure_id_take_value (nf->structure, field_id, &val);
+    gst_structure_id_str_take_value (nf->structure, field, &val);
     return FALSE;
   }
 
@@ -2026,7 +2378,7 @@ gst_caps_normalize (GstCaps * caps)
   for (i = 0; i < gst_caps_get_size (nf.caps); i++) {
     nf.structure = gst_caps_get_structure_unchecked (nf.caps, i);
     nf.features = gst_caps_get_features_unchecked (nf.caps, i);
-    while (!gst_structure_foreach (nf.structure,
+    while (!gst_structure_foreach_id_str (nf.structure,
             gst_caps_normalize_foreach, &nf));
   }
 
@@ -2053,20 +2405,20 @@ gst_caps_compare_structures (gconstpointer one, gconstpointer two)
 
 typedef struct
 {
-  GQuark name;
+  GstIdStr name;
   GValue value;
   GstStructure *compare;
 } UnionField;
 
 static gboolean
-gst_caps_structure_figure_out_union (GQuark field_id, const GValue * value,
-    gpointer user_data)
+gst_caps_structure_figure_out_union (const GstIdStr * field,
+    const GValue * value, gpointer user_data)
 {
   UnionField *u = user_data;
-  const GValue *val = gst_structure_id_get_value (u->compare, field_id);
+  const GValue *val = gst_structure_id_str_get_value (u->compare, field);
 
   if (!val) {
-    if (u->name)
+    if (G_VALUE_TYPE (&u->value) != G_TYPE_INVALID)
       g_value_unset (&u->value);
     return FALSE;
   }
@@ -2074,12 +2426,12 @@ gst_caps_structure_figure_out_union (GQuark field_id, const GValue * value,
   if (gst_value_compare (val, value) == GST_VALUE_EQUAL)
     return TRUE;
 
-  if (u->name) {
+  if (G_VALUE_TYPE (&u->value) != G_TYPE_INVALID) {
     g_value_unset (&u->value);
     return FALSE;
   }
 
-  u->name = field_id;
+  gst_id_str_copy_into (&u->name, field);
   gst_value_union (&u->value, val, value);
 
   return TRUE;
@@ -2090,7 +2442,7 @@ gst_caps_structure_simplify (GstStructure ** result,
     GstStructure * simplify, GstStructure * compare)
 {
   GSList *list;
-  UnionField field = { 0, {0,}, NULL };
+  UnionField field = { GST_ID_STR_INIT, G_VALUE_INIT, NULL };
 
   /* try to subtract to get a real subset */
   if (gst_caps_structure_subtract (&list, simplify, compare)) {
@@ -2110,7 +2462,7 @@ gst_caps_structure_simplify (GstStructure ** result,
 
   /* try to union both structs */
   field.compare = compare;
-  if (gst_structure_foreach (simplify,
+  if (gst_structure_foreach_id_str (simplify,
           gst_caps_structure_figure_out_union, &field)) {
     gboolean ret = FALSE;
 
@@ -2118,7 +2470,7 @@ gst_caps_structure_simplify (GstStructure ** result,
      * but at most one field: field.name */
     if (G_IS_VALUE (&field.value)) {
       if (gst_structure_n_fields (simplify) == gst_structure_n_fields (compare)) {
-        gst_structure_id_take_value (compare, field.name, &field.value);
+        gst_structure_id_str_take_value (compare, &field.name, &field.value);
         *result = NULL;
         ret = TRUE;
       } else {
@@ -2204,8 +2556,7 @@ gst_caps_simplify (GstCaps * caps)
     compare_f = gst_caps_get_features_unchecked (caps, start);
     if (!compare_f)
       compare_f = GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY;
-    if (gst_structure_get_name_id (simplify) !=
-        gst_structure_get_name_id (compare) ||
+    if (!gst_structure_has_name (simplify, gst_structure_get_name (compare)) ||
         !gst_caps_features_is_equal (simplify_f, compare_f))
       start = i;
     for (j = start; j >= 0; j--) {
@@ -2215,9 +2566,8 @@ gst_caps_simplify (GstCaps * caps)
       compare_f = gst_caps_get_features_unchecked (caps, j);
       if (!compare_f)
         compare_f = GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY;
-      if (gst_structure_get_name_id (simplify) !=
-          gst_structure_get_name_id (compare) ||
-          !gst_caps_features_is_equal (simplify_f, compare_f)) {
+      if (!gst_structure_has_name (simplify, gst_structure_get_name (compare))
+          || !gst_caps_features_is_equal (simplify_f, compare_f)) {
         break;
       }
       if (gst_caps_structure_simplify (&result, simplify, compare)) {
@@ -2552,8 +2902,8 @@ gst_caps_transform_to_string (const GValue * src_value, GValue * dest_value)
 /**
  * gst_caps_foreach:
  * @caps: a #GstCaps
- * @func: (scope call): a function to call for each field
- * @user_data: (closure): private data
+ * @func: (scope call) (closure user_data): a function to call for each field
+ * @user_data: private data
  *
  * Calls the provided function once for each structure and caps feature in the
  * #GstCaps. The function must not modify the fields.
@@ -2593,8 +2943,8 @@ gst_caps_foreach (const GstCaps * caps, GstCapsForeachFunc func,
 /**
  * gst_caps_map_in_place:
  * @caps: a #GstCaps
- * @func: (scope call): a function to call for each field
- * @user_data: (closure): private data
+ * @func: (scope call) (closure user_data): a function to call for each field
+ * @user_data: private data
  *
  * Calls the provided function once for each structure and caps feature in the
  * #GstCaps. In contrast to gst_caps_foreach(), the function may modify but not
@@ -2641,8 +2991,8 @@ gst_caps_map_in_place (GstCaps * caps, GstCapsMapFunc func, gpointer user_data)
 /**
  * gst_caps_filter_and_map_in_place:
  * @caps: a #GstCaps
- * @func: (scope call): a function to call for each field
- * @user_data: (closure): private data
+ * @func: (scope call) (closure user_data): a function to call for each field
+ * @user_data: private data
  *
  * Calls the provided function once for each structure and caps feature in the
  * #GstCaps. In contrast to gst_caps_foreach(), the function may modify the
diff --git a/gst/gstcaps.h b/gst/gstcaps.h
index d031b6f..62448e3 100644
--- a/gst/gstcaps.h
+++ b/gst/gstcaps.h
@@ -366,14 +366,28 @@ GstCaps *         gst_caps_new_empty               (void);
 GST_API
 GstCaps *         gst_caps_new_any                 (void);
 
+GST_API
+GstCaps *         gst_caps_new_id_str_empty_simple (const GstIdStr *media_type) G_GNUC_WARN_UNUSED_RESULT;
+
 GST_API
 GstCaps *         gst_caps_new_empty_simple        (const char    *media_type) G_GNUC_WARN_UNUSED_RESULT;
 
+GST_API
+GstCaps *         gst_caps_new_static_str_empty_simple (const char    *media_type) G_GNUC_WARN_UNUSED_RESULT;
+
+GST_API
+GstCaps *         gst_caps_new_id_str_simple       (const GstIdStr *media_type,
+                                                    const GstIdStr *fieldname,
+                                                    ...) G_GNUC_NULL_TERMINATED G_GNUC_WARN_UNUSED_RESULT;
 GST_API
 GstCaps *         gst_caps_new_simple              (const char    *media_type,
                                                     const char    *fieldname,
                                                     ...) G_GNUC_NULL_TERMINATED G_GNUC_WARN_UNUSED_RESULT;
 GST_API
+GstCaps *         gst_caps_new_static_str_simple   (const char    *media_type,
+                                                    const char    *fieldname,
+                                                    ...) G_GNUC_NULL_TERMINATED G_GNUC_WARN_UNUSED_RESULT;
+GST_API
 GstCaps *         gst_caps_new_full                (GstStructure  *struct1,
                                                     ...) G_GNUC_NULL_TERMINATED G_GNUC_WARN_UNUSED_RESULT;
 GST_API
@@ -443,18 +457,40 @@ GstCaps *         gst_caps_copy_nth                (const GstCaps *caps, guint n
 GST_API
 GstCaps *         gst_caps_truncate                (GstCaps       *caps) G_GNUC_WARN_UNUSED_RESULT;
 
+GST_API
+void              gst_caps_id_str_set_value        (GstCaps        *caps,
+                                                    const GstIdStr *field,
+                                                    const GValue   *value);
 GST_API
 void              gst_caps_set_value               (GstCaps       *caps,
                                                     const char    *field,
                                                     const GValue  *value);
 GST_API
+void              gst_caps_set_value_static_str    (GstCaps       *caps,
+                                                    const char    *field,
+                                                    const GValue  *value);
+GST_API
+void              gst_caps_id_str_set_simple       (GstCaps        *caps,
+                                                    const GstIdStr *field, ...) G_GNUC_NULL_TERMINATED;
+GST_API
 void              gst_caps_set_simple              (GstCaps       *caps,
                                                     const char    *field, ...) G_GNUC_NULL_TERMINATED;
 GST_API
+void              gst_caps_set_simple_static_str   (GstCaps       *caps,
+                                                    const char    *field, ...) G_GNUC_NULL_TERMINATED;
+GST_API
+void              gst_caps_id_str_set_simple_valist(GstCaps        *caps,
+                                                    const GstIdStr *field,
+                                                    va_list         varargs);
+GST_API
 void              gst_caps_set_simple_valist       (GstCaps       *caps,
                                                     const char    *field,
                                                     va_list        varargs);
 GST_API
+void              gst_caps_set_simple_static_str_valist (GstCaps       *caps,
+                                                         const char    *field,
+                                                         va_list        varargs);
+GST_API
 gboolean          gst_caps_foreach                 (const GstCaps       *caps,
                                                     GstCapsForeachFunc   func,
                                                     gpointer             user_data);
diff --git a/gst/gstcapsfeatures.c b/gst/gstcapsfeatures.c
index d81169c..2c9ab59 100644
--- a/gst/gstcapsfeatures.c
+++ b/gst/gstcapsfeatures.c
@@ -50,9 +50,13 @@
 #include "config.h"
 #endif
 
+/* FIXME: For deprecated GstCapsFeatures API usage */
+#define GLIB_DISABLE_DEPRECATION_WARNINGS
+
 #include <string.h>
 #include "gst_private.h"
 #include "gstcapsfeatures.h"
+#include "gstidstr-private.h"
 #include <gst/gst.h>
 
 GST_DEBUG_CATEGORY_STATIC (gst_caps_features_debug);
@@ -70,7 +74,7 @@ GType _gst_caps_features_type = 0;
 static gint static_caps_features_parent_refcount = G_MAXINT;
 GstCapsFeatures *_gst_caps_features_any = NULL;
 GstCapsFeatures *_gst_caps_features_memory_system_memory = NULL;
-static GQuark _gst_caps_feature_memory_system_memory = 0;
+static GstIdStr _gst_caps_feature_memory_system_memory = GST_ID_STR_INIT;
 
 G_DEFINE_BOXED_TYPE (GstCapsFeatures, gst_caps_features,
     gst_caps_features_copy, gst_caps_features_free);
@@ -90,8 +94,6 @@ _priv_gst_caps_features_initialize (void)
       "GstCapsFeatures debug");
 
   _gst_caps_features_type = gst_caps_features_get_type ();
-  _gst_caps_feature_memory_system_memory =
-      g_quark_from_static_string (GST_CAPS_FEATURE_MEMORY_SYSTEM_MEMORY);
 
   g_value_register_transform_func (_gst_caps_features_type, G_TYPE_STRING,
       gst_caps_features_transform_to_string);
@@ -99,8 +101,11 @@ _priv_gst_caps_features_initialize (void)
   _gst_caps_features_any = gst_caps_features_new_any ();
   gst_caps_features_set_parent_refcount (_gst_caps_features_any,
       &static_caps_features_parent_refcount);
+  gst_id_str_set_static_str (&_gst_caps_feature_memory_system_memory,
+      GST_CAPS_FEATURE_MEMORY_SYSTEM_MEMORY);
   _gst_caps_features_memory_system_memory =
-      gst_caps_features_new_id (_gst_caps_feature_memory_system_memory, 0);
+      gst_caps_features_new_id_str (&_gst_caps_feature_memory_system_memory,
+      NULL);
   gst_caps_features_set_parent_refcount
       (_gst_caps_features_memory_system_memory,
       &static_caps_features_parent_refcount);
@@ -116,6 +121,7 @@ _priv_gst_caps_features_cleanup (void)
       (_gst_caps_features_memory_system_memory, NULL);
   gst_caps_features_free (_gst_caps_features_memory_system_memory);
   _gst_caps_features_memory_system_memory = NULL;
+  gst_id_str_clear (&_gst_caps_feature_memory_system_memory);
 }
 
 /**
@@ -183,7 +189,8 @@ gst_caps_features_new_empty (void)
   features = g_new (GstCapsFeatures, 1);
   features->type = _gst_caps_features_type;
   features->parent_refcount = NULL;
-  features->array = g_array_new (FALSE, FALSE, sizeof (GQuark));
+  features->array = g_array_new (FALSE, FALSE, sizeof (GstIdStr));
+  g_array_set_clear_func (features->array, (GDestroyNotify) gst_id_str_clear);
   features->is_any = FALSE;
 
   GST_TRACE ("created caps features %p", features);
@@ -234,6 +241,30 @@ gst_caps_features_new_single (const gchar * feature)
   return features;
 }
 
+/**
+ * gst_caps_features_new_single_static_str:
+ * @feature: The feature
+ *
+ * Creates a new #GstCapsFeatures with a single feature.
+ *
+ * @feature needs to be valid for the remaining lifetime of the process, e.g. has
+ * to be a static string.
+ *
+ * Returns: (transfer full): a new #GstCapsFeatures
+ *
+ * Since: 1.26
+ */
+GstCapsFeatures *
+gst_caps_features_new_single_static_str (const gchar * feature)
+{
+  GstCapsFeatures *features;
+  g_return_val_if_fail (feature != NULL, NULL);
+
+  features = gst_caps_features_new_empty ();
+  gst_caps_features_add_static_str (features, feature);
+  return features;
+}
+
 /**
  * gst_caps_features_new:
  * @feature1: name of first feature to set
@@ -289,6 +320,68 @@ gst_caps_features_new_valist (const gchar * feature1, va_list varargs)
   return features;
 }
 
+/**
+ * gst_caps_features_new_static_str:
+ * @feature1: name of first feature to set
+ * @...: additional features
+ *
+ * Creates a new #GstCapsFeatures with the given features.
+ * The last argument must be %NULL.
+ *
+ * @feature1 and all other features need to be valid for the remaining lifetime
+ * of the process, e.g. have to be a static string.
+ *
+ * Returns: (transfer full): a new, empty #GstCapsFeatures
+ *
+ * Since: 1.26
+ */
+GstCapsFeatures *
+gst_caps_features_new_static_str (const gchar * feature1, ...)
+{
+  GstCapsFeatures *features;
+  va_list varargs;
+
+  g_return_val_if_fail (feature1 != NULL, NULL);
+
+  va_start (varargs, feature1);
+  features = gst_caps_features_new_static_str_valist (feature1, varargs);
+  va_end (varargs);
+
+  return features;
+}
+
+/**
+ * gst_caps_features_new_static_str_valist:
+ * @feature1: name of first feature to set
+ * @varargs: variable argument list
+ *
+ * Creates a new #GstCapsFeatures with the given features.
+ *
+ * @feature1 and all other features need to be valid for the remaining lifetime
+ * of the process, e.g. have to be a static string.
+ *
+ * Returns: (transfer full): a new, empty #GstCapsFeatures
+ *
+ * Since: 1.26
+ */
+GstCapsFeatures *
+gst_caps_features_new_static_str_valist (const gchar * feature1,
+    va_list varargs)
+{
+  GstCapsFeatures *features;
+
+  g_return_val_if_fail (feature1 != NULL, NULL);
+
+  features = gst_caps_features_new_empty ();
+
+  while (feature1) {
+    gst_caps_features_add_static_str (features, feature1);
+    feature1 = va_arg (varargs, const gchar *);
+  }
+
+  return features;
+}
+
 /**
  * gst_caps_features_new_id:
  * @feature1: name of first feature to set
@@ -300,6 +393,8 @@ gst_caps_features_new_valist (const gchar * feature1, va_list varargs)
  * Returns: (transfer full): a new, empty #GstCapsFeatures
  *
  * Since: 1.2
+ *
+ * Deprecated: 1.26: Use gst_caps_features_new_id_str().
  */
 GstCapsFeatures *
 gst_caps_features_new_id (GQuark feature1, ...)
@@ -310,7 +405,9 @@ gst_caps_features_new_id (GQuark feature1, ...)
   g_return_val_if_fail (feature1 != 0, NULL);
 
   va_start (varargs, feature1);
+  G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
   features = gst_caps_features_new_id_valist (feature1, varargs);
+  G_GNUC_END_IGNORE_DEPRECATIONS;
   va_end (varargs);
 
   return features;
@@ -326,6 +423,8 @@ gst_caps_features_new_id (GQuark feature1, ...)
  * Returns: (transfer full): a new, empty #GstCapsFeatures
  *
  * Since: 1.2
+ *
+ * Deprecated: 1.26: Use gst_caps_features_new_id_str_valist().
  */
 GstCapsFeatures *
 gst_caps_features_new_id_valist (GQuark feature1, va_list varargs)
@@ -337,13 +436,70 @@ gst_caps_features_new_id_valist (GQuark feature1, va_list varargs)
   features = gst_caps_features_new_empty ();
 
   while (feature1) {
+    G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
     gst_caps_features_add_id (features, feature1);
+    G_GNUC_END_IGNORE_DEPRECATIONS;
     feature1 = va_arg (varargs, GQuark);
   }
 
   return features;
 }
 
+/**
+ * gst_caps_features_new_id_str:
+ * @feature1: name of first feature to set
+ * @...: additional features
+ *
+ * Creates a new #GstCapsFeatures with the given features.
+ * The last argument must be 0.
+ *
+ * Returns: (transfer full): a new, empty #GstCapsFeatures
+ *
+ * Since: 1.26
+ */
+GstCapsFeatures *
+gst_caps_features_new_id_str (const GstIdStr * feature1, ...)
+{
+  GstCapsFeatures *features;
+  va_list varargs;
+
+  g_return_val_if_fail (feature1 != NULL, NULL);
+
+  va_start (varargs, feature1);
+  features = gst_caps_features_new_id_str_valist (feature1, varargs);
+  va_end (varargs);
+
+  return features;
+}
+
+/**
+ * gst_caps_features_new_id_str_valist:
+ * @feature1: name of first feature to set
+ * @varargs: variable argument list
+ *
+ * Creates a new #GstCapsFeatures with the given features.
+ *
+ * Returns: (transfer full): a new, empty #GstCapsFeatures
+ *
+ * Since: 1.26
+ */
+GstCapsFeatures *
+gst_caps_features_new_id_str_valist (const GstIdStr * feature1, va_list varargs)
+{
+  GstCapsFeatures *features;
+
+  g_return_val_if_fail (feature1 != NULL, NULL);
+
+  features = gst_caps_features_new_empty ();
+
+  while (feature1) {
+    gst_caps_features_add_id_str (features, feature1);
+    feature1 = va_arg (varargs, const GstIdStr *);
+  }
+
+  return features;
+}
+
 /**
  * gst_caps_features_set_parent_refcount:
  * @features: a #GstCapsFeatures
@@ -404,7 +560,8 @@ gst_caps_features_copy (const GstCapsFeatures * features)
   copy = gst_caps_features_new_empty ();
   n = gst_caps_features_get_size (features);
   for (i = 0; i < n; i++)
-    gst_caps_features_add_id (copy, gst_caps_features_get_nth_id (features, i));
+    gst_caps_features_add_id_str (copy,
+        gst_caps_features_get_nth_id_str (features, i));
   copy->is_any = features->is_any;
 
   return copy;
@@ -481,9 +638,9 @@ priv_gst_caps_features_append_to_gstring (const GstCapsFeatures * features,
 
   n = features->array->len;
   for (i = 0; i < n; i++) {
-    GQuark *quark = &g_array_index (features->array, GQuark, i);
+    const GstIdStr *feature = &g_array_index (features->array, GstIdStr, i);
 
-    g_string_append (s, g_quark_to_string (*quark));
+    g_string_append (s, gst_id_str_as_str (feature));
     if (i + 1 < n)
       g_string_append (s, ", ");
   }
@@ -611,15 +768,15 @@ const gchar *
 gst_caps_features_get_nth (const GstCapsFeatures * features, guint i)
 {
   const gchar *feature;
-  GQuark quark;
+  const GstIdStr *feature_str;
 
   g_return_val_if_fail (features != NULL, NULL);
 
-  quark = gst_caps_features_get_nth_id (features, i);
-  if (!quark)
+  feature_str = gst_caps_features_get_nth_id_str (features, i);
+  if (!feature_str)
     return NULL;
 
-  feature = g_quark_to_string (quark);
+  feature = gst_id_str_as_str (feature_str);
   return feature;
 }
 
@@ -633,18 +790,46 @@ gst_caps_features_get_nth (const GstCapsFeatures * features, guint i)
  * Returns: The @i-th feature of @features.
  *
  * Since: 1.2
+ *
+ * Deprecated: 1.26: Use gst_caps_features_get_nth_id_str().
  */
 GQuark
 gst_caps_features_get_nth_id (const GstCapsFeatures * features, guint i)
 {
-  GQuark *quark;
+  GQuark quark;
+  const GstIdStr *feature_str;
 
   g_return_val_if_fail (features != NULL, 0);
   g_return_val_if_fail (i < features->array->len, 0);
 
-  quark = &g_array_index (features->array, GQuark, i);
+  feature_str = gst_caps_features_get_nth_id_str (features, i);
 
-  return *quark;
+  quark = g_quark_from_string (gst_id_str_as_str (feature_str));
+  return quark;
+}
+
+/**
+ * gst_caps_features_get_nth_id_str:
+ * @features: a #GstCapsFeatures.
+ * @i: index of the feature
+ *
+ * Returns the @i-th feature of @features.
+ *
+ * Returns: The @i-th feature of @features.
+ *
+ * Since: 1.26
+ */
+const GstIdStr *
+gst_caps_features_get_nth_id_str (const GstCapsFeatures * features, guint i)
+{
+  const GstIdStr *feature;
+
+  g_return_val_if_fail (features != NULL, 0);
+  g_return_val_if_fail (i < features->array->len, 0);
+
+  feature = &g_array_index (features->array, GstIdStr, i);
+
+  return feature;
 }
 
 /**
@@ -662,11 +847,18 @@ gboolean
 gst_caps_features_contains (const GstCapsFeatures * features,
     const gchar * feature)
 {
+  GstIdStr s = GST_ID_STR_INIT;
+  gboolean res;
+
   g_return_val_if_fail (features != NULL, FALSE);
   g_return_val_if_fail (feature != NULL, FALSE);
 
-  return gst_caps_features_contains_id (features,
-      g_quark_from_string (feature));
+  // Not technically correct but the string is never leaving this scope and is never copied
+  gst_id_str_set_static_str (&s, feature);
+  res = gst_caps_features_contains_id_str (features, &s);
+  gst_id_str_clear (&s);
+
+  return res;
 }
 
 /**
@@ -679,24 +871,54 @@ gst_caps_features_contains (const GstCapsFeatures * features,
  * Returns: %TRUE if @features contains @feature.
  *
  * Since: 1.2
+ *
+ * Deprecated: 1.26: Use gst_caps_features_contains_id_str().
  */
 gboolean
 gst_caps_features_contains_id (const GstCapsFeatures * features, GQuark feature)
 {
-  guint i, n;
+  GstIdStr s = GST_ID_STR_INIT;
 
   g_return_val_if_fail (features != NULL, FALSE);
   g_return_val_if_fail (feature != 0, FALSE);
 
+  gst_id_str_set_static_str (&s, g_quark_to_string (feature));
+
+  return gst_caps_features_contains_id_str (features, &s);
+}
+
+/**
+ * gst_caps_features_contains_id_str:
+ * @features: a #GstCapsFeatures.
+ * @feature: a feature
+ *
+ * Checks if @features contains @feature.
+ *
+ * Returns: %TRUE if @features contains @feature.
+ *
+ * Since: 1.26
+ */
+gboolean
+gst_caps_features_contains_id_str (const GstCapsFeatures * features,
+    const GstIdStr * feature)
+{
+  guint i, n;
+
+  g_return_val_if_fail (features != NULL, FALSE);
+  g_return_val_if_fail (feature != NULL, FALSE);
+
   if (features->is_any)
     return TRUE;
 
   n = features->array->len;
-  if (n == 0)
-    return feature == _gst_caps_feature_memory_system_memory;
+  if (n == 0) {
+    return gst_id_str_is_equal (feature,
+        &_gst_caps_feature_memory_system_memory);
+  }
 
   for (i = 0; i < n; i++) {
-    if (gst_caps_features_get_nth_id (features, i) == feature)
+    if (gst_id_str_is_equal (gst_caps_features_get_nth_id_str (features, i),
+            feature))
       return TRUE;
   }
 
@@ -730,12 +952,12 @@ gst_caps_features_is_equal (const GstCapsFeatures * features1,
   if (features1->array->len == 0 && features2->array->len == 0)
     return TRUE;
   if (features1->array->len == 0 && features2->array->len == 1
-      && gst_caps_features_contains_id (features2,
-          _gst_caps_feature_memory_system_memory))
+      && gst_caps_features_contains_id_str (features2,
+          &_gst_caps_feature_memory_system_memory))
     return TRUE;
   if (features2->array->len == 0 && features1->array->len == 1
-      && gst_caps_features_contains_id (features1,
-          _gst_caps_feature_memory_system_memory))
+      && gst_caps_features_contains_id_str (features1,
+          &_gst_caps_feature_memory_system_memory))
     return TRUE;
 
   if (features1->array->len != features2->array->len)
@@ -743,8 +965,8 @@ gst_caps_features_is_equal (const GstCapsFeatures * features1,
 
   n = features1->array->len;
   for (i = 0; i < n; i++)
-    if (!gst_caps_features_contains_id (features2,
-            gst_caps_features_get_nth_id (features1, i)))
+    if (!gst_caps_features_contains_id_str (features2,
+            gst_caps_features_get_nth_id_str (features1, i)))
       return FALSE;
 
   return TRUE;
@@ -768,6 +990,30 @@ gst_caps_features_is_any (const GstCapsFeatures * features)
   return features->is_any;
 }
 
+// Takes ownership of feature
+static void
+gst_caps_features_add_id_str_internal (GstCapsFeatures * features,
+    GstIdStr * feature)
+{
+  if (!gst_caps_feature_name_is_valid (gst_id_str_as_str (feature))) {
+    g_warning ("Invalid caps feature name: %s", gst_id_str_as_str (feature));
+    gst_id_str_clear (feature);
+    return;
+  }
+
+  /* If features is empty it will contain sysmem, however
+   * we want to add it explicitly if it is attempted to be
+   * added as first features
+   */
+  if (features->array->len > 0
+      && gst_caps_features_contains_id_str (features, feature)) {
+    gst_id_str_clear (feature);
+    return;
+  }
+
+  g_array_append_val (features->array, *feature);
+}
+
 /**
  * gst_caps_features_add:
  * @features: a #GstCapsFeatures.
@@ -780,12 +1026,44 @@ gst_caps_features_is_any (const GstCapsFeatures * features)
 void
 gst_caps_features_add (GstCapsFeatures * features, const gchar * feature)
 {
+  GstIdStr s = GST_ID_STR_INIT;
+
   g_return_if_fail (features != NULL);
   g_return_if_fail (IS_MUTABLE (features));
   g_return_if_fail (feature != NULL);
   g_return_if_fail (!features->is_any);
 
-  gst_caps_features_add_id (features, g_quark_from_string (feature));
+  gst_id_str_set (&s, feature);
+
+  gst_caps_features_add_id_str_internal (features, &s);
+}
+
+/**
+ * gst_caps_features_add_static_str:
+ * @features: a #GstCapsFeatures.
+ * @feature: a feature.
+ *
+ * Adds @feature to @features.
+ *
+ * @feature needs to be valid for the remaining lifetime of the process, e.g. has
+ * to be a static string.
+ *
+ * Since: 1.26
+ */
+void
+gst_caps_features_add_static_str (GstCapsFeatures * features,
+    const gchar * feature)
+{
+  GstIdStr s = GST_ID_STR_INIT;
+
+  g_return_if_fail (features != NULL);
+  g_return_if_fail (IS_MUTABLE (features));
+  g_return_if_fail (feature != NULL);
+  g_return_if_fail (!features->is_any);
+
+  gst_id_str_set_static_str (&s, feature);
+
+  gst_caps_features_add_id_str_internal (features, &s);
 }
 
 /**
@@ -796,29 +1074,47 @@ gst_caps_features_add (GstCapsFeatures * features, const gchar * feature)
  * Adds @feature to @features.
  *
  * Since: 1.2
+ *
+ * Deprecated: 1.26: Use gst_caps_features_add_id_str().
  */
 void
 gst_caps_features_add_id (GstCapsFeatures * features, GQuark feature)
 {
+  GstIdStr s = GST_ID_STR_INIT;
+
   g_return_if_fail (features != NULL);
   g_return_if_fail (IS_MUTABLE (features));
   g_return_if_fail (feature != 0);
   g_return_if_fail (!features->is_any);
 
-  if (!gst_caps_feature_name_is_valid (g_quark_to_string (feature))) {
-    g_warning ("Invalid caps feature name: %s", g_quark_to_string (feature));
-    return;
-  }
+  gst_id_str_set_static_str (&s, g_quark_to_string (feature));
 
-  /* If features is empty it will contain sysmem, however
-   * we want to add it explicitly if it is attempted to be
-   * added as first features
-   */
-  if (features->array->len > 0
-      && gst_caps_features_contains_id (features, feature))
-    return;
+  gst_caps_features_add_id_str_internal (features, &s);
+}
 
-  g_array_append_val (features->array, feature);
+/**
+ * gst_caps_features_add_id_str:
+ * @features: a #GstCapsFeatures.
+ * @feature: a feature.
+ *
+ * Adds @feature to @features.
+ *
+ * Since: 1.26
+ */
+void
+gst_caps_features_add_id_str (GstCapsFeatures * features,
+    const GstIdStr * feature)
+{
+  GstIdStr s = GST_ID_STR_INIT;
+
+  g_return_if_fail (features != NULL);
+  g_return_if_fail (IS_MUTABLE (features));
+  g_return_if_fail (feature != NULL);
+  g_return_if_fail (!features->is_any);
+
+  gst_id_str_copy_into (&s, feature);
+
+  gst_caps_features_add_id_str_internal (features, &s);
 }
 
 /**
@@ -833,11 +1129,16 @@ gst_caps_features_add_id (GstCapsFeatures * features, GQuark feature)
 void
 gst_caps_features_remove (GstCapsFeatures * features, const gchar * feature)
 {
+  GstIdStr s = GST_ID_STR_INIT;
+
   g_return_if_fail (features != NULL);
   g_return_if_fail (IS_MUTABLE (features));
   g_return_if_fail (feature != NULL);
 
-  gst_caps_features_remove_id (features, g_quark_from_string (feature));
+  // Not technically correct but the string is never leaving this scope and is never copied
+  gst_id_str_set_static_str (&s, feature);
+  gst_caps_features_remove_id_str (features, &s);
+  gst_id_str_clear (&s);
 }
 
 /**
@@ -848,21 +1149,48 @@ gst_caps_features_remove (GstCapsFeatures * features, const gchar * feature)
  * Removes @feature from @features.
  *
  * Since: 1.2
+ *
+ * Deprecated: 1.26: Use gst_caps_features_remove_id_str().
  */
 void
 gst_caps_features_remove_id (GstCapsFeatures * features, GQuark feature)
 {
-  guint i, n;
+  GstIdStr s = GST_ID_STR_INIT;
+
 
   g_return_if_fail (features != NULL);
   g_return_if_fail (IS_MUTABLE (features));
   g_return_if_fail (feature != 0);
 
+  gst_id_str_set_static_str (&s, g_quark_to_string (feature));
+
+  gst_caps_features_remove_id_str (features, &s);
+}
+
+/**
+ * gst_caps_features_remove_id_str:
+ * @features: a #GstCapsFeatures.
+ * @feature: a feature.
+ *
+ * Removes @feature from @features.
+ *
+ * Since: 1.26
+ */
+void
+gst_caps_features_remove_id_str (GstCapsFeatures * features,
+    const GstIdStr * feature)
+{
+  guint i, n;
+
+  g_return_if_fail (features != NULL);
+  g_return_if_fail (IS_MUTABLE (features));
+  g_return_if_fail (feature != NULL);
+
   n = features->array->len;
   for (i = 0; i < n; i++) {
-    GQuark quark = gst_caps_features_get_nth_id (features, i);
+    const GstIdStr *f = gst_caps_features_get_nth_id_str (features, i);
 
-    if (quark == feature) {
+    if (gst_id_str_is_equal (f, feature)) {
       g_array_remove_index_fast (features->array, i);
       return;
     }
diff --git a/gst/gstcapsfeatures.h b/gst/gstcapsfeatures.h
index cdf7755..2d9806f 100644
--- a/gst/gstcapsfeatures.h
+++ b/gst/gstcapsfeatures.h
@@ -23,6 +23,7 @@
 
 #include <gst/gstconfig.h>
 #include <gst/glib-compat.h>
+#include <gst/gstidstr.h>
 #include <glib-object.h>
 #include <glib.h>
 
@@ -60,18 +61,33 @@ GstCapsFeatures * gst_caps_features_new_any (void);
 GST_API
 GstCapsFeatures * gst_caps_features_new_single (const gchar *feature) G_GNUC_MALLOC;
 
+GST_API
+GstCapsFeatures * gst_caps_features_new_single_static_str (const gchar *feature) G_GNUC_MALLOC;
+
 GST_API
 GstCapsFeatures * gst_caps_features_new (const gchar *feature1, ...) G_GNUC_NULL_TERMINATED;
 
+GST_API
+GstCapsFeatures * gst_caps_features_new_static_str (const gchar *feature1, ...) G_GNUC_NULL_TERMINATED;
+
 GST_API
 GstCapsFeatures * gst_caps_features_new_valist (const gchar *feature1, va_list varargs);
 
 GST_API
+GstCapsFeatures * gst_caps_features_new_static_str_valist (const gchar *feature1, va_list varargs);
+
+GST_DEPRECATED_FOR(gst_caps_features_new_id_str)
 GstCapsFeatures * gst_caps_features_new_id (GQuark feature1, ...);
 
-GST_API
+GST_DEPRECATED_FOR(gst_caps_features_new_id_str_valist)
 GstCapsFeatures * gst_caps_features_new_id_valist (GQuark feature1, va_list varargs);
 
+GST_API
+GstCapsFeatures * gst_caps_features_new_id_str (const GstIdStr * feature1, ...);
+
+GST_API
+GstCapsFeatures * gst_caps_features_new_id_str_valist (const GstIdStr * feature1, va_list varargs);
+
 GST_API
 gboolean          gst_caps_features_set_parent_refcount  (GstCapsFeatures *features, gint * refcount);
 
@@ -93,15 +109,21 @@ guint             gst_caps_features_get_size (const GstCapsFeatures * features);
 GST_API
 const gchar *     gst_caps_features_get_nth (const GstCapsFeatures * features, guint i);
 
-GST_API
+GST_DEPRECATED_FOR(gst_caps_features_get_nth_id_str)
 GQuark            gst_caps_features_get_nth_id (const GstCapsFeatures * features, guint i);
 
 GST_API
-gboolean          gst_caps_features_contains (const GstCapsFeatures * features, const gchar * feature);
+const GstIdStr *  gst_caps_features_get_nth_id_str (const GstCapsFeatures * features, guint i);
 
 GST_API
+gboolean          gst_caps_features_contains (const GstCapsFeatures * features, const gchar * feature);
+
+GST_DEPRECATED_FOR(gst_caps_features_contains_id_str)
 gboolean          gst_caps_features_contains_id (const GstCapsFeatures * features, GQuark feature);
 
+GST_API
+gboolean          gst_caps_features_contains_id_str (const GstCapsFeatures * features, const GstIdStr * feature);
+
 GST_API
 gboolean          gst_caps_features_is_equal (const GstCapsFeatures * features1, const GstCapsFeatures * features2);
 
@@ -112,14 +134,23 @@ GST_API
 void              gst_caps_features_add (GstCapsFeatures * features, const gchar * feature);
 
 GST_API
-void              gst_caps_features_add_id ( GstCapsFeatures * features, GQuark feature);
+void              gst_caps_features_add_static_str (GstCapsFeatures * features, const gchar * feature);
+
+GST_DEPRECATED_FOR(gst_caps_features_add_id_str)
+void              gst_caps_features_add_id (GstCapsFeatures * features, GQuark feature);
 
 GST_API
-void              gst_caps_features_remove (GstCapsFeatures * features, const gchar * feature);
+void              gst_caps_features_add_id_str (GstCapsFeatures * features, const GstIdStr * feature);
 
 GST_API
+void              gst_caps_features_remove (GstCapsFeatures * features, const gchar * feature);
+
+GST_DEPRECATED_FOR(gst_caps_features_remove_id_str)
 void              gst_caps_features_remove_id (GstCapsFeatures * features, GQuark feature);
 
+GST_API
+void              gst_caps_features_remove_id_str (GstCapsFeatures * features, const GstIdStr * feature);
+
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstCapsFeatures, gst_caps_features_free)
 
 G_END_DECLS
diff --git a/gst/gstclock.c b/gst/gstclock.c
index ab8a4b0..d9ea717 100644
--- a/gst/gstclock.c
+++ b/gst/gstclock.c
@@ -499,7 +499,7 @@ gst_clock_id_get_time (GstClockID id)
 /**
  * gst_clock_id_wait:
  * @id: The #GstClockID to wait on
- * @jitter: (out) (allow-none): a pointer that will contain the jitter,
+ * @jitter: (out) (optional): a pointer that will contain the jitter,
  *     can be %NULL.
  *
  * Performs a blocking wait on @id.
@@ -883,7 +883,7 @@ gst_clock_get_resolution (GstClock * clock)
 /* FIXME 2.0: Remove clock parameter below */
 /**
  * gst_clock_adjust_with_calibration:
- * @clock: (allow-none): a #GstClock to use
+ * @clock: (nullable): a #GstClock to use
  * @internal_target: a clock time
  * @cinternal: a reference internal time
  * @cexternal: a reference external time
@@ -976,7 +976,7 @@ gst_clock_adjust_unlocked (GstClock * clock, GstClockTime internal)
 /* FIXME 2.0: Remove clock parameter below */
 /**
  * gst_clock_unadjust_with_calibration:
- * @clock: (allow-none): a #GstClock to use
+ * @clock: (nullable): a #GstClock to use
  * @external_target: a clock time
  * @cinternal: a reference internal time
  * @cexternal: a reference external time
@@ -1194,10 +1194,10 @@ gst_clock_set_calibration (GstClock * clock, GstClockTime internal, GstClockTime
 /**
  * gst_clock_get_calibration:
  * @clock: a #GstClock
- * @internal: (out) (allow-none): a location to store the internal time
- * @external: (out) (allow-none): a location to store the external time
- * @rate_num: (out) (allow-none): a location to store the rate numerator
- * @rate_denom: (out) (allow-none): a location to store the rate denominator
+ * @internal: (out) (optional): a location to store the internal time
+ * @external: (out) (optional): a location to store the external time
+ * @rate_num: (out) (optional): a location to store the rate numerator
+ * @rate_denom: (out) (optional): a location to store the rate denominator
  *
  * Gets the internal rate and reference time of @clock. See
  * gst_clock_set_calibration() for more information.
@@ -1262,7 +1262,7 @@ gst_clock_slave_callback (GstClock * master, GstClockTime time,
 /**
  * gst_clock_set_master:
  * @clock: a #GstClock
- * @master: (allow-none): a master #GstClock
+ * @master: (nullable): a master #GstClock
  *
  * Sets @master as the master clock for @clock. @clock will be automatically
  * calibrated so that gst_clock_get_time() reports the same time as the
@@ -1432,14 +1432,14 @@ gst_clock_id_uses_clock (GstClockID id, GstClock * clock)
 /**
  * gst_clock_add_observation:
  * @clock: a #GstClock
- * @slave: a time on the slave
- * @master: a time on the master
+ * @observation_internal: a time on the internal clock
+ * @observation_external: a time on the external clock
  * @r_squared: (out): a pointer to hold the result
  *
- * The time @master of the master clock and the time @slave of the slave
- * clock are added to the list of observations. If enough observations
- * are available, a linear regression algorithm is run on the
- * observations and @clock is recalibrated.
+ * The time @observation_external of the external or master clock and the time
+ * @observation_internal of the internal or slave clock are added to the list of
+ * observations. If enough observations are available, a linear regression
+ * algorithm is run on the observations and @clock is recalibrated.
  *
  * If this functions returns %TRUE, @r_squared will contain the
  * correlation coefficient of the interpolation. A value of 1.0
@@ -1451,13 +1451,13 @@ gst_clock_id_uses_clock (GstClockID id, GstClock * clock)
  * regression algorithm.
  */
 gboolean
-gst_clock_add_observation (GstClock * clock, GstClockTime slave,
-    GstClockTime master, gdouble * r_squared)
+gst_clock_add_observation (GstClock * clock, GstClockTime observation_internal,
+    GstClockTime observation_external, gdouble * r_squared)
 {
   GstClockTime m_num, m_denom, b, xbase;
 
-  if (!gst_clock_add_observation_unapplied (clock, slave, master, r_squared,
-          &xbase, &b, &m_num, &m_denom))
+  if (!gst_clock_add_observation_unapplied (clock, observation_internal,
+          observation_external, r_squared, &xbase, &b, &m_num, &m_denom))
     return FALSE;
 
   /* if we have a valid regression, adjust the clock */
@@ -1469,17 +1469,17 @@ gst_clock_add_observation (GstClock * clock, GstClockTime slave,
 /**
  * gst_clock_add_observation_unapplied:
  * @clock: a #GstClock
- * @slave: a time on the slave
- * @master: a time on the master
+ * @observation_internal: a time on the internal clock
+ * @observation_external: a time on the external clock
  * @r_squared: (out): a pointer to hold the result
- * @internal: (out) (allow-none): a location to store the internal time
- * @external: (out) (allow-none): a location to store the external time
- * @rate_num: (out) (allow-none): a location to store the rate numerator
- * @rate_denom: (out) (allow-none): a location to store the rate denominator
+ * @internal: (out) (optional): a location to store the internal time
+ * @external: (out) (optional): a location to store the external time
+ * @rate_num: (out) (optional): a location to store the rate numerator
+ * @rate_denom: (out) (optional): a location to store the rate denominator
  *
  * Add a clock observation to the internal slaving algorithm the same as
- * gst_clock_add_observation(), and return the result of the master clock
- * estimation, without updating the internal calibration.
+ * gst_clock_add_observation(), and return the result of the external or master
+ * clock estimation, without updating the internal calibration.
  *
  * The caller can then take the results and call gst_clock_set_calibration()
  * with the values, or some modified version of them.
@@ -1489,9 +1489,9 @@ gst_clock_add_observation (GstClock * clock, GstClockTime slave,
  * Since: 1.6
  */
 gboolean
-gst_clock_add_observation_unapplied (GstClock * clock, GstClockTime slave,
-    GstClockTime master, gdouble * r_squared,
-    GstClockTime * internal, GstClockTime * external,
+gst_clock_add_observation_unapplied (GstClock * clock,
+    GstClockTime internal_observation, GstClockTime external_observation,
+    gdouble * r_squared, GstClockTime * internal, GstClockTime * external,
     GstClockTime * rate_num, GstClockTime * rate_denom)
 {
   GstClockTime m_num, m_denom, b, xbase;
@@ -1499,8 +1499,8 @@ gst_clock_add_observation_unapplied (GstClock * clock, GstClockTime slave,
   guint n;
 
   g_return_val_if_fail (GST_IS_CLOCK (clock), FALSE);
-  g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (slave), FALSE);
-  g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (master), FALSE);
+  g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (internal_observation), FALSE);
+  g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (external_observation), FALSE);
   g_return_val_if_fail (r_squared != NULL, FALSE);
 
   priv = clock->priv;
@@ -1508,11 +1508,12 @@ gst_clock_add_observation_unapplied (GstClock * clock, GstClockTime slave,
   GST_CLOCK_SLAVE_LOCK (clock);
 
   GST_CAT_LOG_OBJECT (GST_CAT_CLOCK, clock,
-      "adding observation slave %" GST_TIME_FORMAT ", master %" GST_TIME_FORMAT,
-      GST_TIME_ARGS (slave), GST_TIME_ARGS (master));
+      "adding observation internal %" GST_TIME_FORMAT ", external %"
+      GST_TIME_FORMAT, GST_TIME_ARGS (internal_observation),
+      GST_TIME_ARGS (external_observation));
 
-  priv->times[(2 * priv->time_index)] = slave;
-  priv->times[(2 * priv->time_index) + 1] = master;
+  priv->times[(2 * priv->time_index)] = internal_observation;
+  priv->times[(2 * priv->time_index) + 1] = external_observation;
 
   priv->time_index++;
   if (G_UNLIKELY (priv->time_index == priv->window_size)) {
diff --git a/gst/gstclock.h b/gst/gstclock.h
index 0649f14..1457cde 100644
--- a/gst/gstclock.h
+++ b/gst/gstclock.h
@@ -610,15 +610,19 @@ GST_API
 GstClockTime            gst_clock_get_timeout           (GstClock *clock);
 
 GST_API
-gboolean                gst_clock_add_observation       (GstClock *clock, GstClockTime slave,
-                                                         GstClockTime master, gdouble *r_squared);
-GST_API
-gboolean                gst_clock_add_observation_unapplied (GstClock *clock, GstClockTime slave,
-                                                         GstClockTime master, gdouble *r_squared,
-                                                         GstClockTime *internal,
-                                                         GstClockTime *external,
-                                                         GstClockTime *rate_num,
-                                                         GstClockTime *rate_denom);
+gboolean                gst_clock_add_observation       (GstClock *clock,
+                                                         GstClockTime observation_internal,
+                                                         GstClockTime observation_external,
+                                                         gdouble *r_squared);
+GST_API
+gboolean                gst_clock_add_observation_unapplied (GstClock *clock,
+                                                             GstClockTime observation_internal,
+                                                             GstClockTime observation_external,
+                                                             gdouble *r_squared,
+                                                             GstClockTime *internal,
+                                                             GstClockTime *external,
+                                                             GstClockTime *rate_num,
+                                                             GstClockTime *rate_denom);
 
 /* getting and adjusting internal/external time */
 
diff --git a/gst/gstcontext.c b/gst/gstcontext.c
index a1b90be..402aa08 100644
--- a/gst/gstcontext.c
+++ b/gst/gstcontext.c
@@ -64,7 +64,6 @@
 #include "gst_private.h"
 #include <string.h>
 #include "gstcontext.h"
-#include "gstquark.h"
 
 struct _GstContext
 {
@@ -175,7 +174,7 @@ gst_context_new (const gchar * context_type, gboolean persistent)
 
   GST_CAT_LOG (GST_CAT_CONTEXT, "creating new context %p", context);
 
-  structure = gst_structure_new_id_empty (GST_QUARK (CONTEXT));
+  structure = gst_structure_new_static_str_empty ("context");
   gst_structure_set_parent_refcount (structure, &context->mini_object.refcount);
   gst_context_init (context);
 
diff --git a/gst/gstdebugutils.c b/gst/gstdebugutils.c
index 482b357..e5e481b 100644
--- a/gst/gstdebugutils.c
+++ b/gst/gstdebugutils.c
@@ -62,6 +62,7 @@
 #include "gstpad.h"
 #include "gstutils.h"
 #include "gstvalue.h"
+#include "gstidstr-private.h"
 
 /*** PIPELINE GRAPHS **********************************************************/
 
@@ -376,14 +377,14 @@ debug_dump_element_pad (GstPad * pad, GstElement * element,
 }
 
 static gboolean
-string_append_field (GQuark field, const GValue * value, gpointer ptr)
+string_append_field (const GstIdStr * field, const GValue * value, gpointer ptr)
 {
   GString *str = (GString *) ptr;
   gchar *value_str = gst_value_serialize (value);
   gchar *esc_value_str;
 
   if (value_str == NULL) {
-    g_string_append_printf (str, "  %18s: NULL\\l", g_quark_to_string (field));
+    g_string_append_printf (str, "  %18s: NULL\\l", gst_id_str_as_str (field));
     return TRUE;
   }
 
@@ -414,7 +415,7 @@ string_append_field (GQuark field, const GValue * value, gpointer ptr)
   }
   esc_value_str = g_strescape (value_str, NULL);
 
-  g_string_append_printf (str, "  %18s: %s\\l", g_quark_to_string (field),
+  g_string_append_printf (str, "  %18s: %s\\l", gst_id_str_as_str (field),
       esc_value_str);
 
   g_free (value_str);
@@ -458,7 +459,8 @@ debug_dump_describe_caps (GstCaps * caps, GstDebugGraphDetails details)
         }
         g_string_append (str, "\\l");
 
-        gst_structure_foreach (structure, string_append_field, (gpointer) str);
+        gst_structure_foreach_id_str (structure, string_append_field,
+            (gpointer) str);
       }
 
       media = g_string_free (str, FALSE);
@@ -852,7 +854,6 @@ gst_debug_bin_to_dot_file (GstBin * bin, GstDebugGraphDetails details,
     const gchar * file_name)
 {
   gchar *full_file_name = NULL;
-  FILE *out;
 
   g_return_if_fail (GST_IS_BIN (bin));
 
@@ -868,20 +869,17 @@ gst_debug_bin_to_dot_file (GstBin * bin, GstDebugGraphDetails details,
   full_file_name = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "%s.dot",
       priv_gst_dump_dot_dir, file_name);
 
-  if ((out = fopen (full_file_name, "wb"))) {
-    gchar *buf;
+  GError *err = NULL;
+  gchar *buf;
 
-    buf = gst_debug_bin_to_dot_data (bin, details);
-    fputs (buf, out);
+  buf = gst_debug_bin_to_dot_data (bin, details);
+  if (!g_file_set_contents (full_file_name, buf, -1, &err)) {
+    GST_WARNING ("Failed to write file '%s' for writing: %s", full_file_name,
+        err->message);
 
-    g_free (buf);
-    fclose (out);
-
-    GST_INFO ("wrote bin graph to : '%s'", full_file_name);
-  } else {
-    GST_WARNING ("Failed to open file '%s' for writing: %s", full_file_name,
-        g_strerror (errno));
   }
+  g_clear_error (&err);
+  g_free (buf);
   g_free (full_file_name);
 }
 
diff --git a/gst/gstdeviceprovider.c b/gst/gstdeviceprovider.c
index 896721b..a847570 100644
--- a/gst/gstdeviceprovider.c
+++ b/gst/gstdeviceprovider.c
@@ -47,7 +47,6 @@
 #include "gstdeviceprovider.h"
 
 #include "gstelementmetadata.h"
-#include "gstquark.h"
 
 struct _GstDeviceProviderPrivate
 {
@@ -279,11 +278,11 @@ gst_device_provider_class_set_metadata (GstDeviceProviderClass * klass,
   g_return_if_fail (description != NULL && *description != '\0');
   g_return_if_fail (author != NULL && *author != '\0');
 
-  gst_structure_id_set ((GstStructure *) klass->metadata,
-      GST_QUARK (ELEMENT_METADATA_LONGNAME), G_TYPE_STRING, longname,
-      GST_QUARK (ELEMENT_METADATA_KLASS), G_TYPE_STRING, classification,
-      GST_QUARK (ELEMENT_METADATA_DESCRIPTION), G_TYPE_STRING, description,
-      GST_QUARK (ELEMENT_METADATA_AUTHOR), G_TYPE_STRING, author, NULL);
+  gst_structure_set_static_str ((GstStructure *) klass->metadata,
+      GST_ELEMENT_METADATA_LONGNAME, G_TYPE_STRING, longname,
+      GST_ELEMENT_METADATA_KLASS, G_TYPE_STRING, classification,
+      GST_ELEMENT_METADATA_DESCRIPTION, G_TYPE_STRING, description,
+      GST_ELEMENT_METADATA_AUTHOR, G_TYPE_STRING, author, NULL);
 }
 
 /**
@@ -327,17 +326,17 @@ gst_device_provider_class_set_static_metadata (GstDeviceProviderClass * klass,
   g_value_init (&val, G_TYPE_STRING);
 
   g_value_set_static_string (&val, longname);
-  gst_structure_id_set_value (s, GST_QUARK (ELEMENT_METADATA_LONGNAME), &val);
+  gst_structure_set_value_static_str (s, GST_ELEMENT_METADATA_LONGNAME, &val);
 
   g_value_set_static_string (&val, classification);
-  gst_structure_id_set_value (s, GST_QUARK (ELEMENT_METADATA_KLASS), &val);
+  gst_structure_set_value_static_str (s, GST_ELEMENT_METADATA_KLASS, &val);
 
   g_value_set_static_string (&val, description);
-  gst_structure_id_set_value (s, GST_QUARK (ELEMENT_METADATA_DESCRIPTION),
+  gst_structure_set_value_static_str (s, GST_ELEMENT_METADATA_DESCRIPTION,
       &val);
 
   g_value_set_static_string (&val, author);
-  gst_structure_id_take_value (s, GST_QUARK (ELEMENT_METADATA_AUTHOR), &val);
+  gst_structure_set_value_static_str (s, GST_ELEMENT_METADATA_AUTHOR, &val);
 }
 
 /**
diff --git a/gst/gstdynamictypefactory.h b/gst/gstdynamictypefactory.h
index 371dafb..4501848 100644
--- a/gst/gstdynamictypefactory.h
+++ b/gst/gstdynamictypefactory.h
@@ -89,8 +89,12 @@ G_BEGIN_DECLS
 #define GST_TYPE_DYNAMIC_TYPE_FACTORY           (gst_dynamic_type_factory_get_type())
 #define GST_DYNAMIC_TYPE_FACTORY(obj)           (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_DYNAMIC_TYPE_FACTORY,\
                                                  GstDynamicTypeFactory))
+#ifndef GST_DISABLE_DEPRECATED
 #define GST_DYNAMIC_TYPE_CLASS(klass)           (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_DYNAMIC_TYPE_FACTORY,\
                                                  GstDynamicTypeFactoryClass))
+#endif
+#define GST_DYNAMIC_TYPE_FACTORY_CLASS(klass)   (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_DYNAMIC_TYPE_FACTORY,\
+                                                 GstDynamicTypeFactoryClass))
 #define GST_IS_DYNAMIC_TYPE_FACTORY(obj)        (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_DYNAMIC_TYPE_FACTORY))
 #define GST_IS_DYNAMIC_TYPE_FACTORY_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_DYNAMIC_TYPE_FACTORY))
 #define GST_DYNAMIC_TYPE_FACTORY_CAST(obj)      ((GstDynamicTypeFactory *)(obj))
diff --git a/gst/gstelement.c b/gst/gstelement.c
index 10ce62b..61c5c90 100644
--- a/gst/gstelement.c
+++ b/gst/gstelement.c
@@ -98,7 +98,6 @@
 #include "gstghostpad.h"
 #include "gstutils.h"
 #include "gstinfo.h"
-#include "gstquark.h"
 #include "gsttracerutils.h"
 #include "gstvalue.h"
 #include <glib/gi18n-lib.h>
@@ -1424,8 +1423,8 @@ gst_element_do_foreach_pad (GstElement * element,
 /**
  * gst_element_foreach_sink_pad:
  * @element: a #GstElement to iterate sink pads of
- * @func: (scope call): function to call for each sink pad
- * @user_data: (closure): user data passed to @func
+ * @func: (scope call) (closure user_data): function to call for each sink pad
+ * @user_data: user data passed to @func
  *
  * Call @func with @user_data for each of @element's sink pads. @func will be
  * called exactly once for each sink pad that exists at the time of this call,
@@ -1450,8 +1449,8 @@ gst_element_foreach_sink_pad (GstElement * element,
 /**
  * gst_element_foreach_src_pad:
  * @element: a #GstElement to iterate source pads of
- * @func: (scope call): function to call for each source pad
- * @user_data: (closure): user data passed to @func
+ * @func: (scope call) (closure user_data): function to call for each source pad
+ * @user_data: user data passed to @func
  *
  * Call @func with @user_data for each of @element's source pads. @func will be
  * called exactly once for each source pad that exists at the time of this call,
@@ -1476,8 +1475,8 @@ gst_element_foreach_src_pad (GstElement * element,
 /**
  * gst_element_foreach_pad:
  * @element: a #GstElement to iterate pads of
- * @func: (scope call): function to call for each pad
- * @user_data: (closure): user data passed to @func
+ * @func: (scope call) (closure user_data): function to call for each pad
+ * @user_data: user data passed to @func
  *
  * Call @func with @user_data for each of @element's pads. @func will be called
  * exactly once for each pad that exists at the time of this call, unless
@@ -1659,11 +1658,11 @@ gst_element_class_set_metadata (GstElementClass * klass,
   g_return_if_fail (description != NULL && *description != '\0');
   g_return_if_fail (author != NULL && *author != '\0');
 
-  gst_structure_id_set ((GstStructure *) klass->metadata,
-      GST_QUARK (ELEMENT_METADATA_LONGNAME), G_TYPE_STRING, longname,
-      GST_QUARK (ELEMENT_METADATA_KLASS), G_TYPE_STRING, classification,
-      GST_QUARK (ELEMENT_METADATA_DESCRIPTION), G_TYPE_STRING, description,
-      GST_QUARK (ELEMENT_METADATA_AUTHOR), G_TYPE_STRING, author, NULL);
+  gst_structure_set_static_str ((GstStructure *) klass->metadata,
+      GST_ELEMENT_METADATA_LONGNAME, G_TYPE_STRING, longname,
+      GST_ELEMENT_METADATA_KLASS, G_TYPE_STRING, classification,
+      GST_ELEMENT_METADATA_DESCRIPTION, G_TYPE_STRING, description,
+      GST_ELEMENT_METADATA_AUTHOR, G_TYPE_STRING, author, NULL);
 }
 
 /**
@@ -1704,17 +1703,17 @@ gst_element_class_set_static_metadata (GstElementClass * klass,
   g_value_init (&val, G_TYPE_STRING);
 
   g_value_set_static_string (&val, longname);
-  gst_structure_id_set_value (s, GST_QUARK (ELEMENT_METADATA_LONGNAME), &val);
+  gst_structure_set_value_static_str (s, GST_ELEMENT_METADATA_LONGNAME, &val);
 
   g_value_set_static_string (&val, classification);
-  gst_structure_id_set_value (s, GST_QUARK (ELEMENT_METADATA_KLASS), &val);
+  gst_structure_set_value_static_str (s, GST_ELEMENT_METADATA_KLASS, &val);
 
   g_value_set_static_string (&val, description);
-  gst_structure_id_set_value (s, GST_QUARK (ELEMENT_METADATA_DESCRIPTION),
+  gst_structure_set_value_static_str (s, GST_ELEMENT_METADATA_DESCRIPTION,
       &val);
 
   g_value_set_static_string (&val, author);
-  gst_structure_id_take_value (s, GST_QUARK (ELEMENT_METADATA_AUTHOR), &val);
+  gst_structure_take_value_static_str (s, GST_ELEMENT_METADATA_AUTHOR, &val);
 }
 
 /**
diff --git a/gst/gstevent.c b/gst/gstevent.c
index 5032f1c..3db6106 100644
--- a/gst/gstevent.c
+++ b/gst/gstevent.c
@@ -79,7 +79,6 @@
 #include "gstevent.h"
 #include "gstenumtypes.h"
 #include "gstutils.h"
-#include "gstquark.h"
 #include "gstvalue.h"
 
 GType _gst_event_type = 0;
@@ -405,8 +404,8 @@ gst_event_writable_structure (GstEvent * event)
 
   if (structure == NULL) {
     structure =
-        gst_structure_new_id_empty (gst_event_type_to_quark (GST_EVENT_TYPE
-            (event)));
+        gst_structure_new_static_str_empty (gst_event_type_get_name
+        (GST_EVENT_TYPE (event)));
     gst_structure_set_parent_refcount (structure, &event->mini_object.refcount);
     GST_EVENT_STRUCTURE (event) = structure;
   }
@@ -445,16 +444,13 @@ gst_event_has_name (GstEvent * event, const gchar * name)
  * Returns: %TRUE if @name matches the name of the event structure.
  *
  * Since: 1.18
+ *
+ * Deprecated: 1.26: Use gst_event_has_name().
  */
 gboolean
 gst_event_has_name_id (GstEvent * event, GQuark name)
 {
-  g_return_val_if_fail (GST_IS_EVENT (event), FALSE);
-
-  if (GST_EVENT_STRUCTURE (event) == NULL)
-    return FALSE;
-
-  return (GST_EVENT_STRUCTURE (event)->name == name);
+  return gst_event_has_name (event, g_quark_to_string (name));
 }
 
 /**
@@ -609,8 +605,8 @@ gst_event_new_flush_stop (gboolean reset_time)
   GST_CAT_INFO (GST_CAT_EVENT, "creating flush stop %d", reset_time);
 
   event = gst_event_new_custom (GST_EVENT_FLUSH_STOP,
-      gst_structure_new_id (GST_QUARK (EVENT_FLUSH_STOP),
-          GST_QUARK (RESET_TIME), G_TYPE_BOOLEAN, reset_time, NULL));
+      gst_structure_new_static_str ("GstEventFlushStop",
+          "reset-time", G_TYPE_BOOLEAN, reset_time, NULL));
 
   return event;
 }
@@ -633,8 +629,7 @@ gst_event_parse_flush_stop (GstEvent * event, gboolean * reset_time)
   structure = GST_EVENT_STRUCTURE (event);
   if (G_LIKELY (reset_time))
     *reset_time =
-        g_value_get_boolean (gst_structure_id_get_value (structure,
-            GST_QUARK (RESET_TIME)));
+        g_value_get_boolean (gst_structure_get_value (structure, "reset-time"));
 }
 
 /**
@@ -668,7 +663,7 @@ gst_event_new_select_streams (GList * streams)
   g_return_val_if_fail (streams != NULL, NULL);
 
   GST_CAT_INFO (GST_CAT_EVENT, "Creating new select-streams event");
-  struc = gst_structure_new_id_empty (GST_QUARK (EVENT_SELECT_STREAMS));
+  struc = gst_structure_new_static_str_empty ("GstEventSelectStreams");
   g_value_init (&val, GST_TYPE_LIST);
   /* Fill struc with streams */
   for (tmpl = streams; tmpl; tmpl = tmpl->next) {
@@ -678,7 +673,7 @@ gst_event_new_select_streams (GList * streams)
     g_value_set_string (&strval, str);
     gst_value_list_append_and_take_value (&val, &strval);
   }
-  gst_structure_id_take_value (struc, GST_QUARK (STREAMS), &val);
+  gst_structure_take_value (struc, "streams", &val);
   event = gst_event_new_custom (GST_EVENT_SELECT_STREAMS, struc);
 
   return event;
@@ -704,8 +699,7 @@ gst_event_parse_select_streams (GstEvent * event, GList ** streams)
 
   structure = GST_EVENT_STRUCTURE (event);
   if (G_LIKELY (streams)) {
-    const GValue *vlist =
-        gst_structure_id_get_value (structure, GST_QUARK (STREAMS));
+    const GValue *vlist = gst_structure_get_value (structure, "streams");
     guint i, sz = gst_value_list_get_size (vlist);
     for (i = 0; i < sz; i++) {
       const GValue *strv = gst_value_list_get_value (vlist, i);
@@ -741,8 +735,8 @@ gst_event_new_stream_group_done (guint group_id)
 
   g_return_val_if_fail (group_id != GST_GROUP_ID_INVALID, NULL);
 
-  s = gst_structure_new_id (GST_QUARK (EVENT_STREAM_GROUP_DONE),
-      GST_QUARK (GROUP_ID), G_TYPE_UINT, group_id, NULL);
+  s = gst_structure_new_static_str ("GstEventStreamGroupDone",
+      "group-id", G_TYPE_UINT, group_id, NULL);
 
   return gst_event_new_custom (GST_EVENT_STREAM_GROUP_DONE, s);
 }
@@ -764,8 +758,8 @@ gst_event_parse_stream_group_done (GstEvent * event, guint * group_id)
   g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_STREAM_GROUP_DONE);
 
   if (group_id) {
-    gst_structure_id_get (GST_EVENT_STRUCTURE (event),
-        GST_QUARK (GROUP_ID), G_TYPE_UINT, group_id, NULL);
+    gst_structure_get (GST_EVENT_STRUCTURE (event),
+        "group-id", G_TYPE_UINT, group_id, NULL);
   }
 }
 
@@ -820,9 +814,9 @@ gst_event_new_gap (GstClockTime timestamp, GstClockTime duration)
       GST_TIME_ARGS (duration));
 
   event = gst_event_new_custom (GST_EVENT_GAP,
-      gst_structure_new_id (GST_QUARK (EVENT_GAP),
-          GST_QUARK (TIMESTAMP), GST_TYPE_CLOCK_TIME, timestamp,
-          GST_QUARK (DURATION), GST_TYPE_CLOCK_TIME, duration, NULL));
+      gst_structure_new_static_str ("GstEventGap",
+          "timestamp", GST_TYPE_CLOCK_TIME, timestamp,
+          "duration", GST_TYPE_CLOCK_TIME, duration, NULL));
 
   return event;
 }
@@ -847,9 +841,9 @@ gst_event_parse_gap (GstEvent * event, GstClockTime * timestamp,
   g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_GAP);
 
   structure = GST_EVENT_STRUCTURE (event);
-  gst_structure_id_get (structure,
-      GST_QUARK (TIMESTAMP), GST_TYPE_CLOCK_TIME, timestamp,
-      GST_QUARK (DURATION), GST_TYPE_CLOCK_TIME, duration, NULL);
+  gst_structure_get (structure,
+      "timestamp", GST_TYPE_CLOCK_TIME, timestamp,
+      "duration", GST_TYPE_CLOCK_TIME, duration, NULL);
 }
 
 /**
@@ -869,8 +863,8 @@ gst_event_set_gap_flags (GstEvent * event, GstGapFlags flags)
   g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_GAP);
   g_return_if_fail (gst_event_is_writable (event));
 
-  gst_structure_id_set (GST_EVENT_STRUCTURE (event),
-      GST_QUARK (GAP_FLAGS), GST_TYPE_GAP_FLAGS, flags, NULL);
+  gst_structure_set (GST_EVENT_STRUCTURE (event),
+      "gap-flags", GST_TYPE_GAP_FLAGS, flags, NULL);
 }
 
 /**
@@ -893,8 +887,8 @@ gst_event_parse_gap_flags (GstEvent * event, GstGapFlags * flags)
   if (flags)
     *flags = 0;
 
-  gst_structure_id_get (GST_EVENT_STRUCTURE (event),
-      GST_QUARK (GAP_FLAGS), GST_TYPE_GAP_FLAGS, flags, NULL);
+  gst_structure_get (GST_EVENT_STRUCTURE (event),
+      "gap-flags", GST_TYPE_GAP_FLAGS, flags, NULL);
 }
 
 /**
@@ -918,8 +912,8 @@ gst_event_new_caps (GstCaps * caps)
   GST_CAT_INFO (GST_CAT_EVENT, "creating caps event %" GST_PTR_FORMAT, caps);
 
   event = gst_event_new_custom (GST_EVENT_CAPS,
-      gst_structure_new_id (GST_QUARK (EVENT_CAPS),
-          GST_QUARK (CAPS), GST_TYPE_CAPS, caps, NULL));
+      gst_structure_new_static_str ("GstEventCaps", "caps", GST_TYPE_CAPS, caps,
+          NULL));
 
   return event;
 }
@@ -942,9 +936,7 @@ gst_event_parse_caps (GstEvent * event, GstCaps ** caps)
 
   structure = GST_EVENT_STRUCTURE (event);
   if (G_LIKELY (caps))
-    *caps =
-        g_value_get_boxed (gst_structure_id_get_value (structure,
-            GST_QUARK (CAPS)));
+    *caps = g_value_get_boxed (gst_structure_get_value (structure, "caps"));
 }
 
 /**
@@ -999,8 +991,8 @@ gst_event_new_segment (const GstSegment * segment)
       segment);
 
   event = gst_event_new_custom (GST_EVENT_SEGMENT,
-      gst_structure_new_id (GST_QUARK (EVENT_SEGMENT),
-          GST_QUARK (SEGMENT), GST_TYPE_SEGMENT, segment, NULL));
+      gst_structure_new_static_str ("GstEventSegment",
+          "segment", GST_TYPE_SEGMENT, segment, NULL));
 
   return event;
 }
@@ -1024,8 +1016,8 @@ gst_event_parse_segment (GstEvent * event, const GstSegment ** segment)
 
   if (segment) {
     structure = GST_EVENT_STRUCTURE (event);
-    *segment = g_value_get_boxed (gst_structure_id_get_value (structure,
-            GST_QUARK (SEGMENT)));
+    *segment = g_value_get_boxed (gst_structure_get_value (structure,
+            "segment"));
   }
 }
 
@@ -1075,10 +1067,11 @@ gst_event_new_tag (GstTagList * taglist)
 
   g_return_val_if_fail (taglist != NULL, NULL);
 
-  s = gst_structure_new_empty (names[gst_tag_list_get_scope (taglist)]);
+  s = gst_structure_new_static_str_empty (names[gst_tag_list_get_scope
+          (taglist)]);
   g_value_init (&val, GST_TYPE_TAG_LIST);
   g_value_take_boxed (&val, taglist);
-  gst_structure_id_take_value (s, GST_QUARK (TAGLIST), &val);
+  gst_structure_take_value (s, "taglist", &val);
   return gst_event_new_custom (GST_EVENT_TAG, s);
 }
 
@@ -1100,8 +1093,7 @@ gst_event_parse_tag (GstEvent * event, GstTagList ** taglist)
   g_return_if_fail (GST_IS_EVENT (event));
   g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_TAG);
 
-  val = gst_structure_id_get_value (GST_EVENT_STRUCTURE (event),
-      GST_QUARK (TAGLIST));
+  val = gst_structure_get_value (GST_EVENT_STRUCTURE (event), "taglist");
 
   if (taglist)
     *taglist = (GstTagList *) g_value_get_boxed (val);
@@ -1134,11 +1126,10 @@ gst_event_new_buffer_size (GstFormat format, gint64 minsize,
       ", maxsize %" G_GINT64_FORMAT ", async %d", gst_format_get_name (format),
       minsize, maxsize, async);
 
-  structure = gst_structure_new_id (GST_QUARK (EVENT_BUFFER_SIZE),
-      GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
-      GST_QUARK (MINSIZE), G_TYPE_INT64, minsize,
-      GST_QUARK (MAXSIZE), G_TYPE_INT64, maxsize,
-      GST_QUARK (ASYNC), G_TYPE_BOOLEAN, async, NULL);
+  structure = gst_structure_new_static_str ("GstEventBufferSize",
+      "format", GST_TYPE_FORMAT, format,
+      "minsize", G_TYPE_INT64, minsize,
+      "maxsize", G_TYPE_INT64, maxsize, "async", G_TYPE_BOOLEAN, async, NULL);
   event = gst_event_new_custom (GST_EVENT_BUFFERSIZE, structure);
 
   return event;
@@ -1166,20 +1157,15 @@ gst_event_parse_buffer_size (GstEvent * event, GstFormat * format,
   structure = GST_EVENT_STRUCTURE (event);
   if (format)
     *format = (GstFormat)
-        g_value_get_enum (gst_structure_id_get_value (structure,
-            GST_QUARK (FORMAT)));
+        g_value_get_enum (gst_structure_get_value (structure, "format"));
   if (minsize)
     *minsize =
-        g_value_get_int64 (gst_structure_id_get_value (structure,
-            GST_QUARK (MINSIZE)));
+        g_value_get_int64 (gst_structure_get_value (structure, "minsize"));
   if (maxsize)
     *maxsize =
-        g_value_get_int64 (gst_structure_id_get_value (structure,
-            GST_QUARK (MAXSIZE)));
+        g_value_get_int64 (gst_structure_get_value (structure, "maxsize"));
   if (async)
-    *async =
-        g_value_get_boolean (gst_structure_id_get_value (structure,
-            GST_QUARK (ASYNC)));
+    *async = g_value_get_boolean (gst_structure_get_value (structure, "async"));
 }
 
 /**
@@ -1249,11 +1235,10 @@ gst_event_new_qos (GstQOSType type, gdouble proportion,
       ", timestamp %" GST_TIME_FORMAT, type, proportion,
       diff, GST_TIME_ARGS (timestamp));
 
-  structure = gst_structure_new_id (GST_QUARK (EVENT_QOS),
-      GST_QUARK (TYPE), GST_TYPE_QOS_TYPE, type,
-      GST_QUARK (PROPORTION), G_TYPE_DOUBLE, proportion,
-      GST_QUARK (DIFF), G_TYPE_INT64, diff,
-      GST_QUARK (TIMESTAMP), G_TYPE_UINT64, timestamp, NULL);
+  structure = gst_structure_new_static_str ("GstEventQOS",
+      "type", GST_TYPE_QOS_TYPE, type,
+      "proportion", G_TYPE_DOUBLE, proportion,
+      "diff", G_TYPE_INT64, diff, "timestamp", G_TYPE_UINT64, timestamp, NULL);
   event = gst_event_new_custom (GST_EVENT_QOS, structure);
 
   return event;
@@ -1284,25 +1269,20 @@ gst_event_parse_qos (GstEvent * event, GstQOSType * type,
   structure = GST_EVENT_STRUCTURE (event);
   if (type)
     *type = (GstQOSType)
-        g_value_get_enum (gst_structure_id_get_value (structure,
-            GST_QUARK (TYPE)));
+        g_value_get_enum (gst_structure_get_value (structure, "type"));
   if (proportion)
     *proportion =
-        g_value_get_double (gst_structure_id_get_value (structure,
-            GST_QUARK (PROPORTION)));
+        g_value_get_double (gst_structure_get_value (structure, "proportion"));
   if (diff)
-    *diff =
-        g_value_get_int64 (gst_structure_id_get_value (structure,
-            GST_QUARK (DIFF)));
+    *diff = g_value_get_int64 (gst_structure_get_value (structure, "diff"));
   if (timestamp) {
     gint64 offset = gst_event_get_running_time_offset (event);
     GstClockTimeDiff diff_ =
-        g_value_get_int64 (gst_structure_id_get_value (structure,
-            GST_QUARK (DIFF)));
+        g_value_get_int64 (gst_structure_get_value (structure,
+            "diff"));
 
     *timestamp =
-        g_value_get_uint64 (gst_structure_id_get_value (structure,
-            GST_QUARK (TIMESTAMP)));
+        g_value_get_uint64 (gst_structure_get_value (structure, "timestamp"));
     /* Catch underflows */
     if (*timestamp > -offset)
       *timestamp += offset;
@@ -1401,16 +1381,15 @@ gst_event_new_seek (gdouble rate, GstFormat format, GstSeekFlags flags,
         stop);
   }
 
-  structure = gst_structure_new_id (GST_QUARK (EVENT_SEEK),
-      GST_QUARK (RATE), G_TYPE_DOUBLE, rate,
-      GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
-      GST_QUARK (FLAGS), GST_TYPE_SEEK_FLAGS, flags,
-      GST_QUARK (CUR_TYPE), GST_TYPE_SEEK_TYPE, start_type,
-      GST_QUARK (CUR), G_TYPE_INT64, start,
-      GST_QUARK (STOP_TYPE), GST_TYPE_SEEK_TYPE, stop_type,
-      GST_QUARK (STOP), G_TYPE_INT64, stop,
-      GST_QUARK (TRICKMODE_INTERVAL), GST_TYPE_CLOCK_TIME, (GstClockTime) 0,
-      NULL);
+  structure = gst_structure_new_static_str ("GstEventSeek",
+      "rate", G_TYPE_DOUBLE, rate,
+      "format", GST_TYPE_FORMAT, format,
+      "flags", GST_TYPE_SEEK_FLAGS, flags,
+      "cur-type", GST_TYPE_SEEK_TYPE, start_type,
+      "cur", G_TYPE_INT64, start,
+      "stop-type", GST_TYPE_SEEK_TYPE, stop_type,
+      "stop", G_TYPE_INT64, stop,
+      "trickmode-interval", GST_TYPE_CLOCK_TIME, (GstClockTime) 0, NULL);
   event = gst_event_new_custom (GST_EVENT_SEEK, structure);
 
   return event;
@@ -1441,33 +1420,23 @@ gst_event_parse_seek (GstEvent * event, gdouble * rate,
 
   structure = GST_EVENT_STRUCTURE (event);
   if (rate)
-    *rate =
-        g_value_get_double (gst_structure_id_get_value (structure,
-            GST_QUARK (RATE)));
+    *rate = g_value_get_double (gst_structure_get_value (structure, "rate"));
   if (format)
     *format = (GstFormat)
-        g_value_get_enum (gst_structure_id_get_value (structure,
-            GST_QUARK (FORMAT)));
+        g_value_get_enum (gst_structure_get_value (structure, "format"));
   if (flags)
     *flags = (GstSeekFlags)
-        g_value_get_flags (gst_structure_id_get_value (structure,
-            GST_QUARK (FLAGS)));
+        g_value_get_flags (gst_structure_get_value (structure, "flags"));
   if (start_type)
     *start_type = (GstSeekType)
-        g_value_get_enum (gst_structure_id_get_value (structure,
-            GST_QUARK (CUR_TYPE)));
+        g_value_get_enum (gst_structure_get_value (structure, "cur-type"));
   if (start)
-    *start =
-        g_value_get_int64 (gst_structure_id_get_value (structure,
-            GST_QUARK (CUR)));
+    *start = g_value_get_int64 (gst_structure_get_value (structure, "cur"));
   if (stop_type)
     *stop_type = (GstSeekType)
-        g_value_get_enum (gst_structure_id_get_value (structure,
-            GST_QUARK (STOP_TYPE)));
+        g_value_get_enum (gst_structure_get_value (structure, "stop-type"));
   if (stop)
-    *stop =
-        g_value_get_int64 (gst_structure_id_get_value (structure,
-            GST_QUARK (STOP)));
+    *stop = g_value_get_int64 (gst_structure_get_value (structure, "stop"));
 }
 
 /**
@@ -1487,8 +1456,8 @@ gst_event_set_seek_trickmode_interval (GstEvent * event, GstClockTime interval)
   g_return_if_fail (gst_event_is_writable (event));
   g_return_if_fail (GST_CLOCK_TIME_IS_VALID (interval));
 
-  gst_structure_id_set (GST_EVENT_STRUCTURE (event),
-      GST_QUARK (TRICKMODE_INTERVAL), GST_TYPE_CLOCK_TIME, interval, NULL);
+  gst_structure_set_static_str (GST_EVENT_STRUCTURE (event),
+      "trickmode-interval", GST_TYPE_CLOCK_TIME, interval, NULL);
 }
 
 /**
@@ -1511,8 +1480,8 @@ gst_event_parse_seek_trickmode_interval (GstEvent * event,
   if (interval)
     *interval = GST_CLOCK_TIME_NONE;
 
-  gst_structure_id_get (GST_EVENT_STRUCTURE (event),
-      GST_QUARK (TRICKMODE_INTERVAL), GST_TYPE_CLOCK_TIME, interval, NULL);
+  gst_structure_get (GST_EVENT_STRUCTURE (event),
+      "trickmode-interval", GST_TYPE_CLOCK_TIME, interval, NULL);
 }
 
 /**
@@ -1557,8 +1526,8 @@ gst_event_new_latency (GstClockTime latency)
   GST_CAT_INFO (GST_CAT_EVENT,
       "creating latency event %" GST_TIME_FORMAT, GST_TIME_ARGS (latency));
 
-  structure = gst_structure_new_id (GST_QUARK (EVENT_LATENCY),
-      GST_QUARK (LATENCY), G_TYPE_UINT64, latency, NULL);
+  structure = gst_structure_new_static_str ("GstEventLatency",
+      "latency", G_TYPE_UINT64, latency, NULL);
   event = gst_event_new_custom (GST_EVENT_LATENCY, structure);
 
   return event;
@@ -1579,8 +1548,8 @@ gst_event_parse_latency (GstEvent * event, GstClockTime * latency)
 
   if (latency)
     *latency =
-        g_value_get_uint64 (gst_structure_id_get_value (GST_EVENT_STRUCTURE
-            (event), GST_QUARK (LATENCY)));
+        g_value_get_uint64 (gst_structure_get_value (GST_EVENT_STRUCTURE
+            (event), "latency"));
 }
 
 /**
@@ -1618,12 +1587,12 @@ gst_event_new_step (GstFormat format, guint64 amount, gdouble rate,
 
   GST_CAT_INFO (GST_CAT_EVENT, "creating step event");
 
-  structure = gst_structure_new_id (GST_QUARK (EVENT_STEP),
-      GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
-      GST_QUARK (AMOUNT), G_TYPE_UINT64, amount,
-      GST_QUARK (RATE), G_TYPE_DOUBLE, rate,
-      GST_QUARK (FLUSH), G_TYPE_BOOLEAN, flush,
-      GST_QUARK (INTERMEDIATE), G_TYPE_BOOLEAN, intermediate, NULL);
+  structure = gst_structure_new_static_str ("GstEventStep",
+      "format", GST_TYPE_FORMAT, format,
+      "amount", G_TYPE_UINT64, amount,
+      "rate", G_TYPE_DOUBLE, rate,
+      "flush", G_TYPE_BOOLEAN, flush,
+      "intermediate", G_TYPE_BOOLEAN, intermediate, NULL);
   event = gst_event_new_custom (GST_EVENT_STEP, structure);
 
   return event;
@@ -1653,20 +1622,18 @@ gst_event_parse_step (GstEvent * event, GstFormat * format, guint64 * amount,
   structure = GST_EVENT_STRUCTURE (event);
   if (format)
     *format =
-        (GstFormat) g_value_get_enum (gst_structure_id_get_value (structure,
-            GST_QUARK (FORMAT)));
+        (GstFormat) g_value_get_enum (gst_structure_get_value (structure,
+            "format"));
   if (amount)
-    *amount = g_value_get_uint64 (gst_structure_id_get_value (structure,
-            GST_QUARK (AMOUNT)));
+    *amount = g_value_get_uint64 (gst_structure_get_value (structure,
+            "amount"));
   if (rate)
-    *rate = g_value_get_double (gst_structure_id_get_value (structure,
-            GST_QUARK (RATE)));
+    *rate = g_value_get_double (gst_structure_get_value (structure, "rate"));
   if (flush)
-    *flush = g_value_get_boolean (gst_structure_id_get_value (structure,
-            GST_QUARK (FLUSH)));
+    *flush = g_value_get_boolean (gst_structure_get_value (structure, "flush"));
   if (intermediate)
-    *intermediate = g_value_get_boolean (gst_structure_id_get_value (structure,
-            GST_QUARK (INTERMEDIATE)));
+    *intermediate = g_value_get_boolean (gst_structure_get_value (structure,
+            "intermediate"));
 }
 
 /**
@@ -1715,8 +1682,9 @@ gst_event_new_sink_message (const gchar * name, GstMessage * msg)
 
   GST_CAT_INFO (GST_CAT_EVENT, "creating sink-message event");
 
-  structure = gst_structure_new_id (g_quark_from_string (name),
-      GST_QUARK (MESSAGE), GST_TYPE_MESSAGE, msg, NULL);
+  structure =
+      gst_structure_new_static_str (name, "message", GST_TYPE_MESSAGE, msg,
+      NULL);
   event = gst_event_new_custom (GST_EVENT_SINK_MESSAGE, structure);
 
   return event;
@@ -1740,8 +1708,8 @@ gst_event_parse_sink_message (GstEvent * event, GstMessage ** msg)
   structure = GST_EVENT_STRUCTURE (event);
   if (msg)
     *msg =
-        GST_MESSAGE (g_value_dup_boxed (gst_structure_id_get_value
-            (structure, GST_QUARK (MESSAGE))));
+        GST_MESSAGE (g_value_dup_boxed (gst_structure_get_value
+            (structure, "message")));
 }
 
 /**
@@ -1779,9 +1747,9 @@ gst_event_new_stream_start (const gchar * stream_id)
 
   g_return_val_if_fail (stream_id != NULL, NULL);
 
-  s = gst_structure_new_id (GST_QUARK (EVENT_STREAM_START),
-      GST_QUARK (STREAM_ID), G_TYPE_STRING, stream_id,
-      GST_QUARK (FLAGS), GST_TYPE_STREAM_FLAGS, GST_STREAM_FLAG_NONE, NULL);
+  s = gst_structure_new_static_str ("GstEventStreamStart",
+      "stream-id", G_TYPE_STRING, stream_id,
+      "flags", GST_TYPE_STREAM_FLAGS, GST_STREAM_FLAG_NONE, NULL);
 
   return gst_event_new_custom (GST_EVENT_STREAM_START, s);
 }
@@ -1806,7 +1774,7 @@ gst_event_parse_stream_start (GstEvent * event, const gchar ** stream_id)
   g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_STREAM_START);
 
   structure = gst_event_get_structure (event);
-  val = gst_structure_id_get_value (structure, GST_QUARK (STREAM_ID));
+  val = gst_structure_get_value (structure, "stream-id");
 
   if (stream_id)
     *stream_id = g_value_get_string (val);
@@ -1828,8 +1796,8 @@ gst_event_set_stream (GstEvent * event, GstStream * stream)
   g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_STREAM_START);
   g_return_if_fail (gst_event_is_writable (event));
 
-  gst_structure_id_set (GST_EVENT_STRUCTURE (event),
-      GST_QUARK (STREAM), GST_TYPE_STREAM, stream, NULL);
+  gst_structure_set (GST_EVENT_STRUCTURE (event),
+      "stream", GST_TYPE_STREAM, stream, NULL);
 }
 
 /**
@@ -1849,8 +1817,8 @@ gst_event_parse_stream (GstEvent * event, GstStream ** stream)
 
   if (stream) {
     *stream = NULL;
-    gst_structure_id_get (GST_EVENT_STRUCTURE (event),
-        GST_QUARK (STREAM), GST_TYPE_STREAM, stream, NULL);
+    gst_structure_get (GST_EVENT_STRUCTURE (event),
+        "stream", GST_TYPE_STREAM, stream, NULL);
   }
 }
 
@@ -1868,8 +1836,8 @@ gst_event_set_stream_flags (GstEvent * event, GstStreamFlags flags)
   g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_STREAM_START);
   g_return_if_fail (gst_event_is_writable (event));
 
-  gst_structure_id_set (GST_EVENT_STRUCTURE (event),
-      GST_QUARK (FLAGS), GST_TYPE_STREAM_FLAGS, flags, NULL);
+  gst_structure_set (GST_EVENT_STRUCTURE (event),
+      "flags", GST_TYPE_STREAM_FLAGS, flags, NULL);
 }
 
 /**
@@ -1887,8 +1855,8 @@ gst_event_parse_stream_flags (GstEvent * event, GstStreamFlags * flags)
 
   if (flags) {
     *flags = 0;
-    gst_structure_id_get (GST_EVENT_STRUCTURE (event),
-        GST_QUARK (FLAGS), GST_TYPE_STREAM_FLAGS, flags, NULL);
+    gst_structure_get (GST_EVENT_STRUCTURE (event),
+        "flags", GST_TYPE_STREAM_FLAGS, flags, NULL);
   }
 }
 
@@ -1915,8 +1883,8 @@ gst_event_set_group_id (GstEvent * event, guint group_id)
   g_return_if_fail (gst_event_is_writable (event));
   g_return_if_fail (group_id != GST_GROUP_ID_INVALID);
 
-  gst_structure_id_set (GST_EVENT_STRUCTURE (event),
-      GST_QUARK (GROUP_ID), G_TYPE_UINT, group_id, NULL);
+  gst_structure_set (GST_EVENT_STRUCTURE (event),
+      "group-id", G_TYPE_UINT, group_id, NULL);
 }
 
 /**
@@ -1938,8 +1906,8 @@ gst_event_parse_group_id (GstEvent * event, guint * group_id)
 
   if (group_id) {
     *group_id = 0;
-    return gst_structure_id_get (GST_EVENT_STRUCTURE (event),
-        GST_QUARK (GROUP_ID), G_TYPE_UINT, group_id, NULL);
+    return gst_structure_get (GST_EVENT_STRUCTURE (event),
+        "group-id", G_TYPE_UINT, group_id, NULL);
   }
 
   return TRUE;
@@ -1970,8 +1938,8 @@ gst_event_new_stream_collection (GstStreamCollection * collection)
   g_return_val_if_fail (collection != NULL, NULL);
   g_return_val_if_fail (GST_IS_STREAM_COLLECTION (collection), NULL);
 
-  s = gst_structure_new_id (GST_QUARK (EVENT_STREAM_COLLECTION),
-      GST_QUARK (COLLECTION), GST_TYPE_STREAM_COLLECTION, collection, NULL);
+  s = gst_structure_new_static_str ("stream-collection",
+      "collection", GST_TYPE_STREAM_COLLECTION, collection, NULL);
 
   return gst_event_new_custom (GST_EVENT_STREAM_COLLECTION, s);
 }
@@ -1997,8 +1965,8 @@ gst_event_parse_stream_collection (GstEvent * event,
   structure = gst_event_get_structure (event);
 
   if (collection) {
-    gst_structure_id_get (structure,
-        GST_QUARK (COLLECTION), GST_TYPE_STREAM_COLLECTION, collection, NULL);
+    gst_structure_get (structure,
+        "collection", GST_TYPE_STREAM_COLLECTION, collection, NULL);
   }
 }
 
@@ -2016,7 +1984,7 @@ GstEvent *
 gst_event_new_toc (GstToc * toc, gboolean updated)
 {
   GstStructure *toc_struct;
-  GQuark id;
+  const gchar *name;
 
   g_return_val_if_fail (toc != NULL, NULL);
 
@@ -2025,13 +1993,12 @@ gst_event_new_toc (GstToc * toc, gboolean updated)
   /* need different structure names so sticky_multi event stuff on pads
    * works, i.e. both TOC events are kept around */
   if (gst_toc_get_scope (toc) == GST_TOC_SCOPE_GLOBAL)
-    id = GST_QUARK (EVENT_TOC_GLOBAL);
+    name = "GstEventTocGlobal";
   else
-    id = GST_QUARK (EVENT_TOC_CURRENT);
+    name = "GstEventTocCurrent";
 
-  toc_struct = gst_structure_new_id (id,
-      GST_QUARK (TOC), GST_TYPE_TOC, toc,
-      GST_QUARK (UPDATED), G_TYPE_BOOLEAN, updated, NULL);
+  toc_struct = gst_structure_new_static_str (name,
+      "toc", GST_TYPE_TOC, toc, "updated", G_TYPE_BOOLEAN, updated, NULL);
 
   return gst_event_new_custom (GST_EVENT_TOC, toc_struct);
 }
@@ -2055,9 +2022,8 @@ gst_event_parse_toc (GstEvent * event, GstToc ** toc, gboolean * updated)
 
   structure = gst_event_get_structure (event);
 
-  gst_structure_id_get (structure,
-      GST_QUARK (TOC), GST_TYPE_TOC, toc,
-      GST_QUARK (UPDATED), G_TYPE_BOOLEAN, updated, NULL);
+  gst_structure_get (structure,
+      "toc", GST_TYPE_TOC, toc, "updated", G_TYPE_BOOLEAN, updated, NULL);
 }
 
 /**
@@ -2079,8 +2045,8 @@ gst_event_new_toc_select (const gchar * uid)
 
   GST_CAT_INFO (GST_CAT_EVENT, "creating toc select event for UID: %s", uid);
 
-  structure = gst_structure_new_id (GST_QUARK (EVENT_TOC_SELECT),
-      GST_QUARK (UID), G_TYPE_STRING, uid, NULL);
+  structure = gst_structure_new_static_str ("GstEventTocSelect",
+      "uid", G_TYPE_STRING, uid, NULL);
 
   return gst_event_new_custom (GST_EVENT_TOC_SELECT, structure);
 }
@@ -2102,7 +2068,7 @@ gst_event_parse_toc_select (GstEvent * event, gchar ** uid)
   g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_TOC_SELECT);
 
   structure = gst_event_get_structure (event);
-  val = gst_structure_id_get_value (structure, GST_QUARK (UID));
+  val = gst_structure_get_value (structure, "uid");
 
   if (uid != NULL)
     *uid = g_value_dup_string (val);
@@ -2239,9 +2205,9 @@ gst_event_new_segment_done (GstFormat format, gint64 position)
 
   GST_CAT_INFO (GST_CAT_EVENT, "creating segment-done event");
 
-  structure = gst_structure_new_id (GST_QUARK (EVENT_SEGMENT_DONE),
-      GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
-      GST_QUARK (POSITION), G_TYPE_INT64, position, NULL);
+  structure = gst_structure_new_static_str ("GstEventSegmentDone",
+      "format", GST_TYPE_FORMAT, format,
+      "position", G_TYPE_INT64, position, NULL);
 
   event = gst_event_new_custom (GST_EVENT_SEGMENT_DONE, structure);
 
@@ -2269,11 +2235,11 @@ gst_event_parse_segment_done (GstEvent * event, GstFormat * format,
 
   structure = gst_event_get_structure (event);
 
-  val = gst_structure_id_get_value (structure, GST_QUARK (FORMAT));
+  val = gst_structure_get_value (structure, "format");
   if (format != NULL)
     *format = g_value_get_enum (val);
 
-  val = gst_structure_id_get_value (structure, GST_QUARK (POSITION));
+  val = gst_structure_get_value (structure, "position");
   if (position != NULL)
     *position = g_value_get_int64 (val);
 }
@@ -2311,9 +2277,9 @@ gst_event_new_instant_rate_change (gdouble rate_multiplier,
       rate_multiplier, new_flags);
 
   event = gst_event_new_custom (GST_EVENT_INSTANT_RATE_CHANGE,
-      gst_structure_new_id (GST_QUARK (EVENT_INSTANT_RATE_CHANGE),
-          GST_QUARK (RATE), G_TYPE_DOUBLE, rate_multiplier,
-          GST_QUARK (FLAGS), GST_TYPE_SEGMENT_FLAGS, new_flags, NULL));
+      gst_structure_new_static_str ("GstEventInstantRateChange",
+          "rate", G_TYPE_DOUBLE, rate_multiplier,
+          "flags", GST_TYPE_SEGMENT_FLAGS, new_flags, NULL));
 
   return event;
 }
@@ -2340,9 +2306,8 @@ gst_event_parse_instant_rate_change (GstEvent * event,
   g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_INSTANT_RATE_CHANGE);
 
   structure = GST_EVENT_STRUCTURE (event);
-  gst_structure_id_get (structure, GST_QUARK (RATE), G_TYPE_DOUBLE,
-      rate_multiplier, GST_QUARK (FLAGS), GST_TYPE_SEGMENT_FLAGS, new_flags,
-      NULL);
+  gst_structure_get (structure, "rate", G_TYPE_DOUBLE,
+      rate_multiplier, "flags", GST_TYPE_SEGMENT_FLAGS, new_flags, NULL);
 }
 
 /**
@@ -2385,10 +2350,10 @@ gst_event_new_instant_rate_sync_time (gdouble rate_multiplier,
       GST_TIME_ARGS (running_time), GST_TIME_ARGS (upstream_running_time));
 
   event = gst_event_new_custom (GST_EVENT_INSTANT_RATE_SYNC_TIME,
-      gst_structure_new_id (GST_QUARK (EVENT_INSTANT_RATE_SYNC_TIME),
-          GST_QUARK (RATE), G_TYPE_DOUBLE, rate_multiplier,
-          GST_QUARK (RUNNING_TIME), GST_TYPE_CLOCK_TIME, running_time,
-          GST_QUARK (UPSTREAM_RUNNING_TIME), GST_TYPE_CLOCK_TIME,
+      gst_structure_new_static_str ("GstEventInstantRateSyncTime",
+          "rate", G_TYPE_DOUBLE, rate_multiplier,
+          "running-time", GST_TYPE_CLOCK_TIME, running_time,
+          "upstream-running-time", GST_TYPE_CLOCK_TIME,
           upstream_running_time, NULL));
 
   return event;
@@ -2419,9 +2384,9 @@ gst_event_parse_instant_rate_sync_time (GstEvent * event,
   g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_INSTANT_RATE_SYNC_TIME);
 
   structure = GST_EVENT_STRUCTURE (event);
-  gst_structure_id_get (structure, GST_QUARK (RATE), G_TYPE_DOUBLE,
-      rate_multiplier, GST_QUARK (RUNNING_TIME), GST_TYPE_CLOCK_TIME,
-      running_time, GST_QUARK (UPSTREAM_RUNNING_TIME), GST_TYPE_CLOCK_TIME,
+  gst_structure_get (structure, "rate", G_TYPE_DOUBLE,
+      rate_multiplier, "running-time", GST_TYPE_CLOCK_TIME,
+      running_time, "upstream-running-time", GST_TYPE_CLOCK_TIME,
       upstream_running_time, NULL);
 }
 
diff --git a/gst/gstevent.h b/gst/gstevent.h
index a58eb40..34e79e9 100644
--- a/gst/gstevent.h
+++ b/gst/gstevent.h
@@ -480,7 +480,7 @@ GstStructure *  gst_event_writable_structure    (GstEvent *event);
 GST_API
 gboolean        gst_event_has_name              (GstEvent *event, const gchar *name);
 
-GST_API
+GST_DEPRECATED_FOR(gst_event_has_name)
 gboolean        gst_event_has_name_id           (GstEvent *event, GQuark name);
 
 /* identifiers for events and messages */
diff --git a/gst/gstidstr-private.h b/gst/gstidstr-private.h
new file mode 100644
index 0000000..7b74940
--- /dev/null
+++ b/gst/gstidstr-private.h
@@ -0,0 +1,288 @@
+/* GStreamer
+ *
+ * Copyright (C) 2024 Sebastian Dröge <sebastian@centricular.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __GST_ID_STR_PRIVATE_H__
+#define __GST_ID_STR_PRIVATE_H__
+
+#include <gst/gstconfig.h>
+#include <gst/gstidstr.h>
+#include <glib-object.h>
+#include <string.h>
+
+G_BEGIN_DECLS
+
+typedef struct {
+  /* < private > */
+  union {
+    struct {
+      guint8 padding[15];
+      // t == 0: Inline-allocated short_string
+      // t == 1: Heap-allocated pointer_string that needs freeing
+      // t == 2: Statically allocated pointer_string that needs no freeing
+      guint8 t;
+    } string_type;
+    struct {
+      gchar s[16];
+      // t == 0 is the NUL terminator
+    } short_string;
+    struct {
+      gchar *s;           // to be freed if t == 1
+      guint32 len;       // Length of the string without NUL-terminator
+#if GLIB_SIZEOF_VOID_P == 8
+      guint8 padding[3]; // always zero
+#elif GLIB_SIZEOF_VOID_P == 4
+      guint8 padding[7]; // always zero
+#else
+  #error "Only 32 bit and 64 bit pointers supported currently"
+#endif
+      guint8 t; // always 1 or 2, see above
+    } pointer_string;
+  } s;
+} GstIdStrPrivate;
+
+static inline void
+_gst_id_str_init_inline (GstIdStr * s)
+{
+  GstIdStrPrivate *sp = (GstIdStrPrivate *) s;
+  memset (sp, 0, sizeof (*sp));
+}
+
+static inline gsize
+_gst_id_str_get_len (const GstIdStr * s)
+{
+  GstIdStrPrivate *sp = (GstIdStrPrivate *) s;
+
+  switch (sp->s.string_type.t) {
+    case 0:
+      return strlen (sp->s.short_string.s);
+    case 1:
+    case 2:
+      return sp->s.pointer_string.len;
+    default:
+      g_assert_not_reached ();
+      return 0;
+  }
+}
+
+static inline void
+_gst_id_str_set_with_len_inline (GstIdStr * s, const gchar * value, gsize len)
+{
+  GstIdStrPrivate *sp = (GstIdStrPrivate *) s;
+
+  g_assert (len <= G_MAXUINT32);
+
+  if (sp->s.string_type.t == 1) {
+    if (sp->s.pointer_string.s == value)
+      return;
+    g_free (sp->s.pointer_string.s);
+  }
+
+  if (len <= 15) {
+    memcpy (sp->s.short_string.s, value, len);
+    memset (&sp->s.short_string.s[len], 0, 16 - len);
+  } else {
+    sp->s.pointer_string.t = 1;
+    sp->s.pointer_string.len = len;
+    sp->s.pointer_string.s = (gchar *) g_malloc (len + 1);
+    memcpy (sp->s.pointer_string.s, value, len);
+    sp->s.pointer_string.s[len] = '\0';
+  }
+}
+
+static inline void
+_gst_id_str_set_inline (GstIdStr * s, const gchar * value)
+{
+  gsize len = strlen (value);
+  _gst_id_str_set_with_len_inline (s, value, len);
+}
+
+static inline void
+_gst_id_str_set_static_str_with_len_inline (GstIdStr * s, const gchar * value, gsize len)
+{
+  GstIdStrPrivate *sp = (GstIdStrPrivate *) s;
+
+  g_assert (len <= G_MAXUINT32);
+
+  if (sp->s.string_type.t == 1)
+    g_free (sp->s.pointer_string.s);
+
+  if (len <= 15) {
+    memcpy (sp->s.short_string.s, value, len);
+    memset (&sp->s.short_string.s[len], 0, 16 - len);
+  } else {
+    sp->s.pointer_string.t = 2;
+    sp->s.pointer_string.len = len;
+    sp->s.pointer_string.s = (gchar *) value;
+  }
+}
+
+static inline void
+_gst_id_str_set_static_str_inline (GstIdStr * s, const gchar * value)
+{
+  gsize len = strlen (value);
+  _gst_id_str_set_static_str_with_len_inline (s, value, len);
+}
+
+static inline void
+_gst_id_str_clear_inline (GstIdStr * s)
+{
+  GstIdStrPrivate *sp = (GstIdStrPrivate *) s;
+
+  if (sp->s.string_type.t == 1) {
+    g_free (sp->s.pointer_string.s);
+  }
+  memset (sp, 0, sizeof (*sp));
+}
+
+static inline void
+_gst_id_str_copy_into_inline (GstIdStr * d,
+    const GstIdStr * s)
+{
+  GstIdStrPrivate *sp = (GstIdStrPrivate *) s;
+  GstIdStrPrivate *dp = (GstIdStrPrivate *) d;
+
+  _gst_id_str_clear_inline (d);
+
+  *dp = *sp;
+  if (dp->s.string_type.t == 1) {
+#if GLIB_CHECK_VERSION (2, 68, 0)
+      dp->s.pointer_string.s = (gchar *) g_memdup2 (dp->s.pointer_string.s, dp->s.pointer_string.len + 1);
+#else
+      dp->s.pointer_string.s = (gchar *) g_memdup (dp->s.pointer_string.s, dp->s.pointer_string.len + 1);
+#endif
+  }
+}
+
+static inline void
+_gst_id_str_move_inline (GstIdStr * d,
+    GstIdStr * s)
+{
+  GstIdStrPrivate *sp = (GstIdStrPrivate *) s;
+  GstIdStrPrivate *dp = (GstIdStrPrivate *) d;
+
+  _gst_id_str_clear_inline (d);
+
+  memcpy (dp, s, sizeof (*sp));
+  memset (sp, 0, sizeof (*sp));
+}
+
+static inline GstIdStr *
+_gst_id_str_new_inline (void)
+{
+  return (GstIdStr *) g_new0 (GstIdStrPrivate, 1);
+}
+
+static inline GstIdStr *
+_gst_id_str_copy_inline (const GstIdStr * s)
+{
+  GstIdStr *copy = _gst_id_str_new_inline ();
+
+  _gst_id_str_copy_into_inline (copy, s);
+
+  return copy;
+}
+
+static inline void
+_gst_id_str_free_inline (GstIdStr * s)
+{
+  _gst_id_str_clear_inline (s);
+  g_free (s);
+}
+
+static inline const gchar *
+_gst_id_str_as_str_inline (const GstIdStr * s)
+{
+  GstIdStrPrivate *sp = (GstIdStrPrivate *) s;
+
+  switch (sp->s.string_type.t) {
+    case 0:
+      return sp->s.short_string.s;
+    case 1:
+    case 2:
+      return sp->s.pointer_string.s;
+    default:
+      g_assert_not_reached ();
+      return NULL;
+  }
+}
+
+static inline gboolean
+_gst_id_str_is_equal_inline (const GstIdStr * s1,
+    const GstIdStr * s2)
+{
+  GstIdStrPrivate *sp1 = (GstIdStrPrivate *) s1;
+  GstIdStrPrivate *sp2 = (GstIdStrPrivate *) s2;
+
+  // Covers the short_string case and equal pointer_string pointers
+  if (sp1 == sp2 || memcmp (sp1, sp2, sizeof (*sp1)) == 0)
+    return TRUE;
+
+  // If one of the strings is a short_string then they can't be equal at this
+  // point: either they're both short_strings and not the same, or one is a
+  // short_string and the other a pointer_string which would mean that they have
+  // different lengths.
+  if (sp1->s.string_type.t == 0 || sp2->s.string_type.t == 0)
+    return FALSE;
+
+  // Otherwise they're both pointer_strings
+  if (sp1->s.pointer_string.len != sp2->s.pointer_string.len)
+    return FALSE;
+  return memcmp (sp1->s.pointer_string.s, sp2->s.pointer_string.s, sp1->s.pointer_string.len) == 0;
+}
+
+static inline gboolean
+_gst_id_str_is_equal_to_str_inline (const GstIdStr * s1,
+    const gchar * s2)
+{
+  return strcmp (_gst_id_str_as_str_inline (s1), s2) == 0;
+}
+
+static inline gboolean
+_gst_id_str_is_equal_to_str_with_len_inline (const GstIdStr * s1,
+    const gchar * s2, gsize len)
+{
+  GstIdStr s2_int = GST_ID_STR_INIT;
+
+  _gst_id_str_set_static_str_with_len_inline (&s2_int, s2, len);
+  return _gst_id_str_is_equal_inline (s1, &s2_int);
+}
+
+#ifndef GST_ID_STR_DISABLE_INLINES
+#define gst_id_str_init(s) _gst_id_str_init_inline(s)
+#define gst_id_str_get_len(s) _gst_id_str_get_len(s)
+#define gst_id_str_set(s, value) _gst_id_str_set_inline(s, value)
+#define gst_id_str_set_with_len(s, value, len) _gst_id_str_set_with_len_inline(s, value, len)
+#define gst_id_str_set_static_str(s, value) _gst_id_str_set_static_str_inline(s, value)
+#define gst_id_str_set_static_str_with_len(s, value, len) _gst_id_str_set_static_str_with_len_inline(s, value, len)
+#define gst_id_str_clear(s) _gst_id_str_clear_inline(s)
+#define gst_id_str_copy(s) _gst_id_str_copy_inline(s)
+#define gst_id_str_new() _gst_id_str_new_inline()
+#define gst_id_str_free(s) _gst_id_str_free_inline(s)
+#define gst_id_str_copy_into(d, s) _gst_id_str_copy_into_inline(d, s)
+#define gst_id_str_move(d, s) _gst_id_str_move_inline(d, s)
+#define gst_id_str_is_equal(s1, s2) _gst_id_str_is_equal_inline(s1, s2)
+#define gst_id_str_is_equal_to_str(s1, s2) _gst_id_str_is_equal_to_str_inline(s1, s2)
+#define gst_id_str_is_equal_to_str_with_len(s1, s2, len) _gst_id_str_is_equal_to_str_with_len_inline(s1, s2, len)
+#define gst_id_str_as_str(s) _gst_id_str_as_str_inline(s)
+#endif
+
+G_END_DECLS
+
+#endif
diff --git a/gst/gstidstr.c b/gst/gstidstr.c
new file mode 100644
index 0000000..c8e2a9c
--- /dev/null
+++ b/gst/gstidstr.c
@@ -0,0 +1,331 @@
+/* GStreamer
+ *
+ * Copyright (C) 2024 Sebastian Dröge <sebastian@centricular.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * SECTION:gstidstr
+ * @title: GstIdStr
+ * @short_description: String type optimized for short strings
+ * @see_also: #GstStructure
+ *
+ * A #GstIdStr is string type optimized for short strings and used for structure
+ * names, structure field names and in other places.
+ *
+ * Strings up to 16 bytes (including NUL terminator) are stored inline, other
+ * strings are stored on the heap.
+ *
+ * ```cpp
+ * GstIdStr s = GST_ID_STR_INIT;
+ *
+ * gst_id_str_set (&s, "Hello, World!");
+ * g_print ("%s\n", gst_id_str_as_str (&s));
+ *
+ * gst_id_str_clear (&s);
+ * ```
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#define GST_ID_STR_DISABLE_INLINES
+
+#include "gstidstr.h"
+#include "gstidstr-private.h"
+
+G_DEFINE_BOXED_TYPE (GstIdStr, gst_id_str, gst_id_str_copy, gst_id_str_free);
+
+// Make sure the string type fields are in the same place for each variant
+// See https://developercommunity.visualstudio.com/t/C-offsetof-an-array-item-is-accepted-by/10736612
+#ifndef _MSC_VER
+G_STATIC_ASSERT (G_STRUCT_OFFSET (GstIdStrPrivate,
+        s.string_type.t) == G_STRUCT_OFFSET (GstIdStrPrivate,
+        s.short_string.s[15]));
+#endif
+G_STATIC_ASSERT (G_STRUCT_OFFSET (GstIdStrPrivate,
+        s.string_type.t) == G_STRUCT_OFFSET (GstIdStrPrivate,
+        s.pointer_string.t));
+// The overall struct should be 16 bytes large and at least pointer aligned
+G_STATIC_ASSERT (sizeof (GstIdStrPrivate) == 16);
+// See https://developercommunity.visualstudio.com/t/C-offsetof-an-array-item-is-accepted-by/10736612
+#ifndef _MSC_VER
+G_STATIC_ASSERT (G_ALIGNOF (GstIdStrPrivate) >= G_ALIGNOF (gpointer));
+// Alignment and size of the private and public type must be the same
+G_STATIC_ASSERT (G_ALIGNOF (GstIdStrPrivate) == G_ALIGNOF (GstIdStr));
+#endif
+G_STATIC_ASSERT (sizeof (GstIdStrPrivate) == sizeof (GstIdStr));
+
+/**
+ * gst_id_str_init:
+ * @s: A %GstIdStr
+ *
+ * Initializes a (usually stack-allocated) id string @s. The newly-initialized
+ * id string will contain an empty string by default as value.
+ *
+ * Since: 1.26
+ */
+void
+gst_id_str_init (GstIdStr * s)
+{
+  _gst_id_str_init_inline (s);
+}
+
+/**
+ * gst_id_str_get_len:
+ * @s: A %GstIdStr
+ *
+ * Returns the length of @s, exluding the NUL-terminator. This is equivalent to
+ * calling `strcmp()` but potentially faster.
+ *
+ * Since: 1.26
+ */
+gsize
+gst_id_str_get_len (const GstIdStr * s)
+{
+  return _gst_id_str_get_len (s);
+}
+
+/**
+ * gst_id_str_set:
+ * @s: A %GstIdStr
+ * @value: A NUL-terminated string
+ *
+ * Sets @s to the string @value.
+ *
+ * Since: 1.26
+ */
+void
+gst_id_str_set (GstIdStr * s, const gchar * value)
+{
+  _gst_id_str_set_inline (s, value);
+}
+
+/**
+ * gst_id_str_set_with_len:
+ * @s: A %GstIdStr
+ * @value: A string
+ * @len: Length of the string
+ *
+ * Sets @s to the string @value of length @len. @value does not have to be
+ * NUL-terminated and @len should not include the NUL-terminator.
+ *
+ * Since: 1.26
+ */
+void
+gst_id_str_set_with_len (GstIdStr * s, const gchar * value, gsize len)
+{
+  _gst_id_str_set_with_len_inline (s, value, len);
+}
+
+/**
+ * gst_id_str_set_static_str:
+ * @s: A %GstIdStr
+ * @value: A NUL-terminated string
+ *
+ * Sets @s to the string @value. @value needs to be valid for the remaining
+ * lifetime of the process, e.g. has to be a static string.
+ *
+ * Since: 1.26
+ */
+void
+gst_id_str_set_static_str (GstIdStr * s, const gchar * value)
+{
+  _gst_id_str_set_static_str_inline (s, value);
+}
+
+/**
+ * gst_id_str_set_static_str_with_len:
+ * @s: A %GstIdStr
+ * @value: A string
+ * @len: Length of the string
+ *
+ * Sets @s to the string @value of length @len. @value needs to be valid for the
+ * remaining lifetime of the process, e.g. has to be a static string.
+ *
+ * @value must be NUL-terminated and @len should not include the
+ * NUL-terminator.
+ *
+ * Since: 1.26
+ */
+void
+gst_id_str_set_static_str_with_len (GstIdStr * s, const gchar * value,
+    gsize len)
+{
+  _gst_id_str_set_static_str_with_len_inline (s, value, len);
+}
+
+/**
+ * gst_id_str_clear:
+ * @s: A %GstIdStr
+ *
+ * Clears @s and sets it to the empty string.
+ *
+ * Since: 1.26
+ */
+void
+gst_id_str_clear (GstIdStr * s)
+{
+  _gst_id_str_clear_inline (s);
+}
+
+/**
+ * gst_id_str_copy:
+ * @s: A %GstIdStr
+ *
+ * Copies @s into newly allocated heap memory.
+ *
+ * Returns: (transfer full): A heap-allocated copy of @s.
+ *
+ * Since: 1.26
+ */
+GstIdStr *
+gst_id_str_copy (const GstIdStr * s)
+{
+  return _gst_id_str_copy_inline (s);
+}
+
+/**
+ * gst_id_str_new:
+ *
+ * Returns a newly heap allocated empty string.
+ *
+ * Returns: (transfer full): A heap-allocated string.
+ *
+ * Since: 1.26
+ */
+GstIdStr *
+gst_id_str_new (void)
+{
+  return _gst_id_str_new_inline ();
+}
+
+/**
+ * gst_id_str_free:
+ * @s: A heap allocated %GstIdStr
+ *
+ * Frees @s. This should only be called for heap-allocated #GstIdStr.
+ *
+ * Since: 1.26
+ */
+void
+gst_id_str_free (GstIdStr * s)
+{
+  _gst_id_str_free_inline (s);
+}
+
+/**
+ * gst_id_str_copy_into:
+ * @d: The destination %GstIdStr
+ * @s: The source %GstIdStr
+ *
+ * Copies @s into @d.
+ *
+ * Since: 1.26
+ */
+void
+gst_id_str_copy_into (GstIdStr * d, const GstIdStr * s)
+{
+  _gst_id_str_copy_into_inline (d, s);
+}
+
+/**
+ * gst_id_str_move:
+ * @d: The destination %GstIdStr
+ * @s: The source %GstIdStr
+ *
+ * Moves @s into @d and resets @s.
+ *
+ * Since: 1.26
+ */
+void
+gst_id_str_move (GstIdStr * d, GstIdStr * s)
+{
+  _gst_id_str_move_inline (d, s);
+}
+
+/**
+ * gst_id_str_is_equal:
+ * @s1: A %GstIdStr
+ * @s2: A %GstIdStr
+ *
+ * Compares @s1 and @s2 for equality.
+ *
+ * Returns: %TRUE if @s1 and @s2 are equal.
+ *
+ * Since: 1.26
+ */
+gboolean
+gst_id_str_is_equal (const GstIdStr * s1, const GstIdStr * s2)
+{
+  return _gst_id_str_is_equal_inline (s1, s2);
+}
+
+/**
+ * gst_id_str_is_equal_to_str:
+ * @s1: A %GstIdStr
+ * @s2: A string
+ *
+ * Compares @s1 and @s2 for equality.
+ *
+ * Returns: %TRUE if @s1 and @s2 are equal.
+ *
+ * Since: 1.26
+ */
+gboolean
+gst_id_str_is_equal_to_str (const GstIdStr * s1, const gchar * s2)
+{
+  return _gst_id_str_is_equal_to_str_inline (s1, s2);
+}
+
+/**
+ * gst_id_str_is_equal_to_str_with_len:
+ * @s1: A %GstIdStr
+ * @s2: A string
+ * @len: Length of @s2.
+ *
+ * Compares @s1 and @s2 with length @len for equality. @s2 does not have to be
+ * NUL-terminated and @len should not include the NUL-terminator.
+ *
+ * This is generally faster than gst_id_str_is_equal_to_str() if the length is
+ * already known.
+ *
+ * Returns: %TRUE if @s1 and @s2 are equal.
+ *
+ * Since: 1.26
+ */
+gboolean
+gst_id_str_is_equal_to_str_with_len (const GstIdStr * s1, const gchar * s2,
+    gsize len)
+{
+  return _gst_id_str_is_equal_to_str_with_len_inline (s1, s2, len);
+}
+
+/**
+ * gst_id_str_as_str:
+ * @s: A %GstIdStr
+ *
+ * Returns: the NUL-terminated string representation of @s.
+ *
+ * Since: 1.26
+ */
+const gchar *
+gst_id_str_as_str (const GstIdStr * s)
+{
+  return _gst_id_str_as_str_inline (s);
+}
diff --git a/gst/gstidstr.h b/gst/gstidstr.h
new file mode 100644
index 0000000..1bf951e
--- /dev/null
+++ b/gst/gstidstr.h
@@ -0,0 +1,114 @@
+/* GStreamer
+ *
+ * Copyright (C) 2024 Sebastian Dröge <sebastian@centricular.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __GST_ID_STR_H__
+#define __GST_ID_STR_H__
+
+#include <gst/gstconfig.h>
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+/**
+ * GstIdStr:
+ *
+ * String type optimized for short strings.
+ *
+ * Strings are usually stack- or inline-allocated, and for short strings smaller
+ * than 16 bytes (including NUL terminator) no heap allocations are performed.
+ *
+ * Since: 1.26
+ */
+typedef struct {
+  /* < private > */
+  gpointer pointer;
+#if GLIB_SIZEOF_VOID_P == 8
+  guint8 padding[8];
+#elif GLIB_SIZEOF_VOID_P == 4
+  guint8 padding[12];
+#else
+  #error "Only 32 bit and 64 bit pointers supported currently"
+#endif
+} GstIdStr;
+
+/**
+ * GST_ID_STR_INIT:
+ *
+ * Initializer for #GstIdStr.
+ *
+ * Since: 1.26
+ */
+#define GST_ID_STR_INIT { .pointer = NULL, .padding = {0, } }
+
+GST_API
+GType gst_id_str_get_type (void);
+
+GST_API
+gsize gst_id_str_get_len (const GstIdStr *s) G_GNUC_PURE;
+
+GST_API
+void gst_id_str_set (GstIdStr *s, const gchar *value);
+
+GST_API
+void gst_id_str_set_with_len (GstIdStr *s, const gchar *value, gsize len);
+
+GST_API
+void gst_id_str_set_static_str (GstIdStr *s, const gchar *value);
+
+GST_API
+void gst_id_str_set_static_str_with_len (GstIdStr *s, const gchar *value, gsize len);
+
+GST_API
+void gst_id_str_init (GstIdStr *s);
+
+GST_API
+void gst_id_str_clear (GstIdStr *s);
+
+GST_API
+GstIdStr * gst_id_str_new (void) G_GNUC_MALLOC;
+
+GST_API
+GstIdStr * gst_id_str_copy (const GstIdStr *s) G_GNUC_MALLOC;
+
+GST_API
+void gst_id_str_free (GstIdStr *s);
+
+GST_API
+void gst_id_str_copy_into (GstIdStr *d, const GstIdStr *s);
+
+GST_API
+void gst_id_str_move (GstIdStr *d, GstIdStr *s);
+
+GST_API
+const gchar * gst_id_str_as_str (const GstIdStr *s) G_GNUC_PURE;
+
+GST_API
+gboolean gst_id_str_is_equal (const GstIdStr *s1, const GstIdStr *s2) G_GNUC_PURE;
+
+GST_API
+gboolean gst_id_str_is_equal_to_str (const GstIdStr *s1, const gchar *s2) G_GNUC_PURE;
+
+GST_API
+gboolean gst_id_str_is_equal_to_str_with_len (const GstIdStr *s1, const gchar *s2, gsize len) G_GNUC_PURE;
+
+G_END_DECLS
+
+#endif
+
diff --git a/gst/gstinfo.c b/gst/gstinfo.c
index 4e61dcd..47df87c 100644
--- a/gst/gstinfo.c
+++ b/gst/gstinfo.c
@@ -101,9 +101,9 @@
 
 #include "gst_private.h"
 #include "gstutils.h"
-#include "gstquark.h"
 #include "gstsegment.h"
 #include "gstvalue.h"
+#include "gstvecdeque.h"
 #include "gstcapsfeatures.h"
 
 #endif /* GST_DISABLE_GST_DEBUG */
@@ -343,7 +343,7 @@ typedef struct
   GDestroyNotify notify;
 }
 LogFuncEntry;
-static GMutex __log_func_mutex;
+static GRWLock __log_func_mutex;
 static GSList *__log_functions = NULL;
 
 /* whether to add the default log function in gst_init() */
@@ -614,6 +614,7 @@ gst_debug_log_full_valist (GstDebugCategory * category, GstDebugLevel level,
 
   G_VA_COPY (message.arguments, args);
 
+  g_rw_lock_reader_lock (&__log_func_mutex);
   handler = __log_functions;
   while (handler) {
     entry = handler->data;
@@ -621,6 +622,8 @@ gst_debug_log_full_valist (GstDebugCategory * category, GstDebugLevel level,
     entry->func (category, level, file, function, line, object, &message,
         entry->user_data);
   }
+  g_rw_lock_reader_unlock (&__log_func_mutex);
+
   g_free (message.message);
   if (message.free_object_id)
     g_free (message.object_id);
@@ -706,6 +709,7 @@ gst_debug_log_literal_full (GstDebugCategory * category, GstDebugLevel level,
   message.object_id = (gchar *) id;
   message.free_object_id = FALSE;
 
+  g_rw_lock_reader_lock (&__log_func_mutex);
   handler = __log_functions;
   while (handler) {
     entry = handler->data;
@@ -713,6 +717,7 @@ gst_debug_log_literal_full (GstDebugCategory * category, GstDebugLevel level,
     entry->func (category, level, file, function, line, object, &message,
         entry->user_data);
   }
+  g_rw_lock_reader_unlock (&__log_func_mutex);
 
   if (message.free_object_id)
     g_free (message.object_id);
@@ -902,7 +907,7 @@ gst_info_structure_to_string (const GstStructure * s)
 {
   if (G_LIKELY (s)) {
     gchar *str = gst_structure_to_string (s);
-    if (G_UNLIKELY (pretty_tags && s->name == GST_QUARK (TAGLIST)))
+    if (G_UNLIKELY (pretty_tags && gst_structure_has_name (s, "taglist")))
       return prettify_structure_string (str);
     else
       return str;
@@ -1061,8 +1066,27 @@ gst_info_describe_stream_collection (GstStreamCollection * collection)
   return ret;
 }
 
-static gchar *
-gst_debug_print_object (gpointer ptr)
+/**
+ * gst_debug_print_object:
+ * @ptr: (nullable): the object
+ *
+ * Returns a string that represents @ptr. This is safe to call with
+ * %GstStructure, %GstCapsFeatures, %GstMiniObject s (e.g. %GstCaps,
+ * %GstBuffer or %GstMessage), and %GObjects (e.g. %GstElement or %GstPad).
+ *
+ * The string representation is meant to be used for debugging purposes and
+ * might change between GStreamer versions.
+ *
+ * Passing other kind of pointers might or might not work and is generally
+ * unsafe to do.
+ *
+ * Returns: (transfer full) (type gchar*): a string containing a string
+ *     representation of the object
+ *
+ * Since: 1.26
+ */
+gchar *
+gst_debug_print_object (gconstpointer ptr)
 {
   GObject *object = (GObject *) ptr;
 
@@ -1158,11 +1182,23 @@ gst_debug_print_object (gpointer ptr)
   return g_strdup_printf ("%p", ptr);
 }
 
-static gchar *
-gst_debug_print_segment (gpointer ptr)
+/**
+ * gst_debug_print_segment:
+ * @segment: (nullable): the %GstSegment
+ *
+ * Returns a string that represents @segments.
+ *
+ * The string representation is meant to be used for debugging purposes and
+ * might change between GStreamer versions.
+ *
+ * Returns: (transfer full) (type gchar*): a string containing a string
+ *     representation of the segment
+ *
+ * Since: 1.26
+ */
+gchar *
+gst_debug_print_segment (const GstSegment * segment)
 {
-  GstSegment *segment = (GstSegment *) ptr;
-
   /* nicely printed segment */
   if (segment == NULL) {
     return g_strdup ("(NULL)");
@@ -1714,7 +1750,6 @@ gst_debug_add_log_function (GstLogFunction func, gpointer user_data,
     GDestroyNotify notify)
 {
   LogFuncEntry *entry;
-  GSList *list;
 
   if (func == NULL)
     func = gst_debug_log_default;
@@ -1723,16 +1758,9 @@ gst_debug_add_log_function (GstLogFunction func, gpointer user_data,
   entry->func = func;
   entry->user_data = user_data;
   entry->notify = notify;
-  /* FIXME: we leak the old list here - other threads might access it right now
-   * in gst_debug_logv. Another solution is to lock the mutex in gst_debug_logv,
-   * but that is waaay costly.
-   * It'd probably be clever to use some kind of RCU here, but I don't know
-   * anything about that.
-   */
-  g_mutex_lock (&__log_func_mutex);
-  list = g_slist_copy (__log_functions);
-  __log_functions = g_slist_prepend (list, entry);
-  g_mutex_unlock (&__log_func_mutex);
+  g_rw_lock_writer_lock (&__log_func_mutex);
+  __log_functions = g_slist_prepend (__log_functions, entry);
+  g_rw_lock_writer_unlock (&__log_func_mutex);
 
   if (gst_is_initialized ())
     GST_DEBUG ("prepended log function %p (user data %p) to log functions",
@@ -1759,26 +1787,16 @@ static guint
 gst_debug_remove_with_compare_func (GCompareFunc func, gpointer data)
 {
   GSList *found;
-  GSList *new, *cleanup = NULL;
+  GSList *cleanup = NULL;
   guint removals = 0;
 
-  g_mutex_lock (&__log_func_mutex);
-  new = __log_functions;
-  cleanup = NULL;
-  while ((found = g_slist_find_custom (new, data, func))) {
-    if (new == __log_functions) {
-      /* make a copy when we have the first hit, so that we modify the copy and
-       * make that the new list later */
-      new = g_slist_copy (new);
-      continue;
-    }
+  g_rw_lock_writer_lock (&__log_func_mutex);
+  while ((found = g_slist_find_custom (__log_functions, data, func))) {
     cleanup = g_slist_prepend (cleanup, found->data);
-    new = g_slist_delete_link (new, found);
+    __log_functions = g_slist_delete_link (__log_functions, found);
     removals++;
   }
-  /* FIXME: We leak the old list here. See _add_log_function for why. */
-  __log_functions = new;
-  g_mutex_unlock (&__log_func_mutex);
+  g_rw_lock_writer_unlock (&__log_func_mutex);
 
   while (cleanup) {
     LogFuncEntry *entry = cleanup->data;
@@ -2538,7 +2556,7 @@ _priv_gst_debug_cleanup (void)
 
   clear_level_names ();
 
-  g_mutex_lock (&__log_func_mutex);
+  g_rw_lock_writer_lock (&__log_func_mutex);
   while (__log_functions) {
     LogFuncEntry *log_func_entry = __log_functions->data;
     if (log_func_entry->notify)
@@ -2546,7 +2564,7 @@ _priv_gst_debug_cleanup (void)
     g_free (log_func_entry);
     __log_functions = g_slist_delete_link (__log_functions, __log_functions);
   }
-  g_mutex_unlock (&__log_func_mutex);
+  g_rw_lock_writer_unlock (&__log_func_mutex);
 }
 
 static void
@@ -3521,7 +3539,7 @@ typedef struct
   gint64 last_use;
   GThread *thread;
 
-  GQueue log;
+  GstVecDeque *log;
   gsize log_size;
 } GstRingBufferLog;
 
@@ -3592,8 +3610,9 @@ gst_ring_buffer_logger_log (GstDebugCategory * category,
         break;
 
       g_hash_table_remove (logger->thread_index, log->thread);
-      while ((buf = g_queue_pop_head (&log->log)))
+      while ((buf = gst_vec_deque_pop_head (log->log)))
         g_free (buf);
+      gst_vec_deque_free (log->log);
       g_free (log);
       g_queue_pop_tail (&logger->threads);
     }
@@ -3604,7 +3623,7 @@ gst_ring_buffer_logger_log (GstDebugCategory * category,
   log = g_hash_table_lookup (logger->thread_index, thread);
   if (!log) {
     log = g_new0 (GstRingBufferLog, 1);
-    g_queue_init (&log->log);
+    log->log = gst_vec_deque_new (2048);
     log->log_size = 0;
     g_queue_push_head (&logger->threads, log);
     log->link = logger->threads.head;
@@ -3619,20 +3638,12 @@ gst_ring_buffer_logger_log (GstDebugCategory * category,
   if (output_len < logger->max_size_per_thread) {
     gchar *buf;
 
-    /* While using a GQueue here is not the most efficient thing to do, we
-     * have to allocate a string for every output anyway and could just store
-     * that instead of copying it to an actual ringbuffer.
-     * Better than GQueue would be GstQueueArray, but that one is in
-     * libgstbase and we can't use it here. That one allocation will not make
-     * much of a difference anymore, considering the number of allocations
-     * needed to get to this point...
-     */
     while (log->log_size + output_len > logger->max_size_per_thread) {
-      buf = g_queue_pop_head (&log->log);
+      buf = gst_vec_deque_pop_head (log->log);
       log->log_size -= strlen (buf);
       g_free (buf);
     }
-    g_queue_push_tail (&log->log, output);
+    gst_vec_deque_push_tail (log->log, output);
     log->log_size += output_len;
   } else {
     gchar *buf;
@@ -3640,7 +3651,7 @@ gst_ring_buffer_logger_log (GstDebugCategory * category,
     /* Can't really write anything as the line is bigger than the maximum
      * allowed log size already, so just remove everything */
 
-    while ((buf = g_queue_pop_head (&log->log)))
+    while ((buf = gst_vec_deque_pop_head (log->log)))
       g_free (buf);
     g_free (output);
     log->log_size = 0;
@@ -3673,16 +3684,17 @@ gst_debug_ring_buffer_logger_get_logs (void)
   tmp = logs = g_new0 (gchar *, ring_buffer_logger->threads.length + 1);
   for (l = ring_buffer_logger->threads.head; l; l = l->next) {
     GstRingBufferLog *log = l->data;
-    GList *l;
     gchar *p;
-    gsize len;
+    gsize n_lines, line_len;
 
     *tmp = p = g_new0 (gchar, log->log_size + 1);
 
-    for (l = log->log.head; l; l = l->next) {
-      len = strlen (l->data);
-      memcpy (p, l->data, len);
-      p += len;
+    n_lines = gst_vec_deque_get_length (log->log);
+    for (gsize i = 0; i < n_lines; i++) {
+      const gchar *line = gst_vec_deque_peek_nth (log->log, i);
+      line_len = strlen (line);
+      memcpy (p, line, line_len);
+      p += line_len;
     }
 
     tmp++;
@@ -3702,7 +3714,7 @@ gst_ring_buffer_logger_free (GstRingBufferLogger * logger)
 
     while ((log = g_queue_pop_head (&logger->threads))) {
       gchar *buf;
-      while ((buf = g_queue_pop_head (&log->log)))
+      while ((buf = gst_vec_deque_pop_head (log->log)))
         g_free (buf);
       g_free (log);
     }
diff --git a/gst/gstinfo.h b/gst/gstinfo.h
index 416bd7c..fb392f3 100644
--- a/gst/gstinfo.h
+++ b/gst/gstinfo.h
@@ -27,6 +27,7 @@
 #include <glib.h>
 #include <glib-object.h>
 #include <gst/gstconfig.h>
+#include <gst/gstsegment.h>
 
 G_BEGIN_DECLS
 
@@ -553,6 +554,12 @@ GST_API
 GSList *        gst_debug_get_all_categories	(void);
 
 
+GST_API
+gchar * gst_debug_print_object  (gconstpointer ptr);
+
+GST_API
+gchar * gst_debug_print_segment (const GstSegment *segment);
+
 GST_API
 gchar * gst_debug_construct_term_color (guint colorinfo);
 
diff --git a/gst/gstiterator.c b/gst/gstiterator.c
index 6d469d7..b5fbb90 100644
--- a/gst/gstiterator.c
+++ b/gst/gstiterator.c
@@ -530,7 +530,7 @@ filter_free (GstIteratorFilter * it)
  * gst_iterator_filter:
  * @it: The #GstIterator to filter
  * @func: (scope call): the compare function to select elements
- * @user_data: (closure): user data passed to the compare function
+ * @user_data: user data passed to the compare function
  *
  * Create a new iterator from an existing iterator. The new iterator
  * will only return those elements that match the given compare function @func.
@@ -579,9 +579,9 @@ gst_iterator_filter (GstIterator * it, GCompareFunc func,
 /**
  * gst_iterator_fold:
  * @it: The #GstIterator to fold over
- * @func: (scope call): the fold function
+ * @func: (scope call) (closure user_data): the fold function
  * @ret: the seed value passed to the fold function
- * @user_data: (closure): user data passed to the fold function
+ * @user_data: user data passed to the fold function
  *
  * Folds @func over the elements of @iter. That is to say, @func will be called
  * as @func (object, @ret, @user_data) for each object in @it. The normal use
@@ -652,8 +652,8 @@ foreach_fold_func (const GValue * item, GValue * unused, ForeachFoldData * data)
 /**
  * gst_iterator_foreach:
  * @it: The #GstIterator to iterate
- * @func: (scope call): the function to call for each element.
- * @user_data: (closure): user data passed to the function
+ * @func: (scope call) (closure user_data): the function to call for each element.
+ * @user_data: user data passed to the function
  *
  * Iterate over all element of @it and call the given function @func for
  * each element.
@@ -699,9 +699,9 @@ find_custom_fold_func (const GValue * item, GValue * ret,
 /**
  * gst_iterator_find_custom:
  * @it: The #GstIterator to iterate
- * @func: (scope call): the compare function to use
+ * @func: (scope call) (closure user_data): the compare function to use
  * @elem: (out): pointer to a #GValue where to store the result
- * @user_data: (closure): user data passed to the compare function
+ * @user_data: user data passed to the compare function
  *
  * Find the first element in @it that matches the compare function @func.
  * @func should return 0 when the element is found. The first parameter
diff --git a/gst/gstmemory.c b/gst/gstmemory.c
index 10d724b..c189457 100644
--- a/gst/gstmemory.c
+++ b/gst/gstmemory.c
@@ -95,7 +95,9 @@ _gst_memory_free (GstMemory * mem)
 
   allocator = mem->allocator;
 
+  GST_TRACER_MEMORY_FREE_PRE (mem);
   gst_allocator_free (allocator, mem);
+  GST_TRACER_MEMORY_FREE_POST (mem);
 
   gst_object_unref (allocator);
 }
@@ -139,6 +141,7 @@ gst_memory_init (GstMemory * mem, GstMemoryFlags flags,
   GST_CAT_DEBUG (GST_CAT_MEMORY, "new memory %p, maxsize:%" G_GSIZE_FORMAT
       " offset:%" G_GSIZE_FORMAT " size:%" G_GSIZE_FORMAT, mem, maxsize,
       offset, size);
+  GST_TRACER_MEMORY_INIT (mem);
 }
 
 /**
diff --git a/gst/gstmessage.c b/gst/gstmessage.c
index f2dd883..a82dea7 100644
--- a/gst/gstmessage.c
+++ b/gst/gstmessage.c
@@ -46,13 +46,11 @@
 #define GST_DISABLE_MINIOBJECT_INLINE_FUNCTIONS
 #include "gst_private.h"
 #include <string.h>             /* memcpy */
-#include "gsterror.h"
 #include "gstenumtypes.h"
 #include "gstinfo.h"
 #include "gstmessage.h"
 #include "gsttaglist.h"
 #include "gstutils.h"
-#include "gstquark.h"
 #include "gstvalue.h"
 
 
@@ -116,8 +114,6 @@ static GstMessageQuarks message_quarks[] = {
   {0, NULL, 0}
 };
 
-static GQuark details_quark = 0;
-
 GType _gst_message_type = 0;
 GST_DEFINE_MINI_OBJECT_TYPE (GstMessage, gst_message);
 
@@ -132,7 +128,6 @@ _priv_gst_message_initialize (void)
     message_quarks[i].quark =
         g_quark_from_static_string (message_quarks[i].name);
   }
-  details_quark = g_quark_from_static_string ("details");
 
   _gst_message_type = gst_message_get_type ();
 }
@@ -399,6 +394,134 @@ gst_message_new_eos (GstObject * src)
   return message;
 }
 
+/* Internal function for setting details on a message. Checks for valid
+ * arguments should be done before calling this.
+ *
+ * Will create a message structure if it doesn't have one already
+ **/
+static void
+message_set_details (GstMessage * message, GstStructure * details)
+{
+  GValue v = G_VALUE_INIT;
+
+  if (GST_MESSAGE_STRUCTURE (message) == NULL) {
+    const gchar *message_name = gst_message_type_get_name (message->type);
+    g_return_if_fail (message_name);
+    GstStructure *structure = gst_structure_new_static_str_empty (message_name);
+    gst_structure_set_parent_refcount (structure,
+        &message->mini_object.refcount);
+    GST_MESSAGE_STRUCTURE (message) = structure;
+  }
+  g_value_init (&v, GST_TYPE_STRUCTURE);
+  g_value_take_boxed (&v, details);
+  gst_structure_take_value (GST_MESSAGE_STRUCTURE (message), "details", &v);
+}
+
+/**
+ * gst_message_set_details:
+ * @message: A #GstMessage
+ * @details: (transfer full) (nullable): A GstStructure with details
+ *
+ * Add @details to @message. Will fail if the message already has details set on
+ * it or if it is not writable.
+ *
+ * Since: 1.26
+ */
+void
+gst_message_set_details (GstMessage * message, GstStructure * details)
+{
+  g_return_if_fail (GST_IS_MESSAGE (message));
+  g_return_if_fail (gst_message_is_writable (message));
+  g_return_if_fail (details);
+
+  if (GST_MESSAGE_STRUCTURE (message)
+      && gst_structure_has_field (GST_MESSAGE_STRUCTURE (message), "details")) {
+    gst_structure_free (details);
+    g_critical ("Message already has details");
+    return;
+  }
+
+  message_set_details (message, details);
+}
+
+/* Internal function for parsing details of a message.
+ * Checks for valid arguments should be done before calling this.
+ *
+ * Will create a details structure if create_if_missing is TRUE
+ */
+static void
+message_parse_details (GstMessage * message, GstStructure ** details,
+    gboolean create_if_missing)
+{
+  *details = NULL;
+
+  if (GST_MESSAGE_STRUCTURE (message) == NULL && !create_if_missing)
+    return;
+
+  if (GST_MESSAGE_STRUCTURE (message) &&
+      gst_structure_has_field (GST_MESSAGE_STRUCTURE (message), "details")) {
+    const GValue *v = gst_structure_get_value (GST_MESSAGE_STRUCTURE (message),
+        "details");
+    if (v && G_VALUE_TYPE (v) == GST_TYPE_STRUCTURE) {
+      *details = g_value_get_boxed (v);
+    }
+  } else if (create_if_missing) {
+    *details = gst_structure_new_static_str_empty ("message-details");
+    message_set_details (message, (GstStructure *) * details);
+  }
+}
+
+/**
+ * gst_message_get_details:
+ * @message: A #GstMessage
+ *
+ * Returns the optional details structure of the message. May be NULL if none.
+ *
+ * The returned structure must not be freed.
+ *
+ * Returns: (transfer none) (nullable): The details, or NULL if none.
+ *
+ * Since: 1.26
+ */
+const GstStructure *
+gst_message_get_details (GstMessage * message)
+{
+  const GstStructure *details;
+
+  g_return_val_if_fail (GST_IS_MESSAGE (message), NULL);
+
+  message_parse_details (message, (GstStructure **) & details, FALSE);
+
+  return details;
+}
+
+/**
+ * gst_message_writable_details:
+ * @message: A writable #GstMessage
+ *
+ * Returns the details structure of the @message. If not present it will be
+ * created. Use this function (instead of gst_message_get_details()) if you
+ * want to write to the @details structure.
+ *
+ * The returned structure must not be freed.
+ *
+ * Returns: (transfer none): The details
+ *
+ * Since: 1.26
+ */
+GstStructure *
+gst_message_writable_details (GstMessage * message)
+{
+  GstStructure *details;
+
+  g_return_val_if_fail (GST_IS_MESSAGE (message), NULL);
+  g_return_val_if_fail (gst_message_is_writable (message), NULL);
+
+  message_parse_details (message, &details, TRUE);
+
+  return details;
+}
+
 /**
  * gst_message_new_error_with_details:
  * @src: (transfer none) (nullable): The object originating the message.
@@ -428,17 +551,11 @@ gst_message_new_error_with_details (GstObject * src, GError * error,
         "string is not valid UTF-8. Please file a bug.");
   }
 
-  structure = gst_structure_new_id (GST_QUARK (MESSAGE_ERROR),
-      GST_QUARK (GERROR), G_TYPE_ERROR, error,
-      GST_QUARK (DEBUG), G_TYPE_STRING, debug, NULL);
+  structure = gst_structure_new_static_str ("GstMessageError",
+      "gerror", G_TYPE_ERROR, error, "debug", G_TYPE_STRING, debug, NULL);
   message = gst_message_new_custom (GST_MESSAGE_ERROR, src, structure);
   if (details) {
-    GValue v = G_VALUE_INIT;
-
-    g_value_init (&v, GST_TYPE_STRUCTURE);
-    g_value_take_boxed (&v, details);
-    gst_structure_id_take_value (GST_MESSAGE_STRUCTURE (message), details_quark,
-        &v);
+    message_set_details (message, details);
   }
 
   return message;
@@ -479,18 +596,33 @@ void
 gst_message_parse_error_details (GstMessage * message,
     const GstStructure ** structure)
 {
-  const GValue *v;
+  g_return_if_fail (GST_IS_MESSAGE (message));
+  g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_ERROR);
+  g_return_if_fail (structure != NULL);
 
+  message_parse_details (message, (GstStructure **) structure, FALSE);
+}
+
+/**
+ * gst_message_parse_error_writable_details:
+ * @message: The writable message object
+ * @structure: (optional) (nullable) (transfer none) (out): A pointer to the returned details
+ *
+ * Returns the details structure if present or will create one if not present.
+ * The returned structure must not be freed.
+ *
+ * Since: 1.26
+ */
+void
+gst_message_parse_error_writable_details (GstMessage * message,
+    GstStructure ** structure)
+{
   g_return_if_fail (GST_IS_MESSAGE (message));
   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_ERROR);
+  g_return_if_fail (gst_message_is_writable (message));
   g_return_if_fail (structure != NULL);
 
-  *structure = NULL;
-  v = gst_structure_id_get_value (GST_MESSAGE_STRUCTURE (message),
-      details_quark);
-  if (v) {
-    *structure = g_value_get_boxed (v);
-  }
+  message_parse_details (message, (GstStructure **) structure, TRUE);
 }
 
 /**
@@ -520,17 +652,11 @@ gst_message_new_warning_with_details (GstObject * src, GError * error,
         "string is not valid UTF-8. Please file a bug.");
   }
 
-  structure = gst_structure_new_id (GST_QUARK (MESSAGE_WARNING),
-      GST_QUARK (GERROR), G_TYPE_ERROR, error,
-      GST_QUARK (DEBUG), G_TYPE_STRING, debug, NULL);
+  structure = gst_structure_new_static_str ("GstMessageWarning",
+      "gerror", G_TYPE_ERROR, error, "debug", G_TYPE_STRING, debug, NULL);
   message = gst_message_new_custom (GST_MESSAGE_WARNING, src, structure);
   if (details) {
-    GValue v = G_VALUE_INIT;
-
-    g_value_init (&v, GST_TYPE_STRUCTURE);
-    g_value_take_boxed (&v, details);
-    gst_structure_id_take_value (GST_MESSAGE_STRUCTURE (message), details_quark,
-        &v);
+    message_set_details (message, details);
   }
 
   return message;
@@ -569,18 +695,33 @@ void
 gst_message_parse_warning_details (GstMessage * message,
     const GstStructure ** structure)
 {
-  const GValue *v;
+  g_return_if_fail (GST_IS_MESSAGE (message));
+  g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_WARNING);
+  g_return_if_fail (structure != NULL);
+
+  message_parse_details (message, (GstStructure **) structure, FALSE);
+}
 
+/**
+ * gst_message_parse_warning_writable_details:
+ * @message: The writable message object
+ * @structure: (optional) (nullable) (transfer none) (out): A pointer to the returned details
+ *
+ * Returns the details structure if present or will create one if not present.
+ * The returned structure must not be freed.
+ *
+ * Since: 1.26
+ */
+void
+gst_message_parse_warning_writable_details (GstMessage * message,
+    GstStructure ** structure)
+{
   g_return_if_fail (GST_IS_MESSAGE (message));
   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_WARNING);
+  g_return_if_fail (gst_message_is_writable (message));
   g_return_if_fail (structure != NULL);
 
-  *structure = NULL;
-  v = gst_structure_id_get_value (GST_MESSAGE_STRUCTURE (message),
-      details_quark);
-  if (v) {
-    *structure = g_value_get_boxed (v);
-  }
+  message_parse_details (message, (GstStructure **) structure, TRUE);
 }
 
 /**
@@ -610,17 +751,11 @@ gst_message_new_info_with_details (GstObject * src, GError * error,
         "string is not valid UTF-8. Please file a bug.");
   }
 
-  structure = gst_structure_new_id (GST_QUARK (MESSAGE_INFO),
-      GST_QUARK (GERROR), G_TYPE_ERROR, error,
-      GST_QUARK (DEBUG), G_TYPE_STRING, debug, NULL);
+  structure = gst_structure_new_static_str ("GstMessageInfo",
+      "gerror", G_TYPE_ERROR, error, "debug", G_TYPE_STRING, debug, NULL);
   message = gst_message_new_custom (GST_MESSAGE_INFO, src, structure);
   if (details) {
-    GValue v = G_VALUE_INIT;
-
-    g_value_init (&v, GST_TYPE_STRUCTURE);
-    g_value_take_boxed (&v, details);
-    gst_structure_id_take_value (GST_MESSAGE_STRUCTURE (message), details_quark,
-        &v);
+    message_set_details (message, details);
   }
 
   return message;
@@ -659,18 +794,33 @@ void
 gst_message_parse_info_details (GstMessage * message,
     const GstStructure ** structure)
 {
-  const GValue *v;
+  g_return_if_fail (GST_IS_MESSAGE (message));
+  g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_INFO);
+  g_return_if_fail (structure != NULL);
+
+  message_parse_details (message, (GstStructure **) structure, FALSE);
+}
 
+/**
+ * gst_message_parse_info_writable_details:
+ * @message: The writable message object
+ * @structure: (optional) (nullable) (transfer none) (out): A pointer to the returned details
+ *
+ * Returns the details structure if present or will create one if not present.
+ * The returned structure must not be freed.
+ *
+ * Since: 1.26
+ */
+void
+gst_message_parse_info_writable_details (GstMessage * message,
+    GstStructure ** structure)
+{
   g_return_if_fail (GST_IS_MESSAGE (message));
   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_INFO);
+  g_return_if_fail (gst_message_is_writable (message));
   g_return_if_fail (structure != NULL);
 
-  *structure = NULL;
-  v = gst_structure_id_get_value (GST_MESSAGE_STRUCTURE (message),
-      details_quark);
-  if (v) {
-    *structure = g_value_get_boxed (v);
-  }
+  message_parse_details (message, (GstStructure **) structure, TRUE);
 }
 
 /**
@@ -694,10 +844,10 @@ gst_message_new_tag (GstObject * src, GstTagList * tag_list)
 
   g_return_val_if_fail (GST_IS_TAG_LIST (tag_list), NULL);
 
-  s = gst_structure_new_id_empty (GST_QUARK (MESSAGE_TAG));
+  s = gst_structure_new_static_str_empty ("GstMessageTag");
   g_value_init (&val, GST_TYPE_TAG_LIST);
   g_value_take_boxed (&val, tag_list);
-  gst_structure_id_take_value (s, GST_QUARK (TAGLIST), &val);
+  gst_structure_take_value (s, "taglist", &val);
   message = gst_message_new_custom (GST_MESSAGE_TAG, src, s);
   return message;
 }
@@ -733,12 +883,12 @@ gst_message_new_buffering (GstObject * src, gint percent)
 
   buffering_left = (percent == 100 ? 0 : -1);
 
-  structure = gst_structure_new_id (GST_QUARK (MESSAGE_BUFFERING),
-      GST_QUARK (BUFFER_PERCENT), G_TYPE_INT, percent,
-      GST_QUARK (BUFFERING_MODE), GST_TYPE_BUFFERING_MODE, GST_BUFFERING_STREAM,
-      GST_QUARK (AVG_IN_RATE), G_TYPE_INT, -1,
-      GST_QUARK (AVG_OUT_RATE), G_TYPE_INT, -1,
-      GST_QUARK (BUFFERING_LEFT), G_TYPE_INT64, buffering_left, NULL);
+  structure = gst_structure_new_static_str ("GstMessageBuffering",
+      "buffer-percent", G_TYPE_INT, percent,
+      "buffering-mode", GST_TYPE_BUFFERING_MODE, GST_BUFFERING_STREAM,
+      "avg-in-rate", G_TYPE_INT, -1,
+      "avg-out-rate", G_TYPE_INT, -1,
+      "buffering-left", G_TYPE_INT64, buffering_left, NULL);
   message = gst_message_new_custom (GST_MESSAGE_BUFFERING, src, structure);
 
   return message;
@@ -765,10 +915,10 @@ gst_message_new_state_changed (GstObject * src,
   GstMessage *message;
   GstStructure *structure;
 
-  structure = gst_structure_new_id (GST_QUARK (MESSAGE_STATE_CHANGED),
-      GST_QUARK (OLD_STATE), GST_TYPE_STATE, (gint) oldstate,
-      GST_QUARK (NEW_STATE), GST_TYPE_STATE, (gint) newstate,
-      GST_QUARK (PENDING_STATE), GST_TYPE_STATE, (gint) pending, NULL);
+  structure = gst_structure_new_static_str ("GstMessageStateChanged",
+      "old-state", GST_TYPE_STATE, (gint) oldstate,
+      "new-state", GST_TYPE_STATE, (gint) newstate,
+      "pending-state", GST_TYPE_STATE, (gint) pending, NULL);
   message = gst_message_new_custom (GST_MESSAGE_STATE_CHANGED, src, structure);
 
   return message;
@@ -820,9 +970,8 @@ gst_message_new_clock_provide (GstObject * src, GstClock * clock,
   GstMessage *message;
   GstStructure *structure;
 
-  structure = gst_structure_new_id (GST_QUARK (MESSAGE_CLOCK_PROVIDE),
-      GST_QUARK (CLOCK), GST_TYPE_CLOCK, clock,
-      GST_QUARK (READY), G_TYPE_BOOLEAN, ready, NULL);
+  structure = gst_structure_new_static_str ("GstMessageClockProvide",
+      "clock", GST_TYPE_CLOCK, clock, "ready", G_TYPE_BOOLEAN, ready, NULL);
   message = gst_message_new_custom (GST_MESSAGE_CLOCK_PROVIDE, src, structure);
 
   return message;
@@ -850,8 +999,8 @@ gst_message_new_clock_lost (GstObject * src, GstClock * clock)
   GstMessage *message;
   GstStructure *structure;
 
-  structure = gst_structure_new_id (GST_QUARK (MESSAGE_CLOCK_LOST),
-      GST_QUARK (CLOCK), GST_TYPE_CLOCK, clock, NULL);
+  structure = gst_structure_new_static_str ("GstMessageClockLost",
+      "clock", GST_TYPE_CLOCK, clock, NULL);
   message = gst_message_new_custom (GST_MESSAGE_CLOCK_LOST, src, structure);
 
   return message;
@@ -875,8 +1024,8 @@ gst_message_new_new_clock (GstObject * src, GstClock * clock)
   GstMessage *message;
   GstStructure *structure;
 
-  structure = gst_structure_new_id (GST_QUARK (MESSAGE_NEW_CLOCK),
-      GST_QUARK (CLOCK), GST_TYPE_CLOCK, clock, NULL);
+  structure = gst_structure_new_static_str ("GstMessageNewClock",
+      "clock", GST_TYPE_CLOCK, clock, NULL);
   message = gst_message_new_custom (GST_MESSAGE_NEW_CLOCK, src, structure);
 
   return message;
@@ -910,10 +1059,9 @@ gst_message_new_structure_change (GstObject * src, GstStructureChangeType type,
   /* g_return_val_if_fail (GST_PAD_DIRECTION (src) == GST_PAD_SINK, NULL); */
   g_return_val_if_fail (GST_IS_ELEMENT (owner), NULL);
 
-  structure = gst_structure_new_id (GST_QUARK (MESSAGE_STRUCTURE_CHANGE),
-      GST_QUARK (TYPE), GST_TYPE_STRUCTURE_CHANGE_TYPE, type,
-      GST_QUARK (OWNER), GST_TYPE_ELEMENT, owner,
-      GST_QUARK (BUSY), G_TYPE_BOOLEAN, busy, NULL);
+  structure = gst_structure_new_static_str ("GstMessageStructureChange",
+      "type", GST_TYPE_STRUCTURE_CHANGE_TYPE, type,
+      "owner", GST_TYPE_ELEMENT, owner, "busy", G_TYPE_BOOLEAN, busy, NULL);
 
   message = gst_message_new_custom (GST_MESSAGE_STRUCTURE_CHANGE, src,
       structure);
@@ -943,9 +1091,9 @@ gst_message_new_segment_start (GstObject * src, GstFormat format,
   GstMessage *message;
   GstStructure *structure;
 
-  structure = gst_structure_new_id (GST_QUARK (MESSAGE_SEGMENT_START),
-      GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
-      GST_QUARK (POSITION), G_TYPE_INT64, position, NULL);
+  structure = gst_structure_new_static_str ("GstMessageSegmentStart",
+      "format", GST_TYPE_FORMAT, format,
+      "position", G_TYPE_INT64, position, NULL);
   message = gst_message_new_custom (GST_MESSAGE_SEGMENT_START, src, structure);
 
   return message;
@@ -973,9 +1121,9 @@ gst_message_new_segment_done (GstObject * src, GstFormat format,
   GstMessage *message;
   GstStructure *structure;
 
-  structure = gst_structure_new_id (GST_QUARK (MESSAGE_SEGMENT_DONE),
-      GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
-      GST_QUARK (POSITION), G_TYPE_INT64, position, NULL);
+  structure = gst_structure_new_static_str ("GstMessageSegmentDone",
+      "format", GST_TYPE_FORMAT, format,
+      "position", G_TYPE_INT64, position, NULL);
   message = gst_message_new_custom (GST_MESSAGE_SEGMENT_DONE, src, structure);
 
   return message;
@@ -1044,7 +1192,7 @@ gst_message_new_duration_changed (GstObject * src)
   GstMessage *message;
 
   message = gst_message_new_custom (GST_MESSAGE_DURATION_CHANGED, src,
-      gst_structure_new_id_empty (GST_QUARK (MESSAGE_DURATION_CHANGED)));
+      gst_structure_new_static_str_empty ("GstMessageDurationChanged"));
 
   return message;
 }
@@ -1090,8 +1238,8 @@ gst_message_new_async_done (GstObject * src, GstClockTime running_time)
   GstMessage *message;
   GstStructure *structure;
 
-  structure = gst_structure_new_id (GST_QUARK (MESSAGE_ASYNC_DONE),
-      GST_QUARK (RUNNING_TIME), G_TYPE_UINT64, running_time, NULL);
+  structure = gst_structure_new_static_str ("GstMessageAsyncDone",
+      "running-time", G_TYPE_UINT64, running_time, NULL);
   message = gst_message_new_custom (GST_MESSAGE_ASYNC_DONE, src, structure);
 
   return message;
@@ -1137,8 +1285,8 @@ gst_message_new_request_state (GstObject * src, GstState state)
   GstMessage *message;
   GstStructure *structure;
 
-  structure = gst_structure_new_id (GST_QUARK (MESSAGE_REQUEST_STATE),
-      GST_QUARK (NEW_STATE), GST_TYPE_STATE, (gint) state, NULL);
+  structure = gst_structure_new_static_str ("GstMessageRequestState",
+      "new-state", GST_TYPE_STATE, (gint) state, NULL);
   message = gst_message_new_custom (GST_MESSAGE_REQUEST_STATE, src, structure);
 
   return message;
@@ -1192,8 +1340,8 @@ gst_message_writable_structure (GstMessage * message)
 
   if (structure == NULL) {
     structure =
-        gst_structure_new_id_empty (gst_message_type_to_quark (GST_MESSAGE_TYPE
-            (message)));
+        gst_structure_new_static_str_empty (gst_message_type_get_name
+        (GST_MESSAGE_TYPE (message)));
     gst_structure_set_parent_refcount (structure,
         &message->mini_object.refcount);
     GST_MESSAGE_STRUCTURE (message) = structure;
@@ -1260,8 +1408,8 @@ gst_message_parse_tag (GstMessage * message, GstTagList ** tag_list)
   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_TAG);
   g_return_if_fail (tag_list != NULL);
 
-  gst_structure_id_get (GST_MESSAGE_STRUCTURE (message),
-      GST_QUARK (TAGLIST), GST_TYPE_TAG_LIST, tag_list, NULL);
+  gst_structure_get (GST_MESSAGE_STRUCTURE (message),
+      "taglist", GST_TYPE_TAG_LIST, tag_list, NULL);
 }
 
 /**
@@ -1282,8 +1430,8 @@ gst_message_parse_buffering (GstMessage * message, gint * percent)
 
   if (percent)
     *percent =
-        g_value_get_int (gst_structure_id_get_value (GST_MESSAGE_STRUCTURE
-            (message), GST_QUARK (BUFFER_PERCENT)));
+        g_value_get_int (gst_structure_get_value (GST_MESSAGE_STRUCTURE
+            (message), "buffer-percent"));
 }
 
 /**
@@ -1303,11 +1451,11 @@ gst_message_set_buffering_stats (GstMessage * message, GstBufferingMode mode,
   g_return_if_fail (GST_IS_MESSAGE (message));
   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_BUFFERING);
 
-  gst_structure_id_set (GST_MESSAGE_STRUCTURE (message),
-      GST_QUARK (BUFFERING_MODE), GST_TYPE_BUFFERING_MODE, mode,
-      GST_QUARK (AVG_IN_RATE), G_TYPE_INT, avg_in,
-      GST_QUARK (AVG_OUT_RATE), G_TYPE_INT, avg_out,
-      GST_QUARK (BUFFERING_LEFT), G_TYPE_INT64, buffering_left, NULL);
+  gst_structure_set (GST_MESSAGE_STRUCTURE (message),
+      "buffering-mode", GST_TYPE_BUFFERING_MODE, mode,
+      "avg-in-rate", G_TYPE_INT, avg_in,
+      "avg-out-rate", G_TYPE_INT, avg_out,
+      "buffering-left", G_TYPE_INT64, buffering_left, NULL);
 }
 
 /**
@@ -1333,18 +1481,18 @@ gst_message_parse_buffering_stats (GstMessage * message,
   structure = GST_MESSAGE_STRUCTURE (message);
   if (mode)
     *mode = (GstBufferingMode)
-        g_value_get_enum (gst_structure_id_get_value (structure,
-            GST_QUARK (BUFFERING_MODE)));
+        g_value_get_enum (gst_structure_get_value (structure,
+            "buffering-mode"));
   if (avg_in)
-    *avg_in = g_value_get_int (gst_structure_id_get_value (structure,
-            GST_QUARK (AVG_IN_RATE)));
+    *avg_in = g_value_get_int (gst_structure_get_value (structure,
+            "avg-in-rate"));
   if (avg_out)
-    *avg_out = g_value_get_int (gst_structure_id_get_value (structure,
-            GST_QUARK (AVG_OUT_RATE)));
+    *avg_out = g_value_get_int (gst_structure_get_value (structure,
+            "avg-out-rate"));
   if (buffering_left)
     *buffering_left =
-        g_value_get_int64 (gst_structure_id_get_value (structure,
-            GST_QUARK (BUFFERING_LEFT)));
+        g_value_get_int64 (gst_structure_get_value (structure,
+            "buffering-left"));
 }
 
 /**
@@ -1389,16 +1537,13 @@ gst_message_parse_state_changed (GstMessage * message,
   structure = GST_MESSAGE_STRUCTURE (message);
   if (oldstate)
     *oldstate = (GstState)
-        g_value_get_enum (gst_structure_id_get_value (structure,
-            GST_QUARK (OLD_STATE)));
+        g_value_get_enum (gst_structure_get_value (structure, "old-state"));
   if (newstate)
     *newstate = (GstState)
-        g_value_get_enum (gst_structure_id_get_value (structure,
-            GST_QUARK (NEW_STATE)));
+        g_value_get_enum (gst_structure_get_value (structure, "new-state"));
   if (pending)
     *pending = (GstState)
-        g_value_get_enum (gst_structure_id_get_value (structure,
-            GST_QUARK (PENDING_STATE)));
+        g_value_get_enum (gst_structure_get_value (structure, "pending-state"));
 }
 
 /**
@@ -1424,14 +1569,12 @@ gst_message_parse_clock_provide (GstMessage * message, GstClock ** clock,
   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_CLOCK_PROVIDE);
 
   structure = GST_MESSAGE_STRUCTURE (message);
-  clock_gvalue = gst_structure_id_get_value (structure, GST_QUARK (CLOCK));
+  clock_gvalue = gst_structure_get_value (structure, "clock");
   g_return_if_fail (clock_gvalue != NULL);
   g_return_if_fail (G_VALUE_TYPE (clock_gvalue) == GST_TYPE_CLOCK);
 
   if (ready)
-    *ready =
-        g_value_get_boolean (gst_structure_id_get_value (structure,
-            GST_QUARK (READY)));
+    *ready = g_value_get_boolean (gst_structure_get_value (structure, "ready"));
   if (clock)
     *clock = (GstClock *) g_value_get_object (clock_gvalue);
 }
@@ -1456,7 +1599,7 @@ gst_message_parse_clock_lost (GstMessage * message, GstClock ** clock)
   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_CLOCK_LOST);
 
   structure = GST_MESSAGE_STRUCTURE (message);
-  clock_gvalue = gst_structure_id_get_value (structure, GST_QUARK (CLOCK));
+  clock_gvalue = gst_structure_get_value (structure, "clock");
   g_return_if_fail (clock_gvalue != NULL);
   g_return_if_fail (G_VALUE_TYPE (clock_gvalue) == GST_TYPE_CLOCK);
 
@@ -1485,7 +1628,7 @@ gst_message_parse_new_clock (GstMessage * message, GstClock ** clock)
   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_NEW_CLOCK);
 
   structure = GST_MESSAGE_STRUCTURE (message);
-  clock_gvalue = gst_structure_id_get_value (structure, GST_QUARK (CLOCK));
+  clock_gvalue = gst_structure_get_value (structure, "clock");
   g_return_if_fail (clock_gvalue != NULL);
   g_return_if_fail (G_VALUE_TYPE (clock_gvalue) == GST_TYPE_CLOCK);
 
@@ -1517,20 +1660,17 @@ gst_message_parse_structure_change (GstMessage * message,
   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_STRUCTURE_CHANGE);
 
   structure = GST_MESSAGE_STRUCTURE (message);
-  owner_gvalue = gst_structure_id_get_value (structure, GST_QUARK (OWNER));
+  owner_gvalue = gst_structure_get_value (structure, "owner");
   g_return_if_fail (owner_gvalue != NULL);
   g_return_if_fail (G_VALUE_TYPE (owner_gvalue) == GST_TYPE_ELEMENT);
 
   if (type)
     *type = (GstStructureChangeType)
-        g_value_get_enum (gst_structure_id_get_value (structure,
-            GST_QUARK (TYPE)));
+        g_value_get_enum (gst_structure_get_value (structure, "type"));
   if (owner)
     *owner = (GstElement *) g_value_get_object (owner_gvalue);
   if (busy)
-    *busy =
-        g_value_get_boolean (gst_structure_id_get_value (structure,
-            GST_QUARK (BUSY)));
+    *busy = g_value_get_boolean (gst_structure_get_value (structure, "busy"));
 }
 
 /**
@@ -1572,9 +1712,8 @@ gst_message_parse_error (GstMessage * message, GError ** gerror, gchar ** debug)
   g_return_if_fail (GST_IS_MESSAGE (message));
   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_ERROR);
 
-  gst_structure_id_get (GST_MESSAGE_STRUCTURE (message),
-      GST_QUARK (GERROR), G_TYPE_ERROR, gerror,
-      GST_QUARK (DEBUG), G_TYPE_STRING, debug, NULL);
+  gst_structure_get (GST_MESSAGE_STRUCTURE (message),
+      "gerror", G_TYPE_ERROR, gerror, "debug", G_TYPE_STRING, debug, NULL);
 }
 
 /**
@@ -1596,9 +1735,8 @@ gst_message_parse_warning (GstMessage * message, GError ** gerror,
   g_return_if_fail (GST_IS_MESSAGE (message));
   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_WARNING);
 
-  gst_structure_id_get (GST_MESSAGE_STRUCTURE (message),
-      GST_QUARK (GERROR), G_TYPE_ERROR, gerror,
-      GST_QUARK (DEBUG), G_TYPE_STRING, debug, NULL);
+  gst_structure_get (GST_MESSAGE_STRUCTURE (message),
+      "gerror", G_TYPE_ERROR, gerror, "debug", G_TYPE_STRING, debug, NULL);
 }
 
 /**
@@ -1619,9 +1757,8 @@ gst_message_parse_info (GstMessage * message, GError ** gerror, gchar ** debug)
   g_return_if_fail (GST_IS_MESSAGE (message));
   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_INFO);
 
-  gst_structure_id_get (GST_MESSAGE_STRUCTURE (message),
-      GST_QUARK (GERROR), G_TYPE_ERROR, gerror,
-      GST_QUARK (DEBUG), G_TYPE_STRING, debug, NULL);
+  gst_structure_get (GST_MESSAGE_STRUCTURE (message),
+      "gerror", G_TYPE_ERROR, gerror, "debug", G_TYPE_STRING, debug, NULL);
 }
 
 /**
@@ -1646,12 +1783,10 @@ gst_message_parse_segment_start (GstMessage * message, GstFormat * format,
   structure = GST_MESSAGE_STRUCTURE (message);
   if (format)
     *format = (GstFormat)
-        g_value_get_enum (gst_structure_id_get_value (structure,
-            GST_QUARK (FORMAT)));
+        g_value_get_enum (gst_structure_get_value (structure, "format"));
   if (position)
     *position =
-        g_value_get_int64 (gst_structure_id_get_value (structure,
-            GST_QUARK (POSITION)));
+        g_value_get_int64 (gst_structure_get_value (structure, "position"));
 }
 
 /**
@@ -1676,12 +1811,10 @@ gst_message_parse_segment_done (GstMessage * message, GstFormat * format,
   structure = GST_MESSAGE_STRUCTURE (message);
   if (format)
     *format = (GstFormat)
-        g_value_get_enum (gst_structure_id_get_value (structure,
-            GST_QUARK (FORMAT)));
+        g_value_get_enum (gst_structure_get_value (structure, "format"));
   if (position)
     *position =
-        g_value_get_int64 (gst_structure_id_get_value (structure,
-            GST_QUARK (POSITION)));
+        g_value_get_int64 (gst_structure_get_value (structure, "position"));
 }
 
 /**
@@ -1704,8 +1837,8 @@ gst_message_parse_async_done (GstMessage * message, GstClockTime * running_time)
   structure = GST_MESSAGE_STRUCTURE (message);
   if (running_time)
     *running_time =
-        g_value_get_uint64 (gst_structure_id_get_value (structure,
-            GST_QUARK (RUNNING_TIME)));
+        g_value_get_uint64 (gst_structure_get_value (structure,
+            "running-time"));
 }
 
 /**
@@ -1728,8 +1861,7 @@ gst_message_parse_request_state (GstMessage * message, GstState * state)
   structure = GST_MESSAGE_STRUCTURE (message);
   if (state)
     *state = (GstState)
-        g_value_get_enum (gst_structure_id_get_value (structure,
-            GST_QUARK (NEW_STATE)));
+        g_value_get_enum (gst_structure_get_value (structure, "new-state"));
 }
 
 /**
@@ -1752,9 +1884,9 @@ gst_message_new_stream_status (GstObject * src, GstStreamStatusType type,
   GstMessage *message;
   GstStructure *structure;
 
-  structure = gst_structure_new_id (GST_QUARK (MESSAGE_STREAM_STATUS),
-      GST_QUARK (TYPE), GST_TYPE_STREAM_STATUS_TYPE, (gint) type,
-      GST_QUARK (OWNER), GST_TYPE_ELEMENT, owner, NULL);
+  structure = gst_structure_new_static_str ("GstMessageStreamStatus",
+      "type", GST_TYPE_STREAM_STATUS_TYPE, (gint) type,
+      "owner", GST_TYPE_ELEMENT, owner, NULL);
   message = gst_message_new_custom (GST_MESSAGE_STREAM_STATUS, src, structure);
 
   return message;
@@ -1783,13 +1915,12 @@ gst_message_parse_stream_status (GstMessage * message,
   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_STREAM_STATUS);
 
   structure = GST_MESSAGE_STRUCTURE (message);
-  owner_gvalue = gst_structure_id_get_value (structure, GST_QUARK (OWNER));
+  owner_gvalue = gst_structure_get_value (structure, "owner");
   g_return_if_fail (owner_gvalue != NULL);
 
   if (type)
     *type = (GstStreamStatusType)
-        g_value_get_enum (gst_structure_id_get_value (structure,
-            GST_QUARK (TYPE)));
+        g_value_get_enum (gst_structure_get_value (structure, "type"));
   if (owner)
     *owner = (GstElement *) g_value_get_object (owner_gvalue);
 }
@@ -1812,7 +1943,7 @@ gst_message_set_stream_status_object (GstMessage * message,
   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_STREAM_STATUS);
 
   structure = GST_MESSAGE_STRUCTURE (message);
-  gst_structure_id_set_value (structure, GST_QUARK (OBJECT), object);
+  gst_structure_set_value_static_str (structure, "object", object);
 }
 
 /**
@@ -1837,7 +1968,7 @@ gst_message_get_stream_status_object (GstMessage * message)
       NULL);
 
   structure = GST_MESSAGE_STRUCTURE (message);
-  result = gst_structure_id_get_value (structure, GST_QUARK (OBJECT));
+  result = gst_structure_get_value (structure, "object");
 
   return result;
 }
@@ -1871,14 +2002,13 @@ gst_message_new_step_done (GstObject * src, GstFormat format, guint64 amount,
   GstMessage *message;
   GstStructure *structure;
 
-  structure = gst_structure_new_id (GST_QUARK (MESSAGE_STEP_DONE),
-      GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
-      GST_QUARK (AMOUNT), G_TYPE_UINT64, amount,
-      GST_QUARK (RATE), G_TYPE_DOUBLE, rate,
-      GST_QUARK (FLUSH), G_TYPE_BOOLEAN, flush,
-      GST_QUARK (INTERMEDIATE), G_TYPE_BOOLEAN, intermediate,
-      GST_QUARK (DURATION), G_TYPE_UINT64, duration,
-      GST_QUARK (EOS), G_TYPE_BOOLEAN, eos, NULL);
+  structure = gst_structure_new_static_str ("GstMessageStepDone",
+      "format", GST_TYPE_FORMAT, format,
+      "amount", G_TYPE_UINT64, amount,
+      "rate", G_TYPE_DOUBLE, rate,
+      "flush", G_TYPE_BOOLEAN, flush,
+      "intermediate", G_TYPE_BOOLEAN, intermediate,
+      "duration", G_TYPE_UINT64, duration, "eos", G_TYPE_BOOLEAN, eos, NULL);
   message = gst_message_new_custom (GST_MESSAGE_STEP_DONE, src, structure);
 
   return message;
@@ -1910,14 +2040,13 @@ gst_message_parse_step_done (GstMessage * message, GstFormat * format,
   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_STEP_DONE);
 
   structure = GST_MESSAGE_STRUCTURE (message);
-  gst_structure_id_get (structure,
-      GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
-      GST_QUARK (AMOUNT), G_TYPE_UINT64, amount,
-      GST_QUARK (RATE), G_TYPE_DOUBLE, rate,
-      GST_QUARK (FLUSH), G_TYPE_BOOLEAN, flush,
-      GST_QUARK (INTERMEDIATE), G_TYPE_BOOLEAN, intermediate,
-      GST_QUARK (DURATION), G_TYPE_UINT64, duration,
-      GST_QUARK (EOS), G_TYPE_BOOLEAN, eos, NULL);
+  gst_structure_get (structure,
+      "format", GST_TYPE_FORMAT, format,
+      "amount", G_TYPE_UINT64, amount,
+      "rate", G_TYPE_DOUBLE, rate,
+      "flush", G_TYPE_BOOLEAN, flush,
+      "intermediate", G_TYPE_BOOLEAN, intermediate,
+      "duration", G_TYPE_UINT64, duration, "eos", G_TYPE_BOOLEAN, eos, NULL);
 }
 
 /**
@@ -1952,13 +2081,13 @@ gst_message_new_step_start (GstObject * src, gboolean active, GstFormat format,
   GstMessage *message;
   GstStructure *structure;
 
-  structure = gst_structure_new_id (GST_QUARK (MESSAGE_STEP_START),
-      GST_QUARK (ACTIVE), G_TYPE_BOOLEAN, active,
-      GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
-      GST_QUARK (AMOUNT), G_TYPE_UINT64, amount,
-      GST_QUARK (RATE), G_TYPE_DOUBLE, rate,
-      GST_QUARK (FLUSH), G_TYPE_BOOLEAN, flush,
-      GST_QUARK (INTERMEDIATE), G_TYPE_BOOLEAN, intermediate, NULL);
+  structure = gst_structure_new_static_str ("GstMessageStepStart",
+      "active", G_TYPE_BOOLEAN, active,
+      "format", GST_TYPE_FORMAT, format,
+      "amount", G_TYPE_UINT64, amount,
+      "rate", G_TYPE_DOUBLE, rate,
+      "flush", G_TYPE_BOOLEAN, flush,
+      "intermediate", G_TYPE_BOOLEAN, intermediate, NULL);
   message = gst_message_new_custom (GST_MESSAGE_STEP_START, src, structure);
 
   return message;
@@ -1989,13 +2118,13 @@ gst_message_parse_step_start (GstMessage * message, gboolean * active,
   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_STEP_START);
 
   structure = GST_MESSAGE_STRUCTURE (message);
-  gst_structure_id_get (structure,
-      GST_QUARK (ACTIVE), G_TYPE_BOOLEAN, active,
-      GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
-      GST_QUARK (AMOUNT), G_TYPE_UINT64, amount,
-      GST_QUARK (RATE), G_TYPE_DOUBLE, rate,
-      GST_QUARK (FLUSH), G_TYPE_BOOLEAN, flush,
-      GST_QUARK (INTERMEDIATE), G_TYPE_BOOLEAN, intermediate, NULL);
+  gst_structure_get (structure,
+      "active", G_TYPE_BOOLEAN, active,
+      "format", GST_TYPE_FORMAT, format,
+      "amount", G_TYPE_UINT64, amount,
+      "rate", G_TYPE_DOUBLE, rate,
+      "flush", G_TYPE_BOOLEAN, flush,
+      "intermediate", G_TYPE_BOOLEAN, intermediate, NULL);
 }
 
 /**
@@ -2032,18 +2161,18 @@ gst_message_new_qos (GstObject * src, gboolean live, guint64 running_time,
   GstMessage *message;
   GstStructure *structure;
 
-  structure = gst_structure_new_id (GST_QUARK (MESSAGE_QOS),
-      GST_QUARK (LIVE), G_TYPE_BOOLEAN, live,
-      GST_QUARK (RUNNING_TIME), G_TYPE_UINT64, running_time,
-      GST_QUARK (STREAM_TIME), G_TYPE_UINT64, stream_time,
-      GST_QUARK (TIMESTAMP), G_TYPE_UINT64, timestamp,
-      GST_QUARK (DURATION), G_TYPE_UINT64, duration,
-      GST_QUARK (JITTER), G_TYPE_INT64, (gint64) 0,
-      GST_QUARK (PROPORTION), G_TYPE_DOUBLE, (gdouble) 1.0,
-      GST_QUARK (QUALITY), G_TYPE_INT, (gint) 1000000,
-      GST_QUARK (FORMAT), GST_TYPE_FORMAT, GST_FORMAT_UNDEFINED,
-      GST_QUARK (PROCESSED), G_TYPE_UINT64, (guint64) - 1,
-      GST_QUARK (DROPPED), G_TYPE_UINT64, (guint64) - 1, NULL);
+  structure = gst_structure_new_static_str ("GstMessageQOS",
+      "live", G_TYPE_BOOLEAN, live,
+      "running-time", G_TYPE_UINT64, running_time,
+      "stream-time", G_TYPE_UINT64, stream_time,
+      "timestamp", G_TYPE_UINT64, timestamp,
+      "duration", G_TYPE_UINT64, duration,
+      "jitter", G_TYPE_INT64, (gint64) 0,
+      "proportion", G_TYPE_DOUBLE, (gdouble) 1.0,
+      "quality", G_TYPE_INT, (gint) 1000000,
+      "format", GST_TYPE_FORMAT, GST_FORMAT_UNDEFINED,
+      "processed", G_TYPE_UINT64, (guint64) - 1,
+      "dropped", G_TYPE_UINT64, (guint64) - 1, NULL);
   message = gst_message_new_custom (GST_MESSAGE_QOS, src, structure);
 
   return message;
@@ -2072,10 +2201,10 @@ gst_message_set_qos_values (GstMessage * message, gint64 jitter,
   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_QOS);
 
   structure = GST_MESSAGE_STRUCTURE (message);
-  gst_structure_id_set (structure,
-      GST_QUARK (JITTER), G_TYPE_INT64, jitter,
-      GST_QUARK (PROPORTION), G_TYPE_DOUBLE, proportion,
-      GST_QUARK (QUALITY), G_TYPE_INT, quality, NULL);
+  gst_structure_set_static_str (structure,
+      "jitter", G_TYPE_INT64, jitter,
+      "proportion", G_TYPE_DOUBLE, proportion,
+      "quality", G_TYPE_INT, quality, NULL);
 }
 
 /**
@@ -2107,10 +2236,10 @@ gst_message_set_qos_stats (GstMessage * message, GstFormat format,
   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_QOS);
 
   structure = GST_MESSAGE_STRUCTURE (message);
-  gst_structure_id_set (structure,
-      GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
-      GST_QUARK (PROCESSED), G_TYPE_UINT64, processed,
-      GST_QUARK (DROPPED), G_TYPE_UINT64, dropped, NULL);
+  gst_structure_set_static_str (structure,
+      "format", GST_TYPE_FORMAT, format,
+      "processed", G_TYPE_UINT64, processed,
+      "dropped", G_TYPE_UINT64, dropped, NULL);
 }
 
 /**
@@ -2145,12 +2274,12 @@ gst_message_parse_qos (GstMessage * message, gboolean * live,
   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_QOS);
 
   structure = GST_MESSAGE_STRUCTURE (message);
-  gst_structure_id_get (structure,
-      GST_QUARK (LIVE), G_TYPE_BOOLEAN, live,
-      GST_QUARK (RUNNING_TIME), G_TYPE_UINT64, running_time,
-      GST_QUARK (STREAM_TIME), G_TYPE_UINT64, stream_time,
-      GST_QUARK (TIMESTAMP), G_TYPE_UINT64, timestamp,
-      GST_QUARK (DURATION), G_TYPE_UINT64, duration, NULL);
+  gst_structure_get (structure,
+      "live", G_TYPE_BOOLEAN, live,
+      "running-time", G_TYPE_UINT64, running_time,
+      "stream-time", G_TYPE_UINT64, stream_time,
+      "timestamp", G_TYPE_UINT64, timestamp,
+      "duration", G_TYPE_UINT64, duration, NULL);
 }
 
 /**
@@ -2178,10 +2307,10 @@ gst_message_parse_qos_values (GstMessage * message, gint64 * jitter,
   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_QOS);
 
   structure = GST_MESSAGE_STRUCTURE (message);
-  gst_structure_id_get (structure,
-      GST_QUARK (JITTER), G_TYPE_INT64, jitter,
-      GST_QUARK (PROPORTION), G_TYPE_DOUBLE, proportion,
-      GST_QUARK (QUALITY), G_TYPE_INT, quality, NULL);
+  gst_structure_get (structure,
+      "jitter", G_TYPE_INT64, jitter,
+      "proportion", G_TYPE_DOUBLE, proportion,
+      "quality", G_TYPE_INT, quality, NULL);
 }
 
 /**
@@ -2214,10 +2343,10 @@ gst_message_parse_qos_stats (GstMessage * message, GstFormat * format,
   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_QOS);
 
   structure = GST_MESSAGE_STRUCTURE (message);
-  gst_structure_id_get (structure,
-      GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
-      GST_QUARK (PROCESSED), G_TYPE_UINT64, processed,
-      GST_QUARK (DROPPED), G_TYPE_UINT64, dropped, NULL);
+  gst_structure_get (structure,
+      "format", GST_TYPE_FORMAT, format,
+      "processed", G_TYPE_UINT64, processed,
+      "dropped", G_TYPE_UINT64, dropped, NULL);
 }
 
 /**
@@ -2249,12 +2378,11 @@ gst_message_new_progress (GstObject * src, GstProgressType type,
   if (type == GST_PROGRESS_TYPE_START || type == GST_PROGRESS_TYPE_CONTINUE)
     percent = 0;
 
-  structure = gst_structure_new_id (GST_QUARK (MESSAGE_PROGRESS),
-      GST_QUARK (TYPE), GST_TYPE_PROGRESS_TYPE, type,
-      GST_QUARK (CODE), G_TYPE_STRING, code,
-      GST_QUARK (TEXT), G_TYPE_STRING, text,
-      GST_QUARK (PERCENT), G_TYPE_INT, percent,
-      GST_QUARK (TIMEOUT), G_TYPE_INT, timeout, NULL);
+  structure = gst_structure_new_static_str ("GstMessageProgress",
+      "type", GST_TYPE_PROGRESS_TYPE, type,
+      "code", G_TYPE_STRING, code,
+      "text", G_TYPE_STRING, text,
+      "percent", G_TYPE_INT, percent, "timeout", G_TYPE_INT, timeout, NULL);
   message = gst_message_new_custom (GST_MESSAGE_PROGRESS, src, structure);
 
   return message;
@@ -2279,10 +2407,9 @@ gst_message_parse_progress (GstMessage * message, GstProgressType * type,
   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_PROGRESS);
 
   structure = GST_MESSAGE_STRUCTURE (message);
-  gst_structure_id_get (structure,
-      GST_QUARK (TYPE), GST_TYPE_PROGRESS_TYPE, type,
-      GST_QUARK (CODE), G_TYPE_STRING, code,
-      GST_QUARK (TEXT), G_TYPE_STRING, text, NULL);
+  gst_structure_get (structure,
+      "type", GST_TYPE_PROGRESS_TYPE, type,
+      "code", G_TYPE_STRING, code, "text", G_TYPE_STRING, text, NULL);
 }
 
 /**
@@ -2305,9 +2432,8 @@ gst_message_new_toc (GstObject * src, GstToc * toc, gboolean updated)
 
   g_return_val_if_fail (toc != NULL, NULL);
 
-  toc_struct = gst_structure_new_id (GST_QUARK (MESSAGE_TOC),
-      GST_QUARK (TOC), GST_TYPE_TOC, toc,
-      GST_QUARK (UPDATED), G_TYPE_BOOLEAN, updated, NULL);
+  toc_struct = gst_structure_new_static_str ("GstMessageToc",
+      "toc", GST_TYPE_TOC, toc, "updated", G_TYPE_BOOLEAN, updated, NULL);
 
   return gst_message_new_custom (GST_MESSAGE_TOC, src, toc_struct);
 }
@@ -2331,9 +2457,8 @@ gst_message_parse_toc (GstMessage * message, GstToc ** toc, gboolean * updated)
   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_TOC);
   g_return_if_fail (toc != NULL);
 
-  gst_structure_id_get (GST_MESSAGE_STRUCTURE (message),
-      GST_QUARK (TOC), GST_TYPE_TOC, toc,
-      GST_QUARK (UPDATED), G_TYPE_BOOLEAN, updated, NULL);
+  gst_structure_get (GST_MESSAGE_STRUCTURE (message),
+      "toc", GST_TYPE_TOC, toc, "updated", G_TYPE_BOOLEAN, updated, NULL);
 }
 
 /**
@@ -2356,8 +2481,8 @@ gst_message_new_reset_time (GstObject * src, GstClockTime running_time)
 
   g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (running_time), NULL);
 
-  structure = gst_structure_new_id (GST_QUARK (MESSAGE_RESET_TIME),
-      GST_QUARK (RUNNING_TIME), G_TYPE_UINT64, running_time, NULL);
+  structure = gst_structure_new_static_str ("GstMessageResetTime",
+      "running-time", G_TYPE_UINT64, running_time, NULL);
   message = gst_message_new_custom (GST_MESSAGE_RESET_TIME, src, structure);
 
   return message;
@@ -2384,8 +2509,8 @@ gst_message_parse_reset_time (GstMessage * message, GstClockTime * running_time)
   structure = GST_MESSAGE_STRUCTURE (message);
   if (running_time)
     *running_time =
-        g_value_get_uint64 (gst_structure_id_get_value (structure,
-            GST_QUARK (RUNNING_TIME)));
+        g_value_get_uint64 (gst_structure_get_value (structure,
+            "running-time"));
 }
 
 /**
@@ -2406,7 +2531,7 @@ gst_message_new_stream_start (GstObject * src)
   GstMessage *message;
   GstStructure *s;
 
-  s = gst_structure_new_id_empty (GST_QUARK (MESSAGE_STREAM_START));
+  s = gst_structure_new_static_str_empty ("GstMessageStreamStart");
   message = gst_message_new_custom (GST_MESSAGE_STREAM_START, src, s);
 
   return message;
@@ -2441,8 +2566,7 @@ gst_message_set_group_id (GstMessage * message, guint group_id)
   g_return_if_fail (group_id != GST_GROUP_ID_INVALID);
 
   structure = GST_MESSAGE_STRUCTURE (message);
-  gst_structure_id_set (structure, GST_QUARK (GROUP_ID), G_TYPE_UINT, group_id,
-      NULL);
+  gst_structure_set (structure, "group-id", G_TYPE_UINT, group_id, NULL);
 }
 
 /**
@@ -2476,7 +2600,7 @@ gst_message_parse_group_id (GstMessage * message, guint * group_id)
 
   structure = GST_MESSAGE_STRUCTURE (message);
 
-  v = gst_structure_id_get_value (structure, GST_QUARK (GROUP_ID));
+  v = gst_structure_get_value (structure, "group-id");
   if (!v)
     return FALSE;
 
@@ -2505,8 +2629,8 @@ gst_message_new_need_context (GstObject * src, const gchar * context_type)
 
   g_return_val_if_fail (context_type != NULL, NULL);
 
-  structure = gst_structure_new_id (GST_QUARK (MESSAGE_NEED_CONTEXT),
-      GST_QUARK (CONTEXT_TYPE), G_TYPE_STRING, context_type, NULL);
+  structure = gst_structure_new_static_str ("GstMessageNeedContext",
+      "context-type", G_TYPE_STRING, context_type, NULL);
   message = gst_message_new_custom (GST_MESSAGE_NEED_CONTEXT, src, structure);
 
   return message;
@@ -2536,7 +2660,7 @@ gst_message_parse_context_type (GstMessage * message,
   structure = GST_MESSAGE_STRUCTURE (message);
 
   if (context_type) {
-    value = gst_structure_id_get_value (structure, GST_QUARK (CONTEXT_TYPE));
+    value = gst_structure_get_value (structure, "context-type");
     *context_type = g_value_get_string (value);
   }
 
@@ -2562,8 +2686,8 @@ gst_message_new_have_context (GstObject * src, GstContext * context)
   GstMessage *message;
   GstStructure *structure;
 
-  structure = gst_structure_new_id (GST_QUARK (MESSAGE_HAVE_CONTEXT),
-      GST_QUARK (CONTEXT), GST_TYPE_CONTEXT, context, NULL);
+  structure = gst_structure_new_static_str ("GstMessageHaveContext",
+      "context", GST_TYPE_CONTEXT, context, NULL);
   message = gst_message_new_custom (GST_MESSAGE_HAVE_CONTEXT, src, structure);
   gst_context_unref (context);
 
@@ -2589,8 +2713,8 @@ gst_message_parse_have_context (GstMessage * message, GstContext ** context)
   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_HAVE_CONTEXT);
 
   if (context)
-    gst_structure_id_get (GST_MESSAGE_STRUCTURE (message),
-        GST_QUARK (CONTEXT), GST_TYPE_CONTEXT, context, NULL);
+    gst_structure_get (GST_MESSAGE_STRUCTURE (message),
+        "context", GST_TYPE_CONTEXT, context, NULL);
 }
 
 /**
@@ -2615,8 +2739,8 @@ gst_message_new_device_added (GstObject * src, GstDevice * device)
   g_return_val_if_fail (device != NULL, NULL);
   g_return_val_if_fail (GST_IS_DEVICE (device), NULL);
 
-  structure = gst_structure_new_id (GST_QUARK (MESSAGE_DEVICE_ADDED),
-      GST_QUARK (DEVICE), GST_TYPE_DEVICE, device, NULL);
+  structure = gst_structure_new_static_str ("GstMessageDeviceAdded",
+      "device", GST_TYPE_DEVICE, device, NULL);
   message = gst_message_new_custom (GST_MESSAGE_DEVICE_ADDED, src, structure);
 
   return message;
@@ -2641,8 +2765,8 @@ gst_message_parse_device_added (GstMessage * message, GstDevice ** device)
   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_DEVICE_ADDED);
 
   if (device)
-    gst_structure_id_get (GST_MESSAGE_STRUCTURE (message),
-        GST_QUARK (DEVICE), GST_TYPE_DEVICE, device, NULL);
+    gst_structure_get (GST_MESSAGE_STRUCTURE (message),
+        "device", GST_TYPE_DEVICE, device, NULL);
 }
 
 /**
@@ -2667,8 +2791,8 @@ gst_message_new_device_removed (GstObject * src, GstDevice * device)
   g_return_val_if_fail (device != NULL, NULL);
   g_return_val_if_fail (GST_IS_DEVICE (device), NULL);
 
-  structure = gst_structure_new_id (GST_QUARK (MESSAGE_DEVICE_REMOVED),
-      GST_QUARK (DEVICE), GST_TYPE_DEVICE, device, NULL);
+  structure = gst_structure_new_static_str ("GstMessageDeviceRemoved",
+      "device", GST_TYPE_DEVICE, device, NULL);
   message = gst_message_new_custom (GST_MESSAGE_DEVICE_REMOVED, src, structure);
 
   return message;
@@ -2693,8 +2817,8 @@ gst_message_parse_device_removed (GstMessage * message, GstDevice ** device)
   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_DEVICE_REMOVED);
 
   if (device)
-    gst_structure_id_get (GST_MESSAGE_STRUCTURE (message),
-        GST_QUARK (DEVICE), GST_TYPE_DEVICE, device, NULL);
+    gst_structure_get (GST_MESSAGE_STRUCTURE (message),
+        "device", GST_TYPE_DEVICE, device, NULL);
 }
 
 /**
@@ -2722,9 +2846,9 @@ gst_message_new_device_changed (GstObject * src, GstDevice * device,
   g_return_val_if_fail (device != NULL, NULL);
   g_return_val_if_fail (GST_IS_DEVICE (device), NULL);
 
-  structure = gst_structure_new_id (GST_QUARK (MESSAGE_DEVICE_CHANGED),
-      GST_QUARK (DEVICE), GST_TYPE_DEVICE, device,
-      GST_QUARK (DEVICE_CHANGED), GST_TYPE_DEVICE, changed_device, NULL);
+  structure = gst_structure_new_static_str ("GstMessageDeviceChanged",
+      "device", GST_TYPE_DEVICE, device,
+      "device-changed", GST_TYPE_DEVICE, changed_device, NULL);
   message = gst_message_new_custom (GST_MESSAGE_DEVICE_CHANGED, src, structure);
 
   return message;
@@ -2753,12 +2877,12 @@ gst_message_parse_device_changed (GstMessage * message, GstDevice ** device,
   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_DEVICE_CHANGED);
 
   if (device)
-    gst_structure_id_get (GST_MESSAGE_STRUCTURE (message),
-        GST_QUARK (DEVICE), GST_TYPE_DEVICE, device, NULL);
+    gst_structure_get (GST_MESSAGE_STRUCTURE (message),
+        "device", GST_TYPE_DEVICE, device, NULL);
 
   if (changed_device)
-    gst_structure_id_get (GST_MESSAGE_STRUCTURE (message),
-        GST_QUARK (DEVICE_CHANGED), GST_TYPE_DEVICE, changed_device, NULL);
+    gst_structure_get (GST_MESSAGE_STRUCTURE (message),
+        "device-changed", GST_TYPE_DEVICE, changed_device, NULL);
 }
 
 /**
@@ -2781,13 +2905,13 @@ gst_message_new_property_notify (GstObject * src, const gchar * property_name,
   g_return_val_if_fail (GST_IS_OBJECT (src), NULL);
   g_return_val_if_fail (property_name != NULL, NULL);
 
-  structure = gst_structure_new_id_empty (GST_QUARK (MESSAGE_PROPERTY_NOTIFY));
+  structure = gst_structure_new_static_str_empty ("GstMessagePropertyNotify");
   g_value_init (&name_val, G_TYPE_STRING);
   /* should already be interned, but let's make sure */
   g_value_set_static_string (&name_val, g_intern_string (property_name));
-  gst_structure_id_take_value (structure, GST_QUARK (PROPERTY_NAME), &name_val);
+  gst_structure_take_value (structure, "property-name", &name_val);
   if (val != NULL)
-    gst_structure_id_take_value (structure, GST_QUARK (PROPERTY_VALUE), val);
+    gst_structure_take_value (structure, "property-value", val);
 
   return gst_message_new_custom (GST_MESSAGE_PROPERTY_NOTIFY, src, structure);
 }
@@ -2825,13 +2949,12 @@ gst_message_parse_property_notify (GstMessage * message, GstObject ** object,
   if (property_name) {
     const GValue *name_value;
 
-    name_value = gst_structure_id_get_value (s, GST_QUARK (PROPERTY_NAME));
+    name_value = gst_structure_get_value (s, "property-name");
     *property_name = g_value_get_string (name_value);
   }
 
   if (property_value)
-    *property_value =
-        gst_structure_id_get_value (s, GST_QUARK (PROPERTY_VALUE));
+    *property_value = gst_structure_get_value (s, "property-value");
 }
 
 /**
@@ -2857,8 +2980,8 @@ gst_message_new_stream_collection (GstObject * src,
   g_return_val_if_fail (GST_IS_STREAM_COLLECTION (collection), NULL);
 
   structure =
-      gst_structure_new_id (GST_QUARK (MESSAGE_STREAM_COLLECTION),
-      GST_QUARK (COLLECTION), GST_TYPE_STREAM_COLLECTION, collection, NULL);
+      gst_structure_new_static_str ("GstMessageStreamCollection",
+      "collection", GST_TYPE_STREAM_COLLECTION, collection, NULL);
   message =
       gst_message_new_custom (GST_MESSAGE_STREAM_COLLECTION, src, structure);
 
@@ -2884,8 +3007,8 @@ gst_message_parse_stream_collection (GstMessage * message,
       GST_MESSAGE_STREAM_COLLECTION);
 
   if (collection)
-    gst_structure_id_get (GST_MESSAGE_STRUCTURE (message),
-        GST_QUARK (COLLECTION), GST_TYPE_STREAM_COLLECTION, collection, NULL);
+    gst_structure_get (GST_MESSAGE_STRUCTURE (message),
+        "collection", GST_TYPE_STREAM_COLLECTION, collection, NULL);
 }
 
 /**
@@ -2920,10 +3043,10 @@ gst_message_new_streams_selected (GstObject * src,
   g_return_val_if_fail (GST_IS_STREAM_COLLECTION (collection), NULL);
 
   structure =
-      gst_structure_new_id (GST_QUARK (MESSAGE_STREAMS_SELECTED),
-      GST_QUARK (COLLECTION), GST_TYPE_STREAM_COLLECTION, collection, NULL);
+      gst_structure_new_static_str ("GstMessageStreamsSelected",
+      "collection", GST_TYPE_STREAM_COLLECTION, collection, NULL);
   g_value_init (&val, GST_TYPE_ARRAY);
-  gst_structure_id_take_value (structure, GST_QUARK (STREAMS), &val);
+  gst_structure_take_value (structure, "streams", &val);
   message =
       gst_message_new_custom (GST_MESSAGE_STREAMS_SELECTED, src, structure);
 
@@ -2949,9 +3072,7 @@ gst_message_streams_selected_get_size (GstMessage * msg)
   g_return_val_if_fail (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_STREAMS_SELECTED,
       0);
 
-  val =
-      gst_structure_id_get_value (GST_MESSAGE_STRUCTURE (msg),
-      GST_QUARK (STREAMS));
+  val = gst_structure_get_value (GST_MESSAGE_STRUCTURE (msg), "streams");
   return gst_value_array_get_size (val);
 }
 
@@ -2975,8 +3096,8 @@ gst_message_streams_selected_add (GstMessage * msg, GstStream * stream)
   g_return_if_fail (GST_IS_STREAM (stream));
 
   val =
-      (GValue *) gst_structure_id_get_value (GST_MESSAGE_STRUCTURE (msg),
-      GST_QUARK (STREAMS));
+      (GValue *) gst_structure_get_value (GST_MESSAGE_STRUCTURE (msg),
+      "streams");
   g_value_init (&to_add, GST_TYPE_STREAM);
   g_value_set_object (&to_add, stream);
   gst_value_array_append_and_take_value (val, &to_add);
@@ -3002,9 +3123,7 @@ gst_message_streams_selected_get_stream (GstMessage * msg, guint idx)
   g_return_val_if_fail (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_STREAMS_SELECTED,
       NULL);
 
-  streams =
-      gst_structure_id_get_value (GST_MESSAGE_STRUCTURE (msg),
-      GST_QUARK (STREAMS));
+  streams = gst_structure_get_value (GST_MESSAGE_STRUCTURE (msg), "streams");
   val = gst_value_array_get_value (streams, idx);
   if (val) {
     return (GstStream *) g_value_dup_object (val);
@@ -3031,8 +3150,8 @@ gst_message_parse_streams_selected (GstMessage * message,
   g_return_if_fail (GST_MESSAGE_TYPE (message) == GST_MESSAGE_STREAMS_SELECTED);
 
   if (collection)
-    gst_structure_id_get (GST_MESSAGE_STRUCTURE (message),
-        GST_QUARK (COLLECTION), GST_TYPE_STREAM_COLLECTION, collection, NULL);
+    gst_structure_get (GST_MESSAGE_STRUCTURE (message),
+        "collection", GST_TYPE_STREAM_COLLECTION, collection, NULL);
 }
 
 /**
@@ -3088,12 +3207,12 @@ gst_message_new_redirect (GstObject * src, const gchar * location,
   g_value_init (&entry_taglists_gvalue, GST_TYPE_LIST);
   g_value_init (&entry_structures_gvalue, GST_TYPE_LIST);
 
-  structure = gst_structure_new_id_empty (GST_QUARK (MESSAGE_REDIRECT));
-  gst_structure_id_take_value (structure, GST_QUARK (REDIRECT_ENTRY_LOCATIONS),
+  structure = gst_structure_new_static_str_empty ("GstMessageRedirect");
+  gst_structure_take_value_static_str (structure, "redirect-entry-locations",
       &entry_locations_gvalue);
-  gst_structure_id_take_value (structure, GST_QUARK (REDIRECT_ENTRY_TAGLISTS),
+  gst_structure_take_value_static_str (structure, "redirect-entry-taglists",
       &entry_taglists_gvalue);
-  gst_structure_id_take_value (structure, GST_QUARK (REDIRECT_ENTRY_STRUCTURES),
+  gst_structure_take_value_static_str (structure, "redirect-entry-structures",
       &entry_structures_gvalue);
 
   message = gst_message_new_custom (GST_MESSAGE_REDIRECT, src, structure);
@@ -3135,16 +3254,15 @@ gst_message_add_redirect_entry (GstMessage * message, const gchar * location,
   structure = GST_MESSAGE_STRUCTURE (message);
 
   entry_locations_gvalue =
-      (GValue *) gst_structure_id_get_value (structure,
-      GST_QUARK (REDIRECT_ENTRY_LOCATIONS));
+      (GValue *) gst_structure_get_value (structure,
+      "redirect-entry-locations");
   g_return_if_fail (GST_VALUE_HOLDS_LIST (entry_locations_gvalue));
   entry_taglists_gvalue =
-      (GValue *) gst_structure_id_get_value (structure,
-      GST_QUARK (REDIRECT_ENTRY_TAGLISTS));
+      (GValue *) gst_structure_get_value (structure, "redirect-entry-taglists");
   g_return_if_fail (GST_VALUE_HOLDS_LIST (entry_taglists_gvalue));
   entry_structures_gvalue =
-      (GValue *) gst_structure_id_get_value (structure,
-      GST_QUARK (REDIRECT_ENTRY_STRUCTURES));
+      (GValue *) gst_structure_get_value (structure,
+      "redirect-entry-structures");
   g_return_if_fail (GST_VALUE_HOLDS_LIST (entry_structures_gvalue));
 
   g_value_init (&val, G_TYPE_STRING);
@@ -3200,16 +3318,13 @@ gst_message_parse_redirect_entry (GstMessage * message, gsize entry_index,
   structure = GST_MESSAGE_STRUCTURE (message);
 
   entry_locations_gvalue =
-      gst_structure_id_get_value (structure,
-      GST_QUARK (REDIRECT_ENTRY_LOCATIONS));
+      gst_structure_get_value (structure, "redirect-entry-locations");
   g_return_if_fail (GST_VALUE_HOLDS_LIST (entry_locations_gvalue));
   entry_taglists_gvalue =
-      gst_structure_id_get_value (structure,
-      GST_QUARK (REDIRECT_ENTRY_TAGLISTS));
+      gst_structure_get_value (structure, "redirect-entry-taglists");
   g_return_if_fail (GST_VALUE_HOLDS_LIST (entry_taglists_gvalue));
   entry_structures_gvalue =
-      gst_structure_id_get_value (structure,
-      GST_QUARK (REDIRECT_ENTRY_STRUCTURES));
+      gst_structure_get_value (structure, "redirect-entry-structures");
   g_return_if_fail (GST_VALUE_HOLDS_LIST (entry_structures_gvalue));
 
   if (location) {
@@ -3254,16 +3369,13 @@ gst_message_get_num_redirect_entries (GstMessage * message)
   structure = GST_MESSAGE_STRUCTURE (message);
 
   entry_locations_gvalue =
-      gst_structure_id_get_value (structure,
-      GST_QUARK (REDIRECT_ENTRY_LOCATIONS));
+      gst_structure_get_value (structure, "redirect-entry-locations");
   g_return_val_if_fail (GST_VALUE_HOLDS_LIST (entry_locations_gvalue), 0);
   entry_taglists_gvalue =
-      gst_structure_id_get_value (structure,
-      GST_QUARK (REDIRECT_ENTRY_TAGLISTS));
+      gst_structure_get_value (structure, "redirect-entry-taglists");
   g_return_val_if_fail (GST_VALUE_HOLDS_LIST (entry_taglists_gvalue), 0);
   entry_structures_gvalue =
-      gst_structure_id_get_value (structure,
-      GST_QUARK (REDIRECT_ENTRY_STRUCTURES));
+      gst_structure_get_value (structure, "redirect-entry-structures");
   g_return_val_if_fail (GST_VALUE_HOLDS_LIST (entry_structures_gvalue), 0);
 
   size = gst_value_list_get_size (entry_locations_gvalue);
@@ -3299,8 +3411,8 @@ gst_message_new_instant_rate_request (GstObject * src, gdouble rate_multiplier)
 
   g_return_val_if_fail (rate_multiplier != 0.0, NULL);
 
-  structure = gst_structure_new_id (GST_QUARK (MESSAGE_INSTANT_RATE_REQUEST),
-      GST_QUARK (RATE), G_TYPE_DOUBLE, rate_multiplier, NULL);
+  structure = gst_structure_new_static_str ("GstMessageInstantRateRequest",
+      "rate", G_TYPE_DOUBLE, rate_multiplier, NULL);
   message =
       gst_message_new_custom (GST_MESSAGE_INSTANT_RATE_REQUEST, src, structure);
 
@@ -3327,8 +3439,7 @@ gst_message_parse_instant_rate_request (GstMessage * message,
       GST_MESSAGE_INSTANT_RATE_REQUEST);
 
   structure = GST_MESSAGE_STRUCTURE (message);
-  gst_structure_id_get (structure, GST_QUARK (RATE), G_TYPE_DOUBLE,
-      rate_multiplier, NULL);
+  gst_structure_get (structure, "rate", G_TYPE_DOUBLE, rate_multiplier, NULL);
 }
 
 /**
diff --git a/gst/gstmessage.h b/gst/gstmessage.h
index ea3f49f..ddb23d0 100644
--- a/gst/gstmessage.h
+++ b/gst/gstmessage.h
@@ -462,6 +462,16 @@ GstStructure *  gst_message_writable_structure  (GstMessage *message);
 GST_API
 gboolean        gst_message_has_name            (GstMessage *message, const gchar *name);
 
+GST_API
+void            gst_message_set_details         (GstMessage *message, GstStructure *details);
+
+GST_API
+const GstStructure *
+                gst_message_get_details         (GstMessage *message);
+
+GST_API
+GstStructure *  gst_message_writable_details    (GstMessage *message);
+
 /* identifiers for events and messages */
 
 GST_API
@@ -489,6 +499,9 @@ void            gst_message_parse_error         (GstMessage *message, GError **g
 GST_API
 void            gst_message_parse_error_details (GstMessage *message, const GstStructure **structure);
 
+GST_API
+void            gst_message_parse_error_writable_details (GstMessage *message, GstStructure **structure);
+
 /* WARNING */
 
 GST_API
@@ -503,6 +516,9 @@ void            gst_message_parse_warning       (GstMessage *message, GError **g
 GST_API
 void            gst_message_parse_warning_details (GstMessage *message, const GstStructure **structure);
 
+GST_API
+void            gst_message_parse_warning_writable_details (GstMessage *message, GstStructure **structure);
+
 /* INFO */
 
 GST_API
@@ -517,6 +533,9 @@ void            gst_message_parse_info          (GstMessage *message, GError **g
 GST_API
 void            gst_message_parse_info_details  (GstMessage *message, const GstStructure **structure);
 
+GST_API
+void            gst_message_parse_info_writable_details  (GstMessage *message, GstStructure **structure);
+
 /* TAG */
 
 GST_API
diff --git a/gst/gstmeta.c b/gst/gstmeta.c
index 6667aff..cbf59aa 100644
--- a/gst/gstmeta.c
+++ b/gst/gstmeta.c
@@ -50,7 +50,6 @@
 #include "gstmeta.h"
 #include "gstinfo.h"
 #include "gstutils.h"
-#include "gstquark.h"
 
 static GHashTable *metainfo = NULL;
 static GRWLock lock;
@@ -58,6 +57,8 @@ static GRWLock lock;
 GQuark _gst_meta_transform_copy;
 GQuark _gst_meta_tag_memory;
 GQuark _gst_meta_tag_memory_reference;
+static GQuark _gst_meta_tags_quark;
+static GQuark _gst_allocation_meta_params_aggregator_quark;
 
 typedef struct
 {
@@ -84,6 +85,9 @@ _priv_gst_meta_initialize (void)
   _gst_meta_tag_memory = g_quark_from_static_string ("memory");
   _gst_meta_tag_memory_reference =
       g_quark_from_static_string ("memory-reference");
+  _gst_meta_tags_quark = g_quark_from_static_string ("tags");
+  _gst_allocation_meta_params_aggregator_quark =
+      g_quark_from_static_string ("GstAllocationMetaParamsAggregator");
 }
 
 static gboolean
@@ -139,7 +143,7 @@ gst_meta_api_type_register (const gchar * api, const gchar ** tags)
     }
   }
 
-  g_type_set_qdata (type, GST_QUARK (TAGS), g_strdupv ((gchar **) tags));
+  g_type_set_qdata (type, _gst_meta_tags_quark, g_strdupv ((gchar **) tags));
 
   return type;
 }
@@ -272,8 +276,8 @@ gst_custom_meta_has_name (GstCustomMeta * meta, const gchar * name)
  * gst_meta_register_custom:
  * @name: the name of the #GstMeta implementation
  * @tags: (array zero-terminated=1): tags for @api
- * @transform_func: (scope notified) (nullable): a #GstMetaTransformFunction
- * @user_data: (closure): user data passed to @transform_func
+ * @transform_func: (scope notified) (nullable) (closure user_data): a #GstMetaTransformFunction
+ * @user_data: user data passed to @transform_func
  * @destroy_data: #GDestroyNotify for user_data
  *
  * Register a new custom #GstMeta implementation, backed by an opaque
@@ -400,7 +404,7 @@ gst_meta_api_type_get_tags (GType api)
   const gchar **tags;
   g_return_val_if_fail (api != 0, FALSE);
 
-  tags = g_type_get_qdata (api, GST_QUARK (TAGS));
+  tags = g_type_get_qdata (api, _gst_meta_tags_quark);
 
   if (!tags[0])
     return NULL;
@@ -408,6 +412,62 @@ gst_meta_api_type_get_tags (GType api)
   return (const gchar * const *) tags;
 }
 
+/**
+ * gst_meta_api_type_aggregate_params:
+ * @api: the GType of the API for which the parameters are being aggregated.
+ * @aggregated_params: This structure will be updated with the
+ *                     combined parameters from both @params0 and @params1.
+ * @params0: a #GstStructure containing the new parameters to be aggregated.
+ * @params1: a #GstStructure containing the new parameters to be aggregated.
+ *
+ * When a element like `tee` decides the allocation, each downstream element may
+ * fill different parameters and pass them to gst_query_add_allocation_meta().
+ * In order to keep these parameters, a merge operation is needed. This
+ * aggregate function can combine the parameters from @params0 and @param1, and
+ * write the result back into @aggregated_params.
+ *
+ * Returns: %TRUE if the parameters were successfully aggregated, %FALSE otherwise.
+ *
+ * Since: 1.26
+ */
+gboolean
+gst_meta_api_type_aggregate_params (GType api,
+    GstStructure ** aggregated_params, const GstStructure * params0,
+    const GstStructure * params1)
+{
+  g_return_val_if_fail (api != 0, FALSE);
+  g_return_val_if_fail (aggregated_params != NULL, FALSE);
+
+  GstAllocationMetaParamsAggregator aggregator_func =
+      g_type_get_qdata (api, _gst_allocation_meta_params_aggregator_quark);
+
+  if (!aggregator_func)
+    return FALSE;
+
+  return aggregator_func (aggregated_params, params0, params1);
+}
+
+/**
+ * gst_meta_api_type_set_params_aggregator:
+ * @api: the #GType of the API for which the aggregator function is being set.
+ * @aggregator: (scope forever): the aggregator function to be associated with the given API
+ *              type.
+ *
+ * This function sets the aggregator function for a specific API type.
+ *
+ * Since: 1.26
+ */
+void
+gst_meta_api_type_set_params_aggregator (GType api,
+    GstAllocationMetaParamsAggregator aggregator)
+{
+  g_return_if_fail (api != 0);
+  g_return_if_fail (aggregator != NULL);
+
+  g_type_set_qdata (api, _gst_allocation_meta_params_aggregator_quark,
+      (GstAllocationMetaParamsAggregator) aggregator);
+}
+
 static const GstMetaInfo *
 gst_meta_register_internal (GType api, const gchar * impl, gsize size,
     GstMetaInitFunction init_func, GstMetaFreeFunction free_func,
diff --git a/gst/gstmeta.h b/gst/gstmeta.h
index 2148471..ddeb098 100644
--- a/gst/gstmeta.h
+++ b/gst/gstmeta.h
@@ -292,6 +292,24 @@ typedef GstMeta *(*GstMetaDeserializeFunction) (const GstMetaInfo *info,
  */
 typedef void (*GstMetaClearFunction) (GstBuffer *buffer, GstMeta *meta);
 
+/**
+ * GstAllocationMetaParamsAggregator:
+ * @aggregated_params: This structure will be updated with the
+ *                     combined parameters from both @params0 and @params1.
+ * @params0: a #GstStructure containing the new parameters to be aggregated.
+ * @params1: a #GstStructure containing the new parameters to be aggregated.
+ *
+ * The aggregator function will combine the parameters from @params0 and @param1
+ * and write the result back into @aggregated_params.
+ *
+ * Returns: %TRUE if the parameters were successfully aggregated, %FALSE otherwise.
+ *
+ * Since: 1.26
+ */
+typedef gboolean (*GstAllocationMetaParamsAggregator) (GstStructure ** aggregated_params,
+                                                       const GstStructure * params0,
+                                                       const GstStructure * params1);
+
 /**
  * GstMetaInfo.serialize_func:
  *
@@ -359,6 +377,16 @@ GType                gst_meta_api_type_register (const gchar *api,
 GST_API
 gboolean             gst_meta_api_type_has_tag  (GType api, GQuark tag);
 
+GST_API
+gboolean             gst_meta_api_type_aggregate_params (GType api,
+                                                         GstStructure ** aggregated_params,
+                                                         const GstStructure * params0,
+                                                         const GstStructure * params1);
+
+GST_API
+void                 gst_meta_api_type_set_params_aggregator (GType api,
+                                                              GstAllocationMetaParamsAggregator aggregator);
+
 GST_API
 const GstMetaInfo *  gst_meta_register          (GType api, const gchar *impl,
                                                  gsize size,
diff --git a/gst/gstpad.c b/gst/gstpad.c
index 2341808..ff7c630 100644
--- a/gst/gstpad.c
+++ b/gst/gstpad.c
@@ -195,6 +195,15 @@ static GstFlowReturn gst_pad_push_event_unchecked (GstPad * pad,
 static gboolean activate_mode_internal (GstPad * pad, GstObject * parent,
     GstPadMode mode, gboolean active);
 
+typedef struct
+{
+  GstPad *pad;
+  GstFlowReturn flow_res;
+} PadChainListData;
+
+static gboolean list_process_buffer_writable (GstBuffer ** buffer, guint idx,
+    gpointer userdata);
+
 static guint gst_pad_signals[LAST_SIGNAL] = { 0 };
 
 static GParamSpec *pspec_caps = NULL;
@@ -1408,9 +1417,9 @@ cleanup_hook (GstPad * pad, GHook * hook)
  * gst_pad_add_probe:
  * @pad: the #GstPad to add the probe to
  * @mask: the probe mask
- * @callback: #GstPadProbeCallback that will be called with notifications of
- *           the pad state
- * @user_data: (closure): user data passed to the callback
+ * @callback: (closure user_data): #GstPadProbeCallback that will be called with
+ *           notifications of the pad state
+ * @user_data: user data passed to the callback
  * @destroy_data: #GDestroyNotify for user_data
  *
  * Be notified of different states of pads. The provided callback is called for
@@ -4014,13 +4023,24 @@ mark_event_not_received (GstPad * pad, PadEvent * ev, gpointer user_data)
  * @pad: a #GstPad
  * @offset: the offset
  *
- * Set the offset that will be applied to the running time of @pad.
+ * Set the offset that will be applied to the running time of @pad. Upon next
+ * buffer, every sticky events (notably segment) will be pushed again with
+ * their running time adjusted. For that reason this is only reliable on
+ * source pads.
  */
 void
 gst_pad_set_offset (GstPad * pad, gint64 offset)
 {
   g_return_if_fail (GST_IS_PAD (pad));
 
+  /* Setting pad offset on a sink pad does not work reliably:
+   * https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6464 */
+  if (GST_PAD_IS_SINK (pad)) {
+    /* Make it non fatal warning for backward compatibility. */
+    GST_WARNING_OBJECT (pad,
+        "Setting pad offset only works reliably on source pads");
+  }
+
   GST_OBJECT_LOCK (pad);
   /* if nothing changed, do nothing */
   if (pad->offset == offset)
@@ -4080,8 +4100,10 @@ push_sticky (GstPad * pad, PadEvent * ev, gpointer user_data)
       data_sticky_order < ev->sticky_order) {
     data->ret = GST_FLOW_CUSTOM_SUCCESS_1;
   } else {
+    GST_TRACER_PAD_PUSH_EVENT_PRE (pad, event);
     data->ret = gst_pad_push_event_unchecked (pad, gst_event_ref (event),
         GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM);
+    GST_TRACER_PAD_PUSH_EVENT_POST (pad, data->ret >= GST_FLOW_OK);
     if (data->ret == GST_FLOW_CUSTOM_SUCCESS_1)
       data->ret = GST_FLOW_OK;
   }
@@ -4152,8 +4174,10 @@ check_sticky (GstPad * pad, GstEvent * event)
       PadEvent *ev = find_event_by_type (pad, GST_EVENT_EOS, 0);
 
       if (ev && !ev->received) {
+        GST_TRACER_PAD_PUSH_EVENT_PRE (pad, event);
         data.ret = gst_pad_push_event_unchecked (pad, gst_event_ref (ev->event),
             GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM);
+        GST_TRACER_PAD_PUSH_EVENT_POST (pad, data.ret >= GST_FLOW_OK);
         /* the event could have been dropped. Because this can only
          * happen if the user asked for it, it's not an error */
         if (data.ret == GST_FLOW_CUSTOM_SUCCESS)
@@ -4645,6 +4669,16 @@ gst_pad_chain (GstPad * pad, GstBuffer * buffer)
       GST_PAD_PROBE_TYPE_BUFFER | GST_PAD_PROBE_TYPE_PUSH, buffer);
 }
 
+static gboolean
+list_process_buffer_writable (GstBuffer ** buffer, guint idx, gpointer userdata)
+{
+  PadChainListData *data = (PadChainListData *) (userdata);
+  data->flow_res = gst_pad_chain_data_unchecked (data->pad,
+      GST_PAD_PROBE_TYPE_BUFFER | GST_PAD_PROBE_TYPE_PUSH, *buffer);
+  *buffer = NULL;
+  return data->flow_res == GST_FLOW_OK;
+}
+
 static GstFlowReturn
 gst_pad_chain_list_default (GstPad * pad, GstObject * parent,
     GstBufferList * list)
@@ -4655,18 +4689,25 @@ gst_pad_chain_list_default (GstPad * pad, GstObject * parent,
 
   GST_LOG_OBJECT (pad, "chaining each buffer in list individually");
 
-  len = gst_buffer_list_length (list);
-
   ret = GST_FLOW_OK;
-  for (i = 0; i < len; i++) {
-    buffer = gst_buffer_list_get (list, i);
-    ret =
-        gst_pad_chain_data_unchecked (pad,
-        GST_PAD_PROBE_TYPE_BUFFER | GST_PAD_PROBE_TYPE_PUSH,
-        gst_buffer_ref (buffer));
-    if (ret != GST_FLOW_OK)
-      break;
+
+  if (gst_buffer_list_is_writable (list)) {
+    PadChainListData data = {.pad = pad,.flow_res = GST_FLOW_OK };
+    gst_buffer_list_foreach (list, list_process_buffer_writable, &data);
+    ret = data.flow_res;
+  } else {
+    len = gst_buffer_list_length (list);
+    for (i = 0; i < len; i++) {
+      buffer = gst_buffer_list_get (list, i);
+      ret =
+          gst_pad_chain_data_unchecked (pad,
+          GST_PAD_PROBE_TYPE_BUFFER | GST_PAD_PROBE_TYPE_PUSH,
+          gst_buffer_ref (buffer));
+      if (ret != GST_FLOW_OK)
+        break;
+    }
   }
+
   gst_buffer_list_unref (list);
 
   return ret;
@@ -5335,8 +5376,9 @@ store_sticky_event (GstPad * pad, GstEvent * event)
   GstEventType type;
   GArray *events;
   gboolean res = FALSE;
-  GQuark name_id = 0;
+  const gchar *name = NULL;
   gboolean insert = TRUE;
+  gboolean changed_stream_id = FALSE;
 
   type = GST_EVENT_TYPE (event);
   guint sticky_order = _to_sticky_order (type);
@@ -5353,10 +5395,9 @@ store_sticky_event (GstPad * pad, GstEvent * event)
   /* Unset the EOS flag when received STREAM_START event, so pad can
    * store sticky event and then push it later */
   if (type == GST_EVENT_STREAM_START) {
-    GST_LOG_OBJECT (pad, "Removing pending EOS, StreamGroupDone, TAG events");
+    GST_LOG_OBJECT (pad, "Removing pending EOS, StreamGroupDone events");
     remove_event_by_type (pad, GST_EVENT_EOS);
     remove_event_by_type (pad, GST_EVENT_STREAM_GROUP_DONE);
-    remove_event_by_type (pad, GST_EVENT_TAG);
     GST_OBJECT_FLAG_UNSET (pad, GST_PAD_FLAG_EOS);
   }
 
@@ -5364,7 +5405,7 @@ store_sticky_event (GstPad * pad, GstEvent * event)
     goto eos;
 
   if (type & GST_EVENT_TYPE_STICKY_MULTI)
-    name_id = gst_structure_get_name_id (gst_event_get_structure (event));
+    name = gst_structure_get_name (gst_event_get_structure (event));
 
   events = pad->priv->events;
   len = events->len;
@@ -5377,9 +5418,18 @@ store_sticky_event (GstPad * pad, GstEvent * event)
 
     if (type == GST_EVENT_TYPE (ev->event)) {
       /* matching types, check matching name if needed */
-      if (name_id && !gst_event_has_name_id (ev->event, name_id))
+      if (name && !gst_event_has_name (ev->event, name))
         continue;
 
+      if (type == GST_EVENT_STREAM_START && event != ev->event) {
+        const gchar *old_stream_id, *new_stream_id;
+
+        gst_event_parse_stream_start (ev->event, &old_stream_id);
+        gst_event_parse_stream_start (event, &new_stream_id);
+
+        changed_stream_id = !g_str_equal (old_stream_id, new_stream_id);
+      }
+
       /* overwrite */
       if ((res = gst_event_replace (&ev->event, event)))
         ev->received = FALSE;
@@ -5409,6 +5459,12 @@ store_sticky_event (GstPad * pad, GstEvent * event)
     ev.received = FALSE;
     g_array_insert_val (events, i, ev);
     res = TRUE;
+    changed_stream_id = type == GST_EVENT_STREAM_START;
+  }
+
+  if (changed_stream_id) {
+    GST_LOG_OBJECT (pad, "Removing pending TAG events");
+    remove_event_by_type (pad, GST_EVENT_TAG);
   }
 
   if (res) {
@@ -5545,6 +5601,8 @@ gst_pad_push_event_unchecked (GstPad * pad, GstEvent * event,
         case GST_EVENT_RECONFIGURE:
           if (GST_PAD_IS_SINK (pad))
             GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_NEED_RECONFIGURE);
+          if (pad->ABI.abi.last_flowret == GST_FLOW_NOT_LINKED)
+            pad->ABI.abi.last_flowret = GST_FLOW_OK;
           break;
         default:
           break;
@@ -5845,6 +5903,7 @@ gst_pad_send_event_unchecked (GstPad * pad, GstEvent * event,
   GstObject *parent;
   gint64 old_pad_offset;
 
+  GST_TRACER_PAD_SEND_EVENT_PRE (pad, event);
   GST_OBJECT_LOCK (pad);
 
   old_pad_offset = pad->offset;
@@ -5896,9 +5955,6 @@ gst_pad_send_event_unchecked (GstPad * pad, GstEvent * event,
       if (G_UNLIKELY (GST_PAD_IS_FLUSHING (pad)))
         goto flushing;
       break;
-    case GST_EVENT_RECONFIGURE:
-      if (GST_PAD_IS_SRC (pad))
-        GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_NEED_RECONFIGURE);
     default:
       GST_CAT_DEBUG_OBJECT (GST_CAT_EVENT, pad,
           "have event type %" GST_PTR_FORMAT, event);
@@ -5926,6 +5982,12 @@ gst_pad_send_event_unchecked (GstPad * pad, GstEvent * event,
           remove_event_by_type (pad, GST_EVENT_TAG);
           GST_OBJECT_FLAG_UNSET (pad, GST_PAD_FLAG_EOS);
           break;
+        case GST_EVENT_RECONFIGURE:
+          if (GST_PAD_IS_SRC (pad))
+            GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_NEED_RECONFIGURE);
+          if (pad->ABI.abi.last_flowret == GST_FLOW_NOT_LINKED)
+            pad->ABI.abi.last_flowret = GST_FLOW_OK;
+          break;
         default:
           if (serialized) {
             /* Take the stream lock to check the EOS status and drop the event
@@ -6017,7 +6079,7 @@ gst_pad_send_event_unchecked (GstPad * pad, GstEvent * event,
   if (need_unlock)
     GST_PAD_STREAM_UNLOCK (pad);
 
-  return ret;
+  goto done;
 
   /* ERROR handling */
 flushing:
@@ -6028,7 +6090,8 @@ flushing:
     GST_CAT_INFO_OBJECT (GST_CAT_EVENT, pad,
         "Received event on flushing pad. Discarding");
     gst_event_unref (event);
-    return GST_FLOW_FLUSHING;
+    ret = GST_FLOW_FLUSHING;
+    goto done;
   }
 inactive:
   {
@@ -6038,7 +6101,8 @@ inactive:
     GST_CAT_INFO_OBJECT (GST_CAT_EVENT, pad,
         "Received flush-stop on inactive pad. Discarding");
     gst_event_unref (event);
-    return GST_FLOW_FLUSHING;
+    ret = GST_FLOW_FLUSHING;
+    goto done;
   }
 eos:
   {
@@ -6048,7 +6112,8 @@ eos:
     GST_CAT_INFO_OBJECT (GST_CAT_EVENT, pad,
         "Received event on EOS pad. Discarding");
     gst_event_unref (event);
-    return GST_FLOW_EOS;
+    ret = GST_FLOW_EOS;
+    goto done;
   }
 probe_stopped:
   {
@@ -6069,7 +6134,7 @@ probe_stopped:
         GST_DEBUG_OBJECT (pad, "an error occurred %s", gst_flow_get_name (ret));
         break;
     }
-    return ret;
+    goto done;
   }
 no_function:
   {
@@ -6079,7 +6144,8 @@ no_function:
     if (need_unlock)
       GST_PAD_STREAM_UNLOCK (pad);
     gst_event_unref (event);
-    return GST_FLOW_NOT_SUPPORTED;
+    ret = GST_FLOW_NOT_SUPPORTED;
+    goto done;
   }
 no_parent:
   {
@@ -6088,7 +6154,8 @@ no_parent:
     if (need_unlock)
       GST_PAD_STREAM_UNLOCK (pad);
     gst_event_unref (event);
-    return GST_FLOW_FLUSHING;
+    ret = GST_FLOW_FLUSHING;
+    goto done;
   }
 precheck_failed:
   {
@@ -6097,8 +6164,11 @@ precheck_failed:
     if (need_unlock)
       GST_PAD_STREAM_UNLOCK (pad);
     gst_event_unref (event);
-    return ret;
+    goto done;
   }
+done:
+  GST_TRACER_PAD_SEND_EVENT_POST (pad, ret);
+  return ret;
 }
 
 /**
@@ -6259,9 +6329,9 @@ foreach_dispatch_function (GstPad * pad, PadEvent * ev, gpointer user_data)
 /**
  * gst_pad_sticky_events_foreach:
  * @pad: the #GstPad that should be used for iteration.
- * @foreach_func: (scope call): the #GstPadStickyEventsForeachFunction that
- *                should be called for every event.
- * @user_data: (closure): the optional user data.
+ * @foreach_func: (scope call) (closure user_data): the
+ *    #GstPadStickyEventsForeachFunction that should be called for every event.
+ * @user_data: the optional user data.
  *
  * Iterates all sticky events on @pad and calls @foreach_func for every
  * event. If @foreach_func returns %FALSE the iteration is immediately stopped.
diff --git a/gst/gstplugin.c b/gst/gstplugin.c
index 4a99635..10ad0b0 100644
--- a/gst/gstplugin.c
+++ b/gst/gstplugin.c
@@ -315,6 +315,10 @@ _priv_gst_plugin_initialize (void)
 
   _gst_plugin_inited = TRUE;
 
+  _priv_gst_plugin_api_quark = g_quark_from_static_string ("plugin-api");
+  _priv_gst_plugin_api_flags_quark =
+      g_quark_from_static_string ("plugin-api-flags");
+
   whitelist = g_getenv ("GST_PLUGIN_LOADING_WHITELIST");
   if (whitelist != NULL && *whitelist != '\0') {
     _plugin_loading_whitelist = g_strsplit (whitelist,
diff --git a/gst/gstpluginloader-win32.c b/gst/gstpluginloader-win32.c
index 0b31d3a..2a40984 100644
--- a/gst/gstpluginloader-win32.c
+++ b/gst/gstpluginloader-win32.c
@@ -1090,7 +1090,8 @@ gst_plugin_loader_new (GstRegistry * registry)
 
   /* Checks whether helper bin is installed or not. Expected exit code is 1 */
   ret = CreateProcessW (NULL, helper_bin_location_wide, NULL, NULL, FALSE,
-      CREATE_UNICODE_ENVIRONMENT, env_string, NULL, &si, &pi);
+      CREATE_UNICODE_ENVIRONMENT | CREATE_NO_WINDOW, env_string,
+      NULL, &si, &pi);
   g_free (helper_bin_location_wide);
 
   if (!ret) {
diff --git a/gst/gstpreset.c b/gst/gstpreset.c
index ed25b5b..e0d4597 100644
--- a/gst/gstpreset.c
+++ b/gst/gstpreset.c
@@ -90,6 +90,8 @@
 extern HMODULE _priv_gst_dll_handle;
 #endif
 
+#include "glib-compat-private.h"
+
 #define GST_CAT_DEFAULT preset_debug
 GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
 
@@ -546,7 +548,7 @@ gst_preset_default_get_preset_names (GstPreset * preset)
   }
 
   /* sort the array now */
-  g_qsort_with_data (groups, num_groups, sizeof (gchar *),
+  g_sort_array (groups, num_groups, sizeof (gchar *),
       (GCompareDataFunc) compare_strings, NULL);
 
   return groups;
diff --git a/gst/gstpromise.c b/gst/gstpromise.c
index 6e0e3eb..97a9b1e 100644
--- a/gst/gstpromise.c
+++ b/gst/gstpromise.c
@@ -381,8 +381,8 @@ gst_promise_new (void)
 
 /**
  * gst_promise_new_with_change_func:
- * @func: (scope notified): a #GstPromiseChangeFunc to call
- * @user_data: (closure): argument to call @func with
+ * @func: (scope notified) (closure user_data): a #GstPromiseChangeFunc to call
+ * @user_data: argument to call @func with
  * @notify: notification function that @user_data is no longer needed
  *
  * @func will be called exactly once when transitioning out of
diff --git a/gst/gstquark.c b/gst/gstquark.c
deleted file mode 100644
index 304e274..0000000
--- a/gst/gstquark.c
+++ /dev/null
@@ -1,100 +0,0 @@
-/* GStreamer
- * Copyright (C) 2006 Jan Schmidt <thaytan@noraisin.net>
- *
- * gstquark.c: Registered quarks for the _priv_gst_quark_table, private to 
- *   GStreamer
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "gst_private.h"
-#include "gstquark.h"
-#include "gstelementmetadata.h"
-
-/* These strings must match order and number declared in the GstQuarkId
- * enum in gstquark.h! */
-static const gchar *_quark_strings[] = {
-  "format", "current", "duration", "rate",
-  "seekable", "segment-start", "segment-end",
-  "src_format", "src_value", "dest_format", "dest_value",
-  "start_format", "start_value", "stop_format", "stop_value",
-  "gerror", "debug", "buffer-percent", "buffering-mode",
-  "avg-in-rate", "avg-out-rate", "buffering-left",
-  "estimated-total", "old-state", "new-state", "pending-state",
-  "clock", "ready", "position", "reset-time", "live", "min-latency",
-  "max-latency", "busy", "type", "owner", "update", "applied-rate",
-  "start", "stop", "minsize", "maxsize", "async", "proportion",
-  "diff", "timestamp", "flags", "cur-type", "cur", "stop-type",
-  "latency", "uri", "object", "taglist", "GstEventSegment",
-  "GstEventBufferSize", "GstEventQOS", "GstEventSeek", "GstEventLatency",
-  "GstMessageError", "GstMessageWarning", "GstMessageInfo",
-  "GstMessageBuffering", "GstMessageStateChanged", "GstMessageClockProvide",
-  "GstMessageClockLost", "GstMessageNewClock", "GstMessageStructureChange",
-  "GstMessageSegmentStart", "GstMessageSegmentDone",
-  "GstMessageDurationChanged",
-  "GstMessageAsyncDone", "GstMessageRequestState", "GstMessageStreamStatus",
-  "GstQueryPosition", "GstQueryDuration", "GstQueryLatency", "GstQueryConvert",
-  "GstQuerySegment", "GstQuerySeeking", "GstQueryFormats", "GstQueryBuffering",
-  "GstQueryURI", "GstEventStep", "GstMessageStepDone", "amount", "flush",
-  "intermediate", "GstMessageStepStart", "active", "eos", "sink-message",
-  "message", "GstMessageQOS", "running-time", "stream-time", "jitter",
-  "quality", "processed", "dropped", "buffering-ranges", "GstMessageProgress",
-  "code", "text", "percent", "timeout", "GstBufferPoolConfig", "caps", "size",
-  "min-buffers", "max-buffers", "prefix", "padding", "align", "time",
-  "GstQueryAllocation", "need-pool", "meta", "pool", "GstEventCaps",
-  "GstEventReconfigure", "segment", "GstQueryScheduling", "pull-mode",
-  "allocator", "GstEventFlushStop", "options", "GstQueryAcceptCaps",
-  "result", "GstQueryCaps", "filter", "modes", "GstEventStreamConfig",
-  "setup-data", "stream-headers", "GstEventGap", "GstQueryDrain", "params",
-  "GstEventTocSelect", "uid", "GstQueryToc", GST_ELEMENT_METADATA_LONGNAME,
-  GST_ELEMENT_METADATA_KLASS, GST_ELEMENT_METADATA_DESCRIPTION,
-  GST_ELEMENT_METADATA_AUTHOR, "toc", "toc-entry", "updated", "extend-uid",
-  "uid", "tags", "sub-entries", "info", "GstMessageTag", "GstEventTag",
-  "GstMessageResetTime",
-  "GstMessageToc", "GstEventTocGlobal", "GstEventTocCurrent",
-  "GstEventSegmentDone",
-  "GstEventStreamStart", "stream-id", "GstQueryContext",
-  "GstMessageNeedContext", "GstMessageHaveContext", "context", "context-type",
-  "GstMessageStreamStart", "group-id", "uri-redirection",
-  "GstMessageDeviceAdded", "GstMessageDeviceRemoved", "device",
-  "uri-redirection-permanent", "GstMessagePropertyNotify", "property-name",
-  "property-value", "streams", "GstEventSelectStreams",
-  "GstMessageStreamCollection", "collection", "stream", "stream-collection",
-  "GstMessageStreamsSelected", "GstMessageRedirect", "redirect-entry-locations",
-  "redirect-entry-taglists", "redirect-entry-structures",
-  "GstEventStreamGroupDone", "GstQueryBitrate", "nominal-bitrate",
-  "GstMessageDeviceChanged", "device-changed", "trickmode-interval",
-  "GstEventInstantRateChange",
-  "GstEventInstantRateSyncTime", "GstMessageInstantRateRequest",
-  "upstream-running-time", "base", "offset", "plugin-api", "plugin-api-flags",
-  "gap-flags", "GstQuerySelectable", "selectable"
-};
-
-GQuark _priv_gst_quark_table[GST_QUARK_MAX];
-
-void
-_priv_gst_quarks_initialize (void)
-{
-  gint i;
-
-  if (G_N_ELEMENTS (_quark_strings) != GST_QUARK_MAX)
-    g_warning ("the quark table is not consistent! %d != %d",
-        (int) G_N_ELEMENTS (_quark_strings), GST_QUARK_MAX);
-
-  for (i = 0; i < GST_QUARK_MAX; i++) {
-    _priv_gst_quark_table[i] = g_quark_from_static_string (_quark_strings[i]);
-  }
-}
diff --git a/gst/gstquark.h b/gst/gstquark.h
deleted file mode 100644
index f7de510..0000000
--- a/gst/gstquark.h
+++ /dev/null
@@ -1,243 +0,0 @@
-/* GStreamer
- * Copyright (C) 2006 Jan Schmidt <thaytan@noraisin.net>
- *
- * gstquark.h: Private header for storing quark info 
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef __GST_QUARK_H__
-#define __GST_QUARK_H__
-
-#include <glib.h>
-
-/* These enums need to match the number and order
- * of strings declared in _quark_table, in gstquark.c */
-typedef enum _GstQuarkId
-{
-  GST_QUARK_FORMAT = 0,
-  GST_QUARK_CURRENT = 1,
-  GST_QUARK_DURATION = 2,
-  GST_QUARK_RATE = 3,
-  GST_QUARK_SEEKABLE = 4,
-  GST_QUARK_SEGMENT_START = 5,
-  GST_QUARK_SEGMENT_END = 6,
-  GST_QUARK_SRC_FORMAT = 7,
-  GST_QUARK_SRC_VALUE = 8,
-  GST_QUARK_DEST_FORMAT = 9,
-  GST_QUARK_DEST_VALUE = 10,
-  GST_QUARK_START_FORMAT = 11,
-  GST_QUARK_START_VALUE = 12,
-  GST_QUARK_STOP_FORMAT = 13,
-  GST_QUARK_STOP_VALUE = 14,
-  GST_QUARK_GERROR = 15,
-  GST_QUARK_DEBUG = 16,
-  GST_QUARK_BUFFER_PERCENT = 17,
-  GST_QUARK_BUFFERING_MODE = 18,
-  GST_QUARK_AVG_IN_RATE = 19,
-  GST_QUARK_AVG_OUT_RATE = 20,
-  GST_QUARK_BUFFERING_LEFT = 21,
-  GST_QUARK_ESTIMATED_TOTAL = 22,
-  GST_QUARK_OLD_STATE = 23,
-  GST_QUARK_NEW_STATE = 24,
-  GST_QUARK_PENDING_STATE = 25,
-  GST_QUARK_CLOCK = 26,
-  GST_QUARK_READY = 27,
-  GST_QUARK_POSITION = 28,
-  GST_QUARK_RESET_TIME = 29,
-  GST_QUARK_LIVE = 30,
-  GST_QUARK_MIN_LATENCY = 31,
-  GST_QUARK_MAX_LATENCY = 32,
-  GST_QUARK_BUSY = 33,
-  GST_QUARK_TYPE = 34,
-  GST_QUARK_OWNER = 35,
-  GST_QUARK_UPDATE = 36,
-  GST_QUARK_APPLIED_RATE = 37,
-  GST_QUARK_START = 38,
-  GST_QUARK_STOP = 39,
-  GST_QUARK_MINSIZE = 40,
-  GST_QUARK_MAXSIZE = 41,
-  GST_QUARK_ASYNC = 42,
-  GST_QUARK_PROPORTION = 43,
-  GST_QUARK_DIFF = 44,
-  GST_QUARK_TIMESTAMP = 45,
-  GST_QUARK_FLAGS = 46,
-  GST_QUARK_CUR_TYPE = 47,
-  GST_QUARK_CUR = 48,
-  GST_QUARK_STOP_TYPE = 49,
-  GST_QUARK_LATENCY = 50,
-  GST_QUARK_URI = 51,
-  GST_QUARK_OBJECT = 52,
-  GST_QUARK_TAGLIST = 53,
-  GST_QUARK_EVENT_SEGMENT = 54,
-  GST_QUARK_EVENT_BUFFER_SIZE = 55,
-  GST_QUARK_EVENT_QOS = 56,
-  GST_QUARK_EVENT_SEEK = 57,
-  GST_QUARK_EVENT_LATENCY = 58,
-  GST_QUARK_MESSAGE_ERROR = 59,
-  GST_QUARK_MESSAGE_WARNING = 60,
-  GST_QUARK_MESSAGE_INFO = 61,
-  GST_QUARK_MESSAGE_BUFFERING = 62,
-  GST_QUARK_MESSAGE_STATE_CHANGED = 63,
-  GST_QUARK_MESSAGE_CLOCK_PROVIDE = 64,
-  GST_QUARK_MESSAGE_CLOCK_LOST = 65,
-  GST_QUARK_MESSAGE_NEW_CLOCK = 66,
-  GST_QUARK_MESSAGE_STRUCTURE_CHANGE = 67,
-  GST_QUARK_MESSAGE_SEGMENT_START = 68,
-  GST_QUARK_MESSAGE_SEGMENT_DONE = 69,
-  GST_QUARK_MESSAGE_DURATION_CHANGED = 70,
-  GST_QUARK_MESSAGE_ASYNC_DONE = 71,
-  GST_QUARK_MESSAGE_REQUEST_STATE = 72,
-  GST_QUARK_MESSAGE_STREAM_STATUS = 73,
-  GST_QUARK_QUERY_POSITION = 74,
-  GST_QUARK_QUERY_DURATION = 75,
-  GST_QUARK_QUERY_LATENCY = 76,
-  GST_QUARK_QUERY_CONVERT = 77,
-  GST_QUARK_QUERY_SEGMENT = 78,
-  GST_QUARK_QUERY_SEEKING = 79,
-  GST_QUARK_QUERY_FORMATS = 80,
-  GST_QUARK_QUERY_BUFFERING = 81,
-  GST_QUARK_QUERY_URI = 82,
-  GST_QUARK_EVENT_STEP = 83,
-  GST_QUARK_MESSAGE_STEP_DONE = 84,
-  GST_QUARK_AMOUNT = 85,
-  GST_QUARK_FLUSH = 86,
-  GST_QUARK_INTERMEDIATE = 87,
-  GST_QUARK_MESSAGE_STEP_START = 88,
-  GST_QUARK_ACTIVE = 89,
-  GST_QUARK_EOS = 90,
-  GST_QUARK_EVENT_SINK_MESSAGE = 91,
-  GST_QUARK_MESSAGE = 92,
-  GST_QUARK_MESSAGE_QOS = 93,
-  GST_QUARK_RUNNING_TIME = 94,
-  GST_QUARK_STREAM_TIME = 95,
-  GST_QUARK_JITTER = 96,
-  GST_QUARK_QUALITY = 97,
-  GST_QUARK_PROCESSED = 98,
-  GST_QUARK_DROPPED = 99,
-  GST_QUARK_BUFFERING_RANGES = 100,
-  GST_QUARK_MESSAGE_PROGRESS = 101,
-  GST_QUARK_CODE = 102,
-  GST_QUARK_TEXT = 103,
-  GST_QUARK_PERCENT = 104,
-  GST_QUARK_TIMEOUT = 105,
-  GST_QUARK_BUFFER_POOL_CONFIG = 106,
-  GST_QUARK_CAPS = 107,
-  GST_QUARK_SIZE = 108,
-  GST_QUARK_MIN_BUFFERS = 109,
-  GST_QUARK_MAX_BUFFERS = 110,
-  GST_QUARK_PREFIX = 111,
-  GST_QUARK_PADDING = 112,
-  GST_QUARK_ALIGN = 113,
-  GST_QUARK_TIME = 114,
-  GST_QUARK_QUERY_ALLOCATION = 115,
-  GST_QUARK_NEED_POOL = 116,
-  GST_QUARK_META = 117,
-  GST_QUARK_POOL = 118,
-  GST_QUARK_EVENT_CAPS = 119,
-  GST_QUARK_EVENT_RECONFIGURE = 120,
-  GST_QUARK_SEGMENT = 121,
-  GST_QUARK_QUERY_SCHEDULING = 122,
-  GST_QUARK_PULL_MODE = 123,
-  GST_QUARK_ALLOCATOR = 124,
-  GST_QUARK_EVENT_FLUSH_STOP = 125,
-  GST_QUARK_OPTIONS = 126,
-  GST_QUARK_QUERY_ACCEPT_CAPS = 127,
-  GST_QUARK_RESULT = 128,
-  GST_QUARK_QUERY_CAPS = 129,
-  GST_QUARK_FILTER = 130,
-  GST_QUARK_MODES = 131,
-  GST_QUARK_EVENT_STREAM_CONFIG = 132,
-  GST_QUARK_SETUP_DATA = 133,
-  GST_QUARK_STREAM_HEADERS = 134,
-  GST_QUARK_EVENT_GAP = 135,
-  GST_QUARK_QUERY_DRAIN = 136,
-  GST_QUARK_PARAMS = 137,
-  GST_QUARK_EVENT_TOC_SELECT = 138,
-  GST_QUARK_UID = 139,
-  GST_QUARK_QUERY_TOC = 140,
-  GST_QUARK_ELEMENT_METADATA_LONGNAME = 141,
-  GST_QUARK_ELEMENT_METADATA_KLASS = 142,
-  GST_QUARK_ELEMENT_METADATA_DESCRIPTION = 143,
-  GST_QUARK_ELEMENT_METADATA_AUTHOR = 144,
-  GST_QUARK_TOC = 145,
-  GST_QUARK_TOC_ENTRY = 146,
-  GST_QUARK_UPDATED = 147,
-  GST_QUARK_EXTEND_UID = 148,
-  GST_QUARK_TOC_UID = 149,
-  GST_QUARK_TAGS = 150,
-  GST_QUARK_SUB_ENTRIES = 151,
-  GST_QUARK_INFO = 152,
-  GST_QUARK_MESSAGE_TAG = 153,
-  GST_QUARK_EVENT_TAG = 154,
-  GST_QUARK_MESSAGE_RESET_TIME = 155,
-  GST_QUARK_MESSAGE_TOC = 156,
-  GST_QUARK_EVENT_TOC_GLOBAL = 157,
-  GST_QUARK_EVENT_TOC_CURRENT = 158,
-  GST_QUARK_EVENT_SEGMENT_DONE = 159,
-  GST_QUARK_EVENT_STREAM_START = 160,
-  GST_QUARK_STREAM_ID = 161,
-  GST_QUARK_QUERY_CONTEXT = 162,
-  GST_QUARK_MESSAGE_NEED_CONTEXT = 163,
-  GST_QUARK_MESSAGE_HAVE_CONTEXT = 164,
-  GST_QUARK_CONTEXT = 165,
-  GST_QUARK_CONTEXT_TYPE = 166,
-  GST_QUARK_MESSAGE_STREAM_START = 167,
-  GST_QUARK_GROUP_ID = 168,
-  GST_QUARK_URI_REDIRECTION = 169,
-  GST_QUARK_MESSAGE_DEVICE_ADDED = 170,
-  GST_QUARK_MESSAGE_DEVICE_REMOVED = 171,
-  GST_QUARK_DEVICE = 172,
-  GST_QUARK_URI_REDIRECTION_PERMANENT = 173,
-  GST_QUARK_MESSAGE_PROPERTY_NOTIFY = 174,
-  GST_QUARK_PROPERTY_NAME = 175,
-  GST_QUARK_PROPERTY_VALUE = 176,
-  GST_QUARK_STREAMS = 177,
-  GST_QUARK_EVENT_SELECT_STREAMS = 178,
-  GST_QUARK_MESSAGE_STREAM_COLLECTION = 179,
-  GST_QUARK_COLLECTION = 180,
-  GST_QUARK_STREAM = 181,
-  GST_QUARK_EVENT_STREAM_COLLECTION = 182,
-  GST_QUARK_MESSAGE_STREAMS_SELECTED = 183,
-  GST_QUARK_MESSAGE_REDIRECT = 184,
-  GST_QUARK_REDIRECT_ENTRY_LOCATIONS = 185,
-  GST_QUARK_REDIRECT_ENTRY_TAGLISTS = 186,
-  GST_QUARK_REDIRECT_ENTRY_STRUCTURES = 187,
-  GST_QUARK_EVENT_STREAM_GROUP_DONE = 188,
-  GST_QUARK_QUERY_BITRATE = 189,
-  GST_QUARK_NOMINAL_BITRATE = 190,
-  GST_QUARK_MESSAGE_DEVICE_CHANGED = 191,
-  GST_QUARK_DEVICE_CHANGED = 192,
-  GST_QUARK_TRICKMODE_INTERVAL = 193,
-  GST_QUARK_EVENT_INSTANT_RATE_CHANGE = 194,
-  GST_QUARK_EVENT_INSTANT_RATE_SYNC_TIME = 195,
-  GST_QUARK_MESSAGE_INSTANT_RATE_REQUEST = 196,
-  GST_QUARK_UPSTREAM_RUNNING_TIME = 197,
-  GST_QUARK_BASE = 198,
-  GST_QUARK_OFFSET = 199,
-  GST_QUARK_PLUGIN_API = 200,
-  GST_QUARK_PLUGIN_API_FLAGS = 201,
-  GST_QUARK_GAP_FLAGS = 202,
-  GST_QUARK_QUERY_SELECTABLE = 203,
-  GST_QUARK_SELECTABLE = 204,
-  GST_QUARK_MAX = 205
-} GstQuarkId;
-
-extern GQuark _priv_gst_quark_table[GST_QUARK_MAX];
-
-#define GST_QUARK(q) _priv_gst_quark_table[GST_QUARK_##q]
-
-#endif
diff --git a/gst/gstquery.c b/gst/gstquery.c
index 3c2490f..2b911a6 100644
--- a/gst/gstquery.c
+++ b/gst/gstquery.c
@@ -59,9 +59,6 @@
 #include "gstquery.h"
 #include "gstvalue.h"
 #include "gstenumtypes.h"
-#include "gstquark.h"
-#include "gsturi.h"
-#include "gstbufferpool.h"
 
 GST_DEBUG_CATEGORY_STATIC (gst_query_debug);
 #define GST_CAT_DEFAULT gst_query_debug
@@ -237,9 +234,9 @@ gst_query_new_position (GstFormat format)
   GstQuery *query;
   GstStructure *structure;
 
-  structure = gst_structure_new_id (GST_QUARK (QUERY_POSITION),
-      GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
-      GST_QUARK (CURRENT), G_TYPE_INT64, G_GINT64_CONSTANT (-1), NULL);
+  structure = gst_structure_new_static_str ("GstQueryPosition",
+      "format", GST_TYPE_FORMAT, format,
+      "current", G_TYPE_INT64, G_GINT64_CONSTANT (-1), NULL);
 
   query = gst_query_new_custom (GST_QUERY_POSITION, structure);
 
@@ -262,12 +259,11 @@ gst_query_set_position (GstQuery * query, GstFormat format, gint64 cur)
   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_POSITION);
 
   s = GST_QUERY_STRUCTURE (query);
-  g_return_if_fail (format == g_value_get_enum (gst_structure_id_get_value (s,
-              GST_QUARK (FORMAT))));
+  g_return_if_fail (format == g_value_get_enum (gst_structure_get_value (s,
+              "format")));
 
-  gst_structure_id_set (s,
-      GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
-      GST_QUARK (CURRENT), G_TYPE_INT64, cur, NULL);
+  gst_structure_set (s,
+      "format", GST_TYPE_FORMAT, format, "current", G_TYPE_INT64, cur, NULL);
 }
 
 /**
@@ -290,11 +286,10 @@ gst_query_parse_position (GstQuery * query, GstFormat * format, gint64 * cur)
   structure = GST_QUERY_STRUCTURE (query);
   if (format)
     *format =
-        (GstFormat) g_value_get_enum (gst_structure_id_get_value (structure,
-            GST_QUARK (FORMAT)));
+        (GstFormat) g_value_get_enum (gst_structure_get_value (structure,
+            "format"));
   if (cur)
-    *cur = g_value_get_int64 (gst_structure_id_get_value (structure,
-            GST_QUARK (CURRENT)));
+    *cur = g_value_get_int64 (gst_structure_get_value (structure, "current"));
 }
 
 
@@ -316,9 +311,9 @@ gst_query_new_duration (GstFormat format)
   GstQuery *query;
   GstStructure *structure;
 
-  structure = gst_structure_new_id (GST_QUARK (QUERY_DURATION),
-      GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
-      GST_QUARK (DURATION), G_TYPE_INT64, G_GINT64_CONSTANT (-1), NULL);
+  structure = gst_structure_new_static_str ("GstQueryDuration",
+      "format", GST_TYPE_FORMAT, format,
+      "duration", G_TYPE_INT64, G_GINT64_CONSTANT (-1), NULL);
 
   query = gst_query_new_custom (GST_QUERY_DURATION, structure);
 
@@ -341,10 +336,10 @@ gst_query_set_duration (GstQuery * query, GstFormat format, gint64 duration)
   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_DURATION);
 
   s = GST_QUERY_STRUCTURE (query);
-  g_return_if_fail (format == g_value_get_enum (gst_structure_id_get_value (s,
-              GST_QUARK (FORMAT))));
-  gst_structure_id_set (s, GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
-      GST_QUARK (DURATION), G_TYPE_INT64, duration, NULL);
+  g_return_if_fail (format == g_value_get_enum (gst_structure_get_value (s,
+              "format")));
+  gst_structure_set (s, "format", GST_TYPE_FORMAT, format,
+      "duration", G_TYPE_INT64, duration, NULL);
 }
 
 /**
@@ -368,11 +363,11 @@ gst_query_parse_duration (GstQuery * query, GstFormat * format,
   structure = GST_QUERY_STRUCTURE (query);
   if (format)
     *format =
-        (GstFormat) g_value_get_enum (gst_structure_id_get_value (structure,
-            GST_QUARK (FORMAT)));
+        (GstFormat) g_value_get_enum (gst_structure_get_value (structure,
+            "format"));
   if (duration)
-    *duration = g_value_get_int64 (gst_structure_id_get_value (structure,
-            GST_QUARK (DURATION)));
+    *duration = g_value_get_int64 (gst_structure_get_value (structure,
+            "duration"));
 }
 
 /**
@@ -393,10 +388,10 @@ gst_query_new_latency (void)
   GstQuery *query;
   GstStructure *structure;
 
-  structure = gst_structure_new_id (GST_QUARK (QUERY_LATENCY),
-      GST_QUARK (LIVE), G_TYPE_BOOLEAN, FALSE,
-      GST_QUARK (MIN_LATENCY), G_TYPE_UINT64, G_GUINT64_CONSTANT (0),
-      GST_QUARK (MAX_LATENCY), G_TYPE_UINT64, GST_CLOCK_TIME_NONE, NULL);
+  structure = gst_structure_new_static_str ("GstQueryLatency",
+      "live", G_TYPE_BOOLEAN, FALSE,
+      "min-latency", G_TYPE_UINT64, G_GUINT64_CONSTANT (0),
+      "max-latency", G_TYPE_UINT64, GST_CLOCK_TIME_NONE, NULL);
 
   query = gst_query_new_custom (GST_QUERY_LATENCY, structure);
 
@@ -422,10 +417,10 @@ gst_query_set_latency (GstQuery * query, gboolean live,
   g_return_if_fail (GST_CLOCK_TIME_IS_VALID (min_latency));
 
   structure = GST_QUERY_STRUCTURE (query);
-  gst_structure_id_set (structure,
-      GST_QUARK (LIVE), G_TYPE_BOOLEAN, live,
-      GST_QUARK (MIN_LATENCY), G_TYPE_UINT64, min_latency,
-      GST_QUARK (MAX_LATENCY), G_TYPE_UINT64, max_latency, NULL);
+  gst_structure_set (structure,
+      "live", G_TYPE_BOOLEAN, live,
+      "min-latency", G_TYPE_UINT64, min_latency,
+      "max-latency", G_TYPE_UINT64, max_latency, NULL);
 }
 
 /**
@@ -447,15 +442,13 @@ gst_query_parse_latency (GstQuery * query, gboolean * live,
 
   structure = GST_QUERY_STRUCTURE (query);
   if (live)
-    *live =
-        g_value_get_boolean (gst_structure_id_get_value (structure,
-            GST_QUARK (LIVE)));
+    *live = g_value_get_boolean (gst_structure_get_value (structure, "live"));
   if (min_latency)
-    *min_latency = g_value_get_uint64 (gst_structure_id_get_value (structure,
-            GST_QUARK (MIN_LATENCY)));
+    *min_latency = g_value_get_uint64 (gst_structure_get_value (structure,
+            "min-latency"));
   if (max_latency)
-    *max_latency = g_value_get_uint64 (gst_structure_id_get_value (structure,
-            GST_QUARK (MAX_LATENCY)));
+    *max_latency = g_value_get_uint64 (gst_structure_get_value (structure,
+            "max-latency"));
 }
 
 /**
@@ -479,11 +472,11 @@ gst_query_new_convert (GstFormat src_format, gint64 value,
   GstQuery *query;
   GstStructure *structure;
 
-  structure = gst_structure_new_id (GST_QUARK (QUERY_CONVERT),
-      GST_QUARK (SRC_FORMAT), GST_TYPE_FORMAT, src_format,
-      GST_QUARK (SRC_VALUE), G_TYPE_INT64, value,
-      GST_QUARK (DEST_FORMAT), GST_TYPE_FORMAT, dest_format,
-      GST_QUARK (DEST_VALUE), G_TYPE_INT64, G_GINT64_CONSTANT (-1), NULL);
+  structure = gst_structure_new_static_str ("GstQueryConvert",
+      "src_format", GST_TYPE_FORMAT, src_format,
+      "src_value", G_TYPE_INT64, value,
+      "dest_format", GST_TYPE_FORMAT, dest_format,
+      "dest_value", G_TYPE_INT64, G_GINT64_CONSTANT (-1), NULL);
 
   query = gst_query_new_custom (GST_QUERY_CONVERT, structure);
 
@@ -509,11 +502,11 @@ gst_query_set_convert (GstQuery * query, GstFormat src_format, gint64 src_value,
   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_CONVERT);
 
   structure = GST_QUERY_STRUCTURE (query);
-  gst_structure_id_set (structure,
-      GST_QUARK (SRC_FORMAT), GST_TYPE_FORMAT, src_format,
-      GST_QUARK (SRC_VALUE), G_TYPE_INT64, src_value,
-      GST_QUARK (DEST_FORMAT), GST_TYPE_FORMAT, dest_format,
-      GST_QUARK (DEST_VALUE), G_TYPE_INT64, dest_value, NULL);
+  gst_structure_set (structure,
+      "src_format", GST_TYPE_FORMAT, src_format,
+      "src_value", G_TYPE_INT64, src_value,
+      "dest_format", GST_TYPE_FORMAT, dest_format,
+      "dest_value", G_TYPE_INT64, dest_value, NULL);
 }
 
 /**
@@ -541,18 +534,18 @@ gst_query_parse_convert (GstQuery * query, GstFormat * src_format,
   structure = GST_QUERY_STRUCTURE (query);
   if (src_format)
     *src_format =
-        (GstFormat) g_value_get_enum (gst_structure_id_get_value (structure,
-            GST_QUARK (SRC_FORMAT)));
+        (GstFormat) g_value_get_enum (gst_structure_get_value (structure,
+            "src_format"));
   if (src_value)
-    *src_value = g_value_get_int64 (gst_structure_id_get_value (structure,
-            GST_QUARK (SRC_VALUE)));
+    *src_value = g_value_get_int64 (gst_structure_get_value (structure,
+            "src_value"));
   if (dest_format)
     *dest_format =
-        (GstFormat) g_value_get_enum (gst_structure_id_get_value (structure,
-            GST_QUARK (DEST_FORMAT)));
+        (GstFormat) g_value_get_enum (gst_structure_get_value (structure,
+            "dest_format"));
   if (dest_value)
-    *dest_value = g_value_get_int64 (gst_structure_id_get_value (structure,
-            GST_QUARK (DEST_VALUE)));
+    *dest_value = g_value_get_int64 (gst_structure_get_value (structure,
+            "dest_value"));
 }
 
 /**
@@ -573,11 +566,11 @@ gst_query_new_segment (GstFormat format)
   GstQuery *query;
   GstStructure *structure;
 
-  structure = gst_structure_new_id (GST_QUARK (QUERY_SEGMENT),
-      GST_QUARK (RATE), G_TYPE_DOUBLE, (gdouble) 0.0,
-      GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
-      GST_QUARK (START_VALUE), G_TYPE_INT64, G_GINT64_CONSTANT (-1),
-      GST_QUARK (STOP_VALUE), G_TYPE_INT64, G_GINT64_CONSTANT (-1), NULL);
+  structure = gst_structure_new_static_str ("GstQuerySegment",
+      "rate", G_TYPE_DOUBLE, (gdouble) 0.0,
+      "format", GST_TYPE_FORMAT, format,
+      "start_value", G_TYPE_INT64, G_GINT64_CONSTANT (-1),
+      "stop_value", G_TYPE_INT64, G_GINT64_CONSTANT (-1), NULL);
 
   query = gst_query_new_custom (GST_QUERY_SEGMENT, structure);
 
@@ -613,11 +606,11 @@ gst_query_set_segment (GstQuery * query, gdouble rate, GstFormat format,
   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_SEGMENT);
 
   structure = GST_QUERY_STRUCTURE (query);
-  gst_structure_id_set (structure,
-      GST_QUARK (RATE), G_TYPE_DOUBLE, rate,
-      GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
-      GST_QUARK (START_VALUE), G_TYPE_INT64, start_value,
-      GST_QUARK (STOP_VALUE), G_TYPE_INT64, stop_value, NULL);
+  gst_structure_set (structure,
+      "rate", G_TYPE_DOUBLE, rate,
+      "format", GST_TYPE_FORMAT, format,
+      "start_value", G_TYPE_INT64, start_value,
+      "stop_value", G_TYPE_INT64, stop_value, NULL);
 }
 
 /**
@@ -644,18 +637,17 @@ gst_query_parse_segment (GstQuery * query, gdouble * rate, GstFormat * format,
 
   structure = GST_QUERY_STRUCTURE (query);
   if (rate)
-    *rate = g_value_get_double (gst_structure_id_get_value (structure,
-            GST_QUARK (RATE)));
+    *rate = g_value_get_double (gst_structure_get_value (structure, "rate"));
   if (format)
     *format =
-        (GstFormat) g_value_get_enum (gst_structure_id_get_value (structure,
-            GST_QUARK (FORMAT)));
+        (GstFormat) g_value_get_enum (gst_structure_get_value (structure,
+            "format"));
   if (start_value)
-    *start_value = g_value_get_int64 (gst_structure_id_get_value (structure,
-            GST_QUARK (START_VALUE)));
+    *start_value = g_value_get_int64 (gst_structure_get_value (structure,
+            "start_value"));
   if (stop_value)
-    *stop_value = g_value_get_int64 (gst_structure_id_get_value (structure,
-            GST_QUARK (STOP_VALUE)));
+    *stop_value = g_value_get_int64 (gst_structure_get_value (structure,
+            "stop_value"));
 }
 
 /**
@@ -745,8 +737,8 @@ gst_query_writable_structure (GstQuery * query)
 
   if (structure == NULL) {
     structure =
-        gst_structure_new_id_empty (gst_query_type_to_quark (GST_QUERY_TYPE
-            (query)));
+        gst_structure_new_static_str_empty (gst_query_type_get_name
+        (GST_QUERY_TYPE (query)));
     gst_structure_set_parent_refcount (structure, &query->mini_object.refcount);
     GST_QUERY_STRUCTURE (query) = structure;
   }
@@ -770,11 +762,11 @@ gst_query_new_seeking (GstFormat format)
   GstQuery *query;
   GstStructure *structure;
 
-  structure = gst_structure_new_id (GST_QUARK (QUERY_SEEKING),
-      GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
-      GST_QUARK (SEEKABLE), G_TYPE_BOOLEAN, FALSE,
-      GST_QUARK (SEGMENT_START), G_TYPE_INT64, G_GINT64_CONSTANT (-1),
-      GST_QUARK (SEGMENT_END), G_TYPE_INT64, G_GINT64_CONSTANT (-1), NULL);
+  structure = gst_structure_new_static_str ("GstQuerySeeking",
+      "format", GST_TYPE_FORMAT, format,
+      "seekable", G_TYPE_BOOLEAN, FALSE,
+      "segment-start", G_TYPE_INT64, G_GINT64_CONSTANT (-1),
+      "segment-end", G_TYPE_INT64, G_GINT64_CONSTANT (-1), NULL);
 
   query = gst_query_new_custom (GST_QUERY_SEEKING, structure);
 
@@ -801,11 +793,11 @@ gst_query_set_seeking (GstQuery * query, GstFormat format,
   g_return_if_fail (gst_query_is_writable (query));
 
   structure = GST_QUERY_STRUCTURE (query);
-  gst_structure_id_set (structure,
-      GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
-      GST_QUARK (SEEKABLE), G_TYPE_BOOLEAN, seekable,
-      GST_QUARK (SEGMENT_START), G_TYPE_INT64, segment_start,
-      GST_QUARK (SEGMENT_END), G_TYPE_INT64, segment_end, NULL);
+  gst_structure_set (structure,
+      "format", GST_TYPE_FORMAT, format,
+      "seekable", G_TYPE_BOOLEAN, seekable,
+      "segment-start", G_TYPE_INT64, segment_start,
+      "segment-end", G_TYPE_INT64, segment_end, NULL);
 }
 
 /**
@@ -832,27 +824,27 @@ gst_query_parse_seeking (GstQuery * query, GstFormat * format,
   structure = GST_QUERY_STRUCTURE (query);
   if (format)
     *format =
-        (GstFormat) g_value_get_enum (gst_structure_id_get_value (structure,
-            GST_QUARK (FORMAT)));
+        (GstFormat) g_value_get_enum (gst_structure_get_value (structure,
+            "format"));
   if (seekable)
-    *seekable = g_value_get_boolean (gst_structure_id_get_value (structure,
-            GST_QUARK (SEEKABLE)));
+    *seekable = g_value_get_boolean (gst_structure_get_value (structure,
+            "seekable"));
   if (segment_start)
-    *segment_start = g_value_get_int64 (gst_structure_id_get_value (structure,
-            GST_QUARK (SEGMENT_START)));
+    *segment_start = g_value_get_int64 (gst_structure_get_value (structure,
+            "segment-start"));
   if (segment_end)
-    *segment_end = g_value_get_int64 (gst_structure_id_get_value (structure,
-            GST_QUARK (SEGMENT_END)));
+    *segment_end = g_value_get_int64 (gst_structure_get_value (structure,
+            "segment-end"));
 }
 
 static GArray *
-ensure_array (GstStructure * s, GQuark quark, gsize element_size,
+ensure_array (GstStructure * s, const gchar * fieldname, gsize element_size,
     GDestroyNotify clear_func)
 {
   GArray *array;
   const GValue *value;
 
-  value = gst_structure_id_get_value (s, quark);
+  value = gst_structure_get_value (s, fieldname);
   if (value) {
     array = (GArray *) g_value_get_boxed (value);
   } else {
@@ -865,7 +857,7 @@ ensure_array (GstStructure * s, GQuark quark, gsize element_size,
     g_value_init (&new_array_val, G_TYPE_ARRAY);
     g_value_take_boxed (&new_array_val, array);
 
-    gst_structure_id_take_value (s, quark, &new_array_val);
+    gst_structure_take_value (s, fieldname, &new_array_val);
   }
   return array;
 }
@@ -886,7 +878,7 @@ gst_query_new_formats (void)
   GstQuery *query;
   GstStructure *structure;
 
-  structure = gst_structure_new_id_empty (GST_QUARK (QUERY_FORMATS));
+  structure = gst_structure_new_static_str_empty ("GstQueryFormats");
   query = gst_query_new_custom (GST_QUERY_FORMATS, structure);
 
   return query;
@@ -1048,17 +1040,17 @@ gst_query_new_buffering (GstFormat format)
 
   /* by default, we configure the answer as no buffering with a 100% buffering
    * progress */
-  structure = gst_structure_new_id (GST_QUARK (QUERY_BUFFERING),
-      GST_QUARK (BUSY), G_TYPE_BOOLEAN, FALSE,
-      GST_QUARK (BUFFER_PERCENT), G_TYPE_INT, 100,
-      GST_QUARK (BUFFERING_MODE), GST_TYPE_BUFFERING_MODE, GST_BUFFERING_STREAM,
-      GST_QUARK (AVG_IN_RATE), G_TYPE_INT, -1,
-      GST_QUARK (AVG_OUT_RATE), G_TYPE_INT, -1,
-      GST_QUARK (BUFFERING_LEFT), G_TYPE_INT64, G_GINT64_CONSTANT (0),
-      GST_QUARK (ESTIMATED_TOTAL), G_TYPE_INT64, G_GINT64_CONSTANT (-1),
-      GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
-      GST_QUARK (START_VALUE), G_TYPE_INT64, G_GINT64_CONSTANT (-1),
-      GST_QUARK (STOP_VALUE), G_TYPE_INT64, G_GINT64_CONSTANT (-1), NULL);
+  structure = gst_structure_new_static_str ("GstQueryBuffering",
+      "busy", G_TYPE_BOOLEAN, FALSE,
+      "buffer-percent", G_TYPE_INT, 100,
+      "buffering-mode", GST_TYPE_BUFFERING_MODE, GST_BUFFERING_STREAM,
+      "avg-in-rate", G_TYPE_INT, -1,
+      "avg-out-rate", G_TYPE_INT, -1,
+      "buffering-left", G_TYPE_INT64, G_GINT64_CONSTANT (0),
+      "estimated-total", G_TYPE_INT64, G_GINT64_CONSTANT (-1),
+      "format", GST_TYPE_FORMAT, format,
+      "start_value", G_TYPE_INT64, G_GINT64_CONSTANT (-1),
+      "stop_value", G_TYPE_INT64, G_GINT64_CONSTANT (-1), NULL);
 
   query = gst_query_new_custom (GST_QUERY_BUFFERING, structure);
 
@@ -1084,9 +1076,9 @@ gst_query_set_buffering_percent (GstQuery * query, gboolean busy, gint percent)
   g_return_if_fail (percent >= 0 && percent <= 100);
 
   structure = GST_QUERY_STRUCTURE (query);
-  gst_structure_id_set (structure,
-      GST_QUARK (BUSY), G_TYPE_BOOLEAN, busy,
-      GST_QUARK (BUFFER_PERCENT), G_TYPE_INT, percent, NULL);
+  gst_structure_set (structure,
+      "busy", G_TYPE_BOOLEAN, busy,
+      "buffer-percent", G_TYPE_INT, percent, NULL);
 }
 
 /**
@@ -1108,11 +1100,10 @@ gst_query_parse_buffering_percent (GstQuery * query, gboolean * busy,
 
   structure = GST_QUERY_STRUCTURE (query);
   if (busy)
-    *busy = g_value_get_boolean (gst_structure_id_get_value (structure,
-            GST_QUARK (BUSY)));
+    *busy = g_value_get_boolean (gst_structure_get_value (structure, "busy"));
   if (percent)
-    *percent = g_value_get_int (gst_structure_id_get_value (structure,
-            GST_QUARK (BUFFER_PERCENT)));
+    *percent = g_value_get_int (gst_structure_get_value (structure,
+            "buffer-percent"));
 }
 
 /**
@@ -1135,11 +1126,11 @@ gst_query_set_buffering_stats (GstQuery * query, GstBufferingMode mode,
   g_return_if_fail (gst_query_is_writable (query));
 
   structure = GST_QUERY_STRUCTURE (query);
-  gst_structure_id_set (structure,
-      GST_QUARK (BUFFERING_MODE), GST_TYPE_BUFFERING_MODE, mode,
-      GST_QUARK (AVG_IN_RATE), G_TYPE_INT, avg_in,
-      GST_QUARK (AVG_OUT_RATE), G_TYPE_INT, avg_out,
-      GST_QUARK (BUFFERING_LEFT), G_TYPE_INT64, buffering_left, NULL);
+  gst_structure_set (structure,
+      "buffering-mode", GST_TYPE_BUFFERING_MODE, mode,
+      "avg-in-rate", G_TYPE_INT, avg_in,
+      "avg-out-rate", G_TYPE_INT, avg_out,
+      "buffering-left", G_TYPE_INT64, buffering_left, NULL);
 }
 
 /**
@@ -1165,18 +1156,18 @@ gst_query_parse_buffering_stats (GstQuery * query,
   structure = GST_QUERY_STRUCTURE (query);
   if (mode)
     *mode = (GstBufferingMode)
-        g_value_get_enum (gst_structure_id_get_value (structure,
-            GST_QUARK (BUFFERING_MODE)));
+        g_value_get_enum (gst_structure_get_value (structure,
+            "buffering-mode"));
   if (avg_in)
-    *avg_in = g_value_get_int (gst_structure_id_get_value (structure,
-            GST_QUARK (AVG_IN_RATE)));
+    *avg_in = g_value_get_int (gst_structure_get_value (structure,
+            "avg-in-rate"));
   if (avg_out)
-    *avg_out = g_value_get_int (gst_structure_id_get_value (structure,
-            GST_QUARK (AVG_OUT_RATE)));
+    *avg_out = g_value_get_int (gst_structure_get_value (structure,
+            "avg-out-rate"));
   if (buffering_left)
     *buffering_left =
-        g_value_get_int64 (gst_structure_id_get_value (structure,
-            GST_QUARK (BUFFERING_LEFT)));
+        g_value_get_int64 (gst_structure_get_value (structure,
+            "buffering-left"));
 }
 
 /**
@@ -1200,11 +1191,11 @@ gst_query_set_buffering_range (GstQuery * query, GstFormat format,
   g_return_if_fail (gst_query_is_writable (query));
 
   structure = GST_QUERY_STRUCTURE (query);
-  gst_structure_id_set (structure,
-      GST_QUARK (FORMAT), GST_TYPE_FORMAT, format,
-      GST_QUARK (START_VALUE), G_TYPE_INT64, start,
-      GST_QUARK (STOP_VALUE), G_TYPE_INT64, stop,
-      GST_QUARK (ESTIMATED_TOTAL), G_TYPE_INT64, estimated_total, NULL);
+  gst_structure_set (structure,
+      "format", GST_TYPE_FORMAT, format,
+      "start_value", G_TYPE_INT64, start,
+      "stop_value", G_TYPE_INT64, stop,
+      "estimated-total", G_TYPE_INT64, estimated_total, NULL);
 }
 
 /**
@@ -1232,18 +1223,18 @@ gst_query_parse_buffering_range (GstQuery * query, GstFormat * format,
   structure = GST_QUERY_STRUCTURE (query);
   if (format)
     *format =
-        (GstFormat) g_value_get_enum (gst_structure_id_get_value (structure,
-            GST_QUARK (FORMAT)));
+        (GstFormat) g_value_get_enum (gst_structure_get_value (structure,
+            "format"));
   if (start)
-    *start = g_value_get_int64 (gst_structure_id_get_value (structure,
-            GST_QUARK (START_VALUE)));
+    *start = g_value_get_int64 (gst_structure_get_value (structure,
+            "start_value"));
   if (stop)
-    *stop = g_value_get_int64 (gst_structure_id_get_value (structure,
-            GST_QUARK (STOP_VALUE)));
+    *stop = g_value_get_int64 (gst_structure_get_value (structure,
+            "stop_value"));
   if (estimated_total)
     *estimated_total =
-        g_value_get_int64 (gst_structure_id_get_value (structure,
-            GST_QUARK (ESTIMATED_TOTAL)));
+        g_value_get_int64 (gst_structure_get_value (structure,
+            "estimated-total"));
 }
 
 /* GstQueryBufferingRange: internal struct for GArray */
@@ -1278,7 +1269,7 @@ gst_query_add_buffering_range (GstQuery * query, gint64 start, gint64 stop)
     return FALSE;
 
   structure = GST_QUERY_STRUCTURE (query);
-  array = ensure_array (structure, GST_QUARK (BUFFERING_RANGES),
+  array = ensure_array (structure, "buffering-ranges",
       sizeof (GstQueryBufferingRange), NULL);
 
   if (array->len > 1) {
@@ -1315,7 +1306,7 @@ gst_query_get_n_buffering_ranges (GstQuery * query)
   g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_BUFFERING, 0);
 
   structure = GST_QUERY_STRUCTURE (query);
-  array = ensure_array (structure, GST_QUARK (BUFFERING_RANGES),
+  array = ensure_array (structure, "buffering-ranges",
       sizeof (GstQueryBufferingRange), NULL);
 
   return array->len;
@@ -1346,7 +1337,7 @@ gst_query_parse_nth_buffering_range (GstQuery * query, guint index,
 
   structure = GST_QUERY_STRUCTURE (query);
 
-  array = ensure_array (structure, GST_QUARK (BUFFERING_RANGES),
+  array = ensure_array (structure, "buffering-ranges",
       sizeof (GstQueryBufferingRange), NULL);
   g_return_val_if_fail (index < array->len, FALSE);
 
@@ -1378,8 +1369,8 @@ gst_query_new_uri (void)
   GstQuery *query;
   GstStructure *structure;
 
-  structure = gst_structure_new_id (GST_QUARK (QUERY_URI),
-      GST_QUARK (URI), G_TYPE_STRING, NULL, NULL);
+  structure = gst_structure_new_static_str ("GstQueryURI",
+      "uri", G_TYPE_STRING, NULL, NULL);
 
   query = gst_query_new_custom (GST_QUERY_URI, structure);
 
@@ -1402,7 +1393,7 @@ gst_query_set_uri (GstQuery * query, const gchar * uri)
   g_return_if_fail (gst_query_is_writable (query));
 
   structure = GST_QUERY_STRUCTURE (query);
-  gst_structure_id_set (structure, GST_QUARK (URI), G_TYPE_STRING, uri, NULL);
+  gst_structure_set (structure, "uri", G_TYPE_STRING, uri, NULL);
 }
 
 /**
@@ -1424,8 +1415,7 @@ gst_query_parse_uri (GstQuery * query, gchar ** uri)
 
   structure = GST_QUERY_STRUCTURE (query);
   if (uri)
-    *uri = g_value_dup_string (gst_structure_id_get_value (structure,
-            GST_QUARK (URI)));
+    *uri = g_value_dup_string (gst_structure_get_value (structure, "uri"));
 }
 
 /**
@@ -1446,8 +1436,7 @@ gst_query_set_uri_redirection (GstQuery * query, const gchar * uri)
   g_return_if_fail (gst_query_is_writable (query));
 
   structure = GST_QUERY_STRUCTURE (query);
-  gst_structure_id_set (structure, GST_QUARK (URI_REDIRECTION),
-      G_TYPE_STRING, uri, NULL);
+  gst_structure_set (structure, "uri-redirection", G_TYPE_STRING, uri, NULL);
 }
 
 /**
@@ -1471,7 +1460,7 @@ gst_query_parse_uri_redirection (GstQuery * query, gchar ** uri)
 
   structure = GST_QUERY_STRUCTURE (query);
   if (uri) {
-    if (!gst_structure_id_get (structure, GST_QUARK (URI_REDIRECTION),
+    if (!gst_structure_get (structure, "uri-redirection",
             G_TYPE_STRING, uri, NULL))
       *uri = NULL;
   }
@@ -1496,7 +1485,7 @@ gst_query_set_uri_redirection_permanent (GstQuery * query, gboolean permanent)
   g_return_if_fail (gst_query_is_writable (query));
 
   structure = GST_QUERY_STRUCTURE (query);
-  gst_structure_id_set (structure, GST_QUARK (URI_REDIRECTION_PERMANENT),
+  gst_structure_set (structure, "uri-redirection-permanent",
       G_TYPE_BOOLEAN, permanent, NULL);
 }
 
@@ -1523,7 +1512,7 @@ gst_query_parse_uri_redirection_permanent (GstQuery * query,
 
   structure = GST_QUERY_STRUCTURE (query);
   if (permanent) {
-    if (!gst_structure_id_get (structure, GST_QUARK (URI_REDIRECTION_PERMANENT),
+    if (!gst_structure_get (structure, "uri-redirection-permanent",
             G_TYPE_BOOLEAN, permanent, NULL))
       *permanent = FALSE;
   }
@@ -1546,9 +1535,9 @@ gst_query_new_allocation (GstCaps * caps, gboolean need_pool)
   GstQuery *query;
   GstStructure *structure;
 
-  structure = gst_structure_new_id (GST_QUARK (QUERY_ALLOCATION),
-      GST_QUARK (CAPS), GST_TYPE_CAPS, caps,
-      GST_QUARK (NEED_POOL), G_TYPE_BOOLEAN, need_pool, NULL);
+  structure = gst_structure_new_static_str ("GstQueryAllocation",
+      "caps", GST_TYPE_CAPS, caps,
+      "need-pool", G_TYPE_BOOLEAN, need_pool, NULL);
 
   query = gst_query_new_custom (GST_QUERY_ALLOCATION, structure);
 
@@ -1578,11 +1567,9 @@ gst_query_parse_allocation (GstQuery * query, GstCaps ** caps,
 
   structure = GST_QUERY_STRUCTURE (query);
   if (caps) {
-    *caps = g_value_get_boxed (gst_structure_id_get_value (structure,
-            GST_QUARK (CAPS)));
+    *caps = g_value_get_boxed (gst_structure_get_value (structure, "caps"));
   }
-  gst_structure_id_get (structure,
-      GST_QUARK (NEED_POOL), G_TYPE_BOOLEAN, need_pool, NULL);
+  gst_structure_get (structure, "need-pool", G_TYPE_BOOLEAN, need_pool, NULL);
 }
 
 typedef struct
@@ -1622,7 +1609,7 @@ gst_query_add_allocation_pool (GstQuery * query, GstBufferPool * pool,
   g_return_if_fail (gst_query_is_writable (query));
 
   structure = GST_QUERY_STRUCTURE (query);
-  array = ensure_array (structure, GST_QUARK (POOL),
+  array = ensure_array (structure, "pool",
       sizeof (AllocationPool), (GDestroyNotify) allocation_pool_free);
 
   if ((ap.pool = pool))
@@ -1652,7 +1639,7 @@ gst_query_get_n_allocation_pools (GstQuery * query)
   g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION, 0);
 
   structure = GST_QUERY_STRUCTURE (query);
-  array = ensure_array (structure, GST_QUARK (POOL),
+  array = ensure_array (structure, "pool",
       sizeof (AllocationPool), (GDestroyNotify) allocation_pool_free);
 
   return array->len;
@@ -1683,7 +1670,7 @@ gst_query_parse_nth_allocation_pool (GstQuery * query, guint index,
   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION);
 
   structure = GST_QUERY_STRUCTURE (query);
-  array = ensure_array (structure, GST_QUARK (POOL),
+  array = ensure_array (structure, "pool",
       sizeof (AllocationPool), (GDestroyNotify) allocation_pool_free);
   g_return_if_fail (index < array->len);
 
@@ -1722,7 +1709,7 @@ gst_query_set_nth_allocation_pool (GstQuery * query, guint index,
   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION);
 
   structure = GST_QUERY_STRUCTURE (query);
-  array = ensure_array (structure, GST_QUARK (POOL),
+  array = ensure_array (structure, "pool",
       sizeof (AllocationPool), (GDestroyNotify) allocation_pool_free);
   g_return_if_fail (index < array->len);
 
@@ -1757,7 +1744,7 @@ gst_query_remove_nth_allocation_pool (GstQuery * query, guint index)
 
   structure = GST_QUERY_STRUCTURE (query);
   array =
-      ensure_array (structure, GST_QUARK (POOL), sizeof (AllocationPool),
+      ensure_array (structure, "pool", sizeof (AllocationPool),
       (GDestroyNotify) allocation_pool_free);
   g_return_if_fail (index < array->len);
 
@@ -1799,7 +1786,7 @@ gst_query_add_allocation_meta (GstQuery * query, GType api,
 
   structure = GST_QUERY_STRUCTURE (query);
   array =
-      ensure_array (structure, GST_QUARK (META), sizeof (AllocationMeta),
+      ensure_array (structure, "meta", sizeof (AllocationMeta),
       (GDestroyNotify) allocation_meta_free);
 
   am.api = api;
@@ -1827,7 +1814,7 @@ gst_query_get_n_allocation_metas (GstQuery * query)
 
   structure = GST_QUERY_STRUCTURE (query);
   array =
-      ensure_array (structure, GST_QUARK (META), sizeof (AllocationMeta),
+      ensure_array (structure, "meta", sizeof (AllocationMeta),
       (GDestroyNotify) allocation_meta_free);
 
   return array->len;
@@ -1856,7 +1843,7 @@ gst_query_parse_nth_allocation_meta (GstQuery * query, guint index,
 
   structure = GST_QUERY_STRUCTURE (query);
   array =
-      ensure_array (structure, GST_QUARK (META), sizeof (AllocationMeta),
+      ensure_array (structure, "meta", sizeof (AllocationMeta),
       (GDestroyNotify) allocation_meta_free);
 
   g_return_val_if_fail (index < array->len, 0);
@@ -1887,7 +1874,7 @@ gst_query_remove_nth_allocation_meta (GstQuery * query, guint index)
 
   structure = GST_QUERY_STRUCTURE (query);
   array =
-      ensure_array (structure, GST_QUARK (META), sizeof (AllocationMeta),
+      ensure_array (structure, "meta", sizeof (AllocationMeta),
       (GDestroyNotify) allocation_meta_free);
   g_return_if_fail (index < array->len);
 
@@ -1918,7 +1905,7 @@ gst_query_find_allocation_meta (GstQuery * query, GType api, guint * index)
 
   structure = GST_QUERY_STRUCTURE (query);
   array =
-      ensure_array (structure, GST_QUARK (META), sizeof (AllocationMeta),
+      ensure_array (structure, "meta", sizeof (AllocationMeta),
       (GDestroyNotify) allocation_meta_free);
 
   len = array->len;
@@ -1967,7 +1954,7 @@ gst_query_add_allocation_param (GstQuery * query, GstAllocator * allocator,
   g_return_if_fail (allocator != NULL || params != NULL);
 
   structure = GST_QUERY_STRUCTURE (query);
-  array = ensure_array (structure, GST_QUARK (ALLOCATOR),
+  array = ensure_array (structure, "allocator",
       sizeof (AllocationParam), (GDestroyNotify) allocation_param_free);
 
   if ((ap.allocator = allocator))
@@ -2003,7 +1990,7 @@ gst_query_get_n_allocation_params (GstQuery * query)
   g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION, 0);
 
   structure = GST_QUERY_STRUCTURE (query);
-  array = ensure_array (structure, GST_QUARK (ALLOCATOR),
+  array = ensure_array (structure, "allocator",
       sizeof (AllocationParam), (GDestroyNotify) allocation_param_free);
 
   return array->len;
@@ -2030,7 +2017,7 @@ gst_query_parse_nth_allocation_param (GstQuery * query, guint index,
   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION);
 
   structure = GST_QUERY_STRUCTURE (query);
-  array = ensure_array (structure, GST_QUARK (ALLOCATOR),
+  array = ensure_array (structure, "allocator",
       sizeof (AllocationParam), (GDestroyNotify) allocation_param_free);
   g_return_if_fail (index < array->len);
 
@@ -2064,7 +2051,7 @@ gst_query_set_nth_allocation_param (GstQuery * query, guint index,
   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION);
 
   structure = GST_QUERY_STRUCTURE (query);
-  array = ensure_array (structure, GST_QUARK (ALLOCATOR),
+  array = ensure_array (structure, "allocator",
       sizeof (AllocationParam), (GDestroyNotify) allocation_param_free);
   g_return_if_fail (index < array->len);
 
@@ -2101,7 +2088,7 @@ gst_query_remove_nth_allocation_param (GstQuery * query, guint index)
 
   structure = GST_QUERY_STRUCTURE (query);
   array =
-      ensure_array (structure, GST_QUARK (ALLOCATOR), sizeof (AllocationParam),
+      ensure_array (structure, "allocator", sizeof (AllocationParam),
       (GDestroyNotify) allocation_param_free);
   g_return_if_fail (index < array->len);
 
@@ -2123,11 +2110,10 @@ gst_query_new_scheduling (void)
   GstQuery *query;
   GstStructure *structure;
 
-  structure = gst_structure_new_id (GST_QUARK (QUERY_SCHEDULING),
-      GST_QUARK (FLAGS), GST_TYPE_SCHEDULING_FLAGS, 0,
-      GST_QUARK (MINSIZE), G_TYPE_INT, 1,
-      GST_QUARK (MAXSIZE), G_TYPE_INT, -1,
-      GST_QUARK (ALIGN), G_TYPE_INT, 0, NULL);
+  structure = gst_structure_new_static_str ("GstQueryScheduling",
+      "flags", GST_TYPE_SCHEDULING_FLAGS, 0,
+      "minsize", G_TYPE_INT, 1,
+      "maxsize", G_TYPE_INT, -1, "align", G_TYPE_INT, 0, NULL);
   query = gst_query_new_custom (GST_QUERY_SCHEDULING, structure);
 
   return query;
@@ -2153,11 +2139,10 @@ gst_query_set_scheduling (GstQuery * query, GstSchedulingFlags flags,
   g_return_if_fail (gst_query_is_writable (query));
 
   structure = GST_QUERY_STRUCTURE (query);
-  gst_structure_id_set (structure,
-      GST_QUARK (FLAGS), GST_TYPE_SCHEDULING_FLAGS, flags,
-      GST_QUARK (MINSIZE), G_TYPE_INT, minsize,
-      GST_QUARK (MAXSIZE), G_TYPE_INT, maxsize,
-      GST_QUARK (ALIGN), G_TYPE_INT, align, NULL);
+  gst_structure_set (structure,
+      "flags", GST_TYPE_SCHEDULING_FLAGS, flags,
+      "minsize", G_TYPE_INT, minsize,
+      "maxsize", G_TYPE_INT, maxsize, "align", G_TYPE_INT, align, NULL);
 }
 
 /**
@@ -2179,11 +2164,10 @@ gst_query_parse_scheduling (GstQuery * query, GstSchedulingFlags * flags,
   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_SCHEDULING);
 
   structure = GST_QUERY_STRUCTURE (query);
-  gst_structure_id_get (structure,
-      GST_QUARK (FLAGS), GST_TYPE_SCHEDULING_FLAGS, flags,
-      GST_QUARK (MINSIZE), G_TYPE_INT, minsize,
-      GST_QUARK (MAXSIZE), G_TYPE_INT, maxsize,
-      GST_QUARK (ALIGN), G_TYPE_INT, align, NULL);
+  gst_structure_get (structure,
+      "flags", GST_TYPE_SCHEDULING_FLAGS, flags,
+      "minsize", G_TYPE_INT, minsize,
+      "maxsize", G_TYPE_INT, maxsize, "align", G_TYPE_INT, align, NULL);
 }
 
 /**
@@ -2203,8 +2187,7 @@ gst_query_add_scheduling_mode (GstQuery * query, GstPadMode mode)
   g_return_if_fail (gst_query_is_writable (query));
 
   structure = GST_QUERY_STRUCTURE (query);
-  array =
-      ensure_array (structure, GST_QUARK (MODES), sizeof (GstPadMode), NULL);
+  array = ensure_array (structure, "modes", sizeof (GstPadMode), NULL);
 
   g_array_append_val (array, mode);
 }
@@ -2227,8 +2210,7 @@ gst_query_get_n_scheduling_modes (GstQuery * query)
   g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_SCHEDULING, 0);
 
   structure = GST_QUERY_STRUCTURE (query);
-  array =
-      ensure_array (structure, GST_QUARK (MODES), sizeof (GstPadMode), NULL);
+  array = ensure_array (structure, "modes", sizeof (GstPadMode), NULL);
 
   return array->len;
 }
@@ -2253,8 +2235,7 @@ gst_query_parse_nth_scheduling_mode (GstQuery * query, guint index)
       GST_PAD_MODE_NONE);
 
   structure = GST_QUERY_STRUCTURE (query);
-  array =
-      ensure_array (structure, GST_QUARK (MODES), sizeof (GstPadMode), NULL);
+  array = ensure_array (structure, "modes", sizeof (GstPadMode), NULL);
   g_return_val_if_fail (index < array->len, GST_PAD_MODE_NONE);
 
   return g_array_index (array, GstPadMode, index);
@@ -2285,8 +2266,7 @@ gst_query_has_scheduling_mode (GstQuery * query, GstPadMode mode)
   g_return_val_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_SCHEDULING, FALSE);
 
   structure = GST_QUERY_STRUCTURE (query);
-  array =
-      ensure_array (structure, GST_QUARK (MODES), sizeof (GstPadMode), NULL);
+  array = ensure_array (structure, "modes", sizeof (GstPadMode), NULL);
 
   len = array->len;
   for (i = 0; i < len; i++) {
@@ -2340,9 +2320,8 @@ gst_query_new_accept_caps (GstCaps * caps)
 
   g_return_val_if_fail (gst_caps_is_fixed (caps), NULL);
 
-  structure = gst_structure_new_id (GST_QUARK (QUERY_ACCEPT_CAPS),
-      GST_QUARK (CAPS), GST_TYPE_CAPS, caps,
-      GST_QUARK (RESULT), G_TYPE_BOOLEAN, FALSE, NULL);
+  structure = gst_structure_new_static_str ("GstQueryAcceptCaps",
+      "caps", GST_TYPE_CAPS, caps, "result", G_TYPE_BOOLEAN, FALSE, NULL);
   query = gst_query_new_custom (GST_QUERY_ACCEPT_CAPS, structure);
 
   return query;
@@ -2365,8 +2344,7 @@ gst_query_parse_accept_caps (GstQuery * query, GstCaps ** caps)
   g_return_if_fail (caps != NULL);
 
   structure = GST_QUERY_STRUCTURE (query);
-  *caps = g_value_get_boxed (gst_structure_id_get_value (structure,
-          GST_QUARK (CAPS)));
+  *caps = g_value_get_boxed (gst_structure_get_value (structure, "caps"));
 }
 
 /**
@@ -2385,8 +2363,7 @@ gst_query_set_accept_caps_result (GstQuery * query, gboolean result)
   g_return_if_fail (gst_query_is_writable (query));
 
   structure = GST_QUERY_STRUCTURE (query);
-  gst_structure_id_set (structure,
-      GST_QUARK (RESULT), G_TYPE_BOOLEAN, result, NULL);
+  gst_structure_set (structure, "result", G_TYPE_BOOLEAN, result, NULL);
 }
 
 /**
@@ -2404,8 +2381,7 @@ gst_query_parse_accept_caps_result (GstQuery * query, gboolean * result)
   g_return_if_fail (GST_QUERY_TYPE (query) == GST_QUERY_ACCEPT_CAPS);
 
   structure = GST_QUERY_STRUCTURE (query);
-  gst_structure_id_get (structure,
-      GST_QUARK (RESULT), G_TYPE_BOOLEAN, result, NULL);
+  gst_structure_get (structure, "result", G_TYPE_BOOLEAN, result, NULL);
 }
 
 /**
@@ -2441,9 +2417,8 @@ gst_query_new_caps (GstCaps * filter)
   GstQuery *query;
   GstStructure *structure;
 
-  structure = gst_structure_new_id (GST_QUARK (QUERY_CAPS),
-      GST_QUARK (FILTER), GST_TYPE_CAPS, filter,
-      GST_QUARK (CAPS), GST_TYPE_CAPS, NULL, NULL);
+  structure = gst_structure_new_static_str ("GstQueryCaps",
+      "filter", GST_TYPE_CAPS, filter, "caps", GST_TYPE_CAPS, NULL, NULL);
   query = gst_query_new_custom (GST_QUERY_CAPS, structure);
 
   return query;
@@ -2466,8 +2441,7 @@ gst_query_parse_caps (GstQuery * query, GstCaps ** filter)
   g_return_if_fail (filter != NULL);
 
   structure = GST_QUERY_STRUCTURE (query);
-  *filter = g_value_get_boxed (gst_structure_id_get_value (structure,
-          GST_QUARK (FILTER)));
+  *filter = g_value_get_boxed (gst_structure_get_value (structure, "filter"));
 }
 
 /**
@@ -2486,7 +2460,7 @@ gst_query_set_caps_result (GstQuery * query, GstCaps * caps)
   g_return_if_fail (gst_query_is_writable (query));
 
   structure = GST_QUERY_STRUCTURE (query);
-  gst_structure_id_set (structure, GST_QUARK (CAPS), GST_TYPE_CAPS, caps, NULL);
+  gst_structure_set (structure, "caps", GST_TYPE_CAPS, caps, NULL);
 }
 
 /**
@@ -2506,8 +2480,7 @@ gst_query_parse_caps_result (GstQuery * query, GstCaps ** caps)
   g_return_if_fail (caps != NULL);
 
   structure = GST_QUERY_STRUCTURE (query);
-  *caps = g_value_get_boxed (gst_structure_id_get_value (structure,
-          GST_QUARK (CAPS)));
+  *caps = g_value_get_boxed (gst_structure_get_value (structure, "caps"));
 }
 
 #if 0
@@ -2539,7 +2512,7 @@ gst_query_new_drain (void)
   GstQuery *query;
   GstStructure *structure;
 
-  structure = gst_structure_new_id_empty (GST_QUARK (QUERY_DRAIN));
+  structure = gst_structure_new_static_str_empty ("GstQueryDrain");
   query = gst_query_new_custom (GST_QUERY_DRAIN, structure);
 
   return query;
@@ -2565,8 +2538,8 @@ gst_query_new_context (const gchar * context_type)
 
   g_return_val_if_fail (context_type != NULL, NULL);
 
-  structure = gst_structure_new_id (GST_QUARK (QUERY_CONTEXT),
-      GST_QUARK (CONTEXT_TYPE), G_TYPE_STRING, context_type, NULL);
+  structure = gst_structure_new_static_str ("GstQueryContext",
+      "context-type", G_TYPE_STRING, context_type, NULL);
   query = gst_query_new_custom (GST_QUERY_CONTEXT, structure);
 
   return query;
@@ -2595,8 +2568,7 @@ gst_query_set_context (GstQuery * query, GstContext * context)
 
   s = GST_QUERY_STRUCTURE (query);
 
-  gst_structure_id_set (s,
-      GST_QUARK (CONTEXT), GST_TYPE_CONTEXT, context, NULL);
+  gst_structure_set (s, "context", GST_TYPE_CONTEXT, context, NULL);
 }
 
 /**
@@ -2619,7 +2591,7 @@ gst_query_parse_context (GstQuery * query, GstContext ** context)
   g_return_if_fail (context != NULL);
 
   structure = GST_QUERY_STRUCTURE (query);
-  v = gst_structure_id_get_value (structure, GST_QUARK (CONTEXT));
+  v = gst_structure_get_value (structure, "context");
   if (v)
     *context = g_value_get_boxed (v);
   else
@@ -2648,7 +2620,7 @@ gst_query_parse_context_type (GstQuery * query, const gchar ** context_type)
   structure = GST_QUERY_STRUCTURE (query);
 
   if (context_type) {
-    value = gst_structure_id_get_value (structure, GST_QUARK (CONTEXT_TYPE));
+    value = gst_structure_get_value (structure, "context-type");
     *context_type = g_value_get_string (value);
   }
 
@@ -2672,7 +2644,7 @@ gst_query_new_bitrate (void)
   GstQuery *query;
   GstStructure *structure;
 
-  structure = gst_structure_new_id_empty (GST_QUARK (QUERY_BITRATE));
+  structure = gst_structure_new_static_str_empty ("GstQueryBitrate");
   query = gst_query_new_custom (GST_QUERY_BITRATE, structure);
 
   return query;
@@ -2698,8 +2670,7 @@ gst_query_set_bitrate (GstQuery * query, guint nominal_bitrate)
 
   s = GST_QUERY_STRUCTURE (query);
 
-  gst_structure_id_set (s,
-      GST_QUARK (NOMINAL_BITRATE), G_TYPE_UINT, nominal_bitrate, NULL);
+  gst_structure_set (s, "nominal-bitrate", G_TYPE_UINT, nominal_bitrate, NULL);
 }
 
 /**
@@ -2722,7 +2693,7 @@ gst_query_parse_bitrate (GstQuery * query, guint * nominal_bitrate)
   structure = GST_QUERY_STRUCTURE (query);
 
   if (nominal_bitrate) {
-    value = gst_structure_id_get_value (structure, GST_QUARK (NOMINAL_BITRATE));
+    value = gst_structure_get_value (structure, "nominal-bitrate");
     *nominal_bitrate = g_value_get_uint (value);
   }
 }
@@ -2744,7 +2715,7 @@ gst_query_new_selectable (void)
   GstQuery *query;
   GstStructure *structure;
 
-  structure = gst_structure_new_id_empty (GST_QUARK (QUERY_SELECTABLE));
+  structure = gst_structure_new_static_str_empty ("GstQuerySelectable");
   query = gst_query_new_custom (GST_QUERY_SELECTABLE, structure);
 
   return query;
@@ -2769,8 +2740,7 @@ gst_query_set_selectable (GstQuery * query, gboolean selectable)
 
   s = GST_QUERY_STRUCTURE (query);
 
-  gst_structure_id_set (s,
-      GST_QUARK (SELECTABLE), G_TYPE_BOOLEAN, selectable, NULL);
+  gst_structure_set (s, "selectable", G_TYPE_BOOLEAN, selectable, NULL);
 }
 
 /**
@@ -2792,8 +2762,7 @@ gst_query_parse_selectable (GstQuery * query, gboolean * selectable)
   structure = GST_QUERY_STRUCTURE (query);
 
   if (selectable) {
-    const GValue *value =
-        gst_structure_id_get_value (structure, GST_QUARK (SELECTABLE));
+    const GValue *value = gst_structure_get_value (structure, "selectable");
     if (value)
       *selectable = g_value_get_boolean (value);
     else
diff --git a/gst/gstregistry.c b/gst/gstregistry.c
index 2226d18..6d06606 100644
--- a/gst/gstregistry.c
+++ b/gst/gstregistry.c
@@ -644,9 +644,9 @@ gst_registry_remove_feature (GstRegistry * registry, GstPluginFeature * feature)
 /**
  * gst_registry_plugin_filter:
  * @registry: registry to query
- * @filter: (scope call): the filter to use
+ * @filter: (scope call) (closure user_data): the filter to use
  * @first: only return first match
- * @user_data: (closure): user data passed to the filter function
+ * @user_data: user data passed to the filter function
  *
  * Runs a filter against all plugins in the registry and returns a #GList with
  * the results. If the first flag is set, only the first match is
@@ -823,9 +823,9 @@ gst_registry_get_device_provider_factory_list (GstRegistry * registry)
 /**
  * gst_registry_feature_filter:
  * @registry: registry to query
- * @filter: (scope call): the filter to use
+ * @filter: (scope call) (closure user_data): the filter to use
  * @first: only return first match
- * @user_data: (closure): user data passed to the filter function
+ * @user_data: user data passed to the filter function
  *
  * Runs a filter against all features of the plugins in the registry
  * and returns a GList with the results.
diff --git a/gst/gststructure.c b/gst/gststructure.c
index 9055ddf..c2f80b4 100644
--- a/gst/gststructure.c
+++ b/gst/gststructure.c
@@ -90,14 +90,17 @@
  *
  * Some types have special delimiters:
  *
- * - [GstValueArray](GST_TYPE_ARRAY) are inside curly brackets (`{` and `}`).
- *   For example `a-structure, array={1, 2, 3}`
+ * - [GstValueArray](GST_TYPE_ARRAY) are inside "less and greater than" (`<` and
+ *   `>`). For example `a-structure, array=<1, 2, 3>
  * - Ranges are inside brackets (`[` and `]`). For example `a-structure,
  *   range=[1, 6, 2]` 1 being the min value, 6 the maximum and 2 the step. To
  *   specify a #GST_TYPE_INT64_RANGE you need to explicitly specify it like:
  *   `a-structure, a-int64-range=(gint64) [1, 5]`
- * - [GstValueList](GST_TYPE_LIST) are inside "less and greater than" (`<` and
- *   `>`). For example `a-structure, list=<1, 2, 3>
+ * - [GstValueList](GST_TYPE_LIST) are inside curly brackets (`{` and `}`).
+ *   For example `a-structure, list={1, 2, 3}`
+ * - [GStrv](G_TYPE_STRV) are inside "less and greater than" (`<` and
+ *   `>`) and each string is double-quoted.
+ *   For example `a-structure, strv=(GStrv)<"foo", "bar">`. Since 1.26.0.
  *
  * Structures are delimited either by a null character `\0` or a semicolon `;`
  * the latter allowing to store multiple structures in the same string (see
@@ -142,8 +145,8 @@
 #include <string.h>
 
 #include "gst_private.h"
-#include "gstquark.h"
 #include <gst/gst.h>
+#include "gstidstr-private.h"
 #include <gobject/gvaluecollector.h>
 
 GST_DEBUG_CATEGORY_STATIC (gst_structure_debug);
@@ -153,7 +156,7 @@ typedef struct _GstStructureField GstStructureField;
 
 struct _GstStructureField
 {
-  GQuark name;
+  GstIdStr name;
   GValue value;
 };
 
@@ -161,6 +164,9 @@ typedef struct
 {
   GstStructure s;
 
+  /* Actual structure name */
+  GstIdStr name;
+
   /* owned by parent structure, NULL if no parent */
   gint *parent_refcount;
 
@@ -176,6 +182,7 @@ typedef struct
 
 #define GST_STRUCTURE_REFCOUNT(s) (((GstStructureImpl*)(s))->parent_refcount)
 #define GST_STRUCTURE_LEN(s) (((GstStructureImpl*)(s))->fields_len)
+#define GST_STRUCTURE_NAME(s) (&((GstStructureImpl*)(s))->name)
 
 #define GST_STRUCTURE_IS_USING_DYNAMIC_ARRAY(s) \
   (((GstStructureImpl*)(s))->fields != &((GstStructureImpl*)(s))->arr[0])
@@ -188,7 +195,8 @@ typedef struct
      g_atomic_int_get (GST_STRUCTURE_REFCOUNT(structure)) == 1)
 
 #define IS_TAGLIST(structure) \
-    (structure->name == GST_QUARK (TAGLIST))
+    (((const GstIdStrPrivate *) GST_STRUCTURE_NAME (structure))->s.string_type.t == 0 && \
+     (memcmp (((const GstIdStrPrivate *) GST_STRUCTURE_NAME (structure))->s.short_string.s, "taglist", sizeof ("taglist")) == 0))
 
 /* Replacement for g_array_append_val */
 static void
@@ -242,8 +250,8 @@ static void gst_structure_set_field (GstStructure * structure,
     GstStructureField * field);
 static GstStructureField *gst_structure_get_field (const GstStructure *
     structure, const gchar * fieldname);
-static GstStructureField *gst_structure_id_get_field (const GstStructure *
-    structure, GQuark field);
+static GstStructureField *gst_structure_id_str_get_field (const GstStructure *
+    structure, const GstIdStr * fieldname);
 static void gst_structure_transform_to_string (const GValue * src_value,
     GValue * dest_value);
 static GstStructure *gst_structure_copy_conditional (const GstStructure *
@@ -267,8 +275,9 @@ _priv_gst_structure_initialize (void)
       "GstStructure debug");
 }
 
+/* takes ownership of @name */
 static GstStructure *
-gst_structure_new_id_empty_with_size (GQuark quark, guint prealloc)
+gst_structure_new_take_id_str_empty_with_size (GstIdStr * name, guint prealloc)
 {
   guint n_alloc;
   GstStructureImpl *structure;
@@ -282,7 +291,8 @@ gst_structure_new_id_empty_with_size (GQuark quark, guint prealloc)
           1) * sizeof (GstStructureField));
 
   ((GstStructure *) structure)->type = _gst_structure_type;
-  ((GstStructure *) structure)->name = quark;
+  ((GstStructure *) structure)->name = 0;
+  gst_id_str_move (&structure->name, name);
   GST_STRUCTURE_REFCOUNT (structure) = NULL;
 
   structure->fields_len = 0;
@@ -294,6 +304,26 @@ gst_structure_new_id_empty_with_size (GQuark quark, guint prealloc)
   return GST_STRUCTURE_CAST (structure);
 }
 
+static GstStructure *
+gst_structure_new_id_str_empty_with_size (const GstIdStr * name, guint prealloc)
+{
+  GstIdStr s = GST_ID_STR_INIT;
+
+  gst_id_str_copy_into (&s, name);
+
+  return gst_structure_new_take_id_str_empty_with_size (&s, prealloc);
+}
+
+static GstStructure *
+gst_structure_new_str_empty_with_size (const gchar * name, guint prealloc)
+{
+  GstIdStr s = GST_ID_STR_INIT;
+
+  gst_id_str_set (&s, name);
+
+  return gst_structure_new_take_id_str_empty_with_size (&s, prealloc);
+}
+
 /**
  * gst_structure_new_id_empty:
  * @quark: name of new structure
@@ -303,13 +333,19 @@ gst_structure_new_id_empty_with_size (GQuark quark, guint prealloc)
  * Free-function: gst_structure_free
  *
  * Returns: (transfer full): a new, empty #GstStructure
+ *
+ * Deprecated: 1.26: Use gst_structure_new_id_str_empty().
  */
 GstStructure *
 gst_structure_new_id_empty (GQuark quark)
 {
+  GstIdStr s = GST_ID_STR_INIT;
+
   g_return_val_if_fail (quark != 0, NULL);
 
-  return gst_structure_new_id_empty_with_size (quark, 0);
+  gst_id_str_set_static_str (&s, g_quark_to_string (quark));
+
+  return gst_structure_new_take_id_str_empty_with_size (&s, 0);
 }
 
 static gboolean
@@ -346,6 +382,28 @@ gst_structure_validate_name (const gchar * name)
   return TRUE;
 }
 
+/**
+ * gst_structure_new_id_str_empty:
+ * @name: name of new structure
+ *
+ * Creates a new, empty #GstStructure with the given name.
+ *
+ * Free-function: gst_structure_free
+ *
+ * Returns: (transfer full): a new, empty #GstStructure
+ *
+ * Since: 1.26
+ */
+GstStructure *
+gst_structure_new_id_str_empty (const GstIdStr * name)
+{
+  g_return_val_if_fail (name != 0, NULL);
+  g_return_val_if_fail (gst_structure_validate_name (gst_id_str_as_str (name)),
+      NULL);
+
+  return gst_structure_new_id_str_empty_with_size (name, 0);
+}
+
 /**
  * gst_structure_new_empty:
  * @name: name of new structure
@@ -363,7 +421,68 @@ gst_structure_new_empty (const gchar * name)
 {
   g_return_val_if_fail (gst_structure_validate_name (name), NULL);
 
-  return gst_structure_new_id_empty_with_size (g_quark_from_string (name), 0);
+  return gst_structure_new_str_empty_with_size (name, 0);
+}
+
+/**
+ * gst_structure_new_static_str_empty:
+ * @name: name of new structure
+ *
+ * Creates a new, empty #GstStructure with the given @name.
+ *
+ * See gst_structure_set_name() for constraints on the @name parameter.
+ *
+ * @name needs to be valid for the remaining lifetime of the process, e.g. has
+ * to be a static string.
+ *
+ * Free-function: gst_structure_free
+ *
+ * Returns: (transfer full): a new, empty #GstStructure
+ *
+ * Since: 1.26
+ */
+GstStructure *
+gst_structure_new_static_str_empty (const gchar * name)
+{
+  GstIdStr s = GST_ID_STR_INIT;
+
+  g_return_val_if_fail (gst_structure_validate_name (name), NULL);
+
+  gst_id_str_set_static_str (&s, name);
+  return gst_structure_new_take_id_str_empty_with_size (&s, 0);
+}
+
+/**
+ * gst_structure_new_static_str:
+ * @name: name of new structure
+ * @firstfield: name of first field to set
+ * @...: additional arguments
+ *
+ * Creates a new #GstStructure with the given name.  Parses the
+ * list of variable arguments and sets fields to the values listed.
+ * Variable arguments should be passed as field name, field type,
+ * and value.  Last variable argument should be %NULL.
+ *
+ * @name, @firstfield and all field names need to be valid for the remaining
+ * lifetime of the process, e.g. have to be a static string.
+ *
+ * Free-function: gst_structure_free
+ *
+ * Returns: (transfer full): a new #GstStructure
+ *
+ * Since: 1.26
+ */
+GstStructure *
+gst_structure_new_static_str (const gchar * name, const gchar * firstfield, ...)
+{
+  GstStructure *structure;
+  va_list varargs;
+
+  va_start (varargs, firstfield);
+  structure = gst_structure_new_static_str_valist (name, firstfield, varargs);
+  va_end (varargs);
+
+  return structure;
 }
 
 /**
@@ -394,6 +513,53 @@ gst_structure_new (const gchar * name, const gchar * firstfield, ...)
   return structure;
 }
 
+/**
+ * gst_structure_new_id_str_valist:
+ * @name: name of new structure
+ * @firstfield: name of first field to set
+ * @varargs: variable argument list
+ *
+ * Creates a new #GstStructure with the given @name.  Structure fields
+ * are set according to the varargs in a manner similar to
+ * gst_structure_new_id_str().
+ *
+ * Free-function: gst_structure_free
+ *
+ * Returns: (transfer full): a new #GstStructure
+ *
+ * Since: 1.26
+ */
+GstStructure *
+gst_structure_new_id_str_valist (const GstIdStr * name,
+    const GstIdStr * firstfield, va_list varargs)
+{
+  GstStructure *structure;
+  va_list copy;
+  guint len = 0;
+  const GstIdStr *field_copy = firstfield;
+  GType type_copy;
+
+  g_return_val_if_fail (gst_structure_validate_name (gst_id_str_as_str (name)),
+      NULL);
+
+  /* Calculate size of varargs */
+  va_copy (copy, varargs);
+  while (field_copy) {
+    type_copy = va_arg (copy, GType);
+    G_VALUE_COLLECT_SKIP (type_copy, copy);
+    field_copy = va_arg (copy, const GstIdStr *);
+    len++;
+  }
+  va_end (copy);
+
+  structure = gst_structure_new_id_str_empty_with_size (name, len);
+
+  if (structure)
+    gst_structure_id_str_set_valist (structure, firstfield, varargs);
+
+  return structure;
+}
+
 /**
  * gst_structure_new_valist:
  * @name: name of new structure
@@ -432,8 +598,7 @@ gst_structure_new_valist (const gchar * name,
   }
   va_end (copy);
 
-  structure =
-      gst_structure_new_id_empty_with_size (g_quark_from_string (name), len);
+  structure = gst_structure_new_str_empty_with_size (name, len);
 
   if (structure)
     gst_structure_set_valist (structure, firstfield, varargs);
@@ -441,6 +606,60 @@ gst_structure_new_valist (const gchar * name,
   return structure;
 }
 
+/**
+ * gst_structure_new_static_str_valist:
+ * @name: name of new structure
+ * @firstfield: name of first field to set
+ * @varargs: variable argument list
+ *
+ * Creates a new #GstStructure with the given @name.  Structure fields
+ * are set according to the varargs in a manner similar to
+ * gst_structure_new().
+ *
+ * See gst_structure_set_name() for constraints on the @name parameter.
+ *
+ * @name, @firstfield and all field names need to be valid for the remaining
+ * lifetime of the process, e.g. have to be a static string.
+ *
+ * Free-function: gst_structure_free
+ *
+ * Returns: (transfer full): a new #GstStructure
+ *
+ * Since: 1.26
+ */
+GstStructure *
+gst_structure_new_static_str_valist (const gchar * name,
+    const gchar * firstfield, va_list varargs)
+{
+  GstIdStr s = GST_ID_STR_INIT;
+  GstStructure *structure;
+  va_list copy;
+  guint len = 0;
+  const gchar *field_copy = firstfield;
+  GType type_copy;
+
+  g_return_val_if_fail (gst_structure_validate_name (name), NULL);
+
+  /* Calculate size of varargs */
+  va_copy (copy, varargs);
+  while (field_copy) {
+    type_copy = va_arg (copy, GType);
+    G_VALUE_COLLECT_SKIP (type_copy, copy);
+    field_copy = va_arg (copy, gchar *);
+    len++;
+  }
+  va_end (copy);
+
+  gst_id_str_set_static_str (&s, name);
+
+  structure = gst_structure_new_take_id_str_empty_with_size (&s, len);
+
+  if (structure)
+    gst_structure_set_static_str_valist (structure, firstfield, varargs);
+
+  return structure;
+}
+
 /**
  * gst_structure_set_parent_refcount:
  * @structure: a #GstStructure
@@ -497,14 +716,16 @@ gst_structure_copy (const GstStructure * structure)
   g_return_val_if_fail (structure != NULL, NULL);
 
   len = GST_STRUCTURE_LEN (structure);
-  new_structure = gst_structure_new_id_empty_with_size (structure->name, len);
+  new_structure =
+      gst_structure_new_id_str_empty_with_size (GST_STRUCTURE_NAME (structure),
+      len);
 
   for (i = 0; i < len; i++) {
-    GstStructureField new_field = { 0 };
+    GstStructureField new_field = { GST_ID_STR_INIT, G_VALUE_INIT };
 
     field = GST_STRUCTURE_FIELD (structure, i);
 
-    new_field.name = field->name;
+    gst_id_str_copy_into (&new_field.name, &field->name);
     gst_value_init_and_copy (&new_field.value, &field->value);
     _structure_append_val (new_structure, &new_field);
   }
@@ -537,10 +758,13 @@ gst_structure_free (GstStructure * structure)
     if (G_IS_VALUE (&field->value)) {
       g_value_unset (&field->value);
     }
+    gst_id_str_clear (&field->name);
   }
   if (GST_STRUCTURE_IS_USING_DYNAMIC_ARRAY (structure))
     g_free (((GstStructureImpl *) structure)->fields);
 
+  gst_id_str_clear (GST_STRUCTURE_NAME (structure));
+
 #ifdef USE_POISONING
   memset (structure, 0xff, sizeof (GstStructure));
 #endif
@@ -627,7 +851,7 @@ gst_structure_get_name (const GstStructure * structure)
 {
   g_return_val_if_fail (structure != NULL, NULL);
 
-  return g_quark_to_string (structure->name);
+  return gst_id_str_as_str (GST_STRUCTURE_NAME (structure));
 }
 
 /**
@@ -642,17 +866,11 @@ gst_structure_get_name (const GstStructure * structure)
 gboolean
 gst_structure_has_name (const GstStructure * structure, const gchar * name)
 {
-  const gchar *structure_name;
-
   g_return_val_if_fail (structure != NULL, FALSE);
   g_return_val_if_fail (name != NULL, FALSE);
 
-  /* getting the string is cheap and comparing short strings is too
-   * should be faster than getting the quark for name and comparing the quarks
-   */
-  structure_name = g_quark_to_string (structure->name);
-
-  return (structure_name && strcmp (structure_name, name) == 0);
+  return gst_id_str_is_equal_to_str (gst_structure_get_name_id_str (structure),
+      name);
 }
 
 /**
@@ -662,13 +880,55 @@ gst_structure_has_name (const GstStructure * structure, const gchar * name)
  * Get the name of @structure as a GQuark.
  *
  * Returns: the quark representing the name of the structure.
+ *
+ * Deprecated: 1.26: Use gst_structure_get_name_id_str().
  */
 GQuark
 gst_structure_get_name_id (const GstStructure * structure)
 {
   g_return_val_if_fail (structure != NULL, 0);
 
-  return structure->name;
+  return
+      g_quark_from_string (gst_id_str_as_str (GST_STRUCTURE_NAME (structure)));
+}
+
+/**
+ * gst_structure_get_name_id_str:
+ * @structure: a #GstStructure
+ *
+ * Get the name of @structure as a GstIdStr.
+ *
+ * Returns: the name of the structure.
+ *
+ * Since: 1.26
+ */
+const GstIdStr *
+gst_structure_get_name_id_str (const GstStructure * structure)
+{
+  g_return_val_if_fail (structure != NULL, 0);
+
+  return GST_STRUCTURE_NAME (structure);
+}
+
+/**
+ * gst_structure_set_name_id_str:
+ * @structure: a #GstStructure
+ * @name: the new name of the structure
+ *
+ * Sets the name of the structure to the given @name.  The string
+ * provided is copied before being used. It must not be empty, start with a
+ * letter and can be followed by letters, numbers and any of "/-_.:".
+ *
+ * Since: 1.26
+ */
+void
+gst_structure_set_name_id_str (GstStructure * structure, const GstIdStr * name)
+{
+  g_return_if_fail (structure != NULL);
+  g_return_if_fail (IS_MUTABLE (structure));
+  g_return_if_fail (gst_structure_validate_name (gst_id_str_as_str (name)));
+
+  gst_id_str_copy_into (GST_STRUCTURE_NAME (structure), name);
 }
 
 /**
@@ -687,16 +947,41 @@ gst_structure_set_name (GstStructure * structure, const gchar * name)
   g_return_if_fail (IS_MUTABLE (structure));
   g_return_if_fail (gst_structure_validate_name (name));
 
-  structure->name = g_quark_from_string (name);
+  gst_id_str_set (GST_STRUCTURE_NAME (structure), name);
+}
+
+/**
+ * gst_structure_set_name_static_str:
+ * @structure: a #GstStructure
+ * @name: the new name of the structure
+ *
+ * Sets the name of the structure to the given @name.  The string
+ * provided is copied before being used. It must not be empty, start with a
+ * letter and can be followed by letters, numbers and any of "/-_.:".
+ *
+ * @name needs to be valid for the remaining lifetime of the process, e.g. has
+ * to be a static string.
+ *
+ * Since: 1.26
+ */
+void
+gst_structure_set_name_static_str (GstStructure * structure, const gchar * name)
+{
+  g_return_if_fail (structure != NULL);
+  g_return_if_fail (IS_MUTABLE (structure));
+  g_return_if_fail (gst_structure_validate_name (name));
+
+  gst_id_str_set_static_str (GST_STRUCTURE_NAME (structure), name);
 }
 
+/* takes ownership of fieldname (but not value) */
 static inline void
-gst_structure_id_set_value_internal (GstStructure * structure, GQuark field,
-    const GValue * value)
+gst_structure_id_str_set_value_internal (GstStructure * structure,
+    GstIdStr * fieldname, const GValue * value)
 {
-  GstStructureField gsfield = { 0, {0,} };
+  GstStructureField gsfield = { GST_ID_STR_INIT, G_VALUE_INIT };
 
-  gsfield.name = field;
+  gst_id_str_move (&gsfield.name, fieldname);
   gst_value_init_and_copy (&gsfield.value, value);
 
   gst_structure_set_field (structure, &gsfield);
@@ -711,17 +996,21 @@ gst_structure_id_set_value_internal (GstStructure * structure, GQuark field,
  * Sets the field with the given GQuark @field to @value.  If the field
  * does not exist, it is created.  If the field exists, the previous
  * value is replaced and freed.
+ *
+ * Deprecated: 1.26: Use gst_structure_id_str_set_value().
  */
 void
 gst_structure_id_set_value (GstStructure * structure,
     GQuark field, const GValue * value)
 {
+  GstIdStr s = GST_ID_STR_INIT;
 
   g_return_if_fail (structure != NULL);
   g_return_if_fail (G_IS_VALUE (value));
   g_return_if_fail (IS_MUTABLE (structure));
 
-  gst_structure_id_set_value_internal (structure, field, value);
+  gst_id_str_set_static_str (&s, g_quark_to_string (field));
+  gst_structure_id_str_set_value_internal (structure, &s, value);
 }
 
 /**
@@ -738,22 +1027,82 @@ void
 gst_structure_set_value (GstStructure * structure,
     const gchar * fieldname, const GValue * value)
 {
+  GstIdStr s = GST_ID_STR_INIT;
+
+  g_return_if_fail (structure != NULL);
+  g_return_if_fail (fieldname != NULL);
+  g_return_if_fail (G_IS_VALUE (value));
+  g_return_if_fail (IS_MUTABLE (structure));
+
+  gst_id_str_set (&s, fieldname);
+  gst_structure_id_str_set_value_internal (structure, &s, value);
+}
+
+/**
+ * gst_structure_set_value_static_str:
+ * @structure: a #GstStructure
+ * @fieldname: the name of the field to set
+ * @value: the new value of the field
+ *
+ * Sets the field with the given name @field to @value.  If the field
+ * does not exist, it is created.  If the field exists, the previous
+ * value is replaced and freed.
+ *
+ * @fieldname needs to be valid for the remaining lifetime of the process, e.g.
+ * has to be a static string.
+ *
+ * Since: 1.26
+ */
+void
+gst_structure_set_value_static_str (GstStructure * structure,
+    const gchar * fieldname, const GValue * value)
+{
+  GstIdStr s = GST_ID_STR_INIT;
+
+  g_return_if_fail (structure != NULL);
+  g_return_if_fail (fieldname != NULL);
+  g_return_if_fail (G_IS_VALUE (value));
+  g_return_if_fail (IS_MUTABLE (structure));
+
+  gst_id_str_set_static_str (&s, fieldname);
+  gst_structure_id_str_set_value_internal (structure, &s, value);
+}
+
+/**
+ * gst_structure_id_str_set_value:
+ * @structure: a #GstStructure
+ * @fieldname: the name of the field to set
+ * @value: the new value of the field
+ *
+ * Sets the field with the given name @field to @value.  If the field
+ * does not exist, it is created.  If the field exists, the previous
+ * value is replaced and freed.
+ *
+ * Since: 1.26
+ */
+void
+gst_structure_id_str_set_value (GstStructure * structure,
+    const GstIdStr * fieldname, const GValue * value)
+{
+  GstIdStr s = GST_ID_STR_INIT;
+
   g_return_if_fail (structure != NULL);
   g_return_if_fail (fieldname != NULL);
   g_return_if_fail (G_IS_VALUE (value));
   g_return_if_fail (IS_MUTABLE (structure));
 
-  gst_structure_id_set_value_internal (structure,
-      g_quark_from_string (fieldname), value);
+  gst_id_str_copy_into (&s, fieldname);
+  gst_structure_id_str_set_value_internal (structure, &s, value);
 }
 
+/* takes ownership of both fieldname and value */
 static inline void
-gst_structure_id_take_value_internal (GstStructure * structure, GQuark field,
-    GValue * value)
+gst_structure_id_str_take_value_internal (GstStructure * structure,
+    GstIdStr * fieldname, GValue * value)
 {
-  GstStructureField gsfield = { 0, {0,} };
+  GstStructureField gsfield = { GST_ID_STR_INIT, G_VALUE_INIT };
 
-  gsfield.name = field;
+  gst_id_str_move (&gsfield.name, fieldname);
   gsfield.value = *value;
 
   gst_structure_set_field (structure, &gsfield);
@@ -775,16 +1124,21 @@ gst_structure_id_take_value_internal (GstStructure * structure, GQuark field,
  * Sets the field with the given GQuark @field to @value.  If the field
  * does not exist, it is created.  If the field exists, the previous
  * value is replaced and freed.
+ *
+ * Deprecated: 1.26: Use gst_structure_id_str_take_value().
  */
 void
 gst_structure_id_take_value (GstStructure * structure, GQuark field,
     GValue * value)
 {
+  GstIdStr s = GST_ID_STR_INIT;
+
   g_return_if_fail (structure != NULL);
   g_return_if_fail (G_IS_VALUE (value));
   g_return_if_fail (IS_MUTABLE (structure));
 
-  gst_structure_id_take_value_internal (structure, field, value);
+  gst_id_str_set_static_str (&s, g_quark_to_string (field));
+  gst_structure_id_str_take_value_internal (structure, &s, value);
 }
 
 /**
@@ -801,38 +1155,99 @@ void
 gst_structure_take_value (GstStructure * structure, const gchar * fieldname,
     GValue * value)
 {
+  GstIdStr s = GST_ID_STR_INIT;
+
+  g_return_if_fail (structure != NULL);
+  g_return_if_fail (fieldname != NULL);
+  g_return_if_fail (G_IS_VALUE (value));
+  g_return_if_fail (IS_MUTABLE (structure));
+
+  gst_id_str_set (&s, fieldname);
+  gst_structure_id_str_take_value_internal (structure, &s, value);
+}
+
+/**
+ * gst_structure_take_value_static_str:
+ * @structure: a #GstStructure
+ * @fieldname: the name of the field to set
+ * @value: (transfer full): the new value of the field
+ *
+ * Sets the field with the given name @field to @value.  If the field
+ * does not exist, it is created.  If the field exists, the previous
+ * value is replaced and freed. The function will take ownership of @value.
+ *
+ * @fieldname needs to be valid for the remaining lifetime of the process, e.g.
+ * has to be a static string.
+ *
+ * Since: 1.26
+ */
+void
+gst_structure_take_value_static_str (GstStructure * structure,
+    const gchar * fieldname, GValue * value)
+{
+  GstIdStr s = GST_ID_STR_INIT;
+
   g_return_if_fail (structure != NULL);
   g_return_if_fail (fieldname != NULL);
   g_return_if_fail (G_IS_VALUE (value));
   g_return_if_fail (IS_MUTABLE (structure));
 
-  gst_structure_id_take_value_internal (structure,
-      g_quark_from_string (fieldname), value);
+  gst_id_str_set_static_str (&s, fieldname);
+  gst_structure_id_str_take_value_internal (structure, &s, value);
+}
+
+/**
+ * gst_structure_id_str_take_value:
+ * @structure: a #GstStructure
+ * @fieldname: the name of the field to set
+ * @value: (transfer full): the new value of the field
+ *
+ * Sets the field with the given GstIdStr @field to @value.  If the field
+ * does not exist, it is created.  If the field exists, the previous
+ * value is replaced and freed.
+ *
+ * Since: 1.26
+ */
+void
+gst_structure_id_str_take_value (GstStructure * structure,
+    const GstIdStr * fieldname, GValue * value)
+{
+  GstIdStr s = GST_ID_STR_INIT;
+
+  g_return_if_fail (structure != NULL);
+  g_return_if_fail (G_IS_VALUE (value));
+  g_return_if_fail (IS_MUTABLE (structure));
+
+  gst_id_str_copy_into (&s, fieldname);
+  gst_structure_id_str_take_value_internal (structure, &s, value);
 }
 
 static void
 gst_structure_set_valist_internal (GstStructure * structure,
-    const gchar * fieldname, va_list varargs)
+    gboolean static_string, const gchar * fieldname, va_list varargs)
 {
   gchar *err = NULL;
   GType type;
 
   while (fieldname) {
-    GstStructureField field = { 0 };
-
-    field.name = g_quark_from_string (fieldname);
+    GstStructureField field = { GST_ID_STR_INIT, G_VALUE_INIT };
 
+    if (static_string)
+      gst_id_str_set_static_str (&field.name, fieldname);
+    else
+      gst_id_str_set (&field.name, fieldname);
     type = va_arg (varargs, GType);
 
     G_VALUE_COLLECT_INIT (&field.value, type, varargs, 0, &err);
     if (G_UNLIKELY (err)) {
       g_critical ("%s", err);
       g_free (err);
+      gst_id_str_clear (&field.name);
       return;
     }
     gst_structure_set_field (structure, &field);
 
-    fieldname = va_arg (varargs, gchar *);
+    fieldname = va_arg (varargs, const gchar *);
   }
 }
 
@@ -856,7 +1271,37 @@ gst_structure_set (GstStructure * structure, const gchar * field, ...)
   g_return_if_fail (IS_MUTABLE (structure) || field == NULL);
 
   va_start (varargs, field);
-  gst_structure_set_valist_internal (structure, field, varargs);
+  gst_structure_set_valist_internal (structure, FALSE, field, varargs);
+  va_end (varargs);
+}
+
+/**
+ * gst_structure_set_static_str:
+ * @structure: a #GstStructure
+ * @fieldname: the name of the field to set
+ * @...: variable arguments
+ *
+ * Parses the variable arguments and sets fields accordingly. Fields that
+ * weren't already part of the structure are added as needed.
+ * Variable arguments should be in the form field name, field type
+ * (as a GType), value(s).  The last variable argument should be %NULL.
+ *
+ * @fieldname and all other field names needs to be valid for the remaining
+ * lifetime of the process, e.g. has to be a static string.
+ *
+ * Since: 1.26
+ */
+void
+gst_structure_set_static_str (GstStructure * structure, const gchar * field,
+    ...)
+{
+  va_list varargs;
+
+  g_return_if_fail (structure != NULL);
+  g_return_if_fail (IS_MUTABLE (structure) || field == NULL);
+
+  va_start (varargs, field);
+  gst_structure_set_valist_internal (structure, TRUE, field, varargs);
   va_end (varargs);
 }
 
@@ -875,7 +1320,30 @@ gst_structure_set_valist (GstStructure * structure,
   g_return_if_fail (structure != NULL);
   g_return_if_fail (IS_MUTABLE (structure));
 
-  gst_structure_set_valist_internal (structure, fieldname, varargs);
+  gst_structure_set_valist_internal (structure, FALSE, fieldname, varargs);
+}
+
+/**
+ * gst_structure_set_static_str_valist:
+ * @structure: a #GstStructure
+ * @fieldname: the name of the field to set
+ * @varargs: variable arguments
+ *
+ * va_list form of gst_structure_set_static_str().
+ *
+ * @fieldname and all other field names needs to be valid for the remaining
+ * lifetime of the process, e.g. has to be a static string.
+ *
+ * Since: 1.26
+ */
+void
+gst_structure_set_static_str_valist (GstStructure * structure,
+    const gchar * fieldname, va_list varargs)
+{
+  g_return_if_fail (structure != NULL);
+  g_return_if_fail (IS_MUTABLE (structure));
+
+  gst_structure_set_valist_internal (structure, TRUE, fieldname, varargs);
 }
 
 static void
@@ -886,15 +1354,16 @@ gst_structure_id_set_valist_internal (GstStructure * structure,
   GType type;
 
   while (fieldname) {
-    GstStructureField field = { 0 };
+    GstStructureField field = { GST_ID_STR_INIT, G_VALUE_INIT };
 
-    field.name = fieldname;
+    gst_id_str_set_static_str (&field.name, g_quark_to_string (fieldname));
     type = va_arg (varargs, GType);
 
     G_VALUE_COLLECT_INIT (&field.value, type, varargs, 0, &err);
     if (G_UNLIKELY (err)) {
       g_critical ("%s", err);
       g_free (err);
+      gst_id_str_clear (&field.name);
       return;
     }
     gst_structure_set_field (structure, &field);
@@ -914,6 +1383,8 @@ gst_structure_id_set_valist_internal (GstStructure * structure,
  * setting of the structure if the caller already knows the associated
  * quark values.
  * The last variable argument must be %NULL.
+ *
+ * Deprecated: 1.26: Use gst_structure_id_str_set().
  */
 void
 gst_structure_id_set (GstStructure * structure, GQuark field, ...)
@@ -934,6 +1405,8 @@ gst_structure_id_set (GstStructure * structure, GQuark field, ...)
  * @varargs: variable arguments
  *
  * va_list form of gst_structure_id_set().
+ *
+ * Deprecated: 1.26: Use gst_structure_id_str_set_valist().
  */
 void
 gst_structure_id_set_valist (GstStructure * structure,
@@ -945,6 +1418,79 @@ gst_structure_id_set_valist (GstStructure * structure,
   gst_structure_id_set_valist_internal (structure, fieldname, varargs);
 }
 
+static void
+gst_structure_id_str_set_valist_internal (GstStructure * structure,
+    const GstIdStr * fieldname, va_list varargs)
+{
+  gchar *err = NULL;
+  GType type;
+
+  while (fieldname) {
+    GstStructureField field = { GST_ID_STR_INIT, G_VALUE_INIT };
+
+    gst_id_str_copy_into (&field.name, fieldname);
+    type = va_arg (varargs, GType);
+
+    G_VALUE_COLLECT_INIT (&field.value, type, varargs, 0, &err);
+    if (G_UNLIKELY (err)) {
+      g_critical ("%s", err);
+      g_free (err);
+      gst_id_str_clear (&field.name);
+      return;
+    }
+    gst_structure_set_field (structure, &field);
+
+    fieldname = va_arg (varargs, const GstIdStr *);
+  }
+}
+
+/**
+ * gst_structure_id_str_set:
+ * @structure: a #GstStructure
+ * @fieldname: the the name of the field to set
+ * @...: variable arguments
+ *
+ * Identical to gst_structure_set, except that field names are
+ * passed using a GstIdStr for the field name. This allows more efficient
+ * setting of the structure if the caller already owns the associated
+ * GstIdStr values or if they can be built from static literals.
+ * The last variable argument must be %NULL.
+ *
+ * Since: 1.26
+ */
+void
+gst_structure_id_str_set (GstStructure * structure, const GstIdStr * fieldname,
+    ...)
+{
+  va_list varargs;
+
+  g_return_if_fail (structure != NULL);
+
+  va_start (varargs, fieldname);
+  gst_structure_id_str_set_valist_internal (structure, fieldname, varargs);
+  va_end (varargs);
+}
+
+/**
+ * gst_structure_id_str_set_valist:
+ * @structure: a #GstStructure
+ * @fieldname: the name of the field to set
+ * @varargs: variable arguments
+ *
+ * va_list form of gst_structure_id_str_set().
+ *
+ * Since: 1.26
+ */
+void
+gst_structure_id_str_set_valist (GstStructure * structure,
+    const GstIdStr * fieldname, va_list varargs)
+{
+  g_return_if_fail (structure != NULL);
+  g_return_if_fail (IS_MUTABLE (structure));
+
+  gst_structure_id_str_set_valist_internal (structure, fieldname, varargs);
+}
+
 /**
  * gst_structure_new_id:
  * @name_quark: name of new structure
@@ -961,10 +1507,13 @@ gst_structure_id_set_valist (GstStructure * structure,
  * Free-function: gst_structure_free
  *
  * Returns: (transfer full): a new #GstStructure
+ *
+ * Deprecated: 1.26: Use gst_structure_new_id_str().
  */
 GstStructure *
 gst_structure_new_id (GQuark name_quark, GQuark field_quark, ...)
 {
+  GstIdStr name = GST_ID_STR_INIT;
   GstStructure *s;
   va_list varargs;
   va_list copy;
@@ -987,7 +1536,8 @@ gst_structure_new_id (GQuark name_quark, GQuark field_quark, ...)
   }
   va_end (copy);
 
-  s = gst_structure_new_id_empty_with_size (name_quark, len);
+  gst_id_str_set_static_str (&name, g_quark_to_string (name_quark));
+  s = gst_structure_new_take_id_str_empty_with_size (&name, len);
 
   gst_structure_id_set_valist_internal (s, field_quark, varargs);
   va_end (varargs);
@@ -995,80 +1545,145 @@ gst_structure_new_id (GQuark name_quark, GQuark field_quark, ...)
   return s;
 }
 
+/**
+ * gst_structure_new_id_str:
+ * @name: name of new structure
+ * @fieldname: the GstIdStr for the name of the field to set
+ * @...: variable arguments
+ *
+ * Creates a new #GstStructure with the given name as a GQuark, followed by
+ * fieldname GstIdStr, GType, argument(s) "triplets" in the same format as
+ * gst_structure_id_str_set(). Basically a convenience wrapper around
+ * gst_structure_new_id_str_empty() and gst_structure_id_str_set().
+ *
+ * The last variable argument must be %NULL (or 0).
+ *
+ * Free-function: gst_structure_free
+ *
+ * Returns: (transfer full): a new #GstStructure
+ *
+ * Since: 1.26
+ */
+GstStructure *
+gst_structure_new_id_str (const GstIdStr * name, const GstIdStr * fieldname,
+    ...)
+{
+  GstStructure *s;
+  va_list varargs;
+  va_list copy;
+  guint len = 0;
+  const GstIdStr *fieldname_copy = fieldname;
+  GType type_copy;
+
+  g_return_val_if_fail (name != 0, NULL);
+  g_return_val_if_fail (gst_structure_validate_name (gst_id_str_as_str (name)),
+      NULL);
+  g_return_val_if_fail (fieldname != NULL, NULL);
+
+  va_start (varargs, fieldname);
+
+  /* Calculate size of varargs */
+  va_copy (copy, varargs);
+  while (fieldname_copy) {
+    type_copy = va_arg (copy, GType);
+    G_VALUE_COLLECT_SKIP (type_copy, copy);
+    fieldname_copy = va_arg (copy, const GstIdStr *);
+    len++;
+  }
+  va_end (copy);
+
+  s = gst_structure_new_id_str_empty_with_size (name, len);
+
+  gst_structure_id_str_set_valist_internal (s, fieldname, varargs);
+  va_end (varargs);
+
+  return s;
+}
+
 #if GST_VERSION_NANO == 1
 #define GIT_G_WARNING g_warning
 #else
 #define GIT_G_WARNING GST_WARNING
 #endif
 
-/* If the structure currently contains a field with the same name, it is
- * replaced with the provided field. Otherwise, the field is added to the
- * structure. The field's value is not deeply copied.
- */
-static void
-gst_structure_set_field (GstStructure * structure, GstStructureField * field)
+static gboolean
+gst_structure_validate_field_value (const GstStructure * structure,
+    const gchar * field_name, const GValue * value)
 {
-  GstStructureField *f;
   GType field_value_type;
-  guint i, len;
+  gboolean is_tag_list;
 
-  len = GST_STRUCTURE_LEN (structure);
+  is_tag_list = IS_TAGLIST (structure);
 
-  field_value_type = G_VALUE_TYPE (&field->value);
+  field_value_type = G_VALUE_TYPE (value);
   if (field_value_type == G_TYPE_STRING) {
     const gchar *s;
 
-    s = g_value_get_string (&field->value);
+    s = g_value_get_string (value);
     /* only check for NULL strings in taglists, as they are allowed in message
      * structs, e.g. error message debug strings */
-    if (G_UNLIKELY (IS_TAGLIST (structure) && (s == NULL || *s == '\0'))) {
+    if (G_UNLIKELY (is_tag_list && (s == NULL || *s == '\0'))) {
       if (s == NULL) {
         GIT_G_WARNING ("Trying to set NULL string on field '%s' on taglist. "
-            "Please file a bug.", g_quark_to_string (field->name));
-        g_value_unset (&field->value);
-        return;
+            "Please file a bug.", field_name);
+        return FALSE;
       } else {
         /* empty strings never make sense */
         GIT_G_WARNING ("Trying to set empty string on taglist field '%s'. "
-            "Please file a bug.", g_quark_to_string (field->name));
-        g_value_unset (&field->value);
-        return;
+            "Please file a bug.", field_name);
+        return FALSE;
       }
     } else if (G_UNLIKELY (s != NULL && !g_utf8_validate (s, -1, NULL))) {
       g_warning ("Trying to set string on %s field '%s', but string is not "
           "valid UTF-8. Please file a bug.",
-          IS_TAGLIST (structure) ? "taglist" : "structure",
-          g_quark_to_string (field->name));
-      g_value_unset (&field->value);
-      return;
+          is_tag_list ? "taglist" : "structure", field_name);
+      return FALSE;
     }
   } else if (G_UNLIKELY (field_value_type == G_TYPE_DATE)) {
     const GDate *d;
 
-    d = g_value_get_boxed (&field->value);
+    d = g_value_get_boxed (value);
     /* only check for NULL GDates in taglists, as they might make sense
      * in other, generic structs */
-    if (G_UNLIKELY ((IS_TAGLIST (structure) && d == NULL))) {
+    if (G_UNLIKELY ((is_tag_list && d == NULL))) {
       GIT_G_WARNING ("Trying to set NULL GDate on field '%s' on taglist. "
-          "Please file a bug.", g_quark_to_string (field->name));
-      g_value_unset (&field->value);
-      return;
+          "Please file a bug.", field_name);
+      return FALSE;
     } else if (G_UNLIKELY (d != NULL && !g_date_valid (d))) {
       g_warning
           ("Trying to set invalid GDate on %s field '%s'. Please file a bug.",
-          IS_TAGLIST (structure) ? "taglist" : "structure",
-          g_quark_to_string (field->name));
-      g_value_unset (&field->value);
-      return;
+          is_tag_list ? "taglist" : "structure", field_name);
+      return FALSE;
     }
   }
 
+  return TRUE;
+}
+
+/* If the structure currently contains a field with the same name, it is
+ * replaced with the provided field. Otherwise, the field is added to the
+ * structure. The field's value is not deeply copied.
+ */
+static void
+gst_structure_set_field (GstStructure * structure, GstStructureField * field)
+{
+  GstStructureField *f;
+  guint i, len;
+
+  if (!gst_structure_validate_field_value (structure,
+          gst_id_str_as_str (&field->name), &field->value)) {
+    g_value_unset (&field->value);
+    return;
+  }
+
+  len = GST_STRUCTURE_LEN (structure);
   for (i = 0; i < len; i++) {
     f = GST_STRUCTURE_FIELD (structure, i);
 
-    if (G_UNLIKELY (f->name == field->name)) {
+    if (G_UNLIKELY (gst_id_str_is_equal (&f->name, &field->name))) {
       g_value_unset (&f->value);
-      memcpy (f, field, sizeof (GstStructureField));
+      f->value = field->value;
+      gst_id_str_clear (&field->name);
       return;
     }
   }
@@ -1079,7 +1694,8 @@ gst_structure_set_field (GstStructure * structure, GstStructureField * field)
 /* If there is no field with the given ID, NULL is returned.
  */
 static GstStructureField *
-gst_structure_id_get_field (const GstStructure * structure, GQuark field_id)
+gst_structure_id_str_get_field (const GstStructure * structure,
+    const GstIdStr * fieldname)
 {
   GstStructureField *field;
   guint i, len;
@@ -1089,7 +1705,7 @@ gst_structure_id_get_field (const GstStructure * structure, GQuark field_id)
   for (i = 0; i < len; i++) {
     field = GST_STRUCTURE_FIELD (structure, i);
 
-    if (G_UNLIKELY (field->name == field_id))
+    if (G_UNLIKELY (gst_id_str_is_equal (&field->name, fieldname)))
       return field;
   }
 
@@ -1102,11 +1718,18 @@ static GstStructureField *
 gst_structure_get_field (const GstStructure * structure,
     const gchar * fieldname)
 {
+  GstIdStr s = GST_ID_STR_INIT;
+  GstStructureField *res;
+
   g_return_val_if_fail (structure != NULL, NULL);
   g_return_val_if_fail (fieldname != NULL, NULL);
 
-  return gst_structure_id_get_field (structure,
-      g_quark_from_string (fieldname));
+  // Not technically correct but the string is never leaving this scope and is never copied
+  gst_id_str_set_static_str (&s, fieldname);
+  res = gst_structure_id_str_get_field (structure, &s);
+  gst_id_str_clear (&s);
+
+  return res;
 }
 
 /**
@@ -1135,6 +1758,34 @@ gst_structure_get_value (const GstStructure * structure,
   return &field->value;
 }
 
+/**
+ * gst_structure_id_str_get_value:
+ * @structure: a #GstStructure
+ * @fieldname: the name of the field to get
+ *
+ * Get the value of the field with name @fieldname.
+ *
+ * Returns: (nullable): the #GValue corresponding to the field with the given
+ * name.
+ *
+ * Since: 1.26
+ */
+const GValue *
+gst_structure_id_str_get_value (const GstStructure * structure,
+    const GstIdStr * fieldname)
+{
+  GstStructureField *field;
+
+  g_return_val_if_fail (structure != NULL, NULL);
+  g_return_val_if_fail (fieldname != NULL, NULL);
+
+  field = gst_structure_id_str_get_field (structure, fieldname);
+  if (field == NULL)
+    return NULL;
+
+  return &field->value;
+}
+
 /**
  * gst_structure_id_get_value:
  * @structure: a #GstStructure
@@ -1149,10 +1800,12 @@ const GValue *
 gst_structure_id_get_value (const GstStructure * structure, GQuark field)
 {
   GstStructureField *gsfield;
+  GstIdStr s = GST_ID_STR_INIT;
 
   g_return_val_if_fail (structure != NULL, NULL);
 
-  gsfield = gst_structure_id_get_field (structure, field);
+  gst_id_str_set_static_str (&s, g_quark_to_string (field));
+  gsfield = gst_structure_id_str_get_field (structure, &s);
   if (gsfield == NULL)
     return NULL;
 
@@ -1170,28 +1823,31 @@ gst_structure_id_get_value (const GstStructure * structure, GQuark field)
 void
 gst_structure_remove_field (GstStructure * structure, const gchar * fieldname)
 {
+  GstIdStr s = GST_ID_STR_INIT;
   GstStructureField *field;
-  GQuark id;
   guint i, len;
 
   g_return_if_fail (structure != NULL);
   g_return_if_fail (fieldname != NULL);
   g_return_if_fail (IS_MUTABLE (structure));
 
-  id = g_quark_from_string (fieldname);
+  // Not technically correct but the string is never leaving this scope and is never copied
+  gst_id_str_set_static_str (&s, fieldname);
   len = GST_STRUCTURE_LEN (structure);
-
   for (i = 0; i < len; i++) {
     field = GST_STRUCTURE_FIELD (structure, i);
 
-    if (field->name == id) {
+    if (gst_id_str_is_equal (&field->name, &s)) {
       if (G_IS_VALUE (&field->value)) {
         g_value_unset (&field->value);
       }
+      gst_id_str_clear (&field->name);
+      gst_id_str_clear (&s);
       _structure_remove_index (structure, i);
       return;
     }
   }
+  gst_id_str_clear (&s);
 }
 
 /**
@@ -1242,6 +1898,94 @@ gst_structure_remove_fields_valist (GstStructure * structure,
   }
 }
 
+/**
+ * gst_structure_id_str_remove_field:
+ * @structure: a #GstStructure
+ * @fieldname: the name of the field to remove
+ *
+ * Removes the field with the given name.  If the field with the given
+ * name does not exist, the structure is unchanged.
+ *
+ * Since: 1.26
+ */
+void
+gst_structure_id_str_remove_field (GstStructure * structure,
+    const GstIdStr * fieldname)
+{
+  GstStructureField *field;
+  guint i, len;
+
+  g_return_if_fail (structure != NULL);
+  g_return_if_fail (fieldname != NULL);
+  g_return_if_fail (IS_MUTABLE (structure));
+
+  len = GST_STRUCTURE_LEN (structure);
+  for (i = 0; i < len; i++) {
+    field = GST_STRUCTURE_FIELD (structure, i);
+
+    if (gst_id_str_is_equal (&field->name, fieldname)) {
+      if (G_IS_VALUE (&field->value)) {
+        g_value_unset (&field->value);
+      }
+      gst_id_str_clear (&field->name);
+      _structure_remove_index (structure, i);
+      return;
+    }
+  }
+}
+
+/**
+ * gst_structure_id_str_remove_fields:
+ * @structure: a #GstStructure
+ * @fieldname: the name of the field to remove
+ * @...: %NULL-terminated list of more fieldnames to remove
+ *
+ * Removes the fields with the given names. If a field does not exist, the
+ * argument is ignored.
+ *
+ * Since: 1.26
+ */
+void
+gst_structure_id_str_remove_fields (GstStructure * structure,
+    const GstIdStr * fieldname, ...)
+{
+  va_list varargs;
+
+  g_return_if_fail (structure != NULL);
+  g_return_if_fail (fieldname != NULL);
+  /* mutability checked in remove_field */
+
+  va_start (varargs, fieldname);
+  gst_structure_id_str_remove_fields_valist (structure, fieldname, varargs);
+  va_end (varargs);
+}
+
+/**
+ * gst_structure_id_str_remove_fields_valist:
+ * @structure: a #GstStructure
+ * @fieldname: the name of the field to remove
+ * @varargs: %NULL-terminated list of more fieldnames to remove
+ *
+ * va_list form of gst_structure_id_str_remove_fields().
+ *
+ * Since: 1.26
+ */
+void
+gst_structure_id_str_remove_fields_valist (GstStructure * structure,
+    const GstIdStr * fieldname, va_list varargs)
+{
+  const GstIdStr *field = fieldname;
+
+  g_return_if_fail (structure != NULL);
+  g_return_if_fail (fieldname != NULL);
+  /* mutability checked in remove_field */
+
+  while (field) {
+    gst_structure_id_str_remove_field (structure, field);
+    field = va_arg (varargs, const GstIdStr *);
+  }
+}
+
 /**
  * gst_structure_remove_all_fields:
  * @structure: a #GstStructure
@@ -1260,15 +2004,43 @@ gst_structure_remove_all_fields (GstStructure * structure)
   for (i = GST_STRUCTURE_LEN (structure) - 1; i >= 0; i--) {
     field = GST_STRUCTURE_FIELD (structure, i);
 
-    if (G_IS_VALUE (&field->value)) {
-      g_value_unset (&field->value);
-    }
-    _structure_remove_index (structure, i);
-  }
+    if (G_IS_VALUE (&field->value)) {
+      g_value_unset (&field->value);
+    }
+    gst_id_str_clear (&field->name);
+    _structure_remove_index (structure, i);
+  }
+}
+
+/**
+ * gst_structure_get_field_type:
+ * @structure: a #GstStructure
+ * @fieldname: the name of the field
+ *
+ * Finds the field with the given name, and returns the type of the
+ * value it contains.  If the field is not found, G_TYPE_INVALID is
+ * returned.
+ *
+ * Returns: the #GValue of the field
+ */
+GType
+gst_structure_get_field_type (const GstStructure * structure,
+    const gchar * fieldname)
+{
+  GstStructureField *field;
+
+  g_return_val_if_fail (structure != NULL, G_TYPE_INVALID);
+  g_return_val_if_fail (fieldname != NULL, G_TYPE_INVALID);
+
+  field = gst_structure_get_field (structure, fieldname);
+  if (field == NULL)
+    return G_TYPE_INVALID;
+
+  return G_VALUE_TYPE (&field->value);
 }
 
 /**
- * gst_structure_get_field_type:
+ * gst_structure_id_str_get_field_type:
  * @structure: a #GstStructure
  * @fieldname: the name of the field
  *
@@ -1277,17 +2049,19 @@ gst_structure_remove_all_fields (GstStructure * structure)
  * returned.
  *
  * Returns: the #GValue of the field
+ *
+ * Since: 1.26
  */
 GType
-gst_structure_get_field_type (const GstStructure * structure,
-    const gchar * fieldname)
+gst_structure_id_str_get_field_type (const GstStructure * structure,
+    const GstIdStr * fieldname)
 {
   GstStructureField *field;
 
   g_return_val_if_fail (structure != NULL, G_TYPE_INVALID);
   g_return_val_if_fail (fieldname != NULL, G_TYPE_INVALID);
 
-  field = gst_structure_get_field (structure, fieldname);
+  field = gst_structure_id_str_get_field (structure, fieldname);
   if (field == NULL)
     return G_TYPE_INVALID;
 
@@ -1329,14 +2103,56 @@ gst_structure_nth_field_name (const GstStructure * structure, guint index)
 
   field = GST_STRUCTURE_FIELD (structure, index);
 
-  return g_quark_to_string (field->name);
+  return gst_id_str_as_str (&field->name);
+}
+
+/**
+ * gst_structure_id_str_nth_field_name:
+ * @structure: a #GstStructure
+ * @index: the index to get the name of
+ *
+ * Get the name (as a GstIdStr) of the given field number,
+ * counting from 0 onwards.
+ *
+ * Returns: the name of the given field number
+ *
+ * Since: 1.26
+ */
+const GstIdStr *
+gst_structure_id_str_nth_field_name (const GstStructure * structure,
+    guint index)
+{
+  GstStructureField *field;
+
+  g_return_val_if_fail (structure != NULL, NULL);
+  g_return_val_if_fail (index < GST_STRUCTURE_LEN (structure), NULL);
+
+  field = GST_STRUCTURE_FIELD (structure, index);
+
+  return &field->name;
+}
+
+typedef struct
+{
+  GstStructureForeachFunc func;
+  gpointer user_data;
+} ForeachAdapterData;
+
+static gboolean
+foreach_quark_adapter (const GstIdStr * fieldname, const GValue * value,
+    gpointer user_data)
+{
+  ForeachAdapterData *data = user_data;
+
+  return data->func (g_quark_from_string (gst_id_str_as_str (fieldname)), value,
+      data->user_data);
 }
 
 /**
  * gst_structure_foreach:
  * @structure: a #GstStructure
- * @func: (scope call): a function to call for each field
- * @user_data: (closure): private data
+ * @func: (scope call) (closure user_data): a function to call for each field
+ * @user_data: private data
  *
  * Calls the provided function once for each field in the #GstStructure. The
  * function must not modify the fields. Also see gst_structure_map_in_place()
@@ -1344,10 +2160,119 @@ gst_structure_nth_field_name (const GstStructure * structure, guint index)
  *
  * Returns: %TRUE if the supplied function returns %TRUE For each of the fields,
  * %FALSE otherwise.
+ *
+ * Deprecated: 1.26: Use gst_structure_foreach_id_str().
  */
 gboolean
 gst_structure_foreach (const GstStructure * structure,
     GstStructureForeachFunc func, gpointer user_data)
+{
+  ForeachAdapterData data = { func, user_data };
+
+  return gst_structure_foreach_id_str (structure, foreach_quark_adapter, &data);
+}
+
+typedef struct
+{
+  GstStructureMapFunc func;
+  gpointer user_data;
+} MapInPlaceAdapterData;
+
+static gboolean
+map_in_place_quark_adapter (const GstIdStr * fieldname, GValue * value,
+    gpointer user_data)
+{
+  MapInPlaceAdapterData *data = user_data;
+
+  return data->func (g_quark_from_string (gst_id_str_as_str (fieldname)), value,
+      data->user_data);
+}
+
+/**
+ * gst_structure_map_in_place:
+ * @structure: a #GstStructure
+ * @func: (scope call) (closure user_data): a function to call for each field
+ * @user_data: private data
+ *
+ * Calls the provided function once for each field in the #GstStructure. In
+ * contrast to gst_structure_foreach(), the function may modify but not delete the
+ * fields. The structure must be mutable.
+ *
+ * Returns: %TRUE if the supplied function returns %TRUE For each of the fields,
+ * %FALSE otherwise.
+ *
+ * Deprecated: 1.26: Use gst_structure_map_in_place_id_str().
+ */
+gboolean
+gst_structure_map_in_place (GstStructure * structure,
+    GstStructureMapFunc func, gpointer user_data)
+{
+  MapInPlaceAdapterData data = { func, user_data };
+
+  return gst_structure_map_in_place_id_str (structure,
+      map_in_place_quark_adapter, &data);
+}
+
+typedef struct
+{
+  GstStructureFilterMapFunc func;
+  gpointer user_data;
+} FilterAndMapInPlaceAdapterData;
+
+static gboolean
+filter_and_map_in_place_quark_adapter (const GstIdStr * fieldname,
+    GValue * value, gpointer user_data)
+{
+  FilterAndMapInPlaceAdapterData *data = user_data;
+
+  return data->func (g_quark_from_string (gst_id_str_as_str (fieldname)), value,
+      data->user_data);
+}
+
+/**
+ * gst_structure_filter_and_map_in_place:
+ * @structure: a #GstStructure
+ * @func: (scope call) (closure user_data): a function to call for each field
+ * @user_data: private data
+ *
+ * Calls the provided function once for each field in the #GstStructure. In
+ * contrast to gst_structure_foreach(), the function may modify the fields.
+ * In contrast to gst_structure_map_in_place(), the field is removed from
+ * the structure if %FALSE is returned from the function.
+ * The structure must be mutable.
+ *
+ * Since: 1.6
+ *
+ * Deprecated: 1.26: Use gst_structure_filter_and_map_in_place_id_str().
+ */
+void
+gst_structure_filter_and_map_in_place (GstStructure * structure,
+    GstStructureFilterMapFunc func, gpointer user_data)
+{
+  FilterAndMapInPlaceAdapterData data = { func, user_data };
+
+  gst_structure_filter_and_map_in_place_id_str (structure,
+      filter_and_map_in_place_quark_adapter, &data);
+}
+
+/**
+ * gst_structure_foreach_id_str:
+ * @structure: a #GstStructure
+ * @func: (scope call) (closure user_data): a function to call for each field
+ * @user_data: private data
+ *
+ * Calls the provided function once for each field in the #GstStructure. The
+ * function must not modify the fields. Also see gst_structure_map_in_place_id_str()
+ * and gst_structure_filter_and_map_in_place_id_str().
+ *
+ * Returns: %TRUE if the supplied function returns %TRUE For each of the fields,
+ * %FALSE otherwise.
+ *
+ * Since: 1.26
+ */
+gboolean
+gst_structure_foreach_id_str (const GstStructure * structure,
+    GstStructureForeachIdStrFunc func, gpointer user_data)
 {
   guint i, len;
   GstStructureField *field;
@@ -1361,7 +2286,7 @@ gst_structure_foreach (const GstStructure * structure,
   for (i = 0; i < len; i++) {
     field = GST_STRUCTURE_FIELD (structure, i);
 
-    ret = func (field->name, &field->value, user_data);
+    ret = func (&field->name, &field->value, user_data);
     if (G_UNLIKELY (!ret))
       return FALSE;
   }
@@ -1370,21 +2295,23 @@ gst_structure_foreach (const GstStructure * structure,
 }
 
 /**
- * gst_structure_map_in_place:
+ * gst_structure_map_in_place_id_str:
  * @structure: a #GstStructure
- * @func: (scope call): a function to call for each field
- * @user_data: (closure): private data
+ * @func: (scope call) (closure user_data): a function to call for each field
+ * @user_data: private data
  *
  * Calls the provided function once for each field in the #GstStructure. In
- * contrast to gst_structure_foreach(), the function may modify but not delete the
+ * contrast to gst_structure_foreach_id_str(), the function may modify but not delete the
  * fields. The structure must be mutable.
  *
  * Returns: %TRUE if the supplied function returns %TRUE For each of the fields,
  * %FALSE otherwise.
+ *
+ * Since: 1.26
  */
 gboolean
-gst_structure_map_in_place (GstStructure * structure,
-    GstStructureMapFunc func, gpointer user_data)
+gst_structure_map_in_place_id_str (GstStructure * structure,
+    GstStructureMapIdStrFunc func, gpointer user_data)
 {
   guint i, len;
   GstStructureField *field;
@@ -1398,7 +2325,7 @@ gst_structure_map_in_place (GstStructure * structure,
   for (i = 0; i < len; i++) {
     field = GST_STRUCTURE_FIELD (structure, i);
 
-    ret = func (field->name, &field->value, user_data);
+    ret = func (&field->name, &field->value, user_data);
     if (!ret)
       return FALSE;
   }
@@ -1407,22 +2334,22 @@ gst_structure_map_in_place (GstStructure * structure,
 }
 
 /**
- * gst_structure_filter_and_map_in_place:
+ * gst_structure_filter_and_map_in_place_id_str:
  * @structure: a #GstStructure
- * @func: (scope call): a function to call for each field
- * @user_data: (closure): private data
+ * @func: (scope call) (closure user_data): a function to call for each field
+ * @user_data: private data
  *
  * Calls the provided function once for each field in the #GstStructure. In
- * contrast to gst_structure_foreach(), the function may modify the fields.
- * In contrast to gst_structure_map_in_place(), the field is removed from
+ * contrast to gst_structure_foreach_id_str(), the function may modify the fields.
+ * In contrast to gst_structure_map_in_place_id_str(), the field is removed from
  * the structure if %FALSE is returned from the function.
  * The structure must be mutable.
  *
- * Since: 1.6
+ * Since: 1.26
  */
 void
-gst_structure_filter_and_map_in_place (GstStructure * structure,
-    GstStructureFilterMapFunc func, gpointer user_data)
+gst_structure_filter_and_map_in_place_id_str (GstStructure * structure,
+    GstStructureFilterMapIdStrFunc func, gpointer user_data)
 {
   guint i, len;
   GstStructureField *field;
@@ -1436,12 +2363,13 @@ gst_structure_filter_and_map_in_place (GstStructure * structure,
   for (i = 0; i < len;) {
     field = GST_STRUCTURE_FIELD (structure, i);
 
-    ret = func (field->name, &field->value, user_data);
+    ret = func (&field->name, &field->value, user_data);
 
     if (!ret) {
       if (G_IS_VALUE (&field->value)) {
         g_value_unset (&field->value);
       }
+      gst_id_str_clear (&field->name);
       _structure_remove_index (structure, i);
       len = GST_STRUCTURE_LEN (structure);
     } else {
@@ -1458,16 +2386,43 @@ gst_structure_filter_and_map_in_place (GstStructure * structure,
  * Check if @structure contains a field named @field.
  *
  * Returns: %TRUE if the structure contains a field with the given name
+ *
+ * Deprecated: 1.26: Use gst_structure_id_str_has_field().
  */
 gboolean
 gst_structure_id_has_field (const GstStructure * structure, GQuark field)
 {
-  GstStructureField *f;
+  GstIdStr s = GST_ID_STR_INIT;
 
   g_return_val_if_fail (structure != NULL, FALSE);
   g_return_val_if_fail (field != 0, FALSE);
 
-  f = gst_structure_id_get_field (structure, field);
+  gst_id_str_set_static_str (&s, g_quark_to_string (field));
+
+  return gst_structure_id_str_has_field (structure, &s);
+}
+
+/**
+ * gst_structure_id_str_has_field:
+ * @structure: a #GstStructure
+ * @fieldname: the name of a field
+ *
+ * Check if @structure contains a field named @fieldname.
+ *
+ * Returns: %TRUE if the structure contains a field with the given name
+ *
+ * Since: 1.26
+ */
+gboolean
+gst_structure_id_str_has_field (const GstStructure * structure,
+    const GstIdStr * fieldname)
+{
+  GstStructureField *f;
+
+  g_return_val_if_fail (structure != NULL, FALSE);
+  g_return_val_if_fail (fieldname != NULL, FALSE);
+
+  f = gst_structure_id_str_get_field (structure, fieldname);
 
   return (f != NULL);
 }
@@ -1485,11 +2440,18 @@ gboolean
 gst_structure_has_field (const GstStructure * structure,
     const gchar * fieldname)
 {
+  GstIdStr s = GST_ID_STR_INIT;
+  gboolean res;
+
   g_return_val_if_fail (structure != NULL, FALSE);
   g_return_val_if_fail (fieldname != NULL, FALSE);
 
-  return gst_structure_id_has_field (structure,
-      g_quark_from_string (fieldname));
+  // Not technically correct but the string is never leaving this scope and is never copied
+  gst_id_str_set_static_str (&s, fieldname);
+  res = gst_structure_id_str_has_field (structure, &s);
+  gst_id_str_clear (&s);
+
+  return res;
 }
 
 /**
@@ -1501,17 +2463,45 @@ gst_structure_has_field (const GstStructure * structure,
  * Check if @structure contains a field named @field and with GType @type.
  *
  * Returns: %TRUE if the structure contains a field with the given name and type
+ *
+ * Deprecated: 1.26: Use gst_structure_id_str_has_field_typed().
  */
 gboolean
 gst_structure_id_has_field_typed (const GstStructure * structure,
     GQuark field, GType type)
 {
-  GstStructureField *f;
+  GstIdStr s = GST_ID_STR_INIT;
 
   g_return_val_if_fail (structure != NULL, FALSE);
   g_return_val_if_fail (field != 0, FALSE);
 
-  f = gst_structure_id_get_field (structure, field);
+  gst_id_str_set_static_str (&s, g_quark_to_string (field));
+
+  return gst_structure_id_str_has_field_typed (structure, &s, type);
+}
+
+/**
+ * gst_structure_id_str_has_field_typed:
+ * @structure: a #GstStructure
+ * @fieldname: the name of a field
+ * @type: the type of a value
+ *
+ * Check if @structure contains a field named @fieldname and with GType @type.
+ *
+ * Returns: %TRUE if the structure contains a field with the given name and type
+ *
+ * Since: 1.26
+ */
+gboolean
+gst_structure_id_str_has_field_typed (const GstStructure * structure,
+    const GstIdStr * fieldname, GType type)
+{
+  GstStructureField *f;
+
+  g_return_val_if_fail (structure != NULL, FALSE);
+  g_return_val_if_fail (fieldname != NULL, FALSE);
+
+  f = gst_structure_id_str_get_field (structure, fieldname);
   if (f == NULL)
     return FALSE;
 
@@ -1532,11 +2522,18 @@ gboolean
 gst_structure_has_field_typed (const GstStructure * structure,
     const gchar * fieldname, GType type)
 {
+  GstIdStr s = GST_ID_STR_INIT;
+  gboolean res;
+
   g_return_val_if_fail (structure != NULL, FALSE);
   g_return_val_if_fail (fieldname != NULL, FALSE);
 
-  return gst_structure_id_has_field_typed (structure,
-      g_quark_from_string (fieldname), type);
+  // Not technically correct but the string is never leaving this scope and is never copied
+  gst_id_str_set_static_str (&s, fieldname);
+  res = gst_structure_id_str_has_field_typed (structure, &s, type);
+  gst_id_str_clear (&s);
+
+  return res;
 }
 
 /* utility functions */
@@ -2060,7 +3057,7 @@ priv_gst_structure_append_to_gstring (const GstStructure * structure,
 
     g_string_append_len (s, ", ", 2);
     /* FIXME: do we need to escape fieldnames? */
-    g_string_append (s, g_quark_to_string (field->name));
+    g_string_append (s, gst_id_str_as_str (&field->name));
     g_string_append_len (s, "=(", 2);
     g_string_append (s, _priv_gst_value_gtype_to_abbr (type));
     g_string_append_c (s, ')');
@@ -2069,7 +3066,7 @@ priv_gst_structure_append_to_gstring (const GstStructure * structure,
       const GstStructure *substruct = gst_value_get_structure (&field->value);
 
       g_string_append_c (s, '[');
-      g_string_append (s, g_quark_to_string (substruct->name));
+      g_string_append (s, gst_structure_get_name (substruct));
       if (!priv_gst_structure_append_to_gstring (substruct, s, flags))
         return FALSE;
       g_string_append_c (s, ']');
@@ -2094,10 +3091,14 @@ priv_gst_structure_append_to_gstring (const GstStructure * structure,
         g_string_append (s, "NULL");
       else
         g_string_append_printf (s, "%p", ptr);
+    } else if (G_TYPE_CHECK_VALUE_TYPE (&field->value, G_TYPE_ARRAY)) {
+      GArray *arr = g_value_get_boxed (&field->value);
+      g_string_append_printf (s, "[%d %s]", arr->len,
+          arr->len == 1 ? "entry" : "entries");
     } else {
       if (!G_TYPE_CHECK_VALUE_TYPE (&field->value, G_TYPE_STRING))
         GST_WARNING ("No value transform to serialize field '%s' of type '%s'",
-            g_quark_to_string (field->name),
+            gst_id_str_as_str (&field->name),
             _priv_gst_value_gtype_to_abbr (type));
       if (strict)
         return FALSE;
@@ -2111,7 +3112,7 @@ priv_gst_structure_append_to_gstring (const GstStructure * structure,
 }
 
 gboolean
-priv__gst_structure_append_template_to_gstring (GQuark field_id,
+priv__gst_structure_append_template_to_gstring (const gchar * field,
     const GValue * value, gpointer user_data)
 {
   GType type = gst_structure_value_get_generic_type (value);
@@ -2119,7 +3120,7 @@ priv__gst_structure_append_template_to_gstring (GQuark field_id,
 
   g_string_append_len (s, ", ", 2);
   /* FIXME: do we need to escape fieldnames? */
-  g_string_append (s, g_quark_to_string (field_id));
+  g_string_append (s, field);
   g_string_append_len (s, "=(", 2);
   g_string_append (s, _priv_gst_value_gtype_to_abbr (type));
   g_string_append_c (s, ')');
@@ -2175,7 +3176,7 @@ structure_serialize (const GstStructure * structure, GstSerializeFlags flags)
   /* we estimate a minimum size based on the number of fields in order to
    * avoid unnecessary reallocs within GString */
   s = g_string_sized_new (STRUCTURE_ESTIMATED_STRING_LEN (structure));
-  g_string_append (s, g_quark_to_string (structure->name));
+  g_string_append (s, gst_structure_get_name (structure));
   if (!priv_gst_structure_append_to_gstring (structure, s, flags)) {
     g_string_free (s, TRUE);
     return NULL;
@@ -2293,7 +3294,7 @@ gst_structure_parse_field (gchar * str,
 
   c = *name_end;
   *name_end = '\0';
-  field->name = g_quark_from_string (name);
+  gst_id_str_set (&field->name, name);
   GST_DEBUG ("trying field name '%s'", name);
   *name_end = c;
 
@@ -2841,13 +3842,17 @@ gst_structure_fixate_field_nearest_fraction (GstStructure * structure,
 }
 
 static gboolean
-default_fixate (GQuark field_id, const GValue * value, gpointer data)
+default_fixate (const GstIdStr * fieldname, GValue * value, gpointer data)
 {
   GstStructure *s = data;
   GValue v = { 0 };
 
   if (gst_value_fixate (&v, value)) {
-    gst_structure_id_take_value (s, field_id, &v);
+    if (gst_structure_validate_field_value (s, gst_id_str_as_str (fieldname),
+            value)) {
+      g_value_unset (value);
+      *value = v;
+    }
   }
   return TRUE;
 }
@@ -2872,7 +3877,7 @@ gst_structure_fixate_field (GstStructure * structure, const char *field_name)
   if (!(field = gst_structure_get_field (structure, field_name)))
     return FALSE;
 
-  return default_fixate (field->name, &field->value, structure);
+  return default_fixate (&field->name, &field->value, structure);
 }
 
 /* our very own version of G_VALUE_LCOPY that allows NULL return locations
@@ -2968,6 +3973,76 @@ wrong_type:
   }
 }
 
+/**
+ * gst_structure_id_str_get_valist:
+ * @structure: a #GstStructure
+ * @first_fieldname: the name of the first field to read
+ * @args: variable arguments
+ *
+ * Parses the variable arguments and reads fields from @structure accordingly.
+ * valist-variant of gst_structure_id_str_get(). Look at the documentation of
+ * gst_structure_id_str_get() for more details.
+ *
+ * Returns: %TRUE, or %FALSE if there was a problem reading any of the fields
+ *
+ * Since: 1.26
+ */
+gboolean
+gst_structure_id_str_get_valist (const GstStructure * structure,
+    const GstIdStr * first_fieldname, va_list args)
+{
+  const GstIdStr *fieldname;
+  GType expected_type = G_TYPE_INVALID;
+
+  g_return_val_if_fail (GST_IS_STRUCTURE (structure), FALSE);
+  g_return_val_if_fail (first_fieldname != NULL, FALSE);
+
+  fieldname = first_fieldname;
+  while (fieldname) {
+    const GValue *val = NULL;
+    gchar *err = NULL;
+
+    expected_type = va_arg (args, GType);
+
+    val = gst_structure_id_str_get_value (structure, fieldname);
+
+    if (val == NULL)
+      goto no_such_field;
+
+    if (G_VALUE_TYPE (val) != expected_type)
+      goto wrong_type;
+
+    GST_VALUE_LCOPY (val, args, 0, &err, gst_id_str_as_str (fieldname));
+    if (err) {
+      g_warning ("%s: %s", G_STRFUNC, err);
+      g_free (err);
+      return FALSE;
+    }
+
+    fieldname = va_arg (args, const GstIdStr *);
+  }
+
+  return TRUE;
+
+/* ERRORS */
+no_such_field:
+  {
+    GST_INFO ("Expected field '%s' in structure: %" GST_PTR_FORMAT,
+        gst_id_str_as_str (fieldname), structure);
+    return FALSE;
+  }
+wrong_type:
+  {
+    GST_INFO ("Expected field '%s' in structure to be of type '%s', but "
+        "field was of type '%s': %" GST_PTR_FORMAT,
+        gst_id_str_as_str (fieldname),
+        GST_STR_NULL (g_type_name (expected_type)),
+        G_VALUE_TYPE_NAME (gst_structure_id_str_get_value (structure,
+                fieldname)), structure);
+    return FALSE;
+  }
+}
+
 /**
  * gst_structure_id_get_valist:
  * @structure: a #GstStructure
@@ -2979,6 +4054,8 @@ wrong_type:
  * gst_structure_id_get() for more details.
  *
  * Returns: %TRUE, or %FALSE if there was a problem reading any of the fields
+ *
+ * Deprecated: 1.26: Use gst_structure_id_str_get_valist().
  */
 gboolean
 gst_structure_id_get_valist (const GstStructure * structure,
@@ -2997,7 +4074,9 @@ gst_structure_id_get_valist (const GstStructure * structure,
 
     expected_type = va_arg (args, GType);
 
+    G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
     val = gst_structure_id_get_value (structure, field_id);
+    G_GNUC_END_IGNORE_DEPRECATIONS;
 
     if (val == NULL)
       goto no_such_field;
@@ -3026,12 +4105,14 @@ no_such_field:
   }
 wrong_type:
   {
+    G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
     GST_DEBUG ("Expected field '%s' in structure to be of type '%s', but "
         "field was of type '%s': %" GST_PTR_FORMAT,
         g_quark_to_string (field_id),
         GST_STR_NULL (g_type_name (expected_type)),
         G_VALUE_TYPE_NAME (gst_structure_id_get_value (structure, field_id)),
         structure);
+    G_GNUC_END_IGNORE_DEPRECATIONS;
     return FALSE;
   }
 }
@@ -3073,6 +4154,45 @@ gst_structure_get (const GstStructure * structure, const char *first_fieldname,
   return ret;
 }
 
+/**
+ * gst_structure_id_str_get:
+ * @structure: a #GstStructure
+ * @first_fieldname: the name of the first field to read
+ * @...: variable arguments
+ *
+ * Parses the variable arguments and reads fields from @structure accordingly.
+ * Variable arguments should be in the form field name (as GstIdStr), field type
+ * (as a GType), pointer(s) to a variable(s) to hold the return value(s). The
+ * last variable argument should be %NULL.
+ *
+ * For refcounted (mini)objects you will receive a new reference which
+ * you must release with a suitable _unref\() when no longer needed. For
+ * strings and boxed types you will receive a copy which you will need to
+ * release with either g_free() or the suitable function for the boxed type.
+ *
+ * Returns: %FALSE if there was a problem reading any of the fields (e.g.
+ *     because the field requested did not exist, or was of a type other
+ *     than the type specified), otherwise %TRUE.
+ *
+ * Since: 1.26
+ */
+gboolean
+gst_structure_id_str_get (const GstStructure * structure,
+    const GstIdStr * first_fieldname, ...)
+{
+  gboolean ret;
+  va_list args;
+
+  g_return_val_if_fail (GST_IS_STRUCTURE (structure), FALSE);
+  g_return_val_if_fail (first_fieldname != NULL, FALSE);
+
+  va_start (args, first_fieldname);
+  ret = gst_structure_id_str_get_valist (structure, first_fieldname, args);
+  va_end (args);
+
+  return ret;
+}
+
 /**
  * gst_structure_id_get:
  * @structure: a #GstStructure
@@ -3098,6 +4218,8 @@ gst_structure_get (const GstStructure * structure, const char *first_fieldname,
  * Returns: %FALSE if there was a problem reading any of the fields (e.g.
  *     because the field requested did not exist, or was of a type other
  *     than the type specified), otherwise %TRUE.
+ *
+ * Deprecated: 1.26: Use gst_structure_id_str_get().
  */
 gboolean
 gst_structure_id_get (const GstStructure * structure, GQuark first_field_id,
@@ -3110,18 +4232,20 @@ gst_structure_id_get (const GstStructure * structure, GQuark first_field_id,
   g_return_val_if_fail (first_field_id != 0, FALSE);
 
   va_start (args, first_field_id);
+  G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
   ret = gst_structure_id_get_valist (structure, first_field_id, args);
+  G_GNUC_END_IGNORE_DEPRECATIONS;
   va_end (args);
 
   return ret;
 }
 
 static gboolean
-gst_structure_is_equal_foreach (GQuark field_id, const GValue * val2,
+gst_structure_is_equal_foreach (const GstIdStr * fieldname, const GValue * val2,
     gpointer data)
 {
   const GstStructure *struct1 = (const GstStructure *) data;
-  const GValue *val1 = gst_structure_id_get_value (struct1, field_id);
+  const GValue *val1 = gst_structure_id_str_get_value (struct1, fieldname);
 
   if (G_UNLIKELY (val1 == NULL))
     return FALSE;
@@ -3151,15 +4275,16 @@ gst_structure_is_equal (const GstStructure * structure1,
   if (G_UNLIKELY (structure1 == structure2))
     return TRUE;
 
-  if (structure1->name != structure2->name) {
+  if (!gst_id_str_is_equal (GST_STRUCTURE_NAME (structure1),
+          GST_STRUCTURE_NAME (structure2))) {
     return FALSE;
   }
   if (GST_STRUCTURE_LEN (structure1) != GST_STRUCTURE_LEN (structure2)) {
     return FALSE;
   }
 
-  return gst_structure_foreach (structure1, gst_structure_is_equal_foreach,
-      (gpointer) structure2);
+  return gst_structure_foreach_id_str (structure1,
+      gst_structure_is_equal_foreach, (gpointer) structure2);
 }
 
 /**
@@ -3181,14 +4306,17 @@ gst_structure_intersect (const GstStructure * struct1,
   g_assert (struct1 != NULL);
   g_assert (struct2 != NULL);
 
-  if (G_UNLIKELY (struct1->name != struct2->name))
+  if (!gst_id_str_is_equal (GST_STRUCTURE_NAME (struct1),
+          GST_STRUCTURE_NAME (struct2)))
     return NULL;
 
   len1 = GST_STRUCTURE_LEN (struct1);
   len2 = GST_STRUCTURE_LEN (struct2);
 
   /* Resulting structure will be at most the size of the smallest structure */
-  dest = gst_structure_new_id_empty_with_size (struct1->name, MIN (len1, len2));
+  dest =
+      gst_structure_new_id_str_empty_with_size (GST_STRUCTURE_NAME (struct1),
+      MIN (len1, len2));
 
   /* copy fields from struct1 which we have not in struct2 to target
    * intersect if we have the field in both */
@@ -3197,12 +4325,12 @@ gst_structure_intersect (const GstStructure * struct1,
     gboolean seenother = FALSE;
     for (it2 = 0; it2 < len2; it2++) {
       GstStructureField *field2 = GST_STRUCTURE_FIELD (struct2, it2);
-      if (field1->name == field2->name) {
-        GValue dest_value = { 0 };
+      if (gst_id_str_is_equal (&field1->name, &field2->name)) {
+        GValue dest_value = G_VALUE_INIT;
         seenother = TRUE;
         /* Get the intersection if any */
         if (gst_value_intersect (&dest_value, &field1->value, &field2->value)) {
-          gst_structure_id_take_value (dest, field1->name, &dest_value);
+          gst_structure_id_str_take_value (dest, &field1->name, &dest_value);
           break;
         } else {
           /* No intersection, return nothing */
@@ -3212,7 +4340,7 @@ gst_structure_intersect (const GstStructure * struct1,
     }
     /* Field1 was only present in struct1, copy it over */
     if (!seenother)
-      gst_structure_id_set_value (dest, field1->name, &field1->value);
+      gst_structure_id_str_set_value (dest, &field1->name, &field1->value);
   }
 
   /* Now iterate over the 2nd struct and copy over everything which
@@ -3223,13 +4351,13 @@ gst_structure_intersect (const GstStructure * struct1,
     gboolean seenother = FALSE;
     for (it1 = 0; it1 < len1; it1++) {
       GstStructureField *field1 = GST_STRUCTURE_FIELD (struct1, it1);
-      if (field1->name == field2->name) {
+      if (gst_id_str_is_equal (&field1->name, &field2->name)) {
         seenother = TRUE;
         break;
       }
     }
     if (!seenother)
-      gst_structure_id_set_value (dest, field2->name, &field2->value);
+      gst_structure_id_str_set_value (dest, &field2->name, &field2->value);
 
   }
 
@@ -3241,11 +4369,11 @@ error:
 }
 
 static gboolean
-gst_caps_structure_can_intersect_field (GQuark id, const GValue * val1,
-    gpointer data)
+gst_caps_structure_can_intersect_field (const GstIdStr * fieldname,
+    const GValue * val1, gpointer data)
 {
   GstStructure *other = (GstStructure *) data;
-  const GValue *val2 = gst_structure_id_get_value (other, id);
+  const GValue *val2 = gst_structure_id_str_get_value (other, fieldname);
 
   if (G_LIKELY (val2)) {
     if (!gst_value_can_intersect (val1, val2)) {
@@ -3283,11 +4411,12 @@ gst_structure_can_intersect (const GstStructure * struct1,
   g_return_val_if_fail (GST_IS_STRUCTURE (struct1), FALSE);
   g_return_val_if_fail (GST_IS_STRUCTURE (struct2), FALSE);
 
-  if (G_UNLIKELY (struct1->name != struct2->name))
+  if (G_UNLIKELY (!gst_id_str_is_equal (GST_STRUCTURE_NAME (struct1),
+              GST_STRUCTURE_NAME (struct2))))
     return FALSE;
 
   /* tries to intersect if we have the field in both */
-  return gst_structure_foreach ((GstStructure *) struct1,
+  return gst_structure_foreach_id_str ((GstStructure *) struct1,
       gst_caps_structure_can_intersect_field, (gpointer) struct2);
 }
 
@@ -3311,7 +4440,8 @@ gst_structure_is_subset (const GstStructure * subset,
 
   g_assert (superset);
 
-  if (G_UNLIKELY (superset->name != subset->name))
+  if (G_UNLIKELY (!gst_id_str_is_equal (GST_STRUCTURE_NAME (superset),
+              GST_STRUCTURE_NAME (subset))))
     return FALSE;
 
   len1 = GST_STRUCTURE_LEN (subset);
@@ -3324,7 +4454,7 @@ gst_structure_is_subset (const GstStructure * subset,
     gboolean seenother = FALSE;
     for (it1 = 0; it1 < len1; it1++) {
       GstStructureField *subfield = GST_STRUCTURE_FIELD (subset, it1);
-      if (subfield->name == superfield->name) {
+      if (gst_id_str_is_equal (&subfield->name, &superfield->name)) {
         int comparison =
             gst_value_compare (&subfield->value, &superfield->value);
         seenother = TRUE;
@@ -3367,7 +4497,7 @@ gst_structure_fixate (GstStructure * structure)
 {
   g_return_if_fail (GST_IS_STRUCTURE (structure));
 
-  gst_structure_foreach (structure, default_fixate, structure);
+  gst_structure_map_in_place_id_str (structure, default_fixate, structure);
 }
 
 static gboolean
@@ -3464,14 +4594,15 @@ _gst_structure_set_any_list (GstStructure * structure, GType type,
   g_value_set_static_boxed (&arval, array);
 
   if (g_value_transform (&arval, &value)) {
-    gst_structure_id_set_value_internal (structure,
-        g_quark_from_string (fieldname), &value);
+    GstIdStr s = GST_ID_STR_INIT;
+    gst_id_str_set (&s, fieldname);
+    gst_structure_id_str_take_value_internal (structure, &s, &value);
   } else {
     g_warning ("Failed to convert a GValueArray");
+    g_value_unset (&value);
   }
 
   g_value_unset (&arval);
-  g_value_unset (&value);
 }
 
 /**
diff --git a/gst/gststructure.h b/gst/gststructure.h
index d86dedc..dcad0ea 100644
--- a/gst/gststructure.h
+++ b/gst/gststructure.h
@@ -25,6 +25,7 @@
 #include <gst/gstclock.h>
 #include <gst/gstdatetime.h>
 #include <gst/glib-compat.h>
+#include <gst/gstidstr.h>
 
 G_BEGIN_DECLS
 
@@ -114,6 +115,61 @@ typedef gboolean (*GstStructureFilterMapFunc) (GQuark   field_id,
                                                GValue * value,
                                                gpointer user_data);
 
+/**
+ * GstStructureForeachIdStrFunc:
+ * @fieldname: the #GstIdStr field name
+ * @value: the #GValue of the field
+ * @user_data: user data
+ *
+ * A function that will be called in gst_structure_foreach_id_str(). The
+ * function may not modify @value.
+ *
+ * Returns: %TRUE if the foreach operation should continue, %FALSE if
+ * the foreach operation should stop with %FALSE.
+ *
+ * Since: 1.26
+ */
+typedef gboolean (*GstStructureForeachIdStrFunc) (const GstIdStr * fieldname,
+                                                  const GValue   * value,
+                                                  gpointer         user_data);
+
+/**
+ * GstStructureMapIdStrFunc:
+ * @fieldname: the #GstIdStr field name
+ * @value: the #GValue of the field
+ * @user_data: user data
+ *
+ * A function that will be called in gst_structure_map_in_place_id_str(). The
+ * function may modify @value.
+ *
+ * Returns: %TRUE if the map operation should continue, %FALSE if
+ * the map operation should stop with %FALSE.
+ *
+ * Since: 1.26
+ */
+typedef gboolean (*GstStructureMapIdStrFunc)     (const GstIdStr * fieldname,
+                                                  GValue         * value,
+                                                  gpointer         user_data);
+
+/**
+ * GstStructureFilterMapIdStrFunc:
+ * @fieldname: the #GstIdStr field name
+ * @value: the #GValue of the field
+ * @user_data: user data
+ *
+ * A function that will be called in gst_structure_filter_and_map_in_place_id_str().
+ * The function may modify @value, and the value will be removed from the
+ * structure if %FALSE is returned.
+ *
+ * Returns: %TRUE if the field should be preserved, %FALSE if it
+ * should be removed.
+ *
+ * Since: 1.26
+ */
+typedef gboolean (*GstStructureFilterMapIdStrFunc) (const GstIdStr * fieldname,
+                                                   GValue          * value,
+                                                   gpointer          user_data);
+
 /**
  * GstStructure:
  * @type: the GType of a structure
@@ -134,20 +190,44 @@ GST_API
 GstStructure *        gst_structure_new_empty            (const gchar * name) G_GNUC_MALLOC;
 
 GST_API
+GstStructure *        gst_structure_new_static_str_empty (const gchar * name) G_GNUC_MALLOC;
+
+GST_DEPRECATED_FOR(gst_structure_new_id_str_empty)
 GstStructure *        gst_structure_new_id_empty         (GQuark quark) G_GNUC_MALLOC;
 
+GST_API
+GstStructure *        gst_structure_new_id_str_empty     (const GstIdStr *name) G_GNUC_MALLOC;
+
 GST_API
 GstStructure *        gst_structure_new                  (const gchar * name,
                                                           const gchar * firstfield,
                                                           ...) G_GNUC_NULL_TERMINATED  G_GNUC_MALLOC;
 GST_API
+GstStructure *        gst_structure_new_static_str       (const gchar * name,
+                                                          const gchar * firstfield,
+                                                          ...) G_GNUC_NULL_TERMINATED  G_GNUC_MALLOC;
+GST_API
+GstStructure *        gst_structure_new_id_str_valist    (const GstIdStr * name,
+                                                          const GstIdStr * firstfield,
+                                                          va_list       varargs) G_GNUC_MALLOC;
+GST_API
 GstStructure *        gst_structure_new_valist           (const gchar * name,
                                                           const gchar * firstfield,
                                                           va_list       varargs) G_GNUC_MALLOC;
 GST_API
+GstStructure *        gst_structure_new_static_str_valist(const gchar * name,
+                                                          const gchar * firstfield,
+                                                          va_list       varargs) G_GNUC_MALLOC;
+GST_DEPRECATED_FOR(gst_structure_new_id_str)
 GstStructure *        gst_structure_new_id               (GQuark name_quark,
                                                           GQuark field_quark,
                                                           ...) G_GNUC_MALLOC;
+
+GST_API
+GstStructure *        gst_structure_new_id_str           (const GstIdStr *name,
+                                                          const GstIdStr *fieldname,
+                                                          ...) G_GNUC_NULL_TERMINATED G_GNUC_MALLOC;
+
 GST_API
 GstStructure *        gst_structure_new_from_string      (const gchar * string);
 
@@ -170,24 +250,41 @@ gboolean              gst_structure_take                 (GstStructure ** oldstr
 GST_API
 const gchar *         gst_structure_get_name             (const GstStructure  * structure);
 
-GST_API
+GST_DEPRECATED_FOR(gst_structure_get_name_id_str)
 GQuark                gst_structure_get_name_id          (const GstStructure  * structure);
 
+GST_API
+const GstIdStr *      gst_structure_get_name_id_str      (const GstStructure  * structure);
+
 GST_API
 gboolean              gst_structure_has_name             (const GstStructure  * structure,
                                                           const gchar         * name);
 GST_API
+void                  gst_structure_set_name_id_str      (GstStructure        * structure,
+                                                          const GstIdStr      * name);
+GST_API
 void                  gst_structure_set_name             (GstStructure        * structure,
                                                           const gchar         * name);
 GST_API
+void                  gst_structure_set_name_static_str  (GstStructure        * structure,
+                                                          const gchar         * name);
+GST_DEPRECATED_FOR(gst_structure_id_str_set_value)
 void                  gst_structure_id_set_value         (GstStructure        * structure,
                                                           GQuark                field,
                                                           const GValue        * value);
 GST_API
+void                  gst_structure_id_str_set_value     (GstStructure        * structure,
+                                                          const GstIdStr      * fieldname,
+                                                          const GValue        * value);
+GST_API
 void                  gst_structure_set_value            (GstStructure        * structure,
                                                           const gchar         * fieldname,
                                                           const GValue        * value);
 GST_API
+void                  gst_structure_set_value_static_str (GstStructure        * structure,
+                                                          const gchar         * fieldname,
+                                                          const GValue        * value);
+GST_API
 void                  gst_structure_set_array            (GstStructure        * structure,
                                                           const gchar         * fieldname,
                                                           const GValueArray   * array);
@@ -195,31 +292,55 @@ GST_API
 void                  gst_structure_set_list             (GstStructure        * structure,
                                                           const gchar         * fieldname,
                                                           const GValueArray   * array);
-GST_API
+GST_DEPRECATED_FOR(gst_structure_id_str_take_value)
 void                  gst_structure_id_take_value        (GstStructure        * structure,
                                                           GQuark                field,
                                                           GValue              * value);
 GST_API
+void                  gst_structure_id_str_take_value    (GstStructure        * structure,
+                                                          const GstIdStr      * fieldname,
+                                                          GValue              * value);
+GST_API
 void                  gst_structure_take_value           (GstStructure        * structure,
                                                           const gchar         * fieldname,
                                                           GValue              * value);
 GST_API
+void                  gst_structure_take_value_static_str(GstStructure        * structure,
+                                                          const gchar         * fieldname,
+                                                          GValue              * value);
+GST_API
 void                  gst_structure_set                  (GstStructure        * structure,
                                                           const gchar         * fieldname,
                                                           ...) G_GNUC_NULL_TERMINATED;
 GST_API
+void                  gst_structure_set_static_str       (GstStructure        * structure,
+                                                          const gchar         * fieldname,
+                                                          ...) G_GNUC_NULL_TERMINATED;
+GST_API
 void                  gst_structure_set_valist           (GstStructure        * structure,
                                                           const gchar         * fieldname,
                                                           va_list varargs);
 GST_API
+void                  gst_structure_set_static_str_valist(GstStructure        * structure,
+                                                          const gchar         * fieldname,
+                                                          va_list varargs);
+GST_DEPRECATED_FOR(gst_structure_id_str_set)
 void                  gst_structure_id_set               (GstStructure        * structure,
                                                           GQuark                fieldname,
                                                           ...) G_GNUC_NULL_TERMINATED;
 GST_API
+void                  gst_structure_id_str_set           (GstStructure        * structure,
+                                                          const GstIdStr      * fieldname,
+                                                          ...) G_GNUC_NULL_TERMINATED;
+GST_DEPRECATED_FOR(gst_structure_id_str_set_valist)
 void                  gst_structure_id_set_valist        (GstStructure        * structure,
                                                           GQuark                fieldname,
                                                           va_list varargs);
 GST_API
+void                  gst_structure_id_str_set_valist    (GstStructure        * structure,
+                                                          const GstIdStr      * fieldname,
+                                                          va_list varargs);
+GST_API
 gboolean              gst_structure_get_valist           (const GstStructure  * structure,
                                                           const char          * first_fieldname,
                                                           va_list              args);
@@ -228,17 +349,28 @@ gboolean              gst_structure_get                  (const GstStructure  *
                                                           const char          * first_fieldname,
                                                           ...) G_GNUC_NULL_TERMINATED;
 GST_API
+gboolean              gst_structure_id_str_get_valist    (const GstStructure  * structure,
+                                                          const GstIdStr      * first_fieldname,
+                                                          va_list              args);
+GST_API
+gboolean              gst_structure_id_str_get           (const GstStructure  * structure,
+                                                          const GstIdStr      * first_fieldname,
+                                                          ...) G_GNUC_NULL_TERMINATED;
+GST_DEPRECATED_FOR(gst_structure_id_str_get_valist)
 gboolean              gst_structure_id_get_valist        (const GstStructure  * structure,
                                                           GQuark                first_field_id,
                                                           va_list               args);
-GST_API
+GST_DEPRECATED_FOR(gst_structure_id_str_get)
 gboolean              gst_structure_id_get               (const GstStructure  * structure,
                                                           GQuark                first_field_id,
                                                           ...) G_GNUC_NULL_TERMINATED;
-GST_API
+GST_DEPRECATED_FOR(gst_structure_id_str_get_value)
 const GValue *        gst_structure_id_get_value         (const GstStructure  * structure,
                                                           GQuark                field);
 GST_API
+const GValue *        gst_structure_id_str_get_value     (const GstStructure  * structure,
+                                                          const GstIdStr      * fieldname);
+GST_API
 const GValue *        gst_structure_get_value            (const GstStructure  * structure,
                                                           const gchar         * fieldname);
 GST_API
@@ -253,23 +385,49 @@ void                  gst_structure_remove_fields_valist (GstStructure        *
                                                           const gchar         * fieldname,
                                                           va_list               varargs);
 GST_API
+void                  gst_structure_id_str_remove_field  (GstStructure        * structure,
+                                                          const GstIdStr      * fieldname);
+GST_API
+void                  gst_structure_id_str_remove_fields (GstStructure        * structure,
+                                                          const GstIdStr      * fieldname,
+                                                          ...) G_GNUC_NULL_TERMINATED;
+GST_API
+void                  gst_structure_id_str_remove_fields_valist(GstStructure  * structure,
+                                                          const GstIdStr      * fieldname,
+                                                          va_list               varargs);
+GST_API
 void                  gst_structure_remove_all_fields    (GstStructure        * structure);
 
 GST_API
 GType                 gst_structure_get_field_type       (const GstStructure  * structure,
                                                           const gchar         * fieldname);
 GST_API
+GType                 gst_structure_id_str_get_field_type(const GstStructure  * structure,
+                                                          const GstIdStr      * fieldname);
+GST_DEPRECATED_FOR(gst_structure_foreach_id_str)
 gboolean              gst_structure_foreach              (const GstStructure  * structure,
                                                           GstStructureForeachFunc   func,
                                                           gpointer              user_data);
-GST_API
+GST_DEPRECATED_FOR(gst_structure_map_in_place_id_str)
 gboolean              gst_structure_map_in_place         (GstStructure        * structure,
                                                           GstStructureMapFunc   func,
                                                           gpointer              user_data);
+GST_DEPRECATED_FOR(gst_structure_filter_and_map_in_place_id_str)
+void                  gst_structure_filter_and_map_in_place (GstStructure             * structure,
+                                                              GstStructureFilterMapFunc func,
+                                                              gpointer                  user_data);
 GST_API
-void                  gst_structure_filter_and_map_in_place (GstStructure        * structure,
-                                                          GstStructureFilterMapFunc   func,
-                                                          gpointer              user_data);
+gboolean              gst_structure_foreach_id_str       (const GstStructure         * structure,
+                                                          GstStructureForeachIdStrFunc func,
+                                                          gpointer                     user_data);
+GST_API
+gboolean              gst_structure_map_in_place_id_str  (GstStructure           * structure,
+                                                          GstStructureMapIdStrFunc func,
+                                                          gpointer                 user_data);
+GST_API
+void                  gst_structure_filter_and_map_in_place_id_str (GstStructure                 * structure,
+                                                                    GstStructureFilterMapIdStrFunc func,
+                                                                    gpointer                       user_data);
 GST_API
 gint                  gst_structure_n_fields             (const GstStructure  * structure);
 
@@ -277,9 +435,12 @@ GST_API
 const gchar *         gst_structure_nth_field_name       (const GstStructure  * structure,
                                                           guint                 index);
 GST_API
+const GstIdStr *      gst_structure_id_str_nth_field_name(const GstStructure  * structure,
+                                                          guint                 index);
+GST_DEPRECATED_FOR(gst_structure_id_str_has_field)
 gboolean              gst_structure_id_has_field         (const GstStructure  * structure,
                                                           GQuark                field);
-GST_API
+GST_DEPRECATED_FOR(gst_structure_id_str_has_field_typed)
 gboolean              gst_structure_id_has_field_typed   (const GstStructure  * structure,
                                                           GQuark                field,
                                                           GType                 type);
@@ -290,6 +451,13 @@ GST_API
 gboolean              gst_structure_has_field_typed      (const GstStructure  * structure,
                                                           const gchar         * fieldname,
                                                           GType                 type);
+GST_API
+gboolean              gst_structure_id_str_has_field     (const GstStructure  * structure,
+                                                          const GstIdStr      * fieldname);
+GST_API
+gboolean              gst_structure_id_str_has_field_typed(const GstStructure  * structure,
+                                                          const GstIdStr      * fieldname,
+                                                          GType                 type);
 
 /* utility functions */
 
diff --git a/gst/gstsystemclock.c b/gst/gstsystemclock.c
index 72c3912..cad9fc7 100644
--- a/gst/gstsystemclock.c
+++ b/gst/gstsystemclock.c
@@ -251,7 +251,7 @@ gst_futex_cond_broadcast (guint * cond_val)
   g_atomic_int_inc (cond_val);
 
 #if defined(HAVE_FUTEX_TIME64)
-#if defined(__BIONIC__)
+#if defined(__ANDROID__)
   if (__builtin_available (android 30, *)) {
 #else
   {
@@ -313,7 +313,7 @@ gst_futex_cond_wait_until (guint * cond_val, GMutex * mutex, gint64 end_time)
    */
 
 #if defined(HAVE_FUTEX_TIME64)
-#if defined(__BIONIC__)
+#if defined(__ANDROID__)
   if (__builtin_available (android 30, *)) {
 #else
   {
diff --git a/gst/gsttaglist.c b/gst/gsttaglist.c
index 222c350..44c26ee 100644
--- a/gst/gsttaglist.c
+++ b/gst/gsttaglist.c
@@ -42,8 +42,8 @@
 #include "gstinfo.h"
 #include "gstvalue.h"
 #include "gstbuffer.h"
-#include "gstquark.h"
 #include "gststructure.h"
+#include "gstidstr-private.h"
 
 #include <gobject/gvaluecollector.h>
 #include <string.h>
@@ -68,12 +68,12 @@ typedef struct
 {
   GType type;                   /* type the data is in */
 
+  GstIdStr name;
   const gchar *nick;            /* translated short description */
   const gchar *blurb;           /* translated long description  */
 
   GstTagMergeFunc merge_func;   /* functions to merge the values */
   GstTagFlag flag;              /* type of tag */
-  GQuark name_quark;            /* quark for the name */
 }
 GstTagInfo;
 
@@ -550,10 +550,10 @@ gst_tag_register_static (const gchar * name, GstTagFlag flag, GType type,
     return;
   }
 
-  info = g_new (GstTagInfo, 1);
+  info = g_new0 (GstTagInfo, 1);
   info->flag = flag;
   info->type = type;
-  info->name_quark = g_quark_from_static_string (name);
+  gst_id_str_set_static_str (&info->name, name);
   info->nick = nick;
   info->blurb = blurb;
   info->merge_func = func;
@@ -755,7 +755,7 @@ gst_tag_list_new_empty (void)
   GstStructure *s;
   GstTagList *tag_list;
 
-  s = gst_structure_new_id_empty (GST_QUARK (TAGLIST));
+  s = gst_structure_new_empty ("taglist");
   tag_list = gst_tag_list_new_internal (s, GST_TAG_SCOPE_STREAM);
   return tag_list;
 }
@@ -956,11 +956,11 @@ gst_tag_list_is_empty (const GstTagList * list)
 }
 
 static gboolean
-gst_tag_list_fields_equal (GQuark field_id, const GValue * value2,
+gst_tag_list_fields_equal (const GstIdStr * field, const GValue * value2,
     gpointer data)
 {
   const GstStructure *struct1 = (const GstStructure *) data;
-  const GValue *value1 = gst_structure_id_get_value (struct1, field_id);
+  const GValue *value1 = gst_structure_id_str_get_value (struct1, field);
   gdouble d1, d2;
 
   if (value1 == NULL) {
@@ -1017,7 +1017,8 @@ gst_tag_list_is_equal (const GstTagList * list1, const GstTagList * list2)
     return FALSE;
   }
 
-  return gst_structure_foreach (s1, gst_tag_list_fields_equal, (gpointer) s2);
+  return gst_structure_foreach_id_str (s1, gst_tag_list_fields_equal,
+      (gpointer) s2);
 }
 
 typedef struct
@@ -1033,7 +1034,7 @@ gst_tag_list_add_value_internal (GstTagList * tag_list, GstTagMergeMode mode,
 {
   GstStructure *list = GST_TAG_LIST_STRUCTURE (tag_list);
   const GValue *value2;
-  GQuark tag_quark;
+  const GstIdStr *tag_name;
 
   if (info == NULL) {
     info = gst_tag_lookup (tag);
@@ -1051,23 +1052,23 @@ gst_tag_list_add_value_internal (GstTagList * tag_list, GstTagMergeMode mode,
     return;
   }
 
-  tag_quark = info->name_quark;
+  tag_name = &info->name;
 
   if (info->merge_func
-      && (value2 = gst_structure_id_get_value (list, tag_quark)) != NULL) {
+      && (value2 = gst_structure_id_str_get_value (list, tag_name)) != NULL) {
     GValue dest = { 0, };
 
     switch (mode) {
       case GST_TAG_MERGE_REPLACE_ALL:
       case GST_TAG_MERGE_REPLACE:
-        gst_structure_id_set_value (list, tag_quark, value);
+        gst_structure_id_str_set_value (list, tag_name, value);
         break;
       case GST_TAG_MERGE_PREPEND:
         if (GST_VALUE_HOLDS_LIST (value2) && !GST_VALUE_HOLDS_LIST (value))
           gst_value_list_prepend_value ((GValue *) value2, value);
         else {
           gst_value_list_merge (&dest, value, value2);
-          gst_structure_id_take_value (list, tag_quark, &dest);
+          gst_structure_id_str_take_value (list, tag_name, &dest);
         }
         break;
       case GST_TAG_MERGE_APPEND:
@@ -1075,7 +1076,7 @@ gst_tag_list_add_value_internal (GstTagList * tag_list, GstTagMergeMode mode,
           gst_value_list_append_value ((GValue *) value2, value);
         else {
           gst_value_list_merge (&dest, value2, value);
-          gst_structure_id_take_value (list, tag_quark, &dest);
+          gst_structure_id_str_take_value (list, tag_name, &dest);
         }
         break;
       case GST_TAG_MERGE_KEEP:
@@ -1089,13 +1090,13 @@ gst_tag_list_add_value_internal (GstTagList * tag_list, GstTagMergeMode mode,
     switch (mode) {
       case GST_TAG_MERGE_APPEND:
       case GST_TAG_MERGE_KEEP:
-        if (gst_structure_id_get_value (list, tag_quark) != NULL)
+        if (gst_structure_id_str_get_value (list, tag_name) != NULL)
           break;
         /* fall through */
       case GST_TAG_MERGE_REPLACE_ALL:
       case GST_TAG_MERGE_REPLACE:
       case GST_TAG_MERGE_PREPEND:
-        gst_structure_id_set_value (list, tag_quark, value);
+        gst_structure_id_str_set_value (list, tag_name, value);
         break;
       case GST_TAG_MERGE_KEEP_ALL:
         break;
@@ -1107,13 +1108,13 @@ gst_tag_list_add_value_internal (GstTagList * tag_list, GstTagMergeMode mode,
 }
 
 static gboolean
-gst_tag_list_copy_foreach (GQuark tag_quark, const GValue * value,
+gst_tag_list_copy_foreach (const GstIdStr * field, const GValue * value,
     gpointer user_data)
 {
   GstTagCopyData *copy = (GstTagCopyData *) user_data;
   const gchar *tag;
 
-  tag = g_quark_to_string (tag_quark);
+  tag = gst_id_str_as_str (field);
   gst_tag_list_add_value_internal (copy->list, copy->mode, tag, value, NULL);
 
   return TRUE;
@@ -1143,7 +1144,7 @@ gst_tag_list_insert (GstTagList * into, const GstTagList * from,
   if (mode == GST_TAG_MERGE_REPLACE_ALL) {
     gst_structure_remove_all_fields (GST_TAG_LIST_STRUCTURE (into));
   }
-  gst_structure_foreach (GST_TAG_LIST_STRUCTURE (from),
+  gst_structure_foreach_id_str (GST_TAG_LIST_STRUCTURE (from),
       gst_tag_list_copy_foreach, &data);
 }
 
@@ -1400,20 +1401,20 @@ typedef struct
 TagForeachData;
 
 static int
-structure_foreach_wrapper (GQuark field_id, const GValue * value,
+structure_foreach_wrapper (const GstIdStr * field, const GValue * value,
     gpointer user_data)
 {
   TagForeachData *data = (TagForeachData *) user_data;
 
-  data->func (data->tag_list, g_quark_to_string (field_id), data->data);
+  data->func (data->tag_list, gst_id_str_as_str (field), data->data);
   return TRUE;
 }
 
 /**
  * gst_tag_list_foreach:
  * @list: list to iterate over
- * @func: (scope call): function to be called for each tag
- * @user_data: (closure): user specified data
+ * @func: (scope call) (closure user_data): function to be called for each tag
+ * @user_data: user specified data
  *
  * Calls the given function for each tag inside the tag list. Note that if there
  * is no tag, the function won't be called at all.
@@ -1430,7 +1431,7 @@ gst_tag_list_foreach (const GstTagList * list, GstTagForeachFunc func,
   data.func = func;
   data.tag_list = list;
   data.data = user_data;
-  gst_structure_foreach (GST_TAG_LIST_STRUCTURE (list),
+  gst_structure_foreach_id_str (GST_TAG_LIST_STRUCTURE (list),
       structure_foreach_wrapper, &data);
 }
 
diff --git a/gst/gsttaskpool.c b/gst/gsttaskpool.c
index 020a1d2..11f2a06 100644
--- a/gst/gsttaskpool.c
+++ b/gst/gsttaskpool.c
@@ -233,8 +233,8 @@ gst_task_pool_cleanup (GstTaskPool * pool)
 /**
  * gst_task_pool_push:
  * @pool: a #GstTaskPool
- * @func: (scope async): the function to call
- * @user_data: (closure): data to pass to @func
+ * @func: (scope async) (closure user_data): the function to call
+ * @user_data: data to pass to @func
  * @error: return location for an error
  *
  * Start the execution of a new thread from @pool.
diff --git a/gst/gsttoc.c b/gst/gsttoc.c
index bee3224..2ee3ce6 100644
--- a/gst/gsttoc.c
+++ b/gst/gsttoc.c
@@ -83,7 +83,6 @@
 #include "gstvalue.h"
 #include "gsttoc.h"
 #include "gstpad.h"
-#include "gstquark.h"
 
 struct _GstTocEntry
 {
diff --git a/gst/gsttracer.c b/gst/gsttracer.c
index 1849142..98c5f8a 100644
--- a/gst/gsttracer.c
+++ b/gst/gsttracer.c
@@ -52,6 +52,11 @@ enum
 
 static GParamSpec *properties[PROP_LAST];
 
+typedef struct
+{
+  gboolean use_structure_params;
+} GstTracerClassPrivate;
+
 static void gst_tracer_set_property (GObject * object, guint prop_id,
     const GValue * value, GParamSpec * pspec);
 static void gst_tracer_get_property (GObject * object, guint prop_id,
@@ -62,14 +67,21 @@ struct _GstTracerPrivate
   gchar *params;
 };
 
+#define _do_init \
+    g_type_add_class_private (g_define_type_id, \
+        sizeof (GstTracerClassPrivate));
+
 #define gst_tracer_parent_class parent_class
-G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (GstTracer, gst_tracer, GST_TYPE_OBJECT);
+G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GstTracer, gst_tracer, GST_TYPE_OBJECT,
+    G_ADD_PRIVATE (GstTracer) _do_init);
 
 static void
 gst_tracer_dispose (GObject * object)
 {
   GstTracer *tracer = GST_TRACER (object);
   g_free (tracer->priv->params);
+
+  G_OBJECT_CLASS (parent_class)->dispose (object);
 }
 
 static void
@@ -192,3 +204,48 @@ gst_tracer_register (GstPlugin * plugin, const gchar * name, GType type)
 
   return TRUE;
 }
+
+/**
+ * gst_tracer_class_uses_structure_params:
+ * @tracer_class: the #GstTracerClass to to check
+ *
+ * If set, the tracer subsystem will consider parameters passed to the
+ * `GST_TRACERS` environment variable as a #GstStructure and use its
+ * fields as properties to instanciate the tracer.
+ *
+ * Returns: %TRUE if the tracer uses structure parameters, %FALSE otherwise
+ *
+ * Since: 1.26
+ */
+gboolean
+gst_tracer_class_uses_structure_params (GstTracerClass * tracer_class)
+{
+  g_return_val_if_fail (GST_IS_TRACER_CLASS (tracer_class), FALSE);
+
+  return G_TYPE_CLASS_GET_PRIVATE (tracer_class, GST_TYPE_TRACER,
+      GstTracerClassPrivate)->use_structure_params;
+}
+
+/**
+ * gst_tracer_class_set_use_structure_params:
+ * @tracer_class: the #GstTracerFactoryClass to mark as using structure parameters
+ * @use_structure_params: %TRUE to use structure parameters, %FALSE otherwise
+ *
+ * Sets whether the tracer should use structure parameters for configuration.
+ * This function configures how parameters should be passed when instantiating
+ * the tracer.
+ *
+ * This is typically called in the tracer's class initialization function to
+ * indicate its parameter handling preference.
+ *
+ * Since: 1.26
+ */
+void
+gst_tracer_class_set_use_structure_params (GstTracerClass * tracer_class,
+    gboolean use_structure_params)
+{
+  g_return_if_fail (GST_IS_TRACER_CLASS (tracer_class));
+
+  G_TYPE_CLASS_GET_PRIVATE (tracer_class, GST_TYPE_TRACER,
+      GstTracerClassPrivate)->use_structure_params = use_structure_params;
+}
diff --git a/gst/gsttracer.h b/gst/gsttracer.h
index 6560296..c1a597a 100644
--- a/gst/gsttracer.h
+++ b/gst/gsttracer.h
@@ -75,6 +75,12 @@ gboolean gst_tracer_register (GstPlugin * plugin, const gchar * name, GType type
 GST_API
 GList* gst_tracing_get_active_tracers (void);
 
+GST_API
+gboolean gst_tracer_class_uses_structure_params  (GstTracerClass *tracer_class);
+GST_API
+void gst_tracer_class_set_use_structure_params   (GstTracerClass *tracer_class,
+                                                  gboolean use_structure_params);
+
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstTracer, gst_object_unref)
 
 G_END_DECLS
diff --git a/gst/gsttracerfactory.c b/gst/gsttracerfactory.c
index 3942ace..b0efcc2 100644
--- a/gst/gsttracerfactory.c
+++ b/gst/gsttracerfactory.c
@@ -32,6 +32,7 @@
 #include "gstinfo.h"
 #include "gsttracerfactory.h"
 #include "gstregistry.h"
+#include "gsttracer.h"
 
 GST_DEBUG_CATEGORY (tracer_debug);
 #define GST_CAT_DEFAULT tracer_debug
diff --git a/gst/gsttracerfactory.h b/gst/gsttracerfactory.h
index ff88a4a..a4bd24b 100644
--- a/gst/gsttracerfactory.h
+++ b/gst/gsttracerfactory.h
@@ -57,6 +57,7 @@ GList *         gst_tracer_factory_get_list          (void);
 GST_API
 GType           gst_tracer_factory_get_tracer_type   (GstTracerFactory * factory);
 
+
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstTracerFactory, gst_object_unref)
 
 G_END_DECLS
diff --git a/gst/gsttracerrecord.c b/gst/gsttracerrecord.c
index 1caa687..f80c6df 100644
--- a/gst/gsttracerrecord.c
+++ b/gst/gsttracerrecord.c
@@ -58,7 +58,8 @@ struct _GstTracerRecordClass
 G_DEFINE_TYPE (GstTracerRecord, gst_tracer_record, GST_TYPE_OBJECT);
 
 static gboolean
-build_field_template (GQuark field_id, const GValue * value, gpointer user_data)
+build_field_template (const GstIdStr * field, const GValue * value,
+    gpointer user_data)
 {
   GString *s = (GString *) user_data;
   const GstStructure *sub;
@@ -69,7 +70,7 @@ build_field_template (GQuark field_id, const GValue * value, gpointer user_data)
 
   if (G_VALUE_TYPE (value) != GST_TYPE_STRUCTURE) {
     GST_ERROR ("expected field of type GstStructure, but %s is %s",
-        g_quark_to_string (field_id), G_VALUE_TYPE_NAME (value));
+        gst_id_str_as_str (field), G_VALUE_TYPE_NAME (value));
     return FALSE;
   }
 
@@ -78,18 +79,19 @@ build_field_template (GQuark field_id, const GValue * value, gpointer user_data)
       GST_TYPE_TRACER_VALUE_FLAGS, &flags, NULL);
 
   if (flags & GST_TRACER_VALUE_FLAGS_OPTIONAL) {
-    gchar *opt_name = g_strconcat ("have-", g_quark_to_string (field_id), NULL);
+    gchar *opt_name = g_strconcat ("have-", gst_id_str_as_str (field), NULL);
 
     /* add a boolean field, that indicates the presence of the next field */
     g_value_init (&template_value, G_TYPE_BOOLEAN);
-    priv__gst_structure_append_template_to_gstring (g_quark_from_string
-        (opt_name), &template_value, s);
+    priv__gst_structure_append_template_to_gstring (opt_name, &template_value,
+        s);
     g_value_unset (&template_value);
     g_free (opt_name);
   }
 
   g_value_init (&template_value, type);
-  res = priv__gst_structure_append_template_to_gstring (field_id,
+  res =
+      priv__gst_structure_append_template_to_gstring (gst_id_str_as_str (field),
       &template_value, s);
   g_value_unset (&template_value);
   return res;
@@ -100,7 +102,7 @@ gst_tracer_record_build_format (GstTracerRecord * self)
 {
   GstStructure *structure = self->spec;
   GString *s;
-  gchar *name = (gchar *) g_quark_to_string (structure->name);
+  gchar *name = (gchar *) gst_structure_get_name (structure);
   gchar *p;
 
   g_return_if_fail (g_str_has_suffix (name, ".class"));
@@ -116,7 +118,7 @@ gst_tracer_record_build_format (GstTracerRecord * self)
 
   s = g_string_sized_new (STRUCTURE_ESTIMATED_STRING_LEN (structure));
   g_string_append (s, name);
-  gst_structure_foreach (structure, build_field_template, s);
+  gst_structure_foreach_id_str (structure, build_field_template, s);
   g_string_append_c (s, ';');
 
   self->format = g_string_free (s, FALSE);
@@ -135,6 +137,8 @@ gst_tracer_record_dispose (GObject * object)
   }
   g_free (self->format);
   self->format = NULL;
+
+  G_OBJECT_CLASS (parent_class)->dispose (object);
 }
 
 static void
@@ -189,7 +193,6 @@ gst_tracer_record_new (const gchar * name, const gchar * firstfield, ...)
   va_list varargs;
   gchar *err = NULL;
   GType type;
-  GQuark id;
 
   va_start (varargs, firstfield);
   structure = gst_structure_new_empty (name);
@@ -197,7 +200,6 @@ gst_tracer_record_new (const gchar * name, const gchar * firstfield, ...)
   while (firstfield) {
     GValue val = { 0, };
 
-    id = g_quark_from_string (firstfield);
     type = va_arg (varargs, GType);
 
     /* all fields passed here must be GstStructures which we take over */
@@ -219,7 +221,7 @@ gst_tracer_record_new (const gchar * name, const gchar * firstfield, ...)
      * to this structure by unsetting the NOCOPY_CONTENTS collect-flag.
      * see boxed_proxy_collect_value in glib's gobject/gboxed.c */
     val.data[1].v_uint &= ~G_VALUE_NOCOPY_CONTENTS;
-    gst_structure_id_take_value (structure, id, &val);
+    gst_structure_take_value (structure, firstfield, &val);
 
     firstfield = va_arg (varargs, gchar *);
   }
diff --git a/gst/gsttracerutils.c b/gst/gsttracerutils.c
index eccf660..e67c812 100644
--- a/gst/gsttracerutils.c
+++ b/gst/gsttracerutils.c
@@ -34,6 +34,7 @@
 #include "gst_private.h"
 #include "gsttracer.h"
 #include "gsttracerfactory.h"
+#include "gstvalue.h"
 #include "gsttracerutils.h"
 
 #ifndef GST_DISABLE_GST_TRACER_HOOKS
@@ -56,7 +57,8 @@ static const gchar *_quark_strings[] = {
   "object-destroyed", "mini-object-reffed", "mini-object-unreffed",
   "object-reffed", "object-unreffed", "plugin-feature-loaded",
   "pad-chain-pre", "pad-chain-post", "pad-chain-list-pre",
-  "pad-chain-list-post",
+  "pad-chain-list-post", "pad-send-event-pre", "pad-send-event-post",
+  "memory-init", "memory-free-pre", "memory-free-post",
 };
 
 GQuark _priv_gst_tracer_quark_table[GST_TRACER_QUARK_MAX];
@@ -66,6 +68,169 @@ GQuark _priv_gst_tracer_quark_table[GST_TRACER_QUARK_MAX];
 gboolean _priv_tracer_enabled = FALSE;
 GHashTable *_priv_tracers = NULL;
 
+static gchar *
+list_available_tracer_properties (GObjectClass * class)
+{
+  GParamSpec **properties;
+  guint n_properties;
+  GString *props_str;
+  guint i;
+
+  props_str = g_string_new (NULL);
+  properties = g_object_class_list_properties (class, &n_properties);
+
+  if (n_properties == 0) {
+    g_string_append (props_str, "No properties available");
+    g_free (properties);
+    return g_string_free (props_str, FALSE);
+  }
+
+  g_string_append (props_str, "Available properties:");
+
+  for (i = 0; i < n_properties; i++) {
+    GParamSpec *prop = properties[i];
+
+    if (!((prop->flags & G_PARAM_CONSTRUCT)
+            || (prop->flags & G_PARAM_CONSTRUCT_ONLY))
+        || !(prop->flags & G_PARAM_WRITABLE))
+      continue;
+
+    if (!g_strcmp0 (g_param_spec_get_name (prop), "parent"))
+      continue;
+    if (!g_strcmp0 (g_param_spec_get_name (prop), "params"))
+      continue;
+
+    const gchar *type_name = G_PARAM_SPEC_TYPE_NAME (prop);
+    GValue default_value = G_VALUE_INIT;
+
+    /* Get default value if possible */
+    g_value_init (&default_value, prop->value_type);
+    g_param_value_set_default (prop, &default_value);
+    gchar *default_str = g_strdup_value_contents (&default_value);
+
+    g_string_append_printf (props_str,
+        "\n  '%s' (%s) (Default: %s): %s",
+        g_param_spec_get_name (prop),
+        type_name,
+        default_str,
+        g_param_spec_get_blurb (prop) ? g_param_spec_get_blurb (prop) :
+        "(no description available)");
+
+    g_free (default_str);
+    g_value_unset (&default_value);
+  }
+
+  g_free (properties);
+  return g_string_free (props_str, FALSE);
+}
+
+static void
+gst_tracer_utils_create_tracer (GstTracerFactory * factory, const gchar * name,
+    const gchar * params)
+{
+  gchar *available_props = NULL;
+  GObjectClass *gobject_class = g_type_class_ref (factory->type);
+  GstTracer *tracer;
+  const gchar **names = NULL;
+  GValue *values = NULL;
+  gint n_properties = 1;
+
+  if (gst_tracer_class_uses_structure_params (GST_TRACER_CLASS (gobject_class))) {
+    GST_DEBUG ("Use structure parameters for %s", params);
+
+    if (!params) {
+      n_properties = 0;
+      goto create;
+    }
+
+    gchar *struct_str = g_strdup_printf ("%s,%s", name, params);
+    GstStructure *structure = gst_structure_from_string (struct_str, NULL);
+    g_free (struct_str);
+
+    if (!structure) {
+      available_props = list_available_tracer_properties (gobject_class);
+      g_warning
+          ("Can't instantiate `%s` tracer: invalid parameters '%s'\n  %s\n",
+          name, params, available_props);
+      goto done;
+    }
+    n_properties = gst_structure_n_fields (structure);
+
+    names = g_new0 (const gchar *, n_properties);
+    values = g_new0 (GValue, n_properties);
+    for (gint i = 0; i < n_properties; i++) {
+      const gchar *field_name = gst_structure_nth_field_name (structure, i);
+      const GValue *field_value =
+          gst_structure_get_value (structure, field_name);
+      GParamSpec *pspec =
+          g_object_class_find_property (gobject_class, field_name);
+
+      if (!pspec) {
+        available_props = list_available_tracer_properties (gobject_class);
+        g_warning
+            ("Can't instantiate `%s` tracer: property '%s' not found\n  %s\n",
+            name, field_name, available_props);
+        goto done;
+      }
+
+      if (G_VALUE_TYPE (field_value) == pspec->value_type) {
+        names[i] = field_name;
+        g_value_init (&values[i], G_VALUE_TYPE (field_value));
+        g_value_copy (field_value, &values[i]);
+      } else if (G_VALUE_TYPE (field_value) == G_TYPE_STRING) {
+        names[i] = field_name;
+        g_value_init (&values[i], G_PARAM_SPEC_VALUE_TYPE (pspec));
+        if (!gst_value_deserialize_with_pspec (&values[i],
+                g_value_get_string (field_value), pspec)) {
+          available_props = list_available_tracer_properties (gobject_class);
+          g_warning
+              ("Can't instantiate `%s` tracer: invalid property '%s' value: '%s'\n  %s\n",
+              name, field_name, g_value_get_string (field_value),
+              available_props);
+          goto done;
+        }
+      } else {
+        available_props = list_available_tracer_properties (gobject_class);
+        g_warning
+            ("Can't instantiate `%s` tracer: property '%s' type mismatch, expected %s, got %s\n  %s\n",
+            name, field_name, g_type_name (pspec->value_type),
+            g_type_name (G_VALUE_TYPE (field_value)), available_props);
+        goto done;
+      }
+    }
+
+    g_type_class_unref (gobject_class);
+  } else {
+    names = g_new0 (const gchar *, n_properties);
+    names[0] = (const gchar *) "params";
+    values = g_new0 (GValue, 1);
+    g_value_init (&values[0], G_TYPE_STRING);
+    g_value_set_string (&values[0], params);
+  }
+  GST_INFO_OBJECT (factory, "creating tracer: type-id=%u",
+      (guint) factory->type);
+
+create:
+  tracer =
+      GST_TRACER (g_object_new_with_properties (factory->type,
+          n_properties, names, values));
+
+  for (gint j = 0; j < n_properties; j++) {
+    g_value_unset (&values[j]);
+  }
+  g_free (names);
+  g_free (values);
+
+  /* Clear floating flag */
+  gst_object_ref_sink (tracer);
+
+  /* tracers register them self to the hooks */
+  gst_object_unref (tracer);
+
+done:
+  g_free (available_props);
+}
+
 /* Initialize the tracing system */
 void
 _priv_gst_tracing_init (void)
@@ -128,24 +293,12 @@ _priv_gst_tracing_init (void)
       if ((feature = gst_registry_lookup_feature (registry, t[i]))) {
         factory = GST_TRACER_FACTORY (gst_plugin_feature_load (feature));
         if (factory) {
-          GstTracer *tracer;
-
-          GST_INFO_OBJECT (factory, "creating tracer: type-id=%u",
-              (guint) factory->type);
-
-          tracer = g_object_new (factory->type, "params", params, NULL);
-
-          /* Clear floating flag */
-          gst_object_ref_sink (tracer);
-
-          /* tracers register them self to the hooks */
-          gst_object_unref (tracer);
+          gst_tracer_utils_create_tracer (factory, t[i], params);
         } else {
-          GST_WARNING_OBJECT (feature,
-              "loading plugin containing feature %s failed!", t[i]);
+          g_warning ("loading plugin containing feature %s failed!", t[i]);
         }
       } else {
-        GST_WARNING ("no tracer named '%s'", t[i]);
+        g_warning ("no tracer named '%s'", t[i]);
       }
       i++;
     }
diff --git a/gst/gsttracerutils.h b/gst/gsttracerutils.h
index e5159be..294fe05 100644
--- a/gst/gsttracerutils.h
+++ b/gst/gsttracerutils.h
@@ -84,6 +84,32 @@ typedef enum /*< skip >*/
   GST_TRACER_QUARK_HOOK_PAD_CHAIN_POST,
   GST_TRACER_QUARK_HOOK_PAD_CHAIN_LIST_PRE,
   GST_TRACER_QUARK_HOOK_PAD_CHAIN_LIST_POST,
+  GST_TRACER_QUARK_HOOK_PAD_SEND_EVENT_PRE,
+  GST_TRACER_QUARK_HOOK_PAD_SEND_EVENT_POST,
+  /**
+   * GST_TRACER_QUARK_HOOK_MEMORY_INIT:
+   *
+   * Post-hook for memory initialization named "memory-init".
+   *
+   * Since: 1.26
+   */
+  GST_TRACER_QUARK_HOOK_MEMORY_INIT,
+  /**
+   * GST_TRACER_QUARK_HOOK_MEMORY_FREE_PRE:
+   *
+   * Pre-hook for memory freeing named "memory-free-pre".
+   *
+   * Since: 1.26
+   */
+  GST_TRACER_QUARK_HOOK_MEMORY_FREE_PRE,
+  /**
+   * GST_TRACER_QUARK_HOOK_MEMORY_FREE_POST:
+   *
+   * Post-hook for memory freeing named "memory-free-post".
+   *
+   * Since: 1.26
+   */
+  GST_TRACER_QUARK_HOOK_MEMORY_FREE_POST,
   GST_TRACER_QUARK_MAX
 } GstTracerQuarkId;
 
@@ -234,7 +260,12 @@ typedef void (*GstTracerHookPadPullRangePost) (GObject *self, GstClockTime ts,
  * @pad: the pad
  * @event: the event
  *
- * Pre-hook for gst_pad_push_event() named "pad-push-event-pre".
+ * Pre-hook for when an event is pushed through a pad, named
+ * "pad-push-event-pre".
+ *
+ * Called by gst_pad_push_event(). Also called by functions other than
+ * gst_pad_push_event() that call gst_pad_push_event_unchecked() directly,
+ * namely push_sticky() and check_sticky().
  */
 typedef void (*GstTracerHookPadPushEventPre) (GObject *self, GstClockTime ts,
     GstPad *pad, GstEvent *event);
@@ -250,7 +281,12 @@ typedef void (*GstTracerHookPadPushEventPre) (GObject *self, GstClockTime ts,
  * @pad: the pad
  * @res: the result of gst_pad_push_event()
  *
- * Post-hook for gst_pad_push_event() named "pad-push-event-post".
+ * Post-hook for when an event has been pushed through a pad, named
+ * "pad-push-event-post".
+ *
+ * Called by gst_pad_push_event(). Also called by functions other than
+ * gst_pad_push_event() that call gst_pad_push_event_unchecked() directly,
+ * namely push_sticky() and check_sticky().
  */
 typedef void (*GstTracerHookPadPushEventPost) (GObject *self, GstClockTime ts,
     GstPad *pad, gboolean res);
@@ -259,6 +295,38 @@ typedef void (*GstTracerHookPadPushEventPost) (GObject *self, GstClockTime ts,
     GstTracerHookPadPushEventPost, (GST_TRACER_ARGS, pad, res)); \
 }G_STMT_END
 
+/**
+ * GstTracerHookPadSendEventPre:
+ * @self: the tracer instance
+ * @ts: the current timestamp
+ * @pad: the pad
+ * @event: the event
+    *
+ * Pre-hook for gst_pad_send_event_unchecked() named "pad-send-event-pre".
+ */
+typedef void (*GstTracerHookPadSendEventPre) (GObject *self, GstClockTime ts,
+    GstPad *pad, GstEvent *event);
+#define GST_TRACER_PAD_SEND_EVENT_PRE(pad, event) G_STMT_START{ \
+  GST_TRACER_DISPATCH(GST_TRACER_QUARK(HOOK_PAD_SEND_EVENT_PRE), \
+    GstTracerHookPadSendEventPre, (GST_TRACER_ARGS, pad, event)); \
+}G_STMT_END
+
+/**
+ * GstTracerHookPadSendEventPost:
+ * @self: the tracer instance
+ * @ts: the current timestamp
+ * @pad: the pad
+ * @res: the result of gst_pad_send_event_unchecked()
+ *
+ * Post-hook for gst_pad_send_event_unchecked() named "pad-send-event-post".
+ */
+typedef void (*GstTracerHookPadSendEventPost) (GObject *self, GstClockTime ts,
+    GstPad *pad, GstFlowReturn res);
+#define GST_TRACER_PAD_SEND_EVENT_POST(pad, res) G_STMT_START{ \
+  GST_TRACER_DISPATCH(GST_TRACER_QUARK(HOOK_PAD_SEND_EVENT_POST), \
+    GstTracerHookPadSendEventPost, (GST_TRACER_ARGS, pad, res)); \
+}G_STMT_END
+
 /**
  * GstTracerHookPadQueryPre:
  * @self: the tracer instance
@@ -839,6 +907,79 @@ typedef void (*GstTracerHookPadChainListPost) (GObject *self, GstClockTime ts,
     GstTracerHookPadChainListPost, (GST_TRACER_ARGS, pad, res)); \
 }G_STMT_END
 
+/**
+ * GstTracerHookMemoryInit:
+ * @self: the tracer instance
+ * @ts: the current timestamp
+ * @mem:  The GstMemory that was initialized
+ *
+ * Hook for memory initialization named "memory-init".
+ *
+ * Since: 1.26
+ */
+typedef void (*GstTracerHookMemoryInit) (GObject *self, GstClockTime ts,
+    GstMemory *mem);
+/**
+ * GST_TRACER_MEMORY_INIT:
+ * @mem: a #GstMemory
+ *
+ * Dispatches the "memory-init" hook.
+ *
+ * Since: 1.26
+ */
+#define GST_TRACER_MEMORY_INIT(mem) G_STMT_START{ \
+  GST_TRACER_DISPATCH(GST_TRACER_QUARK(HOOK_MEMORY_INIT), \
+    GstTracerHookMemoryInit, (GST_TRACER_ARGS, mem)); \
+}G_STMT_END
+
+/**
+ * GstTracerHookMemoryFreePre:
+ * @self: the tracer instance
+ * @ts: the current timestamp
+ * @mem: the memory object for which the memory will be freed.
+ *
+ * Pre-hook for memory freeing named "memory-free-pre".
+ *
+ * Since: 1.26
+ */
+typedef void (*GstTracerHookMemoryFreePre) (GObject *self, GstClockTime ts, GstMemory *mem);
+/**
+ * GST_TRACER_MEMORY_FREE_PRE:
+ * @mem: the memory object
+ *
+ * Dispatches the "memory-free-pre" hook.
+ *
+ * Since: 1.26
+ */
+#define GST_TRACER_MEMORY_FREE_PRE(mem) G_STMT_START{ \
+  GST_TRACER_DISPATCH(GST_TRACER_QUARK(HOOK_MEMORY_FREE_PRE), \
+    GstTracerHookMemoryFreePre, (GST_TRACER_ARGS, mem)); \
+}G_STMT_END
+
+/**
+ * GstTracerHookMemoryFreePost:
+ * @self: the tracer instance
+ * @ts: the current timestamp
+ * @mem: pointer to the memory object that has been freed
+ *
+ * Post-hook for memory freeing named "memory-free-post".
+ *
+ * Since: 1.26
+ */
+typedef void (*GstTracerHookMemoryFreePost) (GObject *self, GstClockTime ts, GstMemory *mem);
+/**
+ * GST_TRACER_MEMORY_FREE_POST:
+ * @mem: pointer to the memory object that has been freed
+ *
+ * Dispatches the "memory-free-post" hook.
+ *
+ * Since: 1.26
+ */
+#define GST_TRACER_MEMORY_FREE_POST(mem) G_STMT_START{ \
+  GST_TRACER_DISPATCH(GST_TRACER_QUARK(HOOK_MEMORY_FREE_POST), \
+    GstTracerHookMemoryFreePost, (GST_TRACER_ARGS, mem)); \
+}G_STMT_END
+
 #else /* !GST_DISABLE_GST_TRACER_HOOKS */
 
 static inline void
@@ -892,6 +1033,12 @@ _priv_gst_tracing_deinit (void)
 #define GST_TRACER_PAD_CHAIN_POST(pad, res)
 #define GST_TRACER_PAD_CHAIN_LIST_PRE(pad, list)
 #define GST_TRACER_PAD_CHAIN_LIST_POST(pad, res)
+#define GST_TRACER_PAD_SEND_EVENT_PRE(pad, event)
+#define GST_TRACER_PAD_SEND_EVENT_POST(pad, res)
+#define GST_TRACER_MEMORY_INIT(mem)
+#define GST_TRACER_MEMORY_FREE_PRE(mem)
+#define GST_TRACER_MEMORY_FREE_POST(mem)
+
 
 #endif /* GST_DISABLE_GST_TRACER_HOOKS */
 
diff --git a/gst/gsturi.c b/gst/gsturi.c
index b071de7..ae9b7b3 100644
--- a/gst/gsturi.c
+++ b/gst/gsturi.c
@@ -2028,8 +2028,9 @@ gst_uri_to_string_with_keys (const GstUri * uri, const GList * keys)
     g_string_append_printf (uri_str, "%s:", uri->scheme);
 
   if (uri->userinfo != NULL || uri->host != NULL ||
-      uri->port != GST_URI_NO_PORT)
+      uri->port != GST_URI_NO_PORT || !g_strcmp0 (uri->scheme, "file")) {
     g_string_append (uri_str, "//");
+  }
 
   if (uri->userinfo != NULL) {
     escaped = _gst_uri_escape_userinfo (uri->userinfo);
diff --git a/gst/gstutils.c b/gst/gstutils.c
index 99e95dd..8d81d04 100644
--- a/gst/gstutils.c
+++ b/gst/gstutils.c
@@ -44,7 +44,6 @@
 #include "gstinfo.h"
 #include "gstparse.h"
 #include "gstvalue.h"
-#include "gstquark.h"
 #include <glib/gi18n-lib.h>
 #include "glib-compat-private.h"
 #include <math.h>
@@ -3542,10 +3541,11 @@ gst_util_get_timestamp (void)
  * @array: the sorted input array
  * @num_elements: number of elements in the array
  * @element_size: size of every element in bytes
- * @search_func: (scope call): function to compare two elements, @search_data will always be passed as second argument
+ * @search_func: (scope call) (closure user_data): function to compare two
+ *    elements, @search_data will always be passed as second argument
  * @mode: search mode that should be used
  * @search_data: element that should be found
- * @user_data: (closure): data to pass to @search_func
+ * @user_data: data to pass to @search_func
  *
  * Searches inside @array for @search_data by using the comparison function
  * @search_func. @array must be sorted ascending.
@@ -3926,6 +3926,86 @@ gst_util_fraction_multiply (gint a_n, gint a_d, gint b_n, gint b_d,
   return TRUE;
 }
 
+/**
+ * gst_util_fraction_multiply_int64:
+ * @a_n: Numerator of first value
+ * @a_d: Denominator of first value
+ * @b_n: Numerator of second value
+ * @b_d: Denominator of second value
+ * @res_n: (out): Pointer to #gint to hold the result numerator
+ * @res_d: (out): Pointer to #gint to hold the result denominator
+ *
+ * Multiplies the fractions @a_n/@a_d and @b_n/@b_d and stores
+ * the result in @res_n and @res_d.
+ *
+ * Returns: %FALSE on overflow, %TRUE otherwise.
+ *
+ * Since: 1.26
+ */
+gboolean
+gst_util_fraction_multiply_int64 (gint64 a_n, gint64 a_d, gint64 b_n,
+    gint64 b_d, gint64 * res_n, gint64 * res_d)
+{
+  gint gcd;
+  gint64 initial_a_n, initial_a_d;
+
+  initial_a_n = a_n;
+  initial_a_d = a_d;
+
+  g_return_val_if_fail (res_n != NULL, FALSE);
+  g_return_val_if_fail (res_d != NULL, FALSE);
+  g_return_val_if_fail (a_d != 0, FALSE);
+  g_return_val_if_fail (b_d != 0, FALSE);
+
+  /* early out if either is 0, as its gcd would be 0 */
+  if (a_n == 0 || b_n == 0) {
+    *res_n = 0;
+    *res_d = 1;
+    return TRUE;
+  }
+
+  gcd = gst_util_greatest_common_divisor_int64 (a_n, a_d);
+  a_n /= gcd;
+  a_d /= gcd;
+
+  gcd = gst_util_greatest_common_divisor_int64 (b_n, b_d);
+  b_n /= gcd;
+  b_d /= gcd;
+
+  gcd = gst_util_greatest_common_divisor_int64 (a_n, b_d);
+  a_n /= gcd;
+  b_d /= gcd;
+
+  gcd = gst_util_greatest_common_divisor_int64 (a_d, b_n);
+  a_d /= gcd;
+  b_n /= gcd;
+
+  /* This would result in overflow */
+  if (a_n != 0 && G_MAXINT64 / ABS (a_n) < ABS (b_n)) {
+    gcd = gst_util_greatest_common_divisor_int64 (initial_a_n, initial_a_d);
+    GST_INFO ("gcd(a_n(%" G_GINT64_FORMAT "), a_d(%" G_GINT64_FORMAT ")) = %d",
+        initial_a_n, initial_a_d, gcd);
+    GST_INFO ("Integer overflow in numerator multiplication: %" G_GINT64_FORMAT
+        " * %" G_GINT64_FORMAT " > G_MAXINT64", ABS (a_n), ABS (b_n));
+    return FALSE;
+  }
+  if (G_MAXINT64 / ABS (a_d) < ABS (b_d)) {
+    GST_ERROR ("Integer overflow in denominator multiplication: %"
+        G_GINT64_FORMAT " * %" G_GINT64_FORMAT " > G_MAXINT64", ABS (a_d),
+        ABS (b_d));
+    return FALSE;
+  }
+
+  *res_n = a_n * b_n;
+  *res_d = a_d * b_d;
+
+  gcd = gst_util_greatest_common_divisor_int64 (*res_n, *res_d);
+  *res_n /= gcd;
+  *res_d /= gcd;
+
+  return TRUE;
+}
+
 /**
  * gst_util_fraction_add:
  * @a_n: Numerator of first value
@@ -4518,6 +4598,51 @@ gst_util_ceil_log2 (guint32 v)
   return y;
 }
 
+/**
+ * gst_util_floor_log2:
+ * @v: a #guint32 value.
+ *
+ * Returns smallest integral value not bigger than log2(v).
+ *
+ * Returns: a computed #guint val.
+ *
+ * Since: 1.26
+ */
+guint
+gst_util_floor_log2 (guint32 v)
+{
+  guint32 result = 0;
+
+  g_return_val_if_fail (v != 0, -1);
+
+  if (v & 0xffff0000) {
+    v >>= 16;
+    result += 16;
+  }
+
+  if (v & 0xff00) {
+    v >>= 8;
+    result += 8;
+  }
+
+  if (v & 0xf0) {
+    v >>= 4;
+    result += 4;
+  }
+
+  if (v & 0xc) {
+    v >>= 2;
+    result += 2;
+  }
+
+  if (v & 0x2) {
+    v >>= 1;
+    result += 1;
+  }
+
+  return result;
+}
+
 /**
  * gst_calculate_linear_regression: (skip)
  * @xy: Pairs of (x,y) values
@@ -4771,6 +4896,10 @@ invalid:
   }
 }
 
+/* Initialized in _priv_gst_plugin_initialize(). */
+GQuark _priv_gst_plugin_api_quark;
+GQuark _priv_gst_plugin_api_flags_quark;
+
 /**
  * gst_type_mark_as_plugin_api:
  * @type: a GType
@@ -4792,8 +4921,8 @@ invalid:
 void
 gst_type_mark_as_plugin_api (GType type, GstPluginAPIFlags flags)
 {
-  g_type_set_qdata (type, GST_QUARK (PLUGIN_API), GINT_TO_POINTER (TRUE));
-  g_type_set_qdata (type, GST_QUARK (PLUGIN_API_FLAGS),
+  g_type_set_qdata (type, _priv_gst_plugin_api_quark, GINT_TO_POINTER (TRUE));
+  g_type_set_qdata (type, _priv_gst_plugin_api_flags_quark,
       GINT_TO_POINTER (flags));
 }
 
@@ -4813,11 +4942,12 @@ gboolean
 gst_type_is_plugin_api (GType type, GstPluginAPIFlags * flags)
 {
   gboolean ret =
-      !!GPOINTER_TO_INT (g_type_get_qdata (type, GST_QUARK (PLUGIN_API)));
+      !!GPOINTER_TO_INT (g_type_get_qdata (type, _priv_gst_plugin_api_quark));
 
   if (ret && flags) {
     *flags =
-        GPOINTER_TO_INT (g_type_get_qdata (type, GST_QUARK (PLUGIN_API_FLAGS)));
+        GPOINTER_TO_INT (g_type_get_qdata (type,
+            _priv_gst_plugin_api_flags_quark));
   }
 
   return ret;
diff --git a/gst/gstutils.h b/gst/gstutils.h
index f42dab8..e6e5449 100644
--- a/gst/gstutils.h
+++ b/gst/gstutils.h
@@ -1222,6 +1222,9 @@ GST_API
 gboolean      gst_util_fraction_multiply        (gint a_n, gint a_d, gint b_n, gint b_d,
                                                  gint *res_n, gint *res_d);
 GST_API
+gboolean      gst_util_fraction_multiply_int64  (gint64 a_n, gint64 a_d, gint64 b_n, gint64 b_d,
+                                                 gint64 *res_n, gint64 *res_d);
+GST_API
 gboolean      gst_util_fraction_add             (gint a_n, gint a_d, gint b_n, gint b_d,
                                                  gint *res_n, gint *res_d);
 GST_API
@@ -1243,6 +1246,9 @@ gboolean      gst_type_is_plugin_api            (GType type, GstPluginAPIFlags *
 GST_API
 guint         gst_util_ceil_log2                (guint32 v);
 
+GST_API
+guint         gst_util_floor_log2               (guint32 v);
+
 GST_API
 gint          gst_util_filename_compare        (const gchar *a, const gchar *b);
 
diff --git a/gst/gstvalue.c b/gst/gstvalue.c
index 315bcfb..86cb5a7 100644
--- a/gst/gstvalue.c
+++ b/gst/gstvalue.c
@@ -46,7 +46,6 @@
 #include <gst/gst.h>
 #include <gobject/gvaluecollector.h>
 #include "gstutils.h"
-#include "gstquark.h"
 
 /* GstValueUnionFunc:
  * @dest: a #GValue for the result
@@ -101,6 +100,8 @@ static gboolean _priv_gst_value_parse_list (gchar * s, gchar ** after,
     GValue * value, GType type, GParamSpec * pspec);
 static gboolean _priv_gst_value_parse_array (gchar * s, gchar ** after,
     GValue * value, GType type, GParamSpec * pspec);
+static gboolean _priv_gst_value_parse_strv (const gchar * s,
+    const gchar ** after, GValue * dest);
 
 typedef struct _GstValueUnionInfo GstValueUnionInfo;
 struct _GstValueUnionInfo
@@ -354,7 +355,7 @@ _priv_gst_value_serialize_any_list (const GValue * value, const gchar * begin,
   GstValueList *vlist = value->data[0].v_pointer;
   GString *s;
   GValue *v;
-  gchar *s_val;
+  gchar *s_val = NULL;
   guint alen = vlist->len;
 
   /* estimate minimum string length to minimise re-allocs in GString */
@@ -2812,8 +2813,13 @@ _priv_gst_value_parse_value (gchar * str,
     g_value_init (value, GST_TYPE_LIST);
     ret = _priv_gst_value_parse_list (s, &s, value, type, pspec);
   } else if (*s == '<') {
-    g_value_init (value, GST_TYPE_ARRAY);
-    ret = _priv_gst_value_parse_array (s, &s, value, type, pspec);
+    if (type == G_TYPE_STRV) {
+      g_value_init (value, G_TYPE_STRV);
+      ret = _priv_gst_value_parse_strv (s, (const gchar **) &s, value);
+    } else {
+      g_value_init (value, GST_TYPE_ARRAY);
+      ret = _priv_gst_value_parse_array (s, &s, value, type, pspec);
+    }
   } else {
     value_s = s;
 
@@ -2893,18 +2899,18 @@ gst_value_serialize_segment_internal (const GValue * value, gboolean escape)
   gchar *t, *res;
   GstStructure *s;
 
-  s = gst_structure_new_id (GST_QUARK (SEGMENT),
-      GST_QUARK (FLAGS), GST_TYPE_SEGMENT_FLAGS, seg->flags,
-      GST_QUARK (RATE), G_TYPE_DOUBLE, seg->rate,
-      GST_QUARK (APPLIED_RATE), G_TYPE_DOUBLE, seg->applied_rate,
-      GST_QUARK (FORMAT), GST_TYPE_FORMAT, seg->format,
-      GST_QUARK (BASE), G_TYPE_UINT64, seg->base,
-      GST_QUARK (OFFSET), G_TYPE_UINT64, seg->offset,
-      GST_QUARK (START), G_TYPE_UINT64, seg->start,
-      GST_QUARK (STOP), G_TYPE_UINT64, seg->stop,
-      GST_QUARK (TIME), G_TYPE_UINT64, seg->time,
-      GST_QUARK (POSITION), G_TYPE_UINT64, seg->position,
-      GST_QUARK (DURATION), G_TYPE_UINT64, seg->duration, NULL);
+  s = gst_structure_new_static_str ("segment",
+      "flags", GST_TYPE_SEGMENT_FLAGS, seg->flags,
+      "rate", G_TYPE_DOUBLE, seg->rate,
+      "applied-rate", G_TYPE_DOUBLE, seg->applied_rate,
+      "format", GST_TYPE_FORMAT, seg->format,
+      "base", G_TYPE_UINT64, seg->base,
+      "offset", G_TYPE_UINT64, seg->offset,
+      "start", G_TYPE_UINT64, seg->start,
+      "stop", G_TYPE_UINT64, seg->stop,
+      "time", G_TYPE_UINT64, seg->time,
+      "position", G_TYPE_UINT64, seg->position,
+      "duration", G_TYPE_UINT64, seg->duration, NULL);
 
   t = gst_structure_to_string (s);
   if (escape) {
@@ -2953,18 +2959,18 @@ gst_value_deserialize_segment_internal (GValue * dest, const gchar * s,
   if (G_UNLIKELY (str == NULL))
     return FALSE;
 
-  res = gst_structure_id_get (str,
-      GST_QUARK (FLAGS), GST_TYPE_SEGMENT_FLAGS, &seg.flags,
-      GST_QUARK (RATE), G_TYPE_DOUBLE, &seg.rate,
-      GST_QUARK (APPLIED_RATE), G_TYPE_DOUBLE, &seg.applied_rate,
-      GST_QUARK (FORMAT), GST_TYPE_FORMAT, &seg.format,
-      GST_QUARK (BASE), G_TYPE_UINT64, &seg.base,
-      GST_QUARK (OFFSET), G_TYPE_UINT64, &seg.offset,
-      GST_QUARK (START), G_TYPE_UINT64, &seg.start,
-      GST_QUARK (STOP), G_TYPE_UINT64, &seg.stop,
-      GST_QUARK (TIME), G_TYPE_UINT64, &seg.time,
-      GST_QUARK (POSITION), G_TYPE_UINT64, &seg.position,
-      GST_QUARK (DURATION), G_TYPE_UINT64, &seg.duration, NULL);
+  res = gst_structure_get (str,
+      "flags", GST_TYPE_SEGMENT_FLAGS, &seg.flags,
+      "rate", G_TYPE_DOUBLE, &seg.rate,
+      "applied-rate", G_TYPE_DOUBLE, &seg.applied_rate,
+      "format", GST_TYPE_FORMAT, &seg.format,
+      "base", G_TYPE_UINT64, &seg.base,
+      "offset", G_TYPE_UINT64, &seg.offset,
+      "start", G_TYPE_UINT64, &seg.start,
+      "stop", G_TYPE_UINT64, &seg.stop,
+      "time", G_TYPE_UINT64, &seg.time,
+      "position", G_TYPE_UINT64, &seg.position,
+      "duration", G_TYPE_UINT64, &seg.duration, NULL);
   gst_structure_free (str);
 
   if (res)
@@ -4537,6 +4543,9 @@ gst_value_is_subset (const GValue * value1, const GValue * value2)
     if (type1 == GST_TYPE_LIST)
       return gst_value_is_subset_list_list (value1, value2);
     return gst_value_is_subset_list (value1, value2);
+  } else if (type2 == GST_TYPE_CAPS) {
+    return gst_caps_is_subset (gst_value_get_caps (value1),
+        gst_value_get_caps (value2));
   }
 
   /*
@@ -4736,13 +4745,14 @@ gst_value_union_flagset_flagset (GValue * dest, const GValue * src1,
 
 /* iterating over the result taking the union with the other structure's value */
 static gboolean
-structure_field_union_into (GQuark field_id, GValue * val, gpointer user_data)
+structure_field_union_into (const GstIdStr * field, GValue * val,
+    gpointer user_data)
 {
   GstStructure *other = user_data;
   const GValue *other_value;
   GValue res_value = G_VALUE_INIT;
 
-  other_value = gst_structure_id_get_value (other, field_id);
+  other_value = gst_structure_id_str_get_value (other, field);
   /* no value in the other struct, just keep this value */
   if (!other_value)
     return TRUE;
@@ -4757,15 +4767,15 @@ structure_field_union_into (GQuark field_id, GValue * val, gpointer user_data)
 
 /* iterating over the other source structure adding missing values */
 static gboolean
-structure_field_union_from (GQuark field_id, const GValue * other_val,
+structure_field_union_from (const GstIdStr * field, const GValue * other_val,
     gpointer user_data)
 {
   GstStructure *result = user_data;
   const GValue *result_value;
 
-  result_value = gst_structure_id_get_value (result, field_id);
+  result_value = gst_structure_id_str_get_value (result, field);
   if (!result_value)
-    gst_structure_id_set_value (result, field_id, other_val);
+    gst_structure_id_str_set_value (result, field, other_val);
 
   return TRUE;
 }
@@ -4792,12 +4802,13 @@ gst_value_union_structure_structure (GValue * dest, const GValue * src1,
 
   result = gst_structure_copy (s1);
   ret =
-      gst_structure_map_in_place (result, structure_field_union_into,
+      gst_structure_map_in_place_id_str (result, structure_field_union_into,
       (gpointer) s2);
   if (!ret)
     goto out;
   ret =
-      gst_structure_foreach (s2, structure_field_union_from, (gpointer) result);
+      gst_structure_foreach_id_str (s2, structure_field_union_from,
+      (gpointer) result);
 
   if (ret) {
     g_value_init (dest, GST_TYPE_STRUCTURE);
@@ -6349,6 +6360,28 @@ gst_value_can_intersect (const GValue * value1, const GValue * value2)
   return gst_value_can_compare_unchecked (value1, value2);
 }
 
+static gboolean
+gst_value_intersect_caps (GValue * dest, const GValue * value1, const GValue *
+    value2)
+{
+  gboolean empty;
+  GstCaps *icaps;
+  GstCaps *caps1 = g_value_get_boxed (value1);
+  GstCaps *caps2 = g_value_get_boxed (value2);
+  g_return_val_if_fail (caps1 != NULL, FALSE);
+  g_return_val_if_fail (caps2 != NULL, FALSE);
+
+  icaps = gst_caps_intersect (caps1, caps2);
+  empty = gst_caps_is_empty (icaps);
+
+  if (dest != NULL) {
+    g_value_init (dest, GST_TYPE_CAPS);
+    gst_value_set_caps (dest, icaps);
+  }
+  gst_caps_unref (icaps);
+  return !empty;
+}
+
 /**
  * gst_value_intersect:
  * @dest: (out caller-allocates) (transfer full) (allow-none):
@@ -6409,6 +6442,8 @@ gst_value_intersect (GValue * dest, const GValue * value1,
       return gst_value_intersect_flagset_flagset (dest, value1, value2);
     if (type1 == GST_TYPE_STRUCTURE)
       return gst_value_intersect_structure_structure (dest, value1, value2);
+    if (type1 == GST_TYPE_CAPS)
+      return gst_value_intersect_caps (dest, value1, value2);
   } else {
     /* Different type comparison */
     len = gst_value_intersect_funcs->len;
@@ -6819,7 +6854,7 @@ gst_value_deserialize_with_pspec (GValue * dest, const gchar * src,
 }
 
 static gboolean
-structure_field_is_fixed (GQuark field_id, const GValue * val,
+structure_field_is_fixed (const GstIdStr * field, const GValue * val,
     gpointer user_data)
 {
   return gst_value_is_fixed (val);
@@ -6867,7 +6902,7 @@ gst_value_is_fixed (const GValue * value)
     /* Flagsets are only fixed if there are no 'don't care' bits */
     return (gst_value_get_flagset_mask (value) == GST_FLAG_SET_MASK_EXACT);
   } else if (GST_VALUE_HOLDS_STRUCTURE (value)) {
-    return gst_structure_foreach (gst_value_get_structure (value),
+    return gst_structure_foreach_id_str (gst_value_get_structure (value),
         structure_field_is_fixed, NULL);
   }
   return gst_type_is_fixed (type);
@@ -7486,6 +7521,7 @@ gst_value_serialize_g_date_time (const GValue * val)
 static gboolean
 gst_value_deserialize_g_date_time (GValue * dest, const gchar * s)
 {
+  GstDateTime *gst_datetime;
   GDateTime *datetime;
 
   if (!s || strcmp (s, "null") == 0) {
@@ -7493,8 +7529,13 @@ gst_value_deserialize_g_date_time (GValue * dest, const gchar * s)
   }
 
   /* The Gstreamer iso8601 parser is a bit more forgiving */
-  datetime =
-      gst_date_time_to_g_date_time (gst_date_time_new_from_iso8601_string (s));
+  gst_datetime = gst_date_time_new_from_iso8601_string (s);
+  if (gst_datetime == NULL) {
+    GST_WARNING ("Failed to deserialize date time string '%s'", s);
+    return FALSE;
+  }
+  datetime = gst_date_time_to_g_date_time (gst_datetime);
+  gst_date_time_unref (gst_datetime);
   if (datetime != NULL) {
     g_value_take_boxed (dest, datetime);
     return TRUE;
@@ -7543,12 +7584,12 @@ gst_value_deserialize_bytes (GValue * dest, const gchar * s)
   guint8 *data;
 
   if (!s) {
-    g_value_set_boxed (dest, g_bytes_new (NULL, 0));
+    g_value_take_boxed (dest, g_bytes_new (NULL, 0));
     return TRUE;
   }
 
   data = g_base64_decode (s, &len);
-  g_value_set_boxed (dest, g_bytes_new_take (data, len));
+  g_value_take_boxed (dest, g_bytes_new_take (data, len));
   return TRUE;
 }
 
@@ -8043,6 +8084,30 @@ gst_value_compare_allocation_params (const GValue * value1,
   return GST_VALUE_UNORDERED;
 }
 
+static void
+gst_value_transform_allocation_params_string (const GValue * value1,
+    GValue * dest_value)
+{
+  GstAllocationParams *params = value1->data[0].v_pointer;
+  gchar *res;
+
+  if (params) {
+    GstStructure *s = NULL;
+
+    s = gst_structure_new_static_str ("GstAllocationParams",
+        "flags", GST_TYPE_MEMORY_FLAGS, params->flags,
+        "align", G_TYPE_UINT64, params->align,
+        "prefix", G_TYPE_UINT64, params->prefix,
+        "padding", G_TYPE_UINT64, params->padding, NULL);
+
+    res = gst_structure_to_string (s);
+    gst_structure_free (s);
+  } else {
+    res = g_strdup ("NULL");
+  }
+
+  dest_value->data[0].v_pointer = res;
+}
 
 /************
  * GObject *
@@ -8081,6 +8146,127 @@ gst_value_transform_object_string (const GValue * src_value,
   dest_value->data[0].v_pointer = str;
 }
 
+/*********
+ * GStrv *
+ *********/
+
+static gchar *
+gst_value_serialize_strv (const GValue * value)
+{
+  const gchar **strv = g_value_get_boxed (value);
+  GString *str = g_string_new ("<");
+
+  while (*strv != NULL) {
+    const gchar *s = *strv;
+
+    /* Add separator if it's not the first string */
+    if (str->len > 1)
+      g_string_append_c (str, ',');
+
+    g_string_append_c (str, '\"');
+
+    /* Escape \ to \\ and " to \" */
+    while (*s != '\0') {
+      if (*s == '\"' || *s == '\\')
+        g_string_append_c (str, '\\');
+      g_string_append_c (str, *s);
+      s++;
+    }
+
+    g_string_append_c (str, '\"');
+
+    strv++;
+  }
+
+  g_string_append_c (str, '>');
+
+  return g_string_free (str, FALSE);
+}
+
+static gboolean
+_priv_gst_value_parse_strv (const gchar * s, const gchar ** after,
+    GValue * dest)
+{
+  /* Parse the format <"foo","bar"> with spaces allowed between delimiters,
+   * and \ for escaping. */
+  if (*s != '<')
+    return FALSE;
+  s++;
+
+  while (g_ascii_isspace (*s))
+    s++;
+
+  GPtrArray *strv = g_ptr_array_new_with_free_func (g_free);
+  while (*s != '>') {
+    if (*s != '\"')
+      goto error;
+    s++;
+
+    /* Find string end and check if we need to unescape it */
+    gboolean escaped = FALSE;
+    const gchar *start = s;
+    while (*s != '\"') {
+      if (*s == '\\') {
+        escaped = TRUE;
+        s++;
+      }
+      if (*s == '\0')
+        goto error;
+      s++;
+    }
+    s++;
+
+    /* Always copy the whole string and unescape inplace */
+    gchar *substr = g_strndup (start, s - start - 1);
+    if (escaped) {
+      gchar *p1 = substr;
+      const gchar *p2 = substr;
+      while (*p2 != '\0') {
+        if (*p2 == '\\')
+          p2++;
+        *p1 = *p2;
+        p1++;
+        p2++;
+      }
+      *p1 = '\0';
+    }
+
+    g_ptr_array_add (strv, substr);
+
+    while (g_ascii_isspace (*s))
+      s++;
+
+    if (*s == ',') {
+      s++;
+      while (g_ascii_isspace (*s))
+        s++;
+    }
+  }
+
+  g_ptr_array_add (strv, NULL);
+  g_value_take_boxed (dest, g_ptr_array_free (strv, FALSE));
+
+  *after = s + 1;
+
+  return TRUE;
+
+error:
+  g_ptr_array_free (strv, TRUE);
+  return FALSE;
+}
+
+static gboolean
+gst_value_deserialize_strv (GValue * dest, const gchar * s)
+{
+  /* If it's not starting with '<' assume it's a simple comma separated list
+   * with no escaping. This makes usage in gst-launch-1.0 easier. */
+  if (*s != '<') {
+    g_value_take_boxed (dest, g_strsplit (s, ",", -1));
+    return TRUE;
+  }
+  return _priv_gst_value_parse_strv (s, &s, dest);
+}
+
 static GTypeInfo _info = {
   0, NULL, NULL, NULL, NULL, NULL, 0, 0, NULL, NULL,
 };
@@ -8311,10 +8497,12 @@ _priv_gst_value_initialize (void)
   REGISTER_SERIALIZATION (gst_bitmask_get_type (), bitmask);
   REGISTER_SERIALIZATION (gst_structure_get_type (), structure);
   REGISTER_SERIALIZATION (gst_flagset_get_type (), flagset);
+  REGISTER_SERIALIZATION (G_TYPE_GTYPE, gtype);
 
   REGISTER_SERIALIZATION_NO_COMPARE (gst_segment_get_type (), segment);
   REGISTER_SERIALIZATION_NO_COMPARE (gst_caps_features_get_type (),
       caps_features);
+  REGISTER_SERIALIZATION_NO_COMPARE (G_TYPE_STRV, strv);
 
   REGISTER_SERIALIZATION_COMPARE_ONLY (gst_allocation_params_get_type (),
       allocation_params);
@@ -8322,26 +8510,18 @@ _priv_gst_value_initialize (void)
 
   REGISTER_SERIALIZATION_CONST (G_TYPE_DOUBLE, double);
   REGISTER_SERIALIZATION_CONST (G_TYPE_FLOAT, float);
-
   REGISTER_SERIALIZATION_CONST (G_TYPE_STRING, string);
   REGISTER_SERIALIZATION_CONST (G_TYPE_BOOLEAN, boolean);
   REGISTER_SERIALIZATION_CONST (G_TYPE_ENUM, enum);
-
   REGISTER_SERIALIZATION_CONST (G_TYPE_FLAGS, gflags);
-
   REGISTER_SERIALIZATION_CONST (G_TYPE_INT, int);
-
   REGISTER_SERIALIZATION_CONST (G_TYPE_INT64, int64);
   REGISTER_SERIALIZATION_CONST (G_TYPE_LONG, long);
-
   REGISTER_SERIALIZATION_CONST (G_TYPE_UINT, uint);
   REGISTER_SERIALIZATION_CONST (G_TYPE_UINT64, uint64);
   REGISTER_SERIALIZATION_CONST (G_TYPE_ULONG, ulong);
-
   REGISTER_SERIALIZATION_CONST (G_TYPE_UCHAR, uchar);
 
-  REGISTER_SERIALIZATION (G_TYPE_GTYPE, gtype);
-
   REGISTER_SERIALIZATION_WITH_PSPEC (gst_value_list_get_type (), value_list);
   REGISTER_SERIALIZATION_WITH_PSPEC (gst_value_array_get_type (), value_array);
 
@@ -8398,6 +8578,8 @@ _priv_gst_value_initialize (void)
       gst_value_transform_flagset_string);
   g_value_register_transform_func (G_TYPE_STRING, GST_TYPE_FLAG_SET,
       gst_value_transform_string_flagset);
+  g_value_register_transform_func (GST_TYPE_ALLOCATION_PARAMS, G_TYPE_STRING,
+      gst_value_transform_allocation_params_string);
 
   /* Only register intersection functions for *different* types.
    * Identical type intersection should be specified directly in
diff --git a/gst/gstvecdeque.c b/gst/gstvecdeque.c
new file mode 100644
index 0000000..88483a7
--- /dev/null
+++ b/gst/gstvecdeque.c
@@ -0,0 +1,996 @@
+/* GStreamer
+ * Copyright (C) 2009 Edward Hervey <bilboed@bilboed.com>
+ * Copyright (C) 2015 Tim-Philipp Müller <tim@centricular.com>
+ *
+ * gstvecdeque.c:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * SECTION:gstvecdeque
+ * @title: GstVecDeque
+ * @short_description: Array based double-ended queue object
+ *
+ * #GstVecDeque is an object that provides standard double-ended queue (deque)
+ * functionality based on an array instead of linked lists. This reduces the
+ * overhead caused by memory management by a large factor.
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+#include <gst/gst.h>
+#include "gstvecdeque.h"
+
+#include "glib-compat-private.h"
+
+#define gst_vec_deque_idx(a, i) \
+  ((a)->array + (((a)->head + (i)) % (a)->size) * (a)->elt_size)
+
+struct _GstVecDeque
+{
+  /* < private > */
+  guint8 *array;
+  gsize size;
+  gsize head;
+  gsize tail;
+  gsize length;
+  gsize elt_size;
+  gboolean struct_array;
+  GDestroyNotify clear_func;
+};
+
+typedef struct
+{
+  GCompareDataFunc func;
+  gpointer user_data;
+} QueueSortData;
+
+/**
+ * gst_vec_deque_new_for_struct: (skip)
+ * @struct_size: Size of each element (e.g. structure) in the array
+ * @initial_size: Initial size of the new queue
+ *
+ * Allocates a new #GstVecDeque object for elements (e.g. structures)
+ * of size @struct_size, with an initial queue size of @initial_size.
+ *
+ * Returns: a new #GstVecDeque object
+ *
+ * Since: 1.26
+ */
+GstVecDeque *
+gst_vec_deque_new_for_struct (gsize struct_size, gsize initial_size)
+{
+  GstVecDeque *array;
+
+  g_return_val_if_fail (struct_size > 0, NULL);
+
+  array = g_new (GstVecDeque, 1);
+  array->elt_size = struct_size;
+  array->size = initial_size;
+  array->array = g_malloc0_n (initial_size, struct_size);
+  array->head = 0;
+  array->tail = 0;
+  array->length = 0;
+  array->struct_array = TRUE;
+  array->clear_func = NULL;
+  return array;
+}
+
+/**
+ * gst_vec_deque_new: (skip)
+ * @initial_size: Initial size of the new queue
+ *
+ * Allocates a new #GstVecDeque object with an initial
+ * queue size of @initial_size.
+ *
+ * Returns: a new #GstVecDeque object
+ *
+ * Since: 1.26
+ */
+GstVecDeque *
+gst_vec_deque_new (gsize initial_size)
+{
+  GstVecDeque *array;
+
+  array = gst_vec_deque_new_for_struct (sizeof (gpointer), initial_size);
+  array->struct_array = FALSE;
+  return array;
+}
+
+/**
+ * gst_vec_deque_free: (skip)
+ * @array: a #GstVecDeque object
+ *
+ * Frees queue @array and all memory associated to it.
+ *
+ * Since: 1.26
+ */
+void
+gst_vec_deque_free (GstVecDeque * array)
+{
+  g_return_if_fail (array != NULL);
+  gst_vec_deque_clear (array);
+  g_free (array->array);
+  g_free (array);
+}
+
+/**
+ * gst_vec_deque_set_clear_func: (skip)
+ * @array: a #GstVecDeque object
+ * @clear_func: a function to clear an element of @array
+ *
+ * Sets a function to clear an element of @array.
+ *
+ * The @clear_func will be called when an element in the array
+ * data segment is removed and when the array is freed and data
+ * segment is deallocated as well. @clear_func will be passed a
+ * pointer to the element to clear, rather than the element itself.
+ *
+ * Note that in contrast with other uses of #GDestroyNotify
+ * functions, @clear_func is expected to clear the contents of
+ * the array element it is given, but not free the element itself.
+ *
+ * Since: 1.26
+ */
+void
+gst_vec_deque_set_clear_func (GstVecDeque * array, GDestroyNotify clear_func)
+{
+  g_return_if_fail (array != NULL);
+  array->clear_func = clear_func;
+}
+
+static void
+gst_vec_deque_clear_idx (GstVecDeque * array, gsize idx)
+{
+  gsize pos;
+
+  if (!array->clear_func)
+    return;
+
+  pos = (idx + array->head) % array->size;
+  if (array->struct_array)
+    array->clear_func (array->array + pos * array->elt_size);
+  else
+    array->clear_func (*(gpointer *) (array->array + pos * array->elt_size));
+}
+
+/**
+ * gst_vec_deque_clear: (skip)
+ * @array: a #GstVecDeque object
+ *
+ * Clears queue @array and frees all memory associated to it.
+ *
+ * Since: 1.26
+ */
+void
+gst_vec_deque_clear (GstVecDeque * array)
+{
+  g_return_if_fail (array != NULL);
+
+  if (array->clear_func != NULL) {
+    gsize i;
+
+    for (i = 0; i < array->length; i++) {
+      gst_vec_deque_clear_idx (array, i);
+    }
+  }
+
+  array->head = 0;
+  array->tail = 0;
+  array->length = 0;
+}
+
+/**
+ * gst_vec_deque_pop_head_struct: (skip)
+ * @array: a #GstVecDeque object
+ *
+ * Returns the head of the queue @array and removes it from the queue.
+ *
+ * Returns: (nullable): pointer to element or struct, or NULL if @array was empty. The
+ *    data pointed to by the returned pointer stays valid only as long as
+ *    the queue array is not modified further!
+ *
+ * Since: 1.26
+ */
+gpointer
+gst_vec_deque_pop_head_struct (GstVecDeque * array)
+{
+  gpointer p_struct;
+  g_return_val_if_fail (array != NULL, NULL);
+  /* empty array */
+  if (G_UNLIKELY (array->length == 0))
+    return NULL;
+
+  p_struct = array->array + (array->elt_size * array->head);
+
+  array->head++;
+  array->head %= array->size;
+  array->length--;
+
+  return p_struct;
+}
+
+/**
+ * gst_vec_deque_pop_head: (skip)
+ * @array: a #GstVecDeque object
+ *
+ * Returns and head of the queue @array and removes
+ * it from the queue.
+ *
+ * Returns: The head of the queue
+ *
+ * Since: 1.26
+ */
+gpointer
+gst_vec_deque_pop_head (GstVecDeque * array)
+{
+  gpointer ret;
+  g_return_val_if_fail (array != NULL, NULL);
+
+  /* empty array */
+  if (G_UNLIKELY (array->length == 0))
+    return NULL;
+
+  ret = *(gpointer *) (array->array + (sizeof (gpointer) * array->head));
+  array->head++;
+  array->head %= array->size;
+  array->length--;
+  return ret;
+}
+
+/**
+ * gst_vec_deque_peek_head_struct: (skip)
+ * @array: a #GstVecDeque object
+ *
+ * Returns the head of the queue @array without removing it from the queue.
+ *
+ * Returns: (nullable): pointer to element or struct, or NULL if @array was empty. The
+ *    data pointed to by the returned pointer stays valid only as long as
+ *    the queue array is not modified further!
+ *
+ * Since: 1.26
+ */
+gpointer
+gst_vec_deque_peek_head_struct (GstVecDeque * array)
+{
+  g_return_val_if_fail (array != NULL, NULL);
+  /* empty array */
+  if (G_UNLIKELY (array->length == 0))
+    return NULL;
+
+  return array->array + (array->elt_size * array->head);
+}
+
+/**
+ * gst_vec_deque_peek_head: (skip)
+ * @array: a #GstVecDeque object
+ *
+ * Returns the head of the queue @array and does not
+ * remove it from the queue.
+ *
+ * Returns: The head of the queue
+ *
+ * Since: 1.26
+ */
+gpointer
+gst_vec_deque_peek_head (GstVecDeque * array)
+{
+  g_return_val_if_fail (array != NULL, NULL);
+  /* empty array */
+  if (G_UNLIKELY (array->length == 0))
+    return NULL;
+
+  return *(gpointer *) (array->array + (sizeof (gpointer) * array->head));
+}
+
+/**
+ * gst_vec_deque_peek_nth: (skip)
+ *
+ * Returns the item at @idx in @array, but does not remove it from the queue.
+ *
+ * Returns: (nullable): The item, or %NULL if @idx was out of bounds
+ *
+ * Since: 1.26
+ */
+gpointer
+gst_vec_deque_peek_nth (GstVecDeque * array, gsize idx)
+{
+  g_return_val_if_fail (array != NULL, NULL);
+  g_return_val_if_fail (idx < array->length, NULL);
+
+  idx = (array->head + idx) % array->size;
+
+  return *(gpointer *) (array->array + (sizeof (gpointer) * idx));
+}
+
+/**
+ * gst_vec_deque_peek_nth_struct: (skip)
+ *
+ * Returns the item at @idx in @array, but does not remove it from the queue.
+ *
+ * Returns: (nullable): The item, or %NULL if @idx was out of bounds
+ *
+ * Since: 1.26
+ */
+gpointer
+gst_vec_deque_peek_nth_struct (GstVecDeque * array, gsize idx)
+{
+  g_return_val_if_fail (array != NULL, NULL);
+  g_return_val_if_fail (idx < array->length, NULL);
+
+  idx = (array->head + idx) % array->size;
+
+  return array->array + (array->elt_size * idx);
+}
+
+static void
+gst_vec_deque_do_expand (GstVecDeque * array)
+{
+  gsize elt_size = array->elt_size;
+  /* newsize is 50% bigger */
+  gsize oldsize = array->size;
+  gsize newsize;
+
+  if (!g_size_checked_mul (&newsize, oldsize, 2))
+    g_error ("growing the queue array would overflow");
+  newsize = MAX (newsize, 16);
+
+  /* copy over data */
+  if (array->tail != 0) {
+    guint8 *array2 = NULL;
+    gsize t1 = 0;
+    gsize t2 = 0;
+
+    array2 = g_malloc0_n (newsize, elt_size);
+    t1 = array->head;
+    t2 = oldsize - array->head;
+
+    /* [0-----TAIL][HEAD------SIZE]
+     *
+     * We want to end up with
+     * [HEAD------------------TAIL][----FREEDATA------NEWSIZE]
+     *
+     * 1) move [HEAD-----SIZE] part to beginning of new array
+     * 2) move [0-------TAIL] part new array, after previous part
+     */
+
+    memcpy (array2, array->array + (elt_size * (gsize) array->head),
+        t2 * elt_size);
+    memcpy (array2 + t2 * elt_size, array->array, t1 * elt_size);
+
+    g_free (array->array);
+    array->array = array2;
+    array->head = 0;
+  } else {
+    /* Fast path, we just need to grow the array */
+    array->array = g_realloc_n (array->array, newsize, elt_size);
+    memset (array->array + elt_size * oldsize, 0,
+        elt_size * (newsize - oldsize));
+  }
+  array->tail = oldsize;
+  array->size = newsize;
+}
+
+/**
+ * gst_vec_deque_push_tail_struct: (skip)
+ * @array: a #GstVecDeque object
+ * @p_struct: address of element or structure to push to the tail of the queue
+ *
+ * Pushes the element at address @p_struct to the tail of the queue @array
+ * (Copies the contents of a structure of the struct_size specified when
+ * creating the queue into the array).
+ *
+ * Since: 1.26
+ */
+void
+gst_vec_deque_push_tail_struct (GstVecDeque * array, gpointer p_struct)
+{
+  gsize elt_size;
+
+  g_return_if_fail (p_struct != NULL);
+  g_return_if_fail (array != NULL);
+  elt_size = array->elt_size;
+
+  /* Check if we need to make room */
+  if (G_UNLIKELY (array->length == array->size))
+    gst_vec_deque_do_expand (array);
+
+  memcpy (array->array + elt_size * array->tail, p_struct, elt_size);
+  array->tail++;
+  array->tail %= array->size;
+  array->length++;
+}
+
+/**
+ * gst_vec_deque_push_tail: (skip)
+ * @array: a #GstVecDeque object
+ * @data: object to push
+ *
+ * Pushes @data to the tail of the queue @array.
+ *
+ * Since: 1.26
+ */
+void
+gst_vec_deque_push_tail (GstVecDeque * array, gpointer data)
+{
+  g_return_if_fail (array != NULL);
+
+  /* Check if we need to make room */
+  if (G_UNLIKELY (array->length == array->size))
+    gst_vec_deque_do_expand (array);
+
+  *(gpointer *) (array->array + sizeof (gpointer) * array->tail) = data;
+  array->tail++;
+  array->tail %= array->size;
+  array->length++;
+}
+
+/* Moves all elements in the queue placed after the given position in the internal array */
+static void
+gst_vec_deque_move_data_after_position (GstVecDeque * array, gsize pos)
+{
+  gsize elt_size = array->elt_size;
+
+  /* If the array does not wrap around OR if it does, but we're inserting past that point */
+  if (array->head < array->tail ||
+      (array->head >= array->tail && pos < array->head)) {
+    memmove (array->array + (pos + 1) * elt_size, array->array + pos * elt_size,
+        (array->tail - pos) * elt_size);
+    return;
+  }
+
+  /* Otherwise, array wraps around and we're inserting before the breaking point. 
+   * First, move everything past that point by one place. */
+  memmove (array->array + elt_size, array->array, array->tail * elt_size);
+
+  /* Then move the last element from before the wrap-around point to right after it. */
+  memcpy (array->array, array->array + (array->size - 1) * elt_size, elt_size);
+
+  /* If we're inserting right before the breaking point, no further action is needed.
+   * Otherwise, move data between insertion point and the breaking point by one place. */
+  if (pos != array->size - 1) {
+    memmove (array->array + (pos + 1) * elt_size, array->array + pos * elt_size,
+        (array->size - pos - 1) * elt_size);
+  }
+}
+
+/**
+ * gst_vec_deque_push_sorted: (skip)
+ * @array: a #GstVecDeque object
+ * @data: object to push
+ * @func: comparison function
+ * @user_data: (nullable): data for comparison function
+ *
+ * Pushes @data to the queue @array, finding the correct position
+ * by comparing @data with each array element using @func.
+ *
+ * This has a time complexity of O(n), so depending on the size of the queue
+ * and expected access patterns, a different data structure might be better.
+ *
+ * Assumes that the array is already sorted. If it is not, make sure
+ * to call gst_vec_deque_sort() first.
+ *
+ * Since: 1.26
+ */
+void
+gst_vec_deque_push_sorted (GstVecDeque * array, gpointer data,
+    GCompareDataFunc func, gpointer user_data)
+{
+  gsize i;
+  gpointer *p_element;
+
+  g_return_if_fail (array != NULL);
+  g_return_if_fail (func != NULL);
+
+  /* Check if we need to make room */
+  if (G_UNLIKELY (array->length == array->size))
+    gst_vec_deque_do_expand (array);
+
+  /* Compare against each element, assuming they're already sorted */
+  for (i = 0; i < array->length; i++) {
+    p_element = (gpointer *) gst_vec_deque_idx (array, i);
+
+    if (func (*p_element, data, user_data) > 0) {
+      gsize pos = (array->head + i) % array->size;
+      gst_vec_deque_move_data_after_position (array, pos);
+
+      *p_element = data;
+      goto finish;
+    }
+  }
+
+  /* No 'bigger' element found - append to tail */
+  *(gpointer *) (array->array + array->elt_size * array->tail) = data;
+
+finish:
+  array->tail++;
+  array->tail %= array->size;
+  array->length++;
+}
+
+/**
+ * gst_vec_deque_push_sorted_struct: (skip)
+ * @array: a #GstVecDeque object
+ * @p_struct: address of element or structure to push into the queue
+ * @func: comparison function
+ * @user_data: (nullable): data for comparison function
+ *
+ * Pushes the element at address @p_struct into the queue @array
+ * (copying the contents of a structure of the struct_size specified
+ * when creating the queue into the array), finding the correct position
+ * by comparing the element at @p_struct with each element in the array using @func.
+ *
+ * This has a time complexity of O(n), so depending on the size of the queue
+ * and expected access patterns, a different data structure might be better.
+ *
+ * Assumes that the array is already sorted. If it is not, make sure
+ * to call gst_vec_deque_sort() first.
+ *
+ * Since: 1.26
+ */
+void
+gst_vec_deque_push_sorted_struct (GstVecDeque * array, gpointer p_struct,
+    GCompareDataFunc func, gpointer user_data)
+{
+  gsize i;
+  gpointer p_element;
+
+  g_return_if_fail (array != NULL);
+  g_return_if_fail (p_struct != NULL);
+  g_return_if_fail (func != NULL);
+
+  /* Check if we need to make room */
+  if (G_UNLIKELY (array->length == array->size))
+    gst_vec_deque_do_expand (array);
+
+  /* Compare against each element, assuming they're already sorted */
+  for (i = 0; i < array->length; i++) {
+    p_element = gst_vec_deque_idx (array, i);
+
+    if (func (p_element, p_struct, user_data) > 0) {
+      gsize pos = (array->head + i) % array->size;
+      gst_vec_deque_move_data_after_position (array, pos);
+
+      memcpy (p_element, p_struct, array->elt_size);
+      goto finish;
+    }
+  }
+
+  /* No 'bigger' element found - append to tail */
+  memcpy (array->array + array->elt_size * array->tail, p_struct,
+      array->elt_size);
+
+finish:
+  array->tail++;
+  array->tail %= array->size;
+  array->length++;
+}
+
+static int
+compare_wrapper (gpointer * a, gpointer * b, QueueSortData * sort_data)
+{
+  return sort_data->func (*a, *b, sort_data->user_data);
+}
+
+/** 
+ * gst_vec_deque_sort: (skip)
+ * @array: a #GstVecDeque object
+ * @compare_func: comparison function
+ * @user_data: (nullable): data for comparison function
+ *
+ * Sorts the queue @array by comparing elements against each other using
+ * the provided @compare_func.
+ *
+ * Since: 1.26
+ */
+void
+gst_vec_deque_sort (GstVecDeque * array, GCompareDataFunc compare_func,
+    gpointer user_data)
+{
+  g_return_if_fail (array != NULL);
+  g_return_if_fail (compare_func != NULL);
+
+  if (array->length == 0)
+    return;
+
+  /* To be able to use g_sort_array, we might need to rearrange:
+   * [0-----TAIL][HEAD-----SIZE] -> [HEAD-------TAIL] */
+  if (array->head >= array->tail) {
+    gsize t1 = array->head;
+    gsize t2 = array->size - array->head;
+    gsize elt_size = array->elt_size;
+
+    /* Copy [0-------TAIL] part to a temporary buffer */
+    guint8 *tmp = g_malloc0_n (t1, elt_size);
+    memcpy (tmp, array->array, t1 * elt_size);
+
+    /* Move [HEAD-----SIZE] part to the beginning of the original array */
+    memmove (array->array, array->array + (elt_size * array->head),
+        t2 * elt_size);
+
+    /* Copy the temporary buffer to the end of the original array */
+    memmove (array->array + (t2 * elt_size), tmp, t1 * elt_size);
+    g_free (tmp);
+
+    array->head = 0;
+    array->tail = array->length % array->size;
+  }
+
+  if (array->struct_array) {
+    g_sort_array (array->array +
+        (array->head % array->size) * array->elt_size, array->length,
+        array->elt_size, compare_func, user_data);
+  } else {
+    /* For non-struct arrays, we need to wrap the provided compare function 
+     * to dereference our pointers before passing them for comparison. 
+     * This matches the behaviour of gst_vec_deque_find(). */
+    QueueSortData sort_data = { compare_func, user_data };
+    g_sort_array (array->array +
+        (array->head % array->size) * array->elt_size, array->length,
+        array->elt_size, (GCompareDataFunc) compare_wrapper, &sort_data);
+  }
+}
+
+/**
+ * gst_vec_deque_peek_tail: (skip)
+ * @array: a #GstVecDeque object
+ *
+ * Returns the tail of the queue @array, but does not remove it from the queue.
+ *
+ * Returns: The tail of the queue
+ *
+ * Since: 1.26
+ */
+gpointer
+gst_vec_deque_peek_tail (GstVecDeque * array)
+{
+  gsize len, idx;
+
+  g_return_val_if_fail (array != NULL, NULL);
+
+  len = array->length;
+
+  /* empty array */
+  if (len == 0)
+    return NULL;
+
+  idx = (array->head + (len - 1)) % array->size;
+
+  return *(gpointer *) (array->array + (sizeof (gpointer) * idx));
+}
+
+/**
+ * gst_vec_deque_peek_tail_struct: (skip)
+ * @array: a #GstVecDeque object
+ *
+ * Returns the tail of the queue @array, but does not remove it from the queue.
+ *
+ * Returns: The tail of the queue
+ *
+ * Since: 1.26
+ */
+gpointer
+gst_vec_deque_peek_tail_struct (GstVecDeque * array)
+{
+  gsize len, idx;
+
+  g_return_val_if_fail (array != NULL, NULL);
+
+  len = array->length;
+
+  /* empty array */
+  if (len == 0)
+    return NULL;
+
+  idx = (array->head + (len - 1)) % array->size;
+
+  return array->array + (array->elt_size * idx);
+}
+
+/**
+ * gst_vec_deque_pop_tail: (skip)
+ * @array: a #GstVecDeque object
+ *
+ * Returns the tail of the queue @array and removes
+ * it from the queue.
+ *
+ * Returns: The tail of the queue
+ *
+ * Since: 1.26
+ */
+gpointer
+gst_vec_deque_pop_tail (GstVecDeque * array)
+{
+  gpointer ret;
+  gsize len, idx;
+
+  g_return_val_if_fail (array != NULL, NULL);
+
+  len = array->length;
+
+  /* empty array */
+  if (len == 0)
+    return NULL;
+
+  idx = (array->head + (len - 1)) % array->size;
+
+  ret = *(gpointer *) (array->array + (sizeof (gpointer) * idx));
+
+  array->tail = idx;
+  array->length--;
+
+  return ret;
+}
+
+/**
+ * gst_vec_deque_pop_tail_struct: (skip)
+ * @array: a #GstVecDeque object
+ *
+ * Returns the tail of the queue @array and removes
+ * it from the queue.
+ *
+ * Returns: The tail of the queue
+ *
+ * Since: 1.26
+ */
+gpointer
+gst_vec_deque_pop_tail_struct (GstVecDeque * array)
+{
+  gpointer ret;
+  gsize len, idx;
+
+  g_return_val_if_fail (array != NULL, NULL);
+
+  len = array->length;
+
+  /* empty array */
+  if (len == 0)
+    return NULL;
+
+  idx = (array->head + (len - 1)) % array->size;
+
+  ret = array->array + (array->elt_size * idx);
+
+  array->tail = idx;
+  array->length--;
+
+  return ret;
+}
+
+/**
+ * gst_vec_deque_is_empty: (skip)
+ * @array: a #GstVecDeque object
+ *
+ * Checks if the queue @array is empty.
+ *
+ * Returns: %TRUE if the queue @array is empty
+ *
+ * Since: 1.26
+ */
+gboolean
+gst_vec_deque_is_empty (GstVecDeque * array)
+{
+  g_return_val_if_fail (array != NULL, FALSE);
+  return (array->length == 0);
+}
+
+
+/**
+ * gst_vec_deque_drop_struct: (skip)
+ * @array: a #GstVecDeque object
+ * @idx: index to drop
+ * @p_struct: address into which to store the data of the dropped structure, or NULL
+ *
+ * Drops the queue element at position @idx from queue @array and copies the
+ * data of the element or structure that was removed into @p_struct if
+ * @p_struct is set (not NULL).
+ *
+ * Returns: TRUE on success, or FALSE on error
+ *
+ * Since: 1.26
+ */
+gboolean
+gst_vec_deque_drop_struct (GstVecDeque * array, gsize idx, gpointer p_struct)
+{
+  int first_item_index, last_item_index;
+  gsize actual_idx;
+  gsize elt_size;
+
+  g_return_val_if_fail (array != NULL, FALSE);
+  actual_idx = (array->head + idx) % array->size;
+
+  g_return_val_if_fail (array->length > 0, FALSE);
+  g_return_val_if_fail (actual_idx < array->size, FALSE);
+
+  elt_size = array->elt_size;
+
+  first_item_index = array->head;
+
+  /* tail points to the first free spot */
+  last_item_index = (array->tail - 1 + array->size) % array->size;
+
+  if (p_struct != NULL)
+    memcpy (p_struct, array->array + elt_size * actual_idx, elt_size);
+
+  /* simple case actual_idx == first item */
+  if (actual_idx == first_item_index) {
+    /* clear current head position if needed */
+    if (p_struct == NULL)
+      gst_vec_deque_clear_idx (array, idx);
+
+    /* move the head plus one */
+    array->head++;
+    array->head %= array->size;
+    array->length--;
+    return TRUE;
+  }
+
+  /* simple case idx == last item */
+  if (actual_idx == last_item_index) {
+    /* clear current tail position if needed */
+    if (p_struct == NULL)
+      gst_vec_deque_clear_idx (array, idx);
+
+    /* move tail minus one, potentially wrapping */
+    array->tail = (array->tail - 1 + array->size) % array->size;
+    array->length--;
+    return TRUE;
+  }
+
+  /* non-wrapped case */
+  if (first_item_index < last_item_index) {
+    /* clear idx if needed */
+    if (p_struct == NULL)
+      gst_vec_deque_clear_idx (array, idx);
+
+    g_assert (first_item_index < actual_idx && actual_idx < last_item_index);
+    /* move everything beyond actual_idx one step towards zero in array */
+    memmove (array->array + elt_size * actual_idx,
+        array->array + elt_size * (actual_idx + 1),
+        (last_item_index - actual_idx) * elt_size);
+    /* tail might wrap, ie if tail == 0 (and last_item_index == size) */
+    array->tail = (array->tail - 1 + array->size) % array->size;
+    array->length--;
+    return TRUE;
+  }
+
+  /* only wrapped cases left */
+  g_assert (first_item_index > last_item_index);
+
+  if (actual_idx < last_item_index) {
+    /* clear idx if needed */
+    if (p_struct == NULL)
+      gst_vec_deque_clear_idx (array, idx);
+
+    /* actual_idx is before last_item_index, move data towards zero */
+    memmove (array->array + elt_size * actual_idx,
+        array->array + elt_size * (actual_idx + 1),
+        (last_item_index - actual_idx) * elt_size);
+    /* tail should not wrap in this case! */
+    g_assert (array->tail > 0);
+    array->tail--;
+    array->length--;
+    return TRUE;
+  }
+
+  if (actual_idx > first_item_index) {
+    /* clear idx if needed */
+    if (p_struct == NULL)
+      gst_vec_deque_clear_idx (array, idx);
+
+    /* actual_idx is after first_item_index, move data to higher indices */
+    memmove (array->array + elt_size * (first_item_index + 1),
+        array->array + elt_size * first_item_index,
+        (actual_idx - first_item_index) * elt_size);
+    array->head++;
+    /* head should not wrap in this case! */
+    g_assert (array->head < array->size);
+    array->length--;
+    return TRUE;
+  }
+
+  g_return_val_if_reached (FALSE);
+}
+
+/**
+ * gst_vec_deque_drop_element: (skip)
+ * @array: a #GstVecDeque object
+ * @idx: index to drop
+ *
+ * Drops the queue element at position @idx from queue @array.
+ *
+ * Returns: the dropped element
+ *
+ * Since: 1.26
+ */
+gpointer
+gst_vec_deque_drop_element (GstVecDeque * array, gsize idx)
+{
+  gpointer ptr;
+
+  if (!gst_vec_deque_drop_struct (array, idx, &ptr))
+    return NULL;
+
+  return ptr;
+}
+
+/**
+ * gst_vec_deque_find: (skip)
+ * @array: a #GstVecDeque object
+ * @func: (nullable): comparison function, or %NULL to find @data by value
+ * @data: data for comparison function
+ *
+ * Finds an element in the queue @array, either by comparing every element
+ * with @func or by looking up @data if no compare function @func is provided,
+ * and returning the index of the found element.
+ *
+ * Returns: Index of the found element or -1 if nothing was found.
+ *
+ * Since: 1.26
+ */
+gsize
+gst_vec_deque_find (GstVecDeque * array, GCompareFunc func, gpointer data)
+{
+  gpointer p_element;
+  gsize elt_size;
+  gsize i;
+
+  /* For struct arrays we need to implement this differently so that
+   * the user gets a pointer to the element data not the dereferenced
+   * pointer itself */
+
+  g_return_val_if_fail (array != NULL, -1);
+  g_return_val_if_fail (array->struct_array == FALSE, -1);
+
+  elt_size = array->elt_size;
+
+  if (func != NULL) {
+    /* Scan from head to tail */
+    for (i = 0; i < array->length; i++) {
+      p_element = array->array + ((i + array->head) % array->size) * elt_size;
+      if (func (*(gpointer *) p_element, data) == 0)
+        return i;
+    }
+  } else {
+    for (i = 0; i < array->length; i++) {
+      p_element = array->array + ((i + array->head) % array->size) * elt_size;
+      if (*(gpointer *) p_element == data)
+        return i;
+    }
+  }
+
+  return -1;
+}
+
+/**
+ * gst_vec_deque_get_length: (skip)
+ * @array: a #GstVecDeque object
+ *
+ * Returns the length of the queue @array
+ *
+ * Returns: the length of the queue @array.
+ *
+ * Since: 1.26
+ */
+gsize
+gst_vec_deque_get_length (GstVecDeque * array)
+{
+  g_return_val_if_fail (array != NULL, 0);
+  return array->length;
+}
diff --git a/gst/gstvecdeque.h b/gst/gstvecdeque.h
new file mode 100644
index 0000000..dd98f1c
--- /dev/null
+++ b/gst/gstvecdeque.h
@@ -0,0 +1,129 @@
+/* GStreamer
+ * Copyright (C) 2009-2010 Edward Hervey <bilboed@bilboed.com>
+ *
+ * gstvecdeque.h:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <glib.h>
+
+#ifndef __GST_VEC_DEQUE_H__
+#define __GST_VEC_DEQUE_H__
+
+#include <glib.h>
+#include <gst/gstconfig.h>
+
+G_BEGIN_DECLS
+
+/**
+ * GstVecDeque: (skip)
+ *
+ * Since: 1.26
+ */
+typedef struct _GstVecDeque GstVecDeque;
+
+GST_API
+GstVecDeque *   gst_vec_deque_new     (gsize initial_size);
+
+GST_API
+void            gst_vec_deque_free    (GstVecDeque * array);
+
+GST_API
+void            gst_vec_deque_set_clear_func (GstVecDeque *array,
+                                              GDestroyNotify clear_func);
+
+GST_API
+void            gst_vec_deque_clear     (GstVecDeque * array);
+
+GST_API
+gpointer        gst_vec_deque_pop_head  (GstVecDeque * array);
+
+GST_API
+gpointer        gst_vec_deque_peek_head (GstVecDeque * array);
+
+GST_API
+gpointer        gst_vec_deque_peek_nth  (GstVecDeque * array, gsize idx);
+
+GST_API
+gpointer        gst_vec_deque_pop_tail  (GstVecDeque * array);
+
+GST_API
+gpointer        gst_vec_deque_peek_tail (GstVecDeque * array);
+
+GST_API
+void            gst_vec_deque_push_tail (GstVecDeque * array,
+                                         gpointer        data);
+GST_API
+gboolean        gst_vec_deque_is_empty  (GstVecDeque * array);
+
+GST_API
+gpointer        gst_vec_deque_drop_element (GstVecDeque * array,
+                                            gsize           idx);
+GST_API
+gsize           gst_vec_deque_find (GstVecDeque * array,
+                                    GCompareFunc    func,
+                                    gpointer        data);
+GST_API
+gsize           gst_vec_deque_get_length (GstVecDeque * array);
+
+/* Functions for use with structures */
+
+GST_API
+GstVecDeque * gst_vec_deque_new_for_struct (gsize struct_size,
+                                            gsize initial_size);
+GST_API
+void            gst_vec_deque_push_tail_struct (GstVecDeque * array,
+                                                  gpointer        p_struct);
+GST_API
+gpointer        gst_vec_deque_pop_head_struct  (GstVecDeque * array);
+
+GST_API
+gpointer        gst_vec_deque_peek_head_struct (GstVecDeque * array);
+
+GST_API
+gpointer        gst_vec_deque_peek_nth_struct  (GstVecDeque * array, gsize idx);
+
+GST_API
+gboolean        gst_vec_deque_drop_struct      (GstVecDeque * array,
+                                                gsize           idx,
+                                                gpointer        p_struct);
+GST_API
+gpointer        gst_vec_deque_pop_tail_struct  (GstVecDeque * array);
+
+GST_API
+gpointer        gst_vec_deque_peek_tail_struct (GstVecDeque * array);
+
+GST_API
+void            gst_vec_deque_push_sorted (GstVecDeque * array, 
+                                           gpointer data,
+                                           GCompareDataFunc func, 
+                                           gpointer user_data);
+
+GST_API
+void            gst_vec_deque_push_sorted_struct (GstVecDeque * array, 
+                                                  gpointer p_struct,
+                                                  GCompareDataFunc func, 
+                                                  gpointer user_data);
+
+GST_API
+void            gst_vec_deque_sort (GstVecDeque *array,
+                                    GCompareDataFunc compare_func,
+                                    gpointer user_data);
+
+G_END_DECLS
+
+#endif
diff --git a/gst/meson.build b/gst/meson.build
index 7ed2a35..93501f1 100644
--- a/gst/meson.build
+++ b/gst/meson.build
@@ -27,6 +27,7 @@ gst_sources = files(
   'gstformat.c',
   'gstghostpad.c',
   'gstdevicemonitor.c',
+  'gstidstr.c',
   'gstinfo.c',
   'gstiterator.c',
   'gstatomicqueue.c',
@@ -43,7 +44,6 @@ gst_sources = files(
   'gstpoll.c',
   'gstpreset.c',
   'gstprotection.c',
-  'gstquark.c',
   'gstquery.c',
   'gstregistry.c',
   'gstregistrychunks.c',
@@ -69,6 +69,7 @@ gst_sources = files(
   'gsturi.c',
   'gstutils.c',
   'gstvalue.c',
+  'gstvecdeque.c',
   'gstparse.c',
 )
 
@@ -105,6 +106,7 @@ gst_headers = files(
   'gstformat.h',
   'gstghostpad.h',
   'gstdevicemonitor.h',
+  'gstidstr.h',
   'gstinfo.h',
   'gstiterator.h',
   'gstatomicqueue.h',
@@ -144,13 +146,14 @@ gst_headers = files(
   'gsturi.h',
   'gstutils.h',
   'gstvalue.h',
+  'gstvecdeque.h',
   'gstregistry.h',
   'gstparse.h',
   'math-compat.h',
 )
 if host_system == 'darwin'
-  gst_headers += 'gstmacos.h'
-  gst_sources += 'gstmacos.m'
+  gst_headers += files('gstmacos.h')
+  gst_sources += files('gstmacos.m')
 endif
 
 install_headers(gst_headers, subdir : 'gstreamer-1.0/gst')
@@ -163,7 +166,7 @@ endif
 
 extra_deps = []
 if host_system == 'android'
-  gst_sources += 'gstandroid.c'
+  gst_sources += files('gstandroid.c')
   extra_deps += cc.find_library('log')
 endif
 
@@ -201,9 +204,9 @@ else
   gst_cdata.set('GST_DISABLE_PARSE_DEFINE', '#define GST_DISABLE_PARSE 1')
 endif
 
-gst_cdata.set10('GST_DISABLE_CAST_CHECKS_DEFINE', cast_checks.disabled())
-gst_cdata.set10('GST_DISABLE_GLIB_ASSERTS_DEFINE', glib_asserts.disabled())
-gst_cdata.set10('GST_DISABLE_GLIB_CHECKS_DEFINE', glib_checks.disabled())
+gst_cdata.set10('GST_DISABLE_CAST_CHECKS_DEFINE', disable_cast_checks)
+gst_cdata.set10('GST_DISABLE_GLIB_ASSERTS_DEFINE', disable_glib_asserts)
+gst_cdata.set10('GST_DISABLE_GLIB_CHECKS_DEFINE', disable_glib_checks)
 
 # FIXME: add --disable-plugin option?
 gst_cdata.set('GST_DISABLE_PLUGIN_DEFINE', '#undef GST_DISABLE_PLUGIN')
@@ -254,7 +257,9 @@ if not tracer_hooks
 endif
 
 if get_option('gstreamer-static-full')
-  libgst_c_args += ['-DGST_FULL_STATIC_COMPILATION']
+  libgst_static_c_args = ['-DGST_FULL_STATIC_COMPILATION']
+else
+  libgst_static_c_args = []
 endif
 
 # Make sure that subproject building gir files work
@@ -266,6 +271,7 @@ libgst = library('gstreamer-1.0', gst_sources,
   soversion : soversion,
   darwin_versions : osxversion,
   c_args : libgst_c_args + ['-DBUILDING_GST'],
+  c_static_args : libgst_static_c_args,
   include_directories : [configinc,
     # HACK, change include paths in .y and .l in final version.
     include_directories('parse')],
@@ -308,7 +314,7 @@ if build_gir
   gir = {
     'sources' : gst_sources + gst_headers + gst_enums + [gst_version_h],
     'namespace' : 'Gst',
-    'nsversion' : apiversion,
+    'nsversion' : api_version,
     'identifier_prefix' : 'Gst',
     'symbol_prefix' : 'gst',
     'export_packages' : pkg_name,
diff --git a/gst/parse/grammar.y.in b/gst/parse/grammar.y.in
index fbc36f1..72801e5 100644
--- a/gst/parse/grammar.y.in
+++ b/gst/parse/grammar.y.in
@@ -119,32 +119,43 @@ __gst_parse_element_free (element_t *data)
 
 /*******************************************************************************************
 *** define SET_ERROR macro/function
+*
+* SET_ERROR() must only be called from the thread running priv_gst_parse_launch() and must
+* only be used for errors that occur during the initial construction of the chain, i.e.
+* before priv_gst_parse_launch() returns.
 *******************************************************************************************/
+static void error_append_probable_reason (graph_t *graph);
+
 #ifdef G_HAVE_ISO_VARARGS
 
-#  define SET_ERROR(error, type, ...) \
+#  define SET_ERROR(graph, type, ...) \
 G_STMT_START { \
+  GError** error = (graph)->error; \
   GST_CAT_ERROR (GST_CAT_PIPELINE, __VA_ARGS__); \
   if ((error) && !*(error)) { \
     g_set_error ((error), GST_PARSE_ERROR, (type), __VA_ARGS__); \
+    error_append_probable_reason ((graph)); \
   } \
 } G_STMT_END
 
 #elif defined(G_HAVE_GNUC_VARARGS)
 
-#  define SET_ERROR(error, type, args...) \
+#  define SET_ERROR(graph, type, args...) \
 G_STMT_START { \
+  GError** error = (graph)->error; \
   GST_CAT_ERROR (GST_CAT_PIPELINE, args ); \
-  if ((error) && !*(error)) { \
-    g_set_error ((error), GST_PARSE_ERROR, (type), args ); \
+  if (error && !*error) { \
+    g_set_error (error, GST_PARSE_ERROR, (type), args ); \
+    error_append_probable_reason ((graph)); \
   } \
 } G_STMT_END
 
 #else
 
 static inline void
-SET_ERROR (GError **error, gint type, const char *format, ...)
+SET_ERROR (graph_t *graph, gint type, const char *format, ...)
 {
+  GError** error = graph->error;
   if (error) {
     if (*error) {
       g_warning ("error while parsing");
@@ -159,12 +170,33 @@ SET_ERROR (GError **error, gint type, const char *format, ...)
       g_set_error (error, GST_PARSE_ERROR, type, string);
 
       g_free (string);
+      error_append_probable_reason ((graph));
     }
   }
 }
 
 #endif /* G_HAVE_ISO_VARARGS */
 
+static void error_append_probable_reason (graph_t *graph) {
+  g_return_if_fail (*graph->error);
+  GError* error = *graph->error;
+
+  reason_receiver_t* receiver = graph->error_probable_reason_receiver;
+  /* If by the time SET_ERROR() was called no bus was set, there is no receiver
+   * and no error from the bus to append. */
+  if (!receiver)
+    return;
+
+  g_mutex_lock (&receiver->mutex);
+  if (receiver->reason) {
+    gchar *new_message = g_strdup_printf ("%s -- %s", error->message,
+        receiver->reason);
+    g_free (error->message);
+    error->message = new_message;
+  }
+  g_mutex_unlock (&receiver->mutex);
+}
+
 /*** define YYPRINTF macro/function if we're debugging */
 
 /* bison 1.35 calls this macro with side effects, we need to make sure the
@@ -292,12 +324,12 @@ beach:
 
 #define TRY_SETUP_LINK(l) G_STMT_START { \
    if( (!(l)->src.element) && (!(l)->src.name) ){ \
-     SET_ERROR (graph->error, GST_PARSE_ERROR_LINK, _("link has no source [sink=%s@%p]"), \
+     SET_ERROR (graph, GST_PARSE_ERROR_LINK, _("link has no source [sink=%s@%p]"), \
 	(l)->sink.name ? (l)->sink.name : "", \
 	(l)->sink.element); \
      gst_parse_free_link (l); \
    }else if( (!(l)->sink.element) && (!(l)->sink.name) ){ \
-     SET_ERROR (graph->error, GST_PARSE_ERROR_LINK, _("link has no sink [source=%s@%p]"), \
+     SET_ERROR (graph, GST_PARSE_ERROR_LINK, _("link has no sink [source=%s@%p]"), \
 	(l)->src.name ? (l)->src.name : "", \
 	(l)->src.element); \
      gst_parse_free_link (l); \
@@ -592,13 +624,13 @@ out:
   return;
 
 not_a_preset:
-  SET_ERROR (graph->error, GST_PARSE_ERROR_COULD_NOT_SET_PROPERTY,
+  SET_ERROR (graph, GST_PARSE_ERROR_COULD_NOT_SET_PROPERTY,
          _("Element \"%s\" is not a GstPreset"),
          GST_ELEMENT_NAME (element));
   goto out;
 
 error:
-  SET_ERROR (graph->error, GST_PARSE_ERROR_COULD_NOT_SET_PROPERTY,
+  SET_ERROR (graph, GST_PARSE_ERROR_COULD_NOT_SET_PROPERTY,
          _("could not set preset \"%s\" in element \"%s\""),
          value, GST_ELEMENT_NAME (element));
   goto out;
@@ -630,7 +662,7 @@ static GstElement * gst_parse_element_make (graph_t *graph, element_t *data) {
   GstElement *ret = NULL;
 
   if (!factory) {
-    SET_ERROR (graph->error, GST_PARSE_ERROR_NO_SUCH_ELEMENT, _("no element \"%s\""), data->factory_name);
+    SET_ERROR (graph, GST_PARSE_ERROR_NO_SUCH_ELEMENT, _("no element \"%s\""), data->factory_name);
     return NULL;
   }
 
@@ -672,7 +704,7 @@ static GstElement * gst_parse_element_make (graph_t *graph, element_t *data) {
       }
 
       if (!collect_value (pspec, value, &values_array[n_params])) {
-        SET_ERROR (graph->error, GST_PARSE_ERROR_COULD_NOT_SET_PROPERTY,
+        SET_ERROR (graph, GST_PARSE_ERROR_COULD_NOT_SET_PROPERTY,
                _("could not set property \"%s\" in element \"%s\" to \"%s\""),
          name, data->factory_name, value);
         g_value_unset (&values_array[n_params]);
@@ -683,7 +715,7 @@ static GstElement * gst_parse_element_make (graph_t *graph, element_t *data) {
 
       ++n_params;
     } else {
-      SET_ERROR (graph->error, GST_PARSE_ERROR_NO_SUCH_PROPERTY, \
+      SET_ERROR (graph, GST_PARSE_ERROR_NO_SUCH_PROPERTY, \
           _("no property \"%s\" in element \"%s\""), name, \
           data->factory_name);
       goto done;
@@ -717,7 +749,7 @@ static GstElement * gst_parse_element_make (graph_t *graph, element_t *data) {
         gst_parse_add_delayed_set (GST_CHILD_PROXY (ret), pp->name, pp->value);
       } else {
         gst_object_unref (target);
-        SET_ERROR (graph->error, GST_PARSE_ERROR_NO_SUCH_PROPERTY, \
+        SET_ERROR (graph, GST_PARSE_ERROR_NO_SUCH_PROPERTY, \
             _("no property \"%s\" in element \"%s\""), pp->name, \
             GST_ELEMENT_NAME (ret));
         goto done;
@@ -726,7 +758,7 @@ static GstElement * gst_parse_element_make (graph_t *graph, element_t *data) {
       GValue v = { 0, };
 
       if (!collect_value (pspec, pp->value, &v)) {
-        SET_ERROR (graph->error, GST_PARSE_ERROR_COULD_NOT_SET_PROPERTY,
+        SET_ERROR (graph, GST_PARSE_ERROR_COULD_NOT_SET_PROPERTY,
                _("could not set property \"%s\" in child of element \"%s\" to \"%s\""),
          pp->name, data->factory_name, pp->value);
         g_value_unset (&v);
@@ -831,7 +863,7 @@ static void gst_parse_element_set (gchar *value, GstElement *element, graph_t *g
       target = G_OBJECT (g_object_ref (element));
       GST_CAT_LOG_OBJECT (GST_CAT_PIPELINE, target, "found %s property", value);
     } else {
-      SET_ERROR (graph->error, GST_PARSE_ERROR_NO_SUCH_PROPERTY, \
+      SET_ERROR (graph, GST_PARSE_ERROR_NO_SUCH_PROPERTY, \
           _("no property \"%s\" in element \"%s\""), value, \
           GST_ELEMENT_NAME (element));
     }
@@ -854,7 +886,7 @@ out:
   return;
 
 error:
-  SET_ERROR (graph->error, GST_PARSE_ERROR_COULD_NOT_SET_PROPERTY,
+  SET_ERROR (graph, GST_PARSE_ERROR_COULD_NOT_SET_PROPERTY,
          _("could not set property \"%s\" in element \"%s\" to \"%s\""),
          value, GST_ELEMENT_NAME (element), pos);
   goto out;
@@ -905,7 +937,7 @@ static void gst_parse_free_delayed_link (DelayedLink *link)
 
 #define PRETTY_PAD_NAME_FMT "%s %s of %s named %s"
 #define PRETTY_PAD_NAME_ARGS(elem, pad_name) \
-  (pad_name ? "pad " : "some"), (pad_name ? pad_name : "pad"), \
+  (pad_name ? "pad" : "some"), (pad_name ? pad_name : "pad"), \
   G_OBJECT_TYPE_NAME(elem), GST_STR_NULL (GST_ELEMENT_NAME (elem))
 
 static void gst_parse_no_more_pads (GstElement *src, gpointer data)
@@ -1042,6 +1074,23 @@ gst_parse_element_can_do_caps (GstElement * e, GstPadDirection dir,
   return can_do;
 }
 
+static gchar*
+format_pad_names(const GSList* list)
+{
+  if (!list)
+    return g_strdup ("(any)");
+  GString* str = g_string_new (NULL);
+  gboolean is_first = TRUE;
+  while (list) {
+    if (!is_first)
+      g_string_append (str, ", ");
+    g_string_append (str, (const gchar *) list->data);
+    list = list->next;
+    is_first = FALSE;
+  }
+  return g_string_free (str, FALSE);
+}
+
 /*
  * performs a link and frees the struct. src and sink elements must be given
  * return values   0 - link performed
@@ -1058,11 +1107,17 @@ gst_parse_perform_link (link_t *link, graph_t *graph)
   g_assert (GST_IS_ELEMENT (src));
   g_assert (GST_IS_ELEMENT (sink));
 
+#ifndef GST_DISABLE_GST_DEBUG
+  gchar* srcpad_names = format_pad_names (srcs);
+  gchar* sinkpad_names = format_pad_names (sinks);
   GST_CAT_INFO (GST_CAT_PIPELINE,
-      "linking " PRETTY_PAD_NAME_FMT " to " PRETTY_PAD_NAME_FMT " (%u/%u) with caps \"%" GST_PTR_FORMAT "\"",
-      PRETTY_PAD_NAME_ARGS (src, link->src.name),
-      PRETTY_PAD_NAME_ARGS (sink, link->sink.name),
-      g_slist_length (srcs), g_slist_length (sinks), link->caps);
+      "linking pads {%s} of %s named %s to pads {%s} of %s named %s with caps \"%" GST_PTR_FORMAT "\"",
+      srcpad_names, G_OBJECT_TYPE_NAME (src), GST_STR_NULL (GST_ELEMENT_NAME (src)),
+      sinkpad_names, G_OBJECT_TYPE_NAME (sink), GST_STR_NULL (GST_ELEMENT_NAME (sink)),
+      link->caps);
+  g_free (srcpad_names);
+  g_free (sinkpad_names);
+#endif
 
   if (!srcs || !sinks) {
     gboolean found_one = gst_element_link_pads_filtered (src,
@@ -1128,27 +1183,27 @@ error:
         gst_parse_element_can_do_caps (sink, GST_PAD_SINK, link->caps);
 
     if (!src_can_do_caps && sink_can_do_caps) {
-      SET_ERROR (graph->error, GST_PARSE_ERROR_LINK,
+      SET_ERROR (graph, GST_PARSE_ERROR_LINK,
           _("could not link %s to %s, %s can't handle caps %s"),
           GST_ELEMENT_NAME (src), GST_ELEMENT_NAME (sink),
           GST_ELEMENT_NAME (src), caps_str);
     } else if (src_can_do_caps && !sink_can_do_caps) {
-      SET_ERROR (graph->error, GST_PARSE_ERROR_LINK,
+      SET_ERROR (graph, GST_PARSE_ERROR_LINK,
           _("could not link %s to %s, %s can't handle caps %s"),
           GST_ELEMENT_NAME (src), GST_ELEMENT_NAME (sink),
           GST_ELEMENT_NAME (sink), caps_str);
     } else if (!src_can_do_caps && !sink_can_do_caps) {
-      SET_ERROR (graph->error, GST_PARSE_ERROR_LINK,
+      SET_ERROR (graph, GST_PARSE_ERROR_LINK,
           _("could not link %s to %s, neither element can handle caps %s"),
           GST_ELEMENT_NAME (src), GST_ELEMENT_NAME (sink), caps_str);
     } else {
-      SET_ERROR (graph->error, GST_PARSE_ERROR_LINK,
+      SET_ERROR (graph, GST_PARSE_ERROR_LINK,
           _("could not link %s to %s with caps %s"),
           GST_ELEMENT_NAME (src), GST_ELEMENT_NAME (sink), caps_str);
     }
     g_free (caps_str);
   } else {
-    SET_ERROR (graph->error, GST_PARSE_ERROR_LINK,
+    SET_ERROR (graph, GST_PARSE_ERROR_LINK,
         _("could not link %s to %s"), GST_ELEMENT_NAME (src),
         GST_ELEMENT_NAME (sink));
   }
@@ -1302,13 +1357,13 @@ elementary:
 **************************************************************/
 chain:	openchain			      { $$=$1;
 						if($$->last.name){
-							SET_ERROR (graph->error, GST_PARSE_ERROR_SYNTAX,
+							SET_ERROR (graph, GST_PARSE_ERROR_SYNTAX,
 							_("unexpected reference \"%s\" - ignoring"), $$->last.name);
 							gst_parse_strfree($$->last.name);
 							$$->last.name=NULL;
 						}
 						if($$->last.pads){
-							SET_ERROR (graph->error, GST_PARSE_ERROR_SYNTAX,
+							SET_ERROR (graph, GST_PARSE_ERROR_SYNTAX,
 							_("unexpected pad-reference \"%s\" - ignoring"), (gchar*)$$->last.pads->data);
 							g_slist_foreach ($$->last.pads, (GFunc) gst_parse_strfree, NULL);
 							g_slist_free ($$->last.pads);
@@ -1343,7 +1398,7 @@ link:	LINK				      { $$ = gst_parse_link_new ();
 						  $$->caps = gst_caps_from_string (str);
 						  g_free (str);
 						  if ($$->caps == NULL)
-						    SET_ERROR (graph->error, GST_PARSE_ERROR_LINK, _("could not parse caps \"%s\""), $1);
+						    SET_ERROR (graph, GST_PARSE_ERROR_LINK, _("could not parse caps \"%s\""), $1);
 						  gst_parse_strfree ($1);
 						}
 					      }
@@ -1354,7 +1409,7 @@ link:	LINK				      { $$ = gst_parse_link_new ();
 						  $$->caps = gst_caps_from_string (str);
 						  g_free (str);
 						  if ($$->caps == NULL)
-						    SET_ERROR (graph->error, GST_PARSE_ERROR_LINK, _("could not parse caps \"%s\""), $1);
+						    SET_ERROR (graph, GST_PARSE_ERROR_LINK, _("could not parse caps \"%s\""), $1);
 						  gst_parse_strfree ($1);
 						}
 					      }
@@ -1381,7 +1436,7 @@ chain:	openchain link PARSE_URL	      { GstElement *element =
 							  gst_element_make_from_uri (GST_URI_SINK, $3, NULL, NULL);
 						/* FIXME: get and parse error properly */
 						if (!element) {
-						  SET_ERROR (graph->error, GST_PARSE_ERROR_NO_SUCH_ELEMENT,
+						  SET_ERROR (graph, GST_PARSE_ERROR_NO_SUCH_ELEMENT,
 							  _("no sink element for URI \"%s\""), $3);
 						}
 						$$ = $1;
@@ -1400,7 +1455,7 @@ openchain:
 							  gst_element_make_from_uri (GST_URI_SRC, $1, NULL, NULL);
 						/* FIXME: get and parse error properly */
 						if (!element) {
-						  SET_ERROR (graph->error, GST_PARSE_ERROR_NO_SUCH_ELEMENT,
+						  SET_ERROR (graph, GST_PARSE_ERROR_NO_SUCH_ELEMENT,
 						    _("no source element for URI \"%s\""), $1);
 						}
 						$$ = gst_parse_chain_new ();
@@ -1491,7 +1546,7 @@ chainlist: /* NOP */			      { $$ = NULL; }
 					      }
 	| chainlist error		      { $$=$1;
 						GST_CAT_DEBUG (GST_CAT_PIPELINE,"trying to recover from syntax error");
-						SET_ERROR (graph->error, GST_PARSE_ERROR_SYNTAX, _("syntax error"));
+						SET_ERROR (graph, GST_PARSE_ERROR_SYNTAX, _("syntax error"));
 					      }
 	;
 
@@ -1513,7 +1568,7 @@ bin:	binopener assignments chainlist ')'   {
 						GSList *walk;
 						GstBin *bin = (GstBin *) gst_element_factory_make ($1, NULL);
 						if (!chain) {
-						  SET_ERROR (graph->error, GST_PARSE_ERROR_EMPTY_BIN,
+						  SET_ERROR (graph, GST_PARSE_ERROR_EMPTY_BIN,
 						    _("specified empty bin \"%s\", not allowed"), $1);
 						  chain = gst_parse_chain_new ();
 						  chain->first.element = chain->last.element = NULL;
@@ -1523,7 +1578,7 @@ bin:	binopener assignments chainlist ')'   {
 						}
 						if (!bin) {
 						  add_missing_element(graph, $1);
-						  SET_ERROR (graph->error, GST_PARSE_ERROR_NO_SUCH_ELEMENT,
+						  SET_ERROR (graph, GST_PARSE_ERROR_NO_SUCH_ELEMENT,
 						    _("no bin \"%s\", unpacking elements"), $1);
 						  /* clear property-list */
 						  g_slist_foreach ($2, (GFunc) gst_parse_strfree, NULL);
@@ -1555,7 +1610,7 @@ bin:	binopener assignments chainlist ')'   {
 graph:	chainlist			      { $$ = graph;
 						$$->chain = $1;
 						if(!$1) {
-						  SET_ERROR (graph->error, GST_PARSE_ERROR_EMPTY, _("empty pipeline not allowed"));
+						  SET_ERROR (graph, GST_PARSE_ERROR_EMPTY, _("empty pipeline not allowed"));
 						}
 					      }
 	;
@@ -1572,6 +1627,77 @@ yyerror (void *scanner, graph_t *graph, const char *s)
 }
 
 
+static GstBusSyncReply
+parse_launch_handle_message_sync (GstBus * bus, GstMessage * message, gpointer user_data)
+{
+  reason_receiver_t *receiver = (reason_receiver_t *) user_data;
+  GstObject *src = GST_MESSAGE_SRC (message);
+  GstMessageType type = GST_MESSAGE_TYPE (message);
+
+  switch (type) {
+    case GST_MESSAGE_ERROR:
+    {
+      GError *error;
+      gchar *debug_msg;
+      gchar *explanation;
+      const GstStructure *details;
+      gst_message_parse_error (message, &error, &debug_msg);
+      gst_message_parse_error_details (message, &details);
+
+      explanation = gst_info_strdup_printf ("%s %" GST_PTR_FORMAT " posted "
+          "an error message: %s", src ? G_OBJECT_TYPE_NAME(src) : "", src,
+          error->message);
+      /* We lock the mutex a bit early so that if errors occur simultaneously
+       * from two threads the following log lines are logged one error at a
+       * time, just for convenience of the person reading the logs. */
+      g_mutex_lock (&receiver->mutex);
+      GST_CAT_ERROR (GST_CAT_PIPELINE, "%s", explanation);
+      if (debug_msg)
+        GST_CAT_ERROR (GST_CAT_PIPELINE, "Debug message: %s", debug_msg);
+      if (details)
+        GST_CAT_ERROR (GST_CAT_PIPELINE, "Details: %" GST_PTR_FORMAT, details);
+
+      /* This message will be suffixed when SET_ERROR() is called.
+       * This allows the message to be seen in gst-launch even if no logging is
+       * enabled, which is the default for GStreamer releases. */
+      if (!receiver->reason)
+        receiver->reason = g_strdup (explanation);
+      g_mutex_unlock (&receiver->mutex);
+
+      g_free (explanation);
+      g_error_free (error);
+      g_free (debug_msg);
+      break;
+    }
+    default:
+      break;
+  }
+
+  return GST_BUS_PASS;
+}
+
+static reason_receiver_t*
+reason_receiver_new (void) {
+  reason_receiver_t *receiver = g_atomic_rc_box_new0 (reason_receiver_t);
+  g_mutex_init (&receiver->mutex);
+  receiver->reason = NULL;
+  return receiver;
+}
+
+static void
+reason_receiver_clear (reason_receiver_t *receiver) {
+  g_mutex_clear (&receiver->mutex);
+  g_free (receiver->reason);
+}
+
+#define reason_receiver_ref(receiver) g_atomic_rc_box_acquire (receiver)
+
+static void
+reason_receiver_unref (reason_receiver_t *receiver) {
+  g_atomic_rc_box_release_full (receiver,
+      (GDestroyNotify) reason_receiver_clear);
+}
+
 GstElement *
 priv_gst_parse_launch (const gchar *str, GError **error, GstParseContext *ctx,
     GstParseFlags flags)
@@ -1581,6 +1707,8 @@ priv_gst_parse_launch (const gchar *str, GError **error, GstParseContext *ctx,
   GSList *walk;
   GstElement *ret;
   yyscan_t scanner;
+  GstBin *bin = NULL;
+  GstBus *temp_bus = NULL, *old_bus = NULL;
 
   g_return_val_if_fail (str != NULL, NULL);
   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
@@ -1590,6 +1718,7 @@ priv_gst_parse_launch (const gchar *str, GError **error, GstParseContext *ctx,
   g.error = error;
   g.ctx = ctx;
   g.flags = flags;
+  g.error_probable_reason_receiver = NULL;
 
 #ifdef __GST_PARSE_TRACE
   GST_CAT_DEBUG (GST_CAT_PIPELINE, "TRACE: tracing enabled");
@@ -1607,7 +1736,7 @@ priv_gst_parse_launch (const gchar *str, GError **error, GstParseContext *ctx,
 #endif
 
   if (yyparse (scanner, &g) != 0) {
-    SET_ERROR (error, GST_PARSE_ERROR_SYNTAX,
+    SET_ERROR (&g, GST_PARSE_ERROR_SYNTAX,
         "Unrecoverable syntax error while parsing pipeline %s", str);
 
     priv_gst_parse_yylex_destroy (scanner);
@@ -1641,13 +1770,23 @@ priv_gst_parse_launch (const gchar *str, GError **error, GstParseContext *ctx,
 
   /* put all elements in our bin if necessary */
   if(g.chain->elements->next){
-    GstBin *bin;
     if (flags & GST_PARSE_FLAG_PLACE_IN_BIN)
       bin = GST_BIN (gst_element_factory_make ("bin", NULL));
     else
       bin = GST_BIN (gst_element_factory_make ("pipeline", NULL));
     g_assert (bin);
 
+    /* Assign the bin a temporary bus to catch any error messages posted during
+     * the construction of the pipeline and log them in a way that is visible
+     * by default in gst-launch. */
+    old_bus = gst_element_get_bus (GST_ELEMENT (bin));
+    temp_bus = gst_bus_new ();
+    g.error_probable_reason_receiver = reason_receiver_new ();
+    gst_bus_set_sync_handler (temp_bus, parse_launch_handle_message_sync,
+        reason_receiver_ref (g.error_probable_reason_receiver),
+        (GDestroyNotify) reason_receiver_unref);
+    gst_element_set_bus (GST_ELEMENT (bin), temp_bus);
+
     for (walk = g.chain->elements; walk; walk = walk->next) {
       if (walk->data != NULL)
         gst_bin_add (bin, GST_ELEMENT (walk->data));
@@ -1670,11 +1809,11 @@ priv_gst_parse_launch (const gchar *str, GError **error, GstParseContext *ctx,
     err=gst_resolve_reference( &(l->src), ret);
     if (err) {
        if(-1==err){
-          SET_ERROR (error, GST_PARSE_ERROR_NO_SUCH_ELEMENT,
+          SET_ERROR (&g, GST_PARSE_ERROR_NO_SUCH_ELEMENT,
               "No src-element named \"%s\" - omitting link", l->src.name);
        }else{
           /* probably a missing element which we've handled already */
-          SET_ERROR (error, GST_PARSE_ERROR_NO_SUCH_ELEMENT,
+          SET_ERROR (&g, GST_PARSE_ERROR_NO_SUCH_ELEMENT,
               "No src-element found - omitting link");
        }
        gst_parse_free_link (l);
@@ -1684,11 +1823,11 @@ priv_gst_parse_launch (const gchar *str, GError **error, GstParseContext *ctx,
     err=gst_resolve_reference( &(l->sink), ret);
     if (err) {
        if(-1==err){
-          SET_ERROR (error, GST_PARSE_ERROR_NO_SUCH_ELEMENT,
+          SET_ERROR (&g, GST_PARSE_ERROR_NO_SUCH_ELEMENT,
               "No sink-element named \"%s\" - omitting link", l->src.name);
        }else{
           /* probably a missing element which we've handled already */
-          SET_ERROR (error, GST_PARSE_ERROR_NO_SUCH_ELEMENT,
+          SET_ERROR (&g, GST_PARSE_ERROR_NO_SUCH_ELEMENT,
               "No sink-element found - omitting link");
        }
        gst_parse_free_link (l);
@@ -1709,6 +1848,14 @@ out:
   }
 #endif /* __GST_PARSE_TRACE */
 
+  if (bin && temp_bus) {
+    gst_element_set_bus (GST_ELEMENT (bin), old_bus);
+    reason_receiver_unref (g.error_probable_reason_receiver);
+    g.error_probable_reason_receiver = NULL;
+    g_clear_object (&temp_bus);
+    g_clear_object (&old_bus);
+  }
+
   return ret;
 
 error1:
diff --git a/gst/parse/types.h b/gst/parse/types.h
index 7aa4d51..d129791 100644
--- a/gst/parse/types.h
+++ b/gst/parse/types.h
@@ -30,12 +30,22 @@ typedef struct {
   GSList *presets;
 } element_t;
 
+/* Filled from a bus sync handler if a error message is posted during the
+ * construction of the chain.
+ * The mutex is necessary as the bus could -- at least in principle -- have
+ * messages posted from several threads simultaneously. */
+typedef struct {
+  GMutex mutex;
+  gchar *reason; /* owned by the struct */
+} reason_receiver_t;
+
 
 typedef struct _graph_t graph_t;
 struct _graph_t {
   chain_t *chain; /* links are supposed to be done now */
   GSList *links;
   GError **error;
+  reason_receiver_t *error_probable_reason_receiver;
   GstParseContext *ctx; /* may be NULL */
   GstParseFlags flags;
 };
diff --git a/gst/printf/vasnprintf.c b/gst/printf/vasnprintf.c
index b202c62..540d647 100644
--- a/gst/printf/vasnprintf.c
+++ b/gst/printf/vasnprintf.c
@@ -646,7 +646,7 @@ vasnprintf (char *resultbuf, size_t *lengthp, const char *format, va_list args)
               break;
 #else
               *p++ = 'l';
-               /*FALLTHROUGH*/
+              G_GNUC_FALLTHROUGH;
 #endif
 #endif
             case TYPE_LONGINT:
diff --git a/gstreamer.doap b/gstreamer.doap
index 66d4c32..a8aa804 100644
--- a/gstreamer.doap
+++ b/gstreamer.doap
@@ -40,121 +40,41 @@ hierarchy, and a set of media-agnostic core elements.
 
  <release>
   <Version>
-   <revision>1.24.12</revision>
-   <branch>1.24</branch>
-   <name></name>
-   <created>2025-01-29</created>
-   <file-release rdf:resource="https://gstreamer.freedesktop.org/src/gstreamer/gstreamer-1.24.12.tar.xz" />
-  </Version>
- </release>
-
- <release>
-  <Version>
-   <revision>1.24.11</revision>
-   <branch>1.24</branch>
-   <name></name>
-   <created>2025-01-06</created>
-   <file-release rdf:resource="https://gstreamer.freedesktop.org/src/gstreamer/gstreamer-1.24.11.tar.xz" />
-  </Version>
- </release>
-
- <release>
-  <Version>
-   <revision>1.24.10</revision>
-   <branch>1.24</branch>
-   <name></name>
-   <created>2024-12-03</created>
-   <file-release rdf:resource="https://gstreamer.freedesktop.org/src/gstreamer/gstreamer-1.24.10.tar.xz" />
-  </Version>
- </release>
-
- <release>
-  <Version>
-   <revision>1.24.9</revision>
-   <branch>1.24</branch>
-   <name></name>
-   <created>2024-10-30</created>
-   <file-release rdf:resource="https://gstreamer.freedesktop.org/src/gstreamer/gstreamer-1.24.9.tar.xz" />
-  </Version>
- </release>
-
- <release>
-  <Version>
-   <revision>1.24.8</revision>
-   <branch>1.24</branch>
-   <name></name>
-   <created>2024-09-19</created>
-   <file-release rdf:resource="https://gstreamer.freedesktop.org/src/gstreamer/gstreamer-1.24.8.tar.xz" />
-  </Version>
- </release>
-
- <release>
-  <Version>
-   <revision>1.24.7</revision>
-   <branch>1.24</branch>
-   <name></name>
-   <created>2024-08-21</created>
-   <file-release rdf:resource="https://gstreamer.freedesktop.org/src/gstreamer/gstreamer-1.24.7.tar.xz" />
-  </Version>
- </release>
-
- <release>
-  <Version>
-   <revision>1.24.6</revision>
-   <branch>1.24</branch>
-   <name></name>
-   <created>2024-07-29</created>
-   <file-release rdf:resource="https://gstreamer.freedesktop.org/src/gstreamer/gstreamer-1.24.6.tar.xz" />
-  </Version>
- </release>
-
- <release>
-  <Version>
-   <revision>1.24.5</revision>
-   <branch>1.24</branch>
-   <name></name>
-   <created>2024-06-20</created>
-   <file-release rdf:resource="https://gstreamer.freedesktop.org/src/gstreamer/gstreamer-1.24.5.tar.xz" />
-  </Version>
- </release>
-
- <release>
-  <Version>
-   <revision>1.24.4</revision>
-   <branch>1.24</branch>
+   <revision>1.26.0</revision>
+   <branch>main</branch>
    <name></name>
-   <created>2024-05-29</created>
-   <file-release rdf:resource="https://gstreamer.freedesktop.org/src/gstreamer/gstreamer-1.24.4.tar.xz" />
+   <created>2025-03-11</created>
+   <file-release rdf:resource="https://gstreamer.freedesktop.org/src/gstreamer/gstreamer-1.26.0.tar.xz" />
   </Version>
  </release>
 
  <release>
   <Version>
-   <revision>1.24.3</revision>
-   <branch>1.24</branch>
+   <revision>1.25.90</revision>
+   <branch>main</branch>
    <name></name>
-   <created>2024-04-30</created>
-   <file-release rdf:resource="https://gstreamer.freedesktop.org/src/gstreamer/gstreamer-1.24.3.tar.xz" />
+   <created>2025-02-23</created>
+   <file-release rdf:resource="https://gstreamer.freedesktop.org/src/gstreamer/gstreamer-1.25.90.tar.xz" />
   </Version>
  </release>
 
  <release>
   <Version>
-   <revision>1.24.2</revision>
-   <branch>1.24</branch>
+   <revision>1.25.50</revision>
+   <branch>main</branch>
    <name></name>
-   <created>2024-04-09</created>
-   <file-release rdf:resource="https://gstreamer.freedesktop.org/src/gstreamer/gstreamer-1.24.2.tar.xz" />
+   <created>2025-02-09</created>
+   <file-release rdf:resource="https://gstreamer.freedesktop.org/src/gstreamer/gstreamer-1.25.50.tar.xz" />
   </Version>
  </release>
 
  <release>
   <Version>
-   <revision>1.24.1</revision>
-   <branch>1.24</branch>
+   <revision>1.25.1</revision>
+   <branch>main</branch>
    <name></name>
-   <created>2024-03-21</created>
-   <file-release rdf:resource="https://gstreamer.freedesktop.org/src/gstreamer/gstreamer-1.24.1.tar.xz" />
+   <created>2025-01-14</created>
+   <file-release rdf:resource="https://gstreamer.freedesktop.org/src/gstreamer/gstreamer-1.25.1.tar.xz" />
   </Version>
  </release>
 
diff --git a/libs/gst/base/base-prelude.h b/libs/gst/base/base-prelude.h
index 87defde..d1a9c36 100644
--- a/libs/gst/base/base-prelude.h
+++ b/libs/gst/base/base-prelude.h
@@ -32,4 +32,16 @@
 #endif
 #endif
 
+#ifndef GST_DISABLE_DEPRECATED
+#define GST_BASE_DEPRECATED GST_BASE_API
+#define GST_BASE_DEPRECATED_FOR(f) GST_BASE_API
+#define GST_BASE_DEPRECATED_TYPE
+#define GST_BASE_DEPRECATED_TYPE_FOR(f)
+#else
+#define GST_BASE_DEPRECATED G_DEPRECATED GST_BASE_API
+#define GST_BASE_DEPRECATED_FOR(f) G_DEPRECATED_FOR(f) GST_BASE_API
+#define GST_BASE_DEPRECATED_TYPE G_DEPRECATED
+#define GST_BASE_DEPRECATED_TYPE_FOR(f) G_DEPRECATED_FOR(f)
+#endif
+
 #endif /* __GST_BASE_PRELUDE_H__ */
diff --git a/libs/gst/base/gstadapter.c b/libs/gst/base/gstadapter.c
index 12d7569..9aa51b0 100644
--- a/libs/gst/base/gstadapter.c
+++ b/libs/gst/base/gstadapter.c
@@ -142,7 +142,7 @@ struct _GstAdapter
   GObject object;
 
   /*< private > */
-  GstQueueArray *bufqueue;
+  GstVecDeque *bufqueue;
   gsize size;
   gsize skip;
   guint count;
@@ -209,7 +209,7 @@ gst_adapter_init (GstAdapter * adapter)
   adapter->dts_at_discont = GST_CLOCK_TIME_NONE;
   adapter->offset_at_discont = GST_BUFFER_OFFSET_NONE;
   adapter->distance_from_discont = 0;
-  adapter->bufqueue = gst_queue_array_new (10);
+  adapter->bufqueue = gst_vec_deque_new (10);
 }
 
 static void
@@ -229,7 +229,7 @@ gst_adapter_finalize (GObject * object)
 
   g_free (adapter->assembled_data);
 
-  gst_queue_array_free (adapter->bufqueue);
+  gst_vec_deque_free (adapter->bufqueue);
 
   GST_CALL_PARENT (G_OBJECT_CLASS, finalize, (object));
 }
@@ -262,7 +262,7 @@ gst_adapter_clear (GstAdapter * adapter)
   if (adapter->info.memory)
     gst_adapter_unmap (adapter);
 
-  while ((obj = gst_queue_array_pop_head (adapter->bufqueue)))
+  while ((obj = gst_vec_deque_pop_head (adapter->bufqueue)))
     gst_mini_object_unref (obj);
 
   adapter->count = 0;
@@ -334,11 +334,11 @@ copy_into_unchecked (GstAdapter * adapter, guint8 * dest, gsize skip,
   } else {
     idx = 0;
   }
-  buf = gst_queue_array_peek_nth (adapter->bufqueue, idx++);
+  buf = gst_vec_deque_peek_nth (adapter->bufqueue, idx++);
   bsize = gst_buffer_get_size (buf);
   while (G_UNLIKELY (skip >= bsize)) {
     skip -= bsize;
-    buf = gst_queue_array_peek_nth (adapter->bufqueue, idx++);
+    buf = gst_vec_deque_peek_nth (adapter->bufqueue, idx++);
     bsize = gst_buffer_get_size (buf);
   }
   /* copy partial buffer */
@@ -353,7 +353,7 @@ copy_into_unchecked (GstAdapter * adapter, guint8 * dest, gsize skip,
 
   /* second step, copy remainder */
   while (size > 0) {
-    buf = gst_queue_array_peek_nth (adapter->bufqueue, idx++);
+    buf = gst_vec_deque_peek_nth (adapter->bufqueue, idx++);
     bsize = gst_buffer_get_size (buf);
     if (G_LIKELY (bsize > 0)) {
       csize = MIN (bsize, size);
@@ -386,16 +386,16 @@ gst_adapter_push (GstAdapter * adapter, GstBuffer * buf)
   adapter->size += size;
 
   /* Note: merging buffers at this point is premature. */
-  if (gst_queue_array_is_empty (adapter->bufqueue)) {
+  if (gst_vec_deque_is_empty (adapter->bufqueue)) {
     GST_LOG_OBJECT (adapter, "pushing %p first %" G_GSIZE_FORMAT " bytes",
         buf, size);
-    gst_queue_array_push_tail (adapter->bufqueue, buf);
+    gst_vec_deque_push_tail (adapter->bufqueue, buf);
     update_timestamps_and_offset (adapter, buf);
   } else {
     /* Otherwise append to the end, and advance our end pointer */
     GST_LOG_OBJECT (adapter, "pushing %p %" G_GSIZE_FORMAT " bytes at end, "
         "size now %" G_GSIZE_FORMAT, buf, size, adapter->size);
-    gst_queue_array_push_tail (adapter->bufqueue, buf);
+    gst_vec_deque_push_tail (adapter->bufqueue, buf);
   }
   ++adapter->count;
 }
@@ -507,7 +507,7 @@ gst_adapter_map (GstAdapter * adapter, gsize size)
 #if 0
   do {
 #endif
-    cur = gst_queue_array_peek_head (adapter->bufqueue);
+    cur = gst_vec_deque_peek_head (adapter->bufqueue);
     skip = adapter->skip;
 
     csize = gst_buffer_get_size (cur);
@@ -568,7 +568,7 @@ gst_adapter_unmap (GstAdapter * adapter)
   g_return_if_fail (GST_IS_ADAPTER (adapter));
 
   if (adapter->info.memory) {
-    GstBuffer *cur = gst_queue_array_peek_head (adapter->bufqueue);
+    GstBuffer *cur = gst_vec_deque_peek_head (adapter->bufqueue);
     GST_LOG_OBJECT (adapter, "unmap memory buffer %p", cur);
     gst_buffer_unmap (cur, &adapter->info);
     adapter->info.memory = NULL;
@@ -648,7 +648,7 @@ gst_adapter_flush_unchecked (GstAdapter * adapter, gsize flush)
   adapter->offset_distance -= adapter->skip;
   adapter->distance_from_discont -= adapter->skip;
 
-  cur = gst_queue_array_peek_head (adapter->bufqueue);
+  cur = gst_vec_deque_peek_head (adapter->bufqueue);
   size = gst_buffer_get_size (cur);
   while (flush >= size) {
     /* can skip whole buffer */
@@ -662,14 +662,14 @@ gst_adapter_flush_unchecked (GstAdapter * adapter, gsize flush)
     --adapter->count;
 
     cur = NULL;
-    gst_buffer_unref (gst_queue_array_pop_head (adapter->bufqueue));
+    gst_buffer_unref (gst_vec_deque_pop_head (adapter->bufqueue));
 
-    if (gst_queue_array_is_empty (adapter->bufqueue)) {
+    if (gst_vec_deque_is_empty (adapter->bufqueue)) {
       GST_LOG_OBJECT (adapter, "adapter empty now");
       break;
     }
     /* there is a new head buffer, update the timestamps */
-    cur = gst_queue_array_peek_head (adapter->bufqueue);
+    cur = gst_vec_deque_peek_head (adapter->bufqueue);
     update_timestamps_and_offset (adapter, cur);
     size = gst_buffer_get_size (cur);
   }
@@ -828,7 +828,7 @@ gst_adapter_get_buffer_fast (GstAdapter * adapter, gsize nbytes)
     return NULL;
 
   skip = adapter->skip;
-  cur = gst_queue_array_peek_head (adapter->bufqueue);
+  cur = gst_vec_deque_peek_head (adapter->bufqueue);
 
   if (skip == 0 && gst_buffer_get_size (cur) == nbytes) {
     GST_LOG_OBJECT (adapter, "providing buffer of %" G_GSIZE_FORMAT " bytes"
@@ -837,12 +837,12 @@ gst_adapter_get_buffer_fast (GstAdapter * adapter, gsize nbytes)
     goto done;
   }
 
-  len = gst_queue_array_get_length (adapter->bufqueue);
+  len = gst_vec_deque_get_length (adapter->bufqueue);
 
   for (idx = 0; idx < len && left > 0; idx++) {
     gsize size, cur_size;
 
-    cur = gst_queue_array_peek_nth (adapter->bufqueue, idx);
+    cur = gst_vec_deque_peek_nth (adapter->bufqueue, idx);
     cur_size = gst_buffer_get_size (cur);
     size = MIN (cur_size - skip, left);
 
@@ -980,7 +980,7 @@ gst_adapter_get_buffer (GstAdapter * adapter, gsize nbytes)
   if (G_UNLIKELY (nbytes > adapter->size))
     return NULL;
 
-  cur = gst_queue_array_peek_head (adapter->bufqueue);
+  cur = gst_vec_deque_peek_head (adapter->bufqueue);
   skip = adapter->skip;
   hsize = gst_buffer_get_size (cur);
 
@@ -1020,10 +1020,10 @@ gst_adapter_get_buffer (GstAdapter * adapter, gsize nbytes)
     gsize read_offset = 0;
 
     idx = 0;
-    len = gst_queue_array_get_length (adapter->bufqueue);
+    len = gst_vec_deque_get_length (adapter->bufqueue);
 
     while (idx < len && read_offset < nbytes + adapter->skip) {
-      cur = gst_queue_array_peek_nth (adapter->bufqueue, idx);
+      cur = gst_vec_deque_peek_nth (adapter->bufqueue, idx);
 
       gst_buffer_foreach_meta (cur, foreach_metadata, buffer);
       read_offset += gst_buffer_get_size (cur);
@@ -1111,7 +1111,7 @@ gst_adapter_take_list (GstAdapter * adapter, gsize nbytes)
   GST_LOG_OBJECT (adapter, "taking %" G_GSIZE_FORMAT " bytes", nbytes);
 
   while (nbytes > 0) {
-    cur = gst_queue_array_peek_head (adapter->bufqueue);
+    cur = gst_vec_deque_peek_head (adapter->bufqueue);
     skip = adapter->skip;
     cur_size = gst_buffer_get_size (cur);
     hsize = MIN (nbytes, cur_size - skip);
@@ -1160,7 +1160,7 @@ gst_adapter_get_list (GstAdapter * adapter, gsize nbytes)
   skip = adapter->skip;
 
   while (nbytes > 0) {
-    cur = gst_queue_array_peek_nth (adapter->bufqueue, idx++);
+    cur = gst_vec_deque_peek_nth (adapter->bufqueue, idx++);
     cur_size = gst_buffer_get_size (cur);
     hsize = MIN (nbytes, cur_size - skip);
 
@@ -1226,7 +1226,7 @@ gst_adapter_take_buffer_list (GstAdapter * adapter, gsize nbytes)
   buffer_list = gst_buffer_list_new_sized (n_bufs);
 
   while (nbytes > 0) {
-    cur = gst_queue_array_peek_head (adapter->bufqueue);
+    cur = gst_vec_deque_peek_head (adapter->bufqueue);
     skip = adapter->skip;
     cur_size = gst_buffer_get_size (cur);
     hsize = MIN (nbytes, cur_size - skip);
@@ -1283,7 +1283,7 @@ gst_adapter_get_buffer_list (GstAdapter * adapter, gsize nbytes)
   skip = adapter->skip;
 
   while (nbytes > 0) {
-    cur = gst_queue_array_peek_nth (adapter->bufqueue, idx++);
+    cur = gst_vec_deque_peek_nth (adapter->bufqueue, idx++);
     cur_size = gst_buffer_get_size (cur);
     hsize = MIN (nbytes, cur_size - skip);
 
@@ -1314,6 +1314,10 @@ gst_adapter_get_buffer_list (GstAdapter * adapter, gsize nbytes)
  * value that can be supplied to gst_adapter_map() without that function
  * returning %NULL.
  *
+ * Calling gst_adapter_map() with the amount of bytes returned by this function
+ * may require expensive operations (like copying the data into a temporary
+ * buffer) in some cases.
+ *
  * Returns: number of bytes available in @adapter
  */
 gsize
@@ -1328,8 +1332,11 @@ gst_adapter_available (GstAdapter * adapter)
  * gst_adapter_available_fast:
  * @adapter: a #GstAdapter
  *
- * Gets the maximum number of bytes that are immediately available without
- * requiring any expensive operations (like copying the data into a
+ * Gets the maximum number of bytes that can be retrieved in a single map
+ * operation without merging buffers.
+ *
+ * Calling gst_adapter_map() with the amount of bytes returned by this function
+ * will never require any expensive operations (like copying the data into a
  * temporary buffer).
  *
  * Returns: number of bytes that are available in @adapter without expensive
@@ -1355,7 +1362,7 @@ gst_adapter_available_fast (GstAdapter * adapter)
   /* take the first non-zero buffer */
   idx = 0;
   while (TRUE) {
-    cur = gst_queue_array_peek_nth (adapter->bufqueue, idx++);
+    cur = gst_vec_deque_peek_nth (adapter->bufqueue, idx++);
     size = gst_buffer_get_size (cur);
     if (size != 0)
       break;
@@ -1454,7 +1461,7 @@ gst_adapter_dts_at_discont (GstAdapter * adapter)
  *
  * The offset is reset to GST_BUFFER_OFFSET_NONE and the distance is set to 0
  * when the adapter is first created or when it is cleared. This also means that
- * before the first byte with an offset is removed from the adapter, the offset
+ * before the first byte with an offset is added to the adapter, the offset
  * and distance returned are GST_BUFFER_OFFSET_NONE and 0 respectively.
  *
  * Since: 1.10
@@ -1483,7 +1490,7 @@ gst_adapter_prev_offset (GstAdapter * adapter, guint64 * distance)
  *
  * The pts is reset to GST_CLOCK_TIME_NONE and the distance is set to 0 when
  * the adapter is first created or when it is cleared. This also means that before
- * the first byte with a pts is removed from the adapter, the pts
+ * the first byte with a pts is added to the adapter, the pts
  * and distance returned are GST_CLOCK_TIME_NONE and 0 respectively.
  *
  * Returns: The previously seen pts.
@@ -1510,7 +1517,7 @@ gst_adapter_prev_pts (GstAdapter * adapter, guint64 * distance)
  *
  * The dts is reset to GST_CLOCK_TIME_NONE and the distance is set to 0 when
  * the adapter is first created or when it is cleared. This also means that before
- * the first byte with a dts is removed from the adapter, the dts
+ * the first byte with a dts is added to the adapter, the dts
  * and distance returned are GST_CLOCK_TIME_NONE and 0 respectively.
  *
  * Returns: The previously seen dts.
@@ -1538,7 +1545,7 @@ gst_adapter_prev_dts (GstAdapter * adapter, guint64 * distance)
  *
  * The pts is reset to GST_CLOCK_TIME_NONE and the distance is set to 0 when
  * the adapter is first created or when it is cleared. This also means that before
- * the first byte with a pts is removed from the adapter, the pts
+ * the first byte with a pts is added to the adapter, the pts
  * and distance returned are GST_CLOCK_TIME_NONE and 0 respectively.
  *
  * Since: 1.2
@@ -1557,10 +1564,10 @@ gst_adapter_prev_pts_at_offset (GstAdapter * adapter, gsize offset,
   g_return_val_if_fail (GST_IS_ADAPTER (adapter), GST_CLOCK_TIME_NONE);
 
   idx = 0;
-  len = gst_queue_array_get_length (adapter->bufqueue);
+  len = gst_vec_deque_get_length (adapter->bufqueue);
 
   while (idx < len && read_offset < offset + adapter->skip) {
-    cur = gst_queue_array_peek_nth (adapter->bufqueue, idx++);
+    cur = gst_vec_deque_peek_nth (adapter->bufqueue, idx++);
 
     if (GST_CLOCK_TIME_IS_VALID (GST_BUFFER_PTS (cur))) {
       pts = GST_BUFFER_PTS (cur);
@@ -1588,7 +1595,7 @@ gst_adapter_prev_pts_at_offset (GstAdapter * adapter, gsize offset,
  *
  * The dts is reset to GST_CLOCK_TIME_NONE and the distance is set to 0 when
  * the adapter is first created or when it is cleared. This also means that before
- * the first byte with a dts is removed from the adapter, the dts
+ * the first byte with a dts is added to the adapter, the dts
  * and distance returned are GST_CLOCK_TIME_NONE and 0 respectively.
  *
  * Since: 1.2
@@ -1607,10 +1614,10 @@ gst_adapter_prev_dts_at_offset (GstAdapter * adapter, gsize offset,
   g_return_val_if_fail (GST_IS_ADAPTER (adapter), GST_CLOCK_TIME_NONE);
 
   idx = 0;
-  len = gst_queue_array_get_length (adapter->bufqueue);
+  len = gst_vec_deque_get_length (adapter->bufqueue);
 
   while (idx < len && read_offset < offset + adapter->skip) {
-    cur = gst_queue_array_peek_nth (adapter->bufqueue, idx++);
+    cur = gst_vec_deque_peek_nth (adapter->bufqueue, idx++);
 
     if (GST_CLOCK_TIME_IS_VALID (GST_BUFFER_DTS (cur))) {
       dts = GST_BUFFER_DTS (cur);
@@ -1680,13 +1687,13 @@ gst_adapter_masked_scan_uint32_peek (GstAdapter * adapter, guint32 mask,
     adapter->scan_offset = 0;
     adapter->scan_entry_idx = G_MAXUINT;
   }
-  buf = gst_queue_array_peek_nth (adapter->bufqueue, idx++);
+  buf = gst_vec_deque_peek_nth (adapter->bufqueue, idx++);
   bsize = gst_buffer_get_size (buf);
   while (G_UNLIKELY (skip >= bsize)) {
     skip -= bsize;
     adapter->scan_offset += bsize;
     adapter->scan_entry_idx = idx;
-    buf = gst_queue_array_peek_nth (adapter->bufqueue, idx++);
+    buf = gst_vec_deque_peek_nth (adapter->bufqueue, idx++);
     bsize = gst_buffer_get_size (buf);
   }
   /* get the data now */
@@ -1725,7 +1732,7 @@ gst_adapter_masked_scan_uint32_peek (GstAdapter * adapter, guint32 mask,
     adapter->scan_offset += info.size;
     adapter->scan_entry_idx = idx;
     gst_buffer_unmap (buf, &info);
-    buf = gst_queue_array_peek_nth (adapter->bufqueue, idx++);
+    buf = gst_vec_deque_peek_nth (adapter->bufqueue, idx++);
 
     if (!gst_buffer_map (buf, &info, GST_MAP_READ))
       return -1;
diff --git a/libs/gst/base/gstaggregator.c b/libs/gst/base/gstaggregator.c
index c93feef..b2d6fcb 100644
--- a/libs/gst/base/gstaggregator.c
+++ b/libs/gst/base/gstaggregator.c
@@ -135,11 +135,6 @@ gst_aggregator_start_time_selection_get_type (void)
   return gtype;
 }
 
-/*  Might become API */
-#if 0
-static void gst_aggregator_merge_tags (GstAggregator * aggregator,
-    const GstTagList * tags, GstTagMergeMode mode);
-#endif
 static void gst_aggregator_set_latency_property (GstAggregator * agg,
     GstClockTime latency);
 static GstClockTime gst_aggregator_get_latency_property (GstAggregator * agg);
@@ -385,9 +380,6 @@ struct _GstAggregatorPrivate
 
   GstCaps *srccaps;             /* protected by the srcpad stream lock */
 
-  GstTagList *tags;
-  gboolean tags_changed;
-
   gboolean peer_latency_live;   /* protected by src_lock */
   GstClockTime peer_latency_min;        /* protected by src_lock */
   GstClockTime peer_latency_max;        /* protected by src_lock */
@@ -633,9 +625,7 @@ gst_aggregator_reset_flow_values (GstAggregator * self)
 static inline void
 gst_aggregator_push_mandatory_events (GstAggregator * self, gboolean up_to_caps)
 {
-  GstAggregatorPrivate *priv = self->priv;
   GstEvent *segment = NULL;
-  GstEvent *tags = NULL;
 
   if (self->priv->send_stream_start) {
     gchar s_id[32];
@@ -679,17 +669,10 @@ gst_aggregator_push_mandatory_events (GstAggregator * self, gboolean up_to_caps)
 
     GST_DEBUG_OBJECT (self, "pushing segment %" GST_PTR_FORMAT, segment);
   }
-
-  if (priv->tags && priv->tags_changed && !self->priv->flushing) {
-    tags = gst_event_new_tag (gst_tag_list_ref (priv->tags));
-    priv->tags_changed = FALSE;
-  }
   GST_OBJECT_UNLOCK (self);
 
   if (segment)
     gst_pad_push_event (self->srcpad, segment);
-  if (tags)
-    gst_pad_push_event (self->srcpad, tags);
 }
 
 /**
@@ -803,6 +786,36 @@ gst_aggregator_finish_buffer_list (GstAggregator * aggregator,
   return klass->finish_buffer_list (aggregator, bufferlist);
 }
 
+/**
+ * gst_aggregator_push_src_event:
+ * @aggregator: The #GstAggregator
+ * @event: (transfer full): the #GstEvent to push.
+ *
+ * This method will push the provided event downstream. If needed, mandatory
+ * events such as stream-start, caps, and segment events will be sent before
+ * pushing the event.
+ *
+ * This API does not allow pushing stream-start, caps, segment and EOS events.
+ * Specific API like gst_aggregator_set_src_caps() should be used for these.
+ *
+ * Since: 1.26
+ */
+gboolean
+gst_aggregator_push_src_event (GstAggregator * aggregator, GstEvent * event)
+{
+  g_return_val_if_fail (GST_EVENT_IS_DOWNSTREAM (event), FALSE);
+  g_return_val_if_fail (GST_EVENT_TYPE (event) != GST_EVENT_STREAM_START &&
+      GST_EVENT_TYPE (event) != GST_EVENT_CAPS &&
+      GST_EVENT_TYPE (event) != GST_EVENT_SEGMENT &&
+      GST_EVENT_TYPE (event) != GST_EVENT_EOS, FALSE);
+
+  if (GST_EVENT_IS_SERIALIZED (event)) {
+    gst_aggregator_push_mandatory_events (aggregator, FALSE);
+  }
+
+  return gst_pad_push_event (aggregator->srcpad, event);
+}
+
 static void
 gst_aggregator_push_eos (GstAggregator * self)
 {
@@ -1296,12 +1309,12 @@ gst_aggregator_default_negotiate (GstAggregator * self)
   GST_DEBUG_OBJECT (self, "updating caps from %" GST_PTR_FORMAT,
       downstream_caps);
   ret = agg_klass->update_src_caps (self, downstream_caps, &caps);
-  if (ret < GST_FLOW_OK) {
-    GST_WARNING_OBJECT (self, "Subclass failed to update provided caps");
-    goto done;
-  } else if (ret == GST_AGGREGATOR_FLOW_NEED_DATA) {
+  if (ret == GST_AGGREGATOR_FLOW_NEED_DATA) {
     GST_DEBUG_OBJECT (self, "Subclass needs more data to decide on caps");
     goto done;
+  } else if (ret < GST_FLOW_OK) {
+    GST_WARNING_OBJECT (self, "Subclass failed to update provided caps");
+    goto done;
   }
   if ((caps == NULL || gst_caps_is_empty (caps)) && ret >= GST_FLOW_OK) {
     ret = GST_FLOW_NOT_NEGOTIATED;
@@ -1651,7 +1664,6 @@ gst_aggregator_flush (GstAggregator * self)
   GST_OBJECT_LOCK (self);
   priv->send_segment = TRUE;
   priv->flushing = FALSE;
-  priv->tags_changed = FALSE;
   GST_OBJECT_UNLOCK (self);
   if (klass->flush)
     ret = klass->flush (self);
@@ -2054,10 +2066,6 @@ gst_aggregator_stop (GstAggregator * agg)
   agg->priv->peer_latency_min = agg->priv->peer_latency_max = 0;
   agg->priv->posted_latency_msg = FALSE;
 
-  if (agg->priv->tags)
-    gst_tag_list_unref (agg->priv->tags);
-  agg->priv->tags = NULL;
-
   gst_aggregator_set_allocation (agg, NULL, NULL, NULL, NULL);
 
   if (agg->priv->running) {
@@ -2841,6 +2849,8 @@ gst_aggregator_constructed (GObject * object)
 {
   GstAggregator *agg = GST_AGGREGATOR (object);
 
+  G_OBJECT_CLASS (aggregator_parent_class)->constructed (object);
+
   if (agg->priv->force_live) {
     GST_OBJECT_FLAG_SET (agg, GST_ELEMENT_FLAG_SOURCE);
   }
@@ -3141,7 +3151,6 @@ gst_aggregator_init (GstAggregator * self, GstAggregatorClass * klass)
   g_return_if_fail (pad_template != NULL);
 
   priv->max_padserial = -1;
-  priv->tags_changed = FALSE;
   priv->ignore_inactive_pads = FALSE;
 
   self->priv->peer_latency_live = FALSE;
@@ -3503,6 +3512,8 @@ gst_aggregator_pad_constructed (GObject * object)
 {
   GstPad *pad = GST_PAD (object);
 
+  G_OBJECT_CLASS (gst_aggregator_pad_parent_class)->constructed (object);
+
   if (GST_PAD_IS_SINK (pad)) {
     gst_pad_set_chain_function (pad,
         GST_DEBUG_FUNCPTR (gst_aggregator_pad_chain));
@@ -3883,43 +3894,6 @@ gst_aggregator_pad_is_inactive (GstAggregatorPad * pad)
   return inactive;
 }
 
-#if 0
-/*
- * gst_aggregator_merge_tags:
- * @self: a #GstAggregator
- * @tags: a #GstTagList to merge
- * @mode: the #GstTagMergeMode to use
- *
- * Adds tags to so-called pending tags, which will be processed
- * before pushing out data downstream.
- *
- * Note that this is provided for convenience, and the subclass is
- * not required to use this and can still do tag handling on its own.
- *
- * MT safe.
- */
-void
-gst_aggregator_merge_tags (GstAggregator * self,
-    const GstTagList * tags, GstTagMergeMode mode)
-{
-  GstTagList *otags;
-
-  g_return_if_fail (GST_IS_AGGREGATOR (self));
-  g_return_if_fail (tags == NULL || GST_IS_TAG_LIST (tags));
-
-  /* FIXME Check if we can use OBJECT lock here! */
-  GST_OBJECT_LOCK (self);
-  if (tags)
-    GST_DEBUG_OBJECT (self, "merging tags %" GST_PTR_FORMAT, tags);
-  otags = self->priv->tags;
-  self->priv->tags = gst_tag_list_merge (self->priv->tags, tags, mode);
-  if (otags)
-    gst_tag_list_unref (otags);
-  self->priv->tags_changed = TRUE;
-  GST_OBJECT_UNLOCK (self);
-}
-#endif
-
 /**
  * gst_aggregator_set_latency:
  * @self: a #GstAggregator
diff --git a/libs/gst/base/gstaggregator.h b/libs/gst/base/gstaggregator.h
index bbac9e4..7c394a7 100644
--- a/libs/gst/base/gstaggregator.h
+++ b/libs/gst/base/gstaggregator.h
@@ -383,6 +383,10 @@ GST_BASE_API
 GstFlowReturn  gst_aggregator_finish_buffer_list    (GstAggregator                *  aggregator,
                                                      GstBufferList                *  bufferlist);
 
+GST_BASE_API
+gboolean       gst_aggregator_push_src_event        (GstAggregator                *  aggregator,
+                                                     GstEvent                     *  event);
+
 GST_BASE_API
 void           gst_aggregator_set_src_caps          (GstAggregator                *  self,
                                                      GstCaps                      *  caps);
diff --git a/libs/gst/base/gstbaseparse.c b/libs/gst/base/gstbaseparse.c
index 422e489..472f88f 100644
--- a/libs/gst/base/gstbaseparse.c
+++ b/libs/gst/base/gstbaseparse.c
@@ -952,16 +952,11 @@ gst_base_parse_queue_tag_event_update (GstBaseParse * parse)
   GST_DEBUG_OBJECT (parse, "merged   : %" GST_PTR_FORMAT, merged_tags);
 
   if (merged_tags == NULL)
-    return;
-
-  if (gst_tag_list_is_empty (merged_tags)) {
-    gst_tag_list_unref (merged_tags);
-    return;
-  }
+    merged_tags = gst_tag_list_new_empty ();
 
   if (parse->priv->framecount >= MIN_FRAMES_TO_POST_BITRATE) {
-    /* only add bitrate tags to non-empty taglists for now, and only if neither
-     * upstream tags nor the subclass sets the bitrate tag in question already */
+    /* only add bitrate tags if neither upstream tags nor the subclass sets the
+     * bitrate tag in question already */
     if (parse->priv->min_bitrate != G_MAXUINT && parse->priv->post_min_bitrate) {
       GST_LOG_OBJECT (parse, "adding min bitrate %u", parse->priv->min_bitrate);
       gst_tag_list_add (merged_tags, GST_TAG_MERGE_KEEP,
@@ -980,6 +975,11 @@ gst_base_parse_queue_tag_event_update (GstBaseParse * parse)
     }
   }
 
+  if (gst_tag_list_is_empty (merged_tags)) {
+    gst_tag_list_unref (merged_tags);
+    return;
+  }
+
   parse->priv->pending_events =
       g_list_prepend (parse->priv->pending_events,
       gst_event_new_tag (merged_tags));
@@ -1111,7 +1111,7 @@ gst_base_parse_convert (GstBaseParse * parse,
 }
 
 static gboolean
-update_upstream_provided (GQuark field_id, const GValue * value,
+update_upstream_provided (const GstIdStr * field, const GValue * value,
     gpointer user_data)
 {
   GstCaps *default_caps = user_data;
@@ -1121,8 +1121,8 @@ update_upstream_provided (GQuark field_id, const GValue * value,
   caps_size = gst_caps_get_size (default_caps);
   for (i = 0; i < caps_size; i++) {
     GstStructure *structure = gst_caps_get_structure (default_caps, i);
-    if (!gst_structure_id_has_field (structure, field_id)) {
-      gst_structure_id_set_value (structure, field_id, value);
+    if (!gst_structure_has_field (structure, gst_id_str_as_str (field))) {
+      gst_structure_id_str_set_value (structure, field, value);
     }
     /* XXX: maybe try to fixate better than gst_caps_fixate() the
      * downstream caps based on upstream values if possible */
@@ -1162,7 +1162,8 @@ gst_base_parse_negotiate_default_caps (GstBaseParse * parse)
 
   if (sinkcaps) {
     structure = gst_caps_get_structure (sinkcaps, 0);
-    gst_structure_foreach (structure, update_upstream_provided, default_caps);
+    gst_structure_foreach_id_str (structure, update_upstream_provided,
+        default_caps);
   }
 
   default_caps = gst_caps_fixate (default_caps);
diff --git a/libs/gst/base/gstbasesink.c b/libs/gst/base/gstbasesink.c
index e94a957..e0d31b3 100644
--- a/libs/gst/base/gstbasesink.c
+++ b/libs/gst/base/gstbasesink.c
@@ -254,7 +254,6 @@ struct _GstBaseSinkPrivate
   /* seqnum of the last instant-rate event.
    * %GST_SEQNUM_INVALID if there isn't one */
   guint32 last_instant_rate_seqnum;
-  guint32 segment_seqnum;
   GstSegment upstream_segment;
   /* Running time at the start of the last segment event
    * or instant-rate switch in *our* segment, not upstream */
@@ -3281,7 +3280,6 @@ gst_base_sink_flush_stop (GstBaseSink * basesink, GstPad * pad,
       basesink->priv->last_instant_rate_seqnum = GST_SEQNUM_INVALID;
       basesink->priv->instant_rate_sync_seqnum = GST_SEQNUM_INVALID;
       basesink->priv->instant_rate_multiplier = 0;
-      basesink->priv->segment_seqnum = GST_SEQNUM_INVALID;
       basesink->priv->instant_rate_offset = 0;
       basesink->priv->last_anchor_running_time = 0;
     }
@@ -3558,7 +3556,6 @@ gst_base_sink_default_event (GstBaseSink * basesink, GstEvent * event)
 
       GST_DEBUG_OBJECT (basesink, "configured segment %" GST_SEGMENT_FORMAT,
           &basesink->segment);
-      basesink->priv->segment_seqnum = seqnum;
       basesink->have_newsegment = TRUE;
       gst_base_sink_reset_qos (basesink);
       GST_OBJECT_UNLOCK (basesink);
@@ -5719,7 +5716,6 @@ gst_base_sink_change_state (GstElement * element, GstStateChange transition)
       priv->instant_rate_sync_seqnum = GST_SEQNUM_INVALID;
       priv->instant_rate_multiplier = 0;
       priv->last_instant_rate_seqnum = GST_SEQNUM_INVALID;
-      priv->segment_seqnum = GST_SEQNUM_INVALID;
       priv->instant_rate_offset = 0;
       priv->last_anchor_running_time = 0;
       if (priv->async_enabled) {
diff --git a/libs/gst/base/gstbasesrc.c b/libs/gst/base/gstbasesrc.c
index a840b4a..a6d1f6a 100644
--- a/libs/gst/base/gstbasesrc.c
+++ b/libs/gst/base/gstbasesrc.c
@@ -1844,8 +1844,10 @@ gst_base_src_perform_seek (GstBaseSrc * src, GstEvent * event, gboolean unlock)
       gst_element_post_message (GST_ELEMENT (src), message);
     }
 
+    GST_OBJECT_LOCK (src);
     src->priv->segment_pending = TRUE;
     src->priv->segment_seqnum = seqnum;
+    GST_OBJECT_UNLOCK (src);
   }
 
   src->priv->discont = TRUE;
@@ -1905,9 +1907,9 @@ gst_base_src_send_event (GstElement * element, GstEvent * event)
 
       /* For external flush, restart the task .. */
       GST_LIVE_LOCK (src);
-      src->priv->segment_pending = TRUE;
 
       GST_OBJECT_LOCK (src->srcpad);
+      src->priv->segment_pending = TRUE;
       start = (GST_PAD_MODE (src->srcpad) == GST_PAD_MODE_PUSH);
       GST_OBJECT_UNLOCK (src->srcpad);
 
@@ -2885,6 +2887,7 @@ gst_base_src_loop (GstPad * pad)
   gboolean eos;
   guint blocksize;
   GList *pending_events = NULL, *tmp;
+  GstEvent *seg_event = NULL;
 
   eos = FALSE;
 
@@ -2973,14 +2976,17 @@ gst_base_src_loop (GstPad * pad)
 
   /* push events to close/start our segment before we push the buffer. */
   if (G_UNLIKELY (src->priv->segment_pending)) {
-    GstEvent *seg_event = gst_event_new_segment (&src->segment);
+    /* generate the event but do not send until outside of live_lock  */
+    seg_event = gst_event_new_segment (&src->segment);
 
+    GST_OBJECT_LOCK (src);
     gst_event_set_seqnum (seg_event, src->priv->segment_seqnum);
     src->priv->segment_seqnum = gst_util_seqnum_next ();
-    gst_pad_push_event (pad, seg_event);
     src->priv->segment_pending = FALSE;
+    GST_OBJECT_UNLOCK (src);
   }
 
+  /* collect any pending events */
   if (g_atomic_int_get (&src->priv->have_events)) {
     GST_OBJECT_LOCK (src);
     /* take the events */
@@ -2989,8 +2995,13 @@ gst_base_src_loop (GstPad * pad)
     g_atomic_int_set (&src->priv->have_events, FALSE);
     GST_OBJECT_UNLOCK (src);
   }
+  GST_LIVE_UNLOCK (src);
 
-  /* Push out pending events if any */
+  /* now outside the live_lock we can push the segment event */
+  if (G_UNLIKELY (seg_event))
+    gst_pad_push_event (pad, seg_event);
+
+  /* and the pending events if any */
   if (G_UNLIKELY (pending_events != NULL)) {
     for (tmp = pending_events; tmp; tmp = g_list_next (tmp)) {
       GstEvent *ev = (GstEvent *) tmp->data;
@@ -3070,7 +3081,6 @@ gst_base_src_loop (GstPad * pad)
     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
     src->priv->discont = FALSE;
   }
-  GST_LIVE_UNLOCK (src);
 
   /* push buffer or buffer list */
   if (src->priv->pending_bufferlist != NULL) {
diff --git a/libs/gst/base/gstcollectpads.c b/libs/gst/base/gstcollectpads.c
index abbae44..fcc803c 100644
--- a/libs/gst/base/gstcollectpads.c
+++ b/libs/gst/base/gstcollectpads.c
@@ -304,8 +304,8 @@ gst_collect_pads_set_buffer_function_locked (GstCollectPads * pads,
 /**
  * gst_collect_pads_set_buffer_function:
  * @pads: the collectpads to use
- * @func: (scope call): the function to set
- * @user_data: (closure): user data passed to the function
+ * @func: (scope call) (closure user_data): the function to set
+ * @user_data: user data passed to the function
  *
  * Set the callback function and user data that will be called with
  * the oldest buffer when all pads have been collected, or %NULL on EOS.
@@ -329,8 +329,8 @@ gst_collect_pads_set_buffer_function (GstCollectPads * pads,
 /**
  * gst_collect_pads_set_compare_function:
  * @pads: the pads to use
- * @func: (scope call): the function to set
- * @user_data: (closure): user data passed to the function
+ * @func: (scope call) (closure user_data): the function to set
+ * @user_data: user data passed to the function
  *
  * Set the timestamp comparison function.
  *
diff --git a/libs/gst/base/gstdataqueue.c b/libs/gst/base/gstdataqueue.c
index ac93b8e..e226e3a 100644
--- a/libs/gst/base/gstdataqueue.c
+++ b/libs/gst/base/gstdataqueue.c
@@ -63,7 +63,7 @@ enum
 struct _GstDataQueuePrivate
 {
   /* the array of data we're keeping our grubby hands on */
-  GstQueueArray *queue;
+  GstVecDeque *queue;
 
   GstDataQueueSize cur_level;   /* size of the queue */
   GstDataQueueCheckFullFunction checkfull;      /* Callback to check if the queue is full */
@@ -107,12 +107,12 @@ struct _GstDataQueuePrivate
   GST_CAT_LOG (data_queue_dataflow,                                     \
                "queue:%p " msg ": %u visible items, %u "                \
                "bytes, %"G_GUINT64_FORMAT                               \
-               " ns, %u elements",                                      \
+               " ns, %" G_GSIZE_FORMAT " elements",                     \
                queue,                                                   \
                q->priv->cur_level.visible,                              \
                q->priv->cur_level.bytes,                                \
                q->priv->cur_level.time,                                 \
-               gst_queue_array_get_length (q->priv->queue))
+               gst_vec_deque_get_length (q->priv->queue))
 
 static void gst_data_queue_finalize (GObject * object);
 
@@ -204,7 +204,7 @@ gst_data_queue_init (GstDataQueue * queue)
   g_mutex_init (&queue->priv->qlock);
   g_cond_init (&queue->priv->item_add);
   g_cond_init (&queue->priv->item_del);
-  queue->priv->queue = gst_queue_array_new (50);
+  queue->priv->queue = gst_vec_deque_new (50);
 
   GST_DEBUG ("initialized queue's not_empty & not_full conditions");
 }
@@ -250,8 +250,8 @@ gst_data_queue_cleanup (GstDataQueue * queue)
 {
   GstDataQueuePrivate *priv = queue->priv;
 
-  while (!gst_queue_array_is_empty (priv->queue)) {
-    GstDataQueueItem *item = gst_queue_array_pop_head (priv->queue);
+  while (!gst_vec_deque_is_empty (priv->queue)) {
+    GstDataQueueItem *item = gst_vec_deque_pop_head (priv->queue);
 
     /* Just call the destroy notify on the item */
     item->destroy (item);
@@ -271,7 +271,7 @@ gst_data_queue_finalize (GObject * object)
   GST_DEBUG ("finalizing queue");
 
   gst_data_queue_cleanup (queue);
-  gst_queue_array_free (priv->queue);
+  gst_vec_deque_free (priv->queue);
 
   GST_DEBUG ("free mutex");
   g_mutex_clear (&priv->qlock);
@@ -301,7 +301,7 @@ gst_data_queue_locked_is_empty (GstDataQueue * queue)
 {
   GstDataQueuePrivate *priv = queue->priv;
 
-  return (gst_queue_array_get_length (priv->queue) == 0);
+  return (gst_vec_deque_get_length (priv->queue) == 0);
 }
 
 static inline gboolean
@@ -419,7 +419,7 @@ gst_data_queue_push_force_unlocked (GstDataQueue * queue,
 {
   GstDataQueuePrivate *priv = queue->priv;
 
-  gst_queue_array_push_tail (priv->queue, item);
+  gst_vec_deque_push_tail (priv->queue, item);
 
   if (item->visible)
     priv->cur_level.visible++;
@@ -598,7 +598,7 @@ gst_data_queue_pop (GstDataQueue * queue, GstDataQueueItem ** item)
   }
 
   /* Get the item from the GQueue */
-  *item = gst_queue_array_pop_head (priv->queue);
+  *item = gst_vec_deque_pop_head (priv->queue);
 
   /* update current level counter */
   if ((*item)->visible)
@@ -668,7 +668,7 @@ gst_data_queue_peek (GstDataQueue * queue, GstDataQueueItem ** item)
   }
 
   /* Get the item from the GQueue */
-  *item = gst_queue_array_peek_head (priv->queue);
+  *item = gst_vec_deque_peek_head (priv->queue);
 
   STATUS (queue, "after peeking");
   GST_DATA_QUEUE_MUTEX_UNLOCK (queue);
@@ -708,12 +708,12 @@ gst_data_queue_drop_head (GstDataQueue * queue, GType type)
   GST_DEBUG ("queue:%p", queue);
 
   GST_DATA_QUEUE_MUTEX_LOCK (queue);
-  idx = gst_queue_array_find (priv->queue, is_of_type, GSIZE_TO_POINTER (type));
+  idx = gst_vec_deque_find (priv->queue, is_of_type, GSIZE_TO_POINTER (type));
 
   if (idx == -1)
     goto done;
 
-  leak = gst_queue_array_drop_element (priv->queue, idx);
+  leak = gst_vec_deque_drop_element (priv->queue, idx);
 
   if (leak->visible)
     priv->cur_level.visible--;
diff --git a/libs/gst/base/gstqueuearray.c b/libs/gst/base/gstqueuearray.c
index cfd80e4..c67f892 100644
--- a/libs/gst/base/gstqueuearray.c
+++ b/libs/gst/base/gstqueuearray.c
@@ -33,32 +33,9 @@
 #include "config.h"
 #endif
 
-#include <string.h>
 #include <gst/gst.h>
 #include "gstqueuearray.h"
 
-#define gst_queue_array_idx(a, i) \
-  ((a)->array + (((a)->head + (i)) % (a)->size) * (a)->elt_size)
-
-struct _GstQueueArray
-{
-  /* < private > */
-  guint8 *array;
-  guint size;
-  guint head;
-  guint tail;
-  guint length;
-  guint elt_size;
-  gboolean struct_array;
-  GDestroyNotify clear_func;
-};
-
-typedef struct
-{
-  GCompareDataFunc func;
-  gpointer user_data;
-} QueueSortData;
-
 /**
  * gst_queue_array_new_for_struct: (skip)
  * @struct_size: Size of each element (e.g. structure) in the array
@@ -70,24 +47,13 @@ typedef struct
  * Returns: a new #GstQueueArray object
  *
  * Since: 1.6
+ * Deprecated: 1.26: Use #GstVecDeque instead.
  */
 GstQueueArray *
 gst_queue_array_new_for_struct (gsize struct_size, guint initial_size)
 {
-  GstQueueArray *array;
-
-  g_return_val_if_fail (struct_size > 0, NULL);
-
-  array = g_new (GstQueueArray, 1);
-  array->elt_size = struct_size;
-  array->size = initial_size;
-  array->array = g_malloc0 (struct_size * initial_size);
-  array->head = 0;
-  array->tail = 0;
-  array->length = 0;
-  array->struct_array = TRUE;
-  array->clear_func = NULL;
-  return array;
+  return (GstQueueArray *) gst_vec_deque_new_for_struct (struct_size,
+      initial_size);
 }
 
 /**
@@ -104,11 +70,7 @@ gst_queue_array_new_for_struct (gsize struct_size, guint initial_size)
 GstQueueArray *
 gst_queue_array_new (guint initial_size)
 {
-  GstQueueArray *array;
-
-  array = gst_queue_array_new_for_struct (sizeof (gpointer), initial_size);
-  array->struct_array = FALSE;
-  return array;
+  return (GstQueueArray *) gst_vec_deque_new (initial_size);
 }
 
 /**
@@ -118,14 +80,12 @@ gst_queue_array_new (guint initial_size)
  * Frees queue @array and all memory associated to it.
  *
  * Since: 1.2
+ * Deprecated: 1.26: Use #GstVecDeque instead.
  */
 void
 gst_queue_array_free (GstQueueArray * array)
 {
-  g_return_if_fail (array != NULL);
-  gst_queue_array_clear (array);
-  g_free (array->array);
-  g_free (array);
+  gst_vec_deque_free ((GstVecDeque *) array);
 }
 
 /**
@@ -145,28 +105,13 @@ gst_queue_array_free (GstQueueArray * array)
  * the array element it is given, but not free the element itself.
  *
  * Since: 1.16
+ * Deprecated: 1.26: Use #GstVecDeque instead.
  */
 void
 gst_queue_array_set_clear_func (GstQueueArray * array,
     GDestroyNotify clear_func)
 {
-  g_return_if_fail (array != NULL);
-  array->clear_func = clear_func;
-}
-
-static void
-gst_queue_array_clear_idx (GstQueueArray * array, guint idx)
-{
-  guint pos;
-
-  if (!array->clear_func)
-    return;
-
-  pos = (idx + array->head) % array->size;
-  if (array->struct_array)
-    array->clear_func (array->array + pos * array->elt_size);
-  else
-    array->clear_func (*(gpointer *) (array->array + pos * array->elt_size));
+  gst_vec_deque_set_clear_func ((GstVecDeque *) array, clear_func);
 }
 
 /**
@@ -176,23 +121,12 @@ gst_queue_array_clear_idx (GstQueueArray * array, guint idx)
  * Clears queue @array and frees all memory associated to it.
  *
  * Since: 1.16
+ * Deprecated: 1.26: Use #GstVecDeque instead.
  */
 void
 gst_queue_array_clear (GstQueueArray * array)
 {
-  g_return_if_fail (array != NULL);
-
-  if (array->clear_func != NULL) {
-    guint i;
-
-    for (i = 0; i < array->length; i++) {
-      gst_queue_array_clear_idx (array, i);
-    }
-  }
-
-  array->head = 0;
-  array->tail = 0;
-  array->length = 0;
+  gst_vec_deque_clear ((GstVecDeque *) array);
 }
 
 /**
@@ -206,23 +140,12 @@ gst_queue_array_clear (GstQueueArray * array)
  *    the queue array is not modified further!
  *
  * Since: 1.6
+ * Deprecated: 1.26: Use #GstVecDeque instead.
  */
 gpointer
 gst_queue_array_pop_head_struct (GstQueueArray * array)
 {
-  gpointer p_struct;
-  g_return_val_if_fail (array != NULL, NULL);
-  /* empty array */
-  if (G_UNLIKELY (array->length == 0))
-    return NULL;
-
-  p_struct = array->array + (array->elt_size * array->head);
-
-  array->head++;
-  array->head %= array->size;
-  array->length--;
-
-  return p_struct;
+  return gst_vec_deque_pop_head_struct ((GstVecDeque *) array);
 }
 
 /**
@@ -235,22 +158,12 @@ gst_queue_array_pop_head_struct (GstQueueArray * array)
  * Returns: The head of the queue
  *
  * Since: 1.2
+ * Deprecated: 1.26: Use #GstVecDeque instead.
  */
 gpointer
 gst_queue_array_pop_head (GstQueueArray * array)
 {
-  gpointer ret;
-  g_return_val_if_fail (array != NULL, NULL);
-
-  /* empty array */
-  if (G_UNLIKELY (array->length == 0))
-    return NULL;
-
-  ret = *(gpointer *) (array->array + (sizeof (gpointer) * array->head));
-  array->head++;
-  array->head %= array->size;
-  array->length--;
-  return ret;
+  return gst_vec_deque_pop_head ((GstVecDeque *) array);
 }
 
 /**
@@ -264,16 +177,12 @@ gst_queue_array_pop_head (GstQueueArray * array)
  *    the queue array is not modified further!
  *
  * Since: 1.6
+ * Deprecated: 1.26: Use #GstVecDeque instead.
  */
 gpointer
 gst_queue_array_peek_head_struct (GstQueueArray * array)
 {
-  g_return_val_if_fail (array != NULL, NULL);
-  /* empty array */
-  if (G_UNLIKELY (array->length == 0))
-    return NULL;
-
-  return array->array + (array->elt_size * array->head);
+  return gst_vec_deque_peek_head_struct ((GstVecDeque *) array);
 }
 
 /**
@@ -286,16 +195,12 @@ gst_queue_array_peek_head_struct (GstQueueArray * array)
  * Returns: The head of the queue
  *
  * Since: 1.2
+ * Deprecated: 1.26: Use #GstVecDeque instead.
  */
 gpointer
 gst_queue_array_peek_head (GstQueueArray * array)
 {
-  g_return_val_if_fail (array != NULL, NULL);
-  /* empty array */
-  if (G_UNLIKELY (array->length == 0))
-    return NULL;
-
-  return *(gpointer *) (array->array + (sizeof (gpointer) * array->head));
+  return gst_vec_deque_peek_head ((GstVecDeque *) array);
 }
 
 /**
@@ -306,16 +211,12 @@ gst_queue_array_peek_head (GstQueueArray * array)
  * Returns: (nullable): The item, or %NULL if @idx was out of bounds
  *
  * Since: 1.16
+ * Deprecated: 1.26: Use #GstVecDeque instead.
  */
 gpointer
 gst_queue_array_peek_nth (GstQueueArray * array, guint idx)
 {
-  g_return_val_if_fail (array != NULL, NULL);
-  g_return_val_if_fail (idx < array->length, NULL);
-
-  idx = (array->head + idx) % array->size;
-
-  return *(gpointer *) (array->array + (sizeof (gpointer) * idx));
+  return gst_vec_deque_peek_nth ((GstVecDeque *) array, idx);
 }
 
 /**
@@ -326,64 +227,12 @@ gst_queue_array_peek_nth (GstQueueArray * array, guint idx)
  * Returns: (nullable): The item, or %NULL if @idx was out of bounds
  *
  * Since: 1.16
+ * Deprecated: 1.26: Use #GstVecDeque instead.
  */
 gpointer
 gst_queue_array_peek_nth_struct (GstQueueArray * array, guint idx)
 {
-  g_return_val_if_fail (array != NULL, NULL);
-  g_return_val_if_fail (idx < array->length, NULL);
-
-  idx = (array->head + idx) % array->size;
-
-  return array->array + (array->elt_size * idx);
-}
-
-static void
-gst_queue_array_do_expand (GstQueueArray * array)
-{
-  gsize elt_size = array->elt_size;
-  /* newsize is 50% bigger */
-  gsize oldsize = array->size;
-  guint64 newsize;
-
-  newsize = MAX ((3 * (guint64) oldsize) / 2, (guint64) oldsize + 1);
-  if (newsize > G_MAXUINT)
-    g_error ("growing the queue array would overflow");
-
-  /* copy over data */
-  if (array->tail != 0) {
-    guint8 *array2 = NULL;
-    gsize t1 = 0;
-    gsize t2 = 0;
-
-    array2 = g_malloc0_n (newsize, elt_size);
-    t1 = array->head;
-    t2 = oldsize - array->head;
-
-    /* [0-----TAIL][HEAD------SIZE]
-     *
-     * We want to end up with
-     * [HEAD------------------TAIL][----FREEDATA------NEWSIZE]
-     *
-     * 1) move [HEAD-----SIZE] part to beginning of new array
-     * 2) move [0-------TAIL] part new array, after previous part
-     */
-
-    memcpy (array2, array->array + (elt_size * (gsize) array->head),
-        t2 * elt_size);
-    memcpy (array2 + t2 * elt_size, array->array, t1 * elt_size);
-
-    g_free (array->array);
-    array->array = array2;
-    array->head = 0;
-  } else {
-    /* Fast path, we just need to grow the array */
-    array->array = g_realloc_n (array->array, newsize, elt_size);
-    memset (array->array + elt_size * oldsize, 0,
-        elt_size * (newsize - oldsize));
-  }
-  array->tail = oldsize;
-  array->size = newsize;
+  return gst_vec_deque_peek_nth_struct ((GstVecDeque *) array, idx);
 }
 
 /**
@@ -396,24 +245,12 @@ gst_queue_array_do_expand (GstQueueArray * array)
  * creating the queue into the array).
  *
  * Since: 1.6
+ * Deprecated: 1.26: Use #GstVecDeque instead.
  */
 void
 gst_queue_array_push_tail_struct (GstQueueArray * array, gpointer p_struct)
 {
-  guint elt_size;
-
-  g_return_if_fail (p_struct != NULL);
-  g_return_if_fail (array != NULL);
-  elt_size = array->elt_size;
-
-  /* Check if we need to make room */
-  if (G_UNLIKELY (array->length == array->size))
-    gst_queue_array_do_expand (array);
-
-  memcpy (array->array + elt_size * array->tail, p_struct, elt_size);
-  array->tail++;
-  array->tail %= array->size;
-  array->length++;
+  gst_vec_deque_push_tail_struct ((GstVecDeque *) array, p_struct);
 }
 
 /**
@@ -424,49 +261,12 @@ gst_queue_array_push_tail_struct (GstQueueArray * array, gpointer p_struct)
  * Pushes @data to the tail of the queue @array.
  *
  * Since: 1.2
+ * Deprecated: 1.26: Use #GstVecDeque instead.
  */
 void
 gst_queue_array_push_tail (GstQueueArray * array, gpointer data)
 {
-  g_return_if_fail (array != NULL);
-
-  /* Check if we need to make room */
-  if (G_UNLIKELY (array->length == array->size))
-    gst_queue_array_do_expand (array);
-
-  *(gpointer *) (array->array + sizeof (gpointer) * array->tail) = data;
-  array->tail++;
-  array->tail %= array->size;
-  array->length++;
-}
-
-/* Moves all elements in the queue placed after the given position in the internal array */
-static void
-gst_queue_array_move_data_after_position (GstQueueArray * array, guint pos)
-{
-  guint elt_size = array->elt_size;
-
-  /* If the array does not wrap around OR if it does, but we're inserting past that point */
-  if (array->head < array->tail ||
-      (array->head >= array->tail && pos < array->head)) {
-    memmove (array->array + (pos + 1) * elt_size, array->array + pos * elt_size,
-        (array->tail - pos) * elt_size);
-    return;
-  }
-
-  /* Otherwise, array wraps around and we're inserting before the breaking point. 
-   * First, move everything past that point by one place. */
-  memmove (array->array + elt_size, array->array, array->tail * elt_size);
-
-  /* Then move the last element from before the wrap-around point to right after it. */
-  memcpy (array->array, array->array + (array->size - 1) * elt_size, elt_size);
-
-  /* If we're inserting right before the breaking point, no further action is needed.
-   * Otherwise, move data between insertion point and the breaking point by one place. */
-  if (pos != array->size - 1) {
-    memmove (array->array + (pos + 1) * elt_size, array->array + pos * elt_size,
-        (array->size - pos - 1) * elt_size);
-  }
+  gst_vec_deque_push_tail ((GstVecDeque *) array, data);
 }
 
 /**
@@ -486,41 +286,13 @@ gst_queue_array_move_data_after_position (GstQueueArray * array, guint pos)
  * to call gst_queue_array_sort() first.
  *
  * Since: 1.24
+ * Deprecated: 1.26: Use #GstVecDeque instead.
  */
 void
 gst_queue_array_push_sorted (GstQueueArray * array, gpointer data,
     GCompareDataFunc func, gpointer user_data)
 {
-  guint i;
-  gpointer *p_element;
-
-  g_return_if_fail (array != NULL);
-  g_return_if_fail (func != NULL);
-
-  /* Check if we need to make room */
-  if (G_UNLIKELY (array->length == array->size))
-    gst_queue_array_do_expand (array);
-
-  /* Compare against each element, assuming they're already sorted */
-  for (i = 0; i < array->length; i++) {
-    p_element = (gpointer *) gst_queue_array_idx (array, i);
-
-    if (func (*p_element, data, user_data) > 0) {
-      guint pos = (array->head + i) % array->size;
-      gst_queue_array_move_data_after_position (array, pos);
-
-      *p_element = data;
-      goto finish;
-    }
-  }
-
-  /* No 'bigger' element found - append to tail */
-  *(gpointer *) (array->array + array->elt_size * array->tail) = data;
-
-finish:
-  array->tail++;
-  array->tail %= array->size;
-  array->length++;
+  gst_vec_deque_push_sorted ((GstVecDeque *) array, data, func, user_data);
 }
 
 /**
@@ -542,49 +314,14 @@ finish:
  * to call gst_queue_array_sort() first.
  *
  * Since: 1.24
+ * Deprecated: 1.26: Use #GstVecDeque instead.
  */
 void
 gst_queue_array_push_sorted_struct (GstQueueArray * array, gpointer p_struct,
     GCompareDataFunc func, gpointer user_data)
 {
-  guint i;
-  gpointer p_element;
-
-  g_return_if_fail (array != NULL);
-  g_return_if_fail (p_struct != NULL);
-  g_return_if_fail (func != NULL);
-
-  /* Check if we need to make room */
-  if (G_UNLIKELY (array->length == array->size))
-    gst_queue_array_do_expand (array);
-
-  /* Compare against each element, assuming they're already sorted */
-  for (i = 0; i < array->length; i++) {
-    p_element = gst_queue_array_idx (array, i);
-
-    if (func (p_element, p_struct, user_data) > 0) {
-      guint pos = (array->head + i) % array->size;
-      gst_queue_array_move_data_after_position (array, pos);
-
-      memcpy (p_element, p_struct, array->elt_size);
-      goto finish;
-    }
-  }
-
-  /* No 'bigger' element found - append to tail */
-  memcpy (array->array + array->elt_size * array->tail, p_struct,
-      array->elt_size);
-
-finish:
-  array->tail++;
-  array->tail %= array->size;
-  array->length++;
-}
-
-static int
-compare_wrapper (gpointer * a, gpointer * b, QueueSortData * sort_data)
-{
-  return sort_data->func (*a, *b, sort_data->user_data);
+  gst_vec_deque_push_sorted_struct ((GstVecDeque *) array, p_struct, func,
+      user_data);
 }
 
 /** 
@@ -597,53 +334,13 @@ compare_wrapper (gpointer * a, gpointer * b, QueueSortData * sort_data)
  * the provided @compare_func.
  *
  * Since: 1.24
+ * Deprecated: 1.26: Use #GstVecDeque instead.
  */
 void
 gst_queue_array_sort (GstQueueArray * array, GCompareDataFunc compare_func,
     gpointer user_data)
 {
-  g_return_if_fail (array != NULL);
-  g_return_if_fail (compare_func != NULL);
-
-  if (array->length == 0)
-    return;
-
-  /* To be able to use g_qsort_with_data, we might need to rearrange:
-   * [0-----TAIL][HEAD-----SIZE] -> [HEAD-------TAIL] */
-  if (array->head >= array->tail) {
-    gsize t1 = array->head;
-    gsize t2 = array->size - array->head;
-    gsize elt_size = array->elt_size;
-
-    /* Copy [0-------TAIL] part to a temporary buffer */
-    guint8 *tmp = g_malloc0_n (t1, elt_size);
-    memcpy (tmp, array->array, t1 * elt_size);
-
-    /* Move [HEAD-----SIZE] part to the beginning of the original array */
-    memmove (array->array, array->array + (elt_size * array->head),
-        t2 * elt_size);
-
-    /* Copy the temporary buffer to the end of the original array */
-    memmove (array->array + (t2 * elt_size), tmp, t1 * elt_size);
-    g_free (tmp);
-
-    array->head = 0;
-    array->tail = array->length % array->size;
-  }
-
-  if (array->struct_array) {
-    g_qsort_with_data (array->array +
-        (array->head % array->size) * array->elt_size, array->length,
-        array->elt_size, compare_func, user_data);
-  } else {
-    /* For non-struct arrays, we need to wrap the provided compare function 
-     * to dereference our pointers before passing them for comparison. 
-     * This matches the behaviour of gst_queue_array_find(). */
-    QueueSortData sort_data = { compare_func, user_data };
-    g_qsort_with_data (array->array +
-        (array->head % array->size) * array->elt_size, array->length,
-        array->elt_size, (GCompareDataFunc) compare_wrapper, &sort_data);
-  }
+  gst_vec_deque_sort ((GstVecDeque *) array, compare_func, user_data);
 }
 
 /**
@@ -655,23 +352,12 @@ gst_queue_array_sort (GstQueueArray * array, GCompareDataFunc compare_func,
  * Returns: The tail of the queue
  *
  * Since: 1.14
+ * Deprecated: 1.26: Use #GstVecDeque instead.
  */
 gpointer
 gst_queue_array_peek_tail (GstQueueArray * array)
 {
-  guint len, idx;
-
-  g_return_val_if_fail (array != NULL, NULL);
-
-  len = array->length;
-
-  /* empty array */
-  if (len == 0)
-    return NULL;
-
-  idx = (array->head + (len - 1)) % array->size;
-
-  return *(gpointer *) (array->array + (sizeof (gpointer) * idx));
+  return gst_vec_deque_peek_tail ((GstVecDeque *) array);
 }
 
 /**
@@ -683,23 +369,12 @@ gst_queue_array_peek_tail (GstQueueArray * array)
  * Returns: The tail of the queue
  *
  * Since: 1.14
+ * Deprecated: 1.26: Use #GstVecDeque instead.
  */
 gpointer
 gst_queue_array_peek_tail_struct (GstQueueArray * array)
 {
-  guint len, idx;
-
-  g_return_val_if_fail (array != NULL, NULL);
-
-  len = array->length;
-
-  /* empty array */
-  if (len == 0)
-    return NULL;
-
-  idx = (array->head + (len - 1)) % array->size;
-
-  return array->array + (array->elt_size * idx);
+  return gst_vec_deque_peek_tail_struct ((GstVecDeque *) array);
 }
 
 /**
@@ -712,29 +387,12 @@ gst_queue_array_peek_tail_struct (GstQueueArray * array)
  * Returns: The tail of the queue
  *
  * Since: 1.14
+ * Deprecated: 1.26: Use #GstVecDeque instead.
  */
 gpointer
 gst_queue_array_pop_tail (GstQueueArray * array)
 {
-  gpointer ret;
-  guint len, idx;
-
-  g_return_val_if_fail (array != NULL, NULL);
-
-  len = array->length;
-
-  /* empty array */
-  if (len == 0)
-    return NULL;
-
-  idx = (array->head + (len - 1)) % array->size;
-
-  ret = *(gpointer *) (array->array + (sizeof (gpointer) * idx));
-
-  array->tail = idx;
-  array->length--;
-
-  return ret;
+  return gst_vec_deque_pop_tail ((GstVecDeque *) array);
 }
 
 /**
@@ -747,29 +405,12 @@ gst_queue_array_pop_tail (GstQueueArray * array)
  * Returns: The tail of the queue
  *
  * Since: 1.14
+ * Deprecated: 1.26: Use #GstVecDeque instead.
  */
 gpointer
 gst_queue_array_pop_tail_struct (GstQueueArray * array)
 {
-  gpointer ret;
-  guint len, idx;
-
-  g_return_val_if_fail (array != NULL, NULL);
-
-  len = array->length;
-
-  /* empty array */
-  if (len == 0)
-    return NULL;
-
-  idx = (array->head + (len - 1)) % array->size;
-
-  ret = array->array + (array->elt_size * idx);
-
-  array->tail = idx;
-  array->length--;
-
-  return ret;
+  return gst_vec_deque_pop_tail_struct ((GstVecDeque *) array);
 }
 
 /**
@@ -781,12 +422,12 @@ gst_queue_array_pop_tail_struct (GstQueueArray * array)
  * Returns: %TRUE if the queue @array is empty
  *
  * Since: 1.2
+ * Deprecated: 1.26: Use #GstVecDeque instead.
  */
 gboolean
 gst_queue_array_is_empty (GstQueueArray * array)
 {
-  g_return_val_if_fail (array != NULL, FALSE);
-  return (array->length == 0);
+  return gst_vec_deque_is_empty ((GstVecDeque *) array);
 }
 
 
@@ -803,109 +444,13 @@ gst_queue_array_is_empty (GstQueueArray * array)
  * Returns: TRUE on success, or FALSE on error
  *
  * Since: 1.6
+ * Deprecated: 1.26: Use #GstVecDeque instead.
  */
 gboolean
 gst_queue_array_drop_struct (GstQueueArray * array, guint idx,
     gpointer p_struct)
 {
-  int first_item_index, last_item_index;
-  guint actual_idx;
-  guint elt_size;
-
-  g_return_val_if_fail (array != NULL, FALSE);
-  actual_idx = (array->head + idx) % array->size;
-
-  g_return_val_if_fail (array->length > 0, FALSE);
-  g_return_val_if_fail (actual_idx < array->size, FALSE);
-
-  elt_size = array->elt_size;
-
-  first_item_index = array->head;
-
-  /* tail points to the first free spot */
-  last_item_index = (array->tail - 1 + array->size) % array->size;
-
-  if (p_struct != NULL)
-    memcpy (p_struct, array->array + elt_size * actual_idx, elt_size);
-
-  /* simple case actual_idx == first item */
-  if (actual_idx == first_item_index) {
-    /* clear current head position if needed */
-    if (p_struct == NULL)
-      gst_queue_array_clear_idx (array, idx);
-
-    /* move the head plus one */
-    array->head++;
-    array->head %= array->size;
-    array->length--;
-    return TRUE;
-  }
-
-  /* simple case idx == last item */
-  if (actual_idx == last_item_index) {
-    /* clear current tail position if needed */
-    if (p_struct == NULL)
-      gst_queue_array_clear_idx (array, idx);
-
-    /* move tail minus one, potentially wrapping */
-    array->tail = (array->tail - 1 + array->size) % array->size;
-    array->length--;
-    return TRUE;
-  }
-
-  /* non-wrapped case */
-  if (first_item_index < last_item_index) {
-    /* clear idx if needed */
-    if (p_struct == NULL)
-      gst_queue_array_clear_idx (array, idx);
-
-    g_assert (first_item_index < actual_idx && actual_idx < last_item_index);
-    /* move everything beyond actual_idx one step towards zero in array */
-    memmove (array->array + elt_size * actual_idx,
-        array->array + elt_size * (actual_idx + 1),
-        (last_item_index - actual_idx) * elt_size);
-    /* tail might wrap, ie if tail == 0 (and last_item_index == size) */
-    array->tail = (array->tail - 1 + array->size) % array->size;
-    array->length--;
-    return TRUE;
-  }
-
-  /* only wrapped cases left */
-  g_assert (first_item_index > last_item_index);
-
-  if (actual_idx < last_item_index) {
-    /* clear idx if needed */
-    if (p_struct == NULL)
-      gst_queue_array_clear_idx (array, idx);
-
-    /* actual_idx is before last_item_index, move data towards zero */
-    memmove (array->array + elt_size * actual_idx,
-        array->array + elt_size * (actual_idx + 1),
-        (last_item_index - actual_idx) * elt_size);
-    /* tail should not wrap in this case! */
-    g_assert (array->tail > 0);
-    array->tail--;
-    array->length--;
-    return TRUE;
-  }
-
-  if (actual_idx > first_item_index) {
-    /* clear idx if needed */
-    if (p_struct == NULL)
-      gst_queue_array_clear_idx (array, idx);
-
-    /* actual_idx is after first_item_index, move data to higher indices */
-    memmove (array->array + elt_size * (first_item_index + 1),
-        array->array + elt_size * first_item_index,
-        (actual_idx - first_item_index) * elt_size);
-    array->head++;
-    /* head should not wrap in this case! */
-    g_assert (array->head < array->size);
-    array->length--;
-    return TRUE;
-  }
-
-  g_return_val_if_reached (FALSE);
+  return gst_vec_deque_drop_struct ((GstVecDeque *) array, idx, p_struct);
 }
 
 /**
@@ -918,16 +463,12 @@ gst_queue_array_drop_struct (GstQueueArray * array, guint idx,
  * Returns: the dropped element
  *
  * Since: 1.2
+ * Deprecated: 1.26: Use #GstVecDeque instead.
  */
 gpointer
 gst_queue_array_drop_element (GstQueueArray * array, guint idx)
 {
-  gpointer ptr;
-
-  if (!gst_queue_array_drop_struct (array, idx, &ptr))
-    return NULL;
-
-  return ptr;
+  return gst_vec_deque_drop_element ((GstVecDeque *) array, idx);
 }
 
 /**
@@ -943,39 +484,12 @@ gst_queue_array_drop_element (GstQueueArray * array, guint idx)
  * Returns: Index of the found element or -1 if nothing was found.
  *
  * Since: 1.2
+ * Deprecated: 1.26: Use #GstVecDeque instead.
  */
 guint
 gst_queue_array_find (GstQueueArray * array, GCompareFunc func, gpointer data)
 {
-  gpointer p_element;
-  guint elt_size;
-  guint i;
-
-  /* For struct arrays we need to implement this differently so that
-   * the user gets a pointer to the element data not the dereferenced
-   * pointer itself */
-
-  g_return_val_if_fail (array != NULL, -1);
-  g_return_val_if_fail (array->struct_array == FALSE, -1);
-
-  elt_size = array->elt_size;
-
-  if (func != NULL) {
-    /* Scan from head to tail */
-    for (i = 0; i < array->length; i++) {
-      p_element = array->array + ((i + array->head) % array->size) * elt_size;
-      if (func (*(gpointer *) p_element, data) == 0)
-        return i;
-    }
-  } else {
-    for (i = 0; i < array->length; i++) {
-      p_element = array->array + ((i + array->head) % array->size) * elt_size;
-      if (*(gpointer *) p_element == data)
-        return i;
-    }
-  }
-
-  return -1;
+  return gst_vec_deque_find ((GstVecDeque *) array, func, data);
 }
 
 /**
@@ -987,10 +501,10 @@ gst_queue_array_find (GstQueueArray * array, GCompareFunc func, gpointer data)
  * Returns: the length of the queue @array.
  *
  * Since: 1.2
+ * Deprecated: 1.26: Use #GstVecDeque instead.
  */
 guint
 gst_queue_array_get_length (GstQueueArray * array)
 {
-  g_return_val_if_fail (array != NULL, 0);
-  return array->length;
+  return gst_vec_deque_get_length ((GstVecDeque *) array);
 }
diff --git a/libs/gst/base/gstqueuearray.h b/libs/gst/base/gstqueuearray.h
index 2a63e95..fa5b8c5 100644
--- a/libs/gst/base/gstqueuearray.h
+++ b/libs/gst/base/gstqueuearray.h
@@ -30,93 +30,95 @@ G_BEGIN_DECLS
 
 /**
  * GstQueueArray: (skip)
+ *
+ * Deprecated: 1.26: Use #GstVecDeque instead.
  */
-typedef struct _GstQueueArray GstQueueArray;
+typedef struct _GstQueueArray GST_BASE_DEPRECATED_TYPE_FOR(GstVecDeque) GstQueueArray;
 
-GST_BASE_API
+GST_BASE_DEPRECATED_FOR(gst_vec_deque_new)
 GstQueueArray * gst_queue_array_new       (guint initial_size);
 
-GST_BASE_API
+GST_BASE_DEPRECATED_FOR(gst_vec_deque_free)
 void            gst_queue_array_free      (GstQueueArray * array);
 
-GST_BASE_API
+GST_BASE_DEPRECATED_FOR(gst_vec_deque_set_clear_func)
 void            gst_queue_array_set_clear_func (GstQueueArray *array,
                                                 GDestroyNotify clear_func);
 
-GST_BASE_API
+GST_BASE_DEPRECATED_FOR(gst_vec_deque_clear)
 void            gst_queue_array_clear     (GstQueueArray * array);
 
-GST_BASE_API
+GST_BASE_DEPRECATED_FOR(gst_vec_deque_pop_head)
 gpointer        gst_queue_array_pop_head  (GstQueueArray * array);
 
-GST_BASE_API
+GST_BASE_DEPRECATED_FOR(gst_vec_deque_peek_head)
 gpointer        gst_queue_array_peek_head (GstQueueArray * array);
 
-GST_BASE_API
+GST_BASE_DEPRECATED_FOR(gst_vec_deque_peek_nth)
 gpointer        gst_queue_array_peek_nth  (GstQueueArray * array, guint idx);
 
-GST_BASE_API
+GST_BASE_DEPRECATED_FOR(gst_vec_deque_pop_tail)
 gpointer        gst_queue_array_pop_tail  (GstQueueArray * array);
 
-GST_BASE_API
+GST_BASE_DEPRECATED_FOR(gst_vec_deque_peek_tail)
 gpointer        gst_queue_array_peek_tail (GstQueueArray * array);
 
-GST_BASE_API
+GST_BASE_DEPRECATED_FOR(gst_vec_deque_push_tail)
 void            gst_queue_array_push_tail (GstQueueArray * array,
                                            gpointer        data);
-GST_BASE_API
+GST_BASE_DEPRECATED_FOR(gst_vec_deque_is_empty)
 gboolean        gst_queue_array_is_empty  (GstQueueArray * array);
 
-GST_BASE_API
+GST_BASE_DEPRECATED_FOR(gst_vec_deque_drop_element)
 gpointer        gst_queue_array_drop_element (GstQueueArray * array,
                                               guint           idx);
-GST_BASE_API
+GST_BASE_DEPRECATED_FOR(gst_vec_deque_find)
 guint           gst_queue_array_find (GstQueueArray * array,
                                       GCompareFunc    func,
                                       gpointer        data);
-GST_BASE_API
+GST_BASE_DEPRECATED_FOR(gst_vec_deque_get_length)
 guint           gst_queue_array_get_length (GstQueueArray * array);
 
 /* Functions for use with structures */
 
-GST_BASE_API
+GST_BASE_DEPRECATED_FOR(gst_vec_deque_new_for_struct)
 GstQueueArray * gst_queue_array_new_for_struct (gsize struct_size,
                                                 guint initial_size);
-GST_BASE_API
+GST_BASE_DEPRECATED_FOR(gst_vec_deque_push_tail_struct)
 void            gst_queue_array_push_tail_struct (GstQueueArray * array,
                                                   gpointer        p_struct);
-GST_BASE_API
+GST_BASE_DEPRECATED_FOR(gst_vec_deque_pop_head_struct)
 gpointer        gst_queue_array_pop_head_struct  (GstQueueArray * array);
 
-GST_BASE_API
+GST_BASE_DEPRECATED_FOR(gst_vec_deque_peek_head_struct)
 gpointer        gst_queue_array_peek_head_struct (GstQueueArray * array);
 
-GST_BASE_API
+GST_BASE_DEPRECATED_FOR(gst_vec_deque_peek_nth_struct)
 gpointer        gst_queue_array_peek_nth_struct  (GstQueueArray * array, guint idx);
 
-GST_BASE_API
+GST_BASE_DEPRECATED_FOR(gst_vec_deque_drop_struct)
 gboolean        gst_queue_array_drop_struct      (GstQueueArray * array,
                                                   guint           idx,
                                                   gpointer        p_struct);
-GST_BASE_API
+GST_BASE_DEPRECATED_FOR(gst_vec_deque_pop_tail_struct)
 gpointer        gst_queue_array_pop_tail_struct  (GstQueueArray * array);
 
-GST_BASE_API
+GST_BASE_DEPRECATED_FOR(gst_vec_deque_peek_tail_struct)
 gpointer        gst_queue_array_peek_tail_struct (GstQueueArray * array);
 
-GST_BASE_API
+GST_BASE_DEPRECATED_FOR(gst_vec_deque_push_sorted)
 void            gst_queue_array_push_sorted (GstQueueArray * array, 
                                              gpointer data,
                                              GCompareDataFunc func, 
                                              gpointer user_data);
 
-GST_BASE_API
+GST_BASE_DEPRECATED_FOR(gst_vec_deque_push_sorted_struct)
 void            gst_queue_array_push_sorted_struct (GstQueueArray * array, 
                                                     gpointer p_struct,
                                                     GCompareDataFunc func, 
                                                     gpointer user_data);
 
-GST_BASE_API
+GST_BASE_DEPRECATED_FOR(gst_vec_deque_sort)
 void            gst_queue_array_sort (GstQueueArray *array,
                                       GCompareDataFunc compare_func,
                                       gpointer user_data);
diff --git a/libs/gst/base/gsttypefindhelper.c b/libs/gst/base/gsttypefindhelper.c
index 455b229..500ea35 100644
--- a/libs/gst/base/gsttypefindhelper.c
+++ b/libs/gst/base/gsttypefindhelper.c
@@ -579,6 +579,14 @@ buf_helper_find_suggest (gpointer data, guint probability, GstCaps * caps)
   }
 }
 
+static guint64
+buf_helper_get_length (gpointer data)
+{
+  GstTypeFindBufHelper *helper = (GstTypeFindBufHelper *) data;
+
+  return helper->size;
+}
+
 /**
  * gst_type_find_helper_for_data:
  * @obj: (nullable): object doing the typefinding, or %NULL (used for logging)
@@ -670,7 +678,7 @@ gst_type_find_helper_for_data_with_extension (GstObject * obj,
   find.data = &helper;
   find.peek = buf_helper_find_peek;
   find.suggest = buf_helper_find_suggest;
-  find.get_length = NULL;
+  find.get_length = buf_helper_get_length;
 
   type_list = gst_type_find_factory_get_list ();
   type_list = prioritize_extension (obj, type_list, extension);
diff --git a/libs/gst/base/meson.build b/libs/gst/base/meson.build
index e08254d..b7aca73 100644
--- a/libs/gst/base/meson.build
+++ b/libs/gst/base/meson.build
@@ -38,7 +38,23 @@ gst_base_headers = files(
   'gsttypefindhelper.h',
 )
 
-gst_base = library('gstbase-@0@'.format(apiversion),
+gst_base_doc_headers = files(
+  'gstbitreader-docs.h',
+  'gstbitwriter-docs.h',
+  'gstbytereader-docs.h',
+  'gstbytewriter-docs.h',
+)
+
+doc_sources = []
+foreach s: gst_base_sources + gst_base_headers + gst_base_doc_headers
+  doc_sources += s.full_path()
+endforeach
+
+libs_sources += {
+  'base': pathsep.join(doc_sources)
+}
+
+gst_base = library('gstbase-@0@'.format(api_version),
   gst_base_sources,
   c_args : gst_c_args + ['-DBUILDING_GST_BASE', '-DG_LOG_DOMAIN="GStreamer-Base"'],
   version : libversion,
@@ -65,7 +81,7 @@ if build_gir
   gir = {
     'sources' : gst_base_sources + gst_base_headers,
     'namespace' : 'GstBase',
-    'nsversion' : apiversion,
+    'nsversion' : api_version,
     'identifier_prefix' : 'Gst',
     'symbol_prefix' : 'gst',
     'export_packages' : pkg_name,
diff --git a/libs/gst/check/gstcheck.h b/libs/gst/check/gstcheck.h
index b7ec2c4..a4a1f2f 100644
--- a/libs/gst/check/gstcheck.h
+++ b/libs/gst/check/gstcheck.h
@@ -452,6 +452,37 @@ G_STMT_START {                                                      \
  */
 #define assert_equals_string(a, b) fail_unless_equals_string(a, b)
 
+/**
+ * fail_unless_matches_string:
+ * @a: a string literal or expression
+ * @b: a regular expression pattern string literal or expression
+ *
+ * This macro checks that @a matches the regular expression in @b aborts if
+ * this is not the case, printing both expressions and the values they
+ * evaluated to. This macro is for use in unit tests.
+ *
+ * Since: 1.26
+ */
+#define fail_unless_matches_string(a, b)                            \
+G_STMT_START {                                                      \
+  const gchar * first = a;                                          \
+  const gchar * second = b;                                         \
+  fail_unless(g_regex_match_simple (second, first, 0, 0),           \
+    "'" #a "' (%s) does not match pattern '" #b"' (%s)", first, second); \
+} G_STMT_END;
+/**
+ * assert_matches_string:
+ * @a: a string literal or expression
+ * @b: a regular expression pattern string literal or expression
+ *
+ * This macro checks that @a matches the regular expression in @b aborts if
+ * this is not the case, printing both expressions and the values they
+ * evaluated to. This macro is for use in unit tests.
+ *
+ * Since: 1.26
+ */
+#define assert_matches_string(a, b) fail_unless_matches_string(a, b)
+
 /**
  * fail_unless_equals_float:
  * @a: a #gdouble or #gfloat value or expression
diff --git a/libs/gst/check/libcheck/README.txt b/libs/gst/check/libcheck/README.txt
index cc0f2ed..e441464 100644
--- a/libs/gst/check/libcheck/README.txt
+++ b/libs/gst/check/libcheck/README.txt
@@ -21,7 +21,7 @@ Steps to sync with upstream:
 
 1. Clone libcheck from the above git repository
 2. Copy files into this directory
-3. Run GNU indent on all the code
+3. Run gst-indent-1.0 on all the code
 4. Fix internal #includes
 5. Manually inspect the diff
 6. Update configure.ac, m4/check-checks.m4, meson.build files, etc
diff --git a/libs/gst/check/meson.build b/libs/gst/check/meson.build
index 6b3a53f..679a15d 100644
--- a/libs/gst/check/meson.build
+++ b/libs/gst/check/meson.build
@@ -17,6 +17,15 @@ gst_check_headers = files(
 )
 install_headers(gst_check_headers, subdir : 'gstreamer-1.0/gst/check/')
 
+doc_sources = []
+foreach s: gst_check_sources + gst_check_headers
+  doc_sources += s.full_path()
+endforeach
+
+libs_sources += {
+  'check': pathsep.join(doc_sources)
+}
+
 
 check_cdata = configuration_data()
 
@@ -37,7 +46,7 @@ configure_file(input : 'libcheck/check.h.in',
   install_dir : join_paths(get_option('includedir'), 'gstreamer-1.0/gst/check'),
   configuration : check_cdata)
 
-gst_check = library('gstcheck-@0@'.format(apiversion),
+gst_check = library('gstcheck-@0@'.format(api_version),
   gst_check_sources,
   c_args : gst_c_args + ['-UG_DISABLE_ASSERT', '-DBUILDING_GST_CHECK', '-DG_LOG_DOMAIN="GStreamer-Check"'],
   version : libversion,
@@ -69,7 +78,7 @@ if build_gir
   gir = {
     'sources' : gst_check_sources + gst_check_headers,
     'namespace' : 'GstCheck',
-    'nsversion' : apiversion,
+    'nsversion' : api_version,
     'identifier_prefix' : 'Gst',
     'symbol_prefix' : 'gst',
     'export_packages' : pkg_name,
diff --git a/libs/gst/controller/meson.build b/libs/gst/controller/meson.build
index 5863df5..9d38af8 100644
--- a/libs/gst/controller/meson.build
+++ b/libs/gst/controller/meson.build
@@ -26,6 +26,16 @@ gst_controller_headers = controller_mkenum_headers + files(
 )
 install_headers(gst_controller_headers, subdir : 'gstreamer-1.0/gst/controller/')
 
+doc_sources = []
+foreach s: gst_controller_sources + gst_controller_headers
+  doc_sources += s.full_path()
+endforeach
+
+libs_sources += {
+  'controller': pathsep.join(doc_sources)
+}
+
+
 controller_enums = gnome.mkenums_simple('controller-enumtypes',
   sources : controller_mkenum_headers,
   header_prefix : '#include <gst/controller/controller-prelude.h>',
@@ -37,7 +47,7 @@ gstcontroller_c = controller_enums[0]
 gstcontroller_h = controller_enums[1]
 
 gst_controller_gen_sources = [gstcontroller_h]
-gst_controller = library('gstcontroller-@0@'.format(apiversion),
+gst_controller = library('gstcontroller-@0@'.format(api_version),
   gst_controller_sources, gstcontroller_h, gstcontroller_c,
   c_args : gst_c_args + ['-DBUILDING_GST_CONTROLLER', '-DG_LOG_DOMAIN="GStreamer-Controller"'],
   install : true,
@@ -63,7 +73,7 @@ if build_gir
   gir = {
     'sources' : gst_controller_sources + gst_controller_headers + [gstcontroller_h] + [gstcontroller_c],
     'namespace': 'GstController',
-    'nsversion': apiversion,
+    'nsversion': api_version,
     'identifier_prefix' : 'Gst',
     'symbol_prefix' : 'gst',
     'export_packages' : pkg_name,
diff --git a/libs/gst/helpers/gst-plugin-scanner.c b/libs/gst/helpers/gst-plugin-scanner.c
index f83e50f..ba0adbf 100644
--- a/libs/gst/helpers/gst-plugin-scanner.c
+++ b/libs/gst/helpers/gst-plugin-scanner.c
@@ -67,6 +67,8 @@ main (int argc, char *argv[])
   my_argv[0] = argv[0];
   my_argv[1] = (char *) "--gst-disable-registry-update";
 
+  g_unsetenv ("GST_TRACERS");
+
 #ifndef GST_DISABLE_REGISTRY
   _gst_disable_registry_cache = TRUE;
 #endif
diff --git a/libs/gst/helpers/meson.build b/libs/gst/helpers/meson.build
index bb8c621..ebe6db1 100644
--- a/libs/gst/helpers/meson.build
+++ b/libs/gst/helpers/meson.build
@@ -46,7 +46,7 @@ gst_scanner_dir = meson.current_build_dir()
 
 
 install_data(['gst_gdb.py', 'glib_gobject_helper.py'],
-  install_dir : join_paths(get_option('datadir'), 'gstreamer-@0@'.format(apiversion), 'gdb'),
+  install_dir : join_paths(get_option('datadir'), 'gstreamer-@0@'.format(api_version), 'gdb'),
   install_tag : 'devel')
 
 # This is needed to make gdb find gst_gdb.py
@@ -55,7 +55,7 @@ env.prepend('PYTHONPATH', meson.current_source_dir())
 meson.add_devenv(env)
 
 gdbconf = configuration_data()
-gdbconf.set('GST_API_VERSION', apiversion)
+gdbconf.set('GST_API_VERSION', api_version)
 gdbconf.set('DATADIR', '@0@/@1@'.format(get_option('prefix'), get_option('datadir')))
 
 if host_system != 'windows'
@@ -68,7 +68,7 @@ else
   gdb_install_dir = disabler()
 endif
 configure_file(input : 'libgstreamer-gdb.py.in',
-  output : 'libgstreamer-@0@.so.@1@-gdb.py'.format(apiversion, libversion),
+  output : 'libgstreamer-@0@.so.@1@-gdb.py'.format(api_version, libversion),
   install_dir : gdb_install_dir,
   install_tag : 'devel',
   configuration : gdbconf)
diff --git a/libs/gst/helpers/ptp/main.rs b/libs/gst/helpers/ptp/main.rs
index e550f53..094be5a 100644
--- a/libs/gst/helpers/ptp/main.rs
+++ b/libs/gst/helpers/ptp/main.rs
@@ -243,14 +243,11 @@ fn run() -> Result<(), Error> {
                 // The delay request is the only message that is sent
                 // from PTP clock implementation, if others are added
                 // additional match arms should be added.
-                match ptp_message.message_type {
-                    PtpMessageType::DELAY_REQ => {
-                        if args.verbose {
-                            trace!("Ignoring our own PTP message");
-                        }
-                        continue 'next_packet;
+                if [PtpMessageType::DELAY_REQ].contains(&ptp_message.message_type) {
+                    if args.verbose {
+                        trace!("Ignoring our own PTP message");
                     }
-                    _ => (),
+                    continue 'next_packet;
                 }
 
                 if let PtpMessagePayload::DelayResp {
@@ -409,6 +406,8 @@ fn run() -> Result<(), Error> {
 }
 
 /// Custom panic hook so we can print them to stderr in a format the main process understands
+// `PanicHookInfo` is the new API and only stable since Rust 1.81.
+#[allow(deprecated)]
 fn panic_hook(info: &std::panic::PanicInfo) {
     error!("Panicked. {}", info);
 }
diff --git a/libs/gst/net/gstnetclientclock.c b/libs/gst/net/gstnetclientclock.c
index 0601cb1..8edc72a 100644
--- a/libs/gst/net/gstnetclientclock.c
+++ b/libs/gst/net/gstnetclientclock.c
@@ -63,6 +63,8 @@
 #include "gstnetclientclock.h"
 #include "gstnetutils.h"
 
+#include "gst/glib-compat-private.h"
+
 #include <gio/gio.h>
 
 #include <string.h>
@@ -145,7 +147,6 @@ struct _GstNetClientInternalClock
   GstClockTime minimum_update_interval;
   GstClockTime last_remote_poll_interval;
   GstClockTime last_remote_time;
-  GstClockTime remote_avg_old;
   guint skipped_updates;
   GstClockTime last_rtts[MEDIAN_PRE_FILTERING_WINDOW];
   gint last_rtts_missing;
@@ -233,7 +234,6 @@ gst_net_client_internal_clock_init (GstNetClientInternalClock * self)
   self->skipped_updates = 0;
   self->last_rtts_missing = MEDIAN_PRE_FILTERING_WINDOW;
   self->marked_corrupted = FALSE;
-  self->remote_avg_old = 0;
 }
 
 static void
@@ -428,7 +428,7 @@ gst_net_client_internal_clock_observe_times (GstNetClientInternalClock * self,
     self->last_rtts_missing--;
   } else {
     memcpy (&last_rtts, &self->last_rtts, sizeof (last_rtts));
-    g_qsort_with_data (&last_rtts,
+    g_sort_array (&last_rtts,
         MEDIAN_PRE_FILTERING_WINDOW, sizeof (GstClockTime),
         (GCompareDataFunc) compare_clock_time, NULL);
 
@@ -530,20 +530,6 @@ gst_net_client_internal_clock_observe_times (GstNetClientInternalClock * self,
       && GST_CLOCK_DIFF (time_before,
           remote_avg) < (GstClockTimeDiff) (max_discont));
 
-  /* Check if new remote_avg is less than before to detect if signal lost
-   * sync due to the remote clock has restarted. Then the new remote time will
-   * be less than the previous time which should not happen if increased in a
-   * monotonic way. Also, only perform this check on a synchronized clock to
-   * avoid startup issues.
-   */
-  if (synched) {
-    if (remote_avg < self->remote_avg_old) {
-      gst_clock_set_synced (GST_CLOCK (self), FALSE);
-    } else {
-      self->remote_avg_old = remote_avg;
-    }
-  }
-
   if (gst_clock_add_observation_unapplied (GST_CLOCK_CAST (self),
           local_avg, remote_avg, &r_squared, &internal_time, &external_time,
           &rate_num, &rate_den)) {
@@ -665,6 +651,7 @@ corrupted:
     self->marked_corrupted = TRUE;
   }
   GST_OBJECT_UNLOCK (self);
+  gst_clock_set_synced (GST_CLOCK (self), FALSE);
   return;
 }
 
diff --git a/libs/gst/net/gstptpclock.c b/libs/gst/net/gstptpclock.c
index 1a17f03..f2b1f1b 100644
--- a/libs/gst/net/gstptpclock.c
+++ b/libs/gst/net/gstptpclock.c
@@ -60,6 +60,8 @@
 
 #include <gst/base/base.h>
 
+#include "gst/glib-compat-private.h"
+
 #ifdef G_OS_WIN32
 #define WIN32_LEAN_AND_MEAN
 #include <windows.h>
@@ -294,8 +296,8 @@ typedef struct
 
   GstClockTime announce_interval;       /* last interval we received */
   GQueue announce_messages;
-  guint64 timed_out_sync;       /* how often did this sender continously time out a FOLLOW_UP */
-  guint64 timed_out_delay_resp; /* how often did this sender continously time out a DELAY_RESP */
+  guint64 timed_out_sync;       /* how often did this sender continuously time out a FOLLOW_UP */
+  guint64 timed_out_delay_resp; /* how often did this sender continuously time out a DELAY_RESP */
 } PtpAnnounceSender;
 
 typedef struct
@@ -1457,7 +1459,7 @@ update_mean_path_delay (PtpDomainData * domain, PtpPendingSync * sync)
   } else {
     memcpy (&last_path_delays, &domain->last_path_delays,
         sizeof (last_path_delays));
-    g_qsort_with_data (&last_path_delays,
+    g_sort_array (&last_path_delays,
         MEDIAN_PRE_FILTERING_WINDOW, sizeof (GstClockTime),
         (GCompareDataFunc) compare_clock_time, NULL);
 
@@ -2050,7 +2052,7 @@ handle_send_time_ack (const guint8 * data, gsize size,
         " from helper process",
         GST_STIME_ARGS ((GstClockTimeDiff) (helper_send_time -
                 sync->delay_req_send_time_local)),
-        GST_STIME_ARGS (receive_time - helper_send_time));
+        GST_STIME_ARGS ((GstClockTimeDiff) (receive_time - helper_send_time)));
     sync->delay_req_send_time_local = helper_send_time;
   }
 }
@@ -3292,7 +3294,7 @@ gst_ptp_clock_get_internal_time (GstClock * clock)
 
 /**
  * gst_ptp_clock_new:
- * @name: Name of the clock
+ * @name: (nullable): Name of the clock
  * @domain: PTP domain
  *
  * Creates a new PTP clock instance that exports the PTP time of the master
@@ -3307,7 +3309,7 @@ gst_ptp_clock_get_internal_time (GstClock * clock)
  * check this with gst_clock_wait_for_sync(), the GstClock::synced signal and
  * gst_clock_is_synced().
  *
- * Returns: (transfer full): A new #GstClock
+ * Returns: (transfer full) (nullable): A new #GstClock
  *
  * Since: 1.6
  */
diff --git a/libs/gst/net/meson.build b/libs/gst/net/meson.build
index f4937d6..60ed92c 100644
--- a/libs/gst/net/meson.build
+++ b/libs/gst/net/meson.build
@@ -23,8 +23,17 @@ gst_net_headers = files(
 )
 install_headers(gst_net_headers, subdir : 'gstreamer-1.0/gst/net/')
 
+doc_sources = []
+foreach s: gst_net_sources + gst_net_headers
+  doc_sources += s.full_path()
+endforeach
+
+libs_sources += {
+  'net': pathsep.join(doc_sources)
+}
+
 gst_net_gen_sources = []
-gst_net = library('gstnet-@0@'.format(apiversion),
+gst_net = library('gstnet-@0@'.format(api_version),
   gst_net_sources,
   c_args : gst_c_args + ['-DBUILDING_GST_NET', '-DG_LOG_DOMAIN="GStreamer-Net"'],
   include_directories : [configinc, libsinc],
@@ -50,7 +59,7 @@ if build_gir
   gir = {
     'sources' : gst_net_sources + gst_net_headers,
     'namespace' : 'GstNet',
-    'nsversion' : apiversion,
+    'nsversion' : api_version,
     'identifier_prefix' : 'Gst',
     'symbol_prefix' : 'gst',
     'export_packages' : pkg_name,
diff --git a/libs/meson.build b/libs/meson.build
index 668dcba..35d0778 100644
--- a/libs/meson.build
+++ b/libs/meson.build
@@ -1 +1,3 @@
+libs_sources = {}
+
 subdir('gst')
diff --git a/meson.build b/meson.build
index dc9dbe2..f1be50c 100644
--- a/meson.build
+++ b/meson.build
@@ -1,6 +1,6 @@
 project('gstreamer', 'c',
-  version : '1.24.12',
-  meson_version : '>= 1.1',
+  version : '1.26.0',
+  meson_version : '>= 1.4',
   default_options : [ 'warning_level=1',
                       'buildtype=debugoptimized' ])
 
@@ -16,7 +16,7 @@ else
 endif
 gst_version_is_dev = gst_version_minor % 2 == 1 and gst_version_micro < 90
 
-apiversion = '1.0'
+api_version = '1.0'
 soversion = 0
 # maintaining compatibility with the previous libtool versioning
 # current = minor * 100 + micro
@@ -108,25 +108,29 @@ if gst_version_is_dev
   add_project_arguments('-DG_DISABLE_DEPRECATED', language: 'c')
 endif
 
-cast_checks = get_option('gobject-cast-checks')
-if cast_checks.disabled() or (cast_checks.auto() and not gst_version_is_dev)
+# Same logic as in GLib.
+glib_debug = get_option('glib_debug')
+disable_cast_checks = glib_debug.disabled() or (
+  glib_debug.auto() and (not get_option('debug') or get_option('optimization') not in [ '0', 'g' ]))
+if disable_cast_checks
   message('Disabling GLib cast checks')
   add_project_arguments('-DG_DISABLE_CAST_CHECKS', language: 'c')
+  disable_cast_checks = true
 endif
 
-glib_asserts = get_option('glib-asserts')
-if glib_asserts.disabled() or (glib_asserts.auto() and not gst_version_is_dev)
+disable_glib_asserts = not get_option('glib_assert')
+if disable_glib_asserts
   message('Disabling GLib asserts')
   add_project_arguments('-DG_DISABLE_ASSERT', language: 'c')
 endif
 
-glib_checks = get_option('glib-checks')
-if glib_checks.disabled() or (glib_checks.auto() and not gst_version_is_dev)
+disable_glib_checks = not get_option('glib_checks')
+if disable_glib_checks
   message('Disabling GLib checks')
   add_project_arguments('-DG_DISABLE_CHECKS', language: 'c')
 endif
 
-cdata.set_quoted('GST_API_VERSION', apiversion)
+cdata.set_quoted('GST_API_VERSION', api_version)
 cdata.set_quoted('GST_DATADIR', datadir)
 cdata.set_quoted('LOCALEDIR', join_paths(prefix, get_option('localedir')))
 cdata.set_quoted('LIBDIR', join_paths(prefix, get_option('libdir')))
@@ -435,6 +439,8 @@ if host_system == 'windows'
 
   if not building_for_win7
     add_project_arguments([
+      '-U_WIN32_WINNT',
+      '-UWINVER',
       '-D_WIN32_WINNT=_WIN32_WINNT_WIN7',
       '-DWINVER=_WIN32_WINNT_WIN7',
     ], language: ['c', 'cpp'])
@@ -511,23 +517,28 @@ else
   endif
 endif
 
+# NOTE: Keep entries alphabetically sorted
 warning_flags = [
-  '-Wmissing-declarations',
-  '-Wmissing-prototypes',
-  '-Wredundant-decls',
-  '-Wundef',
-  '-Wwrite-strings',
+  '-Waddress',
+  '-Waggregate-return',
   '-Wformat',
   '-Wformat-nonliteral',
   '-Wformat-security',
-  '-Wold-style-definition',
+  '-Wimplicit-fallthrough=3',
   '-Winit-self',
+  '-Wmissing-declarations',
   '-Wmissing-include-dirs',
-  '-Waddress',
-  '-Waggregate-return',
+  '-Wmissing-parameter-type',
+  '-Wmissing-prototypes',
   '-Wno-multichar',
-  '-Wvla',
+  '-Wold-style-definition',
   '-Wpointer-arith',
+  '-Wredundant-decls',
+  '-Wshift-negative-value',
+  '-Wtype-limits',
+  '-Wundef',
+  '-Wvla',
+  '-Wwrite-strings',
 ]
 
 foreach extra_arg : warning_flags
@@ -598,6 +609,7 @@ gir_init_section = [ '--add-init-section=extern void gst_init(gint*,gchar**);' +
     'g_setenv("GST_REGISTRY_1.0", "/no/way/this/exists.reg", TRUE);' + \
     'g_setenv("GST_PLUGIN_PATH_1_0", "", TRUE);' + \
     'g_setenv("GST_PLUGIN_SYSTEM_PATH_1_0", "", TRUE);' + \
+    'g_setenv("GST_TRACERS", "", TRUE);' + \
     'gst_init(NULL,NULL);', '--quiet']
 
 gst_c_args = ['-DHAVE_CONFIG_H']
@@ -671,8 +683,14 @@ if host_system == 'darwin'
   pkgconfig_libs = ['-Wl,-rpath,${libdir}']
 endif
 
+if host_machine.system() == 'windows'
+  pathsep = ';'
+else
+  pathsep = ':'
+endif
 
 gst_libraries = []
+subdir('cmake')
 subdir('gst')
 subdir('libs')
 subdir('plugins')
@@ -701,7 +719,7 @@ endif
 configure_file(output : 'config.h', configuration : cdata)
 install_data('gst-element-check-1.0.m4', install_dir : join_paths(get_option('datadir'), 'aclocal'))
 
-meson.add_dist_script('scripts/gen-changelog.py', meson.project_name(), '1.22.0', meson.project_version())
+meson.add_dist_script('scripts/gen-changelog.py', meson.project_name(), '1.24.0', meson.project_version())
 
 plugin_names = []
 gst_plugins = []
diff --git a/meson_options.txt b/meson_options.txt
index 340fb58..39255cf 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -33,12 +33,6 @@ option('benchmarks', type : 'feature', value : 'auto', yield : true)
 option('tools', type : 'feature', value : 'auto', yield : true)
 option('introspection', type : 'feature', value : 'auto', yield : true, description : 'Generate gobject-introspection bindings')
 option('nls', type : 'feature', value : 'auto', yield: true, description : 'Enable native language support (translations)')
-option('gobject-cast-checks', type : 'feature', value : 'auto', yield : true,
-       description: 'Enable run-time GObject cast checks (auto = enabled for development, disabled for stable releases)')
-option('glib-asserts', type : 'feature', value : 'enabled', yield : true,
-       description: 'Enable GLib assertion (auto = enabled for development, disabled for stable releases)')
-option('glib-checks', type : 'feature', value : 'enabled', yield : true,
-       description: 'Enable GLib checks such as API guards (auto = enabled for development, disabled for stable releases)')
 option('extra-checks', type : 'feature', value : 'enabled', yield : true, description : 'Enable extra runtime checks')
 
 # Common options
@@ -48,3 +42,21 @@ option('package-origin', type : 'string', value : 'Unknown package origin', yiel
        description : 'package origin URL to use in plugins')
 option('doc', type : 'feature', value : 'auto', yield: true,
        description: 'Enable documentation.')
+option('glib_debug', type : 'feature', value : 'auto', yield : true, description : 'Enable GLib debug infrastructure (see docs/macros.txt)')
+option('glib_assert', type : 'boolean', value : true, yield : true, description : 'Enable GLib assertion (see docs/macros.txt)',
+  deprecated: {'enabled' : 'true', 'disabled' : 'false', 'auto' : 'false'},
+)
+option('glib_checks', type : 'boolean', value : true, yield : true, description : 'Enable GLib checks such as API guards (see docs/macros.txt)',
+  deprecated: {'enabled' : 'true', 'disabled' : 'false', 'auto' : 'false'},
+)
+
+# Deprecated, kept for backward compat
+option('gobject-cast-checks', type : 'feature', value : 'auto', yield : true,
+       description: 'Enable run-time GObject cast checks (auto = enabled for development, disabled for stable releases)',
+       deprecated: 'glib_debug')
+option('glib-asserts', type : 'feature', value : 'enabled', yield : true,
+       description: 'Enable GLib assertion (auto = enabled for development, disabled for stable releases)',
+       deprecated: 'glib_assert')
+option('glib-checks', type : 'feature', value : 'enabled', yield : true,
+       description: 'Enable GLib checks such as API guards (auto = enabled for development, disabled for stable releases)',
+       deprecated: 'glib_checks')
diff --git a/plugins/elements/gstfakesrc.c b/plugins/elements/gstfakesrc.c
index 7142e2c..e3f66b3 100644
--- a/plugins/elements/gstfakesrc.c
+++ b/plugins/elements/gstfakesrc.c
@@ -617,6 +617,7 @@ gst_fake_src_prepare_buffer (GstFakeSrc * src, guint8 * data, gsize size)
     }
     case FAKE_SRC_FILLTYPE_PATTERN:
       src->pattern_byte = 0x00;
+      /* FALLTHROUGH */
     case FAKE_SRC_FILLTYPE_PATTERN_CONT:
     {
       gint i;
diff --git a/plugins/elements/gstfdsrc.c b/plugins/elements/gstfdsrc.c
index 89ccd5a..c2c59f5 100644
--- a/plugins/elements/gstfdsrc.c
+++ b/plugins/elements/gstfdsrc.c
@@ -109,6 +109,7 @@ enum
 
   PROP_FD,
   PROP_TIMEOUT,
+  PROP_IS_LIVE,
 
   PROP_LAST
 };
@@ -172,6 +173,17 @@ gst_fd_src_class_init (GstFdSrcClass * klass)
           G_MAXUINT64, DEFAULT_TIMEOUT,
           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
+  /**
+   * GstFdSrc:is-live
+   *
+   * Act like a live source if set to %TRUE.
+   *
+   * Since: 1.26
+   */
+  g_object_class_install_property (gobject_class, PROP_IS_LIVE,
+      g_param_spec_boolean ("is-live", "is-live", "Act like a live source",
+          FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
   gst_element_class_set_static_metadata (gstelement_class,
       "Filedescriptor Source",
       "Source/File",
@@ -362,6 +374,10 @@ gst_fd_src_set_property (GObject * object, guint prop_id, const GValue * value,
       GST_DEBUG_OBJECT (src, "poll timeout set to %" GST_TIME_FORMAT,
           GST_TIME_ARGS (src->timeout));
       break;
+    case PROP_IS_LIVE:
+      GST_DEBUG_OBJECT (src, "live set to %d", g_value_get_boolean (value));
+      gst_base_src_set_live (GST_BASE_SRC (src), g_value_get_boolean (value));
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -381,6 +397,9 @@ gst_fd_src_get_property (GObject * object, guint prop_id, GValue * value,
     case PROP_TIMEOUT:
       g_value_set_uint64 (value, src->timeout);
       break;
+    case PROP_IS_LIVE:
+      g_value_set_boolean (value, gst_base_src_is_live (GST_BASE_SRC (src)));
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
diff --git a/plugins/elements/gstfilesrc.c b/plugins/elements/gstfilesrc.c
index 01d2ff6..7c5712a 100644
--- a/plugins/elements/gstfilesrc.c
+++ b/plugins/elements/gstfilesrc.c
@@ -325,7 +325,7 @@ gst_file_src_fill (GstBaseSrc * basesrc, guint64 offset, guint length,
     off_t res;
 
     res = lseek (src->fd, offset, SEEK_SET);
-    if (G_UNLIKELY (res < 0 || res != offset))
+    if (G_UNLIKELY (res == (off_t) - 1 || res != offset))
       goto seek_failed;
 
     src->read_position = offset;
@@ -546,14 +546,14 @@ gst_file_src_start (GstBaseSrc * basesrc)
   {
     off_t res = lseek (src->fd, 0, SEEK_END);
 
-    if (res < 0) {
+    if (res == (off_t) - 1) {
       GST_LOG_OBJECT (src, "disabling seeking, lseek failed: %s",
           g_strerror (errno));
       src->seekable = FALSE;
     } else {
       res = lseek (src->fd, 0, SEEK_SET);
 
-      if (res < 0) {
+      if (res == (off_t) - 1) {
         /* We really don't like not being able to go back to 0 */
         src->seekable = FALSE;
         goto lseek_wonky;
diff --git a/plugins/elements/gstoutputselector.c b/plugins/elements/gstoutputselector.c
index 1a1a3fb..da6deca 100644
--- a/plugins/elements/gstoutputselector.c
+++ b/plugins/elements/gstoutputselector.c
@@ -640,8 +640,8 @@ gst_output_selector_event (GstPad * pad, GstObject * parent, GstEvent * event)
       gst_event_copy_segment (event, &sel->segment);
       GST_DEBUG_OBJECT (sel, "configured SEGMENT %" GST_SEGMENT_FORMAT,
           &sel->segment);
-      /* fall through */
     }
+      /* FALLTHROUGH */
     default:
     {
       active = gst_output_selector_get_active (sel);
diff --git a/plugins/elements/gstqueue.c b/plugins/elements/gstqueue.c
index b65da32..8a654cc 100644
--- a/plugins/elements/gstqueue.c
+++ b/plugins/elements/gstqueue.c
@@ -36,9 +36,9 @@
  * processing on sink and source pad.
  *
  * You can query how many buffers are queued by reading the
- * #GstQueue:current-level-buffers property. You can track changes
- * by connecting to the notify::current-level-buffers signal (which
- * like all signals will be emitted from the streaming thread). The same
+ * #GstQueue:current-level-buffers property. If you set #queue:notify-levels to TRUE,
+ * you can track changes by connecting to the notify::current-level-buffers signal
+ * (which like all signals will be emitted from the streaming thread). The same
  * applies to the #GstQueue:current-level-time and
  * #GstQueue:current-level-bytes properties.
  *
@@ -83,7 +83,7 @@ GST_DEBUG_CATEGORY_STATIC (queue_dataflow);
   GST_CAT_LOG_OBJECT (queue_dataflow, queue, \
                       "(%s:%s) " msg ": %u of %u-%u buffers, %u of %u-%u " \
                       "bytes, %" G_GUINT64_FORMAT " of %" G_GUINT64_FORMAT \
-                      "-%" G_GUINT64_FORMAT " ns, %u items", \
+                      "-%" G_GUINT64_FORMAT " ns, %" G_GSIZE_FORMAT " items", \
                       GST_DEBUG_PAD_NAME (pad), \
                       queue->cur_level.buffers, \
                       queue->min_threshold.buffers, \
@@ -94,7 +94,7 @@ GST_DEBUG_CATEGORY_STATIC (queue_dataflow);
                       queue->cur_level.time, \
                       queue->min_threshold.time, \
                       queue->max_size.time, \
-                      gst_queue_array_get_length (queue->queue))
+                      gst_vec_deque_get_length (queue->queue))
 
 /* Queue signals and args */
 enum
@@ -122,9 +122,13 @@ enum
   PROP_MIN_THRESHOLD_TIME,
   PROP_LEAKY,
   PROP_SILENT,
-  PROP_FLUSH_ON_EOS
+  PROP_FLUSH_ON_EOS,
+  PROP_NOTIFY_LEVELS,
+  PROP_LAST
 };
 
+GParamSpec *properties[PROP_LAST];
+
 /* default property values */
 #define DEFAULT_MAX_SIZE_BUFFERS  200   /* 200 buffers */
 #define DEFAULT_MAX_SIZE_BYTES    (10 * 1024 * 1024)    /* 10 MB       */
@@ -144,6 +148,12 @@ enum
   g_mutex_unlock (&q->qlock);                                            \
 } G_STMT_END
 
+#define GST_QUEUE_MUTEX_UNLOCK_NOTIFY_LEVELS(q, prev_level) G_STMT_START { \
+    GstQueueSize new_level = queue->cur_level;                             \
+    g_mutex_unlock (&q->qlock);                                            \
+    gst_queue_notify_levels (queue, &prev_level, &new_level);              \
+} G_STMT_END
+
 #define GST_QUEUE_WAIT_DEL_CHECK(q, label) G_STMT_START {               \
   STATUS (q, q->sinkpad, "wait for DEL");                               \
   q->waiting_del = TRUE;                                                \
@@ -314,63 +324,62 @@ gst_queue_class_init (GstQueueClass * klass)
       NULL, G_TYPE_NONE, 0);
 
   /* properties */
-  g_object_class_install_property (gobject_class, PROP_CUR_LEVEL_BYTES,
+  properties[PROP_CUR_LEVEL_BYTES] =
       g_param_spec_uint ("current-level-bytes", "Current level (kB)",
-          "Current amount of data in the queue (bytes)",
-          0, G_MAXUINT, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
-  g_object_class_install_property (gobject_class, PROP_CUR_LEVEL_BUFFERS,
+      "Current amount of data in the queue (bytes)",
+      0, G_MAXUINT, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+
+  properties[PROP_CUR_LEVEL_BUFFERS] =
       g_param_spec_uint ("current-level-buffers", "Current level (buffers)",
-          "Current number of buffers in the queue",
-          0, G_MAXUINT, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
-  g_object_class_install_property (gobject_class, PROP_CUR_LEVEL_TIME,
+      "Current number of buffers in the queue",
+      0, G_MAXUINT, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+
+  properties[PROP_CUR_LEVEL_TIME] =
       g_param_spec_uint64 ("current-level-time", "Current level (ns)",
-          "Current amount of data in the queue (in ns)",
-          0, G_MAXUINT64, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+      "Current amount of data in the queue (in ns)",
+      0, G_MAXUINT64, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
 
-  g_object_class_install_property (gobject_class, PROP_MAX_SIZE_BYTES,
+  properties[PROP_MAX_SIZE_BYTES] =
       g_param_spec_uint ("max-size-bytes", "Max. size (kB)",
-          "Max. amount of data in the queue (bytes, 0=disable)",
-          0, G_MAXUINT, DEFAULT_MAX_SIZE_BYTES,
-          G_PARAM_READWRITE | GST_PARAM_MUTABLE_PLAYING |
-          G_PARAM_STATIC_STRINGS));
-  g_object_class_install_property (gobject_class, PROP_MAX_SIZE_BUFFERS,
+      "Max. amount of data in the queue (bytes, 0=disable)",
+      0, G_MAXUINT, DEFAULT_MAX_SIZE_BYTES,
+      G_PARAM_READWRITE | GST_PARAM_MUTABLE_PLAYING | G_PARAM_STATIC_STRINGS);
+
+  properties[PROP_MAX_SIZE_BUFFERS] =
       g_param_spec_uint ("max-size-buffers", "Max. size (buffers)",
-          "Max. number of buffers in the queue (0=disable)", 0, G_MAXUINT,
-          DEFAULT_MAX_SIZE_BUFFERS,
-          G_PARAM_READWRITE | GST_PARAM_MUTABLE_PLAYING |
-          G_PARAM_STATIC_STRINGS));
-  g_object_class_install_property (gobject_class, PROP_MAX_SIZE_TIME,
+      "Max. number of buffers in the queue (0=disable)", 0, G_MAXUINT,
+      DEFAULT_MAX_SIZE_BUFFERS,
+      G_PARAM_READWRITE | GST_PARAM_MUTABLE_PLAYING | G_PARAM_STATIC_STRINGS);
+
+  properties[PROP_MAX_SIZE_TIME] =
       g_param_spec_uint64 ("max-size-time", "Max. size (ns)",
-          "Max. amount of data in the queue (in ns, 0=disable)", 0, G_MAXUINT64,
-          DEFAULT_MAX_SIZE_TIME,
-          G_PARAM_READWRITE | GST_PARAM_MUTABLE_PLAYING |
-          G_PARAM_STATIC_STRINGS));
+      "Max. amount of data in the queue (in ns, 0=disable)", 0, G_MAXUINT64,
+      DEFAULT_MAX_SIZE_TIME,
+      G_PARAM_READWRITE | GST_PARAM_MUTABLE_PLAYING | G_PARAM_STATIC_STRINGS);
 
-  g_object_class_install_property (gobject_class, PROP_MIN_THRESHOLD_BYTES,
+  properties[PROP_MIN_THRESHOLD_BYTES] =
       g_param_spec_uint ("min-threshold-bytes", "Min. threshold (kB)",
-          "Min. amount of data in the queue to allow reading (bytes, 0=disable)",
-          0, G_MAXUINT, 0,
-          G_PARAM_READWRITE | GST_PARAM_MUTABLE_PLAYING |
-          G_PARAM_STATIC_STRINGS));
-  g_object_class_install_property (gobject_class, PROP_MIN_THRESHOLD_BUFFERS,
+      "Min. amount of data in the queue to allow reading (bytes, 0=disable)",
+      0, G_MAXUINT, 0,
+      G_PARAM_READWRITE | GST_PARAM_MUTABLE_PLAYING | G_PARAM_STATIC_STRINGS);
+
+  properties[PROP_MIN_THRESHOLD_BUFFERS] =
       g_param_spec_uint ("min-threshold-buffers", "Min. threshold (buffers)",
-          "Min. number of buffers in the queue to allow reading (0=disable)", 0,
-          G_MAXUINT, 0,
-          G_PARAM_READWRITE | GST_PARAM_MUTABLE_PLAYING |
-          G_PARAM_STATIC_STRINGS));
-  g_object_class_install_property (gobject_class, PROP_MIN_THRESHOLD_TIME,
+      "Min. number of buffers in the queue to allow reading (0=disable)", 0,
+      G_MAXUINT, 0,
+      G_PARAM_READWRITE | GST_PARAM_MUTABLE_PLAYING | G_PARAM_STATIC_STRINGS);
+
+  properties[PROP_MIN_THRESHOLD_TIME] =
       g_param_spec_uint64 ("min-threshold-time", "Min. threshold (ns)",
-          "Min. amount of data in the queue to allow reading (in ns, 0=disable)",
-          0, G_MAXUINT64, 0,
-          G_PARAM_READWRITE | GST_PARAM_MUTABLE_PLAYING |
-          G_PARAM_STATIC_STRINGS));
+      "Min. amount of data in the queue to allow reading (in ns, 0=disable)",
+      0, G_MAXUINT64, 0,
+      G_PARAM_READWRITE | GST_PARAM_MUTABLE_PLAYING | G_PARAM_STATIC_STRINGS);
 
-  g_object_class_install_property (gobject_class, PROP_LEAKY,
+  properties[PROP_LEAKY] =
       g_param_spec_enum ("leaky", "Leaky",
-          "Where the queue leaks, if at all",
-          GST_TYPE_QUEUE_LEAKY, GST_QUEUE_NO_LEAK,
-          G_PARAM_READWRITE | GST_PARAM_MUTABLE_PLAYING |
-          G_PARAM_STATIC_STRINGS));
+      "Where the queue leaks, if at all",
+      GST_TYPE_QUEUE_LEAKY, GST_QUEUE_NO_LEAK,
+      G_PARAM_READWRITE | GST_PARAM_MUTABLE_PLAYING | G_PARAM_STATIC_STRINGS);
 
   /**
    * GstQueue:silent
@@ -378,11 +387,10 @@ gst_queue_class_init (GstQueueClass * klass)
    * Don't emit queue signals. Makes queues more lightweight if no signals are
    * needed.
    */
-  g_object_class_install_property (gobject_class, PROP_SILENT,
+  properties[PROP_SILENT] =
       g_param_spec_boolean ("silent", "Silent",
-          "Don't emit queue signals", FALSE,
-          G_PARAM_READWRITE | GST_PARAM_MUTABLE_PLAYING |
-          G_PARAM_STATIC_STRINGS));
+      "Don't emit queue signals", FALSE,
+      G_PARAM_READWRITE | GST_PARAM_MUTABLE_PLAYING | G_PARAM_STATIC_STRINGS);
 
   /**
    * queue:flush-on-eos:
@@ -399,12 +407,26 @@ gst_queue_class_init (GstQueueClass * klass)
    *
    * Since: 1.2
    */
-  g_object_class_install_property (gobject_class, PROP_FLUSH_ON_EOS,
+  properties[PROP_FLUSH_ON_EOS] =
       g_param_spec_boolean ("flush-on-eos", "Flush on EOS",
-          "Discard all data in the queue when an EOS event is received", FALSE,
-          G_PARAM_READWRITE | GST_PARAM_MUTABLE_PLAYING |
-          G_PARAM_STATIC_STRINGS));
+      "Discard all data in the queue when an EOS event is received", FALSE,
+      G_PARAM_READWRITE | GST_PARAM_MUTABLE_PLAYING | G_PARAM_STATIC_STRINGS);
 
+  /**
+   * GstQueue:notify-levels
+   *
+   * Whether to emit `notify:property-name` signals on levels changes or not
+   *
+   * Default: %FALSE
+   *
+   * Since: 1.26
+   */
+  properties[PROP_NOTIFY_LEVELS] =
+      g_param_spec_boolean ("notify-levels", "Notify-Levels",
+      "Whether to emit `notify` signals on levels changes or not", FALSE,
+      G_PARAM_READWRITE | GST_PARAM_MUTABLE_PLAYING | G_PARAM_STATIC_STRINGS);
+
+  g_object_class_install_properties (gobject_class, PROP_LAST, properties);
   gobject_class->finalize = gst_queue_finalize;
 
   gst_element_class_set_static_metadata (gstelement_class,
@@ -467,7 +489,7 @@ gst_queue_init (GstQueue * queue)
   g_cond_init (&queue->query_handled);
 
   queue->queue =
-      gst_queue_array_new_for_struct (sizeof (GstQueueItem),
+      gst_vec_deque_new_for_struct (sizeof (GstQueueItem),
       DEFAULT_MAX_SIZE_BUFFERS * 3 / 2);
 
   queue->sinktime = GST_CLOCK_STIME_NONE;
@@ -492,12 +514,12 @@ gst_queue_finalize (GObject * object)
 
   GST_DEBUG_OBJECT (queue, "finalizing queue");
 
-  while ((qitem = gst_queue_array_pop_head_struct (queue->queue))) {
+  while ((qitem = gst_vec_deque_pop_head_struct (queue->queue))) {
     /* FIXME: if it's a query, shouldn't we unref that too? */
     if (!qitem->is_query)
       gst_mini_object_unref (qitem->item);
   }
-  gst_queue_array_free (queue->queue);
+  gst_vec_deque_free (queue->queue);
 
   g_mutex_clear (&queue->qlock);
   g_cond_clear (&queue->item_add);
@@ -745,12 +767,30 @@ apply_buffer_list (GstQueue * queue, GstBufferList * buffer_list,
   update_time_level (queue);
 }
 
+static void
+gst_queue_notify_levels (GstQueue * queue, GstQueueSize * prev_level,
+    GstQueueSize * new_level)
+{
+  if (!queue->notify_levels) {
+    return;
+  }
+  if (new_level->buffers != prev_level->buffers)
+    g_object_notify_by_pspec ((GObject *) queue,
+        properties[PROP_CUR_LEVEL_BUFFERS]);
+  if (new_level->bytes != prev_level->bytes)
+    g_object_notify_by_pspec ((GObject *) queue,
+        properties[PROP_CUR_LEVEL_BYTES]);
+  if (new_level->time != prev_level->time)
+    g_object_notify_by_pspec ((GObject *) queue,
+        properties[PROP_CUR_LEVEL_TIME]);
+}
+
 static void
 gst_queue_locked_flush (GstQueue * queue, gboolean full)
 {
   GstQueueItem *qitem;
 
-  while ((qitem = gst_queue_array_pop_head_struct (queue->queue))) {
+  while ((qitem = gst_vec_deque_pop_head_struct (queue->queue))) {
     /* Then lose another reference because we are supposed to destroy that
        data when flushing */
     if (!full && !qitem->is_query && GST_IS_EVENT (qitem->item)
@@ -797,7 +837,7 @@ gst_queue_locked_enqueue_buffer (GstQueue * queue, gpointer item)
   qitem.item = item;
   qitem.is_query = FALSE;
   qitem.size = bsize;
-  gst_queue_array_push_tail_struct (queue->queue, &qitem);
+  gst_vec_deque_push_tail_struct (queue->queue, &qitem);
   GST_QUEUE_SIGNAL_ADD (queue);
 }
 
@@ -818,7 +858,7 @@ gst_queue_locked_enqueue_buffer_list (GstQueue * queue, gpointer item)
   qitem.item = item;
   qitem.is_query = FALSE;
   qitem.size = bsize;
-  gst_queue_array_push_tail_struct (queue->queue, &qitem);
+  gst_vec_deque_push_tail_struct (queue->queue, &qitem);
   GST_QUEUE_SIGNAL_ADD (queue);
 }
 
@@ -843,7 +883,7 @@ gst_queue_locked_enqueue_event (GstQueue * queue, gpointer item)
     case GST_EVENT_SEGMENT:
       apply_segment (queue, event, &queue->sink_segment, TRUE);
       /* if the queue is empty, apply sink segment on the source */
-      if (gst_queue_array_is_empty (queue->queue)) {
+      if (gst_vec_deque_is_empty (queue->queue)) {
         GST_CAT_LOG_OBJECT (queue_dataflow, queue, "Apply segment on srcpad");
         apply_segment (queue, event, &queue->src_segment, FALSE);
         queue->newseg_applied_to_src = TRUE;
@@ -862,7 +902,7 @@ gst_queue_locked_enqueue_event (GstQueue * queue, gpointer item)
   qitem.item = item;
   qitem.is_query = FALSE;
   qitem.size = 0;
-  gst_queue_array_push_tail_struct (queue->queue, &qitem);
+  gst_vec_deque_push_tail_struct (queue->queue, &qitem);
   GST_QUEUE_SIGNAL_ADD (queue);
 }
 
@@ -874,7 +914,7 @@ gst_queue_locked_dequeue (GstQueue * queue)
   GstMiniObject *item;
   gsize bufsize;
 
-  qitem = gst_queue_array_pop_head_struct (queue->queue);
+  qitem = gst_vec_deque_pop_head_struct (queue->queue);
   if (qitem == NULL)
     goto no_item;
 
@@ -1016,6 +1056,7 @@ gst_queue_handle_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
       if (GST_EVENT_IS_SERIALIZED (event)) {
         /* serialized events go in the queue */
         GST_QUEUE_MUTEX_LOCK (queue);
+        GstQueueSize prev_level = queue->cur_level;
 
         /* STREAM_START and SEGMENT reset the EOS status of a
          * pad. Change the cached sinkpad flow result accordingly */
@@ -1069,7 +1110,7 @@ gst_queue_handle_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
         }
 
         gst_queue_locked_enqueue_event (queue, event);
-        GST_QUEUE_MUTEX_UNLOCK (queue);
+        GST_QUEUE_MUTEX_UNLOCK_NOTIFY_LEVELS (queue, prev_level);
       } else {
         /* non-serialized events are forwarded downstream immediately */
         ret = gst_pad_push_event (queue->srcpad, event);
@@ -1117,7 +1158,7 @@ gst_queue_handle_sink_query (GstPad * pad, GstObject * parent, GstQuery * query)
         qitem.item = GST_MINI_OBJECT_CAST (query);
         qitem.is_query = TRUE;
         qitem.size = 0;
-        gst_queue_array_push_tail_struct (queue->queue, &qitem);
+        gst_vec_deque_push_tail_struct (queue->queue, &qitem);
         GST_QUEUE_SIGNAL_ADD (queue);
         while (queue->srcresult == GST_FLOW_OK &&
             queue->last_handled_query != query)
@@ -1148,7 +1189,7 @@ gst_queue_is_empty (GstQueue * queue)
 {
   GstQueueItem *tail;
 
-  tail = gst_queue_array_peek_tail_struct (queue->queue);
+  tail = gst_vec_deque_peek_tail_struct (queue->queue);
 
   if (tail == NULL)
     return TRUE;
@@ -1236,6 +1277,7 @@ gst_queue_chain_buffer_or_list (GstPad * pad, GstObject * parent,
 
   /* we have to lock the queue since we span threads */
   GST_QUEUE_MUTEX_LOCK_CHECK (queue, out_flushing);
+  GstQueueSize prev_level = queue->cur_level;
   /* when we received EOS, we refuse any more data */
   if (queue->eos)
     goto out_eos;
@@ -1283,8 +1325,15 @@ gst_queue_chain_buffer_or_list (GstPad * pad, GstObject * parent,
         /* now we can clean up and exit right away */
         goto out_unref;
       case GST_QUEUE_LEAK_DOWNSTREAM:
+      {
         gst_queue_leak_downstream (queue);
+
+        if (!queue->silent) {
+          GST_QUEUE_MUTEX_UNLOCK_NOTIFY_LEVELS (queue, prev_level);
+          GST_QUEUE_MUTEX_LOCK_CHECK (queue, out_flushing);
+        }
         break;
+      }
       default:
         g_warning ("Unknown leaky type, using default");
         /* fall-through */
@@ -1339,14 +1388,14 @@ gst_queue_chain_buffer_or_list (GstPad * pad, GstObject * parent,
     gst_queue_locked_enqueue_buffer_list (queue, obj);
   else
     gst_queue_locked_enqueue_buffer (queue, obj);
-  GST_QUEUE_MUTEX_UNLOCK (queue);
+  GST_QUEUE_MUTEX_UNLOCK_NOTIFY_LEVELS (queue, prev_level);
 
   return GST_FLOW_OK;
 
   /* special conditions */
 out_unref:
   {
-    GST_QUEUE_MUTEX_UNLOCK (queue);
+    GST_QUEUE_MUTEX_UNLOCK_NOTIFY_LEVELS (queue, prev_level);
 
     gst_mini_object_unref (obj);
 
@@ -1586,12 +1635,14 @@ gst_queue_loop (GstPad * pad)
     }
   }
 
+  GstQueueSize prev_level = queue->cur_level;
+
   ret = gst_queue_push_one (queue);
   queue->srcresult = ret;
   if (ret != GST_FLOW_OK)
     goto out_flushing;
 
-  GST_QUEUE_MUTEX_UNLOCK (queue);
+  GST_QUEUE_MUTEX_UNLOCK_NOTIFY_LEVELS (queue, prev_level);
 
   return;
 
@@ -1616,6 +1667,7 @@ out_flushing:
       g_cond_signal (&queue->query_handled);
     }
     GST_QUEUE_MUTEX_UNLOCK (queue);
+
     /* let app know about us giving up if upstream is not expected to do so */
     /* EOS is already taken care of elsewhere */
     if (eos && (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS)) {
@@ -1896,6 +1948,9 @@ gst_queue_set_property (GObject * object,
     case PROP_FLUSH_ON_EOS:
       queue->flush_on_eos = g_value_get_boolean (value);
       break;
+    case PROP_NOTIFY_LEVELS:
+      queue->notify_levels = g_value_get_boolean (value);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -1949,6 +2004,9 @@ gst_queue_get_property (GObject * object,
     case PROP_FLUSH_ON_EOS:
       g_value_set_boolean (value, queue->flush_on_eos);
       break;
+    case PROP_NOTIFY_LEVELS:
+      g_value_set_boolean (value, queue->notify_levels);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
diff --git a/plugins/elements/gstqueue.h b/plugins/elements/gstqueue.h
index cc632ad..12d8c1b 100644
--- a/plugins/elements/gstqueue.h
+++ b/plugins/elements/gstqueue.h
@@ -109,7 +109,7 @@ struct _GstQueue {
   gboolean      eos;
 
   /* the queue of data we're keeping our grubby hands on */
-  GstQueueArray *queue;
+  GstVecDeque *queue;
 
   GstQueueSize
     cur_level,          /* currently in the queue */
@@ -129,7 +129,8 @@ struct _GstQueue {
   gboolean head_needs_discont, tail_needs_discont;
   gboolean push_newsegment;
 
-  gboolean silent;      /* don't emit signals */
+  gboolean silent;             /* don't emit signals */
+  gboolean notify_levels;      /* emit 'notify' signals on level changes */
 
   /* whether the first new segment has been applied to src */
   gboolean newseg_applied_to_src;
diff --git a/plugins/elements/gstqueue2.c b/plugins/elements/gstqueue2.c
index 82cb148..1fa62f9 100644
--- a/plugins/elements/gstqueue2.c
+++ b/plugins/elements/gstqueue2.c
@@ -201,7 +201,7 @@ static GParamSpec *obj_props[PROP_LAST] = { NULL, };
                       queue->max_level.time, \
                       (guint64) (!QUEUE_IS_USING_QUEUE(queue) ? \
                         queue->current->writing_pos - queue->current->max_reading_pos : \
-                        gst_queue_array_get_length(queue->queue)))
+                        gst_vec_deque_get_length(queue->queue)))
 
 #define GST_QUEUE2_MUTEX_LOCK(q) G_STMT_START {                          \
   g_mutex_lock (&q->qlock);                                              \
@@ -550,7 +550,7 @@ gst_queue2_init (GstQueue2 * queue)
   g_cond_init (&queue->item_add);
   queue->waiting_del = FALSE;
   g_cond_init (&queue->item_del);
-  queue->queue = gst_queue_array_new_for_struct (sizeof (GstQueue2Item), 32);
+  queue->queue = gst_vec_deque_new_for_struct (sizeof (GstQueue2Item), 32);
 
   g_cond_init (&queue->query_handled);
   queue->last_query = FALSE;
@@ -582,11 +582,11 @@ gst_queue2_finalize (GObject * object)
 
   GST_DEBUG_OBJECT (queue, "finalizing queue");
 
-  while ((qitem = gst_queue_array_pop_head_struct (queue->queue))) {
+  while ((qitem = gst_vec_deque_pop_head_struct (queue->queue))) {
     if (qitem->type != GST_QUEUE2_ITEM_TYPE_QUERY)
       gst_mini_object_unref (qitem->item);
   }
-  gst_queue_array_free (queue->queue);
+  gst_vec_deque_free (queue->queue);
 
   queue->last_query = FALSE;
   g_mutex_clear (&queue->qlock);
@@ -1910,7 +1910,7 @@ gst_queue2_locked_flush (GstQueue2 * queue, gboolean full, gboolean clear_temp)
   } else {
     GstQueue2Item *qitem;
 
-    while ((qitem = gst_queue_array_pop_head_struct (queue->queue))) {
+    while ((qitem = gst_vec_deque_pop_head_struct (queue->queue))) {
       if (!full && qitem->type == GST_QUEUE2_ITEM_TYPE_EVENT
           && GST_EVENT_IS_STICKY (qitem->item)
           && GST_EVENT_TYPE (qitem->item) != GST_EVENT_SEGMENT
@@ -2437,7 +2437,7 @@ gst_queue2_locked_enqueue (GstQueue2 * queue, gpointer item,
 
       qitem.type = item_type;
       qitem.item = item;
-      gst_queue_array_push_tail_struct (queue->queue, &qitem);
+      gst_vec_deque_push_tail_struct (queue->queue, &qitem);
     } else {
       gst_mini_object_unref (GST_MINI_OBJECT_CAST (item));
     }
@@ -2469,7 +2469,7 @@ gst_queue2_locked_dequeue (GstQueue2 * queue, GstQueue2ItemType * item_type)
   if (!QUEUE_IS_USING_QUEUE (queue)) {
     item = gst_queue2_read_item_from_file (queue);
   } else {
-    GstQueue2Item *qitem = gst_queue_array_pop_head_struct (queue->queue);
+    GstQueue2Item *qitem = gst_vec_deque_pop_head_struct (queue->queue);
 
     if (qitem == NULL)
       goto no_item;
@@ -2671,8 +2671,8 @@ gst_queue2_handle_sink_event (GstPad * pad, GstObject * parent,
           g_object_notify_by_pspec (G_OBJECT (queue), obj_props[PROP_BITRATE]);
         }
       }
-      /* Fall-through */
     }
+      /* FALLTHROUGH */
     default:
       if (GST_EVENT_IS_SERIALIZED (event)) {
         gboolean bitrate_changed = TRUE;
@@ -2856,7 +2856,7 @@ gst_queue2_is_empty (GstQueue2 * queue)
   if (!QUEUE_IS_USING_QUEUE (queue) && queue->current) {
     return queue->current->writing_pos <= queue->current->max_reading_pos;
   } else {
-    if (gst_queue_array_get_length (queue->queue) == 0)
+    if (gst_vec_deque_get_length (queue->queue) == 0)
       return TRUE;
   }
 
diff --git a/plugins/elements/gstqueue2.h b/plugins/elements/gstqueue2.h
index 8ad8a19..40c69b5 100644
--- a/plugins/elements/gstqueue2.h
+++ b/plugins/elements/gstqueue2.h
@@ -100,7 +100,7 @@ struct _GstQueue2
   gboolean unexpected;
 
   /* the queue of data we're keeping our hands on */
-  GstQueueArray *queue;
+  GstVecDeque *queue;
 
   GCond query_handled;
   gboolean last_query; /* result of last serialized query */
diff --git a/plugins/elements/gsttee.c b/plugins/elements/gsttee.c
index dd90c38..27a4b76 100644
--- a/plugins/elements/gsttee.c
+++ b/plugins/elements/gsttee.c
@@ -685,6 +685,7 @@ gst_tee_query_allocation (const GValue * item, GValue * ret, gpointer user_data)
     /* Afterward, aggregate the common params */
     if (gst_query_find_allocation_meta (ctx->query, api, &ctx_index)) {
       const GstStructure *ctx_param;
+      GstStructure *aggregated_params = NULL;
 
       gst_query_parse_nth_allocation_meta (ctx->query, ctx_index, &ctx_param);
 
@@ -692,7 +693,17 @@ gst_tee_query_allocation (const GValue * item, GValue * ret, gpointer user_data)
       if (ctx_param == NULL && param == NULL)
         continue;
 
-      GST_DEBUG_OBJECT (ctx->tee, "Dropping allocation meta %s",
+      /* Aggregate the two params, if successful, add it to the query.
+       * and then, we always Drop the old params from the query. */
+      if (gst_meta_api_type_aggregate_params (api, &aggregated_params,
+              ctx_param, param)) {
+        gst_query_add_allocation_meta (ctx->query, api, aggregated_params);
+
+        if (aggregated_params)
+          gst_structure_free (aggregated_params);
+      }
+
+      GST_DEBUG_OBJECT (ctx->tee, "Dropping old allocation meta %s",
           g_type_name (api));
       gst_query_remove_nth_allocation_meta (ctx->query, ctx_index);
     }
diff --git a/plugins/elements/gsttypefindelement.c b/plugins/elements/gsttypefindelement.c
index 6cd4e4b..b489099 100644
--- a/plugins/elements/gsttypefindelement.c
+++ b/plugins/elements/gsttypefindelement.c
@@ -720,8 +720,8 @@ gst_type_find_element_sink_event (GstPad * pad, GstObject * parent,
           typefind->cached_events = NULL;
           gst_adapter_clear (typefind->adapter);
           GST_OBJECT_UNLOCK (typefind);
-          /* fall through */
         }
+          /* FALLTHROUGH */
         case GST_EVENT_FLUSH_START:
           res = gst_pad_push_event (typefind->src, event);
           break;
diff --git a/plugins/elements/meson.build b/plugins/elements/meson.build
index 998fb9a..1d30d80 100644
--- a/plugins/elements/meson.build
+++ b/plugins/elements/meson.build
@@ -26,6 +26,34 @@ gst_elements_sources = [
   'gstvalve.c',
 ]
 
+gst_elements_headers = [
+  'gstcapsfilter.h',
+  'gstclocksync.h',
+  'gstconcat.h',
+  'gstcoreelementselements.h',
+  'gstdataurisrc.h',
+  'gstdownloadbuffer.h',
+  'gstelements_private.h',
+  'gstfakesink.h',
+  'gstfakesrc.h',
+  'gstfdsink.h',
+  'gstfdsrc.h',
+  'gstfilesink.h',
+  'gstfilesrc.h',
+  'gstfunnel.h',
+  'gstidentity.h',
+  'gstinputselector.h',
+  'gstmultiqueue.h',
+  'gstoutputselector.h',
+  'gstqueue2.h',
+  'gstqueue.h',
+  'gstsparsefile.h',
+  'gststreamiddemux.h',
+  'gsttee.h',
+  'gsttypefindelement.h',
+  'gstvalve.h',
+]
+
 gst_elements = library('gstcoreelements',
   gst_elements_sources,
   c_args : gst_c_args,
@@ -36,3 +64,12 @@ gst_elements = library('gstcoreelements',
 )
 
 plugins += [gst_elements]
+
+doc_sources = []
+foreach s: gst_elements_sources + gst_elements_headers
+  doc_sources += meson.current_source_dir() / s
+endforeach
+
+plugin_sources += {
+  'coreelements': pathsep.join(doc_sources)
+}
diff --git a/plugins/meson.build b/plugins/meson.build
index ddb3a6e..12c95c3 100644
--- a/plugins/meson.build
+++ b/plugins/meson.build
@@ -1,5 +1,4 @@
 plugins = []
+plugin_sources = {}
 subdir('elements')
-if not get_option('coretracers').disabled()
-  subdir('tracers')
-endif
+subdir('tracers')
diff --git a/plugins/tracers/gstdots.c b/plugins/tracers/gstdots.c
new file mode 100644
index 0000000..8899b2d
--- /dev/null
+++ b/plugins/tracers/gstdots.c
@@ -0,0 +1,291 @@
+/* gstdotstracer.c */
+/**
+ * SECTION:tracer-dots
+ * @short_description: Tracer for dot file generation setup and pipeline
+ * snapshot integration
+ * @title: GstDotsTracer
+ *
+ * The Dots tracer handles dot file generation setup and integrates with the
+ * pipeline-snapshot tracer when available. It ensures proper directory setup
+ * to collaborate with the `gst-dots-viewer` tool, and it handles file cleanup.
+ *
+ * The tracer determines the output directory in the following order:
+ * 1. Uses GST_DEBUG_DUMP_DOT_DIR if set
+ * 2. Falls back to $XDG_CACHE_HOME/gstreamer-dots otherwise
+ *
+ * The determined directory is created if it doesn't exist and set as
+ * `GST_DEBUG_DUMP_DOT_DIR` for the entire process.
+ *
+ * When available, it instantiates the pipeline-snapshot tracer with the
+ * following configuration:
+ * - dots-viewer-ws-url=ws://127.0.0.1:3000/snapshot/
+ * - xdg-cache=true
+ * - folder-mode=numbered
+ *
+ * ## Examples:
+ *
+ * ```
+ * # Basic usage - will delete existing .dot files
+ * GST_TRACERS=dots gst-launch-1.0 videotestsrc ! autovideosink
+ *
+ * # Keep existing .dot files
+ * GST_TRACERS="dots(no-delete=true)" gst-launch-1.0 videotestsrc ! autovideosink
+ * ```
+ *
+ * Since: 1.26
+ */
+
+#include "gst/gsttracerfactory.h"
+#include <gio/gio.h>
+#include <glib/gstdio.h>
+#include <gst/gst.h>
+#include <gst/gsttracer.h>
+
+#define GST_TYPE_DOTS_TRACER (gst_dots_tracer_get_type())
+G_DECLARE_FINAL_TYPE (GstDotsTracer, gst_dots_tracer, GST, DOTS_TRACER,
+    GstTracer)
+/**
+ * GstDotsTracer:
+ *
+ * The #GstDotsTracer structure.
+ *
+ * Since: 1.26
+ */
+/* *INDENT-OFF* */
+struct _GstDotsTracer
+{
+  GstTracer parent;
+
+  gboolean no_delete;
+  gchar *output_dir;
+  GstTracer *pipeline_snapshot_tracer;
+};
+
+G_DEFINE_TYPE (GstDotsTracer, gst_dots_tracer, GST_TYPE_TRACER);
+
+enum {
+  PROP_0,
+  PROP_NO_DELETE,
+  N_PROPERTIES
+};
+
+static GParamSpec *properties[N_PROPERTIES] = {
+  NULL,
+};
+
+GST_DEBUG_CATEGORY_STATIC (dots_debug);
+#define GST_CAT_DEFAULT dots_debug
+
+static void
+gst_dots_tracer_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec)
+/* *INDENT-ON* */
+{
+  GstDotsTracer *self = GST_DOTS_TRACER (object);
+
+  switch (prop_id) {
+    case PROP_NO_DELETE:
+      self->no_delete = g_value_get_boolean (value);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void
+gst_dots_tracer_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec)
+{
+  GstDotsTracer *self = GST_DOTS_TRACER (object);
+
+  switch (prop_id) {
+    case PROP_NO_DELETE:
+      g_value_set_boolean (value, self->no_delete);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void
+gst_dots_tracer_finalize (GObject * obj)
+{
+  GstDotsTracer *self = GST_DOTS_TRACER (obj);
+
+  g_free (self->output_dir);
+
+  if (self->pipeline_snapshot_tracer) {
+    gst_object_unref (self->pipeline_snapshot_tracer);
+  }
+
+  G_OBJECT_CLASS (gst_dots_tracer_parent_class)->finalize (obj);
+}
+
+static void
+clean_dot_files (const gchar * dir_path)
+{
+  GDir *dir;
+  const gchar *filename;
+  GError *error = NULL;
+  GSList *paths = NULL, *l;
+  GSList *dirs = NULL;
+
+  /* Build directory list starting with root dir */
+  dirs = g_slist_prepend (dirs, g_strdup (dir_path));
+
+  /* Find all matching files */
+  while (dirs) {
+    gchar *current_dir = dirs->data;
+    dirs = g_slist_delete_link (dirs, dirs);
+
+    dir = g_dir_open (current_dir, 0, &error);
+    if (!dir) {
+      GST_WARNING ("Could not open directory %s: %s", current_dir,
+          error ? error->message : "unknown error");
+      g_clear_error (&error);
+      g_free (current_dir);
+      continue;
+    }
+
+    while ((filename = g_dir_read_name (dir))) {
+      gchar *path = g_build_filename (current_dir, filename, NULL);
+
+      if (g_file_test (path, G_FILE_TEST_IS_DIR)) {
+        dirs = g_slist_prepend (dirs, path);
+      } else if (g_str_has_suffix (path, ".dot")) {
+        paths = g_slist_prepend (paths, path);
+      } else {
+        g_free (path);
+      }
+    }
+    g_dir_close (dir);
+    g_free (current_dir);
+  }
+
+  /* Delete all matched files */
+  for (l = paths; l; l = l->next) {
+    if (g_unlink (l->data) != 0) {
+      GST_WARNING ("Could not delete file %s", (gchar *) l->data);
+    }
+  }
+
+  g_slist_free_full (paths, g_free);
+}
+
+static gboolean
+try_create_pipeline_snapshot_tracer (GstDotsTracer * self)
+{
+  GstRegistry *registry;
+  GstPluginFeature *feature;
+  GstTracerFactory *factory;
+
+  registry = gst_registry_get ();
+  feature = gst_registry_lookup_feature (registry, "pipeline-snapshot");
+
+  if (!feature) {
+    GST_WARNING ("pipeline-snapshot tracer not found. \
+Please ensure that the `rstracers` plugin is installed.");
+    return FALSE;
+  }
+
+  factory = GST_TRACER_FACTORY (gst_plugin_feature_load (feature));
+  gst_object_unref (feature);
+
+  if (!factory) {
+    GST_WARNING ("Could not load pipeline-snapshot factory. \
+Please ensure GStreamer is properly installed.");
+    return FALSE;
+  }
+
+  GType tracer_type = gst_tracer_factory_get_tracer_type (factory);
+  GObjectClass *tracer_class = g_type_class_ref (tracer_type);
+
+  if (g_object_class_find_property (tracer_class, "dots-viewer-ws-url"))
+    self->pipeline_snapshot_tracer = g_object_new (gst_tracer_factory_get_tracer_type (factory), "dot-dir", self->output_dir, "dots-viewer-ws-url", "ws://127.0.0.1:3000/snapshot/", "folder-mode", 1,  /*numbered */
+        NULL);
+  else
+    self->pipeline_snapshot_tracer =
+        g_object_new (gst_tracer_factory_get_tracer_type (factory), NULL);
+  gst_object_unref (factory);
+  g_type_class_unref (tracer_class);
+
+  if (!self->pipeline_snapshot_tracer) {
+    GST_WARNING ("Could not create pipeline-snapshot tracer instance");
+    return FALSE;
+  }
+
+  GST_INFO ("Successfully created and configured pipeline-snapshot tracer");
+  return TRUE;
+}
+
+static void
+setup_output_directory (GstDotsTracer * self)
+{
+  const gchar *env_dir;
+
+  // Check GST_DEBUG_DUMP_DOT_DIR first
+  env_dir = g_getenv ("GST_DEBUG_DUMP_DOT_DIR");
+  if (env_dir) {
+    self->output_dir = g_strdup (env_dir);
+  } else {
+    // Use XDG cache directory if GST_DEBUG_DUMP_DOT_DIR is not set
+    self->output_dir =
+        g_build_filename (g_get_user_cache_dir (), "gstreamer-dots", NULL);
+
+    GST_ERROR ("Setting GST_DEBUG_DUMP_DOT_DIR to %s", self->output_dir);
+
+    g_setenv ("GST_DEBUG_DUMP_DOT_DIR", self->output_dir, TRUE);
+  }
+
+  // Create output directory if it doesn't exist
+  g_mkdir_with_parents (self->output_dir, 0755);
+
+  // Clean existing .dot files unless no-delete is set
+  if (!self->no_delete) {
+    clean_dot_files (self->output_dir);
+  }
+}
+
+static void
+gst_dots_tracer_init (GstDotsTracer * self)
+{
+  self->no_delete = FALSE;
+  self->pipeline_snapshot_tracer = NULL;
+
+  setup_output_directory (self);
+
+  // Try to create pipeline-snapshot tracer with exact same configuration as
+  // gstdump.rs
+  try_create_pipeline_snapshot_tracer (self);
+}
+
+static void
+gst_dots_tracer_class_init (GstDotsTracerClass * klass)
+{
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+  gobject_class->set_property = gst_dots_tracer_set_property;
+  gobject_class->get_property = gst_dots_tracer_get_property;
+  gobject_class->finalize = gst_dots_tracer_finalize;
+
+  gst_tracer_class_set_use_structure_params (GST_TRACER_CLASS (gobject_class),
+      TRUE);
+
+  /**
+   * GstDotsTracer:no-delete:
+   *
+   * Don't delete existing .dot files on startup.
+   *
+   * Since: 1.26
+   */
+  properties[PROP_NO_DELETE] =
+      g_param_spec_boolean ("no-delete", "No Delete",
+      "Don't delete existing .dot files on startup", FALSE,
+      G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+  g_object_class_install_properties (gobject_class, N_PROPERTIES, properties);
+
+  GST_DEBUG_CATEGORY_INIT (dots_debug, "dots", 0, "dots tracer");
+}
diff --git a/plugins/tracers/gstlatency.c b/plugins/tracers/gstlatency.c
index 9b0e8a7..f2c3621 100644
--- a/plugins/tracers/gstlatency.c
+++ b/plugins/tracers/gstlatency.c
@@ -59,10 +59,6 @@ static void latency_query_stack_destroy (gpointer data);
 
 static GQuark latency_probe_id;
 static GQuark sub_latency_probe_id;
-static GQuark latency_probe_pad;
-static GQuark latency_probe_element;
-static GQuark latency_probe_element_id;
-static GQuark latency_probe_ts;
 static GQuark drop_sub_latency_quark;
 
 static GstTracerRecord *tr_latency;
@@ -182,16 +178,16 @@ log_latency (const GstStructure * data, GstElement * sink_parent,
   g_return_if_fail (sink_parent);
   g_return_if_fail (sink_pad);
 
-  value = gst_structure_id_get_value (data, latency_probe_ts);
+  value = gst_structure_get_value (data, "latency_probe.ts");
   src_ts = g_value_get_uint64 (value);
 
-  value = gst_structure_id_get_value (data, latency_probe_pad);
+  value = gst_structure_get_value (data, "latency_probe.pad");
   src = g_value_get_string (value);
 
-  value = gst_structure_id_get_value (data, latency_probe_element);
+  value = gst_structure_get_value (data, "latency_probe.element");
   element_src = g_value_get_string (value);
 
-  value = gst_structure_id_get_value (data, latency_probe_element_id);
+  value = gst_structure_get_value (data, "latency_probe.element_id");
   id_element_src = g_value_get_string (value);
 
   id_element_sink = g_strdup_printf ("%p", sink_parent);
@@ -222,7 +218,7 @@ log_element_latency (const GstStructure * data, GstElement * parent,
 
   /* TODO filtering */
 
-  value = gst_structure_id_get_value (data, latency_probe_ts);
+  value = gst_structure_get_value (data, "latency_probe.ts");
   src_ts = g_value_get_uint64 (value);
 
   gst_tracer_record_log (tr_element_latency, element_id, element_name, pad_name,
@@ -253,11 +249,11 @@ send_latency_probe (GstLatencyTracer * self, GstElement * parent, GstPad * pad,
       pad_name = gst_pad_get_name (pad);
 
       latency_probe = gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM,
-          gst_structure_new_id (latency_probe_id,
-              latency_probe_element_id, G_TYPE_STRING, element_id,
-              latency_probe_element, G_TYPE_STRING, element_name,
-              latency_probe_pad, G_TYPE_STRING, pad_name,
-              latency_probe_ts, G_TYPE_UINT64, ts, NULL));
+          gst_structure_new_static_str ("latency_probe.id",
+              "latency_probe.element_id", G_TYPE_STRING, element_id,
+              "latency_probe.element", G_TYPE_STRING, element_name,
+              "latency_probe.pad", G_TYPE_STRING, pad_name,
+              "latency_probe.ts", G_TYPE_UINT64, ts, NULL));
 
       GST_DEBUG ("%s_%s: Sending latency event %p", GST_DEBUG_PAD_NAME (pad),
           latency_probe);
@@ -275,11 +271,11 @@ send_latency_probe (GstLatencyTracer * self, GstElement * parent, GstPad * pad,
       pad_name = gst_pad_get_name (peer_pad);
 
       latency_probe = gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM,
-          gst_structure_new_id (sub_latency_probe_id,
-              latency_probe_element_id, G_TYPE_STRING, element_id,
-              latency_probe_element, G_TYPE_STRING, element_name,
-              latency_probe_pad, G_TYPE_STRING, pad_name,
-              latency_probe_ts, G_TYPE_UINT64, ts, NULL));
+          gst_structure_new_static_str ("sub_latency_probe.id",
+              "latency_probe.element_id", G_TYPE_STRING, element_id,
+              "latency_probe.element", G_TYPE_STRING, element_name,
+              "latency_probe.pad", G_TYPE_STRING, pad_name,
+              "latency_probe.ts", G_TYPE_UINT64, ts, NULL));
 
       GST_DEBUG ("%s_%s: Sending sub-latency event %p",
           GST_DEBUG_PAD_NAME (pad), latency_probe);
@@ -378,7 +374,7 @@ do_drop_sub_latency_event (GstPad * pad, GstPadProbeInfo * info,
   if (GST_EVENT_TYPE (ev) == GST_EVENT_CUSTOM_DOWNSTREAM) {
     const GstStructure *data = gst_event_get_structure (ev);
 
-    if (gst_structure_get_name_id (data) == sub_latency_probe_id) {
+    if (gst_structure_has_name (data, "sub_latency_probe.id")) {
       GstPad *peer_pad = gst_pad_get_peer (pad);
       GstElement *peer_parent = get_real_pad_parent (peer_pad);
       const GValue *value;
@@ -387,9 +383,9 @@ do_drop_sub_latency_event (GstPad * pad, GstPadProbeInfo * info,
       const gchar *value_element_id, *value_pad_name;
 
       /* Get the element id, element name and pad name from data */
-      value = gst_structure_id_get_value (data, latency_probe_element_id);
+      value = gst_structure_get_value (data, "latency_probe.element_id");
       value_element_id = g_value_get_string (value);
-      value = gst_structure_id_get_value (data, latency_probe_pad);
+      value = gst_structure_get_value (data, "latency_probe.pad");
       value_pad_name = g_value_get_string (value);
 
       if (pad_name == NULL ||
@@ -427,8 +423,7 @@ do_push_event_pre (GstTracer * self, guint64 ts, GstPad * pad, GstEvent * ev)
 
     /* if not set yet, add a pad probe that prevents sub-latency event from
      * flowing further */
-    if (gst_structure_get_name_id (data) == latency_probe_id) {
-
+    if (gst_structure_has_name (data, "latency_probe.id")) {
       if (!g_object_get_qdata ((GObject *) pad, drop_sub_latency_quark)) {
         GST_DEBUG ("%s_%s: Adding pad probe to drop sub-latency event",
             GST_DEBUG_PAD_NAME (pad));
@@ -447,16 +442,16 @@ do_push_event_pre (GstTracer * self, guint64 ts, GstPad * pad, GstEvent * ev)
       }
     }
 
-    if (gst_structure_get_name_id (data) == sub_latency_probe_id) {
+    if (gst_structure_has_name (data, "sub_latency_probe.id")) {
       const GValue *value;
       gchar *element_id = g_strdup_printf ("%p", peer_parent);
       gchar *pad_name = peer_pad ? gst_pad_get_name (peer_pad) : NULL;
       const gchar *value_element_id, *value_pad_name;
 
       /* Get the element id, element name and pad name from data */
-      value = gst_structure_id_get_value (data, latency_probe_element_id);
+      value = gst_structure_get_value (data, "latency_probe.element_id");
       value_element_id = g_value_get_string (value);
-      value = gst_structure_id_get_value (data, latency_probe_pad);
+      value = gst_structure_get_value (data, "latency_probe.pad");
       value_pad_name = g_value_get_string (value);
 
       if (!g_str_equal (value_element_id, element_id) ||
@@ -544,55 +539,62 @@ do_query_post (GstLatencyTracer * tracer, GstClockTime ts, GstPad * pad,
 
 /* tracer class */
 
+/* Define the GType for GstLatencyTracerFlags */
+static GType
+gst_latency_tracer_flags_get_type (void)
+{
+  static GType type = 0;
+  static const GFlagsValue values[] = {
+    {GST_LATENCY_TRACER_FLAG_PIPELINE, "Trace pipeline latency", "pipeline"},
+    {GST_LATENCY_TRACER_FLAG_ELEMENT, "Trace per-element latency", "element"},
+    {GST_LATENCY_TRACER_FLAG_REPORTED_ELEMENT, "Trace reported element latency",
+        "reported"},
+    {0, NULL, NULL}
+  };
+
+  if (!type) {
+    type = g_flags_register_static ("GstLatencyTracerFlags", values);
+  }
+  return type;
+}
+
+enum
+{
+  PROP_0,
+  PROP_FLAGS,
+  PROP_LAST
+};
+
 static void
-gst_latency_tracer_constructed (GObject * object)
+gst_latency_tracer_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec)
 {
   GstLatencyTracer *self = GST_LATENCY_TRACER (object);
-  gchar *params, *tmp;
-  GstStructure *params_struct = NULL;
-
-  g_object_get (self, "params", &params, NULL);
-
-  if (!params)
-    return;
-
-  tmp = g_strdup_printf ("latency,%s", params);
-  params_struct = gst_structure_from_string (tmp, NULL);
-  g_free (tmp);
-
-  if (params_struct) {
-    const gchar *name, *flags;
-    /* Set the name if assigned */
-    name = gst_structure_get_string (params_struct, "name");
-    if (name)
-      gst_object_set_name (GST_OBJECT (self), name);
-
-    /* Read the flags if available */
-    flags = gst_structure_get_string (params_struct, "flags");
-
-    self->flags = 0;
-
-    if (flags) {
-      GStrv split = g_strsplit (flags, "+", -1);
-      gint i;
-
-      for (i = 0; split[i]; i++) {
-        if (g_str_equal (split[i], "pipeline"))
-          self->flags |= GST_LATENCY_TRACER_FLAG_PIPELINE;
-        else if (g_str_equal (split[i], "element"))
-          self->flags |= GST_LATENCY_TRACER_FLAG_ELEMENT;
-        else if (g_str_equal (split[i], "reported"))
-          self->flags |= GST_LATENCY_TRACER_FLAG_REPORTED_ELEMENT;
-        else
-          GST_WARNING ("Invalid latency tracer flags %s", split[i]);
-      }
 
-      g_strfreev (split);
-    }
-    gst_structure_free (params_struct);
+  switch (prop_id) {
+    case PROP_FLAGS:
+      g_value_set_flags (value, self->flags);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
   }
+}
 
-  g_free (params);
+static void
+gst_latency_tracer_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec)
+{
+  GstLatencyTracer *self = GST_LATENCY_TRACER (object);
+
+  switch (prop_id) {
+    case PROP_FLAGS:
+      self->flags = g_value_get_flags (value);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
 }
 
 static void
@@ -600,57 +602,62 @@ gst_latency_tracer_class_init (GstLatencyTracerClass * klass)
 {
   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
 
-  gobject_class->constructed = gst_latency_tracer_constructed;
+  gst_tracer_class_set_use_structure_params (GST_TRACER_CLASS (klass), TRUE);
+
+  gobject_class->get_property = gst_latency_tracer_get_property;
+  gobject_class->set_property = gst_latency_tracer_set_property;
+
+  g_object_class_install_property (gobject_class, PROP_FLAGS,
+      g_param_spec_flags ("flags", "Flags",
+          "Flags to control what latency measurements to perform",
+          gst_latency_tracer_flags_get_type (),
+          GST_LATENCY_TRACER_FLAG_PIPELINE,
+          G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
 
   latency_probe_id = g_quark_from_static_string ("latency_probe.id");
   sub_latency_probe_id = g_quark_from_static_string ("sub_latency_probe.id");
-  latency_probe_pad = g_quark_from_static_string ("latency_probe.pad");
-  latency_probe_element = g_quark_from_static_string ("latency_probe.element");
-  latency_probe_element_id =
-      g_quark_from_static_string ("latency_probe.element_id");
-  latency_probe_ts = g_quark_from_static_string ("latency_probe.ts");
   drop_sub_latency_quark =
       g_quark_from_static_string ("drop_sub_latency.quark");
 
   /* announce trace formats */
   /* *INDENT-OFF* */
   tr_latency = gst_tracer_record_new ("latency.class",
-      "src-element-id", GST_TYPE_STRUCTURE, gst_structure_new ("scope",
+      "src-element-id", GST_TYPE_STRUCTURE, gst_structure_new_static_str ("scope",
           "type", G_TYPE_GTYPE, G_TYPE_STRING,
           "related-to", GST_TYPE_TRACER_VALUE_SCOPE,
           GST_TRACER_VALUE_SCOPE_ELEMENT,
           NULL),
-      "src-element", GST_TYPE_STRUCTURE, gst_structure_new ("scope",
+      "src-element", GST_TYPE_STRUCTURE, gst_structure_new_static_str ("scope",
           "type", G_TYPE_GTYPE, G_TYPE_STRING,
           "related-to", GST_TYPE_TRACER_VALUE_SCOPE,
           GST_TRACER_VALUE_SCOPE_ELEMENT,
           NULL),
-      "src", GST_TYPE_STRUCTURE, gst_structure_new ("scope",
+      "src", GST_TYPE_STRUCTURE, gst_structure_new_static_str ("scope",
           "type", G_TYPE_GTYPE, G_TYPE_STRING,
           "related-to", GST_TYPE_TRACER_VALUE_SCOPE, GST_TRACER_VALUE_SCOPE_PAD,
           NULL),
-      "sink-element-id", GST_TYPE_STRUCTURE, gst_structure_new ("scope",
+      "sink-element-id", GST_TYPE_STRUCTURE, gst_structure_new_static_str ("scope",
           "type", G_TYPE_GTYPE, G_TYPE_STRING,
           "related-to", GST_TYPE_TRACER_VALUE_SCOPE,
           GST_TRACER_VALUE_SCOPE_ELEMENT,
           NULL),
-      "sink-element", GST_TYPE_STRUCTURE, gst_structure_new ("scope",
+      "sink-element", GST_TYPE_STRUCTURE, gst_structure_new_static_str ("scope",
           "type", G_TYPE_GTYPE, G_TYPE_STRING,
           "related-to", GST_TYPE_TRACER_VALUE_SCOPE,
           GST_TRACER_VALUE_SCOPE_ELEMENT,
           NULL),
-      "sink", GST_TYPE_STRUCTURE, gst_structure_new ("scope",
+      "sink", GST_TYPE_STRUCTURE, gst_structure_new_static_str ("scope",
           "type", G_TYPE_GTYPE, G_TYPE_STRING,
           "related-to", GST_TYPE_TRACER_VALUE_SCOPE, GST_TRACER_VALUE_SCOPE_PAD,
           NULL),
-      "time", GST_TYPE_STRUCTURE, gst_structure_new ("value",
+      "time", GST_TYPE_STRUCTURE, gst_structure_new_static_str ("value",
           "type", G_TYPE_GTYPE, G_TYPE_UINT64,
           "description", G_TYPE_STRING,
               "time it took for the buffer to go from src to sink ns",
           "min", G_TYPE_UINT64, G_GUINT64_CONSTANT (0),
           "max", G_TYPE_UINT64, G_MAXUINT64,
           NULL),
-      "ts", GST_TYPE_STRUCTURE, gst_structure_new ("value",
+      "ts", GST_TYPE_STRUCTURE, gst_structure_new_static_str ("value",
           "type", G_TYPE_GTYPE, G_TYPE_UINT64,
           "description", G_TYPE_STRING, "ts when the latency has been logged",
           "min", G_TYPE_UINT64, G_GUINT64_CONSTANT (0),
@@ -659,28 +666,28 @@ gst_latency_tracer_class_init (GstLatencyTracerClass * klass)
       NULL);
 
   tr_element_latency = gst_tracer_record_new ("element-latency.class",
-      "element-id", GST_TYPE_STRUCTURE, gst_structure_new ("scope",
+      "element-id", GST_TYPE_STRUCTURE, gst_structure_new_static_str ("scope",
           "type", G_TYPE_GTYPE, G_TYPE_STRING,
           "related-to", GST_TYPE_TRACER_VALUE_SCOPE,
           GST_TRACER_VALUE_SCOPE_ELEMENT,
           NULL),
-      "element", GST_TYPE_STRUCTURE, gst_structure_new ("scope",
+      "element", GST_TYPE_STRUCTURE, gst_structure_new_static_str ("scope",
           "type", G_TYPE_GTYPE, G_TYPE_STRING,
           "related-to", GST_TYPE_TRACER_VALUE_SCOPE,
           GST_TRACER_VALUE_SCOPE_ELEMENT,
           NULL),
-      "src", GST_TYPE_STRUCTURE, gst_structure_new ("scope",
+      "src", GST_TYPE_STRUCTURE, gst_structure_new_static_str ("scope",
           "type", G_TYPE_GTYPE, G_TYPE_STRING,
           "related-to", GST_TYPE_TRACER_VALUE_SCOPE, GST_TRACER_VALUE_SCOPE_PAD,
           NULL),
-      "time", GST_TYPE_STRUCTURE, gst_structure_new ("value",
+      "time", GST_TYPE_STRUCTURE, gst_structure_new_static_str ("value",
           "type", G_TYPE_GTYPE, G_TYPE_UINT64,
           "description", G_TYPE_STRING,
               "time it took for the buffer to go from src to sink ns",
           "min", G_TYPE_UINT64, G_GUINT64_CONSTANT (0),
           "max", G_TYPE_UINT64, G_MAXUINT64,
           NULL),
-      "ts", GST_TYPE_STRUCTURE, gst_structure_new ("value",
+      "ts", GST_TYPE_STRUCTURE, gst_structure_new_static_str ("value",
           "type", G_TYPE_GTYPE, G_TYPE_UINT64,
           "description", G_TYPE_STRING, "ts when the latency has been logged",
           "min", G_TYPE_UINT64, G_GUINT64_CONSTANT (0),
@@ -691,35 +698,35 @@ gst_latency_tracer_class_init (GstLatencyTracerClass * klass)
 
   tr_element_reported_latency = gst_tracer_record_new (
       "element-reported-latency.class",
-      "element-id", GST_TYPE_STRUCTURE, gst_structure_new ("scope",
+      "element-id", GST_TYPE_STRUCTURE, gst_structure_new_static_str ("scope",
           "type", G_TYPE_GTYPE, G_TYPE_STRING,
           "related-to", GST_TYPE_TRACER_VALUE_SCOPE,
           GST_TRACER_VALUE_SCOPE_ELEMENT,
           NULL),
-      "element", GST_TYPE_STRUCTURE, gst_structure_new ("scope",
+      "element", GST_TYPE_STRUCTURE, gst_structure_new_static_str ("scope",
           "type", G_TYPE_GTYPE, G_TYPE_STRING,
           "related-to", GST_TYPE_TRACER_VALUE_SCOPE,
           GST_TRACER_VALUE_SCOPE_ELEMENT,
           NULL),
-      "live", GST_TYPE_STRUCTURE, gst_structure_new ("value",
+      "live", GST_TYPE_STRUCTURE, gst_structure_new_static_str ("value",
           "type", G_TYPE_GTYPE, G_TYPE_BOOLEAN,
           "description", G_TYPE_STRING,
               "wether the it is a live stream or not",
           NULL),
-      "min", GST_TYPE_STRUCTURE, gst_structure_new ("value",
+      "min", GST_TYPE_STRUCTURE, gst_structure_new_static_str ("value",
           "type", G_TYPE_GTYPE, G_TYPE_UINT64,
           "description", G_TYPE_STRING,
               "the minimum reported latency",
           "min", G_TYPE_UINT64, G_GUINT64_CONSTANT (0),
           "max", G_TYPE_UINT64, G_MAXUINT64,
           NULL),
-      "max", GST_TYPE_STRUCTURE, gst_structure_new ("value",
+      "max", GST_TYPE_STRUCTURE, gst_structure_new_static_str ("value",
           "type", G_TYPE_GTYPE, G_TYPE_UINT64,
           "description", G_TYPE_STRING, "the maximum reported latency",
           "min", G_TYPE_UINT64, G_GUINT64_CONSTANT (0),
           "max", G_TYPE_UINT64, G_MAXUINT64,
           NULL),
-      "ts", GST_TYPE_STRUCTURE, gst_structure_new ("value",
+      "ts", GST_TYPE_STRUCTURE, gst_structure_new_static_str ("value",
           "type", G_TYPE_GTYPE, G_TYPE_UINT64,
           "description", G_TYPE_STRING, "ts when the latency has been reported",
           "min", G_TYPE_UINT64, G_GUINT64_CONSTANT (0),
diff --git a/plugins/tracers/gstlatency.h b/plugins/tracers/gstlatency.h
index 9301b1d..e69074e 100644
--- a/plugins/tracers/gstlatency.h
+++ b/plugins/tracers/gstlatency.h
@@ -42,6 +42,11 @@ G_BEGIN_DECLS
 typedef struct _GstLatencyTracer GstLatencyTracer;
 typedef struct _GstLatencyTracerClass GstLatencyTracerClass;
 
+/**
+ * GstLatencyTracerFlags:
+ *
+ * Since: 1.16
+ */
 typedef enum
 {
   GST_LATENCY_TRACER_FLAG_PIPELINE = 1 << 0,
@@ -53,6 +58,8 @@ typedef enum
  * GstLatencyTracer:
  *
  * Opaque #GstLatencyTracer data structure
+ *
+ * Since: 1.8
  */
 struct _GstLatencyTracer {
   GstTracer 	 parent;
diff --git a/plugins/tracers/gstleaks.c b/plugins/tracers/gstleaks.c
index 45e5ca9..3eb5f94 100644
--- a/plugins/tracers/gstleaks.c
+++ b/plugins/tracers/gstleaks.c
@@ -44,15 +44,9 @@
  * `GST_TRACERS=leaks;latency`, and multiple instances of the same tracer can be
  * active at the same time.
  *
- * Parameters can also be passed to each tracer. The leaks tracer currently
- * accepts five params:
- * 1. filters: (string) to filter which objects to record
- * 2. check-refs: (boolean) whether to record every location where a leaked
- *    object was reffed and unreffed
- * 3. stack-traces-flags: (string) full or none; see: #GstStackTraceFlags
- * 4. name: (string) set a name for the tracer object itself
- * 5. log-leaks-on-deinit: (boolean) whether to report all leaks on
- *    gst_deinit() by printing them in the debug log; "true" by default
+ * The tracer properties can also be set to each tracer by passing the object
+ * properties in the list of parameters to the tracer. This uses the same
+ * serialization format as #GstStructure (without a name).
  *
  * Examples:
  * ```
@@ -90,7 +84,40 @@ enum
   LAST_SIGNAL
 };
 
-#define DEFAULT_LOG_LEAKS TRUE  /* for backwards-compat */
+#define DEFAULT_LOG_LEAKS TRUE
+#define DEFAULT_CHECK_REFS FALSE
+
+#define GST_TYPE_LEAKS_STACK_TRACE_FLAGS (gst_leaks_stack_trace_flags_get_type())
+static GType
+gst_leaks_stack_trace_flags_get_type (void)
+{
+  static GType type = 0;
+  static const GFlagsValue values[] = {
+    {GST_LEAKS_STACK_TRACE_DISABLED, "Disabled", "disabled"},
+    {GST_LEAKS_STACK_TRACE_NONE, "None", "none"},
+    {GST_LEAKS_STACK_TRACE_FULL, "Full", "full"},
+    {0, NULL, NULL}
+  };
+
+  if (!type) {
+    type = g_flags_register_static ("GstLeaksStackTraceFlags", values);
+  }
+  return type;
+}
+
+#define DEFAULT_STACK_TRACE_FLAGS GST_LEAKS_STACK_TRACE_DISABLED
+
+enum
+{
+  PROP_0,
+  PROP_FILTERS,
+  PROP_CHECK_REFS,
+  PROP_STACK_TRACES_FLAGS,
+  PROP_LOG_LEAKS_ON_DEINIT,
+  N_PROPERTIES
+};
+
+static GParamSpec *properties[N_PROPERTIES] = { NULL, };
 
 #define _do_init \
     GST_DEBUG_CATEGORY_INIT (gst_leaks_debug, "leaks", 0, "leaks tracer");
@@ -158,39 +185,6 @@ object_refing_infos_free (ObjectRefingInfos * infos)
   g_free (infos);
 }
 
-static void
-set_print_stack_trace_from_string (GstLeaksTracer * self, const gchar * str)
-{
-  gchar *trace;
-
-  /* Test if we can retrieve backtrace */
-  trace = gst_debug_get_stack_trace (FALSE);
-  if (!trace)
-    return;
-
-  g_free (trace);
-
-  if (g_strcmp0 (str, "full") == 0)
-    self->trace_flags = GST_STACK_TRACE_SHOW_FULL;
-  else
-    self->trace_flags = GST_STACK_TRACE_SHOW_NONE;
-}
-
-static void
-set_print_stack_trace (GstLeaksTracer * self, GstStructure * params)
-{
-  const gchar *trace_flags = g_getenv ("GST_LEAKS_TRACER_STACK_TRACE");
-
-  self->trace_flags = -1;
-  if (!trace_flags && params)
-    trace_flags = gst_structure_get_string (params, "stack-traces-flags");
-
-  if (!trace_flags)
-    return;
-
-  set_print_stack_trace_from_string (self, trace_flags);
-}
-
 static void
 set_filters (GstLeaksTracer * self, const gchar * filters)
 {
@@ -226,51 +220,6 @@ set_filters (GstLeaksTracer * self, const gchar * filters)
   g_strfreev (tmp);
 }
 
-static void
-set_params_from_structure (GstLeaksTracer * self, GstStructure * params)
-{
-  const gchar *filters, *name;
-
-  filters = gst_structure_get_string (params, "filters");
-  if (filters)
-    set_filters (self, filters);
-
-  name = gst_structure_get_string (params, "name");
-  if (name)
-    gst_object_set_name (GST_OBJECT (self), name);
-
-  gst_structure_get_boolean (params, "check-refs", &self->check_refs);
-  gst_structure_get_boolean (params, "log-leaks-on-deinit", &self->log_leaks);
-}
-
-static void
-set_params (GstLeaksTracer * self)
-{
-  gchar *params, *tmp;
-  GstStructure *params_struct = NULL;
-
-  g_object_get (self, "params", &params, NULL);
-  if (!params)
-    goto set_stacktrace;
-
-  tmp = g_strdup_printf ("leaks,%s", params);
-  params_struct = gst_structure_from_string (tmp, NULL);
-  g_free (tmp);
-
-  if (params_struct)
-    set_params_from_structure (self, params_struct);
-  else
-    set_filters (self, params);
-
-  g_free (params);
-
-set_stacktrace:
-  set_print_stack_trace (self, params_struct);
-
-  if (params_struct)
-    gst_structure_free (params_struct);
-}
-
 static gboolean
 _expand_unhandled_filters (gchar * typename, gpointer unused_value,
     GstLeaksTracer * self)
@@ -415,8 +364,9 @@ handle_object_created (GstLeaksTracer * self, gpointer object, GType type,
   }
 
   GST_OBJECT_LOCK (self);
-  if ((gint) self->trace_flags != -1)
-    infos->creation_trace = gst_debug_get_stack_trace (self->trace_flags);
+  if ((gint) self->trace_flags != GST_LEAKS_STACK_TRACE_DISABLED)
+    infos->creation_trace =
+        gst_debug_get_stack_trace ((GstStackTraceFlags) self->trace_flags);
 
   g_hash_table_insert (self->objects, object, infos);
 
@@ -470,8 +420,9 @@ handle_object_reffed (GstLeaksTracer * self, gpointer object, GType type,
   refinfo->ts = ts;
   refinfo->new_refcount = new_refcount;
   refinfo->reffed = reffed;
-  if ((gint) self->trace_flags != -1)
-    refinfo->trace = gst_debug_get_stack_trace (self->trace_flags);
+  if ((gint) self->trace_flags != GST_LEAKS_STACK_TRACE_DISABLED)
+    refinfo->trace =
+        gst_debug_get_stack_trace ((GstStackTraceFlags) self->trace_flags);
 
   infos->refing_infos = g_list_prepend (infos->refing_infos, refinfo);
 
@@ -523,6 +474,8 @@ static void
 gst_leaks_tracer_init (GstLeaksTracer * self)
 {
   self->log_leaks = DEFAULT_LOG_LEAKS;
+  self->check_refs = DEFAULT_CHECK_REFS;
+  self->trace_flags = DEFAULT_STACK_TRACE_FLAGS;
   self->objects = g_hash_table_new_full (NULL, NULL, NULL,
       (GDestroyNotify) object_refing_infos_free);
 
@@ -545,8 +498,6 @@ gst_leaks_tracer_constructed (GObject * object)
   GstLeaksTracer *self = GST_LEAKS_TRACER (object);
   GstTracer *tracer = GST_TRACER (object);
 
-  set_params (self);
-
   gst_tracing_register_hook (tracer, "mini-object-created",
       G_CALLBACK (mini_object_created_cb));
   gst_tracing_register_hook (tracer, "object-created",
@@ -1021,6 +972,7 @@ gst_leaks_tracer_get_live_objects (GstLeaksTracer * self)
 
   g_value_init (&live_objects, GST_TYPE_LIST);
 
+  GST_TRACE_OBJECT (self, "start listing currently alive objects");
   GST_OBJECT_LOCK (self);
   process_leaks (self, &live_objects);
   GST_OBJECT_UNLOCK (self);
@@ -1138,13 +1090,150 @@ gst_leaks_tracer_activity_stop_tracking (GstLeaksTracer * self)
   GST_OBJECT_UNLOCK (self);
 }
 
+static void
+gst_leaks_tracer_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec)
+{
+  GstLeaksTracer *self = GST_LEAKS_TRACER (object);
+
+  GST_OBJECT_LOCK (self);
+  switch (prop_id) {
+    case PROP_CHECK_REFS:
+      g_value_set_boolean (value, self->check_refs);
+      break;
+    case PROP_STACK_TRACES_FLAGS:
+      g_value_set_flags (value, self->trace_flags);
+      break;
+    case PROP_LOG_LEAKS_ON_DEINIT:
+      g_value_set_boolean (value, self->log_leaks);
+      break;
+    case PROP_FILTERS:
+    {
+      GString *str = g_string_new ("");
+      if (self->filter) {
+        guint i;
+        for (i = 0; i < self->filter->len; i++) {
+          GType type = g_array_index (self->filter, GType, i);
+          if (i > 0)
+            g_string_append_c (str, ',');
+          g_string_append (str, g_type_name (type));
+        }
+      }
+      g_value_take_string (value, g_string_free (str, FALSE));
+      break;
+    }
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+  GST_OBJECT_UNLOCK (self);
+}
+
+static void
+gst_leaks_tracer_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec)
+{
+  GstLeaksTracer *self = GST_LEAKS_TRACER (object);
+
+  GST_OBJECT_LOCK (self);
+  switch (prop_id) {
+    case PROP_CHECK_REFS:
+      self->check_refs = g_value_get_boolean (value);
+      break;
+    case PROP_STACK_TRACES_FLAGS:
+      self->trace_flags = g_value_get_flags (value);
+      break;
+    case PROP_LOG_LEAKS_ON_DEINIT:
+      self->log_leaks = g_value_get_boolean (value);
+      break;
+    case PROP_FILTERS:
+      if (self->filter) {
+        g_array_free (self->filter, TRUE);
+        self->filter = NULL;
+      }
+      const gchar *filters = g_value_get_string (value);
+      if (filters) {
+        set_filters (self, g_value_get_string (value));
+      }
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+  GST_OBJECT_UNLOCK (self);
+}
+
 static void
 gst_leaks_tracer_class_init (GstLeaksTracerClass * klass)
 {
   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
 
+  gst_tracer_class_set_use_structure_params (GST_TRACER_CLASS (klass), TRUE);
+
   gobject_class->constructed = gst_leaks_tracer_constructed;
   gobject_class->finalize = gst_leaks_tracer_finalize;
+  gobject_class->get_property = gst_leaks_tracer_get_property;
+  gobject_class->set_property = gst_leaks_tracer_set_property;
+
+  /**
+   * GstLeaksTracer:filters:
+   *
+   * Comma-separated list of GObject types to track. Only objects of these types
+   * or their subtypes will be monitored for leaks.
+   *
+   * Example: "GstEvent,GstMessage" to only track GstEvent and GstMessage objects.
+   *
+   * Since: 1.26
+   */
+  properties[PROP_FILTERS] = g_param_spec_string ("filters",
+      "Type Filters",
+      "Comma-separated list of GObject types to track", NULL,
+      G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY);
+
+  /**
+   * GstLeaksTracer:check-refs:
+   *
+   * Whether to record every location where a leaked object was reffed and unreffed.
+   * When enabled, the tracer will collect stack traces for every ref/unref operation
+   * on tracked objects.
+   *
+   * Since: 1.26
+   */
+  properties[PROP_CHECK_REFS] = g_param_spec_boolean ("check-refs",
+      "Check References",
+      "Whether to track ref/unref operations", DEFAULT_CHECK_REFS,
+      G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY);
+
+  /**
+   * GstLeaksTracer:stack-traces-flags:
+   *
+   * Stack trace collection mode. Controls whether and how stack traces are collected
+   * for object allocations and ref/unref operations.
+   *
+   * Since: 1.26
+   */
+  properties[PROP_STACK_TRACES_FLAGS] =
+      g_param_spec_flags ("stack-traces-flags", "Stack Trace Flags",
+      "Stack trace collection mode", GST_TYPE_LEAKS_STACK_TRACE_FLAGS,
+      DEFAULT_STACK_TRACE_FLAGS,
+      G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY);
+
+  /**
+   * GstLeaksTracer:log-leaks-on-deinit:
+   *
+   * Whether to report all leaks on gst_deinit() by printing them in the debug log.
+   * When enabled, any detected leaks will be logged under GST_TRACER:7 when the
+   * GStreamer is being shut down.
+   *
+   * Since: 1.26
+   */
+  properties[PROP_LOG_LEAKS_ON_DEINIT] =
+      g_param_spec_boolean ("log-leaks-on-deinit", "Log Leaks",
+      "Whether to log leaks on shutdown", DEFAULT_LOG_LEAKS,
+      G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY);
+
+
+  g_object_class_install_properties (gobject_class, N_PROPERTIES, properties);
 
   tr_alive = gst_tracer_record_new ("object-alive.class",
       RECORD_FIELD_TYPE_NAME, RECORD_FIELD_ADDRESS, RECORD_FIELD_DESC,
@@ -1233,7 +1322,7 @@ gst_leaks_tracer_class_init (GstLeaksTracerClass * klass)
           log_live_objects), NULL, NULL, NULL, G_TYPE_NONE, 0, G_TYPE_NONE);
 
   /**
-   * GstLeaksTracer:::activity-start-tracking
+   * GstLeaksTracer::activity-start-tracking:
    * @leakstracer: the leaks tracer object to emit this signal on
    *
    * Start storing information about all objects that are being created or
@@ -1251,7 +1340,7 @@ gst_leaks_tracer_class_init (GstLeaksTracerClass * klass)
       G_TYPE_NONE);
 
   /**
-   * GstLeaksTracer:::activity-get-checkpoint
+   * GstLeaksTracer::activity-get-checkpoint:
    * @leakstracer: the leaks tracer object to emit this signal on
    *
    * You must call this after calling `activity-start-tracking` and you should
@@ -1281,7 +1370,7 @@ gst_leaks_tracer_class_init (GstLeaksTracerClass * klass)
       G_TYPE_NONE);
 
   /**
-   * GstLeaksTracer:::activity-log-checkpoint
+   * GstLeaksTracer::activity-log-checkpoint:
    * @leakstracer: the leaks tracer object to emit this signal on
    *
    * You must call this after calling `activity-start-tracking` and you should
@@ -1302,7 +1391,7 @@ gst_leaks_tracer_class_init (GstLeaksTracerClass * klass)
       G_TYPE_NONE);
 
   /**
-   * GstLeaksTracer:::activity-stop-tracking
+   * GstLeaksTracer::activity-stop-tracking:
    * @leakstracer: the leaks tracer object to emit this signal on
    *
    * Stop tracking all objects that are being created or removed, undoes the
diff --git a/plugins/tracers/gstleaks.h b/plugins/tracers/gstleaks.h
index 6eaf850..8d81ecb 100644
--- a/plugins/tracers/gstleaks.h
+++ b/plugins/tracers/gstleaks.h
@@ -42,6 +42,20 @@ G_BEGIN_DECLS
 typedef struct _GstLeaksTracer GstLeaksTracer;
 typedef struct _GstLeaksTracerClass GstLeaksTracerClass;
 
+/**
+ * GstLeaksStackTraceFlags:
+ * @GST_LEAKS_STACK_TRACE_DISABLED: no stack trace
+ * @GST_LEAKS_STACK_TRACE_NONE: minimal stack trace
+ * @GST_LEAKS_STACK_TRACE_FULL: full stack trace
+ *
+ * Since: 1.26
+ */
+typedef enum {
+  GST_LEAKS_STACK_TRACE_DISABLED = -1,
+  GST_LEAKS_STACK_TRACE_NONE = GST_STACK_TRACE_SHOW_NONE,
+  GST_LEAKS_STACK_TRACE_FULL = GST_STACK_TRACE_SHOW_FULL
+} GstLeaksStackTraceFlags;
+
 /**
  * GstLeaksTracer:
  *
@@ -71,7 +85,7 @@ struct _GstLeaksTracer {
   gboolean check_refs;
   gboolean log_leaks;
 
-  GstStackTraceFlags trace_flags;
+  GstLeaksStackTraceFlags trace_flags;
 };
 
 struct _GstLeaksTracerClass {
diff --git a/plugins/tracers/gstlog.c b/plugins/tracers/gstlog.c
index bd89ea8..48a2d1a 100644
--- a/plugins/tracers/gstlog.c
+++ b/plugins/tracers/gstlog.c
@@ -51,12 +51,15 @@
  *
  *  * `GST_DEBUG=GST_BUFFER:TRACE`
  *    * `pad-push-pre`, `pad-push-post`
+ *    * `pad-chain-pre`, `pad-chain-post`
  *    * `pad-pull-range-pre`, `pad-pull-range-post`
  *  * `GST_DEBUG=GST_BUFFER_LIST:TRACE`
  *    * `pad-push-list-pre`, `pad-push-list-post`
+ *    * `pad-chain-list-pre`, `pad-chain-list-post`
  *  * `GST_DEBUG=GST_EVENT:TRACE`
  *    * `pad-push-event-pre`, `pad-push-event-post`
- *  * `GST_DEBUG=GST_QUERY:TRACE`
+ *    * `pad-send-event-pre`, `pad-send-event-post`
+ *  * `GST_DEBUG=query:TRACE`
  *    * `pad-query-pre`, `pad-query-post`
  *    * `element-query-pre`, `element-query-post`
  *  * `GST_DEBUG=GST_MESSAGE:TRACE`
@@ -68,7 +71,7 @@
  *    * `element-remove-pad`
  *  * `GST_DEBUG=GST_STATES:TRACE`
  *    * `element-change-state-pre`, `element-change-state-post`
- *  * `GST_DEBUG=GST_BIN:TRACE`
+ *  * `GST_DEBUG=bin:TRACE`
  *    * `bin-add-pre`, `bin-add-post`
  *    * `bin-remove-pre`, `bin-remove-post`
  *  * `GST_DEBUG=GST_PADS:TRACE`
@@ -141,6 +144,8 @@ GST_DEBUG_CATEGORY_STATIC (GST_CAT_ELEMENT_FACTORY);
 G_DEFINE_TYPE_WITH_CODE (GstLogTracer, gst_log_tracer, GST_TYPE_TRACER,
     _do_init);
 
+#define bool_to_str(val) (val ? "true" : "false")
+
 static void
 do_log (GstDebugCategory * cat, const char *func, GObject * obj,
     const char *fmt, ...)
@@ -166,8 +171,8 @@ do_push_buffer_post (GstTracer * self, guint64 ts, GstPad * pad,
     GstFlowReturn res)
 {
   do_log (GST_CAT_BUFFER, GST_FUNCTION, (GObject *) pad,
-      "%" GST_TIME_FORMAT ", pad=%" GST_PTR_FORMAT ", res=%d",
-      GST_TIME_ARGS (ts), pad, res);
+      "%" GST_TIME_FORMAT ", pad=%" GST_PTR_FORMAT ", res=%s",
+      GST_TIME_ARGS (ts), pad, gst_flow_get_name (res));
 }
 
 static void
@@ -175,7 +180,7 @@ do_push_buffer_list_pre (GstTracer * self, guint64 ts, GstPad * pad,
     GstBufferList * list)
 {
   do_log (GST_CAT_BUFFER_LIST, GST_FUNCTION, (GObject *) pad,
-      "%" GST_TIME_FORMAT ", pad=%" GST_PTR_FORMAT ", list=%p",
+      "%" GST_TIME_FORMAT ", pad=%" GST_PTR_FORMAT ", list=%" GST_PTR_FORMAT,
       GST_TIME_ARGS (ts), pad, list);
 }
 
@@ -184,8 +189,44 @@ do_push_buffer_list_post (GstTracer * self, guint64 ts, GstPad * pad,
     GstFlowReturn res)
 {
   do_log (GST_CAT_BUFFER_LIST, GST_FUNCTION, (GObject *) pad,
-      "%" GST_TIME_FORMAT ", pad=%" GST_PTR_FORMAT ", res=%d",
-      GST_TIME_ARGS (ts), pad, res);
+      "%" GST_TIME_FORMAT ", pad=%" GST_PTR_FORMAT ", res=%s",
+      GST_TIME_ARGS (ts), pad, gst_flow_get_name (res));
+}
+
+static void
+do_chain_buffer_pre (GstTracer * self, guint64 ts, GstPad * pad,
+    GstBuffer * buffer)
+{
+  do_log (GST_CAT_BUFFER, GST_FUNCTION, (GObject *) pad,
+      "%" GST_TIME_FORMAT ", pad=%" GST_PTR_FORMAT ", buffer=%" GST_PTR_FORMAT,
+      GST_TIME_ARGS (ts), pad, buffer);
+}
+
+static void
+do_chain_buffer_post (GstTracer * self, guint64 ts, GstPad * pad,
+    GstFlowReturn res)
+{
+  do_log (GST_CAT_BUFFER, GST_FUNCTION, (GObject *) pad,
+      "%" GST_TIME_FORMAT ", pad=%" GST_PTR_FORMAT ", res=%s",
+      GST_TIME_ARGS (ts), pad, gst_flow_get_name (res));
+}
+
+static void
+do_chain_buffer_list_pre (GstTracer * self, guint64 ts, GstPad * pad,
+    GstBufferList * list)
+{
+  do_log (GST_CAT_BUFFER_LIST, GST_FUNCTION, (GObject *) pad,
+      "%" GST_TIME_FORMAT ", pad=%" GST_PTR_FORMAT ", list=%" GST_PTR_FORMAT,
+      GST_TIME_ARGS (ts), pad, list);
+}
+
+static void
+do_chain_buffer_list_post (GstTracer * self, guint64 ts, GstPad * pad,
+    GstFlowReturn res)
+{
+  do_log (GST_CAT_BUFFER_LIST, GST_FUNCTION, (GObject *) pad,
+      "%" GST_TIME_FORMAT ", pad=%" GST_PTR_FORMAT ", res=%s",
+      GST_TIME_ARGS (ts), pad, gst_flow_get_name (res));
 }
 
 static void
@@ -203,7 +244,7 @@ do_pull_range_post (GstTracer * self, guint64 ts, GstPad * pad,
 {
   do_log (GST_CAT_BUFFER, GST_FUNCTION, (GObject *) pad,
       "%" GST_TIME_FORMAT ", pad=%" GST_PTR_FORMAT ", buffer=%" GST_PTR_FORMAT
-      ", res=%d", GST_TIME_ARGS (ts), pad, buffer, res);
+      ", res=%s", GST_TIME_ARGS (ts), pad, buffer, gst_flow_get_name (res));
 }
 
 static void
@@ -218,8 +259,25 @@ static void
 do_push_event_post (GstTracer * self, guint64 ts, GstPad * pad, gboolean res)
 {
   do_log (GST_CAT_EVENT, GST_FUNCTION, (GObject *) pad,
-      "%" GST_TIME_FORMAT ", pad=%" GST_PTR_FORMAT ", res=%d",
-      GST_TIME_ARGS (ts), pad, res);
+      "%" GST_TIME_FORMAT ", pad=%" GST_PTR_FORMAT ", res=%s",
+      GST_TIME_ARGS (ts), pad, bool_to_str (res));
+}
+
+static void
+do_send_event_pre (GstTracer * self, guint64 ts, GstPad * pad, GstEvent * event)
+{
+  do_log (GST_CAT_EVENT, GST_FUNCTION, (GObject *) pad,
+      "%" GST_TIME_FORMAT ", pad=%" GST_PTR_FORMAT ", event=%" GST_PTR_FORMAT,
+      GST_TIME_ARGS (ts), pad, event);
+}
+
+static void
+do_send_event_post (GstTracer * self, guint64 ts, GstPad * pad,
+    GstFlowReturn res)
+{
+  do_log (GST_CAT_EVENT, GST_FUNCTION, (GObject *) pad,
+      "%" GST_TIME_FORMAT ", pad=%" GST_PTR_FORMAT ", res=%s",
+      GST_TIME_ARGS (ts), pad, gst_flow_get_name (res));
 }
 
 static void
@@ -236,7 +294,7 @@ do_pad_query_post (GstTracer * self, guint64 ts, GstPad * pad, GstQuery * query,
 {
   do_log (GST_CAT_QUERY, GST_FUNCTION, (GObject *) pad,
       "%" GST_TIME_FORMAT ", pad=%" GST_PTR_FORMAT ", query=%" GST_PTR_FORMAT
-      ", res=%d", GST_TIME_ARGS (ts), pad, query, res);
+      ", res=%s", GST_TIME_ARGS (ts), pad, query, bool_to_str (res));
 }
 
 static void
@@ -253,8 +311,8 @@ do_post_message_post (GstTracer * self, guint64 ts, GstElement * elem,
     gboolean res)
 {
   do_log (GST_CAT_MESSAGE, GST_FUNCTION, (GObject *) elem,
-      "%" GST_TIME_FORMAT ", element=%" GST_PTR_FORMAT ", res=%d",
-      GST_TIME_ARGS (ts), elem, res);
+      "%" GST_TIME_FORMAT ", element=%" GST_PTR_FORMAT ", res=%s",
+      GST_TIME_ARGS (ts), elem, bool_to_str (res));
 }
 
 static void
@@ -272,7 +330,8 @@ do_element_query_post (GstTracer * self, guint64 ts, GstElement * elem,
 {
   do_log (GST_CAT_QUERY, GST_FUNCTION, (GObject *) elem,
       "%" GST_TIME_FORMAT ", element=%" GST_PTR_FORMAT ", query=%"
-      GST_PTR_FORMAT ", res=%d", GST_TIME_ARGS (ts), elem, query, res);
+      GST_PTR_FORMAT ", res=%s", GST_TIME_ARGS (ts), elem, query,
+      bool_to_str (res));
 }
 
 static void
@@ -306,8 +365,8 @@ do_element_change_state_pre (GstTracer * self, guint64 ts, GstElement * elem,
     GstStateChange change)
 {
   do_log (GST_CAT_STATES, GST_FUNCTION, (GObject *) elem,
-      "%" GST_TIME_FORMAT ", element=%" GST_PTR_FORMAT ", change=%d",
-      GST_TIME_ARGS (ts), elem, (gint) change);
+      "%" GST_TIME_FORMAT ", element=%" GST_PTR_FORMAT ", change=%s",
+      GST_TIME_ARGS (ts), elem, gst_state_change_get_name (change));
 }
 
 static void
@@ -315,8 +374,9 @@ do_element_change_state_post (GstTracer * self, guint64 ts, GstElement * elem,
     GstStateChange change, GstStateChangeReturn res)
 {
   do_log (GST_CAT_STATES, GST_FUNCTION, (GObject *) elem,
-      "%" GST_TIME_FORMAT ", element=%" GST_PTR_FORMAT ", change=%d, res=%d",
-      GST_TIME_ARGS (ts), elem, (gint) change, (gint) res);
+      "%" GST_TIME_FORMAT ", element=%" GST_PTR_FORMAT ", change=%s, res=%s",
+      GST_TIME_ARGS (ts), elem, gst_state_change_get_name (change),
+      gst_element_state_change_return_get_name (res));
 }
 
 static void
@@ -333,7 +393,7 @@ do_bin_add_post (GstTracer * self, guint64 ts, GstBin * bin, GstElement * elem,
 {
   do_log (GST_CAT_BIN, GST_FUNCTION, (GObject *) bin,
       "%" GST_TIME_FORMAT ", bin=%" GST_PTR_FORMAT ", element=%" GST_PTR_FORMAT
-      ", res=%d", GST_TIME_ARGS (ts), bin, elem, res);
+      ", res=%s", GST_TIME_ARGS (ts), bin, elem, bool_to_str (res));
 }
 
 static void
@@ -349,8 +409,8 @@ static void
 do_bin_remove_post (GstTracer * self, guint64 ts, GstBin * bin, gboolean res)
 {
   do_log (GST_CAT_BIN, GST_FUNCTION, (GObject *) bin,
-      "%" GST_TIME_FORMAT ", bin=%" GST_PTR_FORMAT ", res=%d",
-      GST_TIME_ARGS (ts), bin, res);
+      "%" GST_TIME_FORMAT ", bin=%" GST_PTR_FORMAT ", res=%s",
+      GST_TIME_ARGS (ts), bin, bool_to_str (res));
 }
 
 static void
@@ -367,7 +427,7 @@ do_pad_link_post (GstTracer * self, guint64 ts, GstPad * src, GstPad * sink,
 {
   do_log (GST_CAT_PADS, GST_FUNCTION, (GObject *) src,
       "%" GST_TIME_FORMAT ", src=%" GST_PTR_FORMAT ", sink=%" GST_PTR_FORMAT
-      ", res=%d", GST_TIME_ARGS (ts), src, sink, (gint) res);
+      ", res=%s", GST_TIME_ARGS (ts), src, sink, gst_pad_link_get_name (res));
 }
 
 static void
@@ -385,7 +445,7 @@ do_pad_unlink_post (GstTracer * self, guint64 ts, GstPad * src,
 {
   do_log (GST_CAT_PADS, GST_FUNCTION, (GObject *) src,
       "%" GST_TIME_FORMAT ", src=%" GST_PTR_FORMAT ", sink=%" GST_PTR_FORMAT
-      ", res=%d", GST_TIME_ARGS (ts), src, sink, (gint) res);
+      ", res=%s", GST_TIME_ARGS (ts), src, sink, bool_to_str (res));
 }
 
 /* tracer class */
@@ -398,6 +458,8 @@ gst_log_tracer_constructed (GObject * object)
   const gchar *name;
   GstStructure *params_struct = NULL;
 
+  G_OBJECT_CLASS (parent_class)->constructed (object);
+
   g_object_get (self, "params", &params, NULL);
 
   if (!params)
@@ -437,6 +499,14 @@ gst_log_tracer_init (GstLogTracer * self)
       G_CALLBACK (do_push_buffer_list_pre));
   gst_tracing_register_hook (tracer, "pad-push-list-post",
       G_CALLBACK (do_push_buffer_list_post));
+  gst_tracing_register_hook (tracer, "pad-chain-pre",
+      G_CALLBACK (do_chain_buffer_pre));
+  gst_tracing_register_hook (tracer, "pad-chain-post",
+      G_CALLBACK (do_chain_buffer_post));
+  gst_tracing_register_hook (tracer, "pad-chain-list-pre",
+      G_CALLBACK (do_chain_buffer_list_pre));
+  gst_tracing_register_hook (tracer, "pad-chain-list-post",
+      G_CALLBACK (do_chain_buffer_list_post));
   gst_tracing_register_hook (tracer, "pad-pull-range-pre",
       G_CALLBACK (do_pull_range_pre));
   gst_tracing_register_hook (tracer, "pad-pull-range-post",
@@ -445,6 +515,10 @@ gst_log_tracer_init (GstLogTracer * self)
       G_CALLBACK (do_push_event_pre));
   gst_tracing_register_hook (tracer, "pad-push-event-post",
       G_CALLBACK (do_push_event_post));
+  gst_tracing_register_hook (tracer, "pad-send-event-pre",
+      G_CALLBACK (do_send_event_pre));
+  gst_tracing_register_hook (tracer, "pad-send-event-post",
+      G_CALLBACK (do_send_event_post));
   gst_tracing_register_hook (tracer, "pad-query-pre",
       G_CALLBACK (do_pad_query_pre));
   gst_tracing_register_hook (tracer, "pad-query-post",
diff --git a/plugins/tracers/gstrusage.c b/plugins/tracers/gstrusage.c
index c49e902..3241f5d 100644
--- a/plugins/tracers/gstrusage.c
+++ b/plugins/tracers/gstrusage.c
@@ -261,33 +261,6 @@ do_stats (GstTracer * obj, guint64 ts)
 
 /* tracer class */
 
-static void
-gst_rusage_tracer_constructed (GObject * object)
-{
-  GstRUsageTracer *self = GST_RUSAGE_TRACER (object);
-  gchar *params, *tmp;
-  const gchar *name;
-  GstStructure *params_struct = NULL;
-
-  g_object_get (self, "params", &params, NULL);
-
-  if (!params)
-    return;
-
-  tmp = g_strdup_printf ("rusage,%s", params);
-  g_free (params);
-  params_struct = gst_structure_from_string (tmp, NULL);
-  g_free (tmp);
-  if (!params_struct)
-    return;
-
-  /* Set the name if assigned */
-  name = gst_structure_get_string (params_struct, "name");
-  if (name)
-    gst_object_set_name (GST_OBJECT (self), name);
-  gst_structure_free (params_struct);
-}
-
 static void
 gst_rusage_tracer_finalize (GObject * obj)
 {
@@ -303,7 +276,8 @@ gst_rusage_tracer_class_init (GstRUsageTracerClass * klass)
 {
   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
 
-  gobject_class->constructed = gst_rusage_tracer_constructed;
+  gst_tracer_class_set_use_structure_params (GST_TRACER_CLASS (klass), TRUE);
+
   gobject_class->finalize = gst_rusage_tracer_finalize;
 
   if ((num_cpus = sysconf (_SC_NPROCESSORS_ONLN)) == -1) {
diff --git a/plugins/tracers/gststats.c b/plugins/tracers/gststats.c
index d2a84c2..ba3157f 100644
--- a/plugins/tracers/gststats.c
+++ b/plugins/tracers/gststats.c
@@ -25,6 +25,12 @@
  * A tracing module that builds usage statistic for elements and pads.
  */
 
+/**
+ * GstStatsTracer:
+ *
+ * Since: 1.8
+ */
+
 #ifdef HAVE_CONFIG_H
 #  include "config.h"
 #endif
@@ -528,6 +534,8 @@ gst_stats_tracer_constructed (GObject * object)
   const gchar *name;
   GstStructure *params_struct = NULL;
 
+  G_OBJECT_CLASS (parent_class)->constructed (object);
+
   g_object_get (self, "params", &params, NULL);
 
   if (!params)
diff --git a/plugins/tracers/gsttracers.c b/plugins/tracers/gsttracers.c
index e5fe5d0..62fead0 100644
--- a/plugins/tracers/gsttracers.c
+++ b/plugins/tracers/gsttracers.c
@@ -31,9 +31,14 @@
 #include "gstleaks.h"
 #include "gstfactories.h"
 
+GType gst_dots_tracer_get_type (void);
+
 static gboolean
 plugin_init (GstPlugin * plugin)
 {
+  if (!gst_tracer_register (plugin, "dots", gst_dots_tracer_get_type ()))
+    return FALSE;
+
   if (!gst_tracer_register (plugin, "latency", gst_latency_tracer_get_type ()))
     return FALSE;
 #ifndef GST_DISABLE_GST_DEBUG
diff --git a/plugins/tracers/meson.build b/plugins/tracers/meson.build
index b01d566..fb8e945 100644
--- a/plugins/tracers/meson.build
+++ b/plugins/tracers/meson.build
@@ -1,11 +1,5 @@
-if not tracer_hooks
-  if get_option('coretracers').enabled()
-    error('coretracers plugin enabled but not tracer_hooks')
-  endif
-  subdir_done()
-endif
-
 gst_tracers_sources = [
+  'gstdots.c',
   'gstlatency.c',
   'gstleaks.c',
   'gststats.c',
@@ -13,12 +7,49 @@ gst_tracers_sources = [
   'gstfactories.c'
 ]
 
+debug_sources = [
+  'gstlog.c',
+]
+
+getrusage_sources = [
+  'gstrusage.c',
+]
+
+gst_tracers_headers = [
+  'gstfactories.h',
+  'gstlatency.h',
+  'gstleaks.h',
+  'gstlog.h',
+  'gstrusage.h',
+  'gststats.h',
+]
+
+doc_sources = []
+foreach s: gst_tracers_sources + debug_sources + getrusage_sources + gst_tracers_headers
+  doc_sources += meson.current_source_dir() / s
+endforeach
+
+plugin_sources += {
+  'coretracers': pathsep.join(doc_sources)
+}
+
+if get_option('coretracers').disabled()
+  subdir_done()
+endif
+
+if not tracer_hooks
+  if get_option('coretracers').enabled()
+    error('coretracers plugin enabled but not tracer_hooks')
+  endif
+  subdir_done()
+endif
+
 if gst_debug
-  gst_tracers_sources += ['gstlog.c']
+  gst_tracers_sources += debug_sources
 endif
 
 if cdata.has('HAVE_GETRUSAGE')
-  gst_tracers_sources += ['gstrusage.c']
+  gst_tracers_sources += getrusage_sources
 endif
 
 thread_dep = dependency('threads', required : false)
diff --git a/po/be.po b/po/be.po
index 5d78fdb..d172ece 100644
--- a/po/be.po
+++ b/po/be.po
@@ -6,7 +6,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: gstreamer 0.9.7\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2024-11-03 17:36+0000\n"
+"POT-Creation-Date: 2025-02-23 16:55+0000\n"
 "PO-Revision-Date: 2006-01-18 22:26+0200\n"
 "Last-Translator: Ales Nyakhaychyk <nab@mail.by>\n"
 "Language-Team: Belarusian <i18n@mova.org>\n"
@@ -40,8 +40,8 @@ msgid ""
 "the individual categories. Example: GST_AUTOPLUG:5,GST_ELEMENT_*:3"
 msgstr ""
 "Разьмежаваны коскамі сьпіс пар categor_name:level для выстаўленьня "
-"адмысловых узроўняў для асобных катэгорыяў. Напрыклад, GST_AUTOPLUG:5,"
-"GST_ELEMENT_*:3"
+"адмысловых узроўняў для асобных катэгорыяў. Напрыклад, "
+"GST_AUTOPLUG:5,GST_ELEMENT_*:3"
 
 msgid "LIST"
 msgstr "СЬПІС"
diff --git a/po/cs.po b/po/cs.po
index e1250b1..d285da5 100644
--- a/po/cs.po
+++ b/po/cs.po
@@ -9,7 +9,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: gstreamer 1.12.0\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2024-11-03 17:36+0000\n"
+"POT-Creation-Date: 2025-02-23 16:55+0000\n"
 "PO-Revision-Date: 2017-09-13 15:04+0200\n"
 "Last-Translator: Marek Černocký <marek@manet.cz>\n"
 "Language-Team: Czech <translation-team-cs@lists.sourceforge.net>\n"
@@ -43,8 +43,8 @@ msgid ""
 "the individual categories. Example: GST_AUTOPLUG:5,GST_ELEMENT_*:3"
 msgstr ""
 "Čárkami oddělovaný seznam dvojic název_kategorie:úroveň pro nastavení "
-"konkrétních úrovní pro jednotlivé kategorie. Příklad: GST_AUTOPLUG:5,"
-"GST_ELEMENT_*:3"
+"konkrétních úrovní pro jednotlivé kategorie. Příklad: "
+"GST_AUTOPLUG:5,GST_ELEMENT_*:3"
 
 msgid "LIST"
 msgstr "SEZNAM"
diff --git a/po/da.po b/po/da.po
index 4eb33c4..71244be 100644
--- a/po/da.po
+++ b/po/da.po
@@ -10,7 +10,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: gstreamer 1.15.1\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2024-11-03 17:36+0000\n"
+"POT-Creation-Date: 2025-02-23 16:55+0000\n"
 "PO-Revision-Date: 2019-02-14 13:26+0200\n"
 "Last-Translator: Joe Hansen <joedalton2@yahoo.dk>\n"
 "Language-Team: Danish <dansk@dansk-gruppen.dk>\n"
@@ -45,8 +45,8 @@ msgid ""
 "the individual categories. Example: GST_AUTOPLUG:5,GST_ELEMENT_*:3"
 msgstr ""
 "Kommasepareret liste med kategori_navn:niveaupar til at indstille specifikke "
-"niveauer for de individuelle kategorier. Eksempel: GST_AUTOPLUG:5,"
-"GST_ELEMENT_*:3"
+"niveauer for de individuelle kategorier. Eksempel: "
+"GST_AUTOPLUG:5,GST_ELEMENT_*:3"
 
 msgid "LIST"
 msgstr "LISTE"
diff --git a/po/de.po b/po/de.po
index 284c225..fded22d 100644
--- a/po/de.po
+++ b/po/de.po
@@ -9,7 +9,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: gstreamer 1.24.0\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2024-11-03 17:36+0000\n"
+"POT-Creation-Date: 2025-02-23 16:55+0000\n"
 "PO-Revision-Date: 2024-03-16 23:40+0100\n"
 "Last-Translator: Christian Kirbach <christian.kirbach@gmail.com>\n"
 "Language-Team: German <translation-team-de@lists.sourceforge.net>\n"
@@ -45,8 +45,8 @@ msgid ""
 "the individual categories. Example: GST_AUTOPLUG:5,GST_ELEMENT_*:3"
 msgstr ""
 "Durch Kommata getrennte Liste von Paaren »Kategorie_Name:Level«, um "
-"bestimmten Kategorien eigene Stufen  zuzuordnen. Beispiel: GST_AUTOPLUG:5,"
-"GST_ELEMENT_*:3"
+"bestimmten Kategorien eigene Stufen  zuzuordnen. Beispiel: "
+"GST_AUTOPLUG:5,GST_ELEMENT_*:3"
 
 msgid "LIST"
 msgstr "LISTE"
diff --git a/po/eo.po b/po/eo.po
index 9bc35d7..024dfad 100644
--- a/po/eo.po
+++ b/po/eo.po
@@ -8,7 +8,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: gstreamer 1.19.2\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2024-11-03 17:36+0000\n"
+"POT-Creation-Date: 2025-02-23 16:55+0000\n"
 "PO-Revision-Date: 2023-01-08 11:53-0300\n"
 "Last-Translator: Felipe Castro <fefcas@gmail.com>\n"
 "Language-Team: Esperanto <translation-team-eo@lists.sourceforge.net>\n"
@@ -42,8 +42,8 @@ msgid ""
 "the individual categories. Example: GST_AUTOPLUG:5,GST_ELEMENT_*:3"
 msgstr ""
 "Komo-apartita listo de paroj kategori_nomo:nivelo por difini specifajn "
-"nivelojn por la individuaj kategorioj. Ekzemplo: GST_AUTOPLUG:5,"
-"GST_ELEMENT_*:3"
+"nivelojn por la individuaj kategorioj. Ekzemplo: "
+"GST_AUTOPLUG:5,GST_ELEMENT_*:3"
 
 msgid "LIST"
 msgstr "LISTO"
diff --git a/po/eu.po b/po/eu.po
index e005efe..c296430 100644
--- a/po/eu.po
+++ b/po/eu.po
@@ -8,7 +8,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: gstreamer-0.10.26.2\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2024-11-03 17:36+0000\n"
+"POT-Creation-Date: 2025-02-23 16:55+0000\n"
 "PO-Revision-Date: 2010-03-25 13:10+0100\n"
 "Last-Translator: Mikel Olasagasti Uranga <hey_neken@mundurat.net>\n"
 "Language-Team: Basque <translation-team-eu@lists.sourceforge.net>\n"
@@ -44,8 +44,8 @@ msgid ""
 "the individual categories. Example: GST_AUTOPLUG:5,GST_ELEMENT_*:3"
 msgstr ""
 "Kategoria bakoitzari maila jakin bat ezartzeko, erabili komaz bereizitako "
-"kategoriaren_izena:maila pareen zerrenda. Adibidea: GST_AUTOPLUG:5,"
-"GST_ELEMENT_*:3"
+"kategoriaren_izena:maila pareen zerrenda. Adibidea: "
+"GST_AUTOPLUG:5,GST_ELEMENT_*:3"
 
 msgid "LIST"
 msgstr "ZERRENDA"
@@ -1440,8 +1440,8 @@ msgstr "Kanalizazioa askatzen...\n"
 
 #~ msgid "Usage: gst-xmllaunch <file.xml> [ element.property=value ... ]\n"
 #~ msgstr ""
-#~ "Erabilera: gst-xmllaunch <fitxategia.xml> [ elementua."
-#~ "propietatea=balioa... ]\n"
+#~ "Erabilera: gst-xmllaunch <fitxategia.xml> "
+#~ "[ elementua.propietatea=balioa... ]\n"
 
 #, c-format
 #~ msgid "ERROR: parse of xml file '%s' failed.\n"
diff --git a/po/fr.po b/po/fr.po
index 32fadf9..933c942 100644
--- a/po/fr.po
+++ b/po/fr.po
@@ -11,7 +11,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: gstreamer 1.21.90\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2024-11-03 17:36+0000\n"
+"POT-Creation-Date: 2025-02-23 16:55+0000\n"
 "PO-Revision-Date: 2023-06-04 11:11+0200\n"
 "Last-Translator: Christian Wiatr <w9204-fs@yahoo.com>\n"
 "Language-Team: French <traduc@traduc.org>\n"
@@ -46,8 +46,8 @@ msgid ""
 "the individual categories. Example: GST_AUTOPLUG:5,GST_ELEMENT_*:3"
 msgstr ""
 "Liste séparée par des virgules de paires nom_catégorie:niveau définissant "
-"des niveaux spécifiques pour chaque catégorie. Exemple : GST_AUTOPLUG:5,"
-"GST_ELEMENT_*:3"
+"des niveaux spécifiques pour chaque catégorie. Exemple : "
+"GST_AUTOPLUG:5,GST_ELEMENT_*:3"
 
 msgid "LIST"
 msgstr "LISTE"
diff --git a/po/gl.po b/po/gl.po
index 75e6a9d..f620d20 100644
--- a/po/gl.po
+++ b/po/gl.po
@@ -6,7 +6,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: gstreamer 1.0.3\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2024-11-03 17:36+0000\n"
+"POT-Creation-Date: 2025-02-23 16:55+0000\n"
 "PO-Revision-Date: 2012-12-15 03:29+0200\n"
 "Last-Translator: Fran Dieguez <frandieguez@ubuntu.com>\n"
 "Language-Team: Galician <proxecto@trasno.net>\n"
@@ -42,8 +42,8 @@ msgid ""
 "the individual categories. Example: GST_AUTOPLUG:5,GST_ELEMENT_*:3"
 msgstr ""
 "Lista de pares nome_categoría:nivel separados por comas para estabelecer "
-"niveis específicos para as categorías individuais. Exemplo: GST_AUTOPLUG:5,"
-"GST_ELEMENT_*:3"
+"niveis específicos para as categorías individuais. Exemplo: "
+"GST_AUTOPLUG:5,GST_ELEMENT_*:3"
 
 msgid "LIST"
 msgstr "LISTA"
diff --git a/po/gstreamer-1.0.pot b/po/gstreamer-1.0.pot
index 413987b..8ad97b2 100644
--- a/po/gstreamer-1.0.pot
+++ b/po/gstreamer-1.0.pot
@@ -6,9 +6,9 @@
 #, fuzzy
 msgid ""
 msgstr ""
-"Project-Id-Version: gstreamer-1.24.12\n"
+"Project-Id-Version: gstreamer-1.26.0\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2025-01-29 20:12+0000\n"
+"POT-Creation-Date: 2025-03-11 20:14+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"
@@ -101,7 +101,7 @@ msgstr ""
 msgid "Show GStreamer Options"
 msgstr ""
 
-#: gst/gst.c:1015
+#: gst/gst.c:1020
 #, c-format
 msgid "Unknown option"
 msgstr ""
@@ -1045,12 +1045,12 @@ msgstr ""
 msgid "URI scheme '%s' not supported"
 msgstr ""
 
-#: gst/gstutils.c:2683 tools/gst-launch.c:351
+#: gst/gstutils.c:2682 tools/gst-launch.c:351
 #, c-format
 msgid "ERROR: from element %s: %s\n"
 msgstr ""
 
-#: gst/gstutils.c:2685 tools/gst-launch.c:353 tools/gst-launch.c:715
+#: gst/gstutils.c:2684 tools/gst-launch.c:353 tools/gst-launch.c:715
 #, c-format
 msgid ""
 "Additional debug info:\n"
@@ -1060,139 +1060,139 @@ msgstr ""
 #. ******************************************************************************************
 #. *** helpers for pipeline-setup
 #. ******************************************************************************************
-#: gst/parse/grammar.y.in:295
+#: gst/parse/grammar.y.in:327
 #, c-format
 msgid "link has no source [sink=%s@%p]"
 msgstr ""
 
-#: gst/parse/grammar.y.in:300
+#: gst/parse/grammar.y.in:332
 #, c-format
 msgid "link has no sink [source=%s@%p]"
 msgstr ""
 
-#: gst/parse/grammar.y.in:501
+#: gst/parse/grammar.y.in:533
 msgid "No such property."
 msgstr ""
 
-#: gst/parse/grammar.y.in:501 gst/parse/grammar.y.in:687
-#: gst/parse/grammar.y.in:721 gst/parse/grammar.y.in:835
+#: gst/parse/grammar.y.in:533 gst/parse/grammar.y.in:719
+#: gst/parse/grammar.y.in:753 gst/parse/grammar.y.in:867
 #, c-format
 msgid "no property \"%s\" in element \"%s\""
 msgstr ""
 
-#: gst/parse/grammar.y.in:596
+#: gst/parse/grammar.y.in:628
 #, c-format
 msgid "Element \"%s\" is not a GstPreset"
 msgstr ""
 
-#: gst/parse/grammar.y.in:602
+#: gst/parse/grammar.y.in:634
 #, c-format
 msgid "could not set preset \"%s\" in element \"%s\""
 msgstr ""
 
-#: gst/parse/grammar.y.in:633
+#: gst/parse/grammar.y.in:665
 #, c-format
 msgid "no element \"%s\""
 msgstr ""
 
-#: gst/parse/grammar.y.in:676 gst/parse/grammar.y.in:858
+#: gst/parse/grammar.y.in:708 gst/parse/grammar.y.in:890
 #, c-format
 msgid "could not set property \"%s\" in element \"%s\" to \"%s\""
 msgstr ""
 
-#: gst/parse/grammar.y.in:730
+#: gst/parse/grammar.y.in:762
 #, c-format
 msgid "could not set property \"%s\" in child of element \"%s\" to \"%s\""
 msgstr ""
 
-#: gst/parse/grammar.y.in:919
+#: gst/parse/grammar.y.in:951
 msgid "Delayed linking failed."
 msgstr ""
 
-#: gst/parse/grammar.y.in:1132 gst/parse/grammar.y.in:1137
+#: gst/parse/grammar.y.in:1187 gst/parse/grammar.y.in:1192
 #, c-format
 msgid "could not link %s to %s, %s can't handle caps %s"
 msgstr ""
 
-#: gst/parse/grammar.y.in:1142
+#: gst/parse/grammar.y.in:1197
 #, c-format
 msgid "could not link %s to %s, neither element can handle caps %s"
 msgstr ""
 
-#: gst/parse/grammar.y.in:1146
+#: gst/parse/grammar.y.in:1201
 #, c-format
 msgid "could not link %s to %s with caps %s"
 msgstr ""
 
-#: gst/parse/grammar.y.in:1152
+#: gst/parse/grammar.y.in:1207
 #, c-format
 msgid "could not link %s to %s"
 msgstr ""
 
-#: gst/parse/grammar.y.in:1306
+#: gst/parse/grammar.y.in:1361
 #, c-format
 msgid "unexpected reference \"%s\" - ignoring"
 msgstr ""
 
-#: gst/parse/grammar.y.in:1312
+#: gst/parse/grammar.y.in:1367
 #, c-format
 msgid "unexpected pad-reference \"%s\" - ignoring"
 msgstr ""
 
-#: gst/parse/grammar.y.in:1346 gst/parse/grammar.y.in:1357
+#: gst/parse/grammar.y.in:1401 gst/parse/grammar.y.in:1412
 #, c-format
 msgid "could not parse caps \"%s\""
 msgstr ""
 
-#: gst/parse/grammar.y.in:1385
+#: gst/parse/grammar.y.in:1440
 #, c-format
 msgid "no sink element for URI \"%s\""
 msgstr ""
 
-#: gst/parse/grammar.y.in:1404
+#: gst/parse/grammar.y.in:1459
 #, c-format
 msgid "no source element for URI \"%s\""
 msgstr ""
 
-#: gst/parse/grammar.y.in:1494
+#: gst/parse/grammar.y.in:1549
 msgid "syntax error"
 msgstr ""
 
-#: gst/parse/grammar.y.in:1517
+#: gst/parse/grammar.y.in:1572
 #, c-format
 msgid "specified empty bin \"%s\", not allowed"
 msgstr ""
 
-#: gst/parse/grammar.y.in:1527
+#: gst/parse/grammar.y.in:1582
 #, c-format
 msgid "no bin \"%s\", unpacking elements"
 msgstr ""
 
-#: gst/parse/grammar.y.in:1558
+#: gst/parse/grammar.y.in:1613
 msgid "empty pipeline not allowed"
 msgstr ""
 
-#: libs/gst/base/gstbasesink.c:1250
+#: libs/gst/base/gstbasesink.c:1249
 msgid "Pipeline construction is invalid, please add queues."
 msgstr ""
 
-#: libs/gst/base/gstbasesink.c:3148
+#: libs/gst/base/gstbasesink.c:3147
 msgid "A lot of buffers are being dropped."
 msgstr ""
 
-#: libs/gst/base/gstbasesink.c:3806
+#: libs/gst/base/gstbasesink.c:3803
 msgid "Internal data flow problem."
 msgstr ""
 
-#: libs/gst/base/gstbasesink.c:4648 libs/gst/base/gstbasesrc.c:2818
+#: libs/gst/base/gstbasesink.c:4645 libs/gst/base/gstbasesrc.c:2820
 msgid "Internal data flow error."
 msgstr ""
 
-#: libs/gst/base/gstbasesrc.c:2748
+#: libs/gst/base/gstbasesrc.c:2750
 msgid "Internal clock error."
 msgstr ""
 
-#: libs/gst/base/gstbasesrc.c:2776 plugins/elements/gstdownloadbuffer.c:850
+#: libs/gst/base/gstbasesrc.c:2778 plugins/elements/gstdownloadbuffer.c:850
 #: plugins/elements/gstdownloadbuffer.c:1277
 msgid "Failed to map buffer."
 msgstr ""
@@ -1315,93 +1315,98 @@ msgstr ""
 msgid "Stream contains no data."
 msgstr ""
 
-#: tools/gst-inspect.c:359
+#: tools/gst-inspect.c:361
 #, c-format
 msgid "%sImplemented Interfaces%s:\n"
 msgstr ""
 
-#: tools/gst-inspect.c:471
+#: tools/gst-inspect.c:378
+#, c-format
+msgid "%sElement Flags%s:\n"
+msgstr ""
+
+#: tools/gst-inspect.c:501
 msgid "readable"
 msgstr ""
 
-#: tools/gst-inspect.c:476
+#: tools/gst-inspect.c:506
 msgid "writable"
 msgstr ""
 
-#: tools/gst-inspect.c:481
+#: tools/gst-inspect.c:511
 msgid "deprecated"
 msgstr ""
 
-#: tools/gst-inspect.c:485
+#: tools/gst-inspect.c:515
 msgid "controllable"
 msgstr ""
 
-#: tools/gst-inspect.c:490
+#: tools/gst-inspect.c:520
 msgid "conditionally available"
 msgstr ""
 
-#: tools/gst-inspect.c:496
+#: tools/gst-inspect.c:526
 msgid "can be set only at object construction time"
 msgstr ""
 
-#: tools/gst-inspect.c:499
+#: tools/gst-inspect.c:529
 msgid "changeable in NULL, READY, PAUSED or PLAYING state"
 msgstr ""
 
-#: tools/gst-inspect.c:502
+#: tools/gst-inspect.c:532
 msgid "changeable only in NULL, READY or PAUSED state"
 msgstr ""
 
-#: tools/gst-inspect.c:505
+#: tools/gst-inspect.c:535
 msgid "changeable only in NULL or READY state"
 msgstr ""
 
-#: tools/gst-inspect.c:1273
+#: tools/gst-inspect.c:1303
 msgid "Blacklisted files:"
 msgstr ""
 
-#: tools/gst-inspect.c:1288 tools/gst-inspect.c:1427
+#: tools/gst-inspect.c:1318 tools/gst-inspect.c:1457
 #, c-format
 msgid "%sTotal count%s: %s"
 msgstr ""
 
-#: tools/gst-inspect.c:1290
+#: tools/gst-inspect.c:1320
 #, c-format
 msgid "%d blacklisted file"
 msgid_plural "%d blacklisted files"
 msgstr[0] ""
 msgstr[1] ""
 
-#: tools/gst-inspect.c:1429
+#: tools/gst-inspect.c:1459
 #, c-format
 msgid "%d plugin"
 msgid_plural "%d plugins"
 msgstr[0] ""
 msgstr[1] ""
 
-#: tools/gst-inspect.c:1432
+#: tools/gst-inspect.c:1462
 #, c-format
 msgid "%d blacklist entry"
 msgid_plural "%d blacklist entries"
 msgstr[0] ""
 msgstr[1] ""
 
-#: tools/gst-inspect.c:1437
+#: tools/gst-inspect.c:1467
 #, c-format
 msgid "%d feature"
 msgid_plural "%d features"
 msgstr[0] ""
 msgstr[1] ""
 
-#: tools/gst-inspect.c:2188
+#: tools/gst-inspect.c:2228
 msgid "Print all elements"
 msgstr ""
 
-#: tools/gst-inspect.c:2190
+#: tools/gst-inspect.c:2230
 msgid "Print list of blacklisted files"
 msgstr ""
 
-#: tools/gst-inspect.c:2192
+#: tools/gst-inspect.c:2232
 msgid ""
 "Print a machine-parsable list of features the specified plugin or all "
 "plugins provide.\n"
@@ -1409,46 +1414,46 @@ msgid ""
 "automatic plugin installation mechanisms"
 msgstr ""
 
-#: tools/gst-inspect.c:2197
+#: tools/gst-inspect.c:2237
 msgid "List the plugin contents"
 msgstr ""
 
-#: tools/gst-inspect.c:2199
+#: tools/gst-inspect.c:2239
 msgid ""
 "A slashes ('/') separated list of types of elements (also known as klass) to "
 "list. (unordered)"
 msgstr ""
 
-#: tools/gst-inspect.c:2202
+#: tools/gst-inspect.c:2242
 msgid "Check if the specified element or plugin exists"
 msgstr ""
 
-#: tools/gst-inspect.c:2205
+#: tools/gst-inspect.c:2245
 msgid ""
 "When checking if an element or plugin exists, also check that its version is "
 "at least the version specified"
 msgstr ""
 
-#: tools/gst-inspect.c:2209
+#: tools/gst-inspect.c:2249
 msgid "Print supported URI schemes, with the elements that implement them"
 msgstr ""
 
-#: tools/gst-inspect.c:2214
+#: tools/gst-inspect.c:2254
 msgid ""
 "Disable colors in output. You can also achieve the same by setting "
 "'GST_INSPECT_NO_COLORS' environment variable to any value."
 msgstr ""
 
-#: tools/gst-inspect.c:2222
+#: tools/gst-inspect.c:2262
 msgid "Color output, even when not sending to a tty."
 msgstr ""
 
-#: tools/gst-inspect.c:2396
+#: tools/gst-inspect.c:2436
 #, c-format
 msgid "Could not load plugin file: %s\n"
 msgstr ""
 
-#: tools/gst-inspect.c:2402
+#: tools/gst-inspect.c:2442
 #, c-format
 msgid "No such element or plugin '%s'\n"
 msgstr ""
diff --git a/po/gstreamer.pot b/po/gstreamer.pot
index 413987b..8ad97b2 100644
--- a/po/gstreamer.pot
+++ b/po/gstreamer.pot
@@ -6,9 +6,9 @@
 #, fuzzy
 msgid ""
 msgstr ""
-"Project-Id-Version: gstreamer-1.24.12\n"
+"Project-Id-Version: gstreamer-1.26.0\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2025-01-29 20:12+0000\n"
+"POT-Creation-Date: 2025-03-11 20:14+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"
@@ -101,7 +101,7 @@ msgstr ""
 msgid "Show GStreamer Options"
 msgstr ""
 
-#: gst/gst.c:1015
+#: gst/gst.c:1020
 #, c-format
 msgid "Unknown option"
 msgstr ""
@@ -1045,12 +1045,12 @@ msgstr ""
 msgid "URI scheme '%s' not supported"
 msgstr ""
 
-#: gst/gstutils.c:2683 tools/gst-launch.c:351
+#: gst/gstutils.c:2682 tools/gst-launch.c:351
 #, c-format
 msgid "ERROR: from element %s: %s\n"
 msgstr ""
 
-#: gst/gstutils.c:2685 tools/gst-launch.c:353 tools/gst-launch.c:715
+#: gst/gstutils.c:2684 tools/gst-launch.c:353 tools/gst-launch.c:715
 #, c-format
 msgid ""
 "Additional debug info:\n"
@@ -1060,139 +1060,139 @@ msgstr ""
 #. ******************************************************************************************
 #. *** helpers for pipeline-setup
 #. ******************************************************************************************
-#: gst/parse/grammar.y.in:295
+#: gst/parse/grammar.y.in:327
 #, c-format
 msgid "link has no source [sink=%s@%p]"
 msgstr ""
 
-#: gst/parse/grammar.y.in:300
+#: gst/parse/grammar.y.in:332
 #, c-format
 msgid "link has no sink [source=%s@%p]"
 msgstr ""
 
-#: gst/parse/grammar.y.in:501
+#: gst/parse/grammar.y.in:533
 msgid "No such property."
 msgstr ""
 
-#: gst/parse/grammar.y.in:501 gst/parse/grammar.y.in:687
-#: gst/parse/grammar.y.in:721 gst/parse/grammar.y.in:835
+#: gst/parse/grammar.y.in:533 gst/parse/grammar.y.in:719
+#: gst/parse/grammar.y.in:753 gst/parse/grammar.y.in:867
 #, c-format
 msgid "no property \"%s\" in element \"%s\""
 msgstr ""
 
-#: gst/parse/grammar.y.in:596
+#: gst/parse/grammar.y.in:628
 #, c-format
 msgid "Element \"%s\" is not a GstPreset"
 msgstr ""
 
-#: gst/parse/grammar.y.in:602
+#: gst/parse/grammar.y.in:634
 #, c-format
 msgid "could not set preset \"%s\" in element \"%s\""
 msgstr ""
 
-#: gst/parse/grammar.y.in:633
+#: gst/parse/grammar.y.in:665
 #, c-format
 msgid "no element \"%s\""
 msgstr ""
 
-#: gst/parse/grammar.y.in:676 gst/parse/grammar.y.in:858
+#: gst/parse/grammar.y.in:708 gst/parse/grammar.y.in:890
 #, c-format
 msgid "could not set property \"%s\" in element \"%s\" to \"%s\""
 msgstr ""
 
-#: gst/parse/grammar.y.in:730
+#: gst/parse/grammar.y.in:762
 #, c-format
 msgid "could not set property \"%s\" in child of element \"%s\" to \"%s\""
 msgstr ""
 
-#: gst/parse/grammar.y.in:919
+#: gst/parse/grammar.y.in:951
 msgid "Delayed linking failed."
 msgstr ""
 
-#: gst/parse/grammar.y.in:1132 gst/parse/grammar.y.in:1137
+#: gst/parse/grammar.y.in:1187 gst/parse/grammar.y.in:1192
 #, c-format
 msgid "could not link %s to %s, %s can't handle caps %s"
 msgstr ""
 
-#: gst/parse/grammar.y.in:1142
+#: gst/parse/grammar.y.in:1197
 #, c-format
 msgid "could not link %s to %s, neither element can handle caps %s"
 msgstr ""
 
-#: gst/parse/grammar.y.in:1146
+#: gst/parse/grammar.y.in:1201
 #, c-format
 msgid "could not link %s to %s with caps %s"
 msgstr ""
 
-#: gst/parse/grammar.y.in:1152
+#: gst/parse/grammar.y.in:1207
 #, c-format
 msgid "could not link %s to %s"
 msgstr ""
 
-#: gst/parse/grammar.y.in:1306
+#: gst/parse/grammar.y.in:1361
 #, c-format
 msgid "unexpected reference \"%s\" - ignoring"
 msgstr ""
 
-#: gst/parse/grammar.y.in:1312
+#: gst/parse/grammar.y.in:1367
 #, c-format
 msgid "unexpected pad-reference \"%s\" - ignoring"
 msgstr ""
 
-#: gst/parse/grammar.y.in:1346 gst/parse/grammar.y.in:1357
+#: gst/parse/grammar.y.in:1401 gst/parse/grammar.y.in:1412
 #, c-format
 msgid "could not parse caps \"%s\""
 msgstr ""
 
-#: gst/parse/grammar.y.in:1385
+#: gst/parse/grammar.y.in:1440
 #, c-format
 msgid "no sink element for URI \"%s\""
 msgstr ""
 
-#: gst/parse/grammar.y.in:1404
+#: gst/parse/grammar.y.in:1459
 #, c-format
 msgid "no source element for URI \"%s\""
 msgstr ""
 
-#: gst/parse/grammar.y.in:1494
+#: gst/parse/grammar.y.in:1549
 msgid "syntax error"
 msgstr ""
 
-#: gst/parse/grammar.y.in:1517
+#: gst/parse/grammar.y.in:1572
 #, c-format
 msgid "specified empty bin \"%s\", not allowed"
 msgstr ""
 
-#: gst/parse/grammar.y.in:1527
+#: gst/parse/grammar.y.in:1582
 #, c-format
 msgid "no bin \"%s\", unpacking elements"
 msgstr ""
 
-#: gst/parse/grammar.y.in:1558
+#: gst/parse/grammar.y.in:1613
 msgid "empty pipeline not allowed"
 msgstr ""
 
-#: libs/gst/base/gstbasesink.c:1250
+#: libs/gst/base/gstbasesink.c:1249
 msgid "Pipeline construction is invalid, please add queues."
 msgstr ""
 
-#: libs/gst/base/gstbasesink.c:3148
+#: libs/gst/base/gstbasesink.c:3147
 msgid "A lot of buffers are being dropped."
 msgstr ""
 
-#: libs/gst/base/gstbasesink.c:3806
+#: libs/gst/base/gstbasesink.c:3803
 msgid "Internal data flow problem."
 msgstr ""
 
-#: libs/gst/base/gstbasesink.c:4648 libs/gst/base/gstbasesrc.c:2818
+#: libs/gst/base/gstbasesink.c:4645 libs/gst/base/gstbasesrc.c:2820
 msgid "Internal data flow error."
 msgstr ""
 
-#: libs/gst/base/gstbasesrc.c:2748
+#: libs/gst/base/gstbasesrc.c:2750
 msgid "Internal clock error."
 msgstr ""
 
-#: libs/gst/base/gstbasesrc.c:2776 plugins/elements/gstdownloadbuffer.c:850
+#: libs/gst/base/gstbasesrc.c:2778 plugins/elements/gstdownloadbuffer.c:850
 #: plugins/elements/gstdownloadbuffer.c:1277
 msgid "Failed to map buffer."
 msgstr ""
@@ -1315,93 +1315,98 @@ msgstr ""
 msgid "Stream contains no data."
 msgstr ""
 
-#: tools/gst-inspect.c:359
+#: tools/gst-inspect.c:361
 #, c-format
 msgid "%sImplemented Interfaces%s:\n"
 msgstr ""
 
-#: tools/gst-inspect.c:471
+#: tools/gst-inspect.c:378
+#, c-format
+msgid "%sElement Flags%s:\n"
+msgstr ""
+
+#: tools/gst-inspect.c:501
 msgid "readable"
 msgstr ""
 
-#: tools/gst-inspect.c:476
+#: tools/gst-inspect.c:506
 msgid "writable"
 msgstr ""
 
-#: tools/gst-inspect.c:481
+#: tools/gst-inspect.c:511
 msgid "deprecated"
 msgstr ""
 
-#: tools/gst-inspect.c:485
+#: tools/gst-inspect.c:515
 msgid "controllable"
 msgstr ""
 
-#: tools/gst-inspect.c:490
+#: tools/gst-inspect.c:520
 msgid "conditionally available"
 msgstr ""
 
-#: tools/gst-inspect.c:496
+#: tools/gst-inspect.c:526
 msgid "can be set only at object construction time"
 msgstr ""
 
-#: tools/gst-inspect.c:499
+#: tools/gst-inspect.c:529
 msgid "changeable in NULL, READY, PAUSED or PLAYING state"
 msgstr ""
 
-#: tools/gst-inspect.c:502
+#: tools/gst-inspect.c:532
 msgid "changeable only in NULL, READY or PAUSED state"
 msgstr ""
 
-#: tools/gst-inspect.c:505
+#: tools/gst-inspect.c:535
 msgid "changeable only in NULL or READY state"
 msgstr ""
 
-#: tools/gst-inspect.c:1273
+#: tools/gst-inspect.c:1303
 msgid "Blacklisted files:"
 msgstr ""
 
-#: tools/gst-inspect.c:1288 tools/gst-inspect.c:1427
+#: tools/gst-inspect.c:1318 tools/gst-inspect.c:1457
 #, c-format
 msgid "%sTotal count%s: %s"
 msgstr ""
 
-#: tools/gst-inspect.c:1290
+#: tools/gst-inspect.c:1320
 #, c-format
 msgid "%d blacklisted file"
 msgid_plural "%d blacklisted files"
 msgstr[0] ""
 msgstr[1] ""
 
-#: tools/gst-inspect.c:1429
+#: tools/gst-inspect.c:1459
 #, c-format
 msgid "%d plugin"
 msgid_plural "%d plugins"
 msgstr[0] ""
 msgstr[1] ""
 
-#: tools/gst-inspect.c:1432
+#: tools/gst-inspect.c:1462
 #, c-format
 msgid "%d blacklist entry"
 msgid_plural "%d blacklist entries"
 msgstr[0] ""
 msgstr[1] ""
 
-#: tools/gst-inspect.c:1437
+#: tools/gst-inspect.c:1467
 #, c-format
 msgid "%d feature"
 msgid_plural "%d features"
 msgstr[0] ""
 msgstr[1] ""
 
-#: tools/gst-inspect.c:2188
+#: tools/gst-inspect.c:2228
 msgid "Print all elements"
 msgstr ""
 
-#: tools/gst-inspect.c:2190
+#: tools/gst-inspect.c:2230
 msgid "Print list of blacklisted files"
 msgstr ""
 
-#: tools/gst-inspect.c:2192
+#: tools/gst-inspect.c:2232
 msgid ""
 "Print a machine-parsable list of features the specified plugin or all "
 "plugins provide.\n"
@@ -1409,46 +1414,46 @@ msgid ""
 "automatic plugin installation mechanisms"
 msgstr ""
 
-#: tools/gst-inspect.c:2197
+#: tools/gst-inspect.c:2237
 msgid "List the plugin contents"
 msgstr ""
 
-#: tools/gst-inspect.c:2199
+#: tools/gst-inspect.c:2239
 msgid ""
 "A slashes ('/') separated list of types of elements (also known as klass) to "
 "list. (unordered)"
 msgstr ""
 
-#: tools/gst-inspect.c:2202
+#: tools/gst-inspect.c:2242
 msgid "Check if the specified element or plugin exists"
 msgstr ""
 
-#: tools/gst-inspect.c:2205
+#: tools/gst-inspect.c:2245
 msgid ""
 "When checking if an element or plugin exists, also check that its version is "
 "at least the version specified"
 msgstr ""
 
-#: tools/gst-inspect.c:2209
+#: tools/gst-inspect.c:2249
 msgid "Print supported URI schemes, with the elements that implement them"
 msgstr ""
 
-#: tools/gst-inspect.c:2214
+#: tools/gst-inspect.c:2254
 msgid ""
 "Disable colors in output. You can also achieve the same by setting "
 "'GST_INSPECT_NO_COLORS' environment variable to any value."
 msgstr ""
 
-#: tools/gst-inspect.c:2222
+#: tools/gst-inspect.c:2262
 msgid "Color output, even when not sending to a tty."
 msgstr ""
 
-#: tools/gst-inspect.c:2396
+#: tools/gst-inspect.c:2436
 #, c-format
 msgid "Could not load plugin file: %s\n"
 msgstr ""
 
-#: tools/gst-inspect.c:2402
+#: tools/gst-inspect.c:2442
 #, c-format
 msgid "No such element or plugin '%s'\n"
 msgstr ""
diff --git a/po/hr.po b/po/hr.po
index 258f597..a20321b 100644
--- a/po/hr.po
+++ b/po/hr.po
@@ -12,7 +12,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: gstreamer-1.24.0\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2024-11-03 17:36+0000\n"
+"POT-Creation-Date: 2025-02-23 16:55+0000\n"
 "PO-Revision-Date: 2024-03-08 10:47-0800\n"
 "Last-Translator: Božidar Putanec <bozidarp@yahoo.com>\n"
 "Language-Team: Croatian <lokalizacija@linux.hr>\n"
@@ -46,9 +46,9 @@ msgid ""
 "Comma-separated list of category_name:level pairs to set specific levels for "
 "the individual categories. Example: GST_AUTOPLUG:5,GST_ELEMENT_*:3"
 msgstr ""
-"POPIS parova (odvojenih zarezom) u formatu „category_name:level“ za "
-"postavljanje razine debugiranja za pojedine kategorije; Primjer: GST_CAT:5,"
-"GST_ELEMENT_*:3,oggdemux:5"
+"POPIS parova (odvojenih zarezom) u formatu „category_name:level” za "
+"postavljanje razine debugiranja za pojedine kategorije; Primjer: "
+"GST_CAT:5,GST_ELEMENT_*:3,oggdemux:5"
 
 msgid "LIST"
 msgstr "POPIS"
@@ -90,7 +90,7 @@ msgid "Disable updating the registry"
 msgstr "onemogući ažuriranje registra"
 
 msgid "Disable spawning a helper process while scanning the registry"
-msgstr "onemogući stvaranje procesa „helper“ tijekom skeniranja registra"
+msgstr "onemogući stvaranje procesa „helper” tijekom skeniranja registra"
 
 msgid "GStreamer Options"
 msgstr "Opcije GStreamera"
@@ -856,7 +856,7 @@ msgstr "Za protokol %s nije pronađen URI rukovatelj"
 
 #, c-format
 msgid "URI scheme '%s' not supported"
-msgstr "URI shema „%s“ nije podržana"
+msgstr "URI shema „%s” nije podržana"
 
 #, c-format
 msgid "ERROR: from element %s: %s\n"
@@ -886,27 +886,27 @@ msgstr "Nema takvog svojstva."
 
 #, c-format
 msgid "no property \"%s\" in element \"%s\""
-msgstr "nema svojstva „%s“ u elementu „%s“"
+msgstr "nema svojstva „%s” u elementu „%s”"
 
 #, c-format
 msgid "Element \"%s\" is not a GstPreset"
-msgstr "Element „%s“ nije GstPreset."
+msgstr "Element „%s” nije GstPreset."
 
 #, c-format
 msgid "could not set preset \"%s\" in element \"%s\""
-msgstr "nije moguće postaviti preset „%s“ u elementu „%s“"
+msgstr "nije moguće postaviti preset „%s” u elementu „%s”"
 
 #, c-format
 msgid "no element \"%s\""
-msgstr "nema elementa „%s“"
+msgstr "nema elementa „%s”"
 
 #, c-format
 msgid "could not set property \"%s\" in element \"%s\" to \"%s\""
-msgstr "nije moguće postaviti svojstvo „%s“ u elementu „%s“ na „%s“"
+msgstr "nije moguće postaviti svojstvo „%s” u elementu „%s” na „%s”"
 
 #, c-format
 msgid "could not set property \"%s\" in child of element \"%s\" to \"%s\""
-msgstr "nije moguće postaviti svojstvo „%s“ u potomku od elementa „%s“ na „%s“"
+msgstr "nije moguće postaviti svojstvo „%s” u potomku od elementa „%s” na „%s”"
 
 msgid "Delayed linking failed."
 msgstr "Odgođeno povezivanje nije uspjelo."
@@ -930,35 +930,35 @@ msgstr "nije moguće povezati %s sa %s"
 
 #, c-format
 msgid "unexpected reference \"%s\" - ignoring"
-msgstr "neočekivana referencija „%s“ - zanemareno"
+msgstr "neočekivana referencija „%s” - zanemareno"
 
 # pad pads are the element's interface to the outside world -> sučelje
 #, c-format
 msgid "unexpected pad-reference \"%s\" - ignoring"
-msgstr "neočekivana referencija sučelja (pad-reference) „%s“ - zanemareno"
+msgstr "neočekivana referencija sučelja (pad-reference) „%s” - zanemareno"
 
 #, c-format
 msgid "could not parse caps \"%s\""
-msgstr "nije moguće raščlaniti sposobnosti „%s“"
+msgstr "nije moguće raščlaniti sposobnosti „%s”"
 
 #, c-format
 msgid "no sink element for URI \"%s\""
-msgstr "nema elementa-ponor za URI „%s“"
+msgstr "nema elementa-ponor za URI „%s”"
 
 #, c-format
 msgid "no source element for URI \"%s\""
-msgstr "nema elementa-izvor za URI „%s“"
+msgstr "nema elementa-izvor za URI „%s”"
 
 msgid "syntax error"
 msgstr "sintaktička greška"
 
 #, c-format
 msgid "specified empty bin \"%s\", not allowed"
-msgstr "specificiran je prazni spremnik „%s“ -- to nije dopušteno"
+msgstr "specificiran je prazni spremnik „%s” -- to nije dopušteno"
 
 #, c-format
 msgid "no bin \"%s\", unpacking elements"
-msgstr "nema „%s“ bin -- raspakiravanje elemenata"
+msgstr "nema „%s” bin -- raspakiravanje elemenata"
 
 msgid "empty pipeline not allowed"
 msgstr "prazan cjevovod nije dopušten"
@@ -1002,11 +1002,11 @@ msgstr "Nijedan privremeni direktorij nije specificiran."
 
 #, c-format
 msgid "Could not create temp file \"%s\"."
-msgstr "Nije moguće stvoriti privremenu datoteku „%s“."
+msgstr "Nije moguće stvoriti privremenu datoteku „%s”."
 
 #, c-format
 msgid "Could not open file \"%s\" for reading."
-msgstr "Nije moguće otvoriti datoteku „%s“ za čitanje."
+msgstr "Nije moguće otvoriti datoteku „%s” za čitanje."
 
 msgid "Error while writing to download file."
 msgstr "Greška pri pisanju u preuzetu datoteku."
@@ -1016,34 +1016,34 @@ msgstr "Nije specificirana datoteka za pisanje."
 
 #, c-format
 msgid "Could not open file \"%s\" for writing."
-msgstr "Nije moguće otvoriti datoteku „%s“ za pisanje."
+msgstr "Nije moguće otvoriti datoteku „%s” za pisanje."
 
 #, c-format
 msgid "Error closing file \"%s\"."
-msgstr "Greška pri zatvaranju datoteke „%s“."
+msgstr "Greška pri zatvaranju datoteke „%s”."
 
 #, c-format
 msgid "Error while seeking in file \"%s\"."
-msgstr "Greška pri pozicioniranju u datoteci „%s“."
+msgstr "Greška pri pozicioniranju u datoteci „%s”."
 
 #, c-format
 msgid "Error while writing to file \"%s\"."
-msgstr "Greška pri pisanju u datoteku „%s“."
+msgstr "Greška pri pisanju u datoteku „%s”."
 
 msgid "No file name specified for reading."
 msgstr "Nije specificirana datoteka za čitanje."
 
 #, c-format
 msgid "Could not get info on \"%s\"."
-msgstr "Nije moguće dobiti podatke o „%s“."
+msgstr "Nije moguće dobiti podatke o „%s”."
 
 #, c-format
 msgid "\"%s\" is a directory."
-msgstr "„%s“ je direktorij."
+msgstr "„%s” je direktorij."
 
 #, c-format
 msgid "File \"%s\" is a socket."
-msgstr "Datoteka „%s“ je utičnica (socket)."
+msgstr "Datoteka „%s” je utičnica (socket)."
 
 msgid "Failed after iterations as requested."
 msgstr "Neuspjeh nakon iteracija na zahtjev."
@@ -1064,7 +1064,7 @@ msgid "force caps"
 msgstr "nametne sposobnosti"
 
 msgid "force caps without doing a typefind"
-msgstr "nametne sposobnosti bez upotrebe „typefind“"
+msgstr "nametne sposobnosti bez upotrebe „typefind”"
 
 msgid "Stream doesn't contain enough data."
 msgstr "Tok ne sadrži dovoljno podataka."
@@ -1168,8 +1168,8 @@ msgid ""
 "list. (unordered)"
 msgstr ""
 "izlista nesortirani popis vrsta elemenata\n"
-"                                         (odvojenih s „/“); taj popis je\n"
-"                                          poznat kao „klass“"
+"                                         (odvojenih s „/”); taj popis je\n"
+"                                          poznat kao „klass”"
 
 msgid "Check if the specified element or plugin exists"
 msgstr ""
@@ -1194,7 +1194,7 @@ msgid ""
 "'GST_INSPECT_NO_COLORS' environment variable to any value."
 msgstr ""
 "Onemogućite obojeni izlaz. To možete također učiniti i postavljanjem "
-"varijable okruženja „GST_INSPECT_NO_COLORS“ na bilo koju vrijednost."
+"varijable okruženja „GST_INSPECT_NO_COLORS” na bilo koju vrijednost."
 
 msgid "Color output, even when not sending to a tty."
 msgstr "Obojeni izlaz, pa čak kad se šalje na tty."
@@ -1205,7 +1205,7 @@ msgstr "Nije moguće učitati datoteku plugina: %s\n"
 
 #, c-format
 msgid "No such element or plugin '%s'\n"
-msgstr "Nema takvog elementa ili plugina „%s“\n"
+msgstr "Nema takvog elementa ili plugina „%s”\n"
 
 msgid "Index statistics"
 msgstr "Indeksna statistika"
@@ -1218,15 +1218,15 @@ msgstr "GREŠKA: cjevovod ne želi reproducirati (play).\n"
 
 #, c-format
 msgid "Got message #%u from element \"%s\" (%s): "
-msgstr "Primljena je poruka #%u od elementa „%s“ (%s): "
+msgstr "Primljena je poruka #%u od elementa „%s” (%s): "
 
 #, c-format
 msgid "Got message #%u from pad \"%s:%s\" (%s): "
-msgstr "Primljena je poruka #%u od sučelja „%s:%s“ (%s): "
+msgstr "Primljena je poruka #%u od sučelja „%s:%s” (%s): "
 
 #, c-format
 msgid "Got message #%u from object \"%s\" (%s): "
-msgstr "Primljena je poruka #%u od objekta „%s“ (%s): "
+msgstr "Primljena je poruka #%u od objekta „%s” (%s): "
 
 #, c-format
 msgid "Got message #%u (%s): "
@@ -1234,33 +1234,33 @@ msgstr "Primljena je poruka #%u (%s): "
 
 #, c-format
 msgid "Got EOS from element \"%s\".\n"
-msgstr "Primljen je EOS (znak kraja protoka) od elementa „%s“.\n"
+msgstr "Primljen je EOS (znak kraja protoka) od elementa „%s”.\n"
 
 msgid "EOS received - stopping pipeline...\n"
 msgstr "Primljen je EOS - cjevovod se zaustavlja...\n"
 
 #, c-format
 msgid "FOUND TAG      : found by element \"%s\".\n"
-msgstr "PRONAĐEN TAG   : pronađen po elementu „%s“.\n"
+msgstr "PRONAĐEN TAG   : pronađen po elementu „%s”.\n"
 
 #, c-format
 msgid "FOUND TAG      : found by pad \"%s:%s\".\n"
-msgstr "PRONAĐEN TAG   : pronađen po sučelju „%s:%s“.\n"
+msgstr "PRONAĐEN TAG   : pronađen po sučelju „%s:%s”.\n"
 
 #, c-format
 msgid "FOUND TAG      : found by object \"%s\".\n"
-msgstr "PRONAĐEN TAG   : pronađen po objektu „%s“.\n"
+msgstr "PRONAĐEN TAG   : pronađen po objektu „%s”.\n"
 
 msgid "FOUND TAG\n"
 msgstr "PRONAĐEN TAG\n"
 
 #, c-format
 msgid "FOUND TOC      : found by element \"%s\".\n"
-msgstr "PRONAĐEN TOC   : pronađen elementom „%s“.\n"
+msgstr "PRONAĐEN TOC   : pronađen elementom „%s”.\n"
 
 #, c-format
 msgid "FOUND TOC      : found by object \"%s\".\n"
-msgstr "PRONAĐEN TOC   : pronađen objektom „%s“.\n"
+msgstr "PRONAĐEN TOC   : pronađen objektom „%s”.\n"
 
 msgid "FOUND TOC\n"
 msgstr "PRONAĐEN TOC\n"
@@ -1327,7 +1327,7 @@ msgstr "Nema elementa %s\n"
 
 #, c-format
 msgid "Got context from element '%s': %s=%s\n"
-msgstr "Primljen je kontekst od elementa „%s“: %s=%s\n"
+msgstr "Primljen je kontekst od elementa „%s”: %s=%s\n"
 
 msgid "ERROR: pipeline doesn't want to preroll.\n"
 msgstr "GREŠKA: cjevovod se ne želi pripremiti (preroll).\n"
@@ -1340,7 +1340,7 @@ msgid "Use Windows high-resolution clock, precision: %u ms\n"
 msgstr "Koristite Windows sat (clock) visoke rezolucije, preciznost: %u ms\n"
 
 msgid "Output tags (also known as metadata)"
-msgstr "izlazni tagovi (znani i kao „metapodaci“)"
+msgstr "izlazni tagovi (znani i kao „metapodaci”)"
 
 msgid "Output TOC (chapters and editions)"
 msgstr "ispiše TOC (sadržaj: poglavlja i izdanja)"
@@ -1388,14 +1388,14 @@ msgid ""
 msgstr ""
 "Ne ispisuje trenutni položaj cjevovoda. Ako ova opcija nije specificirana, "
 "ispisati će se položaj kad je stdout TTY. Da omogućite ispis položaja kad "
-"stdout nije TTY, koristite „force-position“ opciju."
+"stdout nije TTY, koristite „force-position” opciju."
 
 msgid ""
 "Allow printing current position of pipeline even if stdout is not a TTY. "
 "This option has no effect if the \"no-position\" option is specified"
 msgstr ""
 "Dopušta ispis trenutnog položaja cjevovoda i kad stdout nije TTY. Ova opcija "
-"nema efekta ako je „no-position“ opcija specificirana."
+"nema efekta ako je „no-position” opcija specificirana."
 
 #, c-format
 msgid "ERROR: pipeline could not be constructed: %s.\n"
@@ -1409,7 +1409,7 @@ msgid "WARNING: erroneous pipeline: %s\n"
 msgstr "UPOZORENJE: pogrešni cjevovod: %s\n"
 
 msgid "ERROR: the 'pipeline' element wasn't found.\n"
-msgstr "GREŠKA: nije pronađen element „pipeline“.\n"
+msgstr "GREŠKA: nije pronađen element „pipeline”.\n"
 
 msgid "Setting pipeline to PAUSED ...\n"
 msgstr "Postavljamo cjevovod na PAUSED ...\n"
@@ -1476,8 +1476,8 @@ msgstr "Cjevovod se prazni...\n"
 
 #~ msgid "Usage: gst-xmllaunch <file.xml> [ element.property=value ... ]\n"
 #~ msgstr ""
-#~ "Uporaba: gst-xmllaunch <datoteka.xml> [ element."
-#~ "svojstvo=vrijednost ... ]\n"
+#~ "Uporaba: gst-xmllaunch <datoteka.xml> "
+#~ "[ element.svojstvo=vrijednost ... ]\n"
 
 #~ msgid "ERROR: parse of xml file '%s' failed.\n"
 #~ msgstr "GREŠKA: analiza xml datoteke „%s” nije uspjela.\n"
diff --git a/po/id.po b/po/id.po
index e9904be..2b74cf9 100644
--- a/po/id.po
+++ b/po/id.po
@@ -7,7 +7,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: gstreamer 1.24.0\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2024-11-03 17:36+0000\n"
+"POT-Creation-Date: 2025-02-23 16:55+0000\n"
 "PO-Revision-Date: 2024-03-07 19:31+0700\n"
 "Last-Translator: Andika Triwidada <andika@gmail.com>\n"
 "Language-Team: Indonesian <translation-team-id@lists.sourceforge.net>\n"
@@ -42,8 +42,8 @@ msgid ""
 "the individual categories. Example: GST_AUTOPLUG:5,GST_ELEMENT_*:3"
 msgstr ""
 "Senarai dipisahkan koma dari category_name:level dipasangkan untuk mengatur "
-"level spesifik untuk kategori individual. Misalnya: GST_AUTOPLUG:5,"
-"GST_ELEMENT_*:3"
+"level spesifik untuk kategori individual. Misalnya: "
+"GST_AUTOPLUG:5,GST_ELEMENT_*:3"
 
 msgid "LIST"
 msgstr "SENARAI"
diff --git a/po/lt.po b/po/lt.po
index 9040a79..43b9647 100644
--- a/po/lt.po
+++ b/po/lt.po
@@ -7,7 +7,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: gstreamer 0.10.29.2\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2024-11-03 17:36+0000\n"
+"POT-Creation-Date: 2025-02-23 16:55+0000\n"
 "PO-Revision-Date: 2010-07-16 00:50+0300\n"
 "Last-Translator: Žygimantas Beručka <uid0@akl.lt>\n"
 "Language-Team: Lithuanian <komp_lt@konferencijos.lt>\n"
@@ -44,8 +44,8 @@ msgid ""
 "the individual categories. Example: GST_AUTOPLUG:5,GST_ELEMENT_*:3"
 msgstr ""
 "Kableliais skiriamas category_name:level porų sąrašas, nustatantis "
-"konkrečius lygius paskiroms kategorijoms. Pavyzdys: GST_AUTOPLUG:5,"
-"GST_ELEMENT_*:3"
+"konkrečius lygius paskiroms kategorijoms. Pavyzdys: "
+"GST_AUTOPLUG:5,GST_ELEMENT_*:3"
 
 msgid "LIST"
 msgstr "SĄRAŠAS"
diff --git a/po/lv.po b/po/lv.po
index 374db0d..f5d5b71 100644
--- a/po/lv.po
+++ b/po/lv.po
@@ -5,10 +5,10 @@
 #, fuzzy
 msgid ""
 msgstr ""
-"Project-Id-Version: gstreamer-1.21.90\n"
+"Project-Id-Version: gstreamer-1.24.0\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2024-11-03 17:36+0000\n"
-"PO-Revision-Date: 2023-12-25 17:53+0000\n"
+"POT-Creation-Date: 2025-02-23 16:55+0000\n"
+"PO-Revision-Date: 2024-12-22 09:55+0000\n"
 "Last-Translator: Rihards Priedītis <rprieditis@gmail.com>\n"
 "Language-Team: Latvian <translation-team-lv@lists.sourceforge.net>\n"
 "Language: lv\n"
@@ -18,7 +18,7 @@ msgstr ""
 "Plural-Forms: nplurals=3; plural=(n%10==0 || (n%100>=11 && n%100<=19) ? 0 : "
 "n%10==1 && n%100!=11 ? 1 : 2);\n"
 "X-Bugs: Report translation errors to the Language-Team address.\n"
-"X-Generator: Poedit 3.4.2\n"
+"X-Generator: Poedit 3.5\n"
 
 msgid "Print the GStreamer version"
 msgstr "Izdrukāt GStreamer versiju"
@@ -43,8 +43,8 @@ msgid ""
 "the individual categories. Example: GST_AUTOPLUG:5,GST_ELEMENT_*:3"
 msgstr ""
 "Ar komatu atdalīts kategoriju_nosaukums:līmenis pāru saraksts, lai iestatītu "
-"konkrētus līmeņus atsevišķām kategorijām. Piemērs: GST_AUTOPLUG:5,"
-"GST_ELEMENT_*:3"
+"konkrētus līmeņus atsevišķām kategorijām. Piemērs: "
+"GST_AUTOPLUG:5,GST_ELEMENT_*:3"
 
 msgid "LIST"
 msgstr "SARAKSTS"
@@ -834,10 +834,10 @@ msgid "Private data"
 msgstr "Privātie dati"
 
 msgid "container-specific-track-id"
-msgstr ""
+msgstr "konteinera specifiskais-celiņa-id"
 
 msgid "Container-specific Track ID"
-msgstr ""
+msgstr "Konteinera specifiskais Celiņa Id"
 
 #. separator between two strings
 msgid ", "
@@ -1092,7 +1092,7 @@ msgid "conditionally available"
 msgstr "nosacīti pieejams"
 
 msgid "can be set only at object construction time"
-msgstr ""
+msgstr "var iestatīt tikai objekta konstruēšanas laikā"
 
 msgid "changeable in NULL, READY, PAUSED or PLAYING state"
 msgstr "maināms NULL, READY, PAUSED vai PLAYING stāvoklī"
@@ -1354,11 +1354,10 @@ msgid "PROPERTY-NAME"
 msgstr "ĪPAŠĪBAS-NOSAUKUMS"
 
 msgid "Set the name of the program"
-msgstr ""
+msgstr "Programmas nosaukuma iestatīšana"
 
-#, fuzzy
 msgid "PROGRAM-NAME"
-msgstr "ĪPAŠĪBAS-NOSAUKUMS"
+msgstr "PROGRAMAS-NOSAUKUMS"
 
 msgid "Do not install a fault handler"
 msgstr "Neuzstādīt defektu apstrādātāju"
diff --git a/po/pl.po b/po/pl.po
index 5e56199..97d10ce 100644
--- a/po/pl.po
+++ b/po/pl.po
@@ -6,7 +6,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: gstreamer 1.24.0\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2024-11-03 17:36+0000\n"
+"POT-Creation-Date: 2025-02-23 16:55+0000\n"
 "PO-Revision-Date: 2024-03-07 20:30+0100\n"
 "Last-Translator: Jakub Bogusz <qboosh@pld-linux.org>\n"
 "Language-Team: Polish <translation-team-pl@lists.sourceforge.net>\n"
@@ -41,8 +41,8 @@ msgid ""
 "the individual categories. Example: GST_AUTOPLUG:5,GST_ELEMENT_*:3"
 msgstr ""
 "Rozdzielona przecinkami lista par nazwa_kategorii:poziom dla uzyskania "
-"określonych poziomów dla poszczególnych kategorii. Przykład: GST_AUTOPLUG:5,"
-"GST_ELEMENT_*:3"
+"określonych poziomów dla poszczególnych kategorii. Przykład: "
+"GST_AUTOPLUG:5,GST_ELEMENT_*:3"
 
 msgid "LIST"
 msgstr "LISTA"
diff --git a/po/pt_BR.po b/po/pt_BR.po
index ae7e94c..5eeeeb7 100644
--- a/po/pt_BR.po
+++ b/po/pt_BR.po
@@ -19,11 +19,11 @@ msgid ""
 msgstr ""
 "Project-Id-Version: gstreamer-1.24.0\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2024-11-03 17:36+0000\n"
+"POT-Creation-Date: 2025-02-23 16:55+0000\n"
 "PO-Revision-Date: 2024-10-09 11:12-0300\n"
 "Last-Translator: Rafael Fontenelle <rafaelff@gnome.org>\n"
-"Language-Team: Brazilian Portuguese <ldpbr-translation@lists.sourceforge."
-"net>\n"
+"Language-Team: Brazilian Portuguese <ldpbr-"
+"translation@lists.sourceforge.net>\n"
 "Language: pt_BR\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
@@ -55,8 +55,8 @@ msgid ""
 "the individual categories. Example: GST_AUTOPLUG:5,GST_ELEMENT_*:3"
 msgstr ""
 "Lista de \"categoria_nome:nível\" separados por vírgulas, para definir "
-"níveis específicos para as categorias individuais. Exemplo: GST_AUTOPLUG:5,"
-"GST_ELEMENT_*:3"
+"níveis específicos para as categorias individuais. Exemplo: "
+"GST_AUTOPLUG:5,GST_ELEMENT_*:3"
 
 msgid "LIST"
 msgstr "LISTA"
@@ -417,8 +417,8 @@ msgstr "ISRC"
 
 msgid "International Standard Recording Code - see http://www.ifpi.org/isrc/"
 msgstr ""
-"Código de Gravação Padrão Internacional (ISRC) - consulte http://www.ifpi."
-"org/isrc/"
+"Código de Gravação Padrão Internacional (ISRC) - consulte http://"
+"www.ifpi.org/isrc/"
 
 msgid "organization"
 msgstr "organização"
diff --git a/po/ro.po b/po/ro.po
index 6be1744..ed81f69 100644
--- a/po/ro.po
+++ b/po/ro.po
@@ -20,7 +20,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: gstreamer 1.24.0\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2024-11-03 17:36+0000\n"
+"POT-Creation-Date: 2025-02-23 16:55+0000\n"
 "PO-Revision-Date: 2024-03-08 14:24+0100\n"
 "Last-Translator: Remus-Gabriel Chelu <remusgabriel.chelu@disroot.org>\n"
 "Language-Team: Romanian <translation-team-ro@lists.sourceforge.net>\n"
@@ -68,8 +68,8 @@ msgid ""
 "the individual categories. Example: GST_AUTOPLUG:5,GST_ELEMENT_*:3"
 msgstr ""
 "Listă separată prin virgulă de perechi nume_categorie:nivel pentru a stabili "
-"niveluri specifice pentru fiecare categorie. Exemplu: GST_AUTOPLUG:5,"
-"GST_ELEMENT_*:3"
+"niveluri specifice pentru fiecare categorie. Exemplu: "
+"GST_AUTOPLUG:5,GST_ELEMENT_*:3"
 
 msgid "LIST"
 msgstr "LISTÄ‚"
diff --git a/po/ru.po b/po/ru.po
index cbd1bfb..13027bc 100644
--- a/po/ru.po
+++ b/po/ru.po
@@ -4,13 +4,13 @@
 # Peter Astakhov <astakhovp@mail.ru>, 2005.
 # Артём Попов <artfwo@gmail.com>, 2009.
 # Pavel Maryanov <acid_jack@ukr.net>, 2009.
-# Yuri Kozlov <yuray@komyakino.ru>, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2019, 2021, 2023.
+# Yuri Kozlov <yuray@komyakino.ru>, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2019, 2021, 2023, 2024.
 msgid ""
 msgstr ""
-"Project-Id-Version: gstreamer 1.21.90\n"
+"Project-Id-Version: gstreamer 1.24.0\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2024-11-03 17:36+0000\n"
-"PO-Revision-Date: 2023-01-15 12:54+0300\n"
+"POT-Creation-Date: 2025-02-23 16:55+0000\n"
+"PO-Revision-Date: 2024-11-23 09:47+0300\n"
 "Last-Translator: Yuri Kozlov <yuray@komyakino.ru>\n"
 "Language-Team: Russian <gnu@d07.ru>\n"
 "Language: ru\n"
@@ -20,10 +20,10 @@ msgstr ""
 "X-Bugs: Report translation errors to the Language-Team address.\n"
 "Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
 "n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
-"X-Generator: Lokalize 20.12.0\n"
+"X-Generator: Lokalize 24.08.2\n"
 
 msgid "Print the GStreamer version"
-msgstr "Вывести версию GStreamer"
+msgstr "Показать версию GStreamer"
 
 msgid "Make all warnings fatal"
 msgstr "Сделать все предупреждения фатальными"
@@ -831,10 +831,10 @@ msgid "Private data"
 msgstr "Частная информация"
 
 msgid "container-specific-track-id"
-msgstr ""
+msgstr "container-specific-track-id"
 
 msgid "Container-specific Track ID"
-msgstr ""
+msgstr "ID трека, относящийся к контейнеру"
 
 #. separator between two strings
 msgid ", "
@@ -1091,7 +1091,7 @@ msgid "conditionally available"
 msgstr "условно доступно"
 
 msgid "can be set only at object construction time"
-msgstr ""
+msgstr "может быть задан только во время создания объекта"
 
 msgid "changeable in NULL, READY, PAUSED or PLAYING state"
 msgstr "может быть равно состоянию NULL, READY, PAUSED или PLAYING"
@@ -1352,11 +1352,10 @@ msgid "PROPERTY-NAME"
 msgstr "ИМЯ-СВОЙСТВА"
 
 msgid "Set the name of the program"
-msgstr ""
+msgstr "Задать имя программы"
 
-#, fuzzy
 msgid "PROGRAM-NAME"
-msgstr "ИМЯ-СВОЙСТВА"
+msgstr "ИМЯ-ПРОГРАММЫ"
 
 msgid "Do not install a fault handler"
 msgstr "Не устанавливать обработчик ошибок"
diff --git a/po/sk.po b/po/sk.po
index 62cf283..81d327a 100644
--- a/po/sk.po
+++ b/po/sk.po
@@ -8,7 +8,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: gstreamer 1.7.90\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2024-11-03 17:36+0000\n"
+"POT-Creation-Date: 2025-02-23 16:55+0000\n"
 "PO-Revision-Date: 2016-05-20 11:32+0100\n"
 "Last-Translator: Peter Tuhársky <tuharsky@misbb.sk>\n"
 "Language-Team: Slovak <sk-i18n@lists.linux.sk>\n"
@@ -44,8 +44,8 @@ msgid ""
 "the individual categories. Example: GST_AUTOPLUG:5,GST_ELEMENT_*:3"
 msgstr ""
 "Čiarkami oddelený zoznam dvojíc názov_kategórie:úroveň pre nastavenie "
-"špecifických úrovní pre jednotlivé kategórie. Príklad: GST_AUTOPLUG:5,"
-"GST_ELEMENT_*:3"
+"špecifických úrovní pre jednotlivé kategórie. Príklad: "
+"GST_AUTOPLUG:5,GST_ELEMENT_*:3"
 
 msgid "LIST"
 msgstr "ZOZNAM"
diff --git a/po/sq.po b/po/sq.po
index 7d2c3ed..6b6eff2 100644
--- a/po/sq.po
+++ b/po/sq.po
@@ -8,7 +8,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: gstreamer 1.19.2\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2024-11-03 17:36+0000\n"
+"POT-Creation-Date: 2025-02-23 16:55+0000\n"
 "PO-Revision-Date: 2022-03-22 10:52-0400\n"
 "Last-Translator: Agron Selimaj <as9902613@gmail.com>\n"
 "Language-Team: Albanian <translation-team-sq@lists.sourceforge.net>\n"
@@ -43,8 +43,8 @@ msgid ""
 "the individual categories. Example: GST_AUTOPLUG:5,GST_ELEMENT_*:3"
 msgstr ""
 "Lista e category_name, ndarë me presje:etiketë çifte për të përcaktuar "
-"etiketa specifike për kategoritë individuale. Shembull: GST_AUTOPLUG:5,"
-"GST_ELEMENT_*:3"
+"etiketa specifike për kategoritë individuale. Shembull: "
+"GST_AUTOPLUG:5,GST_ELEMENT_*:3"
 
 msgid "LIST"
 msgstr "LISTË"
diff --git a/po/uk.po b/po/uk.po
index b6b8b09..782ff1c 100644
--- a/po/uk.po
+++ b/po/uk.po
@@ -8,7 +8,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: gstreamer 1.24.0\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2024-11-03 17:36+0000\n"
+"POT-Creation-Date: 2025-02-23 16:55+0000\n"
 "PO-Revision-Date: 2024-07-21 19:42+0300\n"
 "Last-Translator: Yuri Chornoivan <yurchor@ukr.net>\n"
 "Language-Team: Ukrainian <trans-uk@lists.fedoraproject.org>\n"
@@ -398,8 +398,8 @@ msgstr "ISRC"
 
 msgid "International Standard Recording Code - see http://www.ifpi.org/isrc/"
 msgstr ""
-"Інтернаціональний стандартний код запису (ISRC) — дивіться http://www.ifpi."
-"org/isrc/"
+"Інтернаціональний стандартний код запису (ISRC) — дивіться http://"
+"www.ifpi.org/isrc/"
 
 msgid "organization"
 msgstr "організація"
@@ -1471,8 +1471,8 @@ msgstr "Спорожнення каналу...\n"
 
 #~ msgid "Usage: gst-xmllaunch <file.xml> [ element.property=value ... ]\n"
 #~ msgstr ""
-#~ "Використання: gst-xmllaunch <file.xml> [ елемент."
-#~ "властивість=значення ... ]\n"
+#~ "Використання: gst-xmllaunch <file.xml> "
+#~ "[ елемент.властивість=значення ... ]\n"
 
 #~ msgid "ERROR: parse of xml file '%s' failed.\n"
 #~ msgstr "ПОМИЛКА: помилка при аналізі xml файлу «%s».\n"
diff --git a/po/zh_CN.po b/po/zh_CN.po
index e8c916b..a08bd52 100644
--- a/po/zh_CN.po
+++ b/po/zh_CN.po
@@ -7,7 +7,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: gstreamer 1.21.90\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2024-11-03 17:36+0000\n"
+"POT-Creation-Date: 2025-02-23 16:55+0000\n"
 "PO-Revision-Date: 2023-01-21 13:39+0800\n"
 "Last-Translator: Tianze Wang <zwpwjwtz@126.com>\n"
 "Language-Team: Chinese (simplified) <i18n-zh@googlegroups.com>\n"
@@ -39,8 +39,8 @@ msgid ""
 "Comma-separated list of category_name:level pairs to set specific levels for "
 "the individual categories. Example: GST_AUTOPLUG:5,GST_ELEMENT_*:3"
 msgstr ""
-"逗号分隔的“类别名称:级别”列表用来为每个类别设置指定的调试级别。如:"
-"GST_AUTOPLUG:5,GST_ELEMENT_*:3"
+"逗号分隔的“类别名称:级别”列表用来为每个类别设置指定的调试级别。"
+"如:GST_AUTOPLUG:5,GST_ELEMENT_*:3"
 
 msgid "LIST"
 msgstr "列表"
diff --git a/tests/check/elements/filesink.c b/tests/check/elements/filesink.c
index 53bc3a9..dcdb358 100644
--- a/tests/check/elements/filesink.c
+++ b/tests/check/elements/filesink.c
@@ -95,6 +95,14 @@ cleanup_filesink (GstElement * filesink)
       g_rand_free (rand);                                                 \
     } G_STMT_END
 
+#define PUSH_EMPTY_BUF()                                                       \
+  G_STMT_START {                                                               \
+    GstBuffer *buf = gst_buffer_new();                                         \
+    if (sync_buffers)                                                          \
+      GST_BUFFER_FLAG_SET(buf, GST_BUFFER_FLAG_SYNC_AFTER);                    \
+    fail_unless_equals_int(gst_pad_push(mysrcpad, buf), GST_FLOW_OK);          \
+  } G_STMT_END
+
 /* Push Buffer with num_mem_blocks memory block each of size num_bytes*/
 #define PUSH_BUFFER_WITH_MULTIPLE_MEM_BLOCKS(num_mem_blocks, num_bytes)      \
     G_STMT_START {                                                           \
@@ -261,7 +269,7 @@ GST_START_TEST (test_seeking)
   CHECK_QUERY_POSITION (filesink, GST_FORMAT_BYTES, 0);
 
   /* push buffer with size 0 and NULL data */
-  PUSH_BYTES (0);
+  PUSH_EMPTY_BUF ();
   CHECK_QUERY_POSITION (filesink, GST_FORMAT_BYTES, 0);
 
   PUSH_BYTES (1);
diff --git a/tests/check/gst/gstbuffer.c b/tests/check/gst/gstbuffer.c
index dbb8478..31e63f8 100644
--- a/tests/check/gst/gstbuffer.c
+++ b/tests/check/gst/gstbuffer.c
@@ -761,7 +761,10 @@ GST_START_TEST (test_find)
 
   size = gst_buffer_get_sizes (buf, &offset, &maxalloc);
   fail_unless (size == 25);
-  fail_unless (offset >= 0);
+  /* NOTE: The offset isn't checked for the buffer since it's not deterministic
+   * (there could be pre-allocated memory before). The only check that could be
+   * done is to check that it's >= 0 which ... will always be TRUE since it's an
+   * unsigned integer ;) */
   fail_unless (maxalloc >= 25);
   fail_unless (gst_buffer_n_memory (buf) == 4);
 
diff --git a/tests/check/gst/gstcaps.c b/tests/check/gst/gstcaps.c
index b6c1541..059bc5f 100644
--- a/tests/check/gst/gstcaps.c
+++ b/tests/check/gst/gstcaps.c
@@ -1160,7 +1160,8 @@ GST_START_TEST (test_union)
 GST_END_TEST;
 
 static gboolean
-_caps_is_fixed_foreach (GQuark field_id, const GValue * value, gpointer unused)
+_caps_is_fixed_foreach (const GstIdStr * fieldname, const GValue * value,
+    gpointer unused)
 {
   return gst_value_is_fixed (value);
 }
@@ -1179,7 +1180,8 @@ GST_START_TEST (test_normalize)
   for (i = 0; i < gst_caps_get_size (norm); i++) {
     GstStructure *st = gst_caps_get_structure (norm, i);
     /* Make sure all fields of all structures are fixed */
-    fail_unless (gst_structure_foreach (st, _caps_is_fixed_foreach, NULL));
+    fail_unless (gst_structure_foreach_id_str (st, _caps_is_fixed_foreach,
+            NULL));
   }
 
   gst_caps_unref (out);
@@ -1197,7 +1199,8 @@ GST_START_TEST (test_normalize)
   for (i = 0; i < gst_caps_get_size (norm); i++) {
     GstStructure *st = gst_caps_get_structure (norm, i);
     /* Make sure all fields of all structures are fixed */
-    fail_unless (gst_structure_foreach (st, _caps_is_fixed_foreach, NULL));
+    fail_unless (gst_structure_foreach_id_str (st, _caps_is_fixed_foreach,
+            NULL));
   }
 
   gst_caps_unref (out);
@@ -1214,7 +1217,8 @@ GST_START_TEST (test_normalize)
   for (i = 0; i < gst_caps_get_size (norm); i++) {
     GstStructure *st = gst_caps_get_structure (norm, i);
     /* Make sure all fields of all structures are fixed */
-    fail_unless (gst_structure_foreach (st, _caps_is_fixed_foreach, NULL));
+    fail_unless (gst_structure_foreach_id_str (st, _caps_is_fixed_foreach,
+            NULL));
   }
 
   gst_caps_unref (out);
@@ -1262,7 +1266,7 @@ GST_START_TEST (test_features)
   s1 = gst_structure_new ("video/x-raw", "width", G_TYPE_INT, 320, "height",
       GST_TYPE_INT_RANGE, 240, 260, NULL);
   fail_unless (s1 != NULL);
-  f1 = gst_caps_features_new ("memory:EGLImage", NULL);
+  f1 = gst_caps_features_new_static_str ("memory:EGLImage", NULL);
   fail_unless (f1 != NULL);
 
   gst_caps_append_structure_full (c1, s1, f1);
@@ -1289,7 +1293,8 @@ GST_START_TEST (test_features)
   s2 = gst_structure_new ("video/x-raw", "width", G_TYPE_INT, 320, "height",
       GST_TYPE_INT_RANGE, 240, 260, NULL);
   fail_unless (s2 != NULL);
-  f2 = gst_caps_features_new ("memory:VASurface", "meta:VAMeta", NULL);
+  f2 = gst_caps_features_new_static_str ("memory:VASurface", "meta:VAMeta",
+      NULL);
   fail_unless (f2 != NULL);
   gst_caps_append_structure_full (c2, s2, f2);
 
@@ -1363,7 +1368,7 @@ GST_START_TEST (test_features)
 
   c1 = gst_caps_from_string ("video/x-raw");
   f1 = gst_caps_get_features (c1, 0);
-  f2 = gst_caps_features_new ("memory:dmabuf", NULL);
+  f2 = gst_caps_features_new_static_str ("memory:dmabuf", NULL);
   gst_caps_set_features (c1, 0, f2);
 
   gst_caps_unref (c1);
@@ -1373,7 +1378,7 @@ GST_START_TEST (test_features)
       ("video/x-raw, format=NV12; video/x-raw, format=NV16");
   fail_unless_equals_int (gst_caps_get_size (c1), 2);
 
-  f1 = gst_caps_features_new ("memory:EGLImage", NULL);
+  f1 = gst_caps_features_new_static_str ("memory:EGLImage", NULL);
   gst_caps_set_features_simple (c1, f1);
 
   f2 = gst_caps_get_features (c1, 0);
@@ -1386,7 +1391,7 @@ GST_START_TEST (test_features)
   c1 = gst_caps_new_any ();
   fail_unless_equals_int (gst_caps_get_size (c1), 0);
 
-  f1 = gst_caps_features_new ("memory:EGLImage", NULL);
+  f1 = gst_caps_features_new_static_str ("memory:EGLImage", NULL);
   /* Nothing to set the features on, but method should still take
    * ownership of the given features */
   gst_caps_set_features_simple (c1, f1);
@@ -1842,6 +1847,118 @@ GST_START_TEST (test_fixed)
 
 GST_END_TEST;
 
+
+GST_START_TEST (test_nested)
+{
+  GstCaps *caps1, *caps2, *caps3, *caps4, *capsi1, *capsi2, *capsi3;
+
+  /* *INDENT-OFF* */
+  caps1 = gst_caps_from_string (
+            "data/tensors, "
+              "model-name=ssd,"
+              "data=(GstStructure)["
+                "tensors,"
+                  "tensor-a=(GstStructure)["
+                    "tensor/raw,"
+                      "dims=<1>,"
+                      "type=uint32"
+                  "],"
+                  "tensor-b=(GstStructure)["
+                    "tensor/raw,"
+                      "dims=<1>,"
+                      "type=uint32"
+                  "]"
+              "]");
+
+  fail_unless (gst_caps_is_fixed (caps1));
+  caps2 = gst_caps_from_string (
+            "data/tensors, "
+              "model-name=ssd,"
+              "data=(GstStructure)["
+                "tensors,"
+                  "tensor-b=(GstStructure)["
+                    "tensor/raw,"
+                      "type=uint32"
+                  "]"
+              "]");
+
+  capsi1 = gst_caps_intersect (caps1, caps2);
+  fail_unless (gst_caps_is_equal (capsi1, caps1));
+
+  capsi2 = gst_caps_intersect (caps2, caps1);
+  fail_unless (gst_caps_is_equal (capsi2, caps1));
+
+  fail_unless (gst_caps_is_equal (capsi2, capsi1));
+
+  caps3 = gst_caps_from_string (
+    "video/x-raw, " \
+      "tensors=(GstCaps)" \
+        "data/tensors," \
+          "model-name=(string)ssd," \
+          "data=(structure)[" \
+            "tensors," \
+              "num-detections=(structure)[" \
+                "tensor/raw," \
+                  "dims=(int)<1>," \
+                  "type=(string)uint32;]," \
+              "scores=(structure)[" \
+                "tensor/raw," \
+                  "dims=(int)<0,1>," \
+                  "type=(string)float32;]," \
+              "boundingboxes=(structure)[" \
+                "tensor/raw," \
+                  "dims=(int)<0,4>," \
+                  "type=(string)float32;]," \
+            "classes=(structure)[" \
+              "tensor/raw," \
+                "dims=(int)< 0, 1 >, " \
+                "type=(string)uint32;];" \
+          "]"
+      );
+
+  caps4 = gst_caps_from_string (
+      "video/x-raw, " \
+        "tensors=(GstCaps)" \
+          "data/tensors," \
+            "model-name=(string)ssd," \
+            "data=(structure)[" \
+              "tensors," \
+                "num-detections=(structure)[" \
+                  "tensor/raw," \
+                    "type=(string)uint32;]," \
+                "scores=(structure)[" \
+                  "tensor/raw," \
+                    "dims=(int)<0,1>," \
+                    "type=(string)float32;]," \
+                "boundingboxes=(structure)[" \
+                  "tensor/raw," \
+                    "dims=(int)<0,4>," \
+                    "type=(string)float32;]," \
+              "classes=(structure)[" \
+                "tensor/raw," \
+                  "dims=(int)< 0, 1 >, " \
+                  "type=(string)uint32;];" \
+            "]"
+      );
+
+  /* *INDENT-ON* */
+
+  capsi3 = gst_caps_intersect (caps3, caps4);
+
+  fail_unless (gst_caps_is_empty (capsi3) == FALSE);
+  fail_unless (gst_caps_is_equal (capsi3, caps3));
+
+  gst_caps_unref (caps1);
+  gst_caps_unref (caps2);
+  gst_caps_unref (caps3);
+  gst_caps_unref (caps4);
+  gst_caps_unref (capsi1);
+  gst_caps_unref (capsi2);
+  gst_caps_unref (capsi3);
+}
+
+GST_END_TEST;
+
 static Suite *
 gst_caps_suite (void)
 {
@@ -1880,6 +1997,7 @@ gst_caps_suite (void)
   tcase_add_test (tc_chain, test_equality);
   tcase_add_test (tc_chain, test_remains_any);
   tcase_add_test (tc_chain, test_fixed);
+  tcase_add_test (tc_chain, test_nested);
 
   return s;
 }
diff --git a/tests/check/gst/gstcapsfeatures.c b/tests/check/gst/gstcapsfeatures.c
index 9af126f..d299120 100644
--- a/tests/check/gst/gstcapsfeatures.c
+++ b/tests/check/gst/gstcapsfeatures.c
@@ -30,7 +30,7 @@ GST_START_TEST (test_basic_operations)
 {
   GstCapsFeatures *a, *b;
 
-  a = gst_caps_features_new ("m:abc", "m:def", "m:ghi", NULL);
+  a = gst_caps_features_new_static_str ("m:abc", "m:def", "m:ghi", NULL);
   fail_unless (a != NULL);
   b = gst_caps_features_copy (a);
   fail_unless (b != NULL);
diff --git a/tests/check/gst/gstidstr-noinline.c b/tests/check/gst/gstidstr-noinline.c
new file mode 100644
index 0000000..5a221f1
--- /dev/null
+++ b/tests/check/gst/gstidstr-noinline.c
@@ -0,0 +1,22 @@
+/* GStreamer
+ *
+ * Copyright (C) 2024 Sebastian Dröge <sebastian@centricular.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#define GST_ID_STR_DISABLE_INLINES
+#include "gstidstr.c"
diff --git a/tests/check/gst/gstidstr.c b/tests/check/gst/gstidstr.c
new file mode 100644
index 0000000..b902c70
--- /dev/null
+++ b/tests/check/gst/gstidstr.c
@@ -0,0 +1,208 @@
+/* GStreamer
+ *
+ * unit test for GstIdStr
+ *
+ * Copyright (C) 2024 Sebastian Dröge <sebastian@centricular.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gst/gst.h>
+#include <gst/check/gstcheck.h>
+#include "gst/gstidstr-private.h"
+
+#define GST_ID_STR_PRIVATE(s) ((GstIdStrPrivate *)s)
+
+GST_START_TEST (test_init)
+{
+  GstIdStr s = GST_ID_STR_INIT;
+  GstIdStr s2 = GST_ID_STR_INIT;
+  const gchar short_without_nul[] =
+      { 'H', 'e', 'l', 'l', 'o', ',', ' ', 'W', 'o', 'r', 'l', 'd', '!' };
+  const gchar long_without_nul[] =
+      { 'H', 'e', 'l', 'l', 'o', ',', ' ', 'W', 'o', 'r', 'l', 'd', '!', ' ',
+    'G', 'o', 'o', 'd', 'b', 'y', 'e', ',', ' ', 'W', 'o', 'r', 'l', 'd',
+    '!'
+  };
+
+  fail_unless_equals_string (gst_id_str_as_str (&s), "");
+  fail_unless_equals_int (gst_id_str_get_len (&s), 0);
+
+  // Should be stack allocated
+  gst_id_str_set (&s, "Hello, World!");
+  fail_unless_equals_int (GST_ID_STR_PRIVATE (&s)->s.string_type.t, 0);
+  fail_unless_equals_string (gst_id_str_as_str (&s), "Hello, World!");
+  fail_unless_equals_int (gst_id_str_get_len (&s), 13);
+
+  gst_id_str_set_with_len (&s2, short_without_nul, sizeof (short_without_nul));
+  fail_unless_equals_int (GST_ID_STR_PRIVATE (&s2)->s.string_type.t, 0);
+  fail_unless_equals_string (gst_id_str_as_str (&s2), "Hello, World!");
+  fail_unless (gst_id_str_is_equal (&s, &s2));
+  fail_unless_equals_int (gst_id_str_get_len (&s2), 13);
+
+  // Should become the empty string again
+  gst_id_str_clear (&s);
+  fail_unless_equals_string (gst_id_str_as_str (&s), "");
+  fail_unless_equals_int (gst_id_str_get_len (&s), 0);
+
+  // Should be heap allocated
+  gst_id_str_set (&s, "Hello, World! Goodbye, World!");
+  fail_unless_equals_int (GST_ID_STR_PRIVATE (&s)->s.string_type.t, 1);
+  fail_unless_equals_string (gst_id_str_as_str (&s),
+      "Hello, World! Goodbye, World!");
+  fail_unless_equals_int (gst_id_str_get_len (&s), 29);
+
+  gst_id_str_set_with_len (&s2, long_without_nul, sizeof (long_without_nul));
+  fail_unless_equals_int (GST_ID_STR_PRIVATE (&s2)->s.string_type.t, 1);
+  fail_unless_equals_string (gst_id_str_as_str (&s2),
+      "Hello, World! Goodbye, World!");
+  fail_unless (gst_id_str_is_equal (&s, &s2));
+  fail_unless_equals_int (gst_id_str_get_len (&s2), 29);
+
+  // Should become the empty string again
+  gst_id_str_clear (&s);
+  fail_unless_equals_string (gst_id_str_as_str (&s), "");
+  fail_unless_equals_int (gst_id_str_get_len (&s), 0);
+  gst_id_str_clear (&s2);
+  fail_unless_equals_string (gst_id_str_as_str (&s2), "");
+  fail_unless_equals_int (gst_id_str_get_len (&s2), 0);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_alloc)
+{
+  GstIdStr *s = gst_id_str_new ();
+  GstIdStr *copy;
+
+  fail_unless_equals_string (gst_id_str_as_str (s), "");
+
+  // Should be stack allocated
+  gst_id_str_set (s, "Hello, World!");
+  fail_unless_equals_int (GST_ID_STR_PRIVATE (s)->s.string_type.t, 0);
+  fail_unless_equals_string (gst_id_str_as_str (s), "Hello, World!");
+
+  // Should be a full copy
+  copy = gst_id_str_copy (s);
+  fail_unless_equals_int (GST_ID_STR_PRIVATE (copy)->s.string_type.t, 0);
+  fail_unless_equals_string (gst_id_str_as_str (copy), "Hello, World!");
+  // Strings are the same, but pointers should be different because the strings should be inlined
+  fail_unless_equals_string (gst_id_str_as_str (s), gst_id_str_as_str (copy));
+  fail_unless (gst_id_str_as_str (s) != gst_id_str_as_str (copy));
+  gst_id_str_free (copy);
+
+  // Should become the empty string again
+  gst_id_str_clear (s);
+  fail_unless_equals_string (gst_id_str_as_str (s), "");
+
+  // Should be heap allocated
+  gst_id_str_set (s, "Hello, World! Goodbye, World!");
+  fail_unless_equals_int (GST_ID_STR_PRIVATE (s)->s.string_type.t, 1);
+  fail_unless_equals_string (gst_id_str_as_str (s),
+      "Hello, World! Goodbye, World!");
+
+  // Should be a full copy
+  copy = gst_id_str_copy (s);
+  fail_unless_equals_int (GST_ID_STR_PRIVATE (copy)->s.string_type.t, 1);
+  fail_unless_equals_string (gst_id_str_as_str (copy),
+      "Hello, World! Goodbye, World!");
+  gst_id_str_free (copy);
+
+  // Should be stored by pointer but not heap allocated
+  gst_id_str_set_static_str (s, "Hello, World! Goodbye, World!");
+  fail_unless_equals_int (GST_ID_STR_PRIVATE (s)->s.string_type.t, 2);
+  fail_unless_equals_string (gst_id_str_as_str (s),
+      "Hello, World! Goodbye, World!");
+
+  // Should be a shallow copy because it's a static string
+  copy = gst_id_str_copy (s);
+  fail_unless_equals_int (GST_ID_STR_PRIVATE (copy)->s.string_type.t, 2);
+  fail_unless_equals_string (gst_id_str_as_str (copy),
+      "Hello, World! Goodbye, World!");
+  fail_unless_equals_pointer (GST_ID_STR_PRIVATE (copy)->s.pointer_string.s,
+      GST_ID_STR_PRIVATE (s)->s.pointer_string.s);
+  gst_id_str_free (copy);
+
+  // Should become the empty string again
+  gst_id_str_clear (s);
+  fail_unless_equals_string (gst_id_str_as_str (s), "");
+
+  gst_id_str_free (s);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_compare)
+{
+  GstIdStr s1 = GST_ID_STR_INIT;
+  GstIdStr s2 = GST_ID_STR_INIT;
+
+  fail_unless (gst_id_str_is_equal (&s1, &s2));
+  fail_unless (gst_id_str_is_equal (&s1, &s1));
+  fail_unless (gst_id_str_is_equal_to_str (&s1, ""));
+  fail_if (gst_id_str_is_equal_to_str (&s1, "Hello, World!"));
+
+  // Should be stack allocated
+  gst_id_str_set (&s1, "Hello, World!");
+
+  fail_if (gst_id_str_is_equal (&s1, &s2));
+  fail_unless (gst_id_str_is_equal (&s1, &s1));
+  fail_unless (gst_id_str_is_equal_to_str (&s1, "Hello, World!"));
+  fail_if (gst_id_str_is_equal_to_str (&s1, "Hello, World?"));
+  fail_if (gst_id_str_is_equal_to_str (&s1, ""));
+
+  // Should be heap allocated
+  gst_id_str_set (&s1, "Hello, World! Goodbye, World!");
+
+  fail_if (gst_id_str_is_equal (&s1, &s2));
+  fail_unless (gst_id_str_is_equal (&s1, &s1));
+  fail_unless (gst_id_str_is_equal_to_str (&s1,
+          "Hello, World! Goodbye, World!"));
+  fail_if (gst_id_str_is_equal_to_str (&s1, ""));
+  fail_if (gst_id_str_is_equal_to_str (&s1, "Hello, World? Goodbye, World!"));
+
+  gst_id_str_set (&s2, "Hello, World!");
+  fail_if (gst_id_str_is_equal (&s1, &s2));
+
+  gst_id_str_set (&s1, "Hello, World!");
+  fail_unless (gst_id_str_is_equal (&s1, &s2));
+
+  gst_id_str_clear (&s1);
+  gst_id_str_clear (&s2);
+}
+
+GST_END_TEST;
+
+static Suite *
+gst_id_str_suite (void)
+{
+  Suite *s = suite_create ("GstIdStr");
+  TCase *tc_chain = tcase_create ("general");
+
+  suite_add_tcase (s, tc_chain);
+
+  tcase_add_test (tc_chain, test_init);
+  tcase_add_test (tc_chain, test_alloc);
+  tcase_add_test (tc_chain, test_compare);
+
+  return s;
+}
+
+GST_CHECK_MAIN (gst_id_str);
diff --git a/tests/check/gst/gstmessage.c b/tests/check/gst/gstmessage.c
index 88e6cf8..e511df2 100644
--- a/tests/check/gst/gstmessage.c
+++ b/tests/check/gst/gstmessage.c
@@ -85,6 +85,7 @@ GST_START_TEST (test_parsing)
     gchar *debug;
     GstStructure *d;
     const GstStructure *dc;
+    GstStructure *writable_dc;
 
     error = g_error_new (domain, 10, "test error");
     fail_if (error == NULL);
@@ -115,6 +116,15 @@ GST_START_TEST (test_parsing)
             G_TYPE_STRING));
     fail_unless (gst_structure_get_string (dc, "test-field"), "test-contents");
 
+    /* Check writable variant */
+    gst_message_ref (message);
+    /* Should fail if message is not writable */
+    ASSERT_CRITICAL (gst_message_parse_error_writable_details (message,
+            &writable_dc));
+    gst_message_unref (message);
+    gst_message_parse_error_writable_details (message, &writable_dc);
+    fail_unless (dc == writable_dc);
+
     gst_message_unref (message);
     g_error_free (error);
     g_free (debug);
@@ -625,6 +635,54 @@ GST_START_TEST (test_parsing)
     gst_message_parse_instant_rate_request (message, &rate_multiplier);
     fail_unless (rate_multiplier == 1.5);
 
+    gst_message_unref (message);
+  }
+  /* Message details */
+  {
+    GstStructure *details = NULL;
+    const GstStructure *message_structure = NULL;
+
+    /* create a message without a pre-existing structure */
+    message = gst_message_new_eos (NULL);
+
+    details = gst_message_writable_details (message);
+    fail_unless (details != NULL);
+    fail_unless (GST_IS_STRUCTURE (details));
+
+    /* The message (which initially did not have a supporting structure) should
+     * now has a structure whose name should be the message type name */
+    message_structure = gst_message_get_structure (message);
+    fail_if (message_structure == NULL);
+    fail_unless_equals_string (gst_structure_get_name (message_structure),
+        gst_message_type_get_name (GST_MESSAGE_TYPE (message)));
+
+    gst_message_unref (message);
+
+    /* Same thing but when trying to set details */
+    message = gst_message_new_eos (NULL);
+    details =
+        gst_structure_new ("awesome-details", "something", G_TYPE_INT, 42,
+        NULL);
+    gst_message_set_details (message, details);
+
+    details = gst_message_writable_details (message);
+    fail_unless (details != NULL);
+    fail_unless (GST_IS_STRUCTURE (details));
+
+    gst_message_unref (message);
+
+    /* Make sure we can't set details on a message which already has details */
+    message = gst_message_new_eos (NULL);
+    details =
+        gst_structure_new ("awesome-details", "something", G_TYPE_INT, 42,
+        NULL);
+    gst_message_set_details (message, details);
+    details = NULL;
+
+    details = gst_structure_new_empty ("some-other-details");
+    ASSERT_CRITICAL (gst_message_set_details (message, details));
+    /* No need to free structure on failures, it will be freed */
+
     gst_message_unref (message);
   }
 }
diff --git a/tests/check/gst/gstpad.c b/tests/check/gst/gstpad.c
index 0b545ee..28dac2b 100644
--- a/tests/check/gst/gstpad.c
+++ b/tests/check/gst/gstpad.c
@@ -340,6 +340,7 @@ sink_query_caps (GstPad * pad, GstObject * object, GstQuery * q)
           " query-only-field=(int)1");
       gst_query_set_caps_result (q, caps);
       gst_caps_unref (caps);
+      /* FALLTHROUGH */
     default:
       ret = gst_pad_query_default (pad, object, q);
       break;
@@ -3390,6 +3391,84 @@ GST_START_TEST (test_pad_offset_src)
 
 GST_END_TEST;
 
+/* Pushing a writable list should not increase refcount. */
+static GstFlowReturn
+verify_buffer_writable (GstPad * pad, GstObject * parent, GstBuffer * buffer)
+{
+  fail_unless (gst_buffer_is_writable (buffer));
+  gst_buffer_unref (buffer);
+  return GST_FLOW_OK;
+}
+
+static GstFlowReturn
+verify_buffer_refcount_two (GstPad * pad, GstObject * parent,
+    GstBuffer * buffer)
+{
+  fail_unless_equals_int (GST_MINI_OBJECT_REFCOUNT (buffer), 2);
+  gst_buffer_unref (buffer);
+  return GST_FLOW_OK;
+}
+
+GST_START_TEST (test_pad_chain_list_writable)
+{
+  GstPad *src, *sink;
+  GstPadLinkReturn plr;
+  GstCaps *caps;
+
+  /* setup */
+  sink = gst_pad_new ("sink", GST_PAD_SINK);
+  fail_if (sink == NULL);
+  gst_pad_set_chain_function (sink, verify_buffer_writable);
+
+  src = gst_pad_new ("src", GST_PAD_SRC);
+  fail_if (src == NULL);
+
+  caps = gst_caps_from_string ("foo/bar");
+
+  gst_pad_set_active (src, TRUE);
+
+  gst_pad_push_event (src, gst_event_new_stream_start ("test"));
+
+  gst_pad_set_active (sink, TRUE);
+
+  gst_pad_set_caps (src, caps);
+  plr = gst_pad_link (src, sink);
+
+  fail_unless (gst_pad_push_event (src,
+          gst_event_new_segment (&dummy_segment)) == TRUE);
+
+  fail_unless (GST_PAD_LINK_SUCCESSFUL (plr));
+
+  /* Create a buffer list, that moves into gst_pad_push_list */
+  GstBufferList *list = gst_buffer_list_new_sized (1);
+
+  gst_buffer_list_add (list, gst_buffer_new ());
+  gst_buffer_list_add (list, gst_buffer_new ());
+
+  fail_unless (gst_buffer_list_is_writable (list));
+  /* this takes ownership of list, and will free it */
+  gst_pad_push_list (src, list);
+
+  gst_pad_set_chain_function (sink, verify_buffer_refcount_two);
+  list = gst_buffer_list_new_sized (1);
+
+  gst_buffer_list_add (list, gst_buffer_new ());
+
+  /* ref the list one more time, so it is no longer writable */
+  gst_buffer_list_ref (list);
+
+  fail_unless (!gst_buffer_list_is_writable (list));
+  gst_pad_push_list (src, list);
+
+  gst_buffer_list_unref (list);
+
+  gst_object_unref (sink);
+  gst_object_unref (src);
+  gst_caps_unref (caps);
+}
+
+GST_END_TEST;
+
 static Suite *
 gst_pad_suite (void)
 {
@@ -3451,6 +3530,7 @@ gst_pad_suite (void)
   tcase_add_test (tc_chain, test_proxy_accept_caps_with_proxy);
   tcase_add_test (tc_chain, test_proxy_accept_caps_with_incompatible_proxy);
   tcase_add_test (tc_chain, test_pad_offset_src);
+  tcase_add_test (tc_chain, test_pad_chain_list_writable);
 
   return s;
 }
diff --git a/tests/check/gst/gststructure.c b/tests/check/gst/gststructure.c
index 80bc05a..bcc54b1 100644
--- a/tests/check/gst/gststructure.c
+++ b/tests/check/gst/gststructure.c
@@ -864,6 +864,8 @@ GST_START_TEST (test_vararg_getters)
   gst_buffer_unref (buf2);
   buf2 = NULL;
 
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
   /* and now the _id variant */
   ret = gst_structure_id_get (s, g_quark_from_static_string ("double"),
       G_TYPE_DOUBLE, &d, g_quark_from_static_string ("string"), G_TYPE_STRING,
@@ -892,6 +894,58 @@ GST_START_TEST (test_vararg_getters)
   g_free (c);
   gst_caps_unref (caps2);
   gst_buffer_unref (buf2);
+#pragma GCC diagnostic pop
+
+  /* and now the _id_str variant */
+  GstIdStr string_fieldname = GST_ID_STR_INIT;
+  GstIdStr caps_fieldname = GST_ID_STR_INIT;
+  GstIdStr buf_fieldname = GST_ID_STR_INIT;
+  GstIdStr int_fieldname = GST_ID_STR_INIT;
+  GstIdStr int64_fieldname = GST_ID_STR_INIT;
+  GstIdStr double_fieldname = GST_ID_STR_INIT;
+  GstIdStr dooble_fieldname = GST_ID_STR_INIT;
+
+  gst_id_str_set_static_str (&string_fieldname, "string");
+  gst_id_str_set_static_str (&caps_fieldname, "caps");
+  gst_id_str_set_static_str (&buf_fieldname, "buf");
+  gst_id_str_set_static_str (&int_fieldname, "int");
+  gst_id_str_set_static_str (&int64_fieldname, "int64");
+  gst_id_str_set_static_str (&double_fieldname, "double");
+  gst_id_str_set_static_str (&dooble_fieldname, "dooble");
+
+  ret = gst_structure_id_str_get (s, &double_fieldname,
+      G_TYPE_DOUBLE, &d, &string_fieldname, G_TYPE_STRING,
+      &c, &caps_fieldname, GST_TYPE_CAPS, &caps2,
+      &buf_fieldname, GST_TYPE_BUFFER, &buf2,
+      &int_fieldname, G_TYPE_INT, &i,
+      &int64_fieldname, G_TYPE_INT64, &i64, NULL);
+
+  fail_unless (ret);
+  fail_unless_equals_string (c, "Hello World!");
+  fail_unless_equals_int (i, 12345678);
+  fail_unless_equals_float (d, G_MAXDOUBLE);
+  fail_unless (i64 == -99);
+  fail_unless (caps == caps2);
+  fail_unless (buf == buf2);
+
+  /* expected failures */
+  ASSERT_CRITICAL (gst_structure_get (s, 0, G_TYPE_INT, &i, NULL));
+  fail_if (gst_structure_id_str_get (s, &int_fieldname,
+          G_TYPE_INT, &i, &double_fieldname, G_TYPE_FLOAT, &d, NULL));
+  fail_if (gst_structure_id_str_get (s, &int_fieldname,
+          G_TYPE_INT, &i, &dooble_fieldname, G_TYPE_DOUBLE, &d, NULL));
+
+  g_free (c);
+  gst_caps_unref (caps2);
+  gst_buffer_unref (buf2);
+
+  gst_id_str_clear (&string_fieldname);
+  gst_id_str_clear (&caps_fieldname);
+  gst_id_str_clear (&buf_fieldname);
+  gst_id_str_clear (&int_fieldname);
+  gst_id_str_clear (&int64_fieldname);
+  gst_id_str_clear (&double_fieldname);
+  gst_id_str_clear (&dooble_fieldname);
 
   /* finally make sure NULL as return location is handled gracefully */
   ret = gst_structure_get (s, "double", G_TYPE_DOUBLE, NULL, "string",
@@ -925,6 +979,21 @@ foreach_func (GQuark field_id, const GValue * value, gpointer user_data)
   return TRUE;
 }
 
+static gboolean
+foreach_id_str_func (const GstIdStr * fieldname, const GValue * value,
+    gpointer user_data)
+{
+  gint *sum = user_data;
+  gint v = 0;
+
+  if (G_VALUE_HOLDS_INT (value))
+    v = g_value_get_int (value);
+  *sum += v;
+
+  return TRUE;
+}
+
+
 GST_START_TEST (test_foreach)
 {
   GstStructure *s;
@@ -932,10 +1001,16 @@ GST_START_TEST (test_foreach)
 
   s = gst_structure_new ("foo/bar", "baz", G_TYPE_INT, 1, "bla", G_TYPE_INT, 3,
       NULL);
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
   fail_unless (gst_structure_foreach (s, foreach_func, &sum));
+#pragma GCC diagnostic pop
   fail_unless_equals_int (sum, 4);
-  gst_structure_free (s);
 
+  sum = 0;
+  fail_unless (gst_structure_foreach_id_str (s, foreach_id_str_func, &sum));
+  fail_unless_equals_int (sum, 4);
+  gst_structure_free (s);
 }
 
 GST_END_TEST;
@@ -949,6 +1024,15 @@ map_func (GQuark field_id, GValue * value, gpointer user_data)
   return TRUE;
 }
 
+static gboolean
+map_id_str_func (const GstIdStr * fieldname, GValue * value, gpointer user_data)
+{
+  if (G_VALUE_HOLDS_INT (value))
+    g_value_set_int (value, 123);
+
+  return TRUE;
+}
+
 GST_START_TEST (test_map_in_place)
 {
   GstStructure *s, *s2;
@@ -957,11 +1041,20 @@ GST_START_TEST (test_map_in_place)
       NULL);
   s2 = gst_structure_new ("foo/bar", "baz", G_TYPE_INT, 123, "bla", G_TYPE_INT,
       123, NULL);
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
   fail_unless (gst_structure_map_in_place (s, map_func, NULL));
+#pragma GCC diagnostic pop
   fail_unless (gst_structure_is_equal (s, s2));
+
   gst_structure_free (s);
-  gst_structure_free (s2);
+  s = gst_structure_new ("foo/bar", "baz", G_TYPE_INT, 1, "bla", G_TYPE_INT, 3,
+      NULL);
+  fail_unless (gst_structure_map_in_place_id_str (s, map_id_str_func, NULL));
+  fail_unless (gst_structure_is_equal (s, s2));
 
+  gst_structure_free (s);
+  gst_structure_free (s2);
 }
 
 GST_END_TEST;
@@ -978,6 +1071,19 @@ filter_map_func (GQuark field_id, GValue * value, gpointer user_data)
   return TRUE;
 }
 
+static gboolean
+filter_map_id_str_func (const GstIdStr * fieldname, GValue * value,
+    gpointer user_data)
+{
+  if (gst_id_str_is_equal_to_str (fieldname, "bla"))
+    return FALSE;
+
+  if (G_VALUE_HOLDS_INT (value))
+    g_value_set_int (value, 2);
+
+  return TRUE;
+}
+
 GST_START_TEST (test_filter_and_map_in_place)
 {
   GstStructure *s, *s2;
@@ -985,7 +1091,17 @@ GST_START_TEST (test_filter_and_map_in_place)
   s = gst_structure_new ("foo/bar", "baz", G_TYPE_INT, 1, "bla", G_TYPE_INT, 3,
       NULL);
   s2 = gst_structure_new ("foo/bar", "baz", G_TYPE_INT, 2, NULL);
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
   gst_structure_filter_and_map_in_place (s, filter_map_func, NULL);
+#pragma GCC diagnostic pop
+  fail_unless (gst_structure_is_equal (s, s2));
+
+  gst_structure_free (s);
+  s = gst_structure_new ("foo/bar", "baz", G_TYPE_INT, 1, "bla", G_TYPE_INT, 3,
+      NULL);
+  gst_structure_filter_and_map_in_place_id_str (s, filter_map_id_str_func,
+      NULL);
   fail_unless (gst_structure_is_equal (s, s2));
   gst_structure_free (s);
   gst_structure_free (s2);
@@ -1053,6 +1169,31 @@ GST_START_TEST (test_strict)
 
 GST_END_TEST;
 
+GST_START_TEST (test_strv)
+{
+  GstStructure *s;
+  const gchar *strv[] = { "foo", " ,<>\" ", NULL };
+
+  s = gst_structure_new ("test-struct", "strv", G_TYPE_STRV, strv, NULL);
+  fail_unless (s);
+
+  gchar *serialized = gst_structure_serialize_full (s, GST_SERIALIZE_FLAG_NONE);
+  fail_unless (serialized);
+  gst_structure_free (s);
+
+  s = gst_structure_new_from_string (serialized);
+  fail_unless (s);
+  g_free (serialized);
+
+  gchar **out_strv = NULL;
+  fail_unless (gst_structure_get (s, "strv", G_TYPE_STRV, &out_strv, NULL));
+  fail_unless (g_strv_equal (strv, (const gchar * const *) out_strv));
+  gst_structure_free (s);
+  g_strfreev (out_strv);
+}
+
+GST_END_TEST;
+
 static Suite *
 gst_structure_suite (void)
 {
@@ -1087,6 +1228,7 @@ gst_structure_suite (void)
   tcase_add_test (tc_chain, test_flagset);
   tcase_add_test (tc_chain, test_flags);
   tcase_add_test (tc_chain, test_strict);
+  tcase_add_test (tc_chain, test_strv);
   return s;
 }
 
diff --git a/tests/check/gst/gsturi.c b/tests/check/gst/gsturi.c
index 47ebd36..790db30 100644
--- a/tests/check/gst/gsturi.c
+++ b/tests/check/gst/gsturi.c
@@ -227,129 +227,131 @@ struct URITest
     struct QueryValue query[10];
     const gchar *fragment;
   } uri;
+
+  gboolean check_to_str;        // TRUE if this URI should reconstruct the original URI exactly
 };
 
 #define COMMON_URI_TESTS \
   /* VALID URIS.  PARSING AND PRINTING OF THESE SHOULD NOT CHANGE */ \
   /* scheme/path */ \
   {"scheme:", \
-      {"scheme", NULL, NULL, GST_URI_NO_PORT, NULL, {{NULL, NULL}}, NULL}}, \
+      {"scheme", NULL, NULL, GST_URI_NO_PORT, NULL, {{NULL, NULL}}, NULL}, TRUE }, \
   {"scheme:path", \
-      {"scheme", NULL, NULL, GST_URI_NO_PORT, "path", {{NULL, NULL}}, NULL}}, \
+      {"scheme", NULL, NULL, GST_URI_NO_PORT, "path", {{NULL, NULL}}, NULL}, TRUE }, \
   {"path", \
-      {NULL, NULL, NULL, GST_URI_NO_PORT, "path", {{NULL, NULL}}, NULL}}, \
+      {NULL, NULL, NULL, GST_URI_NO_PORT, "path", {{NULL, NULL}}, NULL}, TRUE }, \
   {"/path", \
-      {NULL, NULL, NULL, GST_URI_NO_PORT, "/path", {{NULL, NULL}}, NULL}}, \
+      {NULL, NULL, NULL, GST_URI_NO_PORT, "/path", {{NULL, NULL}}, NULL}, TRUE }, \
   /* hostname/port */ \
   {"scheme://hostname/path", \
         {"scheme", NULL, "hostname", GST_URI_NO_PORT, "/path", {{NULL, NULL}}, \
-          NULL}}, \
+          NULL}, TRUE }, \
   {"scheme://hostname:123/path", \
-      {"scheme", NULL, "hostname", 123, "/path", {{NULL, NULL}}, NULL}}, \
+      {"scheme", NULL, "hostname", 123, "/path", {{NULL, NULL}}, NULL}, TRUE }, \
   /* ipv6 hostname/port */ \
   {"scheme://[01:23:45:67:89:ab:cd:ef]/path", \
         {"scheme", NULL, "01:23:45:67:89:ab:cd:ef", GST_URI_NO_PORT, "/path", \
-          {{NULL, NULL}}, NULL}}, \
+          {{NULL, NULL}}, NULL}, TRUE }, \
   {"scheme://[01:23:45:67:89:ab:cd:ef]:123/path", \
         {"scheme", NULL, "01:23:45:67:89:ab:cd:ef", 123, "/path", {{NULL, \
-                  NULL}}, NULL}}, \
+                  NULL}}, NULL}, TRUE }, \
   /* query/fragment */ \
   {"path?query", \
         {NULL, NULL, NULL, GST_URI_NO_PORT, "path", {{"query", NULL}, {NULL, \
-                  NULL}}, NULL}}, \
+                  NULL}}, NULL}, TRUE }, \
   {"path?query=value", \
         {NULL, NULL, NULL, GST_URI_NO_PORT, "path", {{"query", "value"}, {NULL, \
-                  NULL}}, NULL}}, \
+                  NULL}}, NULL}, TRUE }, \
   {"path?query#fragment", \
         {NULL, NULL, NULL, GST_URI_NO_PORT, "path", {{"query", NULL}, {NULL, \
-                  NULL}}, "fragment"}}, \
+                  NULL}}, "fragment"}, TRUE }, \
   {"path?query=value#fragment", \
         {NULL, NULL, NULL, GST_URI_NO_PORT, "path", {{"query", "value"}, {NULL, \
-                  NULL}}, "fragment"}}, \
+                  NULL}}, "fragment"}, TRUE }, \
   {"scheme:path?query#fragment", \
         {"scheme", NULL, NULL, GST_URI_NO_PORT, "path", {{"query", NULL}, {NULL, \
-                  NULL}}, "fragment"}}, \
+                  NULL}}, "fragment"}, TRUE }, \
   /* full */ \
   {"scheme://hostname:123/path?query#fragment", \
         {"scheme", NULL, "hostname", 123, "/path", {{"query", NULL}, {NULL, \
-                  NULL}}, "fragment"}}, \
+                  NULL}}, "fragment"}, TRUE }, \
   {"scheme://hostname:123/path?query=value#fragment", \
         {"scheme", NULL, "hostname", 123, "/path", {{"query", "value"}, {NULL, \
-                  NULL}}, "fragment"}}, \
+                  NULL}}, "fragment"}, TRUE }, \
   {"scheme://hostname:123?query", \
         {"scheme", NULL, "hostname", 123, NULL, {{"query", NULL}, {NULL, \
-                  NULL}}, NULL}}, \
+                  NULL}}, NULL}, TRUE }, \
   {"scheme://hostname:123?query=value", \
         {"scheme", NULL, "hostname", 123, NULL, {{"query", "value"}, {NULL, \
-                  NULL}}, NULL}}, \
+                  NULL}}, NULL}, TRUE }, \
   {"scheme://hostname:123?query#fragment", \
         {"scheme", NULL, "hostname", 123, NULL, {{"query", NULL}, {NULL, \
-                  NULL}}, "fragment"}}, \
+                  NULL}}, "fragment"}, TRUE }, \
   {"scheme://hostname:123?query=value#fragment", \
         {"scheme", NULL, "hostname", 123, NULL, {{"query", "value"}, {NULL, \
-                  NULL}}, "fragment"}}, \
+                  NULL}}, "fragment"}, TRUE }, \
   /* user/pass */ \
   {"scheme://userinfo@hostname", \
         {"scheme", "userinfo", "hostname", GST_URI_NO_PORT, NULL, {{NULL, \
-                  NULL}}, NULL}}, \
+                  NULL}}, NULL}, TRUE }, \
   {"scheme://userinfo@hostname:123/path?query#fragment", \
         {"scheme", "userinfo", "hostname", 123, "/path", {{"query", NULL}, \
-              {NULL, NULL}}, "fragment"}}, \
+              {NULL, NULL}}, "fragment"}, TRUE }, \
   {"scheme://user:pass@hostname", \
         {"scheme", "user:pass", "hostname", GST_URI_NO_PORT, NULL, {{NULL, \
-                  NULL}}, NULL}}, \
+                  NULL}}, NULL}, TRUE }, \
   {"scheme://user:pass@hostname:123/path?query#fragment", \
         {"scheme", "user:pass", "hostname", 123, "/path", {{"query", NULL}, \
-              {NULL, NULL}}, "fragment"}}, \
+              {NULL, NULL}}, "fragment"}, TRUE }, \
   /* FUNNY URIS.  PARSING AND PRINTING OF THESE MAY CHANGE */ \
   {"scheme:hostname:123/path?query#fragment", \
         {"scheme", NULL, NULL, GST_URI_NO_PORT, "hostname:123/path", {{"query", \
-                  NULL}, {NULL, NULL}}, "fragment"}}, \
+                  NULL}, {NULL, NULL}}, "fragment"}, FALSE }, \
   {"scheme://:pass@hostname:123/path?query#fragment", \
         {"scheme", ":pass", "hostname", 123, "/path", {{"query", NULL}, {NULL, \
-                  NULL}}, "fragment"}}, \
+                  NULL}}, "fragment"}, FALSE }, \
   /* Skip initial white space */ \
   {" \f\n\r\t\vscheme:", \
-      {"scheme", NULL, NULL, GST_URI_NO_PORT, NULL, {{NULL, NULL}}, NULL}}, \
+      {"scheme", NULL, NULL, GST_URI_NO_PORT, NULL, {{NULL, NULL}}, NULL}, FALSE }, \
   {" \f\n\r\t\vpath", \
-      {NULL, NULL, NULL, GST_URI_NO_PORT, "path", {{NULL, NULL}}, NULL}}, \
+      {NULL, NULL, NULL, GST_URI_NO_PORT, "path", {{NULL, NULL}}, NULL}, FALSE }, \
   /* file URI */ \
   {"file://host/home/joe/foo.txt", \
         {"file", NULL, "host", GST_URI_NO_PORT, "/home/joe/foo.txt", {{NULL, \
-                  NULL}}, NULL}}, \
+                  NULL}}, NULL}, FALSE }, \
   {"file:///home/joe/foo.txt", \
         {"file", NULL, NULL, GST_URI_NO_PORT, "/home/joe/foo.txt", {{NULL, \
-                  NULL}}, NULL}},
+                  NULL}}, NULL}, TRUE },
 
 #define UNESCAPED_URI_TESTS \
   /* Test cases for gst_uri_from_string */ \
   {"scheme://user%20info@hostname", \
         {"scheme", "user info", "hostname", GST_URI_NO_PORT, NULL, {{NULL, \
-                  NULL}}, NULL}}, \
+                  NULL}}, NULL}, FALSE }, \
   {"scheme://userinfo@hostname:123/path?query#frag%23ment", \
         {"scheme", "userinfo", "hostname", 123, "/path", {{"query", NULL}, \
-              {NULL, NULL}}, "frag#ment"}}, \
+              {NULL, NULL}}, "frag#ment"}, FALSE }, \
   {"scheme://us%3Aer:pass@hostname", \
         {"scheme", "us:er:pass", "hostname", GST_URI_NO_PORT, NULL, {{NULL, \
-                  NULL}}, NULL}}, \
+                  NULL}}, NULL}, FALSE }, \
   {"scheme://us%3Aer:pa%3Ass@hostname:123/path?query#frag%23ment", \
         {"scheme", "us:er:pa:ss", "hostname", 123, "/path", {{"query", NULL}, \
-              {NULL, NULL}}, "frag#ment"}},
+              {NULL, NULL}}, "frag#ment"}, FALSE },
 
 #define ESCAPED_URI_TESTS \
   /* Test cases for gst_uri_from_string_escaped */ \
   {"scheme://user%20info@hostname", \
         {"scheme", "user%20info", "hostname", GST_URI_NO_PORT, NULL, {{NULL, \
-                  NULL}}, NULL}}, \
+                  NULL}}, NULL}, FALSE }, \
   {"scheme://userinfo@hostname:123/path?query#frag%23ment", \
         {"scheme", "userinfo", "hostname", 123, "/path", {{"query", NULL}, \
-              {NULL, NULL}}, "frag%23ment"}}, \
+              {NULL, NULL}}, "frag%23ment"}, FALSE }, \
   {"scheme://us%3Aer:pass@hostname", \
         {"scheme", "us%3Aer:pass", "hostname", GST_URI_NO_PORT, NULL, {{NULL, \
-                  NULL}}, NULL}}, \
+                  NULL}}, NULL}, FALSE }, \
   {"scheme://us%3Aer:pa%3Ass@hostname:123/path?query#frag%23ment", \
         {"scheme", "us%3Aer:pa%3Ass", "hostname", 123, "/path", {{"query", NULL}, \
-              {NULL, NULL}}, "frag%23ment"}},
+              {NULL, NULL}}, "frag%23ment"}, FALSE },
 
 
 static const struct URITest tests[] = {
@@ -1227,6 +1229,36 @@ GST_START_TEST (test_url_unescape_equals_in_http_query)
 
 GST_END_TEST;
 
+GST_START_TEST (test_url_to_string)
+{
+  GstUri *uri;
+  guint i;
+
+  for (i = 0; i < G_N_ELEMENTS (tests); i++) {
+    if (!tests[i].check_to_str) {
+      continue;
+    }
+
+    GST_DEBUG ("Testing URI '%s'", tests[i].str);
+
+    uri = gst_uri_from_string (tests[i].str);
+    fail_unless (uri != NULL);
+
+    /* Test that these URIs reconstruct to the original string */
+    GList *keys = gst_uri_get_query_keys (uri);
+    gchar *out_uri = gst_uri_to_string_with_keys (uri, keys);
+    fail_unless (out_uri != NULL);
+    fail_unless_equals_string (out_uri, tests[i].str);
+
+    g_list_free (keys);
+    g_free (out_uri);
+
+    gst_uri_unref (uri);
+  }
+}
+
+GST_END_TEST;
+
 static Suite *
 gst_uri_suite (void)
 {
@@ -1256,6 +1288,7 @@ gst_uri_suite (void)
   tcase_add_test (tc_chain, test_url_get_set);
   tcase_add_test (tc_chain, test_url_get_media_fragment_table);
   tcase_add_test (tc_chain, test_url_unescape_equals_in_http_query);
+  tcase_add_test (tc_chain, test_url_to_string);
 
   return s;
 }
diff --git a/tests/check/gst/gstutils.c b/tests/check/gst/gstutils.c
index 252c3c0..653a7f5 100644
--- a/tests/check/gst/gstutils.c
+++ b/tests/check/gst/gstutils.c
@@ -1621,6 +1621,7 @@ testpadreqsink_peer_query (GstPad * pad, GstObject * parent, GstQuery * query)
         res = TRUE;
         break;
       }
+      /* FALLTHROUGH */
     default:
       res = gst_pad_query_default (pad, parent, query);
       break;
diff --git a/tests/check/gst/gstvalue.c b/tests/check/gst/gstvalue.c
index b1d2548..72bc484 100644
--- a/tests/check/gst/gstvalue.c
+++ b/tests/check/gst/gstvalue.c
@@ -3812,7 +3812,7 @@ GST_END_TEST;
 GST_START_TEST (test_serialize_deserialize_caps_features)
 {
   GstCapsFeatures *test_feats[] = {
-    gst_caps_features_new ("abc:val1", "xyz:val2", NULL),
+    gst_caps_features_new_static_str ("abc:val1", "xyz:val2", NULL),
     gst_caps_features_new ("feat:val", NULL),
     gst_caps_features_new_any (),
     gst_caps_features_new_empty ()
@@ -4001,6 +4001,68 @@ GST_START_TEST (test_serialize_deserialize_sample)
 
 GST_END_TEST;
 
+GST_START_TEST (test_serialize_deserialize_strv)
+{
+  GValue v = G_VALUE_INIT;
+  g_value_init (&v, G_TYPE_STRV);
+
+  fail_if (gst_value_deserialize (&v, "<"));
+  fail_if (gst_value_deserialize (&v, "< foo"));
+  fail_if (gst_value_deserialize (&v, "< \"foo"));
+  fail_if (gst_value_deserialize (&v, "< \"foo\\"));
+  fail_if (gst_value_deserialize (&v, "< \"foo\""));
+  fail_if (gst_value_deserialize (&v, "< \"foo\","));
+
+  struct
+  {
+    const gchar *str;
+    const gchar *deserialized[3];
+    const gchar *serialized;
+  } tests[] = {
+    {"", {NULL}, "<>"},
+    {"foo", {"foo", NULL}, "<\"foo\">"},
+    {"foo ", {"foo ", NULL}, "<\"foo \">"},
+    {"foo ,", {"foo ", "", NULL}, "<\"foo \",\"\">"},
+    {"foo , ", {"foo ", " ", NULL}, "<\"foo \",\" \">"},
+    {"foo,bar", {"foo", "bar", NULL}, "<\"foo\",\"bar\">"},
+    {"<>", {NULL}, "<>"},
+    {"<\"\">", {"", NULL}, "<\"\">"},
+    {"< \" \" > ", {" ", NULL}, "<\" \">"},
+    {"<\"foo\",> ", {"foo", NULL}, "<\"foo\">"},
+    {"<\"foo\" , > ", {"foo", NULL}, "<\"foo\">"},
+    {"<\"foo\",\"bar\"> ", {"foo", "bar", NULL}, "<\"foo\",\"bar\">"},
+    {"<\"foo\" , \"bar\"> ", {"foo", "bar", NULL}, "<\"foo\",\"bar\">"},
+    {"<\"\\\"\\\\,<>\">", {"\"\\,<>", NULL}, "<\"\\\"\\\\,<>\">"},
+  };
+
+  for (int i = 0; i < G_N_ELEMENTS (tests); i++) {
+    const gchar *str = tests[i].str;
+    const gchar *const *deserialized = tests[i].deserialized;
+
+    /* Deserialize */
+    if (!gst_value_deserialize (&v, str))
+      fail ("Failed to deserialize %dth '%s'", i, str);
+    const gchar *const *strv = g_value_get_boxed (&v);
+    if (!g_strv_equal (strv, deserialized)) {
+      gchar *strv_str = g_strjoinv (", ", (gchar **) strv);
+      gchar *expected_str = g_strjoinv (", ", (gchar **) deserialized);
+      fail ("Deserialized %dth '%s' to '%s', expected '%s'", i, str, strv_str,
+          expected_str);
+    }
+
+    /* Re-serialize */
+    gchar *serialized = gst_value_serialize (&v);
+    if (!g_str_equal (serialized, tests[i].serialized))
+      fail ("Serialized %dth '%s' to '%s', expected '%s'", i, str, serialized,
+          tests[i].serialized);
+    g_free (serialized);
+
+    g_value_reset (&v);
+  }
+}
+
+GST_END_TEST;
+
 static Suite *
 gst_value_suite (void)
 {
@@ -4063,6 +4125,7 @@ gst_value_suite (void)
   tcase_add_test (tc_chain, test_serialize_deserialize_caps_features);
   tcase_add_test (tc_chain, test_serialize_deserialize_tag_list);
   tcase_add_test (tc_chain, test_serialize_deserialize_sample);
+  tcase_add_test (tc_chain, test_serialize_deserialize_strv);
 
   return s;
 }
diff --git a/tests/check/gst/gstvecdeque.c b/tests/check/gst/gstvecdeque.c
new file mode 100644
index 0000000..5a76737
--- /dev/null
+++ b/tests/check/gst/gstvecdeque.c
@@ -0,0 +1,639 @@
+/* GStreamer
+ *
+ * unit test for GstVecDeque
+ *
+ * Copyright (C) <2009> Edward Hervey <bilboed@bilboed.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gst/gst.h>
+#include <gst/check/gstcheck.h>
+
+/* Simplest test
+ * Initial size : 10
+ * Add 10, Remove 10
+ */
+GST_START_TEST (test_vec_deque_1)
+{
+  GstVecDeque *array;
+  guint i;
+
+  /* Create an array of initial size 10 */
+  array = gst_vec_deque_new (10);
+
+  /* push 5 values in */
+  for (i = 0; i < 5; i++)
+    gst_vec_deque_push_tail (array, GINT_TO_POINTER (i));
+
+  fail_unless_equals_int (gst_vec_deque_get_length (array), 5);
+
+  /* pull 5 values out */
+  for (i = 0; i < 5; i++) {
+    fail_unless_equals_int (GPOINTER_TO_INT (gst_vec_deque_pop_head (array)),
+        i);
+  }
+
+  fail_unless_equals_int (gst_vec_deque_get_length (array), 0);
+
+  gst_vec_deque_free (array);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_vec_deque_grow)
+{
+  GstVecDeque *array;
+  guint i;
+
+  /* Create an array of initial size 10 */
+  array = gst_vec_deque_new (10);
+
+  /* push 10 values in */
+  for (i = 0; i < 10; i++)
+    gst_vec_deque_push_tail (array, GINT_TO_POINTER (i));
+
+  fail_unless_equals_int (gst_vec_deque_get_length (array), 10);
+
+
+  /* If we add one value, it will grow */
+  gst_vec_deque_push_tail (array, GINT_TO_POINTER (10));
+
+  fail_unless_equals_int (gst_vec_deque_get_length (array), 11);
+
+  /* pull the 11 values out */
+  for (i = 0; i < 11; i++) {
+    fail_unless_equals_int (GPOINTER_TO_INT (gst_vec_deque_pop_head (array)),
+        i);
+  }
+
+  fail_unless_equals_int (gst_vec_deque_get_length (array), 0);
+  gst_vec_deque_free (array);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_vec_deque_grow_multiple)
+{
+  GstVecDeque *array;
+  guint i;
+
+  /* Create an array of initial size 10 */
+  array = gst_vec_deque_new (10);
+
+  /* push 11 values in */
+  for (i = 0; i < 11; i++)
+    gst_vec_deque_push_tail (array, GINT_TO_POINTER (i));
+
+  /* With 11 values, it should have grown once (15) */
+  fail_unless_equals_int (gst_vec_deque_get_length (array), 11);
+
+  for (i = 11; i < 20; i++)
+    gst_vec_deque_push_tail (array, GINT_TO_POINTER (i));
+
+  /* With 20 total values, it should have grown another time (3 * 15) / 2 = 22) */
+  fail_unless_equals_int (gst_vec_deque_get_length (array), 20);
+  /* It did grow beyond initial size */
+
+  /* pull the 20 values out */
+  for (i = 0; i < 20; i++) {
+    fail_unless_equals_int (GPOINTER_TO_INT (gst_vec_deque_pop_head (array)),
+        i);
+  }
+
+  fail_unless_equals_int (gst_vec_deque_get_length (array), 0);
+  gst_vec_deque_free (array);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_vec_deque_grow_middle)
+{
+  GstVecDeque *array;
+  guint i;
+
+  /* Create an array of initial size 10 */
+  array = gst_vec_deque_new (10);
+
+  /* push/pull 5 values to end up in the middle */
+  for (i = 0; i < 5; i++) {
+    gst_vec_deque_push_tail (array, GINT_TO_POINTER (i));
+    fail_unless_equals_int (GPOINTER_TO_INT (gst_vec_deque_pop_head (array)),
+        i);
+  }
+
+  /* push 10 values in */
+  for (i = 0; i < 10; i++)
+    gst_vec_deque_push_tail (array, GINT_TO_POINTER (i));
+
+  fail_unless_equals_int (gst_vec_deque_get_length (array), 10);
+
+  /* If we add one value, it will grow */
+  gst_vec_deque_push_tail (array, GINT_TO_POINTER (10));
+  fail_unless_equals_int (gst_vec_deque_get_length (array), 11);
+
+  /* pull the 11 values out */
+  for (i = 0; i < 11; i++) {
+    fail_unless_equals_int (GPOINTER_TO_INT (gst_vec_deque_pop_head (array)),
+        i);
+  }
+
+  fail_unless_equals_int (gst_vec_deque_get_length (array), 0);
+  gst_vec_deque_free (array);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_vec_deque_grow_end)
+{
+  GstVecDeque *array;
+  guint i;
+
+  /* Create an array of initial size 10 */
+  array = gst_vec_deque_new (10);
+
+  /* push/pull 9 values to end up at the last position */
+  for (i = 0; i < 9; i++) {
+    gst_vec_deque_push_tail (array, GINT_TO_POINTER (i));
+    fail_unless_equals_int (GPOINTER_TO_INT (gst_vec_deque_pop_head (array)),
+        i);
+  }
+
+  /* push 10 values in */
+  for (i = 0; i < 10; i++)
+    gst_vec_deque_push_tail (array, GINT_TO_POINTER (i));
+
+  fail_unless_equals_int (gst_vec_deque_get_length (array), 10);
+
+  /* If we add one value, it will grow */
+  gst_vec_deque_push_tail (array, GINT_TO_POINTER (10));
+  fail_unless_equals_int (gst_vec_deque_get_length (array), 11);
+
+  /* pull the 11 values out */
+  for (i = 0; i < 11; i++) {
+    fail_unless_equals_int (GPOINTER_TO_INT (gst_vec_deque_pop_head (array)),
+        i);
+  }
+
+  fail_unless_equals_int (gst_vec_deque_get_length (array), 0);
+  gst_vec_deque_free (array);
+}
+
+GST_END_TEST;
+
+static int
+compare_pointer_value (guintptr a, guintptr b)
+{
+  return (int) (a - b);
+}
+
+GST_START_TEST (test_vec_deque_drop2)
+{
+#define NUM_QA_ELEMENTS 674
+  gboolean in_array[NUM_QA_ELEMENTS] = { FALSE, };
+  GstVecDeque *array;
+  guint i, j, count, idx;
+
+  array = gst_vec_deque_new (10);
+
+  for (i = 0; i < NUM_QA_ELEMENTS; i++) {
+    gpointer element = GUINT_TO_POINTER (i);
+
+    if (g_random_boolean ()) {
+      gst_vec_deque_push_tail (array, element);
+      in_array[i] = TRUE;
+    }
+  }
+
+  for (j = 0, count = 0; j < NUM_QA_ELEMENTS; j++)
+    count += in_array[j] ? 1 : 0;
+  fail_unless_equals_int (gst_vec_deque_get_length (array), count);
+
+  while (gst_vec_deque_get_length (array) > 0) {
+    for (i = 0; i < NUM_QA_ELEMENTS; i++) {
+      gpointer dropped;
+
+      if (g_random_boolean () && g_random_boolean () && in_array[i]) {
+        idx = gst_vec_deque_find (array,
+            (GCompareFunc) compare_pointer_value, GUINT_TO_POINTER (i));
+        dropped = gst_vec_deque_drop_element (array, idx);
+        fail_unless_equals_int (i, GPOINTER_TO_INT (dropped));
+        in_array[i] = FALSE;
+      }
+    }
+
+    for (j = 0, count = 0; j < NUM_QA_ELEMENTS; j++)
+      count += in_array[j] ? 1 : 0;
+    fail_unless_equals_int (gst_vec_deque_get_length (array), count);
+  }
+
+  gst_vec_deque_free (array);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_vec_deque_grow_from_prealloc1)
+{
+  GstVecDeque *array;
+
+  array = gst_vec_deque_new (1);
+  gst_vec_deque_push_tail (array, NULL);
+  gst_vec_deque_push_tail (array, NULL);
+  gst_vec_deque_free (array);
+}
+
+GST_END_TEST;
+GST_START_TEST (test_vec_deque_peek_nth)
+{
+  GstVecDeque *array;
+  guint i;
+
+  /* Create an array of initial size 10 */
+  array = gst_vec_deque_new (10);
+
+  /* push 10 values in */
+  for (i = 0; i < 10; i++)
+    gst_vec_deque_push_tail (array, GINT_TO_POINTER (i));
+
+  for (i = 0; i < 10; i++)
+    fail_unless_equals_int (GPOINTER_TO_INT (gst_vec_deque_peek_nth (array,
+                i)), i);
+
+  gst_vec_deque_pop_head (array);
+
+  for (i = 0; i < 9; i++)
+    fail_unless_equals_int (GPOINTER_TO_INT (gst_vec_deque_peek_nth (array,
+                i)), i + 1);
+
+  gst_vec_deque_free (array);
+}
+
+GST_END_TEST;
+
+
+GST_START_TEST (test_vec_deque_peek_pop_tail)
+{
+  const guint array_sizes[] = { 0, 1, 2, 5 };
+  guint s;
+
+  for (s = 0; s < G_N_ELEMENTS (array_sizes); ++s) {
+    GstVecDeque *array;
+
+    GST_INFO ("Testing with initial size %u", array_sizes[s]);
+
+    array = gst_vec_deque_new (array_sizes[s]);
+    fail_unless_equals_int (gst_vec_deque_get_length (array), 0);
+
+    fail_unless (gst_vec_deque_peek_tail (array) == NULL);
+    fail_unless (gst_vec_deque_pop_tail (array) == NULL);
+
+    gst_vec_deque_push_tail (array, GINT_TO_POINTER (42));
+    fail_unless_equals_int (gst_vec_deque_get_length (array), 1);
+    fail_unless (gst_vec_deque_peek_tail (array) == GINT_TO_POINTER (42));
+    fail_unless (gst_vec_deque_peek_head (array) == GINT_TO_POINTER (42));
+    fail_unless_equals_int (gst_vec_deque_get_length (array), 1);
+    fail_unless (gst_vec_deque_pop_tail (array) == GINT_TO_POINTER (42));
+    fail_unless_equals_int (gst_vec_deque_get_length (array), 0);
+
+    gst_vec_deque_push_tail (array, GINT_TO_POINTER (42));
+    fail_unless_equals_int (gst_vec_deque_get_length (array), 1);
+    fail_unless (gst_vec_deque_pop_head (array) == GINT_TO_POINTER (42));
+    fail_unless_equals_int (gst_vec_deque_get_length (array), 0);
+    fail_unless (gst_vec_deque_peek_tail (array) == NULL);
+    fail_unless (gst_vec_deque_pop_tail (array) == NULL);
+
+    gst_vec_deque_push_tail (array, GINT_TO_POINTER (43));
+    gst_vec_deque_push_tail (array, GINT_TO_POINTER (44));
+
+    fail_unless_equals_int (gst_vec_deque_get_length (array), 2);
+    fail_unless_equals_int (GPOINTER_TO_INT (gst_vec_deque_peek_head (array)),
+        43);
+    fail_unless_equals_int (GPOINTER_TO_INT (gst_vec_deque_peek_tail (array)),
+        44);
+    fail_unless_equals_int (gst_vec_deque_get_length (array), 2);
+    fail_unless (gst_vec_deque_pop_tail (array) == GINT_TO_POINTER (44));
+    fail_unless_equals_int (gst_vec_deque_get_length (array), 1);
+    fail_unless (gst_vec_deque_peek_head (array) == GINT_TO_POINTER (43));
+    fail_unless (gst_vec_deque_peek_tail (array) == GINT_TO_POINTER (43));
+    fail_unless_equals_int (gst_vec_deque_get_length (array), 1);
+
+    gst_vec_deque_free (array);
+  }
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_vec_deque_push_sorted)
+{
+  GstVecDeque *array;
+  gint i;
+
+  /* Create an array of initial size 10 */
+  array = gst_vec_deque_new (10);
+
+  /* Fill it with odd values */
+  for (i = 1; i < 10; i += 2)
+    gst_vec_deque_push_tail (array, GINT_TO_POINTER (i));
+
+  /* Now try to push even values, in reverse order because why not */
+  for (i = 8; i >= 0; i -= 2)
+    gst_vec_deque_push_sorted (array, GINT_TO_POINTER (i),
+        (GCompareDataFunc) compare_pointer_value, NULL);
+
+  fail_unless_equals_int (gst_vec_deque_get_length (array), 10);
+
+  /* Check that the array is now 0-9 in correct order */
+  for (i = 0; i < 10; i++)
+    fail_unless_equals_int (GPOINTER_TO_INT (gst_vec_deque_pop_head (array)),
+        i);
+
+  gst_vec_deque_free (array);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_vec_deque_push_sorted_wrapped)
+{
+  GstVecDeque *array;
+  gint i;
+
+  /* Create an array of initial size 10 */
+  array = gst_vec_deque_new (10);
+
+  /* Push and pull 4 values to offset head/tail.
+   * Pushing +1's the tail and popping +1's the head, so the push after this will
+   * store data at [4] internally, and further 10 pushes will cause the array
+   * to wrap around. */
+  for (i = 0; i < 4; i++) {
+    gst_vec_deque_push_tail (array, GINT_TO_POINTER (i));
+    fail_unless_equals_int (GPOINTER_TO_INT (gst_vec_deque_pop_head (array)),
+        i);
+  }
+
+  /* Fill it with odd values */
+  for (i = 1; i < 10; i += 2)
+    gst_vec_deque_push_tail (array, GINT_TO_POINTER (i));
+
+  /* Now try to push even values, in reverse order because why not */
+  for (i = 8; i >= 0; i -= 2)
+    gst_vec_deque_push_sorted (array, GINT_TO_POINTER (i),
+        (GCompareDataFunc) compare_pointer_value, NULL);
+
+  fail_unless_equals_int (gst_vec_deque_get_length (array), 10);
+
+  /* Check that the array is now 0-9 in correct order */
+  for (i = 0; i < 10; i++)
+    fail_unless_equals_int (GPOINTER_TO_INT (gst_vec_deque_pop_head (array)),
+        i);
+
+  gst_vec_deque_free (array);
+}
+
+GST_END_TEST;
+
+typedef struct
+{
+  gint value;
+} CompareTestStruct;
+
+static int
+compare_struct_value (CompareTestStruct * a, CompareTestStruct * b)
+{
+  return a->value - b->value;
+}
+
+GST_START_TEST (test_vec_deque_push_sorted_struct)
+{
+  GstVecDeque *array;
+  gint i;
+
+  /* Create an array of initial size 10 */
+  array = gst_vec_deque_new_for_struct (sizeof (CompareTestStruct), 10);
+
+  /* Fill it with odd values */
+  for (i = 1; i < 10; i += 2) {
+    CompareTestStruct s = { i };
+    gst_vec_deque_push_tail_struct (array, &s);
+  }
+
+  /* Now try to push even values, in reverse order because why not */
+  for (i = 8; i >= 0; i -= 2) {
+    CompareTestStruct s = { i };
+    gst_vec_deque_push_sorted_struct (array, &s,
+        (GCompareDataFunc) compare_struct_value, NULL);
+  }
+
+  fail_unless_equals_int (gst_vec_deque_get_length (array), 10);
+
+  /* Check that the array is now 0-9 in correct order */
+  for (i = 0; i < 10; i++) {
+    CompareTestStruct *s = gst_vec_deque_pop_head_struct (array);
+    fail_unless_equals_int (s->value, i);
+  }
+
+  gst_vec_deque_free (array);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_vec_deque_push_sorted_struct_wrapped)
+{
+  GstVecDeque *array;
+  gint i;
+
+  /* Create an array of initial size 10 */
+  array = gst_vec_deque_new_for_struct (sizeof (CompareTestStruct), 10);
+
+  /* Push and pull 4 values to offset head/tail.
+   * Pushing +1's the tail and popping +1's the head, so the push after this will
+   * store data at [4] internally, and further 10 pushes will cause the array
+   * to wrap around. */
+  for (i = 0; i < 4; i++) {
+    gst_vec_deque_push_tail (array, GINT_TO_POINTER (i));
+    fail_unless_equals_int (GPOINTER_TO_INT (gst_vec_deque_pop_head (array)),
+        i);
+  }
+
+  /* Fill it with odd values */
+  for (i = 1; i < 10; i += 2) {
+    CompareTestStruct s = { i };
+    gst_vec_deque_push_tail_struct (array, &s);
+  }
+
+  /* Now try to push even values, in reverse order because why not */
+  for (i = 8; i >= 0; i -= 2) {
+    CompareTestStruct s = { i };
+    gst_vec_deque_push_sorted_struct (array, &s,
+        (GCompareDataFunc) compare_struct_value, NULL);
+  }
+
+  fail_unless_equals_int (gst_vec_deque_get_length (array), 10);
+
+  /* Check that the array is now 0-9 in correct order */
+  for (i = 0; i < 10; i++) {
+    CompareTestStruct *s = gst_vec_deque_pop_head_struct (array);
+    fail_unless_equals_int (s->value, i);
+  }
+
+  gst_vec_deque_free (array);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_vec_deque_sort)
+{
+  GstVecDeque *array;
+  gint i;
+
+  /* Create an array of initial size 10 */
+  array = gst_vec_deque_new (10);
+
+  /* Fill it with odd values */
+  for (i = 1; i < 10; i += 2)
+    gst_vec_deque_push_tail (array, GINT_TO_POINTER (i));
+
+  /* Now try to push even values, in reverse order because why not */
+  for (i = 8; i >= 0; i -= 2)
+    gst_vec_deque_push_tail (array, GINT_TO_POINTER (i));
+
+  fail_unless_equals_int (gst_vec_deque_get_length (array), 10);
+
+  /* Sort the array */
+  gst_vec_deque_sort (array, (GCompareDataFunc) compare_pointer_value, NULL);
+
+  fail_unless_equals_int (gst_vec_deque_get_length (array), 10);
+
+  /* Check that the array is now 0-9 in correct order */
+  for (i = 0; i < 10; i++)
+    fail_unless_equals_int (GPOINTER_TO_INT (gst_vec_deque_pop_head (array)),
+        i);
+
+  gst_vec_deque_free (array);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_vec_deque_sort_struct)
+{
+  GstVecDeque *array;
+  gint i;
+
+  /* Create an array of initial size 10 */
+  array = gst_vec_deque_new_for_struct (sizeof (CompareTestStruct), 10);
+
+  /* Fill it with odd values */
+  for (i = 1; i < 10; i += 2) {
+    CompareTestStruct s = { i };
+    gst_vec_deque_push_tail_struct (array, &s);
+  }
+
+  /* Now try to push even values, in reverse order because why not */
+  for (i = 8; i >= 0; i -= 2) {
+    CompareTestStruct s = { i };
+    gst_vec_deque_push_tail_struct (array, &s);
+  }
+
+  fail_unless_equals_int (gst_vec_deque_get_length (array), 10);
+
+  /* Sort the array */
+  gst_vec_deque_sort (array, (GCompareDataFunc) compare_struct_value, NULL);
+
+  /* Check that the array is now 0-9 in correct order */
+  for (i = 0; i < 10; i++) {
+    CompareTestStruct *s = gst_vec_deque_pop_head_struct (array);
+    fail_unless_equals_int (s->value, i);
+  }
+
+  gst_vec_deque_free (array);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_vec_deque_sort_wrapped)
+{
+  GstVecDeque *array;
+  gint i;
+
+  /* Create an array of initial size 10 */
+  array = gst_vec_deque_new (10);
+
+  /* Push and pull 4 values to offset head/tail */
+  for (i = 0; i < 4; i++) {
+    gst_vec_deque_push_tail (array, GINT_TO_POINTER (i));
+    fail_unless_equals_int (GPOINTER_TO_INT (gst_vec_deque_pop_head (array)),
+        i);
+  }
+
+  fail_unless_equals_int (gst_vec_deque_get_length (array), 0);
+
+  /* Fill it with odd values */
+  for (i = 1; i < 10; i += 2)
+    gst_vec_deque_push_tail (array, GINT_TO_POINTER (i));
+
+  /* Now try to push even values, in reverse order because why not
+   * At this point the array should've wrapped around (head > tail) */
+  for (i = 8; i >= 0; i -= 2)
+    gst_vec_deque_push_tail (array, GINT_TO_POINTER (i));
+
+  fail_unless_equals_int (gst_vec_deque_get_length (array), 10);
+
+  /* Sort the array */
+  gst_vec_deque_sort (array, (GCompareDataFunc) compare_pointer_value, NULL);
+
+  /* Check that the array is now 0-9 in correct order */
+  for (i = 0; i < 10; i++)
+    fail_unless_equals_int (GPOINTER_TO_INT (gst_vec_deque_pop_head (array)),
+        i);
+
+  gst_vec_deque_free (array);
+}
+
+GST_END_TEST;
+
+static Suite *
+gst_vec_deque_suite (void)
+{
+  Suite *s = suite_create ("GstVecDeque");
+  TCase *tc_chain = tcase_create ("general");
+
+  suite_add_tcase (s, tc_chain);
+
+  tcase_add_test (tc_chain, test_vec_deque_1);
+  tcase_add_test (tc_chain, test_vec_deque_grow);
+  tcase_add_test (tc_chain, test_vec_deque_grow_multiple);
+  tcase_add_test (tc_chain, test_vec_deque_grow_middle);
+  tcase_add_test (tc_chain, test_vec_deque_grow_end);
+  tcase_add_test (tc_chain, test_vec_deque_drop2);
+  tcase_add_test (tc_chain, test_vec_deque_grow_from_prealloc1);
+  tcase_add_test (tc_chain, test_vec_deque_peek_pop_tail);
+  tcase_add_test (tc_chain, test_vec_deque_peek_nth);
+  tcase_add_test (tc_chain, test_vec_deque_push_sorted);
+  tcase_add_test (tc_chain, test_vec_deque_push_sorted_wrapped);
+  tcase_add_test (tc_chain, test_vec_deque_push_sorted_struct);
+  tcase_add_test (tc_chain, test_vec_deque_push_sorted_struct_wrapped);
+  tcase_add_test (tc_chain, test_vec_deque_sort);
+  tcase_add_test (tc_chain, test_vec_deque_sort_struct);
+  tcase_add_test (tc_chain, test_vec_deque_sort_wrapped);
+
+  return s;
+}
+
+
+GST_CHECK_MAIN (gst_vec_deque);
diff --git a/tests/check/gstreamer.supp b/tests/check/gstreamer.supp
index b39a40f..679fe0e 100644
--- a/tests/check/gstreamer.supp
+++ b/tests/check/gstreamer.supp
@@ -4095,3 +4095,31 @@
   ...
   fun:g_socket_create_source
 }
+
+{
+   And more dlopen work leaks
+   Memcheck:Leak
+   fun:malloc
+   ...
+   fun:dl_open_worker_begin
+   ...
+   fun:dl_open_worker
+}
+
+{
+   ducktape shows up from glib-networking calling into libproxy if there's a proxy setup, like in the CI
+   Memcheck:ReallocZero
+   fun:realloc
+   fun:duk_heap_mem_realloc_indirect.lto_priv.0
+   fun:duk_hbuffer_resize.lto_priv.0
+}
+
+{
+   And more dlopen work leaks
+   Memcheck:Leak
+   fun:malloc
+   ...
+   fun:dl_open_worker_begin
+   ...
+   fun:dl_open_worker
+}
diff --git a/tests/check/libs/gstlibscpp.cc b/tests/check/libs/gstlibscpp.cc
index bee2588..84338b7 100644
--- a/tests/check/libs/gstlibscpp.cc
+++ b/tests/check/libs/gstlibscpp.cc
@@ -21,6 +21,10 @@
 #include <config.h>
 #endif
 
+#ifdef GST_DISABLE_DEPRECATED
+#undef GST_DISABLE_DEPRECATED
+#endif
+
 #include <gst/gst.h>
 #include <gst/check/check.h>
 #include <gst/base/base.h>
diff --git a/tests/check/libs/queuearray.c b/tests/check/libs/queuearray.c
index ecce1ec..ec4ab61 100644
--- a/tests/check/libs/queuearray.c
+++ b/tests/check/libs/queuearray.c
@@ -24,6 +24,10 @@
 #include "config.h"
 #endif
 
+#ifdef GST_DISABLE_DEPRECATED
+#undef GST_DISABLE_DEPRECATED
+#endif
+
 #include <gst/gst.h>
 #include <gst/check/gstcheck.h>
 #include <gst/base/gstqueuearray.h>
diff --git a/tests/check/meson.build b/tests/check/meson.build
index 7d68212..e8419fc 100644
--- a/tests/check/meson.build
+++ b/tests/check/meson.build
@@ -20,6 +20,8 @@ core_tests = [
   [ 'gst/gstelement.c', not gst_registry or not gst_parse],
   [ 'gst/gstelementfactory.c', not gst_registry ],
   [ 'gst/gstghostpad.c', not gst_registry ],
+  [ 'gst/gstidstr.c' ],
+  [ 'gst/gstidstr-noinline.c' ],
   [ 'gst/gstinfo.c' ],
   [ 'gst/gstiterator.c' ],
   [ 'gst/gstmessage.c' ],
@@ -51,6 +53,7 @@ core_tests = [
   [ 'gst/gsturi.c' ],
   [ 'gst/gstutils.c', not gst_registry ],
   [ 'gst/gstvalue.c' ],
+  [ 'gst/gstvecdeque.c' ],
   [ 'generic/states.c', not gst_registry ],
   [ 'libs/adapter.c' ],
   [ 'libs/aggregator.c' ],
diff --git a/tests/validate/meson.build b/tests/validate/meson.build
index 11d8a7c..d6a893f 100644
--- a/tests/validate/meson.build
+++ b/tests/validate/meson.build
@@ -1,4 +1,4 @@
-gst_tester = executable('gst-tester-' + apiversion,
+gst_tester = executable('gst-tester-' + api_version,
     'gst-tester.c',
     c_args : gst_c_args,
     include_directories : [configinc],
@@ -7,7 +7,7 @@ gst_tester = executable('gst-tester-' + apiversion,
     dependencies : [gio_dep],
 )
 
-meson.override_find_program('gst-tester-' + apiversion, gst_tester)
+meson.override_find_program('gst-tester-' + api_version, gst_tester)
 
 tests = [
     'simplest',
diff --git a/tools/gst-inspect.c b/tools/gst-inspect.c
index a413340..52c802b 100644
--- a/tools/gst-inspect.c
+++ b/tools/gst-inspect.c
@@ -50,6 +50,8 @@
 #include <TargetConditionals.h>
 #endif
 
+#include "gst/glib-compat-private.h"
+
 /* "R" : support color
  * "X" : do not clear the screen when leaving the pager
  * "F" : skip the pager if content fit into the screen
@@ -180,13 +182,13 @@ n_print (const char *format, ...)
 }
 
 static gboolean
-print_field (GQuark field, const GValue * value, gpointer pfx)
+print_field (const GstIdStr * fieldname, const GValue * value, gpointer pfx)
 {
   gchar *str = gst_value_serialize (value);
 
   n_print ("%s  %s%15s%s: %s%s%s\n",
-      (gchar *) pfx, FIELD_NAME_COLOR, g_quark_to_string (field), RESET_COLOR,
-      FIELD_VALUE_COLOR, str, RESET_COLOR);
+      (gchar *) pfx, FIELD_NAME_COLOR, gst_id_str_as_str (fieldname),
+      RESET_COLOR, FIELD_VALUE_COLOR, str, RESET_COLOR);
   g_free (str);
   return TRUE;
 }
@@ -224,7 +226,7 @@ print_caps (const GstCaps * caps, const gchar * pfx)
       n_print ("%s%s%s%s\n", pfx, STRUCT_NAME_COLOR,
           gst_structure_get_name (structure), RESET_COLOR);
     }
-    gst_structure_foreach (structure, print_field, (gpointer) pfx);
+    gst_structure_foreach_id_str (structure, print_field, (gpointer) pfx);
   }
 }
 
@@ -370,6 +372,29 @@ print_interfaces (GType type)
   }
 }
 
+static void
+print_element_flags (GstElement * element)
+{
+  n_print (_("%sElement Flags%s:\n"), HEADING_COLOR, RESET_COLOR);
+
+  push_indent ();
+  if (GST_OBJECT_FLAG_IS_SET (element, GST_ELEMENT_FLAG_LOCKED_STATE))
+    n_print ("- %s%s%s\n", DATATYPE_COLOR, "LOCKED_STATE", RESET_COLOR);
+  if (GST_OBJECT_FLAG_IS_SET (element, GST_ELEMENT_FLAG_SINK))
+    n_print ("- %s%s%s\n", DATATYPE_COLOR, "SINK", RESET_COLOR);
+  if (GST_OBJECT_FLAG_IS_SET (element, GST_ELEMENT_FLAG_SOURCE))
+    n_print ("- %s%s%s\n", DATATYPE_COLOR, "SOURCE", RESET_COLOR);
+  if (GST_OBJECT_FLAG_IS_SET (element, GST_ELEMENT_FLAG_PROVIDE_CLOCK))
+    n_print ("- %s%s%s\n", DATATYPE_COLOR, "PROVIDE_CLOCK", RESET_COLOR);
+  if (GST_OBJECT_FLAG_IS_SET (element, GST_ELEMENT_FLAG_REQUIRE_CLOCK))
+    n_print ("- %s%s%s\n", DATATYPE_COLOR, "REQUIRE_CLOCK", RESET_COLOR);
+  if (GST_OBJECT_FLAG_IS_SET (element, GST_ELEMENT_FLAG_INDEXABLE))
+    n_print ("- %s%s%s\n", DATATYPE_COLOR, "REQUIRE_INDEXABLE", RESET_COLOR);
+  pop_indent ();
+
+  n_print ("\n");
+}
+
 static gchar *
 flags_to_string (GFlagsValue * vals, guint flags)
 {
@@ -427,9 +452,10 @@ print_object_properties_info (GObject * obj, GObjectClass * obj_class,
   guint num_properties, i;
   gboolean readable;
   gboolean first_flag;
+  gboolean is_tracer = GST_IS_TRACER (obj);
 
   property_specs = g_object_class_list_properties (obj_class, &num_properties);
-  g_qsort_with_data (property_specs, num_properties, sizeof (gpointer),
+  g_sort_array (property_specs, num_properties, sizeof (gpointer),
       (GCompareDataFunc) sort_gparamspecs, NULL);
 
   n_print ("%s%s%s:\n", HEADING_COLOR, desc, RESET_COLOR);
@@ -447,6 +473,10 @@ print_object_properties_info (GObject * obj, GObjectClass * obj_class,
             || owner_type == GST_TYPE_OBJECT || owner_type == GST_TYPE_PAD))
       continue;
 
+    if (is_tracer && !g_strcmp0 (param->name, "params")) {
+      continue;
+    }
+
     g_value_init (&value, param->value_type);
 
     n_print ("%s%-20s%s: %s%s%s\n", PROP_NAME_COLOR,
@@ -717,7 +747,7 @@ print_object_properties_info (GObject * obj, GObjectClass * obj_class,
             const GstStructure *s = gst_value_get_structure (&value);
             if (s) {
               g_print ("\n");
-              gst_structure_foreach (s, print_field,
+              gst_structure_foreach_id_str (s, print_field,
                   (gpointer) "                           ");
             }
           }
@@ -1797,6 +1827,7 @@ print_element_info (GstPluginFeature * feature, gboolean print_names)
 
   print_hierarchy (G_OBJECT_TYPE (element), 0, &maxlevel);
   print_interfaces (G_OBJECT_TYPE (element));
+  print_element_flags (element);
 
   print_pad_templates_info (element, factory);
   print_clocking_info (element);
@@ -1912,6 +1943,15 @@ print_tracer_info (GstPluginFeature * feature, gboolean print_names)
 
   print_hierarchy (G_OBJECT_TYPE (tracer), 0, &maxlevel);
   print_interfaces (G_OBJECT_TYPE (tracer));
+  print_object_properties_info (G_OBJECT (tracer),
+      G_OBJECT_GET_CLASS (tracer), "Tracer Properties");
+
+  n_print ("\n%sNOTE: those properties can be set using the `GST_TRACERS`"
+      " environment variable as follow:%s"
+      "\n\n    $ %sGST_TRACERS%s=\"%s%s%s(%sproperty1-name%s=value1,%sproperty2-name%s=value2));....\"",
+      HEADING_COLOR, RESET_COLOR, DATATYPE_COLOR, RESET_COLOR,
+      HEADING_COLOR, GST_OBJECT_NAME (factory), RESET_COLOR,
+      PROP_NAME_COLOR, RESET_COLOR, PROP_NAME_COLOR, RESET_COLOR);
 
   /* TODO: list what hooks it registers
    * - the data is available in gsttracerutils, we need to iterate the
diff --git a/tools/gst-launch-1.0.1 b/tools/gst-launch-1.0.1
index 8e2dd75..f54bf83 100644
--- a/tools/gst-launch-1.0.1
+++ b/tools/gst-launch-1.0.1
@@ -18,8 +18,10 @@ For a complete description of possible PIPELINE-DESCRIPTIONS see the section
 
 Please note that \fIgst\-launch\-1.0\fP is primarily a debugging tool for
 developers and users. You should not build applications on top of it. For
-applications, use the gst_parse_launch() function of the GStreamer API as an
-easy way to construct pipelines from pipeline descriptions.
+applications, write a little python script or Rust application (or use whatever
+other programming language you prefer) and use the gst_parse_launch() function
+of the GStreamer API as an easy way to construct pipelines from pipeline
+descriptions.
 .
 .SH "OPTIONS"
 .l
@@ -43,28 +45,22 @@ Output tags (also known as metadata)
 .B  \-e, \-\-eos\-on\-shutdown
 Force an EOS event on sources before shutting the pipeline down. This is
 useful to make sure muxers create readable files when a muxing pipeline is
-shut down forcefully via Control-C.
-.TP 8
-.B  \-i, \-\-index
-Gather and print index statistics. This is mostly useful for playback or
-recording pipelines.
+shut down forcefully via Control-C (especially in case of `mp4mux` and `qtmux`
+where the created file will be unreadable if the file has not been finalised
+properly).
 .TP 8
 .B  \-f, \-\-no\-fault
-Do not install a fault handler
-.TP 8
-.B  \-T, \-\-trace
-Print memory allocation traces. The feature must be enabled at compile time to
-work.
+Do not install a segfault handler
 .TP 8
 .B  \-\-no\-position
-Do not print current position of pipeline.
+Do not print the current position of pipeline.
 If this option is unspecified, the position will be printed when stdout is a TTY.
 To enable printing position when stdout is not a TTY,
-use "force-position" option.
+use the "\-\-force-position" option.
 .TP 8
 .B  \-\-force\-position
-Allow printing current position of pipeline even if stdout is not a TTY.
-This option has no effect if the "no-position" option is specified.
+Allow printing the current position of pipeline even if stdout is not a TTY.
+This option has no effect if the "\-\-no-position" option is specified.
 .TP 8
 
 .
@@ -242,16 +238,22 @@ Lists use this format:      { VALUE \fI[, VALUE ...]\fR }
 
 The examples below assume that you have the correct plug-ins available.
 In general, "pulsesink" can be substituted with another audio output
-plug-in such as "alsasink" or "osxaudiosink"
-Likewise, "xvimagesink" can be substituted with "ximagesink", "glimagesink",
-or "osxvideosink". Keep in mind though that different sinks might
-accept different formats and even the same sink might accept different formats
-on different machines, so you might need to add converter elements like
-audioconvert and audioresample (for audio) or videoconvert (for video)
-in front of the sink to make things work.
+plug-in such as "alsasink", "osxaudiosink" or "wasapisink".
+.br
+Likewise, "xvimagesink" can be substituted with "d3dvideosink", "ximagesink",
+"glimagesink", or "osxvideosink".
+.br
+Keep in mind though that different sinks might accept different formats and
+even the same sink might accept different formats on different machines, so
+you might need to add converter elements like audioconvert and audioresample
+(for audio) or videoconvertscale (for video) in front of the sink to make
+things work.
 
 .B Audio playback
 
+Note: For audio/video playback it's best to use the playbin3 or
+uridecodebin3 elements, these are just example pipelines.
+.br
 Play the mp3 music file "music.mp3" using a libmpg123-based plug-in and
 output to an Pulseaudio device
 .br
@@ -301,17 +303,17 @@ Convert a .WAV file containing raw audio data into an Ogg Vorbis or mp3 file
         gst\-launch\-1.0 filesrc location=music.wav ! wavparse ! audioconvert ! vorbisenc ! oggmux ! filesink location=music.ogg
 .br
 .B
-        gst\-launch\-1.0 filesrc location=music.wav ! wavparse ! audioconvert ! lamemp3enc ! filesink location=music.mp3
+        gst\-launch\-1.0 filesrc location=music.wav ! wavparse ! audioconvert ! lamemp3enc ! xingmux ! id3v2mux ! filesink location=music.mp3
 
 Rips all tracks from compact disc and convert them into a single mp3 file
 .br
 .B
-        gst\-launch\-1.0 cdparanoiasrc mode=continuous ! audioconvert ! lamemp3enc ! mpegaudioparse ! id3v2mux ! filesink location=cd.mp3
+        gst\-launch\-1.0 cdparanoiasrc mode=continuous ! audioconvert ! lamemp3enc ! mpegaudioparse ! xingmux ! id3v2mux ! filesink location=cd.mp3
 
 Rips track 5 from the CD and converts it into a single mp3 file
 .br
 .B
-        gst\-launch\-1.0 cdparanoiasrc track=5 ! audioconvert ! lamemp3enc ! mpegaudioparse ! id3v2mux ! filesink location=track5.mp3
+        gst\-launch\-1.0 cdparanoiasrc track=5 ! audioconvert ! lamemp3enc ! mpegaudioparse ! xingmux ! id3v2mux ! filesink location=track5.mp3
 
 Using \fBgst\-inspect\-1.0\fR(1), it is possible to discover settings like the above
 for cdparanoiasrc that will tell it to rip the entire cd or only tracks of it.
@@ -327,38 +329,38 @@ Records sound from your audio input and encodes it into an ogg file
 
 .B Video
 
-Display only the video portion of an MPEG-1 video file, outputting to
+Note: For audio/video playback it's best to use the playbin3 or
+uridecodebin3 elements, these are just example pipelines.
+.br
+Display only the video portion of an MPEG-2 PS video file, outputting to
 an X display window
 .br
 .B
-        gst\-launch\-1.0 filesrc location=JB_FF9_TheGravityOfLove.mpg ! dvddemux ! mpegvideoparse ! mpeg2dec ! xvimagesink
+        gst\-launch\-1.0 filesrc location=JB_FF9_TheGravityOfLove.mpg ! mpegdemux ! mpegvideoparse ! mpeg2dec ! videoconvert ! xvimagesink
 
 Display the video portion of a .vob file (used on DVDs), outputting to
 an SDL window
 .br
 .B
-        gst\-launch\-1.0 filesrc location=/flflfj.vob ! dvddemux ! mpegvideoparse ! mpeg2dec ! sdlvideosink
+        gst\-launch\-1.0 filesrc location=/flflfj.vob ! dvddemux ! mpegvideoparse ! mpeg2dec ! videoconvert ! sdlvideosink
 
 Play both video and audio portions of an MPEG movie
 .br
 .B
-        gst\-launch\-1.0 filesrc location=movie.mpg ! dvddemux name=demuxer  demuxer. ! queue ! mpegvideoparse ! mpeg2dec ! sdlvideosink  demuxer. ! queue ! mpegaudioparse ! mpg123audiodec ! audioconvert ! audioresample ! pulsesink
+        gst\-launch\-1.0 filesrc location=movie.mpg ! dvddemux name=demuxer  demuxer. ! queue ! mpegvideoparse ! mpeg2dec ! videoconvert ! sdlvideosink  demuxer. ! queue ! mpegaudioparse ! mpg123audiodec ! audioconvert ! audioresample ! pulsesink
 
 Play an AVI movie with an external text subtitle stream
 .br
-.B
-        gst\-launch\-1.0 filesrc location=movie.mpg ! mpegdemux name=demuxer demuxer. ! queue ! mpegvideoparse ! mpeg2dec ! videoconvert ! sdlvideosink   demuxer. ! queue ! mpegaudioparse ! mpg123audiodec ! audioconvert ! audioresample ! pulsesink
-
 This example also shows how to refer to specific pads by name if an element
 (here: textoverlay) has multiple sink or source pads.
 .br
 .B
-        gst\-launch\-1.0 textoverlay name=overlay ! videoconvert ! videoscale !  autovideosink   filesrc location=movie.avi ! decodebin ! videoconvert ! overlay.video_sink   filesrc location=movie.srt ! subparse ! overlay.text_sink
+        gst\-launch\-1.0 textoverlay name=overlay ! videoconvert ! videoscale !  autovideosink   filesrc location=movie.avi ! decodebin3 ! videoconvert ! overlay.video_sink   filesrc location=movie.srt ! subparse ! overlay.text_sink
 
-Play an AVI movie with an external text subtitle stream using playbin
+Play an AVI movie with an external text subtitle stream using playbin3
 .br
 .B
-        gst\-launch\-1.0 playbin uri=file:///path/to/movie.avi suburi=file:///path/to/movie.srt
+        gst\-launch\-1.0 playbin3 uri=file:///path/to/movie.avi suburi=file:///path/to/movie.srt
 
 .B Network streaming
 
@@ -367,19 +369,19 @@ Stream video using RTP and network elements.
 This command would be run on the transmitter
 .br
 .B
-        gst\-launch\-1.0 v4l2src ! video/x\-raw,width=128,height=96,format=UYVY ! videoconvert ! ffenc_h263 ! video/x\-h263 ! rtph263ppay pt=96 ! udpsink host=192.168.1.1 port=5000
+        gst\-launch\-1.0 v4l2src ! queue ! videoconvert ! x264enc tune=zerolatency key-int-max=15 ! video/x\-h264,profile=main !rtph264pay pt=96 config-interval=-1 ! udpsink host=192.168.1.1 port=5000
 
 Use this command on the receiver
 .br
 .B
-        gst\-launch\-1.0 udpsrc port=5000 ! application/x\-rtp, clock\-rate=90000,payload=96 ! rtph263pdepay queue\-delay=0 ! ffdec_h263 ! xvimagesink
+        gst\-launch\-1.0 udpsrc port=5000 ! application/x\-rtp, clock\-rate=90000,payload=96 ! rtpjitterbuffer ! rtph264depay ! h264parse ! avdec_h264 ! videoconvert ! xvimagesink
 
 .B Diagnostic
 
 Generate a null stream and ignore it (and print out details).
 .br
 .B
-        gst\-launch\-1.0 \-v fakesrc num\-buffers=16 ! fakesink
+        gst\-launch\-1.0 \-v fakesrc num\-buffers=16 ! fakesink silent=false
 
 Generate a pure sine tone to test the audio output
 .br
@@ -402,17 +404,19 @@ to get a working pipeline.
 Play any supported audio format
 .br
 .B
-        gst\-launch\-1.0 filesrc location=musicfile ! decodebin ! audioconvert ! audioresample ! pulsesink
+        gst\-launch\-1.0 filesrc location=musicfile ! decodebin3 ! audioconvert ! audioresample ! pulsesink
 
 Play any supported video format with video and audio output. Threads are used
 automatically. To make this even easier, you can use the playbin element:
 .br
 .B
-        gst\-launch\-1.0 filesrc location=videofile ! decodebin name=decoder decoder. ! queue ! audioconvert ! audioresample ! pulsesink   decoder. !  videoconvert ! xvimagesink
+        gst\-launch\-1.0 filesrc location=videofile ! decodebin3 name=decoder decoder. ! queue ! audioconvert ! audioresample ! pulsesink   decoder. !  videoconvert ! xvimagesink
 .br
 .B
-        gst\-launch\-1.0 playbin uri=file:///home/joe/foo.avi
-
+        gst\-launch\-1.0 playbin3 uri=file:///home/joe/foo.avi
+.br
+.B
+        gst\-launch\-1.0 playbin3 uri=https://gstreamer.freedesktop.org/data/media/sintel_trailer\-480p.webm
 
 .B Filtered connections
 
@@ -422,6 +426,9 @@ Show a test image and use the YUY2 or YV12 video format for this.
 .br
 .B
         gst\-launch\-1.0 videotestsrc ! 'video/x\-raw,format=YUY2;video/x\-raw,format=YV12' ! xvimagesink
+.br
+.B
+        gst\-launch\-1.0 v4l2src ! image/jpeg ! queue ! decodebin3 ! videoconvert ! autovideosink
 
 Record audio and write it to a .wav file. Force usage of signed 16 to 32 bit
 samples and a sample rate between 32kHz and 64KHz.
@@ -451,12 +458,13 @@ which allows you to view the .dot file directly without converting it first.
 .br
 When the pipeline changes state through NULL to PLAYING and back to NULL, a
 dot file is generated on each state change. To write a snapshot of the
-pipeline state, send a SIGHUP to the process.
+pipeline state, send a SIGHUP to the process or use the pipeline_snapshot
+tracer from the GStreamer Rust plugins.
 .TP
 \fBGST_REGISTRY\fR
 Path of the plugin registry file. Default is
 ~/.cache/gstreamer\-1.0/registry\-CPU.bin where CPU is the
-machine/cpu type GStreamer was compiled for, e.g. 'i486', 'i686', 'x86\-64', 'ppc',
+machine/cpu type GStreamer was compiled for, e.g. 'x86\_64',
 etc. (check the output of "uname \-i" and "uname \-m" for details).
 .TP
 \fBGST_REGISTRY_UPDATE\fR
@@ -477,8 +485,8 @@ user's home directory
 .TP
 \fBGST_DEBUG_FILE\fR
 Set this variable to a file path to redirect all GStreamer debug
-messages to this file. If left unset, debug messages with be output
-unto the standard error.
+messages to this file. If left unset, debug messages will be output
+to the standard error output.
 .TP
 \fBORC_CODE\fR
 Useful Orc environment variable. Set ORC_CODE=debug to enable debuggers
diff --git a/tools/meson.build b/tools/meson.build
index 04eedfe..ed4e9bb 100644
--- a/tools/meson.build
+++ b/tools/meson.build
@@ -20,7 +20,7 @@ if gst_parse
 endif
 
 foreach tool : tools
-  exe_name = '@0@-@1@'.format(tool, apiversion)
+  exe_name = '@0@-@1@'.format(tool, api_version)
   src_file = '@0@.c'.format(tool)
   extra_deps = []
   extra_c_args = []
-- 
GitLab


From 578d4aacc531cdf2563b2474d7086db05dcbb976 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Dylan=20A=C3=AFssi?= <dylan.aissi@collabora.com>
Date: Wed, 26 Mar 2025 14:32:57 +0100
Subject: [PATCH 2/4] copyright.yml: add license of cmake/FindGStreamer.cmake
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Dylan Aïssi <dylan.aissi@collabora.com>
---
 debian/apertis/copyright.yml | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/debian/apertis/copyright.yml b/debian/apertis/copyright.yml
index 11345d7..698789f 100644
--- a/debian/apertis/copyright.yml
+++ b/debian/apertis/copyright.yml
@@ -8,3 +8,5 @@ tests/benchmarks/mass-elements.scm:
     override-license: LGPL-2.1+
 tests/misc/network-clock.scm:
     override-license: GPL-2
+cmake/FindGStreamer.cmake:
+    license: LGPL-2.1+
-- 
GitLab


From c2bc0e6b949e36fef360b6a0576024d8e8bf9f93 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Dylan=20A=C3=AFssi?= <devel@lists.apertis.org>
Date: Wed, 26 Mar 2025 13:29:30 +0000
Subject: [PATCH 3/4] Release gstreamer1.0 version 1.26.0-1+apertis1
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Dylan Aïssi <dylan.aissi@collabora.com>
---
 debian/changelog | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/debian/changelog b/debian/changelog
index 3817fc8..fcf703c 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,12 @@
+gstreamer1.0 (1.26.0-1+apertis1) apertis; urgency=medium
+
+  * Sync from debian/trixie.
+  * Remaining Apertis specific changes:
+    - Drop dependency on LGPL-3 libdw, only used for better backtraces.
+  * copyright.yml: add license of cmake/FindGStreamer.cmake
+
+ -- Apertis CI <devel@lists.apertis.org>  Wed, 26 Mar 2025 13:29:30 +0000
+
 gstreamer1.0 (1.26.0-1) unstable; urgency=medium
 
   * Revert "d/watch: pin on 1.24.x"
-- 
GitLab


From b32c4adb8a453d9fea4d81a03a52a806edd70567 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Dylan=20A=C3=AFssi?= <dylan.aissi@collabora.com>
Date: Wed, 26 Mar 2025 13:34:32 +0000
Subject: [PATCH 4/4] Refresh the automatically detected licensing information
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Dylan Aïssi <dylan.aissi@collabora.com>
---
 debian/apertis/copyright | 54 ++++++++++++++++++++++++----------------
 1 file changed, 33 insertions(+), 21 deletions(-)

diff --git a/debian/apertis/copyright b/debian/apertis/copyright
index cb87211..3b36d47 100644
--- a/debian/apertis/copyright
+++ b/debian/apertis/copyright
@@ -8,12 +8,16 @@ Files: NEWS
 Copyright: no-info-found
 License: CC-BY-SA-4.0
 
+Files: cmake/FindGStreamer.cmake
+Copyright: 2024, L. E. Segovia <amy@centricular.com>
+License: LGPL-2.1+
+
 Files: data/bash-completion/*
 Copyright: 2015, Mathieu Duponchelle <mathieu.duponchelle@opencreed.com>
 License: LGPL-2+
 
 Files: debian/gst-codec-info.c
-Copyright: 2007-2010, 2014, 2015, Sebastian Dröge <sebastian@centricular.com>
+Copyright: 2007-2010, 2014, 2015, 2024, Sebastian Dröge <sebastian@centricular.com>
 License: LGPL-2+
 
 Files: docs/*
@@ -28,14 +32,6 @@ Files: docs/gst/overview.md
 Copyright: no-info-found
 License: LGPL
 
-Files: docs/index.md
-Copyright: no-info-found
-License: LGPL
-
-Files: docs/plugins/gst_plugins_cache.json
-Copyright: no-info-found
-License: LGPL
-
 Files: docs/random/typefind
 Copyright: Ronald Bultje, 2003, <rbultje@ronald.bitfreak.net> under the
 License: GFDL
@@ -79,6 +75,7 @@ Copyright: 2004-2012, 2014, Wim Taymans <wim.taymans@gmail.com>
 License: LGPL-2+
 
 Files: gst/gstatomicqueue.c
+ gst/gstvecdeque.h
 Copyright: 2006, 2009, 2010, Edward Hervey <bilboed@bilboed.com>
 License: LGPL-2+
 
@@ -148,7 +145,10 @@ License: LGPL-2+
 
 Files: gst/gstcontrolsource.c
  gst/gstcontrolsource.h
-Copyright: 2007-2010, 2014, 2015, Sebastian Dröge <sebastian@centricular.com>
+ gst/gstidstr-private.h
+ gst/gstidstr.c
+ gst/gstidstr.h
+Copyright: 2007-2010, 2014, 2015, 2024, Sebastian Dröge <sebastian@centricular.com>
 License: LGPL-2+
 
 Files: gst/gstdatetime.c
@@ -169,9 +169,7 @@ Files: gst/gstdynamictypefactory.c
  gst/gstdynamictypefactory.h
  gst/gstpluginloader.c
  gst/gstpluginloader.h
- gst/gstquark.c
- gst/gstquark.h
-Copyright: 2005, 2006, 2008, 2014, 2015, Jan Schmidt <jan@centricular.com>
+Copyright: 2005, 2008, 2014, 2015, Jan Schmidt <jan@centricular.com>
 License: LGPL-2+
 
 Files: gst/gsterror.h
@@ -277,6 +275,11 @@ Copyright: 2014, David Waring, British Broadcasting Corporation
  1999, 2000, Erik Walthinsen <omega@cse.ogi.edu>
 License: BSD-3-clause or LGPL-2+
 
+Files: gst/gstvecdeque.c
+Copyright: 2015, Tim-Philipp Müller <tim centricular net>
+ 2009, Edward Hervey <bilboed@bilboed.com>
+License: LGPL-2+
+
 Files: gst/printf/*
 Copyright: 1999, 2000, 2002, 2003, Free Software Foundation, Inc.
 License: LGPL-2+
@@ -332,7 +335,7 @@ License: LGPL-2+
 
 Files: libs/gst/base/gstbitreader-docs.h
  libs/gst/base/gstbytewriter-docs.h
-Copyright: 2007-2010, 2014, 2015, Sebastian Dröge <sebastian@centricular.com>
+Copyright: 2007-2010, 2014, 2015, 2024, Sebastian Dröge <sebastian@centricular.com>
 License: LGPL-2+
 
 Files: libs/gst/base/gstbitreader.c
@@ -457,7 +460,7 @@ Copyright: 2013, Haakon Sporsheim <haakon@pexip.com>
 License: LGPL-2+
 
 Files: libs/gst/controller/*
-Copyright: 2007-2010, 2014, 2015, Sebastian Dröge <sebastian@centricular.com>
+Copyright: 2007-2010, 2014, 2015, 2024, Sebastian Dröge <sebastian@centricular.com>
 License: LGPL-2+
 
 Files: libs/gst/controller/controller-prelude.h
@@ -486,7 +489,7 @@ Copyright: 2015, Mathieu Duponchelle <mathieu.duponchelle@opencreed.com>
 License: LGPL-2+
 
 Files: libs/gst/helpers/gst-plugin-scanner.c
-Copyright: 2005, 2006, 2008, 2014, 2015, Jan Schmidt <jan@centricular.com>
+Copyright: 2005, 2008, 2014, 2015, Jan Schmidt <jan@centricular.com>
 License: LGPL-2+
 
 Files: libs/gst/helpers/gst_gdb.py
@@ -549,7 +552,7 @@ License: LGPL-2+
 
 Files: libs/gst/net/gstptpclock.c
  libs/gst/net/gstptpclock.h
-Copyright: 2007-2010, 2014, 2015, Sebastian Dröge <sebastian@centricular.com>
+Copyright: 2007-2010, 2014, 2015, 2024, Sebastian Dröge <sebastian@centricular.com>
 License: LGPL-2+
 
 Files: libs/gst/net/net-prelude.h
@@ -569,7 +572,7 @@ License: LGPL-2+
 
 Files: plugins/elements/gstconcat.c
  plugins/elements/gstconcat.h
-Copyright: 2007-2010, 2014, 2015, Sebastian Dröge <sebastian@centricular.com>
+Copyright: 2007-2010, 2014, 2015, 2024, Sebastian Dröge <sebastian@centricular.com>
 License: LGPL-2+
 
 Files: plugins/elements/gstcoreelementselements.h
@@ -886,7 +889,12 @@ License: LGPL-2+
 
 Files: tests/check/gst/gstevent.c
  tests/check/gst/gstsegment.c
-Copyright: 2005, 2006, 2008, 2014, 2015, Jan Schmidt <jan@centricular.com>
+Copyright: 2005, 2008, 2014, 2015, Jan Schmidt <jan@centricular.com>
+License: LGPL-2+
+
+Files: tests/check/gst/gstidstr-noinline.c
+ tests/check/gst/gstidstr.c
+Copyright: 2007-2010, 2014, 2015, 2024, Sebastian Dröge <sebastian@centricular.com>
 License: LGPL-2+
 
 Files: tests/check/gst/gstiterator.c
@@ -962,6 +970,10 @@ Copyright: <2005> Thomas Vander Stichele <thomas at apestaart dot org>
  <2004> David Schleef <david at schleef dot org>
 License: LGPL-2+
 
+Files: tests/check/gst/gstvecdeque.c
+Copyright: <2009> Edward Hervey <bilboed@bilboed.com>
+License: LGPL-2+
+
 Files: tests/check/libs/adapter.c
 Copyright: <2005> Wim Taymans <wim at fluendo dot com>
 License: LGPL-2+
@@ -1076,11 +1088,11 @@ Copyright: 2004-2012, 2014, Wim Taymans <wim.taymans@gmail.com>
 License: LGPL-2+
 
 Files: tests/examples/netclock/netclock-server.c
-Copyright: 2005, 2006, 2008, 2014, 2015, Jan Schmidt <jan@centricular.com>
+Copyright: 2005, 2008, 2014, 2015, Jan Schmidt <jan@centricular.com>
 License: LGPL-2+
 
 Files: tests/examples/ptp/ptp-print-times.c
-Copyright: 2007-2010, 2014, 2015, Sebastian Dröge <sebastian@centricular.com>
+Copyright: 2007-2010, 2014, 2015, 2024, Sebastian Dröge <sebastian@centricular.com>
 License: LGPL-2+
 
 Files: tests/examples/streams/testrtpool.c
-- 
GitLab