Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfplat/main.c | 68 ++++++++++++++++++++++++++++------------------ 1 file changed, 42 insertions(+), 26 deletions(-)
diff --git a/dlls/mfplat/main.c b/dlls/mfplat/main.c index 61521ce779..4f634e0d82 100644 --- a/dlls/mfplat/main.c +++ b/dlls/mfplat/main.c @@ -70,6 +70,7 @@ static const WCHAR categories_keyW[] = {'M','e','d','i','a','F','o','u','n','d', 'C','a','t','e','g','o','r','i','e','s',0}; static const WCHAR inputtypesW[] = {'I','n','p','u','t','T','y','p','e','s',0}; static const WCHAR outputtypesW[] = {'O','u','t','p','u','t','T','y','p','e','s',0}; +static const WCHAR attributesW[] = {'A','t','t','r','i','b','u','t','e','s',0}; static const WCHAR szGUIDFmt[] = { '%','0','8','x','-','%','0','4','x','-','%','0','4','x','-','%','0', @@ -166,46 +167,65 @@ BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved) return TRUE; }
-static HRESULT register_transform(CLSID *clsid, WCHAR *name, - UINT32 cinput, MFT_REGISTER_TYPE_INFO *input_types, - UINT32 coutput, MFT_REGISTER_TYPE_INFO *output_types) +static HRESULT register_transform(const CLSID *clsid, const WCHAR *name, + UINT32 cinput, const MFT_REGISTER_TYPE_INFO *input_types, UINT32 coutput, + const MFT_REGISTER_TYPE_INFO *output_types, IMFAttributes *attributes) { static const WCHAR reg_format[] = {'%','s','\','%','s',0}; + HRESULT hr = S_OK; HKEY hclsid = 0; WCHAR buffer[64]; - DWORD size; + DWORD size, ret; WCHAR str[250]; + UINT8 *blob;
GUIDToString(buffer, clsid); sprintfW(str, reg_format, transform_keyW, buffer);
- if (RegCreateKeyW(HKEY_CLASSES_ROOT, str, &hclsid)) - return E_FAIL; + if ((ret = RegCreateKeyW(HKEY_CLASSES_ROOT, str, &hclsid))) + hr = HRESULT_FROM_WIN32(ret);
- size = (strlenW(name) + 1) * sizeof(WCHAR); - if (RegSetValueExW(hclsid, NULL, 0, REG_SZ, (BYTE *)name, size)) - goto err; + if (SUCCEEDED(hr)) + { + size = (strlenW(name) + 1) * sizeof(WCHAR); + if ((ret = RegSetValueExW(hclsid, NULL, 0, REG_SZ, (BYTE *)name, size))) + hr = HRESULT_FROM_WIN32(ret); + }
- if (cinput && input_types) + if (SUCCEEDED(hr) && cinput && input_types) { size = cinput * sizeof(MFT_REGISTER_TYPE_INFO); - if (RegSetValueExW(hclsid, inputtypesW, 0, REG_BINARY, (BYTE *)input_types, size)) - goto err; + if ((ret = RegSetValueExW(hclsid, inputtypesW, 0, REG_BINARY, (BYTE *)input_types, size))) + hr = HRESULT_FROM_WIN32(ret); }
- if (coutput && output_types) + if (SUCCEEDED(hr) && coutput && output_types) { size = coutput * sizeof(MFT_REGISTER_TYPE_INFO); - if (RegSetValueExW(hclsid, outputtypesW, 0, REG_BINARY, (BYTE *)output_types, size)) - goto err; + if ((ret = RegSetValueExW(hclsid, outputtypesW, 0, REG_BINARY, (BYTE *)output_types, size))) + hr = HRESULT_FROM_WIN32(ret); }
- RegCloseKey(hclsid); - return S_OK; + if (SUCCEEDED(hr) && attributes) + { + if (SUCCEEDED(hr = MFGetAttributesAsBlobSize(attributes, &size))) + { + if ((blob = heap_alloc(size))) + { + if (SUCCEEDED(hr = MFGetAttributesAsBlob(attributes, blob, size))) + { + if ((ret = RegSetValueExW(hclsid, attributesW, 0, REG_BINARY, blob, size))) + hr = HRESULT_FROM_WIN32(ret); + } + heap_free(blob); + } + else + hr = E_OUTOFMEMORY; + } + }
-err: RegCloseKey(hclsid); - return E_FAIL; + return hr; }
static HRESULT register_category(CLSID *clsid, GUID *category) @@ -236,17 +256,13 @@ HRESULT WINAPI MFTRegister(CLSID clsid, GUID category, LPWSTR name, UINT32 flags { HRESULT hr;
- TRACE("(%s, %s, %s, %x, %u, %p, %u, %p, %p)\n", debugstr_guid(&clsid), debugstr_guid(&category), - debugstr_w(name), flags, cinput, input_types, - coutput, output_types, attributes); - - if (attributes) - FIXME("attributes not yet supported.\n"); + TRACE("%s, %s, %s, %#x, %u, %p, %u, %p, %p.\n", debugstr_guid(&clsid), debugstr_guid(&category), + debugstr_w(name), flags, cinput, input_types, coutput, output_types, attributes);
if (flags) FIXME("flags not yet supported.\n");
- hr = register_transform(&clsid, name, cinput, input_types, coutput, output_types); + hr = register_transform(&clsid, name, cinput, input_types, coutput, output_types, attributes); if(FAILED(hr)) ERR("Failed to write register transform\n");
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfplat/main.c | 14 +++++++++----- include/mfapi.h | 16 ++++++++++++++++ 2 files changed, 25 insertions(+), 5 deletions(-)
diff --git a/dlls/mfplat/main.c b/dlls/mfplat/main.c index 4f634e0d82..d10e643868 100644 --- a/dlls/mfplat/main.c +++ b/dlls/mfplat/main.c @@ -71,6 +71,7 @@ static const WCHAR categories_keyW[] = {'M','e','d','i','a','F','o','u','n','d', static const WCHAR inputtypesW[] = {'I','n','p','u','t','T','y','p','e','s',0}; static const WCHAR outputtypesW[] = {'O','u','t','p','u','t','T','y','p','e','s',0}; static const WCHAR attributesW[] = {'A','t','t','r','i','b','u','t','e','s',0}; +static const WCHAR mftflagsW[] = {'M','F','T','F','l','a','g','s',0}; static const WCHAR szGUIDFmt[] = { '%','0','8','x','-','%','0','4','x','-','%','0','4','x','-','%','0', @@ -167,7 +168,7 @@ BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved) return TRUE; }
-static HRESULT register_transform(const CLSID *clsid, const WCHAR *name, +static HRESULT register_transform(const CLSID *clsid, const WCHAR *name, UINT32 flags, UINT32 cinput, const MFT_REGISTER_TYPE_INFO *input_types, UINT32 coutput, const MFT_REGISTER_TYPE_INFO *output_types, IMFAttributes *attributes) { @@ -224,6 +225,12 @@ static HRESULT register_transform(const CLSID *clsid, const WCHAR *name, } }
+ if (SUCCEEDED(hr) && flags) + { + if ((ret = RegSetValueExW(hclsid, mftflagsW, 0, REG_DWORD, (BYTE *)&flags, sizeof(flags)))) + hr = HRESULT_FROM_WIN32(ret); + } + RegCloseKey(hclsid); return hr; } @@ -259,10 +266,7 @@ HRESULT WINAPI MFTRegister(CLSID clsid, GUID category, LPWSTR name, UINT32 flags TRACE("%s, %s, %s, %#x, %u, %p, %u, %p, %p.\n", debugstr_guid(&clsid), debugstr_guid(&category), debugstr_w(name), flags, cinput, input_types, coutput, output_types, attributes);
- if (flags) - FIXME("flags not yet supported.\n"); - - hr = register_transform(&clsid, name, cinput, input_types, coutput, output_types, attributes); + hr = register_transform(&clsid, name, flags, cinput, input_types, coutput, output_types, attributes); if(FAILED(hr)) ERR("Failed to write register transform\n");
diff --git a/include/mfapi.h b/include/mfapi.h index d172db147a..f3ca3d9444 100644 --- a/include/mfapi.h +++ b/include/mfapi.h @@ -350,6 +350,22 @@ typedef enum _MFWaveFormatExConvertFlags MFWaveFormatExConvertFlag_ForceExtensible = 1, } MFWaveFormatExConvertFlags;
+enum _MFT_ENUM_FLAG +{ + MFT_ENUM_FLAG_SYNCMFT = 0x00000001, + MFT_ENUM_FLAG_ASYNCMFT = 0x00000002, + MFT_ENUM_FLAG_HARDWARE = 0x00000004, + MFT_ENUM_FLAG_FIELDOFUSE = 0x00000008, + MFT_ENUM_FLAG_LOCALMFT = 0x00000010, + MFT_ENUM_FLAG_TRANSCODE_ONLY = 0x00000020, + MFT_ENUM_FLAG_ALL = 0x0000003f, + MFT_ENUM_FLAG_SORTANDFILTER = 0x00000040, + MFT_ENUM_FLAG_SORTANDFILTER_APPROVED_ONLY = 0x000000c0, + MFT_ENUM_FLAG_SORTANDFILTER_WEB_ONLY = 0x00000140, + MFT_ENUM_FLAG_SORTANDFILTER_WEB_ONLY_EDGEMODE = 0x00000240, + MFT_ENUM_FLAG_UNTRUSTED_STOREMFT = 0x00000400, +}; + HRESULT WINAPI MFAddPeriodicCallback(MFPERIODICCALLBACK callback, IUnknown *context, DWORD *key); HRESULT WINAPI MFAllocateWorkQueue(DWORD *queue); HRESULT WINAPI MFAllocateWorkQueueEx(MFASYNC_WORKQUEUE_TYPE queue_type, DWORD *queue);
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=51937
Your paranoid android.
=== debian9 (32 bit report) ===
mfplat: mfplat.c:2623: Test failed: Unexpected refcount 1. Unhandled exception: page fault on read access to 0x00000008 in 32-bit code (0x7ed97072).
Report errors: mfplat:mfplat crashed (c0000005)
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mf/mf_private.h | 29 +++++++ dlls/mf/tests/mf.c | 163 +++++++++++++++++++++++++++++++++------ dlls/mf/topology.c | 176 ++++++++++++++++++++++++++++++++++++++----- 3 files changed, 330 insertions(+), 38 deletions(-)
diff --git a/dlls/mf/mf_private.h b/dlls/mf/mf_private.h index b5b4e84bba..45a3834eec 100644 --- a/dlls/mf/mf_private.h +++ b/dlls/mf/mf_private.h @@ -18,6 +18,35 @@
#include "mfidl.h"
+#include "wine/heap.h" + +static inline BOOL mf_array_reserve(void **elements, size_t *capacity, size_t count, size_t size) +{ + size_t new_capacity, max_capacity; + void *new_elements; + + if (count <= *capacity) + return TRUE; + + max_capacity = ~(SIZE_T)0 / size; + if (count > max_capacity) + return FALSE; + + new_capacity = max(4, *capacity); + while (new_capacity < count && new_capacity <= max_capacity / 2) + new_capacity *= 2; + if (new_capacity < count) + new_capacity = max_capacity; + + if (!(new_elements = heap_realloc(*elements, new_capacity * size))) + return FALSE; + + *elements = new_elements; + *capacity = new_capacity; + + return TRUE; +} + struct activate_funcs { HRESULT (*create_object)(void *context, IUnknown **object); diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index cea5f98f6e..4974e043af 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -77,11 +77,12 @@ static void test_topology(void) IUnknown test_unk2 = { &test_unk_vtbl }; IUnknown test_unk = { &test_unk_vtbl }; IMFTopologyNode *node, *node2, *node3; + IMFMediaType *mediatype, *mediatype2; IMFTopology *topology, *topology2; - UINT32 attr_count; IUnknown *object; + WORD node_count; + UINT32 count; DWORD size; - WORD count; HRESULT hr; TOPOID id;
@@ -132,19 +133,19 @@ static void test_topology(void) hr = IMFTopology_AddNode(topology, NULL); ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
- count = 1; - hr = IMFTopology_GetNodeCount(topology, &count); + node_count = 1; + hr = IMFTopology_GetNodeCount(topology, &node_count); ok(hr == S_OK, "Failed to get node count, hr %#x.\n", hr); - ok(count == 0, "Unexpected node count %u.\n", count); + ok(node_count == 0, "Unexpected node count %u.\n", node_count);
/* Same id, different nodes. */ hr = IMFTopology_AddNode(topology, node); ok(hr == S_OK, "Failed to add a node, hr %#x.\n", hr);
- count = 0; - hr = IMFTopology_GetNodeCount(topology, &count); + node_count = 0; + hr = IMFTopology_GetNodeCount(topology, &node_count); ok(hr == S_OK, "Failed to get node count, hr %#x.\n", hr); - ok(count == 1, "Unexpected node count %u.\n", count); + ok(node_count == 1, "Unexpected node count %u.\n", node_count);
hr = IMFTopology_AddNode(topology, node2); ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr); @@ -190,10 +191,10 @@ static void test_topology(void) ok(hr == S_OK, "Failed to add a node, hr %#x.\n", hr); IMFTopologyNode_Release(node2);
- count = 0; - hr = IMFTopology_GetNodeCount(topology, &count); + node_count = 0; + hr = IMFTopology_GetNodeCount(topology, &node_count); ok(hr == S_OK, "Failed to get node count, hr %#x.\n", hr); - ok(count == 2, "Unexpected node count %u.\n", count); + ok(node_count == 2, "Unexpected node count %u.\n", node_count);
/* Remove with detached node, existing id. */ hr = MFCreateTopologyNode(MF_TOPOLOGY_TEE_NODE, &node2); @@ -207,18 +208,18 @@ static void test_topology(void) hr = IMFTopology_RemoveNode(topology, node); ok(hr == S_OK, "Failed to remove a node, hr %#x.\n", hr);
- count = 0; - hr = IMFTopology_GetNodeCount(topology, &count); + node_count = 0; + hr = IMFTopology_GetNodeCount(topology, &node_count); ok(hr == S_OK, "Failed to get node count, hr %#x.\n", hr); - ok(count == 1, "Unexpected node count %u.\n", count); + ok(node_count == 1, "Unexpected node count %u.\n", node_count);
hr = IMFTopology_Clear(topology); ok(hr == S_OK, "Failed to clear topology, hr %#x.\n", hr);
- count = 1; - hr = IMFTopology_GetNodeCount(topology, &count); + node_count = 1; + hr = IMFTopology_GetNodeCount(topology, &node_count); ok(hr == S_OK, "Failed to get node count, hr %#x.\n", hr); - ok(count == 0, "Unexpected node count %u.\n", count); + ok(node_count == 0, "Unexpected node count %u.\n", node_count);
hr = IMFTopology_Clear(topology); ok(hr == S_OK, "Failed to clear topology, hr %#x.\n", hr); @@ -366,9 +367,9 @@ static void test_topology(void) hr = IMFTopologyNode_SetObject(node, &test_unk2); ok(hr == S_OK, "Failed to set object, hr %#x.\n", hr);
- hr = IMFTopologyNode_GetCount(node, &attr_count); + hr = IMFTopologyNode_GetCount(node, &count); ok(hr == S_OK, "Failed to get attribute count, hr %#x.\n", hr); - ok(attr_count == 0, "Unexpected attribute count %u.\n", attr_count); + ok(count == 0, "Unexpected attribute count %u.\n", count);
hr = IMFTopologyNode_SetGUID(node, &MF_TOPONODE_TRANSFORM_OBJECTID, &MF_TOPONODE_TRANSFORM_OBJECTID); ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr); @@ -381,12 +382,132 @@ static void test_topology(void) ok(hr == E_FAIL, "Unexpected hr %#x.\n", hr); ok(!object, "Unexpected object %p.\n", object);
- hr = IMFTopologyNode_GetCount(node, &attr_count); + hr = IMFTopologyNode_GetCount(node, &count); ok(hr == S_OK, "Failed to get attribute count, hr %#x.\n", hr); - ok(attr_count == 1, "Unexpected attribute count %u.\n", attr_count); + ok(count == 1, "Unexpected attribute count %u.\n", count); + + /* Preferred stream types. */ + hr = IMFTopologyNode_GetInputCount(node, &count); + ok(hr == S_OK, "Failed to get input count, hr %#x.\n", hr); + ok(count == 0, "Unexpected count %u.\n", count); + + hr = IMFTopologyNode_GetInputPrefType(node, 0, &mediatype); + ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr); + + hr = MFCreateMediaType(&mediatype); + ok(hr == S_OK, "Failed to create media type, hr %#x.\n", hr); + + hr = IMFTopologyNode_SetInputPrefType(node, 0, mediatype); + ok(hr == S_OK, "Failed to set preferred type, hr %#x.\n", hr); + + hr = IMFTopologyNode_GetInputPrefType(node, 0, &mediatype2); + ok(hr == S_OK, "Failed to get preferred type, hr %#x.\n", hr); + ok(mediatype2 == mediatype, "Unexpected mediatype instance.\n"); + IMFMediaType_Release(mediatype2); + + hr = IMFTopologyNode_SetInputPrefType(node, 0, NULL); + ok(hr == S_OK, "Failed to set preferred type, hr %#x.\n", hr); + + hr = IMFTopologyNode_GetInputPrefType(node, 0, &mediatype2); + ok(hr == E_FAIL, "Unexpected hr %#x.\n", hr); + ok(!mediatype2, "Unexpected mediatype instance.\n"); + + hr = IMFTopologyNode_SetInputPrefType(node, 1, mediatype); + ok(hr == S_OK, "Failed to set preferred type, hr %#x.\n", hr); + + hr = IMFTopologyNode_SetInputPrefType(node, 1, mediatype); + ok(hr == S_OK, "Failed to set preferred type, hr %#x.\n", hr); + + hr = IMFTopologyNode_GetInputCount(node, &count); + ok(hr == S_OK, "Failed to get input count, hr %#x.\n", hr); + ok(count == 2, "Unexpected count %u.\n", count); + + hr = IMFTopologyNode_GetOutputCount(node, &count); + ok(hr == S_OK, "Failed to get input count, hr %#x.\n", hr); + ok(count == 0, "Unexpected count %u.\n", count); + + hr = IMFTopologyNode_SetOutputPrefType(node, 0, mediatype); + ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr); + + IMFTopologyNode_Release(node); + + /* Source node. */ + hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &node); + ok(hr == S_OK, "Failed to create a node, hr %#x.\n", hr); + + hr = IMFTopologyNode_SetInputPrefType(node, 0, mediatype); + ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr); + + hr = IMFTopologyNode_SetOutputPrefType(node, 2, mediatype); + ok(hr == S_OK, "Failed to set preferred type, hr %#x.\n", hr); + + hr = IMFTopologyNode_GetOutputPrefType(node, 0, &mediatype2); + ok(hr == E_FAIL, "Failed to get preferred type, hr %#x.\n", hr); + ok(!mediatype2, "Unexpected mediatype instance.\n"); + + hr = IMFTopologyNode_GetOutputCount(node, &count); + ok(hr == S_OK, "Failed to get output count, hr %#x.\n", hr); + ok(count == 3, "Unexpected count %u.\n", count);
IMFTopologyNode_Release(node);
+ /* Tee node. */ + hr = MFCreateTopologyNode(MF_TOPOLOGY_TEE_NODE, &node); + ok(hr == S_OK, "Failed to create a node, hr %#x.\n", hr); + + hr = IMFTopologyNode_SetInputPrefType(node, 0, mediatype); + ok(hr == S_OK, "Failed to set preferred type, hr %#x.\n", hr); + + hr = IMFTopologyNode_GetInputPrefType(node, 0, &mediatype2); + ok(hr == S_OK, "Failed to get preferred type, hr %#x.\n", hr); + ok(mediatype2 == mediatype, "Unexpected mediatype instance.\n"); + IMFMediaType_Release(mediatype2); + + hr = IMFTopologyNode_GetInputCount(node, &count); + ok(hr == S_OK, "Failed to get output count, hr %#x.\n", hr); + ok(count == 0, "Unexpected count %u.\n", count); + + hr = IMFTopologyNode_SetInputPrefType(node, 1, mediatype); + ok(hr == MF_E_INVALIDTYPE, "Unexpected hr %#x.\n", hr); + + hr = IMFTopologyNode_SetInputPrefType(node, 3, mediatype); + ok(hr == MF_E_INVALIDTYPE, "Unexpected hr %#x.\n", hr); + + hr = IMFTopologyNode_SetOutputPrefType(node, 4, mediatype); + ok(hr == S_OK, "Failed to set preferred type, hr %#x.\n", hr); + + hr = IMFTopologyNode_GetInputCount(node, &count); + ok(hr == S_OK, "Failed to get output count, hr %#x.\n", hr); + ok(count == 0, "Unexpected count %u.\n", count); + + hr = IMFTopologyNode_GetOutputCount(node, &count); + ok(hr == S_OK, "Failed to get output count, hr %#x.\n", hr); + ok(count == 5, "Unexpected count %u.\n", count); + + IMFTopologyNode_Release(node); + + /* Transform node. */ + hr = MFCreateTopologyNode(MF_TOPOLOGY_TRANSFORM_NODE, &node); + ok(hr == S_OK, "Failed to create a node, hr %#x.\n", hr); + + hr = IMFTopologyNode_SetInputPrefType(node, 3, mediatype); + ok(hr == S_OK, "Failed to set preferred type, hr %#x.\n", hr); + + hr = IMFTopologyNode_SetOutputPrefType(node, 4, mediatype); + ok(hr == S_OK, "Failed to set preferred type, hr %#x.\n", hr); + + hr = IMFTopologyNode_GetInputCount(node, &count); + ok(hr == S_OK, "Failed to get output count, hr %#x.\n", hr); + ok(count == 4, "Unexpected count %u.\n", count); + + hr = IMFTopologyNode_GetOutputCount(node, &count); + ok(hr == S_OK, "Failed to get output count, hr %#x.\n", hr); + ok(count == 5, "Unexpected count %u.\n", count); + + IMFTopologyNode_Release(node); + + IMFMediaType_Release(mediatype); + hr = IMFTopology_GetOutputNodeCollection(topology, &collection); ok(hr == S_OK || broken(hr == E_FAIL) /* before Win8 */, "Failed to get output node collection, hr %#x.\n", hr); if (SUCCEEDED(hr)) diff --git a/dlls/mf/topology.c b/dlls/mf/topology.c index e01444b8ce..f40fe00c17 100644 --- a/dlls/mf/topology.c +++ b/dlls/mf/topology.c @@ -37,7 +37,8 @@ #include "mfidl.h"
#include "wine/debug.h" -#include "wine/heap.h" + +#include "mf_private.h"
WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
@@ -53,6 +54,11 @@ struct topology TOPOID id; };
+struct node_stream +{ + IMFMediaType *preferred_type; +}; + struct topology_node { IMFTopologyNode IMFTopologyNode_iface; @@ -61,6 +67,18 @@ struct topology_node MF_TOPOLOGY_TYPE node_type; TOPOID id; IUnknown *object; + struct + { + struct node_stream *streams; + size_t size; + size_t count; + } inputs; + struct + { + struct node_stream *streams; + size_t size; + size_t count; + } outputs; CRITICAL_SECTION cs; };
@@ -758,6 +776,7 @@ static ULONG WINAPI topology_node_Release(IMFTopologyNode *iface) { struct topology_node *node = impl_from_IMFTopologyNode(iface); ULONG refcount = InterlockedDecrement(&node->refcount); + unsigned int i;
TRACE("(%p) refcount=%u\n", iface, refcount);
@@ -765,6 +784,18 @@ static ULONG WINAPI topology_node_Release(IMFTopologyNode *iface) { if (node->object) IUnknown_Release(node->object); + for (i = 0; i < node->inputs.count; ++i) + { + if (node->inputs.streams[i].preferred_type) + IMFMediaType_Release(node->inputs.streams[i].preferred_type); + } + for (i = 0; i < node->outputs.count; ++i) + { + if (node->outputs.streams[i].preferred_type) + IMFMediaType_Release(node->outputs.streams[i].preferred_type); + } + heap_free(node->inputs.streams); + heap_free(node->outputs.streams); IMFAttributes_Release(node->attributes); DeleteCriticalSection(&node->cs); heap_free(node); @@ -1154,16 +1185,31 @@ static HRESULT WINAPI topology_node_SetTopoNodeID(IMFTopologyNode *iface, TOPOID
static HRESULT WINAPI topology_node_GetInputCount(IMFTopologyNode *iface, DWORD *count) { - FIXME("(%p)->(%p)\n", iface, count); + struct topology_node *node = impl_from_IMFTopologyNode(iface);
- return E_NOTIMPL; + TRACE("%p, %p.\n", iface, count); + + switch (node->node_type) + { + case MF_TOPOLOGY_TEE_NODE: + *count = 0; + break; + default: + *count = node->inputs.count; + } + + return S_OK; }
static HRESULT WINAPI topology_node_GetOutputCount(IMFTopologyNode *iface, DWORD *count) { - FIXME("(%p)->(%p)\n", iface, count); + struct topology_node *node = impl_from_IMFTopologyNode(iface);
- return E_NOTIMPL; + TRACE("%p, %p.\n", iface, count); + + *count = node->outputs.count; + + return S_OK; }
static HRESULT WINAPI topology_node_ConnectOutput(IMFTopologyNode *iface, DWORD output_index, @@ -1197,32 +1243,128 @@ static HRESULT WINAPI topology_node_GetOutput(IMFTopologyNode *iface, DWORD outp return E_NOTIMPL; }
-static HRESULT WINAPI topology_node_SetOutputPrefType(IMFTopologyNode *iface, DWORD index, IMFMediaType *type) +static HRESULT WINAPI topology_node_SetOutputPrefType(IMFTopologyNode *iface, DWORD index, IMFMediaType *mediatype) { - FIXME("(%p)->(%u, %p)\n", iface, index, type); + struct topology_node *node = impl_from_IMFTopologyNode(iface); + HRESULT hr = S_OK;
- return E_NOTIMPL; + TRACE("%p, %u, %p.\n", iface, index, mediatype); + + EnterCriticalSection(&node->cs); + + if (node->node_type != MF_TOPOLOGY_OUTPUT_NODE) + { + if (mf_array_reserve((void **)&node->outputs.streams, &node->outputs.size, index + 1, + sizeof(*node->outputs.streams))) + { + if (index >= node->outputs.count) + { + memset(&node->outputs.streams[node->outputs.count], 0, + (index - node->outputs.count + 1) * sizeof(*node->outputs.streams)); + node->outputs.count = index + 1; + } + if (node->outputs.streams[index].preferred_type) + IMFMediaType_Release(node->outputs.streams[index].preferred_type); + node->outputs.streams[index].preferred_type = mediatype; + if (node->outputs.streams[index].preferred_type) + IMFMediaType_AddRef(node->outputs.streams[index].preferred_type); + } + else + hr = E_OUTOFMEMORY; + } + else + hr = E_NOTIMPL; + + LeaveCriticalSection(&node->cs); + + return hr; }
-static HRESULT WINAPI topology_node_GetOutputPrefType(IMFTopologyNode *iface, DWORD output_index, IMFMediaType **type) +static HRESULT WINAPI topology_node_GetOutputPrefType(IMFTopologyNode *iface, DWORD index, IMFMediaType **mediatype) { - FIXME("(%p)->(%u, %p)\n", iface, output_index, type); + struct topology_node *node = impl_from_IMFTopologyNode(iface); + HRESULT hr = S_OK;
- return E_NOTIMPL; + TRACE("%p, %u, %p.\n", iface, index, mediatype); + + EnterCriticalSection(&node->cs); + + if (index < node->outputs.count) + { + *mediatype = node->outputs.streams[index].preferred_type; + if (*mediatype) + IMFMediaType_AddRef(*mediatype); + else + hr = E_FAIL; + } + else + hr = E_INVALIDARG; + + LeaveCriticalSection(&node->cs); + + return hr; }
-static HRESULT WINAPI topology_node_SetInputPrefType(IMFTopologyNode *iface, DWORD index, IMFMediaType *type) +static HRESULT WINAPI topology_node_SetInputPrefType(IMFTopologyNode *iface, DWORD index, IMFMediaType *mediatype) { - FIXME("(%p)->(%u, %p)\n", iface, index, type); + struct topology_node *node = impl_from_IMFTopologyNode(iface); + HRESULT hr = S_OK;
- return E_NOTIMPL; + TRACE("%p, %u, %p.\n", iface, index, mediatype); + + EnterCriticalSection(&node->cs); + + if (node->node_type != MF_TOPOLOGY_SOURCESTREAM_NODE && !(index > 0 && node->node_type == MF_TOPOLOGY_TEE_NODE)) + { + if (mf_array_reserve((void **)&node->inputs.streams, &node->inputs.size, index + 1, + sizeof(*node->inputs.streams))) + { + if (index >= node->inputs.count) + { + memset(&node->inputs.streams[node->inputs.count], 0, + (index - node->inputs.count + 1) * sizeof(*node->inputs.streams)); + node->inputs.count = index + 1; + } + if (node->inputs.streams[index].preferred_type) + IMFMediaType_Release(node->inputs.streams[index].preferred_type); + node->inputs.streams[index].preferred_type = mediatype; + if (node->inputs.streams[index].preferred_type) + IMFMediaType_AddRef(node->inputs.streams[index].preferred_type); + } + else + hr = E_OUTOFMEMORY; + } + else + hr = node->node_type == MF_TOPOLOGY_TEE_NODE ? MF_E_INVALIDTYPE : E_NOTIMPL; + + LeaveCriticalSection(&node->cs); + + return hr; }
-static HRESULT WINAPI topology_node_GetInputPrefType(IMFTopologyNode *iface, DWORD index, IMFMediaType **type) +static HRESULT WINAPI topology_node_GetInputPrefType(IMFTopologyNode *iface, DWORD index, IMFMediaType **mediatype) { - FIXME("(%p)->(%u, %p)\n", iface, index, type); + struct topology_node *node = impl_from_IMFTopologyNode(iface); + HRESULT hr = S_OK;
- return E_NOTIMPL; + TRACE("%p, %u, %p.\n", iface, index, mediatype); + + EnterCriticalSection(&node->cs); + + if (index < node->inputs.count) + { + *mediatype = node->inputs.streams[index].preferred_type; + if (*mediatype) + IMFMediaType_AddRef(*mediatype); + else + hr = E_FAIL; + } + else + hr = E_INVALIDARG; + + LeaveCriticalSection(&node->cs); + + return hr; }
static HRESULT WINAPI topology_node_CloneFrom(IMFTopologyNode *iface, IMFTopologyNode *node)
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mf/topology.c | 53 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 46 insertions(+), 7 deletions(-)
diff --git a/dlls/mf/topology.c b/dlls/mf/topology.c index f40fe00c17..298200c40d 100644 --- a/dlls/mf/topology.c +++ b/dlls/mf/topology.c @@ -1078,18 +1078,15 @@ static HRESULT WINAPI topology_node_CopyAllItems(IMFTopologyNode *iface, IMFAttr return IMFAttributes_CopyAllItems(node->attributes, dest); }
-static HRESULT WINAPI topology_node_SetObject(IMFTopologyNode *iface, IUnknown *object) +static HRESULT topology_node_set_object(struct topology_node *node, IUnknown *object) { static const GUID *iids[3] = { &IID_IPersist, &IID_IPersistStorage, &IID_IPersistPropertyBag }; - struct topology_node *node = impl_from_IMFTopologyNode(iface); IPersist *persist = NULL; BOOL has_object_id; GUID object_id; unsigned int i; HRESULT hr;
- TRACE("%p, %p.\n", iface, object); - has_object_id = IMFAttributes_GetGUID(node->attributes, &MF_TOPONODE_TRANSFORM_OBJECTID, &object_id) == S_OK;
if (object && !has_object_id) @@ -1130,6 +1127,15 @@ static HRESULT WINAPI topology_node_SetObject(IMFTopologyNode *iface, IUnknown * return S_OK; }
+static HRESULT WINAPI topology_node_SetObject(IMFTopologyNode *iface, IUnknown *object) +{ + struct topology_node *node = impl_from_IMFTopologyNode(iface); + + TRACE("%p, %p.\n", iface, object); + + return topology_node_set_object(node, object); +} + static HRESULT WINAPI topology_node_GetObject(IMFTopologyNode *iface, IUnknown **object) { struct topology_node *node = impl_from_IMFTopologyNode(iface); @@ -1367,11 +1373,44 @@ static HRESULT WINAPI topology_node_GetInputPrefType(IMFTopologyNode *iface, DWO return hr; }
-static HRESULT WINAPI topology_node_CloneFrom(IMFTopologyNode *iface, IMFTopologyNode *node) +static HRESULT WINAPI topology_node_CloneFrom(IMFTopologyNode *iface, IMFTopologyNode *src_node) { - FIXME("(%p)->(%p)\n", iface, node); + struct topology_node *node = impl_from_IMFTopologyNode(iface); + MF_TOPOLOGY_TYPE node_type; + IUnknown *object; + TOPOID topoid; + HRESULT hr;
- return E_NOTIMPL; + TRACE("%p, %p.\n", iface, src_node); + + if (FAILED(hr = IMFTopologyNode_GetNodeType(src_node, &node_type))) + return hr; + + if (node->node_type != node_type) + return MF_E_INVALIDREQUEST; + + if (FAILED(hr = IMFTopologyNode_GetTopoNodeID(src_node, &topoid))) + return hr; + + object = NULL; + IMFTopologyNode_GetObject(src_node, &object); + + EnterCriticalSection(&node->cs); + + hr = IMFTopologyNode_CopyAllItems(src_node, node->attributes); + + if (SUCCEEDED(hr)) + hr = topology_node_set_object(node, object); + + if (SUCCEEDED(hr)) + node->id = topoid; + + LeaveCriticalSection(&node->cs); + + if (object) + IUnknown_Release(object); + + return hr; }
static const IMFTopologyNodeVtbl topologynodevtbl =