Commit b83a105d49a954f143cd659f1b3298bef123f35a
1 parent
b070c0fd
1. 修正是否实时流判断错误的问题;
2.添加display线程,以实现解码后跳帧,避免解码后的处理操作耗时过长阻塞读取数据包从而导致花屏 3. 优化解码失败可能造成的显存泄漏问题
Showing
2 changed files
with
111 additions
and
74 deletions
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 |