mf/session: Add a stub for IMFTopologyNodeAttributeEditor.
[wine.git] / dlls / mf / tests / mf.c
blob846d311c87775d7897c0473b6d6694f65b672d5a
1 /*
2 * Unit tests for mf.dll.
4 * Copyright 2017 Nikolay Sivov
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include <stdarg.h>
22 #include <string.h>
23 #include <float.h>
25 #define COBJMACROS
27 #include "windef.h"
28 #include "winbase.h"
30 #include "initguid.h"
31 #include "ole2.h"
33 DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0);
34 DEFINE_GUID(MFVideoFormat_P208, 0x38303250, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
35 DEFINE_GUID(MFVideoFormat_ABGR32, 0x00000020, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
37 #undef INITGUID
38 #include <guiddef.h>
39 #include "mfapi.h"
40 #include "mferror.h"
41 #include "mfidl.h"
42 #include "initguid.h"
43 #include "uuids.h"
44 #include "mmdeviceapi.h"
45 #include "audioclient.h"
46 #include "evr.h"
48 #include "wine/test.h"
50 #define EXPECT_REF(obj,ref) _expect_ref((IUnknown*)obj, ref, __LINE__)
51 static void _expect_ref(IUnknown* obj, ULONG expected_refcount, int line)
53 ULONG refcount;
54 IUnknown_AddRef(obj);
55 refcount = IUnknown_Release(obj);
56 ok_(__FILE__, line)(refcount == expected_refcount, "Unexpected refcount %d, expected %d.\n", refcount,
57 expected_refcount);
60 #define check_interface(a, b, c) check_interface_(__LINE__, a, b, c)
61 static void check_interface_(unsigned int line, void *iface_ptr, REFIID iid, BOOL supported)
63 IUnknown *iface = iface_ptr;
64 HRESULT hr, expected_hr;
65 IUnknown *unk;
67 expected_hr = supported ? S_OK : E_NOINTERFACE;
69 hr = IUnknown_QueryInterface(iface, iid, (void **)&unk);
70 ok_(__FILE__, line)(hr == expected_hr, "Got hr %#x, expected %#x.\n", hr, expected_hr);
71 if (SUCCEEDED(hr))
72 IUnknown_Release(unk);
75 #define check_service_interface(a, b, c, d) check_service_interface_(__LINE__, a, b, c, d)
76 static void check_service_interface_(unsigned int line, void *iface_ptr, REFGUID service, REFIID iid, BOOL supported)
78 IUnknown *iface = iface_ptr;
79 HRESULT hr, expected_hr;
80 IUnknown *unk;
82 expected_hr = supported ? S_OK : E_NOINTERFACE;
84 hr = MFGetService(iface, service, iid, (void **)&unk);
85 ok_(__FILE__, line)(hr == expected_hr, "Got hr %#x, expected %#x.\n", hr, expected_hr);
86 if (SUCCEEDED(hr))
87 IUnknown_Release(unk);
90 static HWND create_window(void)
92 RECT r = {0, 0, 640, 480};
94 AdjustWindowRect(&r, WS_OVERLAPPEDWINDOW | WS_VISIBLE, FALSE);
96 return CreateWindowA("static", "mf_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
97 0, 0, r.right - r.left, r.bottom - r.top, NULL, NULL, NULL, NULL);
100 static HRESULT WINAPI test_unk_QueryInterface(IUnknown *iface, REFIID riid, void **obj)
102 if (IsEqualIID(riid, &IID_IUnknown))
104 *obj = iface;
105 IUnknown_AddRef(iface);
106 return S_OK;
109 *obj = NULL;
110 return E_NOINTERFACE;
113 static ULONG WINAPI test_unk_AddRef(IUnknown *iface)
115 return 2;
118 static ULONG WINAPI test_unk_Release(IUnknown *iface)
120 return 1;
123 static const IUnknownVtbl test_unk_vtbl =
125 test_unk_QueryInterface,
126 test_unk_AddRef,
127 test_unk_Release,
130 static void test_topology(void)
132 IMFMediaType *mediatype, *mediatype2, *mediatype3;
133 IMFCollection *collection, *collection2;
134 IUnknown test_unk2 = { &test_unk_vtbl };
135 IUnknown test_unk = { &test_unk_vtbl };
136 IMFTopologyNode *node, *node2, *node3;
137 IMFTopology *topology, *topology2;
138 MF_TOPOLOGY_TYPE node_type;
139 UINT32 count, index;
140 IUnknown *object;
141 WORD node_count;
142 DWORD size;
143 HRESULT hr;
144 TOPOID id;
146 hr = MFCreateTopology(NULL);
147 ok(hr == E_POINTER, "got %#x\n", hr);
149 hr = MFCreateTopology(&topology);
150 ok(hr == S_OK, "Failed to create topology, hr %#x.\n", hr);
151 hr = IMFTopology_GetTopologyID(topology, &id);
152 ok(hr == S_OK, "Failed to get id, hr %#x.\n", hr);
153 ok(id == 1, "Unexpected id.\n");
155 hr = MFCreateTopology(&topology2);
156 ok(hr == S_OK, "Failed to create topology, hr %#x.\n", hr);
157 hr = IMFTopology_GetTopologyID(topology2, &id);
158 ok(hr == S_OK, "Failed to get id, hr %#x.\n", hr);
159 ok(id == 2, "Unexpected id.\n");
161 IMFTopology_Release(topology);
163 hr = MFCreateTopology(&topology);
164 ok(hr == S_OK, "Failed to create topology, hr %#x.\n", hr);
165 hr = IMFTopology_GetTopologyID(topology, &id);
166 ok(hr == S_OK, "Failed to get id, hr %#x.\n", hr);
167 ok(id == 3, "Unexpected id.\n");
169 IMFTopology_Release(topology2);
171 /* No attributes by default. */
172 for (node_type = MF_TOPOLOGY_OUTPUT_NODE; node_type < MF_TOPOLOGY_TEE_NODE; ++node_type)
174 hr = MFCreateTopologyNode(node_type, &node);
175 ok(hr == S_OK, "Failed to create a node for type %d, hr %#x.\n", node_type, hr);
176 hr = IMFTopologyNode_GetCount(node, &count);
177 ok(hr == S_OK, "Failed to get attribute count, hr %#x.\n", hr);
178 ok(!count, "Unexpected attribute count %u.\n", count);
179 IMFTopologyNode_Release(node);
182 hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, NULL);
183 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
185 hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, &node);
186 ok(hr == S_OK, "Failed to create topology node, hr %#x.\n", hr);
188 hr = MFCreateTopologyNode(MF_TOPOLOGY_TEE_NODE, &node2);
189 ok(hr == S_OK, "Failed to create topology node, hr %#x.\n", hr);
191 hr = IMFTopologyNode_GetTopoNodeID(node, &id);
192 ok(hr == S_OK, "Failed to get node id, hr %#x.\n", hr);
193 ok(((id >> 32) == GetCurrentProcessId()) && !!(id & 0xffff), "Unexpected node id %s.\n", wine_dbgstr_longlong(id));
195 hr = IMFTopologyNode_SetTopoNodeID(node2, id);
196 ok(hr == S_OK, "Failed to set node id, hr %#x.\n", hr);
198 hr = IMFTopology_GetNodeCount(topology, NULL);
199 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
201 hr = IMFTopology_AddNode(topology, NULL);
202 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
204 node_count = 1;
205 hr = IMFTopology_GetNodeCount(topology, &node_count);
206 ok(hr == S_OK, "Failed to get node count, hr %#x.\n", hr);
207 ok(node_count == 0, "Unexpected node count %u.\n", node_count);
209 /* Same id, different nodes. */
210 hr = IMFTopology_AddNode(topology, node);
211 ok(hr == S_OK, "Failed to add a node, hr %#x.\n", hr);
213 node_count = 0;
214 hr = IMFTopology_GetNodeCount(topology, &node_count);
215 ok(hr == S_OK, "Failed to get node count, hr %#x.\n", hr);
216 ok(node_count == 1, "Unexpected node count %u.\n", node_count);
218 hr = IMFTopology_AddNode(topology, node2);
219 ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
220 IMFTopologyNode_Release(node2);
222 hr = IMFTopology_GetNodeByID(topology, id, &node2);
223 ok(hr == S_OK, "Failed to get a node, hr %#x.\n", hr);
224 ok(node2 == node, "Unexpected node.\n");
225 IMFTopologyNode_Release(node2);
227 /* Change node id, add it again. */
228 hr = IMFTopologyNode_SetTopoNodeID(node, ++id);
229 ok(hr == S_OK, "Failed to set node id, hr %#x.\n", hr);
231 hr = IMFTopology_GetNodeByID(topology, id, &node2);
232 ok(hr == S_OK, "Failed to get a node, hr %#x.\n", hr);
233 ok(node2 == node, "Unexpected node.\n");
234 IMFTopologyNode_Release(node2);
236 hr = IMFTopology_GetNodeByID(topology, id + 1, &node2);
237 ok(hr == MF_E_NOT_FOUND, "Unexpected hr %#x.\n", hr);
239 hr = IMFTopology_AddNode(topology, node);
240 ok(hr == E_INVALIDARG, "Failed to add a node, hr %#x.\n", hr);
242 hr = IMFTopology_GetNode(topology, 0, &node2);
243 ok(hr == S_OK, "Failed to get a node, hr %#x.\n", hr);
244 ok(node2 == node, "Unexpected node.\n");
245 IMFTopologyNode_Release(node2);
247 hr = IMFTopology_GetNode(topology, 1, NULL);
248 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
250 hr = IMFTopology_GetNode(topology, 1, &node2);
251 ok(hr == MF_E_INVALIDINDEX, "Failed to get a node, hr %#x.\n", hr);
253 hr = IMFTopology_GetNode(topology, -2, &node2);
254 ok(hr == MF_E_INVALIDINDEX, "Failed to get a node, hr %#x.\n", hr);
256 hr = MFCreateTopologyNode(MF_TOPOLOGY_TEE_NODE, &node2);
257 ok(hr == S_OK, "Failed to create topology node, hr %#x.\n", hr);
258 hr = IMFTopology_AddNode(topology, node2);
259 ok(hr == S_OK, "Failed to add a node, hr %#x.\n", hr);
260 IMFTopologyNode_Release(node2);
262 node_count = 0;
263 hr = IMFTopology_GetNodeCount(topology, &node_count);
264 ok(hr == S_OK, "Failed to get node count, hr %#x.\n", hr);
265 ok(node_count == 2, "Unexpected node count %u.\n", node_count);
267 /* Remove with detached node, existing id. */
268 hr = MFCreateTopologyNode(MF_TOPOLOGY_TEE_NODE, &node2);
269 ok(hr == S_OK, "Failed to create topology node, hr %#x.\n", hr);
270 hr = IMFTopologyNode_SetTopoNodeID(node2, id);
271 ok(hr == S_OK, "Failed to set node id, hr %#x.\n", hr);
272 hr = IMFTopology_RemoveNode(topology, node2);
273 ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
274 IMFTopologyNode_Release(node2);
276 hr = IMFTopology_RemoveNode(topology, node);
277 ok(hr == S_OK, "Failed to remove a node, hr %#x.\n", hr);
279 node_count = 0;
280 hr = IMFTopology_GetNodeCount(topology, &node_count);
281 ok(hr == S_OK, "Failed to get node count, hr %#x.\n", hr);
282 ok(node_count == 1, "Unexpected node count %u.\n", node_count);
284 hr = IMFTopology_Clear(topology);
285 ok(hr == S_OK, "Failed to clear topology, hr %#x.\n", hr);
287 node_count = 1;
288 hr = IMFTopology_GetNodeCount(topology, &node_count);
289 ok(hr == S_OK, "Failed to get node count, hr %#x.\n", hr);
290 ok(node_count == 0, "Unexpected node count %u.\n", node_count);
292 hr = IMFTopology_Clear(topology);
293 ok(hr == S_OK, "Failed to clear topology, hr %#x.\n", hr);
295 hr = IMFTopologyNode_SetTopoNodeID(node, 123);
296 ok(hr == S_OK, "Failed to set node id, hr %#x.\n", hr);
298 IMFTopologyNode_Release(node);
300 /* Change id for attached node. */
301 hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, &node);
302 ok(hr == S_OK, "Failed to create topology node, hr %#x.\n", hr);
304 hr = MFCreateTopologyNode(MF_TOPOLOGY_TEE_NODE, &node2);
305 ok(hr == S_OK, "Failed to create topology node, hr %#x.\n", hr);
307 hr = IMFTopology_AddNode(topology, node);
308 ok(hr == S_OK, "Failed to add a node, hr %#x.\n", hr);
310 hr = IMFTopology_AddNode(topology, node2);
311 ok(hr == S_OK, "Failed to add a node, hr %#x.\n", hr);
313 hr = IMFTopologyNode_GetTopoNodeID(node, &id);
314 ok(hr == S_OK, "Failed to get node id, hr %#x.\n", hr);
316 hr = IMFTopologyNode_SetTopoNodeID(node2, id);
317 ok(hr == S_OK, "Failed to get node id, hr %#x.\n", hr);
319 hr = IMFTopology_GetNodeByID(topology, id, &node3);
320 ok(hr == S_OK, "Failed to get a node, hr %#x.\n", hr);
321 ok(node3 == node, "Unexpected node.\n");
322 IMFTopologyNode_Release(node3);
324 IMFTopologyNode_Release(node);
325 IMFTopologyNode_Release(node2);
327 /* Source/output collections. */
328 hr = IMFTopology_Clear(topology);
329 ok(hr == S_OK, "Failed to clear topology, hr %#x.\n", hr);
331 hr = IMFTopology_GetSourceNodeCollection(topology, NULL);
332 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
334 hr = IMFTopology_GetSourceNodeCollection(topology, &collection);
335 ok(hr == S_OK, "Failed to get source node collection, hr %#x.\n", hr);
336 ok(!!collection, "Unexpected object pointer.\n");
338 hr = IMFTopology_GetSourceNodeCollection(topology, &collection2);
339 ok(hr == S_OK, "Failed to get source node collection, hr %#x.\n", hr);
340 ok(!!collection2, "Unexpected object pointer.\n");
341 ok(collection2 != collection, "Expected cloned collection.\n");
343 hr = IMFCollection_GetElementCount(collection, &size);
344 ok(hr == S_OK, "Failed to get item count, hr %#x.\n", hr);
345 ok(!size, "Unexpected item count.\n");
347 hr = IMFCollection_AddElement(collection, (IUnknown *)collection);
348 ok(hr == S_OK, "Failed to add element, hr %#x.\n", hr);
350 hr = IMFCollection_GetElementCount(collection, &size);
351 ok(hr == S_OK, "Failed to get item count, hr %#x.\n", hr);
352 ok(size == 1, "Unexpected item count.\n");
354 hr = IMFCollection_GetElementCount(collection2, &size);
355 ok(hr == S_OK, "Failed to get item count, hr %#x.\n", hr);
356 ok(!size, "Unexpected item count.\n");
358 IMFCollection_Release(collection2);
359 IMFCollection_Release(collection);
361 /* Add some nodes. */
362 hr = IMFTopology_GetSourceNodeCollection(topology, NULL);
363 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
365 hr = IMFTopology_GetOutputNodeCollection(topology, NULL);
366 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
368 hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &node);
369 ok(hr == S_OK, "Failed to create a node, hr %#x.\n", hr);
370 hr = IMFTopology_AddNode(topology, node);
371 ok(hr == S_OK, "Failed to add a node, hr %#x.\n", hr);
372 IMFTopologyNode_Release(node);
374 hr = IMFTopology_GetSourceNodeCollection(topology, &collection);
375 ok(hr == S_OK, "Failed to get source node collection, hr %#x.\n", hr);
376 ok(!!collection, "Unexpected object pointer.\n");
377 hr = IMFCollection_GetElementCount(collection, &size);
378 ok(hr == S_OK, "Failed to get item count, hr %#x.\n", hr);
379 ok(size == 1, "Unexpected item count.\n");
380 IMFCollection_Release(collection);
382 hr = MFCreateTopologyNode(MF_TOPOLOGY_TEE_NODE, &node);
383 ok(hr == S_OK, "Failed to create a node, hr %#x.\n", hr);
384 hr = IMFTopology_AddNode(topology, node);
385 ok(hr == S_OK, "Failed to add a node, hr %#x.\n", hr);
386 IMFTopologyNode_Release(node);
388 hr = IMFTopology_GetSourceNodeCollection(topology, &collection);
389 ok(hr == S_OK, "Failed to get source node collection, hr %#x.\n", hr);
390 ok(!!collection, "Unexpected object pointer.\n");
391 hr = IMFCollection_GetElementCount(collection, &size);
392 ok(hr == S_OK, "Failed to get item count, hr %#x.\n", hr);
393 ok(size == 1, "Unexpected item count.\n");
394 IMFCollection_Release(collection);
396 hr = MFCreateTopologyNode(MF_TOPOLOGY_TRANSFORM_NODE, &node);
397 ok(hr == S_OK, "Failed to create a node, hr %#x.\n", hr);
398 hr = IMFTopology_AddNode(topology, node);
399 ok(hr == S_OK, "Failed to add a node, hr %#x.\n", hr);
400 IMFTopologyNode_Release(node);
402 hr = IMFTopology_GetSourceNodeCollection(topology, &collection);
403 ok(hr == S_OK, "Failed to get source node collection, hr %#x.\n", hr);
404 ok(!!collection, "Unexpected object pointer.\n");
405 hr = IMFCollection_GetElementCount(collection, &size);
406 ok(hr == S_OK, "Failed to get item count, hr %#x.\n", hr);
407 ok(size == 1, "Unexpected item count.\n");
408 IMFCollection_Release(collection);
410 hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, &node);
411 ok(hr == S_OK, "Failed to create a node, hr %#x.\n", hr);
412 hr = IMFTopology_AddNode(topology, node);
413 ok(hr == S_OK, "Failed to add a node, hr %#x.\n", hr);
415 /* Associated object. */
416 hr = IMFTopologyNode_SetObject(node, NULL);
417 ok(hr == S_OK, "Failed to set object, hr %#x.\n", hr);
419 hr = IMFTopologyNode_GetObject(node, NULL);
420 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
422 object = (void *)0xdeadbeef;
423 hr = IMFTopologyNode_GetObject(node, &object);
424 ok(hr == E_FAIL, "Unexpected hr %#x.\n", hr);
425 ok(!object, "Unexpected object %p.\n", object);
427 hr = IMFTopologyNode_SetObject(node, &test_unk);
428 ok(hr == S_OK, "Failed to set object, hr %#x.\n", hr);
430 hr = IMFTopologyNode_GetObject(node, &object);
431 ok(hr == S_OK, "Failed to get object, hr %#x.\n", hr);
432 ok(object == &test_unk, "Unexpected object %p.\n", object);
433 IUnknown_Release(object);
435 hr = IMFTopologyNode_SetObject(node, &test_unk2);
436 ok(hr == S_OK, "Failed to set object, hr %#x.\n", hr);
438 hr = IMFTopologyNode_GetCount(node, &count);
439 ok(hr == S_OK, "Failed to get attribute count, hr %#x.\n", hr);
440 ok(count == 0, "Unexpected attribute count %u.\n", count);
442 hr = IMFTopologyNode_SetGUID(node, &MF_TOPONODE_TRANSFORM_OBJECTID, &MF_TOPONODE_TRANSFORM_OBJECTID);
443 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
445 hr = IMFTopologyNode_SetObject(node, NULL);
446 ok(hr == S_OK, "Failed to set object, hr %#x.\n", hr);
448 object = (void *)0xdeadbeef;
449 hr = IMFTopologyNode_GetObject(node, &object);
450 ok(hr == E_FAIL, "Unexpected hr %#x.\n", hr);
451 ok(!object, "Unexpected object %p.\n", object);
453 hr = IMFTopologyNode_GetCount(node, &count);
454 ok(hr == S_OK, "Failed to get attribute count, hr %#x.\n", hr);
455 ok(count == 1, "Unexpected attribute count %u.\n", count);
457 /* Preferred stream types. */
458 hr = IMFTopologyNode_GetInputCount(node, &count);
459 ok(hr == S_OK, "Failed to get input count, hr %#x.\n", hr);
460 ok(count == 0, "Unexpected count %u.\n", count);
462 hr = IMFTopologyNode_GetInputPrefType(node, 0, &mediatype);
463 ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
465 hr = MFCreateMediaType(&mediatype);
466 ok(hr == S_OK, "Failed to create media type, hr %#x.\n", hr);
468 hr = IMFTopologyNode_SetInputPrefType(node, 0, mediatype);
469 ok(hr == S_OK, "Failed to set preferred type, hr %#x.\n", hr);
471 hr = IMFTopologyNode_GetInputPrefType(node, 0, &mediatype2);
472 ok(hr == S_OK, "Failed to get preferred type, hr %#x.\n", hr);
473 ok(mediatype2 == mediatype, "Unexpected mediatype instance.\n");
474 IMFMediaType_Release(mediatype2);
476 hr = IMFTopologyNode_SetInputPrefType(node, 0, NULL);
477 ok(hr == S_OK, "Failed to set preferred type, hr %#x.\n", hr);
479 hr = IMFTopologyNode_GetInputPrefType(node, 0, &mediatype2);
480 ok(hr == E_FAIL, "Unexpected hr %#x.\n", hr);
481 ok(!mediatype2, "Unexpected mediatype instance.\n");
483 hr = IMFTopologyNode_SetInputPrefType(node, 1, mediatype);
484 ok(hr == S_OK, "Failed to set preferred type, hr %#x.\n", hr);
486 hr = IMFTopologyNode_SetInputPrefType(node, 1, mediatype);
487 ok(hr == S_OK, "Failed to set preferred type, hr %#x.\n", hr);
489 hr = IMFTopologyNode_GetInputCount(node, &count);
490 ok(hr == S_OK, "Failed to get input count, hr %#x.\n", hr);
491 ok(count == 2, "Unexpected count %u.\n", count);
493 hr = IMFTopologyNode_GetOutputCount(node, &count);
494 ok(hr == S_OK, "Failed to get input count, hr %#x.\n", hr);
495 ok(count == 0, "Unexpected count %u.\n", count);
497 hr = IMFTopologyNode_SetOutputPrefType(node, 0, mediatype);
498 ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
500 IMFTopologyNode_Release(node);
502 /* Source node. */
503 hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &node);
504 ok(hr == S_OK, "Failed to create a node, hr %#x.\n", hr);
506 hr = IMFTopologyNode_SetInputPrefType(node, 0, mediatype);
507 ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
509 hr = IMFTopologyNode_SetOutputPrefType(node, 2, mediatype);
510 ok(hr == S_OK, "Failed to set preferred type, hr %#x.\n", hr);
512 hr = IMFTopologyNode_GetOutputPrefType(node, 0, &mediatype2);
513 ok(hr == E_FAIL, "Failed to get preferred type, hr %#x.\n", hr);
514 ok(!mediatype2, "Unexpected mediatype instance.\n");
516 hr = IMFTopologyNode_GetOutputCount(node, &count);
517 ok(hr == S_OK, "Failed to get output count, hr %#x.\n", hr);
518 ok(count == 3, "Unexpected count %u.\n", count);
520 IMFTopologyNode_Release(node);
522 /* Tee node. */
523 hr = MFCreateTopologyNode(MF_TOPOLOGY_TEE_NODE, &node);
524 ok(hr == S_OK, "Failed to create a node, hr %#x.\n", hr);
526 hr = IMFTopologyNode_SetInputPrefType(node, 0, mediatype);
527 ok(hr == S_OK, "Failed to set preferred type, hr %#x.\n", hr);
529 hr = IMFTopologyNode_GetInputPrefType(node, 0, &mediatype2);
530 ok(hr == S_OK, "Failed to get preferred type, hr %#x.\n", hr);
531 ok(mediatype2 == mediatype, "Unexpected mediatype instance.\n");
532 IMFMediaType_Release(mediatype2);
534 hr = IMFTopologyNode_GetOutputPrefType(node, 0, &mediatype2);
535 ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
537 hr = IMFTopologyNode_GetInputCount(node, &count);
538 ok(hr == S_OK, "Failed to get output count, hr %#x.\n", hr);
539 ok(count == 0, "Unexpected count %u.\n", count);
541 hr = IMFTopologyNode_SetInputPrefType(node, 1, mediatype);
542 ok(hr == MF_E_INVALIDTYPE, "Unexpected hr %#x.\n", hr);
544 hr = IMFTopologyNode_SetInputPrefType(node, 3, mediatype);
545 ok(hr == MF_E_INVALIDTYPE, "Unexpected hr %#x.\n", hr);
547 hr = IMFTopologyNode_SetOutputPrefType(node, 4, mediatype);
548 ok(hr == S_OK, "Failed to set preferred type, hr %#x.\n", hr);
550 hr = IMFTopologyNode_GetOutputPrefType(node, 0, &mediatype2);
551 ok(hr == E_FAIL, "Unexpected hr %#x.\n", hr);
553 hr = MFCreateMediaType(&mediatype2);
554 ok(hr == S_OK, "Failed to create media type, hr %#x.\n", hr);
556 /* Changing output type does not change input type. */
557 hr = IMFTopologyNode_SetOutputPrefType(node, 4, mediatype2);
558 ok(hr == S_OK, "Failed to set preferred type, hr %#x.\n", hr);
560 hr = IMFTopologyNode_GetInputPrefType(node, 0, &mediatype3);
561 ok(hr == S_OK, "Failed to get preferred type, hr %#x.\n", hr);
562 ok(mediatype3 == mediatype, "Unexpected mediatype instance.\n");
563 IMFMediaType_Release(mediatype3);
565 IMFMediaType_Release(mediatype2);
567 hr = IMFTopologyNode_GetInputCount(node, &count);
568 ok(hr == S_OK, "Failed to get output count, hr %#x.\n", hr);
569 ok(count == 0, "Unexpected count %u.\n", count);
571 hr = IMFTopologyNode_GetOutputCount(node, &count);
572 ok(hr == S_OK, "Failed to get output count, hr %#x.\n", hr);
573 ok(count == 5, "Unexpected count %u.\n", count);
575 IMFTopologyNode_Release(node);
577 /* Transform node. */
578 hr = MFCreateTopologyNode(MF_TOPOLOGY_TRANSFORM_NODE, &node);
579 ok(hr == S_OK, "Failed to create a node, hr %#x.\n", hr);
581 hr = IMFTopologyNode_SetInputPrefType(node, 3, mediatype);
582 ok(hr == S_OK, "Failed to set preferred type, hr %#x.\n", hr);
584 hr = IMFTopologyNode_GetInputCount(node, &count);
585 ok(hr == S_OK, "Failed to get input count, hr %#x.\n", hr);
586 ok(count == 4, "Unexpected count %u.\n", count);
588 hr = IMFTopologyNode_SetOutputPrefType(node, 4, mediatype);
589 ok(hr == S_OK, "Failed to set preferred type, hr %#x.\n", hr);
591 hr = IMFTopologyNode_GetInputCount(node, &count);
592 ok(hr == S_OK, "Failed to get output count, hr %#x.\n", hr);
593 ok(count == 4, "Unexpected count %u.\n", count);
595 hr = IMFTopologyNode_GetOutputCount(node, &count);
596 ok(hr == S_OK, "Failed to get output count, hr %#x.\n", hr);
597 ok(count == 5, "Unexpected count %u.\n", count);
599 IMFTopologyNode_Release(node);
601 IMFMediaType_Release(mediatype);
603 hr = IMFTopology_GetOutputNodeCollection(topology, &collection);
604 ok(hr == S_OK || broken(hr == E_FAIL) /* before Win8 */, "Failed to get output node collection, hr %#x.\n", hr);
605 if (SUCCEEDED(hr))
607 ok(!!collection, "Unexpected object pointer.\n");
608 hr = IMFCollection_GetElementCount(collection, &size);
609 ok(hr == S_OK, "Failed to get item count, hr %#x.\n", hr);
610 ok(size == 1, "Unexpected item count.\n");
611 IMFCollection_Release(collection);
614 IMFTopology_Release(topology);
616 /* Connect nodes. */
617 hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &node);
618 ok(hr == S_OK, "Failed to create topology node, hr %#x.\n", hr);
620 hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, &node2);
621 ok(hr == S_OK, "Failed to create topology node, hr %#x.\n", hr);
623 EXPECT_REF(node, 1);
624 EXPECT_REF(node2, 1);
626 hr = IMFTopologyNode_ConnectOutput(node, 0, node2, 1);
627 ok(hr == S_OK, "Failed to connect nodes, hr %#x.\n", hr);
629 EXPECT_REF(node, 2);
630 EXPECT_REF(node2, 2);
632 IMFTopologyNode_Release(node);
634 EXPECT_REF(node, 1);
635 EXPECT_REF(node2, 2);
637 IMFTopologyNode_Release(node2);
639 EXPECT_REF(node, 1);
640 EXPECT_REF(node2, 1);
642 hr = IMFTopologyNode_GetNodeType(node2, &node_type);
643 ok(hr == S_OK, "Failed to get node type, hr %#x.\n", hr);
645 IMFTopologyNode_Release(node);
647 /* Connect within topology. */
648 hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &node);
649 ok(hr == S_OK, "Failed to create topology node, hr %#x.\n", hr);
651 hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, &node2);
652 ok(hr == S_OK, "Failed to create topology node, hr %#x.\n", hr);
654 hr = MFCreateTopology(&topology);
655 ok(hr == S_OK, "Failed to create topology, hr %#x.\n", hr);
657 hr = IMFTopology_AddNode(topology, node);
658 ok(hr == S_OK, "Failed to add a node, hr %#x.\n", hr);
660 hr = IMFTopology_AddNode(topology, node2);
661 ok(hr == S_OK, "Failed to add a node, hr %#x.\n", hr);
663 EXPECT_REF(node, 2);
664 EXPECT_REF(node2, 2);
666 hr = IMFTopologyNode_ConnectOutput(node, 0, node2, 1);
667 ok(hr == S_OK, "Failed to connect nodes, hr %#x.\n", hr);
669 EXPECT_REF(node, 3);
670 EXPECT_REF(node2, 3);
672 hr = IMFTopology_Clear(topology);
673 ok(hr == S_OK, "Failed to clear topology, hr %#x.\n", hr);
675 EXPECT_REF(node, 1);
676 EXPECT_REF(node2, 1);
678 /* Removing connected node breaks connection. */
679 hr = IMFTopology_AddNode(topology, node);
680 ok(hr == S_OK, "Failed to add a node, hr %#x.\n", hr);
682 hr = IMFTopology_AddNode(topology, node2);
683 ok(hr == S_OK, "Failed to add a node, hr %#x.\n", hr);
685 hr = IMFTopologyNode_ConnectOutput(node, 0, node2, 1);
686 ok(hr == S_OK, "Failed to connect nodes, hr %#x.\n", hr);
688 hr = IMFTopology_RemoveNode(topology, node);
689 ok(hr == S_OK, "Failed to remove a node, hr %#x.\n", hr);
691 EXPECT_REF(node, 1);
692 EXPECT_REF(node2, 2);
694 hr = IMFTopologyNode_GetOutput(node, 0, &node3, &index);
695 ok(hr == MF_E_NOT_FOUND, "Unexpected hr %#x.\n", hr);
697 hr = IMFTopology_AddNode(topology, node);
698 ok(hr == S_OK, "Failed to add a node, hr %#x.\n", hr);
700 hr = IMFTopologyNode_ConnectOutput(node, 0, node2, 1);
701 ok(hr == S_OK, "Failed to connect nodes, hr %#x.\n", hr);
703 hr = IMFTopology_RemoveNode(topology, node2);
704 ok(hr == S_OK, "Failed to remove a node, hr %#x.\n", hr);
706 EXPECT_REF(node, 2);
707 EXPECT_REF(node2, 1);
709 IMFTopologyNode_Release(node);
710 IMFTopologyNode_Release(node2);
712 /* Cloning nodes of different types. */
713 hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &node);
714 ok(hr == S_OK, "Failed to create topology node, hr %#x.\n", hr);
716 hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, &node2);
717 ok(hr == S_OK, "Failed to create topology node, hr %#x.\n", hr);
719 hr = IMFTopologyNode_CloneFrom(node, node2);
720 ok(hr == MF_E_INVALIDREQUEST, "Unexpected hr %#x.\n", hr);
722 IMFTopologyNode_Release(node2);
724 /* Cloning preferred types. */
725 hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &node2);
726 ok(hr == S_OK, "Failed to create topology node, hr %#x.\n", hr);
728 hr = MFCreateMediaType(&mediatype);
729 ok(hr == S_OK, "Failed to create media type, hr %#x.\n", hr);
731 hr = IMFTopologyNode_SetOutputPrefType(node2, 0, mediatype);
732 ok(hr == S_OK, "Failed to set preferred type, hr %#x.\n", hr);
734 /* Vista checks for additional attributes. */
735 hr = IMFTopologyNode_CloneFrom(node, node2);
736 ok(hr == S_OK || broken(hr == MF_E_ATTRIBUTENOTFOUND) /* Vista */, "Failed to clone a node, hr %#x.\n", hr);
738 hr = IMFTopologyNode_GetOutputPrefType(node, 0, &mediatype2);
739 ok(hr == S_OK, "Failed to get preferred type, hr %#x.\n", hr);
740 ok(mediatype == mediatype2, "Unexpected media type.\n");
742 IMFMediaType_Release(mediatype2);
743 IMFMediaType_Release(mediatype);
745 IMFTopologyNode_Release(node2);
747 /* Existing preferred types are not cleared. */
748 hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &node2);
749 ok(hr == S_OK, "Failed to create topology node, hr %#x.\n", hr);
751 hr = IMFTopologyNode_GetOutputCount(node, &count);
752 ok(hr == S_OK, "Failed to get output count, hr %#x.\n", hr);
753 ok(count == 1, "Unexpected output count.\n");
755 hr = IMFTopologyNode_CloneFrom(node, node2);
756 ok(hr == S_OK || broken(hr == MF_E_ATTRIBUTENOTFOUND) /* Vista */, "Failed to clone a node, hr %#x.\n", hr);
758 hr = IMFTopologyNode_GetOutputCount(node, &count);
759 ok(hr == S_OK, "Failed to get output count, hr %#x.\n", hr);
760 ok(count == 1, "Unexpected output count.\n");
762 hr = IMFTopologyNode_GetOutputPrefType(node, 0, &mediatype2);
763 ok(hr == S_OK, "Failed to get preferred type, hr %#x.\n", hr);
764 ok(!!mediatype2, "Unexpected media type.\n");
765 IMFMediaType_Release(mediatype2);
767 hr = IMFTopologyNode_CloneFrom(node2, node);
768 ok(hr == S_OK || broken(hr == MF_E_ATTRIBUTENOTFOUND) /* Vista */, "Failed to clone a node, hr %#x.\n", hr);
770 hr = IMFTopologyNode_GetOutputCount(node2, &count);
771 ok(hr == S_OK, "Failed to get output count, hr %#x.\n", hr);
772 ok(count == 1, "Unexpected output count.\n");
774 IMFTopologyNode_Release(node2);
775 IMFTopologyNode_Release(node);
777 /* Add one node, connect to another that hasn't been added. */
778 hr = IMFTopology_Clear(topology);
779 ok(hr == S_OK, "Failed to clear topology, hr %#x.\n", hr);
781 hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &node);
782 ok(hr == S_OK, "Failed to create topology node, hr %#x.\n", hr);
784 hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, &node2);
785 ok(hr == S_OK, "Failed to create topology node, hr %#x.\n", hr);
787 hr = IMFTopology_AddNode(topology, node);
788 ok(hr == S_OK, "Failed to add a node, hr %#x.\n", hr);
790 hr = IMFTopology_GetNodeCount(topology, &node_count);
791 ok(hr == S_OK, "Failed to get node count, hr %#x.\n", hr);
792 ok(node_count == 1, "Unexpected node count.\n");
794 hr = IMFTopologyNode_ConnectOutput(node, 0, node2, 0);
795 ok(hr == S_OK, "Failed to connect nodes, hr %#x.\n", hr);
797 hr = IMFTopology_GetNodeCount(topology, &node_count);
798 ok(hr == S_OK, "Failed to get node count, hr %#x.\n", hr);
799 ok(node_count == 1, "Unexpected node count.\n");
801 IMFTopologyNode_Release(node);
802 IMFTopologyNode_Release(node2);
804 /* Add same node to different topologies. */
805 hr = IMFTopology_Clear(topology);
806 ok(hr == S_OK, "Failed to clear topology, hr %#x.\n", hr);
808 hr = MFCreateTopology(&topology2);
809 ok(hr == S_OK, "Failed to create topology, hr %#x.\n", hr);
811 hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &node);
812 ok(hr == S_OK, "Failed to create topology node, hr %#x.\n", hr);
814 hr = IMFTopology_AddNode(topology, node);
815 ok(hr == S_OK, "Failed to add a node, hr %#x.\n", hr);
816 EXPECT_REF(node, 2);
818 hr = IMFTopology_GetNodeCount(topology, &node_count);
819 ok(hr == S_OK, "Failed to get node count, hr %#x.\n", hr);
820 ok(node_count == 1, "Unexpected node count.\n");
822 hr = IMFTopology_GetNodeCount(topology2, &node_count);
823 ok(hr == S_OK, "Failed to get node count, hr %#x.\n", hr);
824 ok(node_count == 0, "Unexpected node count.\n");
826 hr = IMFTopology_AddNode(topology2, node);
827 ok(hr == S_OK, "Failed to add a node, hr %#x.\n", hr);
828 EXPECT_REF(node, 3);
830 hr = IMFTopology_GetNodeCount(topology, &node_count);
831 ok(hr == S_OK, "Failed to get node count, hr %#x.\n", hr);
832 ok(node_count == 1, "Unexpected node count.\n");
834 hr = IMFTopology_GetNodeCount(topology2, &node_count);
835 ok(hr == S_OK, "Failed to get node count, hr %#x.\n", hr);
836 ok(node_count == 1, "Unexpected node count.\n");
838 IMFTopology_Release(topology2);
839 IMFTopology_Release(topology);
842 static void test_topology_tee_node(void)
844 IMFTopologyNode *src_node, *tee_node;
845 IMFMediaType *mediatype, *mediatype2;
846 IMFTopology *topology;
847 unsigned int count;
848 HRESULT hr;
850 hr = MFCreateTopology(&topology);
851 ok(hr == S_OK, "Failed to create topology, hr %#x.\n", hr);
853 hr = MFCreateMediaType(&mediatype);
854 ok(hr == S_OK, "Failed to create media type, hr %#x.\n", hr);
856 hr = MFCreateTopologyNode(MF_TOPOLOGY_TEE_NODE, &tee_node);
857 ok(hr == S_OK, "Failed to create topology node, hr %#x.\n", hr);
859 hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &src_node);
860 ok(hr == S_OK, "Failed to create topology node, hr %#x.\n", hr);
862 hr = IMFTopologyNode_SetInputPrefType(tee_node, 0, mediatype);
863 ok(hr == S_OK, "Failed to set type, hr %#x.\n", hr);
865 /* Even though tee node has only one input and source has only one output,
866 it's possible to connect to higher inputs/outputs. */
868 /* SRC(0) -> TEE(0) */
869 hr = IMFTopologyNode_ConnectOutput(src_node, 0, tee_node, 0);
870 ok(hr == S_OK, "Failed to connect nodes, hr %#x.\n", hr);
872 hr = IMFTopologyNode_GetInputCount(tee_node, &count);
873 ok(hr == S_OK, "Failed to get count, hr %#x.\n", hr);
874 ok(count == 1, "Unexpected count %u.\n", count);
876 hr = IMFTopologyNode_GetInputPrefType(tee_node, 0, &mediatype2);
877 ok(hr == S_OK, "Failed to get type, hr %#x.\n", hr);
878 ok(mediatype2 == mediatype, "Unexpected type.\n");
879 IMFMediaType_Release(mediatype2);
881 /* SRC(0) -> TEE(1) */
882 hr = IMFTopologyNode_ConnectOutput(src_node, 0, tee_node, 1);
883 ok(hr == S_OK, "Failed to connect nodes, hr %#x.\n", hr);
885 hr = IMFTopologyNode_GetInputCount(tee_node, &count);
886 ok(hr == S_OK, "Failed to get count, hr %#x.\n", hr);
887 ok(count == 2, "Unexpected count %u.\n", count);
889 hr = IMFTopologyNode_SetInputPrefType(tee_node, 1, mediatype);
890 ok(hr == MF_E_INVALIDTYPE, "Unexpected hr %#x.\n", hr);
892 /* SRC(1) -> TEE(1) */
893 hr = IMFTopologyNode_ConnectOutput(src_node, 1, tee_node, 1);
894 ok(hr == S_OK, "Failed to connect nodes, hr %#x.\n", hr);
896 hr = IMFTopologyNode_GetOutputCount(src_node, &count);
897 ok(hr == S_OK, "Failed to get count, hr %#x.\n", hr);
898 ok(count == 2, "Unexpected count %u.\n", count);
900 IMFMediaType_Release(mediatype);
901 IMFTopologyNode_Release(src_node);
902 IMFTopologyNode_Release(tee_node);
903 IMFTopology_Release(topology);
906 static HRESULT WINAPI test_getservice_QI(IMFGetService *iface, REFIID riid, void **obj)
908 if (IsEqualIID(riid, &IID_IMFGetService) || IsEqualIID(riid, &IID_IUnknown))
910 *obj = iface;
911 return S_OK;
914 *obj = NULL;
915 return E_NOINTERFACE;
918 static ULONG WINAPI test_getservice_AddRef(IMFGetService *iface)
920 return 2;
923 static ULONG WINAPI test_getservice_Release(IMFGetService *iface)
925 return 1;
928 static HRESULT WINAPI test_getservice_GetService(IMFGetService *iface, REFGUID service, REFIID riid, void **obj)
930 *obj = (void *)0xdeadbeef;
931 return 0x83eddead;
934 static const IMFGetServiceVtbl testmfgetservicevtbl =
936 test_getservice_QI,
937 test_getservice_AddRef,
938 test_getservice_Release,
939 test_getservice_GetService,
942 static IMFGetService test_getservice = { &testmfgetservicevtbl };
944 static HRESULT WINAPI testservice_QI(IUnknown *iface, REFIID riid, void **obj)
946 if (IsEqualIID(riid, &IID_IUnknown))
948 *obj = iface;
949 return S_OK;
952 *obj = NULL;
954 if (IsEqualIID(riid, &IID_IMFGetService))
955 return 0x82eddead;
957 return E_NOINTERFACE;
960 static HRESULT WINAPI testservice2_QI(IUnknown *iface, REFIID riid, void **obj)
962 if (IsEqualIID(riid, &IID_IUnknown))
964 *obj = iface;
965 return S_OK;
968 if (IsEqualIID(riid, &IID_IMFGetService))
970 *obj = &test_getservice;
971 return S_OK;
974 *obj = NULL;
975 return E_NOINTERFACE;
978 static ULONG WINAPI testservice_AddRef(IUnknown *iface)
980 return 2;
983 static ULONG WINAPI testservice_Release(IUnknown *iface)
985 return 1;
988 static const IUnknownVtbl testservicevtbl =
990 testservice_QI,
991 testservice_AddRef,
992 testservice_Release,
995 static const IUnknownVtbl testservice2vtbl =
997 testservice2_QI,
998 testservice_AddRef,
999 testservice_Release,
1002 static IUnknown testservice = { &testservicevtbl };
1003 static IUnknown testservice2 = { &testservice2vtbl };
1005 static void test_MFGetService(void)
1007 IUnknown *unk;
1008 HRESULT hr;
1010 hr = MFGetService(NULL, NULL, NULL, NULL);
1011 ok(hr == E_POINTER, "Unexpected return value %#x.\n", hr);
1013 unk = (void *)0xdeadbeef;
1014 hr = MFGetService(NULL, NULL, NULL, (void **)&unk);
1015 ok(hr == E_POINTER, "Unexpected return value %#x.\n", hr);
1016 ok(unk == (void *)0xdeadbeef, "Unexpected out object.\n");
1018 hr = MFGetService(&testservice, NULL, NULL, NULL);
1019 ok(hr == 0x82eddead, "Unexpected return value %#x.\n", hr);
1021 unk = (void *)0xdeadbeef;
1022 hr = MFGetService(&testservice, NULL, NULL, (void **)&unk);
1023 ok(hr == 0x82eddead, "Unexpected return value %#x.\n", hr);
1024 ok(unk == (void *)0xdeadbeef, "Unexpected out object.\n");
1026 unk = NULL;
1027 hr = MFGetService(&testservice2, NULL, NULL, (void **)&unk);
1028 ok(hr == 0x83eddead, "Unexpected return value %#x.\n", hr);
1029 ok(unk == (void *)0xdeadbeef, "Unexpected out object.\n");
1032 static void test_sequencer_source(void)
1034 IMFSequencerSource *seq_source;
1035 HRESULT hr;
1037 hr = MFStartup(MF_VERSION, MFSTARTUP_FULL);
1038 ok(hr == S_OK, "Startup failure, hr %#x.\n", hr);
1040 hr = MFCreateSequencerSource(NULL, &seq_source);
1041 ok(hr == S_OK, "Failed to create sequencer source, hr %#x.\n", hr);
1043 check_interface(seq_source, &IID_IMFMediaSourceTopologyProvider, TRUE);
1045 IMFSequencerSource_Release(seq_source);
1047 hr = MFShutdown();
1048 ok(hr == S_OK, "Shutdown failure, hr %#x.\n", hr);
1051 struct test_callback
1053 IMFAsyncCallback IMFAsyncCallback_iface;
1056 static HRESULT WINAPI testcallback_QueryInterface(IMFAsyncCallback *iface, REFIID riid, void **obj)
1058 if (IsEqualIID(riid, &IID_IMFAsyncCallback) ||
1059 IsEqualIID(riid, &IID_IUnknown))
1061 *obj = iface;
1062 IMFAsyncCallback_AddRef(iface);
1063 return S_OK;
1066 *obj = NULL;
1067 return E_NOINTERFACE;
1070 static ULONG WINAPI testcallback_AddRef(IMFAsyncCallback *iface)
1072 return 2;
1075 static ULONG WINAPI testcallback_Release(IMFAsyncCallback *iface)
1077 return 1;
1080 static HRESULT WINAPI testcallback_GetParameters(IMFAsyncCallback *iface, DWORD *flags, DWORD *queue)
1082 ok(flags != NULL && queue != NULL, "Unexpected arguments.\n");
1083 return E_NOTIMPL;
1086 static HRESULT WINAPI testcallback_Invoke(IMFAsyncCallback *iface, IMFAsyncResult *result)
1088 ok(result != NULL, "Unexpected result object.\n");
1090 return E_NOTIMPL;
1093 static const IMFAsyncCallbackVtbl testcallbackvtbl =
1095 testcallback_QueryInterface,
1096 testcallback_AddRef,
1097 testcallback_Release,
1098 testcallback_GetParameters,
1099 testcallback_Invoke,
1102 static void init_test_callback(struct test_callback *callback)
1104 callback->IMFAsyncCallback_iface.lpVtbl = &testcallbackvtbl;
1107 static void test_session_events(IMFMediaSession *session)
1109 struct test_callback callback, callback2;
1110 IMFAsyncResult *result;
1111 IMFMediaEvent *event;
1112 HRESULT hr;
1114 init_test_callback(&callback);
1115 init_test_callback(&callback2);
1117 hr = IMFMediaSession_GetEvent(session, MF_EVENT_FLAG_NO_WAIT, &event);
1118 ok(hr == MF_E_NO_EVENTS_AVAILABLE, "Unexpected hr %#x.\n", hr);
1120 /* Async case. */
1121 hr = IMFMediaSession_BeginGetEvent(session, NULL, NULL);
1122 ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
1124 hr = IMFMediaSession_BeginGetEvent(session, &callback.IMFAsyncCallback_iface, (IUnknown *)session);
1125 ok(hr == S_OK, "Failed to Begin*, hr %#x.\n", hr);
1127 /* Same callback, same state. */
1128 hr = IMFMediaSession_BeginGetEvent(session, &callback.IMFAsyncCallback_iface, (IUnknown *)session);
1129 ok(hr == MF_S_MULTIPLE_BEGIN, "Unexpected hr %#x.\n", hr);
1131 /* Same callback, different state. */
1132 hr = IMFMediaSession_BeginGetEvent(session, &callback.IMFAsyncCallback_iface, (IUnknown *)&callback);
1133 ok(hr == MF_E_MULTIPLE_BEGIN, "Unexpected hr %#x.\n", hr);
1135 /* Different callback, same state. */
1136 hr = IMFMediaSession_BeginGetEvent(session, &callback2.IMFAsyncCallback_iface, (IUnknown *)session);
1137 ok(hr == MF_E_MULTIPLE_SUBSCRIBERS, "Unexpected hr %#x.\n", hr);
1139 /* Different callback, different state. */
1140 hr = IMFMediaSession_BeginGetEvent(session, &callback2.IMFAsyncCallback_iface, (IUnknown *)&callback.IMFAsyncCallback_iface);
1141 ok(hr == MF_E_MULTIPLE_SUBSCRIBERS, "Unexpected hr %#x.\n", hr);
1143 hr = MFCreateAsyncResult(NULL, &callback.IMFAsyncCallback_iface, NULL, &result);
1144 ok(hr == S_OK, "Failed to create result, hr %#x.\n", hr);
1146 hr = IMFMediaSession_EndGetEvent(session, result, &event);
1147 ok(hr == E_FAIL, "Unexpected hr %#x.\n", hr);
1149 /* Shutdown behavior. */
1150 hr = IMFMediaSession_Shutdown(session);
1151 ok(hr == S_OK, "Failed to shut down, hr %#x.\n", hr);
1154 static void test_media_session(void)
1156 IMFRateControl *rate_control, *rate_control2;
1157 MFCLOCK_PROPERTIES clock_props;
1158 IMFRateSupport *rate_support;
1159 IMFAttributes *attributes;
1160 IMFMediaSession *session;
1161 IMFTopology *topology;
1162 IMFShutdown *shutdown;
1163 PROPVARIANT propvar;
1164 DWORD status, caps;
1165 IMFClock *clock;
1166 IUnknown *unk;
1167 HRESULT hr;
1168 float rate;
1169 BOOL thin;
1171 hr = MFStartup(MF_VERSION, MFSTARTUP_FULL);
1172 ok(hr == S_OK, "Startup failure, hr %#x.\n", hr);
1174 hr = MFCreateMediaSession(NULL, &session);
1175 ok(hr == S_OK, "Failed to create media session, hr %#x.\n", hr);
1177 check_interface(session, &IID_IMFGetService, TRUE);
1178 check_interface(session, &IID_IMFAttributes, FALSE);
1179 check_interface(session, &IID_IMFTopologyNodeAttributeEditor, FALSE);
1181 hr = MFGetService((IUnknown *)session, &MF_TOPONODE_ATTRIBUTE_EDITOR_SERVICE, &IID_IMFTopologyNodeAttributeEditor,
1182 (void **)&unk);
1183 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
1185 check_interface(unk, &IID_IMFMediaSession, FALSE);
1187 IUnknown_Release(unk);
1189 hr = MFGetService((IUnknown *)session, &MF_RATE_CONTROL_SERVICE, &IID_IMFRateSupport, (void **)&rate_support);
1190 ok(hr == S_OK, "Failed to get rate support interface, hr %#x.\n", hr);
1192 hr = MFGetService((IUnknown *)session, &MF_RATE_CONTROL_SERVICE, &IID_IMFRateControl, (void **)&rate_control);
1193 ok(hr == S_OK, "Failed to get rate control interface, hr %#x.\n", hr);
1195 hr = MFGetService((IUnknown *)session, &MF_LOCAL_MFT_REGISTRATION_SERVICE, &IID_IMFLocalMFTRegistration, (void **)&unk);
1196 ok(hr == S_OK || broken(hr == E_NOINTERFACE) /* Vista */, "Failed to get registration service, hr %#x.\n", hr);
1197 if (SUCCEEDED(hr))
1198 IUnknown_Release(unk);
1200 hr = IMFRateSupport_QueryInterface(rate_support, &IID_IMFMediaSession, (void **)&unk);
1201 ok(hr == S_OK, "Failed to get session interface, hr %#x.\n", hr);
1202 ok(unk == (IUnknown *)session, "Unexpected pointer.\n");
1203 IUnknown_Release(unk);
1205 hr = IMFRateControl_GetRate(rate_control, NULL, NULL);
1206 ok(FAILED(hr), "Unexpected hr %#x.\n", hr);
1208 rate = 0.0f;
1209 hr = IMFRateControl_GetRate(rate_control, NULL, &rate);
1210 ok(hr == S_OK, "Failed to get playback rate, hr %#x.\n", hr);
1211 ok(rate == 1.0f, "Unexpected rate %f.\n", rate);
1213 hr = IMFRateControl_GetRate(rate_control, &thin, NULL);
1214 ok(FAILED(hr), "Unexpected hr %#x.\n", hr);
1216 thin = TRUE;
1217 rate = 0.0f;
1218 hr = IMFRateControl_GetRate(rate_control, &thin, &rate);
1219 ok(hr == S_OK, "Failed to get playback rate, hr %#x.\n", hr);
1220 ok(!thin, "Unexpected thinning.\n");
1221 ok(rate == 1.0f, "Unexpected rate %f.\n", rate);
1223 hr = IMFMediaSession_GetClock(session, &clock);
1224 ok(hr == S_OK, "Failed to get clock, hr %#x.\n", hr);
1226 check_interface(clock, &IID_IMFPresentationClock, TRUE);
1228 hr = IMFClock_QueryInterface(clock, &IID_IMFRateControl, (void **)&rate_control2);
1229 ok(hr == S_OK, "Failed to get rate control, hr %#x.\n", hr);
1231 rate = 0.0f;
1232 hr = IMFRateControl_GetRate(rate_control2, NULL, &rate);
1233 ok(hr == S_OK, "Failed to get clock rate, hr %#x.\n", hr);
1234 ok(rate == 1.0f, "Unexpected rate %f.\n", rate);
1236 hr = IMFRateControl_SetRate(rate_control, FALSE, 1.5f);
1237 todo_wine
1238 ok(hr == S_OK, "Failed to set rate, hr %#x.\n", hr);
1240 IMFRateControl_Release(rate_control2);
1242 hr = IMFClock_GetProperties(clock, &clock_props);
1243 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#x.\n", hr);
1244 IMFClock_Release(clock);
1246 IMFRateControl_Release(rate_control);
1247 IMFRateSupport_Release(rate_support);
1249 IMFMediaSession_Release(session);
1251 hr = MFCreateMediaSession(NULL, &session);
1252 ok(hr == S_OK, "Failed to create media session, hr %#x.\n", hr);
1254 hr = IMFMediaSession_GetClock(session, &clock);
1255 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
1257 hr = IMFClock_QueryInterface(clock, &IID_IMFShutdown, (void **)&shutdown);
1258 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
1260 hr = IMFShutdown_GetShutdownStatus(shutdown, &status);
1261 ok(hr == MF_E_INVALIDREQUEST, "Unexpected hr %#x.\n", hr);
1263 hr = IMFMediaSession_Shutdown(session);
1264 ok(hr == S_OK, "Failed to shut down, hr %#x.\n", hr);
1266 hr = IMFShutdown_GetShutdownStatus(shutdown, &status);
1267 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
1268 ok(status == MFSHUTDOWN_COMPLETED, "Unexpected shutdown status %u.\n", status);
1270 IMFShutdown_Release(shutdown);
1272 hr = IMFMediaSession_ClearTopologies(session);
1273 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr);
1275 hr = IMFMediaSession_Start(session, &GUID_NULL, NULL);
1276 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
1278 propvar.vt = VT_EMPTY;
1279 hr = IMFMediaSession_Start(session, &GUID_NULL, &propvar);
1280 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr);
1282 hr = IMFMediaSession_Pause(session);
1283 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr);
1285 hr = IMFMediaSession_Stop(session);
1286 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr);
1288 hr = IMFMediaSession_Close(session);
1289 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr);
1291 hr = IMFMediaSession_GetClock(session, &clock);
1292 ok(hr == MF_E_SHUTDOWN || broken(hr == E_UNEXPECTED) /* Win7 */, "Unexpected hr %#x.\n", hr);
1294 hr = IMFMediaSession_GetSessionCapabilities(session, &caps);
1295 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr);
1297 hr = IMFMediaSession_GetSessionCapabilities(session, NULL);
1298 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
1300 hr = IMFMediaSession_GetFullTopology(session, MFSESSION_GETFULLTOPOLOGY_CURRENT, 0, &topology);
1301 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr);
1303 hr = IMFMediaSession_Shutdown(session);
1304 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr);
1306 IMFMediaSession_Release(session);
1308 /* Custom topology loader, GUID is not registered. */
1309 hr = MFCreateAttributes(&attributes, 1);
1310 ok(hr == S_OK, "Failed to create attributes, hr %#x.\n", hr);
1312 hr = IMFAttributes_SetGUID(attributes, &MF_SESSION_TOPOLOADER, &MF_SESSION_TOPOLOADER);
1313 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
1315 hr = MFCreateMediaSession(attributes, &session);
1316 ok(hr == S_OK, "Failed to create media session, hr %#x.\n", hr);
1317 IMFMediaSession_Release(session);
1319 /* Disabled quality manager. */
1320 hr = IMFAttributes_SetGUID(attributes, &MF_SESSION_QUALITY_MANAGER, &GUID_NULL);
1321 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
1323 hr = MFCreateMediaSession(attributes, &session);
1324 ok(hr == S_OK, "Failed to create media session, hr %#x.\n", hr);
1325 IMFMediaSession_Release(session);
1327 IMFAttributes_Release(attributes);
1329 /* Basic events behavior. */
1330 hr = MFCreateMediaSession(NULL, &session);
1331 ok(hr == S_OK, "Failed to create media session, hr %#x.\n", hr);
1333 test_session_events(session);
1335 IMFMediaSession_Release(session);
1337 hr = MFShutdown();
1338 ok(hr == S_OK, "Shutdown failure, hr %#x.\n", hr);
1341 static HRESULT WINAPI test_grabber_callback_QueryInterface(IMFSampleGrabberSinkCallback *iface, REFIID riid,
1342 void **obj)
1344 if (IsEqualIID(riid, &IID_IMFSampleGrabberSinkCallback) ||
1345 IsEqualIID(riid, &IID_IMFClockStateSink) ||
1346 IsEqualIID(riid, &IID_IUnknown))
1348 *obj = iface;
1349 IMFSampleGrabberSinkCallback_AddRef(iface);
1350 return S_OK;
1353 *obj = NULL;
1354 return E_NOINTERFACE;
1357 static ULONG WINAPI test_grabber_callback_AddRef(IMFSampleGrabberSinkCallback *iface)
1359 return 2;
1362 static ULONG WINAPI test_grabber_callback_Release(IMFSampleGrabberSinkCallback *iface)
1364 return 1;
1367 static HRESULT WINAPI test_grabber_callback_OnClockStart(IMFSampleGrabberSinkCallback *iface, MFTIME systime,
1368 LONGLONG offset)
1370 return E_NOTIMPL;
1373 static HRESULT WINAPI test_grabber_callback_OnClockStop(IMFSampleGrabberSinkCallback *iface, MFTIME systime)
1375 return E_NOTIMPL;
1378 static HRESULT WINAPI test_grabber_callback_OnClockPause(IMFSampleGrabberSinkCallback *iface, MFTIME systime)
1380 return E_NOTIMPL;
1383 static HRESULT WINAPI test_grabber_callback_OnClockRestart(IMFSampleGrabberSinkCallback *iface, MFTIME systime)
1385 return E_NOTIMPL;
1388 static HRESULT WINAPI test_grabber_callback_OnClockSetRate(IMFSampleGrabberSinkCallback *iface, MFTIME systime, float rate)
1390 return E_NOTIMPL;
1393 static HRESULT WINAPI test_grabber_callback_OnSetPresentationClock(IMFSampleGrabberSinkCallback *iface,
1394 IMFPresentationClock *clock)
1396 return E_NOTIMPL;
1399 static HRESULT WINAPI test_grabber_callback_OnProcessSample(IMFSampleGrabberSinkCallback *iface, REFGUID major_type,
1400 DWORD sample_flags, LONGLONG sample_time, LONGLONG sample_duration, const BYTE *buffer, DWORD sample_size)
1402 return E_NOTIMPL;
1405 static HRESULT WINAPI test_grabber_callback_OnShutdown(IMFSampleGrabberSinkCallback *iface)
1407 return E_NOTIMPL;
1410 static const IMFSampleGrabberSinkCallbackVtbl test_grabber_callback_vtbl =
1412 test_grabber_callback_QueryInterface,
1413 test_grabber_callback_AddRef,
1414 test_grabber_callback_Release,
1415 test_grabber_callback_OnClockStart,
1416 test_grabber_callback_OnClockStop,
1417 test_grabber_callback_OnClockPause,
1418 test_grabber_callback_OnClockRestart,
1419 test_grabber_callback_OnClockSetRate,
1420 test_grabber_callback_OnSetPresentationClock,
1421 test_grabber_callback_OnProcessSample,
1422 test_grabber_callback_OnShutdown,
1425 struct test_source
1427 IMFMediaSource IMFMediaSource_iface;
1428 LONG refcount;
1431 static struct test_source *impl_from_IMFMediaSource(IMFMediaSource *iface)
1433 return CONTAINING_RECORD(iface, struct test_source, IMFMediaSource_iface);
1436 static HRESULT WINAPI test_source_QueryInterface(IMFMediaSource *iface, REFIID riid, void **out)
1438 if (IsEqualIID(riid, &IID_IMFMediaSource)
1439 || IsEqualIID(riid, &IID_IMFMediaEventGenerator)
1440 || IsEqualIID(riid, &IID_IUnknown))
1442 *out = iface;
1444 else
1446 *out = NULL;
1447 return E_NOINTERFACE;
1450 IMFMediaSource_AddRef(iface);
1451 return S_OK;
1454 static ULONG WINAPI test_source_AddRef(IMFMediaSource *iface)
1456 struct test_source *source = impl_from_IMFMediaSource(iface);
1457 return InterlockedIncrement(&source->refcount);
1460 static ULONG WINAPI test_source_Release(IMFMediaSource *iface)
1462 struct test_source *source = impl_from_IMFMediaSource(iface);
1463 ULONG refcount = InterlockedDecrement(&source->refcount);
1465 if (!refcount)
1466 HeapFree(GetProcessHeap(), 0, source);
1468 return refcount;
1471 static HRESULT WINAPI test_source_GetEvent(IMFMediaSource *iface, DWORD flags, IMFMediaEvent **event)
1473 ok(0, "Unexpected call.\n");
1474 return E_NOTIMPL;
1477 static HRESULT WINAPI test_source_BeginGetEvent(IMFMediaSource *iface, IMFAsyncCallback *callback, IUnknown *state)
1479 ok(0, "Unexpected call.\n");
1480 return E_NOTIMPL;
1483 static HRESULT WINAPI test_source_EndGetEvent(IMFMediaSource *iface, IMFAsyncResult *result, IMFMediaEvent **event)
1485 ok(0, "Unexpected call.\n");
1486 return E_NOTIMPL;
1489 static HRESULT WINAPI test_source_QueueEvent(IMFMediaSource *iface, MediaEventType event_type, REFGUID ext_type,
1490 HRESULT hr, const PROPVARIANT *value)
1492 ok(0, "Unexpected call.\n");
1493 return E_NOTIMPL;
1496 static HRESULT WINAPI test_source_GetCharacteristics(IMFMediaSource *iface, DWORD *flags)
1498 ok(0, "Unexpected call.\n");
1499 return E_NOTIMPL;
1502 static HRESULT WINAPI test_source_CreatePresentationDescriptor(IMFMediaSource *iface, IMFPresentationDescriptor **pd)
1504 ok(0, "Unexpected call.\n");
1505 return E_NOTIMPL;
1508 static HRESULT WINAPI test_source_Start(IMFMediaSource *iface, IMFPresentationDescriptor *pd, const GUID *time_format,
1509 const PROPVARIANT *start_position)
1511 ok(0, "Unexpected call.\n");
1512 return E_NOTIMPL;
1515 static HRESULT WINAPI test_source_Stop(IMFMediaSource *iface)
1517 ok(0, "Unexpected call.\n");
1518 return E_NOTIMPL;
1521 static HRESULT WINAPI test_source_Pause(IMFMediaSource *iface)
1523 ok(0, "Unexpected call.\n");
1524 return E_NOTIMPL;
1527 static HRESULT WINAPI test_source_Shutdown(IMFMediaSource *iface)
1529 ok(0, "Unexpected call.\n");
1530 return E_NOTIMPL;
1533 static const IMFMediaSourceVtbl test_source_vtbl =
1535 test_source_QueryInterface,
1536 test_source_AddRef,
1537 test_source_Release,
1538 test_source_GetEvent,
1539 test_source_BeginGetEvent,
1540 test_source_EndGetEvent,
1541 test_source_QueueEvent,
1542 test_source_GetCharacteristics,
1543 test_source_CreatePresentationDescriptor,
1544 test_source_Start,
1545 test_source_Stop,
1546 test_source_Pause,
1547 test_source_Shutdown,
1550 static IMFMediaSource *create_test_source(void)
1552 struct test_source *source;
1554 source = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*source));
1555 source->IMFMediaSource_iface.lpVtbl = &test_source_vtbl;
1556 source->refcount = 1;
1558 return &source->IMFMediaSource_iface;
1561 struct type_attr
1563 const GUID *key;
1564 unsigned int value;
1567 static void init_media_type(IMFMediaType *mediatype, const GUID *major, const struct type_attr *attrs)
1569 HRESULT hr;
1571 hr = IMFMediaType_DeleteAllItems(mediatype);
1572 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
1574 hr = IMFMediaType_SetGUID(mediatype, &MF_MT_MAJOR_TYPE, major);
1575 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
1577 while (attrs->key)
1579 if (IsEqualGUID(attrs->key, &MF_MT_SUBTYPE))
1581 GUID subtype;
1583 memcpy(&subtype, IsEqualGUID(major, &MFMediaType_Audio) ? &MFAudioFormat_Base : &MFVideoFormat_Base,
1584 sizeof(subtype));
1585 subtype.Data1 = attrs->value;
1586 hr = IMFMediaType_SetGUID(mediatype, attrs->key, &subtype);
1588 else
1589 hr = IMFMediaType_SetUINT32(mediatype, attrs->key, attrs->value);
1590 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
1592 attrs++;
1596 static void init_source_node(IMFMediaType *mediatype, IMFMediaSource *source, IMFTopologyNode *node)
1598 IMFPresentationDescriptor *pd;
1599 IMFMediaTypeHandler *handler;
1600 IMFStreamDescriptor *sd;
1601 HRESULT hr;
1603 hr = IMFTopologyNode_DeleteAllItems(node);
1604 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
1606 hr = MFCreateStreamDescriptor(0, 1, &mediatype, &sd);
1607 ok(hr == S_OK, "Failed to create stream descriptor, hr %#x.\n", hr);
1609 hr = IMFStreamDescriptor_GetMediaTypeHandler(sd, &handler);
1610 ok(hr == S_OK, "Failed to get media type handler, hr %#x.\n", hr);
1612 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, mediatype);
1613 ok(hr == S_OK, "Failed to set current media type, hr %#x.\n", hr);
1615 IMFMediaTypeHandler_Release(handler);
1617 hr = MFCreatePresentationDescriptor(1, &sd, &pd);
1618 ok(hr == S_OK, "Failed to create presentation descriptor, hr %#x.\n", hr);
1620 hr = IMFTopologyNode_SetUnknown(node, &MF_TOPONODE_PRESENTATION_DESCRIPTOR, (IUnknown *)pd);
1621 ok(hr == S_OK, "Failed to set node pd, hr %#x.\n", hr);
1623 IMFPresentationDescriptor_Release(pd);
1625 hr = IMFTopologyNode_SetUnknown(node, &MF_TOPONODE_STREAM_DESCRIPTOR, (IUnknown *)sd);
1626 ok(hr == S_OK, "Failed to set node sd, hr %#x.\n", hr);
1628 if (source)
1630 hr = IMFTopologyNode_SetUnknown(node, &MF_TOPONODE_SOURCE, (IUnknown *)source);
1631 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
1634 IMFStreamDescriptor_Release(sd);
1637 static void init_sink_node(IMFActivate *sink_activate, unsigned int method, IMFTopologyNode *node)
1639 IMFStreamSink *stream_sink;
1640 IMFMediaSink *sink;
1641 HRESULT hr;
1643 hr = IMFTopologyNode_DeleteAllItems(node);
1644 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
1646 hr = IMFActivate_ActivateObject(sink_activate, &IID_IMFMediaSink, (void **)&sink);
1647 ok(hr == S_OK, "Failed to activate, hr %#x.\n", hr);
1649 hr = IMFMediaSink_GetStreamSinkByIndex(sink, 0, &stream_sink);
1650 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
1652 IMFMediaSink_Release(sink);
1654 hr = IMFTopologyNode_SetObject(node, (IUnknown *)stream_sink);
1655 ok(hr == S_OK, "Failed to set object, hr %#x.\n", hr);
1657 IMFStreamSink_Release(stream_sink);
1659 hr = IMFTopologyNode_SetUINT32(node, &MF_TOPONODE_CONNECT_METHOD, method);
1660 ok(hr == S_OK, "Failed to set connect method, hr %#x.\n", hr);
1663 enum loader_test_flags
1665 LOADER_EXPECTED_DECODER = 0x1,
1666 LOADER_EXPECTED_CONVERTER = 0x2,
1667 LOADER_TODO = 0x4,
1670 static void test_topology_loader(void)
1672 static const struct loader_test
1674 const GUID *major;
1675 struct
1677 struct type_attr attrs[8];
1678 } input_type;
1679 struct
1681 struct type_attr attrs[8];
1682 } output_type;
1684 MF_CONNECT_METHOD method;
1685 HRESULT expected_result;
1686 unsigned int flags;
1688 loader_tests[] =
1691 /* PCM -> PCM, same type */
1692 &MFMediaType_Audio,
1695 { &MF_MT_SUBTYPE, WAVE_FORMAT_PCM },
1696 { &MF_MT_AUDIO_NUM_CHANNELS, 1 },
1697 { &MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100 },
1698 { &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 44100 },
1699 { &MF_MT_AUDIO_BLOCK_ALIGNMENT, 1 },
1700 { &MF_MT_AUDIO_BITS_PER_SAMPLE, 8 },
1705 { &MF_MT_SUBTYPE, WAVE_FORMAT_PCM },
1706 { &MF_MT_AUDIO_NUM_CHANNELS, 1 },
1707 { &MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100 },
1708 { &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 44100 },
1709 { &MF_MT_AUDIO_BLOCK_ALIGNMENT, 1 },
1710 { &MF_MT_AUDIO_BITS_PER_SAMPLE, 8 },
1714 MF_CONNECT_DIRECT,
1715 S_OK,
1719 /* PCM -> PCM, different bps. */
1720 &MFMediaType_Audio,
1723 { &MF_MT_SUBTYPE, WAVE_FORMAT_PCM },
1724 { &MF_MT_AUDIO_NUM_CHANNELS, 1 },
1725 { &MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100 },
1726 { &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 44100 },
1727 { &MF_MT_AUDIO_BLOCK_ALIGNMENT, 1 },
1728 { &MF_MT_AUDIO_BITS_PER_SAMPLE, 8 },
1733 { &MF_MT_SUBTYPE, WAVE_FORMAT_PCM },
1734 { &MF_MT_AUDIO_NUM_CHANNELS, 1 },
1735 { &MF_MT_AUDIO_SAMPLES_PER_SECOND, 48000 },
1736 { &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 48000 },
1737 { &MF_MT_AUDIO_BLOCK_ALIGNMENT, 1 },
1738 { &MF_MT_AUDIO_BITS_PER_SAMPLE, 8 },
1742 MF_CONNECT_DIRECT,
1743 MF_E_INVALIDMEDIATYPE,
1747 /* PCM -> PCM, different bps. */
1748 &MFMediaType_Audio,
1751 { &MF_MT_SUBTYPE, WAVE_FORMAT_PCM },
1752 { &MF_MT_AUDIO_NUM_CHANNELS, 1 },
1753 { &MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100 },
1754 { &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 44100 },
1755 { &MF_MT_AUDIO_BLOCK_ALIGNMENT, 1 },
1756 { &MF_MT_AUDIO_BITS_PER_SAMPLE, 8 },
1761 { &MF_MT_SUBTYPE, WAVE_FORMAT_PCM },
1762 { &MF_MT_AUDIO_NUM_CHANNELS, 1 },
1763 { &MF_MT_AUDIO_SAMPLES_PER_SECOND, 48000 },
1764 { &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 48000 },
1765 { &MF_MT_AUDIO_BLOCK_ALIGNMENT, 1 },
1766 { &MF_MT_AUDIO_BITS_PER_SAMPLE, 8 },
1770 MF_CONNECT_ALLOW_CONVERTER,
1771 S_OK,
1772 LOADER_EXPECTED_CONVERTER | LOADER_TODO,
1776 /* MP3 -> PCM */
1777 &MFMediaType_Audio,
1780 { &MF_MT_SUBTYPE, WAVE_FORMAT_MPEGLAYER3 },
1781 { &MF_MT_AUDIO_NUM_CHANNELS, 2 },
1782 { &MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100 },
1783 { &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 16000 },
1784 { &MF_MT_AUDIO_BLOCK_ALIGNMENT, 1 },
1789 { &MF_MT_SUBTYPE, WAVE_FORMAT_PCM },
1790 { &MF_MT_AUDIO_NUM_CHANNELS, 1 },
1791 { &MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100 },
1792 { &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 44100 },
1793 { &MF_MT_AUDIO_BLOCK_ALIGNMENT, 1 },
1794 { &MF_MT_AUDIO_BITS_PER_SAMPLE, 8 },
1798 MF_CONNECT_DIRECT,
1799 MF_E_INVALIDMEDIATYPE,
1803 /* MP3 -> PCM */
1804 &MFMediaType_Audio,
1807 { &MF_MT_SUBTYPE, WAVE_FORMAT_MPEGLAYER3 },
1808 { &MF_MT_AUDIO_NUM_CHANNELS, 2 },
1809 { &MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100 },
1810 { &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 16000 },
1811 { &MF_MT_AUDIO_BLOCK_ALIGNMENT, 1 },
1816 { &MF_MT_SUBTYPE, WAVE_FORMAT_PCM },
1817 { &MF_MT_AUDIO_NUM_CHANNELS, 1 },
1818 { &MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100 },
1819 { &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 44100 },
1820 { &MF_MT_AUDIO_BLOCK_ALIGNMENT, 1 },
1821 { &MF_MT_AUDIO_BITS_PER_SAMPLE, 8 },
1825 MF_CONNECT_ALLOW_CONVERTER,
1826 MF_E_TRANSFORM_NOT_POSSIBLE_FOR_CURRENT_MEDIATYPE_COMBINATION,
1827 LOADER_TODO,
1831 /* MP3 -> PCM */
1832 &MFMediaType_Audio,
1835 { &MF_MT_SUBTYPE, WAVE_FORMAT_MPEGLAYER3 },
1836 { &MF_MT_AUDIO_NUM_CHANNELS, 2 },
1837 { &MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100 },
1838 { &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 16000 },
1839 { &MF_MT_AUDIO_BLOCK_ALIGNMENT, 1 },
1844 { &MF_MT_SUBTYPE, WAVE_FORMAT_PCM },
1845 { &MF_MT_AUDIO_NUM_CHANNELS, 1 },
1846 { &MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100 },
1847 { &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 44100 },
1848 { &MF_MT_AUDIO_BLOCK_ALIGNMENT, 1 },
1849 { &MF_MT_AUDIO_BITS_PER_SAMPLE, 8 },
1853 MF_CONNECT_ALLOW_DECODER,
1854 S_OK,
1855 LOADER_EXPECTED_DECODER | LOADER_TODO,
1859 IMFSampleGrabberSinkCallback test_grabber_callback = { &test_grabber_callback_vtbl };
1860 IMFTopologyNode *src_node, *sink_node, *src_node2, *sink_node2, *mft_node;
1861 IMFTopology *topology, *topology2, *full_topology;
1862 IMFMediaType *media_type, *input_type, *output_type;
1863 unsigned int i, count, value, index;
1864 IMFPresentationDescriptor *pd;
1865 IMFActivate *sink_activate;
1866 MF_TOPOLOGY_TYPE node_type;
1867 IMFStreamDescriptor *sd;
1868 IMFTransform *transform;
1869 IMFMediaSource *source;
1870 IMFTopoLoader *loader;
1871 IUnknown *node_object;
1872 WORD node_count;
1873 TOPOID node_id;
1874 HRESULT hr;
1875 BOOL ret;
1877 hr = MFStartup(MF_VERSION, MFSTARTUP_FULL);
1878 ok(hr == S_OK, "Startup failure, hr %#x.\n", hr);
1880 hr = MFCreateTopoLoader(NULL);
1881 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
1883 hr = MFCreateTopoLoader(&loader);
1884 ok(hr == S_OK, "Failed to create topology loader, hr %#x.\n", hr);
1886 hr = MFCreateTopology(&topology);
1887 ok(hr == S_OK, "Failed to create topology, hr %#x.\n", hr);
1889 /* Empty topology */
1890 hr = IMFTopoLoader_Load(loader, topology, &full_topology, NULL);
1891 todo_wine
1892 ok(hr == MF_E_TOPO_UNSUPPORTED, "Unexpected hr %#x.\n", hr);
1894 /* Add source node. */
1895 hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &src_node);
1896 ok(hr == S_OK, "Failed to create topology node, hr %#x.\n", hr);
1898 /* When a decoder is involved, windows requires this attribute to be present */
1899 source = create_test_source();
1901 hr = IMFTopologyNode_SetUnknown(src_node, &MF_TOPONODE_SOURCE, (IUnknown *)source);
1902 ok(hr == S_OK, "Failed to set node source, hr %#x.\n", hr);
1904 hr = MFCreateMediaType(&media_type);
1905 ok(hr == S_OK, "Failed to create media type, hr %#x.\n", hr);
1907 hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio);
1908 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
1909 hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFAudioFormat_PCM);
1910 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
1912 hr = MFCreateStreamDescriptor(0, 1, &media_type, &sd);
1913 ok(hr == S_OK, "Failed to create stream descriptor, hr %#x.\n", hr);
1915 hr = IMFTopologyNode_SetUnknown(src_node, &MF_TOPONODE_STREAM_DESCRIPTOR, (IUnknown *)sd);
1916 ok(hr == S_OK, "Failed to set node sd, hr %#x.\n", hr);
1918 hr = MFCreatePresentationDescriptor(1, &sd, &pd);
1919 ok(hr == S_OK, "Failed to create presentation descriptor, hr %#x.\n", hr);
1921 hr = IMFTopologyNode_SetUnknown(src_node, &MF_TOPONODE_PRESENTATION_DESCRIPTOR, (IUnknown *)pd);
1922 ok(hr == S_OK, "Failed to set node pd, hr %#x.\n", hr);
1924 IMFPresentationDescriptor_Release(pd);
1925 IMFStreamDescriptor_Release(sd);
1926 IMFMediaType_Release(media_type);
1928 hr = IMFTopology_AddNode(topology, src_node);
1929 ok(hr == S_OK, "Failed to add a node, hr %#x.\n", hr);
1931 /* Source node only. */
1932 hr = IMFTopoLoader_Load(loader, topology, &full_topology, NULL);
1933 todo_wine
1934 ok(hr == MF_E_TOPO_UNSUPPORTED, "Unexpected hr %#x.\n", hr);
1936 hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, &sink_node);
1937 ok(hr == S_OK, "Failed to create output node, hr %#x.\n", hr);
1939 hr = MFCreateMediaType(&media_type);
1940 ok(hr == S_OK, "Failed to create media type, hr %#x.\n", hr);
1942 hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio);
1943 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
1944 hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFAudioFormat_PCM);
1945 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
1947 hr = MFCreateSampleGrabberSinkActivate(media_type, &test_grabber_callback, &sink_activate);
1948 ok(hr == S_OK, "Failed to create grabber sink, hr %#x.\n", hr);
1950 hr = IMFTopologyNode_SetObject(sink_node, (IUnknown *)sink_activate);
1951 ok(hr == S_OK, "Failed to set object, hr %#x.\n", hr);
1953 IMFMediaType_Release(media_type);
1955 hr = IMFTopology_AddNode(topology, sink_node);
1956 ok(hr == S_OK, "Failed to add sink node, hr %#x.\n", hr);
1958 hr = IMFTopoLoader_Load(loader, topology, &full_topology, NULL);
1959 todo_wine
1960 ok(hr == MF_E_TOPO_UNSUPPORTED, "Unexpected hr %#x.\n", hr);
1962 hr = IMFTopologyNode_ConnectOutput(src_node, 0, sink_node, 0);
1963 ok(hr == S_OK, "Failed to connect nodes, hr %#x.\n", hr);
1965 /* Sink was not resolved. */
1966 hr = IMFTopoLoader_Load(loader, topology, &full_topology, NULL);
1967 ok(hr == MF_E_TOPO_SINK_ACTIVATES_UNSUPPORTED, "Unexpected hr %#x.\n", hr);
1969 hr = MFCreateMediaType(&input_type);
1970 ok(hr == S_OK, "Failed to create media type, hr %#x.\n", hr);
1972 hr = MFCreateMediaType(&output_type);
1973 ok(hr == S_OK, "Failed to create media type, hr %#x.\n", hr);
1975 for (i = 0; i < ARRAY_SIZE(loader_tests); ++i)
1977 const struct loader_test *test = &loader_tests[i];
1979 init_media_type(input_type, test->major, test->input_type.attrs);
1980 init_media_type(output_type, test->major, test->output_type.attrs);
1982 hr = MFCreateSampleGrabberSinkActivate(output_type, &test_grabber_callback, &sink_activate);
1983 ok(hr == S_OK, "Failed to create grabber sink, hr %#x.\n", hr);
1985 init_source_node(input_type, source, src_node);
1986 init_sink_node(sink_activate, test->method, sink_node);
1988 hr = IMFTopology_GetCount(topology, &count);
1989 ok(hr == S_OK, "Failed to get attribute count, hr %#x.\n", hr);
1990 ok(!count, "Unexpected count %u.\n", count);
1992 hr = IMFTopoLoader_Load(loader, topology, &full_topology, NULL);
1993 todo_wine_if(test->flags & LOADER_TODO)
1994 ok(hr == test->expected_result, "Unexpected hr %#x on test %u.\n", hr, i);
1995 ok(full_topology != topology, "Unexpected instance.\n");
1997 if (test->expected_result == S_OK && hr == S_OK)
1999 hr = IMFTopology_GetCount(full_topology, &count);
2000 ok(hr == S_OK, "Failed to get attribute count, hr %#x.\n", hr);
2001 todo_wine
2002 ok(count == 1, "Unexpected count %u.\n", count);
2004 value = 0xdeadbeef;
2005 hr = IMFTopology_GetUINT32(full_topology, &MF_TOPOLOGY_RESOLUTION_STATUS, &value);
2006 todo_wine {
2007 ok(hr == S_OK, "Failed to get attribute, hr %#x.\n", hr);
2008 ok(value == MF_TOPOLOGY_RESOLUTION_SUCCEEDED, "Unexpected value %#x.\n", value);
2010 count = 2;
2011 if (test->flags & LOADER_EXPECTED_DECODER)
2012 count++;
2013 if (test->flags & LOADER_EXPECTED_CONVERTER)
2014 count++;
2016 hr = IMFTopology_GetNodeCount(full_topology, &node_count);
2017 ok(hr == S_OK, "Failed to get node count, hr %#x.\n", hr);
2018 todo_wine_if(test->flags & (LOADER_EXPECTED_CONVERTER | LOADER_EXPECTED_DECODER))
2019 ok(node_count == count, "Unexpected node count %u.\n", node_count);
2021 hr = IMFTopologyNode_GetTopoNodeID(src_node, &node_id);
2022 ok(hr == S_OK, "Failed to get source node id, hr %#x.\n", hr);
2024 hr = IMFTopology_GetNodeByID(full_topology, node_id, &src_node2);
2025 ok(hr == S_OK, "Failed to get source in resolved topology, hr %#x.\n", hr);
2027 hr = IMFTopologyNode_GetTopoNodeID(sink_node, &node_id);
2028 ok(hr == S_OK, "Failed to get sink node id, hr %#x.\n", hr);
2030 hr = IMFTopology_GetNodeByID(full_topology, node_id, &sink_node2);
2031 ok(hr == S_OK, "Failed to get sink in resolved topology, hr %#x.\n", hr);
2033 if (test->flags & (LOADER_EXPECTED_DECODER | LOADER_EXPECTED_CONVERTER) && strcmp(winetest_platform, "wine"))
2035 hr = IMFTopologyNode_GetOutput(src_node2, 0, &mft_node, &index);
2036 ok(hr == S_OK, "Failed to get transform node in resolved topology, hr %#x.\n", hr);
2037 ok(!index, "Unexpected stream index %u.\n", index);
2039 hr = IMFTopologyNode_GetNodeType(mft_node, &node_type);
2040 ok(hr == S_OK, "Failed to get transform node type in resolved topology, hr %#x.\n", hr);
2041 ok(node_type == MF_TOPOLOGY_TRANSFORM_NODE, "Unexpected node type %u.\n", node_type);
2043 hr = IMFTopologyNode_GetObject(mft_node, &node_object);
2044 ok(hr == S_OK, "Failed to get object of transform node, hr %#x.\n", hr);
2046 if (test->flags & LOADER_EXPECTED_DECODER)
2048 value = 0;
2049 hr = IMFTopologyNode_GetUINT32(mft_node, &MF_TOPONODE_DECODER, &value);
2050 ok(hr == S_OK, "Failed to get attribute, hr %#x.\n", hr);
2051 ok(value == 1, "Unexpected value.\n");
2054 hr = IMFTopologyNode_GetItem(mft_node, &MF_TOPONODE_TRANSFORM_OBJECTID, NULL);
2055 ok(hr == S_OK, "Failed to get attribute, hr %#x.\n", hr);
2057 hr = IUnknown_QueryInterface(node_object, &IID_IMFTransform, (void **)&transform);
2058 ok(hr == S_OK, "Failed to get IMFTransform from transform node's object, hr %#x.\n", hr);
2059 IUnknown_Release(node_object);
2061 hr = IMFTransform_GetInputCurrentType(transform, 0, &media_type);
2062 ok(hr == S_OK, "Failed to get transform input type, hr %#x.\n", hr);
2064 hr = IMFMediaType_Compare(input_type, (IMFAttributes *)media_type, MF_ATTRIBUTES_MATCH_OUR_ITEMS, &ret);
2065 ok(hr == S_OK, "Failed to compare media types, hr %#x.\n", hr);
2066 ok(ret, "Input type of first transform doesn't match source node type.\n");
2068 IMFTopologyNode_Release(mft_node);
2069 IMFMediaType_Release(media_type);
2070 IMFTransform_Release(transform);
2072 hr = IMFTopologyNode_GetInput(sink_node2, 0, &mft_node, &index);
2073 ok(hr == S_OK, "Failed to get transform node in resolved topology, hr %#x.\n", hr);
2074 ok(!index, "Unexpected stream index %u.\n", index);
2076 hr = IMFTopologyNode_GetNodeType(mft_node, &node_type);
2077 ok(hr == S_OK, "Failed to get transform node type in resolved topology, hr %#x.\n", hr);
2078 ok(node_type == MF_TOPOLOGY_TRANSFORM_NODE, "Unexpected node type %u.\n", node_type);
2080 hr = IMFTopologyNode_GetItem(mft_node, &MF_TOPONODE_TRANSFORM_OBJECTID, NULL);
2081 ok(hr == S_OK, "Failed to get attribute, hr %#x.\n", hr);
2083 hr = IMFTopologyNode_GetObject(mft_node, &node_object);
2084 ok(hr == S_OK, "Failed to get object of transform node, hr %#x.\n", hr);
2086 hr = IUnknown_QueryInterface(node_object, &IID_IMFTransform, (void**) &transform);
2087 ok(hr == S_OK, "Failed to get IMFTransform from transform node's object, hr %#x.\n", hr);
2088 IUnknown_Release(node_object);
2090 hr = IMFTransform_GetOutputCurrentType(transform, 0, &media_type);
2091 ok(hr == S_OK, "Failed to get transform output type, hr %#x.\n", hr);
2093 hr = IMFMediaType_Compare(output_type, (IMFAttributes *)media_type, MF_ATTRIBUTES_MATCH_OUR_ITEMS, &ret);
2094 ok(hr == S_OK, "Failed to compare media types, hr %#x.\n", hr);
2095 ok(ret, "Output type of last transform doesn't match sink node type.\n");
2097 IMFTopologyNode_Release(mft_node);
2098 IMFMediaType_Release(media_type);
2099 IMFTransform_Release(transform);
2102 IMFTopologyNode_Release(sink_node2);
2104 hr = IMFTopoLoader_Load(loader, full_topology, &topology2, NULL);
2105 ok(hr == S_OK, "Failed to resolve topology, hr %#x.\n", hr);
2106 ok(full_topology != topology2, "Unexpected instance.\n");
2108 IMFTopology_Release(topology2);
2109 IMFTopology_Release(full_topology);
2112 hr = IMFTopology_GetCount(topology, &count);
2113 ok(hr == S_OK, "Failed to get attribute count, hr %#x.\n", hr);
2114 ok(!count, "Unexpected count %u.\n", count);
2116 IMFActivate_ShutdownObject(sink_activate);
2117 IMFActivate_Release(sink_activate);
2120 IMFMediaType_Release(input_type);
2121 IMFMediaType_Release(output_type);
2123 IMFMediaSource_Release(source);
2124 IMFTopoLoader_Release(loader);
2126 hr = MFShutdown();
2127 ok(hr == S_OK, "Shutdown failure, hr %#x.\n", hr);
2130 static void test_topology_loader_evr(void)
2132 IMFTopologyNode *node, *source_node, *evr_node;
2133 IMFTopology *topology, *full_topology;
2134 IMFMediaTypeHandler *handler;
2135 unsigned int i, count, value;
2136 IMFStreamSink *stream_sink;
2137 IMFMediaType *media_type;
2138 IMFActivate *activate;
2139 IMFTopoLoader *loader;
2140 IMFMediaSink *sink;
2141 WORD node_count;
2142 UINT64 value64;
2143 HWND window;
2144 HRESULT hr;
2146 hr = CoInitialize(NULL);
2147 ok(hr == S_OK, "Failed to initialize, hr %#x.\n", hr);
2149 hr = MFCreateTopoLoader(&loader);
2150 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2152 /* Source node. */
2153 hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &source_node);
2154 ok(hr == S_OK, "Failed to create topology node, hr %#x.\n", hr);
2156 hr = MFCreateMediaType(&media_type);
2157 ok(hr == S_OK, "Failed to create media type, hr %#x.\n", hr);
2159 hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
2160 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2161 hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFVideoFormat_RGB32);
2162 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2163 hr = IMFMediaType_SetUINT64(media_type, &MF_MT_FRAME_SIZE, (UINT64)640 << 32 | 480);
2164 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2165 hr = IMFMediaType_SetUINT32(media_type, &MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE);
2166 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2168 init_source_node(media_type, NULL, source_node);
2170 /* EVR sink node. */
2171 window = create_window();
2173 hr = MFCreateVideoRendererActivate(window, &activate);
2174 ok(hr == S_OK, "Failed to create activate object, hr %#x.\n", hr);
2176 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink);
2177 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2179 hr = IMFMediaSink_GetStreamSinkById(sink, 0, &stream_sink);
2180 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2182 hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, &evr_node);
2183 ok(hr == S_OK, "Failed to create topology node, hr %#x.\n", hr);
2185 hr = IMFTopologyNode_SetObject(evr_node, (IUnknown *)stream_sink);
2186 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2188 hr = IMFStreamSink_GetMediaTypeHandler(stream_sink, &handler);
2189 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2190 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, media_type);
2191 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2192 IMFMediaTypeHandler_Release(handler);
2194 IMFStreamSink_Release(stream_sink);
2195 IMFMediaSink_Release(sink);
2197 hr = MFCreateTopology(&topology);
2198 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2200 hr = IMFTopology_AddNode(topology, source_node);
2201 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2202 hr = IMFTopology_AddNode(topology, evr_node);
2203 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2204 hr = IMFTopologyNode_ConnectOutput(source_node, 0, evr_node, 0);
2205 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2207 hr = IMFTopologyNode_SetUINT32(evr_node, &MF_TOPONODE_CONNECT_METHOD, MF_CONNECT_DIRECT);
2208 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2210 hr = IMFTopologyNode_GetCount(evr_node, &count);
2211 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2212 ok(count == 1, "Unexpected attribute count %u.\n", count);
2214 hr = IMFTopoLoader_Load(loader, topology, &full_topology, NULL);
2215 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2217 hr = IMFTopology_GetNodeCount(full_topology, &node_count);
2218 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2219 ok(node_count == 3, "Unexpected node count %u.\n", node_count);
2221 for (i = 0; i < node_count; ++i)
2223 MF_TOPOLOGY_TYPE node_type;
2225 hr = IMFTopology_GetNode(full_topology, i, &node);
2226 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2228 hr = IMFTopologyNode_GetNodeType(node, &node_type);
2229 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2231 if (node_type == MF_TOPOLOGY_OUTPUT_NODE)
2233 value = 1;
2234 hr = IMFTopologyNode_GetUINT32(node, &MF_TOPONODE_STREAMID, &value);
2235 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2236 ok(!value, "Unexpected stream id %u.\n", value);
2238 else if (node_type == MF_TOPOLOGY_SOURCESTREAM_NODE)
2240 value64 = 1;
2241 hr = IMFTopologyNode_GetUINT64(node, &MF_TOPONODE_MEDIASTART, &value64);
2242 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2243 ok(!value64, "Unexpected value.\n");
2247 IMFTopology_Release(full_topology);
2249 IMFTopoLoader_Release(loader);
2251 IMFTopologyNode_Release(source_node);
2252 IMFTopologyNode_Release(evr_node);
2253 IMFTopology_Release(topology);
2254 IMFMediaType_Release(media_type);
2255 DestroyWindow(window);
2257 CoUninitialize();
2260 static HRESULT WINAPI testshutdown_QueryInterface(IMFShutdown *iface, REFIID riid, void **obj)
2262 if (IsEqualIID(riid, &IID_IMFShutdown) ||
2263 IsEqualIID(riid, &IID_IUnknown))
2265 *obj = iface;
2266 IMFShutdown_AddRef(iface);
2267 return S_OK;
2270 *obj = NULL;
2271 return E_NOINTERFACE;
2274 static ULONG WINAPI testshutdown_AddRef(IMFShutdown *iface)
2276 return 2;
2279 static ULONG WINAPI testshutdown_Release(IMFShutdown *iface)
2281 return 1;
2284 static HRESULT WINAPI testshutdown_Shutdown(IMFShutdown *iface)
2286 return 0xdead;
2289 static HRESULT WINAPI testshutdown_GetShutdownStatus(IMFShutdown *iface, MFSHUTDOWN_STATUS *status)
2291 ok(0, "Unexpected call.\n");
2292 return E_NOTIMPL;
2295 static const IMFShutdownVtbl testshutdownvtbl =
2297 testshutdown_QueryInterface,
2298 testshutdown_AddRef,
2299 testshutdown_Release,
2300 testshutdown_Shutdown,
2301 testshutdown_GetShutdownStatus,
2304 static void test_MFShutdownObject(void)
2306 IMFShutdown testshutdown = { &testshutdownvtbl };
2307 IUnknown testshutdown2 = { &testservicevtbl };
2308 HRESULT hr;
2310 hr = MFShutdownObject(NULL);
2311 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2313 hr = MFShutdownObject((IUnknown *)&testshutdown);
2314 ok(hr == S_OK, "Failed to shut down, hr %#x.\n", hr);
2316 hr = MFShutdownObject(&testshutdown2);
2317 ok(hr == S_OK, "Failed to shut down, hr %#x.\n", hr);
2320 enum clock_action
2322 CLOCK_START,
2323 CLOCK_STOP,
2324 CLOCK_PAUSE,
2327 static HRESULT WINAPI test_clock_sink_QueryInterface(IMFClockStateSink *iface, REFIID riid, void **obj)
2329 if (IsEqualIID(riid, &IID_IMFClockStateSink) ||
2330 IsEqualIID(riid, &IID_IUnknown))
2332 *obj = iface;
2333 IMFClockStateSink_AddRef(iface);
2334 return S_OK;
2337 *obj = NULL;
2338 return E_NOINTERFACE;
2341 static ULONG WINAPI test_clock_sink_AddRef(IMFClockStateSink *iface)
2343 return 2;
2346 static ULONG WINAPI test_clock_sink_Release(IMFClockStateSink *iface)
2348 return 1;
2351 static HRESULT WINAPI test_clock_sink_OnClockStart(IMFClockStateSink *iface, MFTIME system_time, LONGLONG offset)
2353 return E_NOTIMPL;
2356 static HRESULT WINAPI test_clock_sink_OnClockStop(IMFClockStateSink *iface, MFTIME system_time)
2358 return E_NOTIMPL;
2361 static HRESULT WINAPI test_clock_sink_OnClockPause(IMFClockStateSink *iface, MFTIME system_time)
2363 return E_NOTIMPL;
2366 static HRESULT WINAPI test_clock_sink_OnClockRestart(IMFClockStateSink *iface, MFTIME system_time)
2368 return E_NOTIMPL;
2371 static HRESULT WINAPI test_clock_sink_OnClockSetRate(IMFClockStateSink *iface, MFTIME system_time, float rate)
2373 return E_NOTIMPL;
2376 static const IMFClockStateSinkVtbl test_clock_sink_vtbl =
2378 test_clock_sink_QueryInterface,
2379 test_clock_sink_AddRef,
2380 test_clock_sink_Release,
2381 test_clock_sink_OnClockStart,
2382 test_clock_sink_OnClockStop,
2383 test_clock_sink_OnClockPause,
2384 test_clock_sink_OnClockRestart,
2385 test_clock_sink_OnClockSetRate,
2388 static void test_presentation_clock(void)
2390 static const struct clock_state_test
2392 enum clock_action action;
2393 MFCLOCK_STATE clock_state;
2394 MFCLOCK_STATE source_state;
2395 HRESULT hr;
2397 clock_state_change[] =
2399 { CLOCK_STOP, MFCLOCK_STATE_STOPPED, MFCLOCK_STATE_INVALID },
2400 { CLOCK_PAUSE, MFCLOCK_STATE_STOPPED, MFCLOCK_STATE_INVALID, MF_E_INVALIDREQUEST },
2401 { CLOCK_STOP, MFCLOCK_STATE_STOPPED, MFCLOCK_STATE_INVALID, MF_E_CLOCK_STATE_ALREADY_SET },
2402 { CLOCK_START, MFCLOCK_STATE_RUNNING, MFCLOCK_STATE_RUNNING },
2403 { CLOCK_START, MFCLOCK_STATE_RUNNING, MFCLOCK_STATE_RUNNING },
2404 { CLOCK_PAUSE, MFCLOCK_STATE_PAUSED, MFCLOCK_STATE_PAUSED },
2405 { CLOCK_PAUSE, MFCLOCK_STATE_PAUSED, MFCLOCK_STATE_PAUSED, MF_E_CLOCK_STATE_ALREADY_SET },
2406 { CLOCK_STOP, MFCLOCK_STATE_STOPPED, MFCLOCK_STATE_STOPPED },
2407 { CLOCK_START, MFCLOCK_STATE_RUNNING, MFCLOCK_STATE_RUNNING },
2408 { CLOCK_STOP, MFCLOCK_STATE_STOPPED, MFCLOCK_STATE_STOPPED },
2409 { CLOCK_STOP, MFCLOCK_STATE_STOPPED, MFCLOCK_STATE_STOPPED, MF_E_CLOCK_STATE_ALREADY_SET },
2410 { CLOCK_PAUSE, MFCLOCK_STATE_STOPPED, MFCLOCK_STATE_STOPPED, MF_E_INVALIDREQUEST },
2411 { CLOCK_START, MFCLOCK_STATE_RUNNING, MFCLOCK_STATE_RUNNING },
2412 { CLOCK_PAUSE, MFCLOCK_STATE_PAUSED, MFCLOCK_STATE_PAUSED },
2413 { CLOCK_START, MFCLOCK_STATE_RUNNING, MFCLOCK_STATE_RUNNING },
2415 IMFClockStateSink test_sink = { &test_clock_sink_vtbl };
2416 IMFPresentationTimeSource *time_source;
2417 MFCLOCK_PROPERTIES props, props2;
2418 IMFRateControl *rate_control;
2419 IMFPresentationClock *clock;
2420 MFSHUTDOWN_STATUS status;
2421 IMFShutdown *shutdown;
2422 MFTIME systime, time;
2423 LONGLONG clock_time;
2424 MFCLOCK_STATE state;
2425 unsigned int i;
2426 DWORD value;
2427 float rate;
2428 HRESULT hr;
2429 BOOL thin;
2431 hr = MFStartup(MF_VERSION, MFSTARTUP_FULL);
2432 ok(hr == S_OK, "Failed to start up, hr %#x.\n", hr);
2434 hr = MFCreatePresentationClock(&clock);
2435 ok(hr == S_OK, "Failed to create presentation clock, hr %#x.\n", hr);
2437 check_interface(clock, &IID_IMFTimer, TRUE);
2438 check_interface(clock, &IID_IMFRateControl, TRUE);
2439 check_interface(clock, &IID_IMFPresentationClock, TRUE);
2440 check_interface(clock, &IID_IMFShutdown, TRUE);
2441 check_interface(clock, &IID_IMFClock, TRUE);
2443 hr = IMFPresentationClock_QueryInterface(clock, &IID_IMFRateControl, (void **)&rate_control);
2444 ok(hr == S_OK, "Failed to get rate control interface, hr %#x.\n", hr);
2446 hr = IMFPresentationClock_GetTimeSource(clock, &time_source);
2447 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#x.\n", hr);
2449 hr = IMFPresentationClock_GetTimeSource(clock, NULL);
2450 ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
2452 hr = IMFPresentationClock_GetClockCharacteristics(clock, &value);
2453 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#x.\n", hr);
2455 hr = IMFPresentationClock_GetClockCharacteristics(clock, NULL);
2456 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#x.\n", hr);
2458 hr = IMFPresentationClock_GetTime(clock, &time);
2459 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#x.\n", hr);
2461 hr = IMFPresentationClock_GetTime(clock, NULL);
2462 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
2464 value = 1;
2465 hr = IMFPresentationClock_GetContinuityKey(clock, &value);
2466 ok(hr == S_OK, "Failed to get continuity key, hr %#x.\n", hr);
2467 ok(value == 0, "Unexpected value %u.\n", value);
2469 hr = IMFPresentationClock_GetProperties(clock, &props);
2470 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#x.\n", hr);
2472 hr = IMFPresentationClock_GetState(clock, 0, &state);
2473 ok(hr == S_OK, "Failed to get state, hr %#x.\n", hr);
2474 ok(state == MFCLOCK_STATE_INVALID, "Unexpected state %d.\n", state);
2476 hr = IMFPresentationClock_GetCorrelatedTime(clock, 0, &clock_time, &systime);
2477 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#x.\n", hr);
2479 hr = IMFPresentationClock_GetCorrelatedTime(clock, 0, NULL, &systime);
2480 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#x.\n", hr);
2482 hr = IMFPresentationClock_GetCorrelatedTime(clock, 0, &time, NULL);
2483 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#x.\n", hr);
2485 /* Sinks. */
2486 hr = IMFPresentationClock_AddClockStateSink(clock, NULL);
2487 ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
2489 hr = IMFPresentationClock_AddClockStateSink(clock, &test_sink);
2490 ok(hr == S_OK, "Failed to add a sink, hr %#x.\n", hr);
2492 hr = IMFPresentationClock_AddClockStateSink(clock, &test_sink);
2493 ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
2495 hr = IMFPresentationClock_RemoveClockStateSink(clock, NULL);
2496 ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
2498 hr = IMFPresentationClock_RemoveClockStateSink(clock, &test_sink);
2499 ok(hr == S_OK, "Failed to remove sink, hr %#x.\n", hr);
2501 hr = IMFPresentationClock_RemoveClockStateSink(clock, &test_sink);
2502 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2504 /* State change commands, time source is not set yet. */
2505 hr = IMFPresentationClock_Start(clock, 0);
2506 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#x.\n", hr);
2508 hr = IMFPresentationClock_Pause(clock);
2509 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#x.\n", hr);
2511 hr = IMFPresentationClock_Stop(clock);
2512 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#x.\n", hr);
2514 hr = IMFRateControl_SetRate(rate_control, FALSE, 0.0f);
2515 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#x.\n", hr);
2517 /* Set default time source. */
2518 hr = MFCreateSystemTimeSource(&time_source);
2519 ok(hr == S_OK, "Failed to create time source, hr %#x.\n", hr);
2521 hr = IMFPresentationTimeSource_GetClockCharacteristics(time_source, &value);
2522 ok(hr == S_OK, "Failed to get time source flags, hr %#x.\n", hr);
2523 ok(value == (MFCLOCK_CHARACTERISTICS_FLAG_FREQUENCY_10MHZ | MFCLOCK_CHARACTERISTICS_FLAG_IS_SYSTEM_CLOCK),
2524 "Unexpected clock flags %#x.\n", value);
2526 hr = IMFPresentationClock_SetTimeSource(clock, time_source);
2527 ok(hr == S_OK, "Failed to set time source, hr %#x.\n", hr);
2529 hr = IMFPresentationTimeSource_GetProperties(time_source, &props2);
2530 ok(hr == S_OK, "Failed to get time source properties, hr %#x.\n", hr);
2532 hr = IMFPresentationClock_GetClockCharacteristics(clock, &value);
2533 ok(hr == S_OK, "Failed to get clock flags, hr %#x.\n", hr);
2534 ok(value == (MFCLOCK_CHARACTERISTICS_FLAG_FREQUENCY_10MHZ | MFCLOCK_CHARACTERISTICS_FLAG_IS_SYSTEM_CLOCK),
2535 "Unexpected clock flags %#x.\n", value);
2537 hr = IMFPresentationClock_GetProperties(clock, &props);
2538 ok(hr == S_OK, "Failed to get clock properties, hr %#x.\n", hr);
2539 ok(!memcmp(&props, &props2, sizeof(props)), "Unexpected clock properties.\n");
2541 /* State changes. */
2542 for (i = 0; i < ARRAY_SIZE(clock_state_change); ++i)
2544 switch (clock_state_change[i].action)
2546 case CLOCK_STOP:
2547 hr = IMFPresentationClock_Stop(clock);
2548 break;
2549 case CLOCK_PAUSE:
2550 hr = IMFPresentationClock_Pause(clock);
2551 break;
2552 case CLOCK_START:
2553 hr = IMFPresentationClock_Start(clock, 0);
2554 break;
2555 default:
2558 ok(hr == clock_state_change[i].hr, "%u: unexpected hr %#x.\n", i, hr);
2560 hr = IMFPresentationTimeSource_GetState(time_source, 0, &state);
2561 ok(hr == S_OK, "%u: failed to get state, hr %#x.\n", i, hr);
2562 ok(state == clock_state_change[i].source_state, "%u: unexpected state %d.\n", i, state);
2564 hr = IMFPresentationClock_GetState(clock, 0, &state);
2565 ok(hr == S_OK, "%u: failed to get state, hr %#x.\n", i, hr);
2566 ok(state == clock_state_change[i].clock_state, "%u: unexpected state %d.\n", i, state);
2569 /* Clock time stamps. */
2570 hr = IMFPresentationClock_Start(clock, 10);
2571 ok(hr == S_OK, "Failed to start presentation clock, hr %#x.\n", hr);
2573 hr = IMFPresentationClock_Pause(clock);
2574 ok(hr == S_OK, "Failed to pause presentation clock, hr %#x.\n", hr);
2576 hr = IMFPresentationClock_GetTime(clock, &time);
2577 ok(hr == S_OK, "Failed to get clock time, hr %#x.\n", hr);
2579 hr = IMFPresentationTimeSource_GetCorrelatedTime(time_source, 0, &clock_time, &systime);
2580 ok(hr == S_OK, "Failed to get time source time, hr %#x.\n", hr);
2581 ok(time == clock_time, "Unexpected clock time.\n");
2583 hr = IMFPresentationClock_GetCorrelatedTime(clock, 0, &time, &systime);
2584 ok(hr == S_OK, "Failed to get clock time, hr %#x.\n", hr);
2585 ok(time == clock_time, "Unexpected clock time.\n");
2587 IMFPresentationTimeSource_Release(time_source);
2589 hr = IMFRateControl_GetRate(rate_control, NULL, &rate);
2590 ok(hr == S_OK, "Failed to get clock rate, hr %#x.\n", hr);
2592 hr = IMFRateControl_GetRate(rate_control, &thin, NULL);
2593 ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
2595 hr = IMFRateControl_GetRate(rate_control, &thin, &rate);
2596 ok(hr == S_OK, "Failed to get clock rate, hr %#x.\n", hr);
2597 ok(rate == 1.0f, "Unexpected rate.\n");
2598 ok(!thin, "Unexpected thinning.\n");
2600 hr = IMFPresentationClock_GetState(clock, 0, &state);
2601 ok(hr == S_OK, "Failed to get clock state, hr %#x.\n", hr);
2602 ok(state == MFCLOCK_STATE_PAUSED, "Unexpected state %d.\n", state);
2604 hr = IMFPresentationClock_Start(clock, 0);
2605 ok(hr == S_OK, "Failed to stop, hr %#x.\n", hr);
2607 hr = IMFRateControl_SetRate(rate_control, FALSE, 0.0f);
2608 ok(hr == S_OK, "Failed to set clock rate, hr %#x.\n", hr);
2609 hr = IMFRateControl_GetRate(rate_control, &thin, &rate);
2610 ok(hr == S_OK, "Failed to get clock rate, hr %#x.\n", hr);
2611 ok(rate == 0.0f, "Unexpected rate.\n");
2612 hr = IMFRateControl_SetRate(rate_control, FALSE, 1.0f);
2613 ok(hr == S_OK, "Failed to set clock rate, hr %#x.\n", hr);
2614 hr = IMFRateControl_SetRate(rate_control, FALSE, 0.0f);
2615 ok(hr == S_OK, "Failed to set clock rate, hr %#x.\n", hr);
2616 hr = IMFRateControl_SetRate(rate_control, FALSE, 0.5f);
2617 ok(hr == S_OK, "Failed to set clock rate, hr %#x.\n", hr);
2618 hr = IMFRateControl_SetRate(rate_control, TRUE, -1.0f);
2619 ok(hr == MF_E_THINNING_UNSUPPORTED, "Unexpected hr %#x.\n", hr);
2621 hr = IMFPresentationClock_GetState(clock, 0, &state);
2622 ok(hr == S_OK, "Failed to get clock state, hr %#x.\n", hr);
2623 ok(state == MFCLOCK_STATE_RUNNING, "Unexpected state %d.\n", state);
2625 hr = IMFRateControl_GetRate(rate_control, &thin, &rate);
2626 ok(hr == S_OK, "Failed to get clock rate, hr %#x.\n", hr);
2627 ok(rate == 0.5f, "Unexpected rate.\n");
2628 ok(!thin, "Unexpected thinning.\n");
2630 IMFRateControl_Release(rate_control);
2632 hr = IMFPresentationClock_QueryInterface(clock, &IID_IMFShutdown, (void **)&shutdown);
2633 ok(hr == S_OK, "Failed to get shutdown interface, hr %#x.\n", hr);
2635 /* Shutdown behavior. */
2636 hr = IMFShutdown_GetShutdownStatus(shutdown, NULL);
2637 ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
2639 hr = IMFShutdown_GetShutdownStatus(shutdown, &status);
2640 ok(hr == MF_E_INVALIDREQUEST, "Unexpected hr %#x.\n", hr);
2642 hr = IMFShutdown_Shutdown(shutdown);
2643 ok(hr == S_OK, "Failed to shut down, hr %#x.\n", hr);
2645 time_source = NULL;
2646 hr = IMFPresentationClock_GetTimeSource(clock, &time_source);
2647 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2648 ok(!!time_source, "Unexpected instance %p.\n", time_source);
2649 IMFPresentationTimeSource_Release(time_source);
2651 hr = IMFPresentationClock_GetTime(clock, &time);
2652 ok(hr == S_OK, "Failed to get time, hr %#x.\n", hr);
2654 hr = IMFShutdown_GetShutdownStatus(shutdown, &status);
2655 ok(hr == S_OK, "Failed to get status, hr %#x.\n", hr);
2656 ok(status == MFSHUTDOWN_COMPLETED, "Unexpected status.\n");
2658 hr = IMFPresentationClock_Start(clock, 0);
2659 ok(hr == S_OK, "Failed to start the clock, hr %#x.\n", hr);
2661 hr = IMFShutdown_GetShutdownStatus(shutdown, &status);
2662 ok(hr == S_OK, "Failed to get status, hr %#x.\n", hr);
2663 ok(status == MFSHUTDOWN_COMPLETED, "Unexpected status.\n");
2665 hr = IMFShutdown_Shutdown(shutdown);
2666 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2668 IMFShutdown_Release(shutdown);
2670 IMFPresentationClock_Release(clock);
2672 hr = MFShutdown();
2673 ok(hr == S_OK, "Failed to shut down, hr %#x.\n", hr);
2676 static HRESULT WINAPI grabber_callback_QueryInterface(IMFSampleGrabberSinkCallback *iface, REFIID riid, void **obj)
2678 if (IsEqualIID(riid, &IID_IMFSampleGrabberSinkCallback) ||
2679 IsEqualIID(riid, &IID_IMFClockStateSink) ||
2680 IsEqualIID(riid, &IID_IUnknown))
2682 *obj = iface;
2683 IMFSampleGrabberSinkCallback_AddRef(iface);
2684 return S_OK;
2687 *obj = NULL;
2688 return E_NOINTERFACE;
2691 static ULONG WINAPI grabber_callback_AddRef(IMFSampleGrabberSinkCallback *iface)
2693 return 2;
2696 static ULONG WINAPI grabber_callback_Release(IMFSampleGrabberSinkCallback *iface)
2698 return 1;
2701 static HRESULT WINAPI grabber_callback_OnClockStart(IMFSampleGrabberSinkCallback *iface, MFTIME time, LONGLONG offset)
2703 return E_NOTIMPL;
2706 static HRESULT WINAPI grabber_callback_OnClockStop(IMFSampleGrabberSinkCallback *iface, MFTIME time)
2708 return E_NOTIMPL;
2711 static HRESULT WINAPI grabber_callback_OnClockPause(IMFSampleGrabberSinkCallback *iface, MFTIME time)
2713 return E_NOTIMPL;
2716 static HRESULT WINAPI grabber_callback_OnClockRestart(IMFSampleGrabberSinkCallback *iface, MFTIME time)
2718 return E_NOTIMPL;
2721 static HRESULT WINAPI grabber_callback_OnClockSetRate(IMFSampleGrabberSinkCallback *iface, MFTIME time, float rate)
2723 return E_NOTIMPL;
2726 static HRESULT WINAPI grabber_callback_OnSetPresentationClock(IMFSampleGrabberSinkCallback *iface,
2727 IMFPresentationClock *clock)
2729 return S_OK;
2732 static HRESULT WINAPI grabber_callback_OnProcessSample(IMFSampleGrabberSinkCallback *iface, REFGUID major_type,
2733 DWORD sample_flags, LONGLONG sample_time, LONGLONG sample_duration, const BYTE *buffer, DWORD sample_size)
2735 return E_NOTIMPL;
2738 static HRESULT WINAPI grabber_callback_OnShutdown(IMFSampleGrabberSinkCallback *iface)
2740 return S_OK;
2743 static const IMFSampleGrabberSinkCallbackVtbl grabber_callback_vtbl =
2745 grabber_callback_QueryInterface,
2746 grabber_callback_AddRef,
2747 grabber_callback_Release,
2748 grabber_callback_OnClockStart,
2749 grabber_callback_OnClockStop,
2750 grabber_callback_OnClockPause,
2751 grabber_callback_OnClockRestart,
2752 grabber_callback_OnClockSetRate,
2753 grabber_callback_OnSetPresentationClock,
2754 grabber_callback_OnProcessSample,
2755 grabber_callback_OnShutdown,
2758 static IMFSampleGrabberSinkCallback grabber_callback = { &grabber_callback_vtbl };
2760 static void test_sample_grabber(void)
2762 IMFMediaType *media_type, *media_type2, *media_type3;
2763 IMFMediaTypeHandler *handler, *handler2;
2764 IMFPresentationTimeSource *time_source;
2765 IMFPresentationClock *clock, *clock2;
2766 IMFStreamSink *stream, *stream2;
2767 IMFRateSupport *rate_support;
2768 IMFMediaEventGenerator *eg;
2769 IMFMediaSink *sink, *sink2;
2770 DWORD flags, count, id;
2771 IMFActivate *activate;
2772 IMFMediaEvent *event;
2773 ULONG refcount;
2774 IUnknown *unk;
2775 float rate;
2776 HRESULT hr;
2777 GUID guid;
2779 hr = MFStartup(MF_VERSION, MFSTARTUP_FULL);
2780 ok(hr == S_OK, "Failed to start up, hr %#x.\n", hr);
2782 hr = MFCreateMediaType(&media_type);
2783 ok(hr == S_OK, "Failed to create media type, hr %#x.\n", hr);
2785 hr = MFCreateSampleGrabberSinkActivate(NULL, NULL, &activate);
2786 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
2788 hr = MFCreateSampleGrabberSinkActivate(NULL, &grabber_callback, &activate);
2789 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
2791 hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio);
2792 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
2793 hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFAudioFormat_PCM);
2794 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
2796 EXPECT_REF(media_type, 1);
2797 hr = MFCreateSampleGrabberSinkActivate(media_type, &grabber_callback, &activate);
2798 ok(hr == S_OK, "Failed to create grabber activate, hr %#x.\n", hr);
2799 EXPECT_REF(media_type, 2);
2801 hr = IMFActivate_GetCount(activate, &count);
2802 ok(hr == S_OK, "Failed to get attribute count, hr %#x.\n", hr);
2803 ok(!count, "Unexpected count %u.\n", count);
2805 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink);
2806 ok(hr == S_OK, "Failed to activate object, hr %#x.\n", hr);
2808 check_interface(sink, &IID_IMFClockStateSink, TRUE);
2809 check_interface(sink, &IID_IMFMediaEventGenerator, TRUE);
2810 check_interface(sink, &IID_IMFGetService, TRUE);
2811 check_interface(sink, &IID_IMFRateSupport, TRUE);
2812 check_service_interface(sink, &MF_RATE_CONTROL_SERVICE, &IID_IMFRateSupport, TRUE);
2814 if (SUCCEEDED(MFGetService((IUnknown *)sink, &MF_RATE_CONTROL_SERVICE, &IID_IMFRateSupport, (void **)&rate_support)))
2816 hr = IMFRateSupport_GetFastestRate(rate_support, MFRATE_FORWARD, FALSE, &rate);
2817 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2818 ok(rate == FLT_MAX, "Unexpected rate %f.\n", rate);
2820 hr = IMFRateSupport_GetFastestRate(rate_support, MFRATE_FORWARD, TRUE, &rate);
2821 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2822 ok(rate == FLT_MAX, "Unexpected rate %f.\n", rate);
2824 hr = IMFRateSupport_GetFastestRate(rate_support, MFRATE_REVERSE, FALSE, &rate);
2825 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2826 ok(rate == -FLT_MAX, "Unexpected rate %f.\n", rate);
2828 hr = IMFRateSupport_GetFastestRate(rate_support, MFRATE_REVERSE, TRUE, &rate);
2829 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2830 ok(rate == -FLT_MAX, "Unexpected rate %f.\n", rate);
2832 hr = IMFRateSupport_GetSlowestRate(rate_support, MFRATE_FORWARD, FALSE, &rate);
2833 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2834 ok(rate == 0.0f, "Unexpected rate %f.\n", rate);
2836 hr = IMFRateSupport_GetSlowestRate(rate_support, MFRATE_FORWARD, TRUE, &rate);
2837 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2838 ok(rate == 0.0f, "Unexpected rate %f.\n", rate);
2840 hr = IMFRateSupport_GetSlowestRate(rate_support, MFRATE_REVERSE, FALSE, &rate);
2841 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2842 ok(rate == 0.0f, "Unexpected rate %f.\n", rate);
2844 hr = IMFRateSupport_GetSlowestRate(rate_support, MFRATE_REVERSE, TRUE, &rate);
2845 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2846 ok(rate == 0.0f, "Unexpected rate %f.\n", rate);
2848 hr = IMFRateSupport_IsRateSupported(rate_support, TRUE, 1.0f, &rate);
2849 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2850 ok(rate == 1.0f, "Unexpected rate %f.\n", rate);
2852 IMFRateSupport_Release(rate_support);
2855 hr = IMFMediaSink_GetCharacteristics(sink, &flags);
2856 ok(hr == S_OK, "Failed to get sink flags, hr %#x.\n", hr);
2857 ok(flags & MEDIASINK_FIXED_STREAMS, "Unexpected flags %#x.\n", flags);
2859 hr = IMFMediaSink_GetStreamSinkCount(sink, &count);
2860 ok(hr == S_OK, "Failed to get stream count, hr %#x.\n", hr);
2861 ok(count == 1, "Unexpected stream count %u.\n", count);
2863 hr = IMFMediaSink_GetStreamSinkByIndex(sink, 0, &stream);
2864 ok(hr == S_OK, "Failed to get sink stream, hr %#x.\n", hr);
2866 check_interface(stream, &IID_IMFMediaEventGenerator, TRUE);
2867 check_interface(stream, &IID_IMFMediaTypeHandler, TRUE);
2869 hr = IMFStreamSink_GetIdentifier(stream, &id);
2870 ok(hr == S_OK, "Failed to get stream id, hr %#x.\n", hr);
2871 ok(id == 0, "Unexpected id %#x.\n", id);
2873 hr = IMFStreamSink_GetMediaSink(stream, &sink2);
2874 ok(hr == S_OK, "Failed to get media sink, hr %x.\n", hr);
2875 ok(sink2 == sink, "Unexpected sink.\n");
2876 IMFMediaSink_Release(sink2);
2878 hr = IMFMediaSink_GetStreamSinkByIndex(sink, 1, &stream2);
2879 ok(hr == MF_E_INVALIDINDEX, "Unexpected hr %#x.\n", hr);
2881 hr = IMFMediaSink_GetStreamSinkById(sink, 1, &stream2);
2882 ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#x.\n", hr);
2884 hr = IMFMediaSink_AddStreamSink(sink, 1, NULL, &stream2);
2885 ok(hr == MF_E_STREAMSINKS_FIXED, "Unexpected hr %#x.\n", hr);
2887 hr = IMFMediaSink_RemoveStreamSink(sink, 0);
2888 ok(hr == MF_E_STREAMSINKS_FIXED, "Unexpected hr %#x.\n", hr);
2890 hr = IMFMediaSink_RemoveStreamSink(sink, 1);
2891 ok(hr == MF_E_STREAMSINKS_FIXED, "Unexpected hr %#x.\n", hr);
2893 check_interface(sink, &IID_IMFClockStateSink, TRUE);
2895 /* Event generator. */
2896 hr = IMFMediaSink_QueryInterface(sink, &IID_IMFMediaEventGenerator, (void **)&eg);
2897 ok(hr == S_OK, "Failed to get interface, hr %#x.\n", hr);
2899 hr = IMFMediaEventGenerator_GetEvent(eg, MF_EVENT_FLAG_NO_WAIT, &event);
2900 ok(hr == MF_E_NO_EVENTS_AVAILABLE, "Unexpected hr %#x.\n", hr);
2902 hr = IMFMediaSink_QueryInterface(sink, &IID_IMFPresentationTimeSource, (void **)&unk);
2903 ok(hr == E_NOINTERFACE, "Unexpected hr %#x.\n", hr);
2905 hr = IMFStreamSink_QueryInterface(stream, &IID_IMFMediaTypeHandler, (void **)&handler2);
2906 ok(hr == S_OK, "Failed to get handler interface, hr %#x.\n", hr);
2908 hr = IMFStreamSink_GetMediaTypeHandler(stream, &handler);
2909 ok(hr == S_OK, "Failed to get type handler, hr %#x.\n", hr);
2910 hr = IMFMediaTypeHandler_GetMediaTypeCount(handler, &count);
2911 ok(hr == S_OK, "Failed to get media type count, hr %#x.\n", hr);
2912 ok(count == 0, "Unexpected count %u.\n", count);
2913 ok(handler == handler2, "Unexpected handler.\n");
2915 IMFMediaTypeHandler_Release(handler);
2916 IMFMediaTypeHandler_Release(handler2);
2918 /* Set clock. */
2919 hr = MFCreatePresentationClock(&clock);
2920 ok(hr == S_OK, "Failed to create clock object, hr %#x.\n", hr);
2922 hr = IMFMediaSink_GetPresentationClock(sink, NULL);
2923 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
2925 hr = IMFMediaSink_GetPresentationClock(sink, &clock2);
2926 ok(hr == MF_E_NO_CLOCK, "Unexpected hr %#x.\n", hr);
2928 hr = IMFMediaSink_SetPresentationClock(sink, NULL);
2929 ok(hr == S_OK, "Failed to set presentation clock, hr %#x.\n", hr);
2931 hr = IMFMediaSink_SetPresentationClock(sink, clock);
2932 ok(hr == S_OK, "Failed to set presentation clock, hr %#x.\n", hr);
2934 hr = MFCreateSystemTimeSource(&time_source);
2935 ok(hr == S_OK, "Failed to create time source, hr %#x.\n", hr);
2937 hr = IMFPresentationClock_SetTimeSource(clock, time_source);
2938 ok(hr == S_OK, "Failed to set time source, hr %#x.\n", hr);
2939 IMFPresentationTimeSource_Release(time_source);
2941 hr = IMFMediaSink_GetCharacteristics(sink, &flags);
2942 ok(hr == S_OK, "Failed to get sink flags, hr %#x.\n", hr);
2944 hr = IMFActivate_ShutdownObject(activate);
2945 ok(hr == S_OK, "Failed to shut down, hr %#x.\n", hr);
2947 hr = IMFMediaSink_GetCharacteristics(sink, &flags);
2948 ok(hr == S_OK, "Failed to get sink flags, hr %#x.\n", hr);
2950 hr = IMFStreamSink_GetMediaTypeHandler(stream, &handler);
2951 ok(hr == S_OK, "Failed to get type handler, hr %#x.\n", hr);
2953 /* On Win8+ this initialization happens automatically. */
2954 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, media_type);
2955 ok(hr == S_OK, "Failed to set media type, hr %#x.\n", hr);
2957 hr = IMFMediaTypeHandler_GetMediaTypeCount(handler, NULL);
2958 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
2960 hr = IMFMediaTypeHandler_GetMediaTypeCount(handler, &count);
2961 ok(hr == S_OK, "Failed to get media type count, hr %#x.\n", hr);
2962 ok(count == 0, "Unexpected count %u.\n", count);
2964 hr = IMFMediaTypeHandler_GetMajorType(handler, &guid);
2965 ok(hr == S_OK, "Failed to get major type, hr %#x.\n", hr);
2966 ok(IsEqualGUID(&guid, &MFMediaType_Audio), "Unexpected major type %s.\n", wine_dbgstr_guid(&guid));
2968 hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, &media_type2);
2969 ok(hr == S_OK, "Failed to get current type, hr %#x.\n", hr);
2970 ok(media_type2 == media_type, "Unexpected media type.\n");
2971 IMFMediaType_Release(media_type2);
2973 hr = MFCreateMediaType(&media_type2);
2974 ok(hr == S_OK, "Failed to create media type, hr %#x.\n", hr);
2976 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, media_type2);
2977 ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#x.\n", hr);
2979 hr = IMFMediaType_SetGUID(media_type2, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio);
2980 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
2982 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, media_type2);
2983 ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#x.\n", hr);
2985 hr = IMFMediaType_SetGUID(media_type2, &MF_MT_SUBTYPE, &MFAudioFormat_Float);
2986 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
2988 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, media_type2);
2989 ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#x.\n", hr);
2991 hr = IMFMediaType_SetGUID(media_type2, &MF_MT_SUBTYPE, &MFAudioFormat_PCM);
2992 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
2994 hr = IMFMediaType_SetUINT32(media_type2, &MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100);
2995 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
2997 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, media_type2);
2998 ok(hr == S_OK, "Failed to get current type, hr %#x.\n", hr);
2999 IMFMediaType_Release(media_type);
3001 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, NULL);
3002 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
3004 hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, &media_type);
3005 ok(hr == S_OK, "Failed to get current type, hr %#x.\n", hr);
3006 ok(media_type2 == media_type, "Unexpected media type.\n");
3007 IMFMediaType_Release(media_type);
3009 hr = IMFMediaTypeHandler_GetMediaTypeByIndex(handler, 0, &media_type);
3010 ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#x.\n", hr);
3012 hr = IMFMediaTypeHandler_GetMediaTypeByIndex(handler, 0, NULL);
3013 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
3015 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type2, NULL);
3016 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
3018 hr = MFCreateMediaType(&media_type);
3019 ok(hr == S_OK, "Failed to create media type, hr %#x.\n", hr);
3021 hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio);
3022 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
3024 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type, NULL);
3025 ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#x.\n", hr);
3027 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type, &media_type3);
3028 ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#x.\n", hr);
3030 hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFAudioFormat_PCM);
3031 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
3033 media_type3 = (void *)0xdeadbeef;
3034 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type, &media_type3);
3035 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
3036 ok(media_type3 == (void *)0xdeadbeef, "Unexpected media type %p.\n", media_type3);
3038 hr = IMFMediaType_SetUINT32(media_type, &MF_MT_FIXED_SIZE_SAMPLES, 1);
3039 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
3041 hr = IMFMediaType_SetUINT32(media_type, &MF_MT_SAMPLE_SIZE, 1024);
3042 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
3044 media_type3 = (void *)0xdeadbeef;
3045 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type, &media_type3);
3046 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
3047 ok(media_type3 == (void *)0xdeadbeef, "Unexpected media type %p.\n", media_type3);
3049 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, NULL, NULL);
3050 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
3052 hr = IMFMediaEventGenerator_GetEvent(eg, MF_EVENT_FLAG_NO_WAIT, &event);
3053 ok(hr == MF_E_NO_EVENTS_AVAILABLE, "Unexpected hr %#x.\n", hr);
3055 hr = IMFStreamSink_GetEvent(stream, MF_EVENT_FLAG_NO_WAIT, &event);
3056 ok(hr == MF_E_NO_EVENTS_AVAILABLE, "Unexpected hr %#x.\n", hr);
3058 EXPECT_REF(clock, 3);
3059 hr = IMFMediaSink_Shutdown(sink);
3060 ok(hr == S_OK, "Failed to shut down, hr %#x.\n", hr);
3061 EXPECT_REF(clock, 1);
3063 hr = IMFMediaEventGenerator_GetEvent(eg, MF_EVENT_FLAG_NO_WAIT, &event);
3064 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr);
3066 hr = IMFMediaSink_Shutdown(sink);
3067 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr);
3069 hr = IMFMediaSink_GetCharacteristics(sink, &flags);
3070 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr);
3072 hr = IMFMediaSink_AddStreamSink(sink, 1, NULL, &stream2);
3073 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr);
3075 hr = IMFMediaSink_GetStreamSinkCount(sink, &count);
3076 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr);
3078 hr = IMFMediaSink_GetStreamSinkByIndex(sink, 0, &stream2);
3079 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr);
3081 hr = IMFStreamSink_GetEvent(stream, MF_EVENT_FLAG_NO_WAIT, &event);
3082 ok(hr == MF_E_STREAMSINK_REMOVED, "Unexpected hr %#x.\n", hr);
3084 hr = IMFStreamSink_GetMediaSink(stream, &sink2);
3085 ok(hr == MF_E_STREAMSINK_REMOVED, "Unexpected hr %#x.\n", hr);
3087 id = 1;
3088 hr = IMFStreamSink_GetIdentifier(stream, &id);
3089 ok(hr == MF_E_STREAMSINK_REMOVED, "Unexpected hr %#x.\n", hr);
3090 ok(id == 1, "Unexpected id %u.\n", id);
3092 media_type3 = (void *)0xdeadbeef;
3093 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type, &media_type3);
3094 ok(hr == MF_E_STREAMSINK_REMOVED, "Unexpected hr %#x.\n", hr);
3095 ok(media_type3 == (void *)0xdeadbeef, "Unexpected media type %p.\n", media_type3);
3097 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, NULL, NULL);
3098 ok(hr == MF_E_STREAMSINK_REMOVED, "Unexpected hr %#x.\n", hr);
3100 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, NULL);
3101 ok(hr == MF_E_STREAMSINK_REMOVED, "Unexpected hr %#x.\n", hr);
3103 hr = IMFMediaTypeHandler_GetMediaTypeCount(handler, &count);
3104 ok(hr == S_OK, "Failed to get type count, hr %#x.\n", hr);
3106 IMFMediaType_Release(media_type2);
3107 IMFMediaType_Release(media_type);
3109 hr = IMFMediaTypeHandler_GetMediaTypeByIndex(handler, 0, &media_type);
3110 ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#x.\n", hr);
3112 hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, &media_type);
3113 ok(hr == MF_E_STREAMSINK_REMOVED, "Unexpected hr %#x.\n", hr);
3115 hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, NULL);
3116 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
3118 hr = IMFMediaTypeHandler_GetMajorType(handler, NULL);
3119 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
3121 hr = IMFMediaTypeHandler_GetMajorType(handler, &guid);
3122 ok(hr == MF_E_STREAMSINK_REMOVED, "Unexpected hr %#x.\n", hr);
3124 IMFMediaTypeHandler_Release(handler);
3126 handler = (void *)0xdeadbeef;
3127 hr = IMFStreamSink_GetMediaTypeHandler(stream, &handler);
3128 ok(hr == MF_E_STREAMSINK_REMOVED, "Unexpected hr %#x.\n", hr);
3129 ok(handler == (void *)0xdeadbeef, "Unexpected pointer.\n");
3131 hr = IMFStreamSink_GetMediaTypeHandler(stream, NULL);
3132 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
3134 IMFMediaEventGenerator_Release(eg);
3135 IMFMediaSink_Release(sink);
3136 IMFStreamSink_Release(stream);
3138 refcount = IMFActivate_Release(activate);
3139 ok(!refcount, "Unexpected refcount %u.\n", refcount);
3141 /* Rateless mode with MF_SAMPLEGRABBERSINK_IGNORE_CLOCK. */
3142 hr = MFCreateMediaType(&media_type);
3143 ok(hr == S_OK, "Failed to create media type, hr %#x.\n", hr);
3145 hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio);
3146 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
3147 hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFAudioFormat_PCM);
3148 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
3150 hr = MFCreateSampleGrabberSinkActivate(media_type, &grabber_callback, &activate);
3151 ok(hr == S_OK, "Failed to create grabber activate, hr %#x.\n", hr);
3153 hr = IMFActivate_SetUINT32(activate, &MF_SAMPLEGRABBERSINK_IGNORE_CLOCK, 1);
3154 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
3156 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink);
3157 ok(hr == S_OK, "Failed to activate object, hr %#x.\n", hr);
3159 hr = IMFMediaSink_GetCharacteristics(sink, &flags);
3160 ok(hr == S_OK, "Failed to get sink flags, hr %#x.\n", hr);
3161 ok(flags & MEDIASINK_RATELESS, "Unexpected flags %#x.\n", flags);
3163 hr = IMFActivate_ShutdownObject(activate);
3164 ok(hr == S_OK, "Failed to shut down, hr %#x.\n", hr);
3166 hr = IMFMediaSink_Shutdown(sink);
3167 ok(hr == S_OK, "Failed to shut down, hr %#x.\n", hr);
3169 IMFMediaSink_Release(sink);
3171 /* Detaching */
3172 hr = MFCreateSampleGrabberSinkActivate(media_type, &grabber_callback, &activate);
3173 ok(hr == S_OK, "Failed to create grabber activate, hr %#x.\n", hr);
3175 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink);
3176 ok(hr == S_OK, "Failed to activate object, hr %#x.\n", hr);
3177 IMFMediaSink_Release(sink);
3179 hr = IMFActivate_ShutdownObject(activate);
3180 ok(hr == S_OK, "Failed to shut down, hr %#x.\n", hr);
3182 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink);
3183 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr);
3185 hr = IMFActivate_GetCount(activate, &count);
3186 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
3188 hr = IMFActivate_DetachObject(activate);
3189 ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
3191 IMFActivate_Release(activate);
3193 IMFMediaType_Release(media_type);
3194 IMFPresentationClock_Release(clock);
3196 hr = MFShutdown();
3197 ok(hr == S_OK, "Failed to shut down, hr %#x.\n", hr);
3200 static void test_sample_grabber_is_mediatype_supported(void)
3202 IMFMediaType *media_type, *media_type2, *media_type3;
3203 IMFMediaTypeHandler *handler;
3204 IMFActivate *activate;
3205 IMFStreamSink *stream;
3206 IMFMediaSink *sink;
3207 ULONG refcount;
3208 HRESULT hr;
3209 GUID guid;
3211 /* IsMediaTypeSupported checks are done against the creation type, and check format data */
3212 hr = MFCreateMediaType(&media_type);
3213 ok(hr == S_OK, "Failed to create media type, hr %#x.\n", hr);
3215 hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio);
3216 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
3217 hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFAudioFormat_PCM);
3218 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
3219 hr = IMFMediaType_SetUINT32(media_type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100);
3220 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
3222 hr = MFCreateSampleGrabberSinkActivate(media_type, &grabber_callback, &activate);
3223 ok(hr == S_OK, "Failed to create grabber activate, hr %#x.\n", hr);
3225 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink);
3226 ok(hr == S_OK, "Failed to activate object, hr %#x.\n", hr);
3228 hr = IMFMediaSink_GetStreamSinkByIndex(sink, 0, &stream);
3229 ok(hr == S_OK, "Failed to get sink stream, hr %#x.\n", hr);
3230 hr = IMFStreamSink_GetMediaTypeHandler(stream, &handler);
3231 ok(hr == S_OK, "Failed to get type handler, hr %#x.\n", hr);
3232 IMFStreamSink_Release(stream);
3234 IMFMediaSink_Release(sink);
3236 /* On Win8+ this initialization happens automatically. */
3237 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, media_type);
3238 ok(hr == S_OK, "Failed to set media type, hr %#x.\n", hr);
3240 hr = MFCreateMediaType(&media_type2);
3241 ok(hr == S_OK, "Failed to create media type, hr %#x.\n", hr);
3243 hr = IMFMediaType_SetGUID(media_type2, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio);
3244 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
3245 hr = IMFMediaType_SetGUID(media_type2, &MF_MT_SUBTYPE, &MFAudioFormat_PCM);
3246 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
3247 hr = IMFMediaType_SetUINT32(media_type2, &MF_MT_AUDIO_SAMPLES_PER_SECOND, 48000);
3248 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
3250 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type2, NULL);
3251 ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#x.\n", hr);
3253 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, media_type2);
3254 ok(hr == MF_E_INVALIDMEDIATYPE, "Failed to set media type, hr %#x.\n", hr);
3256 /* Make it match grabber type sample rate. */
3257 hr = IMFMediaType_SetUINT32(media_type2, &MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100);
3258 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
3260 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type2, NULL);
3261 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
3263 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, media_type2);
3264 ok(hr == S_OK, "Failed to set media type, hr %#x.\n", hr);
3265 hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, &media_type3);
3266 ok(hr == S_OK, "Failed to set media type, hr %#x.\n", hr);
3267 ok(media_type3 == media_type2, "Unexpected media type instance.\n");
3268 IMFMediaType_Release(media_type3);
3270 /* Change original type. */
3271 hr = IMFMediaType_SetUINT32(media_type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, 48000);
3272 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
3274 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type2, NULL);
3275 ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#x.\n", hr);
3277 hr = IMFMediaType_SetUINT32(media_type2, &MF_MT_AUDIO_SAMPLES_PER_SECOND, 48000);
3278 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
3280 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type2, NULL);
3281 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
3283 hr = IMFMediaTypeHandler_GetMajorType(handler, &guid);
3284 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
3285 ok(IsEqualGUID(&guid, &MFMediaType_Audio), "Unexpected major type.\n");
3287 hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
3288 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
3290 hr = IMFMediaTypeHandler_GetMajorType(handler, &guid);
3291 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
3292 ok(IsEqualGUID(&guid, &MFMediaType_Audio), "Unexpected major type.\n");
3294 IMFMediaType_Release(media_type2);
3295 IMFMediaType_Release(media_type);
3297 IMFMediaTypeHandler_Release(handler);
3299 refcount = IMFActivate_Release(activate);
3300 ok(!refcount, "Unexpected refcount %u.\n", refcount);
3303 static BOOL is_supported_video_type(const GUID *guid)
3305 return IsEqualGUID(guid, &MFVideoFormat_L8)
3306 || IsEqualGUID(guid, &MFVideoFormat_L16)
3307 || IsEqualGUID(guid, &MFVideoFormat_D16)
3308 || IsEqualGUID(guid, &MFVideoFormat_IYUV)
3309 || IsEqualGUID(guid, &MFVideoFormat_YV12)
3310 || IsEqualGUID(guid, &MFVideoFormat_NV12)
3311 || IsEqualGUID(guid, &MFVideoFormat_420O)
3312 || IsEqualGUID(guid, &MFVideoFormat_P010)
3313 || IsEqualGUID(guid, &MFVideoFormat_P016)
3314 || IsEqualGUID(guid, &MFVideoFormat_UYVY)
3315 || IsEqualGUID(guid, &MFVideoFormat_YUY2)
3316 || IsEqualGUID(guid, &MFVideoFormat_P208)
3317 || IsEqualGUID(guid, &MFVideoFormat_NV11)
3318 || IsEqualGUID(guid, &MFVideoFormat_AYUV)
3319 || IsEqualGUID(guid, &MFVideoFormat_ARGB32)
3320 || IsEqualGUID(guid, &MFVideoFormat_RGB32)
3321 || IsEqualGUID(guid, &MFVideoFormat_A2R10G10B10)
3322 || IsEqualGUID(guid, &MFVideoFormat_A16B16G16R16F)
3323 || IsEqualGUID(guid, &MFVideoFormat_RGB24)
3324 || IsEqualGUID(guid, &MFVideoFormat_I420)
3325 || IsEqualGUID(guid, &MFVideoFormat_YVYU)
3326 || IsEqualGUID(guid, &MFVideoFormat_RGB555)
3327 || IsEqualGUID(guid, &MFVideoFormat_RGB565)
3328 || IsEqualGUID(guid, &MFVideoFormat_RGB8)
3329 || IsEqualGUID(guid, &MFVideoFormat_Y216)
3330 || IsEqualGUID(guid, &MFVideoFormat_v410)
3331 || IsEqualGUID(guid, &MFVideoFormat_Y41P)
3332 || IsEqualGUID(guid, &MFVideoFormat_Y41T)
3333 || IsEqualGUID(guid, &MFVideoFormat_Y42T)
3334 || IsEqualGUID(guid, &MFVideoFormat_ABGR32);
3337 static void test_video_processor(void)
3339 DWORD input_count, output_count, input_id, output_id, flags;
3340 DWORD input_min, input_max, output_min, output_max, i, count;
3341 IMFAttributes *attributes, *attributes2;
3342 IMFMediaType *media_type, *media_type2;
3343 MFT_OUTPUT_DATA_BUFFER output_buffer;
3344 MFT_OUTPUT_STREAM_INFO output_info;
3345 MFT_INPUT_STREAM_INFO input_info;
3346 IMFSample *sample, *sample2;
3347 IMFTransform *transform;
3348 IMFMediaBuffer *buffer;
3349 IMFMediaEvent *event;
3350 IUnknown *unk;
3351 HRESULT hr;
3352 GUID guid;
3354 hr = CoInitialize(NULL);
3355 ok(hr == S_OK, "Failed to initialize, hr %#x.\n", hr);
3357 hr = CoCreateInstance(&CLSID_VideoProcessorMFT, NULL, CLSCTX_INPROC_SERVER, &IID_IMFTransform,
3358 (void **)&transform);
3359 if (FAILED(hr))
3361 skip("Failed to create Video Processor instance, skipping tests.\n");
3362 goto failed;
3365 hr = IMFTransform_QueryInterface(transform, &IID_IMFMediaEventGenerator, (void **)&unk);
3366 ok(hr == E_NOINTERFACE, "Unexpected hr %#x.\n", hr);
3368 hr = IMFTransform_QueryInterface(transform, &IID_IMFShutdown, (void **)&unk);
3369 ok(hr == E_NOINTERFACE, "Unexpected hr %#x.\n", hr);
3371 /* Transform global attributes. */
3372 hr = IMFTransform_GetAttributes(transform, &attributes);
3373 ok(hr == S_OK, "Failed to get attributes, hr %#x.\n", hr);
3374 hr = IMFTransform_GetAttributes(transform, &attributes2);
3375 ok(hr == S_OK, "Failed to get attributes, hr %#x.\n", hr);
3376 ok(attributes == attributes2, "Unexpected instance.\n");
3377 IMFAttributes_Release(attributes);
3378 IMFAttributes_Release(attributes2);
3380 hr = IMFTransform_GetStreamLimits(transform, &input_min, &input_max, &output_min, &output_max);
3381 ok(hr == S_OK, "Failed to get stream limits, hr %#x.\n", hr);
3382 ok(input_min == input_max && input_min == 1 && output_min == output_max && output_min == 1,
3383 "Unexpected stream limits.\n");
3385 hr = IMFTransform_GetStreamCount(transform, &input_count, &output_count);
3386 ok(hr == S_OK, "Failed to get stream count, hr %#x.\n", hr);
3387 ok(input_count == 1 && output_count == 1, "Unexpected stream count %u, %u.\n", input_count, output_count);
3389 hr = IMFTransform_GetStreamIDs(transform, 1, &input_id, 1, &output_id);
3390 ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
3392 input_id = 100;
3393 hr = IMFTransform_AddInputStreams(transform, 1, &input_id);
3394 ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
3396 hr = IMFTransform_DeleteInputStream(transform, 0);
3397 ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
3399 hr = IMFTransform_GetInputStatus(transform, 0, &flags);
3400 todo_wine
3401 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#x.\n", hr);
3403 hr = IMFTransform_GetInputStreamAttributes(transform, 0, &attributes);
3404 ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
3406 hr = IMFTransform_GetOutputStatus(transform, &flags);
3407 todo_wine
3408 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#x.\n", hr);
3410 hr = IMFTransform_GetOutputStreamAttributes(transform, 0, &attributes);
3411 ok(hr == S_OK, "Failed to get output attributes, hr %#x.\n", hr);
3412 hr = IMFTransform_GetOutputStreamAttributes(transform, 0, &attributes2);
3413 ok(hr == S_OK, "Failed to get output attributes, hr %#x.\n", hr);
3414 ok(attributes == attributes2, "Unexpected instance.\n");
3415 IMFAttributes_Release(attributes);
3416 IMFAttributes_Release(attributes2);
3418 hr = IMFTransform_GetOutputAvailableType(transform, 0, 0, &media_type);
3419 todo_wine
3420 ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#x.\n", hr);
3422 hr = IMFTransform_GetInputCurrentType(transform, 0, &media_type);
3423 todo_wine
3424 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#x.\n", hr);
3426 hr = IMFTransform_GetInputCurrentType(transform, 1, &media_type);
3427 todo_wine
3428 ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#x.\n", hr);
3430 hr = IMFTransform_GetOutputCurrentType(transform, 0, &media_type);
3431 todo_wine
3432 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#x.\n", hr);
3434 hr = IMFTransform_GetOutputCurrentType(transform, 1, &media_type);
3435 todo_wine
3436 ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#x.\n", hr);
3438 hr = IMFTransform_GetInputStreamInfo(transform, 1, &input_info);
3439 todo_wine
3440 ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#x.\n", hr);
3442 memset(&input_info, 0xcc, sizeof(input_info));
3443 hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info);
3444 todo_wine {
3445 ok(hr == S_OK, "Failed to get stream info, hr %#x.\n", hr);
3446 ok(input_info.dwFlags == 0, "Unexpected flag %#x.\n", input_info.dwFlags);
3447 ok(input_info.cbSize == 0, "Unexpected size %u.\n", input_info.cbSize);
3448 ok(input_info.cbMaxLookahead == 0, "Unexpected lookahead length %u.\n", input_info.cbMaxLookahead);
3449 ok(input_info.cbAlignment == 0, "Unexpected alignment %u.\n", input_info.cbAlignment);
3451 hr = MFCreateMediaEvent(MEUnknown, &GUID_NULL, S_OK, NULL, &event);
3452 ok(hr == S_OK, "Failed to create event object, hr %#x.\n", hr);
3453 hr = IMFTransform_ProcessEvent(transform, 0, event);
3454 ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
3455 hr = IMFTransform_ProcessEvent(transform, 1, event);
3456 ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
3457 IMFMediaEvent_Release(event);
3459 /* Configure stream types. */
3460 for (i = 0;;++i)
3462 if (FAILED(hr = IMFTransform_GetInputAvailableType(transform, 0, i, &media_type)))
3464 todo_wine
3465 ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#x.\n", hr);
3466 break;
3469 hr = IMFTransform_GetInputAvailableType(transform, 0, i, &media_type2);
3470 ok(hr == S_OK, "Failed to get available type, hr %#x.\n", hr);
3471 ok(media_type != media_type2, "Unexpected instance.\n");
3472 IMFMediaType_Release(media_type2);
3474 hr = IMFMediaType_GetMajorType(media_type, &guid);
3475 ok(hr == S_OK, "Failed to get major type, hr %#x.\n", hr);
3476 ok(IsEqualGUID(&guid, &MFMediaType_Video), "Unexpected major type.\n");
3478 hr = IMFMediaType_GetCount(media_type, &count);
3479 ok(hr == S_OK, "Failed to get attributes count, hr %#x.\n", hr);
3480 ok(count == 2, "Unexpected count %u.\n", count);
3482 hr = IMFMediaType_GetGUID(media_type, &MF_MT_SUBTYPE, &guid);
3483 ok(hr == S_OK, "Failed to get subtype, hr %#x.\n", hr);
3484 ok(is_supported_video_type(&guid), "Unexpected media type %s.\n", wine_dbgstr_guid(&guid));
3486 hr = IMFTransform_SetInputType(transform, 0, media_type, MFT_SET_TYPE_TEST_ONLY);
3487 ok(FAILED(hr), "Unexpected hr %#x.\n", hr);
3489 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
3490 ok(FAILED(hr), "Unexpected hr %#x.\n", hr);
3492 hr = IMFTransform_GetOutputCurrentType(transform, 0, &media_type2);
3493 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#x.\n", hr);
3495 /* FIXME: figure out if those require additional attributes or simply advertised but not supported */
3496 if (IsEqualGUID(&guid, &MFVideoFormat_L8) || IsEqualGUID(&guid, &MFVideoFormat_L16)
3497 || IsEqualGUID(&guid, &MFVideoFormat_D16) || IsEqualGUID(&guid, &MFVideoFormat_420O)
3498 || IsEqualGUID(&guid, &MFVideoFormat_A16B16G16R16F))
3500 IMFMediaType_Release(media_type);
3501 continue;
3504 hr = IMFMediaType_SetUINT64(media_type, &MF_MT_FRAME_SIZE, ((UINT64)16 << 32) | 16);
3505 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
3507 hr = IMFTransform_SetInputType(transform, 0, media_type, MFT_SET_TYPE_TEST_ONLY);
3508 ok(hr == S_OK, "Failed to test input type %s, hr %#x.\n", wine_dbgstr_guid(&guid), hr);
3510 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
3511 ok(hr == S_OK, "Failed to test input type, hr %#x.\n", hr);
3513 hr = IMFTransform_GetInputCurrentType(transform, 0, &media_type2);
3514 ok(hr == S_OK, "Failed to get current type, hr %#x.\n", hr);
3515 ok(media_type != media_type2, "Unexpected instance.\n");
3516 IMFMediaType_Release(media_type2);
3518 hr = IMFTransform_GetInputStatus(transform, 0, &flags);
3519 ok(hr == S_OK, "Failed to get input status, hr %#x.\n", hr);
3520 ok(flags == MFT_INPUT_STATUS_ACCEPT_DATA, "Unexpected input status %#x.\n", flags);
3522 hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info);
3523 ok(hr == S_OK, "Failed to get stream info, hr %#x.\n", hr);
3524 ok(input_info.dwFlags == 0, "Unexpected flags %#x.\n", input_info.dwFlags);
3525 ok(input_info.cbMaxLookahead == 0, "Unexpected lookahead length %u.\n", input_info.cbMaxLookahead);
3526 ok(input_info.cbAlignment == 0, "Unexpected alignment %u.\n", input_info.cbAlignment);
3528 IMFMediaType_Release(media_type);
3531 /* IYUV -> RGB32 */
3532 hr = MFCreateMediaType(&media_type);
3533 ok(hr == S_OK, "Failed to create media type, hr %#x.\n", hr);
3535 hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
3536 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
3538 hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFVideoFormat_IYUV);
3539 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
3541 hr = IMFMediaType_SetUINT64(media_type, &MF_MT_FRAME_SIZE, ((UINT64)16 << 32) | 16);
3542 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
3544 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
3545 todo_wine
3546 ok(hr == S_OK, "Failed to set input type, hr %#x.\n", hr);
3548 hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFVideoFormat_RGB32);
3549 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
3551 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
3552 todo_wine
3553 ok(hr == S_OK, "Failed to set output type, hr %#x.\n", hr);
3555 memset(&output_info, 0, sizeof(output_info));
3556 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
3557 todo_wine
3558 ok(hr == S_OK, "Failed to get stream info, hr %#x.\n", hr);
3559 ok(output_info.dwFlags == 0, "Unexpected flags %#x.\n", output_info.dwFlags);
3560 todo_wine
3561 ok(output_info.cbSize > 0, "Unexpected size %u.\n", output_info.cbSize);
3562 ok(output_info.cbAlignment == 0, "Unexpected alignment %u.\n", output_info.cbAlignment);
3564 hr = MFCreateSample(&sample);
3565 ok(hr == S_OK, "Failed to create a sample, hr %#x.\n", hr);
3567 hr = MFCreateSample(&sample2);
3568 ok(hr == S_OK, "Failed to create a sample, hr %#x.\n", hr);
3570 memset(&output_buffer, 0, sizeof(output_buffer));
3571 output_buffer.pSample = sample;
3572 flags = 0;
3573 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output_buffer, &flags);
3574 todo_wine
3575 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "Unexpected hr %#x.\n", hr);
3576 ok(output_buffer.dwStatus == 0, "Unexpected buffer status, %#x.\n", output_buffer.dwStatus);
3577 ok(flags == 0, "Unexpected status %#x.\n", flags);
3579 hr = IMFTransform_ProcessInput(transform, 0, sample2, 0);
3580 todo_wine
3581 ok(hr == S_OK, "Failed to push a sample, hr %#x.\n", hr);
3583 hr = IMFTransform_ProcessInput(transform, 0, sample2, 0);
3584 todo_wine
3585 ok(hr == MF_E_NOTACCEPTING, "Unexpected hr %#x.\n", hr);
3587 memset(&output_buffer, 0, sizeof(output_buffer));
3588 output_buffer.pSample = sample;
3589 flags = 0;
3590 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output_buffer, &flags);
3591 todo_wine
3592 ok(hr == MF_E_NO_SAMPLE_TIMESTAMP, "Unexpected hr %#x.\n", hr);
3593 ok(output_buffer.dwStatus == 0, "Unexpected buffer status, %#x.\n", output_buffer.dwStatus);
3594 ok(flags == 0, "Unexpected status %#x.\n", flags);
3596 hr = IMFSample_SetSampleTime(sample2, 0);
3597 ok(hr == S_OK, "Failed to set sample time, hr %#x.\n", hr);
3598 memset(&output_buffer, 0, sizeof(output_buffer));
3599 output_buffer.pSample = sample;
3600 flags = 0;
3601 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output_buffer, &flags);
3602 todo_wine
3603 ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
3604 ok(output_buffer.dwStatus == 0, "Unexpected buffer status, %#x.\n", output_buffer.dwStatus);
3605 ok(flags == 0, "Unexpected status %#x.\n", flags);
3607 hr = MFCreateMemoryBuffer(1024 * 1024, &buffer);
3608 ok(hr == S_OK, "Failed to create a buffer, hr %#x.\n", hr);
3610 hr = IMFSample_AddBuffer(sample2, buffer);
3611 ok(hr == S_OK, "Failed to add a buffer, hr %#x.\n", hr);
3613 hr = IMFSample_AddBuffer(sample, buffer);
3614 ok(hr == S_OK, "Failed to add a buffer, hr %#x.\n", hr);
3616 memset(&output_buffer, 0, sizeof(output_buffer));
3617 output_buffer.pSample = sample;
3618 flags = 0;
3619 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output_buffer, &flags);
3620 todo_wine
3621 ok(hr == S_OK || broken(FAILED(hr)) /* Win8 */, "Failed to get output buffer, hr %#x.\n", hr);
3622 ok(output_buffer.dwStatus == 0, "Unexpected buffer status, %#x.\n", output_buffer.dwStatus);
3623 ok(flags == 0, "Unexpected status %#x.\n", flags);
3625 if (SUCCEEDED(hr))
3627 memset(&output_buffer, 0, sizeof(output_buffer));
3628 output_buffer.pSample = sample;
3629 flags = 0;
3630 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output_buffer, &flags);
3631 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "Unexpected hr %#x.\n", hr);
3632 ok(output_buffer.dwStatus == 0, "Unexpected buffer status, %#x.\n", output_buffer.dwStatus);
3633 ok(flags == 0, "Unexpected status %#x.\n", flags);
3636 IMFSample_Release(sample2);
3637 IMFSample_Release(sample);
3638 IMFMediaBuffer_Release(buffer);
3640 IMFMediaType_Release(media_type);
3642 IMFTransform_Release(transform);
3644 failed:
3645 CoUninitialize();
3648 static void test_quality_manager(void)
3650 IMFQualityManager *manager;
3651 HRESULT hr;
3653 hr = MFCreateStandardQualityManager(&manager);
3654 ok(hr == S_OK, "Failed to create quality manager, hr %#x.\n", hr);
3656 hr = IMFQualityManager_NotifyPresentationClock(manager, NULL);
3657 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
3659 IMFQualityManager_Release(manager);
3662 static void test_sar(void)
3664 IMFPresentationClock *present_clock, *present_clock2;
3665 IMFMediaType *mediatype, *mediatype2, *mediatype3;
3666 IMFClockStateSink *state_sink, *state_sink2;
3667 IMFMediaTypeHandler *handler, *handler2;
3668 IMFPresentationTimeSource *time_source;
3669 IMFSimpleAudioVolume *simple_volume;
3670 IMFAudioStreamVolume *stream_volume;
3671 IMFMediaSink *sink, *sink2;
3672 IMFStreamSink *stream_sink;
3673 IMFAttributes *attributes;
3674 DWORD i, id, flags, count;
3675 IMFActivate *activate;
3676 MFCLOCK_STATE state;
3677 IMFClock *clock;
3678 IUnknown *unk;
3679 HRESULT hr;
3680 GUID guid;
3681 BOOL mute;
3682 int found;
3684 hr = CoInitialize(NULL);
3685 ok(hr == S_OK, "Failed to initialize, hr %#x.\n", hr);
3687 hr = MFCreateAudioRenderer(NULL, &sink);
3688 if (hr == MF_E_NO_AUDIO_PLAYBACK_DEVICE)
3690 skip("No audio playback device available.\n");
3691 CoUninitialize();
3692 return;
3694 ok(hr == S_OK, "Failed to create renderer, hr %#x.\n", hr);
3696 hr = MFStartup(MF_VERSION, MFSTARTUP_FULL);
3697 ok(hr == S_OK, "Startup failure, hr %#x.\n", hr);
3699 hr = MFCreatePresentationClock(&present_clock);
3700 ok(hr == S_OK, "Failed to create presentation clock, hr %#x.\n", hr);
3702 hr = IMFMediaSink_QueryInterface(sink, &IID_IMFPresentationTimeSource, (void **)&time_source);
3703 todo_wine
3704 ok(hr == S_OK, "Failed to get time source interface, hr %#x.\n", hr);
3706 if (SUCCEEDED(hr))
3708 hr = IMFPresentationTimeSource_QueryInterface(time_source, &IID_IMFClockStateSink, (void **)&state_sink2);
3709 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
3710 hr = IMFPresentationTimeSource_QueryInterface(time_source, &IID_IMFClockStateSink, (void **)&state_sink);
3711 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
3712 ok(state_sink == state_sink2, "Unexpected clock sink.\n");
3713 IMFClockStateSink_Release(state_sink2);
3714 IMFClockStateSink_Release(state_sink);
3716 hr = IMFPresentationTimeSource_GetUnderlyingClock(time_source, &clock);
3717 ok(hr == MF_E_NO_CLOCK, "Unexpected hr %#x.\n", hr);
3719 hr = IMFPresentationTimeSource_GetClockCharacteristics(time_source, &flags);
3720 ok(hr == S_OK, "Failed to get flags, hr %#x.\n", hr);
3721 ok(flags == MFCLOCK_CHARACTERISTICS_FLAG_FREQUENCY_10MHZ, "Unexpected flags %#x.\n", flags);
3723 hr = IMFPresentationTimeSource_GetState(time_source, 0, &state);
3724 ok(hr == S_OK, "Failed to get clock state, hr %#x.\n", hr);
3725 ok(state == MFCLOCK_STATE_INVALID, "Unexpected state %d.\n", state);
3727 hr = IMFPresentationTimeSource_QueryInterface(time_source, &IID_IMFClockStateSink, (void **)&state_sink);
3728 ok(hr == S_OK, "Failed to get state sink, hr %#x.\n", hr);
3730 hr = IMFClockStateSink_OnClockStart(state_sink, 0, 0);
3731 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#x.\n", hr);
3733 IMFClockStateSink_Release(state_sink);
3735 IMFPresentationTimeSource_Release(time_source);
3737 hr = IMFMediaSink_AddStreamSink(sink, 123, NULL, &stream_sink);
3738 ok(hr == MF_E_STREAMSINKS_FIXED, "Unexpected hr %#x.\n", hr);
3740 hr = IMFMediaSink_RemoveStreamSink(sink, 0);
3741 ok(hr == MF_E_STREAMSINKS_FIXED, "Unexpected hr %#x.\n", hr);
3743 hr = IMFMediaSink_GetStreamSinkCount(sink, NULL);
3744 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
3746 hr = IMFMediaSink_GetStreamSinkCount(sink, &count);
3747 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
3748 ok(count == 1, "Unexpected count %u.\n", count);
3750 hr = IMFMediaSink_GetCharacteristics(sink, &flags);
3751 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
3752 ok(flags == (MEDIASINK_FIXED_STREAMS | MEDIASINK_CAN_PREROLL), "Unexpected flags %#x.\n", flags);
3754 check_interface(sink, &IID_IMFMediaSinkPreroll, TRUE);
3755 check_interface(sink, &IID_IMFMediaEventGenerator, TRUE);
3756 check_interface(sink, &IID_IMFClockStateSink, TRUE);
3757 check_interface(sink, &IID_IMFGetService, TRUE);
3758 todo_wine check_interface(sink, &IID_IMFPresentationTimeSource, TRUE);
3759 check_service_interface(sink, &MR_POLICY_VOLUME_SERVICE, &IID_IMFSimpleAudioVolume, TRUE);
3761 /* Clock */
3762 hr = IMFMediaSink_QueryInterface(sink, &IID_IMFClockStateSink, (void **)&state_sink);
3763 ok(hr == S_OK, "Failed to get interface, hr %#x.\n", hr);
3765 hr = IMFClockStateSink_OnClockStart(state_sink, 0, 0);
3766 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#x.\n", hr);
3768 hr = IMFClockStateSink_OnClockPause(state_sink, 0);
3769 ok(hr == MF_E_INVALID_STATE_TRANSITION, "Unexpected hr %#x.\n", hr);
3771 hr = IMFClockStateSink_OnClockStop(state_sink, 0);
3772 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#x.\n", hr);
3774 hr = IMFClockStateSink_OnClockRestart(state_sink, 0);
3775 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#x.\n", hr);
3777 IMFClockStateSink_Release(state_sink);
3779 hr = IMFMediaSink_SetPresentationClock(sink, NULL);
3780 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
3782 hr = IMFMediaSink_SetPresentationClock(sink, present_clock);
3783 todo_wine
3784 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#x.\n", hr);
3786 hr = MFCreateSystemTimeSource(&time_source);
3787 ok(hr == S_OK, "Failed to create time source, hr %#x.\n", hr);
3789 hr = IMFPresentationClock_SetTimeSource(present_clock, time_source);
3790 ok(hr == S_OK, "Failed to set time source, hr %#x.\n", hr);
3791 IMFPresentationTimeSource_Release(time_source);
3793 hr = IMFMediaSink_SetPresentationClock(sink, present_clock);
3794 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
3796 hr = IMFMediaSink_GetPresentationClock(sink, NULL);
3797 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
3799 hr = IMFMediaSink_GetPresentationClock(sink, &present_clock2);
3800 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
3801 ok(present_clock == present_clock2, "Unexpected instance.\n");
3802 IMFPresentationClock_Release(present_clock2);
3804 /* Stream */
3805 hr = IMFMediaSink_GetStreamSinkByIndex(sink, 0, &stream_sink);
3806 ok(hr == S_OK, "Failed to get a stream, hr %#x.\n", hr);
3808 check_interface(stream_sink, &IID_IMFMediaEventGenerator, TRUE);
3809 check_interface(stream_sink, &IID_IMFMediaTypeHandler, TRUE);
3810 todo_wine check_interface(stream_sink, &IID_IMFGetService, TRUE);
3812 hr = IMFStreamSink_GetIdentifier(stream_sink, &id);
3813 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
3814 ok(!id, "Unexpected id.\n");
3816 hr = IMFStreamSink_GetMediaSink(stream_sink, &sink2);
3817 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
3818 ok(sink == sink2, "Unexpected object.\n");
3819 IMFMediaSink_Release(sink2);
3821 hr = IMFStreamSink_GetMediaTypeHandler(stream_sink, &handler);
3822 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
3824 hr = IMFStreamSink_QueryInterface(stream_sink, &IID_IMFMediaTypeHandler, (void **)&handler2);
3825 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
3826 ok(handler2 == handler, "Unexpected instance.\n");
3827 IMFMediaTypeHandler_Release(handler2);
3829 hr = IMFMediaTypeHandler_GetMajorType(handler, &guid);
3830 ok(hr == S_OK, "Failed to get major type, hr %#x.\n", hr);
3831 ok(IsEqualGUID(&guid, &MFMediaType_Audio), "Unexpected type %s.\n", wine_dbgstr_guid(&guid));
3833 count = 0;
3834 hr = IMFMediaTypeHandler_GetMediaTypeCount(handler, &count);
3835 ok(hr == S_OK, "Failed to get type count, hr %#x.\n", hr);
3836 ok(!!count, "Unexpected type count %u.\n", count);
3838 /* A number of same major/subtype entries are returned, with different degrees of finer format
3839 details. Some incomplete types are not accepted, check that at least one of them is considered supported. */
3841 for (i = 0, found = -1; i < count; ++i)
3843 hr = IMFMediaTypeHandler_GetMediaTypeByIndex(handler, i, &mediatype);
3844 ok(hr == S_OK, "Failed to get media type, hr %#x.\n", hr);
3846 if (SUCCEEDED(IMFMediaTypeHandler_IsMediaTypeSupported(handler, mediatype, NULL)))
3847 found = i;
3848 IMFMediaType_Release(mediatype);
3850 if (found != -1) break;
3852 ok(found != -1, "Haven't found a supported type.\n");
3854 hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, &mediatype);
3855 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#x.\n", hr);
3857 hr = MFCreateMediaType(&mediatype);
3858 ok(hr == S_OK, "Failed to create media type, hr %#x.\n", hr);
3860 /* Actual return value is MF_E_ATRIBUTENOTFOUND triggered by missing MF_MT_MAJOR_TYPE */
3861 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, mediatype, NULL);
3862 ok(FAILED(hr), "Unexpected hr %#x.\n", hr);
3864 hr = IMFMediaType_SetGUID(mediatype, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
3865 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
3866 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, mediatype, NULL);
3867 ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#x.\n", hr);
3869 hr = IMFMediaType_SetGUID(mediatype, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio);
3870 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
3871 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, mediatype, NULL);
3872 ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#x.\n", hr);
3874 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, mediatype);
3875 ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#x.\n", hr);
3877 hr = IMFMediaTypeHandler_GetMediaTypeByIndex(handler, found, &mediatype2);
3878 ok(hr == S_OK, "Failed to get media type, hr %#x.\n", hr);
3880 hr = IMFMediaTypeHandler_GetMediaTypeByIndex(handler, found, &mediatype3);
3881 ok(hr == S_OK, "Failed to get media type, hr %#x.\n", hr);
3882 ok(mediatype2 == mediatype3, "Unexpected instance.\n");
3883 IMFMediaType_Release(mediatype3);
3885 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, mediatype2, NULL);
3886 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
3888 IMFMediaType_Release(mediatype);
3890 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, mediatype2);
3891 ok(hr == S_OK, "Failed to set current type, hr %#x.\n", hr);
3893 hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, &mediatype);
3894 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
3895 ok(mediatype == mediatype2, "Unexpected instance.\n");
3896 IMFMediaType_Release(mediatype);
3898 IMFMediaType_Release(mediatype2);
3900 /* Reset back to uninitialized state. */
3901 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, NULL);
3902 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
3904 IMFMediaTypeHandler_Release(handler);
3906 /* State change with initialized stream. */
3907 hr = IMFMediaSink_QueryInterface(sink, &IID_IMFClockStateSink, (void **)&state_sink);
3908 ok(hr == S_OK, "Failed to get interface, hr %#x.\n", hr);
3910 hr = IMFClockStateSink_OnClockStart(state_sink, 0, 0);
3911 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
3913 hr = IMFClockStateSink_OnClockStart(state_sink, 0, 0);
3914 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
3916 hr = IMFClockStateSink_OnClockPause(state_sink, 0);
3917 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
3919 hr = IMFClockStateSink_OnClockStop(state_sink, 0);
3920 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
3922 hr = IMFClockStateSink_OnClockStop(state_sink, 0);
3923 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
3925 hr = IMFClockStateSink_OnClockPause(state_sink, 0);
3926 ok(hr == MF_E_INVALID_STATE_TRANSITION, "Unexpected hr %#x.\n", hr);
3928 hr = IMFClockStateSink_OnClockRestart(state_sink, 0);
3929 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
3931 hr = IMFClockStateSink_OnClockRestart(state_sink, 0);
3932 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
3934 hr = IMFClockStateSink_OnClockStop(state_sink, 0);
3935 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
3937 IMFClockStateSink_Release(state_sink);
3939 IMFStreamSink_Release(stream_sink);
3941 /* Volume control */
3942 hr = MFGetService((IUnknown *)sink, &MR_POLICY_VOLUME_SERVICE, &IID_IMFSimpleAudioVolume, (void **)&simple_volume);
3943 ok(hr == S_OK, "Failed to get interface, hr %#x.\n", hr);
3945 hr = IMFSimpleAudioVolume_GetMute(simple_volume, &mute);
3946 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
3948 IMFSimpleAudioVolume_Release(simple_volume);
3950 hr = MFGetService((IUnknown *)sink, &MR_STREAM_VOLUME_SERVICE, &IID_IMFAudioStreamVolume, (void **)&stream_volume);
3951 ok(hr == S_OK, "Failed to get interface, hr %#x.\n", hr);
3953 hr = IMFAudioStreamVolume_GetChannelCount(stream_volume, &count);
3954 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
3956 hr = IMFAudioStreamVolume_GetChannelCount(stream_volume, NULL);
3957 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
3959 IMFAudioStreamVolume_Release(stream_volume);
3961 hr = MFGetService((IUnknown *)sink, &MR_AUDIO_POLICY_SERVICE, &IID_IMFAudioPolicy, (void **)&unk);
3962 ok(hr == S_OK, "Failed to get interface, hr %#x.\n", hr);
3963 IUnknown_Release(unk);
3965 /* Shutdown */
3966 EXPECT_REF(present_clock, 2);
3967 hr = IMFMediaSink_Shutdown(sink);
3968 ok(hr == S_OK, "Failed to shut down, hr %#x.\n", hr);
3969 EXPECT_REF(present_clock, 1);
3971 hr = IMFMediaSink_Shutdown(sink);
3972 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr);
3974 hr = IMFMediaSink_AddStreamSink(sink, 123, NULL, &stream_sink);
3975 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr);
3977 hr = IMFMediaSink_RemoveStreamSink(sink, 0);
3978 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr);
3980 hr = IMFMediaSink_GetStreamSinkCount(sink, NULL);
3981 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
3983 hr = IMFMediaSink_GetStreamSinkCount(sink, &count);
3984 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr);
3986 hr = IMFMediaSink_GetCharacteristics(sink, &flags);
3987 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr);
3989 hr = IMFMediaSink_SetPresentationClock(sink, NULL);
3990 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr);
3992 hr = IMFMediaSink_SetPresentationClock(sink, present_clock);
3993 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr);
3995 hr = IMFMediaSink_GetPresentationClock(sink, NULL);
3996 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
3998 hr = IMFMediaSink_GetPresentationClock(sink, &present_clock2);
3999 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr);
4001 IMFMediaSink_Release(sink);
4003 /* Activation */
4004 hr = MFCreateAudioRendererActivate(&activate);
4005 ok(hr == S_OK, "Failed to create activation object, hr %#x.\n", hr);
4007 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink);
4008 ok(hr == S_OK, "Failed to activate, hr %#x.\n", hr);
4010 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink2);
4011 ok(hr == S_OK, "Failed to activate, hr %#x.\n", hr);
4012 ok(sink == sink2, "Unexpected instance.\n");
4013 IMFMediaSink_Release(sink2);
4015 hr = IMFMediaSink_GetCharacteristics(sink, &flags);
4016 ok(hr == S_OK, "Failed to get sink flags, hr %#x.\n", hr);
4018 hr = IMFActivate_ShutdownObject(activate);
4019 ok(hr == S_OK, "Failed to shut down, hr %#x.\n", hr);
4021 hr = IMFMediaSink_GetCharacteristics(sink, &flags);
4022 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr);
4024 IMFMediaSink_Release(sink);
4026 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink);
4027 ok(hr == S_OK, "Failed to activate, hr %#x.\n", hr);
4029 hr = IMFMediaSink_GetCharacteristics(sink, &flags);
4030 todo_wine
4031 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr);
4033 IMFMediaSink_Release(sink);
4035 hr = IMFActivate_DetachObject(activate);
4036 ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
4038 IMFActivate_Release(activate);
4040 IMFPresentationClock_Release(present_clock);
4042 hr = MFShutdown();
4043 ok(hr == S_OK, "Shutdown failure, hr %#x.\n", hr);
4045 /* SAR attributes */
4046 hr = MFCreateAttributes(&attributes, 0);
4047 ok(hr == S_OK, "Failed to create attributes, hr %#x.\n", hr);
4049 /* Specify role. */
4050 hr = IMFAttributes_SetUINT32(attributes, &MF_AUDIO_RENDERER_ATTRIBUTE_ENDPOINT_ROLE, eMultimedia);
4051 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
4053 hr = MFCreateAudioRenderer(attributes, &sink);
4054 ok(hr == S_OK, "Failed to create a sink, hr %#x.\n", hr);
4055 IMFMediaSink_Release(sink);
4057 /* Invalid endpoint. */
4058 hr = IMFAttributes_SetString(attributes, &MF_AUDIO_RENDERER_ATTRIBUTE_ENDPOINT_ID, L"endpoint");
4059 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
4061 hr = MFCreateAudioRenderer(attributes, &sink);
4062 ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
4064 hr = IMFAttributes_DeleteItem(attributes, &MF_AUDIO_RENDERER_ATTRIBUTE_ENDPOINT_ROLE);
4065 ok(hr == S_OK, "Failed to remove attribute, hr %#x.\n", hr);
4067 hr = MFCreateAudioRenderer(attributes, &sink);
4068 ok(hr == MF_E_NO_AUDIO_PLAYBACK_DEVICE, "Failed to create a sink, hr %#x.\n", hr);
4070 CoUninitialize();
4073 static void test_evr(void)
4075 IMFVideoSampleAllocatorCallback *allocator_callback;
4076 IMFStreamSink *stream_sink, *stream_sink2;
4077 IMFVideoDisplayControl *display_control;
4078 IMFMediaType *media_type, *media_type2;
4079 IMFVideoSampleAllocator *allocator;
4080 IMFMediaTypeHandler *type_handler;
4081 IMFVideoRenderer *video_renderer;
4082 IMFMediaSink *sink, *sink2;
4083 IMFAttributes *attributes;
4084 DWORD flags, count, value;
4085 IMFActivate *activate;
4086 HWND window, window2;
4087 LONG sample_count;
4088 IMFGetService *gs;
4089 IMFSample *sample;
4090 IUnknown *unk;
4091 UINT64 window3;
4092 HRESULT hr;
4093 GUID guid;
4095 hr = CoInitialize(NULL);
4096 ok(hr == S_OK, "Failed to initialize, hr %#x.\n", hr);
4098 hr = MFCreateVideoRenderer(&IID_IMFVideoRenderer, (void **)&video_renderer);
4099 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4101 hr = IMFVideoRenderer_InitializeRenderer(video_renderer, NULL, NULL);
4102 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4104 IMFVideoRenderer_Release(video_renderer);
4106 hr = MFCreateVideoRendererActivate(NULL, NULL);
4107 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
4109 /* Window */
4110 window = create_window();
4111 hr = MFCreateVideoRendererActivate(window, &activate);
4112 ok(hr == S_OK, "Failed to create activate object, hr %#x.\n", hr);
4114 hr = IMFActivate_GetUINT64(activate, &MF_ACTIVATE_VIDEO_WINDOW, &window3);
4115 ok(hr == S_OK, "Failed to get attribute, hr %#x.\n", hr);
4116 ok(UlongToHandle(window3) == window, "Unexpected value.\n");
4118 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink);
4119 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4121 check_interface(sink, &IID_IMFMediaSinkPreroll, TRUE);
4122 check_interface(sink, &IID_IMFVideoRenderer, TRUE);
4123 check_interface(sink, &IID_IMFMediaEventGenerator, TRUE);
4124 check_interface(sink, &IID_IMFClockStateSink, TRUE);
4125 check_interface(sink, &IID_IMFGetService, TRUE);
4126 check_interface(sink, &IID_IMFQualityAdvise, TRUE);
4128 hr = MFGetService((IUnknown *)sink, &MR_VIDEO_RENDER_SERVICE, &IID_IMFVideoDisplayControl,
4129 (void **)&display_control);
4130 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4132 window2 = NULL;
4133 hr = IMFVideoDisplayControl_GetVideoWindow(display_control, &window2);
4134 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4135 ok(window2 == window, "Unexpected window %p.\n", window2);
4137 IMFVideoDisplayControl_Release(display_control);
4138 IMFMediaSink_Release(sink);
4139 IMFActivate_Release(activate);
4140 DestroyWindow(window);
4142 hr = MFCreateVideoRendererActivate(NULL, &activate);
4143 ok(hr == S_OK, "Failed to create activate object, hr %#x.\n", hr);
4145 hr = IMFActivate_GetCount(activate, &count);
4146 ok(hr == S_OK, "Failed to get attribute count, hr %#x.\n", hr);
4147 ok(count == 1, "Unexpected count %u.\n", count);
4149 hr = IMFActivate_GetUINT64(activate, &MF_ACTIVATE_VIDEO_WINDOW, &window3);
4150 ok(hr == S_OK, "Failed to get attribute, hr %#x.\n", hr);
4151 ok(!window3, "Unexpected value.\n");
4153 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink);
4154 ok(hr == S_OK, "Failed to activate, hr %#x.\n", hr);
4156 hr = IMFMediaSink_QueryInterface(sink, &IID_IMFAttributes, (void **)&attributes);
4157 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4158 hr = IMFAttributes_QueryInterface(attributes, &IID_IMFMediaSink, (void **)&unk);
4159 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4160 IUnknown_Release(unk);
4161 hr = IMFAttributes_GetCount(attributes, &count);
4162 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4163 ok(!!count, "Unexpected count %u.\n", count);
4164 /* Rendering preferences are not immediately propagated to the presenter. */
4165 hr = IMFAttributes_SetUINT32(attributes, &EVRConfig_ForceBob, 1);
4166 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4167 hr = MFGetService((IUnknown *)sink, &MR_VIDEO_RENDER_SERVICE, &IID_IMFVideoDisplayControl, (void **)&display_control);
4168 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4169 hr = IMFVideoDisplayControl_GetRenderingPrefs(display_control, &flags);
4170 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4171 ok(!flags, "Unexpected flags %#x.\n", flags);
4172 IMFVideoDisplayControl_Release(display_control);
4173 IMFAttributes_Release(attributes);
4175 /* Primary stream type handler. */
4176 hr = IMFMediaSink_GetStreamSinkById(sink, 0, &stream_sink);
4177 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4179 hr = IMFStreamSink_QueryInterface(stream_sink, &IID_IMFAttributes, (void **)&attributes);
4180 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4181 hr = IMFAttributes_GetCount(attributes, &count);
4182 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4183 ok(count == 2, "Unexpected count %u.\n", count);
4184 value = 0;
4185 hr = IMFAttributes_GetUINT32(attributes, &MF_SA_REQUIRED_SAMPLE_COUNT, &value);
4186 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4187 ok(value == 1, "Unexpected attribute value %u.\n", value);
4188 value = 0;
4189 hr = IMFAttributes_GetUINT32(attributes, &MF_SA_D3D_AWARE, &value);
4190 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4191 ok(value == 1, "Unexpected attribute value %u.\n", value);
4193 hr = IMFAttributes_QueryInterface(attributes, &IID_IMFStreamSink, (void **)&unk);
4194 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4195 IUnknown_Release(unk);
4196 IMFAttributes_Release(attributes);
4198 hr = IMFStreamSink_GetMediaTypeHandler(stream_sink, &type_handler);
4199 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4201 hr = IMFMediaTypeHandler_GetMajorType(type_handler, NULL);
4202 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
4204 hr = IMFMediaTypeHandler_GetMajorType(type_handler, &guid);
4205 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4206 ok(IsEqualGUID(&guid, &MFMediaType_Video), "Unexpected type %s.\n", wine_dbgstr_guid(&guid));
4208 /* Supported types are not advertised. */
4209 hr = IMFMediaTypeHandler_GetMediaTypeCount(type_handler, NULL);
4210 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
4212 count = 1;
4213 hr = IMFMediaTypeHandler_GetMediaTypeCount(type_handler, &count);
4214 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4215 ok(!count, "Unexpected count %u.\n", count);
4217 hr = IMFMediaTypeHandler_GetMediaTypeByIndex(type_handler, 0, NULL);
4218 ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#x.\n", hr);
4220 hr = IMFMediaTypeHandler_GetMediaTypeByIndex(type_handler, 0, &media_type);
4221 ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#x.\n", hr);
4223 hr = IMFMediaTypeHandler_GetCurrentMediaType(type_handler, NULL);
4224 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
4226 hr = IMFMediaTypeHandler_GetCurrentMediaType(type_handler, &media_type);
4227 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#x.\n", hr);
4229 hr = IMFMediaTypeHandler_SetCurrentMediaType(type_handler, NULL);
4230 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
4232 hr = MFCreateMediaType(&media_type);
4233 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4235 hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
4236 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4238 hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFVideoFormat_RGB32);
4239 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4241 hr = IMFMediaType_SetUINT64(media_type, &MF_MT_FRAME_SIZE, (UINT64)640 << 32 | 480);
4242 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4244 hr = IMFMediaTypeHandler_IsMediaTypeSupported(type_handler, NULL, NULL);
4245 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
4247 hr = IMFMediaTypeHandler_IsMediaTypeSupported(type_handler, media_type, &media_type2);
4248 ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#x.\n", hr);
4250 hr = IMFMediaType_SetUINT32(media_type, &MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE);
4251 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4253 media_type2 = (void *)0x1;
4254 hr = IMFMediaTypeHandler_IsMediaTypeSupported(type_handler, media_type, &media_type2);
4255 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4256 ok(!media_type2, "Unexpected media type %p.\n", media_type2);
4258 hr = IMFMediaTypeHandler_SetCurrentMediaType(type_handler, media_type);
4259 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4261 hr = IMFMediaTypeHandler_GetCurrentMediaType(type_handler, &media_type2);
4262 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4263 hr = IMFMediaType_QueryInterface(media_type2, &IID_IMFVideoMediaType, (void **)&unk);
4264 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4265 IUnknown_Release(unk);
4266 IMFMediaType_Release(media_type2);
4268 IMFMediaType_Release(media_type);
4270 IMFMediaTypeHandler_Release(type_handler);
4272 /* Stream uses an allocator. */
4273 hr = MFGetService((IUnknown *)stream_sink, &MR_VIDEO_ACCELERATION_SERVICE, &IID_IMFVideoSampleAllocator,
4274 (void **)&allocator);
4275 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4277 hr = IMFVideoSampleAllocator_QueryInterface(allocator, &IID_IMFVideoSampleAllocatorCallback, (void **)&allocator_callback);
4278 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4280 sample_count = 0;
4281 hr = IMFVideoSampleAllocatorCallback_GetFreeSampleCount(allocator_callback, &sample_count);
4282 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4283 ok(!sample_count, "Unexpected sample count %d.\n", sample_count);
4285 hr = IMFVideoSampleAllocator_AllocateSample(allocator, &sample);
4286 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#x.\n", hr);
4288 IMFVideoSampleAllocatorCallback_Release(allocator_callback);
4289 IMFVideoSampleAllocator_Release(allocator);
4291 /* Same test for a substream. */
4292 hr = IMFMediaSink_AddStreamSink(sink, 1, NULL, &stream_sink2);
4293 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4295 hr = MFGetService((IUnknown *)stream_sink2, &MR_VIDEO_ACCELERATION_SERVICE, &IID_IMFVideoSampleAllocator,
4296 (void **)&allocator);
4297 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4298 IMFVideoSampleAllocator_Release(allocator);
4300 hr = IMFMediaSink_RemoveStreamSink(sink, 1);
4301 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4303 IMFStreamSink_Release(stream_sink2);
4305 hr = IMFMediaSink_GetCharacteristics(sink, &flags);
4306 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4307 ok(flags == (MEDIASINK_CAN_PREROLL | MEDIASINK_CLOCK_REQUIRED), "Unexpected flags %#x.\n", flags);
4309 hr = IMFMediaSink_QueryInterface(sink, &IID_IMFGetService, (void **)&gs);
4310 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4312 hr = IMFGetService_GetService(gs, &MR_VIDEO_MIXER_SERVICE, &IID_IMFVideoMixerControl, (void **)&unk);
4313 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4314 IUnknown_Release(unk);
4316 IMFGetService_Release(gs);
4318 hr = IMFActivate_ShutdownObject(activate);
4319 ok(hr == S_OK, "Failed to shut down, hr %#x.\n", hr);
4321 hr = IMFMediaSink_GetCharacteristics(sink, &flags);
4322 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr);
4324 /* Activate again. */
4325 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink2);
4326 ok(hr == S_OK, "Failed to activate, hr %#x.\n", hr);
4327 todo_wine
4328 ok(sink == sink2, "Unexpected instance.\n");
4329 IMFMediaSink_Release(sink2);
4331 hr = IMFActivate_DetachObject(activate);
4332 ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
4334 hr = IMFMediaSink_GetCharacteristics(sink, &flags);
4335 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr);
4337 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink2);
4338 ok(hr == S_OK, "Failed to activate, hr %#x.\n", hr);
4340 hr = IMFActivate_ShutdownObject(activate);
4341 ok(hr == S_OK, "Failed to shut down, hr %#x.\n", hr);
4343 IMFMediaSink_Release(sink2);
4344 IMFMediaSink_Release(sink);
4346 IMFActivate_Release(activate);
4348 CoUninitialize();
4351 static void test_MFCreateSimpleTypeHandler(void)
4353 IMFMediaType *media_type, *media_type2, *media_type3;
4354 IMFMediaTypeHandler *handler;
4355 DWORD count;
4356 HRESULT hr;
4357 GUID guid;
4359 hr = MFCreateSimpleTypeHandler(&handler);
4360 ok(hr == S_OK, "Failed to create object, hr %#x.\n", hr);
4362 hr = IMFMediaTypeHandler_GetMediaTypeCount(handler, NULL);
4363 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
4365 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, NULL, NULL);
4366 ok(hr == MF_E_UNEXPECTED, "Unexpected hr %#x.\n", hr);
4368 count = 0;
4369 hr = IMFMediaTypeHandler_GetMediaTypeCount(handler, &count);
4370 ok(hr == S_OK, "Failed to get type count, hr %#x.\n", hr);
4371 ok(count == 1, "Unexpected count %u.\n", count);
4373 hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, NULL);
4374 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
4376 media_type = (void *)0xdeadbeef;
4377 hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, &media_type);
4378 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4379 ok(!media_type, "Unexpected pointer.\n");
4381 hr = MFCreateMediaType(&media_type);
4382 ok(hr == S_OK, "Failed to create media type, hr %#x.\n", hr);
4384 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type, NULL);
4385 ok(hr == MF_E_UNEXPECTED, "Unexpected hr %#x.\n", hr);
4387 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, media_type);
4388 ok(hr == S_OK, "Failed to set current type, hr %#x.\n", hr);
4390 hr = IMFMediaTypeHandler_GetMediaTypeByIndex(handler, 0, &media_type2);
4391 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4392 ok(media_type2 == media_type, "Unexpected type.\n");
4393 IMFMediaType_Release(media_type2);
4395 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, NULL, NULL);
4396 ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
4398 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type, NULL);
4399 ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
4401 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type, &media_type2);
4402 ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
4404 hr = IMFMediaTypeHandler_GetMediaTypeByIndex(handler, 1, &media_type2);
4405 ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#x.\n", hr);
4407 hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, &media_type2);
4408 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4409 ok(media_type == media_type2, "Unexpected pointer.\n");
4410 IMFMediaType_Release(media_type2);
4412 hr = IMFMediaTypeHandler_GetMajorType(handler, &guid);
4413 ok(hr == MF_E_ATTRIBUTENOTFOUND, "Unexpected hr %#x.\n", hr);
4415 hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
4416 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
4418 hr = IMFMediaTypeHandler_GetMajorType(handler, &guid);
4419 ok(hr == S_OK, "Failed to get major type, hr %#x.\n", hr);
4420 ok(IsEqualGUID(&guid, &MFMediaType_Video), "Unexpected major type.\n");
4422 hr = MFCreateMediaType(&media_type3);
4423 ok(hr == S_OK, "Failed to create media type, hr %#x.\n", hr);
4425 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type3, NULL);
4426 ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
4428 hr = IMFMediaType_SetGUID(media_type3, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio);
4429 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
4431 /* Different major types. */
4432 media_type2 = (void *)0xdeadbeef;
4433 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type3, &media_type2);
4434 ok(hr == E_FAIL, "Unexpected hr %#x.\n", hr);
4435 ok(!media_type2, "Unexpected pointer.\n");
4437 hr = IMFMediaType_SetGUID(media_type3, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
4438 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
4440 media_type2 = (void *)0xdeadbeef;
4441 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type3, &media_type2);
4442 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4443 ok(!media_type2, "Unexpected pointer.\n");
4445 /* Handler missing subtype. */
4446 hr = IMFMediaType_SetGUID(media_type3, &MF_MT_SUBTYPE, &MFVideoFormat_RGB8);
4447 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
4449 media_type2 = (void *)0xdeadbeef;
4450 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type3, &media_type2);
4451 ok(hr == E_FAIL, "Unexpected hr %#x.\n", hr);
4452 ok(!media_type2, "Unexpected pointer.\n");
4454 /* Different subtypes. */
4455 hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFVideoFormat_RGB24);
4456 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
4458 media_type2 = (void *)0xdeadbeef;
4459 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type3, &media_type2);
4460 ok(hr == E_FAIL, "Unexpected hr %#x.\n", hr);
4461 ok(!media_type2, "Unexpected pointer.\n");
4463 /* Same major/subtype. */
4464 hr = IMFMediaType_SetGUID(media_type3, &MF_MT_SUBTYPE, &MFVideoFormat_RGB24);
4465 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
4467 media_type2 = (void *)0xdeadbeef;
4468 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type3, &media_type2);
4469 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4470 ok(!media_type2, "Unexpected pointer.\n");
4472 /* Set one more attribute. */
4473 hr = IMFMediaType_SetUINT64(media_type, &MF_MT_FRAME_SIZE, (UINT64)4 << 32 | 4);
4474 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
4476 media_type2 = (void *)0xdeadbeef;
4477 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type3, &media_type2);
4478 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4479 ok(!media_type2, "Unexpected pointer.\n");
4481 IMFMediaType_Release(media_type3);
4482 IMFMediaType_Release(media_type);
4484 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, NULL);
4485 ok(hr == S_OK, "Failed to set current type, hr %#x.\n", hr);
4487 media_type = (void *)0xdeadbeef;
4488 hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, &media_type);
4489 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4490 ok(!media_type, "Unexpected pointer.\n");
4492 hr = IMFMediaTypeHandler_GetMajorType(handler, &guid);
4493 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#x.\n", hr);
4495 IMFMediaTypeHandler_Release(handler);
4498 static void test_MFGetSupportedMimeTypes(void)
4500 PROPVARIANT value;
4501 HRESULT hr;
4503 hr = MFGetSupportedMimeTypes(NULL);
4504 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
4506 value.vt = VT_EMPTY;
4507 hr = MFGetSupportedMimeTypes(&value);
4508 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4509 ok(value.vt == (VT_VECTOR | VT_LPWSTR), "Unexpected value type %#x.\n", value.vt);
4511 PropVariantClear(&value);
4514 static void test_MFGetSupportedSchemes(void)
4516 PROPVARIANT value;
4517 HRESULT hr;
4519 hr = MFGetSupportedSchemes(NULL);
4520 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
4522 value.vt = VT_EMPTY;
4523 hr = MFGetSupportedSchemes(&value);
4524 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4525 ok(value.vt == (VT_VECTOR | VT_LPWSTR), "Unexpected value type %#x.\n", value.vt);
4527 PropVariantClear(&value);
4530 static BOOL is_sample_copier_available_type(IMFMediaType *type)
4532 GUID major = { 0 };
4533 UINT32 count;
4534 HRESULT hr;
4536 hr = IMFMediaType_GetMajorType(type, &major);
4537 ok(hr == S_OK, "Failed to get major type, hr %#x.\n", hr);
4539 hr = IMFMediaType_GetCount(type, &count);
4540 ok(hr == S_OK, "Failed to get attribute count, hr %#x.\n", hr);
4541 ok(count == 1, "Unexpected attribute count %u.\n", count);
4543 return IsEqualGUID(&major, &MFMediaType_Video) || IsEqualGUID(&major, &MFMediaType_Audio);
4546 static void test_sample_copier(void)
4548 IMFAttributes *attributes, *attributes2;
4549 DWORD in_min, in_max, out_min, out_max;
4550 IMFMediaType *mediatype, *mediatype2;
4551 MFT_OUTPUT_STREAM_INFO output_info;
4552 IMFSample *sample, *client_sample;
4553 MFT_INPUT_STREAM_INFO input_info;
4554 DWORD input_count, output_count;
4555 MFT_OUTPUT_DATA_BUFFER buffer;
4556 IMFMediaBuffer *media_buffer;
4557 DWORD count, flags, status;
4558 IMFTransform *copier;
4559 UINT32 value;
4560 HRESULT hr;
4562 hr = MFCreateSampleCopierMFT(&copier);
4563 ok(hr == S_OK, "Failed to create sample copier, hr %#x.\n", hr);
4565 hr = IMFTransform_GetAttributes(copier, &attributes);
4566 ok(hr == S_OK, "Failed to get transform attributes, hr %#x.\n", hr);
4567 hr = IMFTransform_GetAttributes(copier, &attributes2);
4568 ok(hr == S_OK, "Failed to get transform attributes, hr %#x.\n", hr);
4569 ok(attributes == attributes2, "Unexpected instance.\n");
4570 IMFAttributes_Release(attributes2);
4571 hr = IMFAttributes_GetCount(attributes, &count);
4572 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4573 ok(count == 1, "Unexpected attribute count %u.\n", count);
4574 hr = IMFAttributes_GetUINT32(attributes, &MFT_SUPPORT_DYNAMIC_FORMAT_CHANGE, &value);
4575 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4576 ok(!!value, "Unexpected value %u.\n", value);
4577 IMFAttributes_Release(attributes);
4579 hr = IMFTransform_GetInputStreamAttributes(copier, 0, &attributes);
4580 ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
4582 hr = IMFTransform_GetInputStreamAttributes(copier, 1, &attributes);
4583 ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
4585 hr = IMFTransform_GetOutputStreamAttributes(copier, 0, &attributes);
4586 ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
4588 hr = IMFTransform_GetOutputStreamAttributes(copier, 1, &attributes);
4589 ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
4591 hr = IMFTransform_SetOutputBounds(copier, 0, 0);
4592 ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
4594 /* No dynamic streams. */
4595 input_count = output_count = 0;
4596 hr = IMFTransform_GetStreamCount(copier, &input_count, &output_count);
4597 ok(hr == S_OK, "Failed to get stream count, hr %#x.\n", hr);
4598 ok(input_count == 1 && output_count == 1, "Unexpected streams count.\n");
4600 hr = IMFTransform_GetStreamLimits(copier, &in_min, &in_max, &out_min, &out_max);
4601 ok(hr == S_OK, "Failed to get stream limits, hr %#x.\n", hr);
4602 ok(in_min == in_max && in_min == 1 && out_min == out_max && out_min == 1, "Unexpected stream limits.\n");
4604 hr = IMFTransform_GetStreamIDs(copier, 1, &input_count, 1, &output_count);
4605 ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
4607 hr = IMFTransform_DeleteInputStream(copier, 0);
4608 ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
4610 /* Available types. */
4611 hr = IMFTransform_GetInputAvailableType(copier, 0, 0, &mediatype);
4612 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4613 ok(is_sample_copier_available_type(mediatype), "Unexpected type.\n");
4614 IMFMediaType_Release(mediatype);
4616 hr = IMFTransform_GetInputAvailableType(copier, 0, 1, &mediatype);
4617 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4618 ok(is_sample_copier_available_type(mediatype), "Unexpected type.\n");
4619 IMFMediaType_Release(mediatype);
4621 hr = IMFTransform_GetInputAvailableType(copier, 0, 2, &mediatype);
4622 ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#x.\n", hr);
4624 hr = IMFTransform_GetInputAvailableType(copier, 1, 0, &mediatype);
4625 ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#x.\n", hr);
4627 hr = IMFTransform_GetOutputAvailableType(copier, 0, 0, &mediatype);
4628 ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#x.\n", hr);
4630 hr = IMFTransform_GetOutputAvailableType(copier, 1, 0, &mediatype);
4631 ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#x.\n", hr);
4633 hr = IMFTransform_GetInputCurrentType(copier, 0, &mediatype);
4634 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#x.\n", hr);
4636 hr = IMFTransform_GetInputCurrentType(copier, 1, &mediatype);
4637 ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#x.\n", hr);
4639 hr = IMFTransform_GetOutputCurrentType(copier, 0, &mediatype);
4640 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#x.\n", hr);
4642 hr = IMFTransform_GetOutputCurrentType(copier, 1, &mediatype);
4643 ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#x.\n", hr);
4645 hr = MFCreateSample(&sample);
4646 ok(hr == S_OK, "Failed to create a sample, hr %#x.\n", hr);
4648 hr = IMFTransform_ProcessInput(copier, 0, sample, 0);
4649 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#x.\n", hr);
4651 hr = MFCreateMediaType(&mediatype);
4652 ok(hr == S_OK, "Failed to create media type, hr %#x.\n", hr);
4654 hr = IMFTransform_SetOutputType(copier, 0, mediatype, 0);
4655 ok(hr == MF_E_ATTRIBUTENOTFOUND, "Unexpected hr %#x.\n", hr);
4657 hr = IMFMediaType_SetGUID(mediatype, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
4658 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
4660 hr = IMFMediaType_SetGUID(mediatype, &MF_MT_SUBTYPE, &MFVideoFormat_RGB8);
4661 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
4663 hr = IMFMediaType_SetUINT64(mediatype, &MF_MT_FRAME_SIZE, ((UINT64)16) << 32 | 16);
4664 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
4666 hr = IMFTransform_GetOutputStreamInfo(copier, 0, &output_info);
4667 ok(hr == S_OK, "Failed to get stream info, hr %#x.\n", hr);
4668 ok(!output_info.dwFlags, "Unexpected flags %#x.\n", output_info.dwFlags);
4669 ok(!output_info.cbSize, "Unexpected size %u.\n", output_info.cbSize);
4670 ok(!output_info.cbAlignment, "Unexpected alignment %u.\n", output_info.cbAlignment);
4672 hr = IMFTransform_GetInputStreamInfo(copier, 0, &input_info);
4673 ok(hr == S_OK, "Failed to get stream info, hr %#x.\n", hr);
4675 ok(!input_info.hnsMaxLatency, "Unexpected latency %s.\n", wine_dbgstr_longlong(input_info.hnsMaxLatency));
4676 ok(!input_info.dwFlags, "Unexpected flags %#x.\n", input_info.dwFlags);
4677 ok(!input_info.cbSize, "Unexpected size %u.\n", input_info.cbSize);
4678 ok(!input_info.cbMaxLookahead, "Unexpected lookahead size %u.\n", input_info.cbMaxLookahead);
4679 ok(!input_info.cbAlignment, "Unexpected alignment %u.\n", input_info.cbAlignment);
4681 hr = IMFTransform_SetOutputType(copier, 0, mediatype, 0);
4682 ok(hr == S_OK, "Failed to set input type, hr %#x.\n", hr);
4684 hr = IMFTransform_GetOutputStreamInfo(copier, 0, &output_info);
4685 ok(hr == S_OK, "Failed to get stream info, hr %#x.\n", hr);
4686 ok(!output_info.dwFlags, "Unexpected flags %#x.\n", output_info.dwFlags);
4687 ok(output_info.cbSize == 16 * 16, "Unexpected size %u.\n", output_info.cbSize);
4688 ok(!output_info.cbAlignment, "Unexpected alignment %u.\n", output_info.cbAlignment);
4690 hr = IMFTransform_GetOutputCurrentType(copier, 0, &mediatype2);
4691 ok(hr == S_OK, "Failed to get current type, hr %#x.\n", hr);
4692 IMFMediaType_Release(mediatype2);
4694 hr = IMFTransform_GetInputCurrentType(copier, 0, &mediatype2);
4695 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#x.\n", hr);
4697 hr = IMFTransform_GetInputStatus(copier, 0, &flags);
4698 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#x.\n", hr);
4700 /* Setting input type resets output type. */
4701 hr = IMFTransform_GetOutputCurrentType(copier, 0, &mediatype2);
4702 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4703 IMFMediaType_Release(mediatype2);
4705 hr = IMFTransform_SetInputType(copier, 0, mediatype, 0);
4706 ok(hr == S_OK, "Failed to set input type, hr %#x.\n", hr);
4708 hr = IMFTransform_GetOutputCurrentType(copier, 0, &mediatype2);
4709 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#x.\n", hr);
4711 hr = IMFTransform_GetInputAvailableType(copier, 0, 1, &mediatype2);
4712 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4713 ok(is_sample_copier_available_type(mediatype2), "Unexpected type.\n");
4714 IMFMediaType_Release(mediatype2);
4716 hr = IMFTransform_GetInputStreamInfo(copier, 0, &input_info);
4717 ok(hr == S_OK, "Failed to get stream info, hr %#x.\n", hr);
4718 ok(!input_info.hnsMaxLatency, "Unexpected latency %s.\n", wine_dbgstr_longlong(input_info.hnsMaxLatency));
4719 ok(!input_info.dwFlags, "Unexpected flags %#x.\n", input_info.dwFlags);
4720 ok(input_info.cbSize == 16 * 16, "Unexpected size %u.\n", input_info.cbSize);
4721 ok(!input_info.cbMaxLookahead, "Unexpected lookahead size %u.\n", input_info.cbMaxLookahead);
4722 ok(!input_info.cbAlignment, "Unexpected alignment %u.\n", input_info.cbAlignment);
4724 hr = IMFTransform_GetOutputAvailableType(copier, 0, 0, &mediatype2);
4725 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4726 hr = IMFMediaType_IsEqual(mediatype2, mediatype, &flags);
4727 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4728 IMFMediaType_Release(mediatype2);
4730 hr = IMFTransform_GetInputStatus(copier, 0, &flags);
4731 ok(hr == S_OK, "Failed to get input status, hr %#x.\n", hr);
4732 ok(flags == MFT_INPUT_STATUS_ACCEPT_DATA, "Unexpected flags %#x.\n", flags);
4734 hr = IMFTransform_GetInputCurrentType(copier, 0, &mediatype2);
4735 ok(hr == S_OK, "Failed to get current type, hr %#x.\n", hr);
4736 IMFMediaType_Release(mediatype2);
4738 hr = IMFTransform_GetOutputStatus(copier, &flags);
4739 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#x.\n", hr);
4741 hr = IMFTransform_SetOutputType(copier, 0, mediatype, 0);
4742 ok(hr == S_OK, "Failed to set output type, hr %#x.\n", hr);
4744 hr = IMFTransform_GetOutputStatus(copier, &flags);
4745 ok(hr == S_OK, "Failed to get output status, hr %#x.\n", hr);
4746 ok(!flags, "Unexpected flags %#x.\n", flags);
4748 /* Pushing samples. */
4749 hr = MFCreateAlignedMemoryBuffer(output_info.cbSize, output_info.cbAlignment, &media_buffer);
4750 ok(hr == S_OK, "Failed to create media buffer, hr %#x.\n", hr);
4752 hr = IMFSample_AddBuffer(sample, media_buffer);
4753 ok(hr == S_OK, "Failed to add a buffer, hr %#x.\n", hr);
4754 IMFMediaBuffer_Release(media_buffer);
4756 EXPECT_REF(sample, 1);
4757 hr = IMFTransform_ProcessInput(copier, 0, sample, 0);
4758 ok(hr == S_OK, "Failed to process input, hr %#x.\n", hr);
4759 EXPECT_REF(sample, 2);
4761 hr = IMFTransform_GetInputStatus(copier, 0, &flags);
4762 ok(hr == S_OK, "Failed to get input status, hr %#x.\n", hr);
4763 ok(!flags, "Unexpected flags %#x.\n", flags);
4765 hr = IMFTransform_GetOutputStatus(copier, &flags);
4766 ok(hr == S_OK, "Failed to get output status, hr %#x.\n", hr);
4767 ok(flags == MFT_OUTPUT_STATUS_SAMPLE_READY, "Unexpected flags %#x.\n", flags);
4769 hr = IMFTransform_ProcessInput(copier, 0, sample, 0);
4770 ok(hr == MF_E_NOTACCEPTING, "Unexpected hr %#x.\n", hr);
4772 hr = IMFTransform_GetOutputStreamInfo(copier, 0, &output_info);
4773 ok(hr == S_OK, "Failed to get output info, hr %#x.\n", hr);
4775 hr = MFCreateAlignedMemoryBuffer(output_info.cbSize, output_info.cbAlignment, &media_buffer);
4776 ok(hr == S_OK, "Failed to create media buffer, hr %#x.\n", hr);
4778 hr = MFCreateSample(&client_sample);
4779 ok(hr == S_OK, "Failed to create a sample, hr %#x.\n", hr);
4781 hr = IMFSample_AddBuffer(client_sample, media_buffer);
4782 ok(hr == S_OK, "Failed to add a buffer, hr %#x.\n", hr);
4783 IMFMediaBuffer_Release(media_buffer);
4785 status = 0;
4786 memset(&buffer, 0, sizeof(buffer));
4787 buffer.pSample = client_sample;
4788 hr = IMFTransform_ProcessOutput(copier, 0, 1, &buffer, &status);
4789 ok(hr == S_OK, "Failed to get output, hr %#x.\n", hr);
4790 EXPECT_REF(sample, 1);
4792 hr = IMFTransform_ProcessOutput(copier, 0, 1, &buffer, &status);
4793 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "Failed to get output, hr %#x.\n", hr);
4795 /* Flushing. */
4796 hr = IMFTransform_ProcessInput(copier, 0, sample, 0);
4797 ok(hr == S_OK, "Failed to process input, hr %#x.\n", hr);
4798 EXPECT_REF(sample, 2);
4800 hr = IMFTransform_ProcessMessage(copier, MFT_MESSAGE_COMMAND_FLUSH, 0);
4801 ok(hr == S_OK, "Failed to flush, hr %#x.\n", hr);
4802 EXPECT_REF(sample, 1);
4804 IMFSample_Release(sample);
4805 IMFSample_Release(client_sample);
4807 IMFMediaType_Release(mediatype);
4808 IMFTransform_Release(copier);
4811 static void sample_copier_process(IMFTransform *copier, IMFMediaBuffer *input_buffer,
4812 IMFMediaBuffer *output_buffer)
4814 IMFSample *input_sample, *output_sample;
4815 MFT_OUTPUT_DATA_BUFFER buffer;
4816 DWORD status;
4817 HRESULT hr;
4819 hr = MFCreateSample(&input_sample);
4820 ok(hr == S_OK, "Failed to create a sample, hr %#x.\n", hr);
4822 hr = MFCreateSample(&output_sample);
4823 ok(hr == S_OK, "Failed to create a sample, hr %#x.\n", hr);
4825 hr = IMFSample_AddBuffer(input_sample, input_buffer);
4826 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4828 hr = IMFSample_AddBuffer(output_sample, output_buffer);
4829 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4831 hr = IMFTransform_ProcessInput(copier, 0, input_sample, 0);
4832 ok(hr == S_OK, "Failed to process input, hr %#x.\n", hr);
4834 status = 0;
4835 memset(&buffer, 0, sizeof(buffer));
4836 buffer.pSample = output_sample;
4837 hr = IMFTransform_ProcessOutput(copier, 0, 1, &buffer, &status);
4838 ok(hr == S_OK, "Failed to get output, hr %#x.\n", hr);
4840 IMFSample_Release(input_sample);
4841 IMFSample_Release(output_sample);
4844 static void test_sample_copier_output_processing(void)
4846 IMFMediaBuffer *input_buffer, *output_buffer;
4847 MFT_OUTPUT_STREAM_INFO output_info;
4848 IMFMediaType *mediatype;
4849 IMFTransform *copier;
4850 DWORD max_length;
4851 HRESULT hr;
4852 BYTE *ptr;
4854 hr = MFCreateSampleCopierMFT(&copier);
4855 ok(hr == S_OK, "Failed to create sample copier, hr %#x.\n", hr);
4857 /* Configure for 16 x 16 of D3DFMT_X8R8G8B8. */
4858 hr = MFCreateMediaType(&mediatype);
4859 ok(hr == S_OK, "Failed to create media type, hr %#x.\n", hr);
4861 hr = IMFMediaType_SetGUID(mediatype, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
4862 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
4864 hr = IMFMediaType_SetGUID(mediatype, &MF_MT_SUBTYPE, &MFVideoFormat_RGB32);
4865 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
4867 hr = IMFMediaType_SetUINT64(mediatype, &MF_MT_FRAME_SIZE, ((UINT64)16) << 32 | 16);
4868 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
4870 hr = IMFTransform_SetInputType(copier, 0, mediatype, 0);
4871 ok(hr == S_OK, "Failed to set input type, hr %#x.\n", hr);
4873 hr = IMFTransform_SetOutputType(copier, 0, mediatype, 0);
4874 ok(hr == S_OK, "Failed to set input type, hr %#x.\n", hr);
4876 /* Source and destination are linear buffers, destination is twice as large. */
4877 hr = IMFTransform_GetOutputStreamInfo(copier, 0, &output_info);
4878 ok(hr == S_OK, "Failed to get output info, hr %#x.\n", hr);
4880 hr = MFCreateAlignedMemoryBuffer(output_info.cbSize, output_info.cbAlignment, &output_buffer);
4881 ok(hr == S_OK, "Failed to create media buffer, hr %#x.\n", hr);
4883 hr = IMFMediaBuffer_Lock(output_buffer, &ptr, &max_length, NULL);
4884 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4885 memset(ptr, 0xcc, max_length);
4886 hr = IMFMediaBuffer_Unlock(output_buffer);
4887 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4889 hr = MFCreateAlignedMemoryBuffer(output_info.cbSize, output_info.cbAlignment, &input_buffer);
4890 ok(hr == S_OK, "Failed to create media buffer, hr %#x.\n", hr);
4892 hr = IMFMediaBuffer_Lock(input_buffer, &ptr, &max_length, NULL);
4893 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4894 memset(ptr, 0xaa, max_length);
4895 hr = IMFMediaBuffer_Unlock(input_buffer);
4896 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4897 hr = IMFMediaBuffer_SetCurrentLength(input_buffer, 4);
4898 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4900 sample_copier_process(copier, input_buffer, output_buffer);
4902 hr = IMFMediaBuffer_Lock(output_buffer, &ptr, &max_length, NULL);
4903 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4904 ok(ptr[0] == 0xaa && ptr[4] == 0xcc, "Unexpected buffer contents.\n");
4906 hr = IMFMediaBuffer_Unlock(output_buffer);
4907 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4909 IMFMediaType_Release(mediatype);
4910 IMFTransform_Release(copier);
4913 static void test_MFGetTopoNodeCurrentType(void)
4915 IMFMediaType *media_type, *media_type2;
4916 IMFTopologyNode *node;
4917 HRESULT hr;
4919 /* Tee node. */
4920 hr = MFCreateTopologyNode(MF_TOPOLOGY_TEE_NODE, &node);
4921 ok(hr == S_OK, "Failed to create a node, hr %#x.\n", hr);
4923 hr = MFGetTopoNodeCurrentType(node, 0, TRUE, &media_type);
4924 ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
4926 hr = MFGetTopoNodeCurrentType(node, 0, FALSE, &media_type);
4927 ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
4929 hr = MFCreateMediaType(&media_type2);
4930 ok(hr == S_OK, "Failed to create media type, hr %#x.\n", hr);
4932 hr = IMFMediaType_SetGUID(media_type2, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
4933 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
4935 /* Input type returned, if set. */
4936 hr = IMFTopologyNode_SetInputPrefType(node, 0, media_type2);
4937 ok(hr == S_OK, "Failed to set media type, hr %#x.\n", hr);
4939 hr = MFGetTopoNodeCurrentType(node, 0, FALSE, &media_type);
4940 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4941 ok(media_type == media_type2, "Unexpected pointer.\n");
4942 IMFMediaType_Release(media_type);
4944 hr = IMFTopologyNode_SetInputPrefType(node, 0, NULL);
4945 ok(hr == S_OK, "Failed to set media type, hr %#x.\n", hr);
4947 hr = MFGetTopoNodeCurrentType(node, 0, FALSE, &media_type);
4948 ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
4950 /* Set second output. */
4951 hr = IMFTopologyNode_SetOutputPrefType(node, 1, media_type2);
4952 ok(hr == S_OK, "Failed to set media type, hr %#x.\n", hr);
4954 hr = MFGetTopoNodeCurrentType(node, 0, FALSE, &media_type);
4955 ok(hr == E_FAIL, "Unexpected hr %#x.\n", hr);
4957 hr = IMFTopologyNode_SetOutputPrefType(node, 1, NULL);
4958 ok(hr == S_OK, "Failed to set media type, hr %#x.\n", hr);
4960 /* Set first output. */
4961 hr = IMFTopologyNode_SetOutputPrefType(node, 0, media_type2);
4962 ok(hr == S_OK, "Failed to set media type, hr %#x.\n", hr);
4964 hr = MFGetTopoNodeCurrentType(node, 0, FALSE, &media_type);
4965 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4966 ok(media_type == media_type2, "Unexpected pointer.\n");
4967 IMFMediaType_Release(media_type);
4969 hr = IMFTopologyNode_SetOutputPrefType(node, 0, NULL);
4970 ok(hr == S_OK, "Failed to set media type, hr %#x.\n", hr);
4972 /* Set primary output. */
4973 hr = IMFTopologyNode_SetOutputPrefType(node, 1, media_type2);
4974 ok(hr == S_OK, "Failed to set media type, hr %#x.\n", hr);
4976 hr = IMFTopologyNode_SetUINT32(node, &MF_TOPONODE_PRIMARYOUTPUT, 1);
4977 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
4979 hr = MFGetTopoNodeCurrentType(node, 0, FALSE, &media_type);
4980 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4981 ok(media_type == media_type2, "Unexpected pointer.\n");
4982 IMFMediaType_Release(media_type);
4984 hr = MFGetTopoNodeCurrentType(node, 0, TRUE, &media_type);
4985 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4986 ok(media_type == media_type2, "Unexpected pointer.\n");
4987 IMFMediaType_Release(media_type);
4989 IMFTopologyNode_Release(node);
4990 IMFMediaType_Release(media_type2);
4993 START_TEST(mf)
4995 test_topology();
4996 test_topology_tee_node();
4997 test_topology_loader();
4998 test_topology_loader_evr();
4999 test_MFGetService();
5000 test_sequencer_source();
5001 test_media_session();
5002 test_MFShutdownObject();
5003 test_presentation_clock();
5004 test_sample_grabber();
5005 test_sample_grabber_is_mediatype_supported();
5006 test_video_processor();
5007 test_quality_manager();
5008 test_sar();
5009 test_evr();
5010 test_MFCreateSimpleTypeHandler();
5011 test_MFGetSupportedMimeTypes();
5012 test_MFGetSupportedSchemes();
5013 test_sample_copier();
5014 test_sample_copier_output_processing();
5015 test_MFGetTopoNodeCurrentType();