[PATCH 2/5] strmbase: Support aggregation in the base filter.

Zebediah Figura zfigura at codeweavers.com
Tue Jun 4 10:01:17 CDT 2019


From: Zebediah Figura <z.figura12 at gmail.com>

Signed-off-by: Zebediah Figura <z.figura12 at gmail.com>
---
 dlls/evr/evr.c                   |   4 +-
 dlls/qcap/audiorecord.c          |   4 +-
 dlls/qcap/avico.c                |   6 +--
 dlls/qcap/avimux.c               |  13 ++---
 dlls/qcap/smartteefilter.c       |   4 +-
 dlls/qcap/tests/avico.c          |  10 ++--
 dlls/qcap/tests/avimux.c         |   3 +-
 dlls/qcap/vfwcapture.c           |   5 +-
 dlls/qedit/nullrenderer.c        |   4 +-
 dlls/qedit/samplegrabber.c       |   4 +-
 dlls/quartz/avisplit.c           |  13 ++---
 dlls/quartz/dsoundrender.c       |  14 ++---
 dlls/quartz/filesource.c         |  10 ++--
 dlls/quartz/mpegsplit.c          |  14 ++---
 dlls/quartz/parser.c             |   9 ++--
 dlls/quartz/parser.h             |   2 +-
 dlls/quartz/tests/avisplit.c     |   3 +-
 dlls/quartz/tests/dsoundrender.c |   3 +-
 dlls/quartz/tests/filesource.c   |   3 +-
 dlls/quartz/tests/mpegsplit.c    |   3 +-
 dlls/quartz/tests/waveparser.c   |   3 +-
 dlls/quartz/videorenderer.c      |   4 +-
 dlls/quartz/vmr9.c               |   6 +--
 dlls/quartz/waveparser.c         |  13 ++---
 dlls/strmbase/filter.c           | 110 +++++++++++++++++++++++++--------------
 dlls/strmbase/renderer.c         |   8 +--
 dlls/strmbase/transform.c        |   2 +-
 dlls/winegstreamer/gstdemux.c    |  14 ++---
 dlls/wineqtdecoder/qtsplitter.c  |   9 ++--
 include/wine/strmbase.h          |  24 +++++----
 30 files changed, 158 insertions(+), 166 deletions(-)

