From d2a78e5a40b40fe72b893288f2535d4b917cfd3e Mon Sep 17 00:00:00 2001 From: xiongziliang <771730766@qq.com> Date: Mon, 17 Dec 2018 15:21:23 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E6=88=90rtsp=E6=8E=A8=E6=B5=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Rtsp/RtspSession.cpp | 285 +++++++++++++++++++------------------- src/Rtsp/RtspSession.h | 62 ++++++--- src/Rtsp/RtspSplitter.cpp | 8 +- src/Rtsp/RtspSplitter.h | 13 +- 4 files changed, 195 insertions(+), 173 deletions(-) diff --git a/src/Rtsp/RtspSession.cpp b/src/Rtsp/RtspSession.cpp index 4ee826e9..f052b697 100644 --- a/src/Rtsp/RtspSession.cpp +++ b/src/Rtsp/RtspSession.cpp @@ -42,8 +42,6 @@ using namespace toolkit; namespace mediakit { -static int kSockFlags = SOCKET_DEFAULE_FLAGS | FLAG_MORE; - /** * rtsp协议有多种方式传输rtp数据包,目前已支持包括以下4种 * 1: rtp over udp ,这种方式是rtp通过单独的udp端口传输 @@ -72,6 +70,8 @@ static unordered_map > g_mapGetter; //对g_mapGetter上锁保护 static recursive_mutex g_mtxGetter; +static int kSockFlags = SOCKET_DEFAULE_FLAGS | FLAG_MORE; + RtspSession::RtspSession(const std::shared_ptr &pTh, const Socket::Ptr &pSock) : TcpSession(pTh, pSock) { //设置10秒发送缓存 pSock->setSendBufSecond(10); @@ -134,19 +134,29 @@ void RtspSession::onManager() { } } +void RtspSession::onRecv(const Buffer::Ptr &pBuf) { + _ticker.resetTime(); + _ui64TotalBytes += pBuf->size(); + if (_onRecv) { + //http poster的请求数据转发给http getter处理 + _onRecv(pBuf); + } else { +// TraceL << pBuf->size() << "\r\n" << pBuf->data(); + input(pBuf->data(),pBuf->size()); + } +} -int64_t RtspSession::onRecvHeader(const char *header,uint64_t len) { - _parser.Parse(header); //rtsp请求解析 - string strCmd = _parser.Method(); //提取出请求命令字 - _iCseq = atoi(_parser["CSeq"].data()); +void RtspSession::onWholeRtspPacket(Parser &parser) { + string strCmd = parser.Method(); //提取出请求命令字 + _iCseq = atoi(parser["CSeq"].data()); - typedef int (RtspSession::*rtsp_request_handler)(); + typedef bool (RtspSession::*rtsp_request_handler)(const Parser &parser); static unordered_map s_handler_map; static onceToken token( []() { s_handler_map.emplace("OPTIONS",&RtspSession::handleReq_Options); s_handler_map.emplace("DESCRIBE",&RtspSession::handleReq_Describe); s_handler_map.emplace("ANNOUNCE",&RtspSession::handleReq_ANNOUNCE); - s_handler_map.emplace("RECORD",&RtspSession::handleReq_RECORD); + s_handler_map.emplace("RECORD",&RtspSession::handleReq_RECORD); s_handler_map.emplace("SETUP",&RtspSession::handleReq_Setup); s_handler_map.emplace("PLAY",&RtspSession::handleReq_Play); s_handler_map.emplace("PAUSE",&RtspSession::handleReq_Pause); @@ -158,96 +168,82 @@ int64_t RtspSession::onRecvHeader(const char *header,uint64_t len) { }, []() {}); auto it = s_handler_map.find(strCmd); - int ret = 0; if (it != s_handler_map.end()) { - auto fun = it->second; - ret = (this->*fun)(); - if(ret == -1){ + auto &fun = it->second; + if(!(this->*fun)(parser)){ shutdown(); } } else{ shutdown(); WarnL << "不支持的rtsp命令:" << strCmd; } - _parser.Clear(); - return ret; } - -void RtspSession::onRecv(const Buffer::Ptr &pBuf) { - _ticker.resetTime(); - _ui64TotalBytes += pBuf->size(); - if (_onRecv) { - //http poster的请求数据转发给http getter处理 - _onRecv(pBuf); - } else { - inputRtspOrRtcp(pBuf->data(),pBuf->size()); - } -} - -void RtspSession::inputRtspOrRtcp(const char *data,uint64_t len) { -// DebugL << data; - if(data[0] == '$' && _rtpType == PlayerBase::RTP_TCP){ - //这是rtcp +void RtspSession::onRtpPacket(const char *data, uint64_t len) { + if(len > 1600){ + //没有大于MTU的包 return; } - input(data,len); -} - -int RtspSession::handleReq_Options() { - //支持这些命令 - sendRtspResponse("200 OK",{"Public" , "OPTIONS, DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE, ANNOUNCE, RECORD, SET_PARAMETER, GET_PARAMETER"}); - return 0; -} - -void RtspSession::onRecvContent(const char *data, uint64_t len) { -// DebugL << data; - if(_onContent){ - _onContent(data,len); - _onContent = nullptr; + int trackIdx = -1; + uint8_t interleaved = data[1]; + if(interleaved %2 == 0){ + trackIdx = getTrackIndexByInterleaved(interleaved); + } + if (trackIdx != -1) { + handleOneRtp(trackIdx,_aTrackInfo[trackIdx],(unsigned char *)data + 4, len - 4); } } -int RtspSession::handleReq_ANNOUNCE() { - auto parseCopy = _parser; - _onContent = [this,parseCopy](const char *data, uint64_t len){ - _parser = parseCopy; - _strSdp.assign(data,len); - //解析url获取媒体名称 - _mediaInfo.parse(_parser.FullUrl()); - - auto src = dynamic_pointer_cast(MediaSource::find(RTSP_SCHEMA, - _mediaInfo._vhost, - _mediaInfo._app, - _mediaInfo._streamid, - false)); - if(src){ - sendRtspResponse("406 Not Acceptable", {"Content-Type", "text/plain"}, "Already publishing."); - WarnL << "ANNOUNCE:" - << "Already publishing:" - << _mediaInfo._vhost << " " - << _mediaInfo._app << " " - << _mediaInfo._streamid << endl; - shutdown(); - return; - } - - _strSession = makeRandStr(12); - _aTrackInfo = SdpAttr(_strSdp).getAvailableTrack(); - _strUrl = _parser.Url(); - - _pushSrc = std::make_shared(_mediaInfo._vhost,_mediaInfo._app,_mediaInfo._streamid); - _pushSrc->setListener(dynamic_pointer_cast(shared_from_this())); - _pushSrc->onGetSDP(_strSdp); - sendRtspResponse("200 OK"); - }; - return atoi(_parser["Content-Length"].data()); +int64_t RtspSession::getContentLength(Parser &parser) { + if(parser.Method() == "POST"){ + //http post请求的content数据部分是base64编码后的rtsp请求信令包 + return remainDataSize(); + } + return RtspSplitter::getContentLength(parser); } -int RtspSession::handleReq_RECORD(){ - if (_aTrackInfo.empty() || _parser["Session"] != _strSession) { + +bool RtspSession::handleReq_Options(const Parser &parser) { + //支持这些命令 + sendRtspResponse("200 OK",{"Public" , "OPTIONS, DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE, ANNOUNCE, RECORD, SET_PARAMETER, GET_PARAMETER"}); + return true; +} + +bool RtspSession::handleReq_ANNOUNCE(const Parser &parser) { + _strSdp = parser.Content(); + //解析url获取媒体名称 + _mediaInfo.parse(parser.FullUrl()); + + auto src = dynamic_pointer_cast(MediaSource::find(RTSP_SCHEMA, + _mediaInfo._vhost, + _mediaInfo._app, + _mediaInfo._streamid, + false)); + if(src){ + sendRtspResponse("406 Not Acceptable", {"Content-Type", "text/plain"}, "Already publishing."); + WarnL << "ANNOUNCE:" + << "Already publishing:" + << _mediaInfo._vhost << " " + << _mediaInfo._app << " " + << _mediaInfo._streamid << endl; + return false; + } + + _strSession = makeRandStr(12); + _aTrackInfo = SdpAttr(_strSdp).getAvailableTrack(); + _strUrl = parser.Url(); + + _pushSrc = std::make_shared(_mediaInfo._vhost,_mediaInfo._app,_mediaInfo._streamid); + _pushSrc->setListener(dynamic_pointer_cast(shared_from_this())); + _pushSrc->onGetSDP(_strSdp); + sendRtspResponse("200 OK"); + return true; +} + +bool RtspSession::handleReq_RECORD(const Parser &parser){ + if (_aTrackInfo.empty() || parser["Session"] != _strSession) { send_SessionNotFound(); - return -1; + return false; } auto onRes = [this](const string &err){ bool authSuccess = err.empty(); @@ -295,26 +291,23 @@ int RtspSession::handleReq_RECORD(){ //该事件无人监听,默认不鉴权 onRes(""); } - return 0; + return true; } -int RtspSession::handleReq_Describe() { - { - //解析url获取媒体名称 - _strUrl = _parser.Url(); - _mediaInfo.parse(_parser.FullUrl()); - } +bool RtspSession::handleReq_Describe(const Parser &parser) { + //解析url获取媒体名称 + _strUrl = parser.Url(); + _mediaInfo.parse(parser.FullUrl()); - weak_ptr weakSelf = dynamic_pointer_cast(shared_from_this());\ - auto parserCopy = _parser; - findStream([weakSelf,parserCopy](bool success){ + weak_ptr weakSelf = dynamic_pointer_cast(shared_from_this()); + auto authorization = parser["Authorization"]; + + findStream([weakSelf,authorization](bool success){ auto strongSelf = weakSelf.lock(); if(!strongSelf){ return; } - //恢复现场 - strongSelf->_parser = parserCopy; if(!success){ //未找到相应的MediaSource @@ -324,7 +317,6 @@ int RtspSession::handleReq_Describe() { return; } //该请求中的认证信息 - auto authorization = strongSelf->_parser["Authorization"]; onGetRealm invoker = [weakSelf,authorization](const string &realm){ if(realm.empty()){ //无需认证,回复sdp @@ -344,7 +336,7 @@ int RtspSession::handleReq_Describe() { invoker(""); } }); - return 0; + return true; } void RtspSession::onAuthSuccess(const weak_ptr &weakSelf) { auto strongSelf = weakSelf.lock(); @@ -544,23 +536,23 @@ inline void RtspSession::send_UnsupportedTransport() { inline void RtspSession::send_SessionNotFound() { sendRtspResponse("454 Session Not Found",{"Connection","Close"}); } -int RtspSession::handleReq_Setup() { +bool RtspSession::handleReq_Setup(const Parser &parser) { //处理setup命令,该函数可能进入多次 - auto controlSuffix = _parser.FullUrl().substr(1 + _parser.FullUrl().rfind('/')); + auto controlSuffix = parser.FullUrl().substr(1 + parser.FullUrl().rfind('/')); int trackIdx = getTrackIndexByControlSuffix(controlSuffix); if (trackIdx == -1) { //未找到相应track - return -1; + return false; } SdpTrack::Ptr &trackRef = _aTrackInfo[trackIdx]; if (trackRef->_inited) { //已经初始化过该Track - return -1; + return false; } trackRef->_inited = true; //现在初始化 if(_rtpType == PlayerBase::RTP_Invalid){ - auto strTransport = _parser["Transport"]; + auto strTransport = parser["Transport"]; if(strTransport.find("TCP") != string::npos){ _rtpType = PlayerBase::RTP_TCP; }else if(strTransport.find("multicast") != string::npos){ @@ -570,8 +562,12 @@ int RtspSession::handleReq_Setup() { } } + //允许接收rtp、rtcp包 + RtspSplitter::enableRecvRtp(_rtpType == PlayerBase::RTP_TCP); + switch (_rtpType) { case PlayerBase::RTP_TCP: { + trackRef->_interleaved = trackRef->_type * 2; sendRtspResponse("200 OK", {"Transport",StrPrinter << "RTP/AVP/TCP;unicast;" << "interleaved=" << trackRef->_type * 2 << "-" << trackRef->_type * 2 + 1 << ";" @@ -588,19 +584,19 @@ int RtspSession::handleReq_Setup() { //分配端口失败 WarnL << "分配rtp端口失败"; send_NotAcceptable(); - return -1; + return false; } auto pSockRtcp = std::make_shared(_sock->getPoller()); if (!pSockRtcp->bindUdpSock(pSockRtp->get_local_port() + 1,get_local_ip().data())) { //分配端口失败 WarnL << "分配rtcp端口失败"; send_NotAcceptable(); - return -1; + return false; } _apRtpSock[trackIdx] = pSockRtp; _apRtcpSock[trackIdx] = pSockRtcp; //设置客户端内网端口信息 - string strClientPort = FindField(_parser["Transport"].data(), "client_port=", NULL); + string strClientPort = FindField(parser["Transport"].data(), "client_port=", NULL); uint16_t ui16PeerPort = atoi( FindField(strClientPort.data(), NULL, "-").data()); struct sockaddr_in peerAddr; peerAddr.sin_family = AF_INET; @@ -625,7 +621,7 @@ int RtspSession::handleReq_Setup() { _pBrdcaster = RtpBroadCaster::get(get_local_ip(),_mediaInfo._vhost, _mediaInfo._app, _mediaInfo._streamid); if (!_pBrdcaster) { send_NotAcceptable(); - return -1; + return false; } weak_ptr weakSelf = dynamic_pointer_cast(shared_from_this()); _pBrdcaster->setDetachCB(this, [weakSelf]() { @@ -644,7 +640,7 @@ int RtspSession::handleReq_Setup() { //分配端口失败 WarnL << "分配rtcp端口失败"; send_NotAcceptable(); - return -1; + return false; } startListenPeerUdpData(trackIdx); GET_CONFIG_AND_REGISTER(uint32_t,udpTTL,MultiCast::kUdpTTL); @@ -662,15 +658,15 @@ int RtspSession::handleReq_Setup() { default: break; } - return 0; + return true; } -int RtspSession::handleReq_Play() { - if (_aTrackInfo.empty() || _parser["Session"] != _strSession) { +bool RtspSession::handleReq_Play(const Parser &parser) { + if (_aTrackInfo.empty() || parser["Session"] != _strSession) { send_SessionNotFound(); - return -1; + return false; } - auto strRange = _parser["Range"]; + auto strRange = parser["Range"]; auto onRes = [this,strRange](const string &err){ bool authSuccess = err.empty(); if(!authSuccess){ @@ -750,9 +746,6 @@ int RtspSession::handleReq_Play() { if(!strongSelf) { return; } - if(!strongSelf->_enableSendRtp) { - return; - } strongSelf->async([weakSelf,pack](){ auto strongSelf = weakSelf.lock(); if(!strongSelf) { @@ -791,28 +784,28 @@ int RtspSession::handleReq_Play() { //后面是seek或恢复命令,不需要鉴权 onRes(""); } - return 0; + return true; } -int RtspSession::handleReq_Pause() { - if (_parser["Session"] != _strSession) { +bool RtspSession::handleReq_Pause(const Parser &parser) { + if (parser["Session"] != _strSession) { send_SessionNotFound(); - return -1; + return false; } sendRtspResponse("200 OK"); _enableSendRtp = false; - return 0; + return true; } -int RtspSession::handleReq_Teardown() { +bool RtspSession::handleReq_Teardown(const Parser &parser) { sendRtspResponse("200 OK"); TraceL << "播放器断开连接!"; - return 0; + return true; } -int RtspSession::handleReq_Get() { - _http_x_sessioncookie = _parser["x-sessioncookie"]; +bool RtspSession::handleReq_Get(const Parser &parser) { + _http_x_sessioncookie = parser["x-sessioncookie"]; sendRtspResponse("200 OK", {"Connection","Close", "Cache-Control","no-store", @@ -823,18 +816,18 @@ int RtspSession::handleReq_Get() { //注册http getter,以便http poster绑定 lock_guard lock(g_mtxGetter); g_mapGetter[_http_x_sessioncookie] = dynamic_pointer_cast(shared_from_this()); - return 0; + return true; } -int RtspSession::handleReq_Post() { +bool RtspSession::handleReq_Post(const Parser &parser) { lock_guard lock(g_mtxGetter); - string sessioncookie = _parser["x-sessioncookie"]; + string sessioncookie = parser["x-sessioncookie"]; //Poster 找到 Getter auto it = g_mapGetter.find(sessioncookie); if (it == g_mapGetter.end()) { WarnL << "Http Poster未找到Http Getter"; - return -1; + return false; } //Poster 找到Getter的SOCK @@ -842,22 +835,6 @@ int RtspSession::handleReq_Post() { //移除http getter的弱引用记录 g_mapGetter.erase(sessioncookie); - auto nextPacketSize = remainDataSize(); - if(nextPacketSize > 0){ - //防止http poster中的content部分粘包(后续content都是base64编码的rtsp请求包) - _onContent = [this](const char *data,uint64_t len){ - BufferRaw::Ptr buffer = std::make_shared(); - buffer->assign(data,len); - weak_ptr weakSelf = dynamic_pointer_cast(shared_from_this()); - async([weakSelf,buffer](){ - auto strongSelf = weakSelf.lock(); - if(strongSelf){ - strongSelf->onRecv(buffer); - } - },false); - }; - } - //http poster收到请求后转发给http getter处理 _onRecv = [this,httpGetterWeak](const Buffer::Ptr &pBuf){ auto httpGetterStrong = httpGetterWeak.lock(); @@ -877,13 +854,17 @@ int RtspSession::handleReq_Post() { }); }; - return nextPacketSize; + if(!parser.Content().empty()){ + //http poster后面的粘包 + _onRecv(std::make_shared(parser.Content())); + } + return true; } -int RtspSession::handleReq_SET_PARAMETER() { +bool RtspSession::handleReq_SET_PARAMETER(const Parser &parser) { //TraceL<onWrite(rtppt,true); + _pushSrc->onWrite(rtppt, false); } } inline void RtspSession::onRcvPeerUdpData(int iTrackIdx, const Buffer::Ptr &pBuf, const struct sockaddr& addr) { @@ -1153,6 +1134,9 @@ bool RtspSession::sendRtspResponse(const string &res_code, } int RtspSession::send(const Buffer::Ptr &pkt){ +// if(!_enableSendRtp){ +// DebugL << pkt->data(); +// } _ui64TotalBytes += pkt->size(); return TcpSession::send(pkt); } @@ -1200,6 +1184,15 @@ inline int RtspSession::getTrackIndexByControlSuffix(const string &controlSuffix return -1; } +inline int RtspSession::getTrackIndexByInterleaved(int interleaved){ + for (unsigned int i = 0; i < _aTrackInfo.size(); i++) { + if (_aTrackInfo[i]->_interleaved == interleaved) { + return i; + } + } + return -1; +} + bool RtspSession::close() { InfoL << "kick out:" << _mediaInfo._vhost << " " << _mediaInfo._app << " " << _mediaInfo._streamid; safeShutdown(); diff --git a/src/Rtsp/RtspSession.h b/src/Rtsp/RtspSession.h index eecfcf95..9dd6ecfd 100644 --- a/src/Rtsp/RtspSession.h +++ b/src/Rtsp/RtspSession.h @@ -30,15 +30,15 @@ #include #include #include +#include "Util/util.h" +#include "Util/logger.h" #include "Common/config.h" +#include "Network/TcpSession.h" +#include "Player/PlayerBase.h" #include "Rtsp.h" #include "RtpBroadCaster.h" #include "RtspMediaSource.h" -#include "Player/PlayerBase.h" -#include "Util/util.h" -#include "Util/logger.h" -#include "Network/TcpSession.h" -#include "Http/HttpRequestSplitter.h" +#include "RtspSplitter.h" #include "RtpReceiver.h" #include "RtspToRtmpMediaSource.h" @@ -66,7 +66,7 @@ private: uint32_t _offset; }; -class RtspSession: public TcpSession, public HttpRequestSplitter, public RtpReceiver , public MediaSourceEvent{ +class RtspSession: public TcpSession, public RtspSplitter, public RtpReceiver , public MediaSourceEvent{ public: typedef std::shared_ptr Ptr; typedef std::function onGetRealm; @@ -80,26 +80,43 @@ public: void onError(const SockException &err) override; void onManager() override; protected: - //HttpRequestSplitter override - int64_t onRecvHeader(const char *data,uint64_t len) override ; - void onRecvContent(const char *data,uint64_t len) override; + //RtspSplitter override + /** + * 收到完整的rtsp包回调,包括sdp等content数据 + * @param parser rtsp包 + */ + void onWholeRtspPacket(Parser &parser) override; + + /** + * 收到rtp包回调 + * @param data + * @param len + */ + void onRtpPacket(const char *data,uint64_t len) override; + + /** + * 从rtsp头中获取Content长度 + * @param parser + * @return + */ + int64_t getContentLength(Parser &parser) override; + //RtpReceiver override void onRtpSorted(const RtpPacket::Ptr &rtppt, int trackidx) override; //MediaSourceEvent override bool close() override ; private: - void inputRtspOrRtcp(const char *data,uint64_t len); - int handleReq_Options(); //处理options方法 - int handleReq_Describe(); //处理describe方法 - int handleReq_ANNOUNCE(); //处理options方法 - int handleReq_RECORD(); //处理options方法 - int handleReq_Setup(); //处理setup方法 - int handleReq_Play(); //处理play方法 - int handleReq_Pause(); //处理pause方法 - int handleReq_Teardown(); //处理teardown方法 - int handleReq_Get(); //处理Get方法 - int handleReq_Post(); //处理Post方法 - int handleReq_SET_PARAMETER(); //处理SET_PARAMETER方法 + bool handleReq_Options(const Parser &parser); //处理options方法 + bool handleReq_Describe(const Parser &parser); //处理describe方法 + bool handleReq_ANNOUNCE(const Parser &parser); //处理options方法 + bool handleReq_RECORD(const Parser &parser); //处理options方法 + bool handleReq_Setup(const Parser &parser); //处理setup方法 + bool handleReq_Play(const Parser &parser); //处理play方法 + bool handleReq_Pause(const Parser &parser); //处理pause方法 + bool handleReq_Teardown(const Parser &parser); //处理teardown方法 + bool handleReq_Get(const Parser &parser); //处理Get方法 + bool handleReq_Post(const Parser &parser); //处理Post方法 + bool handleReq_SET_PARAMETER(const Parser &parser); //处理SET_PARAMETER方法 void inline send_StreamNotFound(); //rtsp资源未找到 void inline send_UnsupportedTransport(); //不支持的传输模式 @@ -111,6 +128,7 @@ private: inline string printSSRC(uint32_t ui32Ssrc); inline int getTrackIndexByTrackType(TrackType type); inline int getTrackIndexByControlSuffix(const string &controlSuffix); + inline int getTrackIndexByInterleaved(int interleaved); inline void onRcvPeerUdpData(int iTrackIdx, const Buffer::Ptr &pBuf, const struct sockaddr &addr); inline void startListenPeerUdpData(int iTrackIdx); @@ -131,7 +149,6 @@ private: int send(const Buffer::Ptr &pkt) override; private: Ticker _ticker; - Parser _parser; //rtsp解析类 int _iCseq = 0; string _strUrl; string _strSdp; @@ -162,7 +179,6 @@ private: //quicktime 请求rtsp会产生两次tcp连接, //一次发送 get 一次发送post,需要通过x-sessioncookie关联起来 string _http_x_sessioncookie; - function _onContent; function _onRecv; std::function _delayTask; diff --git a/src/Rtsp/RtspSplitter.cpp b/src/Rtsp/RtspSplitter.cpp index 05212514..70ba0cec 100644 --- a/src/Rtsp/RtspSplitter.cpp +++ b/src/Rtsp/RtspSplitter.cpp @@ -59,9 +59,10 @@ int64_t RtspSplitter::onRecvHeader(const char *data, uint64_t len) { return 0; } _parser.Parse(data); - auto ret = atoi(_parser["Content-Length"].data()); + auto ret = getContentLength(_parser); if(ret == 0){ onWholeRtspPacket(_parser); + _parser.Clear(); } return ret; } @@ -69,12 +70,17 @@ int64_t RtspSplitter::onRecvHeader(const char *data, uint64_t len) { void RtspSplitter::onRecvContent(const char *data, uint64_t len) { _parser.setContent(string(data,len)); onWholeRtspPacket(_parser); + _parser.Clear(); } void RtspSplitter::enableRecvRtp(bool enable) { _enableRecvRtp = enable; } +int64_t RtspSplitter::getContentLength(Parser &parser) { + return atoi(parser["Content-Length"].data()); +} + }//namespace mediakit diff --git a/src/Rtsp/RtspSplitter.h b/src/Rtsp/RtspSplitter.h index 9e0d9028..91bd6035 100644 --- a/src/Rtsp/RtspSplitter.h +++ b/src/Rtsp/RtspSplitter.h @@ -36,6 +36,12 @@ class RtspSplitter : public HttpRequestSplitter{ public: RtspSplitter(){} virtual ~RtspSplitter(){} + + /** + * 是否允许接收rtp包 + * @param enable + */ + void enableRecvRtp(bool enable); protected: /** * 收到完整的rtsp包回调,包括sdp等content数据 @@ -51,10 +57,11 @@ protected: virtual void onRtpPacket(const char *data,uint64_t len) = 0; /** - * 是否允许接收rtp包 - * @param enable + * 从rtsp头中获取Content长度 + * @param parser + * @return */ - void enableRecvRtp(bool enable); + virtual int64_t getContentLength(Parser &parser); protected: const char *onSearchPacketTail(const char *data,int len) override ; int64_t onRecvHeader(const char *data,uint64_t len) override;