MV-300 メモ


ハードウェア構成

下写真1が MV-300 を撮影したもの。中央の一番大きな石が PCI 制御チップの ZR36067、右上の石が JPEG 圧縮チップの ZR36060、左上の石がアナログビデオ信号をデジタル信号へと変換するビデオデコーダの KS0127、左下の石がデジタル信号からアナログビデオ信号へと変換するビデオエンコーダの Bt866。

Picture of MV-300
写真1 MV-300

キャプチャ時の画質はビデオデコーダと圧縮チップによって決定する。ビデオ信号はビデオデコーダによってデジタル信号へと変換されてから圧縮チップによって圧縮処理を行われる。ビデオデコーダが崩れたデジタル信号しか生成してくれない場合、圧縮チップがどれだけ低損失でもキャプチャ出来る画像は崩れたデジタル信号以上のものにはならない。

また、ビデオデコーダの画質が良くても圧縮チップの能力が低い場合は動画の取り込み時に欠落フレームが多量発生したり、キャプチャした画像に圧縮ノイズが盛大にのったりしてしまう。ビデオデコーダ単体の性能を知りたい場合、無圧縮形式でのキャプチャを行えば圧縮チップを通さない画像を得る事ができる。

MV-300 の場合、ビデオデコーダに Samsung KS0127 を使用し、圧縮チップに ZR36060 を利用しているのでキャプチャされた動画の画質については問題ないのだが、特定の動画で欠落フレームが発生しやすい点や PCI 制御チップの ZR36067 の DMA 転送能力が低く、無圧縮キャプチャが不可能な点などが玉に瑕。

データの流れ

キャプチャ時

MJPEG 形式でのビデオキャプチャを行う場合、データの流れは下図1のようになる。

capture time dataflow
図1 キャプチャ時のデータの流れ

まず、KS0127 は参照用の 24.576 MHz クリスタルから必要なビデオクロック(CCIR の場合は 27 MHz, NTSC 正方ピクセルの場合は 24.54 MHz, PAL 正方ピクセルは 29.5 MHz)を生成する。全てのビデオ信号はこのクロックに同期して処理(ビデオ信号の A/D 変換も含む)される。

ビデオ入力から入った信号は KS0127 とビデオ出力へのアナログスルーへと分配される。KS0127 に入ったビデオ信号はデジタル YUV 4:2:2 形式に変換される。

KS0127 によってデジタル形式に変換されたビデオ信号は ZR36060, ZR36067 にビデオクロック、垂直同期、水平同期、ODD/EVEN 信号と共に分配される。

ZR36067 に到達したビデオ信号は PCI バスを通してグラフィックカードのオーバレイ領域へと書き込まれる。(無圧縮形式の場合はこのデータがキャプチャされ、オーバレイ領域には書き込まれない)

ZR36060 に到達したビデオ信号はフィールド毎に JPEG 圧縮され、ビデオ信号とは独立したパス(コードバス)を通って ZR36067 に送られる。

ZR36067 に到達した JPEG データは PCI バスを通して渡され、ドライバが用意した DMA バッファに書き込まれる。(この経路は 11M/sec の転送速度しか保証されていない――ただし、この制限がオーバレイ領域への書き込みにまで影響するかは不明)

再生時

MJPEG 形式の AVI ファイルをハードウェアを通して再生する場合、データの流れは下図2のようになる。

replay time dataflow
図2 再生時のデータの流れ

再生時には KS0127 は利用されない。KS0127 とその他のチップを結ぶ信号線(ビデオバス)は接続されたままだが、ここには ZR36060 が出力する信号が流れることになる。

この時に KS0127 から信号が出力されていると動画データに干渉してしまうため、再生時には KS0127 はビデオクロックの生成機能を除いて眠らされる。

まず Motion JPEG データは PCI バスを通して ZR36067 に送られる。ZR36067 は Motion JPEG データをフィールド毎に分割して ZR36067 に(データバスを通して)渡す。

ZR36060 は JPEG データをビデオ信号(YUV4:2:2 形式)にデコードして、ビデオバスに流す。このデータは Bt866 と ZR36067 に渡される。

