cmake链接ffmpeg静态库的方法,及报错答解

参考文章:

【Android FFMPEG 开发】Android Studio 中配置 FFMPEG 库注意事项 ( 静态库 链接 libz.so 库 | 导入 FFMPEG 函数库顺序 )_wx5c66153045676的技术博客_51CTO博客

文章目录
    ​ ​I . 导入 z 库 ( FFMPEG 动态库 与 静态库区别 )​​
    ​ ​II . FFMPEG 库引入顺序​​
    ​ ​III . Android Studio 中 FFMPEG 静态库引入完整 CMakeList.txt 构建脚本​​

 I . 导入 z 库 ( FFMPEG 动态库 与 静态库区别 )

1 . 导入 FFMPEG 静态库 会报以下错误 :​

libavformat/id3v2.c:1021: error: undefined reference to 'uncompress'
  libavformat/rtmpproto.c:1077: error: undefined reference to 'inflateInit_'
  libavformat/rtmpproto.c:1087: error: undefined reference to 'inflate'
  libavformat/rtmpproto.c:1105: error: undefined reference to 'inflateEnd'
  libavformat/http.c:1646: error: undefined reference to 'inflateEnd'
  libavformat/http.c:680: error: undefined reference to 'inflateEnd'
  libavformat/http.c:681: error: undefined reference to 'inflateInit2_'
  libavformat/http.c:686: error: undefined reference to 'zlibCompileFlags'
  libavformat/http.c:1437: error: undefined reference to 'inflate'
  libavformat/matroskadec.c:1402: error: undefined reference to 'inflateInit_'
  libavformat/matroskadec.c:1410: error: undefined reference to 'inflateEnd'
  libavformat/matroskadec.c:1417: error: undefined reference to 'inflate'
  libavformat/mov.c:5073: error: undefined reference to 'uncompress'
  libavformat/swfdec.c:364: error: undefined reference to 'uncompress'
  libavformat/swfdec.c:153: error: undefined reference to 'inflateInit_'
  libavformat/swfdec.c:121: error: undefined reference to 'inflate'
  libavcodec/cscd.c:93: error: undefined reference to 'uncompress'
  libavcodec/flashsv.c:126: error: undefined reference to 'inflateInit_'
  libavcodec/flashsv.c:259: error: undefined reference to 'deflateInit_'
  libavcodec/flashsv.c:261: error: undefined reference to 'deflateBound'
  libavcodec/flashsv.c:262: error: undefined reference to 'deflateEnd'
  libavcodec/flashsv.c:191: error: undefined reference to 'inflateReset'
  libavcodec/flashsv.c:210: error: undefined reference to 'inflateSync'
  libavcodec/flashsv.c:160: error: undefined reference to 'deflateInit_'
  libavcodec/flashsv.c:166: error: undefined reference to 'deflate'
  libavcodec/flashsv.c:167: error: undefined reference to 'deflateEnd'
  libavcodec/flashsv.c:169: error: undefined reference to 'inflateReset'
  libavcodec/lcldec.c:134: error: undefined reference to 'inflateReset'
  libavcodec/mscc.c:141: error: undefined reference to 'inflateReset'
  clang++: error: linker command failed with exit code 1 (use -v to see invocation)
  ninja: build stopped: subcommand failed.

2 . 问题原因 :​ 这是由于没有找到 z 库 ( libz.so ) 导致的 ;

3 . 修改方法 :​ 在 CMakeList.txt 构建脚本中 , 链接库时链接 z 库 ; 在 target_link_libraries 中 , 添加 z 库的链接 , 如下 :

 4 . FFMPEG 静态库 :​ FFMPEG 使用静态库编译需要增加额外配置 , 如上述的 libz.so 库 ; 因为静态库在打包时就需要将所依赖的库都打包到静态库中 ;

5 . FFMPEG 动态库 :​ 如果使用的是 FFMPEG 动态库 , 则不需要引入 z 库 , 动态库在运行时才链接其用到的函数库 ;


II . FFMPEG 库引入顺序

1 . 问题产生 :​ Android Studio 中导入 FFMPEG 库后 , 编译时报如下错误 ; 

