Commit e196619f authored by Nikolay Sivov's avatar Nikolay Sivov Committed by Alexandre Julliard

mf/topology: Setting tee node input type does not create input stream.

parent 42ce4910
...@@ -114,11 +114,11 @@ static const IUnknownVtbl test_unk_vtbl = ...@@ -114,11 +114,11 @@ static const IUnknownVtbl test_unk_vtbl =
static void test_topology(void) static void test_topology(void)
{ {
IMFMediaType *mediatype, *mediatype2, *mediatype3;
IMFCollection *collection, *collection2; IMFCollection *collection, *collection2;
IUnknown test_unk2 = { &test_unk_vtbl }; IUnknown test_unk2 = { &test_unk_vtbl };
IUnknown test_unk = { &test_unk_vtbl }; IUnknown test_unk = { &test_unk_vtbl };
IMFTopologyNode *node, *node2, *node3; IMFTopologyNode *node, *node2, *node3;
IMFMediaType *mediatype, *mediatype2;
IMFTopology *topology, *topology2; IMFTopology *topology, *topology2;
MF_TOPOLOGY_TYPE node_type; MF_TOPOLOGY_TYPE node_type;
UINT32 count, index; UINT32 count, index;
...@@ -516,6 +516,9 @@ static void test_topology(void) ...@@ -516,6 +516,9 @@ static void test_topology(void)
ok(mediatype2 == mediatype, "Unexpected mediatype instance.\n"); ok(mediatype2 == mediatype, "Unexpected mediatype instance.\n");
IMFMediaType_Release(mediatype2); IMFMediaType_Release(mediatype2);
hr = IMFTopologyNode_GetOutputPrefType(node, 0, &mediatype2);
ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
hr = IMFTopologyNode_GetInputCount(node, &count); hr = IMFTopologyNode_GetInputCount(node, &count);
ok(hr == S_OK, "Failed to get output count, hr %#x.\n", hr); ok(hr == S_OK, "Failed to get output count, hr %#x.\n", hr);
ok(count == 0, "Unexpected count %u.\n", count); ok(count == 0, "Unexpected count %u.\n", count);
...@@ -529,6 +532,23 @@ static void test_topology(void) ...@@ -529,6 +532,23 @@ static void test_topology(void)
hr = IMFTopologyNode_SetOutputPrefType(node, 4, mediatype); hr = IMFTopologyNode_SetOutputPrefType(node, 4, mediatype);
ok(hr == S_OK, "Failed to set preferred type, hr %#x.\n", hr); 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); hr = IMFTopologyNode_GetInputCount(node, &count);
ok(hr == S_OK, "Failed to get output count, hr %#x.\n", hr); ok(hr == S_OK, "Failed to get output count, hr %#x.\n", hr);
ok(count == 0, "Unexpected count %u.\n", count); ok(count == 0, "Unexpected count %u.\n", count);
...@@ -546,6 +566,10 @@ static void test_topology(void) ...@@ -546,6 +566,10 @@ static void test_topology(void)
hr = IMFTopologyNode_SetInputPrefType(node, 3, mediatype); hr = IMFTopologyNode_SetInputPrefType(node, 3, mediatype);
ok(hr == S_OK, "Failed to set preferred type, hr %#x.\n", hr); 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); hr = IMFTopologyNode_SetOutputPrefType(node, 4, mediatype);
ok(hr == S_OK, "Failed to set preferred type, hr %#x.\n", hr); ok(hr == S_OK, "Failed to set preferred type, hr %#x.\n", hr);
...@@ -800,6 +824,70 @@ static void test_topology(void) ...@@ -800,6 +824,70 @@ static void test_topology(void)
IMFTopology_Release(topology); 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) static HRESULT WINAPI test_getservice_QI(IMFGetService *iface, REFIID riid, void **obj)
{ {
if (IsEqualIID(riid, &IID_IMFGetService) || IsEqualIID(riid, &IID_IUnknown)) if (IsEqualIID(riid, &IID_IMFGetService) || IsEqualIID(riid, &IID_IUnknown))
...@@ -3725,6 +3813,7 @@ static void test_MFGetTopoNodeCurrentType(void) ...@@ -3725,6 +3813,7 @@ static void test_MFGetTopoNodeCurrentType(void)
START_TEST(mf) START_TEST(mf)
{ {
test_topology(); test_topology();
test_topology_tee_node();
test_topology_loader(); test_topology_loader();
test_MFGetService(); test_MFGetService();
test_sequencer_source(); test_sequencer_source();
......
...@@ -61,6 +61,7 @@ struct topology_node ...@@ -61,6 +61,7 @@ struct topology_node
MF_TOPOLOGY_TYPE node_type; MF_TOPOLOGY_TYPE node_type;
TOPOID id; TOPOID id;
IUnknown *object; IUnknown *object;
IMFMediaType *input_type; /* Only for tee nodes. */
struct node_streams inputs; struct node_streams inputs;
struct node_streams outputs; struct node_streams outputs;
CRITICAL_SECTION cs; CRITICAL_SECTION cs;
...@@ -950,6 +951,8 @@ static ULONG WINAPI topology_node_Release(IMFTopologyNode *iface) ...@@ -950,6 +951,8 @@ static ULONG WINAPI topology_node_Release(IMFTopologyNode *iface)
{ {
if (node->object) if (node->object)
IUnknown_Release(node->object); IUnknown_Release(node->object);
if (node->input_type)
IMFMediaType_Release(node->input_type);
for (i = 0; i < node->inputs.count; ++i) for (i = 0; i < node->inputs.count; ++i)
{ {
if (node->inputs.streams[i].preferred_type) if (node->inputs.streams[i].preferred_type)
...@@ -1361,14 +1364,7 @@ static HRESULT WINAPI topology_node_GetInputCount(IMFTopologyNode *iface, DWORD ...@@ -1361,14 +1364,7 @@ static HRESULT WINAPI topology_node_GetInputCount(IMFTopologyNode *iface, DWORD
TRACE("%p, %p.\n", iface, count); TRACE("%p, %p.\n", iface, count);
switch (node->node_type) *count = node->inputs.count;
{
case MF_TOPOLOGY_TEE_NODE:
*count = 0;
break;
default:
*count = node->inputs.count;
}
return S_OK; return S_OK;
} }
...@@ -1384,6 +1380,15 @@ static HRESULT WINAPI topology_node_GetOutputCount(IMFTopologyNode *iface, DWORD ...@@ -1384,6 +1380,15 @@ static HRESULT WINAPI topology_node_GetOutputCount(IMFTopologyNode *iface, DWORD
return S_OK; 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, static HRESULT topology_node_connect_output(struct topology_node *node, DWORD output_index,
struct topology_node *connection, DWORD input_index) struct topology_node *connection, DWORD input_index)
{ {
...@@ -1406,7 +1411,16 @@ static HRESULT topology_node_connect_output(struct topology_node *node, DWORD ou ...@@ -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); hr = topology_node_reserve_streams(&node->outputs, output_index);
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{
size_t old_count = connection->inputs.count;
hr = topology_node_reserve_streams(&connection->inputs, input_index); 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)) if (SUCCEEDED(hr))
{ {
...@@ -1524,13 +1538,7 @@ static HRESULT WINAPI topology_node_SetOutputPrefType(IMFTopologyNode *iface, DW ...@@ -1524,13 +1538,7 @@ static HRESULT WINAPI topology_node_SetOutputPrefType(IMFTopologyNode *iface, DW
if (node->node_type != MF_TOPOLOGY_OUTPUT_NODE) if (node->node_type != MF_TOPOLOGY_OUTPUT_NODE)
{ {
if (SUCCEEDED(hr = topology_node_reserve_streams(&node->outputs, index))) if (SUCCEEDED(hr = topology_node_reserve_streams(&node->outputs, index)))
{ topology_node_set_stream_type(&node->outputs.streams[index], mediatype);
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 else
hr = E_NOTIMPL; hr = E_NOTIMPL;
...@@ -1540,6 +1548,18 @@ static HRESULT WINAPI topology_node_SetOutputPrefType(IMFTopologyNode *iface, DW ...@@ -1540,6 +1548,18 @@ static HRESULT WINAPI topology_node_SetOutputPrefType(IMFTopologyNode *iface, DW
return hr; 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) static HRESULT WINAPI topology_node_GetOutputPrefType(IMFTopologyNode *iface, DWORD index, IMFMediaType **mediatype)
{ {
struct topology_node *node = impl_from_IMFTopologyNode(iface); struct topology_node *node = impl_from_IMFTopologyNode(iface);
...@@ -1550,13 +1570,7 @@ static HRESULT WINAPI topology_node_GetOutputPrefType(IMFTopologyNode *iface, DW ...@@ -1550,13 +1570,7 @@ static HRESULT WINAPI topology_node_GetOutputPrefType(IMFTopologyNode *iface, DW
EnterCriticalSection(&node->cs); EnterCriticalSection(&node->cs);
if (index < node->outputs.count) if (index < node->outputs.count)
{ hr = topology_node_get_pref_type(&node->outputs, index, mediatype);
*mediatype = node->outputs.streams[index].preferred_type;
if (*mediatype)
IMFMediaType_AddRef(*mediatype);
else
hr = E_FAIL;
}
else else
hr = E_INVALIDARG; hr = E_INVALIDARG;
...@@ -1574,25 +1588,40 @@ static HRESULT WINAPI topology_node_SetInputPrefType(IMFTopologyNode *iface, DWO ...@@ -1574,25 +1588,40 @@ static HRESULT WINAPI topology_node_SetInputPrefType(IMFTopologyNode *iface, DWO
EnterCriticalSection(&node->cs); 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))) case MF_TOPOLOGY_TEE_NODE:
{ if (index)
if (index >= node->inputs.count)
{ {
memset(&node->inputs.streams[node->inputs.count], 0, hr = MF_E_INVALIDTYPE;
(index - node->inputs.count + 1) * sizeof(*node->inputs.streams)); break;
node->inputs.count = index + 1; }
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); LeaveCriticalSection(&node->cs);
...@@ -1610,11 +1639,12 @@ static HRESULT WINAPI topology_node_GetInputPrefType(IMFTopologyNode *iface, DWO ...@@ -1610,11 +1639,12 @@ static HRESULT WINAPI topology_node_GetInputPrefType(IMFTopologyNode *iface, DWO
if (index < node->inputs.count) if (index < node->inputs.count)
{ {
*mediatype = node->inputs.streams[index].preferred_type; hr = topology_node_get_pref_type(&node->inputs, index, mediatype);
if (*mediatype) }
IMFMediaType_AddRef(*mediatype); else if (node->node_type == MF_TOPOLOGY_TEE_NODE && node->input_type)
else {
hr = E_FAIL; *mediatype = node->input_type;
IMFMediaType_AddRef(*mediatype);
} }
else else
hr = E_INVALIDARG; hr = E_INVALIDARG;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment