カクタスソフトウェア
カクタスソフトウェア
サウンド MIDI マルチメディア アプリケーション

インプレイスフィルター

インプレイスフィルターは入力ピンに渡されたバッファをそのまま出力ピンへ伝えます。バッファの内容を参照するだけのフィルターや、単に書き換えるだけのフィルターに適します。入力と出力でデータの属性や長さを変更することはできません。インプレイスフィルターはCTransInPlaceFilterクラスから派生させます。

class CMyFilter : public CTransInPlaceFilter
{
...

CTransInPlaceFilterクラスを用いる場合、以下の関数をオーバーライドする必要があります。

特に通過するデータを参照するだけのフィルターを「サンプルグラバフィルター」と呼びます。

以下にインプレイスフィルターで必要な関数を紹介します。

CreateInstance

フィルターのインスタンスを生成する関数です。

CUnknown* WINAPI CMyFilter::CreateInstance(
    LPUNKNOWN       punk,
    HRESULT         *phr)
{
    ASSERT(phr);
    CMyFilter *pNewObject = new CMyFilter(punk, phr, true);

    if (pNewObject == NULL)
    {
        *phr = E_OUTOFMEMORY;
    }
    return pNewObject;
}

コンストラクター

CMyFilter::CMyFilter(LPUNKNOWN punk, HRESULT *phr, bool modifiesData)
    : CTransInPlaceFilter(NAME("MyFilter"), punk, CLSID_MY_FILTER, phr, modifiesData)
{
    // TODO:
}

CMyFilter::~CMyFilter()
{
    // TODO:
}
NAMEマクロはデバッグの時のみ文字列を生成します。リテールバージョンではNULLとなります。

CTransInPlaceFilterの5番目の引数はTransform()関数内でデータを変更するかどうかを示します。trueを指定した場合、データ変更ありの意味になります。Transform()関数でデータの参照しか行わない場合はfalseを指定します。

    CTransInPlaceFilter(
        TCHAR           *tszName,
        LPUNKNOWN       punk,
        REFCLSID        clsid,
        HRESULT         *phr
        bool            bModifiesData = true)

CheckInputType

この関数はピン接続が可能かどうかをチェックするために、ピンを接続する前にコールされます。この関数がエラーを戻すと、ピン接続は失敗します。カスタムフィルターを設計する場合、フィルターで処理する形式以外はVFW_E_TYPE_NOT_ACCEPTEDを戻すようにします。

以下の例では次の条件をすべて満たした場合のみNOERRORを戻します。

サンプリング周波数は任意です。

HRESULT CMyFilter::CheckInputType(const CMediaType *pmt)
{
    CheckPointer(pmt, E_POINTER);

    WAVEFORMATEX *pwfx = (WAVEFORMATEX*)pmt->pbFormat;

    // オーディオのみ受け付ける

    if (pmt->majortype != MEDIATYPE_Audio)
    {
        return VFW_E_TYPE_NOT_ACCEPTED;
    }
    // WAVEFORMATEX構造体かチェック

    if (pmt->formattype != FORMAT_WaveFormatEx)
    {
        return VFW_E_TYPE_NOT_ACCEPTED;
    }
    // PCMのみ受け付ける

    if (pwfx->wFormatTag != WAVE_FORMAT_PCM)
    {
        return VFW_E_TYPE_NOT_ACCEPTED;
    }
    // 8Bitと16Bitのみ受け付ける

    if ((pwfx->wBitsPerSample != 8)&&(pwfx->wBitsPerSample != 16))
    {
        return VFW_E_TYPE_NOT_ACCEPTED;
    }
    return NOERROR;
}

Transform

この関数は定期的に呼び出され、フィルターを通過するデータにアクセスすることができます。

バッファのアドレスは、IMediaSample::GetPointer()関数で取得します。データの有効長は、IMediaSample::GetActualDataLength()関数で取得します。このバッファのデータはそのまま出力ピンから次のフィルターへ転送されます。

正常に出力用データを用意できた時は、S_OKを戻します。何らかのエラーにより出力用データを用意できなかった時は、S_FALSEを戻します。

HRESULT CMyFilter::Transform(IMediaSample *pMediaSample)
{
    CAutoLock cAutolock(&m_AudioLock);

    BYTE *pSampleBuffer = NULL;
    pMediaSample->GetPointer(&pSampleBuffer);
    long lDataLength = pMediaSample->GetActualDataLength();

    // TODO:

    return S_OK;
}

この関数で用いているCAutoLockクラスはクリティカルセクションをラッピングしたものです。ヘッダーファイルにCCritSecの変数を定義しておきます。cAutolockのインスタンスが有効な期間、他のスレッドをブロックします。

    CCritSec        m_AudioLock;        // Critical Section

必要であれば、IMediaSample::GetTime()関数を用いてデータのストリームタイムを取得することができます。ストリームタイムはフィルタグラフがスタートした時刻を起点とした時刻です。

    REFERENCE_TIME  tStart;
    REFERENCE_TIME  tEnd;
    pMediaSample->GetTime(&tStart, &tEnd);

CTransInPlaceFilterクラスはCTransformFilterクラスを継承しています。以下の関数はCTransformFilterクラスでvirtualとして宣言されているため、CTransInPlaceFilterクラスでの定義が必要です。しかしCTransInPlaceFilterクラスではこれらの関数は必要ないため、ヘッダーにダミーとして定義されています。

出力ピンのメディアタイプは入力ピンと同じなのでGetMediaType()関数はコールされません。

入力バッファがそのまま出力へ伝えられるのでDecideBufferSize()関数は必要ありません。

メディアタイプの変更は起こらないのでCheckTransform()関数は常にS_OKを戻します。

ドキュメントの先頭へ

カクタスソフトウェア 技術協力 資料室 資料室の広場 SourceForge.jp お問い合わせ