FFmpeg问题:308 frames left in the queue on closing

1、问题描述

程序结束时,编码器缓冲区中数据没有完全输出,如下图所示
img

[当然,这只是一个警告,如果缓冲区帧数不多,完全可以忽略]

2、尝试解决

  1. 思路:程序结束时,查看缓冲区是否为空,不为空就输出完再结束,但是根据官网例子,继续采用 avcodec_receive_packet() 去读编码器,却读不出数据。所以猜测是其它问题

  2. 根据加断点,出现该警告的位置在 avcodec_free_context() 里面的 avcodec_close(); 向下探究无果

  3. 警告字面意思,编码器缓冲队列没有出完,去搜编码器缓冲区:报错位置如下,说明队列中确实好多帧没有出队列

 void ff_af_queue_close(AudioFrameQueue *afq)
 {
     if(afq->frame_count)
         av_log(afq->avctx, AV_LOG_WARNING, "%d frames left in the queue on closing\n", afq->frame_count);
     av_freep(&afq->frames);
     memset(afq, 0, sizeof(*afq));
 }
  1. 想办法出队,就去看来出队代码,根据 avcodec_receive_packet() 返回值为 AVERROR(EAGAIN) 、即-11, 进行溯源,找到
 int ff_encode_get_frame(AVCodecContext *avctx, AVFrame *frame)
 {
     AVCodecInternal *avci = avctx->internal;
  
     if (avci->draining)
         return AVERROR_EOF;
  
     if (!avci->buffer_frame->buf[0])
         return AVERROR(EAGAIN);
  
     av_frame_move_ref(frame, avci->buffer_frame);
  
     return 0;
 }
  1. 突然发现 编码器 frame_size 比输入帧的nb_samples 小,导致,缓冲区存在这么多帧,但理论上 应该可以读出来,但还没找到很好的方法,这里采用最直接的方式,就是打开编码器之后,直接给 编码器frame_size 赋值为 nb_samples; 这样问题得到了解决。(但没有根本解决)

3、解决方案

【方案一】

在打开编码器之后,重新赋值编码器的 frame_size ,使其和输入帧的 nb_samples 一样大

audioCodecCtx->frame_size = inputframe->nb_samples,
【方案二】

最好的办法 是在编码之前加一个缓冲区,将输入到编码器的数据采样点数设置成和编码器frame_size一样大
img

【方案三】如果缓冲区帧数不多,可以选择忽略
posted @ 2022-10-28 17:07  小超不挑食  阅读(1336)  评论(0编辑  收藏  举报