libavformat/utils.c:5548: error: undefined reference to 'av_bitstream_filter_filter'
  libavformat/codec2.c:74: error: undefined reference to 'avpriv_codec2_mode_bit_rate'
  libavformat/codec2.c:75: error: undefined reference to 'avpriv_codec2_mode_frame_size'
  libavformat/codec2.c:76: error: undefined reference to 'avpriv_codec2_mode_block_align'
  libavformat/spdifdec.c:63: error: undefined reference to 'av_adts_header_parse'
  clang++: error: linker command failed with exit code 1 (use -v to see invocation)
  ninja: build stopped: subcommand failed.

2 . FFMPEG 导入顺序 :​ FFMPEG 中的 6 个模块 之间有相互依赖关系 , 必须按照指定的顺序进行加载 ;

​3 . 问题案例分析 :​ avcodec 模块 ( 音视频编解码 ) 需要依赖 avformat 模块 ( 音频封装格式 ) ; 因此 , 导入 FFMPEG 函数库时 , avcodec 模块 必须在 avformat 模块之后 ;

​4 . 推荐顺序 :​ ① avfilter , ② avformat , ③ avcodec , ④ avutil , ⑤ swresample , ⑥ swscale ;

# FFMPEG 静态库
        # 注意这些库的顺序必须按照如下进行 , 否则会报错
        #   这些库之间有依赖的关系 , 必须按照顺序加载库 , 如 avcodec 内部依赖 avformat 库
        avfilter
        avformat
        avcodec
        avutil
        swresample
        swscale

III . Android Studio 中 FFMPEG 静态库引入完整 CMakeList.txt 构建脚本

# I . 指定 CMake 最低版本
cmake_minimum_required(VERSION 3.4.1)

# II . 设置函数库编译
add_library( # 参数 1 : 设置生成的动态库名称
        native-lib

        # 参数 2 : 设置生成的函数库类型 : ① 静态库 STATIC ② 动态库 SHARED
        SHARED

        # 参数 3 : 配置要编译的源文件
        native-lib.cpp
        FFMPEG.cpp
        JavaCallHelper.cpp
        AudioChannel.cpp
        VideoChannel.cpp)

# III . 到预设的目录查找 log 库 , 将找到的路径赋值给 log-lib
#       这个路径是 NDK 的 ndk-bundle\platforms\android-29\arch-arm\usr\lib\liblog.so
#       不同的 Android 版本号 和 CPU 架构 需要到对应的目录中查找 , 此处是 29 版本 32 位 ARM 架构的日志库
#
# 可以不配置 :
#       可以不进行该配置, 直接在后面的 target_link_libraries 中链接 log 也不会出错
find_library(
        log-lib

        log)


# IV . 指定 FFMPEG 头文件查找目录
#           CMAKE_SOURCE_DIR 指的是当前的文件地址
include_directories(${CMAKE_SOURCE_DIR}/include)

# V . 指定 FFMPEG 静态库
# CMAKE_CXX_FLAGS 表示会将 C++ 的参数传给编译器
# CMAKE_C_FLAGS 表示会将 C 参数传给编译器

# 参数设置 : 传递 CMAKE_CXX_FLAGS C+= 参数给编译器时 , 在 该参数后面指定库的路径
#   CMAKE_SOURCE_DIR 指的是当前的文件地址
#   -L 参数指定动态库的查找路径
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -L${CMAKE_SOURCE_DIR}/lib")


