diff --git a/webrtc/Sdp.cpp b/webrtc/Sdp.cpp index 3b2cfc9d..b0aae5b5 100644 --- a/webrtc/Sdp.cpp +++ b/webrtc/Sdp.cpp @@ -52,6 +52,18 @@ public: RtpDirection getDirection() const override {return RtpDirection::inactive;} }; +class DirectionInterfaceImp : public SdpItem, public DirectionInterface{ +public: + DirectionInterfaceImp(RtpDirection direct){ + direction = direct; + } + const char* getKey() const override { return getRtpDirectionString(getDirection());} + RtpDirection getDirection() const override {return direction;} + +private: + RtpDirection direction; +}; + static bool registerAllItem(){ registerSdpItem >(); registerSdpItem >(); @@ -502,7 +514,7 @@ void SdpAttrExtmap::parse(const string &str) { string SdpAttrExtmap::toString() const { if (value.empty()) { - if(direction == RtpDirection::invalid){ + if(direction == RtpDirection::invalid || direction == RtpDirection::sendrecv){ value = to_string(index) + " " + ext; } else { value = to_string(index) + "/" + getRtpDirectionString(direction) + " " + ext; @@ -630,9 +642,9 @@ void SdpAttrSSRCGroup::parse(const string &str) { string SdpAttrSSRCGroup::toString() const { if (value.empty()) { - if (type == "FID") { + if (isFID()) { value = type + " " + to_string(u.fid.rtp_ssrc) + " " + to_string(u.fid.rtx_ssrc); - } else if (type == "SIM") { + } else if (isSIM()) { value = type + " " + to_string(u.sim.rtp_ssrc_low) + " " + to_string(u.sim.rtp_ssrc_mid) + " " + to_string(u.sim.rtp_ssrc_high); } else { SDP_THROW2(); @@ -849,7 +861,8 @@ void test_sdp(){ RtcSession session2; session2.loadFrom(str2); - InfoL; + DebugL << session1.toString(); + DebugL << session2.toString(); } void RtcSession::loadFrom(const string &str) { @@ -1013,6 +1026,165 @@ void RtcSession::loadFrom(const string &str) { checkValid(); } +std::shared_ptr wrapSdpAttr(SdpItem::Ptr item){ + auto ret = std::make_shared(); + ret->detail = std::move(item); + return ret; +} + +string RtcSession::toString() const{ + checkValid(); + RtcSessionSdp sdp; + sdp.items.emplace_back(std::make_shared >(to_string(version))); + sdp.items.emplace_back(std::make_shared(origin)); + sdp.items.emplace_back(std::make_shared >(session_name)); + if (!session_info.empty()) { + sdp.items.emplace_back(std::make_shared >(session_info)); + } + sdp.items.emplace_back(std::make_shared(time)); + sdp.items.emplace_back(std::make_shared(connection)); + if (!bandwidth.empty()) { + sdp.items.emplace_back(std::make_shared(bandwidth)); + } + sdp.items.emplace_back(wrapSdpAttr(std::make_shared(msid_semantic))); + sdp.items.emplace_back(wrapSdpAttr(std::make_shared(group))); + for (auto &m : media) { + sdp.medias.emplace_back(); + auto &sdp_media = sdp.medias.back(); + auto mline = std::make_shared(); + mline->type = m.type; + mline->port = m.port; + mline->proto = m.proto; + for (auto &p : m.plan) { + mline->fmts.emplace_back(p.pt); + } + if (m.type == TrackApplication) { + mline->fmts.emplace_back(m.sctp_port); + } + sdp_media.items.emplace_back(std::move(mline)); + sdp_media.items.emplace_back(wrapSdpAttr(std::make_shared(m.mid))); + sdp_media.items.emplace_back(std::make_shared(m.addr)); + sdp_media.items.emplace_back(wrapSdpAttr(std::make_shared(m.ice_ufrag))); + sdp_media.items.emplace_back(wrapSdpAttr(std::make_shared(m.ice_pwd))); + sdp_media.items.emplace_back(wrapSdpAttr(std::make_shared(m.fingerprint))); + sdp_media.items.emplace_back(wrapSdpAttr(std::make_shared(m.role))); + if (m.ice_trickle) { + sdp_media.items.emplace_back(wrapSdpAttr(std::make_shared("ice-trickle"))); + } + if (m.ice_lite) { + sdp_media.items.emplace_back(wrapSdpAttr(std::make_shared("ice-lite"))); + } + if (m.ice_renomination) { + sdp_media.items.emplace_back(wrapSdpAttr(std::make_shared("ice-renomination"))); + } + for (auto &ext : m.extmap) { + sdp_media.items.emplace_back(wrapSdpAttr(std::make_shared(ext))); + } + if (m.direction != RtpDirection::invalid) { + sdp_media.items.emplace_back(wrapSdpAttr(std::make_shared(m.direction))); + } + if (m.rtcp_addr.port) { + sdp_media.items.emplace_back(wrapSdpAttr(std::make_shared(m.rtcp_addr))); + } + if (m.rtcp_mux) { + sdp_media.items.emplace_back(wrapSdpAttr(std::make_shared("rtcp-mux"))); + } + if (m.rtcp_rsize) { + sdp_media.items.emplace_back(wrapSdpAttr(std::make_shared("rtcp-rsize"))); + } + + if(m.type != TrackApplication) { + for (auto &p : m.plan) { + auto rtp_map = std::make_shared(); + rtp_map->pt = p.pt; + rtp_map->codec = p.codec; + rtp_map->sample_rate = p.sample_rate; + rtp_map->channel = p.channel; + sdp_media.items.emplace_back(wrapSdpAttr(std::move(rtp_map))); + + for (auto &fb : p.rtcp_fb) { + auto rtcp_fb = std::make_shared(); + rtcp_fb->pt = p.pt; + rtcp_fb->rtcp_type = fb; + sdp_media.items.emplace_back(wrapSdpAttr(std::move(rtcp_fb))); + } + + if (!p.fmtp.empty()) { + auto fmtp = std::make_shared(); + fmtp->pt = p.pt; + fmtp->arr = p.fmtp; + sdp_media.items.emplace_back(wrapSdpAttr(std::move(fmtp))); + } + } + + if (!m.rtp_ssrc.empty() && !m.rtx_ssrc.empty()) { + auto group = std::make_shared(); + group->type = "FID"; + group->u.fid.rtp_ssrc = m.rtp_ssrc.ssrc; + group->u.fid.rtx_ssrc = m.rtx_ssrc.ssrc; + sdp_media.items.emplace_back(wrapSdpAttr(std::move(group))); + } + + static auto addSSRCItem = [](const RtcSSRC &rtp_ssrc, vector &items) { + SdpAttrSSRC ssrc; + ssrc.ssrc = rtp_ssrc.ssrc; + + ssrc.attribute = "cname"; + ssrc.attribute_value = rtp_ssrc.cname; + items.emplace_back(wrapSdpAttr(std::make_shared(ssrc))); + + if (!rtp_ssrc.msid.empty()) { + ssrc.attribute = "msid"; + ssrc.attribute_value = rtp_ssrc.msid; + items.emplace_back(wrapSdpAttr(std::make_shared(ssrc))); + } + + if (!rtp_ssrc.mslabel.empty()) { + ssrc.attribute = "mslabel"; + ssrc.attribute_value = rtp_ssrc.mslabel; + items.emplace_back(wrapSdpAttr(std::make_shared(ssrc))); + } + + if (!rtp_ssrc.label.empty()) { + ssrc.attribute = "label"; + ssrc.attribute_value = rtp_ssrc.label; + items.emplace_back(wrapSdpAttr(std::make_shared(ssrc))); + } + }; + if (!m.rtp_ssrc.empty()) { + addSSRCItem(m.rtp_ssrc, sdp_media.items); + } + if (!m.rtx_ssrc.empty()) { + addSSRCItem(m.rtx_ssrc, sdp_media.items); + } + + bool enable_sim = false; + if (!m.rtp_ssrc_low.empty() && !m.rtp_ssrc_mid.empty() && !m.rtp_ssrc_high.empty()) { + auto group = std::make_shared(); + group->type = "SIM"; + group->u.sim.rtp_ssrc_low = m.rtp_ssrc_low.ssrc; + group->u.sim.rtp_ssrc_mid = m.rtp_ssrc_mid.ssrc; + group->u.sim.rtp_ssrc_high = m.rtp_ssrc_high.ssrc; + sdp_media.items.emplace_back(wrapSdpAttr(std::move(group))); + enable_sim = true; + } + if (enable_sim) { + addSSRCItem(m.rtp_ssrc_low, sdp_media.items); + addSSRCItem(m.rtp_ssrc_mid, sdp_media.items); + addSSRCItem(m.rtp_ssrc_high, sdp_media.items); + } + } else { + sdp_media.items.emplace_back(wrapSdpAttr(std::make_shared(m.sctpmap))); + sdp_media.items.emplace_back(wrapSdpAttr(std::make_shared("sctp-port", to_string(m.sctp_port)))); + } + + for (auto &cand : m.candidate) { + sdp_media.items.emplace_back(wrapSdpAttr(std::make_shared(cand))); + } + } + return sdp.toString(); +} + string RtcCodecPlan::getFmtp(const char *key) const{ for (auto &item : fmtp) { if (strcasecmp(item.first.data(), key) == 0) { diff --git a/webrtc/Sdp.h b/webrtc/Sdp.h index efca5783..5cf2f0c8 100644 --- a/webrtc/Sdp.h +++ b/webrtc/Sdp.h @@ -96,6 +96,8 @@ protected: template class SdpString : public SdpItem{ public: + SdpString() = default; + SdpString(string val) {value == std::move(val);} // *=* const char* getKey() const override { static string key(1, KEY); return key.data();} }; @@ -104,6 +106,11 @@ class SdpCommon : public SdpItem { public: string key; SdpCommon(string key) { this->key = std::move(key); } + SdpCommon(string key, string val) { + this->key = std::move(key); + this->value = std::move(val); + } + const char* getKey() const override { return key.data();} }; @@ -163,6 +170,7 @@ public: void parse(const string &str) override; string toString() const override; const char* getKey() const override { return "b";} + bool empty() const {return bandwidth == 0;} }; class SdpMedia : public SdpItem { @@ -243,7 +251,7 @@ public: class SdpAttrRtcp : public SdpItem { public: // a=rtcp:9 IN IP4 0.0.0.0 - uint16_t port; + uint16_t port{0}; string nettype {"IN"}; string addrtype {"IP4"}; string address {"0.0.0.0"}; @@ -254,12 +262,16 @@ public: class SdpAttrIceUfrag : public SdpItem { public: + SdpAttrIceUfrag() = default; + SdpAttrIceUfrag(string str) {value = std::move(str);} //a=ice-ufrag:sXJ3 const char* getKey() const override { return "ice-ufrag";} }; class SdpAttrIcePwd : public SdpItem { public: + SdpAttrIcePwd() = default; + SdpAttrIcePwd(string str) {value = std::move(str);} //a=ice-pwd:yEclOTrLg1gEubBFefOqtmyV const char* getKey() const override { return "ice-pwd";} }; @@ -283,6 +295,8 @@ public: class SdpAttrSetup : public SdpItem { public: //a=setup:actpass + SdpAttrSetup() = default; + SdpAttrSetup(DtlsRole r) { role = r; } DtlsRole role{DtlsRole::actpass}; void parse(const string &str) override; string toString() const override; @@ -291,6 +305,8 @@ public: class SdpAttrMid : public SdpItem { public: + SdpAttrMid() = default; + SdpAttrMid(string val) { value = std::move(val); } //a=mid:audio const char* getKey() const override { return "mid";} }; @@ -607,6 +623,7 @@ public: void loadFrom(const string &sdp); void checkValid() const; + string toString() const; }; class RtcConfigure {