You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Windows MinGW64环境下CMake构建FFmpeg C项目报错及优化咨询

Windows MinGW64下CMake构建FFmpeg 5.1 C项目的链接错误问题及优化需求

项目结构

ffmpeg-tutorial
├── include
│   ├── libavcodec
│   ├── libavdevice
│   ├── libavfilter
│   ├── libavformat
│   ├── libavutil
│   ├── libswresample
│   └── libswscale
├── lib
│   ├── pkgconfig
│   ├── libavcodec.a
│   ├── libavdevice.a
│   ├── libavfilter.a
│   ├── libformat.a
│   ├── libavutil.a
│   ├── libswresample.a
│   └── libswscale.a
├── CMakeLists.txt
└── main.c

CMakeLists.txt内容

cmake_minimum_required(VERSION 3.20)
project(ffmpeg_tutorial)

set(CMAKE_C_STANDARD 11)

include_directories(include)
link_directories(lib)
add_executable(ffmpeg_tutorial main.cpp)
target_link_libraries(ffmpeg_tutorial
        avformat
        avcodec
        avutil
        swscale
        swresample
        z
        bz2
        iconv
        ws2_32
        schannel
        kernel32
        advapi32
        kernel32
        user32
        gdi32
        winspool
        shell32
        ole32
        oleaut32
        uuid
        comdlg32
        advapi32
        )

main.c内容

#include <stdio.h>
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libswresample/swresample.h"
int main() {
    std::cout << "Hello, World!" << std::endl;
    std::cout << av_version_info() << std::endl;
    printf("ffmpeg version is %s\n", av_version_info());
    // Open input file
    AVFormatContext *inputContext = nullptr;
    if (avformat_open_input(&inputContext, "input.mp3", nullptr, nullptr) != 0) {
        printf("Couldn't open input file\n");
        return -1;
    }

    // Read input stream
    if (avformat_find_stream_info(inputContext, nullptr) < 0) {
        printf("Couldn't find stream information\n");
        return -1;
    }

    // Get audio stream index
    int audioStream = -1;
    for (int i = 0; i < inputContext->nb_streams; i++) {
        if (inputContext->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
            audioStream = i;
            break;
        }
    }

    if (audioStream == -1) {
        printf("Couldn't find audio stream\n");
        return -1;
    }
}

FFmpeg编译步骤

  1. 安装MSYS2及MinGW64工具链:
    pacman -S mingw-w64-x86_64-toolchain
    
  2. 安装编译依赖:
    pacman -S base-devel yasm nasm pkg-config
    
  3. 编译静态FFmpeg:
    cd ffmpeg
    ./configure --disable-shared --enable-static --arch=x86_64 --target-os=mingw32 --cross-prefix=x86_64-w64-mingw32- --pkg-config-flags=--static --prefix=../ffmpeg-build
    make -j $(nproc)
    make install
    

链接错误信息

