最近のブログ

RDF(RSS 1.0) URL RSS URL ATOM URL

2010年01月30日

日常の備忘録 :: Visual Studio 2008 と Windows 98

気付いてなかったんだけど、Visual Studio 2008 でビルドすると Windows 98 では動かない実行ファイル/DLLが出来る。
何でかなぁと思った調べていたら、対応が削除された様子。
互換性に影響する変更点
実行ファイルに動作する Windows のバージョンが埋め込まれているようなんだけど、この値が変更されて動作しなくなったようだ。
ただ、その値を書き換えればうまくいくかというと、それでもだめなよう。
Visual C++ 2008 で Win98/Me/NT4 対応バイナリを作りたい このページにその辺りのことが書かれている。
リンカのオプションで /SUBSYSTEM:WINDOWS,4.0 とかしてもエラーになってリンクできない。
Windows 98 な対応させたかったら Visual Studio 2005 使わないとダメなよう。

Windows98とVisualStudio2008 ここでも同じことが書かれている。
と言うか、気付くの遅すぎか。

今公開している吉里吉里2についている krmovie.dll ってどっちでビルドしたっけ?
まあ、9X 系のサポートは吉里吉里2でも削除されてるのでいいと言えばいいけど。
1年半くらい誰にも何も言われてないから 2005 でビルドしてたのかな。
次ビルドする時は、気をつけておこう。
ただ、Windows SDK の対応表を見ると、Windows 7 で動く 6.1.7600.16385 では、Visual Studio 2005 の対応が、非推奨になっているので、また面倒。
krmovie.dll のビルドに必要な DirectShow は、Windows SDK に移っているので、Windows 7 で新しく環境作ってビルドしようとしたら、はまるかもしれない。

Windows 98 は、主要コンポーネントだけ見ると DirectX 9、Windows Media Player 9、IE6 とまだまだ使えそうなんだけど、開発する側の環境が厳しくなってきているか。
今リリースしているプラグインは、Visual Studio 2008 でビルドしているので、Windows 98 では動かないものがほとんどなんだけど。気付いてなかったから。
最近 Windows 98マシンを入手したので、その辺りの確認をしたから気付いただけと言う状態。
Visual Studio 2008 にして、Windows 9x系 を切るのなら UNICODE 前提でやってしまっていいから、その辺りは楽になる。

2010/01/31 追記
かなり強引な方法でDLLのインポートを横取りする(未参照を防ぐ)
Windows 95 で動くプログラムを作る (VS2008編)
ここに無理矢理動かす方法がのっていたのでリンク。
試してみると、バージョン書き換えすれば読み込みは少し進むけど、フリーズした。
リンク先のアセンブリコード追加すると、また DLL がロードできなくなった。
アセンブラのオプションとかがまずいのかな。
まあ、そこまで VS2008 でなんとかしたいわけではないからいいか。

投稿者 Takenori : 18:41 | コメント (0) | トラックバック (0)

吉里吉里 その他の開発日誌 :: 炎エフェクトプラグインサンプル動画

WMV 出力プラグインを作ったと言うことで、上げてみる。
WMV 出力プラグインは、今のところ音未対応。
吉里吉里のレイヤーを順に渡していくことで動画が出来る。

投稿者 Takenori : 18:36 | コメント (0) | トラックバック (0)

2009年12月11日

Misc. :: まるまるC MAGAZINE Complete

まるまるC MAGAZINE Complete を買った。
C MAGAZINE には、役立つ記事が多かったので、ずっと欲しかったんだけど 55,000円 と高いのが難点。
全部雑誌で購入していたらもっと高いんだけど。

内容は、DVD 1枚で 容量約 7GB 弱、ファイル数 約 8000。
HDD へのコピーは4時間かかった。
namazu のインデックス作成には 2時間かかった。
さすがにファイル数が多いので時間がかかった。

これでずっとおいていた C MAGAZINE を捨てられる。
後、PC で必要な時に読めるのもいい。
インデックスも作ったので全文検索で必要な記事を見つけやすい。
ただ、購入してから2週間経つんだけど、まだ最初に少し読んだだけで、それ以来見ていない。
まあ、何か新しいものを作り始めた時などに参照するだろう。

