From 8545df07b486077d7389b6f541bbf971dc2a23fc Mon Sep 17 00:00:00 2001
From: smorlat <smorlat@3f6dc0c8-ddfe-455d-9043-3cd528dc4637>
Date: Tue, 31 Mar 2009 21:31:56 +0000
Subject: [PATCH] new directshow/mingw filter works

git-svn-id: svn+ssh://svn.savannah.nongnu.org/linphone/trunk@396 3f6dc0c8-ddfe-455d-9043-3cd528dc4637
---
 .../mediastreamer2/plugins/msdscap/mdscap.cc  | 471 +++++++++++++-----
 linphone/mediastreamer2/src/mscommon.c        |   2 +-
 2 files changed, 361 insertions(+), 112 deletions(-)

diff --git a/linphone/mediastreamer2/plugins/msdscap/mdscap.cc b/linphone/mediastreamer2/plugins/msdscap/mdscap.cc
index a03f2e2106..0041956997 100755
--- a/linphone/mediastreamer2/plugins/msdscap/mdscap.cc
+++ b/linphone/mediastreamer2/plugins/msdscap/mdscap.cc
@@ -355,7 +355,33 @@ DECLARE_INTERFACE_(IMediaSample,IUnknown)
   STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;
   STDMETHOD_(ULONG,AddRef)(THIS) PURE;
   STDMETHOD_(ULONG,Release)(THIS) PURE;
+  STDMETHOD(GetPointer)(THIS_ BYTE **) PURE;
+  STDMETHOD_(long, GetSize)(THIS) PURE;
 };
+/*
+#define INTERFACE IMediaSample
+DECLARE_INTERFACE_(IMediaSample, IUnknown)
+{
+    STDMETHOD(GetPointer)(THIS_ BYTE **) PURE;
+    STDMETHOD_(long, GetSize)(THIS) PURE;
+    STDMETHOD(GetTime)(THIS_ REFERENCE_TIME *, REFERENCE_TIME *) PURE;
+    STDMETHOD(SetTime)(THIS_ REFERENCE_TIME *, REFERENCE_TIME *) PURE;
+    STDMETHOD(IsSyncPoint)(THIS) PURE;
+    STDMETHOD(SetSyncPoint)(THIS_ BOOL) PURE;
+    STDMETHOD(IsPreroll)(THIS) PURE;
+    STDMETHOD(SetPreroll)(THIS_ BOOL) PURE;
+    STDMETHOD_(long, GetActualDataLength)(THIS) PURE;
+    STDMETHOD(SetActualDataLength)(THIS_ long) PURE;
+    STDMETHOD(GetMediaType)(THIS_ AM_MEDIA_TYPE **) PURE;
+    STDMETHOD(SetMediaType)(THIS_ AM_MEDIA_TYPE *) PURE;
+    STDMETHOD(IsDiscontinuity)(THIS) PURE;
+    STDMETHOD(SetDiscontinuity)(THIS_ BOOL) PURE;
+    STDMETHOD(GetMediaTime)(THIS_ LONGLONG *, LONGLONG *) PURE;
+    STDMETHOD(SetMediaTime)(THIS_ LONGLONG *, LONGLONG *) PURE;
+};
+*/
+
+
 #undef INTERFACE
 
 #define INTERFACE IMemAllocator
@@ -437,11 +463,13 @@ ComPtr< IPin > getPin( IBaseFilter *filter, PIN_DIRECTION direction, int num )
   return retVal;
 }
 
-class Callback: public ISampleGrabberCB
+struct DscapState;
+
+class MSCallback: public ISampleGrabberCB
 {
 public:
-  Callback(void);
-  virtual ~Callback(void);
+  MSCallback(DscapState *s);
+  virtual ~MSCallback(void);
   STDMETHODIMP QueryInterface( REFIID riid, void **ppv );
   STDMETHODIMP_(ULONG) AddRef(void);
   STDMETHODIMP_(ULONG) Release(void);
@@ -449,101 +477,17 @@ public:
   STDMETHODIMP BufferCB(double,BYTE*,long);
 protected:
   long m_refCount;
+  DscapState *mState;
 };
 
