完成rtsp推流
This commit is contained in:
parent
212a761e7f
commit
d2a78e5a40
|
|
@ -42,8 +42,6 @@ using namespace toolkit;
|
||||||
|
|
||||||
namespace mediakit {
|
namespace mediakit {
|
||||||
|
|
||||||
static int kSockFlags = SOCKET_DEFAULE_FLAGS | FLAG_MORE;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* rtsp协议有多种方式传输rtp数据包,目前已支持包括以下4种
|
* rtsp协议有多种方式传输rtp数据包,目前已支持包括以下4种
|
||||||
* 1: rtp over udp ,这种方式是rtp通过单独的udp端口传输
|
* 1: rtp over udp ,这种方式是rtp通过单独的udp端口传输
|
||||||
|
|
@ -72,6 +70,8 @@ static unordered_map<string, weak_ptr<RtspSession> > g_mapGetter;
|
||||||
//对g_mapGetter上锁保护
|
//对g_mapGetter上锁保护
|
||||||
static recursive_mutex g_mtxGetter;
|
static recursive_mutex g_mtxGetter;
|
||||||
|
|
||||||
|
static int kSockFlags = SOCKET_DEFAULE_FLAGS | FLAG_MORE;
|
||||||
|
|
||||||
RtspSession::RtspSession(const std::shared_ptr<ThreadPool> &pTh, const Socket::Ptr &pSock) : TcpSession(pTh, pSock) {
|
RtspSession::RtspSession(const std::shared_ptr<ThreadPool> &pTh, const Socket::Ptr &pSock) : TcpSession(pTh, pSock) {
|
||||||
//设置10秒发送缓存
|
//设置10秒发送缓存
|
||||||
pSock->setSendBufSecond(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) {
|
void RtspSession::onWholeRtspPacket(Parser &parser) {
|
||||||
_parser.Parse(header); //rtsp请求解析
|
string strCmd = parser.Method(); //提取出请求命令字
|
||||||
string strCmd = _parser.Method(); //提取出请求命令字
|
_iCseq = atoi(parser["CSeq"].data());
|
||||||
_iCseq = atoi(_parser["CSeq"].data());
|
|
||||||
|
|
||||||
typedef int (RtspSession::*rtsp_request_handler)();
|
typedef bool (RtspSession::*rtsp_request_handler)(const Parser &parser);
|
||||||
static unordered_map<string, rtsp_request_handler> s_handler_map;
|
static unordered_map<string, rtsp_request_handler> s_handler_map;
|
||||||
static onceToken token( []() {
|
static onceToken token( []() {
|
||||||
s_handler_map.emplace("OPTIONS",&RtspSession::handleReq_Options);
|
s_handler_map.emplace("OPTIONS",&RtspSession::handleReq_Options);
|
||||||
s_handler_map.emplace("DESCRIBE",&RtspSession::handleReq_Describe);
|
s_handler_map.emplace("DESCRIBE",&RtspSession::handleReq_Describe);
|
||||||
s_handler_map.emplace("ANNOUNCE",&RtspSession::handleReq_ANNOUNCE);
|
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("SETUP",&RtspSession::handleReq_Setup);
|
||||||
s_handler_map.emplace("PLAY",&RtspSession::handleReq_Play);
|
s_handler_map.emplace("PLAY",&RtspSession::handleReq_Play);
|
||||||
s_handler_map.emplace("PAUSE",&RtspSession::handleReq_Pause);
|
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);
|
auto it = s_handler_map.find(strCmd);
|
||||||
int ret = 0;
|
|
||||||
if (it != s_handler_map.end()) {
|
if (it != s_handler_map.end()) {
|
||||||
auto fun = it->second;
|
auto &fun = it->second;
|
||||||
ret = (this->*fun)();
|
if(!(this->*fun)(parser)){
|
||||||
if(ret == -1){
|
|
||||||
shutdown();
|
shutdown();
|
||||||
}
|
}
|
||||||
} else{
|
} else{
|
||||||
shutdown();
|
shutdown();
|
||||||
WarnL << "不支持的rtsp命令:" << strCmd;
|
WarnL << "不支持的rtsp命令:" << strCmd;
|
||||||
}
|
}
|
||||||
_parser.Clear();
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RtspSession::onRtpPacket(const char *data, uint64_t len) {
|
||||||
void RtspSession::onRecv(const Buffer::Ptr &pBuf) {
|
if(len > 1600){
|
||||||
_ticker.resetTime();
|
//没有大于MTU的包
|
||||||
_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
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
input(data,len);
|
int trackIdx = -1;
|
||||||
}
|
uint8_t interleaved = data[1];
|
||||||
|
if(interleaved %2 == 0){
|
||||||
int RtspSession::handleReq_Options() {
|
trackIdx = getTrackIndexByInterleaved(interleaved);
|
||||||
//支持这些命令
|
}
|
||||||
sendRtspResponse("200 OK",{"Public" , "OPTIONS, DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE, ANNOUNCE, RECORD, SET_PARAMETER, GET_PARAMETER"});
|
if (trackIdx != -1) {
|
||||||
return 0;
|
handleOneRtp(trackIdx,_aTrackInfo[trackIdx],(unsigned char *)data + 4, len - 4);
|
||||||
}
|
|
||||||
|
|
||||||
void RtspSession::onRecvContent(const char *data, uint64_t len) {
|
|
||||||
// DebugL << data;
|
|
||||||
if(_onContent){
|
|
||||||
_onContent(data,len);
|
|
||||||
_onContent = nullptr;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int RtspSession::handleReq_ANNOUNCE() {
|
int64_t RtspSession::getContentLength(Parser &parser) {
|
||||||
auto parseCopy = _parser;
|
if(parser.Method() == "POST"){
|
||||||
_onContent = [this,parseCopy](const char *data, uint64_t len){
|
//http post请求的content数据部分是base64编码后的rtsp请求信令包
|
||||||
_parser = parseCopy;
|
return remainDataSize();
|
||||||
_strSdp.assign(data,len);
|
}
|
||||||
//解析url获取媒体名称
|
return RtspSplitter::getContentLength(parser);
|
||||||
_mediaInfo.parse(_parser.FullUrl());
|
|
||||||
|
|
||||||
auto src = dynamic_pointer_cast<RtmpMediaSource>(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<RtspToRtmpMediaSource>(_mediaInfo._vhost,_mediaInfo._app,_mediaInfo._streamid);
|
|
||||||
_pushSrc->setListener(dynamic_pointer_cast<MediaSourceEvent>(shared_from_this()));
|
|
||||||
_pushSrc->onGetSDP(_strSdp);
|
|
||||||
sendRtspResponse("200 OK");
|
|
||||||
};
|
|
||||||
return atoi(_parser["Content-Length"].data());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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<RtmpMediaSource>(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<RtspToRtmpMediaSource>(_mediaInfo._vhost,_mediaInfo._app,_mediaInfo._streamid);
|
||||||
|
_pushSrc->setListener(dynamic_pointer_cast<MediaSourceEvent>(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();
|
send_SessionNotFound();
|
||||||
return -1;
|
return false;
|
||||||
}
|
}
|
||||||
auto onRes = [this](const string &err){
|
auto onRes = [this](const string &err){
|
||||||
bool authSuccess = err.empty();
|
bool authSuccess = err.empty();
|
||||||
|
|
@ -295,26 +291,23 @@ int RtspSession::handleReq_RECORD(){
|
||||||
//该事件无人监听,默认不鉴权
|
//该事件无人监听,默认不鉴权
|
||||||
onRes("");
|
onRes("");
|
||||||
}
|
}
|
||||||
return 0;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int RtspSession::handleReq_Describe() {
|
bool RtspSession::handleReq_Describe(const Parser &parser) {
|
||||||
{
|
//解析url获取媒体名称
|
||||||
//解析url获取媒体名称
|
_strUrl = parser.Url();
|
||||||
_strUrl = _parser.Url();
|
_mediaInfo.parse(parser.FullUrl());
|
||||||
_mediaInfo.parse(_parser.FullUrl());
|
|
||||||
}
|
|
||||||
|
|
||||||
weak_ptr<RtspSession> weakSelf = dynamic_pointer_cast<RtspSession>(shared_from_this());\
|
weak_ptr<RtspSession> weakSelf = dynamic_pointer_cast<RtspSession>(shared_from_this());
|
||||||
auto parserCopy = _parser;
|
auto authorization = parser["Authorization"];
|
||||||
findStream([weakSelf,parserCopy](bool success){
|
|
||||||
|
findStream([weakSelf,authorization](bool success){
|
||||||
auto strongSelf = weakSelf.lock();
|
auto strongSelf = weakSelf.lock();
|
||||||
if(!strongSelf){
|
if(!strongSelf){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
//恢复现场
|
|
||||||
strongSelf->_parser = parserCopy;
|
|
||||||
|
|
||||||
if(!success){
|
if(!success){
|
||||||
//未找到相应的MediaSource
|
//未找到相应的MediaSource
|
||||||
|
|
@ -324,7 +317,6 @@ int RtspSession::handleReq_Describe() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
//该请求中的认证信息
|
//该请求中的认证信息
|
||||||
auto authorization = strongSelf->_parser["Authorization"];
|
|
||||||
onGetRealm invoker = [weakSelf,authorization](const string &realm){
|
onGetRealm invoker = [weakSelf,authorization](const string &realm){
|
||||||
if(realm.empty()){
|
if(realm.empty()){
|
||||||
//无需认证,回复sdp
|
//无需认证,回复sdp
|
||||||
|
|
@ -344,7 +336,7 @@ int RtspSession::handleReq_Describe() {
|
||||||
invoker("");
|
invoker("");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return 0;
|
return true;
|
||||||
}
|
}
|
||||||
void RtspSession::onAuthSuccess(const weak_ptr<RtspSession> &weakSelf) {
|
void RtspSession::onAuthSuccess(const weak_ptr<RtspSession> &weakSelf) {
|
||||||
auto strongSelf = weakSelf.lock();
|
auto strongSelf = weakSelf.lock();
|
||||||
|
|
@ -544,23 +536,23 @@ inline void RtspSession::send_UnsupportedTransport() {
|
||||||
inline void RtspSession::send_SessionNotFound() {
|
inline void RtspSession::send_SessionNotFound() {
|
||||||
sendRtspResponse("454 Session Not Found",{"Connection","Close"});
|
sendRtspResponse("454 Session Not Found",{"Connection","Close"});
|
||||||
}
|
}
|
||||||
int RtspSession::handleReq_Setup() {
|
bool RtspSession::handleReq_Setup(const Parser &parser) {
|
||||||
//处理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 -1;
|
return false;
|
||||||
}
|
}
|
||||||
SdpTrack::Ptr &trackRef = _aTrackInfo[trackIdx];
|
SdpTrack::Ptr &trackRef = _aTrackInfo[trackIdx];
|
||||||
if (trackRef->_inited) {
|
if (trackRef->_inited) {
|
||||||
//已经初始化过该Track
|
//已经初始化过该Track
|
||||||
return -1;
|
return false;
|
||||||
}
|
}
|
||||||
trackRef->_inited = true; //现在初始化
|
trackRef->_inited = true; //现在初始化
|
||||||
|
|
||||||
if(_rtpType == PlayerBase::RTP_Invalid){
|
if(_rtpType == PlayerBase::RTP_Invalid){
|
||||||
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;
|
||||||
}else if(strTransport.find("multicast") != string::npos){
|
}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) {
|
switch (_rtpType) {
|
||||||
case PlayerBase::RTP_TCP: {
|
case PlayerBase::RTP_TCP: {
|
||||||
|
trackRef->_interleaved = trackRef->_type * 2;
|
||||||
sendRtspResponse("200 OK",
|
sendRtspResponse("200 OK",
|
||||||
{"Transport",StrPrinter << "RTP/AVP/TCP;unicast;"
|
{"Transport",StrPrinter << "RTP/AVP/TCP;unicast;"
|
||||||
<< "interleaved=" << trackRef->_type * 2 << "-" << trackRef->_type * 2 + 1 << ";"
|
<< "interleaved=" << trackRef->_type * 2 << "-" << trackRef->_type * 2 + 1 << ";"
|
||||||
|
|
@ -588,19 +584,19 @@ int RtspSession::handleReq_Setup() {
|
||||||
//分配端口失败
|
//分配端口失败
|
||||||
WarnL << "分配rtp端口失败";
|
WarnL << "分配rtp端口失败";
|
||||||
send_NotAcceptable();
|
send_NotAcceptable();
|
||||||
return -1;
|
return false;
|
||||||
}
|
}
|
||||||
auto pSockRtcp = std::make_shared<Socket>(_sock->getPoller());
|
auto pSockRtcp = std::make_shared<Socket>(_sock->getPoller());
|
||||||
if (!pSockRtcp->bindUdpSock(pSockRtp->get_local_port() + 1,get_local_ip().data())) {
|
if (!pSockRtcp->bindUdpSock(pSockRtp->get_local_port() + 1,get_local_ip().data())) {
|
||||||
//分配端口失败
|
//分配端口失败
|
||||||
WarnL << "分配rtcp端口失败";
|
WarnL << "分配rtcp端口失败";
|
||||||
send_NotAcceptable();
|
send_NotAcceptable();
|
||||||
return -1;
|
return false;
|
||||||
}
|
}
|
||||||
_apRtpSock[trackIdx] = pSockRtp;
|
_apRtpSock[trackIdx] = pSockRtp;
|
||||||
_apRtcpSock[trackIdx] = pSockRtcp;
|
_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());
|
uint16_t ui16PeerPort = atoi( FindField(strClientPort.data(), NULL, "-").data());
|
||||||
struct sockaddr_in peerAddr;
|
struct sockaddr_in peerAddr;
|
||||||
peerAddr.sin_family = AF_INET;
|
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);
|
_pBrdcaster = RtpBroadCaster::get(get_local_ip(),_mediaInfo._vhost, _mediaInfo._app, _mediaInfo._streamid);
|
||||||
if (!_pBrdcaster) {
|
if (!_pBrdcaster) {
|
||||||
send_NotAcceptable();
|
send_NotAcceptable();
|
||||||
return -1;
|
return false;
|
||||||
}
|
}
|
||||||
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,7 +640,7 @@ int RtspSession::handleReq_Setup() {
|
||||||
//分配端口失败
|
//分配端口失败
|
||||||
WarnL << "分配rtcp端口失败";
|
WarnL << "分配rtcp端口失败";
|
||||||
send_NotAcceptable();
|
send_NotAcceptable();
|
||||||
return -1;
|
return false;
|
||||||
}
|
}
|
||||||
startListenPeerUdpData(trackIdx);
|
startListenPeerUdpData(trackIdx);
|
||||||
GET_CONFIG_AND_REGISTER(uint32_t,udpTTL,MultiCast::kUdpTTL);
|
GET_CONFIG_AND_REGISTER(uint32_t,udpTTL,MultiCast::kUdpTTL);
|
||||||
|
|
@ -662,15 +658,15 @@ int RtspSession::handleReq_Setup() {
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return 0;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int RtspSession::handleReq_Play() {
|
bool RtspSession::handleReq_Play(const Parser &parser) {
|
||||||
if (_aTrackInfo.empty() || _parser["Session"] != _strSession) {
|
if (_aTrackInfo.empty() || parser["Session"] != _strSession) {
|
||||||
send_SessionNotFound();
|
send_SessionNotFound();
|
||||||
return -1;
|
return false;
|
||||||
}
|
}
|
||||||
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();
|
||||||
if(!authSuccess){
|
if(!authSuccess){
|
||||||
|
|
@ -750,9 +746,6 @@ int RtspSession::handleReq_Play() {
|
||||||
if(!strongSelf) {
|
if(!strongSelf) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(!strongSelf->_enableSendRtp) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
strongSelf->async([weakSelf,pack](){
|
strongSelf->async([weakSelf,pack](){
|
||||||
auto strongSelf = weakSelf.lock();
|
auto strongSelf = weakSelf.lock();
|
||||||
if(!strongSelf) {
|
if(!strongSelf) {
|
||||||
|
|
@ -791,28 +784,28 @@ int RtspSession::handleReq_Play() {
|
||||||
//后面是seek或恢复命令,不需要鉴权
|
//后面是seek或恢复命令,不需要鉴权
|
||||||
onRes("");
|
onRes("");
|
||||||
}
|
}
|
||||||
return 0;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int RtspSession::handleReq_Pause() {
|
bool RtspSession::handleReq_Pause(const Parser &parser) {
|
||||||
if (_parser["Session"] != _strSession) {
|
if (parser["Session"] != _strSession) {
|
||||||
send_SessionNotFound();
|
send_SessionNotFound();
|
||||||
return -1;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
sendRtspResponse("200 OK");
|
sendRtspResponse("200 OK");
|
||||||
_enableSendRtp = false;
|
_enableSendRtp = false;
|
||||||
return 0;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int RtspSession::handleReq_Teardown() {
|
bool RtspSession::handleReq_Teardown(const Parser &parser) {
|
||||||
sendRtspResponse("200 OK");
|
sendRtspResponse("200 OK");
|
||||||
TraceL << "播放器断开连接!";
|
TraceL << "播放器断开连接!";
|
||||||
return 0;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int RtspSession::handleReq_Get() {
|
bool RtspSession::handleReq_Get(const Parser &parser) {
|
||||||
_http_x_sessioncookie = _parser["x-sessioncookie"];
|
_http_x_sessioncookie = parser["x-sessioncookie"];
|
||||||
sendRtspResponse("200 OK",
|
sendRtspResponse("200 OK",
|
||||||
{"Connection","Close",
|
{"Connection","Close",
|
||||||
"Cache-Control","no-store",
|
"Cache-Control","no-store",
|
||||||
|
|
@ -823,18 +816,18 @@ int RtspSession::handleReq_Get() {
|
||||||
//注册http getter,以便http poster绑定
|
//注册http getter,以便http poster绑定
|
||||||
lock_guard<recursive_mutex> lock(g_mtxGetter);
|
lock_guard<recursive_mutex> lock(g_mtxGetter);
|
||||||
g_mapGetter[_http_x_sessioncookie] = dynamic_pointer_cast<RtspSession>(shared_from_this());
|
g_mapGetter[_http_x_sessioncookie] = dynamic_pointer_cast<RtspSession>(shared_from_this());
|
||||||
return 0;
|
return true;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int RtspSession::handleReq_Post() {
|
bool RtspSession::handleReq_Post(const Parser &parser) {
|
||||||
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 << "Http Poster未找到Http Getter";
|
WarnL << "Http Poster未找到Http Getter";
|
||||||
return -1;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Poster 找到Getter的SOCK
|
//Poster 找到Getter的SOCK
|
||||||
|
|
@ -842,22 +835,6 @@ int RtspSession::handleReq_Post() {
|
||||||
//移除http getter的弱引用记录
|
//移除http getter的弱引用记录
|
||||||
g_mapGetter.erase(sessioncookie);
|
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<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);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
//http poster收到请求后转发给http getter处理
|
//http poster收到请求后转发给http getter处理
|
||||||
_onRecv = [this,httpGetterWeak](const Buffer::Ptr &pBuf){
|
_onRecv = [this,httpGetterWeak](const Buffer::Ptr &pBuf){
|
||||||
auto httpGetterStrong = httpGetterWeak.lock();
|
auto httpGetterStrong = httpGetterWeak.lock();
|
||||||
|
|
@ -877,13 +854,17 @@ int RtspSession::handleReq_Post() {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
return nextPacketSize;
|
if(!parser.Content().empty()){
|
||||||
|
//http poster后面的粘包
|
||||||
|
_onRecv(std::make_shared<BufferString>(parser.Content()));
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int RtspSession::handleReq_SET_PARAMETER() {
|
bool RtspSession::handleReq_SET_PARAMETER(const Parser &parser) {
|
||||||
//TraceL<<endl;
|
//TraceL<<endl;
|
||||||
sendRtspResponse("200 OK");
|
sendRtspResponse("200 OK");
|
||||||
return 0;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void RtspSession::send_NotAcceptable() {
|
inline void RtspSession::send_NotAcceptable() {
|
||||||
|
|
@ -1027,7 +1008,7 @@ inline void RtspSession::sendRtpPacket(const RtpPacket::Ptr & pkt) {
|
||||||
|
|
||||||
void RtspSession::onRtpSorted(const RtpPacket::Ptr &rtppt, int trackidx) {
|
void RtspSession::onRtpSorted(const RtpPacket::Ptr &rtppt, int trackidx) {
|
||||||
if(_pushSrc){
|
if(_pushSrc){
|
||||||
_pushSrc->onWrite(rtppt,true);
|
_pushSrc->onWrite(rtppt, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
inline void RtspSession::onRcvPeerUdpData(int iTrackIdx, const Buffer::Ptr &pBuf, const struct sockaddr& addr) {
|
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){
|
int RtspSession::send(const Buffer::Ptr &pkt){
|
||||||
|
// if(!_enableSendRtp){
|
||||||
|
// DebugL << pkt->data();
|
||||||
|
// }
|
||||||
_ui64TotalBytes += pkt->size();
|
_ui64TotalBytes += pkt->size();
|
||||||
return TcpSession::send(pkt);
|
return TcpSession::send(pkt);
|
||||||
}
|
}
|
||||||
|
|
@ -1200,6 +1184,15 @@ inline int RtspSession::getTrackIndexByControlSuffix(const string &controlSuffix
|
||||||
return -1;
|
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() {
|
bool RtspSession::close() {
|
||||||
InfoL << "kick out:" << _mediaInfo._vhost << " " << _mediaInfo._app << " " << _mediaInfo._streamid;
|
InfoL << "kick out:" << _mediaInfo._vhost << " " << _mediaInfo._app << " " << _mediaInfo._streamid;
|
||||||
safeShutdown();
|
safeShutdown();
|
||||||
|
|
|
||||||
|
|
@ -30,15 +30,15 @@
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
#include "Util/util.h"
|
||||||
|
#include "Util/logger.h"
|
||||||
#include "Common/config.h"
|
#include "Common/config.h"
|
||||||
|
#include "Network/TcpSession.h"
|
||||||
|
#include "Player/PlayerBase.h"
|
||||||
#include "Rtsp.h"
|
#include "Rtsp.h"
|
||||||
#include "RtpBroadCaster.h"
|
#include "RtpBroadCaster.h"
|
||||||
#include "RtspMediaSource.h"
|
#include "RtspMediaSource.h"
|
||||||
#include "Player/PlayerBase.h"
|
#include "RtspSplitter.h"
|
||||||
#include "Util/util.h"
|
|
||||||
#include "Util/logger.h"
|
|
||||||
#include "Network/TcpSession.h"
|
|
||||||
#include "Http/HttpRequestSplitter.h"
|
|
||||||
#include "RtpReceiver.h"
|
#include "RtpReceiver.h"
|
||||||
#include "RtspToRtmpMediaSource.h"
|
#include "RtspToRtmpMediaSource.h"
|
||||||
|
|
||||||
|
|
@ -66,7 +66,7 @@ private:
|
||||||
uint32_t _offset;
|
uint32_t _offset;
|
||||||
};
|
};
|
||||||
|
|
||||||
class RtspSession: public TcpSession, public HttpRequestSplitter, public RtpReceiver , public MediaSourceEvent{
|
class RtspSession: public TcpSession, public RtspSplitter, public RtpReceiver , public MediaSourceEvent{
|
||||||
public:
|
public:
|
||||||
typedef std::shared_ptr<RtspSession> Ptr;
|
typedef std::shared_ptr<RtspSession> Ptr;
|
||||||
typedef std::function<void(const string &realm)> onGetRealm;
|
typedef std::function<void(const string &realm)> onGetRealm;
|
||||||
|
|
@ -80,26 +80,43 @@ public:
|
||||||
void onError(const SockException &err) override;
|
void onError(const SockException &err) override;
|
||||||
void onManager() override;
|
void onManager() override;
|
||||||
protected:
|
protected:
|
||||||
//HttpRequestSplitter override
|
//RtspSplitter override
|
||||||
int64_t onRecvHeader(const char *data,uint64_t len) override ;
|
/**
|
||||||
void onRecvContent(const char *data,uint64_t len) 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
|
//RtpReceiver override
|
||||||
void onRtpSorted(const RtpPacket::Ptr &rtppt, int trackidx) override;
|
void onRtpSorted(const RtpPacket::Ptr &rtppt, int trackidx) override;
|
||||||
//MediaSourceEvent override
|
//MediaSourceEvent override
|
||||||
bool close() override ;
|
bool close() override ;
|
||||||
private:
|
private:
|
||||||
void inputRtspOrRtcp(const char *data,uint64_t len);
|
bool handleReq_Options(const Parser &parser); //处理options方法
|
||||||
int handleReq_Options(); //处理options方法
|
bool handleReq_Describe(const Parser &parser); //处理describe方法
|
||||||
int handleReq_Describe(); //处理describe方法
|
bool handleReq_ANNOUNCE(const Parser &parser); //处理options方法
|
||||||
int handleReq_ANNOUNCE(); //处理options方法
|
bool handleReq_RECORD(const Parser &parser); //处理options方法
|
||||||
int handleReq_RECORD(); //处理options方法
|
bool handleReq_Setup(const Parser &parser); //处理setup方法
|
||||||
int handleReq_Setup(); //处理setup方法
|
bool handleReq_Play(const Parser &parser); //处理play方法
|
||||||
int handleReq_Play(); //处理play方法
|
bool handleReq_Pause(const Parser &parser); //处理pause方法
|
||||||
int handleReq_Pause(); //处理pause方法
|
bool handleReq_Teardown(const Parser &parser); //处理teardown方法
|
||||||
int handleReq_Teardown(); //处理teardown方法
|
bool handleReq_Get(const Parser &parser); //处理Get方法
|
||||||
int handleReq_Get(); //处理Get方法
|
bool handleReq_Post(const Parser &parser); //处理Post方法
|
||||||
int handleReq_Post(); //处理Post方法
|
bool handleReq_SET_PARAMETER(const Parser &parser); //处理SET_PARAMETER方法
|
||||||
int handleReq_SET_PARAMETER(); //处理SET_PARAMETER方法
|
|
||||||
|
|
||||||
void inline send_StreamNotFound(); //rtsp资源未找到
|
void inline send_StreamNotFound(); //rtsp资源未找到
|
||||||
void inline send_UnsupportedTransport(); //不支持的传输模式
|
void inline send_UnsupportedTransport(); //不支持的传输模式
|
||||||
|
|
@ -111,6 +128,7 @@ private:
|
||||||
inline string printSSRC(uint32_t ui32Ssrc);
|
inline string printSSRC(uint32_t ui32Ssrc);
|
||||||
inline int getTrackIndexByTrackType(TrackType type);
|
inline int getTrackIndexByTrackType(TrackType type);
|
||||||
inline int getTrackIndexByControlSuffix(const string &controlSuffix);
|
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 onRcvPeerUdpData(int iTrackIdx, const Buffer::Ptr &pBuf, const struct sockaddr &addr);
|
||||||
inline void startListenPeerUdpData(int iTrackIdx);
|
inline void startListenPeerUdpData(int iTrackIdx);
|
||||||
|
|
@ -131,7 +149,6 @@ private:
|
||||||
int send(const Buffer::Ptr &pkt) override;
|
int send(const Buffer::Ptr &pkt) override;
|
||||||
private:
|
private:
|
||||||
Ticker _ticker;
|
Ticker _ticker;
|
||||||
Parser _parser; //rtsp解析类
|
|
||||||
int _iCseq = 0;
|
int _iCseq = 0;
|
||||||
string _strUrl;
|
string _strUrl;
|
||||||
string _strSdp;
|
string _strSdp;
|
||||||
|
|
@ -162,7 +179,6 @@ private:
|
||||||
//quicktime 请求rtsp会产生两次tcp连接,
|
//quicktime 请求rtsp会产生两次tcp连接,
|
||||||
//一次发送 get 一次发送post,需要通过x-sessioncookie关联起来
|
//一次发送 get 一次发送post,需要通过x-sessioncookie关联起来
|
||||||
string _http_x_sessioncookie;
|
string _http_x_sessioncookie;
|
||||||
function<void(const char *data,uint64_t len)> _onContent;
|
|
||||||
function<void(const Buffer::Ptr &pBuf)> _onRecv;
|
function<void(const Buffer::Ptr &pBuf)> _onRecv;
|
||||||
|
|
||||||
std::function<void()> _delayTask;
|
std::function<void()> _delayTask;
|
||||||
|
|
|
||||||
|
|
@ -59,9 +59,10 @@ int64_t RtspSplitter::onRecvHeader(const char *data, uint64_t len) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
_parser.Parse(data);
|
_parser.Parse(data);
|
||||||
auto ret = atoi(_parser["Content-Length"].data());
|
auto ret = getContentLength(_parser);
|
||||||
if(ret == 0){
|
if(ret == 0){
|
||||||
onWholeRtspPacket(_parser);
|
onWholeRtspPacket(_parser);
|
||||||
|
_parser.Clear();
|
||||||
}
|
}
|
||||||
return ret;
|
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) {
|
void RtspSplitter::onRecvContent(const char *data, uint64_t len) {
|
||||||
_parser.setContent(string(data,len));
|
_parser.setContent(string(data,len));
|
||||||
onWholeRtspPacket(_parser);
|
onWholeRtspPacket(_parser);
|
||||||
|
_parser.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RtspSplitter::enableRecvRtp(bool enable) {
|
void RtspSplitter::enableRecvRtp(bool enable) {
|
||||||
_enableRecvRtp = enable;
|
_enableRecvRtp = enable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int64_t RtspSplitter::getContentLength(Parser &parser) {
|
||||||
|
return atoi(parser["Content-Length"].data());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}//namespace mediakit
|
}//namespace mediakit
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,12 @@ class RtspSplitter : public HttpRequestSplitter{
|
||||||
public:
|
public:
|
||||||
RtspSplitter(){}
|
RtspSplitter(){}
|
||||||
virtual ~RtspSplitter(){}
|
virtual ~RtspSplitter(){}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否允许接收rtp包
|
||||||
|
* @param enable
|
||||||
|
*/
|
||||||
|
void enableRecvRtp(bool enable);
|
||||||
protected:
|
protected:
|
||||||
/**
|
/**
|
||||||
* 收到完整的rtsp包回调,包括sdp等content数据
|
* 收到完整的rtsp包回调,包括sdp等content数据
|
||||||
|
|
@ -51,10 +57,11 @@ protected:
|
||||||
virtual void onRtpPacket(const char *data,uint64_t len) = 0;
|
virtual void onRtpPacket(const char *data,uint64_t len) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 是否允许接收rtp包
|
* 从rtsp头中获取Content长度
|
||||||
* @param enable
|
* @param parser
|
||||||
|
* @return
|
||||||
*/
|
*/
|
||||||
void enableRecvRtp(bool enable);
|
virtual int64_t getContentLength(Parser &parser);
|
||||||
protected:
|
protected:
|
||||||
const char *onSearchPacketTail(const char *data,int len) override ;
|
const char *onSearchPacketTail(const char *data,int len) override ;
|
||||||
int64_t onRecvHeader(const char *data,uint64_t len) override;
|
int64_t onRecvHeader(const char *data,uint64_t len) override;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue