V1.02
1. 删除图片存储到本地的方式; 2. 取流方式由Opencv修改为FFmpeg方式; 3. 解码后的数据直接转为RK_FORMAT_YCbCr_422_SP格式发送给算法; 4. 视频裸流数据存储在内存中,保存30s; 5. 报警图片从报警录像视频中获取;
This commit is contained in:
parent
a53d2f2ff7
commit
ff66a2e0d6
4153
.gitignore
vendored
4153
.gitignore
vendored
File diff suppressed because it is too large
Load Diff
36
ReadMe.md
36
ReadMe.md
|
@ -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
|
||||||
```
|
```
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
/* 倒车灯;1:亮;0:熄灭 */
|
/* 倒车灯;1:亮;0:熄灭 */
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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, ®ion);
|
MvSetBsdWarnRegion(m_type, ®ion);
|
||||||
#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;
|
|
||||||
}
|
|
||||||
|
|
|
@ -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
239
app/HxVideoWriter.h
Normal 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
|
10
app/app.pro
10
app/app.pro
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user