日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

[webrtc] rtcp模块中rtt时间计算

發(fā)布時間:2023/12/13 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [webrtc] rtcp模块中rtt时间计算 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

RTT指 round-trip time,即計算AB兩端的往返時延

這里可以分成兩個問題:

如何在A端估算A和B之間的RTT時間?

如何在B端估算A和B之間的RTT時間?

?

本文參考資料:
rfc 3550
rfc 3611
webrtc issue https://code.google.com/p/webrtc/issues/detail?id=1613
以及解決版本
https://code.google.com/p/webrtc/source/detail?r=4898
https://code.google.com/p/webrtc/source/detail?r=5063

?

?

一、假設(shè)A -> B 發(fā)送視頻. 那么如何在A端估算A->B之間的RTT時間?

RFC 3550 http://tools.ietf.org/html/rfc3550#section-6.4.1
6.4.1 SR: Sender Report RTCP Packet
中描述了如何在發(fā)送端計算RTT時間.
大概過程如下:
A 發(fā)送 SR 包, 并記錄SR包的發(fā)送時間. 記為send_time
B 接收到 A的SR包后, 記錄下最后一次接受到SR包的時間. 記為last_recv_time
... (B等待發(fā)送rtcp包)
B 發(fā)送 RR包, 計算從[last_recv_time] 到 當(dāng)前時間的延時. 記錄為delay_since_last_SR. 附加到RR包中.
A 收到 B的RR包后, 計算RTT
RTT = send_time - delay_since_last_SR - last_recv_time

對應(yīng)到webrtc中的實現(xiàn).

何時發(fā)送rtcp ?
ModuleRtpRtcpImpl::Process
if (rtcp_sender_.TimeToSendRTCPReport()) {
rtcp_sender_.SendRTCP(GetFeedbackState(), kRtcpReport);
}
在RTCPSender::TimeToSendRTCPReport 詳細(xì)說明了RTCP的發(fā)送頻率.
每次發(fā)送RTCP時都會計算出下一次發(fā)送rtcp的時間, 即_nextTimeToSendRTCP.
對于 RR和SR包. 計算如下.
RTCPSender::PrepareRTCP
....
if( rtcpPacketTypeFlags & kRtcpRr ||
rtcpPacketTypeFlags & kRtcpSr)
{
// generate next time to send a RTCP report
// seeded from RTP constructor
int32_t random = rand() % 1000;
int32_t timeToNext = RTCP_INTERVAL_AUDIO_MS;

if(_audio)
{
timeToNext = (RTCP_INTERVAL_AUDIO_MS/2) +
(RTCP_INTERVAL_AUDIO_MS*random/1000);
}else
{
uint32_t minIntervalMs = RTCP_INTERVAL_AUDIO_MS;
if(_sending)
{
// Calculate bandwidth for video; 360 / send bandwidth in kbit/s.
uint32_t send_bitrate_kbit = feedback_state.send_bitrate / 1000;
if (send_bitrate_kbit != 0)
minIntervalMs = 360000 / send_bitrate_kbit;
}
if(minIntervalMs > RTCP_INTERVAL_VIDEO_MS)
{
minIntervalMs = RTCP_INTERVAL_VIDEO_MS;
}
timeToNext = (minIntervalMs/2) + (minIntervalMs*random/1000);
}
_nextTimeToSendRTCP = _clock->TimeInMilliseconds() + timeToNext;
}
依賴于隨機(jī)值, 而且音視頻的時間也不同.


A -> 發(fā)送SR包.
ModuleRtpRtcpImpl::Process
RTCPSender::SendRTCP
RTCPSender::PrepareRTCP
RTCPSender::BuildSR
PrepareRTCP 中通過_sending(是否是發(fā)送端) 狀態(tài)判定發(fā)送SR或RR. SR包中含有發(fā)送時的NTP時間戳.
BuildSR中
_lastSendReport 記錄NTP時間的中間32位. 可以標(biāo)識SR包, 也就是B回應(yīng)RR包中report block的LSR字段(last SR timestamp ), 通過LSR可以查找_lastRTCPTime.
_lastRTCPTime記錄RTCP_NUMBER_OF_SR個數(shù)的SR發(fā)送時間.
這兩個數(shù)組是一一對應(yīng)的.
_lastRTCPTime[0] = Clock::NtpToMs(NTPsec, NTPfrac);
_lastSendReport[0] = (NTPsec << 16) + (NTPfrac >> 16);

