直接显示过滤器中的调用约定

Luk*_*uke 3 c++ com directshow

当我调用过滤器 getpin() 方法时出现以下异常:

运行时检查失败 #0 - ESP 的值未在函数调用中正确保存。这通常是用一种调用约定声明的函数和用另一种调用约定声明的函数指针调用的结果。

所以看来使用了错误的调用约定

我尝试在过滤器标头中修复此问题:

改变:

CBasePin*  GetPin(int n);
Run Code Online (Sandbox Code Playgroud)

到:

CBasePin* __stdcall GetPin(int n);
Run Code Online (Sandbox Code Playgroud)

但这不会编译,因为它说(翻译自德语)

重写虚函数与 CBaseFilter::GetPin 的区别仅在于调用约定

我还尝试在项目配置中设置调用约定,但这不起作用。

那我现在该怎么办?

这是过滤器界面:

class MyFilter : public  CBaseFilter, public IMyFilter
{
public:

    DECLARE_IUNKNOWN;


    MyFilter(LPUNKNOWN pUnk, HRESULT* phr);
    virtual ~MyFilter(void);

    int  GetPinCount();
    CBasePin* GetPin(int n);


    void acceptFilterInput(LPCWSTR pinname, IMediaSample* sample);

    static CUnknown* WINAPI CreateInstance(LPUNKNOWN pUnk, HRESULT *phr);
    STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void ** ppv);

    STDMETHODIMP STDMETHODCALLTYPE  StartRecording();
    STDMETHODIMP STDMETHODCALLTYPE Pause();
    STDMETHODIMP STDMETHODCALLTYPE Stop();

    CCritSec m_lock_filter;

    CBaseInputPin* pin0;
    CBaseInputPin* pin1;
    CBaseInputPin* pin2;

    MCMyOutputPin *outpin;
private:

    CCritSec m_critSec;

    std::vector<IMediaSample*> samplesPin0;
    std::vector<IMediaSample*> samplesPin1;
    std::vector<IMediaSample*> samplesPin2;

    LPCWSTR currentInputPin;


    void workerThread();

    void processQueue(std::vector<IMediaSample*> pPinSamples);


};
Run Code Online (Sandbox Code Playgroud)

这就是我使用过滤器的方式:

int static doSomeWork()
{

    CoInitialize(NULL);
    IGraphBuilder* pGraph = NULL;
    IMediaControl* pMediaControl = NULL;
    IMediaEvent* pMediaEvent = NULL;

    HRESULT hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_ALL, IID_IFilterGraph, (void **) &pGraph);

    if(hr < 0)
    {
        return -1;
    }
    IBaseFilter* pSource = NULL;
    pGraph->QueryInterface(IID_IMediaControl, (void **) pMediaControl);
    pGraph->QueryInterface(IID_IMediaEvent, (void **) pMediaEvent);
    pGraph->AddSourceFilter(TEXT("C:\\TEMP\\video1.avi"), 0, &pSource);

    IPin* pSourceOut = GetPin(pSource, PINDIR_OUTPUT);
    IBaseFilter* pAVISplitter = NULL;
    CoCreateInstance(CLSID_AviSplitter, NULL,   
                             CLSCTX_INPROC_SERVER,
                             IID_IBaseFilter,
              (void**)&pAVISplitter);

    IPin* pAvIIn = GetPin(pAVISplitter, PINDIR_INPUT);

    pGraph->AddFilter(pAVISplitter, L"Splitter");
    pGraph->Connect(pSourceOut, pAvIIn);

    IPin* pAVIOut = GetPin(pAVISplitter, PINDIR_OUTPUT);


    MyFilter* myfilter;
    hr = CoCreateInstance(CLSID_MyFilter, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void **)& myfilter);
    if(hr < 0)
    {
        return -1;
    }
    IPin* myfilterIn = myfilter->GetPin(0);
    IPin* myFilterOut = myfilter->GetPin(3);
    pGraph->Connect(pAVIOut, myfilterIn);

    pGraph->Render(myFilterOut);

    CoUninitialize();


    return 0;
}
Run Code Online (Sandbox Code Playgroud)

错误发生在“myFilter->GetPin(0)”

Rom*_* R. 5

您遇到的问题是由于您违反了 COM 基础原理造成的。

MyFilter* myfilter;
hr = CoCreateInstance(CLSID_MyFilter, NULL, CLSCTX_INPROC_SERVER, 
    IID_IBaseFilter, (void **)& myfilter);
Run Code Online (Sandbox Code Playgroud)

CoCreateInstanceQueryInterface类似的IID_IBaseFilter参数将返回您的IBaseFilter*指针。您应该正确地重新解释收到的指针,以便进一步正确使用。

你采取IBaseFilter*然后应用重新解释强制转换MyFilter*- 这是行不通的。您仍然有IBaseFilter*指针并在其上调用其他方法会导致未定义的行为。

长话短说,你不能(你可以,但这里的答案的初级版本是你不能)MyFilter*在控制应用程序上拥有指针,你只能在那里拥有 COM 接口指针。