Wine-Devel
By thread
wine-devel@list.winehq.org
By month
Messages by month
- ----- 2026 -----
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2001 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
November 2020
- 73 participants
- 1459 messages
Re: [v4 PATCH 1/4] mf/topoloader: Add partial topology resolution tests.
by Marvin
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=82731
Your paranoid android.
=== wvistau64 (32 bit report) ===
mf:
mf: Timeout
=== wvistau64 (64 bit report) ===
mf:
mf: Timeout
Nov. 30, 2020
[v4 PATCH 4/4] mf/topoloader: Unstub IMFTopologyLoader::Load.
by Nikolay Sivov
From: Derek Lesho <dlesho(a)codeweavers.com>
Signed-off-by: Derek Lesho <dlesho(a)codeweavers.com>
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
dlls/mf/tests/mf.c | 6 ++----
dlls/mf/topology.c | 4 +---
2 files changed, 3 insertions(+), 7 deletions(-)
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c
index 5e5c30ec6fc..20e3e8713c6 100644
--- a/dlls/mf/tests/mf.c
+++ b/dlls/mf/tests/mf.c
@@ -1735,7 +1735,6 @@ static void test_topology_loader(void)
MF_CONNECT_DIRECT,
MF_E_INVALIDMEDIATYPE,
- LOADER_TODO,
},
{
@@ -1766,7 +1765,7 @@ static void test_topology_loader(void)
MF_CONNECT_ALLOW_CONVERTER,
S_OK,
- LOADER_EXPECTED_CONVERTER,
+ LOADER_EXPECTED_CONVERTER | LOADER_TODO,
},
{
@@ -1794,7 +1793,6 @@ static void test_topology_loader(void)
MF_CONNECT_DIRECT,
MF_E_INVALIDMEDIATYPE,
- LOADER_TODO,
},
{
@@ -1850,7 +1848,7 @@ static void test_topology_loader(void)
MF_CONNECT_ALLOW_DECODER,
S_OK,
- LOADER_EXPECTED_DECODER,
+ LOADER_EXPECTED_DECODER | LOADER_TODO,
},
};
diff --git a/dlls/mf/topology.c b/dlls/mf/topology.c
index 0ccc8c706b1..0b1b095729b 100644
--- a/dlls/mf/topology.c
+++ b/dlls/mf/topology.c
@@ -2429,11 +2429,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 =
--
2.29.2
Nov. 30, 2020
[v4 PATCH 3/4] mf/topoloader: Implement source node to sink node branch resolver.
by Nikolay Sivov
From: Derek Lesho <dlesho(a)codeweavers.com>
Signed-off-by: Derek Lesho <dlesho(a)codeweavers.com>
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
dlls/mf/topology.c | 273 ++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 268 insertions(+), 5 deletions(-)
diff --git a/dlls/mf/topology.c b/dlls/mf/topology.c
index a09f6ef0ef4..0ccc8c706b1 100644
--- a/dlls/mf/topology.c
+++ b/dlls/mf/topology.c
@@ -1992,15 +1992,278 @@ static HRESULT topology_loader_clone_node(struct topoloader_context *context, IM
return hr;
}
+struct transform_output_type
+{
+ IMFMediaType *type;
+ IMFTransform *transform;
+};
+
+struct connect_context
+{
+ struct topoloader_context *context;
+ IMFTopologyNode *upstream_node;
+ IMFTopologyNode *sink;
+ IMFMediaTypeHandler *sink_handler;
+ const GUID *converter_category;
+};
+
+typedef HRESULT (*p_connect_func)(struct transform_output_type *output_type, struct connect_context *context);
+
+static void topology_loader_release_transforms(IMFActivate **activates, unsigned int count)
+{
+ unsigned int i;
+
+ for (i = 0; i < count; ++i)
+ IMFActivate_Release(activates[i]);
+ CoTaskMemFree(activates);
+}
+
+static HRESULT topology_loader_enumerate_output_types(const GUID *category, IMFMediaType *input_type,
+ p_connect_func connect_func, struct connect_context *context)
+{
+ MFT_REGISTER_TYPE_INFO mft_typeinfo;
+ IMFActivate **activates;
+ unsigned int i, count;
+ HRESULT hr;
+
+ if (FAILED(hr = IMFMediaType_GetMajorType(input_type, &mft_typeinfo.guidMajorType)))
+ return hr;
+
+ if (FAILED(hr = IMFMediaType_GetGUID(input_type, &MF_MT_SUBTYPE, &mft_typeinfo.guidSubtype)))
+ return hr;
+
+ if (FAILED(hr = MFTEnumEx(*category, MFT_ENUM_FLAG_ALL, &mft_typeinfo, NULL, &activates, &count)))
+ return hr;
+
+ hr = E_FAIL;
+
+ for (i = 0; i < count; ++i)
+ {
+ IMFTransform *transform;
+
+ if (FAILED(IMFActivate_ActivateObject(activates[i], &IID_IMFTransform, (void **)&transform)))
+ {
+ WARN("Failed to create a transform.\n");
+ continue;
+ }
+
+ if (SUCCEEDED(hr = IMFTransform_SetInputType(transform, 0, input_type, 0)))
+ {
+ struct transform_output_type output_type;
+ unsigned int output_count = 0;
+
+ output_type.transform = transform;
+ while (SUCCEEDED(IMFTransform_GetOutputAvailableType(transform, 0, output_count++, &output_type.type)))
+ {
+ hr = connect_func(&output_type, context);
+ IMFMediaType_Release(output_type.type);
+ if (SUCCEEDED(hr))
+ {
+ topology_loader_release_transforms(activates, count);
+ return hr;
+ }
+ }
+ }
+
+ IMFActivate_ShutdownObject(activates[i]);
+ }
+
+ topology_loader_release_transforms(activates, count);
+
+ return hr;
+}
+
+static HRESULT connect_to_sink(struct transform_output_type *output_type, struct connect_context *context)
+{
+ IMFTopologyNode *node;
+ HRESULT hr;
+
+ if (FAILED(IMFMediaTypeHandler_IsMediaTypeSupported(context->sink_handler, output_type->type, NULL)))
+ return MF_E_TRANSFORM_NOT_POSSIBLE_FOR_CURRENT_MEDIATYPE_COMBINATION;
+
+ if (FAILED(hr = MFCreateTopologyNode(MF_TOPOLOGY_TRANSFORM_NODE, &node)))
+ return hr;
+
+ IMFTopologyNode_SetObject(node, (IUnknown *)output_type->transform);
+ IMFTopology_AddNode(context->context->output_topology, node);
+ IMFTopologyNode_ConnectOutput(context->upstream_node, 0, node, 0);
+ IMFTopologyNode_ConnectOutput(node, 0, context->sink, 0);
+
+ IMFTopologyNode_Release(node);
+
+ hr = IMFMediaTypeHandler_SetCurrentMediaType(context->sink_handler, output_type->type);
+ if (SUCCEEDED(hr))
+ hr = IMFTransform_SetOutputType(output_type->transform, 0, output_type->type, 0);
+
+ return S_OK;
+}
+
+static HRESULT connect_to_converter(struct transform_output_type *output_type, struct connect_context *context)
+{
+ struct connect_context sink_ctx;
+ IMFTopologyNode *node;
+ HRESULT hr;
+
+ if (SUCCEEDED(connect_to_sink(output_type, context)))
+ return S_OK;
+
+ if (FAILED(hr = MFCreateTopologyNode(MF_TOPOLOGY_TRANSFORM_NODE, &node)))
+ return hr;
+
+ IMFTopologyNode_SetObject(node, (IUnknown *)output_type->transform);
+
+ sink_ctx = *context;
+ sink_ctx.upstream_node = node;
+
+ if (SUCCEEDED(hr = topology_loader_enumerate_output_types(context->converter_category, output_type->type,
+ connect_to_sink, &sink_ctx)))
+ {
+ hr = IMFTopology_AddNode(context->context->output_topology, node);
+ }
+ IMFTopologyNode_Release(node);
+
+ if (SUCCEEDED(hr))
+ {
+ IMFTopology_AddNode(context->context->output_topology, node);
+ IMFTopologyNode_ConnectOutput(context->upstream_node, 0, node, 0);
+
+ hr = IMFTransform_SetOutputType(output_type->transform, 0, output_type->type, 0);
+ }
+
+ 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)
+static HRESULT topology_loader_get_node_type_handler(IMFTopologyNode *node, IMFMediaTypeHandler **handler)
{
- FIXME("Unimplemented.\n");
+ MF_TOPOLOGY_TYPE node_type;
+ IMFStreamSink *stream_sink;
+ IMFStreamDescriptor *sd;
+ IUnknown *object;
+ HRESULT hr;
- return E_NOTIMPL;
+ if (FAILED(hr = IMFTopologyNode_GetNodeType(node, &node_type)))
+ return hr;
+
+ switch (node_type)
+ {
+ case MF_TOPOLOGY_OUTPUT_NODE:
+ if (SUCCEEDED(hr = IMFTopologyNode_GetObject(node, (IUnknown **)&object)))
+ {
+ if (SUCCEEDED(hr = IUnknown_QueryInterface(object, &IID_IMFStreamSink, (void **)&stream_sink)))
+ {
+ hr = IMFStreamSink_GetMediaTypeHandler(stream_sink, handler);
+ IMFStreamSink_Release(stream_sink);
+ }
+ IUnknown_Release(object);
+ }
+ break;
+ case MF_TOPOLOGY_SOURCESTREAM_NODE:
+ if (SUCCEEDED(hr = IMFTopologyNode_GetUnknown(node, &MF_TOPONODE_STREAM_DESCRIPTOR,
+ &IID_IMFStreamDescriptor, (void **)&sd)))
+ {
+ hr = IMFStreamDescriptor_GetMediaTypeHandler(sd, handler);
+ IMFStreamDescriptor_Release(sd);
+ }
+ break;
+ default:
+ WARN("Unexpected node type %u.\n", node_type);
+ return MF_E_UNEXPECTED;
+ }
+
+ return hr;
+}
+
+static HRESULT topology_loader_get_mft_categories(IMFMediaTypeHandler *handler, GUID *decode_cat, GUID *convert_cat)
+{
+ GUID major;
+ HRESULT hr;
+
+ if (FAILED(hr = IMFMediaTypeHandler_GetMajorType(handler, &major)))
+ return hr;
+
+ if (IsEqualGUID(&major, &MFMediaType_Audio))
+ {
+ *decode_cat = MFT_CATEGORY_AUDIO_DECODER;
+ *convert_cat = MFT_CATEGORY_AUDIO_EFFECT;
+ }
+ else if (IsEqualGUID(&major, &MFMediaType_Video))
+ {
+ *decode_cat = MFT_CATEGORY_VIDEO_DECODER;
+ *convert_cat = MFT_CATEGORY_VIDEO_EFFECT;
+ }
+ else
+ {
+ WARN("Unexpected major type %s.\n", debugstr_guid(&major));
+ return MF_E_INVALIDTYPE;
+ }
+
+ return S_OK;
+}
+
+static HRESULT topology_loader_connect_source_to_sink(struct topoloader_context *context, IMFTopologyNode *source,
+ unsigned int output_index, IMFTopologyNode *sink, unsigned int input_index)
+{
+ IMFMediaTypeHandler *source_handler = NULL, *sink_handler = NULL;
+ struct connect_context convert_ctx, sink_ctx;
+ MF_CONNECT_METHOD source_method, sink_method;
+ GUID decode_cat, convert_cat;
+ IMFMediaType *media_type;
+ HRESULT hr;
+
+ TRACE("attempting to connect %p:%u to %p:%u\n", source, output_index, sink, input_index);
+
+ if (FAILED(hr = topology_loader_get_node_type_handler(source, &source_handler)))
+ goto done;
+
+ if (FAILED(hr = topology_loader_get_node_type_handler(sink, &sink_handler)))
+ goto done;
+
+ if (FAILED(IMFTopologyNode_GetUINT32(source, &MF_TOPONODE_CONNECT_METHOD, &source_method)))
+ source_method = MF_CONNECT_DIRECT;
+ if (FAILED(IMFTopologyNode_GetUINT32(sink, &MF_TOPONODE_CONNECT_METHOD, &sink_method)))
+ sink_method = MF_CONNECT_ALLOW_DECODER;
+
+ if (FAILED(hr = topology_loader_get_mft_categories(source_handler, &decode_cat, &convert_cat)))
+ goto done;
+
+ sink_ctx.context = context;
+ sink_ctx.upstream_node = source;
+ sink_ctx.sink = sink;
+ sink_ctx.sink_handler = sink_handler;
+
+ convert_ctx = sink_ctx;
+ convert_ctx.converter_category = &convert_cat;
+
+ if (SUCCEEDED(hr = IMFMediaTypeHandler_GetCurrentMediaType(source_handler, &media_type)))
+ {
+ /* Direct connection. */
+ if (SUCCEEDED(hr = IMFMediaTypeHandler_IsMediaTypeSupported(sink_handler, media_type, NULL))
+ && SUCCEEDED(hr = IMFMediaTypeHandler_SetCurrentMediaType(sink_handler, media_type)))
+ {
+ hr = IMFTopologyNode_ConnectOutput(source, output_index, sink, input_index);
+ }
+ else if (sink_method & MF_CONNECT_ALLOW_CONVERTER)
+ {
+ hr = topology_loader_enumerate_output_types(&convert_cat, media_type, connect_to_sink, &sink_ctx);
+ }
+ else if (sink_method & MF_CONNECT_ALLOW_DECODER)
+ {
+ hr = topology_loader_enumerate_output_types(&decode_cat, media_type, connect_to_converter, &convert_ctx);
+ }
+
+ IMFMediaType_Release(media_type);
+ }
+
+done:
+ if (source_handler)
+ IMFMediaTypeHandler_Release(source_handler);
+ if (sink_handler)
+ IMFMediaTypeHandler_Release(sink_handler);
+
+ return hr;
}
static HRESULT topology_loader_resolve_branch(struct topoloader_context *context, IMFTopologyNode *upstream_node,
@@ -2009,7 +2272,7 @@ static HRESULT topology_loader_resolve_branch(struct topoloader_context *context
static const p_topology_loader_connect_func connectors[MF_TOPOLOGY_TEE_NODE+1][MF_TOPOLOGY_TEE_NODE+1] =
{
/* OUTPUT */ { NULL },
- /* SOURCESTREAM */ { topology_loader_connect_source_node, NULL, NULL, NULL },
+ /* SOURCESTREAM */ { topology_loader_connect_source_to_sink, NULL, NULL, NULL },
/* TRANSFORM */ { NULL },
/* TEE */ { NULL },
};
--
2.29.2
Nov. 30, 2020
[v4 PATCH 2/4] mf/topoloader: Move node connection responsibility to connection function.
by Nikolay Sivov
From: Derek Lesho <dlesho(a)codeweavers.com>
Signed-off-by: Derek Lesho <dlesho(a)codeweavers.com>
Signed-off-by: Nikolay Sivov <nsivov(a)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)
--
2.29.2
Nov. 30, 2020
[v4 PATCH 1/4] mf/topoloader: Add partial topology resolution tests.
by Nikolay Sivov
From: Derek Lesho <dlesho(a)codeweavers.com>
Signed-off-by: Derek Lesho <dlesho(a)codeweavers.com>
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
dlls/mf/tests/Makefile.in | 2 -
dlls/mf/tests/mf.c | 705 ++++++++++++++++++++++++++++++++------
dlls/mf/tests/resource.rc | 22 --
dlls/mf/tests/test.wav | Bin 4488 -> 0 bytes
4 files changed, 597 insertions(+), 132 deletions(-)
delete mode 100644 dlls/mf/tests/resource.rc
delete mode 100644 dlls/mf/tests/test.wav
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..5e5c30ec6fc 100644
--- a/dlls/mf/tests/mf.c
+++ b/dlls/mf/tests/mf.c
@@ -97,34 +97,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,28 +1419,458 @@ 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;
+}
+
+struct type_attr
+{
+ const GUID *key;
+ unsigned int value;
+};
+
+static void init_media_type(IMFMediaType *mediatype, const GUID *major, const struct type_attr *attrs)
+{
+ HRESULT hr;
+
+ hr = IMFMediaType_DeleteAllItems(mediatype);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+ hr = IMFMediaType_SetGUID(mediatype, &MF_MT_MAJOR_TYPE, major);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+ while (attrs->key)
+ {
+ if (IsEqualGUID(attrs->key, &MF_MT_SUBTYPE))
+ {
+ GUID subtype;
+
+ memcpy(&subtype, IsEqualGUID(major, &MFMediaType_Audio) ? &MFAudioFormat_Base : &MFVideoFormat_Base,
+ sizeof(subtype));
+ subtype.Data1 = attrs->value;
+ hr = IMFMediaType_SetGUID(mediatype, attrs->key, &subtype);
+ }
+ else
+ hr = IMFMediaType_SetUINT32(mediatype, attrs->key, attrs->value);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+ attrs++;
+ }
+}
+
+static void init_source_node(IMFMediaType *mediatype, IMFMediaSource *source, IMFTopologyNode *node)
+{
+ IMFPresentationDescriptor *pd;
+ IMFMediaTypeHandler *handler;
+ IMFStreamDescriptor *sd;
+ HRESULT hr;
+
+ hr = IMFTopologyNode_DeleteAllItems(node);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+ hr = MFCreateStreamDescriptor(0, 1, &mediatype, &sd);
+ ok(hr == S_OK, "Failed to create stream descriptor, hr %#x.\n", hr);
+
+ hr = IMFStreamDescriptor_GetMediaTypeHandler(sd, &handler);
+ ok(hr == S_OK, "Failed to get media type handler, hr %#x.\n", hr);
+
+ hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, mediatype);
+ ok(hr == S_OK, "Failed to set current media type, hr %#x.\n", hr);
+
+ IMFMediaTypeHandler_Release(handler);
+
+ hr = MFCreatePresentationDescriptor(1, &sd, &pd);
+ ok(hr == S_OK, "Failed to create presentation descriptor, hr %#x.\n", hr);
+
+ hr = IMFTopologyNode_SetUnknown(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(node, &MF_TOPONODE_STREAM_DESCRIPTOR, (IUnknown *)sd);
+ ok(hr == S_OK, "Failed to set node sd, hr %#x.\n", hr);
+
+ hr = IMFTopologyNode_SetUnknown(node, &MF_TOPONODE_SOURCE, (IUnknown *)source);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+ IMFStreamDescriptor_Release(sd);
+}
+
+static void init_sink_node(IMFActivate *sink_activate, unsigned int method, IMFTopologyNode *node)
+{
+ IMFStreamSink *stream_sink;
+ IMFMediaSink *sink;
+ HRESULT hr;
+
+ hr = IMFTopologyNode_DeleteAllItems(node);
+ ok(hr == S_OK, "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);
+
+ hr = IMFMediaSink_GetStreamSinkByIndex(sink, 0, &stream_sink);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+ IMFMediaSink_Release(sink);
+
+ hr = IMFTopologyNode_SetObject(node, (IUnknown *)stream_sink);
+ ok(hr == S_OK, "Failed to set object, hr %#x.\n", hr);
+
+ IMFStreamSink_Release(stream_sink);
+
+ hr = IMFTopologyNode_SetUINT32(node, &MF_TOPONODE_CONNECT_METHOD, method);
+ ok(hr == S_OK, "Failed to set connect method, hr %#x.\n", hr);
+}
+
+enum loader_test_flags
+{
+ LOADER_EXPECTED_DECODER = 0x1,
+ LOADER_EXPECTED_CONVERTER = 0x2,
+ LOADER_TODO = 0x4,
+};
+
static void test_topology_loader(void)
{
+ static const struct loader_test
+ {
+ const GUID *major;
+ struct
+ {
+ struct type_attr attrs[8];
+ } input_type;
+ struct
+ {
+ struct type_attr attrs[8];
+ } output_type;
+
+ MF_CONNECT_METHOD method;
+ HRESULT expected_result;
+ unsigned int flags;
+ }
+ loader_tests[] =
+ {
+ {
+ /* PCM -> PCM, same type */
+ &MFMediaType_Audio,
+ {
+ {
+ { &MF_MT_SUBTYPE, WAVE_FORMAT_PCM },
+ { &MF_MT_AUDIO_NUM_CHANNELS, 1 },
+ { &MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100 },
+ { &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 44100 },
+ { &MF_MT_AUDIO_BLOCK_ALIGNMENT, 1 },
+ { &MF_MT_AUDIO_BITS_PER_SAMPLE, 8 },
+ }
+ },
+ {
+ {
+ { &MF_MT_SUBTYPE, WAVE_FORMAT_PCM },
+ { &MF_MT_AUDIO_NUM_CHANNELS, 1 },
+ { &MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100 },
+ { &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 44100 },
+ { &MF_MT_AUDIO_BLOCK_ALIGNMENT, 1 },
+ { &MF_MT_AUDIO_BITS_PER_SAMPLE, 8 },
+ }
+ },
+
+ MF_CONNECT_DIRECT,
+ S_OK,
+ },
+
+ {
+ /* PCM -> PCM, different bps. */
+ &MFMediaType_Audio,
+ {
+ {
+ { &MF_MT_SUBTYPE, WAVE_FORMAT_PCM },
+ { &MF_MT_AUDIO_NUM_CHANNELS, 1 },
+ { &MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100 },
+ { &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 44100 },
+ { &MF_MT_AUDIO_BLOCK_ALIGNMENT, 1 },
+ { &MF_MT_AUDIO_BITS_PER_SAMPLE, 8 },
+ }
+ },
+ {
+ {
+ { &MF_MT_SUBTYPE, WAVE_FORMAT_PCM },
+ { &MF_MT_AUDIO_NUM_CHANNELS, 1 },
+ { &MF_MT_AUDIO_SAMPLES_PER_SECOND, 48000 },
+ { &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 48000 },
+ { &MF_MT_AUDIO_BLOCK_ALIGNMENT, 1 },
+ { &MF_MT_AUDIO_BITS_PER_SAMPLE, 8 },
+ }
+ },
+
+ MF_CONNECT_DIRECT,
+ MF_E_INVALIDMEDIATYPE,
+ LOADER_TODO,
+ },
+
+ {
+ /* PCM -> PCM, different bps. */
+ &MFMediaType_Audio,
+ /* Source type */
+ {
+ {
+ { &MF_MT_SUBTYPE, WAVE_FORMAT_PCM },
+ { &MF_MT_AUDIO_NUM_CHANNELS, 1 },
+ { &MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100 },
+ { &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 44100 },
+ { &MF_MT_AUDIO_BLOCK_ALIGNMENT, 1 },
+ { &MF_MT_AUDIO_BITS_PER_SAMPLE, 8 },
+ }
+ },
+ /* Sink type */
+ {
+ {
+ { &MF_MT_SUBTYPE, WAVE_FORMAT_PCM },
+ { &MF_MT_AUDIO_NUM_CHANNELS, 1 },
+ { &MF_MT_AUDIO_SAMPLES_PER_SECOND, 48000 },
+ { &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 48000 },
+ { &MF_MT_AUDIO_BLOCK_ALIGNMENT, 1 },
+ { &MF_MT_AUDIO_BITS_PER_SAMPLE, 8 },
+ }
+ },
+
+ MF_CONNECT_ALLOW_CONVERTER,
+ S_OK,
+ LOADER_EXPECTED_CONVERTER,
+ },
+
+ {
+ /* MP3 -> PCM */
+ &MFMediaType_Audio,
+ {
+ {
+ { &MF_MT_SUBTYPE, WAVE_FORMAT_MPEGLAYER3 },
+ { &MF_MT_AUDIO_NUM_CHANNELS, 2 },
+ { &MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100 },
+ { &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 16000 },
+ { &MF_MT_AUDIO_BLOCK_ALIGNMENT, 1 },
+ }
+ },
+ {
+ {
+ { &MF_MT_SUBTYPE, WAVE_FORMAT_PCM },
+ { &MF_MT_AUDIO_NUM_CHANNELS, 1 },
+ { &MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100 },
+ { &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 44100 },
+ { &MF_MT_AUDIO_BLOCK_ALIGNMENT, 1 },
+ { &MF_MT_AUDIO_BITS_PER_SAMPLE, 8 },
+ }
+ },
+
+ MF_CONNECT_DIRECT,
+ MF_E_INVALIDMEDIATYPE,
+ LOADER_TODO,
+ },
+
+ {
+ /* MP3 -> PCM */
+ &MFMediaType_Audio,
+ {
+ {
+ { &MF_MT_SUBTYPE, WAVE_FORMAT_MPEGLAYER3 },
+ { &MF_MT_AUDIO_NUM_CHANNELS, 2 },
+ { &MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100 },
+ { &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 16000 },
+ { &MF_MT_AUDIO_BLOCK_ALIGNMENT, 1 },
+ }
+ },
+ {
+ {
+ { &MF_MT_SUBTYPE, WAVE_FORMAT_PCM },
+ { &MF_MT_AUDIO_NUM_CHANNELS, 1 },
+ { &MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100 },
+ { &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 44100 },
+ { &MF_MT_AUDIO_BLOCK_ALIGNMENT, 1 },
+ { &MF_MT_AUDIO_BITS_PER_SAMPLE, 8 },
+ }
+ },
+
+ MF_CONNECT_ALLOW_CONVERTER,
+ MF_E_TRANSFORM_NOT_POSSIBLE_FOR_CURRENT_MEDIATYPE_COMBINATION,
+ LOADER_TODO,
+ },
+
+ {
+ /* MP3 -> PCM */
+ &MFMediaType_Audio,
+ {
+ {
+ { &MF_MT_SUBTYPE, WAVE_FORMAT_MPEGLAYER3 },
+ { &MF_MT_AUDIO_NUM_CHANNELS, 2 },
+ { &MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100 },
+ { &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 16000 },
+ { &MF_MT_AUDIO_BLOCK_ALIGNMENT, 1 },
+ }
+ },
+ {
+ {
+ { &MF_MT_SUBTYPE, WAVE_FORMAT_PCM },
+ { &MF_MT_AUDIO_NUM_CHANNELS, 1 },
+ { &MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100 },
+ { &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 44100 },
+ { &MF_MT_AUDIO_BLOCK_ALIGNMENT, 1 },
+ { &MF_MT_AUDIO_BITS_PER_SAMPLE, 8 },
+ }
+ },
+
+ MF_CONNECT_ALLOW_DECODER,
+ S_OK,
+ LOADER_EXPECTED_DECODER,
+ },
+ };
+
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;
+ IMFMediaType *media_type, *input_type, *output_type;
+ unsigned int i, count, value, index;
IMFPresentationDescriptor *pd;
- IMFSourceResolver *resolver;
IMFActivate *sink_activate;
- IMFStreamSink *stream_sink;
- unsigned int count, value;
- IMFMediaType *media_type;
+ MF_TOPOLOGY_TYPE node_type;
IMFStreamDescriptor *sd;
- MF_OBJECT_TYPE obj_type;
+ IMFTransform *transform;
IMFMediaSource *source;
IMFTopoLoader *loader;
- IMFByteStream *stream;
- IMFAttributes *attr;
- IMFMediaSink *sink;
- WCHAR *filename;
- BOOL selected;
+ IUnknown *node_object;
+ WORD node_count;
+ TOPOID node_id;
HRESULT hr;
- GUID guid;
+ BOOL ret;
hr = MFStartup(MF_VERSION, MFSTARTUP_FULL);
ok(hr == S_OK, "Startup failure, hr %#x.\n", hr);
@@ -1487,44 +1889,39 @@ 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);
+ hr = MFCreateMediaType(&media_type);
+ ok(hr == S_OK, "Failed to create media type, hr %#x.\n", hr);
- 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 = 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 = IMFMediaSource_CreatePresentationDescriptor(source, &pd);
- ok(hr == S_OK, "Failed to create descriptor, hr %#x.\n", hr);
- if (FAILED(hr))
- return;
+ hr = MFCreateStreamDescriptor(0, 1, &media_type, &sd);
+ ok(hr == S_OK, "Failed to create stream descriptor, 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 = IMFTopologyNode_SetUnknown(src_node, &MF_TOPONODE_STREAM_DESCRIPTOR, (IUnknown *)sd);
+ ok(hr == S_OK, "Failed to set node sd, 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);
-
- 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);
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 +1931,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 +1945,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 +1964,147 @@ 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);
+ hr = MFCreateMediaType(&input_type);
+ ok(hr == S_OK, "Failed to create media type, hr %#x.\n", hr);
- hr = IMFMediaSink_GetStreamSinkByIndex(sink, 0, &stream_sink);
- ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+ hr = MFCreateMediaType(&output_type);
+ ok(hr == S_OK, "Failed to create media type, hr %#x.\n", hr);
- hr = IMFTopologyNode_SetObject(sink_node, (IUnknown *)stream_sink);
- ok(hr == S_OK, "Failed to set object, hr %#x.\n", hr);
+ for (i = 0; i < ARRAY_SIZE(loader_tests); ++i)
+ {
+ const struct loader_test *test = &loader_tests[i];
- IMFStreamSink_Release(stream_sink);
+ init_media_type(input_type, test->major, test->input_type.attrs);
+ init_media_type(output_type, test->major, test->output_type.attrs);
- 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 = MFCreateSampleGrabberSinkActivate(output_type, &test_grabber_callback, &sink_activate);
+ ok(hr == S_OK, "Failed to create grabber sink, 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");
+ init_source_node(input_type, source, src_node);
+ init_sink_node(sink_activate, test->method, sink_node);
- 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 = IMFTopology_GetCount(topology, &count);
+ ok(hr == S_OK, "Failed to get attribute count, hr %#x.\n", hr);
+ ok(!count, "Unexpected count %u.\n", count);
- hr = IMFTopology_GetCount(full_topology, &count);
- ok(hr == S_OK, "Failed to get attribute count, hr %#x.\n", hr);
+ hr = IMFTopoLoader_Load(loader, topology, &full_topology, NULL);
+todo_wine_if(test->flags & LOADER_TODO)
+ ok(hr == test->expected_result, "Unexpected hr %#x on test %u.\n", hr, i);
+ ok(full_topology != topology, "Unexpected instance.\n");
+
+ if (test->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);
-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));
-}
- 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");
+ count = 2;
+ if (test->flags & LOADER_EXPECTED_DECODER)
+ count++;
+ if (test->flags & LOADER_EXPECTED_CONVERTER)
+ count++;
- 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);
+ todo_wine_if(test->flags & (LOADER_EXPECTED_CONVERTER | LOADER_EXPECTED_DECODER))
+ ok(node_count == count, "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 (test->flags & (LOADER_EXPECTED_DECODER | LOADER_EXPECTED_CONVERTER) && strcmp(winetest_platform, "wine"))
+ {
+ 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, "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.\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(input_type, (IMFAttributes *)media_type, MF_ATTRIBUTES_MATCH_OUR_ITEMS, &ret);
+ ok(hr == S_OK, "Failed to compare media types, hr %#x.\n", hr);
+ ok(ret, "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, "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.\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(output_type, (IMFAttributes *)media_type, MF_ATTRIBUTES_MATCH_OUR_ITEMS, &ret);
+ ok(hr == S_OK, "Failed to compare media types, hr %#x.\n", hr);
+ ok(ret, "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, "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
diff --git a/dlls/mf/tests/test.wav b/dlls/mf/tests/test.wav
deleted file mode 100644
index 51d23936196da1a0452c78713c8af819259d225e..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 4488
zcmWIYbaQJEWMBw)40BD(Em06)U|?VbLYFlRV9dzC!QkT=93ll2_w;k~_Y8Im;RCXL
z63fy|&GbwR^b8FQ8B!8U60LxyG&DA~w6?W(c6Imk^!D}jLqT6(Z%=nuXGeQmYjaa$
zeO*m;Rb_cuX-RQWQDFfL6c!d0mz0*3S5#Kl)YdmNHMg|2cYsVnGN`|=7h+OdYfE!u
zLtSl6Rb>Ulq(Zn!AcH_ARa910*VfgKI%zbNM$^)0jvFnPMvKbP3T3p~9c`R|TVA8>
dC3y36v{gCU_8#q_jCPtvyOyIJ(a)PQhp007ieqznK6
--
2.29.2
Nov. 30, 2020
Re: [PATCH] mfplat/mediatype: Store extra format data as MF_MT_USER_DATA when initializing from WAVEFORMATEX.
by Marvin
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=82724
Your paranoid android.
=== wvistau64 (32 bit report) ===
mfplat:
mfplat: Timeout
=== wvistau64 (64 bit report) ===
mfplat:
mfplat: Timeout
=== w1064_2qxl (64 bit report) ===
mfplat:
mfplat.c:2868: Test failed: Unexpected return value 0x102.
mfplat.c:2224: Test failed: Failed to get event, hr 0xc00d3e85.
mfplat.c:2227: Test failed: Failed to get event, hr 0xc00d3e85.
mfplat.c:2230: Test failed: Failed to finalize GetEvent, hr 0xc00d3e85.
mfplat.c:2233: Test failed: Unexpected result, hr 0xc00d3e85.
Nov. 30, 2020
[PATCH 5/5] dwrite/layout: Use consistent tracing format for default trimming sign.
by Nikolay Sivov
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
dlls/dwrite/layout.c | 90 +++++++++++++++++++++++---------------------
1 file changed, 47 insertions(+), 43 deletions(-)
diff --git a/dlls/dwrite/layout.c b/dlls/dwrite/layout.c
index cedcd914b3f..1f6201a6a93 100644
--- a/dlls/dwrite/layout.c
+++ b/dlls/dwrite/layout.c
@@ -302,9 +302,10 @@ struct dwrite_textformat
struct dwrite_textformat_data format;
};
-struct dwrite_trimmingsign {
+struct dwrite_trimmingsign
+{
IDWriteInlineObject IDWriteInlineObject_iface;
- LONG ref;
+ LONG refcount;
IDWriteTextLayout *layout;
};
@@ -5221,9 +5222,7 @@ HRESULT create_textlayout(const struct textlayout_desc *desc, IDWriteTextLayout
static HRESULT WINAPI dwritetrimmingsign_QueryInterface(IDWriteInlineObject *iface, REFIID riid, void **obj)
{
- struct dwrite_trimmingsign *This = impl_from_IDWriteInlineObject(iface);
-
- TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
+ TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteInlineObject)) {
*obj = iface;
@@ -5239,51 +5238,55 @@ static HRESULT WINAPI dwritetrimmingsign_QueryInterface(IDWriteInlineObject *ifa
static ULONG WINAPI dwritetrimmingsign_AddRef(IDWriteInlineObject *iface)
{
- struct dwrite_trimmingsign *This = impl_from_IDWriteInlineObject(iface);
- ULONG ref = InterlockedIncrement(&This->ref);
- TRACE("(%p)->(%d)\n", This, ref);
- return ref;
+ struct dwrite_trimmingsign *sign = impl_from_IDWriteInlineObject(iface);
+ ULONG refcount = InterlockedIncrement(&sign->refcount);
+
+ TRACE("%p, refcount %d.\n", iface, refcount);
+
+ return refcount;
}
static ULONG WINAPI dwritetrimmingsign_Release(IDWriteInlineObject *iface)
{
- struct dwrite_trimmingsign *This = impl_from_IDWriteInlineObject(iface);
- ULONG ref = InterlockedDecrement(&This->ref);
+ struct dwrite_trimmingsign *sign = impl_from_IDWriteInlineObject(iface);
+ ULONG refcount = InterlockedDecrement(&sign->refcount);
- TRACE("(%p)->(%d)\n", This, ref);
+ TRACE("%p, refcount %d.\n", iface, refcount);
- if (!ref) {
- IDWriteTextLayout_Release(This->layout);
- heap_free(This);
+ if (!refcount)
+ {
+ IDWriteTextLayout_Release(sign->layout);
+ heap_free(sign);
}
- return ref;
+ return refcount;
}
static HRESULT WINAPI dwritetrimmingsign_Draw(IDWriteInlineObject *iface, void *context, IDWriteTextRenderer *renderer,
FLOAT originX, FLOAT originY, BOOL is_sideways, BOOL is_rtl, IUnknown *effect)
{
- struct dwrite_trimmingsign *This = impl_from_IDWriteInlineObject(iface);
+ struct dwrite_trimmingsign *sign = impl_from_IDWriteInlineObject(iface);
DWRITE_LINE_METRICS line;
UINT32 line_count;
- TRACE("(%p)->(%p %p %.2f %.2f %d %d %p)\n", This, context, renderer, originX, originY,
+ TRACE("%p, %p, %p, %.2f, %.2f, %d, %d, %p.\n", iface, context, renderer, originX, originY,
is_sideways, is_rtl, effect);
- IDWriteTextLayout_GetLineMetrics(This->layout, &line, 1, &line_count);
- return IDWriteTextLayout_Draw(This->layout, context, renderer, originX, originY - line.baseline);
+ IDWriteTextLayout_GetLineMetrics(sign->layout, &line, 1, &line_count);
+ return IDWriteTextLayout_Draw(sign->layout, context, renderer, originX, originY - line.baseline);
}
static HRESULT WINAPI dwritetrimmingsign_GetMetrics(IDWriteInlineObject *iface, DWRITE_INLINE_OBJECT_METRICS *ret)
{
- struct dwrite_trimmingsign *This = impl_from_IDWriteInlineObject(iface);
+ struct dwrite_trimmingsign *sign = impl_from_IDWriteInlineObject(iface);
DWRITE_TEXT_METRICS metrics;
HRESULT hr;
- TRACE("(%p)->(%p)\n", This, ret);
+ TRACE("%p, %p.\n", iface, ret);
- hr = IDWriteTextLayout_GetMetrics(This->layout, &metrics);
- if (FAILED(hr)) {
+ hr = IDWriteTextLayout_GetMetrics(sign->layout, &metrics);
+ if (FAILED(hr))
+ {
memset(ret, 0, sizeof(*ret));
return hr;
}
@@ -5297,23 +5300,24 @@ static HRESULT WINAPI dwritetrimmingsign_GetMetrics(IDWriteInlineObject *iface,
static HRESULT WINAPI dwritetrimmingsign_GetOverhangMetrics(IDWriteInlineObject *iface, DWRITE_OVERHANG_METRICS *overhangs)
{
- struct dwrite_trimmingsign *This = impl_from_IDWriteInlineObject(iface);
- TRACE("(%p)->(%p)\n", This, overhangs);
- return IDWriteTextLayout_GetOverhangMetrics(This->layout, overhangs);
+ struct dwrite_trimmingsign *sign = impl_from_IDWriteInlineObject(iface);
+
+ TRACE("%p, %p.\n", iface, overhangs);
+
+ return IDWriteTextLayout_GetOverhangMetrics(sign->layout, overhangs);
}
static HRESULT WINAPI dwritetrimmingsign_GetBreakConditions(IDWriteInlineObject *iface, DWRITE_BREAK_CONDITION *before,
DWRITE_BREAK_CONDITION *after)
{
- struct dwrite_trimmingsign *This = impl_from_IDWriteInlineObject(iface);
-
- TRACE("(%p)->(%p %p)\n", This, before, after);
+ TRACE("%p, %p, %p.\n", iface, before, after);
*before = *after = DWRITE_BREAK_CONDITION_NEUTRAL;
return S_OK;
}
-static const IDWriteInlineObjectVtbl dwritetrimmingsignvtbl = {
+static const IDWriteInlineObjectVtbl dwritetrimmingsignvtbl =
+{
dwritetrimmingsign_QueryInterface,
dwritetrimmingsign_AddRef,
dwritetrimmingsign_Release,
@@ -5350,7 +5354,7 @@ static inline BOOL is_flow_direction_vert(DWRITE_FLOW_DIRECTION direction)
HRESULT create_trimmingsign(IDWriteFactory7 *factory, IDWriteTextFormat *format, IDWriteInlineObject **sign)
{
static const WCHAR ellipsisW = 0x2026;
- struct dwrite_trimmingsign *This;
+ struct dwrite_trimmingsign *object;
DWRITE_READING_DIRECTION reading;
DWRITE_FLOW_DIRECTION flow;
HRESULT hr;
@@ -5366,24 +5370,24 @@ HRESULT create_trimmingsign(IDWriteFactory7 *factory, IDWriteTextFormat *format,
(is_reading_direction_vert(reading) && is_flow_direction_vert(flow)))
return DWRITE_E_FLOWDIRECTIONCONFLICTS;
- This = heap_alloc(sizeof(*This));
- if (!This)
+ if (!(object = heap_alloc(sizeof(*object))))
return E_OUTOFMEMORY;
- This->IDWriteInlineObject_iface.lpVtbl = &dwritetrimmingsignvtbl;
- This->ref = 1;
+ object->IDWriteInlineObject_iface.lpVtbl = &dwritetrimmingsignvtbl;
+ object->refcount = 1;
- hr = IDWriteFactory7_CreateTextLayout(factory, &ellipsisW, 1, format, 0.0f, 0.0f, &This->layout);
- if (FAILED(hr)) {
- heap_free(This);
+ hr = IDWriteFactory7_CreateTextLayout(factory, &ellipsisW, 1, format, 0.0f, 0.0f, &object->layout);
+ if (FAILED(hr))
+ {
+ heap_free(object);
return hr;
}
- IDWriteTextLayout_SetWordWrapping(This->layout, DWRITE_WORD_WRAPPING_NO_WRAP);
- IDWriteTextLayout_SetParagraphAlignment(This->layout, DWRITE_PARAGRAPH_ALIGNMENT_NEAR);
- IDWriteTextLayout_SetTextAlignment(This->layout, DWRITE_TEXT_ALIGNMENT_LEADING);
+ IDWriteTextLayout_SetWordWrapping(object->layout, DWRITE_WORD_WRAPPING_NO_WRAP);
+ IDWriteTextLayout_SetParagraphAlignment(object->layout, DWRITE_PARAGRAPH_ALIGNMENT_NEAR);
+ IDWriteTextLayout_SetTextAlignment(object->layout, DWRITE_TEXT_ALIGNMENT_LEADING);
- *sign = &This->IDWriteInlineObject_iface;
+ *sign = &object->IDWriteInlineObject_iface;
return S_OK;
}
--
2.29.2
Nov. 30, 2020
[PATCH 4/5] dwrite/layout: Zero-initialize initial runs and ranges.
by Nikolay Sivov
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
dlls/dwrite/layout.c | 75 ++++++++++++++++++--------------------------
1 file changed, 31 insertions(+), 44 deletions(-)
diff --git a/dlls/dwrite/layout.c b/dlls/dwrite/layout.c
index 964ef6b9190..cedcd914b3f 100644
--- a/dlls/dwrite/layout.c
+++ b/dlls/dwrite/layout.c
@@ -171,16 +171,18 @@ struct regular_layout_run {
UINT32 glyphcount; /* actual glyph count after shaping, not necessarily the same as reported to Draw() */
};
-struct layout_run {
+struct layout_run
+{
struct list entry;
enum layout_run_kind kind;
- union {
+ union
+ {
struct inline_object_run object;
struct regular_layout_run regular;
} u;
- FLOAT baseline;
- FLOAT height;
- UINT32 start_position; /* run text position in range [0, layout-text-length) */
+ float baseline;
+ float height;
+ unsigned int start_position; /* run text position in range [0, layout-text-length) */
};
struct layout_effective_run {
@@ -494,22 +496,16 @@ static BOOL is_run_rtl(const struct layout_effective_run *run)
return run->run->u.regular.run.bidiLevel & 1;
}
-static struct layout_run *alloc_layout_run(enum layout_run_kind kind, UINT32 start_position)
+static HRESULT alloc_layout_run(enum layout_run_kind kind, unsigned int start_position,
+ struct layout_run **run)
{
- struct layout_run *ret;
-
- ret = heap_alloc(sizeof(*ret));
- if (!ret) return NULL;
+ if (!(*run = heap_alloc_zero(sizeof(**run))))
+ return E_OUTOFMEMORY;
- memset(ret, 0, sizeof(*ret));
- ret->kind = kind;
- if (kind == LAYOUT_RUN_REGULAR) {
- ret->u.regular.sa.script = Script_Unknown;
- ret->u.regular.sa.shapes = DWRITE_SCRIPT_SHAPES_DEFAULT;
- }
- ret->start_position = start_position;
+ (*run)->kind = kind;
+ (*run)->start_position = start_position;
- return ret;
+ return S_OK;
}
static void free_layout_runs(struct dwrite_textlayout *layout)
@@ -772,9 +768,8 @@ static HRESULT layout_itemize(struct dwrite_textlayout *layout)
if (FAILED(hr))
return hr;
- r = alloc_layout_run(LAYOUT_RUN_INLINE, range->h.range.startPosition);
- if (!r)
- return E_OUTOFMEMORY;
+ if (FAILED(hr = alloc_layout_run(LAYOUT_RUN_INLINE, range->h.range.startPosition, &r)))
+ return hr;
r->u.object.object = range->object;
r->u.object.length = get_clipped_range_length(layout, range);
@@ -893,16 +888,14 @@ static HRESULT layout_resolve_fonts(struct dwrite_textlayout *layout)
run->run.fontEmSize = range->fontsize * scale;
- if (mapped_length < length) {
+ if (mapped_length < length)
+ {
struct regular_layout_run *nextrun;
struct layout_run *nextr;
/* keep mapped part for current run, add another run for the rest */
- nextr = alloc_layout_run(LAYOUT_RUN_REGULAR, 0);
- if (!nextr) {
- hr = E_OUTOFMEMORY;
+ if (FAILED(hr = alloc_layout_run(LAYOUT_RUN_REGULAR, 0, &nextr)))
goto fatal;
- }
*nextr = *r;
nextr->start_position = run->descr.textPosition + mapped_length;
@@ -2227,18 +2220,17 @@ static struct layout_range_header *alloc_layout_range(struct dwrite_textlayout *
{
struct layout_range *range;
- range = heap_alloc(sizeof(*range));
+ range = heap_alloc_zero(sizeof(*range));
if (!range) return NULL;
range->weight = layout->format.weight;
range->style = layout->format.style;
range->stretch = layout->format.stretch;
range->fontsize = layout->format.fontsize;
- range->object = NULL;
- range->pair_kerning = FALSE;
range->fontfamily = heap_strdupW(layout->format.family_name);
- if (!range->fontfamily) {
+ if (!range->fontfamily)
+ {
heap_free(range);
return NULL;
}
@@ -2256,10 +2248,9 @@ static struct layout_range_header *alloc_layout_range(struct dwrite_textlayout *
{
struct layout_range_bool *range;
- range = heap_alloc(sizeof(*range));
+ range = heap_alloc_zero(sizeof(*range));
if (!range) return NULL;
- range->value = FALSE;
h = &range->h;
break;
}
@@ -2268,10 +2259,9 @@ static struct layout_range_header *alloc_layout_range(struct dwrite_textlayout *
{
struct layout_range_iface *range;
- range = heap_alloc(sizeof(*range));
+ range = heap_alloc_zero(sizeof(*range));
if (!range) return NULL;
- range->iface = NULL;
h = &range->h;
break;
}
@@ -2279,12 +2269,9 @@ static struct layout_range_header *alloc_layout_range(struct dwrite_textlayout *
{
struct layout_range_spacing *range;
- range = heap_alloc(sizeof(*range));
+ range = heap_alloc_zero(sizeof(*range));
if (!range) return NULL;
- range->leading = 0.0f;
- range->trailing = 0.0f;
- range->min_advance = 0.0f;
h = &range->h;
break;
}
@@ -4805,12 +4792,12 @@ static HRESULT WINAPI dwritetextlayout_sink_SetScriptAnalysis(IDWriteTextAnalysi
{
struct dwrite_textlayout *layout = impl_from_IDWriteTextAnalysisSink1(iface);
struct layout_run *run;
+ HRESULT hr;
TRACE("[%u,%u) script=%u:%s\n", position, position + length, sa->script, debugstr_sa_script(sa->script));
- run = alloc_layout_run(LAYOUT_RUN_REGULAR, position);
- if (!run)
- return E_OUTOFMEMORY;
+ if (FAILED(hr = alloc_layout_run(LAYOUT_RUN_REGULAR, position, &run)))
+ return hr;
run->u.regular.descr.string = &layout->str[position];
run->u.regular.descr.stringLength = length;
@@ -4837,6 +4824,7 @@ static HRESULT WINAPI dwritetextlayout_sink_SetBidiLevel(IDWriteTextAnalysisSink
{
struct dwrite_textlayout *layout = impl_from_IDWriteTextAnalysisSink1(iface);
struct layout_run *cur_run;
+ HRESULT hr;
TRACE("[%u,%u) %u %u\n", position, position + length, explicitLevel, resolvedLevel);
@@ -4868,9 +4856,8 @@ static HRESULT WINAPI dwritetextlayout_sink_SetBidiLevel(IDWriteTextAnalysisSink
/* all fully covered runs are processed at this point, reuse existing run for remaining
reported bidi range and add another run for the rest of original one */
- run = alloc_layout_run(LAYOUT_RUN_REGULAR, position + length);
- if (!run)
- return E_OUTOFMEMORY;
+ if (FAILED(hr = alloc_layout_run(LAYOUT_RUN_REGULAR, position + length, &run)))
+ return hr;
*run = *cur_run;
run->u.regular.descr.textPosition = position + length;
--
2.29.2
Nov. 30, 2020
[PATCH 3/5] dwrite/layout: Zero-initialize layout structure.
by Nikolay Sivov
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
dlls/dwrite/layout.c | 44 +++++++++++---------------------------------
1 file changed, 11 insertions(+), 33 deletions(-)
diff --git a/dlls/dwrite/layout.c b/dlls/dwrite/layout.c
index ab442c453bf..964ef6b9190 100644
--- a/dlls/dwrite/layout.c
+++ b/dlls/dwrite/layout.c
@@ -5080,9 +5080,6 @@ static HRESULT layout_format_from_textformat(struct dwrite_textlayout *layout, I
layout->format.wrapping = IDWriteTextFormat_GetWordWrapping(format);
layout->format.readingdir = IDWriteTextFormat_GetReadingDirection(format);
layout->format.flow = IDWriteTextFormat_GetFlowDirection(format);
- layout->format.fallback = NULL;
- layout->format.spacing.leadingBefore = 0.0f;
- layout->format.spacing.fontLineGapUsage = DWRITE_FONT_LINE_GAP_USAGE_DEFAULT;
hr = IDWriteTextFormat_GetLineSpacing(format, &layout->format.spacing.method,
&layout->format.spacing.height, &layout->format.spacing.baseline);
if (FAILED(hr))
@@ -5115,7 +5112,8 @@ static HRESULT layout_format_from_textformat(struct dwrite_textlayout *layout, I
layout->format.family_len = len;
hr = IDWriteTextFormat_QueryInterface(format, &IID_IDWriteTextFormat1, (void**)&format1);
- if (hr == S_OK) {
+ if (hr == S_OK)
+ {
IDWriteTextFormat2 *format2;
layout->format.vertical_orientation = IDWriteTextFormat1_GetVerticalGlyphOrientation(format1);
@@ -5129,10 +5127,6 @@ static HRESULT layout_format_from_textformat(struct dwrite_textlayout *layout, I
IDWriteTextFormat1_Release(format1);
}
- else {
- layout->format.vertical_orientation = DWRITE_VERTICAL_GLYPH_ORIENTATION_DEFAULT;
- layout->format.optical_alignment = DWRITE_OPTICAL_ALIGNMENT_NONE;
- }
hr = IDWriteTextFormat_QueryInterface(format, &IID_IDWriteTextFormat3, (void **)&format3);
if (hr == S_OK)
@@ -5157,14 +5151,6 @@ static HRESULT init_textlayout(const struct textlayout_desc *desc, struct dwrite
layout->refcount = 1;
layout->len = desc->length;
layout->recompute = RECOMPUTE_EVERYTHING;
- layout->nominal_breakpoints = NULL;
- layout->actual_breakpoints = NULL;
- layout->cluster_count = 0;
- layout->clustermetrics = NULL;
- layout->clusters = NULL;
- layout->lines = NULL;
- layout->lines_size = 0;
- layout->minwidth = 0.0f;
list_init(&layout->eruns);
list_init(&layout->inlineobjects);
list_init(&layout->underlines);
@@ -5176,14 +5162,8 @@ static HRESULT init_textlayout(const struct textlayout_desc *desc, struct dwrite
list_init(&layout->effects);
list_init(&layout->spacing);
list_init(&layout->typographies);
- memset(&layout->format, 0, sizeof(layout->format));
- memset(&layout->metrics, 0, sizeof(layout->metrics));
layout->metrics.layoutWidth = desc->max_width;
layout->metrics.layoutHeight = desc->max_height;
- layout->measuringmode = DWRITE_MEASURING_MODE_NATURAL;
-
- layout->ppdip = 0.0f;
- memset(&layout->transform, 0, sizeof(layout->transform));
layout->str = heap_strdupnW(desc->string, desc->length);
if (desc->length && !layout->str) {
@@ -5212,10 +5192,8 @@ static HRESULT init_textlayout(const struct textlayout_desc *desc, struct dwrite
goto fail;
}
- if (desc->is_gdi_compatible)
- layout->measuringmode = desc->use_gdi_natural ? DWRITE_MEASURING_MODE_GDI_NATURAL : DWRITE_MEASURING_MODE_GDI_CLASSIC;
- else
- layout->measuringmode = DWRITE_MEASURING_MODE_NATURAL;
+ layout->measuringmode = desc->is_gdi_compatible ? (desc->use_gdi_natural ? DWRITE_MEASURING_MODE_GDI_NATURAL :
+ DWRITE_MEASURING_MODE_GDI_CLASSIC) : DWRITE_MEASURING_MODE_NATURAL;
layout->ppdip = desc->ppdip;
layout->transform = desc->transform ? *desc->transform : identity;
@@ -5234,22 +5212,22 @@ fail:
return hr;
}
-HRESULT create_textlayout(const struct textlayout_desc *desc, IDWriteTextLayout **ret)
+HRESULT create_textlayout(const struct textlayout_desc *desc, IDWriteTextLayout **layout)
{
- struct dwrite_textlayout *layout;
+ struct dwrite_textlayout *object;
HRESULT hr;
- *ret = NULL;
+ *layout = NULL;
if (!desc->format || !desc->string)
return E_INVALIDARG;
- layout = heap_alloc(sizeof(struct dwrite_textlayout));
- if (!layout) return E_OUTOFMEMORY;
+ if (!(object = heap_alloc_zero(sizeof(*object))))
+ return E_OUTOFMEMORY;
- hr = init_textlayout(desc, layout);
+ hr = init_textlayout(desc, object);
if (hr == S_OK)
- *ret = (IDWriteTextLayout *)&layout->IDWriteTextLayout4_iface;
+ *layout = (IDWriteTextLayout *)&object->IDWriteTextLayout4_iface;
return hr;
}
--
2.29.2
Nov. 30, 2020
[PATCH 2/5] dwrite/layout: Zero-initialize format structure.
by Nikolay Sivov
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
dlls/dwrite/layout.c | 66 ++++++++++++++++----------------------------
1 file changed, 24 insertions(+), 42 deletions(-)
diff --git a/dlls/dwrite/layout.c b/dlls/dwrite/layout.c
index 25d3bcb4ad0..ab442c453bf 100644
--- a/dlls/dwrite/layout.c
+++ b/dlls/dwrite/layout.c
@@ -5920,10 +5920,10 @@ static struct dwrite_textformat *unsafe_impl_from_IDWriteTextFormat(IDWriteTextF
CONTAINING_RECORD(iface, struct dwrite_textformat, IDWriteTextFormat3_iface) : NULL;
}
-HRESULT create_textformat(const WCHAR *family_name, IDWriteFontCollection *collection, DWRITE_FONT_WEIGHT weight, DWRITE_FONT_STYLE style,
- DWRITE_FONT_STRETCH stretch, FLOAT size, const WCHAR *locale, IDWriteTextFormat **format)
+HRESULT create_textformat(const WCHAR *family_name, IDWriteFontCollection *collection, DWRITE_FONT_WEIGHT weight,
+ DWRITE_FONT_STYLE style, DWRITE_FONT_STRETCH stretch, FLOAT size, const WCHAR *locale, IDWriteTextFormat **format)
{
- struct dwrite_textformat *This;
+ struct dwrite_textformat *object;
*format = NULL;
@@ -5935,45 +5935,27 @@ HRESULT create_textformat(const WCHAR *family_name, IDWriteFontCollection *colle
((UINT32)style > DWRITE_FONT_STYLE_ITALIC))
return E_INVALIDARG;
- This = heap_alloc(sizeof(struct dwrite_textformat));
- if (!This) return E_OUTOFMEMORY;
-
- This->IDWriteTextFormat3_iface.lpVtbl = &dwritetextformatvtbl;
- This->refcount = 1;
- This->format.family_name = heap_strdupW(family_name);
- This->format.family_len = strlenW(family_name);
- This->format.locale = heap_strdupW(locale);
- This->format.locale_len = strlenW(locale);
- /* force locale name to lower case, layout will inherit this modified value */
- strlwrW(This->format.locale);
- This->format.weight = weight;
- This->format.style = style;
- This->format.fontsize = size;
- This->format.tabstop = 4.0f * size;
- This->format.stretch = stretch;
- This->format.textalignment = DWRITE_TEXT_ALIGNMENT_LEADING;
- This->format.optical_alignment = DWRITE_OPTICAL_ALIGNMENT_NONE;
- This->format.paralign = DWRITE_PARAGRAPH_ALIGNMENT_NEAR;
- This->format.wrapping = DWRITE_WORD_WRAPPING_WRAP;
- This->format.last_line_wrapping = TRUE;
- This->format.readingdir = DWRITE_READING_DIRECTION_LEFT_TO_RIGHT;
- This->format.flow = DWRITE_FLOW_DIRECTION_TOP_TO_BOTTOM;
- This->format.spacing.method = DWRITE_LINE_SPACING_METHOD_DEFAULT;
- This->format.spacing.height = 0.0f;
- This->format.spacing.baseline = 0.0f;
- This->format.spacing.leadingBefore = 0.0f;
- This->format.spacing.fontLineGapUsage = DWRITE_FONT_LINE_GAP_USAGE_DEFAULT;
- This->format.vertical_orientation = DWRITE_VERTICAL_GLYPH_ORIENTATION_DEFAULT;
- This->format.trimming.granularity = DWRITE_TRIMMING_GRANULARITY_NONE;
- This->format.trimming.delimiter = 0;
- This->format.trimming.delimiterCount = 0;
- This->format.trimmingsign = NULL;
- This->format.collection = collection;
- This->format.fallback = NULL;
- This->format.automatic_axes = DWRITE_AUTOMATIC_FONT_AXES_NONE;
- IDWriteFontCollection_AddRef(collection);
-
- *format = (IDWriteTextFormat *)&This->IDWriteTextFormat3_iface;
+ if (!(object = heap_alloc_zero(sizeof(*object))))
+ return E_OUTOFMEMORY;
+
+ object->IDWriteTextFormat3_iface.lpVtbl = &dwritetextformatvtbl;
+ object->refcount = 1;
+ object->format.family_name = heap_strdupW(family_name);
+ object->format.family_len = strlenW(family_name);
+ object->format.locale = heap_strdupW(locale);
+ object->format.locale_len = strlenW(locale);
+ /* Force locale name to lower case, layout will inherit this modified value. */
+ strlwrW(object->format.locale);
+ object->format.weight = weight;
+ object->format.style = style;
+ object->format.fontsize = size;
+ object->format.tabstop = 4.0f * size;
+ object->format.stretch = stretch;
+ object->format.last_line_wrapping = TRUE;
+ object->format.collection = collection;
+ IDWriteFontCollection_AddRef(object->format.collection);
+
+ *format = (IDWriteTextFormat *)&object->IDWriteTextFormat3_iface;
return S_OK;
}
--
2.29.2
Nov. 30, 2020