Wire up non-sender RTT for audio, and implement related standardized stats.

The implemented stats are:
- https://www.w3.org/TR/webrtc-stats/#dom-rtcremoteoutboundrtpstreamstats-roundtriptime
- https://www.w3.org/TR/webrtc-stats/#dom-rtcremoteoutboundrtpstreamstats-totalroundtriptime
- https://www.w3.org/TR/webrtc-stats/#dom-rtcremoteoutboundrtpstreamstats-roundtriptimemeasurements

Bug: webrtc:12951, webrtc:12714
Change-Id: Ia362d5c4b0456140e32da79d40edc06ab9ce2a2c
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/226956
Commit-Queue: Ivo Creusen <ivoc@webrtc.org>
Reviewed-by: Henrik Boström <hbos@webrtc.org>
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Reviewed-by: Danil Chapovalov <danilchap@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#34861}
This commit is contained in:
Ivo Creusen
2021-08-26 17:35:51 +00:00
committed by WebRTC LUCI CQ
parent 58157b5cd2
commit fb0dca6c05
30 changed files with 552 additions and 27 deletions

View File

@ -303,6 +303,15 @@ int32_t RTCPReceiver::RTT(uint32_t remote_ssrc,
return 0;
}
RTCPReceiver::NonSenderRttStats RTCPReceiver::GetNonSenderRTT() const {
MutexLock lock(&rtcp_receiver_lock_);
auto it = non_sender_rtts_.find(remote_ssrc_);
if (it == non_sender_rtts_.end()) {
return {};
}
return it->second;
}
void RTCPReceiver::SetNonSenderRttMeasurement(bool enabled) {
MutexLock lock(&rtcp_receiver_lock_);
xr_rrtr_status_ = enabled;
@ -435,6 +444,16 @@ bool RTCPReceiver::ParseCompoundPacket(rtc::ArrayView<const uint8_t> packet,
MutexLock lock(&rtcp_receiver_lock_);
CommonHeader rtcp_block;
// If a sender report is received but no DLRR, we need to reset the
// roundTripTime stat according to the standard, see
// https://www.w3.org/TR/webrtc-stats/#dom-rtcremoteoutboundrtpstreamstats-roundtriptime
struct RtcpReceivedBlock {
bool sender_report = false;
bool dlrr = false;
};
// For each remote SSRC we store if we've received a sender report or a DLRR
// block.
flat_map<uint32_t, RtcpReceivedBlock> received_blocks;
for (const uint8_t* next_block = packet.begin(); next_block != packet.end();
next_block = rtcp_block.NextPacket()) {
ptrdiff_t remaining_blocks_size = packet.end() - next_block;
@ -455,6 +474,7 @@ bool RTCPReceiver::ParseCompoundPacket(rtc::ArrayView<const uint8_t> packet,
switch (rtcp_block.type()) {
case rtcp::SenderReport::kPacketType:
HandleSenderReport(rtcp_block, packet_information);
received_blocks[packet_information->remote_ssrc].sender_report = true;
break;
case rtcp::ReceiverReport::kPacketType:
HandleReceiverReport(rtcp_block, packet_information);
@ -463,7 +483,12 @@ bool RTCPReceiver::ParseCompoundPacket(rtc::ArrayView<const uint8_t> packet,
HandleSdes(rtcp_block, packet_information);
break;
case rtcp::ExtendedReports::kPacketType:
HandleXr(rtcp_block, packet_information);
bool contains_dlrr;
uint32_t ssrc;
HandleXr(rtcp_block, packet_information, contains_dlrr, ssrc);
if (contains_dlrr) {
received_blocks[ssrc].dlrr = true;
}
break;
case rtcp::Bye::kPacketType:
HandleBye(rtcp_block);
@ -515,6 +540,15 @@ bool RTCPReceiver::ParseCompoundPacket(rtc::ArrayView<const uint8_t> packet,
}
}
for (const auto& rb : received_blocks) {
if (rb.second.sender_report && !rb.second.dlrr) {
auto rtt_stats = non_sender_rtts_.find(rb.first);
if (rtt_stats != non_sender_rtts_.end()) {
rtt_stats->second.Invalidate();
}
}
}
if (packet_type_counter_observer_) {
packet_type_counter_observer_->RtcpPacketTypesCounterUpdated(
main_ssrc_, packet_type_counter_);
@ -832,18 +866,22 @@ void RTCPReceiver::HandleBye(const CommonHeader& rtcp_block) {
}
void RTCPReceiver::HandleXr(const CommonHeader& rtcp_block,
PacketInformation* packet_information) {
PacketInformation* packet_information,
bool& contains_dlrr,
uint32_t& ssrc) {
rtcp::ExtendedReports xr;
if (!xr.Parse(rtcp_block)) {
++num_skipped_packets_;
return;
}
ssrc = xr.sender_ssrc();
contains_dlrr = !xr.dlrr().sub_blocks().empty();
if (xr.rrtr())
HandleXrReceiveReferenceTime(xr.sender_ssrc(), *xr.rrtr());
for (const rtcp::ReceiveTimeInfo& time_info : xr.dlrr().sub_blocks())
HandleXrDlrrReportBlock(time_info);
HandleXrDlrrReportBlock(xr.sender_ssrc(), time_info);
if (xr.target_bitrate()) {
HandleXrTargetBitrate(xr.sender_ssrc(), *xr.target_bitrate(),
@ -872,7 +910,8 @@ void RTCPReceiver::HandleXrReceiveReferenceTime(uint32_t sender_ssrc,
}
}
void RTCPReceiver::HandleXrDlrrReportBlock(const rtcp::ReceiveTimeInfo& rti) {
void RTCPReceiver::HandleXrDlrrReportBlock(uint32_t sender_ssrc,
const rtcp::ReceiveTimeInfo& rti) {
if (!registered_ssrcs_.contains(rti.ssrc)) // Not to us.
return;
@ -884,14 +923,21 @@ void RTCPReceiver::HandleXrDlrrReportBlock(const rtcp::ReceiveTimeInfo& rti) {
uint32_t send_time_ntp = rti.last_rr;
// RFC3611, section 4.5, LRR field discription states:
// If no such block has been received, the field is set to zero.
if (send_time_ntp == 0)
if (send_time_ntp == 0) {
auto rtt_stats = non_sender_rtts_.find(sender_ssrc);
if (rtt_stats != non_sender_rtts_.end()) {
rtt_stats->second.Invalidate();
}
return;
}
uint32_t delay_ntp = rti.delay_since_last_rr;
uint32_t now_ntp = CompactNtp(clock_->CurrentNtpTime());
uint32_t rtt_ntp = now_ntp - delay_ntp - send_time_ntp;
xr_rr_rtt_ms_ = CompactNtpRttToMs(rtt_ntp);
non_sender_rtts_[sender_ssrc].Update(TimeDelta::Millis(xr_rr_rtt_ms_));
}
void RTCPReceiver::HandleXrTargetBitrate(