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,32 +99,31 @@ _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/#inboundrtpstats-dict*
https://www.w3.org/TR/webrtc-stats/#outboundrtpstats-dict* */
static void
_get_stats_from_rtp_source_stats (GstWebRTCBin * webrtc,
/* 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,
const gchar * codec_id, const gchar * transport_id, GstStructure * s)
guint ssrc, guint clock_rate, const gchar * codec_id,
const gchar * transport_id, GstStructure * s)
{
guint ssrc, fir, pli, nack, jitter;
int lost, clock_rate;
guint64 packets, bytes;
gboolean internal;
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, "ssrc", G_TYPE_UINT, &ssrc, "clock-rate",
G_TYPE_INT, &clock_rate, "internal", G_TYPE_BOOLEAN, &internal, NULL);
gst_structure_get (source_stats, "internal", G_TYPE_BOOLEAN, &internal,
"have-rb", G_TYPE_BOOLEAN, &have_rb, NULL);
if (internal) {
GstStructure *r_in, *out;
gchar *out_id, *r_in_id;
gboolean have_rb = FALSE;
/* This isn't what we're looking for */
if (internal == TRUE || have_rb == FALSE)
return 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);
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);
@ -136,13 +135,18 @@ _get_stats_from_rtp_source_stats (GstWebRTCBin * webrtc,
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:
To be added:
unsigned long long packetsReceived;
long long packetsLost;
double jitter;
unsigned long packetsDiscarded;
unsigned long packetsRepaired;
unsigned long burstPacketsLost;
@ -161,17 +165,17 @@ _get_stats_from_rtp_source_stats (GstWebRTCBin * webrtc,
unsigned long fullFramesLost;
*/
/* RTCRemoteInboundRTPStreamStats */
if (have_rb) {
guint32 rtt;
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:
@ -183,6 +187,40 @@ _get_stats_from_rtp_source_stats (GstWebRTCBin * webrtc,
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
_get_stats_from_rtp_source_stats (GstWebRTCBin * webrtc,
TransportStream * stream, const GstStructure * source_stats,
const gchar * codec_id, const gchar * transport_id, GstStructure * s)
{
guint ssrc, fir, pli, nack, jitter;
int clock_rate;
guint64 packets, bytes;
gboolean internal;
double ts;
gst_structure_get_double (s, "timestamp", &ts);
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 *out;
gchar *out_id, *r_in_id;
out_id = g_strdup_printf ("rtp-outbound-stream-stats_%u", ssrc);
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 */
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;
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);