Commit 79b0c737514cbf7aedd1a365c8c32cb78fc0d104
1 parent
76a86847
优化代码,防止摄像头掉线卡死
Showing
2 changed files
with
40 additions
and
8 deletions
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 | ... | ... |