mf/tests: Add some SAR supported interfaces checks.
[wine/zf.git] / dlls / mf / tests / mf.c
blob20440499227356b5101012d77ee3548751acad49
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 static HRESULT (WINAPI *pMFCreateSampleCopierMFT)(IMFTransform **copier);
51 static HRESULT (WINAPI *pMFGetTopoNodeCurrentType)(IMFTopologyNode *node, DWORD stream, BOOL output, IMFMediaType **type);
53 static BOOL is_vista(void)
55 return !pMFGetTopoNodeCurrentType;
58 #define EXPECT_REF(obj,ref) _expect_ref((IUnknown*)obj, ref, __LINE__)
59 static void _expect_ref(IUnknown* obj, ULONG expected_refcount, int line)
61 ULONG refcount;
62 IUnknown_AddRef(obj);
63 refcount = IUnknown_Release(obj);
64 ok_(__FILE__, line)(refcount == expected_refcount, "Unexpected refcount %d, expected %d.\n", refcount,
65 expected_refcount);
68 #define check_interface(a, b, c) check_interface_(__LINE__, a, b, c)
69 static void check_interface_(unsigned int line, void *iface_ptr, REFIID iid, BOOL supported)
71 IUnknown *iface = iface_ptr;
72 HRESULT hr, expected_hr;
73 IUnknown *unk;
75 expected_hr = supported ? S_OK : E_NOINTERFACE;
77 hr = IUnknown_QueryInterface(iface, iid, (void **)&unk);
78 ok_(__FILE__, line)(hr == expected_hr, "Got hr %#x, expected %#x.\n", hr, expected_hr);
79 if (SUCCEEDED(hr))
80 IUnknown_Release(unk);
83 #define check_service_interface(a, b, c, d) check_service_interface_(__LINE__, a, b, c, d)
84 static void check_service_interface_(unsigned int line, void *iface_ptr, REFGUID service, REFIID iid, BOOL supported)
86 IUnknown *iface = iface_ptr;
87 HRESULT hr, expected_hr;
88 IUnknown *unk;
90 expected_hr = supported ? S_OK : E_NOINTERFACE;
92 hr = MFGetService(iface, service, iid, (void **)&unk);
93 ok_(__FILE__, line)(hr == expected_hr, "Got hr %#x, expected %#x.\n", hr, expected_hr);
94 if (SUCCEEDED(hr))
95 IUnknown_Release(unk);
98 static HWND create_window(void)
100 RECT r = {0, 0, 640, 480};
102 AdjustWindowRect(&r, WS_OVERLAPPEDWINDOW | WS_VISIBLE, FALSE);
104 return CreateWindowA("static", "mf_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
105 0, 0, r.right - r.left, r.bottom - r.top, NULL, NULL, NULL, NULL);
108 static HRESULT WINAPI test_unk_QueryInterface(IUnknown *iface, REFIID riid, void **obj)
110 if (IsEqualIID(riid, &IID_IUnknown))
112 *obj = iface;
113 IUnknown_AddRef(iface);
114 return S_OK;
117 *obj = NULL;
118 return E_NOINTERFACE;
121 static ULONG WINAPI test_unk_AddRef(IUnknown *iface)
123 return 2;
126 static ULONG WINAPI test_unk_Release(IUnknown *iface)
128 return 1;
131 static const IUnknownVtbl test_unk_vtbl =
133 test_unk_QueryInterface,
134 test_unk_AddRef,
135 test_unk_Release,
138 static void test_topology(void)
140 IMFMediaType *mediatype, *mediatype2, *mediatype3;
141 IMFCollection *collection, *collection2;
142 IUnknown test_unk2 = { &test_unk_vtbl };
143 IUnknown test_unk = { &test_unk_vtbl };
144 IMFTopologyNode *node, *node2, *node3;
145 IMFTopology *topology, *topology2;
146 MF_TOPOLOGY_TYPE node_type;
147 UINT32 count, index;
148 IUnknown *object;
149 WORD node_count;
150 DWORD size;
151 HRESULT hr;
152 TOPOID id;
154 hr = MFCreateTopology(NULL);
155 ok(hr == E_POINTER, "got %#x\n", hr);
157 hr = MFCreateTopology(&topology);
158 ok(hr == S_OK, "Failed to create topology, hr %#x.\n", hr);
159 hr = IMFTopology_GetTopologyID(topology, &id);
160 ok(hr == S_OK, "Failed to get id, hr %#x.\n", hr);
161 ok(id == 1, "Unexpected id.\n");
163 hr = MFCreateTopology(&topology2);
164 ok(hr == S_OK, "Failed to create topology, hr %#x.\n", hr);
165 hr = IMFTopology_GetTopologyID(topology2, &id);
166 ok(hr == S_OK, "Failed to get id, hr %#x.\n", hr);
167 ok(id == 2, "Unexpected id.\n");
169 IMFTopology_Release(topology);
171 hr = MFCreateTopology(&topology);
172 ok(hr == S_OK, "Failed to create topology, hr %#x.\n", hr);
173 hr = IMFTopology_GetTopologyID(topology, &id);
174 ok(hr == S_OK, "Failed to get id, hr %#x.\n", hr);
175 ok(id == 3, "Unexpected id.\n");
177 IMFTopology_Release(topology2);
179 /* No attributes by default. */
180 for (node_type = MF_TOPOLOGY_OUTPUT_NODE; node_type < MF_TOPOLOGY_TEE_NODE; ++node_type)
182 hr = MFCreateTopologyNode(node_type, &node);
183 ok(hr == S_OK, "Failed to create a node for type %d, hr %#x.\n", node_type, hr);
184 hr = IMFTopologyNode_GetCount(node, &count);
185 ok(hr == S_OK, "Failed to get attribute count, hr %#x.\n", hr);
186 ok(!count, "Unexpected attribute count %u.\n", count);
187 IMFTopologyNode_Release(node);
190 hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, NULL);
191 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
193 hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, &node);
194 ok(hr == S_OK, "Failed to create topology node, hr %#x.\n", hr);
196 hr = MFCreateTopologyNode(MF_TOPOLOGY_TEE_NODE, &node2);
197 ok(hr == S_OK, "Failed to create topology node, hr %#x.\n", hr);
199 hr = IMFTopologyNode_GetTopoNodeID(node, &id);
200 ok(hr == S_OK, "Failed to get node id, hr %#x.\n", hr);
201 ok(((id >> 32) == GetCurrentProcessId()) && !!(id & 0xffff), "Unexpected node id %s.\n", wine_dbgstr_longlong(id));
203 hr = IMFTopologyNode_SetTopoNodeID(node2, id);
204 ok(hr == S_OK, "Failed to set node id, hr %#x.\n", hr);
206 hr = IMFTopology_GetNodeCount(topology, NULL);
207 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
209 hr = IMFTopology_AddNode(topology, NULL);
210 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
212 node_count = 1;
213 hr = IMFTopology_GetNodeCount(topology, &node_count);
214 ok(hr == S_OK, "Failed to get node count, hr %#x.\n", hr);
215 ok(node_count == 0, "Unexpected node count %u.\n", node_count);
217 /* Same id, different nodes. */
218 hr = IMFTopology_AddNode(topology, node);
219 ok(hr == S_OK, "Failed to add a node, hr %#x.\n", hr);
221 node_count = 0;
222 hr = IMFTopology_GetNodeCount(topology, &node_count);
223 ok(hr == S_OK, "Failed to get node count, hr %#x.\n", hr);
224 ok(node_count == 1, "Unexpected node count %u.\n", node_count);
226 hr = IMFTopology_AddNode(topology, node2);
227 ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
228 IMFTopologyNode_Release(node2);
230 hr = IMFTopology_GetNodeByID(topology, id, &node2);
231 ok(hr == S_OK, "Failed to get a node, hr %#x.\n", hr);
232 ok(node2 == node, "Unexpected node.\n");
233 IMFTopologyNode_Release(node2);
235 /* Change node id, add it again. */
236 hr = IMFTopologyNode_SetTopoNodeID(node, ++id);
237 ok(hr == S_OK, "Failed to set node id, hr %#x.\n", hr);
239 hr = IMFTopology_GetNodeByID(topology, id, &node2);
240 ok(hr == S_OK, "Failed to get a node, hr %#x.\n", hr);
241 ok(node2 == node, "Unexpected node.\n");
242 IMFTopologyNode_Release(node2);
244 hr = IMFTopology_GetNodeByID(topology, id + 1, &node2);
245 ok(hr == MF_E_NOT_FOUND, "Unexpected hr %#x.\n", hr);
247 hr = IMFTopology_AddNode(topology, node);
248 ok(hr == E_INVALIDARG, "Failed to add a node, hr %#x.\n", hr);
250 hr = IMFTopology_GetNode(topology, 0, &node2);
251 ok(hr == S_OK, "Failed to get a node, hr %#x.\n", hr);
252 ok(node2 == node, "Unexpected node.\n");
253 IMFTopologyNode_Release(node2);
255 hr = IMFTopology_GetNode(topology, 1, NULL);
256 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
258 hr = IMFTopology_GetNode(topology, 1, &node2);
259 ok(hr == MF_E_INVALIDINDEX, "Failed to get a node, hr %#x.\n", hr);
261 hr = IMFTopology_GetNode(topology, -2, &node2);
262 ok(hr == MF_E_INVALIDINDEX, "Failed to get a node, hr %#x.\n", hr);
264 hr = MFCreateTopologyNode(MF_TOPOLOGY_TEE_NODE, &node2);
265 ok(hr == S_OK, "Failed to create topology node, hr %#x.\n", hr);
266 hr = IMFTopology_AddNode(topology, node2);
267 ok(hr == S_OK, "Failed to add a node, hr %#x.\n", hr);
268 IMFTopologyNode_Release(node2);
270 node_count = 0;
271 hr = IMFTopology_GetNodeCount(topology, &node_count);
272 ok(hr == S_OK, "Failed to get node count, hr %#x.\n", hr);
273 ok(node_count == 2, "Unexpected node count %u.\n", node_count);
275 /* Remove with detached node, existing id. */
276 hr = MFCreateTopologyNode(MF_TOPOLOGY_TEE_NODE, &node2);
277 ok(hr == S_OK, "Failed to create topology node, hr %#x.\n", hr);
278 hr = IMFTopologyNode_SetTopoNodeID(node2, id);
279 ok(hr == S_OK, "Failed to set node id, hr %#x.\n", hr);
280 hr = IMFTopology_RemoveNode(topology, node2);
281 ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
282 IMFTopologyNode_Release(node2);
284 hr = IMFTopology_RemoveNode(topology, node);
285 ok(hr == S_OK, "Failed to remove a node, hr %#x.\n", hr);
287 node_count = 0;
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 == 1, "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 node_count = 1;
296 hr = IMFTopology_GetNodeCount(topology, &node_count);
297 ok(hr == S_OK, "Failed to get node count, hr %#x.\n", hr);
298 ok(node_count == 0, "Unexpected node count %u.\n", node_count);
300 hr = IMFTopology_Clear(topology);
301 ok(hr == S_OK, "Failed to clear topology, hr %#x.\n", hr);
303 hr = IMFTopologyNode_SetTopoNodeID(node, 123);
304 ok(hr == S_OK, "Failed to set node id, hr %#x.\n", hr);
306 IMFTopologyNode_Release(node);
308 /* Change id for attached node. */
309 hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, &node);
310 ok(hr == S_OK, "Failed to create topology node, hr %#x.\n", hr);
312 hr = MFCreateTopologyNode(MF_TOPOLOGY_TEE_NODE, &node2);
313 ok(hr == S_OK, "Failed to create topology node, hr %#x.\n", hr);
315 hr = IMFTopology_AddNode(topology, node);
316 ok(hr == S_OK, "Failed to add a node, hr %#x.\n", hr);
318 hr = IMFTopology_AddNode(topology, node2);
319 ok(hr == S_OK, "Failed to add a node, hr %#x.\n", hr);
321 hr = IMFTopologyNode_GetTopoNodeID(node, &id);
322 ok(hr == S_OK, "Failed to get node id, hr %#x.\n", hr);
324 hr = IMFTopologyNode_SetTopoNodeID(node2, id);
325 ok(hr == S_OK, "Failed to get node id, hr %#x.\n", hr);
327 hr = IMFTopology_GetNodeByID(topology, id, &node3);
328 ok(hr == S_OK, "Failed to get a node, hr %#x.\n", hr);
329 ok(node3 == node, "Unexpected node.\n");
330 IMFTopologyNode_Release(node3);
332 IMFTopologyNode_Release(node);
333 IMFTopologyNode_Release(node2);
335 /* Source/output collections. */
336 hr = IMFTopology_Clear(topology);
337 ok(hr == S_OK, "Failed to clear topology, hr %#x.\n", hr);
339 hr = IMFTopology_GetSourceNodeCollection(topology, NULL);
340 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
342 hr = IMFTopology_GetSourceNodeCollection(topology, &collection);
343 ok(hr == S_OK, "Failed to get source node collection, hr %#x.\n", hr);
344 ok(!!collection, "Unexpected object pointer.\n");
346 hr = IMFTopology_GetSourceNodeCollection(topology, &collection2);
347 ok(hr == S_OK, "Failed to get source node collection, hr %#x.\n", hr);
348 ok(!!collection2, "Unexpected object pointer.\n");
349 ok(collection2 != collection, "Expected cloned collection.\n");
351 hr = IMFCollection_GetElementCount(collection, &size);
352 ok(hr == S_OK, "Failed to get item count, hr %#x.\n", hr);
353 ok(!size, "Unexpected item count.\n");
355 hr = IMFCollection_AddElement(collection, (IUnknown *)collection);
356 ok(hr == S_OK, "Failed to add element, hr %#x.\n", hr);
358 hr = IMFCollection_GetElementCount(collection, &size);
359 ok(hr == S_OK, "Failed to get item count, hr %#x.\n", hr);
360 ok(size == 1, "Unexpected item count.\n");
362 hr = IMFCollection_GetElementCount(collection2, &size);
363 ok(hr == S_OK, "Failed to get item count, hr %#x.\n", hr);
364 ok(!size, "Unexpected item count.\n");
366 IMFCollection_Release(collection2);
367 IMFCollection_Release(collection);
369 /* Add some nodes. */
370 hr = IMFTopology_GetSourceNodeCollection(topology, NULL);
371 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
373 hr = IMFTopology_GetOutputNodeCollection(topology, NULL);
374 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
376 hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &node);
377 ok(hr == S_OK, "Failed to create a node, hr %#x.\n", hr);
378 hr = IMFTopology_AddNode(topology, node);
379 ok(hr == S_OK, "Failed to add a node, hr %#x.\n", hr);
380 IMFTopologyNode_Release(node);
382 hr = IMFTopology_GetSourceNodeCollection(topology, &collection);
383 ok(hr == S_OK, "Failed to get source node collection, hr %#x.\n", hr);
384 ok(!!collection, "Unexpected object pointer.\n");
385 hr = IMFCollection_GetElementCount(collection, &size);
386 ok(hr == S_OK, "Failed to get item count, hr %#x.\n", hr);
387 ok(size == 1, "Unexpected item count.\n");
388 IMFCollection_Release(collection);
390 hr = MFCreateTopologyNode(MF_TOPOLOGY_TEE_NODE, &node);
391 ok(hr == S_OK, "Failed to create a node, hr %#x.\n", hr);
392 hr = IMFTopology_AddNode(topology, node);
393 ok(hr == S_OK, "Failed to add a node, hr %#x.\n", hr);
394 IMFTopologyNode_Release(node);
396 hr = IMFTopology_GetSourceNodeCollection(topology, &collection);
397 ok(hr == S_OK, "Failed to get source node collection, hr %#x.\n", hr);
398 ok(!!collection, "Unexpected object pointer.\n");
399 hr = IMFCollection_GetElementCount(collection, &size);
400 ok(hr == S_OK, "Failed to get item count, hr %#x.\n", hr);
401 ok(size == 1, "Unexpected item count.\n");
402 IMFCollection_Release(collection);
404 hr = MFCreateTopologyNode(MF_TOPOLOGY_TRANSFORM_NODE, &node);
405 ok(hr == S_OK, "Failed to create a node, hr %#x.\n", hr);
406 hr = IMFTopology_AddNode(topology, node);
407 ok(hr == S_OK, "Failed to add a node, hr %#x.\n", hr);
408 IMFTopologyNode_Release(node);
410 hr = IMFTopology_GetSourceNodeCollection(topology, &collection);
411 ok(hr == S_OK, "Failed to get source node collection, hr %#x.\n", hr);
412 ok(!!collection, "Unexpected object pointer.\n");
413 hr = IMFCollection_GetElementCount(collection, &size);
414 ok(hr == S_OK, "Failed to get item count, hr %#x.\n", hr);
415 ok(size == 1, "Unexpected item count.\n");
416 IMFCollection_Release(collection);
418 hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, &node);
419 ok(hr == S_OK, "Failed to create a node, hr %#x.\n", hr);
420 hr = IMFTopology_AddNode(topology, node);
421 ok(hr == S_OK, "Failed to add a node, hr %#x.\n", hr);
423 /* Associated object. */
424 hr = IMFTopologyNode_SetObject(node, NULL);
425 ok(hr == S_OK, "Failed to set object, hr %#x.\n", hr);
427 hr = IMFTopologyNode_GetObject(node, NULL);
428 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
430 object = (void *)0xdeadbeef;
431 hr = IMFTopologyNode_GetObject(node, &object);
432 ok(hr == E_FAIL, "Unexpected hr %#x.\n", hr);
433 ok(!object, "Unexpected object %p.\n", object);
435 hr = IMFTopologyNode_SetObject(node, &test_unk);
436 ok(hr == S_OK, "Failed to set object, hr %#x.\n", hr);
438 hr = IMFTopologyNode_GetObject(node, &object);
439 ok(hr == S_OK, "Failed to get object, hr %#x.\n", hr);
440 ok(object == &test_unk, "Unexpected object %p.\n", object);
441 IUnknown_Release(object);
443 hr = IMFTopologyNode_SetObject(node, &test_unk2);
444 ok(hr == S_OK, "Failed to set object, hr %#x.\n", hr);
446 hr = IMFTopologyNode_GetCount(node, &count);
447 ok(hr == S_OK, "Failed to get attribute count, hr %#x.\n", hr);
448 ok(count == 0, "Unexpected attribute count %u.\n", count);
450 hr = IMFTopologyNode_SetGUID(node, &MF_TOPONODE_TRANSFORM_OBJECTID, &MF_TOPONODE_TRANSFORM_OBJECTID);
451 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
453 hr = IMFTopologyNode_SetObject(node, NULL);
454 ok(hr == S_OK, "Failed to set object, hr %#x.\n", hr);
456 object = (void *)0xdeadbeef;
457 hr = IMFTopologyNode_GetObject(node, &object);
458 ok(hr == E_FAIL, "Unexpected hr %#x.\n", hr);
459 ok(!object, "Unexpected object %p.\n", object);
461 hr = IMFTopologyNode_GetCount(node, &count);
462 ok(hr == S_OK, "Failed to get attribute count, hr %#x.\n", hr);
463 ok(count == 1, "Unexpected attribute count %u.\n", count);
465 /* Preferred stream types. */
466 hr = IMFTopologyNode_GetInputCount(node, &count);
467 ok(hr == S_OK, "Failed to get input count, hr %#x.\n", hr);
468 ok(count == 0, "Unexpected count %u.\n", count);
470 hr = IMFTopologyNode_GetInputPrefType(node, 0, &mediatype);
471 ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
473 hr = MFCreateMediaType(&mediatype);
474 ok(hr == S_OK, "Failed to create media type, hr %#x.\n", hr);
476 hr = IMFTopologyNode_SetInputPrefType(node, 0, mediatype);
477 ok(hr == S_OK, "Failed to set preferred type, hr %#x.\n", hr);
479 hr = IMFTopologyNode_GetInputPrefType(node, 0, &mediatype2);
480 ok(hr == S_OK, "Failed to get preferred type, hr %#x.\n", hr);
481 ok(mediatype2 == mediatype, "Unexpected mediatype instance.\n");
482 IMFMediaType_Release(mediatype2);
484 hr = IMFTopologyNode_SetInputPrefType(node, 0, NULL);
485 ok(hr == S_OK, "Failed to set preferred type, hr %#x.\n", hr);
487 hr = IMFTopologyNode_GetInputPrefType(node, 0, &mediatype2);
488 ok(hr == E_FAIL, "Unexpected hr %#x.\n", hr);
489 ok(!mediatype2, "Unexpected mediatype instance.\n");
491 hr = IMFTopologyNode_SetInputPrefType(node, 1, mediatype);
492 ok(hr == S_OK, "Failed to set preferred type, hr %#x.\n", hr);
494 hr = IMFTopologyNode_SetInputPrefType(node, 1, mediatype);
495 ok(hr == S_OK, "Failed to set preferred type, hr %#x.\n", hr);
497 hr = IMFTopologyNode_GetInputCount(node, &count);
498 ok(hr == S_OK, "Failed to get input count, hr %#x.\n", hr);
499 ok(count == 2, "Unexpected count %u.\n", count);
501 hr = IMFTopologyNode_GetOutputCount(node, &count);
502 ok(hr == S_OK, "Failed to get input count, hr %#x.\n", hr);
503 ok(count == 0, "Unexpected count %u.\n", count);
505 hr = IMFTopologyNode_SetOutputPrefType(node, 0, mediatype);
506 ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
508 IMFTopologyNode_Release(node);
510 /* Source node. */
511 hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &node);
512 ok(hr == S_OK, "Failed to create a node, hr %#x.\n", hr);
514 hr = IMFTopologyNode_SetInputPrefType(node, 0, mediatype);
515 ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
517 hr = IMFTopologyNode_SetOutputPrefType(node, 2, mediatype);
518 ok(hr == S_OK, "Failed to set preferred type, hr %#x.\n", hr);
520 hr = IMFTopologyNode_GetOutputPrefType(node, 0, &mediatype2);
521 ok(hr == E_FAIL, "Failed to get preferred type, hr %#x.\n", hr);
522 ok(!mediatype2, "Unexpected mediatype instance.\n");
524 hr = IMFTopologyNode_GetOutputCount(node, &count);
525 ok(hr == S_OK, "Failed to get output count, hr %#x.\n", hr);
526 ok(count == 3, "Unexpected count %u.\n", count);
528 IMFTopologyNode_Release(node);
530 /* Tee node. */
531 hr = MFCreateTopologyNode(MF_TOPOLOGY_TEE_NODE, &node);
532 ok(hr == S_OK, "Failed to create a node, hr %#x.\n", hr);
534 hr = IMFTopologyNode_SetInputPrefType(node, 0, mediatype);
535 ok(hr == S_OK, "Failed to set preferred type, hr %#x.\n", hr);
537 hr = IMFTopologyNode_GetInputPrefType(node, 0, &mediatype2);
538 ok(hr == S_OK, "Failed to get preferred type, hr %#x.\n", hr);
539 ok(mediatype2 == mediatype, "Unexpected mediatype instance.\n");
540 IMFMediaType_Release(mediatype2);
542 hr = IMFTopologyNode_GetOutputPrefType(node, 0, &mediatype2);
543 ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
545 hr = IMFTopologyNode_GetInputCount(node, &count);
546 ok(hr == S_OK, "Failed to get output count, hr %#x.\n", hr);
547 ok(count == 0, "Unexpected count %u.\n", count);
549 hr = IMFTopologyNode_SetInputPrefType(node, 1, mediatype);
550 ok(hr == MF_E_INVALIDTYPE, "Unexpected hr %#x.\n", hr);
552 hr = IMFTopologyNode_SetInputPrefType(node, 3, mediatype);
553 ok(hr == MF_E_INVALIDTYPE, "Unexpected hr %#x.\n", hr);
555 hr = IMFTopologyNode_SetOutputPrefType(node, 4, mediatype);
556 ok(hr == S_OK, "Failed to set preferred type, hr %#x.\n", hr);
558 hr = IMFTopologyNode_GetOutputPrefType(node, 0, &mediatype2);
559 ok(hr == E_FAIL, "Unexpected hr %#x.\n", hr);
561 hr = MFCreateMediaType(&mediatype2);
562 ok(hr == S_OK, "Failed to create media type, hr %#x.\n", hr);
564 /* Changing output type does not change input type. */
565 hr = IMFTopologyNode_SetOutputPrefType(node, 4, mediatype2);
566 ok(hr == S_OK, "Failed to set preferred type, hr %#x.\n", hr);
568 hr = IMFTopologyNode_GetInputPrefType(node, 0, &mediatype3);
569 ok(hr == S_OK, "Failed to get preferred type, hr %#x.\n", hr);
570 ok(mediatype3 == mediatype, "Unexpected mediatype instance.\n");
571 IMFMediaType_Release(mediatype3);
573 IMFMediaType_Release(mediatype2);
575 hr = IMFTopologyNode_GetInputCount(node, &count);
576 ok(hr == S_OK, "Failed to get output count, hr %#x.\n", hr);
577 ok(count == 0, "Unexpected count %u.\n", count);
579 hr = IMFTopologyNode_GetOutputCount(node, &count);
580 ok(hr == S_OK, "Failed to get output count, hr %#x.\n", hr);
581 ok(count == 5, "Unexpected count %u.\n", count);
583 IMFTopologyNode_Release(node);
585 /* Transform node. */
586 hr = MFCreateTopologyNode(MF_TOPOLOGY_TRANSFORM_NODE, &node);
587 ok(hr == S_OK, "Failed to create a node, hr %#x.\n", hr);
589 hr = IMFTopologyNode_SetInputPrefType(node, 3, mediatype);
590 ok(hr == S_OK, "Failed to set preferred type, hr %#x.\n", hr);
592 hr = IMFTopologyNode_GetInputCount(node, &count);
593 ok(hr == S_OK, "Failed to get input count, hr %#x.\n", hr);
594 ok(count == 4, "Unexpected count %u.\n", count);
596 hr = IMFTopologyNode_SetOutputPrefType(node, 4, mediatype);
597 ok(hr == S_OK, "Failed to set preferred type, hr %#x.\n", hr);
599 hr = IMFTopologyNode_GetInputCount(node, &count);
600 ok(hr == S_OK, "Failed to get output count, hr %#x.\n", hr);
601 ok(count == 4, "Unexpected count %u.\n", count);
603 hr = IMFTopologyNode_GetOutputCount(node, &count);
604 ok(hr == S_OK, "Failed to get output count, hr %#x.\n", hr);
605 ok(count == 5, "Unexpected count %u.\n", count);
607 IMFTopologyNode_Release(node);
609 IMFMediaType_Release(mediatype);
611 hr = IMFTopology_GetOutputNodeCollection(topology, &collection);
612 ok(hr == S_OK || broken(hr == E_FAIL) /* before Win8 */, "Failed to get output node collection, hr %#x.\n", hr);
613 if (SUCCEEDED(hr))
615 ok(!!collection, "Unexpected object pointer.\n");
616 hr = IMFCollection_GetElementCount(collection, &size);
617 ok(hr == S_OK, "Failed to get item count, hr %#x.\n", hr);
618 ok(size == 1, "Unexpected item count.\n");
619 IMFCollection_Release(collection);
622 IMFTopology_Release(topology);
624 /* Connect nodes. */
625 hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &node);
626 ok(hr == S_OK, "Failed to create topology node, hr %#x.\n", hr);
628 hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, &node2);
629 ok(hr == S_OK, "Failed to create topology node, hr %#x.\n", hr);
631 EXPECT_REF(node, 1);
632 EXPECT_REF(node2, 1);
634 hr = IMFTopologyNode_ConnectOutput(node, 0, node2, 1);
635 ok(hr == S_OK, "Failed to connect nodes, hr %#x.\n", hr);
637 EXPECT_REF(node, 2);
638 EXPECT_REF(node2, 2);
640 IMFTopologyNode_Release(node);
642 EXPECT_REF(node, 1);
643 EXPECT_REF(node2, 2);
645 IMFTopologyNode_Release(node2);
647 EXPECT_REF(node, 1);
648 EXPECT_REF(node2, 1);
650 hr = IMFTopologyNode_GetNodeType(node2, &node_type);
651 ok(hr == S_OK, "Failed to get node type, hr %#x.\n", hr);
653 IMFTopologyNode_Release(node);
655 /* Connect within topology. */
656 hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &node);
657 ok(hr == S_OK, "Failed to create topology node, hr %#x.\n", hr);
659 hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, &node2);
660 ok(hr == S_OK, "Failed to create topology node, hr %#x.\n", hr);
662 hr = MFCreateTopology(&topology);
663 ok(hr == S_OK, "Failed to create topology, hr %#x.\n", hr);
665 hr = IMFTopology_AddNode(topology, node);
666 ok(hr == S_OK, "Failed to add a node, hr %#x.\n", hr);
668 hr = IMFTopology_AddNode(topology, node2);
669 ok(hr == S_OK, "Failed to add a node, hr %#x.\n", hr);
671 EXPECT_REF(node, 2);
672 EXPECT_REF(node2, 2);
674 hr = IMFTopologyNode_ConnectOutput(node, 0, node2, 1);
675 ok(hr == S_OK, "Failed to connect nodes, hr %#x.\n", hr);
677 EXPECT_REF(node, 3);
678 EXPECT_REF(node2, 3);
680 hr = IMFTopology_Clear(topology);
681 ok(hr == S_OK, "Failed to clear topology, hr %#x.\n", hr);
683 EXPECT_REF(node, 1);
684 EXPECT_REF(node2, 1);
686 /* Removing connected node breaks connection. */
687 hr = IMFTopology_AddNode(topology, node);
688 ok(hr == S_OK, "Failed to add a node, hr %#x.\n", hr);
690 hr = IMFTopology_AddNode(topology, node2);
691 ok(hr == S_OK, "Failed to add a node, hr %#x.\n", hr);
693 hr = IMFTopologyNode_ConnectOutput(node, 0, node2, 1);
694 ok(hr == S_OK, "Failed to connect nodes, hr %#x.\n", hr);
696 hr = IMFTopology_RemoveNode(topology, node);
697 ok(hr == S_OK, "Failed to remove a node, hr %#x.\n", hr);
699 EXPECT_REF(node, 1);
700 EXPECT_REF(node2, 2);
702 hr = IMFTopologyNode_GetOutput(node, 0, &node3, &index);
703 ok(hr == MF_E_NOT_FOUND, "Unexpected hr %#x.\n", hr);
705 hr = IMFTopology_AddNode(topology, node);
706 ok(hr == S_OK, "Failed to add a node, hr %#x.\n", hr);
708 hr = IMFTopologyNode_ConnectOutput(node, 0, node2, 1);
709 ok(hr == S_OK, "Failed to connect nodes, hr %#x.\n", hr);
711 hr = IMFTopology_RemoveNode(topology, node2);
712 ok(hr == S_OK, "Failed to remove a node, hr %#x.\n", hr);
714 EXPECT_REF(node, 2);
715 EXPECT_REF(node2, 1);
717 IMFTopologyNode_Release(node);
718 IMFTopologyNode_Release(node2);
720 /* Cloning nodes of different types. */
721 hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &node);
722 ok(hr == S_OK, "Failed to create topology node, hr %#x.\n", hr);
724 hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, &node2);
725 ok(hr == S_OK, "Failed to create topology node, hr %#x.\n", hr);
727 hr = IMFTopologyNode_CloneFrom(node, node2);
728 ok(hr == MF_E_INVALIDREQUEST, "Unexpected hr %#x.\n", hr);
730 IMFTopologyNode_Release(node2);
732 /* Cloning preferred types. */
733 hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &node2);
734 ok(hr == S_OK, "Failed to create topology node, hr %#x.\n", hr);
736 hr = MFCreateMediaType(&mediatype);
737 ok(hr == S_OK, "Failed to create media type, hr %#x.\n", hr);
739 hr = IMFTopologyNode_SetOutputPrefType(node2, 0, mediatype);
740 ok(hr == S_OK, "Failed to set preferred type, hr %#x.\n", hr);
742 /* Vista checks for additional attributes. */
743 hr = IMFTopologyNode_CloneFrom(node, node2);
744 ok(hr == S_OK || broken(hr == MF_E_ATTRIBUTENOTFOUND) /* Vista */, "Failed to clone a node, hr %#x.\n", hr);
746 hr = IMFTopologyNode_GetOutputPrefType(node, 0, &mediatype2);
747 ok(hr == S_OK, "Failed to get preferred type, hr %#x.\n", hr);
748 ok(mediatype == mediatype2, "Unexpected media type.\n");
750 IMFMediaType_Release(mediatype2);
751 IMFMediaType_Release(mediatype);
753 IMFTopologyNode_Release(node2);
755 /* Existing preferred types are not cleared. */
756 hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &node2);
757 ok(hr == S_OK, "Failed to create topology node, hr %#x.\n", hr);
759 hr = IMFTopologyNode_GetOutputCount(node, &count);
760 ok(hr == S_OK, "Failed to get output count, hr %#x.\n", hr);
761 ok(count == 1, "Unexpected output count.\n");
763 hr = IMFTopologyNode_CloneFrom(node, node2);
764 ok(hr == S_OK || broken(hr == MF_E_ATTRIBUTENOTFOUND) /* Vista */, "Failed to clone a node, hr %#x.\n", hr);
766 hr = IMFTopologyNode_GetOutputCount(node, &count);
767 ok(hr == S_OK, "Failed to get output count, hr %#x.\n", hr);
768 ok(count == 1, "Unexpected output count.\n");
770 hr = IMFTopologyNode_GetOutputPrefType(node, 0, &mediatype2);
771 ok(hr == S_OK, "Failed to get preferred type, hr %#x.\n", hr);
772 ok(!!mediatype2, "Unexpected media type.\n");
773 IMFMediaType_Release(mediatype2);
775 hr = IMFTopologyNode_CloneFrom(node2, node);
776 ok(hr == S_OK || broken(hr == MF_E_ATTRIBUTENOTFOUND) /* Vista */, "Failed to clone a node, hr %#x.\n", hr);
778 hr = IMFTopologyNode_GetOutputCount(node2, &count);
779 ok(hr == S_OK, "Failed to get output count, hr %#x.\n", hr);
780 ok(count == 1, "Unexpected output count.\n");
782 IMFTopologyNode_Release(node2);
783 IMFTopologyNode_Release(node);
785 /* Add one node, connect to another that hasn't been added. */
786 hr = IMFTopology_Clear(topology);
787 ok(hr == S_OK, "Failed to clear topology, hr %#x.\n", hr);
789 hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &node);
790 ok(hr == S_OK, "Failed to create topology node, hr %#x.\n", hr);
792 hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, &node2);
793 ok(hr == S_OK, "Failed to create topology node, hr %#x.\n", hr);
795 hr = IMFTopology_AddNode(topology, node);
796 ok(hr == S_OK, "Failed to add a node, hr %#x.\n", hr);
798 hr = IMFTopology_GetNodeCount(topology, &node_count);
799 ok(hr == S_OK, "Failed to get node count, hr %#x.\n", hr);
800 ok(node_count == 1, "Unexpected node count.\n");
802 hr = IMFTopologyNode_ConnectOutput(node, 0, node2, 0);
803 ok(hr == S_OK, "Failed to connect nodes, hr %#x.\n", hr);
805 hr = IMFTopology_GetNodeCount(topology, &node_count);
806 ok(hr == S_OK, "Failed to get node count, hr %#x.\n", hr);
807 ok(node_count == 1, "Unexpected node count.\n");
809 IMFTopologyNode_Release(node);
810 IMFTopologyNode_Release(node2);
812 /* Add same node to different topologies. */
813 hr = IMFTopology_Clear(topology);
814 ok(hr == S_OK, "Failed to clear topology, hr %#x.\n", hr);
816 hr = MFCreateTopology(&topology2);
817 ok(hr == S_OK, "Failed to create topology, hr %#x.\n", hr);
819 hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &node);
820 ok(hr == S_OK, "Failed to create topology node, hr %#x.\n", hr);
822 hr = IMFTopology_AddNode(topology, node);
823 ok(hr == S_OK, "Failed to add a node, hr %#x.\n", hr);
824 EXPECT_REF(node, 2);
826 hr = IMFTopology_GetNodeCount(topology, &node_count);
827 ok(hr == S_OK, "Failed to get node count, hr %#x.\n", hr);
828 ok(node_count == 1, "Unexpected node count.\n");
830 hr = IMFTopology_GetNodeCount(topology2, &node_count);
831 ok(hr == S_OK, "Failed to get node count, hr %#x.\n", hr);
832 ok(node_count == 0, "Unexpected node count.\n");
834 hr = IMFTopology_AddNode(topology2, node);
835 ok(hr == S_OK, "Failed to add a node, hr %#x.\n", hr);
836 EXPECT_REF(node, 3);
838 hr = IMFTopology_GetNodeCount(topology, &node_count);
839 ok(hr == S_OK, "Failed to get node count, hr %#x.\n", hr);
840 ok(node_count == 1, "Unexpected node count.\n");
842 hr = IMFTopology_GetNodeCount(topology2, &node_count);
843 ok(hr == S_OK, "Failed to get node count, hr %#x.\n", hr);
844 ok(node_count == 1, "Unexpected node count.\n");
846 IMFTopology_Release(topology2);
847 IMFTopology_Release(topology);
850 static void test_topology_tee_node(void)
852 IMFTopologyNode *src_node, *tee_node;
853 IMFMediaType *mediatype, *mediatype2;
854 IMFTopology *topology;
855 unsigned int count;
856 HRESULT hr;
858 hr = MFCreateTopology(&topology);
859 ok(hr == S_OK, "Failed to create topology, hr %#x.\n", hr);
861 hr = MFCreateMediaType(&mediatype);
862 ok(hr == S_OK, "Failed to create media type, hr %#x.\n", hr);
864 hr = MFCreateTopologyNode(MF_TOPOLOGY_TEE_NODE, &tee_node);
865 ok(hr == S_OK, "Failed to create topology node, hr %#x.\n", hr);
867 hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &src_node);
868 ok(hr == S_OK, "Failed to create topology node, hr %#x.\n", hr);
870 hr = IMFTopologyNode_SetInputPrefType(tee_node, 0, mediatype);
871 ok(hr == S_OK, "Failed to set type, hr %#x.\n", hr);
873 /* Even though tee node has only one input and source has only one output,
874 it's possible to connect to higher inputs/outputs. */
876 /* SRC(0) -> TEE(0) */
877 hr = IMFTopologyNode_ConnectOutput(src_node, 0, tee_node, 0);
878 ok(hr == S_OK, "Failed to connect nodes, hr %#x.\n", hr);
880 hr = IMFTopologyNode_GetInputCount(tee_node, &count);
881 ok(hr == S_OK, "Failed to get count, hr %#x.\n", hr);
882 ok(count == 1, "Unexpected count %u.\n", count);
884 hr = IMFTopologyNode_GetInputPrefType(tee_node, 0, &mediatype2);
885 ok(hr == S_OK, "Failed to get type, hr %#x.\n", hr);
886 ok(mediatype2 == mediatype, "Unexpected type.\n");
887 IMFMediaType_Release(mediatype2);
889 /* SRC(0) -> TEE(1) */
890 hr = IMFTopologyNode_ConnectOutput(src_node, 0, tee_node, 1);
891 ok(hr == S_OK, "Failed to connect nodes, hr %#x.\n", hr);
893 hr = IMFTopologyNode_GetInputCount(tee_node, &count);
894 ok(hr == S_OK, "Failed to get count, hr %#x.\n", hr);
895 ok(count == 2, "Unexpected count %u.\n", count);
897 hr = IMFTopologyNode_SetInputPrefType(tee_node, 1, mediatype);
898 ok(hr == MF_E_INVALIDTYPE, "Unexpected hr %#x.\n", hr);
900 /* SRC(1) -> TEE(1) */
901 hr = IMFTopologyNode_ConnectOutput(src_node, 1, tee_node, 1);
902 ok(hr == S_OK, "Failed to connect nodes, hr %#x.\n", hr);
904 hr = IMFTopologyNode_GetOutputCount(src_node, &count);
905 ok(hr == S_OK, "Failed to get count, hr %#x.\n", hr);
906 ok(count == 2, "Unexpected count %u.\n", count);
908 IMFMediaType_Release(mediatype);
909 IMFTopologyNode_Release(src_node);
910 IMFTopologyNode_Release(tee_node);
911 IMFTopology_Release(topology);
914 static HRESULT WINAPI test_getservice_QI(IMFGetService *iface, REFIID riid, void **obj)
916 if (IsEqualIID(riid, &IID_IMFGetService) || IsEqualIID(riid, &IID_IUnknown))
918 *obj = iface;
919 return S_OK;
922 *obj = NULL;
923 return E_NOINTERFACE;
926 static ULONG WINAPI test_getservice_AddRef(IMFGetService *iface)
928 return 2;
931 static ULONG WINAPI test_getservice_Release(IMFGetService *iface)
933 return 1;
936 static HRESULT WINAPI test_getservice_GetService(IMFGetService *iface, REFGUID service, REFIID riid, void **obj)
938 *obj = (void *)0xdeadbeef;
939 return 0x83eddead;
942 static const IMFGetServiceVtbl testmfgetservicevtbl =
944 test_getservice_QI,
945 test_getservice_AddRef,
946 test_getservice_Release,
947 test_getservice_GetService,
950 static IMFGetService test_getservice = { &testmfgetservicevtbl };
952 static HRESULT WINAPI testservice_QI(IUnknown *iface, REFIID riid, void **obj)
954 if (IsEqualIID(riid, &IID_IUnknown))
956 *obj = iface;
957 return S_OK;
960 *obj = NULL;
962 if (IsEqualIID(riid, &IID_IMFGetService))
963 return 0x82eddead;
965 return E_NOINTERFACE;
968 static HRESULT WINAPI testservice2_QI(IUnknown *iface, REFIID riid, void **obj)
970 if (IsEqualIID(riid, &IID_IUnknown))
972 *obj = iface;
973 return S_OK;
976 if (IsEqualIID(riid, &IID_IMFGetService))
978 *obj = &test_getservice;
979 return S_OK;
982 *obj = NULL;
983 return E_NOINTERFACE;
986 static ULONG WINAPI testservice_AddRef(IUnknown *iface)
988 return 2;
991 static ULONG WINAPI testservice_Release(IUnknown *iface)
993 return 1;
996 static const IUnknownVtbl testservicevtbl =
998 testservice_QI,
999 testservice_AddRef,
1000 testservice_Release,
1003 static const IUnknownVtbl testservice2vtbl =
1005 testservice2_QI,
1006 testservice_AddRef,
1007 testservice_Release,
1010 static IUnknown testservice = { &testservicevtbl };
1011 static IUnknown testservice2 = { &testservice2vtbl };
1013 static void test_MFGetService(void)
1015 IUnknown *unk;
1016 HRESULT hr;
1018 hr = MFGetService(NULL, NULL, NULL, NULL);
1019 ok(hr == E_POINTER, "Unexpected return value %#x.\n", hr);
1021 unk = (void *)0xdeadbeef;
1022 hr = MFGetService(NULL, NULL, NULL, (void **)&unk);
1023 ok(hr == E_POINTER, "Unexpected return value %#x.\n", hr);
1024 ok(unk == (void *)0xdeadbeef, "Unexpected out object.\n");
1026 hr = MFGetService(&testservice, NULL, NULL, NULL);
1027 ok(hr == 0x82eddead, "Unexpected return value %#x.\n", hr);
1029 unk = (void *)0xdeadbeef;
1030 hr = MFGetService(&testservice, NULL, NULL, (void **)&unk);
1031 ok(hr == 0x82eddead, "Unexpected return value %#x.\n", hr);
1032 ok(unk == (void *)0xdeadbeef, "Unexpected out object.\n");
1034 unk = NULL;
1035 hr = MFGetService(&testservice2, NULL, NULL, (void **)&unk);
1036 ok(hr == 0x83eddead, "Unexpected return value %#x.\n", hr);
1037 ok(unk == (void *)0xdeadbeef, "Unexpected out object.\n");
1040 static void test_sequencer_source(void)
1042 IMFSequencerSource *seq_source;
1043 HRESULT hr;
1045 hr = MFStartup(MF_VERSION, MFSTARTUP_FULL);
1046 ok(hr == S_OK, "Startup failure, hr %#x.\n", hr);
1048 hr = MFCreateSequencerSource(NULL, &seq_source);
1049 ok(hr == S_OK, "Failed to create sequencer source, hr %#x.\n", hr);
1051 check_interface(seq_source, &IID_IMFMediaSourceTopologyProvider, TRUE);
1053 IMFSequencerSource_Release(seq_source);
1055 hr = MFShutdown();
1056 ok(hr == S_OK, "Shutdown failure, hr %#x.\n", hr);
1059 struct test_callback
1061 IMFAsyncCallback IMFAsyncCallback_iface;
1064 static HRESULT WINAPI testcallback_QueryInterface(IMFAsyncCallback *iface, REFIID riid, void **obj)
1066 if (IsEqualIID(riid, &IID_IMFAsyncCallback) ||
1067 IsEqualIID(riid, &IID_IUnknown))
1069 *obj = iface;
1070 IMFAsyncCallback_AddRef(iface);
1071 return S_OK;
1074 *obj = NULL;
1075 return E_NOINTERFACE;
1078 static ULONG WINAPI testcallback_AddRef(IMFAsyncCallback *iface)
1080 return 2;
1083 static ULONG WINAPI testcallback_Release(IMFAsyncCallback *iface)
1085 return 1;
1088 static HRESULT WINAPI testcallback_GetParameters(IMFAsyncCallback *iface, DWORD *flags, DWORD *queue)
1090 ok(flags != NULL && queue != NULL, "Unexpected arguments.\n");
1091 return E_NOTIMPL;
1094 static HRESULT WINAPI testcallback_Invoke(IMFAsyncCallback *iface, IMFAsyncResult *result)
1096 ok(result != NULL, "Unexpected result object.\n");
1098 return E_NOTIMPL;
1101 static const IMFAsyncCallbackVtbl testcallbackvtbl =
1103 testcallback_QueryInterface,
1104 testcallback_AddRef,
1105 testcallback_Release,
1106 testcallback_GetParameters,
1107 testcallback_Invoke,
1110 static void init_test_callback(struct test_callback *callback)
1112 callback->IMFAsyncCallback_iface.lpVtbl = &testcallbackvtbl;
1115 static void test_session_events(IMFMediaSession *session)
1117 struct test_callback callback, callback2;
1118 IMFAsyncResult *result;
1119 IMFMediaEvent *event;
1120 HRESULT hr;
1122 init_test_callback(&callback);
1123 init_test_callback(&callback2);
1125 hr = IMFMediaSession_GetEvent(session, MF_EVENT_FLAG_NO_WAIT, &event);
1126 ok(hr == MF_E_NO_EVENTS_AVAILABLE, "Unexpected hr %#x.\n", hr);
1128 /* Async case. */
1129 hr = IMFMediaSession_BeginGetEvent(session, NULL, NULL);
1130 ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
1132 hr = IMFMediaSession_BeginGetEvent(session, &callback.IMFAsyncCallback_iface, (IUnknown *)session);
1133 ok(hr == S_OK, "Failed to Begin*, hr %#x.\n", hr);
1135 /* Same callback, same state. */
1136 hr = IMFMediaSession_BeginGetEvent(session, &callback.IMFAsyncCallback_iface, (IUnknown *)session);
1137 ok(hr == MF_S_MULTIPLE_BEGIN, "Unexpected hr %#x.\n", hr);
1139 /* Same callback, different state. */
1140 hr = IMFMediaSession_BeginGetEvent(session, &callback.IMFAsyncCallback_iface, (IUnknown *)&callback);
1141 ok(hr == MF_E_MULTIPLE_BEGIN, "Unexpected hr %#x.\n", hr);
1143 /* Different callback, same state. */
1144 hr = IMFMediaSession_BeginGetEvent(session, &callback2.IMFAsyncCallback_iface, (IUnknown *)session);
1145 ok(hr == MF_E_MULTIPLE_SUBSCRIBERS, "Unexpected hr %#x.\n", hr);
1147 /* Different callback, different state. */
1148 hr = IMFMediaSession_BeginGetEvent(session, &callback2.IMFAsyncCallback_iface, (IUnknown *)&callback.IMFAsyncCallback_iface);
1149 ok(hr == MF_E_MULTIPLE_SUBSCRIBERS, "Unexpected hr %#x.\n", hr);
1151 hr = MFCreateAsyncResult(NULL, &callback.IMFAsyncCallback_iface, NULL, &result);
1152 ok(hr == S_OK, "Failed to create result, hr %#x.\n", hr);
1154 hr = IMFMediaSession_EndGetEvent(session, result, &event);
1155 ok(hr == E_FAIL, "Unexpected hr %#x.\n", hr);
1157 /* Shutdown behavior. */
1158 hr = IMFMediaSession_Shutdown(session);
1159 ok(hr == S_OK, "Failed to shut down, hr %#x.\n", hr);
1162 static void test_media_session(void)
1164 IMFRateControl *rate_control, *rate_control2;
1165 MFCLOCK_PROPERTIES clock_props;
1166 IMFRateSupport *rate_support;
1167 IMFAttributes *attributes;
1168 IMFMediaSession *session;
1169 IMFTopology *topology;
1170 IMFShutdown *shutdown;
1171 PROPVARIANT propvar;
1172 DWORD status, caps;
1173 IMFClock *clock;
1174 IUnknown *unk;
1175 HRESULT hr;
1176 float rate;
1177 BOOL thin;
1179 hr = MFStartup(MF_VERSION, MFSTARTUP_FULL);
1180 ok(hr == S_OK, "Startup failure, hr %#x.\n", hr);
1182 hr = MFCreateMediaSession(NULL, &session);
1183 ok(hr == S_OK, "Failed to create media session, hr %#x.\n", hr);
1185 check_interface(session, &IID_IMFGetService, TRUE);
1186 check_interface(session, &IID_IMFAttributes, FALSE);
1187 check_interface(session, &IID_IMFTopologyNodeAttributeEditor, FALSE);
1189 hr = MFGetService((IUnknown *)session, &MF_TOPONODE_ATTRIBUTE_EDITOR_SERVICE, &IID_IMFTopologyNodeAttributeEditor,
1190 (void **)&unk);
1191 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
1193 check_interface(unk, &IID_IMFMediaSession, FALSE);
1195 IUnknown_Release(unk);
1197 hr = MFGetService((IUnknown *)session, &MF_RATE_CONTROL_SERVICE, &IID_IMFRateSupport, (void **)&rate_support);
1198 ok(hr == S_OK, "Failed to get rate support interface, hr %#x.\n", hr);
1200 hr = MFGetService((IUnknown *)session, &MF_RATE_CONTROL_SERVICE, &IID_IMFRateControl, (void **)&rate_control);
1201 ok(hr == S_OK, "Failed to get rate control interface, hr %#x.\n", hr);
1203 hr = MFGetService((IUnknown *)session, &MF_LOCAL_MFT_REGISTRATION_SERVICE, &IID_IMFLocalMFTRegistration, (void **)&unk);
1204 ok(hr == S_OK || broken(hr == E_NOINTERFACE) /* Vista */, "Failed to get registration service, hr %#x.\n", hr);
1205 if (SUCCEEDED(hr))
1206 IUnknown_Release(unk);
1208 hr = IMFRateSupport_QueryInterface(rate_support, &IID_IMFMediaSession, (void **)&unk);
1209 ok(hr == S_OK, "Failed to get session interface, hr %#x.\n", hr);
1210 ok(unk == (IUnknown *)session, "Unexpected pointer.\n");
1211 IUnknown_Release(unk);
1213 hr = IMFRateControl_GetRate(rate_control, NULL, NULL);
1214 ok(FAILED(hr), "Unexpected hr %#x.\n", hr);
1216 rate = 0.0f;
1217 hr = IMFRateControl_GetRate(rate_control, NULL, &rate);
1218 ok(hr == S_OK, "Failed to get playback rate, hr %#x.\n", hr);
1219 ok(rate == 1.0f, "Unexpected rate %f.\n", rate);
1221 hr = IMFRateControl_GetRate(rate_control, &thin, NULL);
1222 ok(FAILED(hr), "Unexpected hr %#x.\n", hr);
1224 thin = TRUE;
1225 rate = 0.0f;
1226 hr = IMFRateControl_GetRate(rate_control, &thin, &rate);
1227 ok(hr == S_OK, "Failed to get playback rate, hr %#x.\n", hr);
1228 ok(!thin, "Unexpected thinning.\n");
1229 ok(rate == 1.0f, "Unexpected rate %f.\n", rate);
1231 hr = IMFMediaSession_GetClock(session, &clock);
1232 ok(hr == S_OK, "Failed to get clock, hr %#x.\n", hr);
1234 check_interface(clock, &IID_IMFPresentationClock, TRUE);
1236 hr = IMFClock_QueryInterface(clock, &IID_IMFRateControl, (void **)&rate_control2);
1237 ok(hr == S_OK, "Failed to get rate control, hr %#x.\n", hr);
1239 rate = 0.0f;
1240 hr = IMFRateControl_GetRate(rate_control2, NULL, &rate);
1241 ok(hr == S_OK, "Failed to get clock rate, hr %#x.\n", hr);
1242 ok(rate == 1.0f, "Unexpected rate %f.\n", rate);
1244 hr = IMFRateControl_SetRate(rate_control, FALSE, 1.5f);
1245 todo_wine
1246 ok(hr == S_OK, "Failed to set rate, hr %#x.\n", hr);
1248 IMFRateControl_Release(rate_control2);
1250 hr = IMFClock_GetProperties(clock, &clock_props);
1251 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#x.\n", hr);
1252 IMFClock_Release(clock);
1254 IMFRateControl_Release(rate_control);
1255 IMFRateSupport_Release(rate_support);
1257 IMFMediaSession_Release(session);
1259 hr = MFCreateMediaSession(NULL, &session);
1260 ok(hr == S_OK, "Failed to create media session, hr %#x.\n", hr);
1262 hr = IMFMediaSession_GetClock(session, &clock);
1263 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
1265 hr = IMFClock_QueryInterface(clock, &IID_IMFShutdown, (void **)&shutdown);
1266 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
1268 hr = IMFShutdown_GetShutdownStatus(shutdown, &status);
1269 ok(hr == MF_E_INVALIDREQUEST, "Unexpected hr %#x.\n", hr);
1271 hr = IMFMediaSession_Shutdown(session);
1272 ok(hr == S_OK, "Failed to shut down, hr %#x.\n", hr);
1274 hr = IMFShutdown_GetShutdownStatus(shutdown, &status);
1275 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
1276 ok(status == MFSHUTDOWN_COMPLETED, "Unexpected shutdown status %u.\n", status);
1278 IMFShutdown_Release(shutdown);
1280 hr = IMFMediaSession_ClearTopologies(session);
1281 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr);
1283 hr = IMFMediaSession_Start(session, &GUID_NULL, NULL);
1284 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
1286 propvar.vt = VT_EMPTY;
1287 hr = IMFMediaSession_Start(session, &GUID_NULL, &propvar);
1288 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr);
1290 hr = IMFMediaSession_Pause(session);
1291 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr);
1293 hr = IMFMediaSession_Stop(session);
1294 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr);
1296 hr = IMFMediaSession_Close(session);
1297 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr);
1299 hr = IMFMediaSession_GetClock(session, &clock);
1300 ok(hr == MF_E_SHUTDOWN || broken(hr == E_UNEXPECTED) /* Win7 */, "Unexpected hr %#x.\n", hr);
1302 hr = IMFMediaSession_GetSessionCapabilities(session, &caps);
1303 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr);
1305 hr = IMFMediaSession_GetSessionCapabilities(session, NULL);
1306 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
1308 hr = IMFMediaSession_GetFullTopology(session, MFSESSION_GETFULLTOPOLOGY_CURRENT, 0, &topology);
1309 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr);
1311 hr = IMFMediaSession_Shutdown(session);
1312 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr);
1314 IMFMediaSession_Release(session);
1316 /* Custom topology loader, GUID is not registered. */
1317 hr = MFCreateAttributes(&attributes, 1);
1318 ok(hr == S_OK, "Failed to create attributes, hr %#x.\n", hr);
1320 hr = IMFAttributes_SetGUID(attributes, &MF_SESSION_TOPOLOADER, &MF_SESSION_TOPOLOADER);
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 /* Disabled quality manager. */
1328 hr = IMFAttributes_SetGUID(attributes, &MF_SESSION_QUALITY_MANAGER, &GUID_NULL);
1329 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
1331 hr = MFCreateMediaSession(attributes, &session);
1332 ok(hr == S_OK, "Failed to create media session, hr %#x.\n", hr);
1333 IMFMediaSession_Release(session);
1335 IMFAttributes_Release(attributes);
1337 /* Basic events behavior. */
1338 hr = MFCreateMediaSession(NULL, &session);
1339 ok(hr == S_OK, "Failed to create media session, hr %#x.\n", hr);
1341 test_session_events(session);
1343 IMFMediaSession_Release(session);
1345 hr = MFShutdown();
1346 ok(hr == S_OK, "Shutdown failure, hr %#x.\n", hr);
1349 static HRESULT WINAPI test_grabber_callback_QueryInterface(IMFSampleGrabberSinkCallback *iface, REFIID riid,
1350 void **obj)
1352 if (IsEqualIID(riid, &IID_IMFSampleGrabberSinkCallback) ||
1353 IsEqualIID(riid, &IID_IMFClockStateSink) ||
1354 IsEqualIID(riid, &IID_IUnknown))
1356 *obj = iface;
1357 IMFSampleGrabberSinkCallback_AddRef(iface);
1358 return S_OK;
1361 *obj = NULL;
1362 return E_NOINTERFACE;
1365 static ULONG WINAPI test_grabber_callback_AddRef(IMFSampleGrabberSinkCallback *iface)
1367 return 2;
1370 static ULONG WINAPI test_grabber_callback_Release(IMFSampleGrabberSinkCallback *iface)
1372 return 1;
1375 static HRESULT WINAPI test_grabber_callback_OnClockStart(IMFSampleGrabberSinkCallback *iface, MFTIME systime,
1376 LONGLONG offset)
1378 return E_NOTIMPL;
1381 static HRESULT WINAPI test_grabber_callback_OnClockStop(IMFSampleGrabberSinkCallback *iface, MFTIME systime)
1383 return E_NOTIMPL;
1386 static HRESULT WINAPI test_grabber_callback_OnClockPause(IMFSampleGrabberSinkCallback *iface, MFTIME systime)
1388 return E_NOTIMPL;
1391 static HRESULT WINAPI test_grabber_callback_OnClockRestart(IMFSampleGrabberSinkCallback *iface, MFTIME systime)
1393 return E_NOTIMPL;
1396 static HRESULT WINAPI test_grabber_callback_OnClockSetRate(IMFSampleGrabberSinkCallback *iface, MFTIME systime, float rate)
1398 return E_NOTIMPL;
1401 static HRESULT WINAPI test_grabber_callback_OnSetPresentationClock(IMFSampleGrabberSinkCallback *iface,
1402 IMFPresentationClock *clock)
1404 return E_NOTIMPL;
1407 static HRESULT WINAPI test_grabber_callback_OnProcessSample(IMFSampleGrabberSinkCallback *iface, REFGUID major_type,
1408 DWORD sample_flags, LONGLONG sample_time, LONGLONG sample_duration, const BYTE *buffer, DWORD sample_size)
1410 return E_NOTIMPL;
1413 static HRESULT WINAPI test_grabber_callback_OnShutdown(IMFSampleGrabberSinkCallback *iface)
1415 return E_NOTIMPL;
1418 static const IMFSampleGrabberSinkCallbackVtbl test_grabber_callback_vtbl =
1420 test_grabber_callback_QueryInterface,
1421 test_grabber_callback_AddRef,
1422 test_grabber_callback_Release,
1423 test_grabber_callback_OnClockStart,
1424 test_grabber_callback_OnClockStop,
1425 test_grabber_callback_OnClockPause,
1426 test_grabber_callback_OnClockRestart,
1427 test_grabber_callback_OnClockSetRate,
1428 test_grabber_callback_OnSetPresentationClock,
1429 test_grabber_callback_OnProcessSample,
1430 test_grabber_callback_OnShutdown,
1433 struct test_source
1435 IMFMediaSource IMFMediaSource_iface;
1436 LONG refcount;
1439 static struct test_source *impl_from_IMFMediaSource(IMFMediaSource *iface)
1441 return CONTAINING_RECORD(iface, struct test_source, IMFMediaSource_iface);
1444 static HRESULT WINAPI test_source_QueryInterface(IMFMediaSource *iface, REFIID riid, void **out)
1446 if (IsEqualIID(riid, &IID_IMFMediaSource)
1447 || IsEqualIID(riid, &IID_IMFMediaEventGenerator)
1448 || IsEqualIID(riid, &IID_IUnknown))
1450 *out = iface;
1452 else
1454 *out = NULL;
1455 return E_NOINTERFACE;
1458 IMFMediaSource_AddRef(iface);
1459 return S_OK;
1462 static ULONG WINAPI test_source_AddRef(IMFMediaSource *iface)
1464 struct test_source *source = impl_from_IMFMediaSource(iface);
1465 return InterlockedIncrement(&source->refcount);
1468 static ULONG WINAPI test_source_Release(IMFMediaSource *iface)
1470 struct test_source *source = impl_from_IMFMediaSource(iface);
1471 ULONG refcount = InterlockedDecrement(&source->refcount);
1473 if (!refcount)
1474 HeapFree(GetProcessHeap(), 0, source);
1476 return refcount;
1479 static HRESULT WINAPI test_source_GetEvent(IMFMediaSource *iface, DWORD flags, IMFMediaEvent **event)
1481 ok(0, "Unexpected call.\n");
1482 return E_NOTIMPL;
1485 static HRESULT WINAPI test_source_BeginGetEvent(IMFMediaSource *iface, IMFAsyncCallback *callback, IUnknown *state)
1487 ok(0, "Unexpected call.\n");
1488 return E_NOTIMPL;
1491 static HRESULT WINAPI test_source_EndGetEvent(IMFMediaSource *iface, IMFAsyncResult *result, IMFMediaEvent **event)
1493 ok(0, "Unexpected call.\n");
1494 return E_NOTIMPL;
1497 static HRESULT WINAPI test_source_QueueEvent(IMFMediaSource *iface, MediaEventType event_type, REFGUID ext_type,
1498 HRESULT hr, const PROPVARIANT *value)
1500 ok(0, "Unexpected call.\n");
1501 return E_NOTIMPL;
1504 static HRESULT WINAPI test_source_GetCharacteristics(IMFMediaSource *iface, DWORD *flags)
1506 ok(0, "Unexpected call.\n");
1507 return E_NOTIMPL;
1510 static HRESULT WINAPI test_source_CreatePresentationDescriptor(IMFMediaSource *iface, IMFPresentationDescriptor **pd)
1512 ok(0, "Unexpected call.\n");
1513 return E_NOTIMPL;
1516 static HRESULT WINAPI test_source_Start(IMFMediaSource *iface, IMFPresentationDescriptor *pd, const GUID *time_format,
1517 const PROPVARIANT *start_position)
1519 ok(0, "Unexpected call.\n");
1520 return E_NOTIMPL;
1523 static HRESULT WINAPI test_source_Stop(IMFMediaSource *iface)
1525 ok(0, "Unexpected call.\n");
1526 return E_NOTIMPL;
1529 static HRESULT WINAPI test_source_Pause(IMFMediaSource *iface)
1531 ok(0, "Unexpected call.\n");
1532 return E_NOTIMPL;
1535 static HRESULT WINAPI test_source_Shutdown(IMFMediaSource *iface)
1537 ok(0, "Unexpected call.\n");
1538 return E_NOTIMPL;
1541 static const IMFMediaSourceVtbl test_source_vtbl =
1543 test_source_QueryInterface,
1544 test_source_AddRef,
1545 test_source_Release,
1546 test_source_GetEvent,
1547 test_source_BeginGetEvent,
1548 test_source_EndGetEvent,
1549 test_source_QueueEvent,
1550 test_source_GetCharacteristics,
1551 test_source_CreatePresentationDescriptor,
1552 test_source_Start,
1553 test_source_Stop,
1554 test_source_Pause,
1555 test_source_Shutdown,
1558 static IMFMediaSource *create_test_source(void)
1560 struct test_source *source;
1562 source = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*source));
1563 source->IMFMediaSource_iface.lpVtbl = &test_source_vtbl;
1564 source->refcount = 1;
1566 return &source->IMFMediaSource_iface;
1569 struct type_attr
1571 const GUID *key;
1572 unsigned int value;
1575 static void init_media_type(IMFMediaType *mediatype, const GUID *major, const struct type_attr *attrs)
1577 HRESULT hr;
1579 hr = IMFMediaType_DeleteAllItems(mediatype);
1580 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
1582 hr = IMFMediaType_SetGUID(mediatype, &MF_MT_MAJOR_TYPE, major);
1583 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
1585 while (attrs->key)
1587 if (IsEqualGUID(attrs->key, &MF_MT_SUBTYPE))
1589 GUID subtype;
1591 memcpy(&subtype, IsEqualGUID(major, &MFMediaType_Audio) ? &MFAudioFormat_Base : &MFVideoFormat_Base,
1592 sizeof(subtype));
1593 subtype.Data1 = attrs->value;
1594 hr = IMFMediaType_SetGUID(mediatype, attrs->key, &subtype);
1596 else
1597 hr = IMFMediaType_SetUINT32(mediatype, attrs->key, attrs->value);
1598 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
1600 attrs++;
1604 static void init_source_node(IMFMediaType *mediatype, IMFMediaSource *source, IMFTopologyNode *node)
1606 IMFPresentationDescriptor *pd;
1607 IMFMediaTypeHandler *handler;
1608 IMFStreamDescriptor *sd;
1609 HRESULT hr;
1611 hr = IMFTopologyNode_DeleteAllItems(node);
1612 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
1614 hr = MFCreateStreamDescriptor(0, 1, &mediatype, &sd);
1615 ok(hr == S_OK, "Failed to create stream descriptor, hr %#x.\n", hr);
1617 hr = IMFStreamDescriptor_GetMediaTypeHandler(sd, &handler);
1618 ok(hr == S_OK, "Failed to get media type handler, hr %#x.\n", hr);
1620 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, mediatype);
1621 ok(hr == S_OK, "Failed to set current media type, hr %#x.\n", hr);
1623 IMFMediaTypeHandler_Release(handler);
1625 hr = MFCreatePresentationDescriptor(1, &sd, &pd);
1626 ok(hr == S_OK, "Failed to create presentation descriptor, hr %#x.\n", hr);
1628 hr = IMFTopologyNode_SetUnknown(node, &MF_TOPONODE_PRESENTATION_DESCRIPTOR, (IUnknown *)pd);
1629 ok(hr == S_OK, "Failed to set node pd, hr %#x.\n", hr);
1631 IMFPresentationDescriptor_Release(pd);
1633 hr = IMFTopologyNode_SetUnknown(node, &MF_TOPONODE_STREAM_DESCRIPTOR, (IUnknown *)sd);
1634 ok(hr == S_OK, "Failed to set node sd, hr %#x.\n", hr);
1636 if (source)
1638 hr = IMFTopologyNode_SetUnknown(node, &MF_TOPONODE_SOURCE, (IUnknown *)source);
1639 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
1642 IMFStreamDescriptor_Release(sd);
1645 static void init_sink_node(IMFActivate *sink_activate, unsigned int method, IMFTopologyNode *node)
1647 IMFStreamSink *stream_sink;
1648 IMFMediaSink *sink;
1649 HRESULT hr;
1651 hr = IMFTopologyNode_DeleteAllItems(node);
1652 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
1654 hr = IMFActivate_ActivateObject(sink_activate, &IID_IMFMediaSink, (void **)&sink);
1655 ok(hr == S_OK, "Failed to activate, hr %#x.\n", hr);
1657 hr = IMFMediaSink_GetStreamSinkByIndex(sink, 0, &stream_sink);
1658 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
1660 IMFMediaSink_Release(sink);
1662 hr = IMFTopologyNode_SetObject(node, (IUnknown *)stream_sink);
1663 ok(hr == S_OK, "Failed to set object, hr %#x.\n", hr);
1665 IMFStreamSink_Release(stream_sink);
1667 hr = IMFTopologyNode_SetUINT32(node, &MF_TOPONODE_CONNECT_METHOD, method);
1668 ok(hr == S_OK, "Failed to set connect method, hr %#x.\n", hr);
1671 enum loader_test_flags
1673 LOADER_EXPECTED_DECODER = 0x1,
1674 LOADER_EXPECTED_CONVERTER = 0x2,
1675 LOADER_TODO = 0x4,
1678 static void test_topology_loader(void)
1680 static const struct loader_test
1682 const GUID *major;
1683 struct
1685 struct type_attr attrs[8];
1686 } input_type;
1687 struct
1689 struct type_attr attrs[8];
1690 } output_type;
1692 MF_CONNECT_METHOD method;
1693 HRESULT expected_result;
1694 unsigned int flags;
1696 loader_tests[] =
1699 /* PCM -> PCM, same type */
1700 &MFMediaType_Audio,
1703 { &MF_MT_SUBTYPE, WAVE_FORMAT_PCM },
1704 { &MF_MT_AUDIO_NUM_CHANNELS, 1 },
1705 { &MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100 },
1706 { &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 44100 },
1707 { &MF_MT_AUDIO_BLOCK_ALIGNMENT, 1 },
1708 { &MF_MT_AUDIO_BITS_PER_SAMPLE, 8 },
1713 { &MF_MT_SUBTYPE, WAVE_FORMAT_PCM },
1714 { &MF_MT_AUDIO_NUM_CHANNELS, 1 },
1715 { &MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100 },
1716 { &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 44100 },
1717 { &MF_MT_AUDIO_BLOCK_ALIGNMENT, 1 },
1718 { &MF_MT_AUDIO_BITS_PER_SAMPLE, 8 },
1722 MF_CONNECT_DIRECT,
1723 S_OK,
1727 /* PCM -> PCM, different bps. */
1728 &MFMediaType_Audio,
1731 { &MF_MT_SUBTYPE, WAVE_FORMAT_PCM },
1732 { &MF_MT_AUDIO_NUM_CHANNELS, 1 },
1733 { &MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100 },
1734 { &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 44100 },
1735 { &MF_MT_AUDIO_BLOCK_ALIGNMENT, 1 },
1736 { &MF_MT_AUDIO_BITS_PER_SAMPLE, 8 },
1741 { &MF_MT_SUBTYPE, WAVE_FORMAT_PCM },
1742 { &MF_MT_AUDIO_NUM_CHANNELS, 1 },
1743 { &MF_MT_AUDIO_SAMPLES_PER_SECOND, 48000 },
1744 { &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 48000 },
1745 { &MF_MT_AUDIO_BLOCK_ALIGNMENT, 1 },
1746 { &MF_MT_AUDIO_BITS_PER_SAMPLE, 8 },
1750 MF_CONNECT_DIRECT,
1751 MF_E_INVALIDMEDIATYPE,
1755 /* PCM -> PCM, different bps. */
1756 &MFMediaType_Audio,
1759 { &MF_MT_SUBTYPE, WAVE_FORMAT_PCM },
1760 { &MF_MT_AUDIO_NUM_CHANNELS, 1 },
1761 { &MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100 },
1762 { &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 44100 },
1763 { &MF_MT_AUDIO_BLOCK_ALIGNMENT, 1 },
1764 { &MF_MT_AUDIO_BITS_PER_SAMPLE, 8 },
1769 { &MF_MT_SUBTYPE, WAVE_FORMAT_PCM },
1770 { &MF_MT_AUDIO_NUM_CHANNELS, 1 },
1771 { &MF_MT_AUDIO_SAMPLES_PER_SECOND, 48000 },
1772 { &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 48000 },
1773 { &MF_MT_AUDIO_BLOCK_ALIGNMENT, 1 },
1774 { &MF_MT_AUDIO_BITS_PER_SAMPLE, 8 },
1778 MF_CONNECT_ALLOW_CONVERTER,
1779 S_OK,
1780 LOADER_EXPECTED_CONVERTER | LOADER_TODO,
1784 /* MP3 -> PCM */
1785 &MFMediaType_Audio,
1788 { &MF_MT_SUBTYPE, WAVE_FORMAT_MPEGLAYER3 },
1789 { &MF_MT_AUDIO_NUM_CHANNELS, 2 },
1790 { &MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100 },
1791 { &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 16000 },
1792 { &MF_MT_AUDIO_BLOCK_ALIGNMENT, 1 },
1797 { &MF_MT_SUBTYPE, WAVE_FORMAT_PCM },
1798 { &MF_MT_AUDIO_NUM_CHANNELS, 1 },
1799 { &MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100 },
1800 { &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 44100 },
1801 { &MF_MT_AUDIO_BLOCK_ALIGNMENT, 1 },
1802 { &MF_MT_AUDIO_BITS_PER_SAMPLE, 8 },
1806 MF_CONNECT_DIRECT,
1807 MF_E_INVALIDMEDIATYPE,
1811 /* MP3 -> PCM */
1812 &MFMediaType_Audio,
1815 { &MF_MT_SUBTYPE, WAVE_FORMAT_MPEGLAYER3 },
1816 { &MF_MT_AUDIO_NUM_CHANNELS, 2 },
1817 { &MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100 },
1818 { &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 16000 },
1819 { &MF_MT_AUDIO_BLOCK_ALIGNMENT, 1 },
1824 { &MF_MT_SUBTYPE, WAVE_FORMAT_PCM },
1825 { &MF_MT_AUDIO_NUM_CHANNELS, 1 },
1826 { &MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100 },
1827 { &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 44100 },
1828 { &MF_MT_AUDIO_BLOCK_ALIGNMENT, 1 },
1829 { &MF_MT_AUDIO_BITS_PER_SAMPLE, 8 },
1833 MF_CONNECT_ALLOW_CONVERTER,
1834 MF_E_TRANSFORM_NOT_POSSIBLE_FOR_CURRENT_MEDIATYPE_COMBINATION,
1835 LOADER_TODO,
1839 /* MP3 -> PCM */
1840 &MFMediaType_Audio,
1843 { &MF_MT_SUBTYPE, WAVE_FORMAT_MPEGLAYER3 },
1844 { &MF_MT_AUDIO_NUM_CHANNELS, 2 },
1845 { &MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100 },
1846 { &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 16000 },
1847 { &MF_MT_AUDIO_BLOCK_ALIGNMENT, 1 },
1852 { &MF_MT_SUBTYPE, WAVE_FORMAT_PCM },
1853 { &MF_MT_AUDIO_NUM_CHANNELS, 1 },
1854 { &MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100 },
1855 { &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 44100 },
1856 { &MF_MT_AUDIO_BLOCK_ALIGNMENT, 1 },
1857 { &MF_MT_AUDIO_BITS_PER_SAMPLE, 8 },
1861 MF_CONNECT_ALLOW_DECODER,
1862 S_OK,
1863 LOADER_EXPECTED_DECODER | LOADER_TODO,
1867 IMFSampleGrabberSinkCallback test_grabber_callback = { &test_grabber_callback_vtbl };
1868 IMFTopologyNode *src_node, *sink_node, *src_node2, *sink_node2, *mft_node;
1869 IMFTopology *topology, *topology2, *full_topology;
1870 IMFMediaType *media_type, *input_type, *output_type;
1871 unsigned int i, count, value, index;
1872 IMFPresentationDescriptor *pd;
1873 IMFActivate *sink_activate;
1874 MF_TOPOLOGY_TYPE node_type;
1875 IMFStreamDescriptor *sd;
1876 IMFTransform *transform;
1877 IMFMediaSource *source;
1878 IMFTopoLoader *loader;
1879 IUnknown *node_object;
1880 WORD node_count;
1881 TOPOID node_id;
1882 HRESULT hr;
1883 BOOL ret;
1885 hr = MFStartup(MF_VERSION, MFSTARTUP_FULL);
1886 ok(hr == S_OK, "Startup failure, hr %#x.\n", hr);
1888 hr = MFCreateTopoLoader(NULL);
1889 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
1891 hr = MFCreateTopoLoader(&loader);
1892 ok(hr == S_OK, "Failed to create topology loader, hr %#x.\n", hr);
1894 hr = MFCreateTopology(&topology);
1895 ok(hr == S_OK, "Failed to create topology, hr %#x.\n", hr);
1897 /* Empty topology */
1898 hr = IMFTopoLoader_Load(loader, topology, &full_topology, NULL);
1899 todo_wine
1900 ok(hr == MF_E_TOPO_UNSUPPORTED, "Unexpected hr %#x.\n", hr);
1902 /* Add source node. */
1903 hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &src_node);
1904 ok(hr == S_OK, "Failed to create topology node, hr %#x.\n", hr);
1906 /* When a decoder is involved, windows requires this attribute to be present */
1907 source = create_test_source();
1909 hr = IMFTopologyNode_SetUnknown(src_node, &MF_TOPONODE_SOURCE, (IUnknown *)source);
1910 ok(hr == S_OK, "Failed to set node source, hr %#x.\n", hr);
1912 hr = MFCreateMediaType(&media_type);
1913 ok(hr == S_OK, "Failed to create media type, hr %#x.\n", hr);
1915 hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio);
1916 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
1917 hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFAudioFormat_PCM);
1918 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
1920 hr = MFCreateStreamDescriptor(0, 1, &media_type, &sd);
1921 ok(hr == S_OK, "Failed to create stream descriptor, hr %#x.\n", hr);
1923 hr = IMFTopologyNode_SetUnknown(src_node, &MF_TOPONODE_STREAM_DESCRIPTOR, (IUnknown *)sd);
1924 ok(hr == S_OK, "Failed to set node sd, hr %#x.\n", hr);
1926 hr = MFCreatePresentationDescriptor(1, &sd, &pd);
1927 ok(hr == S_OK, "Failed to create presentation descriptor, hr %#x.\n", hr);
1929 hr = IMFTopologyNode_SetUnknown(src_node, &MF_TOPONODE_PRESENTATION_DESCRIPTOR, (IUnknown *)pd);
1930 ok(hr == S_OK, "Failed to set node pd, hr %#x.\n", hr);
1932 IMFPresentationDescriptor_Release(pd);
1933 IMFStreamDescriptor_Release(sd);
1934 IMFMediaType_Release(media_type);
1936 hr = IMFTopology_AddNode(topology, src_node);
1937 ok(hr == S_OK, "Failed to add a node, hr %#x.\n", hr);
1939 /* Source node only. */
1940 hr = IMFTopoLoader_Load(loader, topology, &full_topology, NULL);
1941 todo_wine
1942 ok(hr == MF_E_TOPO_UNSUPPORTED, "Unexpected hr %#x.\n", hr);
1944 hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, &sink_node);
1945 ok(hr == S_OK, "Failed to create output node, hr %#x.\n", hr);
1947 hr = MFCreateMediaType(&media_type);
1948 ok(hr == S_OK, "Failed to create media type, hr %#x.\n", hr);
1950 hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio);
1951 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
1952 hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFAudioFormat_PCM);
1953 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
1955 hr = MFCreateSampleGrabberSinkActivate(media_type, &test_grabber_callback, &sink_activate);
1956 ok(hr == S_OK, "Failed to create grabber sink, hr %#x.\n", hr);
1958 hr = IMFTopologyNode_SetObject(sink_node, (IUnknown *)sink_activate);
1959 ok(hr == S_OK, "Failed to set object, hr %#x.\n", hr);
1961 IMFMediaType_Release(media_type);
1963 hr = IMFTopology_AddNode(topology, sink_node);
1964 ok(hr == S_OK, "Failed to add sink node, hr %#x.\n", hr);
1966 hr = IMFTopoLoader_Load(loader, topology, &full_topology, NULL);
1967 todo_wine
1968 ok(hr == MF_E_TOPO_UNSUPPORTED, "Unexpected hr %#x.\n", hr);
1970 hr = IMFTopologyNode_ConnectOutput(src_node, 0, sink_node, 0);
1971 ok(hr == S_OK, "Failed to connect nodes, hr %#x.\n", hr);
1973 /* Sink was not resolved. */
1974 hr = IMFTopoLoader_Load(loader, topology, &full_topology, NULL);
1975 ok(hr == MF_E_TOPO_SINK_ACTIVATES_UNSUPPORTED, "Unexpected hr %#x.\n", hr);
1977 hr = MFCreateMediaType(&input_type);
1978 ok(hr == S_OK, "Failed to create media type, hr %#x.\n", hr);
1980 hr = MFCreateMediaType(&output_type);
1981 ok(hr == S_OK, "Failed to create media type, hr %#x.\n", hr);
1983 for (i = 0; i < ARRAY_SIZE(loader_tests); ++i)
1985 const struct loader_test *test = &loader_tests[i];
1987 init_media_type(input_type, test->major, test->input_type.attrs);
1988 init_media_type(output_type, test->major, test->output_type.attrs);
1990 hr = MFCreateSampleGrabberSinkActivate(output_type, &test_grabber_callback, &sink_activate);
1991 ok(hr == S_OK, "Failed to create grabber sink, hr %#x.\n", hr);
1993 init_source_node(input_type, source, src_node);
1994 init_sink_node(sink_activate, test->method, sink_node);
1996 hr = IMFTopology_GetCount(topology, &count);
1997 ok(hr == S_OK, "Failed to get attribute count, hr %#x.\n", hr);
1998 ok(!count, "Unexpected count %u.\n", count);
2000 hr = IMFTopoLoader_Load(loader, topology, &full_topology, NULL);
2001 todo_wine_if(test->flags & LOADER_TODO)
2002 ok(hr == test->expected_result, "Unexpected hr %#x on test %u.\n", hr, i);
2003 ok(full_topology != topology, "Unexpected instance.\n");
2005 if (test->expected_result == S_OK && hr == S_OK)
2007 hr = IMFTopology_GetCount(full_topology, &count);
2008 ok(hr == S_OK, "Failed to get attribute count, hr %#x.\n", hr);
2009 todo_wine
2010 ok(count == 1, "Unexpected count %u.\n", count);
2012 value = 0xdeadbeef;
2013 hr = IMFTopology_GetUINT32(full_topology, &MF_TOPOLOGY_RESOLUTION_STATUS, &value);
2014 todo_wine {
2015 ok(hr == S_OK, "Failed to get attribute, hr %#x.\n", hr);
2016 ok(value == MF_TOPOLOGY_RESOLUTION_SUCCEEDED, "Unexpected value %#x.\n", value);
2018 count = 2;
2019 if (test->flags & LOADER_EXPECTED_DECODER)
2020 count++;
2021 if (test->flags & LOADER_EXPECTED_CONVERTER)
2022 count++;
2024 hr = IMFTopology_GetNodeCount(full_topology, &node_count);
2025 ok(hr == S_OK, "Failed to get node count, hr %#x.\n", hr);
2026 todo_wine_if(test->flags & (LOADER_EXPECTED_CONVERTER | LOADER_EXPECTED_DECODER))
2027 ok(node_count == count, "Unexpected node count %u.\n", node_count);
2029 hr = IMFTopologyNode_GetTopoNodeID(src_node, &node_id);
2030 ok(hr == S_OK, "Failed to get source node id, hr %#x.\n", hr);
2032 hr = IMFTopology_GetNodeByID(full_topology, node_id, &src_node2);
2033 ok(hr == S_OK, "Failed to get source in resolved topology, hr %#x.\n", hr);
2035 hr = IMFTopologyNode_GetTopoNodeID(sink_node, &node_id);
2036 ok(hr == S_OK, "Failed to get sink node id, hr %#x.\n", hr);
2038 hr = IMFTopology_GetNodeByID(full_topology, node_id, &sink_node2);
2039 ok(hr == S_OK, "Failed to get sink in resolved topology, hr %#x.\n", hr);
2041 if (test->flags & (LOADER_EXPECTED_DECODER | LOADER_EXPECTED_CONVERTER) && strcmp(winetest_platform, "wine"))
2043 hr = IMFTopologyNode_GetOutput(src_node2, 0, &mft_node, &index);
2044 ok(hr == S_OK, "Failed to get transform node in resolved topology, hr %#x.\n", hr);
2045 ok(!index, "Unexpected stream index %u.\n", index);
2047 hr = IMFTopologyNode_GetNodeType(mft_node, &node_type);
2048 ok(hr == S_OK, "Failed to get transform node type in resolved topology, hr %#x.\n", hr);
2049 ok(node_type == MF_TOPOLOGY_TRANSFORM_NODE, "Unexpected node type %u.\n", node_type);
2051 hr = IMFTopologyNode_GetObject(mft_node, &node_object);
2052 ok(hr == S_OK, "Failed to get object of transform node, hr %#x.\n", hr);
2054 if (test->flags & LOADER_EXPECTED_DECODER)
2056 value = 0;
2057 hr = IMFTopologyNode_GetUINT32(mft_node, &MF_TOPONODE_DECODER, &value);
2058 ok(hr == S_OK, "Failed to get attribute, hr %#x.\n", hr);
2059 ok(value == 1, "Unexpected value.\n");
2062 hr = IMFTopologyNode_GetItem(mft_node, &MF_TOPONODE_TRANSFORM_OBJECTID, NULL);
2063 ok(hr == S_OK, "Failed to get attribute, hr %#x.\n", hr);
2065 hr = IUnknown_QueryInterface(node_object, &IID_IMFTransform, (void **)&transform);
2066 ok(hr == S_OK, "Failed to get IMFTransform from transform node's object, hr %#x.\n", hr);
2067 IUnknown_Release(node_object);
2069 hr = IMFTransform_GetInputCurrentType(transform, 0, &media_type);
2070 ok(hr == S_OK, "Failed to get transform input type, hr %#x.\n", hr);
2072 hr = IMFMediaType_Compare(input_type, (IMFAttributes *)media_type, MF_ATTRIBUTES_MATCH_OUR_ITEMS, &ret);
2073 ok(hr == S_OK, "Failed to compare media types, hr %#x.\n", hr);
2074 ok(ret, "Input type of first transform doesn't match source node type.\n");
2076 IMFTopologyNode_Release(mft_node);
2077 IMFMediaType_Release(media_type);
2078 IMFTransform_Release(transform);
2080 hr = IMFTopologyNode_GetInput(sink_node2, 0, &mft_node, &index);
2081 ok(hr == S_OK, "Failed to get transform node in resolved topology, hr %#x.\n", hr);
2082 ok(!index, "Unexpected stream index %u.\n", index);
2084 hr = IMFTopologyNode_GetNodeType(mft_node, &node_type);
2085 ok(hr == S_OK, "Failed to get transform node type in resolved topology, hr %#x.\n", hr);
2086 ok(node_type == MF_TOPOLOGY_TRANSFORM_NODE, "Unexpected node type %u.\n", node_type);
2088 hr = IMFTopologyNode_GetItem(mft_node, &MF_TOPONODE_TRANSFORM_OBJECTID, NULL);
2089 ok(hr == S_OK, "Failed to get attribute, hr %#x.\n", hr);
2091 hr = IMFTopologyNode_GetObject(mft_node, &node_object);
2092 ok(hr == S_OK, "Failed to get object of transform node, hr %#x.\n", hr);
2094 hr = IUnknown_QueryInterface(node_object, &IID_IMFTransform, (void**) &transform);
2095 ok(hr == S_OK, "Failed to get IMFTransform from transform node's object, hr %#x.\n", hr);
2096 IUnknown_Release(node_object);
2098 hr = IMFTransform_GetOutputCurrentType(transform, 0, &media_type);
2099 ok(hr == S_OK, "Failed to get transform output type, hr %#x.\n", hr);
2101 hr = IMFMediaType_Compare(output_type, (IMFAttributes *)media_type, MF_ATTRIBUTES_MATCH_OUR_ITEMS, &ret);
2102 ok(hr == S_OK, "Failed to compare media types, hr %#x.\n", hr);
2103 ok(ret, "Output type of last transform doesn't match sink node type.\n");
2105 IMFTopologyNode_Release(mft_node);
2106 IMFMediaType_Release(media_type);
2107 IMFTransform_Release(transform);
2110 IMFTopologyNode_Release(sink_node2);
2112 hr = IMFTopology_SetUINT32(full_topology, &IID_IMFTopology, 123);
2113 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2114 hr = IMFTopoLoader_Load(loader, full_topology, &topology2, NULL);
2115 ok(hr == S_OK, "Failed to resolve topology, hr %#x.\n", hr);
2116 ok(full_topology != topology2, "Unexpected instance.\n");
2117 hr = IMFTopology_GetUINT32(topology2, &IID_IMFTopology, &value);
2118 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2120 IMFTopology_Release(topology2);
2121 IMFTopology_Release(full_topology);
2124 hr = IMFTopology_GetCount(topology, &count);
2125 ok(hr == S_OK, "Failed to get attribute count, hr %#x.\n", hr);
2126 ok(!count, "Unexpected count %u.\n", count);
2128 IMFActivate_ShutdownObject(sink_activate);
2129 IMFActivate_Release(sink_activate);
2132 IMFMediaType_Release(input_type);
2133 IMFMediaType_Release(output_type);
2135 IMFMediaSource_Release(source);
2136 IMFTopoLoader_Release(loader);
2138 hr = MFShutdown();
2139 ok(hr == S_OK, "Shutdown failure, hr %#x.\n", hr);
2142 static void test_topology_loader_evr(void)
2144 IMFTopologyNode *node, *source_node, *evr_node;
2145 IMFTopology *topology, *full_topology;
2146 IMFMediaTypeHandler *handler;
2147 unsigned int i, count, value;
2148 IMFStreamSink *stream_sink;
2149 IMFMediaType *media_type;
2150 IMFActivate *activate;
2151 IMFTopoLoader *loader;
2152 IMFMediaSink *sink;
2153 WORD node_count;
2154 UINT64 value64;
2155 HWND window;
2156 HRESULT hr;
2158 hr = CoInitialize(NULL);
2159 ok(hr == S_OK, "Failed to initialize, hr %#x.\n", hr);
2161 hr = MFCreateTopoLoader(&loader);
2162 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2164 /* Source node. */
2165 hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &source_node);
2166 ok(hr == S_OK, "Failed to create topology node, hr %#x.\n", hr);
2168 hr = MFCreateMediaType(&media_type);
2169 ok(hr == S_OK, "Failed to create media type, hr %#x.\n", hr);
2171 hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
2172 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2173 hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFVideoFormat_RGB32);
2174 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2175 hr = IMFMediaType_SetUINT64(media_type, &MF_MT_FRAME_SIZE, (UINT64)640 << 32 | 480);
2176 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2177 hr = IMFMediaType_SetUINT32(media_type, &MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE);
2178 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2180 init_source_node(media_type, NULL, source_node);
2182 /* EVR sink node. */
2183 window = create_window();
2185 hr = MFCreateVideoRendererActivate(window, &activate);
2186 ok(hr == S_OK, "Failed to create activate object, hr %#x.\n", hr);
2188 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink);
2189 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2191 hr = IMFMediaSink_GetStreamSinkById(sink, 0, &stream_sink);
2192 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2194 hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, &evr_node);
2195 ok(hr == S_OK, "Failed to create topology node, hr %#x.\n", hr);
2197 hr = IMFTopologyNode_SetObject(evr_node, (IUnknown *)stream_sink);
2198 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2200 hr = IMFStreamSink_GetMediaTypeHandler(stream_sink, &handler);
2201 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2202 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, media_type);
2203 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2204 IMFMediaTypeHandler_Release(handler);
2206 IMFStreamSink_Release(stream_sink);
2207 IMFMediaSink_Release(sink);
2209 hr = MFCreateTopology(&topology);
2210 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2212 hr = IMFTopology_AddNode(topology, source_node);
2213 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2214 hr = IMFTopology_AddNode(topology, evr_node);
2215 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2216 hr = IMFTopologyNode_ConnectOutput(source_node, 0, evr_node, 0);
2217 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2219 hr = IMFTopologyNode_SetUINT32(evr_node, &MF_TOPONODE_CONNECT_METHOD, MF_CONNECT_DIRECT);
2220 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2222 hr = IMFTopologyNode_GetCount(evr_node, &count);
2223 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2224 ok(count == 1, "Unexpected attribute count %u.\n", count);
2226 hr = IMFTopoLoader_Load(loader, topology, &full_topology, NULL);
2227 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2229 hr = IMFTopology_GetNodeCount(full_topology, &node_count);
2230 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2231 ok(node_count == 3, "Unexpected node count %u.\n", node_count);
2233 for (i = 0; i < node_count; ++i)
2235 MF_TOPOLOGY_TYPE node_type;
2237 hr = IMFTopology_GetNode(full_topology, i, &node);
2238 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2240 hr = IMFTopologyNode_GetNodeType(node, &node_type);
2241 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2243 if (node_type == MF_TOPOLOGY_OUTPUT_NODE)
2245 value = 1;
2246 hr = IMFTopologyNode_GetUINT32(node, &MF_TOPONODE_STREAMID, &value);
2247 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2248 ok(!value, "Unexpected stream id %u.\n", value);
2250 else if (node_type == MF_TOPOLOGY_SOURCESTREAM_NODE)
2252 value64 = 1;
2253 hr = IMFTopologyNode_GetUINT64(node, &MF_TOPONODE_MEDIASTART, &value64);
2254 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2255 ok(!value64, "Unexpected value.\n");
2259 IMFTopology_Release(full_topology);
2261 IMFTopoLoader_Release(loader);
2263 IMFTopologyNode_Release(source_node);
2264 IMFTopologyNode_Release(evr_node);
2265 IMFTopology_Release(topology);
2266 IMFMediaType_Release(media_type);
2267 DestroyWindow(window);
2269 CoUninitialize();
2272 static HRESULT WINAPI testshutdown_QueryInterface(IMFShutdown *iface, REFIID riid, void **obj)
2274 if (IsEqualIID(riid, &IID_IMFShutdown) ||
2275 IsEqualIID(riid, &IID_IUnknown))
2277 *obj = iface;
2278 IMFShutdown_AddRef(iface);
2279 return S_OK;
2282 *obj = NULL;
2283 return E_NOINTERFACE;
2286 static ULONG WINAPI testshutdown_AddRef(IMFShutdown *iface)
2288 return 2;
2291 static ULONG WINAPI testshutdown_Release(IMFShutdown *iface)
2293 return 1;
2296 static HRESULT WINAPI testshutdown_Shutdown(IMFShutdown *iface)
2298 return 0xdead;
2301 static HRESULT WINAPI testshutdown_GetShutdownStatus(IMFShutdown *iface, MFSHUTDOWN_STATUS *status)
2303 ok(0, "Unexpected call.\n");
2304 return E_NOTIMPL;
2307 static const IMFShutdownVtbl testshutdownvtbl =
2309 testshutdown_QueryInterface,
2310 testshutdown_AddRef,
2311 testshutdown_Release,
2312 testshutdown_Shutdown,
2313 testshutdown_GetShutdownStatus,
2316 static void test_MFShutdownObject(void)
2318 IMFShutdown testshutdown = { &testshutdownvtbl };
2319 IUnknown testshutdown2 = { &testservicevtbl };
2320 HRESULT hr;
2322 hr = MFShutdownObject(NULL);
2323 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2325 hr = MFShutdownObject((IUnknown *)&testshutdown);
2326 ok(hr == S_OK, "Failed to shut down, hr %#x.\n", hr);
2328 hr = MFShutdownObject(&testshutdown2);
2329 ok(hr == S_OK, "Failed to shut down, hr %#x.\n", hr);
2332 enum clock_action
2334 CLOCK_START,
2335 CLOCK_STOP,
2336 CLOCK_PAUSE,
2339 static HRESULT WINAPI test_clock_sink_QueryInterface(IMFClockStateSink *iface, REFIID riid, void **obj)
2341 if (IsEqualIID(riid, &IID_IMFClockStateSink) ||
2342 IsEqualIID(riid, &IID_IUnknown))
2344 *obj = iface;
2345 IMFClockStateSink_AddRef(iface);
2346 return S_OK;
2349 *obj = NULL;
2350 return E_NOINTERFACE;
2353 static ULONG WINAPI test_clock_sink_AddRef(IMFClockStateSink *iface)
2355 return 2;
2358 static ULONG WINAPI test_clock_sink_Release(IMFClockStateSink *iface)
2360 return 1;
2363 static HRESULT WINAPI test_clock_sink_OnClockStart(IMFClockStateSink *iface, MFTIME system_time, LONGLONG offset)
2365 return E_NOTIMPL;
2368 static HRESULT WINAPI test_clock_sink_OnClockStop(IMFClockStateSink *iface, MFTIME system_time)
2370 return E_NOTIMPL;
2373 static HRESULT WINAPI test_clock_sink_OnClockPause(IMFClockStateSink *iface, MFTIME system_time)
2375 return E_NOTIMPL;
2378 static HRESULT WINAPI test_clock_sink_OnClockRestart(IMFClockStateSink *iface, MFTIME system_time)
2380 return E_NOTIMPL;
2383 static HRESULT WINAPI test_clock_sink_OnClockSetRate(IMFClockStateSink *iface, MFTIME system_time, float rate)
2385 return E_NOTIMPL;
2388 static const IMFClockStateSinkVtbl test_clock_sink_vtbl =
2390 test_clock_sink_QueryInterface,
2391 test_clock_sink_AddRef,
2392 test_clock_sink_Release,
2393 test_clock_sink_OnClockStart,
2394 test_clock_sink_OnClockStop,
2395 test_clock_sink_OnClockPause,
2396 test_clock_sink_OnClockRestart,
2397 test_clock_sink_OnClockSetRate,
2400 static void test_presentation_clock(void)
2402 static const struct clock_state_test
2404 enum clock_action action;
2405 MFCLOCK_STATE clock_state;
2406 MFCLOCK_STATE source_state;
2407 HRESULT hr;
2409 clock_state_change[] =
2411 { CLOCK_STOP, MFCLOCK_STATE_STOPPED, MFCLOCK_STATE_INVALID },
2412 { CLOCK_PAUSE, MFCLOCK_STATE_STOPPED, MFCLOCK_STATE_INVALID, MF_E_INVALIDREQUEST },
2413 { CLOCK_STOP, MFCLOCK_STATE_STOPPED, MFCLOCK_STATE_INVALID, MF_E_CLOCK_STATE_ALREADY_SET },
2414 { CLOCK_START, MFCLOCK_STATE_RUNNING, MFCLOCK_STATE_RUNNING },
2415 { CLOCK_START, MFCLOCK_STATE_RUNNING, MFCLOCK_STATE_RUNNING },
2416 { CLOCK_PAUSE, MFCLOCK_STATE_PAUSED, MFCLOCK_STATE_PAUSED },
2417 { CLOCK_PAUSE, MFCLOCK_STATE_PAUSED, MFCLOCK_STATE_PAUSED, MF_E_CLOCK_STATE_ALREADY_SET },
2418 { CLOCK_STOP, MFCLOCK_STATE_STOPPED, MFCLOCK_STATE_STOPPED },
2419 { CLOCK_START, MFCLOCK_STATE_RUNNING, MFCLOCK_STATE_RUNNING },
2420 { CLOCK_STOP, MFCLOCK_STATE_STOPPED, MFCLOCK_STATE_STOPPED },
2421 { CLOCK_STOP, MFCLOCK_STATE_STOPPED, MFCLOCK_STATE_STOPPED, MF_E_CLOCK_STATE_ALREADY_SET },
2422 { CLOCK_PAUSE, MFCLOCK_STATE_STOPPED, MFCLOCK_STATE_STOPPED, MF_E_INVALIDREQUEST },
2423 { CLOCK_START, MFCLOCK_STATE_RUNNING, MFCLOCK_STATE_RUNNING },
2424 { CLOCK_PAUSE, MFCLOCK_STATE_PAUSED, MFCLOCK_STATE_PAUSED },
2425 { CLOCK_START, MFCLOCK_STATE_RUNNING, MFCLOCK_STATE_RUNNING },
2427 IMFClockStateSink test_sink = { &test_clock_sink_vtbl };
2428 IMFPresentationTimeSource *time_source;
2429 MFCLOCK_PROPERTIES props, props2;
2430 IMFRateControl *rate_control;
2431 IMFPresentationClock *clock;
2432 MFSHUTDOWN_STATUS status;
2433 IMFShutdown *shutdown;
2434 MFTIME systime, time;
2435 LONGLONG clock_time;
2436 MFCLOCK_STATE state;
2437 unsigned int i;
2438 DWORD value;
2439 float rate;
2440 HRESULT hr;
2441 BOOL thin;
2443 hr = MFStartup(MF_VERSION, MFSTARTUP_FULL);
2444 ok(hr == S_OK, "Failed to start up, hr %#x.\n", hr);
2446 hr = MFCreatePresentationClock(&clock);
2447 ok(hr == S_OK, "Failed to create presentation clock, hr %#x.\n", hr);
2449 check_interface(clock, &IID_IMFTimer, TRUE);
2450 check_interface(clock, &IID_IMFRateControl, TRUE);
2451 check_interface(clock, &IID_IMFPresentationClock, TRUE);
2452 check_interface(clock, &IID_IMFShutdown, TRUE);
2453 check_interface(clock, &IID_IMFClock, TRUE);
2455 hr = IMFPresentationClock_QueryInterface(clock, &IID_IMFRateControl, (void **)&rate_control);
2456 ok(hr == S_OK, "Failed to get rate control interface, hr %#x.\n", hr);
2458 hr = IMFPresentationClock_GetTimeSource(clock, &time_source);
2459 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#x.\n", hr);
2461 hr = IMFPresentationClock_GetTimeSource(clock, NULL);
2462 ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
2464 hr = IMFPresentationClock_GetClockCharacteristics(clock, &value);
2465 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#x.\n", hr);
2467 hr = IMFPresentationClock_GetClockCharacteristics(clock, NULL);
2468 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#x.\n", hr);
2470 hr = IMFPresentationClock_GetTime(clock, &time);
2471 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#x.\n", hr);
2473 hr = IMFPresentationClock_GetTime(clock, NULL);
2474 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
2476 value = 1;
2477 hr = IMFPresentationClock_GetContinuityKey(clock, &value);
2478 ok(hr == S_OK, "Failed to get continuity key, hr %#x.\n", hr);
2479 ok(value == 0, "Unexpected value %u.\n", value);
2481 hr = IMFPresentationClock_GetProperties(clock, &props);
2482 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#x.\n", hr);
2484 hr = IMFPresentationClock_GetState(clock, 0, &state);
2485 ok(hr == S_OK, "Failed to get state, hr %#x.\n", hr);
2486 ok(state == MFCLOCK_STATE_INVALID, "Unexpected state %d.\n", state);
2488 hr = IMFPresentationClock_GetCorrelatedTime(clock, 0, &clock_time, &systime);
2489 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#x.\n", hr);
2491 hr = IMFPresentationClock_GetCorrelatedTime(clock, 0, NULL, &systime);
2492 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#x.\n", hr);
2494 hr = IMFPresentationClock_GetCorrelatedTime(clock, 0, &time, NULL);
2495 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#x.\n", hr);
2497 /* Sinks. */
2498 hr = IMFPresentationClock_AddClockStateSink(clock, NULL);
2499 ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
2501 hr = IMFPresentationClock_AddClockStateSink(clock, &test_sink);
2502 ok(hr == S_OK, "Failed to add a sink, hr %#x.\n", hr);
2504 hr = IMFPresentationClock_AddClockStateSink(clock, &test_sink);
2505 ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
2507 hr = IMFPresentationClock_RemoveClockStateSink(clock, NULL);
2508 ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
2510 hr = IMFPresentationClock_RemoveClockStateSink(clock, &test_sink);
2511 ok(hr == S_OK, "Failed to remove sink, hr %#x.\n", hr);
2513 hr = IMFPresentationClock_RemoveClockStateSink(clock, &test_sink);
2514 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2516 /* State change commands, time source is not set yet. */
2517 hr = IMFPresentationClock_Start(clock, 0);
2518 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#x.\n", hr);
2520 hr = IMFPresentationClock_Pause(clock);
2521 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#x.\n", hr);
2523 hr = IMFPresentationClock_Stop(clock);
2524 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#x.\n", hr);
2526 hr = IMFRateControl_SetRate(rate_control, FALSE, 0.0f);
2527 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#x.\n", hr);
2529 /* Set default time source. */
2530 hr = MFCreateSystemTimeSource(&time_source);
2531 ok(hr == S_OK, "Failed to create time source, hr %#x.\n", hr);
2533 hr = IMFPresentationTimeSource_GetClockCharacteristics(time_source, &value);
2534 ok(hr == S_OK, "Failed to get time source flags, hr %#x.\n", hr);
2535 ok(value == (MFCLOCK_CHARACTERISTICS_FLAG_FREQUENCY_10MHZ | MFCLOCK_CHARACTERISTICS_FLAG_IS_SYSTEM_CLOCK),
2536 "Unexpected clock flags %#x.\n", value);
2538 hr = IMFPresentationClock_SetTimeSource(clock, time_source);
2539 ok(hr == S_OK, "Failed to set time source, hr %#x.\n", hr);
2541 hr = IMFPresentationTimeSource_GetProperties(time_source, &props2);
2542 ok(hr == S_OK, "Failed to get time source properties, hr %#x.\n", hr);
2544 hr = IMFPresentationClock_GetClockCharacteristics(clock, &value);
2545 ok(hr == S_OK, "Failed to get clock flags, hr %#x.\n", hr);
2546 ok(value == (MFCLOCK_CHARACTERISTICS_FLAG_FREQUENCY_10MHZ | MFCLOCK_CHARACTERISTICS_FLAG_IS_SYSTEM_CLOCK),
2547 "Unexpected clock flags %#x.\n", value);
2549 hr = IMFPresentationClock_GetProperties(clock, &props);
2550 ok(hr == S_OK, "Failed to get clock properties, hr %#x.\n", hr);
2551 ok(!memcmp(&props, &props2, sizeof(props)), "Unexpected clock properties.\n");
2553 /* State changes. */
2554 for (i = 0; i < ARRAY_SIZE(clock_state_change); ++i)
2556 switch (clock_state_change[i].action)
2558 case CLOCK_STOP:
2559 hr = IMFPresentationClock_Stop(clock);
2560 break;
2561 case CLOCK_PAUSE:
2562 hr = IMFPresentationClock_Pause(clock);
2563 break;
2564 case CLOCK_START:
2565 hr = IMFPresentationClock_Start(clock, 0);
2566 break;
2567 default:
2570 ok(hr == clock_state_change[i].hr, "%u: unexpected hr %#x.\n", i, hr);
2572 hr = IMFPresentationTimeSource_GetState(time_source, 0, &state);
2573 ok(hr == S_OK, "%u: failed to get state, hr %#x.\n", i, hr);
2574 ok(state == clock_state_change[i].source_state, "%u: unexpected state %d.\n", i, state);
2576 hr = IMFPresentationClock_GetState(clock, 0, &state);
2577 ok(hr == S_OK, "%u: failed to get state, hr %#x.\n", i, hr);
2578 ok(state == clock_state_change[i].clock_state, "%u: unexpected state %d.\n", i, state);
2581 /* Clock time stamps. */
2582 hr = IMFPresentationClock_Start(clock, 10);
2583 ok(hr == S_OK, "Failed to start presentation clock, hr %#x.\n", hr);
2585 hr = IMFPresentationClock_Pause(clock);
2586 ok(hr == S_OK, "Failed to pause presentation clock, hr %#x.\n", hr);
2588 hr = IMFPresentationClock_GetTime(clock, &time);
2589 ok(hr == S_OK, "Failed to get clock time, hr %#x.\n", hr);
2591 hr = IMFPresentationTimeSource_GetCorrelatedTime(time_source, 0, &clock_time, &systime);
2592 ok(hr == S_OK, "Failed to get time source time, hr %#x.\n", hr);
2593 ok(time == clock_time, "Unexpected clock time.\n");
2595 hr = IMFPresentationClock_GetCorrelatedTime(clock, 0, &time, &systime);
2596 ok(hr == S_OK, "Failed to get clock time, hr %#x.\n", hr);
2597 ok(time == clock_time, "Unexpected clock time.\n");
2599 IMFPresentationTimeSource_Release(time_source);
2601 hr = IMFRateControl_GetRate(rate_control, NULL, &rate);
2602 ok(hr == S_OK, "Failed to get clock rate, hr %#x.\n", hr);
2604 hr = IMFRateControl_GetRate(rate_control, &thin, NULL);
2605 ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
2607 hr = IMFRateControl_GetRate(rate_control, &thin, &rate);
2608 ok(hr == S_OK, "Failed to get clock rate, hr %#x.\n", hr);
2609 ok(rate == 1.0f, "Unexpected rate.\n");
2610 ok(!thin, "Unexpected thinning.\n");
2612 hr = IMFPresentationClock_GetState(clock, 0, &state);
2613 ok(hr == S_OK, "Failed to get clock state, hr %#x.\n", hr);
2614 ok(state == MFCLOCK_STATE_PAUSED, "Unexpected state %d.\n", state);
2616 hr = IMFPresentationClock_Start(clock, 0);
2617 ok(hr == S_OK, "Failed to stop, hr %#x.\n", hr);
2619 hr = IMFRateControl_SetRate(rate_control, FALSE, 0.0f);
2620 ok(hr == S_OK, "Failed to set clock rate, hr %#x.\n", hr);
2621 hr = IMFRateControl_GetRate(rate_control, &thin, &rate);
2622 ok(hr == S_OK, "Failed to get clock rate, hr %#x.\n", hr);
2623 ok(rate == 0.0f, "Unexpected rate.\n");
2624 hr = IMFRateControl_SetRate(rate_control, FALSE, 1.0f);
2625 ok(hr == S_OK, "Failed to set clock rate, hr %#x.\n", hr);
2626 hr = IMFRateControl_SetRate(rate_control, FALSE, 0.0f);
2627 ok(hr == S_OK, "Failed to set clock rate, hr %#x.\n", hr);
2628 hr = IMFRateControl_SetRate(rate_control, FALSE, 0.5f);
2629 ok(hr == S_OK, "Failed to set clock rate, hr %#x.\n", hr);
2630 hr = IMFRateControl_SetRate(rate_control, TRUE, -1.0f);
2631 ok(hr == MF_E_THINNING_UNSUPPORTED, "Unexpected hr %#x.\n", hr);
2633 hr = IMFPresentationClock_GetState(clock, 0, &state);
2634 ok(hr == S_OK, "Failed to get clock state, hr %#x.\n", hr);
2635 ok(state == MFCLOCK_STATE_RUNNING, "Unexpected state %d.\n", state);
2637 hr = IMFRateControl_GetRate(rate_control, &thin, &rate);
2638 ok(hr == S_OK, "Failed to get clock rate, hr %#x.\n", hr);
2639 ok(rate == 0.5f, "Unexpected rate.\n");
2640 ok(!thin, "Unexpected thinning.\n");
2642 IMFRateControl_Release(rate_control);
2644 hr = IMFPresentationClock_QueryInterface(clock, &IID_IMFShutdown, (void **)&shutdown);
2645 ok(hr == S_OK, "Failed to get shutdown interface, hr %#x.\n", hr);
2647 /* Shutdown behavior. */
2648 hr = IMFShutdown_GetShutdownStatus(shutdown, NULL);
2649 ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
2651 hr = IMFShutdown_GetShutdownStatus(shutdown, &status);
2652 ok(hr == MF_E_INVALIDREQUEST, "Unexpected hr %#x.\n", hr);
2654 hr = IMFShutdown_Shutdown(shutdown);
2655 ok(hr == S_OK, "Failed to shut down, hr %#x.\n", hr);
2657 time_source = NULL;
2658 hr = IMFPresentationClock_GetTimeSource(clock, &time_source);
2659 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2660 ok(!!time_source, "Unexpected instance %p.\n", time_source);
2661 IMFPresentationTimeSource_Release(time_source);
2663 hr = IMFPresentationClock_GetTime(clock, &time);
2664 ok(hr == S_OK, "Failed to get time, hr %#x.\n", hr);
2666 hr = IMFShutdown_GetShutdownStatus(shutdown, &status);
2667 ok(hr == S_OK, "Failed to get status, hr %#x.\n", hr);
2668 ok(status == MFSHUTDOWN_COMPLETED, "Unexpected status.\n");
2670 hr = IMFPresentationClock_Start(clock, 0);
2671 ok(hr == S_OK, "Failed to start the clock, hr %#x.\n", hr);
2673 hr = IMFShutdown_GetShutdownStatus(shutdown, &status);
2674 ok(hr == S_OK, "Failed to get status, hr %#x.\n", hr);
2675 ok(status == MFSHUTDOWN_COMPLETED, "Unexpected status.\n");
2677 hr = IMFShutdown_Shutdown(shutdown);
2678 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2680 IMFShutdown_Release(shutdown);
2682 IMFPresentationClock_Release(clock);
2684 hr = MFShutdown();
2685 ok(hr == S_OK, "Failed to shut down, hr %#x.\n", hr);
2688 static HRESULT WINAPI grabber_callback_QueryInterface(IMFSampleGrabberSinkCallback *iface, REFIID riid, void **obj)
2690 if (IsEqualIID(riid, &IID_IMFSampleGrabberSinkCallback) ||
2691 IsEqualIID(riid, &IID_IMFClockStateSink) ||
2692 IsEqualIID(riid, &IID_IUnknown))
2694 *obj = iface;
2695 IMFSampleGrabberSinkCallback_AddRef(iface);
2696 return S_OK;
2699 *obj = NULL;
2700 return E_NOINTERFACE;
2703 static ULONG WINAPI grabber_callback_AddRef(IMFSampleGrabberSinkCallback *iface)
2705 return 2;
2708 static ULONG WINAPI grabber_callback_Release(IMFSampleGrabberSinkCallback *iface)
2710 return 1;
2713 static HRESULT WINAPI grabber_callback_OnClockStart(IMFSampleGrabberSinkCallback *iface, MFTIME time, LONGLONG offset)
2715 return E_NOTIMPL;
2718 static HRESULT WINAPI grabber_callback_OnClockStop(IMFSampleGrabberSinkCallback *iface, MFTIME time)
2720 return E_NOTIMPL;
2723 static HRESULT WINAPI grabber_callback_OnClockPause(IMFSampleGrabberSinkCallback *iface, MFTIME time)
2725 return E_NOTIMPL;
2728 static HRESULT WINAPI grabber_callback_OnClockRestart(IMFSampleGrabberSinkCallback *iface, MFTIME time)
2730 return E_NOTIMPL;
2733 static HRESULT WINAPI grabber_callback_OnClockSetRate(IMFSampleGrabberSinkCallback *iface, MFTIME time, float rate)
2735 return E_NOTIMPL;
2738 static HRESULT WINAPI grabber_callback_OnSetPresentationClock(IMFSampleGrabberSinkCallback *iface,
2739 IMFPresentationClock *clock)
2741 return S_OK;
2744 static HRESULT WINAPI grabber_callback_OnProcessSample(IMFSampleGrabberSinkCallback *iface, REFGUID major_type,
2745 DWORD sample_flags, LONGLONG sample_time, LONGLONG sample_duration, const BYTE *buffer, DWORD sample_size)
2747 return E_NOTIMPL;
2750 static HRESULT WINAPI grabber_callback_OnShutdown(IMFSampleGrabberSinkCallback *iface)
2752 return S_OK;
2755 static const IMFSampleGrabberSinkCallbackVtbl grabber_callback_vtbl =
2757 grabber_callback_QueryInterface,
2758 grabber_callback_AddRef,
2759 grabber_callback_Release,
2760 grabber_callback_OnClockStart,
2761 grabber_callback_OnClockStop,
2762 grabber_callback_OnClockPause,
2763 grabber_callback_OnClockRestart,
2764 grabber_callback_OnClockSetRate,
2765 grabber_callback_OnSetPresentationClock,
2766 grabber_callback_OnProcessSample,
2767 grabber_callback_OnShutdown,
2770 static IMFSampleGrabberSinkCallback grabber_callback = { &grabber_callback_vtbl };
2772 static void test_sample_grabber(void)
2774 IMFMediaType *media_type, *media_type2, *media_type3;
2775 IMFMediaTypeHandler *handler, *handler2;
2776 IMFPresentationTimeSource *time_source;
2777 IMFPresentationClock *clock, *clock2;
2778 IMFStreamSink *stream, *stream2;
2779 IMFRateSupport *rate_support;
2780 IMFMediaEventGenerator *eg;
2781 IMFMediaSink *sink, *sink2;
2782 DWORD flags, count, id;
2783 IMFActivate *activate;
2784 IMFMediaEvent *event;
2785 ULONG refcount;
2786 IUnknown *unk;
2787 float rate;
2788 HRESULT hr;
2789 GUID guid;
2791 hr = MFStartup(MF_VERSION, MFSTARTUP_FULL);
2792 ok(hr == S_OK, "Failed to start up, hr %#x.\n", hr);
2794 hr = MFCreateMediaType(&media_type);
2795 ok(hr == S_OK, "Failed to create media type, hr %#x.\n", hr);
2797 hr = MFCreateSampleGrabberSinkActivate(NULL, NULL, &activate);
2798 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
2800 hr = MFCreateSampleGrabberSinkActivate(NULL, &grabber_callback, &activate);
2801 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
2803 hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio);
2804 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
2805 hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFAudioFormat_PCM);
2806 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
2808 EXPECT_REF(media_type, 1);
2809 hr = MFCreateSampleGrabberSinkActivate(media_type, &grabber_callback, &activate);
2810 ok(hr == S_OK, "Failed to create grabber activate, hr %#x.\n", hr);
2811 EXPECT_REF(media_type, 2);
2813 hr = IMFActivate_GetCount(activate, &count);
2814 ok(hr == S_OK, "Failed to get attribute count, hr %#x.\n", hr);
2815 ok(!count, "Unexpected count %u.\n", count);
2817 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink);
2818 ok(hr == S_OK, "Failed to activate object, hr %#x.\n", hr);
2820 check_interface(sink, &IID_IMFClockStateSink, TRUE);
2821 check_interface(sink, &IID_IMFMediaEventGenerator, TRUE);
2822 check_interface(sink, &IID_IMFGetService, TRUE);
2823 check_interface(sink, &IID_IMFRateSupport, TRUE);
2824 check_service_interface(sink, &MF_RATE_CONTROL_SERVICE, &IID_IMFRateSupport, TRUE);
2826 if (SUCCEEDED(MFGetService((IUnknown *)sink, &MF_RATE_CONTROL_SERVICE, &IID_IMFRateSupport, (void **)&rate_support)))
2828 hr = IMFRateSupport_GetFastestRate(rate_support, MFRATE_FORWARD, FALSE, &rate);
2829 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2830 ok(rate == FLT_MAX, "Unexpected rate %f.\n", rate);
2832 hr = IMFRateSupport_GetFastestRate(rate_support, MFRATE_FORWARD, TRUE, &rate);
2833 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2834 ok(rate == FLT_MAX, "Unexpected rate %f.\n", rate);
2836 hr = IMFRateSupport_GetFastestRate(rate_support, MFRATE_REVERSE, FALSE, &rate);
2837 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2838 ok(rate == -FLT_MAX, "Unexpected rate %f.\n", rate);
2840 hr = IMFRateSupport_GetFastestRate(rate_support, MFRATE_REVERSE, TRUE, &rate);
2841 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2842 ok(rate == -FLT_MAX, "Unexpected rate %f.\n", rate);
2844 hr = IMFRateSupport_GetSlowestRate(rate_support, MFRATE_FORWARD, FALSE, &rate);
2845 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2846 ok(rate == 0.0f, "Unexpected rate %f.\n", rate);
2848 hr = IMFRateSupport_GetSlowestRate(rate_support, MFRATE_FORWARD, TRUE, &rate);
2849 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2850 ok(rate == 0.0f, "Unexpected rate %f.\n", rate);
2852 hr = IMFRateSupport_GetSlowestRate(rate_support, MFRATE_REVERSE, FALSE, &rate);
2853 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2854 ok(rate == 0.0f, "Unexpected rate %f.\n", rate);
2856 hr = IMFRateSupport_GetSlowestRate(rate_support, MFRATE_REVERSE, TRUE, &rate);
2857 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2858 ok(rate == 0.0f, "Unexpected rate %f.\n", rate);
2860 hr = IMFRateSupport_IsRateSupported(rate_support, TRUE, 1.0f, &rate);
2861 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2862 ok(rate == 1.0f, "Unexpected rate %f.\n", rate);
2864 IMFRateSupport_Release(rate_support);
2867 hr = IMFMediaSink_GetCharacteristics(sink, &flags);
2868 ok(hr == S_OK, "Failed to get sink flags, hr %#x.\n", hr);
2869 ok(flags & MEDIASINK_FIXED_STREAMS, "Unexpected flags %#x.\n", flags);
2871 hr = IMFMediaSink_GetStreamSinkCount(sink, &count);
2872 ok(hr == S_OK, "Failed to get stream count, hr %#x.\n", hr);
2873 ok(count == 1, "Unexpected stream count %u.\n", count);
2875 hr = IMFMediaSink_GetStreamSinkByIndex(sink, 0, &stream);
2876 ok(hr == S_OK, "Failed to get sink stream, hr %#x.\n", hr);
2878 check_interface(stream, &IID_IMFMediaEventGenerator, TRUE);
2879 check_interface(stream, &IID_IMFMediaTypeHandler, TRUE);
2881 hr = IMFStreamSink_GetIdentifier(stream, &id);
2882 ok(hr == S_OK, "Failed to get stream id, hr %#x.\n", hr);
2883 ok(id == 0, "Unexpected id %#x.\n", id);
2885 hr = IMFStreamSink_GetMediaSink(stream, &sink2);
2886 ok(hr == S_OK, "Failed to get media sink, hr %x.\n", hr);
2887 ok(sink2 == sink, "Unexpected sink.\n");
2888 IMFMediaSink_Release(sink2);
2890 hr = IMFMediaSink_GetStreamSinkByIndex(sink, 1, &stream2);
2891 ok(hr == MF_E_INVALIDINDEX, "Unexpected hr %#x.\n", hr);
2893 hr = IMFMediaSink_GetStreamSinkById(sink, 1, &stream2);
2894 ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#x.\n", hr);
2896 hr = IMFMediaSink_AddStreamSink(sink, 1, NULL, &stream2);
2897 ok(hr == MF_E_STREAMSINKS_FIXED, "Unexpected hr %#x.\n", hr);
2899 hr = IMFMediaSink_RemoveStreamSink(sink, 0);
2900 ok(hr == MF_E_STREAMSINKS_FIXED, "Unexpected hr %#x.\n", hr);
2902 hr = IMFMediaSink_RemoveStreamSink(sink, 1);
2903 ok(hr == MF_E_STREAMSINKS_FIXED, "Unexpected hr %#x.\n", hr);
2905 check_interface(sink, &IID_IMFClockStateSink, TRUE);
2907 /* Event generator. */
2908 hr = IMFMediaSink_QueryInterface(sink, &IID_IMFMediaEventGenerator, (void **)&eg);
2909 ok(hr == S_OK, "Failed to get interface, hr %#x.\n", hr);
2911 hr = IMFMediaEventGenerator_GetEvent(eg, MF_EVENT_FLAG_NO_WAIT, &event);
2912 ok(hr == MF_E_NO_EVENTS_AVAILABLE, "Unexpected hr %#x.\n", hr);
2914 hr = IMFMediaSink_QueryInterface(sink, &IID_IMFPresentationTimeSource, (void **)&unk);
2915 ok(hr == E_NOINTERFACE, "Unexpected hr %#x.\n", hr);
2917 hr = IMFStreamSink_QueryInterface(stream, &IID_IMFMediaTypeHandler, (void **)&handler2);
2918 ok(hr == S_OK, "Failed to get handler interface, hr %#x.\n", hr);
2920 hr = IMFStreamSink_GetMediaTypeHandler(stream, &handler);
2921 ok(hr == S_OK, "Failed to get type handler, hr %#x.\n", hr);
2922 hr = IMFMediaTypeHandler_GetMediaTypeCount(handler, &count);
2923 ok(hr == S_OK, "Failed to get media type count, hr %#x.\n", hr);
2924 ok(count == 0, "Unexpected count %u.\n", count);
2925 ok(handler == handler2, "Unexpected handler.\n");
2927 IMFMediaTypeHandler_Release(handler);
2928 IMFMediaTypeHandler_Release(handler2);
2930 /* Set clock. */
2931 hr = MFCreatePresentationClock(&clock);
2932 ok(hr == S_OK, "Failed to create clock object, hr %#x.\n", hr);
2934 hr = IMFMediaSink_GetPresentationClock(sink, NULL);
2935 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
2937 hr = IMFMediaSink_GetPresentationClock(sink, &clock2);
2938 ok(hr == MF_E_NO_CLOCK, "Unexpected hr %#x.\n", hr);
2940 hr = IMFMediaSink_SetPresentationClock(sink, NULL);
2941 ok(hr == S_OK, "Failed to set presentation clock, hr %#x.\n", hr);
2943 hr = IMFMediaSink_SetPresentationClock(sink, clock);
2944 ok(hr == S_OK, "Failed to set presentation clock, hr %#x.\n", hr);
2946 hr = MFCreateSystemTimeSource(&time_source);
2947 ok(hr == S_OK, "Failed to create time source, hr %#x.\n", hr);
2949 hr = IMFPresentationClock_SetTimeSource(clock, time_source);
2950 ok(hr == S_OK, "Failed to set time source, hr %#x.\n", hr);
2951 IMFPresentationTimeSource_Release(time_source);
2953 hr = IMFMediaSink_GetCharacteristics(sink, &flags);
2954 ok(hr == S_OK, "Failed to get sink flags, hr %#x.\n", hr);
2956 hr = IMFActivate_ShutdownObject(activate);
2957 ok(hr == S_OK, "Failed to shut down, hr %#x.\n", hr);
2959 hr = IMFMediaSink_GetCharacteristics(sink, &flags);
2960 ok(hr == S_OK, "Failed to get sink flags, hr %#x.\n", hr);
2962 hr = IMFStreamSink_GetMediaTypeHandler(stream, &handler);
2963 ok(hr == S_OK, "Failed to get type handler, hr %#x.\n", hr);
2965 /* On Win8+ this initialization happens automatically. */
2966 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, media_type);
2967 ok(hr == S_OK, "Failed to set media type, hr %#x.\n", hr);
2969 hr = IMFMediaTypeHandler_GetMediaTypeCount(handler, NULL);
2970 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
2972 hr = IMFMediaTypeHandler_GetMediaTypeCount(handler, &count);
2973 ok(hr == S_OK, "Failed to get media type count, hr %#x.\n", hr);
2974 ok(count == 0, "Unexpected count %u.\n", count);
2976 hr = IMFMediaTypeHandler_GetMajorType(handler, &guid);
2977 ok(hr == S_OK, "Failed to get major type, hr %#x.\n", hr);
2978 ok(IsEqualGUID(&guid, &MFMediaType_Audio), "Unexpected major type %s.\n", wine_dbgstr_guid(&guid));
2980 hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, &media_type2);
2981 ok(hr == S_OK, "Failed to get current type, hr %#x.\n", hr);
2982 ok(media_type2 == media_type, "Unexpected media type.\n");
2983 IMFMediaType_Release(media_type2);
2985 hr = MFCreateMediaType(&media_type2);
2986 ok(hr == S_OK, "Failed to create media type, 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_MAJOR_TYPE, &MFMediaType_Audio);
2992 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
2994 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, media_type2);
2995 ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#x.\n", hr);
2997 hr = IMFMediaType_SetGUID(media_type2, &MF_MT_SUBTYPE, &MFAudioFormat_Float);
2998 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
3000 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, media_type2);
3001 ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#x.\n", hr);
3003 hr = IMFMediaType_SetGUID(media_type2, &MF_MT_SUBTYPE, &MFAudioFormat_PCM);
3004 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
3006 hr = IMFMediaType_SetUINT32(media_type2, &MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100);
3007 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
3009 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, media_type2);
3010 ok(hr == S_OK, "Failed to get current type, hr %#x.\n", hr);
3011 IMFMediaType_Release(media_type);
3013 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, NULL);
3014 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
3016 hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, &media_type);
3017 ok(hr == S_OK, "Failed to get current type, hr %#x.\n", hr);
3018 ok(media_type2 == media_type, "Unexpected media type.\n");
3019 IMFMediaType_Release(media_type);
3021 hr = IMFMediaTypeHandler_GetMediaTypeByIndex(handler, 0, &media_type);
3022 ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#x.\n", hr);
3024 hr = IMFMediaTypeHandler_GetMediaTypeByIndex(handler, 0, NULL);
3025 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
3027 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type2, NULL);
3028 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
3030 hr = MFCreateMediaType(&media_type);
3031 ok(hr == S_OK, "Failed to create media type, hr %#x.\n", hr);
3033 hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio);
3034 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
3036 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type, NULL);
3037 ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#x.\n", hr);
3039 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type, &media_type3);
3040 ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#x.\n", hr);
3042 hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFAudioFormat_PCM);
3043 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
3045 media_type3 = (void *)0xdeadbeef;
3046 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type, &media_type3);
3047 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
3048 ok(media_type3 == (void *)0xdeadbeef, "Unexpected media type %p.\n", media_type3);
3050 hr = IMFMediaType_SetUINT32(media_type, &MF_MT_FIXED_SIZE_SAMPLES, 1);
3051 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
3053 hr = IMFMediaType_SetUINT32(media_type, &MF_MT_SAMPLE_SIZE, 1024);
3054 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
3056 media_type3 = (void *)0xdeadbeef;
3057 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type, &media_type3);
3058 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
3059 ok(media_type3 == (void *)0xdeadbeef, "Unexpected media type %p.\n", media_type3);
3061 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, NULL, NULL);
3062 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
3064 hr = IMFMediaEventGenerator_GetEvent(eg, MF_EVENT_FLAG_NO_WAIT, &event);
3065 ok(hr == MF_E_NO_EVENTS_AVAILABLE, "Unexpected hr %#x.\n", hr);
3067 hr = IMFStreamSink_GetEvent(stream, MF_EVENT_FLAG_NO_WAIT, &event);
3068 ok(hr == MF_E_NO_EVENTS_AVAILABLE, "Unexpected hr %#x.\n", hr);
3070 EXPECT_REF(clock, 3);
3071 hr = IMFMediaSink_Shutdown(sink);
3072 ok(hr == S_OK, "Failed to shut down, hr %#x.\n", hr);
3073 EXPECT_REF(clock, 1);
3075 hr = IMFMediaEventGenerator_GetEvent(eg, MF_EVENT_FLAG_NO_WAIT, &event);
3076 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr);
3078 hr = IMFMediaSink_Shutdown(sink);
3079 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr);
3081 hr = IMFMediaSink_GetCharacteristics(sink, &flags);
3082 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr);
3084 hr = IMFMediaSink_AddStreamSink(sink, 1, NULL, &stream2);
3085 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr);
3087 hr = IMFMediaSink_GetStreamSinkCount(sink, &count);
3088 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr);
3090 hr = IMFMediaSink_GetStreamSinkByIndex(sink, 0, &stream2);
3091 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr);
3093 hr = IMFStreamSink_GetEvent(stream, MF_EVENT_FLAG_NO_WAIT, &event);
3094 ok(hr == MF_E_STREAMSINK_REMOVED, "Unexpected hr %#x.\n", hr);
3096 hr = IMFStreamSink_GetMediaSink(stream, &sink2);
3097 ok(hr == MF_E_STREAMSINK_REMOVED, "Unexpected hr %#x.\n", hr);
3099 id = 1;
3100 hr = IMFStreamSink_GetIdentifier(stream, &id);
3101 ok(hr == MF_E_STREAMSINK_REMOVED, "Unexpected hr %#x.\n", hr);
3102 ok(id == 1, "Unexpected id %u.\n", id);
3104 media_type3 = (void *)0xdeadbeef;
3105 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type, &media_type3);
3106 ok(hr == MF_E_STREAMSINK_REMOVED, "Unexpected hr %#x.\n", hr);
3107 ok(media_type3 == (void *)0xdeadbeef, "Unexpected media type %p.\n", media_type3);
3109 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, NULL, NULL);
3110 ok(hr == MF_E_STREAMSINK_REMOVED, "Unexpected hr %#x.\n", hr);
3112 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, NULL);
3113 ok(hr == MF_E_STREAMSINK_REMOVED, "Unexpected hr %#x.\n", hr);
3115 hr = IMFMediaTypeHandler_GetMediaTypeCount(handler, &count);
3116 ok(hr == S_OK, "Failed to get type count, hr %#x.\n", hr);
3118 IMFMediaType_Release(media_type2);
3119 IMFMediaType_Release(media_type);
3121 hr = IMFMediaTypeHandler_GetMediaTypeByIndex(handler, 0, &media_type);
3122 ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#x.\n", hr);
3124 hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, &media_type);
3125 ok(hr == MF_E_STREAMSINK_REMOVED, "Unexpected hr %#x.\n", hr);
3127 hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, NULL);
3128 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
3130 hr = IMFMediaTypeHandler_GetMajorType(handler, NULL);
3131 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
3133 hr = IMFMediaTypeHandler_GetMajorType(handler, &guid);
3134 ok(hr == MF_E_STREAMSINK_REMOVED, "Unexpected hr %#x.\n", hr);
3136 IMFMediaTypeHandler_Release(handler);
3138 handler = (void *)0xdeadbeef;
3139 hr = IMFStreamSink_GetMediaTypeHandler(stream, &handler);
3140 ok(hr == MF_E_STREAMSINK_REMOVED, "Unexpected hr %#x.\n", hr);
3141 ok(handler == (void *)0xdeadbeef, "Unexpected pointer.\n");
3143 hr = IMFStreamSink_GetMediaTypeHandler(stream, NULL);
3144 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
3146 IMFMediaEventGenerator_Release(eg);
3147 IMFMediaSink_Release(sink);
3148 IMFStreamSink_Release(stream);
3150 refcount = IMFActivate_Release(activate);
3151 ok(!refcount, "Unexpected refcount %u.\n", refcount);
3153 /* Rateless mode with MF_SAMPLEGRABBERSINK_IGNORE_CLOCK. */
3154 hr = MFCreateMediaType(&media_type);
3155 ok(hr == S_OK, "Failed to create media type, hr %#x.\n", hr);
3157 hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio);
3158 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
3159 hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFAudioFormat_PCM);
3160 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
3162 hr = MFCreateSampleGrabberSinkActivate(media_type, &grabber_callback, &activate);
3163 ok(hr == S_OK, "Failed to create grabber activate, hr %#x.\n", hr);
3165 hr = IMFActivate_SetUINT32(activate, &MF_SAMPLEGRABBERSINK_IGNORE_CLOCK, 1);
3166 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
3168 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink);
3169 ok(hr == S_OK, "Failed to activate object, hr %#x.\n", hr);
3171 hr = IMFMediaSink_GetCharacteristics(sink, &flags);
3172 ok(hr == S_OK, "Failed to get sink flags, hr %#x.\n", hr);
3173 ok(flags & MEDIASINK_RATELESS, "Unexpected flags %#x.\n", flags);
3175 hr = IMFActivate_ShutdownObject(activate);
3176 ok(hr == S_OK, "Failed to shut down, hr %#x.\n", hr);
3178 hr = IMFMediaSink_Shutdown(sink);
3179 ok(hr == S_OK, "Failed to shut down, hr %#x.\n", hr);
3181 IMFMediaSink_Release(sink);
3183 /* Detaching */
3184 hr = MFCreateSampleGrabberSinkActivate(media_type, &grabber_callback, &activate);
3185 ok(hr == S_OK, "Failed to create grabber activate, hr %#x.\n", hr);
3187 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink);
3188 ok(hr == S_OK, "Failed to activate object, hr %#x.\n", hr);
3189 IMFMediaSink_Release(sink);
3191 hr = IMFActivate_ShutdownObject(activate);
3192 ok(hr == S_OK, "Failed to shut down, hr %#x.\n", hr);
3194 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink);
3195 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr);
3197 hr = IMFActivate_GetCount(activate, &count);
3198 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
3200 hr = IMFActivate_DetachObject(activate);
3201 ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
3203 IMFActivate_Release(activate);
3205 IMFMediaType_Release(media_type);
3206 IMFPresentationClock_Release(clock);
3208 hr = MFShutdown();
3209 ok(hr == S_OK, "Failed to shut down, hr %#x.\n", hr);
3212 static void test_sample_grabber_is_mediatype_supported(void)
3214 IMFMediaType *media_type, *media_type2, *media_type3;
3215 IMFMediaTypeHandler *handler;
3216 IMFActivate *activate;
3217 IMFStreamSink *stream;
3218 IMFMediaSink *sink;
3219 ULONG refcount;
3220 HRESULT hr;
3221 GUID guid;
3223 /* IsMediaTypeSupported checks are done against the creation type, and check format data */
3224 hr = MFCreateMediaType(&media_type);
3225 ok(hr == S_OK, "Failed to create media type, hr %#x.\n", hr);
3227 hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio);
3228 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
3229 hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFAudioFormat_PCM);
3230 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
3231 hr = IMFMediaType_SetUINT32(media_type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100);
3232 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
3234 hr = MFCreateSampleGrabberSinkActivate(media_type, &grabber_callback, &activate);
3235 ok(hr == S_OK, "Failed to create grabber activate, hr %#x.\n", hr);
3237 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink);
3238 ok(hr == S_OK, "Failed to activate object, hr %#x.\n", hr);
3240 hr = IMFMediaSink_GetStreamSinkByIndex(sink, 0, &stream);
3241 ok(hr == S_OK, "Failed to get sink stream, hr %#x.\n", hr);
3242 hr = IMFStreamSink_GetMediaTypeHandler(stream, &handler);
3243 ok(hr == S_OK, "Failed to get type handler, hr %#x.\n", hr);
3244 IMFStreamSink_Release(stream);
3246 IMFMediaSink_Release(sink);
3248 /* On Win8+ this initialization happens automatically. */
3249 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, media_type);
3250 ok(hr == S_OK, "Failed to set media type, hr %#x.\n", hr);
3252 hr = MFCreateMediaType(&media_type2);
3253 ok(hr == S_OK, "Failed to create media type, hr %#x.\n", hr);
3255 hr = IMFMediaType_SetGUID(media_type2, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio);
3256 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
3257 hr = IMFMediaType_SetGUID(media_type2, &MF_MT_SUBTYPE, &MFAudioFormat_PCM);
3258 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
3259 hr = IMFMediaType_SetUINT32(media_type2, &MF_MT_AUDIO_SAMPLES_PER_SECOND, 48000);
3260 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
3262 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type2, NULL);
3263 ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#x.\n", hr);
3265 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, media_type2);
3266 ok(hr == MF_E_INVALIDMEDIATYPE, "Failed to set media type, hr %#x.\n", hr);
3268 /* Make it match grabber type sample rate. */
3269 hr = IMFMediaType_SetUINT32(media_type2, &MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100);
3270 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
3272 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type2, NULL);
3273 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
3275 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, media_type2);
3276 ok(hr == S_OK, "Failed to set media type, hr %#x.\n", hr);
3277 hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, &media_type3);
3278 ok(hr == S_OK, "Failed to set media type, hr %#x.\n", hr);
3279 ok(media_type3 == media_type2, "Unexpected media type instance.\n");
3280 IMFMediaType_Release(media_type3);
3282 /* Change original type. */
3283 hr = IMFMediaType_SetUINT32(media_type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, 48000);
3284 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
3286 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type2, NULL);
3287 ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#x.\n", hr);
3289 hr = IMFMediaType_SetUINT32(media_type2, &MF_MT_AUDIO_SAMPLES_PER_SECOND, 48000);
3290 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
3292 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type2, NULL);
3293 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
3295 hr = IMFMediaTypeHandler_GetMajorType(handler, &guid);
3296 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
3297 ok(IsEqualGUID(&guid, &MFMediaType_Audio), "Unexpected major type.\n");
3299 hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
3300 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
3302 hr = IMFMediaTypeHandler_GetMajorType(handler, &guid);
3303 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
3304 ok(IsEqualGUID(&guid, &MFMediaType_Audio), "Unexpected major type.\n");
3306 IMFMediaType_Release(media_type2);
3307 IMFMediaType_Release(media_type);
3309 IMFMediaTypeHandler_Release(handler);
3311 refcount = IMFActivate_Release(activate);
3312 ok(!refcount, "Unexpected refcount %u.\n", refcount);
3315 static BOOL is_supported_video_type(const GUID *guid)
3317 return IsEqualGUID(guid, &MFVideoFormat_L8)
3318 || IsEqualGUID(guid, &MFVideoFormat_L16)
3319 || IsEqualGUID(guid, &MFVideoFormat_D16)
3320 || IsEqualGUID(guid, &MFVideoFormat_IYUV)
3321 || IsEqualGUID(guid, &MFVideoFormat_YV12)
3322 || IsEqualGUID(guid, &MFVideoFormat_NV12)
3323 || IsEqualGUID(guid, &MFVideoFormat_420O)
3324 || IsEqualGUID(guid, &MFVideoFormat_P010)
3325 || IsEqualGUID(guid, &MFVideoFormat_P016)
3326 || IsEqualGUID(guid, &MFVideoFormat_UYVY)
3327 || IsEqualGUID(guid, &MFVideoFormat_YUY2)
3328 || IsEqualGUID(guid, &MFVideoFormat_P208)
3329 || IsEqualGUID(guid, &MFVideoFormat_NV11)
3330 || IsEqualGUID(guid, &MFVideoFormat_AYUV)
3331 || IsEqualGUID(guid, &MFVideoFormat_ARGB32)
3332 || IsEqualGUID(guid, &MFVideoFormat_RGB32)
3333 || IsEqualGUID(guid, &MFVideoFormat_A2R10G10B10)
3334 || IsEqualGUID(guid, &MFVideoFormat_A16B16G16R16F)
3335 || IsEqualGUID(guid, &MFVideoFormat_RGB24)
3336 || IsEqualGUID(guid, &MFVideoFormat_I420)
3337 || IsEqualGUID(guid, &MFVideoFormat_YVYU)
3338 || IsEqualGUID(guid, &MFVideoFormat_RGB555)
3339 || IsEqualGUID(guid, &MFVideoFormat_RGB565)
3340 || IsEqualGUID(guid, &MFVideoFormat_RGB8)
3341 || IsEqualGUID(guid, &MFVideoFormat_Y216)
3342 || IsEqualGUID(guid, &MFVideoFormat_v410)
3343 || IsEqualGUID(guid, &MFVideoFormat_Y41P)
3344 || IsEqualGUID(guid, &MFVideoFormat_Y41T)
3345 || IsEqualGUID(guid, &MFVideoFormat_Y42T)
3346 || IsEqualGUID(guid, &MFVideoFormat_ABGR32);
3349 static void test_video_processor(void)
3351 DWORD input_count, output_count, input_id, output_id, flags;
3352 DWORD input_min, input_max, output_min, output_max, i, count;
3353 IMFAttributes *attributes, *attributes2;
3354 IMFMediaType *media_type, *media_type2;
3355 MFT_OUTPUT_DATA_BUFFER output_buffer;
3356 MFT_OUTPUT_STREAM_INFO output_info;
3357 MFT_INPUT_STREAM_INFO input_info;
3358 IMFSample *sample, *sample2;
3359 IMFTransform *transform;
3360 IMFMediaBuffer *buffer;
3361 IMFMediaEvent *event;
3362 unsigned int value;
3363 HRESULT hr;
3364 GUID guid;
3366 hr = CoInitialize(NULL);
3367 ok(hr == S_OK, "Failed to initialize, hr %#x.\n", hr);
3369 hr = CoCreateInstance(&CLSID_VideoProcessorMFT, NULL, CLSCTX_INPROC_SERVER, &IID_IMFTransform,
3370 (void **)&transform);
3371 if (FAILED(hr))
3373 skip("Failed to create Video Processor instance, skipping tests.\n");
3374 goto failed;
3377 todo_wine
3378 check_interface(transform, &IID_IMFVideoProcessorControl, TRUE);
3379 todo_wine
3380 check_interface(transform, &IID_IMFRealTimeClientEx, TRUE);
3381 check_interface(transform, &IID_IMFMediaEventGenerator, FALSE);
3382 check_interface(transform, &IID_IMFShutdown, FALSE);
3384 /* Transform global attributes. */
3385 hr = IMFTransform_GetAttributes(transform, &attributes);
3386 ok(hr == S_OK, "Failed to get attributes, hr %#x.\n", hr);
3388 hr = IMFAttributes_GetCount(attributes, &count);
3389 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
3390 todo_wine
3391 ok(!!count, "Unexpected attribute count %u.\n", count);
3393 value = 0;
3394 hr = IMFAttributes_GetUINT32(attributes, &MF_SA_D3D11_AWARE, &value);
3395 todo_wine {
3396 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
3397 ok(value == 1, "Unexpected attribute value %u.\n", value);
3399 hr = IMFTransform_GetAttributes(transform, &attributes2);
3400 ok(hr == S_OK, "Failed to get attributes, hr %#x.\n", hr);
3401 ok(attributes == attributes2, "Unexpected instance.\n");
3402 IMFAttributes_Release(attributes);
3403 IMFAttributes_Release(attributes2);
3405 hr = IMFTransform_GetStreamLimits(transform, &input_min, &input_max, &output_min, &output_max);
3406 ok(hr == S_OK, "Failed to get stream limits, hr %#x.\n", hr);
3407 ok(input_min == input_max && input_min == 1 && output_min == output_max && output_min == 1,
3408 "Unexpected stream limits.\n");
3410 hr = IMFTransform_GetStreamCount(transform, &input_count, &output_count);
3411 ok(hr == S_OK, "Failed to get stream count, hr %#x.\n", hr);
3412 ok(input_count == 1 && output_count == 1, "Unexpected stream count %u, %u.\n", input_count, output_count);
3414 hr = IMFTransform_GetStreamIDs(transform, 1, &input_id, 1, &output_id);
3415 ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
3417 input_id = 100;
3418 hr = IMFTransform_AddInputStreams(transform, 1, &input_id);
3419 ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
3421 hr = IMFTransform_DeleteInputStream(transform, 0);
3422 ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
3424 hr = IMFTransform_GetInputStatus(transform, 0, &flags);
3425 todo_wine
3426 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#x.\n", hr);
3428 hr = IMFTransform_GetInputStreamAttributes(transform, 0, &attributes);
3429 ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
3431 hr = IMFTransform_GetOutputStatus(transform, &flags);
3432 todo_wine
3433 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#x.\n", hr);
3435 hr = IMFTransform_GetOutputStreamAttributes(transform, 0, &attributes);
3436 ok(hr == S_OK, "Failed to get output attributes, hr %#x.\n", hr);
3437 hr = IMFTransform_GetOutputStreamAttributes(transform, 0, &attributes2);
3438 ok(hr == S_OK, "Failed to get output attributes, hr %#x.\n", hr);
3439 ok(attributes == attributes2, "Unexpected instance.\n");
3440 IMFAttributes_Release(attributes);
3441 IMFAttributes_Release(attributes2);
3443 hr = IMFTransform_GetOutputAvailableType(transform, 0, 0, &media_type);
3444 todo_wine
3445 ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#x.\n", hr);
3447 hr = IMFTransform_GetInputCurrentType(transform, 0, &media_type);
3448 todo_wine
3449 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#x.\n", hr);
3451 hr = IMFTransform_GetInputCurrentType(transform, 1, &media_type);
3452 todo_wine
3453 ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#x.\n", hr);
3455 hr = IMFTransform_GetOutputCurrentType(transform, 0, &media_type);
3456 todo_wine
3457 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#x.\n", hr);
3459 hr = IMFTransform_GetOutputCurrentType(transform, 1, &media_type);
3460 todo_wine
3461 ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#x.\n", hr);
3463 hr = IMFTransform_GetInputStreamInfo(transform, 1, &input_info);
3464 todo_wine
3465 ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#x.\n", hr);
3467 memset(&input_info, 0xcc, sizeof(input_info));
3468 hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info);
3469 todo_wine {
3470 ok(hr == S_OK, "Failed to get stream info, hr %#x.\n", hr);
3471 ok(input_info.dwFlags == 0, "Unexpected flag %#x.\n", input_info.dwFlags);
3472 ok(input_info.cbSize == 0, "Unexpected size %u.\n", input_info.cbSize);
3473 ok(input_info.cbMaxLookahead == 0, "Unexpected lookahead length %u.\n", input_info.cbMaxLookahead);
3474 ok(input_info.cbAlignment == 0, "Unexpected alignment %u.\n", input_info.cbAlignment);
3476 hr = MFCreateMediaEvent(MEUnknown, &GUID_NULL, S_OK, NULL, &event);
3477 ok(hr == S_OK, "Failed to create event object, hr %#x.\n", hr);
3478 hr = IMFTransform_ProcessEvent(transform, 0, event);
3479 ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
3480 hr = IMFTransform_ProcessEvent(transform, 1, event);
3481 ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
3482 IMFMediaEvent_Release(event);
3484 /* Configure stream types. */
3485 for (i = 0;;++i)
3487 if (FAILED(hr = IMFTransform_GetInputAvailableType(transform, 0, i, &media_type)))
3489 todo_wine
3490 ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#x.\n", hr);
3491 break;
3494 hr = IMFTransform_GetInputAvailableType(transform, 0, i, &media_type2);
3495 ok(hr == S_OK, "Failed to get available type, hr %#x.\n", hr);
3496 ok(media_type != media_type2, "Unexpected instance.\n");
3497 IMFMediaType_Release(media_type2);
3499 hr = IMFMediaType_GetMajorType(media_type, &guid);
3500 ok(hr == S_OK, "Failed to get major type, hr %#x.\n", hr);
3501 ok(IsEqualGUID(&guid, &MFMediaType_Video), "Unexpected major type.\n");
3503 hr = IMFMediaType_GetCount(media_type, &count);
3504 ok(hr == S_OK, "Failed to get attributes count, hr %#x.\n", hr);
3505 ok(count == 2, "Unexpected count %u.\n", count);
3507 hr = IMFMediaType_GetGUID(media_type, &MF_MT_SUBTYPE, &guid);
3508 ok(hr == S_OK, "Failed to get subtype, hr %#x.\n", hr);
3509 ok(is_supported_video_type(&guid), "Unexpected media type %s.\n", wine_dbgstr_guid(&guid));
3511 hr = IMFTransform_SetInputType(transform, 0, media_type, MFT_SET_TYPE_TEST_ONLY);
3512 ok(FAILED(hr), "Unexpected hr %#x.\n", hr);
3514 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
3515 ok(FAILED(hr), "Unexpected hr %#x.\n", hr);
3517 hr = IMFTransform_GetOutputCurrentType(transform, 0, &media_type2);
3518 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#x.\n", hr);
3520 /* FIXME: figure out if those require additional attributes or simply advertised but not supported */
3521 if (IsEqualGUID(&guid, &MFVideoFormat_L8) || IsEqualGUID(&guid, &MFVideoFormat_L16)
3522 || IsEqualGUID(&guid, &MFVideoFormat_D16) || IsEqualGUID(&guid, &MFVideoFormat_420O)
3523 || IsEqualGUID(&guid, &MFVideoFormat_A16B16G16R16F))
3525 IMFMediaType_Release(media_type);
3526 continue;
3529 hr = IMFMediaType_SetUINT64(media_type, &MF_MT_FRAME_SIZE, ((UINT64)16 << 32) | 16);
3530 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
3532 hr = IMFTransform_SetInputType(transform, 0, media_type, MFT_SET_TYPE_TEST_ONLY);
3533 ok(hr == S_OK, "Failed to test input type %s, hr %#x.\n", wine_dbgstr_guid(&guid), hr);
3535 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
3536 ok(hr == S_OK, "Failed to test input type, hr %#x.\n", hr);
3538 hr = IMFTransform_GetInputCurrentType(transform, 0, &media_type2);
3539 ok(hr == S_OK, "Failed to get current type, hr %#x.\n", hr);
3540 ok(media_type != media_type2, "Unexpected instance.\n");
3541 IMFMediaType_Release(media_type2);
3543 hr = IMFTransform_GetInputStatus(transform, 0, &flags);
3544 ok(hr == S_OK, "Failed to get input status, hr %#x.\n", hr);
3545 ok(flags == MFT_INPUT_STATUS_ACCEPT_DATA, "Unexpected input status %#x.\n", flags);
3547 hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info);
3548 ok(hr == S_OK, "Failed to get stream info, hr %#x.\n", hr);
3549 ok(input_info.dwFlags == 0, "Unexpected flags %#x.\n", input_info.dwFlags);
3550 ok(input_info.cbMaxLookahead == 0, "Unexpected lookahead length %u.\n", input_info.cbMaxLookahead);
3551 ok(input_info.cbAlignment == 0, "Unexpected alignment %u.\n", input_info.cbAlignment);
3553 IMFMediaType_Release(media_type);
3556 /* IYUV -> RGB32 */
3557 hr = MFCreateMediaType(&media_type);
3558 ok(hr == S_OK, "Failed to create media type, hr %#x.\n", hr);
3560 hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
3561 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
3563 hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFVideoFormat_IYUV);
3564 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
3566 hr = IMFMediaType_SetUINT64(media_type, &MF_MT_FRAME_SIZE, ((UINT64)16 << 32) | 16);
3567 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
3569 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
3570 todo_wine
3571 ok(hr == S_OK, "Failed to set input type, hr %#x.\n", hr);
3573 hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFVideoFormat_RGB32);
3574 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
3576 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
3577 todo_wine
3578 ok(hr == S_OK, "Failed to set output type, hr %#x.\n", hr);
3580 memset(&output_info, 0, sizeof(output_info));
3581 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
3582 todo_wine
3583 ok(hr == S_OK, "Failed to get stream info, hr %#x.\n", hr);
3584 ok(output_info.dwFlags == 0, "Unexpected flags %#x.\n", output_info.dwFlags);
3585 todo_wine
3586 ok(output_info.cbSize > 0, "Unexpected size %u.\n", output_info.cbSize);
3587 ok(output_info.cbAlignment == 0, "Unexpected alignment %u.\n", output_info.cbAlignment);
3589 hr = MFCreateSample(&sample);
3590 ok(hr == S_OK, "Failed to create a sample, hr %#x.\n", hr);
3592 hr = MFCreateSample(&sample2);
3593 ok(hr == S_OK, "Failed to create a sample, hr %#x.\n", hr);
3595 memset(&output_buffer, 0, sizeof(output_buffer));
3596 output_buffer.pSample = sample;
3597 flags = 0;
3598 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output_buffer, &flags);
3599 todo_wine
3600 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "Unexpected hr %#x.\n", hr);
3601 ok(output_buffer.dwStatus == 0, "Unexpected buffer status, %#x.\n", output_buffer.dwStatus);
3602 ok(flags == 0, "Unexpected status %#x.\n", flags);
3604 hr = IMFTransform_ProcessInput(transform, 0, sample2, 0);
3605 todo_wine
3606 ok(hr == S_OK, "Failed to push a sample, hr %#x.\n", hr);
3608 hr = IMFTransform_ProcessInput(transform, 0, sample2, 0);
3609 todo_wine
3610 ok(hr == MF_E_NOTACCEPTING, "Unexpected hr %#x.\n", hr);
3612 memset(&output_buffer, 0, sizeof(output_buffer));
3613 output_buffer.pSample = sample;
3614 flags = 0;
3615 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output_buffer, &flags);
3616 todo_wine
3617 ok(hr == MF_E_NO_SAMPLE_TIMESTAMP, "Unexpected hr %#x.\n", hr);
3618 ok(output_buffer.dwStatus == 0, "Unexpected buffer status, %#x.\n", output_buffer.dwStatus);
3619 ok(flags == 0, "Unexpected status %#x.\n", flags);
3621 hr = IMFSample_SetSampleTime(sample2, 0);
3622 ok(hr == S_OK, "Failed to set sample time, hr %#x.\n", hr);
3623 memset(&output_buffer, 0, sizeof(output_buffer));
3624 output_buffer.pSample = sample;
3625 flags = 0;
3626 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output_buffer, &flags);
3627 todo_wine
3628 ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
3629 ok(output_buffer.dwStatus == 0, "Unexpected buffer status, %#x.\n", output_buffer.dwStatus);
3630 ok(flags == 0, "Unexpected status %#x.\n", flags);
3632 hr = MFCreateMemoryBuffer(1024 * 1024, &buffer);
3633 ok(hr == S_OK, "Failed to create a buffer, hr %#x.\n", hr);
3635 hr = IMFSample_AddBuffer(sample2, buffer);
3636 ok(hr == S_OK, "Failed to add a buffer, hr %#x.\n", hr);
3638 hr = IMFSample_AddBuffer(sample, buffer);
3639 ok(hr == S_OK, "Failed to add a buffer, hr %#x.\n", hr);
3641 memset(&output_buffer, 0, sizeof(output_buffer));
3642 output_buffer.pSample = sample;
3643 flags = 0;
3644 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output_buffer, &flags);
3645 todo_wine
3646 ok(hr == S_OK || broken(FAILED(hr)) /* Win8 */, "Failed to get output buffer, hr %#x.\n", hr);
3647 ok(output_buffer.dwStatus == 0, "Unexpected buffer status, %#x.\n", output_buffer.dwStatus);
3648 ok(flags == 0, "Unexpected status %#x.\n", flags);
3650 if (SUCCEEDED(hr))
3652 memset(&output_buffer, 0, sizeof(output_buffer));
3653 output_buffer.pSample = sample;
3654 flags = 0;
3655 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output_buffer, &flags);
3656 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "Unexpected hr %#x.\n", hr);
3657 ok(output_buffer.dwStatus == 0, "Unexpected buffer status, %#x.\n", output_buffer.dwStatus);
3658 ok(flags == 0, "Unexpected status %#x.\n", flags);
3661 IMFSample_Release(sample2);
3662 IMFSample_Release(sample);
3663 IMFMediaBuffer_Release(buffer);
3665 IMFMediaType_Release(media_type);
3667 IMFTransform_Release(transform);
3669 failed:
3670 CoUninitialize();
3673 static void test_quality_manager(void)
3675 IMFPresentationClock *clock;
3676 IMFQualityManager *manager;
3677 IMFTopology *topology;
3678 HRESULT hr;
3680 hr = MFStartup(MF_VERSION, MFSTARTUP_FULL);
3681 ok(hr == S_OK, "Startup failure, hr %#x.\n", hr);
3683 hr = MFCreatePresentationClock(&clock);
3684 ok(hr == S_OK, "Failed to create presentation clock, hr %#x.\n", hr);
3686 hr = MFCreateStandardQualityManager(&manager);
3687 ok(hr == S_OK, "Failed to create quality manager, hr %#x.\n", hr);
3689 check_interface(manager, &IID_IMFQualityManager, TRUE);
3690 check_interface(manager, &IID_IMFClockStateSink, TRUE);
3692 hr = IMFQualityManager_NotifyPresentationClock(manager, NULL);
3693 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
3695 hr = IMFQualityManager_NotifyTopology(manager, NULL);
3696 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
3698 /* Set clock, then shutdown. */
3699 EXPECT_REF(clock, 1);
3700 EXPECT_REF(manager, 1);
3701 hr = IMFQualityManager_NotifyPresentationClock(manager, clock);
3702 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
3703 EXPECT_REF(clock, 2);
3704 EXPECT_REF(manager, 2);
3706 hr = IMFQualityManager_Shutdown(manager);
3707 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
3708 EXPECT_REF(clock, 1);
3710 hr = IMFQualityManager_NotifyPresentationClock(manager, clock);
3711 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr);
3713 hr = IMFQualityManager_NotifyTopology(manager, NULL);
3714 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr);
3716 hr = IMFQualityManager_NotifyPresentationClock(manager, NULL);
3717 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr);
3719 hr = IMFQualityManager_Shutdown(manager);
3720 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
3722 IMFQualityManager_Release(manager);
3724 /* Set clock, then release without shutting down. */
3725 hr = MFCreateStandardQualityManager(&manager);
3726 ok(hr == S_OK, "Failed to create quality manager, hr %#x.\n", hr);
3728 EXPECT_REF(clock, 1);
3729 hr = IMFQualityManager_NotifyPresentationClock(manager, clock);
3730 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
3731 EXPECT_REF(clock, 2);
3733 IMFQualityManager_Release(manager);
3734 EXPECT_REF(clock, 2);
3736 IMFPresentationClock_Release(clock);
3738 /* Set topology. */
3739 hr = MFCreateStandardQualityManager(&manager);
3740 ok(hr == S_OK, "Failed to create quality manager, hr %#x.\n", hr);
3742 hr = MFCreateTopology(&topology);
3743 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
3745 EXPECT_REF(topology, 1);
3746 hr = IMFQualityManager_NotifyTopology(manager, topology);
3747 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
3748 EXPECT_REF(topology, 2);
3750 hr = IMFQualityManager_NotifyTopology(manager, NULL);
3751 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
3752 EXPECT_REF(topology, 1);
3754 hr = IMFQualityManager_NotifyTopology(manager, topology);
3755 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
3757 EXPECT_REF(topology, 2);
3758 hr = IMFQualityManager_Shutdown(manager);
3759 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
3760 EXPECT_REF(topology, 1);
3762 hr = IMFQualityManager_NotifyTopology(manager, topology);
3763 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr);
3765 IMFQualityManager_Release(manager);
3767 hr = MFCreateStandardQualityManager(&manager);
3768 ok(hr == S_OK, "Failed to create quality manager, hr %#x.\n", hr);
3770 EXPECT_REF(topology, 1);
3771 hr = IMFQualityManager_NotifyTopology(manager, topology);
3772 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
3773 EXPECT_REF(topology, 2);
3775 IMFQualityManager_Release(manager);
3776 EXPECT_REF(topology, 1);
3778 IMFTopology_Release(topology);
3780 hr = MFShutdown();
3781 ok(hr == S_OK, "Shutdown failure, hr %#x.\n", hr);
3784 static void test_sar(void)
3786 IMFPresentationClock *present_clock, *present_clock2;
3787 IMFMediaType *mediatype, *mediatype2, *mediatype3;
3788 IMFClockStateSink *state_sink, *state_sink2;
3789 IMFMediaTypeHandler *handler, *handler2;
3790 IMFPresentationTimeSource *time_source;
3791 IMFSimpleAudioVolume *simple_volume;
3792 IMFAudioStreamVolume *stream_volume;
3793 IMFMediaSink *sink, *sink2;
3794 IMFStreamSink *stream_sink;
3795 IMFAttributes *attributes;
3796 DWORD i, id, flags, count;
3797 IMFActivate *activate;
3798 MFCLOCK_STATE state;
3799 IMFClock *clock;
3800 IUnknown *unk;
3801 HRESULT hr;
3802 GUID guid;
3803 BOOL mute;
3804 int found;
3806 hr = CoInitialize(NULL);
3807 ok(hr == S_OK, "Failed to initialize, hr %#x.\n", hr);
3809 hr = MFCreateAudioRenderer(NULL, &sink);
3810 if (hr == MF_E_NO_AUDIO_PLAYBACK_DEVICE)
3812 skip("No audio playback device available.\n");
3813 CoUninitialize();
3814 return;
3816 ok(hr == S_OK, "Failed to create renderer, hr %#x.\n", hr);
3818 hr = MFStartup(MF_VERSION, MFSTARTUP_FULL);
3819 ok(hr == S_OK, "Startup failure, hr %#x.\n", hr);
3821 hr = MFCreatePresentationClock(&present_clock);
3822 ok(hr == S_OK, "Failed to create presentation clock, hr %#x.\n", hr);
3824 hr = IMFMediaSink_QueryInterface(sink, &IID_IMFPresentationTimeSource, (void **)&time_source);
3825 todo_wine
3826 ok(hr == S_OK, "Failed to get time source interface, hr %#x.\n", hr);
3828 if (SUCCEEDED(hr))
3830 hr = IMFPresentationTimeSource_QueryInterface(time_source, &IID_IMFClockStateSink, (void **)&state_sink2);
3831 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
3832 hr = IMFPresentationTimeSource_QueryInterface(time_source, &IID_IMFClockStateSink, (void **)&state_sink);
3833 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
3834 ok(state_sink == state_sink2, "Unexpected clock sink.\n");
3835 IMFClockStateSink_Release(state_sink2);
3836 IMFClockStateSink_Release(state_sink);
3838 hr = IMFPresentationTimeSource_GetUnderlyingClock(time_source, &clock);
3839 ok(hr == MF_E_NO_CLOCK, "Unexpected hr %#x.\n", hr);
3841 hr = IMFPresentationTimeSource_GetClockCharacteristics(time_source, &flags);
3842 ok(hr == S_OK, "Failed to get flags, hr %#x.\n", hr);
3843 ok(flags == MFCLOCK_CHARACTERISTICS_FLAG_FREQUENCY_10MHZ, "Unexpected flags %#x.\n", flags);
3845 hr = IMFPresentationTimeSource_GetState(time_source, 0, &state);
3846 ok(hr == S_OK, "Failed to get clock state, hr %#x.\n", hr);
3847 ok(state == MFCLOCK_STATE_INVALID, "Unexpected state %d.\n", state);
3849 hr = IMFPresentationTimeSource_QueryInterface(time_source, &IID_IMFClockStateSink, (void **)&state_sink);
3850 ok(hr == S_OK, "Failed to get state sink, hr %#x.\n", hr);
3852 hr = IMFClockStateSink_OnClockStart(state_sink, 0, 0);
3853 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#x.\n", hr);
3855 IMFClockStateSink_Release(state_sink);
3857 IMFPresentationTimeSource_Release(time_source);
3859 hr = IMFMediaSink_AddStreamSink(sink, 123, NULL, &stream_sink);
3860 ok(hr == MF_E_STREAMSINKS_FIXED, "Unexpected hr %#x.\n", hr);
3862 hr = IMFMediaSink_RemoveStreamSink(sink, 0);
3863 ok(hr == MF_E_STREAMSINKS_FIXED, "Unexpected hr %#x.\n", hr);
3865 hr = IMFMediaSink_GetStreamSinkCount(sink, NULL);
3866 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
3868 hr = IMFMediaSink_GetStreamSinkCount(sink, &count);
3869 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
3870 ok(count == 1, "Unexpected count %u.\n", count);
3872 hr = IMFMediaSink_GetCharacteristics(sink, &flags);
3873 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
3874 ok(flags == (MEDIASINK_FIXED_STREAMS | MEDIASINK_CAN_PREROLL), "Unexpected flags %#x.\n", flags);
3876 check_interface(sink, &IID_IMFMediaSinkPreroll, TRUE);
3877 check_interface(sink, &IID_IMFMediaEventGenerator, TRUE);
3878 check_interface(sink, &IID_IMFClockStateSink, TRUE);
3879 check_interface(sink, &IID_IMFGetService, TRUE);
3880 todo_wine check_interface(sink, &IID_IMFPresentationTimeSource, TRUE);
3881 todo_wine check_service_interface(sink, &MF_RATE_CONTROL_SERVICE, &IID_IMFRateSupport, TRUE);
3882 check_service_interface(sink, &MF_RATE_CONTROL_SERVICE, &IID_IMFRateControl, FALSE);
3883 check_service_interface(sink, &MR_POLICY_VOLUME_SERVICE, &IID_IMFSimpleAudioVolume, TRUE);
3884 check_service_interface(sink, &MR_STREAM_VOLUME_SERVICE, &IID_IMFAudioStreamVolume, TRUE);
3886 /* Clock */
3887 hr = IMFMediaSink_QueryInterface(sink, &IID_IMFClockStateSink, (void **)&state_sink);
3888 ok(hr == S_OK, "Failed to get interface, hr %#x.\n", hr);
3890 hr = IMFClockStateSink_OnClockStart(state_sink, 0, 0);
3891 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#x.\n", hr);
3893 hr = IMFClockStateSink_OnClockPause(state_sink, 0);
3894 ok(hr == MF_E_INVALID_STATE_TRANSITION, "Unexpected hr %#x.\n", hr);
3896 hr = IMFClockStateSink_OnClockStop(state_sink, 0);
3897 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#x.\n", hr);
3899 hr = IMFClockStateSink_OnClockRestart(state_sink, 0);
3900 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#x.\n", hr);
3902 IMFClockStateSink_Release(state_sink);
3904 hr = IMFMediaSink_SetPresentationClock(sink, NULL);
3905 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
3907 hr = IMFMediaSink_SetPresentationClock(sink, present_clock);
3908 todo_wine
3909 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#x.\n", hr);
3911 hr = MFCreateSystemTimeSource(&time_source);
3912 ok(hr == S_OK, "Failed to create time source, hr %#x.\n", hr);
3914 hr = IMFPresentationClock_SetTimeSource(present_clock, time_source);
3915 ok(hr == S_OK, "Failed to set time source, hr %#x.\n", hr);
3916 IMFPresentationTimeSource_Release(time_source);
3918 hr = IMFMediaSink_SetPresentationClock(sink, present_clock);
3919 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
3921 hr = IMFMediaSink_GetPresentationClock(sink, NULL);
3922 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
3924 hr = IMFMediaSink_GetPresentationClock(sink, &present_clock2);
3925 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
3926 ok(present_clock == present_clock2, "Unexpected instance.\n");
3927 IMFPresentationClock_Release(present_clock2);
3929 /* Stream */
3930 hr = IMFMediaSink_GetStreamSinkByIndex(sink, 0, &stream_sink);
3931 ok(hr == S_OK, "Failed to get a stream, hr %#x.\n", hr);
3933 check_interface(stream_sink, &IID_IMFMediaEventGenerator, TRUE);
3934 check_interface(stream_sink, &IID_IMFMediaTypeHandler, TRUE);
3935 todo_wine check_interface(stream_sink, &IID_IMFGetService, TRUE);
3937 hr = IMFStreamSink_GetIdentifier(stream_sink, &id);
3938 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
3939 ok(!id, "Unexpected id.\n");
3941 hr = IMFStreamSink_GetMediaSink(stream_sink, &sink2);
3942 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
3943 ok(sink == sink2, "Unexpected object.\n");
3944 IMFMediaSink_Release(sink2);
3946 hr = IMFStreamSink_GetMediaTypeHandler(stream_sink, &handler);
3947 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
3949 hr = IMFStreamSink_QueryInterface(stream_sink, &IID_IMFMediaTypeHandler, (void **)&handler2);
3950 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
3951 ok(handler2 == handler, "Unexpected instance.\n");
3952 IMFMediaTypeHandler_Release(handler2);
3954 hr = IMFMediaTypeHandler_GetMajorType(handler, &guid);
3955 ok(hr == S_OK, "Failed to get major type, hr %#x.\n", hr);
3956 ok(IsEqualGUID(&guid, &MFMediaType_Audio), "Unexpected type %s.\n", wine_dbgstr_guid(&guid));
3958 count = 0;
3959 hr = IMFMediaTypeHandler_GetMediaTypeCount(handler, &count);
3960 ok(hr == S_OK, "Failed to get type count, hr %#x.\n", hr);
3961 ok(!!count, "Unexpected type count %u.\n", count);
3963 /* A number of same major/subtype entries are returned, with different degrees of finer format
3964 details. Some incomplete types are not accepted, check that at least one of them is considered supported. */
3966 for (i = 0, found = -1; i < count; ++i)
3968 hr = IMFMediaTypeHandler_GetMediaTypeByIndex(handler, i, &mediatype);
3969 ok(hr == S_OK, "Failed to get media type, hr %#x.\n", hr);
3971 if (SUCCEEDED(IMFMediaTypeHandler_IsMediaTypeSupported(handler, mediatype, NULL)))
3972 found = i;
3973 IMFMediaType_Release(mediatype);
3975 if (found != -1) break;
3977 ok(found != -1, "Haven't found a supported type.\n");
3979 hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, &mediatype);
3980 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#x.\n", hr);
3982 hr = MFCreateMediaType(&mediatype);
3983 ok(hr == S_OK, "Failed to create media type, hr %#x.\n", hr);
3985 /* Actual return value is MF_E_ATRIBUTENOTFOUND triggered by missing MF_MT_MAJOR_TYPE */
3986 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, mediatype, NULL);
3987 ok(FAILED(hr), "Unexpected hr %#x.\n", hr);
3989 hr = IMFMediaType_SetGUID(mediatype, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
3990 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
3991 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, mediatype, NULL);
3992 ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#x.\n", hr);
3994 hr = IMFMediaType_SetGUID(mediatype, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio);
3995 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
3996 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, mediatype, NULL);
3997 ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#x.\n", hr);
3999 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, mediatype);
4000 ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#x.\n", hr);
4002 hr = IMFMediaTypeHandler_GetMediaTypeByIndex(handler, found, &mediatype2);
4003 ok(hr == S_OK, "Failed to get media type, hr %#x.\n", hr);
4005 hr = IMFMediaTypeHandler_GetMediaTypeByIndex(handler, found, &mediatype3);
4006 ok(hr == S_OK, "Failed to get media type, hr %#x.\n", hr);
4007 ok(mediatype2 == mediatype3, "Unexpected instance.\n");
4008 IMFMediaType_Release(mediatype3);
4010 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, mediatype2, NULL);
4011 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4013 IMFMediaType_Release(mediatype);
4015 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, mediatype2);
4016 ok(hr == S_OK, "Failed to set current type, hr %#x.\n", hr);
4018 hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, &mediatype);
4019 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4020 ok(mediatype == mediatype2, "Unexpected instance.\n");
4021 IMFMediaType_Release(mediatype);
4023 IMFMediaType_Release(mediatype2);
4025 /* Reset back to uninitialized state. */
4026 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, NULL);
4027 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
4029 IMFMediaTypeHandler_Release(handler);
4031 /* State change with initialized stream. */
4032 hr = IMFMediaSink_QueryInterface(sink, &IID_IMFClockStateSink, (void **)&state_sink);
4033 ok(hr == S_OK, "Failed to get interface, hr %#x.\n", hr);
4035 hr = IMFClockStateSink_OnClockStart(state_sink, 0, 0);
4036 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4038 hr = IMFClockStateSink_OnClockStart(state_sink, 0, 0);
4039 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4041 hr = IMFClockStateSink_OnClockPause(state_sink, 0);
4042 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4044 hr = IMFClockStateSink_OnClockStop(state_sink, 0);
4045 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4047 hr = IMFClockStateSink_OnClockStop(state_sink, 0);
4048 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4050 hr = IMFClockStateSink_OnClockPause(state_sink, 0);
4051 ok(hr == MF_E_INVALID_STATE_TRANSITION, "Unexpected hr %#x.\n", hr);
4053 hr = IMFClockStateSink_OnClockRestart(state_sink, 0);
4054 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4056 hr = IMFClockStateSink_OnClockRestart(state_sink, 0);
4057 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4059 hr = IMFClockStateSink_OnClockStop(state_sink, 0);
4060 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4062 IMFClockStateSink_Release(state_sink);
4064 IMFStreamSink_Release(stream_sink);
4066 /* Volume control */
4067 hr = MFGetService((IUnknown *)sink, &MR_POLICY_VOLUME_SERVICE, &IID_IMFSimpleAudioVolume, (void **)&simple_volume);
4068 ok(hr == S_OK, "Failed to get interface, hr %#x.\n", hr);
4070 hr = IMFSimpleAudioVolume_GetMute(simple_volume, &mute);
4071 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4073 IMFSimpleAudioVolume_Release(simple_volume);
4075 hr = MFGetService((IUnknown *)sink, &MR_STREAM_VOLUME_SERVICE, &IID_IMFAudioStreamVolume, (void **)&stream_volume);
4076 ok(hr == S_OK, "Failed to get interface, hr %#x.\n", hr);
4078 hr = IMFAudioStreamVolume_GetChannelCount(stream_volume, &count);
4079 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4081 hr = IMFAudioStreamVolume_GetChannelCount(stream_volume, NULL);
4082 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
4084 IMFAudioStreamVolume_Release(stream_volume);
4086 hr = MFGetService((IUnknown *)sink, &MR_AUDIO_POLICY_SERVICE, &IID_IMFAudioPolicy, (void **)&unk);
4087 ok(hr == S_OK, "Failed to get interface, hr %#x.\n", hr);
4088 IUnknown_Release(unk);
4090 /* Shutdown */
4091 EXPECT_REF(present_clock, 2);
4092 hr = IMFMediaSink_Shutdown(sink);
4093 ok(hr == S_OK, "Failed to shut down, hr %#x.\n", hr);
4094 EXPECT_REF(present_clock, 1);
4096 hr = IMFMediaSink_Shutdown(sink);
4097 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr);
4099 hr = IMFMediaSink_AddStreamSink(sink, 123, NULL, &stream_sink);
4100 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr);
4102 hr = IMFMediaSink_RemoveStreamSink(sink, 0);
4103 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr);
4105 hr = IMFMediaSink_GetStreamSinkCount(sink, NULL);
4106 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
4108 hr = IMFMediaSink_GetStreamSinkCount(sink, &count);
4109 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr);
4111 hr = IMFMediaSink_GetCharacteristics(sink, &flags);
4112 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr);
4114 hr = IMFMediaSink_SetPresentationClock(sink, NULL);
4115 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr);
4117 hr = IMFMediaSink_SetPresentationClock(sink, present_clock);
4118 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr);
4120 hr = IMFMediaSink_GetPresentationClock(sink, NULL);
4121 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
4123 hr = IMFMediaSink_GetPresentationClock(sink, &present_clock2);
4124 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr);
4126 IMFMediaSink_Release(sink);
4128 /* Activation */
4129 hr = MFCreateAudioRendererActivate(&activate);
4130 ok(hr == S_OK, "Failed to create activation object, hr %#x.\n", hr);
4132 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink);
4133 ok(hr == S_OK, "Failed to activate, hr %#x.\n", hr);
4135 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink2);
4136 ok(hr == S_OK, "Failed to activate, hr %#x.\n", hr);
4137 ok(sink == sink2, "Unexpected instance.\n");
4138 IMFMediaSink_Release(sink2);
4140 hr = IMFMediaSink_GetCharacteristics(sink, &flags);
4141 ok(hr == S_OK, "Failed to get sink flags, hr %#x.\n", hr);
4143 hr = IMFActivate_ShutdownObject(activate);
4144 ok(hr == S_OK, "Failed to shut down, hr %#x.\n", hr);
4146 hr = IMFMediaSink_GetCharacteristics(sink, &flags);
4147 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr);
4149 IMFMediaSink_Release(sink);
4151 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink);
4152 ok(hr == S_OK, "Failed to activate, hr %#x.\n", hr);
4154 hr = IMFMediaSink_GetCharacteristics(sink, &flags);
4155 todo_wine
4156 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr);
4158 IMFMediaSink_Release(sink);
4160 hr = IMFActivate_DetachObject(activate);
4161 ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
4163 IMFActivate_Release(activate);
4165 IMFPresentationClock_Release(present_clock);
4167 hr = MFShutdown();
4168 ok(hr == S_OK, "Shutdown failure, hr %#x.\n", hr);
4170 /* SAR attributes */
4171 hr = MFCreateAttributes(&attributes, 0);
4172 ok(hr == S_OK, "Failed to create attributes, hr %#x.\n", hr);
4174 /* Specify role. */
4175 hr = IMFAttributes_SetUINT32(attributes, &MF_AUDIO_RENDERER_ATTRIBUTE_ENDPOINT_ROLE, eMultimedia);
4176 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
4178 hr = MFCreateAudioRenderer(attributes, &sink);
4179 ok(hr == S_OK, "Failed to create a sink, hr %#x.\n", hr);
4180 IMFMediaSink_Release(sink);
4182 /* Invalid endpoint. */
4183 hr = IMFAttributes_SetString(attributes, &MF_AUDIO_RENDERER_ATTRIBUTE_ENDPOINT_ID, L"endpoint");
4184 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
4186 hr = MFCreateAudioRenderer(attributes, &sink);
4187 ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
4189 hr = IMFAttributes_DeleteItem(attributes, &MF_AUDIO_RENDERER_ATTRIBUTE_ENDPOINT_ROLE);
4190 ok(hr == S_OK, "Failed to remove attribute, hr %#x.\n", hr);
4192 hr = MFCreateAudioRenderer(attributes, &sink);
4193 ok(hr == MF_E_NO_AUDIO_PLAYBACK_DEVICE, "Failed to create a sink, hr %#x.\n", hr);
4195 CoUninitialize();
4198 static void test_evr(void)
4200 IMFVideoSampleAllocatorCallback *allocator_callback;
4201 IMFStreamSink *stream_sink, *stream_sink2;
4202 IMFVideoDisplayControl *display_control;
4203 IMFMediaType *media_type, *media_type2;
4204 IMFVideoSampleAllocator *allocator;
4205 IMFMediaTypeHandler *type_handler;
4206 IMFVideoRenderer *video_renderer;
4207 IMFMediaSink *sink, *sink2;
4208 IMFAttributes *attributes;
4209 DWORD flags, count, value;
4210 IMFActivate *activate;
4211 HWND window, window2;
4212 LONG sample_count;
4213 IMFGetService *gs;
4214 IMFSample *sample;
4215 IUnknown *unk;
4216 UINT64 window3;
4217 HRESULT hr;
4218 GUID guid;
4220 hr = CoInitialize(NULL);
4221 ok(hr == S_OK, "Failed to initialize, hr %#x.\n", hr);
4223 hr = MFCreateVideoRenderer(&IID_IMFVideoRenderer, (void **)&video_renderer);
4224 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4226 hr = IMFVideoRenderer_InitializeRenderer(video_renderer, NULL, NULL);
4227 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4229 IMFVideoRenderer_Release(video_renderer);
4231 hr = MFCreateVideoRendererActivate(NULL, NULL);
4232 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
4234 /* Window */
4235 window = create_window();
4236 hr = MFCreateVideoRendererActivate(window, &activate);
4237 ok(hr == S_OK, "Failed to create activate object, hr %#x.\n", hr);
4239 hr = IMFActivate_GetUINT64(activate, &MF_ACTIVATE_VIDEO_WINDOW, &window3);
4240 ok(hr == S_OK, "Failed to get attribute, hr %#x.\n", hr);
4241 ok(UlongToHandle(window3) == window, "Unexpected value.\n");
4243 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink);
4244 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4246 check_interface(sink, &IID_IMFMediaSinkPreroll, TRUE);
4247 check_interface(sink, &IID_IMFVideoRenderer, TRUE);
4248 check_interface(sink, &IID_IMFMediaEventGenerator, TRUE);
4249 check_interface(sink, &IID_IMFClockStateSink, TRUE);
4250 check_interface(sink, &IID_IMFGetService, TRUE);
4251 check_interface(sink, &IID_IMFQualityAdvise, TRUE);
4253 hr = MFGetService((IUnknown *)sink, &MR_VIDEO_RENDER_SERVICE, &IID_IMFVideoDisplayControl,
4254 (void **)&display_control);
4255 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4257 window2 = NULL;
4258 hr = IMFVideoDisplayControl_GetVideoWindow(display_control, &window2);
4259 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4260 ok(window2 == window, "Unexpected window %p.\n", window2);
4262 IMFVideoDisplayControl_Release(display_control);
4263 IMFMediaSink_Release(sink);
4264 IMFActivate_Release(activate);
4265 DestroyWindow(window);
4267 hr = MFCreateVideoRendererActivate(NULL, &activate);
4268 ok(hr == S_OK, "Failed to create activate object, hr %#x.\n", hr);
4270 hr = IMFActivate_GetCount(activate, &count);
4271 ok(hr == S_OK, "Failed to get attribute count, hr %#x.\n", hr);
4272 ok(count == 1, "Unexpected count %u.\n", count);
4274 hr = IMFActivate_GetUINT64(activate, &MF_ACTIVATE_VIDEO_WINDOW, &window3);
4275 ok(hr == S_OK, "Failed to get attribute, hr %#x.\n", hr);
4276 ok(!window3, "Unexpected value.\n");
4278 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink);
4279 ok(hr == S_OK, "Failed to activate, hr %#x.\n", hr);
4281 hr = IMFMediaSink_QueryInterface(sink, &IID_IMFAttributes, (void **)&attributes);
4282 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4283 hr = IMFAttributes_QueryInterface(attributes, &IID_IMFMediaSink, (void **)&unk);
4284 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4285 IUnknown_Release(unk);
4286 hr = IMFAttributes_GetCount(attributes, &count);
4287 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4288 ok(!!count, "Unexpected count %u.\n", count);
4289 /* Rendering preferences are not immediately propagated to the presenter. */
4290 hr = IMFAttributes_SetUINT32(attributes, &EVRConfig_ForceBob, 1);
4291 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4292 hr = MFGetService((IUnknown *)sink, &MR_VIDEO_RENDER_SERVICE, &IID_IMFVideoDisplayControl, (void **)&display_control);
4293 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4294 hr = IMFVideoDisplayControl_GetRenderingPrefs(display_control, &flags);
4295 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4296 ok(!flags, "Unexpected flags %#x.\n", flags);
4297 IMFVideoDisplayControl_Release(display_control);
4298 IMFAttributes_Release(attributes);
4300 /* Primary stream type handler. */
4301 hr = IMFMediaSink_GetStreamSinkById(sink, 0, &stream_sink);
4302 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4304 hr = IMFStreamSink_QueryInterface(stream_sink, &IID_IMFAttributes, (void **)&attributes);
4305 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4306 hr = IMFAttributes_GetCount(attributes, &count);
4307 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4308 ok(count == 2, "Unexpected count %u.\n", count);
4309 value = 0;
4310 hr = IMFAttributes_GetUINT32(attributes, &MF_SA_REQUIRED_SAMPLE_COUNT, &value);
4311 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4312 ok(value == 1, "Unexpected attribute value %u.\n", value);
4313 value = 0;
4314 hr = IMFAttributes_GetUINT32(attributes, &MF_SA_D3D_AWARE, &value);
4315 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4316 ok(value == 1, "Unexpected attribute value %u.\n", value);
4318 hr = IMFAttributes_QueryInterface(attributes, &IID_IMFStreamSink, (void **)&unk);
4319 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4320 IUnknown_Release(unk);
4321 IMFAttributes_Release(attributes);
4323 hr = IMFStreamSink_GetMediaTypeHandler(stream_sink, &type_handler);
4324 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4326 hr = IMFMediaTypeHandler_GetMajorType(type_handler, NULL);
4327 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
4329 hr = IMFMediaTypeHandler_GetMajorType(type_handler, &guid);
4330 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4331 ok(IsEqualGUID(&guid, &MFMediaType_Video), "Unexpected type %s.\n", wine_dbgstr_guid(&guid));
4333 /* Supported types are not advertised. */
4334 hr = IMFMediaTypeHandler_GetMediaTypeCount(type_handler, NULL);
4335 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
4337 count = 1;
4338 hr = IMFMediaTypeHandler_GetMediaTypeCount(type_handler, &count);
4339 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4340 ok(!count, "Unexpected count %u.\n", count);
4342 hr = IMFMediaTypeHandler_GetMediaTypeByIndex(type_handler, 0, NULL);
4343 ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#x.\n", hr);
4345 hr = IMFMediaTypeHandler_GetMediaTypeByIndex(type_handler, 0, &media_type);
4346 ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#x.\n", hr);
4348 hr = IMFMediaTypeHandler_GetCurrentMediaType(type_handler, NULL);
4349 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
4351 hr = IMFMediaTypeHandler_GetCurrentMediaType(type_handler, &media_type);
4352 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#x.\n", hr);
4354 hr = IMFMediaTypeHandler_SetCurrentMediaType(type_handler, NULL);
4355 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
4357 hr = MFCreateMediaType(&media_type);
4358 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4360 hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
4361 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4363 hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFVideoFormat_RGB32);
4364 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4366 hr = IMFMediaType_SetUINT64(media_type, &MF_MT_FRAME_SIZE, (UINT64)640 << 32 | 480);
4367 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4369 hr = IMFMediaTypeHandler_IsMediaTypeSupported(type_handler, NULL, NULL);
4370 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
4372 hr = IMFMediaTypeHandler_IsMediaTypeSupported(type_handler, media_type, &media_type2);
4373 ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#x.\n", hr);
4375 hr = IMFMediaType_SetUINT32(media_type, &MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE);
4376 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4378 media_type2 = (void *)0x1;
4379 hr = IMFMediaTypeHandler_IsMediaTypeSupported(type_handler, media_type, &media_type2);
4380 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4381 ok(!media_type2, "Unexpected media type %p.\n", media_type2);
4383 hr = IMFMediaTypeHandler_SetCurrentMediaType(type_handler, media_type);
4384 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4386 hr = IMFMediaTypeHandler_GetCurrentMediaType(type_handler, &media_type2);
4387 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4388 hr = IMFMediaType_QueryInterface(media_type2, &IID_IMFVideoMediaType, (void **)&unk);
4389 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4390 IUnknown_Release(unk);
4391 IMFMediaType_Release(media_type2);
4393 IMFMediaType_Release(media_type);
4395 IMFMediaTypeHandler_Release(type_handler);
4397 /* Stream uses an allocator. */
4398 hr = MFGetService((IUnknown *)stream_sink, &MR_VIDEO_ACCELERATION_SERVICE, &IID_IMFVideoSampleAllocator,
4399 (void **)&allocator);
4400 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4402 hr = IMFVideoSampleAllocator_QueryInterface(allocator, &IID_IMFVideoSampleAllocatorCallback, (void **)&allocator_callback);
4403 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4405 sample_count = 0;
4406 hr = IMFVideoSampleAllocatorCallback_GetFreeSampleCount(allocator_callback, &sample_count);
4407 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4408 ok(!sample_count, "Unexpected sample count %d.\n", sample_count);
4410 hr = IMFVideoSampleAllocator_AllocateSample(allocator, &sample);
4411 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#x.\n", hr);
4413 IMFVideoSampleAllocatorCallback_Release(allocator_callback);
4414 IMFVideoSampleAllocator_Release(allocator);
4416 /* Same test for a substream. */
4417 hr = IMFMediaSink_AddStreamSink(sink, 1, NULL, &stream_sink2);
4418 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4420 hr = MFGetService((IUnknown *)stream_sink2, &MR_VIDEO_ACCELERATION_SERVICE, &IID_IMFVideoSampleAllocator,
4421 (void **)&allocator);
4422 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4423 IMFVideoSampleAllocator_Release(allocator);
4425 hr = IMFMediaSink_RemoveStreamSink(sink, 1);
4426 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4428 IMFStreamSink_Release(stream_sink2);
4430 hr = IMFMediaSink_GetCharacteristics(sink, &flags);
4431 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4432 ok(flags == (MEDIASINK_CAN_PREROLL | MEDIASINK_CLOCK_REQUIRED), "Unexpected flags %#x.\n", flags);
4434 hr = IMFMediaSink_QueryInterface(sink, &IID_IMFGetService, (void **)&gs);
4435 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4437 hr = IMFGetService_GetService(gs, &MR_VIDEO_MIXER_SERVICE, &IID_IMFVideoMixerControl, (void **)&unk);
4438 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4439 IUnknown_Release(unk);
4441 IMFGetService_Release(gs);
4443 hr = IMFActivate_ShutdownObject(activate);
4444 ok(hr == S_OK, "Failed to shut down, hr %#x.\n", hr);
4446 hr = IMFMediaSink_GetCharacteristics(sink, &flags);
4447 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr);
4449 /* Activate again. */
4450 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink2);
4451 ok(hr == S_OK, "Failed to activate, hr %#x.\n", hr);
4452 todo_wine
4453 ok(sink == sink2, "Unexpected instance.\n");
4454 IMFMediaSink_Release(sink2);
4456 hr = IMFActivate_DetachObject(activate);
4457 ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
4459 hr = IMFMediaSink_GetCharacteristics(sink, &flags);
4460 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr);
4462 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink2);
4463 ok(hr == S_OK, "Failed to activate, hr %#x.\n", hr);
4465 hr = IMFActivate_ShutdownObject(activate);
4466 ok(hr == S_OK, "Failed to shut down, hr %#x.\n", hr);
4468 IMFMediaSink_Release(sink2);
4469 IMFMediaSink_Release(sink);
4471 IMFActivate_Release(activate);
4473 CoUninitialize();
4476 static void test_MFCreateSimpleTypeHandler(void)
4478 IMFMediaType *media_type, *media_type2, *media_type3;
4479 IMFMediaTypeHandler *handler;
4480 DWORD count;
4481 HRESULT hr;
4482 GUID guid;
4484 hr = MFCreateSimpleTypeHandler(&handler);
4485 ok(hr == S_OK, "Failed to create object, hr %#x.\n", hr);
4487 hr = IMFMediaTypeHandler_GetMediaTypeCount(handler, NULL);
4488 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
4490 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, NULL, NULL);
4491 ok(hr == MF_E_UNEXPECTED, "Unexpected hr %#x.\n", hr);
4493 count = 0;
4494 hr = IMFMediaTypeHandler_GetMediaTypeCount(handler, &count);
4495 ok(hr == S_OK, "Failed to get type count, hr %#x.\n", hr);
4496 ok(count == 1, "Unexpected count %u.\n", count);
4498 hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, NULL);
4499 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
4501 media_type = (void *)0xdeadbeef;
4502 hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, &media_type);
4503 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4504 ok(!media_type, "Unexpected pointer.\n");
4506 hr = MFCreateMediaType(&media_type);
4507 ok(hr == S_OK, "Failed to create media type, hr %#x.\n", hr);
4509 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type, NULL);
4510 ok(hr == MF_E_UNEXPECTED, "Unexpected hr %#x.\n", hr);
4512 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, media_type);
4513 ok(hr == S_OK, "Failed to set current type, hr %#x.\n", hr);
4515 hr = IMFMediaTypeHandler_GetMediaTypeByIndex(handler, 0, &media_type2);
4516 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4517 ok(media_type2 == media_type, "Unexpected type.\n");
4518 IMFMediaType_Release(media_type2);
4520 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, NULL, NULL);
4521 ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
4523 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type, NULL);
4524 ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
4526 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type, &media_type2);
4527 ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
4529 hr = IMFMediaTypeHandler_GetMediaTypeByIndex(handler, 1, &media_type2);
4530 ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#x.\n", hr);
4532 hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, &media_type2);
4533 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4534 ok(media_type == media_type2, "Unexpected pointer.\n");
4535 IMFMediaType_Release(media_type2);
4537 hr = IMFMediaTypeHandler_GetMajorType(handler, &guid);
4538 ok(hr == MF_E_ATTRIBUTENOTFOUND, "Unexpected hr %#x.\n", hr);
4540 hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
4541 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
4543 hr = IMFMediaTypeHandler_GetMajorType(handler, &guid);
4544 ok(hr == S_OK, "Failed to get major type, hr %#x.\n", hr);
4545 ok(IsEqualGUID(&guid, &MFMediaType_Video), "Unexpected major type.\n");
4547 hr = MFCreateMediaType(&media_type3);
4548 ok(hr == S_OK, "Failed to create media type, hr %#x.\n", hr);
4550 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type3, NULL);
4551 ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
4553 hr = IMFMediaType_SetGUID(media_type3, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio);
4554 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
4556 /* Different major types. */
4557 media_type2 = (void *)0xdeadbeef;
4558 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type3, &media_type2);
4559 ok(hr == E_FAIL, "Unexpected hr %#x.\n", hr);
4560 ok(!media_type2, "Unexpected pointer.\n");
4562 hr = IMFMediaType_SetGUID(media_type3, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
4563 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
4565 media_type2 = (void *)0xdeadbeef;
4566 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type3, &media_type2);
4567 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4568 ok(!media_type2, "Unexpected pointer.\n");
4570 /* Handler missing subtype. */
4571 hr = IMFMediaType_SetGUID(media_type3, &MF_MT_SUBTYPE, &MFVideoFormat_RGB8);
4572 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
4574 media_type2 = (void *)0xdeadbeef;
4575 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type3, &media_type2);
4576 ok(hr == E_FAIL, "Unexpected hr %#x.\n", hr);
4577 ok(!media_type2, "Unexpected pointer.\n");
4579 /* Different subtypes. */
4580 hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFVideoFormat_RGB24);
4581 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
4583 media_type2 = (void *)0xdeadbeef;
4584 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type3, &media_type2);
4585 ok(hr == E_FAIL, "Unexpected hr %#x.\n", hr);
4586 ok(!media_type2, "Unexpected pointer.\n");
4588 /* Same major/subtype. */
4589 hr = IMFMediaType_SetGUID(media_type3, &MF_MT_SUBTYPE, &MFVideoFormat_RGB24);
4590 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
4592 media_type2 = (void *)0xdeadbeef;
4593 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type3, &media_type2);
4594 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4595 ok(!media_type2, "Unexpected pointer.\n");
4597 /* Set one more attribute. */
4598 hr = IMFMediaType_SetUINT64(media_type, &MF_MT_FRAME_SIZE, (UINT64)4 << 32 | 4);
4599 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
4601 media_type2 = (void *)0xdeadbeef;
4602 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type3, &media_type2);
4603 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4604 ok(!media_type2, "Unexpected pointer.\n");
4606 IMFMediaType_Release(media_type3);
4607 IMFMediaType_Release(media_type);
4609 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, NULL);
4610 ok(hr == S_OK, "Failed to set current type, hr %#x.\n", hr);
4612 media_type = (void *)0xdeadbeef;
4613 hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, &media_type);
4614 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4615 ok(!media_type, "Unexpected pointer.\n");
4617 hr = IMFMediaTypeHandler_GetMajorType(handler, &guid);
4618 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#x.\n", hr);
4620 IMFMediaTypeHandler_Release(handler);
4623 static void test_MFGetSupportedMimeTypes(void)
4625 PROPVARIANT value;
4626 HRESULT hr;
4628 hr = MFGetSupportedMimeTypes(NULL);
4629 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
4631 value.vt = VT_EMPTY;
4632 hr = MFGetSupportedMimeTypes(&value);
4633 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4634 ok(value.vt == (VT_VECTOR | VT_LPWSTR), "Unexpected value type %#x.\n", value.vt);
4636 PropVariantClear(&value);
4639 static void test_MFGetSupportedSchemes(void)
4641 PROPVARIANT value;
4642 HRESULT hr;
4644 hr = MFGetSupportedSchemes(NULL);
4645 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
4647 value.vt = VT_EMPTY;
4648 hr = MFGetSupportedSchemes(&value);
4649 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4650 ok(value.vt == (VT_VECTOR | VT_LPWSTR), "Unexpected value type %#x.\n", value.vt);
4652 PropVariantClear(&value);
4655 static BOOL is_sample_copier_available_type(IMFMediaType *type)
4657 GUID major = { 0 };
4658 UINT32 count;
4659 HRESULT hr;
4661 hr = IMFMediaType_GetMajorType(type, &major);
4662 ok(hr == S_OK, "Failed to get major type, hr %#x.\n", hr);
4664 hr = IMFMediaType_GetCount(type, &count);
4665 ok(hr == S_OK, "Failed to get attribute count, hr %#x.\n", hr);
4666 ok(count == 1, "Unexpected attribute count %u.\n", count);
4668 return IsEqualGUID(&major, &MFMediaType_Video) || IsEqualGUID(&major, &MFMediaType_Audio);
4671 static void test_sample_copier(void)
4673 IMFAttributes *attributes, *attributes2;
4674 DWORD in_min, in_max, out_min, out_max;
4675 IMFMediaType *mediatype, *mediatype2;
4676 MFT_OUTPUT_STREAM_INFO output_info;
4677 IMFSample *sample, *client_sample;
4678 MFT_INPUT_STREAM_INFO input_info;
4679 DWORD input_count, output_count;
4680 MFT_OUTPUT_DATA_BUFFER buffer;
4681 IMFMediaBuffer *media_buffer;
4682 DWORD count, flags, status;
4683 IMFTransform *copier;
4684 UINT32 value;
4685 HRESULT hr;
4687 if (!pMFCreateSampleCopierMFT)
4689 win_skip("MFCreateSampleCopierMFT() is not available.\n");
4690 return;
4693 hr = pMFCreateSampleCopierMFT(&copier);
4694 ok(hr == S_OK, "Failed to create sample copier, hr %#x.\n", hr);
4696 hr = IMFTransform_GetAttributes(copier, &attributes);
4697 ok(hr == S_OK, "Failed to get transform attributes, hr %#x.\n", hr);
4698 hr = IMFTransform_GetAttributes(copier, &attributes2);
4699 ok(hr == S_OK, "Failed to get transform attributes, hr %#x.\n", hr);
4700 ok(attributes == attributes2, "Unexpected instance.\n");
4701 IMFAttributes_Release(attributes2);
4702 hr = IMFAttributes_GetCount(attributes, &count);
4703 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4704 ok(count == 1, "Unexpected attribute count %u.\n", count);
4705 hr = IMFAttributes_GetUINT32(attributes, &MFT_SUPPORT_DYNAMIC_FORMAT_CHANGE, &value);
4706 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4707 ok(!!value, "Unexpected value %u.\n", value);
4708 IMFAttributes_Release(attributes);
4710 hr = IMFTransform_GetInputStreamAttributes(copier, 0, &attributes);
4711 ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
4713 hr = IMFTransform_GetInputStreamAttributes(copier, 1, &attributes);
4714 ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
4716 hr = IMFTransform_GetOutputStreamAttributes(copier, 0, &attributes);
4717 ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
4719 hr = IMFTransform_GetOutputStreamAttributes(copier, 1, &attributes);
4720 ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
4722 hr = IMFTransform_SetOutputBounds(copier, 0, 0);
4723 ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
4725 /* No dynamic streams. */
4726 input_count = output_count = 0;
4727 hr = IMFTransform_GetStreamCount(copier, &input_count, &output_count);
4728 ok(hr == S_OK, "Failed to get stream count, hr %#x.\n", hr);
4729 ok(input_count == 1 && output_count == 1, "Unexpected streams count.\n");
4731 hr = IMFTransform_GetStreamLimits(copier, &in_min, &in_max, &out_min, &out_max);
4732 ok(hr == S_OK, "Failed to get stream limits, hr %#x.\n", hr);
4733 ok(in_min == in_max && in_min == 1 && out_min == out_max && out_min == 1, "Unexpected stream limits.\n");
4735 hr = IMFTransform_GetStreamIDs(copier, 1, &input_count, 1, &output_count);
4736 ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
4738 hr = IMFTransform_DeleteInputStream(copier, 0);
4739 ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
4741 /* Available types. */
4742 hr = IMFTransform_GetInputAvailableType(copier, 0, 0, &mediatype);
4743 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4744 ok(is_sample_copier_available_type(mediatype), "Unexpected type.\n");
4745 IMFMediaType_Release(mediatype);
4747 hr = IMFTransform_GetInputAvailableType(copier, 0, 1, &mediatype);
4748 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4749 ok(is_sample_copier_available_type(mediatype), "Unexpected type.\n");
4750 IMFMediaType_Release(mediatype);
4752 hr = IMFTransform_GetInputAvailableType(copier, 0, 2, &mediatype);
4753 ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#x.\n", hr);
4755 hr = IMFTransform_GetInputAvailableType(copier, 1, 0, &mediatype);
4756 ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#x.\n", hr);
4758 hr = IMFTransform_GetOutputAvailableType(copier, 0, 0, &mediatype);
4759 ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#x.\n", hr);
4761 hr = IMFTransform_GetOutputAvailableType(copier, 1, 0, &mediatype);
4762 ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#x.\n", hr);
4764 hr = IMFTransform_GetInputCurrentType(copier, 0, &mediatype);
4765 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#x.\n", hr);
4767 hr = IMFTransform_GetInputCurrentType(copier, 1, &mediatype);
4768 ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#x.\n", hr);
4770 hr = IMFTransform_GetOutputCurrentType(copier, 0, &mediatype);
4771 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#x.\n", hr);
4773 hr = IMFTransform_GetOutputCurrentType(copier, 1, &mediatype);
4774 ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#x.\n", hr);
4776 hr = MFCreateSample(&sample);
4777 ok(hr == S_OK, "Failed to create a sample, hr %#x.\n", hr);
4779 hr = IMFTransform_ProcessInput(copier, 0, sample, 0);
4780 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#x.\n", hr);
4782 hr = MFCreateMediaType(&mediatype);
4783 ok(hr == S_OK, "Failed to create media type, hr %#x.\n", hr);
4785 hr = IMFTransform_SetOutputType(copier, 0, mediatype, 0);
4786 ok(hr == MF_E_ATTRIBUTENOTFOUND, "Unexpected hr %#x.\n", hr);
4788 hr = IMFMediaType_SetGUID(mediatype, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
4789 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
4791 hr = IMFMediaType_SetGUID(mediatype, &MF_MT_SUBTYPE, &MFVideoFormat_RGB8);
4792 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
4794 hr = IMFMediaType_SetUINT64(mediatype, &MF_MT_FRAME_SIZE, ((UINT64)16) << 32 | 16);
4795 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
4797 hr = IMFTransform_GetOutputStreamInfo(copier, 0, &output_info);
4798 ok(hr == S_OK, "Failed to get stream info, hr %#x.\n", hr);
4799 ok(!output_info.dwFlags, "Unexpected flags %#x.\n", output_info.dwFlags);
4800 ok(!output_info.cbSize, "Unexpected size %u.\n", output_info.cbSize);
4801 ok(!output_info.cbAlignment, "Unexpected alignment %u.\n", output_info.cbAlignment);
4803 hr = IMFTransform_GetInputStreamInfo(copier, 0, &input_info);
4804 ok(hr == S_OK, "Failed to get stream info, hr %#x.\n", hr);
4806 ok(!input_info.hnsMaxLatency, "Unexpected latency %s.\n", wine_dbgstr_longlong(input_info.hnsMaxLatency));
4807 ok(!input_info.dwFlags, "Unexpected flags %#x.\n", input_info.dwFlags);
4808 ok(!input_info.cbSize, "Unexpected size %u.\n", input_info.cbSize);
4809 ok(!input_info.cbMaxLookahead, "Unexpected lookahead size %u.\n", input_info.cbMaxLookahead);
4810 ok(!input_info.cbAlignment, "Unexpected alignment %u.\n", input_info.cbAlignment);
4812 hr = IMFTransform_SetOutputType(copier, 0, mediatype, 0);
4813 ok(hr == S_OK, "Failed to set input type, hr %#x.\n", hr);
4815 hr = IMFTransform_GetOutputStreamInfo(copier, 0, &output_info);
4816 ok(hr == S_OK, "Failed to get stream info, hr %#x.\n", hr);
4817 ok(!output_info.dwFlags, "Unexpected flags %#x.\n", output_info.dwFlags);
4818 ok(output_info.cbSize == 16 * 16, "Unexpected size %u.\n", output_info.cbSize);
4819 ok(!output_info.cbAlignment, "Unexpected alignment %u.\n", output_info.cbAlignment);
4821 hr = IMFTransform_GetOutputCurrentType(copier, 0, &mediatype2);
4822 ok(hr == S_OK, "Failed to get current type, hr %#x.\n", hr);
4823 IMFMediaType_Release(mediatype2);
4825 hr = IMFTransform_GetInputCurrentType(copier, 0, &mediatype2);
4826 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#x.\n", hr);
4828 hr = IMFTransform_GetInputStatus(copier, 0, &flags);
4829 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#x.\n", hr);
4831 /* Setting input type resets output type. */
4832 hr = IMFTransform_GetOutputCurrentType(copier, 0, &mediatype2);
4833 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4834 IMFMediaType_Release(mediatype2);
4836 hr = IMFTransform_SetInputType(copier, 0, mediatype, 0);
4837 ok(hr == S_OK, "Failed to set input type, hr %#x.\n", hr);
4839 hr = IMFTransform_GetOutputCurrentType(copier, 0, &mediatype2);
4840 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#x.\n", hr);
4842 hr = IMFTransform_GetInputAvailableType(copier, 0, 1, &mediatype2);
4843 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4844 ok(is_sample_copier_available_type(mediatype2), "Unexpected type.\n");
4845 IMFMediaType_Release(mediatype2);
4847 hr = IMFTransform_GetInputStreamInfo(copier, 0, &input_info);
4848 ok(hr == S_OK, "Failed to get stream info, hr %#x.\n", hr);
4849 ok(!input_info.hnsMaxLatency, "Unexpected latency %s.\n", wine_dbgstr_longlong(input_info.hnsMaxLatency));
4850 ok(!input_info.dwFlags, "Unexpected flags %#x.\n", input_info.dwFlags);
4851 ok(input_info.cbSize == 16 * 16, "Unexpected size %u.\n", input_info.cbSize);
4852 ok(!input_info.cbMaxLookahead, "Unexpected lookahead size %u.\n", input_info.cbMaxLookahead);
4853 ok(!input_info.cbAlignment, "Unexpected alignment %u.\n", input_info.cbAlignment);
4855 hr = IMFTransform_GetOutputAvailableType(copier, 0, 0, &mediatype2);
4856 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4857 hr = IMFMediaType_IsEqual(mediatype2, mediatype, &flags);
4858 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4859 IMFMediaType_Release(mediatype2);
4861 hr = IMFTransform_GetInputStatus(copier, 0, &flags);
4862 ok(hr == S_OK, "Failed to get input status, hr %#x.\n", hr);
4863 ok(flags == MFT_INPUT_STATUS_ACCEPT_DATA, "Unexpected flags %#x.\n", flags);
4865 hr = IMFTransform_GetInputCurrentType(copier, 0, &mediatype2);
4866 ok(hr == S_OK, "Failed to get current type, hr %#x.\n", hr);
4867 IMFMediaType_Release(mediatype2);
4869 hr = IMFTransform_GetOutputStatus(copier, &flags);
4870 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#x.\n", hr);
4872 hr = IMFTransform_SetOutputType(copier, 0, mediatype, 0);
4873 ok(hr == S_OK, "Failed to set output type, hr %#x.\n", hr);
4875 hr = IMFTransform_GetOutputStatus(copier, &flags);
4876 ok(hr == S_OK, "Failed to get output status, hr %#x.\n", hr);
4877 ok(!flags, "Unexpected flags %#x.\n", flags);
4879 /* Pushing samples. */
4880 hr = MFCreateAlignedMemoryBuffer(output_info.cbSize, output_info.cbAlignment, &media_buffer);
4881 ok(hr == S_OK, "Failed to create media buffer, hr %#x.\n", hr);
4883 hr = IMFSample_AddBuffer(sample, media_buffer);
4884 ok(hr == S_OK, "Failed to add a buffer, hr %#x.\n", hr);
4885 IMFMediaBuffer_Release(media_buffer);
4887 EXPECT_REF(sample, 1);
4888 hr = IMFTransform_ProcessInput(copier, 0, sample, 0);
4889 ok(hr == S_OK, "Failed to process input, hr %#x.\n", hr);
4890 EXPECT_REF(sample, 2);
4892 hr = IMFTransform_GetInputStatus(copier, 0, &flags);
4893 ok(hr == S_OK, "Failed to get input status, hr %#x.\n", hr);
4894 ok(!flags, "Unexpected flags %#x.\n", flags);
4896 hr = IMFTransform_GetOutputStatus(copier, &flags);
4897 ok(hr == S_OK, "Failed to get output status, hr %#x.\n", hr);
4898 ok(flags == MFT_OUTPUT_STATUS_SAMPLE_READY, "Unexpected flags %#x.\n", flags);
4900 hr = IMFTransform_ProcessInput(copier, 0, sample, 0);
4901 ok(hr == MF_E_NOTACCEPTING, "Unexpected hr %#x.\n", hr);
4903 hr = IMFTransform_GetOutputStreamInfo(copier, 0, &output_info);
4904 ok(hr == S_OK, "Failed to get output info, hr %#x.\n", hr);
4906 hr = MFCreateAlignedMemoryBuffer(output_info.cbSize, output_info.cbAlignment, &media_buffer);
4907 ok(hr == S_OK, "Failed to create media buffer, hr %#x.\n", hr);
4909 hr = MFCreateSample(&client_sample);
4910 ok(hr == S_OK, "Failed to create a sample, hr %#x.\n", hr);
4912 hr = IMFSample_AddBuffer(client_sample, media_buffer);
4913 ok(hr == S_OK, "Failed to add a buffer, hr %#x.\n", hr);
4914 IMFMediaBuffer_Release(media_buffer);
4916 status = 0;
4917 memset(&buffer, 0, sizeof(buffer));
4918 buffer.pSample = client_sample;
4919 hr = IMFTransform_ProcessOutput(copier, 0, 1, &buffer, &status);
4920 ok(hr == S_OK, "Failed to get output, hr %#x.\n", hr);
4921 EXPECT_REF(sample, 1);
4923 hr = IMFTransform_ProcessOutput(copier, 0, 1, &buffer, &status);
4924 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "Failed to get output, hr %#x.\n", hr);
4926 /* Flushing. */
4927 hr = IMFTransform_ProcessInput(copier, 0, sample, 0);
4928 ok(hr == S_OK, "Failed to process input, hr %#x.\n", hr);
4929 EXPECT_REF(sample, 2);
4931 hr = IMFTransform_ProcessMessage(copier, MFT_MESSAGE_COMMAND_FLUSH, 0);
4932 ok(hr == S_OK, "Failed to flush, hr %#x.\n", hr);
4933 EXPECT_REF(sample, 1);
4935 IMFSample_Release(sample);
4936 IMFSample_Release(client_sample);
4938 IMFMediaType_Release(mediatype);
4939 IMFTransform_Release(copier);
4942 struct sample_metadata
4944 unsigned int flags;
4945 LONGLONG duration;
4946 LONGLONG time;
4949 static void sample_copier_process(IMFTransform *copier, IMFMediaBuffer *input_buffer,
4950 IMFMediaBuffer *output_buffer, const struct sample_metadata *md)
4952 static const struct sample_metadata zero_md = { 0, ~0u, ~0u };
4953 IMFSample *input_sample, *output_sample;
4954 MFT_OUTPUT_DATA_BUFFER buffer;
4955 unsigned int flags;
4956 LONGLONG time;
4957 DWORD status;
4958 HRESULT hr;
4960 hr = MFCreateSample(&input_sample);
4961 ok(hr == S_OK, "Failed to create a sample, hr %#x.\n", hr);
4963 if (md)
4965 hr = IMFSample_SetSampleFlags(input_sample, md->flags);
4966 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4968 hr = IMFSample_SetSampleTime(input_sample, md->time);
4969 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4971 hr = IMFSample_SetSampleDuration(input_sample, md->duration);
4972 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4975 hr = MFCreateSample(&output_sample);
4976 ok(hr == S_OK, "Failed to create a sample, hr %#x.\n", hr);
4978 hr = IMFSample_SetSampleFlags(output_sample, ~0u);
4979 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4981 hr = IMFSample_SetSampleTime(output_sample, ~0u);
4982 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4984 hr = IMFSample_SetSampleDuration(output_sample, ~0u);
4985 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4987 hr = IMFSample_AddBuffer(input_sample, input_buffer);
4988 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4990 hr = IMFSample_AddBuffer(output_sample, output_buffer);
4991 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4993 hr = IMFTransform_ProcessInput(copier, 0, input_sample, 0);
4994 ok(hr == S_OK, "Failed to process input, hr %#x.\n", hr);
4996 status = 0;
4997 memset(&buffer, 0, sizeof(buffer));
4998 buffer.pSample = output_sample;
4999 hr = IMFTransform_ProcessOutput(copier, 0, 1, &buffer, &status);
5000 ok(hr == S_OK, "Failed to get output, hr %#x.\n", hr);
5002 if (!md) md = &zero_md;
5004 hr = IMFSample_GetSampleFlags(output_sample, &flags);
5005 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
5006 ok(md->flags == flags, "Unexpected flags.\n");
5007 hr = IMFSample_GetSampleTime(output_sample, &time);
5008 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
5009 ok(md->time == time, "Unexpected time.\n");
5010 hr = IMFSample_GetSampleDuration(output_sample, &time);
5011 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
5012 ok(md->duration == time, "Unexpected duration.\n");
5014 IMFSample_Release(input_sample);
5015 IMFSample_Release(output_sample);
5018 static void test_sample_copier_output_processing(void)
5020 IMFMediaBuffer *input_buffer, *output_buffer;
5021 MFT_OUTPUT_STREAM_INFO output_info;
5022 struct sample_metadata md;
5023 IMFMediaType *mediatype;
5024 IMFTransform *copier;
5025 DWORD max_length;
5026 HRESULT hr;
5027 BYTE *ptr;
5029 if (!pMFCreateSampleCopierMFT)
5030 return;
5032 hr = pMFCreateSampleCopierMFT(&copier);
5033 ok(hr == S_OK, "Failed to create sample copier, hr %#x.\n", hr);
5035 /* Configure for 16 x 16 of D3DFMT_X8R8G8B8. */
5036 hr = MFCreateMediaType(&mediatype);
5037 ok(hr == S_OK, "Failed to create media type, hr %#x.\n", hr);
5039 hr = IMFMediaType_SetGUID(mediatype, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
5040 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
5042 hr = IMFMediaType_SetGUID(mediatype, &MF_MT_SUBTYPE, &MFVideoFormat_RGB32);
5043 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
5045 hr = IMFMediaType_SetUINT64(mediatype, &MF_MT_FRAME_SIZE, ((UINT64)16) << 32 | 16);
5046 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
5048 hr = IMFTransform_SetInputType(copier, 0, mediatype, 0);
5049 ok(hr == S_OK, "Failed to set input type, hr %#x.\n", hr);
5051 hr = IMFTransform_SetOutputType(copier, 0, mediatype, 0);
5052 ok(hr == S_OK, "Failed to set input type, hr %#x.\n", hr);
5054 /* Source and destination are linear buffers, destination is twice as large. */
5055 hr = IMFTransform_GetOutputStreamInfo(copier, 0, &output_info);
5056 ok(hr == S_OK, "Failed to get output info, hr %#x.\n", hr);
5058 hr = MFCreateAlignedMemoryBuffer(output_info.cbSize, output_info.cbAlignment, &output_buffer);
5059 ok(hr == S_OK, "Failed to create media buffer, hr %#x.\n", hr);
5061 hr = IMFMediaBuffer_Lock(output_buffer, &ptr, &max_length, NULL);
5062 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
5063 memset(ptr, 0xcc, max_length);
5064 hr = IMFMediaBuffer_Unlock(output_buffer);
5065 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
5067 hr = MFCreateAlignedMemoryBuffer(output_info.cbSize, output_info.cbAlignment, &input_buffer);
5068 ok(hr == S_OK, "Failed to create media buffer, hr %#x.\n", hr);
5070 hr = IMFMediaBuffer_Lock(input_buffer, &ptr, &max_length, NULL);
5071 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
5072 memset(ptr, 0xaa, max_length);
5073 hr = IMFMediaBuffer_Unlock(input_buffer);
5074 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
5075 hr = IMFMediaBuffer_SetCurrentLength(input_buffer, 4);
5076 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
5078 sample_copier_process(copier, input_buffer, output_buffer, NULL);
5080 hr = IMFMediaBuffer_Lock(output_buffer, &ptr, &max_length, NULL);
5081 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
5082 ok(ptr[0] == 0xaa && ptr[4] == 0xcc, "Unexpected buffer contents.\n");
5084 hr = IMFMediaBuffer_Unlock(output_buffer);
5085 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
5087 md.flags = 123;
5088 md.time = 10;
5089 md.duration = 2;
5090 sample_copier_process(copier, input_buffer, output_buffer, &md);
5092 IMFMediaBuffer_Release(input_buffer);
5093 IMFMediaBuffer_Release(output_buffer);
5095 IMFMediaType_Release(mediatype);
5096 IMFTransform_Release(copier);
5099 static void test_MFGetTopoNodeCurrentType(void)
5101 IMFMediaType *media_type, *media_type2;
5102 IMFTopologyNode *node;
5103 HRESULT hr;
5105 if (!pMFGetTopoNodeCurrentType)
5107 win_skip("MFGetTopoNodeCurrentType() is unsupported.\n");
5108 return;
5111 /* Tee node. */
5112 hr = MFCreateTopologyNode(MF_TOPOLOGY_TEE_NODE, &node);
5113 ok(hr == S_OK, "Failed to create a node, hr %#x.\n", hr);
5115 hr = pMFGetTopoNodeCurrentType(node, 0, TRUE, &media_type);
5116 ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
5118 hr = pMFGetTopoNodeCurrentType(node, 0, FALSE, &media_type);
5119 ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
5121 hr = MFCreateMediaType(&media_type2);
5122 ok(hr == S_OK, "Failed to create media type, hr %#x.\n", hr);
5124 hr = IMFMediaType_SetGUID(media_type2, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
5125 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
5127 /* Input type returned, if set. */
5128 hr = IMFTopologyNode_SetInputPrefType(node, 0, media_type2);
5129 ok(hr == S_OK, "Failed to set media type, hr %#x.\n", hr);
5131 hr = pMFGetTopoNodeCurrentType(node, 0, FALSE, &media_type);
5132 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
5133 ok(media_type == media_type2, "Unexpected pointer.\n");
5134 IMFMediaType_Release(media_type);
5136 hr = IMFTopologyNode_SetInputPrefType(node, 0, NULL);
5137 ok(hr == S_OK, "Failed to set media type, hr %#x.\n", hr);
5139 hr = pMFGetTopoNodeCurrentType(node, 0, FALSE, &media_type);
5140 ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
5142 /* Set second output. */
5143 hr = IMFTopologyNode_SetOutputPrefType(node, 1, media_type2);
5144 ok(hr == S_OK, "Failed to set media type, hr %#x.\n", hr);
5146 hr = pMFGetTopoNodeCurrentType(node, 0, FALSE, &media_type);
5147 ok(hr == E_FAIL, "Unexpected hr %#x.\n", hr);
5149 hr = IMFTopologyNode_SetOutputPrefType(node, 1, NULL);
5150 ok(hr == S_OK, "Failed to set media type, hr %#x.\n", hr);
5152 /* Set first output. */
5153 hr = IMFTopologyNode_SetOutputPrefType(node, 0, media_type2);
5154 ok(hr == S_OK, "Failed to set media type, hr %#x.\n", hr);
5156 hr = pMFGetTopoNodeCurrentType(node, 0, FALSE, &media_type);
5157 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
5158 ok(media_type == media_type2, "Unexpected pointer.\n");
5159 IMFMediaType_Release(media_type);
5161 hr = IMFTopologyNode_SetOutputPrefType(node, 0, NULL);
5162 ok(hr == S_OK, "Failed to set media type, hr %#x.\n", hr);
5164 /* Set primary output. */
5165 hr = IMFTopologyNode_SetOutputPrefType(node, 1, media_type2);
5166 ok(hr == S_OK, "Failed to set media type, hr %#x.\n", hr);
5168 hr = IMFTopologyNode_SetUINT32(node, &MF_TOPONODE_PRIMARYOUTPUT, 1);
5169 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
5171 hr = pMFGetTopoNodeCurrentType(node, 0, FALSE, &media_type);
5172 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
5173 ok(media_type == media_type2, "Unexpected pointer.\n");
5174 IMFMediaType_Release(media_type);
5176 hr = pMFGetTopoNodeCurrentType(node, 0, TRUE, &media_type);
5177 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
5178 ok(media_type == media_type2, "Unexpected pointer.\n");
5179 IMFMediaType_Release(media_type);
5181 IMFTopologyNode_Release(node);
5182 IMFMediaType_Release(media_type2);
5185 static void init_functions(void)
5187 HMODULE mod = GetModuleHandleA("mf.dll");
5189 #define X(f) p##f = (void*)GetProcAddress(mod, #f)
5190 X(MFCreateSampleCopierMFT);
5191 X(MFGetTopoNodeCurrentType);
5192 #undef X
5195 static void test_MFRequireProtectedEnvironment(void)
5197 IMFPresentationDescriptor *pd;
5198 IMFMediaType *mediatype;
5199 IMFStreamDescriptor *sd;
5200 HRESULT hr;
5202 hr = MFCreateMediaType(&mediatype);
5203 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
5205 hr = MFCreateStreamDescriptor(0, 1, &mediatype, &sd);
5206 ok(hr == S_OK, "Failed to create stream descriptor, hr %#x.\n", hr);
5208 hr = MFCreatePresentationDescriptor(1, &sd, &pd);
5209 ok(hr == S_OK, "Failed to create presentation descriptor, hr %#x.\n", hr);
5211 hr = IMFPresentationDescriptor_SelectStream(pd, 0);
5212 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
5214 hr = MFRequireProtectedEnvironment(pd);
5215 ok(hr == S_FALSE, "Unexpected hr %#x.\n", hr);
5217 hr = IMFStreamDescriptor_SetUINT32(sd, &MF_SD_PROTECTED, 1);
5218 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
5220 hr = MFRequireProtectedEnvironment(pd);
5221 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
5223 hr = IMFPresentationDescriptor_DeselectStream(pd, 0);
5224 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
5226 hr = MFRequireProtectedEnvironment(pd);
5227 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
5229 IMFStreamDescriptor_Release(sd);
5230 IMFPresentationDescriptor_Release(pd);
5233 START_TEST(mf)
5235 init_functions();
5237 if (is_vista())
5239 win_skip("Skipping tests on Vista.\n");
5240 return;
5243 test_topology();
5244 test_topology_tee_node();
5245 test_topology_loader();
5246 test_topology_loader_evr();
5247 test_MFGetService();
5248 test_sequencer_source();
5249 test_media_session();
5250 test_MFShutdownObject();
5251 test_presentation_clock();
5252 test_sample_grabber();
5253 test_sample_grabber_is_mediatype_supported();
5254 test_video_processor();
5255 test_quality_manager();
5256 test_sar();
5257 test_evr();
5258 test_MFCreateSimpleTypeHandler();
5259 test_MFGetSupportedMimeTypes();
5260 test_MFGetSupportedSchemes();
5261 test_sample_copier();
5262 test_sample_copier_output_processing();
5263 test_MFGetTopoNodeCurrentType();
5264 test_MFRequireProtectedEnvironment();