Commit f411ddc2 by xiongziliang

优化rtsp服务器代码

修复一个rtp over http的bug
parent 91d88887
...@@ -57,14 +57,12 @@ bool loadIniConfig(const char *ini_path = nullptr); ...@@ -57,14 +57,12 @@ bool loadIniConfig(const char *ini_path = nullptr);
#define CLEAR_ARR(arr) for(auto &item : arr){ item = 0;} #define CLEAR_ARR(arr) for(auto &item : arr){ item = 0;}
#endif //CLEAR_ARR #endif //CLEAR_ARR
#define SERVER_NAME "ZLMediaKit" #define SERVER_NAME "ZLMediaKit-3.0"
#define VHOST_KEY "vhost" #define VHOST_KEY "vhost"
#define HTTP_SCHEMA "http" #define HTTP_SCHEMA "http"
#define RTSP_SCHEMA "rtsp" #define RTSP_SCHEMA "rtsp"
#define RTMP_SCHEMA "rtmp" #define RTMP_SCHEMA "rtmp"
#define DEFAULT_VHOST "__defaultVhost__" #define DEFAULT_VHOST "__defaultVhost__"
#define RTSP_VERSION 1.30
#define RTSP_BUILDTIME __DATE__" CST"
////////////广播名称/////////// ////////////广播名称///////////
namespace Broadcast { namespace Broadcast {
......
...@@ -54,12 +54,16 @@ void HttpRequestSplitter::input(const char *data,uint64_t len) { ...@@ -54,12 +54,16 @@ void HttpRequestSplitter::input(const char *data,uint64_t len) {
//数据按照请求头处理 //数据按照请求头处理
const char *index = nullptr; const char *index = nullptr;
uint64_t remain = len; _remain_data_size = len;
while (_content_len == 0 && remain > 0 && (index = onSearchPacketTail(ptr,remain)) != nullptr) { while (_content_len == 0 && _remain_data_size > 0 && (index = onSearchPacketTail(ptr,_remain_data_size)) != nullptr) {
//_content_len == 0,这是请求头 //_content_len == 0,这是请求头
_content_len = onRecvHeader(ptr, index - ptr); const char *header_ptr = ptr;
int64_t header_size = index - ptr;
ptr = index; ptr = index;
remain = len - (ptr - data); _remain_data_size = len - (ptr - data);
_content_len = onRecvHeader(header_ptr, header_size);
} }
/* /*
...@@ -67,7 +71,7 @@ void HttpRequestSplitter::input(const char *data,uint64_t len) { ...@@ -67,7 +71,7 @@ void HttpRequestSplitter::input(const char *data,uint64_t len) {
*/ */
tail_ref = tail_tmp; tail_ref = tail_tmp;
if(remain <= 0){ if(_remain_data_size <= 0){
//没有剩余数据,清空缓存 //没有剩余数据,清空缓存
_remain_data.clear(); _remain_data.clear();
return; return;
...@@ -75,7 +79,7 @@ void HttpRequestSplitter::input(const char *data,uint64_t len) { ...@@ -75,7 +79,7 @@ void HttpRequestSplitter::input(const char *data,uint64_t len) {
if(_content_len == 0){ if(_content_len == 0){
//尚未找到http头,缓存定位到剩余数据部分 //尚未找到http头,缓存定位到剩余数据部分
string str(ptr,remain); string str(ptr,_remain_data_size);
_remain_data = str; _remain_data = str;
return; return;
} }
...@@ -83,23 +87,23 @@ void HttpRequestSplitter::input(const char *data,uint64_t len) { ...@@ -83,23 +87,23 @@ void HttpRequestSplitter::input(const char *data,uint64_t len) {
//已经找到http头了 //已经找到http头了
if(_content_len > 0){ if(_content_len > 0){
//数据按照固定长度content处理 //数据按照固定长度content处理
if(remain < _content_len){ if(_remain_data_size < _content_len){
//数据不够,缓存定位到剩余数据部分 //数据不够,缓存定位到剩余数据部分
string str(ptr,remain); string str(ptr,_remain_data_size);
_remain_data = str; _remain_data = str;
return; return;
} }
//收到content数据,并且接受content完毕 //收到content数据,并且接受content完毕
onRecvContent(ptr,_content_len); onRecvContent(ptr,_content_len);
remain -= _content_len; _remain_data_size -= _content_len;
ptr += _content_len; ptr += _content_len;
//content处理完毕,后面数据当做请求头处理 //content处理完毕,后面数据当做请求头处理
_content_len = 0; _content_len = 0;
if(remain > 0){ if(_remain_data_size > 0){
//还有数据没有处理完毕 //还有数据没有处理完毕
string str(ptr,remain); string str(ptr,_remain_data_size);
_remain_data = str; _remain_data = str;
data = ptr = (char *)_remain_data.data(); data = ptr = (char *)_remain_data.data();
...@@ -112,7 +116,7 @@ void HttpRequestSplitter::input(const char *data,uint64_t len) { ...@@ -112,7 +116,7 @@ void HttpRequestSplitter::input(const char *data,uint64_t len) {
//_content_len < 0;数据按照不固定长度content处理 //_content_len < 0;数据按照不固定长度content处理
onRecvContent(ptr,remain);//消费掉所有剩余数据 onRecvContent(ptr,_remain_data_size);//消费掉所有剩余数据
_remain_data.clear(); _remain_data.clear();
} }
...@@ -133,6 +137,10 @@ const char *HttpRequestSplitter::onSearchPacketTail(const char *data,int len) { ...@@ -133,6 +137,10 @@ const char *HttpRequestSplitter::onSearchPacketTail(const char *data,int len) {
return pos + 4; return pos + 4;
} }
int64_t HttpRequestSplitter::remainDataSize() {
return _remain_data_size;
}
} /* namespace mediakit */ } /* namespace mediakit */
...@@ -81,9 +81,15 @@ protected: ...@@ -81,9 +81,15 @@ protected:
* 恢复初始设置 * 恢复初始设置
*/ */
void reset(); void reset();
/**
* 剩余数据大小
*/
int64_t remainDataSize();
private: private:
string _remain_data; string _remain_data;
int64_t _content_len = 0; int64_t _content_len = 0;
int64_t _remain_data_size = 0;
}; };
} /* namespace mediakit */ } /* namespace mediakit */
......
...@@ -87,6 +87,7 @@ class PlayerBase : public DemuxerBase, public mINI{ ...@@ -87,6 +87,7 @@ class PlayerBase : public DemuxerBase, public mINI{
public: public:
typedef std::shared_ptr<PlayerBase> Ptr; typedef std::shared_ptr<PlayerBase> Ptr;
typedef enum { typedef enum {
RTP_Invalid = -1,
RTP_TCP = 0, RTP_TCP = 0,
RTP_UDP = 1, RTP_UDP = 1,
RTP_MULTICAST = 2, RTP_MULTICAST = 2,
......
...@@ -77,27 +77,24 @@ public: ...@@ -77,27 +77,24 @@ public:
void onRecv(const Buffer::Ptr &pBuf) override; void onRecv(const Buffer::Ptr &pBuf) override;
void onError(const SockException &err) override; void onError(const SockException &err) override;
void onManager() override; void onManager() override;
protected: protected:
//HttpRequestSplitter override //HttpRequestSplitter override
int64_t onRecvHeader(const char *data,uint64_t len) override ; int64_t onRecvHeader(const char *data,uint64_t len) override ;
void onRecvContent(const char *data,uint64_t len) override;
private: private:
void inputRtspOrRtcp(const char *data,uint64_t len); void inputRtspOrRtcp(const char *data,uint64_t len);
int send(const Buffer::Ptr &pkt) override{
_ui64TotalBytes += pkt->size();
return _pSender->send(pkt,_flags);
}
void shutdown() override ; void shutdown() override ;
void shutdown_l(bool close); void shutdown_l(bool close);
bool handleReq_Options(); //处理options方法 int handleReq_Options(); //处理options方法
bool handleReq_Describe(); //处理describe方法 int handleReq_Describe(); //处理describe方法
bool handleReq_Setup(); //处理setup方法 int handleReq_ANNOUNCE(); //处理options方法
bool handleReq_Play(); //处理play方法 int handleReq_Setup(); //处理setup方法
bool handleReq_Pause(); //处理pause方法 int handleReq_Play(); //处理play方法
bool handleReq_Teardown(); //处理teardown方法 int handleReq_Pause(); //处理pause方法
bool handleReq_Get(); //处理Get方法 int handleReq_Teardown(); //处理teardown方法
bool handleReq_Post(); //处理Post方法 int handleReq_Get(); //处理Get方法
bool handleReq_SET_PARAMETER(); //处理SET_PARAMETER方法 int handleReq_Post(); //处理Post方法
int handleReq_SET_PARAMETER(); //处理SET_PARAMETER方法
void inline send_StreamNotFound(); //rtsp资源未找到 void inline send_StreamNotFound(); //rtsp资源未找到
void inline send_UnsupportedTransport(); //不支持的传输模式 void inline send_UnsupportedTransport(); //不支持的传输模式
...@@ -106,33 +103,9 @@ private: ...@@ -106,33 +103,9 @@ private:
inline bool findStream(); //根据rtsp url查找 MediaSource实例 inline bool findStream(); //根据rtsp url查找 MediaSource实例
inline void findStream(const function<void(bool)> &cb); //根据rtsp url查找 MediaSource实例 inline void findStream(const function<void(bool)> &cb); //根据rtsp url查找 MediaSource实例
inline void initSender(const std::shared_ptr<RtspSession> &pSession); //处理rtsp over http,quicktime使用的 inline string printSSRC(uint32_t ui32Ssrc);
inline void sendRtpPacket(const RtpPacket::Ptr &pkt); inline int getTrackIndexByTrackType(TrackType type);
inline string printSSRC(uint32_t ui32Ssrc) { inline int getTrackIndexByControlSuffix(const string &controlSuffix);
char tmp[9] = { 0 };
ui32Ssrc = htonl(ui32Ssrc);
uint8_t *pSsrc = (uint8_t *) &ui32Ssrc;
for (int i = 0; i < 4; i++) {
sprintf(tmp + 2 * i, "%02X", pSsrc[i]);
}
return tmp;
}
inline int getTrackIndexByTrackType(TrackType type) {
for (unsigned int i = 0; i < _aTrackInfo.size(); i++) {
if (type == _aTrackInfo[i]->_type) {
return i;
}
}
return -1;
}
inline int getTrackIndexByControlSuffix(const string &controlSuffix) {
for (unsigned int i = 0; i < _aTrackInfo.size(); i++) {
if (controlSuffix == _aTrackInfo[i]->_control_surffix) {
return i;
}
}
return -1;
}
inline void onRcvPeerUdpData(int iTrackIdx, const Buffer::Ptr &pBuf, const struct sockaddr &addr); inline void onRcvPeerUdpData(int iTrackIdx, const Buffer::Ptr &pBuf, const struct sockaddr &addr);
inline void startListenPeerUdpData(); inline void startListenPeerUdpData();
...@@ -146,10 +119,16 @@ private: ...@@ -146,10 +119,16 @@ private:
void doDelay(int delaySec,const std::function<void()> &fun); void doDelay(int delaySec,const std::function<void()> &fun);
void cancelDelyaTask(); void cancelDelyaTask();
inline void sendRtpPacket(const RtpPacket::Ptr &pkt);
bool sendRtspResponse(const string &res_code,const std::initializer_list<string> &header, const string &sdp = "" , const char *protocol = "RTSP/1.0");
bool sendRtspResponse(const string &res_code,const StrCaseMap &header = StrCaseMap(), const string &sdp = "",const char *protocol = "RTSP/1.0");
int send(const Buffer::Ptr &pkt) override;
inline void initSender(const std::shared_ptr<RtspSession> &pSession); //处理rtsp over http,quicktime使用的
private: private:
char *_pcBuf = nullptr;
Ticker _ticker; Ticker _ticker;
Parser _parser; //rtsp解析类 Parser _parser; //rtsp解析类
int _iCseq = 0;
string _strUrl; string _strUrl;
string _strSdp; string _strSdp;
string _strSession; string _strSession;
...@@ -157,31 +136,23 @@ private: ...@@ -157,31 +136,23 @@ private:
MediaInfo _mediaInfo; MediaInfo _mediaInfo;
std::weak_ptr<RtspMediaSource> _pMediaSrc; std::weak_ptr<RtspMediaSource> _pMediaSrc;
RingBuffer<RtpPacket::Ptr>::RingReader::Ptr _pRtpReader; RingBuffer<RtpPacket::Ptr>::RingReader::Ptr _pRtpReader;
PlayerBase::eRtpType _rtpType = PlayerBase::RTP_Invalid;
PlayerBase::eRtpType _rtpType = PlayerBase::RTP_UDP;
bool _bSetUped = false;
int _iCseq = 0;
SdpAttr _sdpAttr;
vector<SdpTrack::Ptr> _aTrackInfo; vector<SdpTrack::Ptr> _aTrackInfo;
//RTP over udp
bool _bGotAllPeerUdp = false; bool _bGotAllPeerUdp = false;
#ifdef RTSP_SEND_RTCP
RtcpCounter _aRtcpCnt[2]; //rtcp统计,trackid idx 为数组下标
Ticker _aRtcpTicker[2]; //rtcp发送时间,trackid idx 为数组下标
inline void sendRTCP();
#endif
//RTP over UDP
bool _abGotPeerUdp[2] = { false, false }; //获取客户端udp端口计数 bool _abGotPeerUdp[2] = { false, false }; //获取客户端udp端口计数
weak_ptr<Socket> _apUdpSock[2]; //发送RTP的UDP端口,trackid idx 为数组下标 weak_ptr<Socket> _apUdpSock[2]; //发送RTP的UDP端口,trackid idx 为数组下标
std::shared_ptr<struct sockaddr> _apPeerUdpAddr[2]; //播放器接收RTP的地址,trackid idx 为数组下标 std::shared_ptr<struct sockaddr> _apPeerUdpAddr[2]; //播放器接收RTP的地址,trackid idx 为数组下标
bool _bListenPeerUdpData = false; bool _bListenPeerUdpData = false;
//RTP over udp_multicast
RtpBroadCaster::Ptr _pBrdcaster; RtpBroadCaster::Ptr _pBrdcaster;
//登录认证 //登录认证
string _strNonce; string _strNonce;
//消耗的总流量
uint64_t _ui64TotalBytes = 0;
//RTSP over HTTP //RTSP over HTTP
function<void(void)> _onDestory; function<void(void)> _onDestory;
...@@ -190,18 +161,21 @@ private: ...@@ -190,18 +161,21 @@ private:
//quicktime 请求rtsp会产生两次tcp连接, //quicktime 请求rtsp会产生两次tcp连接,
//一次发送 get 一次发送post,需要通过sessioncookie关联起来 //一次发送 get 一次发送post,需要通过sessioncookie关联起来
string _strSessionCookie; string _strSessionCookie;
//消耗的总流量
uint64_t _ui64TotalBytes = 0;
static recursive_mutex g_mtxGetter; //对quicktime上锁保护 static recursive_mutex g_mtxGetter; //对quicktime上锁保护
static recursive_mutex g_mtxPostter; //对quicktime上锁保护 static recursive_mutex g_mtxPostter; //对quicktime上锁保护
static unordered_map<string, weak_ptr<RtspSession> > g_mapGetter; static unordered_map<string, weak_ptr<RtspSession> > g_mapGetter;
static unordered_map<void *, std::shared_ptr<RtspSession> > g_mapPostter; static unordered_map<void *, std::shared_ptr<RtspSession> > g_mapPostter;
function<void(const char *data,uint64_t len)> _onContent;
std::function<void()> _delayTask; std::function<void()> _delayTask;
uint32_t _iTaskTimeLine = 0; uint32_t _iTaskTimeLine = 0;
atomic<bool> _enableSendRtp; atomic<bool> _enableSendRtp;
#ifdef RTSP_SEND_RTCP
RtcpCounter _aRtcpCnt[2]; //rtcp统计,trackid idx 为数组下标
Ticker _aRtcpTicker[2]; //rtcp发送时间,trackid idx 为数组下标
inline void sendRTCP();
#endif
}; };
} /* namespace mediakit */ } /* namespace mediakit */
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论