webrtc/stats: redo considering internal sources
authorMatthew Waters <matthew@centricular.com>
Mon, 12 Aug 2019 09:42:12 +0000 (19:42 +1000)
committerMatthew Waters <matthew@centricular.com>
Thu, 12 Sep 2019 01:06:41 +0000 (01:06 +0000)
Internal sources seem to be rtp streams we are sending whereas
non-internal sources are the rtp streams we are receiving. Redo the
statistics with that in mind.

ext/webrtc/gstwebrtcstats.c

index faa83b7fde80ddb2a826cc2067e74e9f8af1e052..7ecf9b9aafc81f74862430ae07410fc05e7039d3 100644 (file)
@@ -82,6 +82,8 @@ _get_peer_connection_stats (GstWebRTCBin * webrtc)
 }
 
 #define CLOCK_RATE_VALUE_TO_SECONDS(v,r) ((double) v / (double) clock_rate)
+#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/#inboundrtpstats-dict*
    https://www.w3.org/TR/webrtc-stats/#outboundrtpstats-dict* */
@@ -90,52 +92,43 @@ _get_stats_from_rtp_source_stats (GstWebRTCBin * webrtc,
     const GstStructure * source_stats, const gchar * codec_id,
     const gchar * transport_id, GstStructure * s)
 {
-  GstStructure *in, *out, *r_in, *r_out;
-  gchar *in_id, *out_id, *r_in_id, *r_out_id;
   guint ssrc, fir, pli, nack, jitter;
   int lost, clock_rate;
   guint64 packets, bytes;
-  gboolean have_rb = FALSE, sent_rb = FALSE;
+  gboolean internal;
   double ts;
 
   gst_structure_get_double (s, "timestamp", &ts);
-  gst_structure_get_uint (source_stats, "ssrc", &ssrc);
-  gst_structure_get (source_stats, "have-rb", G_TYPE_BOOLEAN, &have_rb,
-      "sent_rb", G_TYPE_BOOLEAN, &sent_rb, "clock-rate", G_TYPE_INT,
-      &clock_rate, NULL);
-
-  in_id = g_strdup_printf ("rtp-inbound-stream-stats_%u", ssrc);
-  out_id = g_strdup_printf ("rtp-outbound-stream-stats_%u", ssrc);
-  r_in_id = g_strdup_printf ("rtp-remote-inbound-stream-stats_%u", ssrc);
-  r_out_id = g_strdup_printf ("rtp-remote-outbound-stream-stats_%u", ssrc);
-
-  in = gst_structure_new_empty (in_id);
-  _set_base_stats (in, GST_WEBRTC_STATS_INBOUND_RTP, ts, in_id);
-
-  /* RTCStreamStats */
-  gst_structure_set (in, "ssrc", G_TYPE_UINT, ssrc, NULL);
-  gst_structure_set (in, "codec-id", G_TYPE_STRING, codec_id, NULL);
-  gst_structure_set (in, "transport-id", G_TYPE_STRING, transport_id, NULL);
-  if (gst_structure_get_uint (source_stats, "recv-fir-count", &fir))
-    gst_structure_set (in, "fir-count", G_TYPE_UINT, fir, NULL);
-  if (gst_structure_get_uint (source_stats, "recv-pli-count", &pli))
-    gst_structure_set (in, "pli-count", G_TYPE_UINT, pli, NULL);
-  if (gst_structure_get_uint (source_stats, "recv-nack-count", &nack))
-    gst_structure_set (in, "nack-count", G_TYPE_UINT, nack, NULL);
-  /* XXX: mediaType, trackId, sliCount, qpSum */
-
-  /* RTCReceivedRTPStreamStats */
-  if (gst_structure_get_uint64 (source_stats, "packets-received", &packets))
-    gst_structure_set (in, "packets-received", G_TYPE_UINT64, packets, NULL);
-  if (gst_structure_get_uint64 (source_stats, "octets-received", &bytes))
-    gst_structure_set (in, "bytes-received", G_TYPE_UINT64, bytes, NULL);
-  if (gst_structure_get_int (source_stats, "packets-lost", &lost))
-    gst_structure_set (in, "packets-lost", G_TYPE_INT, lost, NULL);
-  if (gst_structure_get_uint (source_stats, "jitter", &jitter))
-    gst_structure_set (in, "jitter", G_TYPE_DOUBLE,
-        CLOCK_RATE_VALUE_TO_SECONDS (jitter, clock_rate), NULL);
-/*
-    RTCReceivedRTPStreamStats
+  gst_structure_get (source_stats, "ssrc", G_TYPE_UINT, &ssrc, "clock-rate",
+      G_TYPE_INT, &clock_rate, "internal", G_TYPE_BOOLEAN, &internal, NULL);
+
+  if (internal) {
+    GstStructure *r_in, *out;
+    gchar *out_id, *r_in_id;
+
+    out_id = g_strdup_printf ("rtp-outbound-stream-stats_%u", ssrc);
+    r_in_id = g_strdup_printf ("rtp-remote-inbound-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);
+
+    /* RTCStreamStats */
+    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);
+    /* XXX: mediaType, trackId, sliCount, qpSum */
+
+    if (gst_structure_get_uint64 (source_stats, "packets-received", &packets))
+      gst_structure_set (r_in, "packets-received", G_TYPE_UINT64, packets,
+          NULL);
+    if (gst_structure_get_int (source_stats, "packets-lost", &lost))
+      gst_structure_set (r_in, "packets-lost", G_TYPE_INT, lost, NULL);
+    if (gst_structure_get_uint (source_stats, "jitter", &jitter))
+      gst_structure_set (r_in, "jitter", G_TYPE_DOUBLE,
+          CLOCK_RATE_VALUE_TO_SECONDS (jitter, clock_rate), NULL);
+
+/* XXX: RTCReceivedRTPStreamStats
     double             fractionLost;
     unsigned long      packetsDiscarded;
     unsigned long      packetsFailedDecryption;
@@ -150,33 +143,89 @@ _get_stats_from_rtp_source_stats (GstWebRTCBin * webrtc,
     double             gapDiscardRate;
 */
 
