« September 2004 | メイン | November 2004 »

October 31, 2004

属性設定用UI

コマンドメニューで残っていた分を追加。メニューだけでも面倒なのに、UIとなると・・・
UIはいくつかは使い回せたり、属性なしも結構あるからだいぶマシかもしれないけど。

属性設定用のUIを作っていく。やっと10個分だ。
このUIとグリッド部、ドキュメント部とのハンドリングについて考える。
以前も何か考えていたなぁと思い、クラス図を見るとやっぱり考えていた。
しかし、そのときはModel/Observerを知らなかったので、単なるクラスとして考えていた。
なので、再考中。
基本的なやりとりは、スクリプトを介すことで汎用的なインターフェイスにしようと思ったが、UIのいくつかは共通化している。
共通化しているUIは単なる有効/無効、ファイル選択だけを属性に持つものだ。
共通化しているUIで異なるスクリプトになるのもある。
クラスを受け渡し!この文章を書いていて気付いた。
文書化は告知や報告など以外に思考の整理としてなかなか役立つ。
誰かに何かを説明しようとしたら当然理路整然としていなければならない。頭の中では筋が通っていると思いこんでいるものは意外と多い。
文章化すればこのような矛盾に気付く。
また、なぜか新しいアイデアなどが思い付くこともある。
人に説明しようとすることはいろいろと役立つことが多い。
話がそれてしまったので元に戻そう。
グリッドと属性設定UIとのやりとりはクラスを受け渡す方法にしよう。
パラメタを持つクラスは1つのクラスから派生させれば、インターフェイスは共通化できる。
ドキュメントの方とはどうするか?
同じような方法をとっても良いが・・・ バケツリレーのような方法でやろう。
つまり、属性設定UI→グリッド→ドキュメントといった具合に受け渡していく。
属性設定UI、グリッド間はクラスでやりとり、グリッド、ドキュメント間はスクリプトとしよう。
グリッドは直接スクリプトを編集することも出来るようにするのでその方が都合がよい。
構造を考えていくと、グリッドがドキュメントへのアクセスを一手に引き受ける形になりそうだな。
I/Oは限定されている方がやりやすい。

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

Bフレッツ+プロバイダの申し込み

Bフレッツ+プロバイダの申し込みを昨夜行った。
現在は書類が送られてくるのを待っている状態だ。
それでプロバイダは固定IPがもらえるところにしたのだが、そのサービスはとりあえず2005年6月までのようだ。(初めは2004年12月までとしていたようだが、延長されていた)
調べたところによると、IPv6切り替えがあるためどこも似たような状況らしい。
先行き不透明。
ややこしい時期に始めてしまった。
でも、IPv4でIPv6をトンネリングするサービスもあるようなので、いろいろと実験は出来そうだ。
将来的に切り替わる予定なのだから早めに準備を進めておくに越したことはない。
とは言っても、すでに出遅れている気もするが。。。
前調べたときは、普及価格帯でIPv6が使えるルーターはまだ出ていなかったと思うが、今ならあるのだろうか?
それよりも、既成製品は諦めてLinuxでルーターマシンを組んだ方が良いだろうか?
自由度で言えばLinuxに軍配が上がるが、手軽さではやはり既成のルーターだろうなぁ。
しばらく、IPv6 Magazineなどを読み漁るか?って、休刊してるし。

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

October 30, 2004

Model/Observerの実装

Model/Observerを実装した。
各タグの属性設定用ダイアログを作る。
数が多いので大変だ。
まだ、5個ぐらいしかできていない。

グリッドのOnRowMovedイベントが来ない?
optionのgoRowMovingをtrueにしているのに。
他に何かしないといけないことがあるのだろうか?
よくわからなかったので、OnSelectCellで代用することにした。
ARowとプロパティのRowが異なっていたら処理するようにした。
これで、現在の行のタグに応じてダイアログ表示が切り替わるようになった。

最終行のコマンドを設定したら行が増加するようにした。
command列の時、Enter orダブルクリックでコマンド選択メニューを表示するようにした。

