diff --git a/src/ai_platform/MultiSourceProcess.cpp b/src/ai_platform/MultiSourceProcess.cpp index 85914e9..ae45e50 100644 --- a/src/ai_platform/MultiSourceProcess.cpp +++ b/src/ai_platform/MultiSourceProcess.cpp @@ -207,8 +207,7 @@ bool CMultiSourceProcess::AddTask(task_param _cur_task_param){ } AbstractDecoder* dec = pDecManager->createDecoder(config); - if (!dec) - { + if (!dec){ return false; } @@ -417,6 +416,10 @@ bool CMultiSourceProcess::finish_task(const string taskID, const bool delete_sna mq_manager_->publish(mq_type_t::HEART_BEAT_MQ, json_str.c_str(), true); #endif +#ifdef WITH_SECOND_PROCESS + pedestrian_vehicle_retrograde_.force_release_result(taskID); //221024 byzsh +#endif + m_task_param_manager->delete_task_param(taskID); return true; @@ -496,6 +499,7 @@ int CMultiSourceProcess::algorthim_vpt(vector vec_gpuMem){ sy_img img; img.w_ = mem->getWidth(); img.h_ = mem->getHeight(); + img.c_ = mem->getChannel(); img.data_ = mem->getMem(); vpt_interest_imgs.push_back(img); vpt_interest_task_id.push_back(mem->getId()); @@ -517,7 +521,6 @@ int CMultiSourceProcess::algorthim_vpt(vector vec_gpuMem){ #ifndef VEHICLE_MULTI_BOXES /* 快照优选(内部可实现不同的快照优选策略) */ m_snapshot_reprocessing->update_bestsnapshot(vec_vptMem, vptResult, deleteObjectID); - /* for snapshot algorithm. 轨迹结束目标 做最后的结果返回(当前返回算法结果+快照保存路径)*/ vehicle_snapshot(vpt_interest_task_id, deleteObjectID); #else @@ -530,8 +533,12 @@ int CMultiSourceProcess::algorthim_vpt(vector vec_gpuMem){ /* for pedestrian safety det. 行人安全分析算法模块 */ // algorthim_pedestrian_safety(vpt_interest_task_id, vpt_interest_imgs,vptResult); - /* for retrograde & trespass algor 逆行&非法闯入算法模块 */ - algorthim_retrograde_trespass(vpt_interest_task_id, vec_vptMem, vptResult, deleteObjectID); + // 逆行 + algorthim_retrograde(vpt_interest_task_id, vec_vptMem, vptResult); + retrograde_snapshot(vpt_interest_task_id, deleteObjectID); + // 闯入 + algorthim_trespass(vpt_interest_task_id, vec_vptMem, vptResult, deleteObjectID); + trespass_snapshot(vpt_interest_task_id, deleteObjectID); // #endif @@ -662,21 +669,12 @@ void CMultiSourceProcess::vehicle_snapshot(vector& vpt_interest_task_id, for (int &j : deleteObjectID[i]) // loop algor type. { OBJ_KEY obj_key = {*task_iter, j}; - endframe_obj_process(obj_key, algorithm_type_t::PLACEHOLDER); + // 该路任务开启了抓拍功能 开始抓拍保存;若未开启抓拍,清空显存资源 + vehicle_locus_finished(obj_key); } } } -/* 轨迹结束帧需要做的算法模块 */ -int CMultiSourceProcess::endframe_obj_process(const OBJ_KEY &obj_key, algorithm_type_t algor_type) { - - // 该路任务开启了抓拍功能 开始抓拍保存;若未开启抓拍,清空显存资源 - vehicle_locus_finished(obj_key); - - /* 开启行人&机动车逆行算法模块,获取该目标的算法分析结果 返回结果+快照 最后释放资源 */ - endframe_retrograde_trespass(obj_key); -} - void CMultiSourceProcess::vehicle_locus_finished(const OBJ_KEY obj_key) { auto task_param_ptr = m_task_param_manager->get_task_algor_param(obj_key.video_id); 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(){ LOG_INFO("timing_snapshot_thread end."); } -void CMultiSourceProcess::algorthim_retrograde_trespass(vector& vpt_interest_task_id, vector vpt_interest_imgs, - vector& vptResult ,vector>& deleteObjectID){ +// 逆行 +void CMultiSourceProcess::algorthim_retrograde(vector& vpt_interest_task_id, vector vpt_interest_imgs, + vector& vptResult){ vector interest_task_id; vector interest_vpt_result; - vector interest_imgs; - - vector trespass_interest_task_id; - vector trespass_interest_vpt_result; - vector> trespass_interest_deleteobjs; - vector trespass_interest_imgs; + vector interest_imgs; int _idx = 0; 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& vpt_inte interest_imgs.emplace_back(vpt_interest_imgs[_idx]); interest_vpt_result.emplace_back(vptResult[_idx]); } + } + + LOG_DEBUG("retrograde interest_vpt_result size: {}", interest_vpt_result.size()); + + if (!interest_imgs.empty()){ + pedestrian_vehicle_retrograde_.update_mstreams(interest_task_id, interest_imgs, interest_vpt_result); + } +} + +// 闯入 +void CMultiSourceProcess::algorthim_trespass(vector& vpt_interest_task_id, vector vpt_interest_imgs, + vector& vptResult ,vector>& deleteObjectID){ + + vector trespass_interest_task_id; + vector trespass_interest_vpt_result; + vector> trespass_interest_deleteobjs; + vector trespass_interest_imgs; + + int _idx = 0; + for (auto _task_id_iter = vpt_interest_task_id.begin(); _task_id_iter != vpt_interest_task_id.end(); + ++_task_id_iter, ++_idx) // loop task_id; + { + auto task_id = *_task_id_iter; + auto algor_map = m_task_param_manager->get_task_other_param(task_id); if (algor_map->find(algorithm_type_t::PEDESTRIAN_TRESPASS) != algor_map->end() || algor_map->find(algorithm_type_t::VEHICLE_TRESPASS) != algor_map->end()) { @@ -843,36 +861,58 @@ void CMultiSourceProcess::algorthim_retrograde_trespass(vector& vpt_inte } } - LOG_DEBUG("trespass_interest_vpt_result size: {}", trespass_interest_vpt_result.size()); - - if (!interest_imgs.empty()) - pedestrian_vehicle_retrograde_.update_mstreams(interest_task_id, interest_imgs, - interest_vpt_result); + LOG_DEBUG("trespass interest_vpt_result size: {}", trespass_interest_vpt_result.size()); if (!trespass_interest_imgs.empty()) { - pedestrian_vehicle_trespass_.update_mstreams( - trespass_interest_task_id, trespass_interest_imgs, trespass_interest_vpt_result, - trespass_interest_deleteobjs); + pedestrian_vehicle_trespass_.update_mstreams( trespass_interest_task_id, trespass_interest_imgs, + trespass_interest_vpt_result, trespass_interest_deleteobjs); } } -int CMultiSourceProcess::endframe_retrograde_trespass(const OBJ_KEY &obj_key) { - auto task_param_ptr = m_task_param_manager->get_task_algor_param(obj_key.video_id); - /* 开启行人&机动车逆行算法模块,获取该目标的算法分析结果 返回结果+快照 最后释放资源 */ - if (task_param_ptr->human_algors.find(algorithm_type_t::PEDESTRIAN_RETROGRADE) != - task_param_ptr->human_algors.end()) - retrograde_trespass_alarm(obj_key, algorithm_type_t::PEDESTRIAN_RETROGRADE); +// for snapshot algorithm. 轨迹结束目标 做最后的结果返回(当前返回算法结果+快照保存路径) +void CMultiSourceProcess::retrograde_snapshot(vector& vpt_interest_task_id, vector> deleteObjectID) { + auto task_iter = vpt_interest_task_id.begin(); + + for (int i = 0; i < deleteObjectID.size(); i++, ++task_iter) // loop taskId. + { + for (int &j : deleteObjectID[i]) // loop algor type. + { + OBJ_KEY obj_key = {*task_iter, j}; + auto task_param_ptr = m_task_param_manager->get_task_algor_param(obj_key.video_id); + + /* 开启行人&机动车逆行算法模块,获取该目标的算法分析结果 返回结果+快照 最后释放资源 */ + if (task_param_ptr->human_algors.find(algorithm_type_t::PEDESTRIAN_RETROGRADE) != task_param_ptr->human_algors.end()){ + retrograde_trespass_alarm(obj_key, algorithm_type_t::PEDESTRIAN_RETROGRADE); + } + + if (task_param_ptr->vehicle_algors.find(algorithm_type_t::VEHICLE_RETROGRADE) != task_param_ptr->vehicle_algors.end()){ + retrograde_trespass_alarm(obj_key, algorithm_type_t::VEHICLE_RETROGRADE); + } + } + } +} - if (task_param_ptr->vehicle_algors.find(algorithm_type_t::VEHICLE_RETROGRADE) != - task_param_ptr->vehicle_algors.end()) - retrograde_trespass_alarm(obj_key, algorithm_type_t::VEHICLE_RETROGRADE); +// for snapshot algorithm. 轨迹结束目标 做最后的结果返回(当前返回算法结果+快照保存路径) +void CMultiSourceProcess::trespass_snapshot(vector& vpt_interest_task_id, vector> deleteObjectID) { + auto task_iter = vpt_interest_task_id.begin(); - if (task_param_ptr->human_algors.find(algorithm_type_t::PEDESTRIAN_TRESPASS) != task_param_ptr->human_algors.end()) - retrograde_trespass_alarm(obj_key, algorithm_type_t::PEDESTRIAN_TRESPASS); + for (int i = 0; i < deleteObjectID.size(); i++, ++task_iter) // loop taskId. + { + for (int &j : deleteObjectID[i]) // loop algor type. + { + OBJ_KEY obj_key = {*task_iter, j}; + auto task_param_ptr = m_task_param_manager->get_task_algor_param(obj_key.video_id); - if (task_param_ptr->vehicle_algors.find(algorithm_type_t::VEHICLE_TRESPASS) != task_param_ptr->vehicle_algors.end()) - retrograde_trespass_alarm(obj_key, algorithm_type_t::VEHICLE_TRESPASS); + if (task_param_ptr->human_algors.find(algorithm_type_t::PEDESTRIAN_TRESPASS) != task_param_ptr->human_algors.end()){ + retrograde_trespass_alarm(obj_key, algorithm_type_t::PEDESTRIAN_TRESPASS); + } + + if (task_param_ptr->vehicle_algors.find(algorithm_type_t::VEHICLE_TRESPASS) != task_param_ptr->vehicle_algors.end()){ + retrograde_trespass_alarm(obj_key, algorithm_type_t::VEHICLE_TRESPASS); + } + } + } } 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 obj_save_info.json_str = json_str; m_save_snapshot_reprocessing->reprocessing_process_wo_locus_async(obj_save_info); } - return true; } \ No newline at end of file diff --git a/src/ai_platform/MultiSourceProcess.h b/src/ai_platform/MultiSourceProcess.h index 534fbe0..6b3e350 100644 --- a/src/ai_platform/MultiSourceProcess.h +++ b/src/ai_platform/MultiSourceProcess.h @@ -49,9 +49,11 @@ public: private: // 算法相关 int algorthim_vpt(vector vec_gpuMem); - // 逆行&非法闯入算法模块 - void algorthim_retrograde_trespass(vector& vpt_interest_task_id, vector vpt_interest_imgs, - vector& vptResult ,vector>& deleteObjectID); + // 逆行 + void algorthim_retrograde(vector& vpt_interest_task_id, vector vpt_interest_imgs, vector& vptResult); + // 闯入 + void algorthim_trespass(vector& vpt_interest_task_id, vector vpt_interest_imgs, + vector& vptResult ,vector>& deleteObjectID); private: // 工具处理函数 @@ -63,12 +65,11 @@ private: void vehicle_snapshot(vector& vpt_interest_task_id, vector> deleteObjectID); void vehicle_locus_finished(const OBJ_KEY obj_key); - int endframe_obj_process(const OBJ_KEY &obj_key, algorithm_type_t algor_type); - 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, const long long id,const std::string &json_str); - int endframe_retrograde_trespass(const OBJ_KEY &obj_key); + void retrograde_snapshot(vector& vpt_interest_task_id, vector> deleteObjectID); + void trespass_snapshot(vector& vpt_interest_task_id, vector> deleteObjectID); void retrograde_trespass_alarm(const OBJ_KEY &obj_key, const algorithm_type_t &algor_type) ; private: diff --git a/src/decoder/dvpp/DvppDec.cpp b/src/decoder/dvpp/DvppDec.cpp deleted file mode 100644 index ce5f416..0000000 --- a/src/decoder/dvpp/DvppDec.cpp +++ /dev/null @@ -1,502 +0,0 @@ -#include "DvppDec.h" -#include "DvppSourceManager.h" - -#include "../../util/vpc_util.h" - -struct Vdec_CallBack_UserData { - uint64_t frameId; - long startTime; - long sendTime; - // void* vdecOutputBuf; - DvppDec* self; - shared_ptr inBufNode; - Vdec_CallBack_UserData() { - frameId = 0; - } -}; - -static const int g_pkt_size = 1024 * 1024; - - DvppDec::DvppDec(){ - m_decode_thread = 0; - m_cached_mem = nullptr; - } - - DvppDec::~DvppDec(){ - releaseResource(); - } - - bool DvppDec::init_vdpp(DvppDecConfig cfg){ - - m_dec_name = cfg.dec_name; - - LOG_INFO("[{}]- Init device start...", m_dec_name); - - m_dvpp_deviceId = atoi(cfg.dev_id.c_str()); - - if(cfg.codec_id == 0){ - // 66:Baseline,77:Main,>=100:High - if(cfg.profile == 77){ - enType = H264_MAIN_LEVEL; - }else if(cfg.profile < 77){ - enType = H264_BASELINE_LEVEL; - }else{ - enType = H264_HIGH_LEVEL; - } - }else if(cfg.codec_id == 1){ - // h265只有main - enType = H265_MAIN_LEVEL; - }else { - LOG_ERROR("[{}]- codec_id is not supported!", m_dec_name); - return false; - } - - post_decoded_cbk = cfg.post_decoded_cbk; - m_pktQueueptr = cfg.pktQueueptr; - - // DvppSourceManager 创建时包含 aclInit,析构时包含 aclFinalize - DvppSourceManager* pSrcMgr = DvppSourceManager::getInstance(); - m_context = pSrcMgr->getContext(m_dvpp_deviceId); - m_dvpp_channel = pSrcMgr->getChannel(m_dvpp_deviceId); - if(m_dvpp_channel < 0){ - LOG_ERROR("[{}]-该设备channel已经用完了!", m_dec_name); - return false; - } - - do - { - CHECK_AND_BREAK(aclrtSetCurrentContext(m_context), "aclrtSetCurrentContext failed !"); - - int ret = 0; - // int ret = picConverter.init(m_context, m_dec_name); - // if(ret != ACL_ERROR_NONE){ - // LOG_ERROR("[{}]- acldvppMalloc failed!, ret:{}", m_dec_name, ret); - // break; - // } - - // queue_size 最小应大于16,否则关键帧之间距离太远的时候会导致回调函数与循环队列卡死 - for (size_t i = 0; i < 20; i++){ - void *vdecInputbuf = nullptr; - ret = acldvppMalloc((void **)&vdecInputbuf, g_pkt_size); - if(ret != ACL_ERROR_NONE){ - LOG_ERROR("[{}]- acldvppMalloc failed!, ret:{}", m_dec_name, ret); - // 析构函数中有对channel 的补救性释放,所以这里可以直接return - return false;; - } - m_vec_vdec.push_back(vdecInputbuf); - } - - if(!m_vdecQueue.init(m_vec_vdec)){ - break; - } - - m_vdec_out_size = cfg.width * cfg.height * 3 / 2; - - LOG_INFO("[{}]- init vdpp success! device:{} channel:{}", m_dec_name, m_dvpp_deviceId, m_dvpp_channel); - return true; - - } while (0); - - LOG_INFO("[{}]- init vdpp failed!", m_dec_name); - // 初始化失败,释放channel - pSrcMgr->releaseChannel(m_dvpp_deviceId, m_dvpp_channel); - return false; -} - -bool DvppDec::start(){ - m_bRunning = true; - - pthread_create(&m_decode_thread,0, - [](void* arg) - { - DvppDec* a=(DvppDec*)arg; - a->decode_thread(); - return (void*)0; - } - ,this); - - return true; -} - -static void *ReportThd(void *arg) -{ - DvppDec *self = (DvppDec *)arg; - if(nullptr != self){ - self->doProcessReport(); - } - return (void *)0; -} - -void DvppDec::doProcessReport(){ - - aclError ret = aclrtSetDevice(m_dvpp_deviceId); - if(ret != ACL_ERROR_NONE){ - // cout << "aclrtSetDevice failed" << endl; - LOG_ERROR("aclrtSetDevice failed !"); - return ; - } - - aclrtContext ctx; - ret = aclrtCreateContext(&ctx, m_dvpp_deviceId); - if (ret != ACL_ERROR_NONE) { - // cout << "aclrtCreateContext failed " << endl; - LOG_ERROR("aclrtCreateContext failed !"); - return ; - } - - CHECK_AND_RETURN_NOVALUE(aclrtSetCurrentContext(ctx), "aclrtSetCurrentContext failed"); - // 阻塞等待vdec线程开始 - - while (!m_bExitReportThd) { - aclrtProcessReport(1000); - } - - ret = aclrtDestroyContext(ctx); - if(ret != ACL_ERROR_NONE){ - LOG_ERROR("aclrtDestroyContext failed !"); - } - LOG_INFO("doProcessReport exit."); -} - -static void VdecCallback(acldvppStreamDesc *input, acldvppPicDesc *output, void *pUserData) -{ - Vdec_CallBack_UserData *userData = (Vdec_CallBack_UserData *) pUserData; - if(nullptr != userData){ - DvppDec* self = userData->self; - if(self != nullptr){ - - self->doVdppVdecCallBack(input, output); - } - delete userData; - userData = nullptr; - } -} - -void DvppDec::doVdppVdecCallBack(acldvppStreamDesc *input, acldvppPicDesc *output){ - - // dvpp_crop(output); - - CHECK_AND_RETURN_NOVALUE(aclrtSetCurrentContext(m_context), "aclrtSetCurrentContext failed"); - - void *inputDataDev = acldvppGetStreamDescData(input); - void *outputDataDev = acldvppGetPicDescData(output); - uint32_t outputSize = acldvppGetPicDescSize(output); - uint32_t width = acldvppGetPicDescWidth(output); - uint32_t width_stride = acldvppGetPicDescWidthStride(output); - uint32_t height = acldvppGetPicDescHeight(output); - uint32_t height_stride = acldvppGetPicDescHeightStride(output); - - - DvppDataMemory* mem = new DvppDataMemory(width, width_stride, height, height_stride, outputSize, m_dec_name, to_string(m_dvpp_deviceId), false, (unsigned char *)outputDataDev); - post_decoded_cbk(m_postDecArg, mem); - - if(m_bSnapShoting){ - // 缓存snapshot - std::unique_lock locker(m_cached_mutex); - - m_cached_mem = new DvppDataMemory(-1, width, width_stride, height, height_stride, outputSize, m_dec_name, to_string(m_dvpp_deviceId), false); - if(m_cached_mem != nullptr){ - aclrtMemcpy(m_cached_mem->getMem(), outputSize, (unsigned char *)outputDataDev, outputSize, ACL_MEMCPY_DEVICE_TO_DEVICE); - } - - locker.unlock(); - m_cached_cond.notify_one(); - m_bSnapShoting = false; - } - - - - -// DvppDataMemory* rgbMem = picConverter.convert2bgr(output, width, height, false); -// if(rgbMem != nullptr){ -// #ifdef TEST_DECODER -// // D2H -// if(vdecHostAddr == nullptr){ -// CHECK_NOT_RETURN(aclrtMallocHost(&vdecHostAddr, width * height * 3), "aclrtMallocHost failed"); -// } -// uint32_t data_size = rgbMem->getSize(); -// CHECK_AND_RETURN_NOVALUE(aclrtMemcpy(vdecHostAddr, data_size, rgbMem->getMem(), data_size, ACL_MEMCPY_DEVICE_TO_HOST), "D2H aclrtMemcpy failed"); - -// // 保存vdec结果 -// if(count_frame > 45 && count_frame < 50) -// { -// string file_name = "./yuv_pic/vdec_out_"+ m_dec_name +".rgb" ; -// FILE *outputFile = fopen(file_name.c_str(), "a"); -// if(outputFile){ -// fwrite(vdecHostAddr, data_size, sizeof(char), outputFile); -// fclose(outputFile); -// } -// } -// else if(count_frame > 50 && vdecHostAddr != nullptr){ -// CHECK_NOT_RETURN(aclrtFreeHost(vdecHostAddr), "aclrtFreeHost failed"); -// vdecHostAddr = nullptr; -// } -// count_frame++; -// #endif -// post_decoded_cbk(m_postDecArg, rgbMem); -// }else{ -// LOG_ERROR("[{}]- convert2bgr failed !", m_dec_name); -// } - - // // 测试 - // acldvppFree(outputDataDev); - // outputDataDev = nullptr; - - m_vdecQueue.addHead(); - - CHECK_AND_RETURN_NOVALUE(acldvppDestroyStreamDesc(input), "acldvppDestroyStreamDesc failed"); - CHECK_AND_RETURN_NOVALUE(acldvppDestroyPicDesc(output), "acldvppDestroyPicDesc failed"); -} - -void DvppDec::close(){ - m_bRunning=false; - - if(m_decode_thread != 0){ - pthread_join(m_decode_thread,0); - } -} - -bool DvppDec::sendVdecEos(aclvdecChannelDesc *vdecChannelDesc){ - // create stream desc - acldvppStreamDesc *streamInputDesc = acldvppCreateStreamDesc(); - if (streamInputDesc == nullptr) { - LOG_ERROR("[{}]- fail to create input stream desc", m_dec_name); - return false; - } - aclError ret = acldvppSetStreamDescEos(streamInputDesc, 1); - if (ret != ACL_SUCCESS) { - LOG_ERROR("[{}]- fail to set eos for stream desc, errorCode = {}", m_dec_name, static_cast(ret)); - (void)acldvppDestroyStreamDesc(streamInputDesc); - return false; - } - - // send vdec eos frame. when all vdec callback are completed, aclvdecSendFrame can be returned. - LOG_INFO("[{}]- send eos", m_dec_name); - ret = aclvdecSendFrame(vdecChannelDesc, streamInputDesc, nullptr, nullptr, nullptr); - (void)acldvppDestroyStreamDesc(streamInputDesc); - if (ret != ACL_SUCCESS) { - LOG_ERROR("[{}]- fail to send eos frame, ret={}", m_dec_name, ret); - return false; - } - - return true; -} - -void DvppDec::releaseResource(){ - for(int i = 0; i < m_vec_vdec.size(); i++){ - if(m_vec_vdec[i] != nullptr){ - acldvppFree(m_vec_vdec[i]); - m_vec_vdec[i] = nullptr; - } - } - m_vec_vdec.clear(); - - DvppSourceManager* pSrcMgr = DvppSourceManager::getInstance(); - pSrcMgr->releaseChannel(m_dvpp_deviceId, m_dvpp_channel); -} - -void DvppDec::decode_thread(){ - - long startTime = UtilTools::get_cur_time_ms(); - - int ret = -1; - - // // dvpp解码参数 - // CHECK_AND_RETURN_NOVALUE(aclrtSetCurrentContext(m_context), "aclrtSetCurrentContext failed"); - - m_bExitReportThd = false; - pthread_t report_thread; - ret = pthread_create(&report_thread, nullptr, ReportThd, (void *)this); - if(ret != 0){ - LOG_ERROR("[{}]- pthread_create failed", m_dec_name); - return; - } - - aclrtSetDevice(m_dvpp_deviceId); - aclrtContext ctx; - ret = aclrtCreateContext(&ctx, m_dvpp_deviceId); - if (ret != ACL_ERROR_NONE) { - // cout << "aclrtCreateContext failed " << endl; - LOG_ERROR("aclrtCreateContext failed !"); - return ; - } - - // 创建aclvdecChannelDesc类型的数据 - aclvdecChannelDesc *vdecChannelDesc = aclvdecCreateChannelDesc(); - if (vdecChannelDesc == nullptr) { - LOG_ERROR("[{}]- aclvdecCreateChannelDesc failed", m_dec_name); - return; - } - do{ - // 创建 channel dec结构体 - // 通道ID在dvpp层面为0~31 - CHECK_AND_BREAK(aclvdecSetChannelDescChannelId(vdecChannelDesc, m_dvpp_channel), "aclvdecSetChannelDescChannelId failed"); - CHECK_AND_BREAK(aclvdecSetChannelDescThreadId(vdecChannelDesc, report_thread), "aclvdecSetChannelDescThreadId failed"); - CHECK_AND_BREAK(aclvdecSetChannelDescCallback(vdecChannelDesc, VdecCallback), "aclvdecSetChannelDescCallback failed"); - CHECK_AND_BREAK(aclvdecSetChannelDescEnType(vdecChannelDesc, enType), "aclvdecSetChannelDescEnType failed"); - CHECK_AND_BREAK(aclvdecSetChannelDescOutPicFormat(vdecChannelDesc, PIXEL_FORMAT_YUV_SEMIPLANAR_420), "aclvdecSetChannelDescOutPicFormat failed"); - CHECK_AND_BREAK(aclvdecCreateChannel(vdecChannelDesc), "aclvdecCreateChannel failed"); - - uint64_t frame_count = 0; - bool bBreak = false; - while (m_bRunning) - { - if (m_bPause){ - std::this_thread::sleep_for(std::chrono::milliseconds(3)); - continue; - } - int ret = sentFrame(vdecChannelDesc, frame_count); - if(ret == 2){ - break; - bBreak = true; - }else if(ret == 1){ - continue; - } - - frame_count++; - } - - // 尽量保证数据全部解码完成 - int sum = 0; - if(!bBreak){ - aclrtSetDevice(m_dvpp_deviceId); - aclrtSetCurrentContext(ctx); - while(!m_pktQueueptr->isEmpty()){ - int ret = sentFrame(vdecChannelDesc, frame_count); - if(ret == 2){ - break; - } - std::this_thread::sleep_for(std::chrono::milliseconds(3)); - sum++; - if(sum > 40){ - // 避免卡死 - break; - } - } - } - - sendVdecEos(vdecChannelDesc); - - CHECK_NOT_RETURN(aclvdecDestroyChannel(vdecChannelDesc), "aclvdecDestroyChannel failed"); - }while(0); - - CHECK_NOT_RETURN(aclvdecDestroyChannelDesc(vdecChannelDesc), "aclvdecDestroyChannelDesc failed"); - - // report_thread 需后于destroy退出 - m_bRunning = false; - m_bExitReportThd = true; - CHECK_NOT_RETURN(pthread_join(report_thread, nullptr), "pthread_join failed"); - - releaseResource(); - LOG_INFO("[{}]- decode thread exit.", m_dec_name); -} - -int DvppDec::sentFrame(aclvdecChannelDesc *vdecChannelDesc, uint64_t frame_count){ - - AVPacket * pkt = m_pktQueueptr->getHead(); - if(pkt == nullptr){ - std::this_thread::sleep_for(std::chrono::milliseconds(10)); - return 1; - } - // 解码 - void *vdecInputbuf = m_vdecQueue.getTail(); - if(vdecInputbuf == nullptr){ - std::this_thread::sleep_for(std::chrono::milliseconds(3)); - return 1; - } - - int ret = aclrtMemcpy(vdecInputbuf, pkt->size, pkt->data, pkt->size, ACL_MEMCPY_HOST_TO_DEVICE); - if(ACL_ERROR_NONE != ret){ - LOG_ERROR("[{}]- aclrtMemcpy failed", m_dec_name); - return 2; - } - - void *vdecOutputBuf = nullptr; - ret = acldvppMalloc((void **)&vdecOutputBuf, m_vdec_out_size); - if(ret != ACL_ERROR_NONE){ - LOG_ERROR("[{}]- acldvppMalloc failed", m_dec_name); - return 2; - } - - acldvppStreamDesc *input_stream_desc = nullptr; - acldvppPicDesc *output_pic_desc = nullptr; - do{ - input_stream_desc = acldvppCreateStreamDesc(); - if (input_stream_desc == nullptr) { - LOG_ERROR("[{}]- acldvppCreateStreamDesc failed", m_dec_name); - break; - } - output_pic_desc = acldvppCreatePicDesc(); - if (output_pic_desc == nullptr) { - LOG_ERROR("[{}]- acldvppCreatePicDesc failed", m_dec_name); - break; - } - CHECK_AND_BREAK(acldvppSetStreamDescData(input_stream_desc, vdecInputbuf), "acldvppSetStreamDescData failed"); - CHECK_AND_BREAK(acldvppSetStreamDescSize(input_stream_desc, pkt->size), "acldvppSetStreamDescSize failed"); - CHECK_AND_BREAK(acldvppSetPicDescData(output_pic_desc, vdecOutputBuf), "acldvppSetPicDescData failed"); - CHECK_AND_BREAK(acldvppSetPicDescSize(output_pic_desc, m_vdec_out_size), "acldvppSetPicDescSize failed"); - - Vdec_CallBack_UserData *user_data = NULL; - user_data = new Vdec_CallBack_UserData; - user_data->frameId = frame_count; - // user_data->startTime = startTime; - user_data->sendTime = UtilTools::get_cur_time_ms(); - user_data->self = this; - ret = aclvdecSendFrame(vdecChannelDesc, input_stream_desc, output_pic_desc, nullptr, reinterpret_cast(user_data)); - av_packet_unref(pkt); - m_pktQueueptr->addHead(); - if(ret != ACL_ERROR_NONE){ - delete user_data; - user_data = nullptr; - LOG_ERROR("[{}]- aclvdecSendFrame failed", m_dec_name); - break; - } - - m_vdecQueue.addTail(); - - return 0; - }while (0); - - // 报错情形 - if(input_stream_desc){ - CHECK_NOT_RETURN(acldvppDestroyStreamDesc(input_stream_desc), "acldvppDestroyStreamDesc failed"); - } - if(output_pic_desc){ - CHECK_NOT_RETURN(acldvppDestroyPicDesc(output_pic_desc), "acldvppDestroyPicDesc failed"); - } - - if (vdecOutputBuf){ - acldvppFree(vdecOutputBuf); - vdecOutputBuf = nullptr; - } - - return 1; -} - - -void DvppDec::setPostDecArg(const void* postDecArg){ - m_postDecArg = postDecArg; -} - -void DvppDec::pause(){ - m_bPause = true; -} - -void DvppDec::resume(){ - m_bPause = false; -} - -DeviceMemory* DvppDec::snapshot(){ - // 开始抓拍 - m_bSnapShoting = true; - - std::unique_lock locker(m_cached_mutex); - while (m_cached_mem == nullptr) - m_cached_cond.wait(locker); // Unlock mutex and wait to be notified - locker.unlock(); - - DeviceMemory* mem = m_cached_mem; - m_cached_mem = nullptr; - - return mem; -} \ No newline at end of file diff --git a/src/decoder/dvpp/DvppDec.h b/src/decoder/dvpp/DvppDec.h deleted file mode 100644 index 52c80ae..0000000 --- a/src/decoder/dvpp/DvppDec.h +++ /dev/null @@ -1,93 +0,0 @@ -#include -#include - -#include "dvpp_headers.h" -#include "depend_headers.h" -#include "user_mem.h" -#include "CircularQueue.hpp" -#include "VpcPicConverter.h" -#include "FFReceiver.h" - -#include -#include -#include - -using namespace std; - -// #define TEST_DECODER - -struct DvppDecConfig{ - string dec_name; - POST_DECODE_CALLBACK post_decoded_cbk; // 解码数据回调接口 - string dev_id; // gpu id - bool force_tcp{true}; // 是否指定使用tcp连接 - int skip_frame{1}; // 跳帧数 - int codec_id; // 0 : h264 1:h265 - int profile; - CircularQueue *pktQueueptr; - - int width; - int height; -}; - - -class DvppDec { -public: - DvppDec(); - ~DvppDec(); - bool init_vdpp(DvppDecConfig cfg); - void setPostDecArg(const void* postDecArg); - bool start(); - void close(); - void pause(); - void resume(); - DeviceMemory* snapshot(); - -public: - void doProcessReport(); - void doVdppVdecCallBack(acldvppStreamDesc *input, acldvppPicDesc *output); - -private: - void decode_thread(); - void releaseResource(); - bool sendVdecEos(aclvdecChannelDesc *vdecChannelDesc); - int sentFrame(aclvdecChannelDesc *vdecChannelDesc, uint64_t frame_count); - -private: - - bool m_bRunning{false}; - bool m_bPause{false}; - bool m_bExitReportThd{false}; - - int m_dvpp_deviceId {-1}; - int m_dvpp_channel {-1}; - aclrtContext m_context; - acldvppStreamFormat enType; - - pthread_t m_decode_thread; - - DvppDecConfig m_cfg; - string m_dec_name; - - vector m_vec_vdec; - CircularQueue m_vdecQueue; - CircularQueue *m_pktQueueptr; - - const void * m_postDecArg; - POST_DECODE_CALLBACK post_decoded_cbk; - - VpcPicConverter picConverter; - - int m_vdec_out_size {-1}; - - bool m_bSnapShoting{false}; - DvppDataMemory* m_cached_mem; - mutex m_cached_mutex; - condition_variable m_cached_cond; - -#ifdef TEST_DECODER - void *vdecHostAddr = nullptr; - int count_frame = 0; -#endif - -}; \ No newline at end of file diff --git a/src/decoder/dvpp/DvppDecoder.cpp b/src/decoder/dvpp/DvppDecoder.cpp index 951e7c7..24bfa9c 100644 --- a/src/decoder/dvpp/DvppDecoder.cpp +++ b/src/decoder/dvpp/DvppDecoder.cpp @@ -1,55 +1,54 @@ #include "DvppDecoder.h" +#include "DvppSourceManager.h" -void receiver_finish_cbk(const void* userPtr){ - if(userPtr != nullptr){ - DvppDecoder* self = (DvppDecoder*)userPtr; - self->taskFinishing(); + +struct Vdec_CallBack_UserData { + uint64_t frameId; + long startTime; + long sendTime; + // void* vdecOutputBuf; + DvppDecoder* self; + Vdec_CallBack_UserData() { + frameId = 0; } -} +}; DvppDecoder::DvppDecoder(){ - m_pktQueueptr = new CircularQueue(); + m_read_thread = 0; + m_decode_thread = 0; + m_cached_mem = nullptr; + + fmt_ctx = nullptr; + m_bRunning = false; + + stream = nullptr; + video_index = -1; + pix_fmt = AV_PIX_FMT_NONE; + m_dec_name = ""; + + m_bPause = false; + m_bReal = true; + + m_bFinished = false; + m_dec_keyframe = false; + m_fps = 0.0; + + m_bSnapShoting = false; } DvppDecoder::~DvppDecoder(){ - delete m_pktQueueptr; - m_pktQueueptr = nullptr; } bool DvppDecoder::init(FFDecConfig cfg){ m_dec_name = cfg.dec_name; - - ReceiverConfig receiver_config; - receiver_config.uri = cfg.uri.c_str(); - receiver_config.dec_name = cfg.dec_name; - receiver_config.force_tcp = cfg.force_tcp; - receiver_config.pktQueueptr = m_pktQueueptr; - receiver_config.receiver_finished_cbk = receiver_finish_cbk; - AVCodecContext* avctx = m_receiver.init_FFmpeg(receiver_config); + + AVCodecContext* avctx = init_FFmpeg(cfg); if(avctx == nullptr){ return false; } - m_receiver.setFinishCbkArg(this); - DvppDecConfig dec_cfg; - if(avctx->codec_id == AV_CODEC_ID_H264){ - dec_cfg.codec_id = 0; - }else if(avctx->codec_id == AV_CODEC_ID_HEVC){ - dec_cfg.codec_id = 1; - }else { - return false; - } - dec_cfg.dec_name = cfg.dec_name; - dec_cfg.post_decoded_cbk = cfg.post_decoded_cbk; - dec_cfg.dev_id = cfg.gpuid; - dec_cfg.force_tcp = cfg.force_tcp; - dec_cfg.skip_frame = cfg.skip_frame; - dec_cfg.profile = avctx->profile; - dec_cfg.pktQueueptr = m_pktQueueptr; - dec_cfg.width = avctx->width; - dec_cfg.height = avctx->height; - bool bRet = m_decoder.init_vdpp(dec_cfg); + bool bRet = init_vdpp(cfg, avctx); if(!bRet){ return false; } @@ -63,22 +62,189 @@ bool DvppDecoder::init(FFDecConfig cfg){ return true; } +AVCodecContext* DvppDecoder::init_FFmpeg(FFDecConfig config){ + +#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 9, 100) + av_register_all(); +#endif +#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 10, 100) + avcodec_register_all(); +#endif + + avformat_network_init(); + + const char* uri = config.uri.c_str(); + fstream infile(uri); + if (infile.is_open()){ + m_bReal = false; + infile.close(); + } else { + m_bReal = true; + } + + // 打开输入视频文件 + AVDictionary *options = nullptr; + av_dict_set( &options, "bufsize", "655360", 0 ); + av_dict_set( &options, "rtsp_transport", config.force_tcp ? "tcp" : "udp", 0 ); + av_dict_set( &options, "stimeout", "30000000", 0 ); // 单位为 百万分之一秒 + + const char* input_file = uri; + + do{ + fmt_ctx = avformat_alloc_context(); + if (avformat_open_input(&fmt_ctx, input_file, nullptr, &options) != 0) { + LOG_ERROR("[{}]- Cannot open input file: {}", m_dec_name, input_file); + break; + } + av_dump_format(fmt_ctx, 0, input_file, 0); + + // 查找流信息 + if (avformat_find_stream_info(fmt_ctx, nullptr) < 0) { + LOG_ERROR("[{}]- Cannot find input stream information!", m_dec_name); + break; + } + + // 查找视频流信息 + AVCodec *decoder = nullptr; + video_index = av_find_best_stream(fmt_ctx, AVMEDIA_TYPE_VIDEO, -1, -1, &decoder, 0); + if (video_index < 0) { + LOG_ERROR("[{}]- Cannot find a video stream in the input file!", m_dec_name); + break; + } + AVCodec *vcodec = avcodec_find_decoder(decoder->id); + + avctx = avcodec_alloc_context3(vcodec); + if(avctx == nullptr){ + LOG_ERROR("[{}]- alloc AVCodecContext failed!", m_dec_name); + break; + } + + // 得到视频流对象 + AVStream* stream = fmt_ctx->streams[video_index]; + AVCodecParameters *codecpar = stream->codecpar; + if (avcodec_parameters_to_context(avctx, codecpar) < 0) + break; + + const AVBitStreamFilter * filter = nullptr; + if(codecpar->codec_id == AV_CODEC_ID_H264){ + filter = av_bsf_get_by_name("h264_mp4toannexb"); + }else if(codecpar->codec_id == AV_CODEC_ID_HEVC){ + filter = av_bsf_get_by_name("hevc_mp4toannexb"); + }else { + LOG_ERROR("[{}]- codec_id is not supported!", m_dec_name); + break; + } + + int ret = av_bsf_alloc(filter, &h264bsfc); + if (ret < 0){ + break; + } + + avcodec_parameters_copy(h264bsfc->par_in, codecpar); + av_bsf_init(h264bsfc); + + frame_width = codecpar->width; + frame_height = codecpar->height; + pix_fmt = (AVPixelFormat)codecpar->format; + m_fps = av_q2d(stream ->avg_frame_rate); + + LOG_INFO("[{}]- init ffmpeg success! input:{} frame_width:{} frame_height:{} fps:{} ", m_dec_name, input_file, frame_width, frame_height, m_fps); + + return avctx; + }while(0); + + release_ffmpeg(); + + LOG_ERROR("[{}]- init ffmpeg failed ! input:{} ", m_dec_name, input_file); + + return nullptr; +} + + bool DvppDecoder::init_vdpp(FFDecConfig cfg, AVCodecContext* avctx) { + + LOG_INFO("[{}]- Init device start...", m_dec_name); + + m_dvpp_deviceId = atoi(cfg.gpuid.c_str()); + + if(avctx->codec_id == AV_CODEC_ID_H264){ + // 66:Baseline,77:Main,>=100:High + if(avctx->profile == 77){ + enType = H264_MAIN_LEVEL; + }else if(avctx->profile < 77){ + enType = H264_BASELINE_LEVEL; + }else{ + enType = H264_HIGH_LEVEL; + } + }else if(avctx->codec_id == AV_CODEC_ID_HEVC){ + // h265只有main + enType = H265_MAIN_LEVEL; + }else { + LOG_ERROR("[{}]- codec_id is not supported!", m_dec_name); + return false; + } + + post_decoded_cbk = cfg.post_decoded_cbk; + + do{ + aclError ret = aclrtSetDevice(m_dvpp_deviceId); + if(ret != ACL_ERROR_NONE){ + LOG_ERROR("[{}]-aclrtSetDevice failed !", m_dec_name); + return false; + } + + ret = aclrtCreateContext(&m_context, m_dvpp_deviceId); + if (ret != ACL_ERROR_NONE) { + LOG_ERROR("[{}]-aclrtCreateContext failed !", m_dec_name); + return false; + } + + // DvppSourceManager 创建时包含 aclInit,析构时包含 aclFinalize + DvppSourceManager* pSrcMgr = DvppSourceManager::getInstance(); + m_dvpp_channel = pSrcMgr->getChannel(m_dvpp_deviceId); + if(m_dvpp_channel < 0){ + LOG_ERROR("[{}]-该设备channel已经用完了!", m_dec_name); + return false; + } + m_vdec_out_size = avctx->width * avctx->height * 3 / 2; + + LOG_INFO("[{}]- init vdpp success! device:{} channel:{}", m_dec_name, m_dvpp_deviceId, m_dvpp_channel); + return true; + }while(0); + + release_dvpp(); + + return false; +} + bool DvppDecoder::isSurport(FFDecConfig& cfg){ return true; } bool DvppDecoder::start(){ - m_receiver.start(); - m_decoder.start(); - return true; + m_bRunning = true; + + pthread_create(&m_read_thread,0, + [](void* arg) + { + DvppDecoder* a=(DvppDecoder*)arg; + a->read_thread(); + return (void*)0; + } + ,this); + + return true; } void DvppDecoder::close(){ - m_receiver.close(); + m_bRunning=false; + + if(m_read_thread != 0){ + pthread_join(m_read_thread,0); + } } void DvppDecoder::setPostDecArg(const void* postDecArg){ - m_decoder.setPostDecArg(postDecArg); + m_postDecArg = postDecArg; } void DvppDecoder::setFinishedDecArg(const void* finishedDecArg){ @@ -86,19 +252,19 @@ void DvppDecoder::setFinishedDecArg(const void* finishedDecArg){ } void DvppDecoder::pause(){ - m_receiver.pause(); + m_bPause = true; } void DvppDecoder::resume(){ - m_receiver.resume(); + m_bPause = false; } void DvppDecoder::setDecKeyframe(bool bKeyframe){ - m_receiver.setDecKeyframe(bKeyframe); + m_dec_keyframe = bKeyframe; } bool DvppDecoder::isRunning(){ - return m_receiver.isRunning(); + return m_bRunning; } bool DvppDecoder::isFinished(){ @@ -106,32 +272,597 @@ bool DvppDecoder::isFinished(){ } bool DvppDecoder::isPausing(){ - return m_receiver.isPausing(); + return m_bPause; } bool DvppDecoder::getResolution(int &width, int &height){ - return m_receiver.getResolution(width, height); + width = frame_width; + height = frame_height; + return true; } float DvppDecoder::fps(){ - return m_receiver.fps(); + return m_fps; } DeviceMemory* DvppDecoder::snapshot(){ // 注意内部有锁 - return m_decoder.snapshot(); + // 开始抓拍 + m_bSnapShoting = true; + + std::unique_lock locker(m_cached_mutex); + while (m_cached_mem == nullptr) + m_cached_cond.wait_for(locker, std::chrono::milliseconds(400)); // Unlock mutex and wait to be notified + locker.unlock(); + + DeviceMemory* mem = m_cached_mem; + m_cached_mem = nullptr; + + return mem; } int DvppDecoder::getCachedQueueLength(){ return 0; } -void DvppDecoder::taskFinishing(){ - // receiver 中读取线程结束时执行 - m_decoder.close(); +void DvppDecoder::release_ffmpeg() { + m_dec_keyframe = false; + if(h264bsfc){ + av_bsf_free(&h264bsfc); + h264bsfc = nullptr; + } + if (fmt_ctx){ + avformat_close_input(&fmt_ctx); + fmt_ctx = nullptr; + } + if(avctx){ + avcodec_free_context(&avctx); + avctx = nullptr; + } +} + +void DvppDecoder::read_thread() { + + int frame_count = 0; + int ret = -1; + + pthread_create(&m_decode_thread,0, + [](void* arg) + { + DvppDecoder* a=(DvppDecoder*)arg; + a->decode_thread(); + return (void*)0; + } + ,this); + + AVPacket* pkt = nullptr; + while (m_bRunning){ + + if (!m_bReal){ + if (m_bPause){ + std::this_thread::sleep_for(std::chrono::milliseconds(3)); + continue; + } + } + + m_pktQueue_mutex.lock(); + if(m_pktQueue.size() > 10){ + m_pktQueue_mutex.unlock(); + std::this_thread::sleep_for(std::chrono::milliseconds(5)); + continue; + } + m_pktQueue_mutex.unlock(); + + pkt = av_packet_alloc(); + av_init_packet( pkt ); + + int result = av_read_frame(fmt_ctx, pkt); + if (result == AVERROR_EOF || result < 0){ + av_packet_free(&pkt); + pkt = nullptr; + LOG_ERROR("[{}]- Failed to read frame!", m_dec_name); + break; + } + + if (m_dec_keyframe && !(pkt->flags & AV_PKT_FLAG_KEY)) { + av_packet_free(&pkt); + pkt = nullptr; + continue; + } + + if (video_index == pkt->stream_index){ + + ret = av_bsf_send_packet(h264bsfc, pkt); + if(ret < 0) { + LOG_ERROR("[{}]- av_bsf_send_packet error!", m_dec_name); + av_packet_free(&pkt); + pkt = nullptr; + continue; + } + + bool bPushed = false; + while ((ret = av_bsf_receive_packet(h264bsfc, pkt)) == 0) { + if(pkt->size > g_pkt_size){ + LOG_ERROR("[{}]- pkt size 大于最大预设值!", m_dec_name); + break; + } + + if(!m_bRunning){ + break; + } + + m_pktQueue_mutex.lock(); + m_pktQueue.push(pkt); + m_pktQueue_mutex.unlock(); + + bPushed = true; + frame_count++; + } + + if(!bPushed){ + av_packet_free(&pkt); + pkt = nullptr; + } + } else { + // 音频等其他分量的情形 + av_packet_free(&pkt); + pkt = nullptr; + } + } + + m_bRunning=false; + + if(m_decode_thread != 0){ + pthread_join(m_decode_thread,0); + } + + m_pktQueue_mutex.lock(); + while(m_pktQueue.size() > 0){ + pkt = m_pktQueue.front(); + av_packet_free(&pkt); + pkt = nullptr; + m_pktQueue.pop(); + } + m_pktQueue_mutex.unlock(); + decode_finished_cbk(m_finishedDecArg); - m_bFinished = true; + LOG_INFO("[{}]- read thread exit.", m_dec_name); + m_bFinished = true; +} + +static void *ReportThd(void *arg) +{ + DvppDecoder *self = (DvppDecoder *)arg; + if(nullptr != self){ + self->doProcessReport(); + } + return (void *)0; +} + +void DvppDecoder::doProcessReport(){ + + aclError ret = aclrtSetDevice(m_dvpp_deviceId); + if(ret != ACL_ERROR_NONE){ + // cout << "aclrtSetDevice failed" << endl; + LOG_ERROR("aclrtSetDevice failed !"); + return ; + } + + aclrtContext ctx; + ret = aclrtCreateContext(&ctx, m_dvpp_deviceId); + if (ret != ACL_ERROR_NONE) { + // cout << "aclrtCreateContext failed " << endl; + LOG_ERROR("aclrtCreateContext failed !"); + return ; + } + + CHECK_AND_RETURN_NOVALUE(aclrtSetCurrentContext(ctx), "aclrtSetCurrentContext failed"); + // 阻塞等待vdec线程开始 + + while (!m_bExitReportThd) { + aclrtProcessReport(1000); + } + + ret = aclrtDestroyContext(ctx); + if(ret != ACL_ERROR_NONE){ + LOG_ERROR("aclrtDestroyContext failed !"); + } + LOG_INFO("doProcessReport exit."); +} + +static void VdecCallback(acldvppStreamDesc *input, acldvppPicDesc *output, void *pUserData) +{ + Vdec_CallBack_UserData *userData = (Vdec_CallBack_UserData *) pUserData; + if(nullptr != userData){ + DvppDecoder* self = userData->self; + if(self != nullptr){ + + self->doVdppVdecCallBack(input, output); + } + delete userData; + userData = nullptr; + } +} + +void DvppDecoder::doVdppVdecCallBack(acldvppStreamDesc *input, acldvppPicDesc *output){ + + m_vdecQueue_mutex.lock(); + if(m_vdecQueue.size() > 0){ + void* inputData = m_vdecQueue.front(); + acldvppFree(inputData); + inputData = nullptr; + m_vdecQueue.pop(); + } + m_vdecQueue_mutex.unlock(); + + + CHECK_AND_RETURN_NOVALUE(aclrtSetCurrentContext(m_context), "aclrtSetCurrentContext failed"); + + void *outputDataDev = acldvppGetPicDescData(output); + uint32_t outputSize = acldvppGetPicDescSize(output); + uint32_t width = acldvppGetPicDescWidth(output); + uint32_t width_stride = acldvppGetPicDescWidthStride(output); + uint32_t height = acldvppGetPicDescHeight(output); + uint32_t height_stride = acldvppGetPicDescHeightStride(output); + + do{ + int ret = acldvppGetPicDescRetCode(output); + if(ret != ACL_ERROR_NONE){ + LOG_ERROR("[{}]- decode result error, retCode:{} ", m_dec_name, ret); + acldvppFree(outputDataDev); + outputDataDev = nullptr; + break; + } + + if(width > 0 && height > 0 && outputSize > 0){ + DvppDataMemory* mem = new DvppDataMemory(width, width_stride, height, height_stride, outputSize, m_dec_name, to_string(m_dvpp_deviceId), false, (unsigned char *)outputDataDev); + if(mem){ + post_decoded_cbk(m_postDecArg, mem); + + if(m_bSnapShoting){ + // 缓存snapshot + std::unique_lock locker(m_cached_mutex); + + m_cached_mem = new DvppDataMemory(-1, width, width_stride, height, height_stride, outputSize, m_dec_name, to_string(m_dvpp_deviceId), false); + if(m_cached_mem != nullptr){ + aclrtMemcpy(m_cached_mem->getMem(), outputSize, (unsigned char *)outputDataDev, outputSize, ACL_MEMCPY_DEVICE_TO_DEVICE); + } + + locker.unlock(); + m_cached_cond.notify_one(); + m_bSnapShoting = false; + } + } else { + LOG_ERROR("[{}]- DvppDataMemory 创建失败! ", m_dec_name, ret); + acldvppFree(outputDataDev); + outputDataDev = nullptr; + } + + } else { + LOG_WARN("[{}]- decode result error, width:{} width_stride:{} height:{} height_stride:{} size:{}", m_dec_name, width, width_stride, height, height_stride, outputSize); + acldvppFree(outputDataDev); + outputDataDev = nullptr; + } + + // DvppDataMemory* rgbMem = picConverter.convert2bgr(output, width, height, false); + // if(rgbMem != nullptr){ + // #ifdef TEST_DECODER + // // D2H + // if(vdecHostAddr == nullptr){ + // CHECK_NOT_RETURN(aclrtMallocHost(&vdecHostAddr, width * height * 3), "aclrtMallocHost failed"); + // } + // uint32_t data_size = rgbMem->getSize(); + // CHECK_AND_RETURN_NOVALUE(aclrtMemcpy(vdecHostAddr, data_size, rgbMem->getMem(), data_size, ACL_MEMCPY_DEVICE_TO_HOST), "D2H aclrtMemcpy failed"); + + // // 保存vdec结果 + // if(count_frame > 45 && count_frame < 50) + // { + // string file_name = "./yuv_pic/vdec_out_"+ m_dec_name +".rgb" ; + // FILE *outputFile = fopen(file_name.c_str(), "a"); + // if(outputFile){ + // fwrite(vdecHostAddr, data_size, sizeof(char), outputFile); + // fclose(outputFile); + // } + // } + // else if(count_frame > 50 && vdecHostAddr != nullptr){ + // CHECK_NOT_RETURN(aclrtFreeHost(vdecHostAddr), "aclrtFreeHost failed"); + // vdecHostAddr = nullptr; + // } + // count_frame++; + // #endif + // post_decoded_cbk(m_postDecArg, rgbMem); + // }else{ + // LOG_ERROR("[{}]- convert2bgr failed !", m_dec_name); + // } + }while(0); + + CHECK_AND_RETURN_NOVALUE(acldvppDestroyStreamDesc(input), "acldvppDestroyStreamDesc failed"); + CHECK_AND_RETURN_NOVALUE(acldvppDestroyPicDesc(output), "acldvppDestroyPicDesc failed"); +} + +void DvppDecoder::decode_thread(){ + + long startTime = UtilTools::get_cur_time_ms(); + + int ret = -1; + + m_bExitReportThd = false; + pthread_t report_thread; + ret = pthread_create(&report_thread, nullptr, ReportThd, (void *)this); + if(ret != 0){ + LOG_ERROR("[{}]- pthread_create failed", m_dec_name); + return; + } + + aclrtSetDevice(m_dvpp_deviceId); + aclrtContext ctx; + ret = aclrtCreateContext(&ctx, m_dvpp_deviceId); + if (ret != ACL_ERROR_NONE) { + // cout << "aclrtCreateContext failed " << endl; + LOG_ERROR("aclrtCreateContext failed !"); + return ; + } + + // 创建aclvdecChannelDesc类型的数据 + aclvdecChannelDesc *vdecChannelDesc = aclvdecCreateChannelDesc(); + if (vdecChannelDesc == nullptr) { + LOG_ERROR("[{}]- aclvdecCreateChannelDesc failed", m_dec_name); + return; + } + do{ + // 创建 channel dec结构体 + // 通道ID在dvpp层面为0~31 + CHECK_AND_BREAK(aclvdecSetChannelDescChannelId(vdecChannelDesc, m_dvpp_channel), "aclvdecSetChannelDescChannelId failed"); + CHECK_AND_BREAK(aclvdecSetChannelDescThreadId(vdecChannelDesc, report_thread), "aclvdecSetChannelDescThreadId failed"); + CHECK_AND_BREAK(aclvdecSetChannelDescCallback(vdecChannelDesc, VdecCallback), "aclvdecSetChannelDescCallback failed"); + CHECK_AND_BREAK(aclvdecSetChannelDescEnType(vdecChannelDesc, enType), "aclvdecSetChannelDescEnType failed"); + CHECK_AND_BREAK(aclvdecSetChannelDescOutPicFormat(vdecChannelDesc, PIXEL_FORMAT_YUV_SEMIPLANAR_420), "aclvdecSetChannelDescOutPicFormat failed"); + CHECK_AND_BREAK(aclvdecCreateChannel(vdecChannelDesc), "aclvdecCreateChannel failed"); + + uint64_t frame_count = 0; + bool bBreak = false; + while (m_bRunning) + { + if (m_bPause){ + std::this_thread::sleep_for(std::chrono::milliseconds(3)); + continue; + } + int ret = sentFrame(vdecChannelDesc, frame_count); + if(ret == 2){ + bBreak = true; + break; + }else if(ret == 1){ + continue; + } + + frame_count++; + } + + // 尽量保证数据全部解码完成 + int sum = 0; + if(!bBreak){ + aclrtSetDevice(m_dvpp_deviceId); + aclrtSetCurrentContext(ctx); + while(m_pktQueue.size() > 0){ + int ret = sentFrame(vdecChannelDesc, frame_count); + if(ret == 2){ + break; + } + std::this_thread::sleep_for(std::chrono::milliseconds(3)); + sum++; + if(sum > 40){ + // 避免卡死 + break; + } + } + } + + sendVdecEos(vdecChannelDesc); + + CHECK_NOT_RETURN(aclvdecDestroyChannel(vdecChannelDesc), "aclvdecDestroyChannel failed"); + }while(0); + + CHECK_NOT_RETURN(aclvdecDestroyChannelDesc(vdecChannelDesc), "aclvdecDestroyChannelDesc failed"); + + // report_thread 需后于destroy退出 + m_bRunning = false; + m_bExitReportThd = true; + CHECK_NOT_RETURN(pthread_join(report_thread, nullptr), "pthread_join failed"); + + // 最后清理一遍未解码的数据 + m_vdecQueue_mutex.lock(); + if(m_vdecQueue.size() > 0){ + void* inputData = m_vdecQueue.front(); + acldvppFree(inputData); + inputData = nullptr; + m_vdecQueue.pop(); + } + m_vdecQueue_mutex.unlock(); + + release_dvpp(); + + ret = aclrtDestroyContext(ctx); + if(ret != ACL_ERROR_NONE){ + LOG_ERROR("aclrtDestroyContext failed !"); + } + + LOG_INFO("[{}]- decode thread exit.", m_dec_name); +} + +#include +#include +#include - LOG_INFO("[{}]- task finished.", m_dec_name); +static int nRecoder = 0; + + + +int DvppDecoder::sentFrame(aclvdecChannelDesc *vdecChannelDesc, uint64_t frame_count){ + + // 此处需要判断 m_vdecQueue 队列长度,避免占用过多显存 + m_vdecQueue_mutex.lock(); + if(m_vdecQueue.size() > 20){ + m_vdecQueue_mutex.unlock(); + std::this_thread::sleep_for(std::chrono::milliseconds(2)); + return 1; + } + m_vdecQueue_mutex.unlock(); + + AVPacket * pkt = nullptr; + m_pktQueue_mutex.lock(); + if(m_pktQueue.size() <= 0){ + m_pktQueue_mutex.unlock(); + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + return 1; + } + pkt = m_pktQueue.front(); + m_pktQueue.pop(); + m_pktQueue_mutex.unlock(); + + // 解码 + void *vdecInputbuf = nullptr; + int ret = acldvppMalloc((void **)&vdecInputbuf, g_pkt_size); + if(ACL_ERROR_NONE != ret){ + LOG_ERROR("[{}]- acldvppMalloc failed!, ret:{}", m_dec_name, ret); + av_packet_free(&pkt); + pkt = nullptr; + return 2; + } + + // std::ofstream outfile; + // string file_name = "./pkt/pkt"; + // file_name = file_name + to_string(nRecoder) + ".bin"; + // outfile.open(file_name.c_str(), std::ios::binary | std::ios::app); + // if (!outfile) { + // std::cerr << "Failed to open file!" << std::endl; + // return 2; + // } + + // outfile.write((const char*)pkt->data, pkt->size); + // outfile.close(); + + // nRecoder ++ ; + // if(nRecoder >= 1000){ + + // return 2; + // } + + + + ret = aclrtMemcpy(vdecInputbuf, pkt->size, pkt->data, pkt->size, ACL_MEMCPY_HOST_TO_DEVICE); + if(ACL_ERROR_NONE != ret){ + LOG_ERROR("[{}]- aclrtMemcpy failed", m_dec_name); + av_packet_free(&pkt); + pkt = nullptr; + return 2; + } + + void *vdecOutputBuf = nullptr; + ret = acldvppMalloc((void **)&vdecOutputBuf, m_vdec_out_size); + if(ret != ACL_ERROR_NONE){ + LOG_ERROR("[{}]- acldvppMalloc failed", m_dec_name); + av_packet_free(&pkt); + pkt = nullptr; + return 2; + } + + acldvppStreamDesc *input_stream_desc = nullptr; + acldvppPicDesc *output_pic_desc = nullptr; + do{ + input_stream_desc = acldvppCreateStreamDesc(); + if (input_stream_desc == nullptr) { + LOG_ERROR("[{}]- acldvppCreateStreamDesc failed", m_dec_name); + break; + } + output_pic_desc = acldvppCreatePicDesc(); + if (output_pic_desc == nullptr) { + LOG_ERROR("[{}]- acldvppCreatePicDesc failed", m_dec_name); + break; + } + CHECK_AND_BREAK(acldvppSetStreamDescData(input_stream_desc, vdecInputbuf), "acldvppSetStreamDescData failed"); + CHECK_AND_BREAK(acldvppSetStreamDescSize(input_stream_desc, pkt->size), "acldvppSetStreamDescSize failed"); + CHECK_AND_BREAK(acldvppSetPicDescData(output_pic_desc, vdecOutputBuf), "acldvppSetPicDescData failed"); + CHECK_AND_BREAK(acldvppSetPicDescSize(output_pic_desc, m_vdec_out_size), "acldvppSetPicDescSize failed"); + + Vdec_CallBack_UserData *user_data = NULL; + user_data = new Vdec_CallBack_UserData; + user_data->frameId = frame_count; + // user_data->startTime = startTime; + user_data->sendTime = UtilTools::get_cur_time_ms(); + user_data->self = this; + ret = aclvdecSendFrame(vdecChannelDesc, input_stream_desc, output_pic_desc, nullptr, reinterpret_cast(user_data)); + av_packet_free(&pkt); + pkt = nullptr; + if(ret != ACL_ERROR_NONE){ + delete user_data; + user_data = nullptr; + LOG_ERROR("[{}]- aclvdecSendFrame failed", m_dec_name); + break; + } + + m_vdecQueue_mutex.lock(); + m_vdecQueue.push(vdecInputbuf); + m_vdecQueue_mutex.unlock(); + + return 0; + }while (0); + + if(pkt != nullptr){ + av_packet_free(&pkt); + pkt = nullptr; + } + + // 报错情形 + if(input_stream_desc){ + CHECK_NOT_RETURN(acldvppDestroyStreamDesc(input_stream_desc), "acldvppDestroyStreamDesc failed"); + } + if(output_pic_desc){ + CHECK_NOT_RETURN(acldvppDestroyPicDesc(output_pic_desc), "acldvppDestroyPicDesc failed"); + } + + if (vdecOutputBuf){ + acldvppFree(vdecOutputBuf); + vdecOutputBuf = nullptr; + } + + return 1; +} + +bool DvppDecoder::sendVdecEos(aclvdecChannelDesc *vdecChannelDesc) { + // create stream desc + acldvppStreamDesc *streamInputDesc = acldvppCreateStreamDesc(); + if (streamInputDesc == nullptr) { + LOG_ERROR("[{}]- fail to create input stream desc", m_dec_name); + return false; + } + aclError ret = acldvppSetStreamDescEos(streamInputDesc, 1); + if (ret != ACL_SUCCESS) { + LOG_ERROR("[{}]- fail to set eos for stream desc, errorCode = {}", m_dec_name, static_cast(ret)); + (void)acldvppDestroyStreamDesc(streamInputDesc); + return false; + } + + // send vdec eos frame. when all vdec callback are completed, aclvdecSendFrame can be returned. + LOG_INFO("[{}]- send eos", m_dec_name); + ret = aclvdecSendFrame(vdecChannelDesc, streamInputDesc, nullptr, nullptr, nullptr); + (void)acldvppDestroyStreamDesc(streamInputDesc); + if (ret != ACL_SUCCESS) { + LOG_ERROR("[{}]- fail to send eos frame, ret={}", m_dec_name, ret); + return false; + } + + return true; +} + +void DvppDecoder::release_dvpp(){ + if(m_context){ + aclError ret = aclrtDestroyContext(m_context); + if(ret != ACL_ERROR_NONE){ + LOG_ERROR("[{}]- aclrtDestroyContext failed !", m_dec_name); + } + } + + DvppSourceManager* pSrcMgr = DvppSourceManager::getInstance(); + pSrcMgr->releaseChannel(m_dvpp_deviceId, m_dvpp_channel); } \ No newline at end of file diff --git a/src/decoder/dvpp/DvppDecoder.h b/src/decoder/dvpp/DvppDecoder.h index 3b5253b..5fb483f 100644 --- a/src/decoder/dvpp/DvppDecoder.h +++ b/src/decoder/dvpp/DvppDecoder.h @@ -1,12 +1,20 @@ #include #include "depend_headers.h" -#include "CircularQueue.hpp" -#include "FFReceiver.h" -#include "DvppDec.h" +#include "dvpp_headers.h" +#include "DvppDataMemory.hpp" + +#include +#include +#include + using namespace std; +typedef void(*RECEIVER_FINISHED_CALLBACK)(const void* userPtr); + +const int g_pkt_size = 1024 * 1024; // 单个AVPacket大小的最大值 + class DvppDecoder{ public: DvppDecoder(); @@ -44,19 +52,72 @@ public: int getCachedQueueLength(); public: - void taskFinishing(); + void doVdppVdecCallBack(acldvppStreamDesc *input, acldvppPicDesc *output); + void doProcessReport(); + +private: + AVCodecContext* init_FFmpeg(FFDecConfig config); + bool init_vdpp(FFDecConfig cfg, AVCodecContext* avctx); + void release_ffmpeg(); + void read_thread(); + + void decode_thread(); + int sentFrame(aclvdecChannelDesc *vdecChannelDesc, uint64_t frame_count); + bool sendVdecEos(aclvdecChannelDesc *vdecChannelDesc); + void release_dvpp(); private: FFDecConfig m_cfg; string m_dec_name; - CircularQueue *m_pktQueueptr; - FFReceiver m_receiver; - DvppDec m_decoder; - const void * m_finishedDecArg; DECODE_FINISHED_CALLBACK decode_finished_cbk; bool m_bFinished{false}; + bool m_bRunning{false}; + bool m_bPause{false}; + bool m_bExitReportThd{false}; + + // 读取数据 + AVStream* stream{nullptr}; + int video_index{-1}; + AVFormatContext *fmt_ctx{nullptr}; + AVPixelFormat pix_fmt; + AVCodecContext *avctx{nullptr}; + AVBSFContext * h264bsfc{nullptr}; + + int frame_width{0}; + int frame_height{0}; + bool m_bReal; // 是否实时流 + float m_fps{0.0}; + + RECEIVER_FINISHED_CALLBACK receiver_finished_cbk; + + pthread_t m_read_thread{0}; + + bool m_dec_keyframe; + + mutex m_pktQueue_mutex; + queue m_pktQueue; + + // 解码 + int m_dvpp_deviceId {-1}; + int m_dvpp_channel {-1}; + aclrtContext m_context{nullptr}; + acldvppStreamFormat enType; + + pthread_t m_decode_thread{0}; + mutex m_vdecQueue_mutex; + queue m_vdecQueue; + + const void * m_postDecArg; + POST_DECODE_CALLBACK post_decoded_cbk; + + int m_vdec_out_size {-1}; + // 截图 + bool m_bSnapShoting{false}; + DvppDataMemory* m_cached_mem{nullptr}; + mutex m_cached_mutex; + condition_variable m_cached_cond; }; \ No newline at end of file diff --git a/src/decoder/dvpp/FFReceiver.cpp b/src/decoder/dvpp/FFReceiver.cpp deleted file mode 100644 index 60e98bb..0000000 --- a/src/decoder/dvpp/FFReceiver.cpp +++ /dev/null @@ -1,300 +0,0 @@ -#include "FFReceiver.h" -#include - -const int g_pkt_size = 1024 * 1024; // 单个AVPacket大小的最大值 - -FFReceiver::FFReceiver(/* args */) -{ - fmt_ctx = nullptr; - m_bRunning = false; - - stream = nullptr; - stream_index = -1; - pix_fmt = AV_PIX_FMT_NONE; - m_dec_name = ""; - - m_bPause = false; - m_bReal = true; - - m_bFinished = false; - m_dec_keyframe = false; - m_fps = 0.0; - - m_read_thread = 0; -} - -FFReceiver::~FFReceiver() -{ - releaseFFmpeg(); - - // 这个只能放在析构函数中,因为会影响到解码类中的m_pktQueueptr队列 - // 所以应当确保在所有工作线程都退出后才释放 - for(int i = 0; i < m_vec_pkt.size(); i++){ - av_packet_free(&m_vec_pkt[i]); - } -} - -AVCodecContext* FFReceiver::init_FFmpeg(ReceiverConfig config){ - -#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 9, 100) - av_register_all(); -#endif -#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 10, 100) - avcodec_register_all(); -#endif - - avformat_network_init(); - - const char* uri = config.uri; - fstream infile(uri); - if (infile.is_open()){ - m_bReal = false; - infile.close(); - }else { - m_bReal = true; - } - - m_dec_name = config.dec_name; - m_pktQueueptr = config.pktQueueptr; - receiver_finished_cbk = config.receiver_finished_cbk; - - // 打开输入视频文件 - AVDictionary *options = nullptr; - av_dict_set( &options, "bufsize", "655360", 0 ); - av_dict_set( &options, "rtsp_transport", config.force_tcp ? "tcp" : "udp", 0 ); - av_dict_set( &options, "stimeout", "30000000", 0 ); // 单位为 百万分之一秒 - - fmt_ctx = avformat_alloc_context(); - const char* input_file = uri; - if (avformat_open_input(&fmt_ctx, input_file, nullptr, &options) != 0) { - LOG_ERROR("[{}]- Cannot open input file: {}", m_dec_name, input_file); - return nullptr; - } - av_dump_format(fmt_ctx, 0, input_file, 0); - - // 查找流信息 - if (avformat_find_stream_info(fmt_ctx, nullptr) < 0) { - LOG_ERROR("[{}]- Cannot find input stream information!", m_dec_name); - return nullptr; - } - - // 查找视频流信息 - AVCodec *decoder = nullptr; - stream_index = av_find_best_stream(fmt_ctx, AVMEDIA_TYPE_VIDEO, -1, -1, &decoder, 0); - if (stream_index < 0) { - LOG_ERROR("[{}]- Cannot find a video stream in the input file!", m_dec_name); - return nullptr; - } - AVCodec *vcodec = avcodec_find_decoder(decoder->id); - - avctx = avcodec_alloc_context3(vcodec); - if(avctx == nullptr){ - LOG_ERROR("[{}]- alloc AVCodecContext failed!", m_dec_name); - return nullptr; - } - - do{ - // 得到视频流对象 - AVStream* stream = fmt_ctx->streams[stream_index]; - AVCodecParameters *codecpar = stream->codecpar; - if (avcodec_parameters_to_context(avctx, codecpar) < 0) - break; - - const AVBitStreamFilter * filter = nullptr; - if(codecpar->codec_id == AV_CODEC_ID_H264){ - filter = av_bsf_get_by_name("h264_mp4toannexb"); - }else if(codecpar->codec_id == AV_CODEC_ID_HEVC){ - filter = av_bsf_get_by_name("hevc_mp4toannexb"); - }else { - LOG_ERROR("[{}]- codec_id is not supported!", m_dec_name); - break; - } - - int ret = av_bsf_alloc(filter, &h264bsfc); - if (ret < 0){ - break; - } - - avcodec_parameters_copy(h264bsfc->par_in, codecpar); - av_bsf_init(h264bsfc); - - frame_width = codecpar->width; - frame_height = codecpar->height; - pix_fmt = (AVPixelFormat)codecpar->format; - m_fps = av_q2d(stream ->avg_frame_rate); - - LOG_INFO("[{}]- init ffmpeg success! input:{} frame_width:{} frame_height:{} fps:{} ", m_dec_name, input_file, frame_width, frame_height, m_fps); - - for(int i = 0; i < 50; i++){ - AVPacket* pkt = av_packet_alloc(); - av_init_packet( pkt ); - m_vec_pkt.push_back(pkt); - } - m_pktQueueptr->init(m_vec_pkt); - - return avctx; - }while(0); - - LOG_ERROR("[{}]- init ffmpeg failed ! input:{} ", m_dec_name); - - return nullptr; -} - -void FFReceiver::releaseFFmpeg(){ - m_dec_keyframe = false; - if(h264bsfc){ - av_bsf_free(&h264bsfc); - h264bsfc = nullptr; - } - if (fmt_ctx){ - avformat_close_input(&fmt_ctx); - fmt_ctx = nullptr; - } - if(avctx){ - avcodec_free_context(&avctx); - avctx = nullptr; - } -} - -void FFReceiver::read_thread(){ - - int frame_count = 0; - int ret = -1; - - AVPacket* pkt; - - while (m_bRunning){ - - if (!m_bReal){ - if (m_bPause){ - std::this_thread::sleep_for(std::chrono::milliseconds(3)); - continue; - } - } - - AVPacket* pkt = m_pktQueueptr->getTail(); - if(pkt == nullptr){ - std::this_thread::sleep_for(std::chrono::milliseconds(3)); - continue; - } - - // AVPacket* pkt = av_packet_alloc(); - // av_init_packet( pkt ); - - int result = av_read_frame(fmt_ctx, pkt); - if (result == AVERROR_EOF || result < 0){ - av_packet_unref(pkt); - LOG_ERROR("[{}]- Failed to read frame!", m_dec_name); - break; - } - - // m_pktQueueptr->addTail(); - - // std::this_thread::sleep_for(std::chrono::milliseconds(1)); - // pkt = m_pktQueueptr->getHead(); - // av_packet_unref(pkt); - // m_pktQueueptr->addHead(); - - // av_packet_free(&pkt); - // pkt = nullptr; - // continue; - - if (m_dec_keyframe && !(pkt->flags & AV_PKT_FLAG_KEY)) { - av_packet_unref(pkt); - continue; - } - - if (stream_index == pkt->stream_index){ - - ret = av_bsf_send_packet(h264bsfc, pkt); - if(ret < 0) { - LOG_ERROR("[{}]- av_bsf_send_packet error!", m_dec_name); - } - - while ((ret = av_bsf_receive_packet(h264bsfc, pkt)) == 0) { - if(pkt->size > g_pkt_size){ - LOG_ERROR("[{}]- pkt size 大于最大预设值!", m_dec_name); - break; - } - - if(!m_bRunning){ - break; - } - - m_pktQueueptr->addTail(); - - frame_count++; - } - } else { - // 音频等其他分量的情形 - av_packet_unref(pkt); - } - } - - LOG_INFO("[{}]- read thread exit.", m_dec_name); - m_bFinished = true; - - receiver_finished_cbk(m_finishedReceiveArg); -} - -bool FFReceiver::start(){ - m_bRunning = true; - - pthread_create(&m_read_thread,0, - [](void* arg) - { - FFReceiver* a=(FFReceiver*)arg; - a->read_thread(); - return (void*)0; - } - ,this); - - return true; -} - -void FFReceiver::close(){ - m_bRunning=false; - - if(m_read_thread != 0){ - pthread_join(m_read_thread,0); - } -} - -float FFReceiver::fps(){ - return m_fps; -} - -bool FFReceiver::getResolution( int &width, int &height ){ - width = frame_width; - height = frame_height; - return true; -} - -void FFReceiver::pause(){ - m_bPause = true; -} - -void FFReceiver::resume(){ - m_bPause = false; -} - -void FFReceiver::setDecKeyframe(bool bKeyframe) -{ - m_dec_keyframe = bKeyframe; -} - -bool FFReceiver::isRunning(){ - return m_bRunning; -} - -bool FFReceiver::isFinished(){ - return m_bFinished; -} - -bool FFReceiver::isPausing(){ - return m_bPause; -} - -void FFReceiver::setFinishCbkArg(const void* userPtr){ - m_finishedReceiveArg = userPtr; -} \ No newline at end of file diff --git a/src/decoder/dvpp/FFReceiver.h b/src/decoder/dvpp/FFReceiver.h deleted file mode 100644 index a380628..0000000 --- a/src/decoder/dvpp/FFReceiver.h +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef __FFRECEIVER_H__ -#define __FFRECEIVER_H__ - -#include "depend_headers.h" -#include "CircularQueue.hpp" - -typedef void(*RECEIVER_FINISHED_CALLBACK)(const void* userPtr); - -struct ReceiverConfig{ - const char* uri; - string dec_name; - bool force_tcp; - CircularQueue *pktQueueptr; - RECEIVER_FINISHED_CALLBACK receiver_finished_cbk; // 解码线程结束后的回调接口 -}; - -class FFReceiver -{ -public: - FFReceiver(/* args */); - ~FFReceiver(); - - AVCodecContext* init_FFmpeg(ReceiverConfig config); - void releaseFFmpeg(); - void close(); - bool start(); - - void pause(); - void resume(); - void setDecKeyframe(bool bKeyframe); - bool isRunning(); - bool isFinished(); - bool isPausing(); - bool getResolution( int &width, int &height ); - float fps(); - - void setName(string nm){ - m_dec_name = nm; - } - - void setFinishCbkArg(const void* userPtr); - -private: - void read_thread(); - -private: - string m_dec_name; - - AVStream* stream; - int stream_index; - AVFormatContext *fmt_ctx; - AVPixelFormat pix_fmt; - int frame_width{0}; - int frame_height{0}; - - pthread_t m_read_thread; - - bool m_bRunning; - bool m_bFinished; - - bool m_bPause; - - bool m_bReal; // 是否实时流 - - float m_fps; - - FFDecConfig m_cfg; - bool m_dec_keyframe; - - AVCodecContext *avctx{nullptr}; - AVBSFContext * h264bsfc{nullptr}; - - vector m_vec_pkt; - CircularQueue *m_pktQueueptr; - - const void * m_finishedReceiveArg; - RECEIVER_FINISHED_CALLBACK receiver_finished_cbk; -}; - - -#endif \ No newline at end of file