winforms 使用directshowlib提取帧多年,但现在我在操作结束时收到异常:过滤器处于错误状态,如何修复?

o2g1uqev  于 2023-04-21  发布在  其他
关注(0)|答案(1)|浏览(102)

尝试在谷歌上搜索directshowlib上的异常,但没有成功找到解决方案。
第168行的例外:

DsError.ThrowExceptionForHR(hr);

它在第149行的WaitUntilDone方法中:

public void WaitUntilDone()
        {
            int hr;
            const int eAbort = unchecked((int)0x80004004);

            do
            {
               
                    System.Windows.Forms.Application.DoEvents();
                    EventCode evCode;
                    if (dis == true)
                    {
                        return;
                    }
                    
                    hr = _mediaEvent.WaitForCompletion(100, out evCode);
                
            }while (hr == eAbort);
            
            DsError.ThrowExceptionForHR(hr);
            OnStatusChanged();
        }

信息:

System.Runtime.InteropServices.COMException: 'The operation could not be performed because the filter is in the wrong state.'

完整的例外:

System.Runtime.InteropServices.COMException
  HResult=0x80040227
  Message=The operation could not be performed because the filter is in the wrong state.
  Source=DirectShowLib-2005
  StackTrace:
   at DirectShowLib.DsError.ThrowExceptionForHR(Int32 hr)
   at Polkan.DataSource.WmvAdapter.WaitUntilDone() in D:\Csharp Projects\Extracting_Frames\Extracting_Frames\Extracting_Frames\WmvAdapter.cs:line 168
   at Polkan.DataSource.WmvAdapter.Start() in D:\Csharp Projects\Extracting_Frames\Extracting_Frames\Extracting_Frames\WmvAdapter.cs:line 144
   at Extracting_Frames.Form1.Start(Boolean secondpass) in D:\Csharp Projects\Extracting_Frames\Extracting_Frames\Extracting_Frames\Form1.cs:line 351
   at Extracting_Frames.Form1.f_StatusChanged(Object sender, EventArgs e) in D:\Csharp Projects\Extracting_Frames\Extracting_Frames\Extracting_Frames\Form1.cs:line 589
   at Polkan.DataSource.WmvAdapter.OnStatusChanged() in D:\Csharp Projects\Extracting_Frames\Extracting_Frames\Extracting_Frames\WmvAdapter.cs:line 176
   at Polkan.DataSource.WmvAdapter.WaitUntilDone() in D:\Csharp Projects\Extracting_Frames\Extracting_Frames\Extracting_Frames\WmvAdapter.cs:line 169
   at Polkan.DataSource.WmvAdapter.Start() in D:\Csharp Projects\Extracting_Frames\Extracting_Frames\Extracting_Frames\WmvAdapter.cs:line 144
   at Extracting_Frames.Form1.Start(Boolean secondpass) in D:\Csharp Projects\Extracting_Frames\Extracting_Frames\Extracting_Frames\Form1.cs:line 351
   at Extracting_Frames.Form1.button8_Click(Object sender, EventArgs e) in D:\Csharp Projects\Extracting_Frames\Extracting_Frames\Extracting_Frames\Form1.cs:line 1738
   at System.Windows.Forms.Control.OnClick(EventArgs e)
   at System.Windows.Forms.Button.OnClick(EventArgs e)
   at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
   at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
   at System.Windows.Forms.Control.WndProc(Message& m)
   at System.Windows.Forms.ButtonBase.WndProc(Message& m)
   at System.Windows.Forms.Button.WndProc(Message& m)
   at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
   at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
   at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
   at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
   at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
   at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
   at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
   at System.Windows.Forms.Application.Run(Form mainForm)
   at Extracting_Frames.Program.Main() in D:\Csharp Projects\Extracting_Frames\Extracting_Frames\Extracting_Frames\Program.cs:line 18

类代码有点长,所以我把它放在www.example.com中pastebin.com,因为某些原因,我只能把它放在pastebin.com中。
我会把这个类放在这里,它有点长:

using System;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Runtime.InteropServices;
using DirectShowLib;
using System.Collections.Generic;
using Extracting_Frames;
using System.Windows.Forms;
using WindowsFormsApplication1;
using System.Text.RegularExpressions;
using System.Linq;

