1. 删除图片存储到本地的方式;
2. 取流方式由Opencv修改为FFmpeg方式;
3. 解码后的数据直接转为RK_FORMAT_YCbCr_422_SP格式发送给算法;
4. 视频裸流数据存储在内存中,保存30s;
5. 报警图片从报警录像视频中获取;
This commit is contained in:
hehaoyang 2023-12-08 14:17:14 +08:00
parent a53d2f2ff7
commit ff66a2e0d6
13 changed files with 936 additions and 4946 deletions

4153
.gitignore vendored

File diff suppressed because it is too large Load Diff

View File

@ -1,18 +1,50 @@
## 版本说明
| 版本 | 说明 |
| --- | --- |
| 1.00 | 初始版本 |
| 1.01 | 1. 通过RKMPP实现硬解码; <br> 2. 视频以图片的方式按帧存储到本地; |
| 1.02 | 1. 删除图片存储到本地的方式; <br> 2. 取流方式由Opencv修改为FFmpeg方式; <br> 3. 解码后的数据直接转为RK_FORMAT_YCbCr_422_SP格式发送给算法; <br> 4. 视频裸流数据存储在内存中保存30s; <br> 5. 报警图片从报警录像视频中获取; |
## 编译方法
#### 下载代码 #### 下载代码
``` ```
git clone http://teweishi.oicp.net:3001/hehaoyang/IVA.git git clone http://teweishi.oicp.net:3001/hehaoyang/IVA.git
``` ```
### 创建软链接 #### 修改配置
* 进入目录
```
cd IVA/app/
```
* 取消 app.pro 文件中以下注释
```
#DEFINES += USE_RABBITMQ
#DEFINES += USE_ALGORITHM
```
* 生成 Makefile 文件
```
qmake app.pro
```
#### 创建软链接
``` ```
cd external/npu/ cd external/npu/
ln -s /usr/lib/librknnrt.so librknn_api.so ln -s /usr/lib/librknnrt.so librknn_api.so
``` ```
### 编译 #### 编译
``` ```
cd ../../
make debug -j4 make debug -j4
``` ```

View File

@ -1,10 +1,10 @@
#include "HxDataBase.h" #include "HxDataBase.h"
#include "HxUtils.h" #include "HxUtils.h"
QMutex HxDataBase::mutex; QMutex HxDataBase::mutex;
QSqlDatabase HxDataBase::database; QSqlDatabase HxDataBase::database;
QString HxDataBase::device_id; QString HxDataBase::device_id;
int HxDataBase::recording_prepend_time;
QString HxDataBase::ftp_address, HxDataBase::ftp_username, HxDataBase::ftp_password; QString HxDataBase::ftp_address, HxDataBase::ftp_username, HxDataBase::ftp_password;
QString HxDataBase::qamqp_address, HxDataBase::qamqp_username, HxDataBase::qamqp_password; QString HxDataBase::qamqp_address, HxDataBase::qamqp_username, HxDataBase::qamqp_password;
int HxDataBase::algorithm_type; int HxDataBase::algorithm_type;
@ -14,6 +14,7 @@ QStringList HxDataBase::bsd_video_input_source;
QStringList HxDataBase::bsd_warn_regions; QStringList HxDataBase::bsd_warn_regions;
EventWarnParamConfig HxDataBase::warm_param_config; EventWarnParamConfig HxDataBase::warm_param_config;
CameraCalibration HxDataBase::adas_camera_calibration; CameraCalibration HxDataBase::adas_camera_calibration;
QStringList HxDataBase::alarm_protect_timestamp;
QSqlDatabase HxDataBase::open(QString filepath, QString connectionName) QSqlDatabase HxDataBase::open(QString filepath, QString connectionName)
{ {
@ -257,6 +258,9 @@ void HxDataBase::initialization()
/* 设备编号 */ /* 设备编号 */
device_id = read_setting("device_id", QString("TVIS")); device_id = read_setting("device_id", QString("TVIS"));
/* 预录时长 Seconds */
recording_prepend_time = read_setting("recording_prepend_time", 5);
/* FTP信息 */ /* FTP信息 */
ftp_address = read_setting("ftp_address", QString("192.168.10.10:7616")); ftp_address = read_setting("ftp_address", QString("192.168.10.10:7616"));
ftp_username = read_setting("ftp_username", QString("nvruser")); ftp_username = read_setting("ftp_username", QString("nvruser"));
@ -295,6 +299,9 @@ void HxDataBase::initialization()
/* 读取 ADAS 相机内外参 */ /* 读取 ADAS 相机内外参 */
read_adas_camera_calibration(); read_adas_camera_calibration();
/* 报警保护时长 */
alarm_protect_timestamp = read_setting("alarm_protect_timestamp", QString("3;3;3;3;3;3;3;3;3;3;3;3;3;3;3;3;3;3;3;3;3;3;3;3;3;3")).split(";");
} }
bool HxDataBase::save_setting() bool HxDataBase::save_setting()
@ -302,6 +309,7 @@ bool HxDataBase::save_setting()
database.transaction(); database.transaction();
write_setting("device_id", device_id); write_setting("device_id", device_id);
write_setting("recording_prepend_time", QString::number(recording_prepend_time));
write_setting("ftp_address", ftp_address); write_setting("ftp_address", ftp_address);
write_setting("ftp_username", ftp_username); write_setting("ftp_username", ftp_username);
write_setting("ftp_password", ftp_password); write_setting("ftp_password", ftp_password);
@ -315,6 +323,7 @@ bool HxDataBase::save_setting()
write_setting("bsd_warn_regions", bsd_warn_regions.join("*")); write_setting("bsd_warn_regions", bsd_warn_regions.join("*"));
write_warm_param_config(); write_warm_param_config();
write_adas_camera_calibration(); write_adas_camera_calibration();
write_setting("alarm_protect_timestamp", alarm_protect_timestamp.join(";"));
return database.commit(); return database.commit();
} }

View File

@ -11,10 +11,10 @@
#include "MvObjectEventDetect.h" #include "MvObjectEventDetect.h"
#define BSD_MAX_CHANNEL 6 #define BSD_MAX_CHANNEL 6
#define TEMPORARY_VIDEO_DIRECTORY "temp/video" #define TEMPORARY_LOG_DIRECTORY "log"
#define TEMPORARY_ALARM_DIRECTORY "temp/alarm" #define TEMPORARY_RECORD_DIRECTORY "record"
class HxDataBase class HxDataBase
{ {
@ -106,6 +106,9 @@ public:
/* 设备编号 */ /* 设备编号 */
static QString device_id; static QString device_id;
/* 预录时长 Seconds */
static int recording_prepend_time;
/* FTP地址 */ /* FTP地址 */
static QString ftp_address; static QString ftp_address;
@ -137,6 +140,9 @@ public:
/* ADAS 相机内外参 */ /* ADAS 相机内外参 */
static CameraCalibration adas_camera_calibration; static CameraCalibration adas_camera_calibration;
/* 报警保护时长 */
static QStringList alarm_protect_timestamp;
}; };
#endif // HXDATABASE_H #endif // HXDATABASE_H

View File

