[Windows Mobile] Capturing video from device camera C# or DirectShow.NET CF Part II

In previous post i explained how to play video or audio on Windows Mobile devices using DirectShow.
I`ve received some emails with request to explain how preview video from device camera.
First of all in Windows Mobile SDK in examples you can find C++ exmaple. I`ve seen examples that suggest  to compile example from SDK to dll and than importing methos from that dll watch camera preview. I did little bit more, i ported whole code to C# so we dont need any dll. So what do we need? we need import 3 api methods, FindFirstDevice, FindClose and GetClientRect

[DllImport("coredll.dll")]
public static extern int GetClientRect(
[In] IntPtr hWnd,
[Out] out Rect lpRect);

[DllImport("coredll.dll")]
public static extern IntPtr FindFirstDevice(
[In] int searchType,
[In] IntPtr searchParam,
[In, Out] ref DEVMGR_DEVICE_INFORMATION pdi);

[DllImport("coredll.dll")]
public static extern int FindClose([In] IntPtr hFindFile);

also we need 6 more Com Interfaces:
IVideoWindow, IBaseFilter, IPersist, IPersistPropertyBag, IPropertyBag, ICaptureGraphBuilder2

[ComVisible(true), ComImport,
Guid("56A868B4-0AD4-11CE-B03A-0020AF0BA770"),
InterfaceType(ComInterfaceType.InterfaceIsDual)]
public interface IVideoWindow
{
[PreserveSig]
int put_Caption([In] string caption);

[PreserveSig]
int get_Caption([Out] out string caption);

[PreserveSig]
int put_WindowStyle([In] int windowStyle);

[PreserveSig]
int get_WindowStyle([Out] out int windowStyle);

[PreserveSig]
int put_WindowStyleEx([In] int windowStyleEx);

[PreserveSig]
int get_WindowStyleEx(out int windowStyleEx);

[PreserveSig]
int put_AutoShow([In] int autoShow);

[PreserveSig]
int get_AutoShow([Out] out int autoShow);

[PreserveSig]
int put_WindowState([In] int windowState);

[PreserveSig]
int get_WindowState([Out] out int windowState);

[PreserveSig]
int put_BackgroundPalette([In] int backgroundPalette);

[PreserveSig]
int get_BackgroundPalette([Out] out int backgroundPalette);

[PreserveSig]
int put_Visible([In] int visible);

[PreserveSig]
int get_Visible([Out] out int visible);

[PreserveSig]
int put_Left([In] int left);

[PreserveSig]
int get_Left([Out] out int left);

[PreserveSig]
int put_Width([In] int width);

[PreserveSig]
int get_Width([Out] out int width);

[PreserveSig]
int put_Top([In] int top);

[PreserveSig]
int get_Top([Out] out int top);

[PreserveSig]
int put_Height([In] int height);

[PreserveSig]
int get_Height([Out] out int height);

[PreserveSig]
int put_Owner([In] IntPtr owner);

[PreserveSig]
int get_Owner([Out] out IntPtr owner);

[PreserveSig]
int put_MessageDrain([In] IntPtr drain);

[PreserveSig]
int get_MessageDrain([Out] out IntPtr drain);

[PreserveSig]
int get_BorderColor([Out] out int color);

[PreserveSig]
int put_BorderColor([In] int color);

[PreserveSig]
int get_FullScreenMode([Out] out int fullScreenMode);

[PreserveSig]
int put_FullScreenMode([In] int fullScreenMode);

[PreserveSig]
int SetWindowForeground([In] int focus);

[PreserveSig]
int NotifyOwnerMessage(
[In] IntPtr hwnd,
[In] int msg,
[In] IntPtr wParam,
[In] IntPtr lParam);

[PreserveSig]
int SetWindowPosition(
[In] int left,
[In] int top,
[In] int width,
[In] int height);

[PreserveSig]
int GetWindowPosition(
[Out] out int left,
[Out] out int top,
[Out] out int width,
[Out] out int height);

[PreserveSig]
int GetMinIdealImageSize(
[Out] out int width,
[Out] out int height);

[PreserveSig]
int GetMaxIdealImageSize(
[Out] out int width,
[Out] out int height);

[PreserveSig]
int GetRestorePosition(
[Out] out int left,
[Out] out int top,
[Out] out int width,
[Out] out int height);

[PreserveSig]
int HideCursor([In] int hideCursor);

[PreserveSig]
int IsCursorHidden([Out] out int hideCursor);

}