namespace Polkan.DataSource
{
    internal class WmvAdapter : ISampleGrabberCB, IDisposable
    {
        #region Fields_Properties_and_Events

        struct DirectoryStruct
        {
            public string name;
            public int lowrange;
            public int highrange;
        }
        List<DirectoryStruct> parseLightningsDirectories;
        string path_exe;
        string histograms_dat_fileName_Directory;
        public string fileName;
        public string fileNameRGB;
        bool dis = false;
        int count = 0;
        private string histograms_dat_fileName = "";
        private string histograms_dat_filenameRGB = "";
        private IFilterGraph2 _filterGraph;
        private IMediaControl _mediaCtrl;
        private IMediaEvent _mediaEvent;
        private int _width;
        private int _height;
        private readonly string _outFolder;
        private readonly string _allFilesOutFolder;
        private int _frameId;
        //better use a custom EventHandler that passes the results of the action to the subscriber.
        public delegate void EventHandler(object sender, EventArgs e);
        public event EventHandler StatusChanged;

        public delegate void FrameCountEventHandler(object sender, FrameCountEventArgs e);
        public event FrameCountEventHandler FrameCountAvailable;

        public delegate void ProgressEventHandler(object sender, ProgressEventArgs e);
        public event ProgressEventHandler ProgressChanged;

        public IMediaSeeking _mSeek;
        public long _duration = 0;
        private long _avgFrameTime = 0;
        private string histogramDatOutputFile;
        private string combinedDatDir;
       
        //just save the averages to a List (not to fs)
        public List<double> AveragesList { get; set; }

        public List<long> histogramValueListR;
        public List<long> histogramValueListG;
        public List<long> histogramValueListB;
        public List<long> histogramValueList;

        public bool Secondpass { get; set; }
        
        public List<int> FramesToSave { get; set; }
        public List<string> LightningsDirectories;
        StreamWriter w;

        #endregion

        #region Constructors and Destructors

        public WmvAdapter(string file, string outFolder)
        {
            histogramDatOutputFile = Form1._outputDir;
            path_exe = path_exe = Path.GetDirectoryName(Application.LocalUserAppDataPath);
            histograms_dat_fileName = "histogramValues.dat";
            histograms_dat_filenameRGB = "histogramValuesRGB.dat";
            //histograms_dat_fileName_Directory = path_exe + "\\" + "dat file";
            histograms_dat_fileName_Directory = Path.Combine(path_exe, "dat file", Path.GetFileName(file));
            fileName = histograms_dat_fileName_Directory + "\\" + histograms_dat_fileName;
            fileNameRGB = histograms_dat_fileName_Directory + "\\" + histograms_dat_filenameRGB;
            
            if (!Directory.Exists(histograms_dat_fileName_Directory))
            {
                Directory.CreateDirectory(histograms_dat_fileName_Directory);
                
                    //File.Create(histograms_dat_fileName_Directory + "\\" + histogramDatOutputFile); // to add options db to save this file name after creation. 
                    // and use the file name histogramDatOutputFile in Form1 from the options db to load the file name as output dir for the current histogram dat file !
                    //string d = histograms_dat_fileName_Directory + "\\" + histogramDatOutputFile;
                    //combinedDatDir = Path.Combine(histograms_dat_fileName_Directory, histogramDatOutputFile);
                    Options_DB.set_datFileOutputDir(histograms_dat_fileName_Directory);
                
            }
            else
            {
               
                    //File.Create(histograms_dat_fileName_Directory + "\\" + histogramDatOutputFile); // to add options db to save this file name after creation. 
                    // and use the file name histogramDatOutputFile in Form1 from the options db to load the file name as output dir for the current histogram dat file !
                    //string d = histograms_dat_fileName_Directory + "\\" + histogramDatOutputFile;
                    //combinedDatDir = Path.Combine(histograms_dat_fileName_Directory, histogramDatOutputFile);
                    Options_DB.set_datFileOutputDir(histograms_dat_fileName_Directory);
                
            }

            _outFolder = outFolder;
            try
            {
                SetupGraph(file);
            }
            catch(Exception err)
            {
                Dispose();
                string myer = err.ToString();
                MessageBox.Show("A codec is required to load this video file. Please use http://www.headbands.com/gspot/ or search the web for the correct codec");
            }
        }

