FFmpeg开发笔记(三十三)分析ZLMediaKit对H.264流的插帧操作

《FFmpeg开发实战:从零基础到短视频上线》一书的"3.4.3 把原始的H264文件封装为MP4格式"介绍了如何把H.264裸流封装为MP4文件。那么在网络上传输的H.264裸流是怎样被接收端获取视频格式的呢?前文指出H.264流必定以"SPS帧→PPS帧→IDR帧"开头,接下来就来验证是否确实如此。

这里用到了雷霄骅雷神写的H264分析器,在此向雷神致敬,雷神10年前写的小程序至今仍然好用。打开H264分析器,该软件的初始界面如下图所示:

单击文件路径栏右边的打开按钮,在弹出的文件对话框中选择某个H.264裸流文件,再单击界面右下角的开始按钮,分析器便开始分析H264文件的内容格式,分析后的结果界面如下图所示:

从分析结果可见,H.264裸流的开头三帧果然是"SPS帧→PPS帧→IDR帧"。单击列表中的某个帧,界面右侧会显示该帧的详细字段信息。

当然,分析器只能读取H.264裸流文件。倘若让分析器读取MP4文件,就无法正常读出各帧信息。那么流媒体服务器又是怎么把MP4文件转化为H.264裸流的呢?

以ZLMediaKit为例,它在向推流序列插入I帧时做了特殊处理,一旦出现I帧,就自动插入SPS与PPS等配置帧。具体代码在ZLMediaKit框架的ext-codec/H264.cpp,查看该源码的H264Track::inputFrame_l函数,找到以下的代码片段,可见程序在判断关键帧之后调用了insertConfigFrame函数。

复制代码
// 判断是否是I帧, 并且如果是,那判断前面是否插入过config帧, 如果插入过就不插入了
if (frame->keyFrame() && !_latest_is_config_frame) {
    insertConfigFrame(frame); // 插入SPS帧和PPS帧
}
if(!frame->dropAble()){
    _latest_is_config_frame = false;
}
ret = VideoTrack::inputFrame(frame);

找到insertConfigFrame函数的定义代码如下,果然函数内容依次插入了SPS帧和PPS帧:

复制代码
// 插入SPS帧和PPS帧
void H264Track::insertConfigFrame(const Frame::Ptr &frame) {
    if (!_sps.empty()) { // 插入SPS帧
        auto spsFrame = FrameImp::create<H264Frame>();
        spsFrame->_prefix_size = 4;
        spsFrame->_buffer.assign("\x00\x00\x00\x01", 4);
        spsFrame->_buffer.append(_sps);
        spsFrame->_dts = frame->dts();
        spsFrame->setIndex(frame->getIndex());
        VideoTrack::inputFrame(spsFrame);
    }
    if (!_pps.empty()) { // 插入PPS帧
        auto ppsFrame = FrameImp::create<H264Frame>();
        ppsFrame->_prefix_size = 4;
        ppsFrame->_buffer.assign("\x00\x00\x00\x01", 4);
        ppsFrame->_buffer.append(_pps);
        ppsFrame->_dts = frame->dts();
        ppsFrame->setIndex(frame->getIndex());
        VideoTrack::inputFrame(ppsFrame);
    }
}

由此可见,ZLMediaKit在每个关键帧前面都额外插入了SPS帧和PPS帧,确保H.264裸流维持着形如"SPS帧→PPS帧→IDR帧"的队形。如果不添加SPS和PPS,客户端在拉流时会报错如下:

复制代码
[NULL @ 0000022ed7782540] non-existing PPS 0 referenced

只有加上SPS与PPS,客户端才能正常拉流解析数据,才能正常渲染视频画面。

更多详细的FFmpeg开发知识参见《FFmpeg开发实战:从零基础到短视频上线》一书。

相关推荐
音视频牛哥11 分钟前
SmartMediaKit macOS版RTSP/RTMP低延迟播放器:技术架构、核心能力与应用实践
音视频·低延迟rtsp播放器·macos直播播放器·macos rtsp播放器·macos rtmp播放器·rtsp播放器mac版·rtmp播放器mac版
潜创微科技3 小时前
沁恒CH9339:USB3.0超高速对拷,两台电脑一根线共享一切
音视频
Cxiaomu3 小时前
从 TRTC Demo 到独立音视频服务:React + TRTC Web SDK 服务化实践
前端·react.js·音视频
EasyGBS6 小时前
政务视频资源汇聚:国标GB28181视频平台EasyGBS在“一网统管”中的定位和落地路径
网络·音视频·政务
蝉蜕日记21 小时前
视频压缩 v1.1.31:高效压缩,无损画质,释放存储空间
音视频·生活·视频编解码·视频·软件需求
lumengabc1 天前
视频制作流程MP4旁白语音生成裁剪视频压缩python处理ppt转视频M4a格式
音视频
音视频牛哥1 天前
AI浪潮下,实时音视频SDK正在经历怎样的价值重构?
人工智能·音视频·实时音视频·rtmp推流·低延迟rtsp播放器·低延迟rtmp播放器·rtsp转rtmp推流
乐橙开放平台1 天前
明厨亮灶笔记:乐橙轻应用 H5 + 小程序插件,一套 BFF 出两张播放凭证
人工智能·笔记·物联网·小程序·音视频·notepad++
ofoxcoding1 天前
Seedance 2.0 与 Wan 2026 视频生成 API 成本效率深度对比分析
网络·人工智能·ai·音视频
xingyuzhisuan1 天前
星宇智算 AI 视频生成工具九维度全测评与行业对标分析
人工智能·音视频