@ -10,13 +10,13 @@
/* 视频设备 */ /* 视频设备 */
HxVideoDevice adas_video_device, bsd_video_device[6], dsm_video_device; HxVideoDevice adas_video_device, bsd_video_device[6], dsm_video_device;
HxTaskDispatch* dispatcher = new HxTaskDispatch(); HxTaskDispatch *dispatcher = new HxTaskDispatch();
QMutex upload_file_mutex; QMutex upload_file_mutex;
QQueue<QString> upload_file_queue; QQueue<QString> upload_file_queue;
#ifdef USE_RABBITMQ #ifdef USE_RABBITMQ
HxRabbitMQUtils HxRabbitMQ; HxRabbitMQ rabbit;
#endif #endif
/* 倒车灯10熄灭 */ /* 倒车灯10熄灭 */
@ -36,25 +36,25 @@ void HxTaskDispatch::initialization(void)
/* 算法模块初始化 */ /* 算法模块初始化 */
#if USE_ALGORITHM #if USE_ALGORITHM
/* adas检测配置 */ /* adas检测配置 */
strcpy(dispatcher->event_detect_config.szAdasDetectConfigPathName, "./algmode/adas_detect.bin"); strcpy(dispatcher->event_detect_config.szAdasDetectConfigPathName, "./resources/algmode/adas_detect.bin");
/* adas跟踪配置 */ /* adas跟踪配置 */
strcpy(dispatcher->event_detect_config.szAdasTrackConfigPathName, "./algmode/adas_track.bin"); strcpy(dispatcher->event_detect_config.szAdasTrackConfigPathName, "./resources/algmode/adas_track.bin");
/* bsd检测配置 */ /* bsd检测配置 */
strcpy(dispatcher->event_detect_config.szBsdDetectConfigPathName, "./algmode/bsd_detect.bin"); strcpy(dispatcher->event_detect_config.szBsdDetectConfigPathName, "./resources/algmode/bsd_detect.bin");
// strcpy(dispatcher->event_detect_config.szRightBsdFrontDetectConfigPathName, "./algmode/bsd_detect.bin"); // strcpy(dispatcher->event_detect_config.szRightBsdFrontDetectConfigPathName, "./resources/algmode/bsd_detect.bin");
/* dsm人脸检测配置 */ /* dsm人脸检测配置 */
strcpy(dispatcher->event_detect_config.szDsmFaceDetectConfigPathName, "./algmode/dsm_face_detect.bin"); strcpy(dispatcher->event_detect_config.szDsmFaceDetectConfigPathName, "./resources/algmode/dsm_face_detect.bin");
/* dsm人脸特征点检测配置 */ /* dsm人脸特征点检测配置 */
strcpy(dispatcher->event_detect_config.szDsmFaceLandMarksDetectConfigPathName, "./algmode/dsm_face_landmarks_detect.bin"); strcpy(dispatcher->event_detect_config.szDsmFaceLandMarksDetectConfigPathName, "./resources/algmode/dsm_face_landmarks_detect.bin");
/* dsm人脸认证检测配置 */ /* dsm人脸认证检测配置 */
strcpy(dispatcher->event_detect_config.szDsmFaceVerificationDetectConfigPathName, "./algmode/dsm_face_verification_detect.bin"); strcpy(dispatcher->event_detect_config.szDsmFaceVerificationDetectConfigPathName, "./resources/algmode/dsm_face_verification_detect.bin");
/* dsm人眼认证检测配置 */ /* dsm人眼认证检测配置 */
strcpy(dispatcher->event_detect_config.szDsmEyeLandMarksDetectConfigPathName, "./algmode/dsm_eye_landmarks_detect.bin"); strcpy(dispatcher->event_detect_config.szDsmEyeLandMarksDetectConfigPathName, "./resources/algmode/dsm_eye_landmarks_detect.bin");
/* dsm人脸认证检测配置 */ /* dsm人脸认证检测配置 */
strcpy(dispatcher->event_detect_config.szDsmSmokeConfPathName, "./algmode/dsm_smoke_detect.bin"); strcpy(dispatcher->event_detect_config.szDsmSmokeConfPathName, "./resources/algmode/dsm_smoke_detect.bin");
strcpy(dispatcher->event_detect_config.szDsmCallConfPathName, "./algmode/dsm_call_detect.bin"); strcpy(dispatcher->event_detect_config.szDsmCallConfPathName, "./resources/algmode/dsm_call_detect.bin");
strcpy(dispatcher->event_detect_config.szDsmFaceFeaturePathName, "./algmode/dsm_face_feature.bin"); strcpy(dispatcher->event_detect_config.szDsmFaceFeaturePathName, "./resources/algmode/dsm_face_feature.bin");
strcpy(dispatcher->event_detect_config.szDsmHeadPoseConfPathName, "./algmode/data_68kp"); strcpy(dispatcher->event_detect_config.szDsmHeadPoseConfPathName, "./resources/algmode/data_68kp");
/* 输出调试信息 */ /* 输出调试信息 */
MvSetPrintf(false); MvSetPrintf(false);
@ -73,9 +73,8 @@ void HxTaskDispatch::initialization(void)
if (result != 0) if (result != 0)
HxLog::append("initialization", "set event warn param config failed!!"); HxLog::append("initialization", "set event warn param config failed!!");
/* 相机标定 */ /* 相机标定 */
if(MvCameraCalibration(&HxDataBase::adas_camera_calibration) != 0) if (MvCameraCalibration(&HxDataBase::adas_camera_calibration) != 0)
HxLog::append("initialization", "camera calibration failed!!"); HxLog::append("initialization", "camera calibration failed!!");
#endif #endif
@ -112,121 +111,97 @@ void HxTaskDispatch::initialization(void)
dispatcher->start(); dispatcher->start();
#ifdef USE_RABBITMQ #ifdef USE_RABBITMQ
HxRabbitMQ.set(HxDataBase::qamqp_address, HxDataBase::qamqp_username, HxDataBase::qamqp_password); rabbit.set(HxDataBase::qamqp_address, HxDataBase::qamqp_username, HxDataBase::qamqp_password);
HxRabbitMQ.set_exchanger_name("vehicle.direct.exchange"); rabbit.set_exchanger_name("vehicle.direct.exchange");
HxRabbitMQ.set_queue_name("bsd_video_transcode_tag"); rabbit.set_queue_name("bsd_video_transcode_tag");
HxRabbitMQ.set_routing_key("bsd_video_transcode_tag_1"); rabbit.set_routing_key("bsd_video_transcode_tag_1");
#endif #endif
} }
void HxTaskDispatch::listern(uint16_t port) void HxTaskDispatch::listern(uint16_t port)
{ {
dispatcher->debug_tool = new HxSocketUtils(port); dispatcher->debug_tool = new HxSocket(port);
connect(dispatcher->debug_tool, &HxSocketUtils::data_receive_event, dispatcher, &HxTaskDispatch::data_receive_event); connect(dispatcher->debug_tool, &HxSocket::data_receive_event, dispatcher, &HxTaskDispatch::data_receive_event);
connect(dispatcher, &HxTaskDispatch::data_write_event, dispatcher->debug_tool, &HxSocketUtils::write); connect(dispatcher, &HxTaskDispatch::data_write_event, dispatcher->debug_tool, &HxSocket::write);
} }
void HxTaskDispatch::connect_to_host(QString address, int port) void HxTaskDispatch::connect_to_host(QString address, int port)
{ {
dispatcher->platform = new HxSocketUtils(address, port); dispatcher->platform = new HxSocket(address, port);
connect(dispatcher->platform, &HxSocketUtils::data_receive_event, dispatcher, &HxTaskDispatch::data_receive_event); connect(dispatcher->platform, &HxSocket::data_receive_event, dispatcher, &HxTaskDispatch::data_receive_event);
connect(dispatcher, &HxTaskDispatch::data_write_event, dispatcher->platform, &HxSocketUtils::write); connect(dispatcher, &HxTaskDispatch::data_write_event, dispatcher->platform, &HxSocket::write);
} }
void HxTaskDispatch::algorithm_alarm_event(QDateTime time, int channel, int level, int event_type, int detect_type, int left, int top, int right, int bottom, int distance, int speed, QString base64_string, QString filepath) void HxTaskDispatch::alarm_upload_event(int algorithm_type, QDateTime timestamp, int channel, int event_type, int danger_level, ObjectPara *object_info, int object_number, CalibrationPoint *face_land_marks, int face_land_marks_number, LaneType left_line_type, LaneType right_line_type)
{ {
Q_UNUSED(speed); HxVideoDevice *device = nullptr;
switch (algorithm_type)
{
case ALGORITHM_TYPE_ADAS:
device = &adas_video_device;
break;
case ALGORITHM_TYPE_BSD:
device = &bsd_video_device[channel];
break;
case ALGORITHM_TYPE_DSM:
device = &dsm_video_device;
break;
default:
return;
}
QJsonObject root({ {"type", 4} }); /* 判断报警是否在保护时间内 */
if (!device->determine_alarm_detection_timestamp(event_type))
return;
QJsonObject msgInfo({ {"time", time.toString("yyyy-MM-dd HH:mm:ss")}, /* 生成报警图片+视频 */
{"channel", channel}, auto filename = QString("%1_%2_%3_%4_%5").arg(HxDataBase::device_id).arg(algorithm_type, 2, 10, QChar('0')).arg(channel, 2, 10, QChar('0')).arg(timestamp.toString("yyyyMMdd"), timestamp.toString("HHmmss"));
{"level", level},
{"event_type", event_type},
{"detect_type", detect_type},
{"left", left},
{"top", top},
{"right", right},
{"bottom", bottom},
{"distance", distance},
{"speed", dispatcher->car_info.fVelocity},
{"image", base64_string},
{"filepath", filepath} });
root.insert("msgInfo", msgInfo); device->create_alarm_data(event_type, filename);
QJsonObject root({{"type", 4}});
QJsonObject msg_info_json({{"time", timestamp.toString("yyyy-MM-dd HH:mm:ss")},
{"channel", channel},
{"level", danger_level},
{"event_type", event_type},
{"left_line_type", left_line_type},
{"right_line_type", right_line_type},
{"image_path", QString("/%1/%2/alarm/%3.jpg").arg(QDateTime::currentDateTime().toString("yyyyMMdd"), HxDataBase::device_id, filename)},
{"record_path", QString("/%1/%2/alarm/%3.mp4").arg(QDateTime::currentDateTime().toString("yyyyMMdd"), HxDataBase::device_id, filename)}});
QJsonArray object_info_json;
for (int i = 0; i < object_number; i++)
{
object_info_json.append(QJsonObject({{"detect_type", object_info[i].nDetectType},
{"left", object_info[i].nLeft},
{"top", object_info[i].nTop},
{"right", object_info[i].nRight},
{"bottom", object_info[i].nBottom},
{"distance", object_info[i].fDist},
{"speed", object_info[i].fVelo},
{"ttc", object_info[i].fTTC},
{"target_post_x", object_info[i].nTargetPosX},
{"target_post_y", object_info[i].nTargetPosY}}));
}
QJsonArray face_land_marks_json;
for (int i = 0; i < face_land_marks_number; i++)
face_land_marks_json.append(QJsonObject({{"x", face_land_marks[i].x}, {"y", face_land_marks[i].y}}));
msg_info_json.insert("object_info", object_info_json);
msg_info_json.insert("face_land_marks", face_land_marks_json);
root.insert("msgInfo", msg_info_json);
emit dispatcher->data_write_event(QJsonDocument(root).toJson(QJsonDocument::Compact)); emit dispatcher->data_write_event(QJsonDocument(root).toJson(QJsonDocument::Compact));
HxLog::append("algorithm", QString("alarm type=0x%1, filepath=%2").arg(QString::number(event_type, 16), filepath)); HxLog::append("algorithm", QString("alarm type=0x%1, filepath=%2").arg(QString::number(event_type, 16), filename));
// dispatcher->send_can_data(channel, pObjectTrackEventResult->nDangerLevel, pObjectTrackEventResult->objInfo[i].nDetectType);
} }
CarInfoInput* HxTaskDispatch::get_car_info(void) { return &dispatcher->car_info; } CarInfoInput *HxTaskDispatch::get_car_info(void) { return &dispatcher->car_info; }
QString HxTaskDispatch::get_video_frame_data(int type, int channel, int frame_id)
{
Q_UNUSED(channel);
switch (type)
{
case 0:
return adas_video_device.build_image(frame_id);
case 1:
return bsd_video_device[channel].build_image(frame_id);
case 2:
return dsm_video_device.build_image(frame_id);
}
return "";
}
bool HxTaskDispatch::get_alarm_detection_timestamp(int type, int channel)
{
switch (type)
{
case 0:
return adas_video_device.get_alarm_detection_timestamp();
case 1:
return bsd_video_device[channel].get_alarm_detection_timestamp();
case 2:
return dsm_video_device.get_alarm_detection_timestamp();
}
return false;
}
QString HxTaskDispatch::build_alarm_image(int type, int channel, int frame_id)
{
switch (type)
{
case 0:
return adas_video_device.build_image(frame_id);
case 1:
return bsd_video_device[channel].build_image(frame_id);
case 2:
return dsm_video_device.build_image(frame_id);
}
return "";
}
QString HxTaskDispatch::build_alarm_video(int type, int channel, int frame_id)
{
switch (type)
{
case 0:
return adas_video_device.build_video(frame_id);
case 1:
return bsd_video_device[channel].build_video(frame_id);
case 2:
return dsm_video_device.build_video(frame_id);
}
return "";
}
void HxTaskDispatch::enqueue_upload_file(QString filename) void HxTaskDispatch::enqueue_upload_file(QString filename)
{ {
@ -241,7 +216,7 @@ void HxTaskDispatch::update_heartbeat()
{ {
heartbeat_timestamp = QDateTime::currentDateTime(); heartbeat_timestamp = QDateTime::currentDateTime();
emit data_write_event(QJsonDocument(QJsonObject({ {"type", 0} })).toJson(QJsonDocument::Compact)); emit data_write_event(QJsonDocument(QJsonObject({{"type", 0}})).toJson(QJsonDocument::Compact));
} }
} }
@ -372,7 +347,7 @@ void HxTaskDispatch::parsing_vehiclue_status(void)
#if USE_ALGORITHM #if USE_ALGORITHM
MvSetDetectChannel(detect_channel); MvSetDetectChannel(detect_channel);
#endif #endif
HxLog::append("algorithm", QString("starting detect channel=0x%1").arg(QString::number(detect_channel, 16))); HxLog::append("algorithm", QString("starting detect channel=0x%1").arg(QString::number(detect_channel, 16)));
} }
} }
@ -380,7 +355,7 @@ void HxTaskDispatch::parsing_vehiclue_status(void)
void HxTaskDispatch::recording_upload_task(void) void HxTaskDispatch::recording_upload_task(void)
{ {
while(true) while (true)
{ {
msleep(1000); msleep(1000);
@ -390,11 +365,11 @@ void HxTaskDispatch::recording_upload_task(void)
auto filename = upload_file_queue.dequeue(); auto filename = upload_file_queue.dequeue();
upload_file_mutex.unlock(); upload_file_mutex.unlock();
QString fullpath = QString("%1/%2").arg(TEMPORARY_ALARM_DIRECTORY).arg(filename); QString fullpath = QString("%1/%2").arg(TEMPORARY_RECORD_DIRECTORY, filename);
if(!QFile::exists(fullpath)) if (!QFile::exists(fullpath))
{ {
HxLog::append("recording upload task", QString("file=%1 not exists, upload failed").arg(filename)); HxLog::append("recording upload task", QString("file=%1 not exists, upload failed").arg(fullpath));
continue; continue;
} }
@ -405,19 +380,18 @@ void HxTaskDispatch::recording_upload_task(void)
{ {
msleep(100); msleep(100);
/* FTP 上传 */ /* 上传 */
HxProcess::execute(QString("curl -u %1:%2 ftp://%3/%4/ --ftp-create-dirs -T %5").arg(HxDataBase::ftp_username, HxDataBase::ftp_password, HxDataBase::ftp_address, path, fullpath)); HxProcess::start(QString("curl -u %1:%2 ftp://%3/%4/ --ftp-create-dirs -T %5").arg(HxDataBase::ftp_username, HxDataBase::ftp_password, HxDataBase::ftp_address, path, fullpath));
QString command = QString("curl -u %1:%2 --ftp-ssl --head ftp://%3/%4/%5").arg(HxDataBase::ftp_username, HxDataBase::ftp_password, HxDataBase::ftp_address, path, filename); /* 判断文件是否存在 */
auto res = HxProcess::start(QString("curl -u %1:%2 --ftp-ssl --head ftp://%3/%4/%5").arg(HxDataBase::ftp_username, HxDataBase::ftp_password, HxDataBase::ftp_address, path, filename));
/* 判断FTP文件是否存在 */
auto res = HxProcess::start(command);
QRegExp rx("Content-Length:\\s\\d{1,9}"); QRegExp rx("Content-Length:\\s\\d{1,9}");
if (rx.indexIn(res, 0) == -1) if (rx.indexIn(res, 0) == -1)
continue; continue;
/* 比较大小 */
QFileInfo info(fullpath); QFileInfo info(fullpath);
auto size1 = info.size(); auto size1 = info.size();
@ -427,10 +401,10 @@ void HxTaskDispatch::recording_upload_task(void)
{ {
HxLog::append("recording upload task", QString("%1 upload finish").arg(filename)); HxLog::append("recording upload task", QString("%1 upload finish").arg(filename));
if(info.suffix() == "mp4") if (info.suffix() == "mp4")
{ {
#ifdef USE_RABBITMQ #ifdef USE_RABBITMQ
emit HxRabbitMQ.publish(QString("{\"ftproot\": \"%1\", \"complate\": true}").arg(("/"+path+"/"+filename))); emit rabbit.publish(QString("{\"ftproot\": \"%1\", \"complate\": true}").arg(("/" + path + "/" + filename)));
#endif #endif
} }
@ -438,7 +412,7 @@ void HxTaskDispatch::recording_upload_task(void)
} }
} }
// QFile::remove(fullpath); QFile::remove(fullpath);
HxLog::append("recording upload task", QString("%1 delete").arg(filename)); HxLog::append("recording upload task", QString("%1 delete").arg(filename));
} }
@ -452,6 +426,7 @@ void HxTaskDispatch::run()
while (true) while (true)
{ {
/* 事件循环用于响应信号 */
QCoreApplication::processEvents(); QCoreApplication::processEvents();
/* 发送心跳数据 */ /* 发送心跳数据 */
@ -460,6 +435,7 @@ void HxTaskDispatch::run()
/* 分析车辆行驶状态 */ /* 分析车辆行驶状态 */
parsing_vehiclue_status(); parsing_vehiclue_status();
/* 延时1s */
QThread::msleep(1000); QThread::msleep(1000);
} }
} }
@ -490,7 +466,8 @@ void HxTaskDispatch::get_warn_param_config(int type)
start_event_warn_kind.append(HxDataBase::warm_param_config.bStartEventWarnKind[i]); start_event_warn_kind.append(HxDataBase::warm_param_config.bStartEventWarnKind[i]);
abnormal_warn_frame_count.append(HxDataBase::warm_param_config.nAbnormalWarnFrameCount[i] / 25); abnormal_warn_frame_count.append(HxDataBase::warm_param_config.nAbnormalWarnFrameCount[i] / 25);
normal_frame_count.append(HxDataBase::warm_param_config.nNormalFrameCount[i] / 25); normal_frame_count.append(HxDataBase::warm_param_config.nNormalFrameCount[i] / 25);
abnormal_warn_interval_frame_count.append(HxDataBase::warm_param_config.nAbnormalWarnIntervalFrameCount[i] / 25); // abnormal_warn_interval_frame_count.append(HxDataBase::warm_param_config.nAbnormalWarnIntervalFrameCount[i] / 25);
abnormal_warn_interval_frame_count.append(HxDataBase::alarm_protect_timestamp.at(i).toInt());
abnormal_warn_score_threshold.append((int)(HxDataBase::warm_param_config.fAbnormalWarnScoreThreshold[i] * ((i >= 17 && i <= 20) ? 1 : 100))); abnormal_warn_score_threshold.append((int)(HxDataBase::warm_param_config.fAbnormalWarnScoreThreshold[i] * ((i >= 17 && i <= 20) ? 1 : 100)));
normal_warn_score_threshold.append((int)(HxDataBase::warm_param_config.fNormalWarnScoreThreshold[i] * ((i >= 17 && i <= 20) ? 1 : 100))); normal_warn_score_threshold.append((int)(HxDataBase::warm_param_config.fNormalWarnScoreThreshold[i] * ((i >= 17 && i <= 20) ? 1 : 100)));
@ -502,7 +479,7 @@ void HxTaskDispatch::get_warn_param_config(int type)
<< "fNormalWarnScoreThreshold=" << HxDataBase::warm_param_config.fNormalWarnScoreThreshold[i]; << "fNormalWarnScoreThreshold=" << HxDataBase::warm_param_config.fNormalWarnScoreThreshold[i];
} }
debug_tool_response_event(type, { {"start_event_warn_kind", start_event_warn_kind}, debug_tool_response_event(type, {{"start_event_warn_kind", start_event_warn_kind},
{"abnormal_warn_frame_count", abnormal_warn_frame_count}, {"abnormal_warn_frame_count", abnormal_warn_frame_count},
{"normal_frame_count", normal_frame_count}, {"normal_frame_count", normal_frame_count},
{"abnormal_warn_interval_frame_count", abnormal_warn_interval_frame_count}, {"abnormal_warn_interval_frame_count", abnormal_warn_interval_frame_count},
@ -519,7 +496,7 @@ void HxTaskDispatch::get_warn_param_config(int type)
{"bsd_second_vel", HxDataBase::warm_param_config.fBsdSecondVel}, {"bsd_second_vel", HxDataBase::warm_param_config.fBsdSecondVel},
{"bsd_third_vel", HxDataBase::warm_param_config.fBsdThirdVel}, {"bsd_third_vel", HxDataBase::warm_param_config.fBsdThirdVel},
{"ldw_distance", HxDataBase::warm_param_config.nLdwDistance}, {"ldw_distance", HxDataBase::warm_param_config.nLdwDistance},
{"dsm_vel", HxDataBase::warm_param_config.fDsmVel} }); {"dsm_vel", HxDataBase::warm_param_config.fDsmVel}});
} }
void HxTaskDispatch::set_warn_param_config(int type, QJsonObject object) void HxTaskDispatch::set_warn_param_config(int type, QJsonObject object)
@ -539,6 +516,9 @@ void HxTaskDispatch::set_warn_param_config(int type, QJsonObject object)
HxDataBase::warm_param_config.nAbnormalWarnIntervalFrameCount[i] = abnormal_warn_interval_frame_count.at(i).toInt() * 25; HxDataBase::warm_param_config.nAbnormalWarnIntervalFrameCount[i] = abnormal_warn_interval_frame_count.at(i).toInt() * 25;
HxDataBase::warm_param_config.fAbnormalWarnScoreThreshold[i] = abnormal_warn_score_threshold.at(i).toDouble() / ((i >= 17 && i <= 20) ? 1 : 100); HxDataBase::warm_param_config.fAbnormalWarnScoreThreshold[i] = abnormal_warn_score_threshold.at(i).toDouble() / ((i >= 17 && i <= 20) ? 1 : 100);
HxDataBase::warm_param_config.fNormalWarnScoreThreshold[i] = normal_warn_score_threshold.at(i).toDouble() / ((i >= 17 && i <= 20) ? 1 : 100); HxDataBase::warm_param_config.fNormalWarnScoreThreshold[i] = normal_warn_score_threshold.at(i).toDouble() / ((i >= 17 && i <= 20) ? 1 : 100);
/* 设置报警保护时长 */
HxDataBase::alarm_protect_timestamp[i] = QString::number(abnormal_warn_interval_frame_count.at(i).toInt());
} }
HxDataBase::warm_param_config.nHmwTime = object.value("hmw_time").toInt(); HxDataBase::warm_param_config.nHmwTime = object.value("hmw_time").toInt();
@ -555,24 +535,24 @@ void HxTaskDispatch::set_warn_param_config(int type, QJsonObject object)
HxDataBase::warm_param_config.fDsmVel = object.value("dsm_vel").toDouble(); HxDataBase::warm_param_config.fDsmVel = object.value("dsm_vel").toDouble();
#if USE_ALGORITHM #if USE_ALGORITHM
if(MvSetEventWarnParamConfig(&HxDataBase::warm_param_config) != 0) if (MvSetEventWarnParamConfig(&HxDataBase::warm_param_config) != 0)
{ {
debug_tool_response_event(type, { {"status", false} }); debug_tool_response_event(type, {{"status", false}});
return; return;
} }
#endif #endif
debug_tool_response_event(type, { {"status", HxDataBase::save_setting()} }); debug_tool_response_event(type, {{"status", HxDataBase::save_setting()}});
} }
void HxTaskDispatch::get_adas_camera_calibration(int type) void HxTaskDispatch::get_adas_camera_calibration(int type)
{ {
#if USE_ALGORITHM #if USE_ALGORITHM
if(MvGetCameraCalibrationInfo(&HxDataBase::adas_camera_calibration) != 0) if (MvGetCameraCalibrationInfo(&HxDataBase::adas_camera_calibration) != 0)
return; return;
#endif #endif
debug_tool_response_event(type, { {"car_len", HxDataBase::adas_camera_calibration.fCarLen}, debug_tool_response_event(type, {{"car_len", HxDataBase::adas_camera_calibration.fCarLen},
{"car_width", HxDataBase::adas_camera_calibration.fCarWidth}, {"car_width", HxDataBase::adas_camera_calibration.fCarWidth},
{"ref_center", HxDataBase::adas_camera_calibration.fRefCenter}, {"ref_center", HxDataBase::adas_camera_calibration.fRefCenter},
{"ref_top", HxDataBase::adas_camera_calibration.fRefTop}, {"ref_top", HxDataBase::adas_camera_calibration.fRefTop},
@ -581,7 +561,7 @@ void HxTaskDispatch::get_adas_camera_calibration(int type)
{"camera_focus", HxDataBase::adas_camera_calibration.fCameraFocus}, {"camera_focus", HxDataBase::adas_camera_calibration.fCameraFocus},
{"camera_dx", HxDataBase::adas_camera_calibration.fCameraDx}, {"camera_dx", HxDataBase::adas_camera_calibration.fCameraDx},
{"pitch", HxDataBase::adas_camera_calibration.fPitch}, {"pitch", HxDataBase::adas_camera_calibration.fPitch},
{"yaw", HxDataBase::adas_camera_calibration.fYaw} }); {"yaw", HxDataBase::adas_camera_calibration.fYaw}});
} }
void HxTaskDispatch::set_adas_camera_calibration(int type, QJsonObject object) void HxTaskDispatch::set_adas_camera_calibration(int type, QJsonObject object)
{ {
@ -597,14 +577,14 @@ void HxTaskDispatch::set_adas_camera_calibration(int type, QJsonObject object)
HxDataBase::adas_camera_calibration.fYaw = object.value("yaw").toDouble(); HxDataBase::adas_camera_calibration.fYaw = object.value("yaw").toDouble();
#if USE_ALGORITHM #if USE_ALGORITHM
if(MvCameraCalibration(&HxDataBase::adas_camera_calibration) != 0) if (MvCameraCalibration(&HxDataBase::adas_camera_calibration) != 0)
{ {
debug_tool_response_event(type, { {"status", false} }); debug_tool_response_event(type, {{"status", false}});
return; return;
} }
#endif #endif
debug_tool_response_event(type, { {"status", HxDataBase::save_setting()} }); debug_tool_response_event(type, {{"status", HxDataBase::save_setting()}});
} }
void HxTaskDispatch::data_receive_event(QByteArray data) void HxTaskDispatch::data_receive_event(QByteArray data)
@ -635,93 +615,80 @@ void HxTaskDispatch::data_receive_event(QByteArray data)
case 5: case 5:
HxProcess::start(QString("date -s %1").arg(msginfo.value("date").toString())); HxProcess::start(QString("date -s %1").arg(msginfo.value("date").toString()));
HxProcess::start(QString("date -s %1").arg(msginfo.value("time").toString())); HxProcess::start(QString("date -s %1").arg(msginfo.value("time").toString()));
debug_tool_response_event(type, { {"status", true} }); debug_tool_response_event(type, {{"status", true}});
HxLog::append("timing", QString(QJsonDocument(msginfo).toJson(QJsonDocument::Compact))); HxLog::append("timing", QString(QJsonDocument(msginfo).toJson(QJsonDocument::Compact)));
break; break;
/* 重启 */ /* 重启 */
case 200: case 200:
debug_tool_response_event(type, { {"status", true} }); debug_tool_response_event(type, {{"status", true}});
HxProcess::start("systemctl restart app.service"); HxProcess::start("systemctl restart app.service");
break; break;
/* 获取算法类型 */ /* 获取算法类型 */
case 240: case 240:
debug_tool_response_event(type, { {"mode", HxDataBase::algorithm_type} }); debug_tool_response_event(type, {{"mode", HxDataBase::algorithm_type}});
break; break;
/* 设置算法类型 */ /* 设置算法类型 */
case 241: case 241:
HxDataBase::algorithm_type = msginfo.value("mode").toInt(); HxDataBase::algorithm_type = msginfo.value("mode").toInt();
debug_tool_response_event(type, { {"status", HxDataBase::save_setting()} }); debug_tool_response_event(type, {{"status", HxDataBase::save_setting()}});
break; break;
/* 获取ADAS视频输入源 */ /* 获取ADAS视频输入源 */
case 242: case 242:
debug_tool_response_event(type, { {"source", HxDataBase::adas_video_input_source} }); debug_tool_response_event(type, {{"source", HxDataBase::adas_video_input_source}});
break; break;
/* 设置ADAS视频输入源 */ /* 设置ADAS视频输入源 */
case 243: case 243:
HxDataBase::adas_video_input_source = msginfo.value("source").toString(); HxDataBase::adas_video_input_source = msginfo.value("source").toString();
debug_tool_response_event(type, { {"status", HxDataBase::save_setting()} }); debug_tool_response_event(type, {{"status", HxDataBase::save_setting()}});
break;
/* 抓拍 */
case 244:
debug_tool_response_event(type, { {"data", adas_video_device.snap()} });
break; break;
/* 获取BSD视频输入源 */ /* 获取BSD视频输入源 */
case 245: case 245:
debug_tool_response_event(type, { {"source", HxDataBase::bsd_video_input_source[msginfo.value("channel").toInt()]} }); debug_tool_response_event(type, {{"source", HxDataBase::bsd_video_input_source[msginfo.value("channel").toInt()]}});
break; break;
/* 设置BSD视频输入源 */ /* 设置BSD视频输入源 */
case 246: case 246:
HxDataBase::bsd_video_input_source[msginfo.value("channel").toInt()] = msginfo.value("source").toString(); HxDataBase::bsd_video_input_source[msginfo.value("channel").toInt()] = msginfo.value("source").toString();
debug_tool_response_event(type, { {"status", HxDataBase::save_setting()} }); debug_tool_response_event(type, {{"status", HxDataBase::save_setting()}});
break;
/* 抓拍 */
case 247:
debug_tool_response_event(type, { {"data", bsd_video_device[msginfo.value("channel").toInt()].snap()} });
break; break;
/* 获取Dsm视频输入源 */ /* 获取Dsm视频输入源 */
case 248: case 248:
debug_tool_response_event(type, { {"source", HxDataBase::dsm_video_input_source} }); debug_tool_response_event(type, {{"source", HxDataBase::dsm_video_input_source}});
break; break;
/* 设置Dsm视频输入源 */ /* 设置Dsm视频输入源 */
case 249: case 249:
HxDataBase::dsm_video_input_source = msginfo.value("source").toString(); HxDataBase::dsm_video_input_source = msginfo.value("source").toString();
debug_tool_response_event(type, { {"status", HxDataBase::save_setting()} }); debug_tool_response_event(type, {{"status", HxDataBase::save_setting()}});
break;
/* 抓拍 */
case 250:
debug_tool_response_event(type, { {"data", dsm_video_device.snap()} });
break; break;
/* 获取BSD报警区域 */ /* 获取BSD报警区域 */
case 251: case 251:
debug_tool_response_event(type, { {"data", HxDataBase::bsd_warn_regions[msginfo.value("channel").toInt()]} }); debug_tool_response_event(type, {{"data", HxDataBase::bsd_warn_regions[msginfo.value("channel").toInt()]}});
break; break;
/* 设置BSD报警区域 */ /* 设置BSD报警区域 */
case 252: case 252:
HxDataBase::bsd_warn_regions[msginfo.value("channel").toInt()] = msginfo.value("data").toString(); HxDataBase::bsd_warn_regions[msginfo.value("channel").toInt()] = msginfo.value("data").toString();
debug_tool_response_event(type, { {"status", HxDataBase::save_setting()} }); debug_tool_response_event(type, {{"status", HxDataBase::save_setting()}});
break; break;
/* 获取设备编号及FTP信息 */ /* 获取设备编号及FTP信息 */
case 253: case 253:
debug_tool_response_event(type, { {"device_id", HxDataBase::device_id}, debug_tool_response_event(type, {
{"ftp_address", HxDataBase::ftp_address}, {"device_id", HxDataBase::device_id},
{"ftp_username", HxDataBase::ftp_username}, {"ftp_address", HxDataBase::ftp_address},
{"ftp_password", HxDataBase::ftp_password}, }); {"ftp_username", HxDataBase::ftp_username},
{"ftp_password", HxDataBase::ftp_password},
});
break; break;
/* 设置设备编号及FTP信息 */ /* 设置设备编号及FTP信息 */
@ -730,10 +697,9 @@ void HxTaskDispatch::data_receive_event(QByteArray data)
HxDataBase::ftp_address = msginfo.value("ftp_address").toString(); HxDataBase::ftp_address = msginfo.value("ftp_address").toString();
HxDataBase::ftp_username = msginfo.value("ftp_username").toString(); HxDataBase::ftp_username = msginfo.value("ftp_username").toString();
HxDataBase::ftp_password = msginfo.value("ftp_password").toString(); HxDataBase::ftp_password = msginfo.value("ftp_password").toString();
debug_tool_response_event(type, { {"status", HxDataBase::save_setting()} }); debug_tool_response_event(type, {{"status", HxDataBase::save_setting()}});
break; break;
case 255: case 255:
get_warn_param_config(type); get_warn_param_config(type);
break; break;
@ -752,9 +718,9 @@ void HxTaskDispatch::data_receive_event(QByteArray data)
/* 获取 RabbitMQ 信息 */ /* 获取 RabbitMQ 信息 */
case 259: case 259:
debug_tool_response_event(type, { {"qamqp_address", HxDataBase::qamqp_address}, debug_tool_response_event(type, {{"qamqp_address", HxDataBase::qamqp_address},
{"qamqp_username", HxDataBase::qamqp_username}, {"qamqp_username", HxDataBase::qamqp_username},
{"qamqp_password", HxDataBase::qamqp_password} }); {"qamqp_password", HxDataBase::qamqp_password}});
break; break;
/* 设置 RabbitMQ 信息 */ /* 设置 RabbitMQ 信息 */
@ -762,11 +728,20 @@ void HxTaskDispatch::data_receive_event(QByteArray data)
HxDataBase::qamqp_address = msginfo.value("qamqp_address").toString(); HxDataBase::qamqp_address = msginfo.value("qamqp_address").toString();
HxDataBase::qamqp_username = msginfo.value("qamqp_username").toString(); HxDataBase::qamqp_username = msginfo.value("qamqp_username").toString();
HxDataBase::qamqp_password = msginfo.value("qamqp_password").toString(); HxDataBase::qamqp_password = msginfo.value("qamqp_password").toString();
debug_tool_response_event(type, { {"status", HxDataBase::save_setting()} }); debug_tool_response_event(type, {{"status", HxDataBase::save_setting()}});
break;
case 261:
debug_tool_response_event(type, {{"recording_prepend_time", HxDataBase::recording_prepend_time}});
break;
case 262:
HxDataBase::recording_prepend_time = msginfo.value("recording_prepend_time").toInt();
debug_tool_response_event(type, {{"status", HxDataBase::save_setting()}});
break; break;
case 0xFFFF: case 0xFFFF:
adas_video_device.test(); adas_video_device.test();
dsm_video_device.test();
break; break;
} }
} }

