Commit fce4580d65558172deb944f08e65d0640546360c

Authored by Hu Chunming
1 parent b00d3d35

更新最新代码:修改解码器实现方式并修改一些bug;优化代码

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&lt;string&gt;&amp; 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&lt;string&gt;&amp; 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 &amp;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