我使用GMFBridge.DLL正确预览/捕获流吗?

时间:2011-06-21 22:03:48

标签: c# directshow directshow.net

我正在尝试使用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();

    }

1 个答案:

答案 0 :(得分:5)

根据我目前的知识正确使用GMFBridge:

从:http://www.gdcl.co.uk/gmfbridge/抓取GMFBridge DLL 从:https://sourceforge.net/projects/directshownet/files/DirectShowNET/

获取DirectShowLib DLL

将它们包含在您的项目中。

创建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);

从这里您可以添加源视频过滤器,它不需要连接到网桥,添加Smart Tee,并将源连接到Smart Tee。

然后创建一个过滤器来容纳将要完成工作的第一个桥接过滤器

BridgeSinkFilter = (IBaseFilter)Bridge.InsertSinkFilter(firstgraph);

此过滤器将持续接受来自Smart Tee捕获引脚的视频。如果第二个图桥接过滤器已连接并正在运行,它会将视频从BridgeSInkFilter传递到第二个图形。否则,它只会抛出它,但它总是在运行。

将BridgeSinkFilter连接到Smart Tee的捕获引脚。 我发现连接引脚的最佳方法是使用https://splicer.svn.codeplex.com/svn/src/Splicer/Utilities/FilterGraphTools.cs的FindPinByDirection,然后调用

firstgraph.connect(pinoutput, pininput)

从此处开始,要预览视频,应添加FilterCategory.LegacyAmFilterCategory中的AVI Decompressor过滤器,并将其连接到Smart Tee的预览引脚。然后,Video Renderer添加并连接到AVI Decompressor。

那应该照顾第一张图。

第二张图需要从桥开始。它将从第一个图形bridgesinkfilter创建一个桥梁,并将其拉到第二个图形,我们可以在其中执行任何我们想要的任务。要做到这一点,我们需要桥梁的另一面。

IBaseFilter BridgeSourceFilter = (IBaseFilter)Bridge.InsertSourceFilter(BridgeSinkFilter,secondgraph);

这将源设置为第一段中的sinkfilter,但是在BridgeSourceFilter的幌子下将其放在我们的第二个图上。

现在连接编码器,ffdshow视频编码器等。 将它连接到BridgeSourceFilter。

添加多路复用器,AVI Mux和文件编写器。连接他们。这就是第二张图的一切。

要完成图形关闭,我们需要创建2个可以启动和停止图形的媒体控制器。

IMediaControl MediaControl_FirstGraph = (IMediaControl)firstgraph;
IMediaControl MediaControl_SecondGraph = (IMediaControl)secondgraph;

现在我们可以致电

MediaControl_FirstGraph.Run() to start previewing the video.

然后要捕获该视频,我们需要连接第一个和第二个图之间的桥,然后运行第二个图。

Bridge.BridgeGraphs(BridgeSinkFilter,BridgeSourceFilter);
MediaControl_SecondGraph.Run()

在任何时候,您都可以通过断开桥接连接来停止捕获,然后停止第二个图形。

Bridge.BridgeGraphs(null, null);
MediaControl_SecondGraph.Stop();

我认为这涵盖了我发现的关于GMF桥控制的内容:)

希望这取决于Geraint Davies的标准

如果第二个图形中的任何位置都有最轻微的错误,当您运行第二个图形时,它将停止第一个图形。这是一个很好的迹象。如果你给它一个无效的名称,比如制作Avi mux - >文件编写者试图保存在一个不真实的位置,它会停止图形

此代码将创建一个新窗口并将视频粘贴到新窗口中。要将视频流式传输到表单的面板框中,您只需要添加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);