mirror of
https://github.com/ZLMediaKit/ZLMediaKit.git
synced 2024-11-26 20:47:08 +08:00
1.添加windows下ffmpeg拉流分发支持,目前不是很完善,后续再修改
2.server/system下未兼容完成
This commit is contained in:
parent
d082955510
commit
306e202ca1
@ -1 +1 @@
|
|||||||
Subproject commit ba5a796d583cd2906e06ec15c0d942e484ea1dbf
|
Subproject commit 7cb850d79ba798e6d1f0bba7c655d38d2865ed92
|
24
README.md
24
README.md
@ -1,17 +1,5 @@
|
|||||||
![logo](https://raw.githubusercontent.com/zlmediakit/ZLMediaKit/master/logo.png)
|
|
||||||
|
|
||||||
[english readme](https://github.com/xiongziliang/ZLMediaKit/blob/master/README_en.md)
|
|
||||||
|
|
||||||
# 一个基于C++11的高性能运营级流媒体服务框架
|
# 一个基于C++11的高性能运营级流媒体服务框架
|
||||||
[![Build Status](https://travis-ci.org/xiongziliang/ZLMediaKit.svg?branch=master)](https://travis-ci.org/xiongziliang/ZLMediaKit)
|
|
||||||
|
|
||||||
|
|
||||||
## 国内用户请使用gitee镜像下载
|
|
||||||
```
|
|
||||||
git clone --depth 1 https://gitee.com/xiahcu/ZLMediaKit
|
|
||||||
cd ZLMediaKit
|
|
||||||
git submodule update --init
|
|
||||||
```
|
|
||||||
## 项目特点
|
## 项目特点
|
||||||
- 基于C++11开发,避免使用裸指针,代码稳定可靠;同时跨平台移植简单方便,代码清晰简洁。
|
- 基于C++11开发,避免使用裸指针,代码稳定可靠;同时跨平台移植简单方便,代码清晰简洁。
|
||||||
- 打包多种流媒体协议(RTSP/RTMP/HLS/HTTP-FLV/Websocket-FLV),支持协议间的互相转换,提供一站式的服务。
|
- 打包多种流媒体协议(RTSP/RTMP/HLS/HTTP-FLV/Websocket-FLV),支持协议间的互相转换,提供一站式的服务。
|
||||||
@ -29,6 +17,7 @@ git submodule update --init
|
|||||||
- 移动嵌入式跨平台流媒体解决方案。
|
- 移动嵌入式跨平台流媒体解决方案。
|
||||||
- 商用级流媒体服务器。
|
- 商用级流媒体服务器。
|
||||||
- 网络编程二次开发SDK。
|
- 网络编程二次开发SDK。
|
||||||
|
- 免费NVR(rtxp拉流代理、分发)。
|
||||||
|
|
||||||
|
|
||||||
## 功能清单
|
## 功能清单
|
||||||
@ -362,8 +351,9 @@ git submodule update --init
|
|||||||
由于使用本项目而产生的商业纠纷或侵权行为一概与本项项目及开发者无关,请自行承担法律风险。
|
由于使用本项目而产生的商业纠纷或侵权行为一概与本项项目及开发者无关,请自行承担法律风险。
|
||||||
|
|
||||||
## 联系方式
|
## 联系方式
|
||||||
- 邮箱:<771730766@qq.com>(本项目相关或流媒体相关问题请走issue流程,否则恕不邮件答复)
|
- 邮箱:<18675721@qq.com>(本项目相关或流媒体相关问题请走issue流程,否则恕不邮件答复)
|
||||||
- QQ群:542509000
|
- QQ群:542509000 (ZLMediakit)
|
||||||
|
- QQ群:936467414 (FreeNVR)
|
||||||
|
|
||||||
## 怎么提问?
|
## 怎么提问?
|
||||||
如果要对项目有相关疑问,建议您这么做:
|
如果要对项目有相关疑问,建议您这么做:
|
||||||
@ -372,12 +362,6 @@ git submodule update --init
|
|||||||
- 3、有些问题,如果不具备参考性的,无需在issue提的,可以在qq群提.
|
- 3、有些问题,如果不具备参考性的,无需在issue提的,可以在qq群提.
|
||||||
- 4、QQ私聊一般不接受无偿技术咨询和支持(谈谈人生理想还是可以的😂),毕竟精力有限,谢谢理解.
|
- 4、QQ私聊一般不接受无偿技术咨询和支持(谈谈人生理想还是可以的😂),毕竟精力有限,谢谢理解.
|
||||||
|
|
||||||
## 捐赠
|
|
||||||
欢迎捐赠以便更好的推动项目的发展,谢谢您的支持!
|
|
||||||
|
|
||||||
[支付宝](https://raw.githubusercontent.com/xiongziliang/other/master/IMG_3919.JPG)
|
|
||||||
|
|
||||||
[微信](https://raw.githubusercontent.com/xiongziliang/other/master/IMG_3920.JPG)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -3,12 +3,7 @@ file(GLOB jsoncpp_src_list ../3rdpart/jsoncpp/*.cpp ../3rdpart/jsoncpp/*.h )
|
|||||||
add_library(jsoncpp STATIC ${jsoncpp_src_list})
|
add_library(jsoncpp STATIC ${jsoncpp_src_list})
|
||||||
|
|
||||||
|
|
||||||
if (CMAKE_SYSTEM_NAME MATCHES "Windows")
|
file(GLOB MediaServer_src_list ./*.cpp ./*.h)
|
||||||
set(MediaServer_src_list ./WebApi.cpp ./WebHook.cpp main.cpp)
|
|
||||||
else()
|
|
||||||
file(GLOB MediaServer_src_list ./*.cpp ./*.h)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
#message(STATUS ${MediaServer_src_list})
|
#message(STATUS ${MediaServer_src_list})
|
||||||
|
|
||||||
add_executable(MediaServer ${MediaServer_src_list})
|
add_executable(MediaServer ${MediaServer_src_list})
|
||||||
|
@ -37,9 +37,15 @@ const char kCmd[] = FFmpeg_FIELD"cmd";
|
|||||||
const char kLog[] = FFmpeg_FIELD"log";
|
const char kLog[] = FFmpeg_FIELD"log";
|
||||||
|
|
||||||
onceToken token([]() {
|
onceToken token([]() {
|
||||||
mINI::Instance()[kBin] = trim(System::execute("which ffmpeg"));
|
#ifdef _WIN32
|
||||||
mINI::Instance()[kCmd] = "%s -re -i %s -c:a aac -strict -2 -ar 44100 -ab 48k -c:v libx264 -f flv %s";
|
string strFFmpeg = "where ffmpeg";
|
||||||
mINI::Instance()[kLog] = "./ffmpeg/ffmpeg.log";
|
#else
|
||||||
|
string strFFmpeg = "which ffmpeg";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
mINI::Instance()[kBin] = trim(System::execute(strFFmpeg)); //todo:暂定如此:配置文件无此配置的话,改为环境变量的ffmpeg
|
||||||
|
mINI::Instance()[kCmd] = "%s -re -i \"%s\" -loglevel quiet -c:a aac -strict -2 -ar 44100 -ab 48k -c:v libx264 -f flv %s "; //防止url中特殊字符
|
||||||
|
mINI::Instance()[kLog] = "./ffmpeg/ffmpeg.log"; //win下建议使用ffmpeg/ffmpeg.log
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -51,7 +57,6 @@ FFmpegSource::~FFmpegSource() {
|
|||||||
DebugL;
|
DebugL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FFmpegSource::play(const string &src_url,const string &dst_url,int timeout_ms,const onPlay &cb) {
|
void FFmpegSource::play(const string &src_url,const string &dst_url,int timeout_ms,const onPlay &cb) {
|
||||||
GET_CONFIG(string,ffmpeg_bin,FFmpeg::kBin);
|
GET_CONFIG(string,ffmpeg_bin,FFmpeg::kBin);
|
||||||
GET_CONFIG(string,ffmpeg_cmd,FFmpeg::kCmd);
|
GET_CONFIG(string,ffmpeg_cmd,FFmpeg::kCmd);
|
||||||
@ -62,8 +67,8 @@ void FFmpegSource::play(const string &src_url,const string &dst_url,int timeout_
|
|||||||
_media_info.parse(dst_url);
|
_media_info.parse(dst_url);
|
||||||
|
|
||||||
char cmd[1024] = {0};
|
char cmd[1024] = {0};
|
||||||
snprintf(cmd, sizeof(cmd),ffmpeg_cmd.data(),ffmpeg_bin.data(),src_url.data(),dst_url.data());
|
snprintf(cmd, sizeof(cmd), ffmpeg_cmd.data(), ffmpeg_bin.data(), src_url.data(), dst_url.data());
|
||||||
_process.run(cmd,File::absolutePath("",ffmpeg_log));
|
_process.run(cmd, ffmpeg_log.empty() ? "" : File::absolutePath("", ffmpeg_log));
|
||||||
InfoL << cmd;
|
InfoL << cmd;
|
||||||
|
|
||||||
if(_media_info._host == "127.0.0.1"){
|
if(_media_info._host == "127.0.0.1"){
|
||||||
|
@ -26,8 +26,15 @@
|
|||||||
|
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
#include <sys/resource.h>
|
#include <sys/resource.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#else
|
||||||
|
//#include <TlHelp32.h>
|
||||||
|
#include <windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include "Util/util.h"
|
#include "Util/util.h"
|
||||||
@ -39,75 +46,109 @@
|
|||||||
using namespace toolkit;
|
using namespace toolkit;
|
||||||
|
|
||||||
void Process::run(const string &cmd, const string &log_file_tmp) {
|
void Process::run(const string &cmd, const string &log_file_tmp) {
|
||||||
kill(2000);
|
kill(2000);
|
||||||
_pid = fork();
|
#ifdef _WIN32
|
||||||
if (_pid < 0) {
|
// string log_file = "";
|
||||||
throw std::runtime_error(StrPrinter << "fork child process falied,err:" << get_uv_errmsg());
|
// if (log_file_tmp.empty())
|
||||||
}
|
// {
|
||||||
if (_pid == 0) {
|
// log_file = R"( >2&1)";
|
||||||
//子进程关闭core文件生成
|
// }
|
||||||
struct rlimit rlim = {0,0};
|
// else
|
||||||
setrlimit(RLIMIT_CORE, &rlim);
|
// {
|
||||||
|
// log_file = log_file_tmp + R"( >2&1)";
|
||||||
|
// }
|
||||||
|
// string strCmd = cmd + " " + log_file; //防止cmd后面没有空格
|
||||||
|
|
||||||
//在启动子进程时,暂时禁用SIGINT、SIGTERM信号
|
STARTUPINFO si;
|
||||||
// ignore the SIGINT and SIGTERM
|
PROCESS_INFORMATION pi;
|
||||||
signal(SIGINT, SIG_IGN);
|
ZeroMemory(&si, sizeof(si)); //结构体初始化;
|
||||||
signal(SIGTERM, SIG_IGN);
|
ZeroMemory(&pi, sizeof(pi));
|
||||||
|
|
||||||
string log_file ;
|
LPTSTR lpDir = const_cast<char*>(cmd .data());
|
||||||
if(log_file_tmp.empty()){
|
|
||||||
log_file = "/dev/null";
|
|
||||||
}else{
|
|
||||||
log_file = StrPrinter << log_file_tmp << "." << getpid();
|
|
||||||
}
|
|
||||||
|
|
||||||
int log_fd = -1;
|
if (CreateProcess(NULL, lpDir, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))
|
||||||
int flags = O_CREAT | O_WRONLY | O_APPEND;
|
{
|
||||||
mode_t mode = S_IRWXO | S_IRWXG | S_IRWXU;// S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH;
|
//下面两行关闭句柄,解除本进程和新进程的关系,不然有可能 不小心调用TerminateProcess函数关掉子进程
|
||||||
File::createfile_path(log_file.data(), mode);
|
CloseHandle(pi.hProcess);
|
||||||
if ((log_fd = ::open(log_file.c_str(), flags, mode)) < 0) {
|
CloseHandle(pi.hThread);
|
||||||
fprintf(stderr, "open log file %s failed:%d(%s)\r\n", log_file.data(), errno, strerror(errno));
|
|
||||||
} else {
|
|
||||||
// dup to stdout and stderr.
|
|
||||||
if (dup2(log_fd, STDOUT_FILENO) < 0) {
|
|
||||||
fprintf(stderr, "dup2 stdout file %s failed:%d(%s)\r\n", log_file.data(), errno, strerror(errno));
|
|
||||||
}
|
|
||||||
if (dup2(log_fd, STDERR_FILENO) < 0) {
|
|
||||||
fprintf(stderr, "dup2 stderr file %s failed:%d(%s)\r\n", log_file.data(), errno, strerror(errno));
|
|
||||||
}
|
|
||||||
// close log fd
|
|
||||||
::close(log_fd);
|
|
||||||
}
|
|
||||||
fprintf(stderr, "\r\n\r\n#### pid=%d,cmd=%s #####\r\n\r\n", getpid(), cmd.data());
|
|
||||||
|
|
||||||
// close other fds
|
_pid = pi.dwProcessId;
|
||||||
// TODO: do in right way.
|
InfoL << "start child proces " << _pid;
|
||||||
for (int i = 3; i < 1024; i++) {
|
}
|
||||||
::close(i);
|
else
|
||||||
}
|
{
|
||||||
|
WarnL << "start child proces fail: " << GetLastError();
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
_pid = fork();
|
||||||
|
if (_pid < 0) {
|
||||||
|
throw std::runtime_error(StrPrinter << "fork child process falied,err:" << get_uv_errmsg());
|
||||||
|
}
|
||||||
|
if (_pid == 0) {
|
||||||
|
//子进程关闭core文件生成
|
||||||
|
struct rlimit rlim = { 0,0 };
|
||||||
|
setrlimit(RLIMIT_CORE, &rlim);
|
||||||
|
|
||||||
auto params = split(cmd, " ");
|
//在启动子进程时,暂时禁用SIGINT、SIGTERM信号
|
||||||
// memory leak in child process, it's ok.
|
// ignore the SIGINT and SIGTERM
|
||||||
char **charpv_params = new char *[params.size() + 1];
|
signal(SIGINT, SIG_IGN);
|
||||||
for (int i = 0; i < (int) params.size(); i++) {
|
signal(SIGTERM, SIG_IGN);
|
||||||
std::string &p = params[i];
|
|
||||||
charpv_params[i] = (char *) p.data();
|
|
||||||
}
|
|
||||||
// EOF: NULL
|
|
||||||
charpv_params[params.size()] = NULL;
|
|
||||||
|
|
||||||
// TODO: execv or execvp
|
string log_file;
|
||||||
auto ret = execv(params[0].c_str(), charpv_params);
|
if (log_file_tmp.empty()) {
|
||||||
if (ret < 0) {
|
log_file = "/dev/null";
|
||||||
fprintf(stderr, "fork process failed, errno=%d(%s)\r\n", errno, strerror(errno));
|
}
|
||||||
}
|
else {
|
||||||
exit(ret);
|
log_file = StrPrinter << log_file_tmp << "." << getpid();
|
||||||
}
|
}
|
||||||
|
|
||||||
InfoL << "start child proces " << _pid;
|
int log_fd = -1;
|
||||||
|
int flags = O_CREAT | O_WRONLY | O_APPEND;
|
||||||
|
mode_t mode = S_IRWXO | S_IRWXG | S_IRWXU;// S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH;
|
||||||
|
File::createfile_path(log_file.data(), mode);
|
||||||
|
if ((log_fd = ::open(log_file.c_str(), flags, mode)) < 0) {
|
||||||
|
fprintf(stderr, "open log file %s failed:%d(%s)\r\n", log_file.data(), errno, strerror(errno));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// dup to stdout and stderr.
|
||||||
|
if (dup2(log_fd, STDOUT_FILENO) < 0) {
|
||||||
|
fprintf(stderr, "dup2 stdout file %s failed:%d(%s)\r\n", log_file.data(), errno, strerror(errno));
|
||||||
|
}
|
||||||
|
if (dup2(log_fd, STDERR_FILENO) < 0) {
|
||||||
|
fprintf(stderr, "dup2 stderr file %s failed:%d(%s)\r\n", log_file.data(), errno, strerror(errno));
|
||||||
|
}
|
||||||
|
// close log fd
|
||||||
|
::close(log_fd);
|
||||||
|
}
|
||||||
|
fprintf(stderr, "\r\n\r\n#### pid=%d,cmd=%s #####\r\n\r\n", getpid(), cmd.data());
|
||||||
|
|
||||||
|
// close other fds
|
||||||
|
// TODO: do in right way.
|
||||||
|
for (int i = 3; i < 1024; i++) {
|
||||||
|
::close(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto params = split(cmd, " ");
|
||||||
|
// memory leak in child process, it's ok.
|
||||||
|
char **charpv_params = new char *[params.size() + 1];
|
||||||
|
for (int i = 0; i < (int)params.size(); i++) {
|
||||||
|
std::string &p = params[i];
|
||||||
|
charpv_params[i] = (char *)p.data();
|
||||||
|
}
|
||||||
|
// EOF: NULL
|
||||||
|
charpv_params[params.size()] = NULL;
|
||||||
|
|
||||||
|
// TODO: execv or execvp
|
||||||
|
auto ret = execv(params[0].c_str(), charpv_params);
|
||||||
|
if (ret < 0) {
|
||||||
|
fprintf(stderr, "fork process failed, errno=%d(%s)\r\n", errno, strerror(errno));
|
||||||
|
}
|
||||||
|
exit(ret);
|
||||||
|
}
|
||||||
|
InfoL << "start child proces " << _pid;
|
||||||
|
#endif // _WIN32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取进程是否存活状态
|
* 获取进程是否存活状态
|
||||||
* @param pid 进程号
|
* @param pid 进程号
|
||||||
@ -120,20 +161,31 @@ static bool s_wait(pid_t pid,int *exit_code_ptr,bool block) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
int status = 0;
|
int status = 0;
|
||||||
pid_t p = waitpid(pid, &status, block ? 0 : WNOHANG);
|
#ifdef _WIN32
|
||||||
int exit_code = (status & 0xFF00) >> 8;
|
HANDLE hProcess = NULL;
|
||||||
if(exit_code_ptr){
|
hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, pid); //打开目标进程
|
||||||
*exit_code_ptr = (status & 0xFF00) >> 8;
|
if (hProcess == NULL) {
|
||||||
}
|
return false;
|
||||||
if (p < 0) {
|
}
|
||||||
WarnL << "waitpid failed, pid=" << pid << ", err=" << get_uv_errmsg();
|
|
||||||
return false;
|
CloseHandle(hProcess);
|
||||||
}
|
#else
|
||||||
if (p > 0) {
|
pid_t p = waitpid(pid, &status, block ? 0 : WNOHANG);
|
||||||
InfoL << "process terminated, pid=" << pid << ", exit code=" << exit_code;
|
int exit_code = (status & 0xFF00) >> 8;
|
||||||
return false;
|
if (exit_code_ptr) {
|
||||||
}
|
*exit_code_ptr = (status & 0xFF00) >> 8;
|
||||||
//WarnL << "process is running, pid=" << _pid;
|
}
|
||||||
|
if (p < 0) {
|
||||||
|
WarnL << "waitpid failed, pid=" << pid << ", err=" << get_uv_errmsg();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (p > 0) {
|
||||||
|
InfoL << "process terminated, pid=" << pid << ", exit code=" << exit_code;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
WarnL << "process is running, pid=" << _pid;
|
||||||
|
#endif // _WIN32
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -142,12 +194,27 @@ static void s_kill(pid_t pid,int max_delay,bool force){
|
|||||||
//pid无效
|
//pid无效
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
#ifdef _WIN32
|
||||||
|
HANDLE hProcess = NULL;
|
||||||
|
hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, pid); //打开目标进程
|
||||||
|
if (hProcess == NULL)
|
||||||
|
{
|
||||||
|
WarnL << "\nOpen Process fAiled: " << GetLastError();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
DWORD ret = TerminateProcess(hProcess, 0); //结束目标进程
|
||||||
|
if (ret == 0)
|
||||||
|
{
|
||||||
|
WarnL << GetLastError;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (::kill(pid, force ? SIGKILL : SIGTERM) == -1) {
|
||||||
|
//进程可能已经退出了
|
||||||
|
WarnL << "kill process " << pid << " failed:" << get_uv_errmsg();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif // _WIN32
|
||||||
|
|
||||||
if (::kill(pid, force ? SIGKILL : SIGTERM) == -1) {
|
|
||||||
//进程可能已经退出了
|
|
||||||
WarnL << "kill process " << pid << " failed:" << get_uv_errmsg();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(force){
|
if(force){
|
||||||
//发送SIGKILL信号后,阻塞等待退出
|
//发送SIGKILL信号后,阻塞等待退出
|
||||||
|
@ -26,9 +26,16 @@
|
|||||||
#ifndef IPTV_PROCESS_H
|
#ifndef IPTV_PROCESS_H
|
||||||
#define IPTV_PROCESS_H
|
#define IPTV_PROCESS_H
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
typedef int pid_t;
|
||||||
|
#else
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
|
#endif // _WIN32
|
||||||
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
class Process {
|
class Process {
|
||||||
|
@ -27,14 +27,19 @@
|
|||||||
#include "System.h"
|
#include "System.h"
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <arpa/inet.h>
|
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
#ifdef _WIN32
|
||||||
|
|
||||||
|
#else
|
||||||
|
#include <arpa/inet.h>
|
||||||
#include <sys/resource.h>
|
#include <sys/resource.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#ifndef ANDROID
|
#ifndef ANDROID
|
||||||
#include <execinfo.h>
|
#include <execinfo.h>
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
@ -247,16 +252,38 @@ bool System::getNetworkUsage(vector<NetworkUsage> &usage) {
|
|||||||
|
|
||||||
|
|
||||||
bool System::getTcpUsage(System::TcpUsage &usage) {
|
bool System::getTcpUsage(System::TcpUsage &usage) {
|
||||||
usage.established = atoi(trim(System::execute("netstat -na|grep ESTABLISHED|wc -l")).data());
|
string strEstab;
|
||||||
usage.syn_recv = atoi(trim(System::execute("netstat -na|grep SYN_RECV|wc -l")).data());
|
string strSynRecv;
|
||||||
usage.time_wait = atoi(trim(System::execute("netstat -na|grep TIME_WAIT|wc -l")).data());
|
string strTimeWait;
|
||||||
usage.close_wait = atoi(trim(System::execute("netstat -na|grep CLOSE_WAIT|wc -l")).data());
|
string strCloseWait;
|
||||||
|
#ifdef _WIN32
|
||||||
|
//使用R"()" 可以不用转义
|
||||||
|
strEstab = R"(netstat -na|find /i /c "ESTABLISHED")";
|
||||||
|
strSynRecv = R"(netstat -na|find /i /c "SYN_RECV")";
|
||||||
|
strTimeWait = R"(netstat -na|find /i /c "TIME_WAIT")";
|
||||||
|
strCloseWait = R"(netstat -na|find /i /c "CLOSE_WAIT")";
|
||||||
|
#else
|
||||||
|
strEstab = "netstat -na|grep ESTABLISHED|wc -l";
|
||||||
|
strSynRecv = "netstat -na|grep SYN_RECV|wc -l";
|
||||||
|
strTimeWait = "netstat -na|grep TIME_WAIT|wc -l";
|
||||||
|
strCloseWait = "netstat -na|grep CLOSE_WAIT|wc -l";
|
||||||
|
#endif
|
||||||
|
usage.established = atoi(trim(System::execute(strEstab)).data());
|
||||||
|
usage.syn_recv = atoi(trim(System::execute(strSynRecv)).data());
|
||||||
|
usage.time_wait = atoi(trim(System::execute(strTimeWait)).data());
|
||||||
|
usage.close_wait = atoi(trim(System::execute(strCloseWait)).data());
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
string System::execute(const string &cmd) {
|
string System::execute(const string &cmd) {
|
||||||
// DebugL << cmd;
|
// DebugL << cmd;
|
||||||
FILE *fPipe = popen(cmd.data(), "r");
|
FILE *fPipe = NULL;
|
||||||
|
#ifdef _WIN32
|
||||||
|
fPipe = _popen(cmd.data(), "r");
|
||||||
|
#else
|
||||||
|
fPipe = popen(cmd.data(), "r");
|
||||||
|
#endif
|
||||||
if(!fPipe){
|
if(!fPipe){
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
@ -265,7 +292,12 @@ string System::execute(const string &cmd) {
|
|||||||
while(fgets(buff, sizeof(buff) - 1, fPipe)){
|
while(fgets(buff, sizeof(buff) - 1, fPipe)){
|
||||||
ret.append(buff);
|
ret.append(buff);
|
||||||
}
|
}
|
||||||
|
#ifdef _WIN32
|
||||||
|
_pclose(fPipe);
|
||||||
|
#else
|
||||||
pclose(fPipe);
|
pclose(fPipe);
|
||||||
|
#endif
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -274,8 +306,11 @@ static string addr2line(const string &address) {
|
|||||||
return System::execute(cmd);
|
return System::execute(cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef ANDROID
|
|
||||||
static void sig_crash(int sig) {
|
static void sig_crash(int sig) {
|
||||||
|
#ifdef _WIN32
|
||||||
|
|
||||||
|
#else
|
||||||
|
#ifndef ANDROID
|
||||||
signal(sig, SIG_DFL);
|
signal(sig, SIG_DFL);
|
||||||
void *array[MAX_STACK_FRAMES];
|
void *array[MAX_STACK_FRAMES];
|
||||||
int size = backtrace(array, MAX_STACK_FRAMES);
|
int size = backtrace(array, MAX_STACK_FRAMES);
|
||||||
@ -296,12 +331,14 @@ static void sig_crash(int sig) {
|
|||||||
free(strings);
|
free(strings);
|
||||||
|
|
||||||
NoticeCenter::Instance().emitEvent(kBroadcastOnCrashDump,sig,stack);
|
NoticeCenter::Instance().emitEvent(kBroadcastOnCrashDump,sig,stack);
|
||||||
|
#endif//#ifndef ANDROID
|
||||||
|
#endif // _WIN32
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif//#ifndef ANDROID
|
|
||||||
|
|
||||||
|
|
||||||
void System::startDaemon() {
|
void System::startDaemon() {
|
||||||
|
#ifdef _WIN32
|
||||||
|
|
||||||
|
#else
|
||||||
static pid_t pid;
|
static pid_t pid;
|
||||||
do{
|
do{
|
||||||
pid = fork();
|
pid = fork();
|
||||||
@ -336,14 +373,17 @@ void System::startDaemon() {
|
|||||||
DebugL << "waitpid被中断:" << get_uv_errmsg();
|
DebugL << "waitpid被中断:" << get_uv_errmsg();
|
||||||
}while (true);
|
}while (true);
|
||||||
}while (true);
|
}while (true);
|
||||||
|
#endif // _WIN32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static string currentDateTime(){
|
static string currentDateTime(){
|
||||||
time_t ts = time(NULL);
|
time_t ts = time(NULL);
|
||||||
std::tm tm_snapshot;
|
std::tm tm_snapshot;
|
||||||
localtime_r(&ts, &tm_snapshot);
|
#ifndef _WIN32
|
||||||
|
localtime_r(&ts, &tm_snapshot);
|
||||||
|
#else
|
||||||
|
localtime_s(&tm_snapshot, &ts);
|
||||||
|
#endif // !_WIN32
|
||||||
|
|
||||||
char buffer[1024] = {0};
|
char buffer[1024] = {0};
|
||||||
std::strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", &tm_snapshot);
|
std::strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", &tm_snapshot);
|
||||||
@ -351,6 +391,9 @@ static string currentDateTime(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
void System::systemSetup(){
|
void System::systemSetup(){
|
||||||
|
#ifdef _WIN32
|
||||||
|
|
||||||
|
#else
|
||||||
struct rlimit rlim,rlim_new;
|
struct rlimit rlim,rlim_new;
|
||||||
if (getrlimit(RLIMIT_CORE, &rlim)==0) {
|
if (getrlimit(RLIMIT_CORE, &rlim)==0) {
|
||||||
rlim_new.rlim_cur = rlim_new.rlim_max = RLIM_INFINITY;
|
rlim_new.rlim_cur = rlim_new.rlim_max = RLIM_INFINITY;
|
||||||
@ -394,5 +437,6 @@ void System::systemSetup(){
|
|||||||
|
|
||||||
cerr << stack_info << endl;
|
cerr << stack_info << endl;
|
||||||
});
|
});
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,10 +47,7 @@
|
|||||||
#include "WebHook.h"
|
#include "WebHook.h"
|
||||||
#include "Thread/WorkThreadPool.h"
|
#include "Thread/WorkThreadPool.h"
|
||||||
#include "Rtp/RtpSelector.h"
|
#include "Rtp/RtpSelector.h"
|
||||||
|
|
||||||
#if !defined(_WIN32)
|
|
||||||
#include "FFmpegSource.h"
|
#include "FFmpegSource.h"
|
||||||
#endif//!defined(_WIN32)
|
|
||||||
|
|
||||||
using namespace Json;
|
using namespace Json;
|
||||||
using namespace toolkit;
|
using namespace toolkit;
|
||||||
@ -268,10 +265,8 @@ static inline string getProxyKey(const string &vhost,const string &app,const str
|
|||||||
return vhost + "/" + app + "/" + stream;
|
return vhost + "/" + app + "/" + stream;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !defined(_WIN32)
|
|
||||||
static unordered_map<string ,FFmpegSource::Ptr> s_ffmpegMap;
|
static unordered_map<string ,FFmpegSource::Ptr> s_ffmpegMap;
|
||||||
static recursive_mutex s_ffmpegMapMtx;
|
static recursive_mutex s_ffmpegMapMtx;
|
||||||
#endif//#if !defined(_WIN32)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 安装api接口
|
* 安装api接口
|
||||||
@ -646,7 +641,6 @@ void installWebApi() {
|
|||||||
val["data"]["flag"] = s_proxyMap.erase(allArgs["key"]) == 1;
|
val["data"]["flag"] = s_proxyMap.erase(allArgs["key"]) == 1;
|
||||||
});
|
});
|
||||||
|
|
||||||
#if !defined(_WIN32)
|
|
||||||
static auto addFFmpegSource = [](const string &src_url,
|
static auto addFFmpegSource = [](const string &src_url,
|
||||||
const string &dst_url,
|
const string &dst_url,
|
||||||
int timeout_ms,
|
int timeout_ms,
|
||||||
@ -713,7 +707,6 @@ void installWebApi() {
|
|||||||
API_REGIST(api,delFFmepgSource,{
|
API_REGIST(api,delFFmepgSource,{
|
||||||
api_delFFmpegSource(API_ARGS_VALUE);
|
api_delFFmpegSource(API_ARGS_VALUE);
|
||||||
});
|
});
|
||||||
#endif
|
|
||||||
|
|
||||||
//新增http api下载可执行程序文件接口
|
//新增http api下载可执行程序文件接口
|
||||||
//测试url http://127.0.0.1/index/api/downloadBin
|
//测试url http://127.0.0.1/index/api/downloadBin
|
||||||
@ -932,10 +925,8 @@ void unInstallWebApi(){
|
|||||||
s_proxyMap.clear();
|
s_proxyMap.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !defined(_WIN32)
|
|
||||||
{
|
{
|
||||||
lock_guard<recursive_mutex> lck(s_ffmpegMapMtx);
|
lock_guard<recursive_mutex> lck(s_ffmpegMapMtx);
|
||||||
s_ffmpegMap.clear();
|
s_ffmpegMap.clear();
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
@ -239,7 +239,7 @@ int main(int argc,char *argv[]) {
|
|||||||
|
|
||||||
//这里是拉流地址,支持rtmp/rtsp协议,负载必须是H264+AAC
|
//这里是拉流地址,支持rtmp/rtsp协议,负载必须是H264+AAC
|
||||||
//如果是其他不识别的音视频将会被忽略(譬如说h264+adpcm转发后会去除音频)
|
//如果是其他不识别的音视频将会被忽略(譬如说h264+adpcm转发后会去除音频)
|
||||||
auto urlList = {"rtsp://184.72.239.149/vod/mp4:BigBuckBunny_115k.mov"
|
auto urlList = {"rtsp://admin:admin123@192.168.1.64:554/cam/realmonitor?channel=1&subtype=1"
|
||||||
//rtsp链接支持输入用户名密码
|
//rtsp链接支持输入用户名密码
|
||||||
/*"rtsp://admin:jzan123456@192.168.0.122/"*/};
|
/*"rtsp://admin:jzan123456@192.168.0.122/"*/};
|
||||||
map<string, PlayerProxy::Ptr> proxyMap;
|
map<string, PlayerProxy::Ptr> proxyMap;
|
||||||
@ -258,7 +258,7 @@ int main(int argc,char *argv[]) {
|
|||||||
//rtsp://127.0.0.1/record/live/0/2017-04-11/11-09-38.mp4
|
//rtsp://127.0.0.1/record/live/0/2017-04-11/11-09-38.mp4
|
||||||
//rtmp://127.0.0.1/record/live/0/2017-04-11/11-09-38.mp4
|
//rtmp://127.0.0.1/record/live/0/2017-04-11/11-09-38.mp4
|
||||||
|
|
||||||
PlayerProxy::Ptr player(new PlayerProxy(DEFAULT_VHOST, "live", to_string(i).data()));
|
PlayerProxy::Ptr player(new PlayerProxy(DEFAULT_VHOST, "live", std::string("chn") + to_string(i).data()));
|
||||||
//指定RTP over TCP(播放rtsp时有效)
|
//指定RTP over TCP(播放rtsp时有效)
|
||||||
(*player)[kRtpType] = Rtsp::RTP_TCP;
|
(*player)[kRtpType] = Rtsp::RTP_TCP;
|
||||||
//开始播放,如果播放失败或者播放中止,将会自动重试若干次,重试次数在配置文件中配置,默认一直重试
|
//开始播放,如果播放失败或者播放中止,将会自动重试若干次,重试次数在配置文件中配置,默认一直重试
|
||||||
|
Loading…
Reference in New Issue
Block a user