[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