Bt866 は渡されたビデオ信号をアナログ信号に変換してビデオ出力端子へと出力する。

ZR36067 に戻ったビデオ信号は PCI バスを通してグラフィックカードのオーバレイ領域へと書き込まれる。

ビデオ信号

画像サイズ

ビデオ信号の形式としては NTSC と PAL, SECAM の3方式があり、MV-300 のドライバは NTSC と PAL に対応している。

PAL は主にヨーロッパ圏で使用され、NTSC はアメリカや日本で使用されている。

NTSC は 858x525 の信号(ITU-R BT601 の場合)で構成され、このうち帰線消去期間(垂直・水平同期信号、カラーバースト信号、文字放送信号、放送局制御信号)などを除いた画像表示領域が 720x480 の大きさである。

しかし、実際の TV では 720x480 の情報を全て表示できるものは少なく、大抵は 686x456 程度の領域しか表示できない。

インタレース

先に NTSC は 858x525 の信号と書いたが、実際にデータを送るばあいには 858x262.5 の 59.94 fps で送られる。最初に 858x525 の画面を一行飛ばしに送信し、次に残った行を送信する。この二つのサイクルで一枚の画面が完成して 858x525, 29.97 fps となる。

テレビが開発された当時の素材技術では、29.97 fps で画面を描画していた場合、画面の下部を描画する頃には画面上部の発光が終ってしまい、ちらつきのある画像となってしまう問題を解決する事ができなかった。この問題を解決するために一度に走査する領域を半分にして画面の書き換えの周期を短くし、ちらつきを押さえようとしたのがインタレース形式。

実際に送られてくるテレビ信号(525i - 525 行インタレース形式)は次の図のような形式となっている。

525 Line Interlace Signal
図3 525 行インタレース信号

上の図のうち、黒の部分が同期信号で灰色の部分がその他の信号(カラーバースト信号や文字放送信号、放送局制御信号等)である。

黄色で囲った部分は走査線の途中で垂直同期信号が始まっているが、これが 262.5 の .5 の部分で、第1フィールドと第2フィールドを区別するために存在する。

各行の利用状況

NTSC は 525 行のうち 480 行しか有効走査線を持たないが、画像信号を含まない 45 行は全く利用されない訳ではなく、それぞれ文字放送やゴースト訂正信号などに利用される。

次の図は日本の地上波放送での走査線の利用状況を示したものである。

NTSC line usage
図4 NTSC での行の利用状況

インタレースで記述したように、まず第1フィールドが 1 〜 263 行の半分まで送られ、引き続き第2フィールドが 263 行の半分から 525 行まで送られ、525 行の1フレームが完成する。

1 〜 9 行(第1フィールド)と、263 〜 272 行(第2フィールド)は垂直同期信号として扱われる。この部分には同期パルスと等価パルス以外の信号は入らず、カラーバースト信号も入らない。

10 〜 13 行と 273 〜 276 行は現在利用されていない。(少なくとも私が調べた文献では)

14 〜 16、21 行と 277 〜 279、284 行は文字放送用の信号が存在する。21、284 行の文字放送データは有効走査線(画像領域)のすぐ上にあるため、作りこみの甘いドライバでは、この部分まで取り込んでしまいやすい。

17 〜 20 行と 280 〜 283 行は放送局制御用の信号が存在する。例えば、18、281 行にはゴースト基準(GCR)信号が存在し、GR チューナではこの信号を元にゴーストを削除している。

業務用の 486 ラインシステムでは、第1フィールドの 21 〜 263 行と第2フィールドの 283 〜 525 行を有効領域として扱うため、トップラインが第2フィールドとなり、ボトムラインが第1フィールドとなる。(ボトムファースト・偶数優先等と呼ばれる)

民生用の 480 ライン DV フォーマットでも、第1フィールドの 23 〜 262 行と第2フィールドの 285 〜 524 行を有効領域として扱うので、業務用 486 ラインシステム同様にトップラインが第2フィールドとなり、ボトムラインが第1フィールドとなる。

