rtptwcc: move TWCC-logic over to the TWCC-manager
authorHavard Graff <havard.graff@gmail.com>
Tue, 23 Feb 2021 08:44:05 +0000 (09:44 +0100)
committerGStreamer Marge Bot <gitlab-merge-bot@gstreamer-foundation.org>
Wed, 25 Aug 2021 08:36:06 +0000 (08:36 +0000)
Prevent cluttering up the rtpsession, and keeping things localized.

Also write TWCC-seqnums for *all* streams in the session if configured by
caps.

A while back WebRTC was not doing TWCC for audio, basically breaking the
whole idea of a "transport-wide seqnuencenumber" applying for all bundled
streams. However, they have since fixed this, and now it no longers
makes sense to be able to single out certain payloadtypes for
use with TWCC, rather just including them all.

This also makes using RTX, RED, FEC etc much simpler, as it will apply
to them all as they enter the rtpsession.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-good/-/merge_requests/927>

gst/rtpmanager/rtpsession.c
gst/rtpmanager/rtptwcc.c
gst/rtpmanager/rtptwcc.h

index b8429a1..9bd537c 100644 (file)
@@ -117,9 +117,6 @@ enum
   else                                  \
    (avg) = ((val) + (15 * (avg))) >> 4;
 
-
-#define TWCC_EXTMAP_STR "http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01"
-
 /* GObject vmethods */
 static void rtp_session_finalize (GObject * object);
 static void rtp_session_set_property (GObject * object, guint prop_id,
@@ -2196,22 +2193,6 @@ clean_packet_info (RTPPacketInfo * pinfo)
     g_bytes_unref (pinfo->header_ext);
 }
 
-static gint32
-packet_info_get_twcc_seqnum (RTPPacketInfo * pinfo, guint8 ext_id)
-{
-  gint32 val = -1;
-  gpointer data;
-  guint size;
-
-  if (pinfo->header_ext &&
-      gst_rtp_buffer_get_extension_onebyte_header_from_bytes (pinfo->header_ext,
-          pinfo->header_ext_bit_pattern, ext_id, 0, &data, &size)) {
-    if (size == 2)
-      val = GST_READ_UINT16_BE (data);
-  }
-  return val;
-}
-
 static gboolean
 source_update_active (RTPSession * sess, RTPSource * source,
     gboolean prevactive)