        ~WmvAdapter()
        {
            CloseInterfaces();
        }

        #endregion

        public void Dispose()
        {
            CloseInterfaces();
        }
        
        public void Start()
        {
            if (this.Secondpass)
            {
                //w = new StreamWriter(@"i:\NumbersTest.txt");
            }
                EstimateFrameCount();
                    int hr = _mediaCtrl.Run();
                    WaitUntilDone();
                    DsError.ThrowExceptionForHR(hr);
                
        }

        public void WaitUntilDone()
        {
            int hr;
            const int eAbort = unchecked((int)0x80004004);

            do
            {
               
                    System.Windows.Forms.Application.DoEvents();
                    EventCode evCode;
                    if (dis == true)
                    {
                        return;
                    }
                    
                    hr = _mediaEvent.WaitForCompletion(100, out evCode);
                
            }while (hr == eAbort);
            
            DsError.ThrowExceptionForHR(hr);
            OnStatusChanged();
        }

        //Edit: added events
        protected virtual void OnStatusChanged()
        {
            if (StatusChanged != null)
                StatusChanged(this, new EventArgs());
        }

        protected virtual void OnFrameCountAvailable(long frameCount)
        {
            if (FrameCountAvailable != null)
                FrameCountAvailable(this, new FrameCountEventArgs() { FrameCount = frameCount });
        }

        protected virtual void OnProgressChanged(int frameID)
        {
            if (ProgressChanged != null)
                ProgressChanged(this, new ProgressEventArgs() { FrameID = frameID });
        }

        /// <summary> build the capture graph for grabber. </summary>
        private void SetupGraph(string file)
        {
            ISampleGrabber sampGrabber = null;
            IBaseFilter capFilter = null;
            IBaseFilter nullrenderer = null;

            _filterGraph = (IFilterGraph2)new FilterGraph();
            _mediaCtrl = (IMediaControl)_filterGraph;
            _mediaEvent = (IMediaEvent)_filterGraph;

            _mSeek = (IMediaSeeking)_filterGraph;

            var mediaFilt = (IMediaFilter)_filterGraph;

            try
            {
                // Add the video source
                int hr = _filterGraph.AddSourceFilter(file, "Ds.NET FileFilter", out capFilter);
                DsError.ThrowExceptionForHR(hr);

                // Get the SampleGrabber interface
                sampGrabber = new SampleGrabber() as ISampleGrabber;

                var baseGrabFlt = sampGrabber as IBaseFilter;

                ConfigureSampleGrabber(sampGrabber);

                // Add the frame grabber to the graph
                hr = _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 = _filterGraph.Connect(iPinOut, iPinIn);
                DsError.ThrowExceptionForHR(hr);

                // Add the null renderer to the graph
                nullrenderer = new NullRenderer() as IBaseFilter;
                hr = _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 = _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);

                //Edit: get the duration
                hr = _mSeek.GetDuration(out _duration);
                DsError.ThrowExceptionForHR(hr);
            }
            finally
            {
                if (capFilter != null)
                {
                    Marshal.ReleaseComObject(capFilter);
                }
                if (sampGrabber != null)
                {
                    Marshal.ReleaseComObject(sampGrabber);
                }
                if (nullrenderer != null)
                {
                    Marshal.ReleaseComObject(nullrenderer);
                }
                GC.Collect();
            }
        }

        private void EstimateFrameCount()
        {
            try
            {
                //1sec / averageFrameTime
                double fr = 10000000.0 / _avgFrameTime;
                double frameCount = fr * (_duration / 10000000.0);
                OnFrameCountAvailable((long)frameCount);

            }
            catch
            {

            }
        }

        public double framesCounts()
        {
            double fr = 10000000.0 / _avgFrameTime;
            double frameCount = fr * (_duration / 10000000.0);
            return frameCount;
        }

