【问题标题】:FFMPEG on cygwin failed to compile libx264 error: unknown type name ‘HMODULE’cygwin 上的 FFMPEG 无法编译 libx264 错误:未知类型名称“HMODULE”
【发布时间】:2017-12-24 04:00:28
【问题描述】:

我正在尝试在cygwin环境下在ffmpeg中编译libx264。

我遵循了来自Koohiimaster's blogFFMPEG compilation guideSO post 1SO post 2 的多个来源的一些指示,但我始终坚持同一步骤,即 libx264 编译(制作)过程。

如 FFMPEG 编译指南中所述,应遵循这些步骤以使 libx264 工作

cd ~/ffmpeg_sources
wget http://download.videolan.org/pub/x264/snapshots/last_x264.tar.bz2
tar xjvf last_x264.tar.bz2
cd x264-snapshot*
PATH="$HOME/bin:$PATH" ./configure --prefix="$HOME/ffmpeg_build" bindir="$HOME/bin" --enable-static --disable-opencl
PATH="$HOME/bin:$PATH" make
make install

但是当我输入这个命令 PATH="$HOME/bin:$PATH" make 时,编译器总是停止并出现以下错误:

In file included from input/avs.c:49:0:
./extras/avisynth_c.h:825:3: error: unknown type name ‘HMODULE’
HMODULE handle;
^

我想知道这是否是 libx264 源的错误,但在我尝试了几个早期的源版本后,它产生了同样的错误。有什么想法可以解决这个问题吗?

