!!!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オプションを追加することも検討した(一度実装もした)のだが、修正範囲が広がるため既存のオプションを使用することにした。