diff --git a/subprojects/gst-plugins-bad/gst-libs/gst/mpegts/gst-metadata-descriptor.c b/subprojects/gst-plugins-bad/gst-libs/gst/mpegts/gst-metadata-descriptor.c
deleted file mode 100644
index 0652a592d5..0000000000
--- a/subprojects/gst-plugins-bad/gst-libs/gst/mpegts/gst-metadata-descriptor.c
+++ /dev/null
@@ -1,137 +0,0 @@
-/* Gstreamer
- * Copyright 2023 Brad Hards <bradh@frogmouth.net>
- *
- * 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., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "mpegts.h"
-#include "gstmpegts-private.h"
-
-#define GST_CAT_DEFAULT mpegts_debug
-
-static GstMpegtsMetadataDescriptor
-    * _gst_mpegts_metadata_descriptor_copy
-    (GstMpegtsMetadataDescriptor * source)
-{
-  GstMpegtsMetadataDescriptor *copy =
-      g_memdup2 (source, sizeof (GstMpegtsMetadataDescriptor));
-  return copy;
-}
-
-static void
-_gst_mpegts_metadata_descriptor_free (GstMpegtsMetadataDescriptor * desc)
-{
-  g_free (desc);
-}
-
-G_DEFINE_BOXED_TYPE (GstMpegtsMetadataDescriptor,
-    gst_mpegts_metadata_descriptor,
-    (GBoxedCopyFunc) _gst_mpegts_metadata_descriptor_copy,
-    (GFreeFunc) _gst_mpegts_metadata_descriptor_free);
-
-/**
- * gst_mpegts_descriptor_parse_metadata:
- * @descriptor: a %GST_TYPE_MPEGTS_METADATA_DESCRIPTOR #GstMpegtsDescriptor
- * @res: (out) (transfer full): #GstMpegtsMetadataDescriptor
- *
- * Parses out the metadata descriptor from the @descriptor.
- *
- * See ISO/IEC 13818-1:2018 Section 2.6.60 and 2.6.61 for details.
- * metadata_application_format is provided in Table 2-82. metadata_format is
- * provided in Table 2-85.
- *
- * Returns: %TRUE if the parsing worked correctly, else %FALSE.
- *
- * Since: 1.24
- */
-gboolean
-gst_mpegts_descriptor_parse_metadata (const GstMpegtsDescriptor * descriptor,
-    GstMpegtsMetadataDescriptor ** desc)
-{
-  guint8 *data;
-  guint8 flag;
-  GstMpegtsMetadataDescriptor *res;
-
-  g_return_val_if_fail (descriptor != NULL && desc != NULL, FALSE);
-  __common_desc_checks (descriptor, GST_MTS_DESC_METADATA, 5, FALSE);
-
-  data = (guint8 *) descriptor->data + 2;
-
-  res = g_new0 (GstMpegtsMetadataDescriptor, 1);
-
-  res->metadata_application_format = GST_READ_UINT16_BE (data);
-  data += 2;
-  if (res->metadata_application_format == 0xFFFF) {
-    // skip over metadata_application_format_identifier if it is provided
-    data += 4;
-  }
-  res->metadata_format = *data;
-  data += 1;
-  if (res->metadata_format == GST_MPEGTS_METADATA_FORMAT_IDENTIFIER_FIELD) {
-    res->metadata_format_identifier = GST_READ_UINT32_BE (data);
-    data += 4;
-  }
-  res->metadata_service_id = *data;
-  data += 1;
-  flag = *data;
-  res->decoder_config_flags = flag >> 5;
-  res->dsm_cc_flag = (flag & 0x10);
-
-  // There are more values if the dsm_cc_flag or decoder flags are set.
-
-  *desc = res;
-
-  return TRUE;
-}
-
-/**
- * gst_mpegts_descriptor_parse_metadata_std:
- * @descriptor: a %GST_MTS_DESC_METADATA_STD #GstMpegtsDescriptor
- * @metadata_input_leak_rate (out): the input leak rate in units of 400bits/sec.
- * @metadata_buffer_size (out): the buffer size in units of 1024 bytes
- * @metadata_output_leak_rate (out): the output leak rate in units of 400bits/sec.
- *
- * Extracts the metadata STD descriptor from @descriptor.
- *
- * See ISO/IEC 13818-1:2018 Section 2.6.62 and 2.6.63 for details.
- *
- * Returns: %TRUE if parsing succeeded, else %FALSE.
- *
- * Since: 1.24
- */
-gboolean
-gst_mpegts_descriptor_parse_metadata_std (const GstMpegtsDescriptor *
-    descriptor, guint32 * metadata_input_leak_rate,
-    guint32 * metadata_buffer_size, guint32 * metadata_output_leak_rate)
-{
-  guint8 *data;
-
-  g_return_val_if_fail (descriptor != NULL && metadata_input_leak_rate != NULL
-      && metadata_buffer_size != NULL
-      && metadata_output_leak_rate != NULL, FALSE);
-  __common_desc_checks (descriptor, GST_MTS_DESC_METADATA_STD, 9, FALSE);
-  data = (guint8 *) descriptor->data + 2;
-  *metadata_input_leak_rate = GST_READ_UINT24_BE (data) & 0x3FFFFF;
-  data += 3;
-  *metadata_buffer_size = GST_READ_UINT24_BE (data) & 0x3FFFFF;
-  data += 3;
-  *metadata_output_leak_rate = GST_READ_UINT24_BE (data) & 0x3FFFFF;
-  return TRUE;
-}
diff --git a/subprojects/gst-plugins-bad/gst-libs/gst/mpegts/gst-metadata-descriptor.h b/subprojects/gst-plugins-bad/gst-libs/gst/mpegts/gst-metadata-descriptor.h
deleted file mode 100644
index acbe497cdf..0000000000
--- a/subprojects/gst-plugins-bad/gst-libs/gst/mpegts/gst-metadata-descriptor.h
+++ /dev/null
@@ -1,116 +0,0 @@
-/* Gstreamer
- * Copyright 2023 Brad Hards <bradh@frogmouth.net>
- *
- * 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., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifndef __GST_MPEGTS_METADATA_DESCRIPTOR_H__
-#define __GST_MPEGTS_METADATA_DESCRIPTOR_H__
-
-#include <gst/gst.h>
-#include <gst/mpegts/mpegts-prelude.h>
-
-G_BEGIN_DECLS
-
-/**
- * GstMpegtsMetadataFormat:
- *
- * metadata_descriptor metadata_format valid values. See ISO/IEC 13818-1:2018(E) Table 2-85.
- *
- * Since: 1.24
- */
-typedef enum {
-  /**
-   * GST_MPEGTS_METADATA_FORMAT_TEM:
-   *
-   * ISO/IEC 15938-1 TeM.
-   *
-   * Since: 1.24
-   */
-  GST_MPEGTS_METADATA_FORMAT_TEM = 0x10,
-  /**
-   * GST_MPEGTS_METADATA_FORMAT_BIM:
-   *
-   * ISO/IEC 15938-1 BiM.
-   *
-   * Since: 1.24
-   */
-  GST_MPEGTS_METADATA_FORMAT_BIM = 0x11,
-  /**
-   * GST_MPEGTS_METADATA_FORMAT_APPLICATION_FORMAT:
-   *
-   * Defined by metadata application format.
-   *
-   * Since: 1.24
-   */
-  GST_MPEGTS_METADATA_FORMAT_APPLICATION_FORMAT = 0x3f,
-  /**
-   * GST_MPEGTS_METADATA_FORMAT_IDENTIFIER_FIELD:
-   *
-   * Defined by metadata_format_identifier field.
-   *
-   * Since: 1.24
-   */
-  GST_MPEGTS_METADATA_FORMAT_IDENTIFIER_FIELD = 0xff
-} GstMpegtsMetadataFormat;
-
-
-/* MPEG-TS Metadata Descriptor (0x26) */
-typedef struct _GstMpegtsMetadataDescriptor GstMpegtsMetadataDescriptor;
-
-/**
- * GstMpegtsMetadataDescriptor:
- * @metadata_application_format: specifies the application responsible for defining usage, syntax and semantics
- * @metadata_format: indicates the format and coding of the metadata
- * @metadata_format_identifier: format identifier (equivalent to registration descriptor), for example 0x4B4C4641 ('KLVA') to indicate SMPTE 336 KLV.
- * @metadata_service_id:  metadata service to which this metadata descriptor applies, typically 0x00
- * @decoder_config_flags: decoder flags, see ISO/IEC 13818-1:2018 Table 2-88.
- * @dsm_cc_flag: true if stream associated with this descriptor is in an ISO/IEC 13818-6 data or object carousel.
- *
- * The metadata descriptor specifies parameters of a metadata service carried in an MPEG-2 Transport Stream (or Program Stream). The descriptor is included in the PMT in the descriptor loop for the elementary stream that carries the
-metadata service. The descriptor specifies the format of the associated metadata, and contains the value of the
-metadata_service_id to identify the metadata service to which the metadata descriptor applies.
- *
- * Note that this structure does not include all of the metadata_descriptor items, and will need extension to support DSM-CC and private data.
- * See ISO/IEC 13818-1:2018 Section 2.6.60 and Section 2.6.61 for more information.
- *
- * Since: 1.24
- */
-struct _GstMpegtsMetadataDescriptor
-{
-  guint16 metadata_application_format;
-  GstMpegtsMetadataFormat metadata_format;
-  guint32 metadata_format_identifier;
-  guint8 metadata_service_id;
-  guint8 decoder_config_flags;
-  gboolean dsm_cc_flag;
-};
-
-/**
- * GST_TYPE_MPEGTS_METADATA_DESCRIPTOR:
- *
- * metadata_descriptor type
- *
- * Since: 1.24
- */
-#define GST_TYPE_MPEGTS_METADATA_DESCRIPTOR (gst_mpegts_metadata_descriptor_get_type ())
-
-GST_MPEGTS_API
-GType gst_mpegts_metadata_descriptor_get_type (void);
-
-G_END_DECLS
-
-#endif
diff --git a/subprojects/gst-plugins-bad/gst-libs/gst/mpegts/gst-mpegtspesmetadatameta.c b/subprojects/gst-plugins-bad/gst-libs/gst/mpegts/gst-mpegtspesmetadatameta.c
deleted file mode 100644
index cc9ce3877e..0000000000
--- a/subprojects/gst-plugins-bad/gst-libs/gst/mpegts/gst-mpegtspesmetadatameta.c
+++ /dev/null
@@ -1,106 +0,0 @@
-/* Gstreamer
- * Copyright 2021 Brad Hards <bradh@frogmouth.net>
- *
- * 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., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "gst-mpegtspesmetadatameta.h"
-
-#define GST_CAT_DEFAULT mpegts_debug
-
-static gboolean
-gst_mpegts_pes_metadata_meta_init (GstMpegtsPESMetadataMeta * meta,
-    gpointer params, GstBuffer * buffer)
-{
-  return TRUE;
-}
-
-static void
-gst_mpegts_pes_metadata_meta_free (GstMpegtsPESMetadataMeta * meta,
-    GstBuffer * buffer)
-{
-}
-
-static gboolean
-gst_mpegts_pes_metadata_meta_transform (GstBuffer * dest, GstMeta * meta,
-    GstBuffer * buffer, GQuark type, gpointer data)
-{
-  GstMpegtsPESMetadataMeta *source_meta, *dest_meta;
-
-  source_meta = (GstMpegtsPESMetadataMeta *) meta;
-
-  if (GST_META_TRANSFORM_IS_COPY (type)) {
-    GstMetaTransformCopy *copy = data;
-    if (!copy->region) {
-      dest_meta = gst_buffer_add_mpegts_pes_metadata_meta (dest);
-      if (!dest_meta)
-        return FALSE;
-      dest_meta->metadata_service_id = source_meta->metadata_service_id;
-      dest_meta->flags = source_meta->flags;
-    }
-  } else {
-    /* return FALSE, if transform type is not supported */
-    return FALSE;
-  }
-  return TRUE;
-}
-
-GType
-gst_mpegts_pes_metadata_meta_api_get_type (void)
-{
-  static GType type;
-  static const gchar *tags[] = { NULL };
-
-  if (g_once_init_enter (&type)) {
-    GType _type =
-        gst_meta_api_type_register ("GstMpegtsPESMetadataMetaAPI", tags);
-    g_once_init_leave (&type, _type);
-  }
-  return type;
-}
-
-const GstMetaInfo *
-gst_mpegts_pes_metadata_meta_get_info (void)
-{
-  static const GstMetaInfo *mpegts_pes_metadata_meta_info = NULL;
-
-  if (g_once_init_enter ((GstMetaInfo **) & mpegts_pes_metadata_meta_info)) {
-    const GstMetaInfo *meta =
-        gst_meta_register (GST_MPEGTS_PES_METADATA_META_API_TYPE,
-        "GstMpegtsPESMetadataMeta", sizeof (GstMpegtsPESMetadataMeta),
-        (GstMetaInitFunction) gst_mpegts_pes_metadata_meta_init,
-        (GstMetaFreeFunction) gst_mpegts_pes_metadata_meta_free,
-        (GstMetaTransformFunction) gst_mpegts_pes_metadata_meta_transform);
-    g_once_init_leave ((GstMetaInfo **) & mpegts_pes_metadata_meta_info,
-        (GstMetaInfo *) meta);
-  }
-
-  return mpegts_pes_metadata_meta_info;
-}
-
-GstMpegtsPESMetadataMeta *
-gst_buffer_add_mpegts_pes_metadata_meta (GstBuffer * buffer)
-{
-  GstMpegtsPESMetadataMeta *meta;
-  meta =
-      (GstMpegtsPESMetadataMeta *) gst_buffer_add_meta (buffer,
-      GST_MPEGTS_PES_METADATA_META_INFO, NULL);
-  return meta;
-}
diff --git a/subprojects/gst-plugins-bad/gst-libs/gst/mpegts/gst-mpegtspesmetadatameta.h b/subprojects/gst-plugins-bad/gst-libs/gst/mpegts/gst-mpegtspesmetadatameta.h
deleted file mode 100644
index ac94408671..0000000000
--- a/subprojects/gst-plugins-bad/gst-libs/gst/mpegts/gst-mpegtspesmetadatameta.h
+++ /dev/null
@@ -1,108 +0,0 @@
-/* Gstreamer
- * Copyright 2021,2023 Brad Hards <bradh@frogmouth.net>
- *
- * 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., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifndef __GST_MPEGTS_PES_METADATA_META_H__
-#define __GST_MPEGTS_PES_METADATA_META_H__
-
-#include <gst/gst.h>
-#include <gst/mpegts/mpegts-prelude.h>
-
-G_BEGIN_DECLS
-
-typedef struct _GstMpegtsPESMetadataMeta GstMpegtsPESMetadataMeta;
-
-/**
- * gst_mpegts_pes_metadata_meta_api_get_type
- *
- * Return the #GType associated with #GstMpegtsPESMetadataMeta
- *
- * Returns: a #GType
- *
- * Since: 1.24
- */
-GST_MPEGTS_API
-GType gst_mpegts_pes_metadata_meta_api_get_type (void);
-
-/**
- * GST_MPEGTS_PES_METADATA_META_API_TYPE:
- *
- * The #GType associated with #GstMpegtsPESMetadataMeta.
- *
- * Since: 1.24
- */
-#define GST_MPEGTS_PES_METADATA_META_API_TYPE  (gst_mpegts_pes_metadata_meta_api_get_type())
-
-/**
- * GST_MPEGTS_PES_METADATA_META_INFO:
- *
- * The #GstMetaInfo associated with #GstMpegtsPESMetadataMeta.
- *
- * Since: 1.24
- */
-#define GST_MPEGTS_PES_METADATA_META_INFO  (gst_mpegts_pes_metadata_meta_get_info())
-
-/**
- * gst_mpegts_pes_metadata_meta_get_info:
- *
- * Gets the global #GstMetaInfo describing the #GstMpegtsPESMetadataMeta meta.
- *
- * Returns: (transfer none): The #GstMetaInfo
- *
- * Since: 1.24
- */
-GST_MPEGTS_API
-const GstMetaInfo * gst_mpegts_pes_metadata_meta_get_info (void);
-
-/**
- * GstMpegtsPESMetadataMeta:
- * @meta: parent #GstMeta
- * @metadata_service_id: metadata service identifier
- * @flags: bit flags, see spec for details
- *
- * Extra buffer metadata describing the PES Metadata context.
- * This is based on the Metadata AU cell header in
- * ISO/IEC 13818-1:2018 Section 2.12.4.
- *
- * AU_cell_data_length is not provided, since it matches the length of the buffer
- *
- * Since: 1.24
- */
-struct _GstMpegtsPESMetadataMeta {
-  GstMeta            meta;
-  guint8             metadata_service_id;
-  guint8             flags;
-};
-
-/**
- * gst_buffer_add_mpegts_pes_metadata_meta:
- * @buffer: a #GstBuffer
- *
- * Creates and adds a #GstMpegtsPESMetadataMeta to a @buffer.
- *
- * Returns: (transfer none): a newly created #GstMpegtsPESMetadataMeta
- *
- * Since: 1.24
- */
-GST_MPEGTS_API
-GstMpegtsPESMetadataMeta *
-gst_buffer_add_mpegts_pes_metadata_meta (GstBuffer * buffer);
-
-G_END_DECLS
-
-#endif
diff --git a/subprojects/gst-plugins-bad/gst-libs/gst/mpegts/gstmpegtsdescriptor.c b/subprojects/gst-plugins-bad/gst-libs/gst/mpegts/gstmpegtsdescriptor.c
index 0d324a7d8d..ef43a3c1ab 100644
--- a/subprojects/gst-plugins-bad/gst-libs/gst/mpegts/gstmpegtsdescriptor.c
+++ b/subprojects/gst-plugins-bad/gst-libs/gst/mpegts/gstmpegtsdescriptor.c
@@ -29,6 +29,7 @@
 
 #include "mpegts.h"
 #include "gstmpegts-private.h"