-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;
-}
-
+#if 1
 using namespace std;
 
 int toto(void)
 {
   int retVal = 0;
   bool initialized = false;
-  Callback *callback = NULL;
+  MSCallback *callback = NULL;
   try {
     COERRORMACRO( CoInitialize(NULL), Error, , "CoInitialize failed" );
     initialized = true;
@@ -600,8 +544,7 @@ int toto(void)
            mediaType->cbFormat != 0 ) {
         VIDEOINFOHEADER *infoHeader = (VIDEOINFOHEADER*)mediaType->pbFormat;
         // TODO: choose format here !!!
-        cerr << "Setting format " << infoHeader->bmiHeader.biWidth
-             << "x" << infoHeader->bmiHeader.biHeight << endl;
+        ms_message("Setting format %ix%i",infoHeader->bmiHeader.biWidth,infoHeader->bmiHeader.biHeight);
         streamConfig->SetFormat( mediaType );
         ok = true;
       };
@@ -630,7 +573,7 @@ int toto(void)
                   "Error disabling one-shot mode" );
     COERRORMACRO( sampleGrabber->SetBufferSamples( TRUE ), Error, ,
                   "Error enabling buffer sampling" );
-    callback = new Callback;
+    callback = new MSCallback(NULL);
     COERRORMACRO( sampleGrabber->SetCallBack( callback, 0 ), Error, ,
                   "Error setting callback interface for grabbing" );
     ComPtr< IPin > grabberIn = getPin( grabberBase.get(), PINDIR_INPUT, 0 );
@@ -687,9 +630,15 @@ int toto(void)
   return retVal;
 }
 
+#endif 
 