【问题讨论】:

    标签: ffmpeg cygwin libx264


    【解决方案1】:

    信息

    HMODULE 类型在 WinDef.h 中声明。因此,您缺少包含此标头。我认为通常WinDef.h 包含在windows.h 中。

    备选方案 1:不带 AVS

    如果您不需要 avs 支持,您可以禁用它,然后看看它是否有效:

    PATH="$HOME/bin:$PATH" ./configure --prefix="$HOME/ffmpeg_build" bindir="$HOME/bin" --enable-static --disable-opencl --disable-avs
    

    实际上,这是一个不错的选择,只需检查一下,看看它是否可以为您提供有关您的问题的更多信息。

    备选方案 2:检查 windows.h

    另一件事是检查您的配置中使用了哪个windows.h 文件。

    在 libx264 源中,input/input.h 包括 windows.h

    input.h 本身随后包含在avs.c 中。 avs.c 之后还包括 extras/avisynth_c.h。所以总而言之,当编译器出现HMODULE handle 行时,应该已经包含windows.h(其中应该包含WinDef.h)。

    因此,要么您的 windows.h 文件在某种程度上“错误”,要么在预处理过程中确实出了问题。

    【讨论】:

    • 您好 Jan,感谢您的指导。我已经尝试过第一个替代方案,但它会产生一个 asm 错误。所以我尝试使用 --disable-asm 命令禁用 asm,最后它可以在我的 bin 文件夹中生成 x264.exe。我将尝试对此进行深入挖掘,并在转换成功后立即报告。
    • 禁用 AVS 有什么作用?它会导致 FFmpeg 的缩减版本吗?
    【解决方案2】:

    在我的系统(Cygwin 2.9.0(0.318/5/3)/Windows 7 64-bit SP1)上,HMODULE 定义在 wtypes.h 中,windows.h 或任何其他包含的文件都不包含它。

    编辑 windows.h(在 /usr/lib/w32api/windows.h)以添加 #include <wtypes.h> 对我有用(我在 #define _INC_WINDOWS 之后添加了它)。

    我还在配置命令中添加了--extra-cflags="-I/usr/include/w32api/",以及--extra-ldflags="-L:/usr/local/lib/",尽管我不确定ldflags 添加是否与此相关或libfdk-aac

    【讨论】:

    • 这似乎禁用了 AVS?
    • 嘿@Hashim,我尝试了类似的方法(请参阅my answer)并得到以下结果。输入:$x264 --help | head -n 6;输出x264 core:157\nSyntax: x264 [options] -o outfile infile\n\nInfile can be raw (in which case resolution is required),\n or YUV4MPEG (*.y4m),\n or Avisynth if compiled with support (no). 最后一行似乎禁用了 AVS,但我不确定。
    【解决方案3】:

    编辑:我从快照页面查看了自述文件。

    $ wget -O - \
       https://download.videolan.org/x264/snapshots/x264-snapshot-20191218-README.txt \
        2>/dev/null
    The snapshotting service is discontinued.
    
    Please use https://code.videolan.org/videolan/x264/ to get the tarballs.
    

    因此,我使用新的存储库进行下载。

    如果您使用前面的说明,您可能希望清除以前的 x264 内容,如下所示

    cd $HOME/programs/ffmpeg/ffmpeg_sources/x264-snapshot-20191217-2245
    make clean
    make distclean
    

    然后,如果您为x264 运行make install,您还需要执行以下操作

    cd $HOME/programs/ffmpeg
    
    find . -type f -name "*x264*" -print0 | \
       xargs -I'{}' -0 \
         bash -c 'orig="{}"; echo; echo "Attempting to remove:"; '\
    'echo "${orig}"; echo "       ... "; echo "         ... as file ..."; '\
    '[ -e "${orig}" ] && rm "${orig}" && '\
    'echo "                              ... success" || '\
    'echo "                              ... FAILURE";'; \
    find . -type d -name "*x264*" -print0 | \
       xargs -I'{}' -0 \
         bash -c 'orig="{}"; echo; echo "Attempting to remove:"; '\
    'echo "${orig}"; echo "       ... "; echo "         ... as directory ..."; '\
    '[ -d "${orig}" ] && rm -rf "${orig}" && '\
    'echo "                              ... success" || '\
    'echo "                              ... FAILURE";';
    

    第二个命令有一个较短但信息较少的版本。它将尝试删除目录中已删除的文件,这可能需要更长的时间。我不确定检查它是否总是有效的最佳方法。

    find . -name "*x265*" -print0 | \
       xargs -I'{}' -0 \
         bash -c 'orig="{}"; echo > tmpf; [ -e "${orig}" ] && rm "${orig}" 2>tmpf; '\
    'grep -v "rm.*cannot.*remove.*directory" tmpf; rm tmpf; '\
    '[ -d "${orig}" ] && rm -rf "${orig}";' 
    

    现在,我们继续采用最新的方式来处理x264

    cd $HOME/programs/ffmpeg/ffmpeg_sources
    git clone https://code.videolan.org/videolan/x264.git
    cd x264
    

    从这里开始,我必须按照与快照页面中的 tarball 相同的步骤操作,即我只是重复了以

    开头的说明
    PATH="$HOME/programs/ffmpeg/bin:$PATH" \
        ./configure --prefix="$HOME/programs/ffmpeg/ffmpeg_build" \
                    --bindir="$HOME/programs/ffmpeg/bin" \
                    --enable-static`
    

    包括wtypes.h 修复。

    我已用 ++从哪里开始下载更新++

    标记了这个位置

    我的系统略有不同。多亏了@Missy 和@Jan 以及其他参考资料的提示——koohiimaster 尤其是(因为我想要一个 Cygwin 版本),以及 this SuperUser answer 的“如何编译最佳版本”,我才能够让事情顺利进行FFmpeg for Windows”(Windows 版本 - 远非我想要的)。

    但是,有一些事情完全不同,我将它们分享给任何可能遇到我这种情况的人。

    系统详情

    $ date && date +'%s'
    Sat, May  2, 2020  2:41:12 PM
    1588452072
    $ uname -a
    CYGWIN_NT-10.0 MY-MACHINE 3.1.4(0.340/5/3) 2020-02-19 08:49 x86_64 Cygwin
    $ bash --version | head -n 1
    GNU bash, version 4.4.12(3)-release (x86_64-unknown-cygwin)
    $ gcc --version | head -n 1
    gcc (GCC) 9.3.0
    $ g++ --version | head -n 1
    g++ (GCC) 9.3.0
    $ make --version | head -n 2
    GNU Make 4.3
    Built for x86_64-pc-cygwin
    $ systeminfo | sed -n 's#^OS\ *##p'
    Name:                   Microsoft Windows 10 Home
    Version:                10.0.18363 N/A Build 18363
    Manufacturer:           Microsoft Corporation
    Configuration:          Standalone Workstation
    Build Type:             Multiprocessor Free
    

    我的目录结构有点不同,但我希望足够接近,让每个人都可以跟随。


    我的步骤和(错误)输出

    mkdir -p ~/programs/ffmpeg
    cd ~/programs/ffmpeg
    mkdir bin && mkdir ffmpeg_sources && mkdir ffmpeg_build
    cd ffmpeg_build
    

    请注意,说明希望您使用以下命令下载和解压,

    wget http://download.videolan.org/pub/x264/snapshots/last_x264.tar.bz2
    tar xjvf last_x264.tar.bz2
    

    但是,这不是实际的 URL;他们希望您从https://download.videolan.org/x264/snapshots/ 下载最新的x264 版本。我还收到了README,因为它让我免于麻烦。

    wget https://download.videolan.org/x264/snapshots/x264-snapshot-20191217-2245.tar.bz2  ## necessary
    wget https://download.videolan.org/x264/snapshots/x264-snapshot-20191218-README.txt  ## optional, but helpful
    

    如果您在几个月左右看到此答案,希望您在文件名末尾有一个不同的日期。为了在这个答案中节省一些空间,我使用xjf 标志而不是xjvf - 我不想冗长。在untaring 之后,我会按照说明继续。

    $ tar xjf x264-snapshot-20191217-2245.tar.bz2
    $ cd x264-snapshot-20191217-2245
    

    现在,我们已准备好构建。您应该位于类似于以下的目录中(尽管您的日期可能不同)。

    $HOME/programs/ffmpeg/ffmpeg_sources/x264-snapshot-20191217-2245

    ++从哪里开始下载更新++

    cd $HOME/programs/ffmpeg/ffmpeg_sources
    git clone https://code.videolan.org/videolan/x264.git
    cd x264
    

    (如果您要进行较新的下载,您的目录应该是$HOME/programs/ffmpeg/ffmpeg_sources/x264

    $ PATH="$HOME/programs/ffmpeg/bin:$PATH" \
        ./configure --prefix="$HOME/programs/ffmpeg/ffmpeg_build" \
                    --bindir="$HOME/programs/ffmpeg/bin" \
                    --enable-static
    

    ## 抑制输出:关于配置的一些不错的信息。没有错误的东西。

    You can run 'make' or 'make fprofiled' now.
    

    下一条命令:

    $ PATH="$HOME/programs/ffmpeg/bin:$PATH" make -j $(nproc)
    

    ## 抑制输出:一些不错的输出 - 甚至没有任何警告。

    In file included from input/avs.c:49:
    ./extras/avisynth_c.h:825:3: error: unknown type name ‘HMODULE’
      825 |   HMODULE handle;
    

    ## 抑制输出:修复此问题后我们将看不到的一堆警告。

    make: *** [Makefile:272: input/avs.o] Error 1
    

    解决方案(以及如何实现)

    感谢@Missy,我知道要寻找什么以及该做什么。

    根据您使用的是较旧的快照还是较新的 git 内容,您当前的工作目录 (pwd) 会有所不同。

    $ pwd   ### (older snapshot)
    /home/bballdave025/programs/ffmpeg/ffmpeg_sources/x264-snapshot-20191217-2245
    $ pwd   ### (newer git stuff)
    /home/bballdave025/programs/ffmpeg/ffmpeg_sources/x264
    

    如果不匹配,cd进入你需要的目录。

    $ whereis w32api
    w32api: /usr/lib/w32api /usr/include/w32api
    grep -iIRHn "^typedef.*HMODULE[;]" /usr/include/w32api
    /usr/include/w32api/wtypes.h:78:typedef void *HMODULE;
    ## For grep
    ## -i : ignore case
    ## -I : ignore binary files
    ## -R : recursive search
    ## -H : output the filename
    ## -n : output the line number
    

    请注意,你们中的一些人可能拥有 mingw 版本或其他类似的版本

    /usr/i686-pc-cygwin/sys-root/usr/include/w32api/

    但如果我们想要一个 Cygwin 构建,那将无济于事。你可能需要像@Missy 那样做

    [add] --extra-cflags="-I/usr/include/w32api/"--extra-ldflags="-L:/usr/local/lib/" 到配置命令中

    不过,我不必这样做。

    我们可以转到./input/input.h./extras/avisynth_c.h(对我来说.~/programs/ffmpeg/ffmpeg_sources/x264-snapshot-20191217-2245)添加行以包含wtypes.h,但是,当我这样做时,它不起作用。该头文件存在问题,我们需要先修复。我将通过传递grep 命令在找到的行之前和之后给出十(10)行Context:-C 10。我还将用cat -n 输入行号。该命令如下(请注意,由于行号,grep 的正则表达式的开头不再有 ^ 锚点)。

    cat -n /usr/include/w32api/wtypes.h | grep -C 10 "typedef.*HMODULE[;]"

    这让我可以找到问题并用更少的行将其展示给您。我们将在 (-B <n_lines>) 之前和之后 (-A <n_lines>) 放一些。

    $   ### before
    $ cat -n /usr/include/w32api/wtypes.h | grep -B 6 -A 2 "typedef.*HMODULE[;]"
        72      byte data[1];
        73  } RemHBRUSH;
        74  #if 0
        75  typedef UINT_PTR WPARAM;
        76  typedef LONG_PTR LPARAM;
        77  typedef LONG_PTR LRESULT;
        78  typedef void *HMODULE;
        79  typedef void *HINSTANCE;
        80  typedef void *HTASK;
    

    #if 0 将是一个问题——它相当于说if false,所以它永远不会被评估或执行。 (如果您想一直看到#endif,请使用-A 49grep)。

    在我看来,最简单的解决方案是将typedef void *HMODULE:if 语句中删除。我会注意文件 cmets 的警告,

    $ head -n 5 /usr/include/w32api/wtypes.h   ### BEFORE
    /*** Autogenerated by WIDL 1.6 from include/wtypes.idl - Do not edit ***/
    
    #ifndef __REQUIRED_RPCNDR_H_VERSION__
    #define __REQUIRED_RPCNDR_H_VERSION__ 475
    #endif
    

    而不是编辑。我认为最好不要单独使用 Win32 API。我将头文件复制到我们的项目中。由于链接器查找头文件的方式,它会首先查找我们的ffmpeg_sources/wtypes.h。 (我尝试重命名它以避免可能的命名空间冲突,但这不起作用)。

    好的,当它位于我们的项目文件夹中时,我无法让链接器找到新的标头(我将其命名为 wtypesx264.h)。完成编辑后,我会将其移回 /usr/include/w32api/ 并使用新名称。

    再一次,我不想过多地使用 Win32 API,所以我不打算编辑 windows.h。这是副本,然后是编辑(我已经在vim 中完成,但您可以在任何您想要的编辑器中进行)。为了向您展示需要进行哪些更改,我展示了 BEFORE 版本 - 之前的 headgrep - 以及即将推出的 AFTER 版本。

    根据您使用的是较旧的快照还是较新的 git 内容,您当前的工作目录 (pwd) 会有所不同。

    $ pwd   ### (older snapshot)
    /home/bballdave025/programs/ffmpeg/ffmpeg_sources/x264-snapshot-20191217-2245
    $ pwd   ### (newer git stuff)
    /home/bballdave025/programs/ffmpeg/ffmpeg_sources/x264
    

    如果你的不匹配,cd 进入相应的目录。

    $ cp /usr/include/w32api/wtypes.h ./wtypes.h
    $ vim wtypes.h
    $ head -n 7 wtypes.h   ### AFTER
    /*** Edited from the version Autogenerated by WIDL 1.6 from include/wtypes.idl
     *  - Edited 2020-05-02 by bballdave025
     ***/
    
    #ifndef __REQUIRED_RPCNDR_H_VERSION__
    #define __REQUIRED_RPCNDR_H_VERSION__ 475
    #endif
    $ cat -n wtypes.h | head -n 83 | tail -n 10   ### AFTER
        74      byte data[1];
        75  } RemHBRUSH;
        76  typedef void *HMODULE;/*[A]Moved here from inside `#if 0` DWB 20200502*/
        77  #if 0
        78  typedef UINT_PTR WPARAM;
        79  typedef LONG_PTR LPARAM;
        80  typedef LONG_PTR LRESULT;
        81  /*[A]Removed `typedef void *HMODULE;` from inside `#if 0` DWB 20200502*/
        82  typedef void *HINSTANCE;
        83  typedef void *HTASK;
    

    现在,我们将在需要的位置包含头文件。再一次,我将显示之前和之后,以显示需要进行的编辑。

    第一次编辑:./input/input.h

    $ cat -n ./input/input.h | head -n 37 | tail -11   ### BEFORE
        27
        28  #ifndef X264_INPUT_H
        29  #define X264_INPUT_H
        30
        31  #include "x264cli.h"
        32
        33  #ifdef _WIN32
        34  #include <windows.h>
        35  #endif
        36
        37  /* options that are used by only some demuxers */
    $ vim ./input/input.h
    $ cat -n ./input/input.h | head -n 39 | tail -13   ### AFTER
        27
        28  #ifndef X264_INPUT_H
        29  #define X264_INPUT_H
        30
        31  #include "x264cli.h"
        32
        33  #ifdef _WIN32
        34  #include <windows.h>
        35  /*Next line added by bballdave025 2020-05-02*/
        36  #include "wtypes.h"
        37  #endif
        38
        39  /* options that are used by only some demuxers */
    

    第二次(也是最后一次)编辑:./extras/avisynth_c.h

    $ cat -n extras/avisynth_c.h | head -n 47 | tail -12   ### BEFORE
        36
        37  #ifndef __AVISYNTH_C__
        38  #define __AVISYNTH_C__
        39
        40  #ifdef __cplusplus
        41  #  define EXTERN_C extern "C"
        42  #else
        43  #  define EXTERN_C
        44  #endif
        45
        46  #define AVSC_USE_STDCALL 1
        47
    $ vim extras/avisynth_c.h
    $ cat -n extras/avisynth_c.h | head -n 53 | tail -18   ### AFTER
        36
        37  #ifndef __AVISYNTH_C__
        38  #define __AVISYNTH_C__
        39
        40  #ifdef __cplusplus
        41  #  define EXTERN_C extern "C"
        42  #else
        43  #  define EXTERN_C
        44  #endif
        45
        46  /*Start of the part added by bballdave025 2020-05-02*/
        47  #ifdef _WIN32
        48  #include "wtypes.h"
        49  #endif
        50  /*  End of the part added by bballdave025 2020-05-02*/
        51
        52  #define AVSC_USE_STDCALL 1
        53
    

    再试一次

    根据您使用的是较旧的快照还是较新的 git 内容,您当前的工作目录 (pwd) 会有所不同。

    $ pwd   ### (older snapshot)
    /home/bballdave025/programs/ffmpeg/ffmpeg_sources/x264-snapshot-20191217-2245
    $ pwd   ### (newer git stuff)
    /home/bballdave025/programs/ffmpeg/ffmpeg_sources/x264
    

    如果你的不匹配,cd 进入相应的目录。

    $ make clean       # I won't show any of the output - there's a lot
    $ make distclean   # I won't show any of the output - there's a lot
    

    让我们检查一下我们的更改是否通过distclean

    $ ls wt*.h
    wtypes.h
    $ grep -RHn "[#]include \"wtypes.h\"" .
    ./extras/avisynth_c.h:48:#include "wtypes.h"
    ./input/input.h:36:#include "wtypes.h"
    

    运行./configure 脚本;这很快,所以我不用担心使用多个处理器。

    $ PATH="$HOME/programs/ffmpeg/bin:$PATH" \
        ./configure --prefix="$HOME/programs/ffmpeg/ffmpeg_build" \
                    --bindir="$HOME/programs/ffmpeg/bin" \
                    --enable-static   ### I won't show output
    

    这是我们的测试,看看它是否有效 - 让我们使用我们所有的处理器运行 make

    $ PATH="$HOME/programs/ffmpeg/bin:$PATH" make -j $(nproc)
    

    输出有一些警告,但没有错误。我不想回去确保一切都达到完美-C 标准,所以我要继续安装部分。

    根据您使用的是较旧的快照还是较新的 git 内容,您当前的工作目录 (pwd) 会有所不同。

    $ pwd   ### (older snapshot)
    /home/bballdave025/programs/ffmpeg/ffmpeg_sources/x264-snapshot-20191217-2245
    $ pwd   ### (newer git stuff)
    /home/bballdave025/programs/ffmpeg/ffmpeg_sources/x264
    

    如果你的不匹配,cd 进入相应的目录。

    $ make install   ### I won't show output
    $ make distclean   ### I won't show output.
    

    现在,我们将使用~/.bashrc 将可执行文件添加到我们的PATH,但我们将首先备份内容,并确保我们知道备份名称,以防我们需要快速修复。

    备份

    $ date && date +'%s'
    Sun, May  3, 2020  3:07:48 PM
    1588540068
    $ cp ~/.bashrc ~/.bashrc.$(date +'%s').bak
    $ echo "$PATH" > ~/.PATH.$(date +'%s').bak
    $ find ~ -mindepth 1 -maxdepth 1 -type f -name ".bashrc*.bak" | sort | tail -1
    /home/13852/.bashrc.1588540100.bak
    $ find ~ -mindepth 1 -maxdepth 1 -type f -name ".PATH*.bak" | sort | tail -1
    /home/13852/.PATH.1588540128.bak
    

    实际变化

    $ echo -e "\n## Make x264 available\nexport PATH=\"/home/bballdave025/programs/ffmpeg/bin:"'$PATH'"\"\n\n" >> ~/.bashrc
    $ source ~/.bashrc
    

    测试预期输出

    二三仪式跳高视频。 (我不认为我可以上传它,在这里,所以尝试你自己的视频)。

    $ # TEST 1
    $ x264 --help | head -n 14
    x264 core:157
    Syntax: x264 [options] -o outfile infile
    
    Infile can be raw (in which case resolution is required),
      or YUV4MPEG (*.y4m),
      or Avisynth if compiled with support (no).
      or libav* formats if compiled with lavf support (no) or ffms support (no).
    Outfile type is selected by filename:
     .264 -> Raw bytestream
     .mkv -> Matroska
     .flv -> Flash Video
     .mp4 -> MP4 if compiled with GPAC or L-SMASH support (no)
    Output bit depth: 8/10
    $ ## That works, but it seems strange that there's no Avisynth after all
    $ ## that trouble
    
    $ # TEST 2
    $ bballdave025@MY-MACHINE /cygdrive/c/Users/bballdave025/Desktop
    $ x264 --input-res 480x360 --preset placebo --tune psnr -o highjump2.mkv FOSBUR-Dick_1968_Olympics_Mexico_City.mkv
    raw [info]: 480x360p 0:0 @ 25/1 fps (cfr)
    x264 [info]: using cpu capabilities: MMX2 SSE2Fast SSSE3 SSE4.2 AVX FMA3 BMI2 AX2
    x264 [info]: profile Progressive High, level 3.1, 4:2:0, 8-bit
    x264 [info]: frame I:1     Avg QP:28.40  size:147888
    x264 [info]: frame P:1     Avg QP:29.52  size:137810
    x264 [info]: mb I  I16..4:  0.0%  0.0% 100.0%
    x264 [info]: mb P  I16..4: 95.7%  0.0%  4.3%  P16..4:  0.0%  0.0%  0.0%  0.0%  .0%    skip: 0.0%
    x264 [info]: 8x8 transform intra:0.0%
    x264 [info]: coded y,uvDC,uvAC intra: 98.8% 100.0% 100.0%
    x264 [info]: i16 v,h,dc,p:  0%  0% 90% 10%
    x264 [info]: i4 v,h,dc,ddl,ddr,vr,hd,vl,hu:  6%  3% 37%  9% 10%  7% 10%  8% 10%
    x264 [info]: i8c dc,h,v,p: 91%  0%  0%  8%
    x264 [info]: Weighted P-Frames: Y:100.0% UV:100.0%
    x264 [info]: kb/s:28569.80
    
    encoded 2 frames, 3.83 fps, 28639.30 kb/s
    
    bballdave025@MY-COMPUTER /cygdrive/c/Users/bballdave025/Desktop
    $
    

    我们得到了一个输出视频。它几乎不像视频,但我预计质量会下降很多。

    由于我想将它用于 FFMPEG 的 Cygwin 构建,我认为我走在正确的轨道上。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-04-17
      • 1970-01-01
      • 2018-06-10
      • 1970-01-01
      • 2015-10-20
      • 2017-04-04
      • 2014-12-12
      • 1970-01-01
      相关资源
      最近更新 更多