MinGWでffmpeg, x264をビルド

MinGWはMinimalist GNU for Windowsの略で、Linux等で利用されているフリーのコンパイラ、gccを使ってWindowsアプリケーションをビルドできる環境をつくることができます。 MinGWを使って、動画・音声の変換ソフトとして名高いffmpeg、MPEG-4動画の作成ソフト、x264をビルドしてみます。 基本的な方向性はこんな感じで。

  1. 他のdll等に依存しないよう、staticなexeをx86版とx86_64版でそれぞれ作る
    → MinGWを入れていない素のWindowsで実行可能にする。
  2. 外部ライブラリをてんこ盛りにし、ライセンスの関係で再配布不可になるオプションも有効にする
    → そもそも再配布可能なバイナリは、インターネット上でいくらでも入手できるので。

ちなみに、MinGW環境だとプロセスの生成やファイルのI/Oがかなり遅いようで、特にconfigureが涙が出るほど遅いです。 できあがるバイナリは別に遅くないのですが、ビルドにはものすご〜く時間がかかるので試す人は覚悟しておきましょう(笑) 各種ライブラリのビルドで試行錯誤している時には何度も心が折れそうになりました…。 Windows上でやってる話ですが、やってることはLinuxでのそれと同じ感覚なので、このメモもLinuxのとこに置いてみるw というか、Linuxでクロスビルドした方が早かったんじゃ?

2016/6追記

等と書いていましたが、まあビルドするときだけの話だし、当時はともかく今のスペックだとそこまで遅いとも感じませんね。 最初のMinGW環境の構築も、今ならMSYS2をインストールすれば、パッケージマネージャーpacmanでgccやgitの追加、インストール済パッケージのアップデートもコマンド一発で済みます。

自分も、今はMSYS2に移行してますが、ffmpegx264, x265本体、またlamefdk-aac,xvidcore等のi686/x86_64のライブラリは自前でビルドしてます。 gitでリモートブランチをひっぱって、適当な自分設定をしてビルド、インストールまでをスクリプト化しちゃってるので、すっかり楽ちん♪

Windows用x64バイナリ

なんとなく一部のライブラリを入れ替えてライセンスをGPLにしたffmpeg, x264のバイナリを置いてみる。 一応、Windows Defederでチェック済。 MSYS2のgcc-6.3.0でビルドしたものだけど、最適化フラグとかの関係でHaswell以降のCPUじゃないと動かないかも。

2017年6月

(ライセンスの関係で無効にしたもの) (OpenSSLの代替)

MinGW環境の構築

MinGW環境のインストール

MinGW環境を作るには、公式のMinGW及びMSYSのインストーラを使う方法が一般的ですが、できるだけ新しいgccを使ってビルドしたいし、いろいろツールを探したり、32bitと64bitを両方ビルドできる環境を作るのはかなり面倒そうなので、xhmikosrさんのところから丸ごといただくことにしましたw

toolsフォルダにあるMSYS_MinGW_GCC_452_x86-x64_Full.7zをダウンロードし、適当なフォルダに展開します。 以降、D:\bin\msysに展開したとします。

解凍したMSYSフォルダにある msys.batをダブルクリックし、MinGWのプロンプトを立ち上げます。 以降、MinGWを起動するには msys.bat を実行する必要があるので、デスクトップにでもショートカットを作っておくと楽です。 ちなみにインストーラを使ってませんし、D:\bin\msys 以下をコピーすれば他のパソコンに環境を丸ごと持っていけるようになってます。

まずは、後々configureする時のために、pkg-config.exe等をコピーしておきます。

$ cd /bin
$ cp -af pkg-config.exe x86_64-w64-mingw32-pkg-config.exe
$ cd /mingw/bin
$ cp -af ar.exe i686-pc-mingw32-ar.exe
$ cp -af as.exe i686-pc-mingw32-as.exe

gitのインストール

