3.0 KiB
3.0 KiB
HLS 输出文件无法生成问题修复
问题描述
在测试 5 路并发处理时,发现 RTSP 输出正常,但 HLS 输出目录始终为空,没有生成 .ts 分片文件和 .m3u8 播放列表。
现象
- FFmpeg muxer 初始化成功(日志显示
muxer server ready) - 编码器正常工作(日志显示
encoded frames=xxx) av_interleaved_write_frame调用成功无错误- 但 HLS 目录中始终没有任何文件生成
根本原因分析
1. 关键帧检测错误
在 src/hw_codec.cpp 的 MppEncoder 类中,关键帧检测存在两处问题:
// 错误代码(修复前)
RK_U32 flag = mpp_packet_get_flag(packet);
out.keyframe = (flag & 0x08) != 0; // 错误的标志位
问题 1:标志位错误
- 代码使用
0x08检测关键帧 - 但
MPP_PACKET_FLAG_INTRA实际值为0x10(0x00000010)
问题 2:MPP 标志不可靠
- 实际测试发现 MPP 返回的
flag值始终为 0 - 即使对于 IDR 帧,MPP 也没有设置关键帧标志
2. HLS 需要关键帧才能写入
FFmpeg 的 HLS muxer 需要接收到关键帧(IDR 帧)才能开始写入分片。由于所有帧都被标记为非关键帧,HLS muxer 无法开始分片,导致没有文件生成。
修复方案
通过解析 H264 NAL 单元类型来检测关键帧:
// 修复后的代码
out.keyframe = (flag & 0x10) != 0; // MPP_PACKET_FLAG_INTRA = 0x00000010
// Fallback: 通过 NAL 类型检测关键帧
if (!out.keyframe && len >= 5) {
const uint8_t* d = out.data.data();
for (size_t i = 0; i + 4 < len && i < 1000; ++i) {
// 查找 NAL 起始码 00 00 00 01
if (d[i]==0 && d[i+1]==0 && d[i+2]==0 && d[i+3]==1) {
uint8_t nal_type = d[i+4] & 0x1F;
// NAL type 5 = IDR slice (关键帧)
// NAL type 7 = SPS (序列参数集,通常伴随关键帧)
if (nal_type == 5 || nal_type == 7) {
out.keyframe = true;
break;
}
}
}
}
NAL 类型参考
| NAL Type | 含义 | 是否关键帧 |
|---|---|---|
| 1 | 非 IDR 切片 | 否 |
| 5 | IDR 切片 | 是 |
| 6 | SEI 补充增强信息 | 否 |
| 7 | SPS 序列参数集 | 是(伴随关键帧) |
| 8 | PPS 图像参数集 | 否 |
验证结果
修复后验证 5 路并发 HLS 输出:
$ ls -la web/hls/cam1/
-rw-rw-r-- 1 477708 index0.ts
-rw-rw-r-- 1 473384 index1.ts
-rw-rw-r-- 1 522828 index2.ts
-rw-rw-r-- 1 510420 index3.ts
-rw-rw-r-- 1 227 index.m3u8
$ cat web/hls/cam1/index.m3u8
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:6
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-DISCONTINUITY
#EXTINF:5.933000,
index0.ts
#EXTINF:5.467000,
index1.ts
...
- ✅ 5 路并发 HLS 输出正常
- ✅ 每路生成
.ts分片文件和.m3u8播放列表 - ✅ 分片时长约 5-6 秒,符合配置
- ✅ RTSP 输出同时正常
相关文件
src/hw_codec.cpp: MPP 编码器关键帧检测逻辑
修复日期
2026-02-26