« July 2004 | メイン | September 2004 »

August 31, 2004

多重継承

COMの場合、1つのクラスに複数のインターフェイスを持たせるのが一般的なようだが、そのためには多重継承をしなければならない。
しかし、すべてのインターフェイスはIUnknownを継承する。
つまり、QueryInterfaceやAddRedなどのメソッドがかぶってしまう。
おいおいどうするんだ?それってやばくないのか?と思っていたが、実は全然問題ないようだ。
そもそもCOMもそれを期待している節があるようだ。

多重継承を行った場合、基底クラスごとに仮想関数テーブルが作られる。
そして、共通の関数は両方のテーブルで同じ物を指す。
つまり、何の問題もないのだ。
ただし、複数の仮想関数テーブルが作られる関係上、キャストは慎重に行わなければいけない。
QueryInterfaceで返すインターフェイスは、要求された型に一度きちんとキャストする必要がある。
そうしなければ、仮想関数テーブルが別物になってしまい、うまく動作しなくなる。
また、仮想関数テーブルが違うと言うことは、ポインタが異なる。
つまり、同じクラスが持っているインターフェイスでも、QueryInterfaceで返ってきたインターフェイス同士を比較してはいけない。
まあ、利用者側としては、同じクラスかどうかなどわからないし、それを期待した実装はしてはいけないので、さして問題はない。
どうしても、比較したい場合は、そのインターフェイスにQueryInterfaceでIUnknownを要求し、そのIUnknownインターフェイスのポインタを比較するようにしないといけないようだ。と言っても、使わないけどね。

ここの説明は、C++がどのようにクラスを実現しているか、メモリ構造がどうなっているかを知っていないとかなりわからないかも。
まあ、C++のクラスのメモリ構造を知ってて、多重継承はどうなの?って説明だからなんだけど。
それと、図があった方がもっとわかりやすいっすね。
自分用の備忘録としてはこれで十分なんだけど。

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

IDLの記述

新しいインターフェイスを作るのでIDLを書くことにした。
IDLを書けば、MIDLでヘッダーとか自動生成されるはず。
で、必要なメソッドはバッファの取得/設定のみかな。
とりあえず、書いてみるとこんな感じかな。
// IRendererBufferAccess.idl
import "oaidl.idl";
[
object,
uuid(2F8FFFC5-E7BE-497a-9254-DB97639131A6),
]
interface IRendererBufferAccess : IUnknown
{
HRESULT SetFrontBuffer( [in] BYTE *buff, [in,out] long *size );
HRESULT SetBackBuffer( [in] BYTE *buff, [in,out] long *size );
HRESULT GetFrontBuffer( [out] BYTE *buff, [in,out] long *size );
HRESULT GetBackBuffer( [out] BYTE *buff, [in,out] long *size );
}

このソースは、試していないのでうまく行くかどうかは不明。
さあ、MIDLだ。コマンドラインでVCのバッチを実行して

MIDL IRendererBufferAccess.idl

と入力する。
すると、いくつかソースが出力されるが、実際に使うのは、_i.cと.hのみ。
他はリモートコールなどの時に使用されるようだ。
とりあえずは、.hをインクルードして、インターフェイスを継承すればいい。

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

August 28, 2004

フィルタDLLの作成

まずはプロジェクトを作成して、サンプルを参考にしてビルドオプションの設定を行う。
でも、いろいろとうまくいかない。
いろいろといじって、コンパイルは通るようになるが、リンクが通らない。
サンプルとは異なり、ATLを使用しているのが原因のようだ。
で、ATL用のライブラリatls.lib (atlsd.lib)を追加したら、とりあえずリンクが通った。
でも、"atlsd.lib(Externs.obj) : warning LNK4210: .CRT セクションが存在します。静的初期化子、または終末記号がハンドルされていない可能性があります。"などのwarningがたくさん出る。
これは、グローバルコンストラクタなどが使われていて、CRTが起動時に実行されないとでるwarningのようだ。
サンプルでも、出ていたが、サンプルでは1個だけだった。
ATLが使われているからなのだろうが、自分が作ったファイルのオブジェクトにまで出ているのが気になる。
CComPtrを使っているのが原因だと思うが・・・
とりあえず使わなくてもいいように書き換えて、ATLのライブラリとインクルードファイルを消した。
すると、ほとんどのwarningが消え、ほとんどサンプルと同じ状態になった。
2つ多くwarningが出ているが、それは#pragma warning(disable:4355)を追加していないためだ。(サンプルにはある)
なので、サンプルと同じ状態になった。
これで、ひとまずは完成だが、今のままだと使えない。
新しいインターフェイスの追加などが必要だ。

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

フィルタのCOMコンポーネント化

とりあえず、ヘルプのCOMコンポーネントやDLL化の項を読んだ。
ほぼサンプルの通りやれば出来そうだ。

DLLとして作られたフィルタはRegsvr32.exeユーティリティを使って登録することができるらしい。
テストなどはこれでいけそうだ。

DLL化した時の振る舞いを考えてみる。
インストーラがある場合は、インストーラによって登録/解除する。
実行時に見つからない場合は、実行時に登録し終了時に登録解除する。ただし、この場合、エラーなどで落ちた時、レジストリに情報が残ってしまう。登録/解除ツールというか、Regsvr32.exeを呼ぶバッチファイルを用意しておけば良いか。

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

August 27, 2004

IBasicVideoの実装

サンプルを見ながらクラスを作成。
CBaseControlVideo::NonDelegatingQueryInterfaceとCBaseControlVideo::GetVideoFormatさえ作れば、目的を達成できるが、他にいろいろ純粋仮想関数があるので、それも実装しないといけない。
ほとんどはE_NOTIMPLエラーを返すだけだが。

とりあえずは、今までグローバルにあったMediaTypeをBufferRendererに保存するように変更。動作確認。
IBasicVideoをサポートするクラスを作成し、追加したらクラスファクトリ系のグローバル変数が必要だと言われる。
つまり、CBaseControlVideoを継承したクラスを作ると
Textures error LNK2001: 外部シンボル ""class CFactoryTemplate * g_Templates" (?g_Templates@@3PAVCFactoryTemplate@@A)" は未解決です。
Textures error LNK2001: 外部シンボル ""int g_cTemplates" (?g_cTemplates@@3HA)" は未解決です。
などが出るようだ。

CBaseControlVideoを継承したクラスを持ったフィルタを作ると、IBasicVideoがフィルタグラフから使われる(検索される)ようになるわけで、そしたらフィルタが登録されていないといけないと言うわけだろうか。
これは、どんどん本格的なフィルタになっていく・・・。と言うか、クラスファクトリを実装してレジストリの登録とかをやったら、もう普通のフィルタです。
でも、そうなると独自メソッドはインターフェイスとして実装しないといけないことになって・・・。
ちょっと大変です。
しかも、レジストリへ登録とかになってくると、インストーラがどうとか言うことになって・・・
IBasicVideoはもういいか。
とりあえずは、LayerDrawとOverlay別々の処理にしておいて、将来的にきちんとしたフィルタとして実装する?
と言っても、かなり近い将来になりそうだけど。
とりあえず、その方針にして、両方を平行で進めることにしよう。
よし、ローカルの実験用リポジトリをブランチだ。

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

August 26, 2004

現在の時間とフレーム

再生中にIMediaSeeking::SetTimeFormatを使って、タイムフォーマットを頻繁に切り替えると再生が乱れる。どうやら、タイムフォーマットを変更すると何らかの初期化が行われているようだ。
そうすると、再生中にはタイムフォーマットの変更は出来なくなる。

IMediaSeeking::ConvertTimeFormatを使用すれば、他のフォーマットへ変換できるが、自分の環境では、フレームからメディアタイムへの変換は出来たが、メディアタイムからフレームへの変換は実装されていないと出た。
どうやら、IMediaSeeking::ConvertTimeFormatは万能ではないようだ。
FPSを使用すれば、ある程度は自前で変換できる。
出来る限り厳密な設定を望むのなら、タイムフォーマットはメディア タイムを設定しておくべきだが、私の個人的な見解では、設定はフレームで行いたい。
でも、取得は時間の方が都合が良さそうだ。
さて、どうしたものか。
タイムフォーマットにフレームが設定可能であればフレームを、そうでなければメディア タイムとしておくかな。
つまり、フレームを基準として動作させることにする。
細かい時間での制御が出来なくなるが、フレーム以上の精度で何かを制御することはあまりないであろう。
よって、以下のような仕様とする。

合計時間と合計フレーム数はグラフ構築時に取得し、保持しておく。また、同時にFPSも計算し保持する。
タイムフォーマットもグラフ構築時に問い合わせを行い、フレームが利用可能であればフレームに設定。利用できない場合はメディア タイムに設定。もし、両方が利用できない場合は、現在時間の取得や設定は利用できない物とする。
フレームが利用できない場合は、合計フレーム数やFPS、現在のフレームの取得/設定は利用できない。つまり、メディア タイム(100ナノsec単位)での制御となる。

以上のような仕様にするのはいいものの、フレームが利用できないといろいろと痛い。ムービー内ループが利用できなくなる。
FPSが他の方法によって取得できれば何とかなるのだが・・・
もう少し調べてみなければならなそうだ。

AM_MEDIA_TYPEのVIDEOINFOHEADERにはビデオ フレームの平均表示時間がある。これを利用すればFPSを得られる!
オーバーレイの場合は、IBasicVideoを取得すればビデオ フレームの平均表示時間が得られる。
でも、出来れば独自レンダーの方も同じようにIBasicVideoを使用したい。調べるとCBaseBasicVideoというベースクラスがあった。しかし、これは少々ややこしそうだ。もう少し見るとCBaseControlVideoが見つかった。こちらの方が簡単に実装できそうだ。
しかし、実装したとしても、どうやればグラフビルダのQueryInterfaceで返されるようになるのかは現在不明。
良いサンプルがあるといいが。

