提交 61621d77 authored 作者: blu's avatar blu

refactor, bugfix, ptz implementation and more

上级 b92bb722
...@@ -93,5 +93,6 @@ ...@@ -93,5 +93,6 @@
"forward_list": "cpp", "forward_list": "cpp",
"future": "cpp", "future": "cpp",
"maque_mem.h": "c" "maque_mem.h": "c"
} },
"C_Cpp.errorSquiggles": "Disabled"
} }
\ No newline at end of file
...@@ -140,45 +140,40 @@ payload: ...@@ -140,45 +140,40 @@ payload:
```json ```json
{ {
"time": ts, "time":1567669674,
"rid": "<request_rid>", "cmd":"config",
"type": "response", "rid":"001231554A20",
"cata": "config", "data":{
"sn": "A000000Z", "sn":"001231554A20",
"code": 0, "vgw":"192.168.55.104:7123",
"msg": "OK", "mqtt":"admin:vJ3zHqWrHbrqxVMT@evcloudsvc.ilabservice.cloud:11883",
"data": { "upload":"evcloudsvc.ilabservice.cloud:10009",
"vgw": "evcloudsvc.ilabservice.cloud:7123", "features":{
"mqtt": "admin:password@evcloudsvc.ilabservice.cloud:11883", "push":"1",
"upload": "evcloudsvc.ilabservice.cloud:10009", "motion":{
"features": { "enabled":0,
"motion": { "region":{
"enable": 1, "maxX":0.7,
"level": 3, // 1 - 6 "maxY":0.7,
"region":{ "minX":0.3,
"minX": 0.1, "minY":0.3
"minY": 0.1, },
"maxX": 0.9, "level":4
"maxY": 0.9 },
} "recordLen":30,
}, "ai":{
"record":{ "enabled":1,
"enable": 1, "faceThresh":0.65,
"interval": 30, // seconds of one slice "humanThresh":0.63,
"duration": 24 // hours of local recording "region":{
}, "maxX":1,
"ai":{ "maxY":1,
"enable": 1, "minX":0,
"face_thresh": 0.75, // 0 - 1 "minY":0
"human_thresh": 0.63, // 0 - 1 }
"region":{ }
"minX": 0.1,
"minY": 0.1,
"maxX": 0.9,
"maxY": 0.9
}
} }
} }
} }
``` ```
...@@ -196,7 +191,6 @@ REQUEST_VIDEOS_T ...@@ -196,7 +191,6 @@ REQUEST_VIDEOS_T
"cmd": "upload_video", "cmd": "upload_video",
"rid": "<random_str>", "rid": "<random_str>",
"data": { "data": {
{
"start": 1567669674, "start": 1567669674,
"end": 1567668000, "end": 1567668000,
"type": 6 "type": 6
...@@ -223,3 +217,52 @@ REQUEST_VIDEOS_T ...@@ -223,3 +217,52 @@ REQUEST_VIDEOS_T
} }
``` ```
### Report: AI Image
```json
{
"category":"ai_image",
"code":0,
"data":{
"data":"<base64_string>",
"encoding":"base64",
"format":"JPG",
"type":"image"
},
"msg":"new ai capture: pic, idx = 0, toltal = 1",
"rid":"",
"sn":"EVC001231554A20",
"time":1589537073532,
"type":"report"
}
```
### Request: status
```json
{
"time": 1567669674,
"cmd": "status",
"rid": "001231554A20",
"data": {}
}
```
### Request PTZ
```json
{
"time":1567669674,
"cmd":"ptz",
"rid":"001231554A20",
"data":{
"action":"left",
"degree":10
}
}
```
...@@ -200,6 +200,9 @@ mqtthelper_LIB_DEPENDS:STATIC= ...@@ -200,6 +200,9 @@ mqtthelper_LIB_DEPENDS:STATIC=
//Dependencies for target //Dependencies for target
ntp_LIB_DEPENDS:STATIC= ntp_LIB_DEPENDS:STATIC=
//Dependencies for target
ptz_LIB_DEPENDS:STATIC=
//Dependencies for target //Dependencies for target
smart_LIB_DEPENDS:STATIC= smart_LIB_DEPENDS:STATIC=
......
...@@ -24,7 +24,8 @@ add_library(evutils STATIC evutils.cc) ...@@ -24,7 +24,8 @@ add_library(evutils STATIC evutils.cc)
add_library(mqtthelper STATIC ../include/mqtt_helper.cc) add_library(mqtthelper STATIC ../include/mqtt_helper.cc)
add_library(motion STATIC motion.cc) add_library(motion STATIC motion.cc)
add_library(smart STATIC smart.cc) add_library(smart STATIC smart.cc)
add_library(ptz STATIC ptz.cc)
#add_library(util STATIC utils.cpp) #add_library(util STATIC utils.cpp)
add_executable(evcamera main.cc) add_executable(evcamera main.cc)
target_link_libraries(evcamera PUBLIC ntp paho-mqtt3a mqtthelper tcp_client evutils smart motion zmq ${COMMON_LIBS} ${XM_LIBS}) target_link_libraries(evcamera PUBLIC ntp paho-mqtt3a mqtthelper tcp_client evutils smart motion ptz zmq ${COMMON_LIBS} ${XM_LIBS})
[
{
"op":"replace",
"path":"/features/ai/faceThresh",
"value":0.65
},
{
"op":"replace",
"path":"/features/motion/enabled",
"value":0
},
{
"op":"replace",
"path":"/features/motion/level",
"value":4
},
{
"op":"replace",
"path":"/features/motion/region/maxX",
"value":0.7
},
{
"op":"replace",
"path":"/features/motion/region/maxY",
"value":0.7
},
{
"op":"replace",
"path":"/features/motion/region/minX",
"value":0.3
},
{
"op":"replace",
"path":"/features/motion/region/minY",
"value":0.3
},
{
"op":"replace",
"path":"/features/push",
"value":1
},
{
"op":"replace",
"path":"/mqtt",
"value":"admin:vJ3zHqWrHbrqxVMT@evcloudsvc.ilabservice.cloud:11883"
},
{
"op":"replace",
"path":"/vgw",
"value":"192.168.55.104:7123"
},
{
"op":"add",
"path":"/sn",
"value":"001231554A20"
}
]
\ No newline at end of file
...@@ -28,9 +28,14 @@ const string consts::kMsgCmdGetConfig = "get_config"; ...@@ -28,9 +28,14 @@ const string consts::kMsgCmdGetConfig = "get_config";
const string consts::kMsgCmdReboot = "reboot"; const string consts::kMsgCmdReboot = "reboot";
const string consts::kMsgCmdPtz = "ptz"; const string consts::kMsgCmdPtz = "ptz";
const string consts::kMsgType = "type"; const string consts::kMsgType = "type";
const string consts::kMsgTypeImage = "image";
const string consts::kMsgEncode = "encoding";
const string consts::kMsgEncodeBase64 = "base64";
const string consts::kMsgFormat = "format";
const string consts::kMsgFormatJpeg = "JPG";
const string consts::kMsgCata = "category"; const string consts::kMsgCata = "category";
const string consts::kMsgTypeReport = "report"; const string consts::kMsgTypeReport = "report";
const string consts::kMsgTypeResponse = "response"; const string consts::kMsgTypeResponse = "response";
const string consts::kMsgTime = "time"; const string consts::kMsgTime = "time";
const string consts::kMsgData = "data"; const string consts::kMsgData = "data";
const string consts::kMsgRid = "rid"; const string consts::kMsgRid = "rid";
...@@ -44,8 +49,11 @@ const string consts::sub_topic = "evcamera/v1.0/request/"; ...@@ -44,8 +49,11 @@ const string consts::sub_topic = "evcamera/v1.0/request/";
const string consts::pub_topic_response = "evcamera/v1.0/response/"; const string consts::pub_topic_response = "evcamera/v1.0/response/";
const string consts::pub_topic_report = "evcamera/v1.0/report"; 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::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";
consts &consts::self(){ consts &consts::self()
{
static consts cons; static consts cons;
return cons; return cons;
} }
...@@ -58,7 +66,7 @@ string msg_field(const json &msg, const string &field) ...@@ -58,7 +66,7 @@ string msg_field(const json &msg, const string &field)
bool is_sdcard_avail(char *path) bool is_sdcard_avail(char *path)
{ {
char p[] = "/sys/block/mmcblk0/size"; char p[] = "/sys/block/mmcblk0/size";
if(path == nullptr){ if(path == nullptr) {
path = p; path = p;
} }
std::ifstream fsize(path); std::ifstream fsize(path);
...@@ -66,7 +74,8 @@ bool is_sdcard_avail(char *path) ...@@ -66,7 +74,8 @@ bool is_sdcard_avail(char *path)
return (fsize >> size) && (size > 0); return (fsize >> size) && (size > 0);
} }
json make_default_config(){ json make_default_cloud_config()
{
return R"( return R"(
{ {
"vgw":"evcloudsvc.ilabservice.cloud:7123", "vgw":"evcloudsvc.ilabservice.cloud:7123",
...@@ -101,9 +110,22 @@ json make_default_config(){ ...@@ -101,9 +110,22 @@ json make_default_config(){
)"_json; )"_json;
} }
void get_mac_addr(char *buf, char *intf){ json make_default_sys_extra_config()
{
return R"(
{
"ptz":{
"x": 177.5,
"y": 0
}
}
)"_json;
}
void get_mac_addr(char *buf, char *intf)
{
char p[] = "/sys/class/net/eth0/address"; char p[] = "/sys/class/net/eth0/address";
if(intf == nullptr){ if(intf == nullptr) {
intf = p; intf = p;
} }
...@@ -111,8 +133,8 @@ void get_mac_addr(char *buf, char *intf){ ...@@ -111,8 +133,8 @@ void get_mac_addr(char *buf, char *intf){
string s; string s;
fsize >>s; fsize >>s;
int i = 0; int i = 0;
for(auto &k:s){ for(auto &k:s) {
if(k != ':'){ if(k != ':') {
*(buf+ i++) = ::toupper(k); *(buf+ i++) = ::toupper(k);
} }
} }
...@@ -121,26 +143,27 @@ void get_mac_addr(char *buf, char *intf){ ...@@ -121,26 +143,27 @@ void get_mac_addr(char *buf, char *intf){
bool get_sdcard_megabytes(uint64_t &total, uint64_t &free, char* path ) bool get_sdcard_megabytes(uint64_t &total, uint64_t &free, char* path )
{ {
struct statvfs stat; struct statvfs stat;
char p[] = "/mnt/sd"; char p[] = "/mnt/sd";
if(path == nullptr){ if(path == nullptr) {
path = p; path = p;
} }
if (statvfs(path, &stat) != 0) { if (statvfs(path, &stat) != 0) {
// error happens, just quits here // error happens, just quits here
return false; return false;
} }
/// NOTES: avoid trucating errors /// NOTES: avoid trucating errors
total = (stat.f_blocks/1024.0) * (stat.f_bsize /1024.0); total = (stat.f_blocks/1024.0) * (stat.f_bsize /1024.0);
free = (stat.f_bavail/1024.0) * (stat.f_bsize /1024.0); free = (stat.f_bavail/1024.0) * (stat.f_bsize /1024.0);
spdlog::info("sd: {} {} {} {} {} {} {}", stat.f_bsize, stat.f_blocks, stat.f_bavail, stat.f_bfree ,stat.f_favail, stat.f_ffree, stat.f_frsize); spdlog::info("sd: {} {} {} {} {} {} {}", stat.f_bsize, stat.f_blocks, stat.f_bavail, stat.f_bfree,stat.f_favail, stat.f_ffree, stat.f_frsize);
return true; return true;
} }
/// returns negtive for failure, otherwise success /// returns negtive for failure, otherwise success
int setupDealer(void **ctx, void **s, string ident, string addr, int sndQS, int timeoutMs) { int setupDealer(void **ctx, void **s, string ident, string addr, int sndQS, int timeoutMs)
{
int ret = 0; int ret = 0;
*ctx = zmq_ctx_new(); *ctx = zmq_ctx_new();
*s = zmq_socket(*ctx, ZMQ_DEALER); *s = zmq_socket(*ctx, ZMQ_DEALER);
...@@ -151,7 +174,7 @@ int setupDealer(void **ctx, void **s, string ident, string addr, int sndQS, int ...@@ -151,7 +174,7 @@ int setupDealer(void **ctx, void **s, string ident, string addr, int sndQS, int
zmq_setsockopt(*s, ZMQ_TCP_KEEPALIVE_INTVL, &ret, sizeof (ret)); zmq_setsockopt(*s, ZMQ_TCP_KEEPALIVE_INTVL, &ret, sizeof (ret));
ret = 2; ret = 2;
zmq_setsockopt(*s, ZMQ_TCP_KEEPALIVE_CNT, &ret, sizeof (ret)); zmq_setsockopt(*s, ZMQ_TCP_KEEPALIVE_CNT, &ret, sizeof (ret));
if(sndQS!=0){ if(sndQS!=0) {
zmq_setsockopt(*s, ZMQ_SNDHWM, &sndQS, sizeof (sndQS)); zmq_setsockopt(*s, ZMQ_SNDHWM, &sndQS, sizeof (sndQS));
} }
if(timeoutMs != 0) { if(timeoutMs != 0) {
...@@ -160,13 +183,14 @@ int setupDealer(void **ctx, void **s, string ident, string addr, int sndQS, int ...@@ -160,13 +183,14 @@ int setupDealer(void **ctx, void **s, string ident, string addr, int sndQS, int
} }
zmq_setsockopt(*s, ZMQ_RCVTIMEO, &timeoutMs, sizeof(timeoutMs)); zmq_setsockopt(*s, ZMQ_RCVTIMEO, &timeoutMs, sizeof(timeoutMs));
} }
ret = zmq_setsockopt(*s, ZMQ_IDENTITY, ident.c_str(), ident.size()); ret = zmq_setsockopt(*s, ZMQ_IDENTITY, ident.c_str(), ident.size());
if(ret < 0) { if(ret < 0) {
zmq_close(*s); zmq_close(*s);
zmq_ctx_destroy(*ctx); zmq_ctx_destroy(*ctx);
spdlog::debug("{} failed setsockopts ZMQ_ROUTING_ID to {}: {}", ident, addr, zmq_strerror(zmq_errno())); spdlog::debug("{} failed setsockopts ZMQ_ROUTING_ID to {}: {}", ident, addr, zmq_strerror(zmq_errno()));
}else{ }
else {
ret = zmq_connect(*s, addr.c_str()); ret = zmq_connect(*s, addr.c_str());
if(ret != 0) { if(ret != 0) {
zmq_close(*s); zmq_close(*s);
...@@ -175,10 +199,11 @@ int setupDealer(void **ctx, void **s, string ident, string addr, int sndQS, int ...@@ -175,10 +199,11 @@ int setupDealer(void **ctx, void **s, string ident, string addr, int sndQS, int
} }
} }
return ret; return ret;
} }
int setupRouter(void **ctx, void **s, string addr, int rcvQS){ int setupRouter(void **ctx, void **s, string addr, int rcvQS)
{
int ret = 0; int ret = 0;
*ctx = zmq_ctx_new(); *ctx = zmq_ctx_new();
*s = zmq_socket(*ctx, ZMQ_ROUTER); *s = zmq_socket(*ctx, ZMQ_ROUTER);
...@@ -199,7 +224,8 @@ int setupRouter(void **ctx, void **s, string addr, int rcvQS){ ...@@ -199,7 +224,8 @@ int setupRouter(void **ctx, void **s, string addr, int rcvQS){
return ret; return ret;
} }
int z_recv_multiple(void *s, vector<uint8_t> &buf, int &frames) { int z_recv_multiple(void *s, vector<uint8_t> &buf, int &frames)
{
int64_t more = 1; int64_t more = 1;
size_t more_size = sizeof(more); size_t more_size = sizeof(more);
int ret = 0; int ret = 0;
...@@ -229,12 +255,72 @@ int z_recv_multiple(void *s, vector<uint8_t> &buf, int &frames) { ...@@ -229,12 +255,72 @@ int z_recv_multiple(void *s, vector<uint8_t> &buf, int &frames) {
if(ret < 0 || (frames != 0 && cnt != frames)) { if(ret < 0 || (frames != 0 && cnt != frames)) {
spdlog::error("failed to recv msg: {}", ret < 0? zmq_strerror(ret): "invalid frames"); spdlog::error("failed to recv msg: {}", ret < 0? zmq_strerror(ret): "invalid frames");
return -1; return -1;
}else{ }
else {
frames = cnt; frames = cnt;
} }
return 0; return 0;
} }
namespace _internal_ {
mutex mutConfigFiles;
}
/// mk MUST NOT be null when isMerge is true
string save_json(json &data, string path, bool isMerge, fn_mk_default_json mk)
{
lock_guard<mutex> lk(_internal_::mutConfigFiles);
string rc;
json js;
if(isMerge) {
rc = load_json(js, path, mk);
if(!rc.empty()) {
return rc;
}
try {
js.merge_or_update(data);
}
catch(exception &e) {
rc = fmt::format("failed to merge json: {}, {} + {}", e.what(), js.to_string(), data.to_string());
return rc;
}
}
ofstream ocfg_(path, std::ios::trunc);
if(ocfg_.is_open()) {
ocfg_ << pretty_print(data);
ocfg_.flush();
ocfg_.close();
}
else {
rc = fmt::format("failed to open configuration file: {}", path);
spdlog::error(rc);
}
return rc;
}
string load_json(json &config, string path, fn_mk_default_json mk)
{
lock_guard<mutex> lk(_internal_::mutConfigFiles);
string rc;
try {
ifstream cfg_(path);
config = json::parse(cfg_);
}
catch(exception &e) {
spdlog::error("failed loading config: {}, force to make default config:\n{}", e.what(), config.to_string());
if(mk != nullptr) {
config = mk();
}
else {
rc = "no default make config function provided";
spdlog::error(rc);
}
}
return rc;
}
} }
\ No newline at end of file
...@@ -43,6 +43,11 @@ typedef struct consts{ ...@@ -43,6 +43,11 @@ typedef struct consts{
static const string kMsgCmdReboot; static const string kMsgCmdReboot;
static const string kMsgCmdPtz; static const string kMsgCmdPtz;
static const string kMsgType; static const string kMsgType;
static const string kMsgTypeImage;
static const string kMsgEncode;
static const string kMsgEncodeBase64;
static const string kMsgFormat;
static const string kMsgFormatJpeg;
static const string kMsgCata; static const string kMsgCata;
static const string kMsgTypeReport; static const string kMsgTypeReport;
static const string kMsgTypeResponse; static const string kMsgTypeResponse;
...@@ -60,12 +65,15 @@ typedef struct consts{ ...@@ -60,12 +65,15 @@ typedef struct consts{
static const string pub_topic_response; static const string pub_topic_response;
static const string pub_topic_report; static const string pub_topic_report;
static const string mqtt_url; static const string mqtt_url;
static const string vgw_addr;
static const string upload_addr;
static consts& self(); static consts& self();
}consts; }consts;
extern string msg_field(const json &msg, const string &field); extern string msg_field(const json &msg, const string &field);
extern bool is_sdcard_avail(char *path = nullptr); extern bool is_sdcard_avail(char *path = nullptr);
extern json make_default_config(); extern json make_default_cloud_config();
extern json make_default_sys_extra_config();
extern void get_mac_addr(char *buf, char *intf = nullptr); extern void get_mac_addr(char *buf, char *intf = nullptr);
extern bool get_sdcard_megabytes(uint64_t &total, uint64_t &free, char* path = nullptr); extern bool get_sdcard_megabytes(uint64_t &total, uint64_t &free, char* path = nullptr);
extern int setupDealer(void **ctx, void **s, string ident, string addr, int sndQS=0, int timeoutMs = -1); extern int setupDealer(void **ctx, void **s, string ident, string addr, int sndQS=0, int timeoutMs = -1);
...@@ -82,6 +90,8 @@ private: ...@@ -82,6 +90,8 @@ private:
size_t maxSize; size_t maxSize;
mutex mut; mutex mut;
TN oldestTs; TN oldestTs;
int freeMB = 0;
const int kReservedMB_ = 300;
cb_remove_elem<TN> fn_remove; cb_remove_elem<TN> fn_remove;
unsigned long cntInsert = 0; unsigned long cntInsert = 0;
public: public:
...@@ -93,16 +103,27 @@ public: ...@@ -93,16 +103,27 @@ public:
if(cntInsert % 10 == 0) { if(cntInsert % 10 == 0) {
oldestTs = chrono::duration_cast<chrono::milliseconds>(chrono::system_clock::now().time_since_epoch()).count() - 60*2*1000*maxSize; oldestTs = chrono::duration_cast<chrono::milliseconds>(chrono::system_clock::now().time_since_epoch()).count() - 60*2*1000*maxSize;
spdlog::info("record: maxSlices {}, oldestTs {}", maxSize, oldestTs); spdlog::info("record: maxSlices {}, oldestTs {}", maxSize, oldestTs);
uint64_t mt, mf;
if(get_sdcard_megabytes(mt, mf)){
freeMB = mf;
}else{
freeMB = -1;
}
} }
++cntInsert; ++cntInsert;
if(elem < oldestTs) {
if(fn != nullptr) { /// ATTENTION: we don't remove old file unless it can't be hold
(*fn)(elem); bool forceRemoveOldFiles = false;
} if(forceRemoveOldFiles){
else if(fn_remove != nullptr) { if(elem < oldestTs) {
(*fn_remove)(elem); if(fn != nullptr) {
(*fn)(elem);
}
else if(fn_remove != nullptr) {
(*fn_remove)(elem);
}
return;
} }
return;
} }
if(list_.size() == 0) { if(list_.size() == 0) {
...@@ -125,7 +146,7 @@ public: ...@@ -125,7 +146,7 @@ public:
list_.insert(itr.base(), elem); list_.insert(itr.base(), elem);
} }
if(list_.size() > maxSize) { if(list_.size() > maxSize||(freeMB != -1 && freeMB <= kReservedMB_)) {
lock_guard<mutex> lg(mut); lock_guard<mutex> lg(mut);
auto ts = *(list_.begin()); auto ts = *(list_.begin());
list_.erase(list_.begin()); list_.erase(list_.begin());
...@@ -200,8 +221,15 @@ public: ...@@ -200,8 +221,15 @@ public:
{ {
return list_; return list_;
} }
size_t capacity(){
return maxSize;
}
}; };
typedef json(*fn_mk_default_json)();
extern string save_json(json &data, string path, bool isMerge, fn_mk_default_json mk = nullptr);
extern string load_json(json &config, string path, fn_mk_default_json mk = nullptr);
} }
#endif #endif
\ No newline at end of file
#ifndef __INTER_TYPES_H__
#define __INTER_TYPES_H__
#include <mqtt_helper.hpp>
typedef struct ev_region_t {
float minx;
float miny;
float maxx;
float maxy;
} ev_region_t;
typedef struct ev_module_config_t {
int stat_current;
ev_region_t region;
bool enabled;
MqttHelper *pClient;
union {
struct {
int interval; // in seconds
} record;
struct {
float face_thresh; //[0,1]
float human_thresh;
int image_report_interval; // max in seconds
} ai;
struct {
int level; // 1 - 6
} motion;
struct {
int fps;
int video_quality;
int bitrate_kb;
int bitrate_type;
int push;
} sys;
} module;
} ev_module_config_t;
#endif
\ No newline at end of file
差异被折叠。
...@@ -78,12 +78,12 @@ typedef struct ev_module_config_t { ...@@ -78,12 +78,12 @@ typedef struct ev_module_config_t {
union { union {
struct { struct {
int interval; // in seconds int interval; // in seconds
}record; } record;
struct { struct {
float face_thresh; //[0,1] float face_thresh; //[0,1]
float human_thresh; float human_thresh;
} ai; } ai;
struct motion{ struct motion {
int level; // 1 - 6 int level; // 1 - 6
} motion; } motion;
} module; } module;
...@@ -353,7 +353,7 @@ void record_video_entry(void *args) ...@@ -353,7 +353,7 @@ void record_video_entry(void *args)
this_thread::sleep_for(10s); this_thread::sleep_for(10s);
continue; continue;
} }
// setup sub // setup sub
void *pSub = zmq_socket(pPubCtx, ZMQ_SUB); void *pSub = zmq_socket(pPubCtx, ZMQ_SUB);
// ret = 1; // ret = 1;
...@@ -394,7 +394,7 @@ void record_video_entry(void *args) ...@@ -394,7 +394,7 @@ void record_video_entry(void *args)
delete fp; delete fp;
} }
fp = new fstream(recFilePath+to_string(nowTs), std::ios::out|std::ios::binary); fp = new fstream(recFilePath+to_string(nowTs), std::ios::out|std::ios::binary);
if(!fp->is_open()){ if(!fp->is_open()) {
spdlog::error("failed to open record file"); spdlog::error("failed to open record file");
delete fp; delete fp;
fp = nullptr; fp = nullptr;
......
...@@ -7,6 +7,8 @@ extern "C" { ...@@ -7,6 +7,8 @@ extern "C" {
#include <stdio.h> #include <stdio.h>
#include <spdlog/spdlog.h> #include <spdlog/spdlog.h>
#include <evpacket.h>
#include "motion.h"
typedef struct { typedef struct {
MaQueMdParam_s stMdParam; MaQueMdParam_s stMdParam;
...@@ -51,8 +53,13 @@ static XM_S32 cb_blind_detect(XM_VOID *pUserArg, MaQueBdResult_s *pstBdRes) ...@@ -51,8 +53,13 @@ static XM_S32 cb_blind_detect(XM_VOID *pUserArg, MaQueBdResult_s *pstBdRes)
return 0; return 0;
} }
void start_md_bd(void *args) void start_md_bd(ev_module_config_t *pArgs)
{ {
if(!pArgs->enabled) {
spdlog::warn("motion detect is disabled");
}
spdlog::info("starting motion detect module");
MdModParam_s mdParam = { 0 }; MdModParam_s mdParam = { 0 };
BdModParam_s bdParam = { 0 }; BdModParam_s bdParam = { 0 };
...@@ -62,9 +69,9 @@ void start_md_bd(void *args) ...@@ -62,9 +69,9 @@ void start_md_bd(void *args)
mdParam.stMdParam.y = 48; mdParam.stMdParam.y = 48;
mdParam.stMdParam.w = 352 - 58*2; mdParam.stMdParam.w = 352 - 58*2;
mdParam.stMdParam.h = 288 - 48*2; mdParam.stMdParam.h = 288 - 48*2;
mdParam.stMdParam.eMdAlarmlevel = 2; // [1, 6] mdParam.stMdParam.eMdAlarmlevel = pArgs->module.motion.level; // [1, 6]
bdParam.stBdParam.bEnabled = 1; bdParam.stBdParam.bEnabled = 1;
bdParam.stBdParam.eBdAlarmLevel = 2; bdParam.stBdParam.eBdAlarmLevel = pArgs->module.motion.level;
if (mdParam.stMdParam.bEnabled) { if (mdParam.stMdParam.bEnabled) {
LibXmMaQue_MD_create(0); LibXmMaQue_MD_create(0);
......
#ifndef __MOTION_H__ #ifndef __MOTION_H__
#define __MOTION_H__ #define __MOTION_H__
#pragma once
void start_md_bd(void *args); #include "internal_types.h"
void start_md_bd(ev_module_config_t *pArgs);
void stop_md_bd(); void stop_md_bd();
#endif #endif
\ No newline at end of file
#include <libxmmaque_api.h>
#include <spdlog/spdlog.h>
#include <fmt/format.h>
#include "ptz.h"
#include <mutex>
#include "evutils.hpp"
#include <string.h>
using namespace std;
using namespace evutils;
using namespace jsoncons;
mutex gMut;
map<string, int> mapDirection = {
{"left", MOTOR_MOVE_LEFT},
{"right", MOTOR_MOVE_RIGHT},
{"up", MOTOR_MOVE_UP},
{"down", MOTOR_MOVE_DOWN},
{"upright", MOTOR_MOVE_RIGHT|MOTOR_MOVE_UP},
{"upleft", MOTOR_MOVE_LEFT|MOTOR_MOVE_UP},
{"downleft", MOTOR_MOVE_LEFT|MOTOR_MOVE_DOWN},
{"downright", MOTOR_MOVE_RIGHT|MOTOR_MOVE_DOWN}
};
void ptz_waitfor_idle()
{
XM_U32 action,x,y;
usleep(100*1000);
while (1) {
if (0 == LibXmMaQue_Motor_getPostion(&action,&x,&y)) {
if (MOTOR_IDLE == action) {
break;
}
else {
usleep(300*1000);
}
}
}
}
string ptz_service_start()
{
static int first_startup = 1;
string rc;
spdlog::info("start ptz service: calibration/re-locating");
if (LibXmMaQue_Motor_create() < 0) {
rc = "ptz failed start service";
return rc;
}
rc = ptz_load();
if(!rc.empty()) {
return rc;
}
spdlog::info("ptz start service finished.");
return rc;
}
string ptz_service_stop()
{
LibXmMaQue_Motor_stop();
LibXmMaQue_Motor_destroy();
}
string ptz_get_params(ptz_param_position & param)
{
uint32_t x, y;
string rc;
if(LibXmMaQue_Motor_getMaxSteps(&x, &y)< 0) {
rc = "ptz failed to get max steps";
return rc;
}
uint32_t direction, cx, cy;
if(LibXmMaQue_Motor_getPostion(&direction, &cx, &cy) < 0) {
rc = "ptz failed to get current position";
return rc;
}
param.min_x = 0;
param.max_x = x;
param.step_x = EV_PTZ_X_DEGREE/x;
param.current_x_deg = cx * param.step_x;
param.current_x_steps = cx;
param.min_y = 0;
param.max_y = y;
param.step_y = EV_PTZ_Y_DEGREE/x;
param.current_y_deg = cy * param.step_y;
param.current_y_steps = cy;
return rc;
}
static const string extraSysConfigFile = "/etc/evsys.json";
string ptz_save()
{
ptz_param_position pos;
auto rc = ptz_get_params(pos);
if(!rc.empty()) {
return rc;
}
json js;
js["ptz"] = json();
js["ptz"]["x"] = pos.current_x_steps;
js["ptz"]["y"] = pos.current_y_steps;
rc = save_json(js, extraSysConfigFile, true, evutils::make_default_sys_extra_config);
return rc;
}
string ptz_load()
{
string rc;
json js;
rc = load_json(js, extraSysConfigFile, evutils::make_default_sys_extra_config);
if(!rc.empty()) {
return rc;
}
auto x = js["ptz"]["x"].as<uint32_t>();
auto y = js["ptz"]["y"].as<uint32_t>();
if(LibXmMaQue_Motor_setPostion(x,y)) {
rc = fmt::format("failed to set position to {}, {}", x, y);
}
ptz_waitfor_idle();
return rc;
}
string ptz_move(string dire, float degree)
{
lock_guard<mutex> lk(gMut);
string rc;
if(mapDirection.count(dire) == 0) {
rc = fmt::format("ptz move invalid direction: {}", dire);
return rc;
}
ptz_param_position curr_pos;
rc = ptz_get_params(curr_pos);
if(!rc.empty()) {
return rc;
}
if(dire == "left" || dire == "rignt") {
curr_pos.current_x_steps = (degree *1.0 / curr_pos.step_x);
}
if(dire == "up" || dire == "down") {
curr_pos.current_y_steps = (degree *1.0 / curr_pos.step_y);
}
if(LibXmMaQue_Motor_move(mapDirection["dire"], 52, 52, curr_pos.current_x_steps, curr_pos.current_y_steps)< 0) {
rc = fmt::format("ptz failed to move {} {}: current({},{}), max({},{})", dire, degree, curr_pos.current_x_deg, curr_pos.current_y_deg, 355, 0);
if(!rc.empty()) {
return rc;
}
}
ptz_waitfor_idle();
rc = ptz_save();
return rc;
}
string ptz_reset()
{
lock_guard<mutex> lk(gMut);
ptz_param_position param;
string rc;
rc = ptz_get_params(param);
if(!rc.empty()) {
return rc;
}
auto targetx = param.max_x/2;
auto targety = param.max_y/2;
if (LibXmMaQue_Motor_setZero()) {
rc = "ptz failed to relocate to (0,0)";
return rc;
}
if(LibXmMaQue_Motor_move(mapDirection["upright"], 52, 52, targetx, targety)< 0) {
rc = fmt::format("ptz failed move to center: {} {}", targetx, targety);
}
ptz_waitfor_idle();
return rc;
}
\ No newline at end of file
#ifndef __EV_PTZ_H__
#define __EV_PTZ_H__
#pragma once
#include <maque_motor.h>
#include <string.h>
/// PTZ
#define EV_PTZ_X_DEGREE 355
// N/A for xiongmai camera
#define EV_PTZ_Y_DEGREE -1
// N/A for xiongmai camera
#define EV_PTZ_Z_DEGREE -1
typedef struct ptz_param_position {
int min_x; // steps
int max_x;
int min_y;
int max_y; // steps
float step_x; // degree per step
float step_y;
int current_x_deg; // in number of steps, not degree
int current_x_steps;
int current_y_deg;
int current_y_steps; //
}ptz_param_position;
std::string ptz_service_start();
std::string ptz_service_stop();
std::string ptz_reset(ptz_param_position);
std::string ptz_move(std::string dire, float degree);
std::string ptz_get_params(ptz_param_position & param);
std::string ptz_load();
#endif
\ No newline at end of file
...@@ -17,7 +17,7 @@ int raw_connect(std::string host, std::string port, int *socket_, int recv_timeo ...@@ -17,7 +17,7 @@ int raw_connect(std::string host, std::string port, int *socket_, int recv_timeo
hints.ai_flags = AI_NUMERICSERV; // port passed as as numeric value hints.ai_flags = AI_NUMERICSERV; // port passed as as numeric value
hints.ai_protocol = 0; hints.ai_protocol = 0;
spdlog::info("raw_connect"); spdlog::info("raw connect: {}:{}", host, port);
addrinfo *addrinfo_result; addrinfo *addrinfo_result;
rv = ::getaddrinfo(host.c_str(), port.c_str(), &hints, &addrinfo_result); rv = ::getaddrinfo(host.c_str(), port.c_str(), &hints, &addrinfo_result);
...@@ -49,7 +49,7 @@ int raw_connect(std::string host, std::string port, int *socket_, int recv_timeo ...@@ -49,7 +49,7 @@ int raw_connect(std::string host, std::string port, int *socket_, int recv_timeo
spdlog::error("setsockopt SO_SNDTIMEO failed"); spdlog::error("setsockopt SO_SNDTIMEO failed");
return -1; return -1;
} }
rv = ::connect(*socket_, rp->ai_addr, rp->ai_addrlen); rv = ::connect(*socket_, rp->ai_addr, rp->ai_addrlen);
if (rv == 0) { if (rv == 0) {
auto addr = (struct sockaddr_in *)rp->ai_addr; auto addr = (struct sockaddr_in *)rp->ai_addr;
......
...@@ -9,37 +9,64 @@ extern "C" ...@@ -9,37 +9,64 @@ extern "C"
} }
#include "mqtt_helper.hpp" #include "mqtt_helper.hpp"
#include <jsoncons/json.hpp>
#include <vector>
#include <chrono>
#define DIV_UP(x, a) ( ((x) + ((a) - 1) ) / a ) using namespace std;
using namespace jsoncons;
#define DIV_UP(x, a) ( ((x) + ((a) - 1) ) / a )
#define SMART_CAP_MIN_SECS 10
long long smartTsLast = 0;
static int smartCnt = 0;
XM_S32 MaQue_JpegEnc_getFrame_callback (XM_VOID *pUserArg, MaQueSmartJpegFrame_s *pstJpegFrame) XM_S32 MaQue_JpegEnc_getFrame_callback (XM_VOID *pUserArg, MaQueSmartJpegFrame_s *pstJpegFrame)
{ {
// if(smartCnt > 0) { ev_module_config_t * mod = (ev_module_config_t *)pUserArg;
// smartCnt--; auto now = chrono::duration_cast<chrono::seconds>(chrono::system_clock::now().time_since_epoch()).count();
// return 0; // no two capture within SMART_CAP_MIN_SECS seconds
// } if(now - smartTsLast < SMART_CAP_MIN_SECS) {
// smartCnt = 1000; return 0;
// XM_CHAR acFile[256] = {0}; }
// FILE *pFile;
// static XM_S32 jpeg_cnt = 0; smartTsLast = now;
json js;
printf("aClassName[%s] idx = %d, toltal = %d\n", pstJpegFrame->aClassName, pstJpegFrame->nIndex, pstJpegFrame->nToltalJpeg); string str = fmt::format("new ai capture: {}, idx = {}, toltal = {}", pstJpegFrame->aClassName, pstJpegFrame->nIndex, pstJpegFrame->nToltalJpeg);
spdlog::info(str);
// if (jpeg_cnt < 30000) { MaQueSmartTarget_s stMaQueSmartTarget = {0};
// sprintf(acFile, "ai/snap_%d.jpg", jpeg_cnt);
// pFile = fopen(acFile, "wb"); // face
// if (pFile == NULL) { int res = LibXmMaQue_SmartGetTarget(0, &stMaQueSmartTarget);
// spdlog::error("open file err"); if(stMaQueSmartTarget.targetFDNum > 0 ) {
// return XM_FAILURE; js["face"] = json();
// } js["face"]["num"] = stMaQueSmartTarget.targetFDNum;
js["face"]["minX"] = stMaQueSmartTarget.aFDRect[0].s16X1;
// fwrite(pstJpegFrame->pBuffer, pstJpegFrame->nDataLen, 1, pFile); js["face"]["minY"] = stMaQueSmartTarget.aFDRect[0].s16Y1;
// fflush(pFile); js["face"]["maxX"] = stMaQueSmartTarget.aFDRect[0].s16X2;
js["face"]["maxY"] = stMaQueSmartTarget.aFDRect[0].s16Y2;
// fclose(pFile); }
// jpeg_cnt++;
// } // pepole
if(stMaQueSmartTarget.targetPDNum > 0 ) {
js["pepole"] = json();
js["pepole"]["num"] = stMaQueSmartTarget.targetPDNum;
js["pepole"]["minX"] = stMaQueSmartTarget.aPDRect[0].s16X1;
js["pepole"]["minY"] = stMaQueSmartTarget.aPDRect[0].s16Y1;
js["pepole"]["maxX"] = stMaQueSmartTarget.aPDRect[0].s16X2;
js["pepole"]["maxY"] = stMaQueSmartTarget.aPDRect[0].s16Y2;
}
if(mod != nullptr && mod->pClient != nullptr) {
string b64;
vector<uint8_t> vec(pstJpegFrame->pBuffer, pstJpegFrame->pBuffer + pstJpegFrame->nDataLen -1);
jsoncons::encode_base64<vector<uint8_t>::iterator, string>(vec.begin(), vec.end(), b64);
js["data"] = b64;
js[consts::kMsgType] = consts::kMsgTypeImage;
js[consts::kMsgEncode] = consts::kMsgEncodeBase64;
js[consts::kMsgFormat] = consts::kMsgFormatJpeg;
MqttMgr::report_response_args(client, consts::pub_topic_response + client->id, 0, str, "ai_image", "", js);
}
return XM_SUCCESS; return XM_SUCCESS;
} }
...@@ -98,8 +125,13 @@ XM_S32 MaQue_Draw_OsdAreaRect(MaQueStreamChannel_e eStreamChn, XM_S32 enable, XM ...@@ -98,8 +125,13 @@ XM_S32 MaQue_Draw_OsdAreaRect(MaQueStreamChannel_e eStreamChn, XM_S32 enable, XM
return XM_SUCCESS; return XM_SUCCESS;
} }
void maq_smart_task_entry(void *pArg) void maq_smart_task_entry(ev_module_config_t *pArg)
{ {
if(!pArg->enabled) {
spdlog::warn("ai detection is disabled");
return;
}
spdlog::info("starting ai detection task");
XM_S32 res; XM_S32 res;
MaQueStreamChannel_e eStreamChn; MaQueStreamChannel_e eStreamChn;
MaQueSmartParams_s stMaQueSmartParams; MaQueSmartParams_s stMaQueSmartParams;
...@@ -228,13 +260,13 @@ void maq_smart_task_entry(void *pArg) ...@@ -228,13 +260,13 @@ void maq_smart_task_entry(void *pArg)
return; return;
} }
res = LibXmMaQue_SmartPDThreshold(0, pdThreshold); res = LibXmMaQue_SmartPDThreshold(0, pArg->module.ai.human_thresh);
if (XM_SUCCESS != res) { if (XM_SUCCESS != res) {
spdlog::error("LibXmMaQue_SmartPDThreshold() Failed!"); spdlog::error("LibXmMaQue_SmartPDThreshold() Failed!");
return; return;
} }
res = LibXmMaQue_SmartFDThreshold(0, fdThreshold); res = LibXmMaQue_SmartFDThreshold(0, pArg->module.ai.face_thresh);
if (XM_SUCCESS != res) { if (XM_SUCCESS != res) {
spdlog::error("LibXmMaQue_SmartFDThreshold() Failed!"); spdlog::error("LibXmMaQue_SmartFDThreshold() Failed!");
return; return;
...@@ -242,11 +274,14 @@ void maq_smart_task_entry(void *pArg) ...@@ -242,11 +274,14 @@ void maq_smart_task_entry(void *pArg)
stCallback.eType = MAQUE_SMART_JPEG_ENCODE_LARGE;//MAQUE_SMART_JPEG_ENCODE_CUTOUT; stCallback.eType = MAQUE_SMART_JPEG_ENCODE_LARGE;//MAQUE_SMART_JPEG_ENCODE_CUTOUT;
stCallback.eClass = MAQUE_SMART_JPEG_CLASS_NONE;//MAQUE_SMART_JPEG_CLASS_FD; stCallback.eClass = MAQUE_SMART_JPEG_CLASS_NONE;//MAQUE_SMART_JPEG_CLASS_FD;
stCallback.stCallback.pCallbackArg = NULL; stCallback.stCallback.pCallbackArg = pArg;
stCallback.stCallback.pCallbackFuncPtr = MaQue_JpegEnc_getFrame_callback; stCallback.stCallback.pCallbackFuncPtr = MaQue_JpegEnc_getFrame_callback;
LibXmMaQue_SmartRegisterCallback(0, &stCallback); LibXmMaQue_SmartRegisterCallback(0, &stCallback);
while (1) { while (1) {
this_thread::sleep_for(3s);
continue;
res = LibXmMaQue_SmartGetTarget(0, &stMaQueSmartTarget); res = LibXmMaQue_SmartGetTarget(0, &stMaQueSmartTarget);
if (XM_SUCCESS != res) { if (XM_SUCCESS != res) {
spdlog::error("LibXmMaQue_SmartGetTarget() Failed!"); spdlog::error("LibXmMaQue_SmartGetTarget() Failed!");
...@@ -272,7 +307,6 @@ void maq_smart_task_entry(void *pArg) ...@@ -272,7 +307,6 @@ void maq_smart_task_entry(void *pArg)
if (stMaQueSmartTarget.targetFDNum > 0) { if (stMaQueSmartTarget.targetFDNum > 0) {
printf("\n\nFace Detection : TotalNum %d\n", stMaQueSmartTarget.targetFDNum); printf("\n\nFace Detection : TotalNum %d\n", stMaQueSmartTarget.targetFDNum);
for (i = 0; i < stMaQueSmartTarget.targetFDNum; i++) { for (i = 0; i < stMaQueSmartTarget.targetFDNum; i++) {
printf("(%d, %d), (%d, %d)\n", stMaQueSmartTarget.aFDRect[i].s16X1, stMaQueSmartTarget.aFDRect[i].s16Y1, printf("(%d, %d), (%d, %d)\n", stMaQueSmartTarget.aFDRect[i].s16X1, stMaQueSmartTarget.aFDRect[i].s16Y1,
stMaQueSmartTarget.aFDRect[i].s16X2, stMaQueSmartTarget.aFDRect[i].s16Y2); stMaQueSmartTarget.aFDRect[i].s16X2, stMaQueSmartTarget.aFDRect[i].s16Y2);
......
...@@ -2,7 +2,8 @@ ...@@ -2,7 +2,8 @@
#define __EV_SMART_HPP__ #define __EV_SMART_HPP__
#pragma once #pragma once
#include "internal_types.h"
void maq_smart_task_entry(void *pArg); void maq_smart_task_entry(ev_module_config_t *pArg);
#endif #endif
\ No newline at end of file
...@@ -61,4 +61,6 @@ static inline unsigned short crc16(const unsigned char* data_p, unsigned char le ...@@ -61,4 +61,6 @@ static inline unsigned short crc16(const unsigned char* data_p, unsigned char le
return crc; return crc;
} }
#endif #endif
\ No newline at end of file
...@@ -28,6 +28,8 @@ using namespace std; ...@@ -28,6 +28,8 @@ using namespace std;
using namespace jsoncons; using namespace jsoncons;
using namespace evutils; using namespace evutils;
#define EV_MAX_PRINTABLE_SIZE 512
extern void on_connected(void* context, MQTTAsync_successData* response); extern void on_connected(void* context, MQTTAsync_successData* response);
extern void on_connlost(void *context, char *cause); extern void on_connlost(void *context, char *cause);
extern int on_msgarrvd(void *context, char *topic, int topicLen, MQTTAsync_message *message); extern int on_msgarrvd(void *context, char *topic, int topicLen, MQTTAsync_message *message);
...@@ -142,7 +144,7 @@ public: ...@@ -142,7 +144,7 @@ public:
spdlog::debug("mqtt url: proto: {}, host: {}, port: {}, user: {}, pass: {}", uri.Protocol, uri.Host, uri.Port, uri.User, uri.Password); spdlog::debug("mqtt url: proto: {}, host: {}, port: {}, user: {}, pass: {}", uri.Protocol, uri.Host, uri.Port, uri.User, uri.Password);
if(MQTTASYNC_SUCCESS != MQTTAsync_create(&client, addr.c_str(), (string("EVC")+id).c_str(), MQTTCLIENT_PERSISTENCE_NONE, NULL)) { if(MQTTASYNC_SUCCESS != MQTTAsync_create(&client, addr.c_str(), ("EVC"+id).c_str(), MQTTCLIENT_PERSISTENCE_NONE, NULL)) {
msg = "failed to async create mqtt"; msg = "failed to async create mqtt";
spdlog::error(msg); spdlog::error(msg);
throw StrException(msg); throw StrException(msg);
...@@ -303,7 +305,7 @@ class MqttMgr { ...@@ -303,7 +305,7 @@ class MqttMgr {
lock_guard<mutex> lg(MqttMgr::mut); lock_guard<mutex> lg(MqttMgr::mut);
try{ try{
if(MqttMgr::insts.count(key) == 0){ if(MqttMgr::insts.count(key) == 0){
auto inst = new MqttHelper(mqtt_url, "evc." + devsn); auto inst = new MqttHelper(mqtt_url, devsn);
MqttMgr::insts[key] = inst; MqttMgr::insts[key] = inst;
}else{ }else{
// //
...@@ -345,6 +347,10 @@ class MqttMgr { ...@@ -345,6 +347,10 @@ class MqttMgr {
return; return;
} }
auto rc = (*client)[topic].pub(message.c_str(), message.size(), 2, false); auto rc = (*client)[topic].pub(message.c_str(), message.size(), 2, false);
if(message.size() > EV_MAX_PRINTABLE_SIZE){
string ellipsis = " <...> ";
message = message.substr(0, EV_MAX_PRINTABLE_SIZE/2 - ellipsis.size()) + ellipsis + message.substr(EV_MAX_PRINTABLE_SIZE/2, EV_MAX_PRINTABLE_SIZE/2);
}
if(rc < 0) { if(rc < 0) {
spdlog::error("failed to pub mqtt message on {}: {}", topic, message); spdlog::error("failed to pub mqtt message on {}: {}", topic, message);
} }
...@@ -398,6 +404,9 @@ class MqttMgr { ...@@ -398,6 +404,9 @@ class MqttMgr {
js.insert_or_assign(consts::kMsgCode, code); js.insert_or_assign(consts::kMsgCode, code);
js.insert_or_assign(consts::kMsgMsg, message); js.insert_or_assign(consts::kMsgMsg, message);
js.insert_or_assign(consts::kMsgSn, client->id); js.insert_or_assign(consts::kMsgSn, client->id);
if(!data.empty()){
js.insert_or_assign(consts::kMsgData, data);
}
_report_response(client, topic, js.to_string()); _report_response(client, topic, js.to_string());
} }
...@@ -422,6 +431,9 @@ class MqttMgr { ...@@ -422,6 +431,9 @@ class MqttMgr {
js.insert_or_assign(consts::kMsgCode, code); js.insert_or_assign(consts::kMsgCode, code);
js.insert_or_assign(consts::kMsgMsg, message); js.insert_or_assign(consts::kMsgMsg, message);
js.insert_or_assign(consts::kMsgSn, client->id); js.insert_or_assign(consts::kMsgSn, client->id);
if(!data.empty()){
js.insert_or_assign(consts::kMsgData, data);
}
_report_response(client, topic, js.to_string()); _report_response(client, topic, js.to_string());
} }
......
...@@ -138,12 +138,13 @@ int write_packet(packet_processor_t *processor, char *data, int len) ...@@ -138,12 +138,13 @@ int write_packet(packet_processor_t *processor, char *data, int len)
pkt.size = len; pkt.size = len;
AVRational time_base; AVRational time_base;
char *fps = getenv("FPS"); char *fps = getenv("FPS");
if(processor->hdr.vpara.fps > 0 && processor->hdr.vpara.fps < 100){ if(processor->hdr.vpara.fps > 0 && processor->hdr.vpara.fps < 100) {
time_base.den = processor->hdr.vpara.fps; time_base.den = processor->hdr.vpara.fps;
}else{ }
else {
time_base.den = 15; time_base.den = 15;
} }
if(fps){ if(fps) {
time_base.den = atoi(fps); time_base.den = atoi(fps);
} }
time_base.num = 1; time_base.num = 1;
...@@ -162,7 +163,8 @@ int write_packet(packet_processor_t *processor, char *data, int len) ...@@ -162,7 +163,8 @@ int write_packet(packet_processor_t *processor, char *data, int len)
} }
int setupRouter(void **ctx, void **s, string addr, int rcvQS=0){ int setupRouter(void **ctx, void **s, string addr, int rcvQS=0)
{
int ret = 0; int ret = 0;
*ctx = zmq_ctx_new(); *ctx = zmq_ctx_new();
*s = zmq_socket(*ctx, ZMQ_ROUTER); *s = zmq_socket(*ctx, ZMQ_ROUTER);
...@@ -183,7 +185,8 @@ int setupRouter(void **ctx, void **s, string addr, int rcvQS=0){ ...@@ -183,7 +185,8 @@ int setupRouter(void **ctx, void **s, string addr, int rcvQS=0){
return ret; return ret;
} }
int z_recv_multiple(void *s, vector<uint8_t> &buf, vector<int>&frameIdx) { int z_recv_multiple(void *s, vector<uint8_t> &buf, vector<int>&frameIdx)
{
int64_t more = 1; int64_t more = 1;
size_t more_size = sizeof(more); size_t more_size = sizeof(more);
int ret = 0; int ret = 0;
...@@ -222,20 +225,21 @@ int z_recv_multiple(void *s, vector<uint8_t> &buf, vector<int>&frameIdx) { ...@@ -222,20 +225,21 @@ int z_recv_multiple(void *s, vector<uint8_t> &buf, vector<int>&frameIdx) {
packet_processor_t globalProcess = {0}; packet_processor_t globalProcess = {0};
void dispatch(string sn, zmq_msg_t &msg){ void dispatch(string sn, zmq_msg_t &msg)
{
evpacket_t *pkt = (evpacket_t *)zmq_msg_data(&msg); evpacket_t *pkt = (evpacket_t *)zmq_msg_data(&msg);
globalProcess.packetId++; globalProcess.packetId++;
//debugHex((char*)zmq_msg_data(&msg), 64); //debugHex((char*)zmq_msg_data(&msg), 64);
auto crc = pkt->meta.crc; auto crc = pkt->meta.crc;
pkt->meta.crc = 0; pkt->meta.crc = 0;
auto crc_ = crc16((unsigned char*)pkt, sizeof(evpacket_t)); auto crc_ = crc16((unsigned char*)pkt, sizeof(evpacket_t));
if(crc != crc_){ if(crc != crc_) {
spdlog::error("invalid crc: {}", pkt->meta.packet_id); spdlog::error("invalid crc: {}", pkt->meta.packet_id);
return; return;
} }
if(globalProcess.pAvCtx == nullptr && globalProcess.packetId %15*10 == 0){ if(globalProcess.pAvCtx == nullptr && globalProcess.packetId %15*10 == 0) {
int rc = 0; int rc = 0;
globalProcess.pAvCtx = rtsp_init(darwinUrl + sn, 0, 1080, 1920, &rc); globalProcess.pAvCtx = rtsp_init(darwinUrl + sn, 0, 1080, 1920, &rc);
if(globalProcess.pAvCtx == nullptr || rc < 0) { if(globalProcess.pAvCtx == nullptr || rc < 0) {
...@@ -247,7 +251,7 @@ void dispatch(string sn, zmq_msg_t &msg){ ...@@ -247,7 +251,7 @@ void dispatch(string sn, zmq_msg_t &msg){
int ret = write_packet(&globalProcess, (char*)zmq_msg_data(&msg) + sizeof(evpacket_t), zmq_msg_size(&msg) - sizeof(evpacket_t) ); int ret = write_packet(&globalProcess, (char*)zmq_msg_data(&msg) + sizeof(evpacket_t), zmq_msg_size(&msg) - sizeof(evpacket_t) );
if(ret < 0) { if(ret < 0) {
spdlog::error("failed to send packet!"); spdlog::error("failed to send packet!");
if(globalProcess.pAvCtx && globalProcess.pAvCtx->pb) { if(globalProcess.pAvCtx && globalProcess.pAvCtx->pb) {
avio_closep(&globalProcess.pAvCtx->pb); avio_closep(&globalProcess.pAvCtx->pb);
} }
if(globalProcess.pAvCtx) { if(globalProcess.pAvCtx) {
...@@ -278,11 +282,11 @@ int main() ...@@ -278,11 +282,11 @@ int main()
void *pRouterCtx = nullptr, *pRouter = nullptr/*, *pDealerCtx = nullptr, *pDealer = nullptr*/; void *pRouterCtx = nullptr, *pRouter = nullptr/*, *pDealerCtx = nullptr, *pDealer = nullptr*/;
setupRouter(&pRouterCtx, &pRouter, addr, 10); setupRouter(&pRouterCtx, &pRouter, addr, 10);
while(1){ while(1) {
int64_t more = 1; int64_t more = 1;
size_t more_size = sizeof(more); size_t more_size = sizeof(more);
int ret = 0; int ret = 0;
zmq_msg_t msg; zmq_msg_t msg;
ret = zmq_msg_init(&msg); ret = zmq_msg_init(&msg);
if(ret < 0) { if(ret < 0) {
spdlog::debug("failed to receive multiple msg on zmq_msg_init: {}", zmq_strerror(zmq_errno())); spdlog::debug("failed to receive multiple msg on zmq_msg_init: {}", zmq_strerror(zmq_errno()));
...@@ -309,11 +313,12 @@ int main() ...@@ -309,11 +313,12 @@ int main()
break; break;
} }
dispatch(sn, msg); dispatch(sn, msg);
}else{ }
else {
spdlog::error("invalid packet fmt"); spdlog::error("invalid packet fmt");
} }
zmq_msg_close(&msg); zmq_msg_close(&msg);
if(ret < 0) { if(ret < 0) {
spdlog::error("failed to recv msg: {}", ret < 0? zmq_strerror(ret): "invalid frames"); spdlog::error("failed to recv msg: {}", ret < 0? zmq_strerror(ret): "invalid frames");
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论