View File

@ -6,6 +6,9 @@
#include "HxUtils.h" #include "HxUtils.h"
#include "MvObjectEventDetect.h" #include "MvObjectEventDetect.h"
#include <opencv2/opencv.hpp>
#include <opencv2/freetype.hpp>
#define ALGORITHM_TYPE_ADAS 0 #define ALGORITHM_TYPE_ADAS 0
#define ALGORITHM_TYPE_BSD 1 #define ALGORITHM_TYPE_BSD 1
#define ALGORITHM_TYPE_DSM 2 #define ALGORITHM_TYPE_DSM 2
@ -31,37 +34,27 @@ public:
*/ */
static void connect_to_host(QString address, int port); static void connect_to_host(QString address, int port);
static void algorithm_alarm_event(QDateTime time, int channel, int level, int event_type, int detect_type, int left, int top, int right, int bottom, int distance, int speed, QString base64_string, QString filepath); /**
* @brief alarm_upload_event
static CarInfoInput* get_car_info(void); * @param type
* @param timestamp
static QString get_video_frame_data(int type, int channel, int frame_id); * @param channel
* @param event_type
* @param danger_level
* @param object_info
* @param object_number
* @param face_land_marks
* @param face_land_marks_number
* @param left_line_type
* @param right_line_type
*/
static void alarm_upload_event(int type, QDateTime timestamp, int channel, int event_type, int danger_level, ObjectPara *object_info, int object_number, CalibrationPoint *face_land_marks, int face_land_marks_number, LaneType left_line_type, LaneType right_line_type);
/** /**
* @brief * @brief get_car_info
* @param type
* @param channel
* @return * @return
*/ */
static bool get_alarm_detection_timestamp(int type, int channel); static CarInfoInput* get_car_info(void);
/**
* @brief
* @param type
* @param channel
* @param frame_id
* @return
*/
static QString build_alarm_image(int type, int channel, int frame_id);
/**
* @brief
* @param type
* @param channel
* @param frame_id
* @return
*/
static QString build_alarm_video(int type, int channel, int frame_id);
/** /**
* @brief enqueue_upload_file * @brief enqueue_upload_file
@ -101,10 +94,10 @@ private:
QDateTime vehicle_status_update_time; QDateTime vehicle_status_update_time;
/* 边缘云 Socket (客户端) */ /* 边缘云 Socket (客户端) */
HxSocketUtils* platform; HxSocket* platform;
/* DebugTool Socket (服务端) */ /* DebugTool Socket (服务端) */
HxSocketUtils* debug_tool; HxSocket* debug_tool;
/* 车辆状态信息 */ /* 车辆状态信息 */
CarInfoInput car_info; CarInfoInput car_info;