-
-typedef struct DscapState{
+struct DscapState{
+	DscapState(){
+		callback=0;
+	}
+	~DscapState(){
+		if (callback) callback->Release();
+	}
 	int devid;
 	MSVideoSize vsize;
 	queue_t rq;
@@ -700,11 +649,114 @@ typedef struct DscapState{
 	float start_time;
 	int frame_count;
 	MSPixFmt fmt;
-} DscapState;
+	ComPtr< IBaseFilter > source;
+	ComPtr< IBaseFilter > nullRenderer;
+	ComPtr< IBaseFilter > grabberBase;
+	ComPtr< IMediaControl > mediaControl;
+	ComPtr< IMediaEvent > mediaEvent;
+	MSCallback * callback;
+};
 
 
+
+MSCallback::MSCallback(DscapState *s): m_refCount(1), mState(s)
+{
+}
+
+MSCallback::~MSCallback(void)
+{
+  ms_message("MSCallback::~MSCallback");
+}
+
+STDMETHODIMP MSCallback::QueryInterface(REFIID riid, void **ppv)
+{
+#ifndef NDEBUG
+	ms_message("MSCallback::QueryInterface");
+#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) MSCallback::AddRef(void)
+{
+	ms_message("MSCallback::AddRef");
+  m_refCount++;
+  return m_refCount;
+}
+
+STDMETHODIMP_(ULONG) MSCallback::Release(void)
+{
+  ms_message("MSCallback::Release");
+
+  if ( !InterlockedDecrement( &m_refCount ) ) {
+		int refcnt=m_refCount;
+		delete this;
+		return refcnt;
+	}
+  return m_refCount;
+}
+
+static void dummy(void*p){
+}
+
+STDMETHODIMP MSCallback::SampleCB( double par1 , IMediaSample * sample)
+{
+	uint8_t *p;
+	unsigned int size;
+	if (sample->GetPointer(&p)!=S_OK){
+		ms_error("error in GetPointer()");
+		return S_OK;
+	}
+	size=sample->GetSize();
+	ms_message( "MSCallback::SampleCB pointer=%p, size=%i",p,size);
+	mblk_t *m=esballoc(p,size,0,dummy);
+	m->b_wptr+=size;
+	ms_mutex_lock(&mState->mutex);
+	putq(&mState->rq,m);
+	ms_mutex_unlock(&mState->mutex);
+  	return S_OK;
+}
+
+
+
+STDMETHODIMP MSCallback::BufferCB( double, BYTE *b, long len)
+{
+	ms_message("MSCallback::BufferCB");
+
+	return S_OK;
+}
+
 static void dscap_init(MSFilter *f){
-	DscapState *s=(DscapState *)ms_new0(DscapState,1);
+	DscapState *s=new DscapState;
 	s->vsize.width=MS_VIDEO_SIZE_CIF_W;
 	s->vsize.height=MS_VIDEO_SIZE_CIF_H;
 	qinit(&s->rq);
@@ -722,22 +774,219 @@ static void dscap_uninit(MSFilter *f){
 	DscapState *s=(DscapState*)f->data;
 	flushq(&s->rq,0);
 	ms_mutex_destroy(&s->mutex);
-	ms_free(s);
+	delete s;
+}
+
+static char * fourcc_to_char(char *str, uint32_t fcc){
+	memcpy(str,&fcc,4);
+	str[4]='\0';
+	return str;
+}
+
+static int find_best_format(ComPtr<IAMStreamConfig> streamConfig, int count, MSVideoSize *requested_size, MSPixFmt requested_fmt ){
+	int i;
+	MSVideoSize best_found=(MSVideoSize){32768,32768};
+	int best_index=-1;
+	char fccstr[5];
+	char selected_fcc[5];
+	for (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;
+			ms_message("Seeing format %ix%i %s",infoHeader->bmiHeader.biWidth,infoHeader->bmiHeader.biHeight,
+					fourcc_to_char(fccstr,infoHeader->bmiHeader.biCompression));
+			if (ms_fourcc_to_pix_fmt(infoHeader->bmiHeader.biCompression)==requested_fmt){
+				MSVideoSize cur;
+				cur.width=infoHeader->bmiHeader.biWidth;
+				cur.height=infoHeader->bmiHeader.biHeight;
+				if (ms_video_size_greater_than(cur,*requested_size)){
+					if (ms_video_size_greater_than(best_found,cur)){
+						best_found=cur;
+						best_index=i;
+						fourcc_to_char(selected_fcc,infoHeader->bmiHeader.biCompression);
+					}
+				}
+			}
+		};
+		if ( mediaType->cbFormat != 0 )
+			CoTaskMemFree( (PVOID)mediaType->pbFormat );
+		if ( mediaType->pUnk != NULL ) mediaType->pUnk->Release();
+			CoTaskMemFree( (PVOID)mediaType );
+	}
+	if (best_index!=-1) {
+		*requested_size=best_found;
+		ms_message("Best camera format is %s %ix%i",selected_fcc,best_found.width,best_found.height);
+	}
+	return best_index;
 }
 
-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 int select_best_format(DscapState *s, ComPtr<IAMStreamConfig> streamConfig, int count){
+	int index;
+	s->fmt=MS_YUV420P;
+	index=find_best_format(streamConfig, count, &s->vsize, s->fmt);
+	if (index!=-1) goto success;
+	s->fmt=MS_YUY2;
+	index=find_best_format(streamConfig, count, &s->vsize, s->fmt);
+	if (index!=-1) goto success;
+	s->fmt=MS_YUYV;
+	index=find_best_format(streamConfig, count, &s->vsize, s->fmt);
+	if (index!=-1) goto success;
+	s->fmt=MS_RGB24;
+	index=find_best_format(streamConfig, count, &s->vsize, s->fmt);
+	if (index!=-1) {
+		s->fmt=MS_RGB24_REV;
+		goto success;
+	}
+	ms_error("This camera does not support any of our pixel formats.");
+	return -1;
+	
+	success:
+	VIDEO_STREAM_CONFIG_CAPS videoConfig;
+	AM_MEDIA_TYPE *mediaType;
+	COERRORMACRO( streamConfig->GetStreamCaps( index, &mediaType,
+                                                 (BYTE *)&videoConfig ),
+                                Error, , "Error getting stream capabilities" );
+    streamConfig->SetFormat( mediaType );
+    return 0;
+}
+
+static void create_dshow_graph(DscapState *s){
+	ComPtr< ICreateDevEnum > createDevEnum;
+	COERRORMACRO( CoInitialize(NULL), Error, , "CoInitialize failed" );
+    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< IGraphBuilder > graphBuilder;
+	graphBuilder.coCreateInstance( CLSID_FilterGraph, IID_IGraphBuilder,
+                                   "Could not create graph builder "
+                                   "interface" );
+    ComPtr< IMoniker > moniker;
+    for ( int i=0;enumMoniker->Next( 1, &moniker, &fetched )==S_OK;++i ) {
+		if (i==s->devid){
+			if (moniker->BindToObject( 0, 0, IID_IBaseFilter, (void **)&s->source )!=S_OK){
+				ms_error("Error binding moniker to base filter" );
+				return;
+			}
+		}
+	}
+	if (s->source.get()==0){
+		ms_error("Could not interface with webcam devid=%i",s->devid);
+		return;
+	}
+	moniker.reset();
+    enumMoniker.reset();
+    s->callback = new MSCallback(s);
+    ms_message("Callback created");
+    fflush(NULL);
+    try{
+    COERRORMACRO( graphBuilder->AddFilter( s->source.get(), L"Source" ),
+                  Error, , "Error adding camera source to filter graph" );
+    ComPtr< IPin > sourceOut = getPin( s->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" );
+    select_best_format(s,streamConfig,count);
+    
+    streamConfig.reset();
+
+    COERRORMACRO( CoCreateInstance( CLSID_SampleGrabber, NULL,
+                                    CLSCTX_INPROC, IID_IBaseFilter,
+                                    (void **)&s->grabberBase ),
+                  Error, , "Error creating sample grabber" );
+    COERRORMACRO( graphBuilder->AddFilter( s->grabberBase.get(), L"Grabber" ),
+                  Error, , "Error adding sample grabber to filter graph" );
+    ComPtr< ISampleGrabber > sampleGrabber;
+    COERRORMACRO( s->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" );
+
+    COERRORMACRO( sampleGrabber->SetCallBack( s->callback, 0 ), Error, ,
+                  "Error setting callback interface for grabbing" );
+    ComPtr< IPin > grabberIn = getPin( s->grabberBase.get(), PINDIR_INPUT, 0 );
+    ERRORMACRO( grabberIn.get() != NULL, Error, ,
+                "Error getting input of sample grabber" );
+    ComPtr< IPin > grabberOut = getPin( s->grabberBase.get(), PINDIR_OUTPUT, 0 );
+    ERRORMACRO( grabberOut.get() != NULL, Error, ,
+                "Error getting output of sample grabber" );
+
+    
+    COERRORMACRO( CoCreateInstance( CLSID_NullRenderer, NULL,
+                                    CLSCTX_INPROC, IID_IBaseFilter,
+                                    (void **)&s->nullRenderer ),
+                  Error, , "Error creating Null Renderer" );
+    COERRORMACRO( graphBuilder->AddFilter( s->nullRenderer.get(), L"Sink" ),
+                  Error, , "Error adding null renderer to filter graph" );
+    ComPtr< IPin > nullIn = getPin( s->nullRenderer.get(), PINDIR_INPUT, 0 );
+
+    ms_message("Attempting to connect");
+    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" );
+
+    ms_message("Success!!!!!!!!!!!!!!!!!!!!!");
+
+
+	ms_message("Querying control interface");
+    COERRORMACRO( graphBuilder->QueryInterface( IID_IMediaControl,
+                                                (void **)&s->mediaControl ),
+                  Error, , "Error requesting media control interface" );
+	ms_message("Got the control interface (%p).",s->mediaControl.get());
+    ms_message("Going to start the graph");
+    HRESULT r;
+	if ((r=s->mediaControl->Run())!=S_OK){
+		ms_error("Error starting graph (%i)",r);
+	}
+    ms_message("Graph started");
+    COERRORMACRO( graphBuilder->QueryInterface( IID_IMediaEvent,
+                                                (void **)&s->mediaEvent ),
+                  Error, , "Error requesting event interface" );
+    ms_message("Graph created");
+	} catch ( Error &e ) {
+    	ms_error(e.what());
+	};
 }
 
 static void dscap_preprocess(MSFilter * obj){
 	DscapState *s=(DscapState*)obj->data;
+	create_dshow_graph(s);
+	//toto();
+    ms_message("preprocess done.");
 }
 
 static void dscap_postprocess(MSFilter * obj){
 	DscapState *s=(DscapState*)obj->data;
+	if (s->mediaControl.get()!=NULL){
+		s->mediaControl->Stop();
+    	long evCode = 0;
+    	s->mediaEvent->WaitForCompletion( INFINITE, &evCode );
+	}
 	flushq(&s->rq,0);
 }
 
@@ -756,16 +1005,15 @@ static void dscap_process(MSFilter * obj){
 	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_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);
@@ -845,6 +1093,7 @@ static void ms_dshow_detect(MSWebCamManager *obj){
 	int i;
 	MSWebCam *cam;
 	ComPtr<IPropertyBag> pBag;
+	
 	COERRORMACRO( CoInitialize(NULL), Error, , "CoInitialize failed" );
  
     ComPtr< ICreateDevEnum > createDevEnum;
diff --git a/linphone/mediastreamer2/src/mscommon.c b/linphone/mediastreamer2/src/mscommon.c
index ddd0f3b3fc..8d0f7c33f9 100644
--- a/linphone/mediastreamer2/src/mscommon.c
+++ b/linphone/mediastreamer2/src/mscommon.c
@@ -494,7 +494,7 @@ static MSWebCamDesc * ms_web_cam_descs[]={
 #if defined(WIN32) && defined(HAVE_DIRECTSHOW)
 	&ms_directx_cam_desc,
 #endif
-#if defined(WIN32) && !defined(HAVE_DIRECTSHOW)
+#if defined(WIN32) && defined(HAVE_VFW)
 	&ms_vfw_cam_desc,
 #endif
 	&mire_desc,
-- 
GitLab