mirror of
https://github.com/mollyim/webrtc.git
synced 2025-05-13 13:50:40 +01:00
Add RTCRemoteOutboundRtpStreamStats
for audio streams
Changes: - adding the `RTCRemoteOutboundRtpStreamStats` dictionary (see [1]) - collection of remote outbound stats (only for audio streams) - adding `remote_id` to the inbound stats and set with the ID of the corresponding remote outbound stats only if the latter are available - unit tests [1] https://www.w3.org/TR/webrtc-stats/#dom-rtcremoteoutboundrtpstreamstats Tested: verified from chrome://webrtc-internals during an appr.tc call Bug: webrtc:12529 Change-Id: Ide91dc04a3c387ba439618a9c6b64a95994a1940 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/211042 Commit-Queue: Alessio Bazzica <alessiob@webrtc.org> Reviewed-by: Björn Terelius <terelius@webrtc.org> Reviewed-by: Sam Zackrisson <saza@webrtc.org> Reviewed-by: Henrik Boström <hbos@webrtc.org> Cr-Commit-Position: refs/heads/master@{#33545}
This commit is contained in:
parent
26abdaf478
commit
f7b1b95f11
10 changed files with 465 additions and 57 deletions
|
@ -388,6 +388,7 @@ class RTC_EXPORT RTCRTPStreamStats : public RTCStats {
|
|||
RTCRTPStreamStats(std::string&& id, int64_t timestamp_us);
|
||||
};
|
||||
|
||||
// https://www.w3.org/TR/webrtc-stats/#receivedrtpstats-dict*
|
||||
class RTC_EXPORT RTCReceivedRtpStreamStats : public RTCRTPStreamStats {
|
||||
public:
|
||||
WEBRTC_RTCSTATS_DECL();
|
||||
|
@ -410,6 +411,22 @@ class RTC_EXPORT RTCReceivedRtpStreamStats : public RTCRTPStreamStats {
|
|||
RTCReceivedRtpStreamStats(std::string&& id, int64_t timestamp_us);
|
||||
};
|
||||
|
||||
// https://www.w3.org/TR/webrtc-stats/#sentrtpstats-dict*
|
||||
class RTC_EXPORT RTCSentRtpStreamStats : public RTCRTPStreamStats {
|
||||
public:
|
||||
WEBRTC_RTCSTATS_DECL();
|
||||
|
||||
RTCSentRtpStreamStats(const RTCSentRtpStreamStats& other);
|
||||
~RTCSentRtpStreamStats() override;
|
||||
|
||||
RTCStatsMember<uint32_t> packets_sent;
|
||||
RTCStatsMember<uint64_t> bytes_sent;
|
||||
|
||||
protected:
|
||||
RTCSentRtpStreamStats(const std::string&& id, int64_t timestamp_us);
|
||||
RTCSentRtpStreamStats(std::string&& id, int64_t timestamp_us);
|
||||
};
|
||||
|
||||
// https://w3c.github.io/webrtc-stats/#inboundrtpstats-dict*
|
||||
// TODO(hbos): Support the remote case |is_remote = true|.
|
||||
// https://bugs.webrtc.org/7065
|
||||
|
@ -423,6 +440,7 @@ class RTC_EXPORT RTCInboundRTPStreamStats final
|
|||
RTCInboundRTPStreamStats(const RTCInboundRTPStreamStats& other);
|
||||
~RTCInboundRTPStreamStats() override;
|
||||
|
||||
RTCStatsMember<std::string> remote_id;
|
||||
RTCStatsMember<uint32_t> packets_received;
|
||||
RTCStatsMember<uint64_t> fec_packets_received;
|
||||
RTCStatsMember<uint64_t> fec_packets_discarded;
|
||||
|
@ -573,6 +591,22 @@ class RTC_EXPORT RTCRemoteInboundRtpStreamStats final
|
|||
RTCStatsMember<int32_t> round_trip_time_measurements;
|
||||
};
|
||||
|
||||
// https://w3c.github.io/webrtc-stats/#remoteoutboundrtpstats-dict*
|
||||
class RTC_EXPORT RTCRemoteOutboundRtpStreamStats final
|
||||
: public RTCSentRtpStreamStats {
|
||||
public:
|
||||
WEBRTC_RTCSTATS_DECL();
|
||||
|
||||
RTCRemoteOutboundRtpStreamStats(const std::string& id, int64_t timestamp_us);
|
||||
RTCRemoteOutboundRtpStreamStats(std::string&& id, int64_t timestamp_us);
|
||||
RTCRemoteOutboundRtpStreamStats(const RTCRemoteOutboundRtpStreamStats& other);
|
||||
~RTCRemoteOutboundRtpStreamStats() override;
|
||||
|
||||
RTCStatsMember<std::string> local_id;
|
||||
RTCStatsMember<double> remote_timestamp;
|
||||
RTCStatsMember<uint64_t> reports_sent;
|
||||
};
|
||||
|
||||
// https://w3c.github.io/webrtc-stats/#dom-rtcmediasourcestats
|
||||
class RTC_EXPORT RTCMediaSourceStats : public RTCStats {
|
||||
public:
|
||||
|
|
|
@ -264,6 +264,14 @@ webrtc::AudioReceiveStream::Stats AudioReceiveStream::GetStats(
|
|||
stats.decoding_plc_cng = ds.decoded_plc_cng;
|
||||
stats.decoding_muted_output = ds.decoded_muted_output;
|
||||
|
||||
stats.last_sender_report_timestamp_ms =
|
||||
call_stats.last_sender_report_timestamp_ms;
|
||||
stats.last_sender_report_remote_timestamp_ms =
|
||||
call_stats.last_sender_report_remote_timestamp_ms;
|
||||
stats.sender_reports_packets_sent = call_stats.sender_reports_packets_sent;
|
||||
stats.sender_reports_bytes_sent = call_stats.sender_reports_bytes_sent;
|
||||
stats.sender_reports_reports_count = call_stats.sender_reports_reports_count;
|
||||
|
||||
return stats;
|
||||
}
|
||||
|
||||
|
|
|
@ -90,6 +90,13 @@ class AudioReceiveStream {
|
|||
int32_t total_interruption_duration_ms = 0;
|
||||
// https://w3c.github.io/webrtc-stats/#dom-rtcinboundrtpstreamstats-estimatedplayouttimestamp
|
||||
absl::optional<int64_t> estimated_playout_ntp_timestamp_ms;
|
||||
// Remote outbound stats derived by the received RTCP sender reports.
|
||||
// https://w3c.github.io/webrtc-stats/#remoteoutboundrtpstats-dict*
|
||||
absl::optional<int64_t> last_sender_report_timestamp_ms;
|
||||
absl::optional<int64_t> last_sender_report_remote_timestamp_ms;
|
||||
uint32_t sender_reports_packets_sent = 0;
|
||||
uint64_t sender_reports_bytes_sent = 0;
|
||||
uint64_t sender_reports_reports_count = 0;
|
||||
};
|
||||
|
||||
struct Config {
|
||||
|
|
|
@ -536,6 +536,13 @@ struct VoiceReceiverInfo : public MediaReceiverInfo {
|
|||
// longer than 150 ms).
|
||||
int32_t interruption_count = 0;
|
||||
int32_t total_interruption_duration_ms = 0;
|
||||
// Remote outbound stats derived by the received RTCP sender reports.
|
||||
// https://w3c.github.io/webrtc-stats/#remoteoutboundrtpstats-dict*
|
||||
absl::optional<int64_t> last_sender_report_timestamp_ms;
|
||||
absl::optional<int64_t> last_sender_report_remote_timestamp_ms;
|
||||
uint32_t sender_reports_packets_sent = 0;
|
||||
uint64_t sender_reports_bytes_sent = 0;
|
||||
uint64_t sender_reports_reports_count = 0;
|
||||
};
|
||||
|
||||
struct VideoSenderInfo : public MediaSenderInfo {
|
||||
|
|
|
@ -2461,6 +2461,13 @@ bool WebRtcVoiceMediaChannel::GetStats(VoiceMediaInfo* info,
|
|||
stats.relative_packet_arrival_delay_seconds;
|
||||
rinfo.interruption_count = stats.interruption_count;
|
||||
rinfo.total_interruption_duration_ms = stats.total_interruption_duration_ms;
|
||||
rinfo.last_sender_report_timestamp_ms =
|
||||
stats.last_sender_report_timestamp_ms;
|
||||
rinfo.last_sender_report_remote_timestamp_ms =
|
||||
stats.last_sender_report_remote_timestamp_ms;
|
||||
rinfo.sender_reports_packets_sent = stats.sender_reports_packets_sent;
|
||||
rinfo.sender_reports_bytes_sent = stats.sender_reports_bytes_sent;
|
||||
rinfo.sender_reports_reports_count = stats.sender_reports_reports_count;
|
||||
|
||||
info->receivers.push_back(rinfo);
|
||||
}
|
||||
|
|
|
@ -109,17 +109,23 @@ std::string RTCTransportStatsIDFromTransportChannel(
|
|||
return sb.str();
|
||||
}
|
||||
|
||||
std::string RTCInboundRTPStreamStatsIDFromSSRC(bool audio, uint32_t ssrc) {
|
||||
std::string RTCInboundRTPStreamStatsIDFromSSRC(cricket::MediaType media_type,
|
||||
uint32_t ssrc) {
|
||||
char buf[1024];
|
||||
rtc::SimpleStringBuilder sb(buf);
|
||||
sb << "RTCInboundRTP" << (audio ? "Audio" : "Video") << "Stream_" << ssrc;
|
||||
sb << "RTCInboundRTP"
|
||||
<< (media_type == cricket::MEDIA_TYPE_AUDIO ? "Audio" : "Video")
|
||||
<< "Stream_" << ssrc;
|
||||
return sb.str();
|
||||
}
|
||||
|
||||
std::string RTCOutboundRTPStreamStatsIDFromSSRC(bool audio, uint32_t ssrc) {
|
||||
std::string RTCOutboundRTPStreamStatsIDFromSSRC(cricket::MediaType media_type,
|
||||
uint32_t ssrc) {
|
||||
char buf[1024];
|
||||
rtc::SimpleStringBuilder sb(buf);
|
||||
sb << "RTCOutboundRTP" << (audio ? "Audio" : "Video") << "Stream_" << ssrc;
|
||||
sb << "RTCOutboundRTP"
|
||||
<< (media_type == cricket::MEDIA_TYPE_AUDIO ? "Audio" : "Video")
|
||||
<< "Stream_" << ssrc;
|
||||
return sb.str();
|
||||
}
|
||||
|
||||
|
@ -134,6 +140,17 @@ std::string RTCRemoteInboundRtpStreamStatsIdFromSourceSsrc(
|
|||
return sb.str();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
std::string RTCMediaSourceStatsIDFromKindAndAttachment(
|
||||
cricket::MediaType media_type,
|
||||
int attachment_id) {
|
||||
|
@ -309,17 +326,21 @@ void SetInboundRTPStreamStatsFromMediaReceiverInfo(
|
|||
static_cast<int32_t>(media_receiver_info.packets_lost);
|
||||
}
|
||||
|
||||
void SetInboundRTPStreamStatsFromVoiceReceiverInfo(
|
||||
const std::string& mid,
|
||||
std::unique_ptr<RTCInboundRTPStreamStats> CreateInboundAudioStreamStats(
|
||||
const cricket::VoiceReceiverInfo& voice_receiver_info,
|
||||
RTCInboundRTPStreamStats* inbound_audio) {
|
||||
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);
|
||||
SetInboundRTPStreamStatsFromMediaReceiverInfo(voice_receiver_info,
|
||||
inbound_audio);
|
||||
inbound_audio.get());
|
||||
inbound_audio->media_type = "audio";
|
||||
inbound_audio->kind = "audio";
|
||||
if (voice_receiver_info.codec_payload_type) {
|
||||
inbound_audio->codec_id = RTCCodecStatsIDFromMidDirectionAndPayload(
|
||||
mid, true, *voice_receiver_info.codec_payload_type);
|
||||
mid, /*inbound=*/true, *voice_receiver_info.codec_payload_type);
|
||||
}
|
||||
inbound_audio->jitter = static_cast<double>(voice_receiver_info.jitter_ms) /
|
||||
rtc::kNumMillisecsPerSec;
|
||||
|
@ -358,6 +379,51 @@ void SetInboundRTPStreamStatsFromVoiceReceiverInfo(
|
|||
voice_receiver_info.fec_packets_received;
|
||||
inbound_audio->fec_packets_discarded =
|
||||
voice_receiver_info.fec_packets_discarded;
|
||||
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;
|
||||
}
|
||||
|
||||
void SetInboundRTPStreamStatsFromVideoReceiverInfo(
|
||||
|
@ -370,7 +436,7 @@ void SetInboundRTPStreamStatsFromVideoReceiverInfo(
|
|||
inbound_video->kind = "video";
|
||||
if (video_receiver_info.codec_payload_type) {
|
||||
inbound_video->codec_id = RTCCodecStatsIDFromMidDirectionAndPayload(
|
||||
mid, true, *video_receiver_info.codec_payload_type);
|
||||
mid, /*inbound=*/true, *video_receiver_info.codec_payload_type);
|
||||
}
|
||||
inbound_video->jitter = static_cast<double>(video_receiver_info.jitter_ms) /
|
||||
rtc::kNumMillisecsPerSec;
|
||||
|
@ -454,7 +520,7 @@ void SetOutboundRTPStreamStatsFromVoiceSenderInfo(
|
|||
outbound_audio->kind = "audio";
|
||||
if (voice_sender_info.codec_payload_type) {
|
||||
outbound_audio->codec_id = RTCCodecStatsIDFromMidDirectionAndPayload(
|
||||
mid, false, *voice_sender_info.codec_payload_type);
|
||||
mid, /*inbound=*/false, *voice_sender_info.codec_payload_type);
|
||||
}
|
||||
// |fir_count|, |pli_count| and |sli_count| are only valid for video and are
|
||||
// purposefully left undefined for audio.
|
||||
|
@ -470,7 +536,7 @@ void SetOutboundRTPStreamStatsFromVideoSenderInfo(
|
|||
outbound_video->kind = "video";
|
||||
if (video_sender_info.codec_payload_type) {
|
||||
outbound_video->codec_id = RTCCodecStatsIDFromMidDirectionAndPayload(
|
||||
mid, false, *video_sender_info.codec_payload_type);
|
||||
mid, /*inbound=*/false, *video_sender_info.codec_payload_type);
|
||||
}
|
||||
outbound_video->fir_count =
|
||||
static_cast<uint32_t>(video_sender_info.firs_rcvd);
|
||||
|
@ -550,8 +616,8 @@ ProduceRemoteInboundRtpStreamStatsFromReportBlockData(
|
|||
remote_inbound->round_trip_time_measurements =
|
||||
report_block_data.num_rtts();
|
||||
|
||||
std::string local_id = RTCOutboundRTPStreamStatsIDFromSSRC(
|
||||
media_type == cricket::MEDIA_TYPE_AUDIO, report_block.source_ssrc);
|
||||
std::string local_id =
|
||||
RTCOutboundRTPStreamStatsIDFromSSRC(media_type, report_block.source_ssrc);
|
||||
// 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()) {
|
||||
|
@ -1678,16 +1744,16 @@ void RTCStatsCollector::ProduceAudioRTPStreamStats_n(
|
|||
std::string mid = *stats.mid;
|
||||
std::string transport_id = RTCTransportStatsIDFromTransportChannel(
|
||||
*stats.transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTP);
|
||||
// Inbound
|
||||
// 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.
|
||||
for (const cricket::VoiceReceiverInfo& voice_receiver_info :
|
||||
track_media_info_map.voice_media_info()->receivers) {
|
||||
if (!voice_receiver_info.connected())
|
||||
continue;
|
||||
auto inbound_audio = std::make_unique<RTCInboundRTPStreamStats>(
|
||||
RTCInboundRTPStreamStatsIDFromSSRC(true, voice_receiver_info.ssrc()),
|
||||
timestamp_us);
|
||||
SetInboundRTPStreamStatsFromVoiceReceiverInfo(mid, voice_receiver_info,
|
||||
inbound_audio.get());
|
||||
// Inbound.
|
||||
auto inbound_audio =
|
||||
CreateInboundAudioStreamStats(voice_receiver_info, mid, timestamp_us);
|
||||
// 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);
|
||||
|
@ -1698,16 +1764,27 @@ void RTCStatsCollector::ProduceAudioRTPStreamStats_n(
|
|||
track_media_info_map.GetAttachmentIdByTrack(audio_track).value());
|
||||
}
|
||||
inbound_audio->transport_id = transport_id;
|
||||
// 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));
|
||||
}
|
||||
report->AddStats(std::move(inbound_audio));
|
||||
}
|
||||
// Outbound
|
||||
// Outbound.
|
||||
std::map<std::string, RTCOutboundRTPStreamStats*> audio_outbound_rtps;
|
||||
for (const cricket::VoiceSenderInfo& voice_sender_info :
|
||||
track_media_info_map.voice_media_info()->senders) {
|
||||
if (!voice_sender_info.connected())
|
||||
continue;
|
||||
auto outbound_audio = std::make_unique<RTCOutboundRTPStreamStats>(
|
||||
RTCOutboundRTPStreamStatsIDFromSSRC(true, voice_sender_info.ssrc()),
|
||||
RTCOutboundRTPStreamStatsIDFromSSRC(cricket::MEDIA_TYPE_AUDIO,
|
||||
voice_sender_info.ssrc()),
|
||||
timestamp_us);
|
||||
SetOutboundRTPStreamStatsFromVoiceSenderInfo(mid, voice_sender_info,
|
||||
outbound_audio.get());
|
||||
|
@ -1728,7 +1805,7 @@ void RTCStatsCollector::ProduceAudioRTPStreamStats_n(
|
|||
std::make_pair(outbound_audio->id(), outbound_audio.get()));
|
||||
report->AddStats(std::move(outbound_audio));
|
||||
}
|
||||
// Remote-inbound
|
||||
// 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
|
||||
|
@ -1765,7 +1842,8 @@ void RTCStatsCollector::ProduceVideoRTPStreamStats_n(
|
|||
if (!video_receiver_info.connected())
|
||||
continue;
|
||||
auto inbound_video = std::make_unique<RTCInboundRTPStreamStats>(
|
||||
RTCInboundRTPStreamStatsIDFromSSRC(false, video_receiver_info.ssrc()),
|
||||
RTCInboundRTPStreamStatsIDFromSSRC(cricket::MEDIA_TYPE_VIDEO,
|
||||
video_receiver_info.ssrc()),
|
||||
timestamp_us);
|
||||
SetInboundRTPStreamStatsFromVideoReceiverInfo(mid, video_receiver_info,
|
||||
inbound_video.get());
|
||||
|
@ -1779,6 +1857,7 @@ void RTCStatsCollector::ProduceVideoRTPStreamStats_n(
|
|||
}
|
||||
inbound_video->transport_id = transport_id;
|
||||
report->AddStats(std::move(inbound_video));
|
||||
// TODO(crbug.com/webrtc/12529): Add remote-outbound stats.
|
||||
}
|
||||
// Outbound
|
||||
std::map<std::string, RTCOutboundRTPStreamStats*> video_outbound_rtps;
|
||||
|
@ -1787,7 +1866,8 @@ void RTCStatsCollector::ProduceVideoRTPStreamStats_n(
|
|||
if (!video_sender_info.connected())
|
||||
continue;
|
||||
auto outbound_video = std::make_unique<RTCOutboundRTPStreamStats>(
|
||||
RTCOutboundRTPStreamStatsIDFromSSRC(false, video_sender_info.ssrc()),
|
||||
RTCOutboundRTPStreamStatsIDFromSSRC(cricket::MEDIA_TYPE_VIDEO,
|
||||
video_sender_info.ssrc()),
|
||||
timestamp_us);
|
||||
SetOutboundRTPStreamStatsFromVideoSenderInfo(mid, video_sender_info,
|
||||
outbound_video.get());
|
||||
|
|
|
@ -119,6 +119,14 @@ namespace {
|
|||
|
||||
const int64_t kGetStatsReportTimeoutMs = 1000;
|
||||
|
||||
// Fake data used by `SetupExampleStatsVoiceGraph()` to fill in remote outbound
|
||||
// stats.
|
||||
constexpr int64_t kRemoteOutboundStatsTimestampMs = 123;
|
||||
constexpr int64_t kRemoteOutboundStatsRemoteTimestampMs = 456;
|
||||
constexpr uint32_t kRemoteOutboundStatsPacketsSent = 7u;
|
||||
constexpr uint64_t kRemoteOutboundStatsBytesSent = 8u;
|
||||
constexpr uint64_t kRemoteOutboundStatsReportsCount = 9u;
|
||||
|
||||
struct CertificateInfo {
|
||||
rtc::scoped_refptr<rtc::RTCCertificate> certificate;
|
||||
std::vector<std::string> ders;
|
||||
|
@ -575,6 +583,11 @@ class RTCStatsCollectorWrapper {
|
|||
EXPECT_TRUE_WAIT(callback->report(), kGetStatsReportTimeoutMs);
|
||||
int64_t after = rtc::TimeUTCMicros();
|
||||
for (const RTCStats& stats : *callback->report()) {
|
||||
if (stats.type() == RTCRemoteInboundRtpStreamStats::kType ||
|
||||
stats.type() == RTCRemoteOutboundRtpStreamStats::kType) {
|
||||
// Ignore remote timestamps.
|
||||
continue;
|
||||
}
|
||||
EXPECT_LE(stats.timestamp_us(), after);
|
||||
}
|
||||
return callback->report();
|
||||
|
@ -619,6 +632,7 @@ class RTCStatsCollectorTest : public ::testing::Test {
|
|||
std::string recv_codec_id;
|
||||
std::string outbound_rtp_id;
|
||||
std::string inbound_rtp_id;
|
||||
std::string remote_outbound_rtp_id;
|
||||
std::string transport_id;
|
||||
std::string sender_track_id;
|
||||
std::string receiver_track_id;
|
||||
|
@ -627,9 +641,9 @@ class RTCStatsCollectorTest : public ::testing::Test {
|
|||
std::string media_source_id;
|
||||
};
|
||||
|
||||
// Sets up the example stats graph (see ASCII art below) used for testing the
|
||||
// stats selection algorithm,
|
||||
// https://w3c.github.io/webrtc-pc/#dfn-stats-selection-algorithm.
|
||||
// Sets up the example stats graph (see ASCII art below) for a video only
|
||||
// call. The graph is used for testing the stats selection algorithm (see
|
||||
// https://w3c.github.io/webrtc-pc/#dfn-stats-selection-algorithm).
|
||||
// These tests test the integration of the stats traversal algorithm inside of
|
||||
// RTCStatsCollector. See rtcstatstraveral_unittest.cc for more stats
|
||||
// traversal tests.
|
||||
|
@ -731,6 +745,125 @@ class RTCStatsCollectorTest : public ::testing::Test {
|
|||
return graph;
|
||||
}
|
||||
|
||||
// Sets up an example stats graph (see ASCII art below) for an audio only call
|
||||
// and checks that the expected stats are generated.
|
||||
ExampleStatsGraph SetupExampleStatsVoiceGraph(
|
||||
bool add_remote_outbound_stats) {
|
||||
constexpr uint32_t kLocalSsrc = 3;
|
||||
constexpr uint32_t kRemoteSsrc = 4;
|
||||
ExampleStatsGraph graph;
|
||||
|
||||
// codec (send)
|
||||
graph.send_codec_id = "RTCCodec_VoiceMid_Outbound_1";
|
||||
cricket::VoiceMediaInfo media_info;
|
||||
RtpCodecParameters send_codec;
|
||||
send_codec.payload_type = 1;
|
||||
send_codec.clock_rate = 0;
|
||||
media_info.send_codecs.insert(
|
||||
std::make_pair(send_codec.payload_type, send_codec));
|
||||
// codec (recv)
|
||||
graph.recv_codec_id = "RTCCodec_VoiceMid_Inbound_2";
|
||||
RtpCodecParameters recv_codec;
|
||||
recv_codec.payload_type = 2;
|
||||
recv_codec.clock_rate = 0;
|
||||
media_info.receive_codecs.insert(
|
||||
std::make_pair(recv_codec.payload_type, recv_codec));
|
||||
// outbound-rtp
|
||||
graph.outbound_rtp_id = "RTCOutboundRTPAudioStream_3";
|
||||
media_info.senders.push_back(cricket::VoiceSenderInfo());
|
||||
media_info.senders[0].local_stats.push_back(cricket::SsrcSenderInfo());
|
||||
media_info.senders[0].local_stats[0].ssrc = kLocalSsrc;
|
||||
media_info.senders[0].codec_payload_type = send_codec.payload_type;
|
||||
// inbound-rtp
|
||||
graph.inbound_rtp_id = "RTCInboundRTPAudioStream_4";
|
||||
media_info.receivers.push_back(cricket::VoiceReceiverInfo());
|
||||
media_info.receivers[0].local_stats.push_back(cricket::SsrcReceiverInfo());
|
||||
media_info.receivers[0].local_stats[0].ssrc = kRemoteSsrc;
|
||||
media_info.receivers[0].codec_payload_type = recv_codec.payload_type;
|
||||
// remote-outbound-rtp
|
||||
if (add_remote_outbound_stats) {
|
||||
graph.remote_outbound_rtp_id = "RTCRemoteOutboundRTPAudioStream_4";
|
||||
media_info.receivers[0].last_sender_report_timestamp_ms =
|
||||
kRemoteOutboundStatsTimestampMs;
|
||||
media_info.receivers[0].last_sender_report_remote_timestamp_ms =
|
||||
kRemoteOutboundStatsRemoteTimestampMs;
|
||||
media_info.receivers[0].sender_reports_packets_sent =
|
||||
kRemoteOutboundStatsPacketsSent;
|
||||
media_info.receivers[0].sender_reports_bytes_sent =
|
||||
kRemoteOutboundStatsBytesSent;
|
||||
media_info.receivers[0].sender_reports_reports_count =
|
||||
kRemoteOutboundStatsReportsCount;
|
||||
}
|
||||
|
||||
// transport
|
||||
graph.transport_id = "RTCTransport_TransportName_1";
|
||||
auto* video_media_channel =
|
||||
pc_->AddVoiceChannel("VoiceMid", "TransportName");
|
||||
video_media_channel->SetStats(media_info);
|
||||
// track (sender)
|
||||
graph.sender = stats_->SetupLocalTrackAndSender(
|
||||
cricket::MEDIA_TYPE_AUDIO, "LocalAudioTrackID", kLocalSsrc, false, 50);
|
||||
graph.sender_track_id = "RTCMediaStreamTrack_sender_" +
|
||||
rtc::ToString(graph.sender->AttachmentId());
|
||||
// track (receiver) and stream (remote stream)
|
||||
graph.receiver = stats_->SetupRemoteTrackAndReceiver(
|
||||
cricket::MEDIA_TYPE_AUDIO, "RemoteAudioTrackID", "RemoteStreamId",
|
||||
kRemoteSsrc);
|
||||
graph.receiver_track_id = "RTCMediaStreamTrack_receiver_" +
|
||||
rtc::ToString(graph.receiver->AttachmentId());
|
||||
graph.remote_stream_id = "RTCMediaStream_RemoteStreamId";
|
||||
// peer-connection
|
||||
graph.peer_connection_id = "RTCPeerConnection";
|
||||
// media-source (kind: video)
|
||||
graph.media_source_id =
|
||||
"RTCAudioSource_" + rtc::ToString(graph.sender->AttachmentId());
|
||||
|
||||
// Expected stats graph:
|
||||
//
|
||||
// +--- track (sender) stream (remote stream) ---> track (receiver)
|
||||
// | ^ ^
|
||||
// | | |
|
||||
// | +--------- outbound-rtp inbound-rtp ---------------+
|
||||
// | | | | | |
|
||||
// | | v v v v
|
||||
// | | codec (send) transport codec (recv) peer-connection
|
||||
// v v
|
||||
// media-source
|
||||
|
||||
// Verify the stats graph is set up correctly.
|
||||
graph.full_report = stats_->GetStatsReport();
|
||||
EXPECT_EQ(graph.full_report->size(), add_remote_outbound_stats ? 11u : 10u);
|
||||
EXPECT_TRUE(graph.full_report->Get(graph.send_codec_id));
|
||||
EXPECT_TRUE(graph.full_report->Get(graph.recv_codec_id));
|
||||
EXPECT_TRUE(graph.full_report->Get(graph.outbound_rtp_id));
|
||||
EXPECT_TRUE(graph.full_report->Get(graph.inbound_rtp_id));
|
||||
EXPECT_TRUE(graph.full_report->Get(graph.transport_id));
|
||||
EXPECT_TRUE(graph.full_report->Get(graph.sender_track_id));
|
||||
EXPECT_TRUE(graph.full_report->Get(graph.receiver_track_id));
|
||||
EXPECT_TRUE(graph.full_report->Get(graph.remote_stream_id));
|
||||
EXPECT_TRUE(graph.full_report->Get(graph.peer_connection_id));
|
||||
EXPECT_TRUE(graph.full_report->Get(graph.media_source_id));
|
||||
// `graph.remote_outbound_rtp_id` is omitted on purpose so that expectations
|
||||
// can be added by the caller depending on what value it sets for the
|
||||
// `add_remote_outbound_stats` argument.
|
||||
const auto& sender_track = graph.full_report->Get(graph.sender_track_id)
|
||||
->cast_to<RTCMediaStreamTrackStats>();
|
||||
EXPECT_EQ(*sender_track.media_source_id, graph.media_source_id);
|
||||
const auto& outbound_rtp = graph.full_report->Get(graph.outbound_rtp_id)
|
||||
->cast_to<RTCOutboundRTPStreamStats>();
|
||||
EXPECT_EQ(*outbound_rtp.media_source_id, graph.media_source_id);
|
||||
EXPECT_EQ(*outbound_rtp.codec_id, graph.send_codec_id);
|
||||
EXPECT_EQ(*outbound_rtp.track_id, graph.sender_track_id);
|
||||
EXPECT_EQ(*outbound_rtp.transport_id, graph.transport_id);
|
||||
const auto& inbound_rtp = graph.full_report->Get(graph.inbound_rtp_id)
|
||||
->cast_to<RTCInboundRTPStreamStats>();
|
||||
EXPECT_EQ(*inbound_rtp.codec_id, graph.recv_codec_id);
|
||||
EXPECT_EQ(*inbound_rtp.track_id, graph.receiver_track_id);
|
||||
EXPECT_EQ(*inbound_rtp.transport_id, graph.transport_id);
|
||||
|
||||
return graph;
|
||||
}
|
||||
|
||||
protected:
|
||||
rtc::ScopedFakeClock fake_clock_;
|
||||
rtc::scoped_refptr<FakePeerConnectionForStats> pc_;
|
||||
|
@ -2872,6 +3005,43 @@ INSTANTIATE_TEST_SUITE_P(All,
|
|||
::testing::Values(cricket::MEDIA_TYPE_AUDIO, // "/0"
|
||||
cricket::MEDIA_TYPE_VIDEO)); // "/1"
|
||||
|
||||
// Checks that no remote outbound stats are collected if not available in
|
||||
// `VoiceMediaInfo`.
|
||||
TEST_F(RTCStatsCollectorTest,
|
||||
RTCRemoteOutboundRtpAudioStreamStatsNotCollected) {
|
||||
ExampleStatsGraph graph =
|
||||
SetupExampleStatsVoiceGraph(/*add_remote_outbound_stats=*/false);
|
||||
EXPECT_FALSE(graph.full_report->Get(graph.remote_outbound_rtp_id));
|
||||
// Also check that no other remote outbound report is created (in case the
|
||||
// expected ID is incorrect).
|
||||
rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
|
||||
ASSERT_NE(report->begin(), report->end())
|
||||
<< "No reports have been generated.";
|
||||
for (const auto& stats : *report) {
|
||||
SCOPED_TRACE(stats.id());
|
||||
EXPECT_NE(stats.type(), RTCRemoteOutboundRtpStreamStats::kType);
|
||||
}
|
||||
}
|
||||
|
||||
// Checks that the remote outbound stats are collected when available in
|
||||
// `VoiceMediaInfo`.
|
||||
TEST_F(RTCStatsCollectorTest, RTCRemoteOutboundRtpAudioStreamStatsCollected) {
|
||||
ExampleStatsGraph graph =
|
||||
SetupExampleStatsVoiceGraph(/*add_remote_outbound_stats=*/true);
|
||||
ASSERT_TRUE(graph.full_report->Get(graph.remote_outbound_rtp_id));
|
||||
const auto& remote_outbound_rtp =
|
||||
graph.full_report->Get(graph.remote_outbound_rtp_id)
|
||||
->cast_to<RTCRemoteOutboundRtpStreamStats>();
|
||||
EXPECT_EQ(remote_outbound_rtp.timestamp_us(),
|
||||
kRemoteOutboundStatsTimestampMs * rtc::kNumMicrosecsPerMillisec);
|
||||
EXPECT_FLOAT_EQ(*remote_outbound_rtp.remote_timestamp,
|
||||
static_cast<double>(kRemoteOutboundStatsRemoteTimestampMs));
|
||||
EXPECT_EQ(*remote_outbound_rtp.packets_sent, kRemoteOutboundStatsPacketsSent);
|
||||
EXPECT_EQ(*remote_outbound_rtp.bytes_sent, kRemoteOutboundStatsBytesSent);
|
||||
EXPECT_EQ(*remote_outbound_rtp.reports_sent,
|
||||
kRemoteOutboundStatsReportsCount);
|
||||
}
|
||||
|
||||
TEST_F(RTCStatsCollectorTest,
|
||||
RTCVideoSourceStatsNotCollectedForSenderWithoutTrack) {
|
||||
const uint32_t kSsrc = 4;
|
||||
|
|
|
@ -399,6 +399,9 @@ class RTCStatsReportVerifier {
|
|||
} else if (stats.type() == RTCRemoteInboundRtpStreamStats::kType) {
|
||||
verify_successful &= VerifyRTCRemoteInboundRtpStreamStats(
|
||||
stats.cast_to<RTCRemoteInboundRtpStreamStats>());
|
||||
} else if (stats.type() == RTCRemoteOutboundRtpStreamStats::kType) {
|
||||
verify_successful &= VerifyRTCRemoteOutboundRTPStreamStats(
|
||||
stats.cast_to<RTCRemoteOutboundRtpStreamStats>());
|
||||
} else if (stats.type() == RTCAudioSourceStats::kType) {
|
||||
// RTCAudioSourceStats::kType and RTCVideoSourceStats::kType both have
|
||||
// the value "media-source", but they are distinguishable with pointer
|
||||
|
@ -769,29 +772,38 @@ class RTCStatsReportVerifier {
|
|||
}
|
||||
|
||||
void VerifyRTCRTPStreamStats(const RTCRTPStreamStats& stream,
|
||||
RTCStatsVerifier* verifier) {
|
||||
verifier->TestMemberIsDefined(stream.ssrc);
|
||||
verifier->TestMemberIsDefined(stream.kind);
|
||||
RTCStatsVerifier& verifier) {
|
||||
verifier.TestMemberIsDefined(stream.ssrc);
|
||||
verifier.TestMemberIsDefined(stream.kind);
|
||||
// Some legacy metrics are only defined for some of the RTP types in the
|
||||
// hierarcy.
|
||||
if (stream.type() == RTCInboundRTPStreamStats::kType ||
|
||||
stream.type() == RTCOutboundRTPStreamStats::kType) {
|
||||
verifier->TestMemberIsDefined(stream.media_type);
|
||||
verifier->TestMemberIsIDReference(stream.track_id,
|
||||
verifier.TestMemberIsDefined(stream.media_type);
|
||||
verifier.TestMemberIsIDReference(stream.track_id,
|
||||
RTCMediaStreamTrackStats::kType);
|
||||
} else {
|
||||
verifier->TestMemberIsUndefined(stream.media_type);
|
||||
verifier->TestMemberIsUndefined(stream.track_id);
|
||||
verifier.TestMemberIsUndefined(stream.media_type);
|
||||
verifier.TestMemberIsUndefined(stream.track_id);
|
||||
}
|
||||
verifier->TestMemberIsIDReference(stream.transport_id,
|
||||
verifier.TestMemberIsIDReference(stream.transport_id,
|
||||
RTCTransportStats::kType);
|
||||
verifier->TestMemberIsIDReference(stream.codec_id, RTCCodecStats::kType);
|
||||
verifier.TestMemberIsIDReference(stream.codec_id, RTCCodecStats::kType);
|
||||
}
|
||||
|
||||
void VerifyRTCSentRTPStreamStats(const RTCSentRtpStreamStats& sent_stream,
|
||||
RTCStatsVerifier& verifier) {
|
||||
VerifyRTCRTPStreamStats(sent_stream, verifier);
|
||||
verifier.TestMemberIsDefined(sent_stream.packets_sent);
|
||||
verifier.TestMemberIsDefined(sent_stream.bytes_sent);
|
||||
}
|
||||
|
||||
bool VerifyRTCInboundRTPStreamStats(
|
||||
const RTCInboundRTPStreamStats& inbound_stream) {
|
||||
RTCStatsVerifier verifier(report_, &inbound_stream);
|
||||
VerifyRTCRTPStreamStats(inbound_stream, &verifier);
|
||||
VerifyRTCRTPStreamStats(inbound_stream, verifier);
|
||||
verifier.TestMemberIsOptionalIDReference(
|
||||
inbound_stream.remote_id, RTCRemoteOutboundRtpStreamStats::kType);
|
||||
if (inbound_stream.media_type.is_defined() &&
|
||||
*inbound_stream.media_type == "video") {
|
||||
verifier.TestMemberIsNonNegative<uint64_t>(inbound_stream.qp_sum);
|
||||
|
@ -928,7 +940,7 @@ class RTCStatsReportVerifier {
|
|||
// TODO(https://crbug.com/webrtc/12532): Invoke
|
||||
// VerifyRTCReceivedRtpStreamStats() instead of VerifyRTCRTPStreamStats()
|
||||
// because they have a shared hierarchy now!
|
||||
VerifyRTCRTPStreamStats(outbound_stream, &verifier);
|
||||
VerifyRTCRTPStreamStats(outbound_stream, verifier);
|
||||
if (outbound_stream.media_type.is_defined() &&
|
||||
*outbound_stream.media_type == "video") {
|
||||
verifier.TestMemberIsIDReference(outbound_stream.media_source_id,
|
||||
|
@ -1021,16 +1033,16 @@ class RTCStatsReportVerifier {
|
|||
|
||||
void VerifyRTCReceivedRtpStreamStats(
|
||||
const RTCReceivedRtpStreamStats& received_rtp,
|
||||
RTCStatsVerifier* verifier) {
|
||||
RTCStatsVerifier& verifier) {
|
||||
VerifyRTCRTPStreamStats(received_rtp, verifier);
|
||||
verifier->TestMemberIsNonNegative<double>(received_rtp.jitter);
|
||||
verifier->TestMemberIsDefined(received_rtp.packets_lost);
|
||||
verifier.TestMemberIsNonNegative<double>(received_rtp.jitter);
|
||||
verifier.TestMemberIsDefined(received_rtp.packets_lost);
|
||||
}
|
||||
|
||||
bool VerifyRTCRemoteInboundRtpStreamStats(
|
||||
const RTCRemoteInboundRtpStreamStats& remote_inbound_stream) {
|
||||
RTCStatsVerifier verifier(report_, &remote_inbound_stream);
|
||||
VerifyRTCReceivedRtpStreamStats(remote_inbound_stream, &verifier);
|
||||
VerifyRTCReceivedRtpStreamStats(remote_inbound_stream, verifier);
|
||||
verifier.TestMemberIsDefined(remote_inbound_stream.fraction_lost);
|
||||
verifier.TestMemberIsIDReference(remote_inbound_stream.local_id,
|
||||
RTCOutboundRTPStreamStats::kType);
|
||||
|
@ -1043,6 +1055,19 @@ class RTCStatsReportVerifier {
|
|||
return verifier.ExpectAllMembersSuccessfullyTested();
|
||||
}
|
||||
|
||||
bool VerifyRTCRemoteOutboundRTPStreamStats(
|
||||
const RTCRemoteOutboundRtpStreamStats& remote_outbound_stream) {
|
||||
RTCStatsVerifier verifier(report_, &remote_outbound_stream);
|
||||
VerifyRTCRTPStreamStats(remote_outbound_stream, verifier);
|
||||
VerifyRTCSentRTPStreamStats(remote_outbound_stream, verifier);
|
||||
verifier.TestMemberIsIDReference(remote_outbound_stream.local_id,
|
||||
RTCOutboundRTPStreamStats::kType);
|
||||
verifier.TestMemberIsNonNegative<double>(
|
||||
remote_outbound_stream.remote_timestamp);
|
||||
verifier.TestMemberIsDefined(remote_outbound_stream.reports_sent);
|
||||
return verifier.ExpectAllMembersSuccessfullyTested();
|
||||
}
|
||||
|
||||
void VerifyRTCMediaSourceStats(const RTCMediaSourceStats& media_source,
|
||||
RTCStatsVerifier* verifier) {
|
||||
verifier->TestMemberIsDefined(media_source.track_identifier);
|
||||
|
|
|
@ -99,24 +99,36 @@ std::vector<const std::string*> GetStatsReferencedIds(const RTCStats& stats) {
|
|||
AddIdIfDefined(track.media_source_id, &neighbor_ids);
|
||||
} else if (type == RTCPeerConnectionStats::kType) {
|
||||
// RTCPeerConnectionStats does not have any neighbor references.
|
||||
} else if (type == RTCInboundRTPStreamStats::kType ||
|
||||
type == RTCOutboundRTPStreamStats::kType) {
|
||||
const auto& rtp = static_cast<const RTCRTPStreamStats&>(stats);
|
||||
AddIdIfDefined(rtp.track_id, &neighbor_ids);
|
||||
AddIdIfDefined(rtp.transport_id, &neighbor_ids);
|
||||
AddIdIfDefined(rtp.codec_id, &neighbor_ids);
|
||||
if (type == RTCOutboundRTPStreamStats::kType) {
|
||||
} else if (type == RTCInboundRTPStreamStats::kType) {
|
||||
const auto& inbound_rtp =
|
||||
static_cast<const RTCInboundRTPStreamStats&>(stats);
|
||||
AddIdIfDefined(inbound_rtp.remote_id, &neighbor_ids);
|
||||
AddIdIfDefined(inbound_rtp.track_id, &neighbor_ids);
|
||||
AddIdIfDefined(inbound_rtp.transport_id, &neighbor_ids);
|
||||
AddIdIfDefined(inbound_rtp.codec_id, &neighbor_ids);
|
||||
} else if (type == RTCOutboundRTPStreamStats::kType) {
|
||||
const auto& outbound_rtp =
|
||||
static_cast<const RTCOutboundRTPStreamStats&>(stats);
|
||||
AddIdIfDefined(outbound_rtp.media_source_id, &neighbor_ids);
|
||||
AddIdIfDefined(outbound_rtp.remote_id, &neighbor_ids);
|
||||
}
|
||||
AddIdIfDefined(outbound_rtp.track_id, &neighbor_ids);
|
||||
AddIdIfDefined(outbound_rtp.transport_id, &neighbor_ids);
|
||||
AddIdIfDefined(outbound_rtp.codec_id, &neighbor_ids);
|
||||
AddIdIfDefined(outbound_rtp.media_source_id, &neighbor_ids);
|
||||
} else if (type == RTCRemoteInboundRtpStreamStats::kType) {
|
||||
const auto& remote_inbound_rtp =
|
||||
static_cast<const RTCRemoteInboundRtpStreamStats&>(stats);
|
||||
AddIdIfDefined(remote_inbound_rtp.transport_id, &neighbor_ids);
|
||||
AddIdIfDefined(remote_inbound_rtp.codec_id, &neighbor_ids);
|
||||
AddIdIfDefined(remote_inbound_rtp.local_id, &neighbor_ids);
|
||||
} else if (type == RTCRemoteOutboundRtpStreamStats::kType) {
|
||||
const auto& remote_outbound_rtp =
|
||||
static_cast<const RTCRemoteOutboundRtpStreamStats&>(stats);
|
||||
// Inherited from `RTCRTPStreamStats`.
|
||||
AddIdIfDefined(remote_outbound_rtp.track_id, &neighbor_ids);
|
||||
AddIdIfDefined(remote_outbound_rtp.transport_id, &neighbor_ids);
|
||||
AddIdIfDefined(remote_outbound_rtp.codec_id, &neighbor_ids);
|
||||
// Direct members of `RTCRemoteOutboundRtpStreamStats`.
|
||||
AddIdIfDefined(remote_outbound_rtp.local_id, &neighbor_ids);
|
||||
} else if (type == RTCAudioSourceStats::kType ||
|
||||
type == RTCVideoSourceStats::kType) {
|
||||
// RTC[Audio/Video]SourceStats does not have any neighbor references.
|
||||
|
|
|
@ -606,9 +606,34 @@ RTCReceivedRtpStreamStats::RTCReceivedRtpStreamStats(
|
|||
|
||||
RTCReceivedRtpStreamStats::~RTCReceivedRtpStreamStats() {}
|
||||
|
||||
// clang-format off
|
||||
WEBRTC_RTCSTATS_IMPL(
|
||||
RTCSentRtpStreamStats, RTCRTPStreamStats, "sent-rtp",
|
||||
&packets_sent,
|
||||
&bytes_sent)
|
||||
// clang-format on
|
||||
|
||||
RTCSentRtpStreamStats::RTCSentRtpStreamStats(const std::string&& id,
|
||||
int64_t timestamp_us)
|
||||
: RTCSentRtpStreamStats(std::string(id), timestamp_us) {}
|
||||
|
||||
RTCSentRtpStreamStats::RTCSentRtpStreamStats(std::string&& id,
|
||||
int64_t timestamp_us)
|
||||
: RTCRTPStreamStats(std::move(id), timestamp_us),
|
||||
packets_sent("packetsSent"),
|
||||
bytes_sent("bytesSent") {}
|
||||
|
||||
RTCSentRtpStreamStats::RTCSentRtpStreamStats(const RTCSentRtpStreamStats& other)
|
||||
: RTCRTPStreamStats(other),
|
||||
packets_sent(other.packets_sent),
|
||||
bytes_sent(other.bytes_sent) {}
|
||||
|
||||
RTCSentRtpStreamStats::~RTCSentRtpStreamStats() {}
|
||||
|
||||
// clang-format off
|
||||
WEBRTC_RTCSTATS_IMPL(
|
||||
RTCInboundRTPStreamStats, RTCReceivedRtpStreamStats, "inbound-rtp",
|
||||
&remote_id,
|
||||
&packets_received,
|
||||
&fec_packets_received,
|
||||
&fec_packets_discarded,
|
||||
|
@ -665,6 +690,7 @@ RTCInboundRTPStreamStats::RTCInboundRTPStreamStats(const std::string& id,
|
|||
RTCInboundRTPStreamStats::RTCInboundRTPStreamStats(std::string&& id,
|
||||
int64_t timestamp_us)
|
||||
: RTCReceivedRtpStreamStats(std::move(id), timestamp_us),
|
||||
remote_id("remoteId"),
|
||||
packets_received("packetsReceived"),
|
||||
fec_packets_received("fecPacketsReceived"),
|
||||
fec_packets_discarded("fecPacketsDiscarded"),
|
||||
|
@ -716,6 +742,7 @@ RTCInboundRTPStreamStats::RTCInboundRTPStreamStats(std::string&& id,
|
|||
RTCInboundRTPStreamStats::RTCInboundRTPStreamStats(
|
||||
const RTCInboundRTPStreamStats& other)
|
||||
: RTCReceivedRtpStreamStats(other),
|
||||
remote_id(other.remote_id),
|
||||
packets_received(other.packets_received),
|
||||
fec_packets_received(other.fec_packets_received),
|
||||
fec_packets_discarded(other.fec_packets_discarded),
|
||||
|
@ -913,6 +940,37 @@ RTCRemoteInboundRtpStreamStats::RTCRemoteInboundRtpStreamStats(
|
|||
|
||||
RTCRemoteInboundRtpStreamStats::~RTCRemoteInboundRtpStreamStats() {}
|
||||
|
||||
// clang-format off
|
||||
WEBRTC_RTCSTATS_IMPL(
|
||||
RTCRemoteOutboundRtpStreamStats, RTCSentRtpStreamStats,
|
||||
"remote-outbound-rtp",
|
||||
&local_id,
|
||||
&remote_timestamp,
|
||||
&reports_sent)
|
||||
// clang-format on
|
||||
|
||||
RTCRemoteOutboundRtpStreamStats::RTCRemoteOutboundRtpStreamStats(
|
||||
const std::string& id,
|
||||
int64_t timestamp_us)
|
||||
: RTCRemoteOutboundRtpStreamStats(std::string(id), timestamp_us) {}
|
||||
|
||||
RTCRemoteOutboundRtpStreamStats::RTCRemoteOutboundRtpStreamStats(
|
||||
std::string&& id,
|
||||
int64_t timestamp_us)
|
||||
: RTCSentRtpStreamStats(std::move(id), timestamp_us),
|
||||
local_id("localId"),
|
||||
remote_timestamp("remoteTimestamp"),
|
||||
reports_sent("reportsSent") {}
|
||||
|
||||
RTCRemoteOutboundRtpStreamStats::RTCRemoteOutboundRtpStreamStats(
|
||||
const RTCRemoteOutboundRtpStreamStats& other)
|
||||
: RTCSentRtpStreamStats(other),
|
||||
local_id(other.local_id),
|
||||
remote_timestamp(other.remote_timestamp),
|
||||
reports_sent(other.reports_sent) {}
|
||||
|
||||
RTCRemoteOutboundRtpStreamStats::~RTCRemoteOutboundRtpStreamStats() {}
|
||||
|
||||
// clang-format off
|
||||
WEBRTC_RTCSTATS_IMPL(RTCMediaSourceStats, RTCStats, "parent-media-source",
|
||||
&track_identifier,
|
||||
|
|
Loading…
Reference in a new issue