抽象RtpExtContext对象

This commit is contained in:
ziyue 2021-06-25 15:31:13 +08:00
parent 964cf39145
commit 7406281c96
4 changed files with 115 additions and 96 deletions

View File

@ -561,4 +561,73 @@ void RtpExt::setType(RtpExtType type) {
RtpExtType RtpExt::getType() const { RtpExtType RtpExt::getType() const {
return _type; return _type;
} }
RtpExtContext::RtpExtContext(const RtcMedia &m){
for (auto &ext : m.extmap) {
auto ext_type = RtpExt::getExtType(ext.ext);
_rtp_ext_id_to_type.emplace(ext.id, ext_type);
_rtp_ext_type_to_id.emplace(ext_type, ext.id);
}
}
string RtpExtContext::getRid(uint32_t ssrc) const{
auto it = _ssrc_to_rid.find(ssrc);
if (it == _ssrc_to_rid.end()) {
return "";
}
return it->second;
}
void RtpExtContext::changeRtpExtId(const RtpHeader *header, bool is_recv, string *rid_ptr) {
string rid, repaired_rid;
auto ext_map = RtpExt::getExtValue(header);
for (auto &pr : ext_map) {
if (is_recv) {
auto it = _rtp_ext_id_to_type.find(pr.first);
if (it == _rtp_ext_id_to_type.end()) {
WarnL << "接收rtp时,忽略不识别的rtp ext, id=" << (int) pr.first;
pr.second.clearExt();
continue;
}
pr.second.setType(it->second);
//重新赋值ext id为 ext type作为后面处理ext的统一中间类型
pr.second.setExtId((uint8_t) it->second);
switch (it->second) {
case RtpExtType::sdes_rtp_stream_id : rid = pr.second.getRtpStreamId(); break;
case RtpExtType::sdes_repaired_rtp_stream_id : repaired_rid = pr.second.getRepairedRtpStreamId(); break;
default : break;
}
} else {
pr.second.setType((RtpExtType) pr.first);
auto it = _rtp_ext_type_to_id.find((RtpExtType) pr.first);
if (it == _rtp_ext_type_to_id.end()) {
WarnL << "发送rtp时, 忽略不被客户端支持rtp ext:" << pr.second.dumpString();
pr.second.clearExt();
continue;
}
//重新赋值ext id为客户端sdp声明的类型
pr.second.setExtId(it->second);
}
}
if (!is_recv) {
return;
}
if (rid.empty()) {
rid = repaired_rid;
}
auto ssrc = ntohl(header->ssrc);
if (rid.empty()) {
//获取rid
rid = _ssrc_to_rid[ssrc];
} else {
//设置rid
if (_ssrc_to_rid.emplace(ssrc, rid).second) {
InfoL << "rid of ssrc " << ssrc << " is:" << rid;
}
}
if (rid_ptr) {
*rid_ptr = rid;
}
}

View File

@ -108,5 +108,23 @@ private:
RtpExtType _type = RtpExtType::padding; RtpExtType _type = RtpExtType::padding;
}; };
class RtcMedia;
class RtpExtContext {
public:
using Ptr = std::shared_ptr<RtpExtContext>;
RtpExtContext(const RtcMedia &media);
~RtpExtContext() = default;
string getRid(uint32_t ssrc) const;
void changeRtpExtId(const RtpHeader *header, bool is_recv, string *rid_ptr = nullptr);
private:
//发送rtp时需要修改rtp ext id
map<RtpExtType, uint8_t> _rtp_ext_type_to_id;
//接收rtp时需要修改rtp ext id
unordered_map<uint8_t, RtpExtType> _rtp_ext_id_to_type;
//ssrc --> rid
unordered_map<uint32_t/*simulcast ssrc*/, string/*rid*/> _ssrc_to_rid;
};
#endif //ZLMEDIAKIT_RTPEXT_H #endif //ZLMEDIAKIT_RTPEXT_H

View File

