ffmpeg中音视频同步浅析

音视频同步原理[ffmpeg]

ffmpeg对视频文件进行解码的大致流程:

1. 注册所有容器格式和CODEC: av_register_all()

2. 打开文件: av_open_input_file()

3. 从文件中提取流信息: av_find_stream_info()

4. 穷举所有的流,查找其中种类为CODEC_TYPE_VIDEO

5. 查找对应的解码器: avcodec_find_decoder()

6. 打开编解码器: avcodec_open()

7. 为解码帧分配内存: avcodec_alloc_frame()

8. 不停地从码流中提取中帧数据: av_read_frame()

9. 判断帧的类型,对于视频帧调用: avcodec_decode_video()

10. 解码完后,释放解码器: avcodec_close()

11. 关闭输入文件:av_close_input_file()

output_example.c 中AV同步的代码如下(我的代码有些修改),这个实现相当简单,不过挺说明问题。

音视频同步-时间戳

媒体内容在播放时,最令人头痛的就是音视频不同步。从技术上来说,解决音视频同步问题的最佳方案就是时间戳:首先选择一个参考时钟(要求参考时钟上的时间是线性递增的);生成数据流时依据参考时钟上的时间给每个数据块都打上时间戳(一般包括开始时间和结束时间);在播放时,读取数据块上的时间戳,同时参考当前参考时钟上的时间来安排播放(如果数据块的开始时间大于当前参考时钟上的时间,则不急于播放该数据块,直到参考时钟达到数据块的开始时间;如果数据块的开始时间小于当前参考时钟上的时间,则“尽快”播放这块数据或者索性将这块数据“丢弃”,以使播放进度追上参考时钟)。

可见,避免音视频不同步现象有两个关键——一是在生成数据流时要打上正确的时间戳。如果数据块上打的时间戳本身就有问题,那么播放时再怎么调整也于事无补。假如,视频流内容是从0s开始的,假设10s时有人开始说话,要求配上音频流,那么音频流的起始时间应该是10s,如果时间戳从0s或其它时间开始打,则这个混合的音视频流在时间同步上本身就出了问题。打时间戳时,视频流和音频流都是参考参考时钟的时间,而数据流之间不会发生参考关系;也就是说,视频流和音频流是通过一个中立的第三方(也就是参考时钟)来实现同步的。第二个关键的地方,就是在播放时基于时间戳对数据流的控制,也就是对数据块早到或晚到采取不同的处理方法。图2.8中,参考时钟时间在0-10s内播放视频流内容过程中,即使收到了音频流数据块也不能立即播放它,而必须等到参考时钟的时间达到10s之后才可以,否则就会引起音视频不同步问题。

基于时间戳的播放过程中,仅仅对早到的或晚到的数据块进行等待或快速处理,有时候是不够的。如果想要更加主动并且有效地调节播放性能,需要引入一个反馈机制,也就是要将当前数据流速度太快或太慢的状态反馈给“源”,让源去放慢或加快数据流的速度。熟悉DirectShow的读者一定知道,DirectShow中的质量控制(Quality Control)就是这么一个反馈机制。DirectShow对于音视频同步的解决方案是相当出色的。但WMF SDK在播放时只负责将ASF数据流读出并解码,而并不负责音视频内容的最终呈现,所以它也缺少这样的一个反馈机制。

音视频同步通讯SDK源码包分享:

Android:http://down.51cto.com/data/711001

Windows:http://down.51cto.com/data/715497

Linux:http://download.csdn.net/detail/weixiaowenrou/5169796

IOS:http://down.51cto.com/data/715486

WEB:http://down.51cto.com/data/710983!

http://6352513.blog.51cto.com/6342513/1180742

猜你喜欢

转载自blog.csdn.net/u012635648/article/details/78695329