查看完整版本: [-- 用Qt和FFmpeg写了个播放器 QtAV库 --]

QTCN开发网 -> Qt 作品展 -> 用Qt和FFmpeg写了个播放器 QtAV库 [打印本页] 登录 -> 注册 -> 回复主题 -> 发表主题

<<   1   2  >>  Pages: ( 2 total )

novesky 2012-11-03 13:45

用Qt和FFmpeg写了个播放器 QtAV库

阅读README很重要
欢迎大家来参与主页 http://wang-bin.github.io/QtAV

2015.12.21 QtAV 1.9.0

QtAV 1.9.0 发布了,该版本改进内容包括:
- 支持Windows Store。应用商店搜索qtav
- 给FFmpeg提交了winrt多线程支持的补丁,性能大有提升,已合并至上游
- 修复iOS部署和运行错误一些问题
- XAudio2 崩溃问题
- Android: 支持content协议,修复从相册打开无法播放问题;windows上编译、部署问题修复

- VA-API: 改善n卡支持;加入hevc, vp9,未测;EGL零拷贝渲染支持,性能最好,需要va-api 0.38(ubuntu15.10)和Qt>=5.5及intel显卡。其他一些改进
- 使用OpenGL, GLSL新接口,OpenGL ES3优化
- 支持播放前一帧
- QMLPlayer: 可以按住预览框拖动,处理安卓的home键、返回键...

- 其他更新请看
下载

2014.12.27 QtAV 1.4.2
- 提高seek速度。要感谢wm4(mpv主力开发者)的指点
- 优化音视频同步逻辑,软解播放高分辨率高帧率视频完胜其他播放器。其他播放器几乎不能看,包括硬解,除了mpv+vaapi。以后将有更好的优化。windows下效果略差。4k 120fps测试视频: http://pan.baidu.com/s/1sj6s40l
- 修复VA-API解码图像下方多出一条模糊的线问题。修复使用libav9时vaapi可能不工作的问题。
- ffmpeg运行时支持hevc dxva硬解的话就启用硬解。目前要使用LAVFilters的ffmpeg。
- Cedarv硬解优化
- 增加可扩展的视频输入源接口。支持qrc资源文件里的音视频播放(QtMultimedia还不支持)
- 异步加载
- 修复使用openal时多个播放器实例播放音频不正常问题
- 修复播放下一帧问题
- 修复截图不是当前帧问题。简化截图接口
- 修复qml视频画面抖动问题
- 正确处理文件名中的特殊字符。
- libass改为动态加载。依赖 https://github.com/wang-bin/capi
- 支持链接到ffmpeg静态库
- rgb48支持。opengl只支持rgb48le

2014.09.10 QtAV 1.4.0
下载:https://sourceforge.net/projects/qtav/files/release/1.4.0
- OpenGL优化,支持更多的格式,支持QML,对于Qt>=5.4支持opengl动态切换
- VAAPI: GLX直接渲染支持,性能大幅提升。检测显卡是否4k以防止系统崩溃.
- DXVA: 更多解码表面以提升性能防止画面抖动
- OSX的VDA硬解支持
- Android支持,部署更简单
- 字幕支持,包括qml
- OpenAL 改进,支持大多数平台
- FFmpeg的libavfilter支持
- 音频播放接口改变
- 简化OSX的部署和安装包制作
- bug修复

2014.05.30 QtAV1.3.4
- CUDA:修复播放时花屏、画面顺序跳动等问题
- VAAPI,DXVA:之前VAAPI的性能很差。现在intel gpu使用sse4.1来拷贝解码数据,性能提升明显。 VAAPI支持drm
- 使用ffmpeg新的硬解接口
- 修复切换解码器后画面显示不对甚至崩溃问题
- 加入avcodec、avformat和各解码器的一些高级选项。
- metadata 支持
- 优先使用流信息里的显示比例。感谢 Sandro Cavazzoni
- 修复文件名编码问题。之前貌似日语文件名打不开
- 修复带图片的音频不显示图片和不能拖动进度的问题
- 支持将QtAV安装为Qt的模块方便开发应用
详情见 http://wang-bin.github.io/qtav.org/blog/1.3.4.html


2014.01.29 QtAV 1.3.1