ドキュメントの方で状態を持った方がスッキリする気がしてきた。
Boarlandのサイトにあるコンポーネントは、ドキュメントを変更した時に、表示を更新するようになっている。
Modelはデータモジュールに置くように説明されている。
で、その通りにした。
このような構造にすると言うことは、データモジュールにドキュメント変更用のメソッドを持たせ、そのメソッド経由でデータを変更し、それと同時に表示更新を行うことだと考えられる。
つまり、データの変更は必ず、データモジュールのメソッド経由で行われることになる。
しかし、現在はフォームの方でカレントコマンドの参照を持ち、それを直接変更している。
そうした方が都合がよいことが多いと考えたためだ。
あー・・・うーん。
フォームでカレントコマンドへの参照を持つのは、別に問題なさそうだ。
列が移動するなどのコマンド確定動作が行われた時に、データモジュール側に通知すればいいだけか。
シーンはどうする?
シーンの切り替わりも一元管理したい。
もう一組Model/Observerを追加すればいいのか!
一度、同期して変更を加えたいものをリストアップした方が良いかもしれないなぁ。
でも、今のところは上記の2つだけかな。

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

October 29, 2004

構文解析

flexはやめよう。
動的解析をするのならインテリセンスが欲しい。
出来れば、状態依存型のほうがいい。
簡単な説明が付与されれば最高だ。
だが、確定済みのスクリプトと入力中のスクリプトは性質が異なる。
flexでの実装もあった方が良いか。
この問題は入力中スクリプトの解析器をもっと詰めてから検討しよう。

リストの全アクセスはどうしよう。
インデックスで順番に見ていくのは遅い。
イテレーターが欲しくなる。
追加しよう。
基本的に読むだけだから、コンストイテレーターだけにしておくか。

現在アクティブになっているシーンはどこが押さえるべきか?
前にドキュメントの方で状態は持たないことにしたが・・・

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

October 28, 2004

ドキュメント管理部

とりあえず、昨日決めた通りstd::listをラップしたようなクラスを作成。
前回アクセスしたイテレーターを保持しておくのと、要素を位置で取得できるようにした。

各コマンドはどのように保持しよう?
各コマンドごとにクラスを作り、保持するのではも良いが、スクリプトをそのまま保持し、毎回動的にパースするほうがいいかな?
ダイアログでの入力も、スクリプトでの直接入力も受け付けるようにしたいので、パーサーはどのみち必要になる。
毎回解釈するようにしよう。

パーサーはflexのみで十分かな?
TJSのを作るとなると、bison(yacc)を使った方が良い気もするが・・・
とりあえず、flexのみで予約語どべーって並べて、力業で作ることにしよう。

でも、表示の更新はどうしよう?
グリッドをすべて書き換えるのはさすがに厳しい気もするが・・・
更新したウィンドウを覚えておき、それによって振り分けるか?
挿入処理があった時はどうする?
全部書き換えてしまうのが楽で、間違いも少ないが・・・
いいや、全部書き換えでやってみよう。
ダメならダメで考えよう。

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

October 27, 2004

ドキュメント管理部の状態

ドキュメント管理部分は状態を持つかどうか。
ドキュメントは逐一更新されるので、必然的に状態を持っていることになるが、その状態ではなく、アクティブなタグ(以下、コマンドと呼ぶ)を認識するかどうかだ。
UIは、エクセルのようなセルとタブを持っている。
各行は一つのコマンドと対応し、タグはシーンごとに作ることにする。
その関係上、アクティブなシーンとコマンドが存在することになる。
当然、ドキュメント管理部は状態を持たない方がスッキリする。
UI側が更新時に毎回位置を指定すれば事足りる。
気になるのは、やはり処理速度だ。
ドキュメント管理部分は挿入や削除などに備え、リストで管理することにしようと思っている。
リストの場合ノードが多くなればなるほど、後ろになればなるほどアクセスが遅くなる。
つまり、コマンドが多くなった時、処理が重くなることになる。
うーん、ま、いっか。
シーンを分ければ何とかなるし、重くなった時はリスト自体が前回アクセスされたノードを保持するようにすれば、解決できそうだ。
よし、ドキュメント管理部分は状態を持たない方向にしよう。
その方がスッキリする。

リストは初めstd::listで行く予定だったが、TListは配列アクセスが出来て楽そうだ。
そこで、TListに気持ちが傾いたのだが、前回アクセスされたノードを保持する機能を持たせることを考えると、よくわからないTListよりも、std::listの方が良い気がしてきた。
やはり、std::listでやってみるかな。

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

BCC Document/Viewの簡単な説明

次の文章を読むよりも、Boarlandのサイトの方が詳しいです。
でも、何回もコードを追うのは面倒なので、簡単な流れを備忘録として以下に記しておくことにします。

