必须先调用avformat_network_init()再avformat_open_input(),否则报“Protocol not found”;FFmpeg 4.0+需用avcodec_parameters_to_context()初始化解码上下文,再avcodec_open2();解码循环严格配对av_read_frame()→avcodec_send_packet()→avcodec_receive_frame(),注意时间基转换与内存释放。

初始化FFmpeg库并打开输入文件
必须先调用 avformat_network_init()(即使不涉及网络流,某些封装格式如 HLS 也依赖它),再用 avformat_open_input() 打开文件。常见错误是跳过初始化,导致 avformat_open_input() 返回负值且 av_strerror() 显示 “Protocol not found”。
- 检查返回值:若
avformat_open_input()返回 av_strerror() 打印具体错误,不要只看 NULL 判断 - 成功后必须调用
avformat_find_stream_info()—— 它会读取若干包来探测编码参数,否则大部分AVStream的codecpar字段为空或不完整 - 注意:该函数可能耗时,对实时性要求高的场景可设
options参数控制 probesize 和 analyzeduration,但默认值通常够用
遍历流并识别视频流
FFmpeg 把音视频、字幕等都视为“流”,需手动查找类型为 AVMEDIA_TYPE_VIDEO 的流。别直接假设索引 0 是视频流 —— MP4/AVI 等容器里音频流可能排在前面。
- 用
av_find_best_stream()最稳妥:av_find_best_stream(fmt_ctx, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0)返回视频流索引;失败时返回负数 - 手动遍历时,检查每个
stream->codecpar->codec_type,而非stream->codec->codec_type(后者在未调用avcodec_parameters_to_context()前不可靠) - 拿到视频流索引后,务必用它访问
fmt_ctx->streams[video_index],而不是硬编码索引
解码前准备编解码上下文
FFmpeg 4.0+ 强制分离参数与上下文,AVStream->codec 已废弃。必须用 avcodec_parameters_to_context() 将流参数复制到新分配的 AVCodecContext,再打开解码器。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
- 步骤顺序不能错:先
avcodec_parameters_to_context(ctx, stream->codecpar),再avcodec_open2(ctx, codec, NULL) - 若
avcodec_open2()失败,常见原因是没有正确设置ctx->pkt_timebase或硬件加速相关字段(如ctx->hw_device_ctx),但纯软件解码时一般不需要 - 解码器打开后,
ctx->time_base是解码时间基,后续计算 PTS/DTS 要用它,不是流的time_base
逐包解码并处理帧
核心循环是 av_read_frame() → avcodec_send_packet() → avcodec_receive_frame()。三者必须严格配对,否则容易卡死或丢帧。
立即学习“C++免费学习笔记(深入)”;
-
av_read_frame()读出的AVPacket必须用av_packet_unref()释放,否则内存泄漏;送入解码器前可检查pkt.stream_index是否匹配视频流索引 -
avcodec_send_packet()返回AVERROR(EAGAIN)表示输入缓冲满,需先调avcodec_receive_frame()取出已解码帧;返回AVERROR_EOF表示输入结束 -
avcodec_receive_frame()成功后,frame->pts是基于解码器 time_base 的时间戳,要转成秒需乘以av_q2d(ctx->time_base)
真正麻烦的是时间戳对齐和帧率推断——容器里未必有可靠 fps,AVStream->r_frame_rate 是编码器建议值,AVStream->avg_frame_rate 可能为 0,实际显示节奏得靠解码帧间差值或重采样逻辑控制。

















