# 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