diff --git a/3rdpart/assert.h b/3rdpart/assert.h index c3b4b1c2..e5699be1 100644 --- a/3rdpart/assert.h +++ b/3rdpart/assert.h @@ -12,19 +12,20 @@ #define ZLMEDIAKIT_ASSERT_H #include + +#ifdef __cplusplus +extern "C" { +#endif +extern void Assert_Throw(int failed, const char *exp, const char *func, const char *file, int line); +#ifdef __cplusplus +} +#endif + #ifndef NDEBUG #ifdef assert #undef assert #endif//assert - #ifdef __cplusplus - extern "C" { - #endif - extern void Assert_Throw(int failed, const char *exp, const char *func, const char *file, int line); - #ifdef __cplusplus - } - #endif - #define assert(exp) Assert_Throw(!(exp), #exp, __FUNCTION__, __FILE__, __LINE__); #else #define assert(e) ((void)0) diff --git a/webrtc/Sdp.cpp b/webrtc/Sdp.cpp index 10074f7d..9b00fd4c 100644 --- a/webrtc/Sdp.cpp +++ b/webrtc/Sdp.cpp @@ -3,10 +3,14 @@ // #include "Sdp.h" +#include "assert.h" +#include "Common/Parser.h" #include +#define CHECK(exp) Assert_Throw(!(exp), #exp, __FUNCTION__, __FILE__, __LINE__); + using onCreateSdpItem = function; -static unordered_map sdpItemCreator; +static map sdpItemCreator; template void registerSdpItem(){ @@ -89,17 +93,15 @@ static bool registerAllItem(){ return true; } -TrackType getTrackType(const string &str){ - if (str == "video") { - return TrackVideo; - } - if (str == "audio") { - return TrackAudio; - } - if (str == "application") { - return TrackApplication; - } - return TrackInvalid; +static map track_str_map = { + {"video", TrackVideo}, + {"audio", TrackAudio}, + {"application", TrackApplication} +}; + +TrackType getTrackType(const string &str) { + auto it = track_str_map.find(str); + return it == track_str_map.end() ? TrackInvalid : it->second; } const char* getTrackString(TrackType type){ @@ -111,17 +113,15 @@ const char* getTrackString(TrackType type){ } } -DtlsRole getDtlsRole(const string &str){ - if (str == "active") { - return DtlsRole::active; - } - if (str == "passive") { - return DtlsRole::passive; - } - if (str == "actpass") { - return DtlsRole::actpass; - } - return DtlsRole::invalid; +static map dtls_role_map = { + {"active", DtlsRole::active}, + {"passive", DtlsRole::passive}, + {"actpass", DtlsRole::actpass} +}; + +DtlsRole getDtlsRole(const string &str) { + auto it = dtls_role_map.find(str); + return it == dtls_role_map.end() ? DtlsRole::invalid : it->second; } const char* getDtlsRoleString(DtlsRole role){ @@ -133,20 +133,16 @@ const char* getDtlsRoleString(DtlsRole role){ } } -RtpDirection getRtpDirection(const string &str){ - if (str == "sendonly") { - return RtpDirection::sendonly; - } - if (str == "recvonly") { - return RtpDirection::recvonly; - } - if (str == "sendrecv") { - return RtpDirection::sendrecv; - } - if (str == "inactive") { - return RtpDirection::inactive; - } - return RtpDirection::invalid; +static map direction_map = { + {"sendonly", RtpDirection::sendonly}, + {"recvonly", RtpDirection::recvonly}, + {"sendrecv", RtpDirection::sendrecv}, + {"inactive", RtpDirection::inactive} +}; + +RtpDirection getRtpDirection(const string &str) { + auto it = direction_map.find(str); + return it == direction_map.end() ? RtpDirection::invalid : it->second; } const char* getRtpDirectionString(RtpDirection val){ @@ -182,14 +178,15 @@ RtpDirection RtcSdpBase::getDirection() const{ return RtpDirection::invalid; } -SdpItem::Ptr RtcSdpBase::getItem(char key, const char *attr_key) const { +SdpItem::Ptr RtcSdpBase::getItem(char key_c, const char *attr_key) const { for (auto item : items) { - if (item->getKey()[0] == key) { + string key(1, key_c); + if (strcasecmp(item->getKey(), key.data()) == 0) { if (!attr_key) { return item; } auto attr = dynamic_pointer_cast(item); - if (attr && !strcmp(attr->detail->getKey() , attr_key)) { + if (attr && !strcasecmp(attr->detail->getKey() , attr_key)) { return attr->detail; } } @@ -884,6 +881,7 @@ void RtcSession::loadFrom(const string &str) { session_info = sdp.getSessionInfo(); connection = sdp.getConnection(); bandwidth = sdp.getBandwidth(); + time = sdp.getSessionTime(); msid_semantic = sdp.getItemClass('a', "msid-semantic"); for (auto &media : sdp.medias) { auto mline = media.getItemClass('m'); @@ -1036,7 +1034,7 @@ void RtcSession::loadFrom(const string &str) { string RtcCodecPlan::getFmtp(const char *key) const{ for (auto &item : fmtp) { - if (item.first == key) { + if (strcasecmp(item.first.data(), key) == 0) { return item.second; } } @@ -1052,34 +1050,41 @@ const RtcCodecPlan *RtcMedia::getPlan(uint8_t pt) const{ return nullptr; } -void RtcMedia::checkValid() const{ - switch (direction) { - case RtpDirection::sendonly: - case RtpDirection::sendrecv: { - if (rtp_ssrc.empty()) { - throw std::invalid_argument("发送rtp但是未指定rtp ssrc"); - } - break; - } - default: break; - } +const RtcCodecPlan *RtcMedia::getPlan(const char *codec) const{ for (auto &item : plan) { - if (item.codec == "rtx") { - if (rtx_ssrc.empty()) { - throw std::invalid_argument("指定开启rtx但是未指定rtx ssrc"); - } - auto apt = atoi(item.getFmtp("apt").data()); - if (!getPlan(apt)) { - throw std::invalid_argument("找不到rtx关联的plan信息"); - } + if (strcasecmp(item.codec.data(), codec) == 0) { + return &item; } } - //todo 校验更多信息 + return nullptr; +} + +void RtcMedia::checkValid() const{ + CHECK(type != TrackInvalid); + CHECK(!mid.empty()); + CHECK(!proto.empty()); + CHECK(direction != RtpDirection::invalid || type == TrackApplication); + CHECK(!plan.empty() || type == TrackApplication ); + bool send_rtp = (direction == RtpDirection::sendonly || direction == RtpDirection::sendrecv); + CHECK(!rtp_ssrc.empty() || !send_rtp); + auto rtx_plan = getPlan("rtx"); + if (rtx_plan) { + //开启rtx后必须指定rtx_ssrc + CHECK(!rtx_ssrc.empty() || !send_rtp); + auto apt = atoi(rtx_plan->getFmtp("apt").data()); + //开启rtx后必须指定其关联的其他的plan + CHECK(getPlan(apt)); + } } void RtcSession::checkValid() const{ + CHECK(version == 0); + CHECK(!origin.empty()); + CHECK(!session_name.empty()); + CHECK(!msid_semantic.empty()); + CHECK(!media.empty()); + CHECK(group.mids.size() <= media.size()); for (auto &item : media) { item.checkValid(); } - //todo 校验更多信息 } \ No newline at end of file diff --git a/webrtc/Sdp.h b/webrtc/Sdp.h index 60f8c6b8..32c92cb6 100644 --- a/webrtc/Sdp.h +++ b/webrtc/Sdp.h @@ -134,6 +134,10 @@ public: void parse(const string &str) override; string toString() const override; const char* getKey() const override { return "o";} + bool empty() const { + return username.empty() || session_id.empty() || session_version.empty() + || nettype.empty() || addrtype.empty() || address.empty(); + } }; class SdpConnection : public SdpItem { @@ -233,6 +237,9 @@ public: void parse(const string &str) override; string toString() const override; const char* getKey() const override { return "msid-semantic";} + bool empty() const { + return msid.empty(); + } }; class SdpAttrRtcp : public SdpItem { @@ -467,10 +474,11 @@ public: SdpItem::Ptr getItem(char key, const char *attr_key = nullptr) const; template - vector getAllItem(char key, const char *attr_key = nullptr) const { + vector getAllItem(char key_c, const char *attr_key = nullptr) const { vector ret; for (auto item : items) { - if (item->getKey()[0] == key) { + string key(1, key_c); + if (strcasecmp(item->getKey(), key.data()) == 0) { if (!attr_key) { auto c = dynamic_pointer_cast(item); if (c) { @@ -478,7 +486,7 @@ public: } } else { auto attr = dynamic_pointer_cast(item); - if (attr && !strcmp(attr->detail->getKey(), attr_key)) { + if (attr && !strcasecmp(attr->detail->getKey(), attr_key)) { auto c = dynamic_pointer_cast(attr->detail); if (c) { ret.emplace_back(*c); @@ -518,7 +526,7 @@ public: string mslabel; string label; - bool empty() const {return ssrc == 0;} + bool empty() const {return ssrc == 0 && cname.empty();} }; //rtc传输编码方案 @@ -582,6 +590,7 @@ public: void checkValid() const; const RtcCodecPlan *getPlan(uint8_t pt) const; + const RtcCodecPlan *getPlan(const char *codec) const; }; class RtcSession{ @@ -590,6 +599,7 @@ public: SdpOrigin origin; string session_name; string session_info; + SdpTime time; SdpConnection connection; SdpBandwidth bandwidth; SdpAttrMsidSemantic msid_semantic;