ffdshowとffmpeg

Win7Codecsの入れ替えから再び幕は上がり・・・

このネタを記事にすると決めたときから決めていたはじめの項目です。某アニメの後半部分の開始話のタイトルを使っています。

で、ちゃんと「再び幕は上がり」なのにも意味はありますよ。

Win7Codecsの入れ替えについてはいろいろと意味があります。この手のcodecは時々最新の物に入れ替えると変な機能がついていたりしますので。

入れ替えたことによって発覚した現象を解決しようとここ3日間くらいいろいろと調べまくっていたわけです。

ちなみに今回の入れ替えで初めて気がついたのは「ffdshowおよびWin7Codecsの設定はある程度簡単にバックアップできる」ことでした。

今までは入れ替えるたびに設定をやり直していたので大変でした。

ある意味タイミングが悪く、この作業をやり始めた次の日にWin7Codecsがまた更新されていたので「再び」入れ直したわけです。

入れ替えた目的が「ffdshowを使った動画エンコード処理を」と思っていたのですが、そうはいかない

ようにいつの間にかなっていました。調べてみると、どうやら今年(2011年)の5月付近にリリースされたバージョンあたりからffdshowのエンコード部分に変更が加えられて

ffdshow経由でのx264のエンコードやxvidのエンコードができなくなってしまった、ということがわかりました。

この機能を維持したいようでしたらffdshowを更新するのは「ちょっと待った」になりそうです。

で、私が考えたのは「ffdshowは元々ffmpegを使っているのだから、ffmpegのコードを強制的にマージさせて機能を復活できないか?」と言うことです。

というわけで、ffdshowとffmpegのコードを取得して・・・

いつの間にFFmpegのグループが分離してLibavなんて作ったんだ?

ffmpegのグループが分離していました・・・。というわけで、Libavも今回の作業の対象になるだろうな~というところです。

ソースコード自体はgitやらsvnやらで取得してくるか、すでにtarなどで固まっている物をとってくればいいと思います。

やってみるにはまず開発環境を

入れる必要があります。以降作業には以下のページを参考にしています。まずはFFmpeg(Libav)のコンパイルから。

各種ライブラリをコンパイルするところから始める場合はお気に入りの動画を携帯で見ようが参考になります。

すでに出来合いのライブラリを結合したりするのであればX5-452’s x264_L-SMASH builds for Windowsを参考にするのがいいともいます。

開発環境はMinGWを使います。開発環境自体もある意味出来合いのものを使った方がいいです。

これはFFmpegのコンパイル時にはMinGWを普通にインストールした物で成功したのですが、後からやるffdshowのコンパイル時にはコンパイル環境の問題からかうまく動かなかったんですね~。

私の使った環境は[XhmikosR’s builds GCC4.6.1]です。X5-452’s x264_L-SMASH builds for Windowsのcompileメモに説明がありますのでそちらを見るといいと思います。

で、次はffdshowを手動でコンパイルする環境です。ffdshowは今現在はffdshow-tryoutという形で継続しています。

一応ffdshowの開発用wikiに必要な物は書いてありますが、いろいろと正しくないような気がしているので書き直しです。

  • VisualStudio 2010 (Visual C++ 2010 Express Editionでも可。できればVisualStudio 2010 Professional Edition以上)
  • DirectX SDKの最新の物 (この記事を書いている段階ではJune 2010が最新)
  • Yasm (Visual Studio 2010系を使うのでそちらの物を選択)
  • Boost C++ Libraries
  • MinGW開発環境 (FFmpeg部のコンパイルに必要)

と、Boost C++ Librariesが説明に加えて必要です。ソースコードをsvnからとってきた後であればWindows側にsvnの管理は必要ありません。

FFmpegのコンパイル

説明ページをなぞるように読んでいけばだいたいうまくいきます。まず補助ライブラリの生成を自分で行うときです。

基本的には

$ ./configure --prefix=/mingw --enable-static --disable-shared
$ make
$ make install

のようなコマンドをがんばって入れていくだけです。

後でリンク時にdllをリンクしてしまうと微妙なので私の場合はconfigure時に後ろ2つのオプションがある物はそれをつけるようにしていました。

もちろん、前処理(bootstrap)が必要な物もあれば、configure時にちょっとしたオプションが必要な物もあります。

補助ライブラリを生成できればあとは本体のFFmpegのコンパイルです。Libavの場合も微妙にオプションの差はありますが基本的には同じオプションです。

使うライブラリに対してenableをつけていくことと、ちゃんと静的ライブラリをリンクするように指定すればまあ間違った物にはならないはずです。

ffdshowのコンパイル

ffdshowのFFmpeg部(ffdshow/src/ffmpeg)はconfigureもなにもないのでそのままmakeを行います。64bitDLLを生成するときにはちょっと別のオプションがいるようですが。

生成に成功すればbin(ffdshow/bin)にffmpeg.dllというDLLが生成されます。(src上でmakeをした場合にはxvidcore.dllも生成されます)