+#include <gst/base/gstbytewriter.h>
 
 #define DEFINE_STATIC_COPY_FUNCTION(type, name) \
 static type * _##name##_copy (type * source) \
@@ -1247,3 +1248,232 @@ gst_mpegts_descriptor_from_custom_with_extension (guint8 tag,
 
   return descriptor;
 }
+
+static GstMpegtsMetadataDescriptor *
+_gst_mpegts_metadata_descriptor_copy (GstMpegtsMetadataDescriptor * source)
+{
+  GstMpegtsMetadataDescriptor *copy =
+      g_memdup2 (source, sizeof (GstMpegtsMetadataDescriptor));
+  return copy;
+}
+
+static void
+_gst_mpegts_metadata_descriptor_free (GstMpegtsMetadataDescriptor * desc)
+{
+  g_free (desc);
+}
+
+G_DEFINE_BOXED_TYPE (GstMpegtsMetadataDescriptor,
+    gst_mpegts_metadata_descriptor,
+    (GBoxedCopyFunc) _gst_mpegts_metadata_descriptor_copy,
+    (GFreeFunc) _gst_mpegts_metadata_descriptor_free);
+
+GstMpegtsDescriptor *
+gst_mpegts_descriptor_from_metadata (const GstMpegtsMetadataDescriptor *
+    metadata_descriptor)
+{
+  g_return_val_if_fail (metadata_descriptor != NULL, NULL);
+
+  int wr_size = 0;
+  guint8 *add_info = NULL;
+  GstByteWriter writer;
+
+  // metadata_descriptor
+  gst_byte_writer_init_with_size (&writer, 32, FALSE);
+
+  gst_byte_writer_put_uint16_be (&writer,
+      metadata_descriptor->metadata_application_format);
+  if (metadata_descriptor->metadata_application_format == 0xFFFF) {
+    gst_byte_writer_put_uint32_be (&writer, metadata_descriptor->metadata_format_identifier);   // metadata_application_format_identifier
+  }
+
+  gst_byte_writer_put_uint8 (&writer, metadata_descriptor->metadata_format);
+  if (metadata_descriptor->metadata_format ==
+      GST_MPEGTS_METADATA_FORMAT_IDENTIFIER_FIELD) {
+    gst_byte_writer_put_uint32_be (&writer, metadata_descriptor->metadata_format_identifier);   // metadata_format_identifier
+  }
+
+  gst_byte_writer_put_uint8 (&writer, metadata_descriptor->metadata_service_id);
+  gst_byte_writer_put_uint8 (&writer, 0x0F);    // decoder_config_flags = 000, DSM_CC_flag = 0, reserved = 1111
+
+  wr_size = gst_byte_writer_get_size (&writer);
+  add_info = gst_byte_writer_reset_and_get_data (&writer);
+
+  GstMpegtsDescriptor *descriptor =
+      _new_descriptor (GST_MTS_DESC_METADATA, wr_size);
+  memcpy (descriptor->data + 2, add_info, wr_size);
+  g_free (add_info);
+
+  return descriptor;
+}
+
+/**
+ * gst_mpegts_descriptor_parse_metadata:
+ * @descriptor: a %GST_TYPE_MPEGTS_METADATA_DESCRIPTOR #GstMpegtsDescriptor
+ * @res: (out) (transfer full): #GstMpegtsMetadataDescriptor
+ *
+ * Parses out the metadata descriptor from the @descriptor.
+ *
+ * See ISO/IEC 13818-1:2018 Section 2.6.60 and 2.6.61 for details.
+ * metadata_application_format is provided in Table 2-82. metadata_format is
+ * provided in Table 2-85.
+ *
+ * Returns: %TRUE if the parsing worked correctly, else %FALSE.
+ *
+ * Since: 1.24
+ */
+gboolean
+gst_mpegts_descriptor_parse_metadata (const GstMpegtsDescriptor * descriptor,
+    GstMpegtsMetadataDescriptor ** desc)
+{
+  guint8 *data;
+  guint8 flag;
+  GstMpegtsMetadataDescriptor *res;
+
+  g_return_val_if_fail (descriptor != NULL && desc != NULL, FALSE);
+  __common_desc_checks (descriptor, GST_MTS_DESC_METADATA, 5, FALSE);
+
+  data = (guint8 *) descriptor->data + 2;
+
+  res = g_new0 (GstMpegtsMetadataDescriptor, 1);
+
+  res->metadata_application_format = GST_READ_UINT16_BE (data);
+  data += 2;
+  if (res->metadata_application_format == 0xFFFF) {
+    // skip over metadata_application_format_identifier if it is provided
+    data += 4;
+  }
+  res->metadata_format = *data;
+  data += 1;
+  if (res->metadata_format == GST_MPEGTS_METADATA_FORMAT_IDENTIFIER_FIELD) {
+    res->metadata_format_identifier = GST_READ_UINT32_BE (data);
+    data += 4;
+  }
+  res->metadata_service_id = *data;
+  data += 1;
+  flag = *data;
+  res->decoder_config_flags = flag >> 5;
+  res->dsm_cc_flag = (flag & 0x10);
+
+  // There are more values if the dsm_cc_flag or decoder flags are set.
+
+  *desc = res;
+
+  return TRUE;
+}
+
+/**
+ * gst_mpegts_descriptor_parse_metadata_std:
+ * @descriptor: a %GST_MTS_DESC_METADATA_STD #GstMpegtsDescriptor
+ * @metadata_input_leak_rate (out): the input leak rate in units of 400bits/sec.
+ * @metadata_buffer_size (out): the buffer size in units of 1024 bytes
+ * @metadata_output_leak_rate (out): the output leak rate in units of 400bits/sec.
+ *
+ * Extracts the metadata STD descriptor from @descriptor.
+ *
+ * See ISO/IEC 13818-1:2018 Section 2.6.62 and 2.6.63 for details.
+ *
+ * Returns: %TRUE if parsing succeeded, else %FALSE.
+ *
+ * Since: 1.24
+ */
+gboolean
+gst_mpegts_descriptor_parse_metadata_std (const GstMpegtsDescriptor *
+    descriptor,
+    guint32 * metadata_input_leak_rate,
+    guint32 * metadata_buffer_size, guint32 * metadata_output_leak_rate)
+{
+  guint8 *data;
+
+  g_return_val_if_fail (descriptor != NULL && metadata_input_leak_rate != NULL
+      && metadata_buffer_size != NULL
+      && metadata_output_leak_rate != NULL, FALSE);
+  __common_desc_checks (descriptor, GST_MTS_DESC_METADATA_STD, 9, FALSE);
+  data = (guint8 *) descriptor->data + 2;
+  *metadata_input_leak_rate = GST_READ_UINT24_BE (data) & 0x3FFFFF;
+  data += 3;
+  *metadata_buffer_size = GST_READ_UINT24_BE (data) & 0x3FFFFF;
+  data += 3;
+  *metadata_output_leak_rate = GST_READ_UINT24_BE (data) & 0x3FFFFF;
+  return TRUE;
+}
+
+static gboolean
+gst_mpegts_pes_metadata_meta_init (GstMpegtsPESMetadataMeta * meta,
+    gpointer params, GstBuffer * buffer)
+{
+  return TRUE;
+}
+
+static void
+gst_mpegts_pes_metadata_meta_free (GstMpegtsPESMetadataMeta * meta,
+    GstBuffer * buffer)
+{
+}
+
+static gboolean
+gst_mpegts_pes_metadata_meta_transform (GstBuffer * dest, GstMeta * meta,
+    GstBuffer * buffer, GQuark type, gpointer data)
+{
+  GstMpegtsPESMetadataMeta *source_meta, *dest_meta;
+
+  source_meta = (GstMpegtsPESMetadataMeta *) meta;
+
+  if (GST_META_TRANSFORM_IS_COPY (type)) {
+    GstMetaTransformCopy *copy = data;
+    if (!copy->region) {
+      dest_meta = gst_buffer_add_mpegts_pes_metadata_meta (dest);
+      if (!dest_meta)
+        return FALSE;
+      dest_meta->metadata_service_id = source_meta->metadata_service_id;
+      dest_meta->flags = source_meta->flags;
+    }
+  } else {
+    /* return FALSE, if transform type is not supported */
+    return FALSE;
+  }
+  return TRUE;
+}
+
+GType
+gst_mpegts_pes_metadata_meta_api_get_type (void)
+{
+  static GType type;
+  static const gchar *tags[] = { NULL };
+
+  if (g_once_init_enter (&type)) {
+    GType _type =
+        gst_meta_api_type_register ("GstMpegtsPESMetadataMetaAPI", tags);
+    g_once_init_leave (&type, _type);
+  }
+  return type;
+}
+
+const GstMetaInfo *
+gst_mpegts_pes_metadata_meta_get_info (void)
+{
+  static const GstMetaInfo *mpegts_pes_metadata_meta_info = NULL;
+
+  if (g_once_init_enter ((GstMetaInfo **) & mpegts_pes_metadata_meta_info)) {
+    const GstMetaInfo *meta =
+        gst_meta_register (GST_MPEGTS_PES_METADATA_META_API_TYPE,
+        "GstMpegtsPESMetadataMeta", sizeof (GstMpegtsPESMetadataMeta),
+        (GstMetaInitFunction) gst_mpegts_pes_metadata_meta_init,
+        (GstMetaFreeFunction) gst_mpegts_pes_metadata_meta_free,
+        (GstMetaTransformFunction) gst_mpegts_pes_metadata_meta_transform);
+    g_once_init_leave ((GstMetaInfo **) & mpegts_pes_metadata_meta_info,
+        (GstMetaInfo *) meta);
+  }
+
+  return mpegts_pes_metadata_meta_info;
+}
+
+GstMpegtsPESMetadataMeta *
+gst_buffer_add_mpegts_pes_metadata_meta (GstBuffer * buffer)
+{
+  GstMpegtsPESMetadataMeta *meta;
+  meta =
+      (GstMpegtsPESMetadataMeta *) gst_buffer_add_meta (buffer,
+      GST_MPEGTS_PES_METADATA_META_INFO, NULL);
+  return meta;
+}
diff --git a/subprojects/gst-plugins-bad/gst-libs/gst/mpegts/gstmpegtsdescriptor.h b/subprojects/gst-plugins-bad/gst-libs/gst/mpegts/gstmpegtsdescriptor.h
index 44782abbc7..860c464ca3 100644
--- a/subprojects/gst-plugins-bad/gst-libs/gst/mpegts/gstmpegtsdescriptor.h
+++ b/subprojects/gst-plugins-bad/gst-libs/gst/mpegts/gstmpegtsdescriptor.h
@@ -32,7 +32,6 @@
 #ifndef GST_MPEGTS_DESCRIPTOR_H
 #define GST_MPEGTS_DESCRIPTOR_H
 
