[Windows Mobile] Capturing Raw Frames or SampleGrabber and DirectShow.NETCF
What is SampleGrabber? this is filter (as a rule Transform or TransInPlace) that goes after filter which samples we are going to grab.
Why do we need SampleGrabber?
1. In windows mobile this is the fastest way to still images, more than that we still uncompressed images (so we dont loose time for encoding/decoding)
2. We can use SampleGrabber to draw text or images on received stream
3. We grab images to memory.
I Think this is enough to say that sample grabber is useful.
The problem is that windows already have sample grabber and we dont need to make any extra moves to use it, but Windows Mobile knows nothing about sample grabber
On www.codeproject.com you can find some articles that explain how to implement SampleGrabber. But there tons limits and problems in every case, so i decided to implement my own.
The main question was “Is it possible to implement SampleGrabber that not need to registered?”. I meant that if i programming on C++ i can use unit (class) that contain samplegrabber code, i if i programming on any other language i can use this unit compiled to dll. Yes its possible (!!!!) we dont need resvrCE and anything else, just unit or dll
I was going to use developed SampleGrabber for barcode reader, but samples that i receive were too blurred to be recognized even by human (may be this is my cam dieing? O,o). anyway that was reason i decided to stop work on it, so here is what i got for this time:
DirectShowNETCF.Native.dll that contain SampleGrabber. How to use it?
[DllImport("DirectShowNETCF.Native.dll")]
private static extern IntPtr GetBaseFilter();
this is method returns IntPtr that equal to IBaseFilter*
how to get IBaseFilter?
IntPtr grabber_ = GetBaseFilter(); IBaseFilter grabber = (IBaseFilter)Marshal.GetTypedObjectForIUnknown(grabber_, typeof(IBaseFilter));
To grab raw frame you have to call
1. getSize(out long size)
2. alloc memory (use DirectShowNETCF.PInvoke.LocalAlloc(0×40, size))
3. call getFrame(IntPtr pBuff)
[ComVisible(true), ComImport,
Guid("2B21644A-D405-4E27-A51C-A4812bE0CE4C"),
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IGetFrame
{
[PreserveSig]
int getFrame(IntPtr pBuff);
[PreserveSig]
int getSize([Out] out long size);
}
//example of grabbing frame
public IntPtr grabFrame(ref long bufSize)
{
IntPtr res_ = IntPtr.Zero;
long size = 0;
frmGrabber.getSize(out size);
bufSize = size;
res_ = PInvoke.LocalAlloc(0x40, (int)size);
frmGrabber.getFrame(res_);
return res_;
}
last version of DirectShowNETCF you can download here
Filed under: Programming
August 31st, 2009 at 2:17 pm
If AMCamera worws correct on your device then reason of your exception can be only that you doing something worng
August 31st, 2009 at 9:03 am
IBaseFilter grabber = (IBaseFilter)Marshal.GetTypedObjectForIUnknown(grabber_, typeof(IBaseFilter));
The above line of code should give me the ibasefilter object right? However i got a null exception error, I am not exactly sure how to implement the samplegrabber, must i pinoke it? thanks
August 27th, 2009 at 11:42 am
hi, i got an error:
System.ArgumentNullException was unhandled for
private IBaseFilter grabber = (IBaseFilter)Marshal.GetTypedObjectForIUnknown(grabber_, typeof(IBaseFilter));
i assumed grabber is the samplegrabber itself? i added grabber to the graph and nullrenderer after it. it should grab the frames n send it to the nullrenderer when the graph is started right? how can i use the grabFrame method? thanks lots!
August 25th, 2009 at 3:29 pm
i answered for tgis question like 5 or more times. you should put directshownetcf.native.dll to folder where executable placed
August 25th, 2009 at 1:52 pm
hello:)
i tested the AMCamera example [i had to add a reference to DirectShowNETCF.dll], i copied both DirectShowNETCF.dll and DirectShowNETCF.Native.dll to both \AMCamera\bin\Debug and \AMCamera\bin\Release and i keep receive MissingMethodException was unhandled: Can’t find PInvoke DLL ‘DirectShowNETCF.Native.dll’ in the Init method. I did had to convert the project before opening it in Visual Studio 2008. Any ideas on how to solve this problem?:)
thank you
August 3rd, 2009 at 5:17 pm
I was using the wrong example.
Now it is o.k. with frame garbing.
August 3rd, 2009 at 3:00 pm
I am trying to capture image as a stream or byte array.
But the only method I see is cam_.stillImage.
Below there is I cam_.grabFrame(ref size);
Can you explain me how I can implement this ?
Regards
July 28th, 2009 at 12:57 pm
i pasted the DirectShowNETCF.Native.dll to the folders where amcamera.exe exists but im still having the error of Can’t find PInvoke DLL ‘DirectShowNETCF.Native.dll’. Am i missing something? thanks all.
July 14th, 2009 at 11:49 am
Hi,
I thought that grabFrame() returns the bitmap inverted, but as it turns out the image is FLIPPED horizontally. Am I doing something wrong??
IntPtr buff = cam_.grabFrame(ref size);
// copy raw data to an array
byte[] array = new byte[(int)size];
Marshal.Copy(buff, array, 0, (int)size);
Bitmap bmp = new Bitmap(width, height);
BitmapData data =
bmp.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadWrite, PixelFormat.Format16bppRgb565);
System.Runtime.InteropServices.Marshal.Copy(array, 0, data.Scan0, array.Length);
DirectShowNETCF.PInvoke.LocalFree(buff);
array = null;
bmp.UnlockBits(data);
July 6th, 2009 at 7:43 am
Hi, thanks a lot.
Copying the DLLs to the same folder in which exe exists solved my problem.
Thanks a lot.