Signed-off-by: Nikolay Sivov nsivov@codeweavers.com ---
v2: skip tests on failure
dlls/mf/tests/mf.c | 30 ++- dlls/winegstreamer/Makefile.in | 7 +- dlls/winegstreamer/gst_private.h | 3 + dlls/winegstreamer/main.c | 14 +- dlls/winegstreamer/mfplat.c | 444 +++++++++++++++++++++++++++++++ dlls/winegstreamer/mfplat.idl | 26 ++ 6 files changed, 516 insertions(+), 8 deletions(-) create mode 100644 dlls/winegstreamer/mfplat.c create mode 100644 dlls/winegstreamer/mfplat.idl
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index 15aa58620a..0d66da1392 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -2079,11 +2079,11 @@ static void test_video_processor(void)
hr = CoCreateInstance(&CLSID_VideoProcessorMFT, NULL, CLSCTX_INPROC_SERVER, &IID_IMFTransform, (void **)&transform); -todo_wine - ok(hr == S_OK || broken(hr == REGDB_E_CLASSNOTREG), "Failed to create video processor transform, hr %#x.\n", hr); - if (FAILED(hr)) + { + skip("Failed to create Video Processor instance, skipping tests.\n"); goto failed; + }
hr = IMFTransform_QueryInterface(transform, &IID_IMFMediaEventGenerator, (void **)&unk); ok(hr == E_NOINTERFACE, "Unexpected hr %#x.\n", hr); @@ -2120,12 +2120,14 @@ todo_wine ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
hr = IMFTransform_GetInputStatus(transform, 0, &flags); +todo_wine ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#x.\n", hr);
hr = IMFTransform_GetInputStreamAttributes(transform, 0, &attributes); ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
hr = IMFTransform_GetOutputStatus(transform, &flags); +todo_wine ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#x.\n", hr);
hr = IMFTransform_GetOutputStreamAttributes(transform, 0, &attributes); @@ -2137,30 +2139,38 @@ todo_wine IMFAttributes_Release(attributes2);
hr = IMFTransform_GetOutputAvailableType(transform, 0, 0, &media_type); +todo_wine ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#x.\n", hr);
hr = IMFTransform_GetInputCurrentType(transform, 0, &media_type); +todo_wine ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#x.\n", hr);
hr = IMFTransform_GetInputCurrentType(transform, 1, &media_type); +todo_wine ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#x.\n", hr);
hr = IMFTransform_GetOutputCurrentType(transform, 0, &media_type); +todo_wine ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#x.\n", hr);
hr = IMFTransform_GetOutputCurrentType(transform, 1, &media_type); +todo_wine ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#x.\n", hr);
hr = IMFTransform_GetInputStreamInfo(transform, 1, &input_info); +todo_wine ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#x.\n", hr);
+ memset(&input_info, 0xcc, sizeof(input_info)); hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info); +todo_wine { ok(hr == S_OK, "Failed to get stream info, hr %#x.\n", hr); ok(input_info.dwFlags == 0, "Unexpected flag %#x.\n", input_info.dwFlags); ok(input_info.cbSize == 0, "Unexpected size %u.\n", input_info.cbSize); ok(input_info.cbMaxLookahead == 0, "Unexpected lookahead length %u.\n", input_info.cbMaxLookahead); ok(input_info.cbAlignment == 0, "Unexpected alignment %u.\n", input_info.cbAlignment); - +} hr = MFCreateMediaEvent(MEUnknown, &GUID_NULL, S_OK, NULL, &event); ok(hr == S_OK, "Failed to create event object, hr %#x.\n", hr); hr = IMFTransform_ProcessEvent(transform, 0, event); @@ -2174,6 +2184,7 @@ todo_wine { if (FAILED(hr = IMFTransform_GetInputAvailableType(transform, 0, i, &media_type))) { + todo_wine ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#x.\n", hr); break; } @@ -2254,17 +2265,22 @@ todo_wine ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
hr = IMFTransform_SetInputType(transform, 0, media_type, 0); +todo_wine ok(hr == S_OK, "Failed to set input type, hr %#x.\n", hr);
hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFVideoFormat_RGB32); ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
hr = IMFTransform_SetOutputType(transform, 0, media_type, 0); +todo_wine ok(hr == S_OK, "Failed to set output type, hr %#x.\n", hr);
+ memset(&output_info, 0, sizeof(output_info)); hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info); +todo_wine ok(hr == S_OK, "Failed to get stream info, hr %#x.\n", hr); ok(output_info.dwFlags == 0, "Unexpected flags %#x.\n", output_info.dwFlags); +todo_wine ok(output_info.cbSize > 0, "Unexpected size %u.\n", output_info.cbSize); ok(output_info.cbAlignment == 0, "Unexpected alignment %u.\n", output_info.cbAlignment);
@@ -2278,20 +2294,24 @@ todo_wine output_buffer.pSample = sample; flags = 0; hr = IMFTransform_ProcessOutput(transform, 0, 1, &output_buffer, &flags); +todo_wine ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "Unexpected hr %#x.\n", hr); ok(output_buffer.dwStatus == 0, "Unexpected buffer status, %#x.\n", output_buffer.dwStatus); ok(flags == 0, "Unexpected status %#x.\n", flags);
hr = IMFTransform_ProcessInput(transform, 0, sample2, 0); +todo_wine ok(hr == S_OK, "Failed to push a sample, hr %#x.\n", hr);
hr = IMFTransform_ProcessInput(transform, 0, sample2, 0); +todo_wine ok(hr == MF_E_NOTACCEPTING, "Unexpected hr %#x.\n", hr);
memset(&output_buffer, 0, sizeof(output_buffer)); output_buffer.pSample = sample; flags = 0; hr = IMFTransform_ProcessOutput(transform, 0, 1, &output_buffer, &flags); +todo_wine ok(hr == MF_E_NO_SAMPLE_TIMESTAMP, "Unexpected hr %#x.\n", hr); ok(output_buffer.dwStatus == 0, "Unexpected buffer status, %#x.\n", output_buffer.dwStatus); ok(flags == 0, "Unexpected status %#x.\n", flags); @@ -2302,6 +2322,7 @@ todo_wine output_buffer.pSample = sample; flags = 0; hr = IMFTransform_ProcessOutput(transform, 0, 1, &output_buffer, &flags); +todo_wine ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr); ok(output_buffer.dwStatus == 0, "Unexpected buffer status, %#x.\n", output_buffer.dwStatus); ok(flags == 0, "Unexpected status %#x.\n", flags); @@ -2319,6 +2340,7 @@ todo_wine output_buffer.pSample = sample; flags = 0; hr = IMFTransform_ProcessOutput(transform, 0, 1, &output_buffer, &flags); +todo_wine ok(hr == S_OK || broken(FAILED(hr)) /* Win8 */, "Failed to get output buffer, hr %#x.\n", hr); ok(output_buffer.dwStatus == 0, "Unexpected buffer status, %#x.\n", output_buffer.dwStatus); ok(flags == 0, "Unexpected status %#x.\n", flags); diff --git a/dlls/winegstreamer/Makefile.in b/dlls/winegstreamer/Makefile.in index fecabe8ba2..437915f6da 100644 --- a/dlls/winegstreamer/Makefile.in +++ b/dlls/winegstreamer/Makefile.in @@ -1,5 +1,5 @@ MODULE = winegstreamer.dll -IMPORTS = strmbase strmiids uuid winmm msacm32 msvfw32 ole32 oleaut32 user32 gdi32 advapi32 +IMPORTS = strmbase strmiids uuid winmm msacm32 msvfw32 ole32 oleaut32 user32 gdi32 advapi32 mfplat mfuuid EXTRAINCL = $(GSTREAMER_CFLAGS) EXTRALIBS = $(GSTREAMER_LIBS) $(PTHREAD_LIBS)
@@ -7,7 +7,10 @@ C_SRCS = \ gst_cbs.c \ gstdemux.c \ gsttffilter.c \ - main.c + main.c \ + mfplat.c + +IDL_SRCS = mfplat.idl
RC_SRCS = \ rsrc.rc diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h index 85659c4bd9..06236e2636 100644 --- a/dlls/winegstreamer/gst_private.h +++ b/dlls/winegstreamer/gst_private.h @@ -53,4 +53,7 @@ void start_dispatch_thread(void) DECLSPEC_HIDDEN;
extern const char *media_quark_string DECLSPEC_HIDDEN;
+extern HRESULT mfplat_get_class_object(REFCLSID rclsid, REFIID riid, void **obj) DECLSPEC_HIDDEN; +extern HRESULT mfplat_can_unload_now(void) DECLSPEC_HIDDEN; + #endif /* __GST_PRIVATE_INCLUDED__ */ diff --git a/dlls/winegstreamer/main.c b/dlls/winegstreamer/main.c index f11e59a914..4419a6fde5 100644 --- a/dlls/winegstreamer/main.c +++ b/dlls/winegstreamer/main.c @@ -232,7 +232,12 @@ BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv) */ HRESULT WINAPI DllCanUnloadNow(void) { - return STRMBASE_DllCanUnloadNow(); + HRESULT hr = STRMBASE_DllCanUnloadNow(); + + if (hr == S_OK) + hr = mfplat_can_unload_now(); + + return hr; }
/*********************************************************************** @@ -240,7 +245,12 @@ HRESULT WINAPI DllCanUnloadNow(void) */ HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv) { - return STRMBASE_DllGetClassObject( rclsid, riid, ppv ); + HRESULT hr; + + if (FAILED(hr = mfplat_get_class_object(rclsid, riid, ppv))) + hr = STRMBASE_DllGetClassObject( rclsid, riid, ppv ); + + return hr; }
/* GStreamer common functions */ diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c new file mode 100644 index 0000000000..2233bbe159 --- /dev/null +++ b/dlls/winegstreamer/mfplat.c @@ -0,0 +1,444 @@ +/* + * Copyright 2019 Nikolay Sivov for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include <stdarg.h> + +#define COBJMACROS +#define NONAMELESSUNION + +#include "mfapi.h" +#include "mfidl.h" + +#include "wine/debug.h" +#include "wine/heap.h" + +WINE_DEFAULT_DEBUG_CHANNEL(mfplat); + +static LONG object_locks; + +struct video_processor +{ + IMFTransform IMFTransform_iface; + LONG refcount; + IMFAttributes *attributes; + IMFAttributes *output_attributes; +}; + +static struct video_processor *impl_video_processor_from_IMFTransform(IMFTransform *iface) +{ + return CONTAINING_RECORD(iface, struct video_processor, IMFTransform_iface); +} + +static HRESULT WINAPI video_processor_QueryInterface(IMFTransform *iface, REFIID riid, void **obj) +{ + TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj); + + if (IsEqualIID(riid, &IID_IMFTransform) || + IsEqualIID(riid, &IID_IUnknown)) + { + *obj = iface; + IMFTransform_AddRef(iface); + return S_OK; + } + + WARN("Unsupported %s.\n", debugstr_guid(riid)); + *obj = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI video_processor_AddRef(IMFTransform *iface) +{ + struct video_processor *transform = impl_video_processor_from_IMFTransform(iface); + ULONG refcount = InterlockedIncrement(&transform->refcount); + + TRACE("%p, refcount %u.\n", iface, refcount); + + return refcount; +} + +static ULONG WINAPI video_processor_Release(IMFTransform *iface) +{ + struct video_processor *transform = impl_video_processor_from_IMFTransform(iface); + ULONG refcount = InterlockedDecrement(&transform->refcount); + + TRACE("%p, refcount %u.\n", iface, refcount); + + if (!refcount) + { + if (transform->attributes) + IMFAttributes_Release(transform->attributes); + if (transform->output_attributes) + IMFAttributes_Release(transform->output_attributes); + heap_free(transform); + } + + return refcount; +} + +static HRESULT WINAPI video_processor_GetStreamLimits(IMFTransform *iface, DWORD *input_minimum, DWORD *input_maximum, + DWORD *output_minimum, DWORD *output_maximum) +{ + TRACE("%p, %p, %p, %p, %p.\n", iface, input_minimum, input_maximum, output_minimum, output_maximum); + + *input_minimum = *input_maximum = *output_minimum = *output_maximum = 1; + + return S_OK; +} + +static HRESULT WINAPI video_processor_GetStreamCount(IMFTransform *iface, DWORD *inputs, DWORD *outputs) +{ + TRACE("%p, %p, %p.\n", iface, inputs, outputs); + + *inputs = *outputs = 1; + + return S_OK; +} + +static HRESULT WINAPI video_processor_GetStreamIDs(IMFTransform *iface, DWORD input_size, DWORD *inputs, + DWORD output_size, DWORD *outputs) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI video_processor_GetInputStreamInfo(IMFTransform *iface, DWORD id, MFT_INPUT_STREAM_INFO *info) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI video_processor_GetOutputStreamInfo(IMFTransform *iface, DWORD id, MFT_OUTPUT_STREAM_INFO *info) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI video_processor_GetAttributes(IMFTransform *iface, IMFAttributes **attributes) +{ + struct video_processor *transform = impl_video_processor_from_IMFTransform(iface); + + TRACE("%p, %p.\n", iface, attributes); + + *attributes = transform->attributes; + IMFAttributes_AddRef(*attributes); + + return S_OK; +} + +static HRESULT WINAPI video_processor_GetInputStreamAttributes(IMFTransform *iface, DWORD id, + IMFAttributes **attributes) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI video_processor_GetOutputStreamAttributes(IMFTransform *iface, DWORD id, + IMFAttributes **attributes) +{ + struct video_processor *transform = impl_video_processor_from_IMFTransform(iface); + + TRACE("%p, %u, %p.\n", iface, id, attributes); + + *attributes = transform->output_attributes; + IMFAttributes_AddRef(*attributes); + + return S_OK; +} + +static HRESULT WINAPI video_processor_DeleteInputStream(IMFTransform *iface, DWORD id) +{ + TRACE("%p, %u.\n", iface, id); + + return E_NOTIMPL; +} + +static HRESULT WINAPI video_processor_AddInputStreams(IMFTransform *iface, DWORD streams, DWORD *ids) +{ + TRACE("%p, %u, %p.\n", iface, streams, ids); + + return E_NOTIMPL; +} + +static HRESULT WINAPI video_processor_GetInputAvailableType(IMFTransform *iface, DWORD id, DWORD index, + IMFMediaType **type) +{ + FIXME("%p, %u, %u, %p.\n", iface, id, index, type); + + return E_NOTIMPL; +} + +static HRESULT WINAPI video_processor_GetOutputAvailableType(IMFTransform *iface, DWORD id, DWORD index, + IMFMediaType **type) +{ + FIXME("%p, %u, %u, %p.\n", iface, id, index, type); + + return E_NOTIMPL; +} + +static HRESULT WINAPI video_processor_SetInputType(IMFTransform *iface, DWORD id, IMFMediaType *type, DWORD flags) +{ + FIXME("%p, %u, %p, %#x.\n", iface, id, type, flags); + + return E_NOTIMPL; +} + +static HRESULT WINAPI video_processor_SetOutputType(IMFTransform *iface, DWORD id, IMFMediaType *type, DWORD flags) +{ + FIXME("%p, %u, %p, %#x.\n", iface, id, type, flags); + + return E_NOTIMPL; +} + +static HRESULT WINAPI video_processor_GetInputCurrentType(IMFTransform *iface, DWORD id, IMFMediaType **type) +{ + FIXME("%p, %u, %p.\n", iface, id, type); + + return E_NOTIMPL; +} + +static HRESULT WINAPI video_processor_GetOutputCurrentType(IMFTransform *iface, DWORD id, IMFMediaType **type) +{ + FIXME("%p, %u, %p.\n", iface, id, type); + + return E_NOTIMPL; +} + +static HRESULT WINAPI video_processor_GetInputStatus(IMFTransform *iface, DWORD id, DWORD *flags) +{ + FIXME("%p, %u, %p.\n", iface, id, flags); + + return E_NOTIMPL; +} + +static HRESULT WINAPI video_processor_GetOutputStatus(IMFTransform *iface, DWORD *flags) +{ + FIXME("%p, %p.\n", iface, flags); + + return E_NOTIMPL; +} + +static HRESULT WINAPI video_processor_SetOutputBounds(IMFTransform *iface, LONGLONG lower, LONGLONG upper) +{ + FIXME("%p, %s, %s.\n", iface, wine_dbgstr_longlong(lower), wine_dbgstr_longlong(upper)); + + return E_NOTIMPL; +} + +static HRESULT WINAPI video_processor_ProcessEvent(IMFTransform *iface, DWORD id, IMFMediaEvent *event) +{ + TRACE("%p, %u, %p.\n", iface, id, event); + + return E_NOTIMPL; +} + +static HRESULT WINAPI video_processor_ProcessMessage(IMFTransform *iface, MFT_MESSAGE_TYPE message, ULONG_PTR param) +{ + FIXME("%p, %u.\n", iface, message); + + return E_NOTIMPL; +} + +static HRESULT WINAPI video_processor_ProcessInput(IMFTransform *iface, DWORD id, IMFSample *sample, DWORD flags) +{ + FIXME("%p, %u, %p, %#x.\n", iface, id, sample, flags); + + return E_NOTIMPL; +} + +static HRESULT WINAPI video_processor_ProcessOutput(IMFTransform *iface, DWORD flags, DWORD count, + MFT_OUTPUT_DATA_BUFFER *samples, DWORD *status) +{ + FIXME("%p, %#x, %u, %p, %p.\n", iface, flags, count, samples, status); + + return E_NOTIMPL; +} + +static const IMFTransformVtbl video_processor_vtbl = +{ + video_processor_QueryInterface, + video_processor_AddRef, + video_processor_Release, + video_processor_GetStreamLimits, + video_processor_GetStreamCount, + video_processor_GetStreamIDs, + video_processor_GetInputStreamInfo, + video_processor_GetOutputStreamInfo, + video_processor_GetAttributes, + video_processor_GetInputStreamAttributes, + video_processor_GetOutputStreamAttributes, + video_processor_DeleteInputStream, + video_processor_AddInputStreams, + video_processor_GetInputAvailableType, + video_processor_GetOutputAvailableType, + video_processor_SetInputType, + video_processor_SetOutputType, + video_processor_GetInputCurrentType, + video_processor_GetOutputCurrentType, + video_processor_GetInputStatus, + video_processor_GetOutputStatus, + video_processor_SetOutputBounds, + video_processor_ProcessEvent, + video_processor_ProcessMessage, + video_processor_ProcessInput, + video_processor_ProcessOutput, +}; + +struct class_factory +{ + IClassFactory IClassFactory_iface; + LONG refcount; + HRESULT (*create_instance)(REFIID riid, void **obj); +}; + +static struct class_factory *impl_from_IClassFactory(IClassFactory *iface) +{ + return CONTAINING_RECORD(iface, struct class_factory, IClassFactory_iface); +} + +static HRESULT WINAPI class_factory_QueryInterface(IClassFactory *iface, REFIID riid, void **obj) +{ + TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj); + + if (IsEqualGUID(riid, &IID_IClassFactory) || + IsEqualGUID(riid, &IID_IUnknown)) + { + *obj = iface; + IClassFactory_AddRef(iface); + return S_OK; + } + + WARN("%s is not supported.\n", debugstr_guid(riid)); + *obj = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI class_factory_AddRef(IClassFactory *iface) +{ + struct class_factory *factory = impl_from_IClassFactory(iface); + return InterlockedIncrement(&factory->refcount); +} + +static ULONG WINAPI class_factory_Release(IClassFactory *iface) +{ + struct class_factory *factory = impl_from_IClassFactory(iface); + ULONG refcount = InterlockedDecrement(&factory->refcount); + + if (!refcount) + heap_free(factory); + + return refcount; +} + +static HRESULT WINAPI class_factory_CreateInstance(IClassFactory *iface, IUnknown *outer, REFIID riid, void **obj) +{ + struct class_factory *factory = impl_from_IClassFactory(iface); + + TRACE("%p, %p, %s, %p.\n", iface, outer, debugstr_guid(riid), obj); + + if (outer) + { + *obj = NULL; + return CLASS_E_NOAGGREGATION; + } + + return factory->create_instance(riid, obj); +} + +static HRESULT WINAPI class_factory_LockServer(IClassFactory *iface, BOOL dolock) +{ + TRACE("%p, %d.\n", iface, dolock); + + if (dolock) + InterlockedIncrement(&object_locks); + else + InterlockedDecrement(&object_locks); + + return S_OK; +} + +static const IClassFactoryVtbl class_factory_vtbl = +{ + class_factory_QueryInterface, + class_factory_AddRef, + class_factory_Release, + class_factory_CreateInstance, + class_factory_LockServer, +}; + +static HRESULT video_processor_create(REFIID riid, void **ret) +{ + struct video_processor *object; + HRESULT hr; + + if (!(object = heap_alloc_zero(sizeof(*object)))) + return E_OUTOFMEMORY; + + object->IMFTransform_iface.lpVtbl = &video_processor_vtbl; + object->refcount = 1; + + if (FAILED(hr = MFCreateAttributes(&object->attributes, 0))) + goto failed; + + if (FAILED(hr = MFCreateAttributes(&object->output_attributes, 0))) + goto failed; + + *ret = &object->IMFTransform_iface; + return S_OK; + +failed: + + IMFTransform_Release(&object->IMFTransform_iface); + return hr; +} + +static const struct class_object +{ + const GUID *clsid; + HRESULT (*create_instance)(REFIID riid, void **obj); +} +class_objects[] = +{ + { &CLSID_VideoProcessorMFT, &video_processor_create }, +}; + +HRESULT mfplat_get_class_object(REFCLSID rclsid, REFIID riid, void **obj) +{ + struct class_factory *factory; + unsigned int i; + HRESULT hr; + + for (i = 0; i < ARRAY_SIZE(class_objects); ++i) + { + if (IsEqualGUID(class_objects[i].clsid, rclsid)) + { + if (!(factory = heap_alloc(sizeof(*factory)))) + return E_OUTOFMEMORY; + + factory->IClassFactory_iface.lpVtbl = &class_factory_vtbl; + factory->refcount = 1; + factory->create_instance = class_objects[i].create_instance; + + hr = IClassFactory_QueryInterface(&factory->IClassFactory_iface, riid, obj); + IClassFactory_Release(&factory->IClassFactory_iface); + return hr; + } + } + + return CLASS_E_CLASSNOTAVAILABLE; +} + +HRESULT mfplat_can_unload_now(void) +{ + return !object_locks ? S_OK : S_FALSE; +} diff --git a/dlls/winegstreamer/mfplat.idl b/dlls/winegstreamer/mfplat.idl new file mode 100644 index 0000000000..05a75bdb8e --- /dev/null +++ b/dlls/winegstreamer/mfplat.idl @@ -0,0 +1,26 @@ +/* + * Copyright 2019 Nikolay Sivov for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#pragma makedep register + +[ + threading(both), + uuid(88753b26-5b24-49bd-b2e7-0c445c78c982) + +] +coclass VideoProcessorMFT { }