转:Android上ffmpeg移植(3)

来源:互联网 发布:js json树状结构遍历 编辑:程序博客网 时间:2024/05/19 08:22

作者:jl

这两天想把ffmpeg移植到android上,前面说了 纯音频这个问题很好解决,但是如果是音视频那么就有一个同步的问题。

这里简单的介绍几个同步的方案:

曾经在DShow下面写过DShow的播放环境,首先无论是waveout还是DSound,它里面有几个buffer的缓冲的序列,这一组 buffer里面每一个播放完成之后都会有一个消息让利知道我们这个buffer播放完成,让你去填充新的buffer,一般一个buffer了不起就是 10ms的音频数据,以44100为例,buffer大小就差不多  10*44100*2*2/1000,双声道立体声差不多1600个字节,这个还好,然后几个buffer这样的轮流下去,这样我们在做同步的时候每次播放10之后会有一个相应,这个相应会让播放视频的线程从wait状态唤醒,然后检查pts,判断是否时间到了,然后是否播放。这样就只用了两个线程,一个音频一个视频,选择音频为时钟,这样的方式是我认为最好的,最小的cpu的消耗。

看了一下ffplay的代码,这个就没有微软的思路好,主要是因为我们的buffer并不只有10ms这么小,我们一个包可能有70或80ms的数据,这样我们的视频就会明显的落后,因为以25fps的视频为例,每一帧就只有1000/25 = 40ms,如果一个音频需要80ms,中间明显就会漏掉一帧,这是不允许的,所以,我们的ffplay引入了一个时钟的概念,有三个时钟可以选择,一个音频 一个视频一个就是外部时钟,外部时钟可能需要单独的环境,但是音频和视频都有问题,首先如果是音频为参考时钟,这样有时候文件不标准的时候,就是说视频的pts本身就是不标准的,这样很容易音频是正常,然后视频不正常。  如果以视频为参考时钟,我看那个ffplay的处理是把多出来的音频数据省略掉,当音频不够,而时钟不到就会填充空白数据,这样做对音质有很大的损伤(当 pts不标准的时候),这样一来,我就开始郁闷了,首先我是打算由视频作为参考时钟,读取一个标准的两帧数据之间的差,然后显示,这样做不稳定。

后来想一想,能不能虚构一个DShow下面的环境,把一块较大的音频数据分几次来填充,每次都会产生一个消息,让视频去判断,想不到问题换个思路简单很多,这样试了一下,效果还可以。

其中有个定时器的问题,我是这样解决的:
http://topic.csdn.net/u/20090622 ... 9-01ab3d82f961.html