库相关:
- OpenAL初步支持
- 修复硬件解码时seek、网络丢包等情况下崩溃问题
- CedarX硬解支持。可以在pcDuino上硬解。感谢 Miroslav Bendik. 可以看他的视频 http://www.youtube.com/watch?v=u3mvDe3GBPI
- FFmpeg log和错误处理
- AVDictionary 支持
- Hi10bits 使用软解
- 还有其他诸多改进
播放器相关:
ctrl+滚动滚轮进行缩放,禁止屏保等
同时加入了界面更加 cool 的 QMLPlayer例子,在windows、mac、linux上都有不错的体验
[attachment=11670]
2013.12.19 QtAV 1.3.0 发布
- windows下dxva硬解初步支持,目前拖动时间可能会有崩溃问题。vaapi目前性能很差
- 可选择音轨
- 可调节亮度、饱和度等
- 循环播放、播放列表、历史记录
- HEVC支持(FFmpeg)
- 优化网络电视界面、其他界面等
以下功能是库里支持但player未加ui的
- 一个视频播放多个输出窗口支持,支持裁剪,自定义filter
[attachment=11471]



2013.07.04 QtAV1.2.2

改进的是音频播放,之前播放mp3和部分视频爆音的问题已无
任意控制播放速度(见图,或Ctrl+上/下来加减速度)
音量控制控件


1.2.1主要更新:
视频显示质量控制
修复显示比例不正确的问题。可以设为任意比例
修复一些崩溃、内存泄漏等错误


2013.05.27 QtAV1.2.0发布:
更新很多东西,主要有
1. player例子加入gui界面,易于操控。自带一些网络电视
2. 独创的播放时渲染引擎无缝动态切换。可以方便地对比各种渲染引擎的cpu使用率
3. X11下XV的支持(Qt4 only)
4. bug修复等
[attachment=10598]




2013-03015
    新增了几个渲染方式,如opengl, direct2d, gdi。在我电脑上direct2d对性能提升非常明显。增加了OSD(现在的设计很烂),原来的O键改成了切换OSD。Ctrl+O是打开文件。
    切换视频大小比例按R。
    完善了qmake的工程框架,移植了很多Qt5里qmake内置函数到Qt4,用qmake语法写的,支持编译检测。若要重新配置请删除编译目录里的.qmake.cache再qmake,mingw可能qmake一次不够,需要两次(还没找到原因,我的pro写得太复杂了)。linux下支持make deb来生成安装包。
    支持VC(我vs2010编译出来的无法运行,2012正常,不解),方法见github 上的wiki。支持Qt5

    命令行:player [-vo qt|gl|d2d|gdi] [url/path]filename
    或者把player改名成player-gl, player-d2d, player-gdi也可以

2013-01-13更新
    已经比较稳定了。目前有一些国内外的开发者在使用了,用来显示摄像头实时视频蛮多的。
    还有很多东西要开发,比如组件化、硬件加速等


源码:https://github.com/wang-bin/QtAV
由于github即将关闭文件上传的功能,所以在sourceforge上也建了一个,可以下载mingw下编译所需的库

win下编译要用到的库如ffmpeg,portaudio可以在https://sourceforge.net/projects/qtav/files/depends 下载
希望对大家有所帮助。

了解了下视频解码和音视频同步的原理,于是一口气写了个播放器,感觉并不难。音频播放使用portaudio,在linux上貌似有问题。功能还比较简单,能正常播放视频。对比了mplayer、迅雷看看播放4G大小的视频的资源使用,它们都要200多M的内存,我的只要50多点,挺意外的。




支持快进快退、暂停继续、音量调节、单帧控制、截图等

TODO:字幕,长宽比例 etc



















uidab 2012-11-05 11:24
顶一下!

哟天气不错 2012-11-09 19:29
咱也来顶一下

yangkun52131 2013-01-08 08:45
好东西,代码很清晰

toby520 2013-01-08 11:58
没找到楼主所说的 mingw下编译要用到的库如ffmpeg,portaudio可以在那个页面的downloads里找

lnjamn 2013-01-10 15:01
能在N9上使用RMVB吗?

novesky 2013-01-14 01:37
mingw-libs_extra那个压缩包, sourceforge里。或者自己编译也行。觉得好的话去顶一下哦

