DirectShow中ISampleGrabberCB的SampleCB回调未触发问题排查
以下是针对「视频正常渲染但SampleCB回调未触发」问题的常见排查点和解决方法:
检查Sample Grabber的配置顺序
必须先为Sample Grabber设置匹配的媒体类型(SetMediaType),再将其加入滤镜图,最后完成滤镜连接或调用RenderStream。如果顺序颠倒,回调大概率不会触发。确认回调模式参数正确
调用SetCallback时,第二个参数要传入1(对应SampleCB模式)。如果传0会触发BufferCB而非SampleCB,代码示例:pGrabber->SetCallback(pYourCBInstance, 1); // 1启用SampleCB回调验证滤镜连接完整性
视频能渲染不代表Sample Grabber被正确插入数据流。确保连接链路是:摄像头输出引脚 → Sample Grabber输入引脚 → 渲染器输入引脚。
推荐用RenderStream直接指定中间滤镜,避免手动连接出错:pGraph->RenderStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, pCaptureFilter, pGrabber, pRenderer);手动连接时要确保每一步
Connect调用都返回S_OK。确保媒体类型匹配
Sample Grabber设置的媒体类型必须和摄像头输出格式兼容。可以先获取摄像头的输出类型再同步给Sample Grabber:AM_MEDIA_TYPE mt; if (SUCCEEDED(pCapturePin->GetConnectedMediaType(&mt))) { pGrabber->SetMediaType(&mt); DeleteMediaType(&mt); }类型不匹配时,Sample Grabber会跳过回调。
保证回调对象生命周期
回调实例必须在滤镜图运行期间持续存在,不能提前销毁(比如局部变量超出作用域、智能指针被提前释放)。要让回调对象的生命周期覆盖滤镜图从启动到停止的全阶段。检查Sample Grabber的特殊设置
如果调用过SetOneShot(TRUE),回调只会触发一次;如果SetBufferSamples(TRUE)但未处理缓冲逻辑,也可能导致回调不触发。默认应保持SetOneShot(FALSE)和SetBufferSamples(FALSE)。
内容的提问来源于stack exchange,提问作者Vinay

