/// <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. graphState = GraphState.Null; isCaptureRendered = false; isPreviewRendered = false; // Remove graph from the ROT if (rotCookie != 0) { DsROT.RemoveGraphFromRot(ref rotCookie); rotCookie = 0; } // 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 (muxFilter != null) graphBuilder.RemoveFilter(muxFilter); if (videoCompressorFilter != null) graphBuilder.RemoveFilter(videoCompressorFilter); if (audioCompressorFilter != null) graphBuilder.RemoveFilter(audioCompressorFilter); if (videoDeviceFilter != null) graphBuilder.RemoveFilter(videoDeviceFilter); if (audioDeviceFilter != null) graphBuilder.RemoveFilter(audioDeviceFilter); // Clean up properties if (videoSources != null) videoSources.Dispose(); videoSources = null; if (audioSources != null) audioSources.Dispose(); audioSources = null; if (propertyPages != null) propertyPages.Dispose(); propertyPages = null; if (tuner != null) tuner.Dispose(); tuner = null; // Cleanup if (graphBuilder != null) Marshal.ReleaseComObject(graphBuilder); graphBuilder = null; if (captureGraphBuilder != null) Marshal.ReleaseComObject(captureGraphBuilder); captureGraphBuilder = null; if (muxFilter != null) Marshal.ReleaseComObject(muxFilter); muxFilter = null; if (fileWriterFilter != null) Marshal.ReleaseComObject(fileWriterFilter); fileWriterFilter = null; if (videoDeviceFilter != null) Marshal.ReleaseComObject(videoDeviceFilter); videoDeviceFilter = null; if (audioDeviceFilter != null) Marshal.ReleaseComObject(audioDeviceFilter); audioDeviceFilter = null; if (videoCompressorFilter != null) Marshal.ReleaseComObject(videoCompressorFilter); videoCompressorFilter = null; if (audioCompressorFilter != null) Marshal.ReleaseComObject(audioCompressorFilter); audioCompressorFilter = null; // These are copies of graphBuilder mediaControl = null; videoWindow = null; // For unmanaged objects we haven't released explicitly GC.Collect(); }
// --------------------- Private Methods ----------------------- /// <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() { Guid cat; Guid med; int hr; Type comType = null; object comObj = null; // Ensure required properties are set if (videoDevice == null && audioDevice == null) throw new ArgumentException("The video and/or audio device have not been set. Please set one or both to valid capture devices.\n"); // Skip if we are already created if ((int)graphState < (int)GraphState.Created) { // Garbage collect, ensure that previous filters are released GC.Collect(); // Make a new filter graph graphBuilder = (IGraphBuilder)Activator.CreateInstance(Type.GetTypeFromCLSID(Clsid.FilterGraph, true)); // Get the Capture Graph Builder Guid clsid = Clsid.CaptureGraphBuilder2; Guid riid = typeof(ICaptureGraphBuilder2).GUID; captureGraphBuilder = (ICaptureGraphBuilder2)DsBugWO.CreateDsInstance(ref clsid, ref riid); // Link the CaptureGraphBuilder to the filter graph hr = captureGraphBuilder.SetFiltergraph(graphBuilder); if (hr < 0) Marshal.ThrowExceptionForHR(hr); comType = Type.GetTypeFromCLSID(Clsid.SampleGrabber); if (comType == null) throw new NotImplementedException(@"DirectShow SampleGrabber not installed/registered!"); comObj = Activator.CreateInstance(comType); sampGrabber = (ISampleGrabber)comObj; comObj = null; baseGrabFlt = (IBaseFilter)sampGrabber; // Add the graph to the Running Object Table so it can be // viewed with GraphEdit #if DEBUG DsROT.AddGraphToRot(graphBuilder, out rotCookie); #endif AMMediaType 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); // Console.WriteLine("MediaEnineCheck ==> Inside StartVideoCapture.cs before MediaSudType"); media.majorType = MediaType.Video; media.subType = MediaSubType.RGB24; //Rajib media.formatType = FormatType.VideoInfo; // ??? hr = sampGrabber.SetMediaType(media); if (hr < 0) Marshal.ThrowExceptionForHR(hr); hr = graphBuilder.AddFilter(baseGrabFlt, "Ds.NET Grabber"); if (hr < 0) Marshal.ThrowExceptionForHR(hr); } // Get the audio device and add it to the filter graph if (AudioDevice != null) { audioDeviceFilter = (IBaseFilter)Marshal.BindToMoniker(AudioDevice.MonikerString); hr = graphBuilder.AddFilter(audioDeviceFilter, "Audio Capture Device"); if (hr < 0) Marshal.ThrowExceptionForHR(hr); } // Get the video compressor and add it to the filter graph if (VideoCompressor != null) { videoCompressorFilter = (IBaseFilter)Marshal.BindToMoniker(VideoCompressor.MonikerString); hr = graphBuilder.AddFilter(videoCompressorFilter, "Video Compressor"); if (hr < 0) Marshal.ThrowExceptionForHR(hr); } // Get the audio compressor and add it to the filter graph if (AudioCompressor != null) { audioCompressorFilter = (IBaseFilter)Marshal.BindToMoniker(AudioCompressor.MonikerString); hr = graphBuilder.AddFilter(audioCompressorFilter, "Audio Compressor"); 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; cat = PinCategory.Capture; med = MediaType.Interleaved; Guid iid = typeof(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 = MediaType.Video; hr = captureGraphBuilder.FindInterface( ref cat, ref med, videoDeviceFilter, ref iid, out o); if (hr != 0) o = null; } videoStreamConfig = o as IAMStreamConfig; // Retrieve the stream control interface for the audio device o = null; cat = PinCategory.Capture; med = MediaType.Audio; iid = typeof(IAMStreamConfig).GUID; hr = captureGraphBuilder.FindInterface( ref cat, ref med, audioDeviceFilter, ref iid, out o); if (hr != 0) o = null; audioStreamConfig = 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; // Reload any audio crossbars if (audioSources != null) audioSources.Dispose(); audioSources = null; // Reload any property pages exposed by filters if (propertyPages != null) propertyPages.Dispose(); propertyPages = null; // Reload capabilities of video device videoCaps = null; // Reload capabilities of video device audioCaps = null; // Retrieve TV Tuner if available o = null; cat = PinCategory.Capture; med = MediaType.Interleaved; iid = typeof(IAMTVTuner).GUID; hr = captureGraphBuilder.FindInterface( ref cat, ref med, videoDeviceFilter, ref iid, out o); if (hr != 0) { med = MediaType.Video; hr = captureGraphBuilder.FindInterface( ref cat, ref med, videoDeviceFilter, ref iid, out o); if (hr != 0) o = null; } IAMTVTuner t = o as IAMTVTuner; if (t != null) tuner = new Tuner(t); videoInfoHeader = (VideoInfoHeader)Marshal.PtrToStructure(media.formatPtr, typeof(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(new SampleGrabberCallback(), 1); if (hr < 0) Marshal.ThrowExceptionForHR(hr); // Update the state now that we are done graphState = GraphState.Created; } }