From 4c296488f113c6a5358b57cfd9e038d8117bd0d7 Mon Sep 17 00:00:00 2001 From: ziyue <1213642868@qq.com> Date: Tue, 6 Jul 2021 21:48:51 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8Drtcp=20rr/sr=E6=97=B6?= =?UTF-8?q?=E9=97=B4=E6=88=B3=E8=BD=AC=E6=8D=A2=E7=9B=B8=E5=85=B3=E9=97=AE?= =?UTF-8?q?=E9=A2=98,=E8=AE=A1=E7=AE=97rtt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Rtcp/Rtcp.cpp | 14 ++++++++ src/Rtcp/Rtcp.h | 2 ++ src/Rtcp/RtcpContext.cpp | 73 ++++++++++++++++++++++++-------------- src/Rtcp/RtcpContext.h | 4 ++- src/Rtp/RtpServer.cpp | 2 +- src/Rtsp/RtspPlayer.cpp | 2 +- src/Rtsp/RtspPusher.cpp | 2 +- src/Rtsp/RtspSession.cpp | 2 +- webrtc/WebRtcTransport.cpp | 4 +-- 9 files changed, 72 insertions(+), 33 deletions(-) diff --git a/src/Rtcp/Rtcp.cpp b/src/Rtcp/Rtcp.cpp index c7c5a277..b734052e 100644 --- a/src/Rtcp/Rtcp.cpp +++ b/src/Rtcp/Rtcp.cpp @@ -263,11 +263,25 @@ string RtcpSR::getNtpStamp() const{ return LogChannel::printTime(tv); } +uint64_t RtcpSR::getNtpUnixStampMS() const { + struct timeval tv; + tv.tv_sec = ntpmsw - 0x83AA7E80; + tv.tv_usec = (decltype(tv.tv_usec)) (ntplsw / ((double) (((uint64_t) 1) << 32) * 1.0e-6)); + return 1000 * tv.tv_sec + tv.tv_usec / 1000; +} + void RtcpSR::setNtpStamp(struct timeval tv) { ntpmsw = htonl(tv.tv_sec + 0x83AA7E80); /* 0x83AA7E80 is the number of seconds from 1900 to 1970 */ ntplsw = htonl((uint32_t) ((double) tv.tv_usec * (double) (((uint64_t) 1) << 32) * 1.0e-6)); } +void RtcpSR::setNtpStamp(uint64_t unix_stamp_ms) { + struct timeval tv; + tv.tv_sec = unix_stamp_ms / 1000; + tv.tv_usec = (unix_stamp_ms % 1000) * 1000; + setNtpStamp(tv); +} + string RtcpSR::dumpString() const{ _StrPrinter printer; printer << RtcpHeader::dumpHeader(); diff --git a/src/Rtcp/Rtcp.h b/src/Rtcp/Rtcp.h index efb591c1..8f74ecc4 100644 --- a/src/Rtcp/Rtcp.h +++ b/src/Rtcp/Rtcp.h @@ -347,12 +347,14 @@ public: * @param tv 时间 */ void setNtpStamp(struct timeval tv); + void setNtpStamp(uint64_t unix_stamp_ms); /** * 返回ntp时间的字符串 * 使用net2Host转换成主机字节序后才可使用此函数 */ string getNtpStamp() const; + uint64_t getNtpUnixStampMS() const; /** * 获取ReportItem对象指针列表 diff --git a/src/Rtcp/RtcpContext.cpp b/src/Rtcp/RtcpContext.cpp index 384b15b2..5ea20ebc 100644 --- a/src/Rtcp/RtcpContext.cpp +++ b/src/Rtcp/RtcpContext.cpp @@ -22,14 +22,14 @@ RtcpContext::RtcpContext(bool is_receiver) { _is_receiver = is_receiver; } -void RtcpContext::onRtp(uint16_t seq, uint32_t stamp, size_t bytes) { +void RtcpContext::onRtp(uint16_t seq, uint32_t stamp, uint32_t sample_rate, size_t bytes) { if (_is_receiver) { //接收者才做复杂的统计运算 auto sys_stamp = getCurrentMillisecond(); if (_last_rtp_sys_stamp) { //计算时间戳抖动值 - double diff = double( - int64_t(sys_stamp) - int64_t(_last_rtp_sys_stamp) - int64_t(stamp) + int64_t(_last_rtp_stamp)); + double diff = double((int64_t(sys_stamp) - int64_t(_last_rtp_sys_stamp)) * (sample_rate / double(1000.0)) + - (int64_t(stamp) - int64_t(_last_rtp_stamp))); if (diff < 0) { diff = -diff; } @@ -68,23 +68,49 @@ void RtcpContext::onRtp(uint16_t seq, uint32_t stamp, size_t bytes) { } void RtcpContext::onRtcp(RtcpHeader *rtcp) { - if ((RtcpType) rtcp->pt != RtcpType::RTCP_SR) { - return; + switch ((RtcpType) rtcp->pt) { + case RtcpType::RTCP_SR: { + auto rtcp_sr = (RtcpSR *) rtcp; + /** + last SR timestamp (LSR): 32 bits + The middle 32 bits out of 64 in the NTP timestamp (as explained in + Section 4) received as part of the most recent RTCP sender report + (SR) packet from source SSRC_n. If no SR has been received yet, + the field is set to zero. + */ + _last_sr_lsr = ((rtcp_sr->ntpmsw & 0xFFFF) << 16) | ((rtcp_sr->ntplsw >> 16) & 0xFFFF); + _last_sr_ntp_sys = getCurrentMillisecond(); + break; + } + case RtcpType::RTCP_RR: { + auto rtcp_rr = (RtcpRR *) rtcp; + for (auto item : rtcp_rr->getItemList()) { + if (!item->last_sr_stamp) { + continue; + } + //rtp接收端收到sr包后,回复rr包的延时,已转换为毫秒 + auto delay_ms = (uint64_t) item->delay_since_last_sr * 1000 / 65536; + //这个rr包对应sr包的ntpmsw和ntplsw + auto ntpmsw = item->last_sr_stamp >> 16; + auto ntplsw = (item->last_sr_stamp & 0xFFFF) << 16; + RtcpSR sr; + //获取当前时间戳 + sr.setNtpStamp(getCurrentMillisecond(true)); + + //当前时间戳与上次发送的sr包直接的ntp时间差 + int64_t ntpmsw_inc = (int64_t)(ntohl(sr.ntpmsw) & 0xFFFF) - (int64_t)ntpmsw; + int64_t ntplsw_inc = (int64_t)(ntohl(sr.ntplsw)) - (int64_t)ntplsw; + + //转换为毫秒 + auto ms_inc = ntpmsw_inc * 1000 + (ntplsw_inc / ((double) (((uint64_t) 1) << 32) * 1.0e-3)); + auto rtt = (int) ((ms_inc - delay_ms) / 2); + _rtt[item->ssrc] = rtt; + //InfoL << "ssrc:" << item->ssrc << ",rtt:" << rtt; + } + break; + } + default: break; } - if (!_is_receiver) { - WarnL << "rtp发送者收到sr包"; - return; - } - auto rtcp_sr = (RtcpSR *) (rtcp); - /** - last SR timestamp (LSR): 32 bits - The middle 32 bits out of 64 in the NTP timestamp (as explained in - Section 4) received as part of the most recent RTCP sender report - (SR) packet from source SSRC_n. If no SR has been received yet, - the field is set to zero. - */ - _last_sr_lsr = ((rtcp_sr->ntpmsw & 0xFFFF) << 16) | ((rtcp_sr->ntplsw >> 16) & 0xFFFF); - _last_sr_ntp_sys = getCurrentMillisecond(); } size_t RtcpContext::getExpectedPackets() const { @@ -120,14 +146,9 @@ Buffer::Ptr RtcpContext::createRtcpSR(uint32_t rtcp_ssrc) { throw std::runtime_error("rtp接收者尝试发送sr包"); } auto rtcp = RtcpSR::create(0); - rtcp->ssrc = htonl(rtcp_ssrc); - - struct timeval tv; - gettimeofday(&tv, NULL); - rtcp->setNtpStamp(tv); - - //转换成rtp时间戳 + rtcp->setNtpStamp(getCurrentMillisecond(true)); rtcp->rtpts = htonl(_last_rtp_stamp); + rtcp->ssrc = htonl(rtcp_ssrc); rtcp->packet_count = htonl((uint32_t) _packets); rtcp->octet_count = htonl((uint32_t) _bytes); return RtcpHeader::toBuffer(std::move(rtcp)); diff --git a/src/Rtcp/RtcpContext.h b/src/Rtcp/RtcpContext.h index d9f705ef..3caa95c2 100644 --- a/src/Rtcp/RtcpContext.h +++ b/src/Rtcp/RtcpContext.h @@ -30,9 +30,10 @@ public: * 输出或输入rtp时调用 * @param seq rtp的seq * @param stamp rtp的时间戳,单位采样数(非毫秒) + * @param rtp rtp时间戳采样率,视频一般为90000,音频一般为采样率 * @param bytes rtp数据长度 */ - void onRtp(uint16_t seq, uint32_t stamp, size_t bytes); + void onRtp(uint16_t seq, uint32_t stamp, uint32_t sample_rate, size_t bytes); /** * 输入sr rtcp包 @@ -112,6 +113,7 @@ private: uint32_t _last_sr_lsr = 0; //上次收到sr时的系统时间戳,单位毫秒 uint64_t _last_sr_ntp_sys = 0; + unordered_map _rtt; }; }//namespace mediakit diff --git a/src/Rtp/RtpServer.cpp b/src/Rtp/RtpServer.cpp index 6827138f..15aed1ce 100644 --- a/src/Rtp/RtpServer.cpp +++ b/src/Rtp/RtpServer.cpp @@ -35,7 +35,7 @@ public: void onRecvRtp(const Buffer::Ptr &buf, struct sockaddr *addr, int addr_len){ //统计rtp接受情况,用于发送rr包 auto header = (RtpHeader *) buf->data(); - onRtp(ntohs(header->seq), ntohl(header->stamp), buf->size()); + onRtp(ntohs(header->seq), ntohl(header->stamp), _sample_rate, buf->size()); sendRtcp(ntohl(header->ssrc), addr, addr_len); } diff --git a/src/Rtsp/RtspPlayer.cpp b/src/Rtsp/RtspPlayer.cpp index 45d0f445..68b966fa 100644 --- a/src/Rtsp/RtspPlayer.cpp +++ b/src/Rtsp/RtspPlayer.cpp @@ -591,7 +591,7 @@ void RtspPlayer::sendRtspRequest(const string &cmd, const string &url,const StrC void RtspPlayer::onBeforeRtpSorted(const RtpPacket::Ptr &rtp, int track_idx){ auto &rtcp_ctx = _rtcp_context[track_idx]; - rtcp_ctx->onRtp(rtp->getSeq(), ntohl(rtp->getHeader()->stamp), rtp->size() - RtpPacket::kRtpTcpHeaderSize); + rtcp_ctx->onRtp(rtp->getSeq(), ntohl(rtp->getHeader()->stamp), rtp->sample_rate, rtp->size() - RtpPacket::kRtpTcpHeaderSize); auto &ticker = _rtcp_send_ticker[track_idx]; if (ticker.elapsedTime() < 3 * 1000) { diff --git a/src/Rtsp/RtspPusher.cpp b/src/Rtsp/RtspPusher.cpp index 2d0a8abe..8b1f6846 100644 --- a/src/Rtsp/RtspPusher.cpp +++ b/src/Rtsp/RtspPusher.cpp @@ -360,7 +360,7 @@ void RtspPusher::updateRtcpContext(const RtpPacket::Ptr &rtp){ int track_index = getTrackIndexByTrackType(rtp->type); auto &ticker = _rtcp_send_ticker[track_index]; auto &rtcp_ctx = _rtcp_context[track_index]; - rtcp_ctx->onRtp(rtp->getSeq(), ntohl(rtp->getHeader()->stamp), rtp->size() - RtpPacket::kRtpTcpHeaderSize); + rtcp_ctx->onRtp(rtp->getSeq(), ntohl(rtp->getHeader()->stamp), rtp->sample_rate, rtp->size() - RtpPacket::kRtpTcpHeaderSize); //send rtcp every 5 second if (ticker.elapsedTime() > 5 * 1000) { diff --git a/src/Rtsp/RtspSession.cpp b/src/Rtsp/RtspSession.cpp index dae2987f..d43a3d2a 100644 --- a/src/Rtsp/RtspSession.cpp +++ b/src/Rtsp/RtspSession.cpp @@ -1126,7 +1126,7 @@ void RtspSession::onBeforeRtpSorted(const RtpPacket::Ptr &rtp, int track_index){ void RtspSession::updateRtcpContext(const RtpPacket::Ptr &rtp){ int track_index = getTrackIndexByTrackType(rtp->type); auto &rtcp_ctx = _rtcp_context[track_index]; - rtcp_ctx->onRtp(rtp->getSeq(), ntohl(rtp->getHeader()->stamp), rtp->size() - RtpPacket::kRtpTcpHeaderSize); + rtcp_ctx->onRtp(rtp->getSeq(), ntohl(rtp->getHeader()->stamp), rtp->sample_rate, rtp->size() - RtpPacket::kRtpTcpHeaderSize); auto &ticker = _rtcp_send_tickers[track_index]; //send rtcp every 5 second diff --git a/webrtc/WebRtcTransport.cpp b/webrtc/WebRtcTransport.cpp index 2eb7cb1f..ec7cc0e8 100644 --- a/webrtc/WebRtcTransport.cpp +++ b/webrtc/WebRtcTransport.cpp @@ -586,7 +586,7 @@ public: //统计rtp接受情况,便于生成nack rtcp包 _nack_ctx.received(seq); //统计rtp收到的情况,好做rr汇报 - _rtcp_context.onRtp(seq, ntohl(rtp->stamp), len); + _rtcp_context.onRtp(seq, ntohl(rtp->stamp), sample_rate, len); } return RtpTrack::inputRtp(type, sample_rate, ptr, len); } @@ -825,7 +825,7 @@ void WebRtcTransportImp::onSendRtp(const RtpPacket::Ptr &rtp, bool flush, bool r } if (!rtx) { //统计rtp发送情况,好做sr汇报 - track->rtcp_context_send->onRtp(rtp->getSeq(), ntohl(rtp->getHeader()->stamp), rtp->size() - RtpPacket::kRtpTcpHeaderSize); + track->rtcp_context_send->onRtp(rtp->getSeq(), ntohl(rtp->getHeader()->stamp), rtp->sample_rate, rtp->size() - RtpPacket::kRtpTcpHeaderSize); track->nack_list.push_back(rtp); #if 0 //此处模拟发送丢包