EDN Admin
Well-known member
Thats in Form1:
<pre class="prettyprint private void button3_Click(object sender, EventArgs e)
{
f.Dispose();
}[/code]
Each time the user start a new operation if automatic or manual its making a new instance of f wich is the class: WmvAdapter.cs
This is the Start function in Form1:
<pre class="prettyprint private void Start(bool secondpass)
{
setpicture(-1);
if (Directory.Exists(_outputDir) && secondpass == false)
{
}
else
{
Directory.CreateDirectory(_outputDir);
}
if (ExtractAutomatic == true)
{
string subDirectory_Automatic_Name = _outputDir + "\" + automaticModeDirectory;
Directory.CreateDirectory(subDirectory_Automatic_Name);
f = new WmvAdapter(_videoFile,
Path.Combine(subDirectory_Automatic_Name));
}
else
{
if (!Directory.Exists(subDirectoryName))
{
string subDirectory_Manual_Name = _outputDir + "\" + averagesListTextFileDirectory + "_Manual";
Directory.CreateDirectory(subDirectory_Manual_Name);
f = new WmvAdapter(_videoFile,
Path.Combine(subDirectory_Manual_Name));
}
f = new WmvAdapter(_videoFile,
Path.Combine(subDirectoryName));
}
button1.Enabled = false;
f.Secondpass = secondpass;
f.FramesToSave = _fts;
f.FrameCountAvailable += new WmvAdapter.FrameCountEventHandler(f_FrameCountAvailable);
f.StatusChanged += new WmvAdapter.EventHandler(f_StatusChanged);
f.ProgressChanged += new WmvAdapter.ProgressEventHandler(f_ProgressChanged);
this.Text = "Processing Please Wait...";
label5.ForeColor = Color.Green;
label5.Text = "Processing Please Wait";
button8.Enabled = false;
button5.Enabled = false;
label5.Visible = true;
pictureBox1.Image = Lightnings_Extractor.Properties.Resources.Weather_Michmoret;
Hrs = 0; //number of hours
Min = 0; //number of Minutes
Sec = 0; //number of Sec
timeElapsed = 0;
label10.Text = "00:00:00";
label11.Visible = false;
label12.Visible = false;
label9.Visible = false;
label8.Visible = false;
this.button1.Enabled = false;
myTrackPanelss1.trackBar1.Enabled = false;
this.checkBox2.Enabled = false;
this.checkBox1.Enabled = false;
numericUpDown1.Enabled = false;
timer1.Start();
//this.Enabled = false;
label2.Text = "";
label1.Visible = true;
label2.Visible = true;
label3.Visible = true;
label4.Visible = true;
f.Start();
}[/code]
This is the two buttons that start the operation one for manual one for automatic both are using the Start function:
<pre class="prettyprint private void button1_Click(object sender, EventArgs e)
{
viewToolStripMenuItem.Enabled = false;
fileToolStripMenuItem.Enabled = false;
button2.Enabled = false;
label14.Visible = false;
label15.Visible = false;
label21.Visible = false;
label22.Visible = false;
label24.Visible = false;
label25.Visible = false;
ExtractAutomatic = false;
if (secondPass == true)
{
Start(true);
}
Start(false);
}
private void button8_Click(object sender, EventArgs e)
{
viewToolStripMenuItem.Enabled = false;
fileToolStripMenuItem.Enabled = false;
button2.Enabled = false;
label14.Visible = false;
label15.Visible = false;
label21.Visible = false;
label22.Visible = false;
label24.Visible = false;
label25.Visible = false;
ExtractAutomatic = true;
DirectoryInfo info = new DirectoryInfo(_videoFile);
string dirName = info.Name;
automaticModeDirectory = dirName + "_Automatic";
subDirectoryName = _outputDir + "\" + automaticModeDirectory;
if (secondPass == true)
{
Start(true);
}
Start(false);
}[/code]
Now when i click the cancel operation button im getting error in the WmvAdapter.cs class on the line:
<pre class="prettyprint hr = _mediaEvent.WaitForCompletion(100, out evCode);[/code]
The error is: COM object that has been separated from its underlying RCW cannot be used.
This line is part of the function WaitUntilDone()
<pre class="prettyprint public void WaitUntilDone()
{
int hr;
const int eAbort = unchecked((int)0x80004004);
do
{
System.Windows.Forms.Application.DoEvents();
EventCode evCode;
hr = _mediaEvent.WaitForCompletion(100, out evCode);
}while (hr == eAbort);
DsError.ThrowExceptionForHR(hr);
OnStatusChanged();
}[/code]
This function WaitUntilDone() is called in the WmvAdapter.cs Start() function:
<pre class="prettyprint public void Start()
{
EstimateFrameCount();
int hr = _mediaCtrl.Run();
WaitUntilDone();
DsError.ThrowExceptionForHR(hr);
}[/code]
I want that when i click the Cancel Operation buttin it will stop all the actions and return to the program regular so i can use it again like nothing happened.
This is the full code of the WmvAdapter.cs:
<pre class="prettyprint 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;
namespace Polkan.DataSource
{
internal class WmvAdapter : ISampleGrabberCB, IDisposable
{
#region Fields_Properties_and_Events
int count = 0;
const string fileName = @"d:histogramValues.dat";
private IFilterGraph2 _filterGraph;
private IMediaControl _mediaCtrl;
private IMediaEvent _mediaEvent;
private int _width;
private int _height;
private readonly string _outFolder;
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;
private IMediaSeeking _mSeek;
private long _duration = 0;
private long _avgFrameTime = 0;
//just save the averages to a List (not to fs)
public List<double> AveragesList { get; set; }
public List<long> histogramValuesList;
public bool Secondpass { get; set; }
public List<int> FramesToSave { get; set; }
#endregion
#region Constructors and Destructors
public WmvAdapter(string file, string outFolder)
{
_outFolder = outFolder;
try
{
SetupGraph(file);
}
catch
{
Dispose();
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()
{
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;
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 its 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;
}
}
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)
{
using (var bitmap = new Bitmap(_width, _height, _width * 3, PixelFormat.Format24bppRgb, pBuffer))
{
if (!this.Secondpass)
{
long[] HistogramValues = Form1.GetHistogram(bitmap);
long t = Form1.GetTopLumAmount(HistogramValues, 1000);
Form1.averagesTest.Add(t);
}
else
{
//this is the changed part
if (_frameId > 0)
{
if (Form1.averagesTest[_frameId] / 1000.0 - Form1.averagesTest[_frameId - 1] / 1000.0 > 150.0)
{
count = 6;
}
if (count > 0)
{
bitmap.RotateFlip(RotateFlipType.Rotate180FlipX);
bitmap.Save(Path.Combine(_outFolder, _frameId.ToString("D6") + ".bmp"));
count --;
}
}
}
_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);
//***************************\
// for (int i = 0; i < (int)framesCounts(); i++)
// {
// get histogram values
long[] HistogramValues = Form1.GetHistogram(bitmap);
if (histogramValuesList == null)
histogramValuesList = new List<long>(256);
histogramValuesList.AddRange(HistogramValues);
//***************************\
//}
}
else
{
if (FramesToSave != null && FramesToSave.Contains(_frameId))
{
bitmap.RotateFlip(RotateFlipType.Rotate180FlipX);
bitmap.Save(Path.Combine(_outFolder, _frameId.ToString("D6") + ".bmp"));
// get histogram values
long[] HistogramValues = Form1.GetHistogram(bitmap);
if (histogramValuesList == null)
histogramValuesList = new List<long>(256);
histogramValuesList.AddRange(HistogramValues);
using (BinaryWriter binWriter =
new BinaryWriter(File.Open(fileName, FileMode.Create)))
{
for (int i = 0; i < histogramValuesList.Count; i++)
{
binWriter.Write(histogramValuesList[(int)i]);
}
binWriter.Close();
}
}
}
_frameId++;
//let only report each 100 frames for performance
if (_frameId % 100 == 0)
OnProgressChanged(_frameId);
}
}
return 0;
}
/* int ISampleGrabberCB.SampleCB(double sampleTime, IMediaSample pSample)
{
Marshal.ReleaseComObject(pSample);
return 0;
}
int ISampleGrabberCB.BufferCB(double sampleTime, IntPtr pBuffer, int bufferLen)
{
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);
//***************************\
// for (int i = 0; i < (int)framesCounts(); i++)
// {
// get histogram values
long[] HistogramValues = Form1.GetHistogram(bitmap);
if (histogramValuesList == null)
histogramValuesList = new List<long>(256);
histogramValuesList.AddRange(HistogramValues);
long t = Form1.GetTopLumAmount(HistogramValues, 1000);
//***************************\
Form1.averagesTest.Add(t); // to add this list to a text file or binary file and read the averages from the file when its is Secondpass !!!!!
//}
}
else
{
if (FramesToSave != null && FramesToSave.Contains(_frameId))
{
bitmap.RotateFlip(RotateFlipType.Rotate180FlipX);
bitmap.Save(Path.Combine(_outFolder, _frameId.ToString("D6") + ".bmp"));
// get histogram values
long[] HistogramValues = Form1.GetHistogram(bitmap);
if (histogramValuesList == null)
histogramValuesList = new List<long>(256);
histogramValuesList.AddRange(HistogramValues);
using (BinaryWriter binWriter =
new BinaryWriter(File.Open(fileName, FileMode.Create)))
{
for (int i = 0; i < histogramValuesList.Count; i++)
{
binWriter.Write(histogramValuesList[(int)i]);
}
binWriter.Close();
}
}
for (int x = 1; x < Form1.averagesTest.Count; x++)
{
double fff = Form1.averagesTest[x] / 1000.0 - Form1.averagesTest[x - 1] / 1000.0;
if (Form1.averagesTest[x] / 1000.0 - Form1.averagesTest[x - 1] / 1000.0 > 180.0)
{
bitmap.RotateFlip(RotateFlipType.Rotate180FlipX);
bitmap.Save(Path.Combine(_outFolder, _frameId.ToString("D6") + ".bmp"));
_frameId++;
}
}
}
_frameId++;
//let only report each 100 frames for performance
if (_frameId % 100 == 0)
OnProgressChanged(_frameId);
}
return 0;
}*/
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; }
}
}
[/code]
The f.Dispose() in WmvAdapter.cs is:
<pre class="prettyprint public void Dispose()
{
CloseInterfaces();
}[/code]
And CloseInterfaces() is:
<pre class="prettyprint private void CloseInterfaces()
{
try
{
if (_mediaCtrl != null)
{
_mediaCtrl.Stop();
_mediaCtrl = null;
}
}
catch (Exception ex)
{
Debug.WriteLine(ex);
}
if (_filterGraph != null)
{
Marshal.ReleaseComObject(_filterGraph);
_filterGraph = null;
}
GC.Collect();
}[/code]
I dont know why im getting this error.
Thanks. <hr class="sig danieli
View the full article
<pre class="prettyprint private void button3_Click(object sender, EventArgs e)
{
f.Dispose();
}[/code]
Each time the user start a new operation if automatic or manual its making a new instance of f wich is the class: WmvAdapter.cs
This is the Start function in Form1:
<pre class="prettyprint private void Start(bool secondpass)
{
setpicture(-1);
if (Directory.Exists(_outputDir) && secondpass == false)
{
}
else
{
Directory.CreateDirectory(_outputDir);
}
if (ExtractAutomatic == true)
{
string subDirectory_Automatic_Name = _outputDir + "\" + automaticModeDirectory;
Directory.CreateDirectory(subDirectory_Automatic_Name);
f = new WmvAdapter(_videoFile,
Path.Combine(subDirectory_Automatic_Name));
}
else
{
if (!Directory.Exists(subDirectoryName))
{
string subDirectory_Manual_Name = _outputDir + "\" + averagesListTextFileDirectory + "_Manual";
Directory.CreateDirectory(subDirectory_Manual_Name);
f = new WmvAdapter(_videoFile,
Path.Combine(subDirectory_Manual_Name));
}
f = new WmvAdapter(_videoFile,
Path.Combine(subDirectoryName));
}
button1.Enabled = false;
f.Secondpass = secondpass;
f.FramesToSave = _fts;
f.FrameCountAvailable += new WmvAdapter.FrameCountEventHandler(f_FrameCountAvailable);
f.StatusChanged += new WmvAdapter.EventHandler(f_StatusChanged);
f.ProgressChanged += new WmvAdapter.ProgressEventHandler(f_ProgressChanged);
this.Text = "Processing Please Wait...";
label5.ForeColor = Color.Green;
label5.Text = "Processing Please Wait";
button8.Enabled = false;
button5.Enabled = false;
label5.Visible = true;
pictureBox1.Image = Lightnings_Extractor.Properties.Resources.Weather_Michmoret;
Hrs = 0; //number of hours
Min = 0; //number of Minutes
Sec = 0; //number of Sec
timeElapsed = 0;
label10.Text = "00:00:00";
label11.Visible = false;
label12.Visible = false;
label9.Visible = false;
label8.Visible = false;
this.button1.Enabled = false;
myTrackPanelss1.trackBar1.Enabled = false;
this.checkBox2.Enabled = false;
this.checkBox1.Enabled = false;
numericUpDown1.Enabled = false;
timer1.Start();
//this.Enabled = false;
label2.Text = "";
label1.Visible = true;
label2.Visible = true;
label3.Visible = true;
label4.Visible = true;
f.Start();
}[/code]
This is the two buttons that start the operation one for manual one for automatic both are using the Start function:
<pre class="prettyprint private void button1_Click(object sender, EventArgs e)
{
viewToolStripMenuItem.Enabled = false;
fileToolStripMenuItem.Enabled = false;
button2.Enabled = false;
label14.Visible = false;
label15.Visible = false;
label21.Visible = false;
label22.Visible = false;
label24.Visible = false;
label25.Visible = false;
ExtractAutomatic = false;
if (secondPass == true)
{
Start(true);
}
Start(false);
}
private void button8_Click(object sender, EventArgs e)
{
viewToolStripMenuItem.Enabled = false;
fileToolStripMenuItem.Enabled = false;
button2.Enabled = false;
label14.Visible = false;
label15.Visible = false;
label21.Visible = false;
label22.Visible = false;
label24.Visible = false;
label25.Visible = false;
ExtractAutomatic = true;
DirectoryInfo info = new DirectoryInfo(_videoFile);
string dirName = info.Name;
automaticModeDirectory = dirName + "_Automatic";
subDirectoryName = _outputDir + "\" + automaticModeDirectory;
if (secondPass == true)
{
Start(true);
}
Start(false);
}[/code]
Now when i click the cancel operation button im getting error in the WmvAdapter.cs class on the line:
<pre class="prettyprint hr = _mediaEvent.WaitForCompletion(100, out evCode);[/code]
The error is: COM object that has been separated from its underlying RCW cannot be used.
This line is part of the function WaitUntilDone()
<pre class="prettyprint public void WaitUntilDone()
{
int hr;
const int eAbort = unchecked((int)0x80004004);
do
{
System.Windows.Forms.Application.DoEvents();
EventCode evCode;
hr = _mediaEvent.WaitForCompletion(100, out evCode);
}while (hr == eAbort);
DsError.ThrowExceptionForHR(hr);
OnStatusChanged();
}[/code]
This function WaitUntilDone() is called in the WmvAdapter.cs Start() function:
<pre class="prettyprint public void Start()
{
EstimateFrameCount();
int hr = _mediaCtrl.Run();
WaitUntilDone();
DsError.ThrowExceptionForHR(hr);
}[/code]
I want that when i click the Cancel Operation buttin it will stop all the actions and return to the program regular so i can use it again like nothing happened.
This is the full code of the WmvAdapter.cs:
<pre class="prettyprint 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;
namespace Polkan.DataSource
{
internal class WmvAdapter : ISampleGrabberCB, IDisposable
{
#region Fields_Properties_and_Events
int count = 0;
const string fileName = @"d:histogramValues.dat";
private IFilterGraph2 _filterGraph;
private IMediaControl _mediaCtrl;
private IMediaEvent _mediaEvent;
private int _width;
private int _height;
private readonly string _outFolder;
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;
private IMediaSeeking _mSeek;
private long _duration = 0;
private long _avgFrameTime = 0;
//just save the averages to a List (not to fs)
public List<double> AveragesList { get; set; }
public List<long> histogramValuesList;
public bool Secondpass { get; set; }
public List<int> FramesToSave { get; set; }
#endregion
#region Constructors and Destructors
public WmvAdapter(string file, string outFolder)
{
_outFolder = outFolder;
try
{
SetupGraph(file);
}
catch
{
Dispose();
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()
{
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;
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 its 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;
}
}
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)
{
using (var bitmap = new Bitmap(_width, _height, _width * 3, PixelFormat.Format24bppRgb, pBuffer))
{
if (!this.Secondpass)
{
long[] HistogramValues = Form1.GetHistogram(bitmap);
long t = Form1.GetTopLumAmount(HistogramValues, 1000);
Form1.averagesTest.Add(t);
}
else
{
//this is the changed part
if (_frameId > 0)
{
if (Form1.averagesTest[_frameId] / 1000.0 - Form1.averagesTest[_frameId - 1] / 1000.0 > 150.0)
{
count = 6;
}
if (count > 0)
{
bitmap.RotateFlip(RotateFlipType.Rotate180FlipX);
bitmap.Save(Path.Combine(_outFolder, _frameId.ToString("D6") + ".bmp"));
count --;
}
}
}
_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);
//***************************\
// for (int i = 0; i < (int)framesCounts(); i++)
// {
// get histogram values
long[] HistogramValues = Form1.GetHistogram(bitmap);
if (histogramValuesList == null)
histogramValuesList = new List<long>(256);
histogramValuesList.AddRange(HistogramValues);
//***************************\
//}
}
else
{
if (FramesToSave != null && FramesToSave.Contains(_frameId))
{
bitmap.RotateFlip(RotateFlipType.Rotate180FlipX);
bitmap.Save(Path.Combine(_outFolder, _frameId.ToString("D6") + ".bmp"));
// get histogram values
long[] HistogramValues = Form1.GetHistogram(bitmap);
if (histogramValuesList == null)
histogramValuesList = new List<long>(256);
histogramValuesList.AddRange(HistogramValues);
using (BinaryWriter binWriter =
new BinaryWriter(File.Open(fileName, FileMode.Create)))
{
for (int i = 0; i < histogramValuesList.Count; i++)
{
binWriter.Write(histogramValuesList[(int)i]);
}
binWriter.Close();
}
}
}
_frameId++;
//let only report each 100 frames for performance
if (_frameId % 100 == 0)
OnProgressChanged(_frameId);
}
}
return 0;
}
/* int ISampleGrabberCB.SampleCB(double sampleTime, IMediaSample pSample)
{
Marshal.ReleaseComObject(pSample);
return 0;
}
int ISampleGrabberCB.BufferCB(double sampleTime, IntPtr pBuffer, int bufferLen)
{
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);
//***************************\
// for (int i = 0; i < (int)framesCounts(); i++)
// {
// get histogram values
long[] HistogramValues = Form1.GetHistogram(bitmap);
if (histogramValuesList == null)
histogramValuesList = new List<long>(256);
histogramValuesList.AddRange(HistogramValues);
long t = Form1.GetTopLumAmount(HistogramValues, 1000);
//***************************\
Form1.averagesTest.Add(t); // to add this list to a text file or binary file and read the averages from the file when its is Secondpass !!!!!
//}
}
else
{
if (FramesToSave != null && FramesToSave.Contains(_frameId))
{
bitmap.RotateFlip(RotateFlipType.Rotate180FlipX);
bitmap.Save(Path.Combine(_outFolder, _frameId.ToString("D6") + ".bmp"));
// get histogram values
long[] HistogramValues = Form1.GetHistogram(bitmap);
if (histogramValuesList == null)
histogramValuesList = new List<long>(256);
histogramValuesList.AddRange(HistogramValues);
using (BinaryWriter binWriter =
new BinaryWriter(File.Open(fileName, FileMode.Create)))
{
for (int i = 0; i < histogramValuesList.Count; i++)
{
binWriter.Write(histogramValuesList[(int)i]);
}
binWriter.Close();
}
}
for (int x = 1; x < Form1.averagesTest.Count; x++)
{
double fff = Form1.averagesTest[x] / 1000.0 - Form1.averagesTest[x - 1] / 1000.0;
if (Form1.averagesTest[x] / 1000.0 - Form1.averagesTest[x - 1] / 1000.0 > 180.0)
{
bitmap.RotateFlip(RotateFlipType.Rotate180FlipX);
bitmap.Save(Path.Combine(_outFolder, _frameId.ToString("D6") + ".bmp"));
_frameId++;
}
}
}
_frameId++;
//let only report each 100 frames for performance
if (_frameId % 100 == 0)
OnProgressChanged(_frameId);
}
return 0;
}*/
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; }
}
}
[/code]
The f.Dispose() in WmvAdapter.cs is:
<pre class="prettyprint public void Dispose()
{
CloseInterfaces();
}[/code]
And CloseInterfaces() is:
<pre class="prettyprint private void CloseInterfaces()
{
try
{
if (_mediaCtrl != null)
{
_mediaCtrl.Stop();
_mediaCtrl = null;
}
}
catch (Exception ex)
{
Debug.WriteLine(ex);
}
if (_filterGraph != null)
{
Marshal.ReleaseComObject(_filterGraph);
_filterGraph = null;
}
GC.Collect();
}[/code]
I dont know why im getting this error.
Thanks. <hr class="sig danieli
View the full article