如何将我的directshow筛选器添加到筛选器图中

How to add my directshow filter into filter graph

本文关键字:筛选 添加 我的 directshow      更新时间:2023-10-16

我已经编写了一个自定义的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中。同时,我已经在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;
}

有人能想出解决这个问题的办法吗。非常感谢您!!!

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

然而,如果你想拥有它,你需要在你的过滤器/引脚上实现一个额外的接口(所谓的"私人接口",因为它对公众可用,但对你的应用程序和过滤器来说是已知的,所以没有人在使用它),以及必要的方法。应用程序将通过QueryInterface获得指针,并能够根据需要调用方法。

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