        private void SaveSizeInfo(ISampleGrabber sampGrabber)
        {
            // Get the media type from the SampleGrabber
            var media = new AMMediaType();
            int hr = sampGrabber.GetConnectedMediaType(media);
            DsError.ThrowExceptionForHR(hr);

            if ((media.formatType != FormatType.VideoInfo) || (media.formatPtr == IntPtr.Zero))
            {
                throw new NotSupportedException("Unknown Grabber Media Format");
            }

            // Grab the size info
            var videoInfoHeader = (VideoInfoHeader)Marshal.PtrToStructure(media.formatPtr, typeof(VideoInfoHeader));
            _width = videoInfoHeader.BmiHeader.Width;
            _height = videoInfoHeader.BmiHeader.Height;
            //Edit: get framerate
            _avgFrameTime = videoInfoHeader.AvgTimePerFrame;

            DsUtils.FreeAMMediaType(media);
            GC.Collect();
        }

        private void ConfigureSampleGrabber(ISampleGrabber sampGrabber)
        {
            var media = new AMMediaType
            {
                majorType = MediaType.Video,
                subType = MediaSubType.RGB24,
                formatType = FormatType.VideoInfo
            };
            int hr = sampGrabber.SetMediaType(media);
            DsError.ThrowExceptionForHR(hr);

            DsUtils.FreeAMMediaType(media);
            GC.Collect();
            hr = sampGrabber.SetCallback(this, 1);
            DsError.ThrowExceptionForHR(hr);
        }

        private void CloseInterfaces()
        {
            try
            {
                if (_mediaCtrl != null)
                {
                    _mediaCtrl.Stop();
                    _mediaCtrl = null;
                    dis = true;
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex);
            }

            if (_filterGraph != null)
            {
                Marshal.ReleaseComObject(_filterGraph);
                _filterGraph = null;
            }
            GC.Collect();
        }
        int ISampleGrabberCB.SampleCB(double sampleTime, IMediaSample pSample)
        {
            Marshal.ReleaseComObject(pSample);
            return 0;
        }

        int ISampleGrabberCB.BufferCB(double sampleTime, IntPtr pBuffer, int bufferLen)
        {
            
            if (Form1.ExtractAutomatic == true)
            {

                if (this.Secondpass)
                {
                    //extract ranges
                    LightningsDirectories = Form1.lightningsRegions;
                    parseLightningsDirectories = new List<DirectoryStruct>();
                    string pattern = @"\[(\d+)\D+(\d+)";
                    Regex expression = new Regex(pattern);
                    foreach (string Directory in LightningsDirectories)
                    {
                        Match match = expression.Match(Directory);
                        DirectoryStruct newrow = new DirectoryStruct();
                        newrow.name = Directory;
                        newrow.lowrange = int.Parse(match.Groups[1].Value);
                        newrow.highrange = int.Parse(match.Groups[2].Value);
                        parseLightningsDirectories.Add(newrow);
                    }
                    

                }

          using (var bitmap = new Bitmap(_width, _height, _width * 3, PixelFormat.Format24bppRgb, pBuffer))
          {
              if (this.Secondpass)
              {
                  if (FramesToSave != null && FramesToSave.Contains(_frameId))
                  {

                      DirectoryStruct[] myrow = parseLightningsDirectories.Where(row =>
                                         (row.lowrange <= _frameId) && (row.highrange >= _frameId)).Select(row => row).ToArray();
                      bitmap.RotateFlip(RotateFlipType.Rotate180FlipX);
                      var myrows = parseLightningsDirectories.Where(row =>
                        (row.lowrange <= _frameId) && (row.highrange >= _frameId)).Select(row => row);
                      bitmap.Save(Path.Combine(_outFolder + "\\" + myrow[0].name, _frameId.ToString("D6") + ".bmp"));
                      long[] HistogramsValuesR = Form1.GetHistogramRGB(bitmap, Form1.ColorChannel.Red);
                      if (histogramValueListR == null)
                          histogramValueListR = new List<long>(256);
                      histogramValueListR.AddRange(HistogramsValuesR);

                      long[] HistogramsValuesG = Form1.GetHistogramRGB(bitmap, Form1.ColorChannel.Green);
                      if (histogramValueListG == null)
                          histogramValueListG = new List<long>(256);
                     /*This line throw out of memory exception*/   histogramValueListG.AddRange(HistogramsValuesG);
                     
                      long[] HistogramsValuesB = Form1.GetHistogramRGB(bitmap, Form1.ColorChannel.Blue);
                      if (histogramValueListB == null)
                          histogramValueListB = new List<long>(256);
                      histogramValueListB.AddRange(HistogramsValuesB);

                  }
              }
              else
              {
                  //this is the changed part
                  using (Bitmap original_bmp = new Bitmap(_width, _height, _width * 3, PixelFormat.Format24bppRgb, pBuffer))
                  {
                      if (_frameId > 0)
                      {
                          long[] HistogramValues = Form1.GetHistogram(original_bmp);
                          if (histogramValueList == null)
                              histogramValueList = new List<long>(256);
                          histogramValueList.AddRange(HistogramValues);
                          if (Form1.extractallframes == true)
                          {
                              original_bmp.Save(Path.Combine(_outFolder + "\\", _frameId.ToString("D6") + ".bmp"));
                          }

                      }
                  }
              }
                    _frameId++;
                    //let only report each 100 frames for performance
                    if (_frameId % 100 == 0)
                        OnProgressChanged(_frameId);
                }
            }
            else
            {
                using (var bitmap = new Bitmap(_width, _height, _width * 3, PixelFormat.Format24bppRgb, pBuffer))
                {
                    if (!this.Secondpass)
                    {
                        //get avg
                        double average = GetAveragePixelValue(bitmap);

                        if (AveragesList == null)
                            AveragesList = new List<double>();
                        //save avg
                        AveragesList.Add(average);
                    }
                    else
                    {
                        if (FramesToSave != null && FramesToSave.Contains(_frameId))
                        {
                            bitmap.RotateFlip(RotateFlipType.Rotate180FlipX);
                            bitmap.Save(Path.Combine(_outFolder, _frameId.ToString("D6") + ".bmp"));
                            using (BinaryWriter binWriter =
                    new BinaryWriter(File.Open(fileName, FileMode.Create)))
                            {
                            }
                        }                       
                    }
                    _frameId++;
                    //let only report each 100 frames for performance
                    if (_frameId % 100 == 0)
                        OnProgressChanged(_frameId);
                }
            }
                return 0;
        }

