以下、Vista で出力するファイルの問題の詳細と修復手順を解説します。
データ内容
Video for Windows API で出力するAVI ファイルファイルは、以下のような構造になっています。
RIFF ヘッダ
LIST チャンク「hdrl」 (データフォーマット情報など) 200〜300バイト
avih チャンク
LIST チャンク「strl」(映像フォーマット情報)
LIST チャンク「strl」(音声フォーマット情報)※音声付の場合のみ
JUNK チャンク 1700〜1800バイト
LIST チャンク「movi」 (データ本体)
LIST チャンク「idx1」 (頭出し用インデックス)
この「JUNK」チャンクは、データとしては意味のない穴埋め用で、それにより「movi」チャンクのデータ本体は、2048バイト目から始まるようになっています。
Vistaで出力した場合、この「JUNK」チャンクのサイズが0バイトになっており、その直後から「movi」チャンクが始まっています。
ところが、実際のデータは、2048 バイト目から始まっていますので、
データ本体の先頭にゴミデータが埋まっていることになります。
修復方法
- ・ヘッダの修正
-
「ゴミデータ」がJUNKチャンクの所属になるように、
- JUNKチャンクのサイズを、ゴミデータのサイズに修正する
- 実データの直前に、新たなmoviチャンクを書き込む
ようにします。
- ・インデックスの修正
-
「idx1」チャンク内の頭出しデータは、moviチャンクのデータ先頭からのバイト位置が記録されています(Vista の場合、ゴミデータを含めた位置に)
そこで、上記ヘッダの修正に合わせ、逆にインデックスの位置を減らします。
実例1. Vistaで作成したデータ:
000000: 52 49 46 46 B4 0B 02 00 41 56 49 20 4C 49 53 54|RIFF AVI LIST|←hdrlチャンク
000010: C0 00 00 00 68 64 72 6C 61 76 69 68 38 00 00 00| hdrlavih |
000020: 35 82 00 00 C0 18 01 00 00 00 00 00 10 08 00 00| |
000030: 14 00 00 00 00 00 00 00 01 00 00 00 BE 9D 00 00| |
000040: 80 02 00 00 E0 01 00 00 00 00 00 00 00 00 00 00| |
000050: 00 00 00 00 00 00 00 00 4C 49 53 54 74 00 00 00| LIST |
000060: 73 74 72 6C 73 74 72 68 38 00 00 00 76 69 64 73|strlstrh vids|
000070: 6D 73 76 63 00 00 00 00 00 00 00 00 00 00 00 00|msvc |
000080: 01 00 00 00 1E 00 00 00 00 00 00 00 14 00 00 00| |
000090: BE 9D 00 00 00 00 00 00 00 00 00 00 00 00 00 00| |
0000A0: 80 02 E0 01 73 74 72 66 28 00 00 00 28 00 00 00| strf |
0000B0: 80 02 00 00 E0 01 00 00 01 00 10 00 43 52 41 4D| CRAM|
0000C0: 02 DC 05 00 00 00 00 00 00 00 00 00 00 00 00 00| |
0000D0: 00 00 00 00 4A 55 4E 4B 00 00 00 00 4C 49 53 54| JUNK LIST|←JUNKチャンク サイズは0
0000E0: 90 09 02 00 6D 6F 76 69 00 00 00 00 00 00 00 00| movi |←moviチャンク
0000F0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00| |
000100: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00| |
(略) ここは movi チャンクのデータとなってるが、先頭にゴミが詰まってる 0x0000E8〜0x0007FFの1816バイト。
0007E0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00| |
0007F0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00| |
000800: 30 30 64 62 BE 9D 00 00 00 80 00 80 00 80 00 80|00db |←1コマ目のデータの始まり moviチャンクの先頭から数えると、0x00800 - 0x0x00e4 = 1820バイト目
(略)
020A70: 2A 85 00 00 69 64 78 31 40 01 00 00 30 30 64 62| idx1 00db|←idxチャンク
020A80: 10 00 00 00 1C 07 00 00 BE 9D 00 00 30 30 64 63| 00dc|←1コマ目の開始位置 0x071c=1820バイト(ゴミの1816バイト分多い)
020A90: 00 00 00 00 E2 A4 00 00 FC 0B 00 00 30 30 64 63| 00dc|←2こまめの開始位置 0xa4e2=42210バイト(ゴミの1816バイト分多い)
(略)
実例2. 正しいデータ:
000000: 52 49 46 46 B4 0B 02 00 41 56 49 20 4C 49 53 54|RIFF AVI LIST|←hdrlチャンク
000010: C0 00 00 00 68 64 72 6C 61 76 69 68 38 00 00 00| hdrlavih |
000020: 35 82 00 00 C0 18 01 00 00 00 00 00 10 08 00 00| |
000030: 14 00 00 00 00 00 00 00 01 00 00 00 BE 9D 00 00| |
000040: 80 02 00 00 E0 01 00 00 00 00 00 00 00 00 00 00| |
000050: 00 00 00 00 00 00 00 00 4C 49 53 54 74 00 00 00| LIST |
000060: 73 74 72 6C 73 74 72 68 38 00 00 00 76 69 64 73|strlstrh vids|
000070: 6D 73 76 63 00 00 00 00 00 00 00 00 00 00 00 00|msvc |
000080: 01 00 00 00 1E 00 00 00 00 00 00 00 14 00 00 00| |
000090: BE 9D 00 00 00 00 00 00 00 00 00 00 00 00 00 00| |
0000A0: 80 02 E0 01 73 74 72 66 28 00 00 00 28 00 00 00| strf |
0000B0: 80 02 00 00 E0 01 00 00 01 00 10 00 43 52 41 4D| CRAM|
0000C0: 02 DC 05 00 00 00 00 00 00 00 00 00 00 00 00 00| |
0000D0: 00 00 00 00 4A 55 4E 4B 18 07 00 00 00 00 00 00| JUNK |←JUNKチャンク サイズは 0x0718=1816バイト
0000E0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00| |
0000F0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00| |
000100: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00| |
(略) ここは JUNKチャンクのデータ
0007E0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00| |
0007F0: 00 00 00 00 4C 49 53 54 78 02 02 00 6D 6F 76 69| LIST movi|←moviチャンク
000800: 30 30 64 62 BE 9D 00 00 00 80 00 80 00 80 00 80|00db |←1コマ目のデータの始まり moviチャンクの先頭から数えると、0x00800 - 0x0x07fc = 4バイト目
(略)
020A70: 2A 85 00 00 69 64 78 31 40 01 00 00 30 30 64 62| idx1 00db|←idxチャンク
020A80: 10 00 00 00 04 00 00 00 BE 9D 00 00 30 30 64 63| 00dc|←1コマ目の開始位置 0x0004=4バイト
020A90: 00 00 00 00 CA 9D 00 00 FC 0B 00 00 30 30 64 63| 00dc|←2コマ目の開始位置 0x9dca=40394バイト
(略)