113 lines
3.0 KiB
Markdown
113 lines
3.0 KiB
Markdown
# 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)
|
||
|
||
**问题 2:MPP 标志不可靠**
|
||
- 实际测试发现 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
|