novesky 2013-01-14 01:42
只要ffmpeg支持就可以。话说n9我还没试过

yangkun52131 2013-02-28 11:26
不错的东西,在播放的时候有时候会出现白色块,还有时候出现花块。

tearring 2013-03-05 01:03
已在vxworks上跑通 ^-^

ppdayz 2013-03-05 14:35
楼主威武

blueseait 2013-03-09 14:51
请问如何在这个项目中加入ffmpeg和portaudio支持?

blueseait 2013-03-15 22:40
我用QtCreator进行编译和运行时,下载了网上mingw-libs_extra文件夹下面的文件,放到src目录下,并在libQtAV.pro文件中配置了ffmpeg的LIBS和INCLUDEPATH,并且注释掉了QtAV.pro中的qtCompileTest(avutil)|error("FFmpeg avutil is required, but compiler can not find it")等,可以通过编译并生成相应运行文件,但是运行的时候会报错。在QtCreator输出:
D:\TDDOWNLOAD\QtAV-master\build\bin\player-gdi.exe 启动中...
程序异常结束。
D:\TDDOWNLOAD\QtAV-master\build\bin\player-gdi.exe 退出,退出代码: -1073741515

直接运行生成的执行文件player-gdi.exe时报因计算机中丢失Qt5Core.dl,尝试重新安装该程序以解决此问题。

novesky 2013-03-15 22:53
windows下的话这里下载 https://sourceforge.net/projects/qtav/files/depends/
然后让编译器能找到头文件和库文件就行。

novesky 2013-03-15 22:59
请下载这里的https://sourceforge.net/projects/qtav/files/depends/
配置头文件和库的路径不需要修改pro,而是应该放在编译器能找到的目录,或者设置环境变量,如gcc的用CPATH增加头文件搜索路径,LIBRARY_PATH增加库搜索路径。vc用INCLUDE和LIB。
如果你注释掉了ffmpeg之外的qtCompileTest,那么那些功能不会被编译。
程序异常我也不清楚,你再试试吧。

novesky 2013-03-15 22:59
在这里:https://sourceforge.net/projects/qtav/files/depends/

novesky 2013-03-15 23:01
不错不错!!

blueseait 2013-03-16 12:01
楼主,谢谢你的指导,我的程序能正常通过编译了,但是在WIN7下用QtCreator建的工程还是不能运行,错误与上面写的一样,不知道是什么原因,请问楼主是否测试过win7+QtCreator环境的运行。另外,请问楼主最新源代码加入的OPENGL是什么版本,我下载了一个openGL加入后有些openGL函数找不到。再次谢谢楼主的无私奉献!

novesky 2013-03-16 13:43
我的mingw是官网上的版本http://www.mingw.org,Qt4、5都是自己编译的。我用QtCreator、命令行都编译过没问题。OpenGL的什么函数找不到?为什么要自己下载OpenGL,mingw应该自带的吧?你的Qt是哪个版本?我来试试

blueseait 2013-03-16 19:07
我下载了你说的官网上的版本mingw,还是有很多函数找不到,比如:
D:\qtav\QtAV-master\src\GLWidgetRenderer.cpp:100: 错误:'GL_SMOOTH' was not declared in this scope
D:\qtav\QtAV-master\src\GLWidgetRenderer.cpp:100: 错误:'glShadeModel' was not declared in this scope
D:\qtav\QtAV-master\src\GLWidgetRenderer.cpp:127: 错误:'glPushMatrix' was not declared in this scope
我用的qtcreator5.01版本,你试试吧

blueseait 2013-03-16 20:53
不对,我用的是qtcreator2.6.2,qt库版本是5.0.1,直接安装网上下载的windows+mingw下编译过的qt5.0.1可安装版本,直接安装的。不加任何外部opengl也是以上错误找不到glShadeModel、glPushMatrix等函数。楼主看看吧

novesky 2013-03-16 21:18
这几个函数是都没有就奇怪了,感觉没有找到opengl的头文件。第一个错误是什么?
另外,Qt提供编译好的版本不能用mingw官网上的编译器,格式不兼容的,还是用Qt指定的mingw吧。
另外,这些都和QtCreator无关