View File

@ -6,6 +6,7 @@
#include <QTcpSocket> #include <QTcpSocket>
#include <QTcpServer> #include <QTcpServer>
#include <QDateTime> #include <QDateTime>
#include <QStorageInfo>
#include <QCoreApplication> #include <QCoreApplication>
#include <QProcess> #include <QProcess>
#include <QThread> #include <QThread>
@ -18,42 +19,30 @@
#include "qamqpqueue.h" #include "qamqpqueue.h"
#endif #endif
class HxThread
{
public:
static void sleep(int millisecond)
{
auto time = QTime::currentTime().addMSecs(millisecond);
while( QTime::currentTime() < time )
QCoreApplication::processEvents(QEventLoop::AllEvents, 100);
}
};
/** /**
* @brief SocketUtils socket * @brief Socket socket
*/ */
class HxSocketUtils : public QObject class HxSocket : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
HxSocketUtils(quint16 port) HxSocket(quint16 port)
{ {
connect(&server, &QTcpServer::newConnection, this, &HxSocketUtils::new_connection); connect(&server, &QTcpServer::newConnection, this, &HxSocket::new_connection);
server.listen(QHostAddress::Any, port); server.listen(QHostAddress::Any, port);
} }
HxSocketUtils(QString address, int port) HxSocket(QString address, int port)
{ {
is_reconnect = true; is_reconnect = true;
socket = new QTcpSocket(); socket = new QTcpSocket();
connect(socket, &QTcpSocket::readyRead, this, &HxSocketUtils::ready_read); connect(socket, &QTcpSocket::readyRead, this, &HxSocket::ready_read);
connect(socket, SIGNAL(disconnected()), this, SLOT(disconnected()), Qt::QueuedConnection); connect(socket, SIGNAL(disconnected()), this, SLOT(disconnected()), Qt::QueuedConnection);
connect(this, &HxSocketUtils::reconnection_event, this, &HxSocketUtils::reconnection); connect(this, &HxSocket::reconnection_event, this, &HxSocket::reconnection);
/* 域名解析 */ /* 域名解析 */
QHostInfo info = QHostInfo::fromName(address); QHostInfo info = QHostInfo::fromName(address);
@ -76,7 +65,7 @@ public slots:
socket = server.nextPendingConnection(); socket = server.nextPendingConnection();
connect(socket, &QTcpSocket::readyRead, this, &HxSocketUtils::ready_read); connect(socket, &QTcpSocket::readyRead, this, &HxSocket::ready_read);
connect(socket, SIGNAL(disconnected()), this, SLOT(disconnected()), Qt::QueuedConnection); connect(socket, SIGNAL(disconnected()), this, SLOT(disconnected()), Qt::QueuedConnection);
} }
@ -120,15 +109,9 @@ public slots:
/* 等待连接 */ /* 等待连接 */
if (!socket->waitForConnected(500)) if (!socket->waitForConnected(500))
{ {
/* 使用 QThread::msleep 延时,会使 Socket 出现接收不到事件信息 (槽无法响应) */ auto time = QTime::currentTime().addMSecs(10000);
// auto time = QTime::currentTime().addMSecs(10000); while (QTime::currentTime() < time)
// while (QTime::currentTime() < time) QCoreApplication::processEvents(QEventLoop::AllEvents, 100);
// {
// QCoreApplication::processEvents(QEventLoop::AllEvents, 100);
// QThread::msleep(100);
// }
HxThread::sleep(10000);
emit reconnection_event(); emit reconnection_event();
} }
@ -145,15 +128,16 @@ private:
class HxDir class HxDir
{ {
public: public:
static bool mkdir(QString name) static bool mkpath(QString name)
{ {
return QDir().mkpath(name); return QDir().mkpath(name);
} }
static void mkdir(QStringList names) static void mkpath(QStringList names)
{ {
foreach (QString name, names) { foreach (QString name, names)
HxDir::mkdir(name); {
HxDir::mkpath(name);
} }
} }
@ -161,6 +145,17 @@ public:
{ {
return QDir(name).removeRecursively(); return QDir(name).removeRecursively();
} }
static double free_size(QString rootPath)
{
foreach (const QStorageInfo &storage, QStorageInfo::mountedVolumes())
{
if (rootPath == storage.rootPath())
return static_cast<double>(storage.bytesAvailable()) / 1024 / 1024 / 1024;
}
return 0;
}
}; };
class HxLog class HxLog
@ -174,9 +169,7 @@ public:
auto current_time = QDateTime::currentDateTime(); auto current_time = QDateTime::currentDateTime();
HxDir::mkdir(QString("log/%1").arg(current_time.toString("yyyyMMdd"))); QFile file(QString("log/%1.log").arg(current_time.toString("yyyyMMdd")));
QFile file(QString("log/%1/%1.txt").arg(current_time.toString("yyyyMMdd")));
if (file.open(QIODevice::WriteOnly | QIODevice::Append)) if (file.open(QIODevice::WriteOnly | QIODevice::Append))
{ {
@ -196,20 +189,6 @@ public:
class HxProcess class HxProcess
{ {
public: public:
static int execute(QString command)
{
qDebug() << command;
auto array = command.split(" ");
QString program = array.at(0);
QStringList arguments;
for (int i = 1; i < array.count(); i++)
arguments << array.at(i);
return QProcess::execute(program, arguments);
}
static QString start(QString command) static QString start(QString command)
{ {
auto array = command.split(" "); auto array = command.split(" ");
@ -228,7 +207,7 @@ public:
}; };
#ifdef USE_RABBITMQ #ifdef USE_RABBITMQ
class HxRabbitMQUtils : public QObject class HxRabbitMQ : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
@ -246,7 +225,7 @@ public:
connect(&client, SIGNAL(connected()), this, SLOT(connected())); connect(&client, SIGNAL(connected()), this, SLOT(connected()));
connect(&client, SIGNAL(disconnected()), this, SLOT(disconnected())); connect(&client, SIGNAL(disconnected()), this, SLOT(disconnected()));
connect(this, &HxRabbitMQUtils::publish, this, &HxRabbitMQUtils::send_message); connect(this, &HxRabbitMQ::publish, this, &HxRabbitMQ::send_message);
client.connectToHost(); client.connectToHost();
} }

View File

@ -36,9 +36,41 @@ class HxVideoDecoder
public: public:
HxVideoDecoder(void) {} HxVideoDecoder(void) {}
#ifndef USE_ALGORITHM static int duration(QString fullpath)
bool initialization(AVFormatContext* ifmt_ctx)
{ {
/* 始化网络设备 */
avformat_network_init();
/* 初始化 */
AVFormatContext *ifmt_ctx = avformat_alloc_context();
/* 打开输入文件 */
if (avformat_open_input(&ifmt_ctx, fullpath.toUtf8().data(), nullptr, nullptr) < 0)
return 0;
/* 获取流信息 */
if (avformat_find_stream_info(ifmt_ctx, nullptr) < 0)
{
avformat_close_input(&ifmt_ctx);
return -1;
}
/* 这里获取的是微秒,需要转成秒 */
int64_t tduration = ifmt_ctx->duration;
/* 打开文件流后,需要关闭,否则会一直占用视频文件,无法进行视频文件的后续操作 */
avformat_close_input(&ifmt_ctx);
/* 销毁 */
avformat_free_context(ifmt_ctx);
return tduration / 1000000;
}
#ifndef USE_ALGORITHM
void initialization(AVFormatContext *ifmt_ctx)
{
status = false;
auto video_stream_index = -1; auto video_stream_index = -1;
for (uint i = 0; i < ifmt_ctx->nb_streams; i++) for (uint i = 0; i < ifmt_ctx->nb_streams; i++)
{ {
@ -47,14 +79,14 @@ public:
} }
if (video_stream_index == -1) if (video_stream_index == -1)
return false; return;
/* 配置解码器 */ /* 配置解码器 */
video_dec_ctx = avcodec_alloc_context3(nullptr); video_dec_ctx = avcodec_alloc_context3(nullptr);
if (video_dec_ctx == nullptr) if (video_dec_ctx == nullptr)
{ {
printf("Could not allocate AVCodecContext"); printf("Could not allocate AVCodecContext");
return false; return;
} }
/* 拷贝 */ /* 拷贝 */
@ -63,14 +95,14 @@ public:
/* 查找解码器 */ /* 查找解码器 */
auto codec = avcodec_find_decoder(video_dec_ctx->codec_id); auto codec = avcodec_find_decoder(video_dec_ctx->codec_id);
if (!codec) if (!codec)
return false; return;
/* 打开解码器 */ /* 打开解码器 */
if (avcodec_open2(video_dec_ctx, codec, nullptr) < 0) if (avcodec_open2(video_dec_ctx, codec, nullptr) < 0)
{ {
codec = nullptr; codec = nullptr;
avcodec_free_context(&video_dec_ctx); avcodec_free_context(&video_dec_ctx);
return false; return;
} }
video_dec_frame = av_frame_alloc(); video_dec_frame = av_frame_alloc();
@ -80,7 +112,7 @@ public:
/* 通过指定像素格式、图像宽、图像高来计算所需的内存大小 */ /* 通过指定像素格式、图像宽、图像高来计算所需的内存大小 */
auto numBytes = av_image_get_buffer_size(AV_PIX_FMT_BGR24, video_dec_ctx->width, video_dec_ctx->height, 1); auto numBytes = av_image_get_buffer_size(AV_PIX_FMT_BGR24, video_dec_ctx->width, video_dec_ctx->height, 1);
/* 创建 video_out_buffer */ /* 创建 video_out_buffer */
video_out_buffer = static_cast<uint8_t*>(av_malloc(static_cast<ulong>(numBytes) * sizeof(uint8_t))); video_out_buffer = static_cast<uint8_t *>(av_malloc(static_cast<ulong>(numBytes) * sizeof(uint8_t)));
/* 填充数据 */ /* 填充数据 */
av_image_fill_arrays(video_picture_frame->data, video_picture_frame->linesize, video_out_buffer, AV_PIX_FMT_BGR24, video_dec_ctx->width, video_dec_ctx->height, 1); av_image_fill_arrays(video_picture_frame->data, video_picture_frame->linesize, video_out_buffer, AV_PIX_FMT_BGR24, video_dec_ctx->width, video_dec_ctx->height, 1);
@ -102,11 +134,13 @@ public:
nullptr /* 特定缩放算法需要的参数(?)默认为NULL */ nullptr /* 特定缩放算法需要的参数(?)默认为NULL */
); );
return true; status = true;
} }
#else #else
bool initialization(void) void initialization(void)
{ {
status = false;
MPP_RET ret = MPP_OK; MPP_RET ret = MPP_OK;
RK_U32 need_split = 1; RK_U32 need_split = 1;
@ -119,29 +153,29 @@ public:
HxLog::append("mpp", QString("mpp_create failed")); HxLog::append("mpp", QString("mpp_create failed"));
return false; return;
} }
/* 配置解器 按帧输入码流 */ /* 配置解器 按帧输入码流 */
ret = mpp_mpi->control(mpp_ctx, MPP_DEC_SET_PARSER_SPLIT_MODE, (MppParam*)&need_split); ret = mpp_mpi->control(mpp_ctx, MPP_DEC_SET_PARSER_SPLIT_MODE, (MppParam *)&need_split);
if (MPP_OK != ret) if (MPP_OK != ret)
{ {
release(); release();
HxLog::append("mpp", QString("mpi->control failed")); HxLog::append("mpp", QString("mpi->control failed"));
return false; return;
} }
/* 配置解器 队列输入 */ /* 配置解器 队列输入 */
ret = mpp_mpi->control(mpp_ctx, MPP_SET_INPUT_BLOCK, (MppParam*)&need_split); ret = mpp_mpi->control(mpp_ctx, MPP_SET_INPUT_BLOCK, (MppParam *)&need_split);
if (MPP_OK != ret) if (MPP_OK != ret)
{ {
release(); release();
HxLog::append("mpp", QString("mpi->control failed")); HxLog::append("mpp", QString("mpi->control failed"));
return false; return;
} }
/* 初始化 MPP 固定为H264 */ /* 初始化 MPP 固定为H264 */
@ -152,10 +186,10 @@ public:
HxLog::append("mpp", QString("mpp_init failed")); HxLog::append("mpp", QString("mpp_init failed"));
return false; return;
} }
return true; status = true;
} }
#endif #endif
@ -191,7 +225,7 @@ public:
#endif #endif
} }
void decode(AVPacket* packet, cv::Mat* mat) void decode(AVPacket *packet, cv::Mat *mat)
{ {
#ifndef USE_ALGORITHM #ifndef USE_ALGORITHM
/* 发送数据到ffmepg放到解码队列中 */ /* 发送数据到ffmepg放到解码队列中 */
@ -201,7 +235,7 @@ public:
if (avcodec_receive_frame(video_dec_ctx, video_dec_frame) == 0) if (avcodec_receive_frame(video_dec_ctx, video_dec_frame) == 0)
{ {
/* 开始转换 */ /* 开始转换 */
sws_scale(video_sws_context, static_cast<const uint8_t* const*>(video_dec_frame->data), video_dec_frame->linesize, 0, video_dec_ctx->height, video_picture_frame->data, video_picture_frame->linesize); sws_scale(video_sws_context, static_cast<const uint8_t *const *>(video_dec_frame->data), video_dec_frame->linesize, 0, video_dec_ctx->height, video_picture_frame->data, video_picture_frame->linesize);
(*mat) = cv::Mat(cv::Size(video_dec_ctx->width, video_dec_ctx->height), CV_8UC3); (*mat) = cv::Mat(cv::Size(video_dec_ctx->width, video_dec_ctx->height), CV_8UC3);
(*mat).data = video_out_buffer; (*mat).data = video_out_buffer;
@ -296,7 +330,7 @@ public:
if (err_info) if (err_info)
{ {
qDebug("decoder_get_frame get err info:%d discard:%d.", qDebug("decoder_get_frame get err info:%d discard:%d.",
mpp_frame_get_errinfo(mpp_frame), mpp_frame_get_discard(mpp_frame)); mpp_frame_get_errinfo(mpp_frame), mpp_frame_get_discard(mpp_frame));
} }
frame_count++; frame_count++;
// qDebug("decode_get_frame get frame %d", frame_count); // qDebug("decode_get_frame get frame %d", frame_count);
@ -305,29 +339,8 @@ public:
{ {
RK_U32 width = mpp_frame_get_width(mpp_frame); RK_U32 width = mpp_frame_get_width(mpp_frame);
RK_U32 height = mpp_frame_get_height(mpp_frame); RK_U32 height = mpp_frame_get_height(mpp_frame);
MppBuffer mpp_buffer = mpp_frame_get_buffer(mpp_frame); MppBuffer mpp_buffer = mpp_frame_get_buffer(mpp_frame);
convert_to_mat(mpp_buffer, width, height, mat); convert_to_mat(mpp_buffer, width, height, mat);
// RK_U32 h_stride = mpp_frame_get_hor_stride(mpp_frame);
// RK_U32 v_stride = mpp_frame_get_ver_stride(mpp_frame);
// cv::Mat yuv_img(height * 3 / 2, width, CV_8UC1);
// RK_U8 *base = (RK_U8 *)mpp_buffer_get_ptr(mpp_buffer);
// RK_U8 *base_c = base + h_stride * v_stride;
// int idx = 0;
// for (int i = 0; i < height; i++, base += h_stride, idx += width)
// {
// memcpy(yuv_img.data + idx, base, width);
// }
// for (int i = 0; i < height / 2; i++, base_c += h_stride, idx += width)
// {
// memcpy(yuv_img.data + idx, base_c, width);
// }
// (*mat) = cv::Mat(cv::Size(width, height), CV_8UC3);
// cv::cvtColor(yuv_img, (*mat), CV_YUV420sp2RGB);
} }
} }
@ -405,36 +418,10 @@ private:
return MPP_BUFFER_MODE_BUTT; return MPP_BUFFER_MODE_BUTT;
} }
return ((MppBufferGroupImpl*)group)->usage; return ((MppBufferGroupImpl *)group)->usage;
} }
int write_image_to_file(void* buf, const char* filename, int sw, int sh, int fmt, int index) { bool convert_to_mat(MppBuffer mpp_buffer, RK_U32 width, RK_U32 height, cv::Mat *mat)
int size;
// char filePath[100];
// const char* outputFilePath = "%s/out%dw%d-h%d-%s.bin";
// snprintf(filePath, 100, outputFilePath,
// path, index, sw, sh, translate_format_str(fmt));
FILE* file = fopen(filename, "wb+");
if (!file) {
fprintf(stderr, "Could not open %s\n", filename);
return false;
}
else {
fprintf(stderr, "open %s and write ok\n", filename);
}
size = sw * sh * get_bpp_from_format(fmt);
fwrite(buf, size, 1, file);
fclose(file);
return 0;
}
bool convert_to_mat(MppBuffer mpp_buffer, RK_U32 width, RK_U32 height, cv::Mat* mat)
{ {
int ret = 0; int ret = 0;
im_rect src_rect, dst_rect; im_rect src_rect, dst_rect;
@ -448,16 +435,18 @@ private:
memset(&dst_img, 0, sizeof(dst_img)); memset(&dst_img, 0, sizeof(dst_img));
src_img = wrapbuffer_virtualaddr(mpp_buffer_get_ptr(mpp_buffer), width, height, RK_FORMAT_YCbCr_420_SP); src_img = wrapbuffer_virtualaddr(mpp_buffer_get_ptr(mpp_buffer), width, height, RK_FORMAT_YCbCr_420_SP);
dst_img = wrapbuffer_virtualaddr(mat->data, width, height, RK_FORMAT_BGR_888); dst_img = wrapbuffer_virtualaddr(mat->data, width, height, RK_FORMAT_YCbCr_422_SP);
if (src_img.width == 0 || dst_img.width == 0) { if (src_img.width == 0 || dst_img.width == 0)
{
printf("%s, %s\n", __FUNCTION__, imStrError()); printf("%s, %s\n", __FUNCTION__, imStrError());
return -1; return -1;
} }
src_img.format = RK_FORMAT_YCbCr_420_SP; src_img.format = RK_FORMAT_YCbCr_420_SP;
dst_img.format = RK_FORMAT_BGR_888; dst_img.format = RK_FORMAT_YCbCr_422_SP;
ret = imcheck(src_img, dst_img, src_rect, dst_rect); ret = imcheck(src_img, dst_img, src_rect, dst_rect);
if (IM_STATUS_NOERROR != ret) { if (IM_STATUS_NOERROR != ret)
{
printf("%d, check error! %s", __LINE__, imStrError((IM_STATUS)ret)); printf("%d, check error! %s", __LINE__, imStrError((IM_STATUS)ret));
return -1; return -1;
} }
@ -468,21 +457,24 @@ private:
} }
#endif #endif
public:
bool status = false;
private: private:
#if USE_ALGORITHM #if USE_ALGORITHM
MppCtx mpp_ctx; MppCtx mpp_ctx;
MppApi* mpp_mpi; MppApi *mpp_mpi;
size_t max_usage; size_t max_usage;
RK_U32 frame_count = 0, frame_num, eos; RK_U32 frame_count = 0, frame_num, eos;
/* 缓冲区管理器 */ /* 缓冲区管理器 */
MppBufferGroup mpp_frame_group; MppBufferGroup mpp_frame_group;
#else #else
uint8_t* video_out_buffer = nullptr; uint8_t *video_out_buffer = nullptr;
struct SwsContext* video_sws_context = nullptr; struct SwsContext *video_sws_context = nullptr;
AVCodecContext* video_dec_ctx = nullptr; AVCodecContext *video_dec_ctx = nullptr;
AVFrame* video_dec_frame = nullptr, * video_picture_frame = nullptr; AVFrame *video_dec_frame = nullptr, *video_picture_frame = nullptr;
#endif #endif
}; };

