FFmpeg-Window Qt环境调试环境搭建教程-2

998 阅读8分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

上一篇文章已经介绍了Qt 调试ffmpeg.c 工程。因为第一篇文章介绍的dll是现成的。所以第二篇文章主要讲解如何自己编译出ffmpeg的dll。

FFmpeg 工程用了大量的 linux 系统的函数,所以 在Window10 需要用 MSYS2 来编译。MSYS2 是什么?网上已经有太多纷繁复杂的介绍。这边就不粘贴了。

简单来说,MSYS2 就是一个软件套件,他可以把linux的软件转成 window的软件,编译打包成 exe文件在 window 运行。

例如 linux 里面 pthread_create() 线程函数,在window 环境是没有这个线程函数的,但是如果你在window 装了 MSYS2,就可以用 MSYS2 的gcc 来编译这个线程函数。这样,linux的api函数,就能在window运行了。

FFmpeg + MSYS2 也是类似的原理。 MSYS2 不只可以 编译出 exe,也可以把原来是 linux 的动态库编译成window的动态库。

例如,linux gcc 编译 动态库最后生成的文件是 xx.so ,在 window MSYS2 gcc 环境下,编译成的动态库是 xx.dll ,两者用的是同一套源码,只不过采用了不同的编译方式,把代码编译成不同平台的动态库。编译成DLL 之后,就可以把DLL 拿出来给自己的QT 项目用了。ffmpeg 的api函数 都是DLL 提供的,例如 编解码 api 函数 是 avcodec.dll,拿到DLL 就可以在 window 平台调用 FFmpeg 的api。

PS: 静态库后缀一样,linux 是 xx.a ,MSYS2 也是生成 xx.a。

MSYS2 官网下载地址:www.msys2.org/


MSYS2 安装完成之后,CMD 进入安装目录 C:\msys64 目录,执行 .\msys2_shell.cmd -mingw32,打开32位的环境。不要直接点击 mingw32.exe 进入32位环境。尽量用 .\msys2_shell.cmd -mingw32。因为后面会改动一下 msys2_shell.cmd 文件。

FFmpeg-2-1.png

运行之后就会进入 linux 的仿真环境,lsps,等linux命令都可以使用。

.\msys2_shell.cmd -mingw32 是 64位的环境,用这个入口编译出来的 ffmpeg.exe 跟 DLL 默认是 64位的。本文先编译 32 位的程序,64位比较麻烦。

FFmpeg-2-1-1.png

MSYS2 Linux仿真环境中包管理命令是 pacman,类似 apt-get,yum。下面用 pacman 安装一些用来编译 FFmpeg 的软件。(pacman 下载速度慢需要切换源)

# 刷新软件包数据
pacman -Sy  
# 安装mingw-w64 ,如果报错 signature not trust,请看下面解决。
pacman -S mingw-w64-i686-toolchain 
pacman -S git
pacman -S make
pacman -S automake 
pacman -S autoconf
pacman -S perl
pacman -S mingw-w64-i686-SDL2
pacman -S libtool
pacman -S mingw-w64-i686-cmake 
pacman -S pkg-config 
pacman -S yasm
# 编译x264 需要 nasm
pacman -S nasm

常见错误:

  • mingw-w64-i686-toolchain 如果按照报 "signature not trust "错,是证书过期了,直接禁用检测,请参考此文章解决。 csdn文章

FFmpeg-2-1-2.png

编译环境的其他准备⼯作:

  • 先关闭 mingw32 命令行。
  • C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\amd64 加进去 window10的环境变量PATH里面,因为这个目录下有 cl.exe 跟link.exe。加进去环境变量,让mingw32 环境能找到这两个命令 cl ,link
  • 重命名 C:/msys64/usr/bin/link.exeC:/msys64/usr/bin/link.bak , 避免和MSVC 的link.exe抵触。
  • 修改 C:\msys64\msys2_shell.cmd 中的 rem set MSYS2_PATH_TYPE=inherit,去掉rem,取消这⼀句的注释,使MSYS2的环境变量继承自window系统
  • 修改完后再 运行 .\msys2_shell.cmd -mingw32,重新打开mingw32 命令行
  • 检查编译环境⼯具,在 mingw32的shell窗⼝输⼊: which cl link yasm cpp 查看 4个命令的路径。 看返回结果,没有no的结果⼀般就没问题。

FFmpeg-2-2.png

相关阅读:cl.exe 命令是干什么的?

好像不执行这5个步奏也能编译成功ffmpeg,为什么要重命名 C:/msys64/usr/bin/link.exe?为什么要使MSYS2的环境变量继承⾃window系统?我也不太了解。


准备工作已经完毕了。

