webrtcstats: Get the remote-inbound stats from the right RTPSource

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.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/merge_requests/1766>
This commit is contained in:
Olivier Crête 2020-10-15 21:23:08 -04:00 committed by GStreamer Merge Bot
parent 1c1661b54f
commit 1deb034e3d

View 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_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)) #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/#inboundrtpstats-dict*
https://www.w3.org/TR/webrtc-stats/#outboundrtpstats-dict* */ https://www.w3.org/TR/webrtc-stats/#outboundrtpstats-dict* */
static void static void
@ -107,7 +206,7 @@ _get_stats_from_rtp_source_stats (GstWebRTCBin * webrtc,
const gchar * codec_id, const gchar * transport_id, GstStructure * s) const gchar * codec_id, const gchar * transport_id, GstStructure * s)
{ {
guint ssrc, fir, pli, nack, jitter; guint ssrc, fir, pli, nack, jitter;
int lost, clock_rate; int clock_rate;
guint64 packets, bytes; guint64 packets, bytes;
gboolean internal; gboolean internal;
double ts; 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); G_TYPE_INT, &clock_rate, "internal", G_TYPE_BOOLEAN, &internal, NULL);
if (internal) { if (internal) {
GstStructure *r_in, *out; GstStructure *out;
gchar *out_id, *r_in_id; gchar *out_id, *r_in_id;
gboolean have_rb = FALSE;
out_id = g_strdup_printf ("rtp-outbound-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);
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); out = gst_structure_new_empty (out_id);
_set_base_stats (out, GST_WEBRTC_STATS_OUTBOUND_RTP, ts, 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); gst_structure_set (out, "nack-count", G_TYPE_UINT, nack, NULL);
/* XXX: mediaType, trackId, sliCount, qpSum */ /* 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: /* RTCOutboundRTPStreamStats:
@ -264,12 +304,9 @@ _get_stats_from_rtp_source_stats (GstWebRTCBin * webrtc,
gst_structure_set (out, "gst-rtpsource-stats", GST_TYPE_STRUCTURE, gst_structure_set (out, "gst-rtpsource-stats", GST_TYPE_STRUCTURE,
source_stats, NULL); source_stats, NULL);
_gst_structure_take_structure (s, out_id, &out); _gst_structure_take_structure (s, out_id, &out);
_gst_structure_take_structure (s, r_in_id, &r_in);
g_free (out_id); g_free (out_id);
g_free (r_in_id);
} else { } else {
GstStructure *in, *r_out; GstStructure *in, *r_out;
gchar *r_out_id, *in_id; gchar *r_out_id, *in_id;
@ -427,10 +464,13 @@ _get_stats_from_rtp_source_stats (GstWebRTCBin * webrtc,
/* RTCSentRtpStreamStats */ /* RTCSentRtpStreamStats */
if (have_sr) { if (have_sr) {
if (gst_structure_get_uint64 (source_stats, "sr-octet-count", &bytes)) guint sr_bytes, sr_packets;
gst_structure_set (r_out, "bytes-sent", G_TYPE_UINT64, bytes, NULL);
if (gst_structure_get_uint64 (source_stats, "sr-packet-count", &packets)) if (gst_structure_get_uint (source_stats, "sr-octet-count", &sr_bytes))
gst_structure_set (r_out, "packets-sent", G_TYPE_UINT64, packets, NULL); 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: /* RTCSentRtpStreamStats:
@ -642,7 +682,7 @@ _get_stats_from_dtls_transport (GstWebRTCBin * webrtc,
static void static void
_get_stats_from_transport_channel (GstWebRTCBin * webrtc, _get_stats_from_transport_channel (GstWebRTCBin * webrtc,
TransportStream * stream, const gchar * codec_id, guint ssrc, TransportStream * stream, const gchar * codec_id, guint ssrc,
GstStructure * s) guint clock_rate, GstStructure * s)
{ {
GstWebRTCDTLSTransport *transport; GstWebRTCDTLSTransport *transport;
GObject *rtp_session; GObject *rtp_session;
@ -682,11 +722,14 @@ _get_stats_from_transport_channel (GstWebRTCBin * webrtc,
/* skip foreign sources */ /* skip foreign sources */
gst_structure_get (stats, "ssrc", G_TYPE_UINT, &stats_ssrc, NULL); gst_structure_get (stats, "ssrc", G_TYPE_UINT, &stats_ssrc, NULL);
if (ssrc && stats_ssrc && ssrc != stats_ssrc) if (gst_structure_get_uint (stats, "ssrc", &stats_ssrc) &&
continue; ssrc == stats_ssrc)
_get_stats_from_rtp_source_stats (webrtc, stream, stats, codec_id,
_get_stats_from_rtp_source_stats (webrtc, stream, stats, codec_id, transport_id, s);
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); 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* */ /* https://www.w3.org/TR/webrtc-stats/#codec-dict* */
static void static void
_get_codec_stats_from_pad (GstWebRTCBin * webrtc, GstPad * pad, _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; GstStructure *stats;
GstCaps *caps; GstCaps *caps;
gchar *id; gchar *id;
double ts; double ts;
guint ssrc = 0; guint ssrc = 0;
gint clock_rate = 0;
gst_structure_get_double (s, "timestamp", &ts); 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); caps = gst_pad_get_current_caps (pad);
if (caps && gst_caps_is_fixed (caps)) { if (caps && gst_caps_is_fixed (caps)) {
GstStructure *caps_s = gst_caps_get_structure (caps, 0); GstStructure *caps_s = gst_caps_get_structure (caps, 0);
gint pt, clock_rate; gint pt;
if (gst_structure_get_int (caps_s, "payload", &pt)) if (gst_structure_get_int (caps_s, "payload", &pt))
gst_structure_set (stats, "payload-type", G_TYPE_UINT, pt, NULL); 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) if (out_ssrc)
*out_ssrc = ssrc; *out_ssrc = ssrc;
if (out_clock_rate)
*out_clock_rate = clock_rate;
} }
static gboolean static gboolean
@ -750,9 +797,9 @@ _get_stats_from_pad (GstWebRTCBin * webrtc, GstPad * pad, GstStructure * s)
GstWebRTCBinPad *wpad = GST_WEBRTC_BIN_PAD (pad); GstWebRTCBinPad *wpad = GST_WEBRTC_BIN_PAD (pad);
TransportStream *stream; TransportStream *stream;
gchar *codec_id; 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) if (!wpad->trans)
goto out; goto out;
@ -761,7 +808,8 @@ _get_stats_from_pad (GstWebRTCBin * webrtc, GstPad * pad, GstStructure * s)
if (!stream) if (!stream)
goto out; 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: out:
g_free (codec_id); g_free (codec_id);