しかし、NTSC DVD では第1フィールドの 23 〜 262 行と第2フィールドの 286 〜 526 行を有効領域として扱うため、DV 系とは丁度 1 ラインずれて、トップラインが第1フィールドとなり、ボトムラインが第2フィールドとなる。

Motion JPEG フォーマット

Motion JPEG 自体はシンプルなフォーマット。動画を構成するすべてのフレームが JPEG 圧縮されているだけ。

ただし、NTSC のようなインタレース画像の場合、フレーム毎圧縮では次の問題が発生する。

  1. 奇数フィールド・偶数フィールド両方がそろうまで圧縮開始できない
  2. インタレース縞の為に圧縮率が悪くなる

特に 1. の問題については、奇数フィールドを格納しておくためのバッファが余計に必要になり、チップのコスト増加につながってしまう。

そこで、一般的な MJPEG キャプチャカードではフィールド毎に JPEG 圧縮を行い、2つの JPEG データで1フレームを構成するようにしている(この為にキャプチャ時にフィールドオーダーを設定する必要が出てくる)

サンプル AVI ファイル は linux 上で 720x496 Even First の設定で取り込んだ1フレームだけを持つ AVI ファイルだが、このファイルからバイナリエディタを利用して FFD8 〜 FFD9 までを切り出してみると次の二つの JPEG イメージを取り出すことができる。

A Even First A Field
B Even First B Field
図5 インタレース形式 MJPEG AVI

I2C バス

I2C バスはデータラインとクロックラインの2本の信号線によって構成されるシンプルなシリアルバス。

Philips が規格の開発元(特許でがっちりと権利を握ってる)で、ビデオデコーダチップやチューナユニット等の制御用バスとしてデファクトスタンダードになっている。(ビデオキャプチャボードをいじろうとしたら Bt848/878 系の 1 チップ集積型以外では避けて通れない。Bt848 系でもチューナユニットまで制御する場合は I2C バスを避けられない)

I2C バスには最大で 16 個までのユニットをカスケード接続することができ、接続されたデバイスにはスレーブとマスターが存在する。

マスターデバイス(PC 用ビデオキャプチャボードでは、大抵 PCI/AGP 制御機能をもったチップ)が I2C バスのクロックラインの制御を独占する。データラインの制御は、スレーブデバイスへのデータ書き込み時にはマスターに、スレーブデバイスからのデータ読み出し時にはスレーブに握られる。

マスターデバイスが生成するクロックパルス(当然流れるのはクロックライン)にあわせてデータラインの電圧を(そのときデータラインの制御を握っているデバイスが)変化させ、通信を行う。

I2C バスを制御する場合、大抵はクロックパルスの生成からデータの組立(bit <-> byte 変換)まで全ての面倒を CPU がソフトウェアで面倒を見なければいけない。

ZR36060

圧縮処理概略

ZR36060 によるビデオ信号の圧縮はほぼ次のような手順によって行われる。

  1. START シグナルがホスト(MV-300 では ZR36067)から送られる。
  2. 垂直同期信号を待つ。
  3. TOP フィールドか判定する(TOP フィールドならば圧縮開始)
  4. アクティブビデオ領域(858x262.5 の内から指定された 704x240)を待つ。
  5. 8 行分のデータをため、8x8 のブロックに分けて圧縮ユニットに送る。
  6. 8x8 のブロック毎に圧縮を行い、順次ホストにデータを転送する。
  7. アクティブビデオ領域の圧縮が終了したら垂直同期信号待ちに戻る。(以後、フィールド判定は行わない)

ビデオ入力

ビデオ入力信号は画像信号と制御信号に分けられる。このうち画像信号の入力フォーマットとしては 16 ビットと 8 ビットの YUV 4:2:2 形式(ITU-R BT601 および ITU-R BT656 互換)を受け付け、制御信号としては 垂直同期・水平同期・EVEN/ODD を受け付ける。

制御信号のうち垂直同期および水平同期は必須だが、ODD/EVEN については利用せずに水平同期と垂直同期から ZR36060 内部で検出することもできる。