Filters/SampVidが役に立ちそうだ。
でも、単にクエリーの時に返しているような感じだな。
次はCBaseControlVideoの実装だ。
にしても、独自レンダーは次々に拡張されていくなぁ・・・

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

各種ビデオパラメータの取得

合計時間や合計フレーム数はIMediaSeekingインターフェイスを利用すれば、得られるが、フレームレートはIBasicVideoの各フレームの平均時間からと思ったけど、この文章を書いてすぐに気付いた。
合計フレーム数を合計時間で割れば出るんじゃないか。FPSなんて。
独自レンダーはIBasicVideoをサポートしていないから・・・って悩む必要なんてなかった。
ただし、これらの値は参考値でしかない。
出来る限り誤差が少なくなるように実装するが、誤差が出ることはあるし、仕方がない。
クロックの同期化などの問題もあるし。
まあ、合計時間や合計フレーム数、FPSを他のところで使うことはあまりないでしょう。
でも、これを元に他のところを制御されたらどうしよう・・・
知ーらないっと。
ま、出来る限りやるってことで。

調べていると、再生レートの操作、コマ送り、音のパンポットの設定等々、いろいろと出来ることがわかる。
でも、一気にいろいろと追加するとややこしいし、使わないからそんなのは無視。

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

August 25, 2004

オーバーレイ機能の実装

基底クラス(dsmovie)からオーバーレイ用のクラスを派生して作る。
とりあえずは、基底クラス側で作ったPauseとRewindだけが機能拡張されている状態。
いくつかのインクルードディレクトリとライブラリをプロジェクトに追加しておく。
で、動作を確認すると従来と同じように動いていることを確認。
また、DLLのデバッグが出来るように、VCで設定を行っておく。
デバッガで追えることも確認した。

pauseとrewindをTJSからコールできるようにし、動作確認。動いているようだ。
とりあえず、rewindがあれば、KAGを書き換えてループさせることが出来る。
まあ、TJSのVideoOverlayクラスでサポートされるから意味ないんだけど。
でも、pauseやrewindをしていると時々ムービーがウィンドウに追従しないという問題(バグ?)に気付いた。メニューで何か操作するときちんと合うようになる。
そうか、tTJSNI_VideoOverlay::WndProcで状態がStopになるからだ。たぶんそれで、どこかでイベントが堰き止められているか、コールしなくなっているのだろう。
本来、EC_COMPLETEが来た時点ではムービーは停止状態ではない。ただ最後まで行っただけ。ここで、ムービーの位置を最初に戻すと、何もしなくても再び再生が始まる。でも、Stop状態だから・・・と言うわけだろう。
ま、ループなどが下位でサポートされれば解決するだろう。
あっ、でも、ここの処理は考えておかないとなぁ。

とりあえずここまでをコミットしておく。

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

基底クラスの作成

OverlayとLayerDrawの両方で使うインターフェイスとメソッドをまとめたクラスを作った。
でも、LayerDrawの矩形設定どうしよう。
レイヤーに対して行えば同じなのだが・・・
内部でもレイヤーに対して処理するだけでうまく行かな。
もう少し調べてみる必要がありそう。

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

インターフェイスの拡張

iTVPVideoOverlayにインターフェイスを追加しようとして気付く。
純粋仮想関数にしたらFlash側にも実装の変更が及ぶ。と言っても、まだサポートしていないってエラーメッセージを返すだけなのだが・・・
むぅ。
Flash側もそれだけやるか。

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

August 23, 2004

modeにいて

modeはopen前に設定されていた物を有効とすることにした。
それは、open時のクラス生成時に生成するクラスを振り分けることにしたからだ。
OverlayとLayerDrawの共通部を基底クラスにし、それを継承してOverlayとLayerDrawの各クラスを作ることにした。
動的再接続を使用して2つを切り替えるのは少々厳しそうだから諦めることにした。MPEG SplitterかDecoderのどちらか忘れた(あるいは両方)が、再接続に必要なインターフェイスを備えていないので、再接続しようとしたらかなり面倒だ。

メモ
デフォルトのフィルターなどもCOMだから、包含することで独自に機能拡張することも可能だ。
つまり、デフォルトのオーバーレイをラップして機能拡張が出来る・・・調べてみるとやりたいことは無理そうだ。

メモ2
フィルタグラフはIReferenceClock を使用して同期をとるようだ。
IReferenceClockではセマフォを使って同期をとるようだ。
DirectXのヘルプ"DirectShow のタイムとクロック"の項を読むとよいようだ。
時間は100ナノ秒単位。
10,000,000 = 1秒。
でも、返される値は意味がない。それは、基準クロックに依存するから。つまり、100ナノ秒単位できちんと増加するわけではない。
制御しづらそう。サウンドがある場合は、サウンドフィルタのクロックに同期化されるんだろうなぁ。
IMediaSample::GetMediaTimeを使えば、そのサンプルのフレーム番号がわかる。
IBasicVideo::get_AvgTimePerFrameを使えば、100ナノ秒単位のフレームレートが得られる。
IVideoFrameStep を使えばコマ送りが出来る。

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

メソッドとプロパティの追加

TJS2 基本的な使い方のネイティブクラスの項を読む。
以前も一度読んだのだが、また頭がこんがらがる。
クラス、インスタンス、オブジェクトと言う言葉が出てくるが、これらの言葉は状況によって取り方が変わる。それに、C++の方かTJSの方かがすぐに判断できなくて、さらにこんがらがる。
まあ、よく読めばわかるんだけど。。。
もう一度読んだらまた???ってなりそうだ。

それはさておき、とりあえず、Overlayにメソッドとプロパティを追加。
VideoOvlIntf.cppですな。
他のをコピペしてただ書き換えるだけ。単純作業だ。
マクロが少し気になるが、たぶん登録処理だろう。

で、メイク。
すんなりいった。
じゃ、次は実際の処理の記述ですな。
でも、I/FにはすでにPause()が入っているけど、実装されていない。
なぜだろう?
ま、考えても仕方ない。追加していこう。
でも、その前にテスト用のTJSスクリプトを書いておいた方がいいかな。

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

ムービー拡張仕様(仮)

VideoOverlayクラスのインターフェイスの拡張仕様を考える。
次のような物にしようと考えているが、追加削除がありそうな臭いぷんぷん。

メソッド
close ( メディアを閉じる )
open ( メディアを開く )
play ( 再生開始 )
setBounds ( 再生矩形の位置とサイズを指定 )
setPos ( 再生矩形の左上位置を指定 )
setSize ( 再生矩形のサイズを指定 )
stop ( 再生停止 )
pause (一時停止) : 新規追加
rewind (巻き戻し) : 新規追加、positionに0を設定するのと同意だが・・・
playSequence (特殊再生) : 新規追加、特定フレーム間ループなどを行えるようにしたい

プロパティ
height ( 再生矩形の縦幅 )
left ( 再生矩形の左端位置 )
position ( 再生位置 ) : 未実装なのを実装する。でも、msecじゃないかも。
top ( 再生矩形の上端位置 )
visible ( 可視かどうか )
width ( 再生矩形の横幅 )
loop (ループ ) 新規追加 : ループの有効/無効を取得/設定。
frame (現在のフレーム) 新規追加 : フレーム番号で取得/設定。使えない時もあるかも。
fps (フレームレート) 新規追加 : 読み込みのみ、実装できないかも
numberOfFrame (全フレーム数) 新規追加 : 読み込みのみ、実装できないかも
totalTime (合計時間) 新規追加 : 読み込みのみ、実装できないかも
layer1 (描画レイヤー指定1) : 新規追加
layer2 (描画レイヤー指定2) : 新規追加
mode (オーバーレイorレイヤー描画) : 新規追加

イベント
onCallbackCommand ( コールバックコマンドが発生した )DirectShow側では使用されない?
onStatusChanged ( ステータスが変更された ) イベント追加 : period (ループ時にループの終点に達した時に発生)

layer1, layer2と言うプロパティを持つ仕様はちょっと格好悪いだろうか?
まあいいか、比較的簡単直せるだろうし。
気にしない気にしない。

まだ書きかけです。

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

なにげにFlashの方も見てみる

COM ( ActiveX ) ですな。
メッセージはサブクラス化(?)しているように見えたが、コメントアウトされている。
でも、これがフックって言っていたやつですな。
フックという呼び方の方が正確なのだろうか?
Codianではフックと書かれている。
サブクラス化とフックは厳密には異なるのだろうか?
何となく違うようだが今は細かいことは気にしないことにした。
っていうか、これはまた面倒ですな。
Flashのレイヤー描画は考えないことにしよう。

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

次は? メモ

TJSのクラスの追加の仕方を再度熟読。
オーバーレイミキサーの説明を読む。
メソッドなどを追加してみる。
激ねむなので、ここにメモっておこう。

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

August 22, 2004

ムービー内移動

連続再生は止めて、ムービー内の任意のフレームへ移動できる機能を実験してみた。
単純に一部の区間をループし、クリックされると次へ移行、また次の区間でループするという物。
複数ムービーをつなげるよりもスムーズにつながった。
まあ、元々一つのムービーなんだから当然と言えば当然かもしれないが。
ただ、かなり離れたフレームへ移動する場合もうまく行かどうかは不明。
でも、たぶんなんとかなるでしょう。(根拠なし)

