我正在尝试使用SDK附带的桌面捕获过滤器(PushSourceDesktop)。我编译它并似乎成功使用它,因为它实际捕获我的桌面并将其保存到文件。但是应用程序在完成/退出时崩溃了。
当我打破错误时,它只说没有可用的源,并且调用堆栈位置是KernelBase.dll!7560280C()。
我想我在这里试一试,看看是否有人能够认识到某些问题,或者我是否正在做一些可能导致崩溃的公然错误。提前谢谢!
编辑:工作代码
int main()
{
HRESULT hr;
hr = CoInitialize(NULL);
{
CComPtr<IBaseFilter> pMux;
CComPtr<IMediaControl> pMC;
CComPtr<IBaseFilter> pFilterr;
CComPtr<IGraphBuilder> pGraph;
CComPtr<ICaptureGraphBuilder2> pBuild;
CComPtr<IUnknown> pUnk;
hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL, CLSCTX_INPROC_SERVER,
IID_ICaptureGraphBuilder2, (void**)&pBuild);
hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void**)(&pGraph));
hr = pBuild->SetFiltergraph(pGraph);
static CLSID const clsid = {0x4ea6930a, 0x2c8a, 0x4ae6, {0xa5, 0x61, 0x56, 0xe4, 0xb5, 0x4, 0x44, 0x37}}; //Pushsourcedesktop
hr = CreateObjectFromPath(TEXT("c:\\filters\\PushSource.dll"), clsid, &pUnk);
pFilterr = pUnk;
if (SUCCEEDED(hr))
{
HRESULT hr = pGraph->AddFilter(pFilterr, L"Private Filter");
}
hr = pBuild->SetOutputFileName(
&MEDIASUBTYPE_Avi, // Specifies AVI for the target file.
L"C:\\wav\\Example2.avi", // File name.
(IBaseFilter**)&pMux, // Receives a pointer to the mux.
NULL);
hr = pBuild->RenderStream(
NULL,//PIN_CATEGORY_CAPTURE,//NULL,//&PIN_CATEGORY_CAPTURE, // Pin category.
NULL,//&MEDIATYPE_Video,//&MEDIATYPE_Interleaved,//NULL,//&MEDIATYPE_Audio, // Media type.
pFilterr,//pSrc, // Capture filter.
NULL,//pCompression2, //pCompression, // Intermediate filter (optional).
(IBaseFilter*)pMux); // Mux or file sink filter.
hr = pGraph->QueryInterface(IID_IMediaControl, (void **)&pMC);
printf("START");
pMC->Pause();
hr = pMC->Run();
Sleep(4000);
hr = pMC->Stop();
printf("END");
}
CoUninitialize();
return 0;
}
答案 0 :(得分:3)
big 问题是,只有在释放所有COM指针后才需要调用CoUninitialize
。既然你正在使用原始指针而不是CComPtr
- 就像智能模板一样,你的代码的可读性都很差,并且很容易犯错并忘记释放其中一个指针。 CoUninitialize
清理了一些内容,然后看起来某些COM对象仍处于活动状态,很快就会遇到麻烦并导致应用崩溃。
除此之外,我认为您没有理由使用COINIT_MULTITHREADED
公寓。为了避免麻烦,您应该在STA线程的过滤器图上进行所有顶级管理。流和工作线程将是MTA,它很好。
ATL
提供了MSDN上详细描述的CComPtr
个模板。 DirectShow BaseClasses为您提供轻量级模拟QzCComPtr
,我建议您为方便起见使用它。
您的代码如下所示:
CoInitialize(...);
{
CComPtr<IFooA> pFooA;
CComPtr<IFooB> pFooB;
// ...
}
CoUninitialize();
我们的想法是在代码到达~CComPtr
之前完成所有CoUninitialize
。