# V . 链接函数库
#       参数 1 : 本构建脚本要生成的动态库目标
#       参数 2 ~ ... : 后面是之前预编译的动态库或静态库 , 或引入的动态库
target_link_libraries(
        native-lib

        # FFMPEG 静态库
        # 注意这些库的顺序必须按照如下进行 , 否则会报错
        #   这些库之间有依赖的关系 , 必须按照顺序加载库 , 如 avcodec 内部依赖 avformat 库
        avfilter
        avformat
        avcodec
        avutil
        swresample
        swscale

        # 日志库
        ${log-lib}

        #FFMPEG 使用到了 libz 库 , 没有会报错
        #   FFMPEG 对于 z 的依赖是以动态库的形式进行的
        #   如果 FFMPEG 是动态库 , 那么可以不链接这个库 , 可以运行时链接这个库
        #   当前 FFMPEG 是静态库 , 需要在编译时将这个库打包到静态库中
        #   推荐使用静态库 , 静态库打包出来的库比动态库小很多 , 一倍左右
        z
)

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 使用CMake添加FFmpeg头文件可以分为以下几个步骤: 1. 在CMakeLists.txt文件中添加以下代码以包含FindFFmpeg.cmake文件,该文件可用于查找FFmpeg库及头文件: ``` set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/") find_package(FFmpeg REQUIRED) ``` 2. 在cmake/Modules文件夹中创建FindFFmpeg.cmake文件,该文件包含用于查找FFmpeg库的CMake代码。以下是FindFFmpeg.cmake文件的示例: ``` find_path(AVCODEC_INCLUDE_DIR libavcodec/avcodec.h PATH_SUFFIXES ffmpeg) find_library(AVCODEC_LIBRARY avcodec) find_path(AVFORMAT_INCLUDE_DIR libavformat/avformat.h PATH_SUFFIXES ffmpeg) find_library(AVFORMAT_LIBRARY avformat) find_path(AVUTIL_INCLUDE_DIR libavutil/avutil.h PATH_SUFFIXES ffmpeg) find_library(AVUTIL_LIBRARY avutil) include(FindPackageHandleStandardArgs) FIND_PACKAGE_HANDLE_STANDARD_ARGS(FFmpeg DEFAULT_MSG AVCODEC_LIBRARY AVFORMAT_LIBRARY AVUTIL_LIBRARY) mark_as_advanced(AVCODEC_INCLUDE_DIR AVFORMAT_INCLUDE_DIR AVUTIL_INCLUDE_DIR AVCODEC_LIBRARY AVFORMAT_LIBRARY AVUTIL_LIBRARY) ``` 3. 在源代码中包含FFmpeg头文件。例如,您可以在源代码中添加以下行: ``` #include <libavformat/avformat.h> #include <libavcodec/avcodec.h> #include <libavutil/avutil.h> ``` 完成上述步骤后,您的项目就应该能够包含并使用FFmpeg库及头文件了。如果在编译过程中出现任何问题,可以检查FindFFmpeg.cmake文件是否正确查找了FFmpeg库及头文件。 ### 回答2: cmake是一个跨平台的编译工具,可以让开发者更方便地构建和编译项目。要添加FFmpeg头文件到cmake中,需要按照以下步骤进行操作: 1. 首先,确保已经安装了FFmpeg,并且知道其安装的路径。 2. 打开项目的CMakeLists.txt文件,并在文件顶部添加一行代码,将FFmpeg的安装路径存储在一个变量中,例如: ```cmake # 设置FFmpeg的安装路径 set(FFMPEG_DIR "/path/to/ffmpeg") ``` 可以将`/path/to/ffmpeg`替换为实际的FFmpeg安装路径。 3. 在CMakeLists.txt文件中的`include_directories`部分下方添加以下代码,以添加FFmpeg的头文件路径: ```cmake # 添加FFmpeg的头文件路径 include_directories(${FFMPEG_DIR}/include) ``` 这将告诉cmake在编译期间搜索FFmpeg的头文件。 4. 最后,确保在链接时能够找到FFmpeg的库文件。在CMakeLists.txt文件的`target_link_libraries`部分下方添加以下代码: ```cmake # 添加FFmpeg的库文件路径和库名称 target_link_libraries(your_target_name ${FFMPEG_DIR}/lib/libavcodec.so ${FFMPEG_DIR}/lib/libavformat.so ${FFMPEG_DIR}/lib/libavutil.so) ``` 这里的`your_target_name`应替换为你的目标名称,`${FFMPEG_DIR}/lib/libavcodec.so`、`${FFMPEG_DIR}/lib/libavformat.so`和`${FFMPEG_DIR}/lib/libavutil.so`分别是FFmpeg的三个核心库文件,路径和名称可能需要根据实际情况进行调整。 以上就是使用cmake添加FFmpeg头文件的步骤。完成后,重新运行cmake即可开始编译包含FFmpeg功能的项目。 ### 回答3: 要在CMake中添加FFmpeg头文件,可以按照以下步骤进行: 1. 首先,确保已经在系统中安装了FFmpeg,并知道其安装路径。 2. 打开你的CMakeLists.txt文件,在顶层项目目录下。 3. 导入FFmpeg的头文件路径,可以使用`include_directories()`命令。例如,假设FFmpeg的头文件路径为`/usr/local/include/ffmpeg`,添加以下命令: ``` include_directories(/usr/local/include/ffmpeg) ``` 4. 如果你还使用了FFmpeg的库文件,可以继续添加库文件路径和链接库的命令。 5. 保存CMakeLists.txt文件。 6. 使用CMake重新生成项目的构建文件。 完成以上步骤后,CMake会在编译项目时自动包含FFmpeg的头文件,以便正确编译和链接项目中的FFmpeg相关代码。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值