在对音视频从新编码并须要进行同步的场景中,须要遵照几项基本原则(不然音视频就会卡顿,不流畅。以音频aac编码频率44.1k,视频h264编码25帧帧率为例):
1. 保证输入端的音视频帧到达间隔基本精确。音频aac每帧时长是23.2ms(1000*1024/44100),视频每帧时长是40ms(1000/25)。因此,用于编码的原始音频samples的到达频率(或从buffer中获取的频率)应该为441 samples/per channel/ per 10ms(每一个样本假设16bits,即882字节/通道/10ms,若是原始音频采样率不是44.1k,编码前须要从新采样);原始视频帧到达频率(或从buffer中获取的频率)应该为1帧/per 40ms(视频帧率可能须要从新采样)。若是输出的音视频流不流畅,可先检查输入端音视频流的输入间隔状况。
2.保证输出端的音视频流时间戳使用同一参考系。好比音视频流都使用当前系统时间做为同一时间参考系,但音视频流能够有不一样的系统时间起始点。好比音频流先开始于1492764087000 ms,视频稍后700ms开始于1492764087700ms。好比rtmp里面使用32位时间戳,则音视频流只能使用相对时间戳,接上例,音频时间戳增加到700ms的时候视频流才从0开始,表示视频流是从音频流的700ms处开始的,这样才能达到同步的效果。 另一种时间戳方案是每一个音视频帧按固定间隔增加,好比音视频时间戳都从0开始,音频每一个aac帧增长23.2ms,每一个视频帧增加40ms。正常状况下,音视频流是同时从0开始按相应各自间隔发送帧的,但也有视频流晚于音频流或音频流晚于视频流的状况。这种状况须要作时间戳同步,稍晚的流起始时间要根据超前的流的时间来设置。前端
3.保证交叉输出时音视频间隔基本精确。这里的输出端就彻底等同于一个硬件编码器,只有保证交叉输出的音视频帧间隔稳定,才能保证播放端的流畅。好比rtmp,每一个aac音频帧输出间隔应该在23ms左右,每一个视频帧输出间隔应该在40ms左右,并且音视频帧是交叉输出。换句话说,每23ms要发送一个aac音频帧,每40ms发送一个视频帧(可使用两个单独的线程来分别发送音视频流)。若是排除了上面的两个问题仍是不能流畅播放,能够检查这个环节是否正常。
编码
总之,从新编码并同步的这个环节,必须创建在数学测量的基础上。有错误或补充的地方,欢迎指出。spa
下面是一个实际项目中基于以上规则的调整实现版本:线程
实际环境中与上述假设条件不符的地方:视频
1.前端输入帧率变化,x264不能稳定输出每秒固定24/25帧。同步
时间戳调整方案:由标准的音视频固定帧间隔累加调整为按帧间实际时间偏移累加。如音频,再也不按每帧间隔23ms去累加,缘由是会出现系统时间间隔1s的状况下音频时间戳增长小于1s的状况;视频再也不按每帧间隔40ms去累加,也改成实际帧间间隔,好比每次编码完以后每帧之间间隔是变化的,帧率可能不到24/25。最终实现音视频时间戳的同步。以系统绝对时间间隔来增长音视频时间戳自己就是同步的;若是使用其余人为制定的时间戳增加方案(好比上面的音视频按固定间隔递增),就须要再引入一个同步模块来处理音视频时间戳之间的递增偏移问题,比较麻烦也难于精确控制。该方法其实就是上面提到的第2条原则:音视频使用同一时间参考系。数学
项目中几种尝试过的错误的方案:it
1. 上面标准的音视频帧间隔累加计算时间戳。这种状况会出现音视频时间戳偏移愈来愈大的问题,可能视频大于音频或者音频大于视频,时间戳会差距愈来愈大。基础
2. 视频流使用原始帧时间戳做为参考。此种方法也不可取,缘由是原始帧的时间戳是基于原始视频流帧率的,你x264从新编码后,帧率已经不同了。帧与帧之间的间隔也没有参考意义。音频