diff --git a/webrtc/TwccContext.cpp b/webrtc/TwccContext.cpp index c479387e..fe3e6541 100644 --- a/webrtc/TwccContext.cpp +++ b/webrtc/TwccContext.cpp @@ -19,10 +19,10 @@ enum class ExtSeqStatus : int { jumped, }; -void TwccContext::onRtp(uint16_t twcc_ext_seq) { +void TwccContext::onRtp(uint32_t ssrc, uint16_t twcc_ext_seq) { switch ((ExtSeqStatus) checkSeqStatus(twcc_ext_seq)) { case ExtSeqStatus::jumped: /*回环后,收到回环前的大ext seq包,过滤掉*/ return; - case ExtSeqStatus::looped: /*回环,触发发送twcc rtcp*/ onSendTwcc(); break; + case ExtSeqStatus::looped: /*回环,触发发送twcc rtcp*/ onSendTwcc(ssrc); break; case ExtSeqStatus::normal: break; default: /*不可达*/assert(0); break; } @@ -40,7 +40,7 @@ void TwccContext::onRtp(uint16_t twcc_ext_seq) { if (checkIfNeedSendTwcc()) { //其他匹配条件立即发送twcc - onSendTwcc(); + onSendTwcc(ssrc); } } @@ -76,11 +76,12 @@ int TwccContext::checkSeqStatus(uint16_t twcc_ext_seq) const { return (int) ExtSeqStatus::normal; } -void TwccContext::onSendTwcc() { +void TwccContext::onSendTwcc(uint32_t ssrc) { auto max = _rtp_recv_status.rbegin()->first; auto begin = _rtp_recv_status.begin(); auto min = begin->first; - auto ref_time = begin->second; + auto ref_time = begin->second >> 6; + auto last_time = ref_time << 6; FCI_TWCC::TwccPacketStatus status; for (auto seq = min; seq <= max; ++seq) { int16_t delta = 0; @@ -88,20 +89,20 @@ void TwccContext::onSendTwcc() { auto it = _rtp_recv_status.find(seq); if (it != _rtp_recv_status.end()) { //recv delta,单位为250us,1ms等于4x250us - delta = (int16_t) (4 * ((int64_t) it->second - (int64_t) ref_time)); + delta = (int16_t) (4 * ((int64_t) it->second - (int64_t) last_time)); if (delta < 0 || delta > 0xFF) { symbol = SymbolStatus::large_delta; } else { symbol = SymbolStatus::small_delta; } - ref_time = it->second; + last_time = it->second; } status.emplace(seq, std::make_pair(symbol, delta)); } - auto fci = FCI_TWCC::create(ref_time / 64, _twcc_pkt_count, status); - InfoL << ((FCI_TWCC *) (fci.data()))->dumpString(fci.size()); - - ++_twcc_pkt_count; + auto fci = FCI_TWCC::create(ref_time, _twcc_pkt_count++, status); + if (_cb) { + _cb(ssrc, std::move(fci)); + } clearStatus(); } @@ -109,3 +110,7 @@ void TwccContext::clearStatus() { _rtp_recv_status.clear(); _min_stamp = 0; } + +void TwccContext::setOnSendTwccCB(TwccContext::onSendTwccCB cb) { + _cb = std::move(cb); +} diff --git a/webrtc/TwccContext.h b/webrtc/TwccContext.h index 0c73c36e..d005e3ce 100644 --- a/webrtc/TwccContext.h +++ b/webrtc/TwccContext.h @@ -18,18 +18,20 @@ using namespace toolkit; class TwccContext { public: + using onSendTwccCB = function; //每个twcc rtcp包最多表明的rtp ext seq增量 static constexpr size_t kMaxSeqDelta = 20; //每个twcc rtcp包发送的最大时间间隔,单位毫秒 - static constexpr size_t kMaxTimeDelta = 64; + static constexpr size_t kMaxTimeDelta = 256; TwccContext() = default; ~TwccContext() = default; - void onRtp(uint16_t twcc_ext_seq); + void onRtp(uint32_t ssrc, uint16_t twcc_ext_seq); + void setOnSendTwccCB(onSendTwccCB cb); private: - void onSendTwcc(); + void onSendTwcc(uint32_t ssrc); bool checkIfNeedSendTwcc() const; int checkSeqStatus(uint16_t twcc_ext_seq) const; void clearStatus(); @@ -40,6 +42,7 @@ private: uint64_t _max_stamp; std::map _rtp_recv_status; uint8_t _twcc_pkt_count = 0; + onSendTwccCB _cb; }; diff --git a/webrtc/WebRtcTransport.cpp b/webrtc/WebRtcTransport.cpp index a4fa3e40..cdd69d44 100644 --- a/webrtc/WebRtcTransport.cpp +++ b/webrtc/WebRtcTransport.cpp @@ -332,6 +332,10 @@ void WebRtcTransportImp::onCreate(){ } return true; }, getPoller()); + + _twcc_ctx.setOnSendTwccCB([this](uint32_t ssrc, string fci) { + onSendTwcc(ssrc, fci); + }); } WebRtcTransportImp::WebRtcTransportImp(const EventPoller::Ptr &poller) : WebRtcTransport(poller) { @@ -810,7 +814,7 @@ void WebRtcTransportImp::onRtp(const char *buf, size_t len) { string rid; auto twcc_ext = track->rtp_ext_ctx->changeRtpExtId(rtp, true, &rid, RtpExtType::transport_cc); if (twcc_ext && !is_rtx) { - _twcc_ctx.onRtp(twcc_ext.getTransportCCSeq()); + _twcc_ctx.onRtp(ssrc, twcc_ext.getTransportCCSeq()); } auto &ref = track->rtp_channel[rid]; @@ -865,6 +869,13 @@ void WebRtcTransportImp::onSendNack(MediaTrack &track, const FCI_NACK &nack, uin sendRtcpPacket((char *) rtcp.get(), rtcp->getSize(), true); } +void WebRtcTransportImp::onSendTwcc(uint32_t ssrc, const string &twcc_fci) { + auto rtcp = RtcpFB::create(RTPFBType::RTCP_RTPFB_TWCC, twcc_fci.data(), twcc_fci.size()); + rtcp->ssrc = htons(0); + rtcp->ssrc_media = htonl(ssrc); + sendRtcpPacket((char *) rtcp.get(), rtcp->getSize(), true); +} + /////////////////////////////////////////////////////////////////// void WebRtcTransportImp::onSortedRtp(MediaTrack &track, const string &rid, RtpPacket::Ptr rtp) { diff --git a/webrtc/WebRtcTransport.h b/webrtc/WebRtcTransport.h index ba76b7b9..fbdbc6f1 100644 --- a/webrtc/WebRtcTransport.h +++ b/webrtc/WebRtcTransport.h @@ -217,6 +217,7 @@ private: void onSortedRtp(MediaTrack &track, const string &rid, RtpPacket::Ptr rtp); void onSendNack(MediaTrack &track, const FCI_NACK &nack, uint32_t ssrc); + void onSendTwcc(uint32_t ssrc, const string &twcc_fci); void createRtpChannel(const string &rid, uint32_t ssrc, MediaTrack &track); void registerSelf(); void unregisterSelf();