ただし、この実験では独自レンダーから、フレームごとにイベントを発行しているので、フレームの切り替わりを取得できるけど、オーバーレイのレンダーを使った場合は取得できない。
たぶん、なんとかできそうな気がするけど、今のところ不明。

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

カウンターが壊れた

なんかわからないけど、カウンターが200万とかを指していた。
明らかにおかしいので、とりあえず0に戻しといた。

しばらく経ったらなぜか元通りに。
何だったんだろうか?

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

吉里吉里をメイク

kirikiri2/src/core/environ/win32/bcb6/tvpwin32.bprを使ってメイクしてみる。
インクルードファイルがいくつか足りないと出た。
前もらったやつからコピーし忘れていたようだ。
再度メイク。
ライブラリがいくつか足りないと出た。
コピーし忘れていたようだ。
再度メイク。
boost関連でリンクエラーが出る。
1.31.0にパッチを当てずにライブラリを作っていたので、今度はパッチを当てて、makeしインストール。
しかし、やはりboost関連でリンクエラーが出る。
なんだろう?
バージョン違いかな?

---以下追記
バージョン管理されている最新のソースのmakeにはboost 1.30が必要なようだ。
1.31.0だとなぜか通らない。
なお、このときの最新のリリースバージョンは吉里吉里 2.23 β3。

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

August 21, 2004

ダブルバッファリングの実験

CMediaSample::SetPointerを使えば出来そうだ。

ヘルプには、
このメソッドは IMediaSample インターフェイスを通しては使えない。サンプルを作成したオブジェクトは (CMediaSample を通して) このメソッドにアクセスできるが、他のオブジェクトはアクセスできない。
とある。

そこで、自前のアロケーターにCMediaSampleを保持しておくようにし、新しいバッファを設定する関数を追加した。
そして、CBaseRenderer::DoRenderSampleで、サンプルのポインタをすげ替えたら、うまくいったようだ。
描画部分はダブルバッファにしていないが、交互にバッファが使われているのを確認した。
これでダブルバッファリングの問題は解決した。

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

August 20, 2004

ダブルバッファリング

最新の吉里吉里をチェックアウトして、メイクしている間、どのような仕様にするか考えていて思い出す。
デコーダーに直接レンダリングさせるのならダブルバッファリングしないといけないんだったと。
でも、どうやればいいのだろう?
たぶん、メディアサンプルかアロケーター辺りをいじればいいんだろう。
で、また実験することになった。

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

オーバーレイの対応

レンダーがデフォルトの物でいいので、グラフ作成部分がすごい簡略化された。
で、再生!
・・・ ウィンドウが4つ出来た!!
やったね!っておい。
オーナーウィンドウや位置を設定しとかないといけないようだ。
設定すると問題なく表示できた。
これでとりあえず目標は達成だな。
次は吉里吉里への組み込みだ。
でも、その前にどのような構成にするか検討しないと。

なんとなく、KAGのソースを見てみる。
ウィンドウがムービーオブジェクトを持っているんすね。
KAGの方の改造はそれほど大変ではなさそうだ。
そして、ふと気付く。
KAGに構文を追加しようと思ったらパーサーをいじらなければならないのではと。
でも、ほとんど予約語追加と対応する処理を記述するだけとかで出来るんじゃないかなぁと期待を抱く。
何となく見た感じだとbisonは使っているけど、flexは使っていないような感じだったけど・・・
ま、その辺は追々だな。
初めはKAGでTJS直打ちすれば済むし。

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

フィルタグラフの複数生成

ヘルプを見ていると、どうもフィルタグラフは複数存在していても良いようだ。
それなら、初めに複数のフィルタグラフを生成しておき、順番に再生していけばうまくいきそうだ。
で、早速試す。
うまくつながっているけど、完璧につながっているかどうかはわからないなぁ。
そこで、アニメのOPを5秒ずつに分けた3つのムービーを準備し、再生してみた。
が、やっぱりつなぎ目で音がとぎれるし、絵も一瞬ぼやける。しかし、MPEGなんだから、その絵が完璧に一致しないのは仕方ないだろうと思う。
問題は音だが・・・やっぱり一瞬とぎれてしまうよなぁ。
完全に繋ごうと思ったら、ソースフィルタからデコーダーへ流れるデータをとぎれないようにしないといけない。
そうするとソースフィルタを工夫しないといけないのだろうか?
そもそもそこまで必要かどうかと言う問題がある。
ムービーをつなげて作る場合、シーンが切り替わるところにムービーの接続点を持ってくるだろう。そうすれば、たいして違和感なく表示される。
また、バックに音楽を流す場合は、ムービーとは別に音楽を流せば何とかなるのではないだろうか。
つまり、完全につながっていなくても大丈夫な気がする。
ま、作り手の工夫次第っすね。

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

グラフの再構築

再接続は少し面倒そうなので、もう一度一から作る方法を試してみることにした。
作ってみてみると・・・つながっているけど、隙間が空いていないのかどうかわからない。
まあ、つながっていないムービーをつなげてもわかるわけないか。
まずはつながっているムービーを分割して用意する必要がありそうだ。
バックに音楽が流れていたらなおよしだが、それはかなり厳しそうだ。
音楽がとぎれなく聞こえるようにするのは可能なのだろうか?
専用の物を作らないと厳しそうだが・・・最近のPCなら難なくやってのけてしまうのだろうか?
とにかくやってみないことにはわからないな。

次に全体をループさせる(1->2->3->1・・・と言う感じ)ように作ってみるが、なぜか同じ物を使おうとしたら適切な中間フィルタがないと言ってくる。
フィルタグラフが削除された時に何かされているのだろうか?
自分で事前にグラフからフィルタを削除したり、Disconnectしたり、いろいろとやってみるが結果は変わらず。
少し考えてふと気付く、ファイルの位置が終端に達しているからでは?と。
とりあえず、IStream::Seekで位置を先頭に移動させる。
が、効果なし。
IMediaPosition::put_CurrentPositionで先頭に移動させても効果なし。
なんなんだろうか?

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

August 19, 2004

ソースフィルタの動的再接続

ヘルプの動的再接続のソースを参考に、と言うかほとんどそのまま実装してみる。
が、いきなりQueryInterfaceでインターフェイスがないと返ってきて終了。
何ーぃ。
まあ、サンプルはソースフィルタではなく、途中のエフェクトフィルタだったので若干異なるのかもしれない。
でも、このIPinFlowControlがないと動的再接続が出来ないのだが・・・
ヘルプを読むと次のように書かれている
---以下引用
フィルタ開発者へ : 動的な再接続をサポートするパーサー フィルタとキャプチャ フィルタでは、その出力ピン上でこのインターフェイスをサポートしなければならない。通常、その他のタイプのフィルタでは、このインターフェイスを実装する必要はない。
---引用終わり
ソースフィルタはサポートしていなくても良いと言うことだろうか?
そもそも、ソースフィルタを差し替えるには他の方法があるような気がしてならない。
さてどうしたものか。