FFmpeg 这个工程编解码等功能,是需要依赖一些外部库的,例如 x264库,aac库等等。所以编译FFmpeg之前,需要把 x264 ,acc 等项目编译出静态库,然后再把x264静态库,acc静态库等 Link 进去 FFmpeg 的DLL里面。

x264 项目编译:

下面的命令请把 /home/loken 改成自己的目录。

编译过程中如果报 final link failed: No space left on device 错误,尝试重启window10。

# 回到用户目录
cd /home/loken
# 创建ffmpeg目录,build目录,统一管理
mkdir -p ffmpeg/build32  
# 进入ffmpeg目录
cd ffmpeg 
#下载x264项目代码
git clone https://gitee.com/mirrors_addons/x264
# 进入x264项目目录
cd x264 
# 执行configure
./configure --prefix=/home/loken/ffmpeg/build32/libx264 \
--host=i686-w64-mingw32 --enable-static \
--extra-ldflags=-Wl,--output-def=libx264.def  
make -j8
make install

如果上面的命令没出错,在 ~/ffmpeg/build32/libx264/lib 目录下会编译出 x264 的静态库 libx264.a

fdk-aac项目编译:

# 回到ffmpeg目录
cd /home/loken/ffmpeg 
git clone --depth 1 https://gitee.com/mirrors/fdk-aac.git
cd fdk-aac
./autogen.sh
./configure --prefix=/home/loken/ffmpeg/build32/libfdk-aac --disable-shared \
--enable-static
make -j8
make install

如果上面的命令没出错,在 ~/ffmpeg/build32/libfdk-aac/lib 目录下会编译出 aac 的静态库 libfdk-aac.a

mp3项目编译:

下面的命令如果报错,请把 "~" 相对目录 改成绝对目录

cd /home/loken/ffmpeg 
git clone --depth 1 https://gitee.com/hqiu/lame.git
cd lame
./configure --prefix=/home/loken/ffmpeg/build32/libmp3lame --disable-frontend \
--disable-shared --enable-static
make -j8
make install

如果上面的命令没出错,在 ~/ffmpeg/build32/libmp3lame/lib 目录下会编译出 mp3 的静态库 libmp3lame.a

libvpx项目编译:

cd /home/loken/ffmpeg 
git clone --depth 1 https://github.com/webmproject/libvpx.git
cd libvpx
./configure --prefix=/home/loken/ffmpeg/build32/libvpx --disable-examples \
--disable-unit-tests --enable-vp9-highbitdepth --as=yasm
make -j8
make install

如果上面的命令没出错,在 ~/ffmpeg/build32/libvpx/lib 目录下会编译出 vpx的静态库 libvpx.a


FFmpeg 工程依赖的外部静态库都已经编译出来,下面可以开始编译 FFmpeg 工程了。

FFmpeg项目编译:

下载 ffmpeg 4.2 源码,链接:pan.baidu.com/s/1VpUvpLhe… 提取码:g3k8

把文件 FFmpeg-4.2.zip 解压到 /home/loken/ffmpeg/ffmpeg

cd /home/loken/ffmpeg/ffmpeg-4.2
./configure \
--prefix=/home/loken/ffmpeg/build32/ffmepg-4.2 \
--enable-gpl \
--enable-sdl2 \
--enable-zlib \
--enable-shared \
--enable-nonfree \
--enable-libx264 \
--enable-libfdk-aac \
--enable-libmp3lame \
--enable-libvpx \
--extra-cflags="-I/home/loken/ffmpeg/build32/libfdk-aac/include" \
--extra-ldflags="-L/home/loken/ffmpeg/build32/libfdk-aac/lib" \
--extra-cflags="-I/home/loken/ffmpeg/build32/libvpx/include" \
--extra-ldflags="-L/home/loken/ffmpeg/build32/libvpx/lib" \
--extra-cflags="-I/home/loken/ffmpeg/build32/libx264/include" \
--extra-ldflags="-L/home/loken/ffmpeg/build32/libx264/lib" \
--extra-cflags="-I/home/loken/ffmpeg/build32/libmp3lame/include" \
--extra-ldflags="-L/home/loken/ffmpeg/build32/libmp3lame/lib"
  
make -j8
make install

编译完成之后,build32/ffmpeg-4.2 目录如下:

FFmpeg-2-3.png

FFmpeg-2-4.png

可以看到 ffmpeg.exe 已经编译出来了。这个时候 在MSYS2 仿真linux命令行里,ffmpeg.exe 是可以运行的。如图。

FFmpeg-2-5.png

但是如果在window CMD 命令行运行 ffmpeg.exe ,会报错,提示缺少 libwinpthread-1.dll 等库。

FFmpeg-2-6.png

C:\msys64\mingw32\bin\libwinpthread-1.dll 复制到 \home\loken\ffmpeg\build32\ffmepg-4.2\bin 。其他缺少的 dll 文件也是如此操作。

