From 51435d955c5ef3078e7307770e5b48a1b7201c23 Mon Sep 17 00:00:00 2001 From: xiongziliang <771730766@qq.com> Date: Sun, 31 Jan 2021 19:55:47 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96rtp=E7=BB=9F=E8=AE=A1?= =?UTF-8?q?=E6=80=A7=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Rtcp/RtcpContext.cpp | 118 +++++++++++++++++++++++---------------- src/Rtcp/RtcpContext.h | 5 +- src/Rtsp/RtspPlayer.cpp | 2 +- src/Rtsp/RtspPusher.cpp | 2 +- src/Rtsp/RtspSession.cpp | 5 +- 5 files changed, 79 insertions(+), 53 deletions(-) diff --git a/src/Rtcp/RtcpContext.cpp b/src/Rtcp/RtcpContext.cpp index 39ccd06d..e4915c09 100644 --- a/src/Rtcp/RtcpContext.cpp +++ b/src/Rtcp/RtcpContext.cpp @@ -9,65 +9,75 @@ */ #include "RtcpContext.h" +#include "Util/logger.h" using namespace toolkit; namespace mediakit { -void RtcpContext::clear(){ +void RtcpContext::clear() { memset(this, 0, sizeof(RtcpContext)); } -RtcpContext::RtcpContext(uint32_t sample_rate){ +RtcpContext::RtcpContext(uint32_t sample_rate, bool is_receiver) { _sample_rate = sample_rate; + _is_receiver = is_receiver; } void RtcpContext::onRtp(uint16_t seq, uint32_t stamp, size_t bytes) { - _bytes += bytes; - ++_packets; - - 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)); - if (diff < 0) { - diff = -diff; + 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)); + if (diff < 0) { + diff = -diff; + } + //抖动单位为采样次数 + diff *= (_sample_rate / 1000.0); + _jitter += (diff - _jitter) / 16.0; + } else { + _jitter = 0; } - //抖动单位为采样次数 - diff *= (_sample_rate / 1000.0); - _jitter += (diff - _jitter) / 16.0; - } else { - _jitter = 0; - } - - if (_last_rtp_seq > 0xFF00 && seq < 0xFF && (!_seq_cycles || _packets - _last_cycle_packets > 0x1FFF)) { - //上次seq大于0xFF00且本次seq小于0xFF, - //且未发生回环或者距离上次回环间隔超过0x1FFF个包,则认为回环 - ++_seq_cycles; - _last_cycle_packets = _packets; - _seq_max = seq; - } else if (seq > _seq_max) { - //本次回环前最大seq - _seq_max = seq; - } - - if (!_seq_base) { - //记录第一个rtp的seq - _seq_base = seq; - } else if (!_seq_cycles && seq < _seq_base) { - //未发生回环,那么取最新的seq为基准seq - _seq_base = seq; + + if (_last_rtp_seq > 0xFF00 && seq < 0xFF && (!_seq_cycles || _packets - _last_cycle_packets > 0x1FFF)) { + //上次seq大于0xFF00且本次seq小于0xFF, + //且未发生回环或者距离上次回环间隔超过0x1FFF个包,则认为回环 + ++_seq_cycles; + _last_cycle_packets = _packets; + _seq_max = seq; + } else if (seq > _seq_max) { + //本次回环前最大seq + _seq_max = seq; + } + + if (!_seq_base) { + //记录第一个rtp的seq + _seq_base = seq; + } else if (!_seq_cycles && seq < _seq_base) { + //未发生回环,那么取最新的seq为基准seq + _seq_base = seq; + } + + _last_rtp_seq = seq; + _last_rtp_sys_stamp = sys_stamp; } + ++_packets; + _bytes += bytes; _last_rtp_stamp = stamp; - _last_rtp_sys_stamp = sys_stamp; - _last_rtp_seq = seq; } -void RtcpContext::onRtcp(RtcpHeader *rtcp){ +void RtcpContext::onRtcp(RtcpHeader *rtcp) { if ((RtcpType) rtcp->pt != RtcpType::RTCP_SR) { return; } - auto rtcp_sr = (RtcpSR *)(rtcp); + 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 @@ -79,29 +89,38 @@ void RtcpContext::onRtcp(RtcpHeader *rtcp){ _last_sr_ntp_sys = getCurrentMillisecond(); } -size_t RtcpContext::getExpectedPackets() const{ +size_t RtcpContext::getExpectedPackets() const { + if (!_is_receiver) { + throw std::runtime_error("rtp发送者无法统计应收包数"); + } return (_seq_cycles << 16) + _seq_max - _seq_base + 1; } -size_t RtcpContext::getExpectedPacketsInterval(){ +size_t RtcpContext::getExpectedPacketsInterval() { auto expected = getExpectedPackets(); auto ret = expected - _last_expected; _last_expected = expected; return ret; } -size_t RtcpContext::getLost(){ +size_t RtcpContext::getLost() { + if (!_is_receiver) { + throw std::runtime_error("rtp发送者无法统计丢包率"); + } return getExpectedPackets() - _packets; } -size_t RtcpContext::geLostInterval(){ +size_t RtcpContext::geLostInterval() { auto lost = getLost(); auto ret = lost - _last_lost; _last_lost = lost; return ret; } -Buffer::Ptr RtcpContext::createRtcpSR(uint32_t rtcp_ssrc){ +Buffer::Ptr RtcpContext::createRtcpSR(uint32_t rtcp_ssrc) { + if (_is_receiver) { + throw std::runtime_error("rtp接收者尝试发送sr包"); + } auto rtcp = RtcpSR::create(0); rtcp->ssrc = htonl(rtcp_ssrc); @@ -111,12 +130,15 @@ Buffer::Ptr RtcpContext::createRtcpSR(uint32_t rtcp_ssrc){ //转换成rtp时间戳 rtcp->rtpts = htonl(uint32_t(_last_rtp_stamp * (_sample_rate / 1000.0))); - rtcp->packet_count = htonl((uint32_t)_packets); - rtcp->octet_count = htonl((uint32_t)_bytes); + rtcp->packet_count = htonl((uint32_t) _packets); + rtcp->octet_count = htonl((uint32_t) _bytes); return RtcpHeader::toBuffer(std::move(rtcp)); } -Buffer::Ptr RtcpContext::createRtcpRR(uint32_t rtcp_ssrc, uint32_t rtp_ssrc){ +Buffer::Ptr RtcpContext::createRtcpRR(uint32_t rtcp_ssrc, uint32_t rtp_ssrc) { + if (!_is_receiver) { + throw std::runtime_error("rtp发送者尝试发送rr包"); + } auto rtcp = RtcpRR::create(1); rtcp->ssrc = htonl(rtcp_ssrc); @@ -139,7 +161,7 @@ Buffer::Ptr RtcpContext::createRtcpRR(uint32_t rtcp_ssrc, uint32_t rtp_ssrc){ // now - Last SR time,单位毫秒 auto delay = getCurrentMillisecond() - _last_sr_ntp_sys; // in units of 1/65536 seconds - auto dlsr = (uint32_t)(delay / 1000.0f * 65536); + auto dlsr = (uint32_t) (delay / 1000.0f * 65536); item->delay_since_last_sr = htonl(_last_sr_lsr ? dlsr : 0); return RtcpHeader::toBuffer(rtcp); } diff --git a/src/Rtcp/RtcpContext.h b/src/Rtcp/RtcpContext.h index 06bac452..cfc00a05 100644 --- a/src/Rtcp/RtcpContext.h +++ b/src/Rtcp/RtcpContext.h @@ -23,8 +23,9 @@ public: /** * 创建rtcp上下文 * @param sample_rate 音频采用率,视频一般为90000 + * @param is_receiver 是否为rtp接收者,接收者更消耗性能 */ - RtcpContext(uint32_t sample_rate); + RtcpContext(uint32_t sample_rate, bool is_receiver); /** * 输出或输入rtp时调用 @@ -82,6 +83,8 @@ private: size_t geLostInterval(); private: + //是否为接收者 + bool _is_receiver; //时间戳抖动值 double _jitter = 0; //视频默认90000,音频为采样率 diff --git a/src/Rtsp/RtspPlayer.cpp b/src/Rtsp/RtspPlayer.cpp index b0cc841a..df930a52 100644 --- a/src/Rtsp/RtspPlayer.cpp +++ b/src/Rtsp/RtspPlayer.cpp @@ -204,7 +204,7 @@ void RtspPlayer::handleResDESCRIBE(const Parser& parser) { throw std::runtime_error("onCheckSDP faied"); } for (auto &track : _sdp_track) { - _rtcp_context.emplace_back(std::make_shared(track->_samplerate)); + _rtcp_context.emplace_back(std::make_shared(track->_samplerate, true)); } sendSetup(0); } diff --git a/src/Rtsp/RtspPusher.cpp b/src/Rtsp/RtspPusher.cpp index 81bd705d..4accfcca 100644 --- a/src/Rtsp/RtspPusher.cpp +++ b/src/Rtsp/RtspPusher.cpp @@ -177,7 +177,7 @@ void RtspPusher::sendAnnounce() { throw std::runtime_error("无有效的Sdp Track"); } for (auto &track : _track_vec) { - _rtcp_context.emplace_back(std::make_shared(track->_samplerate)); + _rtcp_context.emplace_back(std::make_shared(track->_samplerate, false)); } _on_res_func = std::bind(&RtspPusher::handleResAnnounce, this, placeholders::_1); sendRtspRequest("ANNOUNCE", _url, {}, src->getSdp()); diff --git a/src/Rtsp/RtspSession.cpp b/src/Rtsp/RtspSession.cpp index b5e1d838..264e7d1d 100644 --- a/src/Rtsp/RtspSession.cpp +++ b/src/Rtsp/RtspSession.cpp @@ -235,8 +235,9 @@ void RtspSession::handleReq_ANNOUNCE(const Parser &parser) { sendRtspResponse("403 Forbidden", {"Content-Type", "text/plain"}, err); throw SockException(Err_shutdown,StrPrinter << err << ":" << full_url); } + _rtcp_context.clear(); for (auto &track : _sdp_track) { - _rtcp_context.emplace_back(std::make_shared(track->_samplerate)); + _rtcp_context.emplace_back(std::make_shared(track->_samplerate, true)); } _push_src = std::make_shared(_media_info._vhost, _media_info._app, _media_info._streamid); _push_src->setListener(dynamic_pointer_cast(shared_from_this())); @@ -406,7 +407,7 @@ void RtspSession::onAuthSuccess() { return; } for (auto &track : strongSelf->_sdp_track) { - strongSelf->_rtcp_context.emplace_back(std::make_shared(track->_samplerate)); + strongSelf->_rtcp_context.emplace_back(std::make_shared(track->_samplerate, false)); } strongSelf->_sessionid = makeRandStr(12); strongSelf->_play_src = rtsp_src;