[ 50%] Building CXX object CMakeFiles/ffmpeg_tutorial.dir/main.cpp.obj
[100%] Linking CXX executable ffmpeg_tutorial.exe
D:/Msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/10.3.0/../../../../x86_64-w64-mingw32/bin/ld.exe: G:/cywen_private/cpp_projects/ffmpeg-tutorial/lib/libavformat.a(tls_schannel.o): in function `tls_write':
D:\Msys64\usr\src\ffmpeg/libavformat/tls_schannel.c:563: undefined reference to `EncryptMessage'
D:/Msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/10.3.0/../../../../x86_64-w64-mingw32/bin/ld.exe: G:/cywen_private/cpp_projects/ffmpeg-tutorial/lib/libavformat.a(tls_schannel.o): in function `tls_read':
D:\Msys64\usr\src\ffmpeg/libavformat/tls_schannel.c:441: undefined reference to `DecryptMessage'
D:/Msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/10.3.0/../../../../x86_64-w64-mingw32/bin/ld.exe: G:/cywen_private/cpp_projects/ffmpeg-tutorial/lib/libavcodec.a(mfenc.o):mfenc.c:(.rdata$.refptr.IID_ICodecAPI[.refptr.IID_ICodecAPI]+0x0): undefined reference to `IID_ICodecAPI'
D:/Msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/10.3.0/../../../../x86_64-w64-mingw32/bin/ld.exe: G:/cywen_private/cpp_projects/ffmpeg-tutorial/lib/libavcodec.a(tiff.o): in function `tiff_uncompress_lzma':
D:\Msys64\usr\src\ffmpeg/libavcodec/tiff.c:577: undefined reference to `lzma_stream_decoder'
D:/Msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/10.3.0/../../../../x86_64-w64-mingw32/bin/ld.exe: D:\Msys64\usr\src\ffmpeg/libavcodec/tiff.c:582: undefined reference to `lzma_code'
D:/Msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/10.3.0/../../../../x86_64-w64-mingw32/bin/ld.exe: D:\Msys64\usr\src\ffmpeg/libavcodec/tiff.c:583: undefined reference to `lzma_end'
D:/Msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/10.3.0/../../../../x86_64-w64-mingw32/bin/ld.exe: G:/cywen_private/cpp_projects/ffmpeg-tutorial/lib/libavutil.a(random_seed.o): in function `av_get_random_seed':
D:\Msys64\usr\src\ffmpeg/libavutil/random_seed.c:127: undefined reference to `BCryptOpenAlgorithmProvider'
D:/Msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/10.3.0/../../../../x86_64-w64-mingw32/bin/ld.exe: D:\Msys64\usr\src\ffmpeg/libavutil/random_seed.c:130: undefined reference to `BCryptGenRandom'
D:/Msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/10.3.0/../../../../x86_64-w64-mingw32/bin/ld.exe: D:\Msys64\usr\src\ffmpeg/libavutil/random_seed.c:131: undefined reference to `BCryptCloseAlgorithmProvider'
collect2.exe: error: ld returned 1 exit status
mingw32-make[3]: *** [CMakeFiles\ffmpeg_tutorial.dir\build.make:95: ffmpeg_tutorial.exe] Error 1
mingw32-make[2]: *** [CMakeFiles\Makefile2:82: CMakeFiles/ffmpeg_tutorial.dir/all] Error 2
mingw32-make[1]: *** [CMakeFiles\Makefile2:89: CMakeFiles/ffmpeg_tutorial.dir/rule] Error 2
mingw32-make: *** [Makefile:123: ffmpeg_tutorial] Error 2

需求

  1. 解决上述链接错误
  2. 简化CMakeLists.txt中target_link_libraries的冗长参数
  3. 获取该FFmpeg项目的优化建议

解决方案与优化建议

一、链接错误解决

错误源于缺少FFmpeg依赖的系统库和第三方库,需补充到链接列表中:

  • EncryptMessage/DecryptMessage:补充链接secur32
  • IID_ICodecAPI:补充链接mfplat、mf(Media Foundation组件)
  • lzma_*系列函数:补充链接lzma(或编译FFmpeg时加--disable-lzma关闭该功能)
  • BCrypt*系列函数:补充链接bcrypt

临时修复的话,在原target_link_libraries末尾添加:

secur32 mfplat mf lzma bcrypt

二、简化CMake链接参数

利用FFmpeg编译时生成的pkgconfig配置文件,自动管理所有依赖,无需手动罗列库:
修改后的CMakeLists.txt:

cmake_minimum_required(VERSION 3.20)
project(ffmpeg_tutorial C) # 明确指定C语言,避免编译混淆

set(CMAKE_C_STANDARD 11)

# 指向本地FFmpeg的pkgconfig目录
set(ENV{PKG_CONFIG_PATH} "${CMAKE_SOURCE_DIR}/lib/pkgconfig")

find_package(PkgConfig REQUIRED)
# 检查所需FFmpeg组件
pkg_check_modules(FFMPEG REQUIRED IMPORTED_TARGET
    libavformat
    libavcodec
    libavutil
    libswscale
    libswresample
)

add_executable(ffmpeg_tutorial main.c)
# 直接使用pkgconfig导入的目标,自动处理所有依赖
target_link_libraries(ffmpeg_tutorial PRIVATE PkgConfig::FFMPEG)

三、项目优化建议

  1. 文件一致性修复:main.c中混用了C++的std::cout,要么将文件名改为main.cpp,要么替换为C语言的printf,避免编译语言混淆。
  2. FFmpeg编译裁剪:编译FFmpeg时只启用项目需要的功能,比如不需要网络/TLS可加--disable-network,不需要Media Foundation可加--disable-mf,不需要LZMA可加--disable-lzma,减少库体积和依赖。
  3. 资源管理完善:代码中打开的AVFormatContext未关闭,需在程序退出前添加avformat_close_input(&inputContext);避免内存泄漏。
  4. 错误处理增强:使用av_strerror将FFmpeg错误码转为可读信息,比如:
    int ret = avformat_open_input(&inputContext, "input.mp3", NULL, NULL);
    if (ret != 0) {
        char err_buf[AV_ERROR_MAX_STRING_SIZE];
        av_strerror(ret, err_buf, AV_ERROR_MAX_STRING_SIZE);
        printf("打开输入文件失败:%s\n", err_buf);
        return -1;
    }
    
  5. 编译警告开启:添加编译警告参数,提前发现潜在问题:
    target_compile_options(ffmpeg_tutorial PRIVATE -Wall -Wextra)
    
  6. CMake规范遵循:避免使用include_directories、link_directories这类全局指令,改用target_include_directories等目标级指令,符合现代CMake最佳实践。

内容的提问来源于stack exchange,提问作者flywen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 06:16:08