色々なソフトの開発中の最新のリポジトリからソースを入手するためには、cvsやsvn、git等が必要になることがありますが、xhmikosrさんのパッケージにはgitが入ってません。 なので、msysgitからダウンロードしてインストールします。

私は執筆時点の最新版、PortableGit-1.7.4-preview20110204.7z を落として、MinGWと同じ D:\bin\msys 以下に解凍しました。 etcやbinの一部のファイルがxhmikosrのツリーと重複しますが、カブったファイルはすべて無視、つまりxhmikosrさん側優先で大丈夫なようです(多分w)。 sharedビルドのため、同じライブラリのバージョン違いのdllが複数入ってしまいますが、これは仕方ないところですね。


ffmpeg、x264のソースを入手

今回のお題目のffmpeg、x264のソースが必要になります。 リリース版ではなく最新のリビジョンを試したかったので、MinGWのプロンプトから以下のコマンドでそれぞれ入手しました。 ちなみにffmpegのソースはffmpeg-mtを試しています。

$ git clone git://git.videolan.org/x264.git x264
$ git clone git://git.gitorious.org/~astrange/ffmpeg/ffmpeg-mt.git ffmpeg-mt
$ svn checkout http://ffmpegsource.googlecode.com/svn/trunk/ ffms2

gpacのビルド&インストール

さっそく本題のビルドにいきたいところだけど、その前にまずx264が利用するgpacをインストールしておきます。 どうも公式のソースはちょっと問題があったりするらしいので、golgol7777さんのソースを使わせてもらいました。

$ git clone git://github.com/golgol7777/gpac.git gpac

【gpac 32bit版】
$ cd gpac
$ ./configure --prefix=/mingw/i686-pc-mingw32 --strip --static-mp4box
$ make lib apps
$ make install-lib
$ cp -f ./bin/gcc/MP4Box.exe /mingw/i686-pc-mingw32/bin

【gpac 64bit版】
$ make clean
$ ./configure  --prefix=/mingw/x86_64-w64-mingw32 --host=x86_64-w64-mingw32 \
--cross-prefix=x86_64-w64-mingw32- --cpu=x86_64 --target-os=mingw32 --strip --static-mp4box
$ make lib apps
$ make install-lib
$ cp -f ./bin/gcc/MP4Box.exe /mingw/x86_64-w64-mingw32/bin

ffmpeg、x264のビルド(一周目)

外部ライブラリをできるだけ入れるようにすると、ffmpegがx264に、x264がffmpegに依存する形になるので、まずは仮に一周目のビルドをします。 外部ライブラリは何も使わないなら、ここで終わってもいいと思います。 うまくいけば、mingw/i686-pc-mingw32 以下に32bit版が、mingw/x86_64-w64-mingw32 以下に64bit版が作られ、binフォルダのexeファイル単独で実行可能になるはずです。 以下、ビルドの際の注意点を書いときます。

  1. x264は、configureした後、できあがったconfig.makを編集して、LDFLAGSCLIの -lstdc++ の後ろに -static を追加してからmakeしないと、libstdc++-6.dllに依存したバイナリになってしまうようです。
  2. x264をビルドする際にfprofiledを指定して動画は読ませると自動で最適化してくれるらしいです。動画は何でもいいようですが、私は先人の例に倣ってhttp://media.xiph.org/video/derf/y4m/soccer_4cif.y4mをダウンロードして使いました。 動画はなくてもビルドはできます。
  3. ffms2のとこに適当なCFLAGSを指定してるのは、せっかくビルドするんだし、最適化をかけてみるぞ〜って時のサンプルです。あまり激しく最適化すると動作しないバイナリができちゃうかもしれないし、一回は普通に作っておかないとうまく動かない時に問題の切り分けが難しくなると思います。あと、ffmpeg等はcpuを自動認識して最適なコードを動かすようになってるみたいなので、ヘタに最適化しない方がいいのかも。
