/// <summary> /// Completely tear down a filter graph and /// release all associated resources. /// </summary> protected void DestroyGraph() { // Derender the graph (This will stop the graph // and release preview window. It also destroys // half of the graph which is unnecessary but // harmless here.) (ignore errors) try { DerenderGraph(); } catch { } // Update the state after derender because it // depends on correct status. But we also want to // update the state as early as possible in case // of error. ActualGraphState = GraphState.Null; IsPreviewRendered = false; // Remove filters from the graph // This should be unnecessary but the Nvidia WDM // video driver cannot be used by this application // again unless we remove it. Ideally, we should // simply enumerate all the filters in the graph // and remove them. (ignore errors) if (VideoCompressorFilter != null) { GraphBuilder.RemoveFilter(VideoCompressorFilter); } if (VideoDeviceFilter != null) { GraphBuilder.RemoveFilter(VideoDeviceFilter); } // Cleanup if (GraphBuilder != null) { Marshal.ReleaseComObject(GraphBuilder); } GraphBuilder = null; if (CaptureGraphBuilder != null) { Marshal.ReleaseComObject(CaptureGraphBuilder); } CaptureGraphBuilder = null; if (VideoDeviceFilter != null) { Marshal.ReleaseComObject(VideoDeviceFilter); } VideoDeviceFilter = null; if (VideoCompressorFilter != null) { Marshal.ReleaseComObject(VideoCompressorFilter); } VideoCompressorFilter = null; // These are copies of graphBuilder MediaControl = null; VideoWindow = null; // For unmanaged objects we haven't released explicitly GC.Collect(); }
/// <summary> /// Create a new filter graph and add filters (devices, compressors, misc), /// but leave the filters unconnected. Call RenderGraph() /// to connect the filters. /// </summary> protected void CreateGraph() { //Skip if already created if ((int)ActualGraphState < (int)GraphState.Created) { // Make a new filter graph GraphBuilder = (ExtendStreaming.IGraphBuilder)Activator.CreateInstance(Type.GetTypeFromCLSID(Uuid.Clsid.FilterGraph, true)); // Get the Capture Graph Builder var clsid = Uuid.Clsid.CaptureGraphBuilder2; var riid = typeof(ExtendStreaming.ICaptureGraphBuilder2).GUID; CaptureGraphBuilder = (ExtendStreaming.ICaptureGraphBuilder2)Workaround.CreateDsInstance(ref clsid, ref riid); // Link the CaptureGraphBuilder to the filter graph var hr = CaptureGraphBuilder.SetFiltergraph(GraphBuilder); if (hr < 0) { Marshal.ThrowExceptionForHR(hr); } var comType = Type.GetTypeFromCLSID(Uuid.Clsid.SampleGrabber); if (comType == null) { throw new NotImplementedException(@"DirectShow SampleGrabber not installed/registered!"); } var comObj = Activator.CreateInstance(comType); SampGrabber = (EditStreaming.ISampleGrabber)comObj; comObj = null; _baseGrabFlt = (CoreStreaming.IBaseFilter)SampGrabber; var media = new CoreStreaming.AMMediaType(); // Get the video device and add it to the filter graph if (VideoDevice != null) { VideoDeviceFilter = (CoreStreaming.IBaseFilter)Marshal.BindToMoniker(VideoDevice.MonikerString); hr = GraphBuilder.AddFilter(VideoDeviceFilter, "Video Capture Device"); if (hr < 0) { Marshal.ThrowExceptionForHR(hr); } media.majorType = Uuid.MediaType.Video; media.subType = Uuid.MediaSubType.RGB32; //RGB24; media.formatType = Uuid.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 object o; var cat = Uuid.PinCategory.Capture; var med = Uuid.MediaType.Interleaved; var iid = typeof(ExtendStreaming.IAMStreamConfig).GUID; hr = CaptureGraphBuilder.FindInterface(ref cat, ref med, VideoDeviceFilter, ref iid, out o); if (hr != 0) { // If not found, try looking for a video media type med = Uuid.MediaType.Video; hr = CaptureGraphBuilder.FindInterface(ref cat, ref med, VideoDeviceFilter, ref iid, out o); if (hr != 0) { o = null; } } VideoStreamConfig = o as ExtendStreaming.IAMStreamConfig; // Retreive the media control interface (for starting/stopping graph) MediaControl = (ControlStreaming.IMediaControl)GraphBuilder; // Reload any video crossbars //if (videoSources != null) videoSources.Dispose(); videoSources = null; _videoInfoHeader = (EditStreaming.VideoInfoHeader)Marshal.PtrToStructure(media.formatPtr, typeof(EditStreaming.VideoInfoHeader)); Marshal.FreeCoTaskMem(media.formatPtr); media.formatPtr = IntPtr.Zero; hr = SampGrabber.SetBufferSamples(false); 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; }
/// <summary> /// Completely tear down a filter graph and /// release all associated resources. /// </summary> protected void DestroyGraph() { // Derender the graph (This will stop the graph // and release preview window. It also destroys // half of the graph which is unnecessary but // harmless here.) (ignore errors) try { DerenderGraph(); } catch { } // Update the state after derender because it // depends on correct status. But we also want to // update the state as early as possible in case // of error. ActualGraphState = GraphState.Null; IsPreviewRendered = false; // Remove filters from the graph // This should be unnecessary but the Nvidia WDM // video driver cannot be used by this application // again unless we remove it. Ideally, we should // simply enumerate all the filters in the graph // and remove them. (ignore errors) if (VideoCompressorFilter != null) GraphBuilder.RemoveFilter(VideoCompressorFilter); if (VideoDeviceFilter != null) GraphBuilder.RemoveFilter(VideoDeviceFilter); // Cleanup if (GraphBuilder != null) Marshal.ReleaseComObject(GraphBuilder); GraphBuilder = null; if (CaptureGraphBuilder != null) Marshal.ReleaseComObject(CaptureGraphBuilder); CaptureGraphBuilder = null; if (VideoDeviceFilter != null) Marshal.ReleaseComObject(VideoDeviceFilter); VideoDeviceFilter = null; if (VideoCompressorFilter != null) Marshal.ReleaseComObject(VideoCompressorFilter); VideoCompressorFilter = null; // These are copies of graphBuilder MediaControl = null; VideoWindow = null; // For unmanaged objects we haven't released explicitly GC.Collect(); }
/// <summary> /// Create a new filter graph and add filters (devices, compressors, misc), /// but leave the filters unconnected. Call RenderGraph() /// to connect the filters. /// </summary> protected void CreateGraph() { //Skip if already created if ((int)ActualGraphState < (int)GraphState.Created) { // Make a new filter graph GraphBuilder = (ExtendStreaming.IGraphBuilder)Activator.CreateInstance(Type.GetTypeFromCLSID(Uuid.Clsid.FilterGraph, true)); // Get the Capture Graph Builder Guid clsid = Uuid.Clsid.CaptureGraphBuilder2; Guid riid = typeof(ExtendStreaming.ICaptureGraphBuilder2).GUID; CaptureGraphBuilder = (ExtendStreaming.ICaptureGraphBuilder2)Workaround.CreateDsInstance(ref clsid, ref riid); // Link the CaptureGraphBuilder to the filter graph int hr = CaptureGraphBuilder.SetFiltergraph(GraphBuilder); if (hr < 0) Marshal.ThrowExceptionForHR(hr); Type comType = Type.GetTypeFromCLSID(Uuid.Clsid.SampleGrabber); if (comType == null) throw new NotImplementedException(@"DirectShow SampleGrabber not installed/registered!"); object comObj = Activator.CreateInstance(comType); SampGrabber = (EditStreaming.ISampleGrabber)comObj; comObj = null; _baseGrabFlt = (CoreStreaming.IBaseFilter)SampGrabber; var media = new CoreStreaming.AMMediaType(); // Get the video device and add it to the filter graph if (VideoDevice != null) { VideoDeviceFilter = (CoreStreaming.IBaseFilter)Marshal.BindToMoniker(VideoDevice.MonikerString); hr = GraphBuilder.AddFilter(VideoDeviceFilter, "Video Capture Device"); if (hr < 0) Marshal.ThrowExceptionForHR(hr); media.majorType = Uuid.MediaType.Video; media.subType = Uuid.MediaSubType.RGB32;//RGB24; media.formatType = Uuid.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 object o; Guid cat = Uuid.PinCategory.Capture; Guid med = Uuid.MediaType.Interleaved; Guid iid = typeof(ExtendStreaming.IAMStreamConfig).GUID; hr = CaptureGraphBuilder.FindInterface(ref cat, ref med, VideoDeviceFilter, ref iid, out o); if (hr != 0) { // If not found, try looking for a video media type med = Uuid.MediaType.Video; hr = CaptureGraphBuilder.FindInterface( ref cat, ref med, VideoDeviceFilter, ref iid, out o); if (hr != 0) o = null; } VideoStreamConfig = o as ExtendStreaming.IAMStreamConfig; // Retreive the media control interface (for starting/stopping graph) MediaControl = (ControlStreaming.IMediaControl)GraphBuilder; // Reload any video crossbars //if (videoSources != null) videoSources.Dispose(); videoSources = null; _videoInfoHeader = (EditStreaming.VideoInfoHeader)Marshal.PtrToStructure(media.formatPtr, typeof(EditStreaming.VideoInfoHeader)); Marshal.FreeCoTaskMem(media.formatPtr); media.formatPtr = IntPtr.Zero; hr = SampGrabber.SetBufferSamples(false); 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; }