From 0ef396359c9d90f403cd5f7838c1d977b723cca0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= <sebastian@centricular.com>
Date: Thu, 18 Apr 2024 17:07:25 +0300
Subject: [PATCH] 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>
---
 girs/Gst-1.0.gir                              | 491 +++++++++
 girs/GstBase-1.0.gir                          |  89 +-
 .../gst-docs/symbols/symbol_index.json        |   4 +
 .../gst-libs/gst/codecs/gstav1decoder.c       |  16 +-
 .../gst-libs/gst/codecs/gsth264decoder.c      |  16 +-
 .../gst-libs/gst/codecs/gsth265decoder.c      |  16 +-
 .../gst-libs/gst/codecs/gstmpeg2decoder.c     |  18 +-
 .../gst-libs/gst/codecs/gstvp8decoder.c       |  16 +-
 .../gst-libs/gst/codecs/gstvp9decoder.c       |  16 +-
 .../gst/d3d12/gstd3d12fencedatapool.cpp       |  12 +-
 .../codectimestamper/gstcodectimestamper.c    |  24 +-
 .../gst/mpegpsmux/psmuxstream.c               |   2 +-
 .../gst-plugins-bad/sys/aja/gstajacommon.cpp  |  16 +-
 .../gst-plugins-bad/sys/aja/gstajacommon.h    |   2 +-
 .../gst-plugins-bad/sys/aja/gstajasink.cpp    |  32 +-
 .../gst-plugins-bad/sys/aja/gstajasink.h      |   2 +-
 .../gst-plugins-bad/sys/aja/gstajasrc.cpp     |  40 +-
 .../gst-plugins-bad/sys/aja/gstajasrc.h       |   2 +-
 .../gst-plugins-bad/sys/applemedia/vtdec.c    |  23 +-
 .../gst-plugins-bad/sys/applemedia/vtdec.h    |   2 +-
 .../gst-plugins-bad/sys/applemedia/vtenc.c    |  18 +-
 .../gst-plugins-bad/sys/applemedia/vtenc.h    |   2 +-
 .../sys/d3d12/gstd3d12decoder.cpp             |  16 +-
 .../sys/d3d12/gstd3d12encoder.cpp             |  15 +-
 .../sys/decklink/gstdecklink.cpp              |  16 +-
 .../sys/decklink/gstdecklinkaudiosrc.cpp      |  26 +-
 .../sys/decklink/gstdecklinkaudiosrc.h        |   2 +-
 .../sys/decklink/gstdecklinkvideosrc.cpp      |  28 +-
 .../sys/decklink/gstdecklinkvideosrc.h        |   2 +-
 .../sys/mediafoundation/gstmfcapturewinrt.cpp |  16 +-
 .../sys/mediafoundation/gstmfsourcereader.cpp |  16 +-
 .../sys/v4l2codecs/gstv4l2decoder.c           |  36 +-
 .../gst-plugins-bad/sys/va/gstvabaseenc.c     |  20 +-
 .../gst-plugins-bad/sys/va/gstvabaseenc.h     |   3 +-
 .../gst-libs/gst/app/gstappsink.c             |  18 +-
 .../gst-libs/gst/app/gstappsrc.c              |  58 +-
 .../gst-libs/gst/rtsp/gstrtspconnection.c     |  30 +-
 .../gst-libs/gst/video/video-converter.c      |  22 +-
 .../gst/compositor/compositor.c               |  10 +-
 .../gst/compositor/compositor.h               |   2 +-
 .../adaptivedemux2/gstadaptivedemux-track.c   |  31 +-
 .../ext/adaptivedemux2/gstadaptivedemux.c     |   4 +-
 .../ext/adaptivedemux2/gstadaptivedemux.h     |   2 +-
 .../ext/mpg123/gstmpg123audiodec.c            |  12 +-
 .../ext/mpg123/gstmpg123audiodec.h            |   2 +-
 .../gst/multifile/gstsplitmuxsink.c           |  18 +-
 .../gst/multifile/gstsplitmuxsink.h           |   2 +-
 .../gst-plugins-good/sys/osxaudio/gstatenc.c  |  12 +-
 .../gst-plugins-good/sys/osxaudio/gstatenc.h  |   2 +-
 .../gst/rtsp-server/rtsp-stream-transport.c   |  22 +-
 subprojects/gstreamer/gst/gst.h               |   1 +
 subprojects/gstreamer/gst/gstvecdeque.c       | 994 ++++++++++++++++++
 subprojects/gstreamer/gst/gstvecdeque.h       | 129 +++
 subprojects/gstreamer/gst/meson.build         |   2 +
 .../gstreamer/libs/gst/base/base-prelude.h    |  12 +
 .../gstreamer/libs/gst/base/gstadapter.c      |  68 +-
 .../gstreamer/libs/gst/base/gstdataqueue.c    |  26 +-
 .../gstreamer/libs/gst/base/gstqueuearray.c   | 588 +----------
 .../gstreamer/libs/gst/base/gstqueuearray.h   |  54 +-
 .../gstreamer/plugins/elements/gstqueue.c     |  26 +-
 .../gstreamer/plugins/elements/gstqueue.h     |   2 +-
 .../gstreamer/plugins/elements/gstqueue2.c    |  16 +-
 .../gstreamer/plugins/elements/gstqueue2.h    |   2 +-
 .../gstreamer/tests/check/gst/gstvecdeque.c   | 639 +++++++++++
 .../gstreamer/tests/check/libs/gstlibscpp.cc  |   4 +
 .../gstreamer/tests/check/libs/queuearray.c   |   4 +
 subprojects/gstreamer/tests/check/meson.build |   1 +
 67 files changed, 2853 insertions(+), 1017 deletions(-)
 create mode 100644 subprojects/gstreamer/gst/gstvecdeque.c
 create mode 100644 subprojects/gstreamer/gst/gstvecdeque.h
 create mode 100644 subprojects/gstreamer/tests/check/gst/gstvecdeque.c

diff --git a/girs/Gst-1.0.gir b/girs/Gst-1.0.gir
index 4034125c3b..fc20cab5c1 100644
--- a/girs/Gst-1.0.gir
+++ b/girs/Gst-1.0.gir
@@ -49768,6 +49768,463 @@ Free-function: g_free</doc>
         </array>
       </field>
     </record>
+    <record name="VecDeque" c:type="GstVecDeque" disguised="1" version="1.26" introspectable="0">
+      <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvecdeque.c">#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.</doc>
+      <source-position filename="../subprojects/gstreamer/gst/gstvecdeque.h"/>
+      <method name="clear" c:identifier="gst_vec_deque_clear" version="1.26" introspectable="0">
+        <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvecdeque.c">Clears queue @array and frees all memory associated to it.</doc>
+        <source-position filename="../subprojects/gstreamer/gst/gstvecdeque.h"/>
+        <return-value transfer-ownership="none">
+          <type name="none" c:type="void"/>
+        </return-value>
+        <parameters>
+          <instance-parameter name="array" transfer-ownership="none">
+            <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvecdeque.c">a #GstVecDeque object</doc>
+            <type name="VecDeque" c:type="GstVecDeque*"/>
+          </instance-parameter>
+        </parameters>
+      </method>
+      <method name="drop_element" c:identifier="gst_vec_deque_drop_element" version="1.26" introspectable="0">
+        <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvecdeque.c">Drops the queue element at position @idx from queue @array.</doc>
+        <source-position filename="../subprojects/gstreamer/gst/gstvecdeque.h"/>
+        <return-value transfer-ownership="none" nullable="1">
+          <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvecdeque.c">the dropped element</doc>
+          <type name="gpointer" c:type="gpointer"/>
+        </return-value>
+        <parameters>
+          <instance-parameter name="array" transfer-ownership="none">
+            <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvecdeque.c">a #GstVecDeque object</doc>
+            <type name="VecDeque" c:type="GstVecDeque*"/>
+          </instance-parameter>
+          <parameter name="idx" transfer-ownership="none">
+            <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvecdeque.c">index to drop</doc>
+            <type name="gsize" c:type="gsize"/>
+          </parameter>
+        </parameters>
+      </method>
+      <method name="drop_struct" c:identifier="gst_vec_deque_drop_struct" version="1.26" introspectable="0">
+        <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvecdeque.c">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).</doc>
+        <source-position filename="../subprojects/gstreamer/gst/gstvecdeque.h"/>
+        <return-value transfer-ownership="none">
+          <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvecdeque.c">TRUE on success, or FALSE on error</doc>
+          <type name="gboolean" c:type="gboolean"/>
+        </return-value>
+        <parameters>
+          <instance-parameter name="array" transfer-ownership="none">
+            <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvecdeque.c">a #GstVecDeque object</doc>
+            <type name="VecDeque" c:type="GstVecDeque*"/>
+          </instance-parameter>
+          <parameter name="idx" transfer-ownership="none">
+            <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvecdeque.c">index to drop</doc>
+            <type name="gsize" c:type="gsize"/>
+          </parameter>
+          <parameter name="p_struct" transfer-ownership="none" nullable="1" allow-none="1">
+            <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvecdeque.c">address into which to store the data of the dropped structure, or NULL</doc>
+            <type name="gpointer" c:type="gpointer"/>
+          </parameter>
+        </parameters>
+      </method>
+      <method name="find" c:identifier="gst_vec_deque_find" version="1.26" introspectable="0">
+        <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvecdeque.c">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.</doc>
+        <source-position filename="../subprojects/gstreamer/gst/gstvecdeque.h"/>
+        <return-value transfer-ownership="none">
+          <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvecdeque.c">Index of the found element or -1 if nothing was found.</doc>
+          <type name="gsize" c:type="gsize"/>
+        </return-value>
+        <parameters>
+          <instance-parameter name="array" transfer-ownership="none">
+            <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvecdeque.c">a #GstVecDeque object</doc>
+            <type name="VecDeque" c:type="GstVecDeque*"/>
+          </instance-parameter>
+          <parameter name="func" transfer-ownership="none" nullable="1" allow-none="1" closure="1">
+            <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvecdeque.c">comparison function, or %NULL to find @data by value</doc>
+            <type name="GLib.CompareFunc" c:type="GCompareFunc"/>
+          </parameter>
+          <parameter name="data" transfer-ownership="none" nullable="1" allow-none="1">
+            <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvecdeque.c">data for comparison function</doc>
+            <type name="gpointer" c:type="gpointer"/>
+          </parameter>
+        </parameters>
+      </method>
+      <method name="free" c:identifier="gst_vec_deque_free" version="1.26" introspectable="0">
+        <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvecdeque.c">Frees queue @array and all memory associated to it.</doc>
+        <source-position filename="../subprojects/gstreamer/gst/gstvecdeque.h"/>
+        <return-value transfer-ownership="none">
+          <type name="none" c:type="void"/>
+        </return-value>
+        <parameters>
+          <instance-parameter name="array" transfer-ownership="none">
+            <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvecdeque.c">a #GstVecDeque object</doc>
+            <type name="VecDeque" c:type="GstVecDeque*"/>
+          </instance-parameter>
+        </parameters>
+      </method>
+      <method name="get_length" c:identifier="gst_vec_deque_get_length" version="1.26" introspectable="0">
+        <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvecdeque.c">Returns the length of the queue @array</doc>
+        <source-position filename="../subprojects/gstreamer/gst/gstvecdeque.h"/>
+        <return-value transfer-ownership="none">
+          <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvecdeque.c">the length of the queue @array.</doc>
+          <type name="gsize" c:type="gsize"/>
+        </return-value>
+        <parameters>
+          <instance-parameter name="array" transfer-ownership="none">
+            <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvecdeque.c">a #GstVecDeque object</doc>
+            <type name="VecDeque" c:type="GstVecDeque*"/>
+          </instance-parameter>
+        </parameters>
+      </method>
+      <method name="is_empty" c:identifier="gst_vec_deque_is_empty" version="1.26" introspectable="0">
+        <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvecdeque.c">Checks if the queue @array is empty.</doc>
+        <source-position filename="../subprojects/gstreamer/gst/gstvecdeque.h"/>
+        <return-value transfer-ownership="none">
+          <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvecdeque.c">%TRUE if the queue @array is empty</doc>
+          <type name="gboolean" c:type="gboolean"/>
+        </return-value>
+        <parameters>
+          <instance-parameter name="array" transfer-ownership="none">
+            <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvecdeque.c">a #GstVecDeque object</doc>
+            <type name="VecDeque" c:type="GstVecDeque*"/>
+          </instance-parameter>
+        </parameters>
+      </method>
+      <method name="peek_head" c:identifier="gst_vec_deque_peek_head" version="1.26" introspectable="0">
+        <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvecdeque.c">Returns the head of the queue @array and does not
+remove it from the queue.</doc>
+        <source-position filename="../subprojects/gstreamer/gst/gstvecdeque.h"/>
+        <return-value transfer-ownership="none" nullable="1">
+          <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvecdeque.c">The head of the queue</doc>
+          <type name="gpointer" c:type="gpointer"/>
+        </return-value>
+        <parameters>
+          <instance-parameter name="array" transfer-ownership="none">
+            <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvecdeque.c">a #GstVecDeque object</doc>
+            <type name="VecDeque" c:type="GstVecDeque*"/>
+          </instance-parameter>
+        </parameters>
+      </method>
+      <method name="peek_head_struct" c:identifier="gst_vec_deque_peek_head_struct" version="1.26" introspectable="0">
+        <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvecdeque.c">Returns the head of the queue @array without removing it from the queue.</doc>
+        <source-position filename="../subprojects/gstreamer/gst/gstvecdeque.h"/>
+        <return-value transfer-ownership="none" nullable="1">
+          <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvecdeque.c">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!</doc>
+          <type name="gpointer" c:type="gpointer"/>
+        </return-value>
+        <parameters>
+          <instance-parameter name="array" transfer-ownership="none">
+            <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvecdeque.c">a #GstVecDeque object</doc>
+            <type name="VecDeque" c:type="GstVecDeque*"/>
+          </instance-parameter>
+        </parameters>
+      </method>
+      <method name="peek_nth" c:identifier="gst_vec_deque_peek_nth" version="1.26" introspectable="0">
+        <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvecdeque.c">Returns the item at @idx in @array, but does not remove it from the queue.</doc>
+        <source-position filename="../subprojects/gstreamer/gst/gstvecdeque.h"/>
+        <return-value transfer-ownership="none" nullable="1">
+          <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvecdeque.c">The item, or %NULL if @idx was out of bounds</doc>
+          <type name="gpointer" c:type="gpointer"/>
+        </return-value>
+        <parameters>
+          <instance-parameter name="array" transfer-ownership="none">
+            <type name="VecDeque" c:type="GstVecDeque*"/>
+          </instance-parameter>
+          <parameter name="idx" transfer-ownership="none">
+            <type name="gsize" c:type="gsize"/>
+          </parameter>
+        </parameters>
+      </method>
+      <method name="peek_nth_struct" c:identifier="gst_vec_deque_peek_nth_struct" version="1.26" introspectable="0">
+        <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvecdeque.c">Returns the item at @idx in @array, but does not remove it from the queue.</doc>
+        <source-position filename="../subprojects/gstreamer/gst/gstvecdeque.h"/>
+        <return-value transfer-ownership="none" nullable="1">
+          <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvecdeque.c">The item, or %NULL if @idx was out of bounds</doc>
+          <type name="gpointer" c:type="gpointer"/>
+        </return-value>
+        <parameters>
+          <instance-parameter name="array" transfer-ownership="none">
+            <type name="VecDeque" c:type="GstVecDeque*"/>
+          </instance-parameter>
+          <parameter name="idx" transfer-ownership="none">
+            <type name="gsize" c:type="gsize"/>
+          </parameter>
+        </parameters>
+      </method>
+      <method name="peek_tail" c:identifier="gst_vec_deque_peek_tail" version="1.26" introspectable="0">
+        <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvecdeque.c">Returns the tail of the queue @array, but does not remove it from the queue.</doc>
+        <source-position filename="../subprojects/gstreamer/gst/gstvecdeque.h"/>
+        <return-value transfer-ownership="none" nullable="1">
+          <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvecdeque.c">The tail of the queue</doc>
+          <type name="gpointer" c:type="gpointer"/>
+        </return-value>
+        <parameters>
+          <instance-parameter name="array" transfer-ownership="none">
+            <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvecdeque.c">a #GstVecDeque object</doc>
+            <type name="VecDeque" c:type="GstVecDeque*"/>
+          </instance-parameter>
+        </parameters>
+      </method>
+      <method name="peek_tail_struct" c:identifier="gst_vec_deque_peek_tail_struct" version="1.26" introspectable="0">
+        <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvecdeque.c">Returns the tail of the queue @array, but does not remove it from the queue.</doc>
+        <source-position filename="../subprojects/gstreamer/gst/gstvecdeque.h"/>
+        <return-value transfer-ownership="none" nullable="1">
+          <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvecdeque.c">The tail of the queue</doc>
+          <type name="gpointer" c:type="gpointer"/>
+        </return-value>
+        <parameters>
+          <instance-parameter name="array" transfer-ownership="none">
+            <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvecdeque.c">a #GstVecDeque object</doc>
+            <type name="VecDeque" c:type="GstVecDeque*"/>
+          </instance-parameter>
+        </parameters>
+      </method>
+      <method name="pop_head" c:identifier="gst_vec_deque_pop_head" version="1.26" introspectable="0">
+        <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvecdeque.c">Returns and head of the queue @array and removes
+it from the queue.</doc>
+        <source-position filename="../subprojects/gstreamer/gst/gstvecdeque.h"/>
+        <return-value transfer-ownership="none" nullable="1">
+          <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvecdeque.c">The head of the queue</doc>
+          <type name="gpointer" c:type="gpointer"/>
+        </return-value>
+        <parameters>
+          <instance-parameter name="array" transfer-ownership="none">
+            <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvecdeque.c">a #GstVecDeque object</doc>
+            <type name="VecDeque" c:type="GstVecDeque*"/>
+          </instance-parameter>
+        </parameters>
+      </method>
+      <method name="pop_head_struct" c:identifier="gst_vec_deque_pop_head_struct" version="1.26" introspectable="0">
+        <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvecdeque.c">Returns the head of the queue @array and removes it from the queue.</doc>
+        <source-position filename="../subprojects/gstreamer/gst/gstvecdeque.h"/>
+        <return-value transfer-ownership="none" nullable="1">
+          <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvecdeque.c">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!</doc>
+          <type name="gpointer" c:type="gpointer"/>
+        </return-value>
+        <parameters>
+          <instance-parameter name="array" transfer-ownership="none">
+            <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvecdeque.c">a #GstVecDeque object</doc>
+            <type name="VecDeque" c:type="GstVecDeque*"/>
+          </instance-parameter>
+        </parameters>
+      </method>
+      <method name="pop_tail" c:identifier="gst_vec_deque_pop_tail" version="1.26" introspectable="0">
+        <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvecdeque.c">Returns the tail of the queue @array and removes
+it from the queue.</doc>
+        <source-position filename="../subprojects/gstreamer/gst/gstvecdeque.h"/>
+        <return-value transfer-ownership="none" nullable="1">
+          <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvecdeque.c">The tail of the queue</doc>
+          <type name="gpointer" c:type="gpointer"/>
+        </return-value>
+        <parameters>
+          <instance-parameter name="array" transfer-ownership="none">
+            <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvecdeque.c">a #GstVecDeque object</doc>
+            <type name="VecDeque" c:type="GstVecDeque*"/>
+          </instance-parameter>
+        </parameters>
+      </method>
+      <method name="pop_tail_struct" c:identifier="gst_vec_deque_pop_tail_struct" version="1.26" introspectable="0">
+        <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvecdeque.c">Returns the tail of the queue @array and removes
+it from the queue.</doc>
+        <source-position filename="../subprojects/gstreamer/gst/gstvecdeque.h"/>
+        <return-value transfer-ownership="none" nullable="1">
+          <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvecdeque.c">The tail of the queue</doc>
+          <type name="gpointer" c:type="gpointer"/>
+        </return-value>
+        <parameters>
+          <instance-parameter name="array" transfer-ownership="none">
+            <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvecdeque.c">a #GstVecDeque object</doc>
+            <type name="VecDeque" c:type="GstVecDeque*"/>
+          </instance-parameter>
+        </parameters>
+      </method>
+      <method name="push_sorted" c:identifier="gst_vec_deque_push_sorted" version="1.26" introspectable="0">
+        <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvecdeque.c">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.</doc>
+        <source-position filename="../subprojects/gstreamer/gst/gstvecdeque.h"/>
+        <return-value transfer-ownership="none">
+          <type name="none" c:type="void"/>
+        </return-value>
+        <parameters>
+          <instance-parameter name="array" transfer-ownership="none">
+            <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvecdeque.c">a #GstVecDeque object</doc>
+            <type name="VecDeque" c:type="GstVecDeque*"/>
+          </instance-parameter>
+          <parameter name="data" transfer-ownership="none" nullable="1" allow-none="1">
+            <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvecdeque.c">object to push</doc>
+            <type name="gpointer" c:type="gpointer"/>
+          </parameter>
+          <parameter name="func" transfer-ownership="none" closure="2">
+            <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvecdeque.c">comparison function</doc>
+            <type name="GLib.CompareDataFunc" c:type="GCompareDataFunc"/>
+          </parameter>
+          <parameter name="user_data" transfer-ownership="none" nullable="1" allow-none="1">
+            <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvecdeque.c">data for comparison function</doc>
+            <type name="gpointer" c:type="gpointer"/>
+          </parameter>
+        </parameters>
+      </method>
+      <method name="push_sorted_struct" c:identifier="gst_vec_deque_push_sorted_struct" version="1.26" introspectable="0">
+        <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvecdeque.c">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.</doc>
+        <source-position filename="../subprojects/gstreamer/gst/gstvecdeque.h"/>
+        <return-value transfer-ownership="none">
+          <type name="none" c:type="void"/>
+        </return-value>
+        <parameters>
+          <instance-parameter name="array" transfer-ownership="none">
+            <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvecdeque.c">a #GstVecDeque object</doc>
+            <type name="VecDeque" c:type="GstVecDeque*"/>
+          </instance-parameter>
+          <parameter name="p_struct" transfer-ownership="none" nullable="1" allow-none="1">
+            <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvecdeque.c">address of element or structure to push into the queue</doc>
+            <type name="gpointer" c:type="gpointer"/>
+          </parameter>
+          <parameter name="func" transfer-ownership="none" closure="2">
+            <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvecdeque.c">comparison function</doc>
+            <type name="GLib.CompareDataFunc" c:type="GCompareDataFunc"/>
+          </parameter>
+          <parameter name="user_data" transfer-ownership="none" nullable="1" allow-none="1">
+            <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvecdeque.c">data for comparison function</doc>
+            <type name="gpointer" c:type="gpointer"/>
+          </parameter>
+        </parameters>
+      </method>
+      <method name="push_tail" c:identifier="gst_vec_deque_push_tail" version="1.26" introspectable="0">
+        <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvecdeque.c">Pushes @data to the tail of the queue @array.</doc>
+        <source-position filename="../subprojects/gstreamer/gst/gstvecdeque.h"/>
+        <return-value transfer-ownership="none">
+          <type name="none" c:type="void"/>
+        </return-value>
+        <parameters>
+          <instance-parameter name="array" transfer-ownership="none">
+            <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvecdeque.c">a #GstVecDeque object</doc>
+            <type name="VecDeque" c:type="GstVecDeque*"/>
+          </instance-parameter>
+          <parameter name="data" transfer-ownership="none" nullable="1" allow-none="1">
+            <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvecdeque.c">object to push</doc>
+            <type name="gpointer" c:type="gpointer"/>
+          </parameter>
+        </parameters>
+      </method>
+      <method name="push_tail_struct" c:identifier="gst_vec_deque_push_tail_struct">
+        <source-position filename="../subprojects/gstreamer/gst/gstvecdeque.h"/>
+        <return-value transfer-ownership="none">
+          <type name="none" c:type="void"/>
+        </return-value>
+        <parameters>
+          <instance-parameter name="array" transfer-ownership="none">
+            <type name="VecDeque" c:type="GstVecDeque*"/>
+          </instance-parameter>
+          <parameter name="p_struct" transfer-ownership="none" nullable="1" allow-none="1">
+            <type name="gpointer" c:type="gpointer"/>
+          </parameter>
+        </parameters>
+      </method>
+      <method name="set_clear_func" c:identifier="gst_vec_deque_set_clear_func" version="1.26" introspectable="0">
+        <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvecdeque.c">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.</doc>
+        <source-position filename="../subprojects/gstreamer/gst/gstvecdeque.h"/>
+        <return-value transfer-ownership="none">
+          <type name="none" c:type="void"/>
+        </return-value>
+        <parameters>
+          <instance-parameter name="array" transfer-ownership="none">
+            <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvecdeque.c">a #GstVecDeque object</doc>
+            <type name="VecDeque" c:type="GstVecDeque*"/>
+          </instance-parameter>
+          <parameter name="clear_func" transfer-ownership="none" scope="async">
+            <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvecdeque.c">a function to clear an element of @array</doc>
+            <type name="GLib.DestroyNotify" c:type="GDestroyNotify"/>
+          </parameter>
+        </parameters>
+      </method>
+      <method name="sort" c:identifier="gst_vec_deque_sort" version="1.26" introspectable="0">
+        <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvecdeque.c">Sorts the queue @array by comparing elements against each other using
+the provided @compare_func.</doc>
+        <source-position filename="../subprojects/gstreamer/gst/gstvecdeque.h"/>
+        <return-value transfer-ownership="none">
+          <type name="none" c:type="void"/>
+        </return-value>
+        <parameters>
+          <instance-parameter name="array" transfer-ownership="none">
+            <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvecdeque.c">a #GstVecDeque object</doc>
+            <type name="VecDeque" c:type="GstVecDeque*"/>
+          </instance-parameter>
+          <parameter name="compare_func" transfer-ownership="none" closure="1">
+            <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvecdeque.c">comparison function</doc>
+            <type name="GLib.CompareDataFunc" c:type="GCompareDataFunc"/>
+          </parameter>
+          <parameter name="user_data" transfer-ownership="none" nullable="1" allow-none="1">
+            <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvecdeque.c">data for comparison function</doc>
+            <type name="gpointer" c:type="gpointer"/>
+          </parameter>
+        </parameters>
+      </method>
+      <function name="new" c:identifier="gst_vec_deque_new" version="1.26" introspectable="0">
+        <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvecdeque.c">Allocates a new #GstVecDeque object with an initial
+queue size of @initial_size.</doc>
+        <source-position filename="../subprojects/gstreamer/gst/gstvecdeque.h"/>
+        <return-value>
+          <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvecdeque.c">a new #GstVecDeque object</doc>
+          <type name="VecDeque" c:type="GstVecDeque*"/>
+        </return-value>
+        <parameters>
+          <parameter name="initial_size" transfer-ownership="none">
+            <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvecdeque.c">Initial size of the new queue</doc>
+            <type name="gsize" c:type="gsize"/>
+          </parameter>
+        </parameters>
+      </function>
+      <function name="new_for_struct" c:identifier="gst_vec_deque_new_for_struct" version="1.26" introspectable="0">
+        <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvecdeque.c">Allocates a new #GstVecDeque object for elements (e.g. structures)
+of size @struct_size, with an initial queue size of @initial_size.</doc>
+        <source-position filename="../subprojects/gstreamer/gst/gstvecdeque.h"/>
+        <return-value>
+          <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvecdeque.c">a new #GstVecDeque object</doc>
+          <type name="VecDeque" c:type="GstVecDeque*"/>
+        </return-value>
+        <parameters>
+          <parameter name="struct_size" transfer-ownership="none">
+            <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvecdeque.c">Size of each element (e.g. structure) in the array</doc>
+            <type name="gsize" c:type="gsize"/>
+          </parameter>
+          <parameter name="initial_size" transfer-ownership="none">
+            <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvecdeque.c">Initial size of the new queue</doc>
+            <type name="gsize" c:type="gsize"/>
+          </parameter>
+        </parameters>
+      </function>
+    </record>
     <function-macro name="WRITE_UINT16_BE" c:identifier="GST_WRITE_UINT16_BE" introspectable="0">
       <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstutils.h">Store a 16 bit unsigned integer value in big endian format into the memory buffer.</doc>
       <source-position filename="../subprojects/gstreamer/gst/gstutils.h"/>
