ffmpeg解析hevc帧必须使用avcodec_send_packet与avcodec_receive_frame循环配合;需正确传入vps/sps/pps到extradata,确保avpacket指向完整nalu,避免eagain卡顿,并注意yuv对齐及bit-depth动态性。

用 FFmpeg 解析 HEVC 帧,核心是 avcodec_send_packet + avcodec_receive_frame
HEVC 解析不是“读文件→解码→完事”,而是必须走 FFmpeg 的新式解码流程:送 AVPacket 进解码器,再循环取 AVFrame。老的 avcodec_decode_video2 已废弃,强行用会丢帧、卡死或返回 AVERROR(EAGAIN)。
关键点:
- HEVC 码流可能含 VPS/SPS/PPS,必须在调用
avcodec_open2前把它们喂给解码器(通过avcodec_parameters_from_context或手动 setextradata) -
AVPacket的data必须指向完整 NALU(不能是裸 EBSP,也不能跨 NALU 拼接) - HEVC 的 NALU 类型判断要靠
(data[0] & 0x7E) >> 1,不是 H.264 的data[4] & 0x1F
HEVC 的 SPS/PPS/VPS 怎么提取和传给解码器
如果输入是 MP4 或 MKV,FFmpeg 通常自动从容器里抽出了 extradata 并塞进 AVCodecParameters;但如果是裸 .h265(Annex B 格式),就得自己解析 NALU 并拼成 extradata。
实操建议:
- 扫描文件头几百字节,找 0x00000001 或 0x000001 开头的 NALU,用
av_probe_input_buffer2辅助判断是否 HEVC - VPS(NALU type == 32)、SPS(33)、PPS(34)必须按顺序拼接:
VPS+SPS+PPS,长度写入codecpar->extradata_size,数据指针写入codecpar->extradata - 别漏掉 start code 长度——MP4 用 length-based,Annex B 用 0x00000001,二者
extradata构造方式不同
为什么解码器总返回 AVERROR(EAGAIN) 或卡在第一帧
这是 HEVC 解析最常卡住的地方:不是代码错,而是流程没跑满。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
典型原因:
-
avcodec_send_packet返回 0 后,没继续调avcodec_receive_frame直到它返回AVERROR(EAGAIN)—— HEVC 的帧间依赖可能导致多包才出一帧,或一包出多帧(B帧重排) - 送了空包(
pkt.data == nullptr)却没意识到这是 flush 信号,导致解码器内部缓冲未清空 - 时间戳(
pkt.pts/dts)全为AV_NOPTS_VALUE,FFmpeg 内部帧排序失效,avcodec_receive_frame可能永远等不到可输出帧
正确 flush 写法:
avcodec_send_packet(codec_ctx, nullptr);
while (avcodec_receive_frame(codec_ctx, frame) == 0) {
// 处理帧
}
YUV 数据布局和内存对齐要注意什么
HEVC 解码输出默认是 AV_PIX_FMT_YUV420P,但 planar 布局下各 plane 行宽(linesize[0])不一定等于图像宽度——FFmpeg 会按 32 或 64 字节对齐,尤其在硬件加速(如 h265_qsv)时更明显。
别直接 memcpy 整个 frame->data[0] 到自定义 buffer:
- 用
frame->linesize[i]逐行 copy,而不是width * bytes_per_pixel - 检查
frame->height和av_frame_get_height(frame)是否一致(后者考虑了对齐填充) - 若需转 RGB,优先用
sws_scale而非手写循环——HEVC 的 10-bit 输出(AV_PIX_FMT_YUV420P10LE)会额外增加位宽处理逻辑
HEVC 的 bit-depth 和 chroma format 在 SPS 里定义,解码器输出格式由 frame->format 实时决定,不能硬编码假设为 8-bit YUV420P。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










