Am I using the GMFBridge.DLL to preview/capture a stream correctly?
I am trying to use the GMFBuilder so that i can preview a stream from a webcam and save it periodically without restarting the whole graph. However Im not sure if this is correct or not, I was trying to follow examples but the codes been开发者_StackOverflow社区 updated and things have changed.
I try and create:
WEbcam -> Smart Tee (preview) -> AVI Decompressor -> Video Renderer
Smart Tee (Capture) -> BridgeSinkFilter
and also:
BridgeSourceFilter -> ffdshow video encoder -> haali mastroska muxer
(just cause its easy to use)
Input regarding getting the code to run properly would be greatly appreciated.
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();
}
To use GMFBridge correctly to my current knowledge:
Grab the GMFBridge DLL from: http://www.gdcl.co.uk/gmfbridge/ Grab the DirectShowLib DLL from: https://sourceforge.net/projects/directshownet/files/DirectShowNET/
include them both in your project.
Create 2 graphs. 1 is for preview the 2nd is for capture.
IGraphBuilder firstgraph = (IGraphBuilder) new FilterGraph();
IGraphBuilder secondgraph = (IGraphBuilder) new FilterGraph();
Create a Bridge which from the GMFBridge dll, will connect the two graphs
IGMFBridgeController Bridge = (IGMFBridgeController) new GMFBridgeController();
From here you setup the bridge to allow for muxed inputs
Bridge.AddStream(1, eFormatType.eMuxInputs, 1);
from here you can add your source video filter, it doesnt need connected to the bridge, add Smart Tee, and connect source to Smart Tee.
then create a filter to house the first bridge filter that will do the work
BridgeSinkFilter = (IBaseFilter)Bridge.InsertSinkFilter(firstgraph);
This filter will continuously accept video from the capture pin of Smart Tee. If the 2nd graph bridge filter is connected and running it will pass the video from BridgeSInkFilter to the 2nd graph. otherwise, it just throws it out, but it is always running.
Connect the BridgeSinkFilter to the capture pin of Smart Tee. I found the best way to connect the pins is to use FindPinByDirection by https://splicer.svn.codeplex.com/svn/src/Splicer/Utilities/FilterGraphTools.cs and then just call
firstgraph.connect(pinoutput, pininput)
From here, to preview the video, the AVI Decompressor filter from FilterCategory.LegacyAmFilterCategory should be addedd and connected to the Preview pin of Smart Tee. Then Video Renderer added and connected to AVI Decompressor.
That should take care of the first graph.
The second graph needs to start with the bridge. it will create a bridge from the first graph bridgesinkfilter and pull it to a second graph in which we can do anything we want to it. to do this we need the other side of the bridge.
IBaseFilter BridgeSourceFilter = (IBaseFilter)Bridge.InsertSourceFilter(BridgeSinkFilter,secondgraph);
this sets the source as the sinkfilter from the firstgraph but puts it on our second graph under the guise of BridgeSourceFilter.
Now connect an encoder, ffdshow video encoder, etc.. connect it to the BridgeSourceFilter.
add in a muxer, AVI Mux, and file writer. Connect them. Thats everything for the second graph.
To finish the graphs off, we need to create 2 mediacontrollers that can start and stop the graphs.
IMediaControl MediaControl_FirstGraph = (IMediaControl)firstgraph;
IMediaControl MediaControl_SecondGraph = (IMediaControl)secondgraph;
now we can call
MediaControl_FirstGraph.Run() to start previewing the video.
and then to capture that video, we need to connect the bridge between the first and second graph, then run the second graph.
Bridge.BridgeGraphs(BridgeSinkFilter,BridgeSourceFilter);
MediaControl_SecondGraph.Run()
at any point, you can stop capturing by breaking the bridge connection, then stopping the second graph.
Bridge.BridgeGraphs(null, null);
MediaControl_SecondGraph.Stop();
I think that about covers what ive found out about GMF bridge control :)
Hopefully this is up to Geraint Davies's standards
if there is even the slightest error anywhere in the second graph, when you run the second graph, it will stop the first graph. its a good indication something is wrong. If you give it an invalid name like making Avi mux -> file writer try to save in a location that isnt real, itll stop the graph
This code would create a new window and stick the video in that new window. To stream the video into a panel box of a form you just really need to add 4 lines of code.
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);
精彩评论