手順 4. アロケータ プロパティの設定
注 : この手順は CTransInPlaceFilter から派生するフィルタには必要ない。
2 つのピンでメディア タイプが一致した後、接続用のアロケータを選択し、バッファ サイズ、バッファ数などのアロケータ プロパティを調整する。
CTransformFilter クラスには、アップストリーム ピン接続用とダウンストリーム ピン接続用に 1 つずつ、合計 2 つのアロケータがある。アップストリーム フィルタはアップストリーム アロケータを選択し、アロケータ プロパティも選択する。入力ピンは、アップストリーム フィルタが決める内容をすべて受け入れる。この動作を変更する必要がある場合、CBaseInputPin::NotifyAllocator メソッドをオーバーライドする。
変換フィルタの出力ピンはダウンストリーム アロケータを選択する。次の手順を実行する。
- ダウンストリーム フィルタがアロケータを提供できる場合、出力ピンはそのアロケータを使う。それ以外の場合、出力ピンは新しいアロケータを作成する。
- 出力ピンは IMemInputPin::GetAllocatorRequirements を呼び出し、ダウンストリーム フィルタのアロケータ要件を取得する (存在する場合)。
- 出力ピンは変換フィルタの CTransformFilter::DecideBufferSize メソッドを呼び出す。このメソッドは純粋仮想メソッドである。このメソッドのパラメータはアロケータへのポインタ、ダウンストリーム フィルタの要件が入った ALLOCATOR_PROPERTIES 構造体である。ダウンストリーム フィルタにアロケータ要件がない場合、構造体は削除される。
- DecideBufferSize メソッドで、派生クラスは IMemAllocator::SetProperties を呼び出して、アロケータ プロパティを設定する。
一般に、派生クラスは、出力フォーマット、ダウンストリーム フィルタの要件、フィルタ自体の要件に基づいてアロケータ プロパティを選択する。ダウンストリーム フィルタの要求と互換性があるプロパティを選択すること。それ以外の場合、ダウンストリーム フィルタは接続を拒否することがある。
次の例で、RLE エンコーダはバッファ サイズ、バッファ アラインメント、バッファ カウントの最小値を設定する。プレフィックスには、ダウンストリーム フィルタが要求した値を使う。通常、プレフィックスはゼロ バイトだが、プレフィックスを必要とするフィルタもある。たとえば、AVI Mux フィルタはプレフィックスを使って RIFF ヘッダーを書き込む。
HRESULT CRleFilter::DecideBufferSize(
IMemAllocator *pAlloc, ALLOCATOR_PROPERTIES *pProp)
{
AM_MEDIA_TYPE mt;
HRESULT hr = m_pOutput->ConnectionMediaType(&mt);
if (FAILED(hr))
{
return hr;
}
ASSERT(mt.formattype == FORMAT_VideoInfo);
BITMAPINFOHEADER *pbmi = HEADER(mt.pbFormat);
pProp->cbBuffer = DIBSIZE(*pbmi) * 2;
if (pProp->cbAlign == 0)
{
pProp->cbAlign = 1;
}
if (pProp->cBuffers == 0)
{
pProp->cBuffers = 1;
}
// フォーマット ブロックを解放する。
FreeMediaType(mt);
// アロケータ プロパティを設定する。
ALLOCATOR_PROPERTIES Actual;
hr = pAlloc->SetProperties(pProp, &Actual);
if (FAILED(hr))
{
return hr;
}
// 成功した場合も、実際の結果を確認する。
if (pProp->cbBuffer > Actual.cbBuffer)
{
return E_FAIL;
}
return S_OK;
}
アロケータは要求に対して正確に一致できるとは限らない。したがって、SetProperties メソッドは別の ALLOCATOR_PROPERTIES 構造体で実際の結果を返す (前の例では Actual パラメータ)。SetProperties が成功しても、結果を調べ、フィルタの最小限の要件を満たしていることを確認する必要がある。
カスタム アロケータ
デフォルトでは、すべてのフィルタ クラスがそのアロケータに CMemAllocator クラスを使う。このクラスはクライアント プロセスの仮想アドレス空間からメモリを割り当てる (VirtualAlloc を使用)。フィルタが DirectDraw サーフェイスなど、他の種類のメモリを使う必要がある場合、カスタム アロケータを実装できる。CBaseAllocator クラスを使え、また完全に新しいアロケータ クラスを作成することもできる。フィルタにカスタム アロケータがある場合、アロケータを使うピンに従って次のメソッドをオーバーライドすること。
- 入力ピン : CBaseInputPin::GetAllocator および CBaseInputPin::NotifyAllocator
- 出力ピン : CBaseOutputPin::DecideAllocator
他のフィルタがカスタム アロケータを使った接続を拒否する場合、フィルタはその接続を失敗するか、相手のフィルタのアロケータを使って接続できる。相手のフィルタのアロケータを使う場合、アロケータのタイプを示す内部フラグの設定が必要になることがある。この方法の例については、「CDrawImage クラス」を参照すること。