Commit 77e1339cc5e9a80442364cb93aa76a7283171d45
1 parent
ffe81045
GB28181 补充定时抓拍接口,补充保存视频接口
Showing
16 changed files
with
639 additions
and
115 deletions
bin/sip_server_cfg.xml
0 → 100644
1 | +<?xml version="1.0" encoding="GB2312"?> | ||
2 | +<ROOT> | ||
3 | + <Ua>SY_Sip_Server</Ua> | ||
4 | + <Nonce>12345678</Nonce> | ||
5 | + <Ip>192.168.60.179</Ip> | ||
6 | + <Port>15060</Port> | ||
7 | + <SipId>34020000002000000002</SipId> | ||
8 | + <SipRealm>3402000000</SipRealm> | ||
9 | + <Password>sy123456</Password> | ||
10 | + <Timeout>1800</Timeout> | ||
11 | + <Expiry>3600</Expiry> | ||
12 | +</ROOT> |
src/ai_engine_module/pedestrian_vehicle_trespass.cpp
@@ -150,10 +150,27 @@ bool PedestrianVehicleTrespass::in_rect_analysis(const obj_key_t &id, const box_ | @@ -150,10 +150,27 @@ bool PedestrianVehicleTrespass::in_rect_analysis(const obj_key_t &id, const box_ | ||
150 | } | 150 | } |
151 | } | 151 | } |
152 | 152 | ||
153 | +bool PedestrianVehicleTrespass::isInited(string task_id) { | ||
154 | + auto it = m_task_inited.find(task_id); | ||
155 | + if(it == m_task_inited.end()){ | ||
156 | + return false; | ||
157 | + } | ||
158 | + return true; | ||
159 | +} | ||
160 | + | ||
161 | +void PedestrianVehicleTrespass::release(string task_id) { | ||
162 | + auto it = m_task_inited.find(task_id); | ||
163 | + if(it != m_task_inited.end()){ | ||
164 | + m_task_inited.erase(it); | ||
165 | + } | ||
166 | +} | ||
167 | + | ||
153 | /* 根据用户输入的点 初始化禁区区域mask */ | 168 | /* 根据用户输入的点 初始化禁区区域mask */ |
154 | void PedestrianVehicleTrespass::pedestrianvehicletrespass_init_region(const string &task_id, | 169 | void PedestrianVehicleTrespass::pedestrianvehicletrespass_init_region(const string &task_id, |
155 | const algorithm_type_t algor_type, | 170 | const algorithm_type_t algor_type, |
156 | const int width, const int height) { | 171 | const int width, const int height) { |
172 | + m_task_inited[task_id] = true; | ||
173 | + | ||
157 | obj_key_t obj_key = {0, task_id, algor_type}; | 174 | obj_key_t obj_key = {0, task_id, algor_type}; |
158 | 175 | ||
159 | auto &&algor_type_seq = task_id_to_algorithm_type_seq(task_id, task_param_manager_); | 176 | auto &&algor_type_seq = task_id_to_algorithm_type_seq(task_id, task_param_manager_); |
src/ai_engine_module/pedestrian_vehicle_trespass.h
@@ -34,6 +34,10 @@ public: | @@ -34,6 +34,10 @@ public: | ||
34 | 34 | ||
35 | ~PedestrianVehicleTrespass(); | 35 | ~PedestrianVehicleTrespass(); |
36 | 36 | ||
37 | + bool isInited(string task_id); | ||
38 | + | ||
39 | + void release(string task_id); | ||
40 | + | ||
37 | void pedestrianvehicletrespass_init_region(const string &task_id, const algorithm_type_t algor_type, const int width, | 41 | void pedestrianvehicletrespass_init_region(const string &task_id, const algorithm_type_t algor_type, const int width, |
38 | const int height); | 42 | const int height); |
39 | 43 | ||
@@ -55,6 +59,8 @@ private: | @@ -55,6 +59,8 @@ private: | ||
55 | std::map<obj_key_t, vector<result_data_t> > obj_to_alarm_boxes_; | 59 | std::map<obj_key_t, vector<result_data_t> > obj_to_alarm_boxes_; |
56 | std::map<obj_key_t, box_t> obj_to_position_; // 保存物体上一帧的位置,基于非法闯入判断逻辑,上一帧在框外,下一帧闯入禁区 | 60 | std::map<obj_key_t, box_t> obj_to_position_; // 保存物体上一帧的位置,基于非法闯入判断逻辑,上一帧在框外,下一帧闯入禁区 |
57 | std::map<obj_key_t, cv::Mat> trespass_regions; | 61 | std::map<obj_key_t, cv::Mat> trespass_regions; |
62 | + | ||
63 | + std::map<string, bool> m_task_inited; | ||
58 | }; | 64 | }; |
59 | } // namespace pedestrian_vehicle_trespass | 65 | } // namespace pedestrian_vehicle_trespass |
60 | } // namespace ai_engine_module | 66 | } // namespace ai_engine_module |
src/ai_platform/MultiSourceProcess.cpp
@@ -322,7 +322,7 @@ int CMultiSourceProcess::GetTaskStatus(const string taskID) { | @@ -322,7 +322,7 @@ int CMultiSourceProcess::GetTaskStatus(const string taskID) { | ||
322 | bool CMultiSourceProcess::AddTask(task_param _cur_task_param){ | 322 | bool CMultiSourceProcess::AddTask(task_param _cur_task_param){ |
323 | DecoderManager* pDecManager = DecoderManager::getInstance(); | 323 | DecoderManager* pDecManager = DecoderManager::getInstance(); |
324 | 324 | ||
325 | - const char* task_id = _cur_task_param.task_id; | 325 | + string task_id = _cur_task_param.task_id; |
326 | 326 | ||
327 | MgrDecConfig config; | 327 | MgrDecConfig config; |
328 | config.name = task_id; | 328 | config.name = task_id; |
@@ -360,7 +360,7 @@ bool CMultiSourceProcess::AddTask(task_param _cur_task_param){ | @@ -360,7 +360,7 @@ bool CMultiSourceProcess::AddTask(task_param _cur_task_param){ | ||
360 | } | 360 | } |
361 | 361 | ||
362 | decode_cbk_userdata* userPtr = new decode_cbk_userdata; | 362 | decode_cbk_userdata* userPtr = new decode_cbk_userdata; |
363 | - userPtr->task_id = string(task_id); | 363 | + userPtr->task_id = task_id; |
364 | userPtr->opaque = this; | 364 | userPtr->opaque = this; |
365 | userPtr->opaque1 = dec; | 365 | userPtr->opaque1 = dec; |
366 | pDecManager->setPostDecArg(config.name, userPtr); | 366 | pDecManager->setPostDecArg(config.name, userPtr); |
@@ -372,11 +372,6 @@ bool CMultiSourceProcess::AddTask(task_param _cur_task_param){ | @@ -372,11 +372,6 @@ bool CMultiSourceProcess::AddTask(task_param _cur_task_param){ | ||
372 | // 保存新添加任务的配置参数 | 372 | // 保存新添加任务的配置参数 |
373 | m_task_param_manager->add_task_param(task_id, _cur_task_param); | 373 | m_task_param_manager->add_task_param(task_id, _cur_task_param); |
374 | 374 | ||
375 | - int input_image_width = 0; | ||
376 | - int input_image_height = 0; | ||
377 | - pDecManager->getOutResolution(config.name, input_image_width, input_image_height); | ||
378 | - LOG_INFO("task_id: {} width: {} height:{}", task_id, input_image_width, input_image_height); | ||
379 | - | ||
380 | // 所有参数都准备好之后再启动解码 | 375 | // 所有参数都准备好之后再启动解码 |
381 | bool bStart = pDecManager->startDecodeByName(config.name); | 376 | bool bStart = pDecManager->startDecodeByName(config.name); |
382 | if (!bStart){ | 377 | if (!bStart){ |
@@ -391,12 +386,12 @@ bool CMultiSourceProcess::AddTask(task_param _cur_task_param){ | @@ -391,12 +386,12 @@ bool CMultiSourceProcess::AddTask(task_param _cur_task_param){ | ||
391 | #endif | 386 | #endif |
392 | 387 | ||
393 | // 人车物跟踪 | 388 | // 人车物跟踪 |
394 | - if (task_has_vpt_algor(task_id)) | 389 | + if (m_task_param_manager->task_has_vpt_algor(task_id)) |
395 | vpt_process.addTaskTracker(task_id, 1, 1, skip_frame_); | 390 | vpt_process.addTaskTracker(task_id, 1, 1, skip_frame_); |
396 | 391 | ||
397 | // 人脸跟踪 | 392 | // 人脸跟踪 |
398 | #ifdef WITH_FACE_DET_SS | 393 | #ifdef WITH_FACE_DET_SS |
399 | - if (task_has_face_algor(task_id)) | 394 | + if (m_task_param_manager->task_has_face_algor(task_id)) |
400 | m_face_det_ai_engine.add_tracker(task_id, skip_frame_); // 跳帧数暂时写死 | 395 | m_face_det_ai_engine.add_tracker(task_id, skip_frame_); // 跳帧数暂时写死 |
401 | #endif | 396 | #endif |
402 | 397 | ||
@@ -404,37 +399,9 @@ bool CMultiSourceProcess::AddTask(task_param _cur_task_param){ | @@ -404,37 +399,9 @@ bool CMultiSourceProcess::AddTask(task_param _cur_task_param){ | ||
404 | m_FinishedTaskMap[task_id] = false; | 399 | m_FinishedTaskMap[task_id] = false; |
405 | m_FinishedTaskMtx.unlock(); | 400 | m_FinishedTaskMtx.unlock(); |
406 | 401 | ||
407 | - auto algor_map = m_task_param_manager->get_task_other_param(task_id); | ||
408 | - if (algor_map != nullptr){ | ||
409 | - /* 如果开启了行人 机动车非法闯入功能 生成闯入区域mask */ | ||
410 | - if (algor_map->find(algorithm_type_t::PEDESTRIAN_TRESPASS) != algor_map->end()) { | ||
411 | - pedestrian_vehicle_trespass_.pedestrianvehicletrespass_init_region( | ||
412 | - task_id, algorithm_type_t::PEDESTRIAN_TRESPASS, input_image_width, input_image_height); | ||
413 | - } | ||
414 | - | ||
415 | - if (algor_map->find(algorithm_type_t::VEHICLE_TRESPASS) != algor_map->end()) { | ||
416 | - pedestrian_vehicle_trespass_.pedestrianvehicletrespass_init_region( | ||
417 | - task_id, algorithm_type_t::VEHICLE_TRESPASS, input_image_width, input_image_height); | ||
418 | - } | ||
419 | - | ||
420 | - // 设置定时截图的时间间隔 | ||
421 | - auto algor = algor_map->find(algorithm_type_t::VIDEO_TIMING_SNAPSHOT); | ||
422 | - if(algor != algor_map->end()){ | ||
423 | - task_param_manager::algo_param_type_t_* cur_task_params = algor->second; | ||
424 | - if(cur_task_params){ | ||
425 | - int frame_stride = ((algor_config_video_timing_snapshot*)cur_task_params->algor_param)->frame_stride; | ||
426 | - LOG_INFO("task {} snap time interval: {} s", config.name, frame_stride); | ||
427 | - // 单位是ms, 乘以 1000 编成s | ||
428 | - dec->setSnapTimeInterval(frame_stride * 1000); | ||
429 | - } | ||
430 | - } | ||
431 | - | ||
432 | - // 测试代码 | ||
433 | - // auto algor_face = algor_map->find(algorithm_type_t::FACE_SNAPSHOT); | ||
434 | - // if(algor_face != algor_map->end()){ | ||
435 | - // const algor_basic_config_param_t *cur_param = ((algor_init_config_param_t *)(algor_face->second))->basic_param; | ||
436 | - // LOG_INFO("face_snapshot, result_folder: {} result_folder_little: {}", cur_param->result_folder, cur_param->result_folder_little); | ||
437 | - // } | 402 | + int time_interval = m_task_param_manager->get_video_timing_snapshot_interval(task_id); |
403 | + if(time_interval > 0) { | ||
404 | + dec->setSnapTimeInterval(time_interval); | ||
438 | } | 405 | } |
439 | 406 | ||
440 | LOG_INFO("started task {} successed!", config.name); | 407 | LOG_INFO("started task {} successed!", config.name); |
@@ -447,55 +414,6 @@ int CMultiSourceProcess::CountRunningTask() { | @@ -447,55 +414,6 @@ int CMultiSourceProcess::CountRunningTask() { | ||
447 | return pDecManager->count(); | 414 | return pDecManager->count(); |
448 | } | 415 | } |
449 | 416 | ||
450 | -bool CMultiSourceProcess::task_has_vpt_algor(const std::string &task_id){ | ||
451 | - //! TODO: create enum iterator. | ||
452 | - auto algor_map = m_task_param_manager->get_task_other_param(task_id); | ||
453 | - if (algor_map == nullptr) | ||
454 | - return false; | ||
455 | - | ||
456 | - return (algor_map->find(algorithm_type_t::HUMAN_GATHER) != algor_map->end() || | ||
457 | - algor_map->find(algorithm_type_t::HUMAN_SNAPSHOT) != algor_map->end() || | ||
458 | - algor_map->find(algorithm_type_t::NONMOTOR_VEHICLE_SNAPSHOT) != algor_map->end() || | ||
459 | - algor_map->find(algorithm_type_t::SMOKING_DET) != algor_map->end() || | ||
460 | - algor_map->find(algorithm_type_t::NO_REFLECTIVE_CLOTHING) != algor_map->end() || | ||
461 | - algor_map->find(algorithm_type_t::NO_SAFETY_HELMET) != algor_map->end() || | ||
462 | - algor_map->find(algorithm_type_t::CALL_PHONE_DET) != algor_map->end() || | ||
463 | - algor_map->find(algorithm_type_t::VEHICLE_SNAPSHOT) != algor_map->end() || | ||
464 | - algor_map->find(algorithm_type_t::TAKEAWAY_MEMBER_CLASSIFICATION) != algor_map->end() || | ||
465 | - algor_map->find(algorithm_type_t::PEDESTRIAN_FALL) != algor_map->end() || | ||
466 | - algor_map->find(algorithm_type_t::PEDESTRIAN_FIGHT) != algor_map->end() || | ||
467 | - algor_map->find(algorithm_type_t::PEDESTRIAN_RETROGRADE) != algor_map->end() || | ||
468 | - algor_map->find(algorithm_type_t::VEHICLE_RETROGRADE) != algor_map->end() || | ||
469 | - algor_map->find(algorithm_type_t::PEDESTRIAN_TRESPASS) != algor_map->end() || | ||
470 | - algor_map->find(algorithm_type_t::VEHICLE_TRESPASS) != algor_map->end() || | ||
471 | - algor_map->find(algorithm_type_t::NONMOTOR_VEHICLE_NOHELMET) != algor_map->end() || | ||
472 | - algor_map->find(algorithm_type_t::NONMOTOR_VEHICLE_OVERMAN) != algor_map->end() || | ||
473 | - algor_map->find(algorithm_type_t::NONMOTOR_VEHICLE_USEPHONE) != algor_map->end() || | ||
474 | - algor_map->find(algorithm_type_t::NONMOTOR_VEHICLE_REFIT) != algor_map->end() || | ||
475 | - algor_map->find(algorithm_type_t::NONMOTOR_RUNNING_REDLIGHTS) != algor_map->end() || | ||
476 | - algor_map->find(algorithm_type_t::NONMOTOR_CEOSSPARKLINE) != algor_map->end() || | ||
477 | - algor_map->find(algorithm_type_t::NONMOTOR_IN_VEHICLELANE) != algor_map->end() || | ||
478 | - algor_map->find(algorithm_type_t::NONMOTOR_WRONGDIRECTION) != algor_map->end() || | ||
479 | - algor_map->find(algorithm_type_t::PERSON_IN_VEHICLELANE) != algor_map->end() || | ||
480 | - algor_map->find(algorithm_type_t::PERSON_RUNNING_REDLIGHTS) != algor_map->end() || | ||
481 | - algor_map->find(algorithm_type_t::PERSON_CROSS) != algor_map->end() || | ||
482 | - algor_map->find(algorithm_type_t::VEHICLE_WRONGDIRECTION) != algor_map->end() || | ||
483 | - algor_map->find(algorithm_type_t::VEHICLE_SOLIDLINETURNAROUND) != algor_map->end() || | ||
484 | - algor_map->find(algorithm_type_t::VEHICLE_NOTGIVEWAY) != algor_map->end() || | ||
485 | - algor_map->find(algorithm_type_t::VEHICLE_NOTDECELERATION) != algor_map->end() || | ||
486 | - algor_map->find(algorithm_type_t::TRICYCLE_MANNED) != algor_map->end() || | ||
487 | - algor_map->find(algorithm_type_t::TRUCK_MANNED) != algor_map->end()); | ||
488 | -} | ||
489 | - | ||
490 | -bool CMultiSourceProcess::task_has_face_algor(const std::string &task_id){ | ||
491 | - auto algor_map = m_task_param_manager->get_task_other_param(task_id); | ||
492 | - if (nullptr != algor_map){ | ||
493 | - return algor_map->find(algorithm_type_t::FACE_SNAPSHOT) != algor_map->end(); | ||
494 | - } | ||
495 | - | ||
496 | - return false; | ||
497 | -} | ||
498 | - | ||
499 | void CMultiSourceProcess::decoded_cbk(DeviceMemory* devFrame){ | 417 | void CMultiSourceProcess::decoded_cbk(DeviceMemory* devFrame){ |
500 | 418 | ||
501 | do{ | 419 | do{ |
@@ -689,12 +607,13 @@ void CMultiSourceProcess::clear_finished_task(){// 清理已经结束的任务 | @@ -689,12 +607,13 @@ void CMultiSourceProcess::clear_finished_task(){// 清理已经结束的任务 | ||
689 | // 解码器已经结束,且数据队列中没有改任务的数据,则做最后任务清理工作 | 607 | // 解码器已经结束,且数据队列中没有改任务的数据,则做最后任务清理工作 |
690 | finish_task(task_id,false); | 608 | finish_task(task_id,false); |
691 | iter_finished = m_FinishedTaskMap.erase(iter_finished); | 609 | iter_finished = m_FinishedTaskMap.erase(iter_finished); |
610 | + pedestrian_vehicle_trespass_.release(task_id); | ||
692 | continue; | 611 | continue; |
693 | } | 612 | } |
694 | } | 613 | } |
695 | 614 | ||
696 | ++ iter_finished; | 615 | ++ iter_finished; |
697 | - } | 616 | + } |
698 | } | 617 | } |
699 | 618 | ||
700 | bool CMultiSourceProcess::finish_task(const string taskID, const bool delete_snapshot){ | 619 | bool CMultiSourceProcess::finish_task(const string taskID, const bool delete_snapshot){ |
@@ -705,7 +624,7 @@ bool CMultiSourceProcess::finish_task(const string taskID, const bool delete_sna | @@ -705,7 +624,7 @@ bool CMultiSourceProcess::finish_task(const string taskID, const bool delete_sna | ||
705 | 624 | ||
706 | #ifdef WITH_FACE_DET_SS | 625 | #ifdef WITH_FACE_DET_SS |
707 | // 人脸任务结束 | 626 | // 人脸任务结束 |
708 | - if (task_has_face_algor(taskID)) | 627 | + if (m_task_param_manager->task_has_face_algor(taskID)) |
709 | m_face_det_ai_engine.finish_task(taskID); | 628 | m_face_det_ai_engine.finish_task(taskID); |
710 | #endif | 629 | #endif |
711 | 630 | ||
@@ -805,6 +724,30 @@ int CMultiSourceProcess::algorthim_process_thread(){ | @@ -805,6 +724,30 @@ int CMultiSourceProcess::algorthim_process_thread(){ | ||
805 | LOG_WARN("mem is null"); | 724 | LOG_WARN("mem is null"); |
806 | } else { | 725 | } else { |
807 | vec_gpuMem.push_back(gpuMem); | 726 | vec_gpuMem.push_back(gpuMem); |
727 | + | ||
728 | + string task_id = gpuMem->getId(); | ||
729 | + if (!pedestrian_vehicle_trespass_.isInited(task_id)) { | ||
730 | + auto algor_map = m_task_param_manager->get_task_other_param(task_id); | ||
731 | + if (algor_map != nullptr) { | ||
732 | + int input_image_width = gpuMem->getWidth(); | ||
733 | + int input_image_height = gpuMem->getHeight(); | ||
734 | + LOG_INFO("task_id: {} width: {} height:{}", task_id, input_image_width, input_image_height); | ||
735 | + | ||
736 | + /* 如果开启了行人 机动车非法闯入功能 生成闯入区域mask */ | ||
737 | + if (algor_map->find(algorithm_type_t::PEDESTRIAN_TRESPASS) != algor_map->end()) { | ||
738 | + pedestrian_vehicle_trespass_.pedestrianvehicletrespass_init_region( | ||
739 | + task_id, algorithm_type_t::PEDESTRIAN_TRESPASS, input_image_width, input_image_height); | ||
740 | + } | ||
741 | + | ||
742 | + if (algor_map->find(algorithm_type_t::VEHICLE_TRESPASS) != algor_map->end()) { | ||
743 | + pedestrian_vehicle_trespass_.pedestrianvehicletrespass_init_region( | ||
744 | + task_id, algorithm_type_t::VEHICLE_TRESPASS, input_image_width, input_image_height); | ||
745 | + } | ||
746 | + } | ||
747 | + } | ||
748 | + | ||
749 | + | ||
750 | + | ||
808 | } | 751 | } |
809 | 752 | ||
810 | m_RgbDataList.pop_front(); | 753 | m_RgbDataList.pop_front(); |
@@ -913,7 +856,7 @@ int CMultiSourceProcess::algorthim_vpt(vector<DeviceMemory*> vec_gpuMem){ | @@ -913,7 +856,7 @@ int CMultiSourceProcess::algorthim_vpt(vector<DeviceMemory*> vec_gpuMem){ | ||
913 | vector<DeviceMemory*> vec_vptMem; | 856 | vector<DeviceMemory*> vec_vptMem; |
914 | for (int i = 0; i < vec_gpuMem.size(); i++) { | 857 | for (int i = 0; i < vec_gpuMem.size(); i++) { |
915 | DeviceMemory* mem = vec_gpuMem[i]; | 858 | DeviceMemory* mem = vec_gpuMem[i]; |
916 | - if (!task_has_vpt_algor(mem->getId())){ | 859 | + if (!m_task_param_manager->task_has_vpt_algor(mem->getId())){ |
917 | continue; | 860 | continue; |
918 | } | 861 | } |
919 | 862 | ||
@@ -2100,7 +2043,7 @@ void CMultiSourceProcess::algorthim_face_detect(vector<DeviceMemory*> vec_gpuMem | @@ -2100,7 +2043,7 @@ void CMultiSourceProcess::algorthim_face_detect(vector<DeviceMemory*> vec_gpuMem | ||
2100 | vector<DeviceMemory*> vec_vptMem; | 2043 | vector<DeviceMemory*> vec_vptMem; |
2101 | for (int i = 0; i < vec_gpuMem.size(); i++) { | 2044 | for (int i = 0; i < vec_gpuMem.size(); i++) { |
2102 | DeviceMemory* mem = vec_gpuMem[i]; | 2045 | DeviceMemory* mem = vec_gpuMem[i]; |
2103 | - if (!task_has_face_algor(mem->getId())){ | 2046 | + if (!m_task_param_manager->task_has_face_algor(mem->getId())){ |
2104 | continue; | 2047 | continue; |
2105 | } | 2048 | } |
2106 | 2049 |
src/ai_platform/MultiSourceProcess.h
@@ -101,8 +101,6 @@ private: | @@ -101,8 +101,6 @@ private: | ||
101 | 101 | ||
102 | private: | 102 | private: |
103 | // 工具处理函数 | 103 | // 工具处理函数 |
104 | - bool task_has_vpt_algor(const std::string &task_id); | ||
105 | - bool task_has_face_algor(const std::string &task_id); | ||
106 | void clear_finished_task(); | 104 | void clear_finished_task(); |
107 | bool finish_task(const string taskID, const bool delete_snapshot); | 105 | bool finish_task(const string taskID, const bool delete_snapshot); |
108 | int algorithm_vehicle_relult(vector<DeviceMemory*> vec_devMem, vector<onelevel_det_result>& vptResult, vector<vector<int>>& delete_object_id); | 106 | int algorithm_vehicle_relult(vector<DeviceMemory*> vec_devMem, vector<onelevel_det_result>& vptResult, vector<vector<int>>& delete_object_id); |
src/ai_platform/task_param_manager.cpp
@@ -542,3 +542,78 @@ map<string, algor_open_config_param> task_param_manager::get_task_algor_params() | @@ -542,3 +542,78 @@ map<string, algor_open_config_param> task_param_manager::get_task_algor_params() | ||
542 | map<string, map<algo_type, task_param_manager::algo_param_type_t_ *>> task_param_manager::get_task_other_params() { | 542 | map<string, map<algo_type, task_param_manager::algo_param_type_t_ *>> task_param_manager::get_task_other_params() { |
543 | return m_task_params; | 543 | return m_task_params; |
544 | } | 544 | } |
545 | + | ||
546 | +bool task_param_manager::task_has_vpt_algor(const std::string &task_id) { | ||
547 | + auto algor_map = get_task_other_param(task_id); | ||
548 | + if (algor_map == nullptr) | ||
549 | + return false; | ||
550 | + | ||
551 | + return (algor_map->find(algorithm_type_t::HUMAN_GATHER) != algor_map->end() || | ||
552 | + algor_map->find(algorithm_type_t::HUMAN_SNAPSHOT) != algor_map->end() || | ||
553 | + algor_map->find(algorithm_type_t::NONMOTOR_VEHICLE_SNAPSHOT) != algor_map->end() || | ||
554 | + algor_map->find(algorithm_type_t::SMOKING_DET) != algor_map->end() || | ||
555 | + algor_map->find(algorithm_type_t::NO_REFLECTIVE_CLOTHING) != algor_map->end() || | ||
556 | + algor_map->find(algorithm_type_t::NO_SAFETY_HELMET) != algor_map->end() || | ||
557 | + algor_map->find(algorithm_type_t::CALL_PHONE_DET) != algor_map->end() || | ||
558 | + algor_map->find(algorithm_type_t::VEHICLE_SNAPSHOT) != algor_map->end() || | ||
559 | + algor_map->find(algorithm_type_t::TAKEAWAY_MEMBER_CLASSIFICATION) != algor_map->end() || | ||
560 | + algor_map->find(algorithm_type_t::PEDESTRIAN_FALL) != algor_map->end() || | ||
561 | + algor_map->find(algorithm_type_t::PEDESTRIAN_FIGHT) != algor_map->end() || | ||
562 | + algor_map->find(algorithm_type_t::PEDESTRIAN_RETROGRADE) != algor_map->end() || | ||
563 | + algor_map->find(algorithm_type_t::VEHICLE_RETROGRADE) != algor_map->end() || | ||
564 | + algor_map->find(algorithm_type_t::PEDESTRIAN_TRESPASS) != algor_map->end() || | ||
565 | + algor_map->find(algorithm_type_t::VEHICLE_TRESPASS) != algor_map->end() || | ||
566 | + algor_map->find(algorithm_type_t::NONMOTOR_VEHICLE_NOHELMET) != algor_map->end() || | ||
567 | + algor_map->find(algorithm_type_t::NONMOTOR_VEHICLE_OVERMAN) != algor_map->end() || | ||
568 | + algor_map->find(algorithm_type_t::NONMOTOR_VEHICLE_USEPHONE) != algor_map->end() || | ||
569 | + algor_map->find(algorithm_type_t::NONMOTOR_VEHICLE_REFIT) != algor_map->end() || | ||
570 | + algor_map->find(algorithm_type_t::NONMOTOR_RUNNING_REDLIGHTS) != algor_map->end() || | ||
571 | + algor_map->find(algorithm_type_t::NONMOTOR_CEOSSPARKLINE) != algor_map->end() || | ||
572 | + algor_map->find(algorithm_type_t::NONMOTOR_IN_VEHICLELANE) != algor_map->end() || | ||
573 | + algor_map->find(algorithm_type_t::NONMOTOR_WRONGDIRECTION) != algor_map->end() || | ||
574 | + algor_map->find(algorithm_type_t::PERSON_IN_VEHICLELANE) != algor_map->end() || | ||
575 | + algor_map->find(algorithm_type_t::PERSON_RUNNING_REDLIGHTS) != algor_map->end() || | ||
576 | + algor_map->find(algorithm_type_t::PERSON_CROSS) != algor_map->end() || | ||
577 | + algor_map->find(algorithm_type_t::VEHICLE_WRONGDIRECTION) != algor_map->end() || | ||
578 | + algor_map->find(algorithm_type_t::VEHICLE_SOLIDLINETURNAROUND) != algor_map->end() || | ||
579 | + algor_map->find(algorithm_type_t::VEHICLE_NOTGIVEWAY) != algor_map->end() || | ||
580 | + algor_map->find(algorithm_type_t::VEHICLE_NOTDECELERATION) != algor_map->end() || | ||
581 | + algor_map->find(algorithm_type_t::TRICYCLE_MANNED) != algor_map->end() || | ||
582 | + algor_map->find(algorithm_type_t::TRUCK_MANNED) != algor_map->end()); | ||
583 | +} | ||
584 | + | ||
585 | +bool task_param_manager::task_has_face_algor(const std::string &task_id) { | ||
586 | + auto algor_map = get_task_other_param(task_id); | ||
587 | + if (nullptr != algor_map){ | ||
588 | + return algor_map->find(algorithm_type_t::FACE_SNAPSHOT) != algor_map->end(); | ||
589 | + } | ||
590 | + | ||
591 | + return false; | ||
592 | +} | ||
593 | + | ||
594 | +int task_param_manager::get_video_timing_snapshot_interval(std::string& task_id) { | ||
595 | + auto algor_map = get_task_other_param(task_id); | ||
596 | + if (algor_map != nullptr) { | ||
597 | + | ||
598 | + // 设置定时截图的时间间隔 | ||
599 | + auto algor = algor_map->find(algorithm_type_t::VIDEO_TIMING_SNAPSHOT); | ||
600 | + if(algor != algor_map->end()){ | ||
601 | + task_param_manager::algo_param_type_t_* cur_task_params = algor->second; | ||
602 | + if(cur_task_params){ | ||
603 | + int frame_stride = ((algor_config_video_timing_snapshot*)cur_task_params->algor_param)->frame_stride; | ||
604 | + LOG_INFO("task {} snap time interval: {} s", task_id, frame_stride); | ||
605 | + // 单位是ms, 乘以 1000 编成s | ||
606 | + return frame_stride * 1000; | ||
607 | + } | ||
608 | + } | ||
609 | + | ||
610 | + // 测试代码 | ||
611 | + // auto algor_face = algor_map->find(algorithm_type_t::FACE_SNAPSHOT); | ||
612 | + // if(algor_face != algor_map->end()){ | ||
613 | + // const algor_basic_config_param_t *cur_param = ((algor_init_config_param_t *)(algor_face->second))->basic_param; | ||
614 | + // LOG_INFO("face_snapshot, result_folder: {} result_folder_little: {}", cur_param->result_folder, cur_param->result_folder_little); | ||
615 | + // } | ||
616 | + } | ||
617 | + | ||
618 | + return -1; | ||
619 | +} | ||
545 | \ No newline at end of file | 620 | \ No newline at end of file |
src/ai_platform/task_param_manager.h
@@ -43,6 +43,11 @@ public: | @@ -43,6 +43,11 @@ public: | ||
43 | map<string, map<algo_type, algo_param_type_t_*>> get_task_other_params(); | 43 | map<string, map<algo_type, algo_param_type_t_*>> get_task_other_params(); |
44 | void task_param_manager_release(); | 44 | void task_param_manager_release(); |
45 | 45 | ||
46 | + bool task_has_vpt_algor(const std::string &task_id); | ||
47 | + bool task_has_face_algor(const std::string &task_id); | ||
48 | + | ||
49 | + int get_video_timing_snapshot_interval(std::string& task_id); | ||
50 | + | ||
46 | private: | 51 | private: |
47 | task_param_manager(); | 52 | task_param_manager(); |
48 | task_param_manager(const task_param_manager& other); | 53 | task_param_manager(const task_param_manager& other); |
src/decoder/dvpp/DvppStreamDecoder.cpp
@@ -479,6 +479,10 @@ int DvppStreamDecoder::SendData(int videoType, char* data, int len, int isKey, u | @@ -479,6 +479,10 @@ int DvppStreamDecoder::SendData(int videoType, char* data, int len, int isKey, u | ||
479 | 479 | ||
480 | m_frame_nb++; | 480 | m_frame_nb++; |
481 | 481 | ||
482 | + #ifdef USE_VILLAGE | ||
483 | + m_recoderManager.cache_pkt(pkt, m_frame_nb); | ||
484 | +#endif | ||
485 | + | ||
482 | // dvpp 解码 | 486 | // dvpp 解码 |
483 | nSended = sendPkt(vdecChannelDesc, pkt, m_frame_nb, vdec_out_size); | 487 | nSended = sendPkt(vdecChannelDesc, pkt, m_frame_nb, vdec_out_size); |
484 | } | 488 | } |
@@ -568,7 +572,11 @@ int DvppStreamDecoder::parse_stream_info(int videoType, AVPacket* pkt) { | @@ -568,7 +572,11 @@ int DvppStreamDecoder::parse_stream_info(int videoType, AVPacket* pkt) { | ||
568 | av_bsf_init(h264bsfc); | 572 | av_bsf_init(h264bsfc); |
569 | } | 573 | } |
570 | 574 | ||
571 | - m_fps = av_q2d(avctx->framerate); | 575 | + if (avctx->framerate.den) { |
576 | + m_fps = av_q2d(avctx->framerate); | ||
577 | + } else { | ||
578 | + m_fps = 0.0; | ||
579 | + } | ||
572 | 580 | ||
573 | AVFrame* frame = av_frame_alloc(); | 581 | AVFrame* frame = av_frame_alloc(); |
574 | do | 582 | do |
@@ -587,6 +595,13 @@ int DvppStreamDecoder::parse_stream_info(int videoType, AVPacket* pkt) { | @@ -587,6 +595,13 @@ int DvppStreamDecoder::parse_stream_info(int videoType, AVPacket* pkt) { | ||
587 | m_vdec_out_size = frame->width * frame->height * 3 / 2; | 595 | m_vdec_out_size = frame->width * frame->height * 3 / 2; |
588 | } while (0); | 596 | } while (0); |
589 | 597 | ||
598 | +#ifdef USE_VILLAGE | ||
599 | + bool bRet = m_recoderManager.init2(frame->width, frame->height, m_fps, avctx->bit_rate); | ||
600 | + if (!bRet){ | ||
601 | + LOG_ERROR("[{}]- m_recoderManager 初始化失败!", m_dec_name); | ||
602 | + } | ||
603 | +#endif | ||
604 | + | ||
590 | av_frame_free(&frame); | 605 | av_frame_free(&frame); |
591 | frame = nullptr; | 606 | frame = nullptr; |
592 | 607 | ||
@@ -629,7 +644,17 @@ void DvppStreamDecoder::Close() { | @@ -629,7 +644,17 @@ void DvppStreamDecoder::Close() { | ||
629 | h264bsfc = nullptr; | 644 | h264bsfc = nullptr; |
630 | } | 645 | } |
631 | 646 | ||
647 | + m_recoderManager.close(); | ||
648 | + | ||
632 | if(decode_finished_cbk) { | 649 | if(decode_finished_cbk) { |
633 | decode_finished_cbk(m_finishedDecArg); | 650 | decode_finished_cbk(m_finishedDecArg); |
634 | } | 651 | } |
652 | +} | ||
653 | + | ||
654 | +void DvppStreamDecoder::doRecode(RecoderInfo& recoderInfo) { | ||
655 | + m_recoderManager.create_recode_task(recoderInfo); | ||
656 | +} | ||
657 | + | ||
658 | +void DvppStreamDecoder::set_mq_callback(mq_callback_t cb) { | ||
659 | + m_recoderManager.set_mq_callback(cb); | ||
635 | } | 660 | } |
636 | \ No newline at end of file | 661 | \ No newline at end of file |
src/decoder/dvpp/DvppStreamDecoder.h
@@ -6,6 +6,8 @@ | @@ -6,6 +6,8 @@ | ||
6 | 6 | ||
7 | #include "VpcUtils.h" | 7 | #include "VpcUtils.h" |
8 | 8 | ||
9 | +#include "FFRecoderTaskManager.h" | ||
10 | + | ||
9 | using namespace std; | 11 | using namespace std; |
10 | 12 | ||
11 | class DvppStreamDecoder | 13 | class DvppStreamDecoder |
@@ -22,6 +24,10 @@ public: | @@ -22,6 +24,10 @@ public: | ||
22 | 24 | ||
23 | DvppDataMemory* GetFrame(); | 25 | DvppDataMemory* GetFrame(); |
24 | 26 | ||
27 | + void doRecode(RecoderInfo& recoderInfo); | ||
28 | + | ||
29 | + void set_mq_callback(mq_callback_t cb); | ||
30 | + | ||
25 | public: | 31 | public: |
26 | void doProcessReport(); | 32 | void doProcessReport(); |
27 | void doVdppVdecCallBack(acldvppStreamDesc *input, acldvppPicDesc *output, void *pUserData); | 33 | void doVdppVdecCallBack(acldvppStreamDesc *input, acldvppPicDesc *output, void *pUserData); |
@@ -73,6 +79,8 @@ private: | @@ -73,6 +79,8 @@ private: | ||
73 | uint64_t m_out_count {0}; | 79 | uint64_t m_out_count {0}; |
74 | 80 | ||
75 | bool m_bResize {false}; | 81 | bool m_bResize {false}; |
82 | + | ||
83 | + FFRecoderTaskManager m_recoderManager; | ||
76 | }; | 84 | }; |
77 | 85 | ||
78 | 86 |
src/decoder/dvpp/FFRecoder2.cpp
0 → 100644
1 | +// FFRecoder2.cpp | ||
2 | +#include "FFRecoder2.h" | ||
3 | +#include <tuple> | ||
4 | +#include <array> | ||
5 | +#include <vector> | ||
6 | + | ||
7 | +extern "C" { | ||
8 | +#include <libavcodec/avcodec.h> | ||
9 | +#include <libavformat/avformat.h> | ||
10 | +#include <libavutil/opt.h> | ||
11 | +#include <libavutil/timestamp.h> | ||
12 | +#include <libavutil/imgutils.h> | ||
13 | +#include <libswscale/swscale.h> | ||
14 | +} | ||
15 | + | ||
16 | + | ||
17 | +FFRecoder2::FFRecoder2() | ||
18 | + :width_{}, | ||
19 | + height_{}, | ||
20 | + y_size_{}, | ||
21 | + uv_size_{}, | ||
22 | + pts_{}, | ||
23 | + codec_ctx_{ nullptr }, | ||
24 | + fmt_ctx_{ nullptr }, | ||
25 | + out_stream_{ nullptr }, | ||
26 | + yuv_frame_{ nullptr } | ||
27 | +{ | ||
28 | +} | ||
29 | + | ||
30 | +FFRecoder2::~FFRecoder2() | ||
31 | +{ | ||
32 | + uninit(); | ||
33 | +} | ||
34 | + | ||
35 | + | ||
36 | +bool FFRecoder2::init(int w, int h, int fps, int bit_rate, const char* outfile_name) | ||
37 | +{ | ||
38 | + uninit(); | ||
39 | + | ||
40 | + width_ = w; | ||
41 | + height_ = h; | ||
42 | + y_size_ = w * h; | ||
43 | + uv_size_ = y_size_ / 4; | ||
44 | + | ||
45 | + // [1] 创建解码器 | ||
46 | + const AVCodec* encoder = avcodec_find_encoder(AV_CODEC_ID_H264); | ||
47 | + if (!encoder) { | ||
48 | + fprintf(stderr, "Find encoder AV_CODEC_ID_H264 failed!\n"); | ||
49 | + return false; | ||
50 | + } | ||
51 | + // 获取解码器上下文 | ||
52 | + codec_ctx_ = avcodec_alloc_context3(encoder); | ||
53 | + if (!codec_ctx_) { | ||
54 | + fprintf(stderr, "Alloc context for encoder contx failed!\n"); | ||
55 | + return false; | ||
56 | + } | ||
57 | + // 设置解码器上下文参数 | ||
58 | + codec_ctx_->bit_rate = bit_rate; | ||
59 | + codec_ctx_->width = width_; | ||
60 | + codec_ctx_->height = height_; | ||
61 | + codec_ctx_->time_base = AVRational{ 1, fps }; | ||
62 | + codec_ctx_->gop_size = 50; | ||
63 | + codec_ctx_->max_b_frames = 0; | ||
64 | + codec_ctx_->pix_fmt = AV_PIX_FMT_YUV420P; | ||
65 | + codec_ctx_->thread_count = 4; | ||
66 | + codec_ctx_->qmin = 10; | ||
67 | + codec_ctx_->qmax = 51; | ||
68 | + codec_ctx_->qcompress = 0.6f; | ||
69 | + codec_ctx_->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; | ||
70 | + | ||
71 | + //av_opt_set(codec_ctx_->priv_data, "preset", "ultrafast", 0); | ||
72 | + av_opt_set(codec_ctx_->priv_data, "tune", "zerolatency", 0); | ||
73 | + | ||
74 | + // 打开解码器 | ||
75 | + if (avcodec_open2(codec_ctx_, encoder, nullptr) < 0) { | ||
76 | + fprintf(stderr, "Open encoder failed!\n"); | ||
77 | + return false; | ||
78 | + } | ||
79 | + | ||
80 | + // [2] 创建输出上下文 | ||
81 | + avformat_alloc_output_context2(&fmt_ctx_, nullptr, nullptr, outfile_name); | ||
82 | + | ||
83 | + // [3] 添加输出视频流 | ||
84 | + out_stream_ = avformat_new_stream(fmt_ctx_, nullptr); | ||
85 | + out_stream_->id = 0; | ||
86 | + out_stream_->codecpar->codec_tag = 0; | ||
87 | + avcodec_parameters_from_context(out_stream_->codecpar, codec_ctx_); | ||
88 | + | ||
89 | + av_dump_format(fmt_ctx_, out_stream_->id, outfile_name, 1); | ||
90 | + | ||
91 | + // 创建YUV格式帧 | ||
92 | + yuv_frame_ = av_frame_alloc(); | ||
93 | + yuv_frame_->format = AV_PIX_FMT_YUV420P; | ||
94 | + yuv_frame_->width = width_; | ||
95 | + yuv_frame_->height = height_; | ||
96 | + // 为创建的YUV帧分配内存 | ||
97 | + if (av_frame_get_buffer(yuv_frame_, 0) < 0) { | ||
98 | + av_frame_free(&yuv_frame_); | ||
99 | + yuv_frame_ = nullptr; | ||
100 | + fprintf(stderr, "Frame get buffer failed!\n"); | ||
101 | + return false; | ||
102 | + } | ||
103 | + | ||
104 | + // [5] 打开输出视频文件并写入视频头信息 | ||
105 | + if (avio_open(&fmt_ctx_->pb, outfile_name, AVIO_FLAG_WRITE) < 0) { | ||
106 | + fprintf(stderr, "avio_open failed!\n"); | ||
107 | + return false; | ||
108 | + } | ||
109 | + if (avformat_write_header(fmt_ctx_, nullptr) < 0) { | ||
110 | + fprintf(stderr, "Write header failed!\n"); | ||
111 | + return false; | ||
112 | + } | ||
113 | + | ||
114 | + return true; | ||
115 | +} | ||
116 | + | ||
117 | +void FFRecoder2::uninit() | ||
118 | +{ | ||
119 | + if (fmt_ctx_) { | ||
120 | + av_write_trailer(fmt_ctx_); | ||
121 | + avio_close(fmt_ctx_->pb); | ||
122 | + avformat_free_context(fmt_ctx_); | ||
123 | + fmt_ctx_ = nullptr; | ||
124 | + } | ||
125 | + | ||
126 | + if (codec_ctx_) { | ||
127 | + avcodec_close(codec_ctx_); | ||
128 | + avcodec_free_context(&codec_ctx_); | ||
129 | + codec_ctx_ = nullptr; | ||
130 | + } | ||
131 | + | ||
132 | + if (yuv_frame_) { | ||
133 | + av_frame_free(&yuv_frame_); | ||
134 | + yuv_frame_ = nullptr; | ||
135 | + } | ||
136 | + | ||
137 | + width_ = 0; | ||
138 | + height_ = 0; | ||
139 | + y_size_ = 0; | ||
140 | + uv_size_ = 0; | ||
141 | + pts_ = 0; | ||
142 | +} | ||
143 | + | ||
144 | +bool FFRecoder2::write_image(const uint8_t* bgr) | ||
145 | +{ | ||
146 | + // 分配YUV格式数据的内存 | ||
147 | + thread_local std::vector<uint8_t> yuv_data; | ||
148 | + if (yuv_data.size() != y_size_ * 3 / 2) { | ||
149 | + yuv_data.resize(y_size_ * 3 / 2); | ||
150 | + } | ||
151 | + // BGR格式转YUV格式 | ||
152 | + bgr_to_yuv420p(bgr, yuv_data.data()); | ||
153 | + | ||
154 | + return write_yuv(yuv_data.data()); | ||
155 | +} | ||
156 | + | ||
157 | +bool FFRecoder2::write_yuv(const uint8_t* yuv_data) | ||
158 | +{ | ||
159 | + //拷贝YUV数据到帧,由于帧数据存在内存对齐,故需逐行拷贝 | ||
160 | + for (int i = 0; i < height_; i++) { | ||
161 | + memcpy(yuv_frame_->data[0] + i * yuv_frame_->linesize[0], yuv_data + width_ * i, width_); | ||
162 | + } | ||
163 | + const int uv_stride = width_ / 2; | ||
164 | + for (int i = 0; i < height_ / 2; i++) { | ||
165 | + memcpy(yuv_frame_->data[1] + i * yuv_frame_->linesize[1], yuv_data + y_size_ + uv_stride * i, uv_stride); | ||
166 | + memcpy(yuv_frame_->data[2] + i * yuv_frame_->linesize[2], yuv_data + y_size_ + uv_size_ + uv_stride * i, uv_stride); | ||
167 | + } | ||
168 | + | ||
169 | + yuv_frame_->pts = pts_++; | ||
170 | + | ||
171 | + return write_frame(yuv_frame_); | ||
172 | +} | ||
173 | + | ||
174 | +bool FFRecoder2::write_frame(const AVFrame* frame) | ||
175 | +{ | ||
176 | + char errbuf[64]{ 0 }; | ||
177 | + // 将帧数据发送到编码器 | ||
178 | + int ret = avcodec_send_frame(codec_ctx_, frame); | ||
179 | + if (ret < 0) { | ||
180 | + fprintf(stderr, "Error sending a frame to the encoder: %s\n", av_make_error_string(errbuf, sizeof(errbuf), ret)); | ||
181 | + return false; | ||
182 | + } | ||
183 | + | ||
184 | + while (true) { | ||
185 | + AVPacket pkt{ 0 }; | ||
186 | + // 获取编码后的数据 | ||
187 | + ret = avcodec_receive_packet(codec_ctx_, &pkt); | ||
188 | + if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) | ||
189 | + return true; | ||
190 | + else if (ret < 0) { | ||
191 | + fprintf(stderr, "Error encoding a frame: %s\n", av_make_error_string(errbuf, sizeof(errbuf), ret)); | ||
192 | + return false; | ||
193 | + } | ||
194 | + // 将pts缩放到输出流的time_base上 | ||
195 | + av_packet_rescale_ts(&pkt, codec_ctx_->time_base, out_stream_->time_base); | ||
196 | + pkt.stream_index = out_stream_->index; | ||
197 | + // 将数据写入到输出流 | ||
198 | + ret = av_interleaved_write_frame(fmt_ctx_, &pkt); | ||
199 | + av_packet_unref(&pkt); | ||
200 | + if (ret < 0) { | ||
201 | + fprintf(stderr, "Error while writing output packet: %s\n", av_make_error_string(errbuf, sizeof(errbuf), ret)); | ||
202 | + return false; | ||
203 | + } | ||
204 | + } | ||
205 | + | ||
206 | + return true; | ||
207 | +} | ||
208 | + | ||
209 | +bool FFRecoder2::write_pkt(AVPacket* pkt) { | ||
210 | + // 将pts缩放到输出流的time_base上 | ||
211 | + av_packet_rescale_ts(pkt, codec_ctx_->time_base, out_stream_->time_base); | ||
212 | + pkt->stream_index = out_stream_->index; | ||
213 | + // 将数据写入到输出流 | ||
214 | + int ret = av_interleaved_write_frame(fmt_ctx_, pkt); | ||
215 | + | ||
216 | + char errbuf[64]{ 0 }; | ||
217 | + if (ret < 0) { | ||
218 | + fprintf(stderr, "Error while writing output packet: %s\n", av_make_error_string(errbuf, sizeof(errbuf), ret)); | ||
219 | + return false; | ||
220 | + } | ||
221 | + | ||
222 | + return true; | ||
223 | +} | ||
224 | + | ||
225 | +bool FFRecoder2::flush() | ||
226 | +{ | ||
227 | + return write_frame(nullptr); | ||
228 | +} | ||
229 | + | ||
230 | +bool FFRecoder2::bgr_to_yuv420p(const uint8_t* const buf_bgr, uint8_t* const buf_420p) | ||
231 | +{ | ||
232 | + // 分配转换上下文 | ||
233 | + thread_local std::tuple<int,int,int> params{ 0, 0, 0 }; | ||
234 | + thread_local std::unique_ptr<SwsContext, decltype(&sws_freeContext)> sws_context{ nullptr, &sws_freeContext }; | ||
235 | + | ||
236 | + std::tuple<int,int,int> new_params{ width_, height_, av_image_get_linesize(AV_PIX_FMT_YUV420P, width_, 0) }; | ||
237 | + if (!sws_context || params != new_params) | ||
238 | + { | ||
239 | + sws_context.reset(sws_getContext(width_, height_, AV_PIX_FMT_BGR24, width_, height_, | ||
240 | + AV_PIX_FMT_YUV420P, SWS_FAST_BILINEAR, nullptr, nullptr, nullptr)); | ||
241 | + params = new_params; | ||
242 | + } | ||
243 | + | ||
244 | + // 转换格式 | ||
245 | + const int stride = std::get<2>(params);//Y平面一行的数据长度 | ||
246 | + const int ret = sws_scale(sws_context.get(), | ||
247 | + &buf_bgr,/* bgr数据只有一个平面 */ | ||
248 | + std::array<int, 1> {width_ * 3}.data(),/* BGR所以图像宽度*3 */ | ||
249 | + 0, height_, | ||
250 | + std::array<uint8_t* const, 3>{ buf_420p, buf_420p + y_size_, buf_420p + y_size_ + uv_size_ }.data(),/* YUV三个平面的起始地址 */ | ||
251 | + std::array<int, 3>{ stride, stride / 2, stride / 2 }.data() | ||
252 | + );/* YUV每个平面中一行的宽度 */ | ||
253 | + | ||
254 | + return ret >= 0; | ||
255 | +} | ||
256 | + | ||
257 | +bool FFRecoder2::close() | ||
258 | +{ | ||
259 | + flush(); | ||
260 | + uninit(); | ||
261 | +} | ||
0 | \ No newline at end of file | 262 | \ No newline at end of file |
src/decoder/dvpp/FFRecoder2.h
0 → 100644
1 | +#pragma once | ||
2 | +#include <memory> | ||
3 | + | ||
4 | +class AVFrame; | ||
5 | +class AVStream; | ||
6 | +class AVCodecContext; | ||
7 | +class AVFormatContext; | ||
8 | +class AVPacket; | ||
9 | + | ||
10 | +class FFRecoder2 | ||
11 | +{ | ||
12 | +public: | ||
13 | + FFRecoder2(); | ||
14 | + ~FFRecoder2(); | ||
15 | + | ||
16 | + bool init(int w, int h, int fps, int bit_rate, const char* outfile_name); | ||
17 | + void uninit(); | ||
18 | + bool write_image(const uint8_t* bgr); | ||
19 | + bool write_yuv(const uint8_t* yuv_data); | ||
20 | + bool write_frame(const AVFrame* frame); | ||
21 | + bool write_pkt(AVPacket* pkt); | ||
22 | + bool flush(); | ||
23 | + bool close(); | ||
24 | + | ||
25 | +private: | ||
26 | + bool bgr_to_yuv420p(const uint8_t* const buf_bgr, uint8_t* const buf_420p); | ||
27 | + | ||
28 | +private: | ||
29 | + int width_; | ||
30 | + int height_; | ||
31 | + int y_size_; | ||
32 | + int uv_size_; | ||
33 | + int pts_; | ||
34 | + AVCodecContext* codec_ctx_; | ||
35 | + AVFormatContext* fmt_ctx_; | ||
36 | + AVStream* out_stream_; | ||
37 | + AVFrame* yuv_frame_; | ||
38 | +}; | ||
0 | \ No newline at end of file | 39 | \ No newline at end of file |
src/decoder/dvpp/FFRecoderTaskManager.cpp
@@ -60,6 +60,31 @@ bool FFRecoderTaskManager::init(AVStream* stream, AVCodecContext* avctx){ | @@ -60,6 +60,31 @@ bool FFRecoderTaskManager::init(AVStream* stream, AVCodecContext* avctx){ | ||
60 | return true; | 60 | return true; |
61 | } | 61 | } |
62 | 62 | ||
63 | +bool FFRecoderTaskManager::init2(int w, int h, int fps, int bit_rate) { | ||
64 | + m_width = w; | ||
65 | + m_height = h; | ||
66 | + m_bit_rate = bit_rate; | ||
67 | + | ||
68 | + if (fps > 1) { | ||
69 | + m_fps = fps; | ||
70 | + } else { | ||
71 | + m_fps = 25; | ||
72 | + } | ||
73 | + | ||
74 | + m_recoder_thread = new std::thread( | ||
75 | + [](void* arg) { | ||
76 | + FFRecoderTaskManager* _this=(FFRecoderTaskManager*)arg; | ||
77 | + if(_this != nullptr) { | ||
78 | + _this->recode_thread2(); | ||
79 | + }else{ | ||
80 | + LOG_ERROR("recode 线程启动失败 !"); | ||
81 | + } | ||
82 | + return (void*)0; | ||
83 | + }, this); | ||
84 | + | ||
85 | + return true; | ||
86 | +} | ||
87 | + | ||
63 | static AVPacket* packet_clone(AVPacket* pkt) { | 88 | static AVPacket* packet_clone(AVPacket* pkt) { |
64 | AVPacket *new_pkt = av_packet_alloc(); | 89 | AVPacket *new_pkt = av_packet_alloc(); |
65 | av_init_packet( new_pkt ); | 90 | av_init_packet( new_pkt ); |
@@ -259,6 +284,102 @@ void FFRecoderTaskManager::recode_thread() { | @@ -259,6 +284,102 @@ void FFRecoderTaskManager::recode_thread() { | ||
259 | LOG_INFO("recode_thread end."); | 284 | LOG_INFO("recode_thread end."); |
260 | } | 285 | } |
261 | 286 | ||
287 | + | ||
288 | +void FFRecoderTaskManager::recode_thread2() { | ||
289 | + LOG_INFO("recode_thread2 start..."); | ||
290 | + while(true) { | ||
291 | + if(m_bExit) { | ||
292 | + break; | ||
293 | + } | ||
294 | + | ||
295 | + m_recoderinfo_list_mtx.lock(); | ||
296 | + if(m_recoderinfo_list.size() <= 0){ | ||
297 | + m_recoderinfo_list_mtx.unlock(); | ||
298 | + std::this_thread::sleep_for(std::chrono::milliseconds(3)); | ||
299 | + continue; | ||
300 | + } | ||
301 | + | ||
302 | + auto it_param = m_recoderinfo_list.begin(); | ||
303 | + RecoderInfo recoderinfo = *it_param; | ||
304 | + m_recoderinfo_list_mtx.unlock(); | ||
305 | + | ||
306 | + do | ||
307 | + { | ||
308 | + auto it_data = getStartIterator(recoderinfo.frame_nb); | ||
309 | + if(it_data == m_pkt_list.end()) { | ||
310 | + std::this_thread::sleep_for(std::chrono::milliseconds(3)); | ||
311 | + break; | ||
312 | + } | ||
313 | + | ||
314 | + LOG_INFO("start frame_nb: {}", (*it_data)->frame_nb); | ||
315 | + | ||
316 | + m_pkt_list_mtx.lock(); | ||
317 | + auto it = m_pkt_list.begin(); | ||
318 | + while (it != it_data) { | ||
319 | + DataPacket* dataPkt = m_pkt_list.front(); | ||
320 | + delete dataPkt; | ||
321 | + dataPkt = nullptr; | ||
322 | + m_pkt_list.pop_front(); | ||
323 | + it = m_pkt_list.begin(); | ||
324 | + } | ||
325 | + m_pkt_list_mtx.unlock(); | ||
326 | + | ||
327 | + string file_name = recoderinfo.recoderPath; | ||
328 | + | ||
329 | + FFRecoder2 ffrecoder; | ||
330 | + bool bInit = ffrecoder.init(m_width, m_height, m_fps, m_bit_rate, file_name.c_str()); | ||
331 | + if (!bInit) { | ||
332 | + LOG_ERROR("ffrecoder init error : {} {} {}", recoderinfo.task_id, recoderinfo.object_id, recoderinfo.frame_nb); | ||
333 | + ffrecoder.uninit(); | ||
334 | + break; | ||
335 | + } | ||
336 | + LOG_DEBUG("record start, pkt_list size: {} task_id: {} object_id:{} frame_nb: {}", m_pkt_list.size(), recoderinfo.task_id, recoderinfo.object_id, recoderinfo.frame_nb); | ||
337 | + | ||
338 | + int count = 0; | ||
339 | + auto it_save = it_data; | ||
340 | + unsigned long long start_frame_nb = (*it_data)->frame_nb; | ||
341 | + unsigned long long end_frame_nb = (*it_data)->frame_nb; | ||
342 | + for (; it_save != m_pkt_list.end() && count < 500; ++it_save) { | ||
343 | + DataPacket* dataPkt = *it_save; | ||
344 | + if(dataPkt->frame_nb > recoderinfo.frame_nb) { | ||
345 | + break; | ||
346 | + } | ||
347 | + AVPacket* pkt = dataPkt->pkt; | ||
348 | + if(pkt == nullptr) { | ||
349 | + LOG_ERROR("{} pkt is nullptr", recoderinfo.task_id); | ||
350 | + continue; | ||
351 | + } else if (pkt->data == nullptr || pkt->size <= 0){ | ||
352 | + LOG_ERROR("{} pkt data is nullptr", recoderinfo.task_id); | ||
353 | + continue; | ||
354 | + } | ||
355 | + | ||
356 | + ffrecoder.write_pkt(pkt); | ||
357 | + count++; | ||
358 | + end_frame_nb = (*it_save)->frame_nb; | ||
359 | + } | ||
360 | + | ||
361 | + ffrecoder.flush(); | ||
362 | + ffrecoder.uninit(); | ||
363 | + | ||
364 | + // 发送mq消息 | ||
365 | + if(mq_publish_func && recoderinfo.mq_info.length() > 0) { | ||
366 | + mq_publish_func(recoderinfo.mq_info.c_str()); | ||
367 | + // LOG_INFO("record save: {}", recoderinfo.mq_info.c_str()); | ||
368 | + } | ||
369 | + | ||
370 | + LOG_INFO("record end, total save: {} start_frame_nb: {} end_frame_nb: {} file_path: {}", count, start_frame_nb, end_frame_nb, file_name); | ||
371 | + } while (0); | ||
372 | + | ||
373 | + // m_recoderinfo_list 为空会触发 m_pkt_list size 大于1000时的删除操作, | ||
374 | + // 因此应当在本次m_pkt_list操作都完成之后再pop,避免这边在用m_pkt_list, 另一边在删除,从而导致崩溃 | ||
375 | + m_recoderinfo_list_mtx.lock(); | ||
376 | + m_recoderinfo_list.pop_front(); | ||
377 | + m_recoderinfo_list_mtx.unlock(); | ||
378 | + } | ||
379 | + | ||
380 | + LOG_INFO("recode_thread end."); | ||
381 | +} | ||
382 | + | ||
262 | void FFRecoderTaskManager::close() { | 383 | void FFRecoderTaskManager::close() { |
263 | m_bExit = true; | 384 | m_bExit = true; |
264 | 385 |
src/decoder/dvpp/FFRecoderTaskManager.h
1 | #include "FFRecoder.h" | 1 | #include "FFRecoder.h" |
2 | +#include "FFRecoder2.h" | ||
2 | 3 | ||
3 | #include "../../ai_platform/common_header.h" | 4 | #include "../../ai_platform/common_header.h" |
4 | #include "depend_headers.h" | 5 | #include "depend_headers.h" |
@@ -28,6 +29,7 @@ public: | @@ -28,6 +29,7 @@ public: | ||
28 | void cache_pkt(AVPacket* pkt, long long frame_nb); | 29 | void cache_pkt(AVPacket* pkt, long long frame_nb); |
29 | 30 | ||
30 | bool init(AVStream* stream, AVCodecContext* avctx); | 31 | bool init(AVStream* stream, AVCodecContext* avctx); |
32 | + bool init2(int w, int h, int fps, int bit_rate); | ||
31 | void create_recode_task(RecoderInfo& recoderInfo); | 33 | void create_recode_task(RecoderInfo& recoderInfo); |
32 | 34 | ||
33 | void close(); | 35 | void close(); |
@@ -36,6 +38,7 @@ public: | @@ -36,6 +38,7 @@ public: | ||
36 | 38 | ||
37 | public: | 39 | public: |
38 | void recode_thread(); | 40 | void recode_thread(); |
41 | + void recode_thread2(); | ||
39 | 42 | ||
40 | private: | 43 | private: |
41 | void save_intask_recoderinfo(RecoderInfo info); | 44 | void save_intask_recoderinfo(RecoderInfo info); |
@@ -59,4 +62,10 @@ private: | @@ -59,4 +62,10 @@ private: | ||
59 | thread* m_recoder_thread{nullptr}; | 62 | thread* m_recoder_thread{nullptr}; |
60 | 63 | ||
61 | mq_callback_t mq_publish_func; | 64 | mq_callback_t mq_publish_func; |
65 | + | ||
66 | + // FFRecoder2 | ||
67 | + int m_width; | ||
68 | + int m_height; | ||
69 | + int m_fps; | ||
70 | + int m_bit_rate; | ||
62 | }; | 71 | }; |
63 | \ No newline at end of file | 72 | \ No newline at end of file |
src/decoder/gb28181/DvppGB28181Decoder.cpp
@@ -374,13 +374,30 @@ int DvppGB28181Decoder::getCachedQueueLength(){ | @@ -374,13 +374,30 @@ int DvppGB28181Decoder::getCachedQueueLength(){ | ||
374 | } | 374 | } |
375 | 375 | ||
376 | DeviceMemory* DvppGB28181Decoder::snapshot() { | 376 | DeviceMemory* DvppGB28181Decoder::snapshot() { |
377 | - return nullptr; | 377 | + |
378 | + DeviceMemory* snapshot_mem = nullptr; | ||
379 | + int loop_times = 0; | ||
380 | + while (isRunning()) { | ||
381 | + snapshot_mem = streamDecoder.GetFrame(); | ||
382 | + if (snapshot_mem) { | ||
383 | + break; | ||
384 | + } | ||
385 | + | ||
386 | + loop_times++; | ||
387 | + if(loop_times > 100) { | ||
388 | + // 1s都没截取到图,退出 | ||
389 | + break; | ||
390 | + } | ||
391 | + std::this_thread::sleep_for(std::chrono::milliseconds(10)); | ||
392 | + } | ||
393 | + | ||
394 | + return snapshot_mem; | ||
378 | } | 395 | } |
379 | 396 | ||
380 | void DvppGB28181Decoder::doRecode(RecoderInfo& recoderInfo) { | 397 | void DvppGB28181Decoder::doRecode(RecoderInfo& recoderInfo) { |
381 | - | 398 | + return streamDecoder.doRecode(recoderInfo); |
382 | } | 399 | } |
383 | 400 | ||
384 | void DvppGB28181Decoder::set_mq_callback(std::function<bool(const char *msg)> mq_publish) { | 401 | void DvppGB28181Decoder::set_mq_callback(std::function<bool(const char *msg)> mq_publish) { |
385 | - | 402 | + streamDecoder.set_mq_callback(mq_publish); |
386 | } | 403 | } |
387 | \ No newline at end of file | 404 | \ No newline at end of file |
src/decoder/test_28181.cpp
@@ -142,19 +142,8 @@ int main(){ | @@ -142,19 +142,8 @@ int main(){ | ||
142 | 142 | ||
143 | printf("start... \n"); | 143 | printf("start... \n"); |
144 | 144 | ||
145 | - ServerInfo info( | ||
146 | - "SY_Sip_Server", | ||
147 | - "12345678", | ||
148 | - "192.168.60.179", | ||
149 | - 15060, | ||
150 | - "34020000002000000002", | ||
151 | - "3402000000", | ||
152 | - "sy123456", | ||
153 | - 1800, | ||
154 | - 3600); | ||
155 | - | ||
156 | SipServer* pSipServer = SipServer::getInstance(); | 145 | SipServer* pSipServer = SipServer::getInstance(); |
157 | - pSipServer->Init(info); | 146 | + pSipServer->Init(nullptr); |
158 | 147 | ||
159 | 148 | ||
160 | DecoderManager* pDecManager = DecoderManager::getInstance(); | 149 | DecoderManager* pDecManager = DecoderManager::getInstance(); |
src/demo/demo.cpp
@@ -1125,7 +1125,7 @@ string createTask_dvpp28181(void *handle, std::vector<algorithm_type_t> algor_ve | @@ -1125,7 +1125,7 @@ string createTask_dvpp28181(void *handle, std::vector<algorithm_type_t> algor_ve | ||
1125 | 1125 | ||
1126 | algor_init_config_param_t* config_param = tparam.algor_config_params[idx].algor_init_config_param; | 1126 | algor_init_config_param_t* config_param = tparam.algor_config_params[idx].algor_init_config_param; |
1127 | delete config_param; | 1127 | delete config_param; |
1128 | - }else if(tparam.algor_config_params[idx].algor_type == algorithm_type_t::VEHICLE_SOLIDLINETURNAROUND) { | 1128 | + } else if(tparam.algor_config_params[idx].algor_type == algorithm_type_t::VEHICLE_SOLIDLINETURNAROUND) { |
1129 | algor_config_param_manned_incident* algor_param = (algor_config_param_manned_incident*)tparam.algor_config_params[idx].algor_init_config_param->algor_param; | 1129 | algor_config_param_manned_incident* algor_param = (algor_config_param_manned_incident*)tparam.algor_config_params[idx].algor_init_config_param->algor_param; |
1130 | delete algor_param; | 1130 | delete algor_param; |
1131 | algor_basic_config_param_t* basic_param = (algor_basic_config_param_t*)tparam.algor_config_params[idx].algor_init_config_param->basic_param; | 1131 | algor_basic_config_param_t* basic_param = (algor_basic_config_param_t*)tparam.algor_config_params[idx].algor_init_config_param->basic_param; |
@@ -1326,13 +1326,13 @@ while (ch != 'q') { | @@ -1326,13 +1326,13 @@ while (ch != 'q') { | ||
1326 | switch (ch) | 1326 | switch (ch) |
1327 | { | 1327 | { |
1328 | case '0': | 1328 | case '0': |
1329 | - createTask_dvpp28181(handle, algor_vec2, 0, false); | 1329 | + createTask_dvpp28181(handle, algor_vec, 0, false); |
1330 | break; | 1330 | break; |
1331 | case '1': | 1331 | case '1': |
1332 | - createTask_dvpp28181(handle, algor_vec2, 1, false); | 1332 | + createTask_dvpp28181(handle, algor_vec, 1, false); |
1333 | break; | 1333 | break; |
1334 | case '2': | 1334 | case '2': |
1335 | - createTask_dvpp28181(handle, algor_vec2, 2, false); | 1335 | + createTask_dvpp28181(handle, algor_vec, 2, false); |
1336 | break; | 1336 | break; |
1337 | case 'c': | 1337 | case 'c': |
1338 | close_all_task(handle); | 1338 | close_all_task(handle); |