使用ffmpeg制作c++视频播放器(分享源码)
项目地址: 点击打开链接,欢迎pr。
本项目采用ffmpeg解码视频文件,使用多线程处理解码等操作,是学习多线程的不错的机会,在这个项目开发过程中巩固了不少多线程的知识,视频的处理主要是ffmpeg,音频采用SDL播放,界面使用QT,使用QTmer定时器去刷新一帧帧的视频。音视频同步的采用视频追逐音频的方式实现的同步,缺点是当视频线程处理缓慢的时候会出现视频过慢,但是一会就回追上音频,这种现象出现的非常少。项目的结构如下:
1,项目中的多线程
线程使用的是Qt自带的QThread,主要有两条线程,一个解压音视频文件获取音视频包的线程,一个解码视频包将视频包中的视频帧读出到帧队列的线程。除了这两个线程另外还有一个音频处理 的回调函数,和一个刷新视频的定时器,这几部分构成了整个项目的骨架。本项目使用QWaitCondition,QMutex和QMutexLocker保护线程安全,使用两个线程安全的队列分别存储视频包,视频帧。
2,关于音视频同步
音视频同步是这个项目最复杂的部分了,弄了好久,最后还是参考网上的教程代码实现了同步。由于音频是线性存储在音视频文件中的,所以直接解压后解码,用SDL相关的api就可以播放了。而视频不一样,视频帧有好几种,I帧,B帧和P帧。每一帧有一个播放时间pts和解码时间dts,视频帧有很多重复帧,需要跳过他们,然后可以根据前后两帧(应该播放的帧)的pts和音频的pts比较进行音视同步。因为音频时间是没问题的,只要让视频跟上音频就行。计算下一帧的视频pts方法也很简单,把大约十几二十帧存到帧队列,获取前后两帧的pts就可以了,如果视频pts稍微比音频快,就延长视频刷新的时间,比音频慢就减少延时时间。这个音视同步的方法效果很不错了,之前尝试了使用系统时钟来实现同步,总体效果还行,但是如果要控制视频进度就麻烦了,进度可以调整,但是系统时间是不可以调整啊,硬要使用这个方法也不是不可以,只是比直接视频追音频麻烦太多。至于还有一个同步方法,音视追逐视频,,,音频本来好好的,硬要改变反而不好。
3,视频filter
处理视频的一些特效我直接用一个过滤器来处理了,每一个特效当做一个任务,放在任务集合里面,每播放一帧视频之前,视频帧经过集合中的各个任务处理后,被QT信号发送出去,ui线程接收这一帧图像,显示出来,这个视频功能比较少,以后会增加,有了这个过滤器,增加新功能就简单多了。只要使用一下步骤:1,创建任务,2,添加实现算法的方法,3,将任务和算法放在过滤器对应的地方,4,修改界面让用户添加任务到任务队列。后面代码过滤器的位置就不要改变就行。
项目地址: 点击打开链接,欢迎pr,因为这个播放器功能还是很少的,以后还会继续增加他的功能。