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
31 #include "wine/debug.h"
33 #include "mf_private.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(mfplat
);
37 static LONG next_node_id
;
38 static TOPOID next_topology_id
;
42 IMFMediaType
*preferred_type
;
43 struct topology_node
*connection
;
44 DWORD connection_stream
;
49 struct node_stream
*streams
;
56 IMFTopologyNode IMFTopologyNode_iface
;
58 IMFAttributes
*attributes
;
59 MF_TOPOLOGY_TYPE node_type
;
62 IMFMediaType
*input_type
; /* Only for tee nodes. */
63 struct node_streams inputs
;
64 struct node_streams outputs
;
70 IMFTopology IMFTopology_iface
;
72 IMFAttributes
*attributes
;
75 struct topology_node
**nodes
;
82 struct topology_loader
84 IMFTopoLoader IMFTopoLoader_iface
;
90 IMFSequencerSource IMFSequencerSource_iface
;
91 IMFMediaSourceTopologyProvider IMFMediaSourceTopologyProvider_iface
;
95 static inline struct topology
*impl_from_IMFTopology(IMFTopology
*iface
)
97 return CONTAINING_RECORD(iface
, struct topology
, IMFTopology_iface
);
100 static struct topology_node
*impl_from_IMFTopologyNode(IMFTopologyNode
*iface
)
102 return CONTAINING_RECORD(iface
, struct topology_node
, IMFTopologyNode_iface
);
105 static const IMFTopologyNodeVtbl topologynodevtbl
;
107 static struct topology_node
*unsafe_impl_from_IMFTopologyNode(IMFTopologyNode
*iface
)
109 if (!iface
|| iface
->lpVtbl
!= &topologynodevtbl
)
111 return impl_from_IMFTopologyNode(iface
);
114 static HRESULT
create_topology_node(MF_TOPOLOGY_TYPE node_type
, struct topology_node
**node
);
115 static HRESULT
topology_node_connect_output(struct topology_node
*node
, DWORD output_index
,
116 struct topology_node
*connection
, DWORD input_index
);
118 static struct topology
*unsafe_impl_from_IMFTopology(IMFTopology
*iface
);
120 static struct topology_loader
*impl_from_IMFTopoLoader(IMFTopoLoader
*iface
)
122 return CONTAINING_RECORD(iface
, struct topology_loader
, IMFTopoLoader_iface
);
125 static struct seq_source
*impl_from_IMFSequencerSource(IMFSequencerSource
*iface
)
127 return CONTAINING_RECORD(iface
, struct seq_source
, IMFSequencerSource_iface
);
130 static struct seq_source
*impl_from_IMFMediaSourceTopologyProvider(IMFMediaSourceTopologyProvider
*iface
)
132 return CONTAINING_RECORD(iface
, struct seq_source
, IMFMediaSourceTopologyProvider_iface
);
135 static HRESULT
topology_node_reserve_streams(struct node_streams
*streams
, DWORD index
)
137 if (!mf_array_reserve((void **)&streams
->streams
, &streams
->size
, index
+ 1, sizeof(*streams
->streams
)))
138 return E_OUTOFMEMORY
;
140 if (index
>= streams
->count
)
142 memset(&streams
->streams
[streams
->count
], 0, (index
- streams
->count
+ 1) * sizeof(*streams
->streams
));
143 streams
->count
= index
+ 1;
149 static HRESULT WINAPI
topology_QueryInterface(IMFTopology
*iface
, REFIID riid
, void **out
)
151 struct topology
*topology
= impl_from_IMFTopology(iface
);
153 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), out
);
155 if (IsEqualIID(riid
, &IID_IMFTopology
) ||
156 IsEqualIID(riid
, &IID_IMFAttributes
) ||
157 IsEqualIID(riid
, &IID_IUnknown
))
159 *out
= &topology
->IMFTopology_iface
;
163 FIXME("(%s, %p)\n", debugstr_guid(riid
), out
);
165 return E_NOINTERFACE
;
168 IUnknown_AddRef((IUnknown
*)*out
);
172 static ULONG WINAPI
topology_AddRef(IMFTopology
*iface
)
174 struct topology
*topology
= impl_from_IMFTopology(iface
);
175 ULONG refcount
= InterlockedIncrement(&topology
->refcount
);
177 TRACE("%p, refcount %lu.\n", iface
, refcount
);
182 static HRESULT
topology_node_disconnect_output(struct topology_node
*node
, DWORD output_index
)
184 struct topology_node
*connection
= NULL
;
185 struct node_stream
*stream
;
186 DWORD connection_stream
;
189 EnterCriticalSection(&node
->cs
);
191 if (output_index
< node
->outputs
.count
)
193 stream
= &node
->outputs
.streams
[output_index
];
195 if (stream
->connection
)
197 connection
= stream
->connection
;
198 connection_stream
= stream
->connection_stream
;
199 stream
->connection
= NULL
;
200 stream
->connection_stream
= 0;
208 LeaveCriticalSection(&node
->cs
);
212 EnterCriticalSection(&connection
->cs
);
214 if (connection_stream
< connection
->inputs
.count
)
216 stream
= &connection
->inputs
.streams
[connection_stream
];
218 if (stream
->connection
)
220 stream
->connection
= NULL
;
221 stream
->connection_stream
= 0;
225 LeaveCriticalSection(&connection
->cs
);
227 IMFTopologyNode_Release(&connection
->IMFTopologyNode_iface
);
228 IMFTopologyNode_Release(&node
->IMFTopologyNode_iface
);
234 static void topology_node_disconnect(struct topology_node
*node
)
236 struct node_stream
*stream
;
239 for (i
= 0; i
< node
->outputs
.count
; ++i
)
240 topology_node_disconnect_output(node
, i
);
242 for (i
= 0; i
< node
->inputs
.count
; ++i
)
244 stream
= &node
->inputs
.streams
[i
];
245 if (stream
->connection
)
246 topology_node_disconnect_output(stream
->connection
, stream
->connection_stream
);
250 static void topology_clear(struct topology
*topology
)
254 for (i
= 0; i
< topology
->nodes
.count
; ++i
)
256 topology_node_disconnect(topology
->nodes
.nodes
[i
]);
257 IMFTopologyNode_Release(&topology
->nodes
.nodes
[i
]->IMFTopologyNode_iface
);
259 free(topology
->nodes
.nodes
);
260 topology
->nodes
.nodes
= NULL
;
261 topology
->nodes
.count
= 0;
262 topology
->nodes
.size
= 0;
265 static ULONG WINAPI
topology_Release(IMFTopology
*iface
)
267 struct topology
*topology
= impl_from_IMFTopology(iface
);
268 ULONG refcount
= InterlockedDecrement(&topology
->refcount
);
270 TRACE("%p, refcount %lu.\n", iface
, refcount
);
274 if (topology
->attributes
)
275 IMFAttributes_Release(topology
->attributes
);
276 topology_clear(topology
);
283 static HRESULT WINAPI
topology_GetItem(IMFTopology
*iface
, REFGUID key
, PROPVARIANT
*value
)
285 struct topology
*topology
= impl_from_IMFTopology(iface
);
287 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), value
);
289 return IMFAttributes_GetItem(topology
->attributes
, key
, value
);
292 static HRESULT WINAPI
topology_GetItemType(IMFTopology
*iface
, REFGUID key
, MF_ATTRIBUTE_TYPE
*type
)
294 struct topology
*topology
= impl_from_IMFTopology(iface
);
296 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), type
);
298 return IMFAttributes_GetItemType(topology
->attributes
, key
, type
);
301 static HRESULT WINAPI
topology_CompareItem(IMFTopology
*iface
, REFGUID key
, REFPROPVARIANT value
, BOOL
*result
)
303 struct topology
*topology
= impl_from_IMFTopology(iface
);
305 TRACE("%p, %s, %p, %p.\n", iface
, debugstr_guid(key
), value
, result
);
307 return IMFAttributes_CompareItem(topology
->attributes
, key
, value
, result
);
310 static HRESULT WINAPI
topology_Compare(IMFTopology
*iface
, IMFAttributes
*theirs
, MF_ATTRIBUTES_MATCH_TYPE type
,
313 struct topology
*topology
= impl_from_IMFTopology(iface
);
315 TRACE("%p, %p, %d, %p.\n", iface
, theirs
, type
, result
);
317 return IMFAttributes_Compare(topology
->attributes
, theirs
, type
, result
);
320 static HRESULT WINAPI
topology_GetUINT32(IMFTopology
*iface
, REFGUID key
, UINT32
*value
)
322 struct topology
*topology
= impl_from_IMFTopology(iface
);
324 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), value
);
326 return IMFAttributes_GetUINT32(topology
->attributes
, key
, value
);
329 static HRESULT WINAPI
topology_GetUINT64(IMFTopology
*iface
, REFGUID key
, UINT64
*value
)
331 struct topology
*topology
= impl_from_IMFTopology(iface
);
333 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), value
);
335 return IMFAttributes_GetUINT64(topology
->attributes
, key
, value
);
338 static HRESULT WINAPI
topology_GetDouble(IMFTopology
*iface
, REFGUID key
, double *value
)
340 struct topology
*topology
= impl_from_IMFTopology(iface
);
342 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), value
);
344 return IMFAttributes_GetDouble(topology
->attributes
, key
, value
);
347 static HRESULT WINAPI
topology_GetGUID(IMFTopology
*iface
, REFGUID key
, GUID
*value
)
349 struct topology
*topology
= impl_from_IMFTopology(iface
);
351 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), value
);
353 return IMFAttributes_GetGUID(topology
->attributes
, key
, value
);
356 static HRESULT WINAPI
topology_GetStringLength(IMFTopology
*iface
, REFGUID key
, UINT32
*length
)
358 struct topology
*topology
= impl_from_IMFTopology(iface
);
360 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), length
);
362 return IMFAttributes_GetStringLength(topology
->attributes
, key
, length
);
365 static HRESULT WINAPI
topology_GetString(IMFTopology
*iface
, REFGUID key
, WCHAR
*value
,
366 UINT32 size
, UINT32
*length
)
368 struct topology
*topology
= impl_from_IMFTopology(iface
);
370 TRACE("%p, %s, %p, %d, %p.\n", iface
, debugstr_guid(key
), value
, size
, length
);
372 return IMFAttributes_GetString(topology
->attributes
, key
, value
, size
, length
);
375 static HRESULT WINAPI
topology_GetAllocatedString(IMFTopology
*iface
, REFGUID key
,
376 WCHAR
**value
, UINT32
*length
)
378 struct topology
*topology
= impl_from_IMFTopology(iface
);
380 TRACE("%p, %s, %p, %p.\n", iface
, debugstr_guid(key
), value
, length
);
382 return IMFAttributes_GetAllocatedString(topology
->attributes
, key
, value
, length
);
385 static HRESULT WINAPI
topology_GetBlobSize(IMFTopology
*iface
, REFGUID key
, UINT32
*size
)
387 struct topology
*topology
= impl_from_IMFTopology(iface
);
389 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), size
);
391 return IMFAttributes_GetBlobSize(topology
->attributes
, key
, size
);
394 static HRESULT WINAPI
topology_GetBlob(IMFTopology
*iface
, REFGUID key
, UINT8
*buf
,
395 UINT32 bufsize
, UINT32
*blobsize
)
397 struct topology
*topology
= impl_from_IMFTopology(iface
);
399 TRACE("%p, %s, %p, %d, %p.\n", iface
, debugstr_guid(key
), buf
, bufsize
, blobsize
);
401 return IMFAttributes_GetBlob(topology
->attributes
, key
, buf
, bufsize
, blobsize
);
404 static HRESULT WINAPI
topology_GetAllocatedBlob(IMFTopology
*iface
, REFGUID key
, UINT8
**buf
, UINT32
*size
)
406 struct topology
*topology
= impl_from_IMFTopology(iface
);
408 TRACE("%p, %s, %p, %p.\n", iface
, debugstr_guid(key
), buf
, size
);
410 return IMFAttributes_GetAllocatedBlob(topology
->attributes
, key
, buf
, size
);
413 static HRESULT WINAPI
topology_GetUnknown(IMFTopology
*iface
, REFGUID key
, REFIID riid
, void **ppv
)
415 struct topology
*topology
= impl_from_IMFTopology(iface
);
417 TRACE("%p, %s, %s, %p.\n", iface
, debugstr_guid(key
), debugstr_guid(riid
), ppv
);
419 return IMFAttributes_GetUnknown(topology
->attributes
, key
, riid
, ppv
);
422 static HRESULT WINAPI
topology_SetItem(IMFTopology
*iface
, REFGUID key
, REFPROPVARIANT value
)
424 struct topology
*topology
= impl_from_IMFTopology(iface
);
426 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), value
);
428 return IMFAttributes_SetItem(topology
->attributes
, key
, value
);
431 static HRESULT WINAPI
topology_DeleteItem(IMFTopology
*iface
, REFGUID key
)
433 struct topology
*topology
= impl_from_IMFTopology(iface
);
435 TRACE("%p, %s.\n", topology
, debugstr_guid(key
));
437 return IMFAttributes_DeleteItem(topology
->attributes
, key
);
440 static HRESULT WINAPI
topology_DeleteAllItems(IMFTopology
*iface
)
442 struct topology
*topology
= impl_from_IMFTopology(iface
);
444 TRACE("%p.\n", iface
);
446 return IMFAttributes_DeleteAllItems(topology
->attributes
);
449 static HRESULT WINAPI
topology_SetUINT32(IMFTopology
*iface
, REFGUID key
, UINT32 value
)
451 struct topology
*topology
= impl_from_IMFTopology(iface
);
453 TRACE("%p, %s, %d.\n", iface
, debugstr_guid(key
), value
);
455 return IMFAttributes_SetUINT32(topology
->attributes
, key
, value
);
458 static HRESULT WINAPI
topology_SetUINT64(IMFTopology
*iface
, REFGUID key
, UINT64 value
)
460 struct topology
*topology
= impl_from_IMFTopology(iface
);
462 TRACE("%p, %s, %s.\n", iface
, debugstr_guid(key
), wine_dbgstr_longlong(value
));
464 return IMFAttributes_SetUINT64(topology
->attributes
, key
, value
);
467 static HRESULT WINAPI
topology_SetDouble(IMFTopology
*iface
, REFGUID key
, double value
)
469 struct topology
*topology
= impl_from_IMFTopology(iface
);
471 TRACE("%p, %s, %f.\n", iface
, debugstr_guid(key
), value
);
473 return IMFAttributes_SetDouble(topology
->attributes
, key
, value
);
476 static HRESULT WINAPI
topology_SetGUID(IMFTopology
*iface
, REFGUID key
, REFGUID value
)
478 struct topology
*topology
= impl_from_IMFTopology(iface
);
480 TRACE("%p, %s, %s.\n", iface
, debugstr_guid(key
), debugstr_guid(value
));
482 return IMFAttributes_SetGUID(topology
->attributes
, key
, value
);
485 static HRESULT WINAPI
topology_SetString(IMFTopology
*iface
, REFGUID key
, const WCHAR
*value
)
487 struct topology
*topology
= impl_from_IMFTopology(iface
);
489 TRACE("%p, %s, %s.\n", iface
, debugstr_guid(key
), debugstr_w(value
));
491 return IMFAttributes_SetString(topology
->attributes
, key
, value
);
494 static HRESULT WINAPI
topology_SetBlob(IMFTopology
*iface
, REFGUID key
, const UINT8
*buf
, UINT32 size
)
496 struct topology
*topology
= impl_from_IMFTopology(iface
);
498 TRACE("%p, %s, %p, %d.\n", iface
, debugstr_guid(key
), buf
, size
);
500 return IMFAttributes_SetBlob(topology
->attributes
, key
, buf
, size
);
503 static HRESULT WINAPI
topology_SetUnknown(IMFTopology
*iface
, REFGUID key
, IUnknown
*unknown
)
505 struct topology
*topology
= impl_from_IMFTopology(iface
);
507 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), unknown
);
509 return IMFAttributes_SetUnknown(topology
->attributes
, key
, unknown
);
512 static HRESULT WINAPI
topology_LockStore(IMFTopology
*iface
)
514 struct topology
*topology
= impl_from_IMFTopology(iface
);
516 TRACE("%p.\n", iface
);
518 return IMFAttributes_LockStore(topology
->attributes
);
521 static HRESULT WINAPI
topology_UnlockStore(IMFTopology
*iface
)
523 struct topology
*topology
= impl_from_IMFTopology(iface
);
525 TRACE("%p.\n", iface
);
527 return IMFAttributes_UnlockStore(topology
->attributes
);
530 static HRESULT WINAPI
topology_GetCount(IMFTopology
*iface
, UINT32
*count
)
532 struct topology
*topology
= impl_from_IMFTopology(iface
);
534 TRACE("%p, %p.\n", iface
, count
);
536 return IMFAttributes_GetCount(topology
->attributes
, count
);
539 static HRESULT WINAPI
topology_GetItemByIndex(IMFTopology
*iface
, UINT32 index
, GUID
*key
, PROPVARIANT
*value
)
541 struct topology
*topology
= impl_from_IMFTopology(iface
);
543 TRACE("%p, %u, %p, %p.\n", iface
, index
, key
, value
);
545 return IMFAttributes_GetItemByIndex(topology
->attributes
, index
, key
, value
);
548 static HRESULT WINAPI
topology_CopyAllItems(IMFTopology
*iface
, IMFAttributes
*dest
)
550 struct topology
*topology
= impl_from_IMFTopology(iface
);
552 TRACE("%p, %p.\n", iface
, dest
);
554 return IMFAttributes_CopyAllItems(topology
->attributes
, dest
);
557 static HRESULT WINAPI
topology_GetTopologyID(IMFTopology
*iface
, TOPOID
*id
)
559 struct topology
*topology
= impl_from_IMFTopology(iface
);
561 TRACE("%p, %p.\n", iface
, id
);
571 static HRESULT
topology_get_node_by_id(const struct topology
*topology
, TOPOID id
, struct topology_node
**node
)
575 for (i
= 0; i
< topology
->nodes
.count
; ++i
)
577 if (topology
->nodes
.nodes
[i
]->id
== id
)
579 *node
= topology
->nodes
.nodes
[i
];
584 return MF_E_NOT_FOUND
;
587 static HRESULT
topology_add_node(struct topology
*topology
, struct topology_node
*node
)
589 struct topology_node
*match
;
594 if (SUCCEEDED(topology_get_node_by_id(topology
, node
->id
, &match
)))
597 if (!mf_array_reserve((void **)&topology
->nodes
.nodes
, &topology
->nodes
.size
, topology
->nodes
.count
+ 1,
598 sizeof(*topology
->nodes
.nodes
)))
600 return E_OUTOFMEMORY
;
603 topology
->nodes
.nodes
[topology
->nodes
.count
++] = node
;
604 IMFTopologyNode_AddRef(&node
->IMFTopologyNode_iface
);
609 static HRESULT WINAPI
topology_AddNode(IMFTopology
*iface
, IMFTopologyNode
*node_iface
)
611 struct topology
*topology
= impl_from_IMFTopology(iface
);
612 struct topology_node
*node
= unsafe_impl_from_IMFTopologyNode(node_iface
);
614 TRACE("%p, %p.\n", iface
, node_iface
);
616 return topology_add_node(topology
, node
);
619 static HRESULT WINAPI
topology_RemoveNode(IMFTopology
*iface
, IMFTopologyNode
*node
)
621 struct topology
*topology
= impl_from_IMFTopology(iface
);
624 TRACE("%p, %p.\n", iface
, node
);
626 for (i
= 0; i
< topology
->nodes
.count
; ++i
)
628 if (&topology
->nodes
.nodes
[i
]->IMFTopologyNode_iface
== node
)
630 topology_node_disconnect(topology
->nodes
.nodes
[i
]);
631 IMFTopologyNode_Release(&topology
->nodes
.nodes
[i
]->IMFTopologyNode_iface
);
632 count
= topology
->nodes
.count
- i
- 1;
635 memmove(&topology
->nodes
.nodes
[i
], &topology
->nodes
.nodes
[i
+ 1],
636 count
* sizeof(*topology
->nodes
.nodes
));
638 topology
->nodes
.count
--;
646 static HRESULT WINAPI
topology_GetNodeCount(IMFTopology
*iface
, WORD
*count
)
648 struct topology
*topology
= impl_from_IMFTopology(iface
);
650 TRACE("%p, %p.\n", iface
, count
);
655 *count
= topology
->nodes
.count
;
660 static HRESULT WINAPI
topology_GetNode(IMFTopology
*iface
, WORD index
, IMFTopologyNode
**node
)
662 struct topology
*topology
= impl_from_IMFTopology(iface
);
664 TRACE("%p, %u, %p.\n", iface
, index
, node
);
669 if (index
>= topology
->nodes
.count
)
670 return MF_E_INVALIDINDEX
;
672 *node
= &topology
->nodes
.nodes
[index
]->IMFTopologyNode_iface
;
673 IMFTopologyNode_AddRef(*node
);
678 static HRESULT WINAPI
topology_Clear(IMFTopology
*iface
)
680 struct topology
*topology
= impl_from_IMFTopology(iface
);
682 TRACE("%p.\n", iface
);
684 topology_clear(topology
);
688 static HRESULT WINAPI
topology_CloneFrom(IMFTopology
*iface
, IMFTopology
*src
)
690 struct topology
*topology
= impl_from_IMFTopology(iface
);
691 struct topology
*src_topology
= unsafe_impl_from_IMFTopology(src
);
692 struct topology_node
*node
;
696 TRACE("%p, %p.\n", iface
, src
);
698 topology_clear(topology
);
701 for (i
= 0; i
< src_topology
->nodes
.count
; ++i
)
703 if (FAILED(hr
= create_topology_node(src_topology
->nodes
.nodes
[i
]->node_type
, &node
)))
705 WARN("Failed to create a node, hr %#lx.\n", hr
);
709 if (SUCCEEDED(hr
= IMFTopologyNode_CloneFrom(&node
->IMFTopologyNode_iface
,
710 &src_topology
->nodes
.nodes
[i
]->IMFTopologyNode_iface
)))
712 topology_add_node(topology
, node
);
715 IMFTopologyNode_Release(&node
->IMFTopologyNode_iface
);
718 /* Clone connections. */
719 for (i
= 0; i
< src_topology
->nodes
.count
; ++i
)
721 const struct node_streams
*outputs
= &src_topology
->nodes
.nodes
[i
]->outputs
;
723 for (j
= 0; j
< outputs
->count
; ++j
)
725 DWORD input_index
= outputs
->streams
[j
].connection_stream
;
726 TOPOID id
= outputs
->streams
[j
].connection
->id
;
728 /* Skip node lookup in destination topology, assuming same node order. */
729 if (SUCCEEDED(hr
= topology_get_node_by_id(topology
, id
, &node
)))
730 topology_node_connect_output(topology
->nodes
.nodes
[i
], j
, node
, input_index
);
734 /* Copy attributes and id. */
735 hr
= IMFTopology_CopyAllItems(src
, (IMFAttributes
*)&topology
->IMFTopology_iface
);
737 topology
->id
= src_topology
->id
;
742 static HRESULT WINAPI
topology_GetNodeByID(IMFTopology
*iface
, TOPOID id
, IMFTopologyNode
**ret
)
744 struct topology
*topology
= impl_from_IMFTopology(iface
);
745 struct topology_node
*node
;
748 TRACE("%p, %p.\n", iface
, ret
);
750 if (SUCCEEDED(hr
= topology_get_node_by_id(topology
, id
, &node
)))
752 *ret
= &node
->IMFTopologyNode_iface
;
753 IMFTopologyNode_AddRef(*ret
);
761 static HRESULT
topology_get_node_collection(const struct topology
*topology
, MF_TOPOLOGY_TYPE node_type
,
762 IMFCollection
**collection
)
770 if (FAILED(hr
= MFCreateCollection(collection
)))
773 for (i
= 0; i
< topology
->nodes
.count
; ++i
)
775 if (topology
->nodes
.nodes
[i
]->node_type
== node_type
)
777 if (FAILED(hr
= IMFCollection_AddElement(*collection
,
778 (IUnknown
*)&topology
->nodes
.nodes
[i
]->IMFTopologyNode_iface
)))
780 IMFCollection_Release(*collection
);
790 static HRESULT WINAPI
topology_GetSourceNodeCollection(IMFTopology
*iface
, IMFCollection
**collection
)
792 struct topology
*topology
= impl_from_IMFTopology(iface
);
794 TRACE("%p, %p.\n", iface
, collection
);
796 return topology_get_node_collection(topology
, MF_TOPOLOGY_SOURCESTREAM_NODE
, collection
);
799 static HRESULT WINAPI
topology_GetOutputNodeCollection(IMFTopology
*iface
, IMFCollection
**collection
)
801 struct topology
*topology
= impl_from_IMFTopology(iface
);
803 TRACE("%p, %p.\n", iface
, collection
);
805 return topology_get_node_collection(topology
, MF_TOPOLOGY_OUTPUT_NODE
, collection
);
808 static const IMFTopologyVtbl topologyvtbl
=
810 topology_QueryInterface
,
814 topology_GetItemType
,
815 topology_CompareItem
,
821 topology_GetStringLength
,
823 topology_GetAllocatedString
,
824 topology_GetBlobSize
,
826 topology_GetAllocatedBlob
,
830 topology_DeleteAllItems
,
839 topology_UnlockStore
,
841 topology_GetItemByIndex
,
842 topology_CopyAllItems
,
843 topology_GetTopologyID
,
846 topology_GetNodeCount
,
850 topology_GetNodeByID
,
851 topology_GetSourceNodeCollection
,
852 topology_GetOutputNodeCollection
,
855 static struct topology
*unsafe_impl_from_IMFTopology(IMFTopology
*iface
)
857 if (!iface
|| iface
->lpVtbl
!= &topologyvtbl
)
859 return impl_from_IMFTopology(iface
);
862 static TOPOID
topology_generate_id(void)
868 old
= next_topology_id
;
870 while (InterlockedCompareExchange64((LONG64
*)&next_topology_id
, old
+ 1, old
) != old
);
872 return next_topology_id
;
875 /***********************************************************************
876 * MFCreateTopology (mf.@)
878 HRESULT WINAPI
MFCreateTopology(IMFTopology
**topology
)
880 struct topology
*object
;
883 TRACE("%p.\n", topology
);
888 if (!(object
= calloc(1, sizeof(*object
))))
889 return E_OUTOFMEMORY
;
891 object
->IMFTopology_iface
.lpVtbl
= &topologyvtbl
;
892 object
->refcount
= 1;
894 hr
= MFCreateAttributes(&object
->attributes
, 0);
897 IMFTopology_Release(&object
->IMFTopology_iface
);
901 object
->id
= topology_generate_id();
903 *topology
= &object
->IMFTopology_iface
;
908 static HRESULT WINAPI
topology_node_QueryInterface(IMFTopologyNode
*iface
, REFIID riid
, void **out
)
910 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
912 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), out
);
914 if (IsEqualIID(riid
, &IID_IMFTopologyNode
) ||
915 IsEqualIID(riid
, &IID_IMFAttributes
) ||
916 IsEqualIID(riid
, &IID_IUnknown
))
918 *out
= &node
->IMFTopologyNode_iface
;
919 IMFTopologyNode_AddRef(iface
);
923 WARN("Unsupported interface %s.\n", debugstr_guid(riid
));
926 return E_NOINTERFACE
;
929 static ULONG WINAPI
topology_node_AddRef(IMFTopologyNode
*iface
)
931 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
932 ULONG refcount
= InterlockedIncrement(&node
->refcount
);
934 TRACE("%p, refcount %lu.\n", iface
, refcount
);
939 static ULONG WINAPI
topology_node_Release(IMFTopologyNode
*iface
)
941 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
942 ULONG refcount
= InterlockedDecrement(&node
->refcount
);
945 TRACE("%p, refcount %lu.\n", iface
, refcount
);
950 IUnknown_Release(node
->object
);
951 if (node
->input_type
)
952 IMFMediaType_Release(node
->input_type
);
953 for (i
= 0; i
< node
->inputs
.count
; ++i
)
955 if (node
->inputs
.streams
[i
].preferred_type
)
956 IMFMediaType_Release(node
->inputs
.streams
[i
].preferred_type
);
958 for (i
= 0; i
< node
->outputs
.count
; ++i
)
960 if (node
->outputs
.streams
[i
].preferred_type
)
961 IMFMediaType_Release(node
->outputs
.streams
[i
].preferred_type
);
963 free(node
->inputs
.streams
);
964 free(node
->outputs
.streams
);
965 IMFAttributes_Release(node
->attributes
);
966 DeleteCriticalSection(&node
->cs
);
973 static HRESULT WINAPI
topology_node_GetItem(IMFTopologyNode
*iface
, REFGUID key
, PROPVARIANT
*value
)
975 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
977 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), value
);
979 return IMFAttributes_GetItem(node
->attributes
, key
, value
);
982 static HRESULT WINAPI
topology_node_GetItemType(IMFTopologyNode
*iface
, REFGUID key
, MF_ATTRIBUTE_TYPE
*type
)
984 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
986 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), type
);
988 return IMFAttributes_GetItemType(node
->attributes
, key
, type
);
991 static HRESULT WINAPI
topology_node_CompareItem(IMFTopologyNode
*iface
, REFGUID key
, REFPROPVARIANT value
, BOOL
*result
)
993 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
995 TRACE("%p, %s, %p, %p.\n", iface
, debugstr_guid(key
), value
, result
);
997 return IMFAttributes_CompareItem(node
->attributes
, key
, value
, result
);
1000 static HRESULT WINAPI
topology_node_Compare(IMFTopologyNode
*iface
, IMFAttributes
*theirs
,
1001 MF_ATTRIBUTES_MATCH_TYPE type
, BOOL
*result
)
1003 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
1005 TRACE("%p, %p, %d, %p.\n", iface
, theirs
, type
, result
);
1007 return IMFAttributes_Compare(node
->attributes
, theirs
, type
, result
);
1010 static HRESULT WINAPI
topology_node_GetUINT32(IMFTopologyNode
*iface
, REFGUID key
, UINT32
*value
)
1012 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
1014 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), value
);
1016 return IMFAttributes_GetUINT32(node
->attributes
, key
, value
);
1019 static HRESULT WINAPI
topology_node_GetUINT64(IMFTopologyNode
*iface
, REFGUID key
, UINT64
*value
)
1021 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
1023 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), value
);
1025 return IMFAttributes_GetUINT64(node
->attributes
, key
, value
);
1028 static HRESULT WINAPI
topology_node_GetDouble(IMFTopologyNode
*iface
, REFGUID key
, double *value
)
1030 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
1032 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), value
);
1034 return IMFAttributes_GetDouble(node
->attributes
, key
, value
);
1037 static HRESULT WINAPI
topology_node_GetGUID(IMFTopologyNode
*iface
, REFGUID key
, GUID
*value
)
1039 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
1041 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), value
);
1043 return IMFAttributes_GetGUID(node
->attributes
, key
, value
);
1046 static HRESULT WINAPI
topology_node_GetStringLength(IMFTopologyNode
*iface
, REFGUID key
, UINT32
*length
)
1048 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
1050 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), length
);
1052 return IMFAttributes_GetStringLength(node
->attributes
, key
, length
);
1055 static HRESULT WINAPI
topology_node_GetString(IMFTopologyNode
*iface
, REFGUID key
, WCHAR
*value
,
1056 UINT32 size
, UINT32
*length
)
1058 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
1060 TRACE("%p, %s, %p, %d, %p.\n", iface
, debugstr_guid(key
), value
, size
, length
);
1062 return IMFAttributes_GetString(node
->attributes
, key
, value
, size
, length
);
1065 static HRESULT WINAPI
topology_node_GetAllocatedString(IMFTopologyNode
*iface
, REFGUID key
,
1066 WCHAR
**value
, UINT32
*length
)
1068 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
1070 TRACE("%p, %s, %p, %p.\n", iface
, debugstr_guid(key
), value
, length
);
1072 return IMFAttributes_GetAllocatedString(node
->attributes
, key
, value
, length
);
1075 static HRESULT WINAPI
topology_node_GetBlobSize(IMFTopologyNode
*iface
, REFGUID key
, UINT32
*size
)
1077 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
1079 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), size
);
1081 return IMFAttributes_GetBlobSize(node
->attributes
, key
, size
);
1084 static HRESULT WINAPI
topology_node_GetBlob(IMFTopologyNode
*iface
, REFGUID key
, UINT8
*buf
,
1085 UINT32 bufsize
, UINT32
*blobsize
)
1087 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
1089 TRACE("%p, %s, %p, %d, %p.\n", iface
, debugstr_guid(key
), buf
, bufsize
, blobsize
);
1091 return IMFAttributes_GetBlob(node
->attributes
, key
, buf
, bufsize
, blobsize
);
1094 static HRESULT WINAPI
topology_node_GetAllocatedBlob(IMFTopologyNode
*iface
, REFGUID key
, UINT8
**buf
, UINT32
*size
)
1096 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
1098 TRACE("%p, %s, %p, %p.\n", iface
, debugstr_guid(key
), buf
, size
);
1100 return IMFAttributes_GetAllocatedBlob(node
->attributes
, key
, buf
, size
);
1103 static HRESULT WINAPI
topology_node_GetUnknown(IMFTopologyNode
*iface
, REFGUID key
, REFIID riid
, void **ppv
)
1105 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
1107 TRACE("%p, %s, %s, %p.\n", iface
, debugstr_guid(key
), debugstr_guid(riid
), ppv
);
1109 return IMFAttributes_GetUnknown(node
->attributes
, key
, riid
, ppv
);
1112 static HRESULT WINAPI
topology_node_SetItem(IMFTopologyNode
*iface
, REFGUID key
, REFPROPVARIANT value
)
1114 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
1116 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), value
);
1118 return IMFAttributes_SetItem(node
->attributes
, key
, value
);
1121 static HRESULT WINAPI
topology_node_DeleteItem(IMFTopologyNode
*iface
, REFGUID key
)
1123 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
1125 TRACE("%p, %s.\n", iface
, debugstr_guid(key
));
1127 return IMFAttributes_DeleteItem(node
->attributes
, key
);
1130 static HRESULT WINAPI
topology_node_DeleteAllItems(IMFTopologyNode
*iface
)
1132 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
1134 TRACE("%p.\n", iface
);
1136 return IMFAttributes_DeleteAllItems(node
->attributes
);
1139 static HRESULT WINAPI
topology_node_SetUINT32(IMFTopologyNode
*iface
, REFGUID key
, UINT32 value
)
1141 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
1143 TRACE("%p, %s, %d.\n", iface
, debugstr_guid(key
), value
);
1145 return IMFAttributes_SetUINT32(node
->attributes
, key
, value
);
1148 static HRESULT WINAPI
topology_node_SetUINT64(IMFTopologyNode
*iface
, REFGUID key
, UINT64 value
)
1150 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
1152 TRACE("%p, %s, %s.\n", iface
, debugstr_guid(key
), wine_dbgstr_longlong(value
));
1154 return IMFAttributes_SetUINT64(node
->attributes
, key
, value
);
1157 static HRESULT WINAPI
topology_node_SetDouble(IMFTopologyNode
*iface
, REFGUID key
, double value
)
1159 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
1161 TRACE("%p, %s, %f.\n", iface
, debugstr_guid(key
), value
);
1163 return IMFAttributes_SetDouble(node
->attributes
, key
, value
);
1166 static HRESULT WINAPI
topology_node_SetGUID(IMFTopologyNode
*iface
, REFGUID key
, REFGUID value
)
1168 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
1170 TRACE("%p, %s, %s.\n", iface
, debugstr_guid(key
), debugstr_guid(value
));
1172 return IMFAttributes_SetGUID(node
->attributes
, key
, value
);
1175 static HRESULT WINAPI
topology_node_SetString(IMFTopologyNode
*iface
, REFGUID key
, const WCHAR
*value
)
1177 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
1179 TRACE("%p, %s, %s.\n", iface
, debugstr_guid(key
), debugstr_w(value
));
1181 return IMFAttributes_SetString(node
->attributes
, key
, value
);
1184 static HRESULT WINAPI
topology_node_SetBlob(IMFTopologyNode
*iface
, REFGUID key
, const UINT8
*buf
, UINT32 size
)
1186 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
1188 TRACE("%p, %s, %p, %d.\n", iface
, debugstr_guid(key
), buf
, size
);
1190 return IMFAttributes_SetBlob(node
->attributes
, key
, buf
, size
);
1193 static HRESULT WINAPI
topology_node_SetUnknown(IMFTopologyNode
*iface
, REFGUID key
, IUnknown
*unknown
)
1195 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
1197 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), unknown
);
1199 return IMFAttributes_SetUnknown(node
->attributes
, key
, unknown
);
1202 static HRESULT WINAPI
topology_node_LockStore(IMFTopologyNode
*iface
)
1204 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
1206 TRACE("%p.\n", iface
);
1208 return IMFAttributes_LockStore(node
->attributes
);
1211 static HRESULT WINAPI
topology_node_UnlockStore(IMFTopologyNode
*iface
)
1213 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
1215 TRACE("%p.\n", iface
);
1217 return IMFAttributes_UnlockStore(node
->attributes
);
1220 static HRESULT WINAPI
topology_node_GetCount(IMFTopologyNode
*iface
, UINT32
*count
)
1222 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
1224 TRACE("%p, %p.\n", iface
, count
);
1226 return IMFAttributes_GetCount(node
->attributes
, count
);
1229 static HRESULT WINAPI
topology_node_GetItemByIndex(IMFTopologyNode
*iface
, UINT32 index
, GUID
*key
, PROPVARIANT
*value
)
1231 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
1233 TRACE("%p, %u, %p, %p.\n", iface
, index
, key
, value
);
1235 return IMFAttributes_GetItemByIndex(node
->attributes
, index
, key
, value
);
1238 static HRESULT WINAPI
topology_node_CopyAllItems(IMFTopologyNode
*iface
, IMFAttributes
*dest
)
1240 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
1242 TRACE("%p, %p.\n", iface
, dest
);
1244 return IMFAttributes_CopyAllItems(node
->attributes
, dest
);
1247 static HRESULT
topology_node_set_object(struct topology_node
*node
, IUnknown
*object
)
1249 static const GUID
*iids
[3] = { &IID_IPersist
, &IID_IPersistStorage
, &IID_IPersistPropertyBag
};
1250 IPersist
*persist
= NULL
;
1256 has_object_id
= IMFAttributes_GetGUID(node
->attributes
, &MF_TOPONODE_TRANSFORM_OBJECTID
, &object_id
) == S_OK
;
1258 if (object
&& !has_object_id
)
1260 for (i
= 0; i
< ARRAY_SIZE(iids
); ++i
)
1263 if (SUCCEEDED(hr
= IUnknown_QueryInterface(object
, iids
[i
], (void **)&persist
)))
1269 if (FAILED(hr
= IPersist_GetClassID(persist
, &object_id
)))
1271 IPersist_Release(persist
);
1277 EnterCriticalSection(&node
->cs
);
1280 IUnknown_Release(node
->object
);
1281 node
->object
= object
;
1283 IUnknown_AddRef(node
->object
);
1286 IMFAttributes_SetGUID(node
->attributes
, &MF_TOPONODE_TRANSFORM_OBJECTID
, &object_id
);
1288 LeaveCriticalSection(&node
->cs
);
1291 IPersist_Release(persist
);
1296 static HRESULT WINAPI
topology_node_SetObject(IMFTopologyNode
*iface
, IUnknown
*object
)
1298 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
1300 TRACE("%p, %p.\n", iface
, object
);
1302 return topology_node_set_object(node
, object
);
1305 static HRESULT WINAPI
topology_node_GetObject(IMFTopologyNode
*iface
, IUnknown
**object
)
1307 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
1309 TRACE("%p, %p.\n", iface
, object
);
1314 EnterCriticalSection(&node
->cs
);
1316 *object
= node
->object
;
1318 IUnknown_AddRef(*object
);
1320 LeaveCriticalSection(&node
->cs
);
1322 return *object
? S_OK
: E_FAIL
;
1325 static HRESULT WINAPI
topology_node_GetNodeType(IMFTopologyNode
*iface
, MF_TOPOLOGY_TYPE
*node_type
)
1327 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
1329 TRACE("%p, %p.\n", iface
, node_type
);
1331 *node_type
= node
->node_type
;
1336 static HRESULT WINAPI
topology_node_GetTopoNodeID(IMFTopologyNode
*iface
, TOPOID
*id
)
1338 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
1340 TRACE("%p, %p.\n", iface
, id
);
1347 static HRESULT WINAPI
topology_node_SetTopoNodeID(IMFTopologyNode
*iface
, TOPOID id
)
1349 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
1351 TRACE("%p, %s.\n", iface
, wine_dbgstr_longlong(id
));
1358 static HRESULT WINAPI
topology_node_GetInputCount(IMFTopologyNode
*iface
, DWORD
*count
)
1360 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
1362 TRACE("%p, %p.\n", iface
, count
);
1364 *count
= node
->inputs
.count
;
1369 static HRESULT WINAPI
topology_node_GetOutputCount(IMFTopologyNode
*iface
, DWORD
*count
)
1371 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
1373 TRACE("%p, %p.\n", iface
, count
);
1375 *count
= node
->outputs
.count
;
1380 static void topology_node_set_stream_type(struct node_stream
*stream
, IMFMediaType
*mediatype
)
1382 if (stream
->preferred_type
)
1383 IMFMediaType_Release(stream
->preferred_type
);
1384 stream
->preferred_type
= mediatype
;
1385 if (stream
->preferred_type
)
1386 IMFMediaType_AddRef(stream
->preferred_type
);
1389 static HRESULT
topology_node_connect_output(struct topology_node
*node
, DWORD output_index
,
1390 struct topology_node
*connection
, DWORD input_index
)
1392 struct node_stream
*stream
;
1395 if (node
->node_type
== MF_TOPOLOGY_OUTPUT_NODE
|| connection
->node_type
== MF_TOPOLOGY_SOURCESTREAM_NODE
)
1398 EnterCriticalSection(&node
->cs
);
1399 EnterCriticalSection(&connection
->cs
);
1401 topology_node_disconnect_output(node
, output_index
);
1402 if (input_index
< connection
->inputs
.count
)
1404 stream
= &connection
->inputs
.streams
[input_index
];
1405 if (stream
->connection
)
1406 topology_node_disconnect_output(stream
->connection
, stream
->connection_stream
);
1409 hr
= topology_node_reserve_streams(&node
->outputs
, output_index
);
1412 size_t old_count
= connection
->inputs
.count
;
1413 hr
= topology_node_reserve_streams(&connection
->inputs
, input_index
);
1414 if (SUCCEEDED(hr
) && !old_count
&& connection
->input_type
)
1416 topology_node_set_stream_type(connection
->inputs
.streams
, connection
->input_type
);
1417 IMFMediaType_Release(connection
->input_type
);
1418 connection
->input_type
= NULL
;
1424 node
->outputs
.streams
[output_index
].connection
= connection
;
1425 IMFTopologyNode_AddRef(&node
->outputs
.streams
[output_index
].connection
->IMFTopologyNode_iface
);
1426 node
->outputs
.streams
[output_index
].connection_stream
= input_index
;
1427 connection
->inputs
.streams
[input_index
].connection
= node
;
1428 IMFTopologyNode_AddRef(&connection
->inputs
.streams
[input_index
].connection
->IMFTopologyNode_iface
);
1429 connection
->inputs
.streams
[input_index
].connection_stream
= output_index
;
1432 LeaveCriticalSection(&connection
->cs
);
1433 LeaveCriticalSection(&node
->cs
);
1438 static HRESULT WINAPI
topology_node_ConnectOutput(IMFTopologyNode
*iface
, DWORD output_index
,
1439 IMFTopologyNode
*peer
, DWORD input_index
)
1441 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
1442 struct topology_node
*connection
= unsafe_impl_from_IMFTopologyNode(peer
);
1444 TRACE("%p, %lu, %p, %lu.\n", iface
, output_index
, peer
, input_index
);
1448 WARN("External node implementations are not supported.\n");
1449 return E_UNEXPECTED
;
1452 return topology_node_connect_output(node
, output_index
, connection
, input_index
);
1455 static HRESULT WINAPI
topology_node_DisconnectOutput(IMFTopologyNode
*iface
, DWORD output_index
)
1457 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
1459 TRACE("%p, %lu.\n", iface
, output_index
);
1461 return topology_node_disconnect_output(node
, output_index
);
1464 static HRESULT WINAPI
topology_node_GetInput(IMFTopologyNode
*iface
, DWORD input_index
, IMFTopologyNode
**ret
,
1465 DWORD
*output_index
)
1467 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
1470 TRACE("%p, %lu, %p, %p.\n", iface
, input_index
, ret
, output_index
);
1472 EnterCriticalSection(&node
->cs
);
1474 if (input_index
< node
->inputs
.count
)
1476 const struct node_stream
*stream
= &node
->inputs
.streams
[input_index
];
1478 if (stream
->connection
)
1480 *ret
= &stream
->connection
->IMFTopologyNode_iface
;
1481 IMFTopologyNode_AddRef(*ret
);
1482 *output_index
= stream
->connection_stream
;
1485 hr
= MF_E_NOT_FOUND
;
1490 LeaveCriticalSection(&node
->cs
);
1495 static HRESULT WINAPI
topology_node_GetOutput(IMFTopologyNode
*iface
, DWORD output_index
, IMFTopologyNode
**ret
,
1498 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
1501 TRACE("%p, %lu, %p, %p.\n", iface
, output_index
, ret
, input_index
);
1503 EnterCriticalSection(&node
->cs
);
1505 if (output_index
< node
->outputs
.count
)
1507 const struct node_stream
*stream
= &node
->outputs
.streams
[output_index
];
1509 if (stream
->connection
)
1511 *ret
= &stream
->connection
->IMFTopologyNode_iface
;
1512 IMFTopologyNode_AddRef(*ret
);
1513 *input_index
= stream
->connection_stream
;
1516 hr
= MF_E_NOT_FOUND
;
1521 LeaveCriticalSection(&node
->cs
);
1526 static HRESULT WINAPI
topology_node_SetOutputPrefType(IMFTopologyNode
*iface
, DWORD index
, IMFMediaType
*mediatype
)
1528 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
1531 TRACE("%p, %lu, %p.\n", iface
, index
, mediatype
);
1533 EnterCriticalSection(&node
->cs
);
1535 if (node
->node_type
!= MF_TOPOLOGY_OUTPUT_NODE
)
1537 if (SUCCEEDED(hr
= topology_node_reserve_streams(&node
->outputs
, index
)))
1538 topology_node_set_stream_type(&node
->outputs
.streams
[index
], mediatype
);
1543 LeaveCriticalSection(&node
->cs
);
1548 static HRESULT
topology_node_get_pref_type(struct node_streams
*streams
, unsigned int index
, IMFMediaType
**mediatype
)
1550 *mediatype
= streams
->streams
[index
].preferred_type
;
1553 IMFMediaType_AddRef(*mediatype
);
1560 static HRESULT WINAPI
topology_node_GetOutputPrefType(IMFTopologyNode
*iface
, DWORD index
, IMFMediaType
**mediatype
)
1562 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
1565 TRACE("%p, %lu, %p.\n", iface
, index
, mediatype
);
1567 EnterCriticalSection(&node
->cs
);
1569 if (index
< node
->outputs
.count
)
1570 hr
= topology_node_get_pref_type(&node
->outputs
, index
, mediatype
);
1574 LeaveCriticalSection(&node
->cs
);
1579 static HRESULT WINAPI
topology_node_SetInputPrefType(IMFTopologyNode
*iface
, DWORD index
, IMFMediaType
*mediatype
)
1581 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
1584 TRACE("%p, %lu, %p.\n", iface
, index
, mediatype
);
1586 EnterCriticalSection(&node
->cs
);
1588 switch (node
->node_type
)
1590 case MF_TOPOLOGY_TEE_NODE
:
1593 hr
= MF_E_INVALIDTYPE
;
1596 if (node
->inputs
.count
)
1597 topology_node_set_stream_type(&node
->inputs
.streams
[index
], mediatype
);
1600 if (node
->input_type
)
1601 IMFMediaType_Release(node
->input_type
);
1602 node
->input_type
= mediatype
;
1603 if (node
->input_type
)
1604 IMFMediaType_AddRef(node
->input_type
);
1607 case MF_TOPOLOGY_SOURCESTREAM_NODE
:
1611 if (SUCCEEDED(hr
= topology_node_reserve_streams(&node
->inputs
, index
)))
1612 topology_node_set_stream_type(&node
->inputs
.streams
[index
], mediatype
);
1615 LeaveCriticalSection(&node
->cs
);
1620 static HRESULT WINAPI
topology_node_GetInputPrefType(IMFTopologyNode
*iface
, DWORD index
, IMFMediaType
**mediatype
)
1622 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
1625 TRACE("%p, %lu, %p.\n", iface
, index
, mediatype
);
1627 EnterCriticalSection(&node
->cs
);
1629 if (index
< node
->inputs
.count
)
1631 hr
= topology_node_get_pref_type(&node
->inputs
, index
, mediatype
);
1633 else if (node
->node_type
== MF_TOPOLOGY_TEE_NODE
&& node
->input_type
)
1635 *mediatype
= node
->input_type
;
1636 IMFMediaType_AddRef(*mediatype
);
1641 LeaveCriticalSection(&node
->cs
);
1646 static HRESULT WINAPI
topology_node_CloneFrom(IMFTopologyNode
*iface
, IMFTopologyNode
*src_node
)
1648 struct topology_node
*node
= impl_from_IMFTopologyNode(iface
);
1649 MF_TOPOLOGY_TYPE node_type
;
1650 IMFMediaType
*mediatype
;
1656 TRACE("%p, %p.\n", iface
, src_node
);
1658 if (FAILED(hr
= IMFTopologyNode_GetNodeType(src_node
, &node_type
)))
1661 if (node
->node_type
!= node_type
)
1662 return MF_E_INVALIDREQUEST
;
1664 if (FAILED(hr
= IMFTopologyNode_GetTopoNodeID(src_node
, &topoid
)))
1668 IMFTopologyNode_GetObject(src_node
, &object
);
1670 EnterCriticalSection(&node
->cs
);
1672 hr
= IMFTopologyNode_CopyAllItems(src_node
, node
->attributes
);
1675 hr
= topology_node_set_object(node
, object
);
1680 if (SUCCEEDED(IMFTopologyNode_GetInputCount(src_node
, &count
)))
1682 for (i
= 0; i
< count
; ++i
)
1684 if (SUCCEEDED(IMFTopologyNode_GetInputPrefType(src_node
, i
, &mediatype
)))
1686 IMFTopologyNode_SetInputPrefType(iface
, i
, mediatype
);
1687 IMFMediaType_Release(mediatype
);
1692 if (SUCCEEDED(IMFTopologyNode_GetOutputCount(src_node
, &count
)))
1694 for (i
= 0; i
< count
; ++i
)
1696 if (SUCCEEDED(IMFTopologyNode_GetOutputPrefType(src_node
, i
, &mediatype
)))
1698 IMFTopologyNode_SetOutputPrefType(iface
, i
, mediatype
);
1699 IMFMediaType_Release(mediatype
);
1704 LeaveCriticalSection(&node
->cs
);
1707 IUnknown_Release(object
);
1712 static const IMFTopologyNodeVtbl topologynodevtbl
=
1714 topology_node_QueryInterface
,
1715 topology_node_AddRef
,
1716 topology_node_Release
,
1717 topology_node_GetItem
,
1718 topology_node_GetItemType
,
1719 topology_node_CompareItem
,
1720 topology_node_Compare
,
1721 topology_node_GetUINT32
,
1722 topology_node_GetUINT64
,
1723 topology_node_GetDouble
,
1724 topology_node_GetGUID
,
1725 topology_node_GetStringLength
,
1726 topology_node_GetString
,
1727 topology_node_GetAllocatedString
,
1728 topology_node_GetBlobSize
,
1729 topology_node_GetBlob
,
1730 topology_node_GetAllocatedBlob
,
1731 topology_node_GetUnknown
,
1732 topology_node_SetItem
,
1733 topology_node_DeleteItem
,
1734 topology_node_DeleteAllItems
,
1735 topology_node_SetUINT32
,
1736 topology_node_SetUINT64
,
1737 topology_node_SetDouble
,
1738 topology_node_SetGUID
,
1739 topology_node_SetString
,
1740 topology_node_SetBlob
,
1741 topology_node_SetUnknown
,
1742 topology_node_LockStore
,
1743 topology_node_UnlockStore
,
1744 topology_node_GetCount
,
1745 topology_node_GetItemByIndex
,
1746 topology_node_CopyAllItems
,
1747 topology_node_SetObject
,
1748 topology_node_GetObject
,
1749 topology_node_GetNodeType
,
1750 topology_node_GetTopoNodeID
,
1751 topology_node_SetTopoNodeID
,
1752 topology_node_GetInputCount
,
1753 topology_node_GetOutputCount
,
1754 topology_node_ConnectOutput
,
1755 topology_node_DisconnectOutput
,
1756 topology_node_GetInput
,
1757 topology_node_GetOutput
,
1758 topology_node_SetOutputPrefType
,
1759 topology_node_GetOutputPrefType
,
1760 topology_node_SetInputPrefType
,
1761 topology_node_GetInputPrefType
,
1762 topology_node_CloneFrom
,
1765 static HRESULT
create_topology_node(MF_TOPOLOGY_TYPE node_type
, struct topology_node
**node
)
1769 if (!(*node
= calloc(1, sizeof(**node
))))
1770 return E_OUTOFMEMORY
;
1772 (*node
)->IMFTopologyNode_iface
.lpVtbl
= &topologynodevtbl
;
1773 (*node
)->refcount
= 1;
1774 (*node
)->node_type
= node_type
;
1775 hr
= MFCreateAttributes(&(*node
)->attributes
, 0);
1781 (*node
)->id
= ((TOPOID
)GetCurrentProcessId() << 32) | InterlockedIncrement(&next_node_id
);
1782 InitializeCriticalSection(&(*node
)->cs
);
1787 HRESULT
topology_node_get_object(IMFTopologyNode
*node
, REFIID riid
, void **obj
)
1794 if (SUCCEEDED(hr
= IMFTopologyNode_GetObject(node
, &unk
)))
1796 hr
= IUnknown_QueryInterface(unk
, riid
, obj
);
1797 IUnknown_Release(unk
);
1803 /***********************************************************************
1804 * MFCreateTopologyNode (mf.@)
1806 HRESULT WINAPI
MFCreateTopologyNode(MF_TOPOLOGY_TYPE node_type
, IMFTopologyNode
**node
)
1808 struct topology_node
*object
;
1811 TRACE("%d, %p.\n", node_type
, node
);
1816 hr
= create_topology_node(node_type
, &object
);
1818 *node
= &object
->IMFTopologyNode_iface
;
1823 /***********************************************************************
1824 * MFGetTopoNodeCurrentType (mf.@)
1826 HRESULT WINAPI
MFGetTopoNodeCurrentType(IMFTopologyNode
*node
, DWORD stream
, BOOL output
, IMFMediaType
**type
)
1828 IMFMediaTypeHandler
*type_handler
;
1829 MF_TOPOLOGY_TYPE node_type
;
1830 IMFStreamSink
*stream_sink
;
1831 IMFStreamDescriptor
*sd
;
1832 IMFTransform
*transform
;
1833 UINT32 primary_output
;
1836 TRACE("%p, %lu, %d, %p.\n", node
, stream
, output
, type
);
1838 if (FAILED(hr
= IMFTopologyNode_GetNodeType(node
, &node_type
)))
1843 case MF_TOPOLOGY_OUTPUT_NODE
:
1844 if (SUCCEEDED(topology_node_get_object(node
, &IID_IMFStreamSink
, (void **)&stream_sink
)))
1846 hr
= IMFStreamSink_GetMediaTypeHandler(stream_sink
, &type_handler
);
1847 IMFStreamSink_Release(stream_sink
);
1851 hr
= IMFMediaTypeHandler_GetCurrentMediaType(type_handler
, type
);
1852 IMFMediaTypeHandler_Release(type_handler
);
1856 case MF_TOPOLOGY_SOURCESTREAM_NODE
:
1857 if (FAILED(hr
= IMFTopologyNode_GetUnknown(node
, &MF_TOPONODE_STREAM_DESCRIPTOR
, &IID_IMFStreamDescriptor
,
1863 hr
= IMFStreamDescriptor_GetMediaTypeHandler(sd
, &type_handler
);
1864 IMFStreamDescriptor_Release(sd
);
1867 hr
= IMFMediaTypeHandler_GetCurrentMediaType(type_handler
, type
);
1868 IMFMediaTypeHandler_Release(type_handler
);
1871 case MF_TOPOLOGY_TRANSFORM_NODE
:
1872 if (SUCCEEDED(hr
= topology_node_get_object(node
, &IID_IMFTransform
, (void **)&transform
)))
1875 hr
= IMFTransform_GetOutputCurrentType(transform
, stream
, type
);
1877 hr
= IMFTransform_GetInputCurrentType(transform
, stream
, type
);
1878 IMFTransform_Release(transform
);
1881 case MF_TOPOLOGY_TEE_NODE
:
1882 if (SUCCEEDED(hr
= IMFTopologyNode_GetInputPrefType(node
, 0, type
)))
1885 if (FAILED(IMFTopologyNode_GetUINT32(node
, &MF_TOPONODE_PRIMARYOUTPUT
, &primary_output
)))
1888 hr
= IMFTopologyNode_GetOutputPrefType(node
, primary_output
, type
);
1897 static HRESULT WINAPI
topology_loader_QueryInterface(IMFTopoLoader
*iface
, REFIID riid
, void **out
)
1899 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), out
);
1901 if (IsEqualIID(riid
, &IID_IMFTopoLoader
) ||
1902 IsEqualIID(riid
, &IID_IUnknown
))
1905 IMFTopoLoader_AddRef(iface
);
1909 WARN("Unsupported %s.\n", debugstr_guid(riid
));
1911 return E_NOINTERFACE
;
1914 static ULONG WINAPI
topology_loader_AddRef(IMFTopoLoader
*iface
)
1916 struct topology_loader
*loader
= impl_from_IMFTopoLoader(iface
);
1917 ULONG refcount
= InterlockedIncrement(&loader
->refcount
);
1919 TRACE("%p, refcount %lu.\n", iface
, refcount
);
1924 static ULONG WINAPI
topology_loader_Release(IMFTopoLoader
*iface
)
1926 struct topology_loader
*loader
= impl_from_IMFTopoLoader(iface
);
1927 ULONG refcount
= InterlockedDecrement(&loader
->refcount
);
1929 TRACE("%p, refcount %lu.\n", iface
, refcount
);
1937 struct topoloader_context
1939 IMFTopology
*input_topology
;
1940 IMFTopology
*output_topology
;
1941 unsigned int marker
;
1945 static IMFTopologyNode
*topology_loader_get_node_for_marker(struct topoloader_context
*context
, TOPOID
*id
)
1947 IMFTopologyNode
*node
;
1948 unsigned short i
= 0;
1951 while (SUCCEEDED(IMFTopology_GetNode(context
->output_topology
, i
++, &node
)))
1953 if (SUCCEEDED(IMFTopologyNode_GetUINT32(node
, &context
->key
, &value
)) && value
== context
->marker
)
1955 IMFTopologyNode_GetTopoNodeID(node
, id
);
1958 IMFTopologyNode_Release(node
);
1965 static HRESULT
topology_loader_clone_node(struct topoloader_context
*context
, IMFTopologyNode
*node
,
1966 IMFTopologyNode
**ret
, unsigned int marker
)
1968 IMFTopologyNode
*cloned_node
;
1969 MF_TOPOLOGY_TYPE node_type
;
1972 if (ret
) *ret
= NULL
;
1974 IMFTopologyNode_GetNodeType(node
, &node_type
);
1976 if (FAILED(hr
= MFCreateTopologyNode(node_type
, &cloned_node
)))
1979 if (SUCCEEDED(hr
= IMFTopologyNode_CloneFrom(cloned_node
, node
)))
1980 hr
= IMFTopologyNode_SetUINT32(cloned_node
, &context
->key
, marker
);
1983 hr
= IMFTopology_AddNode(context
->output_topology
, cloned_node
);
1985 if (SUCCEEDED(hr
) && ret
)
1988 IMFTopologyNode_AddRef(*ret
);
1991 IMFTopologyNode_Release(cloned_node
);
1996 struct transform_output_type
1999 IMFTransform
*transform
;
2000 IMFActivate
*activate
;
2003 struct connect_context
2005 struct topoloader_context
*context
;
2006 IMFTopologyNode
*upstream_node
;
2007 IMFTopologyNode
*sink
;
2008 IMFMediaTypeHandler
*sink_handler
;
2009 unsigned int output_index
;
2010 unsigned int input_index
;
2011 GUID converter_category
;
2012 GUID decoder_category
;
2015 typedef HRESULT (*p_connect_func
)(struct transform_output_type
*output_type
, struct connect_context
*context
);
2017 static void topology_loader_release_transforms(IMFActivate
**activates
, unsigned int count
)
2021 for (i
= 0; i
< count
; ++i
)
2022 IMFActivate_Release(activates
[i
]);
2023 CoTaskMemFree(activates
);
2026 static HRESULT
topology_loader_enumerate_output_types(const GUID
*category
, IMFMediaType
*input_type
,
2027 p_connect_func connect_func
, struct connect_context
*context
)
2029 MFT_REGISTER_TYPE_INFO mft_typeinfo
;
2030 IMFActivate
**activates
;
2031 unsigned int i
, count
;
2034 if (FAILED(hr
= IMFMediaType_GetMajorType(input_type
, &mft_typeinfo
.guidMajorType
)))
2037 if (FAILED(hr
= IMFMediaType_GetGUID(input_type
, &MF_MT_SUBTYPE
, &mft_typeinfo
.guidSubtype
)))
2040 if (FAILED(hr
= MFTEnumEx(*category
, MFT_ENUM_FLAG_ALL
, &mft_typeinfo
, NULL
, &activates
, &count
)))
2045 for (i
= 0; i
< count
; ++i
)
2047 IMFTransform
*transform
;
2049 if (FAILED(IMFActivate_ActivateObject(activates
[i
], &IID_IMFTransform
, (void **)&transform
)))
2051 WARN("Failed to create a transform.\n");
2055 if (SUCCEEDED(hr
= IMFTransform_SetInputType(transform
, 0, input_type
, 0)))
2057 struct transform_output_type output_type
;
2058 unsigned int output_count
= 0;
2060 output_type
.transform
= transform
;
2061 output_type
.activate
= activates
[i
];
2062 while (SUCCEEDED(IMFTransform_GetOutputAvailableType(transform
, 0, output_count
++, &output_type
.type
)))
2064 hr
= connect_func(&output_type
, context
);
2065 IMFMediaType_Release(output_type
.type
);
2068 topology_loader_release_transforms(activates
, count
);
2074 IMFActivate_ShutdownObject(activates
[i
]);
2077 topology_loader_release_transforms(activates
, count
);
2082 static HRESULT
topology_loader_create_transform(const struct transform_output_type
*output_type
,
2083 IMFTopologyNode
**node
)
2088 if (FAILED(hr
= MFCreateTopologyNode(MF_TOPOLOGY_TRANSFORM_NODE
, node
)))
2091 IMFTopologyNode_SetObject(*node
, (IUnknown
*)output_type
->transform
);
2093 if (SUCCEEDED(IMFActivate_GetGUID(output_type
->activate
, &MF_TRANSFORM_CATEGORY_Attribute
, &guid
)) &&
2094 (IsEqualGUID(&guid
, &MFT_CATEGORY_AUDIO_DECODER
) || IsEqualGUID(&guid
, &MFT_CATEGORY_VIDEO_DECODER
)))
2096 IMFTopologyNode_SetUINT32(*node
, &MF_TOPONODE_DECODER
, 1);
2099 if (SUCCEEDED(IMFActivate_GetGUID(output_type
->activate
, &MFT_TRANSFORM_CLSID_Attribute
, &guid
)))
2100 IMFTopologyNode_SetGUID(*node
, &MF_TOPONODE_TRANSFORM_OBJECTID
, &guid
);
2105 static HRESULT
connect_to_sink(struct transform_output_type
*output_type
, struct connect_context
*context
)
2107 IMFTopologyNode
*node
;
2110 if (FAILED(IMFMediaTypeHandler_IsMediaTypeSupported(context
->sink_handler
, output_type
->type
, NULL
)))
2111 return MF_E_TRANSFORM_NOT_POSSIBLE_FOR_CURRENT_MEDIATYPE_COMBINATION
;
2113 if (FAILED(hr
= topology_loader_create_transform(output_type
, &node
)))
2116 IMFTopology_AddNode(context
->context
->output_topology
, node
);
2117 IMFTopologyNode_ConnectOutput(context
->upstream_node
, 0, node
, 0);
2118 IMFTopologyNode_ConnectOutput(node
, 0, context
->sink
, 0);
2120 IMFTopologyNode_Release(node
);
2122 hr
= IMFMediaTypeHandler_SetCurrentMediaType(context
->sink_handler
, output_type
->type
);
2124 hr
= IMFTransform_SetOutputType(output_type
->transform
, 0, output_type
->type
, 0);
2129 static HRESULT
connect_to_converter(struct transform_output_type
*output_type
, struct connect_context
*context
)
2131 struct connect_context sink_ctx
;
2132 IMFTopologyNode
*node
;
2135 if (SUCCEEDED(connect_to_sink(output_type
, context
)))
2138 if (FAILED(hr
= topology_loader_create_transform(output_type
, &node
)))
2141 sink_ctx
= *context
;
2142 sink_ctx
.upstream_node
= node
;
2144 if (SUCCEEDED(hr
= topology_loader_enumerate_output_types(&context
->converter_category
, output_type
->type
,
2145 connect_to_sink
, &sink_ctx
)))
2147 hr
= IMFTopology_AddNode(context
->context
->output_topology
, node
);
2149 IMFTopologyNode_Release(node
);
2153 IMFTopology_AddNode(context
->context
->output_topology
, node
);
2154 IMFTopologyNode_ConnectOutput(context
->upstream_node
, 0, node
, 0);
2156 hr
= IMFTransform_SetOutputType(output_type
->transform
, 0, output_type
->type
, 0);
2162 typedef HRESULT (*p_topology_loader_connect_func
)(struct topoloader_context
*context
, IMFTopologyNode
*upstream_node
,
2163 unsigned int output_index
, IMFTopologyNode
*downstream_node
, unsigned int input_index
);
2165 static HRESULT
topology_loader_get_node_type_handler(IMFTopologyNode
*node
, IMFMediaTypeHandler
**handler
)
2167 MF_TOPOLOGY_TYPE node_type
;
2168 IMFStreamSink
*stream_sink
;
2169 IMFStreamDescriptor
*sd
;
2172 if (FAILED(hr
= IMFTopologyNode_GetNodeType(node
, &node_type
)))
2177 case MF_TOPOLOGY_OUTPUT_NODE
:
2178 if (SUCCEEDED(hr
= topology_node_get_object(node
, &IID_IMFStreamSink
, (void **)&stream_sink
)))
2180 hr
= IMFStreamSink_GetMediaTypeHandler(stream_sink
, handler
);
2181 IMFStreamSink_Release(stream_sink
);
2184 case MF_TOPOLOGY_SOURCESTREAM_NODE
:
2185 if (SUCCEEDED(hr
= IMFTopologyNode_GetUnknown(node
, &MF_TOPONODE_STREAM_DESCRIPTOR
,
2186 &IID_IMFStreamDescriptor
, (void **)&sd
)))
2188 hr
= IMFStreamDescriptor_GetMediaTypeHandler(sd
, handler
);
2189 IMFStreamDescriptor_Release(sd
);
2193 WARN("Unexpected node type %u.\n", node_type
);
2194 return MF_E_UNEXPECTED
;
2200 static HRESULT
topology_loader_get_mft_categories(IMFMediaTypeHandler
*handler
, GUID
*decode_cat
, GUID
*convert_cat
)
2205 if (FAILED(hr
= IMFMediaTypeHandler_GetMajorType(handler
, &major
)))
2208 if (IsEqualGUID(&major
, &MFMediaType_Audio
))
2210 *decode_cat
= MFT_CATEGORY_AUDIO_DECODER
;
2211 *convert_cat
= MFT_CATEGORY_AUDIO_EFFECT
;
2213 else if (IsEqualGUID(&major
, &MFMediaType_Video
))
2215 *decode_cat
= MFT_CATEGORY_VIDEO_DECODER
;
2216 *convert_cat
= MFT_CATEGORY_VIDEO_EFFECT
;
2220 WARN("Unexpected major type %s.\n", debugstr_guid(&major
));
2221 return MF_E_INVALIDTYPE
;
2227 static HRESULT
topology_loader_connect(IMFMediaTypeHandler
*sink_handler
, unsigned int sink_method
,
2228 struct connect_context
*sink_ctx
, struct connect_context
*convert_ctx
, IMFMediaType
*media_type
)
2232 if (SUCCEEDED(hr
= IMFMediaTypeHandler_IsMediaTypeSupported(sink_handler
, media_type
, NULL
))
2233 && SUCCEEDED(hr
= IMFMediaTypeHandler_SetCurrentMediaType(sink_handler
, media_type
)))
2235 hr
= IMFTopologyNode_ConnectOutput(sink_ctx
->upstream_node
, sink_ctx
->output_index
, sink_ctx
->sink
, sink_ctx
->input_index
);
2238 if (FAILED(hr
) && sink_method
& MF_CONNECT_ALLOW_CONVERTER
)
2240 hr
= topology_loader_enumerate_output_types(&convert_ctx
->converter_category
, media_type
, connect_to_sink
, sink_ctx
);
2243 if (FAILED(hr
) && sink_method
& MF_CONNECT_ALLOW_DECODER
)
2245 hr
= topology_loader_enumerate_output_types(&convert_ctx
->decoder_category
, media_type
,
2246 connect_to_converter
, convert_ctx
);
2252 static HRESULT
topology_loader_foreach_source_type(IMFMediaTypeHandler
*sink_handler
, IMFMediaTypeHandler
*source_handler
,
2253 unsigned int sink_method
, struct connect_context
*sink_ctx
, struct connect_context
*convert_ctx
)
2255 unsigned int index
= 0;
2256 IMFMediaType
*media_type
;
2259 while (SUCCEEDED(hr
= IMFMediaTypeHandler_GetMediaTypeByIndex(source_handler
, index
++, &media_type
)))
2261 hr
= topology_loader_connect(sink_handler
, sink_method
, sink_ctx
, convert_ctx
, media_type
);
2262 if (SUCCEEDED(hr
)) break;
2263 IMFMediaType_Release(media_type
);
2269 hr
= IMFMediaTypeHandler_SetCurrentMediaType(source_handler
, media_type
);
2270 IMFMediaType_Release(media_type
);
2276 static HRESULT
topology_loader_connect_source_to_sink(struct topoloader_context
*context
, IMFTopologyNode
*source
,
2277 unsigned int output_index
, IMFTopologyNode
*sink
, unsigned int input_index
)
2279 IMFMediaTypeHandler
*source_handler
= NULL
, *sink_handler
= NULL
;
2280 struct connect_context convert_ctx
, sink_ctx
;
2281 MF_CONNECT_METHOD source_method
, sink_method
;
2282 unsigned int enumerate_source_types
= 0;
2283 IMFMediaType
*media_type
;
2286 TRACE("attempting to connect %p:%u to %p:%u\n", source
, output_index
, sink
, input_index
);
2288 if (FAILED(hr
= topology_loader_get_node_type_handler(source
, &source_handler
)))
2291 if (FAILED(hr
= topology_loader_get_node_type_handler(sink
, &sink_handler
)))
2294 if (FAILED(IMFTopologyNode_GetUINT32(source
, &MF_TOPONODE_CONNECT_METHOD
, &source_method
)))
2295 source_method
= MF_CONNECT_DIRECT
;
2296 if (FAILED(IMFTopologyNode_GetUINT32(sink
, &MF_TOPONODE_CONNECT_METHOD
, &sink_method
)))
2297 sink_method
= MF_CONNECT_ALLOW_DECODER
;
2299 sink_ctx
.context
= context
;
2300 sink_ctx
.upstream_node
= source
;
2301 sink_ctx
.sink
= sink
;
2302 sink_ctx
.sink_handler
= sink_handler
;
2303 sink_ctx
.output_index
= output_index
;
2304 sink_ctx
.input_index
= input_index
;
2306 convert_ctx
= sink_ctx
;
2307 if (FAILED(hr
= topology_loader_get_mft_categories(source_handler
, &convert_ctx
.decoder_category
,
2308 &convert_ctx
.converter_category
)))
2311 IMFTopology_GetUINT32(context
->output_topology
, &MF_TOPOLOGY_ENUMERATE_SOURCE_TYPES
, &enumerate_source_types
);
2313 if (enumerate_source_types
)
2315 if (source_method
& MF_CONNECT_RESOLVE_INDEPENDENT_OUTPUTTYPES
)
2317 hr
= topology_loader_foreach_source_type(sink_handler
, source_handler
, MF_CONNECT_ALLOW_DECODER
,
2318 &sink_ctx
, &convert_ctx
);
2322 hr
= topology_loader_foreach_source_type(sink_handler
, source_handler
, MF_CONNECT_DIRECT
,
2323 &sink_ctx
, &convert_ctx
);
2325 hr
= topology_loader_foreach_source_type(sink_handler
, source_handler
, MF_CONNECT_ALLOW_CONVERTER
,
2326 &sink_ctx
, &convert_ctx
);
2328 hr
= topology_loader_foreach_source_type(sink_handler
, source_handler
, MF_CONNECT_ALLOW_DECODER
,
2329 &sink_ctx
, &convert_ctx
);
2334 if (SUCCEEDED(hr
= IMFMediaTypeHandler_GetCurrentMediaType(source_handler
, &media_type
)))
2336 hr
= topology_loader_connect(sink_handler
, sink_method
, &sink_ctx
, &convert_ctx
, media_type
);
2337 IMFMediaType_Release(media_type
);
2343 IMFMediaTypeHandler_Release(source_handler
);
2345 IMFMediaTypeHandler_Release(sink_handler
);
2350 static HRESULT
topology_loader_resolve_branch(struct topoloader_context
*context
, IMFTopologyNode
*upstream_node
,
2351 unsigned int output_index
, IMFTopologyNode
*downstream_node
, unsigned input_index
)
2353 static const p_topology_loader_connect_func connectors
[MF_TOPOLOGY_TEE_NODE
+1][MF_TOPOLOGY_TEE_NODE
+1] =
2355 /* OUTPUT */ { NULL
},
2356 /* SOURCESTREAM */ { topology_loader_connect_source_to_sink
, NULL
, NULL
, NULL
},
2357 /* TRANSFORM */ { NULL
},
2360 MF_TOPOLOGY_TYPE u_type
, d_type
;
2361 IMFTopologyNode
*node
;
2365 /* Downstream node might have already been cloned. */
2366 IMFTopologyNode_GetTopoNodeID(downstream_node
, &id
);
2367 if (FAILED(IMFTopology_GetNodeByID(context
->output_topology
, id
, &node
)))
2368 topology_loader_clone_node(context
, downstream_node
, &node
, context
->marker
+ 1);
2370 IMFTopologyNode_GetNodeType(upstream_node
, &u_type
);
2371 IMFTopologyNode_GetNodeType(downstream_node
, &d_type
);
2373 if (!connectors
[u_type
][d_type
])
2375 WARN("Unsupported branch kind %d -> %d.\n", u_type
, d_type
);
2376 IMFTopologyNode_Release(node
);
2380 hr
= connectors
[u_type
][d_type
](context
, upstream_node
, output_index
, node
, input_index
);
2381 IMFTopologyNode_Release(node
);
2385 static HRESULT
topology_loader_resolve_nodes(struct topoloader_context
*context
, unsigned int *layer_size
)
2387 IMFTopologyNode
*downstream_node
, *node
, *orig_node
;
2388 MF_TOPOLOGY_TYPE node_type
;
2389 unsigned int size
= 0;
2394 while ((node
= topology_loader_get_node_for_marker(context
, &id
)))
2398 IMFTopologyNode_GetNodeType(node
, &node_type
);
2401 case MF_TOPOLOGY_SOURCESTREAM_NODE
:
2402 if (SUCCEEDED(hr
= IMFTopology_GetNodeByID(context
->input_topology
, id
, &orig_node
)))
2404 hr
= IMFTopologyNode_GetOutput(orig_node
, 0, &downstream_node
, &input_index
);
2405 IMFTopologyNode_Release(orig_node
);
2410 IMFTopology_RemoveNode(context
->output_topology
, node
);
2411 IMFTopologyNode_Release(node
);
2415 hr
= topology_loader_resolve_branch(context
, node
, 0, downstream_node
, input_index
);
2416 IMFTopologyNode_Release(downstream_node
);
2418 case MF_TOPOLOGY_TRANSFORM_NODE
:
2419 case MF_TOPOLOGY_TEE_NODE
:
2420 FIXME("Unsupported node type %d.\n", node_type
);
2423 WARN("Unexpected node type %d.\n", node_type
);
2426 IMFTopologyNode_DeleteItem(node
, &context
->key
);
2427 IMFTopologyNode_Release(node
);
2438 static BOOL
topology_loader_is_node_d3d_aware(IMFTopologyNode
*node
)
2440 IMFAttributes
*attributes
;
2441 unsigned int d3d_aware
= 0;
2442 IMFTransform
*transform
;
2444 if (FAILED(topology_node_get_object(node
, &IID_IMFAttributes
, (void **)&attributes
)))
2447 IMFAttributes_GetUINT32(attributes
, &MF_SA_D3D_AWARE
, &d3d_aware
);
2448 IMFAttributes_Release(attributes
);
2450 if (!d3d_aware
&& SUCCEEDED(topology_node_get_object(node
, &IID_IMFTransform
, (void **)&transform
)))
2452 d3d_aware
= mf_is_sample_copier_transform(transform
);
2453 IMFTransform_Release(transform
);
2459 static HRESULT
topology_loader_create_copier(IMFTopologyNode
*upstream_node
, DWORD upstream_output
,
2460 IMFTopologyNode
*downstream_node
, unsigned int downstream_input
, IMFTransform
**copier
)
2462 IMFMediaType
*input_type
= NULL
, *output_type
= NULL
;
2463 IMFTransform
*transform
;
2466 if (FAILED(hr
= MFCreateSampleCopierMFT(&transform
)))
2469 if (FAILED(hr
= MFGetTopoNodeCurrentType(upstream_node
, upstream_output
, TRUE
, &input_type
)))
2470 WARN("Failed to get upstream media type hr %#lx.\n", hr
);
2472 if (SUCCEEDED(hr
) && FAILED(hr
= MFGetTopoNodeCurrentType(downstream_node
, downstream_input
, FALSE
, &output_type
)))
2473 WARN("Failed to get downstream media type hr %#lx.\n", hr
);
2475 if (SUCCEEDED(hr
) && FAILED(hr
= IMFTransform_SetInputType(transform
, 0, input_type
, 0)))
2476 WARN("Input type wasn't accepted, hr %#lx.\n", hr
);
2478 if (SUCCEEDED(hr
) && FAILED(hr
= IMFTransform_SetOutputType(transform
, 0, output_type
, 0)))
2479 WARN("Output type wasn't accepted, hr %#lx.\n", hr
);
2483 *copier
= transform
;
2484 IMFTransform_AddRef(*copier
);
2488 IMFMediaType_Release(input_type
);
2490 IMFMediaType_Release(output_type
);
2492 IMFTransform_Release(transform
);
2497 static HRESULT
topology_loader_connect_copier(struct topoloader_context
*context
, IMFTopologyNode
*upstream_node
,
2498 DWORD upstream_output
, IMFTopologyNode
*downstream_node
, DWORD downstream_input
, IMFTransform
*copier
)
2500 IMFTopologyNode
*copier_node
;
2503 if (FAILED(hr
= MFCreateTopologyNode(MF_TOPOLOGY_TRANSFORM_NODE
, &copier_node
)))
2506 IMFTopologyNode_SetObject(copier_node
, (IUnknown
*)copier
);
2507 IMFTopology_AddNode(context
->output_topology
, copier_node
);
2508 IMFTopologyNode_ConnectOutput(upstream_node
, upstream_output
, copier_node
, 0);
2509 IMFTopologyNode_ConnectOutput(copier_node
, 0, downstream_node
, downstream_input
);
2511 IMFTopologyNode_Release(copier_node
);
2516 /* Right now this should be used for output nodes only. */
2517 static HRESULT
topology_loader_connect_d3d_aware_input(struct topoloader_context
*context
,
2518 IMFTopologyNode
*node
)
2520 IMFTopologyNode
*upstream_node
;
2521 IMFTransform
*copier
= NULL
;
2522 IMFStreamSink
*stream_sink
;
2523 DWORD upstream_output
;
2526 if (FAILED(hr
= topology_node_get_object(node
, &IID_IMFStreamSink
, (void **)&stream_sink
)))
2529 if (topology_loader_is_node_d3d_aware(node
))
2531 if (SUCCEEDED(IMFTopologyNode_GetInput(node
, 0, &upstream_node
, &upstream_output
)))
2533 if (!topology_loader_is_node_d3d_aware(upstream_node
))
2535 if (SUCCEEDED(hr
= topology_loader_create_copier(upstream_node
, upstream_output
, node
, 0, &copier
)))
2537 hr
= topology_loader_connect_copier(context
, upstream_node
, upstream_output
, node
, 0, copier
);
2538 IMFTransform_Release(copier
);
2541 IMFTopologyNode_Release(upstream_node
);
2545 IMFStreamSink_Release(stream_sink
);
2550 static void topology_loader_resolve_complete(struct topoloader_context
*context
)
2552 MF_TOPOLOGY_TYPE node_type
;
2553 IMFTopologyNode
*node
;
2557 IMFTopology_GetNodeCount(context
->output_topology
, &node_count
);
2559 for (i
= 0; i
< node_count
; ++i
)
2561 if (SUCCEEDED(IMFTopology_GetNode(context
->output_topology
, i
, &node
)))
2563 IMFTopologyNode_GetNodeType(node
, &node_type
);
2565 if (node_type
== MF_TOPOLOGY_OUTPUT_NODE
)
2567 /* Set MF_TOPONODE_STREAMID for all outputs. */
2568 if (FAILED(IMFTopologyNode_GetItem(node
, &MF_TOPONODE_STREAMID
, NULL
)))
2569 IMFTopologyNode_SetUINT32(node
, &MF_TOPONODE_STREAMID
, 0);
2571 if (FAILED(hr
= topology_loader_connect_d3d_aware_input(context
, node
)))
2572 WARN("Failed to connect D3D-aware input, hr %#lx.\n", hr
);
2574 else if (node_type
== MF_TOPOLOGY_SOURCESTREAM_NODE
)
2576 /* Set MF_TOPONODE_MEDIASTART for all sources. */
2577 if (FAILED(IMFTopologyNode_GetItem(node
, &MF_TOPONODE_MEDIASTART
, NULL
)))
2578 IMFTopologyNode_SetUINT64(node
, &MF_TOPONODE_MEDIASTART
, 0);
2581 IMFTopologyNode_Release(node
);
2586 static HRESULT WINAPI
topology_loader_Load(IMFTopoLoader
*iface
, IMFTopology
*input_topology
,
2587 IMFTopology
**ret_topology
, IMFTopology
*current_topology
)
2589 struct topoloader_context context
= { 0 };
2590 IMFTopology
*output_topology
;
2591 MF_TOPOLOGY_TYPE node_type
;
2592 unsigned int layer_size
;
2593 IMFTopologyNode
*node
;
2594 unsigned short i
= 0;
2595 IMFStreamSink
*sink
;
2597 HRESULT hr
= E_FAIL
;
2599 FIXME("%p, %p, %p, %p.\n", iface
, input_topology
, ret_topology
, current_topology
);
2601 if (current_topology
)
2602 FIXME("Current topology instance is ignored.\n");
2604 /* Basic sanity checks for input topology:
2606 - source nodes must have stream descriptor set;
2607 - sink nodes must be resolved to stream sink objects;
2609 while (SUCCEEDED(IMFTopology_GetNode(input_topology
, i
++, &node
)))
2611 IMFTopologyNode_GetNodeType(node
, &node_type
);
2615 case MF_TOPOLOGY_OUTPUT_NODE
:
2616 if (SUCCEEDED(hr
= IMFTopologyNode_GetObject(node
, &object
)))
2618 /* Sinks must be bound beforehand. */
2619 if (FAILED(IUnknown_QueryInterface(object
, &IID_IMFStreamSink
, (void **)&sink
)))
2620 hr
= MF_E_TOPO_SINK_ACTIVATES_UNSUPPORTED
;
2622 IMFStreamSink_Release(sink
);
2623 IUnknown_Release(object
);
2626 case MF_TOPOLOGY_SOURCESTREAM_NODE
:
2627 hr
= IMFTopologyNode_GetItem(node
, &MF_TOPONODE_STREAM_DESCRIPTOR
, NULL
);
2633 IMFTopologyNode_Release(node
);
2638 if (FAILED(hr
= MFCreateTopology(&output_topology
)))
2641 IMFTopology_CopyAllItems(input_topology
, (IMFAttributes
*)output_topology
);
2643 context
.input_topology
= input_topology
;
2644 context
.output_topology
= output_topology
;
2645 memset(&context
.key
, 0xff, sizeof(context
.key
));
2647 /* Clone source nodes, use initial marker value. */
2649 while (SUCCEEDED(IMFTopology_GetNode(input_topology
, i
++, &node
)))
2651 IMFTopologyNode_GetNodeType(node
, &node_type
);
2653 if (node_type
== MF_TOPOLOGY_SOURCESTREAM_NODE
)
2655 if (FAILED(hr
= topology_loader_clone_node(&context
, node
, NULL
, 0)))
2656 WARN("Failed to clone source node, hr %#lx.\n", hr
);
2659 IMFTopologyNode_Release(node
);
2662 for (context
.marker
= 0;; ++context
.marker
)
2664 if (FAILED(hr
= topology_loader_resolve_nodes(&context
, &layer_size
)))
2666 WARN("Failed to resolve for marker %u, hr %#lx.\n", context
.marker
, hr
);
2670 /* Reached last marker value. */
2676 IMFTopology_Release(output_topology
);
2679 topology_loader_resolve_complete(&context
);
2680 *ret_topology
= output_topology
;
2686 static const IMFTopoLoaderVtbl topologyloadervtbl
=
2688 topology_loader_QueryInterface
,
2689 topology_loader_AddRef
,
2690 topology_loader_Release
,
2691 topology_loader_Load
,
2694 /***********************************************************************
2695 * MFCreateTopoLoader (mf.@)
2697 HRESULT WINAPI
MFCreateTopoLoader(IMFTopoLoader
**loader
)
2699 struct topology_loader
*object
;
2701 TRACE("%p.\n", loader
);
2706 if (!(object
= calloc(1, sizeof(*object
))))
2707 return E_OUTOFMEMORY
;
2709 object
->IMFTopoLoader_iface
.lpVtbl
= &topologyloadervtbl
;
2710 object
->refcount
= 1;
2712 *loader
= &object
->IMFTopoLoader_iface
;
2717 static HRESULT WINAPI
seq_source_QueryInterface(IMFSequencerSource
*iface
, REFIID riid
, void **out
)
2719 struct seq_source
*seq_source
= impl_from_IMFSequencerSource(iface
);
2721 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), out
);
2725 if (IsEqualIID(riid
, &IID_IMFSequencerSource
) ||
2726 IsEqualIID(riid
, &IID_IUnknown
))
2728 *out
= &seq_source
->IMFSequencerSource_iface
;
2730 else if (IsEqualIID(riid
, &IID_IMFMediaSourceTopologyProvider
))
2732 *out
= &seq_source
->IMFMediaSourceTopologyProvider_iface
;
2736 WARN("Unimplemented %s.\n", debugstr_guid(riid
));
2737 return E_NOINTERFACE
;
2741 IUnknown_AddRef((IUnknown
*)*out
);
2746 static ULONG WINAPI
seq_source_AddRef(IMFSequencerSource
*iface
)
2748 struct seq_source
*seq_source
= impl_from_IMFSequencerSource(iface
);
2749 ULONG refcount
= InterlockedIncrement(&seq_source
->refcount
);
2751 TRACE("%p, refcount %lu.\n", iface
, refcount
);
2756 static ULONG WINAPI
seq_source_Release(IMFSequencerSource
*iface
)
2758 struct seq_source
*seq_source
= impl_from_IMFSequencerSource(iface
);
2759 ULONG refcount
= InterlockedDecrement(&seq_source
->refcount
);
2761 TRACE("%p, refcount %lu.\n", iface
, refcount
);
2769 static HRESULT WINAPI
seq_source_AppendTopology(IMFSequencerSource
*iface
, IMFTopology
*topology
,
2770 DWORD flags
, MFSequencerElementId
*id
)
2772 FIXME("%p, %p, %lx, %p.\n", iface
, topology
, flags
, id
);
2777 static HRESULT WINAPI
seq_source_DeleteTopology(IMFSequencerSource
*iface
, MFSequencerElementId id
)
2779 FIXME("%p, %#lx.\n", iface
, id
);
2784 static HRESULT WINAPI
seq_source_GetPresentationContext(IMFSequencerSource
*iface
,
2785 IMFPresentationDescriptor
*descriptor
, MFSequencerElementId
*id
, IMFTopology
**topology
)
2787 FIXME("%p, %p, %p, %p.\n", iface
, descriptor
, id
, topology
);
2792 static HRESULT WINAPI
seq_source_UpdateTopology(IMFSequencerSource
*iface
, MFSequencerElementId id
,
2793 IMFTopology
*topology
)
2795 FIXME("%p, %#lx, %p.\n", iface
, id
, topology
);
2800 static HRESULT WINAPI
seq_source_UpdateTopologyFlags(IMFSequencerSource
*iface
, MFSequencerElementId id
, DWORD flags
)
2802 FIXME("%p, %#lx, %#lx.\n", iface
, id
, flags
);
2807 static HRESULT WINAPI
seq_source_topology_provider_QueryInterface(IMFMediaSourceTopologyProvider
*iface
, REFIID riid
,
2810 struct seq_source
*seq_source
= impl_from_IMFMediaSourceTopologyProvider(iface
);
2811 return IMFSequencerSource_QueryInterface(&seq_source
->IMFSequencerSource_iface
, riid
, obj
);
2814 static ULONG WINAPI
seq_source_topology_provider_AddRef(IMFMediaSourceTopologyProvider
*iface
)
2816 struct seq_source
*seq_source
= impl_from_IMFMediaSourceTopologyProvider(iface
);
2817 return IMFSequencerSource_AddRef(&seq_source
->IMFSequencerSource_iface
);
2820 static ULONG WINAPI
seq_source_topology_provider_Release(IMFMediaSourceTopologyProvider
*iface
)
2822 struct seq_source
*seq_source
= impl_from_IMFMediaSourceTopologyProvider(iface
);
2823 return IMFSequencerSource_Release(&seq_source
->IMFSequencerSource_iface
);
2826 static HRESULT WINAPI
seq_source_topology_provider_GetMediaSourceTopology(IMFMediaSourceTopologyProvider
*iface
,
2827 IMFPresentationDescriptor
*pd
, IMFTopology
**topology
)
2829 FIXME("%p, %p, %p.\n", iface
, pd
, topology
);
2834 static const IMFMediaSourceTopologyProviderVtbl seq_source_topology_provider_vtbl
=
2836 seq_source_topology_provider_QueryInterface
,
2837 seq_source_topology_provider_AddRef
,
2838 seq_source_topology_provider_Release
,
2839 seq_source_topology_provider_GetMediaSourceTopology
,
2842 static const IMFSequencerSourceVtbl seqsourcevtbl
=
2844 seq_source_QueryInterface
,
2847 seq_source_AppendTopology
,
2848 seq_source_DeleteTopology
,
2849 seq_source_GetPresentationContext
,
2850 seq_source_UpdateTopology
,
2851 seq_source_UpdateTopologyFlags
,
2854 /***********************************************************************
2855 * MFCreateSequencerSource (mf.@)
2857 HRESULT WINAPI
MFCreateSequencerSource(IUnknown
*reserved
, IMFSequencerSource
**seq_source
)
2859 struct seq_source
*object
;
2861 TRACE("%p, %p.\n", reserved
, seq_source
);
2866 if (!(object
= calloc(1, sizeof(*object
))))
2867 return E_OUTOFMEMORY
;
2869 object
->IMFSequencerSource_iface
.lpVtbl
= &seqsourcevtbl
;
2870 object
->IMFMediaSourceTopologyProvider_iface
.lpVtbl
= &seq_source_topology_provider_vtbl
;
2871 object
->refcount
= 1;
2873 *seq_source
= &object
->IMFSequencerSource_iface
;