SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

DirectShowフィルタの作成

オーディオチャンネルを分離する
DirectShowフィルタの作成 - 後編

複数の出力ピンを持つDirectShowフィルタの作成方法

  • X ポスト
  • このエントリーをはてなブックマークに追加

ダウンストリームフィルタへの通知

 ファイルから再生して終端に到達したときや、シークによるフラッシュイベントが発生したとき、アップストリームフィルタから通知を受け取ります。通知を受け取ったらダウンストリームフィルタに通知を転送する必要があります。

図1. イベントが発生したとき
図1. イベントが発生したとき

ストリーム終了通知

 再生すべきストリームが終わったときに「ストリーム終了通知(EndOfStream)」を受け取ります。主にファイルの終端に到達した場合に発生します。通知を受け取ったフィルタは、ダウンストリームフィルタの入力ピンに対してIPin::EndOfStreamを呼び出します。 

フラッシュの開始と終了および新セグメント通知

 ファイルを再生中にシークした場合、迅速に新しい位置から再生するためにフラッシュの開始通知が行われます。フィルタは現在処理中または内部で保留しているサンプルを速やかに破棄します。その後フラッシュの終了通知が行われ、フィルタは新しいサンプルを受け付けられる状態になります。最後に、新セグメント通知が行われます。

呼び出すメソッド

 通知を受け取るとき、それに対応する入力ピンのメソッドが呼ばれます。次にCBaseOutputPinの「Deliver」で名前が始まる4つのメソッドをオーバーライドしておき、それを入力ピンから呼び出します。最後に対応するCOutputQueueのメソッドを呼び出します。例えばフラッシュの開始通知であれば、まずアップストリームフィルタの出力ピンが、入力ピンのBeginFlushを呼び出します。入力ピンは出力ピンのDeliverBeginFlushを呼び出します。出力ピンはCOutputQueue::BeginFlushを呼び出し、出力キューに入れます。COutputQueueはストリーミングスレッドでダウンストリームフィルタの入力ピンへ渡します(表2、図2)。

表2.通知と、それに対応するメソッド
種類 入力ピン 出力ピン COutputQueue
フラッシュの開始 BeginFlush DeliverBeginFlush BeginFlush
フラッシュの終了 EndFlush DeliverEndFlush EndFlush
新セグメント NewSegment DeliverNewSegment NewSegment
ストリーム終了通知 EndOfStream DeliverEndOfStream EOS
図2.フラッシュの開始通知の例
図2.フラッシュの開始通知の例
//フラッシュの開始通知のコード
STDMETHODIMP AudioInPin::BeginFlush(void) {
    CAutoLock my_lock(m_pLock);
    NOTE1("%S", __FUNCTION__);
    __super::BeginFlush();
    AudioChSplitterFilter *filter=(AudioChSplitterFilter*)m_pFilter;
    filter->GetOutPin(0)->DeliverBeginFlush();
    filter->GetOutPin(1)->DeliverBeginFlush();
    return S_OK;
}
HRESULT AudioOutPin::DeliverBeginFlush() {
    if(m_OutQ)
        m_OutQ->BeginFlush();
    return S_OK;
}

シークのサポート

 フィルタグラフに対してシーク要求を行うと、各レンダリングフィルタにそれが通知されます。要求を受け取ったフィルタはシークをサポートしていれば、その処理を行い、そうでなければアップストリームフィルタへ要求を渡します。このシーク要求を渡す処理をしてくれるのがCPosPassThruです。

 出力ピンクラスでCUnknown::NonDelegatingQueryInterfaceをオーバーライドし、シーク用のインターフェイスであるIID_IMediaPositionIID_IMediaSeekingのインターフェイスが要求されたら、インスタンスが無い場合は作成し、CPosPassThruQueryInterfaceを呼び出します。

STDMETHODIMP
AudioOutPin::NonDelegatingQueryInterface(REFIID riid, void **ppv) {
    HRESULT hr;
    if(riid==IID_IMediaPosition || riid==IID_IMediaSeeking) {
        if(m_PosPass==NULL) {
            hr=CreatePosPassThru(GetOwner(), FALSE
                , m_pFilter->GetPin(0), (IUnknown**)&m_PosPass);
            if (FAILED(hr)) return hr;
        }
        return m_PosPass->QueryInterface(riid, ppv);
    } 
    return __super::NonDelegatingQueryInterface(riid, ppv);
}

次のページ
サンプルの転送

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
DirectShowフィルタの作成連載記事一覧

もっと読む

この記事の著者

syu5()

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/3090 2008/12/13 13:49

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング