avformat_open_input后必须调用avformat_find_stream_info以填充真实编码参数;av_dump_format仅输出容器层信息;时间基须从stream取,不可硬编码。

avformat_open_input 之后必须调用 avformat_find_stream_info
FFmpeg 打开媒体文件后,AVFormatContext 中的流(streams)只是初步解析出的容器层结构,各流的编码参数(如分辨率、采样率、codec_id)往往为空或不准确。必须显式调用 avformat_find_stream_info 才能触发解码器探测,填充真实音视频参数。
常见错误是跳过这步直接读 codecpar->width 或 codecpar->sample_rate,结果全为 0 或默认值。
- 调用前确保
AVFormatContext已成功初始化(avformat_open_input返回 0) - 推荐传入
NULL作为选项参数,避免干扰内部探测逻辑;若需控制探测深度,可传入AVDictionary *设置analyzeduration(单位微秒)和probesize(字节数) - 返回值 AVERROR_INVALIDDATA),不要忽略
遍历 streams 时注意区分 codecpar 和 codec
FFmpeg 4.0+ 强制使用只读的 codecpar(AVCodecParameters)描述流参数,不再允许直接操作 codec 字段。所有流信息读取必须通过 ic->streams[i]->codecpar。
误用 ic->streams[i]->codec 会导致编译失败(已被移除)或运行时未定义行为。
立即学习“C++免费学习笔记(深入)”;
-
codecpar->codec_type判断流类型:AVMEDIA_TYPE_VIDEO/AVMEDIA_TYPE_AUDIO - 视频流关键字段:
codecpar->width、codecpar->height、codecpar->format(像素格式)、codecpar->codec_id(如AV_CODEC_ID_H264) - 音频流关键字段:
codecpar->sample_rate、codecpar->channels、codecpar->format(采样格式,如AV_SAMPLE_FMT_S16)、codecpar->codec_id(如AV_CODEC_ID_AAC)
av_dump_format 输出的是容器层信息,不是解码后帧数据
av_dump_format 打印的是 demuxer 解析出的封装格式元数据(如 MP4 的 moov、MKV 的 Tracks),包括流数量、时间基、码率估算、编码 ID 等,但不包含帧率、GOP 结构、关键帧间隔等需解码分析的信息。
它常被误认为“已完全解析”,其实只是容器层快照。真正可靠的帧率要查 codecpar->framerate(有理数),或结合 avg_frame_rate 和 r_frame_rate 综合判断。
- 调用位置:应在
avformat_find_stream_info成功之后 - 输出目标:第三个参数设为 0 表示标准输出,设为 1 表示 stderr;调试时建议重定向到文件便于比对
- 注意:
bit_rate是封装层估算值,可能严重偏离实际编码码率,尤其对 VBR 音频
时间基(time_base)必须从 stream 取,不能硬编码
每个流有自己的时间基(AVRational time_base),表示该流中时间戳单位(如 {1, 1000} 表示毫秒)。错误地统一用 {1,AV_TIME_BASE} 或假设为 {1,1000000} 会导致 PTS/DTS 计算错乱,音画不同步。
典型场景是计算帧显示时间:必须用 stream->time_base 将 pkt.pts 转为秒,而不是直接除以固定分母。
- 视频流常用 time_base:
{1,1000}(MP4)、{1,12800}(某些 AAC 封装) - 音频流 time_base 往往与采样率相关,例如 48kHz 音频可能是
{1,48000} - 转换公式:
double seconds = av_q2d(stream->time_base) * pkt.pts;
实际读取流信息最易忽略的是:探测函数失败后仍继续访问 codecpar 字段,以及把容器层时间基和解码器内部时间基混为一谈。这两个点一旦出错,后续解码或同步逻辑基本不可修复。


















