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,
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
*/ */
#include <atomic> #include <atomic>
#include <iomanip>
#include "Common/config.h" #include "Common/config.h"
#include "UDPServer.h" #include "UDPServer.h"
#include "RtspSession.h" #include "RtspSession.h"
...@@ -43,17 +44,11 @@ namespace mediakit { ...@@ -43,17 +44,11 @@ namespace mediakit {
static int kSockFlags = SOCKET_DEFAULE_FLAGS | FLAG_MORE; static int kSockFlags = SOCKET_DEFAULE_FLAGS | FLAG_MORE;
string dateHeader() {
char buf[200];
time_t tt = time(NULL);
strftime(buf, sizeof buf, "Date: %a, %b %d %Y %H:%M:%S GMT\r\n", gmtime(&tt));
return buf;
}
unordered_map<string, weak_ptr<RtspSession> > RtspSession::g_mapGetter; unordered_map<string, weak_ptr<RtspSession> > RtspSession::g_mapGetter;
unordered_map<void *, std::shared_ptr<RtspSession> > RtspSession::g_mapPostter; unordered_map<void *, std::shared_ptr<RtspSession> > RtspSession::g_mapPostter;
recursive_mutex RtspSession::g_mtxGetter; //对quicktime上锁保护 recursive_mutex RtspSession::g_mtxGetter; //对quicktime上锁保护
recursive_mutex RtspSession::g_mtxPostter; //对quicktime上锁保护 recursive_mutex RtspSession::g_mtxPostter; //对quicktime上锁保护
RtspSession::RtspSession(const std::shared_ptr<ThreadPool> &pTh, const Socket::Ptr &pSock) : RtspSession::RtspSession(const std::shared_ptr<ThreadPool> &pTh, const Socket::Ptr &pSock) :
TcpSession(pTh, pSock), _pSender(pSock) { TcpSession(pTh, pSock), _pSender(pSock) {
//设置10秒发送缓存 //设置10秒发送缓存
...@@ -152,41 +147,40 @@ void RtspSession::onManager() { ...@@ -152,41 +147,40 @@ void RtspSession::onManager() {
int64_t RtspSession::onRecvHeader(const char *header,uint64_t len) { int64_t RtspSession::onRecvHeader(const char *header,uint64_t len) {
char tmp[2 * 1024];
_pcBuf = tmp;
_parser.Parse(header); //rtsp请求解析 _parser.Parse(header); //rtsp请求解析
string strCmd = _parser.Method(); //提取出请求命令字 string strCmd = _parser.Method(); //提取出请求命令字
_iCseq = atoi(_parser["CSeq"].data()); _iCseq = atoi(_parser["CSeq"].data());
typedef bool (RtspSession::*rtspCMDHandle)(); typedef int (RtspSession::*rtsp_request_handler)();
static unordered_map<string, rtspCMDHandle> g_mapCmd; static unordered_map<string, rtsp_request_handler> s_handler_map;
static onceToken token( []() { static onceToken token( []() {
g_mapCmd.emplace("OPTIONS",&RtspSession::handleReq_Options); s_handler_map.emplace("OPTIONS",&RtspSession::handleReq_Options);
g_mapCmd.emplace("DESCRIBE",&RtspSession::handleReq_Describe); s_handler_map.emplace("DESCRIBE",&RtspSession::handleReq_Describe);
g_mapCmd.emplace("SETUP",&RtspSession::handleReq_Setup); s_handler_map.emplace("ANNOUNCE",&RtspSession::handleReq_ANNOUNCE);
g_mapCmd.emplace("PLAY",&RtspSession::handleReq_Play); s_handler_map.emplace("SETUP",&RtspSession::handleReq_Setup);
g_mapCmd.emplace("PAUSE",&RtspSession::handleReq_Pause); s_handler_map.emplace("PLAY",&RtspSession::handleReq_Play);
g_mapCmd.emplace("TEARDOWN",&RtspSession::handleReq_Teardown); s_handler_map.emplace("PAUSE",&RtspSession::handleReq_Pause);
g_mapCmd.emplace("GET",&RtspSession::handleReq_Get); s_handler_map.emplace("TEARDOWN",&RtspSession::handleReq_Teardown);
g_mapCmd.emplace("POST",&RtspSession::handleReq_Post); s_handler_map.emplace("GET",&RtspSession::handleReq_Get);
g_mapCmd.emplace("SET_PARAMETER",&RtspSession::handleReq_SET_PARAMETER); s_handler_map.emplace("POST",&RtspSession::handleReq_Post);
g_mapCmd.emplace("GET_PARAMETER",&RtspSession::handleReq_SET_PARAMETER); s_handler_map.emplace("SET_PARAMETER",&RtspSession::handleReq_SET_PARAMETER);
s_handler_map.emplace("GET_PARAMETER",&RtspSession::handleReq_SET_PARAMETER);
}, []() {}); }, []() {});
auto it = g_mapCmd.find(strCmd); auto it = s_handler_map.find(strCmd);
if (it != g_mapCmd.end()) { int ret = 0;
if (it != s_handler_map.end()) {
auto fun = it->second; auto fun = it->second;
if(!(this->*fun)()){ ret = (this->*fun)();
if(ret == -1){
shutdown(); shutdown();
} }
} else{ } else{
shutdown(); shutdown();
WarnL << "cmd=" << strCmd; WarnL << "不支持的rtsp命令:" << strCmd;
} }
_parser.Clear(); _parser.Clear();
return 0; return ret;
} }
...@@ -203,6 +197,7 @@ void RtspSession::onRecv(const Buffer::Ptr &pBuf) { ...@@ -203,6 +197,7 @@ void RtspSession::onRecv(const Buffer::Ptr &pBuf) {
} }
void RtspSession::inputRtspOrRtcp(const char *data,uint64_t len) { void RtspSession::inputRtspOrRtcp(const char *data,uint64_t len) {
// DebugL << data;
if(data[0] == '$' && _rtpType == PlayerBase::RTP_TCP){ if(data[0] == '$' && _rtpType == PlayerBase::RTP_TCP){
//这是rtcp //这是rtcp
return; return;
...@@ -210,23 +205,28 @@ void RtspSession::inputRtspOrRtcp(const char *data,uint64_t len) { ...@@ -210,23 +205,28 @@ void RtspSession::inputRtspOrRtcp(const char *data,uint64_t len) {
input(data,len); input(data,len);
} }
bool RtspSession::handleReq_Options() { int RtspSession::handleReq_Options() {
//支持这些命令 //支持这些命令
int n = sprintf(_pcBuf, sendRtspResponse("200 OK",{"Public" , "OPTIONS, DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE, ANNOUNCE, SET_PARAMETER, GET_PARAMETER"});
"RTSP/1.0 200 OK\r\n" return 0;
"CSeq: %d\r\n"
"Server: %s-%0.2f(build in %s)\r\n"
"%s"
"Public: OPTIONS, DESCRIBE, SETUP, TEARDOWN, PLAY,"
" PAUSE, SET_PARAMETER, GET_PARAMETER\r\n\r\n",
_iCseq, SERVER_NAME,
RTSP_VERSION, RTSP_BUILDTIME,
dateHeader().data());
SocketHelper::send(_pcBuf, n);
return true;
} }
bool RtspSession::handleReq_Describe() { void RtspSession::onRecvContent(const char *data, uint64_t len) {
// DebugL << data;
if(_onContent){
_onContent(data,len);
_onContent = nullptr;
}
}
int RtspSession::handleReq_ANNOUNCE() {
sendRtspResponse("200 OK");
_onContent = [this](const char *data, uint64_t len){
};
return atoi(_parser["Content-Length"].data());
}
int RtspSession::handleReq_Describe() {
{ {
//解析url获取媒体名称 //解析url获取媒体名称
_strUrl = _parser.Url(); _strUrl = _parser.Url();
...@@ -242,8 +242,6 @@ bool RtspSession::handleReq_Describe() { ...@@ -242,8 +242,6 @@ bool RtspSession::handleReq_Describe() {
} }
//恢复现场 //恢复现场
strongSelf->_parser = parserCopy; strongSelf->_parser = parserCopy;
char tmp[2 * 1024];
strongSelf->_pcBuf = tmp;
if(!success){ if(!success){
//未找到相应的MediaSource //未找到相应的MediaSource
...@@ -273,7 +271,7 @@ bool RtspSession::handleReq_Describe() { ...@@ -273,7 +271,7 @@ bool RtspSession::handleReq_Describe() {
invoker(""); invoker("");
} }
}); });
return true; return 0;
} }
void RtspSession::onAuthSuccess(const weak_ptr<RtspSession> &weakSelf) { void RtspSession::onAuthSuccess(const weak_ptr<RtspSession> &weakSelf) {
auto strongSelf = weakSelf.lock(); auto strongSelf = weakSelf.lock();
...@@ -287,22 +285,11 @@ void RtspSession::onAuthSuccess(const weak_ptr<RtspSession> &weakSelf) { ...@@ -287,22 +285,11 @@ void RtspSession::onAuthSuccess(const weak_ptr<RtspSession> &weakSelf) {
//本对象已销毁 //本对象已销毁
return; return;
} }
char response[2 * 1024]; strongSelf->sendRtspResponse("200 OK",
int n = sprintf(response, {"Content-Base",strongSelf->_strUrl,
"RTSP/1.0 200 OK\r\n" "x-Accept-Retransmit","our-retransmit",
"CSeq: %d\r\n" "x-Accept-Dynamic-Rate","1"
"Server: %s-%0.2f(build in %s)\r\n" },strongSelf->_strSdp);
"%s"
"x-Accept-Retransmit: our-retransmit\r\n"
"x-Accept-Dynamic-Rate: 1\r\n"
"Content-Base: %s/\r\n"
"Content-Type: application/sdp\r\n"
"Content-Length: %d\r\n\r\n%s",
strongSelf->_iCseq, SERVER_NAME,
RTSP_VERSION, RTSP_BUILDTIME,
dateHeader().data(), strongSelf->_strUrl.data(),
(int) strongSelf->_strSdp.length(), strongSelf->_strSdp.data());
strongSelf->SocketHelper::send(response, n);
}); });
} }
void RtspSession::onAuthFailed(const weak_ptr<RtspSession> &weakSelf,const string &realm) { void RtspSession::onAuthFailed(const weak_ptr<RtspSession> &weakSelf,const string &realm) {
...@@ -318,34 +305,21 @@ void RtspSession::onAuthFailed(const weak_ptr<RtspSession> &weakSelf,const strin ...@@ -318,34 +305,21 @@ void RtspSession::onAuthFailed(const weak_ptr<RtspSession> &weakSelf,const strin
return; return;
} }
int n;
char response[2 * 1024];
GET_CONFIG_AND_REGISTER(bool,authBasic,Rtsp::kAuthBasic); GET_CONFIG_AND_REGISTER(bool,authBasic,Rtsp::kAuthBasic);
if (!authBasic) { if (!authBasic) {
//我们需要客户端优先以md5方式认证 //我们需要客户端优先以md5方式认证
strongSelf->_strNonce = makeRandStr(32); strongSelf->_strNonce = makeRandStr(32);
n = sprintf(response, strongSelf->sendRtspResponse("401 Unauthorized",
"RTSP/1.0 401 Unauthorized\r\n" {"WWW-Authenticate",
"CSeq: %d\r\n" StrPrinter << "Digest realm=\"" << realm << "\",nonce=\"" << strongSelf->_strNonce << "\"" },
"Server: %s-%0.2f(build in %s)\r\n" strongSelf->_strSdp);
"%s"
"WWW-Authenticate: Digest realm=\"%s\",nonce=\"%s\"\r\n\r\n",
strongSelf->_iCseq, SERVER_NAME,
RTSP_VERSION, RTSP_BUILDTIME,
dateHeader().data(), realm.data(), strongSelf->_strNonce.data());
}else { }else {
//当然我们也支持base64认证,但是我们不建议这样做 //当然我们也支持base64认证,但是我们不建议这样做
n = sprintf(response, strongSelf->sendRtspResponse("401 Unauthorized",
"RTSP/1.0 401 Unauthorized\r\n" {"WWW-Authenticate",
"CSeq: %d\r\n" StrPrinter << "Basic realm=\"" << realm << "\"" },
"Server: %s-%0.2f(build in %s)\r\n" strongSelf->_strSdp);
"%s" }
"WWW-Authenticate: Basic realm=\"%s\"\r\n\r\n",
strongSelf->_iCseq, SERVER_NAME,
RTSP_VERSION, RTSP_BUILDTIME,
dateHeader().data(), realm.data());
}
strongSelf->SocketHelper::send(response, n);
}); });
} }
...@@ -488,62 +462,31 @@ void RtspSession::onAuthUser(const weak_ptr<RtspSession> &weakSelf,const string ...@@ -488,62 +462,31 @@ void RtspSession::onAuthUser(const weak_ptr<RtspSession> &weakSelf,const string
} }
} }
inline void RtspSession::send_StreamNotFound() { inline void RtspSession::send_StreamNotFound() {
int n = sprintf(_pcBuf, sendRtspResponse("404 Stream Not Found",{"Connection","Close"});
"RTSP/1.0 404 Stream Not Found\r\n"
"CSeq: %d\r\n"
"Server: %s-%0.2f(build in %s)\r\n"
"%s"
"Connection: Close\r\n\r\n",
_iCseq, SERVER_NAME,
RTSP_VERSION, RTSP_BUILDTIME,
dateHeader().data());
SocketHelper::send(_pcBuf, n);
} }
inline void RtspSession::send_UnsupportedTransport() { inline void RtspSession::send_UnsupportedTransport() {
int n = sprintf(_pcBuf, sendRtspResponse("461 Unsupported Transport",{"Connection","Close"});
"RTSP/1.0 461 Unsupported Transport\r\n"
"CSeq: %d\r\n"
"Server: %s-%0.2f(build in %s)\r\n"
"%s"
"Connection: Close\r\n\r\n",
_iCseq, SERVER_NAME,
RTSP_VERSION, RTSP_BUILDTIME,
dateHeader().data());
SocketHelper::send(_pcBuf, n);
} }
inline void RtspSession::send_SessionNotFound() { inline void RtspSession::send_SessionNotFound() {
int n = sprintf(_pcBuf, sendRtspResponse("454 Session Not Found",{"Connection","Close"});
"RTSP/1.0 454 Session Not Found\r\n"
"CSeq: %d\r\n"
"Server: %s-%0.2f(build in %s)\r\n"
"%s"
"Connection: Close\r\n\r\n",
_iCseq, SERVER_NAME,
RTSP_VERSION, RTSP_BUILDTIME,
dateHeader().data());
SocketHelper::send(_pcBuf, n);
/*40 Method Not Allowed*/
} }
bool RtspSession::handleReq_Setup() { int RtspSession::handleReq_Setup() {
//处理setup命令,该函数可能进入多次 //处理setup命令,该函数可能进入多次
auto controlSuffix = _parser.FullUrl().substr(1 + _parser.FullUrl().rfind('/')); auto controlSuffix = _parser.FullUrl().substr(1 + _parser.FullUrl().rfind('/'));
int trackIdx = getTrackIndexByControlSuffix(controlSuffix); int trackIdx = getTrackIndexByControlSuffix(controlSuffix);
if (trackIdx == -1) { if (trackIdx == -1) {
//未找到相应track //未找到相应track
return false; return -1;
} }
SdpTrack::Ptr &trackRef = _aTrackInfo[trackIdx]; SdpTrack::Ptr &trackRef = _aTrackInfo[trackIdx];
if (trackRef->_inited) { if (trackRef->_inited) {
//已经初始化过该Track //已经初始化过该Track
return false; return -1;
} }
trackRef->_inited = true; //现在初始化 trackRef->_inited = true; //现在初始化
if(!_bSetUped){ if(_rtpType == PlayerBase::RTP_Invalid){
_bSetUped = true;
auto strTransport = _parser["Transport"]; auto strTransport = _parser["Transport"];
if(strTransport.find("TCP") != string::npos){ if(strTransport.find("TCP") != string::npos){
_rtpType = PlayerBase::RTP_TCP; _rtpType = PlayerBase::RTP_TCP;
...@@ -556,23 +499,13 @@ bool RtspSession::handleReq_Setup() { ...@@ -556,23 +499,13 @@ bool RtspSession::handleReq_Setup() {
switch (_rtpType) { switch (_rtpType) {
case PlayerBase::RTP_TCP: { case PlayerBase::RTP_TCP: {
int iLen = sprintf(_pcBuf, sendRtspResponse("200 OK",
"RTSP/1.0 200 OK\r\n" {"Transport",StrPrinter << "RTP/AVP/TCP;unicast;"
"CSeq: %d\r\n" << "interleaved=" << trackRef->_type * 2 << "-" << trackRef->_type * 2 + 1 << ";"
"Server: %s-%0.2f(build in %s)\r\n" << "ssrc=" << printSSRC(trackRef->_ssrc) << ";mode=play",
"%s" "x-Transport-Options" , "late-tolerance=1.400000",
"Transport: RTP/AVP/TCP;unicast;" "x-Dynamic-Rate" , "1"
"interleaved=%d-%d;ssrc=%s;mode=play\r\n" });
"Session: %s\r\n"
"x-Transport-Options: late-tolerance=1.400000\r\n"
"x-Dynamic-Rate: 1\r\n\r\n",
_iCseq, SERVER_NAME,
RTSP_VERSION, RTSP_BUILDTIME,
dateHeader().data(), trackRef->_type * 2,
trackRef->_type * 2 + 1,
printSSRC(trackRef->_ssrc).data(),
_strSession.data());
SocketHelper::send(_pcBuf, iLen);
} }
break; break;
case PlayerBase::RTP_UDP: { case PlayerBase::RTP_UDP: {
...@@ -582,14 +515,14 @@ bool RtspSession::handleReq_Setup() { ...@@ -582,14 +515,14 @@ bool RtspSession::handleReq_Setup() {
//分配端口失败 //分配端口失败
WarnL << "分配rtp端口失败"; WarnL << "分配rtp端口失败";
send_NotAcceptable(); send_NotAcceptable();
return false; return -1;
} }
auto pSockRtcp = UDPServer::Instance().getSock(get_local_ip().data(),2*trackIdx + 1 ,pSockRtp->get_local_port() + 1); auto pSockRtcp = UDPServer::Instance().getSock(get_local_ip().data(),2*trackIdx + 1 ,pSockRtp->get_local_port() + 1);
if (!pSockRtcp) { if (!pSockRtcp) {
//分配端口失败 //分配端口失败
WarnL << "分配rtcp端口失败"; WarnL << "分配rtcp端口失败";
send_NotAcceptable(); send_NotAcceptable();
return false; return -1;
} }
_apUdpSock[trackIdx] = pSockRtp; _apUdpSock[trackIdx] = pSockRtp;
//设置客户端内网端口信息 //设置客户端内网端口信息
...@@ -604,21 +537,13 @@ bool RtspSession::handleReq_Setup() { ...@@ -604,21 +537,13 @@ bool RtspSession::handleReq_Setup() {
//尝试获取客户端nat映射地址 //尝试获取客户端nat映射地址
startListenPeerUdpData(); startListenPeerUdpData();
//InfoL << "分配端口:" << srv_port; //InfoL << "分配端口:" << srv_port;
int n = sprintf(_pcBuf,
"RTSP/1.0 200 OK\r\n" sendRtspResponse("200 OK",
"CSeq: %d\r\n" {"Transport",StrPrinter << "RTP/AVP/UDP;unicast;"
"Server: %s-%0.2f(build in %s)\r\n" << "client_port=" << strClientPort << ";"
"%s" << "server_port=" << pSockRtp->get_local_port() << "-" << pSockRtcp->get_local_port() << ";"
"Transport: RTP/AVP/UDP;unicast;" << "ssrc=" << printSSRC(trackRef->_ssrc) << ";mode=play"
"client_port=%s;server_port=%d-%d;ssrc=%s;mode=play\r\n" });
"Session: %s\r\n\r\n",
_iCseq, SERVER_NAME,
RTSP_VERSION, RTSP_BUILDTIME,
dateHeader().data(), strClientPort.data(),
pSockRtp->get_local_port(), pSockRtcp->get_local_port(),
printSSRC(trackRef->_ssrc).data(),
_strSession.data());
SocketHelper::send(_pcBuf, n);
} }
break; break;
case PlayerBase::RTP_MULTICAST: { case PlayerBase::RTP_MULTICAST: {
...@@ -626,7 +551,7 @@ bool RtspSession::handleReq_Setup() { ...@@ -626,7 +551,7 @@ bool RtspSession::handleReq_Setup() {
_pBrdcaster = RtpBroadCaster::get(get_local_ip(),_mediaInfo._vhost, _mediaInfo._app, _mediaInfo._streamid); _pBrdcaster = RtpBroadCaster::get(get_local_ip(),_mediaInfo._vhost, _mediaInfo._app, _mediaInfo._streamid);
if (!_pBrdcaster) { if (!_pBrdcaster) {
send_NotAcceptable(); send_NotAcceptable();
return false; return -1;
} }
weak_ptr<RtspSession> weakSelf = dynamic_pointer_cast<RtspSession>(shared_from_this()); weak_ptr<RtspSession> weakSelf = dynamic_pointer_cast<RtspSession>(shared_from_this());
_pBrdcaster->setDetachCB(this, [weakSelf]() { _pBrdcaster->setDetachCB(this, [weakSelf]() {
...@@ -644,56 +569,38 @@ bool RtspSession::handleReq_Setup() { ...@@ -644,56 +569,38 @@ bool RtspSession::handleReq_Setup() {
//分配端口失败 //分配端口失败
WarnL << "分配rtcp端口失败"; WarnL << "分配rtcp端口失败";
send_NotAcceptable(); send_NotAcceptable();
return false; return -1;
} }
startListenPeerUdpData(); startListenPeerUdpData();
GET_CONFIG_AND_REGISTER(uint32_t,udpTTL,MultiCast::kUdpTTL); GET_CONFIG_AND_REGISTER(uint32_t,udpTTL,MultiCast::kUdpTTL);
int n = sprintf(_pcBuf,
"RTSP/1.0 200 OK\r\n" sendRtspResponse("200 OK",
"CSeq: %d\r\n" {"Transport",StrPrinter << "RTP/AVP;multicast;"
"Server: %s-%0.2f(build in %s)\r\n" << "destination=" << _pBrdcaster->getIP() << ";"
"%s" << "source=" << get_local_ip() << ";"
"Transport: RTP/AVP;multicast;destination=%s;" << "port=" << iSrvPort << "-" << pSockRtcp->get_local_port() << ";"
"source=%s;port=%d-%d;ttl=%d;ssrc=%s\r\n" << "ttl=" << udpTTL << ";"
"Session: %s\r\n\r\n", << "ssrc=" << printSSRC(trackRef->_ssrc)
_iCseq, SERVER_NAME, });
RTSP_VERSION, RTSP_BUILDTIME,
dateHeader().data(), _pBrdcaster->getIP().data(),
get_local_ip().data(), iSrvPort, pSockRtcp->get_local_port(),
udpTTL, printSSRC(trackRef->_ssrc).data(),
_strSession.data());
SocketHelper::send(_pcBuf, n);
} }
break; break;
default: default:
break; break;
} }
return true; return 0;
} }
bool RtspSession::handleReq_Play() { int RtspSession::handleReq_Play() {
if (_aTrackInfo.empty() || _parser["Session"] != _strSession) { if (_aTrackInfo.empty() || _parser["Session"] != _strSession) {
send_SessionNotFound(); send_SessionNotFound();
return false; return -1;
} }
auto strRange = _parser["Range"]; auto strRange = _parser["Range"];
auto onRes = [this,strRange](const string &err){ auto onRes = [this,strRange](const string &err){
bool authSuccess = err.empty(); bool authSuccess = err.empty();
char response[2 * 1024];
_pcBuf = response;
if(!authSuccess){ if(!authSuccess){
//第一次play是播放,否则是恢复播放。只对播放鉴权 //第一次play是播放,否则是恢复播放。只对播放鉴权
int n = sprintf(_pcBuf, sendRtspResponse("401 Unauthorized", {"Content-Type", "text/plain"}, err);
"RTSP/1.0 401 Unauthorized\r\n"
"CSeq: %d\r\n"
"Server: %s-%0.2f(build in %s)\r\n"
"%s"
"Content-Type: text/plain\r\n"
"Content-Length: %d\r\n\r\n%s",
_iCseq, SERVER_NAME,
RTSP_VERSION, RTSP_BUILDTIME,
dateHeader().data(),(int)err.size(),err.data());
SocketHelper::send(_pcBuf,n);
shutdown(); shutdown();
return; return;
} }
...@@ -722,16 +629,8 @@ bool RtspSession::handleReq_Play() { ...@@ -722,16 +629,8 @@ bool RtspSession::handleReq_Play() {
pMediaSrc->seekTo(0); pMediaSrc->seekTo(0);
} }
_bFirstPlay = false; _bFirstPlay = false;
int iLen = sprintf(_pcBuf,
"RTSP/1.0 200 OK\r\n"
"CSeq: %d\r\n"
"Server: %s-%0.2f(build in %s)\r\n"
"%s"
"Session: %s\r\n"
"Range: npt=%.2f-\r\n"
"RTP-Info: ", _iCseq, SERVER_NAME, RTSP_VERSION, RTSP_BUILDTIME,
dateHeader().data(), _strSession.data(), pMediaSrc->getTimeStamp(TrackInvalid) / 1000.0);
_StrPrinter rtp_info;
for(auto &track : _aTrackInfo){ for(auto &track : _aTrackInfo){
if (track->_inited == false) { if (track->_inited == false) {
//还有track没有setup //还有track没有setup
...@@ -742,17 +641,17 @@ bool RtspSession::handleReq_Play() { ...@@ -742,17 +641,17 @@ bool RtspSession::handleReq_Play() {
track->_seq = pMediaSrc->getSeqence(track->_type); track->_seq = pMediaSrc->getSeqence(track->_type);
track->_time_stamp = pMediaSrc->getTimeStamp(track->_type); track->_time_stamp = pMediaSrc->getTimeStamp(track->_type);
iLen += sprintf(_pcBuf + iLen, "url=%s/%s;seq=%d;rtptime=%u,", rtp_info << "url=" << _strUrl << "/" << track->_control_surffix << ";"
_strUrl.data(), << "seq=" << track->_seq << ";"
track->_control_surffix.data(), << "rtptime=" << (int)(track->_time_stamp * (track->_samplerate / 1000)) << ",";
track->_seq,
track->_time_stamp * (track->_samplerate / 1000));
} }
iLen -= 1; rtp_info.pop_back();
(_pcBuf)[iLen] = '\0';
iLen += sprintf(_pcBuf + iLen, "\r\n\r\n"); sendRtspResponse("200 OK",
SocketHelper::send(_pcBuf, iLen); {"Range", StrPrinter << "npt=" << setiosflags(ios::fixed) << setprecision(2) << pMediaSrc->getTimeStamp(TrackInvalid) / 1000.0,
"RTP-Info",rtp_info
});
_enableSendRtp = true; _enableSendRtp = true;
...@@ -816,66 +715,51 @@ bool RtspSession::handleReq_Play() { ...@@ -816,66 +715,51 @@ bool RtspSession::handleReq_Play() {
//后面是seek或恢复命令,不需要鉴权 //后面是seek或恢复命令,不需要鉴权
onRes(""); onRes("");
} }
return true; return 0;
} }
bool RtspSession::handleReq_Pause() { int RtspSession::handleReq_Pause() {
if (_parser["Session"] != _strSession) { if (_parser["Session"] != _strSession) {
send_SessionNotFound(); send_SessionNotFound();
return false; return -1;
} }
int n = sprintf(_pcBuf,
"RTSP/1.0 200 OK\r\n" sendRtspResponse("200 OK");
"CSeq: %d\r\n"
"Server: %s-%0.2f(build in %s)\r\n"
"%s"
"Session: %s\r\n\r\n", _iCseq, SERVER_NAME, RTSP_VERSION, RTSP_BUILDTIME,
dateHeader().data(), _strSession.data());
SocketHelper::send(_pcBuf, n);
_enableSendRtp = false; _enableSendRtp = false;
return true; return 0;
} }
bool RtspSession::handleReq_Teardown() { int RtspSession::handleReq_Teardown() {
int n = sprintf(_pcBuf, sendRtspResponse("200 OK");
"RTSP/1.0 200 OK\r\n"
"CSeq: %d\r\n"
"Server: %s-%0.2f(build in %s)\r\n"
"%s"
"Session: %s\r\n\r\n", _iCseq, SERVER_NAME, RTSP_VERSION, RTSP_BUILDTIME,
dateHeader().data(), _strSession.data());
SocketHelper::send(_pcBuf, n);
TraceL << "播放器断开连接!"; TraceL << "播放器断开连接!";
return false; return 0;
} }
bool RtspSession::handleReq_Get() { int RtspSession::handleReq_Get() {
_strSessionCookie = _parser["x-sessioncookie"]; _strSessionCookie = _parser["x-sessioncookie"];
int n = sprintf(_pcBuf, sendRtspResponse("200 OK",
"HTTP/1.0 200 OK\r\n" {"Connection","Close",
"%s" "Cache-Control","no-store",
"Connection: close\r\n" "Pragma","no-store",
"Cache-Control: no-store\r\n" "Content-Type","application/x-rtsp-tunnelled",
"Pragma: no-cache\r\n" },"","HTTP/1.0");
"Content-Type: application/x-rtsp-tunnelled\r\n\r\n",
dateHeader().data()); //注册GET
//注册GET
lock_guard<recursive_mutex> lock(g_mtxGetter); lock_guard<recursive_mutex> lock(g_mtxGetter);
g_mapGetter[_strSessionCookie] = dynamic_pointer_cast<RtspSession>(shared_from_this()); g_mapGetter[_strSessionCookie] = dynamic_pointer_cast<RtspSession>(shared_from_this());
//InfoL << _strSessionCookie; //InfoL << _strSessionCookie;
SocketHelper::send(_pcBuf, n); return 0;
return true;
} }
bool RtspSession::handleReq_Post() { int RtspSession::handleReq_Post() {
lock_guard<recursive_mutex> lock(g_mtxGetter); lock_guard<recursive_mutex> lock(g_mtxGetter);
string sessioncookie = _parser["x-sessioncookie"]; string sessioncookie = _parser["x-sessioncookie"];
//Poster 找到 Getter //Poster 找到 Getter
auto it = g_mapGetter.find(sessioncookie); auto it = g_mapGetter.find(sessioncookie);
if (it == g_mapGetter.end()) { if (it == g_mapGetter.end()) {
//WarnL << sessioncookie; //WarnL << sessioncookie;
return false; return -1;
} }
_bBase64need = true; _bBase64need = true;
//Poster 找到Getter的SOCK //Poster 找到Getter的SOCK
...@@ -884,35 +768,34 @@ bool RtspSession::handleReq_Post() { ...@@ -884,35 +768,34 @@ bool RtspSession::handleReq_Post() {
if (!strongSession) { if (!strongSession) {
send_SessionNotFound(); send_SessionNotFound();
//WarnL; //WarnL;
return false; return -1;
} }
initSender(strongSession); initSender(strongSession);
return true; auto nextPacketSize = remainDataSize();
if(nextPacketSize > 0){
_onContent = [this](const char *data,uint64_t len){
BufferRaw::Ptr buffer = std::make_shared<BufferRaw>();
buffer->assign(data,len);
weak_ptr<RtspSession> weakSelf = dynamic_pointer_cast<RtspSession>(shared_from_this());
async([weakSelf,buffer](){
auto strongSelf = weakSelf.lock();
if(strongSelf){
strongSelf->onRecv(buffer);
}
},false);
};
}
return nextPacketSize;
} }
bool RtspSession::handleReq_SET_PARAMETER() { int RtspSession::handleReq_SET_PARAMETER() {
//TraceL<<endl; //TraceL<<endl;
int n = sprintf(_pcBuf, sendRtspResponse("200 OK");
"RTSP/1.0 200 OK\r\n" return 0;
"CSeq: %d\r\n"
"Server: %s-%0.2f(build in %s)\r\n"
"%s"
"Session: %s\r\n\r\n", _iCseq, SERVER_NAME, RTSP_VERSION, RTSP_BUILDTIME,
dateHeader().data(), _strSession.data());
SocketHelper::send(_pcBuf, n);
return true;
} }
inline void RtspSession::send_NotAcceptable() { inline void RtspSession::send_NotAcceptable() {
int n = sprintf(_pcBuf, sendRtspResponse("406 Not Acceptable",{"Connection","Close"});
"RTSP/1.0 406 Not Acceptable\r\n"
"CSeq: %d\r\n"
"Server: %s-%0.2f(build in %s)\r\n"
"%s"
"Connection: Close\r\n\r\n", _iCseq, SERVER_NAME, RTSP_VERSION, RTSP_BUILDTIME,
dateHeader().data());
SocketHelper::send(_pcBuf, n);
} }
void RtspSession::doDelay(int delaySec, const std::function<void()> &fun) { void RtspSession::doDelay(int delaySec, const std::function<void()> &fun) {
...@@ -990,8 +873,8 @@ inline bool RtspSession::findStream() { ...@@ -990,8 +873,8 @@ inline bool RtspSession::findStream() {
return false; return false;
} }
_strSdp = pMediaSrc->getSdp(); _strSdp = pMediaSrc->getSdp();
_sdpAttr.load(_strSdp); SdpAttr sdpAttr(_strSdp);
_aTrackInfo = _sdpAttr.getAvailableTrack(); _aTrackInfo = sdpAttr.getAvailableTrack();
if (_aTrackInfo.empty()) { if (_aTrackInfo.empty()) {
return false; return false;
...@@ -1121,6 +1004,95 @@ inline void RtspSession::initSender(const std::shared_ptr<RtspSession>& session) ...@@ -1121,6 +1004,95 @@ inline void RtspSession::initSender(const std::shared_ptr<RtspSession>& session)
session->shutdown_l(false); session->shutdown_l(false);
} }
static string dateStr(){
char buf[64];
time_t tt = time(NULL);
strftime(buf, sizeof buf, "%a, %b %d %Y %H:%M:%S GMT", gmtime(&tt));
return buf;
}
bool RtspSession::sendRtspResponse(const string &res_code,
const StrCaseMap &header_const,
const string &sdp,
const char *protocol){
auto header = header_const;
header.emplace("CSeq",StrPrinter << _iCseq);
if(!_strSession.empty()){
header.emplace("Session",_strSession);
}
header.emplace("Server",SERVER_NAME "(build in " __DATE__ " " __TIME__ ")");
header.emplace("Date",dateStr());
if(!sdp.empty()){
header.emplace("Content-Length",StrPrinter << sdp.size());
header.emplace("Content-Type","application/sdp");
}
_StrPrinter printer;
printer << protocol << " " << res_code << "\r\n";
for (auto &pr : header){
printer << pr.first << ": " << pr.second << "\r\n";
}
printer << "\r\n";
if(!sdp.empty()){
printer << sdp;
}
// DebugL << printer;
return send(std::make_shared<BufferString>(printer)) > 0 ;
}
int RtspSession::send(const Buffer::Ptr &pkt){
_ui64TotalBytes += pkt->size();
return _pSender->send(pkt,_flags);
}
bool RtspSession::sendRtspResponse(const string &res_code,
const std::initializer_list<string> &header,
const string &sdp,
const char *protocol) {
string key;
StrCaseMap header_map;
int i = 0;
for(auto &val : header){
if(++i % 2 == 0){
header_map.emplace(key,val);
}else{
key = val;
}
}
return sendRtspResponse(res_code,header_map,sdp,protocol);
}
inline string RtspSession::printSSRC(uint32_t ui32Ssrc) {
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 RtspSession::getTrackIndexByTrackType(TrackType type) {
for (unsigned int i = 0; i < _aTrackInfo.size(); i++) {
if (type == _aTrackInfo[i]->_type) {
return i;
}
}
return -1;
}
inline int RtspSession::getTrackIndexByControlSuffix(const string &controlSuffix) {
for (unsigned int i = 0; i < _aTrackInfo.size(); i++) {
if (controlSuffix == _aTrackInfo[i]->_control_surffix) {
return i;
}
}
return -1;
}
#ifdef RTSP_SEND_RTCP #ifdef RTSP_SEND_RTCP
inline void RtspSession::sendRTCP() { inline void RtspSession::sendRTCP() {
//DebugL; //DebugL;
......
...@@ -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 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论