View File

@ -1,58 +1,32 @@
#include "HxVideoDevice.h" #include "HxVideoDevice.h"
#include "HxDataBase.h" #include "HxDataBase.h"
#include "HxUtils.h"
/* bsd算法结果处理函数 */ /* 算法报警处理函数 */
void algorithm_alarm_callback(int nDataChannel, ObjectTrackEventResult* pObjectTrackEventResult, void* pPrivData) void algorithm_detection_callback(int nDataChannel, ObjectTrackEventResult *pObjectTrackEventResult, void *pPrivData)
{ {
Q_UNUSED(nDataChannel); Q_UNUSED(nDataChannel);
Q_UNUSED(pPrivData); Q_UNUSED(pPrivData);
int algorithm_type = 0, channel = 0;
QDateTime current_time = QDateTime::currentDateTime(); QDateTime current_time = QDateTime::currentDateTime();
if (pObjectTrackEventResult->nEventType == 0) if (nDataChannel == 0)
return;
if (nDataChannel == 0) /* ADAS */
{ {
if (!HxTaskDispatch::get_alarm_detection_timestamp(ALGORITHM_TYPE_ADAS, 0)) algorithm_type = ALGORITHM_TYPE_ADAS;
return;
qDebug() << current_time.toString("[yyyy-MM-dd HH:mm:ss] ") << " Adas FrameId=" << pObjectTrackEventResult->nFrameId << " nEventType=" << pObjectTrackEventResult->nEventType;
/* 生成报警图片 */
auto image_path = HxTaskDispatch::build_alarm_image(ALGORITHM_TYPE_ADAS, 0, pObjectTrackEventResult->nFrameId);
/* 生成报警视频 */
auto record_path = HxTaskDispatch::build_alarm_video(ALGORITHM_TYPE_ADAS, 0, pObjectTrackEventResult->nFrameId);
/* 上传 */
HxTaskDispatch::algorithm_alarm_event(current_time, 0, 0, pObjectTrackEventResult->nEventType, 0, 0, 0, 0, 0, 0, 0, image_path, record_path);
} }
else if (nDataChannel == 2) /* DSM */ else if (nDataChannel == 2)
{ {
if (!HxTaskDispatch::get_alarm_detection_timestamp(ALGORITHM_TYPE_DSM, 0)) algorithm_type = ALGORITHM_TYPE_DSM;
return;
qDebug() << current_time.toString("[yyyy-MM-dd HH:mm:ss] ") << " Dsm FrameId=" << pObjectTrackEventResult->nFrameId << " nEventType=" << pObjectTrackEventResult->nEventType;
/* 生成报警图片 */
auto image_path = HxTaskDispatch::build_alarm_image(ALGORITHM_TYPE_DSM, 0, pObjectTrackEventResult->nFrameId);
/* 生成报警视频 */
auto record_path = HxTaskDispatch::build_alarm_video(ALGORITHM_TYPE_DSM, 0, pObjectTrackEventResult->nFrameId);
/* 上传 */
HxTaskDispatch::algorithm_alarm_event(current_time, 1, 0, pObjectTrackEventResult->nEventType, 0, 0, 0, 0, 0, 0, 0, image_path, record_path);
} }
else if (nDataChannel == 1 || /* BSD-右前 */ else if (nDataChannel == 1 || /* BSD-右前 */
nDataChannel == 3 || /* BSD-右后 */ nDataChannel == 3 || /* BSD-右后 */
nDataChannel == 4 || /* BSD-左前 */ nDataChannel == 4 || /* BSD-左前 */
nDataChannel == 5 || /* BSD-左后 */ nDataChannel == 5 || /* BSD-左后 */
nDataChannel == 6 || /* BSD-前 */ nDataChannel == 6 || /* BSD-前 */
nDataChannel == 7) /* BSD-后 */ nDataChannel == 7) /* BSD-后 */
{ {
int channel = 0; algorithm_type = ALGORITHM_TYPE_BSD;
switch (nDataChannel) switch (nDataChannel)
{ {
@ -75,78 +49,45 @@ void algorithm_alarm_callback(int nDataChannel, ObjectTrackEventResult* pObjectT
channel = 5; channel = 5;
break; break;
} }
if (!HxTaskDispatch::get_alarm_detection_timestamp(ALGORITHM_TYPE_BSD, channel))
return;
qDebug("ProcessBsdAlgResult nDataChannel=%d,nFrameId=%d,nObjectNumber=%d,nEventType=%x,nDangerLevel=%d\n", nDataChannel, pObjectTrackEventResult->nFrameId, pObjectTrackEventResult->nObjectNumber, pObjectTrackEventResult->nEventType, pObjectTrackEventResult->nDangerLevel);
for (int i = 0; i < pObjectTrackEventResult->nObjectNumber; i++)
{
qDebug("pObjectTrackEventResult->objInfo[i].nDetectType=%d\n", pObjectTrackEventResult->objInfo[i].nDetectType);
qDebug("nLeft=%d,nTop=%d,nRight=%d,nBottom=%d\n", pObjectTrackEventResult->objInfo[i].nLeft, pObjectTrackEventResult->objInfo[i].nTop, pObjectTrackEventResult->objInfo[i].nRight, pObjectTrackEventResult->objInfo[i].nBottom);
if (pObjectTrackEventResult->objInfo[i].nDetectType == 0)
continue;
/* 生成报警图片 */
auto image_path = HxTaskDispatch::build_alarm_image(ALGORITHM_TYPE_BSD, channel, pObjectTrackEventResult->nFrameId);
/* 生成报警视频 */
auto record_path = HxTaskDispatch::build_alarm_video(ALGORITHM_TYPE_BSD, channel, pObjectTrackEventResult->nFrameId);
/* 上传 */
HxTaskDispatch::algorithm_alarm_event(current_time, channel,
pObjectTrackEventResult->nDangerLevel,
pObjectTrackEventResult->nEventType,
pObjectTrackEventResult->objInfo[i].nDetectType,
pObjectTrackEventResult->objInfo[i].nLeft,
pObjectTrackEventResult->objInfo[i].nTop,
pObjectTrackEventResult->objInfo[i].nRight,
pObjectTrackEventResult->objInfo[i].nBottom,
pObjectTrackEventResult->objInfo[i].fDist,
pObjectTrackEventResult->objInfo[i].fVelo,
image_path,
record_path);
}
} }
}
// adas算法车道线结果处理函数 for (int i = 0; i < EVENT_WARN_NUM; i++)
void algorithm_lane_line_callback(DrawPointInfo* pPointInfo, void* pPrivData)
{
Q_UNUSED(pPrivData);
for (int i = 0; i < 4; i++)
{ {
printf("ProcessAdasAlgLaneLineResult pPointInfo->nPointCounters[i]=%d\n", pPointInfo->nPointCounters[i]); if ((pObjectTrackEventResult->nEventType >> i & 0x01) == 0x01)
for (unsigned int j = 0; j < pPointInfo->nPointCounters[i]; j++)
{ {
printf("pSrcPointX=%d,pSrcPointY=%d\n", pPointInfo->pSrcPointX[i][j], pPointInfo->pSrcPointY[i][j]); HxTaskDispatch::alarm_upload_event(algorithm_type,
current_time,
channel,
i + 1,
pObjectTrackEventResult->nDangerLevel,
pObjectTrackEventResult->objInfo,
pObjectTrackEventResult->nObjectNumber,
pObjectTrackEventResult->tFaceLandMarks,
pObjectTrackEventResult->nFaceLandMarksNum,
pObjectTrackEventResult->nLeftLineType,
pObjectTrackEventResult->nRightLineType);
} }
} }
return;
} }
HxVideoDevice::HxVideoDevice(void) HxVideoDevice::HxVideoDevice(void)
{ {
detect_frame_buffer.u32Width = 1280; m_detect_frame_buffer.u32Width = 1280;
detect_frame_buffer.u32Height = 720; m_detect_frame_buffer.u32Height = 720;
MvGetFrameBlkInfo(&detect_frame_buffer); m_detect_frame_buffer.pu8VirAddr = (unsigned char *)calloc(m_detect_frame_buffer.u32Width * m_detect_frame_buffer.u32Height * 3, sizeof(unsigned char));
}
bgr_frame_buffer.u32Width = 1280; HxVideoDevice::~HxVideoDevice(void)
bgr_frame_buffer.u32Height = 720; {
MvGetFrameBlkInfo(&bgr_frame_buffer); free(m_detect_frame_buffer.pu8VirAddr);
} }
void HxVideoDevice::set(int type, QString address) void HxVideoDevice::set(int type, QString address)
{ {
this->type = type; m_type = type;
this->address = address; m_address = address;
#if USE_ALGORITHM #if USE_ALGORITHM
auto result = MvSetAlgResultFuncCallback(type, algorithm_alarm_callback, nullptr); auto result = MvSetAlgResultFuncCallback(m_type, algorithm_detection_callback, nullptr);
if (result != 0) if (result != 0)
return; return;
#endif #endif
@ -158,199 +99,165 @@ void HxVideoDevice::set(int type, QString address, BsdWarnRegion region)
{ {
Q_UNUSED(region); Q_UNUSED(region);
this->type = type; m_type = type;
this->address = address; m_address = address;
this->detection_status = false; m_detection_status = false;
#if USE_ALGORITHM #if USE_ALGORITHM
auto result = MvSetAlgResultFuncCallback(type, algorithm_alarm_callback, nullptr); auto result = MvSetAlgResultFuncCallback(m_type, algorithm_detection_callback, nullptr);
if (result != 0) if (result != 0)
return; return;
MvSetBsdWarnRegion(type, &region); MvSetBsdWarnRegion(m_type, &region);
#endif #endif
start(); start();
} }
void HxVideoDevice::set(bool status) { detection_status = status; } void HxVideoDevice::set(bool status) { m_detection_status = status; }
bool HxVideoDevice::get_alarm_detection_timestamp(void) { return alarm_detection_timestamp.secsTo(QDateTime::currentDateTime()) > 10; } bool HxVideoDevice::determine_alarm_detection_timestamp(int event_type)
QString HxVideoDevice::snap()
{ {
// QString filename = ""; if (!m_alarm_detection_timestamps.contains(event_type))
{
m_alarm_detection_timestamps.insert(event_type, QDateTime::currentDateTime());
return true;
}
// record_frames_mutex.lock(); return m_alarm_detection_timestamps[event_type].secsTo(QDateTime::currentDateTime()) > HxDataBase::alarm_protect_timestamp.at(event_type).toInt();
// if (record_frames.size() > 0)
// filename = record_frames.last();
// record_frames_mutex.unlock();
// QFile file(filename);
// if (file.open(QIODevice::ReadOnly))
// return file.readAll().toBase64();
// return "";
Mat mat;
video_frame_mutex.lock();
video_frame.copyTo(mat);
video_frame_mutex.unlock();
return snap(mat);
} }
QString HxVideoDevice::build_image(int frame_id) void HxVideoDevice::create_alarm_data(int event_type, QString filename)
{ {
auto start_id = frame_id - video_fps * 5, end_id = frame_id + video_fps * 5; /* 更新报警检测时间戳 */
m_alarm_detection_timestamps[event_type] = QDateTime::currentDateTime();
alarm_detection_timestamp = QDateTime::currentDateTime(); /* 如果创建队列中存在该文件, 则不在重复创建 */
if (m_records.contains(filename))
return;
QString filename = QString("%1_%2_%3.jpg").arg(start_id > 0 ? start_id : 0).arg(end_id).arg(QDateTime::currentDateTime().toString("yyyyMMddHHmmsszzz")); /* 创建线程 */
QtConcurrent::run([=](QDateTime _alarm_timestamp, QString _filename)
{
Mat mat;
int frame_id = 0;
VideoCapture capture;
HxVideoWriter video_writer;
record_frames_mutex.lock(); /* 添加文件名称, 表示正在创建 */
if (record_frames.contains(frame_id)) m_records_mutex.lock();
QFile::copy(record_frames[frame_id], QString("%1/%2").arg(TEMPORARY_ALARM_DIRECTORY).arg(filename)); m_records.append(filename);
record_frames_mutex.unlock(); m_records_mutex.unlock();
HxTaskDispatch::enqueue_upload_file(filename); sleep(HxDataBase::recording_prepend_time);
return QString("/%1/%2/alarm/%3").arg(QDateTime::currentDateTime().toString("yyyyMMdd"), HxDataBase::device_id, filename); QQueue<HxVideoFrame> frames;
}
QString HxVideoDevice::build_video(int frame_id) m_prerecorded_frames_mutex.lock();
{ for (auto it = m_prerecorded_frames.begin(); it != m_prerecorded_frames.end(); ++it) {
auto start_id = frame_id - video_fps * 5, end_id = frame_id + video_fps * 5; if(it->time > _alarm_timestamp.addSecs(-1 * (HxDataBase::recording_prepend_time + 1)) && it->time < _alarm_timestamp.addSecs(HxDataBase::recording_prepend_time + 1))
frames.enqueue(it->copy());
}
m_prerecorded_frames_mutex.unlock();
QString filename = QString("%1_%2_%3.mp4").arg(start_id > 0 ? start_id : 0).arg(end_id).arg(QDateTime::currentDateTime().toString("yyyyMMddHHmmsszzz")); QString image_path = QString("%1/%2.jpg").arg(TEMPORARY_RECORD_DIRECTORY, _filename);
QString record_path = QString("%1/%2.avi").arg(TEMPORARY_RECORD_DIRECTORY, _filename);
QString _record_path = QString("%1/%2.mp4").arg(TEMPORARY_RECORD_DIRECTORY, _filename);
record_queue_mutex.lock(); HxLog::append("recording", QString("%1 frames count=%2").arg(_record_path).arg(frames.count()));
record_queue.enqueue(filename);
record_queue_mutex.unlock();
return QString("/%1/%2/alarm/%3").arg(QDateTime::currentDateTime().toString("yyyyMMdd"), HxDataBase::device_id, filename); while(!frames.isEmpty())
{
frame_id++;
auto frame = frames.dequeue();
/* 如果文件未被打开 */
if(!video_writer.open_status)
{
/* 查找关键帧 */
if (frame.packet->flags & AV_PKT_FLAG_KEY)
{
HxLog::append("recording", QString("%1 find %2 (AV_PKT_FLAG_KEY)").arg(_record_path).arg(frame_id));
/* 打开(创建)文件 */
video_writer.open(frame.ifmt_ctx, record_path);
if(!video_writer.open_status)
{
video_writer.close();
frame.free();
goto END;
}
}
}
/* 在打开的状态, 开始写入帧数据 */
if(video_writer.open_status)
{
video_writer.send(frame.packet);
}
frame.free();
msleep(10);
}
if(video_writer.open_status)
{
video_writer.close();
if(!QFile::exists(record_path))
goto END;
HxLog::append("recording", QString("%1 create success").arg(_record_path));
capture = VideoCapture(record_path.toUtf8().data());
if(capture.isOpened())
{
capture.set(CAP_PROP_POS_FRAMES, static_cast<int>(capture.get(CV_CAP_PROP_FRAME_COUNT)) / 2);
if(capture.read(mat))
{
vector <int> compression_params;
compression_params.push_back(IMWRITE_JPEG_QUALITY);
compression_params.push_back(90);
if(imwrite(image_path.toUtf8().data(), mat, compression_params))
HxTaskDispatch::enqueue_upload_file(_filename+".jpg");
}
capture.release();
}
QFile::rename(record_path, _record_path);
HxTaskDispatch::enqueue_upload_file(_filename+".mp4");
END:
while(!frames.isEmpty())
frames.dequeue().free();
/* 删除文件表示, 待验证 */
m_records_mutex.lock();
m_records.removeAll(_filename);
m_records_mutex.unlock();
} },
m_alarm_detection_timestamps[event_type], filename);
} }
void HxVideoDevice::test(void) void HxVideoDevice::test(void)
{ {
ObjectTrackEventResult pObjectTrackEventResult; ObjectTrackEventResult pObjectTrackEventResult;
pObjectTrackEventResult.nFrameId = record_frames.lastKey(); pObjectTrackEventResult.nFrameId = 0;
pObjectTrackEventResult.nEventType = EVENT_PCW; pObjectTrackEventResult.nEventType = m_type == 0 ? (ObjectEventType)(EVENT_PCW | EVENT_HMW) : EVENT_YAWN;
pObjectTrackEventResult.nObjectNumber = 1; pObjectTrackEventResult.nObjectNumber = 1;
pObjectTrackEventResult.objInfo[0].nDetectType = PEDESTRIAN_TYPE; pObjectTrackEventResult.objInfo[0].nDetectType = PEDESTRIAN_TYPE;
algorithm_alarm_callback(0, &pObjectTrackEventResult, nullptr); algorithm_detection_callback(0, &pObjectTrackEventResult, nullptr);
} }
vector<uint8_t> HxVideoDevice::compress(Mat frame, int quality) void HxVideoDevice::read_process(void)
{
vector<uint8_t> buffer;
vector<int> compress_params;
compress_params.push_back(IMWRITE_JPEG_QUALITY);
compress_params.push_back(quality);
imencode(".jpg", frame, buffer, compress_params);
return buffer;
}
QString HxVideoDevice::snap(Mat frame) { return frame.data == nullptr ? "" : snap(compress(frame, 50)); }
QString HxVideoDevice::snap(vector<uint8_t> buffer) { return QString(QByteArray::fromRawData((const char*)buffer.data(), buffer.size()).toBase64()); }
void HxVideoDevice::recording_creation_task(void)
{
while (true)
{
if (record_queue.size() > 0)
{
record_queue_mutex.lock();
auto filename = record_queue.dequeue();
record_queue_mutex.unlock();
HxLog::append("recording", QString("type=%1, count=%2, %3 creation task start").arg(type).arg(record_queue.size()).arg(filename));
auto data = filename.split("_");
auto start_id = data[0].toInt(), end_id = data[1].toInt();
while (true)
{
record_frames_mutex.lock();
auto first_key = record_frames.firstKey();
auto last_key = record_frames.lastKey();
record_frames_mutex.unlock();
if (last_key < first_key)
{
HxLog::append("recording", QString("%1 not found last id, creation failed").arg(filename));
break;
}
/* 判断最新的视频帧是否超过设定的时间 */
if (last_key >= end_id)
{
record_frames_mutex.lock();
auto _record_frames = record_frames;
_record_frames.detach();
record_frames_mutex.unlock();
QString fullpath = QString("%1/%2").arg(TEMPORARY_ALARM_DIRECTORY).arg(filename);
VideoWriter writer(fullpath.toUtf8().data(), CV_FOURCC('m', 'p', '4', 'v'), video_fps, Size(video_width, video_height), true);
for (int i = start_id; i <= end_id; i++)
{
if (_record_frames.contains(i))
{
auto __frame = imread(_record_frames[i].toUtf8().data(), CV_LOAD_IMAGE_COLOR);
writer.write(__frame);
HxLog::append("recording", QString("%1 write frame id:%2").arg(filename).arg(i));
}
}
writer.release();
HxTaskDispatch::enqueue_upload_file(filename);
HxLog::append("recording", QString("%1 creation success").arg(type).arg(filename));
break;
}
msleep(100);
}
}
msleep(500);
}
}
void HxVideoDevice::video_frame_queue_check(void)
{
while (true)
{
/* 缓存队列超过30s, 删除掉头数据 */
record_frames_mutex.lock();
while (record_frames.count() > video_fps * 300)
{
auto filename = record_frames.first();
QFile::remove(filename);
record_frames.remove(record_frames.firstKey());
msleep(1);
}
record_frames_mutex.unlock();
msleep(1000);
}
}
void HxVideoDevice::video_frame_read_process()
{ {
while (true) while (true)
{ {
@ -358,7 +265,7 @@ void HxVideoDevice::video_frame_read_process()
int error = 0; int error = 0;
AVDictionary* avdic = nullptr; AVDictionary *avdic = nullptr;
/* 减少卡顿或者花屏现象,相当于增加或扩大了缓冲区,给予编码和发送足够的时间 */ /* 减少卡顿或者花屏现象,相当于增加或扩大了缓冲区,给予编码和发送足够的时间 */
av_dict_set(&avdic, "buffer_size", "1024000", 0); av_dict_set(&avdic, "buffer_size", "1024000", 0);
@ -375,7 +282,7 @@ void HxVideoDevice::video_frame_read_process()
ifmt_ctx = avformat_alloc_context(); ifmt_ctx = avformat_alloc_context();
error = avformat_open_input(&ifmt_ctx, address.toUtf8().data(), nullptr, &avdic); error = avformat_open_input(&ifmt_ctx, m_address.toUtf8().data(), nullptr, &avdic);
av_dict_free(&avdic); av_dict_free(&avdic);
@ -383,7 +290,7 @@ void HxVideoDevice::video_frame_read_process()
{ {
avformat_free_context(ifmt_ctx); avformat_free_context(ifmt_ctx);
HxLog::append("videolivestream", QString("type=%1, avformat_open_input failed, errorcode=%2").arg(type).arg(error)); HxLog::append("videolivestream", QString("type=%1, avformat_open_input failed, errorcode=%2").arg(m_type).arg(error));
continue; continue;
} }
@ -394,48 +301,34 @@ void HxVideoDevice::video_frame_read_process()
avformat_free_context(ifmt_ctx); avformat_free_context(ifmt_ctx);
HxLog::append("videolivestream", QString("type=%1, avformat_find_stream_info failed").arg(type)); HxLog::append("videolivestream", QString("type=%1, avformat_find_stream_info failed").arg(m_type));
return; return;
} }
av_dump_format(ifmt_ctx, 0, address.toUtf8().data(), 0); av_dump_format(ifmt_ctx, 0, m_address.toUtf8().data(), 0);
video_stream_index = -1; auto m_video_stream_index = -1;
for (uint i = 0; i < ifmt_ctx->nb_streams; i++) for (uint i = 0; i < ifmt_ctx->nb_streams; i++)
{ {
if (ifmt_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) if (ifmt_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
{ {
video_fps = ifmt_ctx->streams[i]->avg_frame_rate.num; m_video_stream_index = static_cast<int>(i);
video_width = ifmt_ctx->streams[i]->codecpar->width;
video_height = ifmt_ctx->streams[i]->codecpar->height;
video_stream_index = static_cast<int>(i);
HxLog::append("videolivestream", QString("type=%1, video_fps=%2, video_width=%3, video_height=%4").arg(type).arg(video_fps).arg(video_width).arg(video_height)); m_video_fps = ifmt_ctx->streams[i]->avg_frame_rate.num;
HxLog::append("videolivestream", QString("type=%1, video_fps=%2").arg(m_type).arg(m_video_fps));
break; break;
} }
} }
if (video_stream_index == -1) if (m_video_stream_index == -1)
{ {
avformat_close_input(&ifmt_ctx); avformat_close_input(&ifmt_ctx);
avformat_free_context(ifmt_ctx); avformat_free_context(ifmt_ctx);
HxLog::append("videolivestream", QString("type=%1, not found video stream").arg(type)); HxLog::append("videolivestream", QString("type=%1, not found video stream").arg(m_type));
return;
}
bool decoder_status = false;
#if USE_ALGORITHM
decoder_status = decoder.initialization();
#else
decoder_status = decoder.initialization(ifmt_ctx);
#endif
if (!decoder_status)
{
HxLog::append("videolivestream", QString("type=%1, decoder initialization failed").arg(type));
return; return;
} }
@ -447,22 +340,17 @@ void HxVideoDevice::video_frame_read_process()
if (av_read_frame(ifmt_ctx, &packet) < 0) if (av_read_frame(ifmt_ctx, &packet) < 0)
break; break;
if (packet.stream_index == video_stream_index) m_decoding_frames_mutex.lock();
{ m_decoding_frames.enqueue(HxVideoFrame(ifmt_ctx, &packet));
Mat mat; m_decoding_frames_mutex.unlock();
decoder.decode(&packet, &mat);
if (mat.data != nullptr) m_prerecorded_frames_mutex.lock();
{ m_prerecorded_frames.enqueue(HxVideoFrame(ifmt_ctx, &packet));
video_frame_mutex.lock(); m_prerecorded_frames_mutex.unlock();
mat.copyTo(video_frame);
video_frame_mutex.unlock();
}
}
av_packet_unref(&packet); av_packet_unref(&packet);
msleep(1000 / video_fps); msleep(1000 / m_video_fps);
} }
if (ifmt_ctx != nullptr) if (ifmt_ctx != nullptr)
@ -471,137 +359,91 @@ void HxVideoDevice::video_frame_read_process()
avformat_free_context(ifmt_ctx); avformat_free_context(ifmt_ctx);
ifmt_ctx = nullptr; ifmt_ctx = nullptr;
} }
}
}
decoder.release(); void HxVideoDevice::decoding_process(void)
{
Mat mat;
int m_frame_id = 0;
while (true)
{
msleep(10);
if (m_decoding_frames.isEmpty())
continue;
m_decoding_frames_mutex.lock();
auto frame = m_decoding_frames.dequeue();
m_decoding_frames_mutex.unlock();
if (!m_video_decoder.status)
{
#if USE_ALGORITHM
m_video_decoder.initialization();
#else
if (ifmt_ctx != nullptr)
m_video_decoder.initialization(ifmt_ctx);
#endif
if (!m_video_decoder.status)
{
HxLog::append("videolivestream", QString("type=%1, decoder initialization failed").arg(m_type));
goto frame_free;
}
}
/* 获取YUV数据 */
m_video_decoder.decode(frame.packet, &mat);
if (mat.data != nullptr)
{
/* 是否开始进行分析 */
if (m_detection_status)
{
/* 获取车速 */
auto car_info = HxTaskDispatch::get_car_info();
if (car_info->fVelocity >= 10)
{
m_detect_frame_buffer.nFrameId = m_frame_id; // 帧号
m_detect_frame_buffer.u64PTS = QDateTime::currentMSecsSinceEpoch(); // 时间戳(毫秒)
m_detect_frame_buffer.pu8VirAddr = mat.data;
#if USE_ALGORITHM
MvObjectEventDetect(this->m_type, &m_detect_frame_buffer, car_info);
#endif
m_frame_id++;
}
}
}
frame_free:
frame.free();
} }
} }
void HxVideoDevice::run() void HxVideoDevice::run()
{ {
/* 启动 录像创建任务 */
QtConcurrent::run(this, &HxVideoDevice::recording_creation_task);
/* 创建 缓存队列监控线程 */
QtConcurrent::run(this, &HxVideoDevice::video_frame_queue_check);
/* 创建 视频读取线程 */ /* 创建 视频读取线程 */
QtConcurrent::run(this, &HxVideoDevice::video_frame_read_process); QtConcurrent::run(this, &HxVideoDevice::read_process);
QDateTime time = QDateTime::currentDateTime(); /* 创建 录像 线程 */
QtConcurrent::run(this, &HxVideoDevice::decoding_process);
while (true) while (true)
{ {
// if(time.secsTo(QDateTime::currentDateTime()) >= (1000/video_fps)) /* 判断是否超过预录时长 */
if (!m_prerecorded_frames.isEmpty())
{ {
time = QDateTime::currentDateTime(); while (QDateTime::currentDateTime() > m_prerecorded_frames.first().time.addSecs(60))
Mat mat;
video_frame_mutex.lock();
video_frame.copyTo(mat);
video_frame_mutex.unlock();
if (mat.data != nullptr)
{ {
QString filename = QString("%1/%2_%3_%4.jpg").arg(TEMPORARY_VIDEO_DIRECTORY).arg(QDateTime::currentDateTime().toString("yyyyMMddHHmmsszzz")).arg(type).arg(frame_id); m_prerecorded_frames_mutex.lock();
m_prerecorded_frames.dequeue().free();
vector<int> compress_params; m_prerecorded_frames_mutex.unlock();
compress_params.push_back(IMWRITE_JPEG_QUALITY);
compress_params.push_back(90);
imwrite(filename.toUtf8().data(), mat, compress_params);
record_frames_mutex.lock();
record_frames.insert(frame_id, filename);
record_frames_mutex.unlock();
if (detection_status)
{
auto car_info = HxTaskDispatch::get_car_info();
if (car_info->fVelocity > 10)
{
bgr_frame_buffer.nFrameId = frame_id; // 帧号
bgr_frame_buffer.u64PTS = QDateTime::currentMSecsSinceEpoch(); // 时间戳(毫秒)
memcpy(bgr_frame_buffer.pu8VirAddr, mat.data, 1280 * 720 * 3);
MvConvertImage(&bgr_frame_buffer, &detect_frame_buffer); // bgr->nv16
#if USE_ALGORITHM
MvObjectEventDetect(this->type, &detect_frame_buffer, car_info);
#endif
}
}
frame_id++;
} }
} }
msleep(15);
msleep(1000);
} }
} }
int HxVideoDevice::MvGetFrameBlkInfo(VideoFrameDataInfo* pImageDataInfo)
{
Q_UNUSED(pImageDataInfo);
#if USE_ALGORITHM
if (pImageDataInfo == NULL)
return -1;
pImageDataInfo->pu8VirAddr = (unsigned char*)calloc(pImageDataInfo->u32Width * pImageDataInfo->u32Height * 3, sizeof(unsigned char));
if (pImageDataInfo->pu8VirAddr == NULL)
return -1;
#endif
return 0;
}
int HxVideoDevice::MvReleaseFrameBlkInfo(VideoFrameDataInfo* pImageDataInfo)
{
Q_UNUSED(pImageDataInfo);
#if USE_ALGORITHM
if (pImageDataInfo == NULL)
return -1;
if (pImageDataInfo->pu8VirAddr == NULL)
return -1;
free(pImageDataInfo->pu8VirAddr);
#endif
return 0;
}
int HxVideoDevice::MvConvertImage(VideoFrameDataInfo* pSrcImageDataInfo, VideoFrameDataInfo* pDstImageDataInfo)
{
Q_UNUSED(pSrcImageDataInfo);
Q_UNUSED(pDstImageDataInfo);
#if USE_ALGORITHM
rga_buffer_t src;
rga_buffer_t dst;
src = wrapbuffer_virtualaddr(pSrcImageDataInfo->pu8VirAddr, pSrcImageDataInfo->u32Width, pSrcImageDataInfo->u32Height, RK_FORMAT_BGR_888);
dst = wrapbuffer_virtualaddr(pDstImageDataInfo->pu8VirAddr, pDstImageDataInfo->u32Width, pDstImageDataInfo->u32Height, RK_FORMAT_YCbCr_420_SP);
if (src.width == 0 || dst.width == 0)
{
return -1;
}
src.format = RK_FORMAT_BGR_888;
dst.format = RK_FORMAT_YCbCr_422_SP;
IM_STATUS STATUS;
STATUS = imcvtcolor(src, dst, src.format, dst.format);
if (STATUS != IM_STATUS_SUCCESS)
{
qDebug("imcvtcolor error\n");
return -1;
}
pDstImageDataInfo->u64PTS = pSrcImageDataInfo->u64PTS;
pDstImageDataInfo->nFrameId = pSrcImageDataInfo->nFrameId;
#endif
return 0;
}

