ほっしーの技術ネタ備忘録

技術ネタの備忘録です。基本的に私が忘れないためのものです。他の人の役にも立つといいなぁ。

DirectShow フィルタではまった


最初、フィルタは煩雑だから DMO ( DirectShow Media Object ) で実装しようとした。


実装補助というか、基底クラスが DirectShow SDK に入ってたから派生して書いて…
COM 化するために IUnknown インターフェースを用意する段階になっていざ、
「IMediaObjectImpl が CUnknown からの派生じゃない」ことに気づいた。
IUnknown を自前で実装するのも面倒だったので却下。


で、基底クラスの CTransformFilter から派生してフィルタを実装してみたわけだが…
MSDN 通りにいろいろ関数を実装して COM DLL 化はあっさり成功。
regsvr32.exe による自己登録も難なく完了…だが。


こっちの InputPin がファイルリーダ (Async) フィルタに接続できない謎。


半日ほど MSDN を読み漁った挙句、InputPin の接続完了時に対象ピンに対して
IAsyncReader インターフェースの問い合わせを行わないと切られるらしい。


で、参照をたどると CPullPin という便利なものが付属している模様。
このクラス内部でスレッドを起こして、リーダフィルタの出力ピンから
IAsyncReader を引っ張ってきてぐーるぐる回してくれる模様。


でっ。私はこう実装してみたわけさ。

class CMyInputPin : public CTransformInputPin, public CPullPin
{
public:
    HRESULT Receive( CMediaSample* pSample ) {
        return CTransformInputPin( pSample );
    }
〜省略〜
};


すると、ワーカースレッドの CPullPin::Process() から純粋仮想関数で
CMyInputPin::Receive() を呼んで、基底の CTransformInputPin::Receive() 経由で
CTranformFilter::Receive() に転送。というシナリオが頭にあったんですよ。


そしたらコンパイルエラー。調べてみると…

HRESULT __stdcall CBasePin::Receive( CMediaSample* pSample );
HRESULT CPullPin::Receive( CMediaSample* pSampel ) = 0;


うがー。頼むから統一してくれよ。