safesight-edge/docs/bugfix_hls_keyframe_detection.md

113 lines
3.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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` 类中,关键帧检测存在两处问题:
```cpp
// 错误代码(修复前)
RK_U32 flag = mpp_packet_get_flag(packet);
out.keyframe = (flag & 0x08) != 0; // 错误的标志位
```
**问题 1标志位错误**
- 代码使用 `0x08` 检测关键帧
-`MPP_PACKET_FLAG_INTRA` 实际值为 `0x10` (0x00000010)
**问题 2MPP 标志不可靠**
- 实际测试发现 MPP 返回的 `flag` 值始终为 0
- 即使对于 IDR 帧MPP 也没有设置关键帧标志
### 2. HLS 需要关键帧才能写入
FFmpeg 的 HLS muxer 需要接收到关键帧IDR 帧才能开始写入分片。由于所有帧都被标记为非关键帧HLS muxer 无法开始分片,导致没有文件生成。
## 修复方案
通过解析 H264 NAL 单元类型来检测关键帧:
```cpp
// 修复后的代码
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 输出:
```bash
$ 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
```
```bash
$ 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