Model/ObserverコンポーネントはTModelとTObserverで構成される。
TObserverはビューにTModelはドキュメントに相当する。
データモジュールにTModelを配置し、このデータモジュールでドキュメント(データ)を管理する。
フォームにはTObserverを配置し、TObserverのOnUpdateプロパティに表示更新用のイベントを設定する。
ドキュメントの更新が行われた時は、TModelのNotifyをコールするようにする。
TModelのNotifyは、TModelが管理しているすべてのビュー(TObserver)のDoUpdateをコールし、表示の更新を促す。

至ってシンプルですな。
まあ、表示の更新部分はドキュメントをリロードし、表示を更新。
データ入力を受け付けるところは、逐一ドキュメントへ設定。
回りくどいので、少々重いのではないかという気もしないでもないが、内部の処理に比べて表示の更新は遅いので全然余裕だろう。
表示の更新が頻発するのは気がかりだが、人の入力速度なんてたかだかしれてるしな。
とにかくやってみないことには何とも言えないな。

次はデータ管理部分の構造を考えよう。

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

October 12, 2004

DirectX9で遊ぼうとする

3DのPRGのシステムを作ろうと思って、まずはDirectXのスキニングサンプル(人が歩いているやつ)を改造して、自分で動かせてナビゲーションメッシュで動きを制限できるようにしようと考えたのだが・・・
3Dまともに動かないっす。
とりあえずサンプルをビルドして動かしたら、ハードウェアがないとかでリファレンスドライバで動く始末。
リファレンスドライバはソフトウェア処理だから・・・1FPSも出ていない。
そういや、開発用マシン買うときにリアルタイム3Dのことはあんまり考えてなかった。
まあ、最近リアルタイム3Dでゲームを作るぞと思って、買い替えを考えていたから大丈夫といえば大丈夫だけど、しばらく3Dのプログラムをいろいろといじって遊べないのは痛い。
そこで、もう一台のマシンで動くかどうか試してみることにしたが、エラーが出て起動しなかった。
もう一台のマシンはGeForce2 MXなので、ある程度は動くと思うのだが、ドライバのバージョンが古いせいだろうか。
ドライバのバージョンを上げたいのだが、このマシンはテレビを見るのにも使っていて、以前に新しいドライバに変更したらテレビを見ることが出来なくなって、古いのに戻した記憶がある。
やはり、新PC待ちかなぁ。

最近、テレビをPCで見るのは少々きつく感じてきたので、これの購入を検討中。
と言うか、まだ買えないので、買えるのを待っている状態。
出たら、即買いかも。
これを買えば、テレビを見ているマシンのドライバを新しく出来るので、このマシンを使って動かせなくはないかな。

どっちも、ああ、なんてこったって感じだな。

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

ボタン絵結合ツール

吉里吉里のボタン絵には通常、押下、選択の3つを横に並べたものが必要だ。
単純に横にくっつけると言うのは、プログラムでは簡単だが、普通のペイントツールを使うとかなり面倒だ。(単純に並べるだけなのに、ドットがずれないかどうかに神経を使う)
ペイントツールでこのような機能を持ったものが存在するかもしれないが、知らないので作ることにした。
仕様は、
フォルダをD&Dすればその中にあるBitmapをすべてくっける。
くっつける時のルールは"名前.bmp", "名前_d.bmp", "名前_s.bmp"と言う名前のファイルを一組として、横にくっつくていく。
くっつけられた画像は、D&Dされたフォルダの下にbuttonフォルダを作り、その中へ"名前.bmp"というファイル名で出力する。
とする。
で、なにげにC++Builderでボタンとテキストボックスをくっつけて、D&Dのハンドラ書いて、FindFirstで"*.bmp"を列挙するところまで作った。
そして、くっつける処理はGDI+でも使ってみようと思い、ヘッダーをインクルードするとエラーが山のように出てくる。
あらら。
すごく行き当たりばったりだが、C#で.Net Frameworkを使い作る方向に変更。
少しC#に興味があったからだ。
で、まずはフォームにボタンやエディットボックスを置く。
でも、これはC++Builderに近いなぁ。
これは意外といいかも。
そして、D&Dの処理を調べる。
テキストをD&Dするサンプルがすぐに見つかったので、それを適当に改造して、フォームに対するドロップを処理するようにしようとするが、よくわからない。
そもそも、C#でプログラムを一度も組んだことがないので、文法などもよくわかっていない。
Cを半音上げたものだから、C#って聞いていたので、Cと似たようなものかなぁと思っていたのだが、それほどすんなりとは行かないようだ。
コードの一部に波線が引かれていたので、カーソルを置くとツールチップで説明が出たが、よくわからない。
C#独特の記法のようだ。
C#入門ぐらいは読まないとダメかな。