投稿者 Takenori : 22:00 | コメント (0) | トラックバック (0)

2009年03月21日

吉里吉里 ムービー拡張日誌2 :: アルファチャンネル付き動画公開

アルファチャンネル付き動画 を公開しました。
エンコーダー、プラグイン、サンプル、マニュアルが入っています。

サンプルの動画が大きいので、少しサイズが大きくなってます。
もう少しサンプルの動画を増やせたら、サンプル動画のみを分離して、別途配布という形にする予定です。

投稿者 Takenori : 18:29 | コメント (0) | トラックバック (0)

2008年07月22日

吉里吉里 ムービー拡張日誌2 :: α動画 SSE2対応など

色変換と IDCT の SSE2 版を作った。
Core2Duo で MMX に比べると 18% 程度速くなった。

IDCT は LLM を使っているけど、 ANN も試してみた。
2%ぐらい速くなるが、誤差が大きいせいか汚い。
補間があればもう少しましだろうか?
ANN は使わないことにする。

ブロックが単色かどうかの判定は、AC 係数すべてを調べる必要があると思っていたが、よく考えればハフマン復号化の時にわかることに気付いた。
JPEG では、係数行列の残りが全て 0 の時終端記号が入る。
つまり、デコーダ内部の AC 係数の書き込み終端位置を覚えておけば、AC係数の要素数がわかる。
AC 係数がなくて DC 係数のみの場合、DC 係数値を 8 で割った値が色になる。
これを利用して輝度と色差の両方が DC 係数のみの場合、1度だけ色変換の計算を行って、後は全てその色をコピーすればよい。
1ブロックは 64 要素なので、単色のブロックがある場合だいぶ高速化されるはず。
単色のブロックは完全に透明なブロック以外にもところどころある様子。
単色判定を入れて立ち絵の動画で試したところ 2% 程度速くなった。
期待したほど速くならなかったが、IDCT や 色変換部分の処理が大幅に削減されるので、SSE2 が使えなくて MMX になるような環境であれば、もう少し効果があるはず。

他に考えられる高速化には、ジグザグ行列を転置済みのものにしておくというのがある。
転置済みにしておけば、IDCT 時に1回転置が減る。
SSE2 版で試したところほとんど速度差がない。
MMX 版であればもう少し効果があるかもしれないが、かなり書き換える必要があるので、転置はいいか。

非 SIMD 版も計ろうと動かしたらバグってた。
いつの間に。
まず使うことはないだろうけど、一応修正。
MMX と SSE では、IDCT 内でレベルシフトしていたけど、非 SIMD 版はそれをしていなかったのが原因で色がおかしくなってた様子。
速度的には、SSE2 版より2倍遅い。
非 SIMD 版はどちらかというと動作確認用みたいなものなので、それほど高速化などは考慮していない。

デコーダー側はこれで一通り完成かな。
後は高速化の残骸などを消してソースコードを整理してテスト。


エンコーダーはGUI版を作った。
1個1個エンコードする時はGUI版の方が楽。
エンコードのコア部分は DLL にしているので、コマンドライン版もその DLL を使うように書き換える予定。
でも、こまごまデータもらいながら作るのなら、コマンドライン版はあんまりいらないかも。

投稿者 Takenori : 16:34 | コメント (0) | トラックバック (0)

2008年06月22日

吉里吉里 ムービー拡張日誌2 :: 完全透明ブロックの劣化を回避する

エフェクト用の動画は圧縮率を上げても ( クオリティーを低くしても ) 気付きにくいということで、60% にして試してみたら、うっすらと枠のようなものが見えた。
どうも、完全に透明な部分が劣化して、透明ではなくなってしまっているようだ。
初め αチャンネルを非可逆圧縮にして圧縮率を上げたのが原因と考えて、αチャンネルと色を独立してクオリティーを指定できるようにしようと考えたが、よく考えるとそうではない気がした。
吉里吉里側の演算負荷を下げるために、αチャンネルつき動画は画像を AddAlpha 形式で保持しているが、この形式の場合色に誤差があった場合でも、透明部分が透明でなくなってしまうはず。
という事で、あんまりクオリティーを下げるのはまずいかと思ったが、よく考えれば完全に透明なブロックが劣化しないようにすればいい。
一見、非可逆圧縮で劣化させないようにすることは矛盾しているようだが、完全に透明なブロックのみに限定するのであれば、これは可能だと考えられる。

