1、前言
其实网上到处都能找到相关文章,之所以写这篇文章是因为我在移植过程中遇到过各种各样的坑,然后网上找解决方案解决方案还不一样,最终终于找到了适合自己的一套方案,先记录下来。总结一下其实在QT上移植一个FFmpeg 的库非常简单,很多时候是被误导了,又是windows又是linux,又是32位的QT或者64位QT,或者32位系统64位系统等等乱七八糟的。
我是个记性极差的人,我记不住太多东西也不想去记,写这篇文章的目的就是为了记录我找到了一种可行的办法。
2、库文件下载
下载地址:https://ffmpeg.org/download.html

在弹出的界面中,鼠标下滑,找到release builds,然后找到previous release,这几个都是可以用的,essentials表示的是必要的,顾名思义这是个阉割版,full则是完全版,不带shared的只有可执行文件,如果只想学习FFmpeg的命令行下这个就行了,然后把里面的exe文件路径添加到环境变量里就可以直接用,如果要编程去调里面的函数,就要下带shared的版本。

文件解压后bin、include、lib这几个文件夹里的东西是要移植到QT里的,具体怎么移在后面说。

bin文件夹里面有3个exe文件,和一些dll文件,如下图:

这几个exe文件是可以用命令行运行的,可以先测一下下下来的这个东西能不能在自己电脑上运行,操作方法为:
按住shift键后在空白处右键->在此处打开powershell窗口,然后输入./ffmpeg -version,正常来说会打印出一些版本信息,如下图:

如果没有,则说明下下来的这个库文件不能在你电脑上运行,这个时候想一下是不是下错了。
include文件夹里面还有8个文件夹,这些文件夹里面才是一个个的头文件。

3、创建QT工程
选择编译器要选MSVC的64位的这个

然后main.cpp里面先随便写个hello world:
1 #include "mainwindow.h" 2 #include <QApplication> 3 #include <iostream> 4 5 using namespace std; 6 7 int main(int argc, char *argv[]) 8 { 9 QApplication a(argc, argv); 10 MainWindow w; 11 w.show(); 12 13 cout << "hello" << endl; 14 15 return a.exec(); 16 }
运行一下,能正常输出,证明目前这个工程是没问题的:

4、移植文件
FFmpeg属于三方库,一般会在工程中创建一个thridpart文件夹专门用来存放三方库,然后在thirdpart里面新建一个ffmpeg文件夹,再把下载下来的ffmpeg库里的include和lib两个文件夹全部拷贝到ffmpeg文件夹下,如下图:

现在东西已经放到工程目录了,但是还得告诉QT要把这些东西真正的放到工程里去。注意
注意后面的步骤对新手来说很容易出幺蛾子。
先说错误做法,在工程中右键->添加现有文件,然后把include目录下的子目录下的所有头文件添加进去,或者直接打开.pro文件,找到HEADERS,把需要添加的头文件全部加在后面,这两种做法本质上是一样的,目的是为了让编译器能找到对应的头文件,虽然这样编译器能找到对应的头文件,但是这样做是错的。为什么呢,我们随便打开里面的一个头文件,比如include\libavcodec\avcodec.h,它前面有一段包含别的头文件的代码,如下:
#include "libavutil/samplefmt.h" #include "libavutil/attributes.h" #include "libavutil/avutil.h" #include "libavutil/buffer.h" #include "libavutil/channel_layout.h" #include "libavutil/dict.h" #include "libavutil/frame.h" #include "libavutil/log.h" #include "libavutil/pixfmt.h" #include "libavutil/rational.h"
这里面去包含一个头文件的方式是把头文件所在路径包含进去了,也就是说我们不需要去指定具体应该包含哪个头文件,只需要告诉编译器去“include”这个目录下去找就行了(当然我们使用的时候也要这么用)。具体方法是在.prj文件里面加一个INCLUDEPATH,如下:

接下来要把lib文件夹里的库添加进去,这里网上能找到不同的说法,比如加不加-L,加不加小写的l,加不加.lib等,可能不同的版本是会不一样,但是有个最简单的办法是直接在工程上右键->添加库,如下:




点击完成之后,在.pro文件会增加几行,重点就是看加的那几行的格式,比如:

这个时候我们就知道添加库的写法是这么写的,于是刚刚新增的这么多行都可以删了,按照他自己添加的方法这样写就行了。修改后如下:
LIBS += \ -L$$PWD/thirdpart/ffmpeg/lib/ -lavcodec \ -lavdevice \ -lavfilter \ -lavformat \ -lavutil \ -lpostproc \ -lswresample \ -lswscale
这个时候就可以改下main函数,测试一下移植成功了没,改过的main函数如下:
1 #include "mainwindow.h" 2 #include <QApplication> 3 #include <iostream> 4 5 extern "C" { 6 #include "libavcodec/avcodec.h" 7 } 8 9 using namespace std; 10 11 int main(int argc, char *argv[]) 12 { 13 QApplication a(argc, argv); 14 MainWindow w; 15 w.show(); 16 17 cout << "version is " << endl; 18 cout << avcodec_version() << endl; 19 20 return a.exec(); 21 }
注意包含的ffmpeg的头文件要加exttern “C”,否则编译会报如下错误:
main.obj:-1: error: LNK2019: 无法解析的外部符号 "unsigned int __cdecl avcodec_version(void)" (?avcodec_version@@YAIXZ),该符号在函数 main 中被引用
编译过去之后可以试着运行一下,但是肯定会报错“程序异常结束”,这是因为缺少程序运行时需要的库,这时找到运行的exe文件所在的目录,把ffmpeg里面的bin文件夹里的所有dll文件拷贝到和自己生成的exe文件相同的目录下,再运行就可以了:

运行结果如下:

浙公网安备 33010602011771号