mirror of
https://github.com/ZLMediaKit/ZLMediaKit.git
synced 2024-11-25 20:27:34 +08:00
完成sdp的分析
This commit is contained in:
parent
62036d0f5d
commit
87c53dab92
171
webrtc/Sdp.cpp
171
webrtc/Sdp.cpp
@ -189,7 +189,7 @@ SdpItem::Ptr RtcSdpBase::getItem(char key, const char *attr_key) const {
|
||||
return item;
|
||||
}
|
||||
auto attr = dynamic_pointer_cast<SdpAttr>(item);
|
||||
if (attr && attr->detail->getKey() == attr_key) {
|
||||
if (attr && !strcmp(attr->detail->getKey() , attr_key)) {
|
||||
return attr->detail;
|
||||
}
|
||||
}
|
||||
@ -554,23 +554,18 @@ string SdpAttrRtpMap::toString() const {
|
||||
return SdpItem::toString();
|
||||
}
|
||||
|
||||
void SdpAttrRtcpFb::parse(const string &str) {
|
||||
auto vec = split(str, " ");
|
||||
if (vec.size() < 2) {
|
||||
void SdpAttrRtcpFb::parse(const string &str_in) {
|
||||
auto str = str_in + "\n";
|
||||
char rtcp_type_buf[32] = {0};
|
||||
if (2 != sscanf(str.data(), "%" SCNu8 " %31[^\n]", &pt, rtcp_type_buf)) {
|
||||
SDP_THROW();
|
||||
}
|
||||
pt = atoi(vec[0].data());
|
||||
vec.erase(vec.begin());
|
||||
arr = std::move(vec);
|
||||
rtcp_type = rtcp_type_buf;
|
||||
}
|
||||
|
||||
string SdpAttrRtcpFb::toString() const {
|
||||
if (value.empty()) {
|
||||
value = to_string(pt);
|
||||
for (auto &item : arr) {
|
||||
value += ' ';
|
||||
value += item;
|
||||
}
|
||||
value = to_string(pt) + " " + rtcp_type;
|
||||
}
|
||||
return SdpItem::toString();
|
||||
}
|
||||
@ -870,6 +865,13 @@ void test_sdp(){
|
||||
}
|
||||
InfoL << sdp1.toString();
|
||||
InfoL << sdp2.toString();
|
||||
|
||||
RtcSession session1;
|
||||
session1.loadFrom(str1);
|
||||
|
||||
RtcSession session2;
|
||||
session2.loadFrom(str2);
|
||||
InfoL;
|
||||
}
|
||||
|
||||
void RtcSession::loadFrom(const string &str) {
|
||||
@ -882,32 +884,153 @@ void RtcSession::loadFrom(const string &str) {
|
||||
session_info = sdp.getSessionInfo();
|
||||
connection = sdp.getConnection();
|
||||
bandwidth = sdp.getBandwidth();
|
||||
auto group = sdp.getItemClass<SdpAttrGroup>('a', "group");
|
||||
auto mids = group.mids;
|
||||
|
||||
msid_semantic = sdp.getItemClass<SdpAttrMsidSemantic>('a', "msid-semantic");
|
||||
for (auto &media : sdp.medias) {
|
||||
auto mline = media.getItemClass<SdpMedia>('m');
|
||||
switch (mline.type) {
|
||||
case TrackVideo:
|
||||
case TrackAudio:
|
||||
case TrackApplication:
|
||||
break;
|
||||
case TrackApplication: break;
|
||||
default: throw std::invalid_argument(StrPrinter << "不识别的media类型:" << mline.toString());
|
||||
}
|
||||
RtcMedia rtc_media;
|
||||
this->media.emplace_back();
|
||||
auto &rtc_media = this->media.back();
|
||||
rtc_media.type = mline.type;
|
||||
rtc_media.mid = media.getStringItem('a', "mid");
|
||||
rtc_media.proto = mline.proto;
|
||||
rtc_media.type = mline.type;
|
||||
rtc_media.port = mline.port;
|
||||
rtc_media.direction = media.getDirection();
|
||||
rtc_media.rtp_addr = media.getItemClass<SdpConnection>('c');
|
||||
rtc_media.rtcp_addr = media.getItemClass<SdpAttrRtcp>('a',"rtcp");
|
||||
rtc_media.addr = media.getItemClass<SdpConnection>('c');
|
||||
rtc_media.ice_ufrag = media.getStringItem('a', "ice-ufrag");
|
||||
rtc_media.ice_ufrag = media.getStringItem('a',"ice-pwd");
|
||||
rtc_media.fingerprint = media.getItemClass<SdpAttrFingerprint>('a', "fingerprint");
|
||||
rtc_media.ice_pwd = media.getStringItem('a', "ice-pwd");
|
||||
rtc_media.role = media.getItemClass<SdpAttrSetup>('a', "setup").role;
|
||||
// rtc_media.rtcp_mux =
|
||||
rtc_media.fingerprint = media.getItemClass<SdpAttrFingerprint>('a', "fingerprint");
|
||||
rtc_media.ice_trickle = media.getItem('a', "ice-trickle").operator bool();
|
||||
rtc_media.ice_lite = media.getItem('a', "ice-lite").operator bool();
|
||||
rtc_media.ice_renomination = media.getItem('a', "ice-renomination").operator bool();
|
||||
rtc_media.candidate = media.getAllItem<SdpAttrCandidate>('a', "candidate");
|
||||
|
||||
if (mline.type == TrackType::TrackApplication) {
|
||||
rtc_media.sctp_port = atoi(media.getStringItem('a', "sctp-port").data());
|
||||
rtc_media.sctpmap = media.getItemClass<SdpAttrSctpMap>('a', "sctpmap");
|
||||
continue;
|
||||
}
|
||||
rtc_media.rtcp_addr = media.getItemClass<SdpAttrRtcp>('a', "rtcp");
|
||||
rtc_media.direction = media.getDirection();
|
||||
rtc_media.extmap = media.getAllItem<SdpAttrExtmap>('a', "extmap");
|
||||
rtc_media.rtcp_mux = media.getItem('a', "rtcp-mux").operator bool();
|
||||
rtc_media.rtcp_rsize = media.getItem('a', "rtcp-rsize").operator bool();
|
||||
|
||||
map<uint32_t, RtcSSRC> rtc_ssrc_map;
|
||||
for (auto &ssrc : media.getAllItem<SdpAttrSSRC>('a', "ssrc")) {
|
||||
auto &rtc_ssrc = rtc_ssrc_map[ssrc.ssrc];
|
||||
rtc_ssrc.ssrc = ssrc.ssrc;
|
||||
if (ssrc.attribute == "cname") {
|
||||
rtc_ssrc.cname = ssrc.attribute_value;
|
||||
continue;
|
||||
}
|
||||
if (ssrc.attribute == "msid") {
|
||||
rtc_ssrc.msid = ssrc.attribute_value;
|
||||
continue;
|
||||
}
|
||||
if (ssrc.attribute == "mslabel") {
|
||||
rtc_ssrc.mslabel = ssrc.attribute_value;
|
||||
continue;
|
||||
}
|
||||
if (ssrc.attribute == "label") {
|
||||
rtc_ssrc.label = ssrc.attribute_value;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t ssrc_rtp = 0, ssrc_rtx = 0, ssrc_rtp_low = 0, ssrc_rtp_mid = 0, ssrc_rtp_high = 0;
|
||||
auto ssrc_groups = media.getAllItem<SdpAttrSSRCGroup>('a', "ssrc-group");
|
||||
for (auto &group : ssrc_groups) {
|
||||
if (group.isFID()) {
|
||||
ssrc_rtp = group.u.fid.rtp_ssrc;
|
||||
ssrc_rtx = group.u.fid.rtx_ssrc;
|
||||
rtc_media.rtx = true;
|
||||
} else if (group.isSIM()) {
|
||||
rtc_media.simulcast = true;
|
||||
ssrc_rtp_low = group.u.sim.rtp_ssrc_low;
|
||||
ssrc_rtp_mid = group.u.sim.rtp_ssrc_mid;
|
||||
ssrc_rtp_high = group.u.sim.rtp_ssrc_high;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ssrc_rtp) {
|
||||
//没有指定ssrc-group字段,那么只有一个ssrc
|
||||
if (rtc_ssrc_map.size() > 1) {
|
||||
throw std::invalid_argument("sdp中不存在a=ssrc-group:FID字段,但是ssrc却有多个");
|
||||
}
|
||||
ssrc_rtp = rtc_ssrc_map.begin()->second.ssrc;
|
||||
}
|
||||
for (auto &pr : rtc_ssrc_map) {
|
||||
auto &rtc_ssrc = pr.second;
|
||||
if (rtc_ssrc.ssrc == ssrc_rtp) {
|
||||
rtc_media.rtp_ssrc = rtc_ssrc;
|
||||
}
|
||||
if (rtc_ssrc.ssrc == ssrc_rtx) {
|
||||
rtc_media.rtx_ssrc = rtc_ssrc;
|
||||
}
|
||||
if (rtc_ssrc.ssrc == ssrc_rtp_low) {
|
||||
rtc_media.rtp_ssrc_low = rtc_ssrc;
|
||||
}
|
||||
if (rtc_ssrc.ssrc == ssrc_rtp_mid) {
|
||||
rtc_media.rtp_ssrc_mid = rtc_ssrc;
|
||||
}
|
||||
if (rtc_ssrc.ssrc == ssrc_rtp_high) {
|
||||
rtc_media.rtp_ssrc_high = rtc_ssrc;
|
||||
}
|
||||
}
|
||||
|
||||
auto rtpmap_arr = media.getAllItem<SdpAttrRtpMap>('a', "rtpmap");
|
||||
auto rtcpfb_arr = media.getAllItem<SdpAttrRtcpFb>('a', "rtcp-fb");
|
||||
auto fmtp_aar = media.getAllItem<SdpAttrFmtp>('a', "fmtp");
|
||||
//方便根据pt查找rtpmap,一个pt必有一条
|
||||
map<uint8_t, SdpAttrRtpMap &> rtpmap_map;
|
||||
//方便根据pt查找rtcp-fb,一个pt可能有多条或0条
|
||||
multimap<uint8_t, SdpAttrRtcpFb &> rtcpfb_map;
|
||||
//方便根据pt查找fmtp,一个pt最多一条
|
||||
map<uint8_t, SdpAttrFmtp &> fmtp_map;
|
||||
|
||||
for (auto &rtpmap : rtpmap_arr) {
|
||||
if (!rtpmap_map.emplace(rtpmap.pt, rtpmap).second) {
|
||||
//添加失败,有多条
|
||||
throw std::invalid_argument(StrPrinter << "该pt存在多条a=rtpmap:" << rtpmap.pt);
|
||||
}
|
||||
}
|
||||
for (auto &rtpfb : rtcpfb_arr) {
|
||||
rtcpfb_map.emplace(rtpfb.pt, rtpfb);
|
||||
}
|
||||
for (auto &fmtp : fmtp_aar) {
|
||||
if (!fmtp_map.emplace(fmtp.pt, fmtp).second) {
|
||||
//添加失败,有多条
|
||||
throw std::invalid_argument(StrPrinter << "该pt存在多条a=fmtp:" << fmtp.pt);
|
||||
}
|
||||
}
|
||||
for (auto &pt : mline.fmts) {
|
||||
//遍历所有编码方案的pt
|
||||
rtc_media.plan.emplace_back();
|
||||
auto &plan = rtc_media.plan.back();
|
||||
auto rtpmap_it = rtpmap_map.find(pt);
|
||||
if (rtpmap_it == rtpmap_map.end()) {
|
||||
throw std::invalid_argument(StrPrinter << "该pt不存在相对于的a=rtpmap:" << pt);
|
||||
}
|
||||
plan.pt = rtpmap_it->second.pt;
|
||||
plan.codec = rtpmap_it->second.codec;
|
||||
plan.sample_rate = rtpmap_it->second.sample_rate;
|
||||
plan.channel = rtpmap_it->second.channel;
|
||||
auto fmtp_it = fmtp_map.find(pt);
|
||||
if (fmtp_it != fmtp_map.end()) {
|
||||
plan.fmtp = fmtp_it->second.arr;
|
||||
}
|
||||
for (auto rtpfb_it = rtcpfb_map.find(pt);
|
||||
rtpfb_it != rtcpfb_map.end() && rtpfb_it->second.pt == pt; ++rtpfb_it) {
|
||||
plan.rtcp_fb.emplace_back(rtpfb_it->second.rtcp_type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
group = sdp.getItemClass<SdpAttrGroup>('a', "group");
|
||||
}
|
||||
|
62
webrtc/Sdp.h
62
webrtc/Sdp.h
@ -294,7 +294,7 @@ class SdpAttrExtmap : public SdpItem {
|
||||
public:
|
||||
//https://aggresss.blog.csdn.net/article/details/106436703
|
||||
//a=extmap:1[/sendonly] urn:ietf:params:rtp-hdrext:ssrc-audio-level
|
||||
int index;
|
||||
uint32_t index;
|
||||
RtpDirection direction{RtpDirection::invalid};
|
||||
string ext;
|
||||
void parse(const string &str) override;
|
||||
@ -307,8 +307,8 @@ public:
|
||||
//a=rtpmap:111 opus/48000/2
|
||||
uint8_t pt;
|
||||
string codec;
|
||||
int sample_rate;
|
||||
int channel {0};
|
||||
uint32_t sample_rate;
|
||||
uint32_t channel {0};
|
||||
void parse(const string &str) override;
|
||||
string toString() const override;
|
||||
const char* getKey() const override { return "rtpmap";}
|
||||
@ -323,7 +323,7 @@ public:
|
||||
//a=rtcp-fb:120 goog-remb 支持 REMB (Receiver Estimated Maximum Bitrate) 。
|
||||
//a=rtcp-fb:120 transport-cc 支持 TCC (Transport Congest Control) 。
|
||||
uint8_t pt;
|
||||
vector<string> arr;
|
||||
string rtcp_type;
|
||||
void parse(const string &str) override;
|
||||
string toString() const override;
|
||||
const char* getKey() const override { return "rtcp-fb";}
|
||||
@ -383,6 +383,8 @@ public:
|
||||
} sim;
|
||||
} u;
|
||||
|
||||
bool isFID() const { return type == "FID"; }
|
||||
bool isSIM() const { return type == "SIM"; }
|
||||
void parse(const string &str) override;
|
||||
string toString() const override;
|
||||
const char* getKey() const override { return "ssrc-group";}
|
||||
@ -395,7 +397,7 @@ public:
|
||||
//a=sctpmap: sctpmap-number media-subtypes [streams]
|
||||
uint16_t port;
|
||||
string subtypes;
|
||||
int streams;
|
||||
uint32_t streams;
|
||||
void parse(const string &str) override;
|
||||
string toString() const override;
|
||||
const char* getKey() const override { return "sctpmap";}
|
||||
@ -426,6 +428,7 @@ public:
|
||||
vector<SdpItem::Ptr> items;
|
||||
|
||||
public:
|
||||
virtual ~RtcSdpBase() = default;
|
||||
virtual string toString() const;
|
||||
|
||||
int getVersion() const;
|
||||
@ -461,8 +464,31 @@ public:
|
||||
return item->toString();
|
||||
}
|
||||
|
||||
private:
|
||||
SdpItem::Ptr getItem(char key, const char *attr_key = nullptr) const;
|
||||
|
||||
template<typename cls>
|
||||
vector<cls> getAllItem(char key, const char *attr_key = nullptr) const {
|
||||
vector<cls> ret;
|
||||
for (auto item : items) {
|
||||
if (item->getKey()[0] == key) {
|
||||
if (!attr_key) {
|
||||
auto c = dynamic_pointer_cast<cls>(item);
|
||||
if (c) {
|
||||
ret.emplace_back(*c);
|
||||
}
|
||||
} else {
|
||||
auto attr = dynamic_pointer_cast<SdpAttr>(item);
|
||||
if (attr && !strcmp(attr->detail->getKey(), attr_key)) {
|
||||
auto c = dynamic_pointer_cast<cls>(attr->detail);
|
||||
if (c) {
|
||||
ret.emplace_back(*c);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
class RtcSessionSdp : public RtcSdpBase{
|
||||
@ -486,7 +512,7 @@ enum class RtcSSRCType {
|
||||
//ssrc相关信息
|
||||
class RtcSSRC{
|
||||
public:
|
||||
RtcSSRCType type;
|
||||
uint32_t ssrc {0};
|
||||
string cname;
|
||||
string msid;
|
||||
string mslabel;
|
||||
@ -514,15 +540,22 @@ public:
|
||||
string proto;
|
||||
|
||||
//////// rtp ////////
|
||||
RtcSSRC ssrc;
|
||||
SdpConnection rtp_addr;
|
||||
RtcSSRC rtp_ssrc;
|
||||
// for simulcast
|
||||
bool simulcast{false};
|
||||
RtcSSRC rtp_ssrc_low;
|
||||
RtcSSRC rtp_ssrc_mid;
|
||||
RtcSSRC rtp_ssrc_high;
|
||||
|
||||
SdpConnection addr;
|
||||
RtpDirection direction;
|
||||
vector<RtcCodecPlan> plan;
|
||||
|
||||
//////// rtx - rtcp ////////
|
||||
bool rtx{false};
|
||||
bool rtcp_mux;
|
||||
bool rtcp_rsize;
|
||||
uint32_t rtx_ssrc;
|
||||
RtcSSRC rtx_ssrc;
|
||||
SdpAttrRtcp rtcp_addr;
|
||||
|
||||
//////// ice ////////
|
||||
@ -539,18 +572,23 @@ public:
|
||||
|
||||
//////// extmap ////////
|
||||
vector<SdpAttrExtmap> extmap;
|
||||
|
||||
//////// sctp ////////////
|
||||
SdpAttrSctpMap sctpmap;
|
||||
uint32_t sctp_port {0};
|
||||
};
|
||||
|
||||
class RtcSession{
|
||||
public:
|
||||
int version;
|
||||
uint32_t version;
|
||||
SdpOrigin origin;
|
||||
string session_name;
|
||||
string session_info;
|
||||
SdpConnection connection;
|
||||
SdpBandwidth bandwidth;
|
||||
set<TrackType> group_bundle;
|
||||
SdpAttrMsidSemantic msid_semantic;
|
||||
vector<RtcMedia> media;
|
||||
SdpAttrGroup group;
|
||||
|
||||
void loadFrom(const string &sdp);
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user