【ffmpeg-mt 32bit版】
$ PKG_CONFIG_PATH=/mingw/i686-pc-mingw32/lib/pkgconfig \
./configure --prefix=/mingw/i686-pc-mingw32 --enable-gpl --enable-version3 --enable-nonfree \
--enable-postproc --enable-memalign-hack --enable-runtime-cpudetect --enable-avisynth \
--enable-w32threads
$ make -j 5;make install
【ffmpeg-mt 64bit版】
$ make clean
$ PKG_CONFIG_PATH=/mingw/x86_64-w64-mingw32/lib/pkgconfig \
./configure --prefix=/mingw/x86_64-w64-mingw32 --enable-gpl --enable-version3 --enable-nonfree \
--enable-postproc --enable-memalign-hack --enable-runtime-cpudetect --enable-avisynth \
--enable-w32threads --cross-prefix=x86_64-w64-mingw32- --target-os=mingw32 --arch=x86_64 --cpu=x86_64
$ make -j 5;make install
【ffms2 32bit版】
$ CFLAGS="-O3 -march=native -fforce-addr -mfpmath=sse -msse2 -fomit-frame-pointer -fno-tree-vectorize" \
PKG_CONFIG_PATH=/mingw/i686-pc-mingw32/lib/pkgconfig \
./configure --prefix=/mingw/i686-pc-mingw32
$ make -j 5;make install-strip

【ffms2 64bit版】
$ make clean
$ CFLAGS="-O3 -march=native -fforce-addr -mfpmath=sse -msse2 -fomit-frame-pointer -fno-tree-vectorize" \
PKG_CONFIG_PATH=/mingw/x86_64-w64-mingw32/lib/pkgconfig \
./configure --prefix=/mingw/x86_64-w64-mingw32 --host=x86_64-w64-mingw32
$ make -j 5;make install-strip
【x264 32bit版】
$ PKG_CONFIG_PATH=/mingw/i686-pc-mingw32/lib/pkgconfig ./configure --prefix=/mingw/i686-pc-mingw32 \
--enable-win32thread
(config.makを書き換え)
$ make -j 5 fprofiled VIDS="~/soccer_4cif.y4m"; make install
【x264 64bit版】
$ make clean
$ PKG_CONFIG_PATH=/mingw/x86_64-w64-mingw32/lib/pkgconfig ./configure --prefix=/mingw/x86_64-w64-mingw32 \
--enable-win32thread --host=x86_64-w64-mingw32 --cross-prefix=x86_64-w64-mingw32-
(config.makを書き換え)
$ make -j 5 fprofiled VIDS="~/soccer_4cif.y4m"; make install

ffmpegで使う各種ライブラリのビルド

ffmpegで使う各種ライブラリをダウンロードし、それぞれビルドします。 今回試したライブラリとバージョンは以下のとおり。

configureスクリプトが用意されているものが多いので、ビルド方法はほぼ共通、それぞれ解凍したソースのフォルダでこんな感じに。 CFLAGSを指定して最適化するならお好みで。 ただし、libvpxとかはcpudetectしてるみたいなので留意されたし。

なお、configureオプションには、speexでは --enable-sse を、lameでは --enable-nasm を追加します。 xvidcoreは --disable-shared を除去し、ビルド完了後にlibフォルダにあるdllを削除、xvidcore.aをlibxvidcore.a にリネームしておきます。

【32bit版】
$ PKG_CONFIG_PATH=/mingw/i686-pc-mingw32/lib/pkgconfig \
./configure --prefix=/mingw/i686-pc-mingw32 --disable-shared
$ make -j 5;make install
【64bit版】
$ make clean
$ PKG_CONFIG_PATH=/mingw/x86_64-w64-mingw32/lib/pkgconfig \
./configure --prefix=/mingw/x86_64-w64-mingw32 --host=x86_64-w64-mingw32 --disable-shared
$ make -j 5;make install

