由于音视频流是以两条独立的数据流在网络上传输的,如果网络质量相当差,那么在接收端收到的音视频数据流就有可能不是同步的了,为了克服这种不同步的现象,需要添加同步机制。的同步机制是使用开源库jrtplib3.7.1来实现的,严格遵守rtp协议标准。
解决的方案如下:
当有数据需要发送时,往数据中加入时间戳,在接收端,读取时间戳,进行比较,如果相同或相差很近,就提交播放,如果其中一个时间戳更大,就等待。如果网络质量很差,那么存在两种不同步的情况:
1. 对于单条数据流来说,如果网络质量很差,可能出现数据流的接收不流畅,如果没有做流畅处理,那么就可能出现抖动现象,这需要使用rtp中的时间戳解决。
2. 对于多条数据流来说,如果网络质量很差,可能出现本应该同时播放的数据帧没有在同一时间到达,需要做同步处理。
解决第1个问题的方法是向每个发送的数据包加上时间戳,在rtp库中,时间戳表示在打包数据段中*个采样所对应的时间,时间戳的启始值是随机的,后续的时间戳是在前一个时间戳上的增量,在SendPacket中的时间戳参数表示的是时间戳增量,所以数据流的同步需要计算出时间戳增量。
对于音频数据,由于音频数据的采样率是8000Hz,所以每采样一次需要时间是1/8000s,由于是每20ms封包一次,所以时间戳的增量是(20*10**-3)*8000=160。
对于视频数据,由于视频数据的采样率是90000Hz,所以每采样一次需要时间是1/90000s,如果帧率是25帧/s,所以时间戳增量是90000/25=3600。
在发送端,每发送一个数据包,都打上该数据包对应的时间戳值,只需要向SendPacket的zui后个参数传递时间戳增量,rtp库会自动算出时间戳,并加到发送的rtp数据包首部里边。
在接收端,当收到一个数据包时,获取该rtp数据包的时间戳值,计算出与前一个数据包的时间戳值的差值,乘以该媒体流的时间戳单位,就得出了当前数据包与前一个数据包之间的间隔的打包时间T。所以只要保证在与前一个数据包被提交过后T时间后再提交当前接收到的数据包,那么在rtp层就解决了上边提出的*个问题。
解决第2个问题的方法是使用rtcp发送者报告数据包中的时间信息,发送者报告被发送的间隔时间是不固定的,它的大小与参与到会话中的同步源数量成正比。每个发送者报告中都有个ntp时间和rtp时间,该ntp时间表示在发送时间戳为该rtp时间的rtp包时的系统时间,就是在发送这个rtp包时的系统时间,所以这两个时间值有对应关系,由于对于一个同步源,时间戳单位是固定的,所以可以由后续的某个数据包的rtp时间戳计算出这个数据包所对应的时间,这个时间就是在发送这个数据包时,发送端的系统时间。
使用这种方法就可以计算出每个收到的rtp数据包在发送端的系统时间,这个系统时间在发送端是单调递增的,所以可以通过这个值来同步多条数据流。