修复rtp seq重复导致rtp nack重传列队异常的bug

This commit is contained in:
xiongziliang 2022-02-27 02:07:25 +08:00
parent 7a5cf925b0
commit ba5ca8f5c7
3 changed files with 38 additions and 21 deletions

View File

@ -16,22 +16,22 @@ using namespace mediakit;
static constexpr uint32_t kMaxNackMS = 10 * 1000; static constexpr uint32_t kMaxNackMS = 10 * 1000;
void NackList::push_back(RtpPacket::Ptr rtp) { void NackList::pushBack(RtpPacket::Ptr rtp) {
auto seq = rtp->getSeq(); auto seq = rtp->getSeq();
_nack_cache_seq.emplace_back(seq); _nack_cache_seq.emplace_back(seq);
_nack_cache_pkt.emplace(seq, std::move(rtp)); _nack_cache_pkt.emplace(seq, std::move(rtp));
while (get_cache_ms() > kMaxNackMS) { while (getCacheMS() > kMaxNackMS) {
//需要清除部分nack缓存 //需要清除部分nack缓存
pop_front(); popFront();
} }
} }
void NackList::for_each_nack(const FCI_NACK &nack, const function<void(const RtpPacket::Ptr &rtp)> &func) { void NackList::forEach(const FCI_NACK &nack, const function<void(const RtpPacket::Ptr &rtp)> &func) {
auto seq = nack.getPid(); auto seq = nack.getPid();
for (auto bit : nack.getBitArray()) { for (auto bit : nack.getBitArray()) {
if (bit) { if (bit) {
//丢包 //丢包
RtpPacket::Ptr *ptr = get_rtp(seq); RtpPacket::Ptr *ptr = getRtp(seq);
if (ptr) { if (ptr) {
func(*ptr); func(*ptr);
} }
@ -40,7 +40,7 @@ void NackList::for_each_nack(const FCI_NACK &nack, const function<void(const Rtp
} }
} }
void NackList::pop_front() { void NackList::popFront() {
if (_nack_cache_seq.empty()) { if (_nack_cache_seq.empty()) {
return; return;
} }
@ -48,7 +48,7 @@ void NackList::pop_front() {
_nack_cache_seq.pop_front(); _nack_cache_seq.pop_front();
} }
RtpPacket::Ptr *NackList::get_rtp(uint16_t seq) { RtpPacket::Ptr *NackList::getRtp(uint16_t seq) {
auto it = _nack_cache_pkt.find(seq); auto it = _nack_cache_pkt.find(seq);
if (it == _nack_cache_pkt.end()) { if (it == _nack_cache_pkt.end()) {
return nullptr; return nullptr;
@ -56,19 +56,35 @@ RtpPacket::Ptr *NackList::get_rtp(uint16_t seq) {
return &it->second; return &it->second;
} }
uint32_t NackList::get_cache_ms() { uint32_t NackList::getCacheMS() {
if (_nack_cache_seq.size() < 2) { auto back_stamp = getRtpStamp(_nack_cache_seq.back());
if (back_stamp == -1) {
_nack_cache_seq.pop_back();
return 0; return 0;
} }
uint32_t back = _nack_cache_pkt[_nack_cache_seq.back()]->getStampMS(false);
uint32_t front = _nack_cache_pkt[_nack_cache_seq.front()]->getStampMS(false); auto front_stamp = getRtpStamp(_nack_cache_seq.front());
if (back >= front) { if (front_stamp == -1) {
return back - front; _nack_cache_seq.pop_front();
return 0;
}
if (back_stamp >= front_stamp) {
return back_stamp - front_stamp;
} }
//很有可能回环了 //很有可能回环了
return back + (UINT32_MAX - front); return back_stamp + (UINT32_MAX - front_stamp);
} }
int64_t NackList::getRtpStamp(uint16_t seq) {
auto it = _nack_cache_pkt.find(seq);
if (it == _nack_cache_pkt.end()) {
return -1;
}
return it->second->getStampMS(false);
}
//////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////
void NackContext::received(uint16_t seq, bool is_rtx) { void NackContext::received(uint16_t seq, bool is_rtx) {

View File

@ -20,13 +20,14 @@ public:
NackList() = default; NackList() = default;
~NackList() = default; ~NackList() = default;
void push_back(mediakit::RtpPacket::Ptr rtp); void pushBack(mediakit::RtpPacket::Ptr rtp);
void for_each_nack(const mediakit::FCI_NACK &nack, const std::function<void(const mediakit::RtpPacket::Ptr &rtp)> &cb); void forEach(const mediakit::FCI_NACK &nack, const std::function<void(const mediakit::RtpPacket::Ptr &rtp)> &cb);
private: private:
void pop_front(); void popFront();
uint32_t get_cache_ms(); uint32_t getCacheMS();
mediakit::RtpPacket::Ptr *get_rtp(uint16_t seq); int64_t getRtpStamp(uint16_t seq);
mediakit::RtpPacket::Ptr *getRtp(uint16_t seq);
private: private:
std::deque<uint16_t> _nack_cache_seq; std::deque<uint16_t> _nack_cache_seq;

View File

@ -652,7 +652,7 @@ void WebRtcTransportImp::onRtcp(const char *buf, size_t len) {
} }
auto &track = it->second; auto &track = it->second;
auto &fci = fb->getFci<FCI_NACK>(); auto &fci = fb->getFci<FCI_NACK>();
track->nack_list.for_each_nack(fci, [&](const RtpPacket::Ptr &rtp) { track->nack_list.forEach(fci, [&](const RtpPacket::Ptr &rtp) {
//rtp重传 //rtp重传
onSendRtp(rtp, true, true); onSendRtp(rtp, true, true);
}); });
@ -807,7 +807,7 @@ void WebRtcTransportImp::onSendRtp(const RtpPacket::Ptr &rtp, bool flush, bool r
if (!rtx) { if (!rtx) {
//统计rtp发送情况好做sr汇报 //统计rtp发送情况好做sr汇报
track->rtcp_context_send->onRtp(rtp->getSeq(), rtp->getStamp(), rtp->ntp_stamp, rtp->sample_rate, rtp->size() - RtpPacket::kRtpTcpHeaderSize); track->rtcp_context_send->onRtp(rtp->getSeq(), rtp->getStamp(), rtp->ntp_stamp, rtp->sample_rate, rtp->size() - RtpPacket::kRtpTcpHeaderSize);
track->nack_list.push_back(rtp); track->nack_list.pushBack(rtp);
#if 0 #if 0
//此处模拟发送丢包 //此处模拟发送丢包
if (rtp->type == TrackVideo && rtp->getSeq() % 100 == 0) { if (rtp->type == TrackVideo && rtp->getSeq() % 100 == 0) {