@@ -56121,6 +56578,40 @@ Note that this means subtraction as in sets, not as in mathematics.</doc>
         </parameter>
       </parameters>
     </function>
+    <function name="vec_deque_new" c:identifier="gst_vec_deque_new" moved-to="VecDeque.new" version="1.26" introspectable="0">
+      <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvecdeque.c">Allocates a new #GstVecDeque object with an initial
+queue size of @initial_size.</doc>
+      <source-position filename="../subprojects/gstreamer/gst/gstvecdeque.h"/>
+      <return-value>
+        <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvecdeque.c">a new #GstVecDeque object</doc>
+        <type name="VecDeque" c:type="GstVecDeque*"/>
+      </return-value>
+      <parameters>
+        <parameter name="initial_size" transfer-ownership="none">
+          <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvecdeque.c">Initial size of the new queue</doc>
+          <type name="gsize" c:type="gsize"/>
+        </parameter>
+      </parameters>
+    </function>
+    <function name="vec_deque_new_for_struct" c:identifier="gst_vec_deque_new_for_struct" moved-to="VecDeque.new_for_struct" version="1.26" introspectable="0">
+      <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvecdeque.c">Allocates a new #GstVecDeque object for elements (e.g. structures)
+of size @struct_size, with an initial queue size of @initial_size.</doc>
+      <source-position filename="../subprojects/gstreamer/gst/gstvecdeque.h"/>
+      <return-value>
+        <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvecdeque.c">a new #GstVecDeque object</doc>
+        <type name="VecDeque" c:type="GstVecDeque*"/>
+      </return-value>
+      <parameters>
+        <parameter name="struct_size" transfer-ownership="none">
+          <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvecdeque.c">Size of each element (e.g. structure) in the array</doc>
+          <type name="gsize" c:type="gsize"/>
+        </parameter>
+        <parameter name="initial_size" transfer-ownership="none">
+          <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvecdeque.c">Initial size of the new queue</doc>
+          <type name="gsize" c:type="gsize"/>
+        </parameter>
+      </parameters>
+    </function>
     <function name="version" c:identifier="gst_version">
       <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gst.c">Gets the version number of the GStreamer library.</doc>
       <source-position filename="../subprojects/gstreamer/gst/gst.h"/>
diff --git a/girs/GstBase-1.0.gir b/girs/GstBase-1.0.gir
index 966889f34e..889df8ad68 100644
--- a/girs/GstBase-1.0.gir
+++ b/girs/GstBase-1.0.gir
@@ -2407,6 +2407,20 @@ the first buffer that is received.</doc>
 selected by the `start-time` property.</doc>
       </member>
     </enumeration>
+    <function-macro name="BASE_DEPRECATED_FOR" c:identifier="GST_BASE_DEPRECATED_FOR" introspectable="0">
+      <source-position filename="../subprojects/gstreamer/libs/gst/base/base-prelude.h"/>
+      <parameters>
+        <parameter name="f">
+        </parameter>
+      </parameters>
+    </function-macro>
+    <function-macro name="BASE_DEPRECATED_TYPE_FOR" c:identifier="GST_BASE_DEPRECATED_TYPE_FOR" introspectable="0">
+      <source-position filename="../subprojects/gstreamer/libs/gst/base/base-prelude.h"/>
+      <parameters>
+        <parameter name="f">
+        </parameter>
+      </parameters>
+    </function-macro>
     <function-macro name="BASE_PARSE" c:identifier="GST_BASE_PARSE" introspectable="0">
       <source-position filename="../subprojects/gstreamer/libs/gst/base/gstbaseparse.h"/>
       <parameters>
@@ -13052,13 +13066,15 @@ buffers.</doc>
         </array>
       </field>
     </record>
-    <record name="QueueArray" c:type="GstQueueArray" disguised="1" introspectable="0">
+    <record name="QueueArray" c:type="GstQueueArray" disguised="1" introspectable="0" deprecated="1" deprecated-version="1.26">
       <doc xml:space="preserve" filename="../subprojects/gstreamer/libs/gst/base/gstqueuearray.c">#GstQueueArray is an object that provides standard queue functionality
 based on an array instead of linked lists. This reduces the overhead
 caused by memory management by a large factor.</doc>
+      <doc-deprecated xml:space="preserve">Use #GstVecDeque instead.</doc-deprecated>
       <source-position filename="../subprojects/gstreamer/libs/gst/base/gstqueuearray.h"/>
-      <method name="clear" c:identifier="gst_queue_array_clear" version="1.16" introspectable="0">
+      <method name="clear" c:identifier="gst_queue_array_clear" version="1.16" introspectable="0" deprecated="1" deprecated-version="1.26">
         <doc xml:space="preserve" filename="../subprojects/gstreamer/libs/gst/base/gstqueuearray.c">Clears queue @array and frees all memory associated to it.</doc>
+        <doc-deprecated xml:space="preserve">Use #GstVecDeque instead.</doc-deprecated>
         <source-position filename="../subprojects/gstreamer/libs/gst/base/gstqueuearray.h"/>
         <return-value transfer-ownership="none">
           <type name="none" c:type="void"/>
@@ -13070,8 +13086,9 @@ caused by memory management by a large factor.</doc>
           </instance-parameter>
         </parameters>
       </method>
-      <method name="drop_element" c:identifier="gst_queue_array_drop_element" version="1.2" introspectable="0">
+      <method name="drop_element" c:identifier="gst_queue_array_drop_element" version="1.2" introspectable="0" deprecated="1" deprecated-version="1.26">
         <doc xml:space="preserve" filename="../subprojects/gstreamer/libs/gst/base/gstqueuearray.c">Drops the queue element at position @idx from queue @array.</doc>
+        <doc-deprecated xml:space="preserve">Use #GstVecDeque instead.</doc-deprecated>
         <source-position filename="../subprojects/gstreamer/libs/gst/base/gstqueuearray.h"/>
         <return-value transfer-ownership="none" nullable="1">
           <doc xml:space="preserve" filename="../subprojects/gstreamer/libs/gst/base/gstqueuearray.c">the dropped element</doc>
@@ -13088,10 +13105,11 @@ caused by memory management by a large factor.</doc>
           </parameter>
         </parameters>
       </method>
-      <method name="drop_struct" c:identifier="gst_queue_array_drop_struct" version="1.6" introspectable="0">
+      <method name="drop_struct" c:identifier="gst_queue_array_drop_struct" version="1.6" introspectable="0" deprecated="1" deprecated-version="1.26">
         <doc xml:space="preserve" filename="../subprojects/gstreamer/libs/gst/base/gstqueuearray.c">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).</doc>
+        <doc-deprecated xml:space="preserve">Use #GstVecDeque instead.</doc-deprecated>
         <source-position filename="../subprojects/gstreamer/libs/gst/base/gstqueuearray.h"/>
         <return-value transfer-ownership="none">
           <doc xml:space="preserve" filename="../subprojects/gstreamer/libs/gst/base/gstqueuearray.c">TRUE on success, or FALSE on error</doc>
@@ -13112,10 +13130,11 @@ data of the element or structure that was removed into @p_struct if
           </parameter>
         </parameters>
       </method>
-      <method name="find" c:identifier="gst_queue_array_find" version="1.2" introspectable="0">
+      <method name="find" c:identifier="gst_queue_array_find" version="1.2" introspectable="0" deprecated="1" deprecated-version="1.26">
         <doc xml:space="preserve" filename="../subprojects/gstreamer/libs/gst/base/gstqueuearray.c">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.</doc>
+        <doc-deprecated xml:space="preserve">Use #GstVecDeque instead.</doc-deprecated>
         <source-position filename="../subprojects/gstreamer/libs/gst/base/gstqueuearray.h"/>
         <return-value transfer-ownership="none">
           <doc xml:space="preserve" filename="../subprojects/gstreamer/libs/gst/base/gstqueuearray.c">Index of the found element or -1 if nothing was found.</doc>
@@ -13136,8 +13155,9 @@ and returning the index of the found element.</doc>
           </parameter>
         </parameters>
       </method>
-      <method name="free" c:identifier="gst_queue_array_free" version="1.2" introspectable="0">
+      <method name="free" c:identifier="gst_queue_array_free" version="1.2" introspectable="0" deprecated="1" deprecated-version="1.26">
         <doc xml:space="preserve" filename="../subprojects/gstreamer/libs/gst/base/gstqueuearray.c">Frees queue @array and all memory associated to it.</doc>
+        <doc-deprecated xml:space="preserve">Use #GstVecDeque instead.</doc-deprecated>
         <source-position filename="../subprojects/gstreamer/libs/gst/base/gstqueuearray.h"/>
         <return-value transfer-ownership="none">
           <type name="none" c:type="void"/>
@@ -13149,8 +13169,9 @@ and returning the index of the found element.</doc>
           </instance-parameter>
         </parameters>
       </method>
-      <method name="get_length" c:identifier="gst_queue_array_get_length" version="1.2" introspectable="0">
+      <method name="get_length" c:identifier="gst_queue_array_get_length" version="1.2" introspectable="0" deprecated="1" deprecated-version="1.26">
         <doc xml:space="preserve" filename="../subprojects/gstreamer/libs/gst/base/gstqueuearray.c">Returns the length of the queue @array</doc>
+        <doc-deprecated xml:space="preserve">Use #GstVecDeque instead.</doc-deprecated>
         <source-position filename="../subprojects/gstreamer/libs/gst/base/gstqueuearray.h"/>
         <return-value transfer-ownership="none">
           <doc xml:space="preserve" filename="../subprojects/gstreamer/libs/gst/base/gstqueuearray.c">the length of the queue @array.</doc>
@@ -13163,8 +13184,9 @@ and returning the index of the found element.</doc>
           </instance-parameter>
         </parameters>
       </method>
-      <method name="is_empty" c:identifier="gst_queue_array_is_empty" version="1.2" introspectable="0">
+      <method name="is_empty" c:identifier="gst_queue_array_is_empty" version="1.2" introspectable="0" deprecated="1" deprecated-version="1.26">
         <doc xml:space="preserve" filename="../subprojects/gstreamer/libs/gst/base/gstqueuearray.c">Checks if the queue @array is empty.</doc>
+        <doc-deprecated xml:space="preserve">Use #GstVecDeque instead.</doc-deprecated>
         <source-position filename="../subprojects/gstreamer/libs/gst/base/gstqueuearray.h"/>
         <return-value transfer-ownership="none">
           <doc xml:space="preserve" filename="../subprojects/gstreamer/libs/gst/base/gstqueuearray.c">%TRUE if the queue @array is empty</doc>
@@ -13177,9 +13199,10 @@ and returning the index of the found element.</doc>
           </instance-parameter>
         </parameters>
       </method>
-      <method name="peek_head" c:identifier="gst_queue_array_peek_head" version="1.2" introspectable="0">
+      <method name="peek_head" c:identifier="gst_queue_array_peek_head" version="1.2" introspectable="0" deprecated="1" deprecated-version="1.26">
         <doc xml:space="preserve" filename="../subprojects/gstreamer/libs/gst/base/gstqueuearray.c">Returns the head of the queue @array and does not
 remove it from the queue.</doc>
+        <doc-deprecated xml:space="preserve">Use #GstVecDeque instead.</doc-deprecated>
         <source-position filename="../subprojects/gstreamer/libs/gst/base/gstqueuearray.h"/>
         <return-value transfer-ownership="none" nullable="1">
           <doc xml:space="preserve" filename="../subprojects/gstreamer/libs/gst/base/gstqueuearray.c">The head of the queue</doc>
@@ -13192,8 +13215,9 @@ remove it from the queue.</doc>
           </instance-parameter>
         </parameters>
       </method>
-      <method name="peek_head_struct" c:identifier="gst_queue_array_peek_head_struct" version="1.6" introspectable="0">
+      <method name="peek_head_struct" c:identifier="gst_queue_array_peek_head_struct" version="1.6" introspectable="0" deprecated="1" deprecated-version="1.26">
         <doc xml:space="preserve" filename="../subprojects/gstreamer/libs/gst/base/gstqueuearray.c">Returns the head of the queue @array without removing it from the queue.</doc>
+        <doc-deprecated xml:space="preserve">Use #GstVecDeque instead.</doc-deprecated>
         <source-position filename="../subprojects/gstreamer/libs/gst/base/gstqueuearray.h"/>
         <return-value transfer-ownership="none" nullable="1">
           <doc xml:space="preserve" filename="../subprojects/gstreamer/libs/gst/base/gstqueuearray.c">pointer to element or struct, or NULL if @array was empty. The
@@ -13208,8 +13232,9 @@ remove it from the queue.</doc>
           </instance-parameter>
         </parameters>
       </method>
-      <method name="peek_nth" c:identifier="gst_queue_array_peek_nth" version="1.16" introspectable="0">
+      <method name="peek_nth" c:identifier="gst_queue_array_peek_nth" version="1.16" introspectable="0" deprecated="1" deprecated-version="1.26">
         <doc xml:space="preserve" filename="../subprojects/gstreamer/libs/gst/base/gstqueuearray.c">Returns the item at @idx in @array, but does not remove it from the queue.</doc>
+        <doc-deprecated xml:space="preserve">Use #GstVecDeque instead.</doc-deprecated>
         <source-position filename="../subprojects/gstreamer/libs/gst/base/gstqueuearray.h"/>
         <return-value transfer-ownership="none" nullable="1">
           <doc xml:space="preserve" filename="../subprojects/gstreamer/libs/gst/base/gstqueuearray.c">The item, or %NULL if @idx was out of bounds</doc>
@@ -13224,8 +13249,9 @@ remove it from the queue.</doc>
           </parameter>
         </parameters>
       </method>
-      <method name="peek_nth_struct" c:identifier="gst_queue_array_peek_nth_struct" version="1.16" introspectable="0">
+      <method name="peek_nth_struct" c:identifier="gst_queue_array_peek_nth_struct" version="1.16" introspectable="0" deprecated="1" deprecated-version="1.26">
         <doc xml:space="preserve" filename="../subprojects/gstreamer/libs/gst/base/gstqueuearray.c">Returns the item at @idx in @array, but does not remove it from the queue.</doc>
+        <doc-deprecated xml:space="preserve">Use #GstVecDeque instead.</doc-deprecated>
         <source-position filename="../subprojects/gstreamer/libs/gst/base/gstqueuearray.h"/>
         <return-value transfer-ownership="none" nullable="1">
           <doc xml:space="preserve" filename="../subprojects/gstreamer/libs/gst/base/gstqueuearray.c">The item, or %NULL if @idx was out of bounds</doc>
@@ -13240,8 +13266,9 @@ remove it from the queue.</doc>
           </parameter>
         </parameters>
       </method>
-      <method name="peek_tail" c:identifier="gst_queue_array_peek_tail" version="1.14" introspectable="0">
+      <method name="peek_tail" c:identifier="gst_queue_array_peek_tail" version="1.14" introspectable="0" deprecated="1" deprecated-version="1.26">
         <doc xml:space="preserve" filename="../subprojects/gstreamer/libs/gst/base/gstqueuearray.c">Returns the tail of the queue @array, but does not remove it from the queue.</doc>
+        <doc-deprecated xml:space="preserve">Use #GstVecDeque instead.</doc-deprecated>
         <source-position filename="../subprojects/gstreamer/libs/gst/base/gstqueuearray.h"/>
         <return-value transfer-ownership="none" nullable="1">
           <doc xml:space="preserve" filename="../subprojects/gstreamer/libs/gst/base/gstqueuearray.c">The tail of the queue</doc>
@@ -13254,8 +13281,9 @@ remove it from the queue.</doc>
           </instance-parameter>
         </parameters>
       </method>
-      <method name="peek_tail_struct" c:identifier="gst_queue_array_peek_tail_struct" version="1.14" introspectable="0">
+      <method name="peek_tail_struct" c:identifier="gst_queue_array_peek_tail_struct" version="1.14" introspectable="0" deprecated="1" deprecated-version="1.26">
         <doc xml:space="preserve" filename="../subprojects/gstreamer/libs/gst/base/gstqueuearray.c">Returns the tail of the queue @array, but does not remove it from the queue.</doc>
+        <doc-deprecated xml:space="preserve">Use #GstVecDeque instead.</doc-deprecated>
         <source-position filename="../subprojects/gstreamer/libs/gst/base/gstqueuearray.h"/>
         <return-value transfer-ownership="none" nullable="1">
           <doc xml:space="preserve" filename="../subprojects/gstreamer/libs/gst/base/gstqueuearray.c">The tail of the queue</doc>
@@ -13268,9 +13296,10 @@ remove it from the queue.</doc>
           </instance-parameter>
         </parameters>
       </method>
-      <method name="pop_head" c:identifier="gst_queue_array_pop_head" version="1.2" introspectable="0">
+      <method name="pop_head" c:identifier="gst_queue_array_pop_head" version="1.2" introspectable="0" deprecated="1" deprecated-version="1.26">
         <doc xml:space="preserve" filename="../subprojects/gstreamer/libs/gst/base/gstqueuearray.c">Returns and head of the queue @array and removes
 it from the queue.</doc>
+        <doc-deprecated xml:space="preserve">Use #GstVecDeque instead.</doc-deprecated>
         <source-position filename="../subprojects/gstreamer/libs/gst/base/gstqueuearray.h"/>
         <return-value transfer-ownership="none" nullable="1">
           <doc xml:space="preserve" filename="../subprojects/gstreamer/libs/gst/base/gstqueuearray.c">The head of the queue</doc>
@@ -13283,8 +13312,9 @@ it from the queue.</doc>
           </instance-parameter>
         </parameters>
       </method>
-      <method name="pop_head_struct" c:identifier="gst_queue_array_pop_head_struct" version="1.6" introspectable="0">
+      <method name="pop_head_struct" c:identifier="gst_queue_array_pop_head_struct" version="1.6" introspectable="0" deprecated="1" deprecated-version="1.26">
         <doc xml:space="preserve" filename="../subprojects/gstreamer/libs/gst/base/gstqueuearray.c">Returns the head of the queue @array and removes it from the queue.</doc>
+        <doc-deprecated xml:space="preserve">Use #GstVecDeque instead.</doc-deprecated>
         <source-position filename="../subprojects/gstreamer/libs/gst/base/gstqueuearray.h"/>
         <return-value transfer-ownership="none" nullable="1">
           <doc xml:space="preserve" filename="../subprojects/gstreamer/libs/gst/base/gstqueuearray.c">pointer to element or struct, or NULL if @array was empty. The
@@ -13299,9 +13329,10 @@ it from the queue.</doc>
           </instance-parameter>
         </parameters>
       </method>
-      <method name="pop_tail" c:identifier="gst_queue_array_pop_tail" version="1.14" introspectable="0">
+      <method name="pop_tail" c:identifier="gst_queue_array_pop_tail" version="1.14" introspectable="0" deprecated="1" deprecated-version="1.26">
         <doc xml:space="preserve" filename="../subprojects/gstreamer/libs/gst/base/gstqueuearray.c">Returns the tail of the queue @array and removes
 it from the queue.</doc>
+        <doc-deprecated xml:space="preserve">Use #GstVecDeque instead.</doc-deprecated>
         <source-position filename="../subprojects/gstreamer/libs/gst/base/gstqueuearray.h"/>
         <return-value transfer-ownership="none" nullable="1">
           <doc xml:space="preserve" filename="../subprojects/gstreamer/libs/gst/base/gstqueuearray.c">The tail of the queue</doc>
@@ -13314,9 +13345,10 @@ it from the queue.</doc>
           </instance-parameter>
         </parameters>
       </method>
-      <method name="pop_tail_struct" c:identifier="gst_queue_array_pop_tail_struct" version="1.14" introspectable="0">
+      <method name="pop_tail_struct" c:identifier="gst_queue_array_pop_tail_struct" version="1.14" introspectable="0" deprecated="1" deprecated-version="1.26">
         <doc xml:space="preserve" filename="../subprojects/gstreamer/libs/gst/base/gstqueuearray.c">Returns the tail of the queue @array and removes
 it from the queue.</doc>
+        <doc-deprecated xml:space="preserve">Use #GstVecDeque instead.</doc-deprecated>
         <source-position filename="../subprojects/gstreamer/libs/gst/base/gstqueuearray.h"/>
         <return-value transfer-ownership="none" nullable="1">
           <doc xml:space="preserve" filename="../subprojects/gstreamer/libs/gst/base/gstqueuearray.c">The tail of the queue</doc>
@@ -13329,7 +13361,7 @@ it from the queue.</doc>
           </instance-parameter>
         </parameters>
       </method>
-      <method name="push_sorted" c:identifier="gst_queue_array_push_sorted" version="1.24" introspectable="0">
+      <method name="push_sorted" c:identifier="gst_queue_array_push_sorted" version="1.24" introspectable="0" deprecated="1" deprecated-version="1.26">
         <doc xml:space="preserve" filename="../subprojects/gstreamer/libs/gst/base/gstqueuearray.c">Pushes @data to the queue @array, finding the correct position
 by comparing @data with each array element using @func.
 
@@ -13338,6 +13370,7 @@ 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_queue_array_sort() first.</doc>
+        <doc-deprecated xml:space="preserve">Use #GstVecDeque instead.</doc-deprecated>
         <source-position filename="../subprojects/gstreamer/libs/gst/base/gstqueuearray.h"/>
         <return-value transfer-ownership="none">
           <type name="none" c:type="void"/>
@@ -13361,7 +13394,7 @@ to call gst_queue_array_sort() first.</doc>
           </parameter>
         </parameters>
       </method>
-      <method name="push_sorted_struct" c:identifier="gst_queue_array_push_sorted_struct" version="1.24" introspectable="0">
+      <method name="push_sorted_struct" c:identifier="gst_queue_array_push_sorted_struct" version="1.24" introspectable="0" deprecated="1" deprecated-version="1.26">
         <doc xml:space="preserve" filename="../subprojects/gstreamer/libs/gst/base/gstqueuearray.c">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
@@ -13372,6 +13405,7 @@ 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_queue_array_sort() first.</doc>
+        <doc-deprecated xml:space="preserve">Use #GstVecDeque instead.</doc-deprecated>
         <source-position filename="../subprojects/gstreamer/libs/gst/base/gstqueuearray.h"/>
         <return-value transfer-ownership="none">
           <type name="none" c:type="void"/>
@@ -13395,8 +13429,9 @@ to call gst_queue_array_sort() first.</doc>
           </parameter>
         </parameters>
       </method>
-      <method name="push_tail" c:identifier="gst_queue_array_push_tail" version="1.2" introspectable="0">
+      <method name="push_tail" c:identifier="gst_queue_array_push_tail" version="1.2" introspectable="0" deprecated="1" deprecated-version="1.26">
         <doc xml:space="preserve" filename="../subprojects/gstreamer/libs/gst/base/gstqueuearray.c">Pushes @data to the tail of the queue @array.</doc>
+        <doc-deprecated xml:space="preserve">Use #GstVecDeque instead.</doc-deprecated>
         <source-position filename="../subprojects/gstreamer/libs/gst/base/gstqueuearray.h"/>
         <return-value transfer-ownership="none">
           <type name="none" c:type="void"/>
@@ -13426,7 +13461,7 @@ to call gst_queue_array_sort() first.</doc>
           </parameter>
         </parameters>
       </method>
-      <method name="set_clear_func" c:identifier="gst_queue_array_set_clear_func" version="1.16" introspectable="0">
+      <method name="set_clear_func" c:identifier="gst_queue_array_set_clear_func" version="1.16" introspectable="0" deprecated="1" deprecated-version="1.26">
         <doc xml:space="preserve" filename="../subprojects/gstreamer/libs/gst/base/gstqueuearray.c">Sets a function to clear an element of @array.
 
 The @clear_func will be called when an element in the array
@@ -13437,6 +13472,7 @@ 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.</doc>
+        <doc-deprecated xml:space="preserve">Use #GstVecDeque instead.</doc-deprecated>
         <source-position filename="../subprojects/gstreamer/libs/gst/base/gstqueuearray.h"/>
         <return-value transfer-ownership="none">
           <type name="none" c:type="void"/>
@@ -13452,9 +13488,10 @@ the array element it is given, but not free the element itself.</doc>
           </parameter>
         </parameters>
       </method>
-      <method name="sort" c:identifier="gst_queue_array_sort" version="1.24" introspectable="0">
+      <method name="sort" c:identifier="gst_queue_array_sort" version="1.24" introspectable="0" deprecated="1" deprecated-version="1.26">
         <doc xml:space="preserve" filename="../subprojects/gstreamer/libs/gst/base/gstqueuearray.c">Sorts the queue @array by comparing elements against each other using
 the provided @compare_func.</doc>
+        <doc-deprecated xml:space="preserve">Use #GstVecDeque instead.</doc-deprecated>
         <source-position filename="../subprojects/gstreamer/libs/gst/base/gstqueuearray.h"/>
         <return-value transfer-ownership="none">
           <type name="none" c:type="void"/>
