您的位置:首页 > 编程语言 > Qt开发

从零开始学习音视频编程技术(九) FFMPEG Qt视频播放器之同步进阶篇

2016-09-22 10:19 639 查看
原文地址:http://blog.yundiantech.com/?log=blog&id=12

前面我们已经为播放器加上了简单音视频同步功能。

播放mp4文件的时候似乎没啥问题,但是当播放rmvb文件的时候,问题就暴露出来了。

以电影天堂下载的电影文件为例:

下载地址:

CD1

ftp://dygod2:dygod2@d204.dygod.cn:2088/黑客帝国3.[中英双字.1024高分辨率]/[电影天堂www.dygod.cn]黑客帝国3CD1.rmvb
CD2

ftp://dygod2:dygod2@d204.dygod.cn:2088/黑客帝国3.[中英双字.1024高分辨率]/[电影天堂www.dygod.cn]黑客帝国3CD2.rmvb
CD3

ftp://dygod2:dygod2@d204.dygod.cn:2088/黑客帝国3.[中英双字.1024高分辨率]/[电影天堂www.dygod.cn]黑客帝国3CD3.rmvb
播放第一个文件(既cd1)的时候,问题似乎不大。但播放第二个和第三个文件的时候发现音频和视频会存在固定的偏差(我测试的时候大概是2S)。

使用普通播放器打开这个文件,也会发现开始播放的前几秒,只出声音,却不出图像。

于是分析了一下CD2和CD3的文件,发现其视频pts不是从0开始的,也就是说前面一段数据里面只有音频数据,而没有视频数据。而我们实现同步的方法是通过读取的时候判断pts来决定显示不显示,因此碰到这种情况问题就出现了。

前面使用SDL的时候,我们发现,音频不管读的多块,SDL播放的时候都是按照正常的速度放出来的,因此可以在SDL的回调函数中解码出每一帧音频数据的时候,记录下音频的pts,然后根据此Pts来决定是否显示视频。

前面已经说到视频的pts不是从0开始的,且音频和视频的pts似乎不是连续的。

因此我们也要给视频开一个缓存,先读取出一定数量的视频帧,存入队列。

然后再开一个线程专门用来从视频队列中取出视频并解码,解码之后便将得到的pts与音频线程中记录的音频pts做对比,这样就可以达到同步的目的了。

那么现在 我们就有了3个线程:

1.读取视频的线程

2.解码视频的线程

3.解码播放音频的线程(这个是由SDL创建的)

1.读取视频线程如下:

读取线程和前面的差别不大,都是打开视频,然后在while循环里面读取视频,分别放入音视频的队列:
这里我们是瞬间就把整个视频读入内存了,这样我们播放小视频的话 问题不大,但是当播放大视频的时候,就把内存吃光了,因此必须要管管他。

目前想到比较好的方法就是 读取的时候限制队列的长度,当里面的数据超过某个范围的时候 就先等等。

于是改成如下:
2.视频线程如下:

首先需要先创建一个线程,这里我们不再用Qt的线程 而是直接使用SDL的API来创建线程,这么做当然是为了以后移植着想。
视频线程操作如下:

3.音频线程

至于音频线程就不说了,我也是直接拷贝了被人的代码。其实主要就是在前面的基础上加了获取音频pts的功能,至于怎么获取没有仔细研究他。

主要参考了这篇博客:http://blog.csdn.net/tanlon_0308/article/details/40428139

到这里,我们的播放器已经实现了真正意义上的同步,这次是真的可以播放所有的视频了。

当然啦,这还不能叫播放器,连基本的播放暂停都没有,后面我们就给他加上播放、暂停、跳转等常用的功能。

完整工程下载地址:

http://download.csdn.net/detail/qq214517703/9630369

音视频技术交流讨论欢迎加 QQ群 121376426

原文地址:http://blog.yundiantech.com/?log=blog&id=12



内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