diff --git a/dlls/evr/evr.c b/dlls/evr/evr.c
index 8341c40..21a4af0 100644
--- a/dlls/evr/evr.c
+++ b/dlls/evr/evr.c
@@ -117,7 +117,7 @@ static ULONG WINAPI inner_AddRef(IUnknown *iface)
 static ULONG WINAPI inner_Release(IUnknown *iface)
 {
     evr_filter *This = impl_from_inner_IUnknown(iface);
-    ULONG ref = InterlockedDecrement(&This->filter.refCount);
+    ULONG ref = InterlockedDecrement(&This->filter.refcount);
 
     TRACE("(%p, %p)->(): new ref %d\n", iface, This, ref);
 
@@ -220,7 +220,7 @@ HRESULT evr_filter_create(IUnknown *outer_unk, void **ppv)
     if (!object)
         return E_OUTOFMEMORY;
 
-    BaseFilter_Init(&object->filter, &basefilter_vtbl, &CLSID_EnhancedVideoRenderer,
+    strmbase_filter_init(&object->filter, &basefilter_vtbl, NULL, &CLSID_EnhancedVideoRenderer,
                     (DWORD_PTR)(__FILE__ ": EVR.csFilter"), &basefilter_functable);
 
     object->IUnknown_inner.lpVtbl = &evr_inner_vtbl;
diff --git a/dlls/qcap/audiorecord.c b/dlls/qcap/audiorecord.c
index f789da2..9b493c5 100644
--- a/dlls/qcap/audiorecord.c
+++ b/dlls/qcap/audiorecord.c
@@ -99,7 +99,7 @@ static ULONG WINAPI Unknown_AddRef(IUnknown *iface)
 static ULONG WINAPI Unknown_Release(IUnknown *iface)
 {
     AudioRecord *This = impl_from_IUnknown(iface);
-    ULONG ref = InterlockedDecrement(&This->filter.refCount);
+    ULONG ref = InterlockedDecrement(&This->filter.refcount);
     TRACE("(%p/%p)->() ref=%d\n", iface, This, ref);
     if (!ref) {
         strmbase_filter_cleanup(&This->filter);
@@ -271,7 +271,7 @@ IUnknown* WINAPI QCAP_createAudioCaptureFilter(IUnknown *outer, HRESULT *phr)
     else
         This->outerUnknown = &This->IUnknown_iface;
 
-    BaseFilter_Init(&This->filter, &AudioRecordVtbl, &CLSID_AudioRecord,
+    strmbase_filter_init(&This->filter, &AudioRecordVtbl, NULL, &CLSID_AudioRecord,
             (DWORD_PTR)(__FILE__ ": AudioRecord.csFilter"), &AudioRecordFuncs);
 
     *phr = S_OK;
diff --git a/dlls/qcap/avico.c b/dlls/qcap/avico.c
index cfb23e8..40bc82b 100644
--- a/dlls/qcap/avico.c
+++ b/dlls/qcap/avico.c
@@ -640,15 +640,13 @@ IUnknown* WINAPI QCAP_createAVICompressor(IUnknown *outer, HRESULT *phr)
     AVICompressor *compressor;
     HRESULT hres;
 
-    TRACE("\n");
-
     compressor = heap_alloc_zero(sizeof(*compressor));
     if(!compressor) {
         *phr = E_NOINTERFACE;
         return NULL;
     }
 
-    BaseFilter_Init(&compressor->filter, &AVICompressorVtbl, &CLSID_AVICo,
+    strmbase_filter_init(&compressor->filter, &AVICompressorVtbl, outer, &CLSID_AVICo,
             (DWORD_PTR)(__FILE__ ": AVICompressor.csFilter"), &filter_func_table);
 
     compressor->IPersistPropertyBag_iface.lpVtbl = &PersistPropertyBagVtbl;
@@ -672,5 +670,5 @@ IUnknown* WINAPI QCAP_createAVICompressor(IUnknown *outer, HRESULT *phr)
     }
 
     *phr = S_OK;
-    return (IUnknown*)&compressor->filter.IBaseFilter_iface;
+    return &compressor->filter.IUnknown_inner;
 }
diff --git a/dlls/qcap/avimux.c b/dlls/qcap/avimux.c
index 6a3a40b..de56a20 100644
--- a/dlls/qcap/avimux.c
+++ b/dlls/qcap/avimux.c
@@ -2270,7 +2270,7 @@ static HRESULT create_input_pin(AviMux *avimux)
     return S_OK;
 }
 
-IUnknown* WINAPI QCAP_createAVIMux(IUnknown *pUnkOuter, HRESULT *phr)
+IUnknown * WINAPI QCAP_createAVIMux(IUnknown *outer, HRESULT *phr)
 {
     static const WCHAR output_name[] = {'A','V','I',' ','O','u','t',0};
 
@@ -2278,20 +2278,13 @@ IUnknown* WINAPI QCAP_createAVIMux(IUnknown *pUnkOuter, HRESULT *phr)
     PIN_INFO info;
     HRESULT hr;
 
-    TRACE("(%p)\n", pUnkOuter);
-
-    if(pUnkOuter) {
-        *phr = CLASS_E_NOAGGREGATION;
-        return NULL;
-    }
-
     avimux = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(AviMux));
     if(!avimux) {
         *phr = E_OUTOFMEMORY;
         return NULL;
     }
 
-    BaseFilter_Init(&avimux->filter, &AviMuxVtbl, &CLSID_AviDest,
+    strmbase_filter_init(&avimux->filter, &AviMuxVtbl, outer, &CLSID_AviDest,
             (DWORD_PTR)(__FILE__ ": AviMux.csFilter"), &filter_func_table);
     avimux->IConfigAviMux_iface.lpVtbl = &ConfigAviMuxVtbl;
     avimux->IConfigInterleaving_iface.lpVtbl = &ConfigInterleavingVtbl;
@@ -2328,5 +2321,5 @@ IUnknown* WINAPI QCAP_createAVIMux(IUnknown *pUnkOuter, HRESULT *phr)
 
     ObjectRefCount(TRUE);
     *phr = S_OK;
-    return (IUnknown*)&avimux->filter.IBaseFilter_iface;
+    return &avimux->filter.IUnknown_inner;
 }
diff --git a/dlls/qcap/smartteefilter.c b/dlls/qcap/smartteefilter.c
index 7496fe6..a79e4bb 100644
--- a/dlls/qcap/smartteefilter.c
+++ b/dlls/qcap/smartteefilter.c
@@ -104,7 +104,7 @@ static ULONG WINAPI Unknown_AddRef(IUnknown *iface)
 static ULONG WINAPI Unknown_Release(IUnknown *iface)
 {
     SmartTeeFilter *This = impl_from_IUnknown(iface);
-    ULONG ref = InterlockedDecrement(&This->filter.refCount);
+    ULONG ref = InterlockedDecrement(&This->filter.refcount);
 
     TRACE("(%p)->() ref=%d\n", This, ref);
 
@@ -600,7 +600,7 @@ IUnknown* WINAPI QCAP_createSmartTeeFilter(IUnknown *outer, HRESULT *phr)
     else
         This->outerUnknown = &This->IUnknown_iface;
 
-    BaseFilter_Init(&This->filter, &SmartTeeFilterVtbl, &CLSID_SmartTee,
+    strmbase_filter_init(&This->filter, &SmartTeeFilterVtbl, NULL, &CLSID_SmartTee,
             (DWORD_PTR)(__FILE__ ": SmartTeeFilter.csFilter"), &SmartTeeFilterFuncs);
 
     inputPinInfo.pFilter = &This->filter.IBaseFilter_iface;
diff --git a/dlls/qcap/tests/avico.c b/dlls/qcap/tests/avico.c
index fd8b7f4..837c86d 100644
--- a/dlls/qcap/tests/avico.c
+++ b/dlls/qcap/tests/avico.c
@@ -172,23 +172,23 @@ static void test_aggregation(void)
 
     hr = IBaseFilter_QueryInterface(filter, &IID_IUnknown, (void **)&unk2);
     ok(hr == S_OK, "Got hr %#x.\n", hr);
-    todo_wine ok(unk2 == (IUnknown *)0xdeadbeef, "Got unexpected IUnknown %p.\n", unk2);
+    ok(unk2 == (IUnknown *)0xdeadbeef, "Got unexpected IUnknown %p.\n", unk2);
 
     hr = IBaseFilter_QueryInterface(filter, &IID_IBaseFilter, (void **)&filter2);
     ok(hr == S_OK, "Got hr %#x.\n", hr);
-    todo_wine ok(filter2 == (IBaseFilter *)0xdeadbeef, "Got unexpected IBaseFilter %p.\n", filter2);
+    ok(filter2 == (IBaseFilter *)0xdeadbeef, "Got unexpected IBaseFilter %p.\n", filter2);
 
     hr = IUnknown_QueryInterface(unk, &test_iid, (void **)&unk2);
     ok(hr == E_NOINTERFACE, "Got hr %#x.\n", hr);
     ok(!unk2, "Got unexpected IUnknown %p.\n", unk2);
 
     hr = IBaseFilter_QueryInterface(filter, &test_iid, (void **)&unk2);
-    todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
-    todo_wine ok(unk2 == (IUnknown *)0xdeadbeef, "Got unexpected IUnknown %p.\n", unk2);
+    ok(hr == S_OK, "Got hr %#x.\n", hr);
+    ok(unk2 == (IUnknown *)0xdeadbeef, "Got unexpected IUnknown %p.\n", unk2);
 
     IBaseFilter_Release(filter);
     ref = IUnknown_Release(unk);
-    todo_wine ok(!ref, "Got unexpected refcount %d.\n", ref);
+    ok(!ref, "Got unexpected refcount %d.\n", ref);
     ok(outer_ref == 1, "Got unexpected refcount %d.\n", outer_ref);
 }
 
diff --git a/dlls/qcap/tests/avimux.c b/dlls/qcap/tests/avimux.c
index ed636be..8292067 100644
--- a/dlls/qcap/tests/avimux.c
+++ b/dlls/qcap/tests/avimux.c
@@ -135,8 +135,7 @@ static void test_aggregation(void)
 
     hr = CoCreateInstance(&CLSID_AviDest, &test_outer, CLSCTX_INPROC_SERVER,
             &IID_IUnknown, (void **)&unk);
-    todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
-    if (FAILED(hr)) return;
+    ok(hr == S_OK, "Got hr %#x.\n", hr);
     ok(outer_ref == 1, "Got unexpected refcount %d.\n", outer_ref);
     ok(unk != &test_outer, "Returned IUnknown should not be outer IUnknown.\n");
     ref = get_refcount(unk);
diff --git a/dlls/qcap/vfwcapture.c b/dlls/qcap/vfwcapture.c
index a795a1e..7c25900 100644
--- a/dlls/qcap/vfwcapture.c
+++ b/dlls/qcap/vfwcapture.c
@@ -154,7 +154,7 @@ static ULONG WINAPI unknown_inner_AddRef(IUnknown *iface)
 static ULONG WINAPI unknown_inner_Release(IUnknown *iface)
 {
     VfwCapture *This = impl_from_IUnknown(iface);
-    ULONG ref = InterlockedDecrement(&This->filter.refCount);
+    ULONG ref = InterlockedDecrement(&This->filter.refcount);
 
     TRACE("(%p) ref=%d\n", This, ref);
 
@@ -219,7 +219,8 @@ IUnknown * WINAPI QCAP_createVFWCaptureFilter(IUnknown *pUnkOuter, HRESULT *phr)
     if (!pVfwCapture)
         return NULL;
 
-    BaseFilter_Init(&pVfwCapture->filter, &VfwCapture_Vtbl, &CLSID_VfwCapture, (DWORD_PTR)(__FILE__ ": VfwCapture.csFilter"), &BaseFuncTable);
+    strmbase_filter_init(&pVfwCapture->filter, &VfwCapture_Vtbl, NULL, &CLSID_VfwCapture,
+            (DWORD_PTR)(__FILE__ ": VfwCapture.csFilter"), &BaseFuncTable);
 
     pVfwCapture->IUnknown_inner.lpVtbl = &unknown_inner_vtbl;
     pVfwCapture->IAMStreamConfig_iface.lpVtbl = &IAMStreamConfig_VTable;
diff --git a/dlls/qedit/nullrenderer.c b/dlls/qedit/nullrenderer.c
index c9319fb..b2bfb22 100644
--- a/dlls/qedit/nullrenderer.c
+++ b/dlls/qedit/nullrenderer.c
@@ -110,7 +110,7 @@ static ULONG WINAPI NullRendererInner_AddRef(IUnknown *iface)
 static ULONG WINAPI NullRendererInner_Release(IUnknown *iface)
 {
     NullRendererImpl *This = impl_from_IUnknown(iface);
-    ULONG refCount = InterlockedDecrement(&This->renderer.filter.refCount);
+    ULONG refCount = InterlockedDecrement(&This->renderer.filter.refcount);
 
     if (!refCount)
     {
@@ -190,7 +190,7 @@ HRESULT NullRenderer_create(IUnknown *pUnkOuter, void **ppv)
     else
         pNullRenderer->outer_unk = &pNullRenderer->IUnknown_inner;
 
-    hr = strmbase_renderer_init(&pNullRenderer->renderer, &NullRenderer_Vtbl, pUnkOuter,
+    hr = strmbase_renderer_init(&pNullRenderer->renderer, &NullRenderer_Vtbl, NULL,
             &CLSID_NullRenderer, sink_name,
             (DWORD_PTR)(__FILE__ ": NullRendererImpl.csFilter"), &RendererFuncTable);
 
diff --git a/dlls/qedit/samplegrabber.c b/dlls/qedit/samplegrabber.c
index 76dc3d7..27e08c4 100644
--- a/dlls/qedit/samplegrabber.c
+++ b/dlls/qedit/samplegrabber.c
@@ -319,7 +319,7 @@ 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->filter.refCount);
+    ULONG ref = InterlockedDecrement(&This->filter.refcount);
 
     TRACE("(%p) ref=%d\n", This, ref);
 
@@ -1267,7 +1267,7 @@ HRESULT SampleGrabber_create(IUnknown *pUnkOuter, LPVOID *ppv)
     }
     ZeroMemory(obj, sizeof(SG_Impl));
 
-    BaseFilter_Init(&obj->filter, &IBaseFilter_VTable, &CLSID_SampleGrabber,
+    strmbase_filter_init(&obj->filter, &IBaseFilter_VTable, NULL, &CLSID_SampleGrabber,
             (DWORD_PTR)(__FILE__ ": SG_Impl.csFilter"), &basefunc_vtbl);
     obj->IUnknown_inner.lpVtbl = &samplegrabber_vtbl;
     obj->ISampleGrabber_iface.lpVtbl = &ISampleGrabber_VTable;
diff --git a/dlls/quartz/avisplit.c b/dlls/quartz/avisplit.c
index d5b716c..1fbaaf6 100644
--- a/dlls/quartz/avisplit.c
+++ b/dlls/quartz/avisplit.c
@@ -1424,18 +1424,13 @@ static const BaseFilterFuncTable avi_splitter_func_table =
     .filter_destroy = avi_splitter_destroy,
 };
 
-HRESULT AVISplitter_create(IUnknown * pUnkOuter, LPVOID * ppv)
+HRESULT AVISplitter_create(IUnknown *outer, void **out)
 {
     static const WCHAR sink_name[] = {'i','n','p','u','t',' ','p','i','n',0};
     HRESULT hr;
     AVISplitterImpl * This;
 
-    TRACE("(%p, %p)\n", pUnkOuter, ppv);
-
-    *ppv = NULL;
-
-    if (pUnkOuter)
-        return CLASS_E_NOAGGREGATION;
+    *out = NULL;
 
     /* Note: This memory is managed by the transform filter once created */
     This = CoTaskMemAlloc(sizeof(AVISplitterImpl));
@@ -1443,7 +1438,7 @@ HRESULT AVISplitter_create(IUnknown * pUnkOuter, LPVOID * ppv)
     This->streams = NULL;
     This->oldindex = NULL;
 
-    hr = Parser_Create(&This->Parser, &AVISplitterImpl_Vtbl, &CLSID_AviSplitter,
+    hr = Parser_Create(&This->Parser, &AVISplitterImpl_Vtbl, outer, &CLSID_AviSplitter,
             &avi_splitter_func_table, sink_name, AVISplitter_Sample, AVISplitter_QueryAccept,
             AVISplitter_InputPin_PreConnect, AVISplitter_Flush,
             AVISplitter_Disconnect, AVISplitter_first_request,
@@ -1452,7 +1447,7 @@ HRESULT AVISplitter_create(IUnknown * pUnkOuter, LPVOID * ppv)
     if (FAILED(hr))
         return hr;
 
-    *ppv = &This->Parser.filter.IBaseFilter_iface;
+    *out = &This->Parser.filter.IUnknown_inner;
 
     return hr;
 }
diff --git a/dlls/quartz/dsoundrender.c b/dlls/quartz/dsoundrender.c
index 4c339f8..1545209 100644
--- a/dlls/quartz/dsoundrender.c
+++ b/dlls/quartz/dsoundrender.c
@@ -652,19 +652,14 @@ static const BaseRendererFuncTable BaseFuncTable = {
     dsound_render_query_interface,
 };
 
-HRESULT DSoundRender_create(IUnknown * pUnkOuter, LPVOID * ppv)
+HRESULT DSoundRender_create(IUnknown *outer, void **out)
 {
     static const WCHAR sink_name[] = {'A','u','d','i','o',' ','I','n','p','u','t',' ','p','i','n',' ','(','r','e','n','d','e','r','e','d',')',0};
 
     HRESULT hr;
     DSoundRenderImpl * pDSoundRender;
 
-    TRACE("(%p, %p)\n", pUnkOuter, ppv);
-
-    *ppv = NULL;
-
-    if (pUnkOuter)
-        return CLASS_E_NOAGGREGATION;
+    *out = NULL;
 
     pDSoundRender = CoTaskMemAlloc(sizeof(DSoundRenderImpl));
     if (!pDSoundRender)
@@ -672,8 +667,7 @@ HRESULT DSoundRender_create(IUnknown * pUnkOuter, LPVOID * ppv)
     ZeroMemory(pDSoundRender, sizeof(DSoundRenderImpl));
 
     hr = strmbase_renderer_init(&pDSoundRender->renderer, &DSoundRender_Vtbl,
-            (IUnknown *)&pDSoundRender->renderer. filter.IBaseFilter_iface,
-            &CLSID_DSoundRender, sink_name,
+            outer, &CLSID_DSoundRender, sink_name,
             (DWORD_PTR)(__FILE__ ": DSoundRenderImpl.csFilter"), &BaseFuncTable);
 
     BasicAudio_Init(&pDSoundRender->basicAudio,&IBasicAudio_Vtbl);
@@ -712,7 +706,7 @@ HRESULT DSoundRender_create(IUnknown * pUnkOuter, LPVOID * ppv)
             return HRESULT_FROM_WIN32(GetLastError());
         }
 
-        *ppv = pDSoundRender;
+        *out = &pDSoundRender->renderer.filter.IUnknown_inner;
     }
     else
     {
diff --git a/dlls/quartz/filesource.c b/dlls/quartz/filesource.c
index 11fdbdc..b2fc401 100644
--- a/dlls/quartz/filesource.c
+++ b/dlls/quartz/filesource.c
@@ -446,19 +446,17 @@ static const BaseFilterFuncTable BaseFuncTable =
     .filter_query_interface = async_reader_query_interface,
 };
 
-HRESULT AsyncReader_create(IUnknown * pUnkOuter, LPVOID * ppv)
+HRESULT AsyncReader_create(IUnknown *outer, void **out)
 {
     AsyncReader *pAsyncRead;
     
-    if( pUnkOuter )
-        return CLASS_E_NOAGGREGATION;
-    
     pAsyncRead = CoTaskMemAlloc(sizeof(AsyncReader));
 
     if (!pAsyncRead)
         return E_OUTOFMEMORY;
 
-    BaseFilter_Init(&pAsyncRead->filter, &AsyncReader_Vtbl, &CLSID_AsyncReader, (DWORD_PTR)(__FILE__ ": AsyncReader.csFilter"), &BaseFuncTable);
+    strmbase_filter_init(&pAsyncRead->filter, &AsyncReader_Vtbl, outer, &CLSID_AsyncReader,
+            (DWORD_PTR)(__FILE__ ": AsyncReader.csFilter"), &BaseFuncTable);
 
     pAsyncRead->IFileSourceFilter_iface.lpVtbl = &FileSource_Vtbl;
     pAsyncRead->pOutputPin = NULL;
@@ -466,7 +464,7 @@ HRESULT AsyncReader_create(IUnknown * pUnkOuter, LPVOID * ppv)
     pAsyncRead->pszFileName = NULL;
     pAsyncRead->pmt = NULL;
 
-    *ppv = pAsyncRead;
+    *out = &pAsyncRead->filter.IUnknown_inner;
 
     TRACE("-- created at %p\n", pAsyncRead);
 
diff --git a/dlls/quartz/mpegsplit.c b/dlls/quartz/mpegsplit.c
index 25e1b0d..80c714c 100644
--- a/dlls/quartz/mpegsplit.c
+++ b/dlls/quartz/mpegsplit.c
@@ -868,25 +868,20 @@ static const BaseFilterFuncTable mpeg_splitter_func_table =
     .filter_query_interface = mpeg_splitter_query_interface,
 };
 
-HRESULT MPEGSplitter_create(IUnknown * pUnkOuter, LPVOID * ppv)
+HRESULT MPEGSplitter_create(IUnknown *outer, void **out)
 {
     static const WCHAR sink_name[] = {'I','n','p','u','t',0};
     MPEGSplitterImpl *This;
     HRESULT hr = E_FAIL;
 
-    TRACE("(%p, %p)\n", pUnkOuter, ppv);
-
-    *ppv = NULL;
-
-    if (pUnkOuter)
-        return CLASS_E_NOAGGREGATION;
+    *out = NULL;
 
     This = CoTaskMemAlloc(sizeof(MPEGSplitterImpl));
     if (!This)
         return E_OUTOFMEMORY;
 
     ZeroMemory(This, sizeof(MPEGSplitterImpl));
-    hr = Parser_Create(&This->Parser, &MPEGSplitter_Vtbl, &CLSID_MPEG1Splitter,
+    hr = Parser_Create(&This->Parser, &MPEGSplitter_Vtbl, outer, &CLSID_MPEG1Splitter,
             &mpeg_splitter_func_table, sink_name, MPEGSplitter_process_sample, MPEGSplitter_query_accept,
             MPEGSplitter_pre_connect, MPEGSplitter_cleanup, MPEGSplitter_disconnect,
             MPEGSplitter_first_request, NULL, NULL, MPEGSplitter_seek, NULL);
@@ -898,8 +893,7 @@ HRESULT MPEGSplitter_create(IUnknown * pUnkOuter, LPVOID * ppv)
     This->IAMStreamSelect_iface.lpVtbl = &AMStreamSelectVtbl;
     This->seek = TRUE;
 
-    /* Note: This memory is managed by the parser filter once created */
-    *ppv = &This->Parser.filter.IBaseFilter_iface;
+    *out = &This->Parser.filter.IUnknown_inner;
 
     return hr;
 }
diff --git a/dlls/quartz/parser.c b/dlls/quartz/parser.c
index 4a3bc2e..3320dec 100644
--- a/dlls/quartz/parser.c
+++ b/dlls/quartz/parser.c
@@ -73,8 +73,8 @@ IPin *parser_get_pin(BaseFilter *iface, unsigned int index)
     return filter->ppPins[index];
 }
 
-HRESULT Parser_Create(ParserImpl *pParser, const IBaseFilterVtbl *Parser_Vtbl,
-        const CLSID *pClsid, const BaseFilterFuncTable *func_table, const WCHAR *sink_name,
+HRESULT Parser_Create(ParserImpl *pParser, const IBaseFilterVtbl *vtbl, IUnknown *outer,
+        const CLSID *clsid, const BaseFilterFuncTable *func_table, const WCHAR *sink_name,
         PFN_PROCESS_SAMPLE fnProcessSample, PFN_QUERY_ACCEPT fnQueryAccept, PFN_PRE_CONNECT fnPreConnect,
         PFN_CLEANUP fnCleanup, PFN_DISCONNECT fnDisconnect, REQUESTPROC fnRequest,
         STOPPROCESSPROC fnDone, SourceSeeking_ChangeStop stop,
@@ -83,8 +83,8 @@ HRESULT Parser_Create(ParserImpl *pParser, const IBaseFilterVtbl *Parser_Vtbl,
     HRESULT hr;
     PIN_INFO piInput;
 
-    /* pTransformFilter is already allocated */
-    BaseFilter_Init(&pParser->filter, Parser_Vtbl, pClsid, (DWORD_PTR)(__FILE__ ": ParserImpl.csFilter"), func_table);
+    strmbase_filter_init(&pParser->filter, vtbl, outer, clsid,
+            (DWORD_PTR)(__FILE__ ": ParserImpl.csFilter"), func_table);
 
     pParser->fnDisconnect = fnDisconnect;
 
@@ -160,7 +160,6 @@ void Parser_Destroy(ParserImpl *This)
     ULONG pinref;
     HRESULT hr;
 
-    assert(!This->filter.refCount);
     PullPin_WaitForStateChange(This->pInputPin, INFINITE);
 
     /* Don't need to clean up output pins, freeing input pin will do that */
diff --git a/dlls/quartz/parser.h b/dlls/quartz/parser.h
index aeeb55a..8909c4d 100644
--- a/dlls/quartz/parser.h
+++ b/dlls/quartz/parser.h
@@ -52,7 +52,7 @@ typedef struct Parser_OutputPin
 
 extern HRESULT Parser_AddPin(ParserImpl * This, const PIN_INFO * piOutput, ALLOCATOR_PROPERTIES * props, const AM_MEDIA_TYPE * amt);
 
-HRESULT Parser_Create(ParserImpl *parser, const IBaseFilterVtbl *vtbl,
+HRESULT Parser_Create(ParserImpl *parser, const IBaseFilterVtbl *vtbl, IUnknown *outer,
         const CLSID *clsid, const BaseFilterFuncTable *func_table, const WCHAR *sink_name,
         PFN_PROCESS_SAMPLE, PFN_QUERY_ACCEPT, PFN_PRE_CONNECT, PFN_CLEANUP, PFN_DISCONNECT,
         REQUESTPROC, STOPPROCESSPROC, SourceSeeking_ChangeStop,
diff --git a/dlls/quartz/tests/avisplit.c b/dlls/quartz/tests/avisplit.c
index e177fc8..59edb38 100644
--- a/dlls/quartz/tests/avisplit.c
+++ b/dlls/quartz/tests/avisplit.c
@@ -222,8 +222,7 @@ static void test_aggregation(void)
 
     hr = CoCreateInstance(&CLSID_AviSplitter, &test_outer, CLSCTX_INPROC_SERVER,
             &IID_IUnknown, (void **)&unk);
-    todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
-    if (FAILED(hr)) return;
+    ok(hr == S_OK, "Got hr %#x.\n", hr);
     ok(outer_ref == 1, "Got unexpected refcount %d.\n", outer_ref);
     ok(unk != &test_outer, "Returned IUnknown should not be outer IUnknown.\n");
     ref = get_refcount(unk);
diff --git a/dlls/quartz/tests/dsoundrender.c b/dlls/quartz/tests/dsoundrender.c
index 11a5f80..44c7119 100644
--- a/dlls/quartz/tests/dsoundrender.c
+++ b/dlls/quartz/tests/dsoundrender.c
@@ -217,8 +217,7 @@ static void test_aggregation(void)
 
     hr = CoCreateInstance(&CLSID_DSoundRender, &test_outer, CLSCTX_INPROC_SERVER,
             &IID_IUnknown, (void **)&unk);
-    todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
-    if (FAILED(hr)) return;
+    ok(hr == S_OK, "Got hr %#x.\n", hr);
     ok(outer_ref == 1, "Got unexpected refcount %d.\n", outer_ref);
     ok(unk != &test_outer, "Returned IUnknown should not be outer IUnknown.\n");
     ref = get_refcount(unk);
diff --git a/dlls/quartz/tests/filesource.c b/dlls/quartz/tests/filesource.c
index 691af62..0bac51d 100644
--- a/dlls/quartz/tests/filesource.c
+++ b/dlls/quartz/tests/filesource.c
@@ -183,8 +183,7 @@ static void test_aggregation(void)
 
     hr = CoCreateInstance(&CLSID_AsyncReader, &test_outer, CLSCTX_INPROC_SERVER,
             &IID_IUnknown, (void **)&unk);
-    todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
-    if (FAILED(hr)) return;
+    ok(hr == S_OK, "Got hr %#x.\n", hr);
     ok(outer_ref == 1, "Got unexpected refcount %d.\n", outer_ref);
     ok(unk != &test_outer, "Returned IUnknown should not be outer IUnknown.\n");
     ref = get_refcount(unk);
diff --git a/dlls/quartz/tests/mpegsplit.c b/dlls/quartz/tests/mpegsplit.c
index 3d98c84..c82c5b6 100644
--- a/dlls/quartz/tests/mpegsplit.c
+++ b/dlls/quartz/tests/mpegsplit.c
@@ -225,8 +225,7 @@ static void test_aggregation(void)
 
     hr = CoCreateInstance(&CLSID_MPEG1Splitter, &test_outer, CLSCTX_INPROC_SERVER,
             &IID_IUnknown, (void **)&unk);
-    todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
-    if (FAILED(hr)) return;
+    ok(hr == S_OK, "Got hr %#x.\n", hr);
     ok(outer_ref == 1, "Got unexpected refcount %d.\n", outer_ref);
     ok(unk != &test_outer, "Returned IUnknown should not be outer IUnknown.\n");
     ref = get_refcount(unk);
diff --git a/dlls/quartz/tests/waveparser.c b/dlls/quartz/tests/waveparser.c
index 8ede6e9..fd65099 100644
--- a/dlls/quartz/tests/waveparser.c
+++ b/dlls/quartz/tests/waveparser.c
@@ -219,8 +219,7 @@ static void test_aggregation(void)
 
     hr = CoCreateInstance(&CLSID_WAVEParser, &test_outer, CLSCTX_INPROC_SERVER,
             &IID_IUnknown, (void **)&unk);
-    todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
-    if (FAILED(hr)) return;
+    ok(hr == S_OK, "Got hr %#x.\n", hr);
     ok(outer_ref == 1, "Got unexpected refcount %d.\n", outer_ref);
     ok(unk != &test_outer, "Returned IUnknown should not be outer IUnknown.\n");
     ref = get_refcount(unk);
diff --git a/dlls/quartz/videorenderer.c b/dlls/quartz/videorenderer.c
index 3a84aba..182d5e8 100644
--- a/dlls/quartz/videorenderer.c
+++ b/dlls/quartz/videorenderer.c
@@ -691,7 +691,7 @@ static ULONG WINAPI VideoRendererInner_AddRef(IUnknown *iface)
 static ULONG WINAPI VideoRendererInner_Release(IUnknown *iface)
 {
     VideoRendererImpl *This = impl_from_IUnknown(iface);
-    ULONG refCount = InterlockedDecrement(&This->renderer.filter.refCount);
+    ULONG refCount = InterlockedDecrement(&This->renderer.filter.refcount);
 
     TRACE("(%p)->(): new ref = %d\n", This, refCount);
 
@@ -1002,7 +1002,7 @@ HRESULT VideoRenderer_create(IUnknown *pUnkOuter, void **ppv)
         pVideoRenderer->outer_unk = &pVideoRenderer->IUnknown_inner;
 
     hr = strmbase_renderer_init(&pVideoRenderer->renderer, &VideoRenderer_Vtbl,
-            pUnkOuter, &CLSID_VideoRenderer, sink_name,
+            NULL, &CLSID_VideoRenderer, sink_name,
             (DWORD_PTR)(__FILE__ ": VideoRendererImpl.csFilter"), &BaseFuncTable);
 
     if (FAILED(hr))
diff --git a/dlls/quartz/vmr9.c b/dlls/quartz/vmr9.c
index 0178f36..e53b19d 100644
--- a/dlls/quartz/vmr9.c
+++ b/dlls/quartz/vmr9.c
@@ -831,7 +831,7 @@ static ULONG WINAPI VMR9Inner_AddRef(IUnknown * iface)
 static ULONG WINAPI VMR9Inner_Release(IUnknown * iface)
 {
     struct quartz_vmr *This = impl_from_inner_IUnknown(iface);
-    ULONG refCount = InterlockedDecrement(&This->renderer.filter.refCount);
+    ULONG refCount = InterlockedDecrement(&This->renderer.filter.refcount);
 
     TRACE("(%p/%p)->() Release from %d\n", This, iface, refCount + 1);
 
@@ -2418,11 +2418,11 @@ static HRESULT vmr_create(IUnknown *outer_unk, LPVOID *ppv, const CLSID *clsid)
     pVMR->IVMRWindowlessControl9_iface.lpVtbl = &VMR9_WindowlessControl_Vtbl;
 
     if (IsEqualGUID(clsid, &CLSID_VideoMixingRenderer))
-        hr = strmbase_renderer_init(&pVMR->renderer, &VMR_Vtbl, outer_unk,
+        hr = strmbase_renderer_init(&pVMR->renderer, &VMR_Vtbl, NULL,
                 &CLSID_VideoMixingRenderer, sink_name,
                 (DWORD_PTR)(__FILE__ ": VMR7Impl.csFilter"), &BaseFuncTable);
     else
-        hr = strmbase_renderer_init(&pVMR->renderer, &VMR_Vtbl, outer_unk,
+        hr = strmbase_renderer_init(&pVMR->renderer, &VMR_Vtbl, NULL,
                 &CLSID_VideoMixingRenderer9, sink_name,
                 (DWORD_PTR)(__FILE__ ": VMR9Impl.csFilter"), &BaseFuncTable);
 
diff --git a/dlls/quartz/waveparser.c b/dlls/quartz/waveparser.c
index 7cc01af..1767adf 100644
--- a/dlls/quartz/waveparser.c
+++ b/dlls/quartz/waveparser.c
@@ -425,23 +425,18 @@ static const BaseFilterFuncTable wave_parser_func_table =
     .filter_destroy = wave_parser_destroy,
 };
 
-HRESULT WAVEParser_create(IUnknown * pUnkOuter, LPVOID * ppv)
+HRESULT WAVEParser_create(IUnknown *outer, void **out)
 {
     static const WCHAR sink_name[] = {'i','n','p','u','t',' ','p','i','n',0};
     HRESULT hr;
     WAVEParserImpl * This;
 
-    TRACE("(%p, %p)\n", pUnkOuter, ppv);
-
-    *ppv = NULL;
-
-    if (pUnkOuter)
-        return CLASS_E_NOAGGREGATION;
+    *out = NULL;
 
     /* Note: This memory is managed by the transform filter once created */
     This = CoTaskMemAlloc(sizeof(WAVEParserImpl));
 
-    hr = Parser_Create(&This->Parser, &WAVEParser_Vtbl, &CLSID_WAVEParser,
+    hr = Parser_Create(&This->Parser, &WAVEParser_Vtbl, outer, &CLSID_WAVEParser,
             &wave_parser_func_table, sink_name, WAVEParser_Sample, WAVEParser_QueryAccept,
             WAVEParser_InputPin_PreConnect, WAVEParser_Cleanup, WAVEParser_disconnect,
             WAVEParser_first_request, NULL, NULL, WAVEParserImpl_seek, NULL);
@@ -449,7 +444,7 @@ HRESULT WAVEParser_create(IUnknown * pUnkOuter, LPVOID * ppv)
     if (FAILED(hr))
         return hr;
 
-    *ppv = &This->Parser.filter.IBaseFilter_iface;
+    *out = &This->Parser.filter.IUnknown_inner;
 
     return hr;
 }
diff --git a/dlls/strmbase/filter.c b/dlls/strmbase/filter.c
index 1af955f..b61d3ff 100644
--- a/dlls/strmbase/filter.c
+++ b/dlls/strmbase/filter.c
@@ -22,14 +22,14 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(strmbase);
 
-static inline BaseFilter *impl_from_IBaseFilter(IBaseFilter *iface)
+static inline BaseFilter *impl_from_IUnknown(IUnknown *iface)
 {
-    return CONTAINING_RECORD(iface, BaseFilter, IBaseFilter_iface);
+    return CONTAINING_RECORD(iface, BaseFilter, IUnknown_inner);
 }
 
-HRESULT WINAPI BaseFilterImpl_QueryInterface(IBaseFilter *iface, REFIID iid, void **out)
+static HRESULT WINAPI filter_inner_QueryInterface(IUnknown *iface, REFIID iid, void **out)
 {
-    BaseFilter *filter = impl_from_IBaseFilter(iface);
+    BaseFilter *filter = impl_from_IUnknown(iface);
     HRESULT hr;
 
     TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
@@ -42,41 +42,75 @@ HRESULT WINAPI BaseFilterImpl_QueryInterface(IBaseFilter *iface, REFIID iid, voi
         return hr;
     }
 
-    if (IsEqualIID(iid, &IID_IUnknown)
-            || IsEqualIID(iid, &IID_IPersist)
+    if (IsEqualIID(iid, &IID_IUnknown))
+        *out = iface;
+    else if (IsEqualIID(iid, &IID_IPersist)
             || IsEqualIID(iid, &IID_IMediaFilter)
             || IsEqualIID(iid, &IID_IBaseFilter))
     {
-        *out = iface;
-        IBaseFilter_AddRef(iface);
-        return S_OK;
+        *out = &filter->IBaseFilter_iface;
+    }
+    else
+    {
+        WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
+        return E_NOINTERFACE;
     }
 
-    WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
-    return E_NOINTERFACE;
+    IUnknown_AddRef((IUnknown *)*out);
+    return S_OK;
 }
 
-ULONG WINAPI BaseFilterImpl_AddRef(IBaseFilter * iface)
+static ULONG WINAPI filter_inner_AddRef(IUnknown *iface)
 {
-    BaseFilter *This = impl_from_IBaseFilter(iface);
-    ULONG refCount = InterlockedIncrement(&This->refCount);
+    BaseFilter *filter = impl_from_IUnknown(iface);
+    ULONG refcount = InterlockedIncrement(&filter->refcount);
 
-    TRACE("(%p)->() AddRef from %d\n", This, refCount - 1);
+    TRACE("%p increasing refcount to %u.\n", filter, refcount);
 
-    return refCount;
+    return refcount;
+}
+
+static ULONG WINAPI filter_inner_Release(IUnknown *iface)
+{
+    BaseFilter *filter = impl_from_IUnknown(iface);
+    ULONG refcount = InterlockedDecrement(&filter->refcount);
+
+    TRACE("%p decreasing refcount to %u.\n", filter, refcount);
+
+    if (!refcount)
+        filter->pFuncsTable->filter_destroy(filter);
+
+    return refcount;
+}
+
+static const IUnknownVtbl filter_inner_vtbl =
+{
+    filter_inner_QueryInterface,
+    filter_inner_AddRef,
+    filter_inner_Release,
+};
+
+static inline BaseFilter *impl_from_IBaseFilter(IBaseFilter *iface)
+{
+    return CONTAINING_RECORD(iface, BaseFilter, IBaseFilter_iface);
+}
+
+HRESULT WINAPI BaseFilterImpl_QueryInterface(IBaseFilter *iface, REFIID iid, void **out)
+{
+    BaseFilter *filter = impl_from_IBaseFilter(iface);
+    return IUnknown_QueryInterface(filter->outer_unk, iid, out);
+}
+
+ULONG WINAPI BaseFilterImpl_AddRef(IBaseFilter *iface)
+{
+    BaseFilter *filter = impl_from_IBaseFilter(iface);
+    return IUnknown_AddRef(filter->outer_unk);
 }
 
 ULONG WINAPI BaseFilterImpl_Release(IBaseFilter *iface)
 {
-    BaseFilter *This = impl_from_IBaseFilter(iface);
-    ULONG refCount = InterlockedDecrement(&This->refCount);
-
-    TRACE("(%p)->() Release from %d\n", This, refCount + 1);
-
-    if (!refCount)
-        This->pFuncsTable->filter_destroy(This);
-
-    return refCount;
+    BaseFilter *filter = impl_from_IBaseFilter(iface);
+    return IUnknown_Release(filter->outer_unk);
 }
 
 HRESULT WINAPI BaseFilterImpl_GetClassID(IBaseFilter * iface, CLSID * pClsid)
@@ -222,21 +256,21 @@ VOID WINAPI BaseFilterImpl_IncrementPinVersion(BaseFilter *filter)
     InterlockedIncrement(&filter->pin_version);
 }
 
-void BaseFilter_Init(BaseFilter *This, const IBaseFilterVtbl *Vtbl, const CLSID *pClsid,
-        DWORD_PTR DebugInfo, const BaseFilterFuncTable *pBaseFuncsTable)
+void strmbase_filter_init(BaseFilter *filter, const IBaseFilterVtbl *vtbl, IUnknown *outer,
+        const CLSID *clsid, DWORD_PTR debug_info, const BaseFilterFuncTable *func_table)
 {
-    This->IBaseFilter_iface.lpVtbl = Vtbl;
-    This->refCount = 1;
-    InitializeCriticalSection(&This->csFilter);
-    This->state = State_Stopped;
-    This->rtStreamStart = 0;
-    This->pClock = NULL;
-    ZeroMemory(&This->filterInfo, sizeof(FILTER_INFO));
-    This->clsid = *pClsid;
-    This->csFilter.DebugInfo->Spare[0] = DebugInfo;
-    This->pin_version = 1;
+    memset(filter, 0, sizeof(*filter));
 
-    This->pFuncsTable = pBaseFuncsTable;
+    filter->IBaseFilter_iface.lpVtbl = vtbl;
+    filter->IUnknown_inner.lpVtbl = &filter_inner_vtbl;
+    filter->outer_unk = outer ? outer : &filter->IUnknown_inner;
+    filter->refcount = 1;
+
+    InitializeCriticalSection(&filter->csFilter);
+    filter->clsid = *clsid;
+    filter->csFilter.DebugInfo->Spare[0] = debug_info;
+    filter->pin_version = 1;
+    filter->pFuncsTable = func_table;
 }
 
 void strmbase_filter_cleanup(BaseFilter *This)
diff --git a/dlls/strmbase/renderer.c b/dlls/strmbase/renderer.c
index 5308cd3..6f0bc2d 100644
--- a/dlls/strmbase/renderer.c
+++ b/dlls/strmbase/renderer.c
@@ -249,14 +249,14 @@ static const BaseInputPinFuncTable input_BaseInputFuncTable = {
 };
 
 
-HRESULT WINAPI strmbase_renderer_init(BaseRenderer *This, const IBaseFilterVtbl *Vtbl,
-        IUnknown *pUnkOuter, const CLSID *pClsid, const WCHAR *sink_name, DWORD_PTR DebugInfo,
+HRESULT WINAPI strmbase_renderer_init(BaseRenderer *This, const IBaseFilterVtbl *vtbl,
+        IUnknown *outer, const CLSID *clsid, const WCHAR *sink_name, DWORD_PTR debug_info,
         const BaseRendererFuncTable *pBaseFuncsTable)
 {
     PIN_INFO piInput;
     HRESULT hr;
 
-    BaseFilter_Init(&This->filter, Vtbl, pClsid, DebugInfo, &RendererBaseFilterFuncTable);
+    strmbase_filter_init(&This->filter, vtbl, outer, clsid, debug_info, &RendererBaseFilterFuncTable);
 
     This->pFuncsTable = pBaseFuncsTable;
 
@@ -270,7 +270,7 @@ HRESULT WINAPI strmbase_renderer_init(BaseRenderer *This, const IBaseFilterVtbl
 
     if (SUCCEEDED(hr))
     {
-        hr = CreatePosPassThru(pUnkOuter ? pUnkOuter: (IUnknown *)&This->filter.IBaseFilter_iface, TRUE,
+        hr = CreatePosPassThru(outer ? outer : (IUnknown *)&This->filter.IBaseFilter_iface, TRUE,
                 &This->pInputPin->pin.IPin_iface, &This->pPosition);
         if (FAILED(hr))
             return hr;
diff --git a/dlls/strmbase/transform.c b/dlls/strmbase/transform.c
index 04ef23e..bfe87a1 100644
--- a/dlls/strmbase/transform.c
+++ b/dlls/strmbase/transform.c
@@ -288,7 +288,7 @@ static HRESULT strmbase_transform_init(const CLSID *clsid,
     PIN_INFO piInput;
     PIN_INFO piOutput;
 
-    BaseFilter_Init(&filter->filter, &transform_vtbl, clsid,
+    strmbase_filter_init(&filter->filter, &transform_vtbl, NULL, clsid,
             (DWORD_PTR)(__FILE__ ": TransformFilter.csFilter"), &tfBaseFuncTable);
 
     InitializeCriticalSection(&filter->csReceive);
diff --git a/dlls/winegstreamer/gstdemux.c b/dlls/winegstreamer/gstdemux.c
index 81c6168..8649c8a 100644
--- a/dlls/winegstreamer/gstdemux.c
+++ b/dlls/winegstreamer/gstdemux.c
@@ -1257,14 +1257,11 @@ static const BaseFilterFuncTable BaseFuncTable = {
     .filter_destroy = gstdemux_destroy,
 };
 
-IUnknown * CALLBACK Gstreamer_Splitter_create(IUnknown *pUnkOuter, HRESULT *phr)
+IUnknown * CALLBACK Gstreamer_Splitter_create(IUnknown *outer, HRESULT *phr)
 {
-    IUnknown *obj = NULL;
     PIN_INFO *piInput;
     GSTImpl *This;
 
-    TRACE("%p %p\n", pUnkOuter, phr);
-
     if (!init_gstreamer())
     {
         *phr = E_FAIL;
@@ -1281,8 +1278,8 @@ IUnknown * CALLBACK Gstreamer_Splitter_create(IUnknown *pUnkOuter, HRESULT *phr)
     }
     memset(This, 0, sizeof(*This));
 
-    obj = (IUnknown*)&This->filter.IBaseFilter_iface;
-    BaseFilter_Init(&This->filter, &GST_Vtbl, &CLSID_Gstreamer_Splitter, (DWORD_PTR)(__FILE__ ": GSTImpl.csFilter"), &BaseFuncTable);
+    strmbase_filter_init(&This->filter, &GST_Vtbl, outer, &CLSID_Gstreamer_Splitter,
+            (DWORD_PTR)(__FILE__ ": GSTImpl.csFilter"), &BaseFuncTable);
 
     This->cStreams = 0;
     This->ppPins = NULL;
@@ -1302,9 +1299,8 @@ IUnknown * CALLBACK Gstreamer_Splitter_create(IUnknown *pUnkOuter, HRESULT *phr)
     ZeroMemory(&This->pInputPin.pin.mtCurrent, sizeof(AM_MEDIA_TYPE));
     *phr = S_OK;
 
-    TRACE("returning %p\n", obj);
-
-    return obj;
+    TRACE("Created GStreamer demuxer %p.\n", This);
+    return &This->filter.IUnknown_inner;
 }
 
 static HRESULT WINAPI GST_Stop(IBaseFilter *iface)
diff --git a/dlls/wineqtdecoder/qtsplitter.c b/dlls/wineqtdecoder/qtsplitter.c
index 11ff874..6c1105c 100644
--- a/dlls/wineqtdecoder/qtsplitter.c
+++ b/dlls/wineqtdecoder/qtsplitter.c
@@ -296,9 +296,8 @@ static const BaseFilterFuncTable BaseFuncTable = {
     .filter_destroy = qt_splitter_destroy,
 };
 
-IUnknown * CALLBACK QTSplitter_create(IUnknown *punkout, HRESULT *phr)
+IUnknown * CALLBACK QTSplitter_create(IUnknown *outer, HRESULT *phr)
 {
-    IUnknown *obj = NULL;
     PIN_INFO *piInput;
     QTSplitter *This;
     static const WCHAR wcsInputPinName[] = {'I','n','p','u','t',' ','P','i','n',0};
@@ -308,7 +307,6 @@ IUnknown * CALLBACK QTSplitter_create(IUnknown *punkout, HRESULT *phr)
     RegisterWineDataHandler();
 
     This = CoTaskMemAlloc(sizeof(*This));
-    obj = (IUnknown*)This;
     if (!This)
     {
         *phr = E_OUTOFMEMORY;
@@ -316,7 +314,8 @@ IUnknown * CALLBACK QTSplitter_create(IUnknown *punkout, HRESULT *phr)
     }
     ZeroMemory(This,sizeof(*This));
 
-    BaseFilter_Init(&This->filter, &QT_Vtbl, &CLSID_QTSplitter, (DWORD_PTR)(__FILE__ ": QTSplitter.csFilter"), &BaseFuncTable);
+    strmbase_filter_init(&This->filter, &QT_Vtbl, outer, &CLSID_QTSplitter,
+            (DWORD_PTR)(__FILE__ ": QTSplitter.csFilter"), &BaseFuncTable);
 
     InitializeCriticalSection(&This->csReceive);
     This->csReceive.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__": QTSplitter.csReceive");
@@ -339,7 +338,7 @@ IUnknown * CALLBACK QTSplitter_create(IUnknown *punkout, HRESULT *phr)
     SourceSeeking_Init(&This->sourceSeeking, &QT_Seeking_Vtbl, QTSplitter_ChangeStop, QTSplitter_ChangeStart, QTSplitter_ChangeRate,  &This->filter.csFilter);
 
     *phr = S_OK;
-    return obj;
+    return &This->filter.IUnknown_inner;
 }
 
 static HRESULT WINAPI QT_QueryInterface(IBaseFilter *iface, REFIID riid, LPVOID *ppv)
diff --git a/include/wine/strmbase.h b/include/wine/strmbase.h
index e192e98..87396fd 100644
--- a/include/wine/strmbase.h
+++ b/include/wine/strmbase.h
@@ -154,18 +154,20 @@ HRESULT WINAPI BaseInputPin_Destroy(BaseInputPin *This);
 
 typedef struct BaseFilter
 {
-	IBaseFilter IBaseFilter_iface;
-	LONG refCount;
-	CRITICAL_SECTION csFilter;
+    IBaseFilter IBaseFilter_iface;
+    IUnknown IUnknown_inner;
+    IUnknown *outer_unk;
+    LONG refcount;
+    CRITICAL_SECTION csFilter;
 
-	FILTER_STATE state;
-	REFERENCE_TIME rtStreamStart;
-	IReferenceClock * pClock;
-	FILTER_INFO filterInfo;
-	CLSID clsid;
-        LONG pin_version;
+    FILTER_STATE state;
+    REFERENCE_TIME rtStreamStart;
+    IReferenceClock * pClock;
+    FILTER_INFO filterInfo;
+    CLSID clsid;
+    LONG pin_version;
 
-	const struct BaseFilterFuncTable* pFuncsTable;
+    const struct BaseFilterFuncTable* pFuncsTable;
 } BaseFilter;
 
 typedef struct BaseFilterFuncTable
@@ -190,7 +192,7 @@ HRESULT WINAPI BaseFilterImpl_QueryVendorInfo(IBaseFilter * iface, LPWSTR *pVend
 
 VOID WINAPI BaseFilterImpl_IncrementPinVersion(BaseFilter* This);
 
-void BaseFilter_Init(BaseFilter *filter, const IBaseFilterVtbl *vtbl,
+void strmbase_filter_init(BaseFilter *filter, const IBaseFilterVtbl *vtbl, IUnknown *outer,
         const CLSID *clsid, DWORD_PTR debug_info, const BaseFilterFuncTable *func_table);
 void strmbase_filter_cleanup(BaseFilter *filter);
 
-- 
2.7.4




More information about the wine-devel mailing list