unsigned char *packetBuf; 用来存储解码分片包
unsigned int packetLen; 记录已经存储的长度
每一个RTP包头长度RTP_HEADER_LEN为12,
RTP头后面就是H264数据,
对于RTP里的FU-A分片的H264数据需要重新组包后才能喂给解码器
定义:
unsigned char *data UDP接收数据
unsigned int len 接收UDP数据长度
PACKET_LEN = 1024 * 300
默认RTP的P=0(如果为1则在rtp包末尾减1的非有效荷载即可)
H264数据:
unsigned char *payload = data + RTP_HEADER_LEN;
fu_indicator:FU-A分片包定义头
unsigned char fu_indicator = *payload;
fu_header: FU-A分片包定义头
unsigned char fu_header = *(payload + 1);
startBit == 1表示分片的起始包
unsigned char startBit = fu_header >> 7;
endBit == 1表示分片的结束包
unsigned char endBit = (fu_header & 0x40) >> 6;
payload_len H264的长度
unsigned int payload_len = len - RTP_HEADER_LEN;
futype: 判断当前接受到包的类型
uint8_t futype = fu_indicator & 0x1f;
:28即表示接收到的FU-A包 拼包只拼此类型的包其他为完整的h264包
:7 sps
:8 pps
nal_fua 用于在拼包时重写H264头 即fu_indicator的前3位和fu_header的后5位
uint8_t nal_fua = (fu_indicator & 0xe0) | (fu_header & 0x1f);
定义每个包的分割头,用于在组包时添加到每个包的包头
uint8_t header[4] = {0x00, 0x00, 0x00, 0x01};
组包过程
- PACKET_LEN实例化一块内存的长度,用来存储分片数据
- block 即将数据传给解码器解码
if (futype == 28) {
if (endBit == 1) {
memcpy(packetBuf+packetLen, payload + 2, payload_len - 2);
packetLen += (payload_len - 2);
block(packetBuf, packetLen);
packetLen = 0;
memset(packetBuf, 0, PACKET_LEN);
} else if (startBit == 1) {
memcpy(packetBuf, header, sizeof(header));
*(packetBuf + sizeof(header)) = nal_fua;
memcpy(packetBuf + sizeof(header) + 1, payload + 2, payload_len-2);
packetLen = payload_len - 2 + 4 + 1 ;
} else {
if (packetLen > 0) {
memcpy(packetBuf + packetLen, payload + 2, payload_len - 2);
packetLen += (payload_len - 2);
}
}
}
单包
- 比如futype==7 || futype==8
- 不需组包,直接拼接header
- PACKET_LEN实例化一块内存的长度,用来存储分片数据
- block 即将数据传给解码器解码
unsigned int pl = payload_len + sizeof(header);
memcpy(packetBuf, header, sizeof(header));
memcpy(packetBuf + sizeof(header), payload, payload_len);
block(packetBuf, pl);
memset(packetBuf, 0, PACLET_LEN);
解RTP FU-A结束
网友评论