トップ 検索 一覧 差分 ソース ヘルプ RSS ログイン

MinGW+ffmpeg(8)改造

MinGW+ffmpeg(8)改造

当初の方針より、x264のMBAFF(インターレース)に対応し、携帯動画変換君で使用可能なffmpegに改造する。なお、ここではRevision9726(2007/07/18)のffmpegに対し修正を施す。最新版でない理由はMinGW+ffmpeg(1)準備を参照。

 携帯動画変換君対応

まずは、携帯動画変換君でエンコードを中断する場合の対応を含める。この対応を行わないと、中断ボタンを押してもffmpegが終了せず、中止するには携帯動画変換君ごと強制終了するしかなくなる。修正するのはffmpeg.cの以下の関数だ。

static int read_key(void)

これの後半で、

#elif defined(HAVE_CONIO_H)
    if(kbhit())
        return(getch());
#endif

という箇所がある。ここを

#elif defined(HAVE_CONIO_H)
// felidlabo: this is hack and is not smart way, but useful.
#if defined(__MINGW32__)
    unsigned char ch;
    int n = filelength(0);
    if (n > 0) {
        n = read(0, &ch, 1);
        if (n == 1)
            return ch;
        return n;
    }
#endif
    if(kbhit())
        return(getch());
#endif

と、標準入力に対して低レベルなread関数での対応を含める。

あくまでhackであり賢明な方法ではないかも知れないが、ひとまずこれで中断ボタンに対応出来る。

 x264のMBAFF(インターレース)対応

H.264/AVCにはPIFFとMBAFFというインターレース方式があるが、x264が対応するのはMBAFFの方だ。詳細は後々研究するとして、この対応がffmpegにはないので修正する。

libavcodec/libx264.cを開き、

static int
X264_init(AVCodecContext *avctx)

という関数を修正する。修正場所はどこでもよいのだが、ここでは

    x4->params.analyse.inter = 0;

という行の直前に挿入する。

    // felidlabo: interlace
    x4->params.b_interlaced = (avctx->flags & CODEC_FLAG_INTERLACED_DCT) ? 1 : 0;
    x4->params.analyse.inter = 0;

この修正行は、b_interlacedが単なる二値フラグ(ゼロ・非ゼロ)なので、

    x4->params.b_interlaced = avctx->flags & CODEC_FLAG_INTERLACED_DCT);

という形式でもよいのだが、個人的な好みと後の研究のしやすさのため、上記のようにした。

こうして作成したffmpeg.exeは、x264でのエンコード(-vcodec libx264)時に、-flags ildctとすることでMBAFFを指定できる。例えば

ffmpeg.exe -i input.mpg -vcodec libx264 -flags +ildct -acodec libfaac -f mp4 out.mp4

と言った具合に。

余談

ffmpegには他にもインターレース関連のオプション(例えばilmeフラグ)があり、「どのオプションでインターレースONとすべきか」は迷うところだ。ここではMBAFFが「ジグザグスキャンを1ライン飛びにする」ように動作することから、意味的に最も近そうなildctフラグにマップした。実際にはx264内部ではilme的な動作も行っているだろうが、ffmpegが多数のコーデックに対応している以上、オプションと動作が一対一で対応しないのは仕方のないところだ。

当初は新規に-interlacedオプションを追加することも検討した(一度実装もした)のだが、修正範囲が広がるため既存のオプションを使用することにした。

最終更新時間:2008年04月14日 15時22分59秒