1

directshow CBaseRenderer クラスから派生したカスタム directshow フィルターを作成しました。次のコードは私のフィルターです。

class CRenderSamples : public CBaseRenderer
{
// private data members
// constructors and destructors are private, need to use CoCreateInstance(.)
protected:
    //BYTE *m_pCopyBuffer;
    CMediaType m_MediaType;

    CRenderSamples(LPUNKNOWN pUnk,HRESULT *phr);
    virtual ~CRenderSamples();

public:
    //The CheckMediaType method determines if the 
    //filter accepts a specific media type.
    virtual HRESULT CheckMediaType(const CMediaType *pMediaType);

    // The DoRenderSample method renders a sample.
    virtual HRESULT DoRenderSample(IMediaSample *pMediaSample);

    // Instantiate filter object
    static CUnknown * WINAPI CreateInstance(LPUNKNOWN pUnk, HRESULT *phr);

};

フィルターを正常に作成し、COM に登録しました。また、GraphEdit で pushsourcedesktop フィルターと組み合わせてフィルターをテストしたところ、期待どおりに動作しました。問題はコーディングにあります。フィルター オブジェクトのインスタンス化に使用するポインターの型について、少し混乱しています。IBaseFilter ポインターを使用してフィルター オブジェクトをインスタンス化すると、すべて正常に動作しますが、独自のフィルターに実装する DoRenderSamBple() メソッドを使用できません。ただし、CBaseRenderer を使用すると、AddFilter() 関数の最初のパラメーターが IBaseFilter ポインターを必要とするため、ランタイム エラーが発生します。次のコードは私のアプリです。

#include <stdio.h>
#include <windows.h>
#include <ObjBase.h>
#include <DShow.h>
#include <initguid.h>
#include <stdlib.h>
#include <streams.h>
#include "PushGuids.h"

//#pragma once
#pragma comment(lib,"Strmiids.lib") 

static const GUID CLSID_RENDER_SAMPLES = {0x9ddd8a2a, 0xa66c, 0x423a, { 0xa7, 0xb1, 
                    0xc3, 0x22, 0xae, 0xbc, 0x1c, 0x1e } };


