diff --git a/linphone/mediastreamer2/plugins/msdscap/comptr.hh b/linphone/mediastreamer2/plugins/msdscap/comptr.hh
new file mode 100644
index 0000000000000000000000000000000000000000..6bfa0109e9071b85f468246702dba247f1a3f3b8
--- /dev/null
+++ b/linphone/mediastreamer2/plugins/msdscap/comptr.hh
@@ -0,0 +1,73 @@
+/* HornetsEye - Computer Vision with Ruby
+   Copyright (C) 2006, 2007 Jan Wedekind
+   
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>. */
+#ifndef HORNETSEYE_COMPTR_HH
+#define HORNETSEYE_COMPTR_HH
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef WIN32
+#include <cassert>
+#include <objbase.h>
+#include "error.hh"
+
+namespace Hornetseye {
+
+  template< class I >
+  class ComPtr
+  {
+  public:
+    ComPtr(void): m_i(NULL) {}
+    ComPtr( const ComPtr< I > &ptr ): m_i(ptr.get()) {
+      if ( m_i != NULL ) m_i->AddRef();
+    }
+    ~ComPtr(void) { reset(); }
+    ComPtr< I > &operator=( const ComPtr< I > &other ) {
+      reset();
+      m_i = other.get();
+      if ( m_i != NULL ) m_i->AddRef();
+      return *this;
+    };
+    I **operator&(void) {
+      reset();
+      return &m_i;
+    }
+    void coCreateInstance( REFCLSID clsid, REFIID iid, const char *errorText )
+      throw (Error) {
+      reset();
+      COERRORMACRO( CoCreateInstance( clsid, NULL, CLSCTX_INPROC, iid,
+                                      (void **)&m_i ), Error, , errorText );
+    }
+    I *get(void) const { return m_i; }
+    I &operator*(void) {
+      assert( m_i != NULL );
+      return *m_i;
+    }
+    I *operator->(void) {
+      assert( m_i != NULL );
+      return m_i;
+    }
+    void reset(void) { if ( m_i != NULL ) { m_i->Release(); m_i = NULL; } }
+  protected:
+    I *m_i;
+  };
+
+};
+
+#endif
+
+#endif
diff --git a/linphone/mediastreamer2/plugins/msdscap/ds3.cc b/linphone/mediastreamer2/plugins/msdscap/ds3.cc
new file mode 100644
index 0000000000000000000000000000000000000000..2d8dacfd84819c5e4ca0db864901d34f2c1fb0b0
--- /dev/null
+++ b/linphone/mediastreamer2/plugins/msdscap/ds3.cc
@@ -0,0 +1,702 @@
+// This is a DirectShow interface. But maybe you'll find that it's easier to
+// access the camera directly ;)
+
+// http://www.codeguru.com/cpp/g-m/multimedia/video/article.php/c9551/
+// http://lists.mplayerhq.hu/pipermail/ffmpeg-devel/2007-April/027965.html
+// http://msdn2.microsoft.com/en-us/library/ms787594.aspx
+// http://msdn2.microsoft.com/en-us/library/ms787867.aspx
+// NullRenderer wih reference clock set to NULL
+// http://www.videolan.org/
+// http://git.videolan.org/gitweb.cgi?p=vlc.git;f=modules/access/dshow;hb=0.8.6
+
+// #include <wtypes.h>
+// #include <unknwn.h>
+// #include <ole2.h>
+// #include <limits.h>
+// #include <dshow.h>
+
+#include <iostream>
+#include <iomanip>
+#include <fstream>
+#include <windows.h>
+#include <winnls.h>
+#include <errors.h>
+#include <initguid.h>
+#include <ocidl.h>
+#include <malloc.h>
+#include "comptr.hh"
+#include "error.hh"
+
+#define FILTER_NAME L"HornetsEye Capture Filter"
+#define PIN_NAME L"Capture"
+
+using namespace Hornetseye;
+
+DEFINE_GUID( CLSID_VideoInputDeviceCategory, 0x860BB310, 0x5D01,
+             0x11d0, 0xBD, 0x3B, 0x00, 0xA0, 0xC9, 0x11, 0xCE, 0x86);
+DEFINE_GUID( CLSID_SystemDeviceEnum, 0x62BE5D10, 0x60EB, 0x11d0,
+             0xBD, 0x3B, 0x00, 0xA0, 0xC9, 0x11, 0xCE, 0x86 );
+DEFINE_GUID( CLSID_FilterGraph, 0xe436ebb3, 0x524f, 0x11ce,
+             0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70);
+DEFINE_GUID( CLSID_SampleGrabber, 0xc1f400a0, 0x3f08, 0x11d3,
+             0x9f, 0x0b, 0x00, 0x60, 0x08, 0x03, 0x9e, 0x37 );
+DEFINE_GUID( CLSID_NullRenderer,0xc1f400a4, 0x3f08, 0x11d3,
+             0x9f, 0x0b, 0x00, 0x60, 0x08, 0x03, 0x9e, 0x37 );
+DEFINE_GUID( CLSID_VfwCapture, 0x1b544c22, 0xfd0b, 0x11ce,
+             0x8c, 0x63, 0x0, 0xaa, 0x00, 0x44, 0xb5, 0x1e);
+DEFINE_GUID( IID_IGraphBuilder, 0x56a868a9, 0x0ad4, 0x11ce,
+             0xb0, 0x3a, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70);
+DEFINE_GUID( IID_IBaseFilter, 0x56a86895, 0x0ad4, 0x11ce,
+             0xb0, 0x3a, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70 );
+DEFINE_GUID( IID_ICreateDevEnum, 0x29840822, 0x5b84, 0x11d0,
+             0xbd, 0x3b, 0x00, 0xa0, 0xc9, 0x11, 0xce, 0x86 );
+DEFINE_GUID( IID_IEnumFilters, 0x56a86893, 0xad4, 0x11ce,
+             0xb0, 0x3a, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70 );
+DEFINE_GUID( IID_IEnumPins, 0x56a86892, 0x0ad4, 0x11ce,
+             0xb0, 0x3a, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70 );
+DEFINE_GUID( IID_IMediaSample, 0x56a8689a, 0x0ad4, 0x11ce,
+             0xb0, 0x3a, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70 );
+DEFINE_GUID( IID_IMediaFilter, 0x56a86899, 0x0ad4, 0x11ce,
+             0xb0, 0x3a, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70 );
+DEFINE_GUID( IID_IPin, 0x56a86891, 0x0ad4, 0x11ce,
+             0xb0, 0x3a, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70 );
+DEFINE_GUID( IID_ISampleGrabber, 0x6b652fff, 0x11fe, 0x4fce,
+             0x92, 0xad, 0x02, 0x66, 0xb5, 0xd7, 0xc7, 0x8f );
+DEFINE_GUID( IID_ISampleGrabberCB, 0x0579154a, 0x2b53, 0x4994,
+             0xb0, 0xd0, 0xe7, 0x73, 0x14, 0x8e, 0xff, 0x85 );
+DEFINE_GUID( IID_IMediaEvent, 0x56a868b6, 0x0ad4, 0x11ce,
+             0xb0, 0x3a, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70 );
+DEFINE_GUID( IID_IMediaControl, 0x56a868b1, 0x0ad4, 0x11ce,
+             0xb0, 0x3a, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70 );
+DEFINE_GUID( IID_IMemInputPin, 0x56a8689d, 0x0ad4, 0x11ce,
+             0xb0, 0x3a, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70 );
+DEFINE_GUID( IID_IAMStreamConfig, 0xc6e13340, 0x30ac, 0x11d0,
+             0xa1, 0x8c, 0x00, 0xa0, 0xc9, 0x11, 0x89, 0x56 );
+DEFINE_GUID( IID_IVideoProcAmp, 0x4050560e, 0x42a7, 0x413a,
+             0x85, 0xc2, 0x09, 0x26, 0x9a, 0x2d, 0x0f, 0x44 );
+DEFINE_GUID( MEDIATYPE_Video, 0x73646976, 0x0000, 0x0010,
+             0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 );
+DEFINE_GUID( MEDIASUBTYPE_I420, 0x30323449, 0x0000, 0x0010,
+             0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
+DEFINE_GUID( MEDIASUBTYPE_YV12, 0x32315659, 0x0000, 0x0010,
+             0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 );
+DEFINE_GUID( MEDIASUBTYPE_IYUV, 0x56555949, 0x0000, 0x0010,
+             0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 );
+DEFINE_GUID( MEDIASUBTYPE_YUYV, 0x56595559, 0x0000, 0x0010,
+             0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 );
+DEFINE_GUID( MEDIASUBTYPE_YUY2, 0x32595559, 0x0000, 0x0010,
+             0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 );
+DEFINE_GUID( MEDIASUBTYPE_UYVY, 0x59565955, 0x0000, 0x0010,
+             0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 );
+DEFINE_GUID( MEDIASUBTYPE_RGB24, 0xe436eb7d, 0x524f, 0x11ce,
+             0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70 );
+
+using namespace std;
+
+typedef LONGLONG REFERENCE_TIME;
+
+typedef struct tagVIDEOINFOHEADER {
+  RECT rcSource;
+  RECT rcTarget;
+  DWORD dwBitRate;
+  DWORD dwBitErrorRate;
+  REFERENCE_TIME AvgTimePerFrame;
+  BITMAPINFOHEADER bmiHeader;
+} VIDEOINFOHEADER;
+
+typedef struct _AMMediaType {
+  GUID majortype;
+  GUID subtype;
+  BOOL bFixedSizeSamples;
+  BOOL bTemporalCompression;
+  ULONG lSampleSize;
+  GUID formattype;
+  IUnknown *pUnk;
+  ULONG cbFormat;
+  BYTE *pbFormat;
+} AM_MEDIA_TYPE;
+
+DECLARE_ENUMERATOR_(IEnumMediaTypes,AM_MEDIA_TYPE*);
+
+typedef struct _VIDEO_STREAM_CONFIG_CAPS
+{
+  GUID guid;
+  ULONG VideoStandard;
+  SIZE InputSize;
+  SIZE MinCroppingSize;
+  SIZE MaxCroppingSize;
+  int CropGranularityX;
+  int CropGranularityY;
+  int CropAlignX;
+  int CropAlignY;
+  SIZE MinOutputSize;
+  SIZE MaxOutputSize;
+  int OutputGranularityX;
+  int OutputGranularityY;
+  int StretchTapsX;
+  int StretchTapsY;
+  int ShrinkTapsX;
+  int ShrinkTapsY;
+  LONGLONG MinFrameInterval;
+  LONGLONG MaxFrameInterval;
+  LONG MinBitsPerSecond;
+  LONG MaxBitsPerSecond;
+} VIDEO_STREAM_CONFIG_CAPS;
+
+typedef LONGLONG REFERENCE_TIME;
+
+typedef interface IBaseFilter IBaseFilter;
+typedef interface IReferenceClock IReferenceClock;
+typedef interface IFilterGraph IFilterGraph;
+
+typedef enum _FilterState {
+  State_Stopped,
+  State_Paused,
+  State_Running
+} FILTER_STATE;
+
+#define MAX_FILTER_NAME 128
+typedef struct _FilterInfo {
+  WCHAR achName[MAX_FILTER_NAME]; 
+  IFilterGraph *pGraph;
+} FILTER_INFO;
+
+typedef enum _PinDirection {
+  PINDIR_INPUT,
+  PINDIR_OUTPUT
+} PIN_DIRECTION;
+
+#define MAX_PIN_NAME 128
+typedef struct _PinInfo {
+  IBaseFilter *pFilter;
+  PIN_DIRECTION dir;
+  WCHAR achName[MAX_PIN_NAME];
+} PIN_INFO;
+
+#define INTERFACE IPin
+DECLARE_INTERFACE_(IPin,IUnknown)
+{
+  STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;
+  STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+  STDMETHOD_(ULONG,Release)(THIS) PURE;
+  STDMETHOD(Connect)(THIS_ IPin*,const AM_MEDIA_TYPE*) PURE;
+  STDMETHOD(ReceiveConnection)(THIS_ IPin*,const AM_MEDIA_TYPE*) PURE;
+  STDMETHOD(Disconnect)(THIS) PURE;
+  STDMETHOD(ConnectedTo)(THIS_ IPin**) PURE;
+  STDMETHOD(ConnectionMediaType)(THIS_ AM_MEDIA_TYPE*) PURE;
+  STDMETHOD(QueryPinInfo)(THIS_ PIN_INFO*) PURE;
+  STDMETHOD(QueryDirection)(THIS_ PIN_DIRECTION*) PURE;
+};
+#undef INTERFACE
+
+DECLARE_ENUMERATOR_(IEnumPins,IPin*);
+
+typedef struct _AllocatorProperties {
+  long cBuffers;
+  long cbBuffer;
+  long cbAlign;
+  long cbPrefix;
+} ALLOCATOR_PROPERTIES;
+
+typedef LONG_PTR OAEVENT;
+
+#define INTERFACE IMediaEvent
+DECLARE_INTERFACE_(IMediaEvent,IDispatch)
+{
+  STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;
+  STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+  STDMETHOD_(ULONG,Release)(THIS) PURE;
+  STDMETHOD(GetEventHandle)(THIS_ OAEVENT*) PURE;
+  STDMETHOD(GetEvent)(THIS_ long*,LONG_PTR,LONG_PTR,long) PURE;
+  STDMETHOD(WaitForCompletion)(THIS_ long,long*) PURE;
+  STDMETHOD(CancelDefaultHandling)(THIS_ long) PURE;
+  STDMETHOD(RestoreDefaultHandling)(THIS_ long) PURE;
+  STDMETHOD(FreeEventParams)(THIS_ long,LONG_PTR,LONG_PTR) PURE;
+};
+#undef INTERFACE
+
+typedef long OAFilterState;
+
+#define INTERFACE IMediaControl
+DECLARE_INTERFACE_(IMediaControl,IDispatch)
+{
+  STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;
+  STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+  STDMETHOD_(ULONG,Release)(THIS) PURE;
+  STDMETHOD(Run)(THIS) PURE;
+  STDMETHOD(Pause)(THIS) PURE;
+  STDMETHOD(Stop)(THIS) PURE;
+  STDMETHOD(GetState)(THIS_ LONG,OAFilterState*) PURE;
+  STDMETHOD(RenderFile)(THIS_ BSTR) PURE;
+  STDMETHOD(AddSourceFilter)(THIS_ BSTR,IDispatch**) PURE;
+  STDMETHOD(get_FilterCollection)(THIS_ IDispatch**) PURE;
+  STDMETHOD(get_RegFilterCollection)(THIS_ IDispatch**) PURE;
+  STDMETHOD(StopWhenReady)(THIS) PURE;
+};
+#undef INTERFACE
+
+#define INTERFACE IVideoProcAmp
+DECLARE_INTERFACE_(IVideoProcAmp,IUnknown)
+{
+  STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;
+  STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+  STDMETHOD_(ULONG,Release)(THIS) PURE;
+};
+#undef INTERFACE
+
+#define INTERFACE IAMStreamConfig
+DECLARE_INTERFACE_(IAMStreamConfig,IUnknown)
+{
+  STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;
+  STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+  STDMETHOD_(ULONG,Release)(THIS) PURE;
+  STDMETHOD(SetFormat)(THIS_ AM_MEDIA_TYPE*) PURE;
+  STDMETHOD(GetFormat)(THIS_ AM_MEDIA_TYPE**) PURE;
+  STDMETHOD(GetNumberOfCapabilities)(THIS_ int*,int*) PURE;
+  STDMETHOD(GetStreamCaps)(THIS_ int,AM_MEDIA_TYPE**,BYTE*) PURE;
+};
+#undef INTERFACE
+
+#define INTERFACE IMediaFilter
+DECLARE_INTERFACE_(IMediaFilter,IPersist)
+{
+  STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;
+  STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+  STDMETHOD_(ULONG,Release)(THIS) PURE;
+  STDMETHOD(Stop)(THIS) PURE;
+  STDMETHOD(Pause)(THIS) PURE;
+  STDMETHOD(Run)(THIS_ REFERENCE_TIME) PURE;
+  STDMETHOD(GetState)(THIS_ DWORD,FILTER_STATE*) PURE;
+  STDMETHOD(SetSyncSource)(THIS_ IReferenceClock*) PURE;
+  STDMETHOD(GetSyncSource)(THIS_ IReferenceClock**) PURE;
+};
+#undef INTERFACE
+
+#define INTERFACE IBaseFilter
+DECLARE_INTERFACE_(IBaseFilter,IMediaFilter)
+{
+  STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;
+  STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+  STDMETHOD_(ULONG,Release)(THIS) PURE;
+  STDMETHOD(EnumPins)(THIS_ IEnumPins**) PURE;
+  STDMETHOD(FindPin)(THIS_ LPCWSTR,IPin**) PURE;
+  STDMETHOD(QueryFilterInfo)(THIS_ FILTER_INFO*) PURE;
+  STDMETHOD(JoinFilterGraph)(THIS_ IFilterGraph*,LPCWSTR) PURE;
+  STDMETHOD(QueryVendorInfo)(THIS_ LPWSTR*) PURE;
+};
+#undef INTERFACE
+
+DECLARE_ENUMERATOR_(IEnumFilters,IBaseFilter*);
+
+// #define INTERFACE IEnumFilters
+// DECLARE_INTERFACE_(IEnumFilters,IUnknown)
+// {
+//   STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;
+//   STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+//   STDMETHOD_(ULONG,Release)(THIS) PURE;
+//   STDMETHOD(Next)(THIS_ ULONG,IBaseFilter**,ULONG*) PURE;
+//   STDMETHOD(Skip)(THIS_ ULONG) PURE;
+//   STDMETHOD(Reset)(THIS) PURE;
+//   STDMETHOD(Clone)(THIS_ IEnumFilters**) PURE;
+// };
+// #undef INTERFACE
+
+#define INTERFACE IFilterGraph
+DECLARE_INTERFACE_(IFilterGraph,IUnknown)
+{
+  STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;
+  STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+  STDMETHOD_(ULONG,Release)(THIS) PURE;
+  STDMETHOD(AddFilter)(THIS_ IBaseFilter*,LPCWSTR) PURE;
+  STDMETHOD(RemoveFilter)(THIS_ IBaseFilter*) PURE;
+  STDMETHOD(EnumFilters)(THIS_ IEnumFilters**) PURE;
+  STDMETHOD(FindFilterByName)(THIS_ LPCWSTR,IBaseFilter**) PURE;
+  STDMETHOD(ConnectDirect)(THIS_ IPin*,IPin*,const AM_MEDIA_TYPE*) PURE;
+  STDMETHOD(Reconnect)(THIS_ IPin*) PURE;
+  STDMETHOD(Disconnect)(THIS_ IPin*) PURE;
+  STDMETHOD(SetDefaultSyncSource)(THIS) PURE;
+};
+#undef INTERFACE
+
+#define INTERFACE IGraphBuilder
+DECLARE_INTERFACE_(IGraphBuilder,IFilterGraph)
+{
+  STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;
+  STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+  STDMETHOD_(ULONG,Release)(THIS) PURE;
+  STDMETHOD(Connect)(THIS_ IPin*,IPin*) PURE;
+  STDMETHOD(Render)(THIS_ IPin*) PURE;
+  STDMETHOD(RenderFile)(THIS_ LPCWSTR,LPCWSTR) PURE;
+  STDMETHOD(AddSourceFilter)(THIS_ LPCWSTR,LPCWSTR,IBaseFilter**) PURE;
+  STDMETHOD(SetLogFile)(THIS_ DWORD_PTR) PURE;
+  STDMETHOD(Abort)(THIS) PURE;
+  STDMETHOD(ShouldOperationContinue)(THIS) PURE;
+};
+#undef INTERFACE
+
+#define INTERFACE ICreateDevEnum
+DECLARE_INTERFACE_(ICreateDevEnum,IUnknown)
+{
+  STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;
+  STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+  STDMETHOD_(ULONG,Release)(THIS) PURE;
+  STDMETHOD(CreateClassEnumerator)(THIS_ REFIID,IEnumMoniker**,DWORD) PURE;
+};
+#undef INTERFACE
+
+#define INTERFACE IMediaSample
+DECLARE_INTERFACE_(IMediaSample,IUnknown)
+{
+  STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;
+  STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+  STDMETHOD_(ULONG,Release)(THIS) PURE;
+};
+#undef INTERFACE
+
+#define INTERFACE IMemAllocator
+DECLARE_INTERFACE_(IMemAllocator,IUnknown)
+{
+  STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;
+  STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+  STDMETHOD_(ULONG,Release)(THIS) PURE;
+  STDMETHOD(SetProperties)(THIS_ ALLOCATOR_PROPERTIES*,ALLOCATOR_PROPERTIES*) PURE;
+  STDMETHOD(GetProperties)(THIS_ ALLOCATOR_PROPERTIES*) PURE;
+  STDMETHOD(Commit)(THIS) PURE;
+  STDMETHOD(Decommit)(THIS) PURE;
+  STDMETHOD(GetBuffer)(THIS_ IMediaSample **,REFERENCE_TIME*,REFERENCE_TIME*,DWORD) PURE;
+  STDMETHOD(ReleaseBuffer)(THIS_ IMediaSample*) PURE;
+};
+#undef INTERFACE
+
+#define INTERFACE IMemInputPin
+DECLARE_INTERFACE_(IMemInputPin,IUnknown)
+{
+  STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;
+  STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+  STDMETHOD_(ULONG,Release)(THIS) PURE;
+  STDMETHOD(GetAllocator)(THIS_ IMemAllocator**) PURE;
+  STDMETHOD(NotifyAllocator)(THIS_ IMemAllocator*,BOOL) PURE;
+  STDMETHOD(GetAllocatorRequirements)(THIS_ ALLOCATOR_PROPERTIES*) PURE;
+  STDMETHOD(Receive)(THIS_ IMediaSample*) PURE;
+  STDMETHOD(ReceiveMultiple)(THIS_ IMediaSample**,LONG,LONG*) PURE;
+  STDMETHOD(ReceiveCanBlock)(THIS) PURE;
+};
+#undef INTERFACE
+
+#define INTERFACE ISampleGrabberCB
+DECLARE_INTERFACE_(ISampleGrabberCB,IUnknown)
+{
+  STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;
+  STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+  STDMETHOD_(ULONG,Release)(THIS) PURE;
+  STDMETHOD(SampleCB)(THIS_ double,IMediaSample*) PURE;
+  STDMETHOD(BufferCB)(THIS_ double,BYTE*,long) PURE;
+};
+#undef INTERFACE
+
+#define INTERFACE ISampleGrabber
+DECLARE_INTERFACE_(ISampleGrabber,IUnknown)
+{
+  STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;
+  STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+  STDMETHOD_(ULONG,Release)(THIS) PURE;
+  STDMETHOD(SetOneShot)(THIS_ BOOL) PURE;
+  STDMETHOD(SetMediaType)(THIS_ const AM_MEDIA_TYPE*) PURE;
+  STDMETHOD(GetConnectedMediaType)(THIS_ AM_MEDIA_TYPE*) PURE;
+  STDMETHOD(SetBufferSamples)(THIS_ BOOL) PURE;
+  STDMETHOD(GetCurrentBuffer)(THIS_ long*,long*) PURE;
+  STDMETHOD(GetCurrentSample)(THIS_ IMediaSample**) PURE;
+  STDMETHOD(SetCallBack)(THIS_ ISampleGrabberCB *,long) PURE;
+};
+#undef INTERFACE
+
+ComPtr< IPin > getPin( IBaseFilter *filter, PIN_DIRECTION direction, int num )
+{
+  ComPtr< IPin > retVal;
+  ComPtr< IEnumPins > enumPins;
+  COERRORMACRO( filter->EnumPins( &enumPins ), Error, ,
+                "Error getting pin enumerator" );
+  ULONG found;
+  ComPtr< IPin > pin;
+  while ( enumPins->Next( 1, &pin, &found ) == S_OK ) {
+    PIN_DIRECTION pinDirection = (PIN_DIRECTION)( -1 );
+    pin->QueryDirection( &pinDirection );
+    if ( pinDirection == direction ) {
+      if ( num == 0 ) {
+        retVal = pin;
+        break;
+      };
+      num--;
+    };
+  };
+  return retVal;
+}
+
+class Callback: public ISampleGrabberCB
+{
+public:
+  Callback(void);
+  virtual ~Callback(void);
+  STDMETHODIMP QueryInterface( REFIID riid, void **ppv );
+  STDMETHODIMP_(ULONG) AddRef(void);
+  STDMETHODIMP_(ULONG) Release(void);
+  STDMETHODIMP SampleCB(double,IMediaSample*);
+  STDMETHODIMP BufferCB(double,BYTE*,long);
+protected:
+  long m_refCount;
+};
+
+Callback::Callback(void): m_refCount(1)
+{
+#ifndef NDEBUG
+  cerr << "Callback::Callback" << endl;
+#endif
+}
+
+Callback::~Callback(void)
+{
+#ifndef NDEBUG
+  cerr << "Callback::~Callback" << endl;
+#endif
+}
+
+STDMETHODIMP Callback::QueryInterface(REFIID riid, void **ppv)
+{
+#ifndef NDEBUG
+  cerr << "Callback::QueryInterface" << endl;
+#endif
+  HRESULT retval;
+  if ( ppv == NULL ) return E_POINTER;
+  /*
+  if ( riid == IID_IUnknown ) {
+    *ppv = static_cast< IUnknown * >( this );
+    AddRef();
+    retval = S_OK;
+  } else if ( riid == IID_ISampleGrabberCB ) {
+    *ppv = static_cast< ISampleGrabberCB * >( this );
+    AddRef();
+    retval = S_OK;
+    } else */ {
+#ifndef NDEBUG
+    cerr << setbase( 16 ) << setfill('0')
+         << "DEFINE_GUID( ..., 0x" << setw(8) << (int)riid.Data1 << ", 0x"
+         << setw(4) << (int)riid.Data2 << "," << endl
+         << "             0x"
+         << setw(4) << (int)riid.Data3 << ", 0x" << setw(2)
+         << (int)riid.Data4[0] << ", 0x"
+         << (int)riid.Data4[1] << ", 0x"
+         << (int)riid.Data4[2] << ", 0x"
+         << (int)riid.Data4[3] << ", 0x"
+         << (int)riid.Data4[4] << ", 0x"
+         << (int)riid.Data4[5] << ", 0x"
+         << (int)riid.Data4[6] << ", 0x"
+         << (int)riid.Data4[7] << " ) ?" << endl
+         << setfill( ' ' ) << setw( 0 ) << setbase( 10 );
+#endif
+    retval = E_NOINTERFACE;
+  };
+  return retval;
+};
+
+STDMETHODIMP_(ULONG) Callback::AddRef(void)
+{
+#ifndef NDEBUG
+  cerr << "Callback::AddRef" << endl;
+#endif
+  m_refCount++;
+  return m_refCount;
+}
+
+STDMETHODIMP_(ULONG) Callback::Release(void)
+{
+#ifndef NDEBUG
+  cerr << "Callback::Release" << endl;
+#endif
+  if ( !InterlockedDecrement( &m_refCount ) ) delete this;
+  return m_refCount;
+}
+
+STDMETHODIMP Callback::SampleCB( double, IMediaSample * )
+{
+#ifndef NDEBUG
+  cerr << "Callback::SampleCB" << endl;
+#endif
+  return S_OK;
+}
+
+STDMETHODIMP Callback::BufferCB( double, BYTE *, long )
+{
+#ifndef NDEBUG
+  cerr << "Callback::BufferCB" << endl;
+#endif
+  return E_NOTIMPL;
+}
+
+using namespace std;
+
+int main(void)
+{
+  int retVal = 0;
+  bool initialized = false;
+  Callback *callback = NULL;
+  try {
+    COERRORMACRO( CoInitialize(NULL), Error, , "CoInitialize failed" );
+    initialized = true;
+    ComPtr< IGraphBuilder > graphBuilder;
+    graphBuilder.coCreateInstance( CLSID_FilterGraph, IID_IGraphBuilder,
+                                   "Could not create graph builder "
+                                   "interface" );
+    cerr << "graphBuilder is " << graphBuilder.get() << endl;
+    ComPtr< ICreateDevEnum > createDevEnum;
+    createDevEnum.coCreateInstance( CLSID_SystemDeviceEnum,
+                                    IID_ICreateDevEnum, "Could not create "
+                                    "device enumerator" );
+    ComPtr< IEnumMoniker > enumMoniker;
+    COERRORMACRO( createDevEnum->CreateClassEnumerator
+                  ( CLSID_VideoInputDeviceCategory, &enumMoniker, 0 ), Error, ,
+                  "Error requesting moniker enumerator" );
+    createDevEnum.reset();
+    COERRORMACRO( enumMoniker->Reset(), Error, ,
+                  "Error resetting moniker enumerator" );
+    int index = 0;
+    ComPtr< IMoniker > moniker;
+    for ( int i=0; i<=index; i++ ) {
+      ULONG fetched = 0;
+      COERRORMACRO( enumMoniker->Next( 1, &moniker, &fetched ), Error, ,
+                    "Error fetching next moniker" );
+    };
+    enumMoniker.reset();
+    ComPtr< IBaseFilter > source;
+    COERRORMACRO( moniker->BindToObject( 0, 0, IID_IBaseFilter,
+                                         (void **)&source ), Error, ,
+                  "Error binding moniker to base filter" );
+    moniker.reset();
+    COERRORMACRO( graphBuilder->AddFilter( source.get(), L"Source" ),
+                  Error, , "Error adding camera source to filter graph" );
+    ComPtr< IPin > sourceOut = getPin( source.get(), PINDIR_OUTPUT, 0 );
+    ERRORMACRO( sourceOut.get() != NULL, Error, ,
+                "Error getting output pin of camera source" );
+    ComPtr< IAMStreamConfig > streamConfig;
+    COERRORMACRO( sourceOut->
+                  QueryInterface( IID_IAMStreamConfig,
+                                  (void **)&streamConfig ),
+                  Error, , "Error requesting stream configuration API" );
+    int count, size;
+    COERRORMACRO( streamConfig->GetNumberOfCapabilities( &count, &size ),
+                  Error, , "Error getting number of capabilities" );
+    bool ok = false;
+    for ( int i=0; i<count; i++ ) {
+      VIDEO_STREAM_CONFIG_CAPS videoConfig;
+      AM_MEDIA_TYPE *mediaType;
+      COERRORMACRO( streamConfig->GetStreamCaps( i, &mediaType,
+                                                 (BYTE *)&videoConfig ),
+                    Error, , "Error getting stream capabilities" );
+      if ( mediaType->majortype == MEDIATYPE_Video &&
+           mediaType->cbFormat != 0 ) {
+        VIDEOINFOHEADER *infoHeader = (VIDEOINFOHEADER*)mediaType->pbFormat;
+        // TODO: choose format here !!!
+        cerr << "Setting format " << infoHeader->bmiHeader.biWidth
+             << "x" << infoHeader->bmiHeader.biHeight << endl;
+        streamConfig->SetFormat( mediaType );
+        ok = true;
+      };
+      if ( mediaType->cbFormat != 0 )
+        CoTaskMemFree( (PVOID)mediaType->pbFormat );
+      if ( mediaType->pUnk != NULL ) mediaType->pUnk->Release();
+      CoTaskMemFree( (PVOID)mediaType );
+      if ( ok )
+        break;
+    };
+    streamConfig.reset();
+    ERRORMACRO( ok, Error, , "Could not find any video format" );
+
+    ComPtr< IBaseFilter > grabberBase;
+    COERRORMACRO( CoCreateInstance( CLSID_SampleGrabber, NULL,
+                                    CLSCTX_INPROC, IID_IBaseFilter,
+                                    (void **)&grabberBase ),
+                  Error, , "Error creating sample grabber" );
+    COERRORMACRO( graphBuilder->AddFilter( grabberBase.get(), L"Grabber" ),
+                  Error, , "Error adding sample grabber to filter graph" );
+    ComPtr< ISampleGrabber > sampleGrabber;
+    COERRORMACRO( grabberBase->QueryInterface( IID_ISampleGrabber,
+                                               (void **)&sampleGrabber ),
+                  Error, , "Error requesting sample grabber interface" );
+    COERRORMACRO( sampleGrabber->SetOneShot( FALSE ), Error, ,
+                  "Error disabling one-shot mode" );
+    COERRORMACRO( sampleGrabber->SetBufferSamples( TRUE ), Error, ,
+                  "Error enabling buffer sampling" );
+    callback = new Callback;
+    COERRORMACRO( sampleGrabber->SetCallBack( callback, 0 ), Error, ,
+                  "Error setting callback interface for grabbing" );
+    ComPtr< IPin > grabberIn = getPin( grabberBase.get(), PINDIR_INPUT, 0 );
+    ERRORMACRO( grabberIn.get() != NULL, Error, ,
+                "Error getting input of sample grabber" );
+    ComPtr< IPin > grabberOut = getPin( grabberBase.get(), PINDIR_OUTPUT, 0 );
+    ERRORMACRO( grabberOut.get() != NULL, Error, ,
+                "Error getting output of sample grabber" );
+
+    ComPtr< IBaseFilter > nullRenderer;
+    COERRORMACRO( CoCreateInstance( CLSID_NullRenderer, NULL,
+                                    CLSCTX_INPROC, IID_IBaseFilter,
+                                    (void **)&nullRenderer ),
+                  Error, , "Error creating Null Renderer" );
+    COERRORMACRO( graphBuilder->AddFilter( nullRenderer.get(), L"Sink" ),
+                  Error, , "Error adding null renderer to filter graph" );
+    ComPtr< IPin > nullIn = getPin( nullRenderer.get(), PINDIR_INPUT, 0 );
+
+    cerr << endl << "Attempting to connect" << endl;
+    COERRORMACRO( graphBuilder->Connect( sourceOut.get(), grabberIn.get() ),
+                  Error, , "Error connecting source to sample grabber" );
+    COERRORMACRO( graphBuilder->Connect( grabberOut.get(), nullIn.get() ),
+                  Error, , "Error connecting sample grabber to sink" );
+
+    cerr << "Success!!!!!!!!!!!!!!!!!!!!!" << endl;
+
+    ComPtr< IMediaControl > mediaControl;
+    COERRORMACRO( graphBuilder->QueryInterface( IID_IMediaControl,
+                                                (void **)&mediaControl ),
+                  Error, , "Error requesting media control interface" );
+    COERRORMACRO( mediaControl->Run(), Error, , "Error running graph" );
+
+    ComPtr< IMediaEvent > mediaEvent;
+    COERRORMACRO( graphBuilder->QueryInterface( IID_IMediaEvent,
+                                                (void **)&mediaEvent ),
+                  Error, , "Error requesting event interface" );
+
+    cin.get();
+
+    mediaControl->Stop();
+
+    long evCode = 0;
+    mediaEvent->WaitForCompletion( INFINITE, &evCode );
+
+    // sourceOut.reset();
+    // sinkIn.reset();
+    // source.reset();
+  } catch ( Error &e ) {
+    cerr << e.what() << endl;
+    retVal = 1;
+  };
+  if ( callback != NULL ) callback->Release();
+  if ( initialized ) CoUninitialize();
+  return retVal;
+}
+
+static void ms_dshow_detect(MSWebCamManager *obj);
+
+static MSWebCamDesc ms_dshow_cam_desc={
+	"Directshow capture",
+	&ms_dshow_detect,
+	NULL,
+	&ms_dshow_create_reader,
+	NULL
+};
+
+static void ms_dshow_detect(MSWebCamManager *obj){
+	int i;
+	MSWebCam *cam;
+}
+
+extern "C" void libmsdscap_init(void){
+		ms_web_cam_desc_register(&ms_dshow_cam_desc);
+}
diff --git a/linphone/mediastreamer2/plugins/msdscap/error.cc b/linphone/mediastreamer2/plugins/msdscap/error.cc
new file mode 100644
index 0000000000000000000000000000000000000000..1365a4eca27c7b85b35b1e26e75678859a01ce32
--- /dev/null
+++ b/linphone/mediastreamer2/plugins/msdscap/error.cc
@@ -0,0 +1,23 @@
+/* HornetsEye - Computer Vision with Ruby
+   Copyright (C) 2006, 2007   Jan Wedekind
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>. */
+#include "error.hh"
+
+using namespace std;
+
+namespace Hornetseye {
+  string Error::temp;
+};
+
diff --git a/linphone/mediastreamer2/plugins/msdscap/error.hh b/linphone/mediastreamer2/plugins/msdscap/error.hh
new file mode 100644
index 0000000000000000000000000000000000000000..453c6e74831fa1bd76983b816fa8afc6ff039916
--- /dev/null
+++ b/linphone/mediastreamer2/plugins/msdscap/error.hh
@@ -0,0 +1,133 @@
+/* HornetsEye - Computer Vision with Ruby
+   Copyright (C) 2006, 2007   Jan Wedekind
+   
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>. */
+#ifndef HORNETSEYE_ERROR_HH
+#define HORNETSEYE_ERROR_HH
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <exception>
+#include <sstream>
+#include <string>
+#ifdef WIN32
+#include <stdio.h>
+#include <windef.h>
+#include <wchar.h>
+#include <winsock.h>
+#endif
+
+namespace Hornetseye {
+
+  /** Exception class deriving from std::exception.
+      This class provides a syntax similar to output-streams for convenience.
+      For compability with other libraries it is inheriting the class
+      \c std::exception.
+    
+      Here is an example how to use an instance of this class in C++:
+      \include exceptiontest/exceptiontest.cc
+      
+      Exception-handling also can be done using the macro \c ERRORMACRO:
+      \include exceptiontest/macrotest.cc
+      
+      Mind that the macro uses a variable with the name \c _e. Make sure, that
+      you don't use this variable-name in any of the macro-arguments!
+
+      Ruby already comes with exception classes:
+      \include exceptiontest/exceptiontest.rb
+      
+      @date Mon Aug 23 14:37:05 UTC 2004 */
+  class Error: public std::exception
+  {
+  public:
+    /// Constructor.
+    Error(void) {}
+    /// Copy constructor.
+    Error( Error &e ): std::exception( e )
+      { m_message << e.m_message.str(); }
+    /// Destructor.
+    virtual ~Error(void) throw() {}
+    ///
+    template< typename T >
+    std::ostream &operator<<( const T &t )
+      { m_message << t; return m_message; }
+    /** Interface for manipulators.
+        Manipulators such as \c std::endl and \c std::hex use these
+        functions in constructs like "Error e; e << std::endl".
+        For more information, see the iomanip header. */
+    std::ostream &operator<<( std::ostream& (*__pf)( std::ostream&) )
+      { (*__pf)( m_message ); return m_message; }
+    /// Returns error message (not thread safe).
+    virtual const char* what(void) const throw() {
+      temp = m_message.str();
+      return temp.c_str();
+      return NULL;
+    }
+  protected:
+    /// Memory-stream containing the error message.
+    std::ostringstream m_message;
+    /** Temporary to do null-termination.
+        The method \c what() requires a null-terminated string. */
+    static std::string temp;
+  };
+  
+};
+
+#define ERRORMACRO( condition, class, params, message ) \
+  if ( !( condition ) ) {                               \
+    class _e params;                                    \
+    _e << message;                                      \
+    throw _e;                                           \
+  };
+
+#ifdef WIN32
+#define COERRORMACRO( condition, class, params, message )                     \
+  {                                                                           \
+    HRESULT _hr = condition;                                                  \
+    if ( FAILED( _hr ) ) {                                                    \
+      class _e params;                                                        \
+      _e << message;                                                          \
+      TCHAR *_msg;                                                            \
+      if ( FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER |                    \
+                          FORMAT_MESSAGE_FROM_SYSTEM, 0, _hr, 0,              \
+                          (LPTSTR)&_msg, 0, NULL ) != 0 ) {                   \
+        _e << ": " << _msg;                                                   \
+        LocalFree( _msg );                                                    \
+      };                                                                      \
+      throw _e;                                                               \
+    };                                                                        \
+  };
+
+#define W32ERRORMACRO( condition, class, params, message )                    \
+  {                                                                           \
+    if ( !( condition ) ) {                                                   \
+      class _e params;                                                        \
+      _e << message;                                                          \
+      TCHAR *_msg;                                                            \
+      DWORD _errCode = GetLastError();                                        \
+      if ( FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER |                    \
+                          FORMAT_MESSAGE_FROM_SYSTEM, 0, _errCode, 0,         \
+                          (LPTSTR)&_msg, 0, NULL ) != 0 ) {                   \
+        _e << ": " << _msg;                                                   \
+        LocalFree( _msg );                                                    \
+      };                                                                      \
+      throw _e;                                                               \
+    };                                                                        \
+  };
+
+#endif
+
+#endif
diff --git a/linphone/mediastreamer2/plugins/msdscap/libmsdscap.dev b/linphone/mediastreamer2/plugins/msdscap/libmsdscap.dev
new file mode 100755
index 0000000000000000000000000000000000000000..a54e05e6703739b13bb7b89d6a2497a843bd00c4
--- /dev/null
+++ b/linphone/mediastreamer2/plugins/msdscap/libmsdscap.dev
@@ -0,0 +1,125 @@
+[Project]
+FileName=libmsdscap.dev
+Name=libmsdscap
+UnitCount=4
+PchHead=-1
+PchSource=-1
+Ver=3
+IsCpp=1
+ProfilesCount=2
+ProfileIndex=0
+Folders=
+
+[Unit1]
+FileName=error.hh
+CompileCpp=1
+Folder=libmsdscap
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit2]
+FileName=comptr.hh
+CompileCpp=1
+Folder=libmsdscap
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit3]
+FileName=mdscap.cc
+CompileCpp=1
+Folder=libmsdscap
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit4]
+FileName=error.cc
+CompileCpp=1
+Folder=libmsdscap
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[VersionInfo]
+Major=0
+Minor=1
+Release=1
+Build=1
+LanguageID=1033
+CharsetID=1252
+CompanyName=
+FileVersion=
+FileDescription=
+InternalName=
+LegalCopyright=
+LegalTrademarks=
+OriginalFilename=
+ProductName=
+ProductVersion=
+AutoIncBuildNrOnRebuild=0
+AutoIncBuildNrOnCompile=0
+
+[Profile1]
+ProfileName=MingW 3.4.2
+Type=3
+ObjFiles=
+Includes=../../include;../../../oRTP/include
+Libs=../../build/win32native/;../../../oRTP/build/win32native
+ResourceIncludes=
+MakeIncludes=
+Compiler=-DBUILDING_DLL=1_@@_-DORTP_INET6_@@_
+CppCompiler=-DBUILDING_DLL=1_@@_
+Linker=--no-export-all-symbols_@@_--add-stdcall-alias_@@_-lole32_@@_-loleaut32_@@_-lwinmm_@@_-luuid_@@_-lmediastreamer2_@@_-lortp_@@_
+PreprocDefines=
+CompilerSettings=0000000001001000000000
+Icon=
+ExeOutput=
+ObjectOutput=Output\MingW
+OverrideOutput=0
+OverrideOutputName=libmsdscap.dll
+HostApplication=
+CommandLine=
+UseCustomMakefile=0
+CustomMakefile=
+IncludeVersionInfo=0
+SupportXPThemes=0
+CompilerSet=0
+compilerType=0
+
+[Profile2]
+ProfileName=Visual C++ 2005
+Type=3
+ObjFiles=
+Includes=
+Libs=
+ResourceIncludes=
+MakeIncludes=
+Compiler=/DBUILDING_DLL=1
+CppCompiler=/DBUILDING_DLL=1
+Linker=
+PreprocDefines=
+CompilerSettings=000000000000010000000000000000000000
+Icon=
+ExeOutput=Output\Visual C++ 2005
+ObjectOutput=Objects\Visual C++ 2005
+OverrideOutput=0
+OverrideOutputName=
+HostApplication=
+CommandLine=
+UseCustomMakefile=0
+CustomMakefile=
+IncludeVersionInfo=0
+SupportXPThemes=0
+CompilerSet=1
+compilerType=1
+
diff --git a/linphone/mediastreamer2/plugins/msdscap/mdscap.cc b/linphone/mediastreamer2/plugins/msdscap/mdscap.cc
new file mode 100755
index 0000000000000000000000000000000000000000..a03f2e2106af7b82a18ce8d8785e4f8d76952b48
--- /dev/null
+++ b/linphone/mediastreamer2/plugins/msdscap/mdscap.cc
@@ -0,0 +1,885 @@
+// This is a DirectShow interface. But maybe you'll find that it's easier to
+// access the camera directly ;)
+
+// http://www.codeguru.com/cpp/g-m/multimedia/video/article.php/c9551/
+// http://lists.mplayerhq.hu/pipermail/ffmpeg-devel/2007-April/027965.html
+// http://msdn2.microsoft.com/en-us/library/ms787594.aspx
+// http://msdn2.microsoft.com/en-us/library/ms787867.aspx
+// NullRenderer wih reference clock set to NULL
+// http://www.videolan.org/
+// http://git.videolan.org/gitweb.cgi?p=vlc.git;f=modules/access/dshow;hb=0.8.6
+
+// #include <wtypes.h>
+// #include <unknwn.h>
+// #include <ole2.h>
+// #include <limits.h>
+// #include <dshow.h>
+
+#include <iostream>
+#include <iomanip>
+#include <fstream>
+#include <windows.h>
+#include <winnls.h>
+#include <errors.h>
+#include <initguid.h>
+#include <ocidl.h>
+#include <malloc.h>
+#include "comptr.hh"
+#include "error.hh"
+
+#include <mediastreamer2/mswebcam.h>
+#include <mediastreamer2/msfilter.h>
+#include <mediastreamer2/msticker.h>
+#include <mediastreamer2/msvideo.h>
+
+#define FILTER_NAME L"HornetsEye Capture Filter"
+#define PIN_NAME L"Capture"
+
+using namespace Hornetseye;
+
+DEFINE_GUID( CLSID_VideoInputDeviceCategory, 0x860BB310, 0x5D01,
+             0x11d0, 0xBD, 0x3B, 0x00, 0xA0, 0xC9, 0x11, 0xCE, 0x86);
+DEFINE_GUID( CLSID_SystemDeviceEnum, 0x62BE5D10, 0x60EB, 0x11d0,
+             0xBD, 0x3B, 0x00, 0xA0, 0xC9, 0x11, 0xCE, 0x86 );
+DEFINE_GUID( CLSID_FilterGraph, 0xe436ebb3, 0x524f, 0x11ce,
+             0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70);
+DEFINE_GUID( CLSID_SampleGrabber, 0xc1f400a0, 0x3f08, 0x11d3,
+             0x9f, 0x0b, 0x00, 0x60, 0x08, 0x03, 0x9e, 0x37 );
+DEFINE_GUID( CLSID_NullRenderer,0xc1f400a4, 0x3f08, 0x11d3,
+             0x9f, 0x0b, 0x00, 0x60, 0x08, 0x03, 0x9e, 0x37 );
+DEFINE_GUID( CLSID_VfwCapture, 0x1b544c22, 0xfd0b, 0x11ce,
+             0x8c, 0x63, 0x0, 0xaa, 0x00, 0x44, 0xb5, 0x1e);
+DEFINE_GUID( IID_IGraphBuilder, 0x56a868a9, 0x0ad4, 0x11ce,
+             0xb0, 0x3a, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70);
+DEFINE_GUID( IID_IBaseFilter, 0x56a86895, 0x0ad4, 0x11ce,
+             0xb0, 0x3a, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70 );
+DEFINE_GUID( IID_ICreateDevEnum, 0x29840822, 0x5b84, 0x11d0,
+             0xbd, 0x3b, 0x00, 0xa0, 0xc9, 0x11, 0xce, 0x86 );
+DEFINE_GUID( IID_IEnumFilters, 0x56a86893, 0xad4, 0x11ce,
+             0xb0, 0x3a, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70 );
+DEFINE_GUID( IID_IEnumPins, 0x56a86892, 0x0ad4, 0x11ce,
+             0xb0, 0x3a, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70 );
+DEFINE_GUID( IID_IMediaSample, 0x56a8689a, 0x0ad4, 0x11ce,
+             0xb0, 0x3a, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70 );
+DEFINE_GUID( IID_IMediaFilter, 0x56a86899, 0x0ad4, 0x11ce,
+             0xb0, 0x3a, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70 );
+DEFINE_GUID( IID_IPin, 0x56a86891, 0x0ad4, 0x11ce,
+             0xb0, 0x3a, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70 );
+DEFINE_GUID( IID_ISampleGrabber, 0x6b652fff, 0x11fe, 0x4fce,
+             0x92, 0xad, 0x02, 0x66, 0xb5, 0xd7, 0xc7, 0x8f );
+DEFINE_GUID( IID_ISampleGrabberCB, 0x0579154a, 0x2b53, 0x4994,
+             0xb0, 0xd0, 0xe7, 0x73, 0x14, 0x8e, 0xff, 0x85 );
+DEFINE_GUID( IID_IMediaEvent, 0x56a868b6, 0x0ad4, 0x11ce,
+             0xb0, 0x3a, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70 );
+DEFINE_GUID( IID_IMediaControl, 0x56a868b1, 0x0ad4, 0x11ce,
+             0xb0, 0x3a, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70 );
+DEFINE_GUID( IID_IMemInputPin, 0x56a8689d, 0x0ad4, 0x11ce,
+             0xb0, 0x3a, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70 );
+DEFINE_GUID( IID_IAMStreamConfig, 0xc6e13340, 0x30ac, 0x11d0,
+             0xa1, 0x8c, 0x00, 0xa0, 0xc9, 0x11, 0x89, 0x56 );
+DEFINE_GUID( IID_IVideoProcAmp, 0x4050560e, 0x42a7, 0x413a,
+             0x85, 0xc2, 0x09, 0x26, 0x9a, 0x2d, 0x0f, 0x44 );
+DEFINE_GUID( MEDIATYPE_Video, 0x73646976, 0x0000, 0x0010,
+             0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 );
+DEFINE_GUID( MEDIASUBTYPE_I420, 0x30323449, 0x0000, 0x0010,
+             0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
+DEFINE_GUID( MEDIASUBTYPE_YV12, 0x32315659, 0x0000, 0x0010,
+             0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 );
+DEFINE_GUID( MEDIASUBTYPE_IYUV, 0x56555949, 0x0000, 0x0010,
+             0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 );
+DEFINE_GUID( MEDIASUBTYPE_YUYV, 0x56595559, 0x0000, 0x0010,
+             0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 );
+DEFINE_GUID( MEDIASUBTYPE_YUY2, 0x32595559, 0x0000, 0x0010,
+             0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 );
+DEFINE_GUID( MEDIASUBTYPE_UYVY, 0x59565955, 0x0000, 0x0010,
+             0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 );
+DEFINE_GUID( MEDIASUBTYPE_RGB24, 0xe436eb7d, 0x524f, 0x11ce,
+             0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70 );
+
+using namespace std;
+
+typedef LONGLONG REFERENCE_TIME;
+
+typedef struct tagVIDEOINFOHEADER {
+  RECT rcSource;
+  RECT rcTarget;
+  DWORD dwBitRate;
+  DWORD dwBitErrorRate;
+  REFERENCE_TIME AvgTimePerFrame;
+  BITMAPINFOHEADER bmiHeader;
+} VIDEOINFOHEADER;
+
+typedef struct _AMMediaType {
+  GUID majortype;
+  GUID subtype;
+  BOOL bFixedSizeSamples;
+  BOOL bTemporalCompression;
+  ULONG lSampleSize;
+  GUID formattype;
+  IUnknown *pUnk;
+  ULONG cbFormat;
+  BYTE *pbFormat;
+} AM_MEDIA_TYPE;
+
+DECLARE_ENUMERATOR_(IEnumMediaTypes,AM_MEDIA_TYPE*);
+
+typedef struct _VIDEO_STREAM_CONFIG_CAPS
+{
+  GUID guid;
+  ULONG VideoStandard;
+  SIZE InputSize;
+  SIZE MinCroppingSize;
+  SIZE MaxCroppingSize;
+  int CropGranularityX;
+  int CropGranularityY;
+  int CropAlignX;
+  int CropAlignY;
+  SIZE MinOutputSize;
+  SIZE MaxOutputSize;
+  int OutputGranularityX;
+  int OutputGranularityY;
+  int StretchTapsX;
+  int StretchTapsY;
+  int ShrinkTapsX;
+  int ShrinkTapsY;
+  LONGLONG MinFrameInterval;
+  LONGLONG MaxFrameInterval;
+  LONG MinBitsPerSecond;
+  LONG MaxBitsPerSecond;
+} VIDEO_STREAM_CONFIG_CAPS;
+
+typedef LONGLONG REFERENCE_TIME;
+
+typedef interface IBaseFilter IBaseFilter;
+typedef interface IReferenceClock IReferenceClock;
+typedef interface IFilterGraph IFilterGraph;
+
+typedef enum _FilterState {
+  State_Stopped,
+  State_Paused,
+  State_Running
+} FILTER_STATE;
+
+#define MAX_FILTER_NAME 128
+typedef struct _FilterInfo {
+  WCHAR achName[MAX_FILTER_NAME]; 
+  IFilterGraph *pGraph;
+} FILTER_INFO;
+
+typedef enum _PinDirection {
+  PINDIR_INPUT,
+  PINDIR_OUTPUT
+} PIN_DIRECTION;
+
+#define MAX_PIN_NAME 128
+typedef struct _PinInfo {
+  IBaseFilter *pFilter;
+  PIN_DIRECTION dir;
+  WCHAR achName[MAX_PIN_NAME];
+} PIN_INFO;
+
+#define INTERFACE IPin
+DECLARE_INTERFACE_(IPin,IUnknown)
+{
+  STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;
+  STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+  STDMETHOD_(ULONG,Release)(THIS) PURE;
+  STDMETHOD(Connect)(THIS_ IPin*,const AM_MEDIA_TYPE*) PURE;
+  STDMETHOD(ReceiveConnection)(THIS_ IPin*,const AM_MEDIA_TYPE*) PURE;
+  STDMETHOD(Disconnect)(THIS) PURE;
+  STDMETHOD(ConnectedTo)(THIS_ IPin**) PURE;
+  STDMETHOD(ConnectionMediaType)(THIS_ AM_MEDIA_TYPE*) PURE;
+  STDMETHOD(QueryPinInfo)(THIS_ PIN_INFO*) PURE;
+  STDMETHOD(QueryDirection)(THIS_ PIN_DIRECTION*) PURE;
+};
+#undef INTERFACE
+
+DECLARE_ENUMERATOR_(IEnumPins,IPin*);
+
+typedef struct _AllocatorProperties {
+  long cBuffers;
+  long cbBuffer;
+  long cbAlign;
+  long cbPrefix;
+} ALLOCATOR_PROPERTIES;
+
+typedef LONG_PTR OAEVENT;
+
+#define INTERFACE IMediaEvent
+DECLARE_INTERFACE_(IMediaEvent,IDispatch)
+{
+  STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;
+  STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+  STDMETHOD_(ULONG,Release)(THIS) PURE;
+  STDMETHOD(GetEventHandle)(THIS_ OAEVENT*) PURE;
+  STDMETHOD(GetEvent)(THIS_ long*,LONG_PTR,LONG_PTR,long) PURE;
+  STDMETHOD(WaitForCompletion)(THIS_ long,long*) PURE;
+  STDMETHOD(CancelDefaultHandling)(THIS_ long) PURE;
+  STDMETHOD(RestoreDefaultHandling)(THIS_ long) PURE;
+  STDMETHOD(FreeEventParams)(THIS_ long,LONG_PTR,LONG_PTR) PURE;
+};
+#undef INTERFACE
+
+typedef long OAFilterState;
+
+#define INTERFACE IMediaControl
+DECLARE_INTERFACE_(IMediaControl,IDispatch)
+{
+  STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;
+  STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+  STDMETHOD_(ULONG,Release)(THIS) PURE;
+  STDMETHOD(Run)(THIS) PURE;
+  STDMETHOD(Pause)(THIS) PURE;
+  STDMETHOD(Stop)(THIS) PURE;
+  STDMETHOD(GetState)(THIS_ LONG,OAFilterState*) PURE;
+  STDMETHOD(RenderFile)(THIS_ BSTR) PURE;
+  STDMETHOD(AddSourceFilter)(THIS_ BSTR,IDispatch**) PURE;
+  STDMETHOD(get_FilterCollection)(THIS_ IDispatch**) PURE;
+  STDMETHOD(get_RegFilterCollection)(THIS_ IDispatch**) PURE;
+  STDMETHOD(StopWhenReady)(THIS) PURE;
+};
+#undef INTERFACE
+
+#define INTERFACE IVideoProcAmp
+DECLARE_INTERFACE_(IVideoProcAmp,IUnknown)
+{
+  STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;
+  STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+  STDMETHOD_(ULONG,Release)(THIS) PURE;
+};
+#undef INTERFACE
+
+#define INTERFACE IAMStreamConfig
+DECLARE_INTERFACE_(IAMStreamConfig,IUnknown)
+{
+  STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;
+  STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+  STDMETHOD_(ULONG,Release)(THIS) PURE;
+  STDMETHOD(SetFormat)(THIS_ AM_MEDIA_TYPE*) PURE;
+  STDMETHOD(GetFormat)(THIS_ AM_MEDIA_TYPE**) PURE;
+  STDMETHOD(GetNumberOfCapabilities)(THIS_ int*,int*) PURE;
+  STDMETHOD(GetStreamCaps)(THIS_ int,AM_MEDIA_TYPE**,BYTE*) PURE;
+};
+#undef INTERFACE
+
+#define INTERFACE IMediaFilter
+DECLARE_INTERFACE_(IMediaFilter,IPersist)
+{
+  STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;
+  STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+  STDMETHOD_(ULONG,Release)(THIS) PURE;
+  STDMETHOD(Stop)(THIS) PURE;
+  STDMETHOD(Pause)(THIS) PURE;
+  STDMETHOD(Run)(THIS_ REFERENCE_TIME) PURE;
+  STDMETHOD(GetState)(THIS_ DWORD,FILTER_STATE*) PURE;
+  STDMETHOD(SetSyncSource)(THIS_ IReferenceClock*) PURE;
+  STDMETHOD(GetSyncSource)(THIS_ IReferenceClock**) PURE;
+};
+#undef INTERFACE
+
+#define INTERFACE IBaseFilter
+DECLARE_INTERFACE_(IBaseFilter,IMediaFilter)
+{
+  STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;
+  STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+  STDMETHOD_(ULONG,Release)(THIS) PURE;
+  STDMETHOD(EnumPins)(THIS_ IEnumPins**) PURE;
+  STDMETHOD(FindPin)(THIS_ LPCWSTR,IPin**) PURE;
+  STDMETHOD(QueryFilterInfo)(THIS_ FILTER_INFO*) PURE;
+  STDMETHOD(JoinFilterGraph)(THIS_ IFilterGraph*,LPCWSTR) PURE;
+  STDMETHOD(QueryVendorInfo)(THIS_ LPWSTR*) PURE;
+};
+#undef INTERFACE
+
+DECLARE_ENUMERATOR_(IEnumFilters,IBaseFilter*);
+
+// #define INTERFACE IEnumFilters
+// DECLARE_INTERFACE_(IEnumFilters,IUnknown)
+// {
+//   STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;
+//   STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+//   STDMETHOD_(ULONG,Release)(THIS) PURE;
+//   STDMETHOD(Next)(THIS_ ULONG,IBaseFilter**,ULONG*) PURE;
+//   STDMETHOD(Skip)(THIS_ ULONG) PURE;
+//   STDMETHOD(Reset)(THIS) PURE;
+//   STDMETHOD(Clone)(THIS_ IEnumFilters**) PURE;
+// };
+// #undef INTERFACE
+
+#define INTERFACE IFilterGraph
+DECLARE_INTERFACE_(IFilterGraph,IUnknown)
+{
+  STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;
+  STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+  STDMETHOD_(ULONG,Release)(THIS) PURE;
+  STDMETHOD(AddFilter)(THIS_ IBaseFilter*,LPCWSTR) PURE;
+  STDMETHOD(RemoveFilter)(THIS_ IBaseFilter*) PURE;
+  STDMETHOD(EnumFilters)(THIS_ IEnumFilters**) PURE;
+  STDMETHOD(FindFilterByName)(THIS_ LPCWSTR,IBaseFilter**) PURE;
+  STDMETHOD(ConnectDirect)(THIS_ IPin*,IPin*,const AM_MEDIA_TYPE*) PURE;
+  STDMETHOD(Reconnect)(THIS_ IPin*) PURE;
+  STDMETHOD(Disconnect)(THIS_ IPin*) PURE;
+  STDMETHOD(SetDefaultSyncSource)(THIS) PURE;
+};
+#undef INTERFACE
+
+#define INTERFACE IGraphBuilder
+DECLARE_INTERFACE_(IGraphBuilder,IFilterGraph)
+{
+  STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;
+  STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+  STDMETHOD_(ULONG,Release)(THIS) PURE;
+  STDMETHOD(Connect)(THIS_ IPin*,IPin*) PURE;
+  STDMETHOD(Render)(THIS_ IPin*) PURE;
+  STDMETHOD(RenderFile)(THIS_ LPCWSTR,LPCWSTR) PURE;
+  STDMETHOD(AddSourceFilter)(THIS_ LPCWSTR,LPCWSTR,IBaseFilter**) PURE;
+  STDMETHOD(SetLogFile)(THIS_ DWORD_PTR) PURE;
+  STDMETHOD(Abort)(THIS) PURE;
+  STDMETHOD(ShouldOperationContinue)(THIS) PURE;
+};
+#undef INTERFACE
+
+#define INTERFACE ICreateDevEnum
+DECLARE_INTERFACE_(ICreateDevEnum,IUnknown)
+{
+  STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;
+  STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+  STDMETHOD_(ULONG,Release)(THIS) PURE;
+  STDMETHOD(CreateClassEnumerator)(THIS_ REFIID,IEnumMoniker**,DWORD) PURE;
+};
+#undef INTERFACE
+
+#define INTERFACE IMediaSample
+DECLARE_INTERFACE_(IMediaSample,IUnknown)
+{
+  STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;
+  STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+  STDMETHOD_(ULONG,Release)(THIS) PURE;
+};
+#undef INTERFACE
+
+#define INTERFACE IMemAllocator
+DECLARE_INTERFACE_(IMemAllocator,IUnknown)
+{
+  STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;
+  STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+  STDMETHOD_(ULONG,Release)(THIS) PURE;
+  STDMETHOD(SetProperties)(THIS_ ALLOCATOR_PROPERTIES*,ALLOCATOR_PROPERTIES*) PURE;
+  STDMETHOD(GetProperties)(THIS_ ALLOCATOR_PROPERTIES*) PURE;
+  STDMETHOD(Commit)(THIS) PURE;
+  STDMETHOD(Decommit)(THIS) PURE;
+  STDMETHOD(GetBuffer)(THIS_ IMediaSample **,REFERENCE_TIME*,REFERENCE_TIME*,DWORD) PURE;
+  STDMETHOD(ReleaseBuffer)(THIS_ IMediaSample*) PURE;
+};
+#undef INTERFACE
+
+#define INTERFACE IMemInputPin
+DECLARE_INTERFACE_(IMemInputPin,IUnknown)
+{
+  STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;
+  STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+  STDMETHOD_(ULONG,Release)(THIS) PURE;
+  STDMETHOD(GetAllocator)(THIS_ IMemAllocator**) PURE;
+  STDMETHOD(NotifyAllocator)(THIS_ IMemAllocator*,BOOL) PURE;
+  STDMETHOD(GetAllocatorRequirements)(THIS_ ALLOCATOR_PROPERTIES*) PURE;
+  STDMETHOD(Receive)(THIS_ IMediaSample*) PURE;
+  STDMETHOD(ReceiveMultiple)(THIS_ IMediaSample**,LONG,LONG*) PURE;
+  STDMETHOD(ReceiveCanBlock)(THIS) PURE;
+};
+#undef INTERFACE
+
+#define INTERFACE ISampleGrabberCB
+DECLARE_INTERFACE_(ISampleGrabberCB,IUnknown)
+{
+  STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;
+  STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+  STDMETHOD_(ULONG,Release)(THIS) PURE;
+  STDMETHOD(SampleCB)(THIS_ double,IMediaSample*) PURE;
+  STDMETHOD(BufferCB)(THIS_ double,BYTE*,long) PURE;
+};
+#undef INTERFACE
+
+#define INTERFACE ISampleGrabber
+DECLARE_INTERFACE_(ISampleGrabber,IUnknown)
+{
+  STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;
+  STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+  STDMETHOD_(ULONG,Release)(THIS) PURE;
+  STDMETHOD(SetOneShot)(THIS_ BOOL) PURE;
+  STDMETHOD(SetMediaType)(THIS_ const AM_MEDIA_TYPE*) PURE;
+  STDMETHOD(GetConnectedMediaType)(THIS_ AM_MEDIA_TYPE*) PURE;
+  STDMETHOD(SetBufferSamples)(THIS_ BOOL) PURE;
+  STDMETHOD(GetCurrentBuffer)(THIS_ long*,long*) PURE;
+  STDMETHOD(GetCurrentSample)(THIS_ IMediaSample**) PURE;
+  STDMETHOD(SetCallBack)(THIS_ ISampleGrabberCB *,long) PURE;
+};
+#undef INTERFACE
+
+ComPtr< IPin > getPin( IBaseFilter *filter, PIN_DIRECTION direction, int num )
+{
+  ComPtr< IPin > retVal;
+  ComPtr< IEnumPins > enumPins;
+  COERRORMACRO( filter->EnumPins( &enumPins ), Error, ,
+                "Error getting pin enumerator" );
+  ULONG found;
+  ComPtr< IPin > pin;
+  while ( enumPins->Next( 1, &pin, &found ) == S_OK ) {
+    PIN_DIRECTION pinDirection = (PIN_DIRECTION)( -1 );
+    pin->QueryDirection( &pinDirection );
+    if ( pinDirection == direction ) {
+      if ( num == 0 ) {
+        retVal = pin;
+        break;
+      };
+      num--;
+    };
+  };
+  return retVal;
+}
+
+class Callback: public ISampleGrabberCB
+{
+public:
+  Callback(void);
+  virtual ~Callback(void);
+  STDMETHODIMP QueryInterface( REFIID riid, void **ppv );
+  STDMETHODIMP_(ULONG) AddRef(void);
+  STDMETHODIMP_(ULONG) Release(void);
+  STDMETHODIMP SampleCB(double,IMediaSample*);
+  STDMETHODIMP BufferCB(double,BYTE*,long);
+protected:
+  long m_refCount;
+};
+
+Callback::Callback(void): m_refCount(1)
+{
+#ifndef NDEBUG
+  cerr << "Callback::Callback" << endl;
+#endif
+}
+
+Callback::~Callback(void)
+{
+#ifndef NDEBUG
+  cerr << "Callback::~Callback" << endl;
+#endif
+}
+
+STDMETHODIMP Callback::QueryInterface(REFIID riid, void **ppv)
+{
+#ifndef NDEBUG
+  cerr << "Callback::QueryInterface" << endl;
+#endif
+  HRESULT retval;
+  if ( ppv == NULL ) return E_POINTER;
+  /*
+  if ( riid == IID_IUnknown ) {
+    *ppv = static_cast< IUnknown * >( this );
+    AddRef();
+    retval = S_OK;
+  } else if ( riid == IID_ISampleGrabberCB ) {
+    *ppv = static_cast< ISampleGrabberCB * >( this );
+    AddRef();
+    retval = S_OK;
+    } else */ {
+#ifndef NDEBUG
+    cerr << setbase( 16 ) << setfill('0')
+         << "DEFINE_GUID( ..., 0x" << setw(8) << (int)riid.Data1 << ", 0x"
+         << setw(4) << (int)riid.Data2 << "," << endl
+         << "             0x"
+         << setw(4) << (int)riid.Data3 << ", 0x" << setw(2)
+         << (int)riid.Data4[0] << ", 0x"
+         << (int)riid.Data4[1] << ", 0x"
+         << (int)riid.Data4[2] << ", 0x"
+         << (int)riid.Data4[3] << ", 0x"
+         << (int)riid.Data4[4] << ", 0x"
+         << (int)riid.Data4[5] << ", 0x"
+         << (int)riid.Data4[6] << ", 0x"
+         << (int)riid.Data4[7] << " ) ?" << endl
+         << setfill( ' ' ) << setw( 0 ) << setbase( 10 );
+#endif
+    retval = E_NOINTERFACE;
+  };
+  return retval;
+};
+
+STDMETHODIMP_(ULONG) Callback::AddRef(void)
+{
+#ifndef NDEBUG
+  cerr << "Callback::AddRef" << endl;
+#endif
+  m_refCount++;
+  return m_refCount;
+}
+
+STDMETHODIMP_(ULONG) Callback::Release(void)
+{
+#ifndef NDEBUG
+  cerr << "Callback::Release" << endl;
+#endif
+  if ( !InterlockedDecrement( &m_refCount ) ) delete this;
+  return m_refCount;
+}
+
+STDMETHODIMP Callback::SampleCB( double, IMediaSample * )
+{
+#ifndef NDEBUG
+  cerr << "Callback::SampleCB" << endl;
+#endif
+  return S_OK;
+}
+
+STDMETHODIMP Callback::BufferCB( double, BYTE *, long )
+{
+#ifndef NDEBUG
+  cerr << "Callback::BufferCB" << endl;
+#endif
+  return E_NOTIMPL;
+}
+
+using namespace std;
+
+int toto(void)
+{
+  int retVal = 0;
+  bool initialized = false;
+  Callback *callback = NULL;
+  try {
+    COERRORMACRO( CoInitialize(NULL), Error, , "CoInitialize failed" );
+    initialized = true;
+    ComPtr< IGraphBuilder > graphBuilder;
+    graphBuilder.coCreateInstance( CLSID_FilterGraph, IID_IGraphBuilder,
+                                   "Could not create graph builder "
+                                   "interface" );
+    cerr << "graphBuilder is " << graphBuilder.get() << endl;
+    ComPtr< ICreateDevEnum > createDevEnum;
+    createDevEnum.coCreateInstance( CLSID_SystemDeviceEnum,
+                                    IID_ICreateDevEnum, "Could not create "
+                                    "device enumerator" );
+    ComPtr< IEnumMoniker > enumMoniker;
+    COERRORMACRO( createDevEnum->CreateClassEnumerator
+                  ( CLSID_VideoInputDeviceCategory, &enumMoniker, 0 ), Error, ,
+                  "Error requesting moniker enumerator" );
+    createDevEnum.reset();
+    COERRORMACRO( enumMoniker->Reset(), Error, ,
+                  "Error resetting moniker enumerator" );
+    int index = 0;
+    ComPtr< IMoniker > moniker;
+    for ( int i=0; i<=index; i++ ) {
+      ULONG fetched = 0;
+      COERRORMACRO( enumMoniker->Next( 1, &moniker, &fetched ), Error, ,
+                    "Error fetching next moniker" );
+    };
+    enumMoniker.reset();
+    ComPtr< IBaseFilter > source;
+    COERRORMACRO( moniker->BindToObject( 0, 0, IID_IBaseFilter,
+                                         (void **)&source ), Error, ,
+                  "Error binding moniker to base filter" );
+    moniker.reset();
+    COERRORMACRO( graphBuilder->AddFilter( source.get(), L"Source" ),
+                  Error, , "Error adding camera source to filter graph" );
+    ComPtr< IPin > sourceOut = getPin( source.get(), PINDIR_OUTPUT, 0 );
+    ERRORMACRO( sourceOut.get() != NULL, Error, ,
+                "Error getting output pin of camera source" );
+    ComPtr< IAMStreamConfig > streamConfig;
+    COERRORMACRO( sourceOut->
+                  QueryInterface( IID_IAMStreamConfig,
+                                  (void **)&streamConfig ),
+                  Error, , "Error requesting stream configuration API" );
+    int count, size;
+    COERRORMACRO( streamConfig->GetNumberOfCapabilities( &count, &size ),
+                  Error, , "Error getting number of capabilities" );
+    bool ok = false;
+    for ( int i=0; i<count; i++ ) {
+      VIDEO_STREAM_CONFIG_CAPS videoConfig;
+      AM_MEDIA_TYPE *mediaType;
+      COERRORMACRO( streamConfig->GetStreamCaps( i, &mediaType,
+                                                 (BYTE *)&videoConfig ),
+                    Error, , "Error getting stream capabilities" );
+      if ( mediaType->majortype == MEDIATYPE_Video &&
+           mediaType->cbFormat != 0 ) {
+        VIDEOINFOHEADER *infoHeader = (VIDEOINFOHEADER*)mediaType->pbFormat;
+        // TODO: choose format here !!!
+        cerr << "Setting format " << infoHeader->bmiHeader.biWidth
+             << "x" << infoHeader->bmiHeader.biHeight << endl;
+        streamConfig->SetFormat( mediaType );
+        ok = true;
+      };
+      if ( mediaType->cbFormat != 0 )
+        CoTaskMemFree( (PVOID)mediaType->pbFormat );
+      if ( mediaType->pUnk != NULL ) mediaType->pUnk->Release();
+      CoTaskMemFree( (PVOID)mediaType );
+      if ( ok )
+        break;
+    };
+    streamConfig.reset();
+    ERRORMACRO( ok, Error, , "Could not find any video format" );
+
+    ComPtr< IBaseFilter > grabberBase;
+    COERRORMACRO( CoCreateInstance( CLSID_SampleGrabber, NULL,
+                                    CLSCTX_INPROC, IID_IBaseFilter,
+                                    (void **)&grabberBase ),
+                  Error, , "Error creating sample grabber" );
+    COERRORMACRO( graphBuilder->AddFilter( grabberBase.get(), L"Grabber" ),
+                  Error, , "Error adding sample grabber to filter graph" );
+    ComPtr< ISampleGrabber > sampleGrabber;
+    COERRORMACRO( grabberBase->QueryInterface( IID_ISampleGrabber,
+                                               (void **)&sampleGrabber ),
+                  Error, , "Error requesting sample grabber interface" );
+    COERRORMACRO( sampleGrabber->SetOneShot( FALSE ), Error, ,
+                  "Error disabling one-shot mode" );
+    COERRORMACRO( sampleGrabber->SetBufferSamples( TRUE ), Error, ,
+                  "Error enabling buffer sampling" );
+    callback = new Callback;
+    COERRORMACRO( sampleGrabber->SetCallBack( callback, 0 ), Error, ,
+                  "Error setting callback interface for grabbing" );
+    ComPtr< IPin > grabberIn = getPin( grabberBase.get(), PINDIR_INPUT, 0 );
+    ERRORMACRO( grabberIn.get() != NULL, Error, ,
+                "Error getting input of sample grabber" );
+    ComPtr< IPin > grabberOut = getPin( grabberBase.get(), PINDIR_OUTPUT, 0 );
+    ERRORMACRO( grabberOut.get() != NULL, Error, ,
+                "Error getting output of sample grabber" );
+
+    ComPtr< IBaseFilter > nullRenderer;
+    COERRORMACRO( CoCreateInstance( CLSID_NullRenderer, NULL,
+                                    CLSCTX_INPROC, IID_IBaseFilter,
+                                    (void **)&nullRenderer ),
+                  Error, , "Error creating Null Renderer" );
+    COERRORMACRO( graphBuilder->AddFilter( nullRenderer.get(), L"Sink" ),
+                  Error, , "Error adding null renderer to filter graph" );
+    ComPtr< IPin > nullIn = getPin( nullRenderer.get(), PINDIR_INPUT, 0 );
+
+    cerr << endl << "Attempting to connect" << endl;
+    COERRORMACRO( graphBuilder->Connect( sourceOut.get(), grabberIn.get() ),
+                  Error, , "Error connecting source to sample grabber" );
+    COERRORMACRO( graphBuilder->Connect( grabberOut.get(), nullIn.get() ),
+                  Error, , "Error connecting sample grabber to sink" );
+
+    cerr << "Success!!!!!!!!!!!!!!!!!!!!!" << endl;
+
+    ComPtr< IMediaControl > mediaControl;
+    COERRORMACRO( graphBuilder->QueryInterface( IID_IMediaControl,
+                                                (void **)&mediaControl ),
+                  Error, , "Error requesting media control interface" );
+    COERRORMACRO( mediaControl->Run(), Error, , "Error running graph" );
+
+    ComPtr< IMediaEvent > mediaEvent;
+    COERRORMACRO( graphBuilder->QueryInterface( IID_IMediaEvent,
+                                                (void **)&mediaEvent ),
+                  Error, , "Error requesting event interface" );
+
+    cin.get();
+
+    mediaControl->Stop();
+
+    long evCode = 0;
+    mediaEvent->WaitForCompletion( INFINITE, &evCode );
+
+    // sourceOut.reset();
+    // sinkIn.reset();
+    // source.reset();
+  } catch ( Error &e ) {
+    cerr << e.what() << endl;
+    retVal = 1;
+  };
+  if ( callback != NULL ) callback->Release();
+  if ( initialized ) CoUninitialize();
+  return retVal;
+}
+
+
+
+typedef struct DscapState{
+	int devid;
+	MSVideoSize vsize;
+	queue_t rq;
+	ms_mutex_t mutex;
+	int frame_ind;
+	int frame_max;
+	float fps;
+	float start_time;
+	int frame_count;
+	MSPixFmt fmt;
+} DscapState;
+
+
+static void dscap_init(MSFilter *f){
+	DscapState *s=(DscapState *)ms_new0(DscapState,1);
+	s->vsize.width=MS_VIDEO_SIZE_CIF_W;
+	s->vsize.height=MS_VIDEO_SIZE_CIF_H;
+	qinit(&s->rq);
+	ms_mutex_init(&s->mutex,NULL);
+	s->start_time=0;
+	s->frame_count=-1;
+	s->fps=15;
+	s->fmt=MS_YUV420P;
+	f->data=s;
+}
+
+
+
+static void dscap_uninit(MSFilter *f){
+	DscapState *s=(DscapState*)f->data;
+	flushq(&s->rq,0);
+	ms_mutex_destroy(&s->mutex);
+	ms_free(s);
+}
+
+static void dscap_callback(void *data, mblk_t *m){
+	DscapState *s=(DscapState*)data;
+	ms_mutex_lock(&s->mutex);
+	putq(&s->rq,m);
+	ms_mutex_unlock(&s->mutex);
+}
+
+static void dscap_preprocess(MSFilter * obj){
+	DscapState *s=(DscapState*)obj->data;
+}
+
+static void dscap_postprocess(MSFilter * obj){
+	DscapState *s=(DscapState*)obj->data;
+	flushq(&s->rq,0);
+}
+
+static void dscap_process(MSFilter * obj){
+	DscapState *s=(DscapState*)obj->data;
+	mblk_t *m;
+	uint32_t timestamp;
+	int cur_frame;
+
+	if (s->frame_count==-1){
+		s->start_time=(float)obj->ticker->time;
+		s->frame_count=0;
+	}
+
+	cur_frame=(int)((obj->ticker->time-s->start_time)*s->fps/1000.0);
+	if (cur_frame>s->frame_count){
+		mblk_t *om=NULL;
+		/*keep the most recent frame if several frames have been captured */
+		if (0){
+			ms_mutex_lock(&s->mutex);
+			while((m=getq(&s->rq))!=NULL){
+				ms_mutex_unlock(&s->mutex);
+				if (om!=NULL) freemsg(om);
+				om=m;
+				ms_mutex_lock(&s->mutex);
+			}
+			ms_mutex_unlock(&s->mutex);
+		}
+		if (om!=NULL){
+			timestamp=(uint32_t)(obj->ticker->time*90);/* rtp uses a 90000 Hz clockrate for video*/
+			mblk_set_timestamp_info(om,timestamp);
+			ms_queue_put(obj->outputs[0],om);
+		}
+		s->frame_count++;
+	}
+}
+
+static int dscap_set_fps(MSFilter *f, void *arg){
+	DscapState *s=(DscapState*)f->data;
+	s->fps=*((float*)arg);
+	return 0;
+}
+
+static int dscap_get_pix_fmt(MSFilter *f,void *arg){
+	DscapState *s=(DscapState*)f->data;
+	*((MSPixFmt*)arg)=s->fmt;
+	return 0;
+}
+
+static int dscap_set_vsize(MSFilter *f, void *arg){
+	DscapState *s=(DscapState*)f->data;
+	s->vsize=*((MSVideoSize*)arg);
+	return 0;
+}
+
+static int dscap_get_vsize(MSFilter *f, void *arg){
+	DscapState *s=(DscapState*)f->data;
+	MSVideoSize *vs=(MSVideoSize*)arg;
+	*vs=s->vsize;
+	return 0;
+}
+
+static MSFilterMethod methods[]={
+	{	MS_FILTER_SET_FPS	,	dscap_set_fps	},
+	{	MS_FILTER_GET_PIX_FMT	,	dscap_get_pix_fmt	},
+	{	MS_FILTER_SET_VIDEO_SIZE, dscap_set_vsize	},
+	{	MS_FILTER_GET_VIDEO_SIZE, dscap_get_vsize	},
+	{	0								,	NULL			}
+};
+
+MSFilterDesc ms_dscap_desc={
+	MS_FILTER_PLUGIN_ID,
+	"MSDsCap",
+	N_("A webcam grabber based on directshow."),
+	MS_FILTER_OTHER,
+	NULL,
+	0,
+	1,
+	dscap_init,
+	dscap_preprocess,
+	dscap_process,
+	dscap_postprocess,
+	dscap_uninit,
+	methods
+};
+
+
+static void ms_dshow_detect(MSWebCamManager *obj);
+static MSFilter * ms_dshow_create_reader(MSWebCam *obj){
+	MSFilter *f=ms_filter_new_from_desc(&ms_dscap_desc);
+	DscapState *s=(DscapState*)f->data;
+	s->devid=(int)obj->data;
+	return f;
+}
+
+static MSWebCamDesc ms_dshow_cam_desc={
+	"Directshow capture",
+	&ms_dshow_detect,
+	NULL,
+	&ms_dshow_create_reader,
+	NULL
+};
+
+static void ms_dshow_detect(MSWebCamManager *obj){
+	int i;
+	MSWebCam *cam;
+	ComPtr<IPropertyBag> pBag;
+	COERRORMACRO( CoInitialize(NULL), Error, , "CoInitialize failed" );
+ 
+    ComPtr< ICreateDevEnum > createDevEnum;
+    createDevEnum.coCreateInstance( CLSID_SystemDeviceEnum,
+                                    IID_ICreateDevEnum, "Could not create "
+                                    "device enumerator" );
+    ComPtr< IEnumMoniker > enumMoniker;
+    if (createDevEnum->CreateClassEnumerator( CLSID_VideoInputDeviceCategory, &enumMoniker, 0 )!=S_OK){
+		ms_error("Fail to create class enumerator.");
+		return;
+	}
+    createDevEnum.reset();
+    enumMoniker->Reset();
+    
+    int index = 0;
+    ULONG fetched = 0;
+    ComPtr< IMoniker > moniker;
+    for ( int i=0;enumMoniker->Next( 1, &moniker, &fetched )==S_OK;++i ) {
+		VARIANT var;
+		if (moniker->BindToStorage( 0, 0, IID_IPropertyBag, (void**) &pBag )!=S_OK)
+			continue;
+		VariantInit(&var);
+		if (pBag->Read( L"FriendlyName", &var, NULL )!=S_OK)
+			continue;
+    	char szName[256];
+		WideCharToMultiByte(CP_ACP,0,var.bstrVal,-1,szName,256,0,0);
+		MSWebCam *cam=ms_web_cam_new(&ms_dshow_cam_desc);
+    	cam->name=ms_strdup(szName);
+    	cam->data=(void*)i;
+		ms_web_cam_manager_prepend_cam(obj,cam);
+    	VariantClear(&var);
+	}
+    enumMoniker.reset();
+}
+
+extern "C" void libmsdscap_init(void){
+		ms_web_cam_manager_register_desc(ms_web_cam_manager_get(),&ms_dshow_cam_desc);
+}