フィルタクラスの実装
早速、フィルタクラスを実装していきましょう。コンストラクタで、入力ピンを2つ、出力ピンを1つ作成します。入力ピンのコンストラクタの引数としてチャンネル番号を渡します。0であればL、1であればRです。これにより、L/Rどちらのチャンネルを受け持っているか入力ピンのインスタンス自身が認識できるようになります。
// 入力ピンのコンストラクタは、次のようになっている。 // ch にチャンネル番号を渡す。 AudioInPin::AudioInPin(LPCTSTR pName, CBaseFilter *pFilter , CCritSec *pLock, HRESULT *phr, int ch); // フィルタクラスのコンストラクタ AudioChMuxerFilter::AudioChMuxerFilter(LPUNKNOWN pUnk, HRESULT *phr) : m_FilterLock(), CBaseFilter(FILTER_NAME, pUnk, &m_FilterLock, __uuidof(AudioChMuxerFilter)) { m_InPins[0]=m_InPins[1]=NULL; m_OutPin=NULL; if(FAILED(*phr)) return; m_InPins[0]= new AudioInPin(LIN_PIN_NAME, this, &m_FilterLock, phr, 0); if(FAILED(*phr)) return; m_InPins[1]= new AudioInPin(RIN_PIN_NAME, this, &m_FilterLock, phr, 1); if(FAILED(*phr)) return; m_OutPin= new AudioOutPin(this, &m_FilterLock, phr); }
AudioChMuxerFilter::GetPin
メソッドで、引数のインデックス値に対応したピンを返します。ここではインデックス値が0または1のときは入力ピン、2のときは出力ピンを返すことにします。
CBasePin *AudioChMuxerFilter::GetPin(int n) { switch(n) { case 0: return (CBasePin*)GetInPin(0); case 1: return (CBasePin*)GetInPin(1); case 2: return (CBasePin*)GetOutPin(); } return NULL; }
入力ピンクラスの実装
入力ピンとアップストリームフィルタの出力ピンを接続できるようにしましょう。今回は入力ピンが2つあるので、単に提示されたメディアタイプを検査するだけでなく、片方の入力ピンが接続済のとき、もう片方の入力ピンは同一メディアタイプでのみ接続できるようにします。こうすると、2つのピンの間で周波数やサンプルあたりのビット数が異なると接続できないようになります。
それにはAudioInPin::CheckMediaType
で、入力ピンが接続済かどうか確認し、もし接続済みであれば、どのメディアタイプで接続されているかを取得します。取得したメディアタイプと検査対象のメディアタイプとを比較することにより、同一メディアタイプでのみ接続を許可できます。
HRESULT AudioInPin::CheckMediaType(const CMediaType *pmt) { bool connected=false; // 接続済みフラグ CMediaType mt; // 接続済のメディアタイプ AudioChMuxerFilter *pFilter=(AudioChMuxerFilter*)m_pFilter; int idx = m_Channel == 0 ? 1 : 0; AudioInPin *pPin=pFilter->GetInPin(idx); if(pPin->IsConnected()!=NULL) { pPin->ConnectionMediaType(&mt); connected=true; } if (connected && mt!=*pmt) { // 同一メディアタイプではない。 } // ピンが接続されていない、または、同一メディアタイプ。 // 続いてメディアタイプpmtを検査する。 }
出力ピンクラスの実装
出力ピンとダウンストリームフィルタの入力ピンを接続できるようにしましょう。今回は2つの入力ピンが接続済でない場合は、接続できないようにします。
それにはAudioOutPin::CheckMediaType
で、2つの入力ピンが接続済であるか否かを取得し、どちらか一方でも接続されていない場合は接続拒否します。2つとも接続済であれば、メディアタイプを検査して接続可能かどうかを判定します。
HRESULT AudioOutPin::CheckMediaType(const CMediaType *pmt) { AudioChMuxerFilter *pFilter=(AudioChMuxerFilter*)m_pFilter; AudioInPin *pPin=pFilter->GetInPin(0); if(pPin->IsConnected()==NULL) { return S_FALSE; } pPin=pFilter->GetInPin(1); if(pPin->IsConnected()==NULL) { return S_FALSE; } // メディアタイプpmtを検査する。 }