diff --git a/subprojects/gst-plugins-bad/ext/webrtc/gstwebrtcbin.c b/subprojects/gst-plugins-bad/ext/webrtc/gstwebrtcbin.c index 10d617f1f6..0584e08a14 100644 --- a/subprojects/gst-plugins-bad/ext/webrtc/gstwebrtcbin.c +++ b/subprojects/gst-plugins-bad/ext/webrtc/gstwebrtcbin.c @@ -441,37 +441,6 @@ gst_webrtc_bin_pad_init (GstWebRTCBinPad * pad) { } -static GstPadProbeReturn -webrtc_bin_pad_buffer_cb (GstPad * pad, GstPadProbeInfo * info, - gpointer user_data) -{ - GstWebRTCBinPad *wpad; - GstBuffer *buf; - GstRTPBuffer rtpbuf = GST_RTP_BUFFER_INIT; - - if (info->type & GST_PAD_PROBE_TYPE_BUFFER) { - buf = GST_PAD_PROBE_INFO_BUFFER (info); - } else { - GstBufferList *list; - - list = GST_PAD_PROBE_INFO_BUFFER_LIST (info); - buf = gst_buffer_list_get (list, 0); - } - - if (buf == NULL) - return GST_PAD_PROBE_OK; - - if (!gst_rtp_buffer_map (buf, GST_MAP_READ, &rtpbuf)) - return GST_PAD_PROBE_OK; - - wpad = GST_WEBRTC_BIN_PAD (pad); - wpad->last_ssrc = gst_rtp_buffer_get_ssrc (&rtpbuf); - - gst_rtp_buffer_unmap (&rtpbuf); - - return GST_PAD_PROBE_OK; -} - static GstWebRTCBinPad * gst_webrtc_bin_pad_new (const gchar * name, GstPadDirection direction) { @@ -493,9 +462,6 @@ gst_webrtc_bin_pad_new (const gchar * name, GstPadDirection direction) gst_pad_set_event_function (GST_PAD (pad), gst_webrtcbin_sink_event); gst_pad_set_query_function (GST_PAD (pad), gst_webrtcbin_sink_query); - gst_pad_add_probe (GST_PAD (pad), GST_PAD_PROBE_TYPE_BUFFER | - GST_PAD_PROBE_TYPE_BUFFER_LIST, webrtc_bin_pad_buffer_cb, NULL, NULL); - GST_DEBUG_OBJECT (pad, "new visible pad with direction %s", direction == GST_PAD_SRC ? "src" : "sink"); return pad; diff --git a/subprojects/gst-plugins-bad/ext/webrtc/gstwebrtcbin.h b/subprojects/gst-plugins-bad/ext/webrtc/gstwebrtcbin.h index 232bb451eb..06f12edd9d 100644 --- a/subprojects/gst-plugins-bad/ext/webrtc/gstwebrtcbin.h +++ b/subprojects/gst-plugins-bad/ext/webrtc/gstwebrtcbin.h @@ -46,8 +46,6 @@ struct _GstWebRTCBinPad GstWebRTCRTPTransceiver *trans; gulong block_id; - guint32 last_ssrc; - GstCaps *received_caps; }; diff --git a/subprojects/gst-plugins-bad/ext/webrtc/gstwebrtcstats.c b/subprojects/gst-plugins-bad/ext/webrtc/gstwebrtcstats.c index 1d0dfb1a54..4931a42f17 100644 --- a/subprojects/gst-plugins-bad/ext/webrtc/gstwebrtcstats.c +++ b/subprojects/gst-plugins-bad/ext/webrtc/gstwebrtcstats.c @@ -697,72 +697,6 @@ _get_stats_from_dtls_transport (GstWebRTCBin * webrtc, return id; } -static void -_get_stats_from_transport_channel (GstWebRTCBin * webrtc, - TransportStream * stream, const gchar * codec_id, guint ssrc, - guint clock_rate, GstStructure * s) -{ - GstWebRTCDTLSTransport *transport; - GObject *rtp_session; - GObject *gst_rtp_session; - GstStructure *rtp_stats, *twcc_stats; - GValueArray *source_stats; - gchar *transport_id; - double ts; - int i; - - gst_structure_get_double (s, "timestamp", &ts); - - transport = stream->transport; - if (!transport) - return; - - g_signal_emit_by_name (webrtc->rtpbin, "get-internal-session", - stream->session_id, &rtp_session); - g_object_get (rtp_session, "stats", &rtp_stats, NULL); - g_signal_emit_by_name (webrtc->rtpbin, "get-session", - stream->session_id, &gst_rtp_session); - g_object_get (gst_rtp_session, "twcc-stats", &twcc_stats, NULL); - - gst_structure_get (rtp_stats, "source-stats", G_TYPE_VALUE_ARRAY, - &source_stats, NULL); - - GST_DEBUG_OBJECT (webrtc, "retrieving rtp stream stats from transport %" - GST_PTR_FORMAT " rtp session %" GST_PTR_FORMAT " with %u rtp sources, " - "transport %" GST_PTR_FORMAT, stream, rtp_session, source_stats->n_values, - transport); - - transport_id = - _get_stats_from_dtls_transport (webrtc, transport, twcc_stats, s); - - /* construct stats objects */ - for (i = 0; i < source_stats->n_values; i++) { - const GstStructure *stats; - const GValue *val = g_value_array_get_nth (source_stats, i); - guint stats_ssrc = 0; - - stats = gst_value_get_structure (val); - - /* skip foreign sources */ - 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); - g_object_unref (gst_rtp_session); - gst_structure_free (rtp_stats); - if (twcc_stats) - gst_structure_free (twcc_stats); - g_value_array_free (source_stats); - g_free (transport_id); -} - /* https://www.w3.org/TR/webrtc-stats/#codec-dict* */ static gboolean _get_codec_stats_from_pad (GstWebRTCBin * webrtc, GstPad * pad, @@ -860,33 +794,110 @@ _get_codec_stats_from_pad (GstWebRTCBin * webrtc, GstPad * pad, return has_caps_ssrc; } +struct transport_stream_stats +{ + GstWebRTCBin *webrtc; + TransportStream *stream; + char *transport_id; + char *codec_id; + guint clock_rate; + GValueArray *source_stats; + GstStructure *s; +}; + +static gboolean +webrtc_stats_get_from_transport (SsrcMapItem * entry, + struct transport_stream_stats *ts_stats) +{ + double ts; + int i; + + gst_structure_get_double (ts_stats->s, "timestamp", &ts); + + /* construct stats objects */ + for (i = 0; i < ts_stats->source_stats->n_values; i++) { + const GstStructure *stats; + const GValue *val = g_value_array_get_nth (ts_stats->source_stats, i); + guint stats_ssrc = 0; + + stats = gst_value_get_structure (val); + + /* skip foreign sources */ + if (gst_structure_get_uint (stats, "ssrc", &stats_ssrc) && + entry->ssrc == stats_ssrc) + _get_stats_from_rtp_source_stats (ts_stats->webrtc, ts_stats->stream, + stats, ts_stats->codec_id, ts_stats->transport_id, ts_stats->s); + else if (gst_structure_get_uint (stats, "rb-ssrc", &stats_ssrc) && + entry->ssrc == stats_ssrc) + _get_stats_from_remote_rtp_source_stats (ts_stats->webrtc, + ts_stats->stream, stats, entry->ssrc, ts_stats->clock_rate, + ts_stats->codec_id, ts_stats->transport_id, ts_stats->s); + } + + /* we want to look at all the entries */ + return FALSE; +} + static gboolean _get_stats_from_pad (GstWebRTCBin * webrtc, GstPad * pad, GstStructure * s) { GstWebRTCBinPad *wpad = GST_WEBRTC_BIN_PAD (pad); - TransportStream *stream; - gchar *codec_id; + struct transport_stream_stats ts_stats = { NULL, }; guint ssrc, clock_rate; - gboolean has_caps_ssrc; + GObject *rtp_session; + GObject *gst_rtp_session; + GstStructure *rtp_stats, *twcc_stats; - has_caps_ssrc = _get_codec_stats_from_pad (webrtc, pad, s, &codec_id, &ssrc, + _get_codec_stats_from_pad (webrtc, pad, s, &ts_stats.codec_id, &ssrc, &clock_rate); if (!wpad->trans) goto out; - stream = WEBRTC_TRANSCEIVER (wpad->trans)->stream; - if (!stream) + ts_stats.stream = WEBRTC_TRANSCEIVER (wpad->trans)->stream; + if (!ts_stats.stream) goto out; - if (!has_caps_ssrc) - ssrc = wpad->last_ssrc; + if (wpad->trans->mline == G_MAXUINT) + goto out; - _get_stats_from_transport_channel (webrtc, stream, codec_id, ssrc, - clock_rate, s); + if (!ts_stats.stream->transport) + goto out; + + g_signal_emit_by_name (webrtc->rtpbin, "get-internal-session", + ts_stats.stream->session_id, &rtp_session); + g_object_get (rtp_session, "stats", &rtp_stats, NULL); + g_signal_emit_by_name (webrtc->rtpbin, "get-session", + ts_stats.stream->session_id, &gst_rtp_session); + g_object_get (gst_rtp_session, "twcc-stats", &twcc_stats, NULL); + + gst_structure_get (rtp_stats, "source-stats", G_TYPE_VALUE_ARRAY, + &ts_stats.source_stats, NULL); + + ts_stats.transport_id = + _get_stats_from_dtls_transport (webrtc, ts_stats.stream->transport, + twcc_stats, s); + + GST_DEBUG_OBJECT (webrtc, "retrieving rtp stream stats from transport %" + GST_PTR_FORMAT " rtp session %" GST_PTR_FORMAT " with %u rtp sources, " + "transport %" GST_PTR_FORMAT, ts_stats.stream, rtp_session, + ts_stats.source_stats->n_values, ts_stats.stream->transport); + + ts_stats.s = s; + + transport_stream_find_ssrc_map_item (ts_stats.stream, &ts_stats, + (FindSsrcMapFunc) webrtc_stats_get_from_transport); + + g_clear_object (&rtp_session); + g_clear_object (&gst_rtp_session); + gst_clear_structure (&rtp_stats); + gst_clear_structure (&twcc_stats); + g_value_array_free (ts_stats.source_stats); + ts_stats.source_stats = NULL; + g_clear_pointer (&ts_stats.transport_id, g_free); out: - g_free (codec_id); + g_clear_pointer (&ts_stats.codec_id, g_free); return TRUE; }