2021-10-11 17:16:26 +08:00
|
|
|
|
/*
|
2021-10-06 22:17:38 +08:00
|
|
|
|
* Copyright (c) 2021 The ZLMediaKit project authors. All Rights Reserved.
|
|
|
|
|
*
|
|
|
|
|
* This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit).
|
|
|
|
|
*
|
|
|
|
|
* Use of this source code is governed by MIT license that can be found in the
|
|
|
|
|
* LICENSE file in the root of the source tree. All contributing project authors
|
|
|
|
|
* may be found in the AUTHORS file in the root of the source tree.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include "TwccContext.h"
|
2021-10-07 12:28:59 +08:00
|
|
|
|
#include "Rtcp/RtcpFCI.h"
|
|
|
|
|
|
2022-09-18 21:03:05 +08:00
|
|
|
|
namespace mediakit {
|
2021-10-06 22:17:38 +08:00
|
|
|
|
|
|
|
|
|
enum class ExtSeqStatus : int {
|
|
|
|
|
normal = 0,
|
|
|
|
|
looped,
|
|
|
|
|
jumped,
|
|
|
|
|
};
|
|
|
|
|
|
2021-10-07 15:49:33 +08:00
|
|
|
|
void TwccContext::onRtp(uint32_t ssrc, uint16_t twcc_ext_seq, uint64_t stamp_ms) {
|
2021-10-06 22:17:38 +08:00
|
|
|
|
switch ((ExtSeqStatus) checkSeqStatus(twcc_ext_seq)) {
|
2021-11-27 22:20:22 +08:00
|
|
|
|
case ExtSeqStatus::jumped: /*seq异常,过滤掉*/ return;
|
2021-10-07 14:22:12 +08:00
|
|
|
|
case ExtSeqStatus::looped: /*回环,触发发送twcc rtcp*/ onSendTwcc(ssrc); break;
|
2021-10-06 22:17:38 +08:00
|
|
|
|
case ExtSeqStatus::normal: break;
|
|
|
|
|
default: /*不可达*/assert(0); break;
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-07 15:49:33 +08:00
|
|
|
|
auto result = _rtp_recv_status.emplace(twcc_ext_seq, stamp_ms);
|
2021-10-06 22:17:38 +08:00
|
|
|
|
if (!result.second) {
|
|
|
|
|
WarnL << "recv same twcc ext seq:" << twcc_ext_seq;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_max_stamp = result.first->second;
|
|
|
|
|
if (!_min_stamp) {
|
|
|
|
|
_min_stamp = _max_stamp;
|
|
|
|
|
}
|
|
|
|
|
|
2021-11-18 19:29:54 +08:00
|
|
|
|
if (needSendTwcc()) {
|
2021-10-06 22:17:38 +08:00
|
|
|
|
//其他匹配条件立即发送twcc
|
2021-10-07 14:22:12 +08:00
|
|
|
|
onSendTwcc(ssrc);
|
2021-10-06 22:17:38 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-11-18 19:29:54 +08:00
|
|
|
|
bool TwccContext::needSendTwcc() const {
|
|
|
|
|
if (_rtp_recv_status.empty()) {
|
2021-10-06 22:17:38 +08:00
|
|
|
|
return false;
|
|
|
|
|
}
|
2021-11-18 19:29:54 +08:00
|
|
|
|
return (_rtp_recv_status.size() >= kMaxSeqSize) || (_max_stamp - _min_stamp >= kMaxTimeDelta);
|
2021-10-06 22:17:38 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int TwccContext::checkSeqStatus(uint16_t twcc_ext_seq) const {
|
|
|
|
|
if (_rtp_recv_status.empty()) {
|
|
|
|
|
return (int) ExtSeqStatus::normal;
|
|
|
|
|
}
|
|
|
|
|
auto max = _rtp_recv_status.rbegin()->first;
|
2021-11-27 22:20:22 +08:00
|
|
|
|
auto delta = (int32_t) twcc_ext_seq - (int32_t) max;
|
|
|
|
|
if (delta > 0 && delta < 0xFFFF / 2) {
|
|
|
|
|
//正常增长
|
|
|
|
|
return (int) ExtSeqStatus::normal;
|
|
|
|
|
}
|
|
|
|
|
if (delta < -0xFF00) {
|
|
|
|
|
//回环
|
2021-10-06 22:17:38 +08:00
|
|
|
|
TraceL << "rtp twcc ext seq looped:" << max << " -> " << twcc_ext_seq;
|
|
|
|
|
return (int) ExtSeqStatus::looped;
|
|
|
|
|
}
|
2021-11-27 22:20:22 +08:00
|
|
|
|
if (delta > 0xFF00) {
|
|
|
|
|
//回环后收到前面大的乱序的包,无法处理,丢弃
|
|
|
|
|
TraceL << "rtp twcc ext seq jumped after looped:" << max << " -> " << twcc_ext_seq;
|
2021-10-06 22:17:38 +08:00
|
|
|
|
return (int) ExtSeqStatus::jumped;
|
|
|
|
|
}
|
2021-11-27 22:20:22 +08:00
|
|
|
|
auto min = _rtp_recv_status.begin()->first;
|
|
|
|
|
if (min <= twcc_ext_seq || twcc_ext_seq <= max) {
|
|
|
|
|
//正常回退
|
|
|
|
|
return (int) ExtSeqStatus::normal;
|
|
|
|
|
}
|
|
|
|
|
//seq莫名的大幅增加或减少,无法处理,丢弃
|
|
|
|
|
TraceL << "rtp twcc ext seq jumped:" << max << " -> " << twcc_ext_seq;
|
|
|
|
|
return (int) ExtSeqStatus::jumped;
|
2021-10-06 22:17:38 +08:00
|
|
|
|
}
|
|
|
|
|
|
2021-10-07 14:22:12 +08:00
|
|
|
|
void TwccContext::onSendTwcc(uint32_t ssrc) {
|
2021-10-06 22:17:38 +08:00
|
|
|
|
auto max = _rtp_recv_status.rbegin()->first;
|
|
|
|
|
auto begin = _rtp_recv_status.begin();
|
|
|
|
|
auto min = begin->first;
|
2021-10-07 15:49:33 +08:00
|
|
|
|
//参考时间戳的最小单位是64ms
|
2021-10-07 14:22:12 +08:00
|
|
|
|
auto ref_time = begin->second >> 6;
|
2021-10-07 15:49:33 +08:00
|
|
|
|
//还原基准时间戳
|
2021-10-07 14:22:12 +08:00
|
|
|
|
auto last_time = ref_time << 6;
|
2021-10-07 12:28:59 +08:00
|
|
|
|
FCI_TWCC::TwccPacketStatus status;
|
|
|
|
|
for (auto seq = min; seq <= max; ++seq) {
|
|
|
|
|
int16_t delta = 0;
|
|
|
|
|
SymbolStatus symbol = SymbolStatus::not_received;
|
|
|
|
|
auto it = _rtp_recv_status.find(seq);
|
|
|
|
|
if (it != _rtp_recv_status.end()) {
|
|
|
|
|
//recv delta,单位为250us,1ms等于4x250us
|
2021-10-07 14:22:12 +08:00
|
|
|
|
delta = (int16_t) (4 * ((int64_t) it->second - (int64_t) last_time));
|
2021-10-07 12:28:59 +08:00
|
|
|
|
if (delta < 0 || delta > 0xFF) {
|
|
|
|
|
symbol = SymbolStatus::large_delta;
|
|
|
|
|
} else {
|
|
|
|
|
symbol = SymbolStatus::small_delta;
|
|
|
|
|
}
|
2021-10-07 14:22:12 +08:00
|
|
|
|
last_time = it->second;
|
2021-10-06 22:17:38 +08:00
|
|
|
|
}
|
2021-10-07 12:28:59 +08:00
|
|
|
|
status.emplace(seq, std::make_pair(symbol, delta));
|
2021-10-06 22:17:38 +08:00
|
|
|
|
}
|
2021-10-07 14:22:12 +08:00
|
|
|
|
auto fci = FCI_TWCC::create(ref_time, _twcc_pkt_count++, status);
|
|
|
|
|
if (_cb) {
|
|
|
|
|
_cb(ssrc, std::move(fci));
|
|
|
|
|
}
|
2021-10-06 22:17:38 +08:00
|
|
|
|
clearStatus();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void TwccContext::clearStatus() {
|
|
|
|
|
_rtp_recv_status.clear();
|
|
|
|
|
_min_stamp = 0;
|
|
|
|
|
}
|
2021-10-07 14:22:12 +08:00
|
|
|
|
|
|
|
|
|
void TwccContext::setOnSendTwccCB(TwccContext::onSendTwccCB cb) {
|
|
|
|
|
_cb = std::move(cb);
|
|
|
|
|
}
|
2022-09-18 21:03:05 +08:00
|
|
|
|
|
|
|
|
|
}// namespace mediakit
|