webrtc 代码学习(三十) rtt 计算方法
rtt 计算方法
作者:LanPZzzz
文章目录
1. 请查看 [webrtc] rtcp模块中rtt时间计算
2. 因为我们查看的是A->B,B->A 的数据互通,所以在rtt 的计算的,不管是A端计算还是B端计算,都应该是一样的
3. 我们在测试的时候
- 使用delay,把导到的包延迟发放,rtt没有变,但是按照计算应该是要变的啊
4. BR,RR 包
A (发送BR 包) -> B,BuildSR
std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildSR(const RtcpContext& ctx) {
。。。
rtcp::SenderReport* report = new rtcp::SenderReport();
report->SetSenderSsrc(ssrc_);
在report 放入 A 端的当前时间
report->SetNtp(ctx.now_);
report->SetRtpTimestamp(rtp_timestamp);
report->SetPacketCount(ctx.feedback_state_.packets_sent);
report->SetOctetCount(ctx.feedback_state_.media_bytes_sent);
report->SetReportBlocks(CreateReportBlocks(ctx.feedback_state_));
。。。
}
B (接收到BR 包)
void RTCPReceiver::HandleSenderReport(const CommonHeader& rtcp_block,
PacketInformation* packet_information) {
rtcp::SenderReport sender_report;
if (!sender_report.Parse(rtcp_block)) {
++num_skipped_packets_;
return;
}
const uint32_t remote_ssrc = sender_report.sender_ssrc();
packet_information->remote_ssrc = remote_ssrc;
UpdateTmmbrRemoteIsAlive(remote_ssrc);
// Have I received RTP packets from this party?
if (remote_ssrc_ == remote_ssrc) {
// Only signal that we have received a SR when we accept one.
packet_information->packet_type_flags |= kRtcpSr;
接收到BR 包,是远程ssrc 的,保存A 端的ntp 时间
remote_sender_ntp_time_ = sender_report.ntp();
remote_sender_rtp_time_ = sender_report.rtp_timestamp();
last_received_sr_ntp_ = clock_->CurrentNtpTime();
} else {
// We will only store the send report from one source, but
// we will store all the receive blocks.
packet_information->packet_type_flags |= kRtcpRr;
}
RTC_LOG(LS_WARNING) << "LanPZzzz === RTCPReceiver::HandleSenderReport rtp_rtcp_:"
<< (int64_t)rtp_rtcp_;
for (const rtcp::ReportBlock report_block : sender_report.report_blocks())
HandleReportBlock(report_block, packet_information, remote_ssrc);
}
B (发送RR 包) -> A,BuildRR
rtcp_sender_.SendRTCP(GetFeedbackState(), kRtcpReport);
-> ModuleRtpRtcpImpl::GetFeedbackState (modules\rtp_rtcp\source\rtp_rtcp_impl.cc 358)
-> ModuleRtpRtcpImpl::LastReceivedNTP (modules\rtp_rtcp\source\rtp_rtcp_impl.cc 853)
-> RTCPReceiver::NTP (modules\rtp_rtcp\source\rtcp_receiver.cc 246)主要是获取received_ntp_secs, received_ntp_frac
bool RTCPReceiver::NTP(uint32_t* received_ntp_secs,
uint32_t* received_ntp_frac,
uint32_t* rtcp_arrival_time_secs,
uint32_t* rtcp_arrival_time_frac,
uint32_t* rtcp_timestamp) const {
rtc::CritScope lock(&rtcp_receiver_lock_);
if (!last_received_sr_ntp_.Valid())
return false;
主要是获取received_ntp_secs, received_ntp_frac
// NTP from incoming SenderReport.
if (received_ntp_secs)
*received_ntp_secs = remote_sender_ntp_time_.seconds();
if (received_ntp_frac)
*received_ntp_frac = remote_sender_ntp_time_.fractions();
。。。。
*remote_sr =
((ntp_secs & 0x0000ffff) << 16) + ((ntp_frac & 0xffff0000) >> 16);
remote_sr 就是feeback 中的remote_sr
build RR
std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildRR(const RtcpContext& ctx) {
rtcp::ReceiverReport* report = new rtcp::ReceiverReport();
report->SetSenderSsrc(ssrc_);
report->SetReportBlocks(CreateReportBlocks(ctx.feedback_state_));
。。。
std::vector<rtcp::ReportBlock> RTCPSender::CreateReportBlocks(
const FeedbackState& feedback_state) {
std::vector<rtcp::ReportBlock> result;
if (!receive_statistics_)
return result;
// TODO(danilchap): Support sending more than |RTCP_MAX_REPORT_BLOCKS| per
// compound rtcp packet when single rtcp module is used for multiple media
// streams.
result = receive_statistics_->RtcpReportBlocks(RTCP_MAX_REPORT_BLOCKS);
if (!result.empty() && ((feedback_state.last_rr_ntp_secs != 0) ||
(feedback_state.last_rr_ntp_frac != 0))) {
// Get our NTP as late as possible to avoid a race.
uint32_t now = CompactNtp(clock_->CurrentNtpTime());
uint32_t receive_time = feedback_state.last_rr_ntp_secs & 0x0000FFFF;
receive_time <<= 16;
receive_time += (feedback_state.last_rr_ntp_frac & 0xffff0000) >> 16;
uint32_t delay_since_last_sr = now - receive_time;
// TODO(danilchap): Instead of setting same value on all report blocks,
// set only when media_ssrc match sender ssrc of the sender report
// remote times were taken from.
for (auto& report_block : result) {
report_block.SetLastSr(feedback_state.remote_sr); 这里设置了 LSR, 就是A 端发送的时间
report_block.SetDelayLastSr(delay_since_last_sr);
}
}
return result;
}
5. rtt 计算
void RTCPReceiver::HandleReportBlock(const ReportBlock& report_block,
PacketInformation* packet_information,
uint32_t remote_ssrc) {
。。。
last_received_rb_ms_ = clock_->TimeInMilliseconds();
。。。
int64_t rtt_ms = 0;
uint32_t send_time_ntp = report_block.last_sr();
// RFC3550, section 6.4.1, LSR field discription states:
// If no SR has been received yet, the field is set to zero.
// Receiver rtp_rtcp module is not expected to calculate rtt using
// Sender Reports even if it accidentally can.
if (!receiver_only_ && send_time_ntp != 0) {
uint32_t delay_ntp = report_block.delay_since_last_sr();
// Local NTP time.
uint32_t receive_time_ntp = CompactNtp(clock_->CurrentNtpTime());
// RTT in 1/(2^16) seconds.
这里计算,接收到RR 包,获取ReportBlock 中 LSR,LDSR,公式 rtt = now - LSR - LDSR
uint32_t rtt_ntp = receive_time_ntp - delay_ntp - send_time_ntp;
// Convert to 1/1000 seconds (milliseconds).
rtt_ms = CompactNtpRttToMs(rtt_ntp);
if (rtt_ms > report_block_info->max_rtt_ms)
report_block_info->max_rtt_ms = rtt_ms;
if (report_block_info->num_rtts == 0 ||
rtt_ms < report_block_info->min_rtt_ms)
report_block_info->min_rtt_ms = rtt_ms;
report_block_info->last_rtt_ms = rtt_ms;
report_block_info->sum_rtt_ms += rtt_ms;
++report_block_info->num_rtts;
packet_information->rtt_ms = rtt_ms;
}
packet_information->report_blocks.push_back(report_block_info->report_block);
}