From 7406281c965efc3a4d588567035258f5440a5ec8 Mon Sep 17 00:00:00 2001 From: ziyue <1213642868@qq.com> Date: Fri, 25 Jun 2021 15:31:13 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8A=BD=E8=B1=A1RtpExtContext=E5=AF=B9?= =?UTF-8?q?=E8=B1=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- webrtc/RtpExt.cpp | 71 +++++++++++++++++++++++++++++++++- webrtc/RtpExt.h | 18 +++++++++ webrtc/WebRtcTransport.cpp | 78 +++----------------------------------- webrtc/WebRtcTransport.h | 44 ++++++++++----------- 4 files changed, 115 insertions(+), 96 deletions(-) diff --git a/webrtc/RtpExt.cpp b/webrtc/RtpExt.cpp index dd9a1e2e..99581ca7 100644 --- a/webrtc/RtpExt.cpp +++ b/webrtc/RtpExt.cpp @@ -561,4 +561,73 @@ void RtpExt::setType(RtpExtType type) { RtpExtType RtpExt::getType() const { return _type; -} \ No newline at end of file +} + +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; + } +} diff --git a/webrtc/RtpExt.h b/webrtc/RtpExt.h index 9520bac6..71774657 100644 --- a/webrtc/RtpExt.h +++ b/webrtc/RtpExt.h @@ -108,5 +108,23 @@ private: RtpExtType _type = RtpExtType::padding; }; +class RtcMedia; +class RtpExtContext { +public: + using Ptr = std::shared_ptr; + 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 _rtp_ext_type_to_id; + //接收rtp时需要修改rtp ext id + unordered_map _rtp_ext_id_to_type; + //ssrc --> rid + unordered_map _ssrc_to_rid; +}; #endif //ZLMEDIAKIT_RTPEXT_H diff --git a/webrtc/WebRtcTransport.cpp b/webrtc/WebRtcTransport.cpp index 2a1b14f3..5b2ce735 100644 --- a/webrtc/WebRtcTransport.cpp +++ b/webrtc/WebRtcTransport.cpp @@ -424,11 +424,7 @@ void WebRtcTransportImp::onStartWebRTC() { } if (m_offer->type != TrackApplication) { //记录rtp ext类型与id的关系,方便接收或发送rtp时修改rtp ext id - for (auto &ext : m_offer->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); - } + info->rtp_ext_ctx = std::make_shared(*m_offer); } } @@ -596,12 +592,8 @@ private: function _on_sort; }; -std::shared_ptr WebRtcTransportImp::MediaTrack::getRtpChannel(uint32_t ssrc) const{ - auto it_rid = ssrc_to_rid.find(ssrc); - if (it_rid == ssrc_to_rid.end()) { - return nullptr; - } - auto it_chn = rtp_channel.find(it_rid->second); +std::shared_ptr MediaTrack::getRtpChannel(uint32_t ssrc) const{ + auto it_chn = rtp_channel.find(rtp_ext_ctx->getRid(ssrc)); if (it_chn == rtp_channel.end()) { 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) { //rid --> RtpReceiverImp auto &ref = info->rtp_channel[rid]; @@ -779,13 +718,8 @@ void WebRtcTransportImp::onRtp(const char *buf, size_t len) { //修改ext id至统一 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]; if (!ref) { if (is_rtx) { @@ -910,12 +844,12 @@ void WebRtcTransportImp::onBeforeEncryptRtp(const char *buf, size_t &len, void * if (!pr->first || !pr->second->plan_rtx) { //普通的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->ssrc = htonl(pr->second->answer_ssrc_rtp); } else { //重传的rtp, rtx - changeRtpExtId(*pr->second, header, false); + pr->second->rtp_ext_ctx->changeRtpExtId(header, false); header->pt = pr->second->plan_rtx->pt; if (pr->second->answer_ssrc_rtx) { //有rtx单独的ssrc,有些情况下,浏览器支持rtx,但是未指定rtx单独的ssrc diff --git a/webrtc/WebRtcTransport.h b/webrtc/WebRtcTransport.h index 87450ff3..8fc54c15 100644 --- a/webrtc/WebRtcTransport.h +++ b/webrtc/WebRtcTransport.h @@ -272,6 +272,27 @@ private: uint16_t _last_max_seq = 0; }; +class MediaTrack { +public: + using Ptr = std::shared_ptr; + 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 > rtp_channel; + std::shared_ptr getRtpChannel(uint32_t ssrc) const; +}; + class WebRtcTransportImp : public WebRtcTransport, public MediaSourceEvent, public SockInfo, public std::enable_shared_from_this{ public: using Ptr = std::shared_ptr; @@ -337,27 +358,8 @@ private: bool canSendRtp() const; bool canRecvRtp() const; - class MediaTrack { - public: - using Ptr = std::shared_ptr; - 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 > rtp_channel; - unordered_map ssrc_to_rid; - - std::shared_ptr getRtpChannel(uint32_t ssrc) const; - }; - void onSortedRtp(MediaTrack &track, const string &rid, RtpPacket::Ptr rtp); 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); private: @@ -389,8 +391,4 @@ private: unordered_map > _pt_to_track; //根据rtcp的ssrc获取相关信息,只记录rtp的ssrc,rtx的ssrc不记录 unordered_map _ssrc_to_track; - //发送rtp时需要修改rtp ext id - map _rtp_ext_type_to_id; - //接收rtp时需要修改rtp ext id - unordered_map _rtp_ext_id_to_type; }; \ No newline at end of file