ちなみに、これがちゃんと互換性があるかどうかを調べておかないと後々まずかったりします。

Win7Codecでインストールされたffmpeg.dllと入れ替え可能かどうかちゃんと調べておいた方がいいと思います。

(この検査に引っかかって数時間くらい理由を考えた後にコンパイル環境を出来合いの物に変えましたが)

上にあるプロジェクトはVisualStudio2010で読み込ませればOKです。ffdshowのビルドを指示してみましょう。

たぶん失敗します。いろいろと。Boost C++のライブラリがちゃんと設定されていないためにコンパイルできなかったりYasmのコンパイル指示に-DPREFIXがついていなくて関数がリンクできなかったりQuickSyncを使ったdecode処理のライブラリが無いためにうまくいかなかったり・・・。

これでビルドが成功すればffdshow.axというファイルが生成されるはずです。今回やりたかったことを実現するにはこの二つが変更対象になります。

ffdshowに含まれているffmpegの変更を行ってみる

ここまでくれば本題の「ffdshowでエンコード可能な形式を増やそう」の部分にきます。手順だけ書いておきます。

  1. 増やしたい形式(たとえばx264)のエンコード処理をffmpeg上で参照しているファイルをffdshowのffmpegにコピー(今回の場合はlibavcodec/libx264.c)
  2. これをコンパイルするようにMakefile上にファイル名を追記(ffdshowのffmpegでコンパイルするファイル名はMakefile上では直接書いているので追記だけ)
  3. MakefileのGCCLIBSオプションに増やしたい形式で使用されるライブラリを追記(-lx264を追加)
  4. libavcodec/allcodec.cにこの処理によって追加される形式を追加(External Libraries付近に形式をまねて追記する)
  5. config.hに追加されたライブラリを使用するように設定([#define CONFIG_LIBX264_ENCODER 1]のような追記)
  6. コンパイルしてみる。ファイル不足のエラーが出たときはFFmpeg側からファイルを持って行ってコンパイルするようにさらに追記
  7. ffmpeg.dllのコンパイル成功

ちなみに、FFmpeg側からffdshowのffmpegにコピーする、といっていますが、これは完全には正しくありません。

なぜなら、ffdshow-tryoutのffmpeg部はどうやらLibavを基本として書いているライブラリがほとんどなので正しくはLibavにあるファイルを、になります。

これで、「ffmpeg.dllに指定したライブラリを使ったエンコード処理を含んだライブラリの作成」はできるはずです。

ffdshowのフィルタ部の動作変更・・・

どうもここがうまくいかないようで・・・。私がとった手順は以下の通りです。

  1. codecs/TvideoCodecLibavcodec.cppのコンストラクタにエンコード可能な形式一覧を登録している部分があるのでffmpeg.dllで有効にした形式を登録させる
  2. ffcodecs.cppに対象の形式のFOURCCを返すルーチンであるgetCodecFOURCCsがあるが、これがFOURCCを返していない場合(libvpxなど)があるので正しいFOURCCを返すように変更
  3. codecs/TvideoCodecLibavcodec.cppのTvideoCodecLibavcodec::getCompressColorspacesで対象のエンコーダが受け入れ可能な色形式を定義する(色形式は例ならlibavcodec/libx264.cの最後にエンコーダ情報の定義があるのでそれを参照)

としてみました。でもどの形式でもこれではうまくいかないんですよね・・・。

何かが足りないことは間違いないのですが・・・。

ちなみに、codecs/TvideoCodecLibavcodec.cppにはコメントアウトされている各種エンコード処理がありますのでコメントを解除するとたぶんその形式の変換はできるようになるような気がします。

結局うまくいかなかったが

いろいろと勉強にはなりました。

ちなみに、したかったことはというと「OggTheora形式の動画作成とWebM形式の動画作成をDirectShow経由(GraphEdit経由)でできるようになる」でした。

これだけなら実はXiph.OrgからOpenCodecsをダウンロードしてきてインストールすれば終わりだったりします。

しかもわかると思いますが、「DirectShow経由で」という条件がなければffmpeg.exeを使って終わりだったりしますし、そうでなくてもWebMならばMediaCoderの最新版でできるようになっていたりとこの数日間粘ったのは何だったのか?と思う結果となってしまいました。

さて、こんなことを思った原因が

「次のADVゲームのオープニングの動画形式をどうしようか?」

というのが発端だったりします。

この日記を見れば何となくわかりますが、今の私のADVシステムでOP動画を考えると

  • MPEG1
  • WindowsMediaVideo
  • OggTheora
  • WebM
  • MBC(MovieBlockCode,オリジナル形式)

の5種類の中から選んでいいことになります。どうせほとんどのメーカーではMPEG1のままですしね・・・。

で、どれがいいかを考えるためにすべてで簡単にエンコードできる環境を、がそもそもでした。

あまりに粘る目的を間違えたffdshowとffmpegのコンパイルとカスタムまでの道のりでした・・・。


コメントを残す

メールアドレスが公開されることはありません。

*

この記事のトラックバック用URL