From 0779a4bee605e42c85b7bd941aa9409e123668e0 Mon Sep 17 00:00:00 2001 From: xiongziliang <771730766@qq.com> Date: Fri, 15 May 2020 09:53:17 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E5=96=84rtsp=20=E4=BF=A1=E4=BB=A4?= =?UTF-8?q?=E5=BF=83=E8=B7=B3=E5=8C=85=E7=9B=B8=E5=85=B3=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Rtsp/RtspPlayer.cpp | 48 +++++++++++++++++++++++++++++++---------- src/Rtsp/RtspPlayer.h | 7 ++++-- 2 files changed, 42 insertions(+), 13 deletions(-) diff --git a/src/Rtsp/RtspPlayer.cpp b/src/Rtsp/RtspPlayer.cpp index dad4abe2..87afee56 100644 --- a/src/Rtsp/RtspPlayer.cpp +++ b/src/Rtsp/RtspPlayer.cpp @@ -107,8 +107,7 @@ void RtspPlayer::onConnect(const SockException &err){ onPlayResult_l(err,false); return; } - - sendDescribe(); + sendOptions(); } void RtspPlayer::onRecv(const Buffer::Ptr& pBuf) { @@ -162,7 +161,7 @@ void RtspPlayer::handleResDESCRIBE(const Parser& parser) { string authInfo = parser["WWW-Authenticate"]; //发送DESCRIBE命令后的回复 if ((parser.Url() == "401") && handleAuthenticationFailure(authInfo)) { - sendDescribe(); + sendOptions(); return; } if(parser.Url() == "302" || parser.Url() == "301"){ @@ -358,9 +357,33 @@ void RtspPlayer::sendDescribe() { sendRtspRequest("DESCRIBE",_strUrl,{"Accept","application/sdp"}); } -void RtspPlayer::sendGetParameter(){ +void RtspPlayer::sendOptions(){ + _onHandshake = [this](const Parser& parser){ + if (parser.Url() != "200") { + throw std::runtime_error(StrPrinter << "OPTIONS:" << parser.Url() << " " << parser.Tail() << endl); + } + //获取服务器支持的命令 + _supported_cmd.clear(); + auto public_val = split(parser["Public"],","); + for(auto &cmd : public_val){ + trim(cmd); + _supported_cmd.emplace(cmd); + } + //发送Describe请求,获取sdp + sendDescribe(); + }; + sendRtspRequest("OPTIONS",_strUrl); +} + +void RtspPlayer::sendKeepAlive(){ _onHandshake = [this](const Parser& parser){}; - sendRtspRequest("GET_PARAMETER",_strUrl); + if(_supported_cmd.find("GET_PARAMETER") != _supported_cmd.end()){ + //支持GET_PARAMETER,用此命令保活 + sendRtspRequest("GET_PARAMETER",_strUrl); + }else{ + //不支持GET_PARAMETER,用OPTIONS命令保活 + sendRtspRequest("OPTIONS",_strUrl); + } } void RtspPlayer::sendPause(int type , uint32_t seekMS){ @@ -695,10 +718,10 @@ void RtspPlayer::sendRtspRequest(const string &cmd, const string &url,const StrC void RtspPlayer::onRecvRTP_l(const RtpPacket::Ptr &pkt, const SdpTrack::Ptr &track) { _rtpTicker.resetTime(); - onRecvRTP(pkt,track); + onRecvRTP(pkt, track); int iTrackIndex = getTrackIndexByInterleaved(pkt->interleaved); - if(iTrackIndex == -1){ + if (iTrackIndex == -1) { return; } RtcpCounter &counter = _aRtcpCnt[iTrackIndex]; @@ -708,14 +731,17 @@ void RtspPlayer::onRecvRTP_l(const RtpPacket::Ptr &pkt, const SdpTrack::Ptr &tra //send rtcp every 5 second counter.lastTimeStamp = counter.timeStamp; //直接保存网络字节序 - memcpy(&counter.timeStamp, pkt->data() + 8 , 4); - if(counter.lastTimeStamp != 0){ - sendReceiverReport(_eType == Rtsp::RTP_TCP,iTrackIndex); + memcpy(&counter.timeStamp, pkt->data() + 8, 4); + if (counter.lastTimeStamp != 0) { + sendReceiverReport(_eType == Rtsp::RTP_TCP, iTrackIndex); ticker.resetTime(); } //有些rtsp服务器需要rtcp保活,有些需要发送信令保活 - sendGetParameter(); + if (iTrackIndex == 0) { + //只需要发送一次心跳信令包 + sendKeepAlive(); + } } } diff --git a/src/Rtsp/RtspPlayer.h b/src/Rtsp/RtspPlayer.h index 0e643555..f43753a9 100644 --- a/src/Rtsp/RtspPlayer.h +++ b/src/Rtsp/RtspPlayer.h @@ -95,11 +95,11 @@ private: bool handleAuthenticationFailure(const string &wwwAuthenticateParamsStr); void handleResPAUSE(const Parser &parser, int type); - //发送SETUP命令 + void sendOptions(); void sendSetup(unsigned int uiTrackIndex); void sendPause(int type , uint32_t ms); void sendDescribe(); - void sendGetParameter(); + void sendKeepAlive(); void sendRtspRequest(const string &cmd, const string &url ,const StrCaseMap &header = StrCaseMap()); void sendRtspRequest(const string &cmd, const string &url ,const std::initializer_list &header); void sendReceiverReport(bool overTcp,int iTrackIndex); @@ -141,6 +141,9 @@ private: bool _is_play_back; //是否为性能测试模式 bool _benchmark_mode = false; + + //服务器支持的命令 + set _supported_cmd; }; } /* namespace mediakit */