-#include "gst-metadata-descriptor.h"
 #include <gst/gst.h>
 #include <gst/mpegts/mpegts-prelude.h>
 
@@ -344,15 +343,6 @@ guint gst_mpegts_descriptor_parse_iso_639_language_nb (const GstMpegtsDescriptor
 GST_MPEGTS_API
 GstMpegtsDescriptor * gst_mpegts_descriptor_from_iso_639_language (const gchar * language);
 
-GST_MPEGTS_API
-gboolean gst_mpegts_descriptor_parse_metadata (const GstMpegtsDescriptor *descriptor, GstMpegtsMetadataDescriptor **res);
-
-GST_MPEGTS_API
-gboolean gst_mpegts_descriptor_parse_metadata_std (const GstMpegtsDescriptor *descriptor,
-                                                   guint32 *metadata_input_leak_rate,
-                                                   guint32 *metadata_buffer_size,
-                                                   guint32 *metadata_output_leak_rate);
-
 /* GST_MTS_DESC_DTG_LOGICAL_CHANNEL (0x83) */
 typedef struct _GstMpegtsLogicalChannelDescriptor GstMpegtsLogicalChannelDescriptor;
 typedef struct _GstMpegtsLogicalChannel GstMpegtsLogicalChannel;
@@ -396,6 +386,184 @@ GST_MPEGTS_API
 GstMpegtsDescriptor *
 gst_mpegts_descriptor_from_custom_with_extension (guint8 tag, guint8 tag_extension, const guint8 *data, gsize length);
 
+/**
+ * GstMpegtsMetadataFormat:
+ *
+ * metadata_descriptor metadata_format valid values. See ISO/IEC 13818-1:2018(E) Table 2-85.
+ *
+ * Since: 1.24
+ */
+typedef enum
+{
+  /**
+   * GST_MPEGTS_METADATA_FORMAT_TEM:
+   *
+   * ISO/IEC 15938-1 TeM.
+   *
+   * Since: 1.24
+   */
+  GST_MPEGTS_METADATA_FORMAT_TEM = 0x10,
+  /**
+   * GST_MPEGTS_METADATA_FORMAT_BIM:
+   *
+   * ISO/IEC 15938-1 BiM.
+   *
+   * Since: 1.24
+   */
+  GST_MPEGTS_METADATA_FORMAT_BIM = 0x11,
+  /**
+   * GST_MPEGTS_METADATA_FORMAT_APPLICATION_FORMAT:
+   *
+   * Defined by metadata application format.
+   *
+   * Since: 1.24
+   */
+  GST_MPEGTS_METADATA_FORMAT_APPLICATION_FORMAT = 0x3f,
+  /**
+   * GST_MPEGTS_METADATA_FORMAT_IDENTIFIER_FIELD:
+   *
+   * Defined by metadata_format_identifier field.
+   *
+   * Since: 1.24
+   */
+  GST_MPEGTS_METADATA_FORMAT_IDENTIFIER_FIELD = 0xff
+} GstMpegtsMetadataFormat;
+
+/* MPEG-TS Metadata Descriptor (0x26) */
+typedef struct _GstMpegtsMetadataDescriptor GstMpegtsMetadataDescriptor;
+
+/**
+ * GstMpegtsMetadataDescriptor:
+ * @metadata_application_format: specifies the application responsible for defining usage, syntax and semantics
+ * @metadata_format: indicates the format and coding of the metadata
+ * @metadata_format_identifier: format identifier (equivalent to registration descriptor), for example 0x4B4C4641 ('KLVA') to indicate SMPTE 336 KLV.
+ * @metadata_service_id:  metadata service to which this metadata descriptor applies, typically 0x00
+ * @decoder_config_flags: decoder flags, see ISO/IEC 13818-1:2018 Table 2-88.
+ * @dsm_cc_flag: true if stream associated with this descriptor is in an ISO/IEC 13818-6 data or object carousel.
+ *
+ * The metadata descriptor specifies parameters of a metadata service carried in an MPEG-2 Transport Stream (or Program Stream). The descriptor is included in the PMT in the descriptor loop for the elementary stream that carries the
+metadata service. The descriptor specifies the format of the associated metadata, and contains the value of the
+metadata_service_id to identify the metadata service to which the metadata descriptor applies.
+ *
+ * Note that this structure does not include all of the metadata_descriptor items, and will need extension to support DSM-CC and private data.
+ * See ISO/IEC 13818-1:2018 Section 2.6.60 and Section 2.6.61 for more information.
+ *
+ * Since: 1.24
+ */
+struct _GstMpegtsMetadataDescriptor
+{
+  guint16 metadata_application_format;
+  GstMpegtsMetadataFormat metadata_format;
+  guint32 metadata_format_identifier;
+  guint8 metadata_service_id;
+  guint8 decoder_config_flags;
+  gboolean dsm_cc_flag;
+};
+
+/**
+ * GST_TYPE_MPEGTS_METADATA_DESCRIPTOR:
+ *
+ * metadata_descriptor type
+ *
+ * Since: 1.24
+ */
+#define GST_TYPE_MPEGTS_METADATA_DESCRIPTOR (gst_mpegts_metadata_descriptor_get_type())
+
+GST_MPEGTS_API
+GType gst_mpegts_metadata_descriptor_get_type(void);
+
+GST_MPEGTS_API
+GstMpegtsDescriptor *gst_mpegts_descriptor_from_metadata(const GstMpegtsMetadataDescriptor *metadata_descriptor);
+
+GST_MPEGTS_API
+gboolean gst_mpegts_descriptor_parse_metadata(const GstMpegtsDescriptor *descriptor, GstMpegtsMetadataDescriptor **res);
+
+GST_MPEGTS_API
+gboolean gst_mpegts_descriptor_parse_metadata_std(const GstMpegtsDescriptor *descriptor,
+                                                  guint32 *metadata_input_leak_rate,
+                                                  guint32 *metadata_buffer_size,
+                                                  guint32 *metadata_output_leak_rate);
+
+typedef struct _GstMpegtsPESMetadataMeta GstMpegtsPESMetadataMeta;
+
+/**
+ * gst_mpegts_pes_metadata_meta_api_get_type
+ *
+ * Return the #GType associated with #GstMpegtsPESMetadataMeta
+ *
+ * Returns: a #GType
+ *
+ * Since: 1.24
+ */
+GST_MPEGTS_API
+GType gst_mpegts_pes_metadata_meta_api_get_type(void);
+
+/**
+ * GST_MPEGTS_PES_METADATA_META_API_TYPE:
+ *
+ * The #GType associated with #GstMpegtsPESMetadataMeta.
+ *
+ * Since: 1.24
+ */
+#define GST_MPEGTS_PES_METADATA_META_API_TYPE (gst_mpegts_pes_metadata_meta_api_get_type())
+
+/**
+ * GST_MPEGTS_PES_METADATA_META_INFO:
+ *
+ * The #GstMetaInfo associated with #GstMpegtsPESMetadataMeta.
+ *
+ * Since: 1.24
+ */
+#define GST_MPEGTS_PES_METADATA_META_INFO (gst_mpegts_pes_metadata_meta_get_info())
+
+/**
+ * gst_mpegts_pes_metadata_meta_get_info:
+ *
+ * Gets the global #GstMetaInfo describing the #GstMpegtsPESMetadataMeta meta.
+ *
+ * Returns: (transfer none): The #GstMetaInfo
+ *
+ * Since: 1.24
+ */
+GST_MPEGTS_API
+const GstMetaInfo *gst_mpegts_pes_metadata_meta_get_info(void);
+
+/**
+ * GstMpegtsPESMetadataMeta:
+ * @meta: parent #GstMeta
+ * @metadata_service_id: metadata service identifier
+ * @flags: bit flags, see spec for details
+ *
+ * Extra buffer metadata describing the PES Metadata context.
+ * This is based on the Metadata AU cell header in
+ * ISO/IEC 13818-1:2018 Section 2.12.4.
+ *
+ * AU_cell_data_length is not provided, since it matches the length of the buffer
+ *
+ * Since: 1.24
+ */
+struct _GstMpegtsPESMetadataMeta
+{
+  GstMeta meta;
+  guint8 metadata_service_id;
+  guint8 flags;
+};
+
+/**
+ * gst_buffer_add_mpegts_pes_metadata_meta:
+ * @buffer: a #GstBuffer
+ *
+ * Creates and adds a #GstMpegtsPESMetadataMeta to a @buffer.
+ *
+ * Returns: (transfer none): a newly created #GstMpegtsPESMetadataMeta
+ *
+ * Since: 1.24
+ */
+GST_MPEGTS_API
+GstMpegtsPESMetadataMeta *
+gst_buffer_add_mpegts_pes_metadata_meta(GstBuffer *buffer);
+
+
 G_END_DECLS
 
 #endif				/* GST_MPEGTS_DESCRIPTOR_H */
diff --git a/subprojects/gst-plugins-bad/gst-libs/gst/mpegts/meson.build b/subprojects/gst-plugins-bad/gst-libs/gst/mpegts/meson.build
index db808b39d0..56d7099433 100644
--- a/subprojects/gst-plugins-bad/gst-libs/gst/mpegts/meson.build
+++ b/subprojects/gst-plugins-bad/gst-libs/gst/mpegts/meson.build
@@ -6,8 +6,6 @@ mpegts_sources = files(
   'gst-dvb-section.c',
   'gst-atsc-section.c',
   'gst-scte-section.c',
-  'gst-mpegtspesmetadatameta.c',
-  'gst-metadata-descriptor.c'
 )
 
 mpegts_headers = files(
@@ -20,8 +18,6 @@ mpegts_headers = files(
   'gst-atsc-descriptor.h',
   'gst-dvb-descriptor.h',
   'gst-isdb-descriptor.h',
-  'gst-mpegtspesmetadatameta.h',
-  'gst-metadata-descriptor.h',
   'mpegts-prelude.h',
   'mpegts.h',
 )
@@ -47,7 +43,7 @@ gstmpegts = library('gstmpegts-' + api_version,
   soversion : soversion,
   darwin_versions : osxversion,
   install : true,
-  dependencies : [gst_dep],
+  dependencies : [gst_dep, gstbase_dep],
 )
 
 library_def = {'lib': gstmpegts}
diff --git a/subprojects/gst-plugins-bad/gst-libs/gst/mpegts/mpegts.h b/subprojects/gst-plugins-bad/gst-libs/gst/mpegts/mpegts.h
index a540d1e874..80be35bb3b 100644
--- a/subprojects/gst-plugins-bad/gst-libs/gst/mpegts/mpegts.h
+++ b/subprojects/gst-plugins-bad/gst-libs/gst/mpegts/mpegts.h
@@ -40,8 +40,6 @@
 #include <gst/mpegts/gst-scte-section.h>
 #include <gst/mpegts/gstmpegts-enumtypes.h>
 #include <gst/mpegts/gst-hdmv-section.h>
-#include <gst/mpegts/gst-mpegtspesmetadatameta.h>
-#include <gst/mpegts/gst-metadata-descriptor.h>
 
 G_BEGIN_DECLS