[PATCH 4/5] evr: Add aggregation support for default mixer object.

Nikolay Sivov nsivov at codeweavers.com
Wed Jul 1 07:55:45 CDT 2020


Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
 dlls/evr/mixer.c     | 58 +++++++++++++++++++++++++++++++++++---------
 dlls/evr/tests/evr.c | 17 +++++++++++++
 2 files changed, 63 insertions(+), 12 deletions(-)

diff --git a/dlls/evr/mixer.c b/dlls/evr/mixer.c
index 23994375d45..c8bd300b0d3 100644
--- a/dlls/evr/mixer.c
+++ b/dlls/evr/mixer.c
@@ -60,6 +60,8 @@ struct video_mixer
     IMFVideoMixerBitmap IMFVideoMixerBitmap_iface;
     IMFVideoPositionMapper IMFVideoPositionMapper_iface;
     IMFVideoProcessor IMFVideoProcessor_iface;
+    IUnknown IUnknown_inner;
+    IUnknown *outer_unk;
     LONG refcount;
 
     struct input_stream inputs[MAX_MIXER_INPUT_STREAMS];
@@ -74,6 +76,11 @@ struct video_mixer
     CRITICAL_SECTION cs;
 };
 
+static struct video_mixer *impl_from_IUnknown(IUnknown *iface)
+{
+    return CONTAINING_RECORD(iface, struct video_mixer, IUnknown_inner);
+}
+
 static struct video_mixer *impl_from_IMFTransform(IMFTransform *iface)
 {
     return CONTAINING_RECORD(iface, struct video_mixer, IMFTransform_iface);
@@ -155,17 +162,20 @@ static void video_mixer_clear_types(struct video_mixer *mixer)
     mixer->output.media_type = NULL;
 }
 
