diff --git a/src/Rtcp/RtcpContext.cpp b/src/Rtcp/RtcpContext.cpp index 681c9d17..f7795405 100644 --- a/src/Rtcp/RtcpContext.cpp +++ b/src/Rtcp/RtcpContext.cpp @@ -14,14 +14,97 @@ using namespace toolkit; namespace mediakit { - -void RtcpContext::onRtp(uint16_t seq, uint32_t stamp, uint64_t ntp_stamp_ms, uint32_t sample_rate, size_t bytes) { +void RtcpContext::onRtp(uint16_t /*seq*/, uint32_t stamp, uint64_t ntp_stamp_ms, uint32_t /*sample_rate*/, size_t bytes) { ++_packets; _bytes += bytes; _last_rtp_stamp = stamp; _last_ntp_stamp_ms = ntp_stamp_ms; } +size_t RtcpContext::getExpectedPackets() const { + throw std::runtime_error("没有实现, rtp发送者无法统计应收包数"); +} + +size_t RtcpContext::getExpectedPacketsInterval() { + throw std::runtime_error("没有实现, rtp发送者无法统计应收包数"); +} + +size_t RtcpContext::getLost() { + throw std::runtime_error("没有实现, rtp发送者无法统计丢包率"); +} + +size_t RtcpContext::geLostInterval() { + throw std::runtime_error("没有实现, rtp发送者无法统计丢包率"); +} + +Buffer::Ptr RtcpContext::createRtcpSR(uint32_t rtcp_ssrc) { + throw std::runtime_error("没有实现, rtp接收者尝试发送sr包"); +} + +Buffer::Ptr RtcpContext::createRtcpRR(uint32_t rtcp_ssrc, uint32_t rtp_ssrc) { + throw std::runtime_error("没有实现, rtp发送者尝试发送rr包"); +} + +//////////////////////////////////////////////////////////////////////////////////// + +void RtcpContextForSend::onRtcp(RtcpHeader *rtcp) { + switch ((RtcpType) rtcp->pt) { + case RtcpType::RTCP_RR: { + auto rtcp_rr = (RtcpRR *) rtcp; + for (auto item : rtcp_rr->getItemList()) { + if (!item->last_sr_stamp) { + continue; + } + auto it = _sender_report_ntp.find(item->last_sr_stamp); + if (it == _sender_report_ntp.end()) { + continue; + } + //发送sr到收到rr之间的时间戳增量 + auto ms_inc = getCurrentMillisecond() - it->second; + //rtp接收端收到sr包后,回复rr包的延时,已转换为毫秒 + auto delay_ms = (uint64_t) item->delay_since_last_sr * 1000 / 65536; + auto rtt = (int) (ms_inc - delay_ms); + if (rtt >= 0) { + //rtt不可能小于0 + _rtt[item->ssrc] = rtt; + //InfoL << "ssrc:" << item->ssrc << ",rtt:" << rtt; + } + } + break; + } + default: break; + } +} + +uint32_t RtcpContextForSend::getRtt(uint32_t ssrc) const { + auto it = _rtt.find(ssrc); + if (it == _rtt.end()) { + return 0; + } + return it->second; +} + +Buffer::Ptr RtcpContextForSend::createRtcpSR(uint32_t rtcp_ssrc) { + auto rtcp = RtcpSR::create(0); + rtcp->setNtpStamp(_last_ntp_stamp_ms); + 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); + + //记录上次发送的sender report信息,用于后续统计rtt + auto last_sr_lsr = ((ntohl(rtcp->ntpmsw) & 0xFFFF) << 16) | ((ntohl(rtcp->ntplsw) >> 16) & 0xFFFF); + _sender_report_ntp[last_sr_lsr] = getCurrentMillisecond(); + if (_sender_report_ntp.size() >= 5) { + //删除最早的sr rtcp + _sender_report_ntp.erase(_sender_report_ntp.begin()); + } + + return RtcpHeader::toBuffer(std::move(rtcp)); +} + +//////////////////////////////////////////////////////////////////////////////////// + void RtcpContextForRecv::onRtp(uint16_t seq, uint32_t stamp, uint64_t ntp_stamp_ms, uint32_t sample_rate, size_t bytes) { { //接收者才做复杂的统计运算 @@ -64,7 +147,7 @@ void RtcpContextForRecv::onRtp(uint16_t seq, uint32_t stamp, uint64_t ntp_stamp_ RtcpContext::onRtp(seq, stamp, ntp_stamp_ms, sample_rate, bytes); } -void RtcpContext::onRtcp(RtcpHeader *rtcp) { +void RtcpContextForRecv::onRtcp(RtcpHeader *rtcp) { switch ((RtcpType) rtcp->pt) { case RtcpType::RTCP_SR: { auto rtcp_sr = (RtcpSR *) rtcp; @@ -79,50 +162,14 @@ void RtcpContext::onRtcp(RtcpHeader *rtcp) { _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; - } - auto it = _sender_report_ntp.find(item->last_sr_stamp); - if (it == _sender_report_ntp.end()) { - continue; - } - //发送sr到收到rr之间的时间戳增量 - auto ms_inc = getCurrentMillisecond() - it->second; - //rtp接收端收到sr包后,回复rr包的延时,已转换为毫秒 - auto delay_ms = (uint64_t) item->delay_since_last_sr * 1000 / 65536; - auto rtt = (int) (ms_inc - delay_ms); - if (rtt >= 0) { - //rtt不可能小于0 - _rtt[item->ssrc] = rtt; - //InfoL << "ssrc:" << item->ssrc << ",rtt:" << rtt; - } - } - break; - } default: break; } } -uint32_t RtcpContext::getRtt(uint32_t ssrc) const { - auto it = _rtt.find(ssrc); - if (it == _rtt.end()) { - return 0; - } - return it->second; -} - -size_t RtcpContext::getExpectedPackets() const { - throw std::runtime_error("没有实现, rtp发送者无法统计应收包数"); -} size_t RtcpContextForRecv::getExpectedPackets() const { return (_seq_cycles << 16) + _seq_max - _seq_base + 1; } -size_t RtcpContext::getExpectedPacketsInterval() { - throw std::runtime_error("没有实现, rtp发送者无法统计应收包数"); -} + size_t RtcpContextForRecv::getExpectedPacketsInterval() { auto expected = getExpectedPackets(); auto ret = expected - _last_expected; @@ -130,17 +177,10 @@ size_t RtcpContextForRecv::getExpectedPacketsInterval() { return ret; } -size_t RtcpContext::getLost() { - throw std::runtime_error("没有实现, rtp发送者无法统计丢包率"); -} - size_t RtcpContextForRecv::getLost() { return getExpectedPackets() - _packets; } -size_t RtcpContext::geLostInterval() { - throw std::runtime_error("没有实现, rtp发送者无法统计丢包率"); -} size_t RtcpContextForRecv::geLostInterval() { auto lost = getLost(); auto ret = lost - _last_lost; @@ -148,34 +188,6 @@ size_t RtcpContextForRecv::geLostInterval() { return ret; } -Buffer::Ptr RtcpContext::createRtcpSR(uint32_t rtcp_ssrc) { - throw std::runtime_error("没有实现, rtp接收者尝试发送sr包"); -} - -Buffer::Ptr RtcpContextForSend::createRtcpSR(uint32_t rtcp_ssrc) { - auto rtcp = RtcpSR::create(0); - rtcp->setNtpStamp(_last_ntp_stamp_ms); - 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); - - //记录上次发送的sender report信息,用于后续统计rtt - auto last_sr_lsr = ((ntohl(rtcp->ntpmsw) & 0xFFFF) << 16) | ((ntohl(rtcp->ntplsw) >> 16) & 0xFFFF); - _sender_report_ntp[last_sr_lsr] = getCurrentMillisecond(); - if (_sender_report_ntp.size() >= 5) { - //删除最早的sr rtcp - _sender_report_ntp.erase(_sender_report_ntp.begin()); - } - - return RtcpHeader::toBuffer(std::move(rtcp)); -} - -Buffer::Ptr RtcpContext::createRtcpRR(uint32_t rtcp_ssrc, uint32_t rtp_ssrc) { - throw std::runtime_error("没有实现, rtp发送者尝试发送rr包"); -} - - Buffer::Ptr RtcpContextForRecv::createRtcpRR(uint32_t rtcp_ssrc, uint32_t rtp_ssrc) { auto rtcp = RtcpRR::create(1); rtcp->ssrc = htonl(rtcp_ssrc); diff --git a/src/Rtcp/RtcpContext.h b/src/Rtcp/RtcpContext.h index c476219f..6604d5ff 100644 --- a/src/Rtcp/RtcpContext.h +++ b/src/Rtcp/RtcpContext.h @@ -36,7 +36,7 @@ public: * 输入sr rtcp包 * @param rtcp 输入一个rtcp */ - void onRtcp(RtcpHeader *rtcp); + virtual void onRtcp(RtcpHeader *rtcp) = 0; /** * 计算总丢包数 @@ -63,13 +63,6 @@ public: */ virtual Buffer::Ptr createRtcpRR(uint32_t rtcp_ssrc, uint32_t rtp_ssrc); - /** - * 获取rtt - * @param ssrc rtp ssrc - * @return rtt,单位毫秒 - */ - uint32_t getRtt(uint32_t ssrc) const; - /** * 上次结果与本次结果间应收包数 */ @@ -88,24 +81,36 @@ protected: //上次的rtp时间戳,毫秒 uint32_t _last_rtp_stamp = 0; uint64_t _last_ntp_stamp_ms = 0; - //上次统计的丢包总数 - size_t _last_lost = 0; - //上次统计应收rtp包总数 - size_t _last_expected = 0; - //上次收到sr包时计算出的Last SR timestamp - uint32_t _last_sr_lsr = 0; - //上次收到sr时的系统时间戳,单位毫秒 - uint64_t _last_sr_ntp_sys = 0; - map _rtt; - map _sender_report_ntp; }; class RtcpContextForSend : public RtcpContext { public: Buffer::Ptr createRtcpSR(uint32_t rtcp_ssrc) override; + void onRtcp(RtcpHeader *rtcp) override; + + /** + * 获取rtt + * @param ssrc rtp ssrc + * @return rtt,单位毫秒 + */ + uint32_t getRtt(uint32_t ssrc) const; + +private: + map _rtt; + map _sender_report_ntp; }; class RtcpContextForRecv : public RtcpContext { +public: + void onRtp(uint16_t seq, uint32_t stamp, uint64_t ntp_stamp_ms, uint32_t sample_rate, size_t bytes) override; + Buffer::Ptr createRtcpRR(uint32_t rtcp_ssrc, uint32_t rtp_ssrc) override; + size_t getExpectedPackets() const override; + size_t getExpectedPacketsInterval() override; + size_t getLost() override; + size_t geLostInterval() override; + void onRtcp(RtcpHeader *rtcp) override; + +private: //时间戳抖动值 double _jitter = 0; //第一个seq的值 @@ -120,13 +125,15 @@ class RtcpContextForRecv : public RtcpContext { uint16_t _last_rtp_seq = 0; //上次的rtp的系统时间戳(毫秒)用于统计抖动 uint64_t _last_rtp_sys_stamp = 0; -public: - void onRtp(uint16_t seq, uint32_t stamp, uint64_t ntp_stamp_ms, uint32_t sample_rate, size_t bytes) override; - Buffer::Ptr createRtcpRR(uint32_t rtcp_ssrc, uint32_t rtp_ssrc) override; - size_t getExpectedPackets() const override; - size_t getExpectedPacketsInterval() override; - size_t getLost() override; - size_t geLostInterval() override; + //上次统计的丢包总数 + size_t _last_lost = 0; + //上次统计应收rtp包总数 + size_t _last_expected = 0; + //上次收到sr包时计算出的Last SR timestamp + uint32_t _last_sr_lsr = 0; + //上次收到sr时的系统时间戳,单位毫秒 + uint64_t _last_sr_ntp_sys = 0; }; + }//namespace mediakit #endif //ZLMEDIAKIT_RTCPCONTEXT_H