[resend PATCH 1/3] winegstreamer: Add stub Video Processor MFT.

Nikolay Sivov nsivov at codeweavers.com
Fri Jul 5 04:40:01 CDT 2019


Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---

First time this was dropped because of test failure presumably, probably because of
tests relation to changed module wasn't obvious to testbot or something like that.
It works fine for me locally however, including starting with clean prefix.

 dlls/mf/tests/mf.c               |  25 +-
 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, 513 insertions(+), 6 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..8c1b0c294e 100644
--- a/dlls/mf/tests/mf.c
+++ b/dlls/mf/tests/mf.c
@@ -2079,7 +2079,6 @@ 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))
@@ -2120,12 +2119,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 +2138,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 +2183,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 +2264,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 +2293,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 +2321,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 +2339,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 { }
-- 
2.20.1




More information about the wine-devel mailing list