-static HRESULT WINAPI video_mixer_transform_QueryInterface(IMFTransform *iface, REFIID riid, void **obj)
+static HRESULT WINAPI video_mixer_inner_QueryInterface(IUnknown *iface, REFIID riid, void **obj)
 {
-    struct video_mixer *mixer = impl_from_IMFTransform(iface);
+    struct video_mixer *mixer = impl_from_IUnknown(iface);
 
     TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
 
-    if (IsEqualIID(riid, &IID_IMFTransform) ||
-            IsEqualIID(riid, &IID_IUnknown))
+    if (IsEqualIID(riid, &IID_IUnknown))
     {
         *obj = iface;
     }
+    else if (IsEqualIID(riid, &IID_IMFTransform))
+    {
+        *obj = &mixer->IMFTransform_iface;
+    }
     else if (IsEqualIID(riid, &IID_IMFVideoDeviceID))
     {
         *obj = &mixer->IMFVideoDeviceID_iface;
@@ -206,9 +216,9 @@ static HRESULT WINAPI video_mixer_transform_QueryInterface(IMFTransform *iface,
     return S_OK;
 }
 
-static ULONG WINAPI video_mixer_transform_AddRef(IMFTransform *iface)
+static ULONG WINAPI video_mixer_inner_AddRef(IUnknown *iface)
 {
-    struct video_mixer *mixer = impl_from_IMFTransform(iface);
+    struct video_mixer *mixer = impl_from_IUnknown(iface);
     ULONG refcount = InterlockedIncrement(&mixer->refcount);
 
     TRACE("%p, refcount %u.\n", iface, refcount);
@@ -216,9 +226,9 @@ static ULONG WINAPI video_mixer_transform_AddRef(IMFTransform *iface)
     return refcount;
 }
 
-static ULONG WINAPI video_mixer_transform_Release(IMFTransform *iface)
+static ULONG WINAPI video_mixer_inner_Release(IUnknown *iface)
 {
-    struct video_mixer *mixer = impl_from_IMFTransform(iface);
+    struct video_mixer *mixer = impl_from_IUnknown(iface);
     ULONG refcount = InterlockedDecrement(&mixer->refcount);
     unsigned int i;
 
@@ -241,6 +251,31 @@ static ULONG WINAPI video_mixer_transform_Release(IMFTransform *iface)
     return refcount;
 }
 
+static const IUnknownVtbl video_mixer_inner_vtbl =
+{
+    video_mixer_inner_QueryInterface,
+    video_mixer_inner_AddRef,
+    video_mixer_inner_Release,
+};
+
+static HRESULT WINAPI video_mixer_transform_QueryInterface(IMFTransform *iface, REFIID riid, void **obj)
+{
+    struct video_mixer *mixer = impl_from_IMFTransform(iface);
+    return IUnknown_QueryInterface(mixer->outer_unk, riid, obj);
+}
+
+static ULONG WINAPI video_mixer_transform_AddRef(IMFTransform *iface)
+{
+    struct video_mixer *mixer = impl_from_IMFTransform(iface);
+    return IUnknown_AddRef(mixer->outer_unk);
+}
+
+static ULONG WINAPI video_mixer_transform_Release(IMFTransform *iface)
+{
+    struct video_mixer *mixer = impl_from_IMFTransform(iface);
+    return IUnknown_Release(mixer->outer_unk);
+}
+
 static HRESULT WINAPI video_mixer_transform_GetStreamLimits(IMFTransform *iface, DWORD *input_minimum,
         DWORD *input_maximum, DWORD *output_minimum, DWORD *output_maximum)
 {
@@ -1251,9 +1286,6 @@ HRESULT evr_mixer_create(IUnknown *outer, void **out)
 {
     struct video_mixer *object;
 
-    if (outer)
-        return E_NOINTERFACE;
-
     if (!(object = calloc(1, sizeof(*object))))
         return E_OUTOFMEMORY;
 
@@ -1265,12 +1297,14 @@ HRESULT evr_mixer_create(IUnknown *outer, void **out)
     object->IMFVideoMixerBitmap_iface.lpVtbl = &video_mixer_bitmap_vtbl;
     object->IMFVideoPositionMapper_iface.lpVtbl = &video_mixer_position_mapper_vtbl;
     object->IMFVideoProcessor_iface.lpVtbl = &video_mixer_processor_vtbl;
+    object->IUnknown_inner.lpVtbl = &video_mixer_inner_vtbl;
+    object->outer_unk = outer ? outer : &object->IUnknown_inner;
     object->refcount = 1;
     object->input_count = 1;
     video_mixer_init_input(&object->inputs[0]);
     InitializeCriticalSection(&object->cs);
 
-    *out = &object->IMFTransform_iface;
+    *out = &object->IUnknown_inner;
 
     return S_OK;
 }
diff --git a/dlls/evr/tests/evr.c b/dlls/evr/tests/evr.c
index dd3fbbe0289..1046e70312d 100644
--- a/dlls/evr/tests/evr.c
+++ b/dlls/evr/tests/evr.c
@@ -119,6 +119,7 @@ static void test_aggregation(void)
     IBaseFilter *filter, *filter2;
     IMFVideoPresenter *presenter;
     IUnknown *unk, *unk2;
+    IMFTransform *mixer;
     HRESULT hr;
     ULONG ref;
 
@@ -191,6 +192,22 @@ static void test_aggregation(void)
 
         IUnknown_Release(unk);
     }
+
+    /* Default mixer. */
+    presenter = (void *)0xdeadbeef;
+    hr = CoCreateInstance(&CLSID_MFVideoMixer9, &test_outer, CLSCTX_INPROC_SERVER, &IID_IMFTransform,
+            (void **)&mixer);
+    ok(hr == E_NOINTERFACE, "Unexpected hr %#x.\n", hr);
+    ok(!mixer, "Got interface %p.\n", mixer);
+
+    hr = CoCreateInstance(&CLSID_MFVideoMixer9, &test_outer, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&unk);
+    ok(hr == S_OK, "Unexpected 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);
+    ok(ref == 1, "Got unexpected refcount %d.\n", ref);
+
+    IUnknown_Release(unk);
 }
 
 #define check_interface(a, b, c) check_interface_(__LINE__, a, b, c)
-- 
2.27.0




More information about the wine-devel mailing list