Implemented VfwCapture interface.
This commit is contained in:
parent
bd78de791d
commit
5d16ab67f9
|
@ -14,6 +14,7 @@ C_SRCS = \
|
|||
enumpins.c \
|
||||
pin.c \
|
||||
qcap_main.c \
|
||||
vfwcapture.c \
|
||||
yuv.c
|
||||
|
||||
RC_SRCS = version.rc
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
/* 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 __QCAP_CAPTURE_H__
|
||||
#define __QCAP_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 /* __QCAP_CAPTURE_H__ */
|
|
@ -89,12 +89,12 @@ static CFactoryTemplate const g_cTemplates[] = {
|
|||
&CLSID_AVICompressor,
|
||||
QCAP_createAVICompressor,
|
||||
NULL
|
||||
},{
|
||||
},*/{
|
||||
wVFWCaptFilter,
|
||||
&CLSID_VFWCaptureFilter,
|
||||
&CLSID_VfwCapture,
|
||||
QCAP_createVFWCaptureFilter,
|
||||
NULL
|
||||
},{
|
||||
},/*{
|
||||
wVFWCaptFilterProp,
|
||||
&CLSID_VFWCaptureFilterPropertyPage,
|
||||
QCAP_createVFWCaptureFilterPropertyPage,
|
||||
|
|
|
@ -0,0 +1,914 @@
|
|||
/* 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
|
||||
*
|
||||
*/
|
||||
|
||||
#define NONAMELESSSTRUCT
|
||||
#define NONAMELESSUNION
|
||||
#define COBJMACROS
|
||||
|
||||
#include "config.h"
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "windef.h"
|
||||
#include "winbase.h"
|
||||
#include "wtypes.h"
|
||||
#include "wingdi.h"
|
||||
#include "winuser.h"
|
||||
#include "dshow.h"
|
||||
|
||||
#include "qcap_main.h"
|
||||
#include "wine/debug.h"
|
||||
|
||||
#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"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(qcap);
|
||||
|
||||
#define ICOM_THIS_MULTI(impl,field,iface) \
|
||||
impl* const This=(impl*)((char*)(iface) - offsetof(impl,field))
|
||||
|
||||
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 *, LPCRITICAL_SECTION, IPin ** );
|
||||
|
||||
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;
|
||||
|
||||
static const Video_Init Constructors[] =
|
||||
{
|
||||
/* V4l_Init, */
|
||||
NULL
|
||||
};
|
||||
|
||||
static HRESULT Capture_Initialise(Capture **dimi, IPin *pOut, USHORT card)
|
||||
{
|
||||
HRESULT r = E_FAIL;
|
||||
Capture *driver;
|
||||
int i;
|
||||
|
||||
TRACE("%p %p %hu\n", dimi, pOut, card);
|
||||
|
||||
driver = CoTaskMemAlloc( sizeof(Capture) );
|
||||
if (!driver)
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
for( i=0; FAILED(r) && Constructors[i]; i++ )
|
||||
r = Constructors[i]( driver, pOut, card );
|
||||
|
||||
if( SUCCEEDED(r) )
|
||||
*dimi = driver;
|
||||
else
|
||||
CoTaskMemFree( driver );
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
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) ||
|
||||
IsEqualIID(riid, &IID_IPersist) ||
|
||||
IsEqualIID(riid, &IID_IMediaFilter) ||
|
||||
IsEqualIID(riid, &IID_IBaseFilter))
|
||||
{
|
||||
*ppv = This;
|
||||
}
|
||||
else if (IsEqualIID(riid, &IID_IAMStreamConfig))
|
||||
*ppv = &(This->IAMStreamConfig_vtbl);
|
||||
else if (IsEqualIID(riid, &IID_IAMVideoProcAmp))
|
||||
*ppv = &(This->IAMVideoProcAmp_vtbl);
|
||||
else if (IsEqualIID(riid, &IID_IPersistPropertyBag))
|
||||
*ppv = &(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, "
|
||||
"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->() New refcount: %ld\n", This, refCount);
|
||||
|
||||
return refCount;
|
||||
}
|
||||
|
||||
static ULONG WINAPI VfwCapture_Release(IBaseFilter * iface)
|
||||
{
|
||||
VfwCapture *This = (VfwCapture *)iface;
|
||||
ULONG refCount = InterlockedDecrement(&This->refCount);
|
||||
|
||||
TRACE("%p->() New refcount: %ld\n", This, refCount);
|
||||
|
||||
if (!refCount)
|
||||
{
|
||||
IPinImpl *pin;
|
||||
|
||||
TRACE("destroying everything\n");
|
||||
if (This->init)
|
||||
{
|
||||
if (This->state != State_Stopped)
|
||||
INVOKE(This->myCap, Stop, &This->state);
|
||||
INVOKENP(This->myCap, Destroy);
|
||||
}
|
||||
pin = (IPinImpl*) This->pOutputPin;
|
||||
if (pin->pConnectedTo != NULL)
|
||||
{
|
||||
IPin_Disconnect(pin->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);
|
||||
|
||||
lstrcpyW(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)
|
||||
lstrcpyW(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))
|
||||
{
|
||||
IAMStreamConfig_AddRef(iface);
|
||||
*ppv = 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);
|
||||
IPinImpl *pin;
|
||||
|
||||
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);
|
||||
|
||||
pin = (IPinImpl *)This->pOutputPin;
|
||||
if (pin->pConnectedTo != NULL)
|
||||
{
|
||||
hr = IPin_QueryAccept(pin->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 && pin->pConnectedTo )
|
||||
{
|
||||
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 = iface;
|
||||
IAMVideoProcAmp_AddRef( 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);
|
||||
|
||||
return IUnknown_AddRef((IUnknown *)This);
|
||||
}
|
||||
|
||||
static ULONG WINAPI AMVideoProcAmp_Release(IAMVideoProcAmp * iface)
|
||||
{
|
||||
ICOM_THIS_MULTI(VfwCapture, IAMVideoProcAmp_vtbl, iface);
|
||||
|
||||
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 )
|
||||
{
|
||||
if (IsEqualIID(riid, &IID_IUnknown) ||
|
||||
IsEqualIID(riid, &IID_IPersist) ||
|
||||
IsEqualIID(riid, &IID_IPersistPropertyBag))
|
||||
{
|
||||
IPersistPropertyBag_AddRef(iface);
|
||||
*ppv = iface;
|
||||
return S_OK;
|
||||
}
|
||||
if (IsEqualIID(riid, &IID_IBaseFilter))
|
||||
{
|
||||
/* FIXME: native devenum asks for IBaseFilter, should we return it? */
|
||||
IPersistPropertyBag_AddRef(iface);
|
||||
*ppv = iface;
|
||||
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};
|
||||
|
||||
TRACE("%p/%p-> (%p, %p)\n", iface, This, pPropBag, pErrorLog);
|
||||
|
||||
V_VT(&var) = VT_I4;
|
||||
hr = IPropertyBag_Read(pPropBag, (LPCOLESTR)VFWIndex, &var, pErrorLog);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
VfwPinImpl *pin;
|
||||
|
||||
hr = Capture_Initialise(&This->myCap, This->pOutputPin,
|
||||
(USHORT)var.__VARIANT_NAME_1.__VARIANT_NAME_2.__VARIANT_NAME_3.ulVal);
|
||||
pin = (VfwPinImpl *)This->pOutputPin;
|
||||
pin->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;
|
||||
IKsPropertySet_AddRef( 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 )
|
||||
{
|
||||
LPGUID pGuid;
|
||||
|
||||
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;
|
||||
pGuid = pPropData;
|
||||
*pGuid = PIN_CATEGORY_PREVIEW;
|
||||
FIXME("() Not adding a pin with PIN_CATEGORY_CAPTURE\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 )
|
||||
{
|
||||
static const WCHAR wszOutputPinName[] = { 'O','u','t','p','u','t',0 };
|
||||
ALLOCATOR_PROPERTIES ap;
|
||||
VfwPinImpl * pPinImpl;
|
||||
PIN_INFO piOutput;
|
||||
HRESULT hr;
|
||||
|
||||
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;
|
||||
lstrcpyW(piOutput.achName, wszOutputPinName);
|
||||
ObjectRefCount(TRUE);
|
||||
|
||||
hr = OutputPin_Init(&piOutput, &ap, pBaseFilter, NULL, pCritSec, &pPinImpl->pin);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
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) || 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)->(%s, %s, %e)\n", iface, wine_dbgstr_longlong(tStart),
|
||||
wine_dbgstr_longlong(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
|
||||
};
|
Loading…
Reference in New Issue