[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
Filed under: Programming
March 6th, 2010 at 10:49 am
OK, never mind. I just needed a few ideas to begin with the code.
Anyway, thanks for all your help
March 6th, 2010 at 10:02 am
sorry i`m not going to do your work, you can read directshow documentation on msdn or read some directshow books
March 6th, 2010 at 4:28 am
umm, can you please elaborate using code? thanks
March 5th, 2010 at 8:33 am
connect source filter to encoder and encoder to file writer
March 5th, 2010 at 12:25 am
How do I save the captured video on the file system?
December 24th, 2009 at 2:53 pm
doesnt work what? which exactly class?
December 24th, 2009 at 1:42 pm
Not works for HTC HD2