diff --git a/src/Player/Frame.h b/src/Player/Frame.h index 53afbb2..ff48c67 100644 --- a/src/Player/Frame.h +++ b/src/Player/Frame.h @@ -44,6 +44,7 @@ typedef enum { TrackInvalid = -1, TrackVideo = 0, TrackAudio, + TrackTitle, TrackMax } TrackType; diff --git a/src/RtmpMuxer/RtmpMetedata.h b/src/RtmpMuxer/RtmpMetedata.h index ea0b811..fa193b8 100644 --- a/src/RtmpMuxer/RtmpMetedata.h +++ b/src/RtmpMuxer/RtmpMetedata.h @@ -75,7 +75,7 @@ public: * @return */ TrackType getTrackType() const override { - return TrackInvalid; + return TrackTitle; } /** diff --git a/src/Rtsp/Rtsp.cpp b/src/Rtsp/Rtsp.cpp index 721dee4..b17b751 100644 --- a/src/Rtsp/Rtsp.cpp +++ b/src/Rtsp/Rtsp.cpp @@ -49,78 +49,124 @@ string FindField(const char* buf, const char* start, const char *end ,int bufSiz } return string(msg_start, msg_end); } -int parserSDP(const string& sdp, RtspTrack Track[2]) { - map<string,map<char ,map<string ,string> > > sdpAttr; - string sdpTrack = ""; + + +void SdpAttr::load(const string &sdp) { + _track_map.clear(); + string key; + SdpTrack::Ptr track = std::make_shared<SdpTrack>(); auto lines = split(sdp,"\n"); for (auto &line : lines){ trim(line); - if(line.size() < 2){ - continue; - } - if(line[1] != '='){ + if(line.size() < 2 || line[1] != '='){ continue; } char opt = line[0]; string opt_val = line.substr(2); switch (opt){ case 'o': + track->_o = opt_val; + break; case 's': + track->_s = opt_val; + break; case 'i': + track->_i = opt_val; + break; case 'c': - case 't':{ - sdpAttr[sdpTrack][opt][""] = opt_val; - } + track->_c = opt_val; + break; + case 't': + track->_t = opt_val; + break; + case 'b': + track->_b = opt_val; break; case 'm':{ - sdpTrack = FindField(opt_val.data(), nullptr," "); - sdpAttr[sdpTrack][opt][""] = opt_val; + _track_map[key] = track; + track = std::make_shared<SdpTrack>(); + key = FindField(opt_val.data(), nullptr," ");; + track->_m = opt_val; } break; case 'a':{ string attr = FindField(opt_val.data(), nullptr,":"); if(attr.empty()){ - sdpAttr[sdpTrack][opt][opt_val] = opt_val; + track->_attr[opt_val] = ""; }else{ - sdpAttr[sdpTrack][opt][attr] = FindField(opt_val.data(),":", nullptr); + track->_attr[attr] = FindField(opt_val.data(),":", nullptr); } } break; default: + track->_other[opt] = opt_val; break; } } + _track_map[key] = track; + - for (auto &pr : sdpAttr) { - TrackType trackType = TrackInvalid; - if (pr.first == "video") { - trackType = TrackVideo; + for (auto &pr : _track_map) { + auto &track = *pr.second; + if (pr.first == "") { + track._type = TrackTitle; + } else if (pr.first == "video") { + track._type = TrackVideo; } else if (pr.first == "audio") { - trackType = TrackAudio; - } else if (pr.first == "") { - //title - auto range = pr.second['a']["range"]; - char name[16] = {0},start[16] = {0},end[16] = {0}; - if (2 == sscanf(range.data(), "%15[^=]=%15[^-]-%15s", name, start, end)) { + track._type = TrackAudio; + } else { + track._type = TrackInvalid; + } + auto it = track._attr.find("range"); + if (it != track._attr.end()) { + 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 = atof(start); + track._end = atof(end); + track._duration = track._end - track._start; } - DebugL << range; - continue; - } else { - continue; } - auto rtpmap = pr.second['a']["rtpmap"]; - int pt, samplerate; - char codec[16] = {0}; - if (3 == sscanf(rtpmap.data(), "%d %15[^/]/%d", &pt, codec, &samplerate)) { + it = track._attr.find("rtpmap"); + if(it != track._attr.end()){ + auto rtpmap = it->second; + int pt, samplerate; + char codec[16] = {0}; + if (3 == sscanf(rtpmap.data(), "%d %15[^/]/%d", &pt, codec, &samplerate)) { + track._pt = pt; + track._codec = codec; + track._samplerate = samplerate; + } + } + + it = track._attr.find("fmtp"); + if(it != track._attr.end()) { + track._fmtp = it->second; + } + it = track._attr.find("control"); + if(it != track._attr.end()) { + track._control = it->second; } - DebugL << codec; } +} +SdpTrack::Ptr SdpAttr::getTrack(TrackType type) { + for (auto &pr : _track_map){ + if(pr.second->_type == type){ + return pr.second; + } + } + return nullptr; +} +int parserSDP(const string& sdp, RtspTrack Track[2]) { int track_cnt = 0; string::size_type pos_head = 0; while ((pos_head = sdp.find("m=",pos_head)) != string::npos ) { @@ -169,6 +215,7 @@ static onceToken s_token([](){ "a=recvonly"; RtspTrack track[2]; parserSDP(str,track); + SdpAttr attr(str); track[0].inited=true; }); bool MakeNalu(uint8_t in, NALU &nal) { @@ -190,3 +237,5 @@ bool MakeFU(uint8_t in, FU &fu) { } return true; } + + diff --git a/src/Rtsp/Rtsp.h b/src/Rtsp/Rtsp.h index a5d66a7..9120b99 100644 --- a/src/Rtsp/Rtsp.h +++ b/src/Rtsp/Rtsp.h @@ -38,6 +38,43 @@ using namespace std; using namespace toolkit; using namespace mediakit; +class SdpTrack{ +public: + typedef std::shared_ptr<SdpTrack> Ptr; + + string _m; + string _o; + string _s; + string _i; + string _c; + string _t; + string _b; + + float _duration = 0; + float _start = 0; + float _end = 0; + + map<char,string> _other; + map<string,string> _attr; +public: + int _pt; + string _codec; + int _samplerate; + string _fmtp; + string _control; + TrackType _type; +}; +class SdpAttr { +public: + typedef std::shared_ptr<SdpAttr> Ptr; + SdpAttr(const string &sdp){load(sdp);}; + ~SdpAttr(){} + + void load(const string &sdp); + SdpTrack::Ptr getTrack(TrackType type); +private: + map<string,SdpTrack::Ptr> _track_map; +}; class RtspTrack{ public: @@ -63,7 +100,6 @@ public: string FindField(const char* buf, const char* start, const char *end,int bufSize = 0 ); int parserSDP(const string& sdp, RtspTrack Track[2]); - struct StrCaseCompare { bool operator()(const string& __x, const string& __y) const diff --git a/src/RtspMuxer/RtspSdp.h b/src/RtspMuxer/RtspSdp.h index ce76665..37ddd0e 100644 --- a/src/RtspMuxer/RtspSdp.h +++ b/src/RtspMuxer/RtspSdp.h @@ -115,7 +115,7 @@ public: * @return */ TrackType getTrackType() const override { - return TrackInvalid; + return TrackTitle; } /**