        public static Bitmap ResizeBitmap(Bitmap b, int nWidth, int nHeight)
        {
            Bitmap result = new Bitmap(nWidth, nHeight);
            using (Graphics g = Graphics.FromImage((Image)result))
                g.DrawImage(b, 0, 0, nWidth, nHeight);
            return result;
        }
        private unsafe double GetAveragePixelValue(Bitmap bmp)
        {
            BitmapData bmData = null;

            try
            {
                bmData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);

                int stride = bmData.Stride;
                IntPtr scan0 = bmData.Scan0;
                int w = bmData.Width;
                int h = bmData.Height;

                double sum = 0;
                long pixels = bmp.Width * bmp.Height;

                byte* p = (byte*)scan0.ToPointer();

                for (int y = 0; y < h; y++)
                {
                    p = (byte*)scan0.ToPointer();
                    p += y * stride;

                    for (int x = 0; x < w; x++)
                    {
                        double i = ((double)p[0] + p[1] + p[2]) / 3.0;
                        sum += i;

                        p += 3;
                    }

                    //no offset incrementation needed when getting 
                    //the pointer at the start of each row
                }

                bmp.UnlockBits(bmData);

                double result = sum / (double)pixels;

                return result;
            }
            catch
            {
                try
                {
                    bmp.UnlockBits(bmData);
                }
                catch
                {

                }
            }
            return -1;
        }
    }

    public class FrameCountEventArgs
    {
        public long FrameCount { get; set; }
    }

    public class ProgressEventArgs
    {
        public int FrameID { get; set; }
    }

    public class duration
    {
        public long durationTime { get; set; }
    }
}
raogr8fs

raogr8fs1#

过滤器图形中的一个过滤器触发了此错误并通过过滤器图形管理器转发。通过注册失败代码和异常,您看不到作为错误来源的过滤器。
您需要确定问题的来源,例如,通过减少筛选器图隔离到特定筛选器。例如,您的客户筛选器实现直方图可能是问题的来源。
这个问题也可能与改变过滤器图相比,过去的时候,事情运作良好。长话短说,你有兴趣缩小问题的来源,以特定的过滤器。

相关问题