今やるのはちょっと面倒臭いなぁと思って、どうしようと考えていたらImageMagick(PerlMagick)を使うことを思い付く。
PerlMagickは使ったことがないけど、これなら簡単に出来そうな気がした。(根拠なし)
で、ImageMagickのページのAPI->PerlMagickを読んで適当に作ってみる。(このページの日本語訳ないかなぁ?)
少し悩むが、意外とあっさり出来た。
次のコードで、'b_fast.bmp', 'b_fast_d.bmp', 'b_fast_s.bmp'の3つファイルを横にくっつけて、x.pngという名前で出力する。

use Image::Magick;

$image = Image::Magick->new;
$x = $image->Read('b_fast.bmp', 'b_fast_d.bmp', 'b_fast_s.bmp');
warn "$x" if "$x";
$p = $image->Append(stack=>'false'); # stack falseでLeft to Rightでくっつける
#warn "$x" if "$x";
$x = $p->Write('x.png');
warn "$x" if "$x";

やはり、PerlMagickは便利だ。これから少しずつ使っていきたいなぁと思う。
それはともかく、ここまで出来れば後はいつも通り書けばいい。
次のような感じ。

use Image::Magick;

foreach( glob('*.bmp') ) {
 if( /.+_d\.[bB][mM][pP]/ ) { next; }
 if( /.+_s\.[bB][mM][pP]/ ) { next; }
 /(.+)\.[bB][mM][pP]/;
 $base_name = $1;
 {
  local($image,$x,$p);
  $image = Image::Magick->new;
  $x = $image->Read($base_name.'.bmp', $base_name.'_d.bmp', $base_name.'_s.bmp');
  if( "$x" ) { warn "$x"; next; }
  $p = $image->Append(stack=>'false');
  if( "$x" ) { warn "$x"; next; }
  $x = $p->Write($base_name.'.png');
  if( "$x" ) { warn "$x"; next; }
 }
}

buttonフォルダは作らないが、pngで出力するようにしたのでかまわないだろう。
PerlMagickを使えば楽勝だったな。

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

October 11, 2004

リッチテキストエディットを検討

メッセージ編集部分はリッチテキストエディットで簡単に出来るかなぁと思っていたが、調べるといろいろと面倒な感じがしてきた。
やって出来ないことはないと思うが、同期や操作性のことを考えると、専用のコンポーネントを作ったほうが良い気がしてきた。
TCustomMemo辺りから派生させて作ればいけそうだ。
そして、各文字の属性の管理はフライウェイトパターンかなにかを使えばよいのかな?
デザインパターンの本を参照したいところだが、生憎すでに引越しの梱包済みで、出すのが面倒だ。
ま、この部分はすぐに必要と言うわけではないので、少し後回しにしよう。

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

クラス図を書く

クラス図を書いてみた。
やはり、各ビューを同期させるには、どこかで一元管理した方が作りやすい。
そして、そこへデータの格納や、各ビューへの反映処理を入れることにする。
Doc-Viewアーキテクチャのような感じだ。
でも、Builderはこれをサポートしていないが、確かHPにその回答が書いてあったはず。
見てみると・・・ なるほど、非ビジュアルコンポーネントとして実装するわけね。
これはなかなかよい方法だな。
この方法で実装しよう。
クラス図も書き換えないとな。

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

October 10, 2004

行き当たりばったり

メイン編集画面は上に属性設定画面、下にグリッドで行単位に編集するようなスタイルとし、行き当たりばったりで作っていく。
まずは、コンフィグで設定する項目をダイアログ化しようと作っていくが、数が多く後回しに。
で、次はグリッドと属性設定画面の連携部分を作っていくが・・・ やはり、適当に作っていく限界にぶち当たる。
各画面が同期して変更されて行くスタイルにするには、やはりある程度検討が必要だな。
と言うことで、明日はクラス図でも描こうと思って今日は終了。
現時点でも、そこそこ連携して動いているんだけど、完全とはいかないな。

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

October 06, 2004

プロセスが残る問題への対処

