播放器上音频断续问题的原因

这个问题足足花了我三个礼拜。当前产品的播放器在解分辨率高、码率也高的REAL文件时,音频播放一半会断掉,丢掉一小段BUFFER的数据,然后再继续。并且断的频率和码率呈正比。

既然是音频出了问题,当然先从音频查起,于是从DEMUX,到DECODE,再到PCM RENDER,被我翻了个遍,每个FILTER的INPUT和OUTPUT都加满了调试信息和时间戳的打印,追查两周仍然没有结果,AUDIO这块,并不存在什么问题。但基本上可以确认是由于音频解码来不及导致的。前面BUFFER的DURATION已经播放完成了,而下个BUFFER的数据还没到达,就会导致这种情况。

最后经方案商确认,只有两种可能,一是FITLER的INPUT/OUTPUT BUFFER的空/满状态引起CPU BLOCKING没有在干活,二是既然CPU满负荷工作,那么就是PERFORMANCE的问题了,当前CPU主频实在扛不住高码率的解码了。

1、先解决不让CPU BLOCK的问题。在CPU时间片吃紧的情况下,BUFFER POOL空满状态又和FILTER的优先级设置有关,并且十分敏感!DEMUX肯定必须是最高优先级,否则后面大家都别玩了. 看下面这张FILTERS连接图,应该说是播放器最原型的几个FILTER了

播放器上音频断续问题的原因

(1) 如果VIDEO DECODER和AUDIO DECODER都是中等优先级别,而RENDER是高优先级,那么由于VIDEO DECODER没有足够的时间片来解码,导致VIDEO BITSTREAM BUFFER POOL很快被DEMUX塞满了,进而导致DEMUX无法把后面的BUFFER塞进去,  于是DEMUX卡在那里等待VIDEO BITSTREAM BUFFER POOL不满, 这时候文件读取工作已经被BLOCK住了, 下一块数据很可能就是AUDIO, 但是由于文件offset的原因,没法读出来;而另一条路上音频解码比较快, 于是AUDIO BITSTREAM BUFFER POOL就空了,  AUDIO DECODER没有数据可解,被BLOCK, 音频断掉。

(2) 如果VIDEO DECODER和AUDIO DECODER都是高优先级,而RENDER是中优先级,那么DEMUX出来,连接两个DECODER运行良好,解码比较快,但是RENDER没有得到足够的时间片把解好了的PCM数据BUFFER送出,于是音频断。同时由于AUDIO PCM BUFFER POOL满,堆积了很多来不及输出的PCM数据,于是AUDIO DECODER送出BUFFER时,被卡在等待RENDER INPUT POOL非空的事件通知上,于是AUDIO DECODER被BLOCK,然后AUDIO BITSTREAM BUFFER POOL满,接着DEMUX又被卡住了。哈哈,又彻底玩完了

(3) 也有其他搭配方法,反正就是VIDEO DECODER,AUDIO DECODER, PCM RENDER之间的优先级配比关系,我感觉就像高中物理实验在调节那种三根脚的水平仪,怎么调都无法让水平仪的小气泡正好在中间。吐血三升后,最后我还是选了VIDEO DECODER和AUDIO DECODER都是中等优先级,RENDER是高优先级的方法。这种配比也是方案商比较建议的,并且当时我问对方这种调整有没有什么公式可以参考,他说没有公式,只有经验,凭经验去调,我当时狂FAINT。现在如果有人问我,有没有什么公式,我同样会告诉他:经验,凭经验!

2、经过上面调整后,音频还是断,所以必须着手改善PERFORMANCE了。最简单的方法就是CPU提速,不过现在做不到;另一个比较好的方法就是在DECODER前面丢弃部分视频帧。我简单尝试一下在DECODER之前丢了一半数量的帧,效果看起来居然还不错,虽然理论上帧率降到12fps,但肉眼看起来居然没有什么差别,最重要的是,音频不断了,播放很完美。


所以,在解决这个问题上,实际上我走了很多弯路的。从一开始没有意识到这是一个系统级问题,而认为音频出了问题就应该去查音频模块,到调整BUFFER POOL大小和各FILTER的优先级,最后加上丢帧处理,问题才得以解决。最后看来,音频断的问题并不是一定由音频解码自己本身造成的,还得看别人的脸色,DEMUX是否被卡住,DECODER是否得到足够的INPUT DATA;RENDER是否被卡住,DECODE出来的数据是否及时处理完毕腾出BUFFER。即使AUDIO DECODER自己优先级很高,但前后的FILTER被卡住,音频同样也是会断的。而整条音频播放的链,又受到VIDEO DECODER那条链的影响和制约。这使我想到那句老话,“木桶能装多少水,取决于最短的那块木板”,用来形容这事,再贴切不过了。


本文转自Walzer博客园博客,原文链接:http://www.cnblogs.com/walzer/archive/2007/05/01/733903.html,如需转载请自行联系原作者


上一篇:PLSQL_查询已执行SQL的绑定参数(案例)


下一篇:spring boot + vue 前后分离实现登录功能(三)