Tried to google for the exception on directshowlib but no success to find a solution.
The exception is on line 168:
DsError.ThrowExceptionForHR(hr);
It's in the method WaitUntilDone from line 149:
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();
}
The message:
System.Runtime.InteropServices.COMException: 'The operation could not be performed because the filter is in the wrong state.'
The full exception:
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
The class code is a bit long so I put it in pastebin.com for some reason I can put in pastebin.com only private.
I will put here the class it's a bit long:
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; }
}
}
One of the filters in the filter graph is triggering this error and forwarding it through filter graph manager. By registering the failure code and the exception, you don't see the filter which is the origin of the error.
You need to identify the source of the problem, for example, by reducing filter graph isolating to specific filter. Your customer filter implementing histogram is the likely source of the problem, for example.
The problem might also be related to changed filter graph compared to past times when things worked well. Long story short, you are interested to narrow down the source of the problem to specific filter.