[D3D8][D3D9][DDRAW][DXGI][QEDIT][WINED3D]
[reactos.git] / reactos / dll / directx / wine / qedit / samplegrabber.c
index edae0ae..3af5c3c 100644 (file)
 
 #include "qedit_private.h"
 
+#include <wine/strmbase.h>
+
 static const WCHAR vendor_name[] = { 'W', 'i', 'n', 'e', 0 };
 static const WCHAR pin_in_name[] = { 'I', 'n', 0 };
 static const WCHAR pin_out_name[] = { 'O', 'u', 't', 0 };
 
-static IEnumPins *pinsenum_create(IBaseFilter *filter, IPin **pins, ULONG pinCount);
 static IEnumMediaTypes *mediaenum_create(const AM_MEDIA_TYPE *mtype);
 
-/* Fixed pins enumerator, holds filter referenced */
-typedef struct _PE_Impl {
-    IEnumPins pe;
-    IBaseFilter *filter;
-    LONG refCount;
-    ULONG numPins;
-    ULONG index;
-    IPin *pins[0];
-} PE_Impl;
-
-
-/* IEnumPins interface implementation */
-
-/* IUnknown */
-static ULONG WINAPI
-Fixed_IEnumPins_AddRef(IEnumPins *iface)
-{
-    PE_Impl *This = (PE_Impl *)iface;
-    ULONG refCount = InterlockedIncrement(&This->refCount);
-    TRACE("(%p) new ref = %u\n", This, refCount);
-    return refCount;
-}
-
-/* IUnknown */
-static ULONG WINAPI
-Fixed_IEnumPins_Release(IEnumPins *iface)
-{
-    PE_Impl *This = (PE_Impl *)iface;
-    ULONG refCount = InterlockedDecrement(&This->refCount);
-    TRACE("(%p) new ref = %u\n", This, refCount);
-    if (refCount == 0)
-    {
-        IBaseFilter_Release(This->filter);
-        CoTaskMemFree(This);
-        return 0;
-    }
-    return refCount;
-}
-
-/* IUnknown */
-static HRESULT WINAPI
-Fixed_IEnumPins_QueryInterface(IEnumPins *iface, REFIID riid, void **ppvObject)
-{
-    PE_Impl *This = (PE_Impl *)iface;
-    TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObject);
-
-    if (IsEqualIID(riid, &IID_IUnknown) ||
-        IsEqualIID(riid, &IID_IEnumPins)) {
-       Fixed_IEnumPins_AddRef(iface);
-        *ppvObject = This->pins;
-        return S_OK;
-    }
-    *ppvObject = NULL;
-    WARN("(%p, %s,%p): not found\n", This, debugstr_guid(riid), ppvObject);
-    return E_NOINTERFACE;
-}
-
-/* IEnumPins */
-static HRESULT WINAPI
-Fixed_IEnumPins_Next(IEnumPins *iface, ULONG nPins, IPin **pins, ULONG *fetched)
-{
-    PE_Impl *This = (PE_Impl *)iface;
-    ULONG count = 0;
-    TRACE("(%p)->(%u, %p, %p) index = %u\n", This, nPins, pins, fetched, This->index);
-    if (!nPins)
-        return E_INVALIDARG;
-    if (!pins || ((nPins != 1) && !fetched))
-        return E_POINTER;
-    while ((count < nPins) && (This->index < This->numPins)) {
-        IPin *pin = This->pins[This->index++];
-        IPin_AddRef(pin);
-        pins[count++] = pin;
-    }
-    if (fetched)
-        *fetched = count;
-    return (count == nPins) ? S_OK : S_FALSE;
-}
-
-/* IEnumPins */
-static HRESULT WINAPI
-Fixed_IEnumPins_Skip(IEnumPins *iface, ULONG nPins)
-{
-    PE_Impl *This = (PE_Impl *)iface;
-    TRACE("(%p)->(%u) index = %u\n", This, nPins, This->index);
-    nPins += This->index;
-    if (nPins >= This->numPins) {
-        This->index = This->numPins;
-        return S_FALSE;
-    }
-    This->index = nPins;
-    return S_OK;
-}
-
-/* IEnumPins */
-static HRESULT WINAPI
-Fixed_IEnumPins_Reset(IEnumPins *iface)
-{
-    PE_Impl *This = (PE_Impl *)iface;
-    TRACE("(%p)->() index = %u\n", This, This->index);
-    This->index = 0;
-    return S_OK;
-}
-
-/* IEnumPins */
-static HRESULT WINAPI
-Fixed_IEnumPins_Clone(IEnumPins *iface, IEnumPins **pins)
-{
-    PE_Impl *This = (PE_Impl *)iface;
-    TRACE("(%p)->(%p) index = %u\n", This, pins, This->index);
-    if (!pins)
-        return E_POINTER;
-    *pins = pinsenum_create(This->filter, This->pins, This->numPins);
-    if (!*pins)
-        return E_OUTOFMEMORY;
-    ((PE_Impl *)*pins)->index = This->index;
-    return S_OK;
-}
-
-
-/* Virtual tables and constructor */
-
-static const IEnumPinsVtbl IEnumPins_VTable =
-{
-    Fixed_IEnumPins_QueryInterface,
-    Fixed_IEnumPins_AddRef,
-    Fixed_IEnumPins_Release,
-    Fixed_IEnumPins_Next,
-    Fixed_IEnumPins_Skip,
-    Fixed_IEnumPins_Reset,
-    Fixed_IEnumPins_Clone,
-};
-
-static IEnumPins *pinsenum_create(IBaseFilter *filter, IPin **pins, ULONG pinCount)
-{
-    ULONG len = sizeof(PE_Impl) + (pinCount * sizeof(IPin *));
-    PE_Impl *obj = CoTaskMemAlloc(len);
-    if (obj) {
-        ULONG i;
-        ZeroMemory(obj, len);
-        obj->pe.lpVtbl = &IEnumPins_VTable;
-        obj->refCount = 1;
-        obj->filter = filter;
-        obj->numPins = pinCount;
-        obj->index = 0;
-        for (i=0; i<pinCount; i++)
-            obj->pins[i] = pins[i];
-        IBaseFilter_AddRef(filter);
-    }
-    return &obj->pe;
-}
-
-
 /* Single media type enumerator */
 typedef struct _ME_Impl {
     IEnumMediaTypes me;
@@ -353,22 +202,16 @@ static inline SG_Pin *impl_from_IPin(IPin *iface)
 /* Sample Grabber filter implementation */
 typedef struct _SG_Impl {
     IUnknown IUnknown_inner;
-    IBaseFilter IBaseFilter_iface;
+    BaseFilter filter;
     ISampleGrabber ISampleGrabber_iface;
-    IMemInputPin IMemInputPin_iface;
     /* IMediaSeeking and IMediaPosition are implemented by ISeekingPassThru */
     IUnknown* seekthru_unk;
-    /* TODO: IQualityControl */
     IUnknown *outer_unk;
-    LONG ref;
-    CRITICAL_SECTION critSect;
-    FILTER_INFO info;
-    FILTER_STATE state;
     AM_MEDIA_TYPE mtype;
     SG_Pin pin_in;
     SG_Pin pin_out;
+    IMemInputPin IMemInputPin_iface;
     IMemAllocator *allocator;
-    IReferenceClock *refClock;
     IMemInputPin *memOutput;
     ISampleGrabberCB *grabberIface;
     LONG grabberMethod;
@@ -388,9 +231,14 @@ static inline SG_Impl *impl_from_IUnknown(IUnknown *iface)
     return CONTAINING_RECORD(iface, SG_Impl, IUnknown_inner);
 }
 
+static inline SG_Impl *impl_from_BaseFilter(BaseFilter *iface)
+{
+    return CONTAINING_RECORD(iface, SG_Impl, filter);
+}
+
 static inline SG_Impl *impl_from_IBaseFilter(IBaseFilter *iface)
 {
-    return CONTAINING_RECORD(iface, SG_Impl, IBaseFilter_iface);
+    return CONTAINING_RECORD(iface, SG_Impl, filter.IBaseFilter_iface);
 }
 
 static inline SG_Impl *impl_from_ISampleGrabber(ISampleGrabber *iface)
@@ -408,12 +256,10 @@ static inline SG_Impl *impl_from_IMemInputPin(IMemInputPin *iface)
 static void SampleGrabber_cleanup(SG_Impl *This)
 {
     TRACE("(%p)\n", This);
-    if (This->info.pGraph)
-       WARN("(%p) still joined to filter graph %p\n", This, This->info.pGraph);
+    if (This->filter.filterInfo.pGraph)
+        WARN("(%p) still joined to filter graph %p\n", This, This->filter.filterInfo.pGraph);
     if (This->allocator)
         IMemAllocator_Release(This->allocator);
-    if (This->refClock)
-       IReferenceClock_Release(This->refClock);
     if (This->memOutput)
         IMemInputPin_Release(This->memOutput);
     if (This->grabberIface)
@@ -424,8 +270,6 @@ static void SampleGrabber_cleanup(SG_Impl *This)
         CoTaskMemFree(This->bufferData);
     if(This->seekthru_unk)
         IUnknown_Release(This->seekthru_unk);
-    This->critSect.DebugInfo->Spare[0] = 0;
-    DeleteCriticalSection(&This->critSect);
 }
 
 /* SampleGrabber inner IUnknown */
@@ -440,17 +284,13 @@ static HRESULT WINAPI SampleGrabber_QueryInterface(IUnknown *iface, REFIID riid,
         *ppv = &This->IUnknown_inner;
     else if (IsEqualIID(riid, &IID_IPersist) || IsEqualIID(riid, &IID_IMediaFilter) ||
         IsEqualIID(riid, &IID_IBaseFilter))
-        *ppv = &This->IBaseFilter_iface;
+        *ppv = &This->filter.IBaseFilter_iface;
     else if (IsEqualIID(riid, &IID_ISampleGrabber))
         *ppv = &This->ISampleGrabber_iface;
-    else if (IsEqualIID(riid, &IID_IMemInputPin))
-        *ppv = &This->IMemInputPin_iface;
     else if (IsEqualIID(riid, &IID_IMediaPosition))
         return IUnknown_QueryInterface(This->seekthru_unk, riid, ppv);
     else if (IsEqualIID(riid, &IID_IMediaSeeking))
         return IUnknown_QueryInterface(This->seekthru_unk, riid, ppv);
-    else if (IsEqualIID(riid, &IID_IQualityControl))
-        FIXME("IQualityControl not implemented\n");
     else
         WARN("(%p, %s,%p): not found\n", This, debugstr_guid(riid), ppv);
 
@@ -464,9 +304,9 @@ static HRESULT WINAPI SampleGrabber_QueryInterface(IUnknown *iface, REFIID riid,
 static ULONG WINAPI SampleGrabber_AddRef(IUnknown *iface)
 {
     SG_Impl *This = impl_from_IUnknown(iface);
-    ULONG ref = InterlockedIncrement(&This->ref);
+    ULONG ref = BaseFilterImpl_AddRef(&This->filter.IBaseFilter_iface);
 
-    TRACE("(%p) new ref = %u\n", This, ref);
+    TRACE("(%p) ref=%d\n", This, ref);
 
     return ref;
 }
@@ -474,9 +314,9 @@ static ULONG WINAPI SampleGrabber_AddRef(IUnknown *iface)
 static ULONG WINAPI SampleGrabber_Release(IUnknown *iface)
 {
     SG_Impl *This = impl_from_IUnknown(iface);
-    ULONG ref = InterlockedDecrement(&This->ref);
+    ULONG ref = BaseFilterImpl_Release(&This->filter.IBaseFilter_iface);
 
-    TRACE("(%p) new ref = %u\n", This, ref);
+    TRACE("(%p) ref=%d\n", This, ref);
 
     if (ref == 0)
     {
@@ -494,6 +334,32 @@ static const IUnknownVtbl samplegrabber_vtbl =
     SampleGrabber_Release,
 };
 
+static IPin *WINAPI SampleGrabber_GetPin(BaseFilter *iface, int pos)
+{
+    SG_Impl *This = impl_from_BaseFilter(iface);
+    IPin *pin;
+
+    if (pos == 0)
+        pin = &This->pin_in.IPin_iface;
+    else if (pos == 1)
+        pin = &This->pin_out.IPin_iface;
+    else
+        return NULL;
+
+    IPin_AddRef(pin);
+    return pin;
+}
+
+static LONG WINAPI SampleGrabber_GetPinCount(BaseFilter *iface)
+{
+    return 2;
+}
+
+static const BaseFilterFuncTable basefunc_vtbl = {
+    SampleGrabber_GetPin,
+    SampleGrabber_GetPinCount
+};
+
 /* Helper that buffers data and/or calls installed sample callbacks */
 static void SampleGrabber_callback(SG_Impl *This, IMediaSample *sample)
 {
@@ -505,7 +371,7 @@ static void SampleGrabber_callback(SG_Impl *This, IMediaSample *sample)
         if (size >= 0 && SUCCEEDED(IMediaSample_GetPointer(sample, &data))) {
             if (!data)
                 size = 0;
-            EnterCriticalSection(&This->critSect);
+            EnterCriticalSection(&This->filter.csFilter);
             if (This->bufferLen != size) {
                 if (This->bufferData)
                     CoTaskMemFree(This->bufferData);
@@ -514,7 +380,7 @@ static void SampleGrabber_callback(SG_Impl *This, IMediaSample *sample)
             }
             if (size)
                 CopyMemory(This->bufferData, data, size);
-            LeaveCriticalSection(&This->critSect);
+            LeaveCriticalSection(&This->filter.csFilter);
         }
     }
     if (!This->grabberIface)
@@ -580,24 +446,13 @@ SampleGrabber_IBaseFilter_Release(IBaseFilter *iface)
     return IUnknown_Release(This->outer_unk);
 }
 
-/* IPersist */
-static HRESULT WINAPI
-SampleGrabber_IBaseFilter_GetClassID(IBaseFilter *iface, CLSID *pClassID)
-{
-    TRACE("(%p)\n", pClassID);
-    if (!pClassID)
-        return E_POINTER;
-    *pClassID = CLSID_SampleGrabber;
-    return S_OK;
-}
-
 /* IMediaFilter */
 static HRESULT WINAPI
 SampleGrabber_IBaseFilter_Stop(IBaseFilter *iface)
 {
     SG_Impl *This = impl_from_IBaseFilter(iface);
     TRACE("(%p)\n", This);
-    This->state = State_Stopped;
+    This->filter.state = State_Stopped;
     return S_OK;
 }
 
@@ -607,7 +462,7 @@ SampleGrabber_IBaseFilter_Pause(IBaseFilter *iface)
 {
     SG_Impl *This = impl_from_IBaseFilter(iface);
     TRACE("(%p)\n", This);
-    This->state = State_Paused;
+    This->filter.state = State_Paused;
     return S_OK;
 }
 
@@ -617,68 +472,10 @@ SampleGrabber_IBaseFilter_Run(IBaseFilter *iface, REFERENCE_TIME tStart)
 {
     SG_Impl *This = impl_from_IBaseFilter(iface);
     TRACE("(%p)\n", This);
-    This->state = State_Running;
-    return S_OK;
-}
-
-/* IMediaFilter */
-static HRESULT WINAPI
-SampleGrabber_IBaseFilter_GetState(IBaseFilter *iface, DWORD msTout, FILTER_STATE *state)
-{
-    SG_Impl *This = impl_from_IBaseFilter(iface);
-    TRACE("(%p)->(%u, %p)\n", This, msTout, state);
-    if (!state)
-        return E_POINTER;
-    *state = This->state;
-    return S_OK;
-}
-
-/* IMediaFilter */
-static HRESULT WINAPI
-SampleGrabber_IBaseFilter_SetSyncSource(IBaseFilter *iface, IReferenceClock *clock)
-{
-    SG_Impl *This = impl_from_IBaseFilter(iface);
-    TRACE("(%p)->(%p)\n", This, clock);
-    if (clock != This->refClock)
-    {
-       if (clock)
-           IReferenceClock_AddRef(clock);
-       if (This->refClock)
-           IReferenceClock_Release(This->refClock);
-       This->refClock = clock;
-    }
-    return S_OK;
-}
-
-/* IMediaFilter */
-static HRESULT WINAPI
-SampleGrabber_IBaseFilter_GetSyncSource(IBaseFilter *iface, IReferenceClock **clock)
-{
-    SG_Impl *This = impl_from_IBaseFilter(iface);
-    TRACE("(%p)->(%p)\n", This, clock);
-    if (!clock)
-        return E_POINTER;
-    if (This->refClock)
-       IReferenceClock_AddRef(This->refClock);
-    *clock = This->refClock;
+    This->filter.state = State_Running;
     return S_OK;
 }
 
-/* IBaseFilter */
-static HRESULT WINAPI
-SampleGrabber_IBaseFilter_EnumPins(IBaseFilter *iface, IEnumPins **pins)
-{
-    SG_Impl *This = impl_from_IBaseFilter(iface);
-    IPin *pin[2];
-    TRACE("(%p)->(%p)\n", This, pins);
-    if (!pins)
-        return E_POINTER;
-    pin[0] = &This->pin_in.IPin_iface;
-    pin[1] = &This->pin_out.IPin_iface;
-    *pins = pinsenum_create(iface, pin, 2);
-    return *pins ? S_OK : E_OUTOFMEMORY;
-}
-
 /* IBaseFilter */
 static HRESULT WINAPI
 SampleGrabber_IBaseFilter_FindPin(IBaseFilter *iface, LPCWSTR id, IPin **pin)
@@ -703,30 +500,17 @@ SampleGrabber_IBaseFilter_FindPin(IBaseFilter *iface, LPCWSTR id, IPin **pin)
     return VFW_E_NOT_FOUND;
 }
 
-/* IBaseFilter */
-static HRESULT WINAPI
-SampleGrabber_IBaseFilter_QueryFilterInfo(IBaseFilter *iface, FILTER_INFO *info)
-{
-    SG_Impl *This = impl_from_IBaseFilter(iface);
-    TRACE("(%p)->(%p)\n", This, info);
-    if (!info)
-        return E_POINTER;
-    if (This->info.pGraph)
-       IFilterGraph_AddRef(This->info.pGraph);
-    *info = This->info;
-    return S_OK;
-}
-
 /* IBaseFilter */
 static HRESULT WINAPI
 SampleGrabber_IBaseFilter_JoinFilterGraph(IBaseFilter *iface, IFilterGraph *graph, LPCWSTR name)
 {
     SG_Impl *This = impl_from_IBaseFilter(iface);
+
     TRACE("(%p)->(%p, %s)\n", This, graph, debugstr_w(name));
-    This->info.pGraph = graph;
-    if (name)
-       lstrcpynW(This->info.achName,name,MAX_FILTER_NAME);
+
+    BaseFilterImpl_JoinFilterGraph(iface, graph, name);
     This->oneShot = OneShot_None;
+
     return S_OK;
 }
 
@@ -828,14 +612,14 @@ SampleGrabber_ISampleGrabber_SetBufferSamples(ISampleGrabber *iface, BOOL buffer
 {
     SG_Impl *This = impl_from_ISampleGrabber(iface);
     TRACE("(%p)->(%u)\n", This, bufferEm);
-    EnterCriticalSection(&This->critSect);
+    EnterCriticalSection(&This->filter.csFilter);
     if (bufferEm) {
         if (This->bufferLen < 0)
             This->bufferLen = 0;
     }
     else
         This->bufferLen = -1;
-    LeaveCriticalSection(&This->critSect);
+    LeaveCriticalSection(&This->filter.csFilter);
     return S_OK;
 }
 
@@ -848,7 +632,7 @@ SampleGrabber_ISampleGrabber_GetCurrentBuffer(ISampleGrabber *iface, LONG *bufSi
     TRACE("(%p)->(%p, %p)\n", This, bufSize, buffer);
     if (!bufSize)
         return E_POINTER;
-    EnterCriticalSection(&This->critSect);
+    EnterCriticalSection(&This->filter.csFilter);
     if (!This->pin_in.pair)
         ret = VFW_E_NOT_CONNECTED;
     else if (This->bufferLen < 0)
@@ -864,7 +648,7 @@ SampleGrabber_ISampleGrabber_GetCurrentBuffer(ISampleGrabber *iface, LONG *bufSi
         }
         *bufSize = This->bufferLen;
     }
-    LeaveCriticalSection(&This->critSect);
+    LeaveCriticalSection(&This->filter.csFilter);
     return ret;
 }
 
@@ -970,7 +754,7 @@ SampleGrabber_IMemInputPin_Receive(IMemInputPin *iface, IMediaSample *sample)
     TRACE("(%p)->(%p) output = %p, grabber = %p\n", This, sample, This->memOutput, This->grabberIface);
     if (!sample)
         return E_POINTER;
-    if ((This->state != State_Running) || (This->oneShot == OneShot_Past))
+    if ((This->filter.state != State_Running) || (This->oneShot == OneShot_Past))
         return S_FALSE;
     SampleGrabber_callback(This, sample);
     hr = This->memOutput ? IMemInputPin_Receive(This->memOutput, sample) : S_OK;
@@ -992,7 +776,7 @@ SampleGrabber_IMemInputPin_ReceiveMultiple(IMemInputPin *iface, IMediaSample **s
     TRACE("(%p)->(%p, %u, %p) output = %p, grabber = %p\n", This, samples, nSamples, nProcessed, This->memOutput, This->grabberIface);
     if (!samples || !nProcessed)
         return E_POINTER;
-    if ((This->state != State_Running) || (This->oneShot == OneShot_Past))
+    if ((This->filter.state != State_Running) || (This->oneShot == OneShot_Past))
         return S_FALSE;
     for (idx = 0; idx < nSamples; idx++)
         SampleGrabber_callback(This, samples[idx]);
@@ -1072,7 +856,7 @@ SampleGrabber_Out_IPin_Connect(IPin *iface, IPin *receiver, const AM_MEDIA_TYPE
         return E_POINTER;
     if (This->pair)
         return VFW_E_ALREADY_CONNECTED;
-    if (This->sg->state != State_Stopped)
+    if (This->sg->filter.state != State_Stopped)
         return VFW_E_NOT_STOPPED;
     if (type) {
        TRACE("Media type: %s/%s ssize: %u format: %s (%u bytes)\n",
@@ -1120,7 +904,7 @@ SampleGrabber_In_IPin_ReceiveConnection(IPin *iface, IPin *connector, const AM_M
         return E_POINTER;
     if (This->pair)
         return VFW_E_ALREADY_CONNECTED;
-    if (This->sg->state != State_Stopped)
+    if (This->sg->filter.state != State_Stopped)
         return VFW_E_NOT_STOPPED;
     if (type) {
        TRACE("Media type: %s/%s ssize: %u format: %s (%u bytes)\n",
@@ -1172,7 +956,7 @@ SampleGrabber_In_IPin_Disconnect(IPin *iface)
     SG_Pin *This = impl_from_IPin(iface);
 
     TRACE("(%p)->() pair = %p\n", This, This->pair);
-    if (This->sg->state != State_Stopped)
+    if (This->sg->filter.state != State_Stopped)
         return VFW_E_NOT_STOPPED;
     if (This->pair) {
         This->pair = NULL;
@@ -1188,7 +972,7 @@ SampleGrabber_Out_IPin_Disconnect(IPin *iface)
     SG_Pin *This = impl_from_IPin(iface);
 
     TRACE("(%p)->() pair = %p\n", This, This->pair);
-    if (This->sg->state != State_Stopped)
+    if (This->sg->filter.state != State_Stopped)
         return VFW_E_NOT_STOPPED;
     if (This->pair) {
         This->pair = NULL;
@@ -1246,8 +1030,8 @@ SampleGrabber_IPin_QueryPinInfo(IPin *iface, PIN_INFO *info)
     TRACE("(%p)->(%p)\n", This, info);
     if (!info)
         return E_POINTER;
-    IBaseFilter_AddRef(&This->sg->IBaseFilter_iface);
-    info->pFilter = &This->sg->IBaseFilter_iface;
+    info->pFilter = &This->sg->filter.IBaseFilter_iface;
+    IBaseFilter_AddRef(info->pFilter);
     info->dir = This->dir;
     lstrcpynW(info->achName,This->name,MAX_PIN_NAME);
     return S_OK;
@@ -1374,16 +1158,16 @@ static const IBaseFilterVtbl IBaseFilter_VTable =
     SampleGrabber_IBaseFilter_QueryInterface,
     SampleGrabber_IBaseFilter_AddRef,
     SampleGrabber_IBaseFilter_Release,
-    SampleGrabber_IBaseFilter_GetClassID,
+    BaseFilterImpl_GetClassID,
     SampleGrabber_IBaseFilter_Stop,
     SampleGrabber_IBaseFilter_Pause,
     SampleGrabber_IBaseFilter_Run,
-    SampleGrabber_IBaseFilter_GetState,
-    SampleGrabber_IBaseFilter_SetSyncSource,
-    SampleGrabber_IBaseFilter_GetSyncSource,
-    SampleGrabber_IBaseFilter_EnumPins,
+    BaseFilterImpl_GetState,
+    BaseFilterImpl_SetSyncSource,
+    BaseFilterImpl_GetSyncSource,
+    BaseFilterImpl_EnumPins,
     SampleGrabber_IBaseFilter_FindPin,
-    SampleGrabber_IBaseFilter_QueryFilterInfo,
+    BaseFilterImpl_QueryFilterInfo,
     SampleGrabber_IBaseFilter_JoinFilterGraph,
     SampleGrabber_IBaseFilter_QueryVendorInfo,
 };
@@ -1474,9 +1258,9 @@ HRESULT SampleGrabber_create(IUnknown *pUnkOuter, LPVOID *ppv)
     }
     ZeroMemory(obj, sizeof(SG_Impl));
 
-    obj->ref = 1;
+    BaseFilter_Init(&obj->filter, &IBaseFilter_VTable, &CLSID_SampleGrabber,
+            (DWORD_PTR)(__FILE__ ": SG_Impl.csFilter"), &basefunc_vtbl);
     obj->IUnknown_inner.lpVtbl = &samplegrabber_vtbl;
-    obj->IBaseFilter_iface.lpVtbl = &IBaseFilter_VTable;
     obj->ISampleGrabber_iface.lpVtbl = &ISampleGrabber_VTable;
     obj->IMemInputPin_iface.lpVtbl = &IMemInputPin_VTable;
     obj->pin_in.IPin_iface.lpVtbl = &IPin_In_VTable;
@@ -1489,16 +1273,10 @@ HRESULT SampleGrabber_create(IUnknown *pUnkOuter, LPVOID *ppv)
     obj->pin_out.name = pin_out_name;
     obj->pin_out.sg = obj;
     obj->pin_out.pair = NULL;
-    InitializeCriticalSection(&obj->critSect);
-    obj->critSect.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": SG_Impl.critSect");
-    obj->info.achName[0] = 0;
-    obj->info.pGraph = NULL;
-    obj->state = State_Stopped;
     obj->mtype.majortype = GUID_NULL;
     obj->mtype.subtype = MEDIASUBTYPE_None;
     obj->mtype.formattype = FORMAT_None;
     obj->allocator = NULL;
-    obj->refClock = NULL;
     obj->memOutput = NULL;
     obj->grabberIface = NULL;
     obj->grabberMethod = -1;