1.RTSP之TCP与UDP方式区别
TCP与UDP方式的区别在客户端项服务端SETUP请求中的Transport项体现。
TCP请求方式(RTSP over TCP)
此方式比较灵活,它不用另外建立音视频传输的Socket,而直接使用RTSP的Socket,这样做可以节省不少资源开支。由于采用TCP传输,数据的可靠性得到保障。
Transport项指定了TCP传输方式RTP/AVP/TCP。
UDP请求方式(RTSP over UDP)
此方式需要多建立两个Socket,用于RTCP、RTP数据传送。客户端在SETUP请求时的数据交互中Transport项指定了client_port=56934-56935,它是用来通知服务端与客户端建立Socket通信的。
总结
TCP传输方式使用的是原有的套接字,不用另开套接字,起到节省资源的作用,还能利用TCP的可靠性。另一方面它更具有穿墙的特性,在很多网络的路由中有设置不给于外网访问内网,此时用UDP方式,需要服务端主动连接客户端提供的UDP接口,这请求有可能被防火墙拦截,在抓包分析中表现出来是port unreachable(端口不可达)的错误提示,可见这种方式是比较受限制的。
综上,在可靠连接和资源方面考虑,在嵌入式安防产品中采用TCP方式较多。
2.关于RTSP播放VLC提示音频时间戳的问题
问题描述:使用海康的IPC连接NVR,用VLC播放NVR码流。过一段时间(几分钟)出现音频全部丢失的问题
视频解码,帧率发生变化。
视频时间戳 = 90000/帧率。
音频时间戳 = 320(8000 / 320 = 25)
IPC设置的帧率是12。视频计算时间戳的方式是90000/帧率。音频是直接拿帧长度赋值(320).解码出来视频的帧率是13,或者是12
如果把IPC的帧率改为25(最大值),VLC播放就正常。
IPC帧率为20,解码出为20和21,VLC播放正常。
IPC帧率为15,解码出为15和16,VLC播放一段时间音频失败
如果仅播放音频,音频就正常播放
2022.3.24:
- 添加上RTCP功能(发送SR包)解决了音频丢失的问题。但是画面卡顿(音视频全部会丢包)VLC显示帧率为29.97,但是NVR和IPC显示都是15帧。解析NVR的录像,也是15帧
- 开启VLC连接NVR的视频,发现NVR的本地画面非常卡。但是IE端画面无影响。
时间戳的单位:采样率的倒数。
对于ffmpeg,时间戳间隔为:presentation_time = frame_size/sample_rate;
frame_size:每帧数据对应的字节数
sample_rate:采样率,是指将模拟声音波形进行数字化时,每秒钟抽取声波幅度样本的次数
presentation_time:时间间隔,也就是该帧数据播放的时间长度,单位s,如果用毫秒为单位,乘上1000即可
presentation_time = frame_size*1000/sample_rate;
例如:AAC每帧数据对应的字节数为1024,如果sample_rate==32K,对应的时间间隔为1024*1000/32000 = 32ms
mp3每帧数据对应的字节数为1152 ,如果smple_rate==8k,对应的时间间隔为1152*1000/8000 = 144ms
时间戳的计算:
采样率:1秒采样的个数(采样点)(视频:90000,音频:8000)
帧率:1秒刷新的图片数量(采样率/帧大小)
时间戳:采样率的倒数。(一帧有多少个采样点)
设:一帧采样点数为X。
25 * X = 90000
X = 3600
视频帧率为25帧,播放音视频正常。时间戳:90000 / 25 = 3600
视频帧率变为20帧。时间戳:90000 / 20 = 4500
如果视频编码帧率为20,解码为25,视频很快播完,需要等视频。此时音频过来,就要丢掉。
办法:(音视频同步)补时间戳,不让视频很快播完或播放太快
因为RTCP线程用while循环实现5秒发一次SR包。但是没加usleep睡眠,导致CPU占用率很高(空跑),使NVR接收IPC的数据也很卡。(解决问题2)
2022.3.25
RTP配合RTCP实现音视频同步。
视频正常,音频会偶尔有卡顿。(可能是视频时间戳的问题)
采用计算视频帧率的办法,效果会好很多。
int timeout = 0;
static uint lasttime; //记录上一次视频帧到来的时间
uint time = 0;
//无论是P帧还是I帧,都是视频帧,都要计算
struct timeval tv;
gettimeofday(&tv, NULL);
timeout = tv.tv_sec * 1000 + tv.tv_usec/1000; //获取这次视频帧到来的时间
time = timeout - lasttime; //一个视频帧需要的时间
//printf("time = [%d]\n", time);
if(time > 0 && time <= 1000)
{
m_nRate = 1000 / time; //帧率(毫秒)
//printf("m_nRate = [%d]\n", m_nRate);
}
lasttime = timeout;
视频时间戳 += 90000 / m_nRate; //采样率/帧率
效果基本稳定
2022.3.26
发现IPC在加上RTCP功能后虽然有用。但是更改视频时间戳之后,即使去掉RTCP功能音视频也无影响。(其余型号IPC不能改,改了反而导致视频卡顿)
然后我就试试NVR去掉RTCP功能,只改视频时间戳是否也可以。
最后发现NVR的音频还是会丢。
总结
①:没有进行音视频同步。(加RTCP功能,配合RTP实现音视频同步)
②:视频时间戳不够准确。(自己计算视频帧到来的时间差,用1秒的时间除以这个时间差就是计算出来的视频帧率。然后采样率/帧率就是视频的时间戳)