blueseait 2013-03-16 21:42
我直接用的Qt安装后自动分配的编译器,然后直接运行报:D:\qtav\QtAV-master\src\GLWidgetRenderer.cpp:27: 错误:GL/glext.h: No such file or directory
说找不到这个头文件。所以我才从外部加opengl,但是又与本身自带的有冲突。

novesky 2013-03-17 00:47
你把glext.h那行去掉,换回编译器自带的gl文件。有些gl带这个glext.h文件,有些没有,看来我要加个判断的宏

novesky 2013-03-17 23:12
我修改了代码,会检测是否需要包含glext.h,你试试看

blueseait 2013-03-18 10:12
我在另外一台机器上(操作系统为win7)安装了qt5.0.1,并在qtcreator2.6.2中(安装qt5.0.1时自动安装的)进行编译,结果报找不到
D:\qtav\QtAV-master\src\GLWidgetRenderer.cpp:100: 错误:'GL_SMOOTH' was not declared in this scope
D:\qtav\QtAV-master\src\GLWidgetRenderer.cpp:100: 错误:'glShadeModel' was not declared in this scope
D:\qtav\QtAV-master\src\GLWidgetRenderer.cpp:127: 错误:'glPushMatrix' was not declared in this scope
这些变量和函数。

novesky 2013-03-18 11:02
我怀疑你没有opengl相关文件,不然不可能有这些错误的。include gl.h试试看?

novesky 2013-03-18 11:06
也有可能是OpenGL ES里没有这些。注释掉试试

novesky 2013-03-24 16:54
我看了下,是因为官方编译的 Qt5使用OpenGL  ES2 的缘故,区别还蛮大的。我在qmake工程里加了个检测,重新qmake一下最新代码再编译就行,如果不支持的就会disable掉opengl渲染

pbe_sedm 2013-03-24 23:55
楼主,我有个提议,能不能写些博客啥的,说说你开发这款开源项目的一些经历,纯技术的,文字功底如何不打紧,也许这能吸引更多的中国程序员参与这个项目的开发,独乐乐不如众乐乐,你说是吧!非常诚恳的希望楼主考虑一下这个建议!

novesky 2013-03-25 09:51
恩,谢谢你的建议,我四月份开始写写看。

gavial2011 2013-04-09 10:20
谢谢楼主~

novesky 2013-05-27 12:24
1.2.0 发布

ninsun 2013-10-23 17:25
楼主大大,你能不能写个关于如何使用ffmpeg的简单介绍来着?
像是想要实现播放一个视频,首先要调用ffmpeg的哪个库的那个函数,接着再调用哪个库的那个函数,然后如何如何的这种简单的介绍?
不要详细的说明,只要把关键的函数与步骤说一下就好了。
现成的项目里面功能繁多,想要看出来最基本的用法很麻烦的,特别对于毫无概念的新手来说……

wei_cn129 2013-11-09 22:56
求问楼主,我使用WinXP 32bit,VS2008,QT4.6.2能编译QtAV吗?因为我在您的下载目录中没有找到相关信息,跪谢!

novesky 2013-11-21 16:55
Qt4.7以上可以编译,再低点我没试过。有空了试试看

zhsj 2013-12-04 14:23
一直在找d2d相关的东西,谢谢lz!

贵宾杨佳 2013-12-08 17:44
win7 下直接用Qt creator 编译github上的源代码 出现   :-1: 错误:avutil is required, but compiler can not find it  !!不知道大家有没有碰到?

carmen816 2013-12-13 17:06
对比了mplayer、迅雷看看播放4G大小的视频的资源使用,它们都要200多M的内存,我的只要50多点,挺意外的。
那是因为您的播放器,缓冲的是压缩帧,他们缓冲原始的音视频数据。


楼主的播放器,帧率和时间同步稍有些问题。
FPS 23.976,显示只有15帧左右。播放时间一长,音视频出现不同步。
视频同步音频的方案不够精确,音频本身可能存在累计误差

[attachment=11433]


novesky 2013-12-15 19:18
那是因为您的播放器,缓冲的是压缩帧,他们缓冲原始的音视频数据

这个还真不知道,为什么要这么做?

不同步音频的话应该同步什么?系统时间?我现在的是有问题,来不及画的就丢掉

