« August 2004 | メイン | October 2004 »

September 30, 2004

perlの1行スクリプト

コマンドラインで、正規表現を入力してリネームするツールでも作ろうかなぁと考えていてふと気付く。
perlにやらせれば事足りると。
次のような感じ。
perl -e "foreach( glob(\"*.jpg\") ){ $nam=$_;s/00\.jpg/\.jpg/g;rename($nam,$_);}"
スクリプト内の"をエスケープしないといけないのは面倒だけど、結構お手軽。
ミスることも考えて待避しておけば万全かな。

1行スクリプトは他にもいろいろと使いでがありそう。
PerlMagic(ImageMagic)とか。

投稿者 Takenori : 03:19 PM | コメント (0) | トラックバック

September 28, 2004

ボタン絵ジェネレーター

ボタンの絵をパラメタを設定するだけで生成することが出来るツールを作成。
これで、さくさくボタンが作れるが、このツールを作るのにかかった時間を考えると・・・ 普通に絵を作った方が断然速かった。
まあ、今後もっといっぱい作ることになったら、活躍してくれるでしょう。
たぶん。
そのときにはもっと機能追加が必要な気がするけど。

投稿者 Takenori : 03:58 PM | コメント (0) | トラックバック

September 27, 2004

ラジオボタンは使わない?

ゲームのUIだとラジオボタンはあんまり使わない?
単純な出っ張ったボタンと、へこんだボタンを用意して、選択されているものはへこんだボタンにするとか言う感じか。
で、仮絵をまたExcelで作る。
また、面倒くさい。
つーか、ボタン絵ジェネレーターとか作れそう。
うーん、一考の余地はあるかも。

投稿者 Takenori : 02:30 PM | コメント (0) | トラックバック

September 26, 2004

KAGに慣れる

まずはKAGを理解するために、一般的なADVのフレームワークを作り中。
でも、仮絵のボタンを作るのは面倒だ。
Excelで適当に作って、それをPrintScreenでとって切り取り。
きれいに3等分出来るサイズになっておらず、2ドット足りない。
まあ、中央のボタンが両脇の線を共有しているので当たり前。
仕方なく、右端を1ドット切る。
右の線がないボタンの絵がいっぱい出来た。
面倒なので右端にボタンをくっつけてごまかす。
仮だからね。
取り合えず、タイトル画面が出来たので、設定画面を作りにかかる。
上のメニューで設定できる項目は、ゲーム中の設定画面でも設定できるようにする。
でも、ラジオボタンがない?
もうちょっと探してみよう。

投稿者 Takenori : 08:56 PM | コメント (0) | トラックバック

September 23, 2004

BRenderをkrlmovie.dllへ移動する

幅と高さと平均時間を取得するメソッドを持ったインターフェイスを作る。
別モジュールではなくなるので、別にインターフェイスは作らなくてもいいのだが、作った方がスッキリするので作った。
後は、いろいろと削除したり、移動したり。でも、それは明日にしよう。

投稿者 Takenori : 09:47 PM | コメント (0) | トラックバック

KAG側仕様の検討

video タグに次の属性を追加
position : 再生時間を移動する場合
loop : ループをon/offする場合
frame : 再生フレームを移動する場合
mode : モード"overlay"か"layer"を指定する場合

