mirror of
https://github.com/ZLMediaKit/ZLMediaKit.git
synced 2026-07-05 10:58:11 +08:00
Merge remote-tracking branch 'upstream/master' into master
This commit is contained in:
Submodule 3rdpart/ZLToolKit updated: 8611e88c2e...f564c7ed27
@@ -32,6 +32,8 @@
|
|||||||
|
|
||||||
|
|
||||||
## 功能清单
|
## 功能清单
|
||||||
|
### 功能一览
|
||||||
|
<img width="800" alt="图片" src="https://user-images.githubusercontent.com/11495632/93857284-f15b5f00-fcec-11ea-894d-83eb656dc235.png">
|
||||||
|
|
||||||
- RTSP[S]
|
- RTSP[S]
|
||||||
- RTSP[S] 服务器,支持RTMP/MP4/HLS转RTSP[S],支持亚马逊echo show这样的设备
|
- RTSP[S] 服务器,支持RTMP/MP4/HLS转RTSP[S],支持亚马逊echo show这样的设备
|
||||||
|
|||||||
@@ -1076,50 +1076,60 @@ void installWebApi() {
|
|||||||
CHECK_ARGS("url", "timeout_sec", "expire_sec");
|
CHECK_ARGS("url", "timeout_sec", "expire_sec");
|
||||||
GET_CONFIG(string, snap_root, API::kSnapRoot);
|
GET_CONFIG(string, snap_root, API::kSnapRoot);
|
||||||
|
|
||||||
|
bool have_old_snap = false, res_old_snap = false;
|
||||||
int expire_sec = allArgs["expire_sec"];
|
int expire_sec = allArgs["expire_sec"];
|
||||||
auto scan_path = File::absolutePath(MD5(allArgs["url"]).hexdigest(), snap_root) + "/";
|
auto scan_path = File::absolutePath(MD5(allArgs["url"]).hexdigest(), snap_root) + "/";
|
||||||
string snap_path;
|
string new_snap = StrPrinter << scan_path << time(NULL) << ".jpeg";
|
||||||
|
|
||||||
File::scanDir(scan_path, [&](const string &path, bool isDir) {
|
File::scanDir(scan_path, [&](const string &path, bool isDir) {
|
||||||
if (isDir) {
|
if (isDir || !end_with(path, ".jpeg")) {
|
||||||
//忽略文件夹
|
//忽略文件夹或其他类型的文件
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//找到截图
|
//找到截图
|
||||||
auto tm = FindField(path.data() + scan_path.size(), nullptr, ".jpeg");
|
auto tm = FindField(path.data() + scan_path.size(), nullptr, ".jpeg");
|
||||||
if (atoll(tm.data()) + expire_sec < time(NULL)) {
|
if (atoll(tm.data()) + expire_sec < time(NULL)) {
|
||||||
//截图已经过期,删除之,后面重新生成
|
//截图已经过期,改名,以便再次请求时,可以返回老截图
|
||||||
File::delete_file(path.data());
|
rename(path.data(), new_snap.data());
|
||||||
|
have_old_snap = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//截图未过期,中断遍历,返回上次生成的截图
|
//截图存在,且未过期,那么返回之
|
||||||
snap_path = path;
|
res_old_snap = true;
|
||||||
|
responseSnap(path, headerIn, invoker);
|
||||||
|
//中断遍历
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
if(!snap_path.empty()){
|
if (res_old_snap) {
|
||||||
responseSnap(snap_path, headerIn, invoker);
|
//已经回复了旧的截图
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//无截图或者截图已经过期
|
//无截图或者截图已经过期
|
||||||
snap_path = StrPrinter << scan_path << time(NULL) << ".jpeg";
|
if (!have_old_snap) {
|
||||||
|
//无过期截图,生成一个空文件,目的是顺便创建文件夹路径
|
||||||
//生成一个空文件,目的是顺便创建文件夹路径,
|
//同时防止在FFmpeg生成截图途中不停的尝试调用该api多次启动FFmpeg进程
|
||||||
//同时防止在FFmpeg生成截图途中不停的尝试调用该api启动FFmpeg生成相同的截图
|
auto file = File::create_file(new_snap.data(), "wb");
|
||||||
auto file = File::create_file(snap_path.data(), "wb");
|
|
||||||
if (file) {
|
if (file) {
|
||||||
fclose(file);
|
fclose(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
//启动FFmpeg进程,开始截图
|
|
||||||
FFmpegSnap::makeSnap(allArgs["url"],snap_path,allArgs["timeout_sec"],[invoker,headerIn,snap_path](bool success){
|
|
||||||
if(!success){
|
|
||||||
//生成截图失败,可能残留空文件
|
|
||||||
File::delete_file(snap_path.data());
|
|
||||||
}
|
}
|
||||||
responseSnap(snap_path, headerIn, invoker);
|
|
||||||
|
//启动FFmpeg进程,开始截图,生成临时文件,截图成功后替换为正式文件
|
||||||
|
auto new_snap_tmp = new_snap + ".tmp";
|
||||||
|
FFmpegSnap::makeSnap(allArgs["url"], new_snap_tmp, allArgs["timeout_sec"], [invoker, headerIn, new_snap, new_snap_tmp](bool success) {
|
||||||
|
if (!success) {
|
||||||
|
//生成截图失败,可能残留空文件
|
||||||
|
File::delete_file(new_snap_tmp.data());
|
||||||
|
} else {
|
||||||
|
//临时文件改成正式文件
|
||||||
|
File::delete_file(new_snap.data());
|
||||||
|
rename(new_snap_tmp.data(), new_snap.data());
|
||||||
|
}
|
||||||
|
responseSnap(new_snap, headerIn, invoker);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -298,12 +298,6 @@ static bool makeFolderMenu(const string &httpPath, const string &strFullPath, st
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//字符串是否以xx结尾
|
|
||||||
static bool end_of(const string &str, const string &substr){
|
|
||||||
auto pos = str.rfind(substr);
|
|
||||||
return pos != string::npos && pos == str.size() - substr.size();
|
|
||||||
};
|
|
||||||
|
|
||||||
//拦截hls的播放请求
|
//拦截hls的播放请求
|
||||||
static bool emitHlsPlayed(const Parser &parser, const MediaInfo &mediaInfo, const HttpSession::HttpAccessPathInvoker &invoker,TcpSession &sender){
|
static bool emitHlsPlayed(const Parser &parser, const MediaInfo &mediaInfo, const HttpSession::HttpAccessPathInvoker &invoker,TcpSession &sender){
|
||||||
//访问的hls.m3u8结尾,我们转换成kBroadcastMediaPlayed事件
|
//访问的hls.m3u8结尾,我们转换成kBroadcastMediaPlayed事件
|
||||||
@@ -488,7 +482,7 @@ static string pathCat(const string &a, const string &b){
|
|||||||
* @param cb 回调对象
|
* @param cb 回调对象
|
||||||
*/
|
*/
|
||||||
static void accessFile(TcpSession &sender, const Parser &parser, const MediaInfo &mediaInfo, const string &strFile, const HttpFileManager::invoker &cb) {
|
static void accessFile(TcpSession &sender, const Parser &parser, const MediaInfo &mediaInfo, const string &strFile, const HttpFileManager::invoker &cb) {
|
||||||
bool is_hls = end_of(strFile, kHlsSuffix);
|
bool is_hls = end_with(strFile, kHlsSuffix);
|
||||||
bool file_exist = File::is_file(strFile.data());
|
bool file_exist = File::is_file(strFile.data());
|
||||||
if (!is_hls && !file_exist) {
|
if (!is_hls && !file_exist) {
|
||||||
//文件不存在且不是hls,那么直接返回404
|
//文件不存在且不是hls,那么直接返回404
|
||||||
|
|||||||
@@ -17,12 +17,6 @@ using namespace toolkit;
|
|||||||
|
|
||||||
namespace mediakit {
|
namespace mediakit {
|
||||||
|
|
||||||
//字符串是否以xx结尾
|
|
||||||
static bool end_of(const string &str, const string &substr){
|
|
||||||
auto pos = str.rfind(substr);
|
|
||||||
return pos != string::npos && pos == str.size() - substr.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
PlayerBase::Ptr PlayerBase::createPlayer(const EventPoller::Ptr &poller,const string &url_in) {
|
PlayerBase::Ptr PlayerBase::createPlayer(const EventPoller::Ptr &poller,const string &url_in) {
|
||||||
static auto releasePlayer = [](PlayerBase *ptr){
|
static auto releasePlayer = [](PlayerBase *ptr){
|
||||||
onceToken token(nullptr,[&](){
|
onceToken token(nullptr,[&](){
|
||||||
@@ -54,7 +48,7 @@ PlayerBase::Ptr PlayerBase::createPlayer(const EventPoller::Ptr &poller,const st
|
|||||||
return PlayerBase::Ptr(new RtmpPlayerImp(poller),releasePlayer);
|
return PlayerBase::Ptr(new RtmpPlayerImp(poller),releasePlayer);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((strcasecmp("http",prefix.data()) == 0 || strcasecmp("https",prefix.data()) == 0) && end_of(url, ".m3u8")) {
|
if ((strcasecmp("http",prefix.data()) == 0 || strcasecmp("https",prefix.data()) == 0) && end_with(url, ".m3u8")) {
|
||||||
return PlayerBase::Ptr(new HlsPlayerImp(poller),releasePlayer);
|
return PlayerBase::Ptr(new HlsPlayerImp(poller),releasePlayer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -126,12 +126,6 @@ void RtspSession::onRecv(const Buffer::Ptr &buf) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//字符串是否以xx结尾
|
|
||||||
static inline bool end_of(const string &str, const string &substr){
|
|
||||||
auto pos = str.rfind(substr);
|
|
||||||
return pos != string::npos && pos == str.size() - substr.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
void RtspSession::onWholeRtspPacket(Parser &parser) {
|
void RtspSession::onWholeRtspPacket(Parser &parser) {
|
||||||
string method = parser.Method(); //提取出请求命令字
|
string method = parser.Method(); //提取出请求命令字
|
||||||
_cseq = atoi(parser["CSeq"].data());
|
_cseq = atoi(parser["CSeq"].data());
|
||||||
@@ -224,7 +218,7 @@ void RtspSession::handleReq_ANNOUNCE(const Parser &parser) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto full_url = parser.FullUrl();
|
auto full_url = parser.FullUrl();
|
||||||
if(end_of(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);
|
||||||
|
|||||||
Reference in New Issue
Block a user