diff --git a/src/Common/Parser.cpp b/src/Common/Parser.cpp index 6fa5aa2d..5ac280b9 100644 --- a/src/Common/Parser.cpp +++ b/src/Common/Parser.cpp @@ -320,7 +320,6 @@ void splitUrl(const std::string &url, std::string &host, uint16_t &port) { host = url.substr(0, pos); checkHost(host); } - #if 0 //测试代码 static onceToken token([](){ diff --git a/src/Rtsp/Rtsp.cpp b/src/Rtsp/Rtsp.cpp index 2e3618da..b2d2b86b 100644 --- a/src/Rtsp/Rtsp.cpp +++ b/src/Rtsp/Rtsp.cpp @@ -8,12 +8,12 @@ * may be found in the AUTHORS file in the root of the source tree. */ -#include -#include #include "Rtsp.h" #include "Common/Parser.h" #include "Common/config.h" #include "Network/Socket.h" +#include +#include using namespace std; using namespace toolkit; @@ -22,7 +22,8 @@ namespace mediakit { int RtpPayload::getClockRate(int pt) { switch (pt) { -#define SWITCH_CASE(name, type, value, clock_rate, channel, codec_id) case value : return clock_rate; +#define SWITCH_CASE(name, type, value, clock_rate, channel, codec_id) \ + case value: return clock_rate; RTP_PT_MAP(SWITCH_CASE) #undef SWITCH_CASE default: return 90000; @@ -31,7 +32,8 @@ int RtpPayload::getClockRate(int pt) { TrackType RtpPayload::getTrackType(int pt) { switch (pt) { -#define SWITCH_CASE(name, type, value, clock_rate, channel, codec_id) case value : return type; +#define SWITCH_CASE(name, type, value, clock_rate, channel, codec_id) \ + case value: return type; RTP_PT_MAP(SWITCH_CASE) #undef SWITCH_CASE default: return TrackInvalid; @@ -40,7 +42,8 @@ TrackType RtpPayload::getTrackType(int pt) { int RtpPayload::getAudioChannel(int pt) { switch (pt) { -#define SWITCH_CASE(name, type, value, clock_rate, channel, codec_id) case value : return channel; +#define SWITCH_CASE(name, type, value, clock_rate, channel, codec_id) \ + case value: return channel; RTP_PT_MAP(SWITCH_CASE) #undef SWITCH_CASE default: return 1; @@ -49,7 +52,8 @@ int RtpPayload::getAudioChannel(int pt) { const char *RtpPayload::getName(int pt) { switch (pt) { -#define SWITCH_CASE(name, type, value, clock_rate, channel, codec_id) case value : return #name; +#define SWITCH_CASE(name, type, value, clock_rate, channel, codec_id) \ + case value: return #name; RTP_PT_MAP(SWITCH_CASE) #undef SWITCH_CASE default: return "unknown payload type"; @@ -58,7 +62,8 @@ const char *RtpPayload::getName(int pt) { CodecId RtpPayload::getCodecId(int pt) { switch (pt) { -#define SWITCH_CASE(name, type, value, clock_rate, channel, codec_id) case value : return codec_id; +#define SWITCH_CASE(name, type, value, clock_rate, channel, codec_id) \ + case value: return codec_id; RTP_PT_MAP(SWITCH_CASE) #undef SWITCH_CASE default: return CodecInvalid; @@ -85,7 +90,8 @@ static void getAttrSdp(const multimap &attr, _StrPrinter &printe string SdpTrack::getName() const { switch (_pt) { -#define SWITCH_CASE(name, type, value, clock_rate, channel, codec_id) case value : return #name; +#define SWITCH_CASE(name, type, value, clock_rate, channel, codec_id) \ + case value: return #name; RTP_PT_MAP(SWITCH_CASE) #undef SWITCH_CASE default: return _codec; @@ -94,7 +100,7 @@ string SdpTrack::getName() const { string SdpTrack::getControlUrl(const string &base_url) const { if (_control.find("://") != string::npos) { - //以rtsp://开头 + // 以rtsp://开头 return _control; } return base_url + "/" + _control; @@ -143,6 +149,7 @@ static TrackType toTrackType(const string &str) { } void SdpParser::load(const string &sdp) { + std::multimap global_infos; { _track_vec.clear(); SdpTrack::Ptr track = std::make_shared(); @@ -159,17 +166,23 @@ void SdpParser::load(const string &sdp) { string opt_val = line.substr(2); switch (opt) { case 't': - track->_t = opt_val; + if (_track_vec.empty()) + global_infos.emplace(opt, opt_val); + else + track->_t = opt_val; break; case 'b': - track->_b = opt_val; + if (_track_vec.empty()) + global_infos.emplace(opt, opt_val); + else + track->_b = opt_val; break; case 'm': { track = std::make_shared(); int pt, port, port_count; - char rtp[16] = {0}, type[16]; - if (4 == sscanf(opt_val.data(), " %15[^ ] %d %15[^ ] %d", type, &port, rtp, &pt) || - 5 == sscanf(opt_val.data(), " %15[^ ] %d/%d %15[^ ] %d", type, &port, &port_count, rtp, &pt)) { + char rtp[16] = { 0 }, type[16]; + if (4 == sscanf(opt_val.data(), " %15[^ ] %d %15[^ ] %d", type, &port, rtp, &pt) + || 5 == sscanf(opt_val.data(), " %15[^ ] %d/%d %15[^ ] %d", type, &port, &port_count, rtp, &pt)) { track->_pt = pt; track->_samplerate = RtpPayload::getClockRate(pt); track->_channel = RtpPayload::getAudioChannel(pt); @@ -182,29 +195,55 @@ void SdpParser::load(const string &sdp) { case 'a': { string attr = findSubString(opt_val.data(), nullptr, ":"); if (attr.empty()) { - track->_attr.emplace(opt_val, ""); + if (_track_vec.empty()) + global_infos.emplace(opt, opt_val); + else + track->_attr.emplace(opt_val, ""); } else { - track->_attr.emplace(attr, findSubString(opt_val.data(), ":", nullptr)); + if (_track_vec.empty()) + global_infos.emplace(opt, opt_val); + else + track->_attr.emplace(attr, findSubString(opt_val.data(), ":", nullptr)); + } + break; + } + default: { + if (_track_vec.empty()) { + global_infos.emplace(opt, opt_val); + } else { + track->_other[opt] = opt_val; } break; } - default: track->_other[opt] = opt_val; break; } } } + for (auto &info : global_infos) { + std::string attr; + switch (info.first) { + case 'a': + attr = findSubString(info.second.data(), nullptr, ":"); + if (attr == "control") { + _control_url = findSubString(info.second.data(), ":", nullptr); + } + break; + + default: break; + } + } for (auto &track_ptr : _track_vec) { auto &track = *track_ptr; auto it = track._attr.find("range"); if (it != track._attr.end()) { - char name[16] = {0}, start[16] = {0}, end[16] = {0}; + char name[16] = { 0 }, start[16] = { 0 }, end[16] = { 0 }; int ret = sscanf(it->second.data(), "%15[^=]=%15[^-]-%15s", name, start, end); if (3 == ret || 2 == ret) { if (strcmp(start, "now") == 0) { strcpy(start, "0"); } - track._start = (float) atof(start); - track._end = (float) atof(end); + track._start = (float)atof(start); + track._end = (float)atof(end); track._duration = track._end - track._start; } } @@ -212,11 +251,11 @@ void SdpParser::load(const string &sdp) { for (it = track._attr.find("rtpmap"); it != track._attr.end() && it->first == "rtpmap";) { auto &rtpmap = it->second; int pt, samplerate, channel; - char codec[16] = {0}; + char codec[16] = { 0 }; sscanf(rtpmap.data(), "%d", &pt); if (track._pt != pt && track._pt != 0xff) { - //pt不匹配 + // pt不匹配 it = track._attr.erase(it); continue; } @@ -230,18 +269,18 @@ void SdpParser::load(const string &sdp) { track._samplerate = samplerate; } if (!track._samplerate && track._type == TrackVideo) { - //未设置视频采样率时,赋值为90000 + // 未设置视频采样率时,赋值为90000 track._samplerate = 90000; } ++it; } - for (it = track._attr.find("fmtp"); it != track._attr.end() && it->first == "fmtp"; ) { + for (it = track._attr.find("fmtp"); it != track._attr.end() && it->first == "fmtp";) { auto &fmtp = it->second; int pt; sscanf(fmtp.data(), "%d", &pt); if (track._pt != pt && track._pt != 0xff) { - //pt不匹配 + // pt不匹配 it = track._attr.erase(it); continue; } @@ -315,8 +354,16 @@ string SdpParser::toString() const { return title + video + audio; } -template -class PortManager : public std::enable_shared_from_this > { +std::string SdpParser::getControlUrl(const std::string &url) const { + if (_control_url.find("://") != string::npos) { + // 以rtsp://开头 + return _control_url; + } + return url; +} + +template +class PortManager : public std::enable_shared_from_this> { public: PortManager() { static auto func = [](const string &str, int index) { @@ -326,11 +373,11 @@ public: }; GET_CONFIG_FUNC(uint16_t, s_min_port, RtpProxy::kPortRange, [](const string &str) { return func(str, 0); }); GET_CONFIG_FUNC(uint16_t, s_max_port, RtpProxy::kPortRange, [](const string &str) { return func(str, 1); }); - assert(s_max_port >= s_min_port + 36 -1); + assert(s_max_port >= s_min_port + 36 - 1); setRange((s_min_port + 1) / 2, s_max_port / 2); } - static PortManager& Instance() { + static PortManager &Instance() { static auto instance = std::make_shared(); return *instance; } @@ -344,12 +391,12 @@ public: } if (is_udp) { if (!sock0->bindUdpSock(2 * *sock_pair, local_ip.data(), re_use_port)) { - //分配端口失败 + // 分配端口失败 throw runtime_error("open udp socket[0] failed"); } if (!sock1->bindUdpSock(2 * *sock_pair + 1, local_ip.data(), re_use_port)) { - //分配端口失败 + // 分配端口失败 throw runtime_error("open udp socket[1] failed"); } @@ -359,12 +406,12 @@ public: sock1->setOnAccept(on_cycle); } else { if (!sock0->listen(2 * *sock_pair, local_ip.data())) { - //分配端口失败 + // 分配端口失败 throw runtime_error("listen tcp socket[0] failed"); } if (!sock1->listen(2 * *sock_pair + 1, local_ip.data())) { - //分配端口失败 + // 分配端口失败 throw runtime_error("listen tcp socket[1] failed"); } @@ -400,7 +447,7 @@ private: return; } InfoL << "return port to pool:" << 2 * pos << "-" << 2 * pos + 1; - //回收端口号 + // 回收端口号 lock_guard lck(strong_self->_pool_mtx); strong_self->_port_pair_pool.emplace_back(pos); }); @@ -416,7 +463,7 @@ void makeSockPair(std::pair &pair, const string &local int try_count = 0; while (true) { try { - //udp和tcp端口池使用相同算法和范围分配,但是互不相干 + // udp和tcp端口池使用相同算法和范围分配,但是互不相干 if (is_udp) { PortManager<0>::Instance().makeSockPair(pair, local_ip, re_use_port, is_udp); } else { @@ -433,9 +480,9 @@ void makeSockPair(std::pair &pair, const string &local } string printSSRC(uint32_t ui32Ssrc) { - char tmp[9] = {0}; + char tmp[9] = { 0 }; ui32Ssrc = htonl(ui32Ssrc); - uint8_t *pSsrc = (uint8_t *) &ui32Ssrc; + uint8_t *pSsrc = (uint8_t *)&ui32Ssrc; for (int i = 0; i < 4; i++) { sprintf(tmp + 2 * i, "%02X", pSsrc[i]); } @@ -470,12 +517,10 @@ Buffer::Ptr makeRtpOverTcpPrefix(uint16_t size, uint8_t interleaved) { return rtp_tcp; } -#define AV_RB16(x) \ - ((((const uint8_t*)(x))[0] << 8) | \ - ((const uint8_t*)(x))[1]) +#define AV_RB16(x) ((((const uint8_t *)(x))[0] << 8) | ((const uint8_t *)(x))[1]) size_t RtpHeader::getCsrcSize() const { - //每个csrc占用4字节 + // 每个csrc占用4字节 return csrc << 2; } @@ -487,18 +532,18 @@ uint8_t *RtpHeader::getCsrcData() { } size_t RtpHeader::getExtSize() const { - //rtp有ext + // rtp有ext if (!ext) { return 0; } auto ext_ptr = &payload + getCsrcSize(); - //uint16_t reserved = AV_RB16(ext_ptr); - //每个ext占用4字节 + // uint16_t reserved = AV_RB16(ext_ptr); + // 每个ext占用4字节 return AV_RB16(ext_ptr + 2) << 2; } uint16_t RtpHeader::getExtReserved() const { - //rtp有ext + // rtp有ext if (!ext) { return 0; } @@ -511,12 +556,12 @@ uint8_t *RtpHeader::getExtData() { return nullptr; } auto ext_ptr = &payload + getCsrcSize(); - //多出的4个字节分别为reserved、ext_len + // 多出的4个字节分别为reserved、ext_len return ext_ptr + 4; } size_t RtpHeader::getPayloadOffset() const { - //有ext时,还需要忽略reserved、ext_len 4个字节 + // 有ext时,还需要忽略reserved、ext_len 4个字节 return getCsrcSize() + (ext ? (4 + getExtSize()) : 0); } @@ -528,7 +573,7 @@ size_t RtpHeader::getPaddingSize(size_t rtp_size) const { if (!padding) { return 0; } - auto end = (uint8_t *) this + rtp_size - 1; + auto end = (uint8_t *)this + rtp_size - 1; return *end; } @@ -539,12 +584,12 @@ ssize_t RtpHeader::getPayloadSize(size_t rtp_size) const { string RtpHeader::dumpString(size_t rtp_size) const { _StrPrinter printer; - printer << "version:" << (int) version << "\r\n"; + printer << "version:" << (int)version << "\r\n"; printer << "padding:" << getPaddingSize(rtp_size) << "\r\n"; printer << "ext:" << getExtSize() << "\r\n"; printer << "csrc:" << getCsrcSize() << "\r\n"; - printer << "mark:" << (int) mark << "\r\n"; - printer << "pt:" << (int) pt << "\r\n"; + printer << "mark:" << (int)mark << "\r\n"; + printer << "pt:" << (int)pt << "\r\n"; printer << "seq:" << ntohs(seq) << "\r\n"; printer << "stamp:" << ntohl(stamp) << "\r\n"; printer << "ssrc:" << ntohl(ssrc) << "\r\n"; @@ -557,16 +602,16 @@ string RtpHeader::dumpString(size_t rtp_size) const { /////////////////////////////////////////////////////////////////////// RtpHeader *RtpPacket::getHeader() { - //需除去rtcp over tcp 4个字节长度 - return (RtpHeader *) (data() + RtpPacket::kRtpTcpHeaderSize); + // 需除去rtcp over tcp 4个字节长度 + return (RtpHeader *)(data() + RtpPacket::kRtpTcpHeaderSize); } const RtpHeader *RtpPacket::getHeader() const { - return (RtpHeader *) (data() + RtpPacket::kRtpTcpHeaderSize); + return (RtpHeader *)(data() + RtpPacket::kRtpTcpHeaderSize); } string RtpPacket::dumpString() const { - return ((RtpPacket *) this)->getHeader()->dumpString(size() - RtpPacket::kRtpTcpHeaderSize); + return ((RtpPacket *)this)->getHeader()->dumpString(size() - RtpPacket::kRtpTcpHeaderSize); } uint16_t RtpPacket::getSeq() const { @@ -590,7 +635,7 @@ uint8_t *RtpPacket::getPayload() { } size_t RtpPacket::getPayloadSize() const { - //需除去rtcp over tcp 4个字节长度 + // 需除去rtcp over tcp 4个字节长度 return getHeader()->getPayloadSize(size() - kRtpTcpHeaderSize); } @@ -608,23 +653,22 @@ RtpPacket::Ptr RtpPacket::create() { #endif } - /** -* 构造title类型sdp -* @param dur_sec rtsp点播时长,0代表直播,单位秒 -* @param header 自定义sdp描述 -* @param version sdp版本 -*/ + * 构造title类型sdp + * @param dur_sec rtsp点播时长,0代表直播,单位秒 + * @param header 自定义sdp描述 + * @param version sdp版本 + */ -TitleSdp::TitleSdp(float dur_sec, const std::map& header, int version) : Sdp(0, 0) { +TitleSdp::TitleSdp(float dur_sec, const std::map &header, int version) + : Sdp(0, 0) { _printer << "v=" << version << "\r\n"; if (!header.empty()) { for (auto &pr : header) { _printer << pr.first << "=" << pr.second << "\r\n"; } - } - else { + } else { _printer << "o=- 0 0 IN IP4 0.0.0.0\r\n"; _printer << "s=Streamed by " << kServerName << "\r\n"; _printer << "c=IN IP4 0.0.0.0\r\n"; @@ -632,18 +676,17 @@ TitleSdp::TitleSdp(float dur_sec, const std::map& head } if (dur_sec <= 0) { - //直播 + // 直播 _printer << "a=range:npt=now-\r\n"; - } - else { - //点播 + } else { + // 点播 _dur_sec = dur_sec; _printer << "a=range:npt=0-" << dur_sec << "\r\n"; } _printer << "a=control:*\r\n"; } -}//namespace mediakit +} // namespace mediakit namespace toolkit { StatisticImp(mediakit::RtpPacket); diff --git a/src/Rtsp/Rtsp.h b/src/Rtsp/Rtsp.h index 6bb19d8d..55e8ee5a 100644 --- a/src/Rtsp/Rtsp.h +++ b/src/Rtsp/Rtsp.h @@ -11,13 +11,13 @@ #ifndef RTSP_RTSP_H_ #define RTSP_RTSP_H_ -#include -#include -#include -#include #include "Common/macros.h" #include "Extension/Frame.h" #include "Network/Socket.h" +#include +#include +#include +#include namespace mediakit { @@ -29,40 +29,41 @@ typedef enum { RTP_MULTICAST = 2, } eRtpType; -#define RTP_PT_MAP(XX) \ - XX(PCMU, TrackAudio, 0, 8000, 1, CodecG711U) \ - XX(GSM, TrackAudio , 3, 8000, 1, CodecInvalid) \ - XX(G723, TrackAudio, 4, 8000, 1, CodecInvalid) \ - XX(DVI4_8000, TrackAudio, 5, 8000, 1, CodecInvalid) \ - XX(DVI4_16000, TrackAudio, 6, 16000, 1, CodecInvalid) \ - XX(LPC, TrackAudio, 7, 8000, 1, CodecInvalid) \ - XX(PCMA, TrackAudio, 8, 8000, 1, CodecG711A) \ - XX(G722, TrackAudio, 9, 8000, 1, CodecInvalid) \ - XX(L16_Stereo, TrackAudio, 10, 44100, 2, CodecInvalid) \ - XX(L16_Mono, TrackAudio, 11, 44100, 1, CodecInvalid) \ - XX(QCELP, TrackAudio, 12, 8000, 1, CodecInvalid) \ - XX(CN, TrackAudio, 13, 8000, 1, CodecInvalid) \ - XX(MPA, TrackAudio, 14, 90000, 1, CodecInvalid) \ - XX(G728, TrackAudio, 15, 8000, 1, CodecInvalid) \ - XX(DVI4_11025, TrackAudio, 16, 11025, 1, CodecInvalid) \ - XX(DVI4_22050, TrackAudio, 17, 22050, 1, CodecInvalid) \ - XX(G729, TrackAudio, 18, 8000, 1, CodecInvalid) \ - XX(CelB, TrackVideo, 25, 90000, 1, CodecInvalid) \ - XX(JPEG, TrackVideo, 26, 90000, 1, CodecJPEG) \ - XX(nv, TrackVideo, 28, 90000, 1, CodecInvalid) \ - XX(H261, TrackVideo, 31, 90000, 1, CodecInvalid) \ - XX(MPV, TrackVideo, 32, 90000, 1, CodecInvalid) \ - XX(MP2T, TrackVideo, 33, 90000, 1, CodecInvalid) \ - XX(H263, TrackVideo, 34, 90000, 1, CodecInvalid) \ +#define RTP_PT_MAP(XX) \ + XX(PCMU, TrackAudio, 0, 8000, 1, CodecG711U) \ + XX(GSM, TrackAudio, 3, 8000, 1, CodecInvalid) \ + XX(G723, TrackAudio, 4, 8000, 1, CodecInvalid) \ + XX(DVI4_8000, TrackAudio, 5, 8000, 1, CodecInvalid) \ + XX(DVI4_16000, TrackAudio, 6, 16000, 1, CodecInvalid) \ + XX(LPC, TrackAudio, 7, 8000, 1, CodecInvalid) \ + XX(PCMA, TrackAudio, 8, 8000, 1, CodecG711A) \ + XX(G722, TrackAudio, 9, 8000, 1, CodecInvalid) \ + XX(L16_Stereo, TrackAudio, 10, 44100, 2, CodecInvalid) \ + XX(L16_Mono, TrackAudio, 11, 44100, 1, CodecInvalid) \ + XX(QCELP, TrackAudio, 12, 8000, 1, CodecInvalid) \ + XX(CN, TrackAudio, 13, 8000, 1, CodecInvalid) \ + XX(MPA, TrackAudio, 14, 90000, 1, CodecInvalid) \ + XX(G728, TrackAudio, 15, 8000, 1, CodecInvalid) \ + XX(DVI4_11025, TrackAudio, 16, 11025, 1, CodecInvalid) \ + XX(DVI4_22050, TrackAudio, 17, 22050, 1, CodecInvalid) \ + XX(G729, TrackAudio, 18, 8000, 1, CodecInvalid) \ + XX(CelB, TrackVideo, 25, 90000, 1, CodecInvalid) \ + XX(JPEG, TrackVideo, 26, 90000, 1, CodecJPEG) \ + XX(nv, TrackVideo, 28, 90000, 1, CodecInvalid) \ + XX(H261, TrackVideo, 31, 90000, 1, CodecInvalid) \ + XX(MPV, TrackVideo, 32, 90000, 1, CodecInvalid) \ + XX(MP2T, TrackVideo, 33, 90000, 1, CodecInvalid) \ + XX(H263, TrackVideo, 34, 90000, 1, CodecInvalid) typedef enum { -#define ENUM_DEF(name, type, value, clock_rate, channel, codec_id) PT_ ## name = value, +#define ENUM_DEF(name, type, value, clock_rate, channel, codec_id) PT_##name = value, RTP_PT_MAP(ENUM_DEF) #undef ENUM_DEF - PT_MAX = 128 + PT_MAX + = 128 } PayloadType; -}; +}; // namespace Rtsp #if defined(_WIN32) #pragma pack(push, 1) @@ -71,65 +72,65 @@ typedef enum { class RtpHeader { public: #if __BYTE_ORDER == __BIG_ENDIAN - //版本号,固定为2 - uint32_t version: 2; - //padding - uint32_t padding: 1; - //扩展 - uint32_t ext: 1; - //csrc - uint32_t csrc: 4; - //mark - uint32_t mark: 1; - //负载类型 - uint32_t pt: 7; + // 版本号,固定为2 + uint32_t version : 2; + // padding + uint32_t padding : 1; + // 扩展 + uint32_t ext : 1; + // csrc + uint32_t csrc : 4; + // mark + uint32_t mark : 1; + // 负载类型 + uint32_t pt : 7; #else - //csrc - uint32_t csrc: 4; - //扩展 - uint32_t ext: 1; - //padding - uint32_t padding: 1; - //版本号,固定为2 - uint32_t version: 2; - //负载类型 - uint32_t pt: 7; - //mark - uint32_t mark: 1; + // csrc + uint32_t csrc : 4; + // 扩展 + uint32_t ext : 1; + // padding + uint32_t padding : 1; + // 版本号,固定为2 + uint32_t version : 2; + // 负载类型 + uint32_t pt : 7; + // mark + uint32_t mark : 1; #endif - //序列号 - uint32_t seq: 16; - //时间戳 + // 序列号 + uint32_t seq : 16; + // 时间戳 uint32_t stamp; - //ssrc + // ssrc uint32_t ssrc; - //负载,如果有csrc和ext,前面为 4 * csrc + (4 + 4 * ext_len) + // 负载,如果有csrc和ext,前面为 4 * csrc + (4 + 4 * ext_len) uint8_t payload; public: - //返回csrc字段字节长度 + // 返回csrc字段字节长度 size_t getCsrcSize() const; - //返回csrc字段首地址,不存在时返回nullptr + // 返回csrc字段首地址,不存在时返回nullptr uint8_t *getCsrcData(); - //返回ext字段字节长度 + // 返回ext字段字节长度 size_t getExtSize() const; - //返回ext reserved值 + // 返回ext reserved值 uint16_t getExtReserved() const; - //返回ext段首地址,不存在时返回nullptr + // 返回ext段首地址,不存在时返回nullptr uint8_t *getExtData(); - //返回有效负载指针,跳过csrc、ext - uint8_t* getPayloadData(); - //返回有效负载总长度,不包括csrc、ext、padding + // 返回有效负载指针,跳过csrc、ext + uint8_t *getPayloadData(); + // 返回有效负载总长度,不包括csrc、ext、padding ssize_t getPayloadSize(size_t rtp_size) const; - //打印调试信息 + // 打印调试信息 std::string dumpString(size_t rtp_size) const; private: - //返回有效负载偏移量 + // 返回有效负载偏移量 size_t getPayloadOffset() const; - //返回padding长度 + // 返回padding长度 size_t getPaddingSize(size_t rtp_size) const; } PACKED; @@ -137,40 +138,36 @@ private: #pragma pack(pop) #endif // defined(_WIN32) -//此rtp为rtp over tcp形式,需要忽略前4个字节 -class RtpPacket : public toolkit::BufferRaw{ +// 此rtp为rtp over tcp形式,需要忽略前4个字节 +class RtpPacket : public toolkit::BufferRaw { public: using Ptr = std::shared_ptr; - enum { - kRtpVersion = 2, - kRtpHeaderSize = 12, - kRtpTcpHeaderSize = 4 - }; + enum { kRtpVersion = 2, kRtpHeaderSize = 12, kRtpTcpHeaderSize = 4 }; - //获取rtp头 - RtpHeader* getHeader(); - const RtpHeader* getHeader() const; + // 获取rtp头 + RtpHeader *getHeader(); + const RtpHeader *getHeader() const; - //打印调试信息 + // 打印调试信息 std::string dumpString() const; - //主机字节序的seq + // 主机字节序的seq uint16_t getSeq() const; uint32_t getStamp() const; - //主机字节序的时间戳,已经转换为毫秒 + // 主机字节序的时间戳,已经转换为毫秒 uint64_t getStampMS(bool ntp = true) const; - //主机字节序的ssrc + // 主机字节序的ssrc uint32_t getSSRC() const; - //有效负载,跳过csrc、ext - uint8_t* getPayload(); - //有效负载长度,不包括csrc、ext、padding + // 有效负载,跳过csrc、ext + uint8_t *getPayload(); + // 有效负载长度,不包括csrc、ext、padding size_t getPayloadSize() const; - //音视频类型 + // 音视频类型 TrackType type; - //音频为采样率,视频一般为90000 + // 音频为采样率,视频一般为90000 uint32_t sample_rate; - //ntp时间戳 + // ntp时间戳 uint64_t ntp_stamp; static Ptr create(); @@ -180,7 +177,7 @@ private: RtpPacket() = default; private: - //对象个数统计 + // 对象个数统计 toolkit::ObjectStatistic _statistic; }; @@ -229,7 +226,7 @@ public: uint8_t _interleaved = 0; uint16_t _seq = 0; uint32_t _ssrc = 0; - //时间戳,单位毫秒 + // 时间戳,单位毫秒 uint32_t _time_stamp = 0; }; @@ -246,15 +243,17 @@ public: SdpTrack::Ptr getTrack(TrackType type) const; std::vector getAvailableTrack() const; std::string toString() const; + std::string getControlUrl(const std::string &url) const; private: std::vector _track_vec; + std::string _control_url; }; /** -* rtsp sdp基类 -*/ -class Sdp : public CodecInfo{ + * rtsp sdp基类 + */ +class Sdp : public CodecInfo { public: using Ptr = std::shared_ptr; @@ -263,7 +262,7 @@ public: * @param sample_rate 采样率 * @param payload_type pt类型 */ - Sdp(uint32_t sample_rate, uint8_t payload_type){ + Sdp(uint32_t sample_rate, uint8_t payload_type) { _sample_rate = sample_rate; _payload_type = payload_type; } @@ -274,23 +273,19 @@ public: * 获取sdp字符串 * @return */ - virtual std::string getSdp() const = 0; + virtual std::string getSdp() const = 0; /** * 获取pt * @return */ - uint8_t getPayloadType() const{ - return _payload_type; - } + uint8_t getPayloadType() const { return _payload_type; } /** * 获取采样率 * @return */ - uint32_t getSampleRate() const{ - return _sample_rate; - } + uint32_t getSampleRate() const { return _sample_rate; } private: uint8_t _payload_type; @@ -298,9 +293,9 @@ private: }; /** -* sdp中除音视频外的其他描述部分 -*/ -class TitleSdp : public Sdp{ + * sdp中除音视频外的其他描述部分 + */ +class TitleSdp : public Sdp { public: using Ptr = std::shared_ptr; /** @@ -309,36 +304,28 @@ public: * @param header 自定义sdp描述 * @param version sdp版本 */ - TitleSdp(float dur_sec = 0, - const std::map &header = std::map(), - int version = 0); + TitleSdp(float dur_sec = 0, const std::map &header = std::map(), int version = 0); - std::string getSdp() const override { - return _printer; - } + std::string getSdp() const override { return _printer; } - CodecId getCodecId() const override { - return CodecInvalid; - } + CodecId getCodecId() const override { return CodecInvalid; } - float getDuration() const { - return _dur_sec; - } + float getDuration() const { return _dur_sec; } private: float _dur_sec = 0; toolkit::_StrPrinter _printer; }; -//创建rtp over tcp4个字节的头 +// 创建rtp over tcp4个字节的头 toolkit::Buffer::Ptr makeRtpOverTcpPrefix(uint16_t size, uint8_t interleaved); -//创建rtp-rtcp端口对 +// 创建rtp-rtcp端口对 void makeSockPair(std::pair &pair, const std::string &local_ip, bool re_use_port = false, bool is_udp = true); -//十六进制方式打印ssrc +// 十六进制方式打印ssrc std::string printSSRC(uint32_t ui32Ssrc); bool isRtp(const char *buf, size_t size); -bool isRtcp(const char *buf, size_t size); +bool isRtcp(const char *buf, size_t size); -} //namespace mediakit -#endif //RTSP_RTSP_H_ +} // namespace mediakit +#endif // RTSP_RTSP_H_ diff --git a/src/Rtsp/RtspPlayer.cpp b/src/Rtsp/RtspPlayer.cpp index 0dafa03a..599677ec 100644 --- a/src/Rtsp/RtspPlayer.cpp +++ b/src/Rtsp/RtspPlayer.cpp @@ -38,8 +38,8 @@ RtspPlayer::~RtspPlayer(void) { void RtspPlayer::sendTeardown() { if (alive()) { - if (!_content_base.empty()) { - sendRtspRequest("TEARDOWN", _content_base); + if (!_control_url.empty()) { + sendRtspRequest("TEARDOWN", _control_url); } shutdown(SockException(Err_shutdown, "teardown")); } @@ -203,6 +203,8 @@ void RtspPlayer::handleResDESCRIBE(const Parser &parser) { // 解析sdp SdpParser sdpParser(parser.content()); + _control_url = sdpParser.getControlUrl(_content_base); + string sdp; auto play_track = (TrackType)((int)(*this)[Client::kPlayTrack] - 1); if (play_track != TrackInvalid) { @@ -412,7 +414,7 @@ void RtspPlayer::sendKeepAlive() { _on_response = [](const Parser &parser) {}; if (_supported_cmd.find("GET_PARAMETER") != _supported_cmd.end()) { // 支持GET_PARAMETER,用此命令保活 - sendRtspRequest("GET_PARAMETER", _content_base); + sendRtspRequest("GET_PARAMETER", _control_url); } else { // 不支持GET_PARAMETER,用OPTIONS命令保活 sendRtspRequest("OPTIONS", _play_url); @@ -423,12 +425,12 @@ void RtspPlayer::sendPause(int type, uint32_t seekMS) { _on_response = std::bind(&RtspPlayer::handleResPAUSE, this, placeholders::_1, type); // 开启或暂停rtsp switch (type) { - case type_pause: sendRtspRequest("PAUSE", _content_base); break; + case type_pause: sendRtspRequest("PAUSE", _control_url, {}); break; case type_play: // sendRtspRequest("PLAY", _content_base); // break; case type_seek: - sendRtspRequest("PLAY", _content_base, { "Range", StrPrinter << "npt=" << setiosflags(ios::fixed) << setprecision(2) << seekMS / 1000.0 << "-" }); + sendRtspRequest("PLAY", _control_url, { "Range", StrPrinter << "npt=" << setiosflags(ios::fixed) << setprecision(2) << seekMS / 1000.0 << "-" }); break; default: WarnL << "unknown type : " << type; @@ -442,7 +444,7 @@ void RtspPlayer::pause(bool bPause) { } void RtspPlayer::speed(float speed) { - sendRtspRequest("PLAY", _content_base, { "Scale", StrPrinter << speed }); + sendRtspRequest("PLAY", _control_url, { "Scale", StrPrinter << speed }); } void RtspPlayer::handleResPAUSE(const Parser &parser, int type) { @@ -451,7 +453,7 @@ void RtspPlayer::handleResPAUSE(const Parser &parser, int type) { case type_pause: WarnL << "Pause failed:" << parser.status() << " " << parser.statusStr(); break; case type_play: WarnL << "Play failed:" << parser.status() << " " << parser.statusStr(); - onPlayResult_l(SockException(Err_shutdown, StrPrinter << "rtsp play failed:" << parser.status() << " " << parser.statusStr()), !_play_check_timer); + onPlayResult_l(SockException(Err_other, StrPrinter << "rtsp play failed:" << parser.status() << " " << parser.statusStr()), !_play_check_timer); break; case type_seek: WarnL << "Seek failed:" << parser.status() << " " << parser.statusStr(); break; } @@ -571,6 +573,7 @@ void RtspPlayer::sendRtspRequest(const string &cmd, const string &url, const std key = val; } } + sendRtspRequest(cmd, url, header_map); } @@ -615,12 +618,9 @@ void RtspPlayer::sendRtspRequest(const string &cmd, const string &url, const Str } _StrPrinter printer; - if (cmd == "PLAY") { - printer << cmd << " " << _play_url << " RTSP/1.0\r\n"; - } else { - printer << cmd << " " << url << " RTSP/1.0\r\n"; - } + printer << cmd << " " << url << " RTSP/1.0\r\n"; + TraceL << cmd << " "<< url; for (auto &pr : header) { printer << pr.first << ": " << pr.second << "\r\n"; } @@ -743,7 +743,7 @@ int RtspPlayer::getTrackIndexByTrackType(TrackType track_type) const { if (_sdp_track.size() == 1) { return 0; } - throw SockException(Err_shutdown, StrPrinter << "no such track with type:" << getTrackString(track_type)); + throw SockException(Err_other, StrPrinter << "no such track with type:" << getTrackString(track_type)); } /////////////////////////////////////////////////// diff --git a/src/Rtsp/RtspPlayer.h b/src/Rtsp/RtspPlayer.h index 5a9bd1ee..2b4f34c5 100644 --- a/src/Rtsp/RtspPlayer.h +++ b/src/Rtsp/RtspPlayer.h @@ -129,6 +129,7 @@ private: std::string _session_id; uint32_t _cseq_send = 1; std::string _content_base; + std::string _control_url; Rtsp::eRtpType _rtp_type = Rtsp::RTP_TCP; //当前rtp时间戳