rtpbasedepayload: Drop redundant reference timestamp buffer meta in RTP depayloaders
authorMatt Crane <matt@standard.ai>
Wed, 16 Nov 2022 16:47:54 +0000 (11:47 -0500)
committerGStreamer Marge Bot <gitlab-merge-bot@gstreamer-foundation.org>
Sat, 19 Nov 2022 07:57:44 +0000 (07:57 +0000)
Currently, when rtspsrc property add-reference-timestamp-metadata=true,
a downstream rtph264depay element will attach multiple copies of the
same GstReferenceTimestampMeta to the depayloaded media buffers. This
can have signficant performance impacts further downstream in a pipeline
like the following:

    rtspsrc add-reference-timestamp-metadata=true ! rtph264depay ! h264parse ! ... ! rtph264pay ! ...

For example, if there are 10 packet buffers for a frame of RTP H.264
video, each of those packet buffers will contain the same reference
timestamp meta. The rtph264depay element will then attach all 10
metadata to the depayloaded frame. And then later when we payload the
frame buffer again for proxying, we now have 10 more buffers each with
10 instance of the same metadata. Allocating/deallocating 100+ instances
of metadata @ 30fps for multiple streams has a pretty large performance
impact.

Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/1578

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3431>

subprojects/gst-plugins-base/gst-libs/gst/rtp/gstrtpbasedepayload.c

index 1520581..0fd2d82 100644 (file)
@@ -36,6 +36,9 @@
 GST_DEBUG_CATEGORY_STATIC (rtpbasedepayload_debug);
 #define GST_CAT_DEFAULT (rtpbasedepayload_debug)
 
+static GstStaticCaps ntp_reference_timestamp_caps =
+GST_STATIC_CAPS ("timestamp/x-ntp");
+
 struct _GstRTPBaseDepayloadPrivate
 {
   GstClockTime npt_start;
@@ -50,6 +53,8 @@ struct _GstRTPBaseDepayloadPrivate
   GstClockTime dts;
   GstClockTime duration;
 
+  GstClockTime ref_ts;
+
   guint32 last_ssrc;
   guint32 last_seqnum;
   guint32 last_rtptime;
@@ -395,6 +400,7 @@ gst_rtp_base_depayload_init (GstRTPBaseDepayload * filter,
   priv->dts = -1;
   priv->pts = -1;
   priv->duration = -1;
+  priv->ref_ts = -1;
   priv->source_info = DEFAULT_SOURCE_INFO;
   priv->max_reorder = DEFAULT_MAX_REORDER;
   priv->auto_hdr_ext = DEFAULT_AUTO_HEADER_EXTENSION;
@@ -679,6 +685,8 @@ gst_rtp_base_depayload_handle_buffer (GstRTPBaseDepayload * filter,
   gboolean discont, buf_discont;
   gint gap;
   GstRTPBuffer rtp = { NULL };
+  GstReferenceTimestampMeta *meta;
+  GstCaps *ref_caps;
 
   priv = filter->priv;
   priv->process_flow_ret = GST_FLOW_OK;
@@ -690,6 +698,21 @@ gst_rtp_base_depayload_handle_buffer (GstRTPBaseDepayload * filter,
   if (G_UNLIKELY (!priv->negotiated))
     goto not_negotiated;
 
+  /* Check for duplicate reference timestamp metadata */
+  ref_caps = gst_static_caps_get (&ntp_reference_timestamp_caps);
+  meta = gst_buffer_get_reference_timestamp_meta (in, ref_caps);
+  gst_caps_unref (ref_caps);
+  if (meta) {
+    guint64 ref_ts = meta->timestamp;
+    if (ref_ts == priv->ref_ts) {
+      /* Drop the redundant/duplicate reference timstamp metadata */
+      in = gst_buffer_make_writable (in);
+      gst_buffer_remove_meta (in, GST_META_CAST (meta));
+    } else {
+      priv->ref_ts = ref_ts;
+    }
+  }
+
   if (G_UNLIKELY (!gst_rtp_buffer_map (in, GST_MAP_READ, &rtp)))
     goto invalid_buffer;
 
@@ -923,6 +946,7 @@ gst_rtp_base_depayload_handle_event (GstRTPBaseDepayload * filter,
 
       filter->need_newsegment = !filter->priv->onvif_mode;
       filter->priv->next_seqnum = -1;
+      filter->priv->ref_ts = -1;
       gst_event_replace (&filter->priv->segment_event, NULL);
       break;
     case GST_EVENT_CAPS:
@@ -1542,6 +1566,7 @@ gst_rtp_base_depayload_change_state (GstElement * element,
       priv->play_speed = 1.0;
       priv->play_scale = 1.0;
       priv->clock_base = -1;
+      priv->ref_ts = -1;
       priv->onvif_mode = FALSE;
       priv->next_seqnum = -1;
       priv->negotiated = FALSE;