From e196619f699b2e67d759dbf1f220892c31800639 Mon Sep 17 00:00:00 2001 From: Nikolay Sivov Date: Fri, 22 May 2020 17:15:09 +0300 Subject: [PATCH] mf/topology: Setting tee node input type does not create input stream. Signed-off-by: Nikolay Sivov Signed-off-by: Alexandre Julliard --- dlls/mf/tests/mf.c | 91 +++++++++++++++++++++++++++++++++++- dlls/mf/topology.c | 114 ++++++++++++++++++++++++++++----------------- 2 files changed, 162 insertions(+), 43 deletions(-) diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index bf14ccf0feb..c79ae69f91d 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -114,11 +114,11 @@ static const IUnknownVtbl test_unk_vtbl = static void test_topology(void) { + IMFMediaType *mediatype, *mediatype2, *mediatype3; IMFCollection *collection, *collection2; IUnknown test_unk2 = { &test_unk_vtbl }; IUnknown test_unk = { &test_unk_vtbl }; IMFTopologyNode *node, *node2, *node3; - IMFMediaType *mediatype, *mediatype2; IMFTopology *topology, *topology2; MF_TOPOLOGY_TYPE node_type; UINT32 count, index; @@ -516,6 +516,9 @@ static void test_topology(void) ok(mediatype2 == mediatype, "Unexpected mediatype instance.\n"); IMFMediaType_Release(mediatype2); + hr = IMFTopologyNode_GetOutputPrefType(node, 0, &mediatype2); + ok(hr == E_INVALIDARG, "Unexpected 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); @@ -529,6 +532,23 @@ static void test_topology(void) hr = IMFTopologyNode_SetOutputPrefType(node, 4, mediatype); ok(hr == S_OK, "Failed to set preferred type, hr %#x.\n", hr); + hr = IMFTopologyNode_GetOutputPrefType(node, 0, &mediatype2); + ok(hr == E_FAIL, "Unexpected hr %#x.\n", hr); + + hr = MFCreateMediaType(&mediatype2); + ok(hr == S_OK, "Failed to create media type, hr %#x.\n", hr); + + /* Changing output type does not change input type. */ + hr = IMFTopologyNode_SetOutputPrefType(node, 4, mediatype2); + ok(hr == S_OK, "Failed to set preferred type, hr %#x.\n", hr); + + hr = IMFTopologyNode_GetInputPrefType(node, 0, &mediatype3); + ok(hr == S_OK, "Failed to get preferred type, hr %#x.\n", hr); + ok(mediatype3 == mediatype, "Unexpected mediatype instance.\n"); + IMFMediaType_Release(mediatype3); + + 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); @@ -546,6 +566,10 @@ static void test_topology(void) hr = IMFTopologyNode_SetInputPrefType(node, 3, 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 == 4, "Unexpected count %u.\n", count); + hr = IMFTopologyNode_SetOutputPrefType(node, 4, mediatype); ok(hr == S_OK, "Failed to set preferred type, hr %#x.\n", hr); @@ -800,6 +824,70 @@ static void test_topology(void) IMFTopology_Release(topology); } +static void test_topology_tee_node(void) +{ + IMFTopologyNode *src_node, *tee_node; + IMFMediaType *mediatype, *mediatype2; + IMFTopology *topology; + unsigned int count; + HRESULT hr; + + hr = MFCreateTopology(&topology); + ok(hr == S_OK, "Failed to create topology, hr %#x.\n", hr); + + hr = MFCreateMediaType(&mediatype); + ok(hr == S_OK, "Failed to create media type, hr %#x.\n", hr); + + hr = MFCreateTopologyNode(MF_TOPOLOGY_TEE_NODE, &tee_node); + ok(hr == S_OK, "Failed to create topology node, hr %#x.\n", hr); + + hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &src_node); + ok(hr == S_OK, "Failed to create topology node, hr %#x.\n", hr); + + hr = IMFTopologyNode_SetInputPrefType(tee_node, 0, mediatype); + ok(hr == S_OK, "Failed to set type, hr %#x.\n", hr); + + /* Even though tee node has only one input and source has only one output, + it's possible to connect to higher inputs/outputs. */ + + /* SRC(0) -> TEE(0) */ + hr = IMFTopologyNode_ConnectOutput(src_node, 0, tee_node, 0); + ok(hr == S_OK, "Failed to connect nodes, hr %#x.\n", hr); + + hr = IMFTopologyNode_GetInputCount(tee_node, &count); + ok(hr == S_OK, "Failed to get count, hr %#x.\n", hr); + ok(count == 1, "Unexpected count %u.\n", count); + + hr = IMFTopologyNode_GetInputPrefType(tee_node, 0, &mediatype2); + ok(hr == S_OK, "Failed to get type, hr %#x.\n", hr); + ok(mediatype2 == mediatype, "Unexpected type.\n"); + IMFMediaType_Release(mediatype2); + + /* SRC(0) -> TEE(1) */ + hr = IMFTopologyNode_ConnectOutput(src_node, 0, tee_node, 1); + ok(hr == S_OK, "Failed to connect nodes, hr %#x.\n", hr); + + hr = IMFTopologyNode_GetInputCount(tee_node, &count); + ok(hr == S_OK, "Failed to get count, hr %#x.\n", hr); + ok(count == 2, "Unexpected count %u.\n", count); + + hr = IMFTopologyNode_SetInputPrefType(tee_node, 1, mediatype); + ok(hr == MF_E_INVALIDTYPE, "Unexpected hr %#x.\n", hr); + + /* SRC(1) -> TEE(1) */ + hr = IMFTopologyNode_ConnectOutput(src_node, 1, tee_node, 1); + ok(hr == S_OK, "Failed to connect nodes, hr %#x.\n", hr); + + hr = IMFTopologyNode_GetOutputCount(src_node, &count); + ok(hr == S_OK, "Failed to get count, hr %#x.\n", hr); + ok(count == 2, "Unexpected count %u.\n", count); + + IMFMediaType_Release(mediatype); + IMFTopologyNode_Release(src_node); + IMFTopologyNode_Release(tee_node); + IMFTopology_Release(topology); +} + static HRESULT WINAPI test_getservice_QI(IMFGetService *iface, REFIID riid, void **obj) { if (IsEqualIID(riid, &IID_IMFGetService) || IsEqualIID(riid, &IID_IUnknown)) @@ -3725,6 +3813,7 @@ static void test_MFGetTopoNodeCurrentType(void) START_TEST(mf) { test_topology(); + test_topology_tee_node(); test_topology_loader(); test_MFGetService(); test_sequencer_source(); diff --git a/dlls/mf/topology.c b/dlls/mf/topology.c index 0b4d7344422..91635fd6b8b 100644 --- a/dlls/mf/topology.c +++ b/dlls/mf/topology.c @@ -61,6 +61,7 @@ struct topology_node MF_TOPOLOGY_TYPE node_type; TOPOID id; IUnknown *object; + IMFMediaType *input_type; /* Only for tee nodes. */ struct node_streams inputs; struct node_streams outputs; CRITICAL_SECTION cs; @@ -950,6 +951,8 @@ static ULONG WINAPI topology_node_Release(IMFTopologyNode *iface) { if (node->object) IUnknown_Release(node->object); + if (node->input_type) + IMFMediaType_Release(node->input_type); for (i = 0; i < node->inputs.count; ++i) { if (node->inputs.streams[i].preferred_type) @@ -1361,14 +1364,7 @@ static HRESULT WINAPI topology_node_GetInputCount(IMFTopologyNode *iface, DWORD TRACE("%p, %p.\n", iface, count); - switch (node->node_type) - { - case MF_TOPOLOGY_TEE_NODE: - *count = 0; - break; - default: - *count = node->inputs.count; - } + *count = node->inputs.count; return S_OK; } @@ -1384,6 +1380,15 @@ static HRESULT WINAPI topology_node_GetOutputCount(IMFTopologyNode *iface, DWORD return S_OK; } +static void topology_node_set_stream_type(struct node_stream *stream, IMFMediaType *mediatype) +{ + if (stream->preferred_type) + IMFMediaType_Release(stream->preferred_type); + stream->preferred_type = mediatype; + if (stream->preferred_type) + IMFMediaType_AddRef(stream->preferred_type); +} + static HRESULT topology_node_connect_output(struct topology_node *node, DWORD output_index, struct topology_node *connection, DWORD input_index) { @@ -1406,7 +1411,16 @@ static HRESULT topology_node_connect_output(struct topology_node *node, DWORD ou hr = topology_node_reserve_streams(&node->outputs, output_index); if (SUCCEEDED(hr)) + { + size_t old_count = connection->inputs.count; hr = topology_node_reserve_streams(&connection->inputs, input_index); + if (SUCCEEDED(hr) && !old_count && connection->input_type) + { + topology_node_set_stream_type(connection->inputs.streams, connection->input_type); + IMFMediaType_Release(connection->input_type); + connection->input_type = NULL; + } + } if (SUCCEEDED(hr)) { @@ -1524,13 +1538,7 @@ static HRESULT WINAPI topology_node_SetOutputPrefType(IMFTopologyNode *iface, DW if (node->node_type != MF_TOPOLOGY_OUTPUT_NODE) { if (SUCCEEDED(hr = topology_node_reserve_streams(&node->outputs, index))) - { - 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); - } + topology_node_set_stream_type(&node->outputs.streams[index], mediatype); } else hr = E_NOTIMPL; @@ -1540,6 +1548,18 @@ static HRESULT WINAPI topology_node_SetOutputPrefType(IMFTopologyNode *iface, DW return hr; } +static HRESULT topology_node_get_pref_type(struct node_streams *streams, unsigned int index, IMFMediaType **mediatype) +{ + *mediatype = streams->streams[index].preferred_type; + if (*mediatype) + { + IMFMediaType_AddRef(*mediatype); + return S_OK; + } + + return E_FAIL; +} + static HRESULT WINAPI topology_node_GetOutputPrefType(IMFTopologyNode *iface, DWORD index, IMFMediaType **mediatype) { struct topology_node *node = impl_from_IMFTopologyNode(iface); @@ -1550,13 +1570,7 @@ static HRESULT WINAPI topology_node_GetOutputPrefType(IMFTopologyNode *iface, DW EnterCriticalSection(&node->cs); if (index < node->outputs.count) - { - *mediatype = node->outputs.streams[index].preferred_type; - if (*mediatype) - IMFMediaType_AddRef(*mediatype); - else - hr = E_FAIL; - } + hr = topology_node_get_pref_type(&node->outputs, index, mediatype); else hr = E_INVALIDARG; @@ -1574,25 +1588,40 @@ static HRESULT WINAPI topology_node_SetInputPrefType(IMFTopologyNode *iface, DWO EnterCriticalSection(&node->cs); - if (node->node_type != MF_TOPOLOGY_SOURCESTREAM_NODE && !(index > 0 && node->node_type == MF_TOPOLOGY_TEE_NODE)) + switch (node->node_type) { - if (SUCCEEDED(hr = topology_node_reserve_streams(&node->inputs, index))) - { - if (index >= node->inputs.count) + case MF_TOPOLOGY_TEE_NODE: + if (index) { - memset(&node->inputs.streams[node->inputs.count], 0, - (index - node->inputs.count + 1) * sizeof(*node->inputs.streams)); - node->inputs.count = index + 1; + hr = MF_E_INVALIDTYPE; + break; + } + if (node->inputs.count) + topology_node_set_stream_type(&node->inputs.streams[index], mediatype); + else + { + if (node->input_type) + IMFMediaType_Release(node->input_type); + node->input_type = mediatype; + if (node->input_type) + IMFMediaType_AddRef(node->input_type); + } + break; + case MF_TOPOLOGY_SOURCESTREAM_NODE: + hr = E_NOTIMPL; + break; + default: + if (SUCCEEDED(hr = topology_node_reserve_streams(&node->inputs, index))) + { + 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; + } + topology_node_set_stream_type(&node->inputs.streams[index], mediatype); } - 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 = node->node_type == MF_TOPOLOGY_TEE_NODE ? MF_E_INVALIDTYPE : E_NOTIMPL; LeaveCriticalSection(&node->cs); @@ -1610,11 +1639,12 @@ static HRESULT WINAPI topology_node_GetInputPrefType(IMFTopologyNode *iface, DWO if (index < node->inputs.count) { - *mediatype = node->inputs.streams[index].preferred_type; - if (*mediatype) - IMFMediaType_AddRef(*mediatype); - else - hr = E_FAIL; + hr = topology_node_get_pref_type(&node->inputs, index, mediatype); + } + else if (node->node_type == MF_TOPOLOGY_TEE_NODE && node->input_type) + { + *mediatype = node->input_type; + IMFMediaType_AddRef(*mediatype); } else hr = E_INVALIDARG;