[QCAP] VfwCapture implementation
Maarten Lankhorst
m.b.lankhorst at gmail.com
Thu May 19 06:10:38 CDT 2005
Resend, this time without the YUV stuff, I can't make it any smaller, sorry
-------------- next part --------------
Index: qcap_main.h
===================================================================
RCS file: /home/wine/wine/dlls/qcap/qcap_main.h,v
retrieving revision 1.2
diff -u -p -r1.2 qcap_main.h
--- qcap_main.h 14 May 2005 11:03:44 -0000 1.2
+++ qcap_main.h 18 May 2005 14:25:24 -0000
@@ -56,4 +56,6 @@ void DeleteMediaType(AM_MEDIA_TYPE * pmt
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 */
Index: qcap_main.c
===================================================================
RCS file: /home/wine/wine/dlls/qcap/qcap_main.c,v
retrieving revision 1.5
diff -u -p -r1.5 qcap_main.c
--- qcap_main.c 7 May 2005 18:18:39 -0000 1.5
+++ qcap_main.c 18 May 2005 14:25:25 -0000
@@ -89,12 +89,12 @@ static CFactoryTemplate const g_cTemplat
&CLSID_AVICompressor,
QCAP_createAVICompressor,
NULL
- },{
+ },*/{
wVFWCaptFilter,
- &CLSID_VFWCaptureFilter,
+ &CLSID_VfwCapture,
QCAP_createVFWCaptureFilter,
NULL
- },{
+ },/*{
wVFWCaptFilterProp,
&CLSID_VFWCaptureFilterPropertyPage,
QCAP_createVFWCaptureFilterPropertyPage,
--- /dev/null 2005-05-18 02:16:30.376227688 +0200
+++ null.c 2005-05-18 16:24:34.000000000 +0200
@@ -0,0 +1,101 @@
+/* DirectShow capture services (QCAP.DLL)
+ *
+ * Copyright 2005 Maarten Lankhorst
+ *
+ * This file contains the part of the vfw capture interface that
+ * does the actual capturing stuff required for capturing
+ * and setting/getting media format..
+ *
+ * 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
+ *
+ * Why on earth am I writing a copyright notice for a NULL renderer???
+ */
+
+#include "config.h"
+#if 1 /*ifndef HAVE_LINUX_VIDEODEV_H */
+
+#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 "pin.h"
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(qcap);
+
+HRESULT Capture_Initialise(void ** pointer, IPin *pOut, USHORT card)
+{
+/* ERR("Sorry, you have an EVALUATION version of wine.\n"
+ "\tOnce you bought yours at http://www.codeweavers.com you\n"
+ "\tcan use webcam support, for 5 euro per minute\n"); */
+ ERR("No DirectShow Video for Wine Capture support compiled\n");
+ return E_FAIL;
+}
+
+HRESULT Capture_GetMediaType(void * pBox, AM_MEDIA_TYPE ** mT)
+{
+ return E_FAIL;
+}
+
+HRESULT Capture_SetMediaType(void * pBox, AM_MEDIA_TYPE * mT)
+{
+ return E_FAIL;
+}
+
+HRESULT Capture_GetPropRange(void * pBox, long Property, long *pMin, long *pMax, long *pSteppingDelta, long *pDefault, long *pCapsFlags)
+{
+ return E_FAIL;
+}
+
+HRESULT Capture_GetProp(void *pBox, long Property, long *lValue, long *Flags)
+{
+ return E_FAIL;
+}
+
+HRESULT Capture_SetProp(void *pBox, long Property, long lValue, long Flags)
+{
+ return E_FAIL;
+}
+
+HRESULT Capture_Run(void * pBox, FILTER_STATE *state)
+{
+ return E_FAIL;
+}
+
+HRESULT Capture_Stop(void * pBox, FILTER_STATE *state)
+{
+ return E_FAIL;
+}
+
+HRESULT Capture_Pause(void * pBox, FILTER_STATE *state)
+{
+ return E_FAIL;
+}
+
+HRESULT Capture_Destroy(void * pBox, BOOL destroyall)
+{
+ return E_FAIL;
+}
+
+#endif
+
--- /dev/null 2005-05-18 02:16:30.376227688 +0200
+++ vfwcapture.c 2005-05-18 11:33:19.000000000 +0200
@@ -0,0 +1,790 @@
+/* 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
+ *
+ * Ugh, Now I can't tell what's worser, COM or the bugs in filtergraph, pins, enummedia and devenum..
+ * This file is only compiled if we found a working videodev.h
+ * If it doesn't exist, null.c will be compiled instead
+ */
+
+#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"
+
+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;
+ LPVOID myCap;
+ ULONG refCount;
+ FILTER_INFO filterInfo;
+ FILTER_STATE state;
+ CRITICAL_SECTION csFilter;
+
+ IPin * pOutputPin;
+} VfwCapture;
+
+/* VfwPin implementation */
+typedef struct VfwPinImpl
+{
+ OutputPin pin;
+
+ LPVOID 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)
+ Capture_Stop(This->myCap, &This->state);
+ Capture_Destroy(This->myCap, TRUE);
+ }
+ 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 Capture_Stop(This->myCap, &This->state);
+}
+
+static HRESULT WINAPI VfwCapture_Pause(IBaseFilter * iface)
+{
+ VfwCapture *This = (VfwCapture *)iface;
+ TRACE("()\n");
+ return Capture_Pause(This->myCap, &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 Capture_Run(This->myCap, &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 = Capture_SetMediaType(This->myCap, 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 Capture_GetMediaType(This->myCap, 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 Capture_GetPropRange(This->myCap, 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 Capture_SetProp(This->myCap, Property, lValue, Flags);
+}
+
+static HRESULT WINAPI AMVideoProcAmp_Get(IAMVideoProcAmp * iface, long Property, long *lValue, long *Flags)
+{
+ ICOM_THIS_MULTI(VfwCapture, IAMVideoProcAmp_vtbl, iface);
+ return Capture_GetProp(This->myCap, 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 for props is overridden by the Capture_Run when committing*/
+ 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 = Capture_GetMediaType(This->myCap, &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-18 02:16:30.376227688 +0200
+++ capture.h 2005-05-17 00:13:16.000000000 +0200
@@ -0,0 +1,45 @@
+/* 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__
+
+/* Initialisation */
+HRESULT Capture_Initialise(void ** pointer, IPin *pOut, USHORT card);
+
+/* Control */
+HRESULT Capture_GetMediaType(void * pBox, AM_MEDIA_TYPE ** mT);
+HRESULT Capture_SetMediaType(void * pBox, AM_MEDIA_TYPE * mT);
+HRESULT Capture_GetPropRange(void * pBox, long Property, long *pMin, long *pMax, long *pSteppingDelta, long *pDefault, long *pCapsFlags);
+HRESULT Capture_GetProp(void *pBox, long Property, long *lValue, long *Flags);
+HRESULT Capture_SetProp(void *pBox, long Property, long lValue, long Flags);
+
+/* Stream control */
+HRESULT Capture_Run(void * pBox, FILTER_STATE *state);
+HRESULT Capture_Stop(void * pBox, FILTER_STATE *state);
+HRESULT Capture_Pause(void * pBox, FILTER_STATE *state);
+
+/* Destruction */
+HRESULT Capture_Destroy(void * pBox, BOOL destroyall);
+
+#endif /* __CAPTURE_H__ */
+
--- Makefile.in 2005-05-18 22:35:29.000000000 +0200
+++ Makefile.in 2005-05-18 18:02:25.000000000 +0200
@@ -12,8 +12,10 @@
dllsetup.c \
enummedia.c \
enumpins.c \
+ null.c \
pin.c \
- qcap_main.c
+ qcap_main.c \
+ vfwcapture.c
RC_SRCS = version.rc
More information about the wine-patches
mailing list