rtp包易于过大,一般每个包不要超过1400,这里设置为1380,即DEFAULT_MTU=1380
这里介绍的媒体格式有视频:H264/H265,音频:AAC
1、如果媒体包小于DEFAULT_MTU时可直接写入rtp包中,示例代码:
unsigned char *pNAL; //媒体数据包
int nalsize; //媒体数据包长度
uint32_t timestamp; //时间戳
// RTPSession rtp_session;
/* H264、H265 */
// 以jrtplib以为发送H264/H265视频数据的rtp包,成功时返回值是0
rtp_session.SendPacket(PacketData,PacketDataSize,96,true,(uint32_t)timestamp);
/* AAC */
uint8 aacHeader[4]={0x00,0x10,0x04,0xb8};
aacHeader[2] = nalsize >> 5;
aacHeader[3] = (nalsize & 0x1F) << 3;
memcpy(PacketData,aacHeader,sizeof(aacHeader));
memcpy(PacketData+sizeof(aacHeader),pNAL,nalsize);
PacketDataSize = nalsize+sizeof(aacHeader);
// 以jrtplib以为发送AAC音频数据的rtp包,成功时返回值是0
rtp_session.SendPacket(PacketData,PacketDataSize,97,true,(uint32_t)timestamp);
2、当媒体数据的包长度超过DEFAULT_MTU时需要采用分片封包模式(FUs),示例代码:
unsigned char *pNAL; //媒体数据包
int nalsize; //媒体数据包长度
uint32_t timestamp; //时间戳
unsigned char PacketData[DEFAULT_MTU]; //rtp数据包
uint32_t PacketDataSize = 0; //rtp数据包长度
int rtp_head_size = 0;
//计算rtp包头需要的信息
#if H264 || AAC
const uint8_t fu_indicator = (pNAL[0] & 0xe0) | 28;
const uint8_t fu_header = pNAL[0] & 0x1f;
pNAL++;
nalsize--;
rtp_head_size = 2;
#else if H265
const uint8_t payloadhdr[2]={(pNAL[0]&0x81)|(49<<1),pNAL[1]};
const uint8_t fu_header = (pNAL[0] & 0x7E)>>1;
pNAL+=2;
nalsize-=2;
rtp_head_size = 3;
#endif
//计算需要拆分的片数
uint32_t FU_size = 0;
if((nalsize % (DEFAULT_MTU-rtp_head_size))!=0)
FU_size=nalsize / (DEFAULT_MTU-rtp_head_size) +1;
else
FU_size=nalsize / (DEFAULT_MTU-rtp_head_size);
int start = true; //第一个分片标记
bool end_mask = false; //最后一个分片标志
while(nalsize>0){
const uint32_t fraglen = MIN(DEFAULT_MTU-rtp_head_size, nalsize);
PacketDataSize = fraglen+rtp_head_size;
#if H264 || AAC
PacketData[0]=fu_indicator; //rtp包第一个字节
PacketData[1]=fu_header; //rtp包第二个字节
#else if H265
PacketData[0]=payloadhdr[0]; //rtp包第一个字节
PacketData[1]=payloadhdr[1]; //rtp包第二个字节
PacketData[2]=fu_header; //rtp包第三个字节
#endif
if (start) { //第一个分片需要在最高位需要至1
PacketData[rtp_head_size-1] |= (1<<7);
start = false;
}
if (fraglen == nalsize) { //最后一个分片需要在第2高位需要至1
PacketData[rtp_head_size-1] |= (1<<6);
end_mask=true;
}
memcpy(PacketData+rtp_head_size, pNAL, fraglen); //剩下的数据接在后面
// RTPSession rtp_session;
// 以jrtplib以为发送H264/H265视频数据的rtp包,成功时返回值是0
rtp_session.SendPacket(PacketData,PacketDataSize,96,end_mask,(uint32_t)timestamp);
// 以jrtplib以为发送AAC音频数据的rtp包,成功时返回值是0
rtp_session.SendPacket(PacketData,PacketDataSize,97,true,(uint32_t)timestamp);
//媒体数据包去掉已经发送的部分
nalsize -= fraglen;
pNAL += fraglen;
}