以前、プロセスが残る問題の対処を行ったが、あれで完璧というわけではなかった。
まだ、タイミングによってプロセスが残ってしまうことが判明。
調査すると、DoRenderSample 内でフィルタグラフのIMediaSeeking を使用する箇所で返ってこなくなってしまうようだ。
フィルタグラフはマルチスレッドで動作しており、Stop がコールされても、タイミングによっては、DoRenderSample がコールされてしまうようだ。と言うか、ほとんどの場合、DoRenderSample がコールされてしまう。
そして、その中でフィルタグラフのIMediaSeeking を使うわけだが、すでにdelete中のため、何らかの理由でIMediaSeeking のメソッドがリターンしないようになってしまうようだ。(内部がどのようになっているかわからないので正確な理由は不明。)
そもそも、この時点では単にStopへステートの遷移中なのだから、IMediaSeeking のメソッドぐらい使えても良さそうなものだが、使えない。もしかしたら、デッドロックが発生しているという可能性もある。
レンダーフィルタは下記のようないくつかのクリティカルセクションを使用して動作しているが、それらの取得順序の違いによって・・・ いや、その可能性は低いか。
・m_InterfaceLock フィルタ状態のロック。
・m_RendererLock ストリーミングのロック。
それよりも、フラグの問題かもしれない。レンダーフィルタがもつフィルタは多い。っていうか、内部動作のシーケンス図クレーって感じだ。
BaseClassesはソースが公開されているので、CBaseRenderer などのシーケンス図を書こうと思えば書ける。でも、フィルタグラフのところは不明なので書けない。(もしかしてどこかにあるのかな?)
まあ、結局のところよくわからないのでいろいろと試したが、変なところでフリーズしたりしてうまく行かなかった。
なので、方法を変更することにした。

その方法は次の通り
ストリーミング開始時にコールされるメソッド内でフィルタグラフのIMediaSeeking を使用して、開始フレームを記録する。
レンダリング前にコールされるメソッド内で、自身のフィルタのIMediaSeeking を使用してストリーミングタイムを取得し、記録している開始フレームを加算したものを現在のフレームとみなし、メディアサンプルにメディアタイムとして設定する。もし、自身のIMediaSeeking が使用できない場合は、ストリーミングが開始されてからレンダリングしたフレーム数とドロップしたフレーム数を加算する。ただし、ドロップしたフレーム数はより上位のフィルタでドロップされたものまではわからないので、若干精度が劣る。
そして、DoRenderSample 内でメディアサンプルからメディアタイムを取得し、それを現在のフレームとして使用する。
以上のような処理に変更すると、プロセスが残る問題はなくなった。
ただし、現在のフレーム番号の精度は少し落ちているものと思われる。

この対処でも、完全にこの問題に対処できたとは限らない。
もし、CBaseRenderer::OnStartStreaming が別スレッドコールされてしまうと、同じような問題が発生する可能性がある。しかし、CBaseRenderer::OnStartStreaming を可能な限り追ったところ、CBaseRenderer::Run からコールされているようだ。これが同じスレッドなら・・・
そうだ、GetCurrentThreadId で調べればわかる。
調べるとPlayのコールもととOnStartStreaming のスレッドは異なる。
しかし、OnStartStreaming とレンダリングを行うスレッドも異なった。
結局わからないのか。
でも、フィルタグラフとOnStartStreaming のコール元スレッドが同じ可能性は少し高くなったかも。
もし、スレッドが異なっていたとしても、この問題が発生するのはごくまれだ。(と言っても、起こる可能性があるものは起こってしまうものだけど)
まあ、たぶん同じスレッドでしょう。
他に調べる方法は思い浮かばないし、この問題は解決としておこう。

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

机上デバッグとコメント整備

机上デバッグしつつ、コメントを整備する。

机上デバッグで、以下のようなものを修正。
メモリリークが発生する可能性があったコードを修正。
冗長なコードを修正。
不要なコードを削除。
発生することはない不具合を修正。


修正後念のため、確認用スクリプトを走らす。
問題なし。


思い出した注意事項
セグメントループとピリオドイベント、ループ、モード、描画対象レイヤーはオープン時に初期化されない。

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

October 05, 2004

position/frameプロパティの確認

position/frameプロパティへの値設定の確認を忘れていたので行う。
positionは何事もなかったが、frameはうまく行かなかった。
昨日のピリオドイベントの修正でデグレードしてしまったようだ。
修正して動作確認。
きちんと動作した。

後、pauseも確認していなかったので確認。
うまく行かない。
確認すると、pause状態の処理が全くなかった。
playで再開できるかなぁと、安易に考えていたのだが、TJSのコードを見るとそう言うわけにはいかないようだ。
resumeとかを追加してしまうかなぁ。それより、playの中にpause状態の扱いを追加した方が良いかも。
で、playの中にpauseの扱いを追加。
問題なく再開できるようになった。


うーん、やはり一気に全部チェックするスクリプトを書いておいた方が良いな。

ざっとスクリプトを書いた。
チェックした項目は次の通り
レイヤー描画
音あり/なし MPEG/AVI
close
open
play
stop
pause
rewind
prepare
segment loop
cancel segment loop
period event
cancel period event

