/// <summary> /// Connects pins of graph /// </summary> private void GraphBuilding_ConnectPins() { // Pins used in graph IPin pinSourceCapture = null; IPin pinTeeInput = null; IPin pinTeePreview = null; IPin pinTeeCapture = null; IPin pinSampleGrabberInput = null; IPin pinRendererInput = null; try { // Collect pins pinSourceCapture = DsFindPin.ByDirection(CaptureFilter, PinDirection.Output, 0); pinTeeInput = DsFindPin.ByDirection(SmartTee, PinDirection.Input, 0); pinTeePreview = DsFindPin.ByName(SmartTee, "Preview"); pinTeeCapture = DsFindPin.ByName(SmartTee, "Capture"); pinSampleGrabberInput = DsFindPin.ByDirection(SampleGrabberFilter, PinDirection.Input, 0); pinRendererInput = DsFindPin.ByDirection(VMRenderer, PinDirection.Input, 0); // Connect source to tee splitter int hr = FilterGraph.Connect(pinSourceCapture, pinTeeInput); DsError.ThrowExceptionForHR(hr); // Connect samplegrabber on preview-pin of tee splitter hr = FilterGraph.Connect(pinTeePreview, pinSampleGrabberInput); DsError.ThrowExceptionForHR(hr); // Connect the capture-pin of tee splitter to the renderer hr = FilterGraph.Connect(pinTeeCapture, pinRendererInput); DsError.ThrowExceptionForHR(hr); } catch { throw; } finally { SafeReleaseComObject(pinSourceCapture); pinSourceCapture = null; SafeReleaseComObject(pinTeeInput); pinTeeInput = null; SafeReleaseComObject(pinTeePreview); pinTeePreview = null; SafeReleaseComObject(pinTeeCapture); pinTeeCapture = null; SafeReleaseComObject(pinSampleGrabberInput); pinSampleGrabberInput = null; SafeReleaseComObject(pinRendererInput); pinRendererInput = null; } return; }
private void BuildGraph() { int hr = 0; // quick and dirty dvd graph building graphBuilder = (IFilterGraph2) new FilterGraph(); dvdNavigator = (IBaseFilter) new DVDNavigator(); vmr = (IBaseFilter) new VideoMixingRenderer(); dsRenderer = (IBaseFilter) new DSoundRender(); hr = graphBuilder.AddFilter(dvdNavigator, "DVD Navigator"); DsError.ThrowExceptionForHR(hr); hr = (dvdNavigator as IDvdControl2).SetDVDDirectory(dvdDrive); DsError.ThrowExceptionForHR(hr); hr = graphBuilder.AddFilter(vmr, "VMR"); DsError.ThrowExceptionForHR(hr); // Enable vmr7's mixer hr = (vmr as IVMRFilterConfig).SetNumberOfStreams(1); DsError.ThrowExceptionForHR(hr); deinterlaceControl = (IVMRDeinterlaceControl)vmr; hr = graphBuilder.AddFilter(dsRenderer, "Audio"); DsError.ThrowExceptionForHR(hr); IPin pinOut = DsFindPin.ByDirection(dvdNavigator, PinDirection.Output, 0); IPin pinIn = DsFindPin.ByDirection(vmr, PinDirection.Input, 0); hr = graphBuilder.Connect(pinOut, pinIn); DsError.ThrowExceptionForHR(hr); Marshal.ReleaseComObject(pinOut); Marshal.ReleaseComObject(pinIn); pinOut = DsFindPin.ByDirection(dvdNavigator, PinDirection.Output, 1); pinIn = DsFindPin.ByDirection(dsRenderer, PinDirection.Input, 0); hr = graphBuilder.Connect(pinOut, pinIn); DsError.ThrowExceptionForHR(hr); Marshal.ReleaseComObject(pinOut); Marshal.ReleaseComObject(pinIn); // Run graph hr = (graphBuilder as IMediaControl).Run(); DsError.ThrowExceptionForHR(hr); }
private static bool ConnectFilter(IFilterGraph2 graphBuilder, IBaseFilter networkFilter, IBaseFilter tunerFilter) { IPin pinOut = DsFindPin.ByDirection(networkFilter, PinDirection.Output, 0); IPin pinIn = DsFindPin.ByDirection(tunerFilter, PinDirection.Input, 0); int hr = graphBuilder.Connect(pinOut, pinIn); return (hr == 0); }
public void SetupVideoStream(IFilterGraph2 builder, IBaseFilter capfiler, IBaseFilter renderer, Control target) { //串接後面的Filters 的 Pins //目前不做畫面擷取所以也不需要用SmartTee來分流 IPin pin_out = null; IPin pin_in = null; //==== Streaming Circuit ==== try { //Win7開始預設最好是使用 VideoMixingRenderer7,當然能用VideoMixingRenderer9更好 //原始的VideoRenderer吃不到顯卡的特殊能力 //renderer = (IBaseFilter)new VideoMixingRenderer9(); SetupRenderWindow((IVMRFilterConfig9)renderer, target); builder.AddFilter(renderer, "Video Mixing Renderer 9"); pin_in = DsFindPin.ByDirection(renderer, PinDirection.Input, 0); //裝好Filter以後,在Capture Device找出對應的pin腳然後接上去... //就像焊接電路一樣的觀念 pin_out = DsFindPin.ByCategory(capfiler, PinCategory.Capture, 0); builder.Connect(pin_out, pin_in); } finally { //todo: 這邊應該弄Dispose不應該直接叫 Marshal if (null != pin_out) { Marshal.ReleaseComObject(pin_out); } if (null != pin_in) { Marshal.ReleaseComObject(pin_in); } } }
private static bool ConnectFilter(IFilterGraph2 graphBuilder, IBaseFilter networkFilter, IBaseFilter tunerFilter) { IPin pinOut = DsFindPin.ByDirection(networkFilter, PinDirection.Output, 0); IPin pinIn = DsFindPin.ByDirection(tunerFilter, PinDirection.Input, 0); int hr = graphBuilder.Connect(pinOut, pinIn); return(hr == 0); }
private void SetupCapturePin(int RequestedHeight, int RequestedWidth, short iBPP) { int hr; if (RequestedHeight + RequestedWidth + iBPP > 0) { SetPinParameters(m_pinCapture, RequestedWidth, RequestedHeight, iBPP); } captureSG = new SampleGrabber() as ISampleGrabber; IBaseFilter baseCaptureGrabFlt = captureSG as IBaseFilter; ConfigureSampleGrabber(captureSG, 1); pCaptureSampleIn = DsFindPin.ByDirection(baseCaptureGrabFlt, PinDirection.Input, 0); hr = m_FilterGraph.AddFilter(baseCaptureGrabFlt, "Ds.NET Grabber"); DsError.ThrowExceptionForHR(hr); hr = m_FilterGraph.Connect(m_pinCapture, pCaptureSampleIn); DsError.ThrowExceptionForHR(hr); pCaptureSampleOut = DsFindPin.ByDirection(baseCaptureGrabFlt, PinDirection.Output, 0); //SetupDummyWindow(); }
private void SetupVideoStream(IFilterGraph2 builder, IBaseFilter capfiler, IBaseFilter renderer, IntPtr render_handle, Rectangle render_rect) { //串接後面的Filters 的 Pins //目前不做畫面擷取所以也不需要用SmartTee來分流 IPin pin_out = null; IPin pin_in = null; //==== Streaming Circuit ==== try { //Win7開始預設最好是使用 VideoMixingRenderer7,當然能用VideoMixingRenderer9更好 //原始的VideoRenderer吃不到顯卡的特殊能力 //renderer = (IBaseFilter)new VideoMixingRenderer9(); SetupRenderWindow((IVMRFilterConfig9)renderer, render_handle, render_rect); builder.AddFilter(renderer, "Video Mixing Renderer 9"); pin_in = DsFindPin.ByDirection(renderer, PinDirection.Input, 0); //裝好Filter以後,在Capture Device找出對應的pin腳然後接上去... //就像焊接電路一樣的觀念 pin_out = DsFindPin.ByCategory(capfiler, PinCategory.Capture, 0); //todo: setup capture format //IAMStreamConfig pin_cfg = (IAMStreamConfig) pin_out; //AMMediaType type = null; //int count = 0, size = 0; //pin_cfg.GetNumberOfCapabilities(out count, out size); //for (int i = 0; i < count; i++) //{ // //IntPtr scc = Marshal.AllocHGlobal(Marshal.SizeOf<VideoStreamConfigCaps>()); // VideoStreamConfigCaps cap = new VideoStreamConfigCaps(); // GCHandle handle = GCHandle.Alloc(cap, GCHandleType.Pinned); // IntPtr scc = handle.AddrOfPinnedObject(); // //Marshal.StructureToPtr<VideoStreamConfigCaps>(cap, scc, false); // pin_cfg.GetStreamCaps(i, out type, scc); // handle.Free(); //} builder.Connect(pin_out, pin_in); } finally { //todo: 這邊應該弄Dispose不應該直接叫 Marshal if (null != pin_out) { Marshal.ReleaseComObject(pin_out); } if (null != pin_in) { Marshal.ReleaseComObject(pin_in); } } }
private IBaseFilter BuildPreviewOnlyCaptureGraph(DsDevice dev, VideoFormatHelper.SupportedVideoFormat selectedFormat, ref float iFrameRate, ref int iWidth, ref int iHeight) { // Capture Source (Capture/Video) --> (Input) Sample Grabber (Output) --> (In) Null Renderer IBaseFilter nullRenderer = null; try { IBaseFilter capFilter; // Add the video device int hr = filterGraph.AddSourceFilterForMoniker(dev.Mon, null, dev.Name, out capFilter); DsError.ThrowExceptionForHR(hr); if (capFilter != null) { SetConfigParms(capBuilder, capFilter, selectedFormat, ref iFrameRate, ref iWidth, ref iHeight); } IBaseFilter baseGrabFlt = (IBaseFilter)samplGrabber; ConfigureSampleGrabber(samplGrabber); hr = filterGraph.AddFilter(baseGrabFlt, "ASCOM Video Grabber"); DsError.ThrowExceptionForHR(hr); // Connect the video device output to the sample grabber IPin videoCaptureOutputPin = FindPin(capFilter, PinDirection.Output, MediaType.Video, PinCategory.Capture, "Capture"); IPin grabberInputPin = DsFindPin.ByDirection(baseGrabFlt, PinDirection.Input, 0); hr = filterGraph.Connect(videoCaptureOutputPin, grabberInputPin); DsError.ThrowExceptionForHR(hr); Marshal.ReleaseComObject(videoCaptureOutputPin); Marshal.ReleaseComObject(grabberInputPin); // Add the frame grabber to the graph nullRenderer = (IBaseFilter) new NullRenderer(); hr = filterGraph.AddFilter(nullRenderer, "ASCOM Video Null Renderer"); DsError.ThrowExceptionForHR(hr); // Connect the sample grabber to the null renderer (so frame samples will be coming through) IPin grabberOutputPin = DsFindPin.ByDirection(baseGrabFlt, PinDirection.Output, 0); IPin renderedInputPin = DsFindPin.ByDirection(nullRenderer, PinDirection.Input, 0); hr = filterGraph.Connect(grabberOutputPin, renderedInputPin); DsError.ThrowExceptionForHR(hr); Marshal.ReleaseComObject(grabberOutputPin); Marshal.ReleaseComObject(renderedInputPin); return(capFilter); } finally { if (nullRenderer != null) { Marshal.ReleaseComObject(nullRenderer); } } }
/// <summary> build the capture graph for grabber. </summary> private void SetupGraph(string FileName, Control hWin) { int hr; IBaseFilter ibfRenderer = null; ISampleGrabber sampGrabber = null; IBaseFilter capFilter = null; IPin iPinInFilter = null; IPin iPinOutFilter = null; IPin iPinInDest = null; IBasicAudio basicAudio = null; // Get the graphbuilder object m_FilterGraph = new FilterGraph() as IFilterGraph2; #if DEBUG m_rot = new DsROTEntry(m_FilterGraph); #endif try { // Get the SampleGrabber interface sampGrabber = new SampleGrabber() as ISampleGrabber; // Add the video source hr = m_FilterGraph.AddSourceFilter(FileName, "Ds.NET FileFilter", out capFilter); DsError.ThrowExceptionForHR(hr); // Hopefully this will be the video pin IPin iPinOutSource = DsFindPin.ByDirection(capFilter, PinDirection.Output, 0); IBaseFilter baseGrabFlt = sampGrabber as IBaseFilter; ConfigureSampleGrabber(sampGrabber); iPinInFilter = DsFindPin.ByDirection(baseGrabFlt, PinDirection.Input, 0); iPinOutFilter = DsFindPin.ByDirection(baseGrabFlt, PinDirection.Output, 0); // Add the frame grabber to the graph hr = m_FilterGraph.AddFilter(baseGrabFlt, "Ds.NET Grabber"); DsError.ThrowExceptionForHR(hr); hr = m_FilterGraph.Connect(iPinOutSource, iPinInFilter); DsError.ThrowExceptionForHR(hr); // Get the default video renderer ibfRenderer = (IBaseFilter)new VideoRendererDefault(); // Add it to the graph hr = m_FilterGraph.AddFilter(ibfRenderer, "Ds.NET VideoRendererDefault"); DsError.ThrowExceptionForHR(hr); iPinInDest = DsFindPin.ByDirection(ibfRenderer, PinDirection.Input, 0); // Connect the graph. Many other filters automatically get added here hr = m_FilterGraph.Connect(iPinOutFilter, iPinInDest); DsError.ThrowExceptionForHR(hr); SaveSizeInfo(sampGrabber); // Set the output window IVideoWindow videoWindow = m_FilterGraph as IVideoWindow; hr = videoWindow.put_Owner(hWin.Handle); DsError.ThrowExceptionForHR(hr); hr = videoWindow.put_WindowStyle(WindowStyle.Child | WindowStyle.ClipChildren | WindowStyle.ClipSiblings); DsError.ThrowExceptionForHR(hr); hr = videoWindow.put_Visible(OABool.True); DsError.ThrowExceptionForHR(hr); //TODO : Need a better way to hide the video in the parent Window Rectangle rc = hWin.ClientRectangle; if (mParentWindowDisplay) hr = videoWindow.SetWindowPosition(0, 0, rc.Right, rc.Bottom); else hr = videoWindow.SetWindowPosition(0, 0, 0, 0); DsError.ThrowExceptionForHR(hr); IGraphBuilder graphBuilder = m_FilterGraph as IGraphBuilder; ICaptureGraphBuilder2 captureGraphBuilder = (ICaptureGraphBuilder2)new CaptureGraphBuilder2(); // Attach the filter graph to the capture graph hr = captureGraphBuilder.SetFiltergraph(graphBuilder); DsError.ThrowExceptionForHR(hr); hr = captureGraphBuilder.RenderStream(null, MediaType.Audio, capFilter, null, null); } finally { if (capFilter != null) { Marshal.ReleaseComObject(capFilter); capFilter = null; } if (sampGrabber != null) { Marshal.ReleaseComObject(sampGrabber); sampGrabber = null; } if (ibfRenderer != null) { Marshal.ReleaseComObject(ibfRenderer); ibfRenderer = null; } if (iPinInFilter != null) { Marshal.ReleaseComObject(iPinInFilter); iPinInFilter = null; } if (iPinOutFilter != null) { Marshal.ReleaseComObject(iPinOutFilter); iPinOutFilter = null; } if (iPinInDest != null) { Marshal.ReleaseComObject(iPinInDest); iPinInDest = null; } } }
/// <summary> build the capture graph for grabber. </summary> private void SetupGraph(DsDevice dev, int iSampleRate, int iChannels) { int hr; ISampleGrabber sampGrabber = null; IBaseFilter capFilter = null; ICaptureGraphBuilder2 capGraph = null; IBaseFilter baseGrabFlt = null; IBaseFilter nullrenderer = null; IMediaFilter mediaFilt = m_FilterGraph as IMediaFilter; // Get the graphbuilder object m_FilterGraph = (IFilterGraph2)new FilterGraph(); m_mediaCtrl = m_FilterGraph as IMediaControl; try { // Get the ICaptureGraphBuilder2 capGraph = (ICaptureGraphBuilder2)new CaptureGraphBuilder2(); // Get the SampleGrabber interface sampGrabber = (ISampleGrabber)new SampleGrabber(); // Start building the graph hr = capGraph.SetFiltergraph(m_FilterGraph); DsError.ThrowExceptionForHR(hr); // Add the audio device hr = m_FilterGraph.AddSourceFilterForMoniker(dev.Mon, null, "Audio input", out capFilter); DsError.ThrowExceptionForHR(hr); // If any of the default config items are set if (iSampleRate + iChannels > 0) { SetConfigParms(capGraph, capFilter, iSampleRate, iChannels); } // Get the SampleGrabber interface sampGrabber = new SampleGrabber() as ISampleGrabber; baseGrabFlt = sampGrabber as IBaseFilter; ConfigureSampleGrabber(sampGrabber); // Add the frame grabber to the graph hr = m_FilterGraph.AddFilter(baseGrabFlt, "Ds.NET Grabber"); DsError.ThrowExceptionForHR(hr); // --------------------------------- // Connect the file filter to the sample grabber // Hopefully this will be the audio pin, we could check by reading it's mediatype IPin iPinOut = DsFindPin.ByDirection(capFilter, PinDirection.Output, 0); // Get the input pin from the sample grabber IPin iPinIn = DsFindPin.ByDirection(baseGrabFlt, PinDirection.Input, 0); hr = m_FilterGraph.Connect(iPinOut, iPinIn); DsError.ThrowExceptionForHR(hr); // Add the null renderer to the graph nullrenderer = new NullRenderer() as IBaseFilter; hr = m_FilterGraph.AddFilter(nullrenderer, "Null renderer"); DsError.ThrowExceptionForHR(hr); // --------------------------------- // Connect the sample grabber to the null renderer iPinOut = DsFindPin.ByDirection(baseGrabFlt, PinDirection.Output, 0); iPinIn = DsFindPin.ByDirection(nullrenderer, PinDirection.Input, 0); hr = m_FilterGraph.Connect(iPinOut, iPinIn); DsError.ThrowExceptionForHR(hr); // Read and cache the resulting settings SaveSizeInfo(sampGrabber); } finally { if (capFilter != null) { Marshal.ReleaseComObject(capFilter); capFilter = null; } if (sampGrabber != null) { Marshal.ReleaseComObject(sampGrabber); sampGrabber = null; } if (capGraph != null) { Marshal.ReleaseComObject(capGraph); capGraph = null; } } }
private void InitDevice() { try { //Set the video size to use for capture and recording videoSize = new Size(1280, 720);//827, 505);//1280, 720); //Initialize filter graph and capture graph graph = (IFilterGraph2) new FilterGraph(); captureGraph = (ICaptureGraphBuilder2) new CaptureGraphBuilder2(); captureGraph.SetFiltergraph(graph); //rot = new DsROTEntry(graph); //Create filter for Elgato Guid elgatoGuid = new Guid("39F50F4C-99E1-464A-B6F9-D605B4FB5918"); Type comType = Type.GetTypeFromCLSID(elgatoGuid); IBaseFilter elgatoFilter = (IBaseFilter)Activator.CreateInstance(comType); graph.AddFilter(elgatoFilter, "Elgato Video Capture Filter"); //Create smart tee filter, add to graph, connect Elgato's video out to smart tee in IBaseFilter smartTeeFilter = (IBaseFilter) new SmartTee(); graph.AddFilter(smartTeeFilter, "Smart Tee"); IPin outPin = GetPin(elgatoFilter, "Video"); //GetPin(PinDirection.Output, "Video", elgatoFilter); //IPin inPin = GetPin(elgatoFilter, "Video");//GetPin(PinDirection.Input, smartTeeFilter); IPin inPin = GetPin(smartTeeFilter, "Input"); //GetPin(PinDirection.Input, smartTeeFilter); SetAndGetAllAvailableResolution(outPin); graph.Connect(outPin, inPin); //Create video renderer filter, add it to graph, connect smartTee Preview pin to video renderer's input pin IBaseFilter videoRendererFilter = (IBaseFilter) new VideoRenderer(); graph.AddFilter(videoRendererFilter, "Video Renderer"); // outPin = GetPin(elgatoFilter, "Video");//GetPin(PinDirection.Output, "Preview", smartTeeFilter); outPin = GetPin(smartTeeFilter, "Preview"); //GetPin(PinDirection.Output, "Preview", smartTeeFilter); //outPin = GetPin(smartTeeFilter, "Capture");//GetPin(PinDirection.Output, "Preview", smartTeeFilter); // i'm trying to send the capture output to the screen.. but probably it won't be good //inPin = GetPin(elgatoFilter, "Video");//GetPin(PinDirection.Input, videoRendererFilter); inPin = GetPin(videoRendererFilter, "Input");//GetPin(PinDirection.Input, videoRendererFilter); graph.Connect(outPin, inPin); //Render stream from video renderer captureGraph.RenderStream(PinCategory.Preview, MediaType.Video, videoRendererFilter, null, null); //graph.Render( //Set the video preview to be the videoFeed panel IVideoWindow vw = (IVideoWindow)graph; vw.put_Owner(pictureBox.Handle); vw.put_MessageDrain(form.Handle); vw.put_WindowStyle(WindowStyle.Child | WindowStyle.ClipSiblings | WindowStyle.ClipChildren); vw.SetWindowPosition(0, 0, videoSize.Width, videoSize.Height);//1280, 720); //Start the preview IMediaControl mediaControl = graph as IMediaControl; //pictureBox1. mediaControl.Run(); Task.Run(() => { Task.Delay(1000).Wait(); while (true) { var ss = Screenshot(pictureBox); //ss.Save("outputje.png", ImageFormat.Png); try { imageDetected(ss); } catch (Exception ex) { } Task.Delay(20).Wait(); } }); } catch (Exception err) { error = err.ToString(); } }
private void SetupGraph(Control hWin) { if (theCaptureDevice == null) return; int hr; IBaseFilter ibfRenderer = null; ISampleGrabber sampGrabber = null; IBaseFilter capFilter = null; IPin iPinInFilter = null; IPin iPinOutFilter = null; IPin iPinInDest = null; // Get the graphbuilder object m_FilterGraph = new FilterGraph() as IFilterGraph2; try { // Add the video input device to the graph hr = m_FilterGraph.AddFilter(theCaptureDevice, "source filter"); DsError.ThrowExceptionForHR(hr); if (captureDeviceCrossbar != null) { // Add the video inputs' crossbar to the graph hr = m_FilterGraph.AddFilter(captureDeviceCrossbar, "source crossbar"); DsError.ThrowExceptionForHR(hr); //// Get crossbars's output IPin iPinOutCrossbar = DsFindPin.ByDirection(captureDeviceCrossbar, PinDirection.Output, 0); m_FilterGraph.Render(iPinOutCrossbar); } // Get input device's output iPinOutSource = DsFindPin.ByDirection(theCaptureDevice, PinDirection.Output, 0); ibfRenderer = (IBaseFilter)new VideoRendererDefault(); // Add it to the graph hr = m_FilterGraph.AddFilter(ibfRenderer, "Ds.NET VideoRendererDefault"); DsError.ThrowExceptionForHR(hr); iPinInDest = DsFindPin.ByDirection(ibfRenderer, PinDirection.Input, 0); // Connect the graph. Many other filters automatically get added here hr = m_FilterGraph.Connect(iPinOutSource, iPinInDest); DsError.ThrowExceptionForHR(hr); IVideoWindow videoWindow = m_FilterGraph as IVideoWindow; hr = videoWindow.put_Owner(hWin.Handle); DsError.ThrowExceptionForHR(hr); hr = videoWindow.put_WindowStyle(WindowStyle.Child | WindowStyle.ClipChildren | WindowStyle.ClipSiblings); DsError.ThrowExceptionForHR(hr); hr = videoWindow.put_Visible(OABool.True); DsError.ThrowExceptionForHR(hr); Rectangle rc = hWin.ClientRectangle; hr = videoWindow.SetWindowPosition(0, 0, rc.Right, rc.Bottom); DsError.ThrowExceptionForHR(hr); } finally { if (theCaptureDevice != null) { Marshal.ReleaseComObject(theCaptureDevice); theCaptureDevice = null; } if (capFilter != null) { Marshal.ReleaseComObject(capFilter); capFilter = null; } if (sampGrabber != null) { Marshal.ReleaseComObject(sampGrabber); sampGrabber = null; } if (ibfRenderer != null) { Marshal.ReleaseComObject(ibfRenderer); ibfRenderer = null; } if (iPinInFilter != null) { Marshal.ReleaseComObject(iPinInFilter); iPinInFilter = null; } if (iPinOutFilter != null) { Marshal.ReleaseComObject(iPinOutFilter); iPinOutFilter = null; } if (iPinInDest != null) { Marshal.ReleaseComObject(iPinInDest); iPinInDest = null; } } }
/// <summary> /// Creates the teletext component in the graph. First we try to use the stored informations in the graph /// </summary> /// <param name="graph">The stored graph</param> /// <param name="graphBuilder">The graphbuilder</param> /// <param name="capture">The capture component</param> /// <returns>true, if the building was successful; false otherwise</returns> public bool CreateFilterInstance(Graph graph, IFilterGraph2 graphBuilder, Capture capture) { Log.Log.WriteFile("analog: SetupTeletext()"); Guid guidBaseFilter = typeof (IBaseFilter).GUID; object obj; //find and add tee/sink to sink filter DsDevice[] devices = DsDevice.GetDevicesOfCat(FilterCategory.AMKSSplitter); devices[0].Mon.BindToObject(null, null, ref guidBaseFilter, out obj); _teeSink = (IBaseFilter)obj; int hr = graphBuilder.AddFilter(_teeSink, devices[0].Name); if (hr != 0) { Log.Log.Error("analog:SinkGraphEx.SetupTeletext(): Unable to add tee/sink filter"); return false; } //connect capture filter -> tee sink filter IPin pin = DsFindPin.ByDirection(_teeSink, PinDirection.Input, 0); hr = graphBuilder.Connect(capture.VBIPin, pin); Release.ComObject(pin); if (hr != 0) { //failed... Log.Log.Error("analog: unable to connect capture->tee/sink"); graphBuilder.RemoveFilter(_teeSink); Release.ComObject(_teeSink); _teeSink = _filterWstDecoder = null; return false; } if (!string.IsNullOrEmpty(graph.Teletext.Name)) { Log.Log.WriteFile("analog: Using Teletext-Component configuration from stored graph"); devices = DsDevice.GetDevicesOfCat(graph.Teletext.Category); foreach (DsDevice device in devices) { if (device.Name != null && device.Name.Equals(graph.Teletext.Name)) { //found it, add it to the graph Log.Log.Info("analog:Using teletext component - {0}", graph.Teletext.Name); device.Mon.BindToObject(null, null, ref guidBaseFilter, out obj); _filterWstDecoder = (IBaseFilter)obj; hr = graphBuilder.AddFilter(_filterWstDecoder, device.Name); if (hr != 0) { //failed... Log.Log.Error("analog:SinkGraphEx.SetupTeletext(): Unable to add WST Codec filter"); graphBuilder.RemoveFilter(_filterWstDecoder); _filterWstDecoder = null; } break; } } } if (_filterWstDecoder == null) { Log.Log.WriteFile("analog: No stored or invalid graph for Teletext component - Trying to detect"); //find the WST codec filter devices = DsDevice.GetDevicesOfCat(FilterCategory.AMKSVBICodec); foreach (DsDevice device in devices) { if (device.Name != null && device.Name.IndexOf("WST") >= 0) { //found it, add it to the graph Log.Log.Info("analog:Found WST Codec filter"); device.Mon.BindToObject(null, null, ref guidBaseFilter, out obj); _filterWstDecoder = (IBaseFilter)obj; hr = graphBuilder.AddFilter(_filterWstDecoder, device.Name); if (hr != 0) { //failed... Log.Log.Error("analog:Unable to add WST Codec filter"); graphBuilder.RemoveFilter(_teeSink); Release.ComObject(_teeSink); _teeSink = _filterWstDecoder = null; return false; } graph.Teletext.Name = device.Name; graph.Teletext.Category = FilterCategory.AMKSVBICodec; break; } } //Look for VBI Codec for Vista users as Vista doesn't use WST Codec anymore if (_filterWstDecoder == null) { devices = DsDevice.GetDevicesOfCat(FilterCategory.AMKSMULTIVBICodec); foreach (DsDevice device in devices) if (device.Name != null && device.Name.IndexOf("VBI") >= 0) { //found it, add it to the graph Log.Log.Info("analog:Found VBI Codec filter"); device.Mon.BindToObject(null, null, ref guidBaseFilter, out obj); _filterWstDecoder = (IBaseFilter)obj; hr = graphBuilder.AddFilter(_filterWstDecoder, device.Name); if (hr != 0) { //failed... Log.Log.Error("analog:Unable to add VBI Codec filter"); graphBuilder.RemoveFilter(_teeSink); Release.ComObject(_teeSink); _teeSink = _filterWstDecoder = null; return false; } graph.Teletext.Name = device.Name; graph.Teletext.Category = FilterCategory.AMKSMULTIVBICodec; break; } } } if (_filterWstDecoder == null) { Log.Log.Error("analog: unable to find WST Codec or VBI Codec filter"); graphBuilder.RemoveFilter(_teeSink); Release.ComObject(_teeSink); _teeSink = _filterWstDecoder = null; return false; } //connect tee sink filter-> wst codec filter IPin pinOut = DsFindPin.ByDirection(_teeSink, PinDirection.Output, 0); pin = DsFindPin.ByDirection(_filterWstDecoder, PinDirection.Input, 0); hr = graphBuilder.Connect(pinOut, pin); Release.ComObject(pin); Release.ComObject(pinOut); if (hr != 0) { //failed Log.Log.Error("analog: unable to tee/sink->wst codec"); graphBuilder.RemoveFilter(_filterWstDecoder); graphBuilder.RemoveFilter(_teeSink); Release.ComObject(_filterWstDecoder); Release.ComObject(_teeSink); _teeSink = _filterWstDecoder = null; _teeSink = null; graph.Teletext.Name = null; graph.Teletext.Category = new Guid(); return false; } //done Log.Log.WriteFile("analog: teletext setup"); if (_filterWstDecoder != null) { Log.Log.WriteFile("analog:connect wst/vbi codec->tsfilesink"); _pinWST_VBI = DsFindPin.ByDirection(_filterWstDecoder, PinDirection.Output, 0); } return true; }
/// <summary> /// Creates the filter by trying to detect it /// </summary> /// <param name="crossbar">The crossbar componen</param> /// <param name="tuner">The tuner component</param> /// <param name="graph">The stored graph</param> /// <param name="graphBuilder">The graphBuilder</param> /// <returns>true, if the graph building was successful</returns> private bool CreateAutomaticFilterInstance(Graph graph, Tuner tuner, Crossbar crossbar, IFilterGraph2 graphBuilder) { //get all tv audio tuner devices on this system DsDevice[] devices = null; try { devices = DsDevice.GetDevicesOfCat(FilterCategory.AMKSTVAudio); devices = DeviceSorter.Sort(devices, tuner.TunerName, crossbar.CrossBarName); } catch (Exception) { Log.Log.WriteFile("analog: AddTvAudioFilter no tv audio devices found - Trying TvTuner filter"); } if (devices != null && devices.Length > 0) { // try each tv audio tuner for (int i = 0; i < devices.Length; i++) { IBaseFilter tmp; Log.Log.WriteFile("analog: AddTvAudioFilter try:{0} {1}", devices[i].Name, i); //if tv audio tuner is currently in use we can skip it if (DevicesInUse.Instance.IsUsed(devices[i])) continue; int hr; try { //add tv audio tuner to graph hr = graphBuilder.AddSourceFilterForMoniker(devices[i].Mon, null, devices[i].Name, out tmp); } catch (Exception) { Log.Log.WriteFile("analog: cannot add filter to graph"); continue; } if (hr != 0) { //failed to add tv audio tuner to graph, continue with the next one if (tmp != null) { graphBuilder.RemoveFilter(tmp); Release.ComObject("tvAudioFilter filter", tmp); } continue; } // try connecting the tv tuner-> tv audio tuner if (FilterGraphTools.ConnectPin(graphBuilder, tuner.AudioPin, tmp, 0)) { // Got it ! // Connect tv audio tuner to the crossbar IPin pin = DsFindPin.ByDirection(tmp, PinDirection.Output, 0); hr = graphBuilder.Connect(pin, crossbar.AudioTunerIn); if (hr < 0) { //failed graphBuilder.RemoveFilter(tmp); Release.ComObject("audiotuner pinin", pin); Release.ComObject("audiotuner filter", tmp); } else { //succeeded. we're done Log.Log.WriteFile("analog: AddTvAudioFilter succeeded:{0}", devices[i].Name); Release.ComObject("audiotuner pinin", pin); _filterTvAudioTuner = tmp; _audioDevice = devices[i]; DevicesInUse.Instance.Add(_audioDevice); _tvAudioTunerInterface = tuner.Filter as IAMTVAudio; break; } } else { // cannot connect tv tuner-> tv audio tuner, try next one... graphBuilder.RemoveFilter(tmp); Release.ComObject("audiotuner filter", tmp); } } } if (_filterTvAudioTuner == null) { Log.Log.WriteFile("analog: AddTvAudioFilter no tv audio devices found - Trying TvTuner filter"); int hr = graphBuilder.Connect(tuner.AudioPin, crossbar.AudioTunerIn); if (hr != 0) { Log.Log.Error("analog: unable to add TvAudioTuner to graph - even TvTuner as TvAudio fails"); mode = TvAudioVariant.Unavailable; } else { Log.Log.WriteFile("analog: AddTvAudioFilter connected TvTuner with Crossbar directly succeeded!"); mode = TvAudioVariant.TvTunerConnection; _tvAudioTunerInterface = tuner.Filter as IAMTVAudio; if (_tvAudioTunerInterface != null) { Log.Log.WriteFile("analog: AddTvAudioFilter succeeded - TvTuner is also TvAudio"); _filterTvAudioTuner = tuner.Filter; mode = TvAudioVariant.TvTuner; } } graph.TvAudio.Mode = mode; } else { mode = TvAudioVariant.Normal; graph.TvAudio.Name = _audioDevice.Name; } if (mode != TvAudioVariant.Unavailable && mode != TvAudioVariant.TvTunerConnection && _tvAudioTunerInterface != null) { CheckCapabilities(graph); } return true; }
/// <summary> /// Adds a mpeg2 demultiplexer to the graph /// </summary> /// <param name="_graphBuilder">The graph builder</param> private void AddMpeg2Demultiplexer(IFilterGraph2 _graphBuilder) { Log.Log.WriteFile("analog: AddMpeg2Demultiplexer"); if (_filterMpeg2Demux != null) return; if (_pinCapture == null) return; _filterMpeg2Demux = (IBaseFilter)new MPEG2Demultiplexer(); int hr = _graphBuilder.AddFilter(_filterMpeg2Demux, "MPEG2 Demultiplexer"); if (hr != 0) { Log.Log.WriteFile("analog: AddMPEG2DemuxFilter returns:0x{0:X}", hr); throw new TvException("Unable to add MPEG2 demultiplexer"); } Log.Log.WriteFile("analog: connect capture->mpeg2 demux"); IPin pin = DsFindPin.ByDirection(_filterMpeg2Demux, PinDirection.Input, 0); hr = _graphBuilder.Connect(_pinCapture, pin); if (hr != 0) { Log.Log.WriteFile("analog: ConnectFilters returns:0x{0:X}", hr); throw new TvException("Unable to connect capture-> MPEG2 demultiplexer"); } IMpeg2Demultiplexer demuxer = (IMpeg2Demultiplexer)_filterMpeg2Demux; demuxer.CreateOutputPin(FilterGraphTools.GetVideoMpg2Media(), "Video", out _pinVideo); demuxer.CreateOutputPin(FilterGraphTools.GetAudioMpg2Media(), "Audio", out _pinAudio); demuxer.CreateOutputPin(FilterGraphTools.GetAudioLPCMMedia(), "LPCM", out _pinLPCM); IMPEG2StreamIdMap map = (IMPEG2StreamIdMap)_pinVideo; map.MapStreamId(224, MPEG2Program.ElementaryStream, 0, 0); map = (IMPEG2StreamIdMap)_pinAudio; map.MapStreamId(0xC0, MPEG2Program.ElementaryStream, 0, 0); map = (IMPEG2StreamIdMap)_pinLPCM; map.MapStreamId(0xBD, MPEG2Program.ElementaryStream, 0xA0, 7); }
/// <summary> /// Adds the InterVideo muxer and connects the compressor to it. /// This is the preferred muxer for Plextor cards and others. /// It will be used if the InterVideo Audio Encoder is used also. /// </summary> /// <param name="_graphBuilder">GraphBuilder</param> /// <param name="_capture">Capture</param> /// <returns></returns> private bool AddInterVideoMuxer(IFilterGraph2 _graphBuilder, Capture _capture) { IPin pinOut; Log.Log.Info("analog: using intervideo muxer"); string muxVideoIn = "video compressor"; const string monikerInterVideoMuxer = @"@device:sw:{083863F1-70DE-11D0-BD40-00A0C911CE86}\{317DDB63-870E-11D3-9C32-00104B3801F7}"; _filterAnalogMpegMuxer = Marshal.BindToMoniker(monikerInterVideoMuxer) as IBaseFilter; int hr = _graphBuilder.AddFilter(_filterAnalogMpegMuxer, "InterVideo MPEG Muxer"); if (hr != 0) { Log.Log.WriteFile("analog: add intervideo muxer returns:0x{0:X}", hr); throw new TvException("Unable to add InterVideo Muxer"); } Log.Log.Info("analog: add intervideo muxer successful"); // next connect video compressor->muxer if (_isPlextorConvertX) { muxVideoIn = "Plextor ConvertX"; //no video compressor needed with the Plextor device so we use the first capture pin pinOut = DsFindPin.ByDirection(_capture.VideoFilter, PinDirection.Output, 0); } else { pinOut = DsFindPin.ByDirection(_filterVideoCompressor, PinDirection.Output, 0); } IPin pinIn = DsFindPin.ByDirection(_filterAnalogMpegMuxer, PinDirection.Input, 0); if (pinOut == null) { Log.Log.Info("analog: no output pin found on {0}", muxVideoIn); throw new TvException("no output pin found on video out"); } if (pinIn == null) { Log.Log.Info("analog: no input pin found on intervideo muxer"); throw new TvException("no input pin found on intervideo muxer"); } hr = _graphBuilder.Connect(pinOut, pinIn); if (hr != 0) { Log.Log.WriteFile("analog: unable to connect {0}-> intervideo muxer returns:0x{1:X}", muxVideoIn, hr); throw new TvException("Unable to add unable to connect to video in on intervideo muxer"); } Log.Log.WriteFile("analog: connected video -> intervideo muxer"); // next connect audio compressor->muxer pinOut = DsFindPin.ByDirection(_filterAudioCompressor, PinDirection.Output, 0); pinIn = DsFindPin.ByDirection(_filterAnalogMpegMuxer, PinDirection.Input, 1); if (pinOut == null) { Log.Log.Info("analog: no output pin found on audio compressor"); throw new TvException("no output pin found on audio compressor"); } if (pinIn == null) { Log.Log.Info("analog: no input pin found on intervideo muxer"); throw new TvException("no input pin found on intervideo muxer"); } hr = _graphBuilder.Connect(pinOut, pinIn); if (hr != 0) { Log.Log.WriteFile("analog:unable to connect audio compressor->intervideo muxer returns:0x{0:X}", hr); throw new TvException("Unable to add unable to connect audio compressor->intervideo muxer"); } Log.Log.WriteFile("analog: connected audio -> intervideo muxer"); //and finally we have a capture pin... _pinCapture = DsFindPin.ByDirection(_filterAnalogMpegMuxer, PinDirection.Output, 0); if (_pinCapture == null) { Log.Log.WriteFile("analog:unable find capture pin"); throw new TvException("unable find capture pin"); } return true; }
/// <summary> /// Adds the mpeg muxer /// </summary> /// <param name="_graphBuilder">GraphBuilder</param> /// <returns></returns> private bool AddAnalogMuxer(IFilterGraph2 _graphBuilder) { Log.Log.Info("analog:AddAnalogMuxer"); const string monikerPowerDirectorMuxer = @"@device:sw:{083863F1-70DE-11D0-BD40-00A0C911CE86}\{7F2BBEAF-E11C-4D39-90E8-938FB5A86045}"; _filterAnalogMpegMuxer = Marshal.BindToMoniker(monikerPowerDirectorMuxer) as IBaseFilter; int hr = _graphBuilder.AddFilter(_filterAnalogMpegMuxer, "Analog MPEG Muxer"); if (hr != 0) { Log.Log.WriteFile("analog:AddAnalogMuxer returns:0x{0:X}", hr); throw new TvException("Unable to add AddAnalogMuxer"); } // next connect audio compressor->muxer IPin pinOut = DsFindPin.ByDirection(_filterAudioCompressor, PinDirection.Output, 0); IPin pinIn = DsFindPin.ByDirection(_filterAnalogMpegMuxer, PinDirection.Input, 1); if (pinOut == null) { Log.Log.Info("analog:no output pin found on audio compressor"); throw new TvException("no output pin found on audio compressor"); } if (pinIn == null) { Log.Log.Info("analog:no input pin found on analog muxer"); throw new TvException("no input pin found on muxer"); } hr = _graphBuilder.Connect(pinOut, pinIn); if (hr != 0) { Log.Log.WriteFile("analog:unable to connect audio compressor->muxer returns:0x{0:X}", hr); throw new TvException("Unable to add unable to connect audio compressor->muxer"); } Log.Log.WriteFile("analog: connected audio -> muxer"); // next connect video compressor->muxer pinOut = DsFindPin.ByDirection(_filterVideoCompressor, PinDirection.Output, 0); pinIn = DsFindPin.ByDirection(_filterAnalogMpegMuxer, PinDirection.Input, 0); if (pinOut == null) { Log.Log.Info("analog:no output pin found on video compressor"); throw new TvException("no output pin found on video compressor"); } if (pinIn == null) { Log.Log.Info("analog:no input pin found on analog muxer"); throw new TvException("no input pin found on muxer"); } hr = _graphBuilder.Connect(pinOut, pinIn); if (hr != 0) { Log.Log.WriteFile("analog:unable to connect video compressor->muxer returns:0x{0:X}", hr); throw new TvException("Unable to add unable to connect video compressor->muxer"); } //and finally we have a capture pin... Log.Log.WriteFile("analog: connected video -> muxer"); _pinCapture = DsFindPin.ByDirection(_filterAnalogMpegMuxer, PinDirection.Output, 0); if (_pinCapture == null) { Log.Log.WriteFile("analog:unable find capture pin"); throw new TvException("unable find capture pin"); } return true; }
/// <summary> /// Adds the video compressor. /// </summary> /// <param name="_graphBuilder">GraphBuilder</param> /// <returns></returns> private bool AddVideoCompressor(IFilterGraph2 _graphBuilder) { Log.Log.WriteFile("analog: AddVideoCompressor"); DsDevice[] devices1 = DsDevice.GetDevicesOfCat(FilterCategory.VideoCompressorCategory); DsDevice[] devices2 = DsDevice.GetDevicesOfCat(FilterCategory.LegacyAmFilterCategory); IList<SoftwareEncoder> videoEncoders = _layer.GetSofwareEncodersVideo(); DsDevice[] videoDevices = new DsDevice[videoEncoders.Count]; for (int x = 0; x < videoEncoders.Count; ++x) { videoDevices[x] = null; } for (int i = 0; i < devices1.Length; i++) { for (int x = 0; x < videoEncoders.Count; ++x) { if (videoEncoders[x].Name == devices1[i].Name) { videoDevices[x] = devices1[i]; break; } } } for (int i = 0; i < devices2.Length; i++) { for (int x = 0; x < videoEncoders.Count; ++x) { if (videoEncoders[x].Name == devices2[i].Name) { videoDevices[x] = devices2[i]; break; } } } //for each compressor Log.Log.WriteFile("analog: AddVideoCompressor found:{0} compressor", videoDevices.Length); for (int i = 0; i < videoDevices.Length; i++) { IBaseFilter tmp; if (videoDevices[i] == null || !EncodersInUse.Instance.Add(videoDevices[i], videoEncoders[i])) { continue; } Log.Log.WriteFile("analog: try compressor:{0}", videoDevices[i].Name); int hr; try { //add compressor filter to graph hr = _graphBuilder.AddSourceFilterForMoniker(videoDevices[i].Mon, null, videoDevices[i].Name, out tmp); } catch (Exception) { Log.Log.WriteFile("analog: cannot add compressor to graph"); EncodersInUse.Instance.Remove(videoDevices[i]); continue; } if (hr != 0) { //failed to add filter to graph, continue with the next one if (tmp != null) { _graphBuilder.RemoveFilter(tmp); Release.ComObject("videocompressor", tmp); } EncodersInUse.Instance.Remove(videoDevices[i]); continue; } if (tmp == null) { EncodersInUse.Instance.Remove(videoDevices[i]); continue; } // check if this compressor filter has an mpeg audio output pin Log.Log.WriteFile("analog: connect video pin->video compressor"); IPin pinVideo = DsFindPin.ByDirection(tmp, PinDirection.Input, 0); // we found a nice compressor, lets try to connect the analog video pin to the compressor hr = _graphBuilder.Connect(_pinAnalogVideo, pinVideo); if (hr != 0) { Log.Log.WriteFile("analog: failed to connect video pin->video compressor"); //unable to connec the pin, remove it and continue with next compressor _graphBuilder.RemoveFilter(tmp); Release.ComObject("videocompressor", tmp); EncodersInUse.Instance.Remove(videoDevices[i]); continue; } //succeeded. _videoCompressorDevice = videoDevices[i]; _filterVideoCompressor = tmp; return true; } return false; }
internal override Bitmap TakePicture() { if (m_callbackCompleted != null) { return(null); } // m_pictureControl = pictureControl; m_takePictureEnd = false; DsDevice cameraDevice = DsDevice.GetDevicesOfCat(FilterCategory.VideoInputDevice)[m_cameraDeviceIndex]; IFilterGraph2 filterGraph = null; IBaseFilter cam = null; IPin camCapture = null; // cam ISampleGrabber sg = null; IPin sgIn = null; // samplegrabber try { // setup filterGraph & connect camera filterGraph = (IFilterGraph2) new FilterGraph(); DsError.ThrowExceptionForHR(filterGraph.AddSourceFilterForMoniker(cameraDevice.Mon, null, cameraDevice.Name, out cam)); // setup smarttee and connect so that cam(PinCategory.Capture)->st(PinDirection.Input) camCapture = DsFindPin.ByCategory(cam, PinCategory.Capture, 0); // output ConfStreamDimensions((IAMStreamConfig)camCapture); // connect Camera output to SampleGrabber input sg = (ISampleGrabber) new SampleGrabber(); // configure AMMediaType media = new AMMediaType(); try { media.majorType = MediaType.Video; media.subType = BPP2MediaSubtype(m_configuration.BPP); // this will ask samplegrabber to do convertions for us media.formatType = FormatType.VideoInfo; DsError.ThrowExceptionForHR(sg.SetMediaType(media)); } finally { DsUtils.FreeAMMediaType(media); media = null; } DsError.ThrowExceptionForHR(sg.SetCallback(this, 1)); // 1 = BufferCB DsError.ThrowExceptionForHR(filterGraph.AddFilter((IBaseFilter)sg, "SG")); sgIn = DsFindPin.ByDirection((IBaseFilter)sg, PinDirection.Input, 0); // input DsError.ThrowExceptionForHR(filterGraph.Connect(camCapture, sgIn)); GetSizeInfo(sg); // wait until timeout - or picture has been taken if (m_callbackCompleted == null) { m_callbackCompleted = new ManualResetEvent(false); // start filter DsError.ThrowExceptionForHR(((IMediaControl)filterGraph).Run()); m_callbackState = 5; //if (m_pictureControl != null) //{ // m_callbackCompleted.WaitOne(); //} //else //{ if (!m_callbackCompleted.WaitOne(15000, false)) { throw new Exception(); //"Timeout while waiting for Picture"); } //} return(m_capturedBitmap); } else { return(null); } } finally { // release allocated objects if (m_callbackCompleted != null) { m_callbackCompleted.Close(); m_callbackCompleted = null; } if (sgIn != null) { Marshal.ReleaseComObject(sgIn); sgIn = null; } if (sg != null) { Marshal.ReleaseComObject(sg); sg = null; } if (camCapture != null) { Marshal.ReleaseComObject(camCapture); camCapture = null; } if (cam != null) { Marshal.ReleaseComObject(cam); cam = null; } if (filterGraph != null) { try { ((IMediaControl)filterGraph).Stop(); } catch (Exception) { } Marshal.ReleaseComObject(filterGraph); filterGraph = null; } m_capturedBitmap = null; m_callbackCompleted = null; } }
/// <summary> /// Start using the camera /// </summary> /// <returns>Indicate if the webcam was able to start</returns> public bool Start() { if (!started) { DsDevice[] devices = GetDevices(); if (devices.Length > 0) { DsDevice dev = devices[0]; // Initialize camera int hr; IBaseFilter capFilter = null; ISampleGrabber sampGrabber = null; IPin pCaptureOut = null; IPin pSampleIn = null; IPin pRenderIn = null; m_FilterGraph = new FilterGraph() as IFilterGraph2; try { hr = m_FilterGraph.AddSourceFilterForMoniker(dev.Mon, null, dev.Name, out capFilter); if (m_pinStill == null) { m_pinStill = DsFindPin.ByCategory(capFilter, PinCategory.Preview, 0); } // Still haven't found one. Need to put a splitter in so we have // one stream to capture the bitmap from, and one to display. Ok, we // don't *have* to do it that way, but we are going to anyway. if (m_pinStill == null) { IPin pRaw = null; IPin pSmart = null; // There is no still pin m_VidControl = null; // Add a splitter IBaseFilter iSmartTee = (IBaseFilter) new SmartTee(); try { hr = m_FilterGraph.AddFilter(iSmartTee, "SmartTee"); DsError.ThrowExceptionForHR(hr); // Find the find the capture pin from the video device and the // input pin for the splitter, and connnect them pRaw = DsFindPin.ByCategory(capFilter, PinCategory.Capture, 0); pSmart = DsFindPin.ByDirection(iSmartTee, PinDirection.Input, 0); hr = m_FilterGraph.Connect(pRaw, pSmart); DsError.ThrowExceptionForHR(hr); // Now set the capture and still pins (from the splitter) m_pinStill = DsFindPin.ByName(iSmartTee, "Preview"); pCaptureOut = DsFindPin.ByName(iSmartTee, "Capture"); // If any of the default config items are set, perform the config // on the actual video device (rather than the splitter) if (captureHeight + captureWidth > 0) { SetConfigParms(pRaw, captureWidth, captureHeight, 24); } } finally { if (pRaw != null) { Marshal.ReleaseComObject(pRaw); } if (pRaw != pSmart) { Marshal.ReleaseComObject(pSmart); } if (pRaw != iSmartTee) { Marshal.ReleaseComObject(iSmartTee); } } } else { // Get a control pointer (used in Click()) m_VidControl = capFilter as IAMVideoControl; pCaptureOut = DsFindPin.ByCategory(capFilter, PinCategory.Capture, 0); // If any of the default config items are set if (captureHeight + captureWidth > 0) { SetConfigParms(m_pinStill, captureWidth, captureHeight, 24); } } // Get the SampleGrabber interface sampGrabber = new SampleGrabber() as ISampleGrabber; // Configure the sample grabber IBaseFilter baseGrabFlt = sampGrabber as IBaseFilter; ConfigureSampleGrabber(sampGrabber); pSampleIn = DsFindPin.ByDirection(baseGrabFlt, PinDirection.Input, 0); // Get the default video renderer IBaseFilter pRenderer = new VideoRendererDefault() as IBaseFilter; hr = m_FilterGraph.AddFilter(pRenderer, "Renderer"); DsError.ThrowExceptionForHR(hr); pRenderIn = DsFindPin.ByDirection(pRenderer, PinDirection.Input, 0); // Add the sample grabber to the graph hr = m_FilterGraph.AddFilter(baseGrabFlt, "Ds.NET Grabber"); DsError.ThrowExceptionForHR(hr); if (m_VidControl == null) { // Connect the Still pin to the sample grabber hr = m_FilterGraph.Connect(m_pinStill, pSampleIn); DsError.ThrowExceptionForHR(hr); // Connect the capture pin to the renderer hr = m_FilterGraph.Connect(pCaptureOut, pRenderIn); DsError.ThrowExceptionForHR(hr); } else { // Connect the capture pin to the renderer hr = m_FilterGraph.Connect(pCaptureOut, pRenderIn); DsError.ThrowExceptionForHR(hr); // Connect the Still pin to the sample grabber hr = m_FilterGraph.Connect(m_pinStill, pSampleIn); DsError.ThrowExceptionForHR(hr); } SaveSizeInfo(sampGrabber); ConfigVideoWindow(pictureBox); IMediaControl mediaCtrl = m_FilterGraph as IMediaControl; hr = mediaCtrl.Run(); DsError.ThrowExceptionForHR(hr); } finally { if (sampGrabber != null) { Marshal.ReleaseComObject(sampGrabber); sampGrabber = null; } if (pCaptureOut != null) { Marshal.ReleaseComObject(pCaptureOut); pCaptureOut = null; } if (pRenderIn != null) { Marshal.ReleaseComObject(pRenderIn); pRenderIn = null; } if (pSampleIn != null) { Marshal.ReleaseComObject(pSampleIn); pSampleIn = null; } } m_PictureReady = new ManualResetEvent(false); timer.Interval = (int)(1000 / framesPerSecond); timer.Start(); return(true); } } else { return(true); } return(false); }
/// <summary> /// Connect all mdapifilters between [inftee main] and [TIF MPEG2 Demultiplexer] /// </summary> public void Connectmdapifilter(IFilterGraph2 graphBuilder, ref IBaseFilter lastFilter) { MDPlug[] _mDPlugs = getPlugins(); int iplg; int hr; string filtername; //capture -> maintee -> mdapi(n)-> secondtee -> demux for (iplg = 0; iplg < _instanceNumber; iplg++) { filtername = "mdapifilter" + iplg; Log.Log.Info("mdplugs: add {0}", filtername); hr = graphBuilder.AddFilter(_mDPlugs[iplg].mdapiFilter, filtername); if (hr != 0) { Log.Log.Error("mdplugs:Add {0} returns:0x{1:X}", filtername, hr); throw new TvException("Unable to add " + filtername); } } iplg = 0; filtername = "mdapifilter" + iplg; Log.Log.Info("mdplugs: connect lastFilter->{0}", filtername); IPin mainTeeOut = DsFindPin.ByDirection(lastFilter, PinDirection.Output, 0); IPin mdApiInFirst = DsFindPin.ByDirection(_mDPlugs[iplg].mdapiFilter, PinDirection.Input, 0); hr = graphBuilder.Connect(mainTeeOut, mdApiInFirst); Release.ComObject("lastFilter pin0", mainTeeOut); Release.ComObject("mdapifilter0 pinin", mdApiInFirst); if (hr != 0) { Log.Log.Info("unable to connect lastFilter->{0}", filtername); } if (_instanceNumber > 1) { for (iplg = 0; iplg < _instanceNumber - 1; iplg++) { Log.Log.Info("mdplugs: connect mdapifilter{0}->mdapifilter{1}", iplg, iplg + 1); IPin mdApiOutPrev = DsFindPin.ByDirection(_mDPlugs[iplg].mdapiFilter, PinDirection.Output, 0); IPin mdApiInNext = DsFindPin.ByDirection(_mDPlugs[iplg + 1].mdapiFilter, PinDirection.Input, 0); hr = graphBuilder.Connect(mdApiOutPrev, mdApiInNext); Release.ComObject("mdApiPrev pinout", mdApiOutPrev); Release.ComObject("mdApiNext pinin", mdApiInNext); if (hr != 0) { Log.Log.Info("unable to connect mdapifilter{0}->mdapifilter{1]", iplg, iplg + 1); } } } filtername = "mdapifilter" + iplg; Log.Log.Info("mdplugs: Setting last filter to {0}", filtername); lastFilter = _mDPlugs[iplg].mdapiFilter; }
/// <summary> build the capture graph for grabber. </summary> private void SetupGraph(DsDevice dev, int iWidth, int iHeight, short iBPP) { ISampleGrabber sampGrabber = null; IPin pCaptureOut = null; IPin pRenderIn = null; // Get the graphbuilder object m_FilterGraph = (IFilterGraph2)new FilterGraph(); try { // add the video input device IBaseFilter capFilter; int hr = m_FilterGraph.AddSourceFilterForMoniker(dev.Mon, null, dev.Name, out capFilter); DsError.ThrowExceptionForHR(hr); //if (iHeight + iWidth + iBPP > 0) //{ //SetConfigParms(pRaw, iWidth, iHeight, iBPP); //} pCaptureOut = DsFindPin.ByCategory(capFilter, PinCategory.Capture, 0); // Get the SampleGrabber interface sampGrabber = new SampleGrabber() as ISampleGrabber; // Configure the sample grabber IBaseFilter baseGrabFlt = sampGrabber as IBaseFilter; ConfigureSampleGrabber(sampGrabber); // Add the sample grabber to the graph hr = m_FilterGraph.AddFilter(baseGrabFlt, "Ares Video Grabber"); DsError.ThrowExceptionForHR(hr); pRenderIn = DsFindPin.ByDirection(baseGrabFlt, PinDirection.Input, 0); // Connect the capture pin to the renderer hr = m_FilterGraph.Connect(pCaptureOut, pRenderIn); DsError.ThrowExceptionForHR(hr); // Learn the video properties SaveSizeInfo(sampGrabber); // Start the graph IMediaControl mediaCtrl = (IMediaControl)m_FilterGraph; hr = mediaCtrl.Run(); DsError.ThrowExceptionForHR(hr); } finally { if (sampGrabber != null) { Marshal.ReleaseComObject(sampGrabber); } if (pCaptureOut != null) { Marshal.ReleaseComObject(pCaptureOut); } if (pRenderIn != null) { Marshal.ReleaseComObject(pRenderIn); } } }
/// <summary>; /// Starts grabbing images from the capture device /// </summary> public virtual void Start() { if (_captureTask != null) { Stop(); } _captureTask = new Task(() => { // Create new grabber _capGrabber = new CapGrabber(); _capGrabber.PropertyChanged += capGrabber_PropertyChanged; _capGrabber.NewFrameArrived += capGrabber_NewFrameArrived; _stopSignal = new ManualResetEvent(false); _graph = Activator.CreateInstance(Type.GetTypeFromCLSID(FilterGraph)) as IFilterGraph2; _sourceObject = FilterInfo.CreateFilter(_monikerString); var outputPin = _sourceObject.GetPin(PinCategory.Capture, 0); SelectWebcamResolution(outputPin); _grabber = Activator.CreateInstance(Type.GetTypeFromCLSID(SampleGrabber)) as ISampleGrabber; _grabberObject = _grabber as IBaseFilter; if (_graph == null) { return; } ; _graph.AddFilter(_sourceObject, "source"); _graph.AddFilter(_grabberObject, "grabber"); using (var mediaType = new AMMediaType()) { mediaType.MajorType = MediaTypes.Video; mediaType.SubType = MediaSubTypes.RGB32; if (_grabber != null) { _grabber.SetMediaType(mediaType); var inputPin = _grabberObject.GetPin(PinDirection.Input, 0); if (_graph.Connect(outputPin, inputPin) >= 0) { if (_grabber.GetConnectedMediaType(mediaType) == 0) { var header = (VideoInfoHeader)Marshal.PtrToStructure(mediaType.FormatPtr, typeof(VideoInfoHeader)); _capGrabber.Width = header.BmiHeader.Width; _capGrabber.Height = header.BmiHeader.Height; } } _graph.Render(_grabberObject.GetPin(PinDirection.Output, 0)); _grabber.SetBufferSamples(false); _grabber.SetOneShot(false); _grabber.SetCallback(_capGrabber, 1); } // Get the video window var wnd = (IVideoWindow)_graph; wnd.put_AutoShow(false); // Create the control and run _control = (IMediaControl)_graph; _control.Run(); // Wait for the stop signal _stopSignal.WaitOne(); Cleanup(); } }); _captureTask.Start(); }
/// <summary> /// This method tries to connect a encoder filter to the capture filter /// See the remarks in AddTvEncoderFilter() for the possible options /// </summary> /// <param name="filterEncoder">The filter encoder.</param> /// <param name="isVideo">if set to <c>true</c> the filterEncoder is used for video.</param> /// <param name="isAudio">if set to <c>true</c> the filterEncoder is used for audio.</param> /// <param name="matchPinNames">if set to <c>true</c> the pin names of the encoder filter should match the pin names of the capture filter.</param> /// <param name="_graphBuilder">GraphBuilder</param> /// <param name="_capture">Capture</param> /// <returns> /// true if encoder is connected correctly, otherwise false /// </returns> private static bool ConnectEncoderFilter(IBaseFilter filterEncoder, bool isVideo, bool isAudio, bool matchPinNames, IFilterGraph2 _graphBuilder, Capture _capture) { Log.Log.WriteFile("analog: ConnectEncoderFilter video:{0} audio:{1}", isVideo, isAudio); //find the inputs of the encoder. could be 1 or 2 inputs. IPin pinInput1 = DsFindPin.ByDirection(filterEncoder, PinDirection.Input, 0); IPin pinInput2 = DsFindPin.ByDirection(filterEncoder, PinDirection.Input, 1); //log input pins if (pinInput1 != null) Log.Log.WriteFile("analog: found pin#0 {0}", FilterGraphTools.LogPinInfo(pinInput1)); if (pinInput2 != null) Log.Log.WriteFile("analog: found pin#1 {0}", FilterGraphTools.LogPinInfo(pinInput2)); string pinName1 = FilterGraphTools.GetPinName(pinInput1); string pinName2 = FilterGraphTools.GetPinName(pinInput2); int pinsConnected = 0; int pinsAvailable = 0; IPin[] pins = new IPin[20]; IEnumPins enumPins = null; try { // for each output pin of the capture device _capture.VideoFilter.EnumPins(out enumPins); enumPins.Next(20, pins, out pinsAvailable); Log.Log.WriteFile("analog: pinsAvailable on capture filter:{0}", pinsAvailable); for (int i = 0; i < pinsAvailable; ++i) { int hr; // check if this is an output pin PinDirection pinDir; pins[i].QueryDirection(out pinDir); if (pinDir == PinDirection.Input) continue; //log the pin info... Log.Log.WriteFile("analog: capture pin:{0} {1}", i, FilterGraphTools.LogPinInfo(pins[i])); string pinName = FilterGraphTools.GetPinName(pins[i]); // first lets try to connect this output pin of the capture filter to the 1st input pin // of the encoder // only try to connect when pin name matching is turned off // or when the pin names are the same if (matchPinNames == false || (String.Compare(pinName, pinName1, true) == 0)) { //try to connect the output pin of the capture filter to the first input pin of the encoder hr = _graphBuilder.Connect(pins[i], pinInput1); if (hr == 0) { //succeeded! Log.Log.WriteFile("analog: connected pin:{0} {1} with pin0", i, pinName); pinsConnected++; } //check if all pins are connected if (pinsConnected == 1 && (isAudio == false || isVideo == false)) { //yes, then we are done Log.Log.WriteFile("analog: ConnectEncoderFilter succeeded"); return true; } } // next lets try to connect this output pin of the capture filter to the 2nd input pin // of the encoder // only try to connect when pin name matching is turned off // or when the pin names are the same if (matchPinNames == false || (String.Compare(pinName, pinName2, true) == 0)) { //try to connect the output pin of the capture filter to the 2nd input pin of the encoder hr = _graphBuilder.Connect(pins[i], pinInput2); if (hr == 0) { //succeeded! Log.Log.WriteFile("analog: connected pin:{0} {1} with pin1", i, pinName); pinsConnected++; } //check if all pins are connected if (pinsConnected == 2) { //yes, then we are done Log.Log.WriteFile("analog: ConnectEncoderFilter succeeded"); return true; } //Log.Log.WriteFile("analog: ConnectEncoderFilter to Capture {0} failed", pinName2); } } } finally { if (enumPins != null) Release.ComObject("ienumpins", enumPins); if (pinInput1 != null) Release.ComObject("encoder pin0", pinInput1); if (pinInput2 != null) Release.ComObject("encoder pin1", pinInput2); for (int i = 0; i < pinsAvailable; ++i) { if (pins[i] != null) Release.ComObject("capture pin" + i, pins[i]); } } Log.Log.Write("analog: ConnectEncoderFilter failed (matchPinNames:{0})", matchPinNames); return false; }
/// <summary> /// Creates the filter by trying to detect it /// </summary> /// <param name="crossbar">The crossbar componen</param> /// <param name="tuner">The tuner component</param> /// <param name="graph">The stored graph</param> /// <param name="graphBuilder">The graphBuilder</param> /// <returns>true, if the graph building was successful</returns> private bool CreateAutomaticFilterInstance(Graph graph, Tuner tuner, Crossbar crossbar, IFilterGraph2 graphBuilder) { //get all tv audio tuner devices on this system DsDevice[] devices = null; try { devices = DsDevice.GetDevicesOfCat(FilterCategory.AMKSTVAudio); devices = DeviceSorter.Sort(devices, tuner.TunerName, crossbar.CrossBarName); } catch (Exception) { Log.Log.WriteFile("analog: AddTvAudioFilter no tv audio devices found - Trying TvTuner filter"); } if (devices != null && devices.Length > 0) { // try each tv audio tuner for (int i = 0; i < devices.Length; i++) { IBaseFilter tmp; Log.Log.WriteFile("analog: AddTvAudioFilter try:{0} {1}", devices[i].Name, i); //if tv audio tuner is currently in use we can skip it if (DevicesInUse.Instance.IsUsed(devices[i])) { continue; } int hr; try { //add tv audio tuner to graph hr = graphBuilder.AddSourceFilterForMoniker(devices[i].Mon, null, devices[i].Name, out tmp); } catch (Exception) { Log.Log.WriteFile("analog: cannot add filter to graph"); continue; } if (hr != 0) { //failed to add tv audio tuner to graph, continue with the next one if (tmp != null) { graphBuilder.RemoveFilter(tmp); Release.ComObject("tvAudioFilter filter", tmp); } continue; } // try connecting the tv tuner-> tv audio tuner if (FilterGraphTools.ConnectPin(graphBuilder, tuner.AudioPin, tmp, 0)) { // Got it ! // Connect tv audio tuner to the crossbar IPin pin = DsFindPin.ByDirection(tmp, PinDirection.Output, 0); hr = graphBuilder.Connect(pin, crossbar.AudioTunerIn); if (hr < 0) { //failed graphBuilder.RemoveFilter(tmp); Release.ComObject("audiotuner pinin", pin); Release.ComObject("audiotuner filter", tmp); } else { //succeeded. we're done Log.Log.WriteFile("analog: AddTvAudioFilter succeeded:{0}", devices[i].Name); Release.ComObject("audiotuner pinin", pin); _filterTvAudioTuner = tmp; _audioDevice = devices[i]; DevicesInUse.Instance.Add(_audioDevice); _tvAudioTunerInterface = tuner.Filter as IAMTVAudio; break; } } else { // cannot connect tv tuner-> tv audio tuner, try next one... graphBuilder.RemoveFilter(tmp); Release.ComObject("audiotuner filter", tmp); } } } if (_filterTvAudioTuner == null) { Log.Log.WriteFile("analog: AddTvAudioFilter no tv audio devices found - Trying TvTuner filter"); int hr = graphBuilder.Connect(tuner.AudioPin, crossbar.AudioTunerIn); if (hr != 0) { Log.Log.Error("analog: unable to add TvAudioTuner to graph - even TvTuner as TvAudio fails"); mode = TvAudioVariant.Unavailable; } else { Log.Log.WriteFile("analog: AddTvAudioFilter connected TvTuner with Crossbar directly succeeded!"); mode = TvAudioVariant.TvTunerConnection; _tvAudioTunerInterface = tuner.Filter as IAMTVAudio; if (_tvAudioTunerInterface != null) { Log.Log.WriteFile("analog: AddTvAudioFilter succeeded - TvTuner is also TvAudio"); _filterTvAudioTuner = tuner.Filter; mode = TvAudioVariant.TvTuner; } } graph.TvAudio.Mode = mode; } else { mode = TvAudioVariant.Normal; graph.TvAudio.Name = _audioDevice.Name; } if (mode != TvAudioVariant.Unavailable && mode != TvAudioVariant.TvTunerConnection && _tvAudioTunerInterface != null) { CheckCapabilities(graph); } return(true); }
/// <summary> /// This method tries to connect a multiplexer filter to the encoder filters (or capture filter) /// See the remarks in AddTvMultiPlexer() for the possible options /// </summary> /// <param name="filterMultiPlexer">The multiplexer.</param> /// <param name="matchPinNames">if set to <c>true</c> the pin names of the multiplexer filter should match the pin names of the encoder filter.</param> /// <param name="_graphBuilder">GraphBuilder</param> /// <param name="_tuner">Tuner</param> /// <param name="_capture">Capture</param> /// <returns>true if multiplexer is connected correctly, otherwise false</returns> private bool ConnectMultiplexer(IBaseFilter filterMultiPlexer, bool matchPinNames, IFilterGraph2 _graphBuilder, Tuner _tuner, Capture _capture) { //Log.Log.WriteFile("analog: ConnectMultiplexer()"); // get the input pins of the multiplexer filter (can be 1 or 2 input pins) IPin pinInput1 = DsFindPin.ByDirection(filterMultiPlexer, PinDirection.Input, 0); IPin pinInput2 = DsFindPin.ByDirection(filterMultiPlexer, PinDirection.Input, 1); //log the info for each input pin if (pinInput1 != null) Log.Log.WriteFile("analog: found pin#0 {0}", FilterGraphTools.LogPinInfo(pinInput1)); if (pinInput2 != null) Log.Log.WriteFile("analog: found pin#1 {0}", FilterGraphTools.LogPinInfo(pinInput2)); string pinName1 = FilterGraphTools.GetPinName(pinInput1); string pinName2 = FilterGraphTools.GetPinName(pinInput2); try { if (_filterAudioEncoder != null) Log.Log.WriteFile("analog: AudioEncoder available"); if (_filterVideoEncoder != null) Log.Log.WriteFile("analog: VideoEncoder available"); int pinsConnectedOnMultiplexer = 0; // if we have no encoder filters, the multiplexer should be connected directly to the capture filter if (_filterAudioEncoder == null || _filterVideoEncoder == null) { Log.Log.WriteFile("analog: ConnectMultiplexer to capture filter"); //option 1, connect the multiplexer to the capture filter int pinsConnected = 0; int pinsAvailable = 0; IPin[] pins = new IPin[20]; IEnumPins enumPins = null; try { // for each output pin of the capture filter _capture.VideoFilter.EnumPins(out enumPins); enumPins.Next(20, pins, out pinsAvailable); Log.Log.WriteFile("analog: capture pins available:{0}", pinsAvailable); for (int i = 0; i < pinsAvailable; ++i) { int hr; // check if this is an outpin pin on the capture filter PinDirection pinDir; pins[i].QueryDirection(out pinDir); if (pinDir == PinDirection.Input) continue; //log the pin info Log.Log.WriteFile("analog: capture pin:{0} {1} {2}", i, pinDir, FilterGraphTools.LogPinInfo(pins[i])); string pinName = FilterGraphTools.GetPinName(pins[i]); // try to connect this output pin of the capture filter to the 1st input pin // of the multiplexer // only try to connect when pin name matching is turned off // or when the pin names are the same if (matchPinNames == false || (String.Compare(pinName, pinName1, true) == 0)) { //try to connect the output pin of the capture filter to the 1st input pin of the multiplexer hr = _graphBuilder.Connect(pins[i], pinInput1); if (hr == 0) { //succeeded Log.Log.WriteFile("analog: connected pin:{0} {1} to pin1:{2}", i, FilterGraphTools.LogPinInfo(pins[i]), FilterGraphTools.LogPinInfo(pinInput1)); pinsConnected++; } } // next try to connect this output pin of the capture filter to the 2nd input pin // of the multiplexer // only try to connect when pin name matching is turned off // or when the pin names are the same if (matchPinNames == false || (String.Compare(pinName, pinName2, true) == 0)) { // check if multiplexer has 2 input pins if (pinInput2 != null) { //try to connect the output pin of the capture filter to the 2nd input pin of the multiplexer hr = _graphBuilder.Connect(pins[i], pinInput2); if (hr == 0) { //succeeded Log.Log.WriteFile("analog: connected pin:{0} {1} to pin2:{2}", i, FilterGraphTools.LogPinInfo(pins[i]), FilterGraphTools.LogPinInfo(pinInput2)); pinsConnected++; } } } if (_tuner.IsNvidiaCard() && (pinsConnected == 1) && (_filterVideoEncoder != null)) { Log.Log.WriteFile( "analog: ConnectMultiplexer step 1 software audio encoder connected and no need for a software video encoder"); break; } if (pinsConnected == 2) { //if both pins are connected, we're done.. Log.Log.WriteFile("analog: ConnectMultiplexer succeeded at step 1"); return true; } else { Log.Log.WriteFile("analog: ConnectMultiplexer no succes yet at step 1 only connected:" + pinsConnected + " pins"); } } pinsConnectedOnMultiplexer += pinsConnected; } finally { if (enumPins != null) Release.ComObject("ienumpins", enumPins); for (int i = 0; i < pinsAvailable; ++i) { if (pins[i] != null) Release.ComObject("capture pin" + i, pins[i]); } } } //if we only have a single video encoder if (_filterAudioEncoder == null && _filterVideoEncoder != null) { //option 1, connect the multiplexer to a single encoder filter Log.Log.WriteFile("analog: ConnectMultiplexer to video encoder filter"); int pinsConnected = 0; int pinsAvailable = 0; IPin[] pins = new IPin[20]; IEnumPins enumPins = null; try { // for each output pin of the video encoder filter _filterVideoEncoder.EnumPins(out enumPins); enumPins.Next(20, pins, out pinsAvailable); Log.Log.WriteFile("analog: video encoder pins available:{0}", pinsAvailable); for (int i = 0; i < pinsAvailable; ++i) { int hr; // check if this is an outpin pin on the video encoder filter PinDirection pinDir; pins[i].QueryDirection(out pinDir); if (pinDir == PinDirection.Input) continue; //log the pin info Log.Log.WriteFile("analog: videoencoder pin:{0} {1}", i, FilterGraphTools.LogPinInfo(pins[i])); string pinName = FilterGraphTools.GetPinName(pins[i]); // try to connect this output pin of the video encoder filter to the 1st input pin // of the multiplexer // only try to connect when pin name matching is turned off // or when the pin names are the same if (matchPinNames == false || (String.Compare(pinName, pinName1, true) == 0)) { //try to connect the output pin of the video encoder filter to the 1st input pin of the multiplexer filter hr = _graphBuilder.Connect(pins[i], pinInput1); if (hr == 0) { //succeeded Log.Log.WriteFile("analog: connected pin:{0} {1} to {2}", i, FilterGraphTools.LogPinInfo(pins[i]), FilterGraphTools.LogPinInfo(pinInput1)); pinsConnected++; } } //if the multiplexer has 2 input pins if (pinInput2 != null) { // next try to connect this output pin of the video encoder to the 2nd input pin // of the multiplexer // only try to connect when pin name matching is turned off // or when the pin names are the same if (matchPinNames == false || (String.Compare(pinName, pinName2, true) == 0)) { //try to connect the output pin of the video encoder filter to the 1st input pin of the multiplexer filter hr = _graphBuilder.Connect(pins[i], pinInput2); if (hr == 0) { //succeeded Log.Log.WriteFile("analog: connected pin:{0} {1} to {2}", i, FilterGraphTools.LogPinInfo(pins[i]), FilterGraphTools.LogPinInfo(pinInput2)); pinsConnected++; } } } if (pinsConnected == 1) { // add the already connected pin from the previous step (ConnectMultiplexer to capture filter) pinsConnected += pinsConnectedOnMultiplexer; } if (pinsConnected == 2) { //succeeded and done... Log.Log.WriteFile("analog: ConnectMultiplexer succeeded at step 2"); return true; } else { Log.Log.WriteFile("analog: ConnectMultiplexer no succes yet at step 2 only connected:" + pinsConnected + " pins"); } } } finally { if (enumPins != null) Release.ComObject("ienumpins", enumPins); for (int i = 0; i < pinsAvailable; ++i) { if (pins[i] != null) Release.ComObject("encoder pin" + i, pins[i]); } } } //if we have a video encoder and an audio encoder filter if (_filterAudioEncoder != null || _filterVideoEncoder != null) { Log.Log.WriteFile("analog: ConnectMultiplexer to audio/video encoder filters"); //option 3, connect the multiplexer to the audio/video encoder filters int pinsConnected = 0; int pinsAvailable = 0; IPin[] pins = new IPin[20]; IEnumPins enumPins = null; try { // for each output pin of the video encoder filter if (_filterVideoEncoder != null) _filterVideoEncoder.EnumPins(out enumPins); if (enumPins != null) enumPins.Next(20, pins, out pinsAvailable); Log.Log.WriteFile("analog: videoencoder pins available:{0}", pinsAvailable); for (int i = 0; i < pinsAvailable; ++i) { int hr; // check if this is an outpin pin on the video encoder filter PinDirection pinDir; pins[i].QueryDirection(out pinDir); if (pinDir == PinDirection.Input) continue; //log the pin info Log.Log.WriteFile("analog: videoencoder pin:{0} {1} {2}", i, pinDir, FilterGraphTools.LogPinInfo(pins[i])); string pinName = FilterGraphTools.GetPinName(pins[i]); // try to connect this output pin of the video encoder filter to the 1st input pin // of the multiplexer // only try to connect when pin name matching is turned off // or when the pin names are the same if (matchPinNames == false || (String.Compare(pinName, pinName1, true) == 0)) { //try to connect the output pin of the video encoder filter to the 1st input pin of the multiplexer filter hr = _graphBuilder.Connect(pins[i], pinInput1); if (hr == 0) { //succeeded Log.Log.WriteFile("analog: connected pin:{0} {1} to {2}", i, FilterGraphTools.LogPinInfo(pins[i]), FilterGraphTools.LogPinInfo(pinInput1)); pinsConnected++; } else { Log.Log.WriteFile("Cant connect 0x{0:x}", hr); Log.Log.WriteFile("pin:{0} {1} to {2}", i, FilterGraphTools.LogPinInfo(pins[i]), FilterGraphTools.LogPinInfo(pinInput1)); } } //if multiplexer has 2 inputs.. if (pinInput2 != null) { // next try to connect this output pin of the video encoder to the 2nd input pin // of the multiplexer // only try to connect when pin name matching is turned off // or when the pin names are the same if (matchPinNames == false || (String.Compare(pinName, pinName2, true) == 0)) { //try to connect the output pin of the video encoder filter to the 2nd input pin of the multiplexer filter hr = _graphBuilder.Connect(pins[i], pinInput2); if (hr == 0) { //succeeded Log.Log.WriteFile("analog: connected pin:{0} {1} to {2}", i, FilterGraphTools.LogPinInfo(pins[i]), FilterGraphTools.LogPinInfo(pinInput2)); pinsConnected++; } else { Log.Log.WriteFile("Cant connect 0x{0:x}", hr); Log.Log.WriteFile("pin:{0} {1} to {2}", i, FilterGraphTools.LogPinInfo(pins[i]), FilterGraphTools.LogPinInfo(pinInput2)); } } } if (pinsConnected == 1) { //we are done with the video encoder when there is 1 connection between video encoder filter and multiplexer //next, continue with the audio encoder... Log.Log.WriteFile("analog: ConnectMultiplexer part 1 succeeded"); break; } } if (pinsConnected == 0) // video encoder is not connected, so we fail { Log.Log.WriteFile("analog: Video not connected to multiplexer (pinsConnected == 0) FAILURE"); return false; } Log.Log.WriteFile("analog: (pinsConnected: {0})", pinsConnected); if (_filterAudioEncoder != null) { // for each output pin of the audio encoder filter _filterAudioEncoder.EnumPins(out enumPins); enumPins.Next(20, pins, out pinsAvailable); Log.Log.WriteFile("analog: audioencoder pins available:{0}", pinsAvailable); for (int i = 0; i < pinsAvailable; ++i) { int hr; // check if this is an outpin pin on the audio encoder filter PinDirection pinDir; pins[i].QueryDirection(out pinDir); if (pinDir == PinDirection.Input) continue; Log.Log.WriteFile("analog: audioencoder pin:{0} {1} {2}", i, pinDir, FilterGraphTools.LogPinInfo(pins[i])); string pinName = FilterGraphTools.GetPinName(pins[i]); // try to connect this output pin of the audio encoder filter to the 1st input pin // of the multiplexer // only try to connect when pin name matching is turned off // or when the pin names are the same if (matchPinNames == false || (String.Compare(pinName, pinName1, true) == 0)) { //try to connect the output pin of the audio encoder filter to the 1st input pin of the multiplexer filter hr = _graphBuilder.Connect(pins[i], pinInput1); if (hr == 0) { //succeeded Log.Log.WriteFile("analog: connected pin:{0}", i); pinsConnected++; } } //if multiplexer has 2 input pins if (pinInput2 != null) { // next try to connect this output pin of the audio encoder to the 2nd input pin // of the multiplexer // only try to connect when pin name matching is turned off // or when the pin names are the same if (matchPinNames == false || (String.Compare(pinName, pinName2, true) == 0)) { //try to connect the output pin of the audio encoder filter to the 2nd input pin of the multiplexer filter hr = _graphBuilder.Connect(pins[i], pinInput2); if (hr == 0) { //succeeded Log.Log.WriteFile("analog: connected pin:{0}", i); pinsConnected++; } } } //when both pins on the multiplexer are connected, we're done if (pinsConnected == 2) { Log.Log.WriteFile("analog: part 2 succeeded"); return true; } } } } finally { if (enumPins != null) Release.ComObject("ienumpins", enumPins); for (int i = 0; i < pinsAvailable; ++i) { if (pins[i] != null) Release.ComObject("audio encoder pin" + i, pins[i]); } } } } finally { if (pinInput1 != null) Release.ComObject("multiplexer pin0", pinInput1); if (pinInput2 != null) Release.ComObject("multiplexer pin1", pinInput2); } Log.Log.Error("analog: ConnectMultiplexer failed"); return false; }
private void SetupGraph(string FileName) { int hr; ISampleGrabber sampGrabber = null; IBaseFilter baseGrabFlt = null; IBaseFilter capFilter = null; IBaseFilter nullrenderer = null; // Get the graphbuilder object m_FilterGraph = new FilterGraph() as IFilterGraph2; m_mediaCtrl = m_FilterGraph as IMediaControl; m_MediaEvent = m_FilterGraph as IMediaEvent; IMediaFilter mediaFilt = m_FilterGraph as IMediaFilter; try { // Add the video source hr = m_FilterGraph.AddSourceFilter(FileName, "Ds.NET FileFilter", out capFilter); DsError.ThrowExceptionForHR(hr); // Get the SampleGrabber interface sampGrabber = new SampleGrabber() as ISampleGrabber; baseGrabFlt = sampGrabber as IBaseFilter; ConfigureSampleGrabber(sampGrabber); // Add the frame grabber to the graph hr = m_FilterGraph.AddFilter(baseGrabFlt, "Ds.NET Grabber"); DsError.ThrowExceptionForHR(hr); // --------------------------------- // Connect the file filter to the sample grabber // Hopefully this will be the audio pin, we could check by reading it's mediatype IPin iPinOut = DsFindPin.ByDirection(capFilter, PinDirection.Output, 0); // Get the input pin from the sample grabber IPin iPinIn = DsFindPin.ByDirection(baseGrabFlt, PinDirection.Input, 0); hr = m_FilterGraph.Connect(iPinOut, iPinIn); DsError.ThrowExceptionForHR(hr); // Add the null renderer to the graph nullrenderer = new NullRenderer() as IBaseFilter; hr = m_FilterGraph.AddFilter(nullrenderer, "Null renderer"); DsError.ThrowExceptionForHR(hr); // --------------------------------- // Connect the sample grabber to the null renderer iPinOut = DsFindPin.ByDirection(baseGrabFlt, PinDirection.Output, 0); iPinIn = DsFindPin.ByDirection(nullrenderer, PinDirection.Input, 0); hr = m_FilterGraph.Connect(iPinOut, iPinIn); DsError.ThrowExceptionForHR(hr); // Turn off the clock. This causes the frames to be sent // thru the graph as fast as possible hr = mediaFilt.SetSyncSource(null); DsError.ThrowExceptionForHR(hr); // Read and cache the image sizes SaveSizeInfo(sampGrabber); } finally { if (capFilter != null) { Marshal.ReleaseComObject(capFilter); capFilter = null; } if (sampGrabber != null) { Marshal.ReleaseComObject(sampGrabber); sampGrabber = null; } if (nullrenderer != null) { Marshal.ReleaseComObject(nullrenderer); nullrenderer = null; } } }
public void SetUpForTs(ISampleGrabberCB grabber, int methodToCall) { FilterGraphTools.DisconnectPins(mpeg2Demux); //FilterGraphTools.DisconnectPins(demodulator); FilterGraphTools.DisconnectPins(audioRenderer); FilterGraphTools.DisconnectPins(videoRenderer); //graphBuilder.RemoveFilter(audioRenderer); //graphBuilder.RemoveFilter(videoRenderer); sampleGrabber = (ISampleGrabber) new SampleGrabber(); AMMediaType media = new AMMediaType(); media.majorType = MediaType.Stream; media.subType = MediaSubType.Mpeg2Transport; media.formatType = FormatType.MpegStreams; sampleGrabber.SetOneShot(false); sampleGrabber.SetBufferSamples(true); int hr = sampleGrabber.SetMediaType(media); DsError.ThrowExceptionForHR(hr); graphBuilder.AddFilter((IBaseFilter)sampleGrabber, "Sample Grabber"); nullRenderer = (IBaseFilter) new NullRenderer(); graphBuilder.AddFilter(nullRenderer, "NULL Renderer"); IPin pinIn = DsFindPin.ByName((IBaseFilter)sampleGrabber, "Input"); IPin pinOut = DsFindPin.ByDirection(capture, PinDirection.Output, 0); IEnumMediaTypes eMedia; pinOut.EnumMediaTypes(out eMedia); AMMediaType[] mediaTypes = new AMMediaType[1]; eMedia.Next(mediaTypes.Length, mediaTypes, IntPtr.Zero); hr = sampleGrabber.SetMediaType(mediaTypes[0]); DsError.ThrowExceptionForHR(hr); pinOut.Disconnect(); PinInfo info; pinOut.QueryPinInfo(out info); hr = graphBuilder.ConnectDirect(pinOut, pinIn, mediaTypes[0]); //hr = graphBuilder.Connect(pinOut, pinIn); DsError.ThrowExceptionForHR(hr); // Release the Pin Marshal.ReleaseComObject(pinIn); pinIn = DsFindPin.ByName(nullRenderer, "In"); pinOut = DsFindPin.ByName((IBaseFilter)sampleGrabber, "Output"); hr = graphBuilder.Connect(pinOut, pinIn); DsError.ThrowExceptionForHR(hr); sampleGrabber.SetCallback(grabber, methodToCall); // Release the Pin Marshal.ReleaseComObject(pinIn); pinIn = null; }
public bool Play(string fileName, Form form) { fileName += ".tsbuffer"; Log.WriteFile("play:{0}", fileName); _graphBuilder = (IFilterGraph2) new FilterGraph(); _rotEntry = new DsROTEntry(_graphBuilder); Log.WriteFile("add tsfilesource"); _tsFileSource = new TsFileSource(); _graphBuilder.AddFilter((IBaseFilter)_tsFileSource, "TsFileSource"); #region add mpeg-2 demux filter Log.WriteFile("add mpeg-2 demux"); MPEG2Demultiplexer demux = new MPEG2Demultiplexer(); _mpegDemux = (IBaseFilter)demux; int hr = _graphBuilder.AddFilter(_mpegDemux, "MPEG-2 Demultiplexer"); #endregion #region create mpeg2 demux pins Log.WriteFile("create mpeg-2 demux pins"); //create mpeg-2 demux output pins IMpeg2Demultiplexer demuxer = _mpegDemux as IMpeg2Demultiplexer; if (demuxer != null) { hr = demuxer.CreateOutputPin(GetAudioMpg2Media(), "Audio", out _pinAudio); } if (hr != 0) { Log.WriteFile("unable to create audio pin"); return(false); } if (demuxer != null) { hr = demuxer.CreateOutputPin(GetVideoMpg2Media(), "Video", out _pinVideo); } if (hr != 0) { Log.WriteFile("unable to create video pin"); return(false); } #endregion #region load file in tsfilesource Log.WriteFile("load file in tsfilesource"); IFileSourceFilter interfaceFile = (IFileSourceFilter)_tsFileSource; if (interfaceFile == null) { Log.WriteFile("TSStreamBufferPlayer9:Failed to get IFileSourceFilter"); return(false); } AMMediaType mpeg2ProgramStream = new AMMediaType(); mpeg2ProgramStream.majorType = MediaType.Stream; mpeg2ProgramStream.subType = MediaSubType.Mpeg2Program; mpeg2ProgramStream.unkPtr = IntPtr.Zero; mpeg2ProgramStream.sampleSize = 0; mpeg2ProgramStream.temporalCompression = false; mpeg2ProgramStream.fixedSizeSamples = true; mpeg2ProgramStream.formatType = FormatType.None; mpeg2ProgramStream.formatSize = 0; mpeg2ProgramStream.formatPtr = IntPtr.Zero; hr = interfaceFile.Load(fileName, mpeg2ProgramStream); if (hr != 0) { Log.WriteFile("TSStreamBufferPlayer9:Failed to load file"); return(false); } #region connect tsfilesource->demux Log.WriteFile("connect tsfilesource->demux"); Log.WriteFile("TSStreamBufferPlayer9:connect tsfilesource->mpeg2 demux"); IPin pinTsOut = DsFindPin.ByDirection((IBaseFilter)_tsFileSource, PinDirection.Output, 0); if (pinTsOut == null) { Log.WriteFile("TSStreamBufferPlayer9:failed to find output pin of tsfilesource"); return(false); } IPin pinDemuxIn = DsFindPin.ByDirection(_mpegDemux, PinDirection.Input, 0); if (pinDemuxIn == null) { Log.WriteFile("TSStreamBufferPlayer9:failed to find output pin of tsfilesource"); return(false); } hr = _graphBuilder.Connect(pinTsOut, pinDemuxIn); if (hr != 0) { Log.WriteFile("TSStreamBufferPlayer9:failed to connect tsfilesource->mpeg2 demux:{0:X}", hr); return(false); } Release.ComObject(pinTsOut); Release.ComObject(pinDemuxIn); #endregion #region map demux pids Log.WriteFile("map mpeg2 pids"); IMPEG2StreamIdMap pStreamId = (IMPEG2StreamIdMap)_pinVideo; hr = pStreamId.MapStreamId(0xe0, MPEG2Program.ElementaryStream, 0, 0); if (hr != 0) { Log.WriteFile("TSStreamBufferPlayer9: failed to map pid 0xe0->video pin"); return(false); } pStreamId = (IMPEG2StreamIdMap)_pinAudio; hr = pStreamId.MapStreamId(0xc0, MPEG2Program.ElementaryStream, 0, 0); if (hr != 0) { Log.WriteFile("TSStreamBufferPlayer9: failed to map pid 0xc0->audio pin"); return(false); } #endregion #region render demux audio/video pins Log.WriteFile("render pins"); hr = _graphBuilder.Render(_pinAudio); if (hr != 0) { Log.WriteFile("TSStreamBufferPlayer9:failed to render video output pin:{0:X}", hr); } hr = _graphBuilder.Render(_pinVideo); if (hr != 0) { Log.WriteFile("TSStreamBufferPlayer9:failed to render audio output pin:{0:X}", hr); } #endregion #endregion _videoWin = _graphBuilder as IVideoWindow; if (_videoWin != null) { _videoWin.put_Visible(OABool.True); _videoWin.put_Owner(form.Handle); _videoWin.put_WindowStyle( (WindowStyle)((int)WindowStyle.Child + (int)WindowStyle.ClipSiblings + (int)WindowStyle.ClipChildren)); _videoWin.put_MessageDrain(form.Handle); _videoWin.SetWindowPosition(190, 250, 150, 150); } Log.WriteFile("run graph"); _mediaCtrl = (IMediaControl)_graphBuilder; hr = _mediaCtrl.Run(); Log.WriteFile("TSStreamBufferPlayer9:running:{0:X}", hr); return(true); }
public bool Play(string fileName, Form form) { fileName += ".tsbuffer"; Log.WriteFile("play:{0}", fileName); _graphBuilder = (IFilterGraph2)new FilterGraph(); _rotEntry = new DsROTEntry(_graphBuilder); Log.WriteFile("add tsfilesource"); _tsFileSource = new TsFileSource(); _graphBuilder.AddFilter((IBaseFilter)_tsFileSource, "TsFileSource"); #region add mpeg-2 demux filter Log.WriteFile("add mpeg-2 demux"); MPEG2Demultiplexer demux = new MPEG2Demultiplexer(); _mpegDemux = (IBaseFilter)demux; int hr = _graphBuilder.AddFilter(_mpegDemux, "MPEG-2 Demultiplexer"); #endregion #region create mpeg2 demux pins Log.WriteFile("create mpeg-2 demux pins"); //create mpeg-2 demux output pins IMpeg2Demultiplexer demuxer = _mpegDemux as IMpeg2Demultiplexer; if (demuxer != null) hr = demuxer.CreateOutputPin(GetAudioMpg2Media(), "Audio", out _pinAudio); if (hr != 0) { Log.WriteFile("unable to create audio pin"); return false; } if (demuxer != null) hr = demuxer.CreateOutputPin(GetVideoMpg2Media(), "Video", out _pinVideo); if (hr != 0) { Log.WriteFile("unable to create video pin"); return false; } #endregion #region load file in tsfilesource Log.WriteFile("load file in tsfilesource"); IFileSourceFilter interfaceFile = (IFileSourceFilter)_tsFileSource; if (interfaceFile == null) { Log.WriteFile("TSStreamBufferPlayer9:Failed to get IFileSourceFilter"); return false; } AMMediaType mpeg2ProgramStream = new AMMediaType(); mpeg2ProgramStream.majorType = MediaType.Stream; mpeg2ProgramStream.subType = MediaSubType.Mpeg2Program; mpeg2ProgramStream.unkPtr = IntPtr.Zero; mpeg2ProgramStream.sampleSize = 0; mpeg2ProgramStream.temporalCompression = false; mpeg2ProgramStream.fixedSizeSamples = true; mpeg2ProgramStream.formatType = FormatType.None; mpeg2ProgramStream.formatSize = 0; mpeg2ProgramStream.formatPtr = IntPtr.Zero; hr = interfaceFile.Load(fileName, mpeg2ProgramStream); if (hr != 0) { Log.WriteFile("TSStreamBufferPlayer9:Failed to load file"); return false; } #region connect tsfilesource->demux Log.WriteFile("connect tsfilesource->demux"); Log.WriteFile("TSStreamBufferPlayer9:connect tsfilesource->mpeg2 demux"); IPin pinTsOut = DsFindPin.ByDirection((IBaseFilter)_tsFileSource, PinDirection.Output, 0); if (pinTsOut == null) { Log.WriteFile("TSStreamBufferPlayer9:failed to find output pin of tsfilesource"); return false; } IPin pinDemuxIn = DsFindPin.ByDirection(_mpegDemux, PinDirection.Input, 0); if (pinDemuxIn == null) { Log.WriteFile("TSStreamBufferPlayer9:failed to find output pin of tsfilesource"); return false; } hr = _graphBuilder.Connect(pinTsOut, pinDemuxIn); if (hr != 0) { Log.WriteFile("TSStreamBufferPlayer9:failed to connect tsfilesource->mpeg2 demux:{0:X}", hr); return false; } Release.ComObject(pinTsOut); Release.ComObject(pinDemuxIn); #endregion #region map demux pids Log.WriteFile("map mpeg2 pids"); IMPEG2StreamIdMap pStreamId = (IMPEG2StreamIdMap)_pinVideo; hr = pStreamId.MapStreamId(0xe0, MPEG2Program.ElementaryStream, 0, 0); if (hr != 0) { Log.WriteFile("TSStreamBufferPlayer9: failed to map pid 0xe0->video pin"); return false; } pStreamId = (IMPEG2StreamIdMap)_pinAudio; hr = pStreamId.MapStreamId(0xc0, MPEG2Program.ElementaryStream, 0, 0); if (hr != 0) { Log.WriteFile("TSStreamBufferPlayer9: failed to map pid 0xc0->audio pin"); return false; } #endregion #region render demux audio/video pins Log.WriteFile("render pins"); hr = _graphBuilder.Render(_pinAudio); if (hr != 0) { Log.WriteFile("TSStreamBufferPlayer9:failed to render video output pin:{0:X}", hr); } hr = _graphBuilder.Render(_pinVideo); if (hr != 0) { Log.WriteFile("TSStreamBufferPlayer9:failed to render audio output pin:{0:X}", hr); } #endregion #endregion _videoWin = _graphBuilder as IVideoWindow; if (_videoWin != null) { _videoWin.put_Visible(OABool.True); _videoWin.put_Owner(form.Handle); _videoWin.put_WindowStyle( (WindowStyle)((int)WindowStyle.Child + (int)WindowStyle.ClipSiblings + (int)WindowStyle.ClipChildren)); _videoWin.put_MessageDrain(form.Handle); _videoWin.SetWindowPosition(190, 250, 150, 150); } Log.WriteFile("run graph"); _mediaCtrl = (IMediaControl)_graphBuilder; hr = _mediaCtrl.Run(); Log.WriteFile("TSStreamBufferPlayer9:running:{0:X}", hr); return true; }
// This method changed to work with Windows 7 // Under this OS, the MPEG-2 Demux now have dozens of outputs pins. // Rendering all of them is not a good solution. // The rendering process must be more smart... private void ConnectFilters() { int hr = 0; int pinNumber = 0; IPin pinOut, pinIn; // After the rendering process, our 4 downstream filters must be rendered bool bdaTIFRendered = false; bool bdaSecTabRendered = false; bool audioRendered = false; bool videoRendered = false; // for each output pins... while (true) { pinOut = DsFindPin.ByDirection(mpeg2Demux, PinDirection.Output, pinNumber); // Is the last pin reached ? if (pinOut == null) { break; } IEnumMediaTypes enumMediaTypes = null; AMMediaType[] mediaTypes = new AMMediaType[1]; try { // Get Pin's MediaType enumerator hr = pinOut.EnumMediaTypes(out enumMediaTypes); DsError.ThrowExceptionForHR(hr); // for each media types... while (enumMediaTypes.Next(mediaTypes.Length, mediaTypes, IntPtr.Zero) == 0) { // Store the majortype and the subtype and free the structure Guid majorType = mediaTypes[0].majorType; Guid subType = mediaTypes[0].subType; DsUtils.FreeAMMediaType(mediaTypes[0]); if (majorType == MediaType.Audio) { // Is the Audio already rendered ? if (!audioRendered) { // Get the first input pin pinIn = DsFindPin.ByDirection(audioRenderer, PinDirection.Input, 0); // Render it with IntelliConnect (a decoder should be added between the two filters. hr = graphBuilder.Connect(pinOut, pinIn); DsError.ThrowExceptionForHR(hr); // Release the Pin Marshal.ReleaseComObject(pinIn); pinIn = null; // Notify that the audio renderer is connected audioRendered = true; } } else if (majorType == MediaType.Video) { // Is the Video already rendered ? if (!videoRendered) { // Get the first input pin pinIn = DsFindPin.ByDirection(videoRenderer, PinDirection.Input, 0); // Render it with IntelliConnect (a decoder should be added between the two filters. hr = graphBuilder.Connect(pinOut, pinIn); DsError.ThrowExceptionForHR(hr); // Release the Pin Marshal.ReleaseComObject(pinIn); pinIn = null; // Notify that the video renderer is connected videoRendered = true; } } else if (majorType == MediaType.Mpeg2Sections) { if (subType == MediaSubType.Mpeg2Data) { // Is the MPEG-2 Sections and Tables Filter already rendered ? if (!bdaSecTabRendered) { // Get the first input pin pinIn = DsFindPin.ByDirection(bdaSecTab, PinDirection.Input, 0); // A direct connection is enough hr = graphBuilder.ConnectDirect(pinOut, pinIn, null); DsError.ThrowExceptionForHR(hr); // Release the Pin Marshal.ReleaseComObject(pinIn); pinIn = null; // Notify that the MPEG-2 Sections and Tables Filter is connected bdaSecTabRendered = true; } } // This sample only support DVB-T or DVB-S so only supporting this subtype is enough. // If you want to support ATSC or ISDB, don't forget to handle these network types. else if (subType == MediaSubType.DvbSI) { // Is the BDA MPEG-2 Transport Information Filter already rendered ? if (!bdaTIFRendered) { // Get the first input pin pinIn = DsFindPin.ByDirection(bdaTIF, PinDirection.Input, 0); // A direct connection is enough hr = graphBuilder.ConnectDirect(pinOut, pinIn, null); DsError.ThrowExceptionForHR(hr); // Release the Pin Marshal.ReleaseComObject(pinIn); pinIn = null; // Notify that the BDA MPEG-2 Transport Information Filter is connected bdaTIFRendered = true; } } } } } finally { // Free COM objects Marshal.ReleaseComObject(enumMediaTypes); enumMediaTypes = null; Marshal.ReleaseComObject(pinOut); pinOut = null; } // Next pin, please ! pinNumber++; } }
/// <summary> build the capture graph for grabber. </summary> private void SetupGraph(string FileName, Control hWin) { int hr; IBaseFilter ibfRenderer = null; ISampleGrabber sampGrabber = null; IBaseFilter capFilter = null; IPin iPinInFilter = null; IPin iPinOutFilter = null; IPin iPinInDest = null; // Get the graphbuilder object m_FilterGraph = new FilterGraph() as IFilterGraph2; #if DEBUG m_rot = new DsROTEntry(m_FilterGraph); #endif try { // Get the SampleGrabber interface sampGrabber = new SampleGrabber() as ISampleGrabber; // Add the video source hr = m_FilterGraph.AddSourceFilter(FileName, "Ds.NET FileFilter", out capFilter); DsError.ThrowExceptionForHR(hr); // Hopefully this will be the video pin IPin iPinOutSource = DsFindPin.ByDirection(capFilter, PinDirection.Output, 0); IBaseFilter baseGrabFlt = sampGrabber as IBaseFilter; ConfigureSampleGrabber(sampGrabber); iPinInFilter = DsFindPin.ByDirection(baseGrabFlt, PinDirection.Input, 0); iPinOutFilter = DsFindPin.ByDirection(baseGrabFlt, PinDirection.Output, 0); // Add the frame grabber to the graph hr = m_FilterGraph.AddFilter(baseGrabFlt, "Ds.NET Grabber"); DsError.ThrowExceptionForHR(hr); hr = m_FilterGraph.Connect(iPinOutSource, iPinInFilter); DsError.ThrowExceptionForHR(hr); // Get the default video renderer ibfRenderer = (IBaseFilter) new VideoRendererDefault(); // Add it to the graph hr = m_FilterGraph.AddFilter(ibfRenderer, "Ds.NET VideoRendererDefault"); DsError.ThrowExceptionForHR(hr); iPinInDest = DsFindPin.ByDirection(ibfRenderer, PinDirection.Input, 0); // Connect the graph. Many other filters automatically get added here hr = m_FilterGraph.Connect(iPinOutFilter, iPinInDest); DsError.ThrowExceptionForHR(hr); SaveSizeInfo(sampGrabber); // Set the output window IVideoWindow videoWindow = m_FilterGraph as IVideoWindow; hr = videoWindow.put_Owner(hWin.Handle); DsError.ThrowExceptionForHR(hr); hr = videoWindow.put_WindowStyle(WindowStyle.Child | WindowStyle.ClipChildren | WindowStyle.ClipSiblings); DsError.ThrowExceptionForHR(hr); hr = videoWindow.put_Visible(OABool.True); DsError.ThrowExceptionForHR(hr); Rectangle rc = hWin.ClientRectangle; hr = videoWindow.SetWindowPosition(0, 0, rc.Right, rc.Bottom); DsError.ThrowExceptionForHR(hr); } finally { if (capFilter != null) { Marshal.ReleaseComObject(capFilter); capFilter = null; } if (sampGrabber != null) { Marshal.ReleaseComObject(sampGrabber); sampGrabber = null; } if (ibfRenderer != null) { Marshal.ReleaseComObject(ibfRenderer); ibfRenderer = null; } if (iPinInFilter != null) { Marshal.ReleaseComObject(iPinInFilter); iPinInFilter = null; } if (iPinOutFilter != null) { Marshal.ReleaseComObject(iPinOutFilter); iPinOutFilter = null; } if (iPinInDest != null) { Marshal.ReleaseComObject(iPinInDest); iPinInDest = null; } } }
/// <summary> /// Creates the teletext component in the graph. First we try to use the stored informations in the graph /// </summary> /// <param name="graph">The stored graph</param> /// <param name="graphBuilder">The graphbuilder</param> /// <param name="capture">The capture component</param> /// <returns>true, if the building was successful; false otherwise</returns> public bool CreateFilterInstance(Graph graph, IFilterGraph2 graphBuilder, Capture capture) { Log.Log.WriteFile("analog: SetupTeletext()"); Guid guidBaseFilter = typeof(IBaseFilter).GUID; object obj; //find and add tee/sink to sink filter DsDevice[] devices = DsDevice.GetDevicesOfCat(FilterCategory.AMKSSplitter); devices[0].Mon.BindToObject(null, null, ref guidBaseFilter, out obj); _teeSink = (IBaseFilter)obj; int hr = graphBuilder.AddFilter(_teeSink, devices[0].Name); if (hr != 0) { Log.Log.Error("analog:SinkGraphEx.SetupTeletext(): Unable to add tee/sink filter"); return(false); } //connect capture filter -> tee sink filter IPin pin = DsFindPin.ByDirection(_teeSink, PinDirection.Input, 0); hr = graphBuilder.Connect(capture.VBIPin, pin); Release.ComObject(pin); if (hr != 0) { //failed... Log.Log.Error("analog: unable to connect capture->tee/sink"); graphBuilder.RemoveFilter(_teeSink); Release.ComObject(_teeSink); _teeSink = _filterWstDecoder = null; return(false); } if (!string.IsNullOrEmpty(graph.Teletext.Name)) { Log.Log.WriteFile("analog: Using Teletext-Component configuration from stored graph"); devices = DsDevice.GetDevicesOfCat(graph.Teletext.Category); foreach (DsDevice device in devices) { if (device.Name != null && device.Name.Equals(graph.Teletext.Name)) { //found it, add it to the graph Log.Log.Info("analog:Using teletext component - {0}", graph.Teletext.Name); device.Mon.BindToObject(null, null, ref guidBaseFilter, out obj); _filterWstDecoder = (IBaseFilter)obj; hr = graphBuilder.AddFilter(_filterWstDecoder, device.Name); if (hr != 0) { //failed... Log.Log.Error("analog:SinkGraphEx.SetupTeletext(): Unable to add WST Codec filter"); graphBuilder.RemoveFilter(_filterWstDecoder); _filterWstDecoder = null; } break; } } } if (_filterWstDecoder == null) { Log.Log.WriteFile("analog: No stored or invalid graph for Teletext component - Trying to detect"); //find the WST codec filter devices = DsDevice.GetDevicesOfCat(FilterCategory.AMKSVBICodec); foreach (DsDevice device in devices) { if (device.Name != null && device.Name.IndexOf("WST") >= 0) { //found it, add it to the graph Log.Log.Info("analog:Found WST Codec filter"); device.Mon.BindToObject(null, null, ref guidBaseFilter, out obj); _filterWstDecoder = (IBaseFilter)obj; hr = graphBuilder.AddFilter(_filterWstDecoder, device.Name); if (hr != 0) { //failed... Log.Log.Error("analog:Unable to add WST Codec filter"); graphBuilder.RemoveFilter(_teeSink); Release.ComObject(_teeSink); _teeSink = _filterWstDecoder = null; return(false); } graph.Teletext.Name = device.Name; graph.Teletext.Category = FilterCategory.AMKSVBICodec; break; } } //Look for VBI Codec for Vista users as Vista doesn't use WST Codec anymore if (_filterWstDecoder == null) { devices = DsDevice.GetDevicesOfCat(FilterCategory.AMKSMULTIVBICodec); foreach (DsDevice device in devices) { if (device.Name != null && device.Name.IndexOf("VBI") >= 0) { //found it, add it to the graph Log.Log.Info("analog:Found VBI Codec filter"); device.Mon.BindToObject(null, null, ref guidBaseFilter, out obj); _filterWstDecoder = (IBaseFilter)obj; hr = graphBuilder.AddFilter(_filterWstDecoder, device.Name); if (hr != 0) { //failed... Log.Log.Error("analog:Unable to add VBI Codec filter"); graphBuilder.RemoveFilter(_teeSink); Release.ComObject(_teeSink); _teeSink = _filterWstDecoder = null; return(false); } graph.Teletext.Name = device.Name; graph.Teletext.Category = FilterCategory.AMKSMULTIVBICodec; break; } } } } if (_filterWstDecoder == null) { Log.Log.Error("analog: unable to find WST Codec or VBI Codec filter"); graphBuilder.RemoveFilter(_teeSink); Release.ComObject(_teeSink); _teeSink = _filterWstDecoder = null; return(false); } //connect tee sink filter-> wst codec filter IPin pinOut = DsFindPin.ByDirection(_teeSink, PinDirection.Output, 0); pin = DsFindPin.ByDirection(_filterWstDecoder, PinDirection.Input, 0); hr = graphBuilder.Connect(pinOut, pin); Release.ComObject(pin); Release.ComObject(pinOut); if (hr != 0) { //failed Log.Log.Error("analog: unable to tee/sink->wst codec"); graphBuilder.RemoveFilter(_filterWstDecoder); graphBuilder.RemoveFilter(_teeSink); Release.ComObject(_filterWstDecoder); Release.ComObject(_teeSink); _teeSink = _filterWstDecoder = null; _teeSink = null; graph.Teletext.Name = null; graph.Teletext.Category = new Guid(); return(false); } //done Log.Log.WriteFile("analog: teletext setup"); if (_filterWstDecoder != null) { Log.Log.WriteFile("analog:connect wst/vbi codec->tsfilesink"); _pinWST_VBI = DsFindPin.ByDirection(_filterWstDecoder, PinDirection.Output, 0); } return(true); }
public void PrepareCapture(int i_width, int i_height,float i_frame_rate) { const int BBP = 32; //既にキャプチャ中なら諦める。 if (this.m_graphi_active) { throw new Exception(); } //現在確保中のグラフインスタンスを全て削除 CleanupGraphiObjects(); int hr; ISampleGrabber sampGrabber = null; IBaseFilter capFilter = null; IPin pSampleIn = null; //グラフビルダを作る。 this.m_FilterGraph = new FilterGraph() as IFilterGraph2; try { //フィルタグラフにキャプチャを追加して、capFilterにピンを受け取る。 hr = m_FilterGraph.AddSourceFilterForMoniker(this.m_dev.Mon, null, this.m_dev.Name, out capFilter); DsError.ThrowExceptionForHR(hr); //stillピンを探す m_pinStill = DsFindPin.ByCategory(capFilter, PinCategory.Still, 0); //stillピンが無ければPreviewを探す。 if (m_pinStill == null) { m_pinStill = DsFindPin.ByCategory(capFilter, PinCategory.Preview, 0); } // Still haven't found one. Need to put a splitter in so we have // one stream to capture the bitmap from, and one to display. Ok, we // don't *have* to do it that way, but we are going to anyway. if (m_pinStill == null) { // There is no still pin m_VidControl = null; m_pinStill = DsFindPin.ByCategory(capFilter, PinCategory.Capture, 0); }else{ // Get a control pointer (used in Click()) m_VidControl = capFilter as IAMVideoControl; m_pinStill = DsFindPin.ByCategory(capFilter, PinCategory.Capture, 0); } if (i_height + i_width + BBP > 0) { SetConfigParms(m_pinStill, i_width, i_height,i_frame_rate, BBP); } // Get the SampleGrabber interface sampGrabber = new SampleGrabber() as ISampleGrabber; //sampGrabberの設定 IBaseFilter baseGrabFlt = sampGrabber as IBaseFilter; ConfigureSampleGrabber(sampGrabber); pSampleIn = DsFindPin.ByDirection(baseGrabFlt, PinDirection.Input, 0); // Add the sample grabber to the graph hr = m_FilterGraph.AddFilter(baseGrabFlt, "Ds.NET Grabber"); DsError.ThrowExceptionForHR(hr); if (m_VidControl == null) { // Connect the Still pin to the sample grabber hr = m_FilterGraph.Connect(m_pinStill, pSampleIn); DsError.ThrowExceptionForHR(hr); }else{ // Connect the Still pin to the sample grabber hr = m_FilterGraph.Connect(m_pinStill, pSampleIn); DsError.ThrowExceptionForHR(hr); } hr = sampGrabber.GetConnectedMediaType(this._capture_mediatype); DsError.ThrowExceptionForHR(hr); //ビデオフォーマット等の更新 upateVideoInfo(sampGrabber); } finally { if (sampGrabber != null) { Marshal.ReleaseComObject(sampGrabber); sampGrabber = null; } if (pSampleIn != null) { Marshal.ReleaseComObject(pSampleIn); pSampleIn = null; } } }
private void BuildGraph() { int hr = 0; Guid wavesReverbDMO = new Guid("87fc0268-9a55-4360-95aa-004a1d9de26c"); IPin pinIn, pinOut; graphBuilder = (IFilterGraph2) new FilterGraph(); // Add a source filter hr = graphBuilder.AddSourceFilter(@"..\..\..\Resources\foo.avi", "foo.avi", out fileSource); DsError.ThrowExceptionForHR(hr); // Add an Avi Splitter aviSplitter = (IBaseFilter) new AviSplitter(); hr = graphBuilder.AddFilter(aviSplitter, "Splitter"); DsError.ThrowExceptionForHR(hr); // Add a DMO Wrapper Filter dmoFilter = (IBaseFilter) new DMOWrapperFilter(); dmoWrapperFilter = (IDMOWrapperFilter)dmoFilter; // IDMOWrapperFilter unique method is tested here // // Init this filter with WavesReverb DMO Object // hr = dmoWrapperFilter.Init(wavesReverbDMO, DMOCategory.AudioEffect); DsError.ThrowExceptionForHR(hr); // Add it to the Graph hr = graphBuilder.AddFilter(dmoFilter, "DMO Filter"); DsError.ThrowExceptionForHR(hr); // Add an audio renderer directSoundDevice = (IBaseFilter) new DSoundRender(); hr = graphBuilder.AddFilter(directSoundDevice, "DirectSound Device"); DsError.ThrowExceptionForHR(hr); // Connect Source filter with Avi Splitter pinOut = DsFindPin.ByDirection(fileSource, PinDirection.Output, 0); pinIn = DsFindPin.ByDirection(aviSplitter, PinDirection.Input, 0); hr = graphBuilder.Connect(pinOut, pinIn); DsError.ThrowExceptionForHR(hr); Marshal.ReleaseComObject(pinOut); Marshal.ReleaseComObject(pinIn); // Connect Avi Splitter audio (2nd) pin with DMO Wrapper // Should add an audio codec between the 2 filters pinOut = DsFindPin.ByDirection(aviSplitter, PinDirection.Output, 1); pinIn = DsFindPin.ByDirection(dmoFilter, PinDirection.Input, 0); hr = graphBuilder.Connect(pinOut, pinIn); DsError.ThrowExceptionForHR(hr); Marshal.ReleaseComObject(pinOut); Marshal.ReleaseComObject(pinIn); // Connect DMO Wrapper with the audio renderer pinOut = DsFindPin.ByDirection(dmoFilter, PinDirection.Output, 0); pinIn = DsFindPin.ByDirection(directSoundDevice, PinDirection.Input, 0); hr = graphBuilder.Connect(pinOut, pinIn); DsError.ThrowExceptionForHR(hr); Marshal.ReleaseComObject(pinOut); Marshal.ReleaseComObject(pinIn); // Run this graph (just for fun) hr = (graphBuilder as IMediaControl).Run(); DsError.ThrowExceptionForHR(hr); System.Threading.Thread.Sleep(4000); }
private void StartCapture() { int hr; ISampleGrabber sampGrabber = null; IBaseFilter capFilter = null; ICaptureGraphBuilder2 capGraph = null; if (System.IO.File.Exists(txtAviFileName.Text)) { // Get the graphbuilder object m_FilterGraph = (IFilterGraph2) new FilterGraph(); m_mediaCtrl = m_FilterGraph as IMediaControl; // Get the ICaptureGraphBuilder2 capGraph = (ICaptureGraphBuilder2) new CaptureGraphBuilder2(); // Get the SampleGrabber interface sampGrabber = (ISampleGrabber) new SampleGrabber(); // Start building the graph hr = capGraph.SetFiltergraph(m_FilterGraph); DsError.ThrowExceptionForHR(hr); // Add the video source hr = m_FilterGraph.AddSourceFilter(txtAviFileName.Text, "File Source (Async.)", out capFilter); DsError.ThrowExceptionForHR(hr); //add AVI Decompressor IBaseFilter pAVIDecompressor = (IBaseFilter) new AVIDec(); hr = m_FilterGraph.AddFilter(pAVIDecompressor, "AVI Decompressor"); DsError.ThrowExceptionForHR(hr); // IBaseFilter baseGrabFlt = (IBaseFilter)sampGrabber; ConfigureSampleGrabber(sampGrabber); // Add the frame grabber to the graph hr = m_FilterGraph.AddFilter(baseGrabFlt, "Ds.NET Grabber"); DsError.ThrowExceptionForHR(hr); IBaseFilter vidrender = (IBaseFilter) new VideoRenderer(); hr = m_FilterGraph.AddFilter(vidrender, "Render"); DsError.ThrowExceptionForHR(hr); IPin captpin = DsFindPin.ByDirection(capFilter, PinDirection.Output, 0); IPin samppin = DsFindPin.ByName(baseGrabFlt, "Input"); hr = m_FilterGraph.Connect(captpin, samppin); DsError.ThrowExceptionForHR(hr); FileWriter filewritter = new FileWriter(); IFileSinkFilter filemux = (IFileSinkFilter)filewritter; //filemux.SetFileName("test.avi",); //hr = capGraph.RenderStream(null, MediaType.Video, capFilter, null, vidrender); // DsError.ThrowExceptionForHR(hr); SaveSizeInfo(sampGrabber); // setup buffer if (m_handle == IntPtr.Zero) { m_handle = Marshal.AllocCoTaskMem(m_stride * m_videoHeight); } // tell the callback to ignore new images m_PictureReady = new ManualResetEvent(false); m_bGotOne = false; m_bRunning = false; timer1 = new Thread(timer); timer1.IsBackground = true; timer1.Start(); m_mediaextseek = m_FilterGraph as IAMExtendedSeeking; m_mediapos = m_FilterGraph as IMediaPosition; m_mediaseek = m_FilterGraph as IMediaSeeking; double length = 0; m_mediapos.get_Duration(out length); trackBar_mediapos.Minimum = 0; trackBar_mediapos.Maximum = (int)length; Start(); } else { MessageBox.Show("File does not exist"); } }
/// <summary> /// Open a new video feed (either web-cam or video file). /// </summary> /// <param name="filter">Specifies the web-cam filter to use, or <i>null</i> when opening a video file.</param> /// <param name="pb">Specifies the output window, or <i>null</i> when running headless and only receiving snapshots.</param> /// <param name="strFile">Specifies the video file to use, or <i>null</i> when opening a web-cam feed.</param> /// <param name="vidCap">Optionally specifies the video capabilities to use, or <i>null</i> to ignore and use the default video capabilities.</param> /// <returns>The duration (if any) is returned, or 0.</returns> /// <remarks>To get the video capabilities see the GetVideoCapatiblities method.</remarks> public long Open(Filter filter, PictureBox pb, string strFile, VideoCapability vidCap = null) { int hr; if (filter != null && strFile != null) { throw new ArgumentException("Both the filter and file are non NULL - only one of these can be used at a time; The filter is used with the web-cam and the file is used with a video file."); } m_selectedFilter = filter; m_graphBuilder = (IFilterGraph2)Activator.CreateInstance(Type.GetTypeFromCLSID(Clsid.FilterGraph, true)); // When using a web-cam, create the moniker for the filter and add the filter to the graph. if (strFile == null) { IMoniker moniker = m_selectedFilter.CreateMoniker(); m_graphBuilder.AddSourceFilterForMoniker(moniker, null, m_selectedFilter.Name, out m_camFilter); Marshal.ReleaseComObject(moniker); m_camControl = m_camFilter as IAMCameraControl; // Create the capture builder used to build the web-cam filter graph. m_captureGraphBuilder = (ICaptureGraphBuilder2)Activator.CreateInstance(Type.GetTypeFromCLSID(Clsid.CaptureGraphBuilder2, true)); hr = m_captureGraphBuilder.SetFiltergraph(m_graphBuilder as IGraphBuilder); if (hr < 0) { Marshal.ThrowExceptionForHR(hr); } // Add the web-cam filter to the graph. hr = m_graphBuilder.AddFilter(m_camFilter, m_selectedFilter.Name); if (hr < 0) { Marshal.ThrowExceptionForHR(hr); } // Set the desired video capabilities. if (vidCap != null) { setVideoCapabilities(m_captureGraphBuilder, m_camFilter, vidCap); } } else { // Build the graph with the video file. hr = m_graphBuilder.RenderFile(strFile, null); if (hr < 0) { Marshal.ThrowExceptionForHR(hr); } m_mediaSeek = m_graphBuilder as IMediaSeeking; if (pb != null) { m_videoFrameStep = m_graphBuilder as IVideoFrameStep; } } // Create the sample grabber used to get snapshots. m_sampleGrabber = (ISampleGrabber)Activator.CreateInstance(Type.GetTypeFromCLSID(Clsid.SampleGrabber, true)); m_baseGrabFilter = m_sampleGrabber as IBaseFilter; m_mediaControl = m_graphBuilder as IMediaControl; // When using a target window, get the video window used with the target output window if (pb != null) { m_mediaEventEx = m_graphBuilder as IMediaEventEx; m_videoWindow = m_graphBuilder as IVideoWindow; } // Otherwise create the null renderer for no video output is needed (only snapshots). else { m_nullRenderer = (IBaseFilter)Activator.CreateInstance(Type.GetTypeFromCLSID(Clsid.NullRenderer, true)); } // Add the sample grabber to the filter graph. hr = m_graphBuilder.AddFilter(m_baseGrabFilter, "Ds.Lib Grabber"); if (hr < 0) { Marshal.ThrowExceptionForHR(hr); } // Turn off the sample grabber buffers. hr = m_sampleGrabber.SetBufferSamples(false); if (hr < 0) { Marshal.ThrowExceptionForHR(hr); } // Turn off the sample grabber one-shot. hr = m_sampleGrabber.SetOneShot(false); if (hr < 0) { Marshal.ThrowExceptionForHR(hr); } // Turn ON the sample grabber callback where video data is to be received. hr = m_sampleGrabber.SetCallback(this, 1); if (hr < 0) { Marshal.ThrowExceptionForHR(hr); } // Set the media format used by the sample grabber. AMMediaType media = new AMMediaType(); media.majorType = MediaType.Video; media.subType = MediaSubType.RGB24; media.formatType = FormatType.VideoInfo; hr = m_sampleGrabber.SetMediaType(media); if (hr < 0) { Marshal.ThrowExceptionForHR(hr); } // Connect the WebCam Filters and Frame Grabber. if (m_selectedFilter != null) { Guid cat; Guid med; cat = PinCategory.Preview; med = MediaType.Video; hr = m_captureGraphBuilder.RenderStream(ref cat, ref med, m_camFilter, null, null); if (hr < 0) { Marshal.ThrowExceptionForHR(hr); } cat = PinCategory.Capture; med = MediaType.Video; hr = m_captureGraphBuilder.RenderStream(ref cat, ref med, m_camFilter, null, m_baseGrabFilter); if (hr < 0) { Marshal.ThrowExceptionForHR(hr); } } // Connect the Frame Grabber and (optionally the Null Renderer) else { // Get the video decoder and its pins. m_videoFilter = Utility.GetFilter(m_graphBuilder as IGraphBuilder, "Video Decoder", false); IPin pOutput; hr = Utility.GetPin(m_videoFilter, PinDirection.Output, out pOutput); if (hr < 0) { Marshal.ThrowExceptionForHR(hr); } IPin pInput; hr = pOutput.ConnectedTo(out pInput); if (hr < 0) { Marshal.ThrowExceptionForHR(hr); } PinInfo pinInfo; hr = pInput.QueryPinInfo(out pinInfo); if (hr < 0) { Marshal.ThrowExceptionForHR(hr); } // Get the sample grabber pins. IPin pGrabInput; hr = Utility.GetPin(m_baseGrabFilter, PinDirection.Input, out pGrabInput); if (hr < 0) { Marshal.ThrowExceptionForHR(hr); } IPin pGrabOutput; hr = Utility.GetPin(m_baseGrabFilter, PinDirection.Output, out pGrabOutput); if (hr < 0) { Marshal.ThrowExceptionForHR(hr); } // Disconnect the source filter output and the input it is connected to. hr = pOutput.Disconnect(); if (hr < 0) { Marshal.ThrowExceptionForHR(hr); } hr = pInput.Disconnect(); if (hr < 0) { Marshal.ThrowExceptionForHR(hr); } // Connect the source output to the Grabber input. hr = m_graphBuilder.Connect(pOutput, pGrabInput); if (hr < 0) { Marshal.ThrowExceptionForHR(hr); } // When rendering video output, connect the Grabber output to the original downstream input that the source was connected to. if (m_nullRenderer == null) { hr = m_graphBuilder.Connect(pGrabOutput, pInput); if (hr < 0) { Marshal.ThrowExceptionForHR(hr); } } Marshal.ReleaseComObject(pOutput); Marshal.ReleaseComObject(pInput); Marshal.ReleaseComObject(pGrabInput); Marshal.ReleaseComObject(pGrabOutput); } // Remove sound filters. IBaseFilter soundFilter = Utility.GetFilter(m_graphBuilder as IGraphBuilder, "Audio Decoder", false); if (soundFilter != null) { hr = m_graphBuilder.RemoveFilter(soundFilter); if (hr < 0) { Marshal.ThrowExceptionForHR(hr); } Marshal.ReleaseComObject(soundFilter); } soundFilter = Utility.GetFilter(m_graphBuilder as IGraphBuilder, "Sound", false); if (soundFilter != null) { hr = m_graphBuilder.RemoveFilter(soundFilter); if (hr < 0) { Marshal.ThrowExceptionForHR(hr); } Marshal.ReleaseComObject(soundFilter); } // When using a headless (no video rendering) setup, connect the null renderer to the Sample Grabber. if (m_nullRenderer != null) { // Add the null renderer. hr = m_graphBuilder.AddFilter(m_nullRenderer, "Null Renderer"); if (hr < 0) { Marshal.ThrowExceptionForHR(hr); } // Get the sample grabber output pin. IPin pGrabOutput; hr = Utility.GetPin(m_baseGrabFilter, PinDirection.Output, out pGrabOutput); if (hr < 0) { Marshal.ThrowExceptionForHR(hr); } // Get the null renderer input pin. IPin pInput; hr = Utility.GetPin(m_nullRenderer, PinDirection.Input, out pInput); if (hr < 0) { Marshal.ThrowExceptionForHR(hr); } // Disconnect the sample grabber pin. hr = pGrabOutput.Disconnect(); if (hr < 0) { Marshal.ThrowExceptionForHR(hr); } // Connect the Grabber output to the null renderer. hr = m_graphBuilder.Connect(pGrabOutput, pInput); if (hr < 0) { Marshal.ThrowExceptionForHR(hr); } Marshal.ReleaseComObject(pInput); Marshal.ReleaseComObject(pGrabOutput); // Remove the Video Renderer for it is no longer needed. IBaseFilter ivideorender = Utility.GetFilter(m_graphBuilder as IGraphBuilder, "Video Renderer"); if (ivideorender != null) { m_graphBuilder.RemoveFilter(ivideorender); Marshal.ReleaseComObject(ivideorender); } } // Get the sample grabber media settings and video header. media = new AMMediaType(); hr = m_sampleGrabber.GetConnectedMediaType(media); if (hr < 0) { Marshal.ThrowExceptionForHR(hr); } if ((media.formatType != FormatType.VideoInfo && media.formatType != FormatType.WaveEx && media.formatType != FormatType.MpegVideo) || media.formatPtr == IntPtr.Zero) { throw new Exception("Media grabber format is unknown."); } // Get the video header with frame sizing information. m_videoInfoHeader = Marshal.PtrToStructure(media.formatPtr, typeof(VideoInfoHeader)) as VideoInfoHeader; Marshal.FreeCoTaskMem(media.formatPtr); media.formatPtr = IntPtr.Zero; // If we are rendering video output, setup the video window (which requires a message pump). if (m_videoWindow != null) { // setup the video window hr = m_videoWindow.put_Owner(pb.Handle); if (hr < 0) { Marshal.ThrowExceptionForHR(hr); } hr = m_videoWindow.put_WindowStyle(WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS); if (hr < 0) { Marshal.ThrowExceptionForHR(hr); } // resize the window hr = m_videoWindow.SetWindowPosition(0, 0, pb.Width, pb.Height); if (hr < 0) { Marshal.ThrowExceptionForHR(hr); } hr = m_videoWindow.put_Visible(DsHlp.OATRUE); if (hr < 0) { Marshal.ThrowExceptionForHR(hr); } // Subscribe to the picturebox size changed event. pb.SizeChanged += Pb_SizeChanged; } // start the capturing hr = m_mediaControl.Run(); if (hr < 0) { Marshal.ThrowExceptionForHR(hr); } // When using a video file, immediately stop at the start. if (strFile != null) { hr = m_mediaControl.Pause(); if (hr < 0) { Marshal.ThrowExceptionForHR(hr); } } // When using a media file, we need to save the video file's duration. if (m_mediaSeek != null) { hr = m_mediaSeek.GetDuration(out m_lDuration); if (hr < 0) { Marshal.ThrowExceptionForHR(hr); } } m_bConnected = true; return(m_lDuration); }
private void StartCapture() { int hr; ISampleGrabber sampGrabber = null; IBaseFilter capFilter = null; ICaptureGraphBuilder2 capGraph = null; if (System.IO.File.Exists(txtAviFileName.Text)) { // Get the graphbuilder object m_FilterGraph = (IFilterGraph2) new FilterGraph(); m_mediaCtrl = m_FilterGraph as IMediaControl; // Get the ICaptureGraphBuilder2 capGraph = (ICaptureGraphBuilder2) new CaptureGraphBuilder2(); // Get the SampleGrabber interface sampGrabber = (ISampleGrabber) new SampleGrabber(); // Start building the graph hr = capGraph.SetFiltergraph(m_FilterGraph); DsError.ThrowExceptionForHR(hr); // Add the video source hr = m_FilterGraph.AddSourceFilter(txtAviFileName.Text, "File Source (Async.)", out capFilter); DsError.ThrowExceptionForHR(hr); //add AVI Decompressor IBaseFilter pAVIDecompressor = (IBaseFilter) new AVIDec(); hr = m_FilterGraph.AddFilter(pAVIDecompressor, "AVI Decompressor"); DsError.ThrowExceptionForHR(hr); IBaseFilter ffdshow; try { // Create Decoder filter COM object (ffdshow video decoder) Type comtype = Type.GetTypeFromCLSID(new Guid("{04FE9017-F873-410E-871E-AB91661A4EF7}")); if (comtype == null) throw new NotSupportedException("Creating ffdshow video decoder COM object fails."); object comobj = Activator.CreateInstance(comtype); ffdshow = (IBaseFilter) comobj; // error ocurrs! raised exception comobj = null; } catch { CustomMessageBox.Show("Please install/reinstall ffdshow"); return; } hr = m_FilterGraph.AddFilter(ffdshow, "ffdshow"); DsError.ThrowExceptionForHR(hr); // IBaseFilter baseGrabFlt = (IBaseFilter) sampGrabber; ConfigureSampleGrabber(sampGrabber); // Add the frame grabber to the graph hr = m_FilterGraph.AddFilter(baseGrabFlt, "Ds.NET Grabber"); DsError.ThrowExceptionForHR(hr); IBaseFilter vidrender = (IBaseFilter) new VideoRenderer(); hr = m_FilterGraph.AddFilter(vidrender, "Render"); DsError.ThrowExceptionForHR(hr); IPin captpin = DsFindPin.ByDirection(capFilter, PinDirection.Output, 0); IPin ffdpinin = DsFindPin.ByName(ffdshow, "In"); IPin ffdpinout = DsFindPin.ByName(ffdshow, "Out"); IPin samppin = DsFindPin.ByName(baseGrabFlt, "Input"); hr = m_FilterGraph.Connect(captpin, ffdpinin); DsError.ThrowExceptionForHR(hr); hr = m_FilterGraph.Connect(ffdpinout, samppin); DsError.ThrowExceptionForHR(hr); FileWriter filewritter = new FileWriter(); IFileSinkFilter filemux = (IFileSinkFilter) filewritter; //filemux.SetFileName("test.avi",); //hr = capGraph.RenderStream(null, MediaType.Video, capFilter, null, vidrender); // DsError.ThrowExceptionForHR(hr); SaveSizeInfo(sampGrabber); // setup buffer if (m_handle == IntPtr.Zero) m_handle = Marshal.AllocCoTaskMem(m_stride*m_videoHeight); // tell the callback to ignore new images m_PictureReady = new ManualResetEvent(false); m_bGotOne = false; m_bRunning = false; timer1 = new Thread(timer); timer1.IsBackground = true; timer1.Start(); m_mediaextseek = m_FilterGraph as IAMExtendedSeeking; m_mediapos = m_FilterGraph as IMediaPosition; m_mediaseek = m_FilterGraph as IMediaSeeking; double length = 0; m_mediapos.get_Duration(out length); trackBar_mediapos.Minimum = 0; trackBar_mediapos.Maximum = (int) length; Start(); } else { MessageBox.Show("File does not exist"); } }
/// <summary> build the capture graph for grabber. </summary> private void SetupGraph(string FileName) { int hr; ISampleGrabber sampGrabber = null; IBaseFilter baseGrabFlt = null; IBaseFilter capFilter = null; IBaseFilter nullrenderer = null; // Get the graphbuilder object m_FilterGraph = new FilterGraph() as IFilterGraph2; m_mediaCtrl = m_FilterGraph as IMediaControl; m_MediaEvent = m_FilterGraph as IMediaEvent; IMediaFilter mediaFilt = m_FilterGraph as IMediaFilter; try { #if DEBUG m_rot = new DsROTEntry(m_FilterGraph); #endif // Add the video source hr = m_FilterGraph.AddSourceFilter(FileName, "Ds.NET FileFilter", out capFilter); DsError.ThrowExceptionForHR(hr); // Get the SampleGrabber interface sampGrabber = new SampleGrabber() as ISampleGrabber; baseGrabFlt = sampGrabber as IBaseFilter; ConfigureSampleGrabber(sampGrabber); // Add the frame grabber to the graph hr = m_FilterGraph.AddFilter(baseGrabFlt, "Ds.NET Grabber"); DsError.ThrowExceptionForHR(hr); // --------------------------------- // Connect the file filter to the sample grabber // Hopefully this will be the video pin, we could check by reading it's mediatype IPin iPinOut = DsFindPin.ByDirection(capFilter, PinDirection.Output, 0); // Get the input pin from the sample grabber IPin iPinIn = DsFindPin.ByDirection(baseGrabFlt, PinDirection.Input, 0); hr = m_FilterGraph.Connect(iPinOut, iPinIn); DsError.ThrowExceptionForHR(hr); // Add the null renderer to the graph nullrenderer = new NullRenderer() as IBaseFilter; hr = m_FilterGraph.AddFilter(nullrenderer, "Null renderer"); DsError.ThrowExceptionForHR(hr); // --------------------------------- // Connect the sample grabber to the null renderer iPinOut = DsFindPin.ByDirection(baseGrabFlt, PinDirection.Output, 0); iPinIn = DsFindPin.ByDirection(nullrenderer, PinDirection.Input, 0); hr = m_FilterGraph.Connect(iPinOut, iPinIn); DsError.ThrowExceptionForHR(hr); // Turn off the clock. This causes the frames to be sent // thru the graph as fast as possible hr = mediaFilt.SetSyncSource(null); DsError.ThrowExceptionForHR(hr); // Read and cache the image sizes SaveSizeInfo(sampGrabber); } finally { if (capFilter != null) { Marshal.ReleaseComObject(capFilter); capFilter = null; } if (sampGrabber != null) { Marshal.ReleaseComObject(sampGrabber); sampGrabber = null; } if (nullrenderer != null) { Marshal.ReleaseComObject(nullrenderer); nullrenderer = null; } } }
public void convert(object obj) { string[] pair = obj as string[]; string srcfile = pair[0]; string targetfile = pair[1]; int hr; ibfSrcFile = (IBaseFilter) new AsyncReader(); hr = gb.AddFilter(ibfSrcFile, "Reader"); DsError.ThrowExceptionForHR(hr); IFileSourceFilter ifileSource = (IFileSourceFilter)ibfSrcFile; hr = ifileSource.Load(srcfile, null); DsError.ThrowExceptionForHR(hr); // the guid is the one from ffdshow Type fftype = Type.GetTypeFromCLSID(new Guid("0F40E1E5-4F79-4988-B1A9-CC98794E6B55")); object ffdshow = Activator.CreateInstance(fftype); hr = gb.AddFilter((IBaseFilter)ffdshow, "ffdshow"); DsError.ThrowExceptionForHR(hr); // the guid is the one from the WAV Dest sample in the SDK Type type = Type.GetTypeFromCLSID(new Guid("3C78B8E2-6C4D-11d1-ADE2-0000F8754B99")); object wavedest = Activator.CreateInstance(type); hr = gb.AddFilter((IBaseFilter)wavedest, "WAV Dest"); DsError.ThrowExceptionForHR(hr); // manually tell the graph builder to try to hook up the pin that is left IPin pWaveDestOut = null; hr = icgb.FindPin(wavedest, PinDirection.Output, null, null, true, 0, out pWaveDestOut); DsError.ThrowExceptionForHR(hr); // render step 1 hr = icgb.RenderStream(null, null, ibfSrcFile, (IBaseFilter)ffdshow, (IBaseFilter)wavedest); DsError.ThrowExceptionForHR(hr); // Configure the sample grabber IBaseFilter baseGrabFlt = sg as IBaseFilter; ConfigSampleGrabber(sg); IPin pGrabberIn = DsFindPin.ByDirection(baseGrabFlt, PinDirection.Input, 0); IPin pGrabberOut = DsFindPin.ByDirection(baseGrabFlt, PinDirection.Output, 0); hr = gb.AddFilter((IBaseFilter)sg, "SampleGrabber"); DsError.ThrowExceptionForHR(hr); AMMediaType mediatype = new AMMediaType(); sg.GetConnectedMediaType(mediatype); hr = gb.Connect(pWaveDestOut, pGrabberIn); DsError.ThrowExceptionForHR(hr); // file writer FileWriter file_writer = new FileWriter(); IFileSinkFilter fs = (IFileSinkFilter)file_writer; fs.SetFileName(targetfile, null); hr = gb.AddFilter((DirectShowLib.IBaseFilter)file_writer, "File Writer"); DsError.ThrowExceptionForHR(hr); // render step 2 AMMediaType mediatype2 = new AMMediaType(); pWaveDestOut.ConnectionMediaType(mediatype2); gb.Render(pGrabberOut); // alternatively to the file writer use the NullRenderer() to just discard the rest // assign control m_mediaCtrl = gb as IMediaControl; // run hr = m_mediaCtrl.Run(); DsError.ThrowExceptionForHR(hr); }
/// <summary> build the capture graph for grabber. </summary> private void SetupGraph(DsDevice dev, int iWidth, int iHeight, short iBPP, Control hControl) { int hr; ISampleGrabber sampGrabber = null; IBaseFilter capFilter = null; IPin pCaptureOut = null; IPin pSampleIn = null; IPin pRenderIn = null; // Get the graphbuilder object m_FilterGraph = new FilterGraph() as IFilterGraph2; try { #if DEBUG m_rot = new DsROTEntry(m_FilterGraph); #endif // add the video input device hr = m_FilterGraph.AddSourceFilterForMoniker(dev.Mon, null, dev.Name, out capFilter); DsError.ThrowExceptionForHR(hr); // Find the still pin m_pinStill = DsFindPin.ByCategory(capFilter, PinCategory.Still, 0); // Didn't find one. Is there a preview pin? if (m_pinStill == null) { m_pinStill = DsFindPin.ByCategory(capFilter, PinCategory.Preview, 0); } // Still haven't found one. Need to put a splitter in so we have // one stream to capture the bitmap from, and one to display. Ok, we // don't *have* to do it that way, but we are going to anyway. if (m_pinStill == null) { IPin pRaw = null; IPin pSmart = null; // There is no still pin m_VidControl = null; // Add a splitter IBaseFilter iSmartTee = (IBaseFilter)new SmartTee(); try { hr = m_FilterGraph.AddFilter(iSmartTee, "SmartTee"); DsError.ThrowExceptionForHR(hr); // Find the find the capture pin from the video device and the // input pin for the splitter, and connnect them pRaw = DsFindPin.ByCategory(capFilter, PinCategory.Capture, 0); pSmart = DsFindPin.ByDirection(iSmartTee, PinDirection.Input, 0); hr = m_FilterGraph.Connect(pRaw, pSmart); DsError.ThrowExceptionForHR(hr); // Now set the capture and still pins (from the splitter) m_pinStill = DsFindPin.ByName(iSmartTee, "Preview"); pCaptureOut = DsFindPin.ByName(iSmartTee, "Capture"); // If any of the default config items are set, perform the config // on the actual video device (rather than the splitter) if (iHeight + iWidth + iBPP > 0) { SetConfigParms(pRaw, iWidth, iHeight, iBPP); } } finally { if (pRaw != null) { Marshal.ReleaseComObject(pRaw); } if (pRaw != pSmart) { Marshal.ReleaseComObject(pSmart); } if (pRaw != iSmartTee) { Marshal.ReleaseComObject(iSmartTee); } } } else { // Get a control pointer (used in Click()) m_VidControl = capFilter as IAMVideoControl; pCaptureOut = DsFindPin.ByCategory(capFilter, PinCategory.Capture, 0); // If any of the default config items are set if (iHeight + iWidth + iBPP > 0) { SetConfigParms(m_pinStill, iWidth, iHeight, iBPP); } } // Get the SampleGrabber interface sampGrabber = new SampleGrabber() as ISampleGrabber; // Configure the sample grabber IBaseFilter baseGrabFlt = sampGrabber as IBaseFilter; ConfigureSampleGrabber(sampGrabber); pSampleIn = DsFindPin.ByDirection(baseGrabFlt, PinDirection.Input, 0); // Get the default video renderer IBaseFilter pRenderer = new VideoRendererDefault() as IBaseFilter; hr = m_FilterGraph.AddFilter(pRenderer, "Renderer"); DsError.ThrowExceptionForHR(hr); pRenderIn = DsFindPin.ByDirection(pRenderer, PinDirection.Input, 0); // Add the sample grabber to the graph hr = m_FilterGraph.AddFilter(baseGrabFlt, "Ds.NET Grabber"); DsError.ThrowExceptionForHR(hr); if (m_VidControl == null) { // Connect the Still pin to the sample grabber hr = m_FilterGraph.Connect(m_pinStill, pSampleIn); DsError.ThrowExceptionForHR(hr); // Connect the capture pin to the renderer hr = m_FilterGraph.Connect(pCaptureOut, pRenderIn); DsError.ThrowExceptionForHR(hr); } else { // Connect the capture pin to the renderer hr = m_FilterGraph.Connect(pCaptureOut, pRenderIn); DsError.ThrowExceptionForHR(hr); // Connect the Still pin to the sample grabber hr = m_FilterGraph.Connect(m_pinStill, pSampleIn); DsError.ThrowExceptionForHR(hr); } // Learn the video properties SaveSizeInfo(sampGrabber); ConfigVideoWindow(hControl); // Start the graph IMediaControl mediaCtrl = m_FilterGraph as IMediaControl; hr = mediaCtrl.Run(); DsError.ThrowExceptionForHR(hr); } finally { if (sampGrabber != null) { Marshal.ReleaseComObject(sampGrabber); sampGrabber = null; } if (pCaptureOut != null) { Marshal.ReleaseComObject(pCaptureOut); pCaptureOut = null; } if (pRenderIn != null) { Marshal.ReleaseComObject(pRenderIn); pRenderIn = null; } if (pSampleIn != null) { Marshal.ReleaseComObject(pSampleIn); pSampleIn = null; } } }
private void SetupGraph(DsDevice dev, int iWidth, int iHeight, short iBPP) { int hr; ISampleGrabber sampGrabber = null; IBaseFilter capFilter = null; IPin pCaptureOut = null; IPin pSampleIn = null; IPin pRenderIn = null; m_FilterGraph = new FilterGraph() as IFilterGraph2; try { #if DEBUG m_rot = new DsROTEntry(m_FilterGraph); #endif hr = m_FilterGraph.AddSourceFilterForMoniker(dev.Mon, null, dev.Name, out capFilter); DsError.ThrowExceptionForHR(hr); m_pinStill = DsFindPin.ByCategory(capFilter, PinCategory.Still, 0); if (m_pinStill == null) { m_pinStill = DsFindPin.ByCategory(capFilter, PinCategory.Preview, 0); } if (m_pinStill == null) { IPin pRaw = null; IPin pSmart = null; m_VidControl = null; IBaseFilter iSmartTee = (IBaseFilter) new SmartTee(); try { hr = m_FilterGraph.AddFilter(iSmartTee, "SmartTee"); DsError.ThrowExceptionForHR(hr); pRaw = DsFindPin.ByCategory(capFilter, PinCategory.Capture, 0); pSmart = DsFindPin.ByDirection(iSmartTee, PinDirection.Input, 0); hr = m_FilterGraph.Connect(pRaw, pSmart); DsError.ThrowExceptionForHR(hr); m_pinStill = DsFindPin.ByName(iSmartTee, "Preview"); pCaptureOut = DsFindPin.ByName(iSmartTee, "Capture"); if (iHeight + iWidth + iBPP > 0) { SetConfigParms(pRaw, iWidth, iHeight, iBPP); } } finally { if (pRaw != null) { Marshal.ReleaseComObject(pRaw); } if (pRaw != pSmart) { Marshal.ReleaseComObject(pSmart); } if (pRaw != iSmartTee) { Marshal.ReleaseComObject(iSmartTee); } } } else { m_VidControl = capFilter as IAMVideoControl; pCaptureOut = DsFindPin.ByCategory(capFilter, PinCategory.Capture, 0); if (iHeight + iWidth + iBPP > 0) { SetConfigParms(m_pinStill, iWidth, iHeight, iBPP); } } sampGrabber = new SampleGrabber() as ISampleGrabber; IBaseFilter baseGrabFlt = sampGrabber as IBaseFilter; ConfigureSampleGrabber(sampGrabber); pSampleIn = DsFindPin.ByDirection(baseGrabFlt, PinDirection.Input, 0); IBaseFilter pRenderer = new VideoRendererDefault() as IBaseFilter; hr = m_FilterGraph.AddFilter(pRenderer, "Renderer"); DsError.ThrowExceptionForHR(hr); pRenderIn = DsFindPin.ByDirection(pRenderer, PinDirection.Input, 0); hr = m_FilterGraph.AddFilter(baseGrabFlt, "Ds.NET Grabber"); DsError.ThrowExceptionForHR(hr); if (m_VidControl == null) { hr = m_FilterGraph.Connect(m_pinStill, pSampleIn); DsError.ThrowExceptionForHR(hr); hr = m_FilterGraph.Connect(pCaptureOut, pRenderIn); DsError.ThrowExceptionForHR(hr); } else { hr = m_FilterGraph.Connect(pCaptureOut, pRenderIn); DsError.ThrowExceptionForHR(hr); hr = m_FilterGraph.Connect(m_pinStill, pSampleIn); DsError.ThrowExceptionForHR(hr); } SaveSizeInfo(sampGrabber); IMediaControl mediaCtrl = m_FilterGraph as IMediaControl; hr = mediaCtrl.Run(); DsError.ThrowExceptionForHR(hr); } finally { if (sampGrabber != null) { Marshal.ReleaseComObject(sampGrabber); sampGrabber = null; } if (pCaptureOut != null) { Marshal.ReleaseComObject(pCaptureOut); pCaptureOut = null; } if (pRenderIn != null) { Marshal.ReleaseComObject(pRenderIn); pRenderIn = null; } if (pSampleIn != null) { Marshal.ReleaseComObject(pSampleIn); pSampleIn = null; } } }
public void PrepareCapture(int i_width, int i_height, float i_frame_rate) { const int BBP = 32; //既にキャプチャ中なら諦める。 if (this.m_graphi_active) { throw new Exception(); } //現在確保中のグラフインスタンスを全て削除 CleanupGraphiObjects(); int hr; ISampleGrabber sampGrabber = null; IBaseFilter capFilter = null; IPin pSampleIn = null; //グラフビルダを作る。 this.m_FilterGraph = new FilterGraph() as IFilterGraph2; try { //フィルタグラフにキャプチャを追加して、capFilterにピンを受け取る。 hr = m_FilterGraph.AddSourceFilterForMoniker(this.m_dev.Mon, null, this.m_dev.Name, out capFilter); DsError.ThrowExceptionForHR(hr); //stillピンを探す m_pinStill = DsFindPin.ByCategory(capFilter, PinCategory.Still, 0); //stillピンが無ければPreviewを探す。 if (m_pinStill == null) { m_pinStill = DsFindPin.ByCategory(capFilter, PinCategory.Preview, 0); } // Still haven't found one. Need to put a splitter in so we have // one stream to capture the bitmap from, and one to display. Ok, we // don't *have* to do it that way, but we are going to anyway. if (m_pinStill == null) { // There is no still pin m_VidControl = null; m_pinStill = DsFindPin.ByCategory(capFilter, PinCategory.Capture, 0); } else { // Get a control pointer (used in Click()) m_VidControl = capFilter as IAMVideoControl; m_pinStill = DsFindPin.ByCategory(capFilter, PinCategory.Capture, 0); } if (i_height + i_width + BBP > 0) { SetConfigParms(m_pinStill, i_width, i_height, i_frame_rate, BBP); } // Get the SampleGrabber interface sampGrabber = new SampleGrabber() as ISampleGrabber; //sampGrabberの設定 IBaseFilter baseGrabFlt = sampGrabber as IBaseFilter; ConfigureSampleGrabber(sampGrabber); pSampleIn = DsFindPin.ByDirection(baseGrabFlt, PinDirection.Input, 0); // Add the sample grabber to the graph hr = m_FilterGraph.AddFilter(baseGrabFlt, "Ds.NET Grabber"); DsError.ThrowExceptionForHR(hr); if (m_VidControl == null) { // Connect the Still pin to the sample grabber hr = m_FilterGraph.Connect(m_pinStill, pSampleIn); DsError.ThrowExceptionForHR(hr); } else { // Connect the Still pin to the sample grabber hr = m_FilterGraph.Connect(m_pinStill, pSampleIn); DsError.ThrowExceptionForHR(hr); } hr = sampGrabber.GetConnectedMediaType(this._capture_mediatype); DsError.ThrowExceptionForHR(hr); //ビデオフォーマット等の更新 upateVideoInfo(sampGrabber); } finally { if (sampGrabber != null) { Marshal.ReleaseComObject(sampGrabber); sampGrabber = null; } if (pSampleIn != null) { Marshal.ReleaseComObject(pSampleIn); pSampleIn = null; } } }
/// <summary> build the capture graph for grabber. </summary> private void SetupGraph(DsDevice dev, int iSampleRate, int iChannels) { int hr; ISampleGrabber sampGrabber = null; IBaseFilter capFilter = null; ICaptureGraphBuilder2 capGraph = null; IBaseFilter baseGrabFlt = null; IBaseFilter nullrenderer = null; IMediaFilter mediaFilt = m_FilterGraph as IMediaFilter; // Get the graphbuilder object m_FilterGraph = (IFilterGraph2) new FilterGraph(); m_mediaCtrl = m_FilterGraph as IMediaControl; try { // Get the ICaptureGraphBuilder2 capGraph = (ICaptureGraphBuilder2) new CaptureGraphBuilder2(); // Get the SampleGrabber interface sampGrabber = (ISampleGrabber) new SampleGrabber(); // Start building the graph hr = capGraph.SetFiltergraph(m_FilterGraph); DsError.ThrowExceptionForHR(hr); // Add the audio device hr = m_FilterGraph.AddSourceFilterForMoniker(dev.Mon, null, "Audio input", out capFilter); DsError.ThrowExceptionForHR(hr); // If any of the default config items are set if (iSampleRate + iChannels > 0) { SetConfigParms(capGraph, capFilter, iSampleRate, iChannels); } // Get the SampleGrabber interface sampGrabber = new SampleGrabber() as ISampleGrabber; baseGrabFlt = sampGrabber as IBaseFilter; ConfigureSampleGrabber(sampGrabber); // Add the frame grabber to the graph hr = m_FilterGraph.AddFilter(baseGrabFlt, "Ds.NET Grabber"); DsError.ThrowExceptionForHR(hr); // --------------------------------- // Connect the file filter to the sample grabber // Hopefully this will be the audio pin, we could check by reading it's mediatype IPin iPinOut = DsFindPin.ByDirection(capFilter, PinDirection.Output, 0); // Get the input pin from the sample grabber IPin iPinIn = DsFindPin.ByDirection(baseGrabFlt, PinDirection.Input, 0); hr = m_FilterGraph.Connect(iPinOut, iPinIn); DsError.ThrowExceptionForHR(hr); // Add the null renderer to the graph nullrenderer = new NullRenderer() as IBaseFilter; hr = m_FilterGraph.AddFilter(nullrenderer, "Null renderer"); DsError.ThrowExceptionForHR(hr); // --------------------------------- // Connect the sample grabber to the null renderer iPinOut = DsFindPin.ByDirection(baseGrabFlt, PinDirection.Output, 0); iPinIn = DsFindPin.ByDirection(nullrenderer, PinDirection.Input, 0); hr = m_FilterGraph.Connect(iPinOut, iPinIn); DsError.ThrowExceptionForHR(hr); // Read and cache the resulting settings SaveSizeInfo(sampGrabber); } finally { if (capFilter != null) { Marshal.ReleaseComObject(capFilter); capFilter = null; } if (sampGrabber != null) { Marshal.ReleaseComObject(sampGrabber); sampGrabber = null; } if (capGraph != null) { Marshal.ReleaseComObject(capGraph); capGraph = null; } } }
/// <summary> build the capture graph for grabber. </summary> private void SetupGraph(DsDevice dev, int iWidth, int iHeight, short iBPP, Control hControl) { int hr; ISampleGrabber sampGrabber = null; IBaseFilter capFilter = null; IPin pCaptureOut = null; IPin pSampleIn = null; IPin pRenderIn = null; // Get the graphbuilder object m_FilterGraph = new FilterGraph() as IFilterGraph2; try { #if DEBUG m_rot = new DsROTEntry(m_FilterGraph); #endif // add the video input device hr = m_FilterGraph.AddSourceFilterForMoniker(dev.Mon, null, dev.Name, out capFilter); DsError.ThrowExceptionForHR(hr); // Find the still pin m_pinStill = DsFindPin.ByCategory(capFilter, PinCategory.Still, 0); // Didn't find one. Is there a preview pin? if (m_pinStill == null) { m_pinStill = DsFindPin.ByCategory(capFilter, PinCategory.Preview, 0); } // Still haven't found one. Need to put a splitter in so we have // one stream to capture the bitmap from, and one to display. Ok, we // don't *have* to do it that way, but we are going to anyway. if (m_pinStill == null) { IPin pRaw = null; IPin pSmart = null; // There is no still pin m_VidControl = null; // Add a splitter IBaseFilter iSmartTee = (IBaseFilter) new SmartTee(); try { hr = m_FilterGraph.AddFilter(iSmartTee, "SmartTee"); DsError.ThrowExceptionForHR(hr); // Find the find the capture pin from the video device and the // input pin for the splitter, and connnect them pRaw = DsFindPin.ByCategory(capFilter, PinCategory.Capture, 0); pSmart = DsFindPin.ByDirection(iSmartTee, PinDirection.Input, 0); hr = m_FilterGraph.Connect(pRaw, pSmart); DsError.ThrowExceptionForHR(hr); // Now set the capture and still pins (from the splitter) m_pinStill = DsFindPin.ByName(iSmartTee, "Preview"); pCaptureOut = DsFindPin.ByName(iSmartTee, "Capture"); // If any of the default config items are set, perform the config // on the actual video device (rather than the splitter) if (iHeight + iWidth + iBPP > 0) { SetConfigParms(pRaw, iWidth, iHeight, iBPP); } } finally { if (pRaw != null) { Marshal.ReleaseComObject(pRaw); } if (pRaw != pSmart) { Marshal.ReleaseComObject(pSmart); } if (pRaw != iSmartTee) { Marshal.ReleaseComObject(iSmartTee); } } } else { // Get a control pointer (used in Click()) m_VidControl = capFilter as IAMVideoControl; pCaptureOut = DsFindPin.ByCategory(capFilter, PinCategory.Capture, 0); // If any of the default config items are set if (iHeight + iWidth + iBPP > 0) { SetConfigParms(m_pinStill, iWidth, iHeight, iBPP); } } // Get the SampleGrabber interface sampGrabber = new SampleGrabber() as ISampleGrabber; // Configure the sample grabber IBaseFilter baseGrabFlt = sampGrabber as IBaseFilter; ConfigureSampleGrabber(sampGrabber); pSampleIn = DsFindPin.ByDirection(baseGrabFlt, PinDirection.Input, 0); // Get the default video renderer IBaseFilter pRenderer = new VideoRendererDefault() as IBaseFilter; hr = m_FilterGraph.AddFilter(pRenderer, "Renderer"); DsError.ThrowExceptionForHR(hr); pRenderIn = DsFindPin.ByDirection(pRenderer, PinDirection.Input, 0); // Add the sample grabber to the graph hr = m_FilterGraph.AddFilter(baseGrabFlt, "Ds.NET Grabber"); DsError.ThrowExceptionForHR(hr); if (m_VidControl == null) { // Connect the Still pin to the sample grabber hr = m_FilterGraph.Connect(m_pinStill, pSampleIn); DsError.ThrowExceptionForHR(hr); // Connect the capture pin to the renderer hr = m_FilterGraph.Connect(pCaptureOut, pRenderIn); DsError.ThrowExceptionForHR(hr); } else { // Connect the capture pin to the renderer hr = m_FilterGraph.Connect(pCaptureOut, pRenderIn); DsError.ThrowExceptionForHR(hr); // Connect the Still pin to the sample grabber hr = m_FilterGraph.Connect(m_pinStill, pSampleIn); DsError.ThrowExceptionForHR(hr); } // Learn the video properties SaveSizeInfo(sampGrabber); ConfigVideoWindow(hControl); // Start the graph IMediaControl mediaCtrl = m_FilterGraph as IMediaControl; hr = mediaCtrl.Run(); DsError.ThrowExceptionForHR(hr); } finally { if (sampGrabber != null) { Marshal.ReleaseComObject(sampGrabber); sampGrabber = null; } if (pCaptureOut != null) { Marshal.ReleaseComObject(pCaptureOut); pCaptureOut = null; } if (pRenderIn != null) { Marshal.ReleaseComObject(pRenderIn); pRenderIn = null; } if (pSampleIn != null) { Marshal.ReleaseComObject(pSampleIn); pSampleIn = null; } } }
private void SetupGraph(Control hWin) { if (theCaptureDevice == null) return; int hr; IBaseFilter ibfRenderer = null; ISampleGrabber sampGrabber = null; IBaseFilter capFilter = null; IPin iPinInFilter = null; IPin iPinOutFilter = null; IPin iPinInDest = null; // Get the graphbuilder object m_FilterGraph = new FilterGraph() as IFilterGraph2; //#if DEBUG // m_rot = new DsROTEntry(m_FilterGraph); //#endif try { // Add the video input device to the graph hr = m_FilterGraph.AddFilter(theCaptureDevice, "source filter"); DsError.ThrowExceptionForHR(hr); if (captureDeviceCrossbar != null) { // Add the video inputs' crossbar to the graph hr = m_FilterGraph.AddFilter(captureDeviceCrossbar, "source crossbar"); DsError.ThrowExceptionForHR(hr); //// Get crossbars's output IPin iPinOutCrossbar = DsFindPin.ByDirection(captureDeviceCrossbar, PinDirection.Output, 0); m_FilterGraph.Render(iPinOutCrossbar); } // Get input device's output iPinOutSource = DsFindPin.ByDirection(theCaptureDevice, PinDirection.Output, 0); //DisplayPropertyPageForCapturePin(IntPtr.Zero); //m_FilterGraph.Render(iPinOutSource); //// Get the SampleGrabber interface //sampGrabber = new SampleGrabber() as ISampleGrabber; //IBaseFilter baseGrabFlt = sampGrabber as IBaseFilter; //ConfigureSampleGrabber(sampGrabber); //iPinInFilter = DsFindPin.ByDirection(baseGrabFlt, PinDirection.Input, 0); //iPinOutFilter = DsFindPin.ByDirection(baseGrabFlt, PinDirection.Output, 0); //// Add the frame grabber to the graph //hr = m_FilterGraph.AddFilter(baseGrabFlt, "Ds.NET Grabber"); //DsError.ThrowExceptionForHR(hr); //hr = m_FilterGraph.Connect(iPinOutSource, iPinInFilter); //DsError.ThrowExceptionForHR(hr); //m_FilterGraph.Render(iPinOutSource); ibfRenderer = (IBaseFilter)new VideoRendererDefault(); // Add it to the graph hr = m_FilterGraph.AddFilter(ibfRenderer, "Ds.NET VideoRendererDefault"); DsError.ThrowExceptionForHR(hr); iPinInDest = DsFindPin.ByDirection(ibfRenderer, PinDirection.Input, 0); // Connect the graph. Many other filters automatically get added here hr = m_FilterGraph.Connect(iPinOutSource, iPinInDest); DsError.ThrowExceptionForHR(hr); IVideoWindow videoWindow = m_FilterGraph as IVideoWindow; hr = videoWindow.put_Owner(hWin.Handle); DsError.ThrowExceptionForHR(hr); hr = videoWindow.put_WindowStyle(WindowStyle.Child | WindowStyle.ClipChildren | WindowStyle.ClipSiblings); DsError.ThrowExceptionForHR(hr); hr = videoWindow.put_Visible(OABool.True); DsError.ThrowExceptionForHR(hr); Rectangle rc = hWin.ClientRectangle; hr = videoWindow.SetWindowPosition(0, 0, rc.Right, rc.Bottom); DsError.ThrowExceptionForHR(hr); //// Add the video source ////hr = m_FilterGraph.AddSourceFilter(FileName, "Ds.NET FileFilter", out capFilter); ////DsError.ThrowExceptionForHR(hr); //// Hopefully this will be the video pin //IPin iPinOutSource = DsFindPin.ByDirection(theCaptureDevice, PinDirection.Output, 0); //IBaseFilter baseGrabFlt = sampGrabber as IBaseFilter; //ConfigureSampleGrabber(sampGrabber); //iPinInFilter = DsFindPin.ByDirection(baseGrabFlt, PinDirection.Input, 0); //iPinOutFilter = DsFindPin.ByDirection(baseGrabFlt, PinDirection.Output, 0); //// Add the frame grabber to the graph //hr = m_FilterGraph.AddFilter(baseGrabFlt, "Ds.NET Grabber"); //DsError.ThrowExceptionForHR(hr); //hr = m_FilterGraph.Connect(iPinOutSource, iPinInFilter); //DsError.ThrowExceptionForHR(hr); //// Get the default video renderer //ibfRenderer = (IBaseFilter)new VideoRendererDefault(); //// Add it to the graph //hr = m_FilterGraph.AddFilter(ibfRenderer, "Ds.NET VideoRendererDefault"); //DsError.ThrowExceptionForHR(hr); //iPinInDest = DsFindPin.ByDirection(ibfRenderer, PinDirection.Input, 0); //// Connect the graph. Many other filters automatically get added here //hr = m_FilterGraph.Connect(iPinOutSource, iPinInDest); //DsError.ThrowExceptionForHR(hr); //SaveSizeInfo(sampGrabber); } finally { if (theCaptureDevice != null) { Marshal.ReleaseComObject(theCaptureDevice); theCaptureDevice = null; } if (capFilter != null) { Marshal.ReleaseComObject(capFilter); capFilter = null; } if (sampGrabber != null) { Marshal.ReleaseComObject(sampGrabber); sampGrabber = null; } if (ibfRenderer != null) { Marshal.ReleaseComObject(ibfRenderer); ibfRenderer = null; } if (iPinInFilter != null) { Marshal.ReleaseComObject(iPinInFilter); iPinInFilter = null; } if (iPinOutFilter != null) { Marshal.ReleaseComObject(iPinOutFilter); iPinOutFilter = null; } if (iPinInDest != null) { Marshal.ReleaseComObject(iPinInDest); iPinInDest = null; } } }
private void StartCapture() { int hr; ISampleGrabber sampGrabber = null; IBaseFilter capFilter = null; ICaptureGraphBuilder2 capGraph = null; if (System.IO.File.Exists(txtAviFileName.Text)) { // Get the graphbuilder object m_FilterGraph = (IFilterGraph2) new FilterGraph(); m_mediaCtrl = m_FilterGraph as IMediaControl; // Get the ICaptureGraphBuilder2 capGraph = (ICaptureGraphBuilder2) new CaptureGraphBuilder2(); // Get the SampleGrabber interface sampGrabber = (ISampleGrabber) new SampleGrabber(); // Start building the graph hr = capGraph.SetFiltergraph(m_FilterGraph); DsError.ThrowExceptionForHR(hr); // Add the video source hr = m_FilterGraph.AddSourceFilter(txtAviFileName.Text, "File Source (Async.)", out capFilter); DsError.ThrowExceptionForHR(hr); //add AVI Decompressor IBaseFilter pAVIDecompressor = (IBaseFilter) new AVIDec(); hr = m_FilterGraph.AddFilter(pAVIDecompressor, "AVI Decompressor"); DsError.ThrowExceptionForHR(hr); IBaseFilter ffdshow; try { // Create Decoder filter COM object (ffdshow video decoder) Type comtype = Type.GetTypeFromCLSID(new Guid("{04FE9017-F873-410E-871E-AB91661A4EF7}")); if (comtype == null) { throw new NotSupportedException("Creating ffdshow video decoder COM object fails."); } object comobj = Activator.CreateInstance(comtype); ffdshow = (IBaseFilter)comobj; // error ocurrs! raised exception comobj = null; } catch { CustomMessageBox.Show("Please install/reinstall ffdshow"); return; } hr = m_FilterGraph.AddFilter(ffdshow, "ffdshow"); DsError.ThrowExceptionForHR(hr); // IBaseFilter baseGrabFlt = (IBaseFilter)sampGrabber; ConfigureSampleGrabber(sampGrabber); // Add the frame grabber to the graph hr = m_FilterGraph.AddFilter(baseGrabFlt, "Ds.NET Grabber"); DsError.ThrowExceptionForHR(hr); IBaseFilter vidrender = (IBaseFilter) new VideoRenderer(); hr = m_FilterGraph.AddFilter(vidrender, "Render"); DsError.ThrowExceptionForHR(hr); IPin captpin = DsFindPin.ByDirection(capFilter, PinDirection.Output, 0); IPin ffdpinin = DsFindPin.ByName(ffdshow, "In"); IPin ffdpinout = DsFindPin.ByName(ffdshow, "Out"); IPin samppin = DsFindPin.ByName(baseGrabFlt, "Input"); hr = m_FilterGraph.Connect(captpin, ffdpinin); DsError.ThrowExceptionForHR(hr); hr = m_FilterGraph.Connect(ffdpinout, samppin); DsError.ThrowExceptionForHR(hr); FileWriter filewritter = new FileWriter(); IFileSinkFilter filemux = (IFileSinkFilter)filewritter; //filemux.SetFileName("test.avi",); //hr = capGraph.RenderStream(null, MediaType.Video, capFilter, null, vidrender); // DsError.ThrowExceptionForHR(hr); SaveSizeInfo(sampGrabber); // setup buffer if (m_handle == IntPtr.Zero) { m_handle = Marshal.AllocCoTaskMem(m_stride * m_videoHeight); } // tell the callback to ignore new images m_PictureReady = new ManualResetEvent(false); m_bGotOne = false; m_bRunning = false; timer1 = new Thread(timer); timer1.IsBackground = true; timer1.Start(); m_mediaextseek = m_FilterGraph as IAMExtendedSeeking; m_mediapos = m_FilterGraph as IMediaPosition; m_mediaseek = m_FilterGraph as IMediaSeeking; double length = 0; m_mediapos.get_Duration(out length); trackBar_mediapos.Minimum = 0; trackBar_mediapos.Maximum = (int)length; Start(); } else { MessageBox.Show("File does not exist"); } }
// Build the capture graph for grabber and renderer.</summary> // (Control to show video in, Filename to play) private void SetupGraph(Control hWin, string FileName) { int hr; IBaseFilter ibfRenderer = null; IPin iPinInFilter = null; IPin iPinOutFilter = null; IPin iPinInDest = null; m_FilterGraph = new FilterGraph() as IFilterGraph2; ICaptureGraphBuilder2 icgb2 = new CaptureGraphBuilder2() as ICaptureGraphBuilder2; try { hr = icgb2.SetFiltergraph(m_FilterGraph); DsError.ThrowExceptionForHR(hr); IBaseFilter sourceFilter = null; hr = m_FilterGraph.AddSourceFilter(FileName, "Ds.NET FileFilter", out sourceFilter); DsError.ThrowExceptionForHR(hr); // Hopefully this will be the video pin IPin iPinOutSource = DsFindPin.ByDirection(sourceFilter, PinDirection.Output, 0); // Get the SampleGrabber interface m_sampGrabber = (ISampleGrabber)new SampleGrabber(); IBaseFilter baseGrabFlt = (IBaseFilter)m_sampGrabber; // Configure the Sample Grabber ConfigureSampleGrabber(m_sampGrabber); iPinInFilter = DsFindPin.ByDirection(baseGrabFlt, PinDirection.Input, 0); iPinOutFilter = DsFindPin.ByDirection(baseGrabFlt, PinDirection.Output, 0); // Add it to the filter hr = m_FilterGraph.AddFilter(baseGrabFlt, "Ds.NET Grabber"); DsError.ThrowExceptionForHR(hr); hr = m_FilterGraph.Connect(iPinOutSource, iPinInFilter); DsError.ThrowExceptionForHR(hr); // Get the default video renderer ibfRenderer = (IBaseFilter)new VideoRendererDefault(); // Add it to the graph hr = m_FilterGraph.AddFilter(ibfRenderer, "Ds.NET VideoRendererDefault"); DsError.ThrowExceptionForHR(hr); iPinInDest = DsFindPin.ByDirection(ibfRenderer, PinDirection.Input, 0); // Connect the graph. Many other filters automatically get added here hr = m_FilterGraph.Connect(iPinOutFilter, iPinInDest); DsError.ThrowExceptionForHR(hr); // Configure the Video Window IVideoWindow videoWindow = m_FilterGraph as IVideoWindow; ConfigureVideoWindow(videoWindow, hWin); // Grab some other interfaces m_mediaEvent = m_FilterGraph as IMediaEvent; m_mediaCtrl = m_FilterGraph as IMediaControl; m_mediaPosition = m_FilterGraph as IMediaPosition; } finally { if (icgb2 != null) { Marshal.ReleaseComObject(icgb2); icgb2 = null; } } }