VLC 音频同步的核心代码在aout_DecSynchronize函数中,其中涉及到的变量及逻辑比较复杂,但其核心思想其实已经包含在了下面的注释中:
/**
* Depending on the drift between the actual and intended playback times,
* the audio core may ignore the drift, trigger upsampling or downsampling,
* insert silence or even discard samples.
* Future VLC versions may instead adjust the input rate.
*
* The audio output plugin is responsible for estimating its actual
* playback time, or rather the estimated time when the next sample will
* be played. (The actual playback time is always the current time, that is
* to say mdate(). It is not an useful statistic.)
*
* Most audio output plugins can estimate the delay until playback of
* the next sample to be written to the buffer, or equally the time until
* all samples in the buffer will have been played. Then:
* pts = mdate() + delay
*/
简单来说,就是VLC通过计算得到了音频的实际播放时间和预期播放时间,drift时移即为实际播放时间和预期播放时间的差值,根据drift的值来决定对音频进行上采样、下采样、填0、丢帧或正常播放。
目录
1.预期播放时间
2.实际播放时间
1)AudioTrack delay
2)RingBuffer delay
3.drift
4.起播分析
1.预期播放时间
预期播放时间比较简单,就是该音频帧期望播放的系统时间,只需要将音频帧的pts从streaming时钟转换成系统时钟即可,对应的是aout_DecSynchronize函数的参数dec_pts。即预期播放时间 = dec_pts。
2.实际播放时间
我们知道,类似Android AudioTrack等音频输出插件内部基本都是有缓存的,VLC在往AudioTrack喂数据前又添加了一块RingBuffer。因此,我们需要先计算出这两块缓存内部数据能够播放的时间(delay,代码里写作cache),加上当前的系统时间才能够计算出下一帧buffer的实际播放时间。即实际播放时间 = mdate() + delay。
通过上面的介绍我们知道delay其实是由两部分组成的:AudioTrack的delay和RingBuffer的delay。VLC在audiotrack.c的TimeGet函数中分别计算了这两个delay的值:
1)AudioTrack delay
AudioTrack的delay只需要用当前已经写入AudioTrack的sample数减去AudioTrack播放的sample数就可以了。<