winegstreamer: Return S_OK from H264 decoder ProcessMessage.
[wine.git] / dlls / mf / tests / mf.c
blob31a84e47bc1085985af8158cf2eb06d997062e30
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 "mediaobj.h"
32 #include "ole2.h"
33 #include "wmcodecdsp.h"
34 #include "propvarutil.h"
36 DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0);
37 DEFINE_GUID(MFVideoFormat_P208, 0x38303250, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
38 DEFINE_GUID(MFVideoFormat_ABGR32, 0x00000020, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
40 #undef INITGUID
41 #include <guiddef.h>
42 #include "mfapi.h"
43 #include "mferror.h"
44 #include "mfidl.h"
45 #include "initguid.h"
46 #include "uuids.h"
47 #include "mmdeviceapi.h"
48 #include "audioclient.h"
49 #include "evr.h"
50 #include "d3d9.h"
51 #include "evr9.h"
53 #include "wine/test.h"
55 static HRESULT (WINAPI *pMFCreateSampleCopierMFT)(IMFTransform **copier);
56 static HRESULT (WINAPI *pMFGetTopoNodeCurrentType)(IMFTopologyNode *node, DWORD stream, BOOL output, IMFMediaType **type);
58 static BOOL is_vista(void)
60 return !pMFGetTopoNodeCurrentType;
63 #define EXPECT_REF(obj,ref) _expect_ref((IUnknown*)obj, ref, __LINE__)
64 static void _expect_ref(IUnknown* obj, ULONG expected_refcount, int line)
66 ULONG refcount;
67 IUnknown_AddRef(obj);
68 refcount = IUnknown_Release(obj);
69 ok_(__FILE__, line)(refcount == expected_refcount, "Unexpected refcount %ld, expected %ld.\n", refcount,
70 expected_refcount);
73 #define check_interface(a, b, c) check_interface_(__LINE__, a, b, c)
74 static void check_interface_(unsigned int line, void *iface_ptr, REFIID iid, BOOL supported)
76 IUnknown *iface = iface_ptr;
77 HRESULT hr, expected_hr;
78 IUnknown *unk;
80 expected_hr = supported ? S_OK : E_NOINTERFACE;
82 hr = IUnknown_QueryInterface(iface, iid, (void **)&unk);
83 ok_(__FILE__, line)(hr == expected_hr, "Got hr %#lx, expected %#lx.\n", hr, expected_hr);
84 if (SUCCEEDED(hr))
85 IUnknown_Release(unk);
88 #define check_service_interface(a, b, c, d) check_service_interface_(__LINE__, a, b, c, d)
89 static void check_service_interface_(unsigned int line, void *iface_ptr, REFGUID service, REFIID iid, BOOL supported)
91 IUnknown *iface = iface_ptr;
92 HRESULT hr, expected_hr;
93 IUnknown *unk;
95 expected_hr = supported ? S_OK : E_NOINTERFACE;
97 hr = MFGetService(iface, service, iid, (void **)&unk);
98 ok_(__FILE__, line)(hr == expected_hr, "Got hr %#lx, expected %#lx.\n", hr, expected_hr);
99 if (SUCCEEDED(hr))
100 IUnknown_Release(unk);
103 struct attribute_desc
105 const GUID *key;
106 const char *name;
107 PROPVARIANT value;
108 BOOL ratio;
109 BOOL todo;
110 BOOL todo_value;
112 typedef struct attribute_desc media_type_desc[32];
114 #define ATTR_GUID(k, g, ...) {.key = &k, .name = #k, {.vt = VT_CLSID, .puuid = (GUID *)&g}, __VA_ARGS__ }
115 #define ATTR_UINT32(k, v, ...) {.key = &k, .name = #k, {.vt = VT_UI4, .ulVal = v}, __VA_ARGS__ }
116 #define ATTR_BLOB(k, p, n, ...) {.key = &k, .name = #k, {.vt = VT_VECTOR | VT_UI1, .caub = {.pElems = (void *)p, .cElems = n}}, __VA_ARGS__ }
117 #define ATTR_RATIO(k, n, d, ...) {.key = &k, .name = #k, {.vt = VT_UI8, .uhVal = {.HighPart = n, .LowPart = d}}, .ratio = TRUE, __VA_ARGS__ }
118 #define ATTR_UINT64(k, v, ...) {.key = &k, .name = #k, {.vt = VT_UI8, .uhVal = {.QuadPart = v}}, __VA_ARGS__ }
120 #define check_media_type(a, b, c) check_attributes_(__LINE__, (IMFAttributes *)a, b, c)
121 #define check_attributes(a, b, c) check_attributes_(__LINE__, a, b, c)
122 static void check_attributes_(int line, IMFAttributes *attributes, const struct attribute_desc *desc, ULONG limit)
124 char buffer[256], *buf = buffer;
125 PROPVARIANT value;
126 int i, j, ret;
127 HRESULT hr;
129 for (i = 0; i < limit && desc[i].key; ++i)
131 hr = IMFAttributes_GetItem(attributes, desc[i].key, &value);
132 todo_wine_if(desc[i].todo)
133 ok_(__FILE__, line)(hr == S_OK, "%s missing, hr %#lx\n", debugstr_a(desc[i].name), hr);
134 if (hr != S_OK) continue;
136 switch (value.vt)
138 default: sprintf(buffer, "??"); break;
139 case VT_CLSID: sprintf(buffer, "%s", debugstr_guid(value.puuid)); break;
140 case VT_UI4: sprintf(buffer, "%lu", value.ulVal); break;
141 case VT_UI8:
142 if (desc[i].ratio)
143 sprintf(buffer, "%lu:%lu", value.uhVal.HighPart, value.uhVal.LowPart);
144 else
145 sprintf(buffer, "%I64u", value.uhVal.QuadPart);
146 break;
147 case VT_VECTOR | VT_UI1:
148 buf += sprintf(buf, "size %lu, data {", value.caub.cElems);
149 for (j = 0; j < 16 && j < value.caub.cElems; ++j)
150 buf += sprintf(buf, "0x%02x,", value.caub.pElems[j]);
151 if (value.caub.cElems > 16)
152 buf += sprintf(buf, "...}");
153 else
154 buf += sprintf(buf - (j ? 1 : 0), "}");
155 break;
158 ret = PropVariantCompareEx(&value, &desc[i].value, 0, 0);
159 todo_wine_if(desc[i].todo_value)
160 ok_(__FILE__, line)(ret == 0, "%s mismatch, type %u, value %s\n",
161 debugstr_a(desc[i].name), value.vt, buffer);
165 static HWND create_window(void)
167 RECT r = {0, 0, 640, 480};
169 AdjustWindowRect(&r, WS_OVERLAPPEDWINDOW | WS_VISIBLE, FALSE);
171 return CreateWindowA("static", "mf_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
172 0, 0, r.right - r.left, r.bottom - r.top, NULL, NULL, NULL, NULL);
175 static HRESULT WINAPI test_unk_QueryInterface(IUnknown *iface, REFIID riid, void **obj)
177 if (IsEqualIID(riid, &IID_IUnknown))
179 *obj = iface;
180 IUnknown_AddRef(iface);
181 return S_OK;
184 *obj = NULL;
185 return E_NOINTERFACE;
188 static ULONG WINAPI test_unk_AddRef(IUnknown *iface)
190 return 2;
193 static ULONG WINAPI test_unk_Release(IUnknown *iface)
195 return 1;
198 static const IUnknownVtbl test_unk_vtbl =
200 test_unk_QueryInterface,
201 test_unk_AddRef,
202 test_unk_Release,
205 static void test_topology(void)
207 IMFMediaType *mediatype, *mediatype2, *mediatype3;
208 IMFCollection *collection, *collection2;
209 IUnknown test_unk2 = { &test_unk_vtbl };
210 IUnknown test_unk = { &test_unk_vtbl };
211 IMFTopologyNode *node, *node2, *node3;
212 IMFTopology *topology, *topology2;
213 DWORD size, io_count, index;
214 MF_TOPOLOGY_TYPE node_type;
215 IUnknown *object;
216 WORD node_count;
217 UINT32 count;
218 HRESULT hr;
219 TOPOID id;
221 hr = MFCreateTopology(NULL);
222 ok(hr == E_POINTER, "got %#lx\n", hr);
224 hr = MFCreateTopology(&topology);
225 ok(hr == S_OK, "Failed to create topology, hr %#lx.\n", hr);
226 hr = IMFTopology_GetTopologyID(topology, &id);
227 ok(hr == S_OK, "Failed to get id, hr %#lx.\n", hr);
228 ok(id == 1, "Unexpected id.\n");
230 hr = MFCreateTopology(&topology2);
231 ok(hr == S_OK, "Failed to create topology, hr %#lx.\n", hr);
232 hr = IMFTopology_GetTopologyID(topology2, &id);
233 ok(hr == S_OK, "Failed to get id, hr %#lx.\n", hr);
234 ok(id == 2, "Unexpected id.\n");
236 IMFTopology_Release(topology);
238 hr = MFCreateTopology(&topology);
239 ok(hr == S_OK, "Failed to create topology, hr %#lx.\n", hr);
240 hr = IMFTopology_GetTopologyID(topology, &id);
241 ok(hr == S_OK, "Failed to get id, hr %#lx.\n", hr);
242 ok(id == 3, "Unexpected id.\n");
244 IMFTopology_Release(topology2);
246 /* No attributes by default. */
247 for (node_type = MF_TOPOLOGY_OUTPUT_NODE; node_type < MF_TOPOLOGY_TEE_NODE; ++node_type)
249 hr = MFCreateTopologyNode(node_type, &node);
250 ok(hr == S_OK, "Failed to create a node for type %d, hr %#lx.\n", node_type, hr);
251 hr = IMFTopologyNode_GetCount(node, &count);
252 ok(hr == S_OK, "Failed to get attribute count, hr %#lx.\n", hr);
253 ok(!count, "Unexpected attribute count %u.\n", count);
254 IMFTopologyNode_Release(node);
257 hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, NULL);
258 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
260 hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, &node);
261 ok(hr == S_OK, "Failed to create topology node, hr %#lx.\n", hr);
263 hr = MFCreateTopologyNode(MF_TOPOLOGY_TEE_NODE, &node2);
264 ok(hr == S_OK, "Failed to create topology node, hr %#lx.\n", hr);
266 hr = IMFTopologyNode_GetTopoNodeID(node, &id);
267 ok(hr == S_OK, "Failed to get node id, hr %#lx.\n", hr);
268 ok(((id >> 32) == GetCurrentProcessId()) && !!(id & 0xffff), "Unexpected node id %s.\n", wine_dbgstr_longlong(id));
270 hr = IMFTopologyNode_SetTopoNodeID(node2, id);
271 ok(hr == S_OK, "Failed to set node id, hr %#lx.\n", hr);
273 hr = IMFTopology_GetNodeCount(topology, NULL);
274 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
276 hr = IMFTopology_AddNode(topology, NULL);
277 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
279 node_count = 1;
280 hr = IMFTopology_GetNodeCount(topology, &node_count);
281 ok(hr == S_OK, "Failed to get node count, hr %#lx.\n", hr);
282 ok(node_count == 0, "Unexpected node count %u.\n", node_count);
284 /* Same id, different nodes. */
285 hr = IMFTopology_AddNode(topology, node);
286 ok(hr == S_OK, "Failed to add a node, hr %#lx.\n", hr);
288 node_count = 0;
289 hr = IMFTopology_GetNodeCount(topology, &node_count);
290 ok(hr == S_OK, "Failed to get node count, hr %#lx.\n", hr);
291 ok(node_count == 1, "Unexpected node count %u.\n", node_count);
293 hr = IMFTopology_AddNode(topology, node2);
294 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
295 IMFTopologyNode_Release(node2);
297 hr = IMFTopology_GetNodeByID(topology, id, &node2);
298 ok(hr == S_OK, "Failed to get a node, hr %#lx.\n", hr);
299 ok(node2 == node, "Unexpected node.\n");
300 IMFTopologyNode_Release(node2);
302 /* Change node id, add it again. */
303 hr = IMFTopologyNode_SetTopoNodeID(node, ++id);
304 ok(hr == S_OK, "Failed to set node id, hr %#lx.\n", hr);
306 hr = IMFTopology_GetNodeByID(topology, id, &node2);
307 ok(hr == S_OK, "Failed to get a node, hr %#lx.\n", hr);
308 ok(node2 == node, "Unexpected node.\n");
309 IMFTopologyNode_Release(node2);
311 hr = IMFTopology_GetNodeByID(topology, id + 1, &node2);
312 ok(hr == MF_E_NOT_FOUND, "Unexpected hr %#lx.\n", hr);
314 hr = IMFTopology_AddNode(topology, node);
315 ok(hr == E_INVALIDARG, "Failed to add a node, hr %#lx.\n", hr);
317 hr = IMFTopology_GetNode(topology, 0, &node2);
318 ok(hr == S_OK, "Failed to get a node, hr %#lx.\n", hr);
319 ok(node2 == node, "Unexpected node.\n");
320 IMFTopologyNode_Release(node2);
322 hr = IMFTopology_GetNode(topology, 1, NULL);
323 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
325 hr = IMFTopology_GetNode(topology, 1, &node2);
326 ok(hr == MF_E_INVALIDINDEX, "Failed to get a node, hr %#lx.\n", hr);
328 hr = IMFTopology_GetNode(topology, -2, &node2);
329 ok(hr == MF_E_INVALIDINDEX, "Failed to get a node, hr %#lx.\n", hr);
331 hr = MFCreateTopologyNode(MF_TOPOLOGY_TEE_NODE, &node2);
332 ok(hr == S_OK, "Failed to create topology node, hr %#lx.\n", hr);
333 hr = IMFTopology_AddNode(topology, node2);
334 ok(hr == S_OK, "Failed to add a node, hr %#lx.\n", hr);
335 IMFTopologyNode_Release(node2);
337 node_count = 0;
338 hr = IMFTopology_GetNodeCount(topology, &node_count);
339 ok(hr == S_OK, "Failed to get node count, hr %#lx.\n", hr);
340 ok(node_count == 2, "Unexpected node count %u.\n", node_count);
342 /* Remove with detached node, existing id. */
343 hr = MFCreateTopologyNode(MF_TOPOLOGY_TEE_NODE, &node2);
344 ok(hr == S_OK, "Failed to create topology node, hr %#lx.\n", hr);
345 hr = IMFTopologyNode_SetTopoNodeID(node2, id);
346 ok(hr == S_OK, "Failed to set node id, hr %#lx.\n", hr);
347 hr = IMFTopology_RemoveNode(topology, node2);
348 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
349 IMFTopologyNode_Release(node2);
351 hr = IMFTopology_RemoveNode(topology, node);
352 ok(hr == S_OK, "Failed to remove a node, hr %#lx.\n", hr);
354 node_count = 0;
355 hr = IMFTopology_GetNodeCount(topology, &node_count);
356 ok(hr == S_OK, "Failed to get node count, hr %#lx.\n", hr);
357 ok(node_count == 1, "Unexpected node count %u.\n", node_count);
359 hr = IMFTopology_Clear(topology);
360 ok(hr == S_OK, "Failed to clear topology, hr %#lx.\n", hr);
362 node_count = 1;
363 hr = IMFTopology_GetNodeCount(topology, &node_count);
364 ok(hr == S_OK, "Failed to get node count, hr %#lx.\n", hr);
365 ok(node_count == 0, "Unexpected node count %u.\n", node_count);
367 hr = IMFTopology_Clear(topology);
368 ok(hr == S_OK, "Failed to clear topology, hr %#lx.\n", hr);
370 hr = IMFTopologyNode_SetTopoNodeID(node, 123);
371 ok(hr == S_OK, "Failed to set node id, hr %#lx.\n", hr);
373 IMFTopologyNode_Release(node);
375 /* Change id for attached node. */
376 hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, &node);
377 ok(hr == S_OK, "Failed to create topology node, hr %#lx.\n", hr);
379 hr = MFCreateTopologyNode(MF_TOPOLOGY_TEE_NODE, &node2);
380 ok(hr == S_OK, "Failed to create topology node, hr %#lx.\n", hr);
382 hr = IMFTopology_AddNode(topology, node);
383 ok(hr == S_OK, "Failed to add a node, hr %#lx.\n", hr);
385 hr = IMFTopology_AddNode(topology, node2);
386 ok(hr == S_OK, "Failed to add a node, hr %#lx.\n", hr);
388 hr = IMFTopologyNode_GetTopoNodeID(node, &id);
389 ok(hr == S_OK, "Failed to get node id, hr %#lx.\n", hr);
391 hr = IMFTopologyNode_SetTopoNodeID(node2, id);
392 ok(hr == S_OK, "Failed to get node id, hr %#lx.\n", hr);
394 hr = IMFTopology_GetNodeByID(topology, id, &node3);
395 ok(hr == S_OK, "Failed to get a node, hr %#lx.\n", hr);
396 ok(node3 == node, "Unexpected node.\n");
397 IMFTopologyNode_Release(node3);
399 IMFTopologyNode_Release(node);
400 IMFTopologyNode_Release(node2);
402 /* Source/output collections. */
403 hr = IMFTopology_Clear(topology);
404 ok(hr == S_OK, "Failed to clear topology, hr %#lx.\n", hr);
406 hr = IMFTopology_GetSourceNodeCollection(topology, NULL);
407 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
409 hr = IMFTopology_GetSourceNodeCollection(topology, &collection);
410 ok(hr == S_OK, "Failed to get source node collection, hr %#lx.\n", hr);
411 ok(!!collection, "Unexpected object pointer.\n");
413 hr = IMFTopology_GetSourceNodeCollection(topology, &collection2);
414 ok(hr == S_OK, "Failed to get source node collection, hr %#lx.\n", hr);
415 ok(!!collection2, "Unexpected object pointer.\n");
416 ok(collection2 != collection, "Expected cloned collection.\n");
418 hr = IMFCollection_GetElementCount(collection, &size);
419 ok(hr == S_OK, "Failed to get item count, hr %#lx.\n", hr);
420 ok(!size, "Unexpected item count.\n");
422 hr = IMFCollection_AddElement(collection, (IUnknown *)collection);
423 ok(hr == S_OK, "Failed to add element, hr %#lx.\n", hr);
425 hr = IMFCollection_GetElementCount(collection, &size);
426 ok(hr == S_OK, "Failed to get item count, hr %#lx.\n", hr);
427 ok(size == 1, "Unexpected item count.\n");
429 hr = IMFCollection_GetElementCount(collection2, &size);
430 ok(hr == S_OK, "Failed to get item count, hr %#lx.\n", hr);
431 ok(!size, "Unexpected item count.\n");
433 IMFCollection_Release(collection2);
434 IMFCollection_Release(collection);
436 /* Add some nodes. */
437 hr = IMFTopology_GetSourceNodeCollection(topology, NULL);
438 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
440 hr = IMFTopology_GetOutputNodeCollection(topology, NULL);
441 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
443 hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &node);
444 ok(hr == S_OK, "Failed to create a node, hr %#lx.\n", hr);
445 hr = IMFTopology_AddNode(topology, node);
446 ok(hr == S_OK, "Failed to add a node, hr %#lx.\n", hr);
447 IMFTopologyNode_Release(node);
449 hr = IMFTopology_GetSourceNodeCollection(topology, &collection);
450 ok(hr == S_OK, "Failed to get source node collection, hr %#lx.\n", hr);
451 ok(!!collection, "Unexpected object pointer.\n");
452 hr = IMFCollection_GetElementCount(collection, &size);
453 ok(hr == S_OK, "Failed to get item count, hr %#lx.\n", hr);
454 ok(size == 1, "Unexpected item count.\n");
455 IMFCollection_Release(collection);
457 hr = MFCreateTopologyNode(MF_TOPOLOGY_TEE_NODE, &node);
458 ok(hr == S_OK, "Failed to create a node, hr %#lx.\n", hr);
459 hr = IMFTopology_AddNode(topology, node);
460 ok(hr == S_OK, "Failed to add a node, hr %#lx.\n", hr);
461 IMFTopologyNode_Release(node);
463 hr = IMFTopology_GetSourceNodeCollection(topology, &collection);
464 ok(hr == S_OK, "Failed to get source node collection, hr %#lx.\n", hr);
465 ok(!!collection, "Unexpected object pointer.\n");
466 hr = IMFCollection_GetElementCount(collection, &size);
467 ok(hr == S_OK, "Failed to get item count, hr %#lx.\n", hr);
468 ok(size == 1, "Unexpected item count.\n");
469 IMFCollection_Release(collection);
471 hr = MFCreateTopologyNode(MF_TOPOLOGY_TRANSFORM_NODE, &node);
472 ok(hr == S_OK, "Failed to create a node, hr %#lx.\n", hr);
473 hr = IMFTopology_AddNode(topology, node);
474 ok(hr == S_OK, "Failed to add a node, hr %#lx.\n", hr);
475 IMFTopologyNode_Release(node);
477 hr = IMFTopology_GetSourceNodeCollection(topology, &collection);
478 ok(hr == S_OK, "Failed to get source node collection, hr %#lx.\n", hr);
479 ok(!!collection, "Unexpected object pointer.\n");
480 hr = IMFCollection_GetElementCount(collection, &size);
481 ok(hr == S_OK, "Failed to get item count, hr %#lx.\n", hr);
482 ok(size == 1, "Unexpected item count.\n");
483 IMFCollection_Release(collection);
485 hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, &node);
486 ok(hr == S_OK, "Failed to create a node, hr %#lx.\n", hr);
487 hr = IMFTopology_AddNode(topology, node);
488 ok(hr == S_OK, "Failed to add a node, hr %#lx.\n", hr);
490 /* Associated object. */
491 hr = IMFTopologyNode_SetObject(node, NULL);
492 ok(hr == S_OK, "Failed to set object, hr %#lx.\n", hr);
494 hr = IMFTopologyNode_GetObject(node, NULL);
495 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
497 object = (void *)0xdeadbeef;
498 hr = IMFTopologyNode_GetObject(node, &object);
499 ok(hr == E_FAIL, "Unexpected hr %#lx.\n", hr);
500 ok(!object, "Unexpected object %p.\n", object);
502 hr = IMFTopologyNode_SetObject(node, &test_unk);
503 ok(hr == S_OK, "Failed to set object, hr %#lx.\n", hr);
505 hr = IMFTopologyNode_GetObject(node, &object);
506 ok(hr == S_OK, "Failed to get object, hr %#lx.\n", hr);
507 ok(object == &test_unk, "Unexpected object %p.\n", object);
508 IUnknown_Release(object);
510 hr = IMFTopologyNode_SetObject(node, &test_unk2);
511 ok(hr == S_OK, "Failed to set object, hr %#lx.\n", hr);
513 hr = IMFTopologyNode_GetCount(node, &count);
514 ok(hr == S_OK, "Failed to get attribute count, hr %#lx.\n", hr);
515 ok(count == 0, "Unexpected attribute count %u.\n", count);
517 hr = IMFTopologyNode_SetGUID(node, &MF_TOPONODE_TRANSFORM_OBJECTID, &MF_TOPONODE_TRANSFORM_OBJECTID);
518 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
520 hr = IMFTopologyNode_SetObject(node, NULL);
521 ok(hr == S_OK, "Failed to set object, hr %#lx.\n", hr);
523 object = (void *)0xdeadbeef;
524 hr = IMFTopologyNode_GetObject(node, &object);
525 ok(hr == E_FAIL, "Unexpected hr %#lx.\n", hr);
526 ok(!object, "Unexpected object %p.\n", object);
528 hr = IMFTopologyNode_GetCount(node, &count);
529 ok(hr == S_OK, "Failed to get attribute count, hr %#lx.\n", hr);
530 ok(count == 1, "Unexpected attribute count %u.\n", count);
532 /* Preferred stream types. */
533 hr = IMFTopologyNode_GetInputCount(node, &io_count);
534 ok(hr == S_OK, "Failed to get input count, hr %#lx.\n", hr);
535 ok(io_count == 0, "Unexpected count %lu.\n", io_count);
537 hr = IMFTopologyNode_GetInputPrefType(node, 0, &mediatype);
538 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
540 hr = MFCreateMediaType(&mediatype);
541 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
543 hr = IMFTopologyNode_SetInputPrefType(node, 0, mediatype);
544 ok(hr == S_OK, "Failed to set preferred type, hr %#lx.\n", hr);
546 hr = IMFTopologyNode_GetInputPrefType(node, 0, &mediatype2);
547 ok(hr == S_OK, "Failed to get preferred type, hr %#lx.\n", hr);
548 ok(mediatype2 == mediatype, "Unexpected mediatype instance.\n");
549 IMFMediaType_Release(mediatype2);
551 hr = IMFTopologyNode_SetInputPrefType(node, 0, NULL);
552 ok(hr == S_OK, "Failed to set preferred type, hr %#lx.\n", hr);
554 hr = IMFTopologyNode_GetInputPrefType(node, 0, &mediatype2);
555 ok(hr == E_FAIL, "Unexpected hr %#lx.\n", hr);
556 ok(!mediatype2, "Unexpected mediatype instance.\n");
558 hr = IMFTopologyNode_SetInputPrefType(node, 1, mediatype);
559 ok(hr == S_OK, "Failed to set preferred type, hr %#lx.\n", hr);
561 hr = IMFTopologyNode_SetInputPrefType(node, 1, mediatype);
562 ok(hr == S_OK, "Failed to set preferred type, hr %#lx.\n", hr);
564 hr = IMFTopologyNode_GetInputCount(node, &io_count);
565 ok(hr == S_OK, "Failed to get input count, hr %#lx.\n", hr);
566 ok(io_count == 2, "Unexpected count %lu.\n", io_count);
568 hr = IMFTopologyNode_GetOutputCount(node, &io_count);
569 ok(hr == S_OK, "Failed to get input count, hr %#lx.\n", hr);
570 ok(io_count == 0, "Unexpected count %lu.\n", io_count);
572 hr = IMFTopologyNode_SetOutputPrefType(node, 0, mediatype);
573 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
575 IMFTopologyNode_Release(node);
577 /* Source node. */
578 hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &node);
579 ok(hr == S_OK, "Failed to create a node, hr %#lx.\n", hr);
581 hr = IMFTopologyNode_SetInputPrefType(node, 0, mediatype);
582 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
584 hr = IMFTopologyNode_SetOutputPrefType(node, 2, mediatype);
585 ok(hr == S_OK, "Failed to set preferred type, hr %#lx.\n", hr);
587 hr = IMFTopologyNode_GetOutputPrefType(node, 0, &mediatype2);
588 ok(hr == E_FAIL, "Failed to get preferred type, hr %#lx.\n", hr);
589 ok(!mediatype2, "Unexpected mediatype instance.\n");
591 hr = IMFTopologyNode_GetOutputCount(node, &io_count);
592 ok(hr == S_OK, "Failed to get output count, hr %#lx.\n", hr);
593 ok(io_count == 3, "Unexpected count %lu.\n", io_count);
595 IMFTopologyNode_Release(node);
597 /* Tee node. */
598 hr = MFCreateTopologyNode(MF_TOPOLOGY_TEE_NODE, &node);
599 ok(hr == S_OK, "Failed to create a node, hr %#lx.\n", hr);
601 hr = IMFTopologyNode_SetInputPrefType(node, 0, mediatype);
602 ok(hr == S_OK, "Failed to set preferred type, hr %#lx.\n", hr);
604 hr = IMFTopologyNode_GetInputPrefType(node, 0, &mediatype2);
605 ok(hr == S_OK, "Failed to get preferred type, hr %#lx.\n", hr);
606 ok(mediatype2 == mediatype, "Unexpected mediatype instance.\n");
607 IMFMediaType_Release(mediatype2);
609 hr = IMFTopologyNode_GetOutputPrefType(node, 0, &mediatype2);
610 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
612 hr = IMFTopologyNode_GetInputCount(node, &io_count);
613 ok(hr == S_OK, "Failed to get output count, hr %#lx.\n", hr);
614 ok(io_count == 0, "Unexpected count %lu.\n", io_count);
616 hr = IMFTopologyNode_SetInputPrefType(node, 1, mediatype);
617 ok(hr == MF_E_INVALIDTYPE, "Unexpected hr %#lx.\n", hr);
619 hr = IMFTopologyNode_SetInputPrefType(node, 3, mediatype);
620 ok(hr == MF_E_INVALIDTYPE, "Unexpected hr %#lx.\n", hr);
622 hr = IMFTopologyNode_SetOutputPrefType(node, 4, mediatype);
623 ok(hr == S_OK, "Failed to set preferred type, hr %#lx.\n", hr);
625 hr = IMFTopologyNode_GetOutputPrefType(node, 0, &mediatype2);
626 ok(hr == E_FAIL, "Unexpected hr %#lx.\n", hr);
628 hr = MFCreateMediaType(&mediatype2);
629 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
631 /* Changing output type does not change input type. */
632 hr = IMFTopologyNode_SetOutputPrefType(node, 4, mediatype2);
633 ok(hr == S_OK, "Failed to set preferred type, hr %#lx.\n", hr);
635 hr = IMFTopologyNode_GetInputPrefType(node, 0, &mediatype3);
636 ok(hr == S_OK, "Failed to get preferred type, hr %#lx.\n", hr);
637 ok(mediatype3 == mediatype, "Unexpected mediatype instance.\n");
638 IMFMediaType_Release(mediatype3);
640 IMFMediaType_Release(mediatype2);
642 hr = IMFTopologyNode_GetInputCount(node, &io_count);
643 ok(hr == S_OK, "Failed to get output count, hr %#lx.\n", hr);
644 ok(io_count == 0, "Unexpected count %lu.\n", io_count);
646 hr = IMFTopologyNode_GetOutputCount(node, &io_count);
647 ok(hr == S_OK, "Failed to get output count, hr %#lx.\n", hr);
648 ok(io_count == 5, "Unexpected count %lu.\n", io_count);
650 IMFTopologyNode_Release(node);
652 /* Transform node. */
653 hr = MFCreateTopologyNode(MF_TOPOLOGY_TRANSFORM_NODE, &node);
654 ok(hr == S_OK, "Failed to create a node, hr %#lx.\n", hr);
656 hr = IMFTopologyNode_SetInputPrefType(node, 3, mediatype);
657 ok(hr == S_OK, "Failed to set preferred type, hr %#lx.\n", hr);
659 hr = IMFTopologyNode_GetInputCount(node, &io_count);
660 ok(hr == S_OK, "Failed to get input count, hr %#lx.\n", hr);
661 ok(io_count == 4, "Unexpected count %lu.\n", io_count);
663 hr = IMFTopologyNode_SetOutputPrefType(node, 4, mediatype);
664 ok(hr == S_OK, "Failed to set preferred type, hr %#lx.\n", hr);
666 hr = IMFTopologyNode_GetInputCount(node, &io_count);
667 ok(hr == S_OK, "Failed to get output count, hr %#lx.\n", hr);
668 ok(io_count == 4, "Unexpected count %lu.\n", io_count);
670 hr = IMFTopologyNode_GetOutputCount(node, &io_count);
671 ok(hr == S_OK, "Failed to get output count, hr %#lx.\n", hr);
672 ok(io_count == 5, "Unexpected count %lu.\n", io_count);
674 IMFTopologyNode_Release(node);
676 IMFMediaType_Release(mediatype);
678 hr = IMFTopology_GetOutputNodeCollection(topology, &collection);
679 ok(hr == S_OK || broken(hr == E_FAIL) /* before Win8 */, "Failed to get output node collection, hr %#lx.\n", hr);
680 if (SUCCEEDED(hr))
682 ok(!!collection, "Unexpected object pointer.\n");
683 hr = IMFCollection_GetElementCount(collection, &size);
684 ok(hr == S_OK, "Failed to get item count, hr %#lx.\n", hr);
685 ok(size == 1, "Unexpected item count.\n");
686 IMFCollection_Release(collection);
689 IMFTopology_Release(topology);
691 /* Connect nodes. */
692 hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &node);
693 ok(hr == S_OK, "Failed to create topology node, hr %#lx.\n", hr);
695 hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, &node2);
696 ok(hr == S_OK, "Failed to create topology node, hr %#lx.\n", hr);
698 EXPECT_REF(node, 1);
699 EXPECT_REF(node2, 1);
701 hr = IMFTopologyNode_ConnectOutput(node, 0, node2, 1);
702 ok(hr == S_OK, "Failed to connect nodes, hr %#lx.\n", hr);
704 EXPECT_REF(node, 2);
705 EXPECT_REF(node2, 2);
707 IMFTopologyNode_Release(node);
709 EXPECT_REF(node, 1);
710 EXPECT_REF(node2, 2);
712 IMFTopologyNode_Release(node2);
714 EXPECT_REF(node, 1);
715 EXPECT_REF(node2, 1);
717 hr = IMFTopologyNode_GetNodeType(node2, &node_type);
718 ok(hr == S_OK, "Failed to get node type, hr %#lx.\n", hr);
720 IMFTopologyNode_Release(node);
722 /* Connect within topology. */
723 hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &node);
724 ok(hr == S_OK, "Failed to create topology node, hr %#lx.\n", hr);
726 hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, &node2);
727 ok(hr == S_OK, "Failed to create topology node, hr %#lx.\n", hr);
729 hr = MFCreateTopology(&topology);
730 ok(hr == S_OK, "Failed to create topology, hr %#lx.\n", hr);
732 hr = IMFTopology_AddNode(topology, node);
733 ok(hr == S_OK, "Failed to add a node, hr %#lx.\n", hr);
735 hr = IMFTopology_AddNode(topology, node2);
736 ok(hr == S_OK, "Failed to add a node, hr %#lx.\n", hr);
738 EXPECT_REF(node, 2);
739 EXPECT_REF(node2, 2);
741 hr = IMFTopologyNode_ConnectOutput(node, 0, node2, 1);
742 ok(hr == S_OK, "Failed to connect nodes, hr %#lx.\n", hr);
744 EXPECT_REF(node, 3);
745 EXPECT_REF(node2, 3);
747 hr = IMFTopology_Clear(topology);
748 ok(hr == S_OK, "Failed to clear topology, hr %#lx.\n", hr);
750 EXPECT_REF(node, 1);
751 EXPECT_REF(node2, 1);
753 /* Removing connected node breaks connection. */
754 hr = IMFTopology_AddNode(topology, node);
755 ok(hr == S_OK, "Failed to add a node, hr %#lx.\n", hr);
757 hr = IMFTopology_AddNode(topology, node2);
758 ok(hr == S_OK, "Failed to add a node, hr %#lx.\n", hr);
760 hr = IMFTopologyNode_ConnectOutput(node, 0, node2, 1);
761 ok(hr == S_OK, "Failed to connect nodes, hr %#lx.\n", hr);
763 hr = IMFTopology_RemoveNode(topology, node);
764 ok(hr == S_OK, "Failed to remove a node, hr %#lx.\n", hr);
766 EXPECT_REF(node, 1);
767 EXPECT_REF(node2, 2);
769 hr = IMFTopologyNode_GetOutput(node, 0, &node3, &index);
770 ok(hr == MF_E_NOT_FOUND, "Unexpected hr %#lx.\n", hr);
772 hr = IMFTopology_AddNode(topology, node);
773 ok(hr == S_OK, "Failed to add a node, hr %#lx.\n", hr);
775 hr = IMFTopologyNode_ConnectOutput(node, 0, node2, 1);
776 ok(hr == S_OK, "Failed to connect nodes, hr %#lx.\n", hr);
778 hr = IMFTopology_RemoveNode(topology, node2);
779 ok(hr == S_OK, "Failed to remove a node, hr %#lx.\n", hr);
781 EXPECT_REF(node, 2);
782 EXPECT_REF(node2, 1);
784 IMFTopologyNode_Release(node);
785 IMFTopologyNode_Release(node2);
787 /* Cloning nodes of different types. */
788 hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &node);
789 ok(hr == S_OK, "Failed to create topology node, hr %#lx.\n", hr);
791 hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, &node2);
792 ok(hr == S_OK, "Failed to create topology node, hr %#lx.\n", hr);
794 hr = IMFTopologyNode_CloneFrom(node, node2);
795 ok(hr == MF_E_INVALIDREQUEST, "Unexpected hr %#lx.\n", hr);
797 IMFTopologyNode_Release(node2);
799 /* Cloning preferred types. */
800 hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &node2);
801 ok(hr == S_OK, "Failed to create topology node, hr %#lx.\n", hr);
803 hr = MFCreateMediaType(&mediatype);
804 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
806 hr = IMFTopologyNode_SetOutputPrefType(node2, 0, mediatype);
807 ok(hr == S_OK, "Failed to set preferred type, hr %#lx.\n", hr);
809 /* Vista checks for additional attributes. */
810 hr = IMFTopologyNode_CloneFrom(node, node2);
811 ok(hr == S_OK || broken(hr == MF_E_ATTRIBUTENOTFOUND) /* Vista */, "Failed to clone a node, hr %#lx.\n", hr);
813 hr = IMFTopologyNode_GetOutputPrefType(node, 0, &mediatype2);
814 ok(hr == S_OK, "Failed to get preferred type, hr %#lx.\n", hr);
815 ok(mediatype == mediatype2, "Unexpected media type.\n");
817 IMFMediaType_Release(mediatype2);
818 IMFMediaType_Release(mediatype);
820 IMFTopologyNode_Release(node2);
822 /* Existing preferred types are not cleared. */
823 hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &node2);
824 ok(hr == S_OK, "Failed to create topology node, hr %#lx.\n", hr);
826 hr = IMFTopologyNode_GetOutputCount(node, &io_count);
827 ok(hr == S_OK, "Failed to get output count, hr %#lx.\n", hr);
828 ok(io_count == 1, "Unexpected output count.\n");
830 hr = IMFTopologyNode_CloneFrom(node, node2);
831 ok(hr == S_OK || broken(hr == MF_E_ATTRIBUTENOTFOUND) /* Vista */, "Failed to clone a node, hr %#lx.\n", hr);
833 hr = IMFTopologyNode_GetOutputCount(node, &io_count);
834 ok(hr == S_OK, "Failed to get output count, hr %#lx.\n", hr);
835 ok(io_count == 1, "Unexpected output count.\n");
837 hr = IMFTopologyNode_GetOutputPrefType(node, 0, &mediatype2);
838 ok(hr == S_OK, "Failed to get preferred type, hr %#lx.\n", hr);
839 ok(!!mediatype2, "Unexpected media type.\n");
840 IMFMediaType_Release(mediatype2);
842 hr = IMFTopologyNode_CloneFrom(node2, node);
843 ok(hr == S_OK || broken(hr == MF_E_ATTRIBUTENOTFOUND) /* Vista */, "Failed to clone a node, hr %#lx.\n", hr);
845 hr = IMFTopologyNode_GetOutputCount(node2, &io_count);
846 ok(hr == S_OK, "Failed to get output count, hr %#lx.\n", hr);
847 ok(io_count == 1, "Unexpected output count.\n");
849 IMFTopologyNode_Release(node2);
850 IMFTopologyNode_Release(node);
852 /* Add one node, connect to another that hasn't been added. */
853 hr = IMFTopology_Clear(topology);
854 ok(hr == S_OK, "Failed to clear topology, hr %#lx.\n", hr);
856 hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &node);
857 ok(hr == S_OK, "Failed to create topology node, hr %#lx.\n", hr);
859 hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, &node2);
860 ok(hr == S_OK, "Failed to create topology node, hr %#lx.\n", hr);
862 hr = IMFTopology_AddNode(topology, node);
863 ok(hr == S_OK, "Failed to add a node, hr %#lx.\n", hr);
865 hr = IMFTopology_GetNodeCount(topology, &node_count);
866 ok(hr == S_OK, "Failed to get node count, hr %#lx.\n", hr);
867 ok(node_count == 1, "Unexpected node count.\n");
869 hr = IMFTopologyNode_ConnectOutput(node, 0, node2, 0);
870 ok(hr == S_OK, "Failed to connect nodes, hr %#lx.\n", hr);
872 hr = IMFTopology_GetNodeCount(topology, &node_count);
873 ok(hr == S_OK, "Failed to get node count, hr %#lx.\n", hr);
874 ok(node_count == 1, "Unexpected node count.\n");
876 IMFTopologyNode_Release(node);
877 IMFTopologyNode_Release(node2);
879 /* Add same node to different topologies. */
880 hr = IMFTopology_Clear(topology);
881 ok(hr == S_OK, "Failed to clear topology, hr %#lx.\n", hr);
883 hr = MFCreateTopology(&topology2);
884 ok(hr == S_OK, "Failed to create topology, hr %#lx.\n", hr);
886 hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &node);
887 ok(hr == S_OK, "Failed to create topology node, hr %#lx.\n", hr);
889 hr = IMFTopology_AddNode(topology, node);
890 ok(hr == S_OK, "Failed to add a node, hr %#lx.\n", hr);
891 EXPECT_REF(node, 2);
893 hr = IMFTopology_GetNodeCount(topology, &node_count);
894 ok(hr == S_OK, "Failed to get node count, hr %#lx.\n", hr);
895 ok(node_count == 1, "Unexpected node count.\n");
897 hr = IMFTopology_GetNodeCount(topology2, &node_count);
898 ok(hr == S_OK, "Failed to get node count, hr %#lx.\n", hr);
899 ok(node_count == 0, "Unexpected node count.\n");
901 hr = IMFTopology_AddNode(topology2, node);
902 ok(hr == S_OK, "Failed to add a node, hr %#lx.\n", hr);
903 EXPECT_REF(node, 3);
905 hr = IMFTopology_GetNodeCount(topology, &node_count);
906 ok(hr == S_OK, "Failed to get node count, hr %#lx.\n", hr);
907 ok(node_count == 1, "Unexpected node count.\n");
909 hr = IMFTopology_GetNodeCount(topology2, &node_count);
910 ok(hr == S_OK, "Failed to get node count, hr %#lx.\n", hr);
911 ok(node_count == 1, "Unexpected node count.\n");
913 IMFTopology_Release(topology2);
914 IMFTopology_Release(topology);
917 static void test_topology_tee_node(void)
919 IMFTopologyNode *src_node, *tee_node;
920 IMFMediaType *mediatype, *mediatype2;
921 IMFTopology *topology;
922 DWORD count;
923 HRESULT hr;
925 hr = MFCreateTopology(&topology);
926 ok(hr == S_OK, "Failed to create topology, hr %#lx.\n", hr);
928 hr = MFCreateMediaType(&mediatype);
929 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
931 hr = MFCreateTopologyNode(MF_TOPOLOGY_TEE_NODE, &tee_node);
932 ok(hr == S_OK, "Failed to create topology node, hr %#lx.\n", hr);
934 hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &src_node);
935 ok(hr == S_OK, "Failed to create topology node, hr %#lx.\n", hr);
937 hr = IMFTopologyNode_SetInputPrefType(tee_node, 0, mediatype);
938 ok(hr == S_OK, "Failed to set type, hr %#lx.\n", hr);
940 /* Even though tee node has only one input and source has only one output,
941 it's possible to connect to higher inputs/outputs. */
943 /* SRC(0) -> TEE(0) */
944 hr = IMFTopologyNode_ConnectOutput(src_node, 0, tee_node, 0);
945 ok(hr == S_OK, "Failed to connect nodes, hr %#lx.\n", hr);
947 hr = IMFTopologyNode_GetInputCount(tee_node, &count);
948 ok(hr == S_OK, "Failed to get count, hr %#lx.\n", hr);
949 ok(count == 1, "Unexpected count %lu.\n", count);
951 hr = IMFTopologyNode_GetInputPrefType(tee_node, 0, &mediatype2);
952 ok(hr == S_OK, "Failed to get type, hr %#lx.\n", hr);
953 ok(mediatype2 == mediatype, "Unexpected type.\n");
954 IMFMediaType_Release(mediatype2);
956 /* SRC(0) -> TEE(1) */
957 hr = IMFTopologyNode_ConnectOutput(src_node, 0, tee_node, 1);
958 ok(hr == S_OK, "Failed to connect nodes, hr %#lx.\n", hr);
960 hr = IMFTopologyNode_GetInputCount(tee_node, &count);
961 ok(hr == S_OK, "Failed to get count, hr %#lx.\n", hr);
962 ok(count == 2, "Unexpected count %lu.\n", count);
964 hr = IMFTopologyNode_SetInputPrefType(tee_node, 1, mediatype);
965 ok(hr == MF_E_INVALIDTYPE, "Unexpected hr %#lx.\n", hr);
967 /* SRC(1) -> TEE(1) */
968 hr = IMFTopologyNode_ConnectOutput(src_node, 1, tee_node, 1);
969 ok(hr == S_OK, "Failed to connect nodes, hr %#lx.\n", hr);
971 hr = IMFTopologyNode_GetOutputCount(src_node, &count);
972 ok(hr == S_OK, "Failed to get count, hr %#lx.\n", hr);
973 ok(count == 2, "Unexpected count %lu.\n", count);
975 IMFMediaType_Release(mediatype);
976 IMFTopologyNode_Release(src_node);
977 IMFTopologyNode_Release(tee_node);
978 IMFTopology_Release(topology);
981 static HRESULT WINAPI test_getservice_QI(IMFGetService *iface, REFIID riid, void **obj)
983 if (IsEqualIID(riid, &IID_IMFGetService) || IsEqualIID(riid, &IID_IUnknown))
985 *obj = iface;
986 return S_OK;
989 *obj = NULL;
990 return E_NOINTERFACE;
993 static ULONG WINAPI test_getservice_AddRef(IMFGetService *iface)
995 return 2;
998 static ULONG WINAPI test_getservice_Release(IMFGetService *iface)
1000 return 1;
1003 static HRESULT WINAPI test_getservice_GetService(IMFGetService *iface, REFGUID service, REFIID riid, void **obj)
1005 *obj = (void *)0xdeadbeef;
1006 return 0x83eddead;
1009 static const IMFGetServiceVtbl testmfgetservicevtbl =
1011 test_getservice_QI,
1012 test_getservice_AddRef,
1013 test_getservice_Release,
1014 test_getservice_GetService,
1017 static IMFGetService test_getservice = { &testmfgetservicevtbl };
1019 static HRESULT WINAPI testservice_QI(IUnknown *iface, REFIID riid, void **obj)
1021 if (IsEqualIID(riid, &IID_IUnknown))
1023 *obj = iface;
1024 return S_OK;
1027 *obj = NULL;
1029 if (IsEqualIID(riid, &IID_IMFGetService))
1030 return 0x82eddead;
1032 return E_NOINTERFACE;
1035 static HRESULT WINAPI testservice2_QI(IUnknown *iface, REFIID riid, void **obj)
1037 if (IsEqualIID(riid, &IID_IUnknown))
1039 *obj = iface;
1040 return S_OK;
1043 if (IsEqualIID(riid, &IID_IMFGetService))
1045 *obj = &test_getservice;
1046 return S_OK;
1049 *obj = NULL;
1050 return E_NOINTERFACE;
1053 static ULONG WINAPI testservice_AddRef(IUnknown *iface)
1055 return 2;
1058 static ULONG WINAPI testservice_Release(IUnknown *iface)
1060 return 1;
1063 static const IUnknownVtbl testservicevtbl =
1065 testservice_QI,
1066 testservice_AddRef,
1067 testservice_Release,
1070 static const IUnknownVtbl testservice2vtbl =
1072 testservice2_QI,
1073 testservice_AddRef,
1074 testservice_Release,
1077 static IUnknown testservice = { &testservicevtbl };
1078 static IUnknown testservice2 = { &testservice2vtbl };
1080 static void test_MFGetService(void)
1082 IUnknown *unk;
1083 HRESULT hr;
1085 hr = MFGetService(NULL, NULL, NULL, NULL);
1086 ok(hr == E_POINTER, "Unexpected return value %#lx.\n", hr);
1088 unk = (void *)0xdeadbeef;
1089 hr = MFGetService(NULL, NULL, NULL, (void **)&unk);
1090 ok(hr == E_POINTER, "Unexpected return value %#lx.\n", hr);
1091 ok(unk == (void *)0xdeadbeef, "Unexpected out object.\n");
1093 hr = MFGetService(&testservice, NULL, NULL, NULL);
1094 ok(hr == 0x82eddead, "Unexpected return value %#lx.\n", hr);
1096 unk = (void *)0xdeadbeef;
1097 hr = MFGetService(&testservice, NULL, NULL, (void **)&unk);
1098 ok(hr == 0x82eddead, "Unexpected return value %#lx.\n", hr);
1099 ok(unk == (void *)0xdeadbeef, "Unexpected out object.\n");
1101 unk = NULL;
1102 hr = MFGetService(&testservice2, NULL, NULL, (void **)&unk);
1103 ok(hr == 0x83eddead, "Unexpected return value %#lx.\n", hr);
1104 ok(unk == (void *)0xdeadbeef, "Unexpected out object.\n");
1107 static void test_sequencer_source(void)
1109 IMFSequencerSource *seq_source;
1110 HRESULT hr;
1112 hr = MFStartup(MF_VERSION, MFSTARTUP_FULL);
1113 ok(hr == S_OK, "Startup failure, hr %#lx.\n", hr);
1115 hr = MFCreateSequencerSource(NULL, &seq_source);
1116 ok(hr == S_OK, "Failed to create sequencer source, hr %#lx.\n", hr);
1118 check_interface(seq_source, &IID_IMFMediaSourceTopologyProvider, TRUE);
1120 IMFSequencerSource_Release(seq_source);
1122 hr = MFShutdown();
1123 ok(hr == S_OK, "Shutdown failure, hr %#lx.\n", hr);
1126 struct test_callback
1128 IMFAsyncCallback IMFAsyncCallback_iface;
1131 static HRESULT WINAPI testcallback_QueryInterface(IMFAsyncCallback *iface, REFIID riid, void **obj)
1133 if (IsEqualIID(riid, &IID_IMFAsyncCallback) ||
1134 IsEqualIID(riid, &IID_IUnknown))
1136 *obj = iface;
1137 IMFAsyncCallback_AddRef(iface);
1138 return S_OK;
1141 *obj = NULL;
1142 return E_NOINTERFACE;
1145 static ULONG WINAPI testcallback_AddRef(IMFAsyncCallback *iface)
1147 return 2;
1150 static ULONG WINAPI testcallback_Release(IMFAsyncCallback *iface)
1152 return 1;
1155 static HRESULT WINAPI testcallback_GetParameters(IMFAsyncCallback *iface, DWORD *flags, DWORD *queue)
1157 ok(flags != NULL && queue != NULL, "Unexpected arguments.\n");
1158 return E_NOTIMPL;
1161 static HRESULT WINAPI testcallback_Invoke(IMFAsyncCallback *iface, IMFAsyncResult *result)
1163 ok(result != NULL, "Unexpected result object.\n");
1165 return E_NOTIMPL;
1168 static const IMFAsyncCallbackVtbl testcallbackvtbl =
1170 testcallback_QueryInterface,
1171 testcallback_AddRef,
1172 testcallback_Release,
1173 testcallback_GetParameters,
1174 testcallback_Invoke,
1177 static void init_test_callback(struct test_callback *callback)
1179 callback->IMFAsyncCallback_iface.lpVtbl = &testcallbackvtbl;
1182 static void test_session_events(IMFMediaSession *session)
1184 struct test_callback callback, callback2;
1185 IMFAsyncResult *result;
1186 IMFMediaEvent *event;
1187 HRESULT hr;
1189 init_test_callback(&callback);
1190 init_test_callback(&callback2);
1192 hr = IMFMediaSession_GetEvent(session, MF_EVENT_FLAG_NO_WAIT, &event);
1193 ok(hr == MF_E_NO_EVENTS_AVAILABLE, "Unexpected hr %#lx.\n", hr);
1195 /* Async case. */
1196 hr = IMFMediaSession_BeginGetEvent(session, NULL, NULL);
1197 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
1199 hr = IMFMediaSession_BeginGetEvent(session, &callback.IMFAsyncCallback_iface, (IUnknown *)session);
1200 ok(hr == S_OK, "Failed to Begin*, hr %#lx.\n", hr);
1202 /* Same callback, same state. */
1203 hr = IMFMediaSession_BeginGetEvent(session, &callback.IMFAsyncCallback_iface, (IUnknown *)session);
1204 ok(hr == MF_S_MULTIPLE_BEGIN, "Unexpected hr %#lx.\n", hr);
1206 /* Same callback, different state. */
1207 hr = IMFMediaSession_BeginGetEvent(session, &callback.IMFAsyncCallback_iface, (IUnknown *)&callback.IMFAsyncCallback_iface);
1208 ok(hr == MF_E_MULTIPLE_BEGIN, "Unexpected hr %#lx.\n", hr);
1210 /* Different callback, same state. */
1211 hr = IMFMediaSession_BeginGetEvent(session, &callback2.IMFAsyncCallback_iface, (IUnknown *)session);
1212 ok(hr == MF_E_MULTIPLE_SUBSCRIBERS, "Unexpected hr %#lx.\n", hr);
1214 /* Different callback, different state. */
1215 hr = IMFMediaSession_BeginGetEvent(session, &callback2.IMFAsyncCallback_iface, (IUnknown *)&callback.IMFAsyncCallback_iface);
1216 ok(hr == MF_E_MULTIPLE_SUBSCRIBERS, "Unexpected hr %#lx.\n", hr);
1218 hr = MFCreateAsyncResult(NULL, &callback.IMFAsyncCallback_iface, NULL, &result);
1219 ok(hr == S_OK, "Failed to create result, hr %#lx.\n", hr);
1221 hr = IMFMediaSession_EndGetEvent(session, result, &event);
1222 ok(hr == E_FAIL, "Unexpected hr %#lx.\n", hr);
1224 /* Shutdown behavior. */
1225 hr = IMFMediaSession_Shutdown(session);
1226 ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr);
1229 static void test_media_session(void)
1231 IMFRateSupport *rate_support;
1232 IMFAttributes *attributes;
1233 IMFMediaSession *session;
1234 MFSHUTDOWN_STATUS status;
1235 IMFTopology *topology;
1236 IMFShutdown *shutdown;
1237 PROPVARIANT propvar;
1238 IMFGetService *gs;
1239 IMFClock *clock;
1240 DWORD caps;
1241 HRESULT hr;
1243 hr = MFStartup(MF_VERSION, MFSTARTUP_FULL);
1244 ok(hr == S_OK, "Startup failure, hr %#lx.\n", hr);
1246 hr = MFCreateMediaSession(NULL, &session);
1247 ok(hr == S_OK, "Failed to create media session, hr %#lx.\n", hr);
1249 check_interface(session, &IID_IMFGetService, TRUE);
1250 check_interface(session, &IID_IMFRateSupport, TRUE);
1251 check_interface(session, &IID_IMFRateControl, TRUE);
1252 check_interface(session, &IID_IMFAttributes, FALSE);
1253 check_interface(session, &IID_IMFTopologyNodeAttributeEditor, FALSE);
1254 check_interface(session, &IID_IMFLocalMFTRegistration, FALSE);
1255 check_service_interface(session, &MF_RATE_CONTROL_SERVICE, &IID_IMFRateSupport, TRUE);
1256 check_service_interface(session, &MF_RATE_CONTROL_SERVICE, &IID_IMFRateControl, TRUE);
1257 check_service_interface(session, &MF_TOPONODE_ATTRIBUTE_EDITOR_SERVICE, &IID_IMFTopologyNodeAttributeEditor, TRUE);
1258 check_service_interface(session, &MF_LOCAL_MFT_REGISTRATION_SERVICE, &IID_IMFLocalMFTRegistration, TRUE);
1260 hr = IMFMediaSession_GetClock(session, &clock);
1261 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1263 hr = IMFClock_QueryInterface(clock, &IID_IMFShutdown, (void **)&shutdown);
1264 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1266 hr = IMFShutdown_GetShutdownStatus(shutdown, &status);
1267 ok(hr == MF_E_INVALIDREQUEST, "Unexpected hr %#lx.\n", hr);
1269 hr = IMFMediaSession_Shutdown(session);
1270 ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr);
1272 check_interface(session, &IID_IMFGetService, TRUE);
1274 hr = IMFMediaSession_QueryInterface(session, &IID_IMFGetService, (void **)&gs);
1275 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1277 hr = IMFGetService_GetService(gs, &MF_RATE_CONTROL_SERVICE, &IID_IMFRateSupport, (void **)&rate_support);
1278 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
1280 IMFGetService_Release(gs);
1282 hr = IMFShutdown_GetShutdownStatus(shutdown, &status);
1283 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1284 ok(status == MFSHUTDOWN_COMPLETED, "Unexpected shutdown status %u.\n", status);
1286 IMFShutdown_Release(shutdown);
1288 hr = IMFMediaSession_ClearTopologies(session);
1289 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
1291 hr = IMFMediaSession_Start(session, &GUID_NULL, NULL);
1292 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
1294 propvar.vt = VT_EMPTY;
1295 hr = IMFMediaSession_Start(session, &GUID_NULL, &propvar);
1296 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
1298 hr = IMFMediaSession_Pause(session);
1299 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
1301 hr = IMFMediaSession_Stop(session);
1302 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
1304 hr = IMFMediaSession_Close(session);
1305 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
1307 hr = IMFMediaSession_GetClock(session, &clock);
1308 ok(hr == MF_E_SHUTDOWN || broken(hr == E_UNEXPECTED) /* Win7 */, "Unexpected hr %#lx.\n", hr);
1310 hr = IMFMediaSession_GetSessionCapabilities(session, &caps);
1311 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
1313 hr = IMFMediaSession_GetSessionCapabilities(session, NULL);
1314 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
1316 hr = IMFMediaSession_GetFullTopology(session, MFSESSION_GETFULLTOPOLOGY_CURRENT, 0, &topology);
1317 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
1319 hr = IMFMediaSession_Shutdown(session);
1320 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
1322 IMFMediaSession_Release(session);
1324 /* Custom topology loader, GUID is not registered. */
1325 hr = MFCreateAttributes(&attributes, 1);
1326 ok(hr == S_OK, "Failed to create attributes, hr %#lx.\n", hr);
1328 hr = IMFAttributes_SetGUID(attributes, &MF_SESSION_TOPOLOADER, &MF_SESSION_TOPOLOADER);
1329 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
1331 hr = MFCreateMediaSession(attributes, &session);
1332 ok(hr == S_OK, "Failed to create media session, hr %#lx.\n", hr);
1333 IMFMediaSession_Release(session);
1335 /* Disabled quality manager. */
1336 hr = IMFAttributes_SetGUID(attributes, &MF_SESSION_QUALITY_MANAGER, &GUID_NULL);
1337 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
1339 hr = MFCreateMediaSession(attributes, &session);
1340 ok(hr == S_OK, "Failed to create media session, hr %#lx.\n", hr);
1341 IMFMediaSession_Release(session);
1343 IMFAttributes_Release(attributes);
1345 /* Basic events behavior. */
1346 hr = MFCreateMediaSession(NULL, &session);
1347 ok(hr == S_OK, "Failed to create media session, hr %#lx.\n", hr);
1349 test_session_events(session);
1351 IMFMediaSession_Release(session);
1353 hr = MFShutdown();
1354 ok(hr == S_OK, "Shutdown failure, hr %#lx.\n", hr);
1357 static void test_media_session_rate_control(void)
1359 IMFRateControl *rate_control, *clock_rate_control;
1360 IMFPresentationClock *presentation_clock;
1361 IMFPresentationTimeSource *time_source;
1362 MFCLOCK_PROPERTIES clock_props;
1363 IMFRateSupport *rate_support;
1364 IMFMediaSession *session;
1365 IMFClock *clock;
1366 HRESULT hr;
1367 float rate;
1368 BOOL thin;
1370 hr = MFStartup(MF_VERSION, MFSTARTUP_FULL);
1371 ok(hr == S_OK, "Startup failure, hr %#lx.\n", hr);
1373 hr = MFCreateMediaSession(NULL, &session);
1374 ok(hr == S_OK, "Failed to create media session, hr %#lx.\n", hr);
1376 hr = MFGetService((IUnknown *)session, &MF_RATE_CONTROL_SERVICE, &IID_IMFRateSupport, (void **)&rate_support);
1377 ok(hr == S_OK, "Failed to get rate support interface, hr %#lx.\n", hr);
1379 hr = MFGetService((IUnknown *)session, &MF_RATE_CONTROL_SERVICE, &IID_IMFRateControl, (void **)&rate_control);
1380 ok(hr == S_OK, "Failed to get rate control interface, hr %#lx.\n", hr);
1382 hr = IMFRateControl_GetRate(rate_control, NULL, NULL);
1383 ok(FAILED(hr), "Unexpected hr %#lx.\n", hr);
1385 rate = 0.0f;
1386 hr = IMFRateControl_GetRate(rate_control, NULL, &rate);
1387 ok(hr == S_OK, "Failed to get playback rate, hr %#lx.\n", hr);
1388 ok(rate == 1.0f, "Unexpected rate %f.\n", rate);
1390 hr = IMFRateControl_GetRate(rate_control, &thin, NULL);
1391 ok(FAILED(hr), "Unexpected hr %#lx.\n", hr);
1393 thin = TRUE;
1394 rate = 0.0f;
1395 hr = IMFRateControl_GetRate(rate_control, &thin, &rate);
1396 ok(hr == S_OK, "Failed to get playback rate, hr %#lx.\n", hr);
1397 ok(!thin, "Unexpected thinning.\n");
1398 ok(rate == 1.0f, "Unexpected rate %f.\n", rate);
1400 hr = IMFMediaSession_GetClock(session, &clock);
1401 ok(hr == S_OK, "Failed to get clock, hr %#lx.\n", hr);
1403 hr = IMFClock_QueryInterface(clock, &IID_IMFPresentationClock, (void **)&presentation_clock);
1404 ok(hr == S_OK, "Failed to get rate control, hr %#lx.\n", hr);
1406 hr = IMFClock_QueryInterface(clock, &IID_IMFRateControl, (void **)&clock_rate_control);
1407 ok(hr == S_OK, "Failed to get rate control, hr %#lx.\n", hr);
1409 rate = 0.0f;
1410 hr = IMFRateControl_GetRate(clock_rate_control, NULL, &rate);
1411 ok(hr == S_OK, "Failed to get clock rate, hr %#lx.\n", hr);
1412 ok(rate == 1.0f, "Unexpected rate %f.\n", rate);
1414 hr = IMFRateControl_SetRate(clock_rate_control, FALSE, 1.5f);
1415 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#lx.\n", hr);
1417 hr = IMFRateControl_SetRate(rate_control, FALSE, 1.5f);
1418 ok(hr == S_OK, "Failed to set rate, hr %#lx.\n", hr);
1420 hr = IMFClock_GetProperties(clock, &clock_props);
1421 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#lx.\n", hr);
1423 hr = MFCreateSystemTimeSource(&time_source);
1424 ok(hr == S_OK, "Failed to create time source, hr %#lx.\n", hr);
1426 hr = IMFPresentationClock_SetTimeSource(presentation_clock, time_source);
1427 ok(hr == S_OK, "Failed to set time source, hr %#lx.\n", hr);
1429 hr = IMFRateControl_SetRate(rate_control, FALSE, 1.5f);
1430 ok(hr == S_OK, "Failed to set rate, hr %#lx.\n", hr);
1432 rate = 0.0f;
1433 hr = IMFRateControl_GetRate(clock_rate_control, NULL, &rate);
1434 ok(hr == S_OK, "Failed to get clock rate, hr %#lx.\n", hr);
1435 ok(rate == 1.0f, "Unexpected rate %f.\n", rate);
1437 IMFPresentationTimeSource_Release(time_source);
1439 IMFRateControl_Release(clock_rate_control);
1440 IMFPresentationClock_Release(presentation_clock);
1441 IMFClock_Release(clock);
1443 IMFRateControl_Release(rate_control);
1444 IMFRateSupport_Release(rate_support);
1446 IMFMediaSession_Release(session);
1448 hr = MFShutdown();
1449 ok(hr == S_OK, "Shutdown failure, hr %#lx.\n", hr);
1452 static HRESULT WINAPI test_grabber_callback_QueryInterface(IMFSampleGrabberSinkCallback *iface, REFIID riid,
1453 void **obj)
1455 if (IsEqualIID(riid, &IID_IMFSampleGrabberSinkCallback) ||
1456 IsEqualIID(riid, &IID_IMFClockStateSink) ||
1457 IsEqualIID(riid, &IID_IUnknown))
1459 *obj = iface;
1460 IMFSampleGrabberSinkCallback_AddRef(iface);
1461 return S_OK;
1464 *obj = NULL;
1465 return E_NOINTERFACE;
1468 static ULONG WINAPI test_grabber_callback_AddRef(IMFSampleGrabberSinkCallback *iface)
1470 return 2;
1473 static ULONG WINAPI test_grabber_callback_Release(IMFSampleGrabberSinkCallback *iface)
1475 return 1;
1478 static HRESULT WINAPI test_grabber_callback_OnClockStart(IMFSampleGrabberSinkCallback *iface, MFTIME systime,
1479 LONGLONG offset)
1481 return E_NOTIMPL;
1484 static HRESULT WINAPI test_grabber_callback_OnClockStop(IMFSampleGrabberSinkCallback *iface, MFTIME systime)
1486 return E_NOTIMPL;
1489 static HRESULT WINAPI test_grabber_callback_OnClockPause(IMFSampleGrabberSinkCallback *iface, MFTIME systime)
1491 return E_NOTIMPL;
1494 static HRESULT WINAPI test_grabber_callback_OnClockRestart(IMFSampleGrabberSinkCallback *iface, MFTIME systime)
1496 return E_NOTIMPL;
1499 static HRESULT WINAPI test_grabber_callback_OnClockSetRate(IMFSampleGrabberSinkCallback *iface, MFTIME systime, float rate)
1501 return E_NOTIMPL;
1504 static HRESULT WINAPI test_grabber_callback_OnSetPresentationClock(IMFSampleGrabberSinkCallback *iface,
1505 IMFPresentationClock *clock)
1507 return E_NOTIMPL;
1510 static HRESULT WINAPI test_grabber_callback_OnProcessSample(IMFSampleGrabberSinkCallback *iface, REFGUID major_type,
1511 DWORD sample_flags, LONGLONG sample_time, LONGLONG sample_duration, const BYTE *buffer, DWORD sample_size)
1513 return E_NOTIMPL;
1516 static HRESULT WINAPI test_grabber_callback_OnShutdown(IMFSampleGrabberSinkCallback *iface)
1518 return E_NOTIMPL;
1521 static const IMFSampleGrabberSinkCallbackVtbl test_grabber_callback_vtbl =
1523 test_grabber_callback_QueryInterface,
1524 test_grabber_callback_AddRef,
1525 test_grabber_callback_Release,
1526 test_grabber_callback_OnClockStart,
1527 test_grabber_callback_OnClockStop,
1528 test_grabber_callback_OnClockPause,
1529 test_grabber_callback_OnClockRestart,
1530 test_grabber_callback_OnClockSetRate,
1531 test_grabber_callback_OnSetPresentationClock,
1532 test_grabber_callback_OnProcessSample,
1533 test_grabber_callback_OnShutdown,
1536 struct test_source
1538 IMFMediaSource IMFMediaSource_iface;
1539 LONG refcount;
1542 static struct test_source *impl_from_IMFMediaSource(IMFMediaSource *iface)
1544 return CONTAINING_RECORD(iface, struct test_source, IMFMediaSource_iface);
1547 static HRESULT WINAPI test_source_QueryInterface(IMFMediaSource *iface, REFIID riid, void **out)
1549 if (IsEqualIID(riid, &IID_IMFMediaSource)
1550 || IsEqualIID(riid, &IID_IMFMediaEventGenerator)
1551 || IsEqualIID(riid, &IID_IUnknown))
1553 *out = iface;
1555 else
1557 *out = NULL;
1558 return E_NOINTERFACE;
1561 IMFMediaSource_AddRef(iface);
1562 return S_OK;
1565 static ULONG WINAPI test_source_AddRef(IMFMediaSource *iface)
1567 struct test_source *source = impl_from_IMFMediaSource(iface);
1568 return InterlockedIncrement(&source->refcount);
1571 static ULONG WINAPI test_source_Release(IMFMediaSource *iface)
1573 struct test_source *source = impl_from_IMFMediaSource(iface);
1574 ULONG refcount = InterlockedDecrement(&source->refcount);
1576 if (!refcount)
1577 free(source);
1579 return refcount;
1582 static HRESULT WINAPI test_source_GetEvent(IMFMediaSource *iface, DWORD flags, IMFMediaEvent **event)
1584 ok(0, "Unexpected call.\n");
1585 return E_NOTIMPL;
1588 static HRESULT WINAPI test_source_BeginGetEvent(IMFMediaSource *iface, IMFAsyncCallback *callback, IUnknown *state)
1590 ok(0, "Unexpected call.\n");
1591 return E_NOTIMPL;
1594 static HRESULT WINAPI test_source_EndGetEvent(IMFMediaSource *iface, IMFAsyncResult *result, IMFMediaEvent **event)
1596 ok(0, "Unexpected call.\n");
1597 return E_NOTIMPL;
1600 static HRESULT WINAPI test_source_QueueEvent(IMFMediaSource *iface, MediaEventType event_type, REFGUID ext_type,
1601 HRESULT hr, const PROPVARIANT *value)
1603 ok(0, "Unexpected call.\n");
1604 return E_NOTIMPL;
1607 static HRESULT WINAPI test_source_GetCharacteristics(IMFMediaSource *iface, DWORD *flags)
1609 ok(0, "Unexpected call.\n");
1610 return E_NOTIMPL;
1613 static HRESULT WINAPI test_source_CreatePresentationDescriptor(IMFMediaSource *iface, IMFPresentationDescriptor **pd)
1615 ok(0, "Unexpected call.\n");
1616 return E_NOTIMPL;
1619 static HRESULT WINAPI test_source_Start(IMFMediaSource *iface, IMFPresentationDescriptor *pd, const GUID *time_format,
1620 const PROPVARIANT *start_position)
1622 ok(0, "Unexpected call.\n");
1623 return E_NOTIMPL;
1626 static HRESULT WINAPI test_source_Stop(IMFMediaSource *iface)
1628 ok(0, "Unexpected call.\n");
1629 return E_NOTIMPL;
1632 static HRESULT WINAPI test_source_Pause(IMFMediaSource *iface)
1634 ok(0, "Unexpected call.\n");
1635 return E_NOTIMPL;
1638 static HRESULT WINAPI test_source_Shutdown(IMFMediaSource *iface)
1640 ok(0, "Unexpected call.\n");
1641 return E_NOTIMPL;
1644 static const IMFMediaSourceVtbl test_source_vtbl =
1646 test_source_QueryInterface,
1647 test_source_AddRef,
1648 test_source_Release,
1649 test_source_GetEvent,
1650 test_source_BeginGetEvent,
1651 test_source_EndGetEvent,
1652 test_source_QueueEvent,
1653 test_source_GetCharacteristics,
1654 test_source_CreatePresentationDescriptor,
1655 test_source_Start,
1656 test_source_Stop,
1657 test_source_Pause,
1658 test_source_Shutdown,
1661 static IMFMediaSource *create_test_source(void)
1663 struct test_source *source;
1665 source = calloc(1, sizeof(*source));
1666 source->IMFMediaSource_iface.lpVtbl = &test_source_vtbl;
1667 source->refcount = 1;
1669 return &source->IMFMediaSource_iface;
1672 static void init_media_type(IMFMediaType *mediatype, const struct attribute_desc *desc, ULONG limit)
1674 HRESULT hr;
1675 ULONG i;
1677 hr = IMFMediaType_DeleteAllItems(mediatype);
1678 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1680 for (i = 0; i < limit && desc[i].key; ++i)
1682 hr = IMFMediaType_SetItem(mediatype, desc[i].key, &desc[i].value);
1683 ok(hr == S_OK, "SetItem %s returned %#lx\n", debugstr_a(desc[i].name), hr);
1687 static void init_source_node(IMFMediaType *mediatype, IMFMediaSource *source, IMFTopologyNode *node)
1689 IMFPresentationDescriptor *pd;
1690 IMFMediaTypeHandler *handler;
1691 IMFStreamDescriptor *sd;
1692 HRESULT hr;
1694 hr = IMFTopologyNode_DeleteAllItems(node);
1695 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1697 hr = MFCreateStreamDescriptor(0, 1, &mediatype, &sd);
1698 ok(hr == S_OK, "Failed to create stream descriptor, hr %#lx.\n", hr);
1700 hr = IMFStreamDescriptor_GetMediaTypeHandler(sd, &handler);
1701 ok(hr == S_OK, "Failed to get media type handler, hr %#lx.\n", hr);
1703 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, mediatype);
1704 ok(hr == S_OK, "Failed to set current media type, hr %#lx.\n", hr);
1706 IMFMediaTypeHandler_Release(handler);
1708 hr = MFCreatePresentationDescriptor(1, &sd, &pd);
1709 ok(hr == S_OK, "Failed to create presentation descriptor, hr %#lx.\n", hr);
1711 hr = IMFTopologyNode_SetUnknown(node, &MF_TOPONODE_PRESENTATION_DESCRIPTOR, (IUnknown *)pd);
1712 ok(hr == S_OK, "Failed to set node pd, hr %#lx.\n", hr);
1714 IMFPresentationDescriptor_Release(pd);
1716 hr = IMFTopologyNode_SetUnknown(node, &MF_TOPONODE_STREAM_DESCRIPTOR, (IUnknown *)sd);
1717 ok(hr == S_OK, "Failed to set node sd, hr %#lx.\n", hr);
1719 if (source)
1721 hr = IMFTopologyNode_SetUnknown(node, &MF_TOPONODE_SOURCE, (IUnknown *)source);
1722 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1725 IMFStreamDescriptor_Release(sd);
1728 static void init_sink_node(IMFActivate *sink_activate, unsigned int method, IMFTopologyNode *node)
1730 IMFStreamSink *stream_sink;
1731 IMFMediaSink *sink;
1732 HRESULT hr;
1734 hr = IMFTopologyNode_DeleteAllItems(node);
1735 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1737 hr = IMFActivate_ActivateObject(sink_activate, &IID_IMFMediaSink, (void **)&sink);
1738 ok(hr == S_OK, "Failed to activate, hr %#lx.\n", hr);
1740 hr = IMFMediaSink_GetStreamSinkByIndex(sink, 0, &stream_sink);
1741 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1743 IMFMediaSink_Release(sink);
1745 hr = IMFTopologyNode_SetObject(node, (IUnknown *)stream_sink);
1746 ok(hr == S_OK, "Failed to set object, hr %#lx.\n", hr);
1748 IMFStreamSink_Release(stream_sink);
1750 hr = IMFTopologyNode_SetUINT32(node, &MF_TOPONODE_CONNECT_METHOD, method);
1751 ok(hr == S_OK, "Failed to set connect method, hr %#lx.\n", hr);
1754 enum loader_test_flags
1756 LOADER_EXPECTED_DECODER = 0x1,
1757 LOADER_EXPECTED_CONVERTER = 0x2,
1758 LOADER_TODO = 0x4,
1761 static void test_topology_loader(void)
1763 static const struct loader_test
1765 media_type_desc input_type;
1766 media_type_desc output_type;
1767 MF_CONNECT_METHOD method;
1768 HRESULT expected_result;
1769 unsigned int flags;
1771 loader_tests[] =
1774 /* PCM -> PCM, same type */
1776 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
1777 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
1778 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 1),
1779 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100),
1780 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 44100),
1781 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 1),
1782 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 8),
1785 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
1786 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
1787 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 1),
1788 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100),
1789 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 44100),
1790 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 1),
1791 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 8),
1794 MF_CONNECT_DIRECT,
1795 S_OK,
1799 /* PCM -> PCM, different bps. */
1801 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
1802 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
1803 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 1),
1804 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100),
1805 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 44100),
1806 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 1),
1807 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 8),
1810 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
1811 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
1812 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 1),
1813 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 48000),
1814 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 48000),
1815 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 1),
1816 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 8),
1819 MF_CONNECT_DIRECT,
1820 MF_E_INVALIDMEDIATYPE,
1824 /* PCM -> PCM, different bps. */
1826 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
1827 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
1828 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 1),
1829 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100),
1830 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 44100),
1831 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 1),
1832 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 8),
1835 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
1836 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
1837 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 1),
1838 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 48000),
1839 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 48000),
1840 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 1),
1841 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 8),
1844 MF_CONNECT_ALLOW_CONVERTER,
1845 S_OK,
1846 LOADER_EXPECTED_CONVERTER | LOADER_TODO,
1850 /* MP3 -> PCM */
1852 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
1853 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_MP3),
1854 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
1855 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100),
1856 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 16000),
1857 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 1),
1860 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
1861 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
1862 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 1),
1863 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100),
1864 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 44100),
1865 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 1),
1866 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 8),
1869 MF_CONNECT_DIRECT,
1870 MF_E_INVALIDMEDIATYPE,
1874 /* MP3 -> PCM */
1876 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
1877 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_MP3),
1878 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
1879 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100),
1880 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 16000),
1881 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 1),
1884 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
1885 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
1886 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 1),
1887 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100),
1888 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 44100),
1889 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 1),
1890 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 8),
1893 MF_CONNECT_ALLOW_CONVERTER,
1894 MF_E_TRANSFORM_NOT_POSSIBLE_FOR_CURRENT_MEDIATYPE_COMBINATION,
1895 LOADER_TODO,
1899 /* MP3 -> PCM */
1901 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
1902 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_MP3),
1903 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
1904 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100),
1905 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 16000),
1906 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 1),
1909 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
1910 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
1911 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 1),
1912 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100),
1913 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 44100),
1914 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 1),
1915 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 8),
1918 MF_CONNECT_ALLOW_DECODER,
1919 S_OK,
1920 LOADER_EXPECTED_DECODER | LOADER_TODO,
1924 IMFSampleGrabberSinkCallback test_grabber_callback = { &test_grabber_callback_vtbl };
1925 IMFTopologyNode *src_node, *sink_node, *src_node2, *sink_node2, *mft_node;
1926 IMFTopology *topology, *topology2, *full_topology;
1927 IMFMediaType *media_type, *input_type, *output_type;
1928 IMFPresentationDescriptor *pd;
1929 unsigned int i, count, value;
1930 IMFActivate *sink_activate;
1931 MF_TOPOLOGY_TYPE node_type;
1932 IMFStreamDescriptor *sd;
1933 IMFTransform *transform;
1934 IMFMediaSource *source;
1935 IMFTopoLoader *loader;
1936 IUnknown *node_object;
1937 WORD node_count;
1938 TOPOID node_id;
1939 DWORD index;
1940 HRESULT hr;
1941 BOOL ret;
1943 hr = MFStartup(MF_VERSION, MFSTARTUP_FULL);
1944 ok(hr == S_OK, "Startup failure, hr %#lx.\n", hr);
1946 hr = MFCreateTopoLoader(NULL);
1947 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
1949 hr = MFCreateTopoLoader(&loader);
1950 ok(hr == S_OK, "Failed to create topology loader, hr %#lx.\n", hr);
1952 hr = MFCreateTopology(&topology);
1953 ok(hr == S_OK, "Failed to create topology, hr %#lx.\n", hr);
1955 /* Empty topology */
1956 hr = IMFTopoLoader_Load(loader, topology, &full_topology, NULL);
1957 todo_wine
1958 ok(hr == MF_E_TOPO_UNSUPPORTED, "Unexpected hr %#lx.\n", hr);
1960 /* Add source node. */
1961 hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &src_node);
1962 ok(hr == S_OK, "Failed to create topology node, hr %#lx.\n", hr);
1964 /* When a decoder is involved, windows requires this attribute to be present */
1965 source = create_test_source();
1967 hr = IMFTopologyNode_SetUnknown(src_node, &MF_TOPONODE_SOURCE, (IUnknown *)source);
1968 ok(hr == S_OK, "Failed to set node source, hr %#lx.\n", hr);
1970 hr = MFCreateMediaType(&media_type);
1971 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
1973 hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio);
1974 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
1975 hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFAudioFormat_PCM);
1976 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
1978 hr = MFCreateStreamDescriptor(0, 1, &media_type, &sd);
1979 ok(hr == S_OK, "Failed to create stream descriptor, hr %#lx.\n", hr);
1981 hr = IMFTopologyNode_SetUnknown(src_node, &MF_TOPONODE_STREAM_DESCRIPTOR, (IUnknown *)sd);
1982 ok(hr == S_OK, "Failed to set node sd, hr %#lx.\n", hr);
1984 hr = MFCreatePresentationDescriptor(1, &sd, &pd);
1985 ok(hr == S_OK, "Failed to create presentation descriptor, hr %#lx.\n", hr);
1987 hr = IMFTopologyNode_SetUnknown(src_node, &MF_TOPONODE_PRESENTATION_DESCRIPTOR, (IUnknown *)pd);
1988 ok(hr == S_OK, "Failed to set node pd, hr %#lx.\n", hr);
1990 IMFPresentationDescriptor_Release(pd);
1991 IMFStreamDescriptor_Release(sd);
1992 IMFMediaType_Release(media_type);
1994 hr = IMFTopology_AddNode(topology, src_node);
1995 ok(hr == S_OK, "Failed to add a node, hr %#lx.\n", hr);
1997 /* Source node only. */
1998 hr = IMFTopoLoader_Load(loader, topology, &full_topology, NULL);
1999 todo_wine
2000 ok(hr == MF_E_TOPO_UNSUPPORTED, "Unexpected hr %#lx.\n", hr);
2002 hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, &sink_node);
2003 ok(hr == S_OK, "Failed to create output node, hr %#lx.\n", hr);
2005 hr = MFCreateMediaType(&media_type);
2006 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
2008 hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio);
2009 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
2010 hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFAudioFormat_PCM);
2011 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
2013 hr = MFCreateSampleGrabberSinkActivate(media_type, &test_grabber_callback, &sink_activate);
2014 ok(hr == S_OK, "Failed to create grabber sink, hr %#lx.\n", hr);
2016 hr = IMFTopologyNode_SetObject(sink_node, (IUnknown *)sink_activate);
2017 ok(hr == S_OK, "Failed to set object, hr %#lx.\n", hr);
2019 IMFMediaType_Release(media_type);
2021 hr = IMFTopology_AddNode(topology, sink_node);
2022 ok(hr == S_OK, "Failed to add sink node, hr %#lx.\n", hr);
2024 hr = IMFTopoLoader_Load(loader, topology, &full_topology, NULL);
2025 todo_wine
2026 ok(hr == MF_E_TOPO_UNSUPPORTED, "Unexpected hr %#lx.\n", hr);
2028 hr = IMFTopologyNode_ConnectOutput(src_node, 0, sink_node, 0);
2029 ok(hr == S_OK, "Failed to connect nodes, hr %#lx.\n", hr);
2031 /* Sink was not resolved. */
2032 hr = IMFTopoLoader_Load(loader, topology, &full_topology, NULL);
2033 ok(hr == MF_E_TOPO_SINK_ACTIVATES_UNSUPPORTED, "Unexpected hr %#lx.\n", hr);
2035 hr = MFCreateMediaType(&input_type);
2036 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
2038 hr = MFCreateMediaType(&output_type);
2039 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
2041 for (i = 0; i < ARRAY_SIZE(loader_tests); ++i)
2043 const struct loader_test *test = &loader_tests[i];
2045 init_media_type(input_type, test->input_type, -1);
2046 init_media_type(output_type, test->output_type, -1);
2048 hr = MFCreateSampleGrabberSinkActivate(output_type, &test_grabber_callback, &sink_activate);
2049 ok(hr == S_OK, "Failed to create grabber sink, hr %#lx.\n", hr);
2051 init_source_node(input_type, source, src_node);
2052 init_sink_node(sink_activate, test->method, sink_node);
2054 hr = IMFTopology_GetCount(topology, &count);
2055 ok(hr == S_OK, "Failed to get attribute count, hr %#lx.\n", hr);
2056 ok(!count, "Unexpected count %u.\n", count);
2058 hr = IMFTopoLoader_Load(loader, topology, &full_topology, NULL);
2059 todo_wine_if(test->flags & LOADER_TODO)
2060 ok(hr == test->expected_result, "Unexpected hr %#lx on test %u.\n", hr, i);
2061 ok(full_topology != topology, "Unexpected instance.\n");
2063 if (test->expected_result == S_OK && hr == S_OK)
2065 hr = IMFTopology_GetCount(full_topology, &count);
2066 ok(hr == S_OK, "Failed to get attribute count, hr %#lx.\n", hr);
2067 todo_wine
2068 ok(count == 1, "Unexpected count %u.\n", count);
2070 value = 0xdeadbeef;
2071 hr = IMFTopology_GetUINT32(full_topology, &MF_TOPOLOGY_RESOLUTION_STATUS, &value);
2072 todo_wine {
2073 ok(hr == S_OK, "Failed to get attribute, hr %#lx.\n", hr);
2074 ok(value == MF_TOPOLOGY_RESOLUTION_SUCCEEDED, "Unexpected value %#x.\n", value);
2076 count = 2;
2077 if (test->flags & LOADER_EXPECTED_DECODER)
2078 count++;
2079 if (test->flags & LOADER_EXPECTED_CONVERTER)
2080 count++;
2082 hr = IMFTopology_GetNodeCount(full_topology, &node_count);
2083 ok(hr == S_OK, "Failed to get node count, hr %#lx.\n", hr);
2084 todo_wine_if(test->flags & (LOADER_EXPECTED_CONVERTER | LOADER_EXPECTED_DECODER))
2085 ok(node_count == count, "Unexpected node count %u.\n", node_count);
2087 hr = IMFTopologyNode_GetTopoNodeID(src_node, &node_id);
2088 ok(hr == S_OK, "Failed to get source node id, hr %#lx.\n", hr);
2090 hr = IMFTopology_GetNodeByID(full_topology, node_id, &src_node2);
2091 ok(hr == S_OK, "Failed to get source in resolved topology, hr %#lx.\n", hr);
2093 hr = IMFTopologyNode_GetTopoNodeID(sink_node, &node_id);
2094 ok(hr == S_OK, "Failed to get sink node id, hr %#lx.\n", hr);
2096 hr = IMFTopology_GetNodeByID(full_topology, node_id, &sink_node2);
2097 ok(hr == S_OK, "Failed to get sink in resolved topology, hr %#lx.\n", hr);
2099 if (test->flags & (LOADER_EXPECTED_DECODER | LOADER_EXPECTED_CONVERTER) && strcmp(winetest_platform, "wine"))
2101 hr = IMFTopologyNode_GetOutput(src_node2, 0, &mft_node, &index);
2102 ok(hr == S_OK, "Failed to get transform node in resolved topology, hr %#lx.\n", hr);
2103 ok(!index, "Unexpected stream index %lu.\n", index);
2105 hr = IMFTopologyNode_GetNodeType(mft_node, &node_type);
2106 ok(hr == S_OK, "Failed to get transform node type in resolved topology, hr %#lx.\n", hr);
2107 ok(node_type == MF_TOPOLOGY_TRANSFORM_NODE, "Unexpected node type %u.\n", node_type);
2109 hr = IMFTopologyNode_GetObject(mft_node, &node_object);
2110 ok(hr == S_OK, "Failed to get object of transform node, hr %#lx.\n", hr);
2112 if (test->flags & LOADER_EXPECTED_DECODER)
2114 value = 0;
2115 hr = IMFTopologyNode_GetUINT32(mft_node, &MF_TOPONODE_DECODER, &value);
2116 ok(hr == S_OK, "Failed to get attribute, hr %#lx.\n", hr);
2117 ok(value == 1, "Unexpected value.\n");
2120 hr = IMFTopologyNode_GetItem(mft_node, &MF_TOPONODE_TRANSFORM_OBJECTID, NULL);
2121 ok(hr == S_OK, "Failed to get attribute, hr %#lx.\n", hr);
2123 hr = IUnknown_QueryInterface(node_object, &IID_IMFTransform, (void **)&transform);
2124 ok(hr == S_OK, "Failed to get IMFTransform from transform node's object, hr %#lx.\n", hr);
2125 IUnknown_Release(node_object);
2127 hr = IMFTransform_GetInputCurrentType(transform, 0, &media_type);
2128 ok(hr == S_OK, "Failed to get transform input type, hr %#lx.\n", hr);
2130 hr = IMFMediaType_Compare(input_type, (IMFAttributes *)media_type, MF_ATTRIBUTES_MATCH_OUR_ITEMS, &ret);
2131 ok(hr == S_OK, "Failed to compare media types, hr %#lx.\n", hr);
2132 ok(ret, "Input type of first transform doesn't match source node type.\n");
2134 IMFTopologyNode_Release(mft_node);
2135 IMFMediaType_Release(media_type);
2136 IMFTransform_Release(transform);
2138 hr = IMFTopologyNode_GetInput(sink_node2, 0, &mft_node, &index);
2139 ok(hr == S_OK, "Failed to get transform node in resolved topology, hr %#lx.\n", hr);
2140 ok(!index, "Unexpected stream index %lu.\n", index);
2142 hr = IMFTopologyNode_GetNodeType(mft_node, &node_type);
2143 ok(hr == S_OK, "Failed to get transform node type in resolved topology, hr %#lx.\n", hr);
2144 ok(node_type == MF_TOPOLOGY_TRANSFORM_NODE, "Unexpected node type %u.\n", node_type);
2146 hr = IMFTopologyNode_GetItem(mft_node, &MF_TOPONODE_TRANSFORM_OBJECTID, NULL);
2147 ok(hr == S_OK, "Failed to get attribute, hr %#lx.\n", hr);
2149 hr = IMFTopologyNode_GetObject(mft_node, &node_object);
2150 ok(hr == S_OK, "Failed to get object of transform node, hr %#lx.\n", hr);
2152 hr = IUnknown_QueryInterface(node_object, &IID_IMFTransform, (void**) &transform);
2153 ok(hr == S_OK, "Failed to get IMFTransform from transform node's object, hr %#lx.\n", hr);
2154 IUnknown_Release(node_object);
2156 hr = IMFTransform_GetOutputCurrentType(transform, 0, &media_type);
2157 ok(hr == S_OK, "Failed to get transform output type, hr %#lx.\n", hr);
2159 hr = IMFMediaType_Compare(output_type, (IMFAttributes *)media_type, MF_ATTRIBUTES_MATCH_OUR_ITEMS, &ret);
2160 ok(hr == S_OK, "Failed to compare media types, hr %#lx.\n", hr);
2161 ok(ret, "Output type of last transform doesn't match sink node type.\n");
2163 IMFTopologyNode_Release(mft_node);
2164 IMFMediaType_Release(media_type);
2165 IMFTransform_Release(transform);
2168 IMFTopologyNode_Release(sink_node2);
2170 hr = IMFTopology_SetUINT32(full_topology, &IID_IMFTopology, 123);
2171 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2172 hr = IMFTopoLoader_Load(loader, full_topology, &topology2, NULL);
2173 ok(hr == S_OK, "Failed to resolve topology, hr %#lx.\n", hr);
2174 ok(full_topology != topology2, "Unexpected instance.\n");
2175 hr = IMFTopology_GetUINT32(topology2, &IID_IMFTopology, &value);
2176 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2178 IMFTopology_Release(topology2);
2179 IMFTopology_Release(full_topology);
2182 hr = IMFTopology_GetCount(topology, &count);
2183 ok(hr == S_OK, "Failed to get attribute count, hr %#lx.\n", hr);
2184 ok(!count, "Unexpected count %u.\n", count);
2186 IMFActivate_ShutdownObject(sink_activate);
2187 IMFActivate_Release(sink_activate);
2190 IMFMediaType_Release(input_type);
2191 IMFMediaType_Release(output_type);
2193 IMFMediaSource_Release(source);
2194 IMFTopoLoader_Release(loader);
2196 hr = MFShutdown();
2197 ok(hr == S_OK, "Shutdown failure, hr %#lx.\n", hr);
2200 static void test_topology_loader_evr(void)
2202 IMFTopologyNode *node, *source_node, *evr_node;
2203 IMFTopology *topology, *full_topology;
2204 IMFMediaTypeHandler *handler;
2205 unsigned int i, count, value;
2206 IMFStreamSink *stream_sink;
2207 IMFMediaType *media_type;
2208 IMFActivate *activate;
2209 IMFTopoLoader *loader;
2210 IMFMediaSink *sink;
2211 WORD node_count;
2212 UINT64 value64;
2213 HWND window;
2214 HRESULT hr;
2216 hr = CoInitialize(NULL);
2217 ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
2219 hr = MFCreateTopoLoader(&loader);
2220 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2222 /* Source node. */
2223 hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &source_node);
2224 ok(hr == S_OK, "Failed to create topology node, hr %#lx.\n", hr);
2226 hr = MFCreateMediaType(&media_type);
2227 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
2229 hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
2230 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2231 hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFVideoFormat_RGB32);
2232 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2233 hr = IMFMediaType_SetUINT64(media_type, &MF_MT_FRAME_SIZE, (UINT64)640 << 32 | 480);
2234 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2235 hr = IMFMediaType_SetUINT32(media_type, &MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE);
2236 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2238 init_source_node(media_type, NULL, source_node);
2240 /* EVR sink node. */
2241 window = create_window();
2243 hr = MFCreateVideoRendererActivate(window, &activate);
2244 ok(hr == S_OK, "Failed to create activate object, hr %#lx.\n", hr);
2246 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink);
2247 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2249 hr = IMFMediaSink_GetStreamSinkById(sink, 0, &stream_sink);
2250 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2252 hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, &evr_node);
2253 ok(hr == S_OK, "Failed to create topology node, hr %#lx.\n", hr);
2255 hr = IMFTopologyNode_SetObject(evr_node, (IUnknown *)stream_sink);
2256 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2258 hr = IMFStreamSink_GetMediaTypeHandler(stream_sink, &handler);
2259 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2260 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, media_type);
2261 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2262 IMFMediaTypeHandler_Release(handler);
2264 IMFStreamSink_Release(stream_sink);
2265 IMFMediaSink_Release(sink);
2267 hr = MFCreateTopology(&topology);
2268 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2270 hr = IMFTopology_AddNode(topology, source_node);
2271 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2272 hr = IMFTopology_AddNode(topology, evr_node);
2273 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2274 hr = IMFTopologyNode_ConnectOutput(source_node, 0, evr_node, 0);
2275 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2277 hr = IMFTopologyNode_SetUINT32(evr_node, &MF_TOPONODE_CONNECT_METHOD, MF_CONNECT_DIRECT);
2278 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2280 hr = IMFTopologyNode_GetCount(evr_node, &count);
2281 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2282 ok(count == 1, "Unexpected attribute count %u.\n", count);
2284 hr = IMFTopoLoader_Load(loader, topology, &full_topology, NULL);
2285 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2287 hr = IMFTopology_GetNodeCount(full_topology, &node_count);
2288 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2289 ok(node_count == 3, "Unexpected node count %u.\n", node_count);
2291 for (i = 0; i < node_count; ++i)
2293 MF_TOPOLOGY_TYPE node_type;
2295 hr = IMFTopology_GetNode(full_topology, i, &node);
2296 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2298 hr = IMFTopologyNode_GetNodeType(node, &node_type);
2299 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2301 if (node_type == MF_TOPOLOGY_OUTPUT_NODE)
2303 value = 1;
2304 hr = IMFTopologyNode_GetUINT32(node, &MF_TOPONODE_STREAMID, &value);
2305 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2306 ok(!value, "Unexpected stream id %u.\n", value);
2308 else if (node_type == MF_TOPOLOGY_SOURCESTREAM_NODE)
2310 value64 = 1;
2311 hr = IMFTopologyNode_GetUINT64(node, &MF_TOPONODE_MEDIASTART, &value64);
2312 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2313 ok(!value64, "Unexpected value.\n");
2317 IMFTopology_Release(full_topology);
2319 IMFTopoLoader_Release(loader);
2321 IMFTopologyNode_Release(source_node);
2322 IMFTopologyNode_Release(evr_node);
2323 IMFTopology_Release(topology);
2324 IMFMediaType_Release(media_type);
2325 DestroyWindow(window);
2327 CoUninitialize();
2330 static HRESULT WINAPI testshutdown_QueryInterface(IMFShutdown *iface, REFIID riid, void **obj)
2332 if (IsEqualIID(riid, &IID_IMFShutdown) ||
2333 IsEqualIID(riid, &IID_IUnknown))
2335 *obj = iface;
2336 IMFShutdown_AddRef(iface);
2337 return S_OK;
2340 *obj = NULL;
2341 return E_NOINTERFACE;
2344 static ULONG WINAPI testshutdown_AddRef(IMFShutdown *iface)
2346 return 2;
2349 static ULONG WINAPI testshutdown_Release(IMFShutdown *iface)
2351 return 1;
2354 static HRESULT WINAPI testshutdown_Shutdown(IMFShutdown *iface)
2356 return 0xdead;
2359 static HRESULT WINAPI testshutdown_GetShutdownStatus(IMFShutdown *iface, MFSHUTDOWN_STATUS *status)
2361 ok(0, "Unexpected call.\n");
2362 return E_NOTIMPL;
2365 static const IMFShutdownVtbl testshutdownvtbl =
2367 testshutdown_QueryInterface,
2368 testshutdown_AddRef,
2369 testshutdown_Release,
2370 testshutdown_Shutdown,
2371 testshutdown_GetShutdownStatus,
2374 static void test_MFShutdownObject(void)
2376 IMFShutdown testshutdown = { &testshutdownvtbl };
2377 IUnknown testshutdown2 = { &testservicevtbl };
2378 HRESULT hr;
2380 hr = MFShutdownObject(NULL);
2381 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2383 hr = MFShutdownObject((IUnknown *)&testshutdown);
2384 ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr);
2386 hr = MFShutdownObject(&testshutdown2);
2387 ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr);
2390 enum clock_action
2392 CLOCK_START,
2393 CLOCK_STOP,
2394 CLOCK_PAUSE,
2397 static HRESULT WINAPI test_clock_sink_QueryInterface(IMFClockStateSink *iface, REFIID riid, void **obj)
2399 if (IsEqualIID(riid, &IID_IMFClockStateSink) ||
2400 IsEqualIID(riid, &IID_IUnknown))
2402 *obj = iface;
2403 IMFClockStateSink_AddRef(iface);
2404 return S_OK;
2407 *obj = NULL;
2408 return E_NOINTERFACE;
2411 static ULONG WINAPI test_clock_sink_AddRef(IMFClockStateSink *iface)
2413 return 2;
2416 static ULONG WINAPI test_clock_sink_Release(IMFClockStateSink *iface)
2418 return 1;
2421 static HRESULT WINAPI test_clock_sink_OnClockStart(IMFClockStateSink *iface, MFTIME system_time, LONGLONG offset)
2423 return E_NOTIMPL;
2426 static HRESULT WINAPI test_clock_sink_OnClockStop(IMFClockStateSink *iface, MFTIME system_time)
2428 return E_NOTIMPL;
2431 static HRESULT WINAPI test_clock_sink_OnClockPause(IMFClockStateSink *iface, MFTIME system_time)
2433 return E_NOTIMPL;
2436 static HRESULT WINAPI test_clock_sink_OnClockRestart(IMFClockStateSink *iface, MFTIME system_time)
2438 return E_NOTIMPL;
2441 static HRESULT WINAPI test_clock_sink_OnClockSetRate(IMFClockStateSink *iface, MFTIME system_time, float rate)
2443 return E_NOTIMPL;
2446 static const IMFClockStateSinkVtbl test_clock_sink_vtbl =
2448 test_clock_sink_QueryInterface,
2449 test_clock_sink_AddRef,
2450 test_clock_sink_Release,
2451 test_clock_sink_OnClockStart,
2452 test_clock_sink_OnClockStop,
2453 test_clock_sink_OnClockPause,
2454 test_clock_sink_OnClockRestart,
2455 test_clock_sink_OnClockSetRate,
2458 static void test_presentation_clock(void)
2460 static const struct clock_state_test
2462 enum clock_action action;
2463 MFCLOCK_STATE clock_state;
2464 MFCLOCK_STATE source_state;
2465 HRESULT hr;
2467 clock_state_change[] =
2469 { CLOCK_STOP, MFCLOCK_STATE_STOPPED, MFCLOCK_STATE_INVALID },
2470 { CLOCK_PAUSE, MFCLOCK_STATE_STOPPED, MFCLOCK_STATE_INVALID, MF_E_INVALIDREQUEST },
2471 { CLOCK_STOP, MFCLOCK_STATE_STOPPED, MFCLOCK_STATE_INVALID, MF_E_CLOCK_STATE_ALREADY_SET },
2472 { CLOCK_START, MFCLOCK_STATE_RUNNING, MFCLOCK_STATE_RUNNING },
2473 { CLOCK_START, MFCLOCK_STATE_RUNNING, MFCLOCK_STATE_RUNNING },
2474 { CLOCK_PAUSE, MFCLOCK_STATE_PAUSED, MFCLOCK_STATE_PAUSED },
2475 { CLOCK_PAUSE, MFCLOCK_STATE_PAUSED, MFCLOCK_STATE_PAUSED, MF_E_CLOCK_STATE_ALREADY_SET },
2476 { CLOCK_STOP, MFCLOCK_STATE_STOPPED, MFCLOCK_STATE_STOPPED },
2477 { CLOCK_START, MFCLOCK_STATE_RUNNING, MFCLOCK_STATE_RUNNING },
2478 { CLOCK_STOP, MFCLOCK_STATE_STOPPED, MFCLOCK_STATE_STOPPED },
2479 { CLOCK_STOP, MFCLOCK_STATE_STOPPED, MFCLOCK_STATE_STOPPED, MF_E_CLOCK_STATE_ALREADY_SET },
2480 { CLOCK_PAUSE, MFCLOCK_STATE_STOPPED, MFCLOCK_STATE_STOPPED, MF_E_INVALIDREQUEST },
2481 { CLOCK_START, MFCLOCK_STATE_RUNNING, MFCLOCK_STATE_RUNNING },
2482 { CLOCK_PAUSE, MFCLOCK_STATE_PAUSED, MFCLOCK_STATE_PAUSED },
2483 { CLOCK_START, MFCLOCK_STATE_RUNNING, MFCLOCK_STATE_RUNNING },
2485 IMFClockStateSink test_sink = { &test_clock_sink_vtbl };
2486 IMFPresentationTimeSource *time_source;
2487 MFCLOCK_PROPERTIES props, props2;
2488 IMFRateControl *rate_control;
2489 IMFPresentationClock *clock;
2490 MFSHUTDOWN_STATUS status;
2491 IMFShutdown *shutdown;
2492 MFTIME systime, time;
2493 LONGLONG clock_time;
2494 MFCLOCK_STATE state;
2495 unsigned int i;
2496 DWORD value;
2497 float rate;
2498 HRESULT hr;
2499 BOOL thin;
2501 hr = MFStartup(MF_VERSION, MFSTARTUP_FULL);
2502 ok(hr == S_OK, "Failed to start up, hr %#lx.\n", hr);
2504 hr = MFCreatePresentationClock(&clock);
2505 ok(hr == S_OK, "Failed to create presentation clock, hr %#lx.\n", hr);
2507 check_interface(clock, &IID_IMFTimer, TRUE);
2508 check_interface(clock, &IID_IMFRateControl, TRUE);
2509 check_interface(clock, &IID_IMFPresentationClock, TRUE);
2510 check_interface(clock, &IID_IMFShutdown, TRUE);
2511 check_interface(clock, &IID_IMFClock, TRUE);
2513 hr = IMFPresentationClock_QueryInterface(clock, &IID_IMFRateControl, (void **)&rate_control);
2514 ok(hr == S_OK, "Failed to get rate control interface, hr %#lx.\n", hr);
2516 hr = IMFPresentationClock_GetTimeSource(clock, &time_source);
2517 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#lx.\n", hr);
2519 hr = IMFPresentationClock_GetTimeSource(clock, NULL);
2520 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
2522 hr = IMFPresentationClock_GetClockCharacteristics(clock, &value);
2523 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#lx.\n", hr);
2525 hr = IMFPresentationClock_GetClockCharacteristics(clock, NULL);
2526 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#lx.\n", hr);
2528 hr = IMFPresentationClock_GetTime(clock, &time);
2529 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#lx.\n", hr);
2531 hr = IMFPresentationClock_GetTime(clock, NULL);
2532 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
2534 value = 1;
2535 hr = IMFPresentationClock_GetContinuityKey(clock, &value);
2536 ok(hr == S_OK, "Failed to get continuity key, hr %#lx.\n", hr);
2537 ok(value == 0, "Unexpected value %lu.\n", value);
2539 hr = IMFPresentationClock_GetProperties(clock, &props);
2540 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#lx.\n", hr);
2542 hr = IMFPresentationClock_GetState(clock, 0, &state);
2543 ok(hr == S_OK, "Failed to get state, hr %#lx.\n", hr);
2544 ok(state == MFCLOCK_STATE_INVALID, "Unexpected state %d.\n", state);
2546 hr = IMFPresentationClock_GetCorrelatedTime(clock, 0, &clock_time, &systime);
2547 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#lx.\n", hr);
2549 hr = IMFPresentationClock_GetCorrelatedTime(clock, 0, NULL, &systime);
2550 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#lx.\n", hr);
2552 hr = IMFPresentationClock_GetCorrelatedTime(clock, 0, &time, NULL);
2553 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#lx.\n", hr);
2555 /* Sinks. */
2556 hr = IMFPresentationClock_AddClockStateSink(clock, NULL);
2557 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
2559 hr = IMFPresentationClock_AddClockStateSink(clock, &test_sink);
2560 ok(hr == S_OK, "Failed to add a sink, hr %#lx.\n", hr);
2562 hr = IMFPresentationClock_AddClockStateSink(clock, &test_sink);
2563 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
2565 hr = IMFPresentationClock_RemoveClockStateSink(clock, NULL);
2566 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
2568 hr = IMFPresentationClock_RemoveClockStateSink(clock, &test_sink);
2569 ok(hr == S_OK, "Failed to remove sink, hr %#lx.\n", hr);
2571 hr = IMFPresentationClock_RemoveClockStateSink(clock, &test_sink);
2572 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2574 /* State change commands, time source is not set yet. */
2575 hr = IMFPresentationClock_Start(clock, 0);
2576 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#lx.\n", hr);
2578 hr = IMFPresentationClock_Pause(clock);
2579 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#lx.\n", hr);
2581 hr = IMFPresentationClock_Stop(clock);
2582 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#lx.\n", hr);
2584 hr = IMFRateControl_SetRate(rate_control, FALSE, 0.0f);
2585 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#lx.\n", hr);
2587 /* Set default time source. */
2588 hr = MFCreateSystemTimeSource(&time_source);
2589 ok(hr == S_OK, "Failed to create time source, hr %#lx.\n", hr);
2591 hr = IMFPresentationTimeSource_GetClockCharacteristics(time_source, &value);
2592 ok(hr == S_OK, "Failed to get time source flags, hr %#lx.\n", hr);
2593 ok(value == (MFCLOCK_CHARACTERISTICS_FLAG_FREQUENCY_10MHZ | MFCLOCK_CHARACTERISTICS_FLAG_IS_SYSTEM_CLOCK),
2594 "Unexpected clock flags %#lx.\n", value);
2596 hr = IMFPresentationClock_SetTimeSource(clock, time_source);
2597 ok(hr == S_OK, "Failed to set time source, hr %#lx.\n", hr);
2599 hr = IMFPresentationTimeSource_GetProperties(time_source, &props2);
2600 ok(hr == S_OK, "Failed to get time source properties, hr %#lx.\n", hr);
2602 hr = IMFPresentationClock_GetClockCharacteristics(clock, &value);
2603 ok(hr == S_OK, "Failed to get clock flags, hr %#lx.\n", hr);
2604 ok(value == (MFCLOCK_CHARACTERISTICS_FLAG_FREQUENCY_10MHZ | MFCLOCK_CHARACTERISTICS_FLAG_IS_SYSTEM_CLOCK),
2605 "Unexpected clock flags %#lx.\n", value);
2607 hr = IMFPresentationClock_GetProperties(clock, &props);
2608 ok(hr == S_OK, "Failed to get clock properties, hr %#lx.\n", hr);
2609 ok(!memcmp(&props, &props2, sizeof(props)), "Unexpected clock properties.\n");
2611 /* Changing rate at initial state. */
2612 hr = IMFPresentationClock_GetState(clock, 0, &state);
2613 ok(hr == S_OK, "Failed to get clock state, hr %#lx.\n", hr);
2614 ok(state == MFCLOCK_STATE_INVALID, "Unexpected state %d.\n", state);
2616 hr = IMFRateControl_SetRate(rate_control, FALSE, 0.0f);
2617 ok(hr == S_OK, "Failed to set clock rate, hr %#lx.\n", hr);
2618 hr = IMFRateControl_GetRate(rate_control, &thin, &rate);
2619 ok(hr == S_OK, "Failed to get clock rate, hr %#lx.\n", hr);
2620 ok(rate == 0.0f, "Unexpected rate.\n");
2621 hr = IMFRateControl_SetRate(rate_control, FALSE, 1.0f);
2622 ok(hr == S_OK, "Failed to set clock rate, hr %#lx.\n", hr);
2624 /* State changes. */
2625 for (i = 0; i < ARRAY_SIZE(clock_state_change); ++i)
2627 switch (clock_state_change[i].action)
2629 case CLOCK_STOP:
2630 hr = IMFPresentationClock_Stop(clock);
2631 break;
2632 case CLOCK_PAUSE:
2633 hr = IMFPresentationClock_Pause(clock);
2634 break;
2635 case CLOCK_START:
2636 hr = IMFPresentationClock_Start(clock, 0);
2637 break;
2638 default:
2641 ok(hr == clock_state_change[i].hr, "%u: unexpected hr %#lx.\n", i, hr);
2643 hr = IMFPresentationTimeSource_GetState(time_source, 0, &state);
2644 ok(hr == S_OK, "%u: failed to get state, hr %#lx.\n", i, hr);
2645 ok(state == clock_state_change[i].source_state, "%u: unexpected state %d.\n", i, state);
2647 hr = IMFPresentationClock_GetState(clock, 0, &state);
2648 ok(hr == S_OK, "%u: failed to get state, hr %#lx.\n", i, hr);
2649 ok(state == clock_state_change[i].clock_state, "%u: unexpected state %d.\n", i, state);
2652 /* Clock time stamps. */
2653 hr = IMFPresentationClock_Start(clock, 10);
2654 ok(hr == S_OK, "Failed to start presentation clock, hr %#lx.\n", hr);
2656 hr = IMFPresentationClock_Pause(clock);
2657 ok(hr == S_OK, "Failed to pause presentation clock, hr %#lx.\n", hr);
2659 hr = IMFPresentationClock_GetTime(clock, &time);
2660 ok(hr == S_OK, "Failed to get clock time, hr %#lx.\n", hr);
2662 hr = IMFPresentationTimeSource_GetCorrelatedTime(time_source, 0, &clock_time, &systime);
2663 ok(hr == S_OK, "Failed to get time source time, hr %#lx.\n", hr);
2664 ok(time == clock_time, "Unexpected clock time.\n");
2666 hr = IMFPresentationClock_GetCorrelatedTime(clock, 0, &time, &systime);
2667 ok(hr == S_OK, "Failed to get clock time, hr %#lx.\n", hr);
2668 ok(time == clock_time, "Unexpected clock time.\n");
2670 IMFPresentationTimeSource_Release(time_source);
2672 hr = IMFRateControl_GetRate(rate_control, NULL, &rate);
2673 ok(hr == S_OK, "Failed to get clock rate, hr %#lx.\n", hr);
2675 hr = IMFRateControl_GetRate(rate_control, &thin, NULL);
2676 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
2678 hr = IMFRateControl_GetRate(rate_control, &thin, &rate);
2679 ok(hr == S_OK, "Failed to get clock rate, hr %#lx.\n", hr);
2680 ok(rate == 1.0f, "Unexpected rate.\n");
2681 ok(!thin, "Unexpected thinning.\n");
2683 hr = IMFPresentationClock_GetState(clock, 0, &state);
2684 ok(hr == S_OK, "Failed to get clock state, hr %#lx.\n", hr);
2685 ok(state == MFCLOCK_STATE_PAUSED, "Unexpected state %d.\n", state);
2687 hr = IMFPresentationClock_Start(clock, 0);
2688 ok(hr == S_OK, "Failed to stop, hr %#lx.\n", hr);
2690 hr = IMFRateControl_SetRate(rate_control, FALSE, 0.0f);
2691 ok(hr == S_OK, "Failed to set clock rate, hr %#lx.\n", hr);
2692 hr = IMFRateControl_GetRate(rate_control, &thin, &rate);
2693 ok(hr == S_OK, "Failed to get clock rate, hr %#lx.\n", hr);
2694 ok(rate == 0.0f, "Unexpected rate.\n");
2695 hr = IMFRateControl_SetRate(rate_control, FALSE, 1.0f);
2696 ok(hr == S_OK, "Failed to set clock rate, hr %#lx.\n", hr);
2697 hr = IMFRateControl_SetRate(rate_control, FALSE, 0.0f);
2698 ok(hr == S_OK, "Failed to set clock rate, hr %#lx.\n", hr);
2699 hr = IMFRateControl_SetRate(rate_control, FALSE, 0.5f);
2700 ok(hr == S_OK, "Failed to set clock rate, hr %#lx.\n", hr);
2701 hr = IMFRateControl_SetRate(rate_control, TRUE, -1.0f);
2702 ok(hr == MF_E_THINNING_UNSUPPORTED, "Unexpected hr %#lx.\n", hr);
2703 hr = IMFRateControl_SetRate(rate_control, TRUE, 0.0f);
2704 ok(hr == MF_E_THINNING_UNSUPPORTED, "Unexpected hr %#lx.\n", hr);
2705 hr = IMFRateControl_SetRate(rate_control, TRUE, 1.0f);
2706 ok(hr == MF_E_THINNING_UNSUPPORTED, "Unexpected hr %#lx.\n", hr);
2708 hr = IMFPresentationClock_GetState(clock, 0, &state);
2709 ok(hr == S_OK, "Failed to get clock state, hr %#lx.\n", hr);
2710 ok(state == MFCLOCK_STATE_RUNNING, "Unexpected state %d.\n", state);
2712 hr = IMFRateControl_GetRate(rate_control, &thin, &rate);
2713 ok(hr == S_OK, "Failed to get clock rate, hr %#lx.\n", hr);
2714 ok(rate == 0.5f, "Unexpected rate.\n");
2715 ok(!thin, "Unexpected thinning.\n");
2717 IMFRateControl_Release(rate_control);
2719 hr = IMFPresentationClock_QueryInterface(clock, &IID_IMFShutdown, (void **)&shutdown);
2720 ok(hr == S_OK, "Failed to get shutdown interface, hr %#lx.\n", hr);
2722 /* Shutdown behavior. */
2723 hr = IMFShutdown_GetShutdownStatus(shutdown, NULL);
2724 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
2726 hr = IMFShutdown_GetShutdownStatus(shutdown, &status);
2727 ok(hr == MF_E_INVALIDREQUEST, "Unexpected hr %#lx.\n", hr);
2729 hr = IMFShutdown_Shutdown(shutdown);
2730 ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr);
2732 time_source = NULL;
2733 hr = IMFPresentationClock_GetTimeSource(clock, &time_source);
2734 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2735 ok(!!time_source, "Unexpected instance %p.\n", time_source);
2736 IMFPresentationTimeSource_Release(time_source);
2738 hr = IMFPresentationClock_GetTime(clock, &time);
2739 ok(hr == S_OK, "Failed to get time, hr %#lx.\n", hr);
2741 hr = IMFShutdown_GetShutdownStatus(shutdown, &status);
2742 ok(hr == S_OK, "Failed to get status, hr %#lx.\n", hr);
2743 ok(status == MFSHUTDOWN_COMPLETED, "Unexpected status.\n");
2745 hr = IMFPresentationClock_Start(clock, 0);
2746 ok(hr == S_OK, "Failed to start the clock, hr %#lx.\n", hr);
2748 hr = IMFShutdown_GetShutdownStatus(shutdown, &status);
2749 ok(hr == S_OK, "Failed to get status, hr %#lx.\n", hr);
2750 ok(status == MFSHUTDOWN_COMPLETED, "Unexpected status.\n");
2752 hr = IMFShutdown_Shutdown(shutdown);
2753 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2755 IMFShutdown_Release(shutdown);
2757 IMFPresentationClock_Release(clock);
2759 hr = MFShutdown();
2760 ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr);
2763 static HRESULT WINAPI grabber_callback_QueryInterface(IMFSampleGrabberSinkCallback *iface, REFIID riid, void **obj)
2765 if (IsEqualIID(riid, &IID_IMFSampleGrabberSinkCallback) ||
2766 IsEqualIID(riid, &IID_IMFClockStateSink) ||
2767 IsEqualIID(riid, &IID_IUnknown))
2769 *obj = iface;
2770 IMFSampleGrabberSinkCallback_AddRef(iface);
2771 return S_OK;
2774 *obj = NULL;
2775 return E_NOINTERFACE;
2778 static ULONG WINAPI grabber_callback_AddRef(IMFSampleGrabberSinkCallback *iface)
2780 return 2;
2783 static ULONG WINAPI grabber_callback_Release(IMFSampleGrabberSinkCallback *iface)
2785 return 1;
2788 static HRESULT WINAPI grabber_callback_OnClockStart(IMFSampleGrabberSinkCallback *iface, MFTIME time, LONGLONG offset)
2790 return E_NOTIMPL;
2793 static HRESULT WINAPI grabber_callback_OnClockStop(IMFSampleGrabberSinkCallback *iface, MFTIME time)
2795 return E_NOTIMPL;
2798 static HRESULT WINAPI grabber_callback_OnClockPause(IMFSampleGrabberSinkCallback *iface, MFTIME time)
2800 return E_NOTIMPL;
2803 static HRESULT WINAPI grabber_callback_OnClockRestart(IMFSampleGrabberSinkCallback *iface, MFTIME time)
2805 return E_NOTIMPL;
2808 static HRESULT WINAPI grabber_callback_OnClockSetRate(IMFSampleGrabberSinkCallback *iface, MFTIME time, float rate)
2810 return E_NOTIMPL;
2813 static HRESULT WINAPI grabber_callback_OnSetPresentationClock(IMFSampleGrabberSinkCallback *iface,
2814 IMFPresentationClock *clock)
2816 return S_OK;
2819 static HRESULT WINAPI grabber_callback_OnProcessSample(IMFSampleGrabberSinkCallback *iface, REFGUID major_type,
2820 DWORD sample_flags, LONGLONG sample_time, LONGLONG sample_duration, const BYTE *buffer, DWORD sample_size)
2822 return E_NOTIMPL;
2825 static HRESULT WINAPI grabber_callback_OnShutdown(IMFSampleGrabberSinkCallback *iface)
2827 return S_OK;
2830 static const IMFSampleGrabberSinkCallbackVtbl grabber_callback_vtbl =
2832 grabber_callback_QueryInterface,
2833 grabber_callback_AddRef,
2834 grabber_callback_Release,
2835 grabber_callback_OnClockStart,
2836 grabber_callback_OnClockStop,
2837 grabber_callback_OnClockPause,
2838 grabber_callback_OnClockRestart,
2839 grabber_callback_OnClockSetRate,
2840 grabber_callback_OnSetPresentationClock,
2841 grabber_callback_OnProcessSample,
2842 grabber_callback_OnShutdown,
2845 static IMFSampleGrabberSinkCallback grabber_callback = { &grabber_callback_vtbl };
2847 static void test_sample_grabber(void)
2849 IMFMediaType *media_type, *media_type2, *media_type3;
2850 IMFMediaTypeHandler *handler, *handler2;
2851 IMFPresentationTimeSource *time_source;
2852 IMFPresentationClock *clock, *clock2;
2853 IMFStreamSink *stream, *stream2;
2854 IMFRateSupport *rate_support;
2855 IMFMediaEventGenerator *eg;
2856 IMFMediaSink *sink, *sink2;
2857 DWORD flags, count, id;
2858 IMFActivate *activate;
2859 IMFMediaEvent *event;
2860 UINT32 attr_count;
2861 ULONG refcount;
2862 IUnknown *unk;
2863 float rate;
2864 HRESULT hr;
2865 GUID guid;
2867 hr = MFStartup(MF_VERSION, MFSTARTUP_FULL);
2868 ok(hr == S_OK, "Failed to start up, hr %#lx.\n", hr);
2870 hr = MFCreateMediaType(&media_type);
2871 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
2873 hr = MFCreateSampleGrabberSinkActivate(NULL, NULL, &activate);
2874 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
2876 hr = MFCreateSampleGrabberSinkActivate(NULL, &grabber_callback, &activate);
2877 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
2879 hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio);
2880 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
2881 hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFAudioFormat_PCM);
2882 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
2884 EXPECT_REF(media_type, 1);
2885 hr = MFCreateSampleGrabberSinkActivate(media_type, &grabber_callback, &activate);
2886 ok(hr == S_OK, "Failed to create grabber activate, hr %#lx.\n", hr);
2887 EXPECT_REF(media_type, 2);
2889 hr = IMFActivate_GetCount(activate, &attr_count);
2890 ok(hr == S_OK, "Failed to get attribute count, hr %#lx.\n", hr);
2891 ok(!attr_count, "Unexpected count %u.\n", attr_count);
2893 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink);
2894 ok(hr == S_OK, "Failed to activate object, hr %#lx.\n", hr);
2896 check_interface(sink, &IID_IMFClockStateSink, TRUE);
2897 check_interface(sink, &IID_IMFMediaEventGenerator, TRUE);
2898 check_interface(sink, &IID_IMFGetService, TRUE);
2899 check_interface(sink, &IID_IMFRateSupport, TRUE);
2900 check_service_interface(sink, &MF_RATE_CONTROL_SERVICE, &IID_IMFRateSupport, TRUE);
2902 if (SUCCEEDED(MFGetService((IUnknown *)sink, &MF_RATE_CONTROL_SERVICE, &IID_IMFRateSupport, (void **)&rate_support)))
2904 hr = IMFRateSupport_GetFastestRate(rate_support, MFRATE_FORWARD, FALSE, &rate);
2905 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2906 ok(rate == FLT_MAX, "Unexpected rate %f.\n", rate);
2908 hr = IMFRateSupport_GetFastestRate(rate_support, MFRATE_FORWARD, TRUE, &rate);
2909 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2910 ok(rate == FLT_MAX, "Unexpected rate %f.\n", rate);
2912 hr = IMFRateSupport_GetFastestRate(rate_support, MFRATE_REVERSE, FALSE, &rate);
2913 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2914 ok(rate == -FLT_MAX, "Unexpected rate %f.\n", rate);
2916 hr = IMFRateSupport_GetFastestRate(rate_support, MFRATE_REVERSE, TRUE, &rate);
2917 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2918 ok(rate == -FLT_MAX, "Unexpected rate %f.\n", rate);
2920 hr = IMFRateSupport_GetSlowestRate(rate_support, MFRATE_FORWARD, FALSE, &rate);
2921 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2922 ok(rate == 0.0f, "Unexpected rate %f.\n", rate);
2924 hr = IMFRateSupport_GetSlowestRate(rate_support, MFRATE_FORWARD, TRUE, &rate);
2925 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2926 ok(rate == 0.0f, "Unexpected rate %f.\n", rate);
2928 hr = IMFRateSupport_GetSlowestRate(rate_support, MFRATE_REVERSE, FALSE, &rate);
2929 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2930 ok(rate == 0.0f, "Unexpected rate %f.\n", rate);
2932 hr = IMFRateSupport_GetSlowestRate(rate_support, MFRATE_REVERSE, TRUE, &rate);
2933 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2934 ok(rate == 0.0f, "Unexpected rate %f.\n", rate);
2936 hr = IMFRateSupport_IsRateSupported(rate_support, TRUE, 1.0f, &rate);
2937 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2938 ok(rate == 1.0f, "Unexpected rate %f.\n", rate);
2940 IMFRateSupport_Release(rate_support);
2943 hr = IMFMediaSink_GetCharacteristics(sink, &flags);
2944 ok(hr == S_OK, "Failed to get sink flags, hr %#lx.\n", hr);
2945 ok(flags & MEDIASINK_FIXED_STREAMS, "Unexpected flags %#lx.\n", flags);
2947 hr = IMFMediaSink_GetStreamSinkCount(sink, &count);
2948 ok(hr == S_OK, "Failed to get stream count, hr %#lx.\n", hr);
2949 ok(count == 1, "Unexpected stream count %lu.\n", count);
2951 hr = IMFMediaSink_GetStreamSinkByIndex(sink, 0, &stream);
2952 ok(hr == S_OK, "Failed to get sink stream, hr %#lx.\n", hr);
2954 check_interface(stream, &IID_IMFMediaEventGenerator, TRUE);
2955 check_interface(stream, &IID_IMFMediaTypeHandler, TRUE);
2957 hr = IMFStreamSink_GetIdentifier(stream, &id);
2958 ok(hr == S_OK, "Failed to get stream id, hr %#lx.\n", hr);
2959 ok(id == 0, "Unexpected id %#lx.\n", id);
2961 hr = IMFStreamSink_GetMediaSink(stream, &sink2);
2962 ok(hr == S_OK, "Failed to get media sink, hr %lx.\n", hr);
2963 ok(sink2 == sink, "Unexpected sink.\n");
2964 IMFMediaSink_Release(sink2);
2966 hr = IMFMediaSink_GetStreamSinkByIndex(sink, 1, &stream2);
2967 ok(hr == MF_E_INVALIDINDEX, "Unexpected hr %#lx.\n", hr);
2969 hr = IMFMediaSink_GetStreamSinkById(sink, 1, &stream2);
2970 ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#lx.\n", hr);
2972 hr = IMFMediaSink_AddStreamSink(sink, 1, NULL, &stream2);
2973 ok(hr == MF_E_STREAMSINKS_FIXED, "Unexpected hr %#lx.\n", hr);
2975 hr = IMFMediaSink_RemoveStreamSink(sink, 0);
2976 ok(hr == MF_E_STREAMSINKS_FIXED, "Unexpected hr %#lx.\n", hr);
2978 hr = IMFMediaSink_RemoveStreamSink(sink, 1);
2979 ok(hr == MF_E_STREAMSINKS_FIXED, "Unexpected hr %#lx.\n", hr);
2981 check_interface(sink, &IID_IMFClockStateSink, TRUE);
2983 /* Event generator. */
2984 hr = IMFMediaSink_QueryInterface(sink, &IID_IMFMediaEventGenerator, (void **)&eg);
2985 ok(hr == S_OK, "Failed to get interface, hr %#lx.\n", hr);
2987 hr = IMFMediaEventGenerator_GetEvent(eg, MF_EVENT_FLAG_NO_WAIT, &event);
2988 ok(hr == MF_E_NO_EVENTS_AVAILABLE, "Unexpected hr %#lx.\n", hr);
2990 hr = IMFMediaSink_QueryInterface(sink, &IID_IMFPresentationTimeSource, (void **)&unk);
2991 ok(hr == E_NOINTERFACE, "Unexpected hr %#lx.\n", hr);
2993 hr = IMFStreamSink_QueryInterface(stream, &IID_IMFMediaTypeHandler, (void **)&handler2);
2994 ok(hr == S_OK, "Failed to get handler interface, hr %#lx.\n", hr);
2996 hr = IMFStreamSink_GetMediaTypeHandler(stream, &handler);
2997 ok(hr == S_OK, "Failed to get type handler, hr %#lx.\n", hr);
2998 hr = IMFMediaTypeHandler_GetMediaTypeCount(handler, &count);
2999 ok(hr == S_OK, "Failed to get media type count, hr %#lx.\n", hr);
3000 ok(count == 0, "Unexpected count %lu.\n", count);
3001 ok(handler == handler2, "Unexpected handler.\n");
3003 IMFMediaTypeHandler_Release(handler);
3004 IMFMediaTypeHandler_Release(handler2);
3006 /* Set clock. */
3007 hr = MFCreatePresentationClock(&clock);
3008 ok(hr == S_OK, "Failed to create clock object, hr %#lx.\n", hr);
3010 hr = IMFMediaSink_GetPresentationClock(sink, NULL);
3011 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
3013 hr = IMFMediaSink_GetPresentationClock(sink, &clock2);
3014 ok(hr == MF_E_NO_CLOCK, "Unexpected hr %#lx.\n", hr);
3016 hr = IMFMediaSink_SetPresentationClock(sink, NULL);
3017 ok(hr == S_OK, "Failed to set presentation clock, hr %#lx.\n", hr);
3019 hr = IMFMediaSink_SetPresentationClock(sink, clock);
3020 ok(hr == S_OK, "Failed to set presentation clock, hr %#lx.\n", hr);
3022 hr = MFCreateSystemTimeSource(&time_source);
3023 ok(hr == S_OK, "Failed to create time source, hr %#lx.\n", hr);
3025 hr = IMFPresentationClock_SetTimeSource(clock, time_source);
3026 ok(hr == S_OK, "Failed to set time source, hr %#lx.\n", hr);
3027 IMFPresentationTimeSource_Release(time_source);
3029 hr = IMFMediaSink_GetCharacteristics(sink, &flags);
3030 ok(hr == S_OK, "Failed to get sink flags, hr %#lx.\n", hr);
3032 hr = IMFActivate_ShutdownObject(activate);
3033 ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr);
3035 hr = IMFMediaSink_GetCharacteristics(sink, &flags);
3036 ok(hr == S_OK, "Failed to get sink flags, hr %#lx.\n", hr);
3038 hr = IMFStreamSink_GetMediaTypeHandler(stream, &handler);
3039 ok(hr == S_OK, "Failed to get type handler, hr %#lx.\n", hr);
3041 /* On Win8+ this initialization happens automatically. */
3042 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, media_type);
3043 ok(hr == S_OK, "Failed to set media type, hr %#lx.\n", hr);
3045 hr = IMFMediaTypeHandler_GetMediaTypeCount(handler, NULL);
3046 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
3048 hr = IMFMediaTypeHandler_GetMediaTypeCount(handler, &count);
3049 ok(hr == S_OK, "Failed to get media type count, hr %#lx.\n", hr);
3050 ok(count == 0, "Unexpected count %lu.\n", count);
3052 hr = IMFMediaTypeHandler_GetMajorType(handler, &guid);
3053 ok(hr == S_OK, "Failed to get major type, hr %#lx.\n", hr);
3054 ok(IsEqualGUID(&guid, &MFMediaType_Audio), "Unexpected major type %s.\n", wine_dbgstr_guid(&guid));
3056 hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, &media_type2);
3057 ok(hr == S_OK, "Failed to get current type, hr %#lx.\n", hr);
3058 ok(media_type2 == media_type, "Unexpected media type.\n");
3059 IMFMediaType_Release(media_type2);
3061 hr = MFCreateMediaType(&media_type2);
3062 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
3064 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, media_type2);
3065 ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#lx.\n", hr);
3067 hr = IMFMediaType_SetGUID(media_type2, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio);
3068 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3070 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, media_type2);
3071 ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#lx.\n", hr);
3073 hr = IMFMediaType_SetGUID(media_type2, &MF_MT_SUBTYPE, &MFAudioFormat_Float);
3074 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3076 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, media_type2);
3077 ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#lx.\n", hr);
3079 hr = IMFMediaType_SetGUID(media_type2, &MF_MT_SUBTYPE, &MFAudioFormat_PCM);
3080 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3082 hr = IMFMediaType_SetUINT32(media_type2, &MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100);
3083 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3085 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, media_type2);
3086 ok(hr == S_OK, "Failed to get current type, hr %#lx.\n", hr);
3087 IMFMediaType_Release(media_type);
3089 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, NULL);
3090 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
3092 hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, &media_type);
3093 ok(hr == S_OK, "Failed to get current type, hr %#lx.\n", hr);
3094 ok(media_type2 == media_type, "Unexpected media type.\n");
3095 IMFMediaType_Release(media_type);
3097 hr = IMFMediaTypeHandler_GetMediaTypeByIndex(handler, 0, &media_type);
3098 ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#lx.\n", hr);
3100 hr = IMFMediaTypeHandler_GetMediaTypeByIndex(handler, 0, NULL);
3101 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
3103 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type2, NULL);
3104 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3106 hr = MFCreateMediaType(&media_type);
3107 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
3109 hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio);
3110 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3112 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type, NULL);
3113 ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#lx.\n", hr);
3115 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type, &media_type3);
3116 ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#lx.\n", hr);
3118 hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFAudioFormat_PCM);
3119 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3121 media_type3 = (void *)0xdeadbeef;
3122 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type, &media_type3);
3123 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3124 ok(media_type3 == (void *)0xdeadbeef, "Unexpected media type %p.\n", media_type3);
3126 hr = IMFMediaType_SetUINT32(media_type, &MF_MT_FIXED_SIZE_SAMPLES, 1);
3127 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3129 hr = IMFMediaType_SetUINT32(media_type, &MF_MT_SAMPLE_SIZE, 1024);
3130 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3132 media_type3 = (void *)0xdeadbeef;
3133 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type, &media_type3);
3134 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3135 ok(media_type3 == (void *)0xdeadbeef, "Unexpected media type %p.\n", media_type3);
3137 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, NULL, NULL);
3138 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
3140 hr = IMFMediaEventGenerator_GetEvent(eg, MF_EVENT_FLAG_NO_WAIT, &event);
3141 ok(hr == MF_E_NO_EVENTS_AVAILABLE, "Unexpected hr %#lx.\n", hr);
3143 hr = IMFStreamSink_GetEvent(stream, MF_EVENT_FLAG_NO_WAIT, &event);
3144 ok(hr == MF_E_NO_EVENTS_AVAILABLE, "Unexpected hr %#lx.\n", hr);
3146 EXPECT_REF(clock, 3);
3147 hr = IMFMediaSink_Shutdown(sink);
3148 ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr);
3149 EXPECT_REF(clock, 1);
3151 hr = IMFMediaEventGenerator_GetEvent(eg, MF_EVENT_FLAG_NO_WAIT, &event);
3152 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
3154 hr = IMFMediaSink_Shutdown(sink);
3155 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
3157 hr = IMFMediaSink_GetCharacteristics(sink, &flags);
3158 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
3160 hr = IMFMediaSink_AddStreamSink(sink, 1, NULL, &stream2);
3161 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
3163 hr = IMFMediaSink_GetStreamSinkCount(sink, &count);
3164 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
3166 hr = IMFMediaSink_GetStreamSinkByIndex(sink, 0, &stream2);
3167 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
3169 hr = IMFStreamSink_GetEvent(stream, MF_EVENT_FLAG_NO_WAIT, &event);
3170 ok(hr == MF_E_STREAMSINK_REMOVED, "Unexpected hr %#lx.\n", hr);
3172 hr = IMFStreamSink_GetMediaSink(stream, &sink2);
3173 ok(hr == MF_E_STREAMSINK_REMOVED, "Unexpected hr %#lx.\n", hr);
3175 id = 1;
3176 hr = IMFStreamSink_GetIdentifier(stream, &id);
3177 ok(hr == MF_E_STREAMSINK_REMOVED, "Unexpected hr %#lx.\n", hr);
3178 ok(id == 1, "Unexpected id %lu.\n", id);
3180 media_type3 = (void *)0xdeadbeef;
3181 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type, &media_type3);
3182 ok(hr == MF_E_STREAMSINK_REMOVED, "Unexpected hr %#lx.\n", hr);
3183 ok(media_type3 == (void *)0xdeadbeef, "Unexpected media type %p.\n", media_type3);
3185 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, NULL, NULL);
3186 ok(hr == MF_E_STREAMSINK_REMOVED, "Unexpected hr %#lx.\n", hr);
3188 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, NULL);
3189 ok(hr == MF_E_STREAMSINK_REMOVED, "Unexpected hr %#lx.\n", hr);
3191 hr = IMFMediaTypeHandler_GetMediaTypeCount(handler, &count);
3192 ok(hr == S_OK, "Failed to get type count, hr %#lx.\n", hr);
3194 IMFMediaType_Release(media_type2);
3195 IMFMediaType_Release(media_type);
3197 hr = IMFMediaTypeHandler_GetMediaTypeByIndex(handler, 0, &media_type);
3198 ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#lx.\n", hr);
3200 hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, &media_type);
3201 ok(hr == MF_E_STREAMSINK_REMOVED, "Unexpected hr %#lx.\n", hr);
3203 hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, NULL);
3204 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
3206 hr = IMFMediaTypeHandler_GetMajorType(handler, NULL);
3207 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
3209 hr = IMFMediaTypeHandler_GetMajorType(handler, &guid);
3210 ok(hr == MF_E_STREAMSINK_REMOVED, "Unexpected hr %#lx.\n", hr);
3212 IMFMediaTypeHandler_Release(handler);
3214 handler = (void *)0xdeadbeef;
3215 hr = IMFStreamSink_GetMediaTypeHandler(stream, &handler);
3216 ok(hr == MF_E_STREAMSINK_REMOVED, "Unexpected hr %#lx.\n", hr);
3217 ok(handler == (void *)0xdeadbeef, "Unexpected pointer.\n");
3219 hr = IMFStreamSink_GetMediaTypeHandler(stream, NULL);
3220 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
3222 IMFMediaEventGenerator_Release(eg);
3223 IMFMediaSink_Release(sink);
3224 IMFStreamSink_Release(stream);
3226 refcount = IMFActivate_Release(activate);
3227 ok(!refcount, "Unexpected refcount %lu.\n", refcount);
3229 /* Rateless mode with MF_SAMPLEGRABBERSINK_IGNORE_CLOCK. */
3230 hr = MFCreateMediaType(&media_type);
3231 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
3233 hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio);
3234 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3235 hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFAudioFormat_PCM);
3236 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3238 hr = MFCreateSampleGrabberSinkActivate(media_type, &grabber_callback, &activate);
3239 ok(hr == S_OK, "Failed to create grabber activate, hr %#lx.\n", hr);
3241 hr = IMFActivate_SetUINT32(activate, &MF_SAMPLEGRABBERSINK_IGNORE_CLOCK, 1);
3242 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3244 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink);
3245 ok(hr == S_OK, "Failed to activate object, hr %#lx.\n", hr);
3247 hr = IMFMediaSink_GetCharacteristics(sink, &flags);
3248 ok(hr == S_OK, "Failed to get sink flags, hr %#lx.\n", hr);
3249 ok(flags & MEDIASINK_RATELESS, "Unexpected flags %#lx.\n", flags);
3251 hr = IMFActivate_ShutdownObject(activate);
3252 ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr);
3254 hr = IMFMediaSink_Shutdown(sink);
3255 ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr);
3257 IMFMediaSink_Release(sink);
3259 /* Detaching */
3260 hr = MFCreateSampleGrabberSinkActivate(media_type, &grabber_callback, &activate);
3261 ok(hr == S_OK, "Failed to create grabber activate, hr %#lx.\n", hr);
3263 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink);
3264 ok(hr == S_OK, "Failed to activate object, hr %#lx.\n", hr);
3265 IMFMediaSink_Release(sink);
3267 hr = IMFActivate_ShutdownObject(activate);
3268 ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr);
3270 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink);
3271 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
3273 hr = IMFActivate_GetCount(activate, &attr_count);
3274 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3276 hr = IMFActivate_DetachObject(activate);
3277 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
3279 IMFActivate_Release(activate);
3281 IMFMediaType_Release(media_type);
3282 IMFPresentationClock_Release(clock);
3284 hr = MFShutdown();
3285 ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr);
3288 static void test_sample_grabber_is_mediatype_supported(void)
3290 IMFMediaType *media_type, *media_type2, *media_type3;
3291 IMFMediaTypeHandler *handler;
3292 IMFActivate *activate;
3293 IMFStreamSink *stream;
3294 IMFMediaSink *sink;
3295 ULONG refcount;
3296 HRESULT hr;
3297 GUID guid;
3299 /* IsMediaTypeSupported checks are done against the creation type, and check format data */
3300 hr = MFCreateMediaType(&media_type);
3301 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
3303 hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio);
3304 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3305 hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFAudioFormat_PCM);
3306 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3307 hr = IMFMediaType_SetUINT32(media_type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100);
3308 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3310 hr = MFCreateSampleGrabberSinkActivate(media_type, &grabber_callback, &activate);
3311 ok(hr == S_OK, "Failed to create grabber activate, hr %#lx.\n", hr);
3313 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink);
3314 ok(hr == S_OK, "Failed to activate object, hr %#lx.\n", hr);
3316 hr = IMFMediaSink_GetStreamSinkByIndex(sink, 0, &stream);
3317 ok(hr == S_OK, "Failed to get sink stream, hr %#lx.\n", hr);
3318 hr = IMFStreamSink_GetMediaTypeHandler(stream, &handler);
3319 ok(hr == S_OK, "Failed to get type handler, hr %#lx.\n", hr);
3320 IMFStreamSink_Release(stream);
3322 IMFMediaSink_Release(sink);
3324 /* On Win8+ this initialization happens automatically. */
3325 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, media_type);
3326 ok(hr == S_OK, "Failed to set media type, hr %#lx.\n", hr);
3328 hr = MFCreateMediaType(&media_type2);
3329 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
3331 hr = IMFMediaType_SetGUID(media_type2, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio);
3332 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3333 hr = IMFMediaType_SetGUID(media_type2, &MF_MT_SUBTYPE, &MFAudioFormat_PCM);
3334 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3335 hr = IMFMediaType_SetUINT32(media_type2, &MF_MT_AUDIO_SAMPLES_PER_SECOND, 48000);
3336 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3338 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type2, NULL);
3339 ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#lx.\n", hr);
3341 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, media_type2);
3342 ok(hr == MF_E_INVALIDMEDIATYPE, "Failed to set media type, hr %#lx.\n", hr);
3344 /* Make it match grabber type sample rate. */
3345 hr = IMFMediaType_SetUINT32(media_type2, &MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100);
3346 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3348 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type2, NULL);
3349 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3351 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, media_type2);
3352 ok(hr == S_OK, "Failed to set media type, hr %#lx.\n", hr);
3353 hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, &media_type3);
3354 ok(hr == S_OK, "Failed to set media type, hr %#lx.\n", hr);
3355 ok(media_type3 == media_type2, "Unexpected media type instance.\n");
3356 IMFMediaType_Release(media_type3);
3358 /* Change original type. */
3359 hr = IMFMediaType_SetUINT32(media_type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, 48000);
3360 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3362 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type2, NULL);
3363 ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#lx.\n", hr);
3365 hr = IMFMediaType_SetUINT32(media_type2, &MF_MT_AUDIO_SAMPLES_PER_SECOND, 48000);
3366 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3368 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type2, NULL);
3369 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3371 hr = IMFMediaTypeHandler_GetMajorType(handler, &guid);
3372 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3373 ok(IsEqualGUID(&guid, &MFMediaType_Audio), "Unexpected major type.\n");
3375 hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
3376 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3378 hr = IMFMediaTypeHandler_GetMajorType(handler, &guid);
3379 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3380 ok(IsEqualGUID(&guid, &MFMediaType_Audio), "Unexpected major type.\n");
3382 IMFMediaType_Release(media_type2);
3383 IMFMediaType_Release(media_type);
3385 IMFMediaTypeHandler_Release(handler);
3387 refcount = IMFActivate_Release(activate);
3388 ok(!refcount, "Unexpected refcount %lu.\n", refcount);
3391 static BOOL is_supported_video_type(const GUID *guid)
3393 return IsEqualGUID(guid, &MFVideoFormat_L8)
3394 || IsEqualGUID(guid, &MFVideoFormat_L16)
3395 || IsEqualGUID(guid, &MFVideoFormat_D16)
3396 || IsEqualGUID(guid, &MFVideoFormat_IYUV)
3397 || IsEqualGUID(guid, &MFVideoFormat_YV12)
3398 || IsEqualGUID(guid, &MFVideoFormat_NV12)
3399 || IsEqualGUID(guid, &MFVideoFormat_NV21)
3400 || IsEqualGUID(guid, &MFVideoFormat_420O)
3401 || IsEqualGUID(guid, &MFVideoFormat_P010)
3402 || IsEqualGUID(guid, &MFVideoFormat_P016)
3403 || IsEqualGUID(guid, &MFVideoFormat_UYVY)
3404 || IsEqualGUID(guid, &MFVideoFormat_YUY2)
3405 || IsEqualGUID(guid, &MFVideoFormat_P208)
3406 || IsEqualGUID(guid, &MFVideoFormat_NV11)
3407 || IsEqualGUID(guid, &MFVideoFormat_AYUV)
3408 || IsEqualGUID(guid, &MFVideoFormat_ARGB32)
3409 || IsEqualGUID(guid, &MFVideoFormat_RGB32)
3410 || IsEqualGUID(guid, &MFVideoFormat_A2R10G10B10)
3411 || IsEqualGUID(guid, &MFVideoFormat_A16B16G16R16F)
3412 || IsEqualGUID(guid, &MFVideoFormat_RGB24)
3413 || IsEqualGUID(guid, &MFVideoFormat_I420)
3414 || IsEqualGUID(guid, &MFVideoFormat_YVYU)
3415 || IsEqualGUID(guid, &MFVideoFormat_RGB555)
3416 || IsEqualGUID(guid, &MFVideoFormat_RGB565)
3417 || IsEqualGUID(guid, &MFVideoFormat_RGB8)
3418 || IsEqualGUID(guid, &MFVideoFormat_Y216)
3419 || IsEqualGUID(guid, &MFVideoFormat_v410)
3420 || IsEqualGUID(guid, &MFVideoFormat_Y41P)
3421 || IsEqualGUID(guid, &MFVideoFormat_Y41T)
3422 || IsEqualGUID(guid, &MFVideoFormat_Y42T)
3423 || IsEqualGUID(guid, &MFVideoFormat_ABGR32);
3426 static void test_video_processor(void)
3428 DWORD input_count, output_count, input_id, output_id, flags;
3429 DWORD input_min, input_max, output_min, output_max, i;
3430 IMFAttributes *attributes, *attributes2;
3431 IMFMediaType *media_type, *media_type2;
3432 MFT_OUTPUT_DATA_BUFFER output_buffer;
3433 MFT_OUTPUT_STREAM_INFO output_info;
3434 MFT_INPUT_STREAM_INFO input_info;
3435 IMFSample *sample, *sample2;
3436 IMFTransform *transform;
3437 IMFMediaBuffer *buffer;
3438 IMFMediaEvent *event;
3439 unsigned int value;
3440 UINT32 count;
3441 HRESULT hr;
3442 GUID guid;
3444 hr = CoInitialize(NULL);
3445 ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
3447 hr = CoCreateInstance(&CLSID_VideoProcessorMFT, NULL, CLSCTX_INPROC_SERVER, &IID_IMFTransform,
3448 (void **)&transform);
3449 if (FAILED(hr))
3451 skip("Failed to create Video Processor instance, skipping tests.\n");
3452 goto failed;
3455 todo_wine
3456 check_interface(transform, &IID_IMFVideoProcessorControl, TRUE);
3457 todo_wine
3458 check_interface(transform, &IID_IMFRealTimeClientEx, TRUE);
3459 check_interface(transform, &IID_IMFMediaEventGenerator, FALSE);
3460 check_interface(transform, &IID_IMFShutdown, FALSE);
3462 /* Transform global attributes. */
3463 hr = IMFTransform_GetAttributes(transform, &attributes);
3464 ok(hr == S_OK, "Failed to get attributes, hr %#lx.\n", hr);
3466 hr = IMFAttributes_GetCount(attributes, &count);
3467 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3468 todo_wine
3469 ok(!!count, "Unexpected attribute count %u.\n", count);
3471 value = 0;
3472 hr = IMFAttributes_GetUINT32(attributes, &MF_SA_D3D11_AWARE, &value);
3473 todo_wine {
3474 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3475 ok(value == 1, "Unexpected attribute value %u.\n", value);
3477 hr = IMFTransform_GetAttributes(transform, &attributes2);
3478 ok(hr == S_OK, "Failed to get attributes, hr %#lx.\n", hr);
3479 ok(attributes == attributes2, "Unexpected instance.\n");
3480 IMFAttributes_Release(attributes);
3481 IMFAttributes_Release(attributes2);
3483 hr = IMFTransform_GetStreamLimits(transform, &input_min, &input_max, &output_min, &output_max);
3484 ok(hr == S_OK, "Failed to get stream limits, hr %#lx.\n", hr);
3485 ok(input_min == input_max && input_min == 1 && output_min == output_max && output_min == 1,
3486 "Unexpected stream limits.\n");
3488 hr = IMFTransform_GetStreamCount(transform, &input_count, &output_count);
3489 ok(hr == S_OK, "Failed to get stream count, hr %#lx.\n", hr);
3490 ok(input_count == 1 && output_count == 1, "Unexpected stream count %lu, %lu.\n", input_count, output_count);
3492 hr = IMFTransform_GetStreamIDs(transform, 1, &input_id, 1, &output_id);
3493 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
3495 input_id = 100;
3496 hr = IMFTransform_AddInputStreams(transform, 1, &input_id);
3497 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
3499 hr = IMFTransform_DeleteInputStream(transform, 0);
3500 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
3502 hr = IMFTransform_GetInputStatus(transform, 0, &flags);
3503 todo_wine
3504 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
3506 hr = IMFTransform_GetInputStreamAttributes(transform, 0, &attributes);
3507 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
3509 hr = IMFTransform_GetOutputStatus(transform, &flags);
3510 todo_wine
3511 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
3513 hr = IMFTransform_GetOutputStreamAttributes(transform, 0, &attributes);
3514 ok(hr == S_OK, "Failed to get output attributes, hr %#lx.\n", hr);
3515 hr = IMFTransform_GetOutputStreamAttributes(transform, 0, &attributes2);
3516 ok(hr == S_OK, "Failed to get output attributes, hr %#lx.\n", hr);
3517 ok(attributes == attributes2, "Unexpected instance.\n");
3518 IMFAttributes_Release(attributes);
3519 IMFAttributes_Release(attributes2);
3521 hr = IMFTransform_GetOutputAvailableType(transform, 0, 0, &media_type);
3522 todo_wine
3523 ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#lx.\n", hr);
3525 hr = IMFTransform_GetInputCurrentType(transform, 0, &media_type);
3526 todo_wine
3527 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
3529 hr = IMFTransform_GetInputCurrentType(transform, 1, &media_type);
3530 todo_wine
3531 ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#lx.\n", hr);
3533 hr = IMFTransform_GetOutputCurrentType(transform, 0, &media_type);
3534 todo_wine
3535 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
3537 hr = IMFTransform_GetOutputCurrentType(transform, 1, &media_type);
3538 todo_wine
3539 ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#lx.\n", hr);
3541 hr = IMFTransform_GetInputStreamInfo(transform, 1, &input_info);
3542 todo_wine
3543 ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#lx.\n", hr);
3545 memset(&input_info, 0xcc, sizeof(input_info));
3546 hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info);
3547 todo_wine {
3548 ok(hr == S_OK, "Failed to get stream info, hr %#lx.\n", hr);
3549 ok(input_info.dwFlags == 0, "Unexpected flag %#lx.\n", input_info.dwFlags);
3550 ok(input_info.cbSize == 0, "Unexpected size %lu.\n", input_info.cbSize);
3551 ok(input_info.cbMaxLookahead == 0, "Unexpected lookahead length %lu.\n", input_info.cbMaxLookahead);
3552 ok(input_info.cbAlignment == 0, "Unexpected alignment %lu.\n", input_info.cbAlignment);
3554 hr = MFCreateMediaEvent(MEUnknown, &GUID_NULL, S_OK, NULL, &event);
3555 ok(hr == S_OK, "Failed to create event object, hr %#lx.\n", hr);
3556 hr = IMFTransform_ProcessEvent(transform, 0, event);
3557 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
3558 hr = IMFTransform_ProcessEvent(transform, 1, event);
3559 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
3560 IMFMediaEvent_Release(event);
3562 /* Configure stream types. */
3563 for (i = 0;;++i)
3565 if (FAILED(hr = IMFTransform_GetInputAvailableType(transform, 0, i, &media_type)))
3567 todo_wine
3568 ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#lx.\n", hr);
3569 break;
3572 hr = IMFTransform_GetInputAvailableType(transform, 0, i, &media_type2);
3573 ok(hr == S_OK, "Failed to get available type, hr %#lx.\n", hr);
3574 ok(media_type != media_type2, "Unexpected instance.\n");
3575 IMFMediaType_Release(media_type2);
3577 hr = IMFMediaType_GetMajorType(media_type, &guid);
3578 ok(hr == S_OK, "Failed to get major type, hr %#lx.\n", hr);
3579 ok(IsEqualGUID(&guid, &MFMediaType_Video), "Unexpected major type.\n");
3581 hr = IMFMediaType_GetCount(media_type, &count);
3582 ok(hr == S_OK, "Failed to get attributes count, hr %#lx.\n", hr);
3583 ok(count == 2, "Unexpected count %u.\n", count);
3585 hr = IMFMediaType_GetGUID(media_type, &MF_MT_SUBTYPE, &guid);
3586 ok(hr == S_OK, "Failed to get subtype, hr %#lx.\n", hr);
3587 ok(is_supported_video_type(&guid), "Unexpected media type %s.\n", wine_dbgstr_guid(&guid));
3589 hr = IMFTransform_SetInputType(transform, 0, media_type, MFT_SET_TYPE_TEST_ONLY);
3590 ok(FAILED(hr), "Unexpected hr %#lx.\n", hr);
3592 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
3593 ok(FAILED(hr), "Unexpected hr %#lx.\n", hr);
3595 hr = IMFTransform_GetOutputCurrentType(transform, 0, &media_type2);
3596 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
3598 /* FIXME: figure out if those require additional attributes or simply advertised but not supported */
3599 if (IsEqualGUID(&guid, &MFVideoFormat_L8) || IsEqualGUID(&guid, &MFVideoFormat_L16)
3600 || IsEqualGUID(&guid, &MFVideoFormat_D16) || IsEqualGUID(&guid, &MFVideoFormat_420O)
3601 || IsEqualGUID(&guid, &MFVideoFormat_A16B16G16R16F))
3603 IMFMediaType_Release(media_type);
3604 continue;
3607 hr = IMFMediaType_SetUINT64(media_type, &MF_MT_FRAME_SIZE, ((UINT64)16 << 32) | 16);
3608 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3610 hr = IMFTransform_SetInputType(transform, 0, media_type, MFT_SET_TYPE_TEST_ONLY);
3611 ok(hr == S_OK, "Failed to test input type %s, hr %#lx.\n", wine_dbgstr_guid(&guid), hr);
3613 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
3614 ok(hr == S_OK, "Failed to test input type, hr %#lx.\n", hr);
3616 hr = IMFTransform_GetInputCurrentType(transform, 0, &media_type2);
3617 ok(hr == S_OK, "Failed to get current type, hr %#lx.\n", hr);
3618 ok(media_type != media_type2, "Unexpected instance.\n");
3619 IMFMediaType_Release(media_type2);
3621 hr = IMFTransform_GetInputStatus(transform, 0, &flags);
3622 ok(hr == S_OK, "Failed to get input status, hr %#lx.\n", hr);
3623 ok(flags == MFT_INPUT_STATUS_ACCEPT_DATA, "Unexpected input status %#lx.\n", flags);
3625 hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info);
3626 ok(hr == S_OK, "Failed to get stream info, hr %#lx.\n", hr);
3627 ok(input_info.dwFlags == 0, "Unexpected flags %#lx.\n", input_info.dwFlags);
3628 ok(input_info.cbMaxLookahead == 0, "Unexpected lookahead length %lu.\n", input_info.cbMaxLookahead);
3629 ok(input_info.cbAlignment == 0, "Unexpected alignment %lu.\n", input_info.cbAlignment);
3631 IMFMediaType_Release(media_type);
3634 /* IYUV -> RGB32 */
3635 hr = MFCreateMediaType(&media_type);
3636 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
3638 hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
3639 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3641 hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFVideoFormat_IYUV);
3642 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3644 hr = IMFMediaType_SetUINT64(media_type, &MF_MT_FRAME_SIZE, ((UINT64)16 << 32) | 16);
3645 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3647 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
3648 todo_wine
3649 ok(hr == S_OK, "Failed to set input type, hr %#lx.\n", hr);
3651 hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFVideoFormat_RGB32);
3652 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3654 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
3655 todo_wine
3656 ok(hr == S_OK, "Failed to set output type, hr %#lx.\n", hr);
3658 memset(&output_info, 0, sizeof(output_info));
3659 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
3660 todo_wine
3661 ok(hr == S_OK, "Failed to get stream info, hr %#lx.\n", hr);
3662 ok(output_info.dwFlags == 0, "Unexpected flags %#lx.\n", output_info.dwFlags);
3663 todo_wine
3664 ok(output_info.cbSize > 0, "Unexpected size %lu.\n", output_info.cbSize);
3665 ok(output_info.cbAlignment == 0, "Unexpected alignment %lu.\n", output_info.cbAlignment);
3667 hr = MFCreateSample(&sample);
3668 ok(hr == S_OK, "Failed to create a sample, hr %#lx.\n", hr);
3670 hr = MFCreateSample(&sample2);
3671 ok(hr == S_OK, "Failed to create a sample, hr %#lx.\n", hr);
3673 memset(&output_buffer, 0, sizeof(output_buffer));
3674 output_buffer.pSample = sample;
3675 flags = 0;
3676 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output_buffer, &flags);
3677 todo_wine
3678 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "Unexpected hr %#lx.\n", hr);
3679 ok(output_buffer.dwStatus == 0, "Unexpected buffer status, %#lx.\n", output_buffer.dwStatus);
3680 ok(flags == 0, "Unexpected status %#lx.\n", flags);
3682 hr = IMFTransform_ProcessInput(transform, 0, sample2, 0);
3683 todo_wine
3684 ok(hr == S_OK, "Failed to push a sample, hr %#lx.\n", hr);
3686 hr = IMFTransform_ProcessInput(transform, 0, sample2, 0);
3687 todo_wine
3688 ok(hr == MF_E_NOTACCEPTING, "Unexpected hr %#lx.\n", hr);
3690 memset(&output_buffer, 0, sizeof(output_buffer));
3691 output_buffer.pSample = sample;
3692 flags = 0;
3693 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output_buffer, &flags);
3694 todo_wine
3695 ok(hr == MF_E_NO_SAMPLE_TIMESTAMP, "Unexpected hr %#lx.\n", hr);
3696 ok(output_buffer.dwStatus == 0, "Unexpected buffer status, %#lx.\n", output_buffer.dwStatus);
3697 ok(flags == 0, "Unexpected status %#lx.\n", flags);
3699 hr = IMFSample_SetSampleTime(sample2, 0);
3700 ok(hr == S_OK, "Failed to set sample time, hr %#lx.\n", hr);
3701 memset(&output_buffer, 0, sizeof(output_buffer));
3702 output_buffer.pSample = sample;
3703 flags = 0;
3704 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output_buffer, &flags);
3705 todo_wine
3706 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
3707 ok(output_buffer.dwStatus == 0, "Unexpected buffer status, %#lx.\n", output_buffer.dwStatus);
3708 ok(flags == 0, "Unexpected status %#lx.\n", flags);
3710 hr = MFCreateMemoryBuffer(1024 * 1024, &buffer);
3711 ok(hr == S_OK, "Failed to create a buffer, hr %#lx.\n", hr);
3713 hr = IMFSample_AddBuffer(sample2, buffer);
3714 ok(hr == S_OK, "Failed to add a buffer, hr %#lx.\n", hr);
3716 hr = IMFSample_AddBuffer(sample, buffer);
3717 ok(hr == S_OK, "Failed to add a buffer, hr %#lx.\n", hr);
3719 memset(&output_buffer, 0, sizeof(output_buffer));
3720 output_buffer.pSample = sample;
3721 flags = 0;
3722 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output_buffer, &flags);
3723 todo_wine
3724 ok(hr == S_OK || broken(FAILED(hr)) /* Win8 */, "Failed to get output buffer, hr %#lx.\n", hr);
3725 ok(output_buffer.dwStatus == 0, "Unexpected buffer status, %#lx.\n", output_buffer.dwStatus);
3726 ok(flags == 0, "Unexpected status %#lx.\n", flags);
3728 if (SUCCEEDED(hr))
3730 memset(&output_buffer, 0, sizeof(output_buffer));
3731 output_buffer.pSample = sample;
3732 flags = 0;
3733 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output_buffer, &flags);
3734 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "Unexpected hr %#lx.\n", hr);
3735 ok(output_buffer.dwStatus == 0, "Unexpected buffer status, %#lx.\n", output_buffer.dwStatus);
3736 ok(flags == 0, "Unexpected status %#lx.\n", flags);
3739 IMFSample_Release(sample2);
3740 IMFSample_Release(sample);
3741 IMFMediaBuffer_Release(buffer);
3743 IMFMediaType_Release(media_type);
3745 IMFTransform_Release(transform);
3747 failed:
3748 CoUninitialize();
3751 static void test_quality_manager(void)
3753 IMFPresentationClock *clock;
3754 IMFQualityManager *manager;
3755 IMFTopology *topology;
3756 HRESULT hr;
3758 hr = MFStartup(MF_VERSION, MFSTARTUP_FULL);
3759 ok(hr == S_OK, "Startup failure, hr %#lx.\n", hr);
3761 hr = MFCreatePresentationClock(&clock);
3762 ok(hr == S_OK, "Failed to create presentation clock, hr %#lx.\n", hr);
3764 hr = MFCreateStandardQualityManager(&manager);
3765 ok(hr == S_OK, "Failed to create quality manager, hr %#lx.\n", hr);
3767 check_interface(manager, &IID_IMFQualityManager, TRUE);
3768 check_interface(manager, &IID_IMFClockStateSink, TRUE);
3770 hr = IMFQualityManager_NotifyPresentationClock(manager, NULL);
3771 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
3773 hr = IMFQualityManager_NotifyTopology(manager, NULL);
3774 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3776 /* Set clock, then shutdown. */
3777 EXPECT_REF(clock, 1);
3778 EXPECT_REF(manager, 1);
3779 hr = IMFQualityManager_NotifyPresentationClock(manager, clock);
3780 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3781 EXPECT_REF(clock, 2);
3782 EXPECT_REF(manager, 2);
3784 hr = IMFQualityManager_Shutdown(manager);
3785 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3786 EXPECT_REF(clock, 1);
3788 hr = IMFQualityManager_NotifyPresentationClock(manager, clock);
3789 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
3791 hr = IMFQualityManager_NotifyTopology(manager, NULL);
3792 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
3794 hr = IMFQualityManager_NotifyPresentationClock(manager, NULL);
3795 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
3797 hr = IMFQualityManager_Shutdown(manager);
3798 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3800 IMFQualityManager_Release(manager);
3802 /* Set clock, then release without shutting down. */
3803 hr = MFCreateStandardQualityManager(&manager);
3804 ok(hr == S_OK, "Failed to create quality manager, hr %#lx.\n", hr);
3806 EXPECT_REF(clock, 1);
3807 hr = IMFQualityManager_NotifyPresentationClock(manager, clock);
3808 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3809 EXPECT_REF(clock, 2);
3811 IMFQualityManager_Release(manager);
3812 EXPECT_REF(clock, 2);
3814 IMFPresentationClock_Release(clock);
3816 /* Set topology. */
3817 hr = MFCreateStandardQualityManager(&manager);
3818 ok(hr == S_OK, "Failed to create quality manager, hr %#lx.\n", hr);
3820 hr = MFCreateTopology(&topology);
3821 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3823 EXPECT_REF(topology, 1);
3824 hr = IMFQualityManager_NotifyTopology(manager, topology);
3825 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3826 EXPECT_REF(topology, 2);
3828 hr = IMFQualityManager_NotifyTopology(manager, NULL);
3829 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3830 EXPECT_REF(topology, 1);
3832 hr = IMFQualityManager_NotifyTopology(manager, topology);
3833 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3835 EXPECT_REF(topology, 2);
3836 hr = IMFQualityManager_Shutdown(manager);
3837 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3838 EXPECT_REF(topology, 1);
3840 hr = IMFQualityManager_NotifyTopology(manager, topology);
3841 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
3843 IMFQualityManager_Release(manager);
3845 hr = MFCreateStandardQualityManager(&manager);
3846 ok(hr == S_OK, "Failed to create quality manager, hr %#lx.\n", hr);
3848 EXPECT_REF(topology, 1);
3849 hr = IMFQualityManager_NotifyTopology(manager, topology);
3850 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3851 EXPECT_REF(topology, 2);
3853 IMFQualityManager_Release(manager);
3854 EXPECT_REF(topology, 1);
3856 IMFTopology_Release(topology);
3858 hr = MFShutdown();
3859 ok(hr == S_OK, "Shutdown failure, hr %#lx.\n", hr);
3862 static void check_sar_rate_support(IMFMediaSink *sink)
3864 IMFRateSupport *rate_support;
3865 IMFMediaTypeHandler *handler;
3866 IMFStreamSink *stream_sink;
3867 IMFMediaType *media_type;
3868 HRESULT hr;
3869 float rate;
3871 hr = IMFMediaSink_QueryInterface(sink, &IID_IMFRateSupport, (void **)&rate_support);
3872 todo_wine
3873 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3874 if (FAILED(hr)) return;
3876 hr = IMFMediaSink_GetStreamSinkByIndex(sink, 0, &stream_sink);
3877 if (hr == MF_E_SHUTDOWN)
3879 hr = IMFRateSupport_GetSlowestRate(rate_support, MFRATE_FORWARD, FALSE, NULL);
3880 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
3882 hr = IMFRateSupport_GetSlowestRate(rate_support, MFRATE_FORWARD, FALSE, &rate);
3883 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
3885 hr = IMFRateSupport_GetFastestRate(rate_support, MFRATE_FORWARD, FALSE, &rate);
3886 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
3888 IMFRateSupport_Release(rate_support);
3889 return;
3891 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3893 hr = IMFStreamSink_GetMediaTypeHandler(stream_sink, &handler);
3894 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3896 IMFStreamSink_Release(stream_sink);
3898 hr = IMFRateSupport_GetSlowestRate(rate_support, MFRATE_FORWARD, FALSE, NULL);
3899 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
3901 hr = IMFRateSupport_GetFastestRate(rate_support, MFRATE_FORWARD, FALSE, NULL);
3902 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
3904 hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, &media_type);
3905 if (SUCCEEDED(hr))
3907 hr = IMFRateSupport_GetSlowestRate(rate_support, MFRATE_FORWARD, FALSE, &rate);
3908 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3910 hr = IMFRateSupport_GetSlowestRate(rate_support, MFRATE_FORWARD, TRUE, &rate);
3911 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3913 hr = IMFRateSupport_GetSlowestRate(rate_support, MFRATE_REVERSE, FALSE, &rate);
3914 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3916 hr = IMFRateSupport_GetSlowestRate(rate_support, MFRATE_REVERSE, TRUE, &rate);
3917 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3919 hr = IMFRateSupport_GetFastestRate(rate_support, MFRATE_FORWARD, FALSE, &rate);
3920 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3922 hr = IMFRateSupport_GetFastestRate(rate_support, MFRATE_FORWARD, TRUE, &rate);
3923 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3925 hr = IMFRateSupport_GetFastestRate(rate_support, MFRATE_REVERSE, FALSE, &rate);
3926 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3928 hr = IMFRateSupport_GetFastestRate(rate_support, MFRATE_REVERSE, TRUE, &rate);
3929 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3931 IMFMediaType_Release(media_type);
3933 else
3935 hr = IMFRateSupport_GetSlowestRate(rate_support, MFRATE_FORWARD, FALSE, &rate);
3936 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#lx.\n", hr);
3938 hr = IMFRateSupport_GetSlowestRate(rate_support, MFRATE_FORWARD, TRUE, &rate);
3939 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#lx.\n", hr);
3941 hr = IMFRateSupport_GetSlowestRate(rate_support, MFRATE_REVERSE, FALSE, &rate);
3942 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#lx.\n", hr);
3944 hr = IMFRateSupport_GetSlowestRate(rate_support, MFRATE_REVERSE, TRUE, &rate);
3945 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#lx.\n", hr);
3947 hr = IMFRateSupport_GetFastestRate(rate_support, MFRATE_FORWARD, FALSE, &rate);
3948 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#lx.\n", hr);
3950 hr = IMFRateSupport_GetFastestRate(rate_support, MFRATE_FORWARD, TRUE, &rate);
3951 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#lx.\n", hr);
3953 hr = IMFRateSupport_GetFastestRate(rate_support, MFRATE_REVERSE, FALSE, &rate);
3954 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#lx.\n", hr);
3956 hr = IMFRateSupport_GetFastestRate(rate_support, MFRATE_REVERSE, TRUE, &rate);
3957 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#lx.\n", hr);
3960 IMFMediaTypeHandler_Release(handler);
3961 IMFRateSupport_Release(rate_support);
3964 static void test_sar(void)
3966 IMFPresentationClock *present_clock, *present_clock2;
3967 IMFMediaType *mediatype, *mediatype2, *mediatype3;
3968 IMFClockStateSink *state_sink, *state_sink2;
3969 IMFMediaTypeHandler *handler, *handler2;
3970 IMFPresentationTimeSource *time_source;
3971 IMFSimpleAudioVolume *simple_volume;
3972 IMFAudioStreamVolume *stream_volume;
3973 IMFMediaSink *sink, *sink2;
3974 IMFStreamSink *stream_sink;
3975 IMFAttributes *attributes;
3976 DWORD i, id, flags, count;
3977 IMFActivate *activate;
3978 UINT32 channel_count;
3979 MFCLOCK_STATE state;
3980 IMFClock *clock;
3981 IUnknown *unk;
3982 HRESULT hr;
3983 GUID guid;
3984 BOOL mute;
3985 int found;
3987 hr = CoInitialize(NULL);
3988 ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
3990 hr = MFCreateAudioRenderer(NULL, &sink);
3991 if (hr == MF_E_NO_AUDIO_PLAYBACK_DEVICE)
3993 skip("No audio playback device available.\n");
3994 CoUninitialize();
3995 return;
3997 ok(hr == S_OK, "Failed to create renderer, hr %#lx.\n", hr);
3999 hr = MFStartup(MF_VERSION, MFSTARTUP_FULL);
4000 ok(hr == S_OK, "Startup failure, hr %#lx.\n", hr);
4002 hr = MFCreatePresentationClock(&present_clock);
4003 ok(hr == S_OK, "Failed to create presentation clock, hr %#lx.\n", hr);
4005 hr = IMFMediaSink_QueryInterface(sink, &IID_IMFPresentationTimeSource, (void **)&time_source);
4006 todo_wine
4007 ok(hr == S_OK, "Failed to get time source interface, hr %#lx.\n", hr);
4009 if (SUCCEEDED(hr))
4011 hr = IMFPresentationTimeSource_QueryInterface(time_source, &IID_IMFClockStateSink, (void **)&state_sink2);
4012 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4013 hr = IMFPresentationTimeSource_QueryInterface(time_source, &IID_IMFClockStateSink, (void **)&state_sink);
4014 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4015 ok(state_sink == state_sink2, "Unexpected clock sink.\n");
4016 IMFClockStateSink_Release(state_sink2);
4017 IMFClockStateSink_Release(state_sink);
4019 hr = IMFPresentationTimeSource_GetUnderlyingClock(time_source, &clock);
4020 ok(hr == MF_E_NO_CLOCK, "Unexpected hr %#lx.\n", hr);
4022 hr = IMFPresentationTimeSource_GetClockCharacteristics(time_source, &flags);
4023 ok(hr == S_OK, "Failed to get flags, hr %#lx.\n", hr);
4024 ok(flags == MFCLOCK_CHARACTERISTICS_FLAG_FREQUENCY_10MHZ, "Unexpected flags %#lx.\n", flags);
4026 hr = IMFPresentationTimeSource_GetState(time_source, 0, &state);
4027 ok(hr == S_OK, "Failed to get clock state, hr %#lx.\n", hr);
4028 ok(state == MFCLOCK_STATE_INVALID, "Unexpected state %d.\n", state);
4030 hr = IMFPresentationTimeSource_QueryInterface(time_source, &IID_IMFClockStateSink, (void **)&state_sink);
4031 ok(hr == S_OK, "Failed to get state sink, hr %#lx.\n", hr);
4033 hr = IMFClockStateSink_OnClockStart(state_sink, 0, 0);
4034 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#lx.\n", hr);
4036 IMFClockStateSink_Release(state_sink);
4038 IMFPresentationTimeSource_Release(time_source);
4040 hr = IMFMediaSink_AddStreamSink(sink, 123, NULL, &stream_sink);
4041 ok(hr == MF_E_STREAMSINKS_FIXED, "Unexpected hr %#lx.\n", hr);
4043 hr = IMFMediaSink_RemoveStreamSink(sink, 0);
4044 ok(hr == MF_E_STREAMSINKS_FIXED, "Unexpected hr %#lx.\n", hr);
4046 hr = IMFMediaSink_GetStreamSinkCount(sink, NULL);
4047 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
4049 hr = IMFMediaSink_GetStreamSinkCount(sink, &count);
4050 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4051 ok(count == 1, "Unexpected count %lu.\n", count);
4053 hr = IMFMediaSink_GetCharacteristics(sink, &flags);
4054 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4055 ok(flags == (MEDIASINK_FIXED_STREAMS | MEDIASINK_CAN_PREROLL), "Unexpected flags %#lx.\n", flags);
4057 check_interface(sink, &IID_IMFMediaSinkPreroll, TRUE);
4058 check_interface(sink, &IID_IMFMediaEventGenerator, TRUE);
4059 check_interface(sink, &IID_IMFClockStateSink, TRUE);
4060 check_interface(sink, &IID_IMFGetService, TRUE);
4061 todo_wine check_interface(sink, &IID_IMFPresentationTimeSource, TRUE);
4062 todo_wine check_service_interface(sink, &MF_RATE_CONTROL_SERVICE, &IID_IMFRateSupport, TRUE);
4063 check_service_interface(sink, &MF_RATE_CONTROL_SERVICE, &IID_IMFRateControl, FALSE);
4064 check_service_interface(sink, &MR_POLICY_VOLUME_SERVICE, &IID_IMFSimpleAudioVolume, TRUE);
4065 check_service_interface(sink, &MR_STREAM_VOLUME_SERVICE, &IID_IMFAudioStreamVolume, TRUE);
4067 /* Clock */
4068 hr = IMFMediaSink_QueryInterface(sink, &IID_IMFClockStateSink, (void **)&state_sink);
4069 ok(hr == S_OK, "Failed to get interface, hr %#lx.\n", hr);
4071 hr = IMFClockStateSink_OnClockStart(state_sink, 0, 0);
4072 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#lx.\n", hr);
4074 hr = IMFClockStateSink_OnClockPause(state_sink, 0);
4075 ok(hr == MF_E_INVALID_STATE_TRANSITION, "Unexpected hr %#lx.\n", hr);
4077 hr = IMFClockStateSink_OnClockStop(state_sink, 0);
4078 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#lx.\n", hr);
4080 hr = IMFClockStateSink_OnClockRestart(state_sink, 0);
4081 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#lx.\n", hr);
4083 IMFClockStateSink_Release(state_sink);
4085 hr = IMFMediaSink_SetPresentationClock(sink, NULL);
4086 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4088 hr = IMFMediaSink_SetPresentationClock(sink, present_clock);
4089 todo_wine
4090 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#lx.\n", hr);
4092 hr = MFCreateSystemTimeSource(&time_source);
4093 ok(hr == S_OK, "Failed to create time source, hr %#lx.\n", hr);
4095 hr = IMFPresentationClock_SetTimeSource(present_clock, time_source);
4096 ok(hr == S_OK, "Failed to set time source, hr %#lx.\n", hr);
4097 IMFPresentationTimeSource_Release(time_source);
4099 hr = IMFMediaSink_SetPresentationClock(sink, present_clock);
4100 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4102 hr = IMFMediaSink_GetPresentationClock(sink, NULL);
4103 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
4105 hr = IMFMediaSink_GetPresentationClock(sink, &present_clock2);
4106 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4107 ok(present_clock == present_clock2, "Unexpected instance.\n");
4108 IMFPresentationClock_Release(present_clock2);
4110 /* Stream */
4111 hr = IMFMediaSink_GetStreamSinkByIndex(sink, 0, &stream_sink);
4112 ok(hr == S_OK, "Failed to get a stream, hr %#lx.\n", hr);
4114 check_interface(stream_sink, &IID_IMFMediaEventGenerator, TRUE);
4115 check_interface(stream_sink, &IID_IMFMediaTypeHandler, TRUE);
4116 todo_wine check_interface(stream_sink, &IID_IMFGetService, TRUE);
4118 hr = IMFStreamSink_GetIdentifier(stream_sink, &id);
4119 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4120 ok(!id, "Unexpected id.\n");
4122 hr = IMFStreamSink_GetMediaSink(stream_sink, &sink2);
4123 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4124 ok(sink == sink2, "Unexpected object.\n");
4125 IMFMediaSink_Release(sink2);
4127 hr = IMFStreamSink_GetMediaTypeHandler(stream_sink, &handler);
4128 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4130 hr = IMFStreamSink_QueryInterface(stream_sink, &IID_IMFMediaTypeHandler, (void **)&handler2);
4131 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4132 ok(handler2 == handler, "Unexpected instance.\n");
4133 IMFMediaTypeHandler_Release(handler2);
4135 hr = IMFMediaTypeHandler_GetMajorType(handler, &guid);
4136 ok(hr == S_OK, "Failed to get major type, hr %#lx.\n", hr);
4137 ok(IsEqualGUID(&guid, &MFMediaType_Audio), "Unexpected type %s.\n", wine_dbgstr_guid(&guid));
4139 count = 0;
4140 hr = IMFMediaTypeHandler_GetMediaTypeCount(handler, &count);
4141 ok(hr == S_OK, "Failed to get type count, hr %#lx.\n", hr);
4142 ok(!!count, "Unexpected type count %lu.\n", count);
4144 /* A number of same major/subtype entries are returned, with different degrees of finer format
4145 details. Some incomplete types are not accepted, check that at least one of them is considered supported. */
4147 for (i = 0, found = -1; i < count; ++i)
4149 hr = IMFMediaTypeHandler_GetMediaTypeByIndex(handler, i, &mediatype);
4150 ok(hr == S_OK, "Failed to get media type, hr %#lx.\n", hr);
4152 if (SUCCEEDED(IMFMediaTypeHandler_IsMediaTypeSupported(handler, mediatype, NULL)))
4153 found = i;
4154 IMFMediaType_Release(mediatype);
4156 if (found != -1) break;
4158 ok(found != -1, "Haven't found a supported type.\n");
4160 hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, &mediatype);
4161 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#lx.\n", hr);
4163 hr = MFCreateMediaType(&mediatype);
4164 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
4166 /* Actual return value is MF_E_ATRIBUTENOTFOUND triggered by missing MF_MT_MAJOR_TYPE */
4167 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, mediatype, NULL);
4168 ok(FAILED(hr), "Unexpected hr %#lx.\n", hr);
4170 hr = IMFMediaType_SetGUID(mediatype, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
4171 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4172 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, mediatype, NULL);
4173 ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#lx.\n", hr);
4175 hr = IMFMediaType_SetGUID(mediatype, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio);
4176 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4177 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, mediatype, NULL);
4178 ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#lx.\n", hr);
4180 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, mediatype);
4181 ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#lx.\n", hr);
4183 hr = IMFMediaTypeHandler_GetMediaTypeByIndex(handler, found, &mediatype2);
4184 ok(hr == S_OK, "Failed to get media type, hr %#lx.\n", hr);
4186 hr = IMFMediaTypeHandler_GetMediaTypeByIndex(handler, found, &mediatype3);
4187 ok(hr == S_OK, "Failed to get media type, hr %#lx.\n", hr);
4188 ok(mediatype2 == mediatype3, "Unexpected instance.\n");
4189 IMFMediaType_Release(mediatype3);
4191 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, mediatype2, NULL);
4192 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4194 IMFMediaType_Release(mediatype);
4196 check_sar_rate_support(sink);
4198 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, mediatype2);
4199 ok(hr == S_OK, "Failed to set current type, hr %#lx.\n", hr);
4201 check_sar_rate_support(sink);
4203 hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, &mediatype);
4204 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4205 ok(mediatype == mediatype2, "Unexpected instance.\n");
4206 IMFMediaType_Release(mediatype);
4208 IMFMediaType_Release(mediatype2);
4210 /* Reset back to uninitialized state. */
4211 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, NULL);
4212 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
4214 IMFMediaTypeHandler_Release(handler);
4216 /* State change with initialized stream. */
4217 hr = IMFMediaSink_QueryInterface(sink, &IID_IMFClockStateSink, (void **)&state_sink);
4218 ok(hr == S_OK, "Failed to get interface, hr %#lx.\n", hr);
4220 hr = IMFClockStateSink_OnClockStart(state_sink, 0, 0);
4221 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4223 hr = IMFClockStateSink_OnClockStart(state_sink, 0, 0);
4224 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4226 hr = IMFClockStateSink_OnClockPause(state_sink, 0);
4227 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4229 hr = IMFClockStateSink_OnClockStop(state_sink, 0);
4230 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4232 hr = IMFClockStateSink_OnClockStop(state_sink, 0);
4233 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4235 hr = IMFClockStateSink_OnClockPause(state_sink, 0);
4236 ok(hr == MF_E_INVALID_STATE_TRANSITION, "Unexpected hr %#lx.\n", hr);
4238 hr = IMFClockStateSink_OnClockRestart(state_sink, 0);
4239 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4241 hr = IMFClockStateSink_OnClockRestart(state_sink, 0);
4242 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4244 hr = IMFClockStateSink_OnClockStop(state_sink, 0);
4245 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4247 IMFClockStateSink_Release(state_sink);
4249 IMFStreamSink_Release(stream_sink);
4251 /* Volume control */
4252 hr = MFGetService((IUnknown *)sink, &MR_POLICY_VOLUME_SERVICE, &IID_IMFSimpleAudioVolume, (void **)&simple_volume);
4253 ok(hr == S_OK, "Failed to get interface, hr %#lx.\n", hr);
4255 hr = IMFSimpleAudioVolume_GetMute(simple_volume, &mute);
4256 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4258 IMFSimpleAudioVolume_Release(simple_volume);
4260 hr = MFGetService((IUnknown *)sink, &MR_STREAM_VOLUME_SERVICE, &IID_IMFAudioStreamVolume, (void **)&stream_volume);
4261 ok(hr == S_OK, "Failed to get interface, hr %#lx.\n", hr);
4263 hr = IMFAudioStreamVolume_GetChannelCount(stream_volume, &channel_count);
4264 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4266 hr = IMFAudioStreamVolume_GetChannelCount(stream_volume, NULL);
4267 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
4269 IMFAudioStreamVolume_Release(stream_volume);
4271 hr = MFGetService((IUnknown *)sink, &MR_AUDIO_POLICY_SERVICE, &IID_IMFAudioPolicy, (void **)&unk);
4272 ok(hr == S_OK, "Failed to get interface, hr %#lx.\n", hr);
4273 IUnknown_Release(unk);
4275 /* Shutdown */
4276 EXPECT_REF(present_clock, 2);
4277 hr = IMFMediaSink_Shutdown(sink);
4278 ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr);
4279 EXPECT_REF(present_clock, 1);
4281 hr = IMFMediaSink_Shutdown(sink);
4282 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
4284 hr = IMFMediaSink_AddStreamSink(sink, 123, NULL, &stream_sink);
4285 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
4287 hr = IMFMediaSink_RemoveStreamSink(sink, 0);
4288 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
4290 hr = IMFMediaSink_GetStreamSinkCount(sink, NULL);
4291 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
4293 hr = IMFMediaSink_GetStreamSinkCount(sink, &count);
4294 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
4296 hr = IMFMediaSink_GetCharacteristics(sink, &flags);
4297 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
4299 hr = IMFMediaSink_SetPresentationClock(sink, NULL);
4300 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
4302 hr = IMFMediaSink_SetPresentationClock(sink, present_clock);
4303 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
4305 hr = IMFMediaSink_GetPresentationClock(sink, NULL);
4306 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
4308 hr = IMFMediaSink_GetPresentationClock(sink, &present_clock2);
4309 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
4311 check_sar_rate_support(sink);
4313 IMFMediaSink_Release(sink);
4315 /* Activation */
4316 hr = MFCreateAudioRendererActivate(&activate);
4317 ok(hr == S_OK, "Failed to create activation object, hr %#lx.\n", hr);
4319 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink);
4320 ok(hr == S_OK, "Failed to activate, hr %#lx.\n", hr);
4322 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink2);
4323 ok(hr == S_OK, "Failed to activate, hr %#lx.\n", hr);
4324 ok(sink == sink2, "Unexpected instance.\n");
4325 IMFMediaSink_Release(sink2);
4327 hr = IMFMediaSink_GetCharacteristics(sink, &flags);
4328 ok(hr == S_OK, "Failed to get sink flags, hr %#lx.\n", hr);
4330 hr = IMFActivate_ShutdownObject(activate);
4331 ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr);
4333 hr = IMFMediaSink_GetCharacteristics(sink, &flags);
4334 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
4336 IMFMediaSink_Release(sink);
4338 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink);
4339 ok(hr == S_OK, "Failed to activate, hr %#lx.\n", hr);
4341 hr = IMFMediaSink_GetCharacteristics(sink, &flags);
4342 todo_wine
4343 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
4345 IMFMediaSink_Release(sink);
4347 hr = IMFActivate_DetachObject(activate);
4348 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
4350 IMFActivate_Release(activate);
4352 IMFPresentationClock_Release(present_clock);
4354 hr = MFShutdown();
4355 ok(hr == S_OK, "Shutdown failure, hr %#lx.\n", hr);
4357 /* SAR attributes */
4358 hr = MFCreateAttributes(&attributes, 0);
4359 ok(hr == S_OK, "Failed to create attributes, hr %#lx.\n", hr);
4361 /* Specify role. */
4362 hr = IMFAttributes_SetUINT32(attributes, &MF_AUDIO_RENDERER_ATTRIBUTE_ENDPOINT_ROLE, eMultimedia);
4363 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
4365 hr = MFCreateAudioRenderer(attributes, &sink);
4366 ok(hr == S_OK, "Failed to create a sink, hr %#lx.\n", hr);
4367 IMFMediaSink_Release(sink);
4369 /* Invalid endpoint. */
4370 hr = IMFAttributes_SetString(attributes, &MF_AUDIO_RENDERER_ATTRIBUTE_ENDPOINT_ID, L"endpoint");
4371 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
4373 hr = MFCreateAudioRenderer(attributes, &sink);
4374 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
4376 hr = IMFAttributes_DeleteItem(attributes, &MF_AUDIO_RENDERER_ATTRIBUTE_ENDPOINT_ROLE);
4377 ok(hr == S_OK, "Failed to remove attribute, hr %#lx.\n", hr);
4379 hr = MFCreateAudioRenderer(attributes, &sink);
4380 ok(hr == MF_E_NO_AUDIO_PLAYBACK_DEVICE, "Failed to create a sink, hr %#lx.\n", hr);
4382 IMFAttributes_Release(attributes);
4384 CoUninitialize();
4387 static void test_evr(void)
4389 static const float supported_rates[] =
4391 0.0f, 1.0f, -20.0f, 20.0f, 1000.0f, -1000.0f,
4393 IMFVideoSampleAllocatorCallback *allocator_callback;
4394 IMFStreamSink *stream_sink, *stream_sink2;
4395 IMFVideoDisplayControl *display_control;
4396 IMFMediaType *media_type, *media_type2;
4397 IMFPresentationTimeSource *time_source;
4398 IMFVideoSampleAllocator *allocator;
4399 IMFMediaTypeHandler *type_handler;
4400 IMFVideoRenderer *video_renderer;
4401 IMFPresentationClock *clock;
4402 IMFMediaSink *sink, *sink2;
4403 IMFAttributes *attributes;
4404 UINT32 attr_count, value;
4405 IMFActivate *activate;
4406 HWND window, window2;
4407 IMFRateSupport *rs;
4408 DWORD flags, count;
4409 LONG sample_count;
4410 IMFSample *sample;
4411 unsigned int i;
4412 UINT64 window3;
4413 IUnknown *unk;
4414 float rate;
4415 HRESULT hr;
4416 GUID guid;
4418 hr = MFStartup(MF_VERSION, MFSTARTUP_FULL);
4419 ok(hr == S_OK, "Startup failure, hr %#lx.\n", hr);
4421 hr = MFCreateVideoRenderer(&IID_IMFVideoRenderer, (void **)&video_renderer);
4422 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4424 hr = IMFVideoRenderer_InitializeRenderer(video_renderer, NULL, NULL);
4425 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4427 IMFVideoRenderer_Release(video_renderer);
4429 hr = MFCreateVideoRendererActivate(NULL, NULL);
4430 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
4432 /* Window */
4433 window = create_window();
4434 hr = MFCreateVideoRendererActivate(window, &activate);
4435 ok(hr == S_OK, "Failed to create activate object, hr %#lx.\n", hr);
4437 hr = IMFActivate_GetUINT64(activate, &MF_ACTIVATE_VIDEO_WINDOW, &window3);
4438 ok(hr == S_OK, "Failed to get attribute, hr %#lx.\n", hr);
4439 ok(UlongToHandle(window3) == window, "Unexpected value.\n");
4441 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink);
4442 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4444 check_interface(sink, &IID_IMFMediaSinkPreroll, TRUE);
4445 check_interface(sink, &IID_IMFVideoRenderer, TRUE);
4446 check_interface(sink, &IID_IMFMediaEventGenerator, TRUE);
4447 check_interface(sink, &IID_IMFClockStateSink, TRUE);
4448 check_interface(sink, &IID_IMFGetService, TRUE);
4449 check_interface(sink, &IID_IMFQualityAdvise, TRUE);
4450 check_interface(sink, &IID_IMFRateSupport, TRUE);
4451 check_interface(sink, &IID_IMFRateControl, FALSE);
4452 check_service_interface(sink, &MR_VIDEO_MIXER_SERVICE, &IID_IMFVideoProcessor, TRUE);
4453 check_service_interface(sink, &MR_VIDEO_MIXER_SERVICE, &IID_IMFVideoMixerBitmap, TRUE);
4454 check_service_interface(sink, &MR_VIDEO_MIXER_SERVICE, &IID_IMFVideoMixerControl, TRUE);
4455 check_service_interface(sink, &MR_VIDEO_MIXER_SERVICE, &IID_IMFVideoMixerControl2, TRUE);
4456 check_service_interface(sink, &MR_VIDEO_RENDER_SERVICE, &IID_IMFVideoDisplayControl, TRUE);
4457 check_service_interface(sink, &MR_VIDEO_RENDER_SERVICE, &IID_IMFVideoPositionMapper, TRUE);
4458 check_service_interface(sink, &MR_VIDEO_ACCELERATION_SERVICE, &IID_IMFVideoSampleAllocator, FALSE);
4459 check_service_interface(sink, &MR_VIDEO_ACCELERATION_SERVICE, &IID_IDirect3DDeviceManager9, TRUE);
4460 check_service_interface(sink, &MF_RATE_CONTROL_SERVICE, &IID_IMFRateSupport, TRUE);
4462 hr = MFGetService((IUnknown *)sink, &MR_VIDEO_RENDER_SERVICE, &IID_IMFVideoDisplayControl,
4463 (void **)&display_control);
4464 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4466 window2 = NULL;
4467 hr = IMFVideoDisplayControl_GetVideoWindow(display_control, &window2);
4468 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4469 ok(window2 == window, "Unexpected window %p.\n", window2);
4471 IMFVideoDisplayControl_Release(display_control);
4472 IMFMediaSink_Release(sink);
4473 IMFActivate_Release(activate);
4474 DestroyWindow(window);
4476 hr = MFCreateVideoRendererActivate(NULL, &activate);
4477 ok(hr == S_OK, "Failed to create activate object, hr %#lx.\n", hr);
4479 hr = IMFActivate_GetCount(activate, &attr_count);
4480 ok(hr == S_OK, "Failed to get attribute count, hr %#lx.\n", hr);
4481 ok(attr_count == 1, "Unexpected count %u.\n", attr_count);
4483 hr = IMFActivate_GetUINT64(activate, &MF_ACTIVATE_VIDEO_WINDOW, &window3);
4484 ok(hr == S_OK, "Failed to get attribute, hr %#lx.\n", hr);
4485 ok(!window3, "Unexpected value.\n");
4487 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink);
4488 ok(hr == S_OK, "Failed to activate, hr %#lx.\n", hr);
4490 hr = IMFMediaSink_QueryInterface(sink, &IID_IMFAttributes, (void **)&attributes);
4491 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4492 hr = IMFAttributes_QueryInterface(attributes, &IID_IMFMediaSink, (void **)&unk);
4493 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4494 IUnknown_Release(unk);
4495 hr = IMFAttributes_GetCount(attributes, &attr_count);
4496 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4497 ok(!!attr_count, "Unexpected count %u.\n", attr_count);
4498 /* Rendering preferences are not immediately propagated to the presenter. */
4499 hr = IMFAttributes_SetUINT32(attributes, &EVRConfig_ForceBob, 1);
4500 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4501 hr = MFGetService((IUnknown *)sink, &MR_VIDEO_RENDER_SERVICE, &IID_IMFVideoDisplayControl, (void **)&display_control);
4502 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4503 hr = IMFVideoDisplayControl_GetRenderingPrefs(display_control, &flags);
4504 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4505 ok(!flags, "Unexpected flags %#lx.\n", flags);
4506 IMFVideoDisplayControl_Release(display_control);
4507 IMFAttributes_Release(attributes);
4509 /* Primary stream type handler. */
4510 hr = IMFMediaSink_GetStreamSinkById(sink, 0, &stream_sink);
4511 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4513 hr = IMFStreamSink_QueryInterface(stream_sink, &IID_IMFAttributes, (void **)&attributes);
4514 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4515 hr = IMFAttributes_GetCount(attributes, &attr_count);
4516 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4517 ok(attr_count == 2, "Unexpected count %u.\n", attr_count);
4518 value = 0;
4519 hr = IMFAttributes_GetUINT32(attributes, &MF_SA_REQUIRED_SAMPLE_COUNT, &value);
4520 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4521 ok(value == 1, "Unexpected attribute value %u.\n", value);
4522 value = 0;
4523 hr = IMFAttributes_GetUINT32(attributes, &MF_SA_D3D_AWARE, &value);
4524 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4525 ok(value == 1, "Unexpected attribute value %u.\n", value);
4527 hr = IMFAttributes_QueryInterface(attributes, &IID_IMFStreamSink, (void **)&unk);
4528 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4529 IUnknown_Release(unk);
4530 IMFAttributes_Release(attributes);
4532 hr = IMFStreamSink_GetMediaTypeHandler(stream_sink, &type_handler);
4533 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4535 hr = IMFMediaTypeHandler_GetMajorType(type_handler, NULL);
4536 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
4538 hr = IMFMediaTypeHandler_GetMajorType(type_handler, &guid);
4539 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4540 ok(IsEqualGUID(&guid, &MFMediaType_Video), "Unexpected type %s.\n", wine_dbgstr_guid(&guid));
4542 /* Supported types are not advertised. */
4543 hr = IMFMediaTypeHandler_GetMediaTypeCount(type_handler, NULL);
4544 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
4546 count = 1;
4547 hr = IMFMediaTypeHandler_GetMediaTypeCount(type_handler, &count);
4548 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4549 ok(!count, "Unexpected count %lu.\n", count);
4551 hr = IMFMediaTypeHandler_GetMediaTypeByIndex(type_handler, 0, NULL);
4552 ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#lx.\n", hr);
4554 hr = IMFMediaTypeHandler_GetMediaTypeByIndex(type_handler, 0, &media_type);
4555 ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#lx.\n", hr);
4557 hr = IMFMediaTypeHandler_GetCurrentMediaType(type_handler, NULL);
4558 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
4560 hr = IMFMediaTypeHandler_GetCurrentMediaType(type_handler, &media_type);
4561 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
4563 hr = IMFMediaTypeHandler_SetCurrentMediaType(type_handler, NULL);
4564 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
4566 hr = MFCreateMediaType(&media_type);
4567 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4569 hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
4570 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4572 hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFVideoFormat_RGB32);
4573 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4575 hr = IMFMediaType_SetUINT64(media_type, &MF_MT_FRAME_SIZE, (UINT64)640 << 32 | 480);
4576 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4578 hr = IMFMediaTypeHandler_IsMediaTypeSupported(type_handler, NULL, NULL);
4579 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
4581 hr = IMFMediaTypeHandler_IsMediaTypeSupported(type_handler, media_type, &media_type2);
4582 ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#lx.\n", hr);
4584 hr = IMFMediaType_SetUINT32(media_type, &MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE);
4585 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4587 media_type2 = (void *)0x1;
4588 hr = IMFMediaTypeHandler_IsMediaTypeSupported(type_handler, media_type, &media_type2);
4589 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4590 ok(!media_type2, "Unexpected media type %p.\n", media_type2);
4592 hr = IMFMediaTypeHandler_SetCurrentMediaType(type_handler, media_type);
4593 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4595 hr = IMFMediaTypeHandler_GetCurrentMediaType(type_handler, &media_type2);
4596 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4597 hr = IMFMediaType_QueryInterface(media_type2, &IID_IMFVideoMediaType, (void **)&unk);
4598 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4599 IUnknown_Release(unk);
4600 IMFMediaType_Release(media_type2);
4602 IMFMediaType_Release(media_type);
4604 IMFMediaTypeHandler_Release(type_handler);
4606 /* Stream uses an allocator. */
4607 check_service_interface(stream_sink, &MR_VIDEO_ACCELERATION_SERVICE, &IID_IMFVideoSampleAllocator, TRUE);
4608 check_service_interface(stream_sink, &MR_VIDEO_ACCELERATION_SERVICE, &IID_IDirect3DDeviceManager9, TRUE);
4609 todo_wine {
4610 check_service_interface(stream_sink, &MR_VIDEO_MIXER_SERVICE, &IID_IMFVideoProcessor, TRUE);
4611 check_service_interface(stream_sink, &MR_VIDEO_MIXER_SERVICE, &IID_IMFVideoMixerBitmap, TRUE);
4612 check_service_interface(stream_sink, &MR_VIDEO_MIXER_SERVICE, &IID_IMFVideoMixerControl, TRUE);
4613 check_service_interface(stream_sink, &MR_VIDEO_MIXER_SERVICE, &IID_IMFVideoMixerControl2, TRUE);
4614 check_service_interface(stream_sink, &MR_VIDEO_RENDER_SERVICE, &IID_IMFVideoDisplayControl, TRUE);
4615 check_service_interface(stream_sink, &MR_VIDEO_RENDER_SERVICE, &IID_IMFVideoPositionMapper, TRUE);
4616 check_service_interface(stream_sink, &MF_RATE_CONTROL_SERVICE, &IID_IMFRateSupport, TRUE);
4618 hr = MFGetService((IUnknown *)stream_sink, &MR_VIDEO_ACCELERATION_SERVICE, &IID_IMFVideoSampleAllocator,
4619 (void **)&allocator);
4620 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4622 hr = IMFVideoSampleAllocator_QueryInterface(allocator, &IID_IMFVideoSampleAllocatorCallback, (void **)&allocator_callback);
4623 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4625 sample_count = 0;
4626 hr = IMFVideoSampleAllocatorCallback_GetFreeSampleCount(allocator_callback, &sample_count);
4627 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4628 ok(!sample_count, "Unexpected sample count %ld.\n", sample_count);
4630 hr = IMFVideoSampleAllocator_AllocateSample(allocator, &sample);
4631 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#lx.\n", hr);
4633 IMFVideoSampleAllocatorCallback_Release(allocator_callback);
4634 IMFVideoSampleAllocator_Release(allocator);
4636 /* Same test for a substream. */
4637 hr = IMFMediaSink_AddStreamSink(sink, 1, NULL, &stream_sink2);
4638 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4640 if (SUCCEEDED(hr))
4642 hr = MFGetService((IUnknown *)stream_sink2, &MR_VIDEO_ACCELERATION_SERVICE, &IID_IMFVideoSampleAllocator,
4643 (void **)&allocator);
4644 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4645 IMFVideoSampleAllocator_Release(allocator);
4647 hr = IMFMediaSink_RemoveStreamSink(sink, 1);
4648 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4650 IMFStreamSink_Release(stream_sink2);
4653 hr = IMFMediaSink_GetCharacteristics(sink, &flags);
4654 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4655 ok(flags == (MEDIASINK_CAN_PREROLL | MEDIASINK_CLOCK_REQUIRED), "Unexpected flags %#lx.\n", flags);
4657 hr = IMFActivate_ShutdownObject(activate);
4658 ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr);
4660 hr = IMFMediaSink_GetCharacteristics(sink, &flags);
4661 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
4663 /* Activate again. */
4664 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink2);
4665 ok(hr == S_OK, "Failed to activate, hr %#lx.\n", hr);
4666 todo_wine
4667 ok(sink == sink2, "Unexpected instance.\n");
4668 IMFMediaSink_Release(sink2);
4670 hr = IMFActivate_DetachObject(activate);
4671 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
4673 hr = IMFMediaSink_GetCharacteristics(sink, &flags);
4674 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
4676 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink2);
4677 ok(hr == S_OK, "Failed to activate, hr %#lx.\n", hr);
4679 hr = IMFActivate_ShutdownObject(activate);
4680 ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr);
4682 IMFMediaSink_Release(sink2);
4683 IMFMediaSink_Release(sink);
4685 IMFActivate_Release(activate);
4687 /* Set clock. */
4688 window = create_window();
4690 hr = MFCreateVideoRendererActivate(window, &activate);
4691 ok(hr == S_OK, "Failed to create activate object, hr %#lx.\n", hr);
4693 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink);
4694 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4696 hr = MFCreateSystemTimeSource(&time_source);
4697 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4699 hr = MFCreatePresentationClock(&clock);
4700 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4702 hr = IMFPresentationClock_SetTimeSource(clock, time_source);
4703 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4704 IMFPresentationTimeSource_Release(time_source);
4706 hr = IMFMediaSink_SetPresentationClock(sink, clock);
4707 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4709 hr = IMFMediaSink_QueryInterface(sink, &IID_IMFRateSupport, (void **)&rs);
4710 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4712 rate = 1.0f;
4713 hr = IMFRateSupport_GetSlowestRate(rs, MFRATE_FORWARD, FALSE, &rate);
4714 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4715 ok(rate == 0.0f, "Unexpected rate %f.\n", rate);
4717 rate = 1.0f;
4718 hr = IMFRateSupport_GetSlowestRate(rs, MFRATE_REVERSE, FALSE, &rate);
4719 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4720 ok(rate == 0.0f, "Unexpected rate %f.\n", rate);
4722 rate = 1.0f;
4723 hr = IMFRateSupport_GetSlowestRate(rs, MFRATE_FORWARD, TRUE, &rate);
4724 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4725 ok(rate == 0.0f, "Unexpected rate %f.\n", rate);
4727 rate = 1.0f;
4728 hr = IMFRateSupport_GetSlowestRate(rs, MFRATE_REVERSE, TRUE, &rate);
4729 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4730 ok(rate == 0.0f, "Unexpected rate %f.\n", rate);
4732 hr = IMFRateSupport_GetFastestRate(rs, MFRATE_FORWARD, FALSE, &rate);
4733 ok(hr == MF_E_INVALIDREQUEST, "Unexpected hr %#lx.\n", hr);
4735 hr = IMFRateSupport_GetFastestRate(rs, MFRATE_REVERSE, FALSE, &rate);
4736 ok(hr == MF_E_INVALIDREQUEST, "Unexpected hr %#lx.\n", hr);
4738 hr = IMFRateSupport_GetFastestRate(rs, MFRATE_FORWARD, TRUE, &rate);
4739 ok(hr == MF_E_INVALIDREQUEST, "Unexpected hr %#lx.\n", hr);
4741 hr = IMFRateSupport_GetFastestRate(rs, MFRATE_REVERSE, TRUE, &rate);
4742 ok(hr == MF_E_INVALIDREQUEST, "Unexpected hr %#lx.\n", hr);
4744 hr = IMFRateSupport_GetFastestRate(rs, MFRATE_REVERSE, TRUE, NULL);
4745 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
4747 for (i = 0; i < ARRAY_SIZE(supported_rates); ++i)
4749 rate = supported_rates[i] + 1.0f;
4750 hr = IMFRateSupport_IsRateSupported(rs, TRUE, supported_rates[i], &rate);
4751 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4752 ok(rate == supported_rates[i], "Unexpected rate %f.\n", rate);
4754 rate = supported_rates[i] + 1.0f;
4755 hr = IMFRateSupport_IsRateSupported(rs, FALSE, supported_rates[i], &rate);
4756 ok(hr == MF_E_INVALIDREQUEST, "Unexpected hr %#lx.\n", hr);
4757 ok(rate == supported_rates[i], "Unexpected rate %f.\n", rate);
4759 hr = IMFRateSupport_IsRateSupported(rs, TRUE, supported_rates[i], NULL);
4760 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4762 hr = IMFRateSupport_IsRateSupported(rs, FALSE, supported_rates[i], NULL);
4763 ok(hr == MF_E_INVALIDREQUEST, "Unexpected hr %#lx.\n", hr);
4766 /* Configuring stream type make rate support work. */
4767 hr = IMFMediaSink_GetStreamSinkById(sink, 0, &stream_sink);
4768 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4769 hr = IMFStreamSink_GetMediaTypeHandler(stream_sink, &type_handler);
4770 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4771 hr = MFCreateMediaType(&media_type);
4772 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4773 hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
4774 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4775 hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFVideoFormat_RGB32);
4776 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4777 hr = IMFMediaType_SetUINT64(media_type, &MF_MT_FRAME_SIZE, (UINT64)64 << 32 | 64);
4778 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4779 hr = IMFMediaType_SetUINT32(media_type, &MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE);
4780 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4781 hr = IMFMediaTypeHandler_SetCurrentMediaType(type_handler, media_type);
4782 ok(hr == S_OK, "Failed to set current type, hr %#lx.\n", hr);
4784 rate = 1.0f;
4785 hr = IMFRateSupport_GetSlowestRate(rs, MFRATE_FORWARD, TRUE, &rate);
4786 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4787 ok(rate == 0.0f, "Unexpected rate %f.\n", rate);
4789 rate = 1.0f;
4790 hr = IMFRateSupport_GetSlowestRate(rs, MFRATE_REVERSE, TRUE, &rate);
4791 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4792 ok(rate == 0.0f, "Unexpected rate %f.\n", rate);
4794 rate = 0.0f;
4795 hr = IMFRateSupport_GetFastestRate(rs, MFRATE_FORWARD, TRUE, &rate);
4796 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4797 ok(rate == FLT_MAX, "Unexpected rate %f.\n", rate);
4799 rate = 0.0f;
4800 hr = IMFRateSupport_GetFastestRate(rs, MFRATE_REVERSE, TRUE, &rate);
4801 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4802 ok(rate == -FLT_MAX, "Unexpected rate %f.\n", rate);
4804 hr = IMFRateSupport_GetFastestRate(rs, MFRATE_REVERSE, TRUE, NULL);
4805 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
4807 hr = IMFRateSupport_GetSlowestRate(rs, MFRATE_REVERSE, TRUE, NULL);
4808 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
4810 for (i = 0; i < ARRAY_SIZE(supported_rates); ++i)
4812 rate = supported_rates[i] + 1.0f;
4813 hr = IMFRateSupport_IsRateSupported(rs, TRUE, supported_rates[i], &rate);
4814 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4815 ok(rate == supported_rates[i], "Unexpected rate %f.\n", rate);
4817 rate = supported_rates[i] + 1.0f;
4818 hr = IMFRateSupport_IsRateSupported(rs, FALSE, supported_rates[i], &rate);
4819 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4820 ok(rate == supported_rates[i], "Unexpected rate %f.\n", rate);
4822 hr = IMFRateSupport_IsRateSupported(rs, TRUE, supported_rates[i], NULL);
4823 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4825 hr = IMFRateSupport_IsRateSupported(rs, FALSE, supported_rates[i], NULL);
4826 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4829 IMFMediaTypeHandler_Release(type_handler);
4830 IMFMediaType_Release(media_type);
4831 IMFStreamSink_Release(stream_sink);
4833 hr = IMFMediaSink_Shutdown(sink);
4834 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4836 hr = IMFMediaSink_GetStreamSinkCount(sink, NULL);
4837 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
4839 hr = IMFMediaSink_GetStreamSinkCount(sink, &count);
4840 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
4842 hr = IMFRateSupport_GetSlowestRate(rs, MFRATE_FORWARD, FALSE, &rate);
4843 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
4845 hr = IMFRateSupport_GetFastestRate(rs, MFRATE_FORWARD, FALSE, &rate);
4846 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
4848 hr = IMFRateSupport_GetSlowestRate(rs, MFRATE_FORWARD, FALSE, NULL);
4849 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
4851 hr = IMFRateSupport_GetFastestRate(rs, MFRATE_FORWARD, FALSE, NULL);
4852 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
4854 hr = IMFRateSupport_IsRateSupported(rs, TRUE, 1.0f, &rate);
4855 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
4857 IMFPresentationClock_Release(clock);
4859 IMFActivate_Release(activate);
4860 DestroyWindow(window);
4862 hr = MFShutdown();
4863 ok(hr == S_OK, "Shutdown failure, hr %#lx.\n", hr);
4866 static void test_MFCreateSimpleTypeHandler(void)
4868 IMFMediaType *media_type, *media_type2, *media_type3;
4869 IMFMediaTypeHandler *handler;
4870 DWORD count;
4871 HRESULT hr;
4872 GUID guid;
4874 hr = MFCreateSimpleTypeHandler(&handler);
4875 ok(hr == S_OK, "Failed to create object, hr %#lx.\n", hr);
4877 hr = IMFMediaTypeHandler_GetMediaTypeCount(handler, NULL);
4878 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
4880 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, NULL, NULL);
4881 ok(hr == MF_E_UNEXPECTED, "Unexpected hr %#lx.\n", hr);
4883 count = 0;
4884 hr = IMFMediaTypeHandler_GetMediaTypeCount(handler, &count);
4885 ok(hr == S_OK, "Failed to get type count, hr %#lx.\n", hr);
4886 ok(count == 1, "Unexpected count %lu.\n", count);
4888 hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, NULL);
4889 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
4891 media_type = (void *)0xdeadbeef;
4892 hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, &media_type);
4893 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4894 ok(!media_type, "Unexpected pointer.\n");
4896 hr = MFCreateMediaType(&media_type);
4897 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
4899 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type, NULL);
4900 ok(hr == MF_E_UNEXPECTED, "Unexpected hr %#lx.\n", hr);
4902 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, media_type);
4903 ok(hr == S_OK, "Failed to set current type, hr %#lx.\n", hr);
4905 hr = IMFMediaTypeHandler_GetMediaTypeByIndex(handler, 0, &media_type2);
4906 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4907 ok(media_type2 == media_type, "Unexpected type.\n");
4908 IMFMediaType_Release(media_type2);
4910 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, NULL, NULL);
4911 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
4913 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type, NULL);
4914 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
4916 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type, &media_type2);
4917 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
4919 hr = IMFMediaTypeHandler_GetMediaTypeByIndex(handler, 1, &media_type2);
4920 ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#lx.\n", hr);
4922 hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, &media_type2);
4923 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4924 ok(media_type == media_type2, "Unexpected pointer.\n");
4925 IMFMediaType_Release(media_type2);
4927 hr = IMFMediaTypeHandler_GetMajorType(handler, &guid);
4928 ok(hr == MF_E_ATTRIBUTENOTFOUND, "Unexpected hr %#lx.\n", hr);
4930 hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
4931 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
4933 hr = IMFMediaTypeHandler_GetMajorType(handler, &guid);
4934 ok(hr == S_OK, "Failed to get major type, hr %#lx.\n", hr);
4935 ok(IsEqualGUID(&guid, &MFMediaType_Video), "Unexpected major type.\n");
4937 hr = MFCreateMediaType(&media_type3);
4938 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
4940 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type3, NULL);
4941 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
4943 hr = IMFMediaType_SetGUID(media_type3, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio);
4944 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
4946 /* Different major types. */
4947 media_type2 = (void *)0xdeadbeef;
4948 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type3, &media_type2);
4949 ok(hr == E_FAIL, "Unexpected hr %#lx.\n", hr);
4950 ok(!media_type2, "Unexpected pointer.\n");
4952 hr = IMFMediaType_SetGUID(media_type3, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
4953 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
4955 media_type2 = (void *)0xdeadbeef;
4956 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type3, &media_type2);
4957 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4958 ok(!media_type2, "Unexpected pointer.\n");
4960 /* Handler missing subtype. */
4961 hr = IMFMediaType_SetGUID(media_type3, &MF_MT_SUBTYPE, &MFVideoFormat_RGB8);
4962 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
4964 media_type2 = (void *)0xdeadbeef;
4965 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type3, &media_type2);
4966 ok(hr == E_FAIL, "Unexpected hr %#lx.\n", hr);
4967 ok(!media_type2, "Unexpected pointer.\n");
4969 /* Different subtypes. */
4970 hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFVideoFormat_RGB24);
4971 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
4973 media_type2 = (void *)0xdeadbeef;
4974 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type3, &media_type2);
4975 ok(hr == E_FAIL, "Unexpected hr %#lx.\n", hr);
4976 ok(!media_type2, "Unexpected pointer.\n");
4978 /* Same major/subtype. */
4979 hr = IMFMediaType_SetGUID(media_type3, &MF_MT_SUBTYPE, &MFVideoFormat_RGB24);
4980 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
4982 media_type2 = (void *)0xdeadbeef;
4983 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type3, &media_type2);
4984 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4985 ok(!media_type2, "Unexpected pointer.\n");
4987 /* Set one more attribute. */
4988 hr = IMFMediaType_SetUINT64(media_type, &MF_MT_FRAME_SIZE, (UINT64)4 << 32 | 4);
4989 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
4991 media_type2 = (void *)0xdeadbeef;
4992 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type3, &media_type2);
4993 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4994 ok(!media_type2, "Unexpected pointer.\n");
4996 IMFMediaType_Release(media_type3);
4997 IMFMediaType_Release(media_type);
4999 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, NULL);
5000 ok(hr == S_OK, "Failed to set current type, hr %#lx.\n", hr);
5002 media_type = (void *)0xdeadbeef;
5003 hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, &media_type);
5004 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5005 ok(!media_type, "Unexpected pointer.\n");
5007 hr = IMFMediaTypeHandler_GetMajorType(handler, &guid);
5008 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#lx.\n", hr);
5010 IMFMediaTypeHandler_Release(handler);
5013 static void test_MFGetSupportedMimeTypes(void)
5015 PROPVARIANT value;
5016 HRESULT hr;
5018 hr = MFGetSupportedMimeTypes(NULL);
5019 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
5021 value.vt = VT_EMPTY;
5022 hr = MFGetSupportedMimeTypes(&value);
5023 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5024 ok(value.vt == (VT_VECTOR | VT_LPWSTR), "Unexpected value type %#x.\n", value.vt);
5026 PropVariantClear(&value);
5029 static void test_MFGetSupportedSchemes(void)
5031 PROPVARIANT value;
5032 HRESULT hr;
5034 hr = MFGetSupportedSchemes(NULL);
5035 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
5037 value.vt = VT_EMPTY;
5038 hr = MFGetSupportedSchemes(&value);
5039 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5040 ok(value.vt == (VT_VECTOR | VT_LPWSTR), "Unexpected value type %#x.\n", value.vt);
5042 PropVariantClear(&value);
5045 static BOOL is_sample_copier_available_type(IMFMediaType *type)
5047 GUID major = { 0 };
5048 UINT32 count;
5049 HRESULT hr;
5051 hr = IMFMediaType_GetMajorType(type, &major);
5052 ok(hr == S_OK, "Failed to get major type, hr %#lx.\n", hr);
5054 hr = IMFMediaType_GetCount(type, &count);
5055 ok(hr == S_OK, "Failed to get attribute count, hr %#lx.\n", hr);
5056 ok(count == 1, "Unexpected attribute count %u.\n", count);
5058 return IsEqualGUID(&major, &MFMediaType_Video) || IsEqualGUID(&major, &MFMediaType_Audio);
5061 static void test_sample_copier(void)
5063 IMFAttributes *attributes, *attributes2;
5064 DWORD in_min, in_max, out_min, out_max;
5065 IMFMediaType *mediatype, *mediatype2;
5066 MFT_OUTPUT_STREAM_INFO output_info;
5067 IMFSample *sample, *client_sample;
5068 MFT_INPUT_STREAM_INFO input_info;
5069 DWORD input_count, output_count;
5070 MFT_OUTPUT_DATA_BUFFER buffer;
5071 IMFMediaBuffer *media_buffer;
5072 IMFTransform *copier;
5073 DWORD flags, status;
5074 UINT32 value, count;
5075 HRESULT hr;
5077 if (!pMFCreateSampleCopierMFT)
5079 win_skip("MFCreateSampleCopierMFT() is not available.\n");
5080 return;
5083 hr = pMFCreateSampleCopierMFT(&copier);
5084 ok(hr == S_OK, "Failed to create sample copier, hr %#lx.\n", hr);
5086 hr = IMFTransform_GetAttributes(copier, &attributes);
5087 ok(hr == S_OK, "Failed to get transform attributes, hr %#lx.\n", hr);
5088 hr = IMFTransform_GetAttributes(copier, &attributes2);
5089 ok(hr == S_OK, "Failed to get transform attributes, hr %#lx.\n", hr);
5090 ok(attributes == attributes2, "Unexpected instance.\n");
5091 IMFAttributes_Release(attributes2);
5092 hr = IMFAttributes_GetCount(attributes, &count);
5093 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5094 ok(count == 1, "Unexpected attribute count %u.\n", count);
5095 hr = IMFAttributes_GetUINT32(attributes, &MFT_SUPPORT_DYNAMIC_FORMAT_CHANGE, &value);
5096 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5097 ok(!!value, "Unexpected value %u.\n", value);
5098 IMFAttributes_Release(attributes);
5100 hr = IMFTransform_GetInputStreamAttributes(copier, 0, &attributes);
5101 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
5103 hr = IMFTransform_GetInputStreamAttributes(copier, 1, &attributes);
5104 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
5106 hr = IMFTransform_GetOutputStreamAttributes(copier, 0, &attributes);
5107 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
5109 hr = IMFTransform_GetOutputStreamAttributes(copier, 1, &attributes);
5110 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
5112 hr = IMFTransform_SetOutputBounds(copier, 0, 0);
5113 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
5115 /* No dynamic streams. */
5116 input_count = output_count = 0;
5117 hr = IMFTransform_GetStreamCount(copier, &input_count, &output_count);
5118 ok(hr == S_OK, "Failed to get stream count, hr %#lx.\n", hr);
5119 ok(input_count == 1 && output_count == 1, "Unexpected streams count.\n");
5121 hr = IMFTransform_GetStreamLimits(copier, &in_min, &in_max, &out_min, &out_max);
5122 ok(hr == S_OK, "Failed to get stream limits, hr %#lx.\n", hr);
5123 ok(in_min == in_max && in_min == 1 && out_min == out_max && out_min == 1, "Unexpected stream limits.\n");
5125 hr = IMFTransform_GetStreamIDs(copier, 1, &input_count, 1, &output_count);
5126 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
5128 hr = IMFTransform_DeleteInputStream(copier, 0);
5129 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
5131 /* Available types. */
5132 hr = IMFTransform_GetInputAvailableType(copier, 0, 0, &mediatype);
5133 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5134 ok(is_sample_copier_available_type(mediatype), "Unexpected type.\n");
5135 IMFMediaType_Release(mediatype);
5137 hr = IMFTransform_GetInputAvailableType(copier, 0, 1, &mediatype);
5138 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5139 ok(is_sample_copier_available_type(mediatype), "Unexpected type.\n");
5140 IMFMediaType_Release(mediatype);
5142 hr = IMFTransform_GetInputAvailableType(copier, 0, 2, &mediatype);
5143 ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#lx.\n", hr);
5145 hr = IMFTransform_GetInputAvailableType(copier, 1, 0, &mediatype);
5146 ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#lx.\n", hr);
5148 hr = IMFTransform_GetOutputAvailableType(copier, 0, 0, &mediatype);
5149 ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#lx.\n", hr);
5151 hr = IMFTransform_GetOutputAvailableType(copier, 1, 0, &mediatype);
5152 ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#lx.\n", hr);
5154 hr = IMFTransform_GetInputCurrentType(copier, 0, &mediatype);
5155 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
5157 hr = IMFTransform_GetInputCurrentType(copier, 1, &mediatype);
5158 ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#lx.\n", hr);
5160 hr = IMFTransform_GetOutputCurrentType(copier, 0, &mediatype);
5161 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
5163 hr = IMFTransform_GetOutputCurrentType(copier, 1, &mediatype);
5164 ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#lx.\n", hr);
5166 hr = MFCreateSample(&sample);
5167 ok(hr == S_OK, "Failed to create a sample, hr %#lx.\n", hr);
5169 hr = IMFTransform_ProcessInput(copier, 0, sample, 0);
5170 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
5172 hr = MFCreateMediaType(&mediatype);
5173 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
5175 hr = IMFTransform_SetOutputType(copier, 0, mediatype, 0);
5176 ok(hr == MF_E_ATTRIBUTENOTFOUND, "Unexpected hr %#lx.\n", hr);
5178 hr = IMFMediaType_SetGUID(mediatype, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
5179 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
5181 hr = IMFMediaType_SetGUID(mediatype, &MF_MT_SUBTYPE, &MFVideoFormat_RGB8);
5182 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
5184 hr = IMFMediaType_SetUINT64(mediatype, &MF_MT_FRAME_SIZE, ((UINT64)16) << 32 | 16);
5185 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
5187 hr = IMFTransform_GetOutputStreamInfo(copier, 0, &output_info);
5188 ok(hr == S_OK, "Failed to get stream info, hr %#lx.\n", hr);
5189 ok(!output_info.dwFlags, "Unexpected flags %#lx.\n", output_info.dwFlags);
5190 ok(!output_info.cbSize, "Unexpected size %lu.\n", output_info.cbSize);
5191 ok(!output_info.cbAlignment, "Unexpected alignment %lu.\n", output_info.cbAlignment);
5193 hr = IMFTransform_GetInputStreamInfo(copier, 0, &input_info);
5194 ok(hr == S_OK, "Failed to get stream info, hr %#lx.\n", hr);
5196 ok(!input_info.hnsMaxLatency, "Unexpected latency %s.\n", wine_dbgstr_longlong(input_info.hnsMaxLatency));
5197 ok(!input_info.dwFlags, "Unexpected flags %#lx.\n", input_info.dwFlags);
5198 ok(!input_info.cbSize, "Unexpected size %lu.\n", input_info.cbSize);
5199 ok(!input_info.cbMaxLookahead, "Unexpected lookahead size %lu.\n", input_info.cbMaxLookahead);
5200 ok(!input_info.cbAlignment, "Unexpected alignment %lu.\n", input_info.cbAlignment);
5202 hr = IMFTransform_SetOutputType(copier, 0, mediatype, 0);
5203 ok(hr == S_OK, "Failed to set input type, hr %#lx.\n", hr);
5205 hr = IMFTransform_GetOutputStreamInfo(copier, 0, &output_info);
5206 ok(hr == S_OK, "Failed to get stream info, hr %#lx.\n", hr);
5207 ok(!output_info.dwFlags, "Unexpected flags %#lx.\n", output_info.dwFlags);
5208 ok(output_info.cbSize == 16 * 16, "Unexpected size %lu.\n", output_info.cbSize);
5209 ok(!output_info.cbAlignment, "Unexpected alignment %lu.\n", output_info.cbAlignment);
5211 hr = IMFTransform_GetOutputCurrentType(copier, 0, &mediatype2);
5212 ok(hr == S_OK, "Failed to get current type, hr %#lx.\n", hr);
5213 IMFMediaType_Release(mediatype2);
5215 hr = IMFTransform_GetInputCurrentType(copier, 0, &mediatype2);
5216 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
5218 hr = IMFTransform_GetInputStatus(copier, 0, &flags);
5219 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
5221 /* Setting input type resets output type. */
5222 hr = IMFTransform_GetOutputCurrentType(copier, 0, &mediatype2);
5223 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5224 IMFMediaType_Release(mediatype2);
5226 hr = IMFTransform_SetInputType(copier, 0, mediatype, 0);
5227 ok(hr == S_OK, "Failed to set input type, hr %#lx.\n", hr);
5229 hr = IMFTransform_GetOutputCurrentType(copier, 0, &mediatype2);
5230 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
5232 hr = IMFTransform_GetInputAvailableType(copier, 0, 1, &mediatype2);
5233 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5234 ok(is_sample_copier_available_type(mediatype2), "Unexpected type.\n");
5235 IMFMediaType_Release(mediatype2);
5237 hr = IMFTransform_GetInputStreamInfo(copier, 0, &input_info);
5238 ok(hr == S_OK, "Failed to get stream info, hr %#lx.\n", hr);
5239 ok(!input_info.hnsMaxLatency, "Unexpected latency %s.\n", wine_dbgstr_longlong(input_info.hnsMaxLatency));
5240 ok(!input_info.dwFlags, "Unexpected flags %#lx.\n", input_info.dwFlags);
5241 ok(input_info.cbSize == 16 * 16, "Unexpected size %lu.\n", input_info.cbSize);
5242 ok(!input_info.cbMaxLookahead, "Unexpected lookahead size %lu.\n", input_info.cbMaxLookahead);
5243 ok(!input_info.cbAlignment, "Unexpected alignment %lu.\n", input_info.cbAlignment);
5245 hr = IMFTransform_GetOutputAvailableType(copier, 0, 0, &mediatype2);
5246 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5247 hr = IMFMediaType_IsEqual(mediatype2, mediatype, &flags);
5248 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5249 IMFMediaType_Release(mediatype2);
5251 hr = IMFTransform_GetInputStatus(copier, 0, &flags);
5252 ok(hr == S_OK, "Failed to get input status, hr %#lx.\n", hr);
5253 ok(flags == MFT_INPUT_STATUS_ACCEPT_DATA, "Unexpected flags %#lx.\n", flags);
5255 hr = IMFTransform_GetInputCurrentType(copier, 0, &mediatype2);
5256 ok(hr == S_OK, "Failed to get current type, hr %#lx.\n", hr);
5257 IMFMediaType_Release(mediatype2);
5259 hr = IMFTransform_GetOutputStatus(copier, &flags);
5260 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
5262 hr = IMFTransform_SetOutputType(copier, 0, mediatype, 0);
5263 ok(hr == S_OK, "Failed to set output type, hr %#lx.\n", hr);
5265 hr = IMFTransform_GetOutputStatus(copier, &flags);
5266 ok(hr == S_OK, "Failed to get output status, hr %#lx.\n", hr);
5267 ok(!flags, "Unexpected flags %#lx.\n", flags);
5269 /* Pushing samples. */
5270 hr = MFCreateAlignedMemoryBuffer(output_info.cbSize, output_info.cbAlignment, &media_buffer);
5271 ok(hr == S_OK, "Failed to create media buffer, hr %#lx.\n", hr);
5273 hr = IMFSample_AddBuffer(sample, media_buffer);
5274 ok(hr == S_OK, "Failed to add a buffer, hr %#lx.\n", hr);
5275 IMFMediaBuffer_Release(media_buffer);
5277 EXPECT_REF(sample, 1);
5278 hr = IMFTransform_ProcessInput(copier, 0, sample, 0);
5279 ok(hr == S_OK, "Failed to process input, hr %#lx.\n", hr);
5280 EXPECT_REF(sample, 2);
5282 hr = IMFTransform_GetInputStatus(copier, 0, &flags);
5283 ok(hr == S_OK, "Failed to get input status, hr %#lx.\n", hr);
5284 ok(!flags, "Unexpected flags %#lx.\n", flags);
5286 hr = IMFTransform_GetOutputStatus(copier, &flags);
5287 ok(hr == S_OK, "Failed to get output status, hr %#lx.\n", hr);
5288 ok(flags == MFT_OUTPUT_STATUS_SAMPLE_READY, "Unexpected flags %#lx.\n", flags);
5290 hr = IMFTransform_ProcessInput(copier, 0, sample, 0);
5291 ok(hr == MF_E_NOTACCEPTING, "Unexpected hr %#lx.\n", hr);
5293 hr = IMFTransform_GetOutputStreamInfo(copier, 0, &output_info);
5294 ok(hr == S_OK, "Failed to get output info, hr %#lx.\n", hr);
5296 hr = MFCreateAlignedMemoryBuffer(output_info.cbSize, output_info.cbAlignment, &media_buffer);
5297 ok(hr == S_OK, "Failed to create media buffer, hr %#lx.\n", hr);
5299 hr = MFCreateSample(&client_sample);
5300 ok(hr == S_OK, "Failed to create a sample, hr %#lx.\n", hr);
5302 hr = IMFSample_AddBuffer(client_sample, media_buffer);
5303 ok(hr == S_OK, "Failed to add a buffer, hr %#lx.\n", hr);
5304 IMFMediaBuffer_Release(media_buffer);
5306 status = 0;
5307 memset(&buffer, 0, sizeof(buffer));
5308 buffer.pSample = client_sample;
5309 hr = IMFTransform_ProcessOutput(copier, 0, 1, &buffer, &status);
5310 ok(hr == S_OK, "Failed to get output, hr %#lx.\n", hr);
5311 EXPECT_REF(sample, 1);
5313 hr = IMFTransform_ProcessOutput(copier, 0, 1, &buffer, &status);
5314 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "Failed to get output, hr %#lx.\n", hr);
5316 /* Flushing. */
5317 hr = IMFTransform_ProcessInput(copier, 0, sample, 0);
5318 ok(hr == S_OK, "Failed to process input, hr %#lx.\n", hr);
5319 EXPECT_REF(sample, 2);
5321 hr = IMFTransform_ProcessMessage(copier, MFT_MESSAGE_COMMAND_FLUSH, 0);
5322 ok(hr == S_OK, "Failed to flush, hr %#lx.\n", hr);
5323 EXPECT_REF(sample, 1);
5325 IMFSample_Release(sample);
5326 IMFSample_Release(client_sample);
5328 IMFMediaType_Release(mediatype);
5329 IMFTransform_Release(copier);
5332 struct sample_metadata
5334 unsigned int flags;
5335 LONGLONG duration;
5336 LONGLONG time;
5339 static void sample_copier_process(IMFTransform *copier, IMFMediaBuffer *input_buffer,
5340 IMFMediaBuffer *output_buffer, const struct sample_metadata *md)
5342 static const struct sample_metadata zero_md = { 0, ~0u, ~0u };
5343 IMFSample *input_sample, *output_sample;
5344 MFT_OUTPUT_DATA_BUFFER buffer;
5345 DWORD flags, status;
5346 LONGLONG time;
5347 HRESULT hr;
5349 hr = MFCreateSample(&input_sample);
5350 ok(hr == S_OK, "Failed to create a sample, hr %#lx.\n", hr);
5352 if (md)
5354 hr = IMFSample_SetSampleFlags(input_sample, md->flags);
5355 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5357 hr = IMFSample_SetSampleTime(input_sample, md->time);
5358 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5360 hr = IMFSample_SetSampleDuration(input_sample, md->duration);
5361 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5364 hr = MFCreateSample(&output_sample);
5365 ok(hr == S_OK, "Failed to create a sample, hr %#lx.\n", hr);
5367 hr = IMFSample_SetSampleFlags(output_sample, ~0u);
5368 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5370 hr = IMFSample_SetSampleTime(output_sample, ~0u);
5371 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5373 hr = IMFSample_SetSampleDuration(output_sample, ~0u);
5374 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5376 hr = IMFSample_AddBuffer(input_sample, input_buffer);
5377 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5379 hr = IMFSample_AddBuffer(output_sample, output_buffer);
5380 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5382 hr = IMFTransform_ProcessInput(copier, 0, input_sample, 0);
5383 ok(hr == S_OK, "Failed to process input, hr %#lx.\n", hr);
5385 status = 0;
5386 memset(&buffer, 0, sizeof(buffer));
5387 buffer.pSample = output_sample;
5388 hr = IMFTransform_ProcessOutput(copier, 0, 1, &buffer, &status);
5389 ok(hr == S_OK, "Failed to get output, hr %#lx.\n", hr);
5391 if (!md) md = &zero_md;
5393 hr = IMFSample_GetSampleFlags(output_sample, &flags);
5394 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5395 ok(md->flags == flags, "Unexpected flags.\n");
5396 hr = IMFSample_GetSampleTime(output_sample, &time);
5397 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5398 ok(md->time == time, "Unexpected time.\n");
5399 hr = IMFSample_GetSampleDuration(output_sample, &time);
5400 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5401 ok(md->duration == time, "Unexpected duration.\n");
5403 IMFSample_Release(input_sample);
5404 IMFSample_Release(output_sample);
5407 static void test_sample_copier_output_processing(void)
5409 IMFMediaBuffer *input_buffer, *output_buffer;
5410 MFT_OUTPUT_STREAM_INFO output_info;
5411 struct sample_metadata md;
5412 IMFMediaType *mediatype;
5413 IMFTransform *copier;
5414 DWORD max_length;
5415 HRESULT hr;
5416 BYTE *ptr;
5418 if (!pMFCreateSampleCopierMFT)
5419 return;
5421 hr = pMFCreateSampleCopierMFT(&copier);
5422 ok(hr == S_OK, "Failed to create sample copier, hr %#lx.\n", hr);
5424 /* Configure for 16 x 16 of D3DFMT_X8R8G8B8. */
5425 hr = MFCreateMediaType(&mediatype);
5426 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
5428 hr = IMFMediaType_SetGUID(mediatype, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
5429 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
5431 hr = IMFMediaType_SetGUID(mediatype, &MF_MT_SUBTYPE, &MFVideoFormat_RGB32);
5432 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
5434 hr = IMFMediaType_SetUINT64(mediatype, &MF_MT_FRAME_SIZE, ((UINT64)16) << 32 | 16);
5435 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
5437 hr = IMFTransform_SetInputType(copier, 0, mediatype, 0);
5438 ok(hr == S_OK, "Failed to set input type, hr %#lx.\n", hr);
5440 hr = IMFTransform_SetOutputType(copier, 0, mediatype, 0);
5441 ok(hr == S_OK, "Failed to set input type, hr %#lx.\n", hr);
5443 /* Source and destination are linear buffers, destination is twice as large. */
5444 hr = IMFTransform_GetOutputStreamInfo(copier, 0, &output_info);
5445 ok(hr == S_OK, "Failed to get output info, hr %#lx.\n", hr);
5447 hr = MFCreateAlignedMemoryBuffer(output_info.cbSize, output_info.cbAlignment, &output_buffer);
5448 ok(hr == S_OK, "Failed to create media buffer, hr %#lx.\n", hr);
5450 hr = IMFMediaBuffer_Lock(output_buffer, &ptr, &max_length, NULL);
5451 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5452 memset(ptr, 0xcc, max_length);
5453 hr = IMFMediaBuffer_Unlock(output_buffer);
5454 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5456 hr = MFCreateAlignedMemoryBuffer(output_info.cbSize, output_info.cbAlignment, &input_buffer);
5457 ok(hr == S_OK, "Failed to create media buffer, hr %#lx.\n", hr);
5459 hr = IMFMediaBuffer_Lock(input_buffer, &ptr, &max_length, NULL);
5460 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5461 memset(ptr, 0xaa, max_length);
5462 hr = IMFMediaBuffer_Unlock(input_buffer);
5463 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5464 hr = IMFMediaBuffer_SetCurrentLength(input_buffer, 4);
5465 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5467 sample_copier_process(copier, input_buffer, output_buffer, NULL);
5469 hr = IMFMediaBuffer_Lock(output_buffer, &ptr, &max_length, NULL);
5470 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5471 ok(ptr[0] == 0xaa && ptr[4] == 0xcc, "Unexpected buffer contents.\n");
5473 hr = IMFMediaBuffer_Unlock(output_buffer);
5474 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5476 md.flags = 123;
5477 md.time = 10;
5478 md.duration = 2;
5479 sample_copier_process(copier, input_buffer, output_buffer, &md);
5481 IMFMediaBuffer_Release(input_buffer);
5482 IMFMediaBuffer_Release(output_buffer);
5484 IMFMediaType_Release(mediatype);
5485 IMFTransform_Release(copier);
5488 static void test_MFGetTopoNodeCurrentType(void)
5490 IMFMediaType *media_type, *media_type2;
5491 IMFTopologyNode *node;
5492 HRESULT hr;
5494 if (!pMFGetTopoNodeCurrentType)
5496 win_skip("MFGetTopoNodeCurrentType() is unsupported.\n");
5497 return;
5500 /* Tee node. */
5501 hr = MFCreateTopologyNode(MF_TOPOLOGY_TEE_NODE, &node);
5502 ok(hr == S_OK, "Failed to create a node, hr %#lx.\n", hr);
5504 hr = pMFGetTopoNodeCurrentType(node, 0, TRUE, &media_type);
5505 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
5507 hr = pMFGetTopoNodeCurrentType(node, 0, FALSE, &media_type);
5508 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
5510 hr = MFCreateMediaType(&media_type2);
5511 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
5513 hr = IMFMediaType_SetGUID(media_type2, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
5514 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
5516 /* Input type returned, if set. */
5517 hr = IMFTopologyNode_SetInputPrefType(node, 0, media_type2);
5518 ok(hr == S_OK, "Failed to set media type, hr %#lx.\n", hr);
5520 hr = pMFGetTopoNodeCurrentType(node, 0, FALSE, &media_type);
5521 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5522 ok(media_type == media_type2, "Unexpected pointer.\n");
5523 IMFMediaType_Release(media_type);
5525 hr = IMFTopologyNode_SetInputPrefType(node, 0, NULL);
5526 ok(hr == S_OK, "Failed to set media type, hr %#lx.\n", hr);
5528 hr = pMFGetTopoNodeCurrentType(node, 0, FALSE, &media_type);
5529 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
5531 /* Set second output. */
5532 hr = IMFTopologyNode_SetOutputPrefType(node, 1, media_type2);
5533 ok(hr == S_OK, "Failed to set media type, hr %#lx.\n", hr);
5535 hr = pMFGetTopoNodeCurrentType(node, 0, FALSE, &media_type);
5536 ok(hr == E_FAIL, "Unexpected hr %#lx.\n", hr);
5538 hr = IMFTopologyNode_SetOutputPrefType(node, 1, NULL);
5539 ok(hr == S_OK, "Failed to set media type, hr %#lx.\n", hr);
5541 /* Set first output. */
5542 hr = IMFTopologyNode_SetOutputPrefType(node, 0, media_type2);
5543 ok(hr == S_OK, "Failed to set media type, hr %#lx.\n", hr);
5545 hr = pMFGetTopoNodeCurrentType(node, 0, FALSE, &media_type);
5546 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5547 ok(media_type == media_type2, "Unexpected pointer.\n");
5548 IMFMediaType_Release(media_type);
5550 hr = IMFTopologyNode_SetOutputPrefType(node, 0, NULL);
5551 ok(hr == S_OK, "Failed to set media type, hr %#lx.\n", hr);
5553 /* Set primary output. */
5554 hr = IMFTopologyNode_SetOutputPrefType(node, 1, media_type2);
5555 ok(hr == S_OK, "Failed to set media type, hr %#lx.\n", hr);
5557 hr = IMFTopologyNode_SetUINT32(node, &MF_TOPONODE_PRIMARYOUTPUT, 1);
5558 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
5560 hr = pMFGetTopoNodeCurrentType(node, 0, FALSE, &media_type);
5561 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5562 ok(media_type == media_type2, "Unexpected pointer.\n");
5563 IMFMediaType_Release(media_type);
5565 hr = pMFGetTopoNodeCurrentType(node, 0, TRUE, &media_type);
5566 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5567 ok(media_type == media_type2, "Unexpected pointer.\n");
5568 IMFMediaType_Release(media_type);
5570 IMFTopologyNode_Release(node);
5571 IMFMediaType_Release(media_type2);
5574 static void init_functions(void)
5576 HMODULE mod = GetModuleHandleA("mf.dll");
5578 #define X(f) p##f = (void*)GetProcAddress(mod, #f)
5579 X(MFCreateSampleCopierMFT);
5580 X(MFGetTopoNodeCurrentType);
5581 #undef X
5584 static void test_MFRequireProtectedEnvironment(void)
5586 IMFPresentationDescriptor *pd;
5587 IMFMediaType *mediatype;
5588 IMFStreamDescriptor *sd;
5589 HRESULT hr;
5591 hr = MFCreateMediaType(&mediatype);
5592 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5594 hr = MFCreateStreamDescriptor(0, 1, &mediatype, &sd);
5595 ok(hr == S_OK, "Failed to create stream descriptor, hr %#lx.\n", hr);
5597 hr = MFCreatePresentationDescriptor(1, &sd, &pd);
5598 ok(hr == S_OK, "Failed to create presentation descriptor, hr %#lx.\n", hr);
5600 hr = IMFPresentationDescriptor_SelectStream(pd, 0);
5601 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5603 hr = MFRequireProtectedEnvironment(pd);
5604 ok(hr == S_FALSE, "Unexpected hr %#lx.\n", hr);
5606 hr = IMFStreamDescriptor_SetUINT32(sd, &MF_SD_PROTECTED, 1);
5607 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5609 hr = MFRequireProtectedEnvironment(pd);
5610 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5612 hr = IMFPresentationDescriptor_DeselectStream(pd, 0);
5613 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5615 hr = MFRequireProtectedEnvironment(pd);
5616 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5618 IMFMediaType_Release(mediatype);
5619 IMFStreamDescriptor_Release(sd);
5620 IMFPresentationDescriptor_Release(pd);
5623 static BOOL create_transform(GUID category, MFT_REGISTER_TYPE_INFO *input_type,
5624 MFT_REGISTER_TYPE_INFO *output_type, const WCHAR *expect_name,
5625 const media_type_desc *expect_input, ULONG expect_input_count,
5626 const media_type_desc *expect_output, ULONG expect_output_count,
5627 IMFTransform **transform, GUID *class_id)
5629 MFT_REGISTER_TYPE_INFO *input_types = NULL, *output_types = NULL;
5630 UINT32 input_count = 0, output_count = 0, count = 0, i;
5631 GUID *class_ids = NULL;
5632 WCHAR *name;
5633 HRESULT hr;
5635 hr = MFTEnum(category, 0, input_type, output_type, NULL, &class_ids, &count);
5636 if (FAILED(hr))
5638 todo_wine
5639 win_skip("Failed to enumerate %s, skipping tests.\n", debugstr_w(expect_name));
5640 return FALSE;
5643 ok(hr == S_OK, "MFTEnum returned %lx\n", hr);
5644 ok(count == 1, "got %u\n", count);
5645 *class_id = class_ids[0];
5646 CoTaskMemFree(class_ids);
5648 hr = MFTGetInfo(*class_id, &name, &input_types, &input_count, &output_types, &output_count, NULL);
5649 if (FAILED(hr))
5651 todo_wine
5652 win_skip("Failed to get %s info, skipping tests.\n", debugstr_w(expect_name));
5654 else
5656 ok(hr == S_OK, "MFTEnum returned %lx\n", hr);
5657 ok(!wcscmp(name, expect_name), "got name %s\n", debugstr_w(name));
5658 ok(input_count == expect_input_count, "got input_count %u\n", input_count);
5659 for (i = 0; i < input_count; ++i)
5661 ok(IsEqualGUID(&input_types[i].guidMajorType, expect_input[i][0].value.puuid),
5662 "got input[%u] major %s\n", i, debugstr_guid(&input_types[i].guidMajorType));
5663 ok(IsEqualGUID(&input_types[i].guidSubtype, expect_input[i][1].value.puuid),
5664 "got input[%u] subtype %s\n", i, debugstr_guid(&input_types[i].guidSubtype));
5666 ok(output_count == expect_output_count, "got output_count %u\n", output_count);
5667 for (i = 0; i < output_count; ++i)
5669 ok(IsEqualGUID(&output_types[i].guidMajorType, expect_output[i][0].value.puuid),
5670 "got output[%u] major %s\n", i, debugstr_guid(&output_types[i].guidMajorType));
5671 ok(IsEqualGUID(&output_types[i].guidSubtype, expect_output[i][1].value.puuid),
5672 "got output[%u] subtype %s\n", i, debugstr_guid(&output_types[i].guidSubtype));
5674 CoTaskMemFree(output_types);
5675 CoTaskMemFree(input_types);
5676 CoTaskMemFree(name);
5679 hr = CoCreateInstance(class_id, NULL, CLSCTX_INPROC_SERVER, &IID_IMFTransform, (void **)transform);
5680 if (FAILED(hr))
5682 todo_wine
5683 win_skip("Failed to create %s instance, skipping tests.\n", debugstr_w(expect_name));
5684 return FALSE;
5687 return TRUE;
5690 static IMFSample *create_sample(const BYTE *data, ULONG size)
5692 IMFMediaBuffer *media_buffer;
5693 IMFSample *sample;
5694 DWORD length;
5695 BYTE *buffer;
5696 HRESULT hr;
5697 ULONG ret;
5699 hr = MFCreateSample(&sample);
5700 ok(hr == S_OK, "MFCreateSample returned %#lx\n", hr);
5701 hr = MFCreateMemoryBuffer(size, &media_buffer);
5702 ok(hr == S_OK, "MFCreateMemoryBuffer returned %#lx\n", hr);
5703 hr = IMFMediaBuffer_Lock(media_buffer, &buffer, NULL, &length);
5704 ok(hr == S_OK, "Lock returned %#lx\n", hr);
5705 ok(length == 0, "got length %lu\n", length);
5706 if (!data) memset(buffer, 0xcd, size);
5707 else memcpy(buffer, data, size);
5708 hr = IMFMediaBuffer_Unlock(media_buffer);
5709 ok(hr == S_OK, "Unlock returned %#lx\n", hr);
5710 hr = IMFMediaBuffer_SetCurrentLength(media_buffer, data ? size : 0);
5711 ok(hr == S_OK, "SetCurrentLength returned %#lx\n", hr);
5712 hr = IMFSample_AddBuffer(sample, media_buffer);
5713 ok(hr == S_OK, "AddBuffer returned %#lx\n", hr);
5714 ret = IMFMediaBuffer_Release(media_buffer);
5715 ok(ret == 1, "Release returned %lu\n", ret);
5717 return sample;
5720 #define check_sample(a, b, c, d) check_sample_(__LINE__, a, b, c, d)
5721 static void check_sample_(int line, IMFSample *sample, const void *expect_buf, ULONG expect_len, HANDLE output_file)
5723 IMFMediaBuffer *media_buffer;
5724 DWORD length;
5725 BYTE *buffer;
5726 HRESULT hr;
5727 ULONG ret;
5729 hr = IMFSample_ConvertToContiguousBuffer(sample, &media_buffer);
5730 ok_(__FILE__, line)(hr == S_OK, "ConvertToContiguousBuffer returned %#lx\n", hr);
5731 hr = IMFMediaBuffer_Lock(media_buffer, &buffer, NULL, &length);
5732 ok_(__FILE__, line)(hr == S_OK, "Lock returned %#lx\n", hr);
5733 ok_(__FILE__, line)(expect_len == length, "got length %lu\n", length);
5734 if (length && length == expect_len)
5736 ok_(__FILE__, line)(!memcmp(expect_buf, buffer, expect_len),
5737 "unexpected buffer data\n");
5739 if (output_file) WriteFile(output_file, buffer, length, &length, NULL);
5740 hr = IMFMediaBuffer_Unlock(media_buffer);
5741 ok_(__FILE__, line)(hr == S_OK, "Unlock returned %#lx\n", hr);
5742 ret = IMFMediaBuffer_Release(media_buffer);
5743 ok_(__FILE__, line)(ret == 1, "Release returned %lu\n", ret);
5746 static const BYTE wma_codec_data[10] = {0, 0x44, 0, 0, 0x17, 0, 0, 0, 0, 0};
5747 static const BYTE wma_decoded_data[0x4000] = {0};
5748 static const ULONG wma_block_size = 1487;
5750 static void test_wma_encoder(void)
5752 static const media_type_desc transform_inputs[] =
5755 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
5756 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
5759 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
5760 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_Float),
5763 static const media_type_desc transform_outputs[] =
5766 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
5767 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_WMAudioV8),
5770 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
5771 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_WMAudioV9),
5774 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
5775 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_WMAudio_Lossless),
5779 static const struct attribute_desc input_type_desc[] =
5781 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
5782 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_Float),
5783 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 32),
5784 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
5785 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
5786 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 176400),
5787 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 8),
5788 {0},
5790 const struct attribute_desc output_type_desc[] =
5792 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
5793 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_WMAudioV8),
5794 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
5795 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
5796 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 4003),
5797 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, wma_block_size),
5798 ATTR_BLOB(MF_MT_USER_DATA, wma_codec_data, sizeof(wma_codec_data)),
5799 {0},
5802 MFT_REGISTER_TYPE_INFO output_type = {MFMediaType_Audio, MFAudioFormat_WMAudioV8};
5803 MFT_REGISTER_TYPE_INFO input_type = {MFMediaType_Audio, MFAudioFormat_Float};
5804 MFT_OUTPUT_STREAM_INFO output_info;
5805 MFT_INPUT_STREAM_INFO input_info;
5806 MFT_OUTPUT_DATA_BUFFER output;
5807 const BYTE *wma_encoded_data;
5808 WCHAR output_path[MAX_PATH];
5809 ULONG wma_encoded_data_len;
5810 IMFMediaType *media_type;
5811 IMFTransform *transform;
5812 HANDLE output_file;
5813 IMFSample *sample;
5814 HRSRC resource;
5815 GUID class_id;
5816 DWORD status;
5817 ULONG i, ret;
5818 HRESULT hr;
5820 hr = CoInitialize(NULL);
5821 ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
5823 if (!create_transform(MFT_CATEGORY_AUDIO_ENCODER, &input_type, &output_type, L"WMAudio Encoder MFT",
5824 transform_inputs, ARRAY_SIZE(transform_inputs), transform_outputs, ARRAY_SIZE(transform_outputs),
5825 &transform, &class_id))
5826 goto failed;
5828 check_interface(transform, &IID_IMediaObject, TRUE);
5830 hr = MFCreateMediaType(&media_type);
5831 ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr);
5832 init_media_type(media_type, input_type_desc, -1);
5833 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
5834 ok(hr == S_OK, "SetInputType returned %#lx.\n", hr);
5835 init_media_type(media_type, output_type_desc, -1);
5836 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
5837 ok(hr == S_OK, "SetOutputType returned %#lx.\n", hr);
5838 ret = IMFMediaType_Release(media_type);
5839 ok(ret == 0, "Release returned %lu\n", ret);
5841 memset(&input_info, 0xcd, sizeof(input_info));
5842 hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info);
5843 ok(hr == S_OK, "GetInputStreamInfo returned %#lx\n", hr);
5844 ok(input_info.hnsMaxLatency == 19969161, "got hnsMaxLatency %s\n",
5845 wine_dbgstr_longlong(input_info.hnsMaxLatency));
5846 ok(input_info.dwFlags == 0, "got dwFlags %#lx\n", input_info.dwFlags);
5847 ok(input_info.cbSize == 8, "got cbSize %lu\n", input_info.cbSize);
5848 ok(input_info.cbMaxLookahead == 0, "got cbMaxLookahead %#lx\n", input_info.cbMaxLookahead);
5849 ok(input_info.cbAlignment == 1, "got cbAlignment %#lx\n", input_info.cbAlignment);
5851 memset(&output_info, 0xcd, sizeof(output_info));
5852 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
5853 ok(hr == S_OK, "GetOutputStreamInfo returned %#lx\n", hr);
5854 ok(output_info.dwFlags == 0, "got dwFlags %#lx\n", output_info.dwFlags);
5855 ok(output_info.cbSize == wma_block_size, "got cbSize %#lx\n", output_info.cbSize);
5856 ok(output_info.cbAlignment == 1, "got cbAlignment %#lx\n", output_info.cbAlignment);
5858 i = 0;
5859 sample = create_sample(wma_decoded_data, sizeof(wma_decoded_data));
5860 while (SUCCEEDED(hr = IMFTransform_ProcessInput(transform, 0, sample, 0)))
5862 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
5863 i += sizeof(wma_decoded_data);
5865 ok(hr == MF_E_NOTACCEPTING, "ProcessInput returned %#lx\n", hr);
5866 ok(i == 0x204000, "ProcessInput consumed %#lx bytes\n", i);
5868 hr = IMFTransform_ProcessMessage(transform, MFT_MESSAGE_COMMAND_DRAIN, 0);
5869 ok(hr == S_OK, "ProcessMessage returned %#lx\n", hr);
5870 hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
5871 ok(hr == MF_E_NOTACCEPTING, "ProcessInput returned %#lx\n", hr);
5873 status = 0xdeadbeef;
5874 sample = create_sample(NULL, output_info.cbSize);
5875 memset(&output, 0, sizeof(output));
5876 output.pSample = sample;
5878 /* check wmadata.bin against current encoder output */
5879 resource = FindResourceW(NULL, L"wmadata.bin", (const WCHAR *)RT_RCDATA);
5880 ok(resource != 0, "FindResourceW failed, error %lu\n", GetLastError());
5881 wma_encoded_data = LockResource(LoadResource(GetModuleHandleW(NULL), resource));
5882 wma_encoded_data_len = SizeofResource(GetModuleHandleW(NULL), resource);
5883 ok(wma_encoded_data_len % wma_block_size == 0, "got wma encoded length %lu\n", wma_encoded_data_len);
5885 /* and generate a new one as well in a temporary directory */
5886 GetTempPathW(ARRAY_SIZE(output_path), output_path);
5887 lstrcatW(output_path, L"wmadata.bin");
5888 output_file = CreateFileW(output_path, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
5889 ok(output_file != INVALID_HANDLE_VALUE, "CreateFileW failed, error %lu\n", GetLastError());
5891 i = 0;
5892 while (SUCCEEDED(hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status)))
5894 winetest_push_context("%lu", i);
5895 ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr);
5896 ok(output.pSample == sample, "got pSample %p\n", output.pSample);
5897 ok(output.dwStatus == MFT_OUTPUT_DATA_BUFFER_INCOMPLETE ||
5898 broken(output.dwStatus == (MFT_OUTPUT_DATA_BUFFER_INCOMPLETE|5)) /* win7 */,
5899 "got dwStatus %#lx\n", output.dwStatus);
5900 ok(status == 0, "got status %#lx\n", status);
5901 ok(wma_encoded_data_len > i * wma_block_size, "got %lu blocks\n", i);
5902 check_sample(sample, wma_encoded_data + i * wma_block_size, wma_block_size, output_file);
5903 winetest_pop_context();
5904 i++;
5907 trace("created %s\n", debugstr_w(output_path));
5908 CloseHandle(output_file);
5910 ret = IMFSample_Release(sample);
5911 ok(ret == 0, "Release returned %lu\n", ret);
5913 status = 0xdeadbeef;
5914 sample = create_sample(NULL, output_info.cbSize);
5915 memset(&output, 0, sizeof(output));
5916 output.pSample = sample;
5917 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
5918 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
5919 ok(output.pSample == sample, "got pSample %p\n", output.pSample);
5920 ok(output.dwStatus == 0, "got dwStatus %#lx\n", output.dwStatus);
5921 ok(status == 0, "got status %#lx\n", status);
5922 check_sample(sample, NULL, 0, NULL);
5923 ret = IMFSample_Release(sample);
5924 ok(ret == 0, "Release returned %lu\n", ret);
5926 ret = IMFTransform_Release(transform);
5927 ok(ret == 0, "Release returned %lu\n", ret);
5929 failed:
5930 CoUninitialize();
5933 static void test_wma_decoder(void)
5935 static const media_type_desc transform_inputs[] =
5938 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
5939 ATTR_GUID(MF_MT_SUBTYPE, MEDIASUBTYPE_MSAUDIO1),
5942 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
5943 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_WMAudioV8),
5946 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
5947 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_WMAudioV9),
5950 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
5951 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_WMAudio_Lossless),
5954 static const media_type_desc transform_outputs[] =
5957 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
5958 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
5961 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
5962 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_Float),
5966 static const media_type_desc expect_available_inputs[] =
5969 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
5970 ATTR_GUID(MF_MT_SUBTYPE, MEDIASUBTYPE_MSAUDIO1),
5971 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
5974 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
5975 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_WMAudioV8),
5976 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
5979 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
5980 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_WMAudioV9),
5981 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
5984 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
5985 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_WMAudio_Lossless),
5986 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
5989 static const media_type_desc expect_available_outputs[] =
5992 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
5993 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_Float),
5994 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 32),
5995 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
5996 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
5997 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 176400),
5998 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 8),
5999 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
6000 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
6001 ATTR_UINT32(MF_MT_AUDIO_PREFER_WAVEFORMATEX, 1),
6004 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
6005 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
6006 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16),
6007 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
6008 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
6009 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 88200),
6010 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 4),
6011 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
6012 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
6013 ATTR_UINT32(MF_MT_AUDIO_PREFER_WAVEFORMATEX, 1),
6017 const struct attribute_desc input_type_desc[] =
6019 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
6020 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_WMAudioV8),
6021 ATTR_BLOB(MF_MT_USER_DATA, wma_codec_data, sizeof(wma_codec_data)),
6022 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, wma_block_size),
6023 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
6024 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
6025 {0},
6027 static const struct attribute_desc output_type_desc[] =
6029 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
6030 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_Float),
6031 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 176400),
6032 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 32),
6033 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
6034 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
6035 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 8),
6036 {0},
6039 MFT_REGISTER_TYPE_INFO input_type = {MFMediaType_Audio, MFAudioFormat_WMAudioV8};
6040 MFT_REGISTER_TYPE_INFO output_type = {MFMediaType_Audio, MFAudioFormat_Float};
6041 MFT_OUTPUT_STREAM_INFO output_info;
6042 MFT_OUTPUT_DATA_BUFFER outputs[2];
6043 MFT_INPUT_STREAM_INFO input_info;
6044 MFT_OUTPUT_DATA_BUFFER output;
6045 const BYTE *wma_encoded_data;
6046 ULONG wma_encoded_data_len;
6047 IMFMediaType *media_type;
6048 IMFTransform *transform;
6049 IMFSample *sample;
6050 HRSRC resource;
6051 GUID class_id;
6052 DWORD status;
6053 ULONG i, ret;
6054 HRESULT hr;
6056 hr = CoInitialize(NULL);
6057 ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
6059 if (!create_transform(MFT_CATEGORY_AUDIO_DECODER, &input_type, &output_type, L"WMAudio Decoder MFT",
6060 transform_inputs, ARRAY_SIZE(transform_inputs), transform_outputs, ARRAY_SIZE(transform_outputs),
6061 &transform, &class_id))
6062 goto failed;
6064 check_interface(transform, &IID_IMediaObject, TRUE);
6066 /* check default media types */
6068 hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info);
6069 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetInputStreamInfo returned %#lx\n", hr);
6070 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
6071 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetOutputStreamInfo returned %#lx\n", hr);
6072 hr = IMFTransform_GetOutputAvailableType(transform, 0, 0, &media_type);
6073 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetOutputAvailableType returned %#lx\n", hr);
6075 i = -1;
6076 while (SUCCEEDED(hr = IMFTransform_GetInputAvailableType(transform, 0, ++i, &media_type)))
6078 winetest_push_context("in %lu", i);
6079 ok(hr == S_OK, "GetInputAvailableType returned %#lx\n", hr);
6080 check_media_type(media_type, expect_available_inputs[i], -1);
6081 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
6082 ok(hr == MF_E_INVALIDMEDIATYPE, "SetInputType returned %#lx.\n", hr);
6083 ret = IMFMediaType_Release(media_type);
6084 ok(ret == 0, "Release returned %lu\n", ret);
6085 winetest_pop_context();
6087 todo_wine
6088 ok(hr == MF_E_NO_MORE_TYPES, "GetInputAvailableType returned %#lx\n", hr);
6089 todo_wine
6090 ok(i == 4, "%lu input media types\n", i);
6092 /* setting output media type first doesn't work */
6094 hr = MFCreateMediaType(&media_type);
6095 ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr);
6096 init_media_type(media_type, output_type_desc, -1);
6097 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
6098 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "SetOutputType returned %#lx.\n", hr);
6099 ret = IMFMediaType_Release(media_type);
6100 ok(ret == 0, "Release returned %lu\n", ret);
6102 /* check required input media type attributes */
6104 hr = MFCreateMediaType(&media_type);
6105 ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr);
6106 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
6107 ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetInputType returned %#lx.\n", hr);
6108 init_media_type(media_type, input_type_desc, 1);
6109 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
6110 ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetInputType returned %#lx.\n", hr);
6111 init_media_type(media_type, input_type_desc, 2);
6112 for (i = 2; i < ARRAY_SIZE(input_type_desc) - 1; ++i)
6114 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
6115 ok(hr == MF_E_INVALIDMEDIATYPE, "SetInputType returned %#lx.\n", hr);
6116 init_media_type(media_type, input_type_desc, i + 1);
6118 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
6119 ok(hr == S_OK, "SetInputType returned %#lx.\n", hr);
6120 ret = IMFMediaType_Release(media_type);
6121 ok(ret == 0, "Release returned %lu\n", ret);
6123 hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info);
6124 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetInputStreamInfo returned %#lx\n", hr);
6125 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
6126 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetOutputStreamInfo returned %#lx\n", hr);
6128 /* check new output media types */
6130 i = -1;
6131 while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, ++i, &media_type)))
6133 winetest_push_context("out %lu", i);
6134 ok(hr == S_OK, "GetOutputAvailableType returned %#lx\n", hr);
6135 check_media_type(media_type, expect_available_outputs[i], -1);
6136 ret = IMFMediaType_Release(media_type);
6137 ok(ret == 0, "Release returned %lu\n", ret);
6138 winetest_pop_context();
6140 ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
6141 ok(i == 2, "%lu output media types\n", i);
6143 /* check required output media type attributes */
6145 hr = MFCreateMediaType(&media_type);
6146 ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr);
6147 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
6148 ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetOutputType returned %#lx.\n", hr);
6149 init_media_type(media_type, output_type_desc, 1);
6150 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
6151 ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetOutputType returned %#lx.\n", hr);
6152 init_media_type(media_type, output_type_desc, 2);
6153 for (i = 2; i < ARRAY_SIZE(output_type_desc) - 1; ++i)
6155 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
6156 ok(hr == MF_E_INVALIDMEDIATYPE, "SetOutputType returned %#lx.\n", hr);
6157 init_media_type(media_type, output_type_desc, i + 1);
6159 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
6160 ok(hr == S_OK, "SetOutputType returned %#lx.\n", hr);
6161 ret = IMFMediaType_Release(media_type);
6162 ok(ret == 0, "Release returned %lu\n", ret);
6164 memset(&input_info, 0xcd, sizeof(input_info));
6165 hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info);
6166 ok(hr == S_OK, "GetInputStreamInfo returned %#lx\n", hr);
6167 ok(input_info.hnsMaxLatency == 0, "got hnsMaxLatency %s\n", wine_dbgstr_longlong(input_info.hnsMaxLatency));
6168 ok(input_info.dwFlags == 0, "got dwFlags %#lx\n", input_info.dwFlags);
6169 ok(input_info.cbSize == wma_block_size, "got cbSize %lu\n", input_info.cbSize);
6170 ok(input_info.cbMaxLookahead == 0, "got cbMaxLookahead %#lx\n", input_info.cbMaxLookahead);
6171 ok(input_info.cbAlignment == 1, "got cbAlignment %#lx\n", input_info.cbAlignment);
6173 memset(&output_info, 0xcd, sizeof(output_info));
6174 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
6175 ok(hr == S_OK, "GetOutputStreamInfo returned %#lx\n", hr);
6176 ok(output_info.dwFlags == 0, "got dwFlags %#lx\n", output_info.dwFlags);
6177 todo_wine
6178 ok(output_info.cbSize == 0, "got cbSize %#lx\n", output_info.cbSize);
6179 ok(output_info.cbAlignment == 1, "got cbAlignment %#lx\n", output_info.cbAlignment);
6181 /* MF_MT_AUDIO_AVG_BYTES_PER_SECOND isn't required by SetInputType, but is needed for the transform to work */
6183 hr = MFCreateMediaType(&media_type);
6184 ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr);
6185 init_media_type(media_type, input_type_desc, -1);
6186 hr = IMFMediaType_SetUINT32(media_type, &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 4003);
6187 ok(hr == S_OK, "SetUINT32 returned %#lx\n", hr);
6188 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
6189 ok(hr == S_OK, "SetInputType returned %#lx.\n", hr);
6191 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
6192 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetOutputStreamInfo returned %#lx\n", hr);
6194 init_media_type(media_type, output_type_desc, -1);
6195 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
6196 ok(hr == S_OK, "SetInputType returned %#lx.\n", hr);
6197 ret = IMFMediaType_Release(media_type);
6198 ok(ret == 0, "Release returned %lu\n", ret);
6200 memset(&output_info, 0xcd, sizeof(output_info));
6201 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
6202 ok(hr == S_OK, "GetOutputStreamInfo returned %#lx\n", hr);
6203 ok(output_info.dwFlags == 0, "got dwFlags %#lx\n", output_info.dwFlags);
6204 ok(output_info.cbSize == sizeof(wma_decoded_data), "got cbSize %#lx\n", output_info.cbSize);
6205 ok(output_info.cbAlignment == 1, "got cbAlignment %#lx\n", output_info.cbAlignment);
6207 /* resource is generated using test_wma_encoder output file */
6208 resource = FindResourceW(NULL, L"wmadata.bin", (const WCHAR *)RT_RCDATA);
6209 ok(resource != 0, "FindResourceW failed, error %lu\n", GetLastError());
6210 wma_encoded_data = LockResource(LoadResource(GetModuleHandleW(NULL), resource));
6211 wma_encoded_data_len = SizeofResource(GetModuleHandleW(NULL), resource);
6212 ok(wma_encoded_data_len % wma_block_size == 0, "got wma encoded length %lu\n", wma_encoded_data_len);
6214 sample = create_sample(wma_encoded_data, wma_block_size / 2);
6215 hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
6216 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
6217 ret = IMFSample_Release(sample);
6218 ok(ret == 0, "Release returned %lu\n", ret);
6219 sample = create_sample(wma_encoded_data, wma_block_size + 1);
6220 hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
6221 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
6222 ret = IMFSample_Release(sample);
6223 ok(ret == 0, "Release returned %lu\n", ret);
6224 sample = create_sample(wma_encoded_data, wma_block_size);
6225 hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
6226 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
6227 hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
6228 ok(hr == MF_E_NOTACCEPTING, "ProcessInput returned %#lx\n", hr);
6229 ret = IMFSample_Release(sample);
6230 todo_wine
6231 ok(ret == 1, "Release returned %lu\n", ret);
6233 /* As output_info.dwFlags doesn't have MFT_OUTPUT_STREAM_CAN_PROVIDE_SAMPLES
6234 * IMFTransform_ProcessOutput needs a sample or returns MF_E_TRANSFORM_NEED_MORE_INPUT */
6236 status = 0xdeadbeef;
6237 memset(&output, 0, sizeof(output));
6238 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
6239 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
6240 ok(output.dwStreamID == 0, "got dwStreamID %lu\n", output.dwStreamID);
6241 ok(!output.pSample, "got pSample %p\n", output.pSample);
6242 ok(output.dwStatus == MFT_OUTPUT_DATA_BUFFER_NO_SAMPLE ||
6243 broken(output.dwStatus == (MFT_OUTPUT_DATA_BUFFER_INCOMPLETE|MFT_OUTPUT_DATA_BUFFER_NO_SAMPLE)) /* Win7 */,
6244 "got dwStatus %#lx\n", output.dwStatus);
6245 ok(!output.pEvents, "got pEvents %p\n", output.pEvents);
6246 ok(status == 0, "got status %#lx\n", status);
6248 sample = create_sample(wma_encoded_data, wma_block_size);
6249 hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
6250 ok(hr == MF_E_NOTACCEPTING, "ProcessInput returned %#lx\n", hr);
6251 ret = IMFSample_Release(sample);
6252 ok(ret == 0, "Release returned %lu\n", ret);
6254 status = 0xdeadbeef;
6255 memset(&output, 0, sizeof(output));
6256 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
6257 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
6258 ok(!output.pSample, "got pSample %p\n", output.pSample);
6259 ok(output.dwStatus == MFT_OUTPUT_DATA_BUFFER_NO_SAMPLE ||
6260 broken(output.dwStatus == (MFT_OUTPUT_DATA_BUFFER_INCOMPLETE|MFT_OUTPUT_DATA_BUFFER_NO_SAMPLE)) /* Win7 */,
6261 "got dwStatus %#lx\n", output.dwStatus);
6262 ok(status == 0, "got status %#lx\n", status);
6264 status = 0xdeadbeef;
6265 memset(&output, 0, sizeof(output));
6266 output_info.cbSize = sizeof(wma_decoded_data);
6267 sample = create_sample(NULL, output_info.cbSize);
6268 outputs[0].pSample = sample;
6269 sample = create_sample(NULL, output_info.cbSize);
6270 outputs[1].pSample = sample;
6271 hr = IMFTransform_ProcessOutput(transform, 0, 2, outputs, &status);
6272 ok(hr == E_INVALIDARG, "ProcessOutput returned %#lx\n", hr);
6273 IMFSample_Release(outputs[0].pSample);
6274 IMFSample_Release(outputs[1].pSample);
6276 status = 0xdeadbeef;
6277 output_info.cbSize = sizeof(wma_decoded_data);
6278 sample = create_sample(NULL, output_info.cbSize);
6279 memset(&output, 0, sizeof(output));
6280 output.pSample = sample;
6281 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
6282 ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr);
6283 ok(output.pSample == sample, "got pSample %p\n", output.pSample);
6285 i = 0;
6286 while (hr == S_OK)
6288 ok(output.pSample == sample, "got pSample %p\n", output.pSample);
6289 ok(output.dwStatus == MFT_OUTPUT_DATA_BUFFER_INCOMPLETE || output.dwStatus == 0 ||
6290 broken(output.dwStatus == (MFT_OUTPUT_DATA_BUFFER_INCOMPLETE|7) || output.dwStatus == 7) /* Win7 */,
6291 "got dwStatus %#lx\n", output.dwStatus);
6292 ok(status == 0, "got status %#lx\n", status);
6293 if (output.dwStatus == MFT_OUTPUT_DATA_BUFFER_INCOMPLETE ||
6294 broken(output.dwStatus == (MFT_OUTPUT_DATA_BUFFER_INCOMPLETE|7)))
6296 check_sample(sample, wma_decoded_data, sizeof(wma_decoded_data), NULL);
6297 i += sizeof(wma_decoded_data);
6299 else
6301 DWORD length;
6303 /* FFmpeg doesn't seem to decode WMA buffers in the same way as native */
6305 hr = IMFSample_GetTotalLength(sample, &length);
6306 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
6307 todo_wine
6308 ok(length == sizeof(wma_decoded_data) / 2, "got length %lu\n", length);
6310 if (length == sizeof(wma_decoded_data) / 2)
6312 check_sample(sample, wma_decoded_data, sizeof(wma_decoded_data) / 2, NULL);
6313 i += sizeof(wma_decoded_data) / 2;
6316 ret = IMFSample_Release(sample);
6317 ok(ret == 0, "Release returned %lu\n", ret);
6319 status = 0xdeadbeef;
6320 sample = create_sample(NULL, output_info.cbSize);
6321 memset(&output, 0, sizeof(output));
6322 output.pSample = sample;
6323 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
6325 todo_wine
6326 ok(i == 0xe000, "ProcessOutput produced %#lx bytes\n", i);
6328 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
6329 ok(output.pSample == sample, "got pSample %p\n", output.pSample);
6330 ok(output.dwStatus == 0, "got dwStatus %#lx\n", output.dwStatus);
6331 ok(status == 0, "got status %#lx\n", status);
6332 ret = IMFSample_Release(sample);
6333 ok(ret == 0, "Release returned %lu\n", ret);
6335 status = 0xdeadbeef;
6336 sample = create_sample(NULL, output_info.cbSize);
6337 memset(&output, 0, sizeof(output));
6338 output.pSample = sample;
6339 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
6340 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
6341 ok(output.pSample == sample, "got pSample %p\n", output.pSample);
6342 ok(output.dwStatus == 0 ||
6343 broken(output.dwStatus == (MFT_OUTPUT_DATA_BUFFER_INCOMPLETE|7)) /* Win7 */,
6344 "got dwStatus %#lx\n", output.dwStatus);
6345 ok(status == 0, "got status %#lx\n", status);
6346 check_sample(sample, NULL, 0, NULL);
6347 ret = IMFSample_Release(sample);
6348 ok(ret == 0, "Release returned %lu\n", ret);
6350 sample = create_sample(wma_encoded_data, wma_block_size);
6351 hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
6352 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
6354 ret = IMFTransform_Release(transform);
6355 ok(ret == 0, "Release returned %lu\n", ret);
6356 ret = IMFSample_Release(sample);
6357 ok(ret == 0, "Release returned %lu\n", ret);
6359 failed:
6360 CoUninitialize();
6363 #define next_h264_sample(a, b) next_h264_sample_(__LINE__, a, b)
6364 static IMFSample *next_h264_sample_(int line, const BYTE **h264_buf, ULONG *h264_len)
6366 const BYTE *sample_data;
6368 ok_(__FILE__, line)(*h264_len > 4, "invalid h264 length\n");
6369 ok_(__FILE__, line)(*(UINT32 *)*h264_buf == 0x01000000, "invalid h264 buffer\n");
6370 sample_data = *h264_buf;
6372 (*h264_len) -= 4;
6373 (*h264_buf) += 4;
6375 while (*h264_len >= 4 && *(UINT32 *)*h264_buf != 0x01000000)
6377 (*h264_len)--;
6378 (*h264_buf)++;
6381 return create_sample(sample_data, *h264_buf - sample_data);
6384 static void test_h264_decoder(void)
6386 static const media_type_desc transform_inputs[] =
6389 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
6390 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_H264),
6393 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
6394 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_H264_ES),
6397 static const media_type_desc transform_outputs[] =
6400 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
6401 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12),
6404 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
6405 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YV12),
6408 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
6409 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_IYUV),
6412 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
6413 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_I420),
6416 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
6417 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YUY2),
6420 static const media_type_desc default_outputs[] =
6423 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
6424 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12),
6425 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
6426 ATTR_RATIO(MF_MT_FRAME_RATE, 30000, 1001),
6427 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, 1920),
6428 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
6429 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
6430 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
6433 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
6434 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YV12),
6435 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
6436 ATTR_RATIO(MF_MT_FRAME_RATE, 30000, 1001),
6437 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, 1920),
6438 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
6439 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
6440 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
6443 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
6444 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_IYUV),
6445 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
6446 ATTR_RATIO(MF_MT_FRAME_RATE, 30000, 1001),
6447 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, 1920),
6448 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
6449 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
6450 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
6453 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
6454 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_I420),
6455 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
6456 ATTR_RATIO(MF_MT_FRAME_RATE, 30000, 1001),
6457 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, 1920),
6458 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
6459 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
6460 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
6463 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
6464 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YUY2),
6465 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
6466 ATTR_RATIO(MF_MT_FRAME_RATE, 30000, 1001),
6467 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, 3840),
6468 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
6469 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
6470 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
6473 static const media_type_desc default_outputs_extra[] =
6476 ATTR_RATIO(MF_MT_FRAME_SIZE, 1920, 1080),
6477 ATTR_UINT32(MF_MT_SAMPLE_SIZE, 3110400),
6478 ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0),
6481 ATTR_RATIO(MF_MT_FRAME_SIZE, 1920, 1080),
6482 ATTR_UINT32(MF_MT_SAMPLE_SIZE, 3110400),
6483 ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0),
6486 ATTR_RATIO(MF_MT_FRAME_SIZE, 1920, 1080),
6487 ATTR_UINT32(MF_MT_SAMPLE_SIZE, 3110400),
6488 ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0),
6491 ATTR_RATIO(MF_MT_FRAME_SIZE, 1920, 1080),
6492 ATTR_UINT32(MF_MT_SAMPLE_SIZE, 3110400),
6493 ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0),
6496 ATTR_RATIO(MF_MT_FRAME_SIZE, 1920, 1080),
6497 ATTR_UINT32(MF_MT_SAMPLE_SIZE, 4147200),
6498 ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0),
6501 static const media_type_desc default_outputs_win7[] =
6504 ATTR_RATIO(MF_MT_FRAME_SIZE, 1920, 1088),
6505 ATTR_UINT32(MF_MT_SAMPLE_SIZE, 3133440),
6508 ATTR_RATIO(MF_MT_FRAME_SIZE, 1920, 1088),
6509 ATTR_UINT32(MF_MT_SAMPLE_SIZE, 3133440),
6512 ATTR_RATIO(MF_MT_FRAME_SIZE, 1920, 1088),
6513 ATTR_UINT32(MF_MT_SAMPLE_SIZE, 3133440),
6516 ATTR_RATIO(MF_MT_FRAME_SIZE, 1920, 1088),
6517 ATTR_UINT32(MF_MT_SAMPLE_SIZE, 3133440),
6520 ATTR_RATIO(MF_MT_FRAME_SIZE, 1920, 1088),
6521 ATTR_UINT32(MF_MT_SAMPLE_SIZE, 4177920),
6524 static const struct attribute_desc input_type_desc[] =
6526 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
6527 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_H264),
6528 {0},
6530 static const struct attribute_desc output_type_desc[] =
6532 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
6533 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12),
6534 ATTR_RATIO(MF_MT_FRAME_SIZE, 1920, 1080),
6535 {0},
6537 static const struct attribute_desc output_type_desc_win7[] =
6539 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
6540 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12),
6541 ATTR_RATIO(MF_MT_FRAME_SIZE, 1920, 1088),
6542 {0},
6544 static const MFVideoArea actual_aperture = {.Area={82,84}};
6545 static const DWORD actual_width = 96, actual_height = 96;
6546 const media_type_desc actual_outputs[] =
6549 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
6550 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12),
6551 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
6552 ATTR_RATIO(MF_MT_FRAME_RATE, 30000, 1001),
6553 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height, .todo_value = TRUE),
6554 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 3 / 2, .todo_value = TRUE),
6555 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width, .todo_value = TRUE),
6556 /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
6557 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
6558 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
6559 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
6560 ATTR_BLOB(MF_MT_MINIMUM_DISPLAY_APERTURE, &actual_aperture, 16, .todo = TRUE),
6563 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
6564 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YV12),
6565 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
6566 ATTR_RATIO(MF_MT_FRAME_RATE, 30000, 1001),
6567 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height, .todo_value = TRUE),
6568 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 3 / 2, .todo_value = TRUE),
6569 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width, .todo_value = TRUE),
6570 /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
6571 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
6572 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
6573 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
6574 ATTR_BLOB(MF_MT_MINIMUM_DISPLAY_APERTURE, &actual_aperture, 16, .todo = TRUE),
6577 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
6578 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_IYUV),
6579 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
6580 ATTR_RATIO(MF_MT_FRAME_RATE, 30000, 1001),
6581 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height, .todo_value = TRUE),
6582 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 3 / 2, .todo_value = TRUE),
6583 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width, .todo_value = TRUE),
6584 /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
6585 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
6586 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
6587 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
6588 ATTR_BLOB(MF_MT_MINIMUM_DISPLAY_APERTURE, &actual_aperture, 16, .todo = TRUE),
6591 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
6592 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_I420),
6593 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
6594 ATTR_RATIO(MF_MT_FRAME_RATE, 30000, 1001),
6595 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height, .todo_value = TRUE),
6596 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 3 / 2, .todo_value = TRUE),
6597 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width, .todo_value = TRUE),
6598 /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
6599 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
6600 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
6601 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
6602 ATTR_BLOB(MF_MT_MINIMUM_DISPLAY_APERTURE, &actual_aperture, 16, .todo = TRUE),
6605 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
6606 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YUY2),
6607 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
6608 ATTR_RATIO(MF_MT_FRAME_RATE, 30000, 1001),
6609 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height, .todo_value = TRUE),
6610 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 2, .todo_value = TRUE),
6611 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width * 2, .todo_value = TRUE),
6612 /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
6613 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
6614 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
6615 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
6616 ATTR_BLOB(MF_MT_MINIMUM_DISPLAY_APERTURE, &actual_aperture, 16, .todo = TRUE),
6620 MFT_REGISTER_TYPE_INFO input_type = {MFMediaType_Video, MFVideoFormat_H264};
6621 MFT_REGISTER_TYPE_INFO output_type = {MFMediaType_Video, MFVideoFormat_NV12};
6622 DWORD input_id, output_id, input_count, output_count;
6623 const BYTE *h264_encoded_data, *nv12_frame_data;
6624 ULONG h264_encoded_data_len, nv12_frame_len;
6625 MFT_OUTPUT_STREAM_INFO output_info;
6626 MFT_INPUT_STREAM_INFO input_info;
6627 MFT_OUTPUT_DATA_BUFFER output;
6628 IMFMediaBuffer *media_buffer;
6629 WCHAR output_path[MAX_PATH];
6630 IMFAttributes *attributes;
6631 IMFMediaType *media_type;
6632 IMFTransform *transform;
6633 DWORD status, length;
6634 ULONG i, ret, flags;
6635 HANDLE output_file;
6636 IMFSample *sample;
6637 HRSRC resource;
6638 GUID class_id;
6639 BYTE *data;
6640 HRESULT hr;
6642 hr = CoInitialize(NULL);
6643 ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
6645 if (!create_transform(MFT_CATEGORY_VIDEO_DECODER, &input_type, &output_type, L"Microsoft H264 Video Decoder MFT",
6646 transform_inputs, ARRAY_SIZE(transform_inputs), transform_outputs, ARRAY_SIZE(transform_outputs),
6647 &transform, &class_id))
6648 goto failed;
6650 hr = IMFTransform_GetAttributes(transform, &attributes);
6651 ok(hr == S_OK, "GetAttributes returned %#lx\n", hr);
6652 hr = IMFAttributes_SetUINT32(attributes, &MF_LOW_LATENCY, 1);
6653 ok(hr == S_OK, "SetUINT32 returned %#lx\n", hr);
6654 IMFAttributes_Release(attributes);
6656 /* no output type is available before an input type is set */
6658 hr = IMFTransform_GetOutputAvailableType(transform, 0, 0, &media_type);
6659 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetOutputAvailableType returned %#lx\n", hr);
6661 /* setting output media type first doesn't work */
6663 hr = MFCreateMediaType(&media_type);
6664 ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr);
6665 init_media_type(media_type, default_outputs[0], -1);
6666 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
6667 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "SetOutputType returned %#lx.\n", hr);
6668 ret = IMFMediaType_Release(media_type);
6669 ok(ret == 0, "Release returned %lu\n", ret);
6671 /* check available input types */
6673 flags = MFT_INPUT_STREAM_WHOLE_SAMPLES | MFT_INPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER | MFT_INPUT_STREAM_FIXED_SAMPLE_SIZE;
6674 memset(&input_info, 0xcd, sizeof(input_info));
6675 hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info);
6676 todo_wine
6677 ok(hr == S_OK, "GetInputStreamInfo returned %#lx\n", hr);
6678 todo_wine
6679 ok(input_info.hnsMaxLatency == 0, "got hnsMaxLatency %s\n", wine_dbgstr_longlong(input_info.hnsMaxLatency));
6680 todo_wine
6681 ok(input_info.dwFlags == flags, "got dwFlags %#lx\n", input_info.dwFlags);
6682 todo_wine
6683 ok(input_info.cbSize == 0x1000, "got cbSize %lu\n", input_info.cbSize);
6684 todo_wine
6685 ok(input_info.cbMaxLookahead == 0, "got cbMaxLookahead %#lx\n", input_info.cbMaxLookahead);
6686 todo_wine
6687 ok(input_info.cbAlignment == 0, "got cbAlignment %#lx\n", input_info.cbAlignment);
6689 flags = MFT_OUTPUT_STREAM_WHOLE_SAMPLES | MFT_OUTPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER | MFT_OUTPUT_STREAM_FIXED_SAMPLE_SIZE;
6690 memset(&output_info, 0xcd, sizeof(output_info));
6691 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
6692 ok(hr == S_OK, "GetOutputStreamInfo returned %#lx\n", hr);
6693 ok(output_info.dwFlags == flags, "got dwFlags %#lx\n", output_info.dwFlags);
6694 ok(output_info.cbSize == 1920 * 1088 * 2, "got cbSize %#lx\n", output_info.cbSize);
6695 ok(output_info.cbAlignment == 0, "got cbAlignment %#lx\n", output_info.cbAlignment);
6697 i = -1;
6698 while (SUCCEEDED(hr = IMFTransform_GetInputAvailableType(transform, 0, ++i, &media_type)))
6700 winetest_push_context("in %lu", i);
6701 ok(hr == S_OK, "GetInputAvailableType returned %#lx\n", hr);
6702 check_media_type(media_type, transform_inputs[i], -1);
6703 ret = IMFMediaType_Release(media_type);
6704 ok(ret == 0, "Release returned %lu\n", ret);
6705 winetest_pop_context();
6707 ok(hr == MF_E_NO_MORE_TYPES, "GetInputAvailableType returned %#lx\n", hr);
6708 ok(i == 2 || broken(i == 1) /* Win7 */, "%lu input media types\n", i);
6710 /* check required input media type attributes */
6712 hr = MFCreateMediaType(&media_type);
6713 ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr);
6714 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
6715 ok(hr == E_INVALIDARG, "SetInputType returned %#lx.\n", hr);
6716 init_media_type(media_type, input_type_desc, 1);
6717 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
6718 todo_wine
6719 ok(hr == MF_E_INVALIDMEDIATYPE, "SetInputType returned %#lx.\n", hr);
6720 init_media_type(media_type, input_type_desc, 2);
6721 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
6722 ok(hr == S_OK, "SetInputType returned %#lx.\n", hr);
6723 ret = IMFMediaType_Release(media_type);
6724 ok(ret == 1, "Release returned %lu\n", ret);
6726 flags = MFT_OUTPUT_STREAM_WHOLE_SAMPLES | MFT_OUTPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER | MFT_OUTPUT_STREAM_FIXED_SAMPLE_SIZE;
6727 memset(&output_info, 0xcd, sizeof(output_info));
6728 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
6729 ok(hr == S_OK, "GetOutputStreamInfo returned %#lx\n", hr);
6730 ok(output_info.dwFlags == flags, "got dwFlags %#lx\n", output_info.dwFlags);
6731 todo_wine
6732 ok(output_info.cbSize == 1920 * 1080 * 2 || broken(output_info.cbSize == 1920 * 1088 * 2) /* Win7 */,
6733 "got cbSize %#lx\n", output_info.cbSize);
6734 ok(output_info.cbAlignment == 0, "got cbAlignment %#lx\n", output_info.cbAlignment);
6736 /* output types can now be enumerated (though they are actually the same for all input types) */
6738 i = -1;
6739 while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, ++i, &media_type)))
6741 winetest_push_context("out %lu", i);
6742 ok(hr == S_OK, "GetOutputAvailableType returned %#lx\n", hr);
6743 check_media_type(media_type, default_outputs[i], -1);
6744 if (FAILED(hr = IMFMediaType_GetItem(media_type, &MF_MT_VIDEO_ROTATION, NULL)))
6745 check_media_type(media_type, default_outputs_win7[i], -1);
6746 else
6747 check_media_type(media_type, default_outputs_extra[i], -1);
6748 ret = IMFMediaType_Release(media_type);
6749 ok(ret == 0, "Release returned %lu\n", ret);
6750 winetest_pop_context();
6752 ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
6753 ok(i == 5, "%lu output media types\n", i);
6755 /* check required output media type attributes */
6757 hr = MFCreateMediaType(&media_type);
6758 ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr);
6759 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
6760 todo_wine
6761 ok(hr == E_INVALIDARG, "SetOutputType returned %#lx.\n", hr);
6762 init_media_type(media_type, output_type_desc, 1);
6763 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
6764 todo_wine
6765 ok(hr == MF_E_INVALIDMEDIATYPE, "SetOutputType returned %#lx.\n", hr);
6766 init_media_type(media_type, output_type_desc, 2);
6767 for (i = 2; i < ARRAY_SIZE(output_type_desc) - 1; ++i)
6769 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
6770 todo_wine
6771 ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetOutputType returned %#lx.\n", hr);
6772 init_media_type(media_type, output_type_desc, i + 1);
6774 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
6775 if (broken(hr == MF_E_INVALIDMEDIATYPE))
6777 init_media_type(media_type, output_type_desc_win7, ARRAY_SIZE(output_type_desc_win7) - 1);
6778 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
6780 ok(hr == S_OK, "SetOutputType returned %#lx.\n", hr);
6781 ret = IMFMediaType_Release(media_type);
6782 ok(ret == 1, "Release returned %lu\n", ret);
6784 flags = MFT_INPUT_STREAM_WHOLE_SAMPLES | MFT_INPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER | MFT_INPUT_STREAM_FIXED_SAMPLE_SIZE;
6785 memset(&input_info, 0xcd, sizeof(input_info));
6786 hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info);
6787 ok(hr == S_OK, "GetInputStreamInfo returned %#lx\n", hr);
6788 ok(input_info.hnsMaxLatency == 0, "got hnsMaxLatency %s\n", wine_dbgstr_longlong(input_info.hnsMaxLatency));
6789 ok(input_info.dwFlags == flags, "got dwFlags %#lx\n", input_info.dwFlags);
6790 ok(input_info.cbSize == 0x1000, "got cbSize %lu\n", input_info.cbSize);
6791 ok(input_info.cbMaxLookahead == 0, "got cbMaxLookahead %#lx\n", input_info.cbMaxLookahead);
6792 ok(input_info.cbAlignment == 0, "got cbAlignment %#lx\n", input_info.cbAlignment);
6794 flags = MFT_OUTPUT_STREAM_WHOLE_SAMPLES | MFT_OUTPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER | MFT_OUTPUT_STREAM_FIXED_SAMPLE_SIZE;
6795 memset(&output_info, 0xcd, sizeof(output_info));
6796 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
6797 ok(hr == S_OK, "GetOutputStreamInfo returned %#lx\n", hr);
6798 ok(output_info.dwFlags == flags, "got dwFlags %#lx\n", output_info.dwFlags);
6799 ok(output_info.cbSize == 1920 * 1080 * 2 || broken(output_info.cbSize == 1920 * 1088 * 2) /* Win7 */,
6800 "got cbSize %#lx\n", output_info.cbSize);
6801 ok(output_info.cbAlignment == 0, "got cbAlignment %#lx\n", output_info.cbAlignment);
6803 input_count = output_count = 0xdeadbeef;
6804 hr = IMFTransform_GetStreamCount(transform, &input_count, &output_count);
6805 todo_wine
6806 ok(hr == S_OK, "GetStreamCount returned %#lx\n", hr);
6807 todo_wine
6808 ok(input_count == 1, "got input_count %lu\n", input_count);
6809 todo_wine
6810 ok(output_count == 1, "got output_count %lu\n", output_count);
6811 hr = IMFTransform_GetStreamIDs(transform, 1, &input_id, 1, &output_id);
6812 ok(hr == E_NOTIMPL, "GetStreamIDs returned %#lx\n", hr);
6814 resource = FindResourceW(NULL, L"h264data.bin", (const WCHAR *)RT_RCDATA);
6815 ok(resource != 0, "FindResourceW failed, error %lu\n", GetLastError());
6816 h264_encoded_data = LockResource(LoadResource(GetModuleHandleW(NULL), resource));
6817 h264_encoded_data_len = SizeofResource(GetModuleHandleW(NULL), resource);
6819 /* As output_info.dwFlags doesn't have MFT_OUTPUT_STREAM_CAN_PROVIDE_SAMPLES
6820 * IMFTransform_ProcessOutput needs a sample or returns an error */
6822 status = 0;
6823 memset(&output, 0, sizeof(output));
6824 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
6825 ok(hr == E_INVALIDARG || hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
6826 ok(output.dwStreamID == 0, "got dwStreamID %lu\n", output.dwStreamID);
6827 ok(!output.pSample, "got pSample %p\n", output.pSample);
6828 ok(output.dwStatus == 0, "got dwStatus %#lx\n", output.dwStatus);
6829 ok(!output.pEvents, "got pEvents %p\n", output.pEvents);
6830 ok(status == 0, "got status %#lx\n", status);
6832 i = 0;
6833 sample = next_h264_sample(&h264_encoded_data, &h264_encoded_data_len);
6834 while (1)
6836 status = 0;
6837 memset(&output, 0, sizeof(output));
6838 output.pSample = create_sample(NULL, output_info.cbSize);
6839 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
6840 if (hr != MF_E_TRANSFORM_NEED_MORE_INPUT) break;
6841 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
6842 ok(output.dwStreamID == 0, "got dwStreamID %lu\n", output.dwStreamID);
6843 ok(!!output.pSample, "got pSample %p\n", output.pSample);
6844 ok(output.dwStatus == 0, "got dwStatus %#lx\n", output.dwStatus);
6845 ok(!output.pEvents, "got pEvents %p\n", output.pEvents);
6846 ok(status == 0, "got status %#lx\n", status);
6847 check_sample(output.pSample, NULL, 0, NULL);
6848 ret = IMFSample_Release(output.pSample);
6849 ok(ret == 0, "Release returned %lu\n", ret);
6851 hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
6852 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
6853 ret = IMFSample_Release(sample);
6854 ok(ret <= 1, "Release returned %lu\n", ret);
6855 sample = next_h264_sample(&h264_encoded_data, &h264_encoded_data_len);
6857 hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
6858 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
6859 ret = IMFSample_Release(sample);
6860 ok(ret <= 1, "Release returned %lu\n", ret);
6861 sample = next_h264_sample(&h264_encoded_data, &h264_encoded_data_len);
6862 i++;
6864 hr = IMFTransform_ProcessMessage(transform, MFT_MESSAGE_COMMAND_DRAIN, 0);
6865 ok(hr == S_OK, "ProcessMessage returned %#lx\n", hr);
6867 todo_wine
6868 ok(i == 2, "got %lu iterations\n", i);
6869 todo_wine
6870 ok(h264_encoded_data_len == 48194, "got h264_encoded_data_len %lu\n", h264_encoded_data_len);
6871 todo_wine
6872 ok(hr == MF_E_TRANSFORM_STREAM_CHANGE, "ProcessOutput returned %#lx\n", hr);
6873 ok(output.dwStreamID == 0, "got dwStreamID %lu\n", output.dwStreamID);
6874 ok(!!output.pSample, "got pSample %p\n", output.pSample);
6875 todo_wine
6876 ok(output.dwStatus == MFT_OUTPUT_DATA_BUFFER_FORMAT_CHANGE,
6877 "got dwStatus %#lx\n", output.dwStatus);
6878 ok(!output.pEvents, "got pEvents %p\n", output.pEvents);
6879 todo_wine
6880 ok(status == MFT_PROCESS_OUTPUT_STATUS_NEW_STREAMS,
6881 "got status %#lx\n", status);
6882 if (status == MFT_PROCESS_OUTPUT_STATUS_NEW_STREAMS)
6883 check_sample(output.pSample, NULL, 0, NULL);
6884 ret = IMFSample_Release(output.pSample);
6885 ok(ret == 0, "Release returned %lu\n", ret);
6887 flags = MFT_OUTPUT_STREAM_WHOLE_SAMPLES | MFT_OUTPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER | MFT_OUTPUT_STREAM_FIXED_SAMPLE_SIZE;
6888 memset(&output_info, 0xcd, sizeof(output_info));
6889 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
6890 ok(hr == S_OK, "GetOutputStreamInfo returned %#lx\n", hr);
6891 ok(output_info.dwFlags == flags, "got dwFlags %#lx\n", output_info.dwFlags);
6892 todo_wine
6893 ok(output_info.cbSize == actual_width * actual_height * 2, "got cbSize %#lx\n", output_info.cbSize);
6894 ok(output_info.cbAlignment == 0, "got cbAlignment %#lx\n", output_info.cbAlignment);
6896 i = -1;
6897 while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, ++i, &media_type)))
6899 winetest_push_context("out %lu", i);
6900 ok(hr == S_OK, "GetOutputAvailableType returned %#lx\n", hr);
6901 check_media_type(media_type, actual_outputs[i], -1);
6902 ret = IMFMediaType_Release(media_type);
6903 ok(ret == 0, "Release returned %lu\n", ret);
6904 winetest_pop_context();
6906 ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
6907 ok(i == 5, "%lu output media types\n", i);
6909 /* and generate a new one as well in a temporary directory */
6910 GetTempPathW(ARRAY_SIZE(output_path), output_path);
6911 lstrcatW(output_path, L"nv12frame.bin");
6912 output_file = CreateFileW(output_path, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
6913 ok(output_file != INVALID_HANDLE_VALUE, "CreateFileW failed, error %lu\n", GetLastError());
6915 resource = FindResourceW(NULL, L"nv12frame.bin", (const WCHAR *)RT_RCDATA);
6916 ok(resource != 0, "FindResourceW failed, error %lu\n", GetLastError());
6917 nv12_frame_data = LockResource(LoadResource(GetModuleHandleW(NULL), resource));
6918 nv12_frame_len = SizeofResource(GetModuleHandleW(NULL), resource);
6919 ok(nv12_frame_len == actual_width * actual_height * 3 / 2, "got frame length %lu\n", nv12_frame_len);
6921 status = 0;
6922 memset(&output, 0, sizeof(output));
6923 output.pSample = create_sample(NULL, actual_width * actual_height * 2);
6924 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
6925 todo_wine
6926 ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr);
6927 ok(output.dwStreamID == 0, "got dwStreamID %lu\n", output.dwStreamID);
6928 ok(!!output.pSample, "got pSample %p\n", output.pSample);
6929 ok(output.dwStatus == 0, "got dwStatus %#lx\n", output.dwStatus);
6930 ok(!output.pEvents, "got pEvents %p\n", output.pEvents);
6931 ok(status == 0, "got status %#lx\n", status);
6932 if (hr == S_OK)
6934 /* Win8 and before pad the data with garbage instead of original
6935 * buffer data, make sure it's consistent. */
6936 hr = IMFSample_ConvertToContiguousBuffer(output.pSample, &media_buffer);
6937 ok(hr == S_OK, "ConvertToContiguousBuffer returned %#lx\n", hr);
6938 hr = IMFMediaBuffer_Lock(media_buffer, &data, NULL, &length);
6939 ok(hr == S_OK, "Lock returned %#lx\n", hr);
6940 todo_wine
6941 ok(length == nv12_frame_len, "got length %lu\n", length);
6942 if (length == nv12_frame_len)
6944 for (i = 0; i < actual_aperture.Area.cy; ++i)
6946 memset(data + actual_width * i + actual_aperture.Area.cx, 0xcd, actual_width - actual_aperture.Area.cx);
6947 memset(data + actual_width * (actual_height + i) + actual_aperture.Area.cx, 0xcd, actual_width - actual_aperture.Area.cx);
6949 memset(data + actual_width * actual_aperture.Area.cy, 0xcd, (actual_height - actual_aperture.Area.cy) * actual_width);
6950 memset(data + actual_width * (actual_height + actual_aperture.Area.cy / 2), 0xcd, (actual_height - actual_aperture.Area.cy) / 2 * actual_width);
6952 hr = IMFMediaBuffer_Unlock(media_buffer);
6953 ok(hr == S_OK, "Unlock returned %#lx\n", hr);
6954 IMFMediaBuffer_Release(media_buffer);
6956 if (length == nv12_frame_len)
6957 check_sample(output.pSample, nv12_frame_data, nv12_frame_len, output_file);
6959 ret = IMFSample_Release(output.pSample);
6960 ok(ret == 0, "Release returned %lu\n", ret);
6962 trace("created %s\n", debugstr_w(output_path));
6963 CloseHandle(output_file);
6965 ret = IMFTransform_Release(transform);
6966 ok(ret == 0, "Release returned %lu\n", ret);
6967 ret = IMFSample_Release(sample);
6968 ok(ret == 0, "Release returned %lu\n", ret);
6970 failed:
6971 CoUninitialize();
6974 START_TEST(mf)
6976 init_functions();
6978 if (is_vista())
6980 win_skip("Skipping tests on Vista.\n");
6981 return;
6984 test_topology();
6985 test_topology_tee_node();
6986 test_topology_loader();
6987 test_topology_loader_evr();
6988 test_MFGetService();
6989 test_sequencer_source();
6990 test_media_session();
6991 test_media_session_rate_control();
6992 test_MFShutdownObject();
6993 test_presentation_clock();
6994 test_sample_grabber();
6995 test_sample_grabber_is_mediatype_supported();
6996 test_video_processor();
6997 test_quality_manager();
6998 test_sar();
6999 test_evr();
7000 test_MFCreateSimpleTypeHandler();
7001 test_MFGetSupportedMimeTypes();
7002 test_MFGetSupportedSchemes();
7003 test_sample_copier();
7004 test_sample_copier_output_processing();
7005 test_MFGetTopoNodeCurrentType();
7006 test_MFRequireProtectedEnvironment();
7007 test_wma_encoder();
7008 test_wma_decoder();
7009 test_h264_decoder();