|  | /* | 
|  | * Null Renderer (Promiscuous, not rendering anything at all!) | 
|  | * | 
|  | * Copyright 2004 Christian Costa | 
|  | * Copyright 2008 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA | 
|  | */ | 
|  |  | 
|  | #include "config.h" | 
|  |  | 
|  | #define NONAMELESSSTRUCT | 
|  | #define NONAMELESSUNION | 
|  | #include "quartz_private.h" | 
|  | #include "control_private.h" | 
|  | #include "pin.h" | 
|  |  | 
|  | #include "uuids.h" | 
|  | #include "vfwmsgs.h" | 
|  | #include "amvideo.h" | 
|  | #include "windef.h" | 
|  | #include "winbase.h" | 
|  | #include "dshow.h" | 
|  | #include "evcode.h" | 
|  | #include "strmif.h" | 
|  | #include "ddraw.h" | 
|  |  | 
|  | #include "wine/unicode.h" | 
|  | #include "wine/debug.h" | 
|  |  | 
|  | WINE_DEFAULT_DEBUG_CHANNEL(quartz); | 
|  |  | 
|  | static const WCHAR wcsInputPinName[] = {'i','n','p','u','t',' ','p','i','n',0}; | 
|  | static const WCHAR wcsAltInputPinName[] = {'I','n',0}; | 
|  |  | 
|  | static const IBaseFilterVtbl NullRenderer_Vtbl; | 
|  | static const IUnknownVtbl IInner_VTable; | 
|  | static const IPinVtbl NullRenderer_InputPin_Vtbl; | 
|  | static const IAMFilterMiscFlagsVtbl IAMFilterMiscFlags_Vtbl; | 
|  |  | 
|  | typedef struct NullRendererImpl | 
|  | { | 
|  | BaseFilter filter; | 
|  | const IUnknownVtbl * IInner_vtbl; | 
|  | const IAMFilterMiscFlagsVtbl *IAMFilterMiscFlags_vtbl; | 
|  | IUnknown *seekthru_unk; | 
|  |  | 
|  | BaseInputPin *pInputPin; | 
|  | IUnknown * pUnkOuter; | 
|  | BOOL bUnkOuterValid; | 
|  | BOOL bAggregatable; | 
|  | } NullRendererImpl; | 
|  |  | 
|  | static HRESULT WINAPI NullRenderer_Receive(BaseInputPin *pin, IMediaSample * pSample) | 
|  | { | 
|  | NullRendererImpl *This = ((NullRendererImpl*)pin->pin.pinInfo.pFilter); | 
|  | HRESULT hr = S_OK; | 
|  | REFERENCE_TIME start, stop; | 
|  |  | 
|  | TRACE("%p %p\n", pin, pSample); | 
|  |  | 
|  | if (SUCCEEDED(IMediaSample_GetMediaTime(pSample, &start, &stop))) | 
|  | MediaSeekingPassThru_RegisterMediaTime(This->seekthru_unk, start); | 
|  | EnterCriticalSection(&This->filter.csFilter); | 
|  | if (This->pInputPin->flushing || This->pInputPin->end_of_stream) | 
|  | hr = S_FALSE; | 
|  | LeaveCriticalSection(&This->filter.csFilter); | 
|  |  | 
|  | return hr; | 
|  | } | 
|  |  | 
|  | static HRESULT WINAPI NullRenderer_CheckMediaType(BasePin *iface, const AM_MEDIA_TYPE * pmt) | 
|  | { | 
|  | TRACE("Not a stub!\n"); | 
|  | return S_OK; | 
|  | } | 
|  |  | 
|  | static IPin* WINAPI NullRenderer_GetPin(BaseFilter *iface, int pos) | 
|  | { | 
|  | NullRendererImpl *This = (NullRendererImpl *)iface; | 
|  |  | 
|  | if (pos >= 1 || pos < 0) | 
|  | return NULL; | 
|  |  | 
|  | IPin_AddRef((IPin *)This->pInputPin); | 
|  | return (IPin *)This->pInputPin; | 
|  | } | 
|  |  | 
|  | static LONG WINAPI NullRenderer_GetPinCount(BaseFilter *iface) | 
|  | { | 
|  | return 1; | 
|  | } | 
|  |  | 
|  | static const BaseFilterFuncTable BaseFuncTable = { | 
|  | NullRenderer_GetPin, | 
|  | NullRenderer_GetPinCount | 
|  | }; | 
|  |  | 
|  | static const  BasePinFuncTable input_BaseFuncTable = { | 
|  | NullRenderer_CheckMediaType, | 
|  | NULL, | 
|  | BasePinImpl_GetMediaTypeVersion, | 
|  | BasePinImpl_GetMediaType | 
|  | }; | 
|  |  | 
|  | static const BaseInputPinFuncTable input_BaseInputFuncTable = { | 
|  | NullRenderer_Receive | 
|  | }; | 
|  |  | 
|  |  | 
|  | HRESULT NullRenderer_create(IUnknown * pUnkOuter, LPVOID * ppv) | 
|  | { | 
|  | HRESULT hr; | 
|  | PIN_INFO piInput; | 
|  | NullRendererImpl * pNullRenderer; | 
|  |  | 
|  | TRACE("(%p, %p)\n", pUnkOuter, ppv); | 
|  |  | 
|  | *ppv = NULL; | 
|  |  | 
|  | pNullRenderer = CoTaskMemAlloc(sizeof(NullRendererImpl)); | 
|  | pNullRenderer->pUnkOuter = pUnkOuter; | 
|  | pNullRenderer->bUnkOuterValid = FALSE; | 
|  | pNullRenderer->bAggregatable = FALSE; | 
|  | pNullRenderer->IInner_vtbl = &IInner_VTable; | 
|  | pNullRenderer->IAMFilterMiscFlags_vtbl = &IAMFilterMiscFlags_Vtbl; | 
|  |  | 
|  | BaseFilter_Init(&pNullRenderer->filter, &NullRenderer_Vtbl, &CLSID_NullRenderer, (DWORD_PTR)(__FILE__ ": NullRendererImpl.csFilter"), &BaseFuncTable); | 
|  |  | 
|  | /* construct input pin */ | 
|  | piInput.dir = PINDIR_INPUT; | 
|  | piInput.pFilter = (IBaseFilter *)pNullRenderer; | 
|  | lstrcpynW(piInput.achName, wcsInputPinName, sizeof(piInput.achName) / sizeof(piInput.achName[0])); | 
|  |  | 
|  | hr = BaseInputPin_Construct(&NullRenderer_InputPin_Vtbl, &piInput, &input_BaseFuncTable, &input_BaseInputFuncTable, &pNullRenderer->filter.csFilter, NULL, (IPin **)&pNullRenderer->pInputPin); | 
|  |  | 
|  | if (SUCCEEDED(hr)) | 
|  | { | 
|  | ISeekingPassThru *passthru; | 
|  | hr = CoCreateInstance(&CLSID_SeekingPassThru, pUnkOuter ? pUnkOuter : (IUnknown*)&pNullRenderer->IInner_vtbl, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void**)&pNullRenderer->seekthru_unk); | 
|  | if (FAILED(hr)) { | 
|  | IUnknown_Release((IUnknown*)pNullRenderer); | 
|  | return hr; | 
|  | } | 
|  | IUnknown_QueryInterface(pNullRenderer->seekthru_unk, &IID_ISeekingPassThru, (void**)&passthru); | 
|  | ISeekingPassThru_Init(passthru, TRUE, (IPin*)pNullRenderer->pInputPin); | 
|  | ISeekingPassThru_Release(passthru); | 
|  | *ppv = pNullRenderer; | 
|  | } | 
|  | else | 
|  | { | 
|  | BaseFilterImpl_Release((IBaseFilter*)pNullRenderer); | 
|  | CoTaskMemFree(pNullRenderer); | 
|  | } | 
|  |  | 
|  | return hr; | 
|  | } | 
|  |  | 
|  | static HRESULT WINAPI NullRendererInner_QueryInterface(IUnknown * iface, REFIID riid, LPVOID * ppv) | 
|  | { | 
|  | ICOM_THIS_MULTI(NullRendererImpl, IInner_vtbl, iface); | 
|  | TRACE("(%p/%p)->(%s, %p)\n", This, iface, qzdebugstr_guid(riid), ppv); | 
|  |  | 
|  | if (This->bAggregatable) | 
|  | This->bUnkOuterValid = TRUE; | 
|  |  | 
|  | *ppv = NULL; | 
|  |  | 
|  | if (IsEqualIID(riid, &IID_IUnknown)) | 
|  | *ppv = &This->IInner_vtbl; | 
|  | else if (IsEqualIID(riid, &IID_IPersist)) | 
|  | *ppv = This; | 
|  | else if (IsEqualIID(riid, &IID_IMediaFilter)) | 
|  | *ppv = This; | 
|  | else if (IsEqualIID(riid, &IID_IBaseFilter)) | 
|  | *ppv = This; | 
|  | else if (IsEqualIID(riid, &IID_IMediaSeeking)) | 
|  | return IUnknown_QueryInterface(This->seekthru_unk, riid, ppv); | 
|  | else if (IsEqualIID(riid, &IID_IAMFilterMiscFlags)) | 
|  | *ppv = &This->IAMFilterMiscFlags_vtbl; | 
|  |  | 
|  | if (*ppv) | 
|  | { | 
|  | IUnknown_AddRef((IUnknown *)(*ppv)); | 
|  | return S_OK; | 
|  | } | 
|  |  | 
|  | if (!IsEqualIID(riid, &IID_IPin) && !IsEqualIID(riid, &IID_IVideoWindow)) | 
|  | FIXME("No interface for %s!\n", qzdebugstr_guid(riid)); | 
|  |  | 
|  | return E_NOINTERFACE; | 
|  | } | 
|  |  | 
|  | static ULONG WINAPI NullRendererInner_AddRef(IUnknown * iface) | 
|  | { | 
|  | ICOM_THIS_MULTI(NullRendererImpl, IInner_vtbl, iface); | 
|  | ULONG refCount = InterlockedIncrement(&This->filter.refCount); | 
|  |  | 
|  | TRACE("(%p/%p)->() AddRef from %d\n", This, iface, refCount - 1); | 
|  |  | 
|  | return refCount; | 
|  | } | 
|  |  | 
|  | static ULONG WINAPI NullRendererInner_Release(IUnknown * iface) | 
|  | { | 
|  | ICOM_THIS_MULTI(NullRendererImpl, IInner_vtbl, iface); | 
|  | ULONG refCount = InterlockedDecrement(&This->filter.refCount); | 
|  |  | 
|  | TRACE("(%p/%p)->() Release from %d\n", This, iface, refCount + 1); | 
|  |  | 
|  | if (!refCount) | 
|  | { | 
|  | IPin *pConnectedTo; | 
|  |  | 
|  | if (SUCCEEDED(IPin_ConnectedTo((IPin *)This->pInputPin, &pConnectedTo))) | 
|  | { | 
|  | IPin_Disconnect(pConnectedTo); | 
|  | IPin_Release(pConnectedTo); | 
|  | } | 
|  | IPin_Disconnect((IPin *)This->pInputPin); | 
|  | IPin_Release((IPin *)This->pInputPin); | 
|  |  | 
|  | This->filter.lpVtbl = NULL; | 
|  | if (This->seekthru_unk) | 
|  | IUnknown_Release(This->seekthru_unk); | 
|  |  | 
|  | This->filter.csFilter.DebugInfo->Spare[0] = 0; | 
|  | DeleteCriticalSection(&This->filter.csFilter); | 
|  |  | 
|  | TRACE("Destroying Null Renderer\n"); | 
|  | CoTaskMemFree(This); | 
|  | return 0; | 
|  | } | 
|  | else | 
|  | return refCount; | 
|  | } | 
|  |  | 
|  | static const IUnknownVtbl IInner_VTable = | 
|  | { | 
|  | NullRendererInner_QueryInterface, | 
|  | NullRendererInner_AddRef, | 
|  | NullRendererInner_Release | 
|  | }; | 
|  |  | 
|  | static HRESULT WINAPI NullRenderer_QueryInterface(IBaseFilter * iface, REFIID riid, LPVOID * ppv) | 
|  | { | 
|  | NullRendererImpl *This = (NullRendererImpl *)iface; | 
|  |  | 
|  | if (This->bAggregatable) | 
|  | This->bUnkOuterValid = TRUE; | 
|  |  | 
|  | if (This->pUnkOuter) | 
|  | { | 
|  | if (This->bAggregatable) | 
|  | return IUnknown_QueryInterface(This->pUnkOuter, riid, ppv); | 
|  |  | 
|  | if (IsEqualIID(riid, &IID_IUnknown)) | 
|  | { | 
|  | HRESULT hr; | 
|  |  | 
|  | IUnknown_AddRef((IUnknown *)&(This->IInner_vtbl)); | 
|  | hr = IUnknown_QueryInterface((IUnknown *)&(This->IInner_vtbl), riid, ppv); | 
|  | IUnknown_Release((IUnknown *)&(This->IInner_vtbl)); | 
|  | This->bAggregatable = TRUE; | 
|  | return hr; | 
|  | } | 
|  |  | 
|  | *ppv = NULL; | 
|  | return E_NOINTERFACE; | 
|  | } | 
|  |  | 
|  | return IUnknown_QueryInterface((IUnknown *)&(This->IInner_vtbl), riid, ppv); | 
|  | } | 
|  |  | 
|  | static ULONG WINAPI NullRenderer_AddRef(IBaseFilter * iface) | 
|  | { | 
|  | NullRendererImpl *This = (NullRendererImpl *)iface; | 
|  |  | 
|  | if (This->pUnkOuter && This->bUnkOuterValid) | 
|  | return IUnknown_AddRef(This->pUnkOuter); | 
|  | return IUnknown_AddRef((IUnknown *)&(This->IInner_vtbl)); | 
|  | } | 
|  |  | 
|  | static ULONG WINAPI NullRenderer_Release(IBaseFilter * iface) | 
|  | { | 
|  | NullRendererImpl *This = (NullRendererImpl *)iface; | 
|  |  | 
|  | if (This->pUnkOuter && This->bUnkOuterValid) | 
|  | return IUnknown_Release(This->pUnkOuter); | 
|  | return IUnknown_Release((IUnknown *)&(This->IInner_vtbl)); | 
|  | } | 
|  |  | 
|  | /** IMediaFilter methods **/ | 
|  |  | 
|  | static HRESULT WINAPI NullRenderer_Stop(IBaseFilter * iface) | 
|  | { | 
|  | NullRendererImpl *This = (NullRendererImpl *)iface; | 
|  |  | 
|  | TRACE("(%p/%p)->()\n", This, iface); | 
|  |  | 
|  | EnterCriticalSection(&This->filter.csFilter); | 
|  | { | 
|  | This->filter.state = State_Stopped; | 
|  | MediaSeekingPassThru_ResetMediaTime(This->seekthru_unk); | 
|  | } | 
|  | LeaveCriticalSection(&This->filter.csFilter); | 
|  |  | 
|  | return S_OK; | 
|  | } | 
|  |  | 
|  | static HRESULT WINAPI NullRenderer_Pause(IBaseFilter * iface) | 
|  | { | 
|  | NullRendererImpl *This = (NullRendererImpl *)iface; | 
|  |  | 
|  | TRACE("(%p/%p)->()\n", This, iface); | 
|  |  | 
|  | EnterCriticalSection(&This->filter.csFilter); | 
|  | { | 
|  | if (This->filter.state == State_Stopped) | 
|  | This->pInputPin->end_of_stream = 0; | 
|  | This->filter.state = State_Paused; | 
|  | } | 
|  | LeaveCriticalSection(&This->filter.csFilter); | 
|  |  | 
|  | return S_OK; | 
|  | } | 
|  |  | 
|  | static HRESULT WINAPI NullRenderer_Run(IBaseFilter * iface, REFERENCE_TIME tStart) | 
|  | { | 
|  | HRESULT hr = S_OK; | 
|  | NullRendererImpl *This = (NullRendererImpl *)iface; | 
|  |  | 
|  | TRACE("(%p/%p)->(%s)\n", This, iface, wine_dbgstr_longlong(tStart)); | 
|  |  | 
|  | EnterCriticalSection(&This->filter.csFilter); | 
|  | This->filter.rtStreamStart = tStart; | 
|  | if (This->filter.state == State_Running) | 
|  | goto out; | 
|  | if (This->pInputPin->pin.pConnectedTo) | 
|  | { | 
|  | This->pInputPin->end_of_stream = 0; | 
|  | } | 
|  | else if (This->filter.filterInfo.pGraph) | 
|  | { | 
|  | IMediaEventSink *pEventSink; | 
|  | hr = IFilterGraph_QueryInterface(This->filter.filterInfo.pGraph, &IID_IMediaEventSink, (LPVOID*)&pEventSink); | 
|  | if (SUCCEEDED(hr)) | 
|  | { | 
|  | hr = IMediaEventSink_Notify(pEventSink, EC_COMPLETE, S_OK, (LONG_PTR)This); | 
|  | IMediaEventSink_Release(pEventSink); | 
|  | } | 
|  | hr = S_OK; | 
|  | } | 
|  | if (SUCCEEDED(hr)) | 
|  | This->filter.state = State_Running; | 
|  | out: | 
|  | LeaveCriticalSection(&This->filter.csFilter); | 
|  |  | 
|  | return hr; | 
|  | } | 
|  |  | 
|  | /** IBaseFilter implementation **/ | 
|  |  | 
|  | static HRESULT WINAPI NullRenderer_FindPin(IBaseFilter * iface, LPCWSTR Id, IPin **ppPin) | 
|  | { | 
|  | NullRendererImpl *This = (NullRendererImpl *)iface; | 
|  |  | 
|  | TRACE("(%p/%p)->(%p,%p)\n", This, iface, debugstr_w(Id), ppPin); | 
|  |  | 
|  | if (!Id || !ppPin) | 
|  | return E_POINTER; | 
|  |  | 
|  | if (!lstrcmpiW(Id,wcsInputPinName) || !lstrcmpiW(Id,wcsAltInputPinName)) | 
|  | { | 
|  | *ppPin = (IPin *)This->pInputPin; | 
|  | IPin_AddRef(*ppPin); | 
|  | return S_OK; | 
|  | } | 
|  | *ppPin = NULL; | 
|  | return VFW_E_NOT_FOUND; | 
|  | } | 
|  |  | 
|  | static const IBaseFilterVtbl NullRenderer_Vtbl = | 
|  | { | 
|  | NullRenderer_QueryInterface, | 
|  | NullRenderer_AddRef, | 
|  | NullRenderer_Release, | 
|  | BaseFilterImpl_GetClassID, | 
|  | NullRenderer_Stop, | 
|  | NullRenderer_Pause, | 
|  | NullRenderer_Run, | 
|  | BaseFilterImpl_GetState, | 
|  | BaseFilterImpl_SetSyncSource, | 
|  | BaseFilterImpl_GetSyncSource, | 
|  | BaseFilterImpl_EnumPins, | 
|  | NullRenderer_FindPin, | 
|  | BaseFilterImpl_QueryFilterInfo, | 
|  | BaseFilterImpl_JoinFilterGraph, | 
|  | BaseFilterImpl_QueryVendorInfo | 
|  | }; | 
|  |  | 
|  | static HRESULT WINAPI NullRenderer_InputPin_EndOfStream(IPin * iface) | 
|  | { | 
|  | BaseInputPin* This = (BaseInputPin*)iface; | 
|  | IMediaEventSink* pEventSink; | 
|  | NullRendererImpl *pNull; | 
|  | IFilterGraph *graph; | 
|  | HRESULT hr = S_OK; | 
|  |  | 
|  | TRACE("(%p/%p)->()\n", This, iface); | 
|  |  | 
|  | BaseInputPinImpl_EndOfStream(iface); | 
|  | pNull = (NullRendererImpl*)This->pin.pinInfo.pFilter; | 
|  | graph = pNull->filter.filterInfo.pGraph; | 
|  | if (graph) | 
|  | { | 
|  | hr = IFilterGraph_QueryInterface(pNull->filter.filterInfo.pGraph, &IID_IMediaEventSink, (LPVOID*)&pEventSink); | 
|  | if (SUCCEEDED(hr)) | 
|  | { | 
|  | hr = IMediaEventSink_Notify(pEventSink, EC_COMPLETE, S_OK, (LONG_PTR)pNull); | 
|  | IMediaEventSink_Release(pEventSink); | 
|  | } | 
|  | } | 
|  | MediaSeekingPassThru_EOS(pNull->seekthru_unk); | 
|  |  | 
|  | return hr; | 
|  | } | 
|  |  | 
|  | static HRESULT WINAPI NullRenderer_InputPin_EndFlush(IPin * iface) | 
|  | { | 
|  | BaseInputPin* This = (BaseInputPin*)iface; | 
|  | NullRendererImpl *pNull; | 
|  | HRESULT hr = S_OK; | 
|  |  | 
|  | TRACE("(%p/%p)->()\n", This, iface); | 
|  |  | 
|  | hr = BaseInputPinImpl_EndOfStream(iface); | 
|  | pNull = (NullRendererImpl*)This->pin.pinInfo.pFilter; | 
|  | MediaSeekingPassThru_ResetMediaTime(pNull->seekthru_unk); | 
|  | return hr; | 
|  | } | 
|  |  | 
|  | static const IPinVtbl NullRenderer_InputPin_Vtbl = | 
|  | { | 
|  | BaseInputPinImpl_QueryInterface, | 
|  | BasePinImpl_AddRef, | 
|  | BaseInputPinImpl_Release, | 
|  | BaseInputPinImpl_Connect, | 
|  | BaseInputPinImpl_ReceiveConnection, | 
|  | BasePinImpl_Disconnect, | 
|  | BasePinImpl_ConnectedTo, | 
|  | BasePinImpl_ConnectionMediaType, | 
|  | BasePinImpl_QueryPinInfo, | 
|  | BasePinImpl_QueryDirection, | 
|  | BasePinImpl_QueryId, | 
|  | BaseInputPinImpl_QueryAccept, | 
|  | BasePinImpl_EnumMediaTypes, | 
|  | BasePinImpl_QueryInternalConnections, | 
|  | NullRenderer_InputPin_EndOfStream, | 
|  | BaseInputPinImpl_BeginFlush, | 
|  | NullRenderer_InputPin_EndFlush, | 
|  | BaseInputPinImpl_NewSegment | 
|  | }; | 
|  |  | 
|  | static NullRendererImpl *from_IAMFilterMiscFlags(IAMFilterMiscFlags *iface) { | 
|  | return (NullRendererImpl*)((char*)iface - offsetof(NullRendererImpl, IAMFilterMiscFlags_vtbl)); | 
|  | } | 
|  |  | 
|  | static HRESULT WINAPI AMFilterMiscFlags_QueryInterface(IAMFilterMiscFlags *iface, REFIID riid, void **ppv) { | 
|  | NullRendererImpl *This = from_IAMFilterMiscFlags(iface); | 
|  | return IUnknown_QueryInterface((IUnknown*)This, riid, ppv); | 
|  | } | 
|  |  | 
|  | static ULONG WINAPI AMFilterMiscFlags_AddRef(IAMFilterMiscFlags *iface) { | 
|  | NullRendererImpl *This = from_IAMFilterMiscFlags(iface); | 
|  | return IUnknown_AddRef((IUnknown*)This); | 
|  | } | 
|  |  | 
|  | static ULONG WINAPI AMFilterMiscFlags_Release(IAMFilterMiscFlags *iface) { | 
|  | NullRendererImpl *This = from_IAMFilterMiscFlags(iface); | 
|  | return IUnknown_Release((IUnknown*)This); | 
|  | } | 
|  |  | 
|  | static ULONG WINAPI AMFilterMiscFlags_GetMiscFlags(IAMFilterMiscFlags *iface) { | 
|  | return AM_FILTER_MISC_FLAGS_IS_RENDERER; | 
|  | } | 
|  |  | 
|  | static const IAMFilterMiscFlagsVtbl IAMFilterMiscFlags_Vtbl = { | 
|  | AMFilterMiscFlags_QueryInterface, | 
|  | AMFilterMiscFlags_AddRef, | 
|  | AMFilterMiscFlags_Release, | 
|  | AMFilterMiscFlags_GetMiscFlags | 
|  | }; |