初步兼容simulcast

This commit is contained in:
xiongziliang 2021-05-08 20:27:46 +08:00
parent 826ec33c2c
commit 47dc661bb2
2 changed files with 74 additions and 21 deletions

View File

@ -761,19 +761,35 @@ void SdpAttrSimulcast::parse(const string &str) {
SDP_THROW(); SDP_THROW();
} }
direction = vec[0]; direction = vec[0];
vec = split(vec[1], ";"); rids = split(vec[1], ";");
rid0 = vec[0];
if (vec.size() > 1) {
rid1 = vec[1];
if (vec.size() > 2) {
rid2 = vec[2];
}
}
} }
string SdpAttrSimulcast::toString() const { string SdpAttrSimulcast::toString() const {
if (value.empty()) { if (value.empty()) {
value = direction + " " + rid0 + ";" + rid1 + ";" + rid2; value = direction + " ";
bool first = true;
for (auto &rid : rids) {
if (first) {
first = false;
} else {
value += ';';
}
value += rid;
}
}
return SdpItem::toString();
}
void SdpAttrRid::parse(const string &str) {
auto vec = split(str, " ");
CHECK(vec.size() >= 2);
rid = vec[0];
direction = vec[1];
}
string SdpAttrRid::toString() const {
if (value.empty()) {
value = rid + " " + direction;
} }
return SdpItem::toString(); return SdpItem::toString();
} }
@ -837,7 +853,8 @@ void RtcSession::loadFrom(const string &str, bool check) {
rtc_media.rtcp_rsize = media.getItem('a', "rtcp-rsize").operator bool(); rtc_media.rtcp_rsize = media.getItem('a', "rtcp-rsize").operator bool();
map<uint32_t, RtcSSRC> rtc_ssrc_map; map<uint32_t, RtcSSRC> rtc_ssrc_map;
for (auto &ssrc : media.getAllItem<SdpAttrSSRC>('a', "ssrc")) { auto ssrc_attr = media.getAllItem<SdpAttrSSRC>('a', "ssrc");
for (auto &ssrc : ssrc_attr) {
auto &rtc_ssrc = rtc_ssrc_map[ssrc.ssrc]; auto &rtc_ssrc = rtc_ssrc_map[ssrc.ssrc];
rtc_ssrc.ssrc = ssrc.ssrc; rtc_ssrc.ssrc = ssrc.ssrc;
if (!strcasecmp(ssrc.attribute.data(), "cname")) { if (!strcasecmp(ssrc.attribute.data(), "cname")) {
@ -880,15 +897,24 @@ void RtcSession::loadFrom(const string &str, bool check) {
} }
CHECK(rtc_media.rtp_rtx_ssrc.size() == 2); CHECK(rtc_media.rtp_rtx_ssrc.size() == 2);
} else { } else {
//没有指定ssrc-group:FID字段那么只有1个或0个ssrc auto simulcast = media.getItemClass<SdpAttrSimulcast>('a', "simulcast");
if (rtc_ssrc_map.size() == 1) { if (simulcast.empty()) {
rtc_media.rtp_rtx_ssrc.emplace_back(rtc_ssrc_map.begin()->second); //没有指定ssrc-group:FID字段,也不是simulcast那么只有1个或0个ssrc
} else if (rtc_ssrc_map.size() > 1) { if (rtc_ssrc_map.size() == 1) {
throw std::invalid_argument("sdp中不存在a=ssrc-group:FID字段,但是ssrc却大于1个"); rtc_media.rtp_rtx_ssrc.emplace_back(rtc_ssrc_map.begin()->second);
} else if (rtc_ssrc_map.size() > 1) {
throw std::invalid_argument("sdp中不存在a=ssrc-group:FID字段,但是ssrc却大于1个");
}
} else {
//开启simulcast
rtc_media.rtp_rids = simulcast.rids;
//simulcast最少要求2种方案
CHECK(rtc_media.rtp_rids.size() >= 2);
} }
} }
if (ssrc_group_sim) { if (ssrc_group_sim) {
//指定了a=ssrc-group:SIM
for (auto ssrc : ssrc_group_sim->ssrcs) { for (auto ssrc : ssrc_group_sim->ssrcs) {
auto it = rtc_ssrc_map.find(ssrc); auto it = rtc_ssrc_map.find(ssrc);
if (it == rtc_ssrc_map.end()) { if (it == rtc_ssrc_map.end()) {
@ -896,6 +922,11 @@ void RtcSession::loadFrom(const string &str, bool check) {
} }
rtc_media.rtp_ssrc_sim.emplace_back(it->second); rtc_media.rtp_ssrc_sim.emplace_back(it->second);
} }
} else if (!rtc_media.rtp_rids.empty()) {
//未指定a=ssrc-group:SIM但是指定了a=simulcast,且可能指定了ssrc
for (auto &attr : ssrc_attr) {
rtc_media.rtp_ssrc_sim.emplace_back(rtc_ssrc_map[attr.ssrc]);
}
} }
auto rtpmap_arr = media.getAllItem<SdpAttrRtpMap>('a', "rtpmap"); auto rtpmap_arr = media.getAllItem<SdpAttrRtpMap>('a', "rtpmap");
@ -1188,7 +1219,22 @@ RtcSessionSdp::Ptr RtcSession::toRtcSessionSdp() const{
group->type = "SIM"; group->type = "SIM";
sdp_media.items.emplace_back(wrapSdpAttr(std::move(group))); sdp_media.items.emplace_back(wrapSdpAttr(std::move(group)));
} }
if (m.rtp_rids.size() >= 2) {
auto simulcast = std::make_shared<SdpAttrSimulcast>();
simulcast->direction = "recv";
simulcast->rids = m.rtp_rids;
sdp_media.items.emplace_back(wrapSdpAttr(std::move(simulcast)));
for (auto &rid : m.rtp_rids) {
auto attr_rid = std::make_shared<SdpAttrRid>();
attr_rid->rid = rid;
attr_rid->direction = "recv";
sdp_media.items.emplace_back(wrapSdpAttr(std::move(attr_rid)));
}
}
} }
} else { } else {
sdp_media.items.emplace_back(wrapSdpAttr(std::make_shared<SdpAttrSctpMap>(m.sctpmap))); sdp_media.items.emplace_back(wrapSdpAttr(std::make_shared<SdpAttrSctpMap>(m.sctpmap)));
sdp_media.items.emplace_back(wrapSdpAttr(std::make_shared<SdpCommon>("sctp-port", to_string(m.sctp_port)))); sdp_media.items.emplace_back(wrapSdpAttr(std::make_shared<SdpCommon>("sctp-port", to_string(m.sctp_port))));
@ -1252,7 +1298,10 @@ void RtcMedia::checkValid() const{
CHECK(direction != RtpDirection::invalid || type == TrackApplication); CHECK(direction != RtpDirection::invalid || type == TrackApplication);
CHECK(!plan.empty() || type == TrackApplication ); CHECK(!plan.empty() || type == TrackApplication );
bool send_rtp = (direction == RtpDirection::sendonly || direction == RtpDirection::sendrecv); bool send_rtp = (direction == RtpDirection::sendonly || direction == RtpDirection::sendrecv);
CHECK(!rtp_rtx_ssrc.empty() || !send_rtp); if (rtp_rids.empty() && rtp_ssrc_sim.empty()) {
//非simulcast时检查有没有指定rtp ssrc
CHECK(!rtp_rtx_ssrc.empty() || !send_rtp);
}
#if 0 #if 0
//todo 发现Firefox(88.0)在mac平台下开启rtx后没有指定ssrc //todo 发现Firefox(88.0)在mac平台下开启rtx后没有指定ssrc
@ -1539,6 +1588,8 @@ RETRY:
answer_media.fingerprint = configure.fingerprint; answer_media.fingerprint = configure.fingerprint;
answer_media.ice_lite = configure.ice_lite; answer_media.ice_lite = configure.ice_lite;
answer_media.candidate = configure.candidate; answer_media.candidate = configure.candidate;
answer_media.rtp_rids = offer_media.rtp_rids;
answer_media.rtp_ssrc_sim = offer_media.rtp_ssrc_sim;
switch (offer_media.role) { switch (offer_media.role) {
case DtlsRole::actpass : case DtlsRole::actpass :
case DtlsRole::active : { case DtlsRole::active : {

View File

@ -475,17 +475,18 @@ public:
const char* getKey() const override { return "simulcast";} const char* getKey() const override { return "simulcast";}
void parse(const string &str) override; void parse(const string &str) override;
string toString() const override; string toString() const override;
bool empty() const { return rids.empty(); }
string direction; string direction;
string rid0; vector<string> rids;
string rid1;
string rid2;
}; };
class SdpAttrRid : public SdpItem{ class SdpAttrRid : public SdpItem{
public: public:
//todo void parse(const string &str) override;
string toString() const override;
const char* getKey() const override { return "rid";} const char* getKey() const override { return "rid";}
string direction;
string rid;
}; };
class RtcSdpBase { class RtcSdpBase {
@ -612,6 +613,7 @@ public:
//////// simulcast //////// //////// simulcast ////////
vector<RtcSSRC> rtp_ssrc_sim; vector<RtcSSRC> rtp_ssrc_sim;
vector<string> rtp_rids;
//////// rtcp //////// //////// rtcp ////////
bool rtcp_mux{false}; bool rtcp_mux{false};