[QCAP] VfwCapture

Maarten Lankhorst m.b.lankhorst at gmail.com
Fri May 20 18:38:35 CDT 2005


here you got your driver model :/

ChangeLog
Implemented VfwCapture interface
-------------- next part --------------
--- Makefile.in	2005-05-18 17:34:04.000000000 +0200
+++ Makefile.in	2005-05-21 01:31:08.000000000 +0200
@@ -13,7 +13,10 @@
 	enummedia.c \
 	enumpins.c \
 	pin.c \
-	qcap_main.c
+	qcap_main.c \
+	vfwcapture.c \
+#	v4l.c \
+#	yuv.c
 
 RC_SRCS = version.rc
 
--- /dev/null	2005-05-20 14:44:40.262390264 +0200
+++ vfwcapture.c	2005-05-21 01:16:01.000000000 +0200
@@ -0,0 +1,823 @@
+/* Video For Windows Steering structure
+ *
+ * Copyright 2005 Maarten Lankhorst
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include "config.h"
+
+#define NONAMELESSSTRUCT
+#define NONAMELESSUNION
+
+#include <stdarg.h>
+
+#define COBJMACROS
+
+#include "windef.h"
+#include "winbase.h"
+#include "wtypes.h"
+#include "wingdi.h"
+#include "winuser.h"
+#include "dshow.h"
+
+#include "qcap_main.h"
+#include "wine/unicode.h"
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(qcap);
+
+#include "pin.h"
+#include "capture.h"
+#include "uuids.h"
+#include "mmreg.h"
+#include "vfwmsgs.h"
+#include "amvideo.h"
+#include "strmif.h"
+#include "ddraw.h"
+#include "ocidl.h"
+#include "oleauto.h"
+
+#undef HAVE_V4L2
+
+static const Video_Init Constructors[] = {
+#if 0/*def HAVE_LINUX_VIDEODEV_H*/
+#ifdef HAVE_V4L2
+/* There are 5 reasons I don't add V4l2 support
+ * 1. Webcams don't use it
+ * 2. It is more complicated then V4l and more complicated then it needs to be
+ * 3. V4l2 devices can fall back to V4l
+ * 4. No one really misses it if I leave it out..
+ * 5. (MAIN REASON) *I* don't miss it, if you do, write V4l2 support yourself!
+ * Feel tree to write a V4L2 init function here though */
+   V4l2_Init,
+#endif
+   V4l_Init,
+#endif
+};
+
+static HRESULT Capture_Initialise(Capture **dimi, IPin *pOut, USHORT card)
+{
+   int n;
+   *dimi = CoTaskMemAlloc(sizeof(Capture));
+   if (!dimi) return E_OUTOFMEMORY;
+   TRACE("Trying to find a suitable driver.. bear with me\n");
+
+   for (n = 0; n < sizeof(Constructors) / sizeof(Video_Init); n++)
+      if (SUCCEEDED(Constructors[n](*dimi, pOut, card)))
+         return S_OK;
+
+   if (!n)
+      ERR("No video capture drivers are compiled, Video for wine support NOT available\n");
+   CoTaskMemFree(*dimi);
+   return E_FAIL;
+}
+
+static const IBaseFilterVtbl VfwCapture_Vtbl;
+static const IAMStreamConfigVtbl IAMStreamConfig_VTable;
+static const IAMVideoProcAmpVtbl IAMVideoProcAmp_VTable;
+static const IPersistPropertyBagVtbl IPersistPropertyBag_VTable;
+static const IPinVtbl VfwPin_Vtbl;
+
+static HRESULT VfwPin_Construct(IBaseFilter * pBaseFilter, LPCRITICAL_SECTION pCritSec, IPin ** ppPin);
+static const WCHAR wszOutputPinName[] = { 'O','u','t','p','u','t',0 };
+
+typedef struct VfwCapture
+{
+   const struct IBaseFilterVtbl * lpVtbl;
+   const struct IAMStreamConfigVtbl * IAMStreamConfig_vtbl;
+   const struct IAMVideoProcAmpVtbl * IAMVideoProcAmp_vtbl;
+   const struct IPersistPropertyBagVtbl * IPersistPropertyBag_vtbl;
+
+   BOOL init;
+   Capture *myCap;
+   ULONG refCount;
+   FILTER_INFO filterInfo;
+   FILTER_STATE state;
+   CRITICAL_SECTION csFilter;
+
+   IPin * pOutputPin;
+} VfwCapture;
+
+/* VfwPin implementation */
+typedef struct VfwPinImpl
+{
+   OutputPin pin;
+   Capture *myCap;
+   IKsPropertySetVtbl * KSP_VT;
+} VfwPinImpl;
+
+IUnknown * WINAPI QCAP_createVFWCaptureFilter(IUnknown *pUnkOuter, HRESULT *phr)
+{
+   VfwCapture *pVfwCapture;
+   HRESULT hr;
+
+   TRACE("%p - %p\n", pUnkOuter, phr);
+
+   *phr = CLASS_E_NOAGGREGATION;
+   if (pUnkOuter)
+      return NULL; 
+   *phr = E_OUTOFMEMORY;
+
+   pVfwCapture = CoTaskMemAlloc(sizeof(VfwCapture));
+
+   if (!pVfwCapture)
+      return NULL;
+
+   pVfwCapture->lpVtbl = &VfwCapture_Vtbl;
+   pVfwCapture->IAMStreamConfig_vtbl = &IAMStreamConfig_VTable;
+   pVfwCapture->IAMVideoProcAmp_vtbl = &IAMVideoProcAmp_VTable;
+   pVfwCapture->IPersistPropertyBag_vtbl = &IPersistPropertyBag_VTable;
+   pVfwCapture->refCount = 1;
+   pVfwCapture->filterInfo.achName[0] = '\0';
+   pVfwCapture->filterInfo.pGraph = NULL;
+   pVfwCapture->state = State_Stopped;
+   pVfwCapture->init = FALSE;
+   InitializeCriticalSection(&pVfwCapture->csFilter);
+   hr = VfwPin_Construct((IBaseFilter *)&pVfwCapture->lpVtbl, &pVfwCapture->csFilter, &pVfwCapture->pOutputPin);
+   if (!SUCCEEDED(hr))
+   {
+      CoTaskMemFree(pVfwCapture);
+      return NULL;
+   }
+   TRACE("-- created at %p\n", pVfwCapture);
+
+   ObjectRefCount(TRUE);
+   *phr = S_OK;
+   return (IUnknown *)pVfwCapture;
+}
+
+static HRESULT WINAPI VfwCapture_QueryInterface(IBaseFilter * iface, REFIID riid, LPVOID * ppv)
+{
+   VfwCapture *This = (VfwCapture *)iface;
+   TRACE("(%s, %p)\n", debugstr_guid(riid), ppv);
+   *ppv = NULL;
+
+   if (IsEqualIID(riid, &IID_IUnknown))
+      *ppv = (LPVOID)This;
+   else if (IsEqualIID(riid, &IID_IPersist))
+      *ppv = (LPVOID)This;
+   else if (IsEqualIID(riid, &IID_IMediaFilter))
+      *ppv = (LPVOID)This;
+   else if (IsEqualIID(riid, &IID_IBaseFilter))
+      *ppv = (LPVOID)This;
+   else if (IsEqualIID(riid, &IID_IAMStreamConfig))
+      *ppv = (LPVOID)&(This->IAMStreamConfig_vtbl);
+   else if (IsEqualIID(riid, &IID_IAMVideoProcAmp))
+      *ppv = (LPVOID)&(This->IAMVideoProcAmp_vtbl);
+   else if (IsEqualIID(riid, &IID_IPersistPropertyBag))
+      *ppv = (LPVOID)&(This->IPersistPropertyBag_vtbl);
+
+   if (!IsEqualIID(riid, &IID_IUnknown) &&
+       !IsEqualIID(riid, &IID_IPersist) &&
+       !IsEqualIID(riid, &IID_IPersistPropertyBag) &&
+       !This->init) {
+      FIXME("Capture system not initialised when looking for %s\n"
+            "\t trying it on primary device now\n", debugstr_guid(riid));
+      if (FAILED(Capture_Initialise(&This->myCap, (IPin *)This->pOutputPin, 0))); {
+         ERR("VfwCapture initialisation failed\n");
+         return E_UNEXPECTED;
+      }
+      This->init = TRUE;
+   }
+
+   if (*ppv)
+   {
+      TRACE("Returning %s interface\n", debugstr_guid(riid));
+      IUnknown_AddRef((IUnknown *)(*ppv));
+      return S_OK;
+   }
+
+   FIXME("No interface for %s!\n", debugstr_guid(riid));
+   return E_NOINTERFACE;
+}
+
+static ULONG WINAPI VfwCapture_AddRef(IBaseFilter * iface)
+{
+   VfwCapture *This = (VfwCapture *)iface;
+   ULONG refCount = InterlockedIncrement(&This->refCount);
+
+   TRACE("(%p/%p)->() New refcount: %ld\n", This, iface, refCount);
+
+   return refCount;
+}
+
+static ULONG WINAPI VfwCapture_Release(IBaseFilter * iface)
+{
+   VfwCapture *This = (VfwCapture *)iface;
+   ULONG refCount = InterlockedDecrement(&This->refCount);
+   TRACE("(%p/%p)->() New refcount: %ld\n", This, iface, refCount);
+
+   if (!refCount)
+   {
+      TRACE("(): Destroying everything!\n");
+      if (This->init) {
+         if (This->state != State_Stopped)
+            INVOKE(This->myCap, Stop, &This->state);
+         INVOKENP(This->myCap, Destroy);
+      }
+      if (((IPinImpl *)This->pOutputPin)->pConnectedTo != NULL)
+      {
+         IPin_Disconnect(((IPinImpl *)This->pOutputPin)->pConnectedTo);
+         IPin_Disconnect(This->pOutputPin);
+      }
+      IPin_Release(This->pOutputPin);
+      DeleteCriticalSection(&This->csFilter);
+      This->lpVtbl = NULL;
+      CoTaskMemFree(This);
+      ObjectRefCount(FALSE);
+   }
+   return refCount;
+}
+
+/** IPersist methods **/
+
+static HRESULT WINAPI VfwCapture_GetClassID(IBaseFilter * iface, CLSID * pClsid)
+{
+   TRACE("(%p)\n", pClsid);
+   *pClsid = CLSID_VfwCapture;
+   return S_OK;
+}
+
+/** IMediaFilter methods **/
+
+static HRESULT WINAPI VfwCapture_Stop(IBaseFilter * iface)
+{
+   VfwCapture *This = (VfwCapture *)iface;
+   TRACE("()\n");
+   return INVOKE(This->myCap, Stop, &This->state);
+}
+
+static HRESULT WINAPI VfwCapture_Pause(IBaseFilter * iface)
+{
+   VfwCapture *This = (VfwCapture *)iface;
+   TRACE("()\n");
+   return INVOKE(This->myCap, Pause, &This->state);
+}
+
+static HRESULT WINAPI VfwCapture_Run(IBaseFilter * iface, REFERENCE_TIME tStart)
+{
+   VfwCapture *This = (VfwCapture *)iface;
+   TRACE("(%lx%08lx)\n", (ULONG)(tStart >> 32), (ULONG)tStart);
+   return INVOKE(This->myCap, Run, &This->state);
+}
+
+static HRESULT WINAPI VfwCapture_GetState(IBaseFilter * iface, DWORD dwMilliSecsTimeout, FILTER_STATE *pState)
+{
+   VfwCapture *This = (VfwCapture *)iface;
+   TRACE("(%lu, %p)\n", dwMilliSecsTimeout, pState);
+   *pState = This->state;
+   return S_OK;
+}
+
+static HRESULT WINAPI VfwCapture_SetSyncSource(IBaseFilter * iface, IReferenceClock *pClock)
+{
+   TRACE("(%p)\n", pClock);
+   return S_OK;
+}
+
+static HRESULT WINAPI VfwCapture_GetSyncSource(IBaseFilter * iface, IReferenceClock **ppClock)
+{
+   TRACE("(%p)\n", ppClock);
+   return S_OK;
+}
+
+/** IBaseFilter methods **/
+
+static HRESULT WINAPI VfwCapture_EnumPins(IBaseFilter * iface, IEnumPins **ppEnum)
+{
+   ENUMPINDETAILS epd;
+   VfwCapture *This = (VfwCapture *)iface;
+
+   TRACE("(%p)\n", ppEnum);
+
+   epd.cPins = 1;
+   epd.ppPins = &This->pOutputPin;
+   return IEnumPinsImpl_Construct(&epd, ppEnum);
+}
+
+static HRESULT WINAPI VfwCapture_FindPin(IBaseFilter * iface, LPCWSTR Id, IPin **ppPin)
+{
+   FIXME("(%s, %p) - stub\n", debugstr_w(Id), ppPin);
+   return E_NOTIMPL;
+}
+
+static HRESULT WINAPI VfwCapture_QueryFilterInfo(IBaseFilter * iface, FILTER_INFO *pInfo)
+{
+   VfwCapture *This = (VfwCapture *)iface;
+
+   TRACE("(%p)\n", pInfo);
+
+   strcpyW(pInfo->achName, This->filterInfo.achName);
+   pInfo->pGraph = This->filterInfo.pGraph;
+
+   if (pInfo->pGraph)
+        IFilterGraph_AddRef(pInfo->pGraph);
+   return S_OK;
+}
+
+static HRESULT WINAPI VfwCapture_JoinFilterGraph(IBaseFilter * iface, IFilterGraph *pGraph, LPCWSTR pName)
+{
+   VfwCapture *This = (VfwCapture *)iface;
+
+   TRACE("(%p, %s)\n", pGraph, debugstr_w(pName));
+
+   if (pName)
+       strcpyW(This->filterInfo.achName, pName);
+   else
+       *This->filterInfo.achName = 0;
+   This->filterInfo.pGraph = pGraph; /* NOTE: do NOT increase ref. count */
+
+   return S_OK;
+}
+
+static HRESULT WINAPI VfwCapture_QueryVendorInfo(IBaseFilter * iface, LPWSTR *pVendorInfo)
+{
+   FIXME("(%p) - stub\n", pVendorInfo);
+   return E_NOTIMPL;
+}
+
+static const IBaseFilterVtbl VfwCapture_Vtbl =
+{   
+   VfwCapture_QueryInterface,
+   VfwCapture_AddRef,
+   VfwCapture_Release,
+   VfwCapture_GetClassID,
+   VfwCapture_Stop,
+   VfwCapture_Pause,
+   VfwCapture_Run,
+   VfwCapture_GetState,
+   VfwCapture_SetSyncSource,
+   VfwCapture_GetSyncSource,
+   VfwCapture_EnumPins,
+   VfwCapture_FindPin,
+   VfwCapture_QueryFilterInfo,
+   VfwCapture_JoinFilterGraph,
+   VfwCapture_QueryVendorInfo
+};
+
+/* AMStreamConfig interface, we only need to implement {G,S}etFormat */
+static HRESULT WINAPI AMStreamConfig_QueryInterface(IAMStreamConfig * iface, REFIID riid, LPVOID * ppv)
+{
+   ICOM_THIS_MULTI(VfwCapture, IAMStreamConfig_vtbl, iface);
+   TRACE("%p --> %s\n", This, debugstr_guid(riid));
+   if (IsEqualIID(riid, &IID_IUnknown) ||
+       IsEqualIID(riid, &IID_IAMStreamConfig))
+   {
+       *ppv = (LPVOID)iface;
+       return S_OK;
+   }
+
+   FIXME("No interface for iid %s\n", debugstr_guid(riid));
+   return E_NOINTERFACE;
+}
+
+static ULONG WINAPI AMStreamConfig_AddRef(IAMStreamConfig * iface)
+{
+   ICOM_THIS_MULTI(VfwCapture, IAMStreamConfig_vtbl, iface);
+   TRACE("%p --> Forwarding to VfwCapture (%p)\n", iface, This);
+   return IUnknown_AddRef((IUnknown *)This);
+}
+
+static ULONG WINAPI AMStreamConfig_Release(IAMStreamConfig * iface)
+{
+   ICOM_THIS_MULTI(VfwCapture, IAMStreamConfig_vtbl, iface);
+   TRACE("%p --> Forwarding to VfwCapture (%p)\n", iface, This);
+   return IUnknown_Release((IUnknown *)This);
+}
+
+static HRESULT WINAPI AMStreamConfig_SetFormat(IAMStreamConfig *iface,
+                                              AM_MEDIA_TYPE *pmt) {
+   HRESULT hr;
+   ICOM_THIS_MULTI(VfwCapture, IAMStreamConfig_vtbl, iface);
+
+   TRACE("(%p): %p->%p\n", iface, pmt, pmt->pbFormat);
+
+   if (This->state != State_Stopped)
+   {
+      TRACE("Returning not stopped error\n");
+      return VFW_E_NOT_STOPPED;
+   }
+
+   dump_AM_MEDIA_TYPE(pmt);
+
+   if (((IPinImpl *)This->pOutputPin)->pConnectedTo != NULL) {
+      hr = IPin_QueryAccept(((IPinImpl *)This->pOutputPin)->pConnectedTo, pmt);
+      TRACE("Would accept: %ld\n", hr);
+      if (hr == S_FALSE)
+         return VFW_E_INVALIDMEDIATYPE;
+   }
+
+   hr = INVOKE(This->myCap, SetFormat, pmt);
+   if (SUCCEEDED(hr) && This->filterInfo.pGraph != NULL &&
+                      ((IPinImpl *)This->pOutputPin)->pConnectedTo != NULL) {
+      hr = IFilterGraph_Reconnect(This->filterInfo.pGraph, This->pOutputPin);
+      if (SUCCEEDED(hr))
+         TRACE("Reconnection completed, with new media format..\n");
+   }
+   TRACE("Returning: %ld\n", hr);
+   return hr;
+}
+
+static HRESULT WINAPI AMStreamConfig_GetFormat(IAMStreamConfig *iface,
+                                              AM_MEDIA_TYPE **pmt) {
+   ICOM_THIS_MULTI(VfwCapture, IAMStreamConfig_vtbl, iface);
+
+   TRACE("%p -> (%p)\n", iface, pmt);
+   return INVOKE(This->myCap, GetFormat, pmt);
+}
+
+static HRESULT WINAPI AMStreamConfig_GetNumberOfCapabilities(IAMStreamConfig *iface, int *piCount, int *piSize)
+{
+   FIXME("%p: %p %p - stub, intentional\n", iface, piCount, piSize);
+   return E_NOTIMPL; /* Not implemented for this interface */
+}
+
+static HRESULT WINAPI AMStreamConfig_GetStreamCaps(IAMStreamConfig *iface,
+int iIndex, AM_MEDIA_TYPE **pmt, BYTE *pSCC)
+{
+   FIXME("%p: %d %p %p - stub, intentional\n", iface, iIndex, pmt, pSCC);
+   return E_NOTIMPL; /* Not implemented for this interface */
+}
+
+static const IAMStreamConfigVtbl IAMStreamConfig_VTable =
+{
+   AMStreamConfig_QueryInterface,
+   AMStreamConfig_AddRef,
+   AMStreamConfig_Release,
+   AMStreamConfig_SetFormat,
+   AMStreamConfig_GetFormat,
+   AMStreamConfig_GetNumberOfCapabilities,
+   AMStreamConfig_GetStreamCaps
+};
+
+static HRESULT WINAPI AMVideoProcAmp_QueryInterface(IAMVideoProcAmp * iface, REFIID riid, LPVOID * ppv)
+{
+   if (IsEqualIID(riid, &IID_IUnknown) ||
+       IsEqualIID(riid, &IID_IAMVideoProcAmp))
+   {
+       *ppv = (LPVOID)iface;
+       return S_OK;
+   }
+
+   FIXME("No interface for iid %s\n", debugstr_guid(riid));
+   return E_NOINTERFACE;
+}
+
+static ULONG WINAPI AMVideoProcAmp_AddRef(IAMVideoProcAmp * iface)
+{
+   ICOM_THIS_MULTI(VfwCapture, IAMVideoProcAmp_vtbl, iface);
+   TRACE("%p --> Forwarding to VfwCapture (%p)\n", iface, This);
+   return IUnknown_AddRef((IUnknown *)This);
+}
+
+static ULONG WINAPI AMVideoProcAmp_Release(IAMVideoProcAmp * iface)
+{
+   ICOM_THIS_MULTI(VfwCapture, IAMVideoProcAmp_vtbl, iface);
+   TRACE("%p --> Forwarding to VfwCapture (%p)\n", iface, This);
+   return IUnknown_Release((IUnknown *)This);
+}
+
+static HRESULT WINAPI AMVideoProcAmp_GetRange(IAMVideoProcAmp * iface, long Property, long *pMin, long *pMax, long *pSteppingDelta, long *pDefault, long *pCapsFlags)
+{
+   ICOM_THIS_MULTI(VfwCapture, IAMVideoProcAmp_vtbl, iface);
+   return INVOKE(This->myCap, GetPropRange, Property, pMin, pMax, pSteppingDelta, pDefault, pCapsFlags);
+}
+
+static HRESULT WINAPI AMVideoProcAmp_Set(IAMVideoProcAmp * iface, long Property, long lValue, long Flags)
+{
+   ICOM_THIS_MULTI(VfwCapture, IAMVideoProcAmp_vtbl, iface);
+   return INVOKE(This->myCap, Set_Prop, Property, lValue, Flags);
+}
+
+static HRESULT WINAPI AMVideoProcAmp_Get(IAMVideoProcAmp * iface, long Property, long *lValue, long *Flags)
+{
+   ICOM_THIS_MULTI(VfwCapture, IAMVideoProcAmp_vtbl, iface);
+   return INVOKE(This->myCap, Get_Prop, Property, lValue, Flags);
+}
+
+static const IAMVideoProcAmpVtbl IAMVideoProcAmp_VTable =
+{
+   AMVideoProcAmp_QueryInterface,
+   AMVideoProcAmp_AddRef,
+   AMVideoProcAmp_Release,
+   AMVideoProcAmp_GetRange,
+   AMVideoProcAmp_Set,
+   AMVideoProcAmp_Get,
+};
+
+static HRESULT WINAPI PPB_QueryInterface(IPersistPropertyBag * iface, REFIID riid, LPVOID * ppv)
+{
+   ICOM_THIS_MULTI(VfwCapture, IPersistPropertyBag_vtbl, iface);
+   if (IsEqualIID(riid, &IID_IUnknown) ||
+       IsEqualIID(riid, &IID_IPersist) ||
+       IsEqualIID(riid, &IID_IPersistPropertyBag))
+   {
+      *ppv = (LPVOID)iface;
+      return S_OK;
+   }
+   if (IsEqualIID(riid, &IID_IBaseFilter)) {
+      FIXME("Native devenum asks for IBaseFilter, should I do this?\n");
+      *ppv = (LPVOID)This;
+      IUnknown_AddRef((IUnknown *)This);
+      return S_OK;
+   }
+
+   FIXME("No interface for iid %s\n", debugstr_guid(riid));
+   return E_NOINTERFACE;
+}
+
+static ULONG WINAPI PPB_AddRef(IPersistPropertyBag * iface)
+{
+   ICOM_THIS_MULTI(VfwCapture, IPersistPropertyBag_vtbl, iface);
+   TRACE("%p --> Forwarding to VfwCapture (%p)\n", iface, This);
+   return IUnknown_AddRef((IUnknown *)This);
+}
+
+static ULONG WINAPI PPB_Release(IPersistPropertyBag * iface)
+{
+   ICOM_THIS_MULTI(VfwCapture, IPersistPropertyBag_vtbl, iface);
+   TRACE("%p --> Forwarding to VfwCapture (%p)\n", iface, This);
+   return IUnknown_Release((IUnknown *)This);
+}
+
+static HRESULT WINAPI PPB_GetClassID(IPersistPropertyBag * iface, CLSID * pClassID)
+{
+   ICOM_THIS_MULTI(VfwCapture, IPersistPropertyBag_vtbl, iface);
+   FIXME("%p - stub\n", This);
+   return E_NOTIMPL;
+}
+
+static HRESULT WINAPI PPB_InitNew(IPersistPropertyBag * iface)
+{
+   ICOM_THIS_MULTI(VfwCapture, IPersistPropertyBag_vtbl, iface);
+   FIXME("%p - stub\n", This);
+   return E_NOTIMPL;
+}
+
+static HRESULT WINAPI PPB_Load(IPersistPropertyBag * iface, IPropertyBag *pPropBag, IErrorLog *pErrorLog)
+{
+   ICOM_THIS_MULTI(VfwCapture, IPersistPropertyBag_vtbl, iface);
+   HRESULT hr;
+   VARIANT var;
+   const OLECHAR VFWIndex[] = {'V','F','W','I','n','d','e','x',0};
+   V_VT(&var) = VT_I4;
+
+   TRACE("%p/%p-> (%p, %p)\n", iface, This, pPropBag, pErrorLog);
+
+   hr = IPropertyBag_Read(pPropBag, (LPCOLESTR)VFWIndex, &var, pErrorLog);
+
+   if (SUCCEEDED(hr)) {
+      hr = Capture_Initialise(&This->myCap, This->pOutputPin, (USHORT)var.__VARIANT_NAME_1.__VARIANT_NAME_2.__VARIANT_NAME_3.ulVal);
+      ((VfwPinImpl *)This->pOutputPin)->myCap = This->myCap;
+      if (SUCCEEDED(hr))
+        This->init = TRUE;
+   }
+
+   return hr;
+}
+
+static HRESULT WINAPI PPB_Save(IPersistPropertyBag * iface, IPropertyBag *pPropBag, BOOL fClearDirty, BOOL fSaveAllProperties)
+{
+   ICOM_THIS_MULTI(VfwCapture, IPersistPropertyBag_vtbl, iface);
+   FIXME("%p - stub\n", This);
+   return E_NOTIMPL;
+}
+
+static const IPersistPropertyBagVtbl IPersistPropertyBag_VTable =
+{
+   PPB_QueryInterface,
+   PPB_AddRef,
+   PPB_Release,
+   PPB_GetClassID,
+   PPB_InitNew,
+   PPB_Load,
+   PPB_Save
+};
+
+/* IKsPropertySet interface */
+static HRESULT WINAPI KSP_QueryInterface(IKsPropertySet * iface, REFIID riid, LPVOID * ppv)
+{
+   if (IsEqualIID(riid, &IID_IUnknown) ||
+       IsEqualIID(riid, &IID_IKsPropertySet))
+   {
+       *ppv = (LPVOID)iface;
+       return S_OK;
+   }
+
+   FIXME("No interface for iid %s\n", debugstr_guid(riid));
+   return E_NOINTERFACE;
+}
+
+static ULONG WINAPI KSP_AddRef(IKsPropertySet * iface)
+{
+   ICOM_THIS_MULTI(VfwPinImpl, KSP_VT, iface);
+   TRACE("%p --> Forwarding to VfwPin (%p)\n", iface, This);
+   return IUnknown_AddRef((IUnknown *)This);
+}
+
+static ULONG WINAPI KSP_Release(IKsPropertySet * iface)
+{
+   ICOM_THIS_MULTI(VfwPinImpl, KSP_VT, iface);
+   TRACE("%p --> Forwarding to VfwPin (%p)\n", iface, This);
+   return IUnknown_Release((IUnknown *)This);
+}
+
+static HRESULT WINAPI KSP_Set(IKsPropertySet * iface, REFGUID guidPropSet, DWORD dwPropID, LPVOID pInstanceData, DWORD cbInstanceData, LPVOID pPropData, DWORD cbPropData)
+{
+   FIXME("%p: stub\n", iface);
+   return E_NOTIMPL;
+}
+
+static HRESULT WINAPI KSP_Get(IKsPropertySet * iface, REFGUID guidPropSet, DWORD dwPropID, LPVOID pInstanceData, DWORD cbInstanceData, LPVOID pPropData, DWORD cbPropData, DWORD *pcbReturned)
+{
+   TRACE("()\n");
+   if (!IsEqualIID(guidPropSet, &AMPROPSETID_Pin))
+      return E_PROP_SET_UNSUPPORTED;
+   if (pPropData == NULL && pcbReturned == NULL)
+      return E_POINTER;
+   if (pcbReturned)
+      *pcbReturned = sizeof(GUID);
+   if (pPropData == NULL)
+      return S_OK;
+   if (cbPropData < sizeof(GUID))
+      return E_UNEXPECTED;
+   *(GUID *)pPropData = PIN_CATEGORY_PREVIEW;
+   FIXME("() Not adding a pin with PIN_CATEGORY_CAPTURE for a reason..\n");
+   return S_OK;
+}
+
+static HRESULT WINAPI KSP_QuerySupported(IKsPropertySet * iface, REFGUID guidPropSet, DWORD dwPropID, DWORD *pTypeSupport)
+{
+   FIXME("%p: stub\n", iface);
+   return E_NOTIMPL;
+}
+
+static IKsPropertySetVtbl KSP_VTable =
+{
+   KSP_QueryInterface,
+   KSP_AddRef,
+   KSP_Release,
+   KSP_Set,
+   KSP_Get,
+   KSP_QuerySupported
+};
+
+static HRESULT VfwPin_Construct(IBaseFilter * pBaseFilter, LPCRITICAL_SECTION pCritSec, IPin ** ppPin)
+{
+   ALLOCATOR_PROPERTIES ap;
+   VfwPinImpl * pPinImpl;
+   PIN_INFO piOutput;
+
+   pPinImpl = CoTaskMemAlloc(sizeof(*pPinImpl));
+   if (!pPinImpl)
+      return E_OUTOFMEMORY;
+
+/* What we put here doesn't matter, the driver function should override it then commit */
+   ap.cBuffers = 3;
+   ap.cbBuffer = 230400;
+   ap.cbAlign = 1;
+   ap.cbPrefix = 0;
+
+   piOutput.dir = PINDIR_OUTPUT;
+   piOutput.pFilter = pBaseFilter;
+   strcpyW(piOutput.achName, wszOutputPinName);
+   ObjectRefCount(TRUE);
+
+   if (SUCCEEDED(OutputPin_Init(&piOutput, &ap, pBaseFilter, NULL, pCritSec, &pPinImpl->pin)))
+   {
+      pPinImpl->KSP_VT = &KSP_VTable;
+      pPinImpl->pin.pin.lpVtbl = &VfwPin_Vtbl;
+      *ppPin = (IPin *)(&pPinImpl->pin.pin.lpVtbl);
+      return S_OK;
+   }
+   return E_FAIL;
+}
+
+static HRESULT WINAPI VfwPin_QueryInterface(IPin * iface, REFIID riid, LPVOID * ppv)
+{
+   VfwPinImpl *This = (VfwPinImpl *)iface;
+   TRACE("%s %p\n", debugstr_guid(riid), ppv);
+   *ppv = NULL;
+   if (IsEqualIID(riid, &IID_IUnknown))
+      *ppv = (LPVOID)This;
+   else if (IsEqualIID(riid, &IID_IPin))
+      *ppv = (LPVOID)This;
+   else if (IsEqualIID(riid, &IID_IKsPropertySet))
+      *ppv = (LPVOID)&(This->KSP_VT);
+
+   if (*ppv)
+   {
+      IUnknown_AddRef((IUnknown *)(*ppv));
+      return S_OK;
+   }
+
+   FIXME("No interface for %s!\n", debugstr_guid(riid));
+   return E_NOINTERFACE;
+}
+
+static ULONG WINAPI VfwPin_AddRef(IPin * iface)
+{
+    VfwPinImpl *This = (VfwPinImpl *)iface;
+    ULONG refCount = InterlockedIncrement(&This->pin.pin.refCount);
+
+    TRACE("() -> new refcount: %lu\n", refCount);
+
+    return refCount;
+}
+
+static ULONG WINAPI VfwPin_Release(IPin * iface)
+{
+   VfwPinImpl *This = (VfwPinImpl *)iface;
+   ULONG refCount = InterlockedDecrement(&This->pin.pin.refCount);
+   TRACE("() -> new refcount: %lu\n", refCount);
+
+   if (!refCount)
+   {
+      CoTaskMemFree(This);
+      ObjectRefCount(FALSE);
+   }
+   return refCount;
+}
+
+static HRESULT WINAPI VfwPin_EnumMediaTypes(IPin * iface, IEnumMediaTypes ** ppEnum)
+{
+   ENUMMEDIADETAILS emd;
+   AM_MEDIA_TYPE *pmt;
+   HRESULT hr;
+
+   VfwPinImpl *This = (VfwPinImpl *)iface;
+   emd.cMediaTypes = 1;
+   hr = INVOKE(This->myCap, GetFormat, &pmt);
+   emd.pMediaTypes = pmt;
+   if (SUCCEEDED(hr)) hr = IEnumMediaTypesImpl_Construct(&emd, ppEnum);
+   TRACE("%p -- %lx\n", This, hr);
+   DeleteMediaType(pmt);
+   return hr;
+}
+
+static HRESULT WINAPI VfwPin_QueryInternalConnections(IPin * iface, IPin ** apPin, ULONG * cPin)
+{
+    TRACE("(%p)->(%p, %p)\n", iface, apPin, cPin);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI VfwPin_EndOfStream(IPin * iface)
+{
+    TRACE("()\n");
+    return E_UNEXPECTED;
+}
+
+static HRESULT WINAPI VfwPin_BeginFlush(IPin * iface)
+{
+    TRACE("(%p)->()\n", iface);
+    return E_UNEXPECTED;
+}
+
+static HRESULT WINAPI VfwPin_EndFlush(IPin * iface)
+{
+    TRACE("(%p)->()\n", iface);
+    return E_UNEXPECTED;
+}
+
+static HRESULT WINAPI VfwPin_NewSegment(IPin * iface, REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate)
+{
+    TRACE("(%p)->(%lx%08lx, %lx%08lx, %e)\n", iface, (ULONG)(tStart >> 32), (ULONG)tStart, (ULONG)(tStop >> 32), (ULONG)tStop, dRate);
+    return E_UNEXPECTED;
+}
+
+static const IPinVtbl VfwPin_Vtbl =
+{
+   VfwPin_QueryInterface,
+   VfwPin_AddRef,
+   VfwPin_Release,
+   OutputPin_Connect,
+   OutputPin_ReceiveConnection,
+   OutputPin_Disconnect,
+   IPinImpl_ConnectedTo,
+   IPinImpl_ConnectionMediaType,
+   IPinImpl_QueryPinInfo,
+   IPinImpl_QueryDirection,
+   IPinImpl_QueryId,
+   IPinImpl_QueryAccept,
+   VfwPin_EnumMediaTypes,
+   VfwPin_QueryInternalConnections,
+   VfwPin_EndOfStream, 
+   VfwPin_BeginFlush,
+   VfwPin_EndFlush,
+   VfwPin_NewSegment
+};  
+
--- /dev/null	2005-05-20 14:44:40.262390264 +0200
+++ capture.h	2005-05-21 01:12:49.000000000 +0200
@@ -0,0 +1,52 @@
+/* DirectShow private capture header (QCAP.DLL)
+ *
+ * Copyright 2005 Maarten Lankhorst
+ *
+ * This file contains the (internal) driver registration functions,
+ * driver enumeration APIs and DirectDraw creation functions.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef __CAPTURE_H__
+#define __CAPTURE_H__
+
+typedef HRESULT (* Video_Destroy)(void *pBox);
+typedef HRESULT (* Video_SetMediaType)(void *pBox, AM_MEDIA_TYPE * mT);
+typedef HRESULT (* Video_GetMediaType)(void *pBox, AM_MEDIA_TYPE ** mT);
+typedef HRESULT (* Video_GetPropRange)(void *pBox, long Property, long *pMin, long *pMax, long *pSteppingDelta, long *pDefault, long *pCapsFlags);
+typedef HRESULT (* Video_GetProp)(void *pBox, long Property, long *lValue, long *Flags);
+typedef HRESULT (* Video_SetProp)(void *pBox, long Property, long lValue, long Flags);
+typedef HRESULT (* Video_Control)(void *pBox, FILTER_STATE *state);
+
+typedef struct capturefunctions {
+   Video_Destroy Destroy;
+   Video_SetMediaType SetFormat;
+   Video_GetMediaType GetFormat;
+   Video_GetPropRange GetPropRange;
+   Video_GetProp Get_Prop;
+   Video_SetProp Set_Prop;
+   Video_Control Run, Pause, Stop;
+   void *pMine;
+} Capture;
+
+typedef HRESULT (* Video_Init)(Capture *pBox, IPin *pOut, USHORT card);
+HRESULT V4l_Init(Capture *pBox, IPin *pOut, USHORT card);
+
+#define INVOKE(from, func, para...) from->func(from->pMine, para)
+#define INVOKENP(from, func) from->func(from->pMine)
+
+#endif /* __CAPTURE_H__ */
+
--- qcap_main.c	2005-05-18 17:31:24.000000000 +0200
+++ qcap_main.c	2005-05-18 17:59:49.000000000 +0200
@@ -89,12 +89,12 @@
         &CLSID_AVICompressor, 
         QCAP_createAVICompressor,
         NULL
-    },{
+    },*/{
         wVFWCaptFilter,
-        &CLSID_VFWCaptureFilter,
+        &CLSID_VfwCapture,
         QCAP_createVFWCaptureFilter,
         NULL
-    },{
+    },/*{
         wVFWCaptFilterProp,
         &CLSID_VFWCaptureFilterPropertyPage,
         QCAP_createVFWCaptureFilterPropertyPage,
--- qcap_main.h	2005-05-14 13:03:44.000000000 +0200
+++ qcap_main.h	2005-05-17 20:35:34.000000000 +0200
@@ -56,4 +56,6 @@
 BOOL CompareMediaTypes(const AM_MEDIA_TYPE * pmt1, const AM_MEDIA_TYPE * pmt2, BOOL bWildcards); 
 void dump_AM_MEDIA_TYPE(const AM_MEDIA_TYPE * pmt);
 
+#define ICOM_THIS_MULTI(impl,field,iface) impl* const This=(impl*)((char*)(iface) - offsetof(impl,field))
+
 #endif /* _QCAP_MAIN_H_DEFINED */


More information about the wine-patches mailing list