mirror of
https://github.com/ZLMediaKit/ZLMediaKit.git
synced 2024-11-30 07:26:53 +08:00
Merge branch 'research' of https://gitee.com/liuziloong/FreeNVR
This commit is contained in:
commit
075a615a92
@ -34,6 +34,7 @@ namespace FFmpeg {
|
|||||||
#define FFmpeg_FIELD "ffmpeg."
|
#define FFmpeg_FIELD "ffmpeg."
|
||||||
const string kBin = FFmpeg_FIELD"bin";
|
const string kBin = FFmpeg_FIELD"bin";
|
||||||
const string kCmd = FFmpeg_FIELD"cmd";
|
const string kCmd = FFmpeg_FIELD"cmd";
|
||||||
|
const string kSnap = FFmpeg_FIELD"snap";
|
||||||
const string kLog = FFmpeg_FIELD"log";
|
const string kLog = FFmpeg_FIELD"log";
|
||||||
|
|
||||||
onceToken token([]() {
|
onceToken token([]() {
|
||||||
@ -41,9 +42,12 @@ onceToken token([]() {
|
|||||||
string ffmpeg_bin = System::execute("where ffmpeg");
|
string ffmpeg_bin = System::execute("where ffmpeg");
|
||||||
//windows下先关闭FFmpeg日志(目前不支持日志重定向)
|
//windows下先关闭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 ";
|
mINI::Instance()[kCmd] = "%s -re -i \"%s\" -loglevel quiet -c:a aac -strict -2 -ar 44100 -ab 48k -c:v libx264 -f flv %s ";
|
||||||
|
//利用ffmpeg进行抓拍
|
||||||
|
mINI::Instance()[kSnap] = "%s -i \"%s\" -loglevel quiet -y -f mjpeg -t 0.001 -s 720*576 %s ";
|
||||||
#else
|
#else
|
||||||
string ffmpeg_bin = System::execute("which ffmpeg");
|
string ffmpeg_bin = System::execute("which ffmpeg");
|
||||||
mINI::Instance()[kCmd] = "%s -re -i \"%s\" -c:a aac -strict -2 -ar 44100 -ab 48k -c:v libx264 -f flv %s ";
|
mINI::Instance()[kCmd] = "%s -re -i \"%s\" -c:a aac -strict -2 -ar 44100 -ab 48k -c:v libx264 -f flv %s ";
|
||||||
|
mINI::Instance()[kSnap] = "%s -i \"%s\" -y -f mjpeg -t 0.001 -s 720*576 %s ";
|
||||||
#endif
|
#endif
|
||||||
//默认ffmpeg命令路径为环境变量中路径
|
//默认ffmpeg命令路径为环境变量中路径
|
||||||
mINI::Instance()[kBin] = ffmpeg_bin.empty() ? "ffmpeg" : ffmpeg_bin;
|
mINI::Instance()[kBin] = ffmpeg_bin.empty() ? "ffmpeg" : ffmpeg_bin;
|
||||||
@ -64,6 +68,7 @@ FFmpegSource::~FFmpegSource() {
|
|||||||
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);
|
||||||
|
GET_CONFIG(string, ffmpeg_snap, FFmpeg::kSnap);
|
||||||
GET_CONFIG(string,ffmpeg_log,FFmpeg::kLog);
|
GET_CONFIG(string,ffmpeg_log,FFmpeg::kLog);
|
||||||
|
|
||||||
_src_url = src_url;
|
_src_url = src_url;
|
||||||
|
@ -53,7 +53,7 @@ void Process::run(const string &cmd, const string &log_file_tmp) {
|
|||||||
ZeroMemory(&si, sizeof(si)); //结构体初始化;
|
ZeroMemory(&si, sizeof(si)); //结构体初始化;
|
||||||
ZeroMemory(&pi, sizeof(pi));
|
ZeroMemory(&pi, sizeof(pi));
|
||||||
|
|
||||||
LPTSTR lpDir = const_cast<char*>(cmd .data());
|
LPTSTR lpDir = const_cast<char*>(cmd.data());
|
||||||
|
|
||||||
if (CreateProcess(NULL, lpDir, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)){
|
if (CreateProcess(NULL, lpDir, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)){
|
||||||
//下面两行关闭句柄,解除本进程和新进程的关系,不然有可能 不小心调用TerminateProcess函数关掉子进程
|
//下面两行关闭句柄,解除本进程和新进程的关系,不然有可能 不小心调用TerminateProcess函数关掉子进程
|
||||||
|
@ -71,6 +71,7 @@ static onceToken token([]() {
|
|||||||
});
|
});
|
||||||
}//namespace API
|
}//namespace API
|
||||||
|
|
||||||
|
|
||||||
class ApiRetException: public std::runtime_error {
|
class ApiRetException: public std::runtime_error {
|
||||||
public:
|
public:
|
||||||
ApiRetException(const char *str = "success" ,int code = API::Success):runtime_error(str){
|
ApiRetException(const char *str = "success" ,int code = API::Success):runtime_error(str){
|
||||||
@ -773,6 +774,119 @@ void installWebApi() {
|
|||||||
val["status"] = (int)status;
|
val["status"] = (int)status;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
//获取录像列表(按月),返回天
|
||||||
|
//http://127.0.0.1/index/api/getMp4RecordMonthly?app=live&stream=onvif&period=2020-01
|
||||||
|
api_regist1("/index/api/getMp4RecordMonthly", [](API_ARGS1){
|
||||||
|
CHECK_SECRET();
|
||||||
|
CHECK_ARGS("app", "stream", "period");
|
||||||
|
|
||||||
|
GET_CONFIG(string, recordAppName, Record::kAppName);
|
||||||
|
GET_CONFIG(string, recordPath, Record::kFilePath);
|
||||||
|
GET_CONFIG(bool, enableVhost, General::kEnableVhost);
|
||||||
|
|
||||||
|
auto _vhost = allArgs["vhost"];
|
||||||
|
auto _app = allArgs["app"];
|
||||||
|
auto _stream = allArgs["stream"];
|
||||||
|
auto _period = allArgs["period"];
|
||||||
|
|
||||||
|
//TODO:判断日期格式
|
||||||
|
|
||||||
|
//Vhost为空的话,存储路径不一样
|
||||||
|
if (_vhost.empty()) {
|
||||||
|
_vhost = DEFAULT_VHOST;
|
||||||
|
}
|
||||||
|
|
||||||
|
string strMp4RecordPath = "";
|
||||||
|
if (enableVhost) {
|
||||||
|
strMp4RecordPath = recordPath + "/" + _vhost + "/" + recordAppName + "/" + _app + "/" + _stream + "/" + _period;
|
||||||
|
} else {
|
||||||
|
strMp4RecordPath = recordPath + "/" + recordAppName + "/" + _app + "/" + _stream + "/" + _period;
|
||||||
|
}
|
||||||
|
|
||||||
|
//录像相对路径转绝对路径, 不然vs调试需要设置
|
||||||
|
strMp4RecordPath = File::absolutePath(strMp4RecordPath, "");
|
||||||
|
string strMp4Path = "";
|
||||||
|
File::scanDir(strMp4RecordPath, [&strMp4Path](const string &path, bool isDir) {
|
||||||
|
if (isDir) {
|
||||||
|
//DebugL << "dir:" << path.data();
|
||||||
|
int iPost = path.rfind('/');
|
||||||
|
if (iPost != string::npos)
|
||||||
|
{
|
||||||
|
string strPath = path.substr(iPost + 1);
|
||||||
|
strMp4Path += strPath + ",";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
},false);
|
||||||
|
|
||||||
|
//去掉strMp4Path最后一个 ‘,’
|
||||||
|
strMp4Path = strMp4Path.substr(0, strMp4Path.length() - 1);
|
||||||
|
|
||||||
|
Json::Value nVal;
|
||||||
|
nVal["vhost"] = _vhost.data();
|
||||||
|
nVal["app"] = _app.data();
|
||||||
|
nVal["stream"] = _stream.data();
|
||||||
|
nVal["app"] = _app.data();
|
||||||
|
nVal["path"] = strMp4Path;
|
||||||
|
|
||||||
|
val["data"] = nVal;
|
||||||
|
});
|
||||||
|
|
||||||
|
//获取录像列表(按天)
|
||||||
|
//http://127.0.0.1/index/api/getMp4RecordDaily?app=live&stream=onvif&period=2020-01-17
|
||||||
|
api_regist1("/index/api/getMp4RecordDaily",[](API_ARGS1) {
|
||||||
|
CHECK_SECRET();
|
||||||
|
CHECK_ARGS("app", "stream", "period");
|
||||||
|
|
||||||
|
GET_CONFIG(string, recordAppName, Record::kAppName);
|
||||||
|
GET_CONFIG(string, recordPath, Record::kFilePath);
|
||||||
|
GET_CONFIG(bool, enableVhost, General::kEnableVhost);
|
||||||
|
|
||||||
|
auto _vhost = allArgs["vhost"];
|
||||||
|
auto _app = allArgs["app"];
|
||||||
|
auto _stream = allArgs["stream"];
|
||||||
|
auto _period = allArgs["period"];
|
||||||
|
|
||||||
|
//TODO:判断日期格式
|
||||||
|
|
||||||
|
//Vhost为空的话,存储路径不一样
|
||||||
|
if (_vhost.empty()) {
|
||||||
|
_vhost = DEFAULT_VHOST;
|
||||||
|
}
|
||||||
|
|
||||||
|
string strMp4RecordPath = "";
|
||||||
|
//取录上一级目录,默认前7位位上级目录
|
||||||
|
string strParentPeriod = string(_period).substr(0, 7);
|
||||||
|
if (enableVhost) {
|
||||||
|
strMp4RecordPath = recordPath + "/" + _vhost + "/" + recordAppName + "/" + _app + "/" + _stream + "/" + strParentPeriod + "/" + _period;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
strMp4RecordPath = recordPath + "/" + recordAppName + "/" + _app + "/" + _stream + "/" + strParentPeriod + "/" + _period;
|
||||||
|
}
|
||||||
|
|
||||||
|
//录像相对路径转绝对路径, 不然vs调试需要设置
|
||||||
|
strMp4RecordPath = File::absolutePath(strMp4RecordPath, "");
|
||||||
|
Json::Value nVal;
|
||||||
|
DebugL << recordPath;
|
||||||
|
File::scanDir(strMp4RecordPath, [&](const string &path, bool isDir) {
|
||||||
|
if (!isDir) {
|
||||||
|
//去掉绝对路径,从record开始返回
|
||||||
|
int iPos = path.find(recordAppName);
|
||||||
|
string strPath = path.substr(iPos);
|
||||||
|
|
||||||
|
nVal["path"].append(strPath);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}, false);
|
||||||
|
|
||||||
|
nVal["vhost"] = _vhost.data();
|
||||||
|
nVal["app"] = _app.data();
|
||||||
|
nVal["stream"] = _stream.data();
|
||||||
|
nVal["app"] = _app.data();
|
||||||
|
|
||||||
|
val["data"] = nVal;
|
||||||
|
});
|
||||||
|
|
||||||
////////////以下是注册的Hook API////////////
|
////////////以下是注册的Hook API////////////
|
||||||
api_regist1("/index/hook/on_publish",[](API_ARGS1){
|
api_regist1("/index/hook/on_publish",[](API_ARGS1){
|
||||||
//开始推流事件
|
//开始推流事件
|
||||||
|
@ -1330,7 +1330,7 @@ int hevcDecodeShortTermRps(T_GetBitContext *pvBuf,
|
|||||||
int iDeltaRps;
|
int iDeltaRps;
|
||||||
unsigned int uiAbsDeltaRps;
|
unsigned int uiAbsDeltaRps;
|
||||||
uint8_t u8UseDeltaFlag = 0;
|
uint8_t u8UseDeltaFlag = 0;
|
||||||
uint8_t u8DeltaRpsSign;
|
uint8_t u8DeltaRpsSign = 0;
|
||||||
|
|
||||||
if (is_slice_header) {
|
if (is_slice_header) {
|
||||||
unsigned int uiDeltaIdx = parseUe(pvBuf) + 1;
|
unsigned int uiDeltaIdx = parseUe(pvBuf) + 1;
|
||||||
|
@ -52,10 +52,11 @@ MP4Recorder::~MP4Recorder() {
|
|||||||
|
|
||||||
void MP4Recorder::createFile() {
|
void MP4Recorder::createFile() {
|
||||||
closeFile();
|
closeFile();
|
||||||
auto strDate = getTimeStr("%Y-%m-%d");
|
auto strDate = getTimeStr("%Y-%m");
|
||||||
|
auto strDay = getTimeStr("%Y-%m-%d");
|
||||||
auto strTime = getTimeStr("%H-%M-%S");
|
auto strTime = getTimeStr("%H-%M-%S");
|
||||||
auto strFileTmp = _strPath + strDate + "/." + strTime + ".mp4";
|
auto strFileTmp = _strPath + strDate + "/" + strDay + "/." + strTime + ".mp4";
|
||||||
auto strFile = _strPath + strDate + "/" + strTime + ".mp4";
|
auto strFile = _strPath + strDate + "/" + strDay + "/" + strTime + ".mp4";
|
||||||
|
|
||||||
/////record 业务逻辑//////
|
/////record 业务逻辑//////
|
||||||
_info.ui64StartedTime = ::time(NULL);
|
_info.ui64StartedTime = ::time(NULL);
|
||||||
@ -66,6 +67,7 @@ void MP4Recorder::createFile() {
|
|||||||
+ _info.strAppName + "/"
|
+ _info.strAppName + "/"
|
||||||
+ _info.strStreamId + "/"
|
+ _info.strStreamId + "/"
|
||||||
+ strDate + "/"
|
+ strDate + "/"
|
||||||
|
+ strDay + "/"
|
||||||
+ strTime + ".mp4";
|
+ strTime + ".mp4";
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
Loading…
Reference in New Issue
Block a user