EDN Admin
Well-known member
I have a calss that extract frames from a video file.
Once the extraction is done im doing some calculations in the class there is function called WaitUntilDone()
<div style="color:Black;background-color:White; <pre>
<span style="color:Blue; public <span style="color:Blue; void WaitUntilDone()
{
<span style="color:Blue; int y = 0;
<span style="color:Blue; int hr;
<span style="color:Blue; const <span style="color:Blue; int eAbort = <span style="color:Blue; unchecked((<span style="color:Blue; int)0x80004004);
<span style="color:Blue; do
{
System.Windows.Forms.Application.DoEvents();
EventCode evCode;
hr = _mediaEvent.WaitForCompletion(100, <span style="color:Blue; out evCode);
} <span style="color:Blue; while (hr == eAbort);
<span style="color:Blue; for (<span style="color:Blue; int i = 0; i < results.Count; i++)
{
<span style="color:Blue; if (results > 0)
{
y = y + 1;
<span style="color:Green; //maximum = results;
<span style="color:Green; //minimum = results;
<span style="color:Blue; if (y == 1)
{
maximum = results;
minimum = results;
<span style="color:Green; //max_min.WriteLine(maximum);
<span style="color:Green; //max_min.WriteLine(minimum);
<span style="color:Green; //max_min.Close();
<span style="color:Green; //break;
}
<span style="color:Blue; else
{
<span style="color:Blue; if (results > maximum)
{
maximum = results;
<span style="color:Green; //max_min.WriteLine(maximum);
}
<span style="color:Blue; if (results < minimum)
{
minimum = results;
<span style="color:Green; //max_min.WriteLine(minimum);
}
}
}
}
max_min_threshold = 0.8 * (maximum - minimum) + minimum;
<span style="color:Blue; for (<span style="color:Blue; int i = 0; i < results.Count; i++)
{
<span style="color:Blue; if (results > max_min_threshold)
{
}
}
<span style="color:Green; //max_min.Close();
w.Close();
threshold();
<span style="color:Green; //here you can close the streamwriter, if its on class level
<span style="color:Green; //but dont forget to re-instanciate it when doing the job more than once from
OnStatusChanged();
DsError.ThrowExceptionForHR(hr);
}
[/code]
<br/>
Now in this function in the bottom i did:
for (int i = 0; i < results.Count; i++)<br/>
{<br/>
if (results > max_min_threshold)<br/>
{
<br/>
}<br/>
}
I want that if results > max_min_threshold extract or save to hard disk on this frames.
The problem is that the program already done its work.
So im stuck here how can i run now the class again so it will save only this frames to the hard disk ?
----------------------
Another thing in the top level of this class i have: private IMediaSeeking iSeeking;
And then i can do in the class somewhere iSeeking.SetPositions that should help me to jump to the places where i want to save the frames ot hard disk.
In the first time im running the program its working on all over the frames and just get the average light of them.
On the second time i want to run over again the frames again but this time to use this:
for (int i = 0; i < results.Count; i++)<br/>
{<br/>
if (results > max_min_threshold)<br/>
{
<br/>
}<br/>
}
And then using the iSeeking and save to the hard disk all the frames that fit to the conditions in the loop and IF
This is the class full code where first time im running it in the bottom im retricing the average light of each frame.
<div style="color:Black;background-color:White; <pre>
<span style="color:Blue; using System;
<span style="color:Blue; using System.Diagnostics;
<span style="color:Blue; using System.Drawing;
<span style="color:Blue; using System.Drawing.Imaging;
<span style="color:Blue; using System.IO;
<span style="color:Blue; using System.Runtime.InteropServices;
<span style="color:Blue; using DirectShowLib;
<span style="color:Blue; using System.Windows.Forms;
<span style="color:Blue; using System.Collections.Generic;
<span style="color:Blue; using Extracting_Frames;
<span style="color:Blue; internal <span style="color:Blue; class WmvAdapter : ISampleGrabberCB, IDisposable
{
<span style="color:Blue; #region Fields
<span style="color:Blue; private IMediaSeeking iSeeking;
<span style="color:Blue; double max_min_threshold;
<span style="color:Blue; double maximum = 0;
<span style="color:Blue; double minimum = 255;
<span style="color:Blue; public List<<span style="color:Blue; double> results { <span style="color:Blue; get; <span style="color:Blue; set; }
StreamWriter w = <span style="color:Blue; new StreamWriter(<span style="color:#A31515; @"d:results.txt");
StreamWriter max_min = <span style="color:Blue; new StreamWriter(<span style="color:#A31515; @"d:max_min.txt");
<span style="color:Blue; private IFilterGraph2 _filterGraph;
<span style="color:Blue; private IMediaControl _mediaCtrl;
<span style="color:Blue; private IMediaEvent _mediaEvent;
<span style="color:Blue; private <span style="color:Blue; int _width;
<span style="color:Blue; private <span style="color:Blue; int _height;
<span style="color:Blue; private <span style="color:Blue; readonly <span style="color:Blue; string _outFolder;
<span style="color:Blue; private <span style="color:Blue; int _frameId;
<span style="color:Green; //better use a custom EventHandler that passes the results of the action to the subscriber.
<span style="color:Blue; public <span style="color:Blue; delegate <span style="color:Blue; void EventHandler(<span style="color:Blue; object sender, EventArgs e);
<span style="color:Blue; public <span style="color:Blue; event EventHandler StatusChanged;
<span style="color:Blue; public <span style="color:Blue; delegate <span style="color:Blue; void FrameCountEventHandler(<span style="color:Blue; object sender, FrameCountEventArgs e);
<span style="color:Blue; public <span style="color:Blue; event FrameCountEventHandler FrameCountAvailable;
<span style="color:Blue; public <span style="color:Blue; delegate <span style="color:Blue; void ProgressEventHandler(<span style="color:Blue; object sender, ProgressEventArgs e);
<span style="color:Blue; public <span style="color:Blue; event ProgressEventHandler ProgressChanged;
<span style="color:Blue; private IMediaSeeking _mSeek;
<span style="color:Blue; private <span style="color:Blue; long _duration = 0;
<span style="color:Blue; private <span style="color:Blue; long _avgFrameTime = 0;
<span style="color:Blue; #endregion
<span style="color:Blue; #region Constructors and Destructors
<span style="color:Blue; public WmvAdapter(<span style="color:Blue; string file, <span style="color:Blue; string outFolder)
{
_outFolder = outFolder;
<span style="color:Blue; try
{
SetupGraph(file);
}
<span style="color:Blue; catch
{
Dispose();
<span style="color:Blue; throw;
}
}
~WmvAdapter()
{
CloseInterfaces();
}
<span style="color:Blue; #endregion
<span style="color:Blue; public <span style="color:Blue; void Dispose()
{
CloseInterfaces();
}
<span style="color:Blue; public <span style="color:Blue; void Start()
{
<span style="color:Green; //Edit: get the duration
_mSeek.GetDuration(<span style="color:Blue; out _duration);
EstimateFrameCount();
<span style="color:Blue; int hr = _mediaCtrl.Run();
WaitUntilDone();
DsError.ThrowExceptionForHR(hr);
}
<span style="color:Blue; public <span style="color:Blue; void WaitUntilDone()
{
<span style="color:Blue; int y = 0;
<span style="color:Blue; int hr;
<span style="color:Blue; const <span style="color:Blue; int eAbort = <span style="color:Blue; unchecked((<span style="color:Blue; int)0x80004004);
<span style="color:Blue; do
{
System.Windows.Forms.Application.DoEvents();
EventCode evCode;
hr = _mediaEvent.WaitForCompletion(100, <span style="color:Blue; out evCode);
} <span style="color:Blue; while (hr == eAbort);
<span style="color:Blue; for (<span style="color:Blue; int i = 0; i < results.Count; i++)
{
<span style="color:Blue; if (results > 0)
{
y = y + 1;
<span style="color:Green; //maximum = results;
<span style="color:Green; //minimum = results;
<span style="color:Blue; if (y == 1)
{
maximum = results;
minimum = results;
<span style="color:Green; //max_min.WriteLine(maximum);
<span style="color:Green; //max_min.WriteLine(minimum);
<span style="color:Green; //max_min.Close();
<span style="color:Green; //break;
}
<span style="color:Blue; else
{
<span style="color:Blue; if (results > maximum)
{
maximum = results;
<span style="color:Green; //max_min.WriteLine(maximum);
}
<span style="color:Blue; if (results < minimum)
{
minimum = results;
<span style="color:Green; //max_min.WriteLine(minimum);
}
}
}
}
max_min_threshold = 0.8 * (maximum - minimum) + minimum;
<span style="color:Blue; for (<span style="color:Blue; int i = 0; i < results.Count; i++)
{
<span style="color:Blue; if (results > max_min_threshold)
{
}
}
<span style="color:Green; //max_min.Close();
w.Close();
threshold();
<span style="color:Green; //here you can close the streamwriter, if its on class level
<span style="color:Green; //but dont forget to re-instanciate it when doing the job more than once from
OnStatusChanged();
DsError.ThrowExceptionForHR(hr);
}
<span style="color:Green; /*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);
OnStatusChanged();
DsError.ThrowExceptionForHR(hr);*/
<span style="color:Green; //Edit: added events
<span style="color:Blue; protected <span style="color:Blue; virtual <span style="color:Blue; void OnStatusChanged()
{
<span style="color:Blue; if (StatusChanged != <span style="color:Blue; null)
StatusChanged(<span style="color:Blue; this, <span style="color:Blue; new EventArgs());
}
<span style="color:Blue; protected <span style="color:Blue; virtual <span style="color:Blue; void OnFrameCountAvailable(<span style="color:Blue; long frameCount)
{
<span style="color:Blue; if (FrameCountAvailable != <span style="color:Blue; null)
FrameCountAvailable(<span style="color:Blue; this, <span style="color:Blue; new FrameCountEventArgs() { FrameCount = frameCount });
}
<span style="color:Blue; protected <span style="color:Blue; virtual <span style="color:Blue; void OnProgressChanged(<span style="color:Blue; int frameID)
{
<span style="color:Blue; if (ProgressChanged != <span style="color:Blue; null)
ProgressChanged(<span style="color:Blue; this, <span style="color:Blue; new ProgressEventArgs() { FrameID = frameID });
}
<span style="color:Gray; /// <span style="color:Gray; <summary><span style="color:Green; build the capture graph for grabber. </summary>
<span style="color:Blue; private <span style="color:Blue; void SetupGraph(<span style="color:Blue; string file)
{
ISampleGrabber sampGrabber = <span style="color:Blue; null;
IBaseFilter capFilter = <span style="color:Blue; null;
IBaseFilter nullrenderer = <span style="color:Blue; null;
_filterGraph = (IFilterGraph2)<span style="color:Blue; new FilterGraph();
_mediaCtrl = (IMediaControl)_filterGraph;
_mediaEvent = (IMediaEvent)_filterGraph;
_mSeek = (IMediaSeeking)_filterGraph;
<span style="color:Blue; var mediaFilt = (IMediaFilter)_filterGraph;
<span style="color:Blue; try
{
<span style="color:Green; // Add the video source
<span style="color:Blue; int hr = _filterGraph.AddSourceFilter(file, <span style="color:#A31515; "Ds.NET FileFilter", <span style="color:Blue; out capFilter);
DsError.ThrowExceptionForHR(hr);
<span style="color:Green; // Get the SampleGrabber interface
sampGrabber = <span style="color:Blue; new SampleGrabber() <span style="color:Blue; as ISampleGrabber;
<span style="color:Blue; var baseGrabFlt = sampGrabber <span style="color:Blue; as IBaseFilter;
ConfigureSampleGrabber(sampGrabber);
<span style="color:Green; // Add the frame grabber to the graph
hr = _filterGraph.AddFilter(baseGrabFlt, <span style="color:#A31515; "Ds.NET Grabber");
DsError.ThrowExceptionForHR(hr);
<span style="color:Green; // ---------------------------------
<span style="color:Green; // Connect the file filter to the sample grabber
<span style="color:Green; // Hopefully this will be the video pin, we could check by reading its mediatype
IPin iPinOut = DsFindPin.ByDirection(capFilter, PinDirection.Output, 0);
<span style="color:Green; // Get the input pin from the sample grabber
IPin iPinIn = DsFindPin.ByDirection(baseGrabFlt, PinDirection.Input, 0);
hr = _filterGraph.Connect(iPinOut, iPinIn);
DsError.ThrowExceptionForHR(hr);
<span style="color:Green; // Add the null renderer to the graph
nullrenderer = <span style="color:Blue; new NullRenderer() <span style="color:Blue; as IBaseFilter;
hr = _filterGraph.AddFilter(nullrenderer, <span style="color:#A31515; "Null renderer");
DsError.ThrowExceptionForHR(hr);
<span style="color:Green; // ---------------------------------
<span style="color:Green; // 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);
<span style="color:Green; // Turn off the clock. This causes the frames to be sent
<span style="color:Green; // thru the graph as fast as possible
hr = mediaFilt.SetSyncSource(<span style="color:Blue; null);
DsError.ThrowExceptionForHR(hr);
<span style="color:Green; // Read and cache the image sizes
SaveSizeInfo(sampGrabber);
}
<span style="color:Blue; finally
{
<span style="color:Blue; if (capFilter != <span style="color:Blue; null)
{
Marshal.ReleaseComObject(capFilter);
}
<span style="color:Blue; if (sampGrabber != <span style="color:Blue; null)
{
Marshal.ReleaseComObject(sampGrabber);
}
<span style="color:Blue; if (nullrenderer != <span style="color:Blue; null)
{
Marshal.ReleaseComObject(nullrenderer);
}
GC.Collect();
}
}
<span style="color:Blue; private <span style="color:Blue; void EstimateFrameCount()
{
<span style="color:Green; //1sec / averageFrameTime
<span style="color:Blue; long fr = 10000000 / _avgFrameTime;
<span style="color:Blue; double frameCount = fr * (_duration / 10000000.0);
OnFrameCountAvailable((<span style="color:Blue; long)frameCount);
}
<span style="color:Blue; private <span style="color:Blue; void SaveSizeInfo(ISampleGrabber sampGrabber)
{
<span style="color:Green; // Get the media type from the SampleGrabber
<span style="color:Blue; var media = <span style="color:Blue; new AMMediaType();
<span style="color:Blue; int hr = sampGrabber.GetConnectedMediaType(media);
DsError.ThrowExceptionForHR(hr);
<span style="color:Blue; if ((media.formatType != FormatType.VideoInfo) || (media.formatPtr == IntPtr.Zero))
{
<span style="color:Blue; throw <span style="color:Blue; new NotSupportedException(<span style="color:#A31515; "Unknown Grabber Media Format");
}
<span style="color:Green; // Grab the size info
<span style="color:Blue; var videoInfoHeader = (VideoInfoHeader)Marshal.PtrToStructure(media.formatPtr, <span style="color:Blue; typeof(VideoInfoHeader));
_width = videoInfoHeader.BmiHeader.Width;
_height = videoInfoHeader.BmiHeader.Height;
<span style="color:Green; //Edit: get framerate
_avgFrameTime = videoInfoHeader.AvgTimePerFrame;
DsUtils.FreeAMMediaType(media);
GC.Collect();
}
<span style="color:Blue; private <span style="color:Blue; void ConfigureSampleGrabber(ISampleGrabber sampGrabber)
{
<span style="color:Blue; var media = <span style="color:Blue; new AMMediaType
{
majorType = MediaType.Video,
subType = MediaSubType.RGB24,
formatType = FormatType.VideoInfo
};
<span style="color:Blue; int hr = sampGrabber.SetMediaType(media);
DsError.ThrowExceptionForHR(hr);
DsUtils.FreeAMMediaType(media);
GC.Collect();
hr = sampGrabber.SetCallback(<span style="color:Blue; this, 1);
DsError.ThrowExceptionForHR(hr);
}
<span style="color:Blue; private <span style="color:Blue; void CloseInterfaces()
{
<span style="color:Blue; try
{
<span style="color:Blue; if (_mediaCtrl != <span style="color:Blue; null)
{
_mediaCtrl.Stop();
_mediaCtrl = <span style="color:Blue; null;
}
}
<span style="color:Blue; catch (Exception ex)
{
Debug.WriteLine(ex);
}
<span style="color:Blue; if (_filterGraph != <span style="color:Blue; null)
{
Marshal.ReleaseComObject(_filterGraph);
_filterGraph = <span style="color:Blue; null;
}
GC.Collect();
}
<span style="color:Blue; int ISampleGrabberCB.SampleCB(<span style="color:Blue; double sampleTime, IMediaSample pSample)
{
Marshal.ReleaseComObject(pSample);
<span style="color:Blue; return 0;
}
Bitmap bitmap;
<span style="color:Green; //add a boolean property to indicate the save-mode
<span style="color:Blue; public <span style="color:Blue; bool SaveToDisc { <span style="color:Blue; get; <span style="color:Blue; set; }
<span style="color:Green; //the list for the bitmaps
<span style="color:Blue; public List<Bitmap> Images { <span style="color:Blue; get; <span style="color:Blue; set; }
<span style="color:Blue; int ISampleGrabberCB.BufferCB(<span style="color:Blue; double sampleTime, IntPtr pBuffer, <span style="color:Blue; int bufferLen)
{
<span style="color:Blue; using (bitmap = <span style="color:Blue; new Bitmap(_width, _height, _width * 3, PixelFormat.Format24bppRgb, pBuffer))
{
<span style="color:Green; //Bitmap bitmaps = PixelsGray(bitmap);
<span style="color:Blue; double average = GetAveragePixelValue(bitmap);
<span style="color:Green; //Bitmap bitmaps = converttoBlackAndWhite(bitmap);
<span style="color:Blue; if (SaveToDisc)
{
bitmap.RotateFlip(RotateFlipType.Rotate180FlipX);
bitmap.Save(Path.Combine(_outFolder, _frameId.ToString(<span style="color:#A31515; "D6") + <span style="color:#A31515; ".bmp"));
_frameId++;
}
<span style="color:Blue; else
{
<span style="color:Green; /*if (average > 10)
{
bitmap.RotateFlip(RotateFlipType.Rotate180FlipX);
bitmap.Save(Path.Combine(_outFolder, _frameId.ToString("D6") + ".bmp"));
}*/
w.WriteLine(average);
<span style="color:Blue; if (results == <span style="color:Blue; null)
results = <span style="color:Blue; new List<<span style="color:Blue; double>();
results.Add(average);
<span style="color:Green; //w.WriteLine(" " + _frameId);
_frameId++;
<span style="color:Green; /*if (_frameId == 9227 || _frameId == 9228)
{
bitmap.RotateFlip(RotateFlipType.Rotate180FlipX);
bitmap.Save(Path.Combine(_outFolder, _frameId.ToString("D6") + ".bmp"));
}*/
<span style="color:Blue; if (_frameId % 100 == 0)
OnProgressChanged(_frameId);
<span style="color:Green; /*if (_frameId >= 1800)
{
bitmap.Save(Path.Combine(_outFolder, _frameId.ToString("D6") + ".bmp"));
}*/
<span style="color:Green; //let only report each 100 frames for performance
}
}
<span style="color:Blue; return 0;
}
<span style="color:Blue; private Bitmap PixelsGray(Bitmap originals)
{
<span style="color:Blue; double numberpixels = 0;
<span style="color:Blue; double big_Sum = 0;
<span style="color:Blue; double sum;
Bitmap newGray;
newGray = <span style="color:Blue; new Bitmap(originals.Width, originals.Height);
<span style="color:Blue; int x, y;
<span style="color:Blue; for (x = 0; x < newGray.Width; x++)
{
<span style="color:Blue; for (y = 0; y < originals.Height; y++)
{
Color originalColor = originals.GetPixel(x, y);
<span style="color:Blue; double WhiteBlack = (<span style="color:Blue; int)((originalColor.R) + (originalColor.G)
+ (originalColor.B));
sum = WhiteBlack / 3;
big_Sum = big_Sum + sum;
<span style="color:Green; //newColor = Color.FromArgb(255,(int)sum,(int)sum,(int)sum);
<span style="color:Green; //newGray.SetPixel(x, y, newColor);
numberpixels = originals.Width * originals.Height;
}
}
<span style="color:Blue; double result = big_Sum / numberpixels;
<span style="color:Blue; if (results == <span style="color:Blue; null)
results = <span style="color:Blue; new List<<span style="color:Blue; double>();
results.Add(result);
<span style="color:Blue; return newGray;
}
<span style="color:Blue; private Bitmap converttoBlackAndWhite(Bitmap original)
{
Bitmap newBitmap = <span style="color:Blue; new Bitmap(original.Width, original.Height);
<span style="color:Green; //get a graphics object from the new image
Graphics g = Graphics.FromImage(newBitmap);
<span style="color:Green; //create the grayscale ColorMatrix
ColorMatrix colorMatrix = <span style="color:Blue; new ColorMatrix(
<span style="color:Blue; new <span style="color:Blue; float[][]
{
<span style="color:Blue; new <span style="color:Blue; float[] {.3f, .3f, .3f, 0, 0},
<span style="color:Blue; new <span style="color:Blue; float[] {.59f, .59f, .59f, 0, 0},
<span style="color:Blue; new <span style="color:Blue; float[] {.11f, .11f, .11f, 0, 0},
<span style="color:Blue; new <span style="color:Blue; float[] {0, 0, 0, 1, 0},
<span style="color:Blue; new <span style="color:Blue; float[] {0, 0, 0, 0, 1}
});
<span style="color:Green; //create some image attributes
ImageAttributes attributes = <span style="color:Blue; new ImageAttributes();
<span style="color:Green; //set the color matrix attribute
attributes.SetColorMatrix(colorMatrix);
<span style="color:Green; //draw the original image on the new image
<span style="color:Green; //using the grayscale color matrix
g.DrawImage(original, <span style="color:Blue; new Rectangle(0, 0, original.Width, original.Height),
0, 0, original.Width, original.Height, GraphicsUnit.Pixel, attributes);
<span style="color:Green; //dispose the Graphics object
g.Dispose();
<span style="color:Blue; return newBitmap;
}
<span style="color:Blue; private <span style="color:Blue; unsafe <span style="color:Blue; double GetAveragePixelValue(Bitmap bmp)
{
BitmapData bmData = <span style="color:Blue; null;
<span style="color:Blue; try
{
bmData = bmp.LockBits(<span style="color:Blue; new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
<span style="color:Blue; int stride = bmData.Stride;
IntPtr scan0 = bmData.Scan0;
<span style="color:Blue; int w = bmData.Width;
<span style="color:Blue; int h = bmData.Height;
<span style="color:Blue; long sum = 0;
<span style="color:Blue; long pixels = bmp.Width * bmp.Height;
<span style="color:Blue; byte* p = (<span style="color:Blue; byte*)scan0.ToPointer();
<span style="color:Blue; for (<span style="color:Blue; int y = 0; y < h; y++)
{
p = (<span style="color:Blue; byte*)scan0.ToPointer();
p += y * stride;
<span style="color:Blue; for (<span style="color:Blue; int x = 0; x < w; x++)
{
<span style="color:Blue; double i = (p[0] + p[1] + p[2]) / 3.0;
sum += (<span style="color:Blue; long)i;
p += 3;
}
<span style="color:Green; //no offset incrementation needed when getting
<span style="color:Green; //the pointer at the start of each row
}
bmp.UnlockBits(bmData);
<span style="color:Blue; long result = sum / pixels;
<span style="color:Blue; return (<span style="color:Blue; int)result;
}
<span style="color:Blue; catch
{
<span style="color:Blue; try
{
bmp.UnlockBits(bmData);
}
<span style="color:Blue; catch
{
}
}
<span style="color:Blue; return -1;
}
<span style="color:Blue; private <span style="color:Blue; void threshold()
{
}
}
<span style="color:Blue; public <span style="color:Blue; class FrameCountEventArgs
{
<span style="color:Blue; public <span style="color:Blue; long FrameCount { <span style="color:Blue; get; <span style="color:Blue; set; }
}
<span style="color:Blue; public <span style="color:Blue; class ProgressEventArgs
{
<span style="color:Blue; public <span style="color:Blue; int FrameID { <span style="color:Blue; get; <span style="color:Blue; set; }
}
[/code]
<br/>
I tried to make start() inside the loop and if in the done() function so it will start over again and then somehow to save to hard disk the frames i need but it throwing error.
<hr class="sig danieli
View the full article
Once the extraction is done im doing some calculations in the class there is function called WaitUntilDone()
<div style="color:Black;background-color:White; <pre>
<span style="color:Blue; public <span style="color:Blue; void WaitUntilDone()
{
<span style="color:Blue; int y = 0;
<span style="color:Blue; int hr;
<span style="color:Blue; const <span style="color:Blue; int eAbort = <span style="color:Blue; unchecked((<span style="color:Blue; int)0x80004004);
<span style="color:Blue; do
{
System.Windows.Forms.Application.DoEvents();
EventCode evCode;
hr = _mediaEvent.WaitForCompletion(100, <span style="color:Blue; out evCode);
} <span style="color:Blue; while (hr == eAbort);
<span style="color:Blue; for (<span style="color:Blue; int i = 0; i < results.Count; i++)
{
<span style="color:Blue; if (results > 0)
{
y = y + 1;
<span style="color:Green; //maximum = results;
<span style="color:Green; //minimum = results;
<span style="color:Blue; if (y == 1)
{
maximum = results;
minimum = results;
<span style="color:Green; //max_min.WriteLine(maximum);
<span style="color:Green; //max_min.WriteLine(minimum);
<span style="color:Green; //max_min.Close();
<span style="color:Green; //break;
}
<span style="color:Blue; else
{
<span style="color:Blue; if (results > maximum)
{
maximum = results;
<span style="color:Green; //max_min.WriteLine(maximum);
}
<span style="color:Blue; if (results < minimum)
{
minimum = results;
<span style="color:Green; //max_min.WriteLine(minimum);
}
}
}
}
max_min_threshold = 0.8 * (maximum - minimum) + minimum;
<span style="color:Blue; for (<span style="color:Blue; int i = 0; i < results.Count; i++)
{
<span style="color:Blue; if (results > max_min_threshold)
{
}
}
<span style="color:Green; //max_min.Close();
w.Close();
threshold();
<span style="color:Green; //here you can close the streamwriter, if its on class level
<span style="color:Green; //but dont forget to re-instanciate it when doing the job more than once from
OnStatusChanged();
DsError.ThrowExceptionForHR(hr);
}
[/code]
<br/>
Now in this function in the bottom i did:
for (int i = 0; i < results.Count; i++)<br/>
{<br/>
if (results > max_min_threshold)<br/>
{
<br/>
}<br/>
}
I want that if results > max_min_threshold extract or save to hard disk on this frames.
The problem is that the program already done its work.
So im stuck here how can i run now the class again so it will save only this frames to the hard disk ?
----------------------
Another thing in the top level of this class i have: private IMediaSeeking iSeeking;
And then i can do in the class somewhere iSeeking.SetPositions that should help me to jump to the places where i want to save the frames ot hard disk.
In the first time im running the program its working on all over the frames and just get the average light of them.
On the second time i want to run over again the frames again but this time to use this:
for (int i = 0; i < results.Count; i++)<br/>
{<br/>
if (results > max_min_threshold)<br/>
{
<br/>
}<br/>
}
And then using the iSeeking and save to the hard disk all the frames that fit to the conditions in the loop and IF
This is the class full code where first time im running it in the bottom im retricing the average light of each frame.
<div style="color:Black;background-color:White; <pre>
<span style="color:Blue; using System;
<span style="color:Blue; using System.Diagnostics;
<span style="color:Blue; using System.Drawing;
<span style="color:Blue; using System.Drawing.Imaging;
<span style="color:Blue; using System.IO;
<span style="color:Blue; using System.Runtime.InteropServices;
<span style="color:Blue; using DirectShowLib;
<span style="color:Blue; using System.Windows.Forms;
<span style="color:Blue; using System.Collections.Generic;
<span style="color:Blue; using Extracting_Frames;
<span style="color:Blue; internal <span style="color:Blue; class WmvAdapter : ISampleGrabberCB, IDisposable
{
<span style="color:Blue; #region Fields
<span style="color:Blue; private IMediaSeeking iSeeking;
<span style="color:Blue; double max_min_threshold;
<span style="color:Blue; double maximum = 0;
<span style="color:Blue; double minimum = 255;
<span style="color:Blue; public List<<span style="color:Blue; double> results { <span style="color:Blue; get; <span style="color:Blue; set; }
StreamWriter w = <span style="color:Blue; new StreamWriter(<span style="color:#A31515; @"d:results.txt");
StreamWriter max_min = <span style="color:Blue; new StreamWriter(<span style="color:#A31515; @"d:max_min.txt");
<span style="color:Blue; private IFilterGraph2 _filterGraph;
<span style="color:Blue; private IMediaControl _mediaCtrl;
<span style="color:Blue; private IMediaEvent _mediaEvent;
<span style="color:Blue; private <span style="color:Blue; int _width;
<span style="color:Blue; private <span style="color:Blue; int _height;
<span style="color:Blue; private <span style="color:Blue; readonly <span style="color:Blue; string _outFolder;
<span style="color:Blue; private <span style="color:Blue; int _frameId;
<span style="color:Green; //better use a custom EventHandler that passes the results of the action to the subscriber.
<span style="color:Blue; public <span style="color:Blue; delegate <span style="color:Blue; void EventHandler(<span style="color:Blue; object sender, EventArgs e);
<span style="color:Blue; public <span style="color:Blue; event EventHandler StatusChanged;
<span style="color:Blue; public <span style="color:Blue; delegate <span style="color:Blue; void FrameCountEventHandler(<span style="color:Blue; object sender, FrameCountEventArgs e);
<span style="color:Blue; public <span style="color:Blue; event FrameCountEventHandler FrameCountAvailable;
<span style="color:Blue; public <span style="color:Blue; delegate <span style="color:Blue; void ProgressEventHandler(<span style="color:Blue; object sender, ProgressEventArgs e);
<span style="color:Blue; public <span style="color:Blue; event ProgressEventHandler ProgressChanged;
<span style="color:Blue; private IMediaSeeking _mSeek;
<span style="color:Blue; private <span style="color:Blue; long _duration = 0;
<span style="color:Blue; private <span style="color:Blue; long _avgFrameTime = 0;
<span style="color:Blue; #endregion
<span style="color:Blue; #region Constructors and Destructors
<span style="color:Blue; public WmvAdapter(<span style="color:Blue; string file, <span style="color:Blue; string outFolder)
{
_outFolder = outFolder;
<span style="color:Blue; try
{
SetupGraph(file);
}
<span style="color:Blue; catch
{
Dispose();
<span style="color:Blue; throw;
}
}
~WmvAdapter()
{
CloseInterfaces();
}
<span style="color:Blue; #endregion
<span style="color:Blue; public <span style="color:Blue; void Dispose()
{
CloseInterfaces();
}
<span style="color:Blue; public <span style="color:Blue; void Start()
{
<span style="color:Green; //Edit: get the duration
_mSeek.GetDuration(<span style="color:Blue; out _duration);
EstimateFrameCount();
<span style="color:Blue; int hr = _mediaCtrl.Run();
WaitUntilDone();
DsError.ThrowExceptionForHR(hr);
}
<span style="color:Blue; public <span style="color:Blue; void WaitUntilDone()
{
<span style="color:Blue; int y = 0;
<span style="color:Blue; int hr;
<span style="color:Blue; const <span style="color:Blue; int eAbort = <span style="color:Blue; unchecked((<span style="color:Blue; int)0x80004004);
<span style="color:Blue; do
{
System.Windows.Forms.Application.DoEvents();
EventCode evCode;
hr = _mediaEvent.WaitForCompletion(100, <span style="color:Blue; out evCode);
} <span style="color:Blue; while (hr == eAbort);
<span style="color:Blue; for (<span style="color:Blue; int i = 0; i < results.Count; i++)
{
<span style="color:Blue; if (results > 0)
{
y = y + 1;
<span style="color:Green; //maximum = results;
<span style="color:Green; //minimum = results;
<span style="color:Blue; if (y == 1)
{
maximum = results;
minimum = results;
<span style="color:Green; //max_min.WriteLine(maximum);
<span style="color:Green; //max_min.WriteLine(minimum);
<span style="color:Green; //max_min.Close();
<span style="color:Green; //break;
}
<span style="color:Blue; else
{
<span style="color:Blue; if (results > maximum)
{
maximum = results;
<span style="color:Green; //max_min.WriteLine(maximum);
}
<span style="color:Blue; if (results < minimum)
{
minimum = results;
<span style="color:Green; //max_min.WriteLine(minimum);
}
}
}
}
max_min_threshold = 0.8 * (maximum - minimum) + minimum;
<span style="color:Blue; for (<span style="color:Blue; int i = 0; i < results.Count; i++)
{
<span style="color:Blue; if (results > max_min_threshold)
{
}
}
<span style="color:Green; //max_min.Close();
w.Close();
threshold();
<span style="color:Green; //here you can close the streamwriter, if its on class level
<span style="color:Green; //but dont forget to re-instanciate it when doing the job more than once from
OnStatusChanged();
DsError.ThrowExceptionForHR(hr);
}
<span style="color:Green; /*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);
OnStatusChanged();
DsError.ThrowExceptionForHR(hr);*/
<span style="color:Green; //Edit: added events
<span style="color:Blue; protected <span style="color:Blue; virtual <span style="color:Blue; void OnStatusChanged()
{
<span style="color:Blue; if (StatusChanged != <span style="color:Blue; null)
StatusChanged(<span style="color:Blue; this, <span style="color:Blue; new EventArgs());
}
<span style="color:Blue; protected <span style="color:Blue; virtual <span style="color:Blue; void OnFrameCountAvailable(<span style="color:Blue; long frameCount)
{
<span style="color:Blue; if (FrameCountAvailable != <span style="color:Blue; null)
FrameCountAvailable(<span style="color:Blue; this, <span style="color:Blue; new FrameCountEventArgs() { FrameCount = frameCount });
}
<span style="color:Blue; protected <span style="color:Blue; virtual <span style="color:Blue; void OnProgressChanged(<span style="color:Blue; int frameID)
{
<span style="color:Blue; if (ProgressChanged != <span style="color:Blue; null)
ProgressChanged(<span style="color:Blue; this, <span style="color:Blue; new ProgressEventArgs() { FrameID = frameID });
}
<span style="color:Gray; /// <span style="color:Gray; <summary><span style="color:Green; build the capture graph for grabber. </summary>
<span style="color:Blue; private <span style="color:Blue; void SetupGraph(<span style="color:Blue; string file)
{
ISampleGrabber sampGrabber = <span style="color:Blue; null;
IBaseFilter capFilter = <span style="color:Blue; null;
IBaseFilter nullrenderer = <span style="color:Blue; null;
_filterGraph = (IFilterGraph2)<span style="color:Blue; new FilterGraph();
_mediaCtrl = (IMediaControl)_filterGraph;
_mediaEvent = (IMediaEvent)_filterGraph;
_mSeek = (IMediaSeeking)_filterGraph;
<span style="color:Blue; var mediaFilt = (IMediaFilter)_filterGraph;
<span style="color:Blue; try
{
<span style="color:Green; // Add the video source
<span style="color:Blue; int hr = _filterGraph.AddSourceFilter(file, <span style="color:#A31515; "Ds.NET FileFilter", <span style="color:Blue; out capFilter);
DsError.ThrowExceptionForHR(hr);
<span style="color:Green; // Get the SampleGrabber interface
sampGrabber = <span style="color:Blue; new SampleGrabber() <span style="color:Blue; as ISampleGrabber;
<span style="color:Blue; var baseGrabFlt = sampGrabber <span style="color:Blue; as IBaseFilter;
ConfigureSampleGrabber(sampGrabber);
<span style="color:Green; // Add the frame grabber to the graph
hr = _filterGraph.AddFilter(baseGrabFlt, <span style="color:#A31515; "Ds.NET Grabber");
DsError.ThrowExceptionForHR(hr);
<span style="color:Green; // ---------------------------------
<span style="color:Green; // Connect the file filter to the sample grabber
<span style="color:Green; // Hopefully this will be the video pin, we could check by reading its mediatype
IPin iPinOut = DsFindPin.ByDirection(capFilter, PinDirection.Output, 0);
<span style="color:Green; // Get the input pin from the sample grabber
IPin iPinIn = DsFindPin.ByDirection(baseGrabFlt, PinDirection.Input, 0);
hr = _filterGraph.Connect(iPinOut, iPinIn);
DsError.ThrowExceptionForHR(hr);
<span style="color:Green; // Add the null renderer to the graph
nullrenderer = <span style="color:Blue; new NullRenderer() <span style="color:Blue; as IBaseFilter;
hr = _filterGraph.AddFilter(nullrenderer, <span style="color:#A31515; "Null renderer");
DsError.ThrowExceptionForHR(hr);
<span style="color:Green; // ---------------------------------
<span style="color:Green; // 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);
<span style="color:Green; // Turn off the clock. This causes the frames to be sent
<span style="color:Green; // thru the graph as fast as possible
hr = mediaFilt.SetSyncSource(<span style="color:Blue; null);
DsError.ThrowExceptionForHR(hr);
<span style="color:Green; // Read and cache the image sizes
SaveSizeInfo(sampGrabber);
}
<span style="color:Blue; finally
{
<span style="color:Blue; if (capFilter != <span style="color:Blue; null)
{
Marshal.ReleaseComObject(capFilter);
}
<span style="color:Blue; if (sampGrabber != <span style="color:Blue; null)
{
Marshal.ReleaseComObject(sampGrabber);
}
<span style="color:Blue; if (nullrenderer != <span style="color:Blue; null)
{
Marshal.ReleaseComObject(nullrenderer);
}
GC.Collect();
}
}
<span style="color:Blue; private <span style="color:Blue; void EstimateFrameCount()
{
<span style="color:Green; //1sec / averageFrameTime
<span style="color:Blue; long fr = 10000000 / _avgFrameTime;
<span style="color:Blue; double frameCount = fr * (_duration / 10000000.0);
OnFrameCountAvailable((<span style="color:Blue; long)frameCount);
}
<span style="color:Blue; private <span style="color:Blue; void SaveSizeInfo(ISampleGrabber sampGrabber)
{
<span style="color:Green; // Get the media type from the SampleGrabber
<span style="color:Blue; var media = <span style="color:Blue; new AMMediaType();
<span style="color:Blue; int hr = sampGrabber.GetConnectedMediaType(media);
DsError.ThrowExceptionForHR(hr);
<span style="color:Blue; if ((media.formatType != FormatType.VideoInfo) || (media.formatPtr == IntPtr.Zero))
{
<span style="color:Blue; throw <span style="color:Blue; new NotSupportedException(<span style="color:#A31515; "Unknown Grabber Media Format");
}
<span style="color:Green; // Grab the size info
<span style="color:Blue; var videoInfoHeader = (VideoInfoHeader)Marshal.PtrToStructure(media.formatPtr, <span style="color:Blue; typeof(VideoInfoHeader));
_width = videoInfoHeader.BmiHeader.Width;
_height = videoInfoHeader.BmiHeader.Height;
<span style="color:Green; //Edit: get framerate
_avgFrameTime = videoInfoHeader.AvgTimePerFrame;
DsUtils.FreeAMMediaType(media);
GC.Collect();
}
<span style="color:Blue; private <span style="color:Blue; void ConfigureSampleGrabber(ISampleGrabber sampGrabber)
{
<span style="color:Blue; var media = <span style="color:Blue; new AMMediaType
{
majorType = MediaType.Video,
subType = MediaSubType.RGB24,
formatType = FormatType.VideoInfo
};
<span style="color:Blue; int hr = sampGrabber.SetMediaType(media);
DsError.ThrowExceptionForHR(hr);
DsUtils.FreeAMMediaType(media);
GC.Collect();
hr = sampGrabber.SetCallback(<span style="color:Blue; this, 1);
DsError.ThrowExceptionForHR(hr);
}
<span style="color:Blue; private <span style="color:Blue; void CloseInterfaces()
{
<span style="color:Blue; try
{
<span style="color:Blue; if (_mediaCtrl != <span style="color:Blue; null)
{
_mediaCtrl.Stop();
_mediaCtrl = <span style="color:Blue; null;
}
}
<span style="color:Blue; catch (Exception ex)
{
Debug.WriteLine(ex);
}
<span style="color:Blue; if (_filterGraph != <span style="color:Blue; null)
{
Marshal.ReleaseComObject(_filterGraph);
_filterGraph = <span style="color:Blue; null;
}
GC.Collect();
}
<span style="color:Blue; int ISampleGrabberCB.SampleCB(<span style="color:Blue; double sampleTime, IMediaSample pSample)
{
Marshal.ReleaseComObject(pSample);
<span style="color:Blue; return 0;
}
Bitmap bitmap;
<span style="color:Green; //add a boolean property to indicate the save-mode
<span style="color:Blue; public <span style="color:Blue; bool SaveToDisc { <span style="color:Blue; get; <span style="color:Blue; set; }
<span style="color:Green; //the list for the bitmaps
<span style="color:Blue; public List<Bitmap> Images { <span style="color:Blue; get; <span style="color:Blue; set; }
<span style="color:Blue; int ISampleGrabberCB.BufferCB(<span style="color:Blue; double sampleTime, IntPtr pBuffer, <span style="color:Blue; int bufferLen)
{
<span style="color:Blue; using (bitmap = <span style="color:Blue; new Bitmap(_width, _height, _width * 3, PixelFormat.Format24bppRgb, pBuffer))
{
<span style="color:Green; //Bitmap bitmaps = PixelsGray(bitmap);
<span style="color:Blue; double average = GetAveragePixelValue(bitmap);
<span style="color:Green; //Bitmap bitmaps = converttoBlackAndWhite(bitmap);
<span style="color:Blue; if (SaveToDisc)
{
bitmap.RotateFlip(RotateFlipType.Rotate180FlipX);
bitmap.Save(Path.Combine(_outFolder, _frameId.ToString(<span style="color:#A31515; "D6") + <span style="color:#A31515; ".bmp"));
_frameId++;
}
<span style="color:Blue; else
{
<span style="color:Green; /*if (average > 10)
{
bitmap.RotateFlip(RotateFlipType.Rotate180FlipX);
bitmap.Save(Path.Combine(_outFolder, _frameId.ToString("D6") + ".bmp"));
}*/
w.WriteLine(average);
<span style="color:Blue; if (results == <span style="color:Blue; null)
results = <span style="color:Blue; new List<<span style="color:Blue; double>();
results.Add(average);
<span style="color:Green; //w.WriteLine(" " + _frameId);
_frameId++;
<span style="color:Green; /*if (_frameId == 9227 || _frameId == 9228)
{
bitmap.RotateFlip(RotateFlipType.Rotate180FlipX);
bitmap.Save(Path.Combine(_outFolder, _frameId.ToString("D6") + ".bmp"));
}*/
<span style="color:Blue; if (_frameId % 100 == 0)
OnProgressChanged(_frameId);
<span style="color:Green; /*if (_frameId >= 1800)
{
bitmap.Save(Path.Combine(_outFolder, _frameId.ToString("D6") + ".bmp"));
}*/
<span style="color:Green; //let only report each 100 frames for performance
}
}
<span style="color:Blue; return 0;
}
<span style="color:Blue; private Bitmap PixelsGray(Bitmap originals)
{
<span style="color:Blue; double numberpixels = 0;
<span style="color:Blue; double big_Sum = 0;
<span style="color:Blue; double sum;
Bitmap newGray;
newGray = <span style="color:Blue; new Bitmap(originals.Width, originals.Height);
<span style="color:Blue; int x, y;
<span style="color:Blue; for (x = 0; x < newGray.Width; x++)
{
<span style="color:Blue; for (y = 0; y < originals.Height; y++)
{
Color originalColor = originals.GetPixel(x, y);
<span style="color:Blue; double WhiteBlack = (<span style="color:Blue; int)((originalColor.R) + (originalColor.G)
+ (originalColor.B));
sum = WhiteBlack / 3;
big_Sum = big_Sum + sum;
<span style="color:Green; //newColor = Color.FromArgb(255,(int)sum,(int)sum,(int)sum);
<span style="color:Green; //newGray.SetPixel(x, y, newColor);
numberpixels = originals.Width * originals.Height;
}
}
<span style="color:Blue; double result = big_Sum / numberpixels;
<span style="color:Blue; if (results == <span style="color:Blue; null)
results = <span style="color:Blue; new List<<span style="color:Blue; double>();
results.Add(result);
<span style="color:Blue; return newGray;
}
<span style="color:Blue; private Bitmap converttoBlackAndWhite(Bitmap original)
{
Bitmap newBitmap = <span style="color:Blue; new Bitmap(original.Width, original.Height);
<span style="color:Green; //get a graphics object from the new image
Graphics g = Graphics.FromImage(newBitmap);
<span style="color:Green; //create the grayscale ColorMatrix
ColorMatrix colorMatrix = <span style="color:Blue; new ColorMatrix(
<span style="color:Blue; new <span style="color:Blue; float[][]
{
<span style="color:Blue; new <span style="color:Blue; float[] {.3f, .3f, .3f, 0, 0},
<span style="color:Blue; new <span style="color:Blue; float[] {.59f, .59f, .59f, 0, 0},
<span style="color:Blue; new <span style="color:Blue; float[] {.11f, .11f, .11f, 0, 0},
<span style="color:Blue; new <span style="color:Blue; float[] {0, 0, 0, 1, 0},
<span style="color:Blue; new <span style="color:Blue; float[] {0, 0, 0, 0, 1}
});
<span style="color:Green; //create some image attributes
ImageAttributes attributes = <span style="color:Blue; new ImageAttributes();
<span style="color:Green; //set the color matrix attribute
attributes.SetColorMatrix(colorMatrix);
<span style="color:Green; //draw the original image on the new image
<span style="color:Green; //using the grayscale color matrix
g.DrawImage(original, <span style="color:Blue; new Rectangle(0, 0, original.Width, original.Height),
0, 0, original.Width, original.Height, GraphicsUnit.Pixel, attributes);
<span style="color:Green; //dispose the Graphics object
g.Dispose();
<span style="color:Blue; return newBitmap;
}
<span style="color:Blue; private <span style="color:Blue; unsafe <span style="color:Blue; double GetAveragePixelValue(Bitmap bmp)
{
BitmapData bmData = <span style="color:Blue; null;
<span style="color:Blue; try
{
bmData = bmp.LockBits(<span style="color:Blue; new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
<span style="color:Blue; int stride = bmData.Stride;
IntPtr scan0 = bmData.Scan0;
<span style="color:Blue; int w = bmData.Width;
<span style="color:Blue; int h = bmData.Height;
<span style="color:Blue; long sum = 0;
<span style="color:Blue; long pixels = bmp.Width * bmp.Height;
<span style="color:Blue; byte* p = (<span style="color:Blue; byte*)scan0.ToPointer();
<span style="color:Blue; for (<span style="color:Blue; int y = 0; y < h; y++)
{
p = (<span style="color:Blue; byte*)scan0.ToPointer();
p += y * stride;
<span style="color:Blue; for (<span style="color:Blue; int x = 0; x < w; x++)
{
<span style="color:Blue; double i = (p[0] + p[1] + p[2]) / 3.0;
sum += (<span style="color:Blue; long)i;
p += 3;
}
<span style="color:Green; //no offset incrementation needed when getting
<span style="color:Green; //the pointer at the start of each row
}
bmp.UnlockBits(bmData);
<span style="color:Blue; long result = sum / pixels;
<span style="color:Blue; return (<span style="color:Blue; int)result;
}
<span style="color:Blue; catch
{
<span style="color:Blue; try
{
bmp.UnlockBits(bmData);
}
<span style="color:Blue; catch
{
}
}
<span style="color:Blue; return -1;
}
<span style="color:Blue; private <span style="color:Blue; void threshold()
{
}
}
<span style="color:Blue; public <span style="color:Blue; class FrameCountEventArgs
{
<span style="color:Blue; public <span style="color:Blue; long FrameCount { <span style="color:Blue; get; <span style="color:Blue; set; }
}
<span style="color:Blue; public <span style="color:Blue; class ProgressEventArgs
{
<span style="color:Blue; public <span style="color:Blue; int FrameID { <span style="color:Blue; get; <span style="color:Blue; set; }
}
[/code]
<br/>
I tried to make start() inside the loop and if in the done() function so it will start over again and then somehow to save to hard disk the frames i need but it throwing error.
<hr class="sig danieli
View the full article