[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, &ROPSETID_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