在最近的项目中,遇到需要实现多输入单输出的TransformFilter进行数据流的整合。解决过程艰辛繁琐,经过很多摸索,印象深刻,故作此文纪念。

在微软提供的例子中,有一个叫做InfTee的单输入多输出的TransformFilter的经典例子。InfTee通过动态生成Output PIN实现了多输出。在这个Filter中,始终保持着一个空闲的Output PIN,每次连接之后,就会new一个新的Output PIN。看了此例子之后,仿造那种方法写了一个多输入单输出的Filter。结果当应用到自己的GB时,却出了大问题。因为InfTee是多输出的,所以采用了Output PIN List的方式去管理所有的Output PIN,如果下游的Filter要断开或者改变时,直接从这个List中删除即可,以此实现了动态的管理。但是一旦这种思想放到多输入中时,就行不通了。因为一旦上游的Source Filter要断开或者改变时时,整个Filter Chain就会停止,然后需要Remove这个TransformFilter,然后再重连。这种情况就需要实现动态重连。这就要求我们的Input PIN要实现IPinConnection接口。对于初学者的我来说,IPInConnection实现的可参考资料实在是太少了。时间紧,任务重,所以转念一想,干脆用多个SampleGrabber来代替这种动态重连的功能。具体做法如下。 

 如图:

    

多输入CNN 多输入单输出_SampleGrabber

     步骤1:

         初始化五个SampleGrabber,同时初始化5个对应的ISampleGrabber接口实现类的对象,并将5个SampleGrabber分别连接到GB中。具体做法在我的《SampleGrabber捕获摄像头每一帧图像,并转为BMP文件信息写入内存》一文中已经详细介绍。当然,也可以参照微软的例子StillCap。值得注意的是,在重写BufferCB这个回调函数的时候,注意判断是哪个一个Grabber在调用。我采用的方法是利用一个flag参数进行判断,各个Grabber利用一个SetFlag函数进行设置各自的flag值,然后在BufferCB中根据匹配flag值进行各自的操作。这里的操作就是将得到的pBuffer写入到各自制定的内存中,如Grabber1的flag为1,指定的内存就是Buffer1。

         步骤2:

         自己写一个Add TransformFilter,利用一个导出函数传递以上四个Buffer的值,在filter内部对Source5中得到的buffer和已得到的4个buffer进行整合,然后传出至Grabber5。值得注意的是,传递buffer的时候,一定要传指针,因为回调函数BufferCB会不断的更新buffer的值。如果source1~4中的源有变化时,直接重建变化的filter Chain即可。

         步骤3:

         Grabber5得到上游的buffer之后,利用BufferCB将其存入指定内存,同时传到Dest Filter即可。

 

         这样就是实现了多流的整合。

 

注意事项:

         在调用BufferCB的时候,我们会用Grabber->SetCallback(&mCB, 1);的方式。在这里,每个Grabber都需要拥有自己的的mCB(即ISampleGrabber的对象),这样才能避免死锁的现象。

         当然,这个方法比较笨,而且效率也不高,但是却能避免动态链接的棘手问题。何况,我也不会如何去实现IPinConnection来支持动态链接。网上知道的人也不大乐意告诉我。所以这个方法来解决燃眉之急还是比较可行的。至少对于初学者来说是这样的。


//END ICTwangbiao