-  /* RTCInboundRTPStreamStats */
-  gst_structure_set (in, "remote-id", G_TYPE_STRING, r_out_id, NULL);
-  /* XXX: framesDecoded, lastPacketReceivedTimestamp */
+    /* RTCRemoteInboundRTPStreamStats */
+    /* XXX: framesDecoded, lastPacketReceivedTimestamp */
 
-  r_in = gst_structure_new_empty (r_in_id);
-  _set_base_stats (r_in, GST_WEBRTC_STATS_REMOTE_INBOUND_RTP, ts, r_in_id);
+    out = gst_structure_new_empty (out_id);
+    _set_base_stats (out, GST_WEBRTC_STATS_OUTBOUND_RTP, ts, out_id);
 
-  /* RTCStreamStats */
-  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);
-  /* XXX: mediaType, trackId, sliCount, qpSum */
+    /* RTCStreamStats */
+    gst_structure_set (out, "ssrc", G_TYPE_UINT, ssrc, NULL);
+    gst_structure_set (out, "codec-id", G_TYPE_STRING, codec_id, NULL);
+    gst_structure_set (out, "transport-id", G_TYPE_STRING, transport_id, NULL);
+    if (gst_structure_get_uint (source_stats, "sent-fir-count", &fir))
+      gst_structure_set (out, "fir-count", G_TYPE_UINT, fir, NULL);
+    if (gst_structure_get_uint (source_stats, "sent-pli-count", &pli))
+      gst_structure_set (out, "pli-count", G_TYPE_UINT, pli, NULL);
+    if (gst_structure_get_uint (source_stats, "sent-nack-count", &nack))
+      gst_structure_set (out, "nack-count", G_TYPE_UINT, nack, NULL);
+    /* XXX: mediaType, trackId, sliCount, qpSum */
 
