2004/07/28:bond@Doom9
Bフレームがどのように .aviに収められ、vfwでのエンコード/デコード過程で使われるかについて、一部の人たちには説明して来たが、一度簡単な説明を書いて公開しておいた 方が良いと思った。
内容は以下の通り。
第一の問題
"video for windows" (VFW) コデック・インターフェイス (virtualdub(mod)が使う)
とそのコンテナ (AVI) は Bフレームを扱えない、それどころか、このタイプのフレームの存在すら認識出来ないのだ!
Bフレームのようなモダンテクノロジーを扱えないという事は、これらは時代遅れのテクノロジーと言う事ができる。
Bフレームを使いたければ可能性は二つある:
1)Bフレームを扱えないような 時代遅れの技術を捨てる(そして DirectShow や .MP4 のような新しいものを使う)。
2)時代遅れの技術を開発と裏技でなんとかする。
2種類の裏技
現在、 2) のBフレームs をavi と vfwで扱う方法は2種類ある。
a)エンコーダ側で扱う(xvid と divx5がデフォルトで使うpacked bitstream)
b)デコーダ側で扱う(xvidが packed bitstream をオフにした時に使う)
基本
aviとvfwでBフレームを使う裏技を理解するには、まず次の理解が必要だ。
通常、コンテナの中のフレームは次のように配置されている:
I P B B
ディスプレイは次の順番だ:
I B B P
VFW と AVI が使うのは " 1 フレーム - イン・1 フレーム - アウト " 方式
(それがこのテクノロジーの基礎)、これは
1フレームのインプットがある度に、1フレーム出力しなければならない事を意味する(エンコードでもデコードでも)。
これはBフレームと互換性がない。Bフレーム は 前後の
I/Pフレームとセットで使うべく作られているからだ。しかし vfw/avi は
"2フレーム - イン・1フレーム - アウト" といった事を許さない(モダンな directshow や .mp4では可能)。
通常、つまりよりモダンなテクノロジーを使った場合、デコーダはデコード中に次のような事を行う:
デコードの裏技
では裏技に行こう:
裏技A)AVI and VFW は" 1フレーム-イン・1フレーム-アウト " しかできないので、以下の処理をエンコーダで行う方法( packed bitstream と呼ばれる):
最初のBフレームは1フレームとしてPフレームとパックされる。
I P B B
これは次のようになる。
I PB B N
(*訳注:半角スペースに
注意*)
(N フレームナンバー維持の為の、符号化されていない代替フレーム)
次に、デコーダは以下の処理をする:
まとめると、avi/vfwは" 1 フレーム-イン・1 フレーム-アウト "
方式しか使えないので、2フレームをパックして、これは1フレームですよと偽って処理に流し込むというものだ。
開発者の中には(ffmpegのミヒャエル=ネーデルマイヤーのように)2フレームを1フレームにパックするとMPEG-4規格との互換性が無くなると
す
る人もいます。また、MPEG-4規格を遵守する通常のMPEG-4デコーダはpacked bitstreamなんか知らないのでデコードもできません(*MEncoder -xvidencopts
の(no)closed_gop, divx5bvopあたりがこの "packed B-frame" 相当すると思われる*)。
裏技B) 2番目の案はストリームはaviの中に正しく配置(I P B B)しておいて、デコーダ側に裏技を用意するというものだ。
この裏技は、avi/vfwは "1フレーム-イン・1フレーム-アウト" 方式しか使えないので、ラグを作って、デコーダがこの方式に従いつつも、取得したフレームを吐き出さないようにするもの。packed bitstreamとの違いは、ストリームがMPEG-4規格準拠の方式で記述される事(*そういえばXvid+mp3.avi再生時、冒頭の一瞬は、 素材と異なる真っ白のフレームだった記憶が*)。
エンコードの裏技
ここまでが、デコード側で時代遅れのvfw/aviでB-フレームを使うための2つの裏技。
さらに、エンコード側にも裏技がある(もちろん、ここでも"1フレーム-イン・1フレーム-アウト " 方式に従う必要がある)。
B-フレームをエンコードする為には、エンコーダに(*
エンコード・バッファから必要なフレームが吐き出されてしまう前に*)2フレームを送り込ま無ければならない。この為に、エン
コーダは以下の作業をする:
さてvfw/aviの" 1フレーム-イン・1フレーム-アウト " 方式で、どうやって2) と 3) を行うか?
ここでいわゆるディレイ・フレーム (1-byte 0x7f frames)というものを書き出す。VFWはなにか書き出せばそれで良いのでディレイ・フレームでも構わない訳だ!しかし、それは入力ソースの中に存在 するものではないし、しかも、MPEG-4規格との互換 性は破壊される!
ではどうしよう?
AVI と VFW がトラブルを起こした時、我々がいつもしている事は?『裏技を探す』だ。:
=> virtualdub(mod)にこうした"ディレイ・フレーム"をドロップさせればいい。これで最終的な出力ストリームの中には"ディレイ・フレーム" はなくなる。しかし、vfwコデックを使う他のツールでは"ディレイ・フレーム"が残ってしまう可能性があるので注意してくれ。
AVI と VFW って、いいもんだろ?