View File

@ -1,7 +1,6 @@
#ifndef HXVIDEODEVICE_H #ifndef HXVIDEODEVICE_H
#define HXVIDEODEVICE_H #define HXVIDEODEVICE_H
#include <QtConcurrent> #include <QtConcurrent>
#include <QThread> #include <QThread>
#include <QDateTime> #include <QDateTime>
@ -10,12 +9,10 @@
#include "HxTaskDispatch.h" #include "HxTaskDispatch.h"
#include "HxDataBase.h"
#include "HxVideoWriter.h"
#include "HxVideoDecoder.h" #include "HxVideoDecoder.h"
#include <opencv2/opencv.hpp>
//#include "HxMpp.h"
#if USE_ALGORITHM #if USE_ALGORITHM
#include "rga.h" #include "rga.h"
#include "im2d.hpp" #include "im2d.hpp"
@ -29,75 +26,143 @@ extern "C"
using namespace cv; using namespace cv;
using namespace std; using namespace std;
typedef struct __HxVideoFrame
{
QDateTime time;
AVFormatContext *ifmt_ctx;
AVPacket *packet;
__HxVideoFrame() {}
__HxVideoFrame(AVFormatContext *ifmt_ctx, AVPacket *packet)
{
this->time = QDateTime::currentDateTime();
this->ifmt_ctx = ifmt_ctx;
this->packet = av_packet_clone(packet);
}
__HxVideoFrame(QDateTime time, AVFormatContext *ifmt_ctx, AVPacket *packet)
{
this->time = time;
this->ifmt_ctx = ifmt_ctx;
this->packet = av_packet_clone(packet);
}
__HxVideoFrame copy() { return __HxVideoFrame(this->time, this->ifmt_ctx, this->packet); }
void free()
{
ifmt_ctx = nullptr;
if (packet)
{
av_packet_unref(packet);
av_packet_free(&packet);
}
}
} HxVideoFrame;
class HxVideoDevice : public QThread class HxVideoDevice : public QThread
{ {
Q_OBJECT Q_OBJECT
public: public:
HxVideoDevice(void); HxVideoDevice(void);
~HxVideoDevice(void);
/**
* @brief
* @param type
* @param address
*/
void set(int type, QString address); void set(int type, QString address);
/**
* @brief
* @param type
* @param address
* @param region BSD报警区域
*/
void set(int type, QString address, BsdWarnRegion region); void set(int type, QString address, BsdWarnRegion region);
/**
* @brief
* @param status true: ; false:
*/
void set(bool status); void set(bool status);
bool get_alarm_detection_timestamp(void);
QString snap(void);
QString build_image(int frame_id); /**
QString build_video(int frame_id); * @brief
* @param event_type
* @return true: ; false:
*/
bool determine_alarm_detection_timestamp(int event_type);
/**
* @brief ()
* @param event_type
* @param filename
*/
void create_alarm_data(int event_type, QString filename);
/**
* @brief
*/
void test(void); void test(void);
private: private:
vector<uint8_t> compress(Mat frame, int quality); /* 读取线程 */
QString snap(Mat frame); void read_process(void);
QString snap(vector<uint8_t> data);
void recording_creation_task(void);
void video_frame_queue_check(void);
void video_frame_read_process(void); /* 解码线程 */
void video_decoder_packet(AVPacket packet); void decoding_process(void);
protected: protected:
void run() override; void run() override;
;
private: private:
int MvGetFrameBlkInfo(VideoFrameDataInfo *pImageDataInfo); /* 算法通道类型 */
int MvReleaseFrameBlkInfo(VideoFrameDataInfo *pImageDataInfo); int m_type;
int MvConvertImage(VideoFrameDataInfo *pSrcImageDataInfo, VideoFrameDataInfo *pDstImageDataInfo);
private: /* 视频帧率 */
int type; int m_video_fps = 25;
int frame_id = 0;
QString address = "";
QDateTime alarm_detection_timestamp = QDateTime::currentDateTime();
bool detection_status = true;
QMutex record_queue_mutex; /* 视频地址(RTSP流) */
QQueue<QString> record_queue; QString m_address = "";
VideoFrameDataInfo detect_frame_buffer; /* 报警检测时间 */
VideoFrameDataInfo bgr_frame_buffer; QMap<int, QDateTime> m_alarm_detection_timestamps;
// QMutex video_frames_mutex; /* 检测状态(是否送帧给算法的标识) */
// QQueue<Mat> video_frames; bool m_detection_status = true;
QMutex video_frame_mutex; /* 正在创建的录像文件 */
Mat video_frame; QMutex m_records_mutex;
QList<QString> m_records;
QMutex record_frames_mutex; /* 视频图像帧信息 */
QMap<int, QString> record_frames; VideoFrameDataInfo m_detect_frame_buffer;
int video_fps = 25; /* FFmpeg */
int video_width = 0, video_height = 0;
int video_stream_index = 0;
bool connect_status;
AVFormatContext *ifmt_ctx; AVFormatContext *ifmt_ctx;
HxVideoDecoder decoder; /* 解码帧队列及锁 */
QMutex m_decoding_frames_mutex;
QQueue<HxVideoFrame> m_decoding_frames;
// uint8_t *video_out_buffer = nullptr; /* 预录帧队列及锁 */
// struct SwsContext *video_sws_context = nullptr; QMutex m_prerecorded_frames_mutex;
QQueue<HxVideoFrame> m_prerecorded_frames;
// AVCodecContext *video_dec_ctx = nullptr; /* 视频打包类 */
// AVFrame *video_dec_frame = nullptr, *video_picture_frame = nullptr; HxVideoWriter m_video_writer;
/* 视频解码类 */
HxVideoDecoder m_video_decoder;
}; };
#endif #endif