carmen816 2013-12-17 14:52
引用第39楼novesky于2013-12-15 19:18发表的 回 38楼(carmen816) 的帖子 :
这个还真不知道,为什么要这么做?
不同步音频的话应该同步什么?系统时间?我现在的是有问题,来不及画的就丢掉


VideoThread.cpp
        qreal pts = pkt.pts;
        d.delay = pts - d.clock->value();
        /*
         *after seeking forward, a packet may be the old, v packet may be
         *the new packet, then the d.delay is very large, omit it.
         *TODO: 1. how to choose the value
         * 2. use last delay when seeking
        */
        bool skip_render = false;
        if (qAbs(d.delay) < 2.718) {
            if (d.delay < -kSyncThreshold) { //Speed up. drop frame?
                //continue;
            }
            while (d.delay > kSyncThreshold) { //Slow down
                //d.delay_cond.wait(&d.mutex, d.delay*1000); //replay may fail. why?
                //qDebug("~~~~~wating for %f msecs", d.delay*1000);
                usleep(kSyncThreshold * 1000000UL);
                if (d.stop)
                    d.delay = 0;
                else
                    d.delay -= kSyncThreshold;
            }
            if (d.delay > 0)
                usleep(d.delay * 1000000UL);
        } else { //when to drop off?
            qDebug("delay %f/%f", d.delay, d.clock->value());
            if (d.delay > 0) {
                msleep(64);
            } else {
                // FIXME: if continue without decoding, hw decoding may crash, why?
                //audio packet not cleaned up?
                //continue;
                skip_render = true;
            }
        }
        d.clock->updateVideoPts(pts); //here?
        if (d.stop) {
            qDebug("video thread stop before decode()");
            break;
        }

        if (!dec->decode(pkt.data)) {
            pkt = Packet();
            continue;
        } else {
            int undecoded = dec->undecodedSize();
            if (undecoded > 0) {
                pkt.data.remove(0, pkt.data.size() - undecoded);
            } else {
                pkt = Packet();
            }
        }


        if (skip_render)
            continue;


msleep(64); 25帧为例,1000 / 25 = 40,这边的64值得商榷。
您将解码和帧的刷新放在一个线程中,会影响同步。
解码过程消耗时间比较长,而且解码耗时不是个固定值。会影响“与kSyncThreshold比较”。
所以那些播放器会缓冲解码后的原始音视频数据
ffplay中,使用video_thread解码后queue_picture,放入队列。在video_refresh(另一个线程)中刷视频。


PS:FIXME: if continue without decoding, hw decoding may crash, why?
        软件解码不crash,播放也会出现花屏(或者是黑屏几帧,直到下个I帧出现,看解码器的优化程度)。
        因为视频的解码时,通常解码器会参考上一个包的结果。“hw decoder”或者“hw decoder与ffmpeg之间的连接”写的不健壮那就只能crash了。。。