@ -424,11 +424,7 @@ void WebRtcTransportImp::onStartWebRTC() {
} }
if (m_offer->type != TrackApplication) { if (m_offer->type != TrackApplication) {
//记录rtp ext类型与id的关系方便接收或发送rtp时修改rtp ext id //记录rtp ext类型与id的关系方便接收或发送rtp时修改rtp ext id
for (auto &ext : m_offer->extmap) { info->rtp_ext_ctx = std::make_shared<RtpExtContext>(*m_offer);
auto ext_type = RtpExt::getExtType(ext.ext);
_rtp_ext_id_to_type.emplace(ext.id, ext_type);
_rtp_ext_type_to_id.emplace(ext_type, ext.id);
}
} }
} }
@ -596,12 +592,8 @@ private:
function<void(RtpPacket::Ptr rtp)> _on_sort; function<void(RtpPacket::Ptr rtp)> _on_sort;
}; };
std::shared_ptr<RtpChannel> WebRtcTransportImp::MediaTrack::getRtpChannel(uint32_t ssrc) const{ std::shared_ptr<RtpChannel> MediaTrack::getRtpChannel(uint32_t ssrc) const{
auto it_rid = ssrc_to_rid.find(ssrc); auto it_chn = rtp_channel.find(rtp_ext_ctx->getRid(ssrc));
if (it_rid == ssrc_to_rid.end()) {
return nullptr;
}
auto it_chn = rtp_channel.find(it_rid->second);
if (it_chn == rtp_channel.end()) { if (it_chn == rtp_channel.end()) {
return nullptr; return nullptr;
} }
@ -694,59 +686,6 @@ void WebRtcTransportImp::onRtcp(const char *buf, size_t len) {
/////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////
void WebRtcTransportImp::changeRtpExtId(MediaTrack &info, const RtpHeader *header, bool is_recv, string *rid_ptr) const{
string rid, repaired_rid;
auto ext_map = RtpExt::getExtValue(header);
for (auto &pr : ext_map) {
if (is_recv) {
auto it = _rtp_ext_id_to_type.find(pr.first);
if (it == _rtp_ext_id_to_type.end()) {
WarnL << "接收rtp时,忽略不识别的rtp ext, id=" << (int) pr.first;
pr.second.clearExt();
continue;
}
pr.second.setType(it->second);
//重新赋值ext id为 ext type作为后面处理ext的统一中间类型
pr.second.setExtId((uint8_t) it->second);
switch (it->second) {
case RtpExtType::sdes_rtp_stream_id : rid = pr.second.getRtpStreamId(); break;
case RtpExtType::sdes_repaired_rtp_stream_id : repaired_rid = pr.second.getRepairedRtpStreamId(); break;
default : break;
}
} else {
pr.second.setType((RtpExtType) pr.first);
auto it = _rtp_ext_type_to_id.find((RtpExtType) pr.first);
if (it == _rtp_ext_type_to_id.end()) {
WarnL << "发送rtp时, 忽略不被客户端支持rtp ext:" << pr.second.dumpString();
pr.second.clearExt();
continue;
}
//重新赋值ext id为客户端sdp声明的类型
pr.second.setExtId(it->second);
}
}
if (!is_recv) {
return;
}
if (rid.empty()) {
rid = repaired_rid;
}
auto ssrc = ntohl(header->ssrc);
if (rid.empty()) {
//获取rid
rid = info.ssrc_to_rid[ssrc];
} else {
//设置rid
if (info.ssrc_to_rid.emplace(ssrc, rid).second) {
InfoL << "rid of ssrc " << ssrc << " is:" << rid;
}
}
if (rid_ptr) {
*rid_ptr = rid;
}
}
void WebRtcTransportImp::createRtpChannel(const string &rid, uint32_t ssrc, const MediaTrack::Ptr &info) { void WebRtcTransportImp::createRtpChannel(const string &rid, uint32_t ssrc, const MediaTrack::Ptr &info) {
//rid --> RtpReceiverImp //rid --> RtpReceiverImp
auto &ref = info->rtp_channel[rid]; auto &ref = info->rtp_channel[rid];
@ -779,13 +718,8 @@ void WebRtcTransportImp::onRtp(const char *buf, size_t len) {
//修改ext id至统一 //修改ext id至统一
string rid; string rid;
changeRtpExtId(*info, rtp, true, &rid); info->rtp_ext_ctx->changeRtpExtId(rtp, true, &rid);
#if 0
if (rid.empty() && info->media->type == TrackVideo) {
WarnL << "ssrc:" << ssrc << ", rtx:" << is_rtx << ",seq:" << ntohs((uint16_t) rtp->seq);
}
#endif
auto &ref = info->rtp_channel[rid]; auto &ref = info->rtp_channel[rid];
if (!ref) { if (!ref) {
if (is_rtx) { if (is_rtx) {
@ -910,12 +844,12 @@ void WebRtcTransportImp::onBeforeEncryptRtp(const char *buf, size_t &len, void *
if (!pr->first || !pr->second->plan_rtx) { if (!pr->first || !pr->second->plan_rtx) {
//普通的rtp,或者不支持rtx, 修改目标pt和ssrc //普通的rtp,或者不支持rtx, 修改目标pt和ssrc
changeRtpExtId(*pr->second, header, false); pr->second->rtp_ext_ctx->changeRtpExtId(header, false);
header->pt = pr->second->plan_rtp->pt; header->pt = pr->second->plan_rtp->pt;
header->ssrc = htonl(pr->second->answer_ssrc_rtp); header->ssrc = htonl(pr->second->answer_ssrc_rtp);
} else { } else {
//重传的rtp, rtx //重传的rtp, rtx
changeRtpExtId(*pr->second, header, false); pr->second->rtp_ext_ctx->changeRtpExtId(header, false);
header->pt = pr->second->plan_rtx->pt; header->pt = pr->second->plan_rtx->pt;
if (pr->second->answer_ssrc_rtx) { if (pr->second->answer_ssrc_rtx) {
//有rtx单独的ssrc,有些情况下浏览器支持rtx但是未指定rtx单独的ssrc //有rtx单独的ssrc,有些情况下浏览器支持rtx但是未指定rtx单独的ssrc

View File

@ -272,6 +272,27 @@ private:
uint16_t _last_max_seq = 0; uint16_t _last_max_seq = 0;
}; };
class MediaTrack {
public:
using Ptr = std::shared_ptr<MediaTrack>;
const RtcCodecPlan *plan_rtp;
const RtcCodecPlan *plan_rtx;
uint32_t offer_ssrc_rtp = 0;
uint32_t offer_ssrc_rtx = 0;
uint32_t answer_ssrc_rtp = 0;
uint32_t answer_ssrc_rtx = 0;
const RtcMedia *media;
RtpExtContext::Ptr rtp_ext_ctx;
//for send rtp
NackList nack_list;
RtcpContext::Ptr rtcp_context_send;
//for recv rtp
unordered_map<string/*rid*/, std::shared_ptr<RtpChannel> > rtp_channel;
std::shared_ptr<RtpChannel> getRtpChannel(uint32_t ssrc) const;
};
class WebRtcTransportImp : public WebRtcTransport, public MediaSourceEvent, public SockInfo, public std::enable_shared_from_this<WebRtcTransportImp>{ class WebRtcTransportImp : public WebRtcTransport, public MediaSourceEvent, public SockInfo, public std::enable_shared_from_this<WebRtcTransportImp>{
public: public:
using Ptr = std::shared_ptr<WebRtcTransportImp>; using Ptr = std::shared_ptr<WebRtcTransportImp>;
@ -337,27 +358,8 @@ private:
bool canSendRtp() const; bool canSendRtp() const;
bool canRecvRtp() const; bool canRecvRtp() const;
class MediaTrack {
public:
using Ptr = std::shared_ptr<MediaTrack>;
const RtcCodecPlan *plan_rtp;
const RtcCodecPlan *plan_rtx;
uint32_t offer_ssrc_rtp = 0;
uint32_t offer_ssrc_rtx = 0;
uint32_t answer_ssrc_rtp = 0;
uint32_t answer_ssrc_rtx = 0;
const RtcMedia *media;
NackList nack_list;
RtcpContext::Ptr rtcp_context_send;
unordered_map<string/*rid*/, std::shared_ptr<RtpChannel> > rtp_channel;
unordered_map<uint32_t/*simulcast ssrc*/, string/*rid*/> ssrc_to_rid;
std::shared_ptr<RtpChannel> getRtpChannel(uint32_t ssrc) const;
};
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 changeRtpExtId(MediaTrack &track, const RtpHeader *header, bool is_recv, string *rid_ptr = nullptr) const;
void createRtpChannel(const string &rid, uint32_t ssrc, const MediaTrack::Ptr &info); void createRtpChannel(const string &rid, uint32_t ssrc, const MediaTrack::Ptr &info);
private: private:
@ -389,8 +391,4 @@ private:
unordered_map<uint8_t/*pt*/, std::pair<bool/*is rtx*/,MediaTrack::Ptr> > _pt_to_track; unordered_map<uint8_t/*pt*/, std::pair<bool/*is rtx*/,MediaTrack::Ptr> > _pt_to_track;
//根据rtcp的ssrc获取相关信息只记录rtp的ssrcrtx的ssrc不记录 //根据rtcp的ssrc获取相关信息只记录rtp的ssrcrtx的ssrc不记录
unordered_map<uint32_t/*ssrc*/, MediaTrack::Ptr> _ssrc_to_track; unordered_map<uint32_t/*ssrc*/, MediaTrack::Ptr> _ssrc_to_track;
//发送rtp时需要修改rtp ext id
map<RtpExtType, uint8_t> _rtp_ext_type_to_id;
//接收rtp时需要修改rtp ext id
unordered_map<uint8_t, RtpExtType> _rtp_ext_id_to_type;
}; };