拷贝完缺少的dll文件后,再运行 ffmpeg.exe 就不会报错了。 重要知识点:

  • 如何查看exe ,dll 的是 32位 还是 64位 ? 解答:dumpbin.exe /headers ffmpeg.exe

MSYS2 环境下 ffmpeg 的编译已经讲完了,下面介绍QT 如何调用 FFmpeg 的 api 函数。

之前编译ffmpeg 的时候,configure 指定了 --enable-shared,所以项目生成了几个DLL动态库。

  • avcodec-58.dll 编解码API。
  • avdevice-58.dll 设备API。
  • avfilter-7.dll 滤镜API
  • avformat-58.dll 容器API。
  • 等等。

下面介绍 QT 项目如何加入这些dll。如果之前没装过 qt 跟 Visual Studio 2015 请看第一篇文章。

1,打开Qt creator,点击New File Or Project,选择 Non-Qt Project ,选择 Plain C Application。

FFmpeg-2-8.png

2,勾选编译环境 kit。

FFmpeg-2-9.png

MSVC 的编译器跟 MinGW 编译器有什么不一样呢?如果你Qt项目里的 C 文件,里面用了linux 的api,那只能用MinGW来编译,用MSVC编译会报错。如果没用到 linux的api函数,用MSVC 还是 MinGW 都能编译成功。

3,把 \home\loken\ffmpeg\build32 整个目录拷贝到 ffmpeg-qt-version 项目目录下。

FFmpeg-2-9-1.png

4,修改 ffmpeg-qt-version.pro 文件:

TEMPLATE = app
CONFIG += console
CONFIG -= app_bundle
CONFIG -= qt
​
SOURCES += main.c
​
contains(QT_ARCH, i386) {
    message("32-bit")
    INCLUDEPATH += $$PWD/build32/ffmepg-4.2/include
    LIBS += $$PWD/build32/ffmepg-4.2/bin/avformat.lib \
            $$PWD/build32/ffmepg-4.2/bin/avcodec.lib \
            $$PWD/build32/ffmepg-4.2/bin/avdevice.lib \
            $$PWD/build32/ffmepg-4.2/bin/avfilter.lib \
            $$PWD/build32/ffmepg-4.2/bin/avutil.lib \
            $$PWD/build32/ffmepg-4.2/bin/postproc.lib \
            $$PWD/build32/ffmepg-4.2/bin/swresample.lib \
            $$PWD/build32/ffmepg-4.2/bin/swscale.lib
} else {
    message("64-bit")
}

5,修改 main.c 文件:

#include <stdio.h>
#include "libavutil/avutil.h"
int main(){
    printf("Hello FFMPEG, version is %s\n", av_version_info());
    return 0;
}

6,编译运行 ffmpeg-qt-version 项目。会提示确实缺少dll。

FFmpeg-2-11.png

7,把 build32/ffmpeg-4.2/bin/*.dll 所有DLL都复制到 build-ffmpeg-qt-version-Desktop_xxxx-Debug\debug 目录。然后再次编译运行 ffmpeg-qt-version 项目,就会正常打印出 version。

FFmpeg-2-12.png

注意事项:

  • 项目文件路径不要有中文,QT 可能会报错。

常见错误:

  • 如果报错找不到文件之类的,把qt 的 build-ffmpeg-qt-version-Desktop_xxx-Debug 目录删掉,因为可能有缓存,再重新执行上面步奏。

重要知识点:

  • 上面调用了 ffmpeg 的 api 函数 av_version_info() 打印版本号,这时候 ffmpeg-qt-version 项目并没有用到 linux api 函数,所以 用MinGW 32bit 还是 MSVC2015 32bit 编译都没问题。

  • 虽然我们的 avcodec-58.dll 是MinGW 编译出来的,但是还是可以用MSVC来编译其他的C文件。也就是说 MinGW 编译出来的 DLL 也是可以在 MSVC 环境中被使用的。我个人的理解是 DLL 已经是window系统级别的机器码,肯定能被 MSVC 调用。

  • 需要注意,MSYS2编译ffmpeg 的gcc 版本不能跟 Qt creator里面的MinGW的gcc版本差距太大。

    例如MSYS2里编译ffmpeg dll的gcc是11.0版本,而Qt creator的MinGW的gcc是 5.0,在项目里面就无法使用 ffmpeg 的dll,会报错,应该是gcc版本差距太大,二进制不兼容之类的。


©版权所属:知识星球:弦外之音,QQ:2338195090。

由于笔者的水平有限, 加之编写的同时还要参与开发工作,文中难免会出现一些错误或者不准确的地方,恳请读者批评指正。如果读者有任何宝贵意见,可以加我微信 Loken1。1。