This is the method (simplified) that I use for capturing a frame, it returns IntPtr.
public IntPtr CaptureFrame(IMFSourceReader reader)
{
IntPtr imagePointer = IntPtr.Zero;
IMFSample sample = null;
int actualStreamIndex;
int streamFlags;
long timestamp;
hr = reader.ReadSample(0, 0, out actualStreamIndex, out streamFlags, out timestamp, out sample);
MFError.ThrowExceptionForHR(hr);
IMFMediaBuffer mediaBuf;
hr = sample.ConvertToContiguousBuffer(out mediaBuf);
MFError.ThrowExceptionForHR(hr);
int currentLength;
int maxLength;
hr = mediaBuf.Lock(out imagePointer, out maxLength, out currentLength);
MFError.ThrowExceptionForHR(hr);
hr = mediaBuf.Unlock();
MFError.ThrowExceptionForHR(hr);
return imagePointer;
}
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Ok, first of all, this code is just asking for trouble. The imagePointer returned by Lock is only valid (ie should only be used) up until you call Unlock. As soon as you call Unlock, you are no longer guaranteed that imagePointer points to anything. Therefore using imagePointer IN ANY WAY after calling Unlock is a very bad idea. While it might appear to work (sometimes), you are just setting yourself up for trouble.
This method does not allocate any memory, or transfer ownership of the memory to the caller. Do not release or free the memory; the media buffer will free the memory when the media buffer is destroyed.
So, what you need to hang on to is mediaBuf, which you can free with Marshal.ReleaseComObject (after calling Unlock). Depending, you may also want to hang on to (and release) sample.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hi
Every time I capture a frame, I get IntPtr with image memory address. After saving the image, I'd like to release the pointer. How to do it correctly?
Methods below won't do the trick (they randomly freez the application):
This is the method (simplified) that I use for capturing a frame, it returns IntPtr.
Where to start?
Ok, first of all, this code is just asking for trouble. The imagePointer returned by Lock is only valid (ie should only be used) up until you call Unlock. As soon as you call Unlock, you are no longer guaranteed that imagePointer points to anything. Therefore using imagePointer IN ANY WAY after calling Unlock is a very bad idea. While it might appear to work (sometimes), you are just setting yourself up for trouble.
Second, looking at the docs for IMFMediaBuffer::Lock, we see:
So, what you need to hang on to is mediaBuf, which you can free with Marshal.ReleaseComObject (after calling Unlock). Depending, you may also want to hang on to (and release) sample.
Thank you, it's working now.