[PATCH 5/5] qasf/dmowrapper: Add an initial implementation of IDMOWrapperFilter::Init().

Zebediah Figura z.figura12 at gmail.com
Mon Feb 17 17:30:59 CST 2020


From: Zebediah Figura <zfigura at codeweavers.com>

Signed-off-by: Zebediah Figura <zfigura at codeweavers.com>
---
 dlls/qasf/Makefile.in        |   2 +-
 dlls/qasf/dmowrapper.c       |  26 ++-
 dlls/qasf/tests/Makefile.in  |   2 +-
 dlls/qasf/tests/dmowrapper.c | 307 +++++++++++++++++++++++++++++++++++
 4 files changed, 332 insertions(+), 5 deletions(-)

diff --git a/dlls/qasf/Makefile.in b/dlls/qasf/Makefile.in
index 7ca314e20ba..c1d34a42dab 100644
--- a/dlls/qasf/Makefile.in
+++ b/dlls/qasf/Makefile.in
@@ -1,5 +1,5 @@
 MODULE    = qasf.dll
-IMPORTS   = strmbase dmoguids strmiids uuid
+IMPORTS   = strmbase dmoguids strmiids uuid ole32
 
 EXTRADLLFLAGS = -mno-cygwin
 
diff --git a/dlls/qasf/dmowrapper.c b/dlls/qasf/dmowrapper.c
index d4547d4ba30..1f11c9ff7ef 100644
--- a/dlls/qasf/dmowrapper.c
+++ b/dlls/qasf/dmowrapper.c
@@ -26,6 +26,8 @@ struct dmo_wrapper
 {
     struct strmbase_filter filter;
     IDMOWrapperFilter IDMOWrapperFilter_iface;
+
+    IUnknown *dmo;
 };
 
 static inline struct dmo_wrapper *impl_from_strmbase_filter(struct strmbase_filter *iface)
@@ -58,9 +60,23 @@ static ULONG WINAPI dmo_wrapper_filter_Release(IDMOWrapperFilter *iface)
 
 static HRESULT WINAPI dmo_wrapper_filter_Init(IDMOWrapperFilter *iface, REFCLSID clsid, REFCLSID category)
 {
-    FIXME("iface %p, clsid %s, category %s, stub!\n",
-            iface, wine_dbgstr_guid(clsid), wine_dbgstr_guid(category));
-    return E_NOTIMPL;
+    struct dmo_wrapper *filter = impl_from_IDMOWrapperFilter(iface);
+    IUnknown *unk;
+    HRESULT hr;
+
+    TRACE("filter %p, clsid %s, category %s.\n", filter, debugstr_guid(clsid), debugstr_guid(category));
+
+    if (FAILED(hr = CoCreateInstance(clsid, &filter->filter.IUnknown_inner,
+            CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&unk)))
+        return hr;
+
+    EnterCriticalSection(&filter->filter.csFilter);
+
+    filter->dmo = unk;
+
+    LeaveCriticalSection(&filter->filter.csFilter);
+
+    return S_OK;
 }
 
 static const IDMOWrapperFilterVtbl dmo_wrapper_filter_vtbl =
@@ -80,6 +96,8 @@ static void dmo_wrapper_destroy(struct strmbase_filter *iface)
 {
     struct dmo_wrapper *filter = impl_from_strmbase_filter(iface);
 
+    if (filter->dmo)
+        IUnknown_Release(filter->dmo);
     strmbase_filter_cleanup(&filter->filter);
     free(filter);
 }
@@ -95,6 +113,8 @@ static HRESULT dmo_wrapper_query_interface(struct strmbase_filter *iface, REFIID
         return S_OK;
     }
 
+    if (filter->dmo && !IsEqualGUID(iid, &IID_IUnknown))
+        return IUnknown_QueryInterface(filter->dmo, iid, out);
     return E_NOINTERFACE;
 }
 
diff --git a/dlls/qasf/tests/Makefile.in b/dlls/qasf/tests/Makefile.in
index dd04f4b438f..47bb22e78ab 100644
--- a/dlls/qasf/tests/Makefile.in
+++ b/dlls/qasf/tests/Makefile.in
@@ -1,5 +1,5 @@
 TESTDLL   = qasf.dll
