Commit b83a105d49a954f143cd659f1b3298bef123f35a

Authored by Hu Chunming
1 parent b070c0fd

1. 修正是否实时流判断错误的问题;

2.添加display线程,以实现解码后跳帧,避免解码后的处理操作耗时过长阻塞读取数据包从而导致花屏
3. 优化解码失败可能造成的显存泄漏问题
src/decoder/dvpp/DvppDecoder.cpp
@@ -17,7 +17,6 @@ struct Vdec_CallBack_UserData { @@ -17,7 +17,6 @@ struct Vdec_CallBack_UserData {
17 17
18 DvppDecoder::DvppDecoder(){ 18 DvppDecoder::DvppDecoder(){
19 m_read_thread = 0; 19 m_read_thread = 0;
20 - m_decode_thread = 0;  
21 m_cached_mem = nullptr; 20 m_cached_mem = nullptr;
22 21
23 fmt_ctx = nullptr; 22 fmt_ctx = nullptr;
@@ -76,8 +75,9 @@ AVCodecContext* DvppDecoder::init_FFmpeg(FFDecConfig config){ @@ -76,8 +75,9 @@ AVCodecContext* DvppDecoder::init_FFmpeg(FFDecConfig config){
76 avformat_network_init(); 75 avformat_network_init();
77 76
78 const char* uri = config.uri.c_str(); 77 const char* uri = config.uri.c_str();
79 - fstream infile(uri);  
80 - if (infile.is_open()){ 78 + fstream infile;
  79 + infile.open(uri, ios::in);
  80 + if (!infile.fail()){
81 m_bReal = false; 81 m_bReal = false;
82 infile.close(); 82 infile.close();
83 } else { 83 } else {
@@ -335,6 +335,7 @@ void DvppDecoder::read_thread() { @@ -335,6 +335,7 @@ void DvppDecoder::read_thread() {
335 int frame_count = 0; 335 int frame_count = 0;
336 int ret = -1; 336 int ret = -1;
337 337
  338 + pthread_t m_decode_thread;
338 pthread_create(&m_decode_thread,0, 339 pthread_create(&m_decode_thread,0,
339 [](void* arg) 340 [](void* arg)
340 { 341 {
@@ -393,7 +394,7 @@ void DvppDecoder::read_thread() { @@ -393,7 +394,7 @@ void DvppDecoder::read_thread() {
393 bool bPushed = false; 394 bool bPushed = false;
394 while ((ret = av_bsf_receive_packet(h264bsfc, pkt)) == 0) { 395 while ((ret = av_bsf_receive_packet(h264bsfc, pkt)) == 0) {
395 if(pkt->size > g_pkt_size){ 396 if(pkt->size > g_pkt_size){
396 - LOG_ERROR("[{}]- pkt size 大于最大预设值, 为 {}!", m_dec_name, pkt->size); 397 + LOG_ERROR("[{}]- pkt size 大于最大预设值!", m_dec_name);
397 break; 398 break;
398 } 399 }
399 400
@@ -412,13 +413,12 @@ void DvppDecoder::read_thread() { @@ -412,13 +413,12 @@ void DvppDecoder::read_thread() {
412 data_pkt->frame_nb = frame_nb; 413 data_pkt->frame_nb = frame_nb;
413 m_pktQueue.push(data_pkt); 414 m_pktQueue.push(data_pkt);
414 m_pktQueue_mutex.unlock(); 415 m_pktQueue_mutex.unlock();
415 - bPushed = true;  
416 416
  417 + bPushed = true;
417 frame_count++; 418 frame_count++;
418 } 419 }
419 420
420 - if(!bPushed)  
421 - { 421 + if(!bPushed){
422 av_packet_free(&pkt); 422 av_packet_free(&pkt);
423 pkt = nullptr; 423 pkt = nullptr;
424 } 424 }
@@ -509,6 +509,13 @@ static void VdecCallback(acldvppStreamDesc *input, acldvppPicDesc *output, void @@ -509,6 +509,13 @@ static void VdecCallback(acldvppStreamDesc *input, acldvppPicDesc *output, void
509 } 509 }
510 } 510 }
511 511
  512 +
  513 +static long get_cur_time_ms() {
  514 + chrono::time_point<chrono::system_clock, chrono::milliseconds> tpMicro
  515 + = chrono::time_point_cast<chrono::milliseconds>(chrono::system_clock::now());
  516 + return tpMicro.time_since_epoch().count();
  517 +}
  518 +
512 void DvppDecoder::doVdppVdecCallBack(acldvppStreamDesc *input, acldvppPicDesc *output, unsigned long long frame_nb){ 519 void DvppDecoder::doVdppVdecCallBack(acldvppStreamDesc *input, acldvppPicDesc *output, unsigned long long frame_nb){
513 520
514 m_vdecQueue_mutex.lock(); 521 m_vdecQueue_mutex.lock();
@@ -539,71 +546,58 @@ void DvppDecoder::doVdppVdecCallBack(acldvppStreamDesc *input, acldvppPicDesc *o @@ -539,71 +546,58 @@ void DvppDecoder::doVdppVdecCallBack(acldvppStreamDesc *input, acldvppPicDesc *o
539 break; 546 break;
540 } 547 }
541 548
542 - if(width > 0 && height > 0 && outputSize > 0){  
543 - 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);  
544 - if(mem){  
545 - if(post_decoded_cbk) {  
546 - post_decoded_cbk(m_postDecArg, mem);  
547 - } else {  
548 - delete mem;  
549 - mem = nullptr;  
550 - } 549 + bool bCached = false;
551 550
552 - if(m_bSnapShoting){  
553 - // 缓存snapshot  
554 - std::unique_lock<std::mutex> locker(m_cached_mutex);  
555 -  
556 - m_cached_mem = new DvppDataMemory(-1, width, width_stride, height, height_stride, outputSize, m_dec_name, to_string(m_dvpp_deviceId), false, 0);  
557 - if(m_cached_mem != nullptr){  
558 - aclrtMemcpy(m_cached_mem->getMem(), outputSize, (unsigned char *)outputDataDev, outputSize, ACL_MEMCPY_DEVICE_TO_DEVICE); 551 + if(width > 0 && height > 0 && outputSize > 0){
  552 + if (!m_bReal) {
  553 + while(m_bRunning) {
  554 + // 非实时流,即为文件情形,因为不存在花屏问题,为保证不丢帧,这里做个循环等待
  555 + m_decoded_data_queue_mtx.lock();
  556 + if(m_decoded_data_queue.size() > 5){
  557 + m_decoded_data_queue_mtx.unlock();
  558 + std::this_thread::sleep_for(std::chrono::milliseconds(5));
  559 + continue;
559 } 560 }
560 -  
561 - locker.unlock();  
562 - m_cached_cond.notify_one();  
563 - m_bSnapShoting = false; 561 + m_decoded_data_queue_mtx.unlock();
  562 + break;
564 } 563 }
565 - } else {  
566 - LOG_ERROR("[{}]- DvppDataMemory 创建失败! ", m_dec_name, ret);  
567 - acldvppFree(outputDataDev);  
568 - outputDataDev = nullptr;  
569 } 564 }
570 565
571 - } else { 566 + // cout << m_dec_name << " 解码时间间隔: " << get_cur_time_ms() - last_ts << endl;
  567 + // last_ts = get_cur_time_ms();
  568 +
  569 + // 换成解码后数据, 这里这样做的是为了保证解码一直持续进行,避免后续操作阻碍文件读取和解码从而导致花屏
  570 + m_decoded_data_queue_mtx.lock();
  571 + if(m_decoded_data_queue.size() <= 5) {
  572 + 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);
  573 + if(mem){
  574 + m_decoded_data_queue.push(mem);
  575 + bCached = true;
  576 + }
  577 + }
  578 + m_decoded_data_queue_mtx.unlock();
  579 +
  580 + if(m_bSnapShoting){
  581 + // 缓存snapshot
  582 + std::unique_lock<std::mutex> locker(m_cached_mutex);
  583 +
  584 + m_cached_mem = new DvppDataMemory(-1, width, width_stride, height, height_stride, outputSize, m_dec_name, to_string(m_dvpp_deviceId), false, 0);
  585 + if(m_cached_mem != nullptr){
  586 + aclrtMemcpy(m_cached_mem->getMem(), outputSize, (unsigned char *)outputDataDev, outputSize, ACL_MEMCPY_DEVICE_TO_DEVICE);
  587 + }
  588 +
  589 + locker.unlock();
  590 + m_cached_cond.notify_one();
  591 + m_bSnapShoting = false;
  592 + }
  593 +
  594 + }
  595 +
  596 + if(!bCached) {
572 LOG_WARN("[{}]- decode result error, width:{} width_stride:{} height:{} height_stride:{} size:{}", m_dec_name, width, width_stride, height, height_stride, outputSize); 597 LOG_WARN("[{}]- decode result error, width:{} width_stride:{} height:{} height_stride:{} size:{}", m_dec_name, width, width_stride, height, height_stride, outputSize);
573 acldvppFree(outputDataDev); 598 acldvppFree(outputDataDev);
574 outputDataDev = nullptr; 599 outputDataDev = nullptr;
575 } 600 }
576 -  
577 - // DvppDataMemory* rgbMem = picConverter.convert2bgr(output, width, height, false);  
578 - // if(rgbMem != nullptr){  
579 - // #ifdef TEST_DECODER  
580 - // // D2H  
581 - // if(vdecHostAddr == nullptr){  
582 - // CHECK_NOT_RETURN(aclrtMallocHost(&vdecHostAddr, width * height * 3), "aclrtMallocHost failed");  
583 - // }  
584 - // uint32_t data_size = rgbMem->getSize();  
585 - // CHECK_AND_RETURN_NOVALUE(aclrtMemcpy(vdecHostAddr, data_size, rgbMem->getMem(), data_size, ACL_MEMCPY_DEVICE_TO_HOST), "D2H aclrtMemcpy failed");  
586 -  
587 - // // 保存vdec结果  
588 - // if(count_frame > 45 && count_frame < 50)  
589 - // {  
590 - // string file_name = "./yuv_pic/vdec_out_"+ m_dec_name +".rgb" ;  
591 - // FILE *outputFile = fopen(file_name.c_str(), "a");  
592 - // if(outputFile){  
593 - // fwrite(vdecHostAddr, data_size, sizeof(char), outputFile);  
594 - // fclose(outputFile);  
595 - // }  
596 - // }  
597 - // else if(count_frame > 50 && vdecHostAddr != nullptr){  
598 - // CHECK_NOT_RETURN(aclrtFreeHost(vdecHostAddr), "aclrtFreeHost failed");  
599 - // vdecHostAddr = nullptr;  
600 - // }  
601 - // count_frame++;  
602 - // #endif  
603 - // post_decoded_cbk(m_postDecArg, rgbMem);  
604 - // }else{  
605 - // LOG_ERROR("[{}]- convert2bgr failed !", m_dec_name);  
606 - // }  
607 }while(0); 601 }while(0);
608 602
609 CHECK_AND_RETURN_NOVALUE(acldvppDestroyStreamDesc(input), "acldvppDestroyStreamDesc failed"); 603 CHECK_AND_RETURN_NOVALUE(acldvppDestroyStreamDesc(input), "acldvppDestroyStreamDesc failed");
@@ -624,6 +618,16 @@ void DvppDecoder::decode_thread(){ @@ -624,6 +618,16 @@ void DvppDecoder::decode_thread(){
624 return; 618 return;
625 } 619 }
626 620
  621 + pthread_t display_thread;
  622 + pthread_create(&display_thread,0,
  623 + [](void* arg)
  624 + {
  625 + DvppDecoder* a=(DvppDecoder*)arg;
  626 + a->display_thread();
  627 + return (void*)0;
  628 + }
  629 + ,this);
  630 +
627 aclrtSetDevice(m_dvpp_deviceId); 631 aclrtSetDevice(m_dvpp_deviceId);
628 aclrtContext ctx; 632 aclrtContext ctx;
629 ret = aclrtCreateContext(&ctx, m_dvpp_deviceId); 633 ret = aclrtCreateContext(&ctx, m_dvpp_deviceId);
@@ -651,8 +655,7 @@ void DvppDecoder::decode_thread(){ @@ -651,8 +655,7 @@ void DvppDecoder::decode_thread(){
651 655
652 uint64_t frame_count = 0; 656 uint64_t frame_count = 0;
653 bool bBreak = false; 657 bool bBreak = false;
654 - while (m_bRunning)  
655 - { 658 + while (m_bRunning) {
656 if (m_bPause){ 659 if (m_bPause){
657 std::this_thread::sleep_for(std::chrono::milliseconds(3)); 660 std::this_thread::sleep_for(std::chrono::milliseconds(3));
658 continue; 661 continue;
@@ -662,10 +665,9 @@ void DvppDecoder::decode_thread(){ @@ -662,10 +665,9 @@ void DvppDecoder::decode_thread(){
662 bBreak = true; 665 bBreak = true;
663 break; 666 break;
664 }else if(ret == 1){ 667 }else if(ret == 1){
665 - std::this_thread::sleep_for(std::chrono::milliseconds(3));  
666 continue; 668 continue;
667 } 669 }
668 - 670 +
669 frame_count++; 671 frame_count++;
670 } 672 }
671 673
@@ -699,6 +701,7 @@ void DvppDecoder::decode_thread(){ @@ -699,6 +701,7 @@ void DvppDecoder::decode_thread(){
699 m_bRunning = false; 701 m_bRunning = false;
700 m_bExitReportThd = true; 702 m_bExitReportThd = true;
701 CHECK_NOT_RETURN(pthread_join(report_thread, nullptr), "pthread_join failed"); 703 CHECK_NOT_RETURN(pthread_join(report_thread, nullptr), "pthread_join failed");
  704 + CHECK_NOT_RETURN(pthread_join(display_thread, nullptr), "pthread_join failed");
702 705
703 // 最后清理一遍未解码的数据 706 // 最后清理一遍未解码的数据
704 m_vdecQueue_mutex.lock(); 707 m_vdecQueue_mutex.lock();
@@ -741,7 +744,7 @@ int DvppDecoder::sentFrame(aclvdecChannelDesc *vdecChannelDesc, uint64_t frame_c @@ -741,7 +744,7 @@ int DvppDecoder::sentFrame(aclvdecChannelDesc *vdecChannelDesc, uint64_t frame_c
741 data_pkt = m_pktQueue.front(); 744 data_pkt = m_pktQueue.front();
742 m_pktQueue.pop(); 745 m_pktQueue.pop();
743 m_pktQueue_mutex.unlock(); 746 m_pktQueue_mutex.unlock();
744 - 747 +
745 // 解码 748 // 解码
746 void *vdecInputbuf = nullptr; 749 void *vdecInputbuf = nullptr;
747 int ret = acldvppMalloc((void **)&vdecInputbuf, g_pkt_size); 750 int ret = acldvppMalloc((void **)&vdecInputbuf, g_pkt_size);
@@ -770,7 +773,6 @@ int DvppDecoder::sentFrame(aclvdecChannelDesc *vdecChannelDesc, uint64_t frame_c @@ -770,7 +773,6 @@ int DvppDecoder::sentFrame(aclvdecChannelDesc *vdecChannelDesc, uint64_t frame_c
770 return 2; 773 return 2;
771 } 774 }
772 775
773 - bool bRet = false;  
774 acldvppStreamDesc *input_stream_desc = nullptr; 776 acldvppStreamDesc *input_stream_desc = nullptr;
775 acldvppPicDesc *output_pic_desc = nullptr; 777 acldvppPicDesc *output_pic_desc = nullptr;
776 do{ 778 do{
@@ -808,12 +810,10 @@ int DvppDecoder::sentFrame(aclvdecChannelDesc *vdecChannelDesc, uint64_t frame_c @@ -808,12 +810,10 @@ int DvppDecoder::sentFrame(aclvdecChannelDesc *vdecChannelDesc, uint64_t frame_c
808 user_data = nullptr; 810 user_data = nullptr;
809 break; 811 break;
810 } 812 }
811 - 813 +
812 m_vdecQueue.push(vdecInputbuf); 814 m_vdecQueue.push(vdecInputbuf);
813 m_vdecQueue_mutex.unlock(); 815 m_vdecQueue_mutex.unlock();
814 816
815 - bRet = true;  
816 -  
817 return 0; 817 return 0;
818 }while (0); 818 }while (0);
819 819
@@ -822,7 +822,7 @@ int DvppDecoder::sentFrame(aclvdecChannelDesc *vdecChannelDesc, uint64_t frame_c @@ -822,7 +822,7 @@ int DvppDecoder::sentFrame(aclvdecChannelDesc *vdecChannelDesc, uint64_t frame_c
822 data_pkt = nullptr; 822 data_pkt = nullptr;
823 } 823 }
824 824
825 - if (!bRet){ 825 + if (vdecInputbuf){
826 acldvppFree(vdecInputbuf); 826 acldvppFree(vdecInputbuf);
827 vdecInputbuf = nullptr; 827 vdecInputbuf = nullptr;
828 } 828 }
@@ -870,6 +870,37 @@ bool DvppDecoder::sendVdecEos(aclvdecChannelDesc *vdecChannelDesc) { @@ -870,6 +870,37 @@ bool DvppDecoder::sendVdecEos(aclvdecChannelDesc *vdecChannelDesc) {
870 return true; 870 return true;
871 } 871 }
872 872
  873 +void DvppDecoder::display_thread(){
  874 + LOG_INFO("[{}]- display_thread start...", m_dec_name);
  875 + while(m_bRunning) {
  876 + m_decoded_data_queue_mtx.lock();
  877 + if(m_decoded_data_queue.size() <= 0) {
  878 + m_decoded_data_queue_mtx.unlock();
  879 + std::this_thread::sleep_for(std::chrono::milliseconds(5));
  880 + continue;
  881 + }
  882 + DvppDataMemory* mem = m_decoded_data_queue.front();
  883 + m_decoded_data_queue.pop();
  884 + m_decoded_data_queue_mtx.unlock();
  885 +
  886 + if(post_decoded_cbk) {
  887 + post_decoded_cbk(m_postDecArg, mem);
  888 + } else {
  889 + delete mem;
  890 + mem = nullptr;
  891 + }
  892 + }
  893 +
  894 + while (m_decoded_data_queue.size() > 0){
  895 + DvppDataMemory* mem = m_decoded_data_queue.front();
  896 + m_decoded_data_queue.pop();
  897 + delete mem;
  898 + mem = nullptr;
  899 + }
  900 +
  901 + LOG_INFO("[{}]- display_thread end.", m_dec_name);
  902 +}
  903 +
873 void DvppDecoder::release_dvpp(){ 904 void DvppDecoder::release_dvpp(){
874 if(m_context){ 905 if(m_context){
875 aclError ret = aclrtDestroyContext(m_context); 906 aclError ret = aclrtDestroyContext(m_context);
src/decoder/dvpp/DvppDecoder.h
@@ -71,6 +71,8 @@ private: @@ -71,6 +71,8 @@ private:
71 bool sendVdecEos(aclvdecChannelDesc *vdecChannelDesc); 71 bool sendVdecEos(aclvdecChannelDesc *vdecChannelDesc);
72 void release_dvpp(); 72 void release_dvpp();
73 73
  74 + void display_thread();
  75 +
74 private: 76 private:
75 FFDecConfig m_cfg; 77 FFDecConfig m_cfg;
76 string m_dec_name; 78 string m_dec_name;
@@ -109,7 +111,6 @@ private: @@ -109,7 +111,6 @@ private:
109 aclrtContext m_context{nullptr}; 111 aclrtContext m_context{nullptr};
110 acldvppStreamFormat enType; 112 acldvppStreamFormat enType;
111 113
112 - pthread_t m_decode_thread{0};  
113 mutex m_vdecQueue_mutex; 114 mutex m_vdecQueue_mutex;
114 queue<void*> m_vdecQueue; 115 queue<void*> m_vdecQueue;
115 116
@@ -125,4 +126,9 @@ private: @@ -125,4 +126,9 @@ private:
125 condition_variable m_cached_cond; 126 condition_variable m_cached_cond;
126 127
127 FFRecoderTaskManager m_recoderManager; 128 FFRecoderTaskManager m_recoderManager;
  129 +
  130 + queue<DvppDataMemory*> m_decoded_data_queue;
  131 + mutex m_decoded_data_queue_mtx;
  132 +
  133 + long long last_ts {0};
128 }; 134 };
129 \ No newline at end of file 135 \ No newline at end of file