从零实现RTSP服务器系列(二):基于UDP的H.264 RTP传输
📚 核心知识回顾
1. RTP协议报文结构
// RTP头部定义(12字节)
struct RTPHeader {
uint8_t cc : 4; // CSRC计数器
uint8_t extension : 1; // 扩展标志
uint8_t padding : 1; // 填充标志
uint8_t version : 2; // 版本号(固定2)
uint8_t payloadType : 7; // 负载类型(H.264=96)
uint8_t marker : 1; // 标记位
uint16_t seq; // 序列号
uint32_t timestamp; // 时间戳(90000Hz时钟)
uint32_t ssrc; // 同步信源标识
};
2. H.264关键概念
术语 说明 示例值 NALU 网络抽象层单元 0x00000001 SPS 序列参数集 profile=100 PPS 图像参数集 pic_parameter_set_id=0 IDR帧 即时解码刷新帧 NALU Type=5 FU-A 分片单元类型A FU Indicator=28
常见本地文件的H264码流的Nalu类型表
十六进制 十进制 Nalu Type 0x67 103 7 0x68 104 8 0x06 6 6 0x65 101 5 0x61 97 1 0x41 65 1 0x01 1 1 0x09 9 9
🛠️ 实战开发步骤
1. 生成H.264测试文件
ffmpeg -i input.mp4 -c:v copy -bsf:v h264_mp4toannexb output.h264
或
ffmpeg -i test.mp4 -codec copy -bsf: h264_mp4toannexb -f h264 test.h264
2. RTP分片打包逻辑
// H.264分片打包示例
void send_rtp_packet(const uint8_t* data, int size) {
// FU Indicator结构
uint8_t fu_indicator = (nalu_type & 0xE0) | 28;
// FU Header结构
uint8_t fu_header = nalu_type & 0x1F;
if (is_first_packet) fu_header |= 0x80; // S标记
if (is_last_packet) fu_header |= 0x40; // E标记
// 构造RTP包
RTPPacket packet;
memcpy(packet.payload, &fu_indicator, 1);
memcpy(packet.payload+1, &fu_header, 1);
memcpy(packet.payload+2, data, size-2);
sendto(rtp_socket, &packet, sizeof(packet), 0, ...);
}
3. 关键时序控制
// 视频帧发送间隔控制(25fps)
const int FRAME_INTERVAL = 40; // ms
auto last_send_time = std::chrono::steady_clock::now();
while (true) {
auto now = std::chrono::steady_clock::now();
auto elapsed = std::chrono::duration_cast(now - last_send_time);
if (elapsed.count() >= FRAME_INTERVAL) {
send_rtp_frame();
last_send_time = now;
}
}
📊 RTP包结构示例
偏移量 字段 值 说明 0x00 Version 0x80 RTP版本2,无扩展 0x01 Payload Type 0x60 H.264负载类型 0x02 Sequence 0x1234 递增序列号 0x04 Timestamp 0xABCDEF 90000Hz时钟基准 0x08 SSRC 0xDEADBEEF 同步信源标识 0x0C FU Indicator 0x7C F=0, NRI=3, Type=28 0x0D FU Header 0x85 S=1, E=0, Type=5 0x0E Payload Data … H.264分片数据
⚠️ 开发注意事项
MTU限制 :UDP包建议不超过1400字节时间戳同步 :使用90000Hz时钟基准关键帧处理 :IDR帧需要完整发送SPS/PPS网络字节序 :所有整数字段需转换丢包处理 :需实现简单重传机制(后续课程讲解)
🚀 效果验证
ffplay -rtsp_transport udp rtsp://localhost:554/live
📚 学习资源推荐
RFC3550 - RTP协议规范(https://tools.ietf.org/html/rfc3550) H.264编码白皮书(https://www.itu.int/rec/T-REC-H.264) Live555开源项目(http://www.live555.com/)
下期预告:第三讲《基于UDP的AAC音频传输实现》即将发布!