これは Buz で利用されている Philips の SAA7111 のように ODD/EVEN 信号の出力能力を持たないビデオデコーダと組み合せて利用する事を考えていたためと思われる。(実際 Linux 用の Buz ドライバでは外部の ODD/EVEN 信号を利用しない設定になっていた)

ビットレート制御

ZR36060 のビットレート制御方法としては自動2パスモードと固定品質モード、可変品質モードの3つがある。

自動2パスモードは動画のリアルタイム圧縮には使用すべきものではなく、静止画を圧縮する場合に使用するようにと推奨されている。

自動2パスモードでは最初のパスで量子化テーブルとハフマンテーブルを最適化し、二回目のパスで実際に JPEG 圧縮を行うので指定されたビットレートに誤差 1% 以内の厳密さで収める事ができるが、この為には同じ画像を二回送って圧縮を行う必要がある。

固定品質モードでは DCT で使用する量子化テーブルの細分化率を固定にして JPEG 圧縮を行う。(何を言ってるのか判らない? 心配する事はない、私も判らないのだから)

可変品質モードでは DCT で使用する量子化テーブルの細分化率を圧縮毎に再設定することで、指定されたビットレートの範囲内で、DCT による損失を出来る限り減らそうとする。Linux 用の Buz ドライバで採用しているのはこの方式。(現在私の所で動いている Linux 用 MV-300 ドライバもこの方式を使用)

エラー

ZR36060 での圧縮に際してのエラーとしては、1−アクティブビデオ領域の圧縮が終わる前に垂直同期信号が送られた場合−と、2−アクティブビデオ領域の全てのデータについて JPEG 圧縮は無事に終了したが、最終的に得られた JPEG データのサイズが指定されたビットレートを大きく超えてしまった場合−の2つがある。

1の場合では、フィールドを構成する JPEG データのうちの一部(前半部分)しかホストには渡らず、垂直同期信号を捕まえた時点で ZR36060 はホストにエラーを通知して JPEG 圧縮を停止してしまう。

2の場合では、ZR36060 はフィールドの JPEG 圧縮を完了し、全てのデータをホストに転送するがホストからドライバが割り当てた DMA バッファに JPEG データを転送する際にバッファサイズを超えてしまい、エラーとなる。(余裕のある DMA バッファをあらかじめ割り当てるようにする等のドライバの設計によっては、これをエラーとせずに済む)

1のエラーは MV-300 の VfW ドライバの Advanced 設定で Field Order に ODD First を指定し、Video Shifting に Y - axis: 10 を指定してキャプチャを実行することで確認できる。

この場合、1フレームもキャプチャ出来ずに「警告:フレームはキャプチャされていません。垂直同期割りこみが設定され、使用可能になっているか確認してください」という VfW のエラーメッセージが表示されることになる。

ここまで読んだ人の中には「つまり、ZR36060 を利用している限り(NTSC では有効走査線の直後に垂直同期信号が来るため)480 本全てをキャプチャすることは不可能なのか」と考える人も居るかもしれないが、その心配はない。

垂直同期信号は走査線9本分の長さを持つため、ZR36060 のレジスタで垂直同期パルスの最後(Tail Edge)を同期信号として認識する設定(FIVedge = 1)にしておけば最後の 8 本の有効走査線を JPEG 圧縮する猶予(走査線9本分の時間)が得られる。

このため、FIVedge が適切に設定されている Even First では有効走査線全てを取り込む事が可能になる。

これは私見だが、ODD First 時に 480 本の有効走査線全てをキャプチャできない障害については、レジスタに値を代入しているコードを探してそこを書きかえるだけで副作用無く解決できるのに Ver. 1.3 まで進んでも解決されていないのは何故か非常に疑問だったりする。

GPIO (General Purpose Input/Output) ピン

MV-300 で使用されている ZR36060 には GPIO ピンが 0 〜 7 番まで 8 本用意されている。

このピンは General Purpose(汎用)の文字で表されているとおり、ソフトウェアで任意にピンの状況を変更する事ができ、他のチップとの低水準の(ピンレベルでの)通信に使用される。

