index

2006年 12月
          1 2 3
  4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
  25 26 27 28 29 30 31
2007年 1月
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31        
2007年 2月
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28        

アレ

H.264 動画 を AVI コンテナに入れた際の問題点とか   ▽20070103a #コンピュータ #動画圧縮

詳しくはココ

……後でぜったい内容忘れるから書いてあることをメモっておこう.


そもそもの問題点

VFW インタフェースと AVI コンテナは基本的に「Bフレーム」を扱えない. 古臭いテクノロジなので「Bフレーム」みたいな最新テクノロジには対応できないのだ.

「Bフレーム」を使いたかったら,できることといったらふたつくらい.

  1. んな古いテクノロジはさっさと捨てて,.MP4 を DirectShow 経由で使うとかする.
  2. 何とかして対応できるためにハックと開発をする.

ふたつのハックの方法

ハックとしては 2種類ありうる.

  1. エンコーダがうまいこと処理する(XviD で packed bitstream を使った場合,あと DivX5 も)
  2. デコーダで頑張る(packed bitstream を使ってない時の XviD)

基本的なトコ

まず,vfw/avi で Bフレームがどういう風に扱われてるのか理解しとこう.

通常,コンテナには「I P B B」の順でフレームが格納され,表示の際には「I B B P」の順で出力される.

vfw/avi は「1フレーム読んで 1フレーム出す(1 in, 1 out)」という仕組みになっていて, 1フレーム読み込んだら必ず 1フレーム出力しなきゃならない (エンコードもデコードも両方そう). Bフレームというのは前後ふたつのフレームの情報から間のひとつのフレームを作り出す技術なので, 「2 in, 1 out」という風に動けない vfw/avi ではうまくいかない.

今時の普通のデコーダの挙動を示す.

  1. まず Iフレームを普通に読んで出力する.
  2. 次に Bフレームを出力したいところだが,それには I/P のフレームが必要だ. I は既にデコード済みなので P までのフレームを読んできて Bフレームをデコードし出力. つまり「3 in, 1 out」となる.
  3. 同じように次の Bフレームを出力.
  4. 最後に Pフレームを出力する.

デコード時のハック

まず,やりかたその1.

avi/vfw の「1 in, 1 out」の法則があるので,まずはエンコーダ側で対応しとかなきゃならない. packed bitstream とか呼ばれる手法がこれだ. すなわち,最初の Bフレームが Pフレームと同じ 1フレームに入って, 「I P B B」が「I P+B B N」になるのだ. N というのはフレーム番号だけ持ってる空フレームだ.

その上で,デコーダの挙動はこうなる.

  1. まず Iフレームをデコード
  2. 次に Bフレームをデコード.これは I と P を必要とするが, P は B と一緒に入ってくるのでデコードできる. AVI的には両方で 1フレーム扱いとなっている.
  3. I と P は既に読み込んでるので 2番目の B もデコードできる
  4. 最後に P を出力.

このハックは,1 フレームに 2フレーム分の情報を送ることで, avi/vfw の「1 in, 1 out」の法則をうまく回避できる. が,普通の MPEG4 標準に従って書かれたデコーダは, この packed bitsream を扱うことができない.

やりかたその2.

コンテナには正しく「I P B B」の順にフレームが格納され,デコーダ側でこれを何とかする.

  1. デコーダはまず Iフレームを読み込むが,ここでは空フレームだけを出力する.
  2. 次に Pフレームが入力されるが,ここで最初の Iフレームを出力する. 「1 in, 1 out」の法則は,初回の空フレームも込みで維持されている.
  3. 次に Bフレームが入力されると,ここで I + B + P が揃うので,Bフレームをデコードできる.
  4. 2番目の Bフレームも同様にデコードできる.
  5. 最後に Pフレームを出力.

このハックだと,空フレームを作ることで「1 in, 1 out」のルールに対応できるが, デコーダは入力されたフレームと違うフレームを出力していることになる. が,packed bitsream と違って,MPEG4 標準ではこれを使用するよう定義している.

エンコード時のハック

というわけで,avi/vfw で Bフレームを扱うためのデコード時のハックは 2通りある. さらにエンコード時にもハックがある.

Bフレームをエンコードするには普通は以下の手順が必要となる.

  1. 最初のフレームを Iフレームにエンコードする.
  2. 2番目の,Bフレームとなるべきフレームが入力されるが, Pフレームが来るまでは Bフレームをエンコードすることができない.
  3. 3番目のフレームも同じようにエンコードできない.
  4. 4番目のフレームを Pフレームとしてエンコードする.
  5. I と P が揃ったので,Bフレームをエンコードできる.
  6. 同じように 2番目の Bフレームをエンコードできる.

もちろん,avi/vfw の「1 in, 1 out」の法則により, ステップ 2 と 3 の「何も出力しない」は不可能だ. そこで,エンコーダは「ディレイフレーム(delay frame)」と呼ばれる空フレーム(1バイトの 0x7F のみから成る)を出力する. このディレイフレームは,単に「1 in, 1 out」に従うためだけに出力されるもので, これが MPEG4 標準への準拠を不可能にする.

そこでどんな手段があるだろうか. Virtualdub(mod) は,エンコード中に得たディレイフレームをすべて捨てるという対処をしている. これにより,出力された AVI ファイルにはディレイフレームがなくなる. が,VFW が必ずしもこういうディレイフレームを捨てるフロントエンドで使われるとは限らない.

……AVI とか VFW,これマジどうよw


……けっきょく全部翻訳してしまったw

index