最后SendToNetwork.


B -> 接收到SR包.
ModuleRtpRtcpImpl::IncomingRtcpPacket
RTCPReceiver::IncomingRTCPPacket
RTCPReceiver::HandleSenderReceiverReport
在HandleSenderReceiverReport 中保存 SR包中的NTP時間戳
_remoteSenderInfo.NTPseconds = rtcpPacket.SR.NTPMostSignificant;
_remoteSenderInfo.NTPfraction = rtcpPacket.SR.NTPLeastSignificant;
并記錄SR包接到時的NTP時間戳
_clock->CurrentNtp(_lastReceivedSRNTPsecs, _lastReceivedSRNTPfrac);


B -> 發(fā)送RR包
獲取回饋狀態(tài), 并發(fā)送給A
ModuleRtpRtcpImpl::Process()
if (rtcp_sender_.TimeToSendRTCPReport()) {
rtcp_sender_.SendRTCP(GetFeedbackState(), kRtcpReport);
}

ModuleRtpRtcpImpl::GetFeedbackState()
ModuleRtpRtcpImpl::LastReceivedNTP

state.last_rr_ntp_secs 和state.last_rr_ntp_frac
即為上一次接收到SR包時, 記錄的_clock->CurrentNtp(_lastReceivedSRNTPsecs, _lastReceivedSRNTPfrac); 時間戳.
state.remote_sr 通過_remoteSenderInfo.NTPseconds 和 _remoteSenderInfo.NTPfraction, 取中間32位算出.

RTCPSender::PrepareReport
在這里計算延時, 填充到report block中.

// get our NTP as late as possible to avoid a race
_clock->CurrentNtp(*ntp_secs, *ntp_frac);

// Delay since last received report
uint32_t delaySinceLastReceivedSR = 0;
if ((feedback_state.last_rr_ntp_secs != 0) ||
(feedback_state.last_rr_ntp_frac != 0)) {
// get the 16 lowest bits of seconds and the 16 higest bits of fractions
uint32_t now=*ntp_secs&0x0000FFFF;
now <<=16;
now += (*ntp_frac&0xffff0000)>>16;

uint32_t receiveTime = feedback_state.last_rr_ntp_secs&0x0000FFFF;
receiveTime <<=16;
receiveTime += (feedback_state.last_rr_ntp_frac&0xffff0000)>>16;

delaySinceLastReceivedSR = now-receiveTime;
}
report_block->delaySinceLastSR = delaySinceLastReceivedSR;
report_block->lastSR = feedback_state.remote_sr;

report_block->delaySinceLastSR 即為 從接到SR包到發(fā)送RR包之間的延時.
report_block->lastSR 即SR包中NTP時間戳的中間32位. (在A端_lastSendReport數(shù)組中記錄).

A 收到 B的RR包
ModuleRtpRtcpImpl::IncomingRtcpPacket
RTCPReceiver::IncomingRTCPPacket
RTCPReceiver::HandleSenderReceiverReport
RTCPReceiver::HandleReportBlock
通過 lastSR 到sender模塊中取出SR包的發(fā)送時間.
uint32_t sendTimeMS =
_rtpRtcp.SendTimeOfSendReport(rtcpPacket.ReportBlockItem.LastSR);

計算RTT .

uint32_t delaySinceLastSendReport =
rtcpPacket.ReportBlockItem.DelayLastSR;

// local NTP time when we received this
uint32_t lastReceivedRRNTPsecs = 0;
uint32_t lastReceivedRRNTPfrac = 0;

_clock->CurrentNtp(lastReceivedRRNTPsecs, lastReceivedRRNTPfrac);

