合并代码

This commit is contained in:
xiongziliang 2021-05-22 09:26:49 +08:00
commit 8cbec43ee8
4 changed files with 69 additions and 55 deletions

@ -1 +1 @@
Subproject commit d5de1d4f0c86139fe8f0b6d956e45dee3b151783 Subproject commit b04d132139399637cbb201c2832dd98dc2786e82

View File

@ -512,6 +512,12 @@
"value": null, "value": null,
"description": "rtsp拉流时拉流方式0tcp1udp2组播", "description": "rtsp拉流时拉流方式0tcp1udp2组播",
"disabled": true "disabled": true
},
{
"key": "timeout_sec",
"value": "10",
"description": "拉流超时时间单位秒float类型",
"disabled": true
} }
] ]
} }

View File

@ -600,6 +600,7 @@ void installWebApi() {
bool enable_hls, bool enable_hls,
bool enable_mp4, bool enable_mp4,
int rtp_type, int rtp_type,
float timeoutSec,
const function<void(const SockException &ex,const string &key)> &cb){ const function<void(const SockException &ex,const string &key)> &cb){
auto key = getProxyKey(vhost,app,stream); auto key = getProxyKey(vhost,app,stream);
lock_guard<recursive_mutex> lck(s_proxyMapMtx); lock_guard<recursive_mutex> lck(s_proxyMapMtx);
@ -614,6 +615,12 @@ void installWebApi() {
//指定RTP over TCP(播放rtsp时有效) //指定RTP over TCP(播放rtsp时有效)
(*player)[kRtpType] = rtp_type; (*player)[kRtpType] = rtp_type;
if (timeoutSec > 0.1) {
//播放握手超时时间
(*player)[kTimeoutMS] = timeoutSec * 1000;
}
//开始播放,如果播放失败或者播放中止,将会自动重试若干次,默认一直重试 //开始播放,如果播放失败或者播放中止,将会自动重试若干次,默认一直重试
player->setPlayCallbackOnce([cb,key](const SockException &ex){ player->setPlayCallbackOnce([cb,key](const SockException &ex){
if(ex){ if(ex){
@ -643,6 +650,7 @@ void installWebApi() {
allArgs["enable_hls"],/* 是否hls转发 */ allArgs["enable_hls"],/* 是否hls转发 */
allArgs["enable_mp4"],/* 是否MP4录制 */ allArgs["enable_mp4"],/* 是否MP4录制 */
allArgs["rtp_type"], allArgs["rtp_type"],
allArgs["timeout_sec"],
[invoker,val,headerOut](const SockException &ex,const string &key) mutable{ [invoker,val,headerOut](const SockException &ex,const string &key) mutable{
if (ex) { if (ex) {
val["code"] = API::OtherFailed; val["code"] = API::OtherFailed;
@ -1133,6 +1141,7 @@ void installWebApi() {
true,/* 开启hls转发 */ true,/* 开启hls转发 */
false,/* 禁用MP4录制 */ false,/* 禁用MP4录制 */
0,//rtp over tcp方式拉流 0,//rtp over tcp方式拉流
10,//10秒超时
[invoker,val,headerOut](const SockException &ex,const string &key) mutable{ [invoker,val,headerOut](const SockException &ex,const string &key) mutable{
if(ex){ if(ex){
val["code"] = API::OtherFailed; val["code"] = API::OtherFailed;

View File

@ -202,82 +202,58 @@ void RtspSession::handleReq_ANNOUNCE(const Parser &parser) {
_media_info._vhost, _media_info._vhost,
_media_info._app, _media_info._app,
_media_info._streamid)); _media_info._streamid));
if(src){ if (src) {
sendRtspResponse("406 Not Acceptable", {"Content-Type", "text/plain"}, "Already publishing."); sendRtspResponse("406 Not Acceptable", {"Content-Type", "text/plain"}, "Already publishing.");
string err = StrPrinter << "ANNOUNCE:" string err = StrPrinter << "ANNOUNCE:"
<< "Already publishing:" << "Already publishing:"
<< _media_info._vhost << " " << _media_info._vhost << " "
<< _media_info._app << " " << _media_info._app << " "
<< _media_info._streamid << endl; << _media_info._streamid << endl;
throw SockException(Err_shutdown,err); throw SockException(Err_shutdown, err);
} }
auto full_url = parser.FullUrl(); auto full_url = parser.FullUrl();
_content_base = full_url; _content_base = full_url;
if(end_with(full_url,".sdp")){ if (end_with(full_url, ".sdp")) {
//去除.sdp后缀防止EasyDarwin推流器强制添加.sdp后缀 //去除.sdp后缀防止EasyDarwin推流器强制添加.sdp后缀
full_url = full_url.substr(0,full_url.length() - 4); full_url = full_url.substr(0, full_url.length() - 4);
_media_info.parse(full_url); _media_info.parse(full_url);
} }
if(_media_info._app.empty() || _media_info._streamid.empty()){ if (_media_info._app.empty() || _media_info._streamid.empty()) {
//推流rtsp url必须最少两级(rtsp://host/app/stream_id)不允许莫名其妙的推流url //推流rtsp url必须最少两级(rtsp://host/app/stream_id)不允许莫名其妙的推流url
static constexpr auto err = "rtsp推流url非法,最少确保两级rtsp url"; static constexpr auto err = "rtsp推流url非法,最少确保两级rtsp url";
sendRtspResponse("403 Forbidden", {"Content-Type", "text/plain"}, err); sendRtspResponse("403 Forbidden", {"Content-Type", "text/plain"}, err);
throw SockException(Err_shutdown, StrPrinter << err << ":" << full_url); throw SockException(Err_shutdown, StrPrinter << err << ":" << full_url);
} }
SdpParser sdpParser(parser.Content()); auto onRes = [this, parser, full_url](const string &err, bool enableHls, bool enableMP4){
_sessionid = makeRandStr(12);
_sdp_track = sdpParser.getAvailableTrack();
if (_sdp_track.empty()) {
//sdp无效
static constexpr auto err = "sdp中无有效track";
sendRtspResponse("403 Forbidden", {"Content-Type", "text/plain"}, err);
throw SockException(Err_shutdown,StrPrinter << err << ":" << full_url);
}
_rtcp_context.clear();
for (auto &track : _sdp_track) {
_rtcp_context.emplace_back(std::make_shared<RtcpContext>(track->_samplerate, true));
}
_push_src = std::make_shared<RtspMediaSourceImp>(_media_info._vhost, _media_info._app, _media_info._streamid);
_push_src->setListener(dynamic_pointer_cast<MediaSourceEvent>(shared_from_this()));
_push_src->setSdp(sdpParser.toString());
sendRtspResponse("200 OK");
}
void RtspSession::handleReq_RECORD(const Parser &parser){
if (_sdp_track.empty() || parser["Session"] != _sessionid) {
send_SessionNotFound();
throw SockException(Err_shutdown, _sdp_track.empty() ? "can not find any availabe track when record" : "session not found when record");
}
auto onRes = [this](const string &err, bool enableHls, bool enableMP4){
bool authSuccess = err.empty(); bool authSuccess = err.empty();
if(!authSuccess){ if (!authSuccess) {
sendRtspResponse("401 Unauthorized", {"Content-Type", "text/plain"}, err); sendRtspResponse("401 Unauthorized", {"Content-Type", "text/plain"}, err);
shutdown(SockException(Err_shutdown,StrPrinter << "401 Unauthorized:" << err)); shutdown(SockException(Err_shutdown, StrPrinter << "401 Unauthorized:" << err));
return; return;
} }
//设置转协议 SdpParser sdpParser(parser.Content());
_sessionid = makeRandStr(12);
_sdp_track = sdpParser.getAvailableTrack();
if (_sdp_track.empty()) {
//sdp无效
static constexpr auto err = "sdp中无有效track";
sendRtspResponse("403 Forbidden", {"Content-Type", "text/plain"}, err);
shutdown(SockException(Err_shutdown, StrPrinter << err << ":" << full_url));
return;
}
_rtcp_context.clear();
for (auto &track : _sdp_track) {
_rtcp_context.emplace_back(std::make_shared<RtcpContext>(track->_samplerate, true));
}
_push_src = std::make_shared<RtspMediaSourceImp>(_media_info._vhost, _media_info._app, _media_info._streamid);
_push_src->setListener(dynamic_pointer_cast<MediaSourceEvent>(shared_from_this()));
_push_src->setProtocolTranslation(enableHls, enableMP4); _push_src->setProtocolTranslation(enableHls, enableMP4);
_push_src->setSdp(sdpParser.toString());
_StrPrinter rtp_info; sendRtspResponse("200 OK");
for(auto &track : _sdp_track){
if (track->_inited == false) {
//还有track没有setup
shutdown(SockException(Err_shutdown,"track not setuped"));
return;
}
rtp_info << "url=" << track->getControlUrl(_content_base) << ",";
}
rtp_info.pop_back();
sendRtspResponse("200 OK", {"RTP-Info",rtp_info});
if(_rtp_type == Rtsp::RTP_TCP){
//如果是rtsp推流服务器并且是TCP推流设置socket flags,,这样能提升接收性能
setSocketFlags();
}
}; };
weak_ptr<RtspSession> weakSelf = dynamic_pointer_cast<RtspSession>(shared_from_this()); weak_ptr<RtspSession> weakSelf = dynamic_pointer_cast<RtspSession>(shared_from_this());
@ -297,11 +273,34 @@ void RtspSession::handleReq_RECORD(const Parser &parser){
//rtsp推流需要鉴权 //rtsp推流需要鉴权
auto flag = NoticeCenter::Instance().emitEvent(Broadcast::kBroadcastMediaPublish, _media_info, invoker, static_cast<SockInfo &>(*this)); auto flag = NoticeCenter::Instance().emitEvent(Broadcast::kBroadcastMediaPublish, _media_info, invoker, static_cast<SockInfo &>(*this));
if(!flag){ if (!flag) {
//该事件无人监听,默认不鉴权 //该事件无人监听,默认不鉴权
GET_CONFIG(bool,toHls,General::kPublishToHls); GET_CONFIG(bool, toHls, General::kPublishToHls);
GET_CONFIG(bool,toMP4,General::kPublishToMP4); GET_CONFIG(bool, toMP4, General::kPublishToMP4);
onRes("",toHls,toMP4); onRes("", toHls, toMP4);
}
}
void RtspSession::handleReq_RECORD(const Parser &parser){
if (_sdp_track.empty() || parser["Session"] != _sessionid) {
send_SessionNotFound();
throw SockException(Err_shutdown, _sdp_track.empty() ? "can not find any availabe track when record" : "session not found when record");
}
_StrPrinter rtp_info;
for (auto &track : _sdp_track) {
if (track->_inited == false) {
//还有track没有setup
shutdown(SockException(Err_shutdown, "track not setuped"));
return;
}
rtp_info << "url=" << track->getControlUrl(_content_base) << ",";
}
rtp_info.pop_back();
sendRtspResponse("200 OK", {"RTP-Info", rtp_info});
if (_rtp_type == Rtsp::RTP_TCP) {
//如果是rtsp推流服务器并且是TCP推流设置socket flags,,这样能提升接收性能
setSocketFlags();
} }
} }