あるブロックを DCT 変換すると、最初の係数にはそのブロックの平均色が入る。
この係数は特別扱いし、DC (直流) 係数 と呼ぶ。
もし、ブロックが1色のみの場合は、その色を表した係数がこの DC 係数に入る ( と思っているけど、間違ってるかも ) 。
JPEG 圧縮で劣化する主な原因は、以前書いたと思うけど、この DCT 変換後の係数行列を量子化テーブルの値で割るためで、そこで小数点以下の値が失われてしまう。
逆に言えば、小数点以下の値が出ないような値で割れば、劣化しないことになる。
つまり、ブロックが完全に透明な色のみだった場合、その時の DC 係数値の約数を量子化テーブルの内の DC 係数の箇所に持ってくれば、完全に透明な色のみのブロックは劣化することなく復元できることになる。
という事で、量子化テーブルの最初の値は、完全に透明なブロックを DCT 変換した時の各要素の値の約数になるようにしようと思う。
クオリティーを指定して計算された量子化テーブルの最初の値を、その値より小さな約数値になるようにすることになるので、少し圧縮率は低下すると思うが、まあうっすらと枠が見えてしまうのは避けたいので仕方ない。

実際に試してみると、800x600 149フレーム のパーティクルの動画で 2.86MB が 2.96MB になったが、枠のようなものは見えなくなった。
この程度の圧縮率の低下であればいいかな。
まあ、エンコーダのオプションとして、有効/無効選べるようにしてもいいし。

2008/06/22 修正。
DC 係数を AC と間違って書いていました。

投稿者 Takenori : 01:53 | コメント (0) | トラックバック (0)

2008年06月19日

吉里吉里 ムービー拡張日誌2 :: α動画基本動作OK

α動画のエンコードとデコード(+再生)ができるようになった。
640x480 80フレーム(2.6秒)の立ち絵動画をクオリティ95で圧縮すると、約 3.1 MBになった。
立ち絵なので、αチャンネルは ZLib で圧縮されている。
クオリティ80だと 1.8 MBになる。
元の無圧縮 AVI ファイルは 96MB。
ちなみに同じ動画を WMV 95% にすると 844KB。
許せる範囲かな?
ただ、640x480 とは言っても、立ち絵は半分くらいの領域を使っているのみ。
α動画では、完全に透明ではないピクセルを含む最小矩形領域のみ保存しているので、占める矩形領域が小さいとかなり小さい動画を圧縮しているのと同じになる。
また、この矩形サイズはデコード時も関係している。
吉里吉里側のα合成の負荷を下げるため、レイヤーサイズもこの大きさに変更し、レイヤーにデコード画像を描いている。
ただ、矩形領域なので、大の字のようなポーズだったりすると無駄が多い。

で、違う立ち絵の動画3つを Core2Duo E6750 で再生すると、CPU 負荷 10% ~ 15% 程度。
まだ、MMX 化までしかしていないので、SSE2 まで対応するともっと下がると思う。
ただ、SSE2 が使えない CPU では意味がない。
1.5 GHz程度のマシンでどの程度の負荷かはまだ確かめていない。
ほかに出来る MMX のみでの更なる高速化は、完全に透明なブロックの処理を省けるようにすることくらいかなぁ。
ただ、あの特許申請中のものがなぁ……
完全に透明かどうかではなく、ブロックが単一色かどうかは IDCT の前段階でわかる。
AC 係数がすべて0であれば、そのブロックは単一色となる。
単一色であれば、色変換は1ピクセルだけ行い、後はその色で塗りつぶせばいい。
αチャンネルを ZLib で圧縮したバージョンのほうは、ブロックのαチャンネルをすべて調べるのと気にせず合成してしまうのでどちらが速いかは微妙。
この方法で単一色ならブロックを塗りつぶすようにすれば、完全に透明などは関係なく、べたで塗られているところは高速化される。

