2016-08-30 14:04:35 -07:00
|
|
|
/*
|
|
|
|
|
* Copyright 2016 The WebRTC Project Authors. All rights reserved.
|
|
|
|
|
*
|
|
|
|
|
* Use of this source code is governed by a BSD-style license
|
|
|
|
|
* that can be found in the LICENSE file in the root of the source
|
|
|
|
|
* tree. An additional intellectual property rights grant can be found
|
|
|
|
|
* in the file PATENTS. All contributing project authors may
|
|
|
|
|
* be found in the AUTHORS file in the root of the source tree.
|
|
|
|
|
*/
|
|
|
|
|
|
2019-01-11 09:11:00 -08:00
|
|
|
#include "pc/rtc_stats_collector.h"
|
2016-08-30 14:04:35 -07:00
|
|
|
|
2021-01-29 14:45:08 +00:00
|
|
|
#include <stdio.h>
|
2021-02-10 14:31:24 +01:00
|
|
|
|
2021-01-29 14:45:08 +00:00
|
|
|
#include <algorithm>
|
|
|
|
|
#include <cstdint>
|
2020-02-10 14:05:55 +01:00
|
|
|
#include <map>
|
2016-08-30 14:04:35 -07:00
|
|
|
#include <memory>
|
2017-10-30 09:57:42 -07:00
|
|
|
#include <string>
|
2016-08-30 14:04:35 -07:00
|
|
|
#include <utility>
|
|
|
|
|
#include <vector>
|
|
|
|
|
|
2021-01-29 14:45:08 +00:00
|
|
|
#include "api/array_view.h"
|
2017-10-05 14:53:33 +02:00
|
|
|
#include "api/candidate.h"
|
2019-01-11 09:11:00 -08:00
|
|
|
#include "api/media_stream_interface.h"
|
2021-01-29 14:45:08 +00:00
|
|
|
#include "api/rtp_parameters.h"
|
|
|
|
|
#include "api/rtp_receiver_interface.h"
|
|
|
|
|
#include "api/rtp_sender_interface.h"
|
2021-02-10 14:31:24 +01:00
|
|
|
#include "api/sequence_checker.h"
|
2021-01-29 14:45:08 +00:00
|
|
|
#include "api/stats/rtc_stats.h"
|
|
|
|
|
#include "api/stats/rtcstats_objects.h"
|
|
|
|
|
#include "api/task_queue/queued_task.h"
|
2019-04-09 13:59:31 +02:00
|
|
|
#include "api/video/video_content_type.h"
|
2021-01-29 14:45:08 +00:00
|
|
|
#include "common_video/include/quality_limitation_reason.h"
|
2019-01-11 09:11:00 -08:00
|
|
|
#include "media/base/media_channel.h"
|
2021-01-29 14:45:08 +00:00
|
|
|
#include "modules/audio_processing/include/audio_processing_statistics.h"
|
|
|
|
|
#include "modules/rtp_rtcp/include/report_block_data.h"
|
|
|
|
|
#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
|
|
|
|
|
#include "p2p/base/connection_info.h"
|
|
|
|
|
#include "p2p/base/dtls_transport_internal.h"
|
|
|
|
|
#include "p2p/base/ice_transport_internal.h"
|
2019-01-11 09:11:00 -08:00
|
|
|
#include "p2p/base/p2p_constants.h"
|
2017-09-15 06:47:31 +02:00
|
|
|
#include "p2p/base/port.h"
|
2021-01-29 14:45:08 +00:00
|
|
|
#include "pc/channel.h"
|
|
|
|
|
#include "pc/channel_interface.h"
|
|
|
|
|
#include "pc/data_channel_utils.h"
|
2019-01-11 09:11:00 -08:00
|
|
|
#include "pc/rtc_stats_traversal.h"
|
2020-02-10 14:05:55 +01:00
|
|
|
#include "pc/webrtc_sdp.h"
|
2017-09-15 06:47:31 +02:00
|
|
|
#include "rtc_base/checks.h"
|
2021-01-29 14:45:08 +00:00
|
|
|
#include "rtc_base/ip_address.h"
|
|
|
|
|
#include "rtc_base/location.h"
|
|
|
|
|
#include "rtc_base/logging.h"
|
|
|
|
|
#include "rtc_base/network_constants.h"
|
|
|
|
|
#include "rtc_base/ref_counted_object.h"
|
|
|
|
|
#include "rtc_base/rtc_certificate.h"
|
|
|
|
|
#include "rtc_base/socket_address.h"
|
|
|
|
|
#include "rtc_base/ssl_stream_adapter.h"
|
|
|
|
|
#include "rtc_base/string_encode.h"
|
2018-06-11 16:25:54 +02:00
|
|
|
#include "rtc_base/strings/string_builder.h"
|
2019-01-11 09:11:00 -08:00
|
|
|
#include "rtc_base/time_utils.h"
|
2017-09-15 06:47:31 +02:00
|
|
|
#include "rtc_base/trace_event.h"
|
2016-08-30 14:04:35 -07:00
|
|
|
|
|
|
|
|
namespace webrtc {
|
|
|
|
|
|
2016-10-18 12:48:31 -07:00
|
|
|
namespace {
|
|
|
|
|
|
2019-05-22 15:49:42 +02:00
|
|
|
// TODO(https://crbug.com/webrtc/10656): Consider making IDs less predictable.
|
2016-10-24 04:00:05 -07:00
|
|
|
std::string RTCCertificateIDFromFingerprint(const std::string& fingerprint) {
|
|
|
|
|
return "RTCCertificate_" + fingerprint;
|
|
|
|
|
}
|
|
|
|
|
|
2018-02-15 15:19:50 -08:00
|
|
|
std::string RTCCodecStatsIDFromMidDirectionAndPayload(const std::string& mid,
|
|
|
|
|
bool inbound,
|
|
|
|
|
uint32_t payload_type) {
|
2018-06-11 16:25:54 +02:00
|
|
|
char buf[1024];
|
|
|
|
|
rtc::SimpleStringBuilder sb(buf);
|
|
|
|
|
sb << "RTCCodec_" << mid << (inbound ? "_Inbound_" : "_Outbound_")
|
|
|
|
|
<< payload_type;
|
|
|
|
|
return sb.str();
|
2016-11-23 02:32:06 -08:00
|
|
|
}
|
|
|
|
|
|
2016-10-24 04:00:05 -07:00
|
|
|
std::string RTCIceCandidatePairStatsIDFromConnectionInfo(
|
|
|
|
|
const cricket::ConnectionInfo& info) {
|
2018-06-11 16:25:54 +02:00
|
|
|
char buf[4096];
|
|
|
|
|
rtc::SimpleStringBuilder sb(buf);
|
|
|
|
|
sb << "RTCIceCandidatePair_" << info.local_candidate.id() << "_"
|
|
|
|
|
<< info.remote_candidate.id();
|
|
|
|
|
return sb.str();
|
2016-10-24 04:00:05 -07:00
|
|
|
}
|
|
|
|
|
|
2018-01-14 09:18:58 +01:00
|
|
|
const char kSender[] = "sender";
|
|
|
|
|
const char kReceiver[] = "receiver";
|
|
|
|
|
|
|
|
|
|
std::string RTCMediaStreamTrackStatsIDFromDirectionAndAttachment(
|
|
|
|
|
const char* direction,
|
2018-01-11 17:18:19 +01:00
|
|
|
int attachment_id) {
|
2018-06-11 16:25:54 +02:00
|
|
|
char buf[1024];
|
|
|
|
|
rtc::SimpleStringBuilder sb(buf);
|
|
|
|
|
sb << "RTCMediaStreamTrack_" << direction << "_" << attachment_id;
|
|
|
|
|
return sb.str();
|
2016-11-08 06:29:22 -08:00
|
|
|
}
|
|
|
|
|
|
2016-10-24 04:00:05 -07:00
|
|
|
std::string RTCTransportStatsIDFromTransportChannel(
|
|
|
|
|
const std::string& transport_name,
|
|
|
|
|
int channel_component) {
|
2018-06-11 16:25:54 +02:00
|
|
|
char buf[1024];
|
|
|
|
|
rtc::SimpleStringBuilder sb(buf);
|
|
|
|
|
sb << "RTCTransport_" << transport_name << "_" << channel_component;
|
|
|
|
|
return sb.str();
|
2016-10-24 04:00:05 -07:00
|
|
|
}
|
|
|
|
|
|
2021-03-23 17:23:04 +01:00
|
|
|
std::string RTCInboundRTPStreamStatsIDFromSSRC(cricket::MediaType media_type,
|
|
|
|
|
uint32_t ssrc) {
|
2018-06-11 16:25:54 +02:00
|
|
|
char buf[1024];
|
|
|
|
|
rtc::SimpleStringBuilder sb(buf);
|
2021-03-23 17:23:04 +01:00
|
|
|
sb << "RTCInboundRTP"
|
|
|
|
|
<< (media_type == cricket::MEDIA_TYPE_AUDIO ? "Audio" : "Video")
|
|
|
|
|
<< "Stream_" << ssrc;
|
2018-06-11 16:25:54 +02:00
|
|
|
return sb.str();
|
2016-11-01 03:00:17 -07:00
|
|
|
}
|
|
|
|
|
|
2021-03-23 17:23:04 +01:00
|
|
|
std::string RTCOutboundRTPStreamStatsIDFromSSRC(cricket::MediaType media_type,
|
|
|
|
|
uint32_t ssrc) {
|
2018-06-11 16:25:54 +02:00
|
|
|
char buf[1024];
|
|
|
|
|
rtc::SimpleStringBuilder sb(buf);
|
2021-03-23 17:23:04 +01:00
|
|
|
sb << "RTCOutboundRTP"
|
|
|
|
|
<< (media_type == cricket::MEDIA_TYPE_AUDIO ? "Audio" : "Video")
|
|
|
|
|
<< "Stream_" << ssrc;
|
2018-06-11 16:25:54 +02:00
|
|
|
return sb.str();
|
2016-11-01 01:50:46 -07:00
|
|
|
}
|
|
|
|
|
|
2019-06-24 16:44:51 +02:00
|
|
|
std::string RTCRemoteInboundRtpStreamStatsIdFromSourceSsrc(
|
Implement RTCRemoteInboundRtpStreamStats for both audio and video.
This implements the essentials of RTCRemoteInboundRtpStreamStats. This
includes:
- ssrc
- transportId
- codecId
- packetsLost
- jitter
- localId
- roundTripTime
https://w3c.github.io/webrtc-stats/#remoteinboundrtpstats-dict*
The following members are not implemented because they require more
work...
- From RTCReceivedRtpStreamStats: packetsReceived, packetsDiscarded,
packetsRepaired, burstPacketsLost, burstPacketsDiscarded,
burstLossCount, burstDiscardCount, burstLossRate, burstDiscardRate,
gapLossRate and gapDiscardRate.
- From RTCRemoteInboundRtpStreamStats: fractionLost.
Bug: webrtc:10455, webrtc:10456
Change-Id: If2ab0da7105d8c93bba58e14aa93bd22ffe57f1d
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/138067
Commit-Queue: Henrik Boström <hbos@webrtc.org>
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#28073}
2019-05-27 13:40:25 +02:00
|
|
|
cricket::MediaType media_type,
|
|
|
|
|
uint32_t source_ssrc) {
|
|
|
|
|
char buf[1024];
|
|
|
|
|
rtc::SimpleStringBuilder sb(buf);
|
|
|
|
|
sb << "RTCRemoteInboundRtp"
|
|
|
|
|
<< (media_type == cricket::MEDIA_TYPE_AUDIO ? "Audio" : "Video")
|
2019-06-24 16:44:51 +02:00
|
|
|
<< "Stream_" << source_ssrc;
|
Implement RTCRemoteInboundRtpStreamStats for both audio and video.
This implements the essentials of RTCRemoteInboundRtpStreamStats. This
includes:
- ssrc
- transportId
- codecId
- packetsLost
- jitter
- localId
- roundTripTime
https://w3c.github.io/webrtc-stats/#remoteinboundrtpstats-dict*
The following members are not implemented because they require more
work...
- From RTCReceivedRtpStreamStats: packetsReceived, packetsDiscarded,
packetsRepaired, burstPacketsLost, burstPacketsDiscarded,
burstLossCount, burstDiscardCount, burstLossRate, burstDiscardRate,
gapLossRate and gapDiscardRate.
- From RTCRemoteInboundRtpStreamStats: fractionLost.
Bug: webrtc:10455, webrtc:10456
Change-Id: If2ab0da7105d8c93bba58e14aa93bd22ffe57f1d
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/138067
Commit-Queue: Henrik Boström <hbos@webrtc.org>
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#28073}
2019-05-27 13:40:25 +02:00
|
|
|
return sb.str();
|
|
|
|
|
}
|
|
|
|
|
|
2021-03-23 17:23:04 +01:00
|
|
|
std::string RTCRemoteOutboundRTPStreamStatsIDFromSSRC(
|
|
|
|
|
cricket::MediaType media_type,
|
|
|
|
|
uint32_t source_ssrc) {
|
|
|
|
|
char buf[1024];
|
|
|
|
|
rtc::SimpleStringBuilder sb(buf);
|
|
|
|
|
sb << "RTCRemoteOutboundRTP"
|
|
|
|
|
<< (media_type == cricket::MEDIA_TYPE_AUDIO ? "Audio" : "Video")
|
|
|
|
|
<< "Stream_" << source_ssrc;
|
|
|
|
|
return sb.str();
|
|
|
|
|
}
|
|
|
|
|
|
2019-05-22 15:49:42 +02:00
|
|
|
std::string RTCMediaSourceStatsIDFromKindAndAttachment(
|
|
|
|
|
cricket::MediaType media_type,
|
|
|
|
|
int attachment_id) {
|
|
|
|
|
char buf[1024];
|
|
|
|
|
rtc::SimpleStringBuilder sb(buf);
|
|
|
|
|
sb << "RTC" << (media_type == cricket::MEDIA_TYPE_AUDIO ? "Audio" : "Video")
|
|
|
|
|
<< "Source_" << attachment_id;
|
|
|
|
|
return sb.str();
|
|
|
|
|
}
|
|
|
|
|
|
2016-10-07 02:18:47 -07:00
|
|
|
const char* CandidateTypeToRTCIceCandidateType(const std::string& type) {
|
|
|
|
|
if (type == cricket::LOCAL_PORT_TYPE)
|
|
|
|
|
return RTCIceCandidateType::kHost;
|
|
|
|
|
if (type == cricket::STUN_PORT_TYPE)
|
|
|
|
|
return RTCIceCandidateType::kSrflx;
|
|
|
|
|
if (type == cricket::PRFLX_PORT_TYPE)
|
|
|
|
|
return RTCIceCandidateType::kPrflx;
|
|
|
|
|
if (type == cricket::RELAY_PORT_TYPE)
|
|
|
|
|
return RTCIceCandidateType::kRelay;
|
|
|
|
|
RTC_NOTREACHED();
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
2016-10-18 12:48:31 -07:00
|
|
|
const char* DataStateToRTCDataChannelState(
|
|
|
|
|
DataChannelInterface::DataState state) {
|
|
|
|
|
switch (state) {
|
|
|
|
|
case DataChannelInterface::kConnecting:
|
|
|
|
|
return RTCDataChannelState::kConnecting;
|
|
|
|
|
case DataChannelInterface::kOpen:
|
|
|
|
|
return RTCDataChannelState::kOpen;
|
|
|
|
|
case DataChannelInterface::kClosing:
|
|
|
|
|
return RTCDataChannelState::kClosing;
|
|
|
|
|
case DataChannelInterface::kClosed:
|
|
|
|
|
return RTCDataChannelState::kClosed;
|
|
|
|
|
default:
|
|
|
|
|
RTC_NOTREACHED();
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-01-02 08:08:18 -08:00
|
|
|
const char* IceCandidatePairStateToRTCStatsIceCandidatePairState(
|
|
|
|
|
cricket::IceCandidatePairState state) {
|
|
|
|
|
switch (state) {
|
|
|
|
|
case cricket::IceCandidatePairState::WAITING:
|
|
|
|
|
return RTCStatsIceCandidatePairState::kWaiting;
|
|
|
|
|
case cricket::IceCandidatePairState::IN_PROGRESS:
|
|
|
|
|
return RTCStatsIceCandidatePairState::kInProgress;
|
|
|
|
|
case cricket::IceCandidatePairState::SUCCEEDED:
|
|
|
|
|
return RTCStatsIceCandidatePairState::kSucceeded;
|
|
|
|
|
case cricket::IceCandidatePairState::FAILED:
|
|
|
|
|
return RTCStatsIceCandidatePairState::kFailed;
|
|
|
|
|
default:
|
|
|
|
|
RTC_NOTREACHED();
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-01-16 07:38:02 -08:00
|
|
|
const char* DtlsTransportStateToRTCDtlsTransportState(
|
|
|
|
|
cricket::DtlsTransportState state) {
|
|
|
|
|
switch (state) {
|
|
|
|
|
case cricket::DTLS_TRANSPORT_NEW:
|
|
|
|
|
return RTCDtlsTransportState::kNew;
|
|
|
|
|
case cricket::DTLS_TRANSPORT_CONNECTING:
|
|
|
|
|
return RTCDtlsTransportState::kConnecting;
|
|
|
|
|
case cricket::DTLS_TRANSPORT_CONNECTED:
|
|
|
|
|
return RTCDtlsTransportState::kConnected;
|
|
|
|
|
case cricket::DTLS_TRANSPORT_CLOSED:
|
|
|
|
|
return RTCDtlsTransportState::kClosed;
|
|
|
|
|
case cricket::DTLS_TRANSPORT_FAILED:
|
|
|
|
|
return RTCDtlsTransportState::kFailed;
|
|
|
|
|
default:
|
|
|
|
|
RTC_NOTREACHED();
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-11-21 10:49:36 -08:00
|
|
|
const char* NetworkAdapterTypeToStatsType(rtc::AdapterType type) {
|
|
|
|
|
switch (type) {
|
|
|
|
|
case rtc::ADAPTER_TYPE_CELLULAR:
|
2020-04-02 07:19:12 +02:00
|
|
|
case rtc::ADAPTER_TYPE_CELLULAR_2G:
|
|
|
|
|
case rtc::ADAPTER_TYPE_CELLULAR_3G:
|
|
|
|
|
case rtc::ADAPTER_TYPE_CELLULAR_4G:
|
|
|
|
|
case rtc::ADAPTER_TYPE_CELLULAR_5G:
|
2017-11-21 10:49:36 -08:00
|
|
|
return RTCNetworkType::kCellular;
|
|
|
|
|
case rtc::ADAPTER_TYPE_ETHERNET:
|
|
|
|
|
return RTCNetworkType::kEthernet;
|
|
|
|
|
case rtc::ADAPTER_TYPE_WIFI:
|
|
|
|
|
return RTCNetworkType::kWifi;
|
|
|
|
|
case rtc::ADAPTER_TYPE_VPN:
|
|
|
|
|
return RTCNetworkType::kVpn;
|
|
|
|
|
case rtc::ADAPTER_TYPE_UNKNOWN:
|
|
|
|
|
case rtc::ADAPTER_TYPE_LOOPBACK:
|
2018-06-28 15:38:09 -07:00
|
|
|
case rtc::ADAPTER_TYPE_ANY:
|
2017-11-21 10:49:36 -08:00
|
|
|
return RTCNetworkType::kUnknown;
|
|
|
|
|
}
|
|
|
|
|
RTC_NOTREACHED();
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
2019-05-28 17:42:38 +02:00
|
|
|
const char* QualityLimitationReasonToRTCQualityLimitationReason(
|
|
|
|
|
QualityLimitationReason reason) {
|
|
|
|
|
switch (reason) {
|
|
|
|
|
case QualityLimitationReason::kNone:
|
|
|
|
|
return RTCQualityLimitationReason::kNone;
|
|
|
|
|
case QualityLimitationReason::kCpu:
|
|
|
|
|
return RTCQualityLimitationReason::kCpu;
|
|
|
|
|
case QualityLimitationReason::kBandwidth:
|
|
|
|
|
return RTCQualityLimitationReason::kBandwidth;
|
|
|
|
|
case QualityLimitationReason::kOther:
|
|
|
|
|
return RTCQualityLimitationReason::kOther;
|
|
|
|
|
}
|
2020-11-08 00:49:37 +01:00
|
|
|
RTC_CHECK_NOTREACHED();
|
2019-05-28 17:42:38 +02:00
|
|
|
}
|
|
|
|
|
|
2017-01-20 02:47:10 -08:00
|
|
|
double DoubleAudioLevelFromIntAudioLevel(int audio_level) {
|
|
|
|
|
RTC_DCHECK_GE(audio_level, 0);
|
|
|
|
|
RTC_DCHECK_LE(audio_level, 32767);
|
|
|
|
|
return audio_level / 32767.0;
|
|
|
|
|
}
|
|
|
|
|
|
2016-11-23 02:32:06 -08:00
|
|
|
std::unique_ptr<RTCCodecStats> CodecStatsFromRtpCodecParameters(
|
2018-02-15 15:19:50 -08:00
|
|
|
uint64_t timestamp_us,
|
|
|
|
|
const std::string& mid,
|
2020-11-16 20:08:27 +01:00
|
|
|
const std::string& transport_id,
|
2018-02-15 15:19:50 -08:00
|
|
|
bool inbound,
|
2016-11-23 02:32:06 -08:00
|
|
|
const RtpCodecParameters& codec_params) {
|
|
|
|
|
RTC_DCHECK_GE(codec_params.payload_type, 0);
|
|
|
|
|
RTC_DCHECK_LE(codec_params.payload_type, 127);
|
2017-02-04 12:09:01 -08:00
|
|
|
RTC_DCHECK(codec_params.clock_rate);
|
2016-11-23 02:32:06 -08:00
|
|
|
uint32_t payload_type = static_cast<uint32_t>(codec_params.payload_type);
|
|
|
|
|
std::unique_ptr<RTCCodecStats> codec_stats(new RTCCodecStats(
|
2018-02-15 15:19:50 -08:00
|
|
|
RTCCodecStatsIDFromMidDirectionAndPayload(mid, inbound, payload_type),
|
2016-11-23 02:32:06 -08:00
|
|
|
timestamp_us));
|
|
|
|
|
codec_stats->payload_type = payload_type;
|
2017-02-28 06:56:04 -08:00
|
|
|
codec_stats->mime_type = codec_params.mime_type();
|
2017-02-04 12:09:01 -08:00
|
|
|
if (codec_params.clock_rate) {
|
|
|
|
|
codec_stats->clock_rate = static_cast<uint32_t>(*codec_params.clock_rate);
|
|
|
|
|
}
|
2020-02-10 14:05:55 +01:00
|
|
|
if (codec_params.num_channels) {
|
|
|
|
|
codec_stats->channels = *codec_params.num_channels;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rtc::StringBuilder fmtp;
|
|
|
|
|
if (WriteFmtpParameters(codec_params.parameters, &fmtp)) {
|
|
|
|
|
codec_stats->sdp_fmtp_line = fmtp.Release();
|
|
|
|
|
}
|
2020-11-16 20:08:27 +01:00
|
|
|
codec_stats->transport_id = transport_id;
|
2016-11-23 02:32:06 -08:00
|
|
|
return codec_stats;
|
|
|
|
|
}
|
|
|
|
|
|
2016-11-08 06:29:22 -08:00
|
|
|
void SetMediaStreamTrackStatsFromMediaStreamTrackInterface(
|
|
|
|
|
const MediaStreamTrackInterface& track,
|
|
|
|
|
RTCMediaStreamTrackStats* track_stats) {
|
|
|
|
|
track_stats->track_identifier = track.id();
|
|
|
|
|
track_stats->ended = (track.state() == MediaStreamTrackInterface::kEnded);
|
|
|
|
|
}
|
|
|
|
|
|
2016-11-22 03:16:50 -08:00
|
|
|
// Provides the media independent counters (both audio and video).
|
2016-11-01 03:00:17 -07:00
|
|
|
void SetInboundRTPStreamStatsFromMediaReceiverInfo(
|
|
|
|
|
const cricket::MediaReceiverInfo& media_receiver_info,
|
|
|
|
|
RTCInboundRTPStreamStats* inbound_stats) {
|
|
|
|
|
RTC_DCHECK(inbound_stats);
|
2017-02-07 06:28:11 -08:00
|
|
|
inbound_stats->ssrc = media_receiver_info.ssrc();
|
2016-11-01 03:00:17 -07:00
|
|
|
inbound_stats->packets_received =
|
|
|
|
|
static_cast<uint32_t>(media_receiver_info.packets_rcvd);
|
|
|
|
|
inbound_stats->bytes_received =
|
2019-10-09 15:01:33 +02:00
|
|
|
static_cast<uint64_t>(media_receiver_info.payload_bytes_rcvd);
|
|
|
|
|
inbound_stats->header_bytes_received =
|
|
|
|
|
static_cast<uint64_t>(media_receiver_info.header_and_padding_bytes_rcvd);
|
2016-12-09 04:19:44 -08:00
|
|
|
inbound_stats->packets_lost =
|
2017-12-13 12:26:04 +01:00
|
|
|
static_cast<int32_t>(media_receiver_info.packets_lost);
|
2016-11-01 03:00:17 -07:00
|
|
|
}
|
|
|
|
|
|
2021-03-23 17:23:04 +01:00
|
|
|
std::unique_ptr<RTCInboundRTPStreamStats> CreateInboundAudioStreamStats(
|
2016-11-01 03:00:17 -07:00
|
|
|
const cricket::VoiceReceiverInfo& voice_receiver_info,
|
2021-03-23 17:23:04 +01:00
|
|
|
const std::string& mid,
|
|
|
|
|
int64_t timestamp_us) {
|
|
|
|
|
auto inbound_audio = std::make_unique<RTCInboundRTPStreamStats>(
|
|
|
|
|
/*id=*/RTCInboundRTPStreamStatsIDFromSSRC(cricket::MEDIA_TYPE_AUDIO,
|
|
|
|
|
voice_receiver_info.ssrc()),
|
|
|
|
|
timestamp_us);
|
2016-11-01 03:00:17 -07:00
|
|
|
SetInboundRTPStreamStatsFromMediaReceiverInfo(voice_receiver_info,
|
2021-03-23 17:23:04 +01:00
|
|
|
inbound_audio.get());
|
2016-11-22 03:16:50 -08:00
|
|
|
inbound_audio->media_type = "audio";
|
2018-08-28 14:55:03 +02:00
|
|
|
inbound_audio->kind = "audio";
|
2017-02-07 04:59:16 -08:00
|
|
|
if (voice_receiver_info.codec_payload_type) {
|
2018-02-15 15:19:50 -08:00
|
|
|
inbound_audio->codec_id = RTCCodecStatsIDFromMidDirectionAndPayload(
|
2021-03-23 17:23:04 +01:00
|
|
|
mid, /*inbound=*/true, *voice_receiver_info.codec_payload_type);
|
2017-02-07 04:59:16 -08:00
|
|
|
}
|
2016-11-01 03:00:17 -07:00
|
|
|
inbound_audio->jitter = static_cast<double>(voice_receiver_info.jitter_ms) /
|
|
|
|
|
rtc::kNumMillisecsPerSec;
|
2020-07-06 14:18:07 +03:00
|
|
|
inbound_audio->jitter_buffer_delay =
|
|
|
|
|
voice_receiver_info.jitter_buffer_delay_seconds;
|
|
|
|
|
inbound_audio->jitter_buffer_emitted_count =
|
|
|
|
|
voice_receiver_info.jitter_buffer_emitted_count;
|
|
|
|
|
inbound_audio->total_samples_received =
|
|
|
|
|
voice_receiver_info.total_samples_received;
|
|
|
|
|
inbound_audio->concealed_samples = voice_receiver_info.concealed_samples;
|
|
|
|
|
inbound_audio->silent_concealed_samples =
|
|
|
|
|
voice_receiver_info.silent_concealed_samples;
|
|
|
|
|
inbound_audio->concealment_events = voice_receiver_info.concealment_events;
|
|
|
|
|
inbound_audio->inserted_samples_for_deceleration =
|
|
|
|
|
voice_receiver_info.inserted_samples_for_deceleration;
|
|
|
|
|
inbound_audio->removed_samples_for_acceleration =
|
|
|
|
|
voice_receiver_info.removed_samples_for_acceleration;
|
2020-10-27 09:50:36 +01:00
|
|
|
if (voice_receiver_info.audio_level >= 0) {
|
|
|
|
|
inbound_audio->audio_level =
|
|
|
|
|
DoubleAudioLevelFromIntAudioLevel(voice_receiver_info.audio_level);
|
|
|
|
|
}
|
2020-07-06 14:18:07 +03:00
|
|
|
inbound_audio->total_audio_energy = voice_receiver_info.total_output_energy;
|
|
|
|
|
inbound_audio->total_samples_duration =
|
|
|
|
|
voice_receiver_info.total_output_duration;
|
2016-11-22 03:16:50 -08:00
|
|
|
// |fir_count|, |pli_count| and |sli_count| are only valid for video and are
|
|
|
|
|
// purposefully left undefined for audio.
|
2019-04-15 17:32:00 +02:00
|
|
|
if (voice_receiver_info.last_packet_received_timestamp_ms) {
|
2021-03-22 15:36:53 +01:00
|
|
|
inbound_audio->last_packet_received_timestamp = static_cast<double>(
|
|
|
|
|
*voice_receiver_info.last_packet_received_timestamp_ms);
|
2019-04-15 17:32:00 +02:00
|
|
|
}
|
2019-10-22 15:23:44 +02:00
|
|
|
if (voice_receiver_info.estimated_playout_ntp_timestamp_ms) {
|
2021-03-24 08:51:26 +01:00
|
|
|
// TODO(bugs.webrtc.org/10529): Fix time origin.
|
2019-10-22 15:23:44 +02:00
|
|
|
inbound_audio->estimated_playout_timestamp = static_cast<double>(
|
|
|
|
|
*voice_receiver_info.estimated_playout_ntp_timestamp_ms);
|
|
|
|
|
}
|
2019-04-30 09:45:21 +02:00
|
|
|
inbound_audio->fec_packets_received =
|
|
|
|
|
voice_receiver_info.fec_packets_received;
|
|
|
|
|
inbound_audio->fec_packets_discarded =
|
|
|
|
|
voice_receiver_info.fec_packets_discarded;
|
2021-03-23 17:23:04 +01:00
|
|
|
return inbound_audio;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::unique_ptr<RTCRemoteOutboundRtpStreamStats>
|
|
|
|
|
CreateRemoteOutboundAudioStreamStats(
|
|
|
|
|
const cricket::VoiceReceiverInfo& voice_receiver_info,
|
|
|
|
|
const std::string& mid,
|
|
|
|
|
const std::string& inbound_audio_id,
|
|
|
|
|
const std::string& transport_id) {
|
|
|
|
|
if (!voice_receiver_info.last_sender_report_timestamp_ms.has_value()) {
|
|
|
|
|
// Cannot create `RTCRemoteOutboundRtpStreamStats` when the RTCP SR arrival
|
|
|
|
|
// timestamp is not available - i.e., until the first sender report is
|
|
|
|
|
// received.
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
RTC_DCHECK_GT(voice_receiver_info.sender_reports_reports_count, 0);
|
|
|
|
|
|
|
|
|
|
// Create.
|
|
|
|
|
auto stats = std::make_unique<RTCRemoteOutboundRtpStreamStats>(
|
|
|
|
|
/*id=*/RTCRemoteOutboundRTPStreamStatsIDFromSSRC(
|
|
|
|
|
cricket::MEDIA_TYPE_AUDIO, voice_receiver_info.ssrc()),
|
|
|
|
|
/*timestamp_us=*/rtc::kNumMicrosecsPerMillisec *
|
|
|
|
|
voice_receiver_info.last_sender_report_timestamp_ms.value());
|
|
|
|
|
|
|
|
|
|
// Populate.
|
|
|
|
|
// - RTCRtpStreamStats.
|
|
|
|
|
stats->ssrc = voice_receiver_info.ssrc();
|
|
|
|
|
stats->kind = "audio";
|
|
|
|
|
stats->transport_id = transport_id;
|
|
|
|
|
stats->codec_id = RTCCodecStatsIDFromMidDirectionAndPayload(
|
|
|
|
|
mid,
|
|
|
|
|
/*inbound=*/true, // Remote-outbound same as local-inbound.
|
|
|
|
|
*voice_receiver_info.codec_payload_type);
|
|
|
|
|
// - RTCSentRtpStreamStats.
|
|
|
|
|
stats->packets_sent = voice_receiver_info.sender_reports_packets_sent;
|
|
|
|
|
stats->bytes_sent = voice_receiver_info.sender_reports_bytes_sent;
|
|
|
|
|
// - RTCRemoteOutboundRtpStreamStats.
|
|
|
|
|
stats->local_id = inbound_audio_id;
|
|
|
|
|
RTC_DCHECK(
|
|
|
|
|
voice_receiver_info.last_sender_report_remote_timestamp_ms.has_value());
|
|
|
|
|
stats->remote_timestamp = static_cast<double>(
|
|
|
|
|
voice_receiver_info.last_sender_report_remote_timestamp_ms.value());
|
|
|
|
|
stats->reports_sent = voice_receiver_info.sender_reports_reports_count;
|
|
|
|
|
|
|
|
|
|
return stats;
|
2016-11-01 03:00:17 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SetInboundRTPStreamStatsFromVideoReceiverInfo(
|
2018-02-15 15:19:50 -08:00
|
|
|
const std::string& mid,
|
2016-11-01 03:00:17 -07:00
|
|
|
const cricket::VideoReceiverInfo& video_receiver_info,
|
2016-11-22 03:16:50 -08:00
|
|
|
RTCInboundRTPStreamStats* inbound_video) {
|
2016-11-01 03:00:17 -07:00
|
|
|
SetInboundRTPStreamStatsFromMediaReceiverInfo(video_receiver_info,
|
2016-11-22 03:16:50 -08:00
|
|
|
inbound_video);
|
|
|
|
|
inbound_video->media_type = "video";
|
2018-08-28 14:55:03 +02:00
|
|
|
inbound_video->kind = "video";
|
2017-02-07 04:59:16 -08:00
|
|
|
if (video_receiver_info.codec_payload_type) {
|
2018-02-15 15:19:50 -08:00
|
|
|
inbound_video->codec_id = RTCCodecStatsIDFromMidDirectionAndPayload(
|
2021-03-23 17:23:04 +01:00
|
|
|
mid, /*inbound=*/true, *video_receiver_info.codec_payload_type);
|
2017-02-07 04:59:16 -08:00
|
|
|
}
|
2021-02-19 17:34:22 -08:00
|
|
|
inbound_video->jitter = static_cast<double>(video_receiver_info.jitter_ms) /
|
|
|
|
|
rtc::kNumMillisecsPerSec;
|
2016-11-22 03:16:50 -08:00
|
|
|
inbound_video->fir_count =
|
|
|
|
|
static_cast<uint32_t>(video_receiver_info.firs_sent);
|
|
|
|
|
inbound_video->pli_count =
|
|
|
|
|
static_cast<uint32_t>(video_receiver_info.plis_sent);
|
|
|
|
|
inbound_video->nack_count =
|
|
|
|
|
static_cast<uint32_t>(video_receiver_info.nacks_sent);
|
2020-07-06 14:18:07 +03:00
|
|
|
inbound_video->frames_received = video_receiver_info.frames_received;
|
2017-01-02 08:35:13 -08:00
|
|
|
inbound_video->frames_decoded = video_receiver_info.frames_decoded;
|
2020-07-06 14:18:07 +03:00
|
|
|
inbound_video->frames_dropped = video_receiver_info.frames_dropped;
|
2019-06-27 14:29:34 +02:00
|
|
|
inbound_video->key_frames_decoded = video_receiver_info.key_frames_decoded;
|
2020-07-06 14:18:07 +03:00
|
|
|
if (video_receiver_info.frame_width > 0) {
|
|
|
|
|
inbound_video->frame_width =
|
|
|
|
|
static_cast<uint32_t>(video_receiver_info.frame_width);
|
|
|
|
|
}
|
|
|
|
|
if (video_receiver_info.frame_height > 0) {
|
|
|
|
|
inbound_video->frame_height =
|
|
|
|
|
static_cast<uint32_t>(video_receiver_info.frame_height);
|
|
|
|
|
}
|
|
|
|
|
if (video_receiver_info.framerate_rcvd > 0) {
|
|
|
|
|
inbound_video->frames_per_second = video_receiver_info.framerate_rcvd;
|
|
|
|
|
}
|
2017-02-16 05:34:48 -08:00
|
|
|
if (video_receiver_info.qp_sum)
|
|
|
|
|
inbound_video->qp_sum = *video_receiver_info.qp_sum;
|
2019-07-01 10:07:50 +02:00
|
|
|
inbound_video->total_decode_time =
|
|
|
|
|
static_cast<double>(video_receiver_info.total_decode_time_ms) /
|
|
|
|
|
rtc::kNumMillisecsPerSec;
|
2019-11-25 10:25:42 +01:00
|
|
|
inbound_video->total_inter_frame_delay =
|
|
|
|
|
video_receiver_info.total_inter_frame_delay;
|
|
|
|
|
inbound_video->total_squared_inter_frame_delay =
|
|
|
|
|
video_receiver_info.total_squared_inter_frame_delay;
|
2019-04-15 17:32:00 +02:00
|
|
|
if (video_receiver_info.last_packet_received_timestamp_ms) {
|
2021-03-24 08:51:26 +01:00
|
|
|
inbound_video->last_packet_received_timestamp = static_cast<double>(
|
|
|
|
|
*video_receiver_info.last_packet_received_timestamp_ms);
|
2019-04-15 17:32:00 +02:00
|
|
|
}
|
2019-10-22 15:23:44 +02:00
|
|
|
if (video_receiver_info.estimated_playout_ntp_timestamp_ms) {
|
2021-03-24 08:51:26 +01:00
|
|
|
// TODO(bugs.webrtc.org/10529): Fix time origin if needed.
|
2019-10-22 15:23:44 +02:00
|
|
|
inbound_video->estimated_playout_timestamp = static_cast<double>(
|
|
|
|
|
*video_receiver_info.estimated_playout_ntp_timestamp_ms);
|
|
|
|
|
}
|
2021-03-24 08:51:26 +01:00
|
|
|
// TODO(bugs.webrtc.org/10529): When info's |content_info| is optional
|
|
|
|
|
// support the "unspecified" value.
|
2019-04-09 13:59:31 +02:00
|
|
|
if (video_receiver_info.content_type == VideoContentType::SCREENSHARE)
|
|
|
|
|
inbound_video->content_type = RTCContentType::kScreenshare;
|
2019-08-16 13:09:51 +02:00
|
|
|
if (!video_receiver_info.decoder_implementation_name.empty()) {
|
|
|
|
|
inbound_video->decoder_implementation =
|
|
|
|
|
video_receiver_info.decoder_implementation_name;
|
|
|
|
|
}
|
2016-11-01 03:00:17 -07:00
|
|
|
}
|
|
|
|
|
|
2016-11-22 03:16:50 -08:00
|
|
|
// Provides the media independent counters (both audio and video).
|
2016-11-01 01:50:46 -07:00
|
|
|
void SetOutboundRTPStreamStatsFromMediaSenderInfo(
|
|
|
|
|
const cricket::MediaSenderInfo& media_sender_info,
|
|
|
|
|
RTCOutboundRTPStreamStats* outbound_stats) {
|
|
|
|
|
RTC_DCHECK(outbound_stats);
|
2017-02-07 06:28:11 -08:00
|
|
|
outbound_stats->ssrc = media_sender_info.ssrc();
|
2016-11-01 01:50:46 -07:00
|
|
|
outbound_stats->packets_sent =
|
|
|
|
|
static_cast<uint32_t>(media_sender_info.packets_sent);
|
2019-04-17 13:51:53 +02:00
|
|
|
outbound_stats->retransmitted_packets_sent =
|
|
|
|
|
media_sender_info.retransmitted_packets_sent;
|
2016-11-01 01:50:46 -07:00
|
|
|
outbound_stats->bytes_sent =
|
2019-10-09 15:01:33 +02:00
|
|
|
static_cast<uint64_t>(media_sender_info.payload_bytes_sent);
|
|
|
|
|
outbound_stats->header_bytes_sent =
|
|
|
|
|
static_cast<uint64_t>(media_sender_info.header_and_padding_bytes_sent);
|
2019-04-17 13:51:53 +02:00
|
|
|
outbound_stats->retransmitted_bytes_sent =
|
|
|
|
|
media_sender_info.retransmitted_bytes_sent;
|
2016-11-01 01:50:46 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SetOutboundRTPStreamStatsFromVoiceSenderInfo(
|
2018-02-15 15:19:50 -08:00
|
|
|
const std::string& mid,
|
2016-11-01 01:50:46 -07:00
|
|
|
const cricket::VoiceSenderInfo& voice_sender_info,
|
|
|
|
|
RTCOutboundRTPStreamStats* outbound_audio) {
|
|
|
|
|
SetOutboundRTPStreamStatsFromMediaSenderInfo(voice_sender_info,
|
|
|
|
|
outbound_audio);
|
|
|
|
|
outbound_audio->media_type = "audio";
|
2018-08-28 14:55:03 +02:00
|
|
|
outbound_audio->kind = "audio";
|
2017-02-07 04:59:16 -08:00
|
|
|
if (voice_sender_info.codec_payload_type) {
|
2018-02-15 15:19:50 -08:00
|
|
|
outbound_audio->codec_id = RTCCodecStatsIDFromMidDirectionAndPayload(
|
2021-03-23 17:23:04 +01:00
|
|
|
mid, /*inbound=*/false, *voice_sender_info.codec_payload_type);
|
2017-02-07 04:59:16 -08:00
|
|
|
}
|
2016-11-01 01:50:46 -07:00
|
|
|
// |fir_count|, |pli_count| and |sli_count| are only valid for video and are
|
|
|
|
|
// purposefully left undefined for audio.
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SetOutboundRTPStreamStatsFromVideoSenderInfo(
|
2018-02-15 15:19:50 -08:00
|
|
|
const std::string& mid,
|
2016-11-01 01:50:46 -07:00
|
|
|
const cricket::VideoSenderInfo& video_sender_info,
|
|
|
|
|
RTCOutboundRTPStreamStats* outbound_video) {
|
|
|
|
|
SetOutboundRTPStreamStatsFromMediaSenderInfo(video_sender_info,
|
|
|
|
|
outbound_video);
|
|
|
|
|
outbound_video->media_type = "video";
|
2018-08-28 14:55:03 +02:00
|
|
|
outbound_video->kind = "video";
|
2017-02-07 04:59:16 -08:00
|
|
|
if (video_sender_info.codec_payload_type) {
|
2018-02-15 15:19:50 -08:00
|
|
|
outbound_video->codec_id = RTCCodecStatsIDFromMidDirectionAndPayload(
|
2021-03-23 17:23:04 +01:00
|
|
|
mid, /*inbound=*/false, *video_sender_info.codec_payload_type);
|
2017-02-07 04:59:16 -08:00
|
|
|
}
|
2016-11-01 01:50:46 -07:00
|
|
|
outbound_video->fir_count =
|
|
|
|
|
static_cast<uint32_t>(video_sender_info.firs_rcvd);
|
|
|
|
|
outbound_video->pli_count =
|
|
|
|
|
static_cast<uint32_t>(video_sender_info.plis_rcvd);
|
|
|
|
|
outbound_video->nack_count =
|
|
|
|
|
static_cast<uint32_t>(video_sender_info.nacks_rcvd);
|
2017-01-02 08:35:13 -08:00
|
|
|
if (video_sender_info.qp_sum)
|
|
|
|
|
outbound_video->qp_sum = *video_sender_info.qp_sum;
|
|
|
|
|
outbound_video->frames_encoded = video_sender_info.frames_encoded;
|
2019-06-27 14:29:34 +02:00
|
|
|
outbound_video->key_frames_encoded = video_sender_info.key_frames_encoded;
|
2019-04-08 16:14:23 +02:00
|
|
|
outbound_video->total_encode_time =
|
|
|
|
|
static_cast<double>(video_sender_info.total_encode_time_ms) /
|
|
|
|
|
rtc::kNumMillisecsPerSec;
|
2019-05-20 15:15:38 +02:00
|
|
|
outbound_video->total_encoded_bytes_target =
|
|
|
|
|
video_sender_info.total_encoded_bytes_target;
|
2020-06-10 17:53:39 +03:00
|
|
|
if (video_sender_info.send_frame_width > 0) {
|
|
|
|
|
outbound_video->frame_width =
|
|
|
|
|
static_cast<uint32_t>(video_sender_info.send_frame_width);
|
|
|
|
|
}
|
|
|
|
|
if (video_sender_info.send_frame_height > 0) {
|
|
|
|
|
outbound_video->frame_height =
|
|
|
|
|
static_cast<uint32_t>(video_sender_info.send_frame_height);
|
|
|
|
|
}
|
|
|
|
|
if (video_sender_info.framerate_sent > 0) {
|
|
|
|
|
outbound_video->frames_per_second = video_sender_info.framerate_sent;
|
Reland "Improve outbound-rtp statistics for simulcast"
This reverts commit 9a925c9ce33a6ccdd11b545b11ba68e985c2a65d.
Reason for revert: The original CL is updated in PS #2 to
fix the googRtt issue which was that when the legacy sender
stats were put in "aggregated_senders" we forgot to update
rtt_ms the same way that we do it for "senders".
Original change's description:
> Revert "Improve outbound-rtp statistics for simulcast"
>
> This reverts commit da6cda839dac7d9d18eba8d365188fa94831e0b1.
>
> Reason for revert: Breaks googRtt in legacy getStats API
>
> Original change's description:
> > Improve outbound-rtp statistics for simulcast
> >
> > Bug: webrtc:9547
> > Change-Id: Iec4eb976aa11ee743805425bedb77dcea7c2c9be
> > Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/168120
> > Reviewed-by: Sebastian Jansson <srte@webrtc.org>
> > Reviewed-by: Erik Språng <sprang@webrtc.org>
> > Reviewed-by: Henrik Boström <hbos@webrtc.org>
> > Reviewed-by: Harald Alvestrand <hta@webrtc.org>
> > Commit-Queue: Eldar Rello <elrello@microsoft.com>
> > Cr-Commit-Position: refs/heads/master@{#31097}
>
> TBR=hbos@webrtc.org,sprang@webrtc.org,stefan@webrtc.org,srte@webrtc.org,hta@webrtc.org,elrello@microsoft.com
>
> # Not skipping CQ checks because original CL landed > 1 day ago.
>
> Bug: webrtc:9547
> Change-Id: I06673328c2a5293a7eef03b3aaf2ded9d13df1b3
> Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/174443
> Reviewed-by: Henrik Boström <hbos@webrtc.org>
> Commit-Queue: Henrik Boström <hbos@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#31165}
TBR=hbos@webrtc.org,sprang@webrtc.org,stefan@webrtc.org,srte@webrtc.org,hta@webrtc.org,elrello@microsoft.com
# Not skipping CQ checks because this is a reland.
Bug: webrtc:9547
Change-Id: I723744c496c3c65f95ab6a8940862c8b9f544338
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/174480
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Reviewed-by: Henrik Boström <hbos@webrtc.org>
Commit-Queue: Henrik Boström <hbos@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#31169}
2020-05-05 15:54:46 +02:00
|
|
|
}
|
2020-06-10 17:53:39 +03:00
|
|
|
outbound_video->frames_sent = video_sender_info.frames_sent;
|
|
|
|
|
outbound_video->huge_frames_sent = video_sender_info.huge_frames_sent;
|
2019-05-16 18:38:20 +02:00
|
|
|
outbound_video->total_packet_send_delay =
|
|
|
|
|
static_cast<double>(video_sender_info.total_packet_send_delay_ms) /
|
|
|
|
|
rtc::kNumMillisecsPerSec;
|
2019-05-28 17:42:38 +02:00
|
|
|
outbound_video->quality_limitation_reason =
|
|
|
|
|
QualityLimitationReasonToRTCQualityLimitationReason(
|
|
|
|
|
video_sender_info.quality_limitation_reason);
|
2019-09-09 11:26:45 +02:00
|
|
|
outbound_video->quality_limitation_resolution_changes =
|
|
|
|
|
video_sender_info.quality_limitation_resolution_changes;
|
2019-04-09 13:59:31 +02:00
|
|
|
// TODO(https://crbug.com/webrtc/10529): When info's |content_info| is
|
|
|
|
|
// optional, support the "unspecified" value.
|
|
|
|
|
if (video_sender_info.content_type == VideoContentType::SCREENSHARE)
|
|
|
|
|
outbound_video->content_type = RTCContentType::kScreenshare;
|
2019-08-16 13:09:51 +02:00
|
|
|
if (!video_sender_info.encoder_implementation_name.empty()) {
|
|
|
|
|
outbound_video->encoder_implementation =
|
|
|
|
|
video_sender_info.encoder_implementation_name;
|
|
|
|
|
}
|
Reland "Improve outbound-rtp statistics for simulcast"
This reverts commit 9a925c9ce33a6ccdd11b545b11ba68e985c2a65d.
Reason for revert: The original CL is updated in PS #2 to
fix the googRtt issue which was that when the legacy sender
stats were put in "aggregated_senders" we forgot to update
rtt_ms the same way that we do it for "senders".
Original change's description:
> Revert "Improve outbound-rtp statistics for simulcast"
>
> This reverts commit da6cda839dac7d9d18eba8d365188fa94831e0b1.
>
> Reason for revert: Breaks googRtt in legacy getStats API
>
> Original change's description:
> > Improve outbound-rtp statistics for simulcast
> >
> > Bug: webrtc:9547
> > Change-Id: Iec4eb976aa11ee743805425bedb77dcea7c2c9be
> > Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/168120
> > Reviewed-by: Sebastian Jansson <srte@webrtc.org>
> > Reviewed-by: Erik Språng <sprang@webrtc.org>
> > Reviewed-by: Henrik Boström <hbos@webrtc.org>
> > Reviewed-by: Harald Alvestrand <hta@webrtc.org>
> > Commit-Queue: Eldar Rello <elrello@microsoft.com>
> > Cr-Commit-Position: refs/heads/master@{#31097}
>
> TBR=hbos@webrtc.org,sprang@webrtc.org,stefan@webrtc.org,srte@webrtc.org,hta@webrtc.org,elrello@microsoft.com
>
> # Not skipping CQ checks because original CL landed > 1 day ago.
>
> Bug: webrtc:9547
> Change-Id: I06673328c2a5293a7eef03b3aaf2ded9d13df1b3
> Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/174443
> Reviewed-by: Henrik Boström <hbos@webrtc.org>
> Commit-Queue: Henrik Boström <hbos@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#31165}
TBR=hbos@webrtc.org,sprang@webrtc.org,stefan@webrtc.org,srte@webrtc.org,hta@webrtc.org,elrello@microsoft.com
# Not skipping CQ checks because this is a reland.
Bug: webrtc:9547
Change-Id: I723744c496c3c65f95ab6a8940862c8b9f544338
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/174480
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Reviewed-by: Henrik Boström <hbos@webrtc.org>
Commit-Queue: Henrik Boström <hbos@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#31169}
2020-05-05 15:54:46 +02:00
|
|
|
if (video_sender_info.rid) {
|
|
|
|
|
outbound_video->rid = *video_sender_info.rid;
|
|
|
|
|
}
|
2016-11-01 01:50:46 -07:00
|
|
|
}
|
|
|
|
|
|
Implement RTCRemoteInboundRtpStreamStats for both audio and video.
This implements the essentials of RTCRemoteInboundRtpStreamStats. This
includes:
- ssrc
- transportId
- codecId
- packetsLost
- jitter
- localId
- roundTripTime
https://w3c.github.io/webrtc-stats/#remoteinboundrtpstats-dict*
The following members are not implemented because they require more
work...
- From RTCReceivedRtpStreamStats: packetsReceived, packetsDiscarded,
packetsRepaired, burstPacketsLost, burstPacketsDiscarded,
burstLossCount, burstDiscardCount, burstLossRate, burstDiscardRate,
gapLossRate and gapDiscardRate.
- From RTCRemoteInboundRtpStreamStats: fractionLost.
Bug: webrtc:10455, webrtc:10456
Change-Id: If2ab0da7105d8c93bba58e14aa93bd22ffe57f1d
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/138067
Commit-Queue: Henrik Boström <hbos@webrtc.org>
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#28073}
2019-05-27 13:40:25 +02:00
|
|
|
std::unique_ptr<RTCRemoteInboundRtpStreamStats>
|
|
|
|
|
ProduceRemoteInboundRtpStreamStatsFromReportBlockData(
|
|
|
|
|
const ReportBlockData& report_block_data,
|
|
|
|
|
cricket::MediaType media_type,
|
2020-07-03 11:08:07 +03:00
|
|
|
const std::map<std::string, RTCOutboundRTPStreamStats*>& outbound_rtps,
|
Implement RTCRemoteInboundRtpStreamStats for both audio and video.
This implements the essentials of RTCRemoteInboundRtpStreamStats. This
includes:
- ssrc
- transportId
- codecId
- packetsLost
- jitter
- localId
- roundTripTime
https://w3c.github.io/webrtc-stats/#remoteinboundrtpstats-dict*
The following members are not implemented because they require more
work...
- From RTCReceivedRtpStreamStats: packetsReceived, packetsDiscarded,
packetsRepaired, burstPacketsLost, burstPacketsDiscarded,
burstLossCount, burstDiscardCount, burstLossRate, burstDiscardRate,
gapLossRate and gapDiscardRate.
- From RTCRemoteInboundRtpStreamStats: fractionLost.
Bug: webrtc:10455, webrtc:10456
Change-Id: If2ab0da7105d8c93bba58e14aa93bd22ffe57f1d
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/138067
Commit-Queue: Henrik Boström <hbos@webrtc.org>
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#28073}
2019-05-27 13:40:25 +02:00
|
|
|
const RTCStatsReport& report) {
|
|
|
|
|
const auto& report_block = report_block_data.report_block();
|
|
|
|
|
// RTCStats' timestamp generally refers to when the metric was sampled, but
|
|
|
|
|
// for "remote-[outbound/inbound]-rtp" it refers to the local time when the
|
|
|
|
|
// Report Block was received.
|
2019-09-17 17:06:18 +02:00
|
|
|
auto remote_inbound = std::make_unique<RTCRemoteInboundRtpStreamStats>(
|
2019-06-24 16:44:51 +02:00
|
|
|
RTCRemoteInboundRtpStreamStatsIdFromSourceSsrc(media_type,
|
|
|
|
|
report_block.source_ssrc),
|
Implement RTCRemoteInboundRtpStreamStats for both audio and video.
This implements the essentials of RTCRemoteInboundRtpStreamStats. This
includes:
- ssrc
- transportId
- codecId
- packetsLost
- jitter
- localId
- roundTripTime
https://w3c.github.io/webrtc-stats/#remoteinboundrtpstats-dict*
The following members are not implemented because they require more
work...
- From RTCReceivedRtpStreamStats: packetsReceived, packetsDiscarded,
packetsRepaired, burstPacketsLost, burstPacketsDiscarded,
burstLossCount, burstDiscardCount, burstLossRate, burstDiscardRate,
gapLossRate and gapDiscardRate.
- From RTCRemoteInboundRtpStreamStats: fractionLost.
Bug: webrtc:10455, webrtc:10456
Change-Id: If2ab0da7105d8c93bba58e14aa93bd22ffe57f1d
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/138067
Commit-Queue: Henrik Boström <hbos@webrtc.org>
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#28073}
2019-05-27 13:40:25 +02:00
|
|
|
/*timestamp=*/report_block_data.report_block_timestamp_utc_us());
|
2019-06-24 16:44:51 +02:00
|
|
|
remote_inbound->ssrc = report_block.source_ssrc;
|
Implement RTCRemoteInboundRtpStreamStats for both audio and video.
This implements the essentials of RTCRemoteInboundRtpStreamStats. This
includes:
- ssrc
- transportId
- codecId
- packetsLost
- jitter
- localId
- roundTripTime
https://w3c.github.io/webrtc-stats/#remoteinboundrtpstats-dict*
The following members are not implemented because they require more
work...
- From RTCReceivedRtpStreamStats: packetsReceived, packetsDiscarded,
packetsRepaired, burstPacketsLost, burstPacketsDiscarded,
burstLossCount, burstDiscardCount, burstLossRate, burstDiscardRate,
gapLossRate and gapDiscardRate.
- From RTCRemoteInboundRtpStreamStats: fractionLost.
Bug: webrtc:10455, webrtc:10456
Change-Id: If2ab0da7105d8c93bba58e14aa93bd22ffe57f1d
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/138067
Commit-Queue: Henrik Boström <hbos@webrtc.org>
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#28073}
2019-05-27 13:40:25 +02:00
|
|
|
remote_inbound->kind =
|
|
|
|
|
media_type == cricket::MEDIA_TYPE_AUDIO ? "audio" : "video";
|
|
|
|
|
remote_inbound->packets_lost = report_block.packets_lost;
|
2021-02-28 23:36:03 -08:00
|
|
|
remote_inbound->fraction_lost =
|
|
|
|
|
static_cast<double>(report_block.fraction_lost) / (1 << 8);
|
Implement RTCRemoteInboundRtpStreamStats for both audio and video.
This implements the essentials of RTCRemoteInboundRtpStreamStats. This
includes:
- ssrc
- transportId
- codecId
- packetsLost
- jitter
- localId
- roundTripTime
https://w3c.github.io/webrtc-stats/#remoteinboundrtpstats-dict*
The following members are not implemented because they require more
work...
- From RTCReceivedRtpStreamStats: packetsReceived, packetsDiscarded,
packetsRepaired, burstPacketsLost, burstPacketsDiscarded,
burstLossCount, burstDiscardCount, burstLossRate, burstDiscardRate,
gapLossRate and gapDiscardRate.
- From RTCRemoteInboundRtpStreamStats: fractionLost.
Bug: webrtc:10455, webrtc:10456
Change-Id: If2ab0da7105d8c93bba58e14aa93bd22ffe57f1d
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/138067
Commit-Queue: Henrik Boström <hbos@webrtc.org>
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#28073}
2019-05-27 13:40:25 +02:00
|
|
|
remote_inbound->round_trip_time =
|
|
|
|
|
static_cast<double>(report_block_data.last_rtt_ms()) /
|
|
|
|
|
rtc::kNumMillisecsPerSec;
|
2021-03-01 11:22:06 -08:00
|
|
|
remote_inbound->total_round_trip_time =
|
|
|
|
|
static_cast<double>(report_block_data.sum_rtt_ms()) /
|
|
|
|
|
rtc::kNumMillisecsPerSec;
|
|
|
|
|
remote_inbound->round_trip_time_measurements =
|
|
|
|
|
report_block_data.num_rtts();
|
Implement RTCRemoteInboundRtpStreamStats for both audio and video.
This implements the essentials of RTCRemoteInboundRtpStreamStats. This
includes:
- ssrc
- transportId
- codecId
- packetsLost
- jitter
- localId
- roundTripTime
https://w3c.github.io/webrtc-stats/#remoteinboundrtpstats-dict*
The following members are not implemented because they require more
work...
- From RTCReceivedRtpStreamStats: packetsReceived, packetsDiscarded,
packetsRepaired, burstPacketsLost, burstPacketsDiscarded,
burstLossCount, burstDiscardCount, burstLossRate, burstDiscardRate,
gapLossRate and gapDiscardRate.
- From RTCRemoteInboundRtpStreamStats: fractionLost.
Bug: webrtc:10455, webrtc:10456
Change-Id: If2ab0da7105d8c93bba58e14aa93bd22ffe57f1d
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/138067
Commit-Queue: Henrik Boström <hbos@webrtc.org>
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#28073}
2019-05-27 13:40:25 +02:00
|
|
|
|
2021-03-23 17:23:04 +01:00
|
|
|
std::string local_id =
|
|
|
|
|
RTCOutboundRTPStreamStatsIDFromSSRC(media_type, report_block.source_ssrc);
|
2019-12-19 13:27:27 +01:00
|
|
|
// Look up local stat from |outbound_rtps| where the pointers are non-const.
|
|
|
|
|
auto local_id_it = outbound_rtps.find(local_id);
|
|
|
|
|
if (local_id_it != outbound_rtps.end()) {
|
Implement RTCRemoteInboundRtpStreamStats for both audio and video.
This implements the essentials of RTCRemoteInboundRtpStreamStats. This
includes:
- ssrc
- transportId
- codecId
- packetsLost
- jitter
- localId
- roundTripTime
https://w3c.github.io/webrtc-stats/#remoteinboundrtpstats-dict*
The following members are not implemented because they require more
work...
- From RTCReceivedRtpStreamStats: packetsReceived, packetsDiscarded,
packetsRepaired, burstPacketsLost, burstPacketsDiscarded,
burstLossCount, burstDiscardCount, burstLossRate, burstDiscardRate,
gapLossRate and gapDiscardRate.
- From RTCRemoteInboundRtpStreamStats: fractionLost.
Bug: webrtc:10455, webrtc:10456
Change-Id: If2ab0da7105d8c93bba58e14aa93bd22ffe57f1d
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/138067
Commit-Queue: Henrik Boström <hbos@webrtc.org>
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#28073}
2019-05-27 13:40:25 +02:00
|
|
|
remote_inbound->local_id = local_id;
|
2019-12-19 13:27:27 +01:00
|
|
|
auto& outbound_rtp = *local_id_it->second;
|
|
|
|
|
outbound_rtp.remote_id = remote_inbound->id();
|
Implement RTCRemoteInboundRtpStreamStats for both audio and video.
This implements the essentials of RTCRemoteInboundRtpStreamStats. This
includes:
- ssrc
- transportId
- codecId
- packetsLost
- jitter
- localId
- roundTripTime
https://w3c.github.io/webrtc-stats/#remoteinboundrtpstats-dict*
The following members are not implemented because they require more
work...
- From RTCReceivedRtpStreamStats: packetsReceived, packetsDiscarded,
packetsRepaired, burstPacketsLost, burstPacketsDiscarded,
burstLossCount, burstDiscardCount, burstLossRate, burstDiscardRate,
gapLossRate and gapDiscardRate.
- From RTCRemoteInboundRtpStreamStats: fractionLost.
Bug: webrtc:10455, webrtc:10456
Change-Id: If2ab0da7105d8c93bba58e14aa93bd22ffe57f1d
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/138067
Commit-Queue: Henrik Boström <hbos@webrtc.org>
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#28073}
2019-05-27 13:40:25 +02:00
|
|
|
// The RTP/RTCP transport is obtained from the
|
|
|
|
|
// RTCOutboundRtpStreamStats's transport.
|
|
|
|
|
const auto* transport_from_id = outbound_rtp.transport_id.is_defined()
|
|
|
|
|
? report.Get(*outbound_rtp.transport_id)
|
|
|
|
|
: nullptr;
|
|
|
|
|
if (transport_from_id) {
|
|
|
|
|
const auto& transport = transport_from_id->cast_to<RTCTransportStats>();
|
|
|
|
|
// If RTP and RTCP are not multiplexed, there is a separate RTCP
|
|
|
|
|
// transport paired with the RTP transport, otherwise the same
|
|
|
|
|
// transport is used for RTCP and RTP.
|
|
|
|
|
remote_inbound->transport_id =
|
|
|
|
|
transport.rtcp_transport_stats_id.is_defined()
|
|
|
|
|
? *transport.rtcp_transport_stats_id
|
|
|
|
|
: *outbound_rtp.transport_id;
|
|
|
|
|
}
|
|
|
|
|
// We're assuming the same codec is used on both ends. However if the
|
|
|
|
|
// codec is switched out on the fly we may have received a Report Block
|
|
|
|
|
// based on the previous codec and there is no way to tell which point in
|
|
|
|
|
// time the codec changed for the remote end.
|
|
|
|
|
const auto* codec_from_id = outbound_rtp.codec_id.is_defined()
|
|
|
|
|
? report.Get(*outbound_rtp.codec_id)
|
|
|
|
|
: nullptr;
|
|
|
|
|
if (codec_from_id) {
|
|
|
|
|
remote_inbound->codec_id = *outbound_rtp.codec_id;
|
|
|
|
|
const auto& codec = codec_from_id->cast_to<RTCCodecStats>();
|
|
|
|
|
if (codec.clock_rate.is_defined()) {
|
|
|
|
|
// The Report Block jitter is expressed in RTP timestamp units
|
|
|
|
|
// (https://tools.ietf.org/html/rfc3550#section-6.4.1). To convert this
|
|
|
|
|
// to seconds we divide by the codec's clock rate.
|
|
|
|
|
remote_inbound->jitter =
|
|
|
|
|
static_cast<double>(report_block.jitter) / *codec.clock_rate;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return remote_inbound;
|
|
|
|
|
}
|
|
|
|
|
|
2016-10-28 05:14:53 -07:00
|
|
|
void ProduceCertificateStatsFromSSLCertificateStats(
|
|
|
|
|
int64_t timestamp_us,
|
|
|
|
|
const rtc::SSLCertificateStats& certificate_stats,
|
|
|
|
|
RTCStatsReport* report) {
|
|
|
|
|
RTCCertificateStats* prev_certificate_stats = nullptr;
|
|
|
|
|
for (const rtc::SSLCertificateStats* s = &certificate_stats; s;
|
|
|
|
|
s = s->issuer.get()) {
|
2016-12-21 01:29:05 -08:00
|
|
|
std::string certificate_stats_id =
|
|
|
|
|
RTCCertificateIDFromFingerprint(s->fingerprint);
|
|
|
|
|
// It is possible for the same certificate to show up multiple times, e.g.
|
|
|
|
|
// if local and remote side use the same certificate in a loopback call.
|
|
|
|
|
// If the report already contains stats for this certificate, skip it.
|
|
|
|
|
if (report->Get(certificate_stats_id)) {
|
|
|
|
|
RTC_DCHECK_EQ(s, &certificate_stats);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2016-10-28 05:14:53 -07:00
|
|
|
RTCCertificateStats* certificate_stats =
|
2016-12-21 01:29:05 -08:00
|
|
|
new RTCCertificateStats(certificate_stats_id, timestamp_us);
|
2016-10-28 05:14:53 -07:00
|
|
|
certificate_stats->fingerprint = s->fingerprint;
|
|
|
|
|
certificate_stats->fingerprint_algorithm = s->fingerprint_algorithm;
|
|
|
|
|
certificate_stats->base64_certificate = s->base64_certificate;
|
|
|
|
|
if (prev_certificate_stats)
|
|
|
|
|
prev_certificate_stats->issuer_certificate_id = certificate_stats->id();
|
|
|
|
|
report->AddStats(std::unique_ptr<RTCCertificateStats>(certificate_stats));
|
|
|
|
|
prev_certificate_stats = certificate_stats;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const std::string& ProduceIceCandidateStats(int64_t timestamp_us,
|
|
|
|
|
const cricket::Candidate& candidate,
|
|
|
|
|
bool is_local,
|
2017-01-02 09:59:31 -08:00
|
|
|
const std::string& transport_id,
|
|
|
|
|
RTCStatsReport* report) {
|
2016-10-28 05:14:53 -07:00
|
|
|
const std::string& id = "RTCIceCandidate_" + candidate.id();
|
|
|
|
|
const RTCStats* stats = report->Get(id);
|
|
|
|
|
if (!stats) {
|
|
|
|
|
std::unique_ptr<RTCIceCandidateStats> candidate_stats;
|
|
|
|
|
if (is_local)
|
|
|
|
|
candidate_stats.reset(new RTCLocalIceCandidateStats(id, timestamp_us));
|
|
|
|
|
else
|
|
|
|
|
candidate_stats.reset(new RTCRemoteIceCandidateStats(id, timestamp_us));
|
2017-01-02 09:59:31 -08:00
|
|
|
candidate_stats->transport_id = transport_id;
|
2017-11-21 10:49:36 -08:00
|
|
|
if (is_local) {
|
|
|
|
|
candidate_stats->network_type =
|
|
|
|
|
NetworkAdapterTypeToStatsType(candidate.network_type());
|
2018-09-27 14:40:08 +02:00
|
|
|
if (candidate.type() == cricket::RELAY_PORT_TYPE) {
|
|
|
|
|
std::string relay_protocol = candidate.relay_protocol();
|
|
|
|
|
RTC_DCHECK(relay_protocol.compare("udp") == 0 ||
|
|
|
|
|
relay_protocol.compare("tcp") == 0 ||
|
|
|
|
|
relay_protocol.compare("tls") == 0);
|
|
|
|
|
candidate_stats->relay_protocol = relay_protocol;
|
|
|
|
|
}
|
2017-11-21 10:49:36 -08:00
|
|
|
} else {
|
|
|
|
|
// We don't expect to know the adapter type of remote candidates.
|
|
|
|
|
RTC_DCHECK_EQ(rtc::ADAPTER_TYPE_UNKNOWN, candidate.network_type());
|
|
|
|
|
}
|
2016-10-28 05:14:53 -07:00
|
|
|
candidate_stats->ip = candidate.address().ipaddr().ToString();
|
2021-03-22 13:22:54 +01:00
|
|
|
candidate_stats->address = candidate.address().ipaddr().ToString();
|
2016-10-28 05:14:53 -07:00
|
|
|
candidate_stats->port = static_cast<int32_t>(candidate.address().port());
|
|
|
|
|
candidate_stats->protocol = candidate.protocol();
|
|
|
|
|
candidate_stats->candidate_type =
|
|
|
|
|
CandidateTypeToRTCIceCandidateType(candidate.type());
|
|
|
|
|
candidate_stats->priority = static_cast<int32_t>(candidate.priority());
|
|
|
|
|
|
|
|
|
|
stats = candidate_stats.get();
|
|
|
|
|
report->AddStats(std::move(candidate_stats));
|
|
|
|
|
}
|
|
|
|
|
RTC_DCHECK_EQ(stats->type(), is_local ? RTCLocalIceCandidateStats::kType
|
|
|
|
|
: RTCRemoteIceCandidateStats::kType);
|
|
|
|
|
return stats->id();
|
|
|
|
|
}
|
|
|
|
|
|
2017-01-20 02:47:10 -08:00
|
|
|
std::unique_ptr<RTCMediaStreamTrackStats>
|
|
|
|
|
ProduceMediaStreamTrackStatsFromVoiceSenderInfo(
|
|
|
|
|
int64_t timestamp_us,
|
|
|
|
|
const AudioTrackInterface& audio_track,
|
2018-01-11 17:18:19 +01:00
|
|
|
const cricket::VoiceSenderInfo& voice_sender_info,
|
|
|
|
|
int attachment_id) {
|
2017-01-20 02:47:10 -08:00
|
|
|
std::unique_ptr<RTCMediaStreamTrackStats> audio_track_stats(
|
|
|
|
|
new RTCMediaStreamTrackStats(
|
2018-01-14 09:18:58 +01:00
|
|
|
RTCMediaStreamTrackStatsIDFromDirectionAndAttachment(kSender,
|
|
|
|
|
attachment_id),
|
2018-01-11 17:18:19 +01:00
|
|
|
timestamp_us, RTCMediaStreamTrackKind::kAudio));
|
2017-01-20 02:47:10 -08:00
|
|
|
SetMediaStreamTrackStatsFromMediaStreamTrackInterface(
|
|
|
|
|
audio_track, audio_track_stats.get());
|
2019-05-22 15:49:42 +02:00
|
|
|
audio_track_stats->media_source_id =
|
|
|
|
|
RTCMediaSourceStatsIDFromKindAndAttachment(cricket::MEDIA_TYPE_AUDIO,
|
|
|
|
|
attachment_id);
|
2017-01-20 02:47:10 -08:00
|
|
|
audio_track_stats->remote_source = false;
|
|
|
|
|
audio_track_stats->detached = false;
|
2017-11-24 17:29:59 +01:00
|
|
|
if (voice_sender_info.apm_statistics.echo_return_loss) {
|
|
|
|
|
audio_track_stats->echo_return_loss =
|
|
|
|
|
*voice_sender_info.apm_statistics.echo_return_loss;
|
2017-01-20 02:47:10 -08:00
|
|
|
}
|
2017-11-24 17:29:59 +01:00
|
|
|
if (voice_sender_info.apm_statistics.echo_return_loss_enhancement) {
|
|
|
|
|
audio_track_stats->echo_return_loss_enhancement =
|
|
|
|
|
*voice_sender_info.apm_statistics.echo_return_loss_enhancement;
|
2017-01-20 02:47:10 -08:00
|
|
|
}
|
|
|
|
|
return audio_track_stats;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::unique_ptr<RTCMediaStreamTrackStats>
|
|
|
|
|
ProduceMediaStreamTrackStatsFromVoiceReceiverInfo(
|
|
|
|
|
int64_t timestamp_us,
|
|
|
|
|
const AudioTrackInterface& audio_track,
|
2018-01-11 17:18:19 +01:00
|
|
|
const cricket::VoiceReceiverInfo& voice_receiver_info,
|
|
|
|
|
int attachment_id) {
|
|
|
|
|
// Since receiver tracks can't be reattached, we use the SSRC as
|
|
|
|
|
// an attachment identifier.
|
2017-01-20 02:47:10 -08:00
|
|
|
std::unique_ptr<RTCMediaStreamTrackStats> audio_track_stats(
|
|
|
|
|
new RTCMediaStreamTrackStats(
|
2018-01-14 09:18:58 +01:00
|
|
|
RTCMediaStreamTrackStatsIDFromDirectionAndAttachment(kReceiver,
|
|
|
|
|
attachment_id),
|
2018-01-11 17:18:19 +01:00
|
|
|
timestamp_us, RTCMediaStreamTrackKind::kAudio));
|
2017-01-20 02:47:10 -08:00
|
|
|
SetMediaStreamTrackStatsFromMediaStreamTrackInterface(
|
|
|
|
|
audio_track, audio_track_stats.get());
|
|
|
|
|
audio_track_stats->remote_source = true;
|
|
|
|
|
audio_track_stats->detached = false;
|
|
|
|
|
if (voice_receiver_info.audio_level >= 0) {
|
|
|
|
|
audio_track_stats->audio_level =
|
|
|
|
|
DoubleAudioLevelFromIntAudioLevel(voice_receiver_info.audio_level);
|
|
|
|
|
}
|
2017-10-02 12:00:34 +02:00
|
|
|
audio_track_stats->jitter_buffer_delay =
|
|
|
|
|
voice_receiver_info.jitter_buffer_delay_seconds;
|
2019-01-15 15:46:29 +01:00
|
|
|
audio_track_stats->jitter_buffer_emitted_count =
|
|
|
|
|
voice_receiver_info.jitter_buffer_emitted_count;
|
2019-04-30 09:45:21 +02:00
|
|
|
audio_track_stats->inserted_samples_for_deceleration =
|
|
|
|
|
voice_receiver_info.inserted_samples_for_deceleration;
|
|
|
|
|
audio_track_stats->removed_samples_for_acceleration =
|
|
|
|
|
voice_receiver_info.removed_samples_for_acceleration;
|
2017-07-14 12:17:49 -07:00
|
|
|
audio_track_stats->total_audio_energy =
|
|
|
|
|
voice_receiver_info.total_output_energy;
|
2017-08-24 17:15:13 -07:00
|
|
|
audio_track_stats->total_samples_received =
|
|
|
|
|
voice_receiver_info.total_samples_received;
|
2017-07-14 12:17:49 -07:00
|
|
|
audio_track_stats->total_samples_duration =
|
|
|
|
|
voice_receiver_info.total_output_duration;
|
2017-08-24 17:15:13 -07:00
|
|
|
audio_track_stats->concealed_samples = voice_receiver_info.concealed_samples;
|
2019-04-30 09:45:21 +02:00
|
|
|
audio_track_stats->silent_concealed_samples =
|
|
|
|
|
voice_receiver_info.silent_concealed_samples;
|
2017-09-18 09:28:20 +02:00
|
|
|
audio_track_stats->concealment_events =
|
|
|
|
|
voice_receiver_info.concealment_events;
|
2018-11-22 17:21:10 +01:00
|
|
|
audio_track_stats->jitter_buffer_flushes =
|
|
|
|
|
voice_receiver_info.jitter_buffer_flushes;
|
2018-11-27 12:52:16 +01:00
|
|
|
audio_track_stats->delayed_packet_outage_samples =
|
|
|
|
|
voice_receiver_info.delayed_packet_outage_samples;
|
2019-03-06 09:18:40 +01:00
|
|
|
audio_track_stats->relative_packet_arrival_delay =
|
|
|
|
|
voice_receiver_info.relative_packet_arrival_delay_seconds;
|
2020-03-11 11:18:54 +01:00
|
|
|
audio_track_stats->jitter_buffer_target_delay =
|
|
|
|
|
voice_receiver_info.jitter_buffer_target_delay_seconds;
|
2019-04-29 17:00:46 +02:00
|
|
|
audio_track_stats->interruption_count =
|
|
|
|
|
voice_receiver_info.interruption_count >= 0
|
|
|
|
|
? voice_receiver_info.interruption_count
|
|
|
|
|
: 0;
|
|
|
|
|
audio_track_stats->total_interruption_duration =
|
|
|
|
|
static_cast<double>(voice_receiver_info.total_interruption_duration_ms) /
|
|
|
|
|
rtc::kNumMillisecsPerSec;
|
2017-01-20 02:47:10 -08:00
|
|
|
return audio_track_stats;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::unique_ptr<RTCMediaStreamTrackStats>
|
|
|
|
|
ProduceMediaStreamTrackStatsFromVideoSenderInfo(
|
|
|
|
|
int64_t timestamp_us,
|
|
|
|
|
const VideoTrackInterface& video_track,
|
2018-01-11 17:18:19 +01:00
|
|
|
const cricket::VideoSenderInfo& video_sender_info,
|
|
|
|
|
int attachment_id) {
|
2017-01-20 02:47:10 -08:00
|
|
|
std::unique_ptr<RTCMediaStreamTrackStats> video_track_stats(
|
|
|
|
|
new RTCMediaStreamTrackStats(
|
2018-01-14 09:18:58 +01:00
|
|
|
RTCMediaStreamTrackStatsIDFromDirectionAndAttachment(kSender,
|
|
|
|
|
attachment_id),
|
2018-01-11 17:18:19 +01:00
|
|
|
timestamp_us, RTCMediaStreamTrackKind::kVideo));
|
2017-01-20 02:47:10 -08:00
|
|
|
SetMediaStreamTrackStatsFromMediaStreamTrackInterface(
|
|
|
|
|
video_track, video_track_stats.get());
|
2019-05-22 15:49:42 +02:00
|
|
|
video_track_stats->media_source_id =
|
|
|
|
|
RTCMediaSourceStatsIDFromKindAndAttachment(cricket::MEDIA_TYPE_VIDEO,
|
|
|
|
|
attachment_id);
|
2017-01-20 02:47:10 -08:00
|
|
|
video_track_stats->remote_source = false;
|
|
|
|
|
video_track_stats->detached = false;
|
|
|
|
|
video_track_stats->frame_width =
|
|
|
|
|
static_cast<uint32_t>(video_sender_info.send_frame_width);
|
|
|
|
|
video_track_stats->frame_height =
|
|
|
|
|
static_cast<uint32_t>(video_sender_info.send_frame_height);
|
2017-01-20 06:14:25 -08:00
|
|
|
// TODO(hbos): Will reduce this by frames dropped due to congestion control
|
2018-01-02 14:08:34 +01:00
|
|
|
// when available. https://crbug.com/659137
|
2017-01-20 06:14:25 -08:00
|
|
|
video_track_stats->frames_sent = video_sender_info.frames_encoded;
|
2018-02-28 16:35:03 +01:00
|
|
|
video_track_stats->huge_frames_sent = video_sender_info.huge_frames_sent;
|
2017-01-20 02:47:10 -08:00
|
|
|
return video_track_stats;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::unique_ptr<RTCMediaStreamTrackStats>
|
|
|
|
|
ProduceMediaStreamTrackStatsFromVideoReceiverInfo(
|
|
|
|
|
int64_t timestamp_us,
|
|
|
|
|
const VideoTrackInterface& video_track,
|
2018-01-11 17:18:19 +01:00
|
|
|
const cricket::VideoReceiverInfo& video_receiver_info,
|
|
|
|
|
int attachment_id) {
|
2017-01-20 02:47:10 -08:00
|
|
|
std::unique_ptr<RTCMediaStreamTrackStats> video_track_stats(
|
|
|
|
|
new RTCMediaStreamTrackStats(
|
2018-01-14 09:18:58 +01:00
|
|
|
RTCMediaStreamTrackStatsIDFromDirectionAndAttachment(kReceiver,
|
|
|
|
|
|
|
|
|
|
attachment_id),
|
2018-01-11 17:18:19 +01:00
|
|
|
timestamp_us, RTCMediaStreamTrackKind::kVideo));
|
2017-01-20 02:47:10 -08:00
|
|
|
SetMediaStreamTrackStatsFromMediaStreamTrackInterface(
|
|
|
|
|
video_track, video_track_stats.get());
|
|
|
|
|
video_track_stats->remote_source = true;
|
|
|
|
|
video_track_stats->detached = false;
|
|
|
|
|
if (video_receiver_info.frame_width > 0 &&
|
|
|
|
|
video_receiver_info.frame_height > 0) {
|
|
|
|
|
video_track_stats->frame_width =
|
|
|
|
|
static_cast<uint32_t>(video_receiver_info.frame_width);
|
|
|
|
|
video_track_stats->frame_height =
|
|
|
|
|
static_cast<uint32_t>(video_receiver_info.frame_height);
|
|
|
|
|
}
|
2019-05-28 17:38:08 +02:00
|
|
|
video_track_stats->jitter_buffer_delay =
|
|
|
|
|
video_receiver_info.jitter_buffer_delay_seconds;
|
|
|
|
|
video_track_stats->jitter_buffer_emitted_count =
|
|
|
|
|
video_receiver_info.jitter_buffer_emitted_count;
|
2017-01-20 03:56:50 -08:00
|
|
|
video_track_stats->frames_received = video_receiver_info.frames_received;
|
2017-01-20 07:39:09 -08:00
|
|
|
// TODO(hbos): When we support receiving simulcast, this should be the total
|
|
|
|
|
// number of frames correctly decoded, independent of which SSRC it was
|
|
|
|
|
// received from. Since we don't support that, this is correct and is the same
|
2018-01-02 14:08:34 +01:00
|
|
|
// value as "RTCInboundRTPStreamStats.framesDecoded". https://crbug.com/659137
|
2017-01-20 07:39:09 -08:00
|
|
|
video_track_stats->frames_decoded = video_receiver_info.frames_decoded;
|
2019-08-26 15:04:43 +02:00
|
|
|
video_track_stats->frames_dropped = video_receiver_info.frames_dropped;
|
2019-01-31 16:45:42 +01:00
|
|
|
video_track_stats->freeze_count = video_receiver_info.freeze_count;
|
|
|
|
|
video_track_stats->pause_count = video_receiver_info.pause_count;
|
|
|
|
|
video_track_stats->total_freezes_duration =
|
|
|
|
|
static_cast<double>(video_receiver_info.total_freezes_duration_ms) /
|
|
|
|
|
rtc::kNumMillisecsPerSec;
|
|
|
|
|
video_track_stats->total_pauses_duration =
|
|
|
|
|
static_cast<double>(video_receiver_info.total_pauses_duration_ms) /
|
|
|
|
|
rtc::kNumMillisecsPerSec;
|
|
|
|
|
video_track_stats->total_frames_duration =
|
|
|
|
|
static_cast<double>(video_receiver_info.total_frames_duration_ms) /
|
|
|
|
|
rtc::kNumMillisecsPerSec;
|
|
|
|
|
video_track_stats->sum_squared_frame_durations =
|
|
|
|
|
video_receiver_info.sum_squared_frame_durations;
|
|
|
|
|
|
2017-01-20 02:47:10 -08:00
|
|
|
return video_track_stats;
|
|
|
|
|
}
|
|
|
|
|
|
2018-01-02 14:08:34 +01:00
|
|
|
void ProduceSenderMediaTrackStats(
|
2016-11-08 06:29:22 -08:00
|
|
|
int64_t timestamp_us,
|
2017-01-20 02:47:10 -08:00
|
|
|
const TrackMediaInfoMap& track_media_info_map,
|
2018-02-15 15:19:50 -08:00
|
|
|
std::vector<rtc::scoped_refptr<RtpSenderInternal>> senders,
|
2016-11-08 06:29:22 -08:00
|
|
|
RTCStatsReport* report) {
|
2018-01-02 14:08:34 +01:00
|
|
|
// This function iterates over the senders to generate outgoing track stats.
|
|
|
|
|
|
2016-11-08 06:29:22 -08:00
|
|
|
// TODO(hbos): Return stats of detached tracks. We have to perform stats
|
|
|
|
|
// gathering at the time of detachment to get accurate stats and timestamps.
|
2018-01-02 14:08:34 +01:00
|
|
|
// https://crbug.com/659137
|
2019-01-27 17:29:42 +01:00
|
|
|
for (const auto& sender : senders) {
|
2018-01-02 14:08:34 +01:00
|
|
|
if (sender->media_type() == cricket::MEDIA_TYPE_AUDIO) {
|
|
|
|
|
AudioTrackInterface* track =
|
|
|
|
|
static_cast<AudioTrackInterface*>(sender->track().get());
|
|
|
|
|
if (!track)
|
|
|
|
|
continue;
|
2018-01-23 15:28:16 +01:00
|
|
|
cricket::VoiceSenderInfo null_sender_info;
|
|
|
|
|
const cricket::VoiceSenderInfo* voice_sender_info = &null_sender_info;
|
|
|
|
|
// TODO(hta): Checking on ssrc is not proper. There should be a way
|
|
|
|
|
// to see from a sender whether it's connected or not.
|
|
|
|
|
// Related to https://crbug.com/8694 (using ssrc 0 to indicate "none")
|
2018-02-15 15:19:50 -08:00
|
|
|
if (sender->ssrc() != 0) {
|
2018-01-30 14:43:29 +01:00
|
|
|
// When pc.close is called, sender info is discarded, so
|
|
|
|
|
// we generate zeroes instead. Bug: It should be retained.
|
|
|
|
|
// https://crbug.com/807174
|
2018-02-15 15:19:50 -08:00
|
|
|
const cricket::VoiceSenderInfo* sender_info =
|
2018-01-23 15:28:16 +01:00
|
|
|
track_media_info_map.GetVoiceSenderInfoBySsrc(sender->ssrc());
|
2018-01-30 14:43:29 +01:00
|
|
|
if (sender_info) {
|
|
|
|
|
voice_sender_info = sender_info;
|
|
|
|
|
} else {
|
|
|
|
|
RTC_LOG(LS_INFO)
|
|
|
|
|
<< "RTCStatsCollector: No voice sender info for sender with ssrc "
|
|
|
|
|
<< sender->ssrc();
|
|
|
|
|
}
|
2018-01-23 15:28:16 +01:00
|
|
|
}
|
2018-01-02 14:08:34 +01:00
|
|
|
std::unique_ptr<RTCMediaStreamTrackStats> audio_track_stats =
|
2018-01-11 17:18:19 +01:00
|
|
|
ProduceMediaStreamTrackStatsFromVoiceSenderInfo(
|
|
|
|
|
timestamp_us, *track, *voice_sender_info, sender->AttachmentId());
|
2018-01-02 14:08:34 +01:00
|
|
|
report->AddStats(std::move(audio_track_stats));
|
|
|
|
|
} else if (sender->media_type() == cricket::MEDIA_TYPE_VIDEO) {
|
|
|
|
|
VideoTrackInterface* track =
|
|
|
|
|
static_cast<VideoTrackInterface*>(sender->track().get());
|
|
|
|
|
if (!track)
|
|
|
|
|
continue;
|
2018-01-23 15:28:16 +01:00
|
|
|
cricket::VideoSenderInfo null_sender_info;
|
|
|
|
|
const cricket::VideoSenderInfo* video_sender_info = &null_sender_info;
|
|
|
|
|
// TODO(hta): Check on state not ssrc when state is available
|
2018-01-30 14:43:29 +01:00
|
|
|
// Related to https://bugs.webrtc.org/8694 (using ssrc 0 to indicate
|
|
|
|
|
// "none")
|
2018-02-15 15:19:50 -08:00
|
|
|
if (sender->ssrc() != 0) {
|
2018-01-30 14:43:29 +01:00
|
|
|
// When pc.close is called, sender info is discarded, so
|
|
|
|
|
// we generate zeroes instead. Bug: It should be retained.
|
|
|
|
|
// https://crbug.com/807174
|
2018-02-15 15:19:50 -08:00
|
|
|
const cricket::VideoSenderInfo* sender_info =
|
2018-01-23 15:28:16 +01:00
|
|
|
track_media_info_map.GetVideoSenderInfoBySsrc(sender->ssrc());
|
2018-01-30 14:43:29 +01:00
|
|
|
if (sender_info) {
|
|
|
|
|
video_sender_info = sender_info;
|
|
|
|
|
} else {
|
|
|
|
|
RTC_LOG(LS_INFO) << "No video sender info for sender with ssrc "
|
|
|
|
|
<< sender->ssrc();
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-01-02 14:08:34 +01:00
|
|
|
std::unique_ptr<RTCMediaStreamTrackStats> video_track_stats =
|
2018-01-11 17:18:19 +01:00
|
|
|
ProduceMediaStreamTrackStatsFromVideoSenderInfo(
|
|
|
|
|
timestamp_us, *track, *video_sender_info, sender->AttachmentId());
|
2018-01-02 14:08:34 +01:00
|
|
|
report->AddStats(std::move(video_track_stats));
|
|
|
|
|
} else {
|
|
|
|
|
RTC_NOTREACHED();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ProduceReceiverMediaTrackStats(
|
|
|
|
|
int64_t timestamp_us,
|
|
|
|
|
const TrackMediaInfoMap& track_media_info_map,
|
2018-02-15 15:19:50 -08:00
|
|
|
std::vector<rtc::scoped_refptr<RtpReceiverInternal>> receivers,
|
2018-01-02 14:08:34 +01:00
|
|
|
RTCStatsReport* report) {
|
|
|
|
|
// This function iterates over the receivers to find the remote tracks.
|
2019-01-27 17:29:42 +01:00
|
|
|
for (const auto& receiver : receivers) {
|
2018-01-02 14:08:34 +01:00
|
|
|
if (receiver->media_type() == cricket::MEDIA_TYPE_AUDIO) {
|
|
|
|
|
AudioTrackInterface* track =
|
|
|
|
|
static_cast<AudioTrackInterface*>(receiver->track().get());
|
|
|
|
|
const cricket::VoiceReceiverInfo* voice_receiver_info =
|
|
|
|
|
track_media_info_map.GetVoiceReceiverInfo(*track);
|
|
|
|
|
if (!voice_receiver_info) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
std::unique_ptr<RTCMediaStreamTrackStats> audio_track_stats =
|
|
|
|
|
ProduceMediaStreamTrackStatsFromVoiceReceiverInfo(
|
2018-01-11 17:18:19 +01:00
|
|
|
timestamp_us, *track, *voice_receiver_info,
|
|
|
|
|
receiver->AttachmentId());
|
2018-01-02 14:08:34 +01:00
|
|
|
report->AddStats(std::move(audio_track_stats));
|
|
|
|
|
} else if (receiver->media_type() == cricket::MEDIA_TYPE_VIDEO) {
|
|
|
|
|
VideoTrackInterface* track =
|
|
|
|
|
static_cast<VideoTrackInterface*>(receiver->track().get());
|
|
|
|
|
const cricket::VideoReceiverInfo* video_receiver_info =
|
|
|
|
|
track_media_info_map.GetVideoReceiverInfo(*track);
|
|
|
|
|
if (!video_receiver_info) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
std::unique_ptr<RTCMediaStreamTrackStats> video_track_stats =
|
|
|
|
|
ProduceMediaStreamTrackStatsFromVideoReceiverInfo(
|
2018-01-11 17:18:19 +01:00
|
|
|
timestamp_us, *track, *video_receiver_info,
|
|
|
|
|
receiver->AttachmentId());
|
2018-01-02 14:08:34 +01:00
|
|
|
report->AddStats(std::move(video_track_stats));
|
|
|
|
|
} else {
|
|
|
|
|
RTC_NOTREACHED();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-03-19 13:52:56 +01:00
|
|
|
rtc::scoped_refptr<RTCStatsReport> CreateReportFilteredBySelector(
|
|
|
|
|
bool filter_by_sender_selector,
|
|
|
|
|
rtc::scoped_refptr<const RTCStatsReport> report,
|
|
|
|
|
rtc::scoped_refptr<RtpSenderInternal> sender_selector,
|
|
|
|
|
rtc::scoped_refptr<RtpReceiverInternal> receiver_selector) {
|
|
|
|
|
std::vector<std::string> rtpstream_ids;
|
|
|
|
|
if (filter_by_sender_selector) {
|
|
|
|
|
// Filter mode: RTCStatsCollector::RequestInfo::kSenderSelector
|
|
|
|
|
if (sender_selector) {
|
|
|
|
|
// Find outbound-rtp(s) of the sender, i.e. the outbound-rtp(s) that
|
|
|
|
|
// reference the sender stats.
|
|
|
|
|
// Because we do not implement sender stats, we look at outbound-rtp(s)
|
|
|
|
|
// that reference the track attachment stats for the sender instead.
|
|
|
|
|
std::string track_id =
|
|
|
|
|
RTCMediaStreamTrackStatsIDFromDirectionAndAttachment(
|
|
|
|
|
kSender, sender_selector->AttachmentId());
|
|
|
|
|
for (const auto& stats : *report) {
|
|
|
|
|
if (stats.type() != RTCOutboundRTPStreamStats::kType)
|
|
|
|
|
continue;
|
|
|
|
|
const auto& outbound_rtp = stats.cast_to<RTCOutboundRTPStreamStats>();
|
|
|
|
|
if (outbound_rtp.track_id.is_defined() &&
|
|
|
|
|
*outbound_rtp.track_id == track_id) {
|
|
|
|
|
rtpstream_ids.push_back(outbound_rtp.id());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// Filter mode: RTCStatsCollector::RequestInfo::kReceiverSelector
|
|
|
|
|
if (receiver_selector) {
|
|
|
|
|
// Find inbound-rtp(s) of the receiver, i.e. the inbound-rtp(s) that
|
|
|
|
|
// reference the receiver stats.
|
|
|
|
|
// Because we do not implement receiver stats, we look at inbound-rtp(s)
|
|
|
|
|
// that reference the track attachment stats for the receiver instead.
|
|
|
|
|
std::string track_id =
|
|
|
|
|
RTCMediaStreamTrackStatsIDFromDirectionAndAttachment(
|
|
|
|
|
kReceiver, receiver_selector->AttachmentId());
|
|
|
|
|
for (const auto& stats : *report) {
|
|
|
|
|
if (stats.type() != RTCInboundRTPStreamStats::kType)
|
|
|
|
|
continue;
|
|
|
|
|
const auto& inbound_rtp = stats.cast_to<RTCInboundRTPStreamStats>();
|
|
|
|
|
if (inbound_rtp.track_id.is_defined() &&
|
|
|
|
|
*inbound_rtp.track_id == track_id) {
|
|
|
|
|
rtpstream_ids.push_back(inbound_rtp.id());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (rtpstream_ids.empty())
|
|
|
|
|
return RTCStatsReport::Create(report->timestamp_us());
|
|
|
|
|
return TakeReferencedStats(report->Copy(), rtpstream_ids);
|
|
|
|
|
}
|
|
|
|
|
|
2016-10-18 12:48:31 -07:00
|
|
|
} // namespace
|
|
|
|
|
|
2018-03-19 13:52:56 +01:00
|
|
|
RTCStatsCollector::RequestInfo::RequestInfo(
|
|
|
|
|
rtc::scoped_refptr<RTCStatsCollectorCallback> callback)
|
|
|
|
|
: RequestInfo(FilterMode::kAll, std::move(callback), nullptr, nullptr) {}
|
|
|
|
|
|
|
|
|
|
RTCStatsCollector::RequestInfo::RequestInfo(
|
|
|
|
|
rtc::scoped_refptr<RtpSenderInternal> selector,
|
|
|
|
|
rtc::scoped_refptr<RTCStatsCollectorCallback> callback)
|
|
|
|
|
: RequestInfo(FilterMode::kSenderSelector,
|
|
|
|
|
std::move(callback),
|
|
|
|
|
std::move(selector),
|
|
|
|
|
nullptr) {}
|
|
|
|
|
|
|
|
|
|
RTCStatsCollector::RequestInfo::RequestInfo(
|
|
|
|
|
rtc::scoped_refptr<RtpReceiverInternal> selector,
|
|
|
|
|
rtc::scoped_refptr<RTCStatsCollectorCallback> callback)
|
|
|
|
|
: RequestInfo(FilterMode::kReceiverSelector,
|
|
|
|
|
std::move(callback),
|
|
|
|
|
nullptr,
|
|
|
|
|
std::move(selector)) {}
|
|
|
|
|
|
|
|
|
|
RTCStatsCollector::RequestInfo::RequestInfo(
|
|
|
|
|
RTCStatsCollector::RequestInfo::FilterMode filter_mode,
|
|
|
|
|
rtc::scoped_refptr<RTCStatsCollectorCallback> callback,
|
|
|
|
|
rtc::scoped_refptr<RtpSenderInternal> sender_selector,
|
|
|
|
|
rtc::scoped_refptr<RtpReceiverInternal> receiver_selector)
|
|
|
|
|
: filter_mode_(filter_mode),
|
|
|
|
|
callback_(std::move(callback)),
|
|
|
|
|
sender_selector_(std::move(sender_selector)),
|
|
|
|
|
receiver_selector_(std::move(receiver_selector)) {
|
|
|
|
|
RTC_DCHECK(callback_);
|
|
|
|
|
RTC_DCHECK(!sender_selector_ || !receiver_selector_);
|
|
|
|
|
}
|
|
|
|
|
|
2016-09-05 01:36:50 -07:00
|
|
|
rtc::scoped_refptr<RTCStatsCollector> RTCStatsCollector::Create(
|
2018-01-23 16:38:46 -08:00
|
|
|
PeerConnectionInternal* pc,
|
|
|
|
|
int64_t cache_lifetime_us) {
|
2016-09-05 01:36:50 -07:00
|
|
|
return rtc::scoped_refptr<RTCStatsCollector>(
|
|
|
|
|
new rtc::RefCountedObject<RTCStatsCollector>(pc, cache_lifetime_us));
|
|
|
|
|
}
|
|
|
|
|
|
2018-01-23 16:38:46 -08:00
|
|
|
RTCStatsCollector::RTCStatsCollector(PeerConnectionInternal* pc,
|
2016-09-05 01:36:50 -07:00
|
|
|
int64_t cache_lifetime_us)
|
2016-08-30 14:04:35 -07:00
|
|
|
: pc_(pc),
|
2017-09-29 12:15:02 -07:00
|
|
|
signaling_thread_(pc->signaling_thread()),
|
|
|
|
|
worker_thread_(pc->worker_thread()),
|
|
|
|
|
network_thread_(pc->network_thread()),
|
2016-09-05 01:36:50 -07:00
|
|
|
num_pending_partial_reports_(0),
|
|
|
|
|
partial_report_timestamp_us_(0),
|
Reland "Fix getStats() freeze bug affecting Chromium but not WebRTC standalone."
This is a reland of 05d43c6f7fe497fed0f2c8714e2042dd07a86df2
The original CL got reverted because Chrome did not support IsQuitting() which
triggered a NOTREACHED() inside of a DCHECK. With
https://chromium-review.googlesource.com/c/chromium/src/+/1491620
it is safe to reland this CL.
The only changes between this and the original patch set is that this is now
rebased on top of https://webrtc-review.googlesource.com/c/src/+/124701, i.e.
rtc::PostMessageWithFunctor() has been replaced by rtc::Thread::PostTask().
Original change's description:
> Fix getStats() freeze bug affecting Chromium but not WebRTC standalone.
>
> PeerConnection::Close() is, per-spec, a blocking operation.
> Unfortunately, PeerConnection is implemented to own resources used by
> the network thread, and Close() - on the signaling thread - destroys
> these resources. As such, tasks run in parallel like getStats() get into
> race conditions with Close() unless synchronized. The mechanism in-place
> is RTCStatsCollector::WaitForPendingRequest(), it waits until the
> network thread is done with the in-parallel stats request.
>
> Prior to this CL, this was implemented by performing
> rtc::Thread::ProcessMessages() in a loop until the network thread had
> posted a task on the signaling thread to say that it was done which
> would then get processed by ProcessMessages(). In WebRTC this works, and
> the test is RTCStatsIntegrationTest.GetsStatsWhileClosingPeerConnection.
>
> But because Chromium's thread wrapper does no support
> ProcessMessages(), calling getStats() followed by close() in Chrome
> resulted in waiting forever (https://crbug.com/850907).
>
> In this CL, the process messages loop is removed. Instead, the shared
> resources are guarded by an rtc::Event. WaitForPendingRequest() still
> blocks the signaling thread, but only while shared resources are in use
> by the network thread. After this CL, calling WaitForPendingRequest() no
> longer has any unexpected side-effects since it no longer processes
> other messages that might have been posted on the thread.
>
> The resource ownership and threading model of WebRTC deserves to be
> revisited, but this fixes a common Chromium crash without redesigning
> PeerConnection, in a way that does not cause more blocking than what
> the other PeerConnection methods are already doing.
>
> Note: An alternative to using rtc::Event is to use resource locks and
> to not perform the stats collection on the network thread if the
> request was cancelled before the start of processing, but this has very
> little benefit in terms of performance: once the network thread starts
> collecting the stats, it would use the lock until collection is
> completed, blocking the signaling thread trying to acquire that lock
> anyway. This defeats the purpose and is a riskier change, since
> cancelling partial collection in this inherently racy edge-case would
> have observable differences from the returned stats, which may cause
> more regressions.
>
> Bug: chromium:850907
> Change-Id: Idceeee0bddc0c9d5518b58a2b263abb2bbf47cff
> Reviewed-on: https://webrtc-review.googlesource.com/c/121567
> Commit-Queue: Henrik Boström <hbos@webrtc.org>
> Reviewed-by: Steve Anton <steveanton@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#26707}
TBR=steveanton@webrtc.org
Bug: chromium:850907
Change-Id: I5be7f69f0de65ff1120e4926fbf904def97ea9c0
Reviewed-on: https://webrtc-review.googlesource.com/c/124781
Reviewed-by: Henrik Boström <hbos@webrtc.org>
Reviewed-by: Steve Anton <steveanton@webrtc.org>
Commit-Queue: Henrik Boström <hbos@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#26896}
2019-02-28 09:49:31 +01:00
|
|
|
network_report_event_(true /* manual_reset */,
|
|
|
|
|
true /* initially_signaled */),
|
2016-08-31 07:57:36 -07:00
|
|
|
cache_timestamp_us_(0),
|
|
|
|
|
cache_lifetime_us_(cache_lifetime_us) {
|
2016-08-30 14:04:35 -07:00
|
|
|
RTC_DCHECK(pc_);
|
2016-09-05 01:36:50 -07:00
|
|
|
RTC_DCHECK(signaling_thread_);
|
|
|
|
|
RTC_DCHECK(worker_thread_);
|
|
|
|
|
RTC_DCHECK(network_thread_);
|
2016-08-31 07:57:36 -07:00
|
|
|
RTC_DCHECK_GE(cache_lifetime_us_, 0);
|
2020-07-09 15:32:34 -07:00
|
|
|
pc_->SignalSctpDataChannelCreated().connect(
|
|
|
|
|
this, &RTCStatsCollector::OnSctpDataChannelCreated);
|
2016-08-30 14:04:35 -07:00
|
|
|
}
|
|
|
|
|
|
2016-12-19 05:06:57 -08:00
|
|
|
RTCStatsCollector::~RTCStatsCollector() {
|
|
|
|
|
RTC_DCHECK_EQ(num_pending_partial_reports_, 0);
|
|
|
|
|
}
|
|
|
|
|
|
2016-09-05 01:36:50 -07:00
|
|
|
void RTCStatsCollector::GetStatsReport(
|
|
|
|
|
rtc::scoped_refptr<RTCStatsCollectorCallback> callback) {
|
2018-03-19 13:52:56 +01:00
|
|
|
GetStatsReportInternal(RequestInfo(std::move(callback)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void RTCStatsCollector::GetStatsReport(
|
|
|
|
|
rtc::scoped_refptr<RtpSenderInternal> selector,
|
|
|
|
|
rtc::scoped_refptr<RTCStatsCollectorCallback> callback) {
|
|
|
|
|
GetStatsReportInternal(RequestInfo(std::move(selector), std::move(callback)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void RTCStatsCollector::GetStatsReport(
|
|
|
|
|
rtc::scoped_refptr<RtpReceiverInternal> selector,
|
|
|
|
|
rtc::scoped_refptr<RTCStatsCollectorCallback> callback) {
|
|
|
|
|
GetStatsReportInternal(RequestInfo(std::move(selector), std::move(callback)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void RTCStatsCollector::GetStatsReportInternal(
|
|
|
|
|
RTCStatsCollector::RequestInfo request) {
|
2021-04-08 15:18:05 +02:00
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread_);
|
2018-03-19 13:52:56 +01:00
|
|
|
requests_.push_back(std::move(request));
|
2016-09-05 01:36:50 -07:00
|
|
|
|
2016-08-31 07:57:36 -07:00
|
|
|
// "Now" using a monotonically increasing timer.
|
|
|
|
|
int64_t cache_now_us = rtc::TimeMicros();
|
|
|
|
|
if (cached_report_ &&
|
|
|
|
|
cache_now_us - cache_timestamp_us_ <= cache_lifetime_us_) {
|
2018-03-08 09:53:47 -08:00
|
|
|
// We have a fresh cached report to deliver. Deliver asynchronously, since
|
|
|
|
|
// the caller may not be expecting a synchronous callback, and it avoids
|
|
|
|
|
// reentrancy problems.
|
2018-03-19 13:52:56 +01:00
|
|
|
std::vector<RequestInfo> requests;
|
|
|
|
|
requests.swap(requests_);
|
2021-01-18 09:24:33 +01:00
|
|
|
|
|
|
|
|
// Task subclass to take ownership of the requests.
|
|
|
|
|
// TODO(nisse): Delete when we can use C++14, and do lambda capture with
|
|
|
|
|
// std::move.
|
|
|
|
|
class DeliveryTask : public QueuedTask {
|
|
|
|
|
public:
|
|
|
|
|
DeliveryTask(rtc::scoped_refptr<RTCStatsCollector> collector,
|
|
|
|
|
rtc::scoped_refptr<const RTCStatsReport> cached_report,
|
|
|
|
|
std::vector<RequestInfo> requests)
|
|
|
|
|
: collector_(collector),
|
|
|
|
|
cached_report_(cached_report),
|
|
|
|
|
requests_(std::move(requests)) {}
|
|
|
|
|
bool Run() override {
|
|
|
|
|
collector_->DeliverCachedReport(cached_report_, std::move(requests_));
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
rtc::scoped_refptr<RTCStatsCollector> collector_;
|
|
|
|
|
rtc::scoped_refptr<const RTCStatsReport> cached_report_;
|
|
|
|
|
std::vector<RequestInfo> requests_;
|
|
|
|
|
};
|
|
|
|
|
signaling_thread_->PostTask(std::make_unique<DeliveryTask>(
|
|
|
|
|
this, cached_report_, std::move(requests)));
|
2016-09-05 01:36:50 -07:00
|
|
|
} else if (!num_pending_partial_reports_) {
|
|
|
|
|
// Only start gathering stats if we're not already gathering stats. In the
|
|
|
|
|
// case of already gathering stats, |callback_| will be invoked when there
|
|
|
|
|
// are no more pending partial reports.
|
2016-08-30 14:04:35 -07:00
|
|
|
|
2016-09-05 01:36:50 -07:00
|
|
|
// "Now" using a system clock, relative to the UNIX epoch (Jan 1, 1970,
|
|
|
|
|
// UTC), in microseconds. The system clock could be modified and is not
|
|
|
|
|
// necessarily monotonically increasing.
|
2016-09-13 23:41:47 -07:00
|
|
|
int64_t timestamp_us = rtc::TimeUTCMicros();
|
2016-08-30 14:04:35 -07:00
|
|
|
|
2017-01-02 04:28:51 -08:00
|
|
|
num_pending_partial_reports_ = 2;
|
2016-09-05 01:36:50 -07:00
|
|
|
partial_report_timestamp_us_ = cache_now_us;
|
2016-12-19 04:58:02 -08:00
|
|
|
|
2020-11-13 09:05:21 +01:00
|
|
|
// Prepare |transceiver_stats_infos_| and |call_stats_| for use in
|
2017-01-16 06:16:44 -08:00
|
|
|
// |ProducePartialResultsOnNetworkThread| and
|
|
|
|
|
// |ProducePartialResultsOnSignalingThread|.
|
2020-11-13 09:05:21 +01:00
|
|
|
PrepareTransceiverStatsInfosAndCallStats_s_w();
|
2018-03-30 15:18:41 -07:00
|
|
|
// Prepare |transport_names_| for use in
|
|
|
|
|
// |ProducePartialResultsOnNetworkThread|.
|
|
|
|
|
transport_names_ = PrepareTransportNames_s();
|
2018-02-06 10:34:40 -08:00
|
|
|
|
Reland "Fix getStats() freeze bug affecting Chromium but not WebRTC standalone."
This is a reland of 05d43c6f7fe497fed0f2c8714e2042dd07a86df2
The original CL got reverted because Chrome did not support IsQuitting() which
triggered a NOTREACHED() inside of a DCHECK. With
https://chromium-review.googlesource.com/c/chromium/src/+/1491620
it is safe to reland this CL.
The only changes between this and the original patch set is that this is now
rebased on top of https://webrtc-review.googlesource.com/c/src/+/124701, i.e.
rtc::PostMessageWithFunctor() has been replaced by rtc::Thread::PostTask().
Original change's description:
> Fix getStats() freeze bug affecting Chromium but not WebRTC standalone.
>
> PeerConnection::Close() is, per-spec, a blocking operation.
> Unfortunately, PeerConnection is implemented to own resources used by
> the network thread, and Close() - on the signaling thread - destroys
> these resources. As such, tasks run in parallel like getStats() get into
> race conditions with Close() unless synchronized. The mechanism in-place
> is RTCStatsCollector::WaitForPendingRequest(), it waits until the
> network thread is done with the in-parallel stats request.
>
> Prior to this CL, this was implemented by performing
> rtc::Thread::ProcessMessages() in a loop until the network thread had
> posted a task on the signaling thread to say that it was done which
> would then get processed by ProcessMessages(). In WebRTC this works, and
> the test is RTCStatsIntegrationTest.GetsStatsWhileClosingPeerConnection.
>
> But because Chromium's thread wrapper does no support
> ProcessMessages(), calling getStats() followed by close() in Chrome
> resulted in waiting forever (https://crbug.com/850907).
>
> In this CL, the process messages loop is removed. Instead, the shared
> resources are guarded by an rtc::Event. WaitForPendingRequest() still
> blocks the signaling thread, but only while shared resources are in use
> by the network thread. After this CL, calling WaitForPendingRequest() no
> longer has any unexpected side-effects since it no longer processes
> other messages that might have been posted on the thread.
>
> The resource ownership and threading model of WebRTC deserves to be
> revisited, but this fixes a common Chromium crash without redesigning
> PeerConnection, in a way that does not cause more blocking than what
> the other PeerConnection methods are already doing.
>
> Note: An alternative to using rtc::Event is to use resource locks and
> to not perform the stats collection on the network thread if the
> request was cancelled before the start of processing, but this has very
> little benefit in terms of performance: once the network thread starts
> collecting the stats, it would use the lock until collection is
> completed, blocking the signaling thread trying to acquire that lock
> anyway. This defeats the purpose and is a riskier change, since
> cancelling partial collection in this inherently racy edge-case would
> have observable differences from the returned stats, which may cause
> more regressions.
>
> Bug: chromium:850907
> Change-Id: Idceeee0bddc0c9d5518b58a2b263abb2bbf47cff
> Reviewed-on: https://webrtc-review.googlesource.com/c/121567
> Commit-Queue: Henrik Boström <hbos@webrtc.org>
> Reviewed-by: Steve Anton <steveanton@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#26707}
TBR=steveanton@webrtc.org
Bug: chromium:850907
Change-Id: I5be7f69f0de65ff1120e4926fbf904def97ea9c0
Reviewed-on: https://webrtc-review.googlesource.com/c/124781
Reviewed-by: Henrik Boström <hbos@webrtc.org>
Reviewed-by: Steve Anton <steveanton@webrtc.org>
Commit-Queue: Henrik Boström <hbos@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#26896}
2019-02-28 09:49:31 +01:00
|
|
|
// Don't touch |network_report_| on the signaling thread until
|
|
|
|
|
// ProducePartialResultsOnNetworkThread() has signaled the
|
|
|
|
|
// |network_report_event_|.
|
|
|
|
|
network_report_event_.Reset();
|
2021-01-18 09:24:33 +01:00
|
|
|
rtc::scoped_refptr<RTCStatsCollector> collector(this);
|
|
|
|
|
network_thread_->PostTask(RTC_FROM_HERE, [collector, timestamp_us] {
|
|
|
|
|
collector->ProducePartialResultsOnNetworkThread(timestamp_us);
|
|
|
|
|
});
|
2017-01-02 04:28:51 -08:00
|
|
|
ProducePartialResultsOnSignalingThread(timestamp_us);
|
2016-09-05 01:36:50 -07:00
|
|
|
}
|
2016-08-30 14:04:35 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void RTCStatsCollector::ClearCachedStatsReport() {
|
2021-04-08 15:18:05 +02:00
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread_);
|
2016-08-30 14:04:35 -07:00
|
|
|
cached_report_ = nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
2016-12-19 05:06:57 -08:00
|
|
|
void RTCStatsCollector::WaitForPendingRequest() {
|
2021-04-08 15:18:05 +02:00
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread_);
|
Reland "Fix getStats() freeze bug affecting Chromium but not WebRTC standalone."
This is a reland of 05d43c6f7fe497fed0f2c8714e2042dd07a86df2
The original CL got reverted because Chrome did not support IsQuitting() which
triggered a NOTREACHED() inside of a DCHECK. With
https://chromium-review.googlesource.com/c/chromium/src/+/1491620
it is safe to reland this CL.
The only changes between this and the original patch set is that this is now
rebased on top of https://webrtc-review.googlesource.com/c/src/+/124701, i.e.
rtc::PostMessageWithFunctor() has been replaced by rtc::Thread::PostTask().
Original change's description:
> Fix getStats() freeze bug affecting Chromium but not WebRTC standalone.
>
> PeerConnection::Close() is, per-spec, a blocking operation.
> Unfortunately, PeerConnection is implemented to own resources used by
> the network thread, and Close() - on the signaling thread - destroys
> these resources. As such, tasks run in parallel like getStats() get into
> race conditions with Close() unless synchronized. The mechanism in-place
> is RTCStatsCollector::WaitForPendingRequest(), it waits until the
> network thread is done with the in-parallel stats request.
>
> Prior to this CL, this was implemented by performing
> rtc::Thread::ProcessMessages() in a loop until the network thread had
> posted a task on the signaling thread to say that it was done which
> would then get processed by ProcessMessages(). In WebRTC this works, and
> the test is RTCStatsIntegrationTest.GetsStatsWhileClosingPeerConnection.
>
> But because Chromium's thread wrapper does no support
> ProcessMessages(), calling getStats() followed by close() in Chrome
> resulted in waiting forever (https://crbug.com/850907).
>
> In this CL, the process messages loop is removed. Instead, the shared
> resources are guarded by an rtc::Event. WaitForPendingRequest() still
> blocks the signaling thread, but only while shared resources are in use
> by the network thread. After this CL, calling WaitForPendingRequest() no
> longer has any unexpected side-effects since it no longer processes
> other messages that might have been posted on the thread.
>
> The resource ownership and threading model of WebRTC deserves to be
> revisited, but this fixes a common Chromium crash without redesigning
> PeerConnection, in a way that does not cause more blocking than what
> the other PeerConnection methods are already doing.
>
> Note: An alternative to using rtc::Event is to use resource locks and
> to not perform the stats collection on the network thread if the
> request was cancelled before the start of processing, but this has very
> little benefit in terms of performance: once the network thread starts
> collecting the stats, it would use the lock until collection is
> completed, blocking the signaling thread trying to acquire that lock
> anyway. This defeats the purpose and is a riskier change, since
> cancelling partial collection in this inherently racy edge-case would
> have observable differences from the returned stats, which may cause
> more regressions.
>
> Bug: chromium:850907
> Change-Id: Idceeee0bddc0c9d5518b58a2b263abb2bbf47cff
> Reviewed-on: https://webrtc-review.googlesource.com/c/121567
> Commit-Queue: Henrik Boström <hbos@webrtc.org>
> Reviewed-by: Steve Anton <steveanton@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#26707}
TBR=steveanton@webrtc.org
Bug: chromium:850907
Change-Id: I5be7f69f0de65ff1120e4926fbf904def97ea9c0
Reviewed-on: https://webrtc-review.googlesource.com/c/124781
Reviewed-by: Henrik Boström <hbos@webrtc.org>
Reviewed-by: Steve Anton <steveanton@webrtc.org>
Commit-Queue: Henrik Boström <hbos@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#26896}
2019-02-28 09:49:31 +01:00
|
|
|
// If a request is pending, blocks until the |network_report_event_| is
|
|
|
|
|
// signaled and then delivers the result. Otherwise this is a NO-OP.
|
|
|
|
|
MergeNetworkReport_s();
|
2016-12-19 05:06:57 -08:00
|
|
|
}
|
|
|
|
|
|
2016-09-05 01:36:50 -07:00
|
|
|
void RTCStatsCollector::ProducePartialResultsOnSignalingThread(
|
|
|
|
|
int64_t timestamp_us) {
|
2021-04-08 15:18:05 +02:00
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread_);
|
2020-07-08 11:18:50 +02:00
|
|
|
rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls;
|
|
|
|
|
|
Reland "Fix getStats() freeze bug affecting Chromium but not WebRTC standalone."
This is a reland of 05d43c6f7fe497fed0f2c8714e2042dd07a86df2
The original CL got reverted because Chrome did not support IsQuitting() which
triggered a NOTREACHED() inside of a DCHECK. With
https://chromium-review.googlesource.com/c/chromium/src/+/1491620
it is safe to reland this CL.
The only changes between this and the original patch set is that this is now
rebased on top of https://webrtc-review.googlesource.com/c/src/+/124701, i.e.
rtc::PostMessageWithFunctor() has been replaced by rtc::Thread::PostTask().
Original change's description:
> Fix getStats() freeze bug affecting Chromium but not WebRTC standalone.
>
> PeerConnection::Close() is, per-spec, a blocking operation.
> Unfortunately, PeerConnection is implemented to own resources used by
> the network thread, and Close() - on the signaling thread - destroys
> these resources. As such, tasks run in parallel like getStats() get into
> race conditions with Close() unless synchronized. The mechanism in-place
> is RTCStatsCollector::WaitForPendingRequest(), it waits until the
> network thread is done with the in-parallel stats request.
>
> Prior to this CL, this was implemented by performing
> rtc::Thread::ProcessMessages() in a loop until the network thread had
> posted a task on the signaling thread to say that it was done which
> would then get processed by ProcessMessages(). In WebRTC this works, and
> the test is RTCStatsIntegrationTest.GetsStatsWhileClosingPeerConnection.
>
> But because Chromium's thread wrapper does no support
> ProcessMessages(), calling getStats() followed by close() in Chrome
> resulted in waiting forever (https://crbug.com/850907).
>
> In this CL, the process messages loop is removed. Instead, the shared
> resources are guarded by an rtc::Event. WaitForPendingRequest() still
> blocks the signaling thread, but only while shared resources are in use
> by the network thread. After this CL, calling WaitForPendingRequest() no
> longer has any unexpected side-effects since it no longer processes
> other messages that might have been posted on the thread.
>
> The resource ownership and threading model of WebRTC deserves to be
> revisited, but this fixes a common Chromium crash without redesigning
> PeerConnection, in a way that does not cause more blocking than what
> the other PeerConnection methods are already doing.
>
> Note: An alternative to using rtc::Event is to use resource locks and
> to not perform the stats collection on the network thread if the
> request was cancelled before the start of processing, but this has very
> little benefit in terms of performance: once the network thread starts
> collecting the stats, it would use the lock until collection is
> completed, blocking the signaling thread trying to acquire that lock
> anyway. This defeats the purpose and is a riskier change, since
> cancelling partial collection in this inherently racy edge-case would
> have observable differences from the returned stats, which may cause
> more regressions.
>
> Bug: chromium:850907
> Change-Id: Idceeee0bddc0c9d5518b58a2b263abb2bbf47cff
> Reviewed-on: https://webrtc-review.googlesource.com/c/121567
> Commit-Queue: Henrik Boström <hbos@webrtc.org>
> Reviewed-by: Steve Anton <steveanton@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#26707}
TBR=steveanton@webrtc.org
Bug: chromium:850907
Change-Id: I5be7f69f0de65ff1120e4926fbf904def97ea9c0
Reviewed-on: https://webrtc-review.googlesource.com/c/124781
Reviewed-by: Henrik Boström <hbos@webrtc.org>
Reviewed-by: Steve Anton <steveanton@webrtc.org>
Commit-Queue: Henrik Boström <hbos@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#26896}
2019-02-28 09:49:31 +01:00
|
|
|
partial_report_ = RTCStatsReport::Create(timestamp_us);
|
2016-09-05 01:36:50 -07:00
|
|
|
|
Reland "Fix getStats() freeze bug affecting Chromium but not WebRTC standalone."
This is a reland of 05d43c6f7fe497fed0f2c8714e2042dd07a86df2
The original CL got reverted because Chrome did not support IsQuitting() which
triggered a NOTREACHED() inside of a DCHECK. With
https://chromium-review.googlesource.com/c/chromium/src/+/1491620
it is safe to reland this CL.
The only changes between this and the original patch set is that this is now
rebased on top of https://webrtc-review.googlesource.com/c/src/+/124701, i.e.
rtc::PostMessageWithFunctor() has been replaced by rtc::Thread::PostTask().
Original change's description:
> Fix getStats() freeze bug affecting Chromium but not WebRTC standalone.
>
> PeerConnection::Close() is, per-spec, a blocking operation.
> Unfortunately, PeerConnection is implemented to own resources used by
> the network thread, and Close() - on the signaling thread - destroys
> these resources. As such, tasks run in parallel like getStats() get into
> race conditions with Close() unless synchronized. The mechanism in-place
> is RTCStatsCollector::WaitForPendingRequest(), it waits until the
> network thread is done with the in-parallel stats request.
>
> Prior to this CL, this was implemented by performing
> rtc::Thread::ProcessMessages() in a loop until the network thread had
> posted a task on the signaling thread to say that it was done which
> would then get processed by ProcessMessages(). In WebRTC this works, and
> the test is RTCStatsIntegrationTest.GetsStatsWhileClosingPeerConnection.
>
> But because Chromium's thread wrapper does no support
> ProcessMessages(), calling getStats() followed by close() in Chrome
> resulted in waiting forever (https://crbug.com/850907).
>
> In this CL, the process messages loop is removed. Instead, the shared
> resources are guarded by an rtc::Event. WaitForPendingRequest() still
> blocks the signaling thread, but only while shared resources are in use
> by the network thread. After this CL, calling WaitForPendingRequest() no
> longer has any unexpected side-effects since it no longer processes
> other messages that might have been posted on the thread.
>
> The resource ownership and threading model of WebRTC deserves to be
> revisited, but this fixes a common Chromium crash without redesigning
> PeerConnection, in a way that does not cause more blocking than what
> the other PeerConnection methods are already doing.
>
> Note: An alternative to using rtc::Event is to use resource locks and
> to not perform the stats collection on the network thread if the
> request was cancelled before the start of processing, but this has very
> little benefit in terms of performance: once the network thread starts
> collecting the stats, it would use the lock until collection is
> completed, blocking the signaling thread trying to acquire that lock
> anyway. This defeats the purpose and is a riskier change, since
> cancelling partial collection in this inherently racy edge-case would
> have observable differences from the returned stats, which may cause
> more regressions.
>
> Bug: chromium:850907
> Change-Id: Idceeee0bddc0c9d5518b58a2b263abb2bbf47cff
> Reviewed-on: https://webrtc-review.googlesource.com/c/121567
> Commit-Queue: Henrik Boström <hbos@webrtc.org>
> Reviewed-by: Steve Anton <steveanton@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#26707}
TBR=steveanton@webrtc.org
Bug: chromium:850907
Change-Id: I5be7f69f0de65ff1120e4926fbf904def97ea9c0
Reviewed-on: https://webrtc-review.googlesource.com/c/124781
Reviewed-by: Henrik Boström <hbos@webrtc.org>
Reviewed-by: Steve Anton <steveanton@webrtc.org>
Commit-Queue: Henrik Boström <hbos@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#26896}
2019-02-28 09:49:31 +01:00
|
|
|
ProducePartialResultsOnSignalingThreadImpl(timestamp_us,
|
|
|
|
|
partial_report_.get());
|
2016-09-05 01:36:50 -07:00
|
|
|
|
Reland "Fix getStats() freeze bug affecting Chromium but not WebRTC standalone."
This is a reland of 05d43c6f7fe497fed0f2c8714e2042dd07a86df2
The original CL got reverted because Chrome did not support IsQuitting() which
triggered a NOTREACHED() inside of a DCHECK. With
https://chromium-review.googlesource.com/c/chromium/src/+/1491620
it is safe to reland this CL.
The only changes between this and the original patch set is that this is now
rebased on top of https://webrtc-review.googlesource.com/c/src/+/124701, i.e.
rtc::PostMessageWithFunctor() has been replaced by rtc::Thread::PostTask().
Original change's description:
> Fix getStats() freeze bug affecting Chromium but not WebRTC standalone.
>
> PeerConnection::Close() is, per-spec, a blocking operation.
> Unfortunately, PeerConnection is implemented to own resources used by
> the network thread, and Close() - on the signaling thread - destroys
> these resources. As such, tasks run in parallel like getStats() get into
> race conditions with Close() unless synchronized. The mechanism in-place
> is RTCStatsCollector::WaitForPendingRequest(), it waits until the
> network thread is done with the in-parallel stats request.
>
> Prior to this CL, this was implemented by performing
> rtc::Thread::ProcessMessages() in a loop until the network thread had
> posted a task on the signaling thread to say that it was done which
> would then get processed by ProcessMessages(). In WebRTC this works, and
> the test is RTCStatsIntegrationTest.GetsStatsWhileClosingPeerConnection.
>
> But because Chromium's thread wrapper does no support
> ProcessMessages(), calling getStats() followed by close() in Chrome
> resulted in waiting forever (https://crbug.com/850907).
>
> In this CL, the process messages loop is removed. Instead, the shared
> resources are guarded by an rtc::Event. WaitForPendingRequest() still
> blocks the signaling thread, but only while shared resources are in use
> by the network thread. After this CL, calling WaitForPendingRequest() no
> longer has any unexpected side-effects since it no longer processes
> other messages that might have been posted on the thread.
>
> The resource ownership and threading model of WebRTC deserves to be
> revisited, but this fixes a common Chromium crash without redesigning
> PeerConnection, in a way that does not cause more blocking than what
> the other PeerConnection methods are already doing.
>
> Note: An alternative to using rtc::Event is to use resource locks and
> to not perform the stats collection on the network thread if the
> request was cancelled before the start of processing, but this has very
> little benefit in terms of performance: once the network thread starts
> collecting the stats, it would use the lock until collection is
> completed, blocking the signaling thread trying to acquire that lock
> anyway. This defeats the purpose and is a riskier change, since
> cancelling partial collection in this inherently racy edge-case would
> have observable differences from the returned stats, which may cause
> more regressions.
>
> Bug: chromium:850907
> Change-Id: Idceeee0bddc0c9d5518b58a2b263abb2bbf47cff
> Reviewed-on: https://webrtc-review.googlesource.com/c/121567
> Commit-Queue: Henrik Boström <hbos@webrtc.org>
> Reviewed-by: Steve Anton <steveanton@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#26707}
TBR=steveanton@webrtc.org
Bug: chromium:850907
Change-Id: I5be7f69f0de65ff1120e4926fbf904def97ea9c0
Reviewed-on: https://webrtc-review.googlesource.com/c/124781
Reviewed-by: Henrik Boström <hbos@webrtc.org>
Reviewed-by: Steve Anton <steveanton@webrtc.org>
Commit-Queue: Henrik Boström <hbos@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#26896}
2019-02-28 09:49:31 +01:00
|
|
|
// ProducePartialResultsOnSignalingThread() is running synchronously on the
|
|
|
|
|
// signaling thread, so it is always the first partial result delivered on the
|
|
|
|
|
// signaling thread. The request is not complete until MergeNetworkReport_s()
|
|
|
|
|
// happens; we don't have to do anything here.
|
|
|
|
|
RTC_DCHECK_GT(num_pending_partial_reports_, 1);
|
|
|
|
|
--num_pending_partial_reports_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void RTCStatsCollector::ProducePartialResultsOnSignalingThreadImpl(
|
|
|
|
|
int64_t timestamp_us,
|
|
|
|
|
RTCStatsReport* partial_report) {
|
2021-04-08 15:18:05 +02:00
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread_);
|
2020-07-08 11:18:50 +02:00
|
|
|
rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls;
|
|
|
|
|
|
Reland "Fix getStats() freeze bug affecting Chromium but not WebRTC standalone."
This is a reland of 05d43c6f7fe497fed0f2c8714e2042dd07a86df2
The original CL got reverted because Chrome did not support IsQuitting() which
triggered a NOTREACHED() inside of a DCHECK. With
https://chromium-review.googlesource.com/c/chromium/src/+/1491620
it is safe to reland this CL.
The only changes between this and the original patch set is that this is now
rebased on top of https://webrtc-review.googlesource.com/c/src/+/124701, i.e.
rtc::PostMessageWithFunctor() has been replaced by rtc::Thread::PostTask().
Original change's description:
> Fix getStats() freeze bug affecting Chromium but not WebRTC standalone.
>
> PeerConnection::Close() is, per-spec, a blocking operation.
> Unfortunately, PeerConnection is implemented to own resources used by
> the network thread, and Close() - on the signaling thread - destroys
> these resources. As such, tasks run in parallel like getStats() get into
> race conditions with Close() unless synchronized. The mechanism in-place
> is RTCStatsCollector::WaitForPendingRequest(), it waits until the
> network thread is done with the in-parallel stats request.
>
> Prior to this CL, this was implemented by performing
> rtc::Thread::ProcessMessages() in a loop until the network thread had
> posted a task on the signaling thread to say that it was done which
> would then get processed by ProcessMessages(). In WebRTC this works, and
> the test is RTCStatsIntegrationTest.GetsStatsWhileClosingPeerConnection.
>
> But because Chromium's thread wrapper does no support
> ProcessMessages(), calling getStats() followed by close() in Chrome
> resulted in waiting forever (https://crbug.com/850907).
>
> In this CL, the process messages loop is removed. Instead, the shared
> resources are guarded by an rtc::Event. WaitForPendingRequest() still
> blocks the signaling thread, but only while shared resources are in use
> by the network thread. After this CL, calling WaitForPendingRequest() no
> longer has any unexpected side-effects since it no longer processes
> other messages that might have been posted on the thread.
>
> The resource ownership and threading model of WebRTC deserves to be
> revisited, but this fixes a common Chromium crash without redesigning
> PeerConnection, in a way that does not cause more blocking than what
> the other PeerConnection methods are already doing.
>
> Note: An alternative to using rtc::Event is to use resource locks and
> to not perform the stats collection on the network thread if the
> request was cancelled before the start of processing, but this has very
> little benefit in terms of performance: once the network thread starts
> collecting the stats, it would use the lock until collection is
> completed, blocking the signaling thread trying to acquire that lock
> anyway. This defeats the purpose and is a riskier change, since
> cancelling partial collection in this inherently racy edge-case would
> have observable differences from the returned stats, which may cause
> more regressions.
>
> Bug: chromium:850907
> Change-Id: Idceeee0bddc0c9d5518b58a2b263abb2bbf47cff
> Reviewed-on: https://webrtc-review.googlesource.com/c/121567
> Commit-Queue: Henrik Boström <hbos@webrtc.org>
> Reviewed-by: Steve Anton <steveanton@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#26707}
TBR=steveanton@webrtc.org
Bug: chromium:850907
Change-Id: I5be7f69f0de65ff1120e4926fbf904def97ea9c0
Reviewed-on: https://webrtc-review.googlesource.com/c/124781
Reviewed-by: Henrik Boström <hbos@webrtc.org>
Reviewed-by: Steve Anton <steveanton@webrtc.org>
Commit-Queue: Henrik Boström <hbos@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#26896}
2019-02-28 09:49:31 +01:00
|
|
|
ProduceDataChannelStats_s(timestamp_us, partial_report);
|
|
|
|
|
ProduceMediaStreamStats_s(timestamp_us, partial_report);
|
|
|
|
|
ProduceMediaStreamTrackStats_s(timestamp_us, partial_report);
|
2019-05-22 15:49:42 +02:00
|
|
|
ProduceMediaSourceStats_s(timestamp_us, partial_report);
|
Reland "Fix getStats() freeze bug affecting Chromium but not WebRTC standalone."
This is a reland of 05d43c6f7fe497fed0f2c8714e2042dd07a86df2
The original CL got reverted because Chrome did not support IsQuitting() which
triggered a NOTREACHED() inside of a DCHECK. With
https://chromium-review.googlesource.com/c/chromium/src/+/1491620
it is safe to reland this CL.
The only changes between this and the original patch set is that this is now
rebased on top of https://webrtc-review.googlesource.com/c/src/+/124701, i.e.
rtc::PostMessageWithFunctor() has been replaced by rtc::Thread::PostTask().
Original change's description:
> Fix getStats() freeze bug affecting Chromium but not WebRTC standalone.
>
> PeerConnection::Close() is, per-spec, a blocking operation.
> Unfortunately, PeerConnection is implemented to own resources used by
> the network thread, and Close() - on the signaling thread - destroys
> these resources. As such, tasks run in parallel like getStats() get into
> race conditions with Close() unless synchronized. The mechanism in-place
> is RTCStatsCollector::WaitForPendingRequest(), it waits until the
> network thread is done with the in-parallel stats request.
>
> Prior to this CL, this was implemented by performing
> rtc::Thread::ProcessMessages() in a loop until the network thread had
> posted a task on the signaling thread to say that it was done which
> would then get processed by ProcessMessages(). In WebRTC this works, and
> the test is RTCStatsIntegrationTest.GetsStatsWhileClosingPeerConnection.
>
> But because Chromium's thread wrapper does no support
> ProcessMessages(), calling getStats() followed by close() in Chrome
> resulted in waiting forever (https://crbug.com/850907).
>
> In this CL, the process messages loop is removed. Instead, the shared
> resources are guarded by an rtc::Event. WaitForPendingRequest() still
> blocks the signaling thread, but only while shared resources are in use
> by the network thread. After this CL, calling WaitForPendingRequest() no
> longer has any unexpected side-effects since it no longer processes
> other messages that might have been posted on the thread.
>
> The resource ownership and threading model of WebRTC deserves to be
> revisited, but this fixes a common Chromium crash without redesigning
> PeerConnection, in a way that does not cause more blocking than what
> the other PeerConnection methods are already doing.
>
> Note: An alternative to using rtc::Event is to use resource locks and
> to not perform the stats collection on the network thread if the
> request was cancelled before the start of processing, but this has very
> little benefit in terms of performance: once the network thread starts
> collecting the stats, it would use the lock until collection is
> completed, blocking the signaling thread trying to acquire that lock
> anyway. This defeats the purpose and is a riskier change, since
> cancelling partial collection in this inherently racy edge-case would
> have observable differences from the returned stats, which may cause
> more regressions.
>
> Bug: chromium:850907
> Change-Id: Idceeee0bddc0c9d5518b58a2b263abb2bbf47cff
> Reviewed-on: https://webrtc-review.googlesource.com/c/121567
> Commit-Queue: Henrik Boström <hbos@webrtc.org>
> Reviewed-by: Steve Anton <steveanton@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#26707}
TBR=steveanton@webrtc.org
Bug: chromium:850907
Change-Id: I5be7f69f0de65ff1120e4926fbf904def97ea9c0
Reviewed-on: https://webrtc-review.googlesource.com/c/124781
Reviewed-by: Henrik Boström <hbos@webrtc.org>
Reviewed-by: Steve Anton <steveanton@webrtc.org>
Commit-Queue: Henrik Boström <hbos@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#26896}
2019-02-28 09:49:31 +01:00
|
|
|
ProducePeerConnectionStats_s(timestamp_us, partial_report);
|
2016-09-05 01:36:50 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void RTCStatsCollector::ProducePartialResultsOnNetworkThread(
|
|
|
|
|
int64_t timestamp_us) {
|
2021-04-08 15:18:05 +02:00
|
|
|
RTC_DCHECK_RUN_ON(network_thread_);
|
2020-07-08 11:18:50 +02:00
|
|
|
rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls;
|
|
|
|
|
|
2019-04-30 09:45:21 +02:00
|
|
|
// Touching |network_report_| on this thread is safe by this method because
|
Reland "Fix getStats() freeze bug affecting Chromium but not WebRTC standalone."
This is a reland of 05d43c6f7fe497fed0f2c8714e2042dd07a86df2
The original CL got reverted because Chrome did not support IsQuitting() which
triggered a NOTREACHED() inside of a DCHECK. With
https://chromium-review.googlesource.com/c/chromium/src/+/1491620
it is safe to reland this CL.
The only changes between this and the original patch set is that this is now
rebased on top of https://webrtc-review.googlesource.com/c/src/+/124701, i.e.
rtc::PostMessageWithFunctor() has been replaced by rtc::Thread::PostTask().
Original change's description:
> Fix getStats() freeze bug affecting Chromium but not WebRTC standalone.
>
> PeerConnection::Close() is, per-spec, a blocking operation.
> Unfortunately, PeerConnection is implemented to own resources used by
> the network thread, and Close() - on the signaling thread - destroys
> these resources. As such, tasks run in parallel like getStats() get into
> race conditions with Close() unless synchronized. The mechanism in-place
> is RTCStatsCollector::WaitForPendingRequest(), it waits until the
> network thread is done with the in-parallel stats request.
>
> Prior to this CL, this was implemented by performing
> rtc::Thread::ProcessMessages() in a loop until the network thread had
> posted a task on the signaling thread to say that it was done which
> would then get processed by ProcessMessages(). In WebRTC this works, and
> the test is RTCStatsIntegrationTest.GetsStatsWhileClosingPeerConnection.
>
> But because Chromium's thread wrapper does no support
> ProcessMessages(), calling getStats() followed by close() in Chrome
> resulted in waiting forever (https://crbug.com/850907).
>
> In this CL, the process messages loop is removed. Instead, the shared
> resources are guarded by an rtc::Event. WaitForPendingRequest() still
> blocks the signaling thread, but only while shared resources are in use
> by the network thread. After this CL, calling WaitForPendingRequest() no
> longer has any unexpected side-effects since it no longer processes
> other messages that might have been posted on the thread.
>
> The resource ownership and threading model of WebRTC deserves to be
> revisited, but this fixes a common Chromium crash without redesigning
> PeerConnection, in a way that does not cause more blocking than what
> the other PeerConnection methods are already doing.
>
> Note: An alternative to using rtc::Event is to use resource locks and
> to not perform the stats collection on the network thread if the
> request was cancelled before the start of processing, but this has very
> little benefit in terms of performance: once the network thread starts
> collecting the stats, it would use the lock until collection is
> completed, blocking the signaling thread trying to acquire that lock
> anyway. This defeats the purpose and is a riskier change, since
> cancelling partial collection in this inherently racy edge-case would
> have observable differences from the returned stats, which may cause
> more regressions.
>
> Bug: chromium:850907
> Change-Id: Idceeee0bddc0c9d5518b58a2b263abb2bbf47cff
> Reviewed-on: https://webrtc-review.googlesource.com/c/121567
> Commit-Queue: Henrik Boström <hbos@webrtc.org>
> Reviewed-by: Steve Anton <steveanton@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#26707}
TBR=steveanton@webrtc.org
Bug: chromium:850907
Change-Id: I5be7f69f0de65ff1120e4926fbf904def97ea9c0
Reviewed-on: https://webrtc-review.googlesource.com/c/124781
Reviewed-by: Henrik Boström <hbos@webrtc.org>
Reviewed-by: Steve Anton <steveanton@webrtc.org>
Commit-Queue: Henrik Boström <hbos@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#26896}
2019-02-28 09:49:31 +01:00
|
|
|
// |network_report_event_| is reset before this method is invoked.
|
|
|
|
|
network_report_ = RTCStatsReport::Create(timestamp_us);
|
2016-09-05 01:36:50 -07:00
|
|
|
|
2018-02-06 10:34:40 -08:00
|
|
|
std::map<std::string, cricket::TransportStats> transport_stats_by_name =
|
2018-03-30 15:18:41 -07:00
|
|
|
pc_->GetTransportStatsByNames(transport_names_);
|
2018-02-06 10:34:40 -08:00
|
|
|
std::map<std::string, CertificateStatsPair> transport_cert_stats =
|
|
|
|
|
PrepareTransportCertificateStats_n(transport_stats_by_name);
|
|
|
|
|
|
Reland "Fix getStats() freeze bug affecting Chromium but not WebRTC standalone."
This is a reland of 05d43c6f7fe497fed0f2c8714e2042dd07a86df2
The original CL got reverted because Chrome did not support IsQuitting() which
triggered a NOTREACHED() inside of a DCHECK. With
https://chromium-review.googlesource.com/c/chromium/src/+/1491620
it is safe to reland this CL.
The only changes between this and the original patch set is that this is now
rebased on top of https://webrtc-review.googlesource.com/c/src/+/124701, i.e.
rtc::PostMessageWithFunctor() has been replaced by rtc::Thread::PostTask().
Original change's description:
> Fix getStats() freeze bug affecting Chromium but not WebRTC standalone.
>
> PeerConnection::Close() is, per-spec, a blocking operation.
> Unfortunately, PeerConnection is implemented to own resources used by
> the network thread, and Close() - on the signaling thread - destroys
> these resources. As such, tasks run in parallel like getStats() get into
> race conditions with Close() unless synchronized. The mechanism in-place
> is RTCStatsCollector::WaitForPendingRequest(), it waits until the
> network thread is done with the in-parallel stats request.
>
> Prior to this CL, this was implemented by performing
> rtc::Thread::ProcessMessages() in a loop until the network thread had
> posted a task on the signaling thread to say that it was done which
> would then get processed by ProcessMessages(). In WebRTC this works, and
> the test is RTCStatsIntegrationTest.GetsStatsWhileClosingPeerConnection.
>
> But because Chromium's thread wrapper does no support
> ProcessMessages(), calling getStats() followed by close() in Chrome
> resulted in waiting forever (https://crbug.com/850907).
>
> In this CL, the process messages loop is removed. Instead, the shared
> resources are guarded by an rtc::Event. WaitForPendingRequest() still
> blocks the signaling thread, but only while shared resources are in use
> by the network thread. After this CL, calling WaitForPendingRequest() no
> longer has any unexpected side-effects since it no longer processes
> other messages that might have been posted on the thread.
>
> The resource ownership and threading model of WebRTC deserves to be
> revisited, but this fixes a common Chromium crash without redesigning
> PeerConnection, in a way that does not cause more blocking than what
> the other PeerConnection methods are already doing.
>
> Note: An alternative to using rtc::Event is to use resource locks and
> to not perform the stats collection on the network thread if the
> request was cancelled before the start of processing, but this has very
> little benefit in terms of performance: once the network thread starts
> collecting the stats, it would use the lock until collection is
> completed, blocking the signaling thread trying to acquire that lock
> anyway. This defeats the purpose and is a riskier change, since
> cancelling partial collection in this inherently racy edge-case would
> have observable differences from the returned stats, which may cause
> more regressions.
>
> Bug: chromium:850907
> Change-Id: Idceeee0bddc0c9d5518b58a2b263abb2bbf47cff
> Reviewed-on: https://webrtc-review.googlesource.com/c/121567
> Commit-Queue: Henrik Boström <hbos@webrtc.org>
> Reviewed-by: Steve Anton <steveanton@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#26707}
TBR=steveanton@webrtc.org
Bug: chromium:850907
Change-Id: I5be7f69f0de65ff1120e4926fbf904def97ea9c0
Reviewed-on: https://webrtc-review.googlesource.com/c/124781
Reviewed-by: Henrik Boström <hbos@webrtc.org>
Reviewed-by: Steve Anton <steveanton@webrtc.org>
Commit-Queue: Henrik Boström <hbos@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#26896}
2019-02-28 09:49:31 +01:00
|
|
|
ProducePartialResultsOnNetworkThreadImpl(
|
|
|
|
|
timestamp_us, transport_stats_by_name, transport_cert_stats,
|
|
|
|
|
network_report_.get());
|
Revert "Fix getStats() freeze bug affecting Chromium but not WebRTC standalone."
This reverts commit 05d43c6f7fe497fed0f2c8714e2042dd07a86df2.
Reason for revert: It breaks some Chromium trybots:
https://ci.chromium.org/p/chromium/builders/luci.chromium.try/linux_chromium_asan_rel_ng/206387
https://ci.chromium.org/p/chromium/builders/luci.chromium.try/linux_chromium_tsan_rel_ng/207737
https://ci.chromium.org/p/chromium/builders/luci.chromium.try/win10_chromium_x64_rel_ng/202283
Original change's description:
> Fix getStats() freeze bug affecting Chromium but not WebRTC standalone.
>
> PeerConnection::Close() is, per-spec, a blocking operation.
> Unfortunately, PeerConnection is implemented to own resources used by
> the network thread, and Close() - on the signaling thread - destroys
> these resources. As such, tasks run in parallel like getStats() get into
> race conditions with Close() unless synchronized. The mechanism in-place
> is RTCStatsCollector::WaitForPendingRequest(), it waits until the
> network thread is done with the in-parallel stats request.
>
> Prior to this CL, this was implemented by performing
> rtc::Thread::ProcessMessages() in a loop until the network thread had
> posted a task on the signaling thread to say that it was done which
> would then get processed by ProcessMessages(). In WebRTC this works, and
> the test is RTCStatsIntegrationTest.GetsStatsWhileClosingPeerConnection.
>
> But because Chromium's thread wrapper does no support
> ProcessMessages(), calling getStats() followed by close() in Chrome
> resulted in waiting forever (https://crbug.com/850907).
>
> In this CL, the process messages loop is removed. Instead, the shared
> resources are guarded by an rtc::Event. WaitForPendingRequest() still
> blocks the signaling thread, but only while shared resources are in use
> by the network thread. After this CL, calling WaitForPendingRequest() no
> longer has any unexpected side-effects since it no longer processes
> other messages that might have been posted on the thread.
>
> The resource ownership and threading model of WebRTC deserves to be
> revisited, but this fixes a common Chromium crash without redesigning
> PeerConnection, in a way that does not cause more blocking than what
> the other PeerConnection methods are already doing.
>
> Note: An alternative to using rtc::Event is to use resource locks and
> to not perform the stats collection on the network thread if the
> request was cancelled before the start of processing, but this has very
> little benefit in terms of performance: once the network thread starts
> collecting the stats, it would use the lock until collection is
> completed, blocking the signaling thread trying to acquire that lock
> anyway. This defeats the purpose and is a riskier change, since
> cancelling partial collection in this inherently racy edge-case would
> have observable differences from the returned stats, which may cause
> more regressions.
>
> Bug: chromium:850907
> Change-Id: Idceeee0bddc0c9d5518b58a2b263abb2bbf47cff
> Reviewed-on: https://webrtc-review.googlesource.com/c/121567
> Commit-Queue: Henrik Boström <hbos@webrtc.org>
> Reviewed-by: Steve Anton <steveanton@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#26707}
TBR=steveanton@webrtc.org,hbos@webrtc.org
Change-Id: Icd82cdd5bd086a90999f7fd5f8616e1f2d2153bf
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: chromium:850907
Reviewed-on: https://webrtc-review.googlesource.com/c/123225
Reviewed-by: Mirko Bonadei <mbonadei@webrtc.org>
Commit-Queue: Mirko Bonadei <mbonadei@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#26721}
2019-02-15 21:10:40 +00:00
|
|
|
|
Reland "Fix getStats() freeze bug affecting Chromium but not WebRTC standalone."
This is a reland of 05d43c6f7fe497fed0f2c8714e2042dd07a86df2
The original CL got reverted because Chrome did not support IsQuitting() which
triggered a NOTREACHED() inside of a DCHECK. With
https://chromium-review.googlesource.com/c/chromium/src/+/1491620
it is safe to reland this CL.
The only changes between this and the original patch set is that this is now
rebased on top of https://webrtc-review.googlesource.com/c/src/+/124701, i.e.
rtc::PostMessageWithFunctor() has been replaced by rtc::Thread::PostTask().
Original change's description:
> Fix getStats() freeze bug affecting Chromium but not WebRTC standalone.
>
> PeerConnection::Close() is, per-spec, a blocking operation.
> Unfortunately, PeerConnection is implemented to own resources used by
> the network thread, and Close() - on the signaling thread - destroys
> these resources. As such, tasks run in parallel like getStats() get into
> race conditions with Close() unless synchronized. The mechanism in-place
> is RTCStatsCollector::WaitForPendingRequest(), it waits until the
> network thread is done with the in-parallel stats request.
>
> Prior to this CL, this was implemented by performing
> rtc::Thread::ProcessMessages() in a loop until the network thread had
> posted a task on the signaling thread to say that it was done which
> would then get processed by ProcessMessages(). In WebRTC this works, and
> the test is RTCStatsIntegrationTest.GetsStatsWhileClosingPeerConnection.
>
> But because Chromium's thread wrapper does no support
> ProcessMessages(), calling getStats() followed by close() in Chrome
> resulted in waiting forever (https://crbug.com/850907).
>
> In this CL, the process messages loop is removed. Instead, the shared
> resources are guarded by an rtc::Event. WaitForPendingRequest() still
> blocks the signaling thread, but only while shared resources are in use
> by the network thread. After this CL, calling WaitForPendingRequest() no
> longer has any unexpected side-effects since it no longer processes
> other messages that might have been posted on the thread.
>
> The resource ownership and threading model of WebRTC deserves to be
> revisited, but this fixes a common Chromium crash without redesigning
> PeerConnection, in a way that does not cause more blocking than what
> the other PeerConnection methods are already doing.
>
> Note: An alternative to using rtc::Event is to use resource locks and
> to not perform the stats collection on the network thread if the
> request was cancelled before the start of processing, but this has very
> little benefit in terms of performance: once the network thread starts
> collecting the stats, it would use the lock until collection is
> completed, blocking the signaling thread trying to acquire that lock
> anyway. This defeats the purpose and is a riskier change, since
> cancelling partial collection in this inherently racy edge-case would
> have observable differences from the returned stats, which may cause
> more regressions.
>
> Bug: chromium:850907
> Change-Id: Idceeee0bddc0c9d5518b58a2b263abb2bbf47cff
> Reviewed-on: https://webrtc-review.googlesource.com/c/121567
> Commit-Queue: Henrik Boström <hbos@webrtc.org>
> Reviewed-by: Steve Anton <steveanton@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#26707}
TBR=steveanton@webrtc.org
Bug: chromium:850907
Change-Id: I5be7f69f0de65ff1120e4926fbf904def97ea9c0
Reviewed-on: https://webrtc-review.googlesource.com/c/124781
Reviewed-by: Henrik Boström <hbos@webrtc.org>
Reviewed-by: Steve Anton <steveanton@webrtc.org>
Commit-Queue: Henrik Boström <hbos@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#26896}
2019-02-28 09:49:31 +01:00
|
|
|
// Signal that it is now safe to touch |network_report_| on the signaling
|
|
|
|
|
// thread, and post a task to merge it into the final results.
|
|
|
|
|
network_report_event_.Set();
|
2021-01-18 09:24:33 +01:00
|
|
|
rtc::scoped_refptr<RTCStatsCollector> collector(this);
|
Reland "Fix getStats() freeze bug affecting Chromium but not WebRTC standalone."
This is a reland of 05d43c6f7fe497fed0f2c8714e2042dd07a86df2
The original CL got reverted because Chrome did not support IsQuitting() which
triggered a NOTREACHED() inside of a DCHECK. With
https://chromium-review.googlesource.com/c/chromium/src/+/1491620
it is safe to reland this CL.
The only changes between this and the original patch set is that this is now
rebased on top of https://webrtc-review.googlesource.com/c/src/+/124701, i.e.
rtc::PostMessageWithFunctor() has been replaced by rtc::Thread::PostTask().
Original change's description:
> Fix getStats() freeze bug affecting Chromium but not WebRTC standalone.
>
> PeerConnection::Close() is, per-spec, a blocking operation.
> Unfortunately, PeerConnection is implemented to own resources used by
> the network thread, and Close() - on the signaling thread - destroys
> these resources. As such, tasks run in parallel like getStats() get into
> race conditions with Close() unless synchronized. The mechanism in-place
> is RTCStatsCollector::WaitForPendingRequest(), it waits until the
> network thread is done with the in-parallel stats request.
>
> Prior to this CL, this was implemented by performing
> rtc::Thread::ProcessMessages() in a loop until the network thread had
> posted a task on the signaling thread to say that it was done which
> would then get processed by ProcessMessages(). In WebRTC this works, and
> the test is RTCStatsIntegrationTest.GetsStatsWhileClosingPeerConnection.
>
> But because Chromium's thread wrapper does no support
> ProcessMessages(), calling getStats() followed by close() in Chrome
> resulted in waiting forever (https://crbug.com/850907).
>
> In this CL, the process messages loop is removed. Instead, the shared
> resources are guarded by an rtc::Event. WaitForPendingRequest() still
> blocks the signaling thread, but only while shared resources are in use
> by the network thread. After this CL, calling WaitForPendingRequest() no
> longer has any unexpected side-effects since it no longer processes
> other messages that might have been posted on the thread.
>
> The resource ownership and threading model of WebRTC deserves to be
> revisited, but this fixes a common Chromium crash without redesigning
> PeerConnection, in a way that does not cause more blocking than what
> the other PeerConnection methods are already doing.
>
> Note: An alternative to using rtc::Event is to use resource locks and
> to not perform the stats collection on the network thread if the
> request was cancelled before the start of processing, but this has very
> little benefit in terms of performance: once the network thread starts
> collecting the stats, it would use the lock until collection is
> completed, blocking the signaling thread trying to acquire that lock
> anyway. This defeats the purpose and is a riskier change, since
> cancelling partial collection in this inherently racy edge-case would
> have observable differences from the returned stats, which may cause
> more regressions.
>
> Bug: chromium:850907
> Change-Id: Idceeee0bddc0c9d5518b58a2b263abb2bbf47cff
> Reviewed-on: https://webrtc-review.googlesource.com/c/121567
> Commit-Queue: Henrik Boström <hbos@webrtc.org>
> Reviewed-by: Steve Anton <steveanton@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#26707}
TBR=steveanton@webrtc.org
Bug: chromium:850907
Change-Id: I5be7f69f0de65ff1120e4926fbf904def97ea9c0
Reviewed-on: https://webrtc-review.googlesource.com/c/124781
Reviewed-by: Henrik Boström <hbos@webrtc.org>
Reviewed-by: Steve Anton <steveanton@webrtc.org>
Commit-Queue: Henrik Boström <hbos@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#26896}
2019-02-28 09:49:31 +01:00
|
|
|
signaling_thread_->PostTask(
|
2021-01-18 09:24:33 +01:00
|
|
|
RTC_FROM_HERE, [collector] { collector->MergeNetworkReport_s(); });
|
2016-09-05 01:36:50 -07:00
|
|
|
}
|
|
|
|
|
|
Reland "Fix getStats() freeze bug affecting Chromium but not WebRTC standalone."
This is a reland of 05d43c6f7fe497fed0f2c8714e2042dd07a86df2
The original CL got reverted because Chrome did not support IsQuitting() which
triggered a NOTREACHED() inside of a DCHECK. With
https://chromium-review.googlesource.com/c/chromium/src/+/1491620
it is safe to reland this CL.
The only changes between this and the original patch set is that this is now
rebased on top of https://webrtc-review.googlesource.com/c/src/+/124701, i.e.
rtc::PostMessageWithFunctor() has been replaced by rtc::Thread::PostTask().
Original change's description:
> Fix getStats() freeze bug affecting Chromium but not WebRTC standalone.
>
> PeerConnection::Close() is, per-spec, a blocking operation.
> Unfortunately, PeerConnection is implemented to own resources used by
> the network thread, and Close() - on the signaling thread - destroys
> these resources. As such, tasks run in parallel like getStats() get into
> race conditions with Close() unless synchronized. The mechanism in-place
> is RTCStatsCollector::WaitForPendingRequest(), it waits until the
> network thread is done with the in-parallel stats request.
>
> Prior to this CL, this was implemented by performing
> rtc::Thread::ProcessMessages() in a loop until the network thread had
> posted a task on the signaling thread to say that it was done which
> would then get processed by ProcessMessages(). In WebRTC this works, and
> the test is RTCStatsIntegrationTest.GetsStatsWhileClosingPeerConnection.
>
> But because Chromium's thread wrapper does no support
> ProcessMessages(), calling getStats() followed by close() in Chrome
> resulted in waiting forever (https://crbug.com/850907).
>
> In this CL, the process messages loop is removed. Instead, the shared
> resources are guarded by an rtc::Event. WaitForPendingRequest() still
> blocks the signaling thread, but only while shared resources are in use
> by the network thread. After this CL, calling WaitForPendingRequest() no
> longer has any unexpected side-effects since it no longer processes
> other messages that might have been posted on the thread.
>
> The resource ownership and threading model of WebRTC deserves to be
> revisited, but this fixes a common Chromium crash without redesigning
> PeerConnection, in a way that does not cause more blocking than what
> the other PeerConnection methods are already doing.
>
> Note: An alternative to using rtc::Event is to use resource locks and
> to not perform the stats collection on the network thread if the
> request was cancelled before the start of processing, but this has very
> little benefit in terms of performance: once the network thread starts
> collecting the stats, it would use the lock until collection is
> completed, blocking the signaling thread trying to acquire that lock
> anyway. This defeats the purpose and is a riskier change, since
> cancelling partial collection in this inherently racy edge-case would
> have observable differences from the returned stats, which may cause
> more regressions.
>
> Bug: chromium:850907
> Change-Id: Idceeee0bddc0c9d5518b58a2b263abb2bbf47cff
> Reviewed-on: https://webrtc-review.googlesource.com/c/121567
> Commit-Queue: Henrik Boström <hbos@webrtc.org>
> Reviewed-by: Steve Anton <steveanton@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#26707}
TBR=steveanton@webrtc.org
Bug: chromium:850907
Change-Id: I5be7f69f0de65ff1120e4926fbf904def97ea9c0
Reviewed-on: https://webrtc-review.googlesource.com/c/124781
Reviewed-by: Henrik Boström <hbos@webrtc.org>
Reviewed-by: Steve Anton <steveanton@webrtc.org>
Commit-Queue: Henrik Boström <hbos@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#26896}
2019-02-28 09:49:31 +01:00
|
|
|
void RTCStatsCollector::ProducePartialResultsOnNetworkThreadImpl(
|
|
|
|
|
int64_t timestamp_us,
|
|
|
|
|
const std::map<std::string, cricket::TransportStats>&
|
|
|
|
|
transport_stats_by_name,
|
|
|
|
|
const std::map<std::string, CertificateStatsPair>& transport_cert_stats,
|
|
|
|
|
RTCStatsReport* partial_report) {
|
2021-04-08 15:18:05 +02:00
|
|
|
RTC_DCHECK_RUN_ON(network_thread_);
|
2020-07-08 11:18:50 +02:00
|
|
|
rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls;
|
|
|
|
|
|
Reland "Fix getStats() freeze bug affecting Chromium but not WebRTC standalone."
This is a reland of 05d43c6f7fe497fed0f2c8714e2042dd07a86df2
The original CL got reverted because Chrome did not support IsQuitting() which
triggered a NOTREACHED() inside of a DCHECK. With
https://chromium-review.googlesource.com/c/chromium/src/+/1491620
it is safe to reland this CL.
The only changes between this and the original patch set is that this is now
rebased on top of https://webrtc-review.googlesource.com/c/src/+/124701, i.e.
rtc::PostMessageWithFunctor() has been replaced by rtc::Thread::PostTask().
Original change's description:
> Fix getStats() freeze bug affecting Chromium but not WebRTC standalone.
>
> PeerConnection::Close() is, per-spec, a blocking operation.
> Unfortunately, PeerConnection is implemented to own resources used by
> the network thread, and Close() - on the signaling thread - destroys
> these resources. As such, tasks run in parallel like getStats() get into
> race conditions with Close() unless synchronized. The mechanism in-place
> is RTCStatsCollector::WaitForPendingRequest(), it waits until the
> network thread is done with the in-parallel stats request.
>
> Prior to this CL, this was implemented by performing
> rtc::Thread::ProcessMessages() in a loop until the network thread had
> posted a task on the signaling thread to say that it was done which
> would then get processed by ProcessMessages(). In WebRTC this works, and
> the test is RTCStatsIntegrationTest.GetsStatsWhileClosingPeerConnection.
>
> But because Chromium's thread wrapper does no support
> ProcessMessages(), calling getStats() followed by close() in Chrome
> resulted in waiting forever (https://crbug.com/850907).
>
> In this CL, the process messages loop is removed. Instead, the shared
> resources are guarded by an rtc::Event. WaitForPendingRequest() still
> blocks the signaling thread, but only while shared resources are in use
> by the network thread. After this CL, calling WaitForPendingRequest() no
> longer has any unexpected side-effects since it no longer processes
> other messages that might have been posted on the thread.
>
> The resource ownership and threading model of WebRTC deserves to be
> revisited, but this fixes a common Chromium crash without redesigning
> PeerConnection, in a way that does not cause more blocking than what
> the other PeerConnection methods are already doing.
>
> Note: An alternative to using rtc::Event is to use resource locks and
> to not perform the stats collection on the network thread if the
> request was cancelled before the start of processing, but this has very
> little benefit in terms of performance: once the network thread starts
> collecting the stats, it would use the lock until collection is
> completed, blocking the signaling thread trying to acquire that lock
> anyway. This defeats the purpose and is a riskier change, since
> cancelling partial collection in this inherently racy edge-case would
> have observable differences from the returned stats, which may cause
> more regressions.
>
> Bug: chromium:850907
> Change-Id: Idceeee0bddc0c9d5518b58a2b263abb2bbf47cff
> Reviewed-on: https://webrtc-review.googlesource.com/c/121567
> Commit-Queue: Henrik Boström <hbos@webrtc.org>
> Reviewed-by: Steve Anton <steveanton@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#26707}
TBR=steveanton@webrtc.org
Bug: chromium:850907
Change-Id: I5be7f69f0de65ff1120e4926fbf904def97ea9c0
Reviewed-on: https://webrtc-review.googlesource.com/c/124781
Reviewed-by: Henrik Boström <hbos@webrtc.org>
Reviewed-by: Steve Anton <steveanton@webrtc.org>
Commit-Queue: Henrik Boström <hbos@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#26896}
2019-02-28 09:49:31 +01:00
|
|
|
ProduceCertificateStats_n(timestamp_us, transport_cert_stats, partial_report);
|
|
|
|
|
ProduceCodecStats_n(timestamp_us, transceiver_stats_infos_, partial_report);
|
|
|
|
|
ProduceIceCandidateAndPairStats_n(timestamp_us, transport_stats_by_name,
|
|
|
|
|
call_stats_, partial_report);
|
|
|
|
|
ProduceTransportStats_n(timestamp_us, transport_stats_by_name,
|
|
|
|
|
transport_cert_stats, partial_report);
|
Implement RTCRemoteInboundRtpStreamStats for both audio and video.
This implements the essentials of RTCRemoteInboundRtpStreamStats. This
includes:
- ssrc
- transportId
- codecId
- packetsLost
- jitter
- localId
- roundTripTime
https://w3c.github.io/webrtc-stats/#remoteinboundrtpstats-dict*
The following members are not implemented because they require more
work...
- From RTCReceivedRtpStreamStats: packetsReceived, packetsDiscarded,
packetsRepaired, burstPacketsLost, burstPacketsDiscarded,
burstLossCount, burstDiscardCount, burstLossRate, burstDiscardRate,
gapLossRate and gapDiscardRate.
- From RTCRemoteInboundRtpStreamStats: fractionLost.
Bug: webrtc:10455, webrtc:10456
Change-Id: If2ab0da7105d8c93bba58e14aa93bd22ffe57f1d
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/138067
Commit-Queue: Henrik Boström <hbos@webrtc.org>
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#28073}
2019-05-27 13:40:25 +02:00
|
|
|
ProduceRTPStreamStats_n(timestamp_us, transceiver_stats_infos_,
|
|
|
|
|
partial_report);
|
Revert "Fix getStats() freeze bug affecting Chromium but not WebRTC standalone."
This reverts commit 05d43c6f7fe497fed0f2c8714e2042dd07a86df2.
Reason for revert: It breaks some Chromium trybots:
https://ci.chromium.org/p/chromium/builders/luci.chromium.try/linux_chromium_asan_rel_ng/206387
https://ci.chromium.org/p/chromium/builders/luci.chromium.try/linux_chromium_tsan_rel_ng/207737
https://ci.chromium.org/p/chromium/builders/luci.chromium.try/win10_chromium_x64_rel_ng/202283
Original change's description:
> Fix getStats() freeze bug affecting Chromium but not WebRTC standalone.
>
> PeerConnection::Close() is, per-spec, a blocking operation.
> Unfortunately, PeerConnection is implemented to own resources used by
> the network thread, and Close() - on the signaling thread - destroys
> these resources. As such, tasks run in parallel like getStats() get into
> race conditions with Close() unless synchronized. The mechanism in-place
> is RTCStatsCollector::WaitForPendingRequest(), it waits until the
> network thread is done with the in-parallel stats request.
>
> Prior to this CL, this was implemented by performing
> rtc::Thread::ProcessMessages() in a loop until the network thread had
> posted a task on the signaling thread to say that it was done which
> would then get processed by ProcessMessages(). In WebRTC this works, and
> the test is RTCStatsIntegrationTest.GetsStatsWhileClosingPeerConnection.
>
> But because Chromium's thread wrapper does no support
> ProcessMessages(), calling getStats() followed by close() in Chrome
> resulted in waiting forever (https://crbug.com/850907).
>
> In this CL, the process messages loop is removed. Instead, the shared
> resources are guarded by an rtc::Event. WaitForPendingRequest() still
> blocks the signaling thread, but only while shared resources are in use
> by the network thread. After this CL, calling WaitForPendingRequest() no
> longer has any unexpected side-effects since it no longer processes
> other messages that might have been posted on the thread.
>
> The resource ownership and threading model of WebRTC deserves to be
> revisited, but this fixes a common Chromium crash without redesigning
> PeerConnection, in a way that does not cause more blocking than what
> the other PeerConnection methods are already doing.
>
> Note: An alternative to using rtc::Event is to use resource locks and
> to not perform the stats collection on the network thread if the
> request was cancelled before the start of processing, but this has very
> little benefit in terms of performance: once the network thread starts
> collecting the stats, it would use the lock until collection is
> completed, blocking the signaling thread trying to acquire that lock
> anyway. This defeats the purpose and is a riskier change, since
> cancelling partial collection in this inherently racy edge-case would
> have observable differences from the returned stats, which may cause
> more regressions.
>
> Bug: chromium:850907
> Change-Id: Idceeee0bddc0c9d5518b58a2b263abb2bbf47cff
> Reviewed-on: https://webrtc-review.googlesource.com/c/121567
> Commit-Queue: Henrik Boström <hbos@webrtc.org>
> Reviewed-by: Steve Anton <steveanton@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#26707}
TBR=steveanton@webrtc.org,hbos@webrtc.org
Change-Id: Icd82cdd5bd086a90999f7fd5f8616e1f2d2153bf
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: chromium:850907
Reviewed-on: https://webrtc-review.googlesource.com/c/123225
Reviewed-by: Mirko Bonadei <mbonadei@webrtc.org>
Commit-Queue: Mirko Bonadei <mbonadei@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#26721}
2019-02-15 21:10:40 +00:00
|
|
|
}
|
|
|
|
|
|
Reland "Fix getStats() freeze bug affecting Chromium but not WebRTC standalone."
This is a reland of 05d43c6f7fe497fed0f2c8714e2042dd07a86df2
The original CL got reverted because Chrome did not support IsQuitting() which
triggered a NOTREACHED() inside of a DCHECK. With
https://chromium-review.googlesource.com/c/chromium/src/+/1491620
it is safe to reland this CL.
The only changes between this and the original patch set is that this is now
rebased on top of https://webrtc-review.googlesource.com/c/src/+/124701, i.e.
rtc::PostMessageWithFunctor() has been replaced by rtc::Thread::PostTask().
Original change's description:
> Fix getStats() freeze bug affecting Chromium but not WebRTC standalone.
>
> PeerConnection::Close() is, per-spec, a blocking operation.
> Unfortunately, PeerConnection is implemented to own resources used by
> the network thread, and Close() - on the signaling thread - destroys
> these resources. As such, tasks run in parallel like getStats() get into
> race conditions with Close() unless synchronized. The mechanism in-place
> is RTCStatsCollector::WaitForPendingRequest(), it waits until the
> network thread is done with the in-parallel stats request.
>
> Prior to this CL, this was implemented by performing
> rtc::Thread::ProcessMessages() in a loop until the network thread had
> posted a task on the signaling thread to say that it was done which
> would then get processed by ProcessMessages(). In WebRTC this works, and
> the test is RTCStatsIntegrationTest.GetsStatsWhileClosingPeerConnection.
>
> But because Chromium's thread wrapper does no support
> ProcessMessages(), calling getStats() followed by close() in Chrome
> resulted in waiting forever (https://crbug.com/850907).
>
> In this CL, the process messages loop is removed. Instead, the shared
> resources are guarded by an rtc::Event. WaitForPendingRequest() still
> blocks the signaling thread, but only while shared resources are in use
> by the network thread. After this CL, calling WaitForPendingRequest() no
> longer has any unexpected side-effects since it no longer processes
> other messages that might have been posted on the thread.
>
> The resource ownership and threading model of WebRTC deserves to be
> revisited, but this fixes a common Chromium crash without redesigning
> PeerConnection, in a way that does not cause more blocking than what
> the other PeerConnection methods are already doing.
>
> Note: An alternative to using rtc::Event is to use resource locks and
> to not perform the stats collection on the network thread if the
> request was cancelled before the start of processing, but this has very
> little benefit in terms of performance: once the network thread starts
> collecting the stats, it would use the lock until collection is
> completed, blocking the signaling thread trying to acquire that lock
> anyway. This defeats the purpose and is a riskier change, since
> cancelling partial collection in this inherently racy edge-case would
> have observable differences from the returned stats, which may cause
> more regressions.
>
> Bug: chromium:850907
> Change-Id: Idceeee0bddc0c9d5518b58a2b263abb2bbf47cff
> Reviewed-on: https://webrtc-review.googlesource.com/c/121567
> Commit-Queue: Henrik Boström <hbos@webrtc.org>
> Reviewed-by: Steve Anton <steveanton@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#26707}
TBR=steveanton@webrtc.org
Bug: chromium:850907
Change-Id: I5be7f69f0de65ff1120e4926fbf904def97ea9c0
Reviewed-on: https://webrtc-review.googlesource.com/c/124781
Reviewed-by: Henrik Boström <hbos@webrtc.org>
Reviewed-by: Steve Anton <steveanton@webrtc.org>
Commit-Queue: Henrik Boström <hbos@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#26896}
2019-02-28 09:49:31 +01:00
|
|
|
void RTCStatsCollector::MergeNetworkReport_s() {
|
2021-04-08 15:18:05 +02:00
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread_);
|
Reland "Fix getStats() freeze bug affecting Chromium but not WebRTC standalone."
This is a reland of 05d43c6f7fe497fed0f2c8714e2042dd07a86df2
The original CL got reverted because Chrome did not support IsQuitting() which
triggered a NOTREACHED() inside of a DCHECK. With
https://chromium-review.googlesource.com/c/chromium/src/+/1491620
it is safe to reland this CL.
The only changes between this and the original patch set is that this is now
rebased on top of https://webrtc-review.googlesource.com/c/src/+/124701, i.e.
rtc::PostMessageWithFunctor() has been replaced by rtc::Thread::PostTask().
Original change's description:
> Fix getStats() freeze bug affecting Chromium but not WebRTC standalone.
>
> PeerConnection::Close() is, per-spec, a blocking operation.
> Unfortunately, PeerConnection is implemented to own resources used by
> the network thread, and Close() - on the signaling thread - destroys
> these resources. As such, tasks run in parallel like getStats() get into
> race conditions with Close() unless synchronized. The mechanism in-place
> is RTCStatsCollector::WaitForPendingRequest(), it waits until the
> network thread is done with the in-parallel stats request.
>
> Prior to this CL, this was implemented by performing
> rtc::Thread::ProcessMessages() in a loop until the network thread had
> posted a task on the signaling thread to say that it was done which
> would then get processed by ProcessMessages(). In WebRTC this works, and
> the test is RTCStatsIntegrationTest.GetsStatsWhileClosingPeerConnection.
>
> But because Chromium's thread wrapper does no support
> ProcessMessages(), calling getStats() followed by close() in Chrome
> resulted in waiting forever (https://crbug.com/850907).
>
> In this CL, the process messages loop is removed. Instead, the shared
> resources are guarded by an rtc::Event. WaitForPendingRequest() still
> blocks the signaling thread, but only while shared resources are in use
> by the network thread. After this CL, calling WaitForPendingRequest() no
> longer has any unexpected side-effects since it no longer processes
> other messages that might have been posted on the thread.
>
> The resource ownership and threading model of WebRTC deserves to be
> revisited, but this fixes a common Chromium crash without redesigning
> PeerConnection, in a way that does not cause more blocking than what
> the other PeerConnection methods are already doing.
>
> Note: An alternative to using rtc::Event is to use resource locks and
> to not perform the stats collection on the network thread if the
> request was cancelled before the start of processing, but this has very
> little benefit in terms of performance: once the network thread starts
> collecting the stats, it would use the lock until collection is
> completed, blocking the signaling thread trying to acquire that lock
> anyway. This defeats the purpose and is a riskier change, since
> cancelling partial collection in this inherently racy edge-case would
> have observable differences from the returned stats, which may cause
> more regressions.
>
> Bug: chromium:850907
> Change-Id: Idceeee0bddc0c9d5518b58a2b263abb2bbf47cff
> Reviewed-on: https://webrtc-review.googlesource.com/c/121567
> Commit-Queue: Henrik Boström <hbos@webrtc.org>
> Reviewed-by: Steve Anton <steveanton@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#26707}
TBR=steveanton@webrtc.org
Bug: chromium:850907
Change-Id: I5be7f69f0de65ff1120e4926fbf904def97ea9c0
Reviewed-on: https://webrtc-review.googlesource.com/c/124781
Reviewed-by: Henrik Boström <hbos@webrtc.org>
Reviewed-by: Steve Anton <steveanton@webrtc.org>
Commit-Queue: Henrik Boström <hbos@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#26896}
2019-02-28 09:49:31 +01:00
|
|
|
// The |network_report_event_| must be signaled for it to be safe to touch
|
|
|
|
|
// |network_report_|. This is normally not blocking, but if
|
|
|
|
|
// WaitForPendingRequest() is called while a request is pending, we might have
|
|
|
|
|
// to wait until the network thread is done touching |network_report_|.
|
|
|
|
|
network_report_event_.Wait(rtc::Event::kForever);
|
|
|
|
|
if (!network_report_) {
|
|
|
|
|
// Normally, MergeNetworkReport_s() is executed because it is posted from
|
|
|
|
|
// the network thread. But if WaitForPendingRequest() is called while a
|
|
|
|
|
// request is pending, an early call to MergeNetworkReport_s() is made,
|
|
|
|
|
// merging the report and setting |network_report_| to null. If so, when the
|
|
|
|
|
// previously posted MergeNetworkReport_s() is later executed, the report is
|
|
|
|
|
// already null and nothing needs to be done here.
|
|
|
|
|
return;
|
|
|
|
|
}
|
2016-09-05 01:36:50 -07:00
|
|
|
RTC_DCHECK_GT(num_pending_partial_reports_, 0);
|
Reland "Fix getStats() freeze bug affecting Chromium but not WebRTC standalone."
This is a reland of 05d43c6f7fe497fed0f2c8714e2042dd07a86df2
The original CL got reverted because Chrome did not support IsQuitting() which
triggered a NOTREACHED() inside of a DCHECK. With
https://chromium-review.googlesource.com/c/chromium/src/+/1491620
it is safe to reland this CL.
The only changes between this and the original patch set is that this is now
rebased on top of https://webrtc-review.googlesource.com/c/src/+/124701, i.e.
rtc::PostMessageWithFunctor() has been replaced by rtc::Thread::PostTask().
Original change's description:
> Fix getStats() freeze bug affecting Chromium but not WebRTC standalone.
>
> PeerConnection::Close() is, per-spec, a blocking operation.
> Unfortunately, PeerConnection is implemented to own resources used by
> the network thread, and Close() - on the signaling thread - destroys
> these resources. As such, tasks run in parallel like getStats() get into
> race conditions with Close() unless synchronized. The mechanism in-place
> is RTCStatsCollector::WaitForPendingRequest(), it waits until the
> network thread is done with the in-parallel stats request.
>
> Prior to this CL, this was implemented by performing
> rtc::Thread::ProcessMessages() in a loop until the network thread had
> posted a task on the signaling thread to say that it was done which
> would then get processed by ProcessMessages(). In WebRTC this works, and
> the test is RTCStatsIntegrationTest.GetsStatsWhileClosingPeerConnection.
>
> But because Chromium's thread wrapper does no support
> ProcessMessages(), calling getStats() followed by close() in Chrome
> resulted in waiting forever (https://crbug.com/850907).
>
> In this CL, the process messages loop is removed. Instead, the shared
> resources are guarded by an rtc::Event. WaitForPendingRequest() still
> blocks the signaling thread, but only while shared resources are in use
> by the network thread. After this CL, calling WaitForPendingRequest() no
> longer has any unexpected side-effects since it no longer processes
> other messages that might have been posted on the thread.
>
> The resource ownership and threading model of WebRTC deserves to be
> revisited, but this fixes a common Chromium crash without redesigning
> PeerConnection, in a way that does not cause more blocking than what
> the other PeerConnection methods are already doing.
>
> Note: An alternative to using rtc::Event is to use resource locks and
> to not perform the stats collection on the network thread if the
> request was cancelled before the start of processing, but this has very
> little benefit in terms of performance: once the network thread starts
> collecting the stats, it would use the lock until collection is
> completed, blocking the signaling thread trying to acquire that lock
> anyway. This defeats the purpose and is a riskier change, since
> cancelling partial collection in this inherently racy edge-case would
> have observable differences from the returned stats, which may cause
> more regressions.
>
> Bug: chromium:850907
> Change-Id: Idceeee0bddc0c9d5518b58a2b263abb2bbf47cff
> Reviewed-on: https://webrtc-review.googlesource.com/c/121567
> Commit-Queue: Henrik Boström <hbos@webrtc.org>
> Reviewed-by: Steve Anton <steveanton@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#26707}
TBR=steveanton@webrtc.org
Bug: chromium:850907
Change-Id: I5be7f69f0de65ff1120e4926fbf904def97ea9c0
Reviewed-on: https://webrtc-review.googlesource.com/c/124781
Reviewed-by: Henrik Boström <hbos@webrtc.org>
Reviewed-by: Steve Anton <steveanton@webrtc.org>
Commit-Queue: Henrik Boström <hbos@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#26896}
2019-02-28 09:49:31 +01:00
|
|
|
RTC_DCHECK(partial_report_);
|
|
|
|
|
partial_report_->TakeMembersFrom(network_report_);
|
|
|
|
|
network_report_ = nullptr;
|
2016-09-05 01:36:50 -07:00
|
|
|
--num_pending_partial_reports_;
|
Reland "Fix getStats() freeze bug affecting Chromium but not WebRTC standalone."
This is a reland of 05d43c6f7fe497fed0f2c8714e2042dd07a86df2
The original CL got reverted because Chrome did not support IsQuitting() which
triggered a NOTREACHED() inside of a DCHECK. With
https://chromium-review.googlesource.com/c/chromium/src/+/1491620
it is safe to reland this CL.
The only changes between this and the original patch set is that this is now
rebased on top of https://webrtc-review.googlesource.com/c/src/+/124701, i.e.
rtc::PostMessageWithFunctor() has been replaced by rtc::Thread::PostTask().
Original change's description:
> Fix getStats() freeze bug affecting Chromium but not WebRTC standalone.
>
> PeerConnection::Close() is, per-spec, a blocking operation.
> Unfortunately, PeerConnection is implemented to own resources used by
> the network thread, and Close() - on the signaling thread - destroys
> these resources. As such, tasks run in parallel like getStats() get into
> race conditions with Close() unless synchronized. The mechanism in-place
> is RTCStatsCollector::WaitForPendingRequest(), it waits until the
> network thread is done with the in-parallel stats request.
>
> Prior to this CL, this was implemented by performing
> rtc::Thread::ProcessMessages() in a loop until the network thread had
> posted a task on the signaling thread to say that it was done which
> would then get processed by ProcessMessages(). In WebRTC this works, and
> the test is RTCStatsIntegrationTest.GetsStatsWhileClosingPeerConnection.
>
> But because Chromium's thread wrapper does no support
> ProcessMessages(), calling getStats() followed by close() in Chrome
> resulted in waiting forever (https://crbug.com/850907).
>
> In this CL, the process messages loop is removed. Instead, the shared
> resources are guarded by an rtc::Event. WaitForPendingRequest() still
> blocks the signaling thread, but only while shared resources are in use
> by the network thread. After this CL, calling WaitForPendingRequest() no
> longer has any unexpected side-effects since it no longer processes
> other messages that might have been posted on the thread.
>
> The resource ownership and threading model of WebRTC deserves to be
> revisited, but this fixes a common Chromium crash without redesigning
> PeerConnection, in a way that does not cause more blocking than what
> the other PeerConnection methods are already doing.
>
> Note: An alternative to using rtc::Event is to use resource locks and
> to not perform the stats collection on the network thread if the
> request was cancelled before the start of processing, but this has very
> little benefit in terms of performance: once the network thread starts
> collecting the stats, it would use the lock until collection is
> completed, blocking the signaling thread trying to acquire that lock
> anyway. This defeats the purpose and is a riskier change, since
> cancelling partial collection in this inherently racy edge-case would
> have observable differences from the returned stats, which may cause
> more regressions.
>
> Bug: chromium:850907
> Change-Id: Idceeee0bddc0c9d5518b58a2b263abb2bbf47cff
> Reviewed-on: https://webrtc-review.googlesource.com/c/121567
> Commit-Queue: Henrik Boström <hbos@webrtc.org>
> Reviewed-by: Steve Anton <steveanton@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#26707}
TBR=steveanton@webrtc.org
Bug: chromium:850907
Change-Id: I5be7f69f0de65ff1120e4926fbf904def97ea9c0
Reviewed-on: https://webrtc-review.googlesource.com/c/124781
Reviewed-by: Henrik Boström <hbos@webrtc.org>
Reviewed-by: Steve Anton <steveanton@webrtc.org>
Commit-Queue: Henrik Boström <hbos@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#26896}
2019-02-28 09:49:31 +01:00
|
|
|
// |network_report_| is currently the only partial report collected
|
|
|
|
|
// asynchronously, so |num_pending_partial_reports_| must now be 0 and we are
|
|
|
|
|
// ready to deliver the result.
|
|
|
|
|
RTC_DCHECK_EQ(num_pending_partial_reports_, 0);
|
|
|
|
|
cache_timestamp_us_ = partial_report_timestamp_us_;
|
|
|
|
|
cached_report_ = partial_report_;
|
|
|
|
|
partial_report_ = nullptr;
|
|
|
|
|
transceiver_stats_infos_.clear();
|
|
|
|
|
// Trace WebRTC Stats when getStats is called on Javascript.
|
|
|
|
|
// This allows access to WebRTC stats from trace logs. To enable them,
|
|
|
|
|
// select the "webrtc_stats" category when recording traces.
|
|
|
|
|
TRACE_EVENT_INSTANT1("webrtc_stats", "webrtc_stats", "report",
|
|
|
|
|
cached_report_->ToJson());
|
|
|
|
|
|
|
|
|
|
// Deliver report and clear |requests_|.
|
|
|
|
|
std::vector<RequestInfo> requests;
|
|
|
|
|
requests.swap(requests_);
|
|
|
|
|
DeliverCachedReport(cached_report_, std::move(requests));
|
2016-09-05 01:36:50 -07:00
|
|
|
}
|
|
|
|
|
|
2018-03-08 09:53:47 -08:00
|
|
|
void RTCStatsCollector::DeliverCachedReport(
|
|
|
|
|
rtc::scoped_refptr<const RTCStatsReport> cached_report,
|
2018-03-19 13:52:56 +01:00
|
|
|
std::vector<RTCStatsCollector::RequestInfo> requests) {
|
2021-04-08 15:18:05 +02:00
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread_);
|
2018-03-19 13:52:56 +01:00
|
|
|
RTC_DCHECK(!requests.empty());
|
2018-03-08 09:53:47 -08:00
|
|
|
RTC_DCHECK(cached_report);
|
2018-03-06 09:42:25 -08:00
|
|
|
|
2018-03-19 13:52:56 +01:00
|
|
|
for (const RequestInfo& request : requests) {
|
|
|
|
|
if (request.filter_mode() == RequestInfo::FilterMode::kAll) {
|
|
|
|
|
request.callback()->OnStatsDelivered(cached_report);
|
|
|
|
|
} else {
|
|
|
|
|
bool filter_by_sender_selector;
|
|
|
|
|
rtc::scoped_refptr<RtpSenderInternal> sender_selector;
|
|
|
|
|
rtc::scoped_refptr<RtpReceiverInternal> receiver_selector;
|
|
|
|
|
if (request.filter_mode() == RequestInfo::FilterMode::kSenderSelector) {
|
|
|
|
|
filter_by_sender_selector = true;
|
|
|
|
|
sender_selector = request.sender_selector();
|
|
|
|
|
} else {
|
|
|
|
|
RTC_DCHECK(request.filter_mode() ==
|
|
|
|
|
RequestInfo::FilterMode::kReceiverSelector);
|
|
|
|
|
filter_by_sender_selector = false;
|
|
|
|
|
receiver_selector = request.receiver_selector();
|
|
|
|
|
}
|
|
|
|
|
request.callback()->OnStatsDelivered(CreateReportFilteredBySelector(
|
|
|
|
|
filter_by_sender_selector, cached_report, sender_selector,
|
|
|
|
|
receiver_selector));
|
|
|
|
|
}
|
2016-09-05 01:36:50 -07:00
|
|
|
}
|
2016-08-30 14:04:35 -07:00
|
|
|
}
|
|
|
|
|
|
2016-12-19 04:58:02 -08:00
|
|
|
void RTCStatsCollector::ProduceCertificateStats_n(
|
2016-10-24 04:00:05 -07:00
|
|
|
int64_t timestamp_us,
|
|
|
|
|
const std::map<std::string, CertificateStatsPair>& transport_cert_stats,
|
2016-10-03 14:16:56 -07:00
|
|
|
RTCStatsReport* report) const {
|
2021-04-08 15:18:05 +02:00
|
|
|
RTC_DCHECK_RUN_ON(network_thread_);
|
2020-07-08 11:18:50 +02:00
|
|
|
rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls;
|
|
|
|
|
|
2016-10-28 05:14:53 -07:00
|
|
|
for (const auto& transport_cert_stats_pair : transport_cert_stats) {
|
|
|
|
|
if (transport_cert_stats_pair.second.local) {
|
|
|
|
|
ProduceCertificateStatsFromSSLCertificateStats(
|
|
|
|
|
timestamp_us, *transport_cert_stats_pair.second.local.get(), report);
|
2016-10-03 14:16:56 -07:00
|
|
|
}
|
2016-10-28 05:14:53 -07:00
|
|
|
if (transport_cert_stats_pair.second.remote) {
|
|
|
|
|
ProduceCertificateStatsFromSSLCertificateStats(
|
|
|
|
|
timestamp_us, *transport_cert_stats_pair.second.remote.get(), report);
|
2016-10-03 14:16:56 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-12-19 04:58:02 -08:00
|
|
|
void RTCStatsCollector::ProduceCodecStats_n(
|
2018-02-15 15:19:50 -08:00
|
|
|
int64_t timestamp_us,
|
|
|
|
|
const std::vector<RtpTransceiverStatsInfo>& transceiver_stats_infos,
|
2016-11-23 02:32:06 -08:00
|
|
|
RTCStatsReport* report) const {
|
2021-04-08 15:18:05 +02:00
|
|
|
RTC_DCHECK_RUN_ON(network_thread_);
|
2020-07-08 11:18:50 +02:00
|
|
|
rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls;
|
|
|
|
|
|
2018-02-15 15:19:50 -08:00
|
|
|
for (const auto& stats : transceiver_stats_infos) {
|
|
|
|
|
if (!stats.mid) {
|
|
|
|
|
continue;
|
2018-02-15 16:36:19 +00:00
|
|
|
}
|
2020-11-16 20:08:27 +01:00
|
|
|
std::string transport_id = RTCTransportStatsIDFromTransportChannel(
|
|
|
|
|
*stats.transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTP);
|
|
|
|
|
|
2018-02-15 15:19:50 -08:00
|
|
|
const cricket::VoiceMediaInfo* voice_media_info =
|
|
|
|
|
stats.track_media_info_map->voice_media_info();
|
|
|
|
|
const cricket::VideoMediaInfo* video_media_info =
|
|
|
|
|
stats.track_media_info_map->video_media_info();
|
|
|
|
|
// Audio
|
|
|
|
|
if (voice_media_info) {
|
|
|
|
|
// Inbound
|
|
|
|
|
for (const auto& pair : voice_media_info->receive_codecs) {
|
|
|
|
|
report->AddStats(CodecStatsFromRtpCodecParameters(
|
2020-11-16 20:08:27 +01:00
|
|
|
timestamp_us, *stats.mid, transport_id, true, pair.second));
|
2018-02-15 15:19:50 -08:00
|
|
|
}
|
|
|
|
|
// Outbound
|
|
|
|
|
for (const auto& pair : voice_media_info->send_codecs) {
|
|
|
|
|
report->AddStats(CodecStatsFromRtpCodecParameters(
|
2020-11-16 20:08:27 +01:00
|
|
|
timestamp_us, *stats.mid, transport_id, false, pair.second));
|
2018-02-15 15:19:50 -08:00
|
|
|
}
|
2018-02-15 16:36:19 +00:00
|
|
|
}
|
2018-02-15 15:19:50 -08:00
|
|
|
// Video
|
|
|
|
|
if (video_media_info) {
|
|
|
|
|
// Inbound
|
|
|
|
|
for (const auto& pair : video_media_info->receive_codecs) {
|
|
|
|
|
report->AddStats(CodecStatsFromRtpCodecParameters(
|
2020-11-16 20:08:27 +01:00
|
|
|
timestamp_us, *stats.mid, transport_id, true, pair.second));
|
2018-02-15 15:19:50 -08:00
|
|
|
}
|
|
|
|
|
// Outbound
|
|
|
|
|
for (const auto& pair : video_media_info->send_codecs) {
|
|
|
|
|
report->AddStats(CodecStatsFromRtpCodecParameters(
|
2020-11-16 20:08:27 +01:00
|
|
|
timestamp_us, *stats.mid, transport_id, false, pair.second));
|
2018-02-15 15:19:50 -08:00
|
|
|
}
|
2016-11-23 02:32:06 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-10-18 12:48:31 -07:00
|
|
|
void RTCStatsCollector::ProduceDataChannelStats_s(
|
|
|
|
|
int64_t timestamp_us,
|
|
|
|
|
RTCStatsReport* report) const {
|
2020-06-16 16:54:10 +02:00
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread_);
|
2020-07-08 11:18:50 +02:00
|
|
|
rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls;
|
2020-07-09 15:32:34 -07:00
|
|
|
std::vector<DataChannelStats> data_stats = pc_->GetDataChannelStats();
|
2020-06-16 16:54:10 +02:00
|
|
|
for (const auto& stats : data_stats) {
|
2016-10-18 12:48:31 -07:00
|
|
|
std::unique_ptr<RTCDataChannelStats> data_channel_stats(
|
|
|
|
|
new RTCDataChannelStats(
|
2020-06-16 16:54:10 +02:00
|
|
|
"RTCDataChannel_" + rtc::ToString(stats.internal_id),
|
2016-10-18 12:48:31 -07:00
|
|
|
timestamp_us));
|
2020-06-16 16:54:10 +02:00
|
|
|
data_channel_stats->label = std::move(stats.label);
|
|
|
|
|
data_channel_stats->protocol = std::move(stats.protocol);
|
|
|
|
|
data_channel_stats->data_channel_identifier = stats.id;
|
|
|
|
|
data_channel_stats->state = DataStateToRTCDataChannelState(stats.state);
|
|
|
|
|
data_channel_stats->messages_sent = stats.messages_sent;
|
|
|
|
|
data_channel_stats->bytes_sent = stats.bytes_sent;
|
|
|
|
|
data_channel_stats->messages_received = stats.messages_received;
|
|
|
|
|
data_channel_stats->bytes_received = stats.bytes_received;
|
2016-10-18 12:48:31 -07:00
|
|
|
report->AddStats(std::move(data_channel_stats));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-12-19 04:58:02 -08:00
|
|
|
void RTCStatsCollector::ProduceIceCandidateAndPairStats_n(
|
2017-06-02 06:44:03 -07:00
|
|
|
int64_t timestamp_us,
|
2018-02-06 10:34:40 -08:00
|
|
|
const std::map<std::string, cricket::TransportStats>&
|
|
|
|
|
transport_stats_by_name,
|
2017-06-02 06:44:03 -07:00
|
|
|
const Call::Stats& call_stats,
|
|
|
|
|
RTCStatsReport* report) const {
|
2021-04-08 15:18:05 +02:00
|
|
|
RTC_DCHECK_RUN_ON(network_thread_);
|
2020-07-08 11:18:50 +02:00
|
|
|
rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls;
|
|
|
|
|
|
2018-02-06 10:34:40 -08:00
|
|
|
for (const auto& entry : transport_stats_by_name) {
|
|
|
|
|
const std::string& transport_name = entry.first;
|
|
|
|
|
const cricket::TransportStats& transport_stats = entry.second;
|
|
|
|
|
for (const auto& channel_stats : transport_stats.channel_stats) {
|
2016-11-30 01:50:14 -08:00
|
|
|
std::string transport_id = RTCTransportStatsIDFromTransportChannel(
|
2018-02-06 10:34:40 -08:00
|
|
|
transport_name, channel_stats.component);
|
2016-10-11 14:54:49 -07:00
|
|
|
for (const cricket::ConnectionInfo& info :
|
2019-08-28 08:10:27 +02:00
|
|
|
channel_stats.ice_transport_stats.connection_infos) {
|
2016-10-11 14:54:49 -07:00
|
|
|
std::unique_ptr<RTCIceCandidatePairStats> candidate_pair_stats(
|
2016-10-24 04:00:05 -07:00
|
|
|
new RTCIceCandidatePairStats(
|
|
|
|
|
RTCIceCandidatePairStatsIDFromConnectionInfo(info),
|
|
|
|
|
timestamp_us));
|
2016-10-11 14:54:49 -07:00
|
|
|
|
2016-11-30 01:50:14 -08:00
|
|
|
candidate_pair_stats->transport_id = transport_id;
|
2016-10-07 02:18:47 -07:00
|
|
|
// TODO(hbos): There could be other candidates that are not paired with
|
|
|
|
|
// anything. We don't have a complete list. Local candidates come from
|
|
|
|
|
// Port objects, and prflx candidates (both local and remote) are only
|
2018-01-02 14:08:34 +01:00
|
|
|
// stored in candidate pairs. https://crbug.com/632723
|
2016-10-28 05:14:53 -07:00
|
|
|
candidate_pair_stats->local_candidate_id = ProduceIceCandidateStats(
|
2017-01-02 09:59:31 -08:00
|
|
|
timestamp_us, info.local_candidate, true, transport_id, report);
|
2016-10-28 05:14:53 -07:00
|
|
|
candidate_pair_stats->remote_candidate_id = ProduceIceCandidateStats(
|
2017-01-02 09:59:31 -08:00
|
|
|
timestamp_us, info.remote_candidate, false, transport_id, report);
|
2017-01-02 08:08:18 -08:00
|
|
|
candidate_pair_stats->state =
|
|
|
|
|
IceCandidatePairStateToRTCStatsIceCandidatePairState(info.state);
|
|
|
|
|
candidate_pair_stats->priority = info.priority;
|
2017-02-27 01:38:08 -08:00
|
|
|
candidate_pair_stats->nominated = info.nominated;
|
2016-10-11 14:54:49 -07:00
|
|
|
// TODO(hbos): This writable is different than the spec. It goes to
|
|
|
|
|
// false after a certain amount of time without a response passes.
|
2018-01-02 14:08:34 +01:00
|
|
|
// https://crbug.com/633550
|
2016-10-11 14:54:49 -07:00
|
|
|
candidate_pair_stats->writable = info.writable;
|
|
|
|
|
candidate_pair_stats->bytes_sent =
|
|
|
|
|
static_cast<uint64_t>(info.sent_total_bytes);
|
|
|
|
|
candidate_pair_stats->bytes_received =
|
|
|
|
|
static_cast<uint64_t>(info.recv_total_bytes);
|
2017-02-28 06:34:47 -08:00
|
|
|
candidate_pair_stats->total_round_trip_time =
|
|
|
|
|
static_cast<double>(info.total_round_trip_time_ms) /
|
|
|
|
|
rtc::kNumMillisecsPerSec;
|
|
|
|
|
if (info.current_round_trip_time_ms) {
|
|
|
|
|
candidate_pair_stats->current_round_trip_time =
|
|
|
|
|
static_cast<double>(*info.current_round_trip_time_ms) /
|
|
|
|
|
rtc::kNumMillisecsPerSec;
|
|
|
|
|
}
|
2017-06-02 06:44:03 -07:00
|
|
|
if (info.best_connection) {
|
2017-02-07 06:41:21 -08:00
|
|
|
// The bandwidth estimations we have are for the selected candidate
|
|
|
|
|
// pair ("info.best_connection").
|
2017-06-02 06:44:03 -07:00
|
|
|
RTC_DCHECK_GE(call_stats.send_bandwidth_bps, 0);
|
|
|
|
|
RTC_DCHECK_GE(call_stats.recv_bandwidth_bps, 0);
|
|
|
|
|
if (call_stats.send_bandwidth_bps > 0) {
|
2017-02-07 06:41:21 -08:00
|
|
|
candidate_pair_stats->available_outgoing_bitrate =
|
2017-06-02 06:44:03 -07:00
|
|
|
static_cast<double>(call_stats.send_bandwidth_bps);
|
2017-02-07 06:41:21 -08:00
|
|
|
}
|
2017-06-02 06:44:03 -07:00
|
|
|
if (call_stats.recv_bandwidth_bps > 0) {
|
2017-02-07 06:41:21 -08:00
|
|
|
candidate_pair_stats->available_incoming_bitrate =
|
2017-06-02 06:44:03 -07:00
|
|
|
static_cast<double>(call_stats.recv_bandwidth_bps);
|
2017-02-07 06:41:21 -08:00
|
|
|
}
|
|
|
|
|
}
|
2016-12-09 04:12:39 -08:00
|
|
|
candidate_pair_stats->requests_received =
|
|
|
|
|
static_cast<uint64_t>(info.recv_ping_requests);
|
2016-12-12 01:22:53 -08:00
|
|
|
candidate_pair_stats->requests_sent = static_cast<uint64_t>(
|
|
|
|
|
info.sent_ping_requests_before_first_response);
|
2016-10-11 14:54:49 -07:00
|
|
|
candidate_pair_stats->responses_received =
|
|
|
|
|
static_cast<uint64_t>(info.recv_ping_responses);
|
|
|
|
|
candidate_pair_stats->responses_sent =
|
|
|
|
|
static_cast<uint64_t>(info.sent_ping_responses);
|
2016-12-12 01:22:53 -08:00
|
|
|
RTC_DCHECK_GE(info.sent_ping_requests_total,
|
|
|
|
|
info.sent_ping_requests_before_first_response);
|
|
|
|
|
candidate_pair_stats->consent_requests_sent = static_cast<uint64_t>(
|
|
|
|
|
info.sent_ping_requests_total -
|
|
|
|
|
info.sent_ping_requests_before_first_response);
|
2016-10-11 14:54:49 -07:00
|
|
|
|
|
|
|
|
report->AddStats(std::move(candidate_pair_stats));
|
2016-10-07 02:18:47 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-02-15 15:19:50 -08:00
|
|
|
void RTCStatsCollector::ProduceMediaStreamStats_s(
|
|
|
|
|
int64_t timestamp_us,
|
|
|
|
|
RTCStatsReport* report) const {
|
2021-04-08 15:18:05 +02:00
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread_);
|
2020-07-08 11:18:50 +02:00
|
|
|
rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls;
|
2018-02-15 15:19:50 -08:00
|
|
|
|
|
|
|
|
std::map<std::string, std::vector<std::string>> track_ids;
|
|
|
|
|
|
|
|
|
|
for (const auto& stats : transceiver_stats_infos_) {
|
2019-01-27 17:29:42 +01:00
|
|
|
for (const auto& sender : stats.transceiver->senders()) {
|
2018-02-15 15:19:50 -08:00
|
|
|
std::string track_id =
|
|
|
|
|
RTCMediaStreamTrackStatsIDFromDirectionAndAttachment(
|
|
|
|
|
kSender, sender->internal()->AttachmentId());
|
|
|
|
|
for (auto& stream_id : sender->stream_ids()) {
|
|
|
|
|
track_ids[stream_id].push_back(track_id);
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-01-27 17:29:42 +01:00
|
|
|
for (const auto& receiver : stats.transceiver->receivers()) {
|
2018-02-15 15:19:50 -08:00
|
|
|
std::string track_id =
|
|
|
|
|
RTCMediaStreamTrackStatsIDFromDirectionAndAttachment(
|
|
|
|
|
kReceiver, receiver->internal()->AttachmentId());
|
|
|
|
|
for (auto& stream : receiver->streams()) {
|
2018-03-13 16:05:28 -07:00
|
|
|
track_ids[stream->id()].push_back(track_id);
|
2018-02-15 15:19:50 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Build stats for each stream ID known.
|
|
|
|
|
for (auto& it : track_ids) {
|
|
|
|
|
std::unique_ptr<RTCMediaStreamStats> stream_stats(
|
|
|
|
|
new RTCMediaStreamStats("RTCMediaStream_" + it.first, timestamp_us));
|
|
|
|
|
stream_stats->stream_identifier = it.first;
|
|
|
|
|
stream_stats->track_ids = it.second;
|
|
|
|
|
report->AddStats(std::move(stream_stats));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void RTCStatsCollector::ProduceMediaStreamTrackStats_s(
|
|
|
|
|
int64_t timestamp_us,
|
|
|
|
|
RTCStatsReport* report) const {
|
2021-04-08 15:18:05 +02:00
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread_);
|
2020-07-08 11:18:50 +02:00
|
|
|
rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls;
|
|
|
|
|
|
2018-02-15 15:19:50 -08:00
|
|
|
for (const RtpTransceiverStatsInfo& stats : transceiver_stats_infos_) {
|
|
|
|
|
std::vector<rtc::scoped_refptr<RtpSenderInternal>> senders;
|
2019-01-27 17:29:42 +01:00
|
|
|
for (const auto& sender : stats.transceiver->senders()) {
|
2018-02-15 15:19:50 -08:00
|
|
|
senders.push_back(sender->internal());
|
|
|
|
|
}
|
|
|
|
|
ProduceSenderMediaTrackStats(timestamp_us, *stats.track_media_info_map,
|
|
|
|
|
senders, report);
|
|
|
|
|
|
|
|
|
|
std::vector<rtc::scoped_refptr<RtpReceiverInternal>> receivers;
|
2019-01-27 17:29:42 +01:00
|
|
|
for (const auto& receiver : stats.transceiver->receivers()) {
|
2018-02-15 15:19:50 -08:00
|
|
|
receivers.push_back(receiver->internal());
|
|
|
|
|
}
|
|
|
|
|
ProduceReceiverMediaTrackStats(timestamp_us, *stats.track_media_info_map,
|
|
|
|
|
receivers, report);
|
|
|
|
|
}
|
2016-11-08 06:29:22 -08:00
|
|
|
}
|
|
|
|
|
|
2019-05-22 15:49:42 +02:00
|
|
|
void RTCStatsCollector::ProduceMediaSourceStats_s(
|
|
|
|
|
int64_t timestamp_us,
|
|
|
|
|
RTCStatsReport* report) const {
|
2021-04-08 15:18:05 +02:00
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread_);
|
2020-07-08 11:18:50 +02:00
|
|
|
rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls;
|
|
|
|
|
|
2019-05-22 15:49:42 +02:00
|
|
|
for (const RtpTransceiverStatsInfo& transceiver_stats_info :
|
|
|
|
|
transceiver_stats_infos_) {
|
|
|
|
|
const auto& track_media_info_map =
|
|
|
|
|
transceiver_stats_info.track_media_info_map;
|
|
|
|
|
for (const auto& sender : transceiver_stats_info.transceiver->senders()) {
|
|
|
|
|
const auto& sender_internal = sender->internal();
|
|
|
|
|
const auto& track = sender_internal->track();
|
|
|
|
|
if (!track)
|
|
|
|
|
continue;
|
[getStats] Implement "media-source" audio levels, fixing Chrome bug.
Implements RTCAudioSourceStats members:
- audioLevel
- totalAudioEnergy
- totalSamplesDuration
In this CL description these are collectively referred to as the audio
levels.
The audio levels are removed from sending "track" stats (in Chrome,
these are now reported as undefined instead of 0).
Background:
For sending tracks, audio levels were always reported as 0 in Chrome
(https://crbug.com/736403), while audio levels were correctly reported
for receiving tracks. This problem affected the standard getStats() but
not the legacy getStats(), blocking some people from migrating. This
was likely not a problem in native third_party/webrtc code because the
delivery of audio frames from device to send-stream uses a different
code path outside of chromium.
A recent PR (https://github.com/w3c/webrtc-stats/pull/451) moved the
send-side audio levels to the RTCAudioSourceStats, while keeping the
receive-side audio levels on the "track" stats. This allows an
implementation to report the audio levels even if samples are not sent
onto the network (such as if an ICE connection has not been established
yet), reflecting some of the current implementation.
Changes:
1. Audio levels are added to RTCAudioSourceStats. Send-side audio
"track" stats are left undefined. Receive-side audio "track" stats
are not changed in this CL and continue to work.
2. Audio level computation is moved from the AudioState and
AudioTransportImpl to the AudioSendStream. This is because a) the
AudioTransportImpl::RecordedDataIsAvailable() code path is not
exercised in chromium, and b) audio levels should, per-spec, not be
calculated on a per-call basis, for which the AudioState is defined.
3. The audio level computation is now performed in
AudioSendStream::SendAudioData(), a code path used by both native
and chromium code.
4. Comments are added to document behavior of existing code, such as
AudioLevel and AudioSendStream::SendAudioData().
Note:
In this CL, just like before this CL, audio level is only calculated
after an AudioSendStream has been created. This means that before an
O/A negotiation, audio levels are unavailable.
According to spec, if we have an audio source, we should have audio
levels. An immediate solution to this would have been to calculate the
audio level at pc/rtp_sender.cc. The problem is that the
LocalAudioSinkAdapter::OnData() code path, while exercised in chromium,
is not exercised in native code. The issue of calculating audio levels
on a per-source bases rather than on a per-send stream basis is left to
https://crbug.com/webrtc/10771, an existing "media-source" bug.
This CL can be verified manually in Chrome at:
https://codepen.io/anon/pen/vqRGyq
Bug: chromium:736403, webrtc:10771
Change-Id: I8036cd9984f3b187c3177470a8c0d6670a201a5a
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/143789
Reviewed-by: Oskar Sundbom <ossu@webrtc.org>
Reviewed-by: Stefan Holmer <stefan@webrtc.org>
Commit-Queue: Henrik Boström <hbos@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#28480}
2019-07-03 17:11:10 +02:00
|
|
|
// TODO(https://crbug.com/webrtc/10771): The same track could be attached
|
|
|
|
|
// to multiple senders which should result in multiple senders referencing
|
|
|
|
|
// the same media-source stats. When all media source related metrics are
|
|
|
|
|
// moved to the track's source (e.g. input frame rate is moved from
|
|
|
|
|
// cricket::VideoSenderInfo to VideoTrackSourceInterface::Stats and audio
|
|
|
|
|
// levels are moved to the corresponding audio track/source object), don't
|
|
|
|
|
// create separate media source stats objects on a per-attachment basis.
|
2019-05-22 15:49:42 +02:00
|
|
|
std::unique_ptr<RTCMediaSourceStats> media_source_stats;
|
|
|
|
|
if (track->kind() == MediaStreamTrackInterface::kAudioKind) {
|
2019-09-17 17:06:18 +02:00
|
|
|
auto audio_source_stats = std::make_unique<RTCAudioSourceStats>(
|
2019-05-22 15:49:42 +02:00
|
|
|
RTCMediaSourceStatsIDFromKindAndAttachment(
|
|
|
|
|
cricket::MEDIA_TYPE_AUDIO, sender_internal->AttachmentId()),
|
|
|
|
|
timestamp_us);
|
[getStats] Implement "media-source" audio levels, fixing Chrome bug.
Implements RTCAudioSourceStats members:
- audioLevel
- totalAudioEnergy
- totalSamplesDuration
In this CL description these are collectively referred to as the audio
levels.
The audio levels are removed from sending "track" stats (in Chrome,
these are now reported as undefined instead of 0).
Background:
For sending tracks, audio levels were always reported as 0 in Chrome
(https://crbug.com/736403), while audio levels were correctly reported
for receiving tracks. This problem affected the standard getStats() but
not the legacy getStats(), blocking some people from migrating. This
was likely not a problem in native third_party/webrtc code because the
delivery of audio frames from device to send-stream uses a different
code path outside of chromium.
A recent PR (https://github.com/w3c/webrtc-stats/pull/451) moved the
send-side audio levels to the RTCAudioSourceStats, while keeping the
receive-side audio levels on the "track" stats. This allows an
implementation to report the audio levels even if samples are not sent
onto the network (such as if an ICE connection has not been established
yet), reflecting some of the current implementation.
Changes:
1. Audio levels are added to RTCAudioSourceStats. Send-side audio
"track" stats are left undefined. Receive-side audio "track" stats
are not changed in this CL and continue to work.
2. Audio level computation is moved from the AudioState and
AudioTransportImpl to the AudioSendStream. This is because a) the
AudioTransportImpl::RecordedDataIsAvailable() code path is not
exercised in chromium, and b) audio levels should, per-spec, not be
calculated on a per-call basis, for which the AudioState is defined.
3. The audio level computation is now performed in
AudioSendStream::SendAudioData(), a code path used by both native
and chromium code.
4. Comments are added to document behavior of existing code, such as
AudioLevel and AudioSendStream::SendAudioData().
Note:
In this CL, just like before this CL, audio level is only calculated
after an AudioSendStream has been created. This means that before an
O/A negotiation, audio levels are unavailable.
According to spec, if we have an audio source, we should have audio
levels. An immediate solution to this would have been to calculate the
audio level at pc/rtp_sender.cc. The problem is that the
LocalAudioSinkAdapter::OnData() code path, while exercised in chromium,
is not exercised in native code. The issue of calculating audio levels
on a per-source bases rather than on a per-send stream basis is left to
https://crbug.com/webrtc/10771, an existing "media-source" bug.
This CL can be verified manually in Chrome at:
https://codepen.io/anon/pen/vqRGyq
Bug: chromium:736403, webrtc:10771
Change-Id: I8036cd9984f3b187c3177470a8c0d6670a201a5a
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/143789
Reviewed-by: Oskar Sundbom <ossu@webrtc.org>
Reviewed-by: Stefan Holmer <stefan@webrtc.org>
Commit-Queue: Henrik Boström <hbos@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#28480}
2019-07-03 17:11:10 +02:00
|
|
|
// TODO(https://crbug.com/webrtc/10771): We shouldn't need to have an
|
|
|
|
|
// SSRC assigned (there shouldn't need to exist a send-stream, created
|
|
|
|
|
// by an O/A exchange) in order to read audio media-source stats.
|
|
|
|
|
// TODO(https://crbug.com/webrtc/8694): SSRC 0 shouldn't be a magic
|
|
|
|
|
// value indicating no SSRC.
|
|
|
|
|
if (sender_internal->ssrc() != 0) {
|
|
|
|
|
auto* voice_sender_info =
|
|
|
|
|
track_media_info_map->GetVoiceSenderInfoBySsrc(
|
|
|
|
|
sender_internal->ssrc());
|
|
|
|
|
if (voice_sender_info) {
|
|
|
|
|
audio_source_stats->audio_level = DoubleAudioLevelFromIntAudioLevel(
|
|
|
|
|
voice_sender_info->audio_level);
|
|
|
|
|
audio_source_stats->total_audio_energy =
|
|
|
|
|
voice_sender_info->total_input_energy;
|
|
|
|
|
audio_source_stats->total_samples_duration =
|
|
|
|
|
voice_sender_info->total_input_duration;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
media_source_stats = std::move(audio_source_stats);
|
2019-05-22 15:49:42 +02:00
|
|
|
} else {
|
|
|
|
|
RTC_DCHECK_EQ(MediaStreamTrackInterface::kVideoKind, track->kind());
|
2019-09-17 17:06:18 +02:00
|
|
|
auto video_source_stats = std::make_unique<RTCVideoSourceStats>(
|
2019-05-22 15:49:42 +02:00
|
|
|
RTCMediaSourceStatsIDFromKindAndAttachment(
|
|
|
|
|
cricket::MEDIA_TYPE_VIDEO, sender_internal->AttachmentId()),
|
|
|
|
|
timestamp_us);
|
|
|
|
|
auto* video_track = static_cast<VideoTrackInterface*>(track.get());
|
|
|
|
|
auto* video_source = video_track->GetSource();
|
|
|
|
|
VideoTrackSourceInterface::Stats source_stats;
|
|
|
|
|
if (video_source && video_source->GetStats(&source_stats)) {
|
|
|
|
|
video_source_stats->width = source_stats.input_width;
|
|
|
|
|
video_source_stats->height = source_stats.input_height;
|
|
|
|
|
}
|
[getStats] Implement "media-source" audio levels, fixing Chrome bug.
Implements RTCAudioSourceStats members:
- audioLevel
- totalAudioEnergy
- totalSamplesDuration
In this CL description these are collectively referred to as the audio
levels.
The audio levels are removed from sending "track" stats (in Chrome,
these are now reported as undefined instead of 0).
Background:
For sending tracks, audio levels were always reported as 0 in Chrome
(https://crbug.com/736403), while audio levels were correctly reported
for receiving tracks. This problem affected the standard getStats() but
not the legacy getStats(), blocking some people from migrating. This
was likely not a problem in native third_party/webrtc code because the
delivery of audio frames from device to send-stream uses a different
code path outside of chromium.
A recent PR (https://github.com/w3c/webrtc-stats/pull/451) moved the
send-side audio levels to the RTCAudioSourceStats, while keeping the
receive-side audio levels on the "track" stats. This allows an
implementation to report the audio levels even if samples are not sent
onto the network (such as if an ICE connection has not been established
yet), reflecting some of the current implementation.
Changes:
1. Audio levels are added to RTCAudioSourceStats. Send-side audio
"track" stats are left undefined. Receive-side audio "track" stats
are not changed in this CL and continue to work.
2. Audio level computation is moved from the AudioState and
AudioTransportImpl to the AudioSendStream. This is because a) the
AudioTransportImpl::RecordedDataIsAvailable() code path is not
exercised in chromium, and b) audio levels should, per-spec, not be
calculated on a per-call basis, for which the AudioState is defined.
3. The audio level computation is now performed in
AudioSendStream::SendAudioData(), a code path used by both native
and chromium code.
4. Comments are added to document behavior of existing code, such as
AudioLevel and AudioSendStream::SendAudioData().
Note:
In this CL, just like before this CL, audio level is only calculated
after an AudioSendStream has been created. This means that before an
O/A negotiation, audio levels are unavailable.
According to spec, if we have an audio source, we should have audio
levels. An immediate solution to this would have been to calculate the
audio level at pc/rtp_sender.cc. The problem is that the
LocalAudioSinkAdapter::OnData() code path, while exercised in chromium,
is not exercised in native code. The issue of calculating audio levels
on a per-source bases rather than on a per-send stream basis is left to
https://crbug.com/webrtc/10771, an existing "media-source" bug.
This CL can be verified manually in Chrome at:
https://codepen.io/anon/pen/vqRGyq
Bug: chromium:736403, webrtc:10771
Change-Id: I8036cd9984f3b187c3177470a8c0d6670a201a5a
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/143789
Reviewed-by: Oskar Sundbom <ossu@webrtc.org>
Reviewed-by: Stefan Holmer <stefan@webrtc.org>
Commit-Queue: Henrik Boström <hbos@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#28480}
2019-07-03 17:11:10 +02:00
|
|
|
// TODO(https://crbug.com/webrtc/10771): We shouldn't need to have an
|
|
|
|
|
// SSRC assigned (there shouldn't need to exist a send-stream, created
|
|
|
|
|
// by an O/A exchange) in order to get framesPerSecond.
|
|
|
|
|
// TODO(https://crbug.com/webrtc/8694): SSRC 0 shouldn't be a magic
|
|
|
|
|
// value indicating no SSRC.
|
2019-05-22 15:49:42 +02:00
|
|
|
if (sender_internal->ssrc() != 0) {
|
[getStats] Implement "media-source" audio levels, fixing Chrome bug.
Implements RTCAudioSourceStats members:
- audioLevel
- totalAudioEnergy
- totalSamplesDuration
In this CL description these are collectively referred to as the audio
levels.
The audio levels are removed from sending "track" stats (in Chrome,
these are now reported as undefined instead of 0).
Background:
For sending tracks, audio levels were always reported as 0 in Chrome
(https://crbug.com/736403), while audio levels were correctly reported
for receiving tracks. This problem affected the standard getStats() but
not the legacy getStats(), blocking some people from migrating. This
was likely not a problem in native third_party/webrtc code because the
delivery of audio frames from device to send-stream uses a different
code path outside of chromium.
A recent PR (https://github.com/w3c/webrtc-stats/pull/451) moved the
send-side audio levels to the RTCAudioSourceStats, while keeping the
receive-side audio levels on the "track" stats. This allows an
implementation to report the audio levels even if samples are not sent
onto the network (such as if an ICE connection has not been established
yet), reflecting some of the current implementation.
Changes:
1. Audio levels are added to RTCAudioSourceStats. Send-side audio
"track" stats are left undefined. Receive-side audio "track" stats
are not changed in this CL and continue to work.
2. Audio level computation is moved from the AudioState and
AudioTransportImpl to the AudioSendStream. This is because a) the
AudioTransportImpl::RecordedDataIsAvailable() code path is not
exercised in chromium, and b) audio levels should, per-spec, not be
calculated on a per-call basis, for which the AudioState is defined.
3. The audio level computation is now performed in
AudioSendStream::SendAudioData(), a code path used by both native
and chromium code.
4. Comments are added to document behavior of existing code, such as
AudioLevel and AudioSendStream::SendAudioData().
Note:
In this CL, just like before this CL, audio level is only calculated
after an AudioSendStream has been created. This means that before an
O/A negotiation, audio levels are unavailable.
According to spec, if we have an audio source, we should have audio
levels. An immediate solution to this would have been to calculate the
audio level at pc/rtp_sender.cc. The problem is that the
LocalAudioSinkAdapter::OnData() code path, while exercised in chromium,
is not exercised in native code. The issue of calculating audio levels
on a per-source bases rather than on a per-send stream basis is left to
https://crbug.com/webrtc/10771, an existing "media-source" bug.
This CL can be verified manually in Chrome at:
https://codepen.io/anon/pen/vqRGyq
Bug: chromium:736403, webrtc:10771
Change-Id: I8036cd9984f3b187c3177470a8c0d6670a201a5a
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/143789
Reviewed-by: Oskar Sundbom <ossu@webrtc.org>
Reviewed-by: Stefan Holmer <stefan@webrtc.org>
Commit-Queue: Henrik Boström <hbos@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#28480}
2019-07-03 17:11:10 +02:00
|
|
|
auto* video_sender_info =
|
|
|
|
|
track_media_info_map->GetVideoSenderInfoBySsrc(
|
|
|
|
|
sender_internal->ssrc());
|
|
|
|
|
if (video_sender_info) {
|
2019-05-22 15:49:42 +02:00
|
|
|
video_source_stats->frames_per_second =
|
[getStats] Implement "media-source" audio levels, fixing Chrome bug.
Implements RTCAudioSourceStats members:
- audioLevel
- totalAudioEnergy
- totalSamplesDuration
In this CL description these are collectively referred to as the audio
levels.
The audio levels are removed from sending "track" stats (in Chrome,
these are now reported as undefined instead of 0).
Background:
For sending tracks, audio levels were always reported as 0 in Chrome
(https://crbug.com/736403), while audio levels were correctly reported
for receiving tracks. This problem affected the standard getStats() but
not the legacy getStats(), blocking some people from migrating. This
was likely not a problem in native third_party/webrtc code because the
delivery of audio frames from device to send-stream uses a different
code path outside of chromium.
A recent PR (https://github.com/w3c/webrtc-stats/pull/451) moved the
send-side audio levels to the RTCAudioSourceStats, while keeping the
receive-side audio levels on the "track" stats. This allows an
implementation to report the audio levels even if samples are not sent
onto the network (such as if an ICE connection has not been established
yet), reflecting some of the current implementation.
Changes:
1. Audio levels are added to RTCAudioSourceStats. Send-side audio
"track" stats are left undefined. Receive-side audio "track" stats
are not changed in this CL and continue to work.
2. Audio level computation is moved from the AudioState and
AudioTransportImpl to the AudioSendStream. This is because a) the
AudioTransportImpl::RecordedDataIsAvailable() code path is not
exercised in chromium, and b) audio levels should, per-spec, not be
calculated on a per-call basis, for which the AudioState is defined.
3. The audio level computation is now performed in
AudioSendStream::SendAudioData(), a code path used by both native
and chromium code.
4. Comments are added to document behavior of existing code, such as
AudioLevel and AudioSendStream::SendAudioData().
Note:
In this CL, just like before this CL, audio level is only calculated
after an AudioSendStream has been created. This means that before an
O/A negotiation, audio levels are unavailable.
According to spec, if we have an audio source, we should have audio
levels. An immediate solution to this would have been to calculate the
audio level at pc/rtp_sender.cc. The problem is that the
LocalAudioSinkAdapter::OnData() code path, while exercised in chromium,
is not exercised in native code. The issue of calculating audio levels
on a per-source bases rather than on a per-send stream basis is left to
https://crbug.com/webrtc/10771, an existing "media-source" bug.
This CL can be verified manually in Chrome at:
https://codepen.io/anon/pen/vqRGyq
Bug: chromium:736403, webrtc:10771
Change-Id: I8036cd9984f3b187c3177470a8c0d6670a201a5a
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/143789
Reviewed-by: Oskar Sundbom <ossu@webrtc.org>
Reviewed-by: Stefan Holmer <stefan@webrtc.org>
Commit-Queue: Henrik Boström <hbos@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#28480}
2019-07-03 17:11:10 +02:00
|
|
|
video_sender_info->framerate_input;
|
2021-02-27 00:29:15 -08:00
|
|
|
video_source_stats->frames = video_sender_info->frames;
|
2019-05-22 15:49:42 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
media_source_stats = std::move(video_source_stats);
|
|
|
|
|
}
|
|
|
|
|
media_source_stats->track_identifier = track->id();
|
|
|
|
|
media_source_stats->kind = track->kind();
|
|
|
|
|
report->AddStats(std::move(media_source_stats));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-10-03 14:16:56 -07:00
|
|
|
void RTCStatsCollector::ProducePeerConnectionStats_s(
|
|
|
|
|
int64_t timestamp_us,
|
|
|
|
|
RTCStatsReport* report) const {
|
2021-04-08 15:18:05 +02:00
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread_);
|
2020-07-08 11:18:50 +02:00
|
|
|
rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls;
|
|
|
|
|
|
2016-08-30 14:04:35 -07:00
|
|
|
std::unique_ptr<RTCPeerConnectionStats> stats(
|
2016-08-31 07:57:36 -07:00
|
|
|
new RTCPeerConnectionStats("RTCPeerConnection", timestamp_us));
|
2016-11-14 01:41:09 -08:00
|
|
|
stats->data_channels_opened = internal_record_.data_channels_opened;
|
|
|
|
|
stats->data_channels_closed = internal_record_.data_channels_closed;
|
2016-10-03 14:16:56 -07:00
|
|
|
report->AddStats(std::move(stats));
|
2016-08-30 14:04:35 -07:00
|
|
|
}
|
|
|
|
|
|
2016-12-19 04:58:02 -08:00
|
|
|
void RTCStatsCollector::ProduceRTPStreamStats_n(
|
2017-12-15 11:44:48 -08:00
|
|
|
int64_t timestamp_us,
|
2018-02-15 15:19:50 -08:00
|
|
|
const std::vector<RtpTransceiverStatsInfo>& transceiver_stats_infos,
|
2017-01-16 06:16:44 -08:00
|
|
|
RTCStatsReport* report) const {
|
2021-04-08 15:18:05 +02:00
|
|
|
RTC_DCHECK_RUN_ON(network_thread_);
|
2020-07-08 11:18:50 +02:00
|
|
|
rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls;
|
2016-11-01 01:50:46 -07:00
|
|
|
|
2018-02-15 15:19:50 -08:00
|
|
|
for (const RtpTransceiverStatsInfo& stats : transceiver_stats_infos) {
|
|
|
|
|
if (stats.media_type == cricket::MEDIA_TYPE_AUDIO) {
|
|
|
|
|
ProduceAudioRTPStreamStats_n(timestamp_us, stats, report);
|
|
|
|
|
} else if (stats.media_type == cricket::MEDIA_TYPE_VIDEO) {
|
|
|
|
|
ProduceVideoRTPStreamStats_n(timestamp_us, stats, report);
|
|
|
|
|
} else {
|
|
|
|
|
RTC_NOTREACHED();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-01-23 15:28:16 +01:00
|
|
|
|
2018-02-15 15:19:50 -08:00
|
|
|
void RTCStatsCollector::ProduceAudioRTPStreamStats_n(
|
|
|
|
|
int64_t timestamp_us,
|
|
|
|
|
const RtpTransceiverStatsInfo& stats,
|
|
|
|
|
RTCStatsReport* report) const {
|
2021-04-08 15:18:05 +02:00
|
|
|
RTC_DCHECK_RUN_ON(network_thread_);
|
2020-07-08 11:18:50 +02:00
|
|
|
rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls;
|
|
|
|
|
|
2018-02-15 15:19:50 -08:00
|
|
|
if (!stats.mid || !stats.transport_name) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
RTC_DCHECK(stats.track_media_info_map);
|
|
|
|
|
const TrackMediaInfoMap& track_media_info_map = *stats.track_media_info_map;
|
|
|
|
|
RTC_DCHECK(track_media_info_map.voice_media_info());
|
|
|
|
|
std::string mid = *stats.mid;
|
|
|
|
|
std::string transport_id = RTCTransportStatsIDFromTransportChannel(
|
|
|
|
|
*stats.transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTP);
|
2021-03-23 17:23:04 +01:00
|
|
|
// Inbound and remote-outbound.
|
|
|
|
|
// The remote-outbound stats are based on RTCP sender reports sent from the
|
|
|
|
|
// remote endpoint providing metrics about the remote outbound streams.
|
2018-02-15 15:19:50 -08:00
|
|
|
for (const cricket::VoiceReceiverInfo& voice_receiver_info :
|
|
|
|
|
track_media_info_map.voice_media_info()->receivers) {
|
|
|
|
|
if (!voice_receiver_info.connected())
|
|
|
|
|
continue;
|
2021-03-23 17:23:04 +01:00
|
|
|
// Inbound.
|
|
|
|
|
auto inbound_audio =
|
|
|
|
|
CreateInboundAudioStreamStats(voice_receiver_info, mid, timestamp_us);
|
2018-02-15 15:19:50 -08:00
|
|
|
// TODO(hta): This lookup should look for the sender, not the track.
|
|
|
|
|
rtc::scoped_refptr<AudioTrackInterface> audio_track =
|
|
|
|
|
track_media_info_map.GetAudioTrack(voice_receiver_info);
|
|
|
|
|
if (audio_track) {
|
|
|
|
|
inbound_audio->track_id =
|
|
|
|
|
RTCMediaStreamTrackStatsIDFromDirectionAndAttachment(
|
|
|
|
|
kReceiver,
|
|
|
|
|
track_media_info_map.GetAttachmentIdByTrack(audio_track).value());
|
2016-11-23 02:32:06 -08:00
|
|
|
}
|
2018-02-15 15:19:50 -08:00
|
|
|
inbound_audio->transport_id = transport_id;
|
2021-03-23 17:23:04 +01:00
|
|
|
// Remote-outbound.
|
|
|
|
|
auto remote_outbound_audio = CreateRemoteOutboundAudioStreamStats(
|
|
|
|
|
voice_receiver_info, mid, inbound_audio->id(), transport_id);
|
|
|
|
|
// Add stats.
|
|
|
|
|
if (remote_outbound_audio) {
|
|
|
|
|
// When the remote outbound stats are available, the remote ID for the
|
|
|
|
|
// local inbound stats is set.
|
|
|
|
|
inbound_audio->remote_id = remote_outbound_audio->id();
|
|
|
|
|
report->AddStats(std::move(remote_outbound_audio));
|
|
|
|
|
}
|
2018-02-15 15:19:50 -08:00
|
|
|
report->AddStats(std::move(inbound_audio));
|
|
|
|
|
}
|
2021-03-23 17:23:04 +01:00
|
|
|
// Outbound.
|
2019-12-19 13:27:27 +01:00
|
|
|
std::map<std::string, RTCOutboundRTPStreamStats*> audio_outbound_rtps;
|
2018-02-15 15:19:50 -08:00
|
|
|
for (const cricket::VoiceSenderInfo& voice_sender_info :
|
|
|
|
|
track_media_info_map.voice_media_info()->senders) {
|
|
|
|
|
if (!voice_sender_info.connected())
|
|
|
|
|
continue;
|
2019-09-17 17:06:18 +02:00
|
|
|
auto outbound_audio = std::make_unique<RTCOutboundRTPStreamStats>(
|
2021-03-23 17:23:04 +01:00
|
|
|
RTCOutboundRTPStreamStatsIDFromSSRC(cricket::MEDIA_TYPE_AUDIO,
|
|
|
|
|
voice_sender_info.ssrc()),
|
2018-02-15 15:19:50 -08:00
|
|
|
timestamp_us);
|
|
|
|
|
SetOutboundRTPStreamStatsFromVoiceSenderInfo(mid, voice_sender_info,
|
|
|
|
|
outbound_audio.get());
|
|
|
|
|
rtc::scoped_refptr<AudioTrackInterface> audio_track =
|
|
|
|
|
track_media_info_map.GetAudioTrack(voice_sender_info);
|
|
|
|
|
if (audio_track) {
|
2019-05-22 15:49:42 +02:00
|
|
|
int attachment_id =
|
|
|
|
|
track_media_info_map.GetAttachmentIdByTrack(audio_track).value();
|
2018-02-15 15:19:50 -08:00
|
|
|
outbound_audio->track_id =
|
2019-05-22 15:49:42 +02:00
|
|
|
RTCMediaStreamTrackStatsIDFromDirectionAndAttachment(kSender,
|
|
|
|
|
attachment_id);
|
|
|
|
|
outbound_audio->media_source_id =
|
|
|
|
|
RTCMediaSourceStatsIDFromKindAndAttachment(cricket::MEDIA_TYPE_AUDIO,
|
|
|
|
|
attachment_id);
|
2016-11-01 01:50:46 -07:00
|
|
|
}
|
2018-02-15 15:19:50 -08:00
|
|
|
outbound_audio->transport_id = transport_id;
|
2019-12-19 13:27:27 +01:00
|
|
|
audio_outbound_rtps.insert(
|
|
|
|
|
std::make_pair(outbound_audio->id(), outbound_audio.get()));
|
2018-02-15 15:19:50 -08:00
|
|
|
report->AddStats(std::move(outbound_audio));
|
2016-11-01 01:50:46 -07:00
|
|
|
}
|
2021-03-23 17:23:04 +01:00
|
|
|
// Remote-inbound.
|
Implement RTCRemoteInboundRtpStreamStats for both audio and video.
This implements the essentials of RTCRemoteInboundRtpStreamStats. This
includes:
- ssrc
- transportId
- codecId
- packetsLost
- jitter
- localId
- roundTripTime
https://w3c.github.io/webrtc-stats/#remoteinboundrtpstats-dict*
The following members are not implemented because they require more
work...
- From RTCReceivedRtpStreamStats: packetsReceived, packetsDiscarded,
packetsRepaired, burstPacketsLost, burstPacketsDiscarded,
burstLossCount, burstDiscardCount, burstLossRate, burstDiscardRate,
gapLossRate and gapDiscardRate.
- From RTCRemoteInboundRtpStreamStats: fractionLost.
Bug: webrtc:10455, webrtc:10456
Change-Id: If2ab0da7105d8c93bba58e14aa93bd22ffe57f1d
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/138067
Commit-Queue: Henrik Boström <hbos@webrtc.org>
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#28073}
2019-05-27 13:40:25 +02:00
|
|
|
// These are Report Block-based, information sent from the remote endpoint,
|
|
|
|
|
// providing metrics about our Outbound streams. We take advantage of the fact
|
|
|
|
|
// that RTCOutboundRtpStreamStats, RTCCodecStats and RTCTransport have already
|
|
|
|
|
// been added to the report.
|
|
|
|
|
for (const cricket::VoiceSenderInfo& voice_sender_info :
|
|
|
|
|
track_media_info_map.voice_media_info()->senders) {
|
|
|
|
|
for (const auto& report_block_data : voice_sender_info.report_block_datas) {
|
|
|
|
|
report->AddStats(ProduceRemoteInboundRtpStreamStatsFromReportBlockData(
|
2020-07-03 11:08:07 +03:00
|
|
|
report_block_data, cricket::MEDIA_TYPE_AUDIO, audio_outbound_rtps,
|
|
|
|
|
*report));
|
Implement RTCRemoteInboundRtpStreamStats for both audio and video.
This implements the essentials of RTCRemoteInboundRtpStreamStats. This
includes:
- ssrc
- transportId
- codecId
- packetsLost
- jitter
- localId
- roundTripTime
https://w3c.github.io/webrtc-stats/#remoteinboundrtpstats-dict*
The following members are not implemented because they require more
work...
- From RTCReceivedRtpStreamStats: packetsReceived, packetsDiscarded,
packetsRepaired, burstPacketsLost, burstPacketsDiscarded,
burstLossCount, burstDiscardCount, burstLossRate, burstDiscardRate,
gapLossRate and gapDiscardRate.
- From RTCRemoteInboundRtpStreamStats: fractionLost.
Bug: webrtc:10455, webrtc:10456
Change-Id: If2ab0da7105d8c93bba58e14aa93bd22ffe57f1d
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/138067
Commit-Queue: Henrik Boström <hbos@webrtc.org>
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#28073}
2019-05-27 13:40:25 +02:00
|
|
|
}
|
|
|
|
|
}
|
2018-02-15 15:19:50 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void RTCStatsCollector::ProduceVideoRTPStreamStats_n(
|
|
|
|
|
int64_t timestamp_us,
|
|
|
|
|
const RtpTransceiverStatsInfo& stats,
|
|
|
|
|
RTCStatsReport* report) const {
|
2021-04-08 15:18:05 +02:00
|
|
|
RTC_DCHECK_RUN_ON(network_thread_);
|
2020-07-08 11:18:50 +02:00
|
|
|
rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls;
|
|
|
|
|
|
2018-02-15 15:19:50 -08:00
|
|
|
if (!stats.mid || !stats.transport_name) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
RTC_DCHECK(stats.track_media_info_map);
|
|
|
|
|
const TrackMediaInfoMap& track_media_info_map = *stats.track_media_info_map;
|
|
|
|
|
RTC_DCHECK(track_media_info_map.video_media_info());
|
|
|
|
|
std::string mid = *stats.mid;
|
|
|
|
|
std::string transport_id = RTCTransportStatsIDFromTransportChannel(
|
|
|
|
|
*stats.transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTP);
|
|
|
|
|
// Inbound
|
|
|
|
|
for (const cricket::VideoReceiverInfo& video_receiver_info :
|
|
|
|
|
track_media_info_map.video_media_info()->receivers) {
|
|
|
|
|
if (!video_receiver_info.connected())
|
|
|
|
|
continue;
|
2019-09-17 17:06:18 +02:00
|
|
|
auto inbound_video = std::make_unique<RTCInboundRTPStreamStats>(
|
2021-03-23 17:23:04 +01:00
|
|
|
RTCInboundRTPStreamStatsIDFromSSRC(cricket::MEDIA_TYPE_VIDEO,
|
|
|
|
|
video_receiver_info.ssrc()),
|
2018-02-15 15:19:50 -08:00
|
|
|
timestamp_us);
|
|
|
|
|
SetInboundRTPStreamStatsFromVideoReceiverInfo(mid, video_receiver_info,
|
|
|
|
|
inbound_video.get());
|
|
|
|
|
rtc::scoped_refptr<VideoTrackInterface> video_track =
|
|
|
|
|
track_media_info_map.GetVideoTrack(video_receiver_info);
|
|
|
|
|
if (video_track) {
|
|
|
|
|
inbound_video->track_id =
|
|
|
|
|
RTCMediaStreamTrackStatsIDFromDirectionAndAttachment(
|
|
|
|
|
kReceiver,
|
|
|
|
|
track_media_info_map.GetAttachmentIdByTrack(video_track).value());
|
2016-11-23 02:32:06 -08:00
|
|
|
}
|
2018-02-15 15:19:50 -08:00
|
|
|
inbound_video->transport_id = transport_id;
|
|
|
|
|
report->AddStats(std::move(inbound_video));
|
2021-03-23 17:23:04 +01:00
|
|
|
// TODO(crbug.com/webrtc/12529): Add remote-outbound stats.
|
2018-02-15 15:19:50 -08:00
|
|
|
}
|
|
|
|
|
// Outbound
|
2019-12-19 13:27:27 +01:00
|
|
|
std::map<std::string, RTCOutboundRTPStreamStats*> video_outbound_rtps;
|
2018-02-15 15:19:50 -08:00
|
|
|
for (const cricket::VideoSenderInfo& video_sender_info :
|
2020-06-10 17:53:39 +03:00
|
|
|
track_media_info_map.video_media_info()->senders) {
|
2018-02-15 15:19:50 -08:00
|
|
|
if (!video_sender_info.connected())
|
|
|
|
|
continue;
|
2019-09-17 17:06:18 +02:00
|
|
|
auto outbound_video = std::make_unique<RTCOutboundRTPStreamStats>(
|
2021-03-23 17:23:04 +01:00
|
|
|
RTCOutboundRTPStreamStatsIDFromSSRC(cricket::MEDIA_TYPE_VIDEO,
|
|
|
|
|
video_sender_info.ssrc()),
|
2018-02-15 15:19:50 -08:00
|
|
|
timestamp_us);
|
2020-06-10 17:53:39 +03:00
|
|
|
SetOutboundRTPStreamStatsFromVideoSenderInfo(mid, video_sender_info,
|
|
|
|
|
outbound_video.get());
|
2018-02-15 15:19:50 -08:00
|
|
|
rtc::scoped_refptr<VideoTrackInterface> video_track =
|
|
|
|
|
track_media_info_map.GetVideoTrack(video_sender_info);
|
|
|
|
|
if (video_track) {
|
2019-05-22 15:49:42 +02:00
|
|
|
int attachment_id =
|
|
|
|
|
track_media_info_map.GetAttachmentIdByTrack(video_track).value();
|
2018-02-15 15:19:50 -08:00
|
|
|
outbound_video->track_id =
|
2019-05-22 15:49:42 +02:00
|
|
|
RTCMediaStreamTrackStatsIDFromDirectionAndAttachment(kSender,
|
|
|
|
|
attachment_id);
|
|
|
|
|
outbound_video->media_source_id =
|
|
|
|
|
RTCMediaSourceStatsIDFromKindAndAttachment(cricket::MEDIA_TYPE_VIDEO,
|
|
|
|
|
attachment_id);
|
2016-11-01 01:50:46 -07:00
|
|
|
}
|
2018-02-15 15:19:50 -08:00
|
|
|
outbound_video->transport_id = transport_id;
|
2019-12-19 13:27:27 +01:00
|
|
|
video_outbound_rtps.insert(
|
|
|
|
|
std::make_pair(outbound_video->id(), outbound_video.get()));
|
2018-02-15 15:19:50 -08:00
|
|
|
report->AddStats(std::move(outbound_video));
|
2016-11-01 01:50:46 -07:00
|
|
|
}
|
Implement RTCRemoteInboundRtpStreamStats for both audio and video.
This implements the essentials of RTCRemoteInboundRtpStreamStats. This
includes:
- ssrc
- transportId
- codecId
- packetsLost
- jitter
- localId
- roundTripTime
https://w3c.github.io/webrtc-stats/#remoteinboundrtpstats-dict*
The following members are not implemented because they require more
work...
- From RTCReceivedRtpStreamStats: packetsReceived, packetsDiscarded,
packetsRepaired, burstPacketsLost, burstPacketsDiscarded,
burstLossCount, burstDiscardCount, burstLossRate, burstDiscardRate,
gapLossRate and gapDiscardRate.
- From RTCRemoteInboundRtpStreamStats: fractionLost.
Bug: webrtc:10455, webrtc:10456
Change-Id: If2ab0da7105d8c93bba58e14aa93bd22ffe57f1d
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/138067
Commit-Queue: Henrik Boström <hbos@webrtc.org>
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#28073}
2019-05-27 13:40:25 +02:00
|
|
|
// Remote-inbound
|
|
|
|
|
// These are Report Block-based, information sent from the remote endpoint,
|
|
|
|
|
// providing metrics about our Outbound streams. We take advantage of the fact
|
|
|
|
|
// that RTCOutboundRtpStreamStats, RTCCodecStats and RTCTransport have already
|
|
|
|
|
// been added to the report.
|
|
|
|
|
for (const cricket::VideoSenderInfo& video_sender_info :
|
|
|
|
|
track_media_info_map.video_media_info()->senders) {
|
|
|
|
|
for (const auto& report_block_data : video_sender_info.report_block_datas) {
|
|
|
|
|
report->AddStats(ProduceRemoteInboundRtpStreamStatsFromReportBlockData(
|
2020-07-03 11:08:07 +03:00
|
|
|
report_block_data, cricket::MEDIA_TYPE_VIDEO, video_outbound_rtps,
|
|
|
|
|
*report));
|
Implement RTCRemoteInboundRtpStreamStats for both audio and video.
This implements the essentials of RTCRemoteInboundRtpStreamStats. This
includes:
- ssrc
- transportId
- codecId
- packetsLost
- jitter
- localId
- roundTripTime
https://w3c.github.io/webrtc-stats/#remoteinboundrtpstats-dict*
The following members are not implemented because they require more
work...
- From RTCReceivedRtpStreamStats: packetsReceived, packetsDiscarded,
packetsRepaired, burstPacketsLost, burstPacketsDiscarded,
burstLossCount, burstDiscardCount, burstLossRate, burstDiscardRate,
gapLossRate and gapDiscardRate.
- From RTCRemoteInboundRtpStreamStats: fractionLost.
Bug: webrtc:10455, webrtc:10456
Change-Id: If2ab0da7105d8c93bba58e14aa93bd22ffe57f1d
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/138067
Commit-Queue: Henrik Boström <hbos@webrtc.org>
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#28073}
2019-05-27 13:40:25 +02:00
|
|
|
}
|
|
|
|
|
}
|
2016-11-01 01:50:46 -07:00
|
|
|
}
|
|
|
|
|
|
2016-12-19 04:58:02 -08:00
|
|
|
void RTCStatsCollector::ProduceTransportStats_n(
|
2018-02-06 10:34:40 -08:00
|
|
|
int64_t timestamp_us,
|
|
|
|
|
const std::map<std::string, cricket::TransportStats>&
|
|
|
|
|
transport_stats_by_name,
|
2016-10-24 04:00:05 -07:00
|
|
|
const std::map<std::string, CertificateStatsPair>& transport_cert_stats,
|
|
|
|
|
RTCStatsReport* report) const {
|
2021-04-08 15:18:05 +02:00
|
|
|
RTC_DCHECK_RUN_ON(network_thread_);
|
2020-07-08 11:18:50 +02:00
|
|
|
rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls;
|
|
|
|
|
|
2018-02-06 10:34:40 -08:00
|
|
|
for (const auto& entry : transport_stats_by_name) {
|
|
|
|
|
const std::string& transport_name = entry.first;
|
|
|
|
|
const cricket::TransportStats& transport_stats = entry.second;
|
|
|
|
|
|
2016-10-24 04:00:05 -07:00
|
|
|
// Get reference to RTCP channel, if it exists.
|
|
|
|
|
std::string rtcp_transport_stats_id;
|
2018-02-06 10:34:40 -08:00
|
|
|
for (const cricket::TransportChannelStats& channel_stats :
|
|
|
|
|
transport_stats.channel_stats) {
|
2016-10-24 04:00:05 -07:00
|
|
|
if (channel_stats.component == cricket::ICE_CANDIDATE_COMPONENT_RTCP) {
|
|
|
|
|
rtcp_transport_stats_id = RTCTransportStatsIDFromTransportChannel(
|
2018-02-06 10:34:40 -08:00
|
|
|
transport_name, channel_stats.component);
|
2016-10-24 04:00:05 -07:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Get reference to local and remote certificates of this transport, if they
|
|
|
|
|
// exist.
|
2018-02-06 10:34:40 -08:00
|
|
|
const auto& certificate_stats_it =
|
|
|
|
|
transport_cert_stats.find(transport_name);
|
2016-10-24 04:00:05 -07:00
|
|
|
RTC_DCHECK(certificate_stats_it != transport_cert_stats.cend());
|
|
|
|
|
std::string local_certificate_id;
|
|
|
|
|
if (certificate_stats_it->second.local) {
|
|
|
|
|
local_certificate_id = RTCCertificateIDFromFingerprint(
|
|
|
|
|
certificate_stats_it->second.local->fingerprint);
|
|
|
|
|
}
|
|
|
|
|
std::string remote_certificate_id;
|
|
|
|
|
if (certificate_stats_it->second.remote) {
|
|
|
|
|
remote_certificate_id = RTCCertificateIDFromFingerprint(
|
|
|
|
|
certificate_stats_it->second.remote->fingerprint);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// There is one transport stats for each channel.
|
2018-02-06 10:34:40 -08:00
|
|
|
for (const cricket::TransportChannelStats& channel_stats :
|
|
|
|
|
transport_stats.channel_stats) {
|
2016-10-24 04:00:05 -07:00
|
|
|
std::unique_ptr<RTCTransportStats> transport_stats(
|
2018-02-06 10:34:40 -08:00
|
|
|
new RTCTransportStats(RTCTransportStatsIDFromTransportChannel(
|
|
|
|
|
transport_name, channel_stats.component),
|
|
|
|
|
timestamp_us));
|
2016-10-24 04:00:05 -07:00
|
|
|
transport_stats->bytes_sent = 0;
|
2020-07-06 16:06:37 +02:00
|
|
|
transport_stats->packets_sent = 0;
|
2016-10-24 04:00:05 -07:00
|
|
|
transport_stats->bytes_received = 0;
|
2020-07-06 16:06:37 +02:00
|
|
|
transport_stats->packets_received = 0;
|
2017-01-16 07:38:02 -08:00
|
|
|
transport_stats->dtls_state =
|
|
|
|
|
DtlsTransportStateToRTCDtlsTransportState(channel_stats.dtls_state);
|
2019-08-28 08:10:27 +02:00
|
|
|
transport_stats->selected_candidate_pair_changes =
|
|
|
|
|
channel_stats.ice_transport_stats.selected_candidate_pair_changes;
|
2016-10-24 04:00:05 -07:00
|
|
|
for (const cricket::ConnectionInfo& info :
|
2019-08-28 08:10:27 +02:00
|
|
|
channel_stats.ice_transport_stats.connection_infos) {
|
2016-10-24 04:00:05 -07:00
|
|
|
*transport_stats->bytes_sent += info.sent_total_bytes;
|
2020-07-06 16:06:37 +02:00
|
|
|
*transport_stats->packets_sent +=
|
|
|
|
|
info.sent_total_packets - info.sent_discarded_packets;
|
2016-10-24 04:00:05 -07:00
|
|
|
*transport_stats->bytes_received += info.recv_total_bytes;
|
2020-07-06 16:06:37 +02:00
|
|
|
*transport_stats->packets_received += info.packets_received;
|
2016-10-24 04:00:05 -07:00
|
|
|
if (info.best_connection) {
|
|
|
|
|
transport_stats->selected_candidate_pair_id =
|
|
|
|
|
RTCIceCandidatePairStatsIDFromConnectionInfo(info);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (channel_stats.component != cricket::ICE_CANDIDATE_COMPONENT_RTCP &&
|
|
|
|
|
!rtcp_transport_stats_id.empty()) {
|
|
|
|
|
transport_stats->rtcp_transport_stats_id = rtcp_transport_stats_id;
|
|
|
|
|
}
|
|
|
|
|
if (!local_certificate_id.empty())
|
|
|
|
|
transport_stats->local_certificate_id = local_certificate_id;
|
|
|
|
|
if (!remote_certificate_id.empty())
|
|
|
|
|
transport_stats->remote_certificate_id = remote_certificate_id;
|
2019-10-28 09:51:17 +01:00
|
|
|
// Crypto information
|
|
|
|
|
if (channel_stats.ssl_version_bytes) {
|
|
|
|
|
char bytes[5];
|
|
|
|
|
snprintf(bytes, sizeof(bytes), "%04X", channel_stats.ssl_version_bytes);
|
|
|
|
|
transport_stats->tls_version = bytes;
|
|
|
|
|
}
|
|
|
|
|
if (channel_stats.ssl_cipher_suite != rtc::TLS_NULL_WITH_NULL_NULL &&
|
|
|
|
|
rtc::SSLStreamAdapter::SslCipherSuiteToName(
|
|
|
|
|
channel_stats.ssl_cipher_suite)
|
|
|
|
|
.length()) {
|
|
|
|
|
transport_stats->dtls_cipher =
|
|
|
|
|
rtc::SSLStreamAdapter::SslCipherSuiteToName(
|
|
|
|
|
channel_stats.ssl_cipher_suite);
|
|
|
|
|
}
|
|
|
|
|
if (channel_stats.srtp_crypto_suite != rtc::SRTP_INVALID_CRYPTO_SUITE &&
|
|
|
|
|
rtc::SrtpCryptoSuiteToName(channel_stats.srtp_crypto_suite)
|
|
|
|
|
.length()) {
|
|
|
|
|
transport_stats->srtp_cipher =
|
|
|
|
|
rtc::SrtpCryptoSuiteToName(channel_stats.srtp_crypto_suite);
|
|
|
|
|
}
|
2016-10-24 04:00:05 -07:00
|
|
|
report->AddStats(std::move(transport_stats));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::map<std::string, RTCStatsCollector::CertificateStatsPair>
|
2016-12-19 04:58:02 -08:00
|
|
|
RTCStatsCollector::PrepareTransportCertificateStats_n(
|
2018-02-06 10:34:40 -08:00
|
|
|
const std::map<std::string, cricket::TransportStats>&
|
|
|
|
|
transport_stats_by_name) const {
|
2021-04-08 15:18:05 +02:00
|
|
|
RTC_DCHECK_RUN_ON(network_thread_);
|
2020-07-08 11:18:50 +02:00
|
|
|
rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls;
|
|
|
|
|
|
2016-10-24 04:00:05 -07:00
|
|
|
std::map<std::string, CertificateStatsPair> transport_cert_stats;
|
2018-02-06 10:34:40 -08:00
|
|
|
for (const auto& entry : transport_stats_by_name) {
|
|
|
|
|
const std::string& transport_name = entry.first;
|
|
|
|
|
|
2016-10-24 04:00:05 -07:00
|
|
|
CertificateStatsPair certificate_stats_pair;
|
|
|
|
|
rtc::scoped_refptr<rtc::RTCCertificate> local_certificate;
|
2018-02-06 10:34:40 -08:00
|
|
|
if (pc_->GetLocalCertificate(transport_name, &local_certificate)) {
|
2016-10-24 04:00:05 -07:00
|
|
|
certificate_stats_pair.local =
|
2018-10-25 01:16:26 -07:00
|
|
|
local_certificate->GetSSLCertificateChain().GetStats();
|
2016-10-24 04:00:05 -07:00
|
|
|
}
|
2018-02-06 10:34:40 -08:00
|
|
|
|
2018-02-23 13:04:51 -08:00
|
|
|
std::unique_ptr<rtc::SSLCertChain> remote_cert_chain =
|
|
|
|
|
pc_->GetRemoteSSLCertChain(transport_name);
|
|
|
|
|
if (remote_cert_chain) {
|
|
|
|
|
certificate_stats_pair.remote = remote_cert_chain->GetStats();
|
2016-10-24 04:00:05 -07:00
|
|
|
}
|
2018-02-06 10:34:40 -08:00
|
|
|
|
2016-10-24 04:00:05 -07:00
|
|
|
transport_cert_stats.insert(
|
2018-02-06 10:34:40 -08:00
|
|
|
std::make_pair(transport_name, std::move(certificate_stats_pair)));
|
2016-10-24 04:00:05 -07:00
|
|
|
}
|
|
|
|
|
return transport_cert_stats;
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-13 09:05:21 +01:00
|
|
|
void RTCStatsCollector::PrepareTransceiverStatsInfosAndCallStats_s_w() {
|
2021-04-08 15:18:05 +02:00
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread_);
|
2018-02-15 15:19:50 -08:00
|
|
|
|
2020-11-13 09:05:21 +01:00
|
|
|
transceiver_stats_infos_.clear();
|
2018-02-15 15:19:50 -08:00
|
|
|
// These are used to invoke GetStats for all the media channels together in
|
|
|
|
|
// one worker thread hop.
|
|
|
|
|
std::map<cricket::VoiceMediaChannel*,
|
|
|
|
|
std::unique_ptr<cricket::VoiceMediaInfo>>
|
|
|
|
|
voice_stats;
|
|
|
|
|
std::map<cricket::VideoMediaChannel*,
|
|
|
|
|
std::unique_ptr<cricket::VideoMediaInfo>>
|
|
|
|
|
video_stats;
|
|
|
|
|
|
2020-07-08 11:18:50 +02:00
|
|
|
{
|
|
|
|
|
rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls;
|
2018-02-15 15:19:50 -08:00
|
|
|
|
2020-07-08 11:18:50 +02:00
|
|
|
for (const auto& transceiver : pc_->GetTransceiversInternal()) {
|
|
|
|
|
cricket::MediaType media_type = transceiver->media_type();
|
|
|
|
|
|
|
|
|
|
// Prepare stats entry. The TrackMediaInfoMap will be filled in after the
|
|
|
|
|
// stats have been fetched on the worker thread.
|
2020-11-13 09:05:21 +01:00
|
|
|
transceiver_stats_infos_.emplace_back();
|
|
|
|
|
RtpTransceiverStatsInfo& stats = transceiver_stats_infos_.back();
|
2020-07-08 11:18:50 +02:00
|
|
|
stats.transceiver = transceiver->internal();
|
|
|
|
|
stats.media_type = media_type;
|
|
|
|
|
|
|
|
|
|
cricket::ChannelInterface* channel = transceiver->internal()->channel();
|
|
|
|
|
if (!channel) {
|
|
|
|
|
// The remaining fields require a BaseChannel.
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
stats.mid = channel->content_name();
|
|
|
|
|
stats.transport_name = channel->transport_name();
|
|
|
|
|
|
|
|
|
|
if (media_type == cricket::MEDIA_TYPE_AUDIO) {
|
|
|
|
|
auto* voice_channel = static_cast<cricket::VoiceChannel*>(channel);
|
|
|
|
|
RTC_DCHECK(voice_stats.find(voice_channel->media_channel()) ==
|
|
|
|
|
voice_stats.end());
|
|
|
|
|
voice_stats[voice_channel->media_channel()] =
|
|
|
|
|
std::make_unique<cricket::VoiceMediaInfo>();
|
|
|
|
|
} else if (media_type == cricket::MEDIA_TYPE_VIDEO) {
|
|
|
|
|
auto* video_channel = static_cast<cricket::VideoChannel*>(channel);
|
|
|
|
|
RTC_DCHECK(video_stats.find(video_channel->media_channel()) ==
|
|
|
|
|
video_stats.end());
|
|
|
|
|
video_stats[video_channel->media_channel()] =
|
|
|
|
|
std::make_unique<cricket::VideoMediaInfo>();
|
|
|
|
|
} else {
|
|
|
|
|
RTC_NOTREACHED();
|
|
|
|
|
}
|
2018-02-14 16:07:42 -08:00
|
|
|
}
|
2016-11-23 02:32:06 -08:00
|
|
|
}
|
2018-02-14 16:07:42 -08:00
|
|
|
|
2020-11-13 09:05:21 +01:00
|
|
|
// We jump to the worker thread and call GetStats() on each media channel as
|
|
|
|
|
// well as GetCallStats(). At the same time we construct the
|
|
|
|
|
// TrackMediaInfoMaps, which also needs info from the worker thread. This
|
|
|
|
|
// minimizes the number of thread jumps.
|
2018-02-15 15:19:50 -08:00
|
|
|
worker_thread_->Invoke<void>(RTC_FROM_HERE, [&] {
|
2020-07-08 10:37:00 +02:00
|
|
|
rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls;
|
|
|
|
|
|
2018-02-15 15:19:50 -08:00
|
|
|
for (const auto& entry : voice_stats) {
|
2020-09-14 10:47:50 +02:00
|
|
|
if (!entry.first->GetStats(entry.second.get(),
|
|
|
|
|
/*get_and_clear_legacy_stats=*/false)) {
|
2018-02-15 15:19:50 -08:00
|
|
|
RTC_LOG(LS_WARNING) << "Failed to get voice stats.";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
for (const auto& entry : video_stats) {
|
|
|
|
|
if (!entry.first->GetStats(entry.second.get())) {
|
|
|
|
|
RTC_LOG(LS_WARNING) << "Failed to get video stats.";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-08 10:37:00 +02:00
|
|
|
// Create the TrackMediaInfoMap for each transceiver stats object.
|
2020-11-13 09:05:21 +01:00
|
|
|
for (auto& stats : transceiver_stats_infos_) {
|
2020-07-08 10:37:00 +02:00
|
|
|
auto transceiver = stats.transceiver;
|
|
|
|
|
std::unique_ptr<cricket::VoiceMediaInfo> voice_media_info;
|
|
|
|
|
std::unique_ptr<cricket::VideoMediaInfo> video_media_info;
|
|
|
|
|
if (transceiver->channel()) {
|
|
|
|
|
cricket::MediaType media_type = transceiver->media_type();
|
|
|
|
|
if (media_type == cricket::MEDIA_TYPE_AUDIO) {
|
|
|
|
|
auto* voice_channel =
|
|
|
|
|
static_cast<cricket::VoiceChannel*>(transceiver->channel());
|
|
|
|
|
RTC_DCHECK(voice_stats[voice_channel->media_channel()]);
|
|
|
|
|
voice_media_info =
|
|
|
|
|
std::move(voice_stats[voice_channel->media_channel()]);
|
|
|
|
|
} else if (media_type == cricket::MEDIA_TYPE_VIDEO) {
|
|
|
|
|
auto* video_channel =
|
|
|
|
|
static_cast<cricket::VideoChannel*>(transceiver->channel());
|
|
|
|
|
RTC_DCHECK(video_stats[video_channel->media_channel()]);
|
|
|
|
|
video_media_info =
|
|
|
|
|
std::move(video_stats[video_channel->media_channel()]);
|
|
|
|
|
}
|
2018-02-15 15:19:50 -08:00
|
|
|
}
|
2020-07-08 10:37:00 +02:00
|
|
|
std::vector<rtc::scoped_refptr<RtpSenderInternal>> senders;
|
|
|
|
|
for (const auto& sender : transceiver->senders()) {
|
|
|
|
|
senders.push_back(sender->internal());
|
|
|
|
|
}
|
|
|
|
|
std::vector<rtc::scoped_refptr<RtpReceiverInternal>> receivers;
|
|
|
|
|
for (const auto& receiver : transceiver->receivers()) {
|
|
|
|
|
receivers.push_back(receiver->internal());
|
|
|
|
|
}
|
|
|
|
|
stats.track_media_info_map = std::make_unique<TrackMediaInfoMap>(
|
|
|
|
|
std::move(voice_media_info), std::move(video_media_info), senders,
|
|
|
|
|
receivers);
|
2018-02-15 15:19:50 -08:00
|
|
|
}
|
|
|
|
|
|
2020-11-13 09:05:21 +01:00
|
|
|
call_stats_ = pc_->GetCallStats();
|
|
|
|
|
});
|
2016-11-23 02:32:06 -08:00
|
|
|
}
|
|
|
|
|
|
2018-03-30 15:18:41 -07:00
|
|
|
std::set<std::string> RTCStatsCollector::PrepareTransportNames_s() const {
|
2021-04-08 15:18:05 +02:00
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread_);
|
2020-07-08 11:18:50 +02:00
|
|
|
rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls;
|
|
|
|
|
|
2018-03-30 15:18:41 -07:00
|
|
|
std::set<std::string> transport_names;
|
|
|
|
|
for (const auto& transceiver : pc_->GetTransceiversInternal()) {
|
|
|
|
|
if (transceiver->internal()->channel()) {
|
|
|
|
|
transport_names.insert(
|
|
|
|
|
transceiver->internal()->channel()->transport_name());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (pc_->sctp_transport_name()) {
|
|
|
|
|
transport_names.insert(*pc_->sctp_transport_name());
|
|
|
|
|
}
|
|
|
|
|
return transport_names;
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-09 15:32:34 -07:00
|
|
|
void RTCStatsCollector::OnSctpDataChannelCreated(SctpDataChannel* channel) {
|
2016-11-14 01:41:09 -08:00
|
|
|
channel->SignalOpened.connect(this, &RTCStatsCollector::OnDataChannelOpened);
|
|
|
|
|
channel->SignalClosed.connect(this, &RTCStatsCollector::OnDataChannelClosed);
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-09 15:32:34 -07:00
|
|
|
void RTCStatsCollector::OnDataChannelOpened(DataChannelInterface* channel) {
|
2021-04-08 15:18:05 +02:00
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread_);
|
2016-11-14 01:41:09 -08:00
|
|
|
bool result = internal_record_.opened_data_channels
|
|
|
|
|
.insert(reinterpret_cast<uintptr_t>(channel))
|
|
|
|
|
.second;
|
|
|
|
|
++internal_record_.data_channels_opened;
|
|
|
|
|
RTC_DCHECK(result);
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-09 15:32:34 -07:00
|
|
|
void RTCStatsCollector::OnDataChannelClosed(DataChannelInterface* channel) {
|
2021-04-08 15:18:05 +02:00
|
|
|
RTC_DCHECK_RUN_ON(signaling_thread_);
|
2016-11-14 01:41:09 -08:00
|
|
|
// Only channels that have been fully opened (and have increased the
|
|
|
|
|
// |data_channels_opened_| counter) increase the closed counter.
|
2017-03-20 03:14:14 -07:00
|
|
|
if (internal_record_.opened_data_channels.erase(
|
|
|
|
|
reinterpret_cast<uintptr_t>(channel))) {
|
2016-11-14 01:41:09 -08:00
|
|
|
++internal_record_.data_channels_closed;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-10-18 12:48:31 -07:00
|
|
|
const char* CandidateTypeToRTCIceCandidateTypeForTesting(
|
|
|
|
|
const std::string& type) {
|
|
|
|
|
return CandidateTypeToRTCIceCandidateType(type);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const char* DataStateToRTCDataChannelStateForTesting(
|
|
|
|
|
DataChannelInterface::DataState state) {
|
|
|
|
|
return DataStateToRTCDataChannelState(state);
|
|
|
|
|
}
|
|
|
|
|
|
2016-08-30 14:04:35 -07:00
|
|
|
} // namespace webrtc
|