#include "DvppDecoder.h" #include "DvppSourceManager.h" struct Vdec_CallBack_UserData { uint64_t frameId; unsigned long long frame_nb; long startTime; long sendTime; // void* vdecOutputBuf; DvppDecoder* self; Vdec_CallBack_UserData() { frameId = 0; frame_nb = 0; } }; DvppDecoder::DvppDecoder(){ m_read_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(){ } bool DvppDecoder::init(FFDecConfig cfg){ m_dec_name = cfg.dec_name; AVCodecContext* avctx = init_FFmpeg(cfg); if(avctx == nullptr){ return false; } bool bRet = init_vdpp(cfg, avctx); if(!bRet){ return false; } m_cfg = cfg; decode_finished_cbk = cfg.decode_finished_cbk; m_bFinished = false; 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; infile.open(uri, ios::in); if (!infile.fail()){ 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); #ifdef USE_VILLAGE bool bRet = m_recoderManager.init(stream, avctx); if (!bRet){ LOG_ERROR("[{}]- m_recoderManager 初始化失败!", m_dec_name); } #endif 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_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_bRunning=false; if(m_read_thread != 0){ pthread_join(m_read_thread,0); } } void DvppDecoder::setPostDecArg(const void* postDecArg){ m_postDecArg = postDecArg; } void DvppDecoder::setFinishedDecArg(const void* finishedDecArg){ m_finishedDecArg = finishedDecArg; } void DvppDecoder::pause(){ m_bPause = true; } void DvppDecoder::resume(){ m_bPause = false; } void DvppDecoder::setDecKeyframe(bool bKeyframe){ m_dec_keyframe = bKeyframe; } bool DvppDecoder::isRunning(){ return m_bRunning; } bool DvppDecoder::isFinished(){ return m_bFinished; } bool DvppDecoder::isPausing(){ return m_bPause; } bool DvppDecoder::getResolution(int &width, int &height){ width = frame_width; height = frame_height; return true; } float DvppDecoder::fps(){ return m_fps; } DeviceMemory* DvppDecoder::snapshot(){ // 注意内部有锁 // 开始抓拍 m_bSnapShoting = true; std::unique_lock locker(m_cached_mutex); while (m_cached_mem == nullptr) m_cached_cond.wait_for(locker, std::chrono::seconds(1)); // 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::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; m_bExitDecodeThd = false; pthread_t m_decode_thread; pthread_create(&m_decode_thread,0, [](void* arg) { DvppDecoder* a=(DvppDecoder*)arg; a->decode_thread(); return (void*)0; } ,this); AVPacket* pkt = nullptr; unsigned long long frame_nb = 0; 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; } frame_nb++; #ifdef USE_VILLAGE m_recoderManager.cache_pkt(pkt, frame_nb); #endif m_pktQueue_mutex.lock(); DataPacket* data_pkt = new DataPacket(); data_pkt->pkt = pkt; data_pkt->frame_nb = frame_nb; m_pktQueue.push(data_pkt); m_pktQueue_mutex.unlock(); bPushed = true; frame_count++; } if(!bPushed){ av_packet_free(&pkt); pkt = nullptr; } } else { // 音频等其他分量的情形 av_packet_free(&pkt); pkt = nullptr; } } while(m_bRunning && m_pktQueue.size() > 0) { std::this_thread::sleep_for(std::chrono::milliseconds(5)); } m_bExitDecodeThd = true; if(m_decode_thread != 0){ pthread_join(m_decode_thread,0); } m_pktQueue_mutex.lock(); while(m_pktQueue.size() > 0){ DataPacket* data_pkt = m_pktQueue.front(); delete data_pkt; data_pkt = nullptr; m_pktQueue.pop(); } m_pktQueue_mutex.unlock(); m_bRunning=false; if(decode_finished_cbk) { decode_finished_cbk(m_finishedDecArg); } m_recoderManager.close(); LOG_INFO("[{}]- read thread exit.", m_dec_name); m_bFinished = true; release_ffmpeg(); } 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, userData->frame_nb); } delete userData; userData = nullptr; } } static long get_cur_time_ms() { chrono::time_point tpMicro = chrono::time_point_cast(chrono::system_clock::now()); return tpMicro.time_since_epoch().count(); } void DvppDecoder::doVdppVdecCallBack(acldvppStreamDesc *input, acldvppPicDesc *output, unsigned long long frame_nb){ 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; } bool bCached = false; if(width > 0 && height > 0 && outputSize > 0){ if (!m_bReal) { while(m_bRunning) { // 非实时流,即为文件情形,因为不存在花屏问题,为保证不丢帧,这里做个循环等待 m_decoded_data_queue_mtx.lock(); if(m_decoded_data_queue.size() > 5){ m_decoded_data_queue_mtx.unlock(); std::this_thread::sleep_for(std::chrono::milliseconds(5)); continue; } m_decoded_data_queue_mtx.unlock(); break; } } // cout << m_dec_name << " 解码时间间隔: " << get_cur_time_ms() - last_ts << endl; // last_ts = get_cur_time_ms(); // 换成解码后数据, 这里这样做的是为了保证解码一直持续进行,避免后续操作阻碍文件读取和解码从而导致花屏 m_decoded_data_queue_mtx.lock(); if(m_decoded_data_queue.size() <= 5) { DvppDataMemory* mem = new DvppDataMemory(width, width_stride, height, height_stride, outputSize, m_dec_name, to_string(m_dvpp_deviceId), false, frame_nb, (unsigned char *)outputDataDev); if(mem){ m_decoded_data_queue.push(mem); bCached = true; } } m_decoded_data_queue_mtx.unlock(); 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, 0); 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; } } if(!bCached) { LOG_WARN("[{}]- decode result warning, width:{} width_stride:{} height:{} height_stride:{} size:{}", m_dec_name, width, width_stride, height, height_stride, outputSize); acldvppFree(outputDataDev); outputDataDev = nullptr; } }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; } m_bExitDisplayThd = false; pthread_t display_thread; pthread_create(&display_thread,0, [](void* arg) { DvppDecoder* a=(DvppDecoder*)arg; a->display_thread(); return (void*)0; } ,this); 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_bExitDecodeThd) { 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); // 退出 report thread while(m_bRunning && m_vdecQueue.size() > 0) { std::this_thread::sleep_for(std::chrono::milliseconds(5)); } CHECK_NOT_RETURN(aclvdecDestroyChannelDesc(vdecChannelDesc), "aclvdecDestroyChannelDesc failed"); // report_thread 需后于destroy退出 m_bExitReportThd = true; CHECK_NOT_RETURN(pthread_join(report_thread, nullptr), "report_thread join failed"); // 退出 display thread while(m_bRunning && m_decoded_data_queue.size() > 0) { std::this_thread::sleep_for(std::chrono::milliseconds(5)); } m_bExitDisplayThd = true; CHECK_NOT_RETURN(pthread_join(display_thread, nullptr), "display_thread join failed"); // 最后清理一遍未解码的数据 m_vdecQueue_mutex.lock(); while(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); } 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(); DataPacket * data_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; } data_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); delete data_pkt; data_pkt = nullptr; return 2; } AVPacket* pkt = data_pkt->pkt; 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); delete data_pkt; data_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); delete data_pkt; data_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->frame_nb = data_pkt->frame_nb; // user_data->startTime = startTime; user_data->sendTime = UtilTools::get_cur_time_ms(); user_data->self = this; m_vdecQueue_mutex.lock(); ret = aclvdecSendFrame(vdecChannelDesc, input_stream_desc, output_pic_desc, nullptr, reinterpret_cast(user_data)); delete data_pkt; data_pkt = nullptr; if(ret != ACL_ERROR_NONE){ LOG_ERROR("[{}]- aclvdecSendFrame failed", m_dec_name); m_vdecQueue_mutex.unlock(); delete user_data; user_data = nullptr; break; } m_vdecQueue.push(vdecInputbuf); m_vdecQueue_mutex.unlock(); return 0; }while (0); if(data_pkt != nullptr){ delete data_pkt; data_pkt = nullptr; } if (vdecInputbuf){ acldvppFree(vdecInputbuf); vdecInputbuf = nullptr; } // 报错情形 if(input_stream_desc){ CHECK_NOT_RETURN(acldvppDestroyStreamDesc(input_stream_desc), "acldvppDestroyStreamDesc failed"); } if (vdecOutputBuf){ acldvppFree(vdecOutputBuf); vdecOutputBuf = nullptr; } if(output_pic_desc){ CHECK_NOT_RETURN(acldvppDestroyPicDesc(output_pic_desc), "acldvppDestroyPicDesc failed"); } 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::display_thread(){ LOG_INFO("[{}]- display_thread start...", m_dec_name); while(!m_bExitDisplayThd) { m_decoded_data_queue_mtx.lock(); if(m_decoded_data_queue.size() <= 0) { m_decoded_data_queue_mtx.unlock(); std::this_thread::sleep_for(std::chrono::milliseconds(5)); continue; } DvppDataMemory* mem = m_decoded_data_queue.front(); m_decoded_data_queue.pop(); m_decoded_data_queue_mtx.unlock(); if(post_decoded_cbk) { post_decoded_cbk(m_postDecArg, mem); } else { delete mem; mem = nullptr; } } while (m_decoded_data_queue.size() > 0){ DvppDataMemory* mem = m_decoded_data_queue.front(); m_decoded_data_queue.pop(); delete mem; mem = nullptr; } LOG_INFO("[{}]- display_thread exit.", m_dec_name); } 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); } void DvppDecoder::doRecode(RecoderInfo& recoderInfo) { m_recoderManager.create_recode_task(recoderInfo); } void DvppDecoder::set_mq_callback(mq_callback_t cb) { m_recoderManager.set_mq_callback(cb); }