mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-26 19:51:11 +00:00
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:
parent
1c1661b54f
commit
1deb034e3d
1 changed files with 131 additions and 83 deletions
|
@ -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);
|
||||||
|
|
Loading…
Reference in a new issue