-IMPORTS   = dmoguids strmiids uuid ole32
+IMPORTS   = dmoguids strmiids uuid msdmo ole32
 
 C_SRCS = \
 	dmowrapper.c
diff --git a/dlls/qasf/tests/dmowrapper.c b/dlls/qasf/tests/dmowrapper.c
index e061ca24177..9345b91a178 100644
--- a/dlls/qasf/tests/dmowrapper.c
+++ b/dlls/qasf/tests/dmowrapper.c
@@ -24,14 +24,286 @@
 #include "dmodshow.h"
 #include "wine/test.h"
 
+static const GUID testdmo_clsid = {0x1234};
 static const GUID test_iid = {0x33333333};
 
+static const IMediaObjectVtbl dmo_vtbl;
+
+static IMediaObject testdmo = {&dmo_vtbl};
+static IUnknown *testdmo_outer_unk;
+static LONG testdmo_refcount = 1;
+
+static HRESULT WINAPI dmo_inner_QueryInterface(IUnknown *iface, REFIID iid, void **out)
+{
+    if (winetest_debug > 1) trace("QueryInterface(%s)\n", wine_dbgstr_guid(iid));
+
+    if (IsEqualGUID(iid, &IID_IUnknown))
+        *out = iface;
+    else if (IsEqualGUID(iid, &IID_IMediaObject) || IsEqualGUID(iid, &test_iid))
+        *out = &testdmo;
+    else
+        return E_NOINTERFACE;
+
+    IUnknown_AddRef((IUnknown *)*out);
+    return S_OK;
+}
+
+static ULONG WINAPI dmo_inner_AddRef(IUnknown *iface)
+{
+    return InterlockedIncrement(&testdmo_refcount);
+}
+
+static ULONG WINAPI dmo_inner_Release(IUnknown *iface)
+{
+    return InterlockedDecrement(&testdmo_refcount);
+}
+
+static const IUnknownVtbl dmo_inner_vtbl =
+{
+    dmo_inner_QueryInterface,
+    dmo_inner_AddRef,
+    dmo_inner_Release,
+};
+
+static IUnknown testdmo_inner = {&dmo_inner_vtbl};
+
+static HRESULT WINAPI dmo_QueryInterface(IMediaObject *iface, REFIID iid, void **out)
+{
+    return IUnknown_QueryInterface(testdmo_outer_unk, iid, out);
+}
+
+static ULONG WINAPI dmo_AddRef(IMediaObject *iface)
+{
+    return IUnknown_AddRef(testdmo_outer_unk);
+}
+
+static ULONG WINAPI dmo_Release(IMediaObject *iface)
+{
+    return IUnknown_Release(testdmo_outer_unk);
+}
+
+static HRESULT WINAPI dmo_GetStreamCount(IMediaObject *iface, DWORD *input, DWORD *output)
+{
+    if (winetest_debug > 1) trace("GetStreamCount()\n");
+    *input = 1;
+    *output = 2;
+    return S_OK;
+}
+
+static HRESULT WINAPI dmo_GetInputStreamInfo(IMediaObject *iface, DWORD index, DWORD *flags)
+{
+    ok(0, "Unexpected call.\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI dmo_GetOutputStreamInfo(IMediaObject *iface, DWORD index, DWORD *flags)
+{
+    if (winetest_debug > 1) trace("GetOutputStreamInfo(%u)\n", index);
+    *flags = 0;
+    return S_OK;
+}
+
+static HRESULT WINAPI dmo_GetInputType(IMediaObject *iface, DWORD index, DWORD type_index, DMO_MEDIA_TYPE *type)
+{
+    ok(0, "Unexpected call.\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI dmo_GetOutputType(IMediaObject *iface, DWORD index, DWORD type_index, DMO_MEDIA_TYPE *type)
+{
+    ok(0, "Unexpected call.\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI dmo_SetInputType(IMediaObject *iface, DWORD index, const DMO_MEDIA_TYPE *type, DWORD flags)
+{
+    ok(0, "Unexpected call.\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI dmo_SetOutputType(IMediaObject *iface, DWORD index, const DMO_MEDIA_TYPE *type, DWORD flags)
+{
+    ok(0, "Unexpected call.\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI dmo_GetInputCurrentType(IMediaObject *iface, DWORD index, DMO_MEDIA_TYPE *type)
+{
+    ok(0, "Unexpected call.\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI dmo_GetOutputCurrentType(IMediaObject *iface, DWORD index, DMO_MEDIA_TYPE *type)
+{
+    ok(0, "Unexpected call.\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI dmo_GetInputSizeInfo(IMediaObject *iface, DWORD index,
+        DWORD *size, DWORD *lookahead, DWORD *align)
+{
+    ok(0, "Unexpected call.\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI dmo_GetOutputSizeInfo(IMediaObject *iface, DWORD index, DWORD *size, DWORD *alignment)
+{
+    ok(0, "Unexpected call.\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI dmo_GetInputMaxLatency(IMediaObject *iface, DWORD index, REFERENCE_TIME *latency)
+{
+    ok(0, "Unexpected call.\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI dmo_SetInputMaxLatency(IMediaObject *iface, DWORD index, REFERENCE_TIME latency)
+{
+    ok(0, "Unexpected call.\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI dmo_Flush(IMediaObject *iface)
+{
+    ok(0, "Unexpected call.\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI dmo_Discontinuity(IMediaObject *iface, DWORD index)
+{
+    ok(0, "Unexpected call.\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI dmo_AllocateStreamingResources(IMediaObject *iface)
+{
+    ok(0, "Unexpected call.\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI dmo_FreeStreamingResources(IMediaObject *iface)
+{
+    ok(0, "Unexpected call.\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI dmo_GetInputStatus(IMediaObject *iface, DWORD index, DWORD *flags)
+{
+    ok(0, "Unexpected call.\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI dmo_ProcessInput(IMediaObject *iface, DWORD index,
+    IMediaBuffer *buffer, DWORD flags, REFERENCE_TIME timestamp, REFERENCE_TIME timelength)
+{
+    ok(0, "Unexpected call.\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI dmo_ProcessOutput(IMediaObject *iface, DWORD flags,
+        DWORD count, DMO_OUTPUT_DATA_BUFFER *buffers, DWORD *status)
+{
+    ok(0, "Unexpected call.\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI dmo_Lock(IMediaObject *iface, LONG lock)
+{
+    ok(0, "Unexpected call.\n");
+    return E_NOTIMPL;
+}
+
+static const IMediaObjectVtbl dmo_vtbl =
+{
+    dmo_QueryInterface,
+    dmo_AddRef,
+    dmo_Release,
+    dmo_GetStreamCount,
+    dmo_GetInputStreamInfo,
+    dmo_GetOutputStreamInfo,
+    dmo_GetInputType,
+    dmo_GetOutputType,
+    dmo_SetInputType,
+    dmo_SetOutputType,
+    dmo_GetInputCurrentType,
+    dmo_GetOutputCurrentType,
+    dmo_GetInputSizeInfo,
+    dmo_GetOutputSizeInfo,
+    dmo_GetInputMaxLatency,
+    dmo_SetInputMaxLatency,
+    dmo_Flush,
+    dmo_Discontinuity,
+    dmo_AllocateStreamingResources,
+    dmo_FreeStreamingResources,
+    dmo_GetInputStatus,
+    dmo_ProcessInput,
+    dmo_ProcessOutput,
+    dmo_Lock,
+};
+
+static HRESULT WINAPI dmo_cf_QueryInterface(IClassFactory *iface, REFIID iid, void **out)
+{
+    if (IsEqualGUID(iid, &IID_IUnknown) || IsEqualGUID(iid, &IID_IClassFactory))
+    {
+        *out = iface;
+        return S_OK;
+    }
+    return E_NOINTERFACE;
+}
+
+static ULONG WINAPI dmo_cf_AddRef(IClassFactory *iface)
+{
+    return 2;
+}
+
+static ULONG WINAPI dmo_cf_Release(IClassFactory *iface)
+{
+    return 1;
+}
+
+static HRESULT WINAPI dmo_cf_CreateInstance(IClassFactory *iface, IUnknown *outer, REFIID iid, void **out)
+{
+    ok(!!outer, "Expected to be created aggregated.\n");
+    ok(IsEqualGUID(iid, &IID_IUnknown), "Got unexpected iid %s.\n", wine_dbgstr_guid(iid));
+
+    *out = &testdmo_inner;
+    IUnknown_AddRef(&testdmo_inner);
+    testdmo_outer_unk = outer;
+    return S_OK;
+}
+
+static HRESULT WINAPI dmo_cf_LockServer(IClassFactory *iface, BOOL lock)
+{
+    ok(0, "Unexpected call.\n");
+    return S_OK;
+}
+
+static const IClassFactoryVtbl dmo_cf_vtbl =
+{
+    dmo_cf_QueryInterface,
+    dmo_cf_AddRef,
+    dmo_cf_Release,
+    dmo_cf_CreateInstance,
+    dmo_cf_LockServer,
+};
+
+static IClassFactory testdmo_cf = {&dmo_cf_vtbl};
+
 static IBaseFilter *create_dmo_wrapper(void)
 {
+    IDMOWrapperFilter *wrapper;
     IBaseFilter *filter = NULL;
     HRESULT hr = CoCreateInstance(&CLSID_DMOWrapperFilter, NULL,
             CLSCTX_INPROC_SERVER, &IID_IBaseFilter, (void **)&filter);
     ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+    hr = IBaseFilter_QueryInterface(filter, &IID_IDMOWrapperFilter, (void **)&wrapper);
+    ok(hr == S_OK, "Got hr %#x.\n", hr);
+    hr = IDMOWrapperFilter_Init(wrapper, &testdmo_clsid, &DMOCATEGORY_AUDIO_DECODER);
+    ok(hr == S_OK, "Got hr %#x.\n", hr);
+    IDMOWrapperFilter_Release(wrapper);
+
     return filter;
 }
 
@@ -169,14 +441,49 @@ static void test_aggregation(void)
     IBaseFilter_Release(filter);
     ref = IUnknown_Release(unk);
     ok(!ref, "Got unexpected refcount %d.\n", ref);
+
+    /* Test also aggregation of the inner media object. */
+
+    filter = create_dmo_wrapper();
+
+    hr = IBaseFilter_QueryInterface(filter, &IID_IMediaObject, (void **)&unk);
+    ok(hr == S_OK, "Got hr %#x.\n", hr);
+    ok(unk == (IUnknown *)&testdmo, "Got unexpected object %p.\n", unk);
+    IUnknown_Release(unk);
+
+    hr = IBaseFilter_QueryInterface(filter, &test_iid, (void **)&unk);
+    ok(hr == S_OK, "Got hr %#x.\n", hr);
+    ok(unk == (IUnknown *)&testdmo, "Got unexpected object %p.\n", unk);
+    IUnknown_Release(unk);
+
+    ref = IBaseFilter_Release(filter);
+    ok(!ref, "Got unexpected refcount %d.\n", ref);
 }
 
 START_TEST(dmowrapper)
 {
+    DWORD cookie;
+    HRESULT hr;
+
     CoInitializeEx(NULL, COINIT_MULTITHREADED);
 
+    hr = DMORegister(L"Wine test DMO", &testdmo_clsid, &DMOCATEGORY_AUDIO_DECODER, 0, 0, NULL, 0, NULL);
+    if (FAILED(hr))
+    {
+        skip("Failed to register DMO, hr %#x.\n", hr);
+        return;
+    }
+    ok(hr == S_OK, "Failed to register class, hr %#x.\n", hr);
+
+    hr = CoRegisterClassObject(&testdmo_clsid, (IUnknown *)&testdmo_cf,
+            CLSCTX_INPROC_SERVER, REGCLS_MULTIPLEUSE, &cookie);
+    ok(hr == S_OK, "Failed to register class, hr %#x.\n", hr);
+
     test_interfaces();
     test_aggregation();
 
+    CoRevokeClassObject(cookie);
+    DMOUnregister(&testdmo_clsid, &DMOCATEGORY_AUDIO_DECODER);
+
     CoUninitialize();
 }
-- 
2.25.0




More information about the wine-devel mailing list