2 * Copyright 2017 Nikolay Sivov
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
33 #include "wine/debug.h"
35 #include "mf_private.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(mfplat
);
39 static LONG next_node_id
;
40 static TOPOID next_topology_id
;
44 IMFMediaType
*preferred_type
;
45 struct topology_node
*connection
;
46 DWORD connection_stream
;
51 struct node_stream
*streams
;
58 IMFTopologyNode IMFTopologyNode_iface
;
60 IMFAttributes
*attributes
;
61 MF_TOPOLOGY_TYPE node_type
;
64 IMFMediaType
*input_type
; /* Only for tee nodes. */
65 struct node_streams inputs
;
66 struct node_streams outputs
;
72 IMFTopology IMFTopology_iface
;
74 IMFAttributes
*attributes
;
77 struct topology_node
**nodes
;
84 struct topology_loader
86 IMFTopoLoader IMFTopoLoader_iface
;
92 IMFSequencerSource IMFSequencerSource_iface
;
93 IMFMediaSourceTopologyProvider IMFMediaSourceTopologyProvider_iface
;
97 static inline struct topology
*impl_from_IMFTopology(IMFTopology
*iface
)
99 return CONTAINING_RECORD(iface
, struct topology
, IMFTopology_iface
);
102 static struct topology_node
*impl_from_IMFTopologyNode(IMFTopologyNode
*iface
)
104 return CONTAINING_RECORD(iface
, struct topology_node
, IMFTopologyNode_iface
);
107 static const IMFTopologyNodeVtbl topologynodevtbl
;
109 static struct topology_node
*unsafe_impl_from_IMFTopologyNode(IMFTopologyNode
*iface
)
111 if (!iface
|| iface
->lpVtbl
!= &topologynodevtbl
)
113 return impl_from_IMFTopologyNode(iface
);
116 static HRESULT
create_topology_node(MF_TOPOLOGY_TYPE node_type
, struct topology_node
**node
);
117 static HRESULT
topology_node_connect_output(struct topology_node
*node
, DWORD output_index
,
118 struct topology_node
*connection
, DWORD input_index
);
120 static struct topology
*unsafe_impl_from_IMFTopology(IMFTopology
*iface
);
122 static struct topology_loader
*impl_from_IMFTopoLoader(IMFTopoLoader
*iface
)
124 return CONTAINING_RECORD(iface
, struct topology_loader
, IMFTopoLoader_iface
);
127 static struct seq_source
*impl_from_IMFSequencerSource(IMFSequencerSource
*iface
)
129 return CONTAINING_RECORD(iface
, struct seq_source
, IMFSequencerSource_iface
);
132 static struct seq_source
*impl_from_IMFMediaSourceTopologyProvider(IMFMediaSourceTopologyProvider
*iface
)
134 return CONTAINING_RECORD(iface
, struct seq_source
, IMFMediaSourceTopologyProvider_iface
);
137 static HRESULT
topology_node_reserve_streams(struct node_streams
*streams
, DWORD index
)
139 if (!mf_array_reserve((void **)&streams
->streams
, &streams
->size
, index
+ 1, sizeof(*streams
->streams
)))
140 return E_OUTOFMEMORY
;
142 if (index
>= streams
->count
)
144 memset(&streams
->streams
[streams
->count
], 0, (index
- streams
->count
+ 1) * sizeof(*streams
->streams
));
145 streams
->count
= index
+ 1;
151 static HRESULT WINAPI
topology_QueryInterface(IMFTopology
*iface
, REFIID riid
, void **out
)
153 struct topology
*topology
= impl_from_IMFTopology(iface
);
155 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), out
);
157 if (IsEqualIID(riid
, &IID_IMFTopology
) ||
158 IsEqualIID(riid
, &IID_IMFAttributes
) ||
159 IsEqualIID(riid
, &IID_IUnknown
))
161 *out
= &topology
->IMFTopology_iface
;
165 FIXME("(%s, %p)\n", debugstr_guid(riid
), out
);
167 return E_NOINTERFACE
;
170 IUnknown_AddRef((IUnknown
*)*out
);
174 static ULONG WINAPI
topology_AddRef(IMFTopology
*iface
)
176 struct topology
*topology
= impl_from_IMFTopology(iface
);
177 ULONG refcount
= InterlockedIncrement(&topology
->refcount
);
179 TRACE("%p, refcount %u.\n", iface
, refcount
);
184 static HRESULT
topology_node_disconnect_output(struct topology_node
*node
, DWORD output_index
)
186 struct topology_node
*connection
= NULL
;
187 struct node_stream
*stream
;
188 DWORD connection_stream
;
191 EnterCriticalSection(&node
->cs
);
193 if (output_index
< node
->outputs
.count
)
195 stream
= &node
->outputs
.streams
[output_index
];
197 if (stream
->connection
)
199 connection
= stream
->connection
;
200 connection_stream
= stream
->connection_stream
;
201 stream
->connection
= NULL
;
202 stream
->connection_stream
= 0;
210 LeaveCriticalSection(&node
->cs
);
214 EnterCriticalSection(&connection
->cs
);
216 if (connection_stream
< connection
->inputs
.count
)
218 stream
= &connection
->inputs
.streams
[connection_stream
];
220 if (stream
->connection
)
222 stream
->connection
= NULL
;
223 stream
->connection_stream
= 0;
227 LeaveCriticalSection(&connection
->cs
);
229 IMFTopologyNode_Release(&connection
->IMFTopologyNode_iface
);
230 IMFTopologyNode_Release(&node
->IMFTopologyNode_iface
);
236 static void topology_node_disconnect(struct topology_node
*node
)
238 struct node_stream
*stream
;
241 for (i
= 0; i
< node
->outputs
.count
; ++i
)
242 topology_node_disconnect_output(node
, i
);
244 for (i
= 0; i
< node
->inputs
.count
; ++i
)
246 stream
= &node
->inputs
.streams
[i
];
247 if (stream
->connection
)
248 topology_node_disconnect_output(stream
->connection
, stream
->connection_stream
);
252 static void topology_clear(struct topology
*topology
)
256 for (i
= 0; i
< topology
->nodes
.count
; ++i
)
258 topology_node_disconnect(topology
->nodes
.nodes
[i
]);
259 IMFTopologyNode_Release(&topology
->nodes
.nodes
[i
]->IMFTopologyNode_iface
);
261 heap_free(topology
->nodes
.nodes
);
262 topology
->nodes
.nodes
= NULL
;
263 topology
->nodes
.count
= 0;
264 topology
->nodes
.size
= 0;
267 static ULONG WINAPI
topology_Release(IMFTopology
*iface
)
269 struct topology
*topology
= impl_from_IMFTopology(iface
);
270 ULONG refcount
= InterlockedDecrement(&topology
->refcount
);
272 TRACE("%p, refcount %u.\n", iface
, refcount
);
276 if (topology
->attributes
)
277 IMFAttributes_Release(topology
->attributes
);
278 topology_clear(topology
);
285 static HRESULT WINAPI
topology_GetItem(IMFTopology
*iface
, REFGUID key
, PROPVARIANT
*value
)
287 struct topology
*topology
= impl_from_IMFTopology(iface
);
289 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), value
);
291 return IMFAttributes_GetItem(topology
->attributes
, key
, value
);
294 static HRESULT WINAPI
topology_GetItemType(IMFTopology
*iface
, REFGUID key
, MF_ATTRIBUTE_TYPE
*type
)
296 struct topology
*topology
= impl_from_IMFTopology(iface
);
298 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), type
);
300 return IMFAttributes_GetItemType(topology
->attributes
, key
, type
);
303 static HRESULT WINAPI
topology_CompareItem(IMFTopology
*iface
, REFGUID key
, REFPROPVARIANT value
, BOOL
*result
)
305 struct topology
*topology
= impl_from_IMFTopology(iface
);
307 TRACE("%p, %s, %p, %p.\n", iface
, debugstr_guid(key
), value
, result
);
309 return IMFAttributes_CompareItem(topology
->attributes
, key
, value
, result
);
312 static HRESULT WINAPI
topology_Compare(IMFTopology
*iface
, IMFAttributes
*theirs
, MF_ATTRIBUTES_MATCH_TYPE type
,
315 struct topology
*topology
= impl_from_IMFTopology(iface
);
317 TRACE("%p, %p, %d, %p.\n", iface
, theirs
, type
, result
);
319 return IMFAttributes_Compare(topology
->attributes
, theirs
, type
, result
);
322 static HRESULT WINAPI
topology_GetUINT32(IMFTopology
*iface
, REFGUID key
, UINT32
*value
)
324 struct topology
*topology
= impl_from_IMFTopology(iface
);
326 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), value
);
328 return IMFAttributes_GetUINT32(topology
->attributes
, key
, value
);
331 static HRESULT WINAPI
topology_GetUINT64(IMFTopology
*iface
, REFGUID key
, UINT64
*value
)
333 struct topology
*topology
= impl_from_IMFTopology(iface
);
335 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), value
);
337 return IMFAttributes_GetUINT64(topology
->attributes
, key
, value
);
340 static HRESULT WINAPI
topology_GetDouble(IMFTopology
*iface
, REFGUID key
, double *value
)
342 struct topology
*topology
= impl_from_IMFTopology(iface
);
344 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), value
);
346 return IMFAttributes_GetDouble(topology
->attributes
, key
, value
);
349 static HRESULT WINAPI
topology_GetGUID(IMFTopology
*iface
, REFGUID key
, GUID
*value
)
351 struct topology
*topology
= impl_from_IMFTopology(iface
);
353 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), value
);
355 return IMFAttributes_GetGUID(topology
->attributes
, key
, value
);
358 static HRESULT WINAPI
topology_GetStringLength(IMFTopology
*iface
, REFGUID key
, UINT32
*length
)
360 struct topology
*topology
= impl_from_IMFTopology(iface
);
362 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), length
);
364 return IMFAttributes_GetStringLength(topology
->attributes
, key
, length
);
367 static HRESULT WINAPI
topology_GetString(IMFTopology
*iface
, REFGUID key
, WCHAR
*value
,
368 UINT32 size
, UINT32
*length
)
370 struct topology
*topology
= impl_from_IMFTopology(iface
);
372 TRACE("%p, %s, %p, %d, %p.\n", iface
, debugstr_guid(key
), value
, size
, length
);
374 return IMFAttributes_GetString(topology
->attributes
, key
, value
, size
, length
);
377 static HRESULT WINAPI
topology_GetAllocatedString(IMFTopology
*iface
, REFGUID key
,
378 WCHAR
**value
, UINT32
*length
)
380 struct topology
*topology
= impl_from_IMFTopology(iface
);
382 TRACE("%p, %s, %p, %p.\n", iface
, debugstr_guid(key
), value
, length
);
384 return IMFAttributes_GetAllocatedString(topology
->attributes
, key
, value
, length
);
387 static HRESULT WINAPI
topology_GetBlobSize(IMFTopology
*iface
, REFGUID key
, UINT32
*size
)
389 struct topology
*topology
= impl_from_IMFTopology(iface
);
391 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), size
);
393 return IMFAttributes_GetBlobSize(topology
->attributes
, key
, size
);
396 static HRESULT WINAPI
topology_GetBlob(IMFTopology
*iface
, REFGUID key
, UINT8
*buf
,
397 UINT32 bufsize
, UINT32
*blobsize
)
399 struct topology
*topology
= impl_from_IMFTopology(iface
);
401 TRACE("%p, %s, %p, %d, %p.\n", iface
, debugstr_guid(key
), buf
, bufsize
, blobsize
);
403 return IMFAttributes_GetBlob(topology
->attributes
, key
, buf
, bufsize
, blobsize
);
406 static HRESULT WINAPI
topology_GetAllocatedBlob(IMFTopology
*iface
, REFGUID key
, UINT8
**buf
, UINT32
*size
)
408 struct topology
*topology
= impl_from_IMFTopology(iface
);
410 TRACE("%p, %s, %p, %p.\n", iface
, debugstr_guid(key
), buf
, size
);
412 return IMFAttributes_GetAllocatedBlob(topology
->attributes
, key
, buf
, size
);
415 static HRESULT WINAPI
topology_GetUnknown(IMFTopology
*iface
, REFGUID key
, REFIID riid
, void **ppv
)
417 struct topology
*topology
= impl_from_IMFTopology(iface
);
419 TRACE("%p, %s, %s, %p.\n", iface
, debugstr_guid(key
), debugstr_guid(riid
), ppv
);
421 return IMFAttributes_GetUnknown(topology
->attributes
, key
, riid
, ppv
);
424 static HRESULT WINAPI
topology_SetItem(IMFTopology
*iface
, REFGUID key
, REFPROPVARIANT value
)
426 struct topology
*topology
= impl_from_IMFTopology(iface
);
428 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), value
);
430 return IMFAttributes_SetItem(topology
->attributes
, key
, value
);
433 static HRESULT WINAPI
topology_DeleteItem(IMFTopology
*iface
, REFGUID key
)
435 struct topology
*topology
= impl_from_IMFTopology(iface
);
437 TRACE("%p, %s.\n", topology
, debugstr_guid(key
));
439 return IMFAttributes_DeleteItem(topology
->attributes
, key
);
442 static HRESULT WINAPI
topology_DeleteAllItems(IMFTopology
*iface
)
444 struct topology
*topology
= impl_from_IMFTopology(iface
);
446 TRACE("%p.\n", iface
);
448 return IMFAttributes_DeleteAllItems(topology
->attributes
);
451 static HRESULT WINAPI
topology_SetUINT32(IMFTopology
*iface
, REFGUID key
, UINT32 value
)
453 struct topology
*topology
= impl_from_IMFTopology(iface
);
455 TRACE("%p, %s, %d.\n", iface
, debugstr_guid(key
), value
);
457 return IMFAttributes_SetUINT32(topology
->attributes
, key
, value
);
460 static HRESULT WINAPI
topology_SetUINT64(IMFTopology
*iface
, REFGUID key
, UINT64 value
)
462 struct topology
*topology
= impl_from_IMFTopology(iface
);
464 TRACE("%p, %s, %s.\n", iface
, debugstr_guid(key
), wine_dbgstr_longlong(value
));
466 return IMFAttributes_SetUINT64(topology
->attributes
, key
, value
);
469 static HRESULT WINAPI
topology_SetDouble(IMFTopology
*iface
, REFGUID key
, double value
)
471 struct topology
*topology
= impl_from_IMFTopology(iface
);
473 TRACE("%p, %s, %f.\n", iface
, debugstr_guid(key
), value
);
475 return IMFAttributes_SetDouble(topology
->attributes
, key
, value
);
478 static HRESULT WINAPI
topology_SetGUID(IMFTopology
*iface
, REFGUID key
, REFGUID value
)
480 struct topology
*topology
= impl_from_IMFTopology(iface
);
482 TRACE("%p, %s, %s.\n", iface
, debugstr_guid(key
), debugstr_guid(value
));
484 return IMFAttributes_SetGUID(topology
->attributes
, key
, value
);
487 static HRESULT WINAPI
topology_SetString(IMFTopology
*iface
, REFGUID key
, const WCHAR
*value
)
489 struct topology
*topology
= impl_from_IMFTopology(iface
);
491 TRACE("%p, %s, %s.\n", iface
, debugstr_guid(key
), debugstr_w(value
));
493 return IMFAttributes_SetString(topology
->attributes
, key
, value
);
496 static HRESULT WINAPI
topology_SetBlob(IMFTopology
*iface
, REFGUID key
, const UINT8
*buf
, UINT32 size
)
498 struct topology
*topology
= impl_from_IMFTopology(iface
);
500 TRACE("%p, %s, %p, %d.\n", iface
, debugstr_guid(key
), buf
, size
);
502 return IMFAttributes_SetBlob(topology
->attributes
, key
, buf
, size
);
505 static HRESULT WINAPI
topology_SetUnknown(IMFTopology
*iface
, REFGUID key
, IUnknown
*unknown
)
507 struct topology
*topology
= impl_from_IMFTopology(iface
);
509 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), unknown
);
511 return IMFAttributes_SetUnknown(topology
->attributes
, key
, unknown
);
514 static HRESULT WINAPI
topology_LockStore(IMFTopology
*iface
)
516 struct topology
*topology
= impl_from_IMFTopology(iface
);
518 TRACE("%p.\n", iface
);
520 return IMFAttributes_LockStore(topology
->attributes
);
523 static HRESULT WINAPI
topology_UnlockStore(IMFTopology
*iface
)
525 struct topology
*topology
= impl_from_IMFTopology(iface
);
527 TRACE("%p.\n", iface
);
529 return IMFAttributes_UnlockStore(topology
->attributes
);
532 static HRESULT WINAPI
topology_GetCount(IMFTopology
*iface
, UINT32
*count
)
534 struct topology
*topology
= impl_from_IMFTopology(iface
);
536 TRACE("%p, %p.\n", iface
, count
);
538 return IMFAttributes_GetCount(topology
->attributes
, count
);
541 static HRESULT WINAPI
topology_GetItemByIndex(IMFTopology
*iface
, UINT32 index
, GUID
*key
, PROPVARIANT
*value
)
543 struct topology
*topology
= impl_from_IMFTopology(iface
);
545 TRACE("%p, %u, %p, %p.\n", iface
, index
, key
, value
);
547 return IMFAttributes_GetItemByIndex(topology
->attributes
, index
, key
, value
);
550 static HRESULT WINAPI
topology_CopyAllItems(IMFTopology
*iface
, IMFAttributes
*dest
)
552 struct topology
*topology
= impl_from_IMFTopology(iface
);
554 TRACE("%p, %p.\n", iface
, dest
);
556 return IMFAttributes_CopyAllItems(topology
->attributes
, dest
);
559 static HRESULT WINAPI
topology_GetTopologyID(IMFTopology
*iface
, TOPOID
*id
)
561 struct topology
*topology
= impl_from_IMFTopology(iface
);
563 TRACE("%p, %p.\n", iface
, id
);
573 static HRESULT
topology_get_node_by_id(const struct topology
*topology
, TOPOID id
, struct topology_node
**node
)
577 for (i
= 0; i
< topology
->nodes
.count
; ++i
)
579 if (topology
->nodes
.nodes
[i
]->id
== id
)
581 *node
= topology
->nodes
.nodes
[i
];
586 return MF_E_NOT_FOUND
;
589 static HRESULT
topology_add_node(struct topology
*topology
, struct topology_node
*node
)
591 struct topology_node
*match
;
596 if (SUCCEEDED(topology_get_node_by_id(topology
, node
->id
, &match
)))
599 if (!mf_array_reserve((void **)&topology
->nodes
.nodes
, &topology
->nodes
.size
, topology
->nodes
.count
+ 1,
600 sizeof(*topology
->nodes
.nodes
)))
602 return E_OUTOFMEMORY
;
605 topology
->nodes
.nodes
[topology
->nodes
.count
++] = node
;
606 IMFTopologyNode_AddRef(&node
->IMFTopologyNode_iface
);
611 static HRESULT WINAPI
topology_AddNode(IMFTopology
*iface
, IMFTopologyNode
*node_iface
)
613 struct topology
*topology
= impl_from_IMFTopology(iface
);
614 struct topology_node
*node
= unsafe_impl_from_IMFTopologyNode(node_iface
);
616 TRACE("%p, %p.\n", iface
, node_iface
);
618 return topology_add_node(topology
, node
);
621 static HRESULT WINAPI
topology_RemoveNode(IMFTopology
*iface
, IMFTopologyNode
*node
)
623 struct topology
*topology
= impl_from_IMFTopology(iface
);
626 TRACE("%p, %p.\n", iface
, node
);
628 for (i
= 0; i
< topology
->nodes
.count
; ++i
)
630 if (&topology
->nodes
.nodes
[i
]->IMFTopologyNode_iface
== node
)
632 topology_node_disconnect(topology
->nodes
.nodes
[i
]);
633 IMFTopologyNode_Release(&topology
->nodes
.nodes
[i
]->IMFTopologyNode_iface
);
634 count
= topology
->nodes
.count
- i
- 1;
637 memmove(&topology
->nodes
.nodes
[i
], &topology
->nodes
.nodes
[i
+ 1],
638 count
* sizeof(*topology
->nodes
.nodes
));
640 topology
->nodes
.count
--;
648 static HRESULT WINAPI
topology_GetNodeCount(IMFTopology
*iface
, WORD
*count
)
650 struct topology
*topology
= impl_from_IMFTopology(iface
);
652 TRACE("%p, %p.\n", iface
, count
);
657 *count
= topology
->nodes
.count
;
662 static HRESULT WINAPI
topology_GetNode(IMFTopology
*iface
, WORD index
, IMFTopologyNode
**node
)
664 struct topology
*topology
= impl_from_IMFTopology(iface
);
666 TRACE("%p, %u, %p.\n", iface
, index
, node
);
671 if (index
>= topology
->nodes
.count
)
672 return MF_E_INVALIDINDEX
;
674 *node
= &topology
->nodes
.nodes
[index
]->IMFTopologyNode_iface
;
675 IMFTopologyNode_AddRef(*node
);
680 static HRESULT WINAPI
topology_Clear(IMFTopology
*iface
)
682 struct topology
*topology
= impl_from_IMFTopology(iface
);
684 TRACE("%p.\n", iface
);
686 topology_clear(topology
);
690 static HRESULT WINAPI
topology_CloneFrom(IMFTopology
*iface
, IMFTopology
*src
)
692 struct topology
*topology
= impl_from_IMFTopology(iface
);
693 struct topology
*src_topology
= unsafe_impl_from_IMFTopology(src
);
694 struct topology_node
*node
;
698 TRACE("%p, %p.\n", iface
, src
);
700 topology_clear(topology
);
703 for (i
= 0; i
< src_topology
->nodes
.count
; ++i
)
705 if (FAILED(hr
= create_topology_node(src_topology
->nodes
.nodes
[i
]->node_type
, &node
)))
707 WARN("Failed to create a node, hr %#x.\n", hr
);
711 if (SUCCEEDED(hr
= IMFTopologyNode_CloneFrom(&node
->IMFTopologyNode_iface
,
712 &src_topology
->nodes
.nodes
[i
]->IMFTopologyNode_iface
)))
714 topology_add_node(topology
, node
);
717 IMFTopologyNode_Release(&node
->IMFTopologyNode_iface
);
720 /* Clone connections. */
721 for (i
= 0; i
< src_topology
->nodes
.count
; ++i
)
723 const struct node_streams
*outputs
= &src_topology
->nodes
.nodes
[i
]->outputs
;
725 for (j
= 0; j
< outputs
->count
; ++j
)
727 DWORD input_index
= outputs
->streams
[j
].connection_stream
;
728 TOPOID id
= outputs
->streams
[j
].connection
->id
;
730 /* Skip node lookup in destination topology, assuming same node order. */
731 if (SUCCEEDED(hr
= topology_get_node_by_id(topology
, id
, &node
)))
732 topology_node_connect_output(topology
->nodes
.nodes
[i
], j
, node
, input_index
);
736 /* Copy attributes and id. */
737 hr
= IMFTopology_CopyAllItems(src
, (IMFAttributes
*)&topology
->IMFTopology_iface
);
739 topology
->id
= src_topology
->id
;
744 static HRESULT WINAPI
topology_GetNodeByID(IMFTopology
*iface
, TOPOID id
, IMFTopologyNode
**ret
)
746 struct topology
*topology
= impl_from_IMFTopology(iface
);
747 struct topology_node
*node
;
750 TRACE("%p, %p.\n", iface
, ret
);
752 if (SUCCEEDED(hr
= topology_get_node_by_id(topology
, id
, &node
)))
754 *ret
= &node
->IMFTopologyNode_iface
;
755 IMFTopologyNode_AddRef(*ret
);
763 static HRESULT
topology_get_node_collection(const struct topology
*topology
, MF_TOPOLOGY_TYPE node_type
,
764 IMFCollection
**collection
)
772 if (FAILED(hr
= MFCreateCollection(collection
)))
775 for (i
= 0; i
< topology
->nodes
.count
; ++i
)
777 if (topology
->nodes
.nodes
[i
]->node_type
== node_type
)
779 if (FAILED(hr
= IMFCollection_AddElement(*collection
,
780 (IUnknown
*)&topology
->nodes
.nodes
[i
]->IMFTopologyNode_iface
)))
782 IMFCollection_Release(*collection
);
792 static HRESULT WINAPI
topology_GetSourceNodeCollection(IMFTopology
*iface
, IMFCollection
**collection
)
794 struct topology
*topology
= impl_from_IMFTopology(iface
);
796 TRACE("%p, %p.\n", iface
, collection
);
798 return topology_get_node_collection(topology
, MF_TOPOLOGY_SOURCESTREAM_NODE
, collection
);
801 static HRESULT WINAPI
topology_GetOutputNodeCollection(IMFTopology
*iface
, IMFCollection
**collection
)
803 struct topology
*topology
= impl_from_IMFTopology(iface
);
805 TRACE("%p, %p.\n", iface
, collection
);
807 return topology_get_node_collection(topology
, MF_TOPOLOGY_OUTPUT_NODE
, collection
);
810 static const IMFTopologyVtbl topologyvtbl
=
812 topology_QueryInterface
,
816 topology_GetItemType
,
817 topology_CompareItem
,
823 topology_GetStringLength
,
825 topology_GetAllocatedString
,
826 topology_GetBlobSize
,
828 topology_GetAllocatedBlob
,
832 topology_DeleteAllItems
,
841 topology_UnlockStore
,
843 topology_GetItemByIndex
,
844 topology_CopyAllItems
,
845 topology_GetTopologyID
,
848 topology_GetNodeCount
,
852 topology_GetNodeByID
,
853 topology_GetSourceNodeCollection
,
854 topology_GetOutputNodeCollection
,
857 static struct topology
*unsafe_impl_from_IMFTopology(IMFTopology
*iface
)
859 if (!iface
|| iface
->lpVtbl
!= &topologyvtbl
)
861 return impl_from_IMFTopology(iface
);
864 static TOPOID
topology_generate_id(void)
870 old
= next_topology_id
;
872 while (InterlockedCompareExchange64((LONG64
*)&next_topology_id
, old
+ 1, old
) != old
);
874 return next_topology_id
;
877 /***********************************************************************
878 * MFCreateTopology (mf.@)
880 HRESULT WINAPI
MFCreateTopology(IMFTopology
**topology
)
882 struct topology
*object
;
885 TRACE("%p.\n", topology
);
890 object
= heap_alloc_zero(sizeof(*object
));
892 return E_OUTOFMEMORY
;
894 object
->IMFTopology_iface
.lpVtbl
= &topologyvtbl
;
895 object
->refcount
= 1;
897 hr
= MFCreateAttributes(&object
->attributes
, 0);
900 IMFTopology_Release(&object
->IMFTopology_iface
);
904 object
->id
= topology_generate_id();
906 *topology
= &object
->IMFTopology_iface
;
911 static HRESULT WINAPI
topology_node_QueryInterface(IMFTopologyNode
*iface
, REFIID riid
, void **out
)
913 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
915 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), out
);
917 if (IsEqualIID(riid
, &IID_IMFTopologyNode
) ||
918 IsEqualIID(riid
, &IID_IMFAttributes
) ||
919 IsEqualIID(riid
, &IID_IUnknown
))
921 *out
= &node
->IMFTopologyNode_iface
;
922 IMFTopologyNode_AddRef(iface
);
926 WARN("Unsupported interface %s.\n", debugstr_guid(riid
));
929 return E_NOINTERFACE
;
932 static ULONG WINAPI
topology_node_AddRef(IMFTopologyNode
*iface
)
934 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
935 ULONG refcount
= InterlockedIncrement(&node
->refcount
);
937 TRACE("%p, refcount %u.\n", iface
, refcount
);
942 static ULONG WINAPI
topology_node_Release(IMFTopologyNode
*iface
)
944 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
945 ULONG refcount
= InterlockedDecrement(&node
->refcount
);
948 TRACE("%p, refcount %u.\n", iface
, refcount
);
953 IUnknown_Release(node
->object
);
954 if (node
->input_type
)
955 IMFMediaType_Release(node
->input_type
);
956 for (i
= 0; i
< node
->inputs
.count
; ++i
)
958 if (node
->inputs
.streams
[i
].preferred_type
)
959 IMFMediaType_Release(node
->inputs
.streams
[i
].preferred_type
);
961 for (i
= 0; i
< node
->outputs
.count
; ++i
)
963 if (node
->outputs
.streams
[i
].preferred_type
)
964 IMFMediaType_Release(node
->outputs
.streams
[i
].preferred_type
);
966 heap_free(node
->inputs
.streams
);
967 heap_free(node
->outputs
.streams
);
968 IMFAttributes_Release(node
->attributes
);
969 DeleteCriticalSection(&node
->cs
);
976 static HRESULT WINAPI
topology_node_GetItem(IMFTopologyNode
*iface
, REFGUID key
, PROPVARIANT
*value
)
978 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
980 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), value
);
982 return IMFAttributes_GetItem(node
->attributes
, key
, value
);
985 static HRESULT WINAPI
topology_node_GetItemType(IMFTopologyNode
*iface
, REFGUID key
, MF_ATTRIBUTE_TYPE
*type
)
987 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
989 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), type
);
991 return IMFAttributes_GetItemType(node
->attributes
, key
, type
);
994 static HRESULT WINAPI
topology_node_CompareItem(IMFTopologyNode
*iface
, REFGUID key
, REFPROPVARIANT value
, BOOL
*result
)
996 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
998 TRACE("%p, %s, %p, %p.\n", iface
, debugstr_guid(key
), value
, result
);
1000 return IMFAttributes_CompareItem(node
->attributes
, key
, value
, result
);
1003 static HRESULT WINAPI
topology_node_Compare(IMFTopologyNode
*iface
, IMFAttributes
*theirs
,
1004 MF_ATTRIBUTES_MATCH_TYPE type
, BOOL
*result
)
1006 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
1008 TRACE("%p, %p, %d, %p.\n", iface
, theirs
, type
, result
);
1010 return IMFAttributes_Compare(node
->attributes
, theirs
, type
, result
);
1013 static HRESULT WINAPI
topology_node_GetUINT32(IMFTopologyNode
*iface
, REFGUID key
, UINT32
*value
)
1015 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
1017 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), value
);
1019 return IMFAttributes_GetUINT32(node
->attributes
, key
, value
);
1022 static HRESULT WINAPI
topology_node_GetUINT64(IMFTopologyNode
*iface
, REFGUID key
, UINT64
*value
)
1024 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
1026 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), value
);
1028 return IMFAttributes_GetUINT64(node
->attributes
, key
, value
);
1031 static HRESULT WINAPI
topology_node_GetDouble(IMFTopologyNode
*iface
, REFGUID key
, double *value
)
1033 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
1035 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), value
);
1037 return IMFAttributes_GetDouble(node
->attributes
, key
, value
);
1040 static HRESULT WINAPI
topology_node_GetGUID(IMFTopologyNode
*iface
, REFGUID key
, GUID
*value
)
1042 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
1044 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), value
);
1046 return IMFAttributes_GetGUID(node
->attributes
, key
, value
);
1049 static HRESULT WINAPI
topology_node_GetStringLength(IMFTopologyNode
*iface
, REFGUID key
, UINT32
*length
)
1051 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
1053 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), length
);
1055 return IMFAttributes_GetStringLength(node
->attributes
, key
, length
);
1058 static HRESULT WINAPI
topology_node_GetString(IMFTopologyNode
*iface
, REFGUID key
, WCHAR
*value
,
1059 UINT32 size
, UINT32
*length
)
1061 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
1063 TRACE("%p, %s, %p, %d, %p.\n", iface
, debugstr_guid(key
), value
, size
, length
);
1065 return IMFAttributes_GetString(node
->attributes
, key
, value
, size
, length
);
1068 static HRESULT WINAPI
topology_node_GetAllocatedString(IMFTopologyNode
*iface
, REFGUID key
,
1069 WCHAR
**value
, UINT32
*length
)
1071 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
1073 TRACE("%p, %s, %p, %p.\n", iface
, debugstr_guid(key
), value
, length
);
1075 return IMFAttributes_GetAllocatedString(node
->attributes
, key
, value
, length
);
1078 static HRESULT WINAPI
topology_node_GetBlobSize(IMFTopologyNode
*iface
, REFGUID key
, UINT32
*size
)
1080 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
1082 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), size
);
1084 return IMFAttributes_GetBlobSize(node
->attributes
, key
, size
);
1087 static HRESULT WINAPI
topology_node_GetBlob(IMFTopologyNode
*iface
, REFGUID key
, UINT8
*buf
,
1088 UINT32 bufsize
, UINT32
*blobsize
)
1090 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
1092 TRACE("%p, %s, %p, %d, %p.\n", iface
, debugstr_guid(key
), buf
, bufsize
, blobsize
);
1094 return IMFAttributes_GetBlob(node
->attributes
, key
, buf
, bufsize
, blobsize
);
1097 static HRESULT WINAPI
topology_node_GetAllocatedBlob(IMFTopologyNode
*iface
, REFGUID key
, UINT8
**buf
, UINT32
*size
)
1099 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
1101 TRACE("%p, %s, %p, %p.\n", iface
, debugstr_guid(key
), buf
, size
);
1103 return IMFAttributes_GetAllocatedBlob(node
->attributes
, key
, buf
, size
);
1106 static HRESULT WINAPI
topology_node_GetUnknown(IMFTopologyNode
*iface
, REFGUID key
, REFIID riid
, void **ppv
)
1108 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
1110 TRACE("%p, %s, %s, %p.\n", iface
, debugstr_guid(key
), debugstr_guid(riid
), ppv
);
1112 return IMFAttributes_GetUnknown(node
->attributes
, key
, riid
, ppv
);
1115 static HRESULT WINAPI
topology_node_SetItem(IMFTopologyNode
*iface
, REFGUID key
, REFPROPVARIANT value
)
1117 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
1119 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), value
);
1121 return IMFAttributes_SetItem(node
->attributes
, key
, value
);
1124 static HRESULT WINAPI
topology_node_DeleteItem(IMFTopologyNode
*iface
, REFGUID key
)
1126 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
1128 TRACE("%p, %s.\n", iface
, debugstr_guid(key
));
1130 return IMFAttributes_DeleteItem(node
->attributes
, key
);
1133 static HRESULT WINAPI
topology_node_DeleteAllItems(IMFTopologyNode
*iface
)
1135 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
1137 TRACE("%p.\n", iface
);
1139 return IMFAttributes_DeleteAllItems(node
->attributes
);
1142 static HRESULT WINAPI
topology_node_SetUINT32(IMFTopologyNode
*iface
, REFGUID key
, UINT32 value
)
1144 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
1146 TRACE("%p, %s, %d.\n", iface
, debugstr_guid(key
), value
);
1148 return IMFAttributes_SetUINT32(node
->attributes
, key
, value
);
1151 static HRESULT WINAPI
topology_node_SetUINT64(IMFTopologyNode
*iface
, REFGUID key
, UINT64 value
)
1153 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
1155 TRACE("%p, %s, %s.\n", iface
, debugstr_guid(key
), wine_dbgstr_longlong(value
));
1157 return IMFAttributes_SetUINT64(node
->attributes
, key
, value
);
1160 static HRESULT WINAPI
topology_node_SetDouble(IMFTopologyNode
*iface
, REFGUID key
, double value
)
1162 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
1164 TRACE("%p, %s, %f.\n", iface
, debugstr_guid(key
), value
);
1166 return IMFAttributes_SetDouble(node
->attributes
, key
, value
);
1169 static HRESULT WINAPI
topology_node_SetGUID(IMFTopologyNode
*iface
, REFGUID key
, REFGUID value
)
1171 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
1173 TRACE("%p, %s, %s.\n", iface
, debugstr_guid(key
), debugstr_guid(value
));
1175 return IMFAttributes_SetGUID(node
->attributes
, key
, value
);
1178 static HRESULT WINAPI
topology_node_SetString(IMFTopologyNode
*iface
, REFGUID key
, const WCHAR
*value
)
1180 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
1182 TRACE("%p, %s, %s.\n", iface
, debugstr_guid(key
), debugstr_w(value
));
1184 return IMFAttributes_SetString(node
->attributes
, key
, value
);
1187 static HRESULT WINAPI
topology_node_SetBlob(IMFTopologyNode
*iface
, REFGUID key
, const UINT8
*buf
, UINT32 size
)
1189 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
1191 TRACE("%p, %s, %p, %d.\n", iface
, debugstr_guid(key
), buf
, size
);
1193 return IMFAttributes_SetBlob(node
->attributes
, key
, buf
, size
);
1196 static HRESULT WINAPI
topology_node_SetUnknown(IMFTopologyNode
*iface
, REFGUID key
, IUnknown
*unknown
)
1198 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
1200 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), unknown
);
1202 return IMFAttributes_SetUnknown(node
->attributes
, key
, unknown
);
1205 static HRESULT WINAPI
topology_node_LockStore(IMFTopologyNode
*iface
)
1207 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
1209 TRACE("%p.\n", iface
);
1211 return IMFAttributes_LockStore(node
->attributes
);
1214 static HRESULT WINAPI
topology_node_UnlockStore(IMFTopologyNode
*iface
)
1216 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
1218 TRACE("%p.\n", iface
);
1220 return IMFAttributes_UnlockStore(node
->attributes
);
1223 static HRESULT WINAPI
topology_node_GetCount(IMFTopologyNode
*iface
, UINT32
*count
)
1225 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
1227 TRACE("%p, %p.\n", iface
, count
);
1229 return IMFAttributes_GetCount(node
->attributes
, count
);
1232 static HRESULT WINAPI
topology_node_GetItemByIndex(IMFTopologyNode
*iface
, UINT32 index
, GUID
*key
, PROPVARIANT
*value
)
1234 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
1236 TRACE("%p, %u, %p, %p.\n", iface
, index
, key
, value
);
1238 return IMFAttributes_GetItemByIndex(node
->attributes
, index
, key
, value
);
1241 static HRESULT WINAPI
topology_node_CopyAllItems(IMFTopologyNode
*iface
, IMFAttributes
*dest
)
1243 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
1245 TRACE("%p, %p.\n", iface
, dest
);
1247 return IMFAttributes_CopyAllItems(node
->attributes
, dest
);
1250 static HRESULT
topology_node_set_object(struct topology_node
*node
, IUnknown
*object
)
1252 static const GUID
*iids
[3] = { &IID_IPersist
, &IID_IPersistStorage
, &IID_IPersistPropertyBag
};
1253 IPersist
*persist
= NULL
;
1259 has_object_id
= IMFAttributes_GetGUID(node
->attributes
, &MF_TOPONODE_TRANSFORM_OBJECTID
, &object_id
) == S_OK
;
1261 if (object
&& !has_object_id
)
1263 for (i
= 0; i
< ARRAY_SIZE(iids
); ++i
)
1266 if (SUCCEEDED(hr
= IUnknown_QueryInterface(object
, iids
[i
], (void **)&persist
)))
1272 if (FAILED(hr
= IPersist_GetClassID(persist
, &object_id
)))
1274 IPersist_Release(persist
);
1280 EnterCriticalSection(&node
->cs
);
1283 IUnknown_Release(node
->object
);
1284 node
->object
= object
;
1286 IUnknown_AddRef(node
->object
);
1289 IMFAttributes_SetGUID(node
->attributes
, &MF_TOPONODE_TRANSFORM_OBJECTID
, &object_id
);
1291 LeaveCriticalSection(&node
->cs
);
1294 IPersist_Release(persist
);
1299 static HRESULT WINAPI
topology_node_SetObject(IMFTopologyNode
*iface
, IUnknown
*object
)
1301 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
1303 TRACE("%p, %p.\n", iface
, object
);
1305 return topology_node_set_object(node
, object
);
1308 static HRESULT WINAPI
topology_node_GetObject(IMFTopologyNode
*iface
, IUnknown
**object
)
1310 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
1312 TRACE("%p, %p.\n", iface
, object
);
1317 EnterCriticalSection(&node
->cs
);
1319 *object
= node
->object
;
1321 IUnknown_AddRef(*object
);
1323 LeaveCriticalSection(&node
->cs
);
1325 return *object
? S_OK
: E_FAIL
;
1328 static HRESULT WINAPI
topology_node_GetNodeType(IMFTopologyNode
*iface
, MF_TOPOLOGY_TYPE
*node_type
)
1330 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
1332 TRACE("%p, %p.\n", iface
, node_type
);
1334 *node_type
= node
->node_type
;
1339 static HRESULT WINAPI
topology_node_GetTopoNodeID(IMFTopologyNode
*iface
, TOPOID
*id
)
1341 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
1343 TRACE("%p, %p.\n", iface
, id
);
1350 static HRESULT WINAPI
topology_node_SetTopoNodeID(IMFTopologyNode
*iface
, TOPOID id
)
1352 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
1354 TRACE("%p, %s.\n", iface
, wine_dbgstr_longlong(id
));
1361 static HRESULT WINAPI
topology_node_GetInputCount(IMFTopologyNode
*iface
, DWORD
*count
)
1363 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
1365 TRACE("%p, %p.\n", iface
, count
);
1367 *count
= node
->inputs
.count
;
1372 static HRESULT WINAPI
topology_node_GetOutputCount(IMFTopologyNode
*iface
, DWORD
*count
)
1374 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
1376 TRACE("%p, %p.\n", iface
, count
);
1378 *count
= node
->outputs
.count
;
1383 static void topology_node_set_stream_type(struct node_stream
*stream
, IMFMediaType
*mediatype
)
1385 if (stream
->preferred_type
)
1386 IMFMediaType_Release(stream
->preferred_type
);
1387 stream
->preferred_type
= mediatype
;
1388 if (stream
->preferred_type
)
1389 IMFMediaType_AddRef(stream
->preferred_type
);
1392 static HRESULT
topology_node_connect_output(struct topology_node
*node
, DWORD output_index
,
1393 struct topology_node
*connection
, DWORD input_index
)
1395 struct node_stream
*stream
;
1398 if (node
->node_type
== MF_TOPOLOGY_OUTPUT_NODE
|| connection
->node_type
== MF_TOPOLOGY_SOURCESTREAM_NODE
)
1401 EnterCriticalSection(&node
->cs
);
1402 EnterCriticalSection(&connection
->cs
);
1404 topology_node_disconnect_output(node
, output_index
);
1405 if (input_index
< connection
->inputs
.count
)
1407 stream
= &connection
->inputs
.streams
[input_index
];
1408 if (stream
->connection
)
1409 topology_node_disconnect_output(stream
->connection
, stream
->connection_stream
);
1412 hr
= topology_node_reserve_streams(&node
->outputs
, output_index
);
1415 size_t old_count
= connection
->inputs
.count
;
1416 hr
= topology_node_reserve_streams(&connection
->inputs
, input_index
);
1417 if (SUCCEEDED(hr
) && !old_count
&& connection
->input_type
)
1419 topology_node_set_stream_type(connection
->inputs
.streams
, connection
->input_type
);
1420 IMFMediaType_Release(connection
->input_type
);
1421 connection
->input_type
= NULL
;
1427 node
->outputs
.streams
[output_index
].connection
= connection
;
1428 IMFTopologyNode_AddRef(&node
->outputs
.streams
[output_index
].connection
->IMFTopologyNode_iface
);
1429 node
->outputs
.streams
[output_index
].connection_stream
= input_index
;
1430 connection
->inputs
.streams
[input_index
].connection
= node
;
1431 IMFTopologyNode_AddRef(&connection
->inputs
.streams
[input_index
].connection
->IMFTopologyNode_iface
);
1432 connection
->inputs
.streams
[input_index
].connection_stream
= output_index
;
1435 LeaveCriticalSection(&connection
->cs
);
1436 LeaveCriticalSection(&node
->cs
);
1441 static HRESULT WINAPI
topology_node_ConnectOutput(IMFTopologyNode
*iface
, DWORD output_index
,
1442 IMFTopologyNode
*peer
, DWORD input_index
)
1444 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
1445 struct topology_node
*connection
= unsafe_impl_from_IMFTopologyNode(peer
);
1447 TRACE("%p, %u, %p, %u.\n", iface
, output_index
, peer
, input_index
);
1451 WARN("External node implementations are not supported.\n");
1452 return E_UNEXPECTED
;
1455 return topology_node_connect_output(node
, output_index
, connection
, input_index
);
1458 static HRESULT WINAPI
topology_node_DisconnectOutput(IMFTopologyNode
*iface
, DWORD output_index
)
1460 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
1462 TRACE("%p, %u.\n", iface
, output_index
);
1464 return topology_node_disconnect_output(node
, output_index
);
1467 static HRESULT WINAPI
topology_node_GetInput(IMFTopologyNode
*iface
, DWORD input_index
, IMFTopologyNode
**ret
,
1468 DWORD
*output_index
)
1470 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
1473 TRACE("%p, %u, %p, %p.\n", iface
, input_index
, ret
, output_index
);
1475 EnterCriticalSection(&node
->cs
);
1477 if (input_index
< node
->inputs
.count
)
1479 const struct node_stream
*stream
= &node
->inputs
.streams
[input_index
];
1481 if (stream
->connection
)
1483 *ret
= &stream
->connection
->IMFTopologyNode_iface
;
1484 IMFTopologyNode_AddRef(*ret
);
1485 *output_index
= stream
->connection_stream
;
1488 hr
= MF_E_NOT_FOUND
;
1493 LeaveCriticalSection(&node
->cs
);
1498 static HRESULT WINAPI
topology_node_GetOutput(IMFTopologyNode
*iface
, DWORD output_index
, IMFTopologyNode
**ret
,
1501 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
1504 TRACE("%p, %u, %p, %p.\n", iface
, output_index
, ret
, input_index
);
1506 EnterCriticalSection(&node
->cs
);
1508 if (output_index
< node
->outputs
.count
)
1510 const struct node_stream
*stream
= &node
->outputs
.streams
[output_index
];
1512 if (stream
->connection
)
1514 *ret
= &stream
->connection
->IMFTopologyNode_iface
;
1515 IMFTopologyNode_AddRef(*ret
);
1516 *input_index
= stream
->connection_stream
;
1519 hr
= MF_E_NOT_FOUND
;
1524 LeaveCriticalSection(&node
->cs
);
1529 static HRESULT WINAPI
topology_node_SetOutputPrefType(IMFTopologyNode
*iface
, DWORD index
, IMFMediaType
*mediatype
)
1531 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
1534 TRACE("%p, %u, %p.\n", iface
, index
, mediatype
);
1536 EnterCriticalSection(&node
->cs
);
1538 if (node
->node_type
!= MF_TOPOLOGY_OUTPUT_NODE
)
1540 if (SUCCEEDED(hr
= topology_node_reserve_streams(&node
->outputs
, index
)))
1541 topology_node_set_stream_type(&node
->outputs
.streams
[index
], mediatype
);
1546 LeaveCriticalSection(&node
->cs
);
1551 static HRESULT
topology_node_get_pref_type(struct node_streams
*streams
, unsigned int index
, IMFMediaType
**mediatype
)
1553 *mediatype
= streams
->streams
[index
].preferred_type
;
1556 IMFMediaType_AddRef(*mediatype
);
1563 static HRESULT WINAPI
topology_node_GetOutputPrefType(IMFTopologyNode
*iface
, DWORD index
, IMFMediaType
**mediatype
)
1565 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
1568 TRACE("%p, %u, %p.\n", iface
, index
, mediatype
);
1570 EnterCriticalSection(&node
->cs
);
1572 if (index
< node
->outputs
.count
)
1573 hr
= topology_node_get_pref_type(&node
->outputs
, index
, mediatype
);
1577 LeaveCriticalSection(&node
->cs
);
1582 static HRESULT WINAPI
topology_node_SetInputPrefType(IMFTopologyNode
*iface
, DWORD index
, IMFMediaType
*mediatype
)
1584 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
1587 TRACE("%p, %u, %p.\n", iface
, index
, mediatype
);
1589 EnterCriticalSection(&node
->cs
);
1591 switch (node
->node_type
)
1593 case MF_TOPOLOGY_TEE_NODE
:
1596 hr
= MF_E_INVALIDTYPE
;
1599 if (node
->inputs
.count
)
1600 topology_node_set_stream_type(&node
->inputs
.streams
[index
], mediatype
);
1603 if (node
->input_type
)
1604 IMFMediaType_Release(node
->input_type
);
1605 node
->input_type
= mediatype
;
1606 if (node
->input_type
)
1607 IMFMediaType_AddRef(node
->input_type
);
1610 case MF_TOPOLOGY_SOURCESTREAM_NODE
:
1614 if (SUCCEEDED(hr
= topology_node_reserve_streams(&node
->inputs
, index
)))
1615 topology_node_set_stream_type(&node
->inputs
.streams
[index
], mediatype
);
1618 LeaveCriticalSection(&node
->cs
);
1623 static HRESULT WINAPI
topology_node_GetInputPrefType(IMFTopologyNode
*iface
, DWORD index
, IMFMediaType
**mediatype
)
1625 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
1628 TRACE("%p, %u, %p.\n", iface
, index
, mediatype
);
1630 EnterCriticalSection(&node
->cs
);
1632 if (index
< node
->inputs
.count
)
1634 hr
= topology_node_get_pref_type(&node
->inputs
, index
, mediatype
);
1636 else if (node
->node_type
== MF_TOPOLOGY_TEE_NODE
&& node
->input_type
)
1638 *mediatype
= node
->input_type
;
1639 IMFMediaType_AddRef(*mediatype
);
1644 LeaveCriticalSection(&node
->cs
);
1649 static HRESULT WINAPI
topology_node_CloneFrom(IMFTopologyNode
*iface
, IMFTopologyNode
*src_node
)
1651 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
1652 MF_TOPOLOGY_TYPE node_type
;
1653 IMFMediaType
*mediatype
;
1659 TRACE("%p, %p.\n", iface
, src_node
);
1661 if (FAILED(hr
= IMFTopologyNode_GetNodeType(src_node
, &node_type
)))
1664 if (node
->node_type
!= node_type
)
1665 return MF_E_INVALIDREQUEST
;
1667 if (FAILED(hr
= IMFTopologyNode_GetTopoNodeID(src_node
, &topoid
)))
1671 IMFTopologyNode_GetObject(src_node
, &object
);
1673 EnterCriticalSection(&node
->cs
);
1675 hr
= IMFTopologyNode_CopyAllItems(src_node
, node
->attributes
);
1678 hr
= topology_node_set_object(node
, object
);
1683 if (SUCCEEDED(IMFTopologyNode_GetInputCount(src_node
, &count
)))
1685 for (i
= 0; i
< count
; ++i
)
1687 if (SUCCEEDED(IMFTopologyNode_GetInputPrefType(src_node
, i
, &mediatype
)))
1689 IMFTopologyNode_SetInputPrefType(iface
, i
, mediatype
);
1690 IMFMediaType_Release(mediatype
);
1695 if (SUCCEEDED(IMFTopologyNode_GetOutputCount(src_node
, &count
)))
1697 for (i
= 0; i
< count
; ++i
)
1699 if (SUCCEEDED(IMFTopologyNode_GetOutputPrefType(src_node
, i
, &mediatype
)))
1701 IMFTopologyNode_SetOutputPrefType(iface
, i
, mediatype
);
1702 IMFMediaType_Release(mediatype
);
1707 LeaveCriticalSection(&node
->cs
);
1710 IUnknown_Release(object
);
1715 static const IMFTopologyNodeVtbl topologynodevtbl
=
1717 topology_node_QueryInterface
,
1718 topology_node_AddRef
,
1719 topology_node_Release
,
1720 topology_node_GetItem
,
1721 topology_node_GetItemType
,
1722 topology_node_CompareItem
,
1723 topology_node_Compare
,
1724 topology_node_GetUINT32
,
1725 topology_node_GetUINT64
,
1726 topology_node_GetDouble
,
1727 topology_node_GetGUID
,
1728 topology_node_GetStringLength
,
1729 topology_node_GetString
,
1730 topology_node_GetAllocatedString
,
1731 topology_node_GetBlobSize
,
1732 topology_node_GetBlob
,
1733 topology_node_GetAllocatedBlob
,
1734 topology_node_GetUnknown
,
1735 topology_node_SetItem
,
1736 topology_node_DeleteItem
,
1737 topology_node_DeleteAllItems
,
1738 topology_node_SetUINT32
,
1739 topology_node_SetUINT64
,
1740 topology_node_SetDouble
,
1741 topology_node_SetGUID
,
1742 topology_node_SetString
,
1743 topology_node_SetBlob
,
1744 topology_node_SetUnknown
,
1745 topology_node_LockStore
,
1746 topology_node_UnlockStore
,
1747 topology_node_GetCount
,
1748 topology_node_GetItemByIndex
,
1749 topology_node_CopyAllItems
,
1750 topology_node_SetObject
,
1751 topology_node_GetObject
,
1752 topology_node_GetNodeType
,
1753 topology_node_GetTopoNodeID
,
1754 topology_node_SetTopoNodeID
,
1755 topology_node_GetInputCount
,
1756 topology_node_GetOutputCount
,
1757 topology_node_ConnectOutput
,
1758 topology_node_DisconnectOutput
,
1759 topology_node_GetInput
,
1760 topology_node_GetOutput
,
1761 topology_node_SetOutputPrefType
,
1762 topology_node_GetOutputPrefType
,
1763 topology_node_SetInputPrefType
,
1764 topology_node_GetInputPrefType
,
1765 topology_node_CloneFrom
,
1768 static HRESULT
create_topology_node(MF_TOPOLOGY_TYPE node_type
, struct topology_node
**node
)
1772 *node
= heap_alloc_zero(sizeof(**node
));
1774 return E_OUTOFMEMORY
;
1776 (*node
)->IMFTopologyNode_iface
.lpVtbl
= &topologynodevtbl
;
1777 (*node
)->refcount
= 1;
1778 (*node
)->node_type
= node_type
;
1779 hr
= MFCreateAttributes(&(*node
)->attributes
, 0);
1785 (*node
)->id
= ((TOPOID
)GetCurrentProcessId() << 32) | InterlockedIncrement(&next_node_id
);
1786 InitializeCriticalSection(&(*node
)->cs
);
1791 /***********************************************************************
1792 * MFCreateTopologyNode (mf.@)
1794 HRESULT WINAPI
MFCreateTopologyNode(MF_TOPOLOGY_TYPE node_type
, IMFTopologyNode
**node
)
1796 struct topology_node
*object
;
1799 TRACE("%d, %p.\n", node_type
, node
);
1804 hr
= create_topology_node(node_type
, &object
);
1806 *node
= &object
->IMFTopologyNode_iface
;
1811 /***********************************************************************
1812 * MFGetTopoNodeCurrentType (mf.@)
1814 HRESULT WINAPI
MFGetTopoNodeCurrentType(IMFTopologyNode
*node
, DWORD stream
, BOOL output
, IMFMediaType
**type
)
1816 IMFMediaTypeHandler
*type_handler
;
1817 MF_TOPOLOGY_TYPE node_type
;
1818 IMFStreamSink
*stream_sink
;
1819 IMFStreamDescriptor
*sd
;
1820 IMFTransform
*transform
;
1821 UINT32 primary_output
;
1825 TRACE("%p, %u, %d, %p.\n", node
, stream
, output
, type
);
1827 if (FAILED(hr
= IMFTopologyNode_GetNodeType(node
, &node_type
)))
1832 case MF_TOPOLOGY_OUTPUT_NODE
:
1833 if (FAILED(hr
= IMFTopologyNode_GetObject(node
, &object
)))
1836 hr
= IUnknown_QueryInterface(object
, &IID_IMFStreamSink
, (void **)&stream_sink
);
1837 IUnknown_Release(object
);
1840 hr
= IMFStreamSink_GetMediaTypeHandler(stream_sink
, &type_handler
);
1841 IMFStreamSink_Release(stream_sink
);
1845 hr
= IMFMediaTypeHandler_GetCurrentMediaType(type_handler
, type
);
1846 IMFMediaTypeHandler_Release(type_handler
);
1850 case MF_TOPOLOGY_SOURCESTREAM_NODE
:
1851 if (FAILED(hr
= IMFTopologyNode_GetUnknown(node
, &MF_TOPONODE_STREAM_DESCRIPTOR
, &IID_IMFStreamDescriptor
,
1857 hr
= IMFStreamDescriptor_GetMediaTypeHandler(sd
, &type_handler
);
1858 IMFStreamDescriptor_Release(sd
);
1861 hr
= IMFMediaTypeHandler_GetCurrentMediaType(type_handler
, type
);
1862 IMFMediaTypeHandler_Release(type_handler
);
1865 case MF_TOPOLOGY_TRANSFORM_NODE
:
1866 if (FAILED(hr
= IMFTopologyNode_GetObject(node
, &object
)))
1869 hr
= IUnknown_QueryInterface(object
, &IID_IMFTransform
, (void **)&transform
);
1870 IUnknown_Release(object
);
1874 hr
= IMFTransform_GetOutputCurrentType(transform
, stream
, type
);
1876 hr
= IMFTransform_GetInputCurrentType(transform
, stream
, type
);
1877 IMFTransform_Release(transform
);
1880 case MF_TOPOLOGY_TEE_NODE
:
1881 if (SUCCEEDED(hr
= IMFTopologyNode_GetInputPrefType(node
, 0, type
)))
1884 if (FAILED(IMFTopologyNode_GetUINT32(node
, &MF_TOPONODE_PRIMARYOUTPUT
, &primary_output
)))
1887 hr
= IMFTopologyNode_GetOutputPrefType(node
, primary_output
, type
);
1896 static HRESULT WINAPI
topology_loader_QueryInterface(IMFTopoLoader
*iface
, REFIID riid
, void **out
)
1898 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), out
);
1900 if (IsEqualIID(riid
, &IID_IMFTopoLoader
) ||
1901 IsEqualIID(riid
, &IID_IUnknown
))
1904 IMFTopoLoader_AddRef(iface
);
1908 WARN("Unsupported %s.\n", debugstr_guid(riid
));
1910 return E_NOINTERFACE
;
1913 static ULONG WINAPI
topology_loader_AddRef(IMFTopoLoader
*iface
)
1915 struct topology_loader
*loader
= impl_from_IMFTopoLoader(iface
);
1916 ULONG refcount
= InterlockedIncrement(&loader
->refcount
);
1918 TRACE("%p, refcount %u.\n", iface
, refcount
);
1923 static ULONG WINAPI
topology_loader_Release(IMFTopoLoader
*iface
)
1925 struct topology_loader
*loader
= impl_from_IMFTopoLoader(iface
);
1926 ULONG refcount
= InterlockedDecrement(&loader
->refcount
);
1928 TRACE("%p, refcount %u.\n", iface
, refcount
);
1938 static HRESULT WINAPI
topology_loader_Load(IMFTopoLoader
*iface
, IMFTopology
*input_topology
,
1939 IMFTopology
**output_topology
, IMFTopology
*current_topology
)
1941 struct topology
*topology
= unsafe_impl_from_IMFTopology(input_topology
);
1942 IMFStreamSink
*sink
;
1946 FIXME("%p, %p, %p, %p.\n", iface
, input_topology
, output_topology
, current_topology
);
1948 if (current_topology
)
1949 FIXME("Current topology instance is ignored.\n");
1951 for (i
= 0; i
< topology
->nodes
.count
; ++i
)
1953 struct topology_node
*node
= topology
->nodes
.nodes
[i
];
1955 switch (node
->node_type
)
1957 case MF_TOPOLOGY_OUTPUT_NODE
:
1960 /* Sinks must be bound beforehand. */
1961 if (FAILED(IUnknown_QueryInterface(node
->object
, &IID_IMFStreamSink
, (void **)&sink
)))
1962 return MF_E_TOPO_SINK_ACTIVATES_UNSUPPORTED
;
1963 IMFStreamSink_Release(sink
);
1966 case MF_TOPOLOGY_SOURCESTREAM_NODE
:
1967 if (FAILED(hr
= IMFAttributes_GetItem(node
->attributes
, &MF_TOPONODE_STREAM_DESCRIPTOR
, NULL
)))
1975 if (FAILED(hr
= MFCreateTopology(output_topology
)))
1978 return IMFTopology_CloneFrom(*output_topology
, input_topology
);
1981 static const IMFTopoLoaderVtbl topologyloadervtbl
=
1983 topology_loader_QueryInterface
,
1984 topology_loader_AddRef
,
1985 topology_loader_Release
,
1986 topology_loader_Load
,
1989 /***********************************************************************
1990 * MFCreateTopoLoader (mf.@)
1992 HRESULT WINAPI
MFCreateTopoLoader(IMFTopoLoader
**loader
)
1994 struct topology_loader
*object
;
1996 TRACE("%p.\n", loader
);
2001 object
= heap_alloc(sizeof(*object
));
2003 return E_OUTOFMEMORY
;
2005 object
->IMFTopoLoader_iface
.lpVtbl
= &topologyloadervtbl
;
2006 object
->refcount
= 1;
2008 *loader
= &object
->IMFTopoLoader_iface
;
2013 static HRESULT WINAPI
seq_source_QueryInterface(IMFSequencerSource
*iface
, REFIID riid
, void **out
)
2015 struct seq_source
*seq_source
= impl_from_IMFSequencerSource(iface
);
2017 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), out
);
2021 if (IsEqualIID(riid
, &IID_IMFSequencerSource
) ||
2022 IsEqualIID(riid
, &IID_IUnknown
))
2024 *out
= &seq_source
->IMFSequencerSource_iface
;
2026 else if (IsEqualIID(riid
, &IID_IMFMediaSourceTopologyProvider
))
2028 *out
= &seq_source
->IMFMediaSourceTopologyProvider_iface
;
2032 WARN("Unimplemented %s.\n", debugstr_guid(riid
));
2033 return E_NOINTERFACE
;
2037 IUnknown_AddRef((IUnknown
*)*out
);
2042 static ULONG WINAPI
seq_source_AddRef(IMFSequencerSource
*iface
)
2044 struct seq_source
*seq_source
= impl_from_IMFSequencerSource(iface
);
2045 ULONG refcount
= InterlockedIncrement(&seq_source
->refcount
);
2047 TRACE("%p, refcount %u.\n", iface
, refcount
);
2052 static ULONG WINAPI
seq_source_Release(IMFSequencerSource
*iface
)
2054 struct seq_source
*seq_source
= impl_from_IMFSequencerSource(iface
);
2055 ULONG refcount
= InterlockedDecrement(&seq_source
->refcount
);
2057 TRACE("%p, refcount %u.\n", iface
, refcount
);
2061 heap_free(seq_source
);
2067 static HRESULT WINAPI
seq_source_AppendTopology(IMFSequencerSource
*iface
, IMFTopology
*topology
,
2068 DWORD flags
, MFSequencerElementId
*id
)
2070 FIXME("%p, %p, %x, %p.\n", iface
, topology
, flags
, id
);
2075 static HRESULT WINAPI
seq_source_DeleteTopology(IMFSequencerSource
*iface
, MFSequencerElementId id
)
2077 FIXME("%p, %#x.\n", iface
, id
);
2082 static HRESULT WINAPI
seq_source_GetPresentationContext(IMFSequencerSource
*iface
,
2083 IMFPresentationDescriptor
*descriptor
, MFSequencerElementId
*id
, IMFTopology
**topology
)
2085 FIXME("%p, %p, %p, %p.\n", iface
, descriptor
, id
, topology
);
2090 static HRESULT WINAPI
seq_source_UpdateTopology(IMFSequencerSource
*iface
, MFSequencerElementId id
,
2091 IMFTopology
*topology
)
2093 FIXME("%p, %#x, %p.\n", iface
, id
, topology
);
2098 static HRESULT WINAPI
seq_source_UpdateTopologyFlags(IMFSequencerSource
*iface
, MFSequencerElementId id
, DWORD flags
)
2100 FIXME("%p, %#x, %#x.\n", iface
, id
, flags
);
2105 static HRESULT WINAPI
seq_source_topology_provider_QueryInterface(IMFMediaSourceTopologyProvider
*iface
, REFIID riid
,
2108 struct seq_source
*seq_source
= impl_from_IMFMediaSourceTopologyProvider(iface
);
2109 return IMFSequencerSource_QueryInterface(&seq_source
->IMFSequencerSource_iface
, riid
, obj
);
2112 static ULONG WINAPI
seq_source_topology_provider_AddRef(IMFMediaSourceTopologyProvider
*iface
)
2114 struct seq_source
*seq_source
= impl_from_IMFMediaSourceTopologyProvider(iface
);
2115 return IMFSequencerSource_AddRef(&seq_source
->IMFSequencerSource_iface
);
2118 static ULONG WINAPI
seq_source_topology_provider_Release(IMFMediaSourceTopologyProvider
*iface
)
2120 struct seq_source
*seq_source
= impl_from_IMFMediaSourceTopologyProvider(iface
);
2121 return IMFSequencerSource_Release(&seq_source
->IMFSequencerSource_iface
);
2124 static HRESULT WINAPI
seq_source_topology_provider_GetMediaSourceTopology(IMFMediaSourceTopologyProvider
*iface
,
2125 IMFPresentationDescriptor
*pd
, IMFTopology
**topology
)
2127 FIXME("%p, %p, %p.\n", iface
, pd
, topology
);
2132 static const IMFMediaSourceTopologyProviderVtbl seq_source_topology_provider_vtbl
=
2134 seq_source_topology_provider_QueryInterface
,
2135 seq_source_topology_provider_AddRef
,
2136 seq_source_topology_provider_Release
,
2137 seq_source_topology_provider_GetMediaSourceTopology
,
2140 static const IMFSequencerSourceVtbl seqsourcevtbl
=
2142 seq_source_QueryInterface
,
2145 seq_source_AppendTopology
,
2146 seq_source_DeleteTopology
,
2147 seq_source_GetPresentationContext
,
2148 seq_source_UpdateTopology
,
2149 seq_source_UpdateTopologyFlags
,
2152 /***********************************************************************
2153 * MFCreateSequencerSource (mf.@)
2155 HRESULT WINAPI
MFCreateSequencerSource(IUnknown
*reserved
, IMFSequencerSource
**seq_source
)
2157 struct seq_source
*object
;
2159 TRACE("%p, %p.\n", reserved
, seq_source
);
2164 object
= heap_alloc(sizeof(*object
));
2166 return E_OUTOFMEMORY
;
2168 object
->IMFSequencerSource_iface
.lpVtbl
= &seqsourcevtbl
;
2169 object
->IMFMediaSourceTopologyProvider_iface
.lpVtbl
= &seq_source_topology_provider_vtbl
;
2170 object
->refcount
= 1;
2172 *seq_source
= &object
->IMFSequencerSource_iface
;