loop プロパティの設定/取得
frame プロパティの設定/取得
position プロパティの設定/取得
fps プロパティの取得
numberOfFrame プロパティの取得
totalTime プロパティの取得

period event 待ち


オーバーレイ
上述のレイヤー描画と同等。
ただし、セグメントループとピリオドイベント、prepareは使用できないので確認していない。

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

October 04, 2004

AVIの確認/オーバーレイの確認

音あり/なしのAVIファイルをレイヤー描画で確認した。
何事もなく再生できた。

音あり/なしのAVIファイル、音あり/なしのMPEGファイルをオーバーレイでも確認。
問題なく再生できた。
セグメントループと、ピリオドイベントはオーバーレイでは使えないので、確認はしていない。

とりあえず、これで一通りの基本動作は確認した。

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

ピリオドイベントと無音MPEGの動作確認

まず、ピリオドイベントで忘れていたものを追加。
rewind がコールされた時か、frame にイベント発生フレームよりも小さい値がセットされた時に、イベント発生抑止を解除するようにした。
一度だけしかイベントを送らないというのも忘れていたので、追加した。

1分ぐらいの無音MPEG(.mpv)ファイルを再生して、ピリオドイベントで字幕を変化させるスクリプトをテストしてみる。
どうさせると、いきなりフィルター接続でエラーが返ってくる。
デバッガーで追うと最初のMPEG1スプリッターで、ピンを接続する際、適切な中間フィルタが見つかりませんでしたと言う、エラーが返ってきて失敗していた。
拡張子をmpgにし動作させると、そこは通り、DirectSoundフィルタを接続するところで失敗する。
どうやら、メディアタイプをMPEG1Videoとするのがまずいようだ。
なので、拡張子が.mpvとなっていても、MPEG1System とすることにし、DirectSoundフィルタの接続で失敗したら、音がないものとみなして、DirectSoundフィルタを接続しないような作りに変更した。
また、ついでにAVIの場合も同じような作りにしたので、音無しAVIにも対応したはず。
この修正によって、音があってもなくても拡張子は.mpgとして、内部で判断するようになった。
これで、.mpgでも、.mpvでもどっちでも良くなった。
ただし、MPEG1VideoCDの.datは確認していない。と言うか、ビデオCDは持っていないので確認できない。
ちなみに、MPEG1VideoはTMPGEncで作ったので、一般的なファイルになっているはず。

ピリオドイベントの方は1発でうまく動いた。

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

ストリーム タイムを追う

時間について少し整理する

基準タイム
基準タイムは、基準クロックから返される絶対タイムである。

ストリーム タイム
ストリーム タイムは、グラフが最後に実行を開始したときを基準に定義される。
・グラフが実行しているときは、ストリーム タイムは、基準タイムから開始タイムを差し引いた値に等しい。
・グラフがポーズしているときは、ストリーム タイムはポーズされたときのストリーム タイムに留まる。
・グラフが停止しているときは、ストリーム タイムはゼロである。
・シーク処理後には、ストリーム タイムはゼロにリセットされる。

タイム スタンプ(サンプルタイム)
タイム スタンプは、ストリーム タイムで示されるサンプルの開始タイムと終了タイムを定義する。タイム スタンプは、プレゼンテーション時間と呼ばれることもある。

メディア タイム
メディア タイムは、シーク可能なメディア内のサンプルの本来の位置 (たとえばディスク上のファイル) を指定する。ビデオの場合、メディア タイムはフレーム番号を表す。


シーク処理後には、ストリーム タイムはゼロにリセットされるって、あかんやん。
でも、IMediaSeeking::GetCurrentPosition を使えば正しい位置が返ってくる。
だから、IMediaSeeking::GetCurrentPosition を使えればいいのだが・・・

調べるとちょうどいいのがあった。
CBaseRenderer::GetMediaPositionInterface
フィルタの IMediaPosition および IMediaSeeking インターフェイス ポインタを取得する。
前調べた時はフィルタグラフにばかり目がいって気付かなかった。
じゃ、さっそくこれを使ってみよう。

だめだ、CBaseRenderer::GetMediaPositionInterface で返ってくるインターフェイスからIMediaSeeking::GetCurrentPosition で時間を取得しても、ストリームタイムが返ってくる。

