从零实现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类型表
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<std::chrono::milliseconds>(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分片数据 |
⚠️ 开发注意事项
🚀 效果验证
# 使用FFplay验证流媒体
ffplay -rtsp_transport udp rtsp://localhost:554/live
📚 学习资源推荐
下期预告:第三讲《基于UDP的AAC音频传输实现》即将发布!
评论前必须登录!
注册