尝试将滤镜输出引脚连接到另一个滤镜时出现以下错误。
这是触发错误的行(在输出密码中)
HRESULT hr = pPin->GetAllocatorRequirements(pprops);
这里是函数声明:
class MCMyOutputPin : public CBaseOutputPin
{
....
HRESULT CheckMediaType(const CMediaType *pmt);
HRESULT SetMediaType(const CMediaType *pmt);
HRESULT CompleteConnect(IPin *pReceivePin);
//virtual HRESULT __stdcall Connect(IPin* pPin, const AM_MEDIA_TYPE *pmt);
HRESULT BreakConnect();
HRESULT GetMediaType(int i, CMediaType *pmt);
HRESULT DecideBufferSize(IMemAllocator *pAlloc, ALLOCATOR_PROPERTIES *pProps);
HRESULT DecideAllocator(IMemInputPin *pPin, IMemAllocator **ppAlloc);
HRESULT Deliver(IMediaSample* sample);
BOOL IsConnected();
...
我相信DecideAllocator是由GetAllocatorRequirements调用的。
根据msdn(Building DirectShw Filters),必须使用__stdcall声明函数。 所以在调用函数和被调用函数之间似乎存在调用conventin冲突。 但是,如果我尝试将函数设置为__stdcall:
HRESULT __stdcall DecideAllocator(IMemInputPin *pPin, IMemAllocator **ppAlloc);
我收到编译错误:
' MCMyOutputPin :: DecideAllocator':覆盖虚拟功能不同 来自' CBaseOutputPin :: DecideAllocator'只能通过调用约定
所以我尝试确保使用stdcall调用约定构建基类: 我打开了基类项目(C:\ Program Files(x86)\ Microsoft SDKs \ Windows \ v7.0 \ Samples \ multimedia \ directshow \ baseclasses)并设置
ConfigurationProperties-> C / C ++ - > Advanced-> Calling Convention 到__stdcall(/ Gz)
总结如下:
但是我仍然无法将我项目的outputpins函数的调用约定更改为stdcall
更新
这是我的过滤器NonDelegatingQueryInterface:
STDMETHODIMP MyFilter::NonDelegatingQueryInterface(REFIID riid, void **ppv)
{
if(riid == IID_IMyInterfilter) {
mylogger->LogDebug("In Nondelegationqueryinterface", L"D:\\TEMP\\yc.log");
return GetInterface((IMyFilter*)this, ppv);
}
else
{
return CBaseFilter::NonDelegatingQueryInterface(riid, ppv);
}
}
这里有过滤器标题:
class MyFilter : public CBaseFilter, public IMyFilter
{
public:
CCritSec lockfilter;
DECLARE_IUNKNOWN;
const LONGLONG MEDIATIME = 5;
MyFilter(LPUNKNOWN pUnk, HRESULT* phr);
virtual ~MyFilter(void);
virtual int GetPinCount();
virtual CBasePin* GetPin(int n);
STDMETHODIMP Run(REFERENCE_TIME tStart);
STDMETHODIMP Pause();
STDMETHODIMP Stop();
void acceptFilterInput(LPCWSTR pinname, IMediaSample* sample);
CMyInputPin* getPreviousPIN(LPCWSTR pinname);
CMyInputPin* getNextPIN(LPCWSTR pinname);
//BOOL requestRecordMode(LPCWSTR pinname); //returns false if previous pin thread is not sleeping
static CUnknown* WINAPI CreateInstance(LPUNKNOWN pUnk, HRESULT *phr);
STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void ** ppv);
//STDMETHODIMP StartRecording();
STDMETHODIMP GetThePinCount(int* result);
//STDMETHODIMP StopRecording();
STDMETHOD_(IPin*,GetMyPin)(int index);
//STDMETHODIMP Next(ULONG cPins, IPin** pppins, ULONG fetched);
//STDMETHODIMP Clone(IEnumPins **ppenum);
//STDMETHODIMP Reset();
//STDMETHODIMP Skip(ULONG cpins);
//
CCritSec m_lock_filter;
TimeGiver* m_pTimeGiver;
MCMyOutputPin *outpin;
static const int COUNT_INPUTPINS = 3;
static unsigned __stdcall workerthreadfunc(void *);
HANDLE workerThreadHandle;
private:
MyLogger *mylogger;
CCritSec m_critSec;
bool running;
LPCWSTR currentInputPin;
void startSyncThread();
CMyInputPin* GetPinByName(LPCWSTR name);
LONGLONG* mediaTimeBuffer;
CMyInputPin* inputpins[COUNT_INPUTPINS];
};
以下是过滤器实现:
#include "MyInputPin.h"
#include "CMyOutPutPin.h"
#include "MyLogger.h"
#include <windows.h>
#include <process.h>
#include <string>
using namespace std;
MyFilter::MyFilter(LPUNKNOWN pUnk, HRESULT* phr) : CBaseFilter(NAME("MyFilter"), pUnk, &lockfilter, CLSID_MyInterFilter)
{
HRESULT *hr_0 = NOERROR;
HRESULT *hr_1 = NOERROR;
HRESULT* hr_2 = NOERROR;
HRESULT* hr_3 = NOERROR;
inputpins[0] = new CMyInputPin(TEXT("PIN0"), L"PIN0", pUnk, this, &this->m_lock_filter, hr_0, 0);
inputpins[1] = new CMyInputPin(TEXT("PIN1"), L"PIN1", pUnk, this, &this->m_lock_filter, hr_1, 1);
inputpins[2] = new CMyInputPin(TEXT("PIN2"), L"PIN2", pUnk, this, &this->m_lock_filter, hr_2, 2);
outpin = new MCMyOutputPin(this, hr_3, TEXT("PINOUT0"));
this->running = false;
mylogger = new MyLogger();
mylogger->LogDebug("Construtor of Filter", L"D:\\TEMP\\yc.log");
m_pTimeGiver = new TimeGiver(2, MEDIATIME);
}
CMyInputPin* MyFilter::getPreviousPIN(LPCWSTR pinname)
{
CMyInputPin *inpin = GetPinByName(pinname);
int position = inpin->m_position;
int adjused = position + COUNT_INPUTPINS - 1;
int newInex = adjused % COUNT_INPUTPINS;
return inputpins[newInex];
}
CMyInputPin* MyFilter::getNextPIN(LPCWSTR pinname)
{
CMyInputPin *inpin = GetPinByName(pinname);
int position = inpin->m_position;
int incremented = position++;
int newIndex = incremented % COUNT_INPUTPINS;
return inputpins[newIndex];
}
//BOOL MyFilter::requestRecordMode(LPCWSTR pinname) { //returns false if previous pin thread is not sleeping
// for (int i = 0; i < COUNT_INPUTPINS; i++)
// {
// if (wcscmp(pinname, inputpins[i]->Name()) == 0)
// {
// inputpins[i]->m_bIsSleeping = false;
// }
// else {
// inputpins[i]->m_bIsSleeping = true;
// }
//
// }
// return TRUE;
//}
HRESULT MyFilter::Run(REFERENCE_TIME tStart)
{
mylogger->LogDebug("In MyFilter::Run:", L"D:\\TEMP\\yc.log");
CAutoLock cobjectlock(&m_critSec);
workerThreadHandle = (HANDLE) _beginthreadex(NULL, 0, workerthreadfunc, (void *)this, 0, NULL);
//boost::thread workerThread(&MyFilter::startSyncThread, this);
m_tStart = tStart;
if (m_State == State_Stopped){
HRESULT hr = Pause();
if (FAILED(hr)) {
return hr;
}
}
return S_OK;
}
HRESULT MyFilter::Stop()
{
mylogger->LogDebug("In MyFilter::Stop:", L"D:\\TEMP\\yc.log");
CAutoLock cobjectlock(&m_critSec);
m_State = State_Stopped;
this->m_pTimeGiver->stop();
//this->m_thread.join();
return S_OK;
}
HRESULT MyFilter::Pause()
{
CAutoLock cobjectlock(&m_critSec);
m_State = State_Paused;
mylogger->LogDebug("In MyFilter::PAuse:", L"D:\\TEMP\\yc.log");
return S_OK;
}
MyFilter::~MyFilter(void)
{
//delete mylogger;
//delete outpin;
//delete[] inputpins;
}
int MyFilter::GetPinCount()
{
return COUNT_INPUTPINS + 1; //One outputpin
}
IPin* MyFilter::GetMyPin(int n)
{
CBasePin* pin = this->GetPin(n);
return pin;
}
CBasePin* MyFilter::GetPin(int n)
{
if (n >= 0 && n < COUNT_INPUTPINS)
{
return inputpins[n];
}
if (n == 3)
{
return outpin;
}
return NULL;
}
//HRESULT MyFilter::GetThePinCount(int *result)
//{
// *result = 4;
//}
HRESULT MyFilter::GetThePinCount(int* giveme)
{
*giveme = COUNT_INPUTPINS + 1;
return S_OK;
}
STDMETHODIMP MyFilter::NonDelegatingQueryInterface(REFIID riid, void **ppv)
{
if(riid == IID_IMyInterfilter) {
mylogger->LogDebug("In Nondelegationqueryinterface", L"D:\\TEMP\\yc.log");
return GetInterface((IMyFilter*)this, ppv);
}
else
{
return CBaseFilter::NonDelegatingQueryInterface(riid, ppv);
}
}
/*RESULT MyFilter::StartRecording()
{
this->running = true;
return S_OK;
}*/
//
//HRESULT MyFilter::StopRecording()
//{
// this->running = false;
// return S_OK;
//
//}
CUnknown* WINAPI MyFilter::CreateInstance(LPUNKNOWN pUnk, HRESULT *phr)
{
CUnknown* pNewFilter = new MyFilter(pUnk, phr);
if (phr)
{
if (pNewFilter == NULL)
*phr = E_OUTOFMEMORY;
else
*phr = S_OK;
}
return pNewFilter;
}
void MyFilter::acceptFilterInput(LPCWSTR pinname, IMediaSample* sample)
{
mylogger->LogDebug("In acceptFIlterInput", L"D:\\TEMP\\yc.log");
outpin->Deliver(sample);
}
//STDMETHODIMP MyFilter::Next(ULONG cPins, IPin** pppins, ULONG fetched)
//{
//
//}
//STDMETHODIMP MyFilter::(IEnumPins **ppenum)
//{
//
//}
//STDMETHODIMP MyFilter::Reset()
//{
//
//}
//STDMETHODIMP MyFilter::Skip(ULONG cpins)
//{
//
//}
CMyInputPin* MyFilter::GetPinByName(LPCWSTR name)
{
for (int i = 0; i < COUNT_INPUTPINS; i++)
{
if (wcscmp(name, inputpins[0]->Name()))
{
return inputpins[0];
}
}
return NULL;
}
void MyFilter::startSyncThread()
{
this->m_pTimeGiver->start();
}
unsigned int MyFilter::workerthreadfunc(void * param)
{
MyFilter* myfilter;
myfilter = (MyFilter *)param;
myfilter->m_pTimeGiver->start();
return S_OK;
}
答案 0 :(得分:0)
错误的调用约定是获取此错误消息的典型问题,但它只是可能的原因之一。可以实现相同的不匹配&#34;例如,当你需要返回IFooA*
指针时,通过错误的指针转换,然后返回IFooB*
。然后调用IFooA::BarA
有效执行您的IFooB::BarB
代码,其语法/调用差异结果是堆栈帧失败。我相信你遇到的情况就是这样,因为在特定的接口/方法上构建错误的调用约定并不容易。
问题应该是你调试器停止的界面。我从NonDelegatingQueryInterface
实施开始检查,以确保您返回正确的接口,这些接口匹配正确请求的IID
。
UPD。无论原始问题是什么,这看起来都不好看:
CMyInputPin* MyFilter::GetPinByName(LPCWSTR name)
{
for (int i = 0; i < COUNT_INPUTPINS; i++)
{
// 1. you want [i], not [0]
// 2. you want if(wcscmp(...) == 0)
if (wcscmp(name, inputpins[0]->Name()))
{
// 3. you want [i], not [0]
return inputpins[0];
}
}