// time when we received this in MS
uint32_t receiveTimeMS = Clock::NtpToMs(lastReceivedRRNTPsecs,
lastReceivedRRNTPfrac);

// Estimate RTT
uint32_t d = (delaySinceLastSendReport & 0x0000ffff) * 1000;
d /= 65536;
d += ((delaySinceLastSendReport & 0xffff0000) >> 16) * 1000;

int32_t RTT = 0;

if (sendTimeMS > 0) {
RTT = receiveTimeMS - d - sendTimeMS;
....
}

注意delay since last SR (DLSR) 的單位是1/65536秒.


二、另外一個問題, 那么如何在B端估算A和B之間的RTT時間?

如果是互相視頻聊天的話, A和B都是發(fā)送端, 自然都可以計算出RTT.
但是B如果僅僅是接收者的話, 僅僅依靠RFC3550協(xié)議是無法計算RTT時間的.
需要參考rfc 3611協(xié)議, 實現(xiàn)section4.5 的 DLRR Report Block 即可. http://tools.ietf.org/html/rfc3611#section-4.5

webrtc 在bug 1613 https://code.google.com/p/webrtc/issues/detail?id=1613
中討論該問題. 并在版本 https://code.google.com/p/webrtc/source/detail?r=4898
和https://code.google.com/p/webrtc/source/detail?r=5063 中修復(fù).

具體實現(xiàn)和SR非常類似.
1. 開啟XR協(xié)議 ModuleRtpRtcpImpl::SetRtcpXrRrtrStatus(true)

webrtc的示例loopback 程序中可以這樣啟動
receive_config.rtp.rtcp_xr.receiver_reference_time_report = true;

接受者(B)發(fā)送RTCP時, 附加kRtcpXrReceiverReferenceTime
發(fā)送者(A)發(fā)送RTCP時, 附加kRtcpXrDlrrReportBlock

RTCPSender::PrepareRTCP
if (xrSendReceiverReferenceTimeEnabled_ && !_sending)
{
rtcpPacketTypeFlags |= kRtcpXrReceiverReferenceTime;
}
if (feedback_state.has_last_xr_rr)
{
rtcpPacketTypeFlags |= kRtcpXrDlrrReportBlock;
}

B在發(fā)送kRtcpXrReceiverReferenceTime, 在last_xr_rr_ map中記錄 NTP時間戳中間32位(key) 和 發(fā)送時間(value).

A 收到XR_RR包后
在處理kRtcpXrReceiverReferenceTimeCode
RTCPReceiver::HandleXrReceiveReferenceTime

_remoteXRReceiveTimeInfo.lastRR = RTCPUtility::MidNtp(
packet.XRReceiverReferenceTimeItem.NTPMostSignificant,
packet.XRReceiverReferenceTimeItem.NTPLeastSignificant);
_clock->CurrentNtp(_lastReceivedXRNTPsecs, _lastReceivedXRNTPfrac);

記錄lastRR和收到XR_RR包的時間.

A 發(fā)送RTCP時, 會檢查是否收到過xr_rr包.
ModuleRtpRtcpImpl::GetFeedbackState()
state.has_last_xr_rr = LastReceivedXrReferenceTimeInfo(&state.last_xr_rr);

bool RTCPReceiver::LastReceivedXrReferenceTimeInfo(
RtcpReceiveTimeInfo* info) const {
assert(info);
CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
if (_lastReceivedXRNTPsecs == 0 && _lastReceivedXRNTPfrac == 0) {
return false;
}

info->sourceSSRC = _remoteXRReceiveTimeInfo.sourceSSRC;
info->lastRR = _remoteXRReceiveTimeInfo.lastRR;

// Get the delay since last received report (RFC 3611).
uint32_t receive_time = RTCPUtility::MidNtp(_lastReceivedXRNTPsecs,
_lastReceivedXRNTPfrac);

uint32_t ntp_sec = 0;
uint32_t ntp_frac = 0;
_clock->CurrentNtp(ntp_sec, ntp_frac);
uint32_t now = RTCPUtility::MidNtp(ntp_sec, ntp_frac);

info->delaySinceLastRR = now - receive_time;
return true;
}
計算出 從接到last_xr_rr 到當(dāng)前的延時.
然后發(fā)送 kRtcpXrDlrrReportBlock 出去.

