FFmpeg 基本API avcodec_receive_frame函数内部调用流程分析
1、avcodec_receive_frame 函数定义
avcodec_receive_frame 是 FFmpeg 多媒体处理框架中的核心函数,属于其现代解码 API 的关键组成部分。它与 avcodec_send_packet 配对使用,实现解码。基本流程如下:
- 发送数据包:调用 avcodec_send_packet 将压缩数据包送入解码器。
- 循环接收帧:在 while 循环中反复调用 avcodec_receive_frame,直到其返回 AVERROR(EAGAIN)(表示需要新输入)或 AVERROR_EOF(表示数据已取完)。因为一个数据包可能解码出多个帧,或者解码器内部有缓存,所以需要循环读取。
int attribute_align_arg avcodec_receive_frame(AVCodecContext *avctx, AVFrame *frame)
{// 1. 清空输出帧av_frame_unref(frame);// 2. 判断编解码器类型并分派if (av_codec_is_decoder(avctx->codec))return ff_decode_receive_frame(avctx, frame); // 解码路径return ff_encode_receive_frame(avctx, frame); // 编码路径
}
/*
实现异步解码模型的结果获取端
支持复杂帧关系处理(B帧、分片帧等)
提供硬件加速的统一接口
已成为 FFmpeg 解码操作的标准实践
*/
- 参数:
- avctx: 编解码器上下文
- frame: 输出帧容器(用户分配内存)
- 返回值:
- 0: 成功获取一帧
- AVERROR(EAGAIN): 需要更多输入数据
- AVERROR_EOF: 解码器已刷新完毕
- <0: 其他错误
2、avcodec_receive_frame 内部调用逻辑
avcodec_receive_frame其内部源码调用分析:
int attribute_align_arg avcodec_receive_frame(AVCodecContext *avctx, AVFrame *frame)
{// 1. 清空输出帧av_frame_unref(frame);// 2. 判断编解码器类型并分派if (av_codec_is_decoder(avctx->codec))return ff_decode_receive_frame(avctx, frame); // 解码路径return ff_encode_receive_frame(avctx, frame); // 编码路径
}
/*
实现异步解码模型的结果获取端
支持复杂帧关系处理(B帧、分片帧等)
提供硬件加速的统一接口
已成为 FFmpeg 解码操作的标准实践
*/
2.1 基础参数校验
if (!avcodec_is_open(avctx) || !av_codec_is_decoder(avctx->codec))return AVERROR(EINVAL);
- 检查编解码器是否打开且是解码器
- 防止错误调用(如编码器调用此函数)
2.2 帧获取逻辑
- 缓冲区优先:避免重复解码
- 引用移动:av_frame_move_ref()高效转移数据所有权
2.3 帧验证
ret = frame_validate(avctx, frame);
验证帧的完整性:
- 视频:检查宽/高/格式是否有效
- 音频:检查采样率/声道布局
- 防止无效帧进入后续流程
2.4 视频帧裁剪处理
if (avctx->codec_type == AVMEDIA_TYPE_VIDEO) {ret = apply_cropping(avctx, frame);}
根据解码器上下文中的裁剪参数:
avctx->crop_top, avctx->crop_bottom,
avctx->crop_left, avctx->crop_right
调整视频帧的可见区域。
2.5 帧计数更新
avctx->frame_num++; // 全局帧计数器