[ComVisible(true), ComImport,
Guid("56A86895-0AD4-11CE-B03A-0020AF0BA770"),
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IBaseFilter
{
[PreserveSig]
int GetClassID([Out] out Guid pClassID);

[PreserveSig]
int Stop();

[PreserveSig]
int Pause();

[PreserveSig]
int Run([In] long tStart);

[PreserveSig]
int GetState(
[In] int dwMilliSecsTimeout,
[Out] out int filtState);

[PreserveSig]
int SetSyncSource([In, MarshalAs(UnmanagedType.Interface)] object pClock);

/// <summary>
///
/// </summary>
[PreserveSig]
int GetSyncSource([Out, MarshalAs(UnmanagedType.Interface)] out object pClock);

[PreserveSig]
int EnumPins([Out, MarshalAs(UnmanagedType.Interface)] out object ppEnum);

[PreserveSig]
int FindPin(
[In, MarshalAs(UnmanagedType.LPWStr)] string Id,
[Out, MarshalAs(UnmanagedType.Interface)] out object ppPin);

[PreserveSig]
int QueryFilterInfo([Out] IntPtr pInfo);

[PreserveSig]
int JoinFilterGraph(
[In, MarshalAs(UnmanagedType.Interface)] object pGraph,
[In, MarshalAs(UnmanagedType.LPWStr)] string pName);

[PreserveSig]
int QueryVendorInfo(
[Out, MarshalAs(UnmanagedType.LPWStr)] out string pVendorInfo);
}

[ComVisible(true), ComImport,
Guid("0000010C-0000-0000-C000-000000000046"),
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IPersist
{
[PreserveSig]
int GetClassID([Out] out Guid pClassID);
}

[ComVisible(true), ComImport,
Guid("37D84F60-42CB-11CE-8135-00AA004BB851"),//Guid("5738E040-B67F-11d0-BD4D-00A0C911CE86"),
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IPersistPropertyBag : IPersist
{
#region IPersist
[PreserveSig]
new int GetClassID([Out] out Guid pClassID);
#endregion

[PreserveSig]
int InitNew();

[PreserveSig]
int Load(
[In] IPropertyBag pPropBag,
[In, MarshalAs(UnmanagedType.Interface)] object pErrorLog
);

[PreserveSig]
int Save(
IPropertyBag pPropBag,
[In, MarshalAs(UnmanagedType.Bool)] bool fClearDirty,
[In, MarshalAs(UnmanagedType.Bool)] bool fSaveAllProperties
);
}

[ComVisible(true), ComImport,
Guid("55272A00-42CB-11CE-8135-00AA004BB851"),
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IPropertyBag
{
[PreserveSig]
int Read(
[In, MarshalAs(UnmanagedType.LPWStr)] string pszPropName,
[In, Out, MarshalAs(UnmanagedType.Struct)]    ref    object pVar,
[In] IntPtr pErrorLog);

[PreserveSig]
int Write(
[In, MarshalAs(UnmanagedType.LPWStr)] string pszPropName,
[In, MarshalAs(UnmanagedType.Struct)] ref object pVar);
}

[ComVisible(true), ComImport,
Guid("93E5A4E0-2D50-11D2-ABFA-00A0C9C6E38D"),
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface ICaptureGraphBuilder2
{
[PreserveSig]
int SetFiltergraph([In] IGraphBuilder pfg);

[PreserveSig]
int GetFiltergraph([Out] out IGraphBuilder ppfg);

[PreserveSig]
int SetOutputFileName(
[In] ref Guid pType,
[In, MarshalAs(UnmanagedType.LPWStr)] string lpstrFile,
[Out] out IBaseFilter ppbf,
[Out, MarshalAs(UnmanagedType.Interface)] out object ppSink);

[PreserveSig]
int FindInterface(
[In] ref CGuid pCategory,
[In] ref CGuid pType,
[In] IBaseFilter pbf,
[In] ref Guid riid,
[Out, MarshalAs(UnmanagedType.IUnknown)] out object ppint);

[PreserveSig]
int RenderStream(
[In, MarshalAs(UnmanagedType.LPStruct)] CGuid PinCategory,
[In, MarshalAs(UnmanagedType.LPStruct)] CGuid MediaType,
[In, MarshalAs(UnmanagedType.IUnknown)] object pSource,
[In] IBaseFilter pfCompressor,
[In] IBaseFilter pfRenderer
);

[PreserveSig]
int ControlStream(
[In] ref CGuid pCategory,
[In] ref CGuid pType,
[In] IBaseFilter pFilter,
[In] IntPtr pstart,
[In] IntPtr pstop,
[In] short wStartCookie,
[In] short wStopCookie);

[PreserveSig]
int AllocCapFile(
[In, MarshalAs(UnmanagedType.LPWStr)] string lpstrFile,
[In] long dwlSize);

[PreserveSig]
int CopyCaptureFile(
[In, MarshalAs(UnmanagedType.LPWStr)] string lpwstrOld,
[In, MarshalAs(UnmanagedType.LPWStr)] string lpwstrNew,
[In] int fAllowEscAbort,
[In, MarshalAs(UnmanagedType.Interface)] object pFilter);

[PreserveSig]
int FindPin(
[In] object pSource,
[In] int pindir,
[In] ref CGuid pCategory,
[In] ref CGuid pType,
[In, MarshalAs(UnmanagedType.Bool)] bool fUnconnected,
[In] int num,
[Out, MarshalAs(UnmanagedType.Interface)] out object ppPin);
}

Everything else the same as in SDK example + i made class to hide directshow from cant or not going to understand it :)
Class got 3 public methods:
init() - inits camera and builds graph
release() - stops preview and releases all com objects
run(IntPtr owner) - start preview on control

using System;
using System.Runtime.InteropServices;

namespace DirectShowNETCF
{
public class CCamera
{
private IBaseFilter video = null;
private IBaseFilter renderer = null;
private ICaptureGraphBuilder2 capGraph = null;
private IGraphBuilder graph = null;
private IVideoWindow window = null;
private IMediaControl control = null;

public CCamera()
{
}

~CCamera()
{
release();
}

public bool init()
{
object obj = null;
#region FilterGraph
Guid clsid = CLSID_.FilterGraph;
Guid riid = IID_.IFilterGraph2;
PInvoke.CoCreateInstance(ref clsid, IntPtr.Zero, (uint)CLSCTX_.INPROC_SERVER, ref riid, out obj);
graph = (IGraphBuilder)obj;
if (graph == null)
{
return false;
}
#endregion
obj = null;
#region CaptureGraph
clsid = CLSID_.CaptureGraphBuilder;
riid = IID_.ICaptuGraphBuilder2;
PInvoke.CoCreateInstance(ref clsid, IntPtr.Zero, (uint)CLSCTX_.INPROC_SERVER, ref riid, out obj);
capGraph = (ICaptureGraphBuilder2)obj;
if (capGraph == null)
{
return false;
}
#endregion
obj = null;

int hr = capGraph.SetFiltergraph(graph);
if (hr < 0)
{
return false;
}

if (!getVideoCaptureFilter())
{
return false;
}

hr = graph.AddFilter(video, "Video Capture");
if (hr < 0)
{
return false;
}

if (!getVideoRenderer())
{
return false;
}

hr = graph.AddFilter(renderer, "Video Renderer");
if (hr < 0)
{
return false;
}
hr = capGraph.RenderStream(null, null, video, null, renderer);
if (hr < 0)
{
return false;
}
control = (IMediaControl)graph;
return true;
}

public void release()
{
if (control != null)
{
control.Stop();
}

if (window != null)
{
window.put_Owner(IntPtr.Zero);
window.put_Visible(-1);
}

if (capGraph != null)
{
Marshal.ReleaseComObject(capGraph);
capGraph = null;
}

if (graph != null)
{
Marshal.ReleaseComObject(graph);
graph = null;
control = null;
}

if (video != null)
{
Marshal.ReleaseComObject(video);
video = null;
}

if (renderer != null)
{
Marshal.ReleaseComObject(renderer);
renderer = null;
window = null;
}
}

public bool run(IntPtr owner)
{
if (window != null)
{
Rect rc = new Rect();
PInvoke.GetClientRect(owner, out rc);
window.put_Owner(owner);
window.SetWindowPosition(rc.Left, rc.Top, rc.Right, rc.Bottom);
window.put_WindowStyle(0x40000000 | 0x02000000);
window.put_Visible(0);
}
else
{
return false;
}
return control.Run() >= 0;
}

private bool getVideoCaptureFilter()
{
object obj = null;
Guid clsid = CLSID_.VideoCapture;
Guid riid = IID_.IBaseFilter;
PInvoke.CoCreateInstance(ref clsid, IntPtr.Zero, (uint)CLSCTX_.INPROC_SERVER, ref riid, out obj);
if (obj == null)
{
return false;
}
video = (IBaseFilter)obj;
obj = null;
string name_ = "";
if (!getName(ref name_))
{
return false;
}

IPersistPropertyBag propBag = (IPersistPropertyBag)video;
if (propBag == null)
{
return false;
}

CPropertyBag bag = new CPropertyBag();
object oname = name_;
bag.Write("VCapName", ref oname);
int hr = propBag.Load(bag, null);
if (hr < 0)
{
//System.Windows.Forms.MessageBox.Show("cannot load prop bag");
return false;
}
return true;

}

private bool getVideoRenderer()
{
object obj = null;
Guid clsid = CLSID_.VideoRenderer;
Guid riid = IID_.IBaseFilter;
PInvoke.CoCreateInstance(ref clsid, IntPtr.Zero, (uint)CLSCTX_.INPROC_SERVER, ref riid, out obj);
if (obj == null)
{
return false;
}
renderer = (IBaseFilter)obj;
window = (IVideoWindow)renderer;
return true;
}

private bool getName(ref string name)
{
IntPtr handle = IntPtr.Zero;
IntPtr guid = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(Guid)));
Marshal.StructureToPtr(CLSID_.Camera, guid, false);
DEVMGR_DEVICE_INFORMATION di = new DEVMGR_DEVICE_INFORMATION();
di.dwSize = (uint)System.Runtime.InteropServices.Marshal.SizeOf(typeof(DEVMGR_DEVICE_INFORMATION));
handle = PInvoke.FindFirstDevice(3, guid, ref di);
Marshal.FreeHGlobal(guid);
if ((handle == IntPtr.Zero)||(di.hDevice == IntPtr.Zero))
{
return false;
}

PInvoke.FindClose(handle);
name = di.szLegacyName;
return true;
}
}

public class CPropertyBag : IPropertyBag
{
private object pVar_ = null;

public CPropertyBag()
{
pVar_ = new object();
}

~CPropertyBag()
{
pVar_ = null;
}

public int Read(
[In, MarshalAs(UnmanagedType.LPWStr)] string pszPropName,
[In, Out, MarshalAs(UnmanagedType.Struct)]    ref    object pVar,
[In] IntPtr pErrorLog)
{
pVar = pVar_;
return 0;
}

public int Write(
[In, MarshalAs(UnmanagedType.LPWStr)] string pszPropName,
[In, MarshalAs(UnmanagedType.Struct)] ref object pVar)
{
pVar_ = pVar;
return 0;
}
}
}

Last version of DirectShowNETCF

46 Responses to “[Windows Mobile] Capturing video from device camera C# or DirectShow.NET CF Part II”

Pages: « 5 4 3 [2] 1 » Show All

  1. 20
    admin Says:

    2Andre check next post… it explains how to still image (image, not video)

  2. 19
    Andre Says:

    Hi there, i want to save (still) image to disk how do i format the graph then ? it seems i need to use dmo with the windows video 9 encoder. are you willing to share the source code ? (or send it to me via email ?)

  3. 18
    dany Says:

    Hi…

    Thx for you source code and dll.

    I have any question that how to save to files any video.

    pls would show me how to use capGraph.SetOutFileName

    capGraph.SetOutputFileName(new CGuid(CLSID_.MEDIASUBTYPE_Asf), “test.asf”, out mux, out sink);

    Is that save to file? use only 1 line

  4. 17
    skean Says:

    one rederer is commentary.
    did start graph and called ControlStream method.
    but there is still a problem.

    um..
    .Net CF Directshow is difficult to find another example..
    would you show another explame?

  5. 16
    admin Says:

    why do you try to connect encoder woth renderer?
    did you start graph?
    also to record video you have to use ControlStream method to start

  6. 15
    skean Says:

    I am poor english. I hope you would understand…
    i wish save avi file from camera. so add the Arcsoft Mpeg-4 DMO Class filter.
    and called capGraph.SetOutputFileName(.., .., .., .., ..)
    but don’t save file.
    attached the a part source.
    =======================================================
    ……..
    ……
    ….

    control = (IMediaControl)graph;
    int hr = capGraph.SetFiltergraph(graph);
    if (!getVideoCaptureFilter(box))
    {
    return false;
    }
    hr = graph.AddFilter(video, “Video Capture”);

    clsid = new Guid(”{E3116EB9-2128-4bee-B267-41B9E44D1150}”); // ArcSoft MPEG-4 Encode DMO Class
    riid = IID_.IBaseFilter;
    PInvoke.CoCreateInstance(ref clsid, IntPtr.Zero, (uint)CLSCTX_.INPROC_SERVER, ref riid, out obj);
    mpeg4 = (IBaseFilter)obj;
    obj = null;
    hr = graph.AddFilter(mpeg4, “ArcSoft MPEG-4 Encode DMO Class”);

    if (!getVideoRenderer())
    {
    return false;
    }

    hr = graph.AddFilter(renderer, “Video Renderer”);

    IFileSinkFilter sink;
    IBaseFilter mux;

    hr = capGraph.SetOutputFileName(new DirectShowNETCF.CGuid(CLSID_.MEDIATYPE_Video), “ChoiHOyeon.avi”, out mux, out sink);
    //capGraph.RenderStream(new DirectShowNETCF.CGuid(CLSID_.VideoCapture), new DirectShowNETCF.CGuid(CLSID_.MEDIASUBTYPE_Asf), video, mpeg4, mux);
    capGraph.RenderStream(new DirectShowNETCF.CGuid(CLSID_.PIN_CATEGORY_PREVIEW), new DirectShowNETCF.CGuid(CLSID_.MEDIATYPE_Video), video, mpeg4, renderer);
    //Marshal.ReleaseComObject(mux);
    //Marshal.ReleaseComObject(sink);

  7. 14
    admin Says:

    Yes, you can! you have to connect camera filter to video encoder, than encoder to samplegrabber than samplegrabber to nullrenderer. You wil receive encoded frames in samplegrabber and you will be able to send it using sockets

  8. 13
    jd Says:

    Hi Alex, thanks for the great program. Can I send out the video via wifi to another smartphone while previewing? Any pointers on how to do that? Thanks.

  9. 12
    KenG Says:

    James, Alex’s DirectShowNETCF.dll functionally does 99% of what i did using C++ directshow api calls. See part III comments. The ability to set resolution (size of image captured) and turning camera flash on and off is the only features missing. Hopefully, he will add those features in future releases of the DLL.

  10. 11
    James Says:

    KenG can you share your progress?

Pages: « 5 4 3 [2] 1 » Show All

Leave a Reply