refactor: 梳理 rtx 处理逻辑

This commit is contained in:
Johnny 2021-11-18 18:41:23 +08:00
parent b13a0f5b79
commit da0a7219e9
2 changed files with 61 additions and 24 deletions

View File

@ -385,10 +385,10 @@ void WebRtcTransportImp::onStartWebRTC() {
_ssrc_to_track[track->offer_ssrc_rtx] = track; _ssrc_to_track[track->offer_ssrc_rtx] = track;
//rtp pt --> MediaTrack //rtp pt --> MediaTrack
_pt_to_track.emplace(track->plan_rtp->pt, std::make_pair(false, track)); _pt_to_track.emplace(track->plan_rtp->pt, new WrappedRtpTrack(track, _twcc_ctx, *this));
if (track->plan_rtx) { if (track->plan_rtx) {
//rtx pt --> MediaTrack //rtx pt --> MediaTrack
_pt_to_track.emplace(track->plan_rtx->pt, std::make_pair(true, track)); _pt_to_track.emplace(track->plan_rtx->pt, new WrappedRtxTrack(track));
} }
if (m_offer->type != TrackApplication) { if (m_offer->type != TrackApplication) {
//记录rtp ext类型与id的关系方便接收或发送rtp时修改rtp ext id //记录rtp ext类型与id的关系方便接收或发送rtp时修改rtp ext id
@ -691,43 +691,51 @@ void WebRtcTransportImp::onRtp(const char *buf, size_t len, uint64_t stamp_ms) {
WarnL << "unknown rtp pt:" << (int)rtp->pt; WarnL << "unknown rtp pt:" << (int)rtp->pt;
return; return;
} }
bool is_rtx = it->second.first; it->second->inputRtp(buf, len, stamp_ms, rtp);
}
void WrappedRtpTrack::inputRtp(const char *buf, size_t len, uint64_t stamp_ms, RtpHeader *rtp) {
auto ssrc = ntohl(rtp->ssrc); auto ssrc = ntohl(rtp->ssrc);
auto &track = it->second.second;
//修改ext id至统一 //修改ext id至统一
string rid; string rid;
auto twcc_ext = track->rtp_ext_ctx->changeRtpExtId(rtp, true, &rid, RtpExtType::transport_cc); auto twcc_ext = track->rtp_ext_ctx->changeRtpExtId(rtp, true, &rid, RtpExtType::transport_cc);
if (twcc_ext && !is_rtx) {
if (twcc_ext) {
_twcc_ctx.onRtp(ssrc, twcc_ext.getTransportCCSeq(), stamp_ms); _twcc_ctx.onRtp(ssrc, twcc_ext.getTransportCCSeq(), stamp_ms);
} }
auto &ref = track->rtp_channel[rid]; auto &ref = track->rtp_channel[rid];
if (!ref) { if (!ref) {
if (is_rtx) { _transport.createRtpChannel(rid, ssrc, *track);
//再接收到对应的rtp前丢弃rtx包
WarnL << "unknown rtx rtp, rid:" << rid << ", ssrc:" << ssrc << ", codec:" << track->plan_rtp->codec << ", seq:" << ntohs(rtp->seq);
return;
}
createRtpChannel(rid, ssrc, *track);
} }
if (!is_rtx) { //这是普通的rtp数据
//这是普通的rtp数据
#if 0 #if 0
auto seq = ntohs(rtp->seq); auto seq = ntohs(rtp->seq);
if (track->media->type == TrackVideo && seq % 100 == 0) { if (track->media->type == TrackVideo && seq % 100 == 0) {
//此处模拟接受丢包 //此处模拟接受丢包
return; return;
} }
#endif #endif
//解析并排序rtp //解析并排序rtp
ref->inputRtp(track->media->type, track->plan_rtp->sample_rate, (uint8_t *) buf, len, false); ref->inputRtp(track->media->type, track->plan_rtp->sample_rate, (uint8_t *) buf, len, false);
}
void WrappedRtxTrack::inputRtp(const char *buf, size_t len, uint64_t stamp_ms, RtpHeader *rtp) {
//修改ext id至统一
string rid;
track->rtp_ext_ctx->changeRtpExtId(rtp, true, &rid, RtpExtType::transport_cc);
auto &ref = track->rtp_channel[rid];
if (!ref) {
//再接收到对应的rtp前丢弃rtx包
WarnL << "unknown rtx rtp, rid:" << rid << ", ssrc:" << ntohl(rtp->ssrc) << ", codec:" << track->plan_rtp->codec << ", seq:" << ntohs(rtp->seq);
return; return;
} }
//这里是rtx重传包 //这里是rtx重传包
//https://datatracker.ietf.org/doc/html/rfc4588#section-4 // https://datatracker.ietf.org/doc/html/rfc4588#section-4
auto payload = rtp->getPayloadData(); auto payload = rtp->getPayloadData();
auto size = rtp->getPayloadSize(len); auto size = rtp->getPayloadSize(len);
if (size < 2) { if (size < 2) {
@ -736,7 +744,7 @@ void WebRtcTransportImp::onRtp(const char *buf, size_t len, uint64_t stamp_ms) {
//前两个字节是原始的rtp的seq //前两个字节是原始的rtp的seq
auto origin_seq = payload[0] << 8 | payload[1]; auto origin_seq = payload[0] << 8 | payload[1];
//rtx 转换为 rtp // rtx 转换为 rtp
rtp->pt = track->plan_rtp->pt; rtp->pt = track->plan_rtp->pt;
rtp->seq = htons(origin_seq); rtp->seq = htons(origin_seq);
rtp->ssrc = htonl(ref->getSSRC()); rtp->ssrc = htonl(ref->getSSRC());

View File

@ -189,6 +189,33 @@ public:
std::shared_ptr<RtpChannel> getRtpChannel(uint32_t ssrc) const; std::shared_ptr<RtpChannel> getRtpChannel(uint32_t ssrc) const;
}; };
struct WrappedMediaTrack {
MediaTrack::Ptr track;
explicit WrappedMediaTrack(MediaTrack::Ptr ptr): track(ptr) {}
virtual ~WrappedMediaTrack() {}
virtual void inputRtp(const char *buf, size_t len, uint64_t stamp_ms, RtpHeader *rtp) = 0;
};
struct WrappedRtxTrack: public WrappedMediaTrack {
explicit WrappedRtxTrack(MediaTrack::Ptr ptr)
: WrappedMediaTrack(std::move(ptr)) {}
void inputRtp(const char *buf, size_t len, uint64_t stamp_ms, RtpHeader *rtp) override;
};
class WebRtcTransportImp;
struct WrappedRtpTrack : public WrappedMediaTrack {
explicit WrappedRtpTrack(MediaTrack::Ptr ptr, TwccContext& twcc, WebRtcTransportImp& t)
: WrappedMediaTrack(std::move(ptr))
, _twcc_ctx(twcc)
, _transport(t) {}
TwccContext& _twcc_ctx;
WebRtcTransportImp& _transport;
void inputRtp(const char *buf, size_t len, uint64_t stamp_ms, RtpHeader *rtp) override;
};
class WebRtcTransportImp : public WebRtcTransport { class WebRtcTransportImp : public WebRtcTransport {
public: public:
using Ptr = std::shared_ptr<WebRtcTransportImp>; using Ptr = std::shared_ptr<WebRtcTransportImp>;
@ -202,6 +229,8 @@ public:
bool canRecvRtp() const; bool canRecvRtp() const;
void onSendRtp(const RtpPacket::Ptr &rtp, bool flush, bool rtx = false); void onSendRtp(const RtpPacket::Ptr &rtp, bool flush, bool rtx = false);
void createRtpChannel(const string &rid, uint32_t ssrc, MediaTrack &track);
protected: protected:
WebRtcTransportImp(const EventPoller::Ptr &poller); WebRtcTransportImp(const EventPoller::Ptr &poller);
void onStartWebRTC() override; void onStartWebRTC() override;
@ -224,7 +253,7 @@ private:
void onSortedRtp(MediaTrack &track, const string &rid, RtpPacket::Ptr rtp); void onSortedRtp(MediaTrack &track, const string &rid, RtpPacket::Ptr rtp);
void onSendNack(MediaTrack &track, const FCI_NACK &nack, uint32_t ssrc); void onSendNack(MediaTrack &track, const FCI_NACK &nack, uint32_t ssrc);
void onSendTwcc(uint32_t ssrc, const string &twcc_fci); void onSendTwcc(uint32_t ssrc, const string &twcc_fci);
void createRtpChannel(const string &rid, uint32_t ssrc, MediaTrack &track);
void registerSelf(); void registerSelf();
void unregisterSelf(); void unregisterSelf();
void unrefSelf(); void unrefSelf();
@ -251,7 +280,7 @@ private:
//根据rtcp的ssrc获取相关信息收发rtp和rtx的ssrc都会记录 //根据rtcp的ssrc获取相关信息收发rtp和rtx的ssrc都会记录
unordered_map<uint32_t/*ssrc*/, MediaTrack::Ptr> _ssrc_to_track; unordered_map<uint32_t/*ssrc*/, MediaTrack::Ptr> _ssrc_to_track;
//根据接收rtp的pt获取相关信息 //根据接收rtp的pt获取相关信息
unordered_map<uint8_t/*pt*/, std::pair<bool/*is rtx*/,MediaTrack::Ptr> > _pt_to_track; unordered_map<uint8_t/*pt*/, std::unique_ptr<WrappedMediaTrack>> _pt_to_track;
}; };
class WebRtcTransportManager { class WebRtcTransportManager {