如何将我的directshow过滤器添加到过滤器图形中

时间:2013-08-29 07:49:51

标签: c++ filter render directshow

我编写了一个自定义directshow过滤器,派生自directshow CBaseRenderer类。以下代码是我的过滤器。

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中注册它。 Alos,我已经在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;
}

任何人都可以提出解决此类问题的任何想法。非常感谢你!!!

1 个答案:

答案 0 :(得分:0)

由于您将过滤器塑造为COM类/对象,因此您应该使用COM接口指针。当您将过滤器添加到图表并开始流式传输时,通常您不需要在控制应用程序和过滤器之间进行任何自定义直接交互。

如果你想拥有它,你需要在你的过滤器/引脚上实现一个额外的接口(所谓的“私人接口”,因为它可以公开使用但是你的应用和过滤器只知道其他人正在使用它,以及必要的方法。应用程序将通过QueryInterface获取指针,并且可以根据需要调用方法。

作为普通DirectShow流的一部分,渲染器通过标准路径IPin::Receive接收样本,并且它不需要您从控制应用程序执行任何外部调用。