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秒