private void CloseInterfaces()
        {
            int hr;

            if (m_adecOut != null)
            {
                CleanUpInterface(m_adecOut);
                m_adecOut = null;
            }

            if (_defaultAudioRenderer != null)
            {
                m_graph.RemoveFilter(_defaultAudioRenderer as DirectShowLib.IBaseFilter);

                CleanUpInterface(_defaultAudioRenderer);
                _defaultAudioRenderer = null;
            }

            if (_reclockAudioRenderer != null)
            {
                m_graph.RemoveFilter(_reclockAudioRenderer as DirectShowLib.IBaseFilter);

                CleanUpInterface(_reclockAudioRenderer);
                _reclockAudioRenderer = null;
            }

            if (_wasapiAR != null)
            {
                m_graph.RemoveFilter(_wasapiAR as DirectShowLib.IBaseFilter);

                CleanUpInterface(_wasapiAR);
                _wasapiAR = null;
            }

            if (_lavaudio != null)
            {
                m_graph.RemoveFilter(_lavaudio as DirectShowLib.IBaseFilter);

                CleanUpInterface(_lavaudio);
                _lavaudio = null;
            }

            if (_xyVsFilter != null)
            {
                m_graph.RemoveFilter(_xyVsFilter as DirectShowLib.IBaseFilter);

                CleanUpInterface(_xyVsFilter);
                _xyVsFilter = null;
            }

            if (_xySubFilter != null)
            {
                m_graph.RemoveFilter(_xySubFilter as DirectShowLib.IBaseFilter);

                CleanUpInterface(_xySubFilter);
                _xySubFilter = null;
            }

            if (_lavvideo != null)
            {
                m_graph.RemoveFilter(_lavvideo as DirectShowLib.IBaseFilter);

                CleanUpInterface(_lavvideo);
                _lavvideo = null;
            }

            if (_madvr != null)
            {
                m_graph.RemoveFilter(_madvr as DirectShowLib.IBaseFilter);

                CleanUpInterface(_madvr);
                _madvr = null;
            }

            if (_videoWindow != null)
            {
                // Relinquish ownership (IMPORTANT!) after hiding video window
                hr = _videoWindow.put_Visible(OABool.False);

                hr = _videoWindow.put_Owner(IntPtr.Zero);
            }

            if (_mediaEventEx != null)
            {
                hr = _mediaEventEx.SetNotifyWindow(IntPtr.Zero, 0, IntPtr.Zero);
                //Marshal.ReleaseComObject(_mediaEventEx);
                //_mediaEventEx = null;
            }

            //if (_dvdNav != null)
            //{
            //    Marshal.ReleaseComObject(_dvdNav);
            //    _dvdNav = null;
            //}
            /* //this will double release the source filter
            if (dvdInfo != null)
            {
                Marshal.ReleaseComObject(dvdInfo);
                dvdInfo = null;
            }

            if (_mDvdControl != null)
            {
                Marshal.ReleaseComObject(_mDvdControl);                
            }
            */
            _mDvdControl = null;

            CleanUpInterface(_mPDisplay);
            _mPDisplay = null;
            CleanUpInterface(_sourceFilter);
            _sourceFilter = null;
            CleanUpInterface(_mPEvr);
            _mPEvr = null;
            CleanUpInterface(m_filterGraph);
            m_filterGraph = null;

            m_filterGraph = null;
            _mediaEventEx = null;
            _mediaSeeking = null;
            _mediaPosition = null;
            _mediaControl = null;
            _basicAudio = null;
            _basicVideo = null;
            m_graph = null;
            _videoWindow = null;
            _filterGraph = null;

            if (m_dsRot != null)
                m_dsRot.Dispose();
            m_dsRot = null;

            _mSeekCaps = 0;

            _streams = null;

            GC.Collect();
        }
        private void SetupGraphForRateChange(double rate, IBaseFilter audioRenderer)
        {
            int hr = 0;

            _logger.Debug("SetupGraphForRateChange: {0}", rate);

            if (_wasapiAR != null)
            {
                IBasicAudio ba = _filterGraph as IBasicAudio;
                if (ba != null)
                {
                    int orgVol = 0;
                    hr = ba.get_Volume(out orgVol);
                    DsError.ThrowExceptionForHR(hr);

                    _logger.Debug("SetupGraphForRateChange: Current Volume: {0}", orgVol);

                    if (Math.Abs(rate) > 1.5)
                    {
                        hr = ba.put_Volume(-10000); //turn off the volume so we can ffwd
                        DsError.ThrowExceptionForHR(hr);
                        _logger.Debug("SetupGraphForRateChange: mute");
                    }
                    else if (Math.Abs(rate) <= 1.5)
                    {
                        hr = ba.put_Volume(0); //set the volume back to full
                        DsError.ThrowExceptionForHR(hr);
                        _logger.Debug("SetupGraphForRateChange: enable volume");
                    }
                }
            }
            else
            {
                IPin arIn = null;

                try
                {
                    if (audioRenderer != null)
                    {
                        if (Math.Abs(rate) > 4 && m_adecOut == null)
                        {
                            _logger.Debug("SetupGraphForRateChange: remove audio renderer");

                            //grab the audio decoder's output pin
                            arIn = DsFindPin.ByDirection(audioRenderer, PinDirection.Input, 0);
                            hr = arIn.ConnectedTo(out m_adecOut);
                            DsError.ThrowExceptionForHR(hr);

                            //stop the graph
                            hr = _mediaControl.Stop();
                            DsError.ThrowExceptionForHR(hr);

                            //remove it
                            hr = _filterGraph.RemoveFilter(audioRenderer);
                            DsError.ThrowExceptionForHR(hr);

                            //start the graph again
                            hr = _mediaControl.Run();
                            DsError.ThrowExceptionForHR(hr);
                        }
                        else if (Math.Abs(rate) <= 4 && m_adecOut != null)
                        {
                            _logger.Debug("SetupGraphForRateChange: add the audio renderer back");

                            //stop the graph
                            hr = _mediaControl.Stop();
                            DsError.ThrowExceptionForHR(hr);

                            //add the audio renderer back into the graph
                            hr = _filterGraph.AddFilter(audioRenderer, "Audio Renderer");
                            DsError.ThrowExceptionForHR(hr);

                            //connect it to the decoder pin
                            arIn = DsFindPin.ByDirection(audioRenderer, PinDirection.Input, 0);
                            hr = _filterGraph.ConnectDirect(m_adecOut, arIn, null);
                            DsError.ThrowExceptionForHR(hr);

                            Marshal.ReleaseComObject(m_adecOut);
                            m_adecOut = null;

                            //start the graph again
                            hr = _mediaControl.Run();
                            DsError.ThrowExceptionForHR(hr);
                        }
                    }

                    if (Math.Abs(rate) <= 4)
                    {
                        IBasicAudio ba = _filterGraph as IBasicAudio;
                        if (ba != null)
                        {
                            int orgVol = 0;
                            hr = ba.get_Volume(out orgVol);
                            DsError.ThrowExceptionForHR(hr);
                            _logger.Debug("SetupGraphForRateChange: Current Volume: {0}", orgVol);

                            if (Math.Abs(rate) > 1.5)
                            {
                                hr = ba.put_Volume(-10000); //turn off the volume so we can ffwd
                                DsError.ThrowExceptionForHR(hr);
                                _logger.Debug("SetupGraphForRateChange: mute");
                            }
                            else if (Math.Abs(rate) <= 1.5)
                            {
                                hr = ba.put_Volume(0); //set the volume back to full
                                DsError.ThrowExceptionForHR(hr);
                                _logger.Debug("SetupGraphForRateChange: enable volume");
                            }
                        }
                    }
                }
                finally
                {
                    if (arIn != null)
                        Marshal.ReleaseComObject(arIn);
                }
            }
        }