@@ -13489,9 +13526,10 @@ queue size of @initial_size.</doc>
           </parameter>
         </parameters>
       </function>
-      <function name="new_for_struct" c:identifier="gst_queue_array_new_for_struct" version="1.6" introspectable="0">
+      <function name="new_for_struct" c:identifier="gst_queue_array_new_for_struct" version="1.6" introspectable="0" deprecated="1" deprecated-version="1.26">
         <doc xml:space="preserve" filename="../subprojects/gstreamer/libs/gst/base/gstqueuearray.c">Allocates a new #GstQueueArray object for elements (e.g. structures)
 of size @struct_size, with an initial queue size of @initial_size.</doc>
+        <doc-deprecated xml:space="preserve">Use #GstVecDeque instead.</doc-deprecated>
         <source-position filename="../subprojects/gstreamer/libs/gst/base/gstqueuearray.h"/>
         <return-value>
           <doc xml:space="preserve" filename="../subprojects/gstreamer/libs/gst/base/gstqueuearray.c">a new #GstQueueArray object</doc>
@@ -13875,9 +13913,10 @@ queue size of @initial_size.</doc>
         </parameter>
       </parameters>
     </function>
-    <function name="queue_array_new_for_struct" c:identifier="gst_queue_array_new_for_struct" moved-to="QueueArray.new_for_struct" version="1.6" introspectable="0">
+    <function name="queue_array_new_for_struct" c:identifier="gst_queue_array_new_for_struct" moved-to="QueueArray.new_for_struct" version="1.6" introspectable="0" deprecated="1" deprecated-version="1.26">
       <doc xml:space="preserve" filename="../subprojects/gstreamer/libs/gst/base/gstqueuearray.c">Allocates a new #GstQueueArray object for elements (e.g. structures)
 of size @struct_size, with an initial queue size of @initial_size.</doc>
+      <doc-deprecated xml:space="preserve">Use #GstVecDeque instead.</doc-deprecated>
       <source-position filename="../subprojects/gstreamer/libs/gst/base/gstqueuearray.h"/>
       <return-value>
         <doc xml:space="preserve" filename="../subprojects/gstreamer/libs/gst/base/gstqueuearray.c">a new #GstQueueArray object</doc>
diff --git a/subprojects/gst-docs/symbols/symbol_index.json b/subprojects/gst-docs/symbols/symbol_index.json
index 466357b913..fd704e74cd 100644
--- a/subprojects/gst-docs/symbols/symbol_index.json
+++ b/subprojects/gst-docs/symbols/symbol_index.json
@@ -1351,6 +1351,10 @@
   "GST_AV1_WARP_MODEL_ROTZOOM",
   "GST_AV1_WARP_MODEL_TRANSLATION",
   "GST_BASE_API",
+  "GST_BASE_DEPRECATED",
+  "GST_BASE_DEPRECATED_FOR",
+  "GST_BASE_DEPRECATED_TYPE",
+  "GST_BASE_DEPRECATED_TYPE_FOR",
   "GST_BASE_CAMERA_SRC_CAST",
   "GST_BASE_CAMERA_SRC_IMAGE_PAD_NAME",
   "GST_BASE_CAMERA_SRC_PREVIEW_MESSAGE_NAME",
diff --git a/subprojects/gst-plugins-bad/gst-libs/gst/codecs/gstav1decoder.c b/subprojects/gst-plugins-bad/gst-libs/gst/codecs/gstav1decoder.c
index be0824004b..c1ab7f9994 100644
--- a/subprojects/gst-plugins-bad/gst-libs/gst/codecs/gstav1decoder.c
+++ b/subprojects/gst-plugins-bad/gst-libs/gst/codecs/gstav1decoder.c
@@ -46,7 +46,7 @@ struct _GstAV1DecoderPrivate
   GstVideoCodecFrame *current_frame;
 
   guint preferred_output_delay;
-  GstQueueArray *output_queue;
+  GstVecDeque *output_queue;
   gboolean is_live;
 
   gboolean input_state_changed;
@@ -124,8 +124,8 @@ gst_av1_decoder_init (GstAV1Decoder * self)
   self->priv = priv = gst_av1_decoder_get_instance_private (self);
 
   priv->output_queue =
-      gst_queue_array_new_for_struct (sizeof (GstAV1DecoderOutputFrame), 1);
-  gst_queue_array_set_clear_func (priv->output_queue,
+      gst_vec_deque_new_for_struct (sizeof (GstAV1DecoderOutputFrame), 1);
+  gst_vec_deque_set_clear_func (priv->output_queue,
       (GDestroyNotify) gst_av1_decoder_clear_output_frame);
 }
 
@@ -135,7 +135,7 @@ gst_av1_decoder_finalize (GObject * object)
   GstAV1Decoder *self = GST_AV1_DECODER (object);
   GstAV1DecoderPrivate *priv = self->priv;
 
-  gst_queue_array_free (priv->output_queue);
+  gst_vec_deque_free (priv->output_queue);
 
   G_OBJECT_CLASS (parent_class)->finalize (object);
 }
@@ -158,7 +158,7 @@ gst_av1_decoder_reset (GstAV1Decoder * self)
   if (priv->parser)
     gst_av1_parser_reset (priv->parser, FALSE);
 
-  gst_queue_array_clear (priv->output_queue);
+  gst_vec_deque_clear (priv->output_queue);
 }
 
 static gboolean
@@ -254,9 +254,9 @@ gst_av1_decoder_drain_output_queue (GstAV1Decoder * self,
 
   g_assert (klass->output_picture);
 
-  while (gst_queue_array_get_length (priv->output_queue) > num) {
+  while (gst_vec_deque_get_length (priv->output_queue) > num) {
     GstAV1DecoderOutputFrame *output_frame = (GstAV1DecoderOutputFrame *)
-        gst_queue_array_pop_head_struct (priv->output_queue);
+        gst_vec_deque_pop_head_struct (priv->output_queue);
     GstFlowReturn flow_ret = klass->output_picture (self,
         output_frame->frame, output_frame->picture);
 
@@ -771,7 +771,7 @@ out:
         output_frame.picture = priv->current_picture;
         output_frame.self = self;
 
-        gst_queue_array_push_tail_struct (priv->output_queue, &output_frame);
+        gst_vec_deque_push_tail_struct (priv->output_queue, &output_frame);
       }
     } else {
       GST_LOG_OBJECT (self, "Decode only picture %p", priv->current_picture);
diff --git a/subprojects/gst-plugins-bad/gst-libs/gst/codecs/gsth264decoder.c b/subprojects/gst-plugins-bad/gst-libs/gst/codecs/gsth264decoder.c
index d453c22921..98f3b853cf 100644
--- a/subprojects/gst-plugins-bad/gst-libs/gst/codecs/gsth264decoder.c
+++ b/subprojects/gst-plugins-bad/gst-libs/gst/codecs/gsth264decoder.c
@@ -150,7 +150,7 @@ struct _GstH264DecoderPrivate
   GArray *split_nalu;
 
   /* For delayed output */
-  GstQueueArray *output_queue;
+  GstVecDeque *output_queue;
 
   gboolean input_state_changed;
 
@@ -392,8 +392,8 @@ gst_h264_decoder_init (GstH264Decoder * self)
   priv->split_nalu = g_array_new (FALSE, FALSE, sizeof (GstH264NalUnit));
 
   priv->output_queue =
-      gst_queue_array_new_for_struct (sizeof (GstH264DecoderOutputFrame), 1);
-  gst_queue_array_set_clear_func (priv->output_queue,
+      gst_vec_deque_new_for_struct (sizeof (GstH264DecoderOutputFrame), 1);
+  gst_vec_deque_set_clear_func (priv->output_queue,
       (GDestroyNotify) gst_h264_decoder_clear_output_frame);
 }
 
@@ -412,7 +412,7 @@ gst_h264_decoder_finalize (GObject * object)
   g_array_unref (priv->ref_pic_list0);
   g_array_unref (priv->ref_pic_list1);
   g_array_unref (priv->split_nalu);
-  gst_queue_array_free (priv->output_queue);
+  gst_vec_deque_free (priv->output_queue);
 
   G_OBJECT_CLASS (parent_class)->finalize (object);
 }
@@ -506,7 +506,7 @@ gst_h264_decoder_clear_dpb (GstH264Decoder * self, gboolean flush)
     }
   }
 
-  gst_queue_array_clear (priv->output_queue);
+  gst_vec_deque_clear (priv->output_queue);
   gst_h264_decoder_clear_ref_pic_lists (self);
   gst_clear_h264_picture (&priv->last_field);
   gst_h264_dpb_clear (priv->dpb);
