V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
glumess
V2EX  ›  程序员

Window 下 FFmpeg 和 LibX264 的编译和配置

  •  
  •   glumess · 285 天前 · 1687 次点击
    这是一个创建于 285 天前的主题,其中的信息可能已经有所发展或是发生改变。

    博客原文地址: https://glumes.com

    周末在家折腾 Windows 平台下 FFmepg 和 LibX264 库的编译,长期以来都是在 Mac 平台下做开发,切换到 Windows 平台下还是踩了不少坑。

    参考了网上很多编译文章,质量也是参差不齐,版本也是五花八门,但归根到底还是 Window 下编译环境太坑爹了。

    由于 Windows 上的命令行工具不好用,所以需要安装 MSYS 或者 Cygwin 这样的软件,它们的作用就是模拟 Linux 环境,其中 MSYS 还分 1.0 和 2.0 版本,有的博客文章比较久远,还使用的 1.0 版本了。

    机智地没有选择走 Cygwin 这条路线,节省了不少时间,但还是踩了 MSYS 1.0 版本的坑。

    如果你看到的文章是安装 MSYS 1.0 版本,并且还需要额外安装 MinGW 软件,那么请退出来,重新找个 MSYS 2.0 版本的文章吧,这样还能绕过 MinGW 单独下载太慢的问题(别问为什么我知道,你懂的)。

    使用 MSYS 2.0 版本,就不需要额外安装 MinGW 软件了,它提供了 pacman 软件管理器,通过它来安装依赖的软件。

    官网地址:https://www.msys2.org/

    MSYS 2.0 安装软件的时候,如果网速很慢,可以考虑更新镜像源,使用国内的源。

    搞定软件之后,先编译 libx264 ,在编译 FFmpeg 。

    MinGW 和 MSVC 的作用

    在实际编译的时候,我们也是用不上 MinGW 的,看了一些文章用 MinGW 来编译,最后编译出来的静态库是个 .a 的形式。

    一开始还没反应过来,Windows 下的静态库不是 .lib 嘛,直接用 CMake 去链接 .a 库肯定不行啊。

    还看到一些文章说先把 .a 库转成 .def 文件,然后再把 .def 文件转成 .lib 文件,甚至再把 .lib 文件转成 .dll 的动态库,这么来回折腾一下又是大坑,还好没跳进去。

    转念一想,我要用 CLion 开发工程,编辑器直接用 MSVC 就好了,也用不上 gcc 来编译代码,干嘛用 MinGW 去编译个 .a 库呢,直接编译出 .lib 不好嘛。

    瞬间思路就打开了,调整方向,谷歌直接搜索 compile ffmpeg with msvc ,很快就找到了答案(谷歌搜英文会过滤掉很多网上各种抄袭复制的无效文章)。

    LibX264 编译

    首先下载好 LibX264 源码。

    然后在开始菜单中找到并打开 x64 Native Tools Command Prompt for VS 2019:

    在打开的命令行终端中,进入到 MSYS 安装目录,打开 msys2_shell.cmd ,如下命令:

    注意后缀有个 -use-full-path 。

    这时会打开 MSYS 的新窗口,先把一些汇编依赖安装好:

    pacman -Syu
    pacman -S make
    pacman -S diffutils
    pacman -S yasm
    pacman -S nasm
    

    然后,在该窗口中进入到 LibX264 的源码目录下,把如下代码保存成 .sh 文件并执行:

    OPTIONS="--enable-shared"
    
    CC=cl ./configure $OPTIONS --enable-shared --prefix=$BUILD_DIR/
    
    make -j 16
    make install
    make clean
    

    执行后就开始编译了,注意 configure 命令前缀有个 CC=cl ,代表使用 MSVC 来编译了。

    编译后内容如下:

    将编译后的 libx264.dll.lib 改成 libx264.lib ,这就是静态库了。

    FFmpeg 编译

    继续在 MSYS 2.0 窗口中进入到下载好 FFmpeg 的源码目录,将如下代码保存成 .sh 文件并执行:

    OPTIONS="--toolchain=msvc \
             --arch=x86_64 \
             --enable-yasm  \
             --enable-asm \
             --enable-shared \
             --disable-static \
             --disable-programs \
             --enable-swresample \
             --enable-swscale \
             --enable-libx264 \
             --enable-gpl \
             "
    X264_INCLUDE=$libx264_path/include
    X264_LIB=$libx264_path/lib
    
    CC=cl ./configure $OPTIONS --extra-cflags="-I$X264_INCLUDE" --extra-ldflags="-LIBPATH:$X264_LIB" --prefix=$BUILD_DIR/
    make -j 16
    make install
    make clean
    

    要将代码中的 libx264_path 路径改成上面编译的 libx264 路径,FFmpeg 的编译需要依赖 libx264 的库。

    一番等待后,就编译出了动态库:

    CMake 依赖 FFmpeg 和 LibX264

    最后就是在 Clion 中使用 CMake 去依赖 FFmpeg 和 LibX264 了。

    定义了两个宏函数去链接头文件和库的目录:

    macro(link_ffmpeg)
        include_directories(${ffmpeg}/${platform}/${arch}/include)
        link_directories(${ffmpeg}/${platform}/${arch}/bin)
    endmacro()
    
    macro(link_libx264)
        include_directories(${libx264}/${platform}/${arch}/include)
        link_directories(${libx264}/${platform}/${arch}/lib)
    endmacro()
    

    注意,FFmpeg 链接库用的是 bin 目录下的,libx264 用的是 lib 目录下的。

    在最后这一步反而卡主了:

    target_link_libraries(demo libx264 avcodec avformat)
    

    要么提示找不到 libx264 ,要么找不到 avcodec-59 ,这个时候还需把 ffmpeg 编译结果的 bin 目录添加到系统环境变量中,为了保险起见,把 libx264 的 bin 目录也添加了。

    加完之后,跑一段代码测试一下:

    #include <iostream>
    
    extern "C"{
    #include "libavformat/avformat.h"
    #include "libavcodec/avcodec.h"
    #include "x264.h"
    }
    
    int main() {
        x264_param_t param;
        x264_param_default(&param);
        auto codec = avcodec_find_encoder(AV_CODEC_ID_H264);
        if (codec){
            std::cout << "success!!!" << std::endl;
        }
        return 0;
    }
    

    果然就成功了,这下可以在 Windows 上开发学习 FFmpeg 了。

    参考

    1. https://www.cnblogs.com/wswind/p/10650126.html
    2. https://blog.csdn.net/qq_18453581/article/details/120005712
    3. https://www.roxlu.com/2016/057/compiling-x264-on-windows-with-msvc
    4. https://www.roxlu.com/2019/062/compiling-ffmpeg-with-x264-on-windows-10-using-msvc
    22 条回复    2021-12-22 07:59:52 +08:00
    coderluan
        1
    coderluan  
       285 天前
    实际上你不用 gcc ,只用 msvc ,那么就根本没必要用 msys 或者 mingw ,你直接自己建个普通的空的 vs 项目,然后把全部 ffmpeg 源码塞进去,也是能编译的。
    kkocdko
        2
    kkocdko  
       285 天前 via Android
    建议 msvc 或者 tdm-gcc 或者 llvm-mingw
    个人对于 msys 这种东西比较不适应,用起来很怪,还不如直接用 Linux
    newmlp
        3
    newmlp  
       285 天前
    1 楼说的对
    EPr2hh6LADQWqRVH
        4
    EPr2hh6LADQWqRVH  
       285 天前
    宁死不屈,编译 wasm
    xylophone21
        5
    xylophone21  
       285 天前
    @coderluan 这样编译出来 configure 生成的那些代码就没有了,也许 ffmpeg 里有默认的(不确定)导致你仍然可以用,但这是基于 ffmpeg 的 make 系统比较简单

    BTW ,这就是为啥 Windows 不好用的原因之一
    weiceshi
        6
    weiceshi  
       285 天前
    @xylophone21
    vcpkge install ffmpeg[x264,gpl]:x64-windows
    weiceshi
        7
    weiceshi  
       285 天前
    @weiceshi
    > vcpkge install ffmpeg[x264,gpl]:x64-windows
    vcpkg install ffmpeg[x264,gpl]:x64-windows
    手滑多打了个 e
    glumess
        8
    glumess  
    OP
       285 天前
    @coderluan 还能这么搞的嘛,一开始嫌 vs 太大太卡了,没想到用它..
    glumess
        9
    glumess  
    OP
       285 天前
    @kkocdko 用了这次以后估计也不怎么用了...,不过你说的我留意一下,下次说不定就用上了
    glumess
        10
    glumess  
    OP
       285 天前
    @weiceshi 刚刚搜索了一下 vcpkge ,这个东西不错啊
    glumess
        11
    glumess  
    OP
       285 天前
    @avastms 向生活低头
    ysc3839
        12
    ysc3839  
       285 天前 via Android
    @coderluan #1 这么做不一定可行的,谁知道它的 configure 和 Makefile 做了什么操作,生成了什么代码,很可能就缺少某些动态生成的东西而编译失败。
    @xylophone21 #5 本质是类 Unix 系统仍然占有绝对的市场份额,不兼容它的都会被视为异类。
    coderluan
        13
    coderluan  
       285 天前
    @xylophone21 其实你可以试试 WSL ,有这个大家早就不怎么用 mingw 了。

    多说一句,我认为你想表达的核心“只是 Windows 不支持 Make 命令不方便”而已,但是你表达的时候很多概念都混在了一起,在加上“垃圾”之类的,你的一些原话如果单独发贴妥妥会让人喷。“怎么办啊,要不我替 Windows 给你道个歉吧。”
    coderluan
        14
    coderluan  
       285 天前
    @xylophone21 Sorry ,把你看成楼主了,上面是对楼主说的。
    hhjuteman
        15
    hhjuteman  
       285 天前
    其实你执行过一次就可以做成脚本了。

    SET PATH_BACKUP_=%PATH%
    SET PATH=%ROOT_DIR%\\ThirdParty\\msys64\\usr\\bin;%PATH%
    set CHERE_INVOKING=enabled_from_arguments
    set MSYS2_PATH_TYPE=inherit

    bash --login ../patches/build_ffmpeg_win.sh

    https://github.com/desktop-app/patches/blob/master/build_ffmpeg_win.sh


    我这里发了一段 telegram 里用到的脚本。全自动化

    另外我做 c++音视频开发从来不用 mac ,只用 windows 。vs 的调试是所有 ide 里面最强最好用的,vs 多线程调试图表清晰明了。

    我不知道 windows 开发不友好是从哪里来的,vs 调试图形程序是可以抓帧一帧一帧调试的。

    另外 windows 对 cpu 支持总是最新的,我以前在公司用 10700k ,后来还闲太慢了申请了 5800x 。每次在 mac 上搞点什么那弱鸡的 cpu 和狗屎一样的 xcode 总想让我砸电脑。
    WoWTxT
        16
    WoWTxT  
       285 天前
    这点我之前写过一个文章可以供你参考 https://blog.csdn.net/zhoukai216/article/details/105366905
    msg7086
        17
    msg7086  
       285 天前
    MSVC 和 GCC 编译出来的互相不兼容。
    你项目如果是用 GCC 编译,那就得用 GCC 的 ffmpeg 。MSVC 同理。
    像我编译 x265 多个版本,就是要提前用 GCC 和 MSVC 分别先编译 ffmpeg ,然后再链接到 GCC 和 MSVC 的 x265 上。
    lingxi27
        18
    lingxi27  
       285 天前
    非要在 windows 开发的话,上 docker 或者 wsl 吧
    glumess
        19
    glumess  
    OP
       285 天前
    @coderluan 大哥我错了...
    glumess
        20
    glumess  
    OP
       285 天前
    @hhjuteman win 用得少了...原来这么强大啊...
    glumess
        21
    glumess  
    OP
       285 天前
    @msg7086 嗯嗯,一开始没注意到这么多东西...
    mz02005
        22
    mz02005  
       284 天前 via iPhone
    用 vcpkg
    关于   ·   帮助文档   ·   API   ·   FAQ   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   882 人在线   最高记录 5497   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 48ms · UTC 22:08 · PVG 06:08 · LAX 15:08 · JFK 18:08
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.