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,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 DvppDecoder::DvppDecoder(){ 76 DvppDecoder::DvppDecoder(){
61 m_read_thread = nullptr; 77 m_read_thread = nullptr;
@@ -114,9 +130,11 @@ AVCodecContext* DvppDecoder::init_FFmpeg(FFDecConfig config){ @@ -114,9 +130,11 @@ AVCodecContext* DvppDecoder::init_FFmpeg(FFDecConfig config){
114 av_dict_set( &options, "bufsize", "655360", 0 ); 130 av_dict_set( &options, "bufsize", "655360", 0 );
115 av_dict_set( &options, "rtsp_transport", config.force_tcp ? "tcp" : "udp", 0 ); 131 av_dict_set( &options, "rtsp_transport", config.force_tcp ? "tcp" : "udp", 0 );
116 av_dict_set( &options, "stimeout", "30000000", 0 ); // 单位为 百万分之一秒 132 av_dict_set( &options, "stimeout", "30000000", 0 ); // 单位为 百万分之一秒
  133 + av_dict_set( &options, "max_delay", "500000", 0); //设置最大时延
117 134
118 do{ 135 do{
119 fmt_ctx = avformat_alloc_context(); 136 fmt_ctx = avformat_alloc_context();
  137 + // fmt_ctx->flags |= AVFMT_FLAG_NONBLOCK;
120 if (avformat_open_input(&fmt_ctx, input_file, nullptr, &options) != 0) { 138 if (avformat_open_input(&fmt_ctx, input_file, nullptr, &options) != 0) {
121 LOG_ERROR("[{}]- Cannot open input file: {}", m_dec_name, input_file); 139 LOG_ERROR("[{}]- Cannot open input file: {}", m_dec_name, input_file);
122 break; 140 break;
@@ -135,6 +153,10 @@ AVCodecContext* DvppDecoder::init_FFmpeg(FFDecConfig config){ @@ -135,6 +153,10 @@ AVCodecContext* DvppDecoder::init_FFmpeg(FFDecConfig config){
135 m_bReal = false; 153 m_bReal = false;
136 } else { 154 } else {
137 m_bReal = true; 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,6 +225,12 @@ AVCodecContext* DvppDecoder::init_FFmpeg(FFDecConfig config){
203 225
204 m_vdec_out_size = frame_width * frame_height * 3 / 2; 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 #ifdef USE_VILLAGE 234 #ifdef USE_VILLAGE
207 bool bRet = m_recoderManager.init2(frame_width, frame_height, m_fps, avctx->bit_rate); 235 bool bRet = m_recoderManager.init2(frame_width, frame_height, m_fps, avctx->bit_rate);
208 if (!bRet){ 236 if (!bRet){
@@ -403,6 +431,10 @@ float DvppDecoder::fps(){ @@ -403,6 +431,10 @@ float DvppDecoder::fps(){
403 return m_fps; 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 static int snap_count = 0; 438 static int snap_count = 0;
407 439
408 DeviceMemory* DvppDecoder::snapshot(){ 440 DeviceMemory* DvppDecoder::snapshot(){
@@ -532,15 +564,15 @@ void DvppDecoder::read_thread() { @@ -532,15 +564,15 @@ void DvppDecoder::read_thread() {
532 } 564 }
533 m_decoded_data_queue_mtx.unlock(); 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 std::this_thread::sleep_for(std::chrono::milliseconds(10)); 569 std::this_thread::sleep_for(std::chrono::milliseconds(10));
538 continue; 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 int result = av_read_frame(fmt_ctx, pkt); 576 int result = av_read_frame(fmt_ctx, pkt);
545 if (result == AVERROR_EOF || result < 0){ 577 if (result == AVERROR_EOF || result < 0){
546 av_packet_unref(pkt); 578 av_packet_unref(pkt);
@@ -548,9 +580,7 @@ void DvppDecoder::read_thread() { @@ -548,9 +580,7 @@ void DvppDecoder::read_thread() {
548 break; 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 std::this_thread::sleep_for(std::chrono::milliseconds(10)); 586 std::this_thread::sleep_for(std::chrono::milliseconds(10));
@@ -564,8 +594,6 @@ void DvppDecoder::read_thread() { @@ -564,8 +594,6 @@ void DvppDecoder::read_thread() {
564 594
565 if (video_index == pkt->stream_index){ 595 if (video_index == pkt->stream_index){
566 596
567 - LOG_DEBUG("[{}]- av_bsf_send_packet", m_dec_name);  
568 -  
569 ret = av_bsf_send_packet(h264bsfc, pkt); 597 ret = av_bsf_send_packet(h264bsfc, pkt);
570 if(ret < 0) { 598 if(ret < 0) {
571 LOG_ERROR("[{}]- av_bsf_send_packet error!", m_dec_name); 599 LOG_ERROR("[{}]- av_bsf_send_packet error!", m_dec_name);
src/decoder/dvpp/DvppDecoder.h
@@ -65,6 +65,7 @@ public: @@ -65,6 +65,7 @@ public:
65 public: 65 public:
66 void doVdppVdecCallBack(acldvppStreamDesc *input, acldvppPicDesc *output, void *pUserData); 66 void doVdppVdecCallBack(acldvppStreamDesc *input, acldvppPicDesc *output, void *pUserData);
67 void doProcessReport(); 67 void doProcessReport();
  68 + long long get_last_read_ts();
68 69
69 private: 70 private:
70 AVCodecContext* init_FFmpeg(FFDecConfig config); 71 AVCodecContext* init_FFmpeg(FFDecConfig config);
@@ -133,12 +134,15 @@ private: @@ -133,12 +134,15 @@ private:
133 134
134 long long last_ts {0}; 135 long long last_ts {0};
135 136
  137 + long long m_last_read_ts {0};
  138 +
136 uint64_t m_in_count {0}; 139 uint64_t m_in_count {0};
137 uint64_t m_out_count {0}; 140 uint64_t m_out_count {0};
138 141
139 int m_frameSkip {1}; 142 int m_frameSkip {1};
140 143
141 std::atomic<int> m_DvppCacheCounter{0}; 144 std::atomic<int> m_DvppCacheCounter{0};
  145 + int m_cache_gop{0};
142 146
143 VpcUtils m_vpcUtils; 147 VpcUtils m_vpcUtils;
144 }; 148 };
145 \ No newline at end of file 149 \ No newline at end of file