B 收到XR_SR后
RTCPReceiver::HandleXrDlrrReportBlock
計算出RTT時間. 保存在xr_rr_rtt_ms_


rtp_rtcp_impl_unittest.cc 測試程序.
TEST_F(RtpRtcpImplTest, RttForReceiverOnly)

?

轉(zhuǎn)載于:https://www.cnblogs.com/lingdhox/p/5746210.html

總結(jié)

以上是生活随笔為你收集整理的[webrtc] rtcp模块中rtt时间计算的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 国产精品v | 国产精品久久久久久中文字 | 精品国产二区三区 | 免费h片网站 | 久久免费在线观看视频 | 久久国产精品免费看 | 噜噜噜亚洲色成人网站 | 久草福利资源在线 | 中文字幕在线三区 | av免费资源 | 精品人妻一区二区三区日产 | 日韩精品一区二区在线观看 | 国产欧美日韩精品一区二区三区 | 牛牛热在线视频 | 三级免费黄 | 一级片在线视频 | 99亚洲天堂 | 叶山小百合av一区二区 | 国产av无码国产av毛片 | 毛片毛片毛片毛片毛片毛片毛片毛片毛片毛片 | 91丨porny丨国产 | 国产情侣自拍一区 | 亚洲暴爽 | 久久久久三级 | 一二区精品 | 亚洲乱码一区二区三区 | 亚洲精品国产精品乱码在线观看 | 在线视频 日韩 | 日韩黄色片子 | 亚洲国产剧情 | 日本午夜大片 | 久久午夜精品人妻一区二区三区 | jizzz18| a毛片在线 | 丰满岳乱妇一区二区 | 日产精品一区二区 | 看个毛片 | 中文字幕2018 | 国产视频手机在线观看 | 在线观看视频免费 | 性生交大片免费看l | 人妻aⅴ无码一区二区三区 阿v免费视频 | 欧美大片a| 钰慧的mv视频在线观看 | 日韩欧美中文字幕精品 | 天天看夜夜看 | 午夜激情在线 | 97精品超碰一区二区三区 | 日本三级在线视频 | 黄色网址在线免费观看 | 艳妇臀荡乳欲伦交换在线看 | 91超薄肉色丝袜交足高跟凉鞋 | 91视频社区 | 精品深夜av无码一区二区老年 | 啪啪影音| 亚洲一级视频在线观看 | 四虎音影| 欧美高清一级 | 国产性久久 | 野花社区视频在线观看 | 日韩啊v | 精品一区二区视频 | 777久久久精品一区二区三区 | 麻豆专区 | eeuss鲁丝片一区二区三区 | 天天草天天射 | 日本九九热 | 亚洲免费一区二区 | 中文字幕25页 | 亚洲自拍色 | 成人性视频sm.| 日韩av中文 | 中文字幕2区 | 性v天堂| 日韩精品视频网 | 老司机深夜福利在线观看 | 日韩免费播放 | 看毛片的网址 | 亚洲精品九九 | 国产老妇伦国产熟女老妇视频 | 久久久久亚洲av片无码下载蜜桃 | 亚洲一本在线观看 | 精品黑人一区二区三区观看时间 | 久久精品牌麻豆国产大山 | 天堂精品| 精品无码一级毛片免费 | 午夜精品久久久久久久久久久久久蜜桃 | 麻豆成人精品国产免费 | 在线观看黄色网页 | 999精品在线 | 影音先锋成人资源站 | 欧美绿帽合集xxxxx | 波多野结衣在线一区 | 二区三区在线视频 | 中文字幕精品三区 | 日本黄色大片网站 | 日韩av在线免费看 | 国产精品无码专区av在线播放 | 国产人成精品 |