CBaseFilter.m_pGraph がフィルタグラフをおさえている。
このフィルタグラフにクエリーをかけてIMediaSeeking インターフェイスを取得すればうまくいきそうだ。
とりあえず、コンストラクタで・・・ って、コンストラクタがコールされる時にはまだフィルタグラフに参加していないからダメだ。
DoRenderSample で未取得なら取得するようにした。
で、動作チェック。
キターッ!
きちんと取得できた。
ループもきちんと行われている。

再生が終了してしまうと言う問題だが、あれは勘違いだった。
最終フレームに到達しても再生は終了しないんだった。
そして、シークしてまだ残りフレームがある位置に移動すると、再びヘッドが進み出す。
なんの問題もなかった。


2つほど不具合を発見し修正。
ダブルバッファリングにしたはずが、一部ずっと同じバッファを指していたために、無駄なメモリコピーが発生してしまっていた不具合を修正。
なんか重くなったような気がするなぁと思っていた原因はこれだったのか。

ループを設定して、KAGスクリプトが何もない状態になった時に終了するとプロセスが残ってしまう問題を発見。
tTVPDSMovie::ReleaseAll() のm_MediaControl->Stop(); が返ってこなくなっていた。
tTVPDSLayerVideo のデストラクタでもReleaseAll() をコールするようにしたらそのようなことはなくなった。
ReleaseAll() は何度呼んでも良いようにしているが、なんでそんなことが?
呼び出し過程で問題が発生するような呼び出し順序にしているつもりはなかったのだが・・・ 違う、デストラクタで消えていく順番が怪しい。
派生側が持っているメンバが先に消えてしまっていてどうしよう?状態になりそうだ。
そして、そのメンバにはフィルタグラフに参加しているグラフのインターフェイスもあるし。
でも、まあこれでプロセスが残る問題は解決。

以上で、セグメントループの基本的な動作確認は終了。

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

IMediaSeeking::SetPositions の怪

IMediaSeeking::SetPositionsでシークした際、その移動先が0フレームでなくても、CBaseRenderer::GetSampleTimesで返ってくる位置は0からになっている様子。
そのせいで、途中のフレームにジャンプさせるとうまく行かないようだ。
でも、そしたら・・・ なんかおかしい。
ここはもっと調査しないといけないなぁ。

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

October 03, 2004

BCBのコードをVCでデバッグしたい

デバッガはやっぱり、BCBではなく、VCの方を使いたい。
でも、いろいろと調べていくとBCBは独自のデバッグ情報を吐くらしい。
弱った。
無理なのだろうか?

ProgrammingのDebugging aidsにMs-dbgとか言うものがある。
これ使えないかなぁ?

pdbファイルを作ることは出来たけど、これはVCでは使えないのだろうか?
もっと調べないと良くわからない。

関係ないけどメモ
Open Watcom C/C++と言うのがあった。
消えたと思っていたWatcom C/C++はフリーになったのだろうか?

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

セグメントループのテスト&デバッグ

だいぶ前に組み込んでおきながら今更動作確認。
いきなりTJSで引っかかる。
オブジェクト型を期待しているところに(int)0がきているとかどうとかでる。
初めKAGの方がおかしいのかと思ったが、コーンソールの表示を見るとMovie.tjsに問題がある様子。
オーバーライドしておきながら、親クラスのメソッドではなく、自分のを呼んでしまっている様子。
初めはよくわからなかったので、いろいろと調べていろいろと直す。(実はTJSについてあんまり知らなかったり)
そして、動いたと思ったら、今度はDLL側に問題があり、セグメントループがうまく動かず、調べる。
IMediaSeeking::SetPositions の使い方を勘違いしていたと思い直すが直らず、再度よく見るとそれは勘違いで元のがあっていたようなので、元に戻すと、なぜかうまく動くようになる。謎謎謎・・・
ビルドを忘れていたりしたのだろうか?
よくわからん。
でも、DirectShowは時々こういうことがあるような気がする。いったい何なんだろうか?

残っている問題
最終フレーム付近でセグメントループを使おうとしたら、シークさせるよりも先に再生が終了してしまい、うまくループさせられない。
これは、ダブルバッファリングしているので、内部処理よりも描画は1フレーム遅れている上に、内部的に数フレーム処理が進んでいることがあるようで、さらに先に進んでしまっているんが原因。
フレームを移動させた後、フィルタグラフの状態が再生中かどうかを確認して、再生中じゃない場合は、再度Playをコールした方が良さそう。
かと思ったが、どうやらそこが問題ではない様子。
上述の謎謎謎の部分がやっぱりおかしいようだ。
終了フレーム付近ではない位置でIMediaSeeking::SetPositions をコールして0位置へ移動した時、S_FALSEを返すが、なぜか位置移動は成功している。
なんだこれは?
自分でフレームから100ナノ秒単位に変換している部分がおかしいのだろうか?

