mirror of
https://github.com/ZLMediaKit/ZLMediaKit.git
synced 2024-11-26 12:37:09 +08:00
初步兼容simulcast
This commit is contained in:
parent
826ec33c2c
commit
47dc661bb2
@ -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 : {
|
||||||
|
12
webrtc/Sdp.h
12
webrtc/Sdp.h
@ -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};
|
||||||
|
Loading…
Reference in New Issue
Block a user