C++ DirectShow代码在退出后崩溃(PushSourceDesktop示例)

C++ DirectShow代码在退出后崩溃(PushSourceDesktop示例),c++,com,directshow,C++,Com,Directshow,我正在尝试使用SDK(PushSourceDesktop)附带的桌面捕获过滤器。我编译了它,并且似乎成功地使用了它,因为它实际上捕获了我的桌面并将其保存到一个文件中。但应用程序在完成/退出时崩溃 当我在错误上中断时,它只说没有可用的源,调用堆栈位置是KernelBase.dll!7560280C() 我想我在这里试一试,看看是否有人能认识到一些问题,或者我是否在做一些可能导致崩溃的明显错误的事情。提前谢谢 编辑:工作代码 int main() { HRESULT hr; hr = CoIni

我正在尝试使用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;
}
intmain()
{
HRESULT-hr;
hr=协同初始化(空);
{
CComPtr pMux;
CComPtr pMC;
pFilterr先生;
CComPtr-pGraph;
CComPtr pBuild;
朋克;
hr=CoCreateInstance(CLSID\u CaptureGraphBuilder2,NULL,CLSCTX\u在PROC\u服务器中,
IID_ICaptureGraphBuilder2(无效**)和pBuild);
hr=CoCreateInstance(CLSID_FilterGraph,NULL,CLSCTX_INPROC_SERVER,IID_IGraphBuilder,(void**)(&pGraph));
hr=pBuild->SetFiltergraph(pGraph);
静态CLSID const CLSID={0x4ea6930a,0x2c8a,0x4ae6,{0xa5,0x61,0x56,0xe4,0xb5,0x4,0x44,0x37};//Pushsourcedesktop
hr=CreateObjectFromPath(文本(“c:\\filters\\PushSource.dll”)、clsid和pUnk);
pFilterr=朋克;
如果(成功(hr))
{
HRESULT hr=pGraph->AddFilter(pFilterr,L“专用过滤器”);
}
hr=pBuild->SetOutputFileName(
&MEDIASUBTYPE_Avi,//指定目标文件的Avi。
L“C:\\wav\\Example2.avi”,//文件名。
(IBaseFilter**)&pMux,//接收指向mux的指针。
无效);
hr=pBuild->RenderStream(
NULL,//PIN\u CATEGORY\u CAPTURE,//NULL,//&PIN\u CATEGORY\u CAPTURE,//PIN CATEGORY。
NULL、//&MEDIATYPE\u视频、//&MEDIATYPE\u交错、//NULL、//&MEDIATYPE\u音频、//媒体类型。
pFilterr,//pSrc,//捕获过滤器。
NULL、//pCompression2、//pCompression、//中间筛选器(可选)。
(IBaseFilter*)pMux);//Mux或文件接收器筛选器。
hr=pGraph->QueryInterface(IID_IMediaControl,(void**)和pMC);
printf(“开始”);
pMC->Pause();
hr=pMC->Run();
睡眠(4000);
hr=pMC->Stop();
printf(“结束”);
}
coninitialize();
返回0;
}
最大的问题是,只有在释放所有COM指针后,才能调用
conInitialize
。现在,您使用的是原始指针,而不是像智能模板那样使用
CComPtr
,因此,您的代码可读性都很差,很容易出错并忘记释放其中一个指针
CoUninitialize
会清理一些东西,然后发现某些COM对象仍然处于活动状态,它很快就会遇到问题并导致应用程序崩溃

除此之外,我不认为您有理由使用多线程单元。为了避免麻烦,您应该从STA线程对过滤图进行所有顶级管理。流式线程和工作线程将是MTA,这很好

ATL
提供了MSDN上详细描述的模板。DirectShow基类为您提供了一个轻量级的模拟
QzCComPtr
,我建议您为了自己的方便开始使用它

您的代码如下所示:

CoInitialize(...);
{
  CComPtr<IFooA> pFooA;
  CComPtr<IFooB> pFooB;
  // ...
}
CoUninitialize();
CoInitialize(…);
{
首席财务官pFooA;
首席财务官pFooB;
// ...
}
coninitialize();

这个想法是所有的
~CComPtr
都在代码到达
CoUninitialize

之前完成。啊,我想我现在明白了,我在代码中添加了更改。谢谢你澄清这一关键点!