FFmpeg问题:308 frames left in the queue on closing
1、问题描述
程序结束时,编码器缓冲区中数据没有完全输出,如下图所示
[当然,这只是一个警告,如果缓冲区帧数不多,完全可以忽略]
2、尝试解决
-
思路:程序结束时,查看缓冲区是否为空,不为空就输出完再结束,但是根据官网例子,继续采用 avcodec_receive_packet() 去读编码器,却读不出数据。所以猜测是其它问题
-
根据加断点,出现该警告的位置在 avcodec_free_context() 里面的 avcodec_close(); 向下探究无果
-
警告字面意思,编码器缓冲队列没有出完,去搜编码器缓冲区:报错位置如下,说明队列中确实好多帧没有出队列
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));
}
- 想办法出队,就去看来出队代码,根据 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;
}
- 突然发现 编码器 frame_size 比输入帧的nb_samples 小,导致,缓冲区存在这么多帧,但理论上 应该可以读出来,但还没找到很好的方法,这里采用最直接的方式,就是打开编码器之后,直接给 编码器frame_size 赋值为 nb_samples; 这样问题得到了解决。(但没有根本解决)
3、解决方案
【方案一】
在打开编码器之后,重新赋值编码器的 frame_size ,使其和输入帧的 nb_samples 一样大
audioCodecCtx->frame_size = inputframe->nb_samples,
【方案二】
最好的办法 是在编码之前加一个缓冲区,将输入到编码器的数据采样点数设置成和编码器frame_size一样大