-  /* RTCReceivedRTPStreamStats */
-  if (sent_rb) {
-    if (gst_structure_get_uint (source_stats, "sent-rb-jitter", &jitter))
-      gst_structure_set (r_in, "jitter", G_TYPE_DOUBLE,
-          CLOCK_RATE_VALUE_TO_SECONDS (jitter, clock_rate), NULL);
-    if (gst_structure_get_int (source_stats, "sent-rb-packetslost", &lost))
-      gst_structure_set (r_in, "packets-lost", G_TYPE_INT, lost, NULL);
-    /* packetsReceived, bytesReceived */
+/* RTCSentRTPStreamStats */
+    if (gst_structure_get_uint64 (source_stats, "octets-sent", &bytes))
+      gst_structure_set (out, "bytes-sent", G_TYPE_UINT64, bytes, NULL);
+    if (gst_structure_get_uint64 (source_stats, "packets-sent", &packets))
+      gst_structure_set (out, "packets-sent", G_TYPE_UINT64, packets, NULL);
+/* XXX:
+    unsigned long      packetsDiscardedOnSend;
+    unsigned long long bytesDiscardedOnSend;
+*/
+
+    /* RTCOutboundRTPStreamStats */
+    gst_structure_set (out, "remote-id", G_TYPE_STRING, r_in_id, NULL);
+/* XXX:
+    DOMHighResTimeStamp lastPacketSentTimestamp;
+    double              targetBitrate;
+    unsigned long       framesEncoded;
+    double              totalEncodeTime;
+    double              averageRTCPInterval;
+*/
+    gst_structure_set (s, out_id, GST_TYPE_STRUCTURE, out, NULL);
+    gst_structure_set (s, r_in_id, GST_TYPE_STRUCTURE, r_in, NULL);
+
+    gst_structure_free (out);
+    gst_structure_free (r_in);
+
+    g_free (out_id);
+    g_free (r_in_id);
   } else {
-    /* default values */
-    gst_structure_set (r_in, "jitter", G_TYPE_DOUBLE, 0.0, "packets-lost",
-        G_TYPE_INT, 0, NULL);
-  }
-/* XXX: RTCReceivedRTPStreamStats
+    GstStructure *in, *r_out;
+    gchar *r_out_id, *in_id;
+    gboolean have_rb = FALSE, have_sr = FALSE;
+
+    gst_structure_get (source_stats, "have-rb", G_TYPE_BOOLEAN, &have_rb,
+        "have-sr", G_TYPE_BOOLEAN, &have_sr, NULL);
+
+    in_id = g_strdup_printf ("rtp-inbound-stream-stats_%u", ssrc);
+    r_out_id = g_strdup_printf ("rtp-remote-outbound-stream-stats_%u", ssrc);
+
+    in = gst_structure_new_empty (in_id);
+    _set_base_stats (in, GST_WEBRTC_STATS_INBOUND_RTP, ts, in_id);
+
+    /* RTCStreamStats */
+    gst_structure_set (in, "ssrc", G_TYPE_UINT, ssrc, NULL);
+    gst_structure_set (in, "codec-id", G_TYPE_STRING, codec_id, NULL);
+    gst_structure_set (in, "transport-id", G_TYPE_STRING, transport_id, NULL);
+    if (gst_structure_get_uint (source_stats, "recv-fir-count", &fir))
+      gst_structure_set (in, "fir-count", G_TYPE_UINT, fir, NULL);
+    if (gst_structure_get_uint (source_stats, "recv-pli-count", &pli))
+      gst_structure_set (in, "pli-count", G_TYPE_UINT, pli, NULL);
+    if (gst_structure_get_uint (source_stats, "recv-nack-count", &nack))
+      gst_structure_set (in, "nack-count", G_TYPE_UINT, nack, NULL);
+    /* XXX: mediaType, trackId, sliCount, qpSum */
+
+    /* RTCReceivedRTPStreamStats */
+    if (gst_structure_get_uint64 (source_stats, "packets-received", &packets))
+      gst_structure_set (in, "packets-received", G_TYPE_UINT64, packets, NULL);
+    if (gst_structure_get_uint64 (source_stats, "octets-received", &bytes))
+      gst_structure_set (in, "bytes-received", G_TYPE_UINT64, bytes, NULL);
+    if (gst_structure_get_int (source_stats, "packets-lost", &lost))
+      gst_structure_set (in, "packets-lost", G_TYPE_INT, lost, NULL);
+    if (gst_structure_get_uint (source_stats, "jitter", &jitter))
+      gst_structure_set (in, "jitter", G_TYPE_DOUBLE,
+          CLOCK_RATE_VALUE_TO_SECONDS (jitter, clock_rate), NULL);
+/*
+    RTCReceivedRTPStreamStats
     double             fractionLost;
     unsigned long      packetsDiscarded;
     unsigned long      packetsFailedDecryption;
@@ -191,91 +240,65 @@ _get_stats_from_rtp_source_stats (GstWebRTCBin * webrtc,
     double             gapDiscardRate;
 */
 
