我使用GMFBridge.DLL正确预览/捕获流吗?
我正在尝试使用GMFBuilder,以便我可以预览来自网络摄像头的流并定期保存,而无需重新启动整个图形。 但是,我不确定这是否正确,我试图按照示例,但代码已更新,事情已发生变化。
我试着创造:
WEbcam -> Smart Tee (preview) -> AVI Decompressor -> Video Renderer Smart Tee (Capture) -> BridgeSinkFilter
并且:
BridgeSourceFilter -> ffdshow video encoder -> haali mastroska muxer
(只是因为它易于使用)
关于让代码正常运行的输入将非常感激。
private void button2_Click(object sender, EventArgs e) { IGraphBuilder firstGraph = (IGraphBuilder)new FilterGraph(); IGraphBuilder secondGraph = (IGraphBuilder)new FilterGraph(); IBaseFilter BridgeSinkFilter; IBaseFilter BridgeSourceFilter; IBaseFilter Source; IBaseFilter Mux; IBaseFilter FileWriter; IGMFBridgeController bridge = (IGMFBridgeController)new GMFBridgeController(); bridge.AddStream(1, eFormatType.eMuxInputs, 1); BridgeSinkFilter = (IBaseFilter)bridge.InsertSinkFilter(firstGraph); Source = FindFilter(FilterCategory.VideoInputDevice, "SG330"); firstGraph.AddFilter(Source, "source"); IBaseFilter SmartTee = FindFilter(FilterCategory.LegacyAmFilterCategory, "Smart Tee"); firstGraph.AddFilter(SmartTee, "Smart Tee"); IPin pinin, pinout; pinout = FindPinByDirection( Source, PinDirection.Output); pinin = FindPinByDirection( SmartTee, PinDirection.Input); firstGraph.Connect(pinout, pinin); pinout = FindPinByDirection(SmartTee, PinDirection.Output); pinin = FindPinByDirection(BridgeSinkFilter, PinDirection.Input); firstGraph.Connect(pinout, pinin); IBaseFilter Decomp = FindFilter(FilterCategory.LegacyAmFilterCategory, "AVI Decompressor"); firstGraph.AddFilter(Decomp, "Avi Decompressor"); pinout = FindPinByDirection(SmartTee, PinDirection.Output); pinin = FindPinByDirection(Decomp, PinDirection.Input); firstGraph.Connect(pinout, pinin); IBaseFilter Renderer = FindFilter(FilterCategory.LegacyAmFilterCategory, "Video Renderer"); firstGraph.AddFilter(Renderer, "Video Renderer"); pinout = FindPinByDirection(Decomp, PinDirection.Output); pinin = FindPinByDirection(Renderer, PinDirection.Input); firstGraph.Connect(pinout, pinin); DsROTEntry g = new DsROTEntry(firstGraph); BridgeSourceFilter = (IBaseFilter)bridge.InsertSourceFilter(BridgeSinkFilter, secondGraph); DsROTEntry h = new DsROTEntry(secondGraph); IBaseFilter Muxe = FindFilter(FilterCategory.VideoCompressorCategory, "ffdshow video encoder"); secondGraph.AddFilter(Muxe, "Mux"); pinout = FindPinByDirection(BridgeSourceFilter, PinDirection.Output); pinin = FindPinByDirection(Muxe, PinDirection.Input); secondGraph.Connect(pinout, pinin); IBaseFilter MKV = FindFilter(FilterCategory.LegacyAmFilterCategory, "Haali Matroska Muxer"); IFileSinkFilter fs = (IFileSinkFilter)MKV; fs.SetFileName("c:\\cool.mkv", null); secondGraph.AddFilter(MKV, "mux"); pinout = FindPinByDirection(Muxe, PinDirection.Output); pinin = FindPinByDirection(MKV, PinDirection.Input); secondGraph.Connect(pinout, pinin); bridge.BridgeGraphs(BridgeSinkFilter, BridgeSourceFilter); IMediaControl mediacontrolforpartone = (IMediaControl)firstGraph; mediacontrolforparttwo = (IMediaControl)secondGraph; mediacontrolforpartone.Run(); mediacontrolforparttwo.Run(); }
根据我目前的知识正确使用GMFBridge:
从以下网站获取GMFBridge DLL: http ://www.gdcl.co.uk/gmfbridge/从以下url获取DirectShowLib DLL: https ://sourceforge.net/projects/directshownet/files/DirectShowNET/
将它们包含在您的项目中。
创建2个图表。 1用于预览,第2个用于捕获。
IGraphBuilder firstgraph = (IGraphBuilder) new FilterGraph(); IGraphBuilder secondgraph = (IGraphBuilder) new FilterGraph();
创建一个来自GMFBridge DLL的桥,将连接两个图
IGMFBridgeController Bridge = (IGMFBridgeController) new GMFBridgeController();
从这里开始设置桥接器以允许多路复用输入
Bridge.AddStream(1, eFormatType.eMuxInputs, 1);
从这里您可以添加源videofilter,它不需要连接到网桥,添加Smart Tee,并将源连接到Smart Tee。
然后创建一个filter来容纳将完成工作的第一个桥接filter
BridgeSinkFilter = (IBaseFilter)Bridge.InsertSinkFilter(firstgraph);
此滤波器将连续接受来自Smart Tee捕获引脚的video。 如果第二个图桥接filter已连接并正在运行,它会将video从BridgeSInkFilter传递到第二个图形。 否则,它只会抛出它,但它总是在运行。
将BridgeSinkFilter连接到Smart Tee的捕获引脚。 我发现连接引脚的最佳方法是通过https://splicer.svn.codeplex.com/svn/src/Splicer/Utilities/FilterGraphTools.cs使用FindPinByDirection,然后调用
firstgraph.connect(pinoutput, pininput)
从这里开始,要预览video,应添加FilterCategory.LegacyAmFilterCategory中的AVI Decompressorfilter,并将其连接到Smart Tee的预览引脚。 然后Video Renderer添加并连接到AVI Decompressor。
那应该照顾第一张图。
第二个图需要从桥开始。 它将从第一个图形bridgesinkfilter创建一个桥梁,并将其拉到第二个图形,我们可以在其中执行任何我们想要的任务。 要做到这一点,我们需要桥梁的另一面。
IBaseFilter BridgeSourceFilter = (IBaseFilter)Bridge.InsertSourceFilter(BridgeSinkFilter,secondgraph);
这将源设置为第一段中的sinkfilter,但是在BridgeSourceFilter的幌子下将其放在我们的第二个图上。
现在连接编码器,ffdshowvideo编码器等。将它连接到BridgeSourceFilter。
添加多路复用器,AVI Mux和文件编写器。 连接他们。 那是第二张图的一切。
要完成图形关闭,我们需要创建2个可以启动和停止图形的mediacontrollers。
IMediaControl MediaControl_FirstGraph = (IMediaControl)firstgraph; IMediaControl MediaControl_SecondGraph = (IMediaControl)secondgraph;
现在我们可以打电话
MediaControl_FirstGraph.Run() to start previewing the video.
然后要捕获该video,我们需要连接第一个和第二个图之间的桥,然后运行第二个图。
Bridge.BridgeGraphs(BridgeSinkFilter,BridgeSourceFilter); MediaControl_SecondGraph.Run()
在任何时候,您都可以通过断开桥接连接来停止捕获,然后停止第二个图形。
Bridge.BridgeGraphs(null, null); MediaControl_SecondGraph.Stop();
我认为这涵盖了我发现的关于GMF桥梁控制:)
希望这取决于Geraint Davies的标准
如果第二个图形中的任何位置都有最轻微的错误,当您运行第二个图形时,它将停止第一个图形。 这是一个很好的迹象。 如果你给它一个无效的名称,比如制作Avi mux – >文件编写器尝试保存在一个不真实的位置,它会停止图形
此代码将创建一个新窗口并将video粘贴到新窗口中。 要将video流式传输到表单的面板框中,您只需要添加4行代码。
IVideoWindow var = firstgraph as IVideoWindow(); var.put_Owner(panel1.handle); var.put_windowstyle( windowstyle.child | windowstyle.clipchildren ); var.SetWindowPosition( panel1.clientrectangle.left, panel1.clientrectangle.top, panel1.clientrectangle.width, panel1.clientrectangle.height);