239
app/HxVideoWriter.h Normal file
View File

@ -0,0 +1,239 @@
#ifndef HXVIDEOWRITER_H
#define HXVIDEOWRITER_H
#include <QObject>
#include <QDebug>
extern "C"
{
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libavutil/time.h"
#include "libswscale/swscale.h"
#include "libswresample/swresample.h"
#include <libavutil/audio_fifo.h>
}
class HxVideoWriter
{
public:
HxVideoWriter() : open_status(false) {}
void open(AVFormatContext *ifmt_ctx, QString filename)
{
int ret = -1;
video_index = -1;
audio_index = -1;
video_frame_index = 0;
audio_frame_index = 0;
ofmt_ctx = nullptr;
video_dec_stream = nullptr;
audio_dec_stream = nullptr;
/* 查找流中视频与音频位置 */
if (ifmt_ctx->nb_streams > 2)
{
m_error = QObject::tr("数据流异常");
return;
}
for (uint i = 0; i < ifmt_ctx->nb_streams; i++)
{
if (ifmt_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
{
video_index = static_cast<int>(i);
video_dec_stream = ifmt_ctx->streams[i];
}
else if (ifmt_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
{
audio_index = static_cast<int>(i);
audio_dec_stream = ifmt_ctx->streams[i];
}
}
if (video_index == -1)
{
m_error = QObject::tr("未找到视频流");
return;
}
avformat_alloc_output_context2(&ofmt_ctx, nullptr, nullptr, filename.toStdString().data());
if (!ofmt_ctx)
{
m_error = QObject::tr("无法打开输出文件");
return;
}
for (uint i = 0; i < ifmt_ctx->nb_streams; i++)
{
/* 根据输入流创建输出流 */
AVCodec *codec = avcodec_find_decoder(ifmt_ctx->streams[i]->codecpar->codec_id);
AVStream *out_stream = avformat_new_stream(ofmt_ctx, codec);
if (!out_stream)
{
m_error = QObject::tr("无法创建输出流");
return;
}
/* 复制AVCodecContext的设置 */
AVCodecContext *codec_ctx = avcodec_alloc_context3(codec);
ret = avcodec_parameters_to_context(codec_ctx, ifmt_ctx->streams[i]->codecpar);
if (ret < 0)
{
m_error = QObject::tr("未能将输入流中的codepar复制到编解码器上下文");
avcodec_free_context(&codec_ctx);
return;
}
codec_ctx->codec_tag = 0;
if (ofmt_ctx->oformat->flags & AVFMT_GLOBALHEADER)
codec_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
ret = avcodec_parameters_from_context(out_stream->codecpar, codec_ctx);
if (ret < 0)
{
m_error = QObject::tr("无法将编解码器上下文复制到输出流codepar上下文");
avcodec_free_context(&codec_ctx);
return;
}
avcodec_free_context(&codec_ctx);
}
ofmt_ctx->streams[video_index]->time_base = {1, 25};
av_dump_format(ofmt_ctx, 0, filename.toStdString().data(), 1);
if (!(ofmt_ctx->oformat->flags & AVFMT_NOFILE))
{
ret = avio_open(&ofmt_ctx->pb, filename.toStdString().data(), AVIO_FLAG_WRITE);
if (ret < 0)
{
m_error = QObject::tr("无法打开输出文件");
return;
}
}
ret = avformat_write_header(ofmt_ctx, nullptr);
if (ret < 0)
{
m_error = QObject::tr("无法写入文件头信息");
return;
}
open_status = true;
}
void send(AVPacket *packet)
{
auto out_stream = ofmt_ctx->streams[packet->stream_index];
if (packet->stream_index == video_index)
{
auto pts = av_rescale_q_rnd(packet->pts, video_dec_stream->time_base, out_stream->time_base, (AVRounding)(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX));
auto dts = av_rescale_q_rnd(packet->dts, video_dec_stream->time_base, out_stream->time_base, (AVRounding)(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX));
if (video_frame_index == 0)
{
video_pts = pts < 0 ? 0 : pts;
video_dts = dts < 0 ? 0 : dts;
}
else if (video_frame_index == 1)
{
if (video_pts > pts)
video_pts = pts;
else
video_pts = pts - video_pts;
if (video_dts > dts)
video_dts = dts;
else
video_dts = dts - video_dts;
}
packet->pts = video_pts * video_frame_index;
packet->dts = video_dts * video_frame_index;
packet->duration = 0;
video_frame_index++;
}
else if (packet->stream_index == audio_index)
{
auto pts = av_rescale_q_rnd(packet->pts, audio_dec_stream->time_base, out_stream->time_base, (AVRounding)(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX));
auto dts = av_rescale_q_rnd(packet->dts, audio_dec_stream->time_base, out_stream->time_base, (AVRounding)(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX));
if (audio_frame_index == 1 && pts > 0)
{
audio_pts = pts - audio_pts;
audio_dts = dts - audio_dts;
}
else if (audio_frame_index == 0)
{
audio_pts = pts < 0 ? 0 : pts;
audio_dts = dts < 0 ? 0 : dts;
}
packet->pts = audio_pts * audio_frame_index;
packet->dts = audio_dts * audio_frame_index;
packet->duration = 0;
audio_frame_index++;
}
auto ret = av_interleaved_write_frame(ofmt_ctx, packet);
if (ret < 0)
{
// HxTrace::debug_write_line("VideoWrite", QString("Error muxing packet, ret = %1").arg(ret));
qDebug() << "Error muxing packet";
// 这里是否需要做处理 ???
}
}
void close()
{
// Write file trailer
if (open_status)
av_write_trailer(ofmt_ctx);
video_pts = 0;
video_dts = 0;
audio_pts = 0;
audio_dts = 0;
video_frame_index = 0;
audio_frame_index = 0;
/* close output */
if (ofmt_ctx && !(ofmt_ctx->oformat->flags & AVFMT_NOFILE))
avio_close(ofmt_ctx->pb);
avformat_free_context(ofmt_ctx);
}
QString error() { return m_error; }
public:
bool open_status;
private:
QString m_error;
int video_index, audio_index;
int video_frame_index, audio_frame_index;
long long video_pts, video_dts, audio_pts, audio_dts;
AVFormatContext *ofmt_ctx;
AVStream *video_dec_stream, *audio_dec_stream;
};
#endif

View File

@ -23,7 +23,7 @@ CONFIG += c++11
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
# Input # Input
HEADERS += HxDataBase.h HxTaskDispatch.h HxUtils.h HxVideoDevice.h HxVideoDecoder.h HEADERS += HxDataBase.h HxTaskDispatch.h HxUtils.h HxVideoDevice.h HxVideoDecoder.h HxVideoWriter.h
SOURCES += HxDataBase.cpp HxTaskDispatch.cpp HxVideoDevice.cpp main.cpp SOURCES += HxDataBase.cpp HxTaskDispatch.cpp HxVideoDevice.cpp main.cpp
#DEFINES += USE_RABBITMQ #DEFINES += USE_RABBITMQ
@ -56,10 +56,8 @@ unix {
PRE_TARGETDEPS += $$PWD/external/libObjectEventDetect.a PRE_TARGETDEPS += $$PWD/external/libObjectEventDetect.a
LIBS += -L$$PWD/external/npu -lrknn_api LIBS += -L$$PWD/external/npu -lrknn_api
# LIBS += /usr/lib/librga.so LIBS += /usr/lib/librga.so
LIBS += -L/root/works/librga/libs/Linux/gcc-aarch64 -lrga
PRE_TARGETDEPS += /root/works/librga/libs/Linux/gcc-aarch64/librga.a
LIBS += /usr/local/lib/librockchip_mpp.so LIBS += /usr/local/lib/librockchip_mpp.so
} }
@ -70,4 +68,4 @@ unix {
win32 { win32 {
LIBS += D:/Library/opencv/build/install/x64/mingw/lib/libopencv_*.a LIBS += D:/Library/opencv/build/install/x64/mingw/lib/libopencv_*.a
LIBS += -LD:/Library/ffmpeg/4.4.4/lib -lavcodec -lavdevice -lavfilter -lavformat -lavutil -lpostproc -lswresample -lswscale LIBS += -LD:/Library/ffmpeg/4.4.4/lib -lavcodec -lavdevice -lavfilter -lavformat -lavutil -lpostproc -lswresample -lswscale
} }

View File

@ -3,9 +3,6 @@
#include <HxDataBase.h> #include <HxDataBase.h>
#include "HxTaskDispatch.h" #include "HxTaskDispatch.h"
#include <opencv2/opencv.hpp>
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
QCoreApplication a(argc, argv); QCoreApplication a(argc, argv);
@ -17,8 +14,8 @@ int main(int argc, char *argv[])
HxLog::append("application", "startup"); HxLog::append("application", "startup");
/* 创建数据缓存目录 */ /* 创建数据缓存目录 */
HxDir::mkdir({{TEMPORARY_VIDEO_DIRECTORY}, HxDir::mkpath({{TEMPORARY_LOG_DIRECTORY},
{TEMPORARY_ALARM_DIRECTORY}}); {TEMPORARY_RECORD_DIRECTORY}});
/* 设置最大线程个数 */ /* 设置最大线程个数 */
QThreadPool::globalInstance()->setMaxThreadCount(100); QThreadPool::globalInstance()->setMaxThreadCount(100);