提交 ead11e58 authored 作者: blu's avatar blu

video upload & motion detection

上级 0b173acb
......@@ -80,6 +80,6 @@ payload: {
```json
{ "time":1567669674, "cmd":"upload_video", "rid":"001231554A20", "data":{ "start":1590542800, "end":1590542900, "type":6 } }
{ "time":1567669674, "cmd":"upload_video", "rid":"001231554A20", "data":{ "start":1590716600, "end":1590716700, "type":6 } }
```
......@@ -45,7 +45,7 @@ SN := {UINT8*SN_LEN} # 摄像头SN, 长度为
START_TS := TS # 事件开始时间
END_TS := TS # 时间结束时间
TYPE := UINT8 # 0 - 未定义, 1 - AI人形, 2 - AI人脸, 3 - 移动侦测,
# 4 - 覆盖, 5 - 覆盖解除, 6 - 视频获取
# 4 - 覆盖, 5 - 覆盖解除, 6 - 视频获取, 7 - AI和移动综合
# 其他 - 由发起请求的微服务自定义
FILE_META := FILE_TS,SIZE
FILE_TS := TS # 文件开始时间
......
......@@ -203,12 +203,18 @@ ntp_LIB_DEPENDS:STATIC=
//Dependencies for target
ptz_LIB_DEPENDS:STATIC=
//Dependencies for target
record_upload_LIB_DEPENDS:STATIC=
//Dependencies for target
smart_LIB_DEPENDS:STATIC=
//Dependencies for target
tcp_client_LIB_DEPENDS:STATIC=
//Dependencies for target
upload_LIB_DEPENDS:STATIC=
//Dependencies for target
util_LIB_DEPENDS:STATIC=
......
......@@ -24,7 +24,8 @@ add_library(mqtthelper STATIC ../include/mqtt_helper.cc)
add_library(motion STATIC motion.cc)
add_library(smart STATIC smart.cc)
add_library(ptz STATIC ptz.cc)
add_library(record_upload STATIC record_upload.cc)
add_executable(evcamera main.cc)
target_link_libraries(evcamera PUBLIC ntp paho-mqtt3a mqtthelper tcp_client evutils smart motion ptz zmq ${COMMON_LIBS} ${XM_LIBS})
target_link_libraries(evcamera PUBLIC ntp paho-mqtt3a mqtthelper tcp_client evutils smart motion record_upload ptz zmq ${COMMON_LIBS} ${XM_LIBS})
add_executable(test_fsm test_fsm.cc)
\ No newline at end of file
......@@ -4,6 +4,18 @@ using namespace std;
using namespace jsoncons;
using namespace jsoncons::literals;
unsigned short crc16(const unsigned char* data_p, unsigned char length){
unsigned char x;
unsigned short crc = 0xFFFF;
while (length--){
x = crc >> 8 ^ *data_p++;
x ^= x>>4;
crc = (crc << 8) ^ ((unsigned short)(x << 12)) ^ ((unsigned short)(x <<5)) ^ ((unsigned short)x);
}
return crc;
}
namespace evutils {
const char consts::version[] = "EVC20200429";
const string consts::kMsgCmd = "cmd";
......@@ -55,6 +67,7 @@ const string consts::pub_topic_report = "/evcamera/v1.0/report";
const string consts::mqtt_url = "tcp://admin:vJ3zHqWrHbrqxVMT@evcloudsvc.ilabservice.cloud:11883";
const string consts::vgw_addr = "tcp://evcloudsvc.ilabservice.cloud:7123";
const string consts::upload_addr = "tcp://evcloudsvc.ilabservice.cloud:10009";
const string consts::strPubUrl = "inproc://frame";
consts &consts::self()
{
......
......@@ -15,6 +15,19 @@
#include <fmt/format.h>
#include <jsoncons/json.hpp>
struct StrException : public std::exception {
std::string s;
StrException(std::string ss) : s(ss) {}
~StrException() throw () {} // Updated
const char* what() const throw()
{
return s.c_str();
}
};
unsigned short crc16(const unsigned char* data_p, unsigned char length);
namespace evutils {
using namespace std;
using namespace jsoncons;
......@@ -70,6 +83,7 @@ typedef struct consts{
static const string mqtt_url;
static const string vgw_addr;
static const string upload_addr;
static const string strPubUrl;
static consts& self();
}consts;
......@@ -167,7 +181,7 @@ public:
}
}
set<TN> findByRange(TN tss, TN tse, TN & offsetS, TN &offsetE)
set<TN> findByRange(TN tss, TN tse, TN & offsetS, TN &offsetE, int lagSecs, int *status = nullptr)
{
set<TN> ret;
lock_guard<mutex> lg(mut);
......@@ -179,8 +193,18 @@ public:
auto _it = list_.end();
TN end = *(--_it);
if(tse < first||tss > end) {
if(tse < first||tss > end || tse > end || end - tse < lagSecs*1000) {
int s = 0;
spdlog::info("range requested ({}, {}) is not in range existed ({}, {}).", tss, tse, first, end);
if(tse < first) {
s = -1;
}else{
s = 1;
}
if(status){
*status = s;
}
return ret;
}
......@@ -218,6 +242,9 @@ public:
if(last != 0) {
offsetE = last - tse;
}
if(status){
*status = 0;
}
}
return ret;
......
......@@ -13,6 +13,7 @@ typedef struct ev_region_t {
} ev_region_t;
typedef struct ev_module_config_t {
MqttHelper *pClient;
void **pPubCtx;
struct module{
struct record{
int interval; // in seconds
......
差异被折叠。
......@@ -7,8 +7,10 @@
#include <sml.hpp>
#include <map>
#include <string>
#include "record_upload.h"
namespace sml = boost::sml;
extern thread_upload_args_t gUploadArgs;
namespace md{
/// types
......@@ -23,6 +25,7 @@ namespace md{
const string kKeyN= "n";
const string kKeyP= "p";
const int kMaxCntMotionInPre = 5; // about 20s
const int kMaxDuration = 60*20; // max 20 minutes duration to force generating event videos
/// helpers
auto event_inspection(auto e, std::map<const std::string, int> &m){
......@@ -102,10 +105,13 @@ namespace md{
spdlog::info("post -n-> none, {}", timeEnd/1000);
}
/// TODO: force event generation when max time duration reached
upload_item_t item{timeStart, timeEnd, 7, -1, timeEnd};
{
lock_guard<mutex> lg(*gUploadArgs.mut);
gUploadArgs.que->push(item);
gUploadArgs.cv->notify_one();
}
spdlog::info("event start:{}, end:{}, hasMotion: {}", timeStart, timeEnd, hasMotion);
/// TODO: generate event for uploading
};
const auto action_pre2pre = [this](auto e){
cntMotionOnly++;
......@@ -114,6 +120,22 @@ namespace md{
timeStart = chrono::duration_cast<chrono::milliseconds>(chrono::system_clock::now().time_since_epoch()).count();
}
};
const auto may_generate_event = [this]{
auto now = chrono::duration_cast<chrono::milliseconds>(chrono::system_clock::now().time_since_epoch()).count();
if(timeStart != 0 && (now - timeStart) >= kMaxDuration *1000){
upload_item_t item{timeStart, now, 6, -1, now};
{
lock_guard<mutex> lg(*gUploadArgs.mut);
gUploadArgs.que->push(item);
gUploadArgs.cv->notify_one();
}
timeStart = now;
return true;
}
return false;
};
using namespace sml;
return make_transition_table(
*"init"_s = "none"_s,
......@@ -121,28 +143,35 @@ namespace md{
"none"_s + event<motion>/[]{spdlog::info("none -m-> pre");} = "pre"_s,
"none"_s + event<people>/action_none2in = "in"_s,
"none"_s + event<mpboth>/action_none2in = "in"_s,
// pre
"pre"_s + event<none>/[]{spdlog::info("pre -n-> none");} = "none"_s,
"pre"_s + event<motion>/action_pre2pre = "pre"_s,
"pre"_s + event<people>/action_pre2in = "in"_s,
"pre"_s + event<mpboth>/action_pre2in = "in"_s,
// in
"in"_s + event<none> [guard_in2post]/[]{spdlog::info("in -n-> post");} = "post"_s,
"in"_s + event<motion> [guard_in2post]/[]{spdlog::info("in -m-> post");} = "post"_s,
"in"_s + event<people> [guard_in2post]/[]{spdlog::info("in -p-> post");} = "post"_s,
"in"_s + event<mpboth>/guard_in2post,
"in"_s + sml::on_entry<_> / may_generate_event,
// post
"post"_s + event<mpboth>/guard_post2none = "in"_s,
"post"_s + event<people> [guard_post2none]/action_post2none = "none"_s,
"post"_s + event<motion> [guard_post2none]/action_post2none = "none"_s,
"post"_s + event<none> [guard_post2none]/action_post2none = "none"_s,
// "post"_s + sml::on_entry<_> / may_generate_event,
//
"none"_s + sml::on_entry<_> / [this]{hasMotion = false,timeStart = 0;}
);
}
private:
bool hasMotion{false};
int cntMotionOnly = 0;
uint64_t timeStart{0};
int64_t timeStart{0};
std::map<const std::string, int>guards{{"m", 0}, {"p", 0}, {"n", 0}};
};
}
......
......@@ -7,6 +7,8 @@
#include <fcntl.h>
#include "raw_tcp.h"
using namespace std;
int raw_connect(std::string host, std::string port, int *socket_, int recv_timeout, int send_timeout)
{
int rv = 0;
......@@ -71,3 +73,20 @@ int raw_connect(std::string host, std::string port, int *socket_, int recv_timeo
::freeaddrinfo(addrinfo_result);
return rv;
}
string raw_send(int s, const void *buf, size_t len){
string rc;
ssize_t sent = 0;
while(len > 0) {
sent = ::send(s, buf, len, 0);
if(sent <= 0){
break;
}
len -= sent;
}
if(len > 0 || sent<=0){
rc = fmt::format("failed to send: {}", strerror(errno));
}
return rc;
}
\ No newline at end of file
......@@ -9,6 +9,6 @@
#include <mutex>
#include "common.h"
using namespace std;
int raw_connect(std::string host, std::string port, int *socket_, int recv_timeout = 3, int send_timeout = 3);
std::string raw_send(int s, const void *buf, size_t len);
#endif
\ No newline at end of file
......@@ -39,7 +39,6 @@ XM_S32 MaQue_JpegEnc_getFrame_callback (XM_VOID *pUserArg, MaQueSmartJpegFrame_s
return XM_SUCCESS;
}
void maq_smart_task_entry(ev_module_config_t *pArg)
{
if(!pArg->module.ai.enabled) {
......@@ -210,22 +209,30 @@ void maq_smart_task_entry(ev_module_config_t *pArg)
int deltaMotionCnt = motionCnt_ - motionCntLast;
motionCntLast = motionCnt_;
spdlog::info("deltaTimeMs {}", deltaTimeMs);
if(deltaTimeMs == 0){
spdlog::warn("no video frames in last ~5 seconds");
}else{
if(deltaMotionCnt >= motionCntThresh) {
hasMotion = true;
}
if(hasMotion && hasHuman) {
spdlog::info("ai_task: deltaTimeMs {}, mpboth", deltaTimeMs);
fsm.process_event(md::mpboth{});
}
else if(hasMotion) {
spdlog::info("ai_task: deltaTimeMs {}, motion", deltaTimeMs);
fsm.process_event(md::motion{});
}
else if(hasHuman) {
spdlog::info("ai_task: deltaTimeMs {}, people", deltaTimeMs);
fsm.process_event(md::people{});
}
else {
spdlog::info("ai_task: deltaTimeMs {}, none", deltaTimeMs);
fsm.process_event(md::none{});
}
}
// reset
windowSecs = kMotionDetectWindowSeconds;
hasHuman = false;
......
......@@ -49,18 +49,6 @@ typedef struct evpacket_t {
uint32_t length;
} *evpacket_ptr_t;
static inline unsigned short crc16(const unsigned char* data_p, unsigned char length){
unsigned char x;
unsigned short crc = 0xFFFF;
while (length--){
x = crc >> 8 ^ *data_p++;
x ^= x>>4;
crc = (crc << 8) ^ ((unsigned short)(x << 12)) ^ ((unsigned short)(x <<5)) ^ ((unsigned short)x);
}
return crc;
}
#endif
\ No newline at end of file
......@@ -48,15 +48,6 @@ typedef void (*on_msg_fun_ptr_t)(MqttHelper *hlp, const void * const data, int l
template<typename R>
bool is_ready(std::future<R> const& f);
struct StrException : public std::exception {
std::string s;
StrException(std::string ss) : s(ss) {}
~StrException() throw () {} // Updated
const char* what() const throw()
{
return s.c_str();
}
};
class MqttPub {
private:
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论