今回作っているα動画は、krmovie.dll とは独立した機構になっている。
元々は、高速化のためにレイヤーのサイズをフレームによって変更する必要があったので、別のプラグインとして作ることにした。
それ以外にも制御の多くを TJS 側に持っていく形にした方が、いろいろと都合が良いだろうということもある。
このプラグインでは、バックグラウンドで動画を順にデコードしてキューにためていくことしかしない。
キューから取り出して描画を指示するのは TJS スクリプト側の仕事。
つまり、再生速度のコントロールは TJS 側で行うことになっている。
このような仕組みのため、プラグインを変更することなく、スクリプト側でより柔軟な制御が出来るようになるはず。
ただ、現在デコード順は順方向のみなので、この辺りの指定をもっといろいろ出来るようにすると、さらにいろいろな再生が出来るようになると思う。
また、ファイル終端までデコードが終了したら、指定した別ファイルを続けてデコードすることを可能にしたので、複数のムービーを滑らかにつなげるようになった。
従来セグメントループなどの形で実現していたことを、別々のファイルで出来るので、動画制作時の取り扱いなどが楽になるはず。

投稿者 Takenori : 16:13 | コメント (0) | トラックバック (0)

2008年06月06日

吉里吉里 ムービー拡張日誌2 :: α動画圧縮の一連の流れ

「ブロック分割→色変換→DCT→量子化→ハフマン符号化 ( ゼロランレングス符号化 ) →ハフマン復号化 ( ゼロランレングス符号化 ) →逆量子化→IDCT→色変換→ブロック合成」が出来るようになった
この一連の流れが出来れば、後はそれほど難しい作業ではない。
動画のファイルフォーマットは完全独自にする予定で、フォーマットの仕様は考えて簡単にまとめた。
ただ、開発途中で問題に気付いて変更する可能性はある。

と言うことで、エンコーダーの開発に取り掛かろうと思う。
エンコーダーは、連番 PNG か無圧縮 32bit AVI から、専用フォーマットの α付きモーション JPEG にエンコードする形になる予定。
連番 PNG は、別に連番でなくても良くて、指定フォルダ内にある PNG ファイルを名前でソートして、それを動画としてひとつにまとめる形にするつもり。
最初のバージョンでは、ハフマン符号化テーブルは固定にする。
その後に 2パス圧縮をサポートしてテーブルを最適化し、圧縮率を高めるバージョンを作るかもしれない。
出来上がったものの圧縮率や再生負荷を見て、後の改良は考える。

投稿者 Takenori : 23:05 | コメント (0) | トラックバック (0)

2008年05月28日

吉里吉里 その他の開発日誌 :: 吉里吉里2 + キャプチャープラグイン = 動画作成環境

吉里吉里2 と キャプチャープラグイン の組み合わせが、動画作成環境としてかなり高機能な気がする。
という事で、ゲーム画面動画キャプチャープラグインをリリース。

このページに置いておきます。

投稿者 Takenori : 16:10 | コメント (0) | トラックバック (0)

吉里吉里 その他の開発日誌 :: プレイ画面の動画書き出し

前々から動画の書き出し機能があると便利かなぁと思いつつも、需要があるのかどうかわからなかったので、特に手をつけていなかったんだけど、ある程度は使う人がいそうなのと、自分も使いそうなので作ることにした。

AVI で書き出すものはごうさんが既に作っていたけれど、AVI 2.0未対応で無圧縮で保存されるので、あっという間に2GB超え&HDDへの書き出しが間に合ってなさげで、扱いづらかった。
そこで、AVI 2.0 対応のために DirectShow を使用して書き出すことを考えていたが面倒くさい。
あれこれ考えていて、ふと、WMV で書き出すものなら、さくっと出来る気がした。
という事で、コーディング開始。
さくっと…… と思ったけど、4時間ぐらいコーディングにかかった。
動画系の API は手続きが多いので、いろいろと面倒だった。
改めて考えると、DirectShow を使っても大差なかった気がする。

