I have a problem migrating an application to Vista. The following method which runs fine on XP, will randomly throw a memory access exception (violation) on Vista.
/// <summary>
/// Initiates a frame capture through VMR9/7 GetCurrentImage()
///
/// Returns the frame as bmp through the CaptureComplete event, along with
/// the published frame number (ie where the frame will appear in the avi) which is
/// at best an approximate
/// </summary>
[STAThread]
public void CaptureFrame()
{
if((! captureLock) && previewing)
{
captureLock = true; //we need to avoid concurrent calls, as they use the same objects
int hr = 0;
IntPtr bmpPtr = IntPtr.Zero;
IntPtr pDib = IntPtr.Zero;
Bitmap bmp = null;
BitmapInfoHeader bmi = new BitmapInfoHeader();
byte[] buffer;
try
{
//get a pointer to the image
if(! vmr7Mode) hr = videoWindow.GetCurrentImage(out pDib);
else hr = videoWindow7.GetCurrentImage(out pDib);
DsError.ThrowExceptionForHR(hr);
bmi = (BitmapInfoHeader) Marshal.PtrToStructure(pDib, typeof(BitmapInfoHeader));
if (IntPtr.Size == 32)
bmpPtr = new IntPtr(pDib.ToInt32() + bmi.Size);
else
bmpPtr = new IntPtr(pDib.ToInt64() + bmi.Size);
bmp = new Bitmap(bmi.Width, bmi.Height, System.Drawing.Imaging.PixelFormat.Format32bppRgb);
System.Drawing.Imaging.BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, bmi.Width, bmi.Height),
System.Drawing.Imaging.ImageLockMode.WriteOnly,
System.Drawing.Imaging.PixelFormat.Format32bppRgb);
buffer = new byte[bmi.ImageSize];
Marshal.Copy(bmpPtr, buffer, 0, bmi.ImageSize);
Marshal.Copy(buffer, 0,bmpData.Scan0, bmi.ImageSize);
bmp.UnlockBits(bmpData);
<<EXCEPTION>> Marshal.FreeCoTaskMem(pDib); //exception here
bmp.RotateFlip(RotateFlipType.Rotate180FlipX);
//fire the event with the bmp
CaptureComplete(new Bitmap(bmp),CapturedVideoFrames,CurrentFrame);
bmp.Dispose();
}
catch
{
}
finally
{
//clean up anything we have not already dealt with
if(bmpPtr != IntPtr.Zero) Marshal.FreeCoTaskMem(bmpPtr); bmpPtr = IntPtr.Zero;
if(pDib != IntPtr.Zero) Marshal.FreeCoTaskMem(pDib); pDib = IntPtr.Zero;
GC.Collect();
captureLock = false; //re-enable capture
}
}
}
The exception is thrown by Marshal.FreeCoTaskMem() The code works a seemingly random number of times and then explodes.
Any pointers (chessey pun intended) greatfully received.
Thanks