IVA/app/HxVideoDevice.cpp

407 lines
14 KiB
C++
Raw Normal View History

2023-10-20 23:36:22 +08:00
#include "HxVideoDevice.h"
/* bsd算法结果处理函数 */
void algorithm_alarm_callback(int nDataChannel, ObjectTrackEventResult *pObjectTrackEventResult, void *pPrivData)
{
Q_UNUSED(nDataChannel);
Q_UNUSED(pPrivData);
if (pObjectTrackEventResult->nEventType == 0)
return;
if (nDataChannel == 0) /* ADAS */
{
printf("ProcessAdasAlgResult nDataChannel=%d,nFrameId=%d,nObjectNumber=%d,nEventType=%x\n", nDataChannel, pObjectTrackEventResult->nFrameId, pObjectTrackEventResult->nObjectNumber, pObjectTrackEventResult->nEventType);
/* 生成报警图片 */
auto base64_string = TaskDispatch::build_alarm_image(ALGORITHM_TYPE_ADAS, 0, pObjectTrackEventResult->nFrameId);
/* 生成报警视频 */
auto filename = TaskDispatch::build_alarm_video(ALGORITHM_TYPE_ADAS, 0, pObjectTrackEventResult->nFrameId);
/* 上传 */
TaskDispatch::algorithm_alarm_event(0, 0, pObjectTrackEventResult->nEventType, 0, 0, 0, 0, 0, 0, 0, base64_string, filename);
}
else if (nDataChannel == 2) /* DSM */
{
printf("ProcessDsmAlgResult nDataChannel=%d,nFrameId=%d,nObjectNumber=%d,nEventType=%x\n", nDataChannel, pObjectTrackEventResult->nFrameId, pObjectTrackEventResult->nObjectNumber, pObjectTrackEventResult->nEventType);
/* 生成报警图片 */
auto base64_string = TaskDispatch::build_alarm_image(ALGORITHM_TYPE_DSM, 0, pObjectTrackEventResult->nFrameId);
/* 生成报警视频 */
auto filename = TaskDispatch::build_alarm_video(ALGORITHM_TYPE_DSM, 0, pObjectTrackEventResult->nFrameId);
/* 上传 */
TaskDispatch::algorithm_alarm_event(1, 0, pObjectTrackEventResult->nEventType, 0, 0, 0, 0, 0, 0, 0, base64_string, filename);
}
else if (nDataChannel == 1 || /* BSD-右前 */
nDataChannel == 3 || /* BSD-右后 */
nDataChannel == 4 || /* BSD-左前 */
nDataChannel == 5 || /* BSD-左后 */
nDataChannel == 6 || /* BSD-前 */
nDataChannel == 7) /* BSD-后 */
{
int channel = 0;
switch (nDataChannel)
{
case 6:
channel = 0;
break;
case 7:
channel = 1;
break;
case 4:
channel = 2;
break;
case 1:
channel = 3;
break;
case 5:
channel = 4;
break;
case 3:
channel = 5;
break;
}
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 base64_string = TaskDispatch::build_alarm_image(ALGORITHM_TYPE_BSD, channel, pObjectTrackEventResult->nFrameId);
/* 生成报警视频 */
auto filename = TaskDispatch::build_alarm_video(ALGORITHM_TYPE_BSD, channel, pObjectTrackEventResult->nFrameId);
/* 上传 */
TaskDispatch::algorithm_alarm_event(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,
base64_string,
filename);
}
}
}
VideoDevice::VideoDevice(void)
{
detect_frame_buffer.u32Width = 1280;
detect_frame_buffer.u32Height = 720;
MvGetFrameBlkInfo(&detect_frame_buffer);
bgr_frame_buffer.u32Width = 1280;
bgr_frame_buffer.u32Height = 720;
MvGetFrameBlkInfo(&bgr_frame_buffer);
}
void VideoDevice::set(int type, QString address)
{
this->type = type;
this->address = address;
#if USE_ALGORITHM
auto result = MvSetAlgResultFuncCallback(type, algorithm_alarm_callback, nullptr);
if (result != 0)
return;
#endif
start();
}
void VideoDevice::set(int type, QString address, BsdWarnRegion region)
{
Q_UNUSED(region);
this->type = type;
this->address = address;
this->detection_status = false;
#if USE_ALGORITHM
auto result = MvSetAlgResultFuncCallback(type, algorithm_alarm_callback, nullptr);
if (result != 0)
return;
MvSetBsdWarnRegion(type, &region);
#endif
start();
}
void VideoDevice::set(bool status) { detection_status = status; }
QString VideoDevice::snap() { return snap(video_frame); }
QString VideoDevice::build_image(int id)
{
if (video_frames_string.contains(id))
return snap(video_frames_string[id]);
return "";
}
QString VideoDevice::build_video(int id)
{
QString url = QString("ftp://%3/%4/%5/alarm/").arg(DataBase::ftp_address, QDateTime::currentDateTime().toString("yyyyMMdd"), DataBase::device_id);
QString filename = QString("%1.mp4").arg(QDateTime::currentDateTime().toString("yyyyMMddHHmmsszzz"));
QtConcurrent::run([=]()
{
if(video_frames_string.contains(id))
{
frame_mutex.lock();
auto first_key = video_frames_string.firstKey();
frame_mutex.unlock();
auto start_id = id - frame_fps * 10, end_id = id + frame_fps * 10;
start_id = start_id < first_key ? first_key : start_id;
qDebug() << "build video; start id = "<<start_id << " end id = " << end_id;
while(true)
{
frame_mutex.lock();
auto last_key = video_frames_string.lastKey();
frame_mutex.unlock();
// qDebug() << " end id = " << end_id << " last id = "<< last_key;
/* 判断最新的视频帧是否超过设定的时间 */
if(last_key >= end_id)
{
frame_mutex.lock();
auto _video_frames_string = video_frames_string;
_video_frames_string.detach();
frame_mutex.unlock();
VideoWriter writer(filename.toUtf8().data(), CV_FOURCC('m', 'p', '4', 'v'), frame_fps, Size(video_capture.get(CV_CAP_PROP_FRAME_WIDTH), video_capture.get(CV_CAP_PROP_FRAME_HEIGHT)), true);
for(int i = start_id; i <= end_id; i++)
{
auto __frame = imdecode(_video_frames_string[i], CV_LOAD_IMAGE_COLOR);
writer.write(__frame);
msleep(frame_fps);
qDebug() << " write "<< filename <<". frame id = " << i;
}
writer.release();
qDebug() << "video build finish";
HxProcessUtils::execute(QString("curl -u %1:%2 %3 --ftp-create-dirs -T %4")
.arg(DataBase::ftp_username,
DataBase::ftp_password,
url,
filename));
QFile::remove(filename);
return;
}
msleep(100);
}
} });
return url + filename;
}
void VideoDevice::test(void)
{
ObjectTrackEventResult pObjectTrackEventResult = {0};
pObjectTrackEventResult.nFrameId = video_frames_string.lastKey();
pObjectTrackEventResult.nEventType = EVENT_PCW;
pObjectTrackEventResult.nObjectNumber = 1;
pObjectTrackEventResult.objInfo[0].nDetectType = PEDESTRIAN_TYPE;
algorithm_alarm_callback(0, &pObjectTrackEventResult, nullptr);
}
vector<uint8_t> VideoDevice::compress(Mat frame, int quality)
{
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 VideoDevice::snap(Mat frame)
{
if (frame.data != nullptr)
return snap(compress(frame, 50));
return "";
}
QString VideoDevice::snap(vector<uint8_t> buffer)
{
QByteArray byteArray = QByteArray::fromRawData((const char *)buffer.data(), buffer.size());
return QString(byteArray.toBase64());
}
void VideoDevice::video_frame_queue_check()
{
if (video_frames_string.count() > frame_fps * 30)
{
frame_mutex.lock();
video_frames_string.remove(video_frames_string.firstKey());
frame_mutex.unlock();
}
}
void VideoDevice::read_frame()
{
if (address.isEmpty())
return;
if (detection_status)
{
if (!video_capture.isOpened())
{
video_capture = VideoCapture(address.toUtf8().data());
frame_fps = video_capture.get(CV_CAP_PROP_FPS);
qDebug() << address << " open";
}
auto car = TaskDispatch::get_car_info();
if (car->fVelocity >= 10)
{
if (!video_capture.read(video_frame))
{
qDebug() << address << " close";
video_capture.release();
return;
}
if (video_frame.data != nullptr)
{
frame_mutex.lock();
video_frames_string.insert(frame_id, compress(video_frame, 80));
frame_mutex.unlock();
#if USE_ALGORITHM
bgr_frame_buffer.nFrameId = frame_id; // 帧号
bgr_frame_buffer.u64PTS = QDateTime::currentMSecsSinceEpoch(); // 时间戳(毫秒)
memcpy(bgr_frame_buffer.pu8VirAddr, video_frame.data, 1280 * 720 * 3);
MvConvertImage(&bgr_frame_buffer, &detect_frame_buffer); // bgr->nv16
MvObjectEventDetect(this->type, &detect_frame_buffer, TaskDispatch::get_car_info());
#endif
frame_id++;
}
}
}
}
void VideoDevice::run()
{
frame_id = 0;
while (true)
{
video_frame_queue_check();
read_frame();
msleep(1);
}
}
int VideoDevice::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 VideoDevice::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 VideoDevice::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;
}