AVPacket由av_read_frame()从AVFormatContext中逐帧读取,需先调用avformat_open_input()和avformat_find_stream_info()初始化,并用av_find_best_stream()获取目标流索引,读取后检查stream_index匹配再送解码。

AVPacket 怎么从文件或网络拿到
FFmpeg 里 AVPacket 不是你手动 new 出来的,而是靠 av_read_frame() 从 AVFormatContext 里一帧一帧读出来的。前提是已经调用 avformat_open_input() 和 avformat_find_stream_info() 完成初始化。
常见错误是没检查 stream_index 是否匹配目标解码流(比如视频流),直接往解码器送包,结果 avcodec_send_packet() 返回 AVERROR_INVALIDDATA。
- 先用
av_find_best_stream()找到视频流索引,记作video_stream_idx - 每次
av_read_frame()后,检查packet.stream_index == video_stream_idx - 不需要自己
av_packet_unref()再分配——av_read_frame()内部已管理好内存,你只管用完调av_packet_unref(&packet)释放
avcodec_send_packet() 返回 EAGAIN 怎么办
这是最常卡住的地方:不是数据错了,是解码器输入缓冲区满了,或者还没收到足够多的参考帧(尤其 H.264/H.265 的 IDR 帧)。它不表示失败,只是“稍后再试”。
正确做法是立刻调 avcodec_receive_frame() 尝试取输出,而不是重发 packet。
-
avcodec_send_packet()返回0→ 输入成功;返回AVERROR(EAGAIN)→ 别慌,马上去收 frame -
avcodec_receive_frame()返回0→ 成功拿到一个AVFrame;返回AVERROR(EAGAIN)→ 还没解出,继续送新 packet;返回AVERROR_EOF)→ 输入结束,但可能还有帧在解码器里没吐出来 - 务必循环调用
avcodec_receive_frame()直到它返回EAGAIN,否则会漏掉 flush 阶段的最后一两帧
AVFrame 的 data 和 linesize 怎么安全访问
解码出来的 AVFrame 是引用计数的,data[0] 指向 Y 分量(对 YUV420P),但它的内存不一定连续,linesize[0] 才是每行字节数——别直接用 width * bytes_per_pixel 算。
容易踩的坑:把 frame->data[0] 当成一块完整图像内存 memcpy,结果越界或花屏。
- YUV420P 下:
frame->data[0]是 Y,frame->data[1]是 U,frame->data[2]是 V;对应linesize[0]、linesize[1]、linesize[2] - 想拷贝整帧?用
av_image_copy()或按 plane 分别 memcpy,每行拷frame->linesize[i]字节,共frame->height >> (i ? 1 : 0)行 - 如果后续要转 RGB,别手写循环——用
sws_scale(),它内部会处理 linesize 对齐和 chroma subsampling
为什么解码出来的 AVFrame 时间戳乱了
AVFrame.pts 不是自动填好的。FFmpeg 默认只设 pkt_dts 和 pkt_pts 在 AVPacket 上,AVFrame.pts 需要你自己根据流时间基换算,或依赖解码器自动推导(部分解码器支持)。
多数情况下,应该用 av_frame_get_best_effort_timestamp(),它会综合 pkt_pts、pkt_dts 和解码器内部状态给出最合理的 pts。
- 别直接用
frame->pts,尤其当frame->pts == AV_NOPTS_VALUE时 - 换算公式:真实时间(秒)=
av_frame_get_best_effort_timestamp(frame) * av_q2d(video_stream->time_base) - 如果需要严格对齐音视频,还得把视频 pts 转成与音频 time_base 一致的值,用
av_rescale_q()
实际跑通的关键在于:送 packet 和收 frame 必须是两个独立循环,不能“送一个、等一个”;AVFrame 的内存布局必须按 plane + linesize 访问;时间戳永远别信裸 pts。这些点漏掉一个,画面就可能卡、绿、跳或不同步。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











