入力ピンクラスの実装
クラス定義
フィルタクラスの定義が終わったので、次は入力ピンクラスAudioInPinを定義しましょう。フィルタクラスをCBaseFilterから派生させた場合、基本的に入力ピンクラスはCBaseInputPinから派生させます。いくつかオーバーライドすべきメソッドがあります(表4)。
| メソッド名 | 説明 |
| BeginFlush | フラッシュの開始時に呼ばれる。 |
| EndFlush | フラッシュの終了時に呼ばれる。 |
| EndOfStream | ストリーム終了通知を受け取るときに呼ばれる。 |
| Receive | サンプルを受信したときに呼ばれる。 |
| GetMediaType | 優先メディアタイプを提示する。 |
| CheckMediaType | ピンが特定のメディア タイプを受け入れるかどうかを判定する(純粋仮想)。 |
class AudioInPin : public CBaseInputPin
{
public:
AudioInPin(CBaseFilter *pFilter
, CCritSec *pLock
, HRESULT *phr);
virtual ~AudioInPin();
// IPin
STDMETHODIMP BeginFlush(void);
STDMETHODIMP EndFlush(void);
STDMETHODIMP EndOfStream(void);
STDMETHODIMP Receive(IMediaSample *pSample);
// CBaseInputPin
HRESULT GetMediaType(int iPosition, CMediaType *pMediaType);
HRESULT CheckMediaType(const CMediaType *pmt);
};
コンストラクタ・デストラクタ
入力ピンのコンストラクタでは特に必要な処理はありません。フィルタクラスと同様に、基底クラスであるCBaseInputPinを初期化するだけです。
AudioInPin::AudioInPin(CBaseFilter *pFilter
, CCritSec *pLock, HRESULT *phr) :
CBaseInputPin(INPUT_PIN_NAME, pFilter, pLock, phr, INPUT_PIN_NAME)
{
NOTE1("%S", __FUNCTION__);
}
デストラクタでは何もすることがないので、コードは割愛します。
ピンを接続できるようにする
今回作成するフィルタの入力ピンとアップストリームフィルタにある出力ピンを接続できるようにしましょう。ピン同士を接続するには、お互いのピンが許容するメディアタイプで接続する必要があります。
まずGetMediaTypeを実装します。このメソッドでは、このピンが受け入れる優先メディアタイプを提示します。今回は何も提示しません。原則、フィルタは上流から下流に向かって順に接続されるため、上流フィルタから出力するメディアタイプが確定されていくからです。そのため基本的に入力ピンが優先メディアタイプを提示する必要はありません。
HRESULT AudioInPin::GetMediaType(int iPosition, CMediaType *pMediaType) {
NOTE1("%S",__FUNCTION__);
if(iPosition<0)
return E_INVALIDARG;
return VFW_S_NO_MORE_ITEMS;
}
次にCheckMediaTypeです。このメソッドは引数として渡されたメディアタイプで接続可能かどうかを判定します。今回はステレオのオーディオストリームのみ接続可能として判定する処理を実装します。
HRESULT AudioInPin::CheckMediaType(const CMediaType *pmt) {
NOTE1("%S", __FUNCTION__);
int eq_major =(pmt->majortype==MEDIATYPE_Audio);
int eq_sub =(pmt->subtype==MEDIASUBTYPE_PCM);
int eq_format=(pmt->formattype==FORMAT_WaveFormatEx);
if(eq_major && eq_sub && eq_format) {
if(pmt->Format()==NULL)
return S_FALSE;
if(pmt->FormatLength()!=sizeof(WAVEFORMATEXTENSIBLE) &&
pmt->FormatLength()!=sizeof(WAVEFORMATEX))
{
return S_FALSE;
}
WAVEFORMATEXTENSIBLE *wfxe=
(WAVEFORMATEXTENSIBLE *)pmt->Format();
if((wfxe->Format.wFormatTag==WAVE_FORMAT_EXTENSIBLE ||
wfxe->Format.wFormatTag==WAVE_FORMAT_PCM) &&
wfxe->Format.nChannels==2)
{
return S_OK;
}
return S_FALSE;
}
return S_FALSE;
}
上記コードでは、WAVEFORMATEXだけでなく、多チャンネル、高精度PCMフォーマットを表すときに使われるWAVEFORMATEXTENSIBLEも許容する判定処理を行っています。
WAVEFORMATEXTENSIBLEではwFormatTagの値がWAVE_FORMAT_EXTENSIBLEになります。オーディオサブタイプのGUIDはwFormatTagによって変化しますが、無圧縮の整数PCMであるため同じ値となります。
残りのメソッドは、サンプルの転送に関わることなので後編で実装します。
動作確認
まだ未実装な個所があるので、適当に修正してコンパイルします。その後、GraphEditを使って動作確認をしてみます(図3)。
ファイルソースフィルタをアップストリームフィルタとして接続できないことに注意してください。ファイルソースフィルタはプルモデルとよばれる出力ピンを持ちますが、作成したフィルタはそれに対応していません。そこでプルモデルの出力ピンと接続できるWave Parserを間に挟みます。

前編のまとめ
本稿ではCBaseFilterから派生したフィルタクラスを実装しました。次にCBaseInputPinから派生した入力ピンクラスを実装し、アップストリームフィルタに接続するところまでできました。後編では、以下に挙げる残りのタスクを進めていきます。
- 出力ピンを実装し、接続できるようにする。
- 出力ピンごとにストリーミングスレッドを作成する。
- サンプルを転送する。
