Skip to content
项目
群组
代码片段
帮助
正在加载...
登录
切换导航
E
evcamera
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
OpsTeam
evcamera
Commits
2c0181b7
提交
2c0181b7
authored
5月 14, 2020
作者:
blu
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
recording
上级
298fb4fe
隐藏空白字符变更
内嵌
并排
正在显示
12 个修改的文件
包含
849 行增加
和
1176 行删除
+849
-1176
MQTT.md
docs/MQTT.md
+28
-10
CMakeLists.txt
hi3518/CMakeLists.txt
+3
-5
main.cc
hi3518/main.cc
+370
-291
main.cc.bak2
hi3518/main.cc.bak2
+0
-373
ntp.cc
hi3518/ntp.cc
+1
-1
raw_tcp.cc
hi3518/raw_tcp.cc
+17
-15
ref-memory.hpp
hi3518/ref-memory.hpp
+3
-4
smart.cc
hi3518/smart.cc
+20
-20
utils.hpp
hi3518/utils.hpp
+255
-19
CMakeLists.txt
server/CMakeLists.txt
+6
-6
videogateway.cc
server/videogateway.cc
+145
-431
libzmq
vendor/libzmq
+1
-1
没有找到文件。
docs/MQTT.md
浏览文件 @
2c0181b7
...
@@ -46,7 +46,7 @@ payload: JSON
...
@@ -46,7 +46,7 @@ payload: JSON
```
```
topic: evcamera/v1.0/res_rep
topic: evcamera/v1.0/res_rep
qos:2
qos:2
retian:
tru
e
retian:
fals
e
payload: JSON
payload: JSON
```
```
...
@@ -90,7 +90,12 @@ payload:
...
@@ -90,7 +90,12 @@ payload:
"features"
:
{
"features"
:
{
"motion"
:
{
"motion"
:
{
"enable"
:
1
,
"enable"
:
1
,
"region"
:
{
"min"
:
[
0.5
,
0.5
],
"max"
:
[
0.75
,
0.75
]},
"region"
:
{
"minX"
:
0.1
,
"minY"
:
0.1
,
"maxX"
:
0.9
,
"maxY"
:
0.9
},
"level"
:
3
"level"
:
3
},
},
"record"
:{
"record"
:{
...
@@ -119,11 +124,13 @@ payload:
...
@@ -119,11 +124,13 @@ payload:
"rid"
:
"<random_str>"
,
"rid"
:
"<random_str>"
,
"sn"
:
"A000000Z"
,
"sn"
:
"A000000Z"
,
"data"
:
{
"data"
:
{
{
[
"op"
:
"replace"
,
{
"path"
:
"/features/ai/face_thresh"
,
"op"
:
"replace"
,
"value"
:
0.5
"path"
:
"/features/ai/face_thresh"
,
}
"value"
:
0.5
}
]
}
}
```
```
...
@@ -147,8 +154,13 @@ payload:
...
@@ -147,8 +154,13 @@ payload:
"features"
:
{
"features"
:
{
"motion"
:
{
"motion"
:
{
"enable"
:
1
,
"enable"
:
1
,
"region"
:
{
"min"
:
[
0.5
,
0.5
],
"max"
:
[
0.75
,
0.75
]},
"level"
:
3
,
//
1
-
6
"level"
:
3
//
1
-
6
"region"
:{
"minX"
:
0.1
,
"minY"
:
0.1
,
"maxX"
:
0.9
,
"maxY"
:
0.9
}
},
},
"record"
:{
"record"
:{
"enable"
:
1
,
"enable"
:
1
,
...
@@ -158,7 +170,13 @@ payload:
...
@@ -158,7 +170,13 @@ payload:
"ai"
:{
"ai"
:{
"enable"
:
1
,
"enable"
:
1
,
"face_thresh"
:
0.75
,
//
0
-
1
"face_thresh"
:
0.75
,
//
0
-
1
"human_thresh"
:
0.63
//
0
-
1
"human_thresh"
:
0.63
,
//
0
-
1
"region"
:{
"minX"
:
0.1
,
"minY"
:
0.1
,
"maxX"
:
0.9
,
"maxY"
:
0.9
}
}
}
}
}
}
}
...
...
hi3518/CMakeLists.txt
浏览文件 @
2c0181b7
...
@@ -8,12 +8,12 @@ if("${VENDOR}" STREQUAL "")
...
@@ -8,12 +8,12 @@ if("${VENDOR}" STREQUAL "")
set
(
SHAREDINCS
"
${
CMAKE_SOURCE_DIR
}
/../include"
)
set
(
SHAREDINCS
"
${
CMAKE_SOURCE_DIR
}
/../include"
)
endif
()
endif
()
#set_source_files_properties(main.cc PROPERTIES COMPILE_FLAGS -g)
#set_source_files_properties(main.cc PROPERTIES COMPILE_FLAGS -g)
set
(
COMM_INC_DIR
${
VENDOR
}
/shared/include
${
VENDOR
}
/hi3518/include
${
SHAREDINCS
}
)
set
(
COMM_INC_DIR
${
VENDOR
}
/shared/include
${
VENDOR
}
/hi3518/include
${
SHAREDINCS
}
)
set
(
COMMON_LIB_DIR
${
VENDOR
}
/shared/lib
${
VENDOR
}
/hi3518/lib
)
set
(
COMMON_LIB_DIR
${
VENDOR
}
/shared/lib
${
VENDOR
}
/hi3518/lib
)
list
(
APPEND COMMON_LIBS fmt m dl pthread XmMaQue securec XmSns_50H20AI uv
)
list
(
APPEND COMMON_LIBS fmt m dl pthread
)
list
(
APPEND XM_LIBS XmMaQue securec XmSns_50H20AI
)
include_directories
(
${
CMAKE_SOURCE_DIR
}
${
PROJECT_SOURCE_DIR
}
${
COMM_INC_DIR
}
)
include_directories
(
${
CMAKE_SOURCE_DIR
}
${
PROJECT_SOURCE_DIR
}
${
COMM_INC_DIR
}
)
link_directories
(
${
COMMON_LIB_DIR
}
/root/xiongmai/arm-himix100-linux/target/lib/
)
link_directories
(
${
COMMON_LIB_DIR
}
/root/xiongmai/arm-himix100-linux/target/lib/
)
...
@@ -27,10 +27,8 @@ add_library(motion STATIC motion.cc)
...
@@ -27,10 +27,8 @@ add_library(motion STATIC motion.cc)
add_executable
(
test_mqtt test_mqtt.cc
)
add_executable
(
test_mqtt test_mqtt.cc
)
target_link_libraries
(
test_mqtt PUBLIC paho-mqtt3a fmt m dl pthread
)
target_link_libraries
(
test_mqtt PUBLIC paho-mqtt3a fmt m dl pthread
)
add_executable
(
test_jsoncons test_jsoncons.cc
)
add_executable
(
evcamera main.cc
)
add_executable
(
evcamera main.cc
)
target_link_libraries
(
evcamera PUBLIC ntp paho-mqtt3a tcp_client smart motion
${
COMMON
_LIBS
}
)
target_link_libraries
(
evcamera PUBLIC ntp paho-mqtt3a tcp_client smart motion
zmq
${
COMMON_LIBS
}
${
XM
_LIBS
}
)
add_executable
(
ntp_client ntp_main.cc
)
add_executable
(
ntp_client ntp_main.cc
)
target_link_libraries
(
ntp_client PUBLIC ntp
)
target_link_libraries
(
ntp_client PUBLIC ntp
)
hi3518/main.cc
浏览文件 @
2c0181b7
#include <iostream>
#include <iostream>
#include <string>
#include <string>
#include <chrono>
#include <chrono>
#include <sys/stat.h>
#include <fmt/format.h>
#include <fmt/format.h>
#include <spdlog/spdlog.h>
#include <spdlog/spdlog.h>
#include "ref-memory.hpp"
#include "ref-memory.hpp"
...
@@ -17,10 +18,13 @@
...
@@ -17,10 +18,13 @@
#include <thread>
#include <thread>
#include "mqttmgr.hpp"
#include "mqttmgr.hpp"
#include "utils.hpp"
#include "utils.hpp"
#include <ghc/filesystem.hpp>
using
namespace
std
;
using
namespace
std
;
using
namespace
jsoncons
;
using
namespace
jsoncons
;
using
namespace
evutils
;
using
namespace
evutils
;
using
namespace
chrono_literals
;
namespace
fs
=
ghc
::
filesystem
;
///
///
#define NUM_IFRAME_PICK 2
#define NUM_IFRAME_PICK 2
...
@@ -29,13 +33,13 @@ using namespace evutils;
...
@@ -29,13 +33,13 @@ using namespace evutils;
#define INTERVAL_LOG_QFULL 3 // its about 60/15 *3 secs
#define INTERVAL_LOG_QFULL 3 // its about 60/15 *3 secs
/// device info
/// device info
static
char
dev_sn
[
13
]
=
{
0
};
static
char
dev_sn
[
TERMINAL_SN_SIZE
]
=
{
0
};
/// default video gateway info
/// default video gateway info
static
int
videoQuality
=
MAQUE_IMG_QUALITY_BETTER
;
static
int
videoQuality
=
MAQUE_IMG_QUALITY_BETTER
;
static
uint
32
_t
frameCntTotal
=
0
;
static
uint
64
_t
frameCntTotal
=
0
;
static
uint32_t
frameCntIframe
=
0
;
static
uint32_t
frameCntIframe
=
0
;
static
uint32_t
frameCntPframe
=
0
;
static
uint32_t
frameCntPframe
=
0
;
static
uint64_t
packetId
=
0
;
static
uint64_t
packetId
=
0
;
...
@@ -53,9 +57,58 @@ static mutex _mutFrame;
...
@@ -53,9 +57,58 @@ static mutex _mutFrame;
static
condition_variable
_condFrame
;
static
condition_variable
_condFrame
;
static
Notifier
_notiFrame
=
{
&
_mutFrame
,
&
_condFrame
};
static
Notifier
_notiFrame
=
{
&
_mutFrame
,
&
_condFrame
};
static
CallBackArg
args
=
{
nullptr
,
&
_notiFrame
,
&
_frameQueue
};
static
CallBackArg
args
=
{
nullptr
,
&
_notiFrame
,
&
_frameQueue
};
static
int
raw_socket_
=
0
;
static
bool
bGotTime
=
false
;
static
bool
bGotTime
=
false
;
// zmq
static
void
*
pPubCtx
=
nullptr
;
static
void
*
pPub
=
nullptr
;
static
const
string
strPubUrl
=
"inproc://frame"
;
static
void
*
pSub
=
nullptr
;
static
void
*
pDealerCtx
=
nullptr
;
static
void
*
pDealer
=
nullptr
;
static
string
vgwUrl
=
"tcp://192.168.55.104:7123"
;
//
static
string
configFilePath
=
"/etc/evcamera.json"
;
static
json
gJsonConfig
;
//
static
OrderedList
<
long
long
>
*
gRecFilesList
=
nullptr
;
//
static
string
strMaQuePath
=
"/mnt/sd/Config/"
;
static
string
strSDCardReservedPaths
[]
=
{
recFilePath
,
strMaQuePath
};
/// flags used to stop modules
/// 0: stopped, 1: requested to stop, 2: runningstatic int
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
;
union
{
struct
{
int
interval
;
// in seconds
}
record
;
struct
{
float
face_thresh
;
//[0,1]
float
human_thresh
;
}
ai
;
struct
motion
{
int
level
;
// 1 - 6
}
motion
;
}
module
;
}
ev_module_config_t
;
static
ev_module_config_t
gConfigRecord
=
{
0
};
static
ev_module_config_t
gConfigAI
=
{
0
};
static
ev_module_config_t
gConfigMotion
=
{
0
};
enum
EV_MSG_ERROR_CODE
{
enum
EV_MSG_ERROR_CODE
{
EV_MSG_ERROR_NONE
,
EV_MSG_ERROR_NONE
,
EV_MSG_ERROR_EXCEPTION
,
EV_MSG_ERROR_EXCEPTION
,
...
@@ -66,14 +119,18 @@ enum EV_MSG_ERROR_CODE {
...
@@ -66,14 +119,18 @@ enum EV_MSG_ERROR_CODE {
void
clean_up
(
int
sig
)
void
clean_up
(
int
sig
)
{
{
if
(
sig
==
SIGPIPE
)
{
// vgw connection error
bConnected
=
false
;
bNeedRetry
=
true
;
return
;
}
spdlog
::
warn
(
"clearn up called, with sig: {}"
,
sig
);
spdlog
::
warn
(
"clearn up called, with sig: {}"
,
sig
);
if
(
args
.
recFD
)
{
if
(
args
.
recFD
)
{
fclose
(
args
.
recFD
);
fclose
(
args
.
recFD
);
}
}
if
(
raw_socket_
)
{
::
close
(
raw_socket_
);
}
// while (args.dataq->size() > 0) {
// while (args.dataq->size() > 0) {
// DataItem elem = args.dataq->front();
// DataItem elem = args.dataq->front();
...
@@ -162,6 +219,13 @@ int32_t configure_stream(MaQueStreamChannel_e eStreamChn, MaQueVideoEncodeCfg_s
...
@@ -162,6 +219,13 @@ int32_t configure_stream(MaQueStreamChannel_e eStreamChn, MaQueVideoEncodeCfg_s
return
res
;
return
res
;
}
}
//
void
frame_free
(
void
*
data
,
void
*
hint
)
{
MaQueVideoEncFrameInfo_s
*
frame
=
(
MaQueVideoEncFrameInfo_s
*
)
hint
;
MaQue_Demo_Mem_release
(
frame
->
handleMem
);
}
//
//
XM_S32
cb_frame_proc
(
XM_VOID
*
pUserArg
,
MaQueVideoEncFrameInfo_s
*
frame
)
XM_S32
cb_frame_proc
(
XM_VOID
*
pUserArg
,
MaQueVideoEncFrameInfo_s
*
frame
)
{
{
...
@@ -169,219 +233,237 @@ XM_S32 cb_frame_proc(XM_VOID *pUserArg, MaQueVideoEncFrameInfo_s *frame)
...
@@ -169,219 +233,237 @@ XM_S32 cb_frame_proc(XM_VOID *pUserArg, MaQueVideoEncFrameInfo_s *frame)
CallBackArg
*
args
=
(
CallBackArg
*
)
pUserArg
;
CallBackArg
*
args
=
(
CallBackArg
*
)
pUserArg
;
struct
timeval
stTimeVal
;
struct
timeval
stTimeVal
;
int
ret
;
int
ret
;
frameCntTotal
++
;
frameCntTotal
++
;
if
(
logLevel
<=
spdlog
::
level
::
debug
)
{
zmq_msg_t
msg
;
printf
(
"
\n\n
new frame: %u, p0 h:%08X
\n
"
,
frameCntTotal
,
(
int
)
frame
->
handleMem
);
void
*
hint
=
NULL
;
if
(
frame
->
eEncodeType
==
MAQUE_ENCODE_TYPE_H264
&&
frame
->
eFrameType
==
MAQUE_FRAME_TYPE_VIDEO
&&
frame
->
nDataLen
>
0
)
{
evpacket_t
*
pkt
=
(
evpacket_t
*
)((
char
*
)
frame
->
pData
-
sizeof
(
evpacket_t
));
pkt
->
meta
.
magic
[
0
]
=
0xBE
;
pkt
->
meta
.
magic
[
1
]
=
0xEF
;
memcpy
(
pkt
->
meta
.
sn
,
dev_sn
,
sizeof
(
dev_sn
));
/// NOTES: since both ends use little-endian, we don't use htonl, htons to save clocks
pkt
->
vpara
.
frame_type
=
frame
->
eSubType
+
1
;
pkt
->
vpara
.
packet_type
=
frame
->
eEncodeType
;
pkt
->
vpara
.
res
.
width
=
frame
->
nWidth
;
pkt
->
vpara
.
res
.
height
=
frame
->
nHeight
;
/// TODO:
pkt
->
vpara
.
fps
=
15
;
//pkt->vpara.ts = frame->stTimeStamp;
pkt
->
length
=
frame
->
nDataLen
;
pkt
->
meta
.
packet_id
=
packetId
;
pkt
->
meta
.
crc
=
0
;
pkt
->
meta
.
crc
=
crc16
((
unsigned
char
*
)
pkt
,
sizeof
(
evpacket_t
));
if
(
frame
->
eSubType
==
MAQUE_FRAME_SUBTYPE_I
)
{
frameCntIframe
++
;
}
else
if
(
frame
->
eSubType
==
MAQUE_FRAME_SUBTYPE_P
)
{
frameCntPframe
++
;
}
zmq_msg_init_data
(
&
msg
,
(
char
*
)
pkt
,
frame
->
nDataLen
+
sizeof
(
evpacket_t
),
nullptr
,
nullptr
);
zmq_msg_send
(
&
msg
,
pPub
,
0
);
packetId
++
;
}
}
if
(
bCanRecord
)
{
MaQue_Demo_Mem_release
(
frame
->
handleMem
);
auto
nWrite
=
fwrite
(
frame
->
pData
,
1
,
frame
->
nDataLen
,
args
->
recFD
);
if
(
frame
->
nDataLen
!=
nWrite
)
{
return
XM_SUCCESS
;
spdlog
::
error
(
"failed to write file"
);
}
if
(
args
->
recFD
)
{
fclose
(
args
->
recFD
);
void
frame_send_entry
(
void
*
args
)
}
{
int
ret
=
0
;
int
flagFail
=
3
;
// 1 - sub, 2 - dealer , 3 - both
// should never exit
while
(
1
){
/// TODO: check enable status
this_thread
::
sleep_for
(
4
s
);
if
(
false
){
continue
;
}
}
}
if
(
enablePush
&&
bConnected
==
false
&&
frameCntTotal
%
(
NUM_MAX_QUEQUE_SIZE
*
3
)
==
0
)
{
// setup dealer
bNeedRetry
=
true
;
if
(
flagFail
&
2
){
bConnected
=
false
;
ret
=
setupDealer
(
&
pDealerCtx
,
&
pDealer
,
string
(
dev_sn
),
vgwUrl
,
10
);
if
(
raw_socket_
)
{
if
(
ret
<
0
)
{
::
close
(
raw_socket_
);
spdlog
::
error
(
"failed to connect cloud vgw: {}"
,
vgwUrl
);
raw_socket_
=
0
;
continue
;
}
spdlog
::
info
(
"success connect to vgw"
);
}
}
}
//printf("\n==== prepare frame with enablePush:%d, dataQ: %08hhX, frametype: %d\n", enablePush, (int)args->dataq, frame->eEncodeType);
// setup sub
if
(
enablePush
&&
args
->
dataq
&&
frame
->
eEncodeType
==
MAQUE_ENCODE_TYPE_H264
)
{
if
(
flagFail
&
1
){
unique_lock
<
mutex
>
lock
(
*
args
->
noti
->
mut
);
pSub
=
zmq_socket
(
pPubCtx
,
ZMQ_SUB
);
// check delayed packets for about 12s. sufficiently high
if
(
pSub
==
nullptr
)
{
if
(
args
->
dataq
->
size
()
>=
NUM_MAX_QUEQUE_SIZE
)
{
spdlog
::
error
(
"failed to create frame sending socket"
);
spdlog
::
warn
(
"dataq full"
);
continue
;
volatile
MaQueVideoEncFrameInfo_s
*
p1
=
(
MaQueVideoEncFrameInfo_s
*
)
args
->
dataq
->
front
().
ud
;
if
(
logLevel
==
spdlog
::
level
::
debug
)
{
printf
(
"%u, p1 h:%08X
\n
"
,
frameCntTotal
,
(
int
)
p1
->
handleMem
);
}
}
args
->
dataq
->
pop
();
if
(
p1
==
frame
)
{
ret
=
zmq_connect
(
pSub
,
strPubUrl
.
c_str
());
spdlog
::
error
(
"BUG!!! new frame address same as what in Queue"
);
if
(
ret
!=
0
)
{
spdlog
::
error
(
"failed connect frame pub: {}"
,
strPubUrl
);
continue
;
}
}
MaQue_Demo_Mem_release
(
p1
->
handleMem
);
ret
=
zmq_setsockopt
(
pSub
,
ZMQ_SUBSCRIBE
,
""
,
0
);
p1
=
nullptr
;
spdlog
::
info
(
"zmq sub successed (for frame sending)"
)
;
}
}
if
(
frame
->
pData
&&
frame
->
nDataLen
>
0
)
{
zmq_msg_t
msg
;
timeval
tv
;
while
(
1
)
{
//::gettimeofday(&tv,NULL);
// TODO: reconnect
DataItem
dt
=
{(
char
*
)
frame
->
pData
-
sizeof
(
evpacket_t
),
frame
->
nDataLen
+
sizeof
(
evpacket_t
),
(
void
*
)
frame
};
zmq_msg_init
(
&
msg
);
evpacket_t
*
pkt
=
(
evpacket_t
*
)
dt
.
buf
;
ret
=
zmq_msg_recv
(
&
msg
,
pSub
,
0
);
if
(
ret
<
0
)
{
memset
(
pkt
,
0
,
sizeof
(
*
pkt
));
spdlog
::
error
(
"failed to recv zmq msg: {}"
,
zmq_strerror
(
zmq_errno
()));
pkt
->
meta
.
magic
[
0
]
=
0xBE
;
flagFail
=
1
;
pkt
->
meta
.
magic
[
1
]
=
0xEF
;
break
;
memcpy
(
pkt
->
meta
.
sn
,
dev_sn
,
sizeof
(
dev_sn
));
/// NOTES: since both ends use little-endian, we don't use htonl, htons to save clocks
pkt
->
vpara
.
frame_type
=
frame
->
eSubType
+
1
;
pkt
->
vpara
.
packet_type
=
frame
->
eEncodeType
;
pkt
->
vpara
.
res
.
width
=
frame
->
nWidth
;
pkt
->
vpara
.
res
.
height
=
frame
->
nHeight
;
/// TODO:
pkt
->
vpara
.
fps
=
15
;
//pkt->vpara.ts = frame->stTimeStamp;
pkt
->
length
=
frame
->
nDataLen
;
pkt
->
meta
.
packet_id
=
packetId
;
pkt
->
meta
.
crc
=
0
;
pkt
->
meta
.
crc
=
crc16
((
unsigned
char
*
)
pkt
,
sizeof
(
evpacket_t
));
if
(
frame
->
eSubType
==
MAQUE_FRAME_SUBTYPE_I
)
{
frameCntIframe
++
;
}
else
if
(
frame
->
eSubType
==
MAQUE_FRAME_SUBTYPE_P
)
{
frameCntPframe
++
;
}
}
MaQue_Demo_Mem_addRef
(
frame
->
handleMem
);
// ssize_t sz = zmq_msg_size(&msg);
args
->
dataq
->
push
(
dt
);
// char *ptr = (char*)zmq_msg_data(&msg);
bPFrameAvail
=
true
;
ret
=
zmq_msg_send
(
&
msg
,
pDealer
,
0
);
spdlog
::
debug
(
"frame meter ic:{}, pc:{}, tc:{}, len:{}, cid:{}"
,
frameCntIframe
,
frameCntPframe
,
frameCntTotal
,
frame
->
nDataLen
,
packetId
);
zmq_msg_close
(
&
msg
);
packetId
++
;
if
(
ret
<
0
)
{
spdlog
::
error
(
"failed to send vgw: {}, {}"
,
zmq_strerror
(
zmq_errno
()));
flagFail
=
2
;
break
;
}
}
}
else
{
if
(
flagFail
&
1
)
{
spdlog
::
error
(
"invalid frame"
);
zmq_close
(
pSub
);
pSub
=
nullptr
;
}
if
(
flagFail
&
2
){
zmq_close
(
pDealer
);
zmq_ctx_destroy
(
pDealerCtx
);
pDealer
=
nullptr
;
pDealerCtx
=
nullptr
;
}
}
lock
.
unlock
();
args
->
noti
->
cond
->
notify_one
();
}
else
{
//spdlog::warn("pusher is disabled {}:{}", __FILE__, __LINE__);
}
if
(
logLevel
<=
spdlog
::
level
::
debug
)
{
printf
(
"%u, p2 h:%08X
\n
"
,
frameCntTotal
,
(
int
)
frame
->
handleMem
);
}
}
MaQue_Demo_Mem_release
(
frame
->
handleMem
);
return
XM_SUCCESS
;
}
}
void
frame_send_entry
(
void
*
args
)
{
void
load_sd_files
(
OrderedList
<
long
long
>
&
_list
){
CallBackArg
*
pvArg
=
(
CallBackArg
*
)
args
;
auto
now
=
chrono
::
duration_cast
<
chrono
::
milliseconds
>
(
chrono
::
system_clock
::
now
().
time_since_epoch
()).
count
();
int
freshConnect
=
0
;
try
{
DataItem
elem
=
{
0
};
string
fname
,
baseName
;
while
(
1
)
{
for
(
const
auto
&
entry
:
fs
::
directory_iterator
(
recFilePath
))
{
MaQueVideoEncFrameInfo_s
*
pMem
;
fname
=
entry
.
path
().
c_str
();
{
if
(
entry
.
file_size
()
==
0
||
!
entry
.
is_regular_file
()
||
entry
.
path
().
extension
()
!=
".h264"
)
{
unique_lock
<
mutex
>
lk
(
*
pvArg
->
noti
->
mut
);
spdlog
::
warn
(
"{} loadVideoFiles skipped {} (empty/directory/!h264)"
,
entry
.
path
().
c_str
());
pvArg
->
noti
->
cond
->
wait
(
lk
,
[
pvArg
]
{
return
!
pvArg
->
dataq
->
empty
();});
if
(
pvArg
->
dataq
->
empty
())
{
spdlog
::
warn
(
"dataq empty"
);
continue
;
continue
;
}
}
// /// remove old frames
// lk.unlock();
auto
ts
=
stoi
(
entry
.
path
().
stem
().
c_str
());
// while(pvArg->dataq->size() > 2) {
if
(
ts
<
TS_2020
){
// lk.lock();
/// TODO: files records when offline with no valid time got
// elem = pvArg->dataq->front();
fs
::
remove
(
entry
.
path
());
// pvArg->dataq->pop();
spdlog
::
warn
(
"remove records having invalid timestamp: {}"
,
ts
);
// lk.unlock();
continue
;
// pMem = (MaQueVideoEncFrameInfo_s *)elem.ud;
// MaQue_Demo_Mem_release(pMem->handleMem);
// }
// lk.lock();
elem
=
pvArg
->
dataq
->
front
();
pvArg
->
dataq
->
pop
();
lk
.
unlock
();
pMem
=
(
MaQueVideoEncFrameInfo_s
*
)
elem
.
ud
;
}
if
(
bConnected
==
false
)
{
if
(
bNeedRetry
==
true
)
{
// try reconect
bNeedRetry
=
false
;
if
(
raw_socket_
!=
0
)
{
::
close
(
raw_socket_
);
raw_socket_
=
0
;
}
spdlog
::
info
(
"try reconnecting to video gateway {}:{}"
,
host
,
port
);
auto
ret
=
raw_connect
(
host
,
port
,
&
raw_socket_
);
if
(
ret
<
0
||
raw_socket_
<=
0
)
{
spdlog
::
error
(
"failed to reconnect {}:{}"
,
host
,
port
);
bConnected
=
false
;
}
else
{
spdlog
::
info
(
"successfully connected to {}:{}"
,
host
,
port
);
bConnected
=
true
;
//LibXmMaQue_OSD_showTime(0, MAQUE_STREAM_CHN_MAIN, &stOsdTimeModParamMain.stOsdParam);
//freshConnect = pvArg->dataq->size();
/// pop all frames
}
}
}
_list
.
insert
(
ts
);
}
}
}
catch
(
exception
&
e
)
{
spdlog
::
error
(
"{}:{} loadVideoFiles exception : {}"
,
__FILE__
,
__LINE__
,
e
.
what
());
}
}
if
(
bConnected
==
false
||
!
pMem
||
elem
.
size
<=
0
||
elem
.
buf
==
nullptr
||
(
elem
.
buf
+
sizeof
(
evpacket_t
))
==
nullptr
)
{
void
remove_ts_file
(
long
long
ts
){
//printf("invalid frame. addr: %08X, len:%u\n", (uint32_t)elem.buf, elem.size);
string
fname
=
to_string
(
ts
)
+
".h264"
;
string
msg
;
fs
::
remove
(
fname
);
if
(
elem
.
size
<=
0
)
{
}
msg
=
fmt
::
format
(
"invalid frame size: {}"
,
elem
.
size
);
spdlog
::
warn
(
msg
);
}
else
if
(
elem
.
buf
==
nullptr
||
elem
.
buf
+
sizeof
(
evpacket_t
)
==
nullptr
)
{
msg
=
fmt
::
format
(
"invalid buffer addr: {0:p}"
,
elem
.
buf
);
spdlog
::
warn
(
msg
);
}
else
{
/// bConnected is false. needn't to log again
//msg = fmt::format("no connection to video gateway server {}:{}", host, port);
//spdlog::warn(msg);
}
/// release msg
void
record_video_entry
(
void
*
args
)
if
(
pMem
&&
pMem
->
handleMem
)
{
{
if
(
logLevel
<=
spdlog
::
level
::
debug
)
{
int
ret
=
0
;
printf
(
"%u, p3 h:%08X
\n
"
,
frameCntTotal
,
(
int
)
pMem
->
handleMem
);
// this thread will never exit
}
while
(
1
)
{
MaQue_Demo_Mem_release
(
pMem
->
handleMem
);
if
(
!
is_sdcard_avail
())
{
pMem
=
nullptr
;
spdlog
::
error
(
"no sd card valial. can't record local videos"
);
}
this_thread
::
sleep_for
(
10
s
);
continue
;
}
uint64_t
total
=
0
,
avail
=
0
;
if
(
!
get_sdcard_megabytes
(
total
,
avail
)){
spdlog
::
error
(
"failed to get sd card size"
);
continue
;
continue
;
}
}
/// send frame
spdlog
::
info
(
"sd card: {}MB total, {}MB free"
,
total
,
avail
);
if
(
elem
.
size
>
0
)
{
auto
sz
=
elem
.
size
;
// calc num of slices
char
*
ptr
=
elem
.
buf
;
// reserve 0.5GB space
ssize_t
sent
=
0
;
ssize_t
maxSlices
=
(
total
-
512
)
/
10
;
while
(
elem
.
size
>
0
)
{
OrderedList
<
long
long
>
tsList
(
maxSlices
,
remove_ts_file
);
ptr
+=
sent
;
gRecFilesList
=
&
tsList
;
sent
=
::
send
(
raw_socket_
,
ptr
,
elem
.
size
>
NUM_MAX_PACKET_BYTES
?
NUM_MAX_PACKET_BYTES
:
elem
.
size
,
0
);
// load existing videos
if
(
sent
<=
0
)
{
load_sd_files
(
tsList
);
break
;
// setup sub
void
*
pSub
=
zmq_socket
(
pPubCtx
,
ZMQ_SUB
);
// ret = 1;
// zmq_setsockopt(pSub, ZMQ_TCP_KEEPALIVE, &ret, sizeof (ret));
// ret = 2;
// zmq_setsockopt(pSub, ZMQ_TCP_KEEPALIVE_IDLE, &ret, sizeof (ret));
// zmq_setsockopt(pSub, ZMQ_TCP_KEEPALIVE_INTVL, &ret, sizeof (ret));
ret
=
zmq_connect
(
pSub
,
strPubUrl
.
c_str
());
if
(
ret
!=
0
)
{
spdlog
::
error
(
"failed connect frame pub: {}"
,
strPubUrl
);
exit
(
1
);
}
ret
=
zmq_setsockopt
(
pSub
,
ZMQ_SUBSCRIBE
,
""
,
0
);
spdlog
::
info
(
"zmq sub successed (record)"
);
zmq_msg_t
msg
;
long
long
preTs
=
0
;
long
long
nowTs
=
0
;
uint32_t
cnt
=
0
;
fstream
*
fp
=
nullptr
;
while
(
1
)
{
zmq_msg_init
(
&
msg
);
ret
=
zmq_msg_recv
(
&
msg
,
pSub
,
0
);
if
(
ret
<
0
)
{
spdlog
::
error
(
"failed to recv zmq msg: {}"
,
zmq_strerror
(
ret
));
continue
;
}
ssize_t
sz
=
zmq_msg_size
(
&
msg
);
char
*
ptr
=
(
char
*
)
zmq_msg_data
(
&
msg
);
/// we calc timestamps about every 2s
if
(
cnt
%
30
==
0
)
{
nowTs
=
chrono
::
duration_cast
<
chrono
::
milliseconds
>
(
chrono
::
system_clock
::
now
().
time_since_epoch
()).
count
();
}
if
(
nowTs
-
preTs
>
gConfigRecord
.
module
.
record
.
interval
*
1000
)
{
if
(
fp
!=
nullptr
)
{
if
(
fp
->
is_open
())
fp
->
close
();
delete
fp
;
}
}
else
{
fp
=
new
fstream
(
recFilePath
+
to_string
(
nowTs
),
std
::
ios
::
out
|
std
::
ios
::
binary
);
//spdlog::debug("sent:{}, total:{}", sent, sz);
if
(
!
fp
->
is_open
()){
spdlog
::
error
(
"failed to open record file"
);
delete
fp
;
fp
=
nullptr
;
}
else
{
tsList
.
insert
(
nowTs
);
}
}
elem
.
size
-=
sent
;
preTs
=
nowTs
;
}
}
if
(
sent
<=
0
)
{
if
(
fp
!=
nullptr
)
{
spdlog
::
error
(
"failed to send, peer down"
);
fp
->
write
(
ptr
,
sz
);
/// TODO: reconnection
bConnected
=
false
;
bNeedRetry
=
true
;
}
}
cnt
++
;
zmq_msg_close
(
&
msg
);
}
}
else
{
spdlog
::
error
(
"frame size error"
);
zmq_close
(
pSub
);
}
/// DO NOT! do this
if
(
logLevel
<=
spdlog
::
level
::
debug
)
{
//zmq_ctx_destroy(pPubCtx);
printf
(
"%u, p4 h:%08X
\n
"
,
frameCntTotal
,
(
int
)
pMem
->
handleMem
);
}
MaQue_Demo_Mem_release
(
pMem
->
handleMem
);
}
}
}
}
/// verify request message
/// verify request message
...
@@ -468,66 +550,42 @@ void report_response_args(string topic, int code, string message, string cata, s
...
@@ -468,66 +550,42 @@ void report_response_args(string topic, int code, string message, string cata, s
_report_response
(
topic
,
js
.
to_string
());
_report_response
(
topic
,
js
.
to_string
());
}
}
int
apply_config
(
json
&
js
)
string
verify_config
(
json
&
data
)
{
{
auto
hasSD
=
is_sdcard_avail
();
/// verify parameters
string
str
,
strWarn
;
string
str
,
strWarn
;
if
(
!
js
.
contains
(
kMsgData
))
{
string
veri
[]
=
{
kMsgConfigVgw
,
kMsgConfigMqtt
,
kMsgConfigUpload
};
str
=
fmt
::
format
(
"no data object in config: {}"
,
js
.
to_string
());
for
(
auto
&
k
:
veri
)
{
}
auto
value
=
msg_field
(
data
,
k
);
else
{
if
(
value
.
empty
())
{
json
data
=
js
[
kMsgData
];
str
=
fmt
::
format
(
"no {} field in data: {}"
,
k
,
data
.
to_string
());
string
veri
[]
=
{
kMsgConfigVgw
,
kMsgConfigMqtt
,
kMsgConfigUpload
};
break
;
for
(
auto
&
k
:
veri
)
{
}
auto
value
=
msg_field
(
data
,
k
);
else
{
if
(
value
.
empty
())
{
// parse host and port
str
=
fmt
::
format
(
"no {} field in data: {}"
,
k
,
js
.
to_string
());
auto
uri
=
httplib
::
Uri
::
Parse
(
value
);
if
(
uri
.
Host
.
empty
()
||
uri
.
Port
.
empty
())
{
str
=
fmt
::
format
(
"host addr invalid {}:{}, {}"
,
k
,
value
,
data
.
to_string
());
break
;
break
;
}
}
else
{
// check network connections
// parse host and port
int
socket
=
0
;
auto
uri
=
httplib
::
Uri
::
Parse
(
value
);
auto
rc
=
raw_connect
(
uri
.
Host
,
uri
.
Port
,
&
socket
);
if
(
uri
.
Host
.
empty
()
||
uri
.
Port
.
empty
())
{
if
(
rc
<
0
||
socket
==
0
)
{
str
=
fmt
::
format
(
"host addr invalid {}:{}, {}"
,
k
,
value
,
js
.
to_string
());
str
=
fmt
::
format
(
"failed to connect to {}:{}, {}"
,
k
,
value
,
data
.
to_string
());
break
;
break
;
}
// check network connections
int
socket
=
0
;
auto
rc
=
raw_connect
(
uri
.
Host
,
uri
.
Port
,
&
socket
);
if
(
rc
<
0
||
socket
==
0
)
{
str
=
fmt
::
format
(
"failed to connect to {}:{}, {}"
,
k
,
value
,
js
.
to_string
());
break
;
}
else
{
// we must close the test socket
::
close
(
socket
);
}
}
}
// check features field
json
features
=
data
.
get_value_or
<
json
>
(
kMsgConfigFeatures
,
json
());
string
feats
[]
=
{
kMsgConfigMotion
,
kMsgConfigRecord
,
kMsgConfigAi
};
for
(
auto
&
k
:
feats
)
{
auto
f
=
features
.
get_value_or
<
json
>
(
k
,
json
());
if
(
f
.
size
()
==
0
)
{
strWarn
=
fmt
::
format
(
"{}, "
,
k
);
}
}
if
(
!
strWarn
.
empty
())
{
else
{
strWarn
=
"no below feature in config, default configuration is applied: "
+
strWarn
;
// we must close the test socket
::
close
(
socket
);
}
}
}
}
}
}
if
(
!
str
.
empty
())
{
if
(
!
str
.
empty
())
{
report_response_args
(
pub_topic
,
EV_MSG_ERROR_CONTENT_SYNTAX
,
str
,
kMsgCmdConfig
,
msg_field
(
js
,
kMsgRid
),
json
());
spdlog
::
error
(
str
);
spdlog
::
error
(
str
);
return
-
EV_MSG_ERROR_CONTENT_SYNTAX
;
}
}
// try to apply
return
str
;
}
}
/// handles all incoming request from cloud services
/// handles all incoming request from cloud services
...
@@ -588,14 +646,36 @@ void start_mqtt(void *arg)
...
@@ -588,14 +646,36 @@ void start_mqtt(void *arg)
client
->
subscribe
(
sub_topic
+
dev_sn
,
handle_mqtt_req
,
false
);
client
->
subscribe
(
sub_topic
+
dev_sn
,
handle_mqtt_req
,
false
);
}
}
//
void
updateConfigFile
(
json
&
config
){
ofstream
ocfg_
(
configFilePath
,
std
::
ios
::
trunc
);
ocfg_
<<
pretty_print
(
gJsonConfig
);
}
void
readConfigFile
(
json
&
config
){
try
{
ifstream
cfg_
(
configFilePath
);
gJsonConfig
=
json
::
parse
(
cfg_
);
}
catch
(
exception
&
e
){
gJsonConfig
=
evutils
::
make_default_config
();
spdlog
::
error
(
"failed get config: {}, force to make default config:
\n
{}"
,
e
.
what
(),
gJsonConfig
.
to_string
());
updateConfigFile
(
gJsonConfig
);
}
}
void
create_sd_directories
(){
// create record paths
for
(
auto
&
k
:
strSDCardReservedPaths
){
system
((
string
(
"mkdir -p "
)
+
k
).
c_str
());
}
}
///
///
int
main
(
int
argc
,
char
*
argv
[])
int
main
(
int
argc
,
char
*
argv
[])
{
{
int
ret
=
XM_SUCCESS
;
int
ret
=
XM_SUCCESS
;
spdlog
::
info
(
"test on hi3518ev300, {}"
,
is_big_endian
());
get_mac_addr
(
dev_sn
);
get_mac_addr
(
dev_sn
);
spdlog
::
info
(
"hi3518ev300, sn: {}, version: {}, BE: {}"
,
dev_sn
,
evutils
::
version
,
is_big_endian
());
// get env for host and port
// get env for host and port
auto
host_
=
getenv
(
"VGW_HOST"
);
auto
host_
=
getenv
(
"VGW_HOST"
);
...
@@ -617,6 +697,13 @@ int main(int argc, char *argv[])
...
@@ -617,6 +697,13 @@ int main(int argc, char *argv[])
/// TODO: check sd availability
/// TODO: check sd availability
bool
bSDAvail
=
is_sdcard_avail
();
bool
bSDAvail
=
is_sdcard_avail
();
if
(
bSDAvail
)
{
create_sd_directories
();
}
/// TODO: load configuration
readConfigFile
(
gJsonConfig
);
verify_config
(
gJsonConfig
);
auto
logLevel_
=
getenv
(
"LOG_LEVEL"
);
auto
logLevel_
=
getenv
(
"LOG_LEVEL"
);
if
(
logLevel_
)
{
if
(
logLevel_
)
{
...
@@ -636,31 +723,26 @@ int main(int argc, char *argv[])
...
@@ -636,31 +723,26 @@ int main(int argc, char *argv[])
}
}
}
}
MaQue_Demo_Mem_Init
();
// blocking update time, since time is critical to every other component
bool
bGotTime
=
false
;
/// thread of utp time
time_t
stm
;
auto
thNtp
=
thread
([]
{
while
(
!
bGotTime
)
bool
bGotTime
=
false
;
{
time_t
stm
;
if
(
getNtpTime
(
&
stm
)
>=
0
)
{
while
(
!
bGotTime
)
spdlog
::
info
(
"ntp got time"
);
{
::
stime
(
&
stm
);
if
(
getNtpTime
(
&
stm
)
>=
0
)
{
bGotTime
=
true
;
spdlog
::
info
(
"ntp got time"
);
::
stime
(
&
stm
);
bGotTime
=
true
;
}
else
{
spdlog
::
warn
(
"failed to get ntp time"
);
}
this_thread
::
sleep_for
(
chrono
::
seconds
(
20
));
}
}
});
else
{
spdlog
::
warn
(
"failed to get ntp time"
);
if
(
thNtp
.
joinable
())
{
}
th
Ntp
.
detach
(
);
th
is_thread
::
sleep_for
(
chrono
::
seconds
(
3
)
);
}
}
MaQueStartParam_s
startParam
=
{
MAQUE_VIDEO_STANDARD_PAL
,
{
MAQUE_VIDEO_COMPRESS_H264
,
MAQUE_VIDEO_COMPRESS_H265
},
"/mnt/sd/Config/"
};
MaQue_Demo_Mem_Init
();
MaQueStartParam_s
startParam
=
{
MAQUE_VIDEO_STANDARD_PAL
,
{
MAQUE_VIDEO_COMPRESS_H264
,
MAQUE_VIDEO_COMPRESS_H265
}};
memcpy
(
startParam
.
aWritableDir
,
strMaQuePath
.
c_str
(),
sizeof
(
startParam
.
aWritableDir
));
ret
=
LibXmMaQue_System_startUp
(
&
startParam
);
ret
=
LibXmMaQue_System_startUp
(
&
startParam
);
spdlog
::
info
(
"ret: {}"
,
ret
);
spdlog
::
info
(
"ret: {}"
,
ret
);
...
@@ -678,10 +760,10 @@ int main(int argc, char *argv[])
...
@@ -678,10 +760,10 @@ int main(int argc, char *argv[])
spdlog
::
info
(
"abt ret: {}"
,
ret
);
spdlog
::
info
(
"abt ret: {}"
,
ret
);
if
(
XM_SUCCESS
==
ret
)
{
if
(
XM_SUCCESS
==
ret
)
{
spdlog
::
info
(
fmt
::
format
(
"capbilities: supported codecs {0:#b},"
spdlog
::
info
(
fmt
::
format
(
"capbilities: supported codecs {0:#b},"
"max fhd/s {0:d}, max res: {0:d}, per ch mres: {0:d}, {0:d}, {0:d}, {0:d}"
,
"max fhd/s {0:d}, max res: {0:d}, per ch mres: {0:d}, {0:d}, {0:d}, {0:d}"
,
int
(
capb
.
videoEncTypeMask
),
int
(
capb
.
videoEncTypeMask
),
int
(
capb
.
maxEncPowerX1080P
),
int
(
capb
.
eDecImageSizeMax
),
int
(
capb
.
astVidEncChnAbility
[
0
].
eCapSizeMax
),
int
(
capb
.
maxEncPowerX1080P
),
int
(
capb
.
eDecImageSizeMax
),
int
(
capb
.
astVidEncChnAbility
[
0
].
eCapSizeMax
),
int
(
capb
.
astVidEncChnAbility
[
1
].
eCapSizeMax
),
int
(
capb
.
astVidEncChnAbility
[
2
].
eCapSizeMax
),
int
(
capb
.
astVidEncChnAbility
[
3
].
eCapSizeMax
)));
int
(
capb
.
astVidEncChnAbility
[
1
].
eCapSizeMax
),
int
(
capb
.
astVidEncChnAbility
[
2
].
eCapSizeMax
),
int
(
capb
.
astVidEncChnAbility
[
3
].
eCapSizeMax
)));
}
}
//
//
...
@@ -692,23 +774,13 @@ int main(int argc, char *argv[])
...
@@ -692,23 +774,13 @@ int main(int argc, char *argv[])
cfg
.
nIFrameInterval
=
10
;
cfg
.
nIFrameInterval
=
10
;
cfg
.
eImageQuality
=
(
MaQueImageQuality_e
)
videoQuality
;
cfg
.
eImageQuality
=
(
MaQueImageQuality_e
)
videoQuality
;
cfg
.
eVidComp
=
MAQUE_VIDEO_COMPRESS_H264
;
cfg
.
eVidComp
=
MAQUE_VIDEO_COMPRESS_H264
;
cfg
.
nBitRate
=
200
*
8
;
// 200KB
cfg
.
eBitrateCtrl
=
MAQUE_BITRATE_CTRL_VBR
;
cfg
.
nBitRate
=
1024
;
// 1Mbps
ret
=
configure_stream
((
MaQueStreamChannel_e
)
0
,
&
cfg
);
ret
=
configure_stream
((
MaQueStreamChannel_e
)
0
,
&
cfg
);
spdlog
::
info
(
"cfg stream ret: {}"
,
ret
);
spdlog
::
info
(
"cfg stream ret: {}"
,
ret
);
///
/// record setting
/// TODO: load or make defualt configuration
if
(
enableRecord
&&
bSDAvail
)
{
gConfigRecord
.
module
.
record
.
interval
=
60
*
2
;
// 2 minutes interval
FILE
*
recFD
=
fopen
(
recFilePath
,
"w+"
);
if
(
!
recFD
)
{
spdlog
::
error
(
"fopen() Failed: {}"
,
recFilePath
);
bCanRecord
=
false
;
}
else
{
args
.
recFD
=
recFD
;
bCanRecord
=
true
;
}
}
ret
=
LibXmMaQue_VideoEnc_startStream
(
0
,
(
MaQueStreamChannel_e
)
0
,
cb_frame_proc
,
(
void
*
)
&
args
);
ret
=
LibXmMaQue_VideoEnc_startStream
(
0
,
(
MaQueStreamChannel_e
)
0
,
cb_frame_proc
,
(
void
*
)
&
args
);
if
(
XM_SUCCESS
==
ret
)
{
if
(
XM_SUCCESS
==
ret
)
{
...
@@ -716,25 +788,32 @@ int main(int argc, char *argv[])
...
@@ -716,25 +788,32 @@ int main(int argc, char *argv[])
}
}
signal
(
SIGINT
,
clean_up
);
signal
(
SIGINT
,
clean_up
);
//signal(SIGTERM, clean_up);
//
signal(SIGTERM, clean_up);
signal
(
SIGKILL
,
clean_up
);
signal
(
SIGKILL
,
clean_up
);
signal
(
SIGPIPE
,
SIG_IGN
);
if
(
enablePush
)
{
// frame dispatching
ret
=
raw_connect
(
host
,
port
,
&
raw_socket_
);
pPubCtx
=
zmq_ctx_new
();
if
(
ret
<
0
||
raw_socket_
<=
0
)
{
pPub
=
zmq_socket
(
pPubCtx
,
ZMQ_PUB
);
spdlog
::
error
(
"failed connect to video gateway at {}:{}"
,
host
,
port
);
ret
=
zmq_bind
(
pPub
,
strPubUrl
.
c_str
());
bConnected
=
false
;
if
(
ret
<
0
)
{
}
spdlog
::
error
(
"{} failed to create zmq pub topic: {}"
,
strPubUrl
);
else
{
exit
(
1
);
bConnected
=
true
;
}
spdlog
::
info
(
"successfully connected to video gateway at {}:{}"
,
host
,
port
);
/// TODO: configuration issues handling
}
if
(
msg_field
(
gJsonConfig
,
kMsgConfigVgw
).
empty
()){
thread
thPush
=
thread
(
frame_send_entry
,
&
args
);
spdlog
::
error
(
"missing vgw config"
);
spdlog
::
info
(
"sizeof pkt header {}, sizeof tv {}"
,
sizeof
(
evpacket_t
),
sizeof
(
timeval
));
}
thread
thPush
=
thread
(
frame_send_entry
,
&
args
);
spdlog
::
info
(
"sizeof pkt header {}, sizeof tv {}"
,
sizeof
(
evpacket_t
),
sizeof
(
timeval
));
if
(
thPush
.
joinable
()){
thPush
.
detach
();
thPush
.
detach
();
}
}
else
{
spdlog
::
warn
(
"push video is not enabled in environ settings"
);
thread
thVideoRecord
=
thread
(
record_video_entry
,
nullptr
);
if
(
thVideoRecord
.
joinable
()){
thVideoRecord
.
detach
();
}
}
start_md_bd
(
&
args
);
start_md_bd
(
&
args
);
...
...
hi3518/main.cc.bak2
deleted
100644 → 0
浏览文件 @
298fb4fe
#include <iostream>
#include <string>
#include <chrono>
#include <fmt/format.h>
#include <spdlog/spdlog.h>
#include "utils.h"
#include "ref-memory.hpp"
#include <maque_system.h>
#include <maque_video_enc.h>
#include <maque_time.h>
#include "common.h"
#include "ntp.h"
#include <time.h>
#include "raw_tcp.h"
#include <evpacket.h>
#include "smart.h"
#include "motion.h"
#include <thread>
#include <rtsp_pusher.hpp>
using namespace std;
//
//#define ENALBE_RECORD
#define NUM_IFRAME_PICK 2
#define NUM_MAX_QUEQUE_SIZE 60
#define NUM_MAX_PACKET_BYTES 1000
static unsigned long long frameCntTotal = 0;
static unsigned long long frameCntIframe = 0;
static unsigned long long frameCntPframe = 0;
static unsigned long long frameCntIframePrev = 0;
static bool bPFrameAvail = false;
static bool bAvailable = false;
static bool enablePush = false;
static queue<DataItem> _frameQueue;
static mutex _mutFrame;
static condition_variable _condFrame;
static Notifier _notiFrame = {&_mutFrame, &_condFrame};
static CallBackArg args = {nullptr, &_notiFrame, &_frameQueue};
static int raw_socket_ = 0;
static bool bGotTime = false;
void clean_up(int sig){
spdlog::warn("clearn up called, with sig: {}", sig);
if(args.recFD){
fclose(args.recFD);
}
if(raw_socket_){
::close(raw_socket_);
}
while(args.dataq->size() > 0){
DataItem elem = args.dataq->front();
args.dataq->pop();
MaQueVideoEncFrameInfo_s *pMem = (MaQueVideoEncFrameInfo_s*) elem.ud;
MaQue_Demo_Mem_release(pMem->handleMem);
}
//stop_md_bd();
LibXmMaQue_System_destroy();
exit(1);
}
MaQueVideoEncodeCfg_s *init_stream_cfg(MaQueVideoEncodeCfg_s *cfg) {
cfg->eVidComp = -1;
cfg->eCapSize = -1;
cfg->eBitrateCtrl = -1;
cfg->eImageQuality = -1;
cfg->nFps = -1;
cfg->nBitRate = -1;
cfg->nIFrameInterval = -1;
cfg->iQpMin = -1;
cfg->iQpMax = -1;
return cfg;
}
int32_t configure_stream(MaQueStreamChannel_e eStreamChn, MaQueVideoEncodeCfg_s *cfg)
{
int32_t res;
MaQueVideoEncodeCfg_s oldCfg;
if (LibXmMaQue_VideoEnc_getCfg(0, eStreamChn, &oldCfg)){
spdlog::error("LibXmMaQue_VideoEncode_getCfg error");
return -1;
}
if(cfg->eVidComp != -1) {
oldCfg.eVidComp = cfg->eVidComp;
}
if(cfg->eCapSize != -1) {
oldCfg.eCapSize = cfg->eCapSize;
}
if(cfg->eBitrateCtrl != -1) {
oldCfg.eBitrateCtrl = cfg->eBitrateCtrl;
}
if(cfg->eImageQuality != -1) {
oldCfg.eImageQuality = cfg->eImageQuality;
}
if(cfg->nFps != -1){
oldCfg.nFps = cfg->nFps;
}
if(cfg->nBitRate != -1){
oldCfg.nBitRate = cfg->nBitRate;
}
if(cfg->nIFrameInterval != -1) {
oldCfg.nIFrameInterval = cfg->nIFrameInterval;
}
if (cfg->iQpMin > 0 && cfg->iQpMin <= 51
&& cfg->iQpMax > 0 && cfg->iQpMax <= 51)
{
oldCfg.iQpMin = cfg->iQpMin;
oldCfg.iQpMax = cfg->iQpMax;
oldCfg.bUseUserQp = 1;
}
spdlog::info("main: fps={}", oldCfg.nFps);
res = LibXmMaQue_VideoEnc_setCfg(0, eStreamChn, &oldCfg);
if(!res){
memcpy(cfg, &oldCfg, sizeof(oldCfg));
}
return res;
}
//
XM_S32 cb_frame_proc(XM_VOID *pUserArg, MaQueVideoEncFrameInfo_s *frame){
MaQueSystemTime_s *pstSysTime = &frame->stTimeStamp.stSysTime;
CallBackArg* args = (CallBackArg *)pUserArg;
struct timeval stTimeVal;
int ret;
//spdlog::info("new frame {}", frameCntTotal);
frameCntTotal++;
// stTimeVal.tv_sec = pstSysTime->day * 24 * 60 * 60 + pstSysTime->hour * 60 * 60
// + pstSysTime->minute * 60 + pstSysTime->second;
// stTimeVal.tv_usec = pstSysTime->second * 1000;
#ifdef ENALBE_RECORD
if(args->recFD)
{
fwrite(frame->pData, 1, frame->nDataLen, args->recFD);
}
#endif
if(enablePush && args->dataq && frame->eEncodeType == MAQUE_ENCODE_TYPE_H264) {
lock_guard<mutex> lock(*args->noti->mut);
if(args->dataq->size() >= NUM_MAX_QUEQUE_SIZE){
bAvailable = false;
spdlog::warn("dataq full");
}else if(args->dataq->size() <= NUM_MAX_QUEQUE_SIZE*2/3){
bAvailable = true;
}
if(frame->eSubType == MAQUE_FRAME_SUBTYPE_I){
frameCntIframe++;
}
if(bAvailable && frame->pData && frame->nDataLen > 0){
timeval tv;
//::gettimeofday(&tv,NULL);
//DataItem dt = {(char *)frame->pData - sizeof(evpacket_t), frame->nDataLen + sizeof(evpacket_t), (void*)frame};
DataItem dt = {(char *)frame->pData, frame->nDataLen, (void*)frame};
evpacket_t * pkt = (evpacket_t *)dt.buf;
memset(pkt, 0, sizeof(*pkt));
pkt->meta.magic[0] = 0xBE;
pkt->meta.magic[1] = 0xEF;
pkt->vpara.frame_type = (evframe_type_t)(frame->eSubType +1);
pkt->vpara.packet_type = (evpacket_type_t)(frame->eEncodeType);
pkt->vpara.res.width = htons(frame->nWidth);
pkt->vpara.res.height = htons(frame->nHeight);
//pkt->vpara.ts = tv;
pkt->length = htonl(frame->nDataLen);
//if(frame->eSubType == MAQUE_FRAME_SUBTYPE_I && (frameCntIframe-1) % NUM_IFRAME_PICK == 0) {
MaQue_Demo_Mem_addRef(frame->handleMem);
args->dataq->push(std::move(dt));
args->noti->cond->notify_all();
frameCntIframePrev = frameCntIframe;
// bPFrameAvail = true;
// frameCntPframe = 0;
// spdlog::debug("=====\nframe meter ic: {}, tc: {}, len: {}, p avail", frameCntIframe, frameCntTotal, frame->nDataLen);
// }else if(bPFrameAvail && frame->eSubType == MAQUE_FRAME_SUBTYPE_P && frameCntIframe == frameCntIframePrev){
// MaQue_Demo_Mem_addRef(frame->handleMem);
// args->dataq->push(std::move(dt));
// args->noti->cond->notify_all();
// ++frameCntPframe;
// spdlog::debug("=====\nframe meter pc: {}, tc: {}, len: {}, p avail", frameCntPframe, frameCntTotal, frame->nDataLen);
// // spdlog::info("pframe : {}, {}", frameCntIframe, frameCntIframePrev);
// }else{
// //spdlog::error("pframe not avail: {}, {}", frameCntIframe, frameCntIframePrev);
// bPFrameAvail = false;
// }
}else{
spdlog::warn("h264 not avail");
}
}
if(frame->handleMem != 0) {
MaQue_Demo_Mem_release(frame->handleMem);
}
return XM_SUCCESS;
}
void frame_send_entry(void * args){
CallBackArg * pvArg = (CallBackArg *)args;
unsigned long long frameCnt = 0;
while(1){
DataItem elem;
{
unique_lock<mutex> lk(*pvArg->noti->mut);
pvArg->noti->cond->wait(lk, [pvArg] {return !pvArg->dataq->empty();});
if(pvArg->dataq->empty()){
this_thread::sleep_for(chrono::milliseconds(500));
printf("dataq empty");
continue;
}
elem = pvArg->dataq->front();
//pvArg->dataq->pop();
frameCnt++;
}
MaQueVideoEncFrameInfo_s *pMem = (MaQueVideoEncFrameInfo_s *)elem.ud;
// send frame
if(elem.size <= 0 || elem.buf == nullptr || (elem.buf + sizeof(evpacket_t)) == nullptr) {
spdlog::error("invalid frame. addr: {0:x}, len: {0:d}", (uint32_t)elem.buf, elem.size);
pvArg->dataq->pop();
continue;
}
if(elem.size > 0){
char * ptr = elem.buf;
size_t sent = 0;
// while((elem.size -= sent) > 0 &&
// (sent = ::send(raw_socket_, (ptr+=sent), elem.size >
// NUM_MAX_PACKET_BYTES? NUM_MAX_PACKET_BYTES:elem.size, 0)) > 0) {
// //
// }
while(elem.size >0) {
ptr += sent;
//sent = ::send(raw_socket_, ptr, elem.size > NUM_MAX_PACKET_BYTES? NUM_MAX_PACKET_BYTES:elem.size, 0);
sent = ::send(raw_socket_, ptr, elem.size, 0);
if(sent <= 0){
break;
}
elem.size -= sent;
}
if(sent < 0){
spdlog::error("faile to send");
exit(1);
}
}else{
spdlog::error("size error or not got time");
}
MaQue_Demo_Mem_release(pMem->handleMem);
pvArg->dataq->pop();
}
}
//
int main(int argc, char *argv[]){
int ret = XM_SUCCESS;
spdlog::set_level(spdlog::level::debug);
spdlog::info("test on hi3518ev300");
char *host = "192.168.55.104", *port = "7123";
if(argc == 3){
host = argv[1];
port = argv[2];
enablePush = true;
}
// time_t stm;
// if(getNtpTime(&stm) >=0){
// if(stime(&stm) < 0){
// spdlog::error("failed to set system time");
// }else{
// spdlog::info("ntp got time");
// bGotTime = true;
// }
// }
MaQueStartParam_s startParam = {0, {MAQUE_VIDEO_COMPRESS_H264, MAQUE_VIDEO_COMPRESS_H265}, "/mnt/sd/Config/"};
ret = LibXmMaQue_System_startUp(&startParam);
spdlog::info("ret: {}", ret);
//
MaQueMemoryApi_s memApi = {MaQue_Demo_Mem_alloc, MaQue_Demo_Mem_release, MaQue_Demo_Mem_addRef, MaQue_Demo_Mem_setLength};
ret = LibXmMaQue_Mem_init(&memApi);
spdlog::info("mem ret: {}", ret);
MaQueSystemTime_s tm;
LibXmMaQue_Time_getCurrentTime(&tm);
LibXmMaQue_Time_print(&tm, "NULL");
const char * testUrl = "rtsp://evcloud.ilabservice.cloud/test_pusher";
//
MaQueCodeAbilities_s capb;
ret = LibXmMaQue_VideoEnc_getAbilities(0, &capb);
spdlog::info("abt ret: {}", ret);
if(XM_SUCCESS == ret){
spdlog::info(fmt::format("capbilities: supported codecs {0:#b}, \
max fhd/s {0:d}, max res: {0:d}, per ch mres: {0:d}, {0:d}, {0:d}, {0:d}", int(capb.videoEncTypeMask),
int(capb.maxEncPowerX1080P), int(capb.eDecImageSizeMax), int(capb.astVidEncChnAbility[0].eCapSizeMax),
int(capb.astVidEncChnAbility[1].eCapSizeMax), int(capb.astVidEncChnAbility[2].eCapSizeMax), int(capb.astVidEncChnAbility[3].eCapSizeMax)));
}
//
MaQueVideoEncodeCfg_s cfg;
init_stream_cfg(&cfg);
cfg.nFps = 10;
cfg.eIFrmIntvType=IFRAME_INTV_TYPE_TIME;
cfg.nIFrameInterval = 10;
cfg.eImageQuality = MAQUE_IMG_QUALITY_GOOD;
cfg.eVidComp = MAQUE_VIDEO_COMPRESS_H264;
ret = configure_stream(0, &cfg);
spdlog::info("cfg stream ret: {}", ret);
//
#ifdef ENALBE_RECORD
const char * const recFilePath = "/mnt/sd/record/rec.264";
FILE *recFD = fopen(recFilePath, "w+");
if(!recFD)
{
spdlog::error("fopen() Failed: {}", recFilePath);
LibXmMaQue_System_destroy();
exit(0);
}
args.recFD = recFD;
#endif
ret = LibXmMaQue_VideoEnc_startStream(0, 0, cb_frame_proc, (void*)&args);
if(XM_SUCCESS == ret) {
spdlog::info("created record task successfully");
}
signal(SIGINT, clean_up);
//signal(SIGTERM, clean_up);
signal(SIGKILL, clean_up);
RtspPusher pusher1(testUrl, &_notiFrame, &_frameQueue);
thread thPusher;
if(enablePush) {
// ret = raw_connect(host, port, &raw_socket_);
// if(ret <0 || raw_socket_ <= 0){
// spdlog::error("failed to create socket");
// exit(1);
// }
// thread thPush = thread(frame_send_entry, &args);
// spdlog::info("sizeof pkt header {}, sizeof tv {}", sizeof(evpacket_t), sizeof(timeval));
// thPush.detach();
pusher1.start(thPusher);
}
start_md_bd(&args);
thread thSmart = thread(maq_smart_task_entry, &args);
thSmart.join();
}
\ No newline at end of file
hi3518/ntp.cc
浏览文件 @
2c0181b7
...
@@ -22,7 +22,7 @@ int getNtpTime(time_t * txTm)
...
@@ -22,7 +22,7 @@ int getNtpTime(time_t * txTm)
{
{
int
socket_
=
0
,
n
=
0
,
rv
=
0
;
// Socket file descriptor and the n return result from writing/reading from the socket.
int
socket_
=
0
,
n
=
0
,
rv
=
0
;
// Socket file descriptor and the n return result from writing/reading from the socket.
int
portno
=
123
;
// NTP UDP port number.
int
portno
=
123
;
// NTP UDP port number.
const
char
*
host_name
=
"
cn.pool.ntp.org
"
;
// NTP server host-name.
const
char
*
host_name
=
"
time.nist.gov
"
;
// NTP server host-name.
// Structure that defines the 48 byte NTP packet protocol.
// Structure that defines the 48 byte NTP packet protocol.
typedef
struct
{
typedef
struct
{
...
...
hi3518/raw_tcp.cc
浏览文件 @
2c0181b7
...
@@ -33,6 +33,23 @@ int raw_connect(std::string host, std::string port, int *socket_, int recv_timeo
...
@@ -33,6 +33,23 @@ int raw_connect(std::string host, std::string port, int *socket_, int recv_timeo
last_errno
=
errno
;
last_errno
=
errno
;
continue
;
continue
;
}
}
struct
timeval
timeout
;
timeout
.
tv_sec
=
recv_timeout
;
timeout
.
tv_usec
=
0
;
if
(
setsockopt
(
*
socket_
,
SOL_SOCKET
,
SO_RCVTIMEO
,
(
char
*
)
&
timeout
,
sizeof
(
timeout
))
<
0
)
{
spdlog
::
error
(
"setsockopt SO_RCVTIMEO failed"
);
return
-
1
;
}
timeout
.
tv_sec
=
send_timeout
;
if
(
setsockopt
(
*
socket_
,
SOL_SOCKET
,
SO_SNDTIMEO
,
(
char
*
)
&
timeout
,
sizeof
(
timeout
))
<
0
)
{
spdlog
::
error
(
"setsockopt SO_SNDTIMEO failed"
);
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
;
...
@@ -50,21 +67,6 @@ int raw_connect(std::string host, std::string port, int *socket_, int recv_timeo
...
@@ -50,21 +67,6 @@ int raw_connect(std::string host, std::string port, int *socket_, int recv_timeo
rv
=
-
1
;
rv
=
-
1
;
}
}
}
}
struct
timeval
timeout
;
timeout
.
tv_sec
=
recv_timeout
;
timeout
.
tv_usec
=
0
;
if
(
setsockopt
(
*
socket_
,
SOL_SOCKET
,
SO_RCVTIMEO
,
(
char
*
)
&
timeout
,
sizeof
(
timeout
))
<
0
)
{
spdlog
::
error
(
"setsockopt SO_RCVTIMEO failed"
);
return
-
1
;
}
timeout
.
tv_sec
=
send_timeout
;
if
(
setsockopt
(
*
socket_
,
SOL_SOCKET
,
SO_SNDTIMEO
,
(
char
*
)
&
timeout
,
sizeof
(
timeout
))
<
0
)
{
spdlog
::
error
(
"setsockopt SO_SNDTIMEO failed"
);
return
-
1
;
}
::
freeaddrinfo
(
addrinfo_result
);
::
freeaddrinfo
(
addrinfo_result
);
return
rv
;
return
rv
;
...
...
hi3518/ref-memory.hpp
浏览文件 @
2c0181b7
...
@@ -42,15 +42,15 @@ XM_S32 MaQue_Demo_Mem_setLength(XM_HANDLE handle, XM_U32 len)
...
@@ -42,15 +42,15 @@ XM_S32 MaQue_Demo_Mem_setLength(XM_HANDLE handle, XM_U32 len)
XM_S32
MaQue_Demo_Mem_alloc
(
XM_HANDLE
*
pHandle
,
MaQueMemAllocParam_s
*
pstAllocParam
)
XM_S32
MaQue_Demo_Mem_alloc
(
XM_HANDLE
*
pHandle
,
MaQueMemAllocParam_s
*
pstAllocParam
)
{
{
pthread_mutex_lock
(
&
g_mutexMem
);
DemoMemory_s
*
pstMem
=
NULL
;
DemoMemory_s
*
pstMem
=
NULL
;
pstMem
=
(
DemoMemory_s
*
)
malloc
(
sizeof
(
DemoMemory_s
));
pstMem
=
(
DemoMemory_s
*
)
malloc
(
sizeof
(
DemoMemory_s
));
memset
(
pstMem
,
0
,
sizeof
(
*
pstMem
));
if
(
!
pstMem
)
{
if
(
!
pstMem
)
{
spdlog
::
error
(
"malloc failed!"
);
spdlog
::
error
(
"malloc failed!"
);
pthread_mutex_unlock
(
&
g_mutexMem
);
return
-
1
;
return
-
1
;
}
}
memset
(
pstMem
,
0
,
sizeof
(
*
pstMem
));
pthread_mutex_lock
(
&
g_mutexMem
);
switch
(
pstAllocParam
->
eMemType
)
{
switch
(
pstAllocParam
->
eMemType
)
{
case
MAQUE_MEM_TYPE_VIDEO_ENC
:
case
MAQUE_MEM_TYPE_VIDEO_ENC
:
...
@@ -61,7 +61,6 @@ XM_S32 MaQue_Demo_Mem_alloc(XM_HANDLE *pHandle, MaQueMemAllocParam_s *pstAllocPa
...
@@ -61,7 +61,6 @@ XM_S32 MaQue_Demo_Mem_alloc(XM_HANDLE *pHandle, MaQueMemAllocParam_s *pstAllocPa
XM_U8
*
raw
=
(
XM_U8
*
)
malloc
(
pstAllocParam
->
nBufSize
+
sizeof
(
evpacket_t
));
XM_U8
*
raw
=
(
XM_U8
*
)
malloc
(
pstAllocParam
->
nBufSize
+
sizeof
(
evpacket_t
));
pstMem
->
pBuffer
=
raw
+
sizeof
(
evpacket_t
);
pstMem
->
pBuffer
=
raw
+
sizeof
(
evpacket_t
);
//printf("malloc. raw: %08X, shifted: %08X\n", (uint32_t)raw, (uint32_t)pstMem->pBuffer);
//printf("malloc. raw: %08X, shifted: %08X\n", (uint32_t)raw, (uint32_t)pstMem->pBuffer);
if
(
raw
)
{
if
(
raw
)
{
pstMem
->
index
=
0xff
;
pstMem
->
index
=
0xff
;
pstMem
->
nBufSize
=
pstAllocParam
->
nBufSize
;
pstMem
->
nBufSize
=
pstAllocParam
->
nBufSize
;
...
...
hi3518/smart.cc
浏览文件 @
2c0181b7
...
@@ -12,31 +12,31 @@ extern "C"
...
@@ -12,31 +12,31 @@ extern "C"
static
int
smartCnt
=
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
)
{
//
if(smartCnt > 0) {
smartCnt
--
;
//
smartCnt--;
return
0
;
//
return 0;
}
//
}
smartCnt
=
1000
;
//
smartCnt = 1000;
XM_CHAR
acFile
[
256
]
=
{
0
};
//
XM_CHAR acFile[256] = {0};
FILE
*
pFile
;
//
FILE *pFile;
static
XM_S32
jpeg_cnt
=
0
;
//
static XM_S32 jpeg_cnt = 0;
printf
(
"aClassName[%s] idx = %d, toltal = %d
\n
"
,
pstJpegFrame
->
aClassName
,
pstJpegFrame
->
nIndex
,
pstJpegFrame
->
nToltalJpeg
);
printf
(
"aClassName[%s] idx = %d, toltal = %d
\n
"
,
pstJpegFrame
->
aClassName
,
pstJpegFrame
->
nIndex
,
pstJpegFrame
->
nToltalJpeg
);
if
(
jpeg_cnt
<
30000
)
{
//
if (jpeg_cnt < 30000) {
sprintf
(
acFile
,
"ai/snap_%d.jpg"
,
jpeg_cnt
);
//
sprintf(acFile, "ai/snap_%d.jpg", jpeg_cnt);
pFile
=
fopen
(
acFile
,
"wb"
);
//
pFile = fopen(acFile, "wb");
if
(
pFile
==
NULL
)
{
//
if (pFile == NULL) {
spdlog
::
error
(
"open file err"
);
//
spdlog::error("open file err");
return
XM_FAILURE
;
//
return XM_FAILURE;
}
//
}
fwrite
(
pstJpegFrame
->
pBuffer
,
pstJpegFrame
->
nDataLen
,
1
,
pFile
);
//
fwrite(pstJpegFrame->pBuffer, pstJpegFrame->nDataLen, 1, pFile);
fflush
(
pFile
);
//
fflush(pFile);
fclose
(
pFile
);
//
fclose(pFile);
jpeg_cnt
++
;
//
jpeg_cnt++;
}
//
}
return
XM_SUCCESS
;
return
XM_SUCCESS
;
}
}
...
...
hi3518/utils.hpp
浏览文件 @
2c0181b7
...
@@ -6,6 +6,12 @@
...
@@ -6,6 +6,12 @@
#include <fstream>
#include <fstream>
#include <algorithm>
#include <algorithm>
#include <sys/statvfs.h>
#include <sys/statvfs.h>
#include <mutex>
#include <set>
#include <zmq.h>
#include <string>
#include <spdlog/spdlog.h>
#include <fmt/format.h>
using
namespace
std
;
using
namespace
std
;
using
namespace
jsoncons
;
using
namespace
jsoncons
;
...
@@ -52,8 +58,8 @@ const string kMsgSn = "sn";
...
@@ -52,8 +58,8 @@ const string kMsgSn = "sn";
char
hostArr
[]
=
"192.168.55.104"
;
char
hostArr
[]
=
"192.168.55.104"
;
char
portArr
[]
=
"7123"
;
char
portArr
[]
=
"7123"
;
char
*
host
=
hostArr
,
*
port
=
portArr
;
char
*
host
=
hostArr
,
*
port
=
portArr
;
char
recFilePathArr
[]
=
"/mnt/sd/record/rec.264
"
;
string
recFilePath
=
"/mnt/sd/records/
"
;
c
har
*
recFilePath
=
recFilePathArr
;
c
onst
long
long
TS_2020
=
1577836800000L
;
/// topics
/// topics
string
sub_topic
=
"evcamera/v1.0/request/"
;
string
sub_topic
=
"evcamera/v1.0/request/"
;
...
@@ -79,25 +85,32 @@ bool is_sdcard_avail(char *path = nullptr)
...
@@ -79,25 +85,32 @@ bool is_sdcard_avail(char *path = nullptr)
json
make_default_config
(){
json
make_default_config
(){
return
R"(
return
R"(
{
{
"
sn": "A000000Z
",
"
vgw":"evcloudsvc.ilabservice.cloud:7123
",
"
vgw": "192.168.55.104:712
3",
"
mqtt":"admin:vJ3zHqWrHbrqxVMT@evcloudsvc.ilabservice.cloud:1188
3",
"
mqtt": "admin:vJ3zHqWrHbrqxVMT@evcloudsvc.ilabservice.cloud:11883
",
"
upload":"evcloudsvc.ilabservice.cloud:10010
",
"
upload": "evcloudsvc.ilabservice.cloud:10008",
"
features":{
"features": {
"push":0,
"motion":
{
"motion":{
"enable
":
1,
"enable
d":
1,
"region":
{"min": [0.35,0.35], "max": [0.65, 0.65]},
"region":
{
"level": 3
"maxX":1,
}
,
"maxY":1
,
"record":{
"minX":0,
"enable": 1,
"minY":0
"interval": 300
,
}
,
"
duration": 24
"
level":3
},
},
"recordLen":120,
"ai":{
"ai":{
"enable": 1,
"enabled":1,
"faceThresh": 0.6,
"faceThresh":0.75,
"humanThresh": 0.6
"humanThresh":0.63,
"region":{
"maxX":1,
"maxY":1,
"minX":0,
"minY":0
}
}
}
}
}
}
}
...
@@ -119,6 +132,7 @@ void get_mac_addr(char *buf, char *intf = nullptr){
...
@@ -119,6 +132,7 @@ void get_mac_addr(char *buf, char *intf = nullptr){
*
(
buf
+
i
++
)
=
::
toupper
(
k
);
*
(
buf
+
i
++
)
=
::
toupper
(
k
);
}
}
}
}
*
(
buf
+
i
)
=
0
;
}
}
bool
get_sdcard_megabytes
(
uint64_t
&
total
,
uint64_t
&
free
,
char
*
path
=
nullptr
)
bool
get_sdcard_megabytes
(
uint64_t
&
total
,
uint64_t
&
free
,
char
*
path
=
nullptr
)
...
@@ -141,6 +155,228 @@ bool get_sdcard_megabytes(uint64_t &total, uint64_t &free, char* path = nullptr)
...
@@ -141,6 +155,228 @@ bool get_sdcard_megabytes(uint64_t &total, uint64_t &free, char* path = nullptr)
return
true
;
return
true
;
}
}
template
<
typename
T
>
using
cb_remove_elem
=
void
(
*
)(
T
elem
);
template
<
typename
TN
>
class
OrderedList
{
private
:
set
<
TN
>
list_
;
size_t
maxSize
;
mutex
mut
;
TN
oldestTs
;
cb_remove_elem
<
TN
>
fn_remove
;
unsigned
long
cntInsert
=
0
;
public
:
OrderedList
()
=
delete
;
OrderedList
(
ssize_t
maxSize
,
cb_remove_elem
<
TN
>
fn_remove
)
:
maxSize
(
maxSize
),
fn_remove
(
fn_remove
){}
void
insert
(
TN
elem
,
cb_remove_elem
<
TN
>
fn
=
nullptr
)
{
// list_.insert(lower_bound(list_.begin(), list_.end(), elem), elem);
if
(
cntInsert
%
10
==
0
)
{
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
);
}
++
cntInsert
;
if
(
elem
<
oldestTs
){
if
(
fn
!=
nullptr
){
(
*
fn
)(
elem
);
}
else
if
(
fn_remove
!=
nullptr
){
(
*
fn_remove
)(
elem
);
}
return
;
}
if
(
list_
.
size
()
==
0
)
{
list_
.
insert
(
list_
.
begin
(),
elem
);
return
;
}
auto
itr
=
list_
.
rbegin
();
for
(;
itr
!=
list_
.
rend
();
itr
++
)
{
if
(
*
itr
<
elem
)
{
break
;
}
}
if
(
itr
==
list_
.
rbegin
()
)
{
list_
.
insert
(
list_
.
end
(),
elem
);
}
else
{
list_
.
insert
(
itr
.
base
(),
elem
);
}
if
(
list_
.
size
()
>
maxSize
)
{
lock_guard
<
mutex
>
lg
(
mut
);
auto
ts
=
*
(
list_
.
begin
());
list_
.
erase
(
list_
.
begin
());
if
(
fn
!=
nullptr
){
(
*
fn
)(
ts
);
}
else
if
(
fn_remove
!=
nullptr
){
(
*
fn_remove
)(
ts
);
}
else
{
// no callback available
}
// auto baseName = videoFileTs2Name(ts);
// fs::path fname(this->urlOut + "/" + baseName + ".mp4");
// fs::remove(fname);
}
}
set
<
TN
>
findByRange
(
TN
tss
,
TN
tse
,
TN
&
offsetS
,
TN
&
offsetE
){
set
<
TN
>
ret
;
lock_guard
<
mutex
>
lg
(
mut
);
if
(
list_
.
size
()
==
0
)
{
return
ret
;
}
TN
first
=
*
(
list_
.
begin
());
auto
_it
=
list_
.
end
();
TN
end
=
*
(
--
_it
);
if
(
tse
<
first
||
tss
>
end
)
{
spdlog
::
info
(
"range requested ({}, {}) is not in range existed ({}, {})."
,
tss
,
tse
,
first
,
end
);
return
ret
;
}
first
=
end
=
0
;
int
found
=
0
;
TN
last
=
0
;
auto
itr
=
list_
.
rbegin
();
for
(;
itr
!=
list_
.
rend
();
itr
++
)
{
if
(
*
itr
>
tse
)
{
continue
;
}
if
(
*
itr
<=
tse
)
{
if
(
found
!=
1
)
{
spdlog
::
info
(
"
\t
matched : {}, s:{}, e:{}"
,
*
itr
,
tss
,
tse
);
found
=
1
;
// check the end offset, not guaranteed
if
(
itr
!=
list_
.
rbegin
()){
auto
t
=
itr
;
last
=
*
(
--
t
);
}
}
ret
.
insert
(
*
itr
);
if
(
tss
>=
*
itr
)
{
break
;
}
}
}
if
(
found
==
1
)
{
auto
itr
=
ret
.
begin
();
offsetS
=
tss
-
*
itr
;
if
(
last
!=
0
)
{
offsetE
=
last
-
tse
;
}
}
return
ret
;
}
};
/// returns negtive for failure, otherwise success
int
setupDealer
(
void
**
ctx
,
void
**
s
,
string
ident
,
string
addr
,
int
sndQS
=
0
,
int
timeoutMs
=
-
1
)
{
int
ret
=
0
;
*
ctx
=
zmq_ctx_new
();
*
s
=
zmq_socket
(
*
ctx
,
ZMQ_DEALER
);
ret
=
1
;
zmq_setsockopt
(
*
s
,
ZMQ_TCP_KEEPALIVE
,
&
ret
,
sizeof
(
ret
));
ret
=
20
;
zmq_setsockopt
(
*
s
,
ZMQ_TCP_KEEPALIVE_IDLE
,
&
ret
,
sizeof
(
ret
));
zmq_setsockopt
(
*
s
,
ZMQ_TCP_KEEPALIVE_INTVL
,
&
ret
,
sizeof
(
ret
));
ret
=
2
;
zmq_setsockopt
(
*
s
,
ZMQ_TCP_KEEPALIVE_CNT
,
&
ret
,
sizeof
(
ret
));
if
(
sndQS
!=
0
){
zmq_setsockopt
(
*
s
,
ZMQ_SNDHWM
,
&
sndQS
,
sizeof
(
sndQS
));
}
if
(
timeoutMs
!=
0
)
{
if
(
timeoutMs
==
-
1
)
{
timeoutMs
=
5
*
1000
;
}
zmq_setsockopt
(
*
s
,
ZMQ_RCVTIMEO
,
&
timeoutMs
,
sizeof
(
timeoutMs
));
}
ret
=
zmq_setsockopt
(
*
s
,
ZMQ_IDENTITY
,
ident
.
c_str
(),
ident
.
size
());
if
(
ret
<
0
)
{
zmq_close
(
*
s
);
zmq_ctx_destroy
(
*
ctx
);
spdlog
::
debug
(
"{} failed setsockopts ZMQ_ROUTING_ID to {}: {}"
,
ident
,
addr
,
zmq_strerror
(
zmq_errno
()));
}
else
{
ret
=
zmq_connect
(
*
s
,
addr
.
c_str
());
if
(
ret
!=
0
)
{
zmq_close
(
*
s
);
zmq_ctx_destroy
(
*
ctx
);
spdlog
::
error
(
"{} failed connect dealer: {}"
,
ident
,
addr
);
}
}
return
ret
;
}
int
setupRouter
(
void
**
ctx
,
void
**
s
,
string
addr
,
int
rcvQS
=
0
){
int
ret
=
0
;
*
ctx
=
zmq_ctx_new
();
*
s
=
zmq_socket
(
*
ctx
,
ZMQ_ROUTER
);
ret
=
1
;
zmq_setsockopt
(
*
s
,
ZMQ_TCP_KEEPALIVE
,
&
ret
,
sizeof
(
ret
));
ret
=
5
;
zmq_setsockopt
(
*
s
,
ZMQ_TCP_KEEPALIVE_IDLE
,
&
ret
,
sizeof
(
ret
));
zmq_setsockopt
(
*
s
,
ZMQ_TCP_KEEPALIVE_INTVL
,
&
ret
,
sizeof
(
ret
));
ret
=
2
;
zmq_setsockopt
(
*
s
,
ZMQ_TCP_KEEPALIVE_CNT
,
&
ret
,
sizeof
(
ret
));
if
(
rcvQS
!=
0
)
{
zmq_setsockopt
(
*
s
,
ZMQ_RCVHWM
,
&
rcvQS
,
sizeof
(
rcvQS
));
}
ret
=
zmq_bind
(
*
s
,
addr
.
c_str
());
if
(
ret
<
0
)
{
spdlog
::
debug
(
"failed to bind zmq at {} for reason: {}, retrying load configuration..."
,
addr
,
zmq_strerror
(
zmq_errno
()));
}
return
ret
;
}
int
z_recv_multiple
(
void
*
s
,
vector
<
uint8_t
>
&
buf
,
int
&
frames
)
{
int64_t
more
=
1
;
size_t
more_size
=
sizeof
(
more
);
int
ret
=
0
;
int
cnt
=
0
;
while
(
more
>
0
)
{
cnt
++
;
zmq_msg_t
msg
;
ret
=
zmq_msg_init
(
&
msg
);
if
(
ret
<
0
)
{
spdlog
::
debug
(
"failed to receive multiple msg on zmq_msg_init: {}"
,
zmq_strerror
(
zmq_errno
()));
break
;
}
ret
=
zmq_msg_recv
(
&
msg
,
s
,
0
);
if
(
ret
<
0
)
{
spdlog
::
debug
(
"z_recv_multiple: {}"
,
zmq_strerror
(
zmq_errno
()));
break
;
}
buf
.
insert
(
buf
.
end
(),
(
uint8_t
*
)
zmq_msg_data
(
&
msg
),
(
uint8_t
*
)
zmq_msg_data
(
&
msg
)
+
ret
);
zmq_msg_close
(
&
msg
);
ret
=
zmq_getsockopt
(
s
,
ZMQ_RCVMORE
,
&
more
,
&
more_size
);
if
(
ret
<
0
)
{
spdlog
::
debug
(
"z_recv_multiple: {}"
,
zmq_strerror
(
zmq_errno
()));
break
;
}
}
if
(
ret
<
0
||
(
frames
!=
0
&&
cnt
!=
frames
))
{
spdlog
::
error
(
"failed to recv msg: {}"
,
ret
<
0
?
zmq_strerror
(
ret
)
:
"invalid frames"
);
return
-
1
;
}
else
{
frames
=
cnt
;
}
return
0
;
}
}
}
...
...
server/CMakeLists.txt
浏览文件 @
2c0181b7
...
@@ -11,16 +11,16 @@ endif()
...
@@ -11,16 +11,16 @@ endif()
set
(
COMM_INC_DIR
${
VENDOR
}
/shared/include
${
VENDOR
}
/x64/include
${
SHAREDINC
}
)
set
(
COMM_INC_DIR
${
VENDOR
}
/shared/include
${
VENDOR
}
/x64/include
${
SHAREDINC
}
)
set
(
COMMON_LIB_DIR
${
VENDOR
}
/shared/lib
${
VENDOR
}
/x64/lib
)
set
(
COMMON_LIB_DIR
${
VENDOR
}
/shared/lib
${
VENDOR
}
/x64/lib
)
# list(APPEND COMMON_LIBS avformat avdevice avcodec swscale avfilter avutil swresample lzma x264 fmt uv pthread dl m z)
# list(APPEND COMMON_LIBS avformat avdevice avcodec swscale avfilter avutil swresample lzma x264 fmt uv pthread dl m z)
list
(
APPEND COMM_LIBS fmt
uv
pthread dl m z
)
list
(
APPEND COMM_LIBS fmt
zmq
pthread dl m z
)
list
(
APPEND VGW_LIBS avformat avcodec swscale avutil swresample lzma x264
)
list
(
APPEND VGW_LIBS avformat avcodec swscale avutil swresample lzma x264
)
include_directories
(
${
CMAKE_SOURCE_DIR
}
${
PROJECT_SOURCE_DIR
}
${
COMM_INC_DIR
}
)
include_directories
(
${
CMAKE_SOURCE_DIR
}
${
PROJECT_SOURCE_DIR
}
${
COMM_INC_DIR
}
)
link_directories
(
${
COMMON_LIB_DIR
}
)
link_directories
(
${
COMMON_LIB_DIR
}
)
#add_library(mime STATIC mime.c)
#add_library(util STATIC utils.cpp)
add_executable
(
vgw videogateway.cc
)
add_executable
(
vgw videogateway.cc
)
target_link_libraries
(
vgw PUBLIC
${
VGW_LIBS
}
${
COMM_LIBS
}
)
target_link_libraries
(
vgw PUBLIC
${
VGW_LIBS
}
${
COMM_LIBS
}
)
add_executable
(
agent agent.cc
)
# add_executable(test_mqtt test_mqtt_rd.cc)
target_link_libraries
(
agent PUBLIC paho-mqtt3a
${
COMM_LIBS
}
)
# target_link_libraries(test_mqtt PUBLIC ${COMM_LIBS})
# add_executable(agent agent.cc)
# target_link_libraries(agent PUBLIC paho-mqtt3a ${COMM_LIBS})
server/videogateway.cc
浏览文件 @
2c0181b7
#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdlib.h>
#include <string.h>
#include <string.h>
#include <uv.h>
#include <spdlog/spdlog.h>
#include <spdlog/spdlog.h>
#include <evpacket.h>
#include <evpacket.h>
#include <sys/time.h>
#include <sys/time.h>
#include <mutex>
#include <mutex>
#include <map>
#include <map>
#include <queue>
#include <queue>
#include <zmq.h>
extern
"C"
extern
"C"
{
{
...
@@ -23,24 +23,12 @@ using namespace std;
...
@@ -23,24 +23,12 @@ using namespace std;
#define MAX_FRAME_SIZE 500000
#define MAX_FRAME_SIZE 500000
#define MAX_RETRY_PUSH_INTV 450
#define MAX_RETRY_PUSH_INTV 450
string
darwinUrl
=
"rtsp://evcloud.ilabservice.cloud:554/"
;
string
darwinUrl
=
"rtsp://evcloud
svc
.ilabservice.cloud:554/"
;
string
bindPort
=
"7123"
;
string
bindPort
=
"7123"
;
string
bindAddr
=
"0.0.0.0"
;
string
bindAddr
=
"0.0.0.0"
;
uv_loop_t
*
loop
;
struct
sockaddr_in
addr
;
typedef
struct
{
uv_write_t
req
;
uv_buf_t
buf
;
}
write_req_t
;
typedef
struct
{
typedef
struct
{
uv_tcp_t
*
handle
;
evpacket_t
hdr
;
evpacket_t
hdr
;
evpacket_video_t
vpara
;
char
*
buf
;
unsigned
int
size
;
int
state
;
// 0 - unkown; 1 - receiving header; 2 - header ready, receiving body; 3 - body ready, processing
int
state
;
// 0 - unkown; 1 - receiving header; 2 - header ready, receiving body; 3 - body ready, processing
AVFormatContext
*
pAvCtx
;
AVFormatContext
*
pAvCtx
;
uint64_t
packetId
;
uint64_t
packetId
;
...
@@ -49,42 +37,9 @@ typedef struct {
...
@@ -49,42 +37,9 @@ typedef struct {
int64_t
pts
;
int64_t
pts
;
}
packet_processor_t
;
}
packet_processor_t
;
typedef
struct
{
uv_tcp_t
handle
;
packet_processor_t
processor
;
}
packet_client
;
typedef
struct
dataque_frame_t
{
char
devsn
[
12
];
int
codec
;
int
width
;
int
height
;
int
size
;
uint8_t
*
buf
;
}
*
dataque_frame_ptr_t
;
typedef
struct
devinfo_t
{
string
devsn
;
int
state
;
// 0 - init, 1 - running, 2 - send err, 3 - request close, 4 - ready to close
queue
<
dataque_frame_t
>
*
que
;
AVFormatContext
*
ctx
;
devinfo_t
(
string
devsn
,
queue
<
dataque_frame_t
>
*
que
,
AVFormatContext
*
ctx
)
:
devsn
(
devsn
),
que
(
que
),
ctx
(
ctx
)
{}
~
devinfo_t
()
{
// TODO: for each item in que, delete them
if
(
que
)
delete
que
;
if
(
ctx
)
avformat_free_context
(
ctx
);
}
}
*
devinfo_ptr_t
;
AVIOInterruptCB
int_cb
;
AVIOInterruptCB
int_cb
;
map
<
string
,
packet_client
*>
devConnMap
;
bool
is_big_endian
(
void
)
bool
is_big_endian
(
void
)
{
{
union
{
union
{
...
@@ -95,57 +50,6 @@ bool is_big_endian(void)
...
@@ -95,57 +50,6 @@ bool is_big_endian(void)
return
bint
.
c
[
0
]
==
1
;
return
bint
.
c
[
0
]
==
1
;
}
}
void
free_write_req
(
uv_write_t
*
req
)
{
write_req_t
*
wr
=
(
write_req_t
*
)
req
;
free
(
wr
->
buf
.
base
);
free
(
wr
);
}
void
alloc_buffer
(
uv_handle_t
*
handle
,
size_t
suggested_size
,
uv_buf_t
*
buf
)
{
buf
->
base
=
(
char
*
)
malloc
(
suggested_size
);
buf
->
len
=
suggested_size
;
}
void
on_closed
(
uv_handle_t
*
handle
)
{
packet_client
*
pclient
=
(
packet_client
*
)
handle
;
spdlog
::
error
(
"closing client"
);
// TODO:
if
(
pclient
->
processor
.
buf
)
{
free
(
pclient
->
processor
.
buf
);
}
if
(
pclient
->
processor
.
pAvCtx
)
{
if
(
pclient
->
processor
.
pAvCtx
->
pb
)
{
avio_closep
(
&
pclient
->
processor
.
pAvCtx
->
pb
);
}
avformat_free_context
(
pclient
->
processor
.
pAvCtx
);
}
if
(
pclient
->
processor
.
hdr
.
meta
.
sn
[
0
]
!=
0
)
{
/// NOTES: avoid corrupted stacks
pclient
->
processor
.
hdr
.
meta
.
sn
[
9
]
=
0
;
string
sn_
=
string
(
pclient
->
processor
.
hdr
.
meta
.
sn
);
if
(
devConnMap
.
count
(
sn_
)
!=
0
)
{
devConnMap
.
erase
(
sn_
);
}
}
pclient
->
processor
.
pAvCtx
=
nullptr
;
delete
pclient
;
}
void
on_written
(
uv_write_t
*
req
,
int
status
)
{
if
(
status
)
{
spdlog
::
error
(
"Write error {}"
,
uv_strerror
(
status
));
}
free_write_req
(
req
);
}
void
debugHex
(
char
*
buf
,
int
len
)
void
debugHex
(
char
*
buf
,
int
len
)
{
{
int
i
=
0
;
int
i
=
0
;
...
@@ -202,21 +106,14 @@ AVFormatContext *rtsp_init(string rtsp_url, int codec, int height, int width, in
...
@@ -202,21 +106,14 @@ AVFormatContext *rtsp_init(string rtsp_url, int codec, int height, int width, in
out_codecpar
->
format
=
AV_PIX_FMT_YUV420P
;
out_codecpar
->
format
=
AV_PIX_FMT_YUV420P
;
//int_cb = {av_callback, nullptr};
//int_cb = {av_callback, nullptr};
pAVFormatRemux
->
interrupt_callback
=
int_cb
;
//pAVFormatRemux->interrupt_callback = int_cb;
/// NOTES: avio_open2 is not needed below, since we directly constructed the avformat ctx
// ret = avio_open2(&pAVFormatRemux->pb, rtsp_url.c_str(), AVIO_FLAG_WRITE, nullptr/*&pAVFormatRemux->interrupt_callback*/, &pOptsRemux);
// /// TODO: not supported protocol
// if(ret <0) {
// spdlog::error("failed to open2: {}: {}", rtsp_url, av_err2str(ret));
// if(rc) *rc = ret;
// return nullptr;
// }
ret
=
avformat_write_header
(
pAVFormatRemux
,
&
pOptsRemux
);
ret
=
avformat_write_header
(
pAVFormatRemux
,
&
pOptsRemux
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
{
spdlog
::
error
(
"failed to writeheader: {}"
,
rtsp_url
);
spdlog
::
error
(
"failed to writeheader: {}"
,
rtsp_url
);
if
(
rc
)
*
rc
=
ret
;
if
(
rc
)
*
rc
=
ret
;
return
nullptr
;
return
nullptr
;
}
}
spdlog
::
info
(
"success connect to darwin {}"
,
rtsp_url
);
av_dict_free
(
&
pOptsRemux
);
av_dict_free
(
&
pOptsRemux
);
...
@@ -226,7 +123,7 @@ AVFormatContext *rtsp_init(string rtsp_url, int codec, int height, int width, in
...
@@ -226,7 +123,7 @@ AVFormatContext *rtsp_init(string rtsp_url, int codec, int height, int width, in
int
write_packet
(
packet_processor_t
*
processor
,
char
*
data
,
int
len
)
int
write_packet
(
packet_processor_t
*
processor
,
char
*
data
,
int
len
)
{
{
AVFormatContext
*
ctx
=
nullptr
;
AVFormatContext
*
ctx
=
nullptr
;
if
(
processor
==
nullptr
||
(
ctx
=
processor
->
pAvCtx
)
==
nullptr
||
ctx
->
streams
==
nullptr
||
*
ctx
->
streams
==
nullptr
)
{
if
(
processor
==
nullptr
||
(
ctx
=
processor
->
pAvCtx
)
==
nullptr
||
ctx
->
streams
==
nullptr
||
*
(
ctx
->
streams
)
==
nullptr
)
{
spdlog
::
error
(
"no avformatctx or stream available for write"
);
spdlog
::
error
(
"no avformatctx or stream available for write"
);
return
-
1
;
return
-
1
;
}
}
...
@@ -240,7 +137,15 @@ int write_packet(packet_processor_t *processor, char *data, int len)
...
@@ -240,7 +137,15 @@ int write_packet(packet_processor_t *processor, char *data, int len)
pkt
.
data
=
(
uint8_t
*
)
data
;
pkt
.
data
=
(
uint8_t
*
)
data
;
pkt
.
size
=
len
;
pkt
.
size
=
len
;
AVRational
time_base
;
AVRational
time_base
;
time_base
.
den
=
processor
->
vpara
.
fps
;
// this is fps
char
*
fps
=
getenv
(
"FPS"
);
if
(
processor
->
hdr
.
vpara
.
fps
>
0
&&
processor
->
hdr
.
vpara
.
fps
<
100
){
time_base
.
den
=
processor
->
hdr
.
vpara
.
fps
;
}
else
{
time_base
.
den
=
15
;
}
if
(
fps
){
time_base
.
den
=
atoi
(
fps
);
}
time_base
.
num
=
1
;
time_base
.
num
=
1
;
pkt
.
dts
=
av_rescale_q_rnd
(
++
processor
->
pts
,
time_base
,
out_stream
->
time_base
,
(
AV_ROUND_NEAR_INF
|
AV_ROUND_PASS_MINMAX
));
pkt
.
dts
=
av_rescale_q_rnd
(
++
processor
->
pts
,
time_base
,
out_stream
->
time_base
,
(
AV_ROUND_NEAR_INF
|
AV_ROUND_PASS_MINMAX
));
pkt
.
pts
=
av_rescale_q
(
processor
->
pts
,
time_base
,
out_stream
->
time_base
);
pkt
.
pts
=
av_rescale_q
(
processor
->
pts
,
time_base
,
out_stream
->
time_base
);
...
@@ -249,327 +154,107 @@ int write_packet(packet_processor_t *processor, char *data, int len)
...
@@ -249,327 +154,107 @@ int write_packet(packet_processor_t *processor, char *data, int len)
ret
=
av_write_frame
(
ctx
,
&
pkt
);
ret
=
av_write_frame
(
ctx
,
&
pkt
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
{
fprintf
(
stderr
,
"Error muxing packet
\n
"
);
spdlog
::
error
(
"Error muxing packet: {}"
,
av_err2str
(
ret
)
);
}
}
//av_packet_unref(&pkt);
//av_packet_unref(&pkt);
return
ret
;
return
ret
;
}
}
void
on_read
(
uv_stream_t
*
client
,
ssize_t
nread
,
const
uv_buf_t
*
buf
)
{
packet_client
*
pclient
=
(
packet_client
*
)
client
;
char
*
data
=
buf
->
base
;
lock_guard
<
mutex
>
lk
(
pclient
->
processor
.
mut
);
if
(
nread
>
0
)
{
evpacket_ptr_t
pkt
=
(
evpacket_ptr_t
)
data
;
if
(
nread
>=
2
&&
pkt
->
meta
.
magic
[
0
]
==
(
char
)
0xBE
&&
pkt
->
meta
.
magic
[
1
]
==
(
char
)
0xEF
)
{
// new packet
pclient
->
processor
.
size
=
0
;
pclient
->
processor
.
state
=
1
;
// rcv header
}
while
(
pclient
->
processor
.
state
!=
0
&&
nread
>
0
)
{
int
setupRouter
(
void
**
ctx
,
void
**
s
,
string
addr
,
int
rcvQS
=
0
){
switch
(
pclient
->
processor
.
state
)
{
int
ret
=
0
;
// rcv header
*
ctx
=
zmq_ctx_new
();
case
1
:
{
*
s
=
zmq_socket
(
*
ctx
,
ZMQ_ROUTER
);
if
(
nread
+
pclient
->
processor
.
size
>=
sizeof
(
evpacket_t
))
{
ret
=
1
;
// whole header ready
zmq_setsockopt
(
*
s
,
ZMQ_TCP_KEEPALIVE
,
&
ret
,
sizeof
(
ret
));
auto
delta
=
sizeof
(
evpacket_t
)
-
pclient
->
processor
.
size
;
ret
=
5
;
memcpy
(
&
pclient
->
processor
.
hdr
+
pclient
->
processor
.
size
,
data
,
delta
);
zmq_setsockopt
(
*
s
,
ZMQ_TCP_KEEPALIVE_IDLE
,
&
ret
,
sizeof
(
ret
));
/// NOTES: since both ends use little-endian, we don't apply ntohl, ntohs to save clocks
zmq_setsockopt
(
*
s
,
ZMQ_TCP_KEEPALIVE_INTVL
,
&
ret
,
sizeof
(
ret
));
//debugHex((char*)&pclient->processor.hdr, 64);
ret
=
2
;
zmq_setsockopt
(
*
s
,
ZMQ_TCP_KEEPALIVE_CNT
,
&
ret
,
sizeof
(
ret
));
/// check crc first
if
(
rcvQS
!=
0
)
{
uint16_t
crc
=
pclient
->
processor
.
hdr
.
meta
.
crc
;
zmq_setsockopt
(
*
s
,
ZMQ_RCVHWM
,
&
rcvQS
,
sizeof
(
rcvQS
));
pclient
->
processor
.
hdr
.
meta
.
crc
=
0
;
}
uint16_t
crc_
=
crc16
((
unsigned
char
*
)
&
pclient
->
processor
.
hdr
,
sizeof
(
evpacket_t
));
ret
=
zmq_bind
(
*
s
,
addr
.
c_str
());
if
(
crc
!=
crc_
||
pclient
->
processor
.
hdr
.
meta
.
magic
[
0
]
!=
(
char
)
0xBE
||
pclient
->
processor
.
hdr
.
meta
.
magic
[
1
]
!=
(
char
)
0xEF
||
pclient
->
processor
.
hdr
.
length
==
0
)
{
if
(
ret
<
0
)
{
printf
(
"invalid magic/len/cid. hdr: %02hhX%02hhX, len:%d, cid:%lu, sid:%lu. crc:%04hhX, crcc:%04hhX. BUG!!!
\n
"
,
pclient
->
processor
.
hdr
.
meta
.
magic
[
0
],
pclient
->
processor
.
hdr
.
meta
.
magic
[
1
],
pclient
->
processor
.
hdr
.
length
,
spdlog
::
debug
(
"failed to bind zmq at {} for reason: {}, retrying load configuration..."
,
addr
,
zmq_strerror
(
zmq_errno
()));
pclient
->
processor
.
hdr
.
meta
.
packet_id
,
pclient
->
processor
.
packetId
,
crc
,
crc_
);
}
pclient
->
processor
.
size
=
0
;
return
ret
;
pclient
->
processor
.
state
=
1
;
}
nread
=
0
;
continue
;
int
z_recv_multiple
(
void
*
s
,
vector
<
uint8_t
>
&
buf
,
vector
<
int
>&
frameIdx
)
{
}
int64_t
more
=
1
;
else
{
size_t
more_size
=
sizeof
(
more
);
// printf("new packet: %02hhX%02hhX, len: %u, cid:%lu, sid:%lu\n", pclient->processor.hdr.meta.magic[0], pclient->processor.hdr.meta.magic[1], pclient->processor.hdr.length, pclient->processor.hdr.meta.packet_id,pclient->processor.packetId);
int
ret
=
0
;
}
int
cnt
=
0
;
while
(
more
>
0
)
{
/// check packetid
cnt
++
;
if
(
pclient
->
processor
.
packetId
==
0
)
{
zmq_msg_t
msg
;
pclient
->
processor
.
packetId
=
pclient
->
processor
.
hdr
.
meta
.
packet_id
;
ret
=
zmq_msg_init
(
&
msg
);
}
if
(
ret
<
0
)
{
else
{
spdlog
::
debug
(
"failed to receive multiple msg on zmq_msg_init: {}"
,
zmq_strerror
(
zmq_errno
()));
/// ignore too large packets
if
(
/*pclient->processor.hdr.meta.packet_id <= pclient->processor.packetId ||*/
pclient
->
processor
.
hdr
.
length
>=
MAX_FRAME_SIZE
)
{
spdlog
::
error
(
"invalid packetId or len, ignored. len: {}, server:{}, client:{}"
,
pclient
->
processor
.
hdr
.
length
,
pclient
->
processor
.
packetId
,
pclient
->
processor
.
hdr
.
meta
.
packet_id
);
pclient
->
processor
.
size
=
0
;
pclient
->
processor
.
state
=
1
;
nread
=
0
;
continue
;
}
}
pclient
->
processor
.
buf
=
(
char
*
)
malloc
(
pclient
->
processor
.
hdr
.
length
);
if
(
pclient
->
processor
.
buf
==
nullptr
)
{
spdlog
::
error
(
"memroy issues {}:{}"
,
__FILE__
,
__LINE__
);
pclient
->
processor
.
size
=
0
;
pclient
->
processor
.
state
=
1
;
nread
=
0
;
continue
;
}
/// reconnect every 30s
if
(
pclient
->
processor
.
pAvCtx
==
nullptr
&&
(
pclient
->
processor
.
failedCnt
++
%
MAX_RETRY_PUSH_INTV
==
0
))
{
spdlog
::
info
(
"device sn: {}"
,
pclient
->
processor
.
hdr
.
meta
.
sn
);
int
rc
=
0
;
pclient
->
processor
.
pAvCtx
=
rtsp_init
(
darwinUrl
+
string
(
pclient
->
processor
.
hdr
.
meta
.
sn
),
AV_CODEC_ID_H264
,
pclient
->
processor
.
hdr
.
vpara
.
res
.
height
,
pclient
->
processor
.
hdr
.
vpara
.
res
.
width
,
&
rc
);
if
(
pclient
->
processor
.
pAvCtx
==
nullptr
)
{
spdlog
::
error
(
"failed connect to rtsp server {}: {}"
,
darwinUrl
,
av_err2str
(
rc
));
}
else
{
pclient
->
processor
.
failedCnt
=
0
;
string
sn_
=
string
(
pclient
->
processor
.
hdr
.
meta
.
sn
);
if
(
devConnMap
.
count
(
sn_
)
==
0
)
{
devConnMap
[
sn_
]
=
pclient
;
}
}
}
/// copy vpara
if
(
pclient
->
processor
.
vpara
.
fps
==
0
)
{
pclient
->
processor
.
vpara
=
pclient
->
processor
.
hdr
.
vpara
;
}
nread
-=
delta
;
data
+=
delta
;
pclient
->
processor
.
size
=
0
;
pclient
->
processor
.
state
=
2
;
// header ready. rcv body
}
else
{
// small header
memcpy
(
&
pclient
->
processor
.
hdr
+
pclient
->
processor
.
size
,
data
,
nread
);
//data += nread;
pclient
->
processor
.
size
+=
nread
;
nread
=
0
;
if
(
pclient
->
processor
.
size
>=
2
&&
(
pclient
->
processor
.
hdr
.
meta
.
magic
[
0
]
!=
(
char
)
0xBE
||
pclient
->
processor
.
hdr
.
meta
.
magic
[
1
]
!=
(
char
)
0xEF
))
{
printf
(
"invalid packet header: %02hhX%02hhX. BUG!!! %s:%d
\n
"
,
pclient
->
processor
.
hdr
.
meta
.
magic
[
0
],
pclient
->
processor
.
hdr
.
meta
.
magic
[
1
],
__FILE__
,
__LINE__
);
pclient
->
processor
.
size
=
0
;
pclient
->
processor
.
state
=
1
;
nread
=
0
;
continue
;
}
// state remains in rcv header
spdlog
::
debug
(
"small header. size:{}"
,
pclient
->
processor
.
size
);
}
}
break
;
case
2
:
{
// full body
if
(
nread
+
pclient
->
processor
.
size
>=
pclient
->
processor
.
hdr
.
length
)
{
auto
delta
=
pclient
->
processor
.
hdr
.
length
-
pclient
->
processor
.
size
;
memcpy
(
pclient
->
processor
.
buf
+
pclient
->
processor
.
size
,
data
,
delta
);
nread
-=
delta
;
data
+=
delta
;
// TODO: handle body dispatch
// spdlog::debug("TODO: full body got. left for next header: {}", nread);
if
(
pclient
->
processor
.
pAvCtx
!=
nullptr
)
{
auto
ret
=
write_packet
(
&
pclient
->
processor
,
pclient
->
processor
.
buf
,
pclient
->
processor
.
hdr
.
length
);
pclient
->
processor
.
packetId
=
pclient
->
processor
.
hdr
.
meta
.
packet_id
;
if
(
ret
<
0
)
{
spdlog
::
error
(
"failed to send packet"
);
// reset hand reconnect
if
(
pclient
->
processor
.
pAvCtx
&&
pclient
->
processor
.
pAvCtx
->
pb
)
{
avio_closep
(
&
pclient
->
processor
.
pAvCtx
->
pb
);
}
if
(
pclient
->
processor
.
pAvCtx
)
{
avformat_free_context
(
pclient
->
processor
.
pAvCtx
);
}
pclient
->
processor
.
pAvCtx
=
nullptr
;
}
}
/// clear instance-local buffer
free
(
pclient
->
processor
.
buf
);
pclient
->
processor
.
buf
=
nullptr
;
// /// response two bytes
// write_req_t *req = (write_req_t*) malloc(sizeof(write_req_t));
// char *res= (char*)malloc(2);
// res[0] = (char)0xDE;
// res[1] = (char)0xAD;
// req->buf = uv_buf_init(res, 2);
// uv_write((uv_write_t*) req, client, &req->buf, 1, on_written);
// next
pclient
->
processor
.
state
=
1
;
pclient
->
processor
.
size
=
0
;
}
else
{
//TODO: handle buf. <<NEED BUGFIX HERE>>
if
(
pclient
->
processor
.
buf
==
nullptr
)
{
spdlog
::
error
(
"error state {} {}"
,
__FILE__
,
__LINE__
);
exit
(
1
);
}
memcpy
(
pclient
->
processor
.
buf
+
pclient
->
processor
.
size
,
data
,
nread
);
pclient
->
processor
.
size
+=
nread
;
nread
=
0
;
//spdlog::debug("small body. size:{}", pclient->processor.size);
}
}
break
;
break
;
case
0
:
{
}
// TODO: none
ret
=
zmq_recvmsg
(
s
,
&
msg
,
0
);
spdlog
::
warn
(
"should be here state=0"
);
if
(
ret
<
0
)
{
// force to waiting for header
spdlog
::
debug
(
"z_recv_multiple: {}"
,
zmq_strerror
(
zmq_errno
()));
pclient
->
processor
.
state
=
1
;
nread
=
0
;
}
break
;
break
;
default:
{
}
spdlog
::
warn
(
"should be here state=none"
);
buf
.
insert
(
buf
.
end
(),
(
uint8_t
*
)
zmq_msg_data
(
&
msg
),
(
uint8_t
*
)
zmq_msg_data
(
&
msg
)
+
ret
);
// TODO: close and free resources
// spdlog::info("buff size: {}", buf.size());
uv_close
((
uv_handle_t
*
)
client
,
on_closed
);
frameIdx
.
push_back
(
buf
.
size
());
}
zmq_msg_close
(
&
msg
);
ret
=
zmq_getsockopt
(
s
,
ZMQ_RCVMORE
,
&
more
,
&
more_size
);
if
(
ret
<
0
)
{
spdlog
::
debug
(
"z_recv_multiple: {}"
,
zmq_strerror
(
zmq_errno
()));
break
;
break
;
}
}
}
}
}
if
(
nread
<
0
)
{
if
(
ret
<
0
)
{
if
(
nread
!=
UV_EOF
)
{
spdlog
::
error
(
"failed to recv msg: {}"
,
ret
<
0
?
zmq_strerror
(
ret
)
:
"invalid frames"
);
spdlog
::
error
(
"Read error {}, closing"
,
uv_err_name
(
nread
));
return
-
1
;
}
else
{
spdlog
::
error
(
"read error {}"
,
uv_err_name
(
nread
));
uv_close
((
uv_handle_t
*
)
client
,
on_closed
);
}
}
}
free
(
buf
->
base
)
;
return
0
;
}
}
void
on_connect
(
uv_stream_t
*
server
,
int
status
)
packet_processor_t
globalProcess
=
{
0
};
{
if
(
status
<
0
)
{
void
dispatch
(
string
sn
,
zmq_msg_t
&
msg
){
spdlog
::
error
(
"New connection error {}"
,
uv_strerror
(
status
));
evpacket_t
*
pkt
=
(
evpacket_t
*
)
zmq_msg_data
(
&
msg
);
globalProcess
.
packetId
++
;
//debugHex((char*)zmq_msg_data(&msg), 64);
auto
crc
=
pkt
->
meta
.
crc
;
pkt
->
meta
.
crc
=
0
;
auto
crc_
=
crc16
((
unsigned
char
*
)
pkt
,
sizeof
(
evpacket_t
));
if
(
crc
!=
crc_
){
spdlog
::
error
(
"invalid crc: {}"
,
pkt
->
meta
.
packet_id
);
return
;
return
;
}
}
spdlog
::
info
(
"client connected"
);
packet_client
*
client
=
new
packet_client
();
client
->
processor
.
handle
=
&
client
->
handle
;
uv_tcp_init
(
loop
,
(
uv_tcp_t
*
)
client
);
if
(
uv_accept
(
server
,
(
uv_stream_t
*
)
client
)
==
0
)
{
uv_read_start
((
uv_stream_t
*
)
client
,
alloc_buffer
,
on_read
);
}
else
{
spdlog
::
error
(
"failed to accept"
);
uv_close
((
uv_handle_t
*
)
client
,
on_closed
);
}
}
/// NOTES: since libuv async-api already implements multi-thread internally, the following
if
(
globalProcess
.
pAvCtx
==
nullptr
&&
globalProcess
.
packetId
%
15
*
10
==
0
){
/// 'bottom-half' implementaion class is never used.
int
rc
=
0
;
// class RtspPusher {
globalProcess
.
pAvCtx
=
rtsp_init
(
darwinUrl
+
sn
,
0
,
1080
,
1920
,
&
rc
);
// private:
if
(
globalProcess
.
pAvCtx
==
nullptr
||
rc
<
0
)
{
// map<string, devinfo_t *> devMap;
spdlog
::
error
(
"failed to connect to darwin: {}"
,
darwinUrl
);
// map<string, Notifier *> devNoti;
}
memcpy
(
&
globalProcess
.
hdr
,
zmq_msg_data
(
&
msg
),
sizeof
(
globalProcess
.
hdr
));
// int num_clients;
// string darwin_addr;
// protected:
// public:
// RtspPusher()
// {
// darwin_addr = "rtsp://evcloud.ilabservice.cloud:554/";
// }
// RtspPusher(string darwin_addr):darwin_addr(darwin_addr) {}
// ~RtspPusher()
// {
// /// NOTES: ATTENTION!!! N-phase shutdown
// for(auto &[k, v]:devNoti) {
// lock_guard<mutex> lk(*v->mut);
// if(devMap.count(k) != 0) {
// delete devMap[k];
// devMap.erase(k);
// }
// }
// for(auto &[k, v]:devNoti) {
// lock_guard<mutex> lk(*v->mut);
// delete v->cond;
// v->cond = nullptr;
// }
// for(auto &[k, v]:devNoti) {
// delete v->mut;
// delete v;
// devNoti.erase(k);
// }
// }
// int send(string devsn, dataque_frame_t && item)
// {
// int ret = 0;
// AVFormatContext *ctx = nullptr;
// if(devMap.count(devsn) == 0) {
// string url = darwin_addr + devsn;
// ctx = rtsp_init(url, item.codec, item.height, item.width, &ret);
// if(ctx == nullptr) {
// spdlog::error("failed to connect rtsp: {}", av_err2str(ret));
// return -1;
// }
// queue<dataque_frame_t> * qu = new queue<dataque_frame_t>();
// devMap.insert({devsn, new devinfo_t{devsn, qu, ctx}});
// //
// mutex *mut = new mutex();
// condition_variable *cv = new condition_variable();
// devNoti.insert({devsn, new Notifier({mut, cv})});
// }
// if(devMap.count(devsn) == 0 || devNoti.count(devsn) == 0) {
// spdlog::error("failed to get resources map for: {}, maybe stopped", devsn);
// return -2;
// }
// devinfo_t *info = devMap[devsn];
// Notifier *noti = devNoti[devsn];
// lock_guard<mutex> lock(*noti->mut);
// /// double check
// if(devMap.count(devsn) == 0 || devNoti.count(devsn) == 0||devNoti[devsn]->cond == nullptr) {
// spdlog::error("failed to get resources map for: {}, maybe stopped", devsn);
// return -2;
// }
// /// push new frame
// info->que->push(std::move(item));
// noti->cond->notify_one();
// }
// int run(thread &th){
// th = thread([]{
// // TODO: some multi-worker impl here.
// });
// if(th.joinable()){
// th.detach();
// }else{
// spdlog::error("failed to create or join worker thread");
// }
// }
// };
static
bool
bInSegv
=
false
;
void
clean_up
(
int
sig
)
{
if
(
sig
==
SIGSEGV
&&
bInSegv
==
true
)
{
exit
(
1
);
}
}
// try to cleanup before exit. (most concerned on socket closing for the edge node)
int
ret
=
write_packet
(
&
globalProcess
,
(
char
*
)
zmq_msg_data
(
&
msg
)
+
sizeof
(
evpacket_t
),
zmq_msg_size
(
&
msg
)
-
sizeof
(
evpacket_t
)
);
if
(
ret
<
0
)
{
spdlog
::
error
(
"failed to send packet!"
);
if
(
globalProcess
.
pAvCtx
&&
globalProcess
.
pAvCtx
->
pb
)
{
avio_closep
(
&
globalProcess
.
pAvCtx
->
pb
);
}
if
(
globalProcess
.
pAvCtx
)
{
avformat_free_context
(
globalProcess
.
pAvCtx
);
}
globalProcess
.
pAvCtx
=
nullptr
;
}
}
}
int
main
()
int
main
()
...
@@ -580,17 +265,6 @@ int main()
...
@@ -580,17 +265,6 @@ int main()
darwinUrl
=
string
(
darwinUrl_
);
darwinUrl
=
string
(
darwinUrl_
);
}
}
/// bind addr
auto
bindAddr_
=
getenv
(
"HOST"
);
if
(
bindAddr_
)
{
bindAddr
=
bindAddr_
;
}
auto
bindPort_
=
getenv
(
"PORT"
);
if
(
bindPort_
)
{
bindPort
=
string
(
bindPort_
);
}
auto
logLevel_
=
getenv
(
"LOG_LEVEL"
);
auto
logLevel_
=
getenv
(
"LOG_LEVEL"
);
if
(
logLevel_
)
{
if
(
logLevel_
)
{
spdlog
::
set_level
(
spdlog
::
level
::
from_str
(
logLevel_
));
spdlog
::
set_level
(
spdlog
::
level
::
from_str
(
logLevel_
));
...
@@ -600,17 +274,57 @@ int main()
...
@@ -600,17 +274,57 @@ int main()
spdlog
::
set_level
(
spdlog
::
level
::
debug
);
spdlog
::
set_level
(
spdlog
::
level
::
debug
);
}
}
loop
=
uv_default_loop
();
string
addr
=
"tcp://0.0.0.0:7123"
;
uv_tcp_t
server
;
void
*
pRouterCtx
=
nullptr
,
*
pRouter
=
nullptr
/*, *pDealerCtx = nullptr, *pDealer = nullptr*/
;
uv_tcp_init
(
loop
,
&
server
);
setupRouter
(
&
pRouterCtx
,
&
pRouter
,
addr
,
10
);
uv_ip4_addr
(
bindAddr
.
c_str
(),
stoi
(
bindPort
),
&
addr
);
uv_tcp_bind
(
&
server
,
(
const
struct
sockaddr
*
)
&
addr
,
0
);
while
(
1
){
spdlog
::
info
(
"sizeof pkt header {}, sizeof tv {}, bigendian: {}"
,
sizeof
(
evpacket_t
),
sizeof
(
timeval
),
is_big_endian
());
int64_t
more
=
1
;
int
r
=
uv_listen
((
uv_stream_t
*
)
&
server
,
DEFAULT_BACKLOG
,
on_connect
);
size_t
more_size
=
sizeof
(
more
);
if
(
r
)
{
int
ret
=
0
;
spdlog
::
error
(
"Listen error {}"
,
uv_strerror
(
r
));
zmq_msg_t
msg
;
return
1
;
ret
=
zmq_msg_init
(
&
msg
);
if
(
ret
<
0
)
{
spdlog
::
debug
(
"failed to receive multiple msg on zmq_msg_init: {}"
,
zmq_strerror
(
zmq_errno
()));
break
;
}
ret
=
zmq_msg_recv
(
&
msg
,
pRouter
,
0
);
if
(
ret
<
0
)
{
spdlog
::
debug
(
"z_recv_multiple: {}"
,
zmq_strerror
(
zmq_errno
()));
break
;
}
string
sn
((
char
*
)
zmq_msg_data
(
&
msg
),
zmq_msg_size
(
&
msg
));
zmq_msg_close
(
&
msg
);
// ignore the first frame
ret
=
zmq_getsockopt
(
pRouter
,
ZMQ_RCVMORE
,
&
more
,
&
more_size
);
if
(
ret
<
0
)
{
spdlog
::
debug
(
"z_recv_multiple: {}"
,
zmq_strerror
(
zmq_errno
()));
break
;
}
if
(
more
>
0
)
{
ret
=
zmq_msg_init
(
&
msg
);
ret
|=
zmq_msg_recv
(
&
msg
,
pRouter
,
0
);
if
(
ret
<
0
)
{
spdlog
::
debug
(
"z_recv_multiple: {}"
,
zmq_strerror
(
zmq_errno
()));
break
;
}
dispatch
(
sn
,
msg
);
}
else
{
spdlog
::
error
(
"invalid packet fmt"
);
}
zmq_msg_close
(
&
msg
);
if
(
ret
<
0
)
{
spdlog
::
error
(
"failed to recv msg: {}"
,
ret
<
0
?
zmq_strerror
(
ret
)
:
"invalid frames"
);
return
-
1
;
}
}
}
spdlog
::
info
(
"started video gateway service from {}:{} to {}"
,
bindAddr
,
bindPort
,
darwinUrl
);
return
uv_run
(
loop
,
UV_RUN_DEFAULT
);
this_thread
::
sleep_for
(
2
s
);
zmq_close
(
pRouter
);
zmq_ctx_destroy
(
pRouterCtx
);
return
0
;
}
}
libzmq
@
a84ffa12
Subproject commit
2aa87c94cc8be57a878e2e3c6a0551e8fdf6c886
Subproject commit
a84ffa12b2eb3569ced199660bac5ad128bff1f0
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论