Wine 开发系列之——DirectShow

DirectShow是Windows下的流媒体处理架构。涉及到了流媒体的抓取/预览、编码/解码、分离/混合、格式转换等等。在处理摄像头数据的程序中应用尤为广泛。通过Wine迁移摄像头相关的程序需要解决的问题也大多是解决DirectShow相关的问题。

DirectShow是基于模块化的,每个功能对象都是基于COM接口的,这里先介绍下几个基本的对象:Graph、Filter和Pin。Graph是需要实现某个功能添加的filter集合,如图是一个可以预览摄像头的Graph组成。Filter是一个处理数据的功能模块,可以抽象的理解成一个电子元器件。Pin是各个filter传输数据的节点,是包含在filter对象中的,可以抽象理解成电子元器件的输入/输出引脚。

深度截图_选择区域_20190526121006

社区版的Wine目前支持摄像头输出RGB24然后render的功能,但是应用程序往往会用到一些更复杂的特性。在这里分享下解决这些问题的思路。

  • 一、分析Graph组成

遇到的最常见问题就是连接失败的问题,要处理这个问题就先要弄清楚Graph中是由哪些filter组成的,更重要的是哪些是应用层添加的。我采用的方法是开启quartz通道的日志,然后grep -a -E “AddFilter|RemoveFilter|FilterGraph2_Connect |RenderStream”日志文件。如下图中可以清楚的知道graph中添加了四个filter。一般第一条FilterGraph2_Connect前面的就是应用层添加的,后面都是连接过程中Wine内部逻辑添加的Filter。当然也有AddFilter和Connect交替的情况,那就要更详细的分析日志了。另外要注意的是不要太相信AddFilter传入的Filter名称,要通过Filter指针的值查看ole日志才能真正确认创建的Filter对应的CLSID,CLSID才能和Filter的功能唯一对应上(大部分情况都能通过Filter的名称看出filter对应的模块,但也遇到过名称对不上的情况,感觉不对的时候就要查下到底对应的是那个CLSID)。

深度截图_选择区域_20190526114300

  • 二、分析连接失败的原因

Graph要正常跑起来,先要将里面的Filter连接起来。判断连接是否完整只需要看通过应用层发起的Connect是否连接成功,需要细心过滤掉连接过程中递归调用的FilterGraph2_Connect。如上图中AVIDecomprssor的filter就不是必须的,其他必须的filter应用层都通过FilterGraph2_Connect指定了。

Connect的动作实际上是将两个Filter的Pin连接起来,最终都是调用IPin_Connect函数。如下图直观的反映出连接的过程:连接的过程由Output Pin发起,指定MediaType之后询问Input Pin是否接收,双方确认没有问题之后就可以连接成功。大部分连接失败的原因都是MediaType不匹配导致的。

cbasepin-connect

通过上面可以看出,查看两个Pin连接的过程主要关注AttemptConnection和ReceiveConnection两个方法的输出就可以了,通过开启strmbase日志通道就可以输出这部分的日志。常见的还有用到Grabber Filter的,需要开启qedit日志通道关注SampleGrabber_Out_IPin_Connect和SampleGrabber_In_IPin_ReceiveConnection。关注这些日志基本可以找出连接失败的原因。

  • 小结

以上仅当一个抛砖引玉的作用,对相关问题有个认识,写的也是比较通用的。实际遇到问题可能是从摄像头驱动到应用层用到的一些特殊特性导致的,不具备普遍性这里就不一一列举了。

 

发表评论

电子邮件地址不会被公开。 必填项已用*标注