Signed-off-by: Nikolay Sivov nsivov@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 { }
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mf/session.c | 15 +++++++++++++-- dlls/mf/tests/mf.c | 48 +++++++++++++++++++++++++++++++++++++--------- 2 files changed, 52 insertions(+), 11 deletions(-)
diff --git a/dlls/mf/session.c b/dlls/mf/session.c index c43e6d2838..1a36933883 100644 --- a/dlls/mf/session.c +++ b/dlls/mf/session.c @@ -68,6 +68,7 @@ struct media_session LONG refcount; IMFMediaEventQueue *event_queue; IMFPresentationClock *clock; + IMFRateControl *clock_rate_control; struct list topologies; enum session_state state; CRITICAL_SECTION cs; @@ -315,6 +316,8 @@ static ULONG WINAPI mfsession_Release(IMFMediaSession *iface) IMFMediaEventQueue_Release(session->event_queue); if (session->clock) IMFPresentationClock_Release(session->clock); + if (session->clock_rate_control) + IMFRateControl_Release(session->clock_rate_control); DeleteCriticalSection(&session->cs); heap_free(session); } @@ -723,9 +726,11 @@ static HRESULT WINAPI session_rate_control_SetRate(IMFRateControl *iface, BOOL t
static HRESULT WINAPI session_rate_control_GetRate(IMFRateControl *iface, BOOL *thin, float *rate) { - FIXME("%p, %p, %p.\n", iface, thin, rate); + struct media_session *session = impl_session_from_IMFRateControl(iface);
- return E_NOTIMPL; + TRACE("%p, %p, %p.\n", iface, thin, rate); + + return IMFRateControl_GetRate(session->clock_rate_control, thin, rate); }
static const IMFRateControlVtbl session_rate_control_vtbl = @@ -769,6 +774,12 @@ HRESULT WINAPI MFCreateMediaSession(IMFAttributes *config, IMFMediaSession **ses if (FAILED(hr = MFCreatePresentationClock(&object->clock))) goto failed;
+ if (FAILED(hr = IMFPresentationClock_QueryInterface(object->clock, &IID_IMFRateControl, + (void **)&object->clock_rate_control))) + { + goto failed; + } + *session = &object->IMFMediaSession_iface;
return S_OK; diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index 8c1b0c294e..5f848b152f 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -951,14 +951,16 @@ static void test_session_events(IMFMediaSession *session)
static void test_media_session(void) { + IMFRateControl *rate_control, *rate_control2; MFCLOCK_PROPERTIES clock_props; + IMFRateSupport *rate_support; IMFMediaSession *session; - IMFRateControl *rc, *rc2; - IMFRateSupport *rs; IMFGetService *gs; IMFClock *clock; IUnknown *unk; HRESULT hr; + float rate; + BOOL thin;
hr = MFStartup(MF_VERSION, MFSTARTUP_FULL); ok(hr == S_OK, "Startup failure, hr %#x.\n", hr); @@ -972,29 +974,57 @@ static void test_media_session(void) hr = IMFMediaSession_QueryInterface(session, &IID_IMFGetService, (void **)&gs); ok(hr == S_OK, "Failed to get interface, hr %#x.\n", hr);
- hr = IMFGetService_GetService(gs, &MF_RATE_CONTROL_SERVICE, &IID_IMFRateSupport, (void **)&rs); + hr = IMFGetService_GetService(gs, &MF_RATE_CONTROL_SERVICE, &IID_IMFRateSupport, (void **)&rate_support); ok(hr == S_OK, "Failed to get rate support interface, hr %#x.\n", hr);
- hr = IMFGetService_GetService(gs, &MF_RATE_CONTROL_SERVICE, &IID_IMFRateControl, (void **)&rc); + hr = IMFGetService_GetService(gs, &MF_RATE_CONTROL_SERVICE, &IID_IMFRateControl, (void **)&rate_control); ok(hr == S_OK, "Failed to get rate control interface, hr %#x.\n", hr);
- hr = IMFRateSupport_QueryInterface(rs, &IID_IMFMediaSession, (void **)&unk); + hr = IMFRateSupport_QueryInterface(rate_support, &IID_IMFMediaSession, (void **)&unk); ok(hr == S_OK, "Failed to get session interface, hr %#x.\n", hr); ok(unk == (IUnknown *)session, "Unexpected pointer.\n"); IUnknown_Release(unk);
+ hr = IMFRateControl_GetRate(rate_control, NULL, NULL); + ok(FAILED(hr), "Unexpected hr %#x.\n", hr); + + rate = 0.0f; + hr = IMFRateControl_GetRate(rate_control, NULL, &rate); + ok(hr == S_OK, "Failed to get playback rate, hr %#x.\n", hr); + ok(rate == 1.0f, "Unexpected rate %f.\n", rate); + + hr = IMFRateControl_GetRate(rate_control, &thin, NULL); + ok(FAILED(hr), "Unexpected hr %#x.\n", hr); + + thin = TRUE; + rate = 0.0f; + hr = IMFRateControl_GetRate(rate_control, &thin, &rate); + ok(hr == S_OK, "Failed to get playback rate, hr %#x.\n", hr); + ok(!thin, "Unexpected thinning.\n"); + ok(rate == 1.0f, "Unexpected rate %f.\n", rate); + hr = IMFMediaSession_GetClock(session, &clock); ok(hr == S_OK, "Failed to get clock, hr %#x.\n", hr);
- hr = IMFClock_QueryInterface(clock, &IID_IMFRateControl, (void **)&rc2); + hr = IMFClock_QueryInterface(clock, &IID_IMFRateControl, (void **)&rate_control2); ok(hr == S_OK, "Failed to get rate control, hr %#x.\n", hr); - IMFRateControl_Release(rc2); + + rate = 0.0f; + hr = IMFRateControl_GetRate(rate_control2, NULL, &rate); + ok(hr == S_OK, "Failed to get clock rate, hr %#x.\n", hr); + ok(rate == 1.0f, "Unexpected rate %f.\n", rate); + + hr = IMFRateControl_SetRate(rate_control, FALSE, 1.5f); +todo_wine + ok(hr == S_OK, "Failed to set rate, hr %#x.\n", hr); + + IMFRateControl_Release(rate_control2);
hr = IMFClock_GetProperties(clock, &clock_props); ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#x.\n", hr);
- IMFRateControl_Release(rc); - IMFRateSupport_Release(rs); + IMFRateControl_Release(rate_control); + IMFRateSupport_Release(rate_support);
IMFGetService_Release(gs);
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=54507
Your paranoid android.
=== wvistau64_he (32 bit report) ===
mf: mf.c:917: Test failed: Unexpected hr 0xc00d36da. mf.c:921: Test failed: Unexpected hr 0. mf.c:937: Test failed: Unexpected return value 0x102.
=== w7pro64 (32 bit report) ===
mf: mf.c:917: Test failed: Unexpected hr 0xc00d36da. mf.c:921: Test failed: Unexpected hr 0. mf.c:937: Test failed: Unexpected return value 0x102.
=== w8 (32 bit report) ===
mf: mf.c:917: Test failed: Unexpected hr 0xc00d36da. mf.c:921: Test failed: Unexpected hr 0xc00d36da.
=== w8adm (32 bit report) ===
mf: mf.c:917: Test failed: Unexpected hr 0xc00d36da. mf.c:921: Test failed: Unexpected hr 0. mf.c:937: Test failed: Unexpected return value 0x102.
=== w864 (32 bit report) ===
mf: mf.c:917: Test failed: Unexpected hr 0xc00d36da. mf.c:921: Test failed: Unexpected hr 0. mf.c:937: Test failed: Unexpected return value 0x102.
=== w1064v1507 (32 bit report) ===
mf: mf.c:917: Test failed: Unexpected hr 0xc00d36da. mf.c:921: Test failed: Unexpected hr 0. mf.c:937: Test failed: Unexpected return value 0x102.
=== w7pro64 (64 bit report) ===
mf: mf.c:917: Test failed: Unexpected hr 0xc00d36da. mf.c:921: Test failed: Unexpected hr 0. mf.c:937: Test failed: Unexpected return value 0x102.
=== w864 (64 bit report) ===
mf: mf.c:906: Test failed: Unexpected hr 0.
=== w1064v1507 (64 bit report) ===
mf: mf.c:917: Test failed: Unexpected hr 0xc00d36da. mf.c:921: Test failed: Unexpected hr 0. mf.c:937: Test failed: Unexpected return value 0x102.
=== w1064v1809 (64 bit report) ===
mf: mf.c:917: Test failed: Unexpected hr 0xc00d36da. mf.c:921: Test failed: Unexpected hr 0xc00d36da.
=== debian9 (32 bit report) ===
mf: mf.c:2112: Test failed: Failed to create video processor transform, hr 0x80040154.
=== debian9 (32 bit French report) ===
mf: mf.c:2112: Test failed: Failed to create video processor transform, hr 0x80040154.
=== debian9 (32 bit Japanese:Japan report) ===
mf: mf.c:2112: Test failed: Failed to create video processor transform, hr 0x80040154.
=== debian9 (32 bit Chinese:China report) ===
mf: mf.c:2112: Test failed: Failed to create video processor transform, hr 0x80040154.
=== debian9 (32 bit WoW report) ===
mf: mf.c:2112: Test failed: Failed to create video processor transform, hr 0x80040154.
=== debian9 (64 bit WoW report) ===
mf: mf.c:2112: Test failed: Failed to create video processor transform, hr 0x80040154.
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mf/session.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/dlls/mf/session.c b/dlls/mf/session.c index 1a36933883..1276f2ec92 100644 --- a/dlls/mf/session.c +++ b/dlls/mf/session.c @@ -681,7 +681,7 @@ static HRESULT WINAPI session_rate_support_GetFastestRate(IMFRateSupport *iface, return E_NOTIMPL; }
-static HRESULT WINAPI session_rate_support_IsSupported(IMFRateSupport *iface, BOOL thin, float rate, +static HRESULT WINAPI session_rate_support_IsRateSupported(IMFRateSupport *iface, BOOL thin, float rate, float *nearest_supported_rate) { FIXME("%p, %d, %f, %p.\n", iface, thin, rate, nearest_supported_rate); @@ -696,7 +696,7 @@ static const IMFRateSupportVtbl session_rate_support_vtbl = session_rate_support_Release, session_rate_support_GetSlowestRate, session_rate_support_GetFastestRate, - session_rate_support_IsSupported, + session_rate_support_IsRateSupported, };
static HRESULT WINAPI session_rate_control_QueryInterface(IMFRateControl *iface, REFIID riid, void **obj)
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=54508
Your paranoid android.
=== debian9 (32 bit report) ===
mf: mf.c:2112: Test failed: Failed to create video processor transform, hr 0x80040154.
=== debian9 (32 bit Chinese:China report) ===
mf: mf.c:2112: Test failed: Failed to create video processor transform, hr 0x80040154.
=== debian9 (32 bit WoW report) ===
mf: mf.c:2112: Test failed: Failed to create video processor transform, hr 0x80040154.
=== debian9 (64 bit WoW report) ===
mf: mf.c:2112: Test failed: Failed to create video processor transform, hr 0x80040154.
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=54506
Your paranoid android.
=== debian9 (32 bit report) ===
mf: mf.c:2082: Test failed: Failed to create video processor transform, hr 0x80040154.
=== debian9 (32 bit French report) ===
mf: mf.c:2082: Test failed: Failed to create video processor transform, hr 0x80040154.
=== debian9 (32 bit Japanese:Japan report) ===
mf: mf.c:2082: Test failed: Failed to create video processor transform, hr 0x80040154.
=== debian9 (32 bit Chinese:China report) ===
mf: mf.c:2082: Test failed: Failed to create video processor transform, hr 0x80040154.
=== debian9 (32 bit WoW report) ===
mf: mf.c:2082: Test failed: Failed to create video processor transform, hr 0x80040154.
=== debian9 (64 bit WoW report) ===
mf: mf.c:2082: Test failed: Failed to create video processor transform, hr 0x80040154.
Nikolay Sivov nsivov@codeweavers.com writes:
Signed-off-by: Nikolay Sivov nsivov@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.
Well, it fails anywhere that gstreamer isn't installed, which means pretty much any 32-bit build (including mine).
On 7/5/19 1:54 PM, Alexandre Julliard wrote:
Nikolay Sivov nsivov@codeweavers.com writes:
Signed-off-by: Nikolay Sivov nsivov@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.
Well, it fails anywhere that gstreamer isn't installed, which means pretty much any 32-bit build (including mine).
Ok, I thought we're treating such cases as broken builds essentially, I'll skip them.