Signed-off-by: Derek Lesho dlesho@codeweavers.com --- v3: - Rebase against 133ba763e1f419dc23fd58ac82c6d8a73014ae22. - Remove accidental inclusion of test.mp3. --- dlls/mf/tests/Makefile.in | 2 - dlls/mf/tests/mf.c | 601 +++++++++++++++++++++++++++++++------- dlls/mf/tests/resource.rc | 22 -- 3 files changed, 499 insertions(+), 126 deletions(-) delete mode 100644 dlls/mf/tests/resource.rc
diff --git a/dlls/mf/tests/Makefile.in b/dlls/mf/tests/Makefile.in index 5eb9ee4d4e3..614eb4fbc9e 100644 --- a/dlls/mf/tests/Makefile.in +++ b/dlls/mf/tests/Makefile.in @@ -3,5 +3,3 @@ IMPORTS = mf mfplat mfuuid ole32 user32
C_SRCS = \ mf.c - -RC_SRCS = resource.rc diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index fda80974724..092735466be 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -44,6 +44,7 @@ DEFINE_GUID(MFVideoFormat_ABGR32, 0x00000020, 0x0000, 0x0010, 0x80, 0x00, 0x00, #include "mmdeviceapi.h" #include "audioclient.h" #include "evr.h" +#include "propvarutil.h"
#include "wine/test.h"
@@ -97,34 +98,6 @@ static HWND create_window(void) 0, 0, r.right - r.left, r.bottom - r.top, NULL, NULL, NULL, NULL); }
-static WCHAR *load_resource(const WCHAR *name) -{ - static WCHAR pathW[MAX_PATH]; - DWORD written; - HANDLE file; - HRSRC res; - void *ptr; - - GetTempPathW(ARRAY_SIZE(pathW), pathW); - lstrcatW(pathW, name); - - file = CreateFileW(pathW, GENERIC_READ|GENERIC_WRITE, 0, - NULL, CREATE_ALWAYS, 0, 0); - ok(file != INVALID_HANDLE_VALUE, "file creation failed, at %s, error %d\n", - wine_dbgstr_w(pathW), GetLastError()); - - res = FindResourceW(NULL, name, (LPCWSTR)RT_RCDATA); - ok(res != 0, "couldn't find resource\n"); - ptr = LockResource(LoadResource(GetModuleHandleA(NULL), res)); - WriteFile(file, ptr, SizeofResource(GetModuleHandleA(NULL), res), - &written, NULL); - ok(written == SizeofResource(GetModuleHandleA(NULL), res), - "couldn't write resource\n" ); - CloseHandle(file); - - return pathW; -} - static HRESULT WINAPI test_unk_QueryInterface(IUnknown *iface, REFIID riid, void **obj) { if (IsEqualIID(riid, &IID_IUnknown)) @@ -1447,26 +1420,316 @@ static const IMFSampleGrabberSinkCallbackVtbl test_grabber_callback_vtbl = test_grabber_callback_OnShutdown, };
+struct test_source +{ + IMFMediaSource IMFMediaSource_iface; + LONG refcount; +}; + +static struct test_source *impl_from_IMFMediaSource(IMFMediaSource *iface) +{ + return CONTAINING_RECORD(iface, struct test_source, IMFMediaSource_iface); +} + +static HRESULT WINAPI test_source_QueryInterface(IMFMediaSource *iface, REFIID riid, void **out) +{ + if (IsEqualIID(riid, &IID_IMFMediaSource) + || IsEqualIID(riid, &IID_IMFMediaEventGenerator) + || IsEqualIID(riid, &IID_IUnknown)) + { + *out = iface; + } + else + { + *out = NULL; + return E_NOINTERFACE; + } + + IMFMediaSource_AddRef(iface); + return S_OK; +} + +static ULONG WINAPI test_source_AddRef(IMFMediaSource *iface) +{ + struct test_source *source = impl_from_IMFMediaSource(iface); + return InterlockedIncrement(&source->refcount); +} + +static ULONG WINAPI test_source_Release(IMFMediaSource *iface) +{ + struct test_source *source = impl_from_IMFMediaSource(iface); + ULONG refcount = InterlockedDecrement(&source->refcount); + + if (!refcount) + HeapFree(GetProcessHeap(), 0, source); + + return refcount; +} + +static HRESULT WINAPI test_source_GetEvent(IMFMediaSource *iface, DWORD flags, IMFMediaEvent **event) +{ + ok(0, "Unexpected call.\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI test_source_BeginGetEvent(IMFMediaSource *iface, IMFAsyncCallback *callback, IUnknown *state) +{ + ok(0, "Unexpected call.\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI test_source_EndGetEvent(IMFMediaSource *iface, IMFAsyncResult *result, IMFMediaEvent **event) +{ + ok(0, "Unexpected call.\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI test_source_QueueEvent(IMFMediaSource *iface, MediaEventType event_type, REFGUID ext_type, + HRESULT hr, const PROPVARIANT *value) +{ + ok(0, "Unexpected call.\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI test_source_GetCharacteristics(IMFMediaSource *iface, DWORD *flags) +{ + ok(0, "Unexpected call.\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI test_source_CreatePresentationDescriptor(IMFMediaSource *iface, IMFPresentationDescriptor **pd) +{ + ok(0, "Unexpected call.\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI test_source_Start(IMFMediaSource *iface, IMFPresentationDescriptor *pd, const GUID *time_format, + const PROPVARIANT *start_position) +{ + ok(0, "Unexpected call.\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI test_source_Stop(IMFMediaSource *iface) +{ + ok(0, "Unexpected call.\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI test_source_Pause(IMFMediaSource *iface) +{ + ok(0, "Unexpected call.\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI test_source_Shutdown(IMFMediaSource *iface) +{ + ok(0, "Unexpected call.\n"); + return E_NOTIMPL; +} + +static const IMFMediaSourceVtbl test_source_vtbl = +{ + test_source_QueryInterface, + test_source_AddRef, + test_source_Release, + test_source_GetEvent, + test_source_BeginGetEvent, + test_source_EndGetEvent, + test_source_QueueEvent, + test_source_GetCharacteristics, + test_source_CreatePresentationDescriptor, + test_source_Start, + test_source_Stop, + test_source_Pause, + test_source_Shutdown, +}; + +static IMFMediaSource *create_test_source(void) +{ + struct test_source *source; + + source = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*source)); + source->IMFMediaSource_iface.lpVtbl = &test_source_vtbl; + source->refcount = 1; + + return &source->IMFMediaSource_iface; +} + static void test_topology_loader(void) { + static const struct resolution_test + { + union + { + WAVEFORMATEX input_type; + MPEGLAYER3WAVEFORMAT mp3_input_type; + }; + WAVEFORMATEX output_type; + MF_CONNECT_METHOD method; + HRESULT expected_result; + BOOL expect_decoder, expect_converter, wine_todo; + } + resolution_tests[] = + { + { + .input_type = { + .wFormatTag = WAVE_FORMAT_PCM, .nChannels = 1, .nSamplesPerSec = 44100, + .nAvgBytesPerSec = 44100, .nBlockAlign = 1, .wBitsPerSample = 8, .cbSize = 0, + }, + .output_type = { + .wFormatTag = WAVE_FORMAT_PCM, .nChannels = 1, .nSamplesPerSec = 44100, + .nAvgBytesPerSec = 44100, .nBlockAlign = 1, .wBitsPerSample = 8, .cbSize = 0, + }, + .method = MF_CONNECT_DIRECT, + .expected_result = S_OK, + .expect_decoder = FALSE, + .expect_converter = FALSE, + .wine_todo = FALSE, + }, + { + .input_type = { + .wFormatTag = WAVE_FORMAT_PCM, .nChannels = 1, .nSamplesPerSec = 44100, + .nAvgBytesPerSec = 44100, .nBlockAlign = 1, .wBitsPerSample = 8, .cbSize = 0, + }, + .output_type = { + .wFormatTag = WAVE_FORMAT_PCM, .nChannels = 1, .nSamplesPerSec = 48000, + .nAvgBytesPerSec = 48000, .nBlockAlign = 1, .wBitsPerSample = 8, .cbSize = 0, + }, + .method = MF_CONNECT_DIRECT, + .expected_result = MF_E_INVALIDMEDIATYPE, + .expect_decoder = FALSE, + .expect_converter = FALSE, + .wine_todo = FALSE, + }, + { + .input_type = { + .wFormatTag = WAVE_FORMAT_PCM, .nChannels = 1, .nSamplesPerSec = 44100, + .nAvgBytesPerSec = 44100, .nBlockAlign = 1, .wBitsPerSample = 8, .cbSize = 0, + }, + .output_type = { + .wFormatTag = WAVE_FORMAT_PCM, .nChannels = 1, .nSamplesPerSec = 48000, + .nAvgBytesPerSec = 48000, .nBlockAlign = 1, .wBitsPerSample = 8, .cbSize = 0, + }, + .method = MF_CONNECT_ALLOW_CONVERTER, + .expected_result = S_OK, + .expect_decoder = FALSE, + .expect_converter = TRUE, + .wine_todo = TRUE, + }, + /* Test MF_TOPONODE_CONNECT_METHOD: + - 0x1 (MF_CONNECT_ALLOW_CONVERTER) allows converters + - 0x3 (MF_CONNECT_ALLOW_DECODER) allows converters and decoders + - 0x2 allows neither */ + { + .mp3_input_type = { + { + .wFormatTag = WAVE_FORMAT_MPEGLAYER3, .nChannels = 2, .nSamplesPerSec = 44100, + .nAvgBytesPerSec = 16000, .nBlockAlign = 1, .wBitsPerSample = 0, .cbSize = MPEGLAYER3_WFX_EXTRA_BYTES, + }, + .wID = MPEGLAYER3_ID_MPEG, + .fdwFlags = 0, + .nBlockSize = 417, + .nFramesPerBlock = 0, + .nCodecDelay = 0, + }, + .output_type = { + .wFormatTag = WAVE_FORMAT_PCM, .nChannels = 1, .nSamplesPerSec = 44100, + .nAvgBytesPerSec = 44100, .nBlockAlign = 1, .wBitsPerSample = 8, .cbSize = 0, + }, + .method = MF_CONNECT_DIRECT, + .expected_result = MF_E_INVALIDMEDIATYPE, + .expect_decoder = FALSE, + .expect_converter = FALSE, + .wine_todo = TRUE, + }, + { + .mp3_input_type = { + { + .wFormatTag = WAVE_FORMAT_MPEGLAYER3, .nChannels = 2, .nSamplesPerSec = 44100, + .nAvgBytesPerSec = 16000, .nBlockAlign = 1, .wBitsPerSample = 0, .cbSize = MPEGLAYER3_WFX_EXTRA_BYTES, + }, + .wID = MPEGLAYER3_ID_MPEG, + .fdwFlags = 0, + .nBlockSize = 417, + .nFramesPerBlock = 0, + .nCodecDelay = 0, + }, + .output_type = { + .wFormatTag = WAVE_FORMAT_PCM, .nChannels = 2, .nSamplesPerSec = 44100, + .nAvgBytesPerSec = 44100, .nBlockAlign = 1, .wBitsPerSample = 8, .cbSize = 0, + }, + .method = MF_CONNECT_ALLOW_CONVERTER, + .expected_result = MF_E_TRANSFORM_NOT_POSSIBLE_FOR_CURRENT_MEDIATYPE_COMBINATION, + .expect_decoder = FALSE, + .expect_converter = FALSE, + .wine_todo = TRUE, + }, + { + .mp3_input_type = { + { + .wFormatTag = WAVE_FORMAT_MPEGLAYER3, .nChannels = 2, .nSamplesPerSec = 44100, + .nAvgBytesPerSec = 16000, .nBlockAlign = 1, .wBitsPerSample = 0, .cbSize = MPEGLAYER3_WFX_EXTRA_BYTES, + }, + .wID = MPEGLAYER3_ID_MPEG, + .fdwFlags = 0, + .nBlockSize = 417, + .nFramesPerBlock = 0, + .nCodecDelay = 0, + }, + .output_type = { + .wFormatTag = WAVE_FORMAT_PCM, .nChannels = 2, .nSamplesPerSec = 44100, + .nAvgBytesPerSec = 44100, .nBlockAlign = 1, .wBitsPerSample = 8, .cbSize = 0, + }, + .method = 2, + .expected_result = MF_E_INVALIDMEDIATYPE, + .expect_decoder = FALSE, + .expect_converter = FALSE, + .wine_todo = TRUE, + }, + { + .mp3_input_type = { + { + .wFormatTag = WAVE_FORMAT_MPEGLAYER3, .nChannels = 2, .nSamplesPerSec = 44100, + .nAvgBytesPerSec = 16000, .nBlockAlign = 1, .wBitsPerSample = 0, .cbSize = MPEGLAYER3_WFX_EXTRA_BYTES, + }, + .wID = MPEGLAYER3_ID_MPEG, + .fdwFlags = 0, + .nBlockSize = 417, + .nFramesPerBlock = 0, + .nCodecDelay = 0, + }, + .output_type = { + .wFormatTag = WAVE_FORMAT_PCM, .nChannels = 1, .nSamplesPerSec = 44100, + .nAvgBytesPerSec = 44100, .nBlockAlign = 1, .wBitsPerSample = 8, .cbSize = 0, + }, + .method = MF_CONNECT_ALLOW_DECODER, + .expected_result = S_OK, + .expect_decoder = TRUE, + .expect_converter = FALSE, + .wine_todo = TRUE, + }, + }; + IMFSampleGrabberSinkCallback test_grabber_callback = { &test_grabber_callback_vtbl }; + IMFTopologyNode *src_node, *sink_node, *src_node2, *sink_node2, *mft_node; IMFTopology *topology, *topology2, *full_topology; - IMFTopologyNode *src_node, *sink_node; + unsigned int count, value, index; IMFPresentationDescriptor *pd; - IMFSourceResolver *resolver; IMFActivate *sink_activate; IMFStreamSink *stream_sink; - unsigned int count, value; + MF_TOPOLOGY_TYPE node_type; IMFMediaType *media_type; IMFStreamDescriptor *sd; - MF_OBJECT_TYPE obj_type; + IMFTransform *transform; IMFMediaSource *source; IMFTopoLoader *loader; - IMFByteStream *stream; - IMFAttributes *attr; + IUnknown *node_object; + BOOL compare_result; IMFMediaSink *sink; - WCHAR *filename; - BOOL selected; + WORD node_count; + unsigned int i; + TOPOID node_id; HRESULT hr; GUID guid;
@@ -1487,44 +1750,41 @@ static void test_topology_loader(void) todo_wine ok(hr == MF_E_TOPO_UNSUPPORTED, "Unexpected hr %#x.\n", hr);
- hr = MFCreateSourceResolver(&resolver); - ok(hr == S_OK, "Failed to create source resolver, hr %#x.\n", hr); + /* Add source node. */ + hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &src_node); + ok(hr == S_OK, "Failed to create topology node, hr %#x.\n", hr);
- filename = load_resource(L"test.wav"); + /* when a decoder is involved, windows requires this attribute to be present */ + source = create_test_source();
- hr = MFCreateFile(MF_ACCESSMODE_READ, MF_OPENMODE_FAIL_IF_NOT_EXIST, MF_FILEFLAGS_NONE, filename, &stream); - ok(hr == S_OK, "Failed to create file stream, hr %#x.\n", hr); + hr = IMFTopologyNode_SetUnknown(src_node, &MF_TOPONODE_SOURCE, (IUnknown *)source); + ok(hr == S_OK, "Failed to set node source, hr %#x.\n", hr);
- IMFByteStream_QueryInterface(stream, &IID_IMFAttributes, (void **)&attr); - IMFAttributes_SetString(attr, &MF_BYTESTREAM_CONTENT_TYPE, L"audio/wav"); - IMFAttributes_Release(attr); + IMFMediaSource_Release(source);
- hr = IMFSourceResolver_CreateObjectFromByteStream(resolver, stream, NULL, MF_RESOLUTION_MEDIASOURCE, NULL, - &obj_type, (IUnknown **)&source); - ok(hr == S_OK || broken(FAILED(hr)) /* Vista */, "Failed to create source, hr %#x.\n", hr); - if (FAILED(hr)) - return; + hr = MFCreateMediaType(&media_type); + ok(hr == S_OK, "Failed to create media type, hr %#x.\n", hr);
- hr = IMFMediaSource_CreatePresentationDescriptor(source, &pd); - ok(hr == S_OK, "Failed to create descriptor, hr %#x.\n", hr); - if (FAILED(hr)) - return; + hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio); + ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr); + hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFAudioFormat_PCM); + ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
- hr = IMFPresentationDescriptor_GetStreamDescriptorByIndex(pd, 0, &selected, &sd); - ok(hr == S_OK, "Failed to get stream descriptor, hr %#x.\n", hr); + hr = MFCreateStreamDescriptor(0, 1, &media_type, &sd); + ok(hr == S_OK, "Failed to create stream descriptor, hr %#x.\n");
- /* Add source node. */ - hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &src_node); - ok(hr == S_OK, "Failed to create topology node, hr %#x.\n", hr); + hr = IMFTopologyNode_SetUnknown(src_node, &MF_TOPONODE_STREAM_DESCRIPTOR, (IUnknown *)sd); + ok(hr == S_OK, "Failed to set node sd, hr %#x.\n", hr);
- hr = IMFTopologyNode_SetUnknown(src_node, &MF_TOPONODE_SOURCE, (IUnknown *)source); - ok(hr == S_OK, "Failed to set node source, hr %#x.\n", hr); + hr = MFCreatePresentationDescriptor(1, &sd, &pd); + ok(hr == S_OK, "Failed to create presentation descriptor, hr %#x.\n");
hr = IMFTopologyNode_SetUnknown(src_node, &MF_TOPONODE_PRESENTATION_DESCRIPTOR, (IUnknown *)pd); ok(hr == S_OK, "Failed to set node pd, hr %#x.\n", hr);
- hr = IMFTopologyNode_SetUnknown(src_node, &MF_TOPONODE_STREAM_DESCRIPTOR, (IUnknown *)sd); - ok(hr == S_OK, "Failed to set node sd, hr %#x.\n", hr); + IMFPresentationDescriptor_Release(pd); + IMFStreamDescriptor_Release(sd); + IMFMediaType_Release(media_type);
hr = IMFTopology_AddNode(topology, src_node); ok(hr == S_OK, "Failed to add a node, hr %#x.\n", hr); @@ -1534,7 +1794,9 @@ todo_wine todo_wine ok(hr == MF_E_TOPO_UNSUPPORTED, "Unexpected hr %#x.\n", hr);
- /* Add grabber sink. */ + hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, &sink_node); + ok(hr == S_OK, "Failed to create output node, hr %#x.\n", hr); + hr = MFCreateMediaType(&media_type); ok(hr == S_OK, "Failed to create media type, hr %#x.\n", hr);
@@ -1546,13 +1808,11 @@ todo_wine hr = MFCreateSampleGrabberSinkActivate(media_type, &test_grabber_callback, &sink_activate); ok(hr == S_OK, "Failed to create grabber sink, hr %#x.\n", hr);
- IMFMediaType_Release(media_type); - - hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, &sink_node); - ok(hr == S_OK, "Failed to create output node, hr %#x.\n", hr); - hr = IMFTopologyNode_SetObject(sink_node, (IUnknown *)sink_activate); ok(hr == S_OK, "Failed to set object, hr %#x.\n", hr); + + IMFMediaType_Release(media_type); + hr = IMFTopology_AddNode(topology, sink_node); ok(hr == S_OK, "Failed to add sink node, hr %#x.\n", hr);
@@ -1567,55 +1827,192 @@ todo_wine hr = IMFTopoLoader_Load(loader, topology, &full_topology, NULL); ok(hr == MF_E_TOPO_SINK_ACTIVATES_UNSUPPORTED, "Unexpected hr %#x.\n", hr);
- hr = IMFActivate_ActivateObject(sink_activate, &IID_IMFMediaSink, (void **)&sink); - ok(hr == S_OK, "Failed to activate, hr %#x.\n", hr); + for (i = 0; i < ARRAY_SIZE(resolution_tests); i++) + { + IMFMediaType *input_type, *output_type; + IMFMediaTypeHandler *mth;
- hr = IMFMediaSink_GetStreamSinkByIndex(sink, 0, &stream_sink); - ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + /* TODO: remove once MFInitMediaTypeFromWaveFormatEx gains support for non-zero cbSize */ + if(resolution_tests[i].wine_todo && !strcmp(winetest_platform, "wine")) + { + todo_wine ok(0, "Skipping test %u on wine.\n", i); + continue; + }
- hr = IMFTopologyNode_SetObject(sink_node, (IUnknown *)stream_sink); - ok(hr == S_OK, "Failed to set object, hr %#x.\n", hr); + hr = MFCreateMediaType(&input_type); + ok(hr == S_OK, "Failed to create media type, hr %#x.\n", hr);
- IMFStreamSink_Release(stream_sink); + hr = MFInitMediaTypeFromWaveFormatEx(input_type, &resolution_tests[i].input_type, sizeof(WAVEFORMATEX) + resolution_tests[i].input_type.cbSize); + ok(hr == S_OK, "MFInitMediaTypeFromWaveFormatEx failed, hr %#x.\n", hr);
- hr = IMFTopology_GetCount(topology, &count); - ok(hr == S_OK, "Failed to get attribute count, hr %#x.\n", hr); - ok(count == 0, "Unexpected count %u.\n", count); + hr = MFCreateMediaType(&output_type); + ok(hr == S_OK, "Failed to create media type, hr %#x.\n", hr);
- hr = IMFTopoLoader_Load(loader, topology, &full_topology, NULL); - ok(hr == S_OK, "Failed to resolve topology, hr %#x.\n", hr); - ok(full_topology != topology, "Unexpected instance.\n"); + hr = MFInitMediaTypeFromWaveFormatEx(output_type, &resolution_tests[i].output_type, sizeof(WAVEFORMATEX) + resolution_tests[i].output_type.cbSize); + ok(hr == S_OK, "MFInitMediaTypeFromWaveFormatEx failed, hr %#x.\n", hr);
- hr = IMFTopology_GetCount(topology, &count); - ok(hr == S_OK, "Failed to get attribute count, hr %#x.\n", hr); - ok(count == 0, "Unexpected count %u.\n", count); + hr = MFCreateStreamDescriptor(0, 1, &input_type, &sd); + ok(hr == S_OK, "Failed to create stream descriptor, hr %#x.\n", hr);
- hr = IMFTopology_GetCount(full_topology, &count); - ok(hr == S_OK, "Failed to get attribute count, hr %#x.\n", hr); + hr = IMFStreamDescriptor_GetMediaTypeHandler(sd, &mth); + ok(hr == S_OK, "Failed to get media type handler, hr %#x.\n", hr); + + hr = IMFMediaTypeHandler_SetCurrentMediaType(mth, input_type); + ok(hr == S_OK, "Failed to set current media type, hr %#x.\n", hr); + + IMFMediaTypeHandler_Release(mth); + + hr = MFCreatePresentationDescriptor(1, &sd, &pd); + ok(hr == S_OK, "Failed to create presentation descriptor, hr %#x.\n", hr); + + hr = IMFTopologyNode_SetUnknown(src_node, &MF_TOPONODE_PRESENTATION_DESCRIPTOR, (IUnknown *)pd); + ok(hr == S_OK, "Failed to set node pd, hr %#x.\n", hr); + + IMFPresentationDescriptor_Release(pd); + + hr = IMFTopologyNode_SetUnknown(src_node, &MF_TOPONODE_STREAM_DESCRIPTOR, (IUnknown *)sd); + ok(hr == S_OK, "Failed to set node sd, hr %#x.\n", hr); + + IMFStreamDescriptor_Release(sd); + + hr = MFCreateSampleGrabberSinkActivate(output_type, &test_grabber_callback, &sink_activate); + ok(hr == S_OK, "Failed to create grabber sink, hr %#x.\n", hr); + + hr = IMFActivate_ActivateObject(sink_activate, &IID_IMFMediaSink, (void **)&sink); + ok(hr == S_OK, "Failed to activate, hr %#x.\n", hr); + + hr = IMFMediaSink_GetStreamSinkByIndex(sink, 0, &stream_sink); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + IMFMediaSink_Release(sink); + + hr = IMFTopologyNode_SetObject(sink_node, (IUnknown *)stream_sink); + ok(hr == S_OK, "Failed to set object, hr %#x.\n", hr); + + IMFStreamSink_Release(stream_sink); + + hr = IMFTopologyNode_SetUINT32(sink_node, &MF_TOPONODE_CONNECT_METHOD, resolution_tests[i].method); + ok(hr == S_OK, "Failed to set connect method, hr %#x.\n", hr); + + hr = IMFTopology_GetCount(topology, &count); + ok(hr == S_OK, "Failed to get attribute count, hr %#x.\n", hr); + ok(count == 0, "Unexpected count %u.\n", count); + + hr = IMFTopoLoader_Load(loader, topology, &full_topology, NULL); +todo_wine_if(resolution_tests[i].wine_todo) + ok(hr == resolution_tests[i].expected_result, "Unexpected hr %#x on test %u.\n", hr, i); + ok(full_topology != topology, "Unexpected instance.\n"); + + if (resolution_tests[i].expected_result == S_OK && hr == S_OK) + { + hr = IMFTopology_GetCount(full_topology, &count); + ok(hr == S_OK, "Failed to get attribute count, hr %#x.\n", hr); todo_wine - ok(count == 1, "Unexpected count %u.\n", count); + ok(count == 1, "Unexpected count %u.\n", count);
- hr = IMFTopology_GetItemByIndex(full_topology, 0, &guid, NULL); + hr = IMFTopology_GetItemByIndex(full_topology, 0, &guid, NULL); todo_wine { - ok(hr == S_OK, "Failed to get attribute key, hr %#x.\n", hr); - ok(IsEqualGUID(&guid, &MF_TOPOLOGY_RESOLUTION_STATUS), "Unexpected key %s.\n", wine_dbgstr_guid(&guid)); + ok(hr == S_OK, "Failed to get attribute key, hr %#x.\n", hr); + ok(IsEqualGUID(&guid, &MF_TOPOLOGY_RESOLUTION_STATUS), "Unexpected key %s.\n", wine_dbgstr_guid(&guid)); } - value = 0xdeadbeef; - hr = IMFTopology_GetUINT32(full_topology, &MF_TOPOLOGY_RESOLUTION_STATUS, &value); + value = 0xdeadbeef; + hr = IMFTopology_GetUINT32(full_topology, &MF_TOPOLOGY_RESOLUTION_STATUS, &value); todo_wine { - ok(hr == S_OK, "Failed to get attribute, hr %#x.\n", hr); - ok(value == MF_TOPOLOGY_RESOLUTION_SUCCEEDED, "Unexpected value %#x.\n", value); + ok(hr == S_OK, "Failed to get attribute, hr %#x.\n", hr); + ok(value == MF_TOPOLOGY_RESOLUTION_SUCCEEDED, "Unexpected value %#x.\n", value); } - hr = IMFTopoLoader_Load(loader, full_topology, &topology2, NULL); - ok(hr == S_OK, "Failed to resolve topology, hr %#x.\n", hr); - ok(full_topology != topology2, "Unexpected instance.\n");
- IMFTopology_Release(topology2); - IMFTopology_Release(full_topology); + hr = IMFTopology_GetNodeCount(full_topology, &node_count); + ok(hr == S_OK, "Failed to get node count, hr %#x.\n", hr); + ok(node_count == 2 + resolution_tests[i].expect_decoder + resolution_tests[i].expect_converter, "Unexpected node count %u.\n", node_count); + + hr = IMFTopologyNode_GetTopoNodeID(src_node, &node_id); + ok(hr == S_OK, "Failed to get source node id, hr %#x.\n", hr); + + hr = IMFTopology_GetNodeByID(full_topology, node_id, &src_node2); + ok(hr == S_OK, "Failed to get source in resolved topology, hr %#x.\n", hr); + + hr = IMFTopologyNode_GetTopoNodeID(sink_node, &node_id); + ok(hr == S_OK, "Failed to get sink node id, hr %#x.\n", hr); + + hr = IMFTopology_GetNodeByID(full_topology, node_id, &sink_node2); + ok(hr == S_OK, "Failed to get sink in resolved topology, hr %#x.\n", hr); + + if (resolution_tests[i].expect_decoder || resolution_tests[i].expect_converter) + { + hr = IMFTopologyNode_GetOutput(src_node2, 0, &mft_node, &index); + ok(hr == S_OK, "Failed to get transform node in resolved topology, hr %#x.\n", hr); + ok(index == 0, "Unexpected stream index %u.\n", index); + + hr = IMFTopologyNode_GetNodeType(mft_node, &node_type); + ok(hr == S_OK, "Failed to get transform node type in resolved topology, hr %#x.\n", hr); + ok(node_type == MF_TOPOLOGY_TRANSFORM_NODE, "Unexpected node type %u, expected MF_TOPOLOGY_TRANSFORM_NODE.\n", node_type); + + hr = IMFTopologyNode_GetObject(mft_node, &node_object); + ok(hr == S_OK, "Failed to get object of transform node, hr %#x.\n", hr); + + hr = IUnknown_QueryInterface(node_object, &IID_IMFTransform, (void**) &transform); + ok(hr == S_OK, "Failed to get IMFTransform from transform node's object, hr %#x.\n", hr); + IUnknown_Release(node_object); + + hr = IMFTransform_GetInputCurrentType(transform, 0, &media_type); + ok(hr == S_OK, "Failed to get transform input type, hr %#x.\n", hr); + + hr = IMFMediaType_Compare(media_type, (IMFAttributes *)input_type, MF_ATTRIBUTES_MATCH_ALL_ITEMS, &compare_result); + ok(hr == S_OK, "Failed to compare media types, hr %#x.\n", hr); + ok(compare_result, "Input type of first transform doesn't match source node type.\n"); + + IMFTopologyNode_Release(mft_node); + IMFMediaType_Release(media_type); + IMFTransform_Release(transform); + + hr = IMFTopologyNode_GetInput(sink_node2, 0, &mft_node, &index); + ok(hr == S_OK, "Failed to get transform node in resolved topology, hr %#x.\n", hr); + ok(index == 0, "Unexpected stream index %u.\n", index); + + hr = IMFTopologyNode_GetNodeType(mft_node, &node_type); + ok(hr == S_OK, "Failed to get transform node type in resolved topology, hr %#x.\n", hr); + ok(node_type == MF_TOPOLOGY_TRANSFORM_NODE, "Unexpected node type %u, expected MF_TOPOLOGY_TRANSFORM_NODE.\n", node_type); + + hr = IMFTopologyNode_GetObject(mft_node, &node_object); + ok(hr == S_OK, "Failed to get object of transform node, hr %#x.\n", hr); + + hr = IUnknown_QueryInterface(node_object, &IID_IMFTransform, (void**) &transform); + ok(hr == S_OK, "Failed to get IMFTransform from transform node's object, hr %#x.\n", hr); + IUnknown_Release(node_object); + + hr = IMFTransform_GetOutputCurrentType(transform, 0, &media_type); + ok(hr == S_OK, "Failed to get transform output type, hr %#x.\n", hr); + + hr = IMFMediaType_Compare(media_type, (IMFAttributes *)output_type, MF_ATTRIBUTES_MATCH_ALL_ITEMS, &compare_result); + ok(hr == S_OK, "Failed to compare media types, hr %#x.\n", hr); + ok(compare_result, "Output type of last transform doesn't match sink node type.\n"); + + IMFTopologyNode_Release(mft_node); + IMFMediaType_Release(media_type); + IMFTransform_Release(transform); + } + + IMFTopologyNode_Release(sink_node2); + + hr = IMFTopoLoader_Load(loader, full_topology, &topology2, NULL); + ok(hr == S_OK, "Failed to resolve topology, hr %#x.\n", hr); + ok(full_topology != topology2, "Unexpected instance.\n"); + + IMFTopology_Release(topology2); + IMFTopology_Release(full_topology); + } + + hr = IMFTopology_GetCount(topology, &count); + ok(hr == S_OK, "Failed to get attribute count, hr %#x.\n", hr); + ok(count == 0, "Unexpected count %u.\n", count); + + IMFActivate_ShutdownObject(sink_activate); + IMFActivate_Release(sink_activate); + IMFMediaType_Release(input_type); + IMFMediaType_Release(output_type); + }
- IMFMediaSource_Release(source); - IMFSourceResolver_Release(resolver); - IMFByteStream_Release(stream); IMFTopoLoader_Release(loader);
hr = MFShutdown(); diff --git a/dlls/mf/tests/resource.rc b/dlls/mf/tests/resource.rc deleted file mode 100644 index f54212a8c8f..00000000000 --- a/dlls/mf/tests/resource.rc +++ /dev/null @@ -1,22 +0,0 @@ -/* - * 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 "windef.h" - -/* @makedep: test.wav */ -test.wav RCDATA test.wav
Signed-off-by: Derek Lesho dlesho@codeweavers.com --- dlls/mf/topology.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/dlls/mf/topology.c b/dlls/mf/topology.c index 8032e438b73..a09f6ef0ef4 100644 --- a/dlls/mf/topology.c +++ b/dlls/mf/topology.c @@ -2022,8 +2022,6 @@ static HRESULT topology_loader_resolve_branch(struct topoloader_context *context if (FAILED(IMFTopology_GetNodeByID(context->output_topology, id, &node))) topology_loader_clone_node(context, downstream_node, &node, context->marker + 1);
- IMFTopologyNode_ConnectOutput(upstream_node, output_index, node, input_index); - IMFTopologyNode_GetNodeType(upstream_node, &u_type); IMFTopologyNode_GetNodeType(downstream_node, &d_type);
@@ -2033,7 +2031,7 @@ static HRESULT topology_loader_resolve_branch(struct topoloader_context *context return E_FAIL; }
- return connectors[u_type][d_type](context, upstream_node, output_index, downstream_node, input_index); + return connectors[u_type][d_type](context, upstream_node, output_index, node, input_index); }
static HRESULT topology_loader_resolve_nodes(struct topoloader_context *context, unsigned int *layer_size)
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=82672
Your paranoid android.
=== wvistau64 (32 bit report) ===
mf: mf: Timeout
=== wvistau64 (64 bit report) ===
mf: mf: Timeout
Signed-off-by: Derek Lesho dlesho@codeweavers.com --- dlls/mf/topology.c | 268 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 266 insertions(+), 2 deletions(-)
diff --git a/dlls/mf/topology.c b/dlls/mf/topology.c index a09f6ef0ef4..4756a30895b 100644 --- a/dlls/mf/topology.c +++ b/dlls/mf/topology.c @@ -1992,15 +1992,279 @@ static HRESULT topology_loader_clone_node(struct topoloader_context *context, IM return hr; }
+struct available_output_type +{ + IMFMediaType *type; + IMFTransform *transform; +}; + +static HRESULT topology_loader_enumerate_output_types(GUID *category, IMFMediaType *input_type, HRESULT (*new_type)(struct available_output_type *, void *), void *context) +{ + MFT_REGISTER_TYPE_INFO mft_typeinfo; + GUID major_type, subtype; + IMFActivate **activates; + UINT32 num_activates; + HRESULT hr; + + if (FAILED(hr = IMFMediaType_GetMajorType(input_type, &major_type))) + return hr; + + if (FAILED(hr = IMFMediaType_GetGUID(input_type, &MF_MT_SUBTYPE, &subtype))) + return hr; + + mft_typeinfo.guidMajorType = major_type; + mft_typeinfo.guidSubtype = subtype; + + if (FAILED(hr = MFTEnumEx(*category, MFT_ENUM_FLAG_ALL, &mft_typeinfo, NULL, &activates, &num_activates))) + return hr; + + hr = E_FAIL; + + for (unsigned int i = 0; i < num_activates; i++) + { + IMFTransform *mft; + + if (FAILED(IMFActivate_ActivateObject(activates[i], &IID_IMFTransform, (void**) &mft))) + { + IMFActivate_Release(activates[i]); + continue; + } + + if (SUCCEEDED(hr = IMFTransform_SetInputType(mft, 0, input_type, 0))) + { + struct available_output_type avail = {.transform = mft}; + unsigned int output_count = 0; + + while (SUCCEEDED(IMFTransform_GetOutputAvailableType(mft, 0, output_count++, &avail.type))) + { + if (SUCCEEDED(hr = new_type(&avail, context))) + { + IMFActivate_Release(activates[i]); + return hr; + } + } + } + + IMFActivate_ShutdownObject(activates[i]); + IMFActivate_Release(activates[i]); + } + + return hr; +} + +struct connect_to_sink_context +{ + struct topoloader_context *context; + IMFTopologyNode *src, *sink; + IMFMediaTypeHandler *sink_mth; +}; + +HRESULT connect_to_sink(struct available_output_type *type, void *context) +{ + IMFTopologyNode *node; + struct connect_to_sink_context *ctx = context; + + if (SUCCEEDED(IMFMediaTypeHandler_IsMediaTypeSupported(ctx->sink_mth, type->type, NULL))) + { + MFCreateTopologyNode(MF_TOPOLOGY_TRANSFORM_NODE, &node); + IMFTopologyNode_SetObject(node, (IUnknown *) type->transform); + IMFTopologyNode_ConnectOutput(ctx->src, 0, node, 0); + IMFTopologyNode_ConnectOutput(node, 0, ctx->sink, 0); + + IMFTopology_AddNode(ctx->context->output_topology, node); + IMFTopologyNode_Release(node); + + IMFMediaTypeHandler_SetCurrentMediaType(ctx->sink_mth, type->type); + IMFTransform_SetOutputType(type->transform, 0, type->type, 0); + + return S_OK; + } + return MF_E_TRANSFORM_NOT_POSSIBLE_FOR_CURRENT_MEDIATYPE_COMBINATION; +} + +struct connect_to_converter_context +{ + struct connect_to_sink_context sink_ctx; + GUID *converter_category; +}; + +HRESULT connect_to_converter(struct available_output_type *type, void *context) +{ + struct connect_to_converter_context *ctx = context; + struct connect_to_sink_context sink_ctx; + IMFTopologyNode *node; + HRESULT hr; + + if (SUCCEEDED(connect_to_sink(type, &ctx->sink_ctx))) + return S_OK; + + MFCreateTopologyNode(MF_TOPOLOGY_TRANSFORM_NODE, &node); + IMFTopologyNode_SetObject(node, (IUnknown *) type->transform); + + sink_ctx = ctx->sink_ctx; + sink_ctx.src = node; + if (SUCCEEDED(hr = topology_loader_enumerate_output_types(ctx->converter_category, type->type, connect_to_sink, &sink_ctx))) + { + IMFTopologyNode_ConnectOutput(ctx->sink_ctx.src, 0, node, 0); + + IMFTopology_AddNode(ctx->sink_ctx.context->output_topology, node); + + IMFTransform_SetOutputType(type->transform, 0, type->type, 0); + + return S_OK; + } + IMFTopologyNode_Release(node); + return hr; +} + typedef HRESULT (*p_topology_loader_connect_func)(struct topoloader_context *context, IMFTopologyNode *upstream_node, unsigned int output_index, IMFTopologyNode *downstream_node, unsigned int input_index);
static HRESULT topology_loader_connect_source_node(struct topoloader_context *context, IMFTopologyNode *upstream_node, unsigned int output_index, IMFTopologyNode *downstream_node, unsigned int input_index) { - FIXME("Unimplemented.\n"); + UINT32 enum_src_types, src_method = 0, sink_method = MF_CONNECT_ALLOW_DECODER; + IMFMediaTypeHandler *src_mth = NULL, *sink_mth = NULL; + struct connect_to_converter_context convert_ctx; + unsigned int i, k, i_, k_, src_type_count; + GUID major_type, decode_cat, convert_cat; + struct connect_to_sink_context sink_ctx; + IMFStreamDescriptor *desc = NULL; + IMFStreamSink *stream_sink; + IMFMediaType *media_type; + HRESULT hr;
- return E_NOTIMPL; + TRACE("attempting to connect %p:%u to %p:%u\n", upstream_node, output_index, downstream_node, input_index); + + IMFTopologyNode_GetUnknown(upstream_node, &MF_TOPONODE_STREAM_DESCRIPTOR, &IID_IMFStreamDescriptor, (void **)&desc); + + if (FAILED(hr = IMFStreamDescriptor_GetMediaTypeHandler(desc, &src_mth))) + goto done; + + if (FAILED(hr = IMFMediaTypeHandler_GetMediaTypeCount(src_mth, &src_type_count))) + goto done; + + IMFTopologyNode_GetObject(downstream_node, (IUnknown **)&stream_sink); + + if (FAILED(hr = IMFStreamSink_GetMediaTypeHandler(stream_sink, &sink_mth))) + { + IMFStreamSink_Release(stream_sink); + goto done; + } + IMFStreamSink_Release(stream_sink); + + IMFTopologyNode_GetUINT32(upstream_node, &MF_TOPONODE_CONNECT_METHOD, &src_method); + IMFTopologyNode_GetUINT32(downstream_node, &MF_TOPONODE_CONNECT_METHOD, &sink_method); + IMFTopology_GetUINT32(context->input_topology, &MF_TOPOLOGY_ENUMERATE_SOURCE_TYPES, &enum_src_types); + + if (FAILED(hr = IMFMediaTypeHandler_GetMajorType(src_mth, &major_type))) + goto done; + + if (IsEqualGUID(&major_type, &MFMediaType_Audio)) + { + decode_cat = MFT_CATEGORY_AUDIO_DECODER; + convert_cat = MFT_CATEGORY_AUDIO_EFFECT; + } + else if (IsEqualGUID(&major_type, &MFMediaType_Video)) + { + decode_cat = MFT_CATEGORY_VIDEO_DECODER; + convert_cat = MFT_CATEGORY_VIDEO_EFFECT; + } + else + { + hr = MF_E_INVALIDTYPE; + goto done; + } + + sink_ctx.context = context; + sink_ctx.src = upstream_node; + sink_ctx.sink = downstream_node; + sink_ctx.sink_mth = sink_mth; + + convert_ctx.sink_ctx = sink_ctx; + convert_ctx.converter_category = &convert_cat; + + i_ = (enum_src_types && src_method & MF_CONNECT_RESOLVE_INDEPENDENT_OUTPUTTYPES) ? src_type_count : 1; + k_ = (enum_src_types && !(src_method & MF_CONNECT_RESOLVE_INDEPENDENT_OUTPUTTYPES)) ? src_type_count : 1; + for(i = 0; i < i_; i++) + { + /* MF_CONNECT_DIRECT */ + for (k = 0; k < k_; k++) + { + if (enum_src_types) + { + if (FAILED(hr = IMFMediaTypeHandler_GetMediaTypeByIndex(src_mth, i * k, &media_type))) goto done; + } + else + if (FAILED(hr = IMFMediaTypeHandler_GetCurrentMediaType(src_mth, &media_type))) goto done; + + if (SUCCEEDED(hr = IMFMediaTypeHandler_IsMediaTypeSupported(sink_mth, media_type, NULL))) + { + IMFMediaTypeHandler_SetCurrentMediaType(src_mth, media_type); + IMFMediaTypeHandler_SetCurrentMediaType(sink_mth, media_type); + IMFTopologyNode_ConnectOutput(upstream_node, output_index, downstream_node, input_index); + IMFMediaType_Release(media_type); + goto done; + } + + IMFMediaType_Release(media_type); + } + + for (k = 0; k < k_; k++) + { + if (enum_src_types) + { + if (FAILED(hr = IMFMediaTypeHandler_GetMediaTypeByIndex(src_mth, i * k, &media_type))) goto done; + } + else + if (FAILED(hr = IMFMediaTypeHandler_GetCurrentMediaType(src_mth, &media_type))) goto done; + + if (sink_method & MF_CONNECT_ALLOW_CONVERTER) + { + if (SUCCEEDED(hr = topology_loader_enumerate_output_types(&convert_cat, media_type, connect_to_sink, &sink_ctx))) + { + IMFMediaTypeHandler_SetCurrentMediaType(src_mth, media_type); + IMFMediaType_Release(media_type); + goto done; + } + } + + IMFMediaType_Release(media_type); + } + + for (k = 0; k < k_; k++) + { + if (enum_src_types) + { + if (FAILED(hr = IMFMediaTypeHandler_GetMediaTypeByIndex(src_mth, i * k, &media_type))) goto done; + } + else + if (FAILED(hr = IMFMediaTypeHandler_GetCurrentMediaType(src_mth, &media_type))) goto done; + + if (sink_method & MF_CONNECT_ALLOW_DECODER) + { + if (SUCCEEDED(hr = topology_loader_enumerate_output_types(&decode_cat, media_type, connect_to_converter, &convert_ctx))) + { + IMFMediaTypeHandler_SetCurrentMediaType(src_mth, media_type); + IMFMediaType_Release(media_type); + goto done; + } + } + + IMFMediaType_Release(media_type); + } + } + hr = MF_E_INVALIDMEDIATYPE; + + done: + if (desc) + IMFStreamDescriptor_Release(desc); + if (src_mth) + IMFMediaTypeHandler_Release(src_mth); + if (sink_mth) + IMFMediaTypeHandler_Release(sink_mth); + + return hr; }
static HRESULT topology_loader_resolve_branch(struct topoloader_context *context, IMFTopologyNode *upstream_node,
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=82673
Your paranoid android.
=== wvistau64 (32 bit report) ===
mf: mf: Timeout
=== wvistau64 (64 bit report) ===
mf: mf: Timeout
Signed-off-by: Derek Lesho dlesho@codeweavers.com --- dlls/mf/topology.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/dlls/mf/topology.c b/dlls/mf/topology.c index 4756a30895b..99f3c12f190 100644 --- a/dlls/mf/topology.c +++ b/dlls/mf/topology.c @@ -2430,11 +2430,9 @@ static HRESULT WINAPI topology_loader_Load(IMFTopoLoader *iface, IMFTopology *in break; }
- /* For now return original topology. */ - *ret_topology = output_topology;
- return IMFTopology_CloneFrom(output_topology, input_topology); + return hr; }
static const IMFTopoLoaderVtbl topologyloadervtbl =
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=82674
Your paranoid android.
=== wvistau64 (32 bit report) ===
mf: mf: Timeout
=== wvistau64 (64 bit report) ===
mf: mf: Timeout
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=82671
Your paranoid android.
=== wvistau64 (32 bit report) ===
mf: mf: Timeout
=== wvistau64 (64 bit report) ===
mf: mf: Timeout