-  /* RTCRemoteInboundRTPStreamStats */
-  gst_structure_set (r_in, "local-id", G_TYPE_STRING, out_id, NULL);
-  if (have_rb) {
-    guint32 rtt;
-    if (gst_structure_get_uint (source_stats, "rb-round-trip", &rtt)) {
-      /* 16.16 fixed point to double */
-      double val =
-          (double) ((rtt & 0xffff0000) >> 16) + ((rtt & 0xffff) / 65536.0);
-      gst_structure_set (r_in, "round-trip-time", G_TYPE_DOUBLE, val, NULL);
+    /* RTCInboundRTPStreamStats */
+    gst_structure_set (in, "remote-id", G_TYPE_STRING, r_out_id, NULL);
+    /* XXX: framesDecoded, lastPacketReceivedTimestamp */
+
+    r_out = gst_structure_new_empty (r_out_id);
+    _set_base_stats (r_out, GST_WEBRTC_STATS_REMOTE_OUTBOUND_RTP, ts, r_out_id);
+    /* RTCStreamStats */
+    gst_structure_set (r_out, "ssrc", G_TYPE_UINT, ssrc, NULL);
+    gst_structure_set (r_out, "codec-id", G_TYPE_STRING, codec_id, NULL);
+    gst_structure_set (r_out, "transport-id", G_TYPE_STRING, transport_id,
+        NULL);
+    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_out, "round-trip-time", G_TYPE_DOUBLE, val, NULL);
+      }
+    } else {
+      /* default values */
+      gst_structure_set (r_out, "round-trip-time", G_TYPE_DOUBLE, 0.0, NULL);
     }
-  } else {
-    /* default values */
-    gst_structure_set (r_in, "round-trip-time", G_TYPE_DOUBLE, 0.0, NULL);
-  }
-  /* XXX: framesDecoded, lastPacketReceivedTimestamp */
-
-  out = gst_structure_new_empty (out_id);
-  _set_base_stats (out, GST_WEBRTC_STATS_OUTBOUND_RTP, ts, out_id);
-
-  /* RTCStreamStats */
-  gst_structure_set (out, "ssrc", G_TYPE_UINT, ssrc, NULL);
-  gst_structure_set (out, "codec-id", G_TYPE_STRING, codec_id, NULL);
-  gst_structure_set (out, "transport-id", G_TYPE_STRING, transport_id, NULL);
-  if (gst_structure_get_uint (source_stats, "sent-fir-count", &fir))
-    gst_structure_set (out, "fir-count", G_TYPE_UINT, fir, NULL);
-  if (gst_structure_get_uint (source_stats, "sent-pli-count", &pli))
-    gst_structure_set (out, "pli-count", G_TYPE_UINT, pli, NULL);
-  if (gst_structure_get_uint (source_stats, "sent-nack-count", &nack))
-    gst_structure_set (out, "nack-count", G_TYPE_UINT, nack, NULL);
-  /* XXX: mediaType, trackId, sliCount, qpSum */
+    /* XXX: mediaType, trackId, sliCount, qpSum */
 
 /* RTCSentRTPStreamStats */
-  if (gst_structure_get_uint64 (source_stats, "octets-sent", &bytes))
-    gst_structure_set (out, "bytes-sent", G_TYPE_UINT64, bytes, NULL);
-  if (gst_structure_get_uint64 (source_stats, "packets-sent", &packets))
-    gst_structure_set (out, "packets-sent", G_TYPE_UINT64, packets, NULL);
+    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);
+    }
 /* XXX:
     unsigned long      packetsDiscardedOnSend;
     unsigned long long bytesDiscardedOnSend;
 */
 
