Commit 79b0c737514cbf7aedd1a365c8c32cb78fc0d104

Authored by Hu Chunming
1 parent 76a86847

优化代码,防止摄像头掉线卡死

src/decoder/dvpp/DvppDecoder.cpp
... ... @@ -56,6 +56,22 @@ static void VdecCallback(acldvppStreamDesc *input, acldvppPicDesc *output, void
56 56 }
57 57 }
58 58  
  59 +static int AVInterruptCallBackFun(void *param)
  60 +{
  61 + DvppDecoder *pDecoder = (DvppDecoder*)param;
  62 + if (nullptr == pDecoder) return 0;
  63 +
  64 + long long cur_ts = get_cur_time_ms();
  65 + long time_gap = cur_ts - pDecoder->get_last_read_ts();
  66 + if (time_gap > 1000*30) {
  67 + LOG_WARN("摄像头异常,释放阻塞");
  68 + //通知FFMpeg可以从阻塞工作线程中释放操作
  69 + return 1;
  70 + } else {
  71 + //通知FFMpeg继续阻塞工作
  72 + return 0;
  73 + }
  74 +}
59 75  
60 76 DvppDecoder::DvppDecoder(){
61 77 m_read_thread = nullptr;
... ... @@ -114,9 +130,11 @@ AVCodecContext* DvppDecoder::init_FFmpeg(FFDecConfig config){
114 130 av_dict_set( &options, "bufsize", "655360", 0 );
115 131 av_dict_set( &options, "rtsp_transport", config.force_tcp ? "tcp" : "udp", 0 );
116 132 av_dict_set( &options, "stimeout", "30000000", 0 ); // 单位为 百万分之一秒
  133 + av_dict_set( &options, "max_delay", "500000", 0); //设置最大时延
117 134  
118 135 do{
119 136 fmt_ctx = avformat_alloc_context();
  137 + // fmt_ctx->flags |= AVFMT_FLAG_NONBLOCK;
120 138 if (avformat_open_input(&fmt_ctx, input_file, nullptr, &options) != 0) {
121 139 LOG_ERROR("[{}]- Cannot open input file: {}", m_dec_name, input_file);
122 140 break;
... ... @@ -135,6 +153,10 @@ AVCodecContext* DvppDecoder::init_FFmpeg(FFDecConfig config){
135 153 m_bReal = false;
136 154 } else {
137 155 m_bReal = true;
  156 +
  157 + fmt_ctx->interrupt_callback.callback = AVInterruptCallBackFun;
  158 + fmt_ctx->interrupt_callback.opaque = this;
  159 + m_last_read_ts = get_cur_time_ms();
138 160 }
139 161 }
140 162  
... ... @@ -203,6 +225,12 @@ AVCodecContext* DvppDecoder::init_FFmpeg(FFDecConfig config){
203 225  
204 226 m_vdec_out_size = frame_width * frame_height * 3 / 2;
205 227  
  228 + if (avctx->gop_size > 0) {
  229 + m_cache_gop = avctx->gop_size + 1;
  230 + } else {
  231 + m_cache_gop = 20;
  232 + }
  233 +
206 234 #ifdef USE_VILLAGE
207 235 bool bRet = m_recoderManager.init2(frame_width, frame_height, m_fps, avctx->bit_rate);
208 236 if (!bRet){
... ... @@ -403,6 +431,10 @@ float DvppDecoder::fps(){
403 431 return m_fps;
404 432 }
405 433  
  434 +long long DvppDecoder::get_last_read_ts() {
  435 + return m_last_read_ts;
  436 +}
  437 +
406 438 static int snap_count = 0;
407 439  
408 440 DeviceMemory* DvppDecoder::snapshot(){
... ... @@ -532,15 +564,15 @@ void DvppDecoder::read_thread() {
532 564 }
533 565 m_decoded_data_queue_mtx.unlock();
534 566  
535   - if(m_DvppCacheCounter.load() > 20) {
  567 + if(m_DvppCacheCounter.load() > m_cache_gop) {
536 568 // 解码器解码不过来
537 569 std::this_thread::sleep_for(std::chrono::milliseconds(10));
538 570 continue;
539 571 }
  572 + } else {
  573 + m_last_read_ts = get_cur_time_ms();
540 574 }
541 575  
542   - // LOG_DEBUG("[{}]- read in", m_dec_name);
543   -
544 576 int result = av_read_frame(fmt_ctx, pkt);
545 577 if (result == AVERROR_EOF || result < 0){
546 578 av_packet_unref(pkt);
... ... @@ -548,9 +580,7 @@ void DvppDecoder::read_thread() {
548 580 break;
549 581 }
550 582  
551   - // LOG_DEBUG("[{}]- read out", m_dec_name);
552   -
553   - if (m_bReal && m_DvppCacheCounter.load() > 20){
  583 + if (m_bReal && m_DvppCacheCounter.load() > m_cache_gop){
554 584 // 解码器解码不过来。实时流在此处的处理会导致花屏,这是由于解码器性能问题导致,无法避免
555 585 // 实时流在这里处理是为了避免长时间不读取数据导致数据中断
556 586 std::this_thread::sleep_for(std::chrono::milliseconds(10));
... ... @@ -564,8 +594,6 @@ void DvppDecoder::read_thread() {
564 594  
565 595 if (video_index == pkt->stream_index){
566 596  
567   - LOG_DEBUG("[{}]- av_bsf_send_packet", m_dec_name);
568   -
569 597 ret = av_bsf_send_packet(h264bsfc, pkt);
570 598 if(ret < 0) {
571 599 LOG_ERROR("[{}]- av_bsf_send_packet error!", m_dec_name);
... ...
src/decoder/dvpp/DvppDecoder.h
... ... @@ -65,6 +65,7 @@ public:
65 65 public:
66 66 void doVdppVdecCallBack(acldvppStreamDesc *input, acldvppPicDesc *output, void *pUserData);
67 67 void doProcessReport();
  68 + long long get_last_read_ts();
68 69  
69 70 private:
70 71 AVCodecContext* init_FFmpeg(FFDecConfig config);
... ... @@ -133,12 +134,15 @@ private:
133 134  
134 135 long long last_ts {0};
135 136  
  137 + long long m_last_read_ts {0};
  138 +
136 139 uint64_t m_in_count {0};
137 140 uint64_t m_out_count {0};
138 141  
139 142 int m_frameSkip {1};
140 143  
141 144 std::atomic<int> m_DvppCacheCounter{0};
  145 + int m_cache_gop{0};
142 146  
143 147 VpcUtils m_vpcUtils;
144 148 };
145 149 \ No newline at end of file
... ...