From d248da62fff59e75b5da6d00f1cb2c727fc737ff Mon Sep 17 00:00:00 2001 From: fiss <2657262686@qq.com> Date: Fri, 17 Mar 2023 07:14:25 +0000 Subject: [PATCH] 优化代码,修正dvpp的一些bug --- src/demo/main_dvpp.cpp | 36 +++++++++++++++++------------------- src/dvpp/DvppDec.cpp | 220 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------------------------------------------------------------------------------------------------- src/dvpp/DvppDec.h | 7 ++++++- src/dvpp/DvppDecoder.cpp | 661 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ src/dvpp/DvppDecoder.h | 71 +++++++++++------------------------------------------------------------ src/dvpp/DvppDecoder2.h | 192 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ src/dvpp/DvppDecoderApi.cpp | 4 ++-- src/dvpp/DvppDecoderApi.h | 4 ++-- src/dvpp/DvppSourceManager.cpp | 5 ++++- src/dvpp/FFReceiver.cpp | 13 +++++++------ src/dvpp/VpcPicConverter.cpp | 54 +++++++++++++++++++++++++----------------------------- src/dvpp/VpcPicConverter.h | 7 ++++--- src/dvpp/dvpp_headers.h | 9 +++++++++ src/interface/FFNvDecoderManager.cpp | 2 +- 14 files changed, 272 insertions(+), 1013 deletions(-) delete mode 100644 src/dvpp/DvppDecoder2.h diff --git a/src/demo/main_dvpp.cpp b/src/demo/main_dvpp.cpp index b5366d7..7e8ef57 100644 --- a/src/demo/main_dvpp.cpp +++ b/src/demo/main_dvpp.cpp @@ -91,23 +91,11 @@ void postDecoded(const void * userPtr, DeviceRgbMemory* devFrame){ AbstractDecoder* decoder = (AbstractDecoder*)userPtr; if (decoder!= nullptr) { - // cout << "decode name: " << decoder->getName() << endl; - - // const char* gpu_pixfmt = av_get_pix_fmt_name((AVPixelFormat)gpuFrame->format); - // cout << "pixfmt: " << gpu_pixfmt << endl; - // cout << "keyframe: " << gpuFrame->key_frame << " width: " << gpuFrame->width << " height: "<< gpuFrame->height << endl; - // cout << "decode successed ✿✿ヽ(°▽°)ノ✿ " << endl; + } - int sum = sum1; - if (decoder->getName() == "dec0") - { - sum1 ++ ; - sum = sum1; - } else if (decoder->getName() == "dec2") - { - sum2 ++ ; - sum = sum2; - } + if(devFrame){ + delete devFrame; + devFrame = nullptr; } } @@ -169,7 +157,8 @@ bool decode_request_stream_cbk(const char* deviceId){ // string test_uri = "rtsp://176.10.0.2:8554/stream"; // string test_uri = "/mnt/f/fiss/test_data/h265.mp4"; // string test_uri = "rtsp://176.10.0.4:8554/stream"; -string test_uri = "rtsp://admin:admin@123456@192.168.60.176:554/cam/realmonitor?channel=1&subtype=0"; +// string test_uri = "rtsp://admin:admin@123456@192.168.60.176:554/cam/realmonitor?channel=1&subtype=0"; +string test_uri = "/home/huchunming/data/woyikewangh265.mp4"; void createDecode(int index, const char* gpu_id){ FFNvDecoderManager* pDecManager = FFNvDecoderManager::getInstance(); @@ -241,6 +230,7 @@ void createDvppDecoder(int index, char* devId, int channelId){ AbstractDecoder* decoder = pDecManager->createDecoder(config); if (!decoder) { + cout << "创建解码器失败" << endl; return ; } pDecManager->setPostDecArg(config.name, decoder); @@ -256,7 +246,7 @@ void logFF(void *, int level, const char *fmt, va_list ap) int main(int argc, char* argv[]){ - test_uri = argv[1]; + // test_uri = argv[1]; char* gpuid = argv[2]; int port = atoi(argv[3]); cout << test_uri << " gpu_id:" << gpuid << " port:" << port << endl; @@ -272,7 +262,7 @@ int main(int argc, char* argv[]){ // cudaSetDevice(atoi(gpuid)); while (true) { - std::this_thread::sleep_for(std::chrono::minutes(1)); + std::this_thread::sleep_for(std::chrono::seconds(10)); FFNvDecoderManager* pDecManager = FFNvDecoderManager::getInstance(); int count = pDecManager->count(); cout << "当前时间:" << UtilTools::get_cur_time_ms() << " 当前运行路数: " << pDecManager->count() << endl; @@ -288,6 +278,14 @@ int main(int argc, char* argv[]){ createDvppDecoder(i, gpuid, 0); i++; + createDvppDecoder(i, gpuid, 0); + i++; + createDvppDecoder(i, gpuid, 0); + i++; + + for(;i<30;i++){ + createDvppDecoder(i, gpuid, 0); + } while (true) { diff --git a/src/dvpp/DvppDec.cpp b/src/dvpp/DvppDec.cpp index a76a348..1f94c5c 100644 --- a/src/dvpp/DvppDec.cpp +++ b/src/dvpp/DvppDec.cpp @@ -1,15 +1,6 @@ #include "DvppDec.h" #include "DvppSourceManager.h" -#define CHECK_AND_RETURN(ret, message) \ - if(ret != 0) {LOG_ERROR("[{}]- {}", m_dec_name, message); return ret;} -#define CHECK_NOT_RETURN(ret, message) \ - if(ret != 0) {LOG_ERROR("[{}]- {}", m_dec_name, message);} -#define CHECK_AND_RETURN_NOVALUE(ret, message) \ - if(ret != 0) {LOG_ERROR("[{}]- {}", m_dec_name, message); return;} -#define CHECK_AND_BREAK(ret, message) \ - if(ret != 0) {LOG_ERROR("[{}]- {}", m_dec_name, message); break;} - struct Vdec_CallBack_UserData { uint64_t frameId; long startTime; @@ -22,10 +13,6 @@ struct Vdec_CallBack_UserData { } }; -#ifdef TEST_DECODER -static void *vdecHostAddr = nullptr; -#endif - static const int g_pkt_size = 1024 * 1024; DvppDec::DvppDec(){ @@ -33,11 +20,14 @@ static const int g_pkt_size = 1024 * 1024; } DvppDec::~DvppDec(){ - + releaseResource(); } bool DvppDec::init_vdpp(DvppDecConfig cfg){ - cout << "Init device....\n"; + + m_dec_name = cfg.dec_name; + + LOG_INFO("[{}]- Init device start...", m_dec_name); m_dvpp_deviceId = atoi(cfg.dev_id.c_str()); @@ -54,7 +44,7 @@ static const int g_pkt_size = 1024 * 1024; // h265只有main enType = H265_MAIN_LEVEL; }else { - cout << "codec_id is not supported!" << endl; + LOG_ERROR("[{}]- codec_id is not supported!", m_dec_name); return false; } @@ -66,42 +56,47 @@ static const int g_pkt_size = 1024 * 1024; m_context = pSrcMgr->getContext(m_dvpp_deviceId); m_dvpp_channel = pSrcMgr->getChannel(m_dvpp_deviceId); if(m_dvpp_channel < 0){ - cout << "该设备channel已经用完了" << endl; + LOG_ERROR("[{}]-该设备channel已经用完了!", m_dec_name); return false; } - cout << "devProgram start, device: " << m_dvpp_deviceId << endl; - int ret = aclrtSetCurrentContext(m_context); - if (ret != ACL_ERROR_NONE) { - cout << "aclrtSetCurrentContext failed" << endl; - return false; - } - - // queue_size 最小应大于16,否则关键帧之间距离太远的时候会导致回调函数与循环队列卡死 - for (size_t i = 0; i < 20; i++){ - void *vdecInputbuf = nullptr; - int ret = acldvppMalloc((void **)&vdecInputbuf, g_pkt_size); - if(ret != ACL_ERROR_NONE){ - cout << "acldvppMalloc failed" << endl; - return false;; - } - m_vec_vdec.push_back(vdecInputbuf); - } + do + { + CHECK_AND_BREAK(aclrtSetCurrentContext(m_context), "aclrtSetCurrentContext failed !"); - if(!m_vdecQueue.init(m_vec_vdec)){ - return false; - } + int ret = picConverter.init(m_context, m_dec_name); + if(ret != ACL_ERROR_NONE){ + LOG_ERROR("[{}]- acldvppMalloc failed!, ret:{}", m_dec_name, ret); + break; + } - ret = picConverter.init(m_context); - if(!ret){ - picConverter.release(); - } + // 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); + } - m_vdec_out_size = cfg.width * cfg.height * 3 / 2; - m_dec_name = cfg.dec_name; + if(!m_vdecQueue.init(m_vec_vdec)){ + break; + } - cout << "init vdpp success!" << endl; - return true; + 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(){ @@ -139,22 +134,18 @@ void DvppDec::doProcessReport(){ } } -static int count_frame = 0; -static long lastts = 0; static void VdecCallback(acldvppStreamDesc *input, acldvppPicDesc *output, void *pUserData) { - cout << "VdecCallback: " << UtilTools::get_cur_time_ms() - lastts << endl; - lastts = UtilTools::get_cur_time_ms(); - Vdec_CallBack_UserData *userData = (Vdec_CallBack_UserData *) pUserData; - DvppDec* self = userData->self; - if(self != nullptr){ + if(nullptr != userData){ + DvppDec* self = userData->self; + if(self != nullptr){ - self->doVdppVdecCallBack(input, output); - } - - delete userData; - userData = nullptr; + self->doVdppVdecCallBack(input, output); + } + delete userData; + userData = nullptr; + } } void DvppDec::doVdppVdecCallBack(acldvppStreamDesc *input, acldvppPicDesc *output){ @@ -166,43 +157,38 @@ void DvppDec::doVdppVdecCallBack(acldvppStreamDesc *input, acldvppPicDesc *outpu uint32_t outputSize = acldvppGetPicDescSize(output); uint32_t width = acldvppGetPicDescWidth(output); uint32_t height = acldvppGetPicDescHeight(output); - - cout << "width = " << width << " height = " << height << " data_size:" << outputSize << endl; - if (!m_bPause) - { - DvppRgbMemory* rgbMem = picConverter.convert2bgr(output, width, height, false); - post_decoded_cbk(m_postDecArg, rgbMem); + + DvppRgbMemory* rgbMem = picConverter.convert2bgr(output, width, height, false); + if(rgbMem != nullptr){ #ifdef TEST_DECODER - if(rgbMem != nullptr){ - // 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; + // 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); } - count_frame++; - } + } + else if(count_frame > 50 && vdecHostAddr != nullptr){ + CHECK_NOT_RETURN(aclrtFreeHost(vdecHostAddr), "aclrtFreeHost failed"); + vdecHostAddr = nullptr; + } + count_frame++; #endif - - }else{ - std::this_thread::sleep_for(std::chrono::milliseconds(3)); - } + post_decoded_cbk(m_postDecArg, rgbMem); + }else{ + LOG_ERROR("[{}]- convert2bgr failed !", m_dec_name); + } acldvppFree((uint8_t*)outputDataDev); outputDataDev = nullptr; @@ -211,8 +197,6 @@ void DvppDec::doVdppVdecCallBack(acldvppStreamDesc *input, acldvppPicDesc *outpu CHECK_AND_RETURN_NOVALUE(acldvppDestroyStreamDesc(input), "acldvppDestroyStreamDesc failed"); CHECK_AND_RETURN_NOVALUE(acldvppDestroyPicDesc(output), "acldvppDestroyPicDesc failed"); - - cout << "callback exit." << endl; } void DvppDec::close(){ @@ -227,21 +211,21 @@ bool DvppDec::sendVdecEos(aclvdecChannelDesc *vdecChannelDesc){ // create stream desc acldvppStreamDesc *streamInputDesc = acldvppCreateStreamDesc(); if (streamInputDesc == nullptr) { - cout << "fail to create input stream desc" << endl; + LOG_ERROR("[{}]- fail to create input stream desc", m_dec_name); return false; } aclError ret = acldvppSetStreamDescEos(streamInputDesc, 1); if (ret != ACL_SUCCESS) { - cout << "fail to set eos for stream desc, errorCode = " << static_cast(ret) << endl; + 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. - cout << "send eos" << endl; + LOG_INFO("[{}]- send eos", m_dec_name); ret = aclvdecSendFrame(vdecChannelDesc, streamInputDesc, nullptr, nullptr, nullptr); if (ret != ACL_SUCCESS) { - cout << "fail to send eos frame, ret=" << ret << endl; + LOG_ERROR("[{}]- fail to send eos frame, ret={}", m_dec_name, ret); (void)acldvppDestroyStreamDesc(streamInputDesc); return false; } @@ -251,7 +235,6 @@ bool DvppDec::sendVdecEos(aclvdecChannelDesc *vdecChannelDesc){ } void DvppDec::releaseResource(){ - for(int i = 0; i < m_vec_vdec.size(); i++){ if(m_vec_vdec[i] != nullptr){ acldvppFree(m_vec_vdec[i]); @@ -277,14 +260,14 @@ void DvppDec::decode_thread(){ pthread_t report_thread; ret = pthread_create(&report_thread, nullptr, ReportThd, (void *)this); if(ret != 0){ - cout << "pthread_create failed" << endl; + LOG_ERROR("[{}]- pthread_create failed", m_dec_name); return; } // 创建aclvdecChannelDesc类型的数据 aclvdecChannelDesc *vdecChannelDesc = aclvdecCreateChannelDesc(); if (vdecChannelDesc == nullptr) { - cout << "aclvdecCreateChannelDesc failed"; + LOG_ERROR("[{}]- aclvdecCreateChannelDesc failed", m_dec_name); return; } do{ @@ -301,6 +284,10 @@ void DvppDec::decode_thread(){ bool bBreak = false; while (m_bRunning) { + if (m_bPause){ + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + continue; + } int ret = sentFrame(vdecChannelDesc, frame_count); if(ret == 2){ break; @@ -341,7 +328,8 @@ void DvppDec::decode_thread(){ m_bExitReportThd = true; CHECK_NOT_RETURN(pthread_join(report_thread, nullptr), "pthread_join failed"); - cout << "decode thread exit." << endl; + releaseResource(); + LOG_INFO("[{}]- decode thread exit.", m_dec_name); } int DvppDec::sentFrame(aclvdecChannelDesc *vdecChannelDesc, uint64_t frame_count){ @@ -349,41 +337,41 @@ 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)); - // cout << "getTail failed" << endl; - // continue; return 1; } // 解码 void *vdecInputbuf = m_vdecQueue.getTail(); if(vdecInputbuf == nullptr){ std::this_thread::sleep_for(std::chrono::milliseconds(3)); - // cout << "getTail failed" << endl; - // continue; return 1; } int ret = aclrtMemcpy(vdecInputbuf, pkt->size, pkt->data, pkt->size, ACL_MEMCPY_HOST_TO_DEVICE); if(ACL_ERROR_NONE != ret){ - cout << "aclrtMemcpy failed" << endl; - // break; + 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){ - cout << "acldvppMalloc failed" << endl; - // break; + 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) { cout << "acldvppCreateStreamDesc error" << endl; } + 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) { cout<< "acldvppCreatePicDesc error" << endl; } + 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"); @@ -395,12 +383,13 @@ int DvppDec::sentFrame(aclvdecChannelDesc *vdecChannelDesc, uint64_t 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){ - cout << "aclvdecSendFrame failed" << endl; - m_pktQueueptr->addHead(); - av_packet_unref(pkt); + delete user_data; + user_data = nullptr; + LOG_ERROR("[{}]- aclvdecSendFrame failed", m_dec_name); break; } @@ -409,6 +398,7 @@ int DvppDec::sentFrame(aclvdecChannelDesc *vdecChannelDesc, uint64_t frame_count return 0; }while (0); + // 报错情形 if(input_stream_desc){ CHECK_NOT_RETURN(acldvppDestroyStreamDesc(input_stream_desc), "acldvppDestroyStreamDesc failed"); } diff --git a/src/dvpp/DvppDec.h b/src/dvpp/DvppDec.h index 08bde3a..adc9dda 100644 --- a/src/dvpp/DvppDec.h +++ b/src/dvpp/DvppDec.h @@ -14,7 +14,6 @@ using namespace std; #define TEST_DECODER - struct DvppDecConfig{ string dec_name; POST_DECODE_CALLBACK post_decoded_cbk; // 解码数据回调接口 @@ -77,4 +76,10 @@ private: VpcPicConverter picConverter; int m_vdec_out_size {-1}; + +#ifdef TEST_DECODER + void *vdecHostAddr = nullptr; + int count_frame = 0; +#endif + }; \ No newline at end of file diff --git a/src/dvpp/DvppDecoder.cpp b/src/dvpp/DvppDecoder.cpp index efa52ea..45c4738 100644 --- a/src/dvpp/DvppDecoder.cpp +++ b/src/dvpp/DvppDecoder.cpp @@ -1,629 +1,120 @@ #include "DvppDecoder.h" -#include "DvppSourceManager.h" -#define CHECK_AND_RETURN(ret, message) \ - if(ret != 0) {cout << "device: " << m_dvpp_deviceId << ", chn: " << m_dvpp_channel << ", ret: " << ret << ", [ERROR] " << message; return ret;} -#define CHECK_NOT_RETURN(ret, message) \ - if(ret != 0) {cout << "device: " << m_dvpp_deviceId << ", chn: " << m_dvpp_channel << ", ret: " << ret << ", [ERROR] " << message;} -#define CHECK_AND_RETURN_NOVALUE(ret, message) \ - if(ret != 0) {cout << "device: " << m_dvpp_deviceId << ", chn: " << m_dvpp_channel << ", ret: " << ret << ", [ERROR] " << message; return;} - - - -struct Vdec_CallBack_UserData { - uint64_t frameId; - long startTime; - long sendTime; - // void* vdecOutputBuf; - DvppDecoder* self; - shared_ptr inBufNode; - Vdec_CallBack_UserData() { - frameId = 0; +void receiver_finish_cbk(const void* userPtr){ + if(userPtr != nullptr){ + DvppDecoder* self = (DvppDecoder*)userPtr; + self->taskFinishing(); } -}; - - -const int g_pkt_que_size = 10; -const int g_pkt_size = 1024 * 1024; - -#ifdef TEST_DECODER -void *vdecHostAddr; -#endif - -static long GetCurTimeUs(){ - chrono::time_point tpMicro - = chrono::time_point_cast(chrono::system_clock::now()); - - return tpMicro.time_since_epoch().count(); } -DvppDecoder::DvppDecoder() -{ - // 初始化解码对象 - 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_decode_thread = 0; - m_post_decode_thread = 0; - - m_bFinished = false; - m_dec_keyframe = false; - m_fps = 0.0; +DvppDecoder::DvppDecoder(){ + m_pktQueueptr = new CircularQueue(); } -DvppDecoder::~DvppDecoder() -{ - m_dec_keyframe = false; - releaseResource(); +DvppDecoder::~DvppDecoder(){ + delete m_pktQueueptr; + m_pktQueueptr = nullptr; } -bool DvppDecoder::init_FFmpeg(const char* uri, bool force_tcp){ - -#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(); - - // 打开输入视频文件 - AVDictionary *options = nullptr; - av_dict_set( &options, "bufsize", "655360", 0 ); - av_dict_set( &options, "rtsp_transport", force_tcp ? "tcp" : "udp", 0 ); - // av_dict_set( &options, "listen_timeout", "30", 0 ); // 单位为s - 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) { - cout << "Cannot open input file:" << input_file << endl; - return false; - } - av_dump_format(fmt_ctx, 0, input_file, 0); - - // 查找流信息 - if (avformat_find_stream_info(fmt_ctx, nullptr) < 0) { - cout << "Cannot find input stream information" << endl; - return false; - } - - // 查找视频流信息 - AVCodec *decoder = nullptr; - stream_index = av_find_best_stream(fmt_ctx, AVMEDIA_TYPE_VIDEO, -1, -1, &decoder, 0); - if (stream_index < 0) { - cout << "Cannot find a video stream in the input file" << endl; - return false; - } - AVCodec *vcodec = avcodec_find_decoder(decoder->id); - - AVCodecContext *avctx = avcodec_alloc_context3(vcodec); - if(avctx == nullptr){ - cout << "alloc AVCodecContext failed." << endl; - return false; - } - - 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){ - // 66:Baseline,77:Main,>=100:High - if(codecpar->profile == 77){ - enType = H264_MAIN_LEVEL; - }else if(codecpar->profile < 77){ - enType = H264_BASELINE_LEVEL; - }else{ - enType = H264_HIGH_LEVEL; - } - filter = av_bsf_get_by_name("h264_mp4toannexb"); - }else if(codecpar->codec_id == AV_CODEC_ID_HEVC){ - // h265只有main - enType = H265_MAIN_LEVEL; - filter = av_bsf_get_by_name("hevc_mp4toannexb"); - }else { - cout << "codec_id is not supported!" << endl; - 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); - - m_vdec_out_size = frame_width * frame_height * 3 /2; - - cout << "frame_width = " << frame_width << " frame_height = " << frame_height << " fps = " << m_fps << " m_vdec_out_size:" << m_vdec_out_size << endl; - - cout << "init ffmpeg success!" << endl; - - return true; - }while(0); - - avcodec_free_context(&avctx); - - return false; -} - -static void *ReportThd(void *arg) -{ - DvppDecoder *self = (DvppDecoder *)arg; - if(nullptr != self){ - self->doProcessReport(); - } - return (void *)0; -} - -void DvppDecoder::doProcessReport(){ - // aclrtContext thdContext = nullptr; - // CHECK_AND_RETURN_NOVALUE(aclrtCreateContext(&thdContext, m_dvpp_deviceId), "aclrtCreateContext failed"); - - CHECK_AND_RETURN_NOVALUE(aclrtSetCurrentContext(m_context), "aclrtSetCurrentContext failed"); - // 阻塞等待vdec线程开始 - - int ret; - while (m_bRunning) { - ret = aclrtProcessReport(1000); - if (ret != ACL_ERROR_NONE) { - cout << "device: " << m_dvpp_deviceId << ", chn: " << m_dvpp_channel << ", aclrtProcessReport failed, ret: " << ret << endl; - } - } - - // CHECK_AND_RETURN_NOVALUE(aclrtDestroyContext(thdContext), "aclrtDestroyContext failed"); -} - -int count_frame = 0; -long lastts = 0; -static void VdecCallback(acldvppStreamDesc *input, acldvppPicDesc *output, void *pUserData) -{ - cout << "VdecCallback: " << GetCurTimeUs() - lastts << endl; - lastts = GetCurTimeUs(); - - Vdec_CallBack_UserData *userData = (Vdec_CallBack_UserData *) pUserData; - DvppDecoder* self = userData->self; - if(self != nullptr){ - - self->doVdppVdecCallBack(input, output, self); - } - - delete userData; - userData = nullptr; -} - -void DvppDecoder::doVdppVdecCallBack(acldvppStreamDesc *input, acldvppPicDesc *output, DvppDecoder *self){ - - 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 height = acldvppGetPicDescHeight(output); - - cout << "width = " << width << " height = " << height << " data_size:" << outputSize << endl; - - if (!m_bPause) - { - DeviceRgbMemory* rgbMem = picConverter.convert2bgr(output, width, height, false); -#ifdef TEST_DECODER - if(rgbMem != nullptr){ - // D2H - 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"+ getName() +".rgb" ; - FILE *outputFile = fopen(file_name.c_str(), "a"); - if(outputFile){ - fwrite(vdecHostAddr, data_size, sizeof(char), outputFile); - fclose(outputFile); - } - } - count_frame++; - } -#endif - - }else{ - std::this_thread::sleep_for(std::chrono::milliseconds(3)); - } - - cout << "callback acldvppFree." << endl; - - acldvppFree((uint8_t*)outputDataDev); - outputDataDev = nullptr; - - m_vdecQueue.addHead(); - - CHECK_AND_RETURN_NOVALUE(acldvppDestroyStreamDesc(input), "acldvppDestroyStreamDesc failed"); - CHECK_AND_RETURN_NOVALUE(acldvppDestroyPicDesc(output), "acldvppDestroyPicDesc failed"); - - cout << "callback exit." << endl; -} - -bool DvppDecoder::init_vdpp(int devId){ - cout << "Init device....\n"; - // 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){ - cout << "该设备channel已经用完了" << endl; - return false; - } - - cout << "devProgram start, device: " << m_dvpp_deviceId << endl; - int ret = aclrtSetCurrentContext(m_context); - if (ret != ACL_ERROR_NONE) { - cout << "aclrtSetCurrentContext failed" << endl; - return false; - } - - // queue_size 最小应大于16,否则关键帧之间距离太远的时候会导致回调函数与循环队列卡死 - for (size_t i = 0; i < 20; i++){ - void *vdecInputbuf = nullptr; - int ret = acldvppMalloc((void **)&vdecInputbuf, g_pkt_size); - if(ret != ACL_ERROR_NONE){ - cout << "acldvppMalloc failed" << endl; - return false;; - } - m_vec_vdec.push_back(vdecInputbuf); - } - - if(!m_vdecQueue.init(m_vec_vdec)){ - return false; - } - -#ifdef TEST_DECODER - CHECK_NOT_RETURN(aclrtMallocHost(&vdecHostAddr, frame_width * frame_height * 3), "aclrtMallocHost failed"); -#endif - - cout << "init vdpp success!" << endl; - return true; -} - -bool DvppDecoder::init(FFDecConfig& cfg){ - m_cfg = cfg; - - fstream infile(cfg.uri); - if (infile.is_open()){ - m_bReal = false; - infile.close(); - }else { - m_bReal = true; - } - - post_decoded_cbk = cfg.post_decoded_cbk; - decode_finished_cbk = cfg.decode_finished_cbk; - - bool ret = init_FFmpeg(cfg.uri.c_str(), cfg.force_tcp); - if(!ret){ - return false; - } - - m_dvpp_deviceId = atoi(cfg.gpuid.c_str()); - ret = init_vdpp(m_dvpp_deviceId); - if (!ret) - { - releaseFFmpeg(); - } +bool DvppDecoder::init(FFDecConfig cfg){ - ret = picConverter.init(m_context); - if(!ret){ - picConverter.release(); - } - - return ret; -} - -bool DvppDecoder::start(){ - m_bRunning = true; - - pthread_create(&m_decode_thread,0, - [](void* arg) - { - DvppDecoder* a=(DvppDecoder*)arg; - a->decode_thread(); - return (void*)0; - } - ,this); - - return true; -} - -void DvppDecoder::close(){ - m_bRunning=false; - - if(m_decode_thread != 0){ - pthread_join(m_decode_thread,0); - } - -#ifdef TEST_DECODER - if(vdecHostAddr != nullptr){ - CHECK_NOT_RETURN(aclrtFreeHost(vdecHostAddr), "aclrtFreeHost failed"); - } -#endif -} - -bool DvppDecoder::sendVdecEos(aclvdecChannelDesc *vdecChannelDesc){ - // create stream desc - acldvppStreamDesc *streamInputDesc = acldvppCreateStreamDesc(); - if (streamInputDesc == nullptr) { - cout << "fail to create input stream desc" << endl; + 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); + if(avctx == nullptr){ return false; } - aclError ret = acldvppSetStreamDescEos(streamInputDesc, 1); - if (ret != ACL_SUCCESS) { - cout << "fail to set eos for stream desc, errorCode = " << static_cast(ret) << endl; - (void)acldvppDestroyStreamDesc(streamInputDesc); + 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; } - - // send vdec eos frame. when all vdec callback are completed, aclvdecSendFrame can be returned. - ret = aclvdecSendFrame(vdecChannelDesc, streamInputDesc, nullptr, nullptr, nullptr); - if (ret != ACL_SUCCESS) { - cout << "fail to send eos frame, ret=" << ret << endl; - (void)acldvppDestroyStreamDesc(streamInputDesc); + 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); + if(!bRet){ return false; } - (void)acldvppDestroyStreamDesc(streamInputDesc); - - return true; -} -void DvppDecoder::releaseFFmpeg(){ - m_dec_keyframe = false; - if(h264bsfc){ - av_bsf_free(&h264bsfc); - h264bsfc = nullptr; - } - if (fmt_ctx) - { - avformat_close_input(&fmt_ctx); - fmt_ctx = nullptr; - } -} + m_cfg = cfg; -void DvppDecoder::releaseResource(){ - releaseFFmpeg(); + decode_finished_cbk = cfg.decode_finished_cbk; - for(int i = 0; i < m_vec_vdec.size(); i++){ - if(m_vec_vdec[i] != nullptr){ - acldvppFree((uint8_t*)m_vec_vdec[i]); - m_vec_vdec[i] = nullptr; - } - } - m_vec_vdec.clear(); + m_bFinished = false; - DvppSourceManager* pSrcMgr = DvppSourceManager::getInstance(); - pSrcMgr->releaseChannel(m_dvpp_deviceId, m_dvpp_channel); + return true; } -void DvppDecoder::decode_thread(){ - - int frame_count = 0; - long startTime = GetCurTimeUs(); - - int ret = -1; - - // dvpp解码参数 - CHECK_AND_RETURN_NOVALUE(aclrtSetCurrentContext(m_context), "aclrtSetCurrentContext failed"); - - pthread_t report_thread; - ret = pthread_create(&report_thread, nullptr, ReportThd, (void *)this); - if(ret != 0){ - cout << "pthread_create failed" << endl; - return; - } - - // 创建aclvdecChannelDesc类型的数据 - aclvdecChannelDesc *vdecChannelDesc = aclvdecCreateChannelDesc(); - if (vdecChannelDesc == nullptr) { - cout << "aclvdecCreateChannelDesc failed"; - return; - } - // 创建 channel dec结构体 - // 通道ID在dvpp层面为0~31 - CHECK_AND_RETURN_NOVALUE(aclvdecSetChannelDescChannelId(vdecChannelDesc, m_dvpp_channel), "aclvdecSetChannelDescChannelId failed"); - CHECK_AND_RETURN_NOVALUE(aclvdecSetChannelDescThreadId(vdecChannelDesc, report_thread), "aclvdecSetChannelDescThreadId failed"); - CHECK_AND_RETURN_NOVALUE(aclvdecSetChannelDescCallback(vdecChannelDesc, VdecCallback), "aclvdecSetChannelDescCallback failed"); - CHECK_AND_RETURN_NOVALUE(aclvdecSetChannelDescEnType(vdecChannelDesc, enType), "aclvdecSetChannelDescEnType failed"); - CHECK_AND_RETURN_NOVALUE(aclvdecSetChannelDescOutPicFormat(vdecChannelDesc, PIXEL_FORMAT_YUV_SEMIPLANAR_420), "aclvdecSetChannelDescOutPicFormat failed"); - CHECK_AND_RETURN_NOVALUE(aclvdecCreateChannel(vdecChannelDesc), "aclvdecCreateChannel failed"); - - AVPacket* pkt ; - pkt = av_packet_alloc(); - av_init_packet( pkt ); - - acldvppStreamDesc *input_stream_desc = nullptr; - acldvppPicDesc *output_pic_desc = nullptr; - - void *vdecInputbuf = nullptr; - void *vdecOutputBuf = nullptr; - while (m_bRunning) - { - if (!m_bReal) - { - if (m_bPause) - { - std::this_thread::sleep_for(std::chrono::milliseconds(3)); - continue; - } - } - - int result = av_read_frame(fmt_ctx, pkt); - if (result == AVERROR_EOF || result < 0) - { - cout << "Failed to read frame!" << endl; - break; - } - - 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) { - cout << "av_bsf_send_packet error" << endl; - } - - while ((ret = av_bsf_receive_packet(h264bsfc, pkt)) == 0) { - // 解码 - - if(pkt->size > g_pkt_size){ - cout << "pkt size 大于 预设" << endl; - break; - } - - if(!m_bRunning){ - break; - } - - vdecInputbuf = m_vdecQueue.getTail(); - if(vdecInputbuf == nullptr){ - std::this_thread::sleep_for(std::chrono::milliseconds(3)); - // cout << "getTail failed" << endl; - continue; - } - - ret = aclrtMemcpy(vdecInputbuf, pkt->size, pkt->data, pkt->size, ACL_MEMCPY_HOST_TO_DEVICE); - if(ACL_ERROR_NONE != ret){ - cout << "aclrtMemcpy failed" << endl; - goto end_flag; - } - - ret = acldvppMalloc((void **)&vdecOutputBuf, m_vdec_out_size); - if(ret != ACL_ERROR_NONE){ - cout << "acldvppMalloc failed" << endl; - goto end_flag; - } - - /************ 解码*************/ - input_stream_desc = acldvppCreateStreamDesc(); - if (input_stream_desc == nullptr) { cout << "acldvppCreateStreamDesc error" << endl; } - output_pic_desc = acldvppCreatePicDesc(); - if (output_pic_desc == nullptr) { cout<< "acldvppCreatePicDesc error" << endl; } - CHECK_NOT_RETURN(acldvppSetStreamDescData(input_stream_desc, vdecInputbuf), "acldvppSetStreamDescData failed"); - CHECK_NOT_RETURN(acldvppSetStreamDescSize(input_stream_desc, pkt->size), "acldvppSetStreamDescSize failed"); - CHECK_NOT_RETURN(acldvppSetPicDescData(output_pic_desc, vdecOutputBuf), "acldvppSetPicDescData failed"); - CHECK_NOT_RETURN(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 = GetCurTimeUs(); - user_data->self = this; - // user_data->inBufNode = bufNode; - cout << "send frame" << endl; - CHECK_NOT_RETURN(aclvdecSendFrame(vdecChannelDesc, input_stream_desc, output_pic_desc, nullptr, reinterpret_cast(user_data)), - "aclvdecSendFrame failed"); - - frame_count++; - - m_vdecQueue.addTail(); - - vdecInputbuf = nullptr; - vdecOutputBuf = nullptr; - } - /****************************/ - } - av_packet_unref(pkt); - } - -end_flag: - - av_packet_free(&pkt); - - sendVdecEos(vdecChannelDesc); - - CHECK_NOT_RETURN(aclvdecDestroyChannel(vdecChannelDesc), "aclvdecDestroyChannel failed"); - CHECK_NOT_RETURN(aclvdecDestroyChannelDesc(vdecChannelDesc), "aclvdecDestroyChannelDesc failed"); - - // report_thread 需后于destroy退出 - m_bRunning = false; - CHECK_NOT_RETURN(pthread_join(report_thread, nullptr), "pthread_join failed"); - - if(m_vdecQueue.length() > 0){ - cout << m_vdecQueue.length() << endl; - } - - if(vdecOutputBuf != nullptr){ - acldvppFree((uint8_t*)vdecOutputBuf); - vdecOutputBuf = nullptr; - } +bool DvppDecoder::isSurport(FFDecConfig& cfg){ + return true; +} - cout << "read thread exit." << endl; +bool DvppDecoder::start(){ + m_receiver.start(); + m_decoder.start(); + return true; } -float DvppDecoder::fps(){ - return m_fps; +void DvppDecoder::close(){ + m_receiver.close(); } -bool DvppDecoder::isSurport(FFDecConfig& cfg){ - bool bRet = init(cfg); - return bRet; +void DvppDecoder::setPostDecArg(const void* postDecArg){ + m_decoder.setPostDecArg(postDecArg); } -bool DvppDecoder::getResolution( int &width, int &height ){ - width = frame_width; - height = frame_height; - return true; +void DvppDecoder::setFinishedDecArg(const void* finishedDecArg){ + m_finishedDecArg = finishedDecArg; } void DvppDecoder::pause(){ - m_bPause = true; + m_receiver.pause(); } void DvppDecoder::resume(){ - m_bPause = false; + m_receiver.resume(); } -void DvppDecoder::setDecKeyframe(bool bKeyframe) -{ - m_dec_keyframe = bKeyframe; +void DvppDecoder::setDecKeyframe(bool bKeyframe){ + m_receiver.setDecKeyframe(bKeyframe); } bool DvppDecoder::isRunning(){ - return m_bRunning; + return m_receiver.isRunning(); } bool DvppDecoder::isFinished(){ - return m_bFinished; + return m_bFinished; } bool DvppDecoder::isPausing(){ - return m_bPause; + return m_receiver.isPausing(); } -int DvppDecoder::getCachedQueueLength(){ - // TODO - return 0; +bool DvppDecoder::getResolution(int &width, int &height){ + return m_receiver.getResolution(width, height); +} + +float DvppDecoder::fps(){ + return m_receiver.fps(); } FFImgInfo* DvppDecoder::snapshot(){ @@ -631,10 +122,16 @@ FFImgInfo* DvppDecoder::snapshot(){ return nullptr; } -void DvppDecoder::setPostDecArg(const void* postDecArg){ - m_postDecArg = postDecArg; +int DvppDecoder::getCachedQueueLength(){ + return 0; } -void DvppDecoder::setFinishedDecArg(const void* finishedDecArg){ - m_finishedDecArg = finishedDecArg; +void DvppDecoder::taskFinishing(){ + // receiver 中读取线程结束时执行 + m_decoder.close(); + decode_finished_cbk(m_finishedDecArg); + + m_bFinished = true; + + LOG_INFO("[{}]- task finished.", m_dec_name); } \ No newline at end of file diff --git a/src/dvpp/DvppDecoder.h b/src/dvpp/DvppDecoder.h index db5064b..c6b32fd 100644 --- a/src/dvpp/DvppDecoder.h +++ b/src/dvpp/DvppDecoder.h @@ -1,24 +1,17 @@ #include -#include -#include "dvpp_headers.h" #include "depend_headers.h" -#include "user_mem.h" #include "CircularQueue.hpp" -#include "VpcPicConverter.h" - -#include +#include "FFReceiver.h" +#include "DvppDec.h" using namespace std; -#define TEST_DECODER - - class DvppDecoder{ public: DvppDecoder(); ~DvppDecoder(); - bool init(FFDecConfig& cfg); + bool init(FFDecConfig cfg); void close(); bool start(); void pause(); @@ -33,12 +26,8 @@ public: bool isSurport(FFDecConfig& cfg); - int getCachedQueueLength(); - float fps(); - DECODER_TYPE getDecoderType(){ return DECODER_TYPE_DVPP; } - void setName(string nm){ m_dec_name = nm; } @@ -52,60 +41,22 @@ public: void setPostDecArg(const void* postDecArg); void setFinishedDecArg(const void* finishedDecArg); -public: - void doProcessReport(); - void doVdppVdecCallBack(acldvppStreamDesc *input, acldvppPicDesc *output, DvppDecoder *self); - -private: - void decode_thread(); - void post_decode_thread(); - void releaseFFmpeg(); - void releaseResource(); - bool init_FFmpeg(const char* uri, bool force_tcp); - bool init_vdpp(int _deviceId); + int getCachedQueueLength(); - bool sendVdecEos(aclvdecChannelDesc *vdecChannelDesc); +public: + void taskFinishing(); private: - AVStream* stream; - int stream_index; - AVFormatContext *fmt_ctx; - AVPixelFormat pix_fmt; - uint32_t m_vdec_out_size{0}; - int frame_width{0}; - int frame_height{0}; - - int m_dvpp_deviceId {-1}; - int m_dvpp_channel {-1}; - - pthread_t m_decode_thread; - pthread_t m_post_decode_thread; - - bool m_bRunning; - bool m_bFinished; - - bool m_bPause; - - bool m_bReal; // 是否实时流 - - float m_fps; - FFDecConfig m_cfg; string m_dec_name; - bool m_dec_keyframe; - - AVBSFContext * h264bsfc{nullptr}; - aclrtContext m_context; - acldvppStreamFormat enType; + CircularQueue *m_pktQueueptr; + FFReceiver m_receiver; + DvppDec m_decoder; - vector m_vec_vdec; - CircularQueue m_vdecQueue; - - const void * m_postDecArg; - POST_DECODE_CALLBACK post_decoded_cbk; const void * m_finishedDecArg; DECODE_FINISHED_CALLBACK decode_finished_cbk; - VpcPicConverter picConverter; + bool m_bFinished{false}; + }; \ No newline at end of file diff --git a/src/dvpp/DvppDecoder2.h b/src/dvpp/DvppDecoder2.h deleted file mode 100644 index d044f9b..0000000 --- a/src/dvpp/DvppDecoder2.h +++ /dev/null @@ -1,192 +0,0 @@ -#include - -#include "depend_headers.h" -#include "CircularQueue.hpp" -#include "FFReceiver.h" -#include "DvppDec.h" - -using namespace std; - -class DvppDecoder2{ -public: - DvppDecoder2(); - ~DvppDecoder2(); - bool init(FFDecConfig cfg); - void close(); - bool start(); - void pause(); - void resume(); - - void setDecKeyframe(bool bKeyframe); - - bool isRunning(); - bool isFinished(); - bool isPausing(); - bool getResolution( int &width, int &height ); - - bool isSurport(FFDecConfig& cfg); - - float fps(); - - void setName(string nm){ - m_dec_name = nm; - } - - string getName(){ - return m_dec_name; - } - - FFImgInfo* snapshot(); - - void setPostDecArg(const void* postDecArg); - void setFinishedDecArg(const void* finishedDecArg); - - int getCachedQueueLength(); - -public: - void taskFinishing(); - -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; - -}; - -void receiver_finish_cbk(const void* userPtr){ - if(userPtr != nullptr){ - DvppDecoder2* self = (DvppDecoder2*)userPtr; - self->taskFinishing(); - } -} - -DvppDecoder2::DvppDecoder2(){ - m_pktQueueptr = new CircularQueue(); -} - -DvppDecoder2::~DvppDecoder2(){ - delete m_pktQueueptr; - m_pktQueueptr = nullptr; -} - -bool DvppDecoder2::init(FFDecConfig cfg){ - - 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); - 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); - if(!bRet){ - return false; - } - - m_cfg = cfg; - - decode_finished_cbk = cfg.decode_finished_cbk; - - return true; -} - -bool DvppDecoder2::isSurport(FFDecConfig& cfg){ - return true; -} - -bool DvppDecoder2::start(){ - m_receiver.start(); - m_decoder.start(); - return true; -} - -void DvppDecoder2::close(){ - m_receiver.close(); -} - -void DvppDecoder2::setPostDecArg(const void* postDecArg){ - m_decoder.setPostDecArg(postDecArg); -} - -void DvppDecoder2::setFinishedDecArg(const void* finishedDecArg){ - m_finishedDecArg = finishedDecArg; -} - -void DvppDecoder2::pause(){ - m_receiver.pause(); -} - -void DvppDecoder2::resume(){ - m_receiver.resume(); -} - -void DvppDecoder2::setDecKeyframe(bool bKeyframe){ - m_receiver.setDecKeyframe(bKeyframe); -} - -bool DvppDecoder2::isRunning(){ - return m_receiver.isRunning(); -} - -bool DvppDecoder2::isFinished(){ - return m_receiver.isFinished(); -} - -bool DvppDecoder2::isPausing(){ - return m_receiver.isPausing(); -} - -bool DvppDecoder2::getResolution(int &width, int &height){ - return m_receiver.getResolution(width, height); -} - -float DvppDecoder2::fps(){ - return m_receiver.fps(); -} - -FFImgInfo* DvppDecoder2::snapshot(){ - // TODO - return nullptr; -} - -int DvppDecoder2::getCachedQueueLength(){ - return 0; -} - -void DvppDecoder2::taskFinishing(){ - // receiver 中读取线程结束时执行 - m_decoder.close(); - decode_finished_cbk(m_finishedDecArg); - - LOG_INFO("[{}]- task finished.", m_dec_name); - -} \ No newline at end of file diff --git a/src/dvpp/DvppDecoderApi.cpp b/src/dvpp/DvppDecoderApi.cpp index fd2f54e..44ed20e 100644 --- a/src/dvpp/DvppDecoderApi.cpp +++ b/src/dvpp/DvppDecoderApi.cpp @@ -1,5 +1,5 @@ #include "DvppDecoderApi.h" -#include "DvppDecoder2.h" +#include "DvppDecoder.h" DvppDecoderApi::DvppDecoderApi(){ m_pDecoder = nullptr; @@ -13,7 +13,7 @@ DvppDecoderApi::~DvppDecoderApi(){ } bool DvppDecoderApi::init(FFDecConfig& cfg){ - m_pDecoder = new DvppDecoder2(); + m_pDecoder = new DvppDecoder(); if(m_pDecoder != nullptr){ return m_pDecoder->init(cfg); } diff --git a/src/dvpp/DvppDecoderApi.h b/src/dvpp/DvppDecoderApi.h index c465e03..e1b98a8 100644 --- a/src/dvpp/DvppDecoderApi.h +++ b/src/dvpp/DvppDecoderApi.h @@ -6,7 +6,7 @@ using namespace std; -class DvppDecoder2; +class DvppDecoder; class DvppDecoderApi : public AbstractDecoder{ public: @@ -40,5 +40,5 @@ public: void setPostDecArg(const void* postDecArg); void setFinishedDecArg(const void* finishedDecArg); private: - DvppDecoder2* m_pDecoder; + DvppDecoder* m_pDecoder; }; \ No newline at end of file diff --git a/src/dvpp/DvppSourceManager.cpp b/src/dvpp/DvppSourceManager.cpp index a3a0f35..4f4ce47 100644 --- a/src/dvpp/DvppSourceManager.cpp +++ b/src/dvpp/DvppSourceManager.cpp @@ -59,5 +59,8 @@ int DvppSourceManager::getChannel(int devId){ void DvppSourceManager::releaseChannel(int devId, int iChannel){ string channelKey = "channel_" + to_string(devId) + "_" + to_string(iChannel) ; - channelMap.erase(channelKey); + auto it = channelMap.find(channelKey); + if(it != channelMap.end()){ + channelMap.erase(channelKey); + } } \ No newline at end of file diff --git a/src/dvpp/FFReceiver.cpp b/src/dvpp/FFReceiver.cpp index 84ae526..26685a6 100644 --- a/src/dvpp/FFReceiver.cpp +++ b/src/dvpp/FFReceiver.cpp @@ -26,6 +26,12 @@ FFReceiver::FFReceiver(/* args */) 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){ @@ -131,8 +137,6 @@ AVCodecContext* FFReceiver::init_FFmpeg(ReceiverConfig config){ LOG_ERROR("[{}]- init ffmpeg failed ! input:{} ", m_dec_name); - releaseFFmpeg(); - return nullptr; } @@ -150,10 +154,6 @@ void FFReceiver::releaseFFmpeg(){ avcodec_free_context(&avctx); avctx = nullptr; } - - for(int i = 0; i < m_vec_pkt.size(); i++){ - av_packet_free(&m_vec_pkt[i]); - } } void FFReceiver::read_thread(){ @@ -214,6 +214,7 @@ void FFReceiver::read_thread(){ } LOG_INFO("[{}]- read thread exit.", m_dec_name); + m_bFinished = true; receiver_finished_cbk(m_finishedReceiveArg); } diff --git a/src/dvpp/VpcPicConverter.cpp b/src/dvpp/VpcPicConverter.cpp index 7af3508..c6d0a51 100644 --- a/src/dvpp/VpcPicConverter.cpp +++ b/src/dvpp/VpcPicConverter.cpp @@ -3,35 +3,40 @@ #define ALIGN_UP(val, align) (((val) % (align) == 0) ? (val) : (((val) / (align) + 1) * (align))) -bool VpcPicConverter::init(aclrtContext context){ +VpcPicConverter::VpcPicConverter(){ - aclrtSetCurrentContext(context); - aclrtCreateStream(&stream_); - - // 3. 创建图片数据处理通道时的通道描述信息,dvppChannelDesc_是acldvppChannelDesc类型 - dvppChannelDesc_ = acldvppCreateChannelDesc(); +} - // 4. 创建图片数据处理的通道。 - int ret = acldvppCreateChannel(dvppChannelDesc_); - if(ret != ACL_ERROR_NONE){ - LOG_ERROR("acldvppCreateChannel failed !"); - return false; +VpcPicConverter::~VpcPicConverter(){ + if(nullptr == stream_){ + aclrtDestroyStream(stream_); } +} - ret = acldvppSetChannelDescMode(dvppChannelDesc_, DVPP_CHNMODE_VPC); - if(ret != ACL_ERROR_NONE){ - LOG_ERROR("acldvppSetChannelDescMode failed !"); - return false; - } +int VpcPicConverter::init(aclrtContext context, string dec_name){ + + m_dec_name = dec_name; + + CHECK_AND_RETURN(aclrtSetCurrentContext(context), "aclrtSetCurrentContext failed"); + CHECK_AND_RETURN(aclrtCreateStream(&stream_), "aclrtCreateStream failed! "); - return true; + dvppChannelDesc_ = acldvppCreateChannelDesc(); + + int ret = ACL_ERROR_NONE; + do + { + ret = acldvppCreateChannel(dvppChannelDesc_); + CHECK_AND_BREAK(ret, "acldvppCreateChannel failed !"); + + ret = acldvppSetChannelDescMode(dvppChannelDesc_, DVPP_CHNMODE_VPC); + CHECK_AND_BREAK(ret, "acldvppSetChannelDescMode failed !"); + } while (0); + + return ret; } DvppRgbMemory* VpcPicConverter::convert2bgr(acldvppPicDesc *inputDesc_, int out_width, int out_height, bool key_frame){ - // 8. 创建色域转换的输出图片的描述信息,并设置各属性值, 输出的宽和高要求和输入一致 - // 如果色域转换的输出图片作为模型推理的输入,则输出图片的宽高要与模型要求的宽高保持一致 - // outputDesc_是acldvppPicDesc类型 int out_buf_width = ALIGN_UP(out_width, 16) * 3; int out_buf_height = ALIGN_UP(out_height, 2); int out_buf_size = out_buf_width * out_buf_height; @@ -48,8 +53,6 @@ DvppRgbMemory* VpcPicConverter::convert2bgr(acldvppPicDesc *inputDesc_, int out_ acldvppSetPicDescHeightStride(outputDesc_, out_buf_height); acldvppSetPicDescSize(outputDesc_, out_buf_size); - - aclError ret = ACL_ERROR_NONE; do{ // 9. 执行异步色域转换,再调用aclrtSynchronizeStream接口阻塞程序运行,直到指定Stream中的所有任务都完成 @@ -65,8 +68,6 @@ DvppRgbMemory* VpcPicConverter::convert2bgr(acldvppPicDesc *inputDesc_, int out_ } }while(0); - // 10. 色域转换结束后,释放资源,包括输入/输出图片的描述信息、输入/输出内存 - // acldvppDestroyPicDesc(inputDesc_); acldvppDestroyPicDesc(outputDesc_); if(ret != ACL_ERROR_NONE){ @@ -75,9 +76,4 @@ DvppRgbMemory* VpcPicConverter::convert2bgr(acldvppPicDesc *inputDesc_, int out_ } return rgbMem; -} - -void VpcPicConverter::release(){ - aclrtDestroyStream(stream_); - // aclrtDestroyContext(context_); } \ No newline at end of file diff --git a/src/dvpp/VpcPicConverter.h b/src/dvpp/VpcPicConverter.h index 6d0d859..18d6921 100644 --- a/src/dvpp/VpcPicConverter.h +++ b/src/dvpp/VpcPicConverter.h @@ -5,15 +5,16 @@ class VpcPicConverter{ public: - bool init(aclrtContext context); + VpcPicConverter(); + ~VpcPicConverter(); + int init(aclrtContext context, string dec_name); DvppRgbMemory* convert2bgr(acldvppPicDesc *input, int out_width, int out_height, bool key_frame); - void release(); - private: aclrtContext context_; aclrtStream stream_; int m_devId; acldvppChannelDesc *dvppChannelDesc_ ; + string m_dec_name; }; \ No newline at end of file diff --git a/src/dvpp/dvpp_headers.h b/src/dvpp/dvpp_headers.h index 49e0e61..3d981af 100644 --- a/src/dvpp/dvpp_headers.h +++ b/src/dvpp/dvpp_headers.h @@ -27,5 +27,14 @@ #include "acl/ops/acl_dvpp.h" +#define CHECK_AND_RETURN(ret, message) \ + if(ret != 0) {LOG_ERROR("[{}]- {}", m_dec_name, message); return ret;} +#define CHECK_NOT_RETURN(ret, message) \ + if(ret != 0) {LOG_ERROR("[{}]- {}", m_dec_name, message);} +#define CHECK_AND_RETURN_NOVALUE(ret, message) \ + if(ret != 0) {LOG_ERROR("[{}]- {}", m_dec_name, message); return;} +#define CHECK_AND_BREAK(ret, message) \ + if(ret != 0) {LOG_ERROR("[{}]- {}", m_dec_name, message); break;} + #endif diff --git a/src/interface/FFNvDecoderManager.cpp b/src/interface/FFNvDecoderManager.cpp index a32c4bb..b274b12 100644 --- a/src/interface/FFNvDecoderManager.cpp +++ b/src/interface/FFNvDecoderManager.cpp @@ -52,10 +52,10 @@ AbstractDecoder* FFNvDecoderManager::createDecoder(MgrDecConfig config){ return nullptr; } + config.cfg.dec_name = config.name; bool bRet= dec->init(config.cfg); if (bRet) { - dec->setName(config.name) ; decoderMap[config.name] = dec; LOG_INFO("[{}][{}]- 解码器初始化成功",config.name, config.cfg.uri); -- libgit2 0.21.4