DirectShow创建释放Capture Filter时出现大量内存泄漏问题
DirectShow摄像头Capture Filter内存泄漏问题排查
核心原因分析
- COM对象引用计数未完全释放:DirectShow的所有COM对象必须严格遵循
AddRef()/Release()配对原则。如果代码中创建Capture Filter时,遗漏了对设备枚举器(ICreateDevEnum)、设备别名(IMoniker)、枚举器(IEnumMoniker)这些中间对象的Release()调用,哪怕只漏一个,都会导致大量对象无法被回收,进而产生句柄和内存泄漏。 - 设备资源未显式回收:部分摄像头驱动在创建Capture Filter后,会自动激活硬件资源(比如内核级设备句柄),仅靠COM对象的
Release()无法触发驱动释放这些资源。需要先将Filter添加到过滤图再移除,或者调用相关接口通知设备进入空闲状态。 - 过滤图资源残留:哪怕没有构建完整的播放流程,只要初始化了过滤图相关对象(比如
ICaptureGraphBuilder2),就需要确保所有关联的Filter都被从图中移除,否则内部的数据流上下文会持续占用资源。
针对性修复步骤
补全所有COM对象的Release调用
确保枚举设备、创建Filter过程中产生的所有COM对象都调用Release(),示例代码如下:// 枚举设备 ICreateDevEnum *pDevEnum = NULL; CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, (void**)&pDevEnum); IEnumMoniker *pEnum = NULL; pDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEnum, 0); IMoniker *pMoniker = NULL; pEnum->Next(1, &pMoniker, NULL); // 创建Capture Filter IBaseFilter *pCapFilter = NULL; pMoniker->BindToObject(NULL, NULL, IID_IBaseFilter, (void**)&pCapFilter); // --- 业务逻辑(此处无额外逻辑)--- // 正确释放所有对象(按创建逆序) pCapFilter->Release(); pMoniker->Release(); // 这行很容易遗漏,是泄漏重灾区 pEnum->Release(); pDevEnum->Release();显式清理设备硬件资源
如果补全Release后仍有泄漏,尝试将Filter加入过滤图再移除,强制触发资源回收:IFilterGraph *pGraph = NULL; CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IFilterGraph, (void**)&pGraph); // 添加到图中 pGraph->AddFilter(pCapFilter, L"Capture Filter"); // 立即移除 pGraph->RemoveFilter(pCapFilter); // 释放图对象 pGraph->Release();检查驱动兼容性处理
若多台设备都出现问题,可能是DirectShow与部分摄像头驱动的兼容性问题。可以尝试调用IAMVideoControl::SetMode接口,强制关闭设备的实时捕获模式:IAMVideoControl *pVidControl = NULL; pCapFilter->QueryInterface(IID_IAMVideoControl, (void**)&pVidControl); if(pVidControl){ pVidControl->SetMode(NULL, VideoControlFlag_Trigger); pVidControl->Release(); }
内容的提问来源于stack exchange,提问作者kppodd
相关产品推荐
相关产品推荐

