public Bitmap GetNextFrame( )
{
lock ( sync )
{
if ( file == IntPtr.Zero )
{
throw new System.IO.IOException( "Cannot read video frames since video file is not open." );
}
// get frame at specified position
IntPtr DIB = Win32.AVIStreamGetFrame( getFrame, position );
if ( DIB == IntPtr.Zero )
throw new VideoException( "Failed getting frame." );
Win32.BITMAPINFOHEADER bitmapInfoHeader;
// copy BITMAPINFOHEADER from unmanaged memory
bitmapInfoHeader = (Win32.BITMAPINFOHEADER) Marshal.PtrToStructure( DIB, typeof( Win32.BITMAPINFOHEADER ) );
// create new bitmap
Bitmap image = new Bitmap( width, height, PixelFormat.Format24bppRgb );
// lock bitmap data
BitmapData imageData = image.LockBits(
new Rectangle( 0, 0, width, height ),
ImageLockMode.ReadWrite,
PixelFormat.Format24bppRgb );
// copy image data
int srcStride = imageData.Stride;
int dstStride = imageData.Stride;
// check image direction
if ( bitmapInfoHeader.height > 0 )
{
// it`s a bottom-top image
int dst = imageData.Scan0.ToInt32( ) + dstStride * ( height - 1 );
int src = DIB.ToInt32( ) + Marshal.SizeOf( typeof( Win32.BITMAPINFOHEADER ) );
for ( int y = 0; y < height; y++ )
{
Win32.memcpy( dst, src, srcStride );
dst -= dstStride;
src += srcStride;
}
}
else
{
// it`s a top bootom image
int dst = imageData.Scan0.ToInt32( );
int src = DIB.ToInt32( ) + Marshal.SizeOf( typeof( Win32.BITMAPINFOHEADER ) );
// copy the whole image
Win32.memcpy( dst, src, srcStride * height );
}
// unlock bitmap data
image.UnlockBits( imageData );
// move position to the next frame
position++;
return image;
}
}
}
/// <summary> /// Worker thread. /// </summary> /// private void WorkerThread( ) { ReasonToFinishPlaying reasonToStop = ReasonToFinishPlaying.StoppedByUser; // AVI reader AVIReader aviReader = new AVIReader( ); try { // open file aviReader.Open( source ); // stop positions int stopPosition = aviReader.Start + aviReader.Length; // frame interval int interval = ( frameIntervalFromSource ) ? (int) ( 1000 / aviReader.FrameRate ) : frameInterval; while ( !stopEvent.WaitOne( 0, false ) ) { // start time DateTime start = DateTime.Now; // get next frame Bitmap bitmap = aviReader.GetNextFrame( ); framesReceived++; bytesReceived += bitmap.Width * bitmap.Height * ( Bitmap.GetPixelFormatSize( bitmap.PixelFormat ) >> 3 ); if ( NewFrame != null ) NewFrame( this, new NewFrameEventArgs( bitmap ) ); // free image bitmap.Dispose( ); // check current position if ( aviReader.Position >= stopPosition ) { reasonToStop = ReasonToFinishPlaying.EndOfStreamReached; break; } // wait for a while ? if ( interval > 0 ) { // get frame extract duration TimeSpan span = DateTime.Now.Subtract( start ); // miliseconds to sleep int msec = interval - (int) span.TotalMilliseconds; if ( ( msec > 0 ) && ( stopEvent.WaitOne( msec, false ) ) ) break; } } } catch ( Exception exception ) { // provide information to clients if ( VideoSourceError != null ) { VideoSourceError( this, new VideoSourceErrorEventArgs( exception.Message ) ); } } aviReader.Dispose( ); aviReader = null; if ( PlayingFinished != null ) { PlayingFinished( this, reasonToStop ); } }