@@ -1801,9 +1801,9 @@ gst_h264_decoder_drain_output_queue (GstH264Decoder * self, guint num,
   g_assert (klass->output_picture);
   g_assert (ret != NULL);
 
-  while (gst_queue_array_get_length (priv->output_queue) > num) {
+  while (gst_vec_deque_get_length (priv->output_queue) > num) {
     GstH264DecoderOutputFrame *output_frame = (GstH264DecoderOutputFrame *)
-        gst_queue_array_pop_head_struct (priv->output_queue);
+        gst_vec_deque_pop_head_struct (priv->output_queue);
     GstFlowReturn flow_ret = klass->output_picture (self, output_frame->frame,
         output_frame->picture);
 
@@ -1881,7 +1881,7 @@ gst_h264_decoder_do_output_picture (GstH264Decoder * self,
   output_frame.frame = frame;
   output_frame.picture = picture;
   output_frame.self = self;
-  gst_queue_array_push_tail_struct (priv->output_queue, &output_frame);
+  gst_vec_deque_push_tail_struct (priv->output_queue, &output_frame);
 
   gst_h264_decoder_drain_output_queue (self, priv->preferred_output_delay,
       &priv->last_flow);
diff --git a/subprojects/gst-plugins-bad/gst-libs/gst/codecs/gsth265decoder.c b/subprojects/gst-plugins-bad/gst-libs/gst/codecs/gsth265decoder.c
index e4da9d1d43..33df8c20b7 100644
--- a/subprojects/gst-plugins-bad/gst-libs/gst/codecs/gsth265decoder.c
+++ b/subprojects/gst-plugins-bad/gst-libs/gst/codecs/gsth265decoder.c
@@ -133,7 +133,7 @@ struct _GstH265DecoderPrivate
   /* For delayed output */
   guint preferred_output_delay;
   gboolean is_live;
-  GstQueueArray *output_queue;
+  GstVecDeque *output_queue;
 
   gboolean input_state_changed;
 
@@ -238,8 +238,8 @@ gst_h265_decoder_init (GstH265Decoder * self)
   g_array_set_clear_func (priv->nalu,
       (GDestroyNotify) gst_h265_decoder_clear_nalu);
   priv->output_queue =
-      gst_queue_array_new_for_struct (sizeof (GstH265DecoderOutputFrame), 1);
-  gst_queue_array_set_clear_func (priv->output_queue,
+      gst_vec_deque_new_for_struct (sizeof (GstH265DecoderOutputFrame), 1);
+  gst_vec_deque_set_clear_func (priv->output_queue,
       (GDestroyNotify) gst_h265_decoder_clear_output_frame);
 }
 
@@ -254,7 +254,7 @@ gst_h265_decoder_finalize (GObject * object)
   g_array_unref (priv->ref_pic_list1);
   g_array_unref (priv->nalu);
   g_array_unref (priv->split_nalu);
-  gst_queue_array_free (priv->output_queue);
+  gst_vec_deque_free (priv->output_queue);
 
   G_OBJECT_CLASS (parent_class)->finalize (object);
 }
@@ -344,9 +344,9 @@ gst_h265_decoder_drain_output_queue (GstH265Decoder * self, guint num,
   g_assert (klass->output_picture);
   g_assert (ret != NULL);
 
-  while (gst_queue_array_get_length (priv->output_queue) > num) {
+  while (gst_vec_deque_get_length (priv->output_queue) > num) {
     GstH265DecoderOutputFrame *output_frame = (GstH265DecoderOutputFrame *)
-        gst_queue_array_pop_head_struct (priv->output_queue);
+        gst_vec_deque_pop_head_struct (priv->output_queue);
     GstFlowReturn flow_ret = klass->output_picture (self, output_frame->frame,
         output_frame->picture);
 
@@ -1741,7 +1741,7 @@ gst_h265_decoder_do_output_picture (GstH265Decoder * self,
   output_frame.frame = frame;
   output_frame.picture = picture;
   output_frame.self = self;
-  gst_queue_array_push_tail_struct (priv->output_queue, &output_frame);
+  gst_vec_deque_push_tail_struct (priv->output_queue, &output_frame);
 
   gst_h265_decoder_drain_output_queue (self, priv->preferred_output_delay,
       &priv->last_flow);
@@ -1767,7 +1767,7 @@ gst_h265_decoder_clear_dpb (GstH265Decoder * self, gboolean flush)
     }
   }
 
-  gst_queue_array_clear (priv->output_queue);
+  gst_vec_deque_clear (priv->output_queue);
   gst_h265_dpb_clear (priv->dpb);
   priv->last_output_poc = G_MININT32;
 }
diff --git a/subprojects/gst-plugins-bad/gst-libs/gst/codecs/gstmpeg2decoder.c b/subprojects/gst-plugins-bad/gst-libs/gst/codecs/gstmpeg2decoder.c
index 508aa1626a..680c5bb774 100644
--- a/subprojects/gst-plugins-bad/gst-libs/gst/codecs/gstmpeg2decoder.c
+++ b/subprojects/gst-plugins-bad/gst-libs/gst/codecs/gstmpeg2decoder.c
@@ -264,7 +264,7 @@ struct _GstMpeg2DecoderPrivate
 
   guint preferred_output_delay;
   /* for delayed output */
-  GstQueueArray *output_queue;
+  GstVecDeque *output_queue;
   /* used for low-latency vs. high throughput mode decision */
   gboolean is_live;
 
@@ -357,8 +357,8 @@ gst_mpeg2_decoder_start (GstVideoDecoder * decoder)
   priv->last_flow = GST_FLOW_OK;
 
   priv->output_queue =
-      gst_queue_array_new_for_struct (sizeof (GstMpeg2DecoderOutputFrame), 1);
-  gst_queue_array_set_clear_func (priv->output_queue,
+      gst_vec_deque_new_for_struct (sizeof (GstMpeg2DecoderOutputFrame), 1);
+  gst_vec_deque_set_clear_func (priv->output_queue,
       (GDestroyNotify) gst_mpeg2_decoder_clear_output_frame);
 
   return TRUE;
@@ -372,7 +372,7 @@ gst_mpeg2_decoder_stop (GstVideoDecoder * decoder)
 
   g_clear_pointer (&self->input_state, gst_video_codec_state_unref);
   g_clear_pointer (&priv->dpb, gst_mpeg2_dpb_free);
-  gst_queue_array_free (priv->output_queue);
+  gst_vec_deque_free (priv->output_queue);
 
   return TRUE;
 }
@@ -429,7 +429,7 @@ gst_mpeg2_decoder_drain (GstVideoDecoder * decoder)
   }
 
   gst_mpeg2_decoder_drain_output_queue (self, 0, &ret);
-  gst_queue_array_clear (priv->output_queue);
+  gst_vec_deque_clear (priv->output_queue);
   gst_mpeg2_dpb_clear (priv->dpb);
 
   return ret;
@@ -448,7 +448,7 @@ gst_mpeg2_decoder_flush (GstVideoDecoder * decoder)
   GstMpeg2DecoderPrivate *priv = self->priv;
 
   gst_mpeg2_dpb_clear (priv->dpb);
-  gst_queue_array_clear (priv->output_queue);
+  gst_vec_deque_clear (priv->output_queue);
   priv->state &= GST_MPEG2_DECODER_STATE_VALID_SEQ_HEADERS;
   priv->pic_hdr = PIC_HDR_INIT;
   priv->pic_ext = PIC_HDR_EXT_INIT;
@@ -1173,7 +1173,7 @@ gst_mpeg2_decoder_do_output_picture (GstMpeg2Decoder * decoder,
   output_frame.frame = frame;
   output_frame.picture = to_output;
   output_frame.self = decoder;
-  gst_queue_array_push_tail_struct (priv->output_queue, &output_frame);
+  gst_vec_deque_push_tail_struct (priv->output_queue, &output_frame);
   gst_mpeg2_decoder_drain_output_queue (decoder, priv->preferred_output_delay,
       &priv->last_flow);
 }
@@ -1342,9 +1342,9 @@ gst_mpeg2_decoder_drain_output_queue (GstMpeg2Decoder * self, guint num,
 
   g_assert (klass->output_picture);
 
-  while (gst_queue_array_get_length (priv->output_queue) > num) {
+  while (gst_vec_deque_get_length (priv->output_queue) > num) {
     GstMpeg2DecoderOutputFrame *output_frame = (GstMpeg2DecoderOutputFrame *)
-        gst_queue_array_pop_head_struct (priv->output_queue);
+        gst_vec_deque_pop_head_struct (priv->output_queue);
     GST_LOG_OBJECT (self,
         "Output picture %p (frame_num %d, poc %d, pts: %" GST_TIME_FORMAT
         "), from DPB",
diff --git a/subprojects/gst-plugins-bad/gst-libs/gst/codecs/gstvp8decoder.c b/subprojects/gst-plugins-bad/gst-libs/gst/codecs/gstvp8decoder.c
index eae9c12c88..f27b2bfdde 100644
--- a/subprojects/gst-plugins-bad/gst-libs/gst/codecs/gstvp8decoder.c
+++ b/subprojects/gst-plugins-bad/gst-libs/gst/codecs/gstvp8decoder.c
@@ -45,7 +45,7 @@ struct _GstVp8DecoderPrivate
   gboolean wait_keyframe;
   guint preferred_output_delay;
   /* for delayed output */
-  GstQueueArray *output_queue;
+  GstVecDeque *output_queue;
   gboolean is_live;
 
   gboolean input_state_changed;
@@ -117,8 +117,8 @@ gst_vp8_decoder_start (GstVideoDecoder * decoder)
   priv->wait_keyframe = TRUE;
 
   priv->output_queue =
-      gst_queue_array_new_for_struct (sizeof (GstVp8DecoderOutputFrame), 1);
-  gst_queue_array_set_clear_func (priv->output_queue,
+      gst_vec_deque_new_for_struct (sizeof (GstVp8DecoderOutputFrame), 1);
+  gst_vec_deque_set_clear_func (priv->output_queue,
       (GDestroyNotify) gst_vp8_decoder_clear_output_frame);
 
   return TRUE;
@@ -134,7 +134,7 @@ gst_vp8_decoder_reset (GstVp8Decoder * self)
   gst_clear_vp8_picture (&self->alt_ref_picture);
 
   priv->wait_keyframe = TRUE;
-  gst_queue_array_clear (priv->output_queue);
+  gst_vec_deque_clear (priv->output_queue);
 }
 
 static gboolean
@@ -149,7 +149,7 @@ gst_vp8_decoder_stop (GstVideoDecoder * decoder)
   }
 
   gst_vp8_decoder_reset (self);
-  gst_queue_array_free (priv->output_queue);
+  gst_vec_deque_free (priv->output_queue);
 
   return TRUE;
 }
@@ -480,7 +480,7 @@ gst_vp8_decoder_handle_frame (GstVideoDecoder * decoder,
     output_frame.frame = frame;
     output_frame.picture = picture;
     output_frame.self = self;
-    gst_queue_array_push_tail_struct (priv->output_queue, &output_frame);
+    gst_vec_deque_push_tail_struct (priv->output_queue, &output_frame);
   }
 
   gst_vp8_decoder_drain_output_queue (self, priv->preferred_output_delay,
@@ -530,9 +530,9 @@ gst_vp8_decoder_drain_output_queue (GstVp8Decoder * self, guint num,
 
   g_assert (klass->output_picture);
 
-  while (gst_queue_array_get_length (priv->output_queue) > num) {
+  while (gst_vec_deque_get_length (priv->output_queue) > num) {
     GstVp8DecoderOutputFrame *output_frame = (GstVp8DecoderOutputFrame *)
-        gst_queue_array_pop_head_struct (priv->output_queue);
+        gst_vec_deque_pop_head_struct (priv->output_queue);
     /* Output queued frames whatever the return value is, in order to empty
      * the queue */
     GstFlowReturn flow_ret = klass->output_picture (self,
diff --git a/subprojects/gst-plugins-bad/gst-libs/gst/codecs/gstvp9decoder.c b/subprojects/gst-plugins-bad/gst-libs/gst/codecs/gstvp9decoder.c
index 2c309ae12c..e50115078f 100644
--- a/subprojects/gst-plugins-bad/gst-libs/gst/codecs/gstvp9decoder.c
+++ b/subprojects/gst-plugins-bad/gst-libs/gst/codecs/gstvp9decoder.c
@@ -82,7 +82,7 @@ struct _GstVp9DecoderPrivate
   gboolean wait_keyframe;
   /* controls how many frames to delay when calling output_picture() */
   guint preferred_output_delay;
-  GstQueueArray *output_queue;
+  GstVecDeque *output_queue;
   gboolean is_live;
 
   gboolean input_state_changed;
@@ -164,8 +164,8 @@ gst_vp9_decoder_start (GstVideoDecoder * decoder)
   priv->render_height = 0;
 
   priv->output_queue =
-      gst_queue_array_new_for_struct (sizeof (GstVp9DecoderOutputFrame), 1);
-  gst_queue_array_set_clear_func (priv->output_queue,
+      gst_vec_deque_new_for_struct (sizeof (GstVp9DecoderOutputFrame), 1);
+  gst_vec_deque_set_clear_func (priv->output_queue,
       (GDestroyNotify) gst_vp9_decoder_clear_output_frame);
 
   return TRUE;
@@ -180,7 +180,7 @@ gst_vp9_decoder_stop (GstVideoDecoder * decoder)
   g_clear_pointer (&self->input_state, gst_video_codec_state_unref);
   g_clear_pointer (&priv->parser, gst_vp9_stateful_parser_free);
   g_clear_pointer (&priv->dpb, gst_vp9_dpb_free);
-  gst_queue_array_free (priv->output_queue);
+  gst_vec_deque_free (priv->output_queue);
 
   return TRUE;
 }
@@ -305,7 +305,7 @@ gst_vp9_decoder_reset (GstVp9Decoder * self)
     gst_vp9_dpb_clear (priv->dpb);
 
   priv->wait_keyframe = TRUE;
-  gst_queue_array_clear (priv->output_queue);
+  gst_vec_deque_clear (priv->output_queue);
 }
 
 static GstFlowReturn
@@ -559,7 +559,7 @@ gst_vp9_decoder_handle_frame (GstVideoDecoder * decoder,
     output_frame.frame = frame;
     output_frame.picture = picture;
     output_frame.self = self;
-    gst_queue_array_push_tail_struct (priv->output_queue, &output_frame);
+    gst_vec_deque_push_tail_struct (priv->output_queue, &output_frame);
   }
 
   gst_vp9_decoder_drain_output_queue (self,
@@ -609,9 +609,9 @@ gst_vp9_decoder_drain_output_queue (GstVp9Decoder * self, guint num,
 
   g_assert (klass->output_picture);
 
-  while (gst_queue_array_get_length (priv->output_queue) > num) {
+  while (gst_vec_deque_get_length (priv->output_queue) > num) {
     GstVp9DecoderOutputFrame *output_frame = (GstVp9DecoderOutputFrame *)
-        gst_queue_array_pop_head_struct (priv->output_queue);
+        gst_vec_deque_pop_head_struct (priv->output_queue);
     /* Output queued frames whatever the return value is, in order to empty
      * the queue */
     GstFlowReturn flow_ret = klass->output_picture (self,
diff --git a/subprojects/gst-plugins-bad/gst-libs/gst/d3d12/gstd3d12fencedatapool.cpp b/subprojects/gst-plugins-bad/gst-libs/gst/d3d12/gstd3d12fencedatapool.cpp
index f4abc6be26..4069abe3cd 100644
--- a/subprojects/gst-plugins-bad/gst-libs/gst/d3d12/gstd3d12fencedatapool.cpp
+++ b/subprojects/gst-plugins-bad/gst-libs/gst/d3d12/gstd3d12fencedatapool.cpp
@@ -50,18 +50,18 @@ struct _GstD3D12FenceData : public GstMiniObject
 {
   _GstD3D12FenceData ()
   {
-    queue = gst_queue_array_new_for_struct (sizeof (NotifyData), 4);
-    gst_queue_array_set_clear_func (queue,
+    queue = gst_vec_deque_new_for_struct (sizeof (NotifyData), 4);
+    gst_vec_deque_set_clear_func (queue,
         (GDestroyNotify) notify_data_clear_func);
   }
 
   ~_GstD3D12FenceData ()
   {
-    gst_queue_array_free (queue);
+    gst_vec_deque_free (queue);
   }
 
   GstD3D12FenceDataPool *pool = nullptr;
-  GstQueueArray *queue;
+  GstVecDeque *queue;
 };
 
 GST_DEFINE_MINI_OBJECT_TYPE (GstD3D12FenceData, gst_d3d12_fence_data);
@@ -139,7 +139,7 @@ gst_d3d12_fence_data_pool_release (GstD3D12FenceDataPool * pool,
     GstD3D12FenceData * data)
 {
   auto priv = pool->priv;
-  gst_queue_array_clear (data->queue);
+  gst_vec_deque_clear (data->queue);
 
   {
     std::lock_guard < std::mutex > lk (priv->lock);
@@ -229,7 +229,7 @@ gst_d3d12_fence_data_add_notify_internal (GstD3D12FenceData * data,
   notify_data.user_data = user_data;
   notify_data.notify = notify;
 
-  gst_queue_array_push_tail_struct (data->queue, &notify_data);
+  gst_vec_deque_push_tail_struct (data->queue, &notify_data);
 }
 
 /**
diff --git a/subprojects/gst-plugins-bad/gst/codectimestamper/gstcodectimestamper.c b/subprojects/gst-plugins-bad/gst/codectimestamper/gstcodectimestamper.c
index c30f88d5c3..33fd42cfae 100644
--- a/subprojects/gst-plugins-bad/gst/codectimestamper/gstcodectimestamper.c
+++ b/subprojects/gst-plugins-bad/gst/codectimestamper/gstcodectimestamper.c
@@ -48,7 +48,7 @@ struct _GstCodecTimestamperPrivate
   GstSegment in_segment;
 
   GList *current_frame_events;
-  GstQueueArray *queue;
+  GstVecDeque *queue;
   GArray *timestamp_queue;
 
   gint fps_n;
@@ -194,8 +194,8 @@ gst_codec_timestamper_init (GstCodecTimestamper * self,
   gst_element_add_pad (GST_ELEMENT (self), self->srcpad);
 
   priv->queue =
-      gst_queue_array_new_for_struct (sizeof (GstCodecTimestamperFrame), 16);
-  gst_queue_array_set_clear_func (priv->queue,
+      gst_vec_deque_new_for_struct (sizeof (GstCodecTimestamperFrame), 16);
+  gst_vec_deque_set_clear_func (priv->queue,
       (GDestroyNotify) gst_codec_timestamper_clear_frame);
   priv->timestamp_queue =
       g_array_sized_new (FALSE, FALSE, sizeof (GstClockTime), 16);
@@ -210,7 +210,7 @@ gst_codec_timestamper_finalize (GObject * object)
   GstCodecTimestamper *self = GST_CODEC_TIMESTAMPER (object);
   GstCodecTimestamperPrivate *priv = self->priv;
 
-  gst_queue_array_free (priv->queue);
+  gst_vec_deque_free (priv->queue);
   g_array_unref (priv->timestamp_queue);
   g_rec_mutex_clear (&priv->lock);
 
@@ -301,9 +301,9 @@ gst_codec_timestamper_flush (GstCodecTimestamper * self)
 {
   GstCodecTimestamperPrivate *priv = self->priv;
 
-  while (gst_queue_array_get_length (priv->queue) > 0) {
+  while (gst_vec_deque_get_length (priv->queue) > 0) {
     GstCodecTimestamperFrame *frame = (GstCodecTimestamperFrame *)
-        gst_queue_array_pop_head_struct (priv->queue);
+        gst_vec_deque_pop_head_struct (priv->queue);
 
     gst_codec_timestamper_flush_events (self, &frame->events);
     gst_codec_timestamper_clear_frame (frame);
@@ -471,7 +471,7 @@ gst_codec_timestamper_process_output_frame (GstCodecTimestamper * self)
   guint len;
   GstCodecTimestamperFrame *frame;
 
-  len = gst_queue_array_get_length (priv->queue);
+  len = gst_vec_deque_get_length (priv->queue);
   if (len < priv->window_size) {
     GST_TRACE_OBJECT (self, "Need more data, queued %d/%d", len,
         priv->window_size);
@@ -479,7 +479,7 @@ gst_codec_timestamper_process_output_frame (GstCodecTimestamper * self)
   }
 
   frame = (GstCodecTimestamperFrame *)
-      gst_queue_array_pop_head_struct (priv->queue);
+      gst_vec_deque_pop_head_struct (priv->queue);
 
   return gst_codec_timestamper_output_frame (self, frame);
 }
@@ -491,9 +491,9 @@ gst_codec_timestamper_drain (GstCodecTimestamper * self)
 
   GST_DEBUG_OBJECT (self, "Draining");
 
-  while (gst_queue_array_get_length (priv->queue) > 0) {
+  while (gst_vec_deque_get_length (priv->queue) > 0) {
     GstCodecTimestamperFrame *frame = (GstCodecTimestamperFrame *)
-        gst_queue_array_pop_head_struct (priv->queue);
+        gst_vec_deque_pop_head_struct (priv->queue);
     gst_codec_timestamper_output_frame (self, frame);
   }
 
@@ -582,7 +582,7 @@ gst_codec_timestamper_chain (GstPad * pad, GstObject * parent,
       ", adjusted pts %" GST_TIME_FORMAT,
       GST_TIME_ARGS (GST_BUFFER_PTS (buffer)), GST_TIME_ARGS (pts));
 
-  gst_queue_array_push_tail_struct (priv->queue, &frame);
+  gst_vec_deque_push_tail_struct (priv->queue, &frame);
   if (GST_CLOCK_TIME_IS_VALID (frame.pts)) {
     g_array_append_val (priv->timestamp_queue, frame.pts);
     g_array_sort (priv->timestamp_queue, (GCompareFunc) pts_compare_func);
@@ -701,7 +701,7 @@ gst_codec_timestamper_reset (GstCodecTimestamper * self)
 {
   GstCodecTimestamperPrivate *priv = self->priv;
 
-  gst_queue_array_clear (priv->queue);
+  gst_vec_deque_clear (priv->queue);
   g_array_set_size (priv->timestamp_queue, 0);
   priv->fps_n = 0;
   priv->fps_d = 1;
diff --git a/subprojects/gst-plugins-bad/gst/mpegpsmux/psmuxstream.c b/subprojects/gst-plugins-bad/gst/mpegpsmux/psmuxstream.c
index 25b201097a..92564c22c2 100644
--- a/subprojects/gst-plugins-bad/gst/mpegpsmux/psmuxstream.c
+++ b/subprojects/gst-plugins-bad/gst/mpegpsmux/psmuxstream.c
@@ -512,7 +512,7 @@ psmux_stream_add_data (PsMuxStream * stream, GstBuffer * buffer,
     stream->last_pts = pts;
 
   stream->bytes_avail += packet->map.size;
-  /* FIXME: perhaps use GstQueueArray instead? */
+  /* FIXME: perhaps use GstVecDeque instead? */
   stream->buffers = g_list_append (stream->buffers, packet);
 
 }
diff --git a/subprojects/gst-plugins-bad/sys/aja/gstajacommon.cpp b/subprojects/gst-plugins-bad/sys/aja/gstajacommon.cpp
index 8b749a017b..dd812d3984 100644
--- a/subprojects/gst-plugins-bad/sys/aja/gstajacommon.cpp
+++ b/subprojects/gst-plugins-bad/sys/aja/gstajacommon.cpp
@@ -534,17 +534,17 @@ static GstAjaMemory *_aja_memory_new_block(GstAjaAllocator *alloc,
   mem = (GstAjaMemory *)g_new0(GstAjaMemory, 1);
 
   GST_OBJECT_LOCK(alloc);
-  guint n = gst_queue_array_get_length(alloc->freed_mems);
+  guint n = gst_vec_deque_get_length(alloc->freed_mems);
   for (guint i = 0; i < n; i++) {
     FreedMemory *fmem =
-        (FreedMemory *)gst_queue_array_peek_nth_struct(alloc->freed_mems, i);
+        (FreedMemory *)gst_vec_deque_peek_nth_struct(alloc->freed_mems, i);
 
     if (fmem->size == size) {
       data = fmem->data;
       GST_TRACE_OBJECT(
           alloc, "Using cached freed memory of size %" G_GSIZE_FORMAT " at %p",
           fmem->size, fmem->data);
-      gst_queue_array_drop_struct(alloc->freed_mems, i, NULL);
+      gst_vec_deque_drop_struct(alloc->freed_mems, i, NULL);
       break;
     }
   }
@@ -625,9 +625,9 @@ static void gst_aja_allocator_free(GstAllocator *alloc, GstMemory *mem) {
     GstAjaAllocator *aja_alloc = GST_AJA_ALLOCATOR(alloc);
 
     GST_OBJECT_LOCK(aja_alloc);
-    while (gst_queue_array_get_length(aja_alloc->freed_mems) > 8) {
+    while (gst_vec_deque_get_length(aja_alloc->freed_mems) > 8) {
       FreedMemory *fmem =
-          (FreedMemory *)gst_queue_array_pop_head_struct(aja_alloc->freed_mems);
+          (FreedMemory *)gst_vec_deque_pop_head_struct(aja_alloc->freed_mems);
 
       GST_TRACE_OBJECT(
           alloc, "Freeing cached memory of size %" G_GSIZE_FORMAT " at %p",
@@ -643,7 +643,7 @@ static void gst_aja_allocator_free(GstAllocator *alloc, GstMemory *mem) {
                      mem->maxsize, dmem->data);
     fmem.data = dmem->data;
     fmem.size = mem->size;
-    gst_queue_array_push_tail_struct(aja_alloc->freed_mems, &fmem);
+    gst_vec_deque_push_tail_struct(aja_alloc->freed_mems, &fmem);
     GST_OBJECT_UNLOCK(aja_alloc);
   }
 
@@ -656,7 +656,7 @@ static void gst_aja_allocator_finalize(GObject *alloc) {
   GST_DEBUG_OBJECT(alloc, "Freeing allocator");
 
   FreedMemory *mem;
-  while ((mem = (FreedMemory *)gst_queue_array_pop_head_struct(
+  while ((mem = (FreedMemory *)gst_vec_deque_pop_head_struct(
               aja_alloc->freed_mems))) {
     GST_TRACE_OBJECT(alloc, "Freeing cached memory at %p", mem->data);
     aja_alloc->device->device->DMABufferUnlock((ULWord *)mem->data, mem->size);
@@ -696,7 +696,7 @@ GstAllocator *gst_aja_allocator_new(GstAjaNtv2Device *device) {
       (GstAjaAllocator *)g_object_new(GST_TYPE_AJA_ALLOCATOR, NULL);
 
   alloc->device = gst_aja_ntv2_device_ref(device);
-  alloc->freed_mems = gst_queue_array_new_for_struct(sizeof(FreedMemory), 16);
+  alloc->freed_mems = gst_vec_deque_new_for_struct(sizeof(FreedMemory), 16);
 
   GST_DEBUG_OBJECT(alloc, "Creating allocator for device %d",
                    device->device->GetIndexNumber());
diff --git a/subprojects/gst-plugins-bad/sys/aja/gstajacommon.h b/subprojects/gst-plugins-bad/sys/aja/gstajacommon.h
index ed1c638bf8..619a07f7e4 100644
--- a/subprojects/gst-plugins-bad/sys/aja/gstajacommon.h
+++ b/subprojects/gst-plugins-bad/sys/aja/gstajacommon.h
@@ -92,7 +92,7 @@ struct _GstAjaAllocator {
   GstAllocator allocator;
 
   GstAjaNtv2Device *device;
-  GstQueueArray *freed_mems;
+  GstVecDeque *freed_mems;
 };
 
 struct _GstAjaAllocatorClass {
diff --git a/subprojects/gst-plugins-bad/sys/aja/gstajasink.cpp b/subprojects/gst-plugins-bad/sys/aja/gstajasink.cpp
index dba75a4b57..d3b4daed4f 100644
--- a/subprojects/gst-plugins-bad/sys/aja/gstajasink.cpp
+++ b/subprojects/gst-plugins-bad/sys/aja/gstajasink.cpp
@@ -330,7 +330,7 @@ static void gst_aja_sink_init(GstAjaSink *self) {
   self->handle_ancillary_meta = DEFAULT_HANDLE_ANCILLARY_META;
 
   self->queue =
-      gst_queue_array_new_for_struct(sizeof(QueueItem), self->queue_size);
+      gst_vec_deque_new_for_struct(sizeof(QueueItem), self->queue_size);
 }
 
 void gst_aja_sink_set_property(GObject *object, guint property_id,
@@ -451,8 +451,8 @@ void gst_aja_sink_finalize(GObject *object) {
   GstAjaSink *self = GST_AJA_SINK(object);
 
   g_assert(self->device == NULL);
-  g_assert(gst_queue_array_get_length(self->queue) == 0);
-  g_clear_pointer(&self->queue, gst_queue_array_free);
+  g_assert(gst_vec_deque_get_length(self->queue) == 0);
+  g_clear_pointer(&self->queue, gst_vec_deque_free);
 
   g_mutex_clear(&self->queue_lock);
   g_cond_clear(&self->queue_cond);
@@ -557,7 +557,7 @@ static gboolean gst_aja_sink_stop(GstAjaSink *self) {
   self->configured_audio_channels = 0;
   GST_OBJECT_UNLOCK(self);
 
-  while ((item = (QueueItem *)gst_queue_array_pop_head_struct(self->queue))) {
+  while ((item = (QueueItem *)gst_vec_deque_pop_head_struct(self->queue))) {
     if (item->type == QUEUE_ITEM_TYPE_FRAME) {
       gst_buffer_unmap(item->video_buffer, &item->video_map);
       gst_buffer_unref(item->video_buffer);
@@ -1417,7 +1417,7 @@ static gboolean gst_aja_sink_event(GstBaseSink *bsink, GstEvent *event) {
 
       g_mutex_lock(&self->queue_lock);
       while (
-          (item = (QueueItem *)gst_queue_array_pop_head_struct(self->queue))) {
+          (item = (QueueItem *)gst_vec_deque_pop_head_struct(self->queue))) {
         if (item->type == QUEUE_ITEM_TYPE_FRAME) {
           gst_buffer_unmap(item->video_buffer, &item->video_map);
           gst_buffer_unref(item->video_buffer);
@@ -1842,8 +1842,8 @@ static GstFlowReturn gst_aja_sink_render(GstBaseSink *bsink,
   }
 
   g_mutex_lock(&self->queue_lock);
-  while (gst_queue_array_get_length(self->queue) >= self->queue_size) {
-    QueueItem *tmp = (QueueItem *)gst_queue_array_pop_head_struct(self->queue);
+  while (gst_vec_deque_get_length(self->queue) >= self->queue_size) {
+    QueueItem *tmp = (QueueItem *)gst_vec_deque_pop_head_struct(self->queue);
 
     if (tmp->type == QUEUE_ITEM_TYPE_FRAME) {
       GST_WARNING_OBJECT(self, "Element queue overrun, dropping old frame");
@@ -1874,9 +1874,9 @@ static GstFlowReturn gst_aja_sink_render(GstBaseSink *bsink,
 
   GST_TRACE_OBJECT(self, "Queuing frame video %p audio %p", item.video_map.data,
                    item.audio_buffer ? item.audio_map.data : NULL);
-  gst_queue_array_push_tail_struct(self->queue, &item);
-  GST_TRACE_OBJECT(self, "%u frames queued",
-                   gst_queue_array_get_length(self->queue));
+  gst_vec_deque_push_tail_struct(self->queue, &item);
+  GST_TRACE_OBJECT(self, "%" G_GSIZE_FORMAT " frames queued",
+                   gst_vec_deque_get_length(self->queue));
   g_cond_signal(&self->queue_cond);
   g_mutex_unlock(&self->queue_lock);
 
@@ -1907,7 +1907,7 @@ static void output_thread_func(AJAThread *thread, void *data) {
 
   g_mutex_lock(&self->queue_lock);
 restart:
-  if (self->draining && gst_queue_array_get_length(self->queue) == 0) {
+  if (self->draining && gst_vec_deque_get_length(self->queue) == 0) {
     GST_DEBUG_OBJECT(self, "Drained");
     self->draining = FALSE;
     g_cond_signal(&self->drain_cond);
@@ -1916,7 +1916,7 @@ restart:
   GST_DEBUG_OBJECT(self, "Waiting for playing or shutdown");
   while ((!self->playing && !self->shutdown) ||
          (self->playing &&
-          gst_queue_array_get_length(self->queue) < self->queue_size / 2 &&
+          gst_vec_deque_get_length(self->queue) < self->queue_size / 2 &&
           !self->eos))
     g_cond_wait(&self->queue_cond, &self->queue_lock);
   if (self->shutdown) {
@@ -2011,7 +2011,7 @@ restart:
 
   g_mutex_lock(&self->queue_lock);
   while (self->playing && !self->shutdown &&
-         !(self->draining && gst_queue_array_get_length(self->queue) == 0)) {
+         !(self->draining && gst_vec_deque_get_length(self->queue) == 0)) {
     AUTOCIRCULATE_STATUS status;
 
     self->device->device->AutoCirculateGetStatus(self->channel, status);
@@ -2061,7 +2061,7 @@ restart:
     if (status.GetNumAvailableOutputFrames() > 1) {
       QueueItem item, *item_p;
 
-      while ((item_p = (QueueItem *)gst_queue_array_pop_head_struct(
+      while ((item_p = (QueueItem *)gst_vec_deque_pop_head_struct(
                   self->queue)) == NULL &&
              self->playing && !self->shutdown && !self->draining) {
         GST_DEBUG_OBJECT(
@@ -2096,8 +2096,8 @@ restart:
         continue;
       }
 
-      GST_TRACE_OBJECT(self, "%u frames queued",
-                       gst_queue_array_get_length(self->queue));
+      GST_TRACE_OBJECT(self, "%" G_GSIZE_FORMAT " frames queued",
+                       gst_vec_deque_get_length(self->queue));
 
       item = *item_p;
       g_mutex_unlock(&self->queue_lock);
diff --git a/subprojects/gst-plugins-bad/sys/aja/gstajasink.h b/subprojects/gst-plugins-bad/sys/aja/gstajasink.h
index 4a30838db9..bc58b220fb 100644
--- a/subprojects/gst-plugins-bad/sys/aja/gstajasink.h
+++ b/subprojects/gst-plugins-bad/sys/aja/gstajasink.h
@@ -47,7 +47,7 @@ struct _GstAjaSink {
   // Everything below protected by queue lock
   GMutex queue_lock;
   GCond queue_cond;
-  GstQueueArray *queue;
+  GstVecDeque *queue;
   gboolean eos;
   gboolean playing;
   gboolean shutdown;
diff --git a/subprojects/gst-plugins-bad/sys/aja/gstajasrc.cpp b/subprojects/gst-plugins-bad/sys/aja/gstajasrc.cpp
index 76f61eda16..908230d23c 100644
--- a/subprojects/gst-plugins-bad/sys/aja/gstajasrc.cpp
+++ b/subprojects/gst-plugins-bad/sys/aja/gstajasrc.cpp
@@ -102,7 +102,7 @@ enum {
   PROP_ATTACH_ANCILLARY_META,
 };
 
-// Make these plain C structs for usage in GstQueueArray
+// Make these plain C structs for usage in GstVecDeque
 G_BEGIN_DECLS
 
 typedef enum {
@@ -422,7 +422,7 @@ static void gst_aja_src_init(GstAjaSrc *self) {
   self->attach_ancillary_meta = DEFAULT_ATTACH_ANCILLARY_META;
 
   self->queue =
-      gst_queue_array_new_for_struct(sizeof(QueueItem), self->queue_size);
+      gst_vec_deque_new_for_struct(sizeof(QueueItem), self->queue_size);
   gst_base_src_set_live(GST_BASE_SRC_CAST(self), TRUE);
   gst_base_src_set_format(GST_BASE_SRC_CAST(self), GST_FORMAT_TIME);
 
@@ -575,8 +575,8 @@ void gst_aja_src_finalize(GObject *object) {
   GstAjaSrc *self = GST_AJA_SRC(object);
 
   g_assert(self->device == NULL);
-  g_assert(gst_queue_array_get_length(self->queue) == 0);
-  g_clear_pointer(&self->queue, gst_queue_array_free);
+  g_assert(gst_vec_deque_get_length(self->queue) == 0);
+  g_clear_pointer(&self->queue, gst_vec_deque_free);
 
   gst_clear_object(&self->clock);
 
@@ -1576,7 +1576,7 @@ static gboolean gst_aja_src_stop(GstAjaSrc *self) {
   self->configured_audio_channels = 0;
   GST_OBJECT_UNLOCK(self);
 
-  while ((item = (QueueItem *)gst_queue_array_pop_head_struct(self->queue))) {
+  while ((item = (QueueItem *)gst_vec_deque_pop_head_struct(self->queue))) {
     queue_item_clear(item);
   }
   self->queue_num_frames = 0;
@@ -1768,7 +1768,7 @@ next_item:
   item.type = QUEUE_ITEM_TYPE_DUMMY;
 
   g_mutex_lock(&self->queue_lock);
-  while (gst_queue_array_is_empty(self->queue) && !self->flushing) {
+  while (gst_vec_deque_is_empty(self->queue) && !self->flushing) {
     g_cond_wait(&self->queue_cond, &self->queue_lock);
   }
 
@@ -1778,7 +1778,7 @@ next_item:
     return GST_FLOW_FLUSHING;
   }
 
-  item = *(QueueItem *)gst_queue_array_pop_head_struct(self->queue);
+  item = *(QueueItem *)gst_vec_deque_pop_head_struct(self->queue);
   if (item.type == QUEUE_ITEM_TYPE_FRAME) {
     self->queue_num_frames -= 1;
   }
@@ -2283,7 +2283,7 @@ next_item:
     g_free(__dbg);                                                          \
     __msg = gst_message_new_error(GST_OBJECT(el), __err, __fmt_dbg);        \
     QueueItem item = {.type = QUEUE_ITEM_TYPE_ERROR, .error{.msg = __msg}}; \
-    gst_queue_array_push_tail_struct(el->queue, &item);                     \
+    gst_vec_deque_push_tail_struct(el->queue, &item);                     \
     g_cond_signal(&el->queue_cond);                                         \
   }                                                                         \
   G_STMT_END;
@@ -2386,7 +2386,7 @@ restart:
               .signal_change = {.have_signal = FALSE,
                                 .detected_format = ::NTV2_FORMAT_UNKNOWN,
                                 .vpid = 0}};
-          gst_queue_array_push_tail_struct(self->queue, &item);
+          gst_vec_deque_push_tail_struct(self->queue, &item);
           g_cond_signal(&self->queue_cond);
           have_signal = FALSE;
           discont = TRUE;
@@ -2511,7 +2511,7 @@ restart:
                               .detected_format = ::NTV2_FORMAT_UNKNOWN,
                               .vpid = 0}};
         last_detected_video_format = ::NTV2_FORMAT_UNKNOWN;
-        gst_queue_array_push_tail_struct(self->queue, &item);
+        gst_vec_deque_push_tail_struct(self->queue, &item);
         g_cond_signal(&self->queue_cond);
         have_signal = FALSE;
         discont = TRUE;
@@ -2548,7 +2548,7 @@ restart:
                               .detected_format = current_video_format,
                               .vpid = vpid_a}};
         last_detected_video_format = current_video_format;
-        gst_queue_array_push_tail_struct(self->queue, &item);
+        gst_vec_deque_push_tail_struct(self->queue, &item);
         g_cond_signal(&self->queue_cond);
         have_signal = FALSE;
         discont = TRUE;
@@ -2564,7 +2564,7 @@ restart:
                             .detected_format = current_video_format,
                             .vpid = vpid_a}};
       last_detected_video_format = current_video_format;
-      gst_queue_array_push_tail_struct(self->queue, &item);
+      gst_vec_deque_push_tail_struct(self->queue, &item);
       g_cond_signal(&self->queue_cond);
     }
 
@@ -2606,7 +2606,7 @@ restart:
             .signal_change = {.have_signal = TRUE,
                               .detected_format = current_video_format,
                               .vpid = vpid_a}};
-        gst_queue_array_push_tail_struct(self->queue, &item);
+        gst_vec_deque_push_tail_struct(self->queue, &item);
         g_cond_signal(&self->queue_cond);
         have_signal = TRUE;
       }
@@ -2866,7 +2866,7 @@ restart:
                           .frames_dropped = {.driver_side = TRUE,
                                              .timestamp_start = timestamp,
                                              .timestamp_end = timestamp_end}};
-        gst_queue_array_push_tail_struct(self->queue, &item);
+        gst_vec_deque_push_tail_struct(self->queue, &item);
         g_cond_signal(&self->queue_cond);
 
         frames_dropped_last = transfer_status.acFramesDropped;
@@ -2906,11 +2906,11 @@ restart:
       frame_stamp.GetInputTimeCode(time_code, tc_index);
 
       while (self->queue_num_frames >= self->queue_size) {
-        guint n = gst_queue_array_get_length(self->queue);
+        guint n = gst_vec_deque_get_length(self->queue);
 
         for (guint i = 0; i < n; i++) {
           QueueItem *tmp =
-              (QueueItem *)gst_queue_array_peek_nth_struct(self->queue, i);
+              (QueueItem *)gst_vec_deque_peek_nth_struct(self->queue, i);
           if (tmp->type == QUEUE_ITEM_TYPE_FRAME) {
             GST_WARNING_OBJECT(self,
                                "Element queue overrun, dropping old frame");
@@ -2926,8 +2926,8 @@ restart:
                                               self->configured_info.fps_d,
                                               self->configured_info.fps_n)}};
             queue_item_clear(tmp);
-            gst_queue_array_drop_struct(self->queue, i, NULL);
-            gst_queue_array_push_tail_struct(self->queue, &item);
+            gst_vec_deque_drop_struct(self->queue, i, NULL);
+            gst_vec_deque_push_tail_struct(self->queue, &item);
             self->queue_num_frames -= 1;
             discont = TRUE;
             g_cond_signal(&self->queue_cond);
@@ -2958,7 +2958,7 @@ restart:
 
       GST_TRACE_OBJECT(self, "Queuing frame %" GST_TIME_FORMAT,
                        GST_TIME_ARGS(capture_time));
-      gst_queue_array_push_tail_struct(self->queue, &item);
+      gst_vec_deque_push_tail_struct(self->queue, &item);
       self->queue_num_frames += 1;
       GST_TRACE_OBJECT(self, "%u frames queued", self->queue_num_frames);
       g_cond_signal(&self->queue_cond);
@@ -2979,7 +2979,7 @@ restart:
                                 .detected_format = current_video_format,
                                 .vpid = vpid_a}};
           last_detected_video_format = current_video_format;
-          gst_queue_array_push_tail_struct(self->queue, &item);
+          gst_vec_deque_push_tail_struct(self->queue, &item);
           g_cond_signal(&self->queue_cond);
           have_signal = FALSE;
           discont = TRUE;
diff --git a/subprojects/gst-plugins-bad/sys/aja/gstajasrc.h b/subprojects/gst-plugins-bad/sys/aja/gstajasrc.h
index bd76e8afb2..c40d49ccbc 100644
--- a/subprojects/gst-plugins-bad/sys/aja/gstajasrc.h
+++ b/subprojects/gst-plugins-bad/sys/aja/gstajasrc.h
@@ -47,7 +47,7 @@ struct _GstAjaSrc {
   // Everything below protected by queue lock
   GMutex queue_lock;
   GCond queue_cond;
-  GstQueueArray *queue;
+  GstVecDeque *queue;
   guint queue_num_frames;
   gboolean playing;
   gboolean shutdown;
diff --git a/subprojects/gst-plugins-bad/sys/applemedia/vtdec.c b/subprojects/gst-plugins-bad/sys/applemedia/vtdec.c
index 0c6f7d6b9c..b2ea9e5470 100644
--- a/subprojects/gst-plugins-bad/sys/applemedia/vtdec.c
+++ b/subprojects/gst-plugins-bad/sys/applemedia/vtdec.c
@@ -232,7 +232,7 @@ gst_vtdec_start (GstVideoDecoder * decoder)
   vtdec->is_flushing = FALSE;
   vtdec->is_draining = FALSE;
   vtdec->downstream_ret = GST_FLOW_OK;
-  vtdec->reorder_queue = gst_queue_array_new (0);
+  vtdec->reorder_queue = gst_vec_deque_new (0);
 
   /* Create the output task, but pause it immediately */
   vtdec->pause_task = TRUE;
@@ -262,10 +262,10 @@ gst_vtdec_stop (GstVideoDecoder * decoder)
   gst_vtdec_drain_decoder (GST_VIDEO_DECODER_CAST (vtdec), TRUE);
   vtdec->downstream_ret = GST_FLOW_FLUSHING;
 
-  while ((frame = gst_queue_array_pop_head (vtdec->reorder_queue))) {
+  while ((frame = gst_vec_deque_pop_head (vtdec->reorder_queue))) {
     gst_video_decoder_release_frame (decoder, frame);
   }
-  gst_queue_array_free (vtdec->reorder_queue);
+  gst_vec_deque_free (vtdec->reorder_queue);
   vtdec->reorder_queue = NULL;
 
   gst_pad_stop_task (GST_VIDEO_DECODER_SRC_PAD (decoder));
@@ -306,7 +306,7 @@ gst_vtdec_output_loop (GstVtdec * vtdec)
   gboolean is_flushing;
 
   g_mutex_lock (&vtdec->queue_mutex);
-  while (gst_queue_array_is_empty (vtdec->reorder_queue)
+  while (gst_vec_deque_is_empty (vtdec->reorder_queue)
       && !vtdec->pause_task && !vtdec->is_flushing && !vtdec->is_draining) {
     g_cond_wait (&vtdec->queue_cond, &vtdec->queue_mutex);
   }
@@ -319,9 +319,9 @@ gst_vtdec_output_loop (GstVtdec * vtdec)
 
   /* push a buffer if there are enough frames to guarantee 
    * that we push in PTS order, or if we're draining/flushing */
-  while ((gst_queue_array_get_length (vtdec->reorder_queue) >=
+  while ((gst_vec_deque_get_length (vtdec->reorder_queue) >=
           vtdec->dbp_size) || vtdec->is_flushing || vtdec->is_draining) {
-    frame = gst_queue_array_pop_head (vtdec->reorder_queue);
+    frame = gst_vec_deque_pop_head (vtdec->reorder_queue);
     is_flushing = vtdec->is_flushing;
     g_cond_signal (&vtdec->queue_cond);
     g_mutex_unlock (&vtdec->queue_mutex);
@@ -365,7 +365,7 @@ gst_vtdec_output_loop (GstVtdec * vtdec)
   if (ret != GST_FLOW_OK) {
     g_mutex_lock (&vtdec->queue_mutex);
 
-    while ((frame = gst_queue_array_pop_head (vtdec->reorder_queue))) {
+    while ((frame = gst_vec_deque_pop_head (vtdec->reorder_queue))) {
       GST_LOG_OBJECT (vtdec, "flushing frame %d", frame->system_frame_number);
       gst_video_decoder_release_frame (decoder, frame);
     }
@@ -1256,16 +1256,17 @@ gst_vtdec_session_output_callback (void *decompression_output_ref_con,
    * which will lock up if we decide to wait in this callback, creating a deadlock. */
   push_anyway = vtdec->is_flushing || vtdec->is_draining;
   while (!push_anyway
-      && gst_queue_array_get_length (vtdec->reorder_queue) >
+      && gst_vec_deque_get_length (vtdec->reorder_queue) >
       vtdec->dbp_size * 2 + 1) {
     g_cond_wait (&vtdec->queue_cond, &vtdec->queue_mutex);
     push_anyway = vtdec->is_flushing || vtdec->is_draining;
   }
 
-  gst_queue_array_push_sorted (vtdec->reorder_queue, frame, sort_frames_by_pts,
+  gst_vec_deque_push_sorted (vtdec->reorder_queue, frame, sort_frames_by_pts,
       NULL);
-  GST_LOG ("pushed frame %d, queue length %d", frame->decode_frame_number,
-      gst_queue_array_get_length (vtdec->reorder_queue));
+  GST_LOG ("pushed frame %d, queue length %" G_GSIZE_FORMAT,
+      frame->decode_frame_number,
+      gst_vec_deque_get_length (vtdec->reorder_queue));
   g_cond_signal (&vtdec->queue_cond);
   g_mutex_unlock (&vtdec->queue_mutex);
 }
diff --git a/subprojects/gst-plugins-bad/sys/applemedia/vtdec.h b/subprojects/gst-plugins-bad/sys/applemedia/vtdec.h
index f7385d8f80..246f4ff5b1 100644
--- a/subprojects/gst-plugins-bad/sys/applemedia/vtdec.h
+++ b/subprojects/gst-plugins-bad/sys/applemedia/vtdec.h
@@ -56,7 +56,7 @@ struct _GstVtdec
   GstVideoTextureCache *texture_cache;
   GstGLContextHelper *ctxh;
 
-  GstQueueArray *reorder_queue;
+  GstVecDeque *reorder_queue;
   gint dbp_size;
   GMutex queue_mutex;
   GCond queue_cond;
diff --git a/subprojects/gst-plugins-bad/sys/applemedia/vtenc.c b/subprojects/gst-plugins-bad/sys/applemedia/vtenc.c
index 20800bbb71..95775195c4 100644
--- a/subprojects/gst-plugins-bad/sys/applemedia/vtenc.c
+++ b/subprojects/gst-plugins-bad/sys/applemedia/vtenc.c
@@ -781,9 +781,9 @@ gst_vtenc_start (GstVideoEncoder * enc)
   self->is_flushing = FALSE;
   self->downstream_ret = GST_FLOW_OK;
 
-  self->output_queue = gst_queue_array_new (VTENC_OUTPUT_QUEUE_SIZE);
-  /* Set clear_func to unref all remaining frames in gst_queue_array_free() */
-  gst_queue_array_set_clear_func (self->output_queue,
+  self->output_queue = gst_vec_deque_new (VTENC_OUTPUT_QUEUE_SIZE);
+  /* Set clear_func to unref all remaining frames in gst_vec_deque_free() */
+  gst_vec_deque_set_clear_func (self->output_queue,
       (GDestroyNotify) gst_video_codec_frame_unref);
 
   /* Create the output task, but pause it immediately */
@@ -830,7 +830,7 @@ gst_vtenc_stop (GstVideoEncoder * enc)
   self->video_info.width = self->video_info.height = 0;
   self->video_info.fps_n = self->video_info.fps_d = 0;
 
-  gst_queue_array_free (self->output_queue);
+  gst_vec_deque_free (self->output_queue);
   self->output_queue = NULL;
 
   return TRUE;
@@ -2039,7 +2039,7 @@ gst_vtenc_enqueue_buffer (void *outputCallbackRefCon,
   /* Limit the amount of frames in our output queue
    * to avoid processing too many frames ahead */
   g_mutex_lock (&self->queue_mutex);
-  while (gst_queue_array_get_length (self->output_queue) >
+  while (gst_vec_deque_get_length (self->output_queue) >
       VTENC_OUTPUT_QUEUE_SIZE) {
     g_cond_wait (&self->queue_cond, &self->queue_mutex);
   }
@@ -2058,7 +2058,7 @@ beach:
   }
 
   /* Buffer-less frames will be discarded in the output loop */
-  gst_queue_array_push_tail (self->output_queue, frame);
+  gst_vec_deque_push_tail (self->output_queue, frame);
   g_cond_signal (&self->queue_cond);
   g_mutex_unlock (&self->queue_mutex);
 }
@@ -2072,7 +2072,7 @@ gst_vtenc_loop (GstVTEnc * self)
   gboolean should_pause;
 
   g_mutex_lock (&self->queue_mutex);
-  while (gst_queue_array_is_empty (self->output_queue) && !self->pause_task
+  while (gst_vec_deque_is_empty (self->output_queue) && !self->pause_task
       && !self->is_flushing) {
     g_cond_wait (&self->queue_cond, &self->queue_mutex);
   }
@@ -2083,7 +2083,7 @@ gst_vtenc_loop (GstVTEnc * self)
     return;
   }
 
-  while ((outframe = gst_queue_array_pop_head (self->output_queue))) {
+  while ((outframe = gst_vec_deque_pop_head (self->output_queue))) {
     g_cond_signal (&self->queue_cond);
     g_mutex_unlock (&self->queue_mutex);
 
@@ -2136,7 +2136,7 @@ gst_vtenc_loop (GstVTEnc * self)
   if (ret != GST_FLOW_OK) {
     g_mutex_lock (&self->queue_mutex);
 
-    while ((outframe = gst_queue_array_pop_head (self->output_queue))) {
+    while ((outframe = gst_vec_deque_pop_head (self->output_queue))) {
       GST_LOG_OBJECT (self, "flushing frame %d", outframe->system_frame_number);
       gst_video_codec_frame_unref (outframe);
     }
diff --git a/subprojects/gst-plugins-bad/sys/applemedia/vtenc.h b/subprojects/gst-plugins-bad/sys/applemedia/vtenc.h
index ebeccfb625..4d32b0dc7c 100644
--- a/subprojects/gst-plugins-bad/sys/applemedia/vtenc.h
+++ b/subprojects/gst-plugins-bad/sys/applemedia/vtenc.h
@@ -82,7 +82,7 @@ struct _GstVTEnc
   CFDictionaryRef keyframe_props;
   GstClockTime dts_offset;
 
-  GstQueueArray * output_queue;
+  GstVecDeque * output_queue;
   /* Protects output_queue, is_flushing and pause_task */
   GMutex queue_mutex;
   GCond queue_cond;
diff --git a/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12decoder.cpp b/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12decoder.cpp
index 2a9517d0ce..2e6417f9c5 100644
--- a/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12decoder.cpp
+++ b/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12decoder.cpp
@@ -255,7 +255,7 @@ struct DecoderSessionData
 {
   DecoderSessionData ()
   {
-    output_queue = gst_queue_array_new_for_struct (sizeof (DecoderOutputData),
+    output_queue = gst_vec_deque_new_for_struct (sizeof (DecoderOutputData),
         16);
   }
 
@@ -277,7 +277,7 @@ struct DecoderSessionData
     if (output_state)
       gst_video_codec_state_unref (output_state);
 
-    gst_queue_array_free (output_queue);
+    gst_vec_deque_free (output_queue);
   }
 
   D3D12_VIDEO_DECODER_DESC decoder_desc = {};
@@ -323,7 +323,7 @@ struct DecoderSessionData
 
   std::mutex queue_lock;
   std::condition_variable queue_cond;
-  GstQueueArray *output_queue;
+  GstVecDeque *output_queue;
 
   std::recursive_mutex lock;
 };
@@ -475,7 +475,7 @@ gst_d3d12_decoder_drain (GstD3D12Decoder * decoder, GstVideoDecoder * videodec)
   if (priv->output_thread && priv->session) {
     auto empty_data = DecoderOutputData ();
     std::lock_guard < std::mutex > lk (priv->session->queue_lock);
-    gst_queue_array_push_tail_struct (priv->session->output_queue, &empty_data);
+    gst_vec_deque_push_tail_struct (priv->session->output_queue, &empty_data);
     priv->session->queue_cond.notify_one ();
   }
 
@@ -807,7 +807,7 @@ gst_d3d12_decoder_stop (GstD3D12Decoder * decoder)
   if (priv->output_thread && priv->session) {
     auto empty_data = DecoderOutputData ();
     std::lock_guard < std::mutex > lk (priv->session->queue_lock);
-    gst_queue_array_push_tail_struct (priv->session->output_queue, &empty_data);
+    gst_vec_deque_push_tail_struct (priv->session->output_queue, &empty_data);
     priv->session->queue_cond.notify_one ();
   }
 
@@ -1621,11 +1621,11 @@ gst_d3d12_decoder_output_loop (GstD3D12Decoder * self)
     {
       GST_LOG_OBJECT (self, "Waiting for output data");
       std::unique_lock < std::mutex > lk (priv->session->queue_lock);
-      while (gst_queue_array_is_empty (priv->session->output_queue))
+      while (gst_vec_deque_is_empty (priv->session->output_queue))
         priv->session->queue_cond.wait (lk);
 
       output_data = *((DecoderOutputData *)
-          gst_queue_array_pop_head_struct (priv->session->output_queue));
+          gst_vec_deque_pop_head_struct (priv->session->output_queue));
     }
 
     if (!output_data.frame) {
@@ -1694,7 +1694,7 @@ gst_d3d12_decoder_output_picture (GstD3D12Decoder * decoder,
   output_data.height = display_height;
 
   std::lock_guard < std::mutex > lk (priv->session->queue_lock);
-  gst_queue_array_push_tail_struct (priv->session->output_queue, &output_data);
+  gst_vec_deque_push_tail_struct (priv->session->output_queue, &output_data);
   priv->session->queue_cond.notify_one ();
 
   return priv->last_flow;
diff --git a/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12encoder.cpp b/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12encoder.cpp
index 1ba0c07a05..65e38ab9d9 100644
--- a/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12encoder.cpp
+++ b/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12encoder.cpp
@@ -62,7 +62,7 @@ struct EncoderSessionData
 {
   EncoderSessionData ()
   {
-    output_queue = gst_queue_array_new_for_struct (sizeof (EncoderOutputData),
+    output_queue = gst_vec_deque_new_for_struct (sizeof (EncoderOutputData),
         16);
   }
 
@@ -72,7 +72,7 @@ struct EncoderSessionData
       gst_buffer_pool_set_active (upload_pool, FALSE);
     gst_clear_object (&upload_pool);
     gst_clear_object (&encoder_pool);
-    gst_queue_array_free (output_queue);
+    gst_vec_deque_free (output_queue);
   }
 
   ComPtr<ID3D12VideoEncoder> encoder;
@@ -80,7 +80,7 @@ struct EncoderSessionData
 
   std::mutex queue_lock;
   std::condition_variable queue_cond;
-  GstQueueArray *output_queue;
+  GstVecDeque *output_queue;
 
   GstD3D12EncoderBufferPool *encoder_pool = nullptr;
   GstBufferPool *upload_pool = nullptr;
@@ -361,7 +361,7 @@ gst_d3d12_encoder_drain (GstD3D12Encoder * self, gboolean locked)
     GST_DEBUG_OBJECT (self, "Sending empty task");
     auto empty_data = EncoderOutputData ();
     std::lock_guard < std::mutex > lk (priv->session->queue_lock);
-    gst_queue_array_push_tail_struct (priv->session->output_queue, &empty_data);
+    gst_vec_deque_push_tail_struct (priv->session->output_queue, &empty_data);
     priv->session->queue_cond.notify_one ();
   }
 
@@ -1144,11 +1144,11 @@ gst_d3d12_encoder_output_loop (GstD3D12Encoder * self)
     {
       GST_LOG_OBJECT (self, "Waiting for output data");
       std::unique_lock < std::mutex > lk (priv->session->queue_lock);
-      while (gst_queue_array_is_empty (priv->session->output_queue))
+      while (gst_vec_deque_is_empty (priv->session->output_queue))
         priv->session->queue_cond.wait (lk);
 
       output_data = *((EncoderOutputData *)
-          gst_queue_array_pop_head_struct (priv->session->output_queue));
+          gst_vec_deque_pop_head_struct (priv->session->output_queue));
     }
 
     if (!output_data.frame) {
@@ -1474,8 +1474,7 @@ gst_d3d12_encoder_handle_frame (GstVideoEncoder * encoder,
   GST_VIDEO_ENCODER_STREAM_UNLOCK (self);
   {
     std::lock_guard < std::mutex > lk (priv->session->queue_lock);
-    gst_queue_array_push_tail_struct (priv->session->output_queue,
-        &output_data);
+    gst_vec_deque_push_tail_struct (priv->session->output_queue, &output_data);
     priv->session->queue_cond.notify_one ();
   }
   GST_VIDEO_ENCODER_STREAM_LOCK (self);
diff --git a/subprojects/gst-plugins-bad/sys/decklink/gstdecklink.cpp b/subprojects/gst-plugins-bad/sys/decklink/gstdecklink.cpp
index 47fd63eaa3..5d57463a4a 100644
--- a/subprojects/gst-plugins-bad/sys/decklink/gstdecklink.cpp
+++ b/subprojects/gst-plugins-bad/sys/decklink/gstdecklink.cpp
@@ -1344,7 +1344,7 @@ private:
   GMutex m_mutex;
   uint32_t m_lastBufferSize;
   uint32_t m_nonEmptyCalls;
-  GstQueueArray *m_buffers;
+  GstVecDeque *m_buffers;
   gint m_refcount;
 
   void _clearBufferPool ()
@@ -1354,7 +1354,7 @@ private:
     if (!m_buffers)
         return;
 
-    while ((buf = (uint8_t *) gst_queue_array_pop_head (m_buffers))) {
+    while ((buf = (uint8_t *) gst_vec_deque_pop_head (m_buffers))) {
       uint8_t offset = *(buf - 1);
       void *alloc_buf = buf - 128 + offset;
         g_free (alloc_buf);
@@ -1369,13 +1369,13 @@ public:
   {
     g_mutex_init (&m_mutex);
 
-    m_buffers = gst_queue_array_new (60);
+    m_buffers = gst_vec_deque_new (60);
   }
 
   virtual ~ GStreamerDecklinkMemoryAllocator () {
     Decommit ();
 
-    gst_queue_array_free (m_buffers);
+    gst_vec_deque_free (m_buffers);
 
     g_mutex_clear (&m_mutex);
   }
@@ -1429,7 +1429,7 @@ public:
     }
 
     /* Look if there is a free buffer in the pool */
-    if (!(buf = (uint8_t *) gst_queue_array_pop_head (m_buffers))) {
+    if (!(buf = (uint8_t *) gst_vec_deque_pop_head (m_buffers))) {
       /* If not, alloc a new one */
       buf = (uint8_t *) g_malloc (bufferSize + 128);
 
@@ -1454,9 +1454,9 @@ public:
 
     /* If there are still unused buffers in the pool
      * remove one of them every fifth call */
-    if (gst_queue_array_get_length (m_buffers) > 0) {
+    if (gst_vec_deque_get_length (m_buffers) > 0) {
       if (++m_nonEmptyCalls >= 5) {
-        buf = (uint8_t *) gst_queue_array_pop_head (m_buffers);
+        buf = (uint8_t *) gst_vec_deque_pop_head (m_buffers);
         uint8_t offset = *(buf - 1);
         void *alloc_buf = buf - 128 + offset;
         g_free (alloc_buf);
@@ -1480,7 +1480,7 @@ public:
     uint8_t *alloc_buffer = ((uint8_t *) buffer) - 128 + offset;
     uint32_t size = *(uint32_t *) alloc_buffer;
     if (size == m_lastBufferSize) {
-      gst_queue_array_push_tail (m_buffers, buffer);
+      gst_vec_deque_push_tail (m_buffers, buffer);
     } else {
       g_free (alloc_buffer);
     }
diff --git a/subprojects/gst-plugins-bad/sys/decklink/gstdecklinkaudiosrc.cpp b/subprojects/gst-plugins-bad/sys/decklink/gstdecklinkaudiosrc.cpp
index 95de53a2b1..fac07c2f59 100644
--- a/subprojects/gst-plugins-bad/sys/decklink/gstdecklinkaudiosrc.cpp
+++ b/subprojects/gst-plugins-bad/sys/decklink/gstdecklinkaudiosrc.cpp
@@ -260,7 +260,7 @@ gst_decklink_audio_src_init (GstDecklinkAudioSrc * self)
   g_cond_init (&self->cond);
 
   self->current_packets =
-      gst_queue_array_new_for_struct (sizeof (CapturePacket),
+      gst_vec_deque_new_for_struct (sizeof (CapturePacket),
       DEFAULT_BUFFER_SIZE);
 
   self->skipped_last = 0;
@@ -353,12 +353,12 @@ gst_decklink_audio_src_finalize (GObject * object)
   g_mutex_clear (&self->lock);
   g_cond_clear (&self->cond);
   if (self->current_packets) {
-    while (gst_queue_array_get_length (self->current_packets) > 0) {
+    while (gst_vec_deque_get_length (self->current_packets) > 0) {
       CapturePacket *tmp = (CapturePacket *)
-          gst_queue_array_pop_head_struct (self->current_packets);
+          gst_vec_deque_pop_head_struct (self->current_packets);
       capture_packet_clear (tmp);
     }
-    gst_queue_array_free (self->current_packets);
+    gst_vec_deque_free (self->current_packets);
     self->current_packets = NULL;
   }
 
@@ -570,10 +570,10 @@ gst_decklink_audio_src_got_packet (GstElement * element,
     CapturePacket p;
     guint skipped_packets = 0;
 
-    while (gst_queue_array_get_length (self->current_packets) >=
+    while (gst_vec_deque_get_length (self->current_packets) >=
         self->buffer_size) {
       CapturePacket *tmp = (CapturePacket *)
-          gst_queue_array_pop_head_struct (self->current_packets);
+          gst_vec_deque_pop_head_struct (self->current_packets);
       if (skipped_packets == 0 && self->skipped_last == 0)
         self->skip_from_timestamp = tmp->timestamp;
       skipped_packets++;
@@ -609,7 +609,7 @@ gst_decklink_audio_src_got_packet (GstElement * element,
     p.hardware_duration = hardware_duration;
     p.no_signal = no_signal;
     packet->AddRef ();
-    gst_queue_array_push_tail_struct (self->current_packets, &p);
+    gst_vec_deque_push_tail_struct (self->current_packets, &p);
     g_cond_signal (&self->cond);
   }
   g_mutex_unlock (&self->lock);
@@ -640,7 +640,7 @@ gst_decklink_audio_src_create (GstPushSrc * bsrc, GstBuffer ** buffer)
 
 retry:
   g_mutex_lock (&self->lock);
-  while (gst_queue_array_is_empty (self->current_packets) && !self->flushing) {
+  while (gst_vec_deque_is_empty (self->current_packets) && !self->flushing) {
     g_cond_wait (&self->cond, &self->lock);
   }
 
@@ -651,7 +651,7 @@ retry:
   }
 
   p = *(CapturePacket *)
-      gst_queue_array_pop_head_struct (self->current_packets);
+      gst_vec_deque_pop_head_struct (self->current_packets);
   g_mutex_unlock (&self->lock);
 
   p.packet->GetBytes ((gpointer *) & data);
@@ -951,9 +951,9 @@ gst_decklink_audio_src_unlock_stop (GstBaseSrc * bsrc)
 
   g_mutex_lock (&self->lock);
   self->flushing = FALSE;
-  while (gst_queue_array_get_length (self->current_packets) > 0) {
+  while (gst_vec_deque_get_length (self->current_packets) > 0) {
     CapturePacket *tmp = (CapturePacket *)
-        gst_queue_array_pop_head_struct (self->current_packets);
+        gst_vec_deque_pop_head_struct (self->current_packets);
     capture_packet_clear (tmp);
   }
   g_mutex_unlock (&self->lock);
@@ -1027,9 +1027,9 @@ gst_decklink_audio_src_stop (GstDecklinkAudioSrc * self)
 {
   GST_DEBUG_OBJECT (self, "Stopping");
 
-  while (gst_queue_array_get_length (self->current_packets) > 0) {
+  while (gst_vec_deque_get_length (self->current_packets) > 0) {
     CapturePacket *tmp = (CapturePacket *)
-        gst_queue_array_pop_head_struct (self->current_packets);
+        gst_vec_deque_pop_head_struct (self->current_packets);
     capture_packet_clear (tmp);
   }
 
diff --git a/subprojects/gst-plugins-bad/sys/decklink/gstdecklinkaudiosrc.h b/subprojects/gst-plugins-bad/sys/decklink/gstdecklinkaudiosrc.h
index 9b1e69c12a..a7fb26222f 100644
--- a/subprojects/gst-plugins-bad/sys/decklink/gstdecklinkaudiosrc.h
+++ b/subprojects/gst-plugins-bad/sys/decklink/gstdecklinkaudiosrc.h
@@ -63,7 +63,7 @@ struct _GstDecklinkAudioSrc
   GCond cond;
   GMutex lock;
   gboolean flushing;
-  GstQueueArray *current_packets;
+  GstVecDeque *current_packets;
 
   /* properties for handling jittery timestamps */
   GstClockTime alignment_threshold;
diff --git a/subprojects/gst-plugins-bad/sys/decklink/gstdecklinkvideosrc.cpp b/subprojects/gst-plugins-bad/sys/decklink/gstdecklinkvideosrc.cpp
index 8e6865c03b..501c9ce3ac 100644
--- a/subprojects/gst-plugins-bad/sys/decklink/gstdecklinkvideosrc.cpp
+++ b/subprojects/gst-plugins-bad/sys/decklink/gstdecklinkvideosrc.cpp
@@ -448,7 +448,7 @@ gst_decklink_video_src_init (GstDecklinkVideoSrc * self)
   g_cond_init (&self->cond);
 
   self->current_frames =
-      gst_queue_array_new_for_struct (sizeof (CaptureFrame),
+      gst_vec_deque_new_for_struct (sizeof (CaptureFrame),
       DEFAULT_BUFFER_SIZE);
 }
 
@@ -601,12 +601,12 @@ gst_decklink_video_src_finalize (GObject * object)
   g_cond_clear (&self->cond);
 
   if (self->current_frames) {
-    while (gst_queue_array_get_length (self->current_frames) > 0) {
+    while (gst_vec_deque_get_length (self->current_frames) > 0) {
       CaptureFrame *tmp = (CaptureFrame *)
-          gst_queue_array_pop_head_struct (self->current_frames);
+          gst_vec_deque_pop_head_struct (self->current_frames);
       capture_frame_clear (tmp);
     }
-    gst_queue_array_free (self->current_frames);
+    gst_vec_deque_free (self->current_frames);
     self->current_frames = NULL;
   }
 
@@ -865,7 +865,7 @@ gst_decklink_video_src_got_frame (GstElement * element,
     memset (&f, 0, sizeof (f));
 
     /* Notify the streaming thread about the signal loss */
-    gst_queue_array_push_tail_struct (self->current_frames, &f);
+    gst_vec_deque_push_tail_struct (self->current_frames, &f);
     g_cond_signal (&self->cond);
     g_mutex_unlock (&self->lock);
 
@@ -904,10 +904,10 @@ gst_decklink_video_src_got_frame (GstElement * element,
     guint field_count = 0;
     guint skipped_frames = 0;
 
-    while (gst_queue_array_get_length (self->current_frames) >=
+    while (gst_vec_deque_get_length (self->current_frames) >=
         self->buffer_size) {
       CaptureFrame *tmp = (CaptureFrame *)
-          gst_queue_array_pop_head_struct (self->current_frames);
+          gst_vec_deque_pop_head_struct (self->current_frames);
       if (tmp->frame) {
         if (skipped_frames == 0 && self->skipped_last == 0)
           self->skip_from_timestamp = tmp->timestamp;
@@ -991,7 +991,7 @@ gst_decklink_video_src_got_frame (GstElement * element,
     }
 
     frame->AddRef ();
-    gst_queue_array_push_tail_struct (self->current_frames, &f);
+    gst_vec_deque_push_tail_struct (self->current_frames, &f);
     g_cond_signal (&self->cond);
   }
   g_mutex_unlock (&self->lock);
@@ -1262,7 +1262,7 @@ gst_decklink_video_src_create (GstPushSrc * bsrc, GstBuffer ** buffer)
 
   g_mutex_lock (&self->lock);
 retry:
-  while (gst_queue_array_is_empty (self->current_frames) && !self->flushing) {
+  while (gst_vec_deque_is_empty (self->current_frames) && !self->flushing) {
     g_cond_wait (&self->cond, &self->lock);
   }
 
@@ -1272,7 +1272,7 @@ retry:
     return GST_FLOW_FLUSHING;
   }
 
-  f = *(CaptureFrame *) gst_queue_array_pop_head_struct (self->current_frames);
+  f = *(CaptureFrame *) gst_vec_deque_pop_head_struct (self->current_frames);
 
   // We will have no frame if frames without signal are dropped immediately
   // but we still have to signal that it's lost here.
@@ -1561,9 +1561,9 @@ gst_decklink_video_src_unlock_stop (GstBaseSrc * bsrc)
 
   g_mutex_lock (&self->lock);
   self->flushing = FALSE;
-  while (gst_queue_array_get_length (self->current_frames) > 0) {
+  while (gst_vec_deque_get_length (self->current_frames) > 0) {
     CaptureFrame *tmp =
-        (CaptureFrame *) gst_queue_array_pop_head_struct (self->current_frames);
+        (CaptureFrame *) gst_vec_deque_pop_head_struct (self->current_frames);
     capture_frame_clear (tmp);
   }
   g_mutex_unlock (&self->lock);
@@ -1628,9 +1628,9 @@ gst_decklink_video_src_stop (GstDecklinkVideoSrc * self)
 {
   GST_DEBUG_OBJECT (self, "Stopping");
 
-  while (gst_queue_array_get_length (self->current_frames) > 0) {
+  while (gst_vec_deque_get_length (self->current_frames) > 0) {
     CaptureFrame *tmp =
-        (CaptureFrame *) gst_queue_array_pop_head_struct (self->current_frames);
+        (CaptureFrame *) gst_vec_deque_pop_head_struct (self->current_frames);
     capture_frame_clear (tmp);
   }
   self->caps_mode = GST_DECKLINK_MODE_AUTO;
diff --git a/subprojects/gst-plugins-bad/sys/decklink/gstdecklinkvideosrc.h b/subprojects/gst-plugins-bad/sys/decklink/gstdecklinkvideosrc.h
index f43e8385f1..9b6d2edaef 100644
--- a/subprojects/gst-plugins-bad/sys/decklink/gstdecklinkvideosrc.h
+++ b/subprojects/gst-plugins-bad/sys/decklink/gstdecklinkvideosrc.h
@@ -82,7 +82,7 @@ struct _GstDecklinkVideoSrc
   GCond cond;
   GMutex lock;
   gboolean flushing;
-  GstQueueArray *current_frames;
+  GstVecDeque *current_frames;
   GstDecklinkSignalState signal_state;
 
   guint buffer_size;
diff --git a/subprojects/gst-plugins-bad/sys/mediafoundation/gstmfcapturewinrt.cpp b/subprojects/gst-plugins-bad/sys/mediafoundation/gstmfcapturewinrt.cpp
index 5475e385c3..2272b7417e 100644
--- a/subprojects/gst-plugins-bad/sys/mediafoundation/gstmfcapturewinrt.cpp
+++ b/subprojects/gst-plugins-bad/sys/mediafoundation/gstmfcapturewinrt.cpp
@@ -61,7 +61,7 @@ struct _GstMFCaptureWinRT
   GMainLoop *loop;
 
   /* protected by lock */
-  GstQueueArray *queue;
+  GstVecDeque *queue;
 
   GstCaps *supported_caps;
   GstVideoInfo info;
@@ -137,8 +137,8 @@ static void
 gst_mf_capture_winrt_init (GstMFCaptureWinRT * self)
 {
   self->queue =
-      gst_queue_array_new_for_struct (sizeof (GstMFCaptureWinRTFrame), 2);
-  gst_queue_array_set_clear_func (self->queue,
+      gst_vec_deque_new_for_struct (sizeof (GstMFCaptureWinRTFrame), 2);
+  gst_vec_deque_set_clear_func (self->queue,
       (GDestroyNotify) gst_mf_capture_winrt_frame_clear);
   g_mutex_init (&self->lock);
   g_cond_init (&self->cond);
@@ -173,7 +173,7 @@ gst_mf_capture_winrt_finalize (GObject * object)
   g_main_loop_unref (self->loop);
   g_main_context_unref (self->context);
 
-  gst_queue_array_free (self->queue);
+  gst_vec_deque_free (self->queue);
   gst_clear_caps (&self->supported_caps);
   g_mutex_clear (&self->lock);
   g_cond_clear (&self->cond);
@@ -377,7 +377,7 @@ gst_mf_capture_winrt_stop (GstMFSourceObject * object)
 
   hr = self->capture->StopCapture ();
 
-  gst_queue_array_clear (self->queue);
+  gst_vec_deque_clear (self->queue);
 
   if (!gst_mf_result (hr)) {
     GST_ERROR_OBJECT (self, "Capture object doesn't want to stop capture");
@@ -402,7 +402,7 @@ gst_mf_capture_winrt_on_frame (IMediaFrameReference * frame, void *user_data)
   winrt_frame.frame = frame;
   winrt_frame.clock_time =
       gst_mf_source_object_get_running_time (GST_MF_SOURCE_OBJECT (self));
-  gst_queue_array_push_tail_struct (self->queue, &winrt_frame);
+  gst_vec_deque_push_tail_struct (self->queue, &winrt_frame);
   frame->AddRef ();
 
   g_cond_broadcast (&self->cond);
@@ -454,7 +454,7 @@ gst_mf_capture_winrt_get_video_media_frame (GstMFCaptureWinRT * self,
   }
 
   while (!self->flushing && !self->got_error &&
-      gst_queue_array_is_empty (self->queue))
+      gst_vec_deque_is_empty (self->queue))
     g_cond_wait (&self->cond, &self->lock);
 
   if (self->got_error) {
@@ -468,7 +468,7 @@ gst_mf_capture_winrt_get_video_media_frame (GstMFCaptureWinRT * self,
   }
 
   winrt_frame =
-      (GstMFCaptureWinRTFrame *) gst_queue_array_pop_head_struct (self->queue);
+      (GstMFCaptureWinRTFrame *) gst_vec_deque_pop_head_struct (self->queue);
 
   frame_ref = winrt_frame->frame;
   g_assert (frame_ref);
diff --git a/subprojects/gst-plugins-bad/sys/mediafoundation/gstmfsourcereader.cpp b/subprojects/gst-plugins-bad/sys/mediafoundation/gstmfsourcereader.cpp
index cfd56768f0..eab42a06d3 100644
--- a/subprojects/gst-plugins-bad/sys/mediafoundation/gstmfsourcereader.cpp
+++ b/subprojects/gst-plugins-bad/sys/mediafoundation/gstmfsourcereader.cpp
@@ -70,7 +70,7 @@ struct _GstMFSourceReader
   GMainLoop *loop;
 
   /* protected by lock */
-  GstQueueArray *queue;
+  GstVecDeque *queue;
 
   IMFActivate *activate;
   IMFMediaSource *source;
@@ -145,8 +145,8 @@ static void
 gst_mf_source_reader_init (GstMFSourceReader * self)
 {
   self->queue =
-      gst_queue_array_new_for_struct (sizeof (GstMFSourceReaderSample), 2);
-  gst_queue_array_set_clear_func (self->queue,
+      gst_vec_deque_new_for_struct (sizeof (GstMFSourceReaderSample), 2);
+  gst_vec_deque_set_clear_func (self->queue,
       (GDestroyNotify) gst_mf_source_reader_sample_clear);
   g_mutex_init (&self->lock);
   g_cond_init (&self->cond);
@@ -376,7 +376,7 @@ gst_mf_source_reader_finalize (GObject * object)
   g_main_loop_unref (self->loop);
   g_main_context_unref (self->context);
 
-  gst_queue_array_free (self->queue);
+  gst_vec_deque_free (self->queue);
   gst_clear_caps (&self->supported_caps);
   g_mutex_clear (&self->lock);
   g_cond_clear (&self->cond);
@@ -459,7 +459,7 @@ gst_mf_source_reader_stop (GstMFSourceObject * object)
 {
   GstMFSourceReader *self = GST_MF_SOURCE_READER (object);
 
-  gst_queue_array_clear (self->queue);
+  gst_vec_deque_clear (self->queue);
 
   return TRUE;
 }
@@ -496,7 +496,7 @@ gst_mf_source_reader_read_sample (GstMFSourceReader * self)
   reader_sample.clock_time =
       gst_mf_source_object_get_running_time (GST_MF_SOURCE_OBJECT (self));
 
-  gst_queue_array_push_tail_struct (self->queue, &reader_sample);
+  gst_vec_deque_push_tail_struct (self->queue, &reader_sample);
 
   return GST_FLOW_OK;
 }
@@ -516,7 +516,7 @@ gst_mf_source_reader_get_media_buffer (GstMFSourceReader * self,
   *timestamp = GST_CLOCK_TIME_NONE;
   *duration = GST_CLOCK_TIME_NONE;
 
-  while (gst_queue_array_is_empty (self->queue)) {
+  while (gst_vec_deque_is_empty (self->queue)) {
     ret = gst_mf_source_reader_read_sample (self);
     if (ret != GST_FLOW_OK)
       return ret;
@@ -530,7 +530,7 @@ gst_mf_source_reader_get_media_buffer (GstMFSourceReader * self,
   }
 
   reader_sample =
-      (GstMFSourceReaderSample *) gst_queue_array_pop_head_struct (self->queue);
+      (GstMFSourceReaderSample *) gst_vec_deque_pop_head_struct (self->queue);
   sample = reader_sample->sample;
   g_assert (sample);
 
diff --git a/subprojects/gst-plugins-bad/sys/v4l2codecs/gstv4l2decoder.c b/subprojects/gst-plugins-bad/sys/v4l2codecs/gstv4l2decoder.c
index 251ce48ee7..afb4e01aee 100644
--- a/subprojects/gst-plugins-bad/sys/v4l2codecs/gstv4l2decoder.c
+++ b/subprojects/gst-plugins-bad/sys/v4l2codecs/gstv4l2decoder.c
@@ -75,8 +75,8 @@ struct _GstV4l2Decoder
   gboolean opened;
   gint media_fd;
   gint video_fd;
-  GstQueueArray *request_pool;
-  GstQueueArray *pending_requests;
+  GstVecDeque *request_pool;
+  GstVecDeque *pending_requests;
   guint version;
 
   enum v4l2_buf_type src_buf_type;
@@ -116,8 +116,8 @@ gst_v4l2_decoder_finalize (GObject * obj)
 
   g_free (self->media_device);
   g_free (self->video_device);
-  gst_queue_array_free (self->request_pool);
-  gst_queue_array_free (self->pending_requests);
+  gst_vec_deque_free (self->request_pool);
+  gst_vec_deque_free (self->pending_requests);
 
   G_OBJECT_CLASS (gst_v4l2_decoder_parent_class)->finalize (obj);
 }
@@ -125,8 +125,8 @@ gst_v4l2_decoder_finalize (GObject * obj)
 static void
 gst_v4l2_decoder_init (GstV4l2Decoder * self)
 {
-  self->request_pool = gst_queue_array_new (16);
-  self->pending_requests = gst_queue_array_new (16);
+  self->request_pool = gst_vec_deque_new (16);
+  self->pending_requests = gst_vec_deque_new (16);
 }
 
 static void
@@ -221,10 +221,10 @@ gst_v4l2_decoder_close (GstV4l2Decoder * self)
 {
   GstV4l2Request *request;
 
-  while ((request = gst_queue_array_pop_head (self->pending_requests)))
+  while ((request = gst_vec_deque_pop_head (self->pending_requests)))
     gst_v4l2_request_unref (request);
 
-  while ((request = gst_queue_array_pop_head (self->request_pool)))
+  while ((request = gst_vec_deque_pop_head (self->request_pool)))
     gst_v4l2_request_free (request);
 
   if (self->media_fd)
@@ -265,7 +265,7 @@ gst_v4l2_decoder_streamoff (GstV4l2Decoder * self, GstPadDirection direction)
 
     /* STREAMOFF have the effect of cancelling all requests and unqueuing all
      * buffers, so clear the pending request list */
-    while ((pending_req = gst_queue_array_pop_head (self->pending_requests))) {
+    while ((pending_req = gst_vec_deque_pop_head (self->pending_requests))) {
       g_clear_pointer (&pending_req->bitstream, gst_memory_unref);
       pending_req->pending = FALSE;
       gst_v4l2_request_unref (pending_req);
@@ -1061,7 +1061,7 @@ GstV4l2Request *
 gst_v4l2_decoder_alloc_request (GstV4l2Decoder * self, guint32 frame_num,
     GstMemory * bitstream, GstBuffer * pic_buf)
 {
-  GstV4l2Request *request = gst_queue_array_pop_head (self->request_pool);
+  GstV4l2Request *request = gst_vec_deque_pop_head (self->request_pool);
   gint ret;
 
   if (!request) {
@@ -1107,7 +1107,7 @@ GstV4l2Request *
 gst_v4l2_decoder_alloc_sub_request (GstV4l2Decoder * self,
     GstV4l2Request * prev_request, GstMemory * bitstream)
 {
-  GstV4l2Request *request = gst_queue_array_pop_head (self->request_pool);
+  GstV4l2Request *request = gst_vec_deque_pop_head (self->request_pool);
   gint ret;
 
   if (!request) {
@@ -1213,9 +1213,9 @@ gst_v4l2_request_unref (GstV4l2Request * request)
 
     GST_DEBUG_OBJECT (decoder, "Freeing pending request %i.", request->fd);
 
-    idx = gst_queue_array_find (decoder->pending_requests, NULL, request);
+    idx = gst_vec_deque_find (decoder->pending_requests, NULL, request);
     if (idx >= 0)
-      gst_queue_array_drop_element (decoder->pending_requests, idx);
+      gst_vec_deque_drop_element (decoder->pending_requests, idx);
 
     gst_v4l2_request_free (request);
     return;
@@ -1231,7 +1231,7 @@ gst_v4l2_request_unref (GstV4l2Request * request)
     return;
   }
 
-  gst_queue_array_push_tail (decoder->request_pool, request);
+  gst_vec_deque_push_tail (decoder->request_pool, request);
   g_clear_object (&request->decoder);
 }
 
@@ -1276,15 +1276,15 @@ gst_v4l2_request_queue (GstV4l2Request * request, guint flags)
     request->hold_pic_buf = TRUE;
 
   request->pending = TRUE;
-  gst_queue_array_push_tail (decoder->pending_requests,
+  gst_vec_deque_push_tail (decoder->pending_requests,
       gst_v4l2_request_ref (request));
 
   max_pending = MAX (1, decoder->render_delay);
 
-  if (gst_queue_array_get_length (decoder->pending_requests) > max_pending) {
+  if (gst_vec_deque_get_length (decoder->pending_requests) > max_pending) {
     GstV4l2Request *pending_req;
 
-    pending_req = gst_queue_array_peek_head (decoder->pending_requests);
+    pending_req = gst_vec_deque_peek_head (decoder->pending_requests);
     gst_v4l2_request_set_done (pending_req);
   }
 
@@ -1316,7 +1316,7 @@ gst_v4l2_request_set_done (GstV4l2Request * request)
     return ret;
   }
 
-  while ((pending_req = gst_queue_array_pop_head (decoder->pending_requests))) {
+  while ((pending_req = gst_vec_deque_pop_head (decoder->pending_requests))) {
     gst_v4l2_decoder_dequeue_sink (decoder);
     g_clear_pointer (&pending_req->bitstream, gst_memory_unref);
 
diff --git a/subprojects/gst-plugins-bad/sys/va/gstvabaseenc.c b/subprojects/gst-plugins-bad/sys/va/gstvabaseenc.c
index 194bdaa0a7..4df7bd2e01 100644
--- a/subprojects/gst-plugins-bad/sys/va/gstvabaseenc.c
+++ b/subprojects/gst-plugins-bad/sys/va/gstvabaseenc.c
@@ -557,7 +557,7 @@ gst_va_base_enc_drain (GstVideoEncoder * venc)
   g_queue_clear_full (&base->ref_list,
       (GDestroyNotify) gst_video_codec_frame_unref);
 
-  gst_queue_array_clear (base->dts_queue);
+  gst_vec_deque_clear (base->dts_queue);
 
   return GST_FLOW_OK;
 
@@ -593,7 +593,7 @@ error_and_purge_all:
   g_queue_clear_full (&base->ref_list,
       (GDestroyNotify) gst_video_codec_frame_unref);
 
-  gst_queue_array_clear (base->dts_queue);
+  gst_vec_deque_clear (base->dts_queue);
 
   return ret;
 }
@@ -752,7 +752,7 @@ gst_va_base_enc_flush (GstVideoEncoder * venc)
 
   _flush_all_frames (GST_VA_BASE_ENC (venc));
 
-  gst_queue_array_clear (base->dts_queue);
+  gst_vec_deque_clear (base->dts_queue);
 
   return TRUE;
 }
@@ -891,7 +891,7 @@ gst_va_base_enc_init (GstVaBaseEnc * self)
   g_queue_init (&self->output_list);
   gst_video_info_init (&self->in_info);
 
-  self->dts_queue = gst_queue_array_new_for_struct (sizeof (GstClockTime), 8);
+  self->dts_queue = gst_vec_deque_new_for_struct (sizeof (GstClockTime), 8);
 
   self->priv = gst_va_base_enc_get_instance_private (self);
 }
@@ -903,7 +903,7 @@ gst_va_base_enc_dispose (GObject * object)
 
   _flush_all_frames (GST_VA_BASE_ENC (object));
   gst_va_base_enc_close (GST_VIDEO_ENCODER (object));
-  g_clear_pointer (&base->dts_queue, gst_queue_array_free);
+  g_clear_pointer (&base->dts_queue, gst_vec_deque_free);
 
   G_OBJECT_CLASS (parent_class)->dispose (object);
 }
@@ -1154,7 +1154,7 @@ gst_va_base_enc_push_dts (GstVaBaseEnc * base,
 {
   /* We need to manually insert max_reorder_num slots before the
      first frame to ensure DTS never bigger than PTS. */
-  if (gst_queue_array_get_length (base->dts_queue) == 0 && max_reorder_num > 0) {
+  if (gst_vec_deque_get_length (base->dts_queue) == 0 && max_reorder_num > 0) {
     GstClockTime dts_diff = 0, dts;
 
     if (GST_CLOCK_TIME_IS_VALID (frame->duration))
@@ -1170,12 +1170,12 @@ gst_va_base_enc_push_dts (GstVaBaseEnc * base,
         dts = frame->pts;
       }
 
-      gst_queue_array_push_tail_struct (base->dts_queue, &dts);
+      gst_vec_deque_push_tail_struct (base->dts_queue, &dts);
       max_reorder_num--;
     }
   }
 
-  gst_queue_array_push_tail_struct (base->dts_queue, &frame->pts);
+  gst_vec_deque_push_tail_struct (base->dts_queue, &frame->pts);
 }
 
 GstClockTime
@@ -1183,10 +1183,10 @@ gst_va_base_enc_pop_dts (GstVaBaseEnc * base)
 {
   GstClockTime dts;
 
-  g_return_val_if_fail (gst_queue_array_get_length (base->dts_queue) > 0,
+  g_return_val_if_fail (gst_vec_deque_get_length (base->dts_queue) > 0,
       GST_CLOCK_TIME_NONE);
 
-  dts = *((GstClockTime *) gst_queue_array_pop_head_struct (base->dts_queue));
+  dts = *((GstClockTime *) gst_vec_deque_pop_head_struct (base->dts_queue));
   return dts;
 }
 
diff --git a/subprojects/gst-plugins-bad/sys/va/gstvabaseenc.h b/subprojects/gst-plugins-bad/sys/va/gstvabaseenc.h
index e0164621b3..e79a181929 100644
--- a/subprojects/gst-plugins-bad/sys/va/gstvabaseenc.h
+++ b/subprojects/gst-plugins-bad/sys/va/gstvabaseenc.h
@@ -23,7 +23,6 @@
 #include "gstvadevice.h"
 #include "gstvaencoder.h"
 #include "gstvaprofile.h"
-#include <gst/base/gstqueuearray.h>
 
 G_BEGIN_DECLS
 
@@ -61,7 +60,7 @@ struct _GstVaBaseEnc
   GQueue reorder_list;
   GQueue ref_list;
   GQueue output_list;
-  GstQueueArray *dts_queue;
+  GstVecDeque *dts_queue;
 
   GstVideoCodecState *input_state;
   union {
diff --git a/subprojects/gst-plugins-base/gst-libs/gst/app/gstappsink.c b/subprojects/gst-plugins-base/gst-libs/gst/app/gstappsink.c
index eeb6d68c25..568b16690a 100644
--- a/subprojects/gst-plugins-base/gst-libs/gst/app/gstappsink.c
+++ b/subprojects/gst-plugins-base/gst-libs/gst/app/gstappsink.c
@@ -123,7 +123,7 @@ struct _GstAppSinkPrivate
 
   GCond cond;
   GMutex mutex;
-  GstQueueArray *queue;
+  GstVecDeque *queue;
   GstBuffer *preroll_buffer;
   GstCaps *preroll_caps;
   GstCaps *last_caps;
@@ -615,7 +615,7 @@ gst_app_sink_init (GstAppSink * appsink)
 
   g_mutex_init (&priv->mutex);
   g_cond_init (&priv->cond);
-  priv->queue = gst_queue_array_new (16);
+  priv->queue = gst_vec_deque_new (16);
   priv->sample = gst_sample_new (NULL, NULL, NULL, NULL);
 
   priv->emit_signals = DEFAULT_PROP_EMIT_SIGNALS;
@@ -646,7 +646,7 @@ gst_app_sink_dispose (GObject * obj)
   g_mutex_lock (&priv->mutex);
   if (priv->callbacks)
     callbacks = g_steal_pointer (&priv->callbacks);
-  while ((queue_obj = gst_queue_array_pop_head (priv->queue)))
+  while ((queue_obj = gst_vec_deque_pop_head (priv->queue)))
     gst_mini_object_unref (queue_obj);
   gst_buffer_replace (&priv->preroll_buffer, NULL);
   gst_caps_replace (&priv->preroll_caps, NULL);
@@ -670,7 +670,7 @@ gst_app_sink_finalize (GObject * obj)
 
   g_mutex_clear (&priv->mutex);
   g_cond_clear (&priv->cond);
-  gst_queue_array_free (priv->queue);
+  gst_vec_deque_free (priv->queue);
 
   G_OBJECT_CLASS (parent_class)->finalize (obj);
 }
@@ -800,7 +800,7 @@ gst_app_sink_flush_unlocked (GstAppSink * appsink)
   GST_DEBUG_OBJECT (appsink, "flush stop appsink");
   priv->is_eos = FALSE;
   gst_buffer_replace (&priv->preroll_buffer, NULL);
-  while ((obj = gst_queue_array_pop_head (priv->queue)))
+  while ((obj = gst_vec_deque_pop_head (priv->queue)))
     gst_mini_object_unref (obj);
 
   gst_queue_status_info_reset (&priv->queue_status_info);
@@ -868,7 +868,7 @@ gst_app_sink_setcaps (GstBaseSink * sink, GstCaps * caps)
   g_mutex_lock (&priv->mutex);
   GST_DEBUG_OBJECT (appsink, "receiving CAPS");
 
-  gst_queue_array_push_tail (priv->queue, gst_event_new_caps (caps));
+  gst_vec_deque_push_tail (priv->queue, gst_event_new_caps (caps));
   gst_queue_status_info_push_event (&priv->queue_status_info);
 
   if (!priv->preroll_buffer)
@@ -976,7 +976,7 @@ gst_app_sink_event (GstBaseSink * sink, GstEvent * event)
     if (priv->callbacks)
       callbacks = callbacks_ref (priv->callbacks);
 
-    gst_queue_array_push_tail (priv->queue, gst_event_ref (event));
+    gst_vec_deque_push_tail (priv->queue, gst_event_ref (event));
     gst_queue_status_info_push_event (&priv->queue_status_info);
 
     if ((priv->wait_status & APP_WAITING))
@@ -1054,7 +1054,7 @@ dequeue_object (GstAppSink * appsink)
   GstAppSinkPrivate *priv = appsink->priv;
   GstMiniObject *obj;
 
-  obj = gst_queue_array_pop_head (priv->queue);
+  obj = gst_vec_deque_pop_head (priv->queue);
 
   if (GST_IS_BUFFER (obj) || GST_IS_BUFFER_LIST (obj)) {
     GST_DEBUG_OBJECT (appsink, "dequeued buffer/list %p", obj);
@@ -1179,7 +1179,7 @@ restart:
     }
   }
   /* we need to ref the buffer/list when pushing it in the queue */
-  gst_queue_array_push_tail (priv->queue, gst_mini_object_ref (data));
+  gst_vec_deque_push_tail (priv->queue, gst_mini_object_ref (data));
   gst_queue_status_info_push (&priv->queue_status_info, data,
       &priv->last_segment, GST_OBJECT_CAST (appsink));
 
diff --git a/subprojects/gst-plugins-base/gst-libs/gst/app/gstappsrc.c b/subprojects/gst-plugins-base/gst-libs/gst/app/gstappsrc.c
index 32e35d6ebb..c013f5cc09 100644
--- a/subprojects/gst-plugins-base/gst-libs/gst/app/gstappsrc.c
+++ b/subprojects/gst-plugins-base/gst-libs/gst/app/gstappsrc.c
@@ -143,7 +143,7 @@ struct _GstAppSrcPrivate
 {
   GCond cond;
   GMutex mutex;
-  GstQueueArray *queue;
+  GstVecDeque *queue;
   GstAppSrcWaitStatus wait_status;
 
   GstCaps *last_caps;
@@ -157,7 +157,7 @@ struct _GstAppSrcPrivate
   gboolean pending_custom_segment;
   /* events that have been delayed until either the caps is configured, ensuring
      that no events are sent before CAPS, or buffers are being pushed. */
-  GstQueueArray *delayed_events;
+  GstVecDeque *delayed_events;
   /* if a buffer has been pushed yet */
   gboolean pushed_buffer;
 
@@ -744,8 +744,8 @@ gst_app_src_init (GstAppSrc * appsrc)
 
   g_mutex_init (&priv->mutex);
   g_cond_init (&priv->cond);
-  priv->queue = gst_queue_array_new (16);
-  priv->delayed_events = gst_queue_array_new (16);
+  priv->queue = gst_vec_deque_new (16);
+  priv->delayed_events = gst_vec_deque_new (16);
   priv->wait_status = NOONE_WAITING;
   priv->pushed_buffer = FALSE;
 
@@ -775,8 +775,8 @@ gst_app_src_flush_queued (GstAppSrc * src, gboolean retain_last_caps)
   GstAppSrcPrivate *priv = src->priv;
   GstCaps *requeue_caps = NULL;
 
-  while (!gst_queue_array_is_empty (priv->queue)) {
-    obj = gst_queue_array_pop_head (priv->queue);
+  while (!gst_vec_deque_is_empty (priv->queue)) {
+    obj = gst_vec_deque_pop_head (priv->queue);
     if (obj) {
       if (GST_IS_CAPS (obj) && retain_last_caps) {
         gst_caps_replace (&requeue_caps, GST_CAPS_CAST (obj));
@@ -786,10 +786,10 @@ gst_app_src_flush_queued (GstAppSrc * src, gboolean retain_last_caps)
   }
 
   if (requeue_caps) {
-    gst_queue_array_push_tail (priv->queue, requeue_caps);
+    gst_vec_deque_push_tail (priv->queue, requeue_caps);
   }
 
-  gst_queue_array_clear (priv->delayed_events);
+  gst_vec_deque_clear (priv->delayed_events);
   priv->pushed_buffer = FALSE;
 
   gst_queue_status_info_reset (&priv->queue_status_info);
@@ -834,8 +834,8 @@ gst_app_src_finalize (GObject * obj)
 
   g_mutex_clear (&priv->mutex);
   g_cond_clear (&priv->cond);
-  gst_queue_array_free (priv->queue);
-  gst_queue_array_free (priv->delayed_events);
+  gst_vec_deque_free (priv->queue);
+  gst_vec_deque_free (priv->delayed_events);
 
   g_free (priv->uri);
 
@@ -1033,7 +1033,7 @@ gst_app_src_send_event (GstElement * element, GstEvent * event)
         GST_DEBUG_OBJECT (appsrc, "queue event: %" GST_PTR_FORMAT, event);
         g_mutex_lock (&priv->mutex);
 
-        gst_queue_array_push_tail (priv->queue, event);
+        gst_vec_deque_push_tail (priv->queue, event);
 
         if ((priv->wait_status & STREAM_WAITING))
           g_cond_broadcast (&priv->cond);
@@ -1442,10 +1442,10 @@ push_delayed_events (GstAppSrc * appsrc)
 {
   GstAppSrcPrivate *priv = appsrc->priv;
 
-  while (!gst_queue_array_is_empty (priv->delayed_events)) {
+  while (!gst_vec_deque_is_empty (priv->delayed_events)) {
     GstEvent *event;
 
-    event = gst_queue_array_pop_head (priv->delayed_events);
+    event = gst_vec_deque_pop_head (priv->delayed_events);
     GST_DEBUG_OBJECT (appsrc, "sending event: %" GST_PTR_FORMAT, event);
 
     g_mutex_unlock (&priv->mutex);
@@ -1517,8 +1517,8 @@ gst_app_src_create (GstBaseSrc * bsrc, guint64 offset, guint size,
       goto flushing;
 
     /* return data as long as we have some */
-    if (!gst_queue_array_is_empty (priv->queue)) {
-      GstMiniObject *obj = gst_queue_array_pop_head (priv->queue);
+    if (!gst_vec_deque_is_empty (priv->queue)) {
+      GstMiniObject *obj = gst_vec_deque_pop_head (priv->queue);
 
       if (priv->current_caps && needs_segment (obj)) {
         /* need to have sent a segment before sending `obj` */
@@ -1546,7 +1546,7 @@ gst_app_src_create (GstBaseSrc * bsrc, guint64 offset, guint size,
           gst_app_src_do_negotiate (bsrc);
 
         /* sending delayed events which were waiting on the caps */
-        if (!gst_queue_array_is_empty (priv->delayed_events)) {
+        if (!gst_vec_deque_is_empty (priv->delayed_events)) {
           /* need to send a segment before the events */
           ensure_segment (appsrc);
 
@@ -1573,7 +1573,7 @@ gst_app_src_create (GstBaseSrc * bsrc, guint64 offset, guint size,
           priv->need_discont_downstream = FALSE;
         }
 
-        if (!gst_queue_array_is_empty (priv->delayed_events)) {
+        if (!gst_vec_deque_is_empty (priv->delayed_events)) {
           /* don't keep delaying events if a buffer has been pushed without CAPS */
           GST_DEBUG_OBJECT (appsrc, "push delayed events before buffer");
           push_delayed_events (appsrc);
@@ -1599,7 +1599,7 @@ gst_app_src_create (GstBaseSrc * bsrc, guint64 offset, guint size,
           priv->need_discont_downstream = FALSE;
         }
 
-        if (!gst_queue_array_is_empty (priv->delayed_events)) {
+        if (!gst_vec_deque_is_empty (priv->delayed_events)) {
           /* don't keep delaying events if a buffer has been pushed without CAPS */
           GST_DEBUG_OBJECT (appsrc, "push delayed events before buffer");
           push_delayed_events (appsrc);
@@ -1644,7 +1644,7 @@ gst_app_src_create (GstBaseSrc * bsrc, guint64 offset, guint size,
           if (!priv->current_caps && !priv->pushed_buffer) {
             GST_DEBUG_OBJECT (appsrc,
                 "did not send caps yet, delay event for now");
-            gst_queue_array_push_tail (priv->delayed_events, event);
+            gst_vec_deque_push_tail (priv->delayed_events, event);
           } else {
             /* We are about to push an event, release out lock */
             g_mutex_unlock (&priv->mutex);
@@ -1691,7 +1691,7 @@ gst_app_src_create (GstBaseSrc * bsrc, guint64 offset, guint size,
        * signal) we can still be empty because the pushed buffer got flushed or
        * when the application pushes the requested buffer later, we support both
        * possibilities. */
-      if (!gst_queue_array_is_empty (priv->queue))
+      if (!gst_vec_deque_is_empty (priv->queue))
         continue;
 
       /* no buffer yet, maybe we are EOS, if not, block for more data. */
@@ -1776,10 +1776,10 @@ gst_app_src_set_caps (GstAppSrc * appsrc, const GstCaps * caps)
     new_caps = caps ? gst_caps_copy (caps) : NULL;
     GST_DEBUG_OBJECT (appsrc, "setting caps to %" GST_PTR_FORMAT, caps);
 
-    while ((t = gst_queue_array_peek_tail (priv->queue)) && GST_IS_CAPS (t)) {
-      gst_caps_unref (gst_queue_array_pop_tail (priv->queue));
+    while ((t = gst_vec_deque_peek_tail (priv->queue)) && GST_IS_CAPS (t)) {
+      gst_caps_unref (gst_vec_deque_pop_tail (priv->queue));
     }
-    gst_queue_array_push_tail (priv->queue, new_caps);
+    gst_vec_deque_push_tail (priv->queue, new_caps);
     gst_caps_replace (&priv->last_caps, new_caps);
 
     if ((priv->wait_status & STREAM_WAITING))
@@ -2442,16 +2442,16 @@ gst_app_src_push_internal (GstAppSrc * appsrc, GstBuffer * buffer,
         priv->need_discont_upstream = TRUE;
         goto dropped;
       } else if (priv->leaky_type == GST_APP_LEAKY_TYPE_DOWNSTREAM) {
-        guint i, length = gst_queue_array_get_length (priv->queue);
+        guint i, length = gst_vec_deque_get_length (priv->queue);
         GstMiniObject *item = NULL;
 
         /* Find the oldest buffer or buffer list and drop it, then update the
          * limits. Dropping one is sufficient to go below the limits again.
          */
         for (i = 0; i < length; i++) {
-          item = gst_queue_array_peek_nth (priv->queue, i);
+          item = gst_vec_deque_peek_nth (priv->queue, i);
           if (GST_IS_BUFFER (item) || GST_IS_BUFFER_LIST (item)) {
-            gst_queue_array_drop_element (priv->queue, i);
+            gst_vec_deque_drop_element (priv->queue, i);
             break;
           }
           /* To not accidentally have an event after the loop */
@@ -2502,7 +2502,7 @@ gst_app_src_push_internal (GstAppSrc * appsrc, GstBuffer * buffer,
     GstEvent *event = gst_event_new_segment (&priv->last_segment);
 
     GST_DEBUG_OBJECT (appsrc, "enqueue new segment %" GST_PTR_FORMAT, event);
-    gst_queue_array_push_tail (priv->queue, event);
+    gst_vec_deque_push_tail (priv->queue, event);
     priv->pending_custom_segment = FALSE;
   }
 
@@ -2525,7 +2525,7 @@ gst_app_src_push_internal (GstAppSrc * appsrc, GstBuffer * buffer,
 
     if (!steal_ref)
       gst_buffer_list_ref (buflist);
-    gst_queue_array_push_tail (priv->queue, buflist);
+    gst_vec_deque_push_tail (priv->queue, buflist);
   } else {
     /* Mark the buffer as DISCONT if we previously dropped a buffer instead of
      * queueing it */
@@ -2543,7 +2543,7 @@ gst_app_src_push_internal (GstAppSrc * appsrc, GstBuffer * buffer,
     GST_DEBUG_OBJECT (appsrc, "queueing buffer %p", buffer);
     if (!steal_ref)
       gst_buffer_ref (buffer);
-    gst_queue_array_push_tail (priv->queue, buffer);
+    gst_vec_deque_push_tail (priv->queue, buffer);
   }
 
   gst_app_src_update_queued_push (appsrc,
diff --git a/subprojects/gst-plugins-base/gst-libs/gst/rtsp/gstrtspconnection.c b/subprojects/gst-plugins-base/gst-libs/gst/rtsp/gstrtspconnection.c
index a822d956b9..474a7452f2 100644
--- a/subprojects/gst-plugins-base/gst-libs/gst/rtsp/gstrtspconnection.c
+++ b/subprojects/gst-plugins-base/gst-libs/gst/rtsp/gstrtspconnection.c
@@ -3953,7 +3953,7 @@ struct _GstRTSPWatch
   /* queued message for transmission */
   guint id;
   GMutex mutex;
-  GstQueueArray *messages;
+  GstVecDeque *messages;
   gsize messages_bytes;
   guint messages_count;
 
@@ -4221,7 +4221,7 @@ gst_rtsp_source_dispatch_write (GPollableOutputStream * stream,
 
   g_mutex_lock (&watch->mutex);
   do {
-    guint n_messages = gst_queue_array_get_length (watch->messages);
+    guint n_messages = gst_vec_deque_get_length (watch->messages);
     GOutputVector *vectors;
     GstMapInfo *map_infos;
     guint *ids;
@@ -4266,7 +4266,7 @@ gst_rtsp_source_dispatch_write (GPollableOutputStream * stream,
     }
 
     for (i = 0, n_vectors = 0, n_memories = 0, n_ids = 0; i < n_messages; i++) {
-      msg = gst_queue_array_peek_nth_struct (watch->messages, i);
+      msg = gst_vec_deque_peek_nth_struct (watch->messages, i);
       if (msg->id != 0)
         n_ids++;
 
@@ -4304,7 +4304,7 @@ gst_rtsp_source_dispatch_write (GPollableOutputStream * stream,
 
     for (i = 0, j = 0, n_mmap = 0, l = 0, bytes_to_write = 0; i < n_messages;
         i++) {
-      msg = gst_queue_array_peek_nth_struct (watch->messages, i);
+      msg = gst_vec_deque_peek_nth_struct (watch->messages, i);
 
       if (msg->data_offset < msg->data_size) {
         vectors[j].buffer = (msg->data_is_data_header ?
@@ -4374,7 +4374,7 @@ gst_rtsp_source_dispatch_write (GPollableOutputStream * stream,
     if (bytes_written == bytes_to_write) {
       /* fast path, just unmap all memories, free memory, drop all messages and notify them */
       l = 0;
-      while ((msg = gst_queue_array_pop_head_struct (watch->messages))) {
+      while ((msg = gst_vec_deque_pop_head_struct (watch->messages))) {
         if (msg->id) {
           ids[l] = msg->id;
           l++;
@@ -4388,7 +4388,7 @@ gst_rtsp_source_dispatch_write (GPollableOutputStream * stream,
     } else if (bytes_written > 0) {
       /* not done, let's skip all messages that were sent already and free them */
       for (i = 0, drop_messages = 0; i < n_messages; i++) {
-        msg = gst_queue_array_peek_nth_struct (watch->messages, i);
+        msg = gst_vec_deque_peek_nth_struct (watch->messages, i);
 
         if (bytes_written >= msg->data_size - msg->data_offset) {
           guint body_size;
@@ -4434,7 +4434,7 @@ gst_rtsp_source_dispatch_write (GPollableOutputStream * stream,
       }
 
       while (drop_messages > 0) {
-        msg = gst_queue_array_pop_head_struct (watch->messages);
+        msg = gst_vec_deque_pop_head_struct (watch->messages);
         g_assert (msg);
         drop_messages--;
       }
@@ -4482,10 +4482,10 @@ write_error:
     if (watch->funcs.error_full) {
       guint i, n_messages;
 
-      n_messages = gst_queue_array_get_length (watch->messages);
+      n_messages = gst_vec_deque_get_length (watch->messages);
       for (i = 0; i < n_messages; i++) {
         GstRTSPSerializedMessage *msg =
-            gst_queue_array_peek_nth_struct (watch->messages, i);
+            gst_vec_deque_peek_nth_struct (watch->messages, i);
         if (msg->id)
           watch->funcs.error_full (watch, res, NULL, msg->id, watch->user_data);
       }
@@ -4509,10 +4509,10 @@ gst_rtsp_source_finalize (GSource * source)
   build_reset (&watch->builder);
   gst_rtsp_message_unset (&watch->message);
 
-  while ((msg = gst_queue_array_pop_head_struct (watch->messages))) {
+  while ((msg = gst_vec_deque_pop_head_struct (watch->messages))) {
     gst_rtsp_serialized_message_clear (msg);
   }
-  gst_queue_array_free (watch->messages);
+  gst_vec_deque_free (watch->messages);
   watch->messages = NULL;
   watch->messages_bytes = 0;
   watch->messages_count = 0;
@@ -4575,7 +4575,7 @@ gst_rtsp_watch_new (GstRTSPConnection * conn,
 
   g_mutex_init (&result->mutex);
   result->messages =
-      gst_queue_array_new_for_struct (sizeof (GstRTSPSerializedMessage), 10);
+      gst_vec_deque_new_for_struct (sizeof (GstRTSPSerializedMessage), 10);
   g_cond_init (&result->queue_not_full);
 
   gst_rtsp_watch_reset (result);
@@ -4750,7 +4750,7 @@ gst_rtsp_watch_write_serialized_messages (GstRTSPWatch * watch,
     goto flushing;
 
   /* try to send the message synchronously first */
-  if (gst_queue_array_get_length (watch->messages) == 0) {
+  if (gst_vec_deque_get_length (watch->messages) == 0) {
     gint j, k;
     GOutputVector *vectors;
     GstMapInfo *map_infos;
@@ -4907,7 +4907,7 @@ gst_rtsp_watch_write_serialized_messages (GstRTSPWatch * watch,
     }
 
     /* add the record to a queue. */
-    gst_queue_array_push_tail_struct (watch->messages, &local_message);
+    gst_vec_deque_push_tail_struct (watch->messages, &local_message);
     watch->messages_bytes +=
         (local_message.data_size - local_message.data_offset);
     if (local_message.body_data)
@@ -5174,7 +5174,7 @@ gst_rtsp_watch_set_flushing (GstRTSPWatch * watch, gboolean flushing)
   if (flushing) {
     GstRTSPSerializedMessage *msg;
 
-    while ((msg = gst_queue_array_pop_head_struct (watch->messages))) {
+    while ((msg = gst_vec_deque_pop_head_struct (watch->messages))) {
       gst_rtsp_serialized_message_clear (msg);
     }
   }
diff --git a/subprojects/gst-plugins-base/gst-libs/gst/video/video-converter.c b/subprojects/gst-plugins-base/gst-libs/gst/video/video-converter.c
index d33acaada6..57e84835bd 100644
--- a/subprojects/gst-plugins-base/gst-libs/gst/video/video-converter.c
+++ b/subprojects/gst-plugins-base/gst-libs/gst/video/video-converter.c
@@ -134,8 +134,8 @@ struct _GstParallelizedTaskRunner
   gboolean own_pool;
   guint n_threads;
 
-  GstQueueArray *tasks;
-  GstQueueArray *work_items;
+  GstVecDeque *tasks;
+  GstVecDeque *work_items;
 
   GMutex lock;
 
@@ -149,7 +149,7 @@ gst_parallelized_task_thread_func (gpointer data)
   GstParallelizedWorkItem *work_item;
 
   g_mutex_lock (&runner->lock);
-  work_item = gst_queue_array_pop_head (runner->work_items);
+  work_item = gst_vec_deque_pop_head (runner->work_items);
   g_mutex_unlock (&runner->lock);
 
   g_assert (work_item != NULL);
@@ -168,8 +168,8 @@ gst_parallelized_task_runner_join (GstParallelizedTaskRunner * self)
 
   while (!joined) {
     g_mutex_lock (&self->lock);
-    if (!(joined = gst_queue_array_is_empty (self->tasks))) {
-      gpointer task = gst_queue_array_pop_head (self->tasks);
+    if (!(joined = gst_vec_deque_is_empty (self->tasks))) {
+      gpointer task = gst_vec_deque_pop_head (self->tasks);
       g_mutex_unlock (&self->lock);
       gst_task_pool_join (self->pool, task);
     } else {
@@ -183,8 +183,8 @@ gst_parallelized_task_runner_free (GstParallelizedTaskRunner * self)
 {
   gst_parallelized_task_runner_join (self);
 
-  gst_queue_array_free (self->work_items);
-  gst_queue_array_free (self->tasks);
+  gst_vec_deque_free (self->work_items);
+  gst_vec_deque_free (self->tasks);
   if (self->own_pool)
     gst_task_pool_cleanup (self->pool);
   gst_object_unref (self->pool);
@@ -221,8 +221,8 @@ gst_parallelized_task_runner_new (guint n_threads, GstTaskPool * pool,
     gst_task_pool_prepare (self->pool, NULL);
   }
 
-  self->tasks = gst_queue_array_new (n_threads);
-  self->work_items = gst_queue_array_new (n_threads);
+  self->tasks = gst_vec_deque_new (n_threads);
+  self->work_items = gst_vec_deque_new (n_threads);
 
   self->n_threads = n_threads;
 
@@ -265,7 +265,7 @@ gst_parallelized_task_runner_run (GstParallelizedTaskRunner * self,
       work_item->self = self;
       work_item->func = func;
       work_item->user_data = task_data[i];
-      gst_queue_array_push_tail (self->work_items, work_item);
+      gst_vec_deque_push_tail (self->work_items, work_item);
 
       task =
           gst_task_pool_push (self->pool, gst_parallelized_task_thread_func,
@@ -273,7 +273,7 @@ gst_parallelized_task_runner_run (GstParallelizedTaskRunner * self,
 
       /* The return value of push() is unfortunately nullable, and we can't deal with that */
       g_assert (task != NULL);
-      gst_queue_array_push_tail (self->tasks, task);
+      gst_vec_deque_push_tail (self->tasks, task);
     }
     g_mutex_unlock (&self->lock);
   }
diff --git a/subprojects/gst-plugins-base/gst/compositor/compositor.c b/subprojects/gst-plugins-base/gst/compositor/compositor.c
index 54a2e9dc58..182b08e90d 100644
--- a/subprojects/gst-plugins-base/gst/compositor/compositor.c
+++ b/subprojects/gst-plugins-base/gst/compositor/compositor.c
@@ -1263,8 +1263,8 @@ gst_parallelized_task_runner_join (GstParallelizedTaskRunner * self)
 
   while (!joined) {
     g_mutex_lock (&self->lock);
-    if (!(joined = gst_queue_array_is_empty (self->tasks))) {
-      gpointer task = gst_queue_array_pop_head (self->tasks);
+    if (!(joined = gst_vec_deque_is_empty (self->tasks))) {
+      gpointer task = gst_vec_deque_pop_head (self->tasks);
       g_mutex_unlock (&self->lock);
       gst_task_pool_join (self->pool, task);
     } else {
@@ -1278,7 +1278,7 @@ gst_parallelized_task_runner_free (GstParallelizedTaskRunner * self)
 {
   gst_parallelized_task_runner_join (self);
 
-  gst_queue_array_free (self->tasks);
+  gst_vec_deque_free (self->tasks);
   if (self->own_pool)
     gst_task_pool_cleanup (self->pool);
   gst_object_unref (self->pool);
@@ -1315,7 +1315,7 @@ gst_parallelized_task_runner_new (guint n_threads, GstTaskPool * pool,
     gst_task_pool_prepare (self->pool, NULL);
   }
 
-  self->tasks = gst_queue_array_new (n_threads);
+  self->tasks = gst_vec_deque_new (n_threads);
 
   self->n_threads = n_threads;
 
@@ -1370,7 +1370,7 @@ gst_parallelized_task_runner_run (GstParallelizedTaskRunner * self,
        * on.
        */
       g_assert (task != NULL);
-      gst_queue_array_push_tail (self->tasks, task);
+      gst_vec_deque_push_tail (self->tasks, task);
     }
     g_mutex_unlock (&self->lock);
   }
diff --git a/subprojects/gst-plugins-base/gst/compositor/compositor.h b/subprojects/gst-plugins-base/gst/compositor/compositor.h
index c3d2998422..2d4c06c171 100644
--- a/subprojects/gst-plugins-base/gst/compositor/compositor.h
+++ b/subprojects/gst-plugins-base/gst/compositor/compositor.h
@@ -105,7 +105,7 @@ struct _GstParallelizedTaskRunner
   gboolean own_pool;
   guint n_threads;
 
-  GstQueueArray *tasks;
+  GstVecDeque *tasks;
 
   GstParallelizedTaskFunc func;
   gpointer *task_data;
diff --git a/subprojects/gst-plugins-good/ext/adaptivedemux2/gstadaptivedemux-track.c b/subprojects/gst-plugins-good/ext/adaptivedemux2/gstadaptivedemux-track.c
index 2d9556b421..7dd6b527f1 100644
--- a/subprojects/gst-plugins-good/ext/adaptivedemux2/gstadaptivedemux-track.c
+++ b/subprojects/gst-plugins-good/ext/adaptivedemux2/gstadaptivedemux-track.c
@@ -38,9 +38,10 @@ GST_DEBUG_CATEGORY_EXTERN (adaptivedemux2_debug);
 void
 gst_adaptive_demux_track_flush (GstAdaptiveDemuxTrack * track)
 {
-  GST_DEBUG_ID (track->id, "Flushing track with %u queued items",
-      gst_queue_array_get_length (track->queue));
-  gst_queue_array_clear (track->queue);
+  GST_DEBUG_ID (track->id,
+      "Flushing track with %" G_GSIZE_FORMAT " queued items",
+      gst_vec_deque_get_length (track->queue));
+  gst_vec_deque_clear (track->queue);
 
   gst_event_store_flush (&track->sticky_events);
 
@@ -94,13 +95,13 @@ static gboolean
 track_dequeue_item_locked (GstAdaptiveDemux * demux,
     GstAdaptiveDemuxTrack * track, TrackQueueItem * out_item)
 {
-  TrackQueueItem *item = gst_queue_array_peek_head_struct (track->queue);
+  TrackQueueItem *item = gst_vec_deque_peek_head_struct (track->queue);
 
   if (item == NULL)
     return FALSE;
 
   *out_item = *item;
-  gst_queue_array_pop_head (track->queue);
+  gst_vec_deque_pop_head (track->queue);
 
   GST_LOG_ID (track->id,
       "item running_time %" GST_STIME_FORMAT " end %"
@@ -340,7 +341,7 @@ gst_adaptive_demux_track_drain_to (GstAdaptiveDemuxTrack * track,
     }
 
     /* Otherwise check what's enqueued */
-    item = gst_queue_array_peek_head_struct (track->queue);
+    item = gst_vec_deque_peek_head_struct (track->queue);
     /* track is empty, we're done */
     if (item == NULL) {
       GST_DEBUG_ID (track->id, "Track completely drained");
@@ -483,7 +484,7 @@ track_queue_data_locked (GstAdaptiveDemux * demux,
       GST_STIME_ARGS (item.runningtime_end));
 
   track->level_bytes += size;
-  gst_queue_array_push_tail_struct (track->queue, &item);
+  gst_vec_deque_push_tail_struct (track->queue, &item);
 
   /* If we were waiting for this track to add something, notify output thread */
   /* FIXME: This should be in adaptive demux */
@@ -603,16 +604,16 @@ _track_sink_event_function (GstPad * pad, GstObject * parent, GstEvent * event)
       if (track->eos) {
         gint i, len;
         /* Find and drop latest EOS if present */
-        len = gst_queue_array_get_length (track->queue);
+        len = gst_vec_deque_get_length (track->queue);
         for (i = len - 1; i >= 0; i--) {
           TrackQueueItem *item =
-              gst_queue_array_peek_nth_struct (track->queue, i);
+              gst_vec_deque_peek_nth_struct (track->queue, i);
           if (GST_IS_EVENT (item->item)
               && GST_EVENT_TYPE (item->item) == GST_EVENT_EOS) {
             TrackQueueItem sub;
             GST_DEBUG_ID (track->id,
                 "Removing previously received EOS (pos:%d)", i);
-            if (gst_queue_array_drop_struct (track->queue, i, &sub))
+            if (gst_vec_deque_drop_struct (track->queue, i, &sub))
               gst_mini_object_unref (sub.item);
             break;
           }
@@ -755,9 +756,9 @@ gst_adaptive_demux_track_update_next_position (GstAdaptiveDemuxTrack * track)
     return;
   }
 
-  len = gst_queue_array_get_length (track->queue);
+  len = gst_vec_deque_get_length (track->queue);
   for (i = 0; i < len; i++) {
-    TrackQueueItem *item = gst_queue_array_peek_nth_struct (track->queue, i);
+    TrackQueueItem *item = gst_vec_deque_peek_nth_struct (track->queue, i);
 
     if (item->runningtime != GST_CLOCK_STIME_NONE) {
       GST_DEBUG_ID (track->id,
@@ -813,7 +814,7 @@ _demux_track_free (GstAdaptiveDemuxTrack * track)
   gst_object_unref (track->stream_object);
   if (track->tags)
     gst_tag_list_unref (track->tags);
-  gst_queue_array_free (track->queue);
+  gst_vec_deque_free (track->queue);
 
   gst_event_store_deinit (&track->sticky_events);
 
@@ -941,8 +942,8 @@ gst_adaptive_demux_track_new (GstAdaptiveDemux * demux,
   track->active = FALSE;
   track->draining = FALSE;
 
-  track->queue = gst_queue_array_new_for_struct (sizeof (TrackQueueItem), 50);
-  gst_queue_array_set_clear_func (track->queue,
+  track->queue = gst_vec_deque_new_for_struct (sizeof (TrackQueueItem), 50);
+  gst_vec_deque_set_clear_func (track->queue,
       (GDestroyNotify) _track_queue_item_clear);
 
   gst_event_store_init (&track->sticky_events);
diff --git a/subprojects/gst-plugins-good/ext/adaptivedemux2/gstadaptivedemux.c b/subprojects/gst-plugins-good/ext/adaptivedemux2/gstadaptivedemux.c
index dbbe6f1a5f..24d6e85cb3 100644
--- a/subprojects/gst-plugins-good/ext/adaptivedemux2/gstadaptivedemux.c
+++ b/subprojects/gst-plugins-good/ext/adaptivedemux2/gstadaptivedemux.c
@@ -3300,7 +3300,7 @@ handle_slot_pending_track_switch_locked (GstAdaptiveDemux * demux,
       slot->pending_track->buffering_threshold);
   pending_is_ready |= slot->pending_track->eos;
 
-  if (!pending_is_ready && gst_queue_array_get_length (track->queue) > 0) {
+  if (!pending_is_ready && gst_vec_deque_get_length (track->queue) > 0) {
     GST_DEBUG_OBJECT (demux,
         "Replacement track '%s' doesn't have enough data for switching yet",
         slot->pending_track->id);
@@ -3435,7 +3435,7 @@ restart:
     } else {
       GST_DEBUG_ID (track->id, "Track is EOS, not waiting for timed data");
 
-      if (gst_queue_array_get_length (track->queue) > 0) {
+      if (gst_vec_deque_get_length (track->queue) > 0) {
         all_tracks_empty = FALSE;
       }
     }
diff --git a/subprojects/gst-plugins-good/ext/adaptivedemux2/gstadaptivedemux.h b/subprojects/gst-plugins-good/ext/adaptivedemux2/gstadaptivedemux.h
index e740699081..b0ed01868e 100644
--- a/subprojects/gst-plugins-good/ext/adaptivedemux2/gstadaptivedemux.h
+++ b/subprojects/gst-plugins-good/ext/adaptivedemux2/gstadaptivedemux.h
@@ -150,7 +150,7 @@ struct _GstAdaptiveDemuxTrack
   GstPad *pending_srcpad;
 
   /* Data storage */
-  GstQueueArray *queue;
+  GstVecDeque *queue;
 
   /* Sticky event storage for this track */
   GstEventStore sticky_events;
diff --git a/subprojects/gst-plugins-good/ext/mpg123/gstmpg123audiodec.c b/subprojects/gst-plugins-good/ext/mpg123/gstmpg123audiodec.c
index ed6430ec8e..44632204db 100644
--- a/subprojects/gst-plugins-good/ext/mpg123/gstmpg123audiodec.c
+++ b/subprojects/gst-plugins-good/ext/mpg123/gstmpg123audiodec.c
@@ -217,7 +217,7 @@ gst_mpg123_audio_dec_init (GstMpg123AudioDec * mpg123_decoder)
 {
   mpg123_decoder->handle = NULL;
   mpg123_decoder->audio_clip_info_queue =
-      gst_queue_array_new_for_struct (sizeof (GstMpg123AudioDecClipInfo), 16);
+      gst_vec_deque_new_for_struct (sizeof (GstMpg123AudioDecClipInfo), 16);
 
   gst_audio_decoder_set_needs_format (GST_AUDIO_DECODER (mpg123_decoder), TRUE);
   gst_audio_decoder_set_use_default_pad_acceptcaps (GST_AUDIO_DECODER_CAST
@@ -232,7 +232,7 @@ gst_mpg123_audio_dec_dispose (GObject * object)
   GstMpg123AudioDec *mpg123_decoder = GST_MPG123_AUDIO_DEC (object);
 
   if (mpg123_decoder->audio_clip_info_queue != NULL) {
-    gst_queue_array_free (mpg123_decoder->audio_clip_info_queue);
+    gst_vec_deque_free (mpg123_decoder->audio_clip_info_queue);
     mpg123_decoder->audio_clip_info_queue = NULL;
   }
 
@@ -754,7 +754,7 @@ static void gst_mpg123_audio_dec_push_clip_info
     (GstMpg123AudioDec * mpg123_decoder, guint64 clip_start, guint64 clip_end)
 {
   GstMpg123AudioDecClipInfo clip_info = { clip_start, clip_end };
-  gst_queue_array_push_tail_struct (mpg123_decoder->audio_clip_info_queue,
+  gst_vec_deque_push_tail_struct (mpg123_decoder->audio_clip_info_queue,
       &clip_info);
 }
 
@@ -771,7 +771,7 @@ gst_mpg123_audio_dec_pop_oldest_clip_info (GstMpg123AudioDec *
     return;
 
   clip_info =
-      gst_queue_array_pop_head_struct (mpg123_decoder->audio_clip_info_queue);
+      gst_vec_deque_pop_head_struct (mpg123_decoder->audio_clip_info_queue);
 
   *clip_start = clip_info->clip_start;
   *clip_end = clip_info->clip_end;
@@ -780,14 +780,14 @@ gst_mpg123_audio_dec_pop_oldest_clip_info (GstMpg123AudioDec *
 static void
 gst_mpg123_audio_dec_clear_clip_info_queue (GstMpg123AudioDec * mpg123_decoder)
 {
-  gst_queue_array_clear (mpg123_decoder->audio_clip_info_queue);
+  gst_vec_deque_clear (mpg123_decoder->audio_clip_info_queue);
 }
 
 
 static guint
 gst_mpg123_audio_dec_get_info_queue_size (GstMpg123AudioDec * mpg123_decoder)
 {
-  return gst_queue_array_get_length (mpg123_decoder->audio_clip_info_queue);
+  return gst_vec_deque_get_length (mpg123_decoder->audio_clip_info_queue);
 }
 
 static gboolean
diff --git a/subprojects/gst-plugins-good/ext/mpg123/gstmpg123audiodec.h b/subprojects/gst-plugins-good/ext/mpg123/gstmpg123audiodec.h
index 2da140d718..ed1d13517e 100644
--- a/subprojects/gst-plugins-good/ext/mpg123/gstmpg123audiodec.h
+++ b/subprojects/gst-plugins-good/ext/mpg123/gstmpg123audiodec.h
@@ -42,7 +42,7 @@ struct _GstMpg123AudioDec
 
   off_t frame_offset;
 
-  GstQueueArray *audio_clip_info_queue;
+  GstVecDeque *audio_clip_info_queue;
 };
 
 GST_ELEMENT_REGISTER_DECLARE (mpg123audiodec);
diff --git a/subprojects/gst-plugins-good/gst/multifile/gstsplitmuxsink.c b/subprojects/gst-plugins-good/gst/multifile/gstsplitmuxsink.c
index b08347e863..0fa4fae394 100644
--- a/subprojects/gst-plugins-good/gst/multifile/gstsplitmuxsink.c
+++ b/subprojects/gst-plugins-good/gst/multifile/gstsplitmuxsink.c
@@ -620,7 +620,7 @@ gst_splitmux_sink_init (GstSplitMuxSink * splitmux)
   GST_OBJECT_FLAG_SET (splitmux, GST_ELEMENT_FLAG_SINK);
   splitmux->split_requested = FALSE;
   splitmux->do_split_next_gop = FALSE;
-  splitmux->times_to_split = gst_queue_array_new_for_struct (8, 8);
+  splitmux->times_to_split = gst_vec_deque_new_for_struct (8, 8);
   splitmux->next_fku_time = GST_CLOCK_TIME_NONE;
 
   g_queue_init (&splitmux->pending_input_gops);
@@ -697,7 +697,7 @@ gst_splitmux_sink_finalize (GObject * object)
     gst_video_time_code_interval_free (splitmux->tc_interval);
 
   if (splitmux->times_to_split)
-    gst_queue_array_free (splitmux->times_to_split);
+    gst_vec_deque_free (splitmux->times_to_split);
 
   g_free (splitmux->location);
 
@@ -2344,7 +2344,7 @@ need_new_fragment (GstSplitMuxSink * splitmux,
   thresh_bytes = splitmux->threshold_bytes;
   thresh_time = splitmux->threshold_time;
   ptr_to_time = (GstClockTime *)
-      gst_queue_array_peek_head_struct (splitmux->times_to_split);
+      gst_vec_deque_peek_head_struct (splitmux->times_to_split);
   if (ptr_to_time)
     time_to_split = *ptr_to_time;
   check_robust_muxing = splitmux->use_robust_muxing
@@ -2376,16 +2376,16 @@ need_new_fragment (GstSplitMuxSink * splitmux,
   if (gop->start_time >= time_to_split) {
     GST_OBJECT_LOCK (splitmux);
     /* Dequeue running time */
-    gst_queue_array_pop_head_struct (splitmux->times_to_split);
+    gst_vec_deque_pop_head_struct (splitmux->times_to_split);
     /* Empty any running times after this that are past now */
-    ptr_to_time = gst_queue_array_peek_head_struct (splitmux->times_to_split);
+    ptr_to_time = gst_vec_deque_peek_head_struct (splitmux->times_to_split);
     while (ptr_to_time) {
       time_to_split = *ptr_to_time;
       if (gop->start_time < time_to_split) {
         break;
       }
-      gst_queue_array_pop_head_struct (splitmux->times_to_split);
-      ptr_to_time = gst_queue_array_peek_head_struct (splitmux->times_to_split);
+      gst_vec_deque_pop_head_struct (splitmux->times_to_split);
+      ptr_to_time = gst_vec_deque_peek_head_struct (splitmux->times_to_split);
     }
     GST_TRACE_OBJECT (splitmux,
         "GOP start time %" GST_STIME_FORMAT " is after requested split point %"
@@ -3971,7 +3971,7 @@ gst_splitmux_sink_reset (GstSplitMuxSink * splitmux)
   g_atomic_int_set (&(splitmux->do_split_next_gop), FALSE);
 
   splitmux->next_fku_time = GST_CLOCK_TIME_NONE;
-  gst_queue_array_clear (splitmux->times_to_split);
+  gst_vec_deque_clear (splitmux->times_to_split);
 
   g_list_foreach (splitmux->contexts, (GFunc) mq_stream_ctx_reset, NULL);
   splitmux->queued_keyframes = 0;
@@ -4121,7 +4121,7 @@ split_at_running_time (GstSplitMuxSink * splitmux, GstClockTime split_time)
   gboolean send_keyframe_requests;
 
   GST_SPLITMUX_LOCK (splitmux);
-  gst_queue_array_push_tail_struct (splitmux->times_to_split, &split_time);
+  gst_vec_deque_push_tail_struct (splitmux->times_to_split, &split_time);
   send_keyframe_requests = splitmux->send_keyframe_requests;
   GST_SPLITMUX_UNLOCK (splitmux);
 
diff --git a/subprojects/gst-plugins-good/gst/multifile/gstsplitmuxsink.h b/subprojects/gst-plugins-good/gst/multifile/gstsplitmuxsink.h
index 140149adc1..ce4da4c837 100644
--- a/subprojects/gst-plugins-good/gst/multifile/gstsplitmuxsink.h
+++ b/subprojects/gst-plugins-good/gst/multifile/gstsplitmuxsink.h
@@ -210,7 +210,7 @@ struct _GstSplitMuxSink
 
   gboolean split_requested;
   gboolean do_split_next_gop;
-  GstQueueArray *times_to_split;
+  GstVecDeque *times_to_split;
 
   /* Async finalize options */
   gboolean async_finalize;
diff --git a/subprojects/gst-plugins-good/sys/osxaudio/gstatenc.c b/subprojects/gst-plugins-good/sys/osxaudio/gstatenc.c
index 4a8d04c4b9..a549678201 100644
--- a/subprojects/gst-plugins-good/sys/osxaudio/gstatenc.c
+++ b/subprojects/gst-plugins-good/sys/osxaudio/gstatenc.c
@@ -256,8 +256,8 @@ gst_atenc_start (GstAudioEncoder * enc)
 
   GST_DEBUG_OBJECT (self, "Starting encoder");
 
-  self->input_queue = gst_queue_array_new (0);
-  gst_queue_array_set_clear_func (self->input_queue,
+  self->input_queue = gst_vec_deque_new (0);
+  gst_vec_deque_set_clear_func (self->input_queue,
       (GDestroyNotify) gst_buffer_unref);
 
   return TRUE;
@@ -271,7 +271,7 @@ gst_atenc_flush (GstAudioEncoder * enc)
   GST_DEBUG_OBJECT (self, "Flushing encoder");
   AudioConverterReset (self->converter);
 
-  gst_queue_array_clear (self->input_queue);
+  gst_vec_deque_clear (self->input_queue);
 }
 
 static gboolean
@@ -288,7 +288,7 @@ gst_atenc_stop (GstAudioEncoder * enc)
     self->converter = NULL;
   }
 
-  gst_queue_array_free (self->input_queue);
+  gst_vec_deque_free (self->input_queue);
   self->input_queue = NULL;
 
   if (self->used_buffer) {
@@ -364,7 +364,7 @@ gst_atenc_fill_buffer (AudioConverterRef converter, UInt32 * packets_amount,
    * No data currently available, but more is expected => packets_amount=0 and return 1
    * No data available and input got EOS => packets_amount=0 and return noErr
    */
-  buf = gst_queue_array_pop_head (self->input_queue);
+  buf = gst_vec_deque_pop_head (self->input_queue);
   if (!buf) {
     *packets_amount = 0;
 
@@ -419,7 +419,7 @@ gst_atenc_handle_frame (GstAudioEncoder * enc, GstBuffer * buffer)
     GST_DEBUG_OBJECT (self, "No input buffer, draining encoder");
   } else {
     self->input_eos = FALSE;
-    gst_queue_array_push_tail (self->input_queue, buffer);
+    gst_vec_deque_push_tail (self->input_queue, buffer);
     GST_LOG ("Pushed buffer to queue");
   }
 
diff --git a/subprojects/gst-plugins-good/sys/osxaudio/gstatenc.h b/subprojects/gst-plugins-good/sys/osxaudio/gstatenc.h
index 6bfdd6fdc9..12fe673e9c 100644
--- a/subprojects/gst-plugins-good/sys/osxaudio/gstatenc.h
+++ b/subprojects/gst-plugins-good/sys/osxaudio/gstatenc.h
@@ -68,7 +68,7 @@ struct _GstATEnc
   AudioConverterRef converter;
   UInt32 max_output_buffer_size;
   UInt32 n_output_samples;
-  GstQueueArray *input_queue;
+  GstVecDeque *input_queue;
   GstAudioBuffer *used_buffer;
   gboolean input_eos;
 
diff --git a/subprojects/gst-rtsp-server/gst/rtsp-server/rtsp-stream-transport.c b/subprojects/gst-rtsp-server/gst/rtsp-server/rtsp-stream-transport.c
index 4502ec1fd5..39d2d84a00 100644
--- a/subprojects/gst-rtsp-server/gst/rtsp-server/rtsp-stream-transport.c
+++ b/subprojects/gst-rtsp-server/gst/rtsp-server/rtsp-stream-transport.c
@@ -88,7 +88,7 @@ struct _GstRTSPStreamTransportPrivate
 
   /* TCP backlog */
   GstClockTime first_rtp_timestamp;
-  GstQueueArray *items;
+  GstVecDeque *items;
   GRecMutex backlog_lock;
 };
 
@@ -141,9 +141,9 @@ static void
 gst_rtsp_stream_transport_init (GstRTSPStreamTransport * trans)
 {
   trans->priv = gst_rtsp_stream_transport_get_instance_private (trans);
-  trans->priv->items = gst_queue_array_new_for_struct (sizeof (BackLogItem), 0);
+  trans->priv->items = gst_vec_deque_new_for_struct (sizeof (BackLogItem), 0);
   trans->priv->first_rtp_timestamp = GST_CLOCK_TIME_NONE;
-  gst_queue_array_set_clear_func (trans->priv->items,
+  gst_vec_deque_set_clear_func (trans->priv->items,
       (GDestroyNotify) clear_backlog_item);
   g_rec_mutex_init (&trans->priv->backlog_lock);
 }
@@ -171,7 +171,7 @@ gst_rtsp_stream_transport_finalize (GObject * obj)
   if (priv->url)
     gst_rtsp_url_free (priv->url);
 
-  gst_queue_array_free (priv->items);
+  gst_vec_deque_free (priv->items);
 
   g_rec_mutex_clear (&priv->backlog_lock);
 
@@ -855,11 +855,11 @@ get_first_backlog_timestamp (GstRTSPStreamTransport * trans)
   GstClockTime ret = GST_CLOCK_TIME_NONE;
   guint i, l;
 
-  l = gst_queue_array_get_length (priv->items);
+  l = gst_vec_deque_get_length (priv->items);
 
   for (i = 0; i < l; i++) {
     BackLogItem *item = (BackLogItem *)
-        gst_queue_array_peek_nth_struct (priv->items, i);
+        gst_vec_deque_peek_nth_struct (priv->items, i);
 
     if (item->is_rtp) {
       ret = get_backlog_item_timestamp (item);
@@ -890,7 +890,7 @@ gst_rtsp_stream_transport_backlog_push (GstRTSPStreamTransport * trans,
     item.buffer_list = buffer_list;
   item.is_rtp = is_rtp;
 
-  gst_queue_array_push_tail_struct (priv->items, &item);
+  gst_vec_deque_push_tail_struct (priv->items, &item);
 
   item_timestamp = get_backlog_item_timestamp (&item);
 
@@ -904,7 +904,7 @@ gst_rtsp_stream_transport_backlog_push (GstRTSPStreamTransport * trans,
     g_assert (queue_duration >= 0);
 
     if (queue_duration > MAX_BACKLOG_DURATION &&
-        gst_queue_array_get_length (priv->items) > MAX_BACKLOG_SIZE) {
+        gst_vec_deque_get_length (priv->items) > MAX_BACKLOG_SIZE) {
       ret = FALSE;
     }
   } else if (is_rtp) {
@@ -930,7 +930,7 @@ gst_rtsp_stream_transport_backlog_pop (GstRTSPStreamTransport * trans,
 
   priv = trans->priv;
 
-  item = (BackLogItem *) gst_queue_array_pop_head_struct (priv->items);
+  item = (BackLogItem *) gst_vec_deque_pop_head_struct (priv->items);
 
   priv->first_rtp_timestamp = get_first_backlog_timestamp (trans);
 
@@ -963,7 +963,7 @@ gst_rtsp_stream_transport_backlog_peek_is_rtp (GstRTSPStreamTransport * trans)
 
   priv = trans->priv;
 
-  item = (BackLogItem *) gst_queue_array_peek_head_struct (priv->items);
+  item = (BackLogItem *) gst_vec_deque_peek_head_struct (priv->items);
 
   return item->is_rtp;
 }
@@ -974,7 +974,7 @@ gst_rtsp_stream_transport_backlog_peek_is_rtp (GstRTSPStreamTransport * trans)
 gboolean
 gst_rtsp_stream_transport_backlog_is_empty (GstRTSPStreamTransport * trans)
 {
-  return gst_queue_array_is_empty (trans->priv->items);
+  return gst_vec_deque_is_empty (trans->priv->items);
 }
 
 /* Not MT-safe, caller should ensure consistent locking.
diff --git a/subprojects/gstreamer/gst/gst.h b/subprojects/gstreamer/gst/gst.h
index 25010b3631..e599bbe6a5 100644
--- a/subprojects/gstreamer/gst/gst.h
+++ b/subprojects/gstreamer/gst/gst.h
@@ -90,6 +90,7 @@
 #include <gst/gsturi.h>
 #include <gst/gstutils.h>
 #include <gst/gstvalue.h>
+#include <gst/gstvecdeque.h>
 
 #include <gst/gstparse.h>
 
diff --git a/subprojects/gstreamer/gst/gstvecdeque.c b/subprojects/gstreamer/gst/gstvecdeque.c
new file mode 100644
index 0000000000..dd1ba81ed1
--- /dev/null
+++ b/subprojects/gstreamer/gst/gstvecdeque.c
@@ -0,0 +1,994 @@
+/* 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"
+
+#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_element_tail: (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_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_vec_deque_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_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/subprojects/gstreamer/gst/gstvecdeque.h b/subprojects/gstreamer/gst/gstvecdeque.h
new file mode 100644
index 0000000000..dd98f1c997
--- /dev/null
+++ b/subprojects/gstreamer/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/subprojects/gstreamer/gst/meson.build b/subprojects/gstreamer/gst/meson.build
index 03f4996731..c5aabcb12e 100644
--- a/subprojects/gstreamer/gst/meson.build
+++ b/subprojects/gstreamer/gst/meson.build
@@ -69,6 +69,7 @@ gst_sources = files(
   'gsturi.c',
   'gstutils.c',
   'gstvalue.c',
+  'gstvecdeque.c',
   'gstparse.c',
 )
 
@@ -144,6 +145,7 @@ gst_headers = files(
   'gsturi.h',
   'gstutils.h',
   'gstvalue.h',
+  'gstvecdeque.h',
   'gstregistry.h',
   'gstparse.h',
   'math-compat.h',
diff --git a/subprojects/gstreamer/libs/gst/base/base-prelude.h b/subprojects/gstreamer/libs/gst/base/base-prelude.h
index 87defde34e..d1a9c36fa2 100644
--- a/subprojects/gstreamer/libs/gst/base/base-prelude.h
+++ b/subprojects/gstreamer/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/subprojects/gstreamer/libs/gst/base/gstadapter.c b/subprojects/gstreamer/libs/gst/base/gstadapter.c
index 8af45eded2..5886ee932e 100644
--- a/subprojects/gstreamer/libs/gst/base/gstadapter.c
+++ b/subprojects/gstreamer/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);
 
@@ -1355,7 +1355,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;
@@ -1557,10 +1557,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);
@@ -1607,10 +1607,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 +1680,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 +1725,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/subprojects/gstreamer/libs/gst/base/gstdataqueue.c b/subprojects/gstreamer/libs/gst/base/gstdataqueue.c
index ac93b8e346..e226e3a772 100644
--- a/subprojects/gstreamer/libs/gst/base/gstdataqueue.c
+++ b/subprojects/gstreamer/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/subprojects/gstreamer/libs/gst/base/gstqueuearray.c b/subprojects/gstreamer/libs/gst/base/gstqueuearray.c
index cfd80e4734..c67f892499 100644
--- a/subprojects/gstreamer/libs/gst/base/gstqueuearray.c
+++ b/subprojects/gstreamer/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/subprojects/gstreamer/libs/gst/base/gstqueuearray.h b/subprojects/gstreamer/libs/gst/base/gstqueuearray.h
index 2a63e95cf3..fa5b8c5573 100644
--- a/subprojects/gstreamer/libs/gst/base/gstqueuearray.h
+++ b/subprojects/gstreamer/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/subprojects/gstreamer/plugins/elements/gstqueue.c b/subprojects/gstreamer/plugins/elements/gstqueue.c
index 50c2bf59f2..ccfafc0228 100644
--- a/subprojects/gstreamer/plugins/elements/gstqueue.c
+++ b/subprojects/gstreamer/plugins/elements/gstqueue.c
@@ -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
@@ -467,7 +467,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 +492,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,7 +745,7 @@ 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)
@@ -792,7 +792,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);
 }
 
@@ -813,7 +813,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);
 }
 
@@ -838,7 +838,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;
@@ -857,7 +857,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);
 }
 
@@ -869,7 +869,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;
 
@@ -1112,7 +1112,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)
@@ -1143,7 +1143,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;
diff --git a/subprojects/gstreamer/plugins/elements/gstqueue.h b/subprojects/gstreamer/plugins/elements/gstqueue.h
index cc632ad355..d1a434905d 100644
--- a/subprojects/gstreamer/plugins/elements/gstqueue.h
+++ b/subprojects/gstreamer/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 */
diff --git a/subprojects/gstreamer/plugins/elements/gstqueue2.c b/subprojects/gstreamer/plugins/elements/gstqueue2.c
index 999c231d14..04770370f8 100644
--- a/subprojects/gstreamer/plugins/elements/gstqueue2.c
+++ b/subprojects/gstreamer/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);
@@ -1905,7 +1905,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
@@ -2432,7 +2432,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));
     }
@@ -2464,7 +2464,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;
@@ -2851,7 +2851,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/subprojects/gstreamer/plugins/elements/gstqueue2.h b/subprojects/gstreamer/plugins/elements/gstqueue2.h
index 8ad8a19f22..40c69b5edb 100644
--- a/subprojects/gstreamer/plugins/elements/gstqueue2.h
+++ b/subprojects/gstreamer/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/subprojects/gstreamer/tests/check/gst/gstvecdeque.c b/subprojects/gstreamer/tests/check/gst/gstvecdeque.c
new file mode 100644
index 0000000000..5a76737eae
--- /dev/null
+++ b/subprojects/gstreamer/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/subprojects/gstreamer/tests/check/libs/gstlibscpp.cc b/subprojects/gstreamer/tests/check/libs/gstlibscpp.cc
index bee25889ed..84338b714c 100644
--- a/subprojects/gstreamer/tests/check/libs/gstlibscpp.cc
+++ b/subprojects/gstreamer/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/subprojects/gstreamer/tests/check/libs/queuearray.c b/subprojects/gstreamer/tests/check/libs/queuearray.c
index ecce1ec366..ec4ab61aa9 100644
--- a/subprojects/gstreamer/tests/check/libs/queuearray.c
+++ b/subprojects/gstreamer/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/subprojects/gstreamer/tests/check/meson.build b/subprojects/gstreamer/tests/check/meson.build
index 65402791aa..3b898449df 100644
--- a/subprojects/gstreamer/tests/check/meson.build
+++ b/subprojects/gstreamer/tests/check/meson.build
@@ -51,6 +51,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' ],