[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

49 Responses to “[Windows Mobile] Capturing Raw Frames or SampleGrabber and DirectShow.NETCF”

  1. 1
    KenG Says:

    Tested DirectShowNETCF.dll enumerating and setting resolution feature - works great. Started to test the sample grabber (AMCamera) by first using your C# example…however your example does not appear to work with the current version of the DLL…am I missing something?

  2. 2
    admin Says:

    Oops :) Sorry that was debug version :D will update soon

  3. 3
    admin Says:

    Updated :)

  4. 4
    N Says:

    AMCamera dont work :( ¿why?

  5. 5
    admin Says:

    What do you mean by “does not work”? did you put DirectShowNETCF.Native.dll to the folder where executable?

  6. 6
    N Says:

    The camera does not display when I press button Start
    Nice work

  7. 7
    admin Says:

    does init and start return true?

  8. 8
    N Says:

    The panel is in black, do not worry it will resolve
    When made the video capture?
    Thanks for reply
    Greetings

  9. 9
    admin Says:

    Color of panel says nothing. methods init and start returns boolean if it false it means that its impossible for some reasons init or start graph

  10. 10
    N Says:

    The method init return false

  11. 11
    admin Says:

    I made minor changes, now example says where exaclty problem, new version uploaded, can you check it?

  12. 12
    N Says:

    Now see that, you’re the best.
    I look forward to your next update;)

  13. 13
    admin Says:

    Does it work or you can see reason why it failed? if reason please tell me it

  14. 14
    N Says:

    I think it’s because at some point in the execution method init () returns false and can not be displayed then the method run () does not start.
    It’s what I think, remember I’m newbie on directshow XD

  15. 15
    admin Says:

    Man i uploaded new version and new Demo of AMCamera if it fail on init method it return why, please check it on your device, because it works on mine

  16. 16
    N Says:

    Ah sorry I had not seen, if it works now, you’re the boss
    Thanks!!!!

  17. 17
    KenG Says:

    Tested AMCamera example and everything works fine on Motorola MC55. I tried to save the raw frame data to a bmp and/or jpg file assuming the default resolution for my device (W=352, H=288). However, I am apparently not doing something correctly. Below is the code added to AMCamera example. Not sure if you had planned on adding functionality to DLL to do this.

    using System.Drawing.Imaging;
    using System.Runtime.InteropServices;

    private void button1_Click(object sender, EventArgs e)
    {
    long size = 0;
    IntPtr data = cam_.grabFrame(ref size);

    byte[] array = new byte[(int)size];
    System.Runtime.InteropServices.Marshal.Copy(data, array, 0, (int)size);
    DirectShowNETCF.PInvoke.LocalFree(data);

    try
    {
    Bitmap bmp = CopyDataToBitmap(array);
    bmp.Save(textBox1.Text, System.Drawing.Imaging.ImageFormat.Bmp);
    }
    catch (Exception err)
    {
    MessageBox.Show(err.Message);
    }

    //System.IO.FileStream fs = new System.IO.FileStream(textBox1.Text, System.IO.FileMode.Create);
    //fs.Write(array, 0, (int)size);
    //fs.Flush();
    //fs.Close();
    array = null;
    }

    private Bitmap CopyDataToBitmap(byte[] data)
    {
    //Create the Bitmap to the know height, width and format
    Bitmap bmp = new Bitmap(352, 288, PixelFormat.Format24bppRgb);

    //Create a BitmapData and Lock all pixels to be written
    BitmapData bmpData = bmp.LockBits(
    new Rectangle(0, 0, bmp.Width, bmp.Height),
    ImageLockMode.WriteOnly,
    PixelFormat.Format24bppRgb);

    //Copy the data from the byte array into BitmapData.Scan0
    Marshal.Copy(data, 0, bmpData.Scan0, data.Length);

    //Unlock the pixels
    bmp.UnlockBits(bmpData);

    //Return the bitmap
    return bmp;

    }

  18. 18
    admin Says:

    Hi KenG,

    the problem is that i`m almost sure that camera returns raw frames in YUY12 format or something from YUV, and to receive bitmat you will need to convert it to rgb and than copy to bitmap (dont forget about stride), but if we talk about YUV you should notify that first part of memory (width * height) this is grayscale image, very useful because most morfology algorithms use grayscale images

  19. 19
    Mint Says:

    Hi, I downloaded the Directshownetcf.dll from ur website and also the examples written in C#.
    Camera project is working fine on Windows Mobile Emulator 6.
    But when I started the AMCamera project, it is giving error on init-
    Can’t find PInvoke DLL ‘DirectShowNETCF.Native.dll’.

    Am i missing somthing ?
    Thanks.

  20. 20
    admin Says:

    Hello,
    Yes you forgot to load DirectShowNETCF.Native.dll on device (to the same folder where exacutable placed)

  21. 21
    Mint Says:

    Hi, thanks a lot.
    Copying the DLLs to the same folder in which exe exists solved my problem.

    Thanks a lot.

  22. 22
    cHRIS Says:

    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);

  23. 23
    jd Says:

    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.

  24. 24
    Brujo Says:

    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

  25. 25
    Brujo Says:

    I was using the wrong example.
    Now it is o.k. with frame garbing.

  26. 26
    sqrt Says:

    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

  27. 27
    admin Says:

    i answered for tgis question like 5 or more times. you should put directshownetcf.native.dll to folder where executable placed

  28. 28
    jd Says:

    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!

  29. 29
    jd Says:

    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 :D

  30. 30
    admin Says:

    If AMCamera worws correct on your device then reason of your exception can be only that you doing something worng

  31. 31
    jd Says:

    I declared private static IntPtr grabber_ = new intPtr(); and private IBaseFilter grabber = null;

    in the init() method, i used the above code > IntPtr grabber_ = GetBaseFilter();
    IBaseFilter grabber = (IBaseFilter)Marshal.GetTypedObjectForIUnknown(grabber_, typeof(IBaseFilter)); the rest of the code is same as the sample above.

    but i kept getting nullargument exception, when i checked the intrptr, it has a value = intptr.zero. any ideas? thank you very much.

  32. 32
    Aram Says:

    Hi , I have problem when running grabFrame(ref size) method, nullreference exception . Please help??

  33. 33
    admin Says:

    i dont know when and how you call this method, so its dificult to help you…

  34. 34
    Jordi Says:

    Hi,
    Can you put a source code example to use the samplegrabber with a custom filter graph like MPEG1?

    Thanx.

  35. 35
    Yasin Says:

    Hi,
    Thanks for sharing such a good info with us.

    I get an error msg that says “Cannot init camera! Result: ConnectGrabberError_2″ when i click start button on device.

    Why do you think that I get this error message ?

    Thanks in advance.

    Yasin

  36. 36
    admin Says:

    ConnectGrabberError_2 means that there something wrong when we trying to connect samplegrabber and video renderer. What exactly class example you got this message on?

  37. 37
    J Says:

    I’m getting ConnectGrabberError_2 on init(), when using DirectShowNETCF.Camera.AMCameraEx.AMCameraEx or DirectShowNETCF.Camera.AMCamera.AMCamera. But DirectShowNETCF.Camera.Camera works fine.

    Any ideas?

  38. 38
    admin Says:

    strange, what OS and what Device you got this problem on?

  39. 39
    J Says:

    Mine is HTC 2125 and WM 5.0

  40. 40
    vinay Says:

    Is there any way to draw images on the stream and make them interactable?

  41. 41
    admin Says:

    2vinay: its not implemented yet, but if you want you can buy samplegrabber sources and draw image you need on raw frame

  42. 42
    Andre Says:

    Same here: “Cannot init camera! Result: ConnectGrabberError_2 ”

    Also DirectShowNETCF.Camera.Camera works fine, but not the others.

    It’s a HTC-8900 - Win 6.0

    Any ideas?

  43. 43
    admin Says:

    seems like HTC cant render rgb24, i`m working on custom renderer now

  44. 44
    Rui Says:

    Sorry to bother you again with this issue… I copied both DirectShowNETCF.dll and DirectShowNETCF.Native.dll to \AMCamera\bin\Debug, the folder where the executable is placed and I still receive MissingMethodException was unhandled: Can’t find PInvoke DLL ‘DirectShowNETCF.Native.dll’ in the Init method.
    Am I missing something?
    In the Output window in VS 2008 all references are loaded except for this one.
    Sorry and thanks for your help.

  45. 45
    admin Says:

    you should put DirectShowNETCF.dll on device where executable deployed

  46. 46
    Rui Says:

    Hey thanks, that worked on the device. It doesn’t work on the simulator however, but solved my problem :)

  47. 47
    vito Says:

    hi!, where is DirectShowNETCF.Native.dll located? I downloaded the DirectShowNetCF libraries, but I have:

    -DirectShowNETCF.dll
    -AMCameraEx.Native.dll
    -AMCamera.Native.dll
    -NullRenderer.dll

    I don’t have DirectShowNETCF.Native.dll. thanks

  48. 48
    vito Says:

    Hi Alex, sorry for all my questions. your blog helps me a lot. I can’t understand how to use the next code you developed.

    //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(0×40, (int)size);
    frmGrabber.getFrame(res_);
    return res_;
    }

    can you show me a mothod calling it?
    thanks!

  49. 49
    mbeg Says:

    Hey alex..thanks for the post..i have ru into a problem though..the camera never captures any frames…says “cannot init camera” when i press start..whats going wrong?please help!
    thanks!

Leave a Reply