新しいタグとして以下のようなものを追加
[videolayer layer=# page=fore channel=(1 or 2)] : channel はlayer1 かlayer2 を表す。
[clearvideolayer channel=(1 or 2)]

[pausevideo]
[preparevideo]
[rewindvideo]

[videosegloop start=# end=#]
[cancelvideosegloop]
[videoevent frame=#]
[cancelvideoevent]

[wv]でperiodも待つ。(すでに実装している)

以上のような感じかな。
で、書いてみて、デバッグする。
おお、KAGで動いた。
当たり前だけど、こっちの方がスッキリする。

投稿者 Takenori : 08:15 PM | コメント (0) | トラックバック

VideoOverlayクラスのドキュメントを書く

VideoOverlayクラスのドキュメントを書いてアップした。
次は、KAGの方を拡張しないと。
でも、どんな感じにするかなぁ。
と言うか、だいたい自然に決まってしまうけど。

レイヤー描画の機能がKAGから使えるようになれば、かなりお手軽になる。
サクサクですな。

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

気になっているところ

prepareのperiodイベント発生付近がきわどいかも。
イベントがマルチスレッドでなければ問題ないが・・・ つーか、スレッドセーフにしておけよって感じか。
何らかのロック機構があった方が良いかも。

イベント、状態遷移まわりはきちんと整理しておいた方が良さそう。

AVIの動作確認。
音無しMPEGファイルの動作確認。
SetSegmentLoop、CancelSegmentLoop、SetPeriodEvent、CancelPeriodEvent の動作確認。
メソッドなどは一度テスト用のコードを書かないと。

SetPeriodEventで、再生位置が指定されたフレームより前に移動した時に、イベント発生抑止を解除するのを忘れていた。

投稿者 Takenori : 03:04 PM | コメント (0) | トラックバック

吉里吉里へのマージ

Dee氏に、リリースした時に吉里吉里へのマージなどしていただけるのでしょうか? と聞いたところ、
"そうですね、安定したものでkaedeさんの了承を得られればしたいと思います"と言う回答を頂けた。
安定したらっすね。(笑
BRenderは、いろいろと苦労した分かなり安定しているはず。
後は他の部分のテストだな。
その前に、追加したメソッド群をまとめておかないと。

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

KAGの拡張

今はTJSを直接呼ぶことで、追加した機能を使用しているが、やはりKAGから指定できた方が楽だ。
で、拡張方法をDee氏に聞いたところ、
"MainWindow.tjsの最後の方に タグハンドラ群があって、全部 elm という引数をとっていますが、ここにタグの属性値が辞書配列で渡されてきます。
タグを追加したい場合はタグハンドラ群に、周りの関数に習って関数を追加すれば OK です。
タグハンドラの戻り値は基本的には次のタグへのms単位でのウェイトです。"
なるほどー。
簡単そうだ。

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

トランジションについて

トランジションは完了時に表と裏のレイヤが入れ替わるだけとのこと。
それなら、オーバーレイでLayer1, Layer2と持っている分には問題ないはず。
良かった良かった。

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

リリーサーの問題

以前、リリーサーを使ったら、うまく行かなかったのだが、Dee氏によると、
"単一の実行可能ファイルを作ろうとするとちょっとめんどうでsrc/core/environ/win32/optionarea.bin を tvpwin32.exe のお尻にくっつけて、くっつけた物の名前を krkr.exe としておいておかなければなりません。"とのこと。
そう言うことだったのか。
じゃ、copyでくっつければO.K.そうだな。

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

MPEGの問題

Dee氏によると、DVD再生ソフトなどを入れると、MPEGのデコーダーが標準のものではなくなって、時々不具合が出るとか。
それならば、フィルタグラフを作る時にクラスIDを直指定して、作れば問題ないはず。
ついでに直すことにした。
たぶん、フィルタの追加をダウンストリームからやっていけば、自動的には繋がれないと思う。
と言うか、Renderとか呼ばなきゃ大丈夫か。
で、AVIはどうしよう?
面倒そうでなければAVIも直指定にしておくかなぁ? うーん、自動の方がいい気もする。AVIはコデックとかいろいろあって、何かありそうな予感するし。
QuickTimeは要らないと言うことなので、ほったらかしにしよう。

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

BRenderのインストーラー

やはり、BRenderのインストールはない方が良いとのこと。
まあ、何となくはわかっていたんですけど・・・
だって、だってソースが汚くなるんだもん。とか言ってみたところで、始まらないので、なんとか、本体の方に吸収する方向で行こう。
と言っても、krmovie.dllとkrlmovie.dllを分離したので、少しはマシかもって、ダメだ。IBasicVideoは親が持っているんだった。
IBasicVideo *Video() を仮想にしてもいいけど、それよりも他の方法で解決したいなぁ。
IBasicVideoで使っているのは、
get_AvgTimePerFrame
get_SourceWidth
get_SourceHeight
の3つ。
で、get_SourceWidth と get_SourceHeight を使っているのは、GetVideoSize だけで、GetVideoSize は元々仮想なので、GetVideoSize を継承すれば問題ない。
じゃ、単にget_AvgTimePerFrameを仮想にすれば、O.K.かな。
意外とさっくり行くかも。
面倒なことは面倒だけど、簡単そうだな。たぶん。
三歩進んで二歩下がる~♪

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

ついにサンプル公開

ムービー レイヤー描画サンプルに置いてあります。
いろいろと実験してみてください。
私は責任もてませんけど。

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

September 22, 2004

本体側の修正

DLLが分離したのに伴い、本体側もそれに対応。
というか、ほとんど元の状態に戻したようなもの。
後、Flash側も要らなくなったものを削除。
それと、本体側でおかしかった部分を修正。
レイヤーサイズがムービーサイズと違う場合、強制的にムービーサイズに合わせるようにした。以前は、レイヤーが保持しているイメージサイズだけだった。

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

インストーラーでタイムスタンプ忘れ

BRenderインストーラーでタイムスタンプをきちんとつけるのを忘れてた。
そのせいで、インストールした日付のファイルが出来てしまう。
そのうち直さないと。

投稿者 Takenori : 12:28 PM | コメント (0) | トラックバック

DLLの分離

レイヤー描画のDLLをkrlmovie.dll として分離した。
さくっと出来た。
これで、GetVideoOverlayObjectのパラメタ渡しバージョンが必要なくなり、modeを渡してDLL内で判断し生成するのではなく、外で判断し、DLLを使い分ける格好になった。
何となくシンプルになったかな。

次は本体の方で読み分ければ、分離は完成。
Flash側も少し修正しないといけないけど。

投稿者 Takenori : 08:21 AM | コメント (0) | トラックバック

September 21, 2004

BRenderアップロード

これだけあってもどうしようもないんだけど、取り合えず上げておく。
文書もいろいろ考えていたら短くなって、別ページにしなくても・・・ とかいろいろあるが、上げてしまう。
徐々に改善していこう。

投稿者 Takenori : 02:52 PM | コメント (0) | トラックバック

ドキュメントを書く

BRenderをアップするためにドキュメントを書いた。
ドキュメントは面倒だ。
GNUライセンスなどの汎用的なライセンス形態にするのもうなずける。
でも、いろいろと書いたんだけど。
結構疲れた。
アップロードはもう一度確認するためもう少し後の予定。
でも、アップした後も、初めのうちは何度も改版しそうだ。

投稿者 Takenori : 09:14 AM | コメント (0) | トラックバック

September 20, 2004

新 BRenderインストーラーの作成

msvcr71.dll を含んだインストーラーを作成した。
これでmsvcr71.dll がない環境でも問題なくインストールできるようになった。
後、ついでに少しソースの整理もした。

投稿者 Takenori : 09:46 AM | コメント (0) | トラックバック

続・BRender.axのインストール問題

msvcr71.dll がシステムディレクトリにない場合は、システムディレクトリにコピーしてしまおう。
そっちの方がよい。
で、ゲームのインストーラーを作る時は、ゲームをインストールしたディレクトリにもmsvcr71.dll を置くことにする。
これで文句ないだろう。
理屈上、msvcr71.dll のコピーは、実行可能プログラムと共にアプリケーション ディレクトリに保存してください。となっているので、msvcr71.dll を使用するアプリは、自分のディレクトリにmsvcr71.dll を置くだろうし、LoadLibraryで優先されるのはそちらになる。
つまり、システムディレクトリのmsvcr71.dll が使用されるのは、どこかの自分のようなお間抜けさんの場合で、きちんと理解してする人の場合は問題ない。
それに、お間抜けさんの場合も一応動くので万々歳?
ま、OSをクリーン インストールした状態でテストすれば、気付くんだけどね。
よし、コピーしてしまう方向で行こう。

投稿者 Takenori : 08:47 AM | コメント (0) | トラックバック

オーバーレイモードの確認

オーバーレイモードでもうまく再生されるかどうか確認。
問題ないようだが、時々msvcr71.dllが要求される。
レイヤー描画モード以外では必要ないはずなのだが・・・ なぜ?
これは問題だ。
従来との互換性の問題が出てしまう。
msvcr71.dll自体は再配布可能モジュールのはずなので、配布することは出来るのだが、手軽さが落ちてしまう。

ほぼ確実な解決策はkrmovie.dll を2つに分けてしまうことだ。
つまり、オーバーレイ時はkrmovie.dll、レイヤー描画時はkrlmovie.dllと言った感じだ。
構成としてはこの方が綺麗かもしれない。
機能的には結構違いがあるので、それを明確にする意味でも良いかもしれない。
ソースコードもさっぱりする。
でも、dllが増えると煩雑かなぁ?
・・・
ここは分ける方向かな。
さっぱりするし。
それで行こう。

投稿者 Takenori : 08:20 AM | コメント (0) | トラックバック

BRender.axのインストール問題

BRender.ax がインストール出来ないと言う問題が再現した。
次のようなメッセージが出た。
LoadLibrary("BRender.ax")に失敗しました - 指定されたモジュールが見つかりません。
リリース前に確認しようとなにげにやったら出来なくて、なんだなんだとなった。
検索したり実験したりしてなんとか解決。
解法は、次のページにあった。
独自ActiveXがregsvr32で登録できない
dllから他のdllを使用していて、それがないからLoadLibraryに失敗していたというわけか。
ちなみに、mfc71.dllは使用していなかったので不要だった。
後、初めはBRenderのリリース版の方でmsvcrtd.libをリンクしていたので、
msvcr71d.dllが読み込まれていた。
これは、msvcrt.libに変更した。

で、結局のところ、msvcr71.dllが必要と言うことだ。
これはインストーラを書き換えた方が良さそうだな。
msvcr71.dllも内部に持ち、システムディレクトリに見つからなかったらコピーするようにしないと。
MSDNによると・・・
-----以下、引用
アプリケーションでは msvcr71.dll を使用し、再配布する必要があります。システム ディレクトリには、msvcr71.dll のコピーを作成しないでください。また、既にコピーが存在する場合でも、使用しないでください。msvcr71.dll のコピーは、実行可能プログラムと共にアプリケーション ディレクトリに保存してください。/MD スイッチを使用して Visual C++ .NET で構築したアプリケーションはすべて msvcr71.dll を使用します。
-----引用終わり
つまり、マルチスレッドと動的リンクを使うアプリはmsvcr71.dllが必要なわけね。
それと、システムディレクトリにmsvcr71.dllをコピーするのはまずいのか。
じゃあ、インストーラーと同じディレクトリに置くようにしないといけないのか?
と言うことは、単にインストーラーと一緒に固めれば済みそうだけど、そうすると、インストーラーを作る時に問題が発生しそうだから、インストール時、msvcr71.dllをカレントディレクトリに書き出すようにするのが良さそうだな。

インストールの時だけでなく、レイヤー描画を使用する吉里吉里の実行時にも必要だ。やっぱり、システムディレクトリにコピーが必要かな。
この辺りはもう少し検討&検証しよう。

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

September 19, 2004

画像結合ツールの開発 その1

ヤフオクに出品するものの写真の結合をやりながら思う、面倒くせー。
これは明らかに自動化できる作業だ。
で、画像結合ツールを作ると思い立ち、作業に取りかかった。
今回はめずらしくGUIで作る。
いつもは、Perlとかでさっさとやってしまうのに。
まあ、気まぐれだ。
そして、C++Builderを起動してぺこぺこやる。
C++Builderはあまり慣れていないので、少々手こずるけど、GUIアプリを作るのはすごく楽だ。

とりあえず、DrawGridに画像をD&Dして結合するようなIFにしようと思い、DrawGridをいじる。
でも、エクスプローラーからファイルをD&D出来ない。
ドラッグ&ドロップ用のイベントを書いてもうまくできない。
セル同士のドラッグ&ドロップが出来るようになっただけだ。
調べてみると::DragAcceptFiles( Handle, TRUE );とやって、WM_DROPFILESメッセージを処理するようにしないといけないらしい。
メッセージ処理用メソッドを作るにはBEGIN_MESSAGE_MAPを使うらしい。
なんか、MFCみたいだ。
でも、調べてみると、このマクロは単にDispatchに展開されるだけのようだ。
マクロだとデバッグ時にいろいろと面倒なこともあるので、Dispatchは自分でオーバーライドすることにした。
そして、DragAcceptFilesにDrawGridのハンドルを渡しメイク。
カーソルが変わった。
D&D出来るようだ。
で、ドロップ。
・・・
WM_DROPFILESのハンドラに来ない。
なぜ?
って、DrawGridのDispatchにWM_DROPFILESハンドラを書かないといけないんじゃないか。
普通にメインのフォームのやつに書いていた。

DrawGridを継承するコンポーネントを作る。
きちんとWM_DROPFILESハンドラに来るようなった。
次に画像データの保持だが、面倒なのでvectorで10*10決め打ちで作ることにした。ま、ツールだしね。
std::vector > m_Cells; こんな感じ。
そして値初期化の時にm_Cells.reserve(10)とやって作る。当然2次元なので2次元目もreserveし、NULLで初期化。
画像はTJPEGImageで保持させた。
そして、メイクしてインストールしようとしたら、"パッケージ'vcljpg60'にもユニット'Jconsts'が含まれるためパッケージ'dclusr60'は読み込めません。"と出た。
なんだ、コンポーネントでTJPEGImageを使うのはまずいのか?
よくわからん。
じゃ、libjpegを使おうと言うことで、検索。
とりあえず、ここを参考にする。
他にも検索していて、GDI+と言う言葉が目に入った。
そうだ、GDI+を使った方が楽かも。
急遽ligjpegからGDI+に方向転換。
少し調査。

少し時間が空いて、今日。
Cマガを見るとちょうどGDI+の話題だった。
なんと間のいい。
とりあえず購入。

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

すべてを追加してメイク

特殊再生のセグメントループとイベントフレーム設定機能を追加しメイク。
これで、一通りの機能は追加し終わったはず。

で、動作確認。
layerのvisible周りが変更になったので、prepareに書き換えておく。
ちょっと問題が発生したので、少し修正。
以前、prepareは
pause
rewind
play
1コマ描画
stop
rewind
のように処理すると、書いたが、
pause
rewind
play
1コマ描画
pause
rewind
に変更した。

セグメントループとイベントフレーム設定機能はまだ動作確認していない。
この動作確認はいろいろと準備が必要なので、もうちょっと後でテスト予定。

残りは、テストとドキュメントだな。

投稿者 Takenori : 06:14 AM | コメント (0) | トラックバック

Flash側DLLのメイク

DirectShow側のDLLに追加したメソッドなどをFlash側にも追加した。
と言っても、中身は空っぽ。
単に未サポートと返すだけだ。
いくつかのメソッドは簡単に実装できそうだったが、面倒なのでやめた。
そして、メイクするが、TShockwaveFlashがないと言われる。
よくわからん。とりあえず、クグってTShockwaveFlashを探す。
日本語ページで1個ヒットしたが、リンク切れだった。
仕方なく、googleのキャッシュを開いてみたら、なんとか読めた。ラッキー
Delphi 6の解説のようだったが、とにかく、ActiveXコンポーネントを取り込めると言うことのようだ。
で、C++ Builder 6でも似たようなものを探す。
コンポーネント->ActiveXの取り込みが同じもののようだ。
そして、Shockwave Flash (Version 1.0) を選択し、コンポーネントを追加、インストールする。
なんかうまくいった。
しかし、今度はリンク時にflashbpk.libがないと言われる。
flashbpk.libって?
クグるがヒットせず。
ふと気付き、以前Dee氏からもらったライブラリ類の中を検索。見つかった。
で、コピー。
メイクが通った。
これで、Flash側はO.K.かな。と言っても、何もしていないに等しいけど。

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

September 18, 2004

prepareメソッドの追加

以前、変なフレームが表示される問題で、
open
pause
visible = true
play
のようにすれば、大丈夫だろうと書いたが、やっぱり準備メソッドを追加した。
内部的には
pause
rewind
play
1コマ描画
stop
rewind
のように処理する。
たぶん、
prepare();
[wv]
visible = true;
のような感じで書けばうまく行くはず。
動作確認は、セグメントループとイベント設定が出来た時に同時に行う予定。

投稿者 Takenori : 06:38 AM | コメント (0) | トラックバック

Visioを注文

以前からシーケンス図や状態遷移図を描きたいなぁと思っていて、IIOSSなどを使ってみたりしていたのだが、作図に限って言えば、Visioは使いやすい。
シーケンス図の編集は泣きそうになるのだが、その以外はいい。
で、最近お金が入ったので昨日Amazonで注文してしまった。
Vision Standard 2003 と Visio Professional 2003 Version/Product Upgrade だ。
なんでこんな構成になっているのかよくわからないが、Professionalを買うよりも安いので、まあいい。
到着予定は、1個が19日~21日、1個が22日~25日の予定だ。
なぜか分割発送を選んでしまった。
しかも、先に届くのはProduct Upgrade の方。
なんだかなぁと言う状況だ。

それはともかく、ビデオの再生でいろいろと機能追加して、複雑になってきているので、状態遷移図やシーケンス図で整理できるようになって、いい感じだ。
本当は先に図を描いておいた方がいいんだけど、Visioがなかったから仕方ない。
これからは先に描くだろうし。
状態遷移図とか描くのもなかなか楽しいしね。

投稿者 Takenori : 06:27 AM | コメント (0) | トラックバック

イベント発生の仕様

イベント発生の仕様はどのようにしたらよいだろう?
基本的には特定のフレームをセットしたら、再生中にそのフレームに来たら、periodイベントを投げるというものだが、問題はドロップフレームが発生する可能性があると言うことだ
つまり、if( curFrame == eventFrame ) ではなく、if( curFrame >= eventFrame ) としなければならないわけだが、そんなことをしてしまうと、指定フレーム以降毎フレームイベントを投げてしまう。
それならということで、フラグをもうけて1度しか投げないようにすれば良いかというと、そしたら、ループ中にイベントが発生するように設定したら、1回しか投げられなくて、期待したのと違うという事態にもなる。
じゃあ、指定したフレームより前のフレームに移動したらフラグを解除して・・・ と考えていったわけだが、ふと、利用する時はどのようなものが使いやすいか、と言うことについて考えてみた。
そして、そのフレームを通過した時、1回だけしか投げないと言う仕様にしてしまった方がスッキリするのではないかと思った。
たとえば、イベントを投げるとeventFrame=-1;などとして、イベントを投げるフレームを忘れてしまうわけだ。フラグも要らない。
ループなどでは何度も設定しないといけないわけだが、そう言う仕様だと言うことにすれば問題ないだろうし、ループ中で何度も投げることは少ないだろう。
ただ、問題点として、再生中のフレームより小さいフレーム番号にイベントを設定すると、設定した次のフレームにイベントが投げられてしまう。これはちょっと不便だ。
なら、ドロップフレームは10フレームまで考慮し、それよりフレーム番号が大きい場合は無視するように・・・ そしたら、取りこぼしが怖いなぁ。
設定した時のフレームの前後関係を保持し、現在のフレーム番号の方が大きい場合は、イベントが発生しないようにし、設定されているフレームよりも小さいフレーム番号へ移動した時にこの発生しないようにしたものを解除すると言うのが妥当だろうか。
ちょっと複雑になってしまったけど、仕方ないかな。
とりあえず、そんな感じにするか。

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

September 16, 2004

特殊再生系I/Fの追加

VideoOvlIntf.cppへTJS用のクラスへマクロを使って、メソッドを追加。
VideoOvlImpl.h/.cppへ上記のところからコールする用のメソッドを追加。
DLLへも呼び出しが必要な場合は、さらにkrmovie.hへメソッドの追加が必要になる。(今回は必要ない)
うーん、深い。
まあ、よくあることだけどね。
で、コードジェネレーターみたいなのが欲しいと思ったりもするけど、今回はそんなに追加するわけじゃないので必要ないかなぁとか考える。
でも、もしかしたらすでに付いているかも。ま、もう予定しているのは追加したので、もういいんだけど。

で、次は実装。
指定フレーム間ループは、フレーム比較さえ気を付ければ簡単。
イベント発生はちょっと検討が必要かも。不用意にイベント送りまくらないように。

投稿者 Takenori : 11:21 PM | コメント (0) | トラックバック

September 15, 2004

追加したプロパティの確認

バリリアンと型にはtjs_uint64への変換がないのかな?
なぜかそこでエラーになったので、そこはtjs_int64とした。
そしたら、メイクが通ったので、動作確認。
とりあえず、コンソールに各プロパティの値を出すことにした。
で、実行。
なぜかエラー、よく見るとkrmovie.dllがエラーを出していた。
そうだ、krmovie.dllのビルド忘れていた。
ビルドして再度実行。
きちんとそれっぽい値が出ている。
よし、ここは大丈夫そうだな。
後でもう一度きちんと見た方がいいけど。

投稿者 Takenori : 11:55 PM | コメント (0) | トラックバック

September 14, 2004

未実装のプロパティ系を実装

まだ実装していなかった、次のプロパティ群を実装。
メイクはまだ。

組み込んだプロパティを列挙すると次の通り。
プロパティ
position ( 再生位置 )
frame (現在のフレーム)
fps (フレームレート)
numberOfFrame (全フレーム数)
totalTime (合計時間)

positionは迷ったが、ついでに組み込んだ。単位はミリ秒のまま。
totalTimeも単位はミリ秒とした。
positionやframeを使い、再生位置を設定した場合、完全に指定した位置になるわけではなく、指定した位置に最も近いキーフレームの位置に設定される。
これは、再生中に素早くシークできるようにするため。
なので、シークしたい位置には、ムービーを作る際にキーフレームを入れておく必要がある。
次は、特殊再生の実装だな。

これらプロパティはオーバーレイでも使用できるようになっているはず。
でも、特殊再生はレイヤー描画モード専用となる。
Flash, ビデオオーバーレイ, レイヤー描画モードで機能がだいぶ違う。
機能の多さは
Flash < ビデオオーバーレイ < レイヤー描画モード
となるのかな。
でも、サイズ指定などがレイヤー描画モードにはないので、必ずしも上記のようにはならないか。
各機能がどれで使えるかはまとめておかないと混乱の元だな。

ムービーの位置指定のSetLeft, SetTop, SetPositionとSetVisibleも実装した。
レイヤーへスルーさせただけだけど。
他の幅などを設定するものは、レイヤー描画モード時は何もせずにリターンさせた。

Visibleで思い出したが、1コマ目にゴミが表示される問題はどうしよう。
たぶん、
open
pause
visible = true
play
で、回避されるはずだが・・・
一回実験しないとな。

投稿者 Takenori : 03:04 AM | コメント (0) | トラックバック

EC_UPDATEイベントと共にフレーム番号を

なんとか、BRender側でEC_UPDATEイベントを送る時に、フレーム番号も一緒に送れるようになった。
また、忘れない内にBRenderのインストーラのリソースも更新しておく。
これで、BRenderは予定していた機能の組み込みは終了のはず。
次は、吉里吉里側でまだ実装していない機能の追加と、基底クラス書き換えによって増えたメソッドとDLLから出すメソッドのFlash側への実装だな。

投稿者 Takenori : 12:48 AM | コメント (0) | トラックバック

時間からフレーム番号へ

とりあえず、以下のようなコードで変換。

REFERENCE_TIME TimeStart;
REFERENCE_TIME TimeEnd;
GetSampleTimes( pSample, &TimeStart, &TimeEnd );
double renderTime = TimeStart / 10000000.0;
REFTIME AvgTimePerFrame;
CBaseControlVideo::get_AvgTimePerFrame( &AvgTimePerFrame );
EventParam1 = (LONG)(renderTime / AvgTimePerFrame + 0.5);

なぜか、REFERENCE_TIMEはLONGLONGで、REFTIMEはdouble。
とりあえず、doubleにあわせて計算。
最終的に四捨五入してフレーム番号とする。(レンダリング時間は処理時間を考慮して、少し遅く、もしくは早く設定されている。詳しく言えば、1フレーム目は少し遅く、それ以降は少し早くなっている。はず)
これで、だいたいいい感じのフレーム番号が出ているようだ。
でも、開始直後など時々ドロップフレームがある。
まあ、仕方ないでしょう。
このフレーム数を使って処理する部分は、ドロップフレームが発生する可能性を考慮して作らないといけない。
つまり、何フレーム目でと言う処理で、==とかで比較すると、一生一致しない可能性がある。
この点は気を付けないとな。

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

September 13, 2004

現在のフレーム番号の取得

様々な場所でIMediaSampleからメディアタイムを得ようとするが、得ることは出来ず。
やはりデコーダーはメディアタイムを設定していないようだ。
ということは、レンダーは即座にレンダリングすることになる。
しかし、CBaseRenderer::Receiveがコールされてから実際にレンダリングされるまでには、一度イベント待ちがある。
つまり、このイベント待ちの直後の時間が、そのフレームの時間に近い。
そして、CBaseRendererでは、イベント待ちの後にOnWaitEnd がコールされるようになっているので、これをオーバーライドすれば、目的の時間に最も近い時間が得られるはずだ。
また、OnWaitStartと言うメソッドもある。
何となく、気になったので、この2つのメソッドを通過する時間をOutputDebugString でデバッガへ出力。すると、明らかにイベント待ちをしたような時間差がある。
イベントってレンダラー自身がIMediaSampleからメディアタイムを得て、IReferenceClock::AdviseTimeを使用し、そこからイベントが送られてくるのを待つんじゃなかったっけ?
調べると、やはりCBaseRenderer::ScheduleSample でスケジューリングされていた。
その中では、GetSampleTimesがコールされていて、そこから得た時間を元にスケジューリングしているようだ。
しかし、GetSampleTimesの中では、IMediaSample::GetTimeを使って時間を得ている。
以前、IMediaSample::GetTimeを直接コールしても、時間を得ることが出来なかったのだが・・・ なぜか出来ている。
あれ?っと思い、GetSampleTimes をコールしたら、時間を取得できた。
さらに、ありぃ?と思い、IMediaSample::GetTimeを直接コールしてみたら、またしても時間を取得できた。
なぜ?
私は幻を見たのだろうか? そんなことはないはずだが・・・
でも、100nsec単位の時間が返ってきている。確か、ビデオではフレーム番号がメディアタイムのはずだが。
GetSampleTimes はタイム スタンプを取得するとある。
って、あああぁぁぁぁぁぁぁぁ。
IMediaSample::GetTimeとIMediaSample::GetMediaTimeって、メソッド違うじゃないか!
IMediaSample::GetMediaTimeにしたら、やっぱり取得できなかった。
と言うことは、IMediaSample::GetTimeからフレーム番号に変換すれば何とかなりそうだ。
ここは意外と盲点かも。って、俺がアホなだけかな。

ちなみに、IMediaSeeking::SetTimeFormat( &TIME_FORMAT_FRAME )と設定しても、IMediaSample::GetMediaTimeでメディアタイムを得ることは出来なかった。

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

September 11, 2004

特殊再生仕様

はじめは、事前に何らかのスクリプトをセットして再生する方法を考えていたが、次のようなメソッドを追加すれば、事足りそう。

SetSegmentLoop (指定フレーム間ループ) : 未実装。
CancelSegmentLoop (指定フレーム間ループ解除) : 未実装。
SetPeriodEvent (指定フレームでのイベント) : 未実装。
CancelPeriodEvent (指定フレームでのイベント解除) : 未実装。

Get系を追加するかどうかは検討中。

上記のようなメソッドとイベント待ちを使い、イベント後の振る舞いの設定で、多彩な再生が可能になるはず。
ムービーをつなげてストーリーが展開していくようなものも出来るだろう。

投稿者 Takenori : 08:15 PM | コメント (0) | トラックバック

仕様や進捗

とりあえず、新規追加部分について、進捗をまとめることに。

メソッド
pause (一時停止) : 組み込み済み
rewind (巻き戻し) : 組み込み済み
playSequence (特殊再生) : 未実装、仕様検討中。

プロパティ
position ( 再生位置 ) : 未実装。若干必要性が疑問。
loop (ループ ) : 組み込み済み。
frame (現在のフレーム) : 未実装。
fps (フレームレート) : 未実装。
numberOfFrame (全フレーム数) : 未実装。
totalTime (合計時間) : 未実装。
layer1 (描画レイヤー指定1) : 組み込み済み
layer2 (描画レイヤー指定2) : 組み込み済み
mode (オーバーレイorレイヤー描画) : 組み込み済み

イベント
onStatusChanged ( ステータスが変更された ) periodイベント追加 : 組み込み済み


オーバーレイの方にある、位置指定やサイズ、表示/非表示についてはどうするか検討中。
セットしたレイヤーに対して行うのと同じだし。
ただ、スルーするだけでも良いが・・・

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

September 10, 2004

BRenderの拡張をしようとする

BRenderは画面更新時にEC_UPDATEイベントを送るが、そのとき同時に、何フレーム目かを送れるように変更しようとした。
IMediaSampleに問い合わせれば、フレーム番号が取得できるはずだから、簡単に出来ると思っていたのだが・・・
取得しようとしたら、"このサンプルにはメディア タイムがセットされていない。"って、返ってきた。
どうしよう。
これはまた大変そうだ。
他の方法をとるかなぁ。

まずは調査だ。

投稿者 Takenori : 11:47 PM | コメント (0) | トラックバック

エラーウィンドウ大量発生バグの解決

バグは、
kag.movie.layer1 = null;
としたら、エラーウィンドウが大量発生するというものだった。
で、この部分のコードはレイヤー(LayerIntf.cpp)のassignImagesのところをコピーしてきた。(同じようにレイヤーを引数にとるので)
コードは次のような感じ。

tTJSNI_BaseLayer *src;
tTJSVariantClosure clo = param[0]->AsObjectClosureNoAddRef();
if(clo.Object)
{
   if(TJS_FAILED(clo.Object->NativeInstanceSupport(TJS_NIS_GETINSTANCE,
           tTJSNC_Layer::ClassID, (iTJSNativeInstance**)&src)))
       TVPThrowExceptionMessage(TVPSpecifyLayer);
}
if(!src) TVPThrowExceptionMessage(TVPSpecifyLayer);
_this->AssignImages(src);

で、問題はsrcが初期化されていないこと。
*src = NULL;ってやった方が良さそう。
でも、そうすると下のif(!src)に引っかかって、エクセプション。
なので、(!src)の部分は上のif文の中に入れた。
で、自分のlayer1プロパティを設定するところは以下のような感じ。

tTJSNI_BaseLayer *src = NULL;
tTJSVariantClosure clo = param->AsObjectClosureNoAddRef();
if(clo.Object)
{
   if(TJS_FAILED(clo.Object->NativeInstanceSupport(TJS_NIS_GETINSTANCE,
               tTJSNC_Layer::ClassID, (iTJSNativeInstance**)&src)))
               TVPThrowExceptionMessage(TVPSpecifyLayer);
   if(!src) TVPThrowExceptionMessage(TVPSpecifyLayer);
}
_this->SetLayer1(src);

自分のところはこうしたが、レイヤーの方はいいのかな?
まあ、nullが引数であることはないのかも。
自分のところは、設定を解除するのに使っているので必要。
とりあえず、報告かな?
新しいのでは直っているのかもしれないけど。

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

やっぱり、BCBがなんかおかしい

今日もなぜかブレイクポイントで止まらない。
全部消してやると動く。
さっぱりわからん。
ここに来ていったいなんだと言うんだ。
もっと片っ端から消してみるかな。

で、片っ端から削除したら動くようになった。
でもまだ油断は出来ない。
明日になったら、またうまくいかないようになっているかもしれない。
そう言えば、BCBのアップデートってやったっけ?
やったようなやっていないような。
一応もう一度やってみるかな。

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

September 09, 2004

BCBでデバッグが出来なくなる

BCBで一度リリースビルドしたあと、デバッグビルドしたのだが、ブレークポイントで止まらなくなってしまった。
それで、再構築を何度もやったり、プロジェクトファイルを元に戻したり、したのだがうまくいかない。
BCBの問題かと思って、他ので試したらうまく行く。
VCで作ったDLLをデバッグ版にして、生成されるファイルを片っ端から削除しメイクしたらうまく動くようになった。
やっぱり、何かが残っていたのだろうか?
というか、それ以外はあんまり考えられないんだけど。
ま、解決して良かった。
今度、また同じようなことがあったら、まずは手作業で全部消してみよう。

投稿者 Takenori : 02:12 AM | コメント (0) | トラックバック

BRenderインストーラの作成

BRenderインストーラを作成した。
面倒なのでVCでMFCを使って組んだ。
MFCを使ってと言っても、書いたコードのほとんどはAPIコールだが。
にしても、面倒臭い。
基本的には、リソースに入れたファイルをシステムディレクトリに書き込んで、その書き込んだBRender.axをロードして、登録する関数ポインタを得て、それをコールするだけなのだが、きちんとエラーの処理などをしているのでコードがかなり多くなってしまっている。まあ、当然のことなのだが。

でも、これでBRender.axの公開にだいぶ近づいた。
後はドキュメントを書くだけ。面倒だけど。
そして、その次はレイヤー描画だ。
なんとか、来週ぐらいに一度リリース出来ると良いのだが・・・
まとまった時間がとれれば可能かな?

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

September 08, 2004

インストーラを作ろうとする

regsvr32 BRender.ax
とやっても、コンポーネントを登録できない環境があるようです。
もしかしたら、操作上の問題かもしれないけど、インストーラを作ろうと思い立ち、VS.NET 2003でインストーラを作ろうとしてみる。
適当にやったけど、よくわからなかったのでヘルプを見る。
すると、コンポーネントだけをインストールするインストーラは、作れないとか。
アプリと同時インストールじゃないといけないらしい。
なんて不親切な。
そしてさらに、インストール (ActiveXコンポーネントを) と言う項を見ると、全部普通にコーディングしないといけないようなことが書かれていた。
面倒くせーと思ったが、ダイアログベースで、OK/Cancelのボタンだけ付けて、OKが押されたらコンポーネントをコピーしてDllRegisterServerをコールするだけだからそんなでもないかと思い直した。
まあとにかく、インストーラ作らないと。

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

レイヤーへの描画サンプル

サンプルを置こうと思ったけど、いろいろいじっていたらちょっとまずい部分を発見したので、とりあえずやめにした。
まあ、激しいエラーが出て大慌ててでアプリ強制終了させると言うことがあったんですが。
原因は、フレームの更新部分にあったようで、レイヤーにnull設定したら、フレームの更新のたびにエラーが出て、毎秒30個エラーボックスが出るという悲惨なことに。

で、とりあえず画面イメージだけ。クリックすれば実寸になります。
layVideo.gif

どうしても、早く見たいって言う人がいたら言って下さい。
あげますんで。
でも、今のところ動作無保証です。
何があっても知りません。
まあ、他のアプリと同時に起動させていなければ大丈夫でしょう。
と言っても、その内リリースされると思うから別に今じゃなくてもいいんですけどね。

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

リリースに向けて

まずはCOMコンポーネントを公開に向けて利用方法などの資料整理だな。
ムービー拡張を組み込んだ吉里吉里は、いろいろとやらないといけないことが残っているので、まずはそれを片づけないと。
それと、ブログを整理してDirectShowの解説ドキュメントも書いておきたいな。
ブログのままだとぐちゃぐちゃだし。というか、1から読まないとよくわからない状態。

吉里吉里でムービーの上に文字が表示されているサンプルって、早く見たいって人はいるのだろうか?
たぶん、リリースまでにはまだ時間がかかりそうだからこんな感じだ!って、置いておくのも良いかもしれない。
でも、その前にDee氏に一言断っておいた方がいいな。
一度またIRCに行こう。

さて、ここからが面倒臭い作業だが、リリースに向けてがんばらねば。

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

使用感など

現時点では、KAGで直接記述することが出来ないので、KAGスクリプト内にTJSスクリプトを書くことになる。
で、初期化部分はこんな感じ。
[iscript]
kag.movie.loop = true;
kag.fore.layers[1].setSize(640,480); // ここは内部でムービーサイズを
kag.back.layers[1].setSize(640,480); // 割り当てるなどしないと
kag.movie.layer1 = kag.fore.layers[1];
kag.movie.layer2 = kag.back.layers[1];
kag.movie.mode = vomLayer; // オーバーレイはvomOverlay(default)
[endscript]
初期化さえ書いてしまえば、後はほとんどTJSで変更する部分はないかも。
たぶん、次のようにループをOFFにしたり、ONにしたりするぐらいだと思う。
[iscript]
kag.movie.loop = false;
[endscript]
そして、ムービーの位置などはレイヤーを使って操作する。(たぶん今はムービーのやつは効かないはず)
この辺りのオーバーレイモードとの違いなどはもう少し検証する必要がありそうだ。
後、レイヤーに描画されるので、トランジションなんかも出来るかもしれない。(未テスト)
にしても、意外と安定している。
まあ、サンプルでいろいろと実験してたからなぁ。
それにしても、なんか普通だな。
普通にムービーが再生されて文字が出ている。
元々こうだったんじゃないかとさえ思える。

それにしても、レイヤーに描画されるようになったことで、いじりがいがありそうだ。

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

September 07, 2004

レイヤーへの描画、長かった・・・

ついにレイヤーにムービーが表示された。
テキストがムービーの上に出ている。
やったー。

でも、同時にいくつか問題が。。。

とりあえず解決したものとして、初めループ出来なかったのが直せた。
ただし、これでいいのかどうかは謎だ。
どういうことかというと、ループの終点でperiodイベントを送っているが、periodを送ったすぐ後で、playを送っている。
これはステータスをplayに戻すためだ。
単にStatusへplayを設定すればいいだけかもしれないが、とりあえずこのような実装にした。
ここはもう少し調査する必要がありそうだ。

もう一つは、ムービー開始点で一瞬ちらつくと言うことだ。
これは、ムービーが開始され、1フレーム目を描画し終わる前に画面が描画されてしまうために発生してしまう。
どうしてそうなるかと言うと、現在、描画後画像をレイヤーにアサインするような作りになっているのだが、初めは何も描画されていない真っ白な画像がレイヤーにアサインされている。
つまり、そのレイヤーを表示にした瞬間、この白い画像が描画されてしまう。
そして、1フレーム目が描画され、アサインされた瞬間に普通の絵が出る。
とりあえず、内部的にムービーの1フレーム目が描画され、アサインする時に表示にするようにしたが、本来は表示前にreadyか何かのメソッドを準備し、1フレーム目をレンダリングしレイヤーにその画像をアサインするようにした方が良いだろう。
そうすれば、表示にした時、1フレーム目が表示されるので特に問題ない。
しかし、そうすると1フレーム目が2回表示されて・・・というか、ダブルバッファリングだから表示が1フレーム遅れるのは仕方ないか。
ま、この辺りはもう少し考えて改善することにしよう。

何はともあれ表示されるようになったので、ちょっとこれで遊ぶぞーぅ。

投稿者 Takenori : 09:11 PM | コメント (0) | トラックバック

DLLへ公開メソッドの追加

tGetVideoOverlayObjectと同じ機能を持った構造体渡しバージョンを作った。
そして、元のtGetVideoOverlayObjectは、mode引数を削除し、従来のままの関数とした。
で、ビルド&実行。
うまくいった!
引数が7個とかになるとまずいのだろうか?
引数の制約でもあるのか?
でも、別にスタック渡しなら問題なさそうな気もするが・・・
よくわからないけどいいや、解決したし。
詳しく追ってもいいけど、そんなに引数が多い関数は滅多に作らないだろう。
ま、後で気が向いたら詳しく追おう。

そして、いよいよレイヤー描画の動作確認だ。
でもその前にTJSスクリプト書かないと。

投稿者 Takenori : 07:28 PM | コメント (0) | トラックバック

フレームを止める

フレームを止めて、メニューをTopページだけにしました。
ちょっと使いづらいかも・・・
でも、慣れかな。
そんなにいろんな項目を頻繁に切り替えて見たりしなければ大丈夫でしょう。

後、他のページで書いていた気ままに3Dもこっちへ移動。
次は昔書いていたドキュメントを移動したい。

投稿者 Takenori : 07:02 PM | コメント (0) | トラックバック

レンダラー

Lightflow
レッドクイーン
YafRay
Parthenon

投稿者 Takenori : 06:51 PM | コメント (0) | トラックバック

レイヤー描画を組み込んでビルド

レイヤー描画関連の機能を組み込んでビルド。
動作確認をしたら、なぜかDLL内の関数に渡される引数の一つがおかしなことに。
呼び出し方法も指定しているし・・・
引数が多いのが原因?というか、そう言うことってあるのか?
よくわからない。

BCBとVCでデバッグできないかなぁ。
BCBでデバッグ中だと、VCからそのプロセスにアタッチできなかった。
VCがBCBで吐いたコードのデバッグ情報を読み込んでくれれば楽なのだが・・・
VCのデバッガの方がいいし。
出来るかなぁ?

やっぱり、よくわからない。
もう一個メソッドをDLLから出してみるかなぁ。

投稿者 Takenori : 06:42 AM | コメント (0) | トラックバック

変更点など

変更点は署名(T.Imoto)入りのコメントで囲んでおくことにした。
後、出来る限りここに変更点を記しておくことに。
飽きて止めてしまいそうな気もするけど。

VideoOvlIft.cpp
ttstr tTJSNI_BaseVideoOverlay::GetStatusString() const にpauseとperiodを追加。
tTJSNC_VideoOverlay::tTJSNC_VideoOverlay() にメソッドとプロパティを追加。

SoundBufferBaseIntf.h
tTVPSoundStatusにssPauseとssPeriodを追加。

VideoOvlImp.h/.cpp
必要なメソッドとメンバ変数を追加。
必要な処理を追加 or 変更。

krmovie.h
iTVPVideoOverlay にインターフェイスを追加。

ScriptMgnIntf.cpp
TVPInitTJSScript にtTVPVideoOverlayModeを追加。

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

krmovie.dllのビルド

クラス生成の切り替えを組み込んだのでビルドしたのだが・・・
tTVPBaseBitmapとtTJSNI_BaseLayerを使おうと、ヘッダーをインクルードしていたところで激しくコンパイルエラーが。
なんかいろいろと大変そうです。
DLLで使おうとするのがまずいのか、VCで使うのがまずいのか。
そんなpragmaないとかも言われたし。
なおすのはかなり大変なようなので、仕方なく現在の方法を断念。

初期化部分と、更新部分は相互扶助によって行うことに。
レイヤー描画用のメソッドがいっぱい増えてしまった。
ここいらは後でもう一度見直した方がよいかもしれない。

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

September 06, 2004

Lightflowのファイル

Lightflowのシーンは独自のファイルフォーマットがあるようだ。
それも、アスキー形式とバイナリ形式がある。
シーンプロキシをLfASCIISceneProxyにすれば、指定したストリームにアスキー形式でシーンを出力してくれる。
当然、そのファイルをレンダリングさせたり、そのファイルからシーンを構築できたりする。
つまり、I/Fがなくても直接このスクリプトを書けばレンダリングさせることが出来る。でも、それはかなり面倒くさい。やっぱり、I/Fは必要だ。
アレ?ということはこの発見は意味ないか。
ま、ネットワークレンダリングの時に役立つぐらいかな。
でも、なぜか少しI/Fのイメージがわいた。

投稿者 Takenori : 06:42 PM | コメント (0) | トラックバック

レイヤー描画ビデオクラスの作成

オーバーレイとレイヤー描画の共通基底クラスへオーバーレイのIBasicVideoインターフェイスを移す。
共通基底クラスの純粋仮想関数を何もせずにリターンするように実装する。
これで、共通基底クラスの純粋仮想関数はなくなった。
まあ、それぞれのクラスで実装しないものを、何もしない関数として上位に実装しただけだが。
レイヤー描画ビデオクラスをコーディング。
まだ、ビルドしていないがとりあえずコーディング終了。
後は、生成部分でのクラス生成分けと、レンダーフィルターからの描画更新イベントに対応すれば、とりあえずはレイヤーに描画できるようになるはず。

CLSID_BufferRendererは手書きで定義したが、IDLにcoclassを記述して、MIDLに生成させた方が良いかもしれない。
ビルドしたところ、問題なかったのでそのままにした。

投稿者 Takenori : 02:56 AM | コメント (0) | トラックバック

September 05, 2004

I/Fなどについて悩む

一般的には、レンダーツリーとか言われるものが使われるようだが、どこまでツリーで表現しているのだろうか?
マテリアルの属性や位置はツリーで表しやすいが、特定のオブジェクトにだけライトを当てたい場合などはステートマシンのように設定できる方が望ましい。丸描いてこの中にあるオブジェクトには有効で、こっちの丸の中にあるオブジェクトにはこれで、両方が重なっているところにはこれをといった具合だ。
というか、そんな使い方はしないのかな?
あまりにステートマシンの性質が頭の中にあるせいでそう言う発想になってしまっているのだろうか?
そもそも、Lightflowでそう言うことが出来るのかどうかまだよくわかっていないので、そっちを先に調べるのが先決だな。
ま、今日は他のことで時間がなくなってしまったので、何げに考えていたことを書いただけなのだが。

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

ムービーレイヤー描画の制約

諸般の事情により、ムービーレイヤーはムービーの画像サイズを変更できないことにしたので、LayerVideoが持つBitmapはムービーのサイズと同一です。
描画対象レイヤーはそのBitmapと同一サイズである必要があります。
なので、レイヤーサイズがムービーのサイズを異なる場合、強制的にレイヤーサイズを変更してしまいます。(いいのかなぁ)
ムービーサイズとレイヤーサイズにはご注意を。
ムービーの画像サイズを変更出来るようにすれば、この問題は解消されるのだけれども、それは後で考えよう。

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

コメント整備とコードの修正

ヘッダーコメントで欠けていた部分を追記。
コメント追記中に発見した不具合の修正。
メンバ名やパラメタ順序など統一性がとれていなかった部分を修正。
動作確認。

とりあえずは、これでこのフィルタコンポーネントは完成だ。
未テストな部分も多いけど、それはまたおいおいやることにしよう。リリース前とかに。
で、ここから吉里吉里への組み込みだな。
IBasicVideoをサポートしたので、両方で同じような処理に出来る部分が増えた。
平均レートの問題も解決した。
フィルタコンポーネント化したことで、すっきりする。
さあ、吉里吉里だ。

投稿者 Takenori : 03:28 PM | コメント (0) | トラックバック

September 04, 2004

プレーヤーもダブルバッファリングに対応

プレーヤーもフィルターの変更に伴いダブルバッファリング化した。
結構すんなり動作。
でも、ダブルバッファリング化されているのかどうかわかりづらいな。
片方だけを描画してみたり、入れ替えたりしてみたところ、少しカクカクした動作になった。
たぶん、うまくいっているのだろう。

これで、フィルタコンポーネント側はとりあえず完成かな。
一応、ソースの確認とコメントの整備、利用側へ提供するコードの整備を行う必要があるけど。

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

ダブルバッファの実装

フィルタの方にダブルバッファの機能を追加。
バッファへアクセスする部分は、クリティカルセクションでロックするようにした。
で、ロックはCCritSec とCAutoLock を組み合わせることで、かなり楽に出来る。
CAutoLock のコンストラクタにCCritSec を渡せばロックされ、デストラクタでロックが解除される。
すごい楽チンです。
しかも、効率的なインラインコードに展開されるとか。
至れり尽くせりですな。

セマフォなんかもこういうふうに実装するといいのかもね。
解除し忘れとかなくなるし。

次はプレーヤー側の対応だな。

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

LightflowのI/Fをまとめる

Lightflowの各パラメータをクラスにまとめる。早く、I/F作って、ごりごりレンダリングさせてー。まあ、まずはLightwaveのデータをレンダリングできるようにしよう。で、サーフェイスとかパラメタいろいろいじって楽しむんだー。(子供のように楽しげに話す) かっけーって言うようなものを作るっすよー。
 でも、どんなI/Fにするかが問題だな。まずはファイル喰わせてレンダリングするようなのを作りたいと思っているけど、その次はパラメタいじってレンダリングしてって言う作業を手軽に出来るGUIが欲しくなってくるかも。最終目標はシーンをごりごりいじれるツールだな。後ネットワークレンダリングも。あー、わくわくしてくる。
 後、Yさんに教えてもらったのだがXSIがかなり安くなったとか。一番安いのは8万円弱。ちょっと買ってみたい気もする。でも先立つものが。。。お金入ったらまず豪速新PCを買いたいしなぁ

投稿者 Takenori : 06:40 PM | コメント (0) | トラックバック

アロケーターの集成化

アロケーターは今まで、newしていたが、集成にしても問題なさそうなので、集成にすることにした。
で、書き換えて動作確認。
問題なく動いた。

フィルタ側のソースコードを少し整理した。
次はダブルバッファリングの実装だな。
少し考えないと。

投稿者 Takenori : 04:54 PM | コメント (0) | トラックバック

終了時アクセス違反の調査

IGraphBuilderを最後にリリースしているのだが、どうやらこの部分でアクセス違反が起きているらしい。
なぜか、すでにリリースされてしまっているようだ。

集成の問題か!
もらったー!
やはり、集成の問題だった。
CBaseVideoRendererを継承したレンダーのコンストラクタで、CBaseControlVideoを継承したクラスをメンバに持っているので、CBaseControlVideo::CBaseControlVideo( NAME("Video properties"), pUnk, phr, &m_InterfaceLock, this ) と言うように初期化していた。
しかし、本来はCBaseControlVideo::CBaseControlVideo( NAME("Video properties"), GetOwner(), phr, &m_InterfaceLock, this ) と初期化しなければならない。
コンストラクタで渡されるpUnkは集成された所有者オブジェクトへのポインタと説明されている。
そして、pUnkがどこから渡されるかと言えばクラスファクトリだ。
さらに追うと利用者がCoCreateInstanceから渡たすものだ。
で、CoCreateInstanceではNULLと指定していた。集成なしということだ。
つまり、最初のように初期化すると集成なしとされる。
これがどういうことになるかというと、リリースした時メンバ変数をdeleteしようとしてしまう。
ま、おかしくなって当然ですな。
そして、本来は2番目の初期化方法のようにGetOwner()によって、集成もとのオブジェクトのポインタを得るわけだ。
そうすれば、参照カウンタは集成元のオブジェクトのものが使われるようになり、解放時もオーナーが解放されるようになる。
これで、万事O.K.と言うわけだ。


集成の説明 (間違っているかも)
複数のインターフェイスを1つのクラスに持たせる場合、多重継承が使われるが、多重継承を使いたくない場合というのは往々にしてある。
そんなとき、よくメンバにそのクラスを持ってしまうと言う方法がとられる。
そして、そのクラスが保持するインターフェイスが要求された時、そのメンバのポインタを返すことで要求を満たす。
これが集成である。
しかし、COMの場合、すべてのインターフェイスは参照カウンタを保持する。そして、参照カウンタが0になった時、そのオブジェクトはdeleteされる。
つまり、メンバ変数がdeleteされるという状況に遭遇してしまう。
このような状況を回避するため、集成されたオブジェクトはそのオブジェクトをメンバとして保持しているオブジェクトのポインタを保持し、参照カウンタへの操作は、その保持しているオブジェクトのものをコールされる。
つまり、集成する場合は、以上のようなルールに従わなければならない。
そして、このようなものを集成と言う。

以上のような形体以外の実装も存在するようだが、だいたい集成とはこんな感じです。

投稿者 Takenori : 02:06 PM | コメント (0) | トラックバック

DLL内の関数

DllGetClassObject や DllCanUnloadNow、エントリーポイントがないと思っていたら、BaseClassesの中にあった。
つまり、strmbasd.libの中に入っている。
この辺りは問題ないようだ。

COMのDLLサーバー内ではCoInitializeは使ってはいけない。(使っていなかった)

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

September 03, 2004

LightflowをC++から使おうと試す

DLし展開して出来たinlude の下にチュートリアルのソースをコピーしたソースファイルを置き、コンパイルする。
インクルードファイル内でエラー。
なんか、インクルードファイルがWWWの中にいるとか、仕方ないのでWWWをLightflowに置換する。
後、インクルードファイルをすべてVCのインクルードの中のLightflowへコピーする。
そしたら、iostream.hがないとか言われる。
iostreamに書き換えて、using namespace std;も追加する。
そしたら、iomanip.hがないとか言われる。
マニピュレーター用? たぶんいらないと思うのでコメントアウト。
で、とりあえずコンパイルは通るようになった。
でも、リンク時にいろいろとないと言われる。
どうやら、/link Lightflow.libが必要な模様。
で、やっとメイクできた。
実行したらエラー。
C++で組んでもやっぱり環境変数の設定はいるのね。
LIGHTFLOWPATH=C:Lightflow
LIGHTFLOW_SE_MEMORY=32000
LIGHTFLOW_VE_MEMORY=32000
PATH=%LIGHTFLOWPATH%
を設定。で、実行。
tgaイメージが出来た。GIMPで読める。
Lightflow.libも面倒なので、VCのlibフォルダにコピーしてしまった。

投稿者 Takenori : 11:38 PM | コメント (0) | トラックバック

プレーヤーの修正

今まで内部で持っていたレンダーフィルターをCoCreateInstanceで得るようにし、他にもいろいろと依存していた部分を書き換えた。
やっぱり、インターフェイスだけでつながるようにするとすっきりするなぁ。
で、デバッグは両方でいろいろとやらないといけないかと思いきや、プレーヤー側だけで出来る様子。(たぶん、レンダーフィルタがデバッグビルドだから)
でも、変。
うまくいかない。
これは少し時間がかかるかも。

ディスコネクトした時にデストラクタが呼ばれている。
なぜ?
と言うか、今まではなぜ動いていたんだ?
前はアロケーターをCComPtrで保持していたからか?
でも・・・
もう少し調査の必要がありそうだ。

アロケーターのReleaseがコールされる時の参照カウンタ値が違う。
CComPtrの場合、代入時にAddRefで参照カウンタがインクリメントされるが、アロケーターをCComPtrで保持しないようにしたから、Release時に参照カウンタ値がなくなり、Deleteされてしまうのか。
と言うことで、ピンのコンストラクタでアロケーターを生成した後、きちんとAddRefするように変更。
でも、newせずに単にメンバに持つって言うのはまずいのかなぁ。
いいような気もするけど。なんでこんな実装になっているのだろう? ピンはレンダーが普通にメンバとして保持しているのに。
ここから拾ってきた物をベースにしているのだが・・・
サンプルを見るとレンダーがアロケーターを持ってるしぃ。
まあ、だとしてもAddRefは必要なのかな。
でも、よく見るとnewしている意味がわからんな。

IBasicVideo::get_SourceHeightでアサートが出る。ピンが接続されていないとか。
レンダーのコンストラクタでCBaseControlVideo::SetControlVideoPinでレンダーの入力ピンを設定しておかなければいけないようだ。

とりあえず、シングルバッファーで普通に動くようになったが、CoUninitializeでアクセス違反が出る。
また、わかりづらいところで・・・
CoUninitializeの処理について調べないと。

投稿者 Takenori : 02:30 PM | コメント (0) | トラックバック

September 02, 2004

フィルタの修正

インターフェイスを追加しようとして、いろいろと入らないことが判明し、処理の書き換えを行った。
そのおかげでだいぶコードがすっきりした。
次はプレーヤー側の修正だ。
でも、そっちは結構大がかりかも。

投稿者 Takenori : 09:49 PM | コメント (0) | トラックバック

インターフェイスの変更(?)

レンダーからイベントを送るため、IMediaEventSinkをセットするメソッドを追加したいと思い、IDLファイルにメソッドを追記し、IMediaEventSink型を使うために、import "axextend.idl";を追加する。
と、やっていてふと気付く、フィルタはイベントを送るんだから、IMediaEventSinkははじめから持っているんじゃないかと。
調べると・・・あった。
CBaseFilter.m_pSinkだ。
IMediaEventSinkを設定する関数は無駄だったんですね。
で、作っていた物を書き換えて動作確認する。
問題なく動いた。
IMediaEventSink関連の処理は全くの無駄だった。(涙
無駄な処理を削除していくのもまた悲しい。
それはともかく、MediaTypeを取得する物もインターフェイスへ追加しようと思ったが、フィルターではなく、ピンの方のIPin::ConnectionMediaTypeで取得できることがわかったので、やめる。
まあ、これ関連の処理も全くの無駄だったんだけど、これはこれで処理は短くなっていたので良しとしよう。書き換えないといけないけど。
で、結局インターフェイスはそのままでいいことになった。

投稿者 Takenori : 09:32 PM | コメント (0) | トラックバック

September 01, 2004

とりあえずシングルバッファで作り、登録

とりあえず、シングルバッファで動作するようにし、フィルタをレジストリに登録する。
後、IBasicVideoの既定転送元矩形も作っておく。

登録は、
regsvr32 BRender.ax
と入力する。

ちなみに登録解除はこう
regsvr32 /u BRender.ax

で、CoCreateInstanceしてみたら、きちんとインターフェイスを取得出た。
でも、実際に使うにはいろいろと直さないといけないところがある。
いい感じになってきた。

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

COM内でのメモリ割り当て

COM内でメモリの割り当てを行う場合は、CoTaskMemAlloc / CoTaskMemFree を使わないといけないようだ。

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

perl2html

このページにperlに関する備忘録を作ろうと思っていたのだが、perlをHTML化するのが面倒だった。
当然、ツールを作ることを考えていたのだが、flexを使おうと思っていた。
しかし、すでに似たようなツールがあるのではないかと探したところ、やはりあった。
ここだ。
perlで書かれている。
スタイルシートが使われないことや、少し気に入らない部分を書き直した。
書き直したソースはこんな感じだ。

#!/usr/bin/perl
#
# perl2html.pl

# キーワードのリスト
# ハイライトしたいキーワードをここに追加できる
@keyword = qw (abs accept alarm and atan2 bind binmode bless caller chdir
 chmod chomp chop chown chr chroot close closedir connect continue cos
 crypt dbmclose dbmopen defined delete die do dump each else elsif endgrent
 endhostent endnetent endprotoent endpwent endservent eof eq eval exec exists
 exit exp fcntl fileno flock foreach fork format formline getc getgrent getgrgid
 getgrnam gethostbyaddr gethostbyname gethostent getlogin getnetbyaddr getnetbyname
 getnetent getpeername getpgrp getppid getpriority getprotobyname getprotobynumber
 getprotoent getpwent getpwnam getpwuid getservbyname getservbyport getservent
 getsockname getsockopt glob gmtime goto grep hex if import index int ioctl
 join keys kill last lc lcfirst length link listen local localtime log lstat
 map map mkdir msgctl msgget msgrcv msgsnd my next no oct open opendir or
 ord our pack package pipe pop pos print printf prototype push quotemeta
 qw qx rand read readdir readline readlink readpipe recv redo ref rename
 require reset return reverse rewinddir rindex rmdir scalar seek seekdir
 select semctl semget semop send setgrent sethostent setnetent setpgrp
 setpriority setprotoent setpwent setservent setsockopt shift shmctl
 shmget shmread shmwrite shutdown sin sleep socket socketpair sort
 splice split sprintf sqrt srand stat study sub substr symlink syscall
 sysopen sysread sysseek system syswrite tell telldir tie tied time
 times truncate uc ucfirst umask undef unlink unpack unshift untie
 use utime  values vec wait waitpid wantarray warn while write);

# ファイル名が入力されたかどうか
$input = $ARGV[0];
if ($input eq ""){
    print "Input PERL script name.\n";
    exit(0);
    }
# ファイルのオープン
open INP, "$input.pl";
print "<p class =\"csource\"><br />\n";
foreach $line (<INP>){
    chomp $line;
    # タグの変換
    $line =~ s/&/&amp;/g;
    $line =~ s/"/&quot;/g;
    $line =~ s/</&lt;/g;
    $line =~ s/>/&gt;/g;
    # タブをスペースに変換
    $line =~ s/\t/&nbsp;&nbsp;&nbsp;&nbsp;/g;
    # スペースをスペースに変換
    $line =~ s/\s/&nbsp;/g;
    # コメント行
    $line =~ s/#.*/\<span class=\"ccomment\"\>$&\<\/span\>/;
    # 引用
    $line =~ s|(&quot;[ -~]*&quot;)|<span class=\"cdoublequotation\">$1</span>|g;
    # サブルーチン
    $line =~ s|(&amp;[\w]+)|<span class=\"ckeyword\">$1</span>|g;
    $line =~ s|^(sub [\w]+)|<span class=\"ckeyword\">$1</span>|;
    # キーワード
    foreach $keyword (@keyword){
        $line =~ s|\b$keyword\b|<span class=\"ckeyword\">$keyword</span>|g;
        }
    print "$line<br />\n";
    }
# 終了メッセージ
print "</p><br />\n";
exit (0);

単純な置換なんで、うまくいかないこともあると思うが、あんまり気にしないことにした。
と言うか、すでにいろいろとおかしいかも。キーワードリストの中のキーワードを強調してしまっていたりするし、&をすべてサブルーチンコールにしてしまっているし、エスケープしてるのに文字列と見なしてるし、置換の中の#をコメントの開始と見ているし。
やはり、ある程度構文を解析しないと完全にはいかないかな。flexでスタート条件などを使えばうまくいきそうな部分も多いけど。
でも、だいたいの場合はうまくいくからいいでしょ。

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

flex / bisonの導入

flex/bisonはじめて8時間以内FAQを見て導入。
bisonとflexはSourceForge GnuWIn32 File Listからとってくる。
以前、インストールした時はいろいろと足りなくて、いろいろ入れた気が・・・。
で、普通にbison.simpleとかないっすね。
バージョンが
bison 1.875
flex 2.5.4a
となっていたので、参考にしたページよりかなりbisonのバージョンが上がってますね。
とりあえず、解凍して出来た物をそれぞれC:\bisonとC:\flexに入れて、それぞれのbinへパスを通す。
で、動きやがれ!
動いた。一部コンパイルでエラーが出ているが、昔のバージョンから何かが変わって、指定方法が違うようになってしまったからだろう。
特に問題はないことにしよう。
bisonよりflexが使いたくて入れたわけだし。
なので、うまくいかなかったら、また調べることにする。

投稿者 Takenori : 03:55 PM | コメント (0) | トラックバック

IRendererBufferAcces関連仕様

Set系は、基本的にフィルタグラフを作ってから、再生を開始するまでに行うようにする。
再生中の呼び出しは動作保証されない。
再生が開始された時に、Setが呼ばれていない場合は、TBufferRendererが自分でメモリを割り当てる。
特にメモリを渡す必要がない場合はこの方法を使用する。
TBufferRendererが確保したメモリをGetし、そのメモリを再度Setしてはいけない。TBufferRendererは、Setによってメモリが設定されると、自分で確保したメモリは解放するので、不正アクセスが発生してしまう。
当然、TBufferRendererが確保したメモリをGetし、そのメモリを解放するなどという暴挙に出てはいけない。
buffにNULLを入れて呼び出すと、sizeに要求されているサイズが返ってくる。
TBufferRendererはフレームが更新された時、EC_UPDATEを投げる。利用者はEC_UPDATEを受け取ったら、GetFrontBufferし描画などの処理を行う。

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

インターフェイスを加えてビルド

IRendererBufferAccesを継承するように書き換えて、メソッドを以下のように追加する。
STDMETHOD( SetFrontBuffer )( BYTE *buff, long *size);
STDMETHOD( SetBackBuffer ) ( BYTE *buff, long *size);
STDMETHOD( GetFrontBuffer )( BYTE *buff, long *size);
STDMETHOD( GetBackBuffer ) ( BYTE *buff, long *size);
STDMETHODと言うマクロは、CでもC++でも使えるようにする物だが、他が思いっきりC++で書かれているので、全然意味なしです。
完全に共通にするにはマクロ バリバリにしないといけません。
ま、特に気にしなくてもいいでしょう。Cで書くことはほとんどないでしょうし。
定義は、とりあえずS_OKを返すだけにしておきます。
HRESULT TBufferRenderer::SetFrontBuffer( BYTE *buff, long *size) { return S_OK; }
で、ビルド。
きちんとビルドされた。
次はいよいよ実装だ。

投稿者 Takenori : 12:46 AM | コメント (0) | トラックバック

Total : Today : Yesterday :