# GB28181 **Repository Path**: AndroidCoderPeng/GB28181 ## Basic Information - **Project Name**: GB28181 - **Description**: 国标推流Demo - **Primary Language**: Unknown - **License**: AGPL-3.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2025-08-26 - **Last Updated**: 2025-12-17 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Android平台(Java/Kotlin/C++)GB/T 28181-2016推流流程说明 ## 1. 初始化 SIP 参数并注册到国标平台 - 在 Java 层初始化 SIP 相关参数(如设备 ID、服务器地址、端口等),并通过 JNI 传递至 Native 层; - Native 层使用 **eXosip2** 库向国标平台(GB/T 28181)发起注册请求; - 注册成功后,记录程序启动的微秒级时间戳(即 `System.nanoTime() / 1000`),作为后续音视频帧时间戳的基准。 ## 2. 视频采集与编码 - 使用 **Camera1 API** 采集视频画面,获取 **YUV (NV21)** 格式的原始数据; - 将 **NV21 转换为 NV12**(适配硬件编码器输入要求); - 通过硬件编码器生成完整的 **H.264 帧数据**,**必须包含起始码(Start Code: `0x00000001`)**; > ⚠️ **关键提示**:若 H.264 帧缺少起始码,PS 封装将失败或平台无法解析,导致推流无画面! - 记录每帧编码完成时的时间戳(单位:微秒),相对于步骤 1 中的起始时间。 ## 3. 音频采集 - 使用 **AudioRecord** 采集原始 **PCM 裸流**(通常为 16-bit、单声道、8kHz); - 同样记录每帧音频数据的时间戳(单位:微秒),相对于步骤 1 中的起始时间。 ## 4. 拉流信令控制推流启停 - 客户端默认仅进行本地预览,不进行编码与推流; - 当国标平台下发 **拉流信令(Invite 请求)** 后,客户端才开始: - 启动音视频编码; - 封装并推送媒体流; ## 5. 视频帧封装为 PS 流 - 通过 JNI 将 H.264 帧数据传递至 Native 层; - 在 Native 层 提取 **SPS/PPS** 帧数据并初始化媒体复用器; > ⚠️ **关键提示**:必须在发送任何视频帧前完成复用器初始化,否则推流将无画面! - 根据平台分配的 **Stream ID**,将 H.264 数据封装为符合 **GB/T 28181 标准的 MPEG-TS/PS 流**。 ## 6. 音频帧编码与封装 - 通过 JNI 将 PCM 裸流传递至 Native 层; - 在 Native 层将 PCM 编码为 **G.711 μ-law**; - 同样根据 **Stream ID**,将 G.711 音频帧封装进同一 PS 流中,与视频同步复用。 > ⚠️ **关键提示**:PS封装极其麻烦,每个字段都需要搞清实际含义,否则无法正确封装! ## 7. PS 包分片处理 - 国标平台通常通过 **RTP over TCP/UDP** 传输 PS 流; - 由于 **RTP MTU 限制约为 1400 字节**,需对较大的 PS 包进行分片; - 判断每个 PS 包大小: - 若 ≤ 1400 字节:直接作为单个 RTP 包发送; - 若 > 1400 字节:按 RFC 3984 或 GB/T 28181 规范进行 **RTP 分片封装**。 ## 8. 网络传输 - 将封装好的 RTP 包(单包或分片)通过 **TCP 或 UDP** 发送至国标平台: - **TCP 模式**:连接可靠、抗丢包,适合网络不稳定环境; - **UDP 模式**:延迟更低,适合实时性要求高的场景; - 传输协议类型由平台信令协商确定,客户端动态适配。