基本的にソースフィルタを差し替えたい場面はムービーの終点になる。
つまり、すでにストリームにはデータは流れていないはずだ。
なら、そのままはずしてしまえばよいのではないだろうか?
とはいうものの、やっぱり危険な香りがするので、IMediaControl::Stop()を事前に呼び出し、フィルタを停止状態にしておくことにする。
しかし、この場合ムービーのつなぎ目に隙間が生じてしまう可能性がある。
まあ、隙間が出来たら、ソースフィルタのみを停止し、つなぎかえれば何とかなるのではないだろうか。そのときはそのときにいろいろと考えよう。
で、IMediaControl::Stop()を呼び、IPinFlowControl::Block()は呼ばずにIGraphConfig::Reconnectを実行してみたのだが、入力ピンがIPinConnectionをサポートしていないと返ってきて終了。
・・・
なんですとー。
まあ、毎度のことなんだけど・・・
よし、自分でDisconnectを呼んで、その後また自分で繋ごう。
で、やってみたらなんかうまく再生されない。
GraphEditで見てみると・・・
20040819graph.gif
めためたです。(涙
本来は次のようにきれいにつながっています。
20040819graph02.gif
でも、よく見てみると、スプリッターから先がぶった切れているだけのようだ。
なら面倒だが、再度繋げば大丈夫なんだろうか?
でも、そうすると一から構築するのと大差ない気がするのだが・・・
さてどうした物か。
とりあえず、どの辺りでぶった切れているのか調べると、ソースフィルタをDisconnectした後にすでに切れてしまっているようだ。
うーん・・・
明日考えよう。

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

接続しているピンの取得

接続しているピンを取得するには、IPin::QueryInternalConnectionsではなくIPin::ConnectedToを使えばいいようだ。
QueryInternalConnectionsはインプリメントされていない場合があるが、ConnectedToにはそのようなエラーは定義されていない。
たぶん下位の部分で実装されているのだろう。
これで、スプリッターのピンの問題は解決した。
次はソースフィルタを差し替えれば、次のムービーが再生されるはず。

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

August 18, 2004

ある程度整理できた

一通り整理して、ビルドが通り、動くところまでいく。
でも、いくつか問題が。
ソースフィルタにQueryInternalConnectionsがインプリメントされていないので、そこからスプリッターが取得できない。
とりあえずは問題ないが、再接続時に困る。
フィルターを列挙してそれで何とかなるのかな。
まあ、やってみよう。

他にもまだまだきちんとしていないところが・・・
MPEGに依存している部分や、関連が混み合っている部分がある。
まあ、ビルドが通るようになったので、少しずつ整理していこう。

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

C++ビルダでフォーム表示の切り替え

C++ビルダでフォームの同じ位置に異なるダイアログのようなコントロールの固まりを切り替えながら使用する方法を調べる。
ページコントロールを使えば、タブによって切り替えられるが、タブが表示されてしまうのはちょっとかっこわるい。
そこで、同じ位置にパネルを配置し、その各パネルを表示/非表示することで、とりあえずは切り替えられることがわかった。
しかし、フォームの編集が出来ない。
各パネルないにフレームを配置し、そのフレームを編集することで、各コントロールを編集することは出来るが・・・どうもしっくり来ない。
もっと良い方法はない物だろうか?
出来れば、動的に割り当てられるとかなり良いのだが。。。

とりあえず次のようにすればいいようだ。

m_Frame = new TFrame1(this);
m_Frame->Parent = MyPanel;
m_Frame->Align = alClient;
m_Frame->Show();

まず、フレームを生成する時にオーナーをFormにする。
Parentに位置を決めるためのパネルを設定する。
アライメントをクライアント領域に設定する。(アライメントはフレームの方で設定しておけば問題ないようだ)
で、表示する。
後はいらなくなったら非表示にして削除する。
そして、各フレームの各コントロールの状態を保持する構造体でも作ってデータを設定/取得出来れば万事O.K.だ。

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

August 17, 2004

ソースの整理2

エクセプションクラスは組み込めた。
そのおかげで例外処理部がきれいになった。

ユーティリティー的なのは全部CPlayerに入れてしまうことにした。
そして、MPEG依存部分 ( フィルタ名を直指定で検索している箇所がある ) をなくしていく。
しかし、ソースの整理と同時にやると面倒なことになる可能性があるので、とりあえずは従来の処理を有効にしておく。#if #else #endifで分けておく。(リファクタリング時に機能追加しないのは基本らしいし)

ソース整理はもう少しかかりそうだ。
ビルドして動かす間でしばらくかかるので、時々中だるみする。
やっぱり、細かくやっていった方がいいな。

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

CComPtrの代入時の振る舞い

COMのインターフェイスを管理する時はATLのCComPtrを使うと楽だ。
ソースはatlcomcli.hにある。
で、代入時の振る舞いがちょっと気になったので調べてみた。
中ではAtlComPtrAssignが呼ばれている。
その中を見ると次のような感じ。

if (pp == NULL)
   return NULL;

if (lp != NULL)
   lp->AddRef();
if (*pp)
   (*pp)->Release();
*
pp = lp;
return lp;

やっぱ代入元もAddRefされてるんすね。
と言うことは、呼び出し元管理のインターフェイスは代入後Release呼んどいた方が良さそうだ。

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

August 16, 2004

ソース整理・構成の変更

CIStreamProxy、CIStreamReader、IStreamはCMovieに、グラフ系のはCPlayerに入れる。
HRESULTからAMGetErrorTextでエラーメッセージを作ってくれるexceptionクラスも作っておくことに。
でも、まだ整理中。
さっさときれいにしないとねぇ。
と言うか、もっと早くやっとけよ。って気が。

でも、他のユーティリティー的なのはどうするか?
グラフ関連のが多いから、そう言うクラスを作ってまとめるかな。
うーん、行き当たりばったりだけどいいのかなぁ。
少し、きちんとモデリングした方がいい気がする。
まあ、吉里吉里に組み込む時にやるか。
そうしよう。

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

August 15, 2004

連続再生について

今日はとあるイベントに行った後、アキバへ行ったりしていたので進捗がないが、昨日考えたことをここに記しておく。

遅延なく連続再生するためにメモリ上にデータを置こうと思っていたが、そんなことをしなくても、ディスクに一度アクセスすればキャッシュがきいてほとんどの場合遅延なく読み込めるのではないかと思う。NT系のディスクキャッシュは強力だし。
で、それより問題になると思われるのはグラフの再構築だ。
もし一から構築しなおすと、完全につながらないのではないかと考えられる。
何となくだが、グラフの構築はそこそこ時間のかかる処理のように見える。
そこで、どうするか? だ。
簡単に思い付くのはフィルタグラフを複数作っておくという物だが・・・ 複数作っても大丈夫なのだろうか? また、うまく切り替えられるのだろうか?
次善の策としてはソースフィルタの差し替えだ。
すべてを作り直すのではなく、次のムービーのソースフィルタのみを事前に準備しておき、切り替え時にその部分のみつなぎかえると言う方法だ。
どっちにしても、ソースコードを整理しないといけないので、どちらを選択してもいいのだが、ソースフィルタの差し替えで済むのならそれが一番なので、まずは差し替えを試してみることにする。

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

August 14, 2004

ソースフィルタの変更

asyncio.h/.cppとasyncrdr.h/.cppをそのままコピーしてきて、吉里吉里のCIStreamReaderとCIStreamProxyを別ファイルに分離して、それをインクルード。
VC.NET 2003でビルドするとasyncio.cppでビルドエラーが。
単に型チェックが厳しくなっただけのようだ。
asyncio.cppの422行目のCreateThreadへ渡す関数ポインタを(LPTHREAD_START_ROUTINE)にキャストしたらビルドが通る。たぶん、これで大丈夫だろう(あまりこういうことはしない方がいいけど)。

ビルドが通ることを確認したので、ソースフィルタを変更する。
と言っても、AddFilterでCIStreamReaderをグラフに追加し、その出力ピンとレンダーをつなぐだけ。
IStreamはとりあえずSHCreateStreamOnFileでお手軽に生成。
でも、SHCreateStreamOnFileに渡すファイル名はなぜかマルチバイト文字セット。
仕方なく、WideCharToMultiByteで変換する。
なんで、ワイド文字列(Unicode)じゃないのだろうか?
シェル系はワイド文字列が多かったはずだが・・・あれ?逆だったかな?
まあ、いいか。どっちでも。面倒だけど。
で、前回と同じように再生されることを確認。
なんか、かなりあっさりと出来た。

次はいよいよメモリからの再生。
でも、そんなに難しくはなさそう。
IStreamを継承したクラスを作って、ぽんっと渡せば済みそうだし。

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

MSDNをインストール

COMの部分が日本語化されていないかなぁと言う淡い期待を抱きながらMSDNの2004/07をインストール。
やっぱり、英語のままだった。
仕方ない、英語を読むか。

吉里吉里のコードを見て、IStreamについてはだいたいわかったが、IMonikerについては手掛かりがない。
MSDNを入れるついでに一緒に入っているSampleソースもコピーしておいたので、Grepをかけるが、それっぽいのは見つからなかった。
ふと思い立ち、DirectShowのサンプルに対してGrepをかけたら、いっぱい出てきた。
モニカはCOMオブジェクトを一意に識別する仕組みっぽい。
で、マルチメディア ストリーミングで使われるモニカはデバイス モニカかファイル モニカとなっている。
モニカはよくわからないし、いろいろと面倒だなぁ。
とりあえず、マルチメディア ストリーミングはほっとくか。

メモ (ちょっと関係ない)
DirectShowのビデオキャプチャプログラミング

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

August 13, 2004

Asyncサンプル

メモリから読み込む場合、このサンプルがほとんどそのままっぽい。
Base部分は吉里吉里と同じ?
とりあえず、memfileのソースを読むが、やっぱり簡単そうだ。
でも、BaseやFilterを見ると・・・って、いつものようになるのだろうか?

Filterを軽く見た感じではそうでもなさそうだ。
Baseがいろいろとやってくれているのだろう。
でも、Baseのソースを見ると・・・いろいろとややこしそうなことをしている。
面倒だなぁ。
Baseはあんまり見ずに、そのまま流用でいいかな。

吉里吉里ソースを見直すとIStreamを渡すようになっている。
つまり、メモリ用のIStreamのなんかを作ればいけるのか?
ファイル用のIStreamはSHCreateStreamOnFileをコールするだけでいけるようだ。
でも、COMってどうやって作るんだっけ?
すっかり忘れてしまった。

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

IDLファイル

COMのインターフェイスを定義(宣言?)したIDLファイルがあることを思い出した。
IMpegVideoDecoderのインターフェイス定義もあるかと思い、grepをかけたが見つからなかった。
IMpegVideoDecoderに関する情報は全くないなぁ。

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

マルチメディア ストリーミング

IDirectDrawMediaSampleAllocatorのことについて調べていて、
IDirectDrawMediaStreamを発見する。
どうやら、IDirectDrawMediaSampleAllocatorを使うには、IDirectDrawMediaStreamを使わなければならいなような雰囲気だ。
しかし、IDirectDrawMediaStreamはインターフェイス一覧にない。
なぜだ?
うーん、MicrosoftのDirectDrawをなくしたいと言う思惑だろうか?
まあ、使用禁止インターフェイス一覧になかったら気にせずに使おう。

そして、IDirectDrawMediaStreamの項を見ているとマルチメディア ストリーミングへのリンクがあった。
マルチメディア ストリーミング?
そんなのあったっけ?と思ったら、ヘルプ付録にあった。
うーん・・・普通のところに書いていて欲しかった。
まあ、とにかくマルチメディア ストリーミングの項を読まねば。
・・・
例によって例のごとくよくわからない。
いや、よくわからないと言うか、今回のような構成で使用できるのかどうかがわからない。
マルチメディア ストリーミングはどうやらファイルを与えて、任意のサンプルを得るための仕組みのようだ。
つまり、適当につなげて・・・と言うような用途には利用できないのかもしれない。

マルチメディア ストリーミングの入力はファイルかモニカを使用するようだ。
モニカについてはよくわかっていない。

調べた結果、オーバーレイかマルチメディア ストリーミングを使用しないとDirectDrawへ直接書き込めなさそうだ。
しかし、MPEG-1 ビデオ デコーダ フィルタの
> このフィルタは、DirectDraw サーフェスへのデコードも可能である。
と言う一文がかなり気になる。
何らかの方法でDirectDraw サーフェスへ直接書き込めそうなのだが・・・
とりあえずは、そのことを気にとめておいて、メモリ上からの再生とオーバーレイの切り替えを先にやろう。
オーバーレイ、マルチメディア ストリーミング、モニカはその過程でわかっていくだろう。


メモ
DirectShow の ページ

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

August 12, 2004

DirectDrawSurfaceへの描画方法の調査

ビデオレンダリングフィルタを使えば、DirectDrawSurfaceに描画出来るようだが、そうしてしまうと、描画タイミングを得る方法がわからない。
あるのかもしれないが、調べた限りではわからなかった。

IDirectDrawMediaSampleAllocatorとIDirectDrawMediaSampleを使えば、デコーダーにDirectDrawSurfaceへ直接描画させられそうであるが、これはどうすればいいのだろうか?
どのメディアタイプで接続すれば良いのかがわからない。
アロケーターに呼び出しがかかるのは、レンダー接続時のCheckMediaType呼び出しより後だったはず。
つまり、その時点で受け入れるメディアタイプをどうするかが問題だ。
いや、他ので実験してみればよいのか。
いけるかも。

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

Oleview

IMpegVideoDecoderのことが気になったので、OLEViewで調べてみるが、インターフェイスが見つからなかった。
ハテ?
DirectShowのインターフェイスはどこにあるんだろう?
もちっと真剣に探すかな。
うーん、IMpegVideoDecoderにはそれほど関心がないので、ほっとくか。

OLEViewのことはすっかり忘れていたが、なぜか突然思い出した。
COMのことに関しては、Visual C++プログラマのためのCOM入門がそこそこわかりやすいかも。
まあ、私はmacromedia DirectorのMOAで泣いたので、COMについてはそこそこ知っていたから、本当にわかりやすいかどうかはわからなかったり。
でも、OLEViewについての解説があるので、それはそれで良いかも。って言うか、この本の存在自体しばらく忘れていたんですが。

次こういうことがあったときにOLEViewをすぐ思い出せるようにここにメモ。
って、そん時はこの文書も忘れてそう。

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

Namazu Perl5.8で動かず

DLしたメーリングリストログにNamazuをかけようとしたが、すぐ落ちてしまった。
やはり、Perl 5.8系では動かないのだろうか?
いろいろと調べたりするのが面倒なので、Perl 5.6系が入っている方のマシンでインデックスを作ることにした。
インデックスさえ作ってしまえばこっちのものだしね。

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

メーリングリストのログDL

やはり、DirectShowのメーリングリストのログから検索したくなり、メーリングリストのログをDLすることに。
DLするために簡単なPerlスクリプトを書く。
以下のような感じ。

※このままでは実行できません。
これでしばらく実行しておけばローカルにログのコピーが置ける。
ローカルにたまったらNamazuでインデックスを作ろう。


$target_url = 'www.freeml.com';
$base_url = 'http://www.freeml.com/message/directshow@freeml.com/';
$target_object = 'message/directshow@freeml.com/';
$start_num =;
$end_num =;

use Win32::Internet;

local $INET = new Win32::Internet();    # WinInetのインスタンスを得る
if( defined( $INET ) ) {        # 成功
   local $HTTP;
   $INET->HTTP( $HTTP, $target_url );  # HTTPのインスタンスを得る
   if( defined( $HTTP ) ) {            # 成功
       $HTTP->ConnectBackoff(2000);    # リトライの間隔 (in milliseconds)
       $HTTP->ConnectRetries(100);
       $HTTP->ConnectTimeout(10000);   # in milliseconds
       $HTTP->ControlReceiveTimeout(10000);
       $HTTP->ControlSendTimeout(10000);
       $HTTP->DataReceiveTimeout(10000);
       $HTTP->DataSendTimeout(10000);
       for( $i = $start_num; $i <= $end_num; $i++ )
       {
           print "Reading    page - $i\n";
           $send_command = sprintf("%07d",$i);
           {
               my $REQ;
               $ref_page = "http://" . $target_url . "/" . $target_object . $send_command;
               print "Open " . $ref_page ." ... ";
               $HTTP->OpenRequest( $REQ, $target_object . $send_command, "GET","", "","text/*\0image/gif\0image/jpeg\0\0",INTERNET_FLAG_RELOAD );  # HTTPのリクエストを生成
               if( defined( $REQ ) ) {                     # 成功
                   print "Success.\n Reading...";
                   sleep(1);
                   $REQ->SendRequest();        # リクエストを送る
                   $file = $REQ->ReadEntireFile();         # 返ってきたデータを読む
                   $REQ->Close();                          # リクエストを閉じる
                   {
                       open( FOUT, ">$send_command.html" ) or die "cannot open file!";
                       print FOUT $file;
                       close( FOUT );
                   }
               }
               else {
                   print "Fail.\n"
               }
           }
       }
       $HTTP->Close();
   }
   $INET->Close();
}

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

August 10, 2004

高速化への実験

今までのことを整理していてふと気付く。
DirectDraw Surfaceを使えばさらに高速化できるのではないかと。
とは言っても、直接使うことは出来ない。
吉里吉里の仕様上、最終的にはメモリ上にイメージがなくてはならない。
しかし、これは最終的にメモリ上にあれば良いと言うことでもある。
つまり、DirectShowにDirectDraw Surfaceへレンダリングさせ、それを再びメモリへコピーしてこようという作戦だ。
明らかに非効率的な方法のように感じるが、これによって少しCPU負荷が下がる可能性がある。

最近のグラフィックスカードはMPEG再生支援機能という物がだいたい搭載されている。
MPEGのデコードは前フレームとの差分や逆離散コサイン変換などがあり結構重い処理だ。
そして、MPEG再生支援機能とは動き補償やIDCTなどをさすようだ。
当然、MPEGムービーは入力データ量よりも出力データ量のほうが遙かに大きくなる。
あくまで推測だが、、MPEG再生支援機能によって、この少ないデータ量をグラフィックスカードへ送り、グラフィックスカード内で伸張されるのではないかと考えられる。(このようになっていればかなり効率が良い)
つまり、CPUの処理量とメモリコピーの量がかなり軽減されるわけだ。(推測だけど)
しかし、この後でVRAMからメインメモリへのコピーを行わなければならない。
当然これは負荷がかかる。しかも、その後またメインメモリからVRAMへのコピーが発生する。
結局のところハードウェアによってなくなった分とVRAMからメインメモリへのコピーでどちらが重いかと言うことになる。

うーん、微妙ですね。
たいして速くならない気もする。
まあ、興味があるのでちょっとやってみようって感じですね。

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

August 09, 2004

ファイルの差し替え

複数ファイルの連続再生だが、どうやらメモリ上からの再生と同時にやった方が簡単そうだ。
ファイルグラフを再構築するのであれば、話は違うかもしれないが、ファイルを切り替えるにはソースフィルタを作らなければならなそうだ。
まあ、メモリ上からの再生もあるので、このあたりのことはあまり調べていないんだけど。
と言うわけで、次はメモリ上からの再生(ソースフィルタ)の作成に移ることにする。
ソースはAsync フィルタ サンプルと吉里吉里のが参考になりそうだ。

ループ再生はイベントさえ実装してしまえば全然余裕と言うか、すでにループ再生しているので、もう、やってもやらなくてもどっちでも同じだ。

何というか、DirectShow一巡りという感じがしてきた。
パーサー、スプリッター、デコーダーは作らないが、両端のフィルタは作る(作った)ので、だいたいの用途では事足りそうだ。

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

ソースの整理とイベント化

上下反転の実験用コードの削除と、連続再生用に少しだけコードを整理する。
Texture3Dでは再描画がメッセージではなく、メッセージループでメッセージがないときに描画&Sleepと言う構成だったので、レンダーのDoRenderSampleがコールされ、サンプルが得られた時点でIMediaEventSinkインターフェイスを使ってメッセージを送信するように変更した。( メッセージはOnRenderEndで送る方が良いかも )
なお、定義済みのイベントではそのような目的の物はなかったので、独自に定義した。
ヘルプに独自定義に関する文章は見つからなかったが、DirectShowのイベントが定義してあるEvcode.hにEC_USERが定義してあったので、たぶんこれを使ってユーザーイベントを定義することになっているのだろうと勝手に解釈し、#define EC_UPDATE (EC_USER+1)と定義した。(ウィンドウメッセージにもWM_USERって言うのがあるし)

よく調べるとDirectX8.1の英語ヘルプのには次のように書かれていた。
Filters can define custom events with event codes in the range EC_USER and higher.
どうやら、上記のような使い方で問題ないようだ。

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

August 08, 2004

DirectShowメーリングリスト

DirectShowについて語ろうと言う、DirectShow関連の開発に関するメーリングリストがあった。
とりあえず登録しておく。
でも、ログに検索機能がないのですごい見づらい。
途中まで順番に見て行っていたが、見つからずやめた。

何で検索がないんだろう?
MyPageとかに登録すれば使えるのか?
過去ログ全部落として、ローカルでインデックス作って検索するかなぁ・・・かなり嫌だけど。

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

デコーダーで上下反転

BITMAPINFOHEADERのbiHeightの項を見ると、
ビットマップの高さをピクセル単位で指定する。biHeight の値が正である場合、ビットマップはボトムアップ DIB であり、左下隅が原点となる。biHeight の値が負である場合、ビットマップはトップダウン DIB であり、左上隅が原点となる。
と書かれている。
つまり、VIDEOINFOHEADERのメンバ、bmiHeader.biHeightをマイナス値にすれば、上下反転は実現できそうだ。
でも、BITMAPINFOHEADERの説明の最初に『AVI RIFFファイルの・・・』とか書かれているが、気にしない。
とにかくやってみよう。

と書いたものの、どこでAM_MEDIA_TYPEを設定すればいいのかよくわからない。
レンダーのSetMediaTypeで指定してみるがうまくいかず。って、よく考えたら、レンダーは自前で用意しているんだから当然か。
他に、レンダーのCheckMediaTypeの中に入れてみたり、アロケーターのAllocでMediaSampleに設定してみたり、GetBufferの中でやってみたり、独自のMediaSampleを作ったりしたがどれもうまくいかない。
ネットでいろいろ検索するも有用な情報は得られない。
で、再度いろいろと考えてみる。
Allocの中やCheckMediaTypeの中で行われるのはおかしい。
接続時か、それより前に設定されるべきだ。
そうしないと使えるかどうかわからないはずだ。
そして、ピンのところを見ていると・・・Connectの引数にAM_MEDIA_TYPEを渡せるようになっている!これだ!

途中の試行錯誤は割愛して、手順を説明すると次のようになる。
まずは、普通に接続する。
CheckMediaTypeの時に渡されるMediaTypeで、OKを返した物のコピーを取っておく。
接続が完了したら、デコーダーとレンダラーの接続を切る。
コピーしておいたMediaTypeのVIDEOINFOHEADERのメンバ、bmiHeader.biHeightを *= -1;してマイナスにする。
そして、このMediaTypeを使い、Connectする。
すると、上下が反転された(画面上では反転していない)画像が出てくる。※普通のBMPは上下が逆に格納されている。つまり、上下反転したら反転していないBMPが得られる。

同じ箇所でrcTargetを使えば、拡大縮小なども出来るかと思ったが、うまくいかなかった。
このあたりはまだまだ調査が必要そうだ。もしかしたら、デコーダーでは出来ないかもしれない。でも、効率面を考えると出来るようにしてあってもおかしくないが・・・
まあ、とりあえずは上下反転できたのでよしとしよう。
次は複数ファイルの連続再生だな。
グラフを一から再構築すればすぐに出来そうだが、そうせずに出来ないかなぁ。
ま、いろいろ調べよう。

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

デザイン変更

HPのデザインを一新。
しまりがあっていい感じ?
でも、まだBBSは変更していないので、ちょっと変かも。

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

August 07, 2004

デコーダーがダイレクトSurfaceに書き込み

アロケーターをCBaseAllocatorから継承するように書き換え、いくつかのメソッドを変更。
なんとか、デコーダーがダイレクトにSurfaceへ書き込んでくれるようになった。
負荷もだいぶ軽くなった。
まあ、640*480*32bppのコピーが1回減ったので当たり前と言えば当たり前。
でも、出力はBmp形式なので、上下逆だ。
吉里吉里はどうなんだろう?
たぶん、上下反転にはなっていないだろうなぁ。
ドキュメントを見た感じもそうはなっていなさそうだし。
吉里吉里より先にDirectShowで上下反転せずに出力できないか調べるか。
出力先の矩形のTopとBottomを入れ替えると逆転しないかな。
マイナス値を使ったり、上のような方法で反転する仕様って言うのは時々あるし。
StretchBltとかそうだし。

で、いろいろ試すが、どこでメディアタイプを設定するのかよくわからない。
もちっと真剣にヘルプを読むかな。

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

ピンとアロケーターの実装

参考ソースを今まで作ってきた物にあうように若干修正して(ほとんどそのまま、でも、オーバーライドした関数は単にスルーようにした)、ビルド。
デバッガで動きを追ってみる。

次は、アロケーターがDirect Draw Surfaceを返すように改造だ。
いよいよ核心ですな。
でも、CMemAllocatorではなく、CBaseAllocatorを継承した方がよい気がするなぁ・・・
メモリは確保せず、持っているサーフェイスのポインタを渡すだけだし。
でも、要求されたサイズがサーフェイスのサイズを上回っていたらどうするか・・・
エラーにするか、それともメモリ確保をして、多段コピーするようにするか。
デコーダーに渡す時に丸める処理を入れるから、上回ることはそんなに多くないだろうし、エラーにしても他のアロケーターが使われるだけだろうから、たいして問題はないでしょう。まあ、そのときは多段コピーで性能が落ちるけど致し方ない。

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

さくっと分離

レンダーを別ファイルに分離して、ソースの整理を行って、ビルドが通った。
グローバル変数はそのまま。
やっぱめんどうだし、そんなに多くないから今はいいやって感じで。
で、次はアロケーターとピンですね。

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

August 05, 2004

ソースの整理

レンダーを別ファイルに分離して、ソースの整理を行う。
でも、サンプルとはいえ、グローバル変数多すぎ。
ちょっと考えないと。
リファクタリング・リファクタリング。

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

最適化にハマる

このページこのページを読みながら最適化について少しはまる。
と言うか、元々そう言うことにハマりやすいたちで、今回も例に漏れずハマりかけております。
でも、まだ傷は浅くもう元の道に戻っています。
と言うより、コード量が少なくて最適化の余地がまだあまりなかったり。

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

開発日誌って・・・

開発日誌の増加量が半端ではない。
このまま行くとどうなってしまうのだろうか?
再利用性なんてあったもんじゃない。
最後にカテゴライズしてインデックスを作ればそこそこ後で見返すのも楽になるだろうか?
それよりも心配なのは、もっと時間のかかる物の開発を始めた時である。
その時はどうするのだろうか・・・
うーん・・・その時はその時ですね。
ああ、いいかげん。

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

ピン、アロケーターの振る舞いの確認

次の手順で進める。
Texture3Dのフィルター部のソースを分離&整理し、ピンとアロケーターを実装する。
ただし、まずは分離&整理を行う。
次に何もしないラッパーとして働く ( オーバーライドするが何もしない ) ピンとアロケーターを作り、動作を確認する。
後、もしかしたら、メディアサンプルも実装する必要があるかもしれない。

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

August 04, 2004

Texture3D(改)をメインに

サンプルのTexture3Dを改良していった方が簡単だと思い、その方向で行くことにした。
DirectDrawでいろいろやったのは何だったんだろうと言う考えが、頭をよぎるが気にしないことにする。
で、まずは必要のない3D関連の処理を取り、TextureをSurfaceにする。
デコーダーの出力形式をRGB32にするのは以外と簡単で、CheckMediaType内で受け入れる形式をRGB32にすれば、RGB32で出力してくれるようになった。
それと、MPEGファイル名が直値だったのをプログラムの実行ディレクトリ+ファイル名(直値)とした。
とりあえず、これでだいたい準備は整ったかな。
ヘルプも読んでだいたい理解したので、次はピンとアロケーターの作成だな。

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

バージョン管理

サンプルをいろいろといじるようになってきたので、バージョン管理でもしようと思い立ち、TortoiseSVNをさわる。
リポジトリの内容を見やすいようにViewCVSを入れようとここここを見る。
参考にしてインストール。
おお、いい感じに表示された。
RapidSVNも入れようとしたが、なぜかDL出来なかった。後でまた試すことにする。
WinMergeをまだ入れていなかったので、ついでにインストール。
マージするときのプログラムに設定しておく。

メモ
TortoiseSVN ユーザガイド

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

拡縮デコード

デコーダーに直接指定したバッファへ書き込みを行ってもらうことは可能なようだ。
それには、自前のアロケーターを準備すれば良いようだ。
任意位置への拡大縮小描画もできそうだ。
でも、任意位置って使えるのかなぁ・・・
まあ、使う場面はあることはあるか。
別にそうしなくてもいいような気もしないでもないが。

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

シーケンス図が書きたい

DirectShowのヘルプのデータフローの項を読みながら思う。シーケンス図が書きたい。

Visioがあれば、あまり好きではないがVisioでさくっと書くのだが、あいにく持っていない。
で、やっぱIIOSSかなと思い。
おもむろに最新版JavaをDL。もちろんSDKの方。
で、次にIIOSSをDL。
Javaをインストールした後、IIOSSのインストール方法を見ながらインストールする。
IDEはヒープサイズの初期化のところでエラーが出て起動できなかったが、とりあえずはMEFが使えたらよいので気にしないことにした。
これで、いろいろと図が描けるぞぅ。

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

August 03, 2004

Texture3D(改)の最適化

Texture3D(改)は重い。
MPEG Video Decoderから得たIMediaSampleをテクスチャにコピーし、それをまたバックバッファーにコピーしているので、かなり重いだろう。
でも、吉里吉里でも似たようなことになる。

まずは、テクスチャへのコピー処理を小手先で最適化する。少し軽くなった。でも、それほど軽くない。と言うか、重い。
MPEG Video DecoderからRGB24で受け取り、それをX8R8G8B8にコピーしている。
はじめから、MPEG Video DecoderにX8R8G8B8で吐いてもらえば、もっと処理を軽くできるのではないだろうか?
ヘルプのMPEG-1 ビデオ デコーダ フィルタ項を読む。
MEDIASUBTYPE_RGB32がサポートされている。
と言うことは、何とかなりそうだ。
さらに次のような記載がある。
このフィルタは、DirectDraw サーフェスへのデコードも可能である。
DirectDraw サーフェスが使えれば、このコピー処理の固まりは全部すっ飛ばせるのか・・・でも、今回は出来ない。ささっと諦める。

さらによく考えると、MPEG Video Decoderに途中のバッファに書いてもらえばよいのではないだろうか?
そうすれば1回コピーがなくなる。つまり、コピー処理が2/3になる。これはいい。
MPEG Video DecoderにRGB32で中間バッファに書き込んでもらえれば、ほとんどの処理はしなくていい。
吉里吉里ではこの中間バッファがレイヤーに当たるだろうから、かなり手間いらずだ。
でも、拡縮する場合は・・・ぐぉ、中間バッファに書き込んでもらう部分は複雑になりそうだ。
しかし、コピー回数を1回増やすのは避けたい。
まずはMPEG Video Decoderに直接書き込んでもらう方法を調査だ。
軽く調べるがこれはちょっと本腰を入れてヘルプを読まねばならなそうだ。
がんばって読むか。

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

DirectShow 実験プログラム第1段階 - 3

長くなったので、またまた分割。
ある程度やった内容に沿って、分けた方が良かったのではないかと、反省を始める。
まあ、今後はそうしようと言うことで今回はもう気にしない。
でも、この実験プログラムうんたらの前は分けている。
おいおい退化かよ。

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

BBS設置

BBSを設置した。
表示部分を結構いじったので、不具合があるかも。
まあ、大丈夫でしょう。

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

DirectShow 実験プログラム第1段階 - 2

かなり長くなってしまったので分離する。
なんか計画性は皆無だな。

メモ
超高速描画の謎--以前読んだ気もする・・・

DirectShowを扱う部分のコードを吉里吉里のからコピペして、改良していく。
とその前に、コメントとルールを決めておくことにした。
基本的にはDoxygenで自動的にドキュメント(関数リファレンス)を吐かせたいから、Doxygenの書き方には従う。
で、後は項目や細かい書き方だな。
以前、会社で作ったものを参考にしながら、自分の書きたいように作り直す。(こうゆう規約を作るのは、自分が多かったなぁ・・・)
ヘッダーコメントは//スタイルよりも/**/の方が書く量が減るし、書き始めが左に少しずれるので/**/を使うことにした。
そんな感じでだいたい決めた。
そのうち内規として上げておこう。

で、早速コーディングだと意気込んで。
まずはプロジェクトにDirectShowに必要なライブラリなどを加える。
そして、コーディング・・・よくわからない。
ヘルプとサンプル、ソースコードを何度も見直す。
そのうち何とかわかってきた。
とりあえずここにある程度まとめる。

吉里吉里のコードIStream周りを追う。深い。止める。
今回は、ファイルが独立しているので、IFileSourceFilterですませることにした。
ここでふと、Texture3Dを改良したプログラムで音が鳴っていなかったことに気付く。
そこで、GraphEditでシミュレートしようと思うが、独自に拡張したフィルタを追加する方法がわからない。GraphEditのヘルプを見ればいいんだろうが面倒だなぁと思っていると、実行中プロセスのフィルタグラフを見る方法があると書かれている。
そのためには、実行中オブジェクト テーブル (ROT)にプログラムで登録する必要があるらしい。
ここってハッと気付く、Texture3DのソースでなんとかROTと言う関数があって、よくわからない処理をしていたことを。
そう言うことだったのか。
今後は、DirectShowのプログラムを書くときは、デバッグ用にROTへの登録処理を書くことにする。
ちょっと話がそれたが、Texture3Dではそのままでグラフを見ることが出来るようなので、GraphEditで見る。
サウンドの出力がない。
とりあえず、練習用にこれにサウンドの出力を追加してみるか。

まず、DirectSoundのフィルターがなんかよくわからなかったので、IAMDirectSoundかな?と思い、おもむろにグラフビルダーにQueryInterfaceしてみる。後で気付くが、これははっきり言ってアホな行為です。
たぶん、IAMDirectSoundはフィルターではありません。DirectSoundフィルタのインターフェイスの一つです。
しかも、IGraphBuilderにQueryInterfaceしても見つからないと思われる。
まあ、このあたりのことはさらに理解が深まったときに書くとして、結果としてどうやったかを書きます。
CoCreateInstanceでCLSID_DSoundRenderを使い、DirectSoundフィルターを生成します。
フィルタグラフにDirectSoundフィルタを追加します。
MPEG-I Stream SplitterフィルタをフィルタグラフにFindFilterByNameで見つけます。
後は、両者のピンで合致するものを検索してつなげればできあがりです。
見事に音が鳴りました。
にしても、インターフェイスの継承関係を表したクラス図と、各インターフェイスが所持しているインターフェイスがわかる図がほしいなぁ。
どこかにないだろうか?
昔、macromedia DirectorのXDKを使ってXtra(プラグイン)を作るために、そんな感じの図を書いた記憶が・・・
DirectShowで似たようなものを書くのはちょっとしんどいな。便利そうだけど。
落ちていないかなぁ・・・うーむぅ。
まあ、それはいいとして、この実験でDirectShowについての理解がかなり深まった。

続く・・・

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

August 02, 2004

DirectShowっていったい・・・

私は馬鹿なのだろうか?
DirectShowのヘルプとサンプルを見ると何となくわかったような気になる。
でも、コーディングの時になると、やっぱりわからない。
たぶん、それでもほぼ期待した動作をするコードを書くことは出来るだろう。
何かが引っかかる。

グラフビルダーにムービーファイルを渡すと、最も基本的な構成でフィルタグラフを構築してくれる。
自分で構築したいときは、AddFilterを使ってフィルタを追加し、ピンを接続する。
でも、ピンの接続先は指定しない。勝手につないでくれる。
よくヘルプを見るとメディアタイプを指定することで、グラフビルダは正しい位置にフィルタを挿入できるとある。

GraphEditを少しいじってみて、ヘルプを読み直す。
ああ・・・、了解了解。
よく見ると接続先を指定している。
もう少し実験すれば確証が得られそうだ。

Texture3Dサンプルの場合
まず自作のCTextureRendererをグラフビルダーにAddFilterで追加している。
次にグラフビルダーのAddSourceFilterをコールすることで、ファイルを渡されたグラフビルダーがメディアを理解し、残りのフィルタグラフを自動的に構築するようにしている。この時点ですべてつながっているのではないかと思われるが、サンプルを見た感じでは、つながっていないようだ。
そして、CTextureRendererの入力ピンをCTextureRendererからFindPinで取得、ソースフィルタの出力ピンをソースフィルタからFindPinで取得し、その2つのピンをグラフビルダーのConnectでつなげている。Connectは必要であれば、間に適切なフィルタを挿入する。
つまり、グラフビルダーがどこまで自動的に構築できるかをよく認識し、自動的に出来ない部分を手動でつないでやる。と言うことのようだ。

IGraphBuilderとIFilterGraphで、フィルタグラフへのフィルタ追加&グラフ構築ができる手は限られている。
IFilterGraphはAddFilterとConnectDirectの2つ。
IGraphBuilderはConnect、Render、RenderFileとAddSourceFilterだ。

ちょっとメモ
メリット値
モニカ
続く・・・

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

Amazonで買えない時

Amazonで在庫切れになっていて買えない時、出版社に直接注文したら買える場合もあるようだ。

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

IRC チャンネルでのチャンネルの作り方

IRCでは、参加者が一人もいないチャンネルは自動的に消滅します。
逆に、それまで存在しなかったチャンネル名を入力すると自動的にチャンネルが作られます。

例えば、チャンネル名を『#gはいうおvhせ』などと適当に打って入室してみましょう。
すると、勝手に『gはいうおvhせ』というチャンネルが出来上がります。
当然、他の人が『gはいうおvhせ』に参加して普通に話す事も出来ます。

つまり、自分独自の部屋名を入力するだけで誰でも簡単にチャンネルを作る事が出来るのです。
-----------
そうだったのか。
知らなかった。
つまり、PC立ち上げっぱなしにして、ログインしておけば、そのチャンネルは維持されるわけか。

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

August 01, 2004

DirectShow 実験プログラム第1段階

とりあえずは、以前自分が作ったDirectDrawのプログラムと吉里吉里のソースとDirectShowを使った動画再生とフレームビットマップ取得方法のサンプルソースを参考に作る。

まずは、VCでプロジェクトを作って、draw.libをリンクに加え、Direct Drawの初期化部分を作る。
でも、なんでVCはあんなにAboutダイアログ好きなのだろう。私は、ほとんどの場合使わないのだが。。。
コーディングしながらふと気付く。DirectX5ぐらいのヘルプはないだろうか?
VC.NETのヘルプを見ても、そのあたりの関数は消えている。MSDNを入れれば復活するかなぁ。
そうだ、Cマガの付録から探せばいいんだ。
で、探すとあった。
DX5.2とDX7のヘルプとサンプルソースを入れる。
でも、DX5.2の日本語ヘルプはなくて、なぜかDX3のが入っていた。
まあ、DX7のヘルプがメインになるだろうから大丈夫だろう。

サンプルなどを見ていて思い出してきた。
このころはCOM丸出しだったんだった。

DX7使うにはdxguid.libも必要な様子。
フルスクリーンじゃないとバックバッファ使えないんだった。(本当にそうだったかなぁ?)
とりあえずは、DirectDrawを初期化してから、オフスクリーンバッファのポインタを取得して、そこへ書き込むまでは出来た。
予想外に手こずるなぁ。

DXMediaSDKのヘルプも必要そうなのでコピーしておく。
でも、英語版しかなかった。
まあ、それはともかく次はDirectShowだ。
上述のページによると・・・
streams.hとそれに必要なライブラリがサンプルのディレクトリ内にあり、ビルドするにはSDK内のdxsdk\samples\Multimedia\DirectShow\BaseClassesをINCLUDEディレクトリに追加し、 baseclasses.dswをビルドして得られるstrmbase.libとstrmbasd.libをリンクできるようにしておかなければならない。
・・・とある。
本当なの?と言うか、これ使ってしまっていいの?
後、吉里吉里は固めたファイル内からムービーを読み込むためにMicrosoftから提供されているasyncio.h/.cppとasyncrdr.h/.cppを使っているとか。
吉里吉里のkrmovieのプロジェクトを見てみると、strmbasd.libをリンクしていた。
それに、streams.hもインクルードしている。
やっぱり、必要なようだ。
よくヘルプを見ると、8以前のバージョンでは上記ライブラリはバイナリで提供されていたようだ。

DirectShowについて再びいろいろと調べる。少し理解が深まった。
そして、出来れば、吉里吉里の実装に近い形態で作りたいと思い、コードを追う。
IDirectDrawSurfaceが取得できれば・・・と思って、いろいろと調べるがよくわからず。と言うか、取得方法がない気がする。
結局、Dee氏に質問することにした。
結論はメモリへのポインタとして取得することしかできないとのこと。
まあ、DirectDrawだけだと自由度が低いし、Lock遅いって言うし、そう言う実装になりそうだなぁ。
---それといろいろと聞いたのでメモ
聞いたときのバージョンは吉里吉里2 2.22 rev.2/ KAG3 3.22 rev.2

オーバーレイクラスにレイヤーを渡し、そのレイヤーへビデオを書いてもらうような作りにする予定だが、そのレイヤーを渡すメソッドでは、TJSオブジェクトが渡されることになる。
つまり、実体はiTJSDispatch2。
そこから、tTJSNI_Layerを得るには、iTJSDispatch2::NativeInstanceSupportをコールする。
paramがプロパティに渡されたtTJSVariant型のオブジェクトだとしてparam.AsObjectNoAddRef()->NativeInstanceSupport(TJS_NIS_GETINSTANCE, tTJSNC_Layer::ClassID, (iTJSNativeInstance**)& tTJSNI_Layer型変数);でtTJSNI_Layerを取得できる。

tTJSNI_Layerで画像そのものへのポインタを得るには、
const void * GetMainImagePixelBuffer() const;
void * GetMainImagePixelBufferForWrite();
tjs_int GetMainImagePixelBufferPitch() const;
などを使う。

レイヤそのものは画像バッファしか持っていないし、DIBセクションであることもDirectDrawのSurfaceであることも期待できない。
ピクセルバッファのみへのアクセスしかtTJSNI_BaseLayerを通じては提供されていない。
DirectDrawは画面解像度の切り替えの時に使用して、あとは最終的な画像を画面に転送する際に(指定によっては)使用するが、そうでもなければ吉里吉里はいっさい使っていない。

レイヤには画像を書いただけだと何も起こらないので、書き込んだ後はtTJSNI_BaseLayer::Updateをコールしなければならない。
tTJSNI_BaseLayer::Updateはメインスレッドから呼ばないと変になるので、メインスレッドから呼ぶような実装にしなければならない。
つまり、別スレッドからイベントを投げて、ウィンドウのメッセージキューで処理すると良い。
TimerImpl.cpp (タイマ) で UtilWindow というのを使って実際にそういうことをやっているので、参考にすると良い。
tTJSNI_BaseLayer::Updateレイヤに変更が有ったという通知をするだけで、実際に描画が行われるのはその後、すべてのイベントが処理し終わった後になる。
イベントがほとんどない場合で、十分高速なPCだと、Updateを30fpsでコールすれば、描画サイクルも30fpsになる。

KAG のクリック待ちのアニメーションや文字表示のタイミングでタイマは使われている。そうでもなければKAGだとタイマは動いてないはず。

吉里吉里の Timer クラスで実装されているタイマーはWindowsの物ではなく、スレッドが一つ立ち上がってて複数のタイミングを管理しており、スレッドは次のタイマのイベントの時間が来るまでSleepで眠ってる。ただ、それだと精度が妖しいので timeGetTimeで補正している。
---メモ終わり
吉里吉里の実装に関するメモは分離して保存しておいた方がよいかも。

続く・・・

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

バージョン管理システムについてのメモ

使ったことがあるものと、これから使おうとしているものを比較してみる。
ただ、使ったことがあるものは少々バージョンが古かったりするので、現在のものとは違うかもしれない。
後、あんまり詳しく比較はしない。
と言うか、最もよく使う、チェックイン、チェックアウト、ロック、ロック解除ぐらいしか比較していない。

Visual SourceSafe 6.0
チェックアウト&ロック、チェックイン&ロック解除を持つ。
チェックアウトするとロックがかかり、チェックインするとロックが解除される。
チェックアウト以外に取得というものがあり、ソースはこれで取ってくる。
取得したソースは読み取り専用属性が付く。
編集する際はチェックアウトする。すると、ソースの読み取り専用属性が解除され、リポジトリ上のソースはロックされる。
編集が終わったらチェックインする。すると、ソースに読み取り専用属性が再び付き、ロックが解除される。
読み取り専用属性はローカルで簡単に解除できるけど、そんなことをしてもあんまり意味がないのでしない。
説明を読んでわかる通り、小規模開発向け。
でも、作りがシンプルな分使いやすい。
チェックアウト&ロックをした人と管理者が休むと作業が止まってしまうこともある。あんまりないけど、その時はとりあえず叫ぶ。
ただ、マージがほとんど発生しないので、精神的に良い。
マージは非生産的な作業の雰囲気を漂わせている上に、かなりの集中力がいるので、ファイル数が多いと相当辛い。

StarTeam 4.2
チェックイン、チェックアウト、ロック、ロック解除を持つ。
チェックイン、チェックアウトとロック、ロック解除が独立している。
当然、ロックしていないと、他の人が同じソースをチェックインして、マージが発生することがある。
ただし、生産性を下げないためにロックはあまりしない。
そのためマージ作業に遭遇するが、それは諦めるしかない。
もし、他の人が同じファイルをいじっているのを発見したら、出来るだけ早くmakeが通る状態にしてチェックインするのが吉。
そうすればマージ作業から逃れられる。チェックインは早い者勝ちなのだ。とにかく細かく早くリリースしよう。
ただ、焦って致命的なバグを入れてしまわないようにしよう。そんなことをしたら、かなり非難されてしまう。それと、チェックインを急いでいるのは出来るだけ周りに悟らないようにしよう。何食わぬ顔をしながら、素早くコーディングするのだ。
また、周りがどのような作業をしていて、どのファイルをさわっているかに常に気をつけておこう。同じファイルをいじる時期は出来たらずらしたい。かち合う場合はとにかく素早くコーディングだ!
また、ロック機構があるので、担当者に休まれたら叫ぶという状況は発生しうる。
なんか、いいとこなしのような印象を与えてしまうかもしれないが、実際はそんなことはない。
いろいろと機能盛りだくさんだし、それほど悪くはないシステムだ。
にしても、StarTeamってBorlandだったのか。違ったような気がしたが。
そもそも私が使っていたのは4.2とだいぶ古かったので、変わってしまったのかもしれない。

Subversion, CVS
コミット(チェックイン)、チェックアウトを持つ。
まだ使ったことはないので、よく知らない。
ただ、ロック機構がないので担当者不在で叫ぶことはない。
それに、フリーだ。
ただし、CVSはテキストを扱うことを主眼に作られているため、制止画や動画などの扱いは苦手らしい。
Subversionはマニュアルによるとバイナリファイルもうまく扱うようだ。
なお、この項は今後使っていくことで書き換えるかもしれない。

マージへの福音
辛く不毛なマージ作業。そのマージ作業を劇的に楽にしてくれるツールがある。
WinMergeだ。日本語版はこちら
このツールがあるとマージはかなり楽だ。一度使うとやめられない。
とりあえず、マージする予定があるのならインストールしておこう。
テキストのdiffをとるにも使えるし。

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

PC切り替え器

RATOC Systems, Inc.REX-210と言うPC切り替え器を使っているのだが、時々PCがおかしな挙動をしていた。
片方は、マウスのスクロールを動かすと進むや戻るが押されたような効果が出て、HPなど見ていたらページ飛びまくって大変なことになる。
もう片方はディスプレイの解像度が変になる。
何となく原因というか対処法らしき物がわかっていたのだが、今日ほぼ間違いないと思った。
それは、現在アクティブになっていない状態でPCを起動すると、前述の症状が出る。
つまり、アクティブにして起動すれば問題ない。
でも、こんな症状は自分だけなのだろうか。
似たような症状が出ている人っていますか?

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

boost regex++をBCB6に入れる

boostを取ってくる。
展開して、libs/regex/build に移動して、

make -fbcb6.mak
make -fbcb6.mak install

boost以下のインクルードファイル類はBCBのIncludeディレクトリーへ手でコピー。(なぜmake installでやってくれないのだろうか)

でも、makeはBorlandのやつが使われるようになっていたのか。って、他のmakeはまだ入れていないか。
後、実際に使うのはもう少し先になりそうだ。

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

ファイルの解凍

+Lhacaは時々解凍できずに落ちることがある。
今日はbz2を解凍しようとしたら落ちた。
少し前は1GB超のファイルを解凍しようとしていたら落ちた。

で、cygwinでも入れるかー、とやや落胆しながら考えていたのだが、ふとeoを入れてみた。
すると難なく解凍できた。
解凍はこれからeoにするかな。
+Lhacaは圧縮用だ。

ファイルが壊れていないかどうか確かめるためにMD5を確認する必要があった。
特に何もツールを入れていなかったので、Perlで組むかと、やや面倒臭げに考えるが、以前コマンドラインのツールを会社でDLして使ったことを思い出す。
早速ググって見つける。
これ
出来た出来た。

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

Total : Today : Yesterday :