gsmにはconfigureスクリプトはないので、こんな感じでビルド。 frontendのexeファイルのとこでエラーが発生しますが、ライブラリはできてるのでとりあえず無視(^^;;

【gsm 32bit版】
$ make
$ install -m 644 lib/libgsm.a /mingw/i686-pc-mingw32/lib/
$ mkdir -p /mingw/i686-pc-mingw32/include/gsm/
$ install -m 644 inc/gsm.h /mingw/i686-pc-mingw32/include/gsm/
【gsm 64bit版】
$ make clean
$ make CC=x86_64-w64-mingw32-gcc
$ install -m 644 lib/libgsm.a /mingw/x86_64-w64-mingw32/lib/
$ mkdir -p /mingw/x86_64-w64-mingw32/include/gsm/
$ install -m 644 inc/gsm.h /mingw/x86_64-w64-mingw32/include/gsm/

当初、うまくffmpegに入らなかったlibrtmpとlibschroedingerですが、何とか問題を回避する方法をみつけたので、こちらに移動しました(4/23)。 configureのログを眺めていたらlibrtmpのチェックのところでundefined reference 'timeGetTime@0'とか出ていて、この辺の関数はwinmmにあるもののようです。 schroedingerも、orcライブラリの辺りでundefined referenceになっていました。

結局、ffmpegのconfigureスクリプトに--extra-libs="-lwinmm -lorc-0.4"を追加してみたらOKでした。

【OpenSSL 32bit版】
$ ./Configure mingw threads no-shared zlib --prefix=/mingw/i686-pc-mingw32
$ make -j 5; make test
$ make install

【OpenSSL 64bit版】
$ ./Configure mingw64 threads no-shared zlib no-asm --prefix=/mingw/x86_64-w64-mingw32 \
--cross-compile-prefix=x86_64-w64-mingw32-
$ make -j 5; make test
$ make install

【rtmpdump 32bit版】
$ make SYS=mingw SHARED= CROSS_COMPILE=i686-pc-mingw32- \
OPT="-O3 -march=native -fno-tree-vectorize"
$ make SYS=mingw SHARED= install prefix=/mingw/i686-pc-mingw32

【rtmpdump 64bit版】
$ make SYS=mingw SHARED= CROSS_COMPILE=x86_64-w64-mingw32- \
OPT="-O3 -march=native -fno-tree-vectorize"
$ make SYS=mingw SHARED= install prefix=/mingw/x86_64-w64-mingw32

現在断念しているライブラリ(^^;;

WebMはx68_64のMinGWがtargetにないので無理やりパッチを当ててみて、とりあえずビルドはできたけど、やっぱりffmpegでまともに使えないみたいなので、とりあえず32bit版だけ利用し、64bitは現状断念…。

【libvpx 32bit版】
$ PKG_CONFIG_PATH=/mingw/i686-pc-mingw32/lib/pkgconfig \
./configure --target=x86-win32-gcc --cpu=i686 --prefix=/mingw/i686-pc-mingw32 --disable-shared \
--disable-examples
$ make -j 5;make install
【libvpx 64bit版】
$ make clean
$ PKG_CONFIG_PATH=/mingw/x86_64-w64-mingw32/lib/pkgconfig CROSS=x86_64-w64-mingw32- \
./configure --target=x86_64-win64-gcc --prefix=/mingw/x86_64-w64-mingw32 --disable-shared \
--disable-examples
$ make -j 5;make install

OpenCVは、OpenCVのソースファイルと、ビルドに必要なCMakeを入手して、こんな感じでやったらビルドはできたっぽい。 ちなみにx86_64版をビルドする場合は、4のconfigureで[Specify options for cross-compiling] を選び、C, C++, Fortranは mingw/bin/x86_64-w64-mingw32-の付いたgcc.exe、c++exe、gfortran.exeを、OSは[Windows]を指定すればいいみたい。

けど、static版ライブラリのファイル名がおかしかったり、ffmpegのconfigureで認識できなかったりする…。 別に動画の対応フォーマットが増えるわけでもないみたいだから、とりあえず抜きにして、後で考えるかなぁ。

  1. OpenCV-2.2.0-win.zipをダウンロードして解凍
  2. cmake-2.8.4-win32-x86.zip をダウンロードして D:\bin\mingw にでも解凍
  3. msysプロンプトから cmake-gui を実行して、ソースを1のフォルダ、ビルドバイナリを適当な新規フォルダに
  4. [configure]をクリックし、[MSYS Makefile]、[Specify native compilers]を選択して[Next]をクリック
  5. [generate]をクリックし、処理が完了したらcmake-guiを閉じる
  6. 3のフォルダに移動して make install/strip

xavsやnutはビルドはできたけど、まあいいやってことでスキップ。 この辺は、とりあえず自分的に優先度が低いので放置w


ffmpeg、x264のビルド(本番)

ライブラリも揃ったところで本番のビルド。 といってもffmpegのビルドオプションがやけに増えてる以外は一周目と同じことを繰り返しているだけです。 ただし、一周目のゴミが残っているとマズいのでそれぞれmake cleanしてから実行します。 libvpxは現在32bit版しかうまく動いていないので、64bit版のオプションからは外しています。

configureスクリプトがlibrtmp等の認識に失敗するので、--extra-libs="-lwinmm -lorc-0.4"を追加しました(4/23)。

【ffmpeg-mt 32bit版】
$ make clean
$ PKG_CONFIG_PATH=/mingw/i686-pc-mingw32/lib/pkgconfig \
./configure --prefix=/mingw/i686-pc-mingw32 --enable-gpl --enable-version3 --enable-nonfree \
--enable-postproc --enable-memalign-hack --enable-runtime-cpudetect --enable-avisynth --disable-debug \
--extra-libs="-lwinmm -lorc-0.4" --enable-w32threads --enable-zlib --enable-bzlib --enable-libmp3lame \
--enable-libfaac --enable-libvorbis --enable-libtheora --enable-libspeex --enable-libopencore-amrnb \
--enable-libopencore-amrwb --enable-libopenjpeg --enable-libxvid --enable-libgsm --enable-librtmp \
--enable-libschroedinger --enable-libx264 --enable-libvpx
$ make -j 5;make install
【ffmpeg-mt 64bit版】
$ make clean
$ PKG_CONFIG_PATH=/mingw/x86_64-w64-mingw32/lib/pkgconfig \
./configure --prefix=/mingw/x86_64-w64-mingw32 --cross-prefix=x86_64-w64-mingw32- --target-os=mingw32 \
--arch=x86_64 --cpu=x86_64 --enable-gpl --enable-version3 --enable-nonfree --enable-postproc \
--enable-memalign-hack --enable-runtime-cpudetect --enable-avisynth --disable-debug \
--extra-libs="-lwinmm -lorc-0.4"  --enable-w32threads --enable-zlib --enable-bzlib --enable-libmp3lame \
--enable-libfaac --enable-libvorbis --enable-libtheora --enable-libspeex --enable-libopencore-amrnb \
--enable-libopencore-amrwb --enable-libopenjpeg --enable-libxvid --enable-libgsm --enable-librtmp \
--enable-libschroedinger --enable-libx264
$ make -j 5;make install
【ffms2 32bit版】
$ make clean
$ CFLAGS="-O3 -march=native -fforce-addr -mfpmath=sse -msse2 -fomit-frame-pointer -fno-tree-vectorize" \
PKG_CONFIG_PATH=/mingw/i686-pc-mingw32/lib/pkgconfig \
./configure --prefix=/mingw/i686-pc-mingw32
$ make -j 5;make install-strip

【ffms2 64bit版】
$ make clean
$ CFLAGS="-O3 -march=native -fforce-addr -mfpmath=sse -msse2 -fomit-frame-pointer -fno-tree-vectorize" \
PKG_CONFIG_PATH=/mingw/x86_64-w64-mingw32/lib/pkgconfig \
./configure --prefix=/mingw/x86_64-w64-mingw32 --host=x86_64-w64-mingw32
$ make -j 5;make install-strip
【x264 32bit版】
$ make clean
$ PKG_CONFIG_PATH=/mingw/i686-pc-mingw32/lib/pkgconfig ./configure --prefix=/mingw/i686-pc-mingw32 \
--enable-win32thread
(config.makを書き換え)
$ make -j 5 fprofiled VIDS="~/soccer_4cif.y4m"; make install
【x264 64bit版】
$ make clean
$ PKG_CONFIG_PATH=/mingw/x86_64-w64-mingw32/lib/pkgconfig ./configure --prefix=/mingw/x86_64-w64-mingw32 \
--enable-win32thread --host=x86_64-w64-mingw32 --cross-prefix=x86_64-w64-mingw32-
(config.makを書き換え)
$ make -j 5 fprofiled VIDS="~/soccer_4cif.y4m"; make install

すべてつつがなく完了すると、D:\bin\msys\mingw\i686-pc-mingw32\bin にx86版、D:\bin\msys\mingw\x86_64-w64-mingw32\bin にx86_64版のffmpeg.exe、x264.exeができあがります(D:\bin\msys は最初にMinGWをインストールしたフォルダ)。 外部ライブラリをすべてstaticにビルドしてるので、ファイルサイズが結構大きくなっていますが(私の環境では10MB以上)、そのかわりobjdumpで確認してみても、素のWindowsが持ってるdllしか参照していません。 あとはこのファイルを任意のフォルダにコピーするなり、煮るなり、焼くなり、ご随意に。 といっても、この方法でビルドしたバイナリは自分のところで使う分にはOKですが、ライセンス上問題があるので勝手に第三者に配布してはいけません。 今回の趣旨に関係ないので試してませんが、ffmpegのビルドオプションから --enable-nonfree を除けば大丈夫…、になるかな?

$ cd /mingw/x86_64-w64-mingw32/bin
$ objdump -p ffmpeg.exe|grep "DLL Name"
        DLL Name: AVICAP32.dll
        DLL Name: AVIFIL32.dll
        DLL Name: KERNEL32.dll
        DLL Name: msvcrt.dll
        DLL Name: msvcrt.dll
        DLL Name: PSAPI.DLL
        DLL Name: USER32.dll

$ objdump -p x264.exe|grep "DLL Name"
        DLL Name: AVIFIL32.dll
        DLL Name: KERNEL32.dll
        DLL Name: msvcrt.dll
        DLL Name: msvcrt.dll
        DLL Name: WINMM.dll
D:\bin\msys\mingw\x86_64-w64-mingw32\bin>x264 --version
x264 0.114.1924 08d04a4
(libswscale 0.12.0)
(libavformat 52.104.0)
(ffmpegsource 2.15.0.1)
built on Apr  10 2011, gcc: 4.5.2
configuration: --bit-depth=8
x264 license: GPL version 2 or later
libswscale/libavformat/ffmpegsource license: nonfree and unredistributable
WARNING: This binary is unredistributable!

最後に、作成されたバイナリがまともな速度で動作しているかどうか、XvidVideo.RUと自分でビルドしたバイナリの簡単な比較をしてみました。 ちなみにリビジョンはともに1924です。 下の表は、soccer_4cif.y4m をオプションを何も指定しないで mp4に変換した際の平均fpsですが、ほぼ遜色ない速度が出ていると言って良さそうです。

x86版x86_64版
XvidVideo.RU 237.43fps267.06fps
自ビルド 245.44fps263.39fps

Return to Previous page一つ前のページに戻る / Return to topこのページのTOPに戻る