// 申请一块内存用于存储rtp包数据,初始化rtp包头
struct RTP_PACKET_S * rtpPacket = (RTP_PACKET_S *)malloc(500000);
rtpHeaderInit(rtpPacket, 0, 0, 0, RTP_VERSION, RTP_PAYLOAD_TYPE_H264, 0, 0, 0, 0x88923423);
// 创建套接字
rtpServerSockfd = socket(AF_INET, SOCK_DGRAM, 0);
// 打开h.264文件
int fd = open(argv[1], O_RDONLY);
// 申请内存用于读取h.264文件内容
uint8_t * frame = (uint8_t*)malloc(500000);
while(1)
{
// 读取h.264文件
readSize = read(fd, frame, 500000);
// 找到第一个NALU数据,不包含00 00 01/00 00 00 01分隔
getFirstNaluFrame(frame, 500000, &offset, &naluLen);
// 处理并发送NALU数据
rtpSendH264Frame(rtpServerSockfd, CLIENT_IP, CLIENT_PORT, rtpPacket, frame + offset, naluLen);
// 移动文件读写位置到下一个NALU起始处
lseek(fd, fd_Lseek, SEEK_SET );
// 发送完一包NALU后,根据帧率计算延时
usleep(1000*1000/FPS);
}
// rtpSendH264Frame函数分析
static int rtpSendH264Frame(int rtpSockfd, char * ip, int16_t port, struct RTP_PACKET_S * rtpPacket, uint8_t * naluFrame, int naluLen)
{
// 1.单NALU打包
// 填充payload
memcpy(rtpPacket->rtpPayload, naluFrame, naluLen);
// udp发送
sendto(rtpSockfd, (void*)rtpPacket, naluLen + RTP_HEADER_SIZE, 0, (struct sockaddr *)&addr, sizeof(addr));
// 2.分片打包
// 计算完整包个数和最后一包剩余字节数
int packetNum = naluLen / RTP_MAX_PKT_SIZE; // 有几个完整的包
int lastRemainSize = naluLen % RTP_MAX_PKT_SIZE; // 最后一包剩余的字节数
for(int i = 0; i < packetNum; i++) // 发送所有整包
{
// 分片发送是payoad前需加2字节的数据,具体见"4.将H264码流打包成RTP包.md"
rtpPacket->rtpPayload[0]
rtpPacket->rtpPayload[1]
// 填充payload
memcpy(rtpPacket->rtpPayload+2, naluFrame+pos, RTP_MAX_PKT_SIZE);
// udp发送
sendto(rtpSockfd, rtpPacket, RTP_HEADER_SIZE+RTP_MAX_PKT_SIZE+2, 0, (struct sockaddr *)&addr, sizeof(addr));
}
if(lastRemainSize > 0) // 发送剩余的数据
{
// 分片发送是payoad前需加2字节的数据,具体见"4.将H264码流打包成RTP包.md"
rtpPacket->rtpPayload[0]
rtpPacket->rtpPayload[1]
// 填充payload
memcpy(rtpPacket->rtpPayload+2, naluFrame+pos, lastRemainSize+2);
// udp发送
sendto(rtpSockfd, (void*)rtpPacket, RTP_HEADER_SIZE+lastRemainSize+2, 0, (struct sockaddr *)&addr, sizeof(addr));
}
}