/// <summary> /// Connects the filters of a previously created graph /// (created by CreateGraph()). Once rendered the graph /// is ready to be used. This method may also destroy /// streams if we have streams we no longer want. /// </summary> void RenderGraph() { var didSomething = false; // Stop the graph _mediaControl?.Stop(); // Create the graph if needed (group should already be created) CreateGraph(); // Derender the graph if we have a capture or preview stream // that we no longer want. We can't derender the capture and // preview streams seperately. // Notice the second case will leave a capture stream intact // even if we no longer want it. This allows the user that is // not using the preview to Stop() and Start() without // rerendering the graph. if (!_wantPreviewRendered && _isPreviewRendered) { DerenderGraph(); } // Render preview stream (only if necessary) if (_wantPreviewRendered && !_isPreviewRendered) { // Render preview (video -> renderer) var cat = PinCategory.Preview; var med = MediaType.Video; var hr = _captureGraphBuilder.RenderStream(cat, med, _videoDeviceFilter, _baseGrabFlt, null); if (hr < 0) { Marshal.ThrowExceptionForHR(hr); } // Get the IVideoWindow interface _videoWindow = (IVideoWindow)_graphBuilder; // Set the video window to be a child of the main window hr = _videoWindow.put_Owner(PreviewWindow); if (hr < 0) { Marshal.ThrowExceptionForHR(hr); } // Set video window style hr = _videoWindow.put_WindowStyle(WindowStyle.Child | WindowStyle.ClipChildren | WindowStyle.ClipSiblings); if (hr < 0) { Marshal.ThrowExceptionForHR(hr); } // Make the video window visible, now that it is properly positioned hr = _videoWindow.put_Visible(OABool.True); if (hr < 0) { Marshal.ThrowExceptionForHR(hr); } _isPreviewRendered = true; didSomething = true; var media = new AMMediaType(); hr = _sampGrabber.GetConnectedMediaType(media); if (hr < 0) { Marshal.ThrowExceptionForHR(hr); } if (media.formatType != FormatType.VideoInfo || media.formatPtr == IntPtr.Zero) { throw new NotSupportedException("Unknown Grabber Media Format"); } _videoInfoHeader = (VideoInfoHeader)Marshal.PtrToStructure(media.formatPtr, typeof(VideoInfoHeader)); Marshal.FreeCoTaskMem(media.formatPtr); media.formatPtr = IntPtr.Zero; } if (didSomething) { _actualGraphState = GraphState.Rendered; } }
/// <summary> /// Create a new filter graph and add filters (devices, compressors, misc), /// but leave the filters unconnected. Call RenderGraph() /// to connect the filters. /// </summary> void CreateGraph() { //Skip if already created if ((int)_actualGraphState < (int)GraphState.Created) { // Make a new filter graph _graphBuilder = (IGraphBuilder) new FilterGraph(); // Get the Capture Graph Builder _captureGraphBuilder = (ICaptureGraphBuilder2) new CaptureGraphBuilder2(); // Link the CaptureGraphBuilder to the filter graph var hr = _captureGraphBuilder.SetFiltergraph(_graphBuilder); if (hr < 0) { Marshal.ThrowExceptionForHR(hr); } var comObj = new SampleGrabber(); _sampGrabber = (ISampleGrabber)comObj; _baseGrabFlt = (IBaseFilter)_sampGrabber; var media = new AMMediaType(); // Get the video device and add it to the filter graph if (VideoDevice != null) { _videoDeviceFilter = (IBaseFilter)Marshal.BindToMoniker(VideoDevice.MonikerString); hr = _graphBuilder.AddFilter(_videoDeviceFilter, "Video Capture Device"); if (hr < 0) { Marshal.ThrowExceptionForHR(hr); } media.majorType = MediaType.Video; media.subType = MediaSubType.RGB32; //RGB24; media.formatType = FormatType.VideoInfo; media.temporalCompression = true; //New hr = _sampGrabber.SetMediaType(media); if (hr < 0) { Marshal.ThrowExceptionForHR(hr); } hr = _graphBuilder.AddFilter(_baseGrabFlt, "Grabber"); if (hr < 0) { Marshal.ThrowExceptionForHR(hr); } } // Retrieve the stream control interface for the video device // FindInterface will also add any required filters // (WDM devices in particular may need additional // upstream filters to function). // Try looking for an interleaved media type var cat = PinCategory.Capture; var med = MediaType.Interleaved; var iid = typeof(IAMStreamConfig).GUID; hr = _captureGraphBuilder.FindInterface(cat, med, _videoDeviceFilter, iid, out var o); if (hr != 0) { // If not found, try looking for a video media type med = MediaType.Video; hr = _captureGraphBuilder.FindInterface(cat, med, _videoDeviceFilter, iid, out o); if (hr != 0) { // ReSharper disable once RedundantAssignment o = null; } } //VideoStreamConfig = o as IAMStreamConfig; // Retreive the media control interface (for starting/stopping graph) _mediaControl = (IMediaControl)_graphBuilder; // Reload any video crossbars //if (videoSources != null) videoSources.Dispose(); videoSources = null; _videoInfoHeader = Marshal.PtrToStructure <VideoInfoHeader>(media.formatPtr); Marshal.FreeCoTaskMem(media.formatPtr); media.formatPtr = IntPtr.Zero; hr = _sampGrabber.SetBufferSamples(true); if (hr == 0) { hr = _sampGrabber.SetOneShot(false); } if (hr == 0) { hr = _sampGrabber.SetCallback(null, 0); } if (hr < 0) { Marshal.ThrowExceptionForHR(hr); } } // Update the state now that we are done _actualGraphState = GraphState.Created; }