@@ -2237,16 +2218,7 @@ source_update_active (RTPSession * sess, RTPSource * source,
 static void
 process_twcc_packet (RTPSession * sess, RTPPacketInfo * pinfo)
 {
-  gint32 twcc_seqnum;
-
-  if (sess->twcc_recv_ext_id == 0)
-    return;
-
-  twcc_seqnum = packet_info_get_twcc_seqnum (pinfo, sess->twcc_recv_ext_id);
-  if (twcc_seqnum == -1)
-    return;
-
-  if (rtp_twcc_manager_recv_packet (sess->twcc, twcc_seqnum, pinfo)) {
+  if (rtp_twcc_manager_recv_packet (sess->twcc, pinfo)) {
     RTP_SESSION_UNLOCK (sess);
 
     /* TODO: find a better rational for this number, and possibly tune it based
@@ -3151,29 +3123,6 @@ invalid_packet:
   }
 }
 
-static guint8
-_get_extmap_id_for_attribute (const GstStructure * s, const gchar * ext_name)
-{
-  guint i;
-  guint8 extmap_id = 0;
-  guint n_fields = gst_structure_n_fields (s);
-
-  for (i = 0; i < n_fields; i++) {
-    const gchar *field_name = gst_structure_nth_field_name (s, i);
-    if (g_str_has_prefix (field_name, "extmap-")) {
-      const gchar *str = gst_structure_get_string (s, field_name);
-      if (str && g_strcmp0 (str, ext_name) == 0) {
-        gint64 id = g_ascii_strtoll (field_name + 7, NULL, 10);
-        if (id > 0 && id < 15) {
-          extmap_id = id;
-          break;
-        }
-      }
-    }
-  }
-  return extmap_id;
-}
-
 /**
  * rtp_session_update_send_caps:
  * @sess: an #RTPSession
@@ -3229,29 +3178,9 @@ rtp_session_update_send_caps (RTPSession * sess, GstCaps * caps)
     sess->internal_ssrc_from_caps_or_property = FALSE;
   }
 
-  sess->twcc_send_ext_id = _get_extmap_id_for_attribute (s, TWCC_EXTMAP_STR);
-  if (sess->twcc_send_ext_id > 0) {
-    GST_INFO ("TWCC enabled for send using extension id: %u",
-        sess->twcc_send_ext_id);
-  }
-}
-
-static void
-send_twcc_packet (RTPSession * sess, RTPPacketInfo * pinfo)
-{
-  gint32 twcc_seqnum;
-
-  if (sess->twcc_send_ext_id == 0)
-    return;
-
-  twcc_seqnum = packet_info_get_twcc_seqnum (pinfo, sess->twcc_send_ext_id);
-  if (twcc_seqnum == -1)
-    return;
-
-  rtp_twcc_manager_send_packet (sess->twcc, twcc_seqnum, pinfo);
+  rtp_twcc_manager_parse_send_ext_id (sess->twcc, s);
 }
 
-
 /**
  * rtp_session_send_rtp:
  * @sess: an #RTPSession
@@ -3286,7 +3215,7 @@ rtp_session_send_rtp (RTPSession * sess, gpointer data, gboolean is_list,
           current_time, running_time, -1))
     goto invalid_packet;
 
-  send_twcc_packet (sess, &pinfo);
+  rtp_twcc_manager_send_packet (sess->twcc, &pinfo);
 
   source = obtain_internal_source (sess, pinfo.ssrc, &created, current_time);
   if (created)
@@ -4947,10 +4876,5 @@ void
 rtp_session_update_recv_caps_structure (RTPSession * sess,
     const GstStructure * s)
 {
-  guint8 ext_id = _get_extmap_id_for_attribute (s, TWCC_EXTMAP_STR);
-  if (ext_id > 0) {
-    sess->twcc_recv_ext_id = ext_id;
-    GST_INFO ("TWCC enabled for recv using extension id: %u",
-        sess->twcc_recv_ext_id);
-  }
+  rtp_twcc_manager_parse_recv_ext_id (sess->twcc, s);
 }
index f529f37..b5fa79b 100644 (file)
@@ -25,6 +25,8 @@
 GST_DEBUG_CATEGORY_EXTERN (rtp_session_debug);
 #define GST_CAT_DEFAULT rtp_session_debug
 
+#define TWCC_EXTMAP_STR "http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01"
+
 #define REF_TIME_UNIT (64 * GST_MSECOND)
 #define DELTA_UNIT (250 * GST_USECOND)
 #define MAX_TS_DELTA (0xff * DELTA_UNIT)
@@ -71,6 +73,10 @@ struct _RTPTWCCManager
 {
   GObject object;
 
+  guint8 send_ext_id;
+  guint8 recv_ext_id;
+  guint16 send_seqnum;
+
   guint mtu;
   guint max_packets_per_rtcp;
   GArray *recv_packets;
@@ -155,6 +161,51 @@ recv_packet_init (RecvPacket * packet, guint16 seqnum, RTPPacketInfo * pinfo)
   packet->ts = pinfo->running_time;
 }
 
+static guint8
+_get_extmap_id_for_attribute (const GstStructure * s, const gchar * ext_name)
+{
+  guint i;
+  guint8 extmap_id = 0;
+  guint n_fields = gst_structure_n_fields (s);
+
+  for (i = 0; i < n_fields; i++) {
+    const gchar *field_name = gst_structure_nth_field_name (s, i);
+    if (g_str_has_prefix (field_name, "extmap-")) {
+      const gchar *str = gst_structure_get_string (s, field_name);
+      if (str && g_strcmp0 (str, ext_name) == 0) {
+        gint64 id = g_ascii_strtoll (field_name + 7, NULL, 10);
+        if (id > 0 && id < 15) {
+          extmap_id = id;
+          break;
+        }
+      }
+    }
+  }
+  return extmap_id;
+}
+
+void
+rtp_twcc_manager_parse_recv_ext_id (RTPTWCCManager * twcc,
+    const GstStructure * s)
+{
+  twcc->recv_ext_id = _get_extmap_id_for_attribute (s, TWCC_EXTMAP_STR);
+  if (twcc->recv_ext_id > 0) {
+    GST_INFO ("TWCC enabled for recv using extension id: %u",
+        twcc->recv_ext_id);
+  }
+}
+
+void
+rtp_twcc_manager_parse_send_ext_id (RTPTWCCManager * twcc,
+    const GstStructure * s)
+{
+  twcc->send_ext_id = _get_extmap_id_for_attribute (s, TWCC_EXTMAP_STR);
+  if (twcc->send_ext_id > 0) {
+    GST_INFO ("TWCC enabled for send using extension id: %u",
+        twcc->send_ext_id);
+  }
+}
+
 void
 rtp_twcc_manager_set_mtu (RTPTWCCManager * twcc, guint mtu)
 {
@@ -180,6 +231,63 @@ rtp_twcc_manager_get_feedback_interval (RTPTWCCManager * twcc)
   return twcc->feedback_interval;
 }
 
+static gboolean
+_get_twcc_seqnum_data (RTPPacketInfo * pinfo, guint8 ext_id, gpointer * data)
+{
+  gboolean ret = FALSE;
+  guint size;
+
+  if (pinfo->header_ext &&
+      gst_rtp_buffer_get_extension_onebyte_header_from_bytes (pinfo->header_ext,
+          pinfo->header_ext_bit_pattern, ext_id, 0, data, &size)) {
+    if (size == 2)
+      ret = TRUE;
+  }
+  return ret;
+}
+
+static void
+_set_twcc_seqnum_data (GstBuffer * buf, guint8 ext_id, guint16 seqnum)
+{
+  GstRTPBuffer rtp = GST_RTP_BUFFER_INIT;
+  gpointer data;
+
+  if (gst_rtp_buffer_map (buf, GST_MAP_READWRITE, &rtp)) {
+    if (gst_rtp_buffer_get_extension_onebyte_header (&rtp,
+            ext_id, 0, &data, NULL)) {
+      GST_WRITE_UINT16_BE (data, seqnum);
+    }
+    gst_rtp_buffer_unmap (&rtp);
+  }
+}
+
+static guint16
+rtp_twcc_manager_set_send_twcc_seqnum (RTPTWCCManager * twcc,
+    RTPPacketInfo * pinfo)
+{
+  guint16 seqnum = twcc->send_seqnum++;
+  pinfo->data = gst_buffer_make_writable (pinfo->data);
+  _set_twcc_seqnum_data (pinfo->data, twcc->send_ext_id, seqnum);
+  return seqnum;
+}
+
+static gint32
+rtp_twcc_manager_get_recv_twcc_seqnum (RTPTWCCManager * twcc,
+    RTPPacketInfo * pinfo)
+{
+  gint32 val = -1;
+  gpointer data;
+
+  if (twcc->recv_ext_id == 0)
+    return val;
+
+  if (_get_twcc_seqnum_data (pinfo, twcc->recv_ext_id, &data)) {
+    val = GST_READ_UINT16_BE (data);
+  }
+
+  return val;
+}
+
 static gint
 _twcc_seqnum_sort (gconstpointer a, gconstpointer b)
 {
@@ -621,13 +729,17 @@ _many_packets_some_lost (RTPTWCCManager * twcc, guint16 seqnum)
 }
 
 gboolean
-rtp_twcc_manager_recv_packet (RTPTWCCManager * twcc,
-    guint16 seqnum, RTPPacketInfo * pinfo)
+rtp_twcc_manager_recv_packet (RTPTWCCManager * twcc, RTPPacketInfo * pinfo)
 {
   gboolean send_feedback = FALSE;
   RecvPacket packet;
+  gint32 seqnum;
   gint diff;
 
+  seqnum = rtp_twcc_manager_get_recv_twcc_seqnum (twcc, pinfo);
+  if (seqnum == -1)
+    return FALSE;
+
   /* if this packet would exceed the capacity of our MTU, we create a feedback
      with the current packets, and start over with this one */
   if (_exceeds_max_packets (twcc, seqnum)) {
@@ -666,8 +778,10 @@ rtp_twcc_manager_recv_packet (RTPTWCCManager * twcc,
   recv_packet_init (&packet, seqnum, pinfo);
   g_array_append_val (twcc->recv_packets, packet);
   twcc->last_seqnum = seqnum;
-  GST_LOG ("Receive: twcc-seqnum: %u, marker: %d, ts: %" GST_TIME_FORMAT,
-      seqnum, pinfo->marker, GST_TIME_ARGS (pinfo->running_time));
+
+  GST_LOG ("Receive: twcc-seqnum: %u, pt: %u, marker: %d, ts: %"
+      GST_TIME_FORMAT, seqnum, pinfo->pt, pinfo->marker,
+      GST_TIME_ARGS (pinfo->running_time));
 
   if (!pinfo->marker)
     twcc->packet_count_no_marker++;
@@ -732,15 +846,22 @@ sent_packet_init (SentPacket * packet, guint16 seqnum, RTPPacketInfo * pinfo)
 }
 
 void
-rtp_twcc_manager_send_packet (RTPTWCCManager * twcc,
-    guint16 seqnum, RTPPacketInfo * pinfo)
+rtp_twcc_manager_send_packet (RTPTWCCManager * twcc, RTPPacketInfo * pinfo)
 {
   SentPacket packet;
+  guint16 seqnum;
+
+  if (twcc->send_ext_id == 0)
+    return;
+
+  seqnum = rtp_twcc_manager_set_send_twcc_seqnum (twcc, pinfo);
+
   sent_packet_init (&packet, seqnum, pinfo);
   g_array_append_val (twcc->sent_packets, packet);
 
-  GST_LOG ("Send: twcc-seqnum: %u, marker: %d, ts: %" GST_TIME_FORMAT,
-      seqnum, pinfo->marker, GST_TIME_ARGS (pinfo->running_time));
+
+  GST_LOG ("Send: twcc-seqnum: %u, pt: %u, marker: %d, ts: %" GST_TIME_FORMAT,
+      seqnum, pinfo->pt, pinfo->marker, GST_TIME_ARGS (pinfo->running_time));
 }
 
 static void
index bb14dba..79b5687 100644 (file)
@@ -53,16 +53,20 @@ struct _RTPTWCCPacket
 
 RTPTWCCManager * rtp_twcc_manager_new (guint mtu);
 
+void rtp_twcc_manager_parse_recv_ext_id (RTPTWCCManager * twcc,
+    const GstStructure * s);
+void rtp_twcc_manager_parse_send_ext_id (RTPTWCCManager * twcc,
+    const GstStructure * s);
+
 void rtp_twcc_manager_set_mtu (RTPTWCCManager * twcc, guint mtu);
 void rtp_twcc_manager_set_feedback_interval (RTPTWCCManager * twcc,
     GstClockTime feedback_interval);
 GstClockTime rtp_twcc_manager_get_feedback_interval (RTPTWCCManager * twcc);
 
 gboolean rtp_twcc_manager_recv_packet (RTPTWCCManager * twcc,
-    guint16 seqnum, RTPPacketInfo * pinfo);
-
+    RTPPacketInfo * pinfo);
 void rtp_twcc_manager_send_packet (RTPTWCCManager * twcc,
-    guint16 seqnum, RTPPacketInfo * pinfo);
+    RTPPacketInfo * pinfo);
 
 GstBuffer * rtp_twcc_manager_get_feedback (RTPTWCCManager * twcc,
     guint32 sender_ssrc);