必须调用avcodec_send_packet(codec_ctx, nullptr)触发flush才能收全帧,否则含b帧的视频会丢最后2–5帧;av_frame_make_writable失败主因是原始帧未分配可写内存,需先av_frame_get_buffer;sws_scale颜色异常多因linesize设置错误,应使用av_image_fill_linesizes计算;windows链接需按avcodec.lib→avutil.lib→swscale.lib顺序。

ffmpeg\_avcodec\_send_packet 后没收到帧?检查解码器是否已 flush
很多初学者调用 avcodec_send_packet 后循环 avcodec_receive_frame,结果只拿到前几帧就卡住或提前退出——其实是因为视频末尾还有缓存帧未输出。FFmpeg 解码器内部会缓冲若干帧用于 B 帧依赖重建,必须显式发送空包触发 flush:
- 在输入 packet 全部送完后,调用一次
avcodec_send_packet(codec_ctx, nullptr) - 之后继续循环
avcodec_receive_frame,直到返回AVERROR_EOF - 漏掉这一步,MP4/H.264 等含 B 帧的视频大概率丢最后 2–5 帧
av\_frame\_make\_writable 失败导致写入崩溃?先确认像素格式和内存分配方式
想把 YUV 转成 RGB 或直接修改像素值时,av_frame_make_writable 返回负值(如 -22 即 AVERROR(EINVAL)),常见原因不是函数调用错,而是原始帧根本没分配可写内存:
- 从解码器拿到的
AVFrame*默认指向只读内存(尤其硬解或某些封装格式) - 若
frame->buf[0] == nullptr,说明没绑定AVBufferRef,此时av_frame_make_writable必失败 - 安全做法:先
av_frame_copy_props(dst, src),再av_frame_get_buffer(dst, 32)分配新内存,最后sws_scale拷贝数据
用 sws\_scale 转换分辨率/色彩空间时颜色发灰?检查 src/dst frame 的 linesize 对齐
sws_scale 输出图像偏暗、色块或绿屏,大概率是 AVFrame.linesize[] 设置错误,而非参数传错:
- YUV420P 的
linesize[0]是 width,但linesize[1]和linesize[2]应为width / 2(非width) - 手动创建 dst frame 时,别直接设
frame->linesize[i] = width;应调用av_image_fill_linesizes(frame->linesize, pix_fmt, width)计算 - libswscale 对 linesize 敏感,错一个字节就可能越界读写,表现为随机色块或 crash
Windows 下链接 libavcodec.dll 失败?优先用 pkg-config 或手动补全依赖链
VS 编译时报 LNK2019: unresolved external symbol avcodec_open2,不是头文件没包含,而是没连对动态库顺序:
立即学习“C++免费学习笔记(深入)”;
- FFmpeg 动态库有强依赖顺序:
avcodec→avutil→swresample(音频)或swscale(图像) - MinGW 用户用
pkg-config --libs libavcodec最稳;MSVC 用户需按avcodec.lib avutil.lib swscale.lib顺序添加到链接器输入 - 漏掉
avutil.lib是最常见原因,因为AVFrame、AVPacket等基础结构体定义都在里面
avcodec_send_packet(nullptr) 这一步,文档里轻描淡写,但几乎每个真实项目都会在这里卡半天。