当然ボードによってこのピンの利用状況は違うので、Buz 用のドライバのソースから MV-300 用のドライバをでっち上げる場合には、このピンが何処(どの石のどのピン)に接続されているかを調べなければならない。

もちろん Zoran が作成し、その設計を PDF で配布している H33 というリファレンスボード(ビデオデコーダ&エンコーダには CONEXANT の Bt819 と Bt856 を使用)の設計で GPIO ピンの結線状況についても指定されているので ZR36067 との接続に関しては Buz も MV-300 も同じだと期待できるのだが、ビデオデコーダとビデオエンコーダに関しては使用している石が違う(Buz では Philips の SAA7111 と SAA7158、MV-300 では Samsung の KS0127 と CONEXANT の Bt866)ためボードによって接続状況が異なる。

以上が前置き、次に示すのが個人的に調べた範囲内での MV-300 の GPIO ピン接続状況。(2000, 1/4 訂正)

もちろん、上記情報はいい加減な計測機器(箱型 9V 乾電池と豆電球)と Linux 用ドライバの反応で調べた情報なので間違っている可能性は大。

それでも WDM ドライバを独自に書いてみたいとかいう奇特な人が居るなら、こう言う情報も無いよりはあった方が良いだろうという事で記述しておく。

HAV (Horizontal Active Video) 領域

KS0127 には HAV(Horizontal Active Video - 水平有効画像)領域というものを設定するレジスタがある。このようなレジスタでは本来、デフォルトで適切な値が設定されており、特殊な事をしたい場合にのみレジスタの値を変更するのが普通だと思うのだが、恐ろしい事に KS0127 ではデフォルトの HAV 領域が左にずれていて、情報があるはずの画面右側 5 〜 10 ピクセルが UNUSED YUV で設定した値で塗りつぶされてしまう。

実際にどの程度の情報が失われているかというと、それは下のサンプルで判ると思う。

ks0127 Horizontal Active Video
サンプル1 KS0127 の HAV 領域

1は Windows 用標準ドライバ(Ver. 1.3)を利用して取りこんだデータで、2〜4は Linux 用ドライバで KS0127 のレジスタに入れる値を変更しながら取りこんだデータである。

まず、標準ドライバは 704x480 であり、Linux 用ドライバは 720x480 である為、多少取りこんだ画像の領域には違いが出ている。しかし縦にならべた4つの画像は同一フレーム内の同一領域となっている。

1と2を比較すると、同じ場所から黒の領域が始まっている事が判る。2の画像は HAV および UNUSED YUV の設定に関して KS0127 のデフォルトの値をそのまま使用して取りこんだ画像である。

この段階では黒の部分が HAV から外れた部分か、それとも単に画像信号が無い部分かが判定できないため、UNUSED YUV(KS0127 の 0x35 〜 0x37)に 0xff8080 を入れて取りこんでみた画像が3である。黒が白に変化し、UNUSED YUV に設定した値で塗りつぶされていることが確認できる。

そこで、HAV 領域をデフォルトの状態から 10 ピクセル右にずらして取りこんだ画像が4である。UNUSED YUV に設定した白はこの画像には(左側にも)含まれていなかった。また、今まで塗りつぶされていた部分にも(多少ではあるが)画像データが存在した事が確認できる。

HAV 領域をずらす場合は 0x05 〜 0x0c のレジスタに、デフォルト値からのずれを書きこめば良い。具体的には、右に 10 ピクセルずらす場合、0x05 と 0x06 の二つのレジスタに 0x14 = 20 を書きこむ事で実現できる。

この程度の欠落ならば(Marvel G400 TV の様に縦 8 ピクセル 横 8 ピクセル丸々だと問題だけど)大目に見ても良いのではないかという人もいるかと思うが、単にレジスタに書きこむ値を変更するだけで副作用無く解決できるのだからさっさと直して欲しいものだと思う。(というか、何故デバッグ段階で修正されなかったのかが不思議でならない)


[||→]
(C) 1999 MOGI, Kazuhiro(茂木 和洋)
kazhiro@a2.ocv.ne.jp