webrtcstats: Get the remote-inbound stats from the right RTPSource 10/262810/2
authorOlivier CrĂȘte <olivier.crete@collabora.com>
Fri, 16 Oct 2020 01:23:08 +0000 (21:23 -0400)
committerSangchul Lee <sc11.lee@samsung.com>
Mon, 23 Aug 2021 10:46:53 +0000 (10:46 +0000)
This also means that we need to get the clock-rate from the codec instead
of from the RTPSource, as the remote one doesn't include a clock rate.

Change-Id: Ib7ee7746a26897fb0a6a188f8a4132acbd0a4e60
Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/merge_requests/1766>

ext/webrtc/gstwebrtcstats.c

index 452ec90..a901be2 100644 (file)
@@ -99,6 +99,105 @@ _gst_structure_take_structure (GstStructure * s, const char *fieldname,
 #define FIXED_16_16_TO_DOUBLE(v) ((double) ((v & 0xffff0000) >> 16) + ((v & 0xffff) / 65536.0))
 #define FIXED_32_32_TO_DOUBLE(v) ((double) ((v & G_GUINT64_CONSTANT (0xffffffff00000000)) >> 32) + ((v & G_GUINT64_CONSTANT (0xffffffff)) / 4294967296.0))
 
+/* https://www.w3.org/TR/webrtc-stats/#remoteinboundrtpstats-dict* */
+static gboolean
+_get_stats_from_remote_rtp_source_stats (GstWebRTCBin * webrtc,
+    TransportStream * stream, const GstStructure * source_stats,
+    guint ssrc, guint clock_rate, const gchar * codec_id,
+    const gchar * transport_id, GstStructure * s)
+{
+  gboolean have_rb = FALSE, internal = FALSE;
+  int lost;
+  GstStructure *r_in;
+  gchar *r_in_id, *out_id;
+  guint32 rtt;
+  guint fraction_lost, jitter;
+  double ts;
+
+  gst_structure_get_double (s, "timestamp", &ts);
+  gst_structure_get (source_stats, "internal", G_TYPE_BOOLEAN, &internal,
+      "have-rb", G_TYPE_BOOLEAN, &have_rb, NULL);
+
+  /* This isn't what we're looking for */
+  if (internal == TRUE || have_rb == FALSE)
+    return FALSE;
+
+  r_in_id = g_strdup_printf ("rtp-remote-inbound-stream-stats_%u", ssrc);
+  out_id = g_strdup_printf ("rtp-outbound-stream-stats_%u", ssrc);
+
+  r_in = gst_structure_new_empty (r_in_id);
+  _set_base_stats (r_in, GST_WEBRTC_STATS_REMOTE_INBOUND_RTP, ts, r_in_id);
+
+  /* RTCRtpStreamStats */
+  gst_structure_set (r_in, "local-id", G_TYPE_STRING, out_id, NULL);
+  gst_structure_set (r_in, "ssrc", G_TYPE_UINT, ssrc, NULL);
+  gst_structure_set (r_in, "codec-id", G_TYPE_STRING, codec_id, NULL);
+  gst_structure_set (r_in, "transport-id", G_TYPE_STRING, transport_id, NULL);
+  /* To be added: kind */
+
+  /* RTCReceivedRtpStreamStats */
+
+  if (gst_structure_get_int (source_stats, "rb-packetslost", &lost))
+    gst_structure_set (r_in, "packets-lost", G_TYPE_INT, lost, NULL);
+
+  if (clock_rate && gst_structure_get_uint (source_stats, "rb-jitter", &jitter))
+    gst_structure_set (r_in, "jitter", G_TYPE_DOUBLE,
+        CLOCK_RATE_VALUE_TO_SECONDS (jitter, clock_rate), NULL);
+
+  /* RTCReceivedRtpStreamStats:
+
+     unsigned long long  packetsReceived;
+     unsigned long      packetsDiscarded;
+     unsigned long      packetsRepaired;
+     unsigned long      burstPacketsLost;
+     unsigned long      burstPacketsDiscarded;
+     unsigned long      burstLossCount;
+     unsigned long      burstDiscardCount;
+     double             burstLossRate;
+     double             burstDiscardRate;
+     double             gapLossRate;
+     double             gapDiscardRate;
+
+     Can't be implemented frame re-assembly happens after rtpbin:
+
+     unsigned long        framesDropped;
+     unsigned long        partialFramesLost;
+     unsigned long        fullFramesLost;
+   */
+
+  /* RTCRemoteInboundRTPStreamStats */
+
+  if (gst_structure_get_uint (source_stats, "rb-fractionlost", &fraction_lost))
+    gst_structure_set (r_in, "fraction-lost", G_TYPE_DOUBLE,
+        (double) fraction_lost / 256.0, NULL);
+
+  if (gst_structure_get_uint (source_stats, "rb-round-trip", &rtt)) {
+    /* 16.16 fixed point to double */
+    double val = FIXED_16_16_TO_DOUBLE (rtt);
+    gst_structure_set (r_in, "round-trip-time", G_TYPE_DOUBLE, val, NULL);
+  }
+
+  /* RTCRemoteInboundRTPStreamStats:
+
+     To be added:
+
+     DOMString            localId;
+     double               totalRoundTripTime;
+     unsigned long long   reportsReceived;
+     unsigned long long   roundTripTimeMeasurements;
+   */
+
+  gst_structure_set (r_in, "gst-rtpsource-stats", GST_TYPE_STRUCTURE,
+      source_stats, NULL);
+
+  _gst_structure_take_structure (s, r_in_id, &r_in);
+
+  g_free (r_in_id);
+  g_free (out_id);
+
+  return TRUE;
+}
+
 /* https://www.w3.org/TR/webrtc-stats/#inboundrtpstats-dict*
    https://www.w3.org/TR/webrtc-stats/#outboundrtpstats-dict* */
 static void
@@ -107,7 +206,7 @@ _get_stats_from_rtp_source_stats (GstWebRTCBin * webrtc,
     const gchar * codec_id, const gchar * transport_id, GstStructure * s)
 {
   guint ssrc, fir, pli, nack, jitter;
-  int lost, clock_rate;
+  int clock_rate;
   guint64 packets, bytes;
   gboolean internal;
   double ts;
@@ -117,71 +216,10 @@ _get_stats_from_rtp_source_stats (GstWebRTCBin * webrtc,
       G_TYPE_INT, &clock_rate, "internal", G_TYPE_BOOLEAN, &internal, NULL);
 
   if (internal) {
-    GstStructure *r_in, *out;
+    GstStructure *out;
     gchar *out_id, *r_in_id;
-    gboolean have_rb = FALSE;
 
     out_id = g_strdup_printf ("rtp-outbound-stream-stats_%u", ssrc);
-    r_in_id = g_strdup_printf ("rtp-remote-inbound-stream-stats_%u", ssrc);
-
-    gst_structure_get (source_stats, "have-rb", G_TYPE_BOOLEAN, &have_rb, NULL);
-
-    r_in = gst_structure_new_empty (r_in_id);
-    _set_base_stats (r_in, GST_WEBRTC_STATS_REMOTE_INBOUND_RTP, ts, r_in_id);
-
-    /* RTCRtpStreamStats */
-    gst_structure_set (r_in, "local-id", G_TYPE_STRING, out_id, NULL);
-    gst_structure_set (r_in, "ssrc", G_TYPE_UINT, ssrc, NULL);
-    gst_structure_set (r_in, "codec-id", G_TYPE_STRING, codec_id, NULL);
-    gst_structure_set (r_in, "transport-id", G_TYPE_STRING, transport_id, NULL);
-    /* To be added: kind */
-
-    /* RTCReceivedRtpStreamStats:
-
-       To be added:
-
-       unsigned long long   packetsReceived;
-       long long            packetsLost;
-       double               jitter;
-       unsigned long      packetsDiscarded;
-       unsigned long      packetsRepaired;
-       unsigned long      burstPacketsLost;
-       unsigned long      burstPacketsDiscarded;
-       unsigned long      burstLossCount;
-       unsigned long      burstDiscardCount;
-       double             burstLossRate;
-       double             burstDiscardRate;
-       double             gapLossRate;
-       double             gapDiscardRate;
-
-       Can't be implemented frame re-assembly happens after rtpbin:
-
-       unsigned long        framesDropped;
-       unsigned long        partialFramesLost;
-       unsigned long        fullFramesLost;
-     */
-
-
-    /* RTCRemoteInboundRTPStreamStats */
-
-    if (have_rb) {
-      guint32 rtt;
-      if (gst_structure_get_uint (source_stats, "rb-round-trip", &rtt)) {
-        /* 16.16 fixed point to double */
-        double val = FIXED_16_16_TO_DOUBLE (rtt);
-        gst_structure_set (r_in, "round-trip-time", G_TYPE_DOUBLE, val, NULL);
-      }
-    }
-
-    /* RTCRemoteInboundRTPStreamStats:
-
-       To be added:
-
-       DOMString            localId;
-       double               totalRoundTripTime;
-       unsigned long long   reportsReceived;
-       unsigned long long   roundTripTimeMeasurements;
-     */
 
     out = gst_structure_new_empty (out_id);
     _set_base_stats (out, GST_WEBRTC_STATS_OUTBOUND_RTP, ts, out_id);
@@ -209,8 +247,10 @@ _get_stats_from_rtp_source_stats (GstWebRTCBin * webrtc,
       gst_structure_set (out, "nack-count", G_TYPE_UINT, nack, NULL);
     /* XXX: mediaType, trackId, sliCount, qpSum */
 
-    gst_structure_set (out, "remote-id", G_TYPE_STRING, r_in_id, NULL);
-
+    r_in_id = g_strdup_printf ("rtp-remote-inbound-stream-stats_%u", ssrc);
+    if (gst_structure_has_field (s, r_in_id))
+      gst_structure_set (out, "remote-id", G_TYPE_STRING, r_in_id, NULL);
+    g_free (r_in_id);
 
     /*  RTCOutboundRTPStreamStats:
 
@@ -264,12 +304,9 @@ _get_stats_from_rtp_source_stats (GstWebRTCBin * webrtc,
     gst_structure_set (out, "gst-rtpsource-stats", GST_TYPE_STRUCTURE,
         source_stats, NULL);
 
-
     _gst_structure_take_structure (s, out_id, &out);
-    _gst_structure_take_structure (s, r_in_id, &r_in);
 
     g_free (out_id);
-    g_free (r_in_id);
   } else {
     GstStructure *in, *r_out;
     gchar *r_out_id, *in_id;
@@ -427,10 +464,13 @@ _get_stats_from_rtp_source_stats (GstWebRTCBin * webrtc,
     /* RTCSentRtpStreamStats */
 
     if (have_sr) {
-      if (gst_structure_get_uint64 (source_stats, "sr-octet-count", &bytes))
-        gst_structure_set (r_out, "bytes-sent", G_TYPE_UINT64, bytes, NULL);
-      if (gst_structure_get_uint64 (source_stats, "sr-packet-count", &packets))
-        gst_structure_set (r_out, "packets-sent", G_TYPE_UINT64, packets, NULL);
+      guint sr_bytes, sr_packets;
+
+      if (gst_structure_get_uint (source_stats, "sr-octet-count", &sr_bytes))
+        gst_structure_set (r_out, "bytes-sent", G_TYPE_UINT, sr_bytes, NULL);
+      if (gst_structure_get_uint (source_stats, "sr-packet-count", &sr_packets))
+        gst_structure_set (r_out, "packets-sent", G_TYPE_UINT, sr_packets,
+            NULL);
     }
 
     /* RTCSentRtpStreamStats:
@@ -642,7 +682,7 @@ _get_stats_from_dtls_transport (GstWebRTCBin * webrtc,
 static void
 _get_stats_from_transport_channel (GstWebRTCBin * webrtc,
     TransportStream * stream, const gchar * codec_id, guint ssrc,
-    GstStructure * s)
+    guint clock_rate, GstStructure * s)
 {
   GstWebRTCDTLSTransport *transport;
   GObject *rtp_session;
@@ -682,11 +722,14 @@ _get_stats_from_transport_channel (GstWebRTCBin * webrtc,
 
     /* skip foreign sources */
     gst_structure_get (stats, "ssrc", G_TYPE_UINT, &stats_ssrc, NULL);
-    if (ssrc && stats_ssrc && ssrc != stats_ssrc)
-      continue;
-
-    _get_stats_from_rtp_source_stats (webrtc, stream, stats, codec_id,
-        transport_id, s);
+    if (gst_structure_get_uint (stats, "ssrc", &stats_ssrc) &&
+        ssrc == stats_ssrc)
+      _get_stats_from_rtp_source_stats (webrtc, stream, stats, codec_id,
+          transport_id, s);
+    else if (gst_structure_get_uint (stats, "rb-ssrc", &stats_ssrc) &&
+        ssrc == stats_ssrc)
+      _get_stats_from_remote_rtp_source_stats (webrtc, stream, stats, ssrc,
+          clock_rate, codec_id, transport_id, s);
   }
 
   g_object_unref (rtp_session);
@@ -698,13 +741,14 @@ _get_stats_from_transport_channel (GstWebRTCBin * webrtc,
 /* https://www.w3.org/TR/webrtc-stats/#codec-dict* */
 static void
 _get_codec_stats_from_pad (GstWebRTCBin * webrtc, GstPad * pad,
-    GstStructure * s, gchar ** out_id, guint * out_ssrc)
+    GstStructure * s, gchar ** out_id, guint * out_ssrc, guint * out_clock_rate)
 {
   GstStructure *stats;
   GstCaps *caps;
   gchar *id;
   double ts;
   guint ssrc = 0;
+  gint clock_rate = 0;
 
   gst_structure_get_double (s, "timestamp", &ts);
 
@@ -715,7 +759,7 @@ _get_codec_stats_from_pad (GstWebRTCBin * webrtc, GstPad * pad,
   caps = gst_pad_get_current_caps (pad);
   if (caps && gst_caps_is_fixed (caps)) {
     GstStructure *caps_s = gst_caps_get_structure (caps, 0);
-    gint pt, clock_rate;
+    gint pt;
 
     if (gst_structure_get_int (caps_s, "payload", &pt))
       gst_structure_set (stats, "payload-type", G_TYPE_UINT, pt, NULL);
@@ -742,6 +786,9 @@ _get_codec_stats_from_pad (GstWebRTCBin * webrtc, GstPad * pad,
 
   if (out_ssrc)
     *out_ssrc = ssrc;
+
+  if (out_clock_rate)
+    *out_clock_rate = clock_rate;
 }
 
 static gboolean
@@ -750,9 +797,9 @@ _get_stats_from_pad (GstWebRTCBin * webrtc, GstPad * pad, GstStructure * s)
   GstWebRTCBinPad *wpad = GST_WEBRTC_BIN_PAD (pad);
   TransportStream *stream;
   gchar *codec_id;
-  guint ssrc;
+  guint ssrc, clock_rate;
 
-  _get_codec_stats_from_pad (webrtc, pad, s, &codec_id, &ssrc);
+  _get_codec_stats_from_pad (webrtc, pad, s, &codec_id, &ssrc, &clock_rate);
 
   if (!wpad->trans)
     goto out;
@@ -761,7 +808,8 @@ _get_stats_from_pad (GstWebRTCBin * webrtc, GstPad * pad, GstStructure * s)
   if (!stream)
     goto out;
 
-  _get_stats_from_transport_channel (webrtc, stream, codec_id, ssrc, s);
+  _get_stats_from_transport_channel (webrtc, stream, codec_id, ssrc,
+      clock_rate, s);
 
 out:
   g_free (codec_id);