• Qt使用FFmpeg的动态库


    C/C++ 项目有两种编译方式,MinGW 跟 MSVC,如下:

     

    1,《MinGW编译静态库

    2,《MSVC编译静态库

    但是 MinGW 编译的静态库,是不能给 MSVC 的链接器使用的,虽然两者编译器生成的 .o 跟 .obj 目标文件是 ABI 兼容的,但是他们的链接器不通用。

    而 静态库 实际上就是把 目标文件 打包在一起,所以 MinGW 编译的静态库,只能给 MinGW 编译方式的项目使用。MSVC 同理。



    下面来讲一下 qt creator 如何引入 用 MinGW 方式编译出来的 FFmpeg 动态库。

    MinGW 编译 FFmpeg 请参考 《用msys2与mingw编译FFmpeg》,编译完成之后,目录如下:

    上图中,这些 lib 并不是静态库,而是动态库的导入库。而 dll 文件就是动态库,使用 FFmpeg 的库的时候,还需要按需引入一些头文件,哪些头文件后面会讲到。

    实际上 ffmpeg-n4.4.1-mingw 目录,是有两种导入库的,一种是 xxx.lib ,一种是 xxx.dll.a ,如下:

    可以这么理解这两种导入库,lib 是给 msvc 链接器用的,.a 的导入库是给 MinGW 链接器用的。MinGW 跟 MSVC 对于格式的处理有点不一样,所以需要分开。

    这里提醒一下,虽然 dll 是用 MinGW 的 gcc 编译出来的,但是 dll 也可以给 MSVC 用的。他们是兼容的。

    不过,我实际测试后发现,qt creator 的 MinGW 可以用 lib 导入库,也可以用 .a 导入库,都可以。但是 qt creator 的 MSVC 只能用 lib 导入库 ,用 .a 导入库来定位就会报错。


    打开 Qt Creator,点击菜单栏的 New File or Project,选择 Non-Qt Project ,选择 Plain C Application。

    项目名称填 ffmpeg-shared-libs-use,编译工具选 qmake,如下:

    勾选编译环境 Kit ,Qt 5.15.2 MinGw 64-bit


    然后把 C:\msys64\home\loken\ffmpeg\build64 这个目录拷贝到 ffmpeg-qt-version 项目目录下,如下:

    然后 修改 ffmpeg-shared-libs-use.pro 的内容,修改为以下内容:

    1. TEMPLATE = app
    2. CONFIG += console c++11
    3. CONFIG -= app_bundle
    4. CONFIG -= qt
    5. #定义 DLL 的导入库的类型
    6. #DLL_IMPORT_TYPE = msvc
    7. DLL_IMPORT_TYPE = mingw
    8. #HEADERS += xxx.h
    9. SOURCES += main.c
    10. contains(QT_ARCH, i386) {
    11. message("32-bit")
    12. }
    13. contains(QT_ARCH, x86_64) {
    14. message("64-bit")
    15. message({% math %}DLL_IMPORT_TYPE)
    16. contains(DLL_IMPORT_TYPE, mingw) {
    17. INCLUDEPATH += {% endmath %}PWD/build64/ffmpeg-n4.4.1-mingw/include
    18. LIBS += {% math %}PWD/build64/ffmpeg-n4.4.1-mingw/lib/libavformat.dll.a \
    19. {% endmath %}PWD/build64/ffmpeg-n4.4.1-mingw/lib/libavcodec.dll.a \
    20. {% math %}PWD/build64/ffmpeg-n4.4.1-mingw/lib/libavdevice.dll.a \
    21. {% endmath %}PWD/build64/ffmpeg-n4.4.1-mingw/lib/libavfilter.dll.a \
    22. {% math %}PWD/build64/ffmpeg-n4.4.1-mingw/lib/libavutil.dll.a \
    23. {% endmath %}PWD/build64/ffmpeg-n4.4.1-mingw/lib/libpostproc.dll.a \
    24. {% math %}PWD/build64/ffmpeg-n4.4.1-mingw/lib/libswresample.dll.a \
    25. {% endmath %}PWD/build64/ffmpeg-n4.4.1-mingw/lib/libswscale.dll.a
    26. }
    27. contains(DLL_IMPORT_TYPE, msvc) {
    28. INCLUDEPATH += {% math %}PWD/build64/ffmpeg-n4.4.1-mingw/include
    29. LIBS += {% endmath %}PWD/build64/ffmpeg-n4.4.1-mingw/bin/avcodec.lib \
    30. {% math %}PWD/build64/ffmpeg-n4.4.1-mingw/bin/avdevice.lib \
    31. {% endmath %}PWD/build64/ffmpeg-n4.4.1-mingw/bin/avfilter.lib \
    32. {% math %}PWD/build64/ffmpeg-n4.4.1-mingw/bin/avformat.lib \
    33. {% endmath %}PWD/build64/ffmpeg-n4.4.1-mingw/bin/avutil.lib \
    34. {% math %}PWD/build64/ffmpeg-n4.4.1-mingw/bin/postproc.lib \
    35. {% endmath %}PWD/build64/ffmpeg-n4.4.1-mingw/bin/swresample.lib \
    36. $$PWD/build64/ffmpeg-n4.4.1-mingw/bin/swscale.lib
    37. }
    38. }

    提示:gitbook 生成 html 的时候 改乱了 上面的代码,请按照下图进行修改:

    然后把 main.c 的内容也修改一下,创建项目的时候只是输出了一个 hello world,我们现在在 main.c 里面调一下 FFmpeg 的一些 API 函数,如下:

    1. #include <stdio.h>
    2. #include "libavcodec/avcodec.h"
    3. #include "libavdevice/avdevice.h"
    4. #include "libavfilter/avfilter.h"
    5. #include "libavformat/avformat.h"
    6. int main()
    7. {
    8. printf("avcodec version is %u \n",avcodec_version());
    9. printf("avdevice version is %u \n",avdevice_version());
    10. printf("avfilter version is %u \n",avfilter_version());
    11. printf("avfilter version is %u \n",avformat_version());
    12. return 0;
    13. }

    上面的代码打印了 4 个库的版本号,我为什么知道有这 4个函数可以用,可以用以下命令查看 dll 提供了哪些函数可以调用。

    dumpbin /EXPORTS ./avcodec-58.dll > avcodec-58.txt
    

    然后去 FFmpeg-n4.4.1 的源码里面搜这个函数的定义,有哪些参数,返回值就行了。一般在 头文件里面,所以我上面引入了 4个头文件。

    也可以查官网的文档手册来看 API 函数的调用。


    上面这样改好之后,点 qt creator 编译运行的时候会报找不到 一些dll,这时候需要把 这些缺失的 dll 复制到 exe 的同目录下,因为 我们的 FFmpeg 动态库在 MinGW 环境下编译的,所以依赖一些 MinGW的库,也需要把这些库复制过来,例如 libiconv-2.dll ,liblzma-5.dll 等等。

    这些库一定要复制对,不要把 32位的 复制过来,推荐 Everything 搜索,如下:

    复制完之后如下:

    这样,再次运行,就可以正常打印出 信息,如下:


    下面再使用 qt creator 的 MSVC 来编译 main.c 看看,如下:

    同时要修改一下 DLL_IMPORT_TYPE 变量,设置为 msvc,这样链接的时候就会使用 lib 后缀的导入库,因为我 pro 文件里面用了这个 DLL_IMPORT_TYPE 变量来执行不同的分支代码。


    前面 引入的 都是 msys2 + mingw 编译出来 FFmpeg 动态库。

    qt creator 如何 引入 msys2 + msvc 编译出来 FFmpeg 动态库 原理也是类似的,这里就不讲解了。


    推荐一个零声学院免费公开课程,个人觉得老师讲得不错,分享给大家:[Linux,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,TCP/IP,协程,DPDK等技术内容,立即学习]

  • 相关阅读:
    c++ std::mutex 多个线程同时访问的同步原语
    苹果“欠”用户的承诺,何时会兑现?
    6种方法轻松将PDF转换为Word文档,办公必备!
    opencv 车牌识别
    宝塔面板一键部署芸众商城智慧商业系统 打造多终端直播分销商城
    C++之类和函数权限访问总结(二百二十七)
    网页元素解析a标签
    Java第四十六天,Git系列,Git中级
    Leetcode(695)——岛屿的最大面积
    Tkinter 入门之旅
  • 原文地址:https://blog.csdn.net/u012117034/article/details/125619873