Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mf/mf.spec | 2 +- dlls/mf/tests/mf.c | 81 +++++++++++++++++++++++++++++++++++++++++++ dlls/mf/topology.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++ include/mfidl.idl | 1 + 4 files changed, 168 insertions(+), 1 deletion(-)
diff --git a/dlls/mf/mf.spec b/dlls/mf/mf.spec index 1c3fc9c953..4b5b085d08 100644 --- a/dlls/mf/mf.spec +++ b/dlls/mf/mf.spec @@ -75,7 +75,7 @@ @ stdcall MFGetService(ptr ptr ptr ptr) @ stdcall MFGetSupportedMimeTypes(ptr) @ stdcall MFGetSupportedSchemes(ptr) -@ stub MFGetTopoNodeCurrentType +@ stdcall MFGetTopoNodeCurrentType(ptr long long ptr) @ stub MFReadSequencerSegmentOffset @ stub MFRequireProtectedEnvironment @ stdcall MFShutdownObject(ptr) diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index dcb20aff05..da533d05d3 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -3103,6 +3103,86 @@ static void test_sample_copier(void) IMFTransform_Release(copier); }
+static void test_MFGetTopoNodeCurrentType(void) +{ + IMFMediaType *media_type, *media_type2; + IMFTopologyNode *node; + HRESULT hr; + + /* Tee node. */ + hr = MFCreateTopologyNode(MF_TOPOLOGY_TEE_NODE, &node); + ok(hr == S_OK, "Failed to create a node, hr %#x.\n", hr); + + hr = MFGetTopoNodeCurrentType(node, 0, TRUE, &media_type); + ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr); + + hr = MFGetTopoNodeCurrentType(node, 0, FALSE, &media_type); + ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr); + + hr = MFCreateMediaType(&media_type2); + ok(hr == S_OK, "Failed to create media type, hr %#x.\n", hr); + + hr = IMFMediaType_SetGUID(media_type2, &MF_MT_MAJOR_TYPE, &MFMediaType_Video); + ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr); + + /* Input type returned, if set. */ + hr = IMFTopologyNode_SetInputPrefType(node, 0, media_type2); + ok(hr == S_OK, "Failed to set media type, hr %#x.\n", hr); + + hr = MFGetTopoNodeCurrentType(node, 0, FALSE, &media_type); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(media_type == media_type2, "Unexpected pointer.\n"); + IMFMediaType_Release(media_type); + + hr = IMFTopologyNode_SetInputPrefType(node, 0, NULL); + ok(hr == S_OK, "Failed to set media type, hr %#x.\n", hr); + + hr = MFGetTopoNodeCurrentType(node, 0, FALSE, &media_type); + ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr); + + /* Set second output. */ + hr = IMFTopologyNode_SetOutputPrefType(node, 1, media_type2); + ok(hr == S_OK, "Failed to set media type, hr %#x.\n", hr); + + hr = MFGetTopoNodeCurrentType(node, 0, FALSE, &media_type); + ok(hr == E_FAIL, "Unexpected hr %#x.\n", hr); + + hr = IMFTopologyNode_SetOutputPrefType(node, 1, NULL); + ok(hr == S_OK, "Failed to set media type, hr %#x.\n", hr); + + /* Set first output. */ + hr = IMFTopologyNode_SetOutputPrefType(node, 0, media_type2); + ok(hr == S_OK, "Failed to set media type, hr %#x.\n", hr); + + hr = MFGetTopoNodeCurrentType(node, 0, FALSE, &media_type); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(media_type == media_type2, "Unexpected pointer.\n"); + IMFMediaType_Release(media_type); + + hr = IMFTopologyNode_SetOutputPrefType(node, 0, NULL); + ok(hr == S_OK, "Failed to set media type, hr %#x.\n", hr); + + /* Set primary output. */ + hr = IMFTopologyNode_SetOutputPrefType(node, 1, media_type2); + ok(hr == S_OK, "Failed to set media type, hr %#x.\n", hr); + + hr = IMFTopologyNode_SetUINT32(node, &MF_TOPONODE_PRIMARYOUTPUT, 1); + ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr); + + hr = MFGetTopoNodeCurrentType(node, 0, FALSE, &media_type); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(media_type == media_type2, "Unexpected pointer.\n"); + IMFMediaType_Release(media_type); + + hr = MFGetTopoNodeCurrentType(node, 0, TRUE, &media_type); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(media_type == media_type2, "Unexpected pointer.\n"); + IMFMediaType_Release(media_type); + + IMFTopologyNode_Release(node); + IMFMediaType_Release(media_type2); +} + START_TEST(mf) { test_topology(); @@ -3121,4 +3201,5 @@ START_TEST(mf) test_MFGetSupportedMimeTypes(); test_MFGetSupportedSchemes(); test_sample_copier(); + test_MFGetTopoNodeCurrentType(); } diff --git a/dlls/mf/topology.c b/dlls/mf/topology.c index db82816328..67afba6ba4 100644 --- a/dlls/mf/topology.c +++ b/dlls/mf/topology.c @@ -1786,6 +1786,91 @@ HRESULT WINAPI MFCreateTopologyNode(MF_TOPOLOGY_TYPE node_type, IMFTopologyNode return hr; }
+/*********************************************************************** + * MFGetTopoNodeCurrentType (mf.@) + */ +HRESULT WINAPI MFGetTopoNodeCurrentType(IMFTopologyNode *node, DWORD stream, BOOL output, IMFMediaType **type) +{ + IMFMediaTypeHandler *type_handler; + MF_TOPOLOGY_TYPE node_type; + IMFStreamSink *stream_sink; + IMFStreamDescriptor *sd; + IMFTransform *transform; + UINT32 primary_output; + IUnknown *object; + HRESULT hr; + + TRACE("%p, %u, %d, %p.\n", node, stream, output, type); + + if (FAILED(hr = IMFTopologyNode_GetNodeType(node, &node_type))) + return hr; + + switch (node_type) + { + case MF_TOPOLOGY_OUTPUT_NODE: + if (FAILED(hr = IMFTopologyNode_GetObject(node, &object))) + return hr; + + hr = IUnknown_QueryInterface(object, &IID_IMFStreamSink, (void **)&stream_sink); + IUnknown_Release(object); + if (SUCCEEDED(hr)) + { + hr = IMFStreamSink_GetMediaTypeHandler(stream_sink, &type_handler); + IMFStreamSink_Release(stream_sink); + + if (SUCCEEDED(hr)) + { + hr = IMFMediaTypeHandler_GetCurrentMediaType(type_handler, type); + IMFMediaTypeHandler_Release(type_handler); + } + } + break; + case MF_TOPOLOGY_SOURCESTREAM_NODE: + if (FAILED(hr = IMFTopologyNode_GetUnknown(node, &MF_TOPONODE_STREAM_DESCRIPTOR, &IID_IMFStreamDescriptor, + (void **)&sd))) + { + return hr; + } + + hr = IMFStreamDescriptor_GetMediaTypeHandler(sd, &type_handler); + IMFStreamDescriptor_Release(sd); + if (SUCCEEDED(hr)) + { + hr = IMFMediaTypeHandler_GetCurrentMediaType(type_handler, type); + IMFMediaTypeHandler_Release(type_handler); + } + break; + case MF_TOPOLOGY_TRANSFORM_NODE: + if (FAILED(hr = IMFTopologyNode_GetObject(node, &object))) + return hr; + + hr = IUnknown_QueryInterface(object, &IID_IMFTransform, (void **)&transform); + IUnknown_Release(object); + if (SUCCEEDED(hr)) + { + if (output) + hr = IMFTransform_GetOutputCurrentType(transform, stream, type); + else + hr = IMFTransform_GetInputCurrentType(transform, stream, type); + IMFTransform_Release(transform); + } + break; + case MF_TOPOLOGY_TEE_NODE: + if (SUCCEEDED(hr = IMFTopologyNode_GetInputPrefType(node, 0, type))) + break; + + if (FAILED(IMFTopologyNode_GetUINT32(node, &MF_TOPONODE_PRIMARYOUTPUT, &primary_output))) + primary_output = 0; + + hr = IMFTopologyNode_GetOutputPrefType(node, primary_output, type); + break; + default: + ; + } + + return hr; +} + static HRESULT WINAPI topology_loader_QueryInterface(IMFTopoLoader *iface, REFIID riid, void **out) { TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), out); diff --git a/include/mfidl.idl b/include/mfidl.idl index cf04ec17ce..60337f8106 100644 --- a/include/mfidl.idl +++ b/include/mfidl.idl @@ -609,6 +609,7 @@ cpp_quote("HRESULT WINAPI MFGetSupportedMimeTypes(PROPVARIANT *array);") cpp_quote("HRESULT WINAPI MFGetSupportedSchemes(PROPVARIANT *array);") cpp_quote("HRESULT WINAPI MFGetService(IUnknown *object, REFGUID service, REFIID iid, void **obj);") cpp_quote("MFTIME WINAPI MFGetSystemTime(void);") +cpp_quote("HRESULT WINAPI MFGetTopoNodeCurrentType(IMFTopologyNode *node, DWORD stream, BOOL output, IMFMediaType **type);") cpp_quote("HRESULT WINAPI MFShutdownObject(IUnknown *object);")
typedef enum _MFMEDIASOURCE_CHARACTERISTICS