DirectShow将sampleGrabber转换为ISampleGrabber

时间:2013-06-24 18:15:23

标签: c# .net-4.0 com directshow directshow.net

我有一个奇怪的错误,我无法绕过头脑。我在一个运行的单独线程中创建了一个图表,我正在尝试访问在控制台应用程序中工作的线程之外的IBaseFilter sampleGrabber,但我将代码移动到一个新项目,我正在尝试转换sampleGrabberISampleGrabber运行时抱怨空引用异常。如果我调试sampleGrabber它确实有接口ISampleGrabber但是我不能再进行转换。在运行图形的线程中移动代码允许我进行转换,但它不适合我的应用程序。

如何通过强制转换sampleGrabberISampleGrabber失败来显示空引用异常?

2 个答案:

答案 0 :(得分:3)

问题是DirectShow过滤器是早期的COM类,它们在引用计数,接口,标记,持久性的一部分中实现COM的子集 - 基本上所有好事都持续了多年 - 但是它们完全忽略了公寓。 DirectShow本身是多线程的,通常有一个控制线程,并且有工作流线程。 DirectShow概念假设您可以轻松地在线程之间传递接口指针,并且不会涉及,预期和需要编组。

然后.NET检查了COM包装器,而DirectShow.NET包装了接口指针,好像它们是功能完备的公寓感知COM指针一样。同时,Microsoft停止向DirectShow提供更新(例如,使用免费的线程封送程序提供Sample Grabber),最终在.NET上遇到问题时,您无法通过接口指针执行一个简单的操作。

在本机代码域中使用API​​仍然没有问题,因为您可以跳过编组并使用直接指针。

您在一个公寓上构建图表,然后您从另一个公寓的Sample Grabber接听回电(或者,在您的方案中,您只需在工作线程上执行某些操作)。您不能使用原始接口指针,尤其是那些在成员变量中,因为.NET运行时检查会遇到公寓不匹配,尤其是试图编组另一个公寓的接口指针。

如果它是带有源代码的自定义过滤器,您可以添加自定义IMarshal实现或利用free threaded marshaler来修复本机代码端的.NET问题,或者添加帮助程序以通过跨公寓的指针。

在.NET代码域中,最好的方法是避免使用来自多个公寓的指针。可能有选择,但我认为最简单的选择是

  • 在MTA中工作,可以让多个线程访问DirectShow接口指针
  • 使用CLSID_FilterGraphNoThread版本的Filter Graph Manager
  • 在专用线程上初始化和终止过滤器图形,在图形操作期间调度窗口消息

即,使用STA并且没有额外的线程接触指针,否则不使用STA。

答案 1 :(得分:0)

在使用IGlobalInterface并思考Roman的评论之后,我意识到设置处理samplegrabber的函数最好是在另一个线程中,从而绕过STA。