で、動かすと IWMWriter::BeginWriting でエラーが返ってくる。
内容は、Video codec エラー ( An unexpected error occurred with the video codec ) 。
さっぱり理由がわからない。
サンプルのソースといろいろ見比べたり、サンプルをデバッガで動かして入っている値を見たりして修正するも改善せず。
もしかして、スレッドを分離しているのが原因? と思って、IWMWriter::BeginWriting を初期化側のスレッドとあわせるとエラーにならなくなった。
別スレッドにしたらだめだったのか。
でも、実際の書き出し部分はスレッドが分かれていても問題ない様子。
バッググラウンドでひたすらエンコードしてもらう必要があるので、書き出し部分は別スレッドに出来ないと少し面倒なので、そこは良かった。

という事で、吉里吉里でゲーム画面の動画を書き出すプラグインを作った (結局1日かかった)。
が、ここではまだ音に対応していない。
吉里吉里の本体から直接音を得る方法はない様子。
本体をいじるか、ループバックで録音するか。
結局、ループバックで録音する方法で行くことにした。
エラー音やクリック音などが鳴ると、一緒に録音されてしまうという難点があるが、まあそこは諦めるという事で。
音のキャプチャー自体は、DirectShow を用いて行った。
ここは特に問題なかったのだが、WMV 書き出しでまたうまく行かない。
エンコードしていたら途中で落ちてしまう。
エラーは The writer has received samples whose presentation times differ by an amount greater than the maximum synchronization tolerance. You can set the synchronization tolerance by calling IWMWriterAdvanced::SetSyncTolerance. とか。
IWMWriterAdvanced::SetSyncTolerance で時間を長くすると、どんどんメモリに溜めていってなかなかエンコードしない様子。
で、終わったものをみてもうまく撮れていない。
なんなんだろう? といろいろと調べていたら、書き出し時に指定するストリーム番号が設定されていなかった……
絵だけや音だけの場合、そこがおかしくても問題ないけど、絵と音のように2つ以上ストリームがある場合はまずいようだ。
というか、設定する部分を見逃していた。
これで音も撮れるようになった。
結局2日かかった。

ただ、これには問題がある。
WMV をリアルタイムでエンコードする関係上、すごくCPUパワーが必要。
640x480 30FPS では、Core 2 Duo E6750 (2.66GHz)、メモリ 4G、HDD RAID 0 でも間に合わない。
動きの少ないシーンでは大丈夫のようだが、動画を再生しながらとなるとだめ。
エンコードが間に合わない場合、メモリ上にひたすら画像を溜めていくのんだけど、どうも吉里吉里側の描画の方が処理落ちして、それであんまりメモリには溜まらずに進んでいく様子。
プライオリティーをいじれば解決するかもしれないけど、4Gあっても1分程度しか撮れないのであまり効果はない。
これはクアッドコア必須か。
ただ、Video Codec を Windows Media Video V7 や V8 にすると負荷が下がり撮れる。
というか、マルチスレッド化されておらず片方のコアをめいっぱい使っているだけのように見えるが、撮れることは撮れている様子。
まあ、これでいいかなぁと思ったが、もっと速い CPU が欲しいと自分も周りもつぶやいていて、少し考える。

連番 JPEG 書き出しバージョンを作ろう!
JPEG エンコードは、SIMD 拡張版 IJG JPEG library を使う。
で、組む。
1時間ぐらいで出来た。
WAV でもいいから音入らない? と言われる。
で、組む。
さらに1時間ぐらいで出来た。
いい感じ。
Core 2 Duo E6750 (2.66GHz) で CPU 負荷が 20 ~ 30% 程度。
比較的軽い。
WMV よりも容量が大きくなってしまうのは仕方ないが、バラバラのファイルになるので HDD 容量のみの問題だから、容量が大きくなるのはそれほど問題ではない。

実際のゲーム画面がキャプチャーされたものを見る。
普通に見れる。
というか、ゲームじゃなくてこっちでもいいとか思ったり。
それはどうか…… と言う話なんだけど、字幕付きのアニメを見ている感覚で楽。
これはちょっと考えさせられた。

このプラグインは少し使い方が厄介なので、マニュアルを少し書かないといけない。
その辺り書けたら公開するかも。

投稿者 Takenori : 13:31 | コメント (4) | トラックバック (0)