有两种实现方式
第一种:直接发送
RtspServer_init
RtspServerListen
RtspClientMsg //线程1 : 不断监控是否又客服端来连接自己,并且建立双方的连接
if(strstr(cmdName, "OPTIONS")) OptionAnswer;
if(strstr(cmdName, "DESCRIBE")) DescribeAnswer;
if(strstr(cmdName, "SETUP")) SetupAnswer;
if(strstr(cmdName, "PLAY")) PlayAnswer;
if(strstr(cmdName, "PAUSE")) PauseAnswer;
if(strstr(cmdName, "TEARDOWN")) TeardownAnswer;
SAMPLE_VENC_720P_CLASSIC
SAMPLE_COMM_VENC_StartGetStream
SAMPLE_COMM_VENC_GetVencStreamProc //线程2 : 不断从海思的解码器中获取H.264码流
save_stream_rtsp
VENC_Sent //正真的发送数据
sendto(udpfd, sendbuf, bytes, 0, (struct sockaddr *)&server,sizeof(server));
//向UDP中发送数据
第二种:利用buffer和线程环回发送
RtspServer_init
RtspServerListen
RtspClientMsg //线程1 : 不断监控是否又客服端来连接自己,并且建立双方的连接
if(strstr(cmdName, "OPTIONS")) OptionAnswer;
if(strstr(cmdName, "DESCRIBE")) DescribeAnswer;
if(strstr(cmdName, "SETUP")) SetupAnswer;
if(strstr(cmdName, "PLAY")) PlayAnswer;
if(strstr(cmdName, "PAUSE")) PauseAnswer;
if(strstr(cmdName, "TEARDOWN")) TeardownAnswer;
vdRTPSendThread //线程2 : 不断监控全局变量的RTP_BUF是否为空,不为空就发送数据
VENC_Sent //正真的发送数据
sendto(udpfd, sendbuf, bytes, 0, (struct sockaddr *)&server,sizeof(server));
//向UDP中发送数据
SAMPLE_VENC_720P_CLASSIC
SAMPLE_COMM_VENC_StartGetStream
SAMPLE_COMM_VENC_GetVencStreamProc //线程3 : 不断从海思的解码器中获取H.264码流
saveStream
list_add_tail(&(p->list),&RTP_BUF);//添加数据
第一种:这种方式是,获取到一帧h.264码流,就马上通过rtsp发送。
优点:编写代码简单。
缺点:不能应对真实网络,有时候网络会阻塞,这样会导致上一帧还没有发送结束,下一帧就来了,这样会让视频的失真率变高。
第二种:这种利用全局变量buffer,把从海思中传来的视频流,先保存到buffer中,而单开的线程,只管发送数据,有就发,没有就等待。
优点:适合网络传输的需求。
缺点:编写代码复杂。
真正的发送函数:
HI_S32 VENC_Sent(char *buffer,int buflen);
这个函数包含了所有视频要发送的所操作,包括封包,拆包。
对于每一个NALU,根据其包含的数据量的不同,其大小也有差异。在IP网络中,当要传输的IP 报文大小超过最大传输单元MTU(Maximum Transmission Unit )时就会产生IP分片情况。在以太网环境中可传输的最大 IP 报文(MTU)的大小为 1500 字节。如果发送的IP数据包大于MTU,数据包就会被拆开来传送,这样就会产生很多数据包碎片,增加丢包率,降低网络速度。对于视频传输而言,若RTP 包大于MTU 而由底层协议任意拆包,可能会导致接收端播放器的延时播放甚至无法正常播放。因此对于大于MTU 的NALU 单元,必须进行拆包处理。
参考: