服务器端的sendto
- 首先要得到客户端的IP地址和端口号
struct sockaddr_in server;
server.sin_family=AF_INET;
server.sin_port=htons(g_rtspClients[is].rtpport[0]); // htons 转换为网络序
server.sin_addr.s_addr=inet_addr(g_rtspClients[is].IP);
-
计算出RTP timestamp,RTP timestamp表示每帧的时间,也同样是每帧之间时间间隔。
两帧之间RTP timestamp的增量 = 时钟频率 / 帧率
其中时钟频率可从SDP中获取(在描述DESCRIBE中),如:
m=video 2834 RTP/AVP 96
a=rtpmap:96 H264/90000其时钟频率为90000(通常视频的时钟频率),若视频帧率为25fps,则相邻帧间RTP timestamp增量值 = 90000/25 = 3600。
另外,通常音频的时钟频率一般为8000
注意:帧率要按照自己的帧率做修改;
- rtp_hdr RTP头
rtp_hdr =(RTP_FIXED_HEADER*)&sendbuf[0];
rtp_hdr->payload = RTP_H264; // 类型
rtp_hdr->version = 2; // rtp的版本号
rtp_hdr->marker = 0; // 当前包是不是最后一包的标志
rtp_hdr->ssrc = htonl(10); // 信源标记
这里的数组sendbuf[0] 数组首地址定义一个RTP_FIXED_HEADER*指针类型;
这个RTP_FIXED_HEADER结构体中的参数占用0~11个字节;这样一来下面的FU indicator就要从第12个字节地址开始了。
-
分包
h264包在传输的时候,如果包太大,会被分成多个片。NALU头会被如下的2个自己代替。
The FU indicator octet has the following format:
±--------------+
|0|1|2|3|4|5|6|7|
±±±±±±±±+
|F|NRI| Type |
±--------------+
别被名字吓到这个格式就是上面提到的RTP h264负载类型,Type为FU-A
为I帧NRI=1;非I帧RI=0; 为1的时候会代表受重视的成都要高。
The FU header has the following format:
±--------------+
|0|1|2|3|4|5|6|7|
±±±±±±±±+
|S|E|R| Type |
±--------------+
S bit为1表示分片的NAL开始,当它为1时,E不能为1
E bit为1表示结束,当它为1,S不能为1
R bit保留位
Type就是NALU头中的Type,取1-23的那个值 -
当一帧被分包发送的时候,NALU头会被如下的2个自己代替:FU indicator和FU header。这两个各位1个字节;
fu_ind =(FU_INDICATOR*)&sendbuf[12]; // 数组指针地址定位到数组12的位置
fu_ind->F= 0; // 由上面4.分包可以查看这些参数的位数
fu_ind->NRI= nIsIFrm; // 为I帧NRI=1;非I帧RI=0;
fu_ind->TYPE=28; // FU-A 分片的单元 查看NALU 可以理解
fu_hdr =(FU_HEADER*)&sendbuf[13];
fu_hdr->E=0;
fu_hdr->R=0;
fu_hdr->S=1;
fu_hdr->TYPE=nNaluType;
具体可参考本站介绍
https://blog.csdn.net/weixin_40673765/article/details/99583789