-  /* RTCOutboundRTPStreamStats */
-  gst_structure_set (out, "remote-id", G_TYPE_STRING, r_in_id, NULL);
-/* XXX:
-    DOMHighResTimeStamp lastPacketSentTimestamp;
-    double              targetBitrate;
-    unsigned long       framesEncoded;
-    double              totalEncodeTime;
-    double              averageRTCPInterval;
-*/
-
-  r_out = gst_structure_new_empty (r_out_id);
-  _set_base_stats (r_out, GST_WEBRTC_STATS_REMOTE_OUTBOUND_RTP, ts, r_out_id);
-  /* RTCStreamStats */
-  gst_structure_set (r_out, "ssrc", G_TYPE_UINT, ssrc, NULL);
-  gst_structure_set (r_out, "codec-id", G_TYPE_STRING, codec_id, NULL);
-  gst_structure_set (r_out, "transport-id", G_TYPE_STRING, transport_id, NULL);
-  /* XXX: mediaType, trackId, sliCount, qpSum */
-
-/* RTCSentRTPStreamStats */
-/*  if (gst_structure_get_uint64 (source_stats, "octets-sent", &bytes))
-    gst_structure_set (r_out, "bytes-sent", G_TYPE_UINT64, bytes, NULL);
-  if (gst_structure_get_uint64 (source_stats, "packets-sent", &packets))
-    gst_structure_set (r_out, "packets-sent", G_TYPE_UINT64, packets, NULL);*/
-/* XXX:
-    unsigned long      packetsDiscardedOnSend;
-    unsigned long long bytesDiscardedOnSend;
-*/
+    if (have_sr) {
+      guint64 ntptime;
+      if (gst_structure_get_uint64 (source_stats, "sr-ntptime", &ntptime)) {
+        /* 16.16 fixed point to double */
+        double val = FIXED_32_32_TO_DOUBLE (ntptime);
+        gst_structure_set (r_out, "remote-timestamp", G_TYPE_DOUBLE, val, NULL);
+      }
+    } else {
+      /* default values */
+      gst_structure_set (r_out, "remote-timestamp", G_TYPE_DOUBLE, 0.0, NULL);
+    }
 
-  gst_structure_set (r_out, "local-id", G_TYPE_STRING, in_id, NULL);
+    gst_structure_set (r_out, "local-id", G_TYPE_STRING, in_id, NULL);
 
-  gst_structure_set (s, in_id, GST_TYPE_STRUCTURE, in, NULL);
-  gst_structure_set (s, out_id, GST_TYPE_STRUCTURE, out, NULL);
-  gst_structure_set (s, r_in_id, GST_TYPE_STRUCTURE, r_in, NULL);
-  gst_structure_set (s, r_out_id, GST_TYPE_STRUCTURE, r_out, NULL);
+    gst_structure_set (s, in_id, GST_TYPE_STRUCTURE, in, NULL);
+    gst_structure_set (s, r_out_id, GST_TYPE_STRUCTURE, r_out, NULL);
 
-  gst_structure_free (in);
-  gst_structure_free (out);
-  gst_structure_free (r_in);
-  gst_structure_free (r_out);
+    gst_structure_free (in);
+    gst_structure_free (r_out);
 
-  g_free (in_id);
-  g_free (out_id);
-  g_free (r_in_id);
-  g_free (r_out_id);
+    g_free (in_id);
+    g_free (r_out_id);
+  }
 }
 
 /* https://www.w3.org/TR/webrtc-stats/#candidatepair-dict* */
@@ -441,16 +464,13 @@ _get_stats_from_transport_channel (GstWebRTCBin * webrtc,
   for (i = 0; i < source_stats->n_values; i++) {
     const GstStructure *stats;
     const GValue *val = g_value_array_get_nth (source_stats, i);
-    gboolean internal;
     guint stats_ssrc = 0;
 
     stats = gst_value_get_structure (val);
 
-    /* skip internal or foreign sources */
-    gst_structure_get (stats,
-        "internal", G_TYPE_BOOLEAN, &internal,
-        "ssrc", G_TYPE_UINT, &stats_ssrc, NULL);
-    if (internal || (ssrc && stats_ssrc && ssrc != stats_ssrc))
+    /* 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, stats, codec_id, transport_id, s);