AudioThread.cpp
        if (!dec->decode(pkt.data)) {
            qWarning("Decode audio failed");
            qreal dt = pkt.pts - d.last_pts;
            if (dt > 0.618 || dt < 0) {
                dt = 0;
            }
            //qDebug("sleep %f", dt);
            //TODO: avoid acummulative error. External clock?
            msleep((unsigned long)(dt*1000.0));
            pkt = Packet();
            d.last_pts = d.clock->value(); //not pkt.pts! the delay is updated!
            continue;
        }
        QByteArray decoded(dec->data());
        int decodedSize = decoded.size();
        int decodedPos = 0;
        qreal delay =0;
        //AudioFormat.durationForBytes() calculates int type internally. not accurate
        AudioFormat &af = dec->resampler()->inAudioFormat();
        qreal byte_rate = af.bytesPerSecond();
        while (decodedSize > 0) {
            if (d.stop) {
                qDebug("audio thread stop after decode()");
                break;
            }
            int chunk = qMin(decodedSize, int(max_len*byte_rate));
            //AudioFormat.bytesForDuration
            qreal chunk_delay = (qreal)chunk/(qreal)byte_rate;
            pkt.pts += chunk_delay;
            d.clock->updateDelay(delay += chunk_delay);

AVClock 默认是 ClockType AudioClock
int chunk = qMin(decodedSize, int(max_len*byte_rate)); --->>> 意味着AVClock每0.02秒更新一次。
这导致您设计的AVClock不是线性的,而是离散的(相对视频而言,如果视频帧是30帧,每个视频帧间隔0.033秒,时钟和帧间隔处于同一数量级。。。),造成丢帧。


不同步音频的话应该同步什么?系统时间?
音频时间和系统时间结合。。。
下面文章的方案和ffplay所使用的如出一辙
http://www.rosoo.net/a/201203/15806.html   (三、音视频同步)

PS:十分惊叹楼主在QT,C++,架构设计等方面的造诣,使我受益匪浅。
        再次感谢楼主开源的精神。


novesky 2013-12-17 15:35
很感谢你的回复,很有价值。同步那块里面的数字阿什么的有些是随便写的。同时用绝对时间(比如系统时间)来同步也想过,不过有个问题就是如果音频慢了怎么办?是重采样来降低音频播放速度还是直接丢掉一部分?我还没试过。不知道你怎么看。
硬解的话我也猜到了会和前几帧相关,但是能否丢掉特殊的帧呢?看了下I、P、B都是互相联系的,好像丢什么都不行。这样的话seek时就有问题了,直接从中间某一帧开始解,会崩溃。
另外,渲染视频画面是在gui线程,不在解码线程,这个跟Qt有关。
其他的我回家再看看。

carmen816 2013-12-17 16:47
引用第41楼novesky于2013-12-17 15:35发表的 回 40楼(carmen816) 的帖子 :
很感谢你的回复,很有价值。同步那块里面的数字阿什么的有些是随便写的。同时用绝对时间(比如系统时间)来同步也想过,不过有个问题就是如果音频慢了怎么办?是重采样来降低音频播放速度还是直接丢掉一部分?我还没试过。不知道你怎么看。
硬解的话我也猜到了会和前几帧相关,但是能否丢掉特殊的帧呢?看了下I、P、B都是互相联系的,好像丢什么都不行。这样的话seek时就有问题了,直接从中间某一帧开始解,会崩溃。
另外,渲染视频画面是在gui线程,不在解码线程,这个跟Qt有关。
其他的我回家再看看。

1.硬解的话我也猜到了会和前几帧相关,但是能否丢掉特殊的帧呢?看了下I、P、B都是互相联系的,好像丢什么都不行。这样的话seek时就有问题了,直接从中间某一帧开始解,会崩溃。
       seek后,下一个I 帧之前的数据全部丢弃。音频需要跟着同步。


2.另外,渲染视频画面是在gui线程,不在解码线程,这个跟Qt有关。
       最后渲染是在GUI线程没错,但是您对于帧的处理,超时丢弃,定时等待,格式转换,outputSet->sendVideoFrame,这些是在视频解码同一线程,并不是指最后画的过程。
        视频解码线程通常情况比较忙,应该在一个空闲线程控制上述过程。



novesky 2013-12-17 18:10
恩,谢谢,我回去试下。你是搞多媒体的吗?很专业啊。

novesky 2013-12-18 12:41
AVPacket只能判断是否含有关键帧,我把没关键帧的丢了,还是崩溃。

novesky 2013-12-18 12:51
看了下vlc的相关代码,好复杂,不过发现AVCodecContext.skip_frame = AVDISCARD_NONREF就不会崩溃了。默认的AVDISCARD_DEFAULT
只是跳过无用的包。

novesky 2013-12-18 14:39
有QQ么?

carmen816 2013-12-19 13:44
引用第46楼novesky于2013-12-18 14:39发表的 回 42楼(carmen816) 的帖子 :
有QQ么?


chenjieat 2013-12-26 14:51
太赞了,我的目标啊!

blueseait 2013-12-31 11:42
1.3版本功能上有很大进步,但是如果要支持dxva硬解码需要重新编译ffmpeg并且加入dxva的外部包支持,我在网上找了一下没有找到关于FFMPEG与DXVA结合编译的文章,不知道楼主可否指导一下如何如何编译出支持DXVA的FFMPEG?


查看完整版本: [-- 用Qt和FFmpeg写了个播放器 QtAV库 --] [-- top --]



Powered by phpwind v8.7 Code ©2003-2011 phpwind
Gzip disabled