IMediaSeeking::ConvertTimeFormat は例のごとく実装されていませんと返ってくる。
やはり期待できないヤツだ。

S_FALSEを返すかどうかはさして重要ではないようだ。
S_FALSEを返しても、シークはきちんと行われている。
最終フレーム付近でうまくいかないのは、SetFrameがコールされていないのが原因のようだ。
つまり、より上位の問題だ。
と言うことは、Builder側のソースなのだが・・・
Builder側のソースへOutputDebugStringを入れて、VCで拾ってみる。
ちょっと不安だったがうまく拾えた。
これで少しデバッグがやりやすくなるかも。

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

オーバーレイでの動作確認

オーバーレイでも手動グラフ構築が問題ない確認した。
問題はなかったが、初めにちょっともたつくような印象を受けた。
まあ、構築プロセスが長くなっているので、少し時間がかかるようになってしまったのかもしれない。
リリースビルドにすれば大丈夫かな。

ちなみにオーバーレイ時のレンダーフィルタにはCLSID_VideoRenderer を使うようにした。
たぶんこれが標準だと思われる。
無意味にオーバーレイ ミキサー フィルタとかにしても良かったが、やっぱり変なことはしない方がいいだろうからね。

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

October 02, 2004

フィルタグラフを手動で構築

DVDプレーヤーをインストールした特定の環境ではMPEGがうまく動作しない場合があるそうなので、フィルタグラフを手動で構築するように書き換えた。
とりあえず、レイヤー描画の方で確認したが、問題なく動作した。
オーバーレイの方はまだ確認していない。(2つ確認するのは面倒だなぁ・・・)

具体的には次のフィルタが使われるようにした。
CLSID_MPEG1Splitter
CLSID_CMpegVideoCodec
CLSID_DSoundRender
オーディオはCLSID_MPEG1Splitter とCLSID_DSoundRender を繋ぐ際、自動決定されるようにしているが、標準のCLSID_MPEG1Splitter を使用しているので、CLSID_CMpegAudioCodec が使われるはず。
これでも問題があるようなら、CLSID_CMpegAudioCodec も手動で繋がないといけないが、たぶん大丈夫だろう。(根拠なし)

今回の注意点
ヘルプのMPEGフィルタのクラスIDでCLSID_CMPEGVideoCodec と書かれているが、本当はCLSID_CMpegVideoCodec。
ハメられた。
なぜか、Audioの方はきちんとCLSID_CMpegAudioCodec と書かれている。

今回ふと気付いたこと
オーディオがないAVIファイルをレイヤー描画で再生しようとしたら、たぶん失敗する。
なので、これは非サポートとする。

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

あれ?アクセス数が・・・

最近やる気が減少気味だったけど、また盛り返してきて、ムービー拡張を進めた。
そして、それをブログに書いてHPを確認してみたら、アクセス数が32とかになっていた。
あり?
前まで日に10とかそこいらだったような・・・
なんかわからないけど増えたようだ。
ムービー拡張ももう少しなのでがんばって進めていこう。

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

BRender.axの内包

BRender から必要なソースをコピーし、CBaseControlVideo を継承し作成したクラスを削除、IBasicVideo インターフェイスを取得できないようにする。
代わりにIRendererBufferVideo インターフェイスを作成し、それを継承するようにし、IBasicVideo が提供していたメソッドを実装する。

krlmovie 側では基底クラスでIBasicVideo のメソッドをラップし、IBasicVideo を使用している箇所から分離、そのメソッドを継承側でオーバーライドしてIRendererBufferVideo インターフェイスのメソッドをコールするようにする。
以上のようにすることで、IBasicVideo インターフェイスがなくても動くようにした。
これでクラスファクトリがどうとか言う問題はなくなる。
また、追加されたメソッドはインターフェイスを別にしたので、コードもなかなかスッキリした。
BRender.ax をアンインストールし、動作確認。
以前と同じように動作した。
これでBRender.axは必要なくなった。

にしても、次の2つは紛らわしい。
typedef LONGLONG REFERENCE_TIME;
typedef double REFTIME;
REFERENCE_TIMEは100ナノ秒単位、REFTIMEは普通に実数で時間を保持している。

次は特定の環境でMPEG再生がうまく行かない問題の対処だな。
フィルターをつなぎ合わせるメソッドは作ってあるので、ひたすらクエリーして接続していくだけのはず。

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

Total : Today : Yesterday :