int CALLBACK WinMain(
  _In_  HINSTANCE hInstance,
  _In_  HINSTANCE hPrevInstance,
  _In_  LPSTR lpCmdLine,
  _In_  int nCmdShow
){
    IGraphBuilder *pGraph = NULL;
    IMediaControl *pControl = NULL;
    IMediaEvent*   pEvent = NULL;


    HRESULT hr = CoInitialize(NULL);
    if (FAILED(hr)) {
         MessageBox(NULL,TEXT("ERROR - Could not initialize COM library."),TEXT("Error!"),MB_OK);
        return EXIT_FAILURE;
    }


    hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, 
            IID_IGraphBuilder, (void **)&pGraph);
    if (FAILED(hr)) {
        MessageBox(NULL,TEXT("Could not create the Filter Graph    Manager."),TEXT("Error!"),MB_OK);
        return EXIT_FAILURE;
    }

    hr = pGraph -> QueryInterface(IID_IMediaControl, (void **)&pControl);
    hr = pGraph -> QueryInterface(IID_IMediaEvent, (void **)&pEvent);


    IBaseFilter* pPushSourceDesktop = 0;
    hr = CoCreateInstance(CLSID_PushSourceDesktop, 0, CLSCTX_INPROC_SERVER,
                IID_IBaseFilter, (void**)&pPushSourceDesktop);

    if (FAILED(hr)) {
        MessageBox(NULL,TEXT("Could not create PushSourceDesktop filter."),TEXT("Error!"),MB_OK);
        return EXIT_FAILURE;
    }


    hr = pGraph -> AddFilter(pPushSourceDesktop, L"PushSourceDesktop"); 
    if (FAILED(hr)) {
        MessageBox(NULL,TEXT("Could not add PushSourceDesktop filter."),TEXT("Error!"),MB_OK);
        return 0;
    }

    //IBaseFilter *pRenderSamples;  
    CBaseRenderer *pRenderSamples;
    //IBaseFilter *pRenderer;
    hr = CoCreateInstance(CLSID_RENDER_SAMPLES,0,CLSCTX_INPROC_SERVER,
                IID_IBaseFilter, (void**)&pRenderSamples);
    if (FAILED(hr)) {
        MessageBox(NULL,TEXT("Could not instantiate RenderSamples."),TEXT("Error!"),MB_OK);
        return EXIT_FAILURE;
    }else{
        MessageBox(NULL,TEXT("Successfully instantiate RenderSamples filter."),TEXT("Success!"),MB_OK);
    }

    hr = pGraph -> AddFilter(pRenderSamples, L"Render Samples"); 
    if (FAILED(hr)) {
        MessageBox(NULL,TEXT("Could not add RenderSamples filter."),TEXT("Error!"),MB_OK);
        return EXIT_FAILURE;
    }else{
        MessageBox(NULL,TEXT("Successfully add RenderSamples filter."),TEXT("Success!"),MB_OK);
    }

    IPin **ppPushPinDesktop = new (IPin*);
    hr = pPushSourceDesktop -> FindPin(L"1", ppPushPinDesktop); 
    if (FAILED(hr)) {
        MessageBox(NULL,TEXT("Could not find pin of filter PushSourceDesktop."),TEXT("Error!"),MB_OK);
        return EXIT_FAILURE;
    }

    IPin **ppRenderSamples = new (IPin*);
    hr = pRenderSamples -> FindPin(L"In", ppRenderSamples); 
    switch(hr)
    {
        case S_OK:
            MessageBox(NULL,TEXT("Successfully find pin."),TEXT("Success!"),MB_OK);
            break;
        case E_POINTER:
            MessageBox(NULL,TEXT("Null pointer argument."),TEXT("Null Pointer!"),MB_OK);
            return EXIT_FAILURE;
        case VFW_E_NOT_FOUND:
            MessageBox(NULL,TEXT("Could not find a pin with this identifier."),TEXT("Error!"),MB_OK);
            return EXIT_FAILURE;
    }

    hr = pGraph -> Connect(*ppPushPinDesktop,*ppRenderSamples);
    switch(hr){
        case S_OK:
            MessageBox(NULL,TEXT("Successfully connect PushSourceDesktop and RenderSamples."),TEXT("Success!"),MB_OK);
            break;
        case VFW_S_PARTIAL_RENDER:
            MessageBox(NULL,TEXT("Partial success; some of the streams from this pin use an unsupported format."),
                        TEXT("Partial success!"),MB_OK);
            break;
        case E_ABORT:
            MessageBox(NULL,TEXT("Operation aborted."),TEXT("Aborted!"),MB_OK);
            break;
        case E_POINTER:
            MessageBox(NULL,TEXT("NULL pointer argument."),TEXT("NULL Pointer!"),MB_OK);
            break;
        case VFW_E_CANNOT_CONNECT:
            MessageBox(NULL,TEXT("No combination of intermediate filters could be found to make the connection."),TEXT("Aborted!"),MB_OK);
            break;
        case VFW_E_NOT_IN_GRAPH:
            MessageBox(NULL,TEXT("At least one of the filters is not in the filter graph."),TEXT("Filter no in filter graph"),MB_OK);
            break;
        default:
            MessageBox(NULL,TEXT("Unknow error"),TEXT("Error!"),MB_OK);
            return EXIT_FAILURE;
    }

    pControl -> Release();
    pEvent -> Release();

    (*ppPushPinDesktop) -> Release();
    pPushSourceDesktop -> Release();

    pRenderSamples-> Release();
    (*ppRenderSamples)->Release();

    pGraph -> Release();
    CoUninitialize(); 

    return EXIT_SUCCESS;
}

誰でもそのような問題を解決するためのアイデアを与えることができますか? どうもありがとうございました!!!

4

1 に答える 1

0

フィルターを COM クラス/オブジェクトとして形成したので、そこから COM インターフェイス ポインターを操作する必要があります。フィルタをグラフに追加してストリーミングを開始する場合、ほとんどの場合、制御アプリとフィルタの間でカスタムの直接対話を行う必要はありません。

ただし、それが必要な場合は、フィルター/ピンに追加のインターフェイスを実装する必要があります (パブリックに利用できるという点で「プライベートインターフェイス」と呼ばれますが、アプリとフィルターのみに認識されるため、他の誰も使用していません) )、およびその上で必要なメソッド。アプリケーションは 経由でポインタを取得し、QueryInterface必要に応じてメソッドを呼び出すことができます。

通常の DirectShow ストリーミングの一部として、レンダラーは標準パス経由でサンプルを受け取りIPin::Receiveます。制御アプリケーションから外部呼び出しを実行する必要はありません。

于 2013-08-29T08:18:05.987 に答える