Commit fce4580d65558172deb944f08e65d0640546360c
1 parent
b00d3d35
更新最新代码:修改解码器实现方式并修改一些bug;优化代码
Showing
8 changed files
with
945 additions
and
1089 deletions
src/ai_platform/MultiSourceProcess.cpp
... | ... | @@ -207,8 +207,7 @@ bool CMultiSourceProcess::AddTask(task_param _cur_task_param){ |
207 | 207 | } |
208 | 208 | |
209 | 209 | AbstractDecoder* dec = pDecManager->createDecoder(config); |
210 | - if (!dec) | |
211 | - { | |
210 | + if (!dec){ | |
212 | 211 | return false; |
213 | 212 | } |
214 | 213 | |
... | ... | @@ -417,6 +416,10 @@ bool CMultiSourceProcess::finish_task(const string taskID, const bool delete_sna |
417 | 416 | mq_manager_->publish(mq_type_t::HEART_BEAT_MQ, json_str.c_str(), true); |
418 | 417 | #endif |
419 | 418 | |
419 | +#ifdef WITH_SECOND_PROCESS | |
420 | + pedestrian_vehicle_retrograde_.force_release_result(taskID); //221024 byzsh | |
421 | +#endif | |
422 | + | |
420 | 423 | m_task_param_manager->delete_task_param(taskID); |
421 | 424 | |
422 | 425 | return true; |
... | ... | @@ -496,6 +499,7 @@ int CMultiSourceProcess::algorthim_vpt(vector<DeviceMemory*> vec_gpuMem){ |
496 | 499 | sy_img img; |
497 | 500 | img.w_ = mem->getWidth(); |
498 | 501 | img.h_ = mem->getHeight(); |
502 | + img.c_ = mem->getChannel(); | |
499 | 503 | img.data_ = mem->getMem(); |
500 | 504 | vpt_interest_imgs.push_back(img); |
501 | 505 | vpt_interest_task_id.push_back(mem->getId()); |
... | ... | @@ -517,7 +521,6 @@ int CMultiSourceProcess::algorthim_vpt(vector<DeviceMemory*> vec_gpuMem){ |
517 | 521 | #ifndef VEHICLE_MULTI_BOXES |
518 | 522 | /* 快照优选(内部可实现不同的快照优选策略) */ |
519 | 523 | m_snapshot_reprocessing->update_bestsnapshot(vec_vptMem, vptResult, deleteObjectID); |
520 | - | |
521 | 524 | /* for snapshot algorithm. 轨迹结束目标 做最后的结果返回(当前返回算法结果+快照保存路径)*/ |
522 | 525 | vehicle_snapshot(vpt_interest_task_id, deleteObjectID); |
523 | 526 | #else |
... | ... | @@ -530,8 +533,12 @@ int CMultiSourceProcess::algorthim_vpt(vector<DeviceMemory*> vec_gpuMem){ |
530 | 533 | /* for pedestrian safety det. 行人安全分析算法模块 */ |
531 | 534 | // algorthim_pedestrian_safety(vpt_interest_task_id, vpt_interest_imgs,vptResult); |
532 | 535 | |
533 | - /* for retrograde & trespass algor 逆行&非法闯入算法模块 */ | |
534 | - algorthim_retrograde_trespass(vpt_interest_task_id, vec_vptMem, vptResult, deleteObjectID); | |
536 | + // 逆行 | |
537 | + algorthim_retrograde(vpt_interest_task_id, vec_vptMem, vptResult); | |
538 | + retrograde_snapshot(vpt_interest_task_id, deleteObjectID); | |
539 | + // 闯入 | |
540 | + algorthim_trespass(vpt_interest_task_id, vec_vptMem, vptResult, deleteObjectID); | |
541 | + trespass_snapshot(vpt_interest_task_id, deleteObjectID); | |
535 | 542 | |
536 | 543 | // #endif |
537 | 544 | |
... | ... | @@ -662,21 +669,12 @@ void CMultiSourceProcess::vehicle_snapshot(vector<string>& vpt_interest_task_id, |
662 | 669 | for (int &j : deleteObjectID[i]) // loop algor type. |
663 | 670 | { |
664 | 671 | OBJ_KEY obj_key = {*task_iter, j}; |
665 | - endframe_obj_process(obj_key, algorithm_type_t::PLACEHOLDER); | |
672 | + // 该路任务开启了抓拍功能 开始抓拍保存;若未开启抓拍,清空显存资源 | |
673 | + vehicle_locus_finished(obj_key); | |
666 | 674 | } |
667 | 675 | } |
668 | 676 | } |
669 | 677 | |
670 | -/* 轨迹结束帧需要做的算法模块 */ | |
671 | -int CMultiSourceProcess::endframe_obj_process(const OBJ_KEY &obj_key, algorithm_type_t algor_type) { | |
672 | - | |
673 | - // 该路任务开启了抓拍功能 开始抓拍保存;若未开启抓拍,清空显存资源 | |
674 | - vehicle_locus_finished(obj_key); | |
675 | - | |
676 | - /* 开启行人&机动车逆行算法模块,获取该目标的算法分析结果 返回结果+快照 最后释放资源 */ | |
677 | - endframe_retrograde_trespass(obj_key); | |
678 | -} | |
679 | - | |
680 | 678 | void CMultiSourceProcess::vehicle_locus_finished(const OBJ_KEY obj_key) { |
681 | 679 | auto task_param_ptr = m_task_param_manager->get_task_algor_param(obj_key.video_id); |
682 | 680 | auto task_other_param_ptr = m_task_param_manager->get_task_other_param(obj_key.video_id); |
... | ... | @@ -809,16 +807,12 @@ void CMultiSourceProcess::timing_snapshot_thread(){ |
809 | 807 | LOG_INFO("timing_snapshot_thread end."); |
810 | 808 | } |
811 | 809 | |
812 | -void CMultiSourceProcess::algorthim_retrograde_trespass(vector<string>& vpt_interest_task_id, vector<DeviceMemory*> vpt_interest_imgs, | |
813 | - vector<onelevel_det_result>& vptResult ,vector<vector<int>>& deleteObjectID){ | |
810 | +// 逆行 | |
811 | +void CMultiSourceProcess::algorthim_retrograde(vector<string>& vpt_interest_task_id, vector<DeviceMemory*> vpt_interest_imgs, | |
812 | + vector<onelevel_det_result>& vptResult){ | |
814 | 813 | vector<string> interest_task_id; |
815 | 814 | vector<onelevel_det_result> interest_vpt_result; |
816 | - vector<DeviceMemory*> interest_imgs; | |
817 | - | |
818 | - vector<string> trespass_interest_task_id; | |
819 | - vector<onelevel_det_result> trespass_interest_vpt_result; | |
820 | - vector<vector<int>> trespass_interest_deleteobjs; | |
821 | - vector<DeviceMemory*> trespass_interest_imgs; | |
815 | + vector<DeviceMemory*> interest_imgs; | |
822 | 816 | |
823 | 817 | int _idx = 0; |
824 | 818 | for (auto _task_id_iter = vpt_interest_task_id.begin(); _task_id_iter != vpt_interest_task_id.end(); |
... | ... | @@ -833,6 +827,30 @@ void CMultiSourceProcess::algorthim_retrograde_trespass(vector<string>& vpt_inte |
833 | 827 | interest_imgs.emplace_back(vpt_interest_imgs[_idx]); |
834 | 828 | interest_vpt_result.emplace_back(vptResult[_idx]); |
835 | 829 | } |
830 | + } | |
831 | + | |
832 | + LOG_DEBUG("retrograde interest_vpt_result size: {}", interest_vpt_result.size()); | |
833 | + | |
834 | + if (!interest_imgs.empty()){ | |
835 | + pedestrian_vehicle_retrograde_.update_mstreams(interest_task_id, interest_imgs, interest_vpt_result); | |
836 | + } | |
837 | +} | |
838 | + | |
839 | +// 闯入 | |
840 | +void CMultiSourceProcess::algorthim_trespass(vector<string>& vpt_interest_task_id, vector<DeviceMemory*> vpt_interest_imgs, | |
841 | + vector<onelevel_det_result>& vptResult ,vector<vector<int>>& deleteObjectID){ | |
842 | + | |
843 | + vector<string> trespass_interest_task_id; | |
844 | + vector<onelevel_det_result> trespass_interest_vpt_result; | |
845 | + vector<vector<int>> trespass_interest_deleteobjs; | |
846 | + vector<DeviceMemory*> trespass_interest_imgs; | |
847 | + | |
848 | + int _idx = 0; | |
849 | + for (auto _task_id_iter = vpt_interest_task_id.begin(); _task_id_iter != vpt_interest_task_id.end(); | |
850 | + ++_task_id_iter, ++_idx) // loop task_id; | |
851 | + { | |
852 | + auto task_id = *_task_id_iter; | |
853 | + auto algor_map = m_task_param_manager->get_task_other_param(task_id); | |
836 | 854 | |
837 | 855 | if (algor_map->find(algorithm_type_t::PEDESTRIAN_TRESPASS) != algor_map->end() || |
838 | 856 | algor_map->find(algorithm_type_t::VEHICLE_TRESPASS) != algor_map->end()) { |
... | ... | @@ -843,36 +861,58 @@ void CMultiSourceProcess::algorthim_retrograde_trespass(vector<string>& vpt_inte |
843 | 861 | } |
844 | 862 | } |
845 | 863 | |
846 | - LOG_DEBUG("trespass_interest_vpt_result size: {}", trespass_interest_vpt_result.size()); | |
847 | - | |
848 | - if (!interest_imgs.empty()) | |
849 | - pedestrian_vehicle_retrograde_.update_mstreams(interest_task_id, interest_imgs, | |
850 | - interest_vpt_result); | |
864 | + LOG_DEBUG("trespass interest_vpt_result size: {}", trespass_interest_vpt_result.size()); | |
851 | 865 | |
852 | 866 | if (!trespass_interest_imgs.empty()) { |
853 | - pedestrian_vehicle_trespass_.update_mstreams( | |
854 | - trespass_interest_task_id, trespass_interest_imgs, trespass_interest_vpt_result, | |
855 | - trespass_interest_deleteobjs); | |
867 | + pedestrian_vehicle_trespass_.update_mstreams( trespass_interest_task_id, trespass_interest_imgs, | |
868 | + trespass_interest_vpt_result, trespass_interest_deleteobjs); | |
856 | 869 | } |
857 | 870 | } |
858 | 871 | |
859 | -int CMultiSourceProcess::endframe_retrograde_trespass(const OBJ_KEY &obj_key) { | |
860 | - auto task_param_ptr = m_task_param_manager->get_task_algor_param(obj_key.video_id); | |
861 | 872 | |
862 | - /* 开启行人&机动车逆行算法模块,获取该目标的算法分析结果 返回结果+快照 最后释放资源 */ | |
863 | - if (task_param_ptr->human_algors.find(algorithm_type_t::PEDESTRIAN_RETROGRADE) != | |
864 | - task_param_ptr->human_algors.end()) | |
865 | - retrograde_trespass_alarm(obj_key, algorithm_type_t::PEDESTRIAN_RETROGRADE); | |
873 | +// for snapshot algorithm. 轨迹结束目标 做最后的结果返回(当前返回算法结果+快照保存路径) | |
874 | +void CMultiSourceProcess::retrograde_snapshot(vector<string>& vpt_interest_task_id, vector<vector<int>> deleteObjectID) { | |
875 | + auto task_iter = vpt_interest_task_id.begin(); | |
876 | + | |
877 | + for (int i = 0; i < deleteObjectID.size(); i++, ++task_iter) // loop taskId. | |
878 | + { | |
879 | + for (int &j : deleteObjectID[i]) // loop algor type. | |
880 | + { | |
881 | + OBJ_KEY obj_key = {*task_iter, j}; | |
882 | + auto task_param_ptr = m_task_param_manager->get_task_algor_param(obj_key.video_id); | |
883 | + | |
884 | + /* 开启行人&机动车逆行算法模块,获取该目标的算法分析结果 返回结果+快照 最后释放资源 */ | |
885 | + if (task_param_ptr->human_algors.find(algorithm_type_t::PEDESTRIAN_RETROGRADE) != task_param_ptr->human_algors.end()){ | |
886 | + retrograde_trespass_alarm(obj_key, algorithm_type_t::PEDESTRIAN_RETROGRADE); | |
887 | + } | |
888 | + | |
889 | + if (task_param_ptr->vehicle_algors.find(algorithm_type_t::VEHICLE_RETROGRADE) != task_param_ptr->vehicle_algors.end()){ | |
890 | + retrograde_trespass_alarm(obj_key, algorithm_type_t::VEHICLE_RETROGRADE); | |
891 | + } | |
892 | + } | |
893 | + } | |
894 | +} | |
866 | 895 | |
867 | - if (task_param_ptr->vehicle_algors.find(algorithm_type_t::VEHICLE_RETROGRADE) != | |
868 | - task_param_ptr->vehicle_algors.end()) | |
869 | - retrograde_trespass_alarm(obj_key, algorithm_type_t::VEHICLE_RETROGRADE); | |
896 | +// for snapshot algorithm. 轨迹结束目标 做最后的结果返回(当前返回算法结果+快照保存路径) | |
897 | +void CMultiSourceProcess::trespass_snapshot(vector<string>& vpt_interest_task_id, vector<vector<int>> deleteObjectID) { | |
898 | + auto task_iter = vpt_interest_task_id.begin(); | |
870 | 899 | |
871 | - if (task_param_ptr->human_algors.find(algorithm_type_t::PEDESTRIAN_TRESPASS) != task_param_ptr->human_algors.end()) | |
872 | - retrograde_trespass_alarm(obj_key, algorithm_type_t::PEDESTRIAN_TRESPASS); | |
900 | + for (int i = 0; i < deleteObjectID.size(); i++, ++task_iter) // loop taskId. | |
901 | + { | |
902 | + for (int &j : deleteObjectID[i]) // loop algor type. | |
903 | + { | |
904 | + OBJ_KEY obj_key = {*task_iter, j}; | |
905 | + auto task_param_ptr = m_task_param_manager->get_task_algor_param(obj_key.video_id); | |
873 | 906 | |
874 | - if (task_param_ptr->vehicle_algors.find(algorithm_type_t::VEHICLE_TRESPASS) != task_param_ptr->vehicle_algors.end()) | |
875 | - retrograde_trespass_alarm(obj_key, algorithm_type_t::VEHICLE_TRESPASS); | |
907 | + if (task_param_ptr->human_algors.find(algorithm_type_t::PEDESTRIAN_TRESPASS) != task_param_ptr->human_algors.end()){ | |
908 | + retrograde_trespass_alarm(obj_key, algorithm_type_t::PEDESTRIAN_TRESPASS); | |
909 | + } | |
910 | + | |
911 | + if (task_param_ptr->vehicle_algors.find(algorithm_type_t::VEHICLE_TRESPASS) != task_param_ptr->vehicle_algors.end()){ | |
912 | + retrograde_trespass_alarm(obj_key, algorithm_type_t::VEHICLE_TRESPASS); | |
913 | + } | |
914 | + } | |
915 | + } | |
876 | 916 | } |
877 | 917 | |
878 | 918 | void CMultiSourceProcess::retrograde_trespass_alarm(const OBJ_KEY &obj_key, const algorithm_type_t &algor_type) { |
... | ... | @@ -946,7 +986,6 @@ bool CMultiSourceProcess::save_snapshot_process(const OBJ_KEY &obj_key, const al |
946 | 986 | obj_save_info.json_str = json_str; |
947 | 987 | m_save_snapshot_reprocessing->reprocessing_process_wo_locus_async(obj_save_info); |
948 | 988 | } |
949 | - | |
950 | 989 | |
951 | 990 | return true; |
952 | 991 | } |
953 | 992 | \ No newline at end of file | ... | ... |
src/ai_platform/MultiSourceProcess.h
... | ... | @@ -49,9 +49,11 @@ public: |
49 | 49 | private: |
50 | 50 | // 算法相关 |
51 | 51 | int algorthim_vpt(vector<DeviceMemory*> vec_gpuMem); |
52 | - // 逆行&非法闯入算法模块 | |
53 | - void algorthim_retrograde_trespass(vector<string>& vpt_interest_task_id, vector<DeviceMemory*> vpt_interest_imgs, | |
54 | - vector<onelevel_det_result>& vptResult ,vector<vector<int>>& deleteObjectID); | |
52 | + // 逆行 | |
53 | + void algorthim_retrograde(vector<string>& vpt_interest_task_id, vector<DeviceMemory*> vpt_interest_imgs, vector<onelevel_det_result>& vptResult); | |
54 | + // 闯入 | |
55 | + void algorthim_trespass(vector<string>& vpt_interest_task_id, vector<DeviceMemory*> vpt_interest_imgs, | |
56 | + vector<onelevel_det_result>& vptResult ,vector<vector<int>>& deleteObjectID); | |
55 | 57 | |
56 | 58 | private: |
57 | 59 | // 工具处理函数 |
... | ... | @@ -63,12 +65,11 @@ private: |
63 | 65 | void vehicle_snapshot(vector<string>& vpt_interest_task_id, vector<vector<int>> deleteObjectID); |
64 | 66 | void vehicle_locus_finished(const OBJ_KEY obj_key); |
65 | 67 | |
66 | - int endframe_obj_process(const OBJ_KEY &obj_key, algorithm_type_t algor_type); | |
67 | - | |
68 | 68 | bool save_snapshot_process(const OBJ_KEY &obj_key, const algorithm_type_t &algorithm_type, vpc_img_info img_info, vpc_img_info roi_img, |
69 | 69 | const long long id,const std::string &json_str); |
70 | 70 | |
71 | - int endframe_retrograde_trespass(const OBJ_KEY &obj_key); | |
71 | + void retrograde_snapshot(vector<string>& vpt_interest_task_id, vector<vector<int>> deleteObjectID); | |
72 | + void trespass_snapshot(vector<string>& vpt_interest_task_id, vector<vector<int>> deleteObjectID); | |
72 | 73 | void retrograde_trespass_alarm(const OBJ_KEY &obj_key, const algorithm_type_t &algor_type) ; |
73 | 74 | |
74 | 75 | private: | ... | ... |
src/decoder/dvpp/DvppDec.cpp deleted
1 | -#include "DvppDec.h" | |
2 | -#include "DvppSourceManager.h" | |
3 | - | |
4 | -#include "../../util/vpc_util.h" | |
5 | - | |
6 | -struct Vdec_CallBack_UserData { | |
7 | - uint64_t frameId; | |
8 | - long startTime; | |
9 | - long sendTime; | |
10 | - // void* vdecOutputBuf; | |
11 | - DvppDec* self; | |
12 | - shared_ptr<MemNode> inBufNode; | |
13 | - Vdec_CallBack_UserData() { | |
14 | - frameId = 0; | |
15 | - } | |
16 | -}; | |
17 | - | |
18 | -static const int g_pkt_size = 1024 * 1024; | |
19 | - | |
20 | - DvppDec::DvppDec(){ | |
21 | - m_decode_thread = 0; | |
22 | - m_cached_mem = nullptr; | |
23 | - } | |
24 | - | |
25 | - DvppDec::~DvppDec(){ | |
26 | - releaseResource(); | |
27 | - } | |
28 | - | |
29 | - bool DvppDec::init_vdpp(DvppDecConfig cfg){ | |
30 | - | |
31 | - m_dec_name = cfg.dec_name; | |
32 | - | |
33 | - LOG_INFO("[{}]- Init device start...", m_dec_name); | |
34 | - | |
35 | - m_dvpp_deviceId = atoi(cfg.dev_id.c_str()); | |
36 | - | |
37 | - if(cfg.codec_id == 0){ | |
38 | - // 66:Baseline,77:Main,>=100:High | |
39 | - if(cfg.profile == 77){ | |
40 | - enType = H264_MAIN_LEVEL; | |
41 | - }else if(cfg.profile < 77){ | |
42 | - enType = H264_BASELINE_LEVEL; | |
43 | - }else{ | |
44 | - enType = H264_HIGH_LEVEL; | |
45 | - } | |
46 | - }else if(cfg.codec_id == 1){ | |
47 | - // h265只有main | |
48 | - enType = H265_MAIN_LEVEL; | |
49 | - }else { | |
50 | - LOG_ERROR("[{}]- codec_id is not supported!", m_dec_name); | |
51 | - return false; | |
52 | - } | |
53 | - | |
54 | - post_decoded_cbk = cfg.post_decoded_cbk; | |
55 | - m_pktQueueptr = cfg.pktQueueptr; | |
56 | - | |
57 | - // DvppSourceManager 创建时包含 aclInit,析构时包含 aclFinalize | |
58 | - DvppSourceManager* pSrcMgr = DvppSourceManager::getInstance(); | |
59 | - m_context = pSrcMgr->getContext(m_dvpp_deviceId); | |
60 | - m_dvpp_channel = pSrcMgr->getChannel(m_dvpp_deviceId); | |
61 | - if(m_dvpp_channel < 0){ | |
62 | - LOG_ERROR("[{}]-该设备channel已经用完了!", m_dec_name); | |
63 | - return false; | |
64 | - } | |
65 | - | |
66 | - do | |
67 | - { | |
68 | - CHECK_AND_BREAK(aclrtSetCurrentContext(m_context), "aclrtSetCurrentContext failed !"); | |
69 | - | |
70 | - int ret = 0; | |
71 | - // int ret = picConverter.init(m_context, m_dec_name); | |
72 | - // if(ret != ACL_ERROR_NONE){ | |
73 | - // LOG_ERROR("[{}]- acldvppMalloc failed!, ret:{}", m_dec_name, ret); | |
74 | - // break; | |
75 | - // } | |
76 | - | |
77 | - // queue_size 最小应大于16,否则关键帧之间距离太远的时候会导致回调函数与循环队列卡死 | |
78 | - for (size_t i = 0; i < 20; i++){ | |
79 | - void *vdecInputbuf = nullptr; | |
80 | - ret = acldvppMalloc((void **)&vdecInputbuf, g_pkt_size); | |
81 | - if(ret != ACL_ERROR_NONE){ | |
82 | - LOG_ERROR("[{}]- acldvppMalloc failed!, ret:{}", m_dec_name, ret); | |
83 | - // 析构函数中有对channel 的补救性释放,所以这里可以直接return | |
84 | - return false;; | |
85 | - } | |
86 | - m_vec_vdec.push_back(vdecInputbuf); | |
87 | - } | |
88 | - | |
89 | - if(!m_vdecQueue.init(m_vec_vdec)){ | |
90 | - break; | |
91 | - } | |
92 | - | |
93 | - m_vdec_out_size = cfg.width * cfg.height * 3 / 2; | |
94 | - | |
95 | - LOG_INFO("[{}]- init vdpp success! device:{} channel:{}", m_dec_name, m_dvpp_deviceId, m_dvpp_channel); | |
96 | - return true; | |
97 | - | |
98 | - } while (0); | |
99 | - | |
100 | - LOG_INFO("[{}]- init vdpp failed!", m_dec_name); | |
101 | - // 初始化失败,释放channel | |
102 | - pSrcMgr->releaseChannel(m_dvpp_deviceId, m_dvpp_channel); | |
103 | - return false; | |
104 | -} | |
105 | - | |
106 | -bool DvppDec::start(){ | |
107 | - m_bRunning = true; | |
108 | - | |
109 | - pthread_create(&m_decode_thread,0, | |
110 | - [](void* arg) | |
111 | - { | |
112 | - DvppDec* a=(DvppDec*)arg; | |
113 | - a->decode_thread(); | |
114 | - return (void*)0; | |
115 | - } | |
116 | - ,this); | |
117 | - | |
118 | - return true; | |
119 | -} | |
120 | - | |
121 | -static void *ReportThd(void *arg) | |
122 | -{ | |
123 | - DvppDec *self = (DvppDec *)arg; | |
124 | - if(nullptr != self){ | |
125 | - self->doProcessReport(); | |
126 | - } | |
127 | - return (void *)0; | |
128 | -} | |
129 | - | |
130 | -void DvppDec::doProcessReport(){ | |
131 | - | |
132 | - aclError ret = aclrtSetDevice(m_dvpp_deviceId); | |
133 | - if(ret != ACL_ERROR_NONE){ | |
134 | - // cout << "aclrtSetDevice failed" << endl; | |
135 | - LOG_ERROR("aclrtSetDevice failed !"); | |
136 | - return ; | |
137 | - } | |
138 | - | |
139 | - aclrtContext ctx; | |
140 | - ret = aclrtCreateContext(&ctx, m_dvpp_deviceId); | |
141 | - if (ret != ACL_ERROR_NONE) { | |
142 | - // cout << "aclrtCreateContext failed " << endl; | |
143 | - LOG_ERROR("aclrtCreateContext failed !"); | |
144 | - return ; | |
145 | - } | |
146 | - | |
147 | - CHECK_AND_RETURN_NOVALUE(aclrtSetCurrentContext(ctx), "aclrtSetCurrentContext failed"); | |
148 | - // 阻塞等待vdec线程开始 | |
149 | - | |
150 | - while (!m_bExitReportThd) { | |
151 | - aclrtProcessReport(1000); | |
152 | - } | |
153 | - | |
154 | - ret = aclrtDestroyContext(ctx); | |
155 | - if(ret != ACL_ERROR_NONE){ | |
156 | - LOG_ERROR("aclrtDestroyContext failed !"); | |
157 | - } | |
158 | - LOG_INFO("doProcessReport exit."); | |
159 | -} | |
160 | - | |
161 | -static void VdecCallback(acldvppStreamDesc *input, acldvppPicDesc *output, void *pUserData) | |
162 | -{ | |
163 | - Vdec_CallBack_UserData *userData = (Vdec_CallBack_UserData *) pUserData; | |
164 | - if(nullptr != userData){ | |
165 | - DvppDec* self = userData->self; | |
166 | - if(self != nullptr){ | |
167 | - | |
168 | - self->doVdppVdecCallBack(input, output); | |
169 | - } | |
170 | - delete userData; | |
171 | - userData = nullptr; | |
172 | - } | |
173 | -} | |
174 | - | |
175 | -void DvppDec::doVdppVdecCallBack(acldvppStreamDesc *input, acldvppPicDesc *output){ | |
176 | - | |
177 | - // dvpp_crop(output); | |
178 | - | |
179 | - CHECK_AND_RETURN_NOVALUE(aclrtSetCurrentContext(m_context), "aclrtSetCurrentContext failed"); | |
180 | - | |
181 | - void *inputDataDev = acldvppGetStreamDescData(input); | |
182 | - void *outputDataDev = acldvppGetPicDescData(output); | |
183 | - uint32_t outputSize = acldvppGetPicDescSize(output); | |
184 | - uint32_t width = acldvppGetPicDescWidth(output); | |
185 | - uint32_t width_stride = acldvppGetPicDescWidthStride(output); | |
186 | - uint32_t height = acldvppGetPicDescHeight(output); | |
187 | - uint32_t height_stride = acldvppGetPicDescHeightStride(output); | |
188 | - | |
189 | - | |
190 | - DvppDataMemory* mem = new DvppDataMemory(width, width_stride, height, height_stride, outputSize, m_dec_name, to_string(m_dvpp_deviceId), false, (unsigned char *)outputDataDev); | |
191 | - post_decoded_cbk(m_postDecArg, mem); | |
192 | - | |
193 | - if(m_bSnapShoting){ | |
194 | - // 缓存snapshot | |
195 | - std::unique_lock<std::mutex> locker(m_cached_mutex); | |
196 | - | |
197 | - m_cached_mem = new DvppDataMemory(-1, width, width_stride, height, height_stride, outputSize, m_dec_name, to_string(m_dvpp_deviceId), false); | |
198 | - if(m_cached_mem != nullptr){ | |
199 | - aclrtMemcpy(m_cached_mem->getMem(), outputSize, (unsigned char *)outputDataDev, outputSize, ACL_MEMCPY_DEVICE_TO_DEVICE); | |
200 | - } | |
201 | - | |
202 | - locker.unlock(); | |
203 | - m_cached_cond.notify_one(); | |
204 | - m_bSnapShoting = false; | |
205 | - } | |
206 | - | |
207 | - | |
208 | - | |
209 | - | |
210 | -// DvppDataMemory* rgbMem = picConverter.convert2bgr(output, width, height, false); | |
211 | -// if(rgbMem != nullptr){ | |
212 | -// #ifdef TEST_DECODER | |
213 | -// // D2H | |
214 | -// if(vdecHostAddr == nullptr){ | |
215 | -// CHECK_NOT_RETURN(aclrtMallocHost(&vdecHostAddr, width * height * 3), "aclrtMallocHost failed"); | |
216 | -// } | |
217 | -// uint32_t data_size = rgbMem->getSize(); | |
218 | -// CHECK_AND_RETURN_NOVALUE(aclrtMemcpy(vdecHostAddr, data_size, rgbMem->getMem(), data_size, ACL_MEMCPY_DEVICE_TO_HOST), "D2H aclrtMemcpy failed"); | |
219 | - | |
220 | -// // 保存vdec结果 | |
221 | -// if(count_frame > 45 && count_frame < 50) | |
222 | -// { | |
223 | -// string file_name = "./yuv_pic/vdec_out_"+ m_dec_name +".rgb" ; | |
224 | -// FILE *outputFile = fopen(file_name.c_str(), "a"); | |
225 | -// if(outputFile){ | |
226 | -// fwrite(vdecHostAddr, data_size, sizeof(char), outputFile); | |
227 | -// fclose(outputFile); | |
228 | -// } | |
229 | -// } | |
230 | -// else if(count_frame > 50 && vdecHostAddr != nullptr){ | |
231 | -// CHECK_NOT_RETURN(aclrtFreeHost(vdecHostAddr), "aclrtFreeHost failed"); | |
232 | -// vdecHostAddr = nullptr; | |
233 | -// } | |
234 | -// count_frame++; | |
235 | -// #endif | |
236 | -// post_decoded_cbk(m_postDecArg, rgbMem); | |
237 | -// }else{ | |
238 | -// LOG_ERROR("[{}]- convert2bgr failed !", m_dec_name); | |
239 | -// } | |
240 | - | |
241 | - // // 测试 | |
242 | - // acldvppFree(outputDataDev); | |
243 | - // outputDataDev = nullptr; | |
244 | - | |
245 | - m_vdecQueue.addHead(); | |
246 | - | |
247 | - CHECK_AND_RETURN_NOVALUE(acldvppDestroyStreamDesc(input), "acldvppDestroyStreamDesc failed"); | |
248 | - CHECK_AND_RETURN_NOVALUE(acldvppDestroyPicDesc(output), "acldvppDestroyPicDesc failed"); | |
249 | -} | |
250 | - | |
251 | -void DvppDec::close(){ | |
252 | - m_bRunning=false; | |
253 | - | |
254 | - if(m_decode_thread != 0){ | |
255 | - pthread_join(m_decode_thread,0); | |
256 | - } | |
257 | -} | |
258 | - | |
259 | -bool DvppDec::sendVdecEos(aclvdecChannelDesc *vdecChannelDesc){ | |
260 | - // create stream desc | |
261 | - acldvppStreamDesc *streamInputDesc = acldvppCreateStreamDesc(); | |
262 | - if (streamInputDesc == nullptr) { | |
263 | - LOG_ERROR("[{}]- fail to create input stream desc", m_dec_name); | |
264 | - return false; | |
265 | - } | |
266 | - aclError ret = acldvppSetStreamDescEos(streamInputDesc, 1); | |
267 | - if (ret != ACL_SUCCESS) { | |
268 | - LOG_ERROR("[{}]- fail to set eos for stream desc, errorCode = {}", m_dec_name, static_cast<int32_t>(ret)); | |
269 | - (void)acldvppDestroyStreamDesc(streamInputDesc); | |
270 | - return false; | |
271 | - } | |
272 | - | |
273 | - // send vdec eos frame. when all vdec callback are completed, aclvdecSendFrame can be returned. | |
274 | - LOG_INFO("[{}]- send eos", m_dec_name); | |
275 | - ret = aclvdecSendFrame(vdecChannelDesc, streamInputDesc, nullptr, nullptr, nullptr); | |
276 | - (void)acldvppDestroyStreamDesc(streamInputDesc); | |
277 | - if (ret != ACL_SUCCESS) { | |
278 | - LOG_ERROR("[{}]- fail to send eos frame, ret={}", m_dec_name, ret); | |
279 | - return false; | |
280 | - } | |
281 | - | |
282 | - return true; | |
283 | -} | |
284 | - | |
285 | -void DvppDec::releaseResource(){ | |
286 | - for(int i = 0; i < m_vec_vdec.size(); i++){ | |
287 | - if(m_vec_vdec[i] != nullptr){ | |
288 | - acldvppFree(m_vec_vdec[i]); | |
289 | - m_vec_vdec[i] = nullptr; | |
290 | - } | |
291 | - } | |
292 | - m_vec_vdec.clear(); | |
293 | - | |
294 | - DvppSourceManager* pSrcMgr = DvppSourceManager::getInstance(); | |
295 | - pSrcMgr->releaseChannel(m_dvpp_deviceId, m_dvpp_channel); | |
296 | -} | |
297 | - | |
298 | -void DvppDec::decode_thread(){ | |
299 | - | |
300 | - long startTime = UtilTools::get_cur_time_ms(); | |
301 | - | |
302 | - int ret = -1; | |
303 | - | |
304 | - // // dvpp解码参数 | |
305 | - // CHECK_AND_RETURN_NOVALUE(aclrtSetCurrentContext(m_context), "aclrtSetCurrentContext failed"); | |
306 | - | |
307 | - m_bExitReportThd = false; | |
308 | - pthread_t report_thread; | |
309 | - ret = pthread_create(&report_thread, nullptr, ReportThd, (void *)this); | |
310 | - if(ret != 0){ | |
311 | - LOG_ERROR("[{}]- pthread_create failed", m_dec_name); | |
312 | - return; | |
313 | - } | |
314 | - | |
315 | - aclrtSetDevice(m_dvpp_deviceId); | |
316 | - aclrtContext ctx; | |
317 | - ret = aclrtCreateContext(&ctx, m_dvpp_deviceId); | |
318 | - if (ret != ACL_ERROR_NONE) { | |
319 | - // cout << "aclrtCreateContext failed " << endl; | |
320 | - LOG_ERROR("aclrtCreateContext failed !"); | |
321 | - return ; | |
322 | - } | |
323 | - | |
324 | - // 创建aclvdecChannelDesc类型的数据 | |
325 | - aclvdecChannelDesc *vdecChannelDesc = aclvdecCreateChannelDesc(); | |
326 | - if (vdecChannelDesc == nullptr) { | |
327 | - LOG_ERROR("[{}]- aclvdecCreateChannelDesc failed", m_dec_name); | |
328 | - return; | |
329 | - } | |
330 | - do{ | |
331 | - // 创建 channel dec结构体 | |
332 | - // 通道ID在dvpp层面为0~31 | |
333 | - CHECK_AND_BREAK(aclvdecSetChannelDescChannelId(vdecChannelDesc, m_dvpp_channel), "aclvdecSetChannelDescChannelId failed"); | |
334 | - CHECK_AND_BREAK(aclvdecSetChannelDescThreadId(vdecChannelDesc, report_thread), "aclvdecSetChannelDescThreadId failed"); | |
335 | - CHECK_AND_BREAK(aclvdecSetChannelDescCallback(vdecChannelDesc, VdecCallback), "aclvdecSetChannelDescCallback failed"); | |
336 | - CHECK_AND_BREAK(aclvdecSetChannelDescEnType(vdecChannelDesc, enType), "aclvdecSetChannelDescEnType failed"); | |
337 | - CHECK_AND_BREAK(aclvdecSetChannelDescOutPicFormat(vdecChannelDesc, PIXEL_FORMAT_YUV_SEMIPLANAR_420), "aclvdecSetChannelDescOutPicFormat failed"); | |
338 | - CHECK_AND_BREAK(aclvdecCreateChannel(vdecChannelDesc), "aclvdecCreateChannel failed"); | |
339 | - | |
340 | - uint64_t frame_count = 0; | |
341 | - bool bBreak = false; | |
342 | - while (m_bRunning) | |
343 | - { | |
344 | - if (m_bPause){ | |
345 | - std::this_thread::sleep_for(std::chrono::milliseconds(3)); | |
346 | - continue; | |
347 | - } | |
348 | - int ret = sentFrame(vdecChannelDesc, frame_count); | |
349 | - if(ret == 2){ | |
350 | - break; | |
351 | - bBreak = true; | |
352 | - }else if(ret == 1){ | |
353 | - continue; | |
354 | - } | |
355 | - | |
356 | - frame_count++; | |
357 | - } | |
358 | - | |
359 | - // 尽量保证数据全部解码完成 | |
360 | - int sum = 0; | |
361 | - if(!bBreak){ | |
362 | - aclrtSetDevice(m_dvpp_deviceId); | |
363 | - aclrtSetCurrentContext(ctx); | |
364 | - while(!m_pktQueueptr->isEmpty()){ | |
365 | - int ret = sentFrame(vdecChannelDesc, frame_count); | |
366 | - if(ret == 2){ | |
367 | - break; | |
368 | - } | |
369 | - std::this_thread::sleep_for(std::chrono::milliseconds(3)); | |
370 | - sum++; | |
371 | - if(sum > 40){ | |
372 | - // 避免卡死 | |
373 | - break; | |
374 | - } | |
375 | - } | |
376 | - } | |
377 | - | |
378 | - sendVdecEos(vdecChannelDesc); | |
379 | - | |
380 | - CHECK_NOT_RETURN(aclvdecDestroyChannel(vdecChannelDesc), "aclvdecDestroyChannel failed"); | |
381 | - }while(0); | |
382 | - | |
383 | - CHECK_NOT_RETURN(aclvdecDestroyChannelDesc(vdecChannelDesc), "aclvdecDestroyChannelDesc failed"); | |
384 | - | |
385 | - // report_thread 需后于destroy退出 | |
386 | - m_bRunning = false; | |
387 | - m_bExitReportThd = true; | |
388 | - CHECK_NOT_RETURN(pthread_join(report_thread, nullptr), "pthread_join failed"); | |
389 | - | |
390 | - releaseResource(); | |
391 | - LOG_INFO("[{}]- decode thread exit.", m_dec_name); | |
392 | -} | |
393 | - | |
394 | -int DvppDec::sentFrame(aclvdecChannelDesc *vdecChannelDesc, uint64_t frame_count){ | |
395 | - | |
396 | - AVPacket * pkt = m_pktQueueptr->getHead(); | |
397 | - if(pkt == nullptr){ | |
398 | - std::this_thread::sleep_for(std::chrono::milliseconds(10)); | |
399 | - return 1; | |
400 | - } | |
401 | - // 解码 | |
402 | - void *vdecInputbuf = m_vdecQueue.getTail(); | |
403 | - if(vdecInputbuf == nullptr){ | |
404 | - std::this_thread::sleep_for(std::chrono::milliseconds(3)); | |
405 | - return 1; | |
406 | - } | |
407 | - | |
408 | - int ret = aclrtMemcpy(vdecInputbuf, pkt->size, pkt->data, pkt->size, ACL_MEMCPY_HOST_TO_DEVICE); | |
409 | - if(ACL_ERROR_NONE != ret){ | |
410 | - LOG_ERROR("[{}]- aclrtMemcpy failed", m_dec_name); | |
411 | - return 2; | |
412 | - } | |
413 | - | |
414 | - void *vdecOutputBuf = nullptr; | |
415 | - ret = acldvppMalloc((void **)&vdecOutputBuf, m_vdec_out_size); | |
416 | - if(ret != ACL_ERROR_NONE){ | |
417 | - LOG_ERROR("[{}]- acldvppMalloc failed", m_dec_name); | |
418 | - return 2; | |
419 | - } | |
420 | - | |
421 | - acldvppStreamDesc *input_stream_desc = nullptr; | |
422 | - acldvppPicDesc *output_pic_desc = nullptr; | |
423 | - do{ | |
424 | - input_stream_desc = acldvppCreateStreamDesc(); | |
425 | - if (input_stream_desc == nullptr) { | |
426 | - LOG_ERROR("[{}]- acldvppCreateStreamDesc failed", m_dec_name); | |
427 | - break; | |
428 | - } | |
429 | - output_pic_desc = acldvppCreatePicDesc(); | |
430 | - if (output_pic_desc == nullptr) { | |
431 | - LOG_ERROR("[{}]- acldvppCreatePicDesc failed", m_dec_name); | |
432 | - break; | |
433 | - } | |
434 | - CHECK_AND_BREAK(acldvppSetStreamDescData(input_stream_desc, vdecInputbuf), "acldvppSetStreamDescData failed"); | |
435 | - CHECK_AND_BREAK(acldvppSetStreamDescSize(input_stream_desc, pkt->size), "acldvppSetStreamDescSize failed"); | |
436 | - CHECK_AND_BREAK(acldvppSetPicDescData(output_pic_desc, vdecOutputBuf), "acldvppSetPicDescData failed"); | |
437 | - CHECK_AND_BREAK(acldvppSetPicDescSize(output_pic_desc, m_vdec_out_size), "acldvppSetPicDescSize failed"); | |
438 | - | |
439 | - Vdec_CallBack_UserData *user_data = NULL; | |
440 | - user_data = new Vdec_CallBack_UserData; | |
441 | - user_data->frameId = frame_count; | |
442 | - // user_data->startTime = startTime; | |
443 | - user_data->sendTime = UtilTools::get_cur_time_ms(); | |
444 | - user_data->self = this; | |
445 | - ret = aclvdecSendFrame(vdecChannelDesc, input_stream_desc, output_pic_desc, nullptr, reinterpret_cast<void *>(user_data)); | |
446 | - av_packet_unref(pkt); | |
447 | - m_pktQueueptr->addHead(); | |
448 | - if(ret != ACL_ERROR_NONE){ | |
449 | - delete user_data; | |
450 | - user_data = nullptr; | |
451 | - LOG_ERROR("[{}]- aclvdecSendFrame failed", m_dec_name); | |
452 | - break; | |
453 | - } | |
454 | - | |
455 | - m_vdecQueue.addTail(); | |
456 | - | |
457 | - return 0; | |
458 | - }while (0); | |
459 | - | |
460 | - // 报错情形 | |
461 | - if(input_stream_desc){ | |
462 | - CHECK_NOT_RETURN(acldvppDestroyStreamDesc(input_stream_desc), "acldvppDestroyStreamDesc failed"); | |
463 | - } | |
464 | - if(output_pic_desc){ | |
465 | - CHECK_NOT_RETURN(acldvppDestroyPicDesc(output_pic_desc), "acldvppDestroyPicDesc failed"); | |
466 | - } | |
467 | - | |
468 | - if (vdecOutputBuf){ | |
469 | - acldvppFree(vdecOutputBuf); | |
470 | - vdecOutputBuf = nullptr; | |
471 | - } | |
472 | - | |
473 | - return 1; | |
474 | -} | |
475 | - | |
476 | - | |
477 | -void DvppDec::setPostDecArg(const void* postDecArg){ | |
478 | - m_postDecArg = postDecArg; | |
479 | -} | |
480 | - | |
481 | -void DvppDec::pause(){ | |
482 | - m_bPause = true; | |
483 | -} | |
484 | - | |
485 | -void DvppDec::resume(){ | |
486 | - m_bPause = false; | |
487 | -} | |
488 | - | |
489 | -DeviceMemory* DvppDec::snapshot(){ | |
490 | - // 开始抓拍 | |
491 | - m_bSnapShoting = true; | |
492 | - | |
493 | - std::unique_lock<std::mutex> locker(m_cached_mutex); | |
494 | - while (m_cached_mem == nullptr) | |
495 | - m_cached_cond.wait(locker); // Unlock mutex and wait to be notified | |
496 | - locker.unlock(); | |
497 | - | |
498 | - DeviceMemory* mem = m_cached_mem; | |
499 | - m_cached_mem = nullptr; | |
500 | - | |
501 | - return mem; | |
502 | -} | |
503 | 0 | \ No newline at end of file |
src/decoder/dvpp/DvppDec.h deleted
1 | -#include<string> | |
2 | -#include <pthread.h> | |
3 | - | |
4 | -#include "dvpp_headers.h" | |
5 | -#include "depend_headers.h" | |
6 | -#include "user_mem.h" | |
7 | -#include "CircularQueue.hpp" | |
8 | -#include "VpcPicConverter.h" | |
9 | -#include "FFReceiver.h" | |
10 | - | |
11 | -#include <queue> | |
12 | -#include <mutex> | |
13 | -#include <condition_variable> | |
14 | - | |
15 | -using namespace std; | |
16 | - | |
17 | -// #define TEST_DECODER | |
18 | - | |
19 | -struct DvppDecConfig{ | |
20 | - string dec_name; | |
21 | - POST_DECODE_CALLBACK post_decoded_cbk; // 解码数据回调接口 | |
22 | - string dev_id; // gpu id | |
23 | - bool force_tcp{true}; // 是否指定使用tcp连接 | |
24 | - int skip_frame{1}; // 跳帧数 | |
25 | - int codec_id; // 0 : h264 1:h265 | |
26 | - int profile; | |
27 | - CircularQueue<AVPacket*> *pktQueueptr; | |
28 | - | |
29 | - int width; | |
30 | - int height; | |
31 | -}; | |
32 | - | |
33 | - | |
34 | -class DvppDec { | |
35 | -public: | |
36 | - DvppDec(); | |
37 | - ~DvppDec(); | |
38 | - bool init_vdpp(DvppDecConfig cfg); | |
39 | - void setPostDecArg(const void* postDecArg); | |
40 | - bool start(); | |
41 | - void close(); | |
42 | - void pause(); | |
43 | - void resume(); | |
44 | - DeviceMemory* snapshot(); | |
45 | - | |
46 | -public: | |
47 | - void doProcessReport(); | |
48 | - void doVdppVdecCallBack(acldvppStreamDesc *input, acldvppPicDesc *output); | |
49 | - | |
50 | -private: | |
51 | - void decode_thread(); | |
52 | - void releaseResource(); | |
53 | - bool sendVdecEos(aclvdecChannelDesc *vdecChannelDesc); | |
54 | - int sentFrame(aclvdecChannelDesc *vdecChannelDesc, uint64_t frame_count); | |
55 | - | |
56 | -private: | |
57 | - | |
58 | - bool m_bRunning{false}; | |
59 | - bool m_bPause{false}; | |
60 | - bool m_bExitReportThd{false}; | |
61 | - | |
62 | - int m_dvpp_deviceId {-1}; | |
63 | - int m_dvpp_channel {-1}; | |
64 | - aclrtContext m_context; | |
65 | - acldvppStreamFormat enType; | |
66 | - | |
67 | - pthread_t m_decode_thread; | |
68 | - | |
69 | - DvppDecConfig m_cfg; | |
70 | - string m_dec_name; | |
71 | - | |
72 | - vector<void*> m_vec_vdec; | |
73 | - CircularQueue<void *> m_vdecQueue; | |
74 | - CircularQueue<AVPacket *> *m_pktQueueptr; | |
75 | - | |
76 | - const void * m_postDecArg; | |
77 | - POST_DECODE_CALLBACK post_decoded_cbk; | |
78 | - | |
79 | - VpcPicConverter picConverter; | |
80 | - | |
81 | - int m_vdec_out_size {-1}; | |
82 | - | |
83 | - bool m_bSnapShoting{false}; | |
84 | - DvppDataMemory* m_cached_mem; | |
85 | - mutex m_cached_mutex; | |
86 | - condition_variable m_cached_cond; | |
87 | - | |
88 | -#ifdef TEST_DECODER | |
89 | - void *vdecHostAddr = nullptr; | |
90 | - int count_frame = 0; | |
91 | -#endif | |
92 | - | |
93 | -}; | |
94 | 0 | \ No newline at end of file |
src/decoder/dvpp/DvppDecoder.cpp
1 | 1 | #include "DvppDecoder.h" |
2 | +#include "DvppSourceManager.h" | |
2 | 3 | |
3 | -void receiver_finish_cbk(const void* userPtr){ | |
4 | - if(userPtr != nullptr){ | |
5 | - DvppDecoder* self = (DvppDecoder*)userPtr; | |
6 | - self->taskFinishing(); | |
4 | + | |
5 | +struct Vdec_CallBack_UserData { | |
6 | + uint64_t frameId; | |
7 | + long startTime; | |
8 | + long sendTime; | |
9 | + // void* vdecOutputBuf; | |
10 | + DvppDecoder* self; | |
11 | + Vdec_CallBack_UserData() { | |
12 | + frameId = 0; | |
7 | 13 | } |
8 | -} | |
14 | +}; | |
9 | 15 | |
10 | 16 | DvppDecoder::DvppDecoder(){ |
11 | - m_pktQueueptr = new CircularQueue<AVPacket *>(); | |
17 | + m_read_thread = 0; | |
18 | + m_decode_thread = 0; | |
19 | + m_cached_mem = nullptr; | |
20 | + | |
21 | + fmt_ctx = nullptr; | |
22 | + m_bRunning = false; | |
23 | + | |
24 | + stream = nullptr; | |
25 | + video_index = -1; | |
26 | + pix_fmt = AV_PIX_FMT_NONE; | |
27 | + m_dec_name = ""; | |
28 | + | |
29 | + m_bPause = false; | |
30 | + m_bReal = true; | |
31 | + | |
32 | + m_bFinished = false; | |
33 | + m_dec_keyframe = false; | |
34 | + m_fps = 0.0; | |
35 | + | |
36 | + m_bSnapShoting = false; | |
12 | 37 | } |
13 | 38 | |
14 | 39 | DvppDecoder::~DvppDecoder(){ |
15 | - delete m_pktQueueptr; | |
16 | - m_pktQueueptr = nullptr; | |
17 | 40 | } |
18 | 41 | |
19 | 42 | bool DvppDecoder::init(FFDecConfig cfg){ |
20 | 43 | |
21 | 44 | m_dec_name = cfg.dec_name; |
22 | - | |
23 | - ReceiverConfig receiver_config; | |
24 | - receiver_config.uri = cfg.uri.c_str(); | |
25 | - receiver_config.dec_name = cfg.dec_name; | |
26 | - receiver_config.force_tcp = cfg.force_tcp; | |
27 | - receiver_config.pktQueueptr = m_pktQueueptr; | |
28 | - receiver_config.receiver_finished_cbk = receiver_finish_cbk; | |
29 | - AVCodecContext* avctx = m_receiver.init_FFmpeg(receiver_config); | |
45 | + | |
46 | + AVCodecContext* avctx = init_FFmpeg(cfg); | |
30 | 47 | if(avctx == nullptr){ |
31 | 48 | return false; |
32 | 49 | } |
33 | - m_receiver.setFinishCbkArg(this); | |
34 | 50 | |
35 | - DvppDecConfig dec_cfg; | |
36 | - if(avctx->codec_id == AV_CODEC_ID_H264){ | |
37 | - dec_cfg.codec_id = 0; | |
38 | - }else if(avctx->codec_id == AV_CODEC_ID_HEVC){ | |
39 | - dec_cfg.codec_id = 1; | |
40 | - }else { | |
41 | - return false; | |
42 | - } | |
43 | - dec_cfg.dec_name = cfg.dec_name; | |
44 | - dec_cfg.post_decoded_cbk = cfg.post_decoded_cbk; | |
45 | - dec_cfg.dev_id = cfg.gpuid; | |
46 | - dec_cfg.force_tcp = cfg.force_tcp; | |
47 | - dec_cfg.skip_frame = cfg.skip_frame; | |
48 | - dec_cfg.profile = avctx->profile; | |
49 | - dec_cfg.pktQueueptr = m_pktQueueptr; | |
50 | - dec_cfg.width = avctx->width; | |
51 | - dec_cfg.height = avctx->height; | |
52 | - bool bRet = m_decoder.init_vdpp(dec_cfg); | |
51 | + bool bRet = init_vdpp(cfg, avctx); | |
53 | 52 | if(!bRet){ |
54 | 53 | return false; |
55 | 54 | } |
... | ... | @@ -63,22 +62,189 @@ bool DvppDecoder::init(FFDecConfig cfg){ |
63 | 62 | return true; |
64 | 63 | } |
65 | 64 | |
65 | +AVCodecContext* DvppDecoder::init_FFmpeg(FFDecConfig config){ | |
66 | + | |
67 | +#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 9, 100) | |
68 | + av_register_all(); | |
69 | +#endif | |
70 | +#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 10, 100) | |
71 | + avcodec_register_all(); | |
72 | +#endif | |
73 | + | |
74 | + avformat_network_init(); | |
75 | + | |
76 | + const char* uri = config.uri.c_str(); | |
77 | + fstream infile(uri); | |
78 | + if (infile.is_open()){ | |
79 | + m_bReal = false; | |
80 | + infile.close(); | |
81 | + } else { | |
82 | + m_bReal = true; | |
83 | + } | |
84 | + | |
85 | + // 打开输入视频文件 | |
86 | + AVDictionary *options = nullptr; | |
87 | + av_dict_set( &options, "bufsize", "655360", 0 ); | |
88 | + av_dict_set( &options, "rtsp_transport", config.force_tcp ? "tcp" : "udp", 0 ); | |
89 | + av_dict_set( &options, "stimeout", "30000000", 0 ); // 单位为 百万分之一秒 | |
90 | + | |
91 | + const char* input_file = uri; | |
92 | + | |
93 | + do{ | |
94 | + fmt_ctx = avformat_alloc_context(); | |
95 | + if (avformat_open_input(&fmt_ctx, input_file, nullptr, &options) != 0) { | |
96 | + LOG_ERROR("[{}]- Cannot open input file: {}", m_dec_name, input_file); | |
97 | + break; | |
98 | + } | |
99 | + av_dump_format(fmt_ctx, 0, input_file, 0); | |
100 | + | |
101 | + // 查找流信息 | |
102 | + if (avformat_find_stream_info(fmt_ctx, nullptr) < 0) { | |
103 | + LOG_ERROR("[{}]- Cannot find input stream information!", m_dec_name); | |
104 | + break; | |
105 | + } | |
106 | + | |
107 | + // 查找视频流信息 | |
108 | + AVCodec *decoder = nullptr; | |
109 | + video_index = av_find_best_stream(fmt_ctx, AVMEDIA_TYPE_VIDEO, -1, -1, &decoder, 0); | |
110 | + if (video_index < 0) { | |
111 | + LOG_ERROR("[{}]- Cannot find a video stream in the input file!", m_dec_name); | |
112 | + break; | |
113 | + } | |
114 | + AVCodec *vcodec = avcodec_find_decoder(decoder->id); | |
115 | + | |
116 | + avctx = avcodec_alloc_context3(vcodec); | |
117 | + if(avctx == nullptr){ | |
118 | + LOG_ERROR("[{}]- alloc AVCodecContext failed!", m_dec_name); | |
119 | + break; | |
120 | + } | |
121 | + | |
122 | + // 得到视频流对象 | |
123 | + AVStream* stream = fmt_ctx->streams[video_index]; | |
124 | + AVCodecParameters *codecpar = stream->codecpar; | |
125 | + if (avcodec_parameters_to_context(avctx, codecpar) < 0) | |
126 | + break; | |
127 | + | |
128 | + const AVBitStreamFilter * filter = nullptr; | |
129 | + if(codecpar->codec_id == AV_CODEC_ID_H264){ | |
130 | + filter = av_bsf_get_by_name("h264_mp4toannexb"); | |
131 | + }else if(codecpar->codec_id == AV_CODEC_ID_HEVC){ | |
132 | + filter = av_bsf_get_by_name("hevc_mp4toannexb"); | |
133 | + }else { | |
134 | + LOG_ERROR("[{}]- codec_id is not supported!", m_dec_name); | |
135 | + break; | |
136 | + } | |
137 | + | |
138 | + int ret = av_bsf_alloc(filter, &h264bsfc); | |
139 | + if (ret < 0){ | |
140 | + break; | |
141 | + } | |
142 | + | |
143 | + avcodec_parameters_copy(h264bsfc->par_in, codecpar); | |
144 | + av_bsf_init(h264bsfc); | |
145 | + | |
146 | + frame_width = codecpar->width; | |
147 | + frame_height = codecpar->height; | |
148 | + pix_fmt = (AVPixelFormat)codecpar->format; | |
149 | + m_fps = av_q2d(stream ->avg_frame_rate); | |
150 | + | |
151 | + LOG_INFO("[{}]- init ffmpeg success! input:{} frame_width:{} frame_height:{} fps:{} ", m_dec_name, input_file, frame_width, frame_height, m_fps); | |
152 | + | |
153 | + return avctx; | |
154 | + }while(0); | |
155 | + | |
156 | + release_ffmpeg(); | |
157 | + | |
158 | + LOG_ERROR("[{}]- init ffmpeg failed ! input:{} ", m_dec_name, input_file); | |
159 | + | |
160 | + return nullptr; | |
161 | +} | |
162 | + | |
163 | + bool DvppDecoder::init_vdpp(FFDecConfig cfg, AVCodecContext* avctx) { | |
164 | + | |
165 | + LOG_INFO("[{}]- Init device start...", m_dec_name); | |
166 | + | |
167 | + m_dvpp_deviceId = atoi(cfg.gpuid.c_str()); | |
168 | + | |
169 | + if(avctx->codec_id == AV_CODEC_ID_H264){ | |
170 | + // 66:Baseline,77:Main,>=100:High | |
171 | + if(avctx->profile == 77){ | |
172 | + enType = H264_MAIN_LEVEL; | |
173 | + }else if(avctx->profile < 77){ | |
174 | + enType = H264_BASELINE_LEVEL; | |
175 | + }else{ | |
176 | + enType = H264_HIGH_LEVEL; | |
177 | + } | |
178 | + }else if(avctx->codec_id == AV_CODEC_ID_HEVC){ | |
179 | + // h265只有main | |
180 | + enType = H265_MAIN_LEVEL; | |
181 | + }else { | |
182 | + LOG_ERROR("[{}]- codec_id is not supported!", m_dec_name); | |
183 | + return false; | |
184 | + } | |
185 | + | |
186 | + post_decoded_cbk = cfg.post_decoded_cbk; | |
187 | + | |
188 | + do{ | |
189 | + aclError ret = aclrtSetDevice(m_dvpp_deviceId); | |
190 | + if(ret != ACL_ERROR_NONE){ | |
191 | + LOG_ERROR("[{}]-aclrtSetDevice failed !", m_dec_name); | |
192 | + return false; | |
193 | + } | |
194 | + | |
195 | + ret = aclrtCreateContext(&m_context, m_dvpp_deviceId); | |
196 | + if (ret != ACL_ERROR_NONE) { | |
197 | + LOG_ERROR("[{}]-aclrtCreateContext failed !", m_dec_name); | |
198 | + return false; | |
199 | + } | |
200 | + | |
201 | + // DvppSourceManager 创建时包含 aclInit,析构时包含 aclFinalize | |
202 | + DvppSourceManager* pSrcMgr = DvppSourceManager::getInstance(); | |
203 | + m_dvpp_channel = pSrcMgr->getChannel(m_dvpp_deviceId); | |
204 | + if(m_dvpp_channel < 0){ | |
205 | + LOG_ERROR("[{}]-该设备channel已经用完了!", m_dec_name); | |
206 | + return false; | |
207 | + } | |
208 | + m_vdec_out_size = avctx->width * avctx->height * 3 / 2; | |
209 | + | |
210 | + LOG_INFO("[{}]- init vdpp success! device:{} channel:{}", m_dec_name, m_dvpp_deviceId, m_dvpp_channel); | |
211 | + return true; | |
212 | + }while(0); | |
213 | + | |
214 | + release_dvpp(); | |
215 | + | |
216 | + return false; | |
217 | +} | |
218 | + | |
66 | 219 | bool DvppDecoder::isSurport(FFDecConfig& cfg){ |
67 | 220 | return true; |
68 | 221 | } |
69 | 222 | |
70 | 223 | bool DvppDecoder::start(){ |
71 | - m_receiver.start(); | |
72 | - m_decoder.start(); | |
73 | - return true; | |
224 | + m_bRunning = true; | |
225 | + | |
226 | + pthread_create(&m_read_thread,0, | |
227 | + [](void* arg) | |
228 | + { | |
229 | + DvppDecoder* a=(DvppDecoder*)arg; | |
230 | + a->read_thread(); | |
231 | + return (void*)0; | |
232 | + } | |
233 | + ,this); | |
234 | + | |
235 | + return true; | |
74 | 236 | } |
75 | 237 | |
76 | 238 | void DvppDecoder::close(){ |
77 | - m_receiver.close(); | |
239 | + m_bRunning=false; | |
240 | + | |
241 | + if(m_read_thread != 0){ | |
242 | + pthread_join(m_read_thread,0); | |
243 | + } | |
78 | 244 | } |
79 | 245 | |
80 | 246 | void DvppDecoder::setPostDecArg(const void* postDecArg){ |
81 | - m_decoder.setPostDecArg(postDecArg); | |
247 | + m_postDecArg = postDecArg; | |
82 | 248 | } |
83 | 249 | |
84 | 250 | void DvppDecoder::setFinishedDecArg(const void* finishedDecArg){ |
... | ... | @@ -86,19 +252,19 @@ void DvppDecoder::setFinishedDecArg(const void* finishedDecArg){ |
86 | 252 | } |
87 | 253 | |
88 | 254 | void DvppDecoder::pause(){ |
89 | - m_receiver.pause(); | |
255 | + m_bPause = true; | |
90 | 256 | } |
91 | 257 | |
92 | 258 | void DvppDecoder::resume(){ |
93 | - m_receiver.resume(); | |
259 | + m_bPause = false; | |
94 | 260 | } |
95 | 261 | |
96 | 262 | void DvppDecoder::setDecKeyframe(bool bKeyframe){ |
97 | - m_receiver.setDecKeyframe(bKeyframe); | |
263 | + m_dec_keyframe = bKeyframe; | |
98 | 264 | } |
99 | 265 | |
100 | 266 | bool DvppDecoder::isRunning(){ |
101 | - return m_receiver.isRunning(); | |
267 | + return m_bRunning; | |
102 | 268 | } |
103 | 269 | |
104 | 270 | bool DvppDecoder::isFinished(){ |
... | ... | @@ -106,32 +272,597 @@ bool DvppDecoder::isFinished(){ |
106 | 272 | } |
107 | 273 | |
108 | 274 | bool DvppDecoder::isPausing(){ |
109 | - return m_receiver.isPausing(); | |
275 | + return m_bPause; | |
110 | 276 | } |
111 | 277 | |
112 | 278 | bool DvppDecoder::getResolution(int &width, int &height){ |
113 | - return m_receiver.getResolution(width, height); | |
279 | + width = frame_width; | |
280 | + height = frame_height; | |
281 | + return true; | |
114 | 282 | } |
115 | 283 | |
116 | 284 | float DvppDecoder::fps(){ |
117 | - return m_receiver.fps(); | |
285 | + return m_fps; | |
118 | 286 | } |
119 | 287 | |
120 | 288 | DeviceMemory* DvppDecoder::snapshot(){ |
121 | 289 | // 注意内部有锁 |
122 | - return m_decoder.snapshot(); | |
290 | + // 开始抓拍 | |
291 | + m_bSnapShoting = true; | |
292 | + | |
293 | + std::unique_lock<std::mutex> locker(m_cached_mutex); | |
294 | + while (m_cached_mem == nullptr) | |
295 | + m_cached_cond.wait_for(locker, std::chrono::milliseconds(400)); // Unlock mutex and wait to be notified | |
296 | + locker.unlock(); | |
297 | + | |
298 | + DeviceMemory* mem = m_cached_mem; | |
299 | + m_cached_mem = nullptr; | |
300 | + | |
301 | + return mem; | |
123 | 302 | } |
124 | 303 | |
125 | 304 | int DvppDecoder::getCachedQueueLength(){ |
126 | 305 | return 0; |
127 | 306 | } |
128 | 307 | |
129 | -void DvppDecoder::taskFinishing(){ | |
130 | - // receiver 中读取线程结束时执行 | |
131 | - m_decoder.close(); | |
308 | +void DvppDecoder::release_ffmpeg() { | |
309 | + m_dec_keyframe = false; | |
310 | + if(h264bsfc){ | |
311 | + av_bsf_free(&h264bsfc); | |
312 | + h264bsfc = nullptr; | |
313 | + } | |
314 | + if (fmt_ctx){ | |
315 | + avformat_close_input(&fmt_ctx); | |
316 | + fmt_ctx = nullptr; | |
317 | + } | |
318 | + if(avctx){ | |
319 | + avcodec_free_context(&avctx); | |
320 | + avctx = nullptr; | |
321 | + } | |
322 | +} | |
323 | + | |
324 | +void DvppDecoder::read_thread() { | |
325 | + | |
326 | + int frame_count = 0; | |
327 | + int ret = -1; | |
328 | + | |
329 | + pthread_create(&m_decode_thread,0, | |
330 | + [](void* arg) | |
331 | + { | |
332 | + DvppDecoder* a=(DvppDecoder*)arg; | |
333 | + a->decode_thread(); | |
334 | + return (void*)0; | |
335 | + } | |
336 | + ,this); | |
337 | + | |
338 | + AVPacket* pkt = nullptr; | |
339 | + while (m_bRunning){ | |
340 | + | |
341 | + if (!m_bReal){ | |
342 | + if (m_bPause){ | |
343 | + std::this_thread::sleep_for(std::chrono::milliseconds(3)); | |
344 | + continue; | |
345 | + } | |
346 | + } | |
347 | + | |
348 | + m_pktQueue_mutex.lock(); | |
349 | + if(m_pktQueue.size() > 10){ | |
350 | + m_pktQueue_mutex.unlock(); | |
351 | + std::this_thread::sleep_for(std::chrono::milliseconds(5)); | |
352 | + continue; | |
353 | + } | |
354 | + m_pktQueue_mutex.unlock(); | |
355 | + | |
356 | + pkt = av_packet_alloc(); | |
357 | + av_init_packet( pkt ); | |
358 | + | |
359 | + int result = av_read_frame(fmt_ctx, pkt); | |
360 | + if (result == AVERROR_EOF || result < 0){ | |
361 | + av_packet_free(&pkt); | |
362 | + pkt = nullptr; | |
363 | + LOG_ERROR("[{}]- Failed to read frame!", m_dec_name); | |
364 | + break; | |
365 | + } | |
366 | + | |
367 | + if (m_dec_keyframe && !(pkt->flags & AV_PKT_FLAG_KEY)) { | |
368 | + av_packet_free(&pkt); | |
369 | + pkt = nullptr; | |
370 | + continue; | |
371 | + } | |
372 | + | |
373 | + if (video_index == pkt->stream_index){ | |
374 | + | |
375 | + ret = av_bsf_send_packet(h264bsfc, pkt); | |
376 | + if(ret < 0) { | |
377 | + LOG_ERROR("[{}]- av_bsf_send_packet error!", m_dec_name); | |
378 | + av_packet_free(&pkt); | |
379 | + pkt = nullptr; | |
380 | + continue; | |
381 | + } | |
382 | + | |
383 | + bool bPushed = false; | |
384 | + while ((ret = av_bsf_receive_packet(h264bsfc, pkt)) == 0) { | |
385 | + if(pkt->size > g_pkt_size){ | |
386 | + LOG_ERROR("[{}]- pkt size 大于最大预设值!", m_dec_name); | |
387 | + break; | |
388 | + } | |
389 | + | |
390 | + if(!m_bRunning){ | |
391 | + break; | |
392 | + } | |
393 | + | |
394 | + m_pktQueue_mutex.lock(); | |
395 | + m_pktQueue.push(pkt); | |
396 | + m_pktQueue_mutex.unlock(); | |
397 | + | |
398 | + bPushed = true; | |
399 | + frame_count++; | |
400 | + } | |
401 | + | |
402 | + if(!bPushed){ | |
403 | + av_packet_free(&pkt); | |
404 | + pkt = nullptr; | |
405 | + } | |
406 | + } else { | |
407 | + // 音频等其他分量的情形 | |
408 | + av_packet_free(&pkt); | |
409 | + pkt = nullptr; | |
410 | + } | |
411 | + } | |
412 | + | |
413 | + m_bRunning=false; | |
414 | + | |
415 | + if(m_decode_thread != 0){ | |
416 | + pthread_join(m_decode_thread,0); | |
417 | + } | |
418 | + | |
419 | + m_pktQueue_mutex.lock(); | |
420 | + while(m_pktQueue.size() > 0){ | |
421 | + pkt = m_pktQueue.front(); | |
422 | + av_packet_free(&pkt); | |
423 | + pkt = nullptr; | |
424 | + m_pktQueue.pop(); | |
425 | + } | |
426 | + m_pktQueue_mutex.unlock(); | |
427 | + | |
132 | 428 | decode_finished_cbk(m_finishedDecArg); |
133 | 429 | |
134 | - m_bFinished = true; | |
430 | + LOG_INFO("[{}]- read thread exit.", m_dec_name); | |
431 | + m_bFinished = true; | |
432 | +} | |
433 | + | |
434 | +static void *ReportThd(void *arg) | |
435 | +{ | |
436 | + DvppDecoder *self = (DvppDecoder *)arg; | |
437 | + if(nullptr != self){ | |
438 | + self->doProcessReport(); | |
439 | + } | |
440 | + return (void *)0; | |
441 | +} | |
442 | + | |
443 | +void DvppDecoder::doProcessReport(){ | |
444 | + | |
445 | + aclError ret = aclrtSetDevice(m_dvpp_deviceId); | |
446 | + if(ret != ACL_ERROR_NONE){ | |
447 | + // cout << "aclrtSetDevice failed" << endl; | |
448 | + LOG_ERROR("aclrtSetDevice failed !"); | |
449 | + return ; | |
450 | + } | |
451 | + | |
452 | + aclrtContext ctx; | |
453 | + ret = aclrtCreateContext(&ctx, m_dvpp_deviceId); | |
454 | + if (ret != ACL_ERROR_NONE) { | |
455 | + // cout << "aclrtCreateContext failed " << endl; | |
456 | + LOG_ERROR("aclrtCreateContext failed !"); | |
457 | + return ; | |
458 | + } | |
459 | + | |
460 | + CHECK_AND_RETURN_NOVALUE(aclrtSetCurrentContext(ctx), "aclrtSetCurrentContext failed"); | |
461 | + // 阻塞等待vdec线程开始 | |
462 | + | |
463 | + while (!m_bExitReportThd) { | |
464 | + aclrtProcessReport(1000); | |
465 | + } | |
466 | + | |
467 | + ret = aclrtDestroyContext(ctx); | |
468 | + if(ret != ACL_ERROR_NONE){ | |
469 | + LOG_ERROR("aclrtDestroyContext failed !"); | |
470 | + } | |
471 | + LOG_INFO("doProcessReport exit."); | |
472 | +} | |
473 | + | |
474 | +static void VdecCallback(acldvppStreamDesc *input, acldvppPicDesc *output, void *pUserData) | |
475 | +{ | |
476 | + Vdec_CallBack_UserData *userData = (Vdec_CallBack_UserData *) pUserData; | |
477 | + if(nullptr != userData){ | |
478 | + DvppDecoder* self = userData->self; | |
479 | + if(self != nullptr){ | |
480 | + | |
481 | + self->doVdppVdecCallBack(input, output); | |
482 | + } | |
483 | + delete userData; | |
484 | + userData = nullptr; | |
485 | + } | |
486 | +} | |
487 | + | |
488 | +void DvppDecoder::doVdppVdecCallBack(acldvppStreamDesc *input, acldvppPicDesc *output){ | |
489 | + | |
490 | + m_vdecQueue_mutex.lock(); | |
491 | + if(m_vdecQueue.size() > 0){ | |
492 | + void* inputData = m_vdecQueue.front(); | |
493 | + acldvppFree(inputData); | |
494 | + inputData = nullptr; | |
495 | + m_vdecQueue.pop(); | |
496 | + } | |
497 | + m_vdecQueue_mutex.unlock(); | |
498 | + | |
499 | + | |
500 | + CHECK_AND_RETURN_NOVALUE(aclrtSetCurrentContext(m_context), "aclrtSetCurrentContext failed"); | |
501 | + | |
502 | + void *outputDataDev = acldvppGetPicDescData(output); | |
503 | + uint32_t outputSize = acldvppGetPicDescSize(output); | |
504 | + uint32_t width = acldvppGetPicDescWidth(output); | |
505 | + uint32_t width_stride = acldvppGetPicDescWidthStride(output); | |
506 | + uint32_t height = acldvppGetPicDescHeight(output); | |
507 | + uint32_t height_stride = acldvppGetPicDescHeightStride(output); | |
508 | + | |
509 | + do{ | |
510 | + int ret = acldvppGetPicDescRetCode(output); | |
511 | + if(ret != ACL_ERROR_NONE){ | |
512 | + LOG_ERROR("[{}]- decode result error, retCode:{} ", m_dec_name, ret); | |
513 | + acldvppFree(outputDataDev); | |
514 | + outputDataDev = nullptr; | |
515 | + break; | |
516 | + } | |
517 | + | |
518 | + if(width > 0 && height > 0 && outputSize > 0){ | |
519 | + DvppDataMemory* mem = new DvppDataMemory(width, width_stride, height, height_stride, outputSize, m_dec_name, to_string(m_dvpp_deviceId), false, (unsigned char *)outputDataDev); | |
520 | + if(mem){ | |
521 | + post_decoded_cbk(m_postDecArg, mem); | |
522 | + | |
523 | + if(m_bSnapShoting){ | |
524 | + // 缓存snapshot | |
525 | + std::unique_lock<std::mutex> locker(m_cached_mutex); | |
526 | + | |
527 | + m_cached_mem = new DvppDataMemory(-1, width, width_stride, height, height_stride, outputSize, m_dec_name, to_string(m_dvpp_deviceId), false); | |
528 | + if(m_cached_mem != nullptr){ | |
529 | + aclrtMemcpy(m_cached_mem->getMem(), outputSize, (unsigned char *)outputDataDev, outputSize, ACL_MEMCPY_DEVICE_TO_DEVICE); | |
530 | + } | |
531 | + | |
532 | + locker.unlock(); | |
533 | + m_cached_cond.notify_one(); | |
534 | + m_bSnapShoting = false; | |
535 | + } | |
536 | + } else { | |
537 | + LOG_ERROR("[{}]- DvppDataMemory 创建失败! ", m_dec_name, ret); | |
538 | + acldvppFree(outputDataDev); | |
539 | + outputDataDev = nullptr; | |
540 | + } | |
541 | + | |
542 | + } else { | |
543 | + LOG_WARN("[{}]- decode result error, width:{} width_stride:{} height:{} height_stride:{} size:{}", m_dec_name, width, width_stride, height, height_stride, outputSize); | |
544 | + acldvppFree(outputDataDev); | |
545 | + outputDataDev = nullptr; | |
546 | + } | |
547 | + | |
548 | + // DvppDataMemory* rgbMem = picConverter.convert2bgr(output, width, height, false); | |
549 | + // if(rgbMem != nullptr){ | |
550 | + // #ifdef TEST_DECODER | |
551 | + // // D2H | |
552 | + // if(vdecHostAddr == nullptr){ | |
553 | + // CHECK_NOT_RETURN(aclrtMallocHost(&vdecHostAddr, width * height * 3), "aclrtMallocHost failed"); | |
554 | + // } | |
555 | + // uint32_t data_size = rgbMem->getSize(); | |
556 | + // CHECK_AND_RETURN_NOVALUE(aclrtMemcpy(vdecHostAddr, data_size, rgbMem->getMem(), data_size, ACL_MEMCPY_DEVICE_TO_HOST), "D2H aclrtMemcpy failed"); | |
557 | + | |
558 | + // // 保存vdec结果 | |
559 | + // if(count_frame > 45 && count_frame < 50) | |
560 | + // { | |
561 | + // string file_name = "./yuv_pic/vdec_out_"+ m_dec_name +".rgb" ; | |
562 | + // FILE *outputFile = fopen(file_name.c_str(), "a"); | |
563 | + // if(outputFile){ | |
564 | + // fwrite(vdecHostAddr, data_size, sizeof(char), outputFile); | |
565 | + // fclose(outputFile); | |
566 | + // } | |
567 | + // } | |
568 | + // else if(count_frame > 50 && vdecHostAddr != nullptr){ | |
569 | + // CHECK_NOT_RETURN(aclrtFreeHost(vdecHostAddr), "aclrtFreeHost failed"); | |
570 | + // vdecHostAddr = nullptr; | |
571 | + // } | |
572 | + // count_frame++; | |
573 | + // #endif | |
574 | + // post_decoded_cbk(m_postDecArg, rgbMem); | |
575 | + // }else{ | |
576 | + // LOG_ERROR("[{}]- convert2bgr failed !", m_dec_name); | |
577 | + // } | |
578 | + }while(0); | |
579 | + | |
580 | + CHECK_AND_RETURN_NOVALUE(acldvppDestroyStreamDesc(input), "acldvppDestroyStreamDesc failed"); | |
581 | + CHECK_AND_RETURN_NOVALUE(acldvppDestroyPicDesc(output), "acldvppDestroyPicDesc failed"); | |
582 | +} | |
583 | + | |
584 | +void DvppDecoder::decode_thread(){ | |
585 | + | |
586 | + long startTime = UtilTools::get_cur_time_ms(); | |
587 | + | |
588 | + int ret = -1; | |
589 | + | |
590 | + m_bExitReportThd = false; | |
591 | + pthread_t report_thread; | |
592 | + ret = pthread_create(&report_thread, nullptr, ReportThd, (void *)this); | |
593 | + if(ret != 0){ | |
594 | + LOG_ERROR("[{}]- pthread_create failed", m_dec_name); | |
595 | + return; | |
596 | + } | |
597 | + | |
598 | + aclrtSetDevice(m_dvpp_deviceId); | |
599 | + aclrtContext ctx; | |
600 | + ret = aclrtCreateContext(&ctx, m_dvpp_deviceId); | |
601 | + if (ret != ACL_ERROR_NONE) { | |
602 | + // cout << "aclrtCreateContext failed " << endl; | |
603 | + LOG_ERROR("aclrtCreateContext failed !"); | |
604 | + return ; | |
605 | + } | |
606 | + | |
607 | + // 创建aclvdecChannelDesc类型的数据 | |
608 | + aclvdecChannelDesc *vdecChannelDesc = aclvdecCreateChannelDesc(); | |
609 | + if (vdecChannelDesc == nullptr) { | |
610 | + LOG_ERROR("[{}]- aclvdecCreateChannelDesc failed", m_dec_name); | |
611 | + return; | |
612 | + } | |
613 | + do{ | |
614 | + // 创建 channel dec结构体 | |
615 | + // 通道ID在dvpp层面为0~31 | |
616 | + CHECK_AND_BREAK(aclvdecSetChannelDescChannelId(vdecChannelDesc, m_dvpp_channel), "aclvdecSetChannelDescChannelId failed"); | |
617 | + CHECK_AND_BREAK(aclvdecSetChannelDescThreadId(vdecChannelDesc, report_thread), "aclvdecSetChannelDescThreadId failed"); | |
618 | + CHECK_AND_BREAK(aclvdecSetChannelDescCallback(vdecChannelDesc, VdecCallback), "aclvdecSetChannelDescCallback failed"); | |
619 | + CHECK_AND_BREAK(aclvdecSetChannelDescEnType(vdecChannelDesc, enType), "aclvdecSetChannelDescEnType failed"); | |
620 | + CHECK_AND_BREAK(aclvdecSetChannelDescOutPicFormat(vdecChannelDesc, PIXEL_FORMAT_YUV_SEMIPLANAR_420), "aclvdecSetChannelDescOutPicFormat failed"); | |
621 | + CHECK_AND_BREAK(aclvdecCreateChannel(vdecChannelDesc), "aclvdecCreateChannel failed"); | |
622 | + | |
623 | + uint64_t frame_count = 0; | |
624 | + bool bBreak = false; | |
625 | + while (m_bRunning) | |
626 | + { | |
627 | + if (m_bPause){ | |
628 | + std::this_thread::sleep_for(std::chrono::milliseconds(3)); | |
629 | + continue; | |
630 | + } | |
631 | + int ret = sentFrame(vdecChannelDesc, frame_count); | |
632 | + if(ret == 2){ | |
633 | + bBreak = true; | |
634 | + break; | |
635 | + }else if(ret == 1){ | |
636 | + continue; | |
637 | + } | |
638 | + | |
639 | + frame_count++; | |
640 | + } | |
641 | + | |
642 | + // 尽量保证数据全部解码完成 | |
643 | + int sum = 0; | |
644 | + if(!bBreak){ | |
645 | + aclrtSetDevice(m_dvpp_deviceId); | |
646 | + aclrtSetCurrentContext(ctx); | |
647 | + while(m_pktQueue.size() > 0){ | |
648 | + int ret = sentFrame(vdecChannelDesc, frame_count); | |
649 | + if(ret == 2){ | |
650 | + break; | |
651 | + } | |
652 | + std::this_thread::sleep_for(std::chrono::milliseconds(3)); | |
653 | + sum++; | |
654 | + if(sum > 40){ | |
655 | + // 避免卡死 | |
656 | + break; | |
657 | + } | |
658 | + } | |
659 | + } | |
660 | + | |
661 | + sendVdecEos(vdecChannelDesc); | |
662 | + | |
663 | + CHECK_NOT_RETURN(aclvdecDestroyChannel(vdecChannelDesc), "aclvdecDestroyChannel failed"); | |
664 | + }while(0); | |
665 | + | |
666 | + CHECK_NOT_RETURN(aclvdecDestroyChannelDesc(vdecChannelDesc), "aclvdecDestroyChannelDesc failed"); | |
667 | + | |
668 | + // report_thread 需后于destroy退出 | |
669 | + m_bRunning = false; | |
670 | + m_bExitReportThd = true; | |
671 | + CHECK_NOT_RETURN(pthread_join(report_thread, nullptr), "pthread_join failed"); | |
672 | + | |
673 | + // 最后清理一遍未解码的数据 | |
674 | + m_vdecQueue_mutex.lock(); | |
675 | + if(m_vdecQueue.size() > 0){ | |
676 | + void* inputData = m_vdecQueue.front(); | |
677 | + acldvppFree(inputData); | |
678 | + inputData = nullptr; | |
679 | + m_vdecQueue.pop(); | |
680 | + } | |
681 | + m_vdecQueue_mutex.unlock(); | |
682 | + | |
683 | + release_dvpp(); | |
684 | + | |
685 | + ret = aclrtDestroyContext(ctx); | |
686 | + if(ret != ACL_ERROR_NONE){ | |
687 | + LOG_ERROR("aclrtDestroyContext failed !"); | |
688 | + } | |
689 | + | |
690 | + LOG_INFO("[{}]- decode thread exit.", m_dec_name); | |
691 | +} | |
692 | + | |
693 | +#include <fstream> | |
694 | +#include <iostream> | |
695 | +#include <cstring> | |
135 | 696 | |
136 | - LOG_INFO("[{}]- task finished.", m_dec_name); | |
697 | +static int nRecoder = 0; | |
698 | + | |
699 | + | |
700 | + | |
701 | +int DvppDecoder::sentFrame(aclvdecChannelDesc *vdecChannelDesc, uint64_t frame_count){ | |
702 | + | |
703 | + // 此处需要判断 m_vdecQueue 队列长度,避免占用过多显存 | |
704 | + m_vdecQueue_mutex.lock(); | |
705 | + if(m_vdecQueue.size() > 20){ | |
706 | + m_vdecQueue_mutex.unlock(); | |
707 | + std::this_thread::sleep_for(std::chrono::milliseconds(2)); | |
708 | + return 1; | |
709 | + } | |
710 | + m_vdecQueue_mutex.unlock(); | |
711 | + | |
712 | + AVPacket * pkt = nullptr; | |
713 | + m_pktQueue_mutex.lock(); | |
714 | + if(m_pktQueue.size() <= 0){ | |
715 | + m_pktQueue_mutex.unlock(); | |
716 | + std::this_thread::sleep_for(std::chrono::milliseconds(10)); | |
717 | + return 1; | |
718 | + } | |
719 | + pkt = m_pktQueue.front(); | |
720 | + m_pktQueue.pop(); | |
721 | + m_pktQueue_mutex.unlock(); | |
722 | + | |
723 | + // 解码 | |
724 | + void *vdecInputbuf = nullptr; | |
725 | + int ret = acldvppMalloc((void **)&vdecInputbuf, g_pkt_size); | |
726 | + if(ACL_ERROR_NONE != ret){ | |
727 | + LOG_ERROR("[{}]- acldvppMalloc failed!, ret:{}", m_dec_name, ret); | |
728 | + av_packet_free(&pkt); | |
729 | + pkt = nullptr; | |
730 | + return 2; | |
731 | + } | |
732 | + | |
733 | + // std::ofstream outfile; | |
734 | + // string file_name = "./pkt/pkt"; | |
735 | + // file_name = file_name + to_string(nRecoder) + ".bin"; | |
736 | + // outfile.open(file_name.c_str(), std::ios::binary | std::ios::app); | |
737 | + // if (!outfile) { | |
738 | + // std::cerr << "Failed to open file!" << std::endl; | |
739 | + // return 2; | |
740 | + // } | |
741 | + | |
742 | + // outfile.write((const char*)pkt->data, pkt->size); | |
743 | + // outfile.close(); | |
744 | + | |
745 | + // nRecoder ++ ; | |
746 | + // if(nRecoder >= 1000){ | |
747 | + | |
748 | + // return 2; | |
749 | + // } | |
750 | + | |
751 | + | |
752 | + | |
753 | + ret = aclrtMemcpy(vdecInputbuf, pkt->size, pkt->data, pkt->size, ACL_MEMCPY_HOST_TO_DEVICE); | |
754 | + if(ACL_ERROR_NONE != ret){ | |
755 | + LOG_ERROR("[{}]- aclrtMemcpy failed", m_dec_name); | |
756 | + av_packet_free(&pkt); | |
757 | + pkt = nullptr; | |
758 | + return 2; | |
759 | + } | |
760 | + | |
761 | + void *vdecOutputBuf = nullptr; | |
762 | + ret = acldvppMalloc((void **)&vdecOutputBuf, m_vdec_out_size); | |
763 | + if(ret != ACL_ERROR_NONE){ | |
764 | + LOG_ERROR("[{}]- acldvppMalloc failed", m_dec_name); | |
765 | + av_packet_free(&pkt); | |
766 | + pkt = nullptr; | |
767 | + return 2; | |
768 | + } | |
769 | + | |
770 | + acldvppStreamDesc *input_stream_desc = nullptr; | |
771 | + acldvppPicDesc *output_pic_desc = nullptr; | |
772 | + do{ | |
773 | + input_stream_desc = acldvppCreateStreamDesc(); | |
774 | + if (input_stream_desc == nullptr) { | |
775 | + LOG_ERROR("[{}]- acldvppCreateStreamDesc failed", m_dec_name); | |
776 | + break; | |
777 | + } | |
778 | + output_pic_desc = acldvppCreatePicDesc(); | |
779 | + if (output_pic_desc == nullptr) { | |
780 | + LOG_ERROR("[{}]- acldvppCreatePicDesc failed", m_dec_name); | |
781 | + break; | |
782 | + } | |
783 | + CHECK_AND_BREAK(acldvppSetStreamDescData(input_stream_desc, vdecInputbuf), "acldvppSetStreamDescData failed"); | |
784 | + CHECK_AND_BREAK(acldvppSetStreamDescSize(input_stream_desc, pkt->size), "acldvppSetStreamDescSize failed"); | |
785 | + CHECK_AND_BREAK(acldvppSetPicDescData(output_pic_desc, vdecOutputBuf), "acldvppSetPicDescData failed"); | |
786 | + CHECK_AND_BREAK(acldvppSetPicDescSize(output_pic_desc, m_vdec_out_size), "acldvppSetPicDescSize failed"); | |
787 | + | |
788 | + Vdec_CallBack_UserData *user_data = NULL; | |
789 | + user_data = new Vdec_CallBack_UserData; | |
790 | + user_data->frameId = frame_count; | |
791 | + // user_data->startTime = startTime; | |
792 | + user_data->sendTime = UtilTools::get_cur_time_ms(); | |
793 | + user_data->self = this; | |
794 | + ret = aclvdecSendFrame(vdecChannelDesc, input_stream_desc, output_pic_desc, nullptr, reinterpret_cast<void *>(user_data)); | |
795 | + av_packet_free(&pkt); | |
796 | + pkt = nullptr; | |
797 | + if(ret != ACL_ERROR_NONE){ | |
798 | + delete user_data; | |
799 | + user_data = nullptr; | |
800 | + LOG_ERROR("[{}]- aclvdecSendFrame failed", m_dec_name); | |
801 | + break; | |
802 | + } | |
803 | + | |
804 | + m_vdecQueue_mutex.lock(); | |
805 | + m_vdecQueue.push(vdecInputbuf); | |
806 | + m_vdecQueue_mutex.unlock(); | |
807 | + | |
808 | + return 0; | |
809 | + }while (0); | |
810 | + | |
811 | + if(pkt != nullptr){ | |
812 | + av_packet_free(&pkt); | |
813 | + pkt = nullptr; | |
814 | + } | |
815 | + | |
816 | + // 报错情形 | |
817 | + if(input_stream_desc){ | |
818 | + CHECK_NOT_RETURN(acldvppDestroyStreamDesc(input_stream_desc), "acldvppDestroyStreamDesc failed"); | |
819 | + } | |
820 | + if(output_pic_desc){ | |
821 | + CHECK_NOT_RETURN(acldvppDestroyPicDesc(output_pic_desc), "acldvppDestroyPicDesc failed"); | |
822 | + } | |
823 | + | |
824 | + if (vdecOutputBuf){ | |
825 | + acldvppFree(vdecOutputBuf); | |
826 | + vdecOutputBuf = nullptr; | |
827 | + } | |
828 | + | |
829 | + return 1; | |
830 | +} | |
831 | + | |
832 | +bool DvppDecoder::sendVdecEos(aclvdecChannelDesc *vdecChannelDesc) { | |
833 | + // create stream desc | |
834 | + acldvppStreamDesc *streamInputDesc = acldvppCreateStreamDesc(); | |
835 | + if (streamInputDesc == nullptr) { | |
836 | + LOG_ERROR("[{}]- fail to create input stream desc", m_dec_name); | |
837 | + return false; | |
838 | + } | |
839 | + aclError ret = acldvppSetStreamDescEos(streamInputDesc, 1); | |
840 | + if (ret != ACL_SUCCESS) { | |
841 | + LOG_ERROR("[{}]- fail to set eos for stream desc, errorCode = {}", m_dec_name, static_cast<int32_t>(ret)); | |
842 | + (void)acldvppDestroyStreamDesc(streamInputDesc); | |
843 | + return false; | |
844 | + } | |
845 | + | |
846 | + // send vdec eos frame. when all vdec callback are completed, aclvdecSendFrame can be returned. | |
847 | + LOG_INFO("[{}]- send eos", m_dec_name); | |
848 | + ret = aclvdecSendFrame(vdecChannelDesc, streamInputDesc, nullptr, nullptr, nullptr); | |
849 | + (void)acldvppDestroyStreamDesc(streamInputDesc); | |
850 | + if (ret != ACL_SUCCESS) { | |
851 | + LOG_ERROR("[{}]- fail to send eos frame, ret={}", m_dec_name, ret); | |
852 | + return false; | |
853 | + } | |
854 | + | |
855 | + return true; | |
856 | +} | |
857 | + | |
858 | +void DvppDecoder::release_dvpp(){ | |
859 | + if(m_context){ | |
860 | + aclError ret = aclrtDestroyContext(m_context); | |
861 | + if(ret != ACL_ERROR_NONE){ | |
862 | + LOG_ERROR("[{}]- aclrtDestroyContext failed !", m_dec_name); | |
863 | + } | |
864 | + } | |
865 | + | |
866 | + DvppSourceManager* pSrcMgr = DvppSourceManager::getInstance(); | |
867 | + pSrcMgr->releaseChannel(m_dvpp_deviceId, m_dvpp_channel); | |
137 | 868 | } |
138 | 869 | \ No newline at end of file | ... | ... |
src/decoder/dvpp/DvppDecoder.h
1 | 1 | #include<string> |
2 | 2 | |
3 | 3 | #include "depend_headers.h" |
4 | -#include "CircularQueue.hpp" | |
5 | -#include "FFReceiver.h" | |
6 | -#include "DvppDec.h" | |
4 | +#include "dvpp_headers.h" | |
5 | +#include "DvppDataMemory.hpp" | |
6 | + | |
7 | +#include <queue> | |
8 | +#include <mutex> | |
9 | +#include <condition_variable> | |
10 | + | |
7 | 11 | |
8 | 12 | using namespace std; |
9 | 13 | |
14 | +typedef void(*RECEIVER_FINISHED_CALLBACK)(const void* userPtr); | |
15 | + | |
16 | +const int g_pkt_size = 1024 * 1024; // 单个AVPacket大小的最大值 | |
17 | + | |
10 | 18 | class DvppDecoder{ |
11 | 19 | public: |
12 | 20 | DvppDecoder(); |
... | ... | @@ -44,19 +52,72 @@ public: |
44 | 52 | int getCachedQueueLength(); |
45 | 53 | |
46 | 54 | public: |
47 | - void taskFinishing(); | |
55 | + void doVdppVdecCallBack(acldvppStreamDesc *input, acldvppPicDesc *output); | |
56 | + void doProcessReport(); | |
57 | + | |
58 | +private: | |
59 | + AVCodecContext* init_FFmpeg(FFDecConfig config); | |
60 | + bool init_vdpp(FFDecConfig cfg, AVCodecContext* avctx); | |
61 | + void release_ffmpeg(); | |
62 | + void read_thread(); | |
63 | + | |
64 | + void decode_thread(); | |
65 | + int sentFrame(aclvdecChannelDesc *vdecChannelDesc, uint64_t frame_count); | |
66 | + bool sendVdecEos(aclvdecChannelDesc *vdecChannelDesc); | |
67 | + void release_dvpp(); | |
48 | 68 | |
49 | 69 | private: |
50 | 70 | FFDecConfig m_cfg; |
51 | 71 | string m_dec_name; |
52 | 72 | |
53 | - CircularQueue<AVPacket *> *m_pktQueueptr; | |
54 | - FFReceiver m_receiver; | |
55 | - DvppDec m_decoder; | |
56 | - | |
57 | 73 | const void * m_finishedDecArg; |
58 | 74 | DECODE_FINISHED_CALLBACK decode_finished_cbk; |
59 | 75 | |
60 | 76 | bool m_bFinished{false}; |
77 | + bool m_bRunning{false}; | |
78 | + bool m_bPause{false}; | |
79 | + bool m_bExitReportThd{false}; | |
80 | + | |
81 | + // 读取数据 | |
82 | + AVStream* stream{nullptr}; | |
83 | + int video_index{-1}; | |
84 | + AVFormatContext *fmt_ctx{nullptr}; | |
85 | + AVPixelFormat pix_fmt; | |
86 | + AVCodecContext *avctx{nullptr}; | |
87 | + AVBSFContext * h264bsfc{nullptr}; | |
88 | + | |
89 | + int frame_width{0}; | |
90 | + int frame_height{0}; | |
91 | + bool m_bReal; // 是否实时流 | |
92 | + float m_fps{0.0}; | |
93 | + | |
94 | + RECEIVER_FINISHED_CALLBACK receiver_finished_cbk; | |
95 | + | |
96 | + pthread_t m_read_thread{0}; | |
97 | + | |
98 | + bool m_dec_keyframe; | |
99 | + | |
100 | + mutex m_pktQueue_mutex; | |
101 | + queue<AVPacket*> m_pktQueue; | |
102 | + | |
103 | + // 解码 | |
104 | + int m_dvpp_deviceId {-1}; | |
105 | + int m_dvpp_channel {-1}; | |
106 | + aclrtContext m_context{nullptr}; | |
107 | + acldvppStreamFormat enType; | |
108 | + | |
109 | + pthread_t m_decode_thread{0}; | |
110 | + mutex m_vdecQueue_mutex; | |
111 | + queue<void*> m_vdecQueue; | |
112 | + | |
113 | + const void * m_postDecArg; | |
114 | + POST_DECODE_CALLBACK post_decoded_cbk; | |
115 | + | |
116 | + int m_vdec_out_size {-1}; | |
61 | 117 | |
118 | + // 截图 | |
119 | + bool m_bSnapShoting{false}; | |
120 | + DvppDataMemory* m_cached_mem{nullptr}; | |
121 | + mutex m_cached_mutex; | |
122 | + condition_variable m_cached_cond; | |
62 | 123 | }; |
63 | 124 | \ No newline at end of file | ... | ... |
src/decoder/dvpp/FFReceiver.cpp deleted
1 | -#include "FFReceiver.h" | |
2 | -#include <fstream> | |
3 | - | |
4 | -const int g_pkt_size = 1024 * 1024; // 单个AVPacket大小的最大值 | |
5 | - | |
6 | -FFReceiver::FFReceiver(/* args */) | |
7 | -{ | |
8 | - fmt_ctx = nullptr; | |
9 | - m_bRunning = false; | |
10 | - | |
11 | - stream = nullptr; | |
12 | - stream_index = -1; | |
13 | - pix_fmt = AV_PIX_FMT_NONE; | |
14 | - m_dec_name = ""; | |
15 | - | |
16 | - m_bPause = false; | |
17 | - m_bReal = true; | |
18 | - | |
19 | - m_bFinished = false; | |
20 | - m_dec_keyframe = false; | |
21 | - m_fps = 0.0; | |
22 | - | |
23 | - m_read_thread = 0; | |
24 | -} | |
25 | - | |
26 | -FFReceiver::~FFReceiver() | |
27 | -{ | |
28 | - releaseFFmpeg(); | |
29 | - | |
30 | - // 这个只能放在析构函数中,因为会影响到解码类中的m_pktQueueptr队列 | |
31 | - // 所以应当确保在所有工作线程都退出后才释放 | |
32 | - for(int i = 0; i < m_vec_pkt.size(); i++){ | |
33 | - av_packet_free(&m_vec_pkt[i]); | |
34 | - } | |
35 | -} | |
36 | - | |
37 | -AVCodecContext* FFReceiver::init_FFmpeg(ReceiverConfig config){ | |
38 | - | |
39 | -#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 9, 100) | |
40 | - av_register_all(); | |
41 | -#endif | |
42 | -#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 10, 100) | |
43 | - avcodec_register_all(); | |
44 | -#endif | |
45 | - | |
46 | - avformat_network_init(); | |
47 | - | |
48 | - const char* uri = config.uri; | |
49 | - fstream infile(uri); | |
50 | - if (infile.is_open()){ | |
51 | - m_bReal = false; | |
52 | - infile.close(); | |
53 | - }else { | |
54 | - m_bReal = true; | |
55 | - } | |
56 | - | |
57 | - m_dec_name = config.dec_name; | |
58 | - m_pktQueueptr = config.pktQueueptr; | |
59 | - receiver_finished_cbk = config.receiver_finished_cbk; | |
60 | - | |
61 | - // 打开输入视频文件 | |
62 | - AVDictionary *options = nullptr; | |
63 | - av_dict_set( &options, "bufsize", "655360", 0 ); | |
64 | - av_dict_set( &options, "rtsp_transport", config.force_tcp ? "tcp" : "udp", 0 ); | |
65 | - av_dict_set( &options, "stimeout", "30000000", 0 ); // 单位为 百万分之一秒 | |
66 | - | |
67 | - fmt_ctx = avformat_alloc_context(); | |
68 | - const char* input_file = uri; | |
69 | - if (avformat_open_input(&fmt_ctx, input_file, nullptr, &options) != 0) { | |
70 | - LOG_ERROR("[{}]- Cannot open input file: {}", m_dec_name, input_file); | |
71 | - return nullptr; | |
72 | - } | |
73 | - av_dump_format(fmt_ctx, 0, input_file, 0); | |
74 | - | |
75 | - // 查找流信息 | |
76 | - if (avformat_find_stream_info(fmt_ctx, nullptr) < 0) { | |
77 | - LOG_ERROR("[{}]- Cannot find input stream information!", m_dec_name); | |
78 | - return nullptr; | |
79 | - } | |
80 | - | |
81 | - // 查找视频流信息 | |
82 | - AVCodec *decoder = nullptr; | |
83 | - stream_index = av_find_best_stream(fmt_ctx, AVMEDIA_TYPE_VIDEO, -1, -1, &decoder, 0); | |
84 | - if (stream_index < 0) { | |
85 | - LOG_ERROR("[{}]- Cannot find a video stream in the input file!", m_dec_name); | |
86 | - return nullptr; | |
87 | - } | |
88 | - AVCodec *vcodec = avcodec_find_decoder(decoder->id); | |
89 | - | |
90 | - avctx = avcodec_alloc_context3(vcodec); | |
91 | - if(avctx == nullptr){ | |
92 | - LOG_ERROR("[{}]- alloc AVCodecContext failed!", m_dec_name); | |
93 | - return nullptr; | |
94 | - } | |
95 | - | |
96 | - do{ | |
97 | - // 得到视频流对象 | |
98 | - AVStream* stream = fmt_ctx->streams[stream_index]; | |
99 | - AVCodecParameters *codecpar = stream->codecpar; | |
100 | - if (avcodec_parameters_to_context(avctx, codecpar) < 0) | |
101 | - break; | |
102 | - | |
103 | - const AVBitStreamFilter * filter = nullptr; | |
104 | - if(codecpar->codec_id == AV_CODEC_ID_H264){ | |
105 | - filter = av_bsf_get_by_name("h264_mp4toannexb"); | |
106 | - }else if(codecpar->codec_id == AV_CODEC_ID_HEVC){ | |
107 | - filter = av_bsf_get_by_name("hevc_mp4toannexb"); | |
108 | - }else { | |
109 | - LOG_ERROR("[{}]- codec_id is not supported!", m_dec_name); | |
110 | - break; | |
111 | - } | |
112 | - | |
113 | - int ret = av_bsf_alloc(filter, &h264bsfc); | |
114 | - if (ret < 0){ | |
115 | - break; | |
116 | - } | |
117 | - | |
118 | - avcodec_parameters_copy(h264bsfc->par_in, codecpar); | |
119 | - av_bsf_init(h264bsfc); | |
120 | - | |
121 | - frame_width = codecpar->width; | |
122 | - frame_height = codecpar->height; | |
123 | - pix_fmt = (AVPixelFormat)codecpar->format; | |
124 | - m_fps = av_q2d(stream ->avg_frame_rate); | |
125 | - | |
126 | - LOG_INFO("[{}]- init ffmpeg success! input:{} frame_width:{} frame_height:{} fps:{} ", m_dec_name, input_file, frame_width, frame_height, m_fps); | |
127 | - | |
128 | - for(int i = 0; i < 50; i++){ | |
129 | - AVPacket* pkt = av_packet_alloc(); | |
130 | - av_init_packet( pkt ); | |
131 | - m_vec_pkt.push_back(pkt); | |
132 | - } | |
133 | - m_pktQueueptr->init(m_vec_pkt); | |
134 | - | |
135 | - return avctx; | |
136 | - }while(0); | |
137 | - | |
138 | - LOG_ERROR("[{}]- init ffmpeg failed ! input:{} ", m_dec_name); | |
139 | - | |
140 | - return nullptr; | |
141 | -} | |
142 | - | |
143 | -void FFReceiver::releaseFFmpeg(){ | |
144 | - m_dec_keyframe = false; | |
145 | - if(h264bsfc){ | |
146 | - av_bsf_free(&h264bsfc); | |
147 | - h264bsfc = nullptr; | |
148 | - } | |
149 | - if (fmt_ctx){ | |
150 | - avformat_close_input(&fmt_ctx); | |
151 | - fmt_ctx = nullptr; | |
152 | - } | |
153 | - if(avctx){ | |
154 | - avcodec_free_context(&avctx); | |
155 | - avctx = nullptr; | |
156 | - } | |
157 | -} | |
158 | - | |
159 | -void FFReceiver::read_thread(){ | |
160 | - | |
161 | - int frame_count = 0; | |
162 | - int ret = -1; | |
163 | - | |
164 | - AVPacket* pkt; | |
165 | - | |
166 | - while (m_bRunning){ | |
167 | - | |
168 | - if (!m_bReal){ | |
169 | - if (m_bPause){ | |
170 | - std::this_thread::sleep_for(std::chrono::milliseconds(3)); | |
171 | - continue; | |
172 | - } | |
173 | - } | |
174 | - | |
175 | - AVPacket* pkt = m_pktQueueptr->getTail(); | |
176 | - if(pkt == nullptr){ | |
177 | - std::this_thread::sleep_for(std::chrono::milliseconds(3)); | |
178 | - continue; | |
179 | - } | |
180 | - | |
181 | - // AVPacket* pkt = av_packet_alloc(); | |
182 | - // av_init_packet( pkt ); | |
183 | - | |
184 | - int result = av_read_frame(fmt_ctx, pkt); | |
185 | - if (result == AVERROR_EOF || result < 0){ | |
186 | - av_packet_unref(pkt); | |
187 | - LOG_ERROR("[{}]- Failed to read frame!", m_dec_name); | |
188 | - break; | |
189 | - } | |
190 | - | |
191 | - // m_pktQueueptr->addTail(); | |
192 | - | |
193 | - // std::this_thread::sleep_for(std::chrono::milliseconds(1)); | |
194 | - // pkt = m_pktQueueptr->getHead(); | |
195 | - // av_packet_unref(pkt); | |
196 | - // m_pktQueueptr->addHead(); | |
197 | - | |
198 | - // av_packet_free(&pkt); | |
199 | - // pkt = nullptr; | |
200 | - // continue; | |
201 | - | |
202 | - if (m_dec_keyframe && !(pkt->flags & AV_PKT_FLAG_KEY)) { | |
203 | - av_packet_unref(pkt); | |
204 | - continue; | |
205 | - } | |
206 | - | |
207 | - if (stream_index == pkt->stream_index){ | |
208 | - | |
209 | - ret = av_bsf_send_packet(h264bsfc, pkt); | |
210 | - if(ret < 0) { | |
211 | - LOG_ERROR("[{}]- av_bsf_send_packet error!", m_dec_name); | |
212 | - } | |
213 | - | |
214 | - while ((ret = av_bsf_receive_packet(h264bsfc, pkt)) == 0) { | |
215 | - if(pkt->size > g_pkt_size){ | |
216 | - LOG_ERROR("[{}]- pkt size 大于最大预设值!", m_dec_name); | |
217 | - break; | |
218 | - } | |
219 | - | |
220 | - if(!m_bRunning){ | |
221 | - break; | |
222 | - } | |
223 | - | |
224 | - m_pktQueueptr->addTail(); | |
225 | - | |
226 | - frame_count++; | |
227 | - } | |
228 | - } else { | |
229 | - // 音频等其他分量的情形 | |
230 | - av_packet_unref(pkt); | |
231 | - } | |
232 | - } | |
233 | - | |
234 | - LOG_INFO("[{}]- read thread exit.", m_dec_name); | |
235 | - m_bFinished = true; | |
236 | - | |
237 | - receiver_finished_cbk(m_finishedReceiveArg); | |
238 | -} | |
239 | - | |
240 | -bool FFReceiver::start(){ | |
241 | - m_bRunning = true; | |
242 | - | |
243 | - pthread_create(&m_read_thread,0, | |
244 | - [](void* arg) | |
245 | - { | |
246 | - FFReceiver* a=(FFReceiver*)arg; | |
247 | - a->read_thread(); | |
248 | - return (void*)0; | |
249 | - } | |
250 | - ,this); | |
251 | - | |
252 | - return true; | |
253 | -} | |
254 | - | |
255 | -void FFReceiver::close(){ | |
256 | - m_bRunning=false; | |
257 | - | |
258 | - if(m_read_thread != 0){ | |
259 | - pthread_join(m_read_thread,0); | |
260 | - } | |
261 | -} | |
262 | - | |
263 | -float FFReceiver::fps(){ | |
264 | - return m_fps; | |
265 | -} | |
266 | - | |
267 | -bool FFReceiver::getResolution( int &width, int &height ){ | |
268 | - width = frame_width; | |
269 | - height = frame_height; | |
270 | - return true; | |
271 | -} | |
272 | - | |
273 | -void FFReceiver::pause(){ | |
274 | - m_bPause = true; | |
275 | -} | |
276 | - | |
277 | -void FFReceiver::resume(){ | |
278 | - m_bPause = false; | |
279 | -} | |
280 | - | |
281 | -void FFReceiver::setDecKeyframe(bool bKeyframe) | |
282 | -{ | |
283 | - m_dec_keyframe = bKeyframe; | |
284 | -} | |
285 | - | |
286 | -bool FFReceiver::isRunning(){ | |
287 | - return m_bRunning; | |
288 | -} | |
289 | - | |
290 | -bool FFReceiver::isFinished(){ | |
291 | - return m_bFinished; | |
292 | -} | |
293 | - | |
294 | -bool FFReceiver::isPausing(){ | |
295 | - return m_bPause; | |
296 | -} | |
297 | - | |
298 | -void FFReceiver::setFinishCbkArg(const void* userPtr){ | |
299 | - m_finishedReceiveArg = userPtr; | |
300 | -} | |
301 | 0 | \ No newline at end of file |
src/decoder/dvpp/FFReceiver.h deleted
1 | -#ifndef __FFRECEIVER_H__ | |
2 | -#define __FFRECEIVER_H__ | |
3 | - | |
4 | -#include "depend_headers.h" | |
5 | -#include "CircularQueue.hpp" | |
6 | - | |
7 | -typedef void(*RECEIVER_FINISHED_CALLBACK)(const void* userPtr); | |
8 | - | |
9 | -struct ReceiverConfig{ | |
10 | - const char* uri; | |
11 | - string dec_name; | |
12 | - bool force_tcp; | |
13 | - CircularQueue<AVPacket*> *pktQueueptr; | |
14 | - RECEIVER_FINISHED_CALLBACK receiver_finished_cbk; // 解码线程结束后的回调接口 | |
15 | -}; | |
16 | - | |
17 | -class FFReceiver | |
18 | -{ | |
19 | -public: | |
20 | - FFReceiver(/* args */); | |
21 | - ~FFReceiver(); | |
22 | - | |
23 | - AVCodecContext* init_FFmpeg(ReceiverConfig config); | |
24 | - void releaseFFmpeg(); | |
25 | - void close(); | |
26 | - bool start(); | |
27 | - | |
28 | - void pause(); | |
29 | - void resume(); | |
30 | - void setDecKeyframe(bool bKeyframe); | |
31 | - bool isRunning(); | |
32 | - bool isFinished(); | |
33 | - bool isPausing(); | |
34 | - bool getResolution( int &width, int &height ); | |
35 | - float fps(); | |
36 | - | |
37 | - void setName(string nm){ | |
38 | - m_dec_name = nm; | |
39 | - } | |
40 | - | |
41 | - void setFinishCbkArg(const void* userPtr); | |
42 | - | |
43 | -private: | |
44 | - void read_thread(); | |
45 | - | |
46 | -private: | |
47 | - string m_dec_name; | |
48 | - | |
49 | - AVStream* stream; | |
50 | - int stream_index; | |
51 | - AVFormatContext *fmt_ctx; | |
52 | - AVPixelFormat pix_fmt; | |
53 | - int frame_width{0}; | |
54 | - int frame_height{0}; | |
55 | - | |
56 | - pthread_t m_read_thread; | |
57 | - | |
58 | - bool m_bRunning; | |
59 | - bool m_bFinished; | |
60 | - | |
61 | - bool m_bPause; | |
62 | - | |
63 | - bool m_bReal; // 是否实时流 | |
64 | - | |
65 | - float m_fps; | |
66 | - | |
67 | - FFDecConfig m_cfg; | |
68 | - bool m_dec_keyframe; | |
69 | - | |
70 | - AVCodecContext *avctx{nullptr}; | |
71 | - AVBSFContext * h264bsfc{nullptr}; | |
72 | - | |
73 | - vector<AVPacket*> m_vec_pkt; | |
74 | - CircularQueue<AVPacket *> *m_pktQueueptr; | |
75 | - | |
76 | - const void * m_finishedReceiveArg; | |
77 | - RECEIVER_FINISHED_CALLBACK receiver_finished_cbk; | |
78 | -}; | |
79 | - | |
80 | - | |
81 | -#endif | |
82 | 0 | \ No newline at end of file |