mf/tests: Add more topology loader connect method tests.
[wine.git] / dlls / mf / tests / mf.c
blob33f7c119386e5ce80a596abb8d1ebbdf5898f4d3
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"
29 #include "d3d9types.h"
31 #include "initguid.h"
32 #include "control.h"
33 #include "dmo.h"
34 #include "mediaobj.h"
35 #include "ole2.h"
36 #include "wmcodecdsp.h"
37 #include "propsys.h"
38 #include "propvarutil.h"
40 DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0);
41 DEFINE_GUID(MFVideoFormat_P208, 0x38303250, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
42 DEFINE_GUID(MFVideoFormat_ABGR32, 0x00000020, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
43 DEFINE_GUID(CLSID_WINEAudioConverter, 0x6a170414, 0xaad9, 0x4693, 0xb8, 0x06, 0x3a, 0x0c, 0x47, 0xc5, 0x70, 0xd6);
45 DEFINE_GUID(DMOVideoFormat_RGB32, D3DFMT_X8R8G8B8, 0x524f, 0x11ce, 0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70);
46 DEFINE_GUID(DMOVideoFormat_RGB24, D3DFMT_R8G8B8, 0x524f, 0x11ce, 0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70);
47 DEFINE_GUID(DMOVideoFormat_RGB565, D3DFMT_R5G6B5, 0x524f, 0x11ce, 0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70);
48 DEFINE_GUID(DMOVideoFormat_RGB555, D3DFMT_X1R5G5B5, 0x524f, 0x11ce, 0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70);
49 DEFINE_GUID(DMOVideoFormat_RGB8, D3DFMT_P8, 0x524f, 0x11ce, 0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70);
51 #undef INITGUID
52 #include <guiddef.h>
53 #include "mfapi.h"
54 #include "mferror.h"
55 #include "mfidl.h"
56 #include "initguid.h"
57 #include "uuids.h"
58 #include "mmdeviceapi.h"
59 #include "audioclient.h"
60 #include "evr.h"
61 #include "d3d9.h"
62 #include "evr9.h"
64 #include "wine/test.h"
66 static HRESULT (WINAPI *pMFCreateSampleCopierMFT)(IMFTransform **copier);
67 static HRESULT (WINAPI *pMFGetTopoNodeCurrentType)(IMFTopologyNode *node, DWORD stream, BOOL output, IMFMediaType **type);
69 static BOOL has_video_processor;
70 static BOOL is_vista(void)
72 return !pMFGetTopoNodeCurrentType;
75 #define EXPECT_REF(obj,ref) _expect_ref((IUnknown*)obj, ref, __LINE__)
76 static void _expect_ref(IUnknown* obj, ULONG expected_refcount, int line)
78 ULONG refcount;
79 IUnknown_AddRef(obj);
80 refcount = IUnknown_Release(obj);
81 ok_(__FILE__, line)(refcount == expected_refcount, "Unexpected refcount %ld, expected %ld.\n", refcount,
82 expected_refcount);
85 #define check_interface(a, b, c) check_interface_(__LINE__, a, b, c)
86 static void check_interface_(unsigned int line, void *iface_ptr, REFIID iid, BOOL supported)
88 IUnknown *iface = iface_ptr;
89 HRESULT hr, expected_hr;
90 IUnknown *unk;
92 expected_hr = supported ? S_OK : E_NOINTERFACE;
94 hr = IUnknown_QueryInterface(iface, iid, (void **)&unk);
95 ok_(__FILE__, line)(hr == expected_hr, "Got hr %#lx, expected %#lx.\n", hr, expected_hr);
96 if (SUCCEEDED(hr))
97 IUnknown_Release(unk);
100 #define check_service_interface(a, b, c, d) check_service_interface_(__LINE__, a, b, c, d)
101 static void check_service_interface_(unsigned int line, void *iface_ptr, REFGUID service, REFIID iid, BOOL supported)
103 IUnknown *iface = iface_ptr;
104 HRESULT hr, expected_hr;
105 IUnknown *unk;
107 expected_hr = supported ? S_OK : E_NOINTERFACE;
109 hr = MFGetService(iface, service, iid, (void **)&unk);
110 ok_(__FILE__, line)(hr == expected_hr, "Got hr %#lx, expected %#lx.\n", hr, expected_hr);
111 if (SUCCEEDED(hr))
112 IUnknown_Release(unk);
115 static void check_dmo(const GUID *class_id, const WCHAR *expect_name, const GUID *expect_major_type,
116 const GUID *expect_input, ULONG expect_input_count, const GUID *expect_output, ULONG expect_output_count)
118 ULONG i, input_count = 0, output_count = 0;
119 DMO_PARTIAL_MEDIATYPE output[32] = {{{0}}};
120 DMO_PARTIAL_MEDIATYPE input[32] = {{{0}}};
121 WCHAR name[80];
122 HRESULT hr;
124 winetest_push_context("%s", debugstr_w(expect_name));
126 hr = DMOGetName(class_id, name);
127 ok(hr == S_OK, "DMOGetName returned %#lx\n", hr);
128 todo_wine_if(!wcscmp(expect_name, L"WMAudio Decoder DMO"))
129 ok(!wcscmp(name, expect_name), "got name %s\n", debugstr_w(name));
131 hr = DMOGetTypes(class_id, ARRAY_SIZE(input), &input_count, input,
132 ARRAY_SIZE(output), &output_count, output);
133 ok(hr == S_OK, "DMOGetTypes returned %#lx\n", hr);
134 ok(input_count == expect_input_count, "got input_count %lu\n", input_count);
135 ok(output_count == expect_output_count, "got output_count %lu\n", output_count);
137 for (i = 0; i < input_count; ++i)
139 winetest_push_context("in %lu", i);
140 ok(IsEqualGUID(&input[i].type, expect_major_type),
141 "got type %s\n", debugstr_guid(&input[i].type));
142 ok(IsEqualGUID(&input[i].subtype, expect_input + i),
143 "got subtype %s\n", debugstr_guid(&input[i].subtype));
144 winetest_pop_context();
147 for (i = 0; i < output_count; ++i)
149 winetest_push_context("out %lu", i);
150 ok(IsEqualGUID(&output[i].type, expect_major_type),
151 "got type %s\n", debugstr_guid(&output[i].type));
152 ok(IsEqualGUID(&output[i].subtype, expect_output + i),
153 "got subtype %s\n", debugstr_guid( &output[i].subtype));
154 winetest_pop_context();
157 winetest_pop_context();
160 struct attribute_desc
162 const GUID *key;
163 const char *name;
164 PROPVARIANT value;
165 BOOL ratio;
166 BOOL todo;
167 BOOL todo_value;
169 typedef struct attribute_desc media_type_desc[32];
171 #define ATTR_GUID(k, g, ...) {.key = &k, .name = #k, {.vt = VT_CLSID, .puuid = (GUID *)&g}, __VA_ARGS__ }
172 #define ATTR_UINT32(k, v, ...) {.key = &k, .name = #k, {.vt = VT_UI4, .ulVal = v}, __VA_ARGS__ }
173 #define ATTR_BLOB(k, p, n, ...) {.key = &k, .name = #k, {.vt = VT_VECTOR | VT_UI1, .caub = {.pElems = (void *)p, .cElems = n}}, __VA_ARGS__ }
174 #define ATTR_RATIO(k, n, d, ...) {.key = &k, .name = #k, {.vt = VT_UI8, .uhVal = {.HighPart = n, .LowPart = d}}, .ratio = TRUE, __VA_ARGS__ }
175 #define ATTR_UINT64(k, v, ...) {.key = &k, .name = #k, {.vt = VT_UI8, .uhVal = {.QuadPart = v}}, __VA_ARGS__ }
177 #define check_media_type(a, b, c) check_attributes_(__LINE__, (IMFAttributes *)a, b, c)
178 #define check_attributes(a, b, c) check_attributes_(__LINE__, a, b, c)
179 static void check_attributes_(int line, IMFAttributes *attributes, const struct attribute_desc *desc, ULONG limit)
181 char buffer[256], *buf = buffer;
182 PROPVARIANT value;
183 int i, j, ret;
184 HRESULT hr;
186 for (i = 0; i < limit && desc[i].key; ++i)
188 hr = IMFAttributes_GetItem(attributes, desc[i].key, &value);
189 todo_wine_if(desc[i].todo)
190 ok_(__FILE__, line)(hr == S_OK, "%s missing, hr %#lx\n", debugstr_a(desc[i].name), hr);
191 if (hr != S_OK) continue;
193 switch (value.vt)
195 default: sprintf(buffer, "??"); break;
196 case VT_CLSID: sprintf(buffer, "%s", debugstr_guid(value.puuid)); break;
197 case VT_UI4: sprintf(buffer, "%lu", value.ulVal); break;
198 case VT_UI8:
199 if (desc[i].ratio)
200 sprintf(buffer, "%lu:%lu", value.uhVal.HighPart, value.uhVal.LowPart);
201 else
202 sprintf(buffer, "%I64u", value.uhVal.QuadPart);
203 break;
204 case VT_VECTOR | VT_UI1:
205 buf += sprintf(buf, "size %lu, data {", value.caub.cElems);
206 for (j = 0; j < 16 && j < value.caub.cElems; ++j)
207 buf += sprintf(buf, "0x%02x,", value.caub.pElems[j]);
208 if (value.caub.cElems > 16)
209 buf += sprintf(buf, "...}");
210 else
211 buf += sprintf(buf - (j ? 1 : 0), "}");
212 break;
215 ret = PropVariantCompareEx(&value, &desc[i].value, 0, 0);
216 todo_wine_if(desc[i].todo_value)
217 ok_(__FILE__, line)(ret == 0, "%s mismatch, type %u, value %s\n",
218 debugstr_a(desc[i].name), value.vt, buffer);
222 static HWND create_window(void)
224 RECT r = {0, 0, 640, 480};
226 AdjustWindowRect(&r, WS_OVERLAPPEDWINDOW | WS_VISIBLE, FALSE);
228 return CreateWindowA("static", "mf_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
229 0, 0, r.right - r.left, r.bottom - r.top, NULL, NULL, NULL, NULL);
232 static BOOL create_transform(GUID category, MFT_REGISTER_TYPE_INFO *input_type,
233 MFT_REGISTER_TYPE_INFO *output_type, const WCHAR *expect_name, const GUID *expect_major_type,
234 const GUID *expect_input, ULONG expect_input_count, const GUID *expect_output, ULONG expect_output_count,
235 IMFTransform **transform, const GUID *expect_class_id, GUID *class_id)
237 MFT_REGISTER_TYPE_INFO *input_types = NULL, *output_types = NULL;
238 UINT32 input_count = 0, output_count = 0, count = 0, i;
239 GUID *class_ids = NULL;
240 WCHAR *name;
241 HRESULT hr;
243 hr = MFTEnum(category, 0, input_type, output_type, NULL, &class_ids, &count);
244 if (FAILED(hr) || count == 0)
246 todo_wine
247 win_skip("Failed to enumerate %s, skipping tests.\n", debugstr_w(expect_name));
248 return FALSE;
251 ok(hr == S_OK, "MFTEnum returned %lx\n", hr);
252 for (i = 0; i < count; ++i)
254 if (IsEqualGUID(expect_class_id, class_ids + i))
255 break;
257 ok(i < count, "failed to find %s transform\n", debugstr_w(expect_name));
258 *class_id = class_ids[i];
259 CoTaskMemFree(class_ids);
260 ok(IsEqualGUID(class_id, expect_class_id), "got class id %s\n", debugstr_guid(class_id));
262 hr = MFTGetInfo(*class_id, &name, &input_types, &input_count, &output_types, &output_count, NULL);
263 if (FAILED(hr))
265 todo_wine
266 win_skip("Failed to get %s info, skipping tests.\n", debugstr_w(expect_name));
268 else
270 ok(hr == S_OK, "MFTEnum returned %lx\n", hr);
271 ok(!wcscmp(name, expect_name), "got name %s\n", debugstr_w(name));
272 ok(input_count == expect_input_count, "got input_count %u\n", input_count);
273 for (i = 0; i < input_count; ++i)
275 ok(IsEqualGUID(&input_types[i].guidMajorType, expect_major_type),
276 "got input[%u] major %s\n", i, debugstr_guid(&input_types[i].guidMajorType));
277 ok(IsEqualGUID(&input_types[i].guidSubtype, expect_input + i),
278 "got input[%u] subtype %s\n", i, debugstr_guid(&input_types[i].guidSubtype));
280 ok(output_count == expect_output_count, "got output_count %u\n", output_count);
281 for (i = 0; i < output_count; ++i)
283 ok(IsEqualGUID(&output_types[i].guidMajorType, expect_major_type),
284 "got output[%u] major %s\n", i, debugstr_guid(&output_types[i].guidMajorType));
285 ok(IsEqualGUID(&output_types[i].guidSubtype, expect_output + i),
286 "got output[%u] subtype %s\n", i, debugstr_guid(&output_types[i].guidSubtype));
288 CoTaskMemFree(output_types);
289 CoTaskMemFree(input_types);
290 CoTaskMemFree(name);
293 hr = CoCreateInstance(class_id, NULL, CLSCTX_INPROC_SERVER, &IID_IMFTransform, (void **)transform);
294 if (FAILED(hr))
296 todo_wine
297 win_skip("Failed to create %s instance, skipping tests.\n", debugstr_w(expect_name));
298 return FALSE;
301 return TRUE;
304 static HRESULT WINAPI test_unk_QueryInterface(IUnknown *iface, REFIID riid, void **obj)
306 if (IsEqualIID(riid, &IID_IUnknown))
308 *obj = iface;
309 IUnknown_AddRef(iface);
310 return S_OK;
313 *obj = NULL;
314 return E_NOINTERFACE;
317 static ULONG WINAPI test_unk_AddRef(IUnknown *iface)
319 return 2;
322 static ULONG WINAPI test_unk_Release(IUnknown *iface)
324 return 1;
327 static const IUnknownVtbl test_unk_vtbl =
329 test_unk_QueryInterface,
330 test_unk_AddRef,
331 test_unk_Release,
334 static void test_topology(void)
336 IMFMediaType *mediatype, *mediatype2, *mediatype3;
337 IMFCollection *collection, *collection2;
338 IUnknown test_unk2 = { &test_unk_vtbl };
339 IUnknown test_unk = { &test_unk_vtbl };
340 IMFTopologyNode *node, *node2, *node3;
341 IMFTopology *topology, *topology2;
342 DWORD size, io_count, index;
343 MF_TOPOLOGY_TYPE node_type;
344 IUnknown *object;
345 WORD node_count;
346 UINT32 count;
347 HRESULT hr;
348 TOPOID id;
349 LONG ref;
351 hr = MFCreateTopology(NULL);
352 ok(hr == E_POINTER, "got %#lx\n", hr);
354 hr = MFCreateTopology(&topology);
355 ok(hr == S_OK, "Failed to create topology, hr %#lx.\n", hr);
356 hr = IMFTopology_GetTopologyID(topology, &id);
357 ok(hr == S_OK, "Failed to get id, hr %#lx.\n", hr);
358 ok(id == 1, "Unexpected id.\n");
360 hr = MFCreateTopology(&topology2);
361 ok(hr == S_OK, "Failed to create topology, hr %#lx.\n", hr);
362 hr = IMFTopology_GetTopologyID(topology2, &id);
363 ok(hr == S_OK, "Failed to get id, hr %#lx.\n", hr);
364 ok(id == 2, "Unexpected id.\n");
366 ref = IMFTopology_Release(topology);
367 ok(ref == 0, "Release returned %ld\n", ref);
369 hr = MFCreateTopology(&topology);
370 ok(hr == S_OK, "Failed to create topology, hr %#lx.\n", hr);
371 hr = IMFTopology_GetTopologyID(topology, &id);
372 ok(hr == S_OK, "Failed to get id, hr %#lx.\n", hr);
373 ok(id == 3, "Unexpected id.\n");
375 ref = IMFTopology_Release(topology2);
376 ok(ref == 0, "Release returned %ld\n", ref);
378 /* No attributes by default. */
379 for (node_type = MF_TOPOLOGY_OUTPUT_NODE; node_type < MF_TOPOLOGY_TEE_NODE; ++node_type)
381 hr = MFCreateTopologyNode(node_type, &node);
382 ok(hr == S_OK, "Failed to create a node for type %d, hr %#lx.\n", node_type, hr);
383 hr = IMFTopologyNode_GetCount(node, &count);
384 ok(hr == S_OK, "Failed to get attribute count, hr %#lx.\n", hr);
385 ok(!count, "Unexpected attribute count %u.\n", count);
386 ref = IMFTopologyNode_Release(node);
387 ok(ref == 0, "Release returned %ld\n", ref);
390 hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, NULL);
391 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
393 hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, &node);
394 ok(hr == S_OK, "Failed to create topology node, hr %#lx.\n", hr);
396 hr = MFCreateTopologyNode(MF_TOPOLOGY_TEE_NODE, &node2);
397 ok(hr == S_OK, "Failed to create topology node, hr %#lx.\n", hr);
399 hr = IMFTopologyNode_GetTopoNodeID(node, &id);
400 ok(hr == S_OK, "Failed to get node id, hr %#lx.\n", hr);
401 ok(((id >> 32) == GetCurrentProcessId()) && !!(id & 0xffff), "Unexpected node id %s.\n", wine_dbgstr_longlong(id));
403 hr = IMFTopologyNode_SetTopoNodeID(node2, id);
404 ok(hr == S_OK, "Failed to set node id, hr %#lx.\n", hr);
406 hr = IMFTopology_GetNodeCount(topology, NULL);
407 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
409 hr = IMFTopology_AddNode(topology, NULL);
410 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
412 node_count = 1;
413 hr = IMFTopology_GetNodeCount(topology, &node_count);
414 ok(hr == S_OK, "Failed to get node count, hr %#lx.\n", hr);
415 ok(node_count == 0, "Unexpected node count %u.\n", node_count);
417 /* Same id, different nodes. */
418 hr = IMFTopology_AddNode(topology, node);
419 ok(hr == S_OK, "Failed to add a node, hr %#lx.\n", hr);
421 node_count = 0;
422 hr = IMFTopology_GetNodeCount(topology, &node_count);
423 ok(hr == S_OK, "Failed to get node count, hr %#lx.\n", hr);
424 ok(node_count == 1, "Unexpected node count %u.\n", node_count);
426 hr = IMFTopology_AddNode(topology, node2);
427 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
428 ref = IMFTopologyNode_Release(node2);
429 ok(ref == 0, "Release returned %ld\n", ref);
431 hr = IMFTopology_GetNodeByID(topology, id, &node2);
432 ok(hr == S_OK, "Failed to get a node, hr %#lx.\n", hr);
433 ok(node2 == node, "Unexpected node.\n");
434 IMFTopologyNode_Release(node2);
436 /* Change node id, add it again. */
437 hr = IMFTopologyNode_SetTopoNodeID(node, ++id);
438 ok(hr == S_OK, "Failed to set node id, hr %#lx.\n", hr);
440 hr = IMFTopology_GetNodeByID(topology, id, &node2);
441 ok(hr == S_OK, "Failed to get a node, hr %#lx.\n", hr);
442 ok(node2 == node, "Unexpected node.\n");
443 IMFTopologyNode_Release(node2);
445 hr = IMFTopology_GetNodeByID(topology, id + 1, &node2);
446 ok(hr == MF_E_NOT_FOUND, "Unexpected hr %#lx.\n", hr);
448 hr = IMFTopology_AddNode(topology, node);
449 ok(hr == E_INVALIDARG, "Failed to add a node, hr %#lx.\n", hr);
451 hr = IMFTopology_GetNode(topology, 0, &node2);
452 ok(hr == S_OK, "Failed to get a node, hr %#lx.\n", hr);
453 ok(node2 == node, "Unexpected node.\n");
454 IMFTopologyNode_Release(node2);
456 hr = IMFTopology_GetNode(topology, 1, NULL);
457 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
459 hr = IMFTopology_GetNode(topology, 1, &node2);
460 ok(hr == MF_E_INVALIDINDEX, "Failed to get a node, hr %#lx.\n", hr);
462 hr = IMFTopology_GetNode(topology, -2, &node2);
463 ok(hr == MF_E_INVALIDINDEX, "Failed to get a node, hr %#lx.\n", hr);
465 hr = MFCreateTopologyNode(MF_TOPOLOGY_TEE_NODE, &node2);
466 ok(hr == S_OK, "Failed to create topology node, hr %#lx.\n", hr);
467 hr = IMFTopology_AddNode(topology, node2);
468 ok(hr == S_OK, "Failed to add a node, hr %#lx.\n", hr);
469 ref = IMFTopologyNode_Release(node2);
470 ok(ref == 1, "Release returned %ld\n", ref);
472 node_count = 0;
473 hr = IMFTopology_GetNodeCount(topology, &node_count);
474 ok(hr == S_OK, "Failed to get node count, hr %#lx.\n", hr);
475 ok(node_count == 2, "Unexpected node count %u.\n", node_count);
477 /* Remove with detached node, existing id. */
478 hr = MFCreateTopologyNode(MF_TOPOLOGY_TEE_NODE, &node2);
479 ok(hr == S_OK, "Failed to create topology node, hr %#lx.\n", hr);
480 hr = IMFTopologyNode_SetTopoNodeID(node2, id);
481 ok(hr == S_OK, "Failed to set node id, hr %#lx.\n", hr);
482 hr = IMFTopology_RemoveNode(topology, node2);
483 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
484 ref = IMFTopologyNode_Release(node2);
485 ok(ref == 0, "Release returned %ld\n", ref);
487 hr = IMFTopology_RemoveNode(topology, node);
488 ok(hr == S_OK, "Failed to remove a node, hr %#lx.\n", hr);
490 node_count = 0;
491 hr = IMFTopology_GetNodeCount(topology, &node_count);
492 ok(hr == S_OK, "Failed to get node count, hr %#lx.\n", hr);
493 ok(node_count == 1, "Unexpected node count %u.\n", node_count);
495 hr = IMFTopology_Clear(topology);
496 ok(hr == S_OK, "Failed to clear topology, hr %#lx.\n", hr);
498 node_count = 1;
499 hr = IMFTopology_GetNodeCount(topology, &node_count);
500 ok(hr == S_OK, "Failed to get node count, hr %#lx.\n", hr);
501 ok(node_count == 0, "Unexpected node count %u.\n", node_count);
503 hr = IMFTopology_Clear(topology);
504 ok(hr == S_OK, "Failed to clear topology, hr %#lx.\n", hr);
506 hr = IMFTopologyNode_SetTopoNodeID(node, 123);
507 ok(hr == S_OK, "Failed to set node id, hr %#lx.\n", hr);
509 ref = IMFTopologyNode_Release(node);
510 ok(ref == 0, "Release returned %ld\n", ref);
512 /* Change id for attached node. */
513 hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, &node);
514 ok(hr == S_OK, "Failed to create topology node, hr %#lx.\n", hr);
516 hr = MFCreateTopologyNode(MF_TOPOLOGY_TEE_NODE, &node2);
517 ok(hr == S_OK, "Failed to create topology node, hr %#lx.\n", hr);
519 hr = IMFTopology_AddNode(topology, node);
520 ok(hr == S_OK, "Failed to add a node, hr %#lx.\n", hr);
522 hr = IMFTopology_AddNode(topology, node2);
523 ok(hr == S_OK, "Failed to add a node, hr %#lx.\n", hr);
525 hr = IMFTopologyNode_GetTopoNodeID(node, &id);
526 ok(hr == S_OK, "Failed to get node id, hr %#lx.\n", hr);
528 hr = IMFTopologyNode_SetTopoNodeID(node2, id);
529 ok(hr == S_OK, "Failed to get node id, hr %#lx.\n", hr);
531 hr = IMFTopology_GetNodeByID(topology, id, &node3);
532 ok(hr == S_OK, "Failed to get a node, hr %#lx.\n", hr);
533 ok(node3 == node, "Unexpected node.\n");
534 IMFTopologyNode_Release(node3);
536 /* Source/output collections. */
537 hr = IMFTopology_Clear(topology);
538 ok(hr == S_OK, "Failed to clear topology, hr %#lx.\n", hr);
540 ref = IMFTopologyNode_Release(node);
541 ok(ref == 0, "Release returned %ld\n", ref);
542 ref = IMFTopologyNode_Release(node2);
543 ok(ref == 0, "Release returned %ld\n", ref);
545 hr = IMFTopology_GetSourceNodeCollection(topology, NULL);
546 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
548 hr = IMFTopology_GetSourceNodeCollection(topology, &collection);
549 ok(hr == S_OK, "Failed to get source node collection, hr %#lx.\n", hr);
550 ok(!!collection, "Unexpected object pointer.\n");
552 hr = IMFTopology_GetSourceNodeCollection(topology, &collection2);
553 ok(hr == S_OK, "Failed to get source node collection, hr %#lx.\n", hr);
554 ok(!!collection2, "Unexpected object pointer.\n");
555 ok(collection2 != collection, "Expected cloned collection.\n");
557 hr = IMFCollection_GetElementCount(collection, &size);
558 ok(hr == S_OK, "Failed to get item count, hr %#lx.\n", hr);
559 ok(!size, "Unexpected item count.\n");
561 EXPECT_REF(collection, 1);
562 hr = IMFCollection_AddElement(collection, (IUnknown *)collection);
563 ok(hr == S_OK, "Failed to add element, hr %#lx.\n", hr);
564 EXPECT_REF(collection, 2);
566 hr = IMFCollection_GetElementCount(collection, &size);
567 ok(hr == S_OK, "Failed to get item count, hr %#lx.\n", hr);
568 ok(size == 1, "Unexpected item count.\n");
570 /* Empty collection to stop referencing itself */
571 hr = IMFCollection_RemoveAllElements(collection);
572 ok(hr == S_OK, "Failed to get item count, hr %#lx.\n", hr);
574 hr = IMFCollection_GetElementCount(collection2, &size);
575 ok(hr == S_OK, "Failed to get item count, hr %#lx.\n", hr);
576 ok(!size, "Unexpected item count.\n");
578 ref = IMFCollection_Release(collection2);
579 ok(ref == 0, "Release returned %ld\n", ref);
580 ref = IMFCollection_Release(collection);
581 ok(ref == 0, "Release returned %ld\n", ref);
583 /* Add some nodes. */
584 hr = IMFTopology_GetSourceNodeCollection(topology, NULL);
585 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
587 hr = IMFTopology_GetOutputNodeCollection(topology, NULL);
588 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
590 hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &node);
591 ok(hr == S_OK, "Failed to create a node, hr %#lx.\n", hr);
592 hr = IMFTopology_AddNode(topology, node);
593 ok(hr == S_OK, "Failed to add a node, hr %#lx.\n", hr);
594 IMFTopologyNode_Release(node);
596 hr = IMFTopology_GetSourceNodeCollection(topology, &collection);
597 ok(hr == S_OK, "Failed to get source node collection, hr %#lx.\n", hr);
598 ok(!!collection, "Unexpected object pointer.\n");
599 hr = IMFCollection_GetElementCount(collection, &size);
600 ok(hr == S_OK, "Failed to get item count, hr %#lx.\n", hr);
601 ok(size == 1, "Unexpected item count.\n");
602 ref = IMFCollection_Release(collection);
603 ok(ref == 0, "Release returned %ld\n", ref);
605 hr = MFCreateTopologyNode(MF_TOPOLOGY_TEE_NODE, &node);
606 ok(hr == S_OK, "Failed to create a node, hr %#lx.\n", hr);
607 hr = IMFTopology_AddNode(topology, node);
608 ok(hr == S_OK, "Failed to add a node, hr %#lx.\n", hr);
609 IMFTopologyNode_Release(node);
611 hr = IMFTopology_GetSourceNodeCollection(topology, &collection);
612 ok(hr == S_OK, "Failed to get source node collection, hr %#lx.\n", hr);
613 ok(!!collection, "Unexpected object pointer.\n");
614 hr = IMFCollection_GetElementCount(collection, &size);
615 ok(hr == S_OK, "Failed to get item count, hr %#lx.\n", hr);
616 ok(size == 1, "Unexpected item count.\n");
617 ref = IMFCollection_Release(collection);
618 ok(ref == 0, "Release returned %ld\n", ref);
620 hr = MFCreateTopologyNode(MF_TOPOLOGY_TRANSFORM_NODE, &node);
621 ok(hr == S_OK, "Failed to create a node, hr %#lx.\n", hr);
622 hr = IMFTopology_AddNode(topology, node);
623 ok(hr == S_OK, "Failed to add a node, hr %#lx.\n", hr);
624 IMFTopologyNode_Release(node);
626 hr = IMFTopology_GetSourceNodeCollection(topology, &collection);
627 ok(hr == S_OK, "Failed to get source node collection, hr %#lx.\n", hr);
628 ok(!!collection, "Unexpected object pointer.\n");
629 hr = IMFCollection_GetElementCount(collection, &size);
630 ok(hr == S_OK, "Failed to get item count, hr %#lx.\n", hr);
631 ok(size == 1, "Unexpected item count.\n");
632 ref = IMFCollection_Release(collection);
633 ok(ref == 0, "Release returned %ld\n", ref);
635 hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, &node);
636 ok(hr == S_OK, "Failed to create a node, hr %#lx.\n", hr);
637 hr = IMFTopology_AddNode(topology, node);
638 ok(hr == S_OK, "Failed to add a node, hr %#lx.\n", hr);
640 /* Associated object. */
641 hr = IMFTopologyNode_SetObject(node, NULL);
642 ok(hr == S_OK, "Failed to set object, hr %#lx.\n", hr);
644 hr = IMFTopologyNode_GetObject(node, NULL);
645 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
647 object = (void *)0xdeadbeef;
648 hr = IMFTopologyNode_GetObject(node, &object);
649 ok(hr == E_FAIL, "Unexpected hr %#lx.\n", hr);
650 ok(!object, "Unexpected object %p.\n", object);
652 hr = IMFTopologyNode_SetObject(node, &test_unk);
653 ok(hr == S_OK, "Failed to set object, hr %#lx.\n", hr);
655 hr = IMFTopologyNode_GetObject(node, &object);
656 ok(hr == S_OK, "Failed to get object, hr %#lx.\n", hr);
657 ok(object == &test_unk, "Unexpected object %p.\n", object);
658 IUnknown_Release(object);
660 hr = IMFTopologyNode_SetObject(node, &test_unk2);
661 ok(hr == S_OK, "Failed to set object, hr %#lx.\n", hr);
663 hr = IMFTopologyNode_GetCount(node, &count);
664 ok(hr == S_OK, "Failed to get attribute count, hr %#lx.\n", hr);
665 ok(count == 0, "Unexpected attribute count %u.\n", count);
667 hr = IMFTopologyNode_SetGUID(node, &MF_TOPONODE_TRANSFORM_OBJECTID, &MF_TOPONODE_TRANSFORM_OBJECTID);
668 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
670 hr = IMFTopologyNode_SetObject(node, NULL);
671 ok(hr == S_OK, "Failed to set object, hr %#lx.\n", hr);
673 object = (void *)0xdeadbeef;
674 hr = IMFTopologyNode_GetObject(node, &object);
675 ok(hr == E_FAIL, "Unexpected hr %#lx.\n", hr);
676 ok(!object, "Unexpected object %p.\n", object);
678 hr = IMFTopologyNode_GetCount(node, &count);
679 ok(hr == S_OK, "Failed to get attribute count, hr %#lx.\n", hr);
680 ok(count == 1, "Unexpected attribute count %u.\n", count);
682 /* Preferred stream types. */
683 hr = IMFTopologyNode_GetInputCount(node, &io_count);
684 ok(hr == S_OK, "Failed to get input count, hr %#lx.\n", hr);
685 ok(io_count == 0, "Unexpected count %lu.\n", io_count);
687 hr = IMFTopologyNode_GetInputPrefType(node, 0, &mediatype);
688 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
690 hr = MFCreateMediaType(&mediatype);
691 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
693 hr = IMFTopologyNode_SetInputPrefType(node, 0, mediatype);
694 ok(hr == S_OK, "Failed to set preferred type, hr %#lx.\n", hr);
696 hr = IMFTopologyNode_GetInputPrefType(node, 0, &mediatype2);
697 ok(hr == S_OK, "Failed to get preferred type, hr %#lx.\n", hr);
698 ok(mediatype2 == mediatype, "Unexpected mediatype instance.\n");
699 IMFMediaType_Release(mediatype2);
701 hr = IMFTopologyNode_SetInputPrefType(node, 0, NULL);
702 ok(hr == S_OK, "Failed to set preferred type, hr %#lx.\n", hr);
704 hr = IMFTopologyNode_GetInputPrefType(node, 0, &mediatype2);
705 ok(hr == E_FAIL, "Unexpected hr %#lx.\n", hr);
706 ok(!mediatype2, "Unexpected mediatype instance.\n");
708 hr = IMFTopologyNode_SetInputPrefType(node, 1, mediatype);
709 ok(hr == S_OK, "Failed to set preferred type, hr %#lx.\n", hr);
711 hr = IMFTopologyNode_SetInputPrefType(node, 1, mediatype);
712 ok(hr == S_OK, "Failed to set preferred type, hr %#lx.\n", hr);
714 hr = IMFTopologyNode_GetInputCount(node, &io_count);
715 ok(hr == S_OK, "Failed to get input count, hr %#lx.\n", hr);
716 ok(io_count == 2, "Unexpected count %lu.\n", io_count);
718 hr = IMFTopologyNode_GetOutputCount(node, &io_count);
719 ok(hr == S_OK, "Failed to get input count, hr %#lx.\n", hr);
720 ok(io_count == 0, "Unexpected count %lu.\n", io_count);
722 hr = IMFTopologyNode_SetOutputPrefType(node, 0, mediatype);
723 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
725 ref = IMFTopologyNode_Release(node);
726 ok(ref == 1, "Release returned %ld\n", ref);
728 /* Source node. */
729 hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &node);
730 ok(hr == S_OK, "Failed to create a node, hr %#lx.\n", hr);
732 hr = IMFTopologyNode_SetInputPrefType(node, 0, mediatype);
733 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
735 hr = IMFTopologyNode_SetOutputPrefType(node, 2, mediatype);
736 ok(hr == S_OK, "Failed to set preferred type, hr %#lx.\n", hr);
738 hr = IMFTopologyNode_GetOutputPrefType(node, 0, &mediatype2);
739 ok(hr == E_FAIL, "Failed to get preferred type, hr %#lx.\n", hr);
740 ok(!mediatype2, "Unexpected mediatype instance.\n");
742 hr = IMFTopologyNode_GetOutputCount(node, &io_count);
743 ok(hr == S_OK, "Failed to get output count, hr %#lx.\n", hr);
744 ok(io_count == 3, "Unexpected count %lu.\n", io_count);
746 ref = IMFTopologyNode_Release(node);
747 ok(ref == 0, "Release returned %ld\n", ref);
749 /* Tee node. */
750 hr = MFCreateTopologyNode(MF_TOPOLOGY_TEE_NODE, &node);
751 ok(hr == S_OK, "Failed to create a node, hr %#lx.\n", hr);
753 hr = IMFTopologyNode_SetInputPrefType(node, 0, mediatype);
754 ok(hr == S_OK, "Failed to set preferred type, hr %#lx.\n", hr);
756 hr = IMFTopologyNode_GetInputPrefType(node, 0, &mediatype2);
757 ok(hr == S_OK, "Failed to get preferred type, hr %#lx.\n", hr);
758 ok(mediatype2 == mediatype, "Unexpected mediatype instance.\n");
759 IMFMediaType_Release(mediatype2);
761 hr = IMFTopologyNode_GetOutputPrefType(node, 0, &mediatype2);
762 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
764 hr = IMFTopologyNode_GetInputCount(node, &io_count);
765 ok(hr == S_OK, "Failed to get output count, hr %#lx.\n", hr);
766 ok(io_count == 0, "Unexpected count %lu.\n", io_count);
768 hr = IMFTopologyNode_SetInputPrefType(node, 1, mediatype);
769 ok(hr == MF_E_INVALIDTYPE, "Unexpected hr %#lx.\n", hr);
771 hr = IMFTopologyNode_SetInputPrefType(node, 3, mediatype);
772 ok(hr == MF_E_INVALIDTYPE, "Unexpected hr %#lx.\n", hr);
774 hr = IMFTopologyNode_SetOutputPrefType(node, 4, mediatype);
775 ok(hr == S_OK, "Failed to set preferred type, hr %#lx.\n", hr);
777 hr = IMFTopologyNode_GetOutputPrefType(node, 0, &mediatype2);
778 ok(hr == E_FAIL, "Unexpected hr %#lx.\n", hr);
780 hr = MFCreateMediaType(&mediatype2);
781 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
783 /* Changing output type does not change input type. */
784 hr = IMFTopologyNode_SetOutputPrefType(node, 4, mediatype2);
785 ok(hr == S_OK, "Failed to set preferred type, hr %#lx.\n", hr);
787 hr = IMFTopologyNode_GetInputPrefType(node, 0, &mediatype3);
788 ok(hr == S_OK, "Failed to get preferred type, hr %#lx.\n", hr);
789 ok(mediatype3 == mediatype, "Unexpected mediatype instance.\n");
790 IMFMediaType_Release(mediatype3);
792 IMFMediaType_Release(mediatype2);
794 hr = IMFTopologyNode_GetInputCount(node, &io_count);
795 ok(hr == S_OK, "Failed to get output count, hr %#lx.\n", hr);
796 ok(io_count == 0, "Unexpected count %lu.\n", io_count);
798 hr = IMFTopologyNode_GetOutputCount(node, &io_count);
799 ok(hr == S_OK, "Failed to get output count, hr %#lx.\n", hr);
800 ok(io_count == 5, "Unexpected count %lu.\n", io_count);
802 ref = IMFTopologyNode_Release(node);
803 ok(ref == 0, "Release returned %ld\n", ref);
805 /* Transform node. */
806 hr = MFCreateTopologyNode(MF_TOPOLOGY_TRANSFORM_NODE, &node);
807 ok(hr == S_OK, "Failed to create a node, hr %#lx.\n", hr);
809 hr = IMFTopologyNode_SetInputPrefType(node, 3, mediatype);
810 ok(hr == S_OK, "Failed to set preferred type, hr %#lx.\n", hr);
812 hr = IMFTopologyNode_GetInputCount(node, &io_count);
813 ok(hr == S_OK, "Failed to get input count, hr %#lx.\n", hr);
814 ok(io_count == 4, "Unexpected count %lu.\n", io_count);
816 hr = IMFTopologyNode_SetOutputPrefType(node, 4, mediatype);
817 ok(hr == S_OK, "Failed to set preferred type, hr %#lx.\n", hr);
819 hr = IMFTopologyNode_GetInputCount(node, &io_count);
820 ok(hr == S_OK, "Failed to get output count, hr %#lx.\n", hr);
821 ok(io_count == 4, "Unexpected count %lu.\n", io_count);
823 hr = IMFTopologyNode_GetOutputCount(node, &io_count);
824 ok(hr == S_OK, "Failed to get output count, hr %#lx.\n", hr);
825 ok(io_count == 5, "Unexpected count %lu.\n", io_count);
827 ref = IMFTopologyNode_Release(node);
828 ok(ref == 0, "Release returned %ld\n", ref);
830 IMFMediaType_Release(mediatype);
832 hr = IMFTopology_GetOutputNodeCollection(topology, &collection);
833 ok(hr == S_OK || broken(hr == E_FAIL) /* before Win8 */, "Failed to get output node collection, hr %#lx.\n", hr);
834 if (SUCCEEDED(hr))
836 ok(!!collection, "Unexpected object pointer.\n");
837 hr = IMFCollection_GetElementCount(collection, &size);
838 ok(hr == S_OK, "Failed to get item count, hr %#lx.\n", hr);
839 ok(size == 1, "Unexpected item count.\n");
840 ref = IMFCollection_Release(collection);
841 ok(ref == 0, "Release returned %ld\n", ref);
844 ref = IMFTopology_Release(topology);
845 ok(ref == 0, "Release returned %ld\n", ref);
847 /* Connect nodes. */
848 hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &node);
849 ok(hr == S_OK, "Failed to create topology node, hr %#lx.\n", hr);
851 hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, &node2);
852 ok(hr == S_OK, "Failed to create topology node, hr %#lx.\n", hr);
854 EXPECT_REF(node, 1);
855 EXPECT_REF(node2, 1);
857 hr = IMFTopologyNode_ConnectOutput(node, 0, node2, 1);
858 ok(hr == S_OK, "Failed to connect nodes, hr %#lx.\n", hr);
860 EXPECT_REF(node, 2);
861 EXPECT_REF(node2, 2);
863 IMFTopologyNode_Release(node);
865 EXPECT_REF(node, 1);
866 EXPECT_REF(node2, 2);
868 IMFTopologyNode_Release(node2);
870 EXPECT_REF(node, 1);
871 EXPECT_REF(node2, 1);
873 hr = IMFTopologyNode_GetNodeType(node2, &node_type);
874 ok(hr == S_OK, "Failed to get node type, hr %#lx.\n", hr);
876 IMFTopologyNode_Release(node);
878 /* Connect within topology. */
879 hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &node);
880 ok(hr == S_OK, "Failed to create topology node, hr %#lx.\n", hr);
882 hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, &node2);
883 ok(hr == S_OK, "Failed to create topology node, hr %#lx.\n", hr);
885 hr = MFCreateTopology(&topology);
886 ok(hr == S_OK, "Failed to create topology, hr %#lx.\n", hr);
888 hr = IMFTopology_AddNode(topology, node);
889 ok(hr == S_OK, "Failed to add a node, hr %#lx.\n", hr);
891 hr = IMFTopology_AddNode(topology, node2);
892 ok(hr == S_OK, "Failed to add a node, hr %#lx.\n", hr);
894 EXPECT_REF(node, 2);
895 EXPECT_REF(node2, 2);
897 hr = IMFTopologyNode_ConnectOutput(node, 0, node2, 1);
898 ok(hr == S_OK, "Failed to connect nodes, hr %#lx.\n", hr);
900 EXPECT_REF(node, 3);
901 EXPECT_REF(node2, 3);
903 hr = IMFTopology_Clear(topology);
904 ok(hr == S_OK, "Failed to clear topology, hr %#lx.\n", hr);
906 EXPECT_REF(node, 1);
907 EXPECT_REF(node2, 1);
909 /* Removing connected node breaks connection. */
910 hr = IMFTopology_AddNode(topology, node);
911 ok(hr == S_OK, "Failed to add a node, hr %#lx.\n", hr);
913 hr = IMFTopology_AddNode(topology, node2);
914 ok(hr == S_OK, "Failed to add a node, hr %#lx.\n", hr);
916 hr = IMFTopologyNode_ConnectOutput(node, 0, node2, 1);
917 ok(hr == S_OK, "Failed to connect nodes, hr %#lx.\n", hr);
919 hr = IMFTopology_RemoveNode(topology, node);
920 ok(hr == S_OK, "Failed to remove a node, hr %#lx.\n", hr);
922 EXPECT_REF(node, 1);
923 EXPECT_REF(node2, 2);
925 hr = IMFTopologyNode_GetOutput(node, 0, &node3, &index);
926 ok(hr == MF_E_NOT_FOUND, "Unexpected hr %#lx.\n", hr);
928 hr = IMFTopology_AddNode(topology, node);
929 ok(hr == S_OK, "Failed to add a node, hr %#lx.\n", hr);
931 hr = IMFTopologyNode_ConnectOutput(node, 0, node2, 1);
932 ok(hr == S_OK, "Failed to connect nodes, hr %#lx.\n", hr);
934 hr = IMFTopology_RemoveNode(topology, node2);
935 ok(hr == S_OK, "Failed to remove a node, hr %#lx.\n", hr);
937 EXPECT_REF(node, 2);
938 EXPECT_REF(node2, 1);
940 IMFTopologyNode_Release(node);
941 IMFTopologyNode_Release(node2);
943 /* Cloning nodes of different types. */
944 hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &node);
945 ok(hr == S_OK, "Failed to create topology node, hr %#lx.\n", hr);
947 hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, &node2);
948 ok(hr == S_OK, "Failed to create topology node, hr %#lx.\n", hr);
950 hr = IMFTopologyNode_CloneFrom(node, node2);
951 ok(hr == MF_E_INVALIDREQUEST, "Unexpected hr %#lx.\n", hr);
953 ref = IMFTopologyNode_Release(node2);
954 ok(ref == 0, "Release returned %ld\n", ref);
956 /* Cloning preferred types. */
957 hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &node2);
958 ok(hr == S_OK, "Failed to create topology node, hr %#lx.\n", hr);
960 hr = MFCreateMediaType(&mediatype);
961 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
963 hr = IMFTopologyNode_SetOutputPrefType(node2, 0, mediatype);
964 ok(hr == S_OK, "Failed to set preferred type, hr %#lx.\n", hr);
966 /* Vista checks for additional attributes. */
967 hr = IMFTopologyNode_CloneFrom(node, node2);
968 ok(hr == S_OK || broken(hr == MF_E_ATTRIBUTENOTFOUND) /* Vista */, "Failed to clone a node, hr %#lx.\n", hr);
970 hr = IMFTopologyNode_GetOutputPrefType(node, 0, &mediatype2);
971 ok(hr == S_OK, "Failed to get preferred type, hr %#lx.\n", hr);
972 ok(mediatype == mediatype2, "Unexpected media type.\n");
974 IMFMediaType_Release(mediatype2);
976 ref = IMFTopologyNode_Release(node2);
977 ok(ref == 0, "Release returned %ld\n", ref);
979 IMFMediaType_Release(mediatype);
981 /* Existing preferred types are not cleared. */
982 hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &node2);
983 ok(hr == S_OK, "Failed to create topology node, hr %#lx.\n", hr);
985 hr = IMFTopologyNode_GetOutputCount(node, &io_count);
986 ok(hr == S_OK, "Failed to get output count, hr %#lx.\n", hr);
987 ok(io_count == 1, "Unexpected output count.\n");
989 hr = IMFTopologyNode_CloneFrom(node, node2);
990 ok(hr == S_OK || broken(hr == MF_E_ATTRIBUTENOTFOUND) /* Vista */, "Failed to clone a node, hr %#lx.\n", hr);
992 hr = IMFTopologyNode_GetOutputCount(node, &io_count);
993 ok(hr == S_OK, "Failed to get output count, hr %#lx.\n", hr);
994 ok(io_count == 1, "Unexpected output count.\n");
996 hr = IMFTopologyNode_GetOutputPrefType(node, 0, &mediatype2);
997 ok(hr == S_OK, "Failed to get preferred type, hr %#lx.\n", hr);
998 ok(!!mediatype2, "Unexpected media type.\n");
999 IMFMediaType_Release(mediatype2);
1001 hr = IMFTopologyNode_CloneFrom(node2, node);
1002 ok(hr == S_OK || broken(hr == MF_E_ATTRIBUTENOTFOUND) /* Vista */, "Failed to clone a node, hr %#lx.\n", hr);
1004 hr = IMFTopologyNode_GetOutputCount(node2, &io_count);
1005 ok(hr == S_OK, "Failed to get output count, hr %#lx.\n", hr);
1006 ok(io_count == 1, "Unexpected output count.\n");
1008 ref = IMFTopologyNode_Release(node2);
1009 ok(ref == 0, "Release returned %ld\n", ref);
1010 ref = IMFTopologyNode_Release(node);
1011 ok(ref == 0, "Release returned %ld\n", ref);
1013 /* Add one node, connect to another that hasn't been added. */
1014 hr = IMFTopology_Clear(topology);
1015 ok(hr == S_OK, "Failed to clear topology, hr %#lx.\n", hr);
1017 hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &node);
1018 ok(hr == S_OK, "Failed to create topology node, hr %#lx.\n", hr);
1020 hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, &node2);
1021 ok(hr == S_OK, "Failed to create topology node, hr %#lx.\n", hr);
1023 hr = IMFTopology_AddNode(topology, node);
1024 ok(hr == S_OK, "Failed to add a node, hr %#lx.\n", hr);
1026 hr = IMFTopology_GetNodeCount(topology, &node_count);
1027 ok(hr == S_OK, "Failed to get node count, hr %#lx.\n", hr);
1028 ok(node_count == 1, "Unexpected node count.\n");
1030 hr = IMFTopologyNode_ConnectOutput(node, 0, node2, 0);
1031 ok(hr == S_OK, "Failed to connect nodes, hr %#lx.\n", hr);
1033 hr = IMFTopology_GetNodeCount(topology, &node_count);
1034 ok(hr == S_OK, "Failed to get node count, hr %#lx.\n", hr);
1035 ok(node_count == 1, "Unexpected node count.\n");
1037 /* Add same node to different topologies. */
1038 hr = IMFTopology_Clear(topology);
1039 ok(hr == S_OK, "Failed to clear topology, hr %#lx.\n", hr);
1041 hr = MFCreateTopology(&topology2);
1042 ok(hr == S_OK, "Failed to create topology, hr %#lx.\n", hr);
1044 hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &node);
1045 ok(hr == S_OK, "Failed to create topology node, hr %#lx.\n", hr);
1047 hr = IMFTopology_AddNode(topology, node);
1048 ok(hr == S_OK, "Failed to add a node, hr %#lx.\n", hr);
1049 EXPECT_REF(node, 2);
1051 hr = IMFTopology_GetNodeCount(topology, &node_count);
1052 ok(hr == S_OK, "Failed to get node count, hr %#lx.\n", hr);
1053 ok(node_count == 1, "Unexpected node count.\n");
1055 hr = IMFTopology_GetNodeCount(topology2, &node_count);
1056 ok(hr == S_OK, "Failed to get node count, hr %#lx.\n", hr);
1057 ok(node_count == 0, "Unexpected node count.\n");
1059 hr = IMFTopology_AddNode(topology2, node);
1060 ok(hr == S_OK, "Failed to add a node, hr %#lx.\n", hr);
1061 EXPECT_REF(node, 3);
1063 hr = IMFTopology_GetNodeCount(topology, &node_count);
1064 ok(hr == S_OK, "Failed to get node count, hr %#lx.\n", hr);
1065 ok(node_count == 1, "Unexpected node count.\n");
1067 hr = IMFTopology_GetNodeCount(topology2, &node_count);
1068 ok(hr == S_OK, "Failed to get node count, hr %#lx.\n", hr);
1069 ok(node_count == 1, "Unexpected node count.\n");
1071 ref = IMFTopology_Release(topology2);
1072 ok(ref == 0, "Release returned %ld\n", ref);
1073 ref = IMFTopology_Release(topology);
1074 ok(ref == 0, "Release returned %ld\n", ref);
1076 ref = IMFTopologyNode_Release(node);
1077 ok(ref == 0, "Release returned %ld\n", ref);
1078 ref = IMFTopologyNode_Release(node2);
1079 ok(ref == 0, "Release returned %ld\n", ref);
1082 static void test_topology_tee_node(void)
1084 IMFTopologyNode *src_node, *tee_node;
1085 IMFMediaType *mediatype, *mediatype2;
1086 IMFTopology *topology;
1087 DWORD count;
1088 HRESULT hr;
1089 LONG ref;
1091 hr = MFCreateTopology(&topology);
1092 ok(hr == S_OK, "Failed to create topology, hr %#lx.\n", hr);
1094 hr = MFCreateMediaType(&mediatype);
1095 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
1097 hr = MFCreateTopologyNode(MF_TOPOLOGY_TEE_NODE, &tee_node);
1098 ok(hr == S_OK, "Failed to create topology node, hr %#lx.\n", hr);
1100 hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &src_node);
1101 ok(hr == S_OK, "Failed to create topology node, hr %#lx.\n", hr);
1103 hr = IMFTopologyNode_SetInputPrefType(tee_node, 0, mediatype);
1104 ok(hr == S_OK, "Failed to set type, hr %#lx.\n", hr);
1106 /* Even though tee node has only one input and source has only one output,
1107 it's possible to connect to higher inputs/outputs. */
1109 /* SRC(0) -> TEE(0) */
1110 hr = IMFTopologyNode_ConnectOutput(src_node, 0, tee_node, 0);
1111 ok(hr == S_OK, "Failed to connect nodes, hr %#lx.\n", hr);
1113 hr = IMFTopologyNode_GetInputCount(tee_node, &count);
1114 ok(hr == S_OK, "Failed to get count, hr %#lx.\n", hr);
1115 ok(count == 1, "Unexpected count %lu.\n", count);
1117 hr = IMFTopologyNode_GetInputPrefType(tee_node, 0, &mediatype2);
1118 ok(hr == S_OK, "Failed to get type, hr %#lx.\n", hr);
1119 ok(mediatype2 == mediatype, "Unexpected type.\n");
1120 IMFMediaType_Release(mediatype2);
1122 /* SRC(0) -> TEE(1) */
1123 hr = IMFTopologyNode_ConnectOutput(src_node, 0, tee_node, 1);
1124 ok(hr == S_OK, "Failed to connect nodes, hr %#lx.\n", hr);
1126 hr = IMFTopologyNode_GetInputCount(tee_node, &count);
1127 ok(hr == S_OK, "Failed to get count, hr %#lx.\n", hr);
1128 ok(count == 2, "Unexpected count %lu.\n", count);
1130 hr = IMFTopologyNode_SetInputPrefType(tee_node, 1, mediatype);
1131 ok(hr == MF_E_INVALIDTYPE, "Unexpected hr %#lx.\n", hr);
1133 /* SRC(1) -> TEE(1) */
1134 hr = IMFTopologyNode_ConnectOutput(src_node, 1, tee_node, 1);
1135 ok(hr == S_OK, "Failed to connect nodes, hr %#lx.\n", hr);
1137 hr = IMFTopologyNode_GetOutputCount(src_node, &count);
1138 ok(hr == S_OK, "Failed to get count, hr %#lx.\n", hr);
1139 ok(count == 2, "Unexpected count %lu.\n", count);
1141 EXPECT_REF(src_node, 2);
1142 EXPECT_REF(tee_node, 2);
1143 hr = IMFTopologyNode_DisconnectOutput(src_node, 1);
1144 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1146 ref = IMFTopologyNode_Release(src_node);
1147 ok(ref == 0, "Release returned %ld\n", ref);
1148 ref = IMFTopologyNode_Release(tee_node);
1149 ok(ref == 0, "Release returned %ld\n", ref);
1151 ref = IMFMediaType_Release(mediatype);
1152 ok(ref == 0, "Release returned %ld\n", ref);
1153 ref = IMFTopology_Release(topology);
1154 ok(ref == 0, "Release returned %ld\n", ref);
1157 static HRESULT WINAPI test_getservice_QI(IMFGetService *iface, REFIID riid, void **obj)
1159 if (IsEqualIID(riid, &IID_IMFGetService) || IsEqualIID(riid, &IID_IUnknown))
1161 *obj = iface;
1162 return S_OK;
1165 *obj = NULL;
1166 return E_NOINTERFACE;
1169 static ULONG WINAPI test_getservice_AddRef(IMFGetService *iface)
1171 return 2;
1174 static ULONG WINAPI test_getservice_Release(IMFGetService *iface)
1176 return 1;
1179 static HRESULT WINAPI test_getservice_GetService(IMFGetService *iface, REFGUID service, REFIID riid, void **obj)
1181 *obj = (void *)0xdeadbeef;
1182 return 0x83eddead;
1185 static const IMFGetServiceVtbl testmfgetservicevtbl =
1187 test_getservice_QI,
1188 test_getservice_AddRef,
1189 test_getservice_Release,
1190 test_getservice_GetService,
1193 static IMFGetService test_getservice = { &testmfgetservicevtbl };
1195 static HRESULT WINAPI testservice_QI(IUnknown *iface, REFIID riid, void **obj)
1197 if (IsEqualIID(riid, &IID_IUnknown))
1199 *obj = iface;
1200 return S_OK;
1203 *obj = NULL;
1205 if (IsEqualIID(riid, &IID_IMFGetService))
1206 return 0x82eddead;
1208 return E_NOINTERFACE;
1211 static HRESULT WINAPI testservice2_QI(IUnknown *iface, REFIID riid, void **obj)
1213 if (IsEqualIID(riid, &IID_IUnknown))
1215 *obj = iface;
1216 return S_OK;
1219 if (IsEqualIID(riid, &IID_IMFGetService))
1221 *obj = &test_getservice;
1222 return S_OK;
1225 *obj = NULL;
1226 return E_NOINTERFACE;
1229 static ULONG WINAPI testservice_AddRef(IUnknown *iface)
1231 return 2;
1234 static ULONG WINAPI testservice_Release(IUnknown *iface)
1236 return 1;
1239 static const IUnknownVtbl testservicevtbl =
1241 testservice_QI,
1242 testservice_AddRef,
1243 testservice_Release,
1246 static const IUnknownVtbl testservice2vtbl =
1248 testservice2_QI,
1249 testservice_AddRef,
1250 testservice_Release,
1253 static IUnknown testservice = { &testservicevtbl };
1254 static IUnknown testservice2 = { &testservice2vtbl };
1256 static void test_MFGetService(void)
1258 IUnknown *unk;
1259 HRESULT hr;
1261 hr = MFGetService(NULL, NULL, NULL, NULL);
1262 ok(hr == E_POINTER, "Unexpected return value %#lx.\n", hr);
1264 unk = (void *)0xdeadbeef;
1265 hr = MFGetService(NULL, NULL, NULL, (void **)&unk);
1266 ok(hr == E_POINTER, "Unexpected return value %#lx.\n", hr);
1267 ok(unk == (void *)0xdeadbeef, "Unexpected out object.\n");
1269 hr = MFGetService(&testservice, NULL, NULL, NULL);
1270 ok(hr == 0x82eddead, "Unexpected return value %#lx.\n", hr);
1272 unk = (void *)0xdeadbeef;
1273 hr = MFGetService(&testservice, NULL, NULL, (void **)&unk);
1274 ok(hr == 0x82eddead, "Unexpected return value %#lx.\n", hr);
1275 ok(unk == (void *)0xdeadbeef, "Unexpected out object.\n");
1277 unk = NULL;
1278 hr = MFGetService(&testservice2, NULL, NULL, (void **)&unk);
1279 ok(hr == 0x83eddead, "Unexpected return value %#lx.\n", hr);
1280 ok(unk == (void *)0xdeadbeef, "Unexpected out object.\n");
1283 static void test_sequencer_source(void)
1285 IMFSequencerSource *seq_source;
1286 HRESULT hr;
1287 LONG ref;
1289 hr = MFStartup(MF_VERSION, MFSTARTUP_FULL);
1290 ok(hr == S_OK, "Startup failure, hr %#lx.\n", hr);
1292 hr = MFCreateSequencerSource(NULL, &seq_source);
1293 ok(hr == S_OK, "Failed to create sequencer source, hr %#lx.\n", hr);
1295 check_interface(seq_source, &IID_IMFMediaSourceTopologyProvider, TRUE);
1297 ref = IMFSequencerSource_Release(seq_source);
1298 ok(ref == 0, "Release returned %ld\n", ref);
1300 hr = MFShutdown();
1301 ok(hr == S_OK, "Shutdown failure, hr %#lx.\n", hr);
1304 struct test_stream_sink
1306 IMFStreamSink IMFStreamSink_iface;
1307 IMFMediaTypeHandler *handler;
1310 static struct test_stream_sink *impl_from_IMFStreamSink(IMFStreamSink *iface)
1312 return CONTAINING_RECORD(iface, struct test_stream_sink, IMFStreamSink_iface);
1315 static HRESULT WINAPI test_stream_sink_QueryInterface(IMFStreamSink *iface, REFIID riid, void **obj)
1317 if (IsEqualIID(riid, &IID_IMFStreamSink)
1318 || IsEqualIID(riid, &IID_IMFMediaEventGenerator)
1319 || IsEqualIID(riid, &IID_IUnknown))
1321 IMFStreamSink_AddRef((*obj = iface));
1322 return S_OK;
1325 *obj = NULL;
1326 return E_NOINTERFACE;
1329 static ULONG WINAPI test_stream_sink_AddRef(IMFStreamSink *iface)
1331 return 2;
1334 static ULONG WINAPI test_stream_sink_Release(IMFStreamSink *iface)
1336 return 1;
1339 static HRESULT WINAPI test_stream_sink_GetEvent(IMFStreamSink *iface, DWORD flags, IMFMediaEvent **event)
1341 ok(0, "Unexpected call.\n");
1342 return E_NOTIMPL;
1345 static HRESULT WINAPI test_stream_sink_BeginGetEvent(IMFStreamSink *iface, IMFAsyncCallback *callback, IUnknown *state)
1347 ok(0, "Unexpected call.\n");
1348 return E_NOTIMPL;
1351 static HRESULT WINAPI test_stream_sink_EndGetEvent(IMFStreamSink *iface, IMFAsyncResult *result,
1352 IMFMediaEvent **event)
1354 ok(0, "Unexpected call.\n");
1355 return E_NOTIMPL;
1358 static HRESULT WINAPI test_stream_sink_QueueEvent(IMFStreamSink *iface, MediaEventType event_type,
1359 REFGUID ext_type, HRESULT hr, const PROPVARIANT *value)
1361 ok(0, "Unexpected call.\n");
1362 return E_NOTIMPL;
1365 static HRESULT WINAPI test_stream_sink_GetMediaSink(IMFStreamSink *iface, IMFMediaSink **sink)
1367 ok(0, "Unexpected call.\n");
1368 return E_NOTIMPL;
1371 static HRESULT WINAPI test_stream_sink_GetIdentifier(IMFStreamSink *iface, DWORD *id)
1373 ok(0, "Unexpected call.\n");
1374 return E_NOTIMPL;
1377 static HRESULT WINAPI test_stream_sink_GetMediaTypeHandler(IMFStreamSink *iface, IMFMediaTypeHandler **handler)
1379 struct test_stream_sink *impl = impl_from_IMFStreamSink(iface);
1381 if (impl->handler)
1383 IMFMediaTypeHandler_AddRef((*handler = impl->handler));
1384 return S_OK;
1387 ok(0, "Unexpected call.\n");
1388 return E_NOTIMPL;
1391 static HRESULT WINAPI test_stream_sink_ProcessSample(IMFStreamSink *iface, IMFSample *sample)
1393 ok(0, "Unexpected call.\n");
1394 return E_NOTIMPL;
1397 static HRESULT WINAPI test_stream_sink_PlaceMarker(IMFStreamSink *iface, MFSTREAMSINK_MARKER_TYPE marker_type,
1398 const PROPVARIANT *marker_value, const PROPVARIANT *context)
1400 ok(0, "Unexpected call.\n");
1401 return E_NOTIMPL;
1404 static HRESULT WINAPI test_stream_sink_Flush(IMFStreamSink *iface)
1406 ok(0, "Unexpected call.\n");
1407 return E_NOTIMPL;
1410 static const IMFStreamSinkVtbl test_stream_sink_vtbl =
1412 test_stream_sink_QueryInterface,
1413 test_stream_sink_AddRef,
1414 test_stream_sink_Release,
1415 test_stream_sink_GetEvent,
1416 test_stream_sink_BeginGetEvent,
1417 test_stream_sink_EndGetEvent,
1418 test_stream_sink_QueueEvent,
1419 test_stream_sink_GetMediaSink,
1420 test_stream_sink_GetIdentifier,
1421 test_stream_sink_GetMediaTypeHandler,
1422 test_stream_sink_ProcessSample,
1423 test_stream_sink_PlaceMarker,
1424 test_stream_sink_Flush,
1427 static const struct test_stream_sink test_stream_sink = {.IMFStreamSink_iface.lpVtbl = &test_stream_sink_vtbl};
1429 struct test_callback
1431 IMFAsyncCallback IMFAsyncCallback_iface;
1434 static HRESULT WINAPI testcallback_QueryInterface(IMFAsyncCallback *iface, REFIID riid, void **obj)
1436 if (IsEqualIID(riid, &IID_IMFAsyncCallback) ||
1437 IsEqualIID(riid, &IID_IUnknown))
1439 *obj = iface;
1440 IMFAsyncCallback_AddRef(iface);
1441 return S_OK;
1444 *obj = NULL;
1445 return E_NOINTERFACE;
1448 static ULONG WINAPI testcallback_AddRef(IMFAsyncCallback *iface)
1450 return 2;
1453 static ULONG WINAPI testcallback_Release(IMFAsyncCallback *iface)
1455 return 1;
1458 static HRESULT WINAPI testcallback_GetParameters(IMFAsyncCallback *iface, DWORD *flags, DWORD *queue)
1460 ok(flags != NULL && queue != NULL, "Unexpected arguments.\n");
1461 return E_NOTIMPL;
1464 static HRESULT WINAPI testcallback_Invoke(IMFAsyncCallback *iface, IMFAsyncResult *result)
1466 ok(result != NULL, "Unexpected result object.\n");
1468 return E_NOTIMPL;
1471 static const IMFAsyncCallbackVtbl testcallbackvtbl =
1473 testcallback_QueryInterface,
1474 testcallback_AddRef,
1475 testcallback_Release,
1476 testcallback_GetParameters,
1477 testcallback_Invoke,
1480 static void init_test_callback(struct test_callback *callback)
1482 callback->IMFAsyncCallback_iface.lpVtbl = &testcallbackvtbl;
1485 static void test_session_events(IMFMediaSession *session)
1487 struct test_callback callback, callback2;
1488 IMFAsyncResult *result;
1489 IMFMediaEvent *event;
1490 HRESULT hr;
1492 init_test_callback(&callback);
1493 init_test_callback(&callback2);
1495 hr = IMFMediaSession_GetEvent(session, MF_EVENT_FLAG_NO_WAIT, &event);
1496 ok(hr == MF_E_NO_EVENTS_AVAILABLE, "Unexpected hr %#lx.\n", hr);
1498 /* Async case. */
1499 hr = IMFMediaSession_BeginGetEvent(session, NULL, NULL);
1500 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
1502 hr = IMFMediaSession_BeginGetEvent(session, &callback.IMFAsyncCallback_iface, (IUnknown *)session);
1503 ok(hr == S_OK, "Failed to Begin*, hr %#lx.\n", hr);
1505 /* Same callback, same state. */
1506 hr = IMFMediaSession_BeginGetEvent(session, &callback.IMFAsyncCallback_iface, (IUnknown *)session);
1507 ok(hr == MF_S_MULTIPLE_BEGIN, "Unexpected hr %#lx.\n", hr);
1509 /* Same callback, different state. */
1510 hr = IMFMediaSession_BeginGetEvent(session, &callback.IMFAsyncCallback_iface, (IUnknown *)&callback.IMFAsyncCallback_iface);
1511 ok(hr == MF_E_MULTIPLE_BEGIN, "Unexpected hr %#lx.\n", hr);
1513 /* Different callback, same state. */
1514 hr = IMFMediaSession_BeginGetEvent(session, &callback2.IMFAsyncCallback_iface, (IUnknown *)session);
1515 ok(hr == MF_E_MULTIPLE_SUBSCRIBERS, "Unexpected hr %#lx.\n", hr);
1517 /* Different callback, different state. */
1518 hr = IMFMediaSession_BeginGetEvent(session, &callback2.IMFAsyncCallback_iface, (IUnknown *)&callback.IMFAsyncCallback_iface);
1519 ok(hr == MF_E_MULTIPLE_SUBSCRIBERS, "Unexpected hr %#lx.\n", hr);
1521 hr = MFCreateAsyncResult(NULL, &callback.IMFAsyncCallback_iface, NULL, &result);
1522 ok(hr == S_OK, "Failed to create result, hr %#lx.\n", hr);
1524 hr = IMFMediaSession_EndGetEvent(session, result, &event);
1525 ok(hr == E_FAIL, "Unexpected hr %#lx.\n", hr);
1527 /* Shutdown behavior. */
1528 hr = IMFMediaSession_Shutdown(session);
1529 ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr);
1532 static void test_media_session(void)
1534 IMFRateSupport *rate_support;
1535 IMFAttributes *attributes;
1536 IMFMediaSession *session;
1537 MFSHUTDOWN_STATUS status;
1538 IMFTopology *topology;
1539 IMFShutdown *shutdown;
1540 PROPVARIANT propvar;
1541 IMFGetService *gs;
1542 IMFClock *clock;
1543 DWORD caps;
1544 HRESULT hr;
1546 hr = MFStartup(MF_VERSION, MFSTARTUP_FULL);
1547 ok(hr == S_OK, "Startup failure, hr %#lx.\n", hr);
1549 hr = MFCreateMediaSession(NULL, &session);
1550 ok(hr == S_OK, "Failed to create media session, hr %#lx.\n", hr);
1552 check_interface(session, &IID_IMFGetService, TRUE);
1553 check_interface(session, &IID_IMFRateSupport, TRUE);
1554 check_interface(session, &IID_IMFRateControl, TRUE);
1555 check_interface(session, &IID_IMFAttributes, FALSE);
1556 check_interface(session, &IID_IMFTopologyNodeAttributeEditor, FALSE);
1557 check_interface(session, &IID_IMFLocalMFTRegistration, FALSE);
1558 check_service_interface(session, &MF_RATE_CONTROL_SERVICE, &IID_IMFRateSupport, TRUE);
1559 check_service_interface(session, &MF_RATE_CONTROL_SERVICE, &IID_IMFRateControl, TRUE);
1560 check_service_interface(session, &MF_TOPONODE_ATTRIBUTE_EDITOR_SERVICE, &IID_IMFTopologyNodeAttributeEditor, TRUE);
1561 check_service_interface(session, &MF_LOCAL_MFT_REGISTRATION_SERVICE, &IID_IMFLocalMFTRegistration, TRUE);
1563 hr = IMFMediaSession_GetClock(session, &clock);
1564 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1566 hr = IMFClock_QueryInterface(clock, &IID_IMFShutdown, (void **)&shutdown);
1567 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1569 hr = IMFShutdown_GetShutdownStatus(shutdown, &status);
1570 ok(hr == MF_E_INVALIDREQUEST, "Unexpected hr %#lx.\n", hr);
1572 hr = IMFMediaSession_Shutdown(session);
1573 ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr);
1575 check_interface(session, &IID_IMFGetService, TRUE);
1577 hr = IMFMediaSession_QueryInterface(session, &IID_IMFGetService, (void **)&gs);
1578 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1580 hr = IMFGetService_GetService(gs, &MF_RATE_CONTROL_SERVICE, &IID_IMFRateSupport, (void **)&rate_support);
1581 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
1583 IMFGetService_Release(gs);
1585 hr = IMFShutdown_GetShutdownStatus(shutdown, &status);
1586 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1587 ok(status == MFSHUTDOWN_COMPLETED, "Unexpected shutdown status %u.\n", status);
1589 IMFShutdown_Release(shutdown);
1591 hr = IMFMediaSession_ClearTopologies(session);
1592 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
1594 hr = IMFMediaSession_Start(session, &GUID_NULL, NULL);
1595 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
1597 propvar.vt = VT_EMPTY;
1598 hr = IMFMediaSession_Start(session, &GUID_NULL, &propvar);
1599 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
1601 hr = IMFMediaSession_Pause(session);
1602 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
1604 hr = IMFMediaSession_Stop(session);
1605 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
1607 hr = IMFMediaSession_Close(session);
1608 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
1610 hr = IMFMediaSession_GetClock(session, &clock);
1611 ok(hr == MF_E_SHUTDOWN || broken(hr == E_UNEXPECTED) /* Win7 */, "Unexpected hr %#lx.\n", hr);
1613 hr = IMFMediaSession_GetSessionCapabilities(session, &caps);
1614 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
1616 hr = IMFMediaSession_GetSessionCapabilities(session, NULL);
1617 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
1619 hr = IMFMediaSession_GetFullTopology(session, MFSESSION_GETFULLTOPOLOGY_CURRENT, 0, &topology);
1620 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
1622 hr = IMFMediaSession_Shutdown(session);
1623 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
1625 IMFMediaSession_Release(session);
1627 /* Custom topology loader, GUID is not registered. */
1628 hr = MFCreateAttributes(&attributes, 1);
1629 ok(hr == S_OK, "Failed to create attributes, hr %#lx.\n", hr);
1631 hr = IMFAttributes_SetGUID(attributes, &MF_SESSION_TOPOLOADER, &MF_SESSION_TOPOLOADER);
1632 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
1634 hr = MFCreateMediaSession(attributes, &session);
1635 ok(hr == S_OK, "Failed to create media session, hr %#lx.\n", hr);
1636 IMFMediaSession_Release(session);
1638 /* Disabled quality manager. */
1639 hr = IMFAttributes_SetGUID(attributes, &MF_SESSION_QUALITY_MANAGER, &GUID_NULL);
1640 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
1642 hr = MFCreateMediaSession(attributes, &session);
1643 ok(hr == S_OK, "Failed to create media session, hr %#lx.\n", hr);
1644 IMFMediaSession_Release(session);
1646 IMFAttributes_Release(attributes);
1648 /* Basic events behavior. */
1649 hr = MFCreateMediaSession(NULL, &session);
1650 ok(hr == S_OK, "Failed to create media session, hr %#lx.\n", hr);
1652 test_session_events(session);
1654 IMFMediaSession_Release(session);
1656 hr = MFShutdown();
1657 ok(hr == S_OK, "Shutdown failure, hr %#lx.\n", hr);
1660 static void test_media_session_rate_control(void)
1662 IMFRateControl *rate_control, *clock_rate_control;
1663 IMFPresentationClock *presentation_clock;
1664 IMFPresentationTimeSource *time_source;
1665 MFCLOCK_PROPERTIES clock_props;
1666 IMFRateSupport *rate_support;
1667 IMFMediaSession *session;
1668 IMFClock *clock;
1669 HRESULT hr;
1670 float rate;
1671 BOOL thin;
1673 hr = MFStartup(MF_VERSION, MFSTARTUP_FULL);
1674 ok(hr == S_OK, "Startup failure, hr %#lx.\n", hr);
1676 hr = MFCreateMediaSession(NULL, &session);
1677 ok(hr == S_OK, "Failed to create media session, hr %#lx.\n", hr);
1679 hr = MFGetService((IUnknown *)session, &MF_RATE_CONTROL_SERVICE, &IID_IMFRateSupport, (void **)&rate_support);
1680 ok(hr == S_OK, "Failed to get rate support interface, hr %#lx.\n", hr);
1682 hr = MFGetService((IUnknown *)session, &MF_RATE_CONTROL_SERVICE, &IID_IMFRateControl, (void **)&rate_control);
1683 ok(hr == S_OK, "Failed to get rate control interface, hr %#lx.\n", hr);
1685 hr = IMFRateControl_GetRate(rate_control, NULL, NULL);
1686 ok(FAILED(hr), "Unexpected hr %#lx.\n", hr);
1688 rate = 0.0f;
1689 hr = IMFRateControl_GetRate(rate_control, NULL, &rate);
1690 ok(hr == S_OK, "Failed to get playback rate, hr %#lx.\n", hr);
1691 ok(rate == 1.0f, "Unexpected rate %f.\n", rate);
1693 hr = IMFRateControl_GetRate(rate_control, &thin, NULL);
1694 ok(FAILED(hr), "Unexpected hr %#lx.\n", hr);
1696 thin = TRUE;
1697 rate = 0.0f;
1698 hr = IMFRateControl_GetRate(rate_control, &thin, &rate);
1699 ok(hr == S_OK, "Failed to get playback rate, hr %#lx.\n", hr);
1700 ok(!thin, "Unexpected thinning.\n");
1701 ok(rate == 1.0f, "Unexpected rate %f.\n", rate);
1703 hr = IMFMediaSession_GetClock(session, &clock);
1704 ok(hr == S_OK, "Failed to get clock, hr %#lx.\n", hr);
1706 hr = IMFClock_QueryInterface(clock, &IID_IMFPresentationClock, (void **)&presentation_clock);
1707 ok(hr == S_OK, "Failed to get rate control, hr %#lx.\n", hr);
1709 hr = IMFClock_QueryInterface(clock, &IID_IMFRateControl, (void **)&clock_rate_control);
1710 ok(hr == S_OK, "Failed to get rate control, hr %#lx.\n", hr);
1712 rate = 0.0f;
1713 hr = IMFRateControl_GetRate(clock_rate_control, NULL, &rate);
1714 ok(hr == S_OK, "Failed to get clock rate, hr %#lx.\n", hr);
1715 ok(rate == 1.0f, "Unexpected rate %f.\n", rate);
1717 hr = IMFRateControl_SetRate(clock_rate_control, FALSE, 1.5f);
1718 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#lx.\n", hr);
1720 hr = IMFRateControl_SetRate(rate_control, FALSE, 1.5f);
1721 ok(hr == S_OK, "Failed to set rate, hr %#lx.\n", hr);
1723 hr = IMFClock_GetProperties(clock, &clock_props);
1724 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#lx.\n", hr);
1726 hr = MFCreateSystemTimeSource(&time_source);
1727 ok(hr == S_OK, "Failed to create time source, hr %#lx.\n", hr);
1729 hr = IMFPresentationClock_SetTimeSource(presentation_clock, time_source);
1730 ok(hr == S_OK, "Failed to set time source, hr %#lx.\n", hr);
1732 hr = IMFRateControl_SetRate(rate_control, FALSE, 1.5f);
1733 ok(hr == S_OK, "Failed to set rate, hr %#lx.\n", hr);
1735 rate = 0.0f;
1736 hr = IMFRateControl_GetRate(clock_rate_control, NULL, &rate);
1737 ok(hr == S_OK, "Failed to get clock rate, hr %#lx.\n", hr);
1738 ok(rate == 1.0f, "Unexpected rate %f.\n", rate);
1740 IMFPresentationTimeSource_Release(time_source);
1742 IMFRateControl_Release(clock_rate_control);
1743 IMFPresentationClock_Release(presentation_clock);
1744 IMFClock_Release(clock);
1746 IMFRateControl_Release(rate_control);
1747 IMFRateSupport_Release(rate_support);
1749 IMFMediaSession_Release(session);
1751 hr = MFShutdown();
1752 ok(hr == S_OK, "Shutdown failure, hr %#lx.\n", hr);
1755 static HRESULT WINAPI test_grabber_callback_QueryInterface(IMFSampleGrabberSinkCallback *iface, REFIID riid,
1756 void **obj)
1758 if (IsEqualIID(riid, &IID_IMFSampleGrabberSinkCallback) ||
1759 IsEqualIID(riid, &IID_IMFClockStateSink) ||
1760 IsEqualIID(riid, &IID_IUnknown))
1762 *obj = iface;
1763 IMFSampleGrabberSinkCallback_AddRef(iface);
1764 return S_OK;
1767 *obj = NULL;
1768 return E_NOINTERFACE;
1771 static ULONG WINAPI test_grabber_callback_AddRef(IMFSampleGrabberSinkCallback *iface)
1773 return 2;
1776 static ULONG WINAPI test_grabber_callback_Release(IMFSampleGrabberSinkCallback *iface)
1778 return 1;
1781 static HRESULT WINAPI test_grabber_callback_OnClockStart(IMFSampleGrabberSinkCallback *iface, MFTIME systime,
1782 LONGLONG offset)
1784 return E_NOTIMPL;
1787 static HRESULT WINAPI test_grabber_callback_OnClockStop(IMFSampleGrabberSinkCallback *iface, MFTIME systime)
1789 return E_NOTIMPL;
1792 static HRESULT WINAPI test_grabber_callback_OnClockPause(IMFSampleGrabberSinkCallback *iface, MFTIME systime)
1794 return E_NOTIMPL;
1797 static HRESULT WINAPI test_grabber_callback_OnClockRestart(IMFSampleGrabberSinkCallback *iface, MFTIME systime)
1799 return E_NOTIMPL;
1802 static HRESULT WINAPI test_grabber_callback_OnClockSetRate(IMFSampleGrabberSinkCallback *iface, MFTIME systime, float rate)
1804 return E_NOTIMPL;
1807 static HRESULT WINAPI test_grabber_callback_OnSetPresentationClock(IMFSampleGrabberSinkCallback *iface,
1808 IMFPresentationClock *clock)
1810 return E_NOTIMPL;
1813 static HRESULT WINAPI test_grabber_callback_OnProcessSample(IMFSampleGrabberSinkCallback *iface, REFGUID major_type,
1814 DWORD sample_flags, LONGLONG sample_time, LONGLONG sample_duration, const BYTE *buffer, DWORD sample_size)
1816 return E_NOTIMPL;
1819 static HRESULT WINAPI test_grabber_callback_OnShutdown(IMFSampleGrabberSinkCallback *iface)
1821 return E_NOTIMPL;
1824 static const IMFSampleGrabberSinkCallbackVtbl test_grabber_callback_vtbl =
1826 test_grabber_callback_QueryInterface,
1827 test_grabber_callback_AddRef,
1828 test_grabber_callback_Release,
1829 test_grabber_callback_OnClockStart,
1830 test_grabber_callback_OnClockStop,
1831 test_grabber_callback_OnClockPause,
1832 test_grabber_callback_OnClockRestart,
1833 test_grabber_callback_OnClockSetRate,
1834 test_grabber_callback_OnSetPresentationClock,
1835 test_grabber_callback_OnProcessSample,
1836 test_grabber_callback_OnShutdown,
1839 struct test_source
1841 IMFMediaSource IMFMediaSource_iface;
1842 LONG refcount;
1845 static struct test_source *impl_from_IMFMediaSource(IMFMediaSource *iface)
1847 return CONTAINING_RECORD(iface, struct test_source, IMFMediaSource_iface);
1850 static HRESULT WINAPI test_source_QueryInterface(IMFMediaSource *iface, REFIID riid, void **out)
1852 if (IsEqualIID(riid, &IID_IMFMediaSource)
1853 || IsEqualIID(riid, &IID_IMFMediaEventGenerator)
1854 || IsEqualIID(riid, &IID_IUnknown))
1856 *out = iface;
1858 else
1860 *out = NULL;
1861 return E_NOINTERFACE;
1864 IMFMediaSource_AddRef(iface);
1865 return S_OK;
1868 static ULONG WINAPI test_source_AddRef(IMFMediaSource *iface)
1870 struct test_source *source = impl_from_IMFMediaSource(iface);
1871 return InterlockedIncrement(&source->refcount);
1874 static ULONG WINAPI test_source_Release(IMFMediaSource *iface)
1876 struct test_source *source = impl_from_IMFMediaSource(iface);
1877 ULONG refcount = InterlockedDecrement(&source->refcount);
1879 if (!refcount)
1880 free(source);
1882 return refcount;
1885 static HRESULT WINAPI test_source_GetEvent(IMFMediaSource *iface, DWORD flags, IMFMediaEvent **event)
1887 ok(0, "Unexpected call.\n");
1888 return E_NOTIMPL;
1891 static HRESULT WINAPI test_source_BeginGetEvent(IMFMediaSource *iface, IMFAsyncCallback *callback, IUnknown *state)
1893 ok(0, "Unexpected call.\n");
1894 return E_NOTIMPL;
1897 static HRESULT WINAPI test_source_EndGetEvent(IMFMediaSource *iface, IMFAsyncResult *result, IMFMediaEvent **event)
1899 ok(0, "Unexpected call.\n");
1900 return E_NOTIMPL;
1903 static HRESULT WINAPI test_source_QueueEvent(IMFMediaSource *iface, MediaEventType event_type, REFGUID ext_type,
1904 HRESULT hr, const PROPVARIANT *value)
1906 ok(0, "Unexpected call.\n");
1907 return E_NOTIMPL;
1910 static HRESULT WINAPI test_source_GetCharacteristics(IMFMediaSource *iface, DWORD *flags)
1912 ok(0, "Unexpected call.\n");
1913 return E_NOTIMPL;
1916 static HRESULT WINAPI test_source_CreatePresentationDescriptor(IMFMediaSource *iface, IMFPresentationDescriptor **pd)
1918 ok(0, "Unexpected call.\n");
1919 return E_NOTIMPL;
1922 static HRESULT WINAPI test_source_Start(IMFMediaSource *iface, IMFPresentationDescriptor *pd, const GUID *time_format,
1923 const PROPVARIANT *start_position)
1925 ok(0, "Unexpected call.\n");
1926 return E_NOTIMPL;
1929 static HRESULT WINAPI test_source_Stop(IMFMediaSource *iface)
1931 ok(0, "Unexpected call.\n");
1932 return E_NOTIMPL;
1935 static HRESULT WINAPI test_source_Pause(IMFMediaSource *iface)
1937 ok(0, "Unexpected call.\n");
1938 return E_NOTIMPL;
1941 static HRESULT WINAPI test_source_Shutdown(IMFMediaSource *iface)
1943 ok(0, "Unexpected call.\n");
1944 return E_NOTIMPL;
1947 static const IMFMediaSourceVtbl test_source_vtbl =
1949 test_source_QueryInterface,
1950 test_source_AddRef,
1951 test_source_Release,
1952 test_source_GetEvent,
1953 test_source_BeginGetEvent,
1954 test_source_EndGetEvent,
1955 test_source_QueueEvent,
1956 test_source_GetCharacteristics,
1957 test_source_CreatePresentationDescriptor,
1958 test_source_Start,
1959 test_source_Stop,
1960 test_source_Pause,
1961 test_source_Shutdown,
1964 static IMFMediaSource *create_test_source(void)
1966 struct test_source *source;
1968 source = calloc(1, sizeof(*source));
1969 source->IMFMediaSource_iface.lpVtbl = &test_source_vtbl;
1970 source->refcount = 1;
1972 return &source->IMFMediaSource_iface;
1975 static void init_media_type(IMFMediaType *mediatype, const struct attribute_desc *desc, ULONG limit)
1977 HRESULT hr;
1978 ULONG i;
1980 hr = IMFMediaType_DeleteAllItems(mediatype);
1981 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1983 for (i = 0; i < limit && desc[i].key; ++i)
1985 hr = IMFMediaType_SetItem(mediatype, desc[i].key, &desc[i].value);
1986 ok(hr == S_OK, "SetItem %s returned %#lx\n", debugstr_a(desc[i].name), hr);
1990 static void init_source_node(IMFMediaSource *source, MF_CONNECT_METHOD method, IMFTopologyNode *node,
1991 UINT enum_types_count, IMFMediaType **enum_types, const media_type_desc *current_desc)
1993 IMFPresentationDescriptor *pd;
1994 IMFStreamDescriptor *sd;
1995 HRESULT hr;
1997 hr = IMFTopologyNode_DeleteAllItems(node);
1998 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2000 hr = MFCreateStreamDescriptor(0, enum_types_count, enum_types, &sd);
2001 ok(hr == S_OK, "Failed to create stream descriptor, hr %#lx.\n", hr);
2003 hr = MFCreatePresentationDescriptor(1, &sd, &pd);
2004 ok(hr == S_OK, "Failed to create presentation descriptor, hr %#lx.\n", hr);
2006 hr = IMFTopologyNode_SetUnknown(node, &MF_TOPONODE_PRESENTATION_DESCRIPTOR, (IUnknown *)pd);
2007 ok(hr == S_OK, "Failed to set node pd, hr %#lx.\n", hr);
2009 IMFPresentationDescriptor_Release(pd);
2011 hr = IMFTopologyNode_SetUnknown(node, &MF_TOPONODE_STREAM_DESCRIPTOR, (IUnknown *)sd);
2012 ok(hr == S_OK, "Failed to set node sd, hr %#lx.\n", hr);
2014 if (method != -1)
2016 hr = IMFTopologyNode_SetUINT32(node, &MF_TOPONODE_CONNECT_METHOD, method);
2017 ok(hr == S_OK, "Failed to set connect method, hr %#lx.\n", hr);
2020 if (source)
2022 hr = IMFTopologyNode_SetUnknown(node, &MF_TOPONODE_SOURCE, (IUnknown *)source);
2023 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2026 if (current_desc)
2028 IMFMediaTypeHandler *handler;
2029 IMFMediaType *type;
2031 hr = MFCreateMediaType(&type);
2032 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2033 init_media_type(type, *current_desc, -1);
2035 hr = IMFStreamDescriptor_GetMediaTypeHandler(sd, &handler);
2036 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2037 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, type);
2038 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2040 IMFMediaTypeHandler_Release(handler);
2041 IMFMediaType_Release(type);
2044 IMFStreamDescriptor_Release(sd);
2047 static void init_sink_node(IMFActivate *sink_activate, MF_CONNECT_METHOD method, IMFTopologyNode *node)
2049 IMFStreamSink *stream_sink;
2050 IMFMediaSink *sink;
2051 HRESULT hr;
2053 hr = IMFTopologyNode_DeleteAllItems(node);
2054 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2056 hr = IMFActivate_ActivateObject(sink_activate, &IID_IMFMediaSink, (void **)&sink);
2057 ok(hr == S_OK, "Failed to activate, hr %#lx.\n", hr);
2059 hr = IMFMediaSink_GetStreamSinkByIndex(sink, 0, &stream_sink);
2060 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2062 IMFMediaSink_Release(sink);
2064 hr = IMFTopologyNode_SetObject(node, (IUnknown *)stream_sink);
2065 ok(hr == S_OK, "Failed to set object, hr %#lx.\n", hr);
2067 IMFStreamSink_Release(stream_sink);
2069 if (method != -1)
2071 hr = IMFTopologyNode_SetUINT32(node, &MF_TOPONODE_CONNECT_METHOD, method);
2072 ok(hr == S_OK, "Failed to set connect method, hr %#lx.\n", hr);
2076 enum loader_test_flags
2078 LOADER_EXPECTED_DECODER = 0x1,
2079 LOADER_EXPECTED_CONVERTER = 0x2,
2080 LOADER_TODO = 0x4,
2081 LOADER_NEEDS_VIDEO_PROCESSOR = 0x8,
2082 LOADER_SET_ENUMERATE_SOURCE_TYPES = 0x10,
2085 static void test_topology_loader(void)
2087 static const media_type_desc audio_pcm_44100 =
2089 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
2090 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
2091 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 1),
2092 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100),
2093 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 44100),
2094 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 1),
2095 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 8),
2097 static const media_type_desc audio_pcm_48000 =
2099 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
2100 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
2101 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 1),
2102 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 48000),
2103 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 48000),
2104 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 1),
2105 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 8),
2107 static const media_type_desc audio_mp3_44100 =
2109 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
2110 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_MP3),
2111 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
2112 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100),
2113 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 16000),
2114 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 1),
2116 static const media_type_desc audio_pcm_44100_incomplete =
2118 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
2119 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
2120 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 1),
2121 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100),
2122 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 1),
2123 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 8),
2126 const struct loader_test
2128 const media_type_desc *input_type;
2129 const media_type_desc *output_type;
2130 const media_type_desc *current_input;
2131 MF_CONNECT_METHOD source_method;
2132 MF_CONNECT_METHOD sink_method;
2133 HRESULT expected_result;
2134 unsigned int flags;
2136 loader_tests[] =
2139 /* PCM -> PCM, same enumerated type, no current type */
2140 .input_type = &audio_pcm_44100, .output_type = &audio_pcm_44100, .sink_method = MF_CONNECT_DIRECT, .source_method = -1,
2141 .expected_result = S_OK,
2142 .flags = LOADER_TODO,
2145 /* PCM -> PCM, same enumerated type, incomplete current type */
2146 .input_type = &audio_pcm_44100, .output_type = &audio_pcm_44100, .sink_method = MF_CONNECT_DIRECT, .source_method = -1,
2147 .current_input = &audio_pcm_44100_incomplete,
2148 .expected_result = MF_E_INVALIDMEDIATYPE,
2149 .flags = LOADER_TODO,
2152 /* PCM -> PCM, same enumerated bps, different current bps */
2153 .input_type = &audio_pcm_48000, .output_type = &audio_pcm_48000, .sink_method = MF_CONNECT_DIRECT, .source_method = -1,
2154 .current_input = &audio_pcm_44100,
2155 .expected_result = MF_E_INVALIDMEDIATYPE,
2158 /* PCM -> PCM, same enumerated bps, different current bps, force enumerate */
2159 .input_type = &audio_pcm_48000, .output_type = &audio_pcm_48000, .sink_method = MF_CONNECT_DIRECT, .source_method = -1,
2160 .current_input = &audio_pcm_44100,
2161 .expected_result = S_OK,
2162 .flags = LOADER_SET_ENUMERATE_SOURCE_TYPES,
2166 /* PCM -> PCM, incomplete enumerated type, same current type */
2167 .input_type = &audio_pcm_44100_incomplete, .output_type = &audio_pcm_44100, .sink_method = MF_CONNECT_DIRECT, .source_method = -1,
2168 .current_input = &audio_pcm_44100,
2169 .expected_result = S_OK,
2172 /* PCM -> PCM, incomplete enumerated type, same current type, force enumerate */
2173 .input_type = &audio_pcm_44100_incomplete, .output_type = &audio_pcm_44100, .sink_method = MF_CONNECT_DIRECT, .source_method = -1,
2174 .current_input = &audio_pcm_44100,
2175 .expected_result = MF_E_NO_MORE_TYPES,
2176 .flags = LOADER_SET_ENUMERATE_SOURCE_TYPES | LOADER_TODO,
2180 /* PCM -> PCM, different enumerated bps, no current type */
2181 .input_type = &audio_pcm_44100, .output_type = &audio_pcm_48000, .sink_method = MF_CONNECT_DIRECT, .source_method = -1,
2182 .expected_result = MF_E_INVALIDMEDIATYPE,
2183 .flags = LOADER_TODO,
2186 /* PCM -> PCM, different enumerated bps, same current bps */
2187 .input_type = &audio_pcm_44100, .output_type = &audio_pcm_48000, .sink_method = MF_CONNECT_DIRECT, .source_method = -1,
2188 .current_input = &audio_pcm_48000,
2189 .expected_result = S_OK,
2192 /* PCM -> PCM, different enumerated bps, same current bps, force enumerate */
2193 .input_type = &audio_pcm_44100, .output_type = &audio_pcm_48000, .sink_method = MF_CONNECT_DIRECT, .source_method = -1,
2194 .current_input = &audio_pcm_48000,
2195 .expected_result = MF_E_NO_MORE_TYPES,
2196 .flags = LOADER_SET_ENUMERATE_SOURCE_TYPES,
2199 /* PCM -> PCM, different enumerated bps, no current type, sink allow converter */
2200 .input_type = &audio_pcm_44100, .output_type = &audio_pcm_48000, .sink_method = MF_CONNECT_ALLOW_CONVERTER, .source_method = MF_CONNECT_DIRECT,
2201 .expected_result = S_OK,
2202 .flags = LOADER_NEEDS_VIDEO_PROCESSOR | LOADER_EXPECTED_CONVERTER | LOADER_TODO,
2205 /* PCM -> PCM, different enumerated bps, no current type, sink allow decoder */
2206 .input_type = &audio_pcm_44100, .output_type = &audio_pcm_48000, .sink_method = MF_CONNECT_ALLOW_DECODER, .source_method = MF_CONNECT_DIRECT,
2207 .expected_result = S_OK,
2208 .flags = LOADER_NEEDS_VIDEO_PROCESSOR | LOADER_EXPECTED_CONVERTER | LOADER_TODO,
2211 /* PCM -> PCM, different enumerated bps, no current type, default methods */
2212 .input_type = &audio_pcm_44100, .output_type = &audio_pcm_48000, .sink_method = -1, .source_method = -1,
2213 .expected_result = S_OK,
2214 .flags = LOADER_NEEDS_VIDEO_PROCESSOR | LOADER_EXPECTED_CONVERTER | LOADER_TODO,
2217 /* PCM -> PCM, different enumerated bps, no current type, source allow converter */
2218 .input_type = &audio_pcm_44100, .output_type = &audio_pcm_48000, .sink_method = MF_CONNECT_DIRECT, .source_method = MF_CONNECT_ALLOW_CONVERTER,
2219 .expected_result = MF_E_INVALIDMEDIATYPE,
2220 .flags = LOADER_TODO,
2224 /* MP3 -> PCM */
2225 .input_type = &audio_mp3_44100, .output_type = &audio_pcm_44100, .sink_method = MF_CONNECT_DIRECT, .source_method = -1,
2226 .current_input = &audio_mp3_44100,
2227 .expected_result = MF_E_INVALIDMEDIATYPE,
2230 /* MP3 -> PCM, force enumerate */
2231 .input_type = &audio_mp3_44100, .output_type = &audio_pcm_44100, .sink_method = MF_CONNECT_DIRECT, .source_method = -1,
2232 .current_input = &audio_mp3_44100,
2233 .expected_result = MF_E_NO_MORE_TYPES,
2234 .flags = LOADER_SET_ENUMERATE_SOURCE_TYPES,
2237 /* MP3 -> PCM */
2238 .input_type = &audio_mp3_44100, .output_type = &audio_pcm_44100, .sink_method = MF_CONNECT_ALLOW_CONVERTER, .source_method = -1,
2239 .current_input = &audio_mp3_44100,
2240 .expected_result = MF_E_TRANSFORM_NOT_POSSIBLE_FOR_CURRENT_MEDIATYPE_COMBINATION,
2241 .flags = LOADER_NEEDS_VIDEO_PROCESSOR | LOADER_TODO,
2244 /* MP3 -> PCM */
2245 .input_type = &audio_mp3_44100, .output_type = &audio_pcm_44100, .sink_method = MF_CONNECT_ALLOW_DECODER, .source_method = -1,
2246 .current_input = &audio_mp3_44100,
2247 .expected_result = S_OK,
2248 .flags = LOADER_EXPECTED_DECODER | LOADER_TODO,
2252 IMFSampleGrabberSinkCallback test_grabber_callback = { &test_grabber_callback_vtbl };
2253 IMFTopologyNode *src_node, *sink_node, *src_node2, *sink_node2, *mft_node;
2254 IMFTopology *topology, *topology2, *full_topology;
2255 IMFMediaType *media_type, *input_type, *output_type;
2256 IMFPresentationDescriptor *pd;
2257 unsigned int i, count, value;
2258 IMFActivate *sink_activate;
2259 MF_TOPOLOGY_TYPE node_type;
2260 IMFStreamDescriptor *sd;
2261 IMFTransform *transform;
2262 IMFMediaSource *source;
2263 IMFTopoLoader *loader;
2264 IUnknown *node_object;
2265 WORD node_count;
2266 TOPOID node_id;
2267 DWORD index;
2268 HRESULT hr;
2269 BOOL ret;
2270 LONG ref;
2272 hr = MFStartup(MF_VERSION, MFSTARTUP_FULL);
2273 ok(hr == S_OK, "Startup failure, hr %#lx.\n", hr);
2275 hr = MFCreateTopoLoader(NULL);
2276 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
2278 hr = MFCreateTopoLoader(&loader);
2279 ok(hr == S_OK, "Failed to create topology loader, hr %#lx.\n", hr);
2281 hr = MFCreateTopology(&topology);
2282 ok(hr == S_OK, "Failed to create topology, hr %#lx.\n", hr);
2284 /* Empty topology */
2285 hr = IMFTopoLoader_Load(loader, topology, &full_topology, NULL);
2286 todo_wine_if(hr == S_OK)
2287 ok(hr == MF_E_TOPO_UNSUPPORTED, "Unexpected hr %#lx.\n", hr);
2288 if (hr == S_OK) IMFTopology_Release(full_topology);
2290 /* Add source node. */
2291 hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &src_node);
2292 ok(hr == S_OK, "Failed to create topology node, hr %#lx.\n", hr);
2294 /* When a decoder is involved, windows requires this attribute to be present */
2295 source = create_test_source();
2297 hr = IMFTopologyNode_SetUnknown(src_node, &MF_TOPONODE_SOURCE, (IUnknown *)source);
2298 ok(hr == S_OK, "Failed to set node source, hr %#lx.\n", hr);
2300 hr = MFCreateMediaType(&media_type);
2301 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
2303 hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio);
2304 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
2305 hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFAudioFormat_PCM);
2306 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
2308 hr = MFCreateStreamDescriptor(0, 1, &media_type, &sd);
2309 ok(hr == S_OK, "Failed to create stream descriptor, hr %#lx.\n", hr);
2311 hr = IMFTopologyNode_SetUnknown(src_node, &MF_TOPONODE_STREAM_DESCRIPTOR, (IUnknown *)sd);
2312 ok(hr == S_OK, "Failed to set node sd, hr %#lx.\n", hr);
2314 hr = MFCreatePresentationDescriptor(1, &sd, &pd);
2315 ok(hr == S_OK, "Failed to create presentation descriptor, hr %#lx.\n", hr);
2317 hr = IMFTopologyNode_SetUnknown(src_node, &MF_TOPONODE_PRESENTATION_DESCRIPTOR, (IUnknown *)pd);
2318 ok(hr == S_OK, "Failed to set node pd, hr %#lx.\n", hr);
2320 IMFMediaType_Release(media_type);
2322 hr = IMFTopology_AddNode(topology, src_node);
2323 ok(hr == S_OK, "Failed to add a node, hr %#lx.\n", hr);
2325 /* Source node only. */
2326 hr = IMFTopoLoader_Load(loader, topology, &full_topology, NULL);
2327 todo_wine_if(hr == E_INVALIDARG)
2328 ok(hr == MF_E_TOPO_UNSUPPORTED, "Unexpected hr %#lx.\n", hr);
2330 hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, &sink_node);
2331 ok(hr == S_OK, "Failed to create output node, hr %#lx.\n", hr);
2333 hr = MFCreateMediaType(&media_type);
2334 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
2336 hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio);
2337 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
2338 hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFAudioFormat_PCM);
2339 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
2341 hr = MFCreateSampleGrabberSinkActivate(media_type, &test_grabber_callback, &sink_activate);
2342 ok(hr == S_OK, "Failed to create grabber sink, hr %#lx.\n", hr);
2344 hr = IMFTopologyNode_SetObject(sink_node, (IUnknown *)sink_activate);
2345 ok(hr == S_OK, "Failed to set object, hr %#lx.\n", hr);
2347 IMFMediaType_Release(media_type);
2349 hr = IMFTopology_AddNode(topology, sink_node);
2350 ok(hr == S_OK, "Failed to add sink node, hr %#lx.\n", hr);
2352 hr = IMFTopoLoader_Load(loader, topology, &full_topology, NULL);
2353 todo_wine_if(hr == MF_E_TOPO_SINK_ACTIVATES_UNSUPPORTED)
2354 ok(hr == MF_E_TOPO_UNSUPPORTED, "Unexpected hr %#lx.\n", hr);
2356 hr = IMFTopologyNode_ConnectOutput(src_node, 0, sink_node, 0);
2357 ok(hr == S_OK, "Failed to connect nodes, hr %#lx.\n", hr);
2359 /* Sink was not resolved. */
2360 hr = IMFTopoLoader_Load(loader, topology, &full_topology, NULL);
2361 ok(hr == MF_E_TOPO_SINK_ACTIVATES_UNSUPPORTED, "Unexpected hr %#lx.\n", hr);
2363 hr = MFCreateMediaType(&input_type);
2364 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
2366 hr = MFCreateMediaType(&output_type);
2367 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
2369 for (i = 0; i < ARRAY_SIZE(loader_tests); ++i)
2371 const struct loader_test *test = &loader_tests[i];
2373 winetest_push_context("%u", i);
2375 init_media_type(input_type, *test->input_type, -1);
2376 init_media_type(output_type, *test->output_type, -1);
2378 hr = MFCreateSampleGrabberSinkActivate(output_type, &test_grabber_callback, &sink_activate);
2379 ok(hr == S_OK, "Failed to create grabber sink, hr %#lx.\n", hr);
2381 init_source_node(source, test->source_method, src_node, 1, &input_type, test->current_input);
2382 init_sink_node(sink_activate, test->sink_method, sink_node);
2384 hr = IMFTopology_GetCount(topology, &count);
2385 ok(hr == S_OK, "Failed to get attribute count, hr %#lx.\n", hr);
2386 ok(!count, "Unexpected count %u.\n", count);
2388 if (test->flags & LOADER_SET_ENUMERATE_SOURCE_TYPES)
2389 IMFTopology_SetUINT32(topology, &MF_TOPOLOGY_ENUMERATE_SOURCE_TYPES, 1);
2390 hr = IMFTopoLoader_Load(loader, topology, &full_topology, NULL);
2391 IMFTopology_DeleteItem(topology, &MF_TOPOLOGY_ENUMERATE_SOURCE_TYPES);
2393 if (test->flags & LOADER_NEEDS_VIDEO_PROCESSOR && !has_video_processor)
2394 ok(hr == MF_E_INVALIDMEDIATYPE || hr == MF_E_TOPO_CODEC_NOT_FOUND,
2395 "Unexpected hr %#lx\n", hr);
2396 else
2398 todo_wine_if(test->flags & LOADER_TODO)
2399 ok(hr == test->expected_result, "Unexpected hr %#lx\n", hr);
2400 ok(full_topology != topology, "Unexpected instance.\n");
2403 if (test->expected_result != hr)
2405 if (hr != S_OK) ref = 0;
2406 else ref = IMFTopology_Release(full_topology);
2407 ok(ref == 0, "Release returned %ld\n", ref);
2409 else if (test->expected_result == S_OK)
2411 hr = IMFTopology_GetCount(full_topology, &count);
2412 ok(hr == S_OK, "Failed to get attribute count, hr %#lx.\n", hr);
2413 todo_wine
2414 ok(count == (test->flags & LOADER_SET_ENUMERATE_SOURCE_TYPES ? 2 : 1),
2415 "Unexpected count %u.\n", count);
2417 value = 0xdeadbeef;
2418 hr = IMFTopology_GetUINT32(full_topology, &MF_TOPOLOGY_RESOLUTION_STATUS, &value);
2419 todo_wine {
2420 ok(hr == S_OK, "Failed to get attribute, hr %#lx.\n", hr);
2421 ok(value == MF_TOPOLOGY_RESOLUTION_SUCCEEDED, "Unexpected value %#x.\n", value);
2423 count = 2;
2424 if (test->flags & LOADER_EXPECTED_DECODER)
2425 count++;
2426 if (test->flags & LOADER_EXPECTED_CONVERTER)
2427 count++;
2429 hr = IMFTopology_GetNodeCount(full_topology, &node_count);
2430 ok(hr == S_OK, "Failed to get node count, hr %#lx.\n", hr);
2431 todo_wine_if(test->flags & (LOADER_EXPECTED_CONVERTER | LOADER_EXPECTED_DECODER))
2432 ok(node_count == count, "Unexpected node count %u.\n", node_count);
2434 hr = IMFTopologyNode_GetTopoNodeID(src_node, &node_id);
2435 ok(hr == S_OK, "Failed to get source node id, hr %#lx.\n", hr);
2437 hr = IMFTopology_GetNodeByID(full_topology, node_id, &src_node2);
2438 ok(hr == S_OK, "Failed to get source in resolved topology, hr %#lx.\n", hr);
2440 hr = IMFTopologyNode_GetTopoNodeID(sink_node, &node_id);
2441 ok(hr == S_OK, "Failed to get sink node id, hr %#lx.\n", hr);
2443 hr = IMFTopology_GetNodeByID(full_topology, node_id, &sink_node2);
2444 ok(hr == S_OK, "Failed to get sink in resolved topology, hr %#lx.\n", hr);
2446 if (test->flags & (LOADER_EXPECTED_DECODER | LOADER_EXPECTED_CONVERTER) && strcmp(winetest_platform, "wine"))
2448 hr = IMFTopologyNode_GetOutput(src_node2, 0, &mft_node, &index);
2449 ok(hr == S_OK, "Failed to get transform node in resolved topology, hr %#lx.\n", hr);
2450 ok(!index, "Unexpected stream index %lu.\n", index);
2452 hr = IMFTopologyNode_GetNodeType(mft_node, &node_type);
2453 ok(hr == S_OK, "Failed to get transform node type in resolved topology, hr %#lx.\n", hr);
2454 ok(node_type == MF_TOPOLOGY_TRANSFORM_NODE, "Unexpected node type %u.\n", node_type);
2456 hr = IMFTopologyNode_GetObject(mft_node, &node_object);
2457 ok(hr == S_OK, "Failed to get object of transform node, hr %#lx.\n", hr);
2459 if (test->flags & LOADER_EXPECTED_DECODER)
2461 value = 0;
2462 hr = IMFTopologyNode_GetUINT32(mft_node, &MF_TOPONODE_DECODER, &value);
2463 ok(hr == S_OK, "Failed to get attribute, hr %#lx.\n", hr);
2464 ok(value == 1, "Unexpected value.\n");
2467 hr = IMFTopologyNode_GetItem(mft_node, &MF_TOPONODE_TRANSFORM_OBJECTID, NULL);
2468 ok(hr == S_OK, "Failed to get attribute, hr %#lx.\n", hr);
2470 hr = IUnknown_QueryInterface(node_object, &IID_IMFTransform, (void **)&transform);
2471 ok(hr == S_OK, "Failed to get IMFTransform from transform node's object, hr %#lx.\n", hr);
2472 IUnknown_Release(node_object);
2474 hr = IMFTransform_GetInputCurrentType(transform, 0, &media_type);
2475 ok(hr == S_OK, "Failed to get transform input type, hr %#lx.\n", hr);
2477 hr = IMFMediaType_Compare(input_type, (IMFAttributes *)media_type, MF_ATTRIBUTES_MATCH_OUR_ITEMS, &ret);
2478 ok(hr == S_OK, "Failed to compare media types, hr %#lx.\n", hr);
2479 ok(ret, "Input type of first transform doesn't match source node type.\n");
2481 IMFTopologyNode_Release(mft_node);
2482 IMFMediaType_Release(media_type);
2483 IMFTransform_Release(transform);
2485 hr = IMFTopologyNode_GetInput(sink_node2, 0, &mft_node, &index);
2486 ok(hr == S_OK, "Failed to get transform node in resolved topology, hr %#lx.\n", hr);
2487 ok(!index, "Unexpected stream index %lu.\n", index);
2489 hr = IMFTopologyNode_GetNodeType(mft_node, &node_type);
2490 ok(hr == S_OK, "Failed to get transform node type in resolved topology, hr %#lx.\n", hr);
2491 ok(node_type == MF_TOPOLOGY_TRANSFORM_NODE, "Unexpected node type %u.\n", node_type);
2493 hr = IMFTopologyNode_GetItem(mft_node, &MF_TOPONODE_TRANSFORM_OBJECTID, NULL);
2494 ok(hr == S_OK, "Failed to get attribute, hr %#lx.\n", hr);
2496 hr = IMFTopologyNode_GetObject(mft_node, &node_object);
2497 ok(hr == S_OK, "Failed to get object of transform node, hr %#lx.\n", hr);
2499 hr = IUnknown_QueryInterface(node_object, &IID_IMFTransform, (void**) &transform);
2500 ok(hr == S_OK, "Failed to get IMFTransform from transform node's object, hr %#lx.\n", hr);
2501 IUnknown_Release(node_object);
2503 hr = IMFTransform_GetOutputCurrentType(transform, 0, &media_type);
2504 ok(hr == S_OK, "Failed to get transform output type, hr %#lx.\n", hr);
2506 hr = IMFMediaType_Compare(output_type, (IMFAttributes *)media_type, MF_ATTRIBUTES_MATCH_OUR_ITEMS, &ret);
2507 ok(hr == S_OK, "Failed to compare media types, hr %#lx.\n", hr);
2508 ok(ret, "Output type of last transform doesn't match sink node type.\n");
2510 IMFTopologyNode_Release(mft_node);
2511 IMFMediaType_Release(media_type);
2512 IMFTransform_Release(transform);
2515 IMFTopologyNode_Release(src_node2);
2516 IMFTopologyNode_Release(sink_node2);
2518 hr = IMFTopology_SetUINT32(full_topology, &IID_IMFTopology, 123);
2519 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2520 hr = IMFTopoLoader_Load(loader, full_topology, &topology2, NULL);
2521 ok(hr == S_OK, "Failed to resolve topology, hr %#lx.\n", hr);
2522 ok(full_topology != topology2, "Unexpected instance.\n");
2523 hr = IMFTopology_GetUINT32(topology2, &IID_IMFTopology, &value);
2524 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2526 ref = IMFTopology_Release(topology2);
2527 ok(ref == 0, "Release returned %ld\n", ref);
2528 ref = IMFTopology_Release(full_topology);
2529 ok(ref == 0, "Release returned %ld\n", ref);
2532 hr = IMFTopology_GetCount(topology, &count);
2533 ok(hr == S_OK, "Failed to get attribute count, hr %#lx.\n", hr);
2534 ok(!count, "Unexpected count %u.\n", count);
2536 hr = IMFActivate_ShutdownObject(sink_activate);
2537 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2538 ref = IMFActivate_Release(sink_activate);
2539 ok(ref == 0, "Release returned %ld\n", ref);
2541 winetest_pop_context();
2544 ref = IMFTopology_Release(topology);
2545 ok(ref == 0, "Release returned %ld\n", ref);
2546 ref = IMFTopoLoader_Release(loader);
2547 ok(ref == 0, "Release returned %ld\n", ref);
2548 ref = IMFTopologyNode_Release(src_node);
2549 ok(ref == 0, "Release returned %ld\n", ref);
2550 ref = IMFTopologyNode_Release(sink_node);
2551 ok(ref == 0, "Release returned %ld\n", ref);
2553 ref = IMFMediaSource_Release(source);
2554 ok(ref == 0, "Release returned %ld\n", ref);
2556 ref = IMFPresentationDescriptor_Release(pd);
2557 ok(ref == 0, "Release returned %ld\n", ref);
2558 ref = IMFStreamDescriptor_Release(sd);
2559 ok(ref == 0, "Release returned %ld\n", ref);
2561 ref = IMFMediaType_Release(input_type);
2562 ok(ref == 0, "Release returned %ld\n", ref);
2563 /* FIXME: is native really leaking refs here, or are we? */
2564 ref = IMFMediaType_Release(output_type);
2565 todo_wine
2566 ok(ref != 0, "Release returned %ld\n", ref);
2568 hr = MFShutdown();
2569 ok(hr == S_OK, "Shutdown failure, hr %#lx.\n", hr);
2572 static void test_topology_loader_evr(void)
2574 static const media_type_desc media_type_desc =
2576 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
2577 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32),
2578 ATTR_RATIO(MF_MT_FRAME_SIZE, 640, 480),
2579 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE),
2580 {0},
2582 IMFTopologyNode *node, *source_node, *evr_node;
2583 IMFTopology *topology, *full_topology;
2584 IMFMediaTypeHandler *handler;
2585 unsigned int i, count, value;
2586 IMFStreamSink *stream_sink;
2587 IMFMediaType *media_type;
2588 IMFActivate *activate;
2589 IMFTopoLoader *loader;
2590 IMFMediaSink *sink;
2591 WORD node_count;
2592 UINT64 value64;
2593 HWND window;
2594 HRESULT hr;
2595 LONG ref;
2597 hr = CoInitialize(NULL);
2598 ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
2600 hr = MFCreateTopoLoader(&loader);
2601 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2603 /* Source node. */
2604 hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &source_node);
2605 ok(hr == S_OK, "Failed to create topology node, hr %#lx.\n", hr);
2607 hr = MFCreateMediaType(&media_type);
2608 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
2609 init_media_type(media_type, media_type_desc, -1);
2610 init_source_node(NULL, -1, source_node, 1, &media_type, &media_type_desc);
2612 /* EVR sink node. */
2613 window = create_window();
2615 hr = MFCreateVideoRendererActivate(window, &activate);
2616 ok(hr == S_OK, "Failed to create activate object, hr %#lx.\n", hr);
2618 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink);
2619 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2621 hr = IMFMediaSink_GetStreamSinkById(sink, 0, &stream_sink);
2622 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2624 hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, &evr_node);
2625 ok(hr == S_OK, "Failed to create topology node, hr %#lx.\n", hr);
2627 hr = IMFTopologyNode_SetObject(evr_node, (IUnknown *)stream_sink);
2628 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2630 hr = IMFStreamSink_GetMediaTypeHandler(stream_sink, &handler);
2631 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2632 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, media_type);
2633 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2634 IMFMediaTypeHandler_Release(handler);
2636 IMFStreamSink_Release(stream_sink);
2638 hr = MFCreateTopology(&topology);
2639 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2641 hr = IMFTopology_AddNode(topology, source_node);
2642 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2643 hr = IMFTopology_AddNode(topology, evr_node);
2644 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2645 hr = IMFTopologyNode_ConnectOutput(source_node, 0, evr_node, 0);
2646 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2648 hr = IMFTopologyNode_SetUINT32(evr_node, &MF_TOPONODE_CONNECT_METHOD, MF_CONNECT_DIRECT);
2649 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2651 hr = IMFTopologyNode_GetCount(evr_node, &count);
2652 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2653 ok(count == 1, "Unexpected attribute count %u.\n", count);
2655 hr = IMFTopoLoader_Load(loader, topology, &full_topology, NULL);
2656 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2658 hr = IMFTopology_GetNodeCount(full_topology, &node_count);
2659 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2660 ok(node_count == 3, "Unexpected node count %u.\n", node_count);
2662 for (i = 0; i < node_count; ++i)
2664 MF_TOPOLOGY_TYPE node_type;
2666 hr = IMFTopology_GetNode(full_topology, i, &node);
2667 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2669 hr = IMFTopologyNode_GetNodeType(node, &node_type);
2670 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2672 if (node_type == MF_TOPOLOGY_OUTPUT_NODE)
2674 value = 1;
2675 hr = IMFTopologyNode_GetUINT32(node, &MF_TOPONODE_STREAMID, &value);
2676 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2677 ok(!value, "Unexpected stream id %u.\n", value);
2679 else if (node_type == MF_TOPOLOGY_SOURCESTREAM_NODE)
2681 value64 = 1;
2682 hr = IMFTopologyNode_GetUINT64(node, &MF_TOPONODE_MEDIASTART, &value64);
2683 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2684 ok(!value64, "Unexpected value.\n");
2687 IMFTopologyNode_Release(node);
2690 ref = IMFTopology_Release(full_topology);
2691 ok(ref == 0, "Release returned %ld\n", ref);
2692 ref = IMFTopoLoader_Release(loader);
2693 ok(ref == 0, "Release returned %ld\n", ref);
2694 ref = IMFTopology_Release(topology);
2695 ok(ref == 0, "Release returned %ld\n", ref);
2696 ref = IMFTopologyNode_Release(source_node);
2697 ok(ref == 0, "Release returned %ld\n", ref);
2698 ref = IMFTopologyNode_Release(evr_node);
2699 ok(ref == 0, "Release returned %ld\n", ref);
2701 hr = IMFActivate_ShutdownObject(activate);
2702 ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr);
2703 ref = IMFActivate_Release(activate);
2704 ok(ref == 0, "Release returned %ld\n", ref);
2705 ref = IMFMediaSink_Release(sink);
2706 ok(ref == 0, "Release returned %ld\n", ref);
2708 ref = IMFMediaType_Release(media_type);
2709 ok(ref == 0, "Release returned %ld\n", ref);
2711 DestroyWindow(window);
2713 CoUninitialize();
2716 static HRESULT WINAPI testshutdown_QueryInterface(IMFShutdown *iface, REFIID riid, void **obj)
2718 if (IsEqualIID(riid, &IID_IMFShutdown) ||
2719 IsEqualIID(riid, &IID_IUnknown))
2721 *obj = iface;
2722 IMFShutdown_AddRef(iface);
2723 return S_OK;
2726 *obj = NULL;
2727 return E_NOINTERFACE;
2730 static ULONG WINAPI testshutdown_AddRef(IMFShutdown *iface)
2732 return 2;
2735 static ULONG WINAPI testshutdown_Release(IMFShutdown *iface)
2737 return 1;
2740 static HRESULT WINAPI testshutdown_Shutdown(IMFShutdown *iface)
2742 return 0xdead;
2745 static HRESULT WINAPI testshutdown_GetShutdownStatus(IMFShutdown *iface, MFSHUTDOWN_STATUS *status)
2747 ok(0, "Unexpected call.\n");
2748 return E_NOTIMPL;
2751 static const IMFShutdownVtbl testshutdownvtbl =
2753 testshutdown_QueryInterface,
2754 testshutdown_AddRef,
2755 testshutdown_Release,
2756 testshutdown_Shutdown,
2757 testshutdown_GetShutdownStatus,
2760 static void test_MFShutdownObject(void)
2762 IMFShutdown testshutdown = { &testshutdownvtbl };
2763 IUnknown testshutdown2 = { &testservicevtbl };
2764 HRESULT hr;
2766 hr = MFShutdownObject(NULL);
2767 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2769 hr = MFShutdownObject((IUnknown *)&testshutdown);
2770 ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr);
2772 hr = MFShutdownObject(&testshutdown2);
2773 ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr);
2776 enum clock_action
2778 CLOCK_START,
2779 CLOCK_STOP,
2780 CLOCK_PAUSE,
2783 static HRESULT WINAPI test_clock_sink_QueryInterface(IMFClockStateSink *iface, REFIID riid, void **obj)
2785 if (IsEqualIID(riid, &IID_IMFClockStateSink) ||
2786 IsEqualIID(riid, &IID_IUnknown))
2788 *obj = iface;
2789 IMFClockStateSink_AddRef(iface);
2790 return S_OK;
2793 *obj = NULL;
2794 return E_NOINTERFACE;
2797 static ULONG WINAPI test_clock_sink_AddRef(IMFClockStateSink *iface)
2799 return 2;
2802 static ULONG WINAPI test_clock_sink_Release(IMFClockStateSink *iface)
2804 return 1;
2807 static HRESULT WINAPI test_clock_sink_OnClockStart(IMFClockStateSink *iface, MFTIME system_time, LONGLONG offset)
2809 return E_NOTIMPL;
2812 static HRESULT WINAPI test_clock_sink_OnClockStop(IMFClockStateSink *iface, MFTIME system_time)
2814 return E_NOTIMPL;
2817 static HRESULT WINAPI test_clock_sink_OnClockPause(IMFClockStateSink *iface, MFTIME system_time)
2819 return E_NOTIMPL;
2822 static HRESULT WINAPI test_clock_sink_OnClockRestart(IMFClockStateSink *iface, MFTIME system_time)
2824 return E_NOTIMPL;
2827 static HRESULT WINAPI test_clock_sink_OnClockSetRate(IMFClockStateSink *iface, MFTIME system_time, float rate)
2829 return E_NOTIMPL;
2832 static const IMFClockStateSinkVtbl test_clock_sink_vtbl =
2834 test_clock_sink_QueryInterface,
2835 test_clock_sink_AddRef,
2836 test_clock_sink_Release,
2837 test_clock_sink_OnClockStart,
2838 test_clock_sink_OnClockStop,
2839 test_clock_sink_OnClockPause,
2840 test_clock_sink_OnClockRestart,
2841 test_clock_sink_OnClockSetRate,
2844 static void test_presentation_clock(void)
2846 static const struct clock_state_test
2848 enum clock_action action;
2849 MFCLOCK_STATE clock_state;
2850 MFCLOCK_STATE source_state;
2851 HRESULT hr;
2853 clock_state_change[] =
2855 { CLOCK_STOP, MFCLOCK_STATE_STOPPED, MFCLOCK_STATE_INVALID },
2856 { CLOCK_PAUSE, MFCLOCK_STATE_STOPPED, MFCLOCK_STATE_INVALID, MF_E_INVALIDREQUEST },
2857 { CLOCK_STOP, MFCLOCK_STATE_STOPPED, MFCLOCK_STATE_INVALID, MF_E_CLOCK_STATE_ALREADY_SET },
2858 { CLOCK_START, MFCLOCK_STATE_RUNNING, MFCLOCK_STATE_RUNNING },
2859 { CLOCK_START, MFCLOCK_STATE_RUNNING, MFCLOCK_STATE_RUNNING },
2860 { CLOCK_PAUSE, MFCLOCK_STATE_PAUSED, MFCLOCK_STATE_PAUSED },
2861 { CLOCK_PAUSE, MFCLOCK_STATE_PAUSED, MFCLOCK_STATE_PAUSED, MF_E_CLOCK_STATE_ALREADY_SET },
2862 { CLOCK_STOP, MFCLOCK_STATE_STOPPED, MFCLOCK_STATE_STOPPED },
2863 { CLOCK_START, MFCLOCK_STATE_RUNNING, MFCLOCK_STATE_RUNNING },
2864 { CLOCK_STOP, MFCLOCK_STATE_STOPPED, MFCLOCK_STATE_STOPPED },
2865 { CLOCK_STOP, MFCLOCK_STATE_STOPPED, MFCLOCK_STATE_STOPPED, MF_E_CLOCK_STATE_ALREADY_SET },
2866 { CLOCK_PAUSE, MFCLOCK_STATE_STOPPED, MFCLOCK_STATE_STOPPED, MF_E_INVALIDREQUEST },
2867 { CLOCK_START, MFCLOCK_STATE_RUNNING, MFCLOCK_STATE_RUNNING },
2868 { CLOCK_PAUSE, MFCLOCK_STATE_PAUSED, MFCLOCK_STATE_PAUSED },
2869 { CLOCK_START, MFCLOCK_STATE_RUNNING, MFCLOCK_STATE_RUNNING },
2871 IMFClockStateSink test_sink = { &test_clock_sink_vtbl };
2872 IMFPresentationTimeSource *time_source;
2873 MFCLOCK_PROPERTIES props, props2;
2874 IMFRateControl *rate_control;
2875 IMFPresentationClock *clock;
2876 MFSHUTDOWN_STATUS status;
2877 IMFShutdown *shutdown;
2878 MFTIME systime, time;
2879 LONGLONG clock_time;
2880 MFCLOCK_STATE state;
2881 unsigned int i;
2882 DWORD value;
2883 float rate;
2884 HRESULT hr;
2885 BOOL thin;
2887 hr = MFStartup(MF_VERSION, MFSTARTUP_FULL);
2888 ok(hr == S_OK, "Failed to start up, hr %#lx.\n", hr);
2890 hr = MFCreatePresentationClock(&clock);
2891 ok(hr == S_OK, "Failed to create presentation clock, hr %#lx.\n", hr);
2893 check_interface(clock, &IID_IMFTimer, TRUE);
2894 check_interface(clock, &IID_IMFRateControl, TRUE);
2895 check_interface(clock, &IID_IMFPresentationClock, TRUE);
2896 check_interface(clock, &IID_IMFShutdown, TRUE);
2897 check_interface(clock, &IID_IMFClock, TRUE);
2899 hr = IMFPresentationClock_QueryInterface(clock, &IID_IMFRateControl, (void **)&rate_control);
2900 ok(hr == S_OK, "Failed to get rate control interface, hr %#lx.\n", hr);
2902 hr = IMFPresentationClock_GetTimeSource(clock, &time_source);
2903 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#lx.\n", hr);
2905 hr = IMFPresentationClock_GetTimeSource(clock, NULL);
2906 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
2908 hr = IMFPresentationClock_GetClockCharacteristics(clock, &value);
2909 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#lx.\n", hr);
2911 hr = IMFPresentationClock_GetClockCharacteristics(clock, NULL);
2912 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#lx.\n", hr);
2914 hr = IMFPresentationClock_GetTime(clock, &time);
2915 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#lx.\n", hr);
2917 hr = IMFPresentationClock_GetTime(clock, NULL);
2918 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
2920 value = 1;
2921 hr = IMFPresentationClock_GetContinuityKey(clock, &value);
2922 ok(hr == S_OK, "Failed to get continuity key, hr %#lx.\n", hr);
2923 ok(value == 0, "Unexpected value %lu.\n", value);
2925 hr = IMFPresentationClock_GetProperties(clock, &props);
2926 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#lx.\n", hr);
2928 hr = IMFPresentationClock_GetState(clock, 0, &state);
2929 ok(hr == S_OK, "Failed to get state, hr %#lx.\n", hr);
2930 ok(state == MFCLOCK_STATE_INVALID, "Unexpected state %d.\n", state);
2932 hr = IMFPresentationClock_GetCorrelatedTime(clock, 0, &clock_time, &systime);
2933 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#lx.\n", hr);
2935 hr = IMFPresentationClock_GetCorrelatedTime(clock, 0, NULL, &systime);
2936 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#lx.\n", hr);
2938 hr = IMFPresentationClock_GetCorrelatedTime(clock, 0, &time, NULL);
2939 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#lx.\n", hr);
2941 /* Sinks. */
2942 hr = IMFPresentationClock_AddClockStateSink(clock, NULL);
2943 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
2945 hr = IMFPresentationClock_AddClockStateSink(clock, &test_sink);
2946 ok(hr == S_OK, "Failed to add a sink, hr %#lx.\n", hr);
2948 hr = IMFPresentationClock_AddClockStateSink(clock, &test_sink);
2949 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
2951 hr = IMFPresentationClock_RemoveClockStateSink(clock, NULL);
2952 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
2954 hr = IMFPresentationClock_RemoveClockStateSink(clock, &test_sink);
2955 ok(hr == S_OK, "Failed to remove sink, hr %#lx.\n", hr);
2957 hr = IMFPresentationClock_RemoveClockStateSink(clock, &test_sink);
2958 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2960 /* State change commands, time source is not set yet. */
2961 hr = IMFPresentationClock_Start(clock, 0);
2962 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#lx.\n", hr);
2964 hr = IMFPresentationClock_Pause(clock);
2965 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#lx.\n", hr);
2967 hr = IMFPresentationClock_Stop(clock);
2968 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#lx.\n", hr);
2970 hr = IMFRateControl_SetRate(rate_control, FALSE, 0.0f);
2971 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#lx.\n", hr);
2973 /* Set default time source. */
2974 hr = MFCreateSystemTimeSource(&time_source);
2975 ok(hr == S_OK, "Failed to create time source, hr %#lx.\n", hr);
2977 hr = IMFPresentationTimeSource_GetClockCharacteristics(time_source, &value);
2978 ok(hr == S_OK, "Failed to get time source flags, hr %#lx.\n", hr);
2979 ok(value == (MFCLOCK_CHARACTERISTICS_FLAG_FREQUENCY_10MHZ | MFCLOCK_CHARACTERISTICS_FLAG_IS_SYSTEM_CLOCK),
2980 "Unexpected clock flags %#lx.\n", value);
2982 hr = IMFPresentationClock_SetTimeSource(clock, time_source);
2983 ok(hr == S_OK, "Failed to set time source, hr %#lx.\n", hr);
2985 hr = IMFPresentationTimeSource_GetProperties(time_source, &props2);
2986 ok(hr == S_OK, "Failed to get time source properties, hr %#lx.\n", hr);
2988 hr = IMFPresentationClock_GetClockCharacteristics(clock, &value);
2989 ok(hr == S_OK, "Failed to get clock flags, hr %#lx.\n", hr);
2990 ok(value == (MFCLOCK_CHARACTERISTICS_FLAG_FREQUENCY_10MHZ | MFCLOCK_CHARACTERISTICS_FLAG_IS_SYSTEM_CLOCK),
2991 "Unexpected clock flags %#lx.\n", value);
2993 hr = IMFPresentationClock_GetProperties(clock, &props);
2994 ok(hr == S_OK, "Failed to get clock properties, hr %#lx.\n", hr);
2995 ok(!memcmp(&props, &props2, sizeof(props)), "Unexpected clock properties.\n");
2997 /* Changing rate at initial state. */
2998 hr = IMFPresentationClock_GetState(clock, 0, &state);
2999 ok(hr == S_OK, "Failed to get clock state, hr %#lx.\n", hr);
3000 ok(state == MFCLOCK_STATE_INVALID, "Unexpected state %d.\n", state);
3002 hr = IMFRateControl_SetRate(rate_control, FALSE, 0.0f);
3003 ok(hr == S_OK, "Failed to set clock rate, hr %#lx.\n", hr);
3004 hr = IMFRateControl_GetRate(rate_control, &thin, &rate);
3005 ok(hr == S_OK, "Failed to get clock rate, hr %#lx.\n", hr);
3006 ok(rate == 0.0f, "Unexpected rate.\n");
3007 hr = IMFRateControl_SetRate(rate_control, FALSE, 1.0f);
3008 ok(hr == S_OK, "Failed to set clock rate, hr %#lx.\n", hr);
3010 /* State changes. */
3011 for (i = 0; i < ARRAY_SIZE(clock_state_change); ++i)
3013 switch (clock_state_change[i].action)
3015 case CLOCK_STOP:
3016 hr = IMFPresentationClock_Stop(clock);
3017 break;
3018 case CLOCK_PAUSE:
3019 hr = IMFPresentationClock_Pause(clock);
3020 break;
3021 case CLOCK_START:
3022 hr = IMFPresentationClock_Start(clock, 0);
3023 break;
3024 default:
3027 ok(hr == clock_state_change[i].hr, "%u: unexpected hr %#lx.\n", i, hr);
3029 hr = IMFPresentationTimeSource_GetState(time_source, 0, &state);
3030 ok(hr == S_OK, "%u: failed to get state, hr %#lx.\n", i, hr);
3031 ok(state == clock_state_change[i].source_state, "%u: unexpected state %d.\n", i, state);
3033 hr = IMFPresentationClock_GetState(clock, 0, &state);
3034 ok(hr == S_OK, "%u: failed to get state, hr %#lx.\n", i, hr);
3035 ok(state == clock_state_change[i].clock_state, "%u: unexpected state %d.\n", i, state);
3038 /* Clock time stamps. */
3039 hr = IMFPresentationClock_Start(clock, 10);
3040 ok(hr == S_OK, "Failed to start presentation clock, hr %#lx.\n", hr);
3042 hr = IMFPresentationClock_Pause(clock);
3043 ok(hr == S_OK, "Failed to pause presentation clock, hr %#lx.\n", hr);
3045 hr = IMFPresentationClock_GetTime(clock, &time);
3046 ok(hr == S_OK, "Failed to get clock time, hr %#lx.\n", hr);
3048 hr = IMFPresentationTimeSource_GetCorrelatedTime(time_source, 0, &clock_time, &systime);
3049 ok(hr == S_OK, "Failed to get time source time, hr %#lx.\n", hr);
3050 ok(time == clock_time, "Unexpected clock time.\n");
3052 hr = IMFPresentationClock_GetCorrelatedTime(clock, 0, &time, &systime);
3053 ok(hr == S_OK, "Failed to get clock time, hr %#lx.\n", hr);
3054 ok(time == clock_time, "Unexpected clock time.\n");
3056 IMFPresentationTimeSource_Release(time_source);
3058 hr = IMFRateControl_GetRate(rate_control, NULL, &rate);
3059 ok(hr == S_OK, "Failed to get clock rate, hr %#lx.\n", hr);
3061 hr = IMFRateControl_GetRate(rate_control, &thin, NULL);
3062 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
3064 hr = IMFRateControl_GetRate(rate_control, &thin, &rate);
3065 ok(hr == S_OK, "Failed to get clock rate, hr %#lx.\n", hr);
3066 ok(rate == 1.0f, "Unexpected rate.\n");
3067 ok(!thin, "Unexpected thinning.\n");
3069 hr = IMFPresentationClock_GetState(clock, 0, &state);
3070 ok(hr == S_OK, "Failed to get clock state, hr %#lx.\n", hr);
3071 ok(state == MFCLOCK_STATE_PAUSED, "Unexpected state %d.\n", state);
3073 hr = IMFPresentationClock_Start(clock, 0);
3074 ok(hr == S_OK, "Failed to stop, hr %#lx.\n", hr);
3076 hr = IMFRateControl_SetRate(rate_control, FALSE, 0.0f);
3077 ok(hr == S_OK, "Failed to set clock rate, hr %#lx.\n", hr);
3078 hr = IMFRateControl_GetRate(rate_control, &thin, &rate);
3079 ok(hr == S_OK, "Failed to get clock rate, hr %#lx.\n", hr);
3080 ok(rate == 0.0f, "Unexpected rate.\n");
3081 hr = IMFRateControl_SetRate(rate_control, FALSE, 1.0f);
3082 ok(hr == S_OK, "Failed to set clock rate, hr %#lx.\n", hr);
3083 hr = IMFRateControl_SetRate(rate_control, FALSE, 0.0f);
3084 ok(hr == S_OK, "Failed to set clock rate, hr %#lx.\n", hr);
3085 hr = IMFRateControl_SetRate(rate_control, FALSE, 0.5f);
3086 ok(hr == S_OK, "Failed to set clock rate, hr %#lx.\n", hr);
3087 hr = IMFRateControl_SetRate(rate_control, TRUE, -1.0f);
3088 ok(hr == MF_E_THINNING_UNSUPPORTED, "Unexpected hr %#lx.\n", hr);
3089 hr = IMFRateControl_SetRate(rate_control, TRUE, 0.0f);
3090 ok(hr == MF_E_THINNING_UNSUPPORTED, "Unexpected hr %#lx.\n", hr);
3091 hr = IMFRateControl_SetRate(rate_control, TRUE, 1.0f);
3092 ok(hr == MF_E_THINNING_UNSUPPORTED, "Unexpected hr %#lx.\n", hr);
3094 hr = IMFPresentationClock_GetState(clock, 0, &state);
3095 ok(hr == S_OK, "Failed to get clock state, hr %#lx.\n", hr);
3096 ok(state == MFCLOCK_STATE_RUNNING, "Unexpected state %d.\n", state);
3098 hr = IMFRateControl_GetRate(rate_control, &thin, &rate);
3099 ok(hr == S_OK, "Failed to get clock rate, hr %#lx.\n", hr);
3100 ok(rate == 0.5f, "Unexpected rate.\n");
3101 ok(!thin, "Unexpected thinning.\n");
3103 IMFRateControl_Release(rate_control);
3105 hr = IMFPresentationClock_QueryInterface(clock, &IID_IMFShutdown, (void **)&shutdown);
3106 ok(hr == S_OK, "Failed to get shutdown interface, hr %#lx.\n", hr);
3108 /* Shutdown behavior. */
3109 hr = IMFShutdown_GetShutdownStatus(shutdown, NULL);
3110 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
3112 hr = IMFShutdown_GetShutdownStatus(shutdown, &status);
3113 ok(hr == MF_E_INVALIDREQUEST, "Unexpected hr %#lx.\n", hr);
3115 hr = IMFShutdown_Shutdown(shutdown);
3116 ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr);
3118 time_source = NULL;
3119 hr = IMFPresentationClock_GetTimeSource(clock, &time_source);
3120 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3121 ok(!!time_source, "Unexpected instance %p.\n", time_source);
3122 IMFPresentationTimeSource_Release(time_source);
3124 hr = IMFPresentationClock_GetTime(clock, &time);
3125 ok(hr == S_OK, "Failed to get time, hr %#lx.\n", hr);
3127 hr = IMFShutdown_GetShutdownStatus(shutdown, &status);
3128 ok(hr == S_OK, "Failed to get status, hr %#lx.\n", hr);
3129 ok(status == MFSHUTDOWN_COMPLETED, "Unexpected status.\n");
3131 hr = IMFPresentationClock_Start(clock, 0);
3132 ok(hr == S_OK, "Failed to start the clock, hr %#lx.\n", hr);
3134 hr = IMFShutdown_GetShutdownStatus(shutdown, &status);
3135 ok(hr == S_OK, "Failed to get status, hr %#lx.\n", hr);
3136 ok(status == MFSHUTDOWN_COMPLETED, "Unexpected status.\n");
3138 hr = IMFShutdown_Shutdown(shutdown);
3139 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3141 IMFShutdown_Release(shutdown);
3143 IMFPresentationClock_Release(clock);
3145 hr = MFShutdown();
3146 ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr);
3149 static HRESULT WINAPI grabber_callback_QueryInterface(IMFSampleGrabberSinkCallback *iface, REFIID riid, void **obj)
3151 if (IsEqualIID(riid, &IID_IMFSampleGrabberSinkCallback) ||
3152 IsEqualIID(riid, &IID_IMFClockStateSink) ||
3153 IsEqualIID(riid, &IID_IUnknown))
3155 *obj = iface;
3156 IMFSampleGrabberSinkCallback_AddRef(iface);
3157 return S_OK;
3160 *obj = NULL;
3161 return E_NOINTERFACE;
3164 static ULONG WINAPI grabber_callback_AddRef(IMFSampleGrabberSinkCallback *iface)
3166 return 2;
3169 static ULONG WINAPI grabber_callback_Release(IMFSampleGrabberSinkCallback *iface)
3171 return 1;
3174 static HRESULT WINAPI grabber_callback_OnClockStart(IMFSampleGrabberSinkCallback *iface, MFTIME time, LONGLONG offset)
3176 return E_NOTIMPL;
3179 static HRESULT WINAPI grabber_callback_OnClockStop(IMFSampleGrabberSinkCallback *iface, MFTIME time)
3181 return E_NOTIMPL;
3184 static HRESULT WINAPI grabber_callback_OnClockPause(IMFSampleGrabberSinkCallback *iface, MFTIME time)
3186 return E_NOTIMPL;
3189 static HRESULT WINAPI grabber_callback_OnClockRestart(IMFSampleGrabberSinkCallback *iface, MFTIME time)
3191 return E_NOTIMPL;
3194 static HRESULT WINAPI grabber_callback_OnClockSetRate(IMFSampleGrabberSinkCallback *iface, MFTIME time, float rate)
3196 return E_NOTIMPL;
3199 static HRESULT WINAPI grabber_callback_OnSetPresentationClock(IMFSampleGrabberSinkCallback *iface,
3200 IMFPresentationClock *clock)
3202 return S_OK;
3205 static HRESULT WINAPI grabber_callback_OnProcessSample(IMFSampleGrabberSinkCallback *iface, REFGUID major_type,
3206 DWORD sample_flags, LONGLONG sample_time, LONGLONG sample_duration, const BYTE *buffer, DWORD sample_size)
3208 return E_NOTIMPL;
3211 static HRESULT WINAPI grabber_callback_OnShutdown(IMFSampleGrabberSinkCallback *iface)
3213 return S_OK;
3216 static const IMFSampleGrabberSinkCallbackVtbl grabber_callback_vtbl =
3218 grabber_callback_QueryInterface,
3219 grabber_callback_AddRef,
3220 grabber_callback_Release,
3221 grabber_callback_OnClockStart,
3222 grabber_callback_OnClockStop,
3223 grabber_callback_OnClockPause,
3224 grabber_callback_OnClockRestart,
3225 grabber_callback_OnClockSetRate,
3226 grabber_callback_OnSetPresentationClock,
3227 grabber_callback_OnProcessSample,
3228 grabber_callback_OnShutdown,
3231 static IMFSampleGrabberSinkCallback grabber_callback = { &grabber_callback_vtbl };
3233 static void test_sample_grabber(void)
3235 IMFMediaType *media_type, *media_type2, *media_type3;
3236 IMFMediaTypeHandler *handler, *handler2;
3237 IMFPresentationTimeSource *time_source;
3238 IMFPresentationClock *clock, *clock2;
3239 IMFStreamSink *stream, *stream2;
3240 IMFRateSupport *rate_support;
3241 IMFMediaEventGenerator *eg;
3242 IMFMediaSink *sink, *sink2;
3243 DWORD flags, count, id;
3244 IMFActivate *activate;
3245 IMFMediaEvent *event;
3246 UINT32 attr_count;
3247 float rate;
3248 HRESULT hr;
3249 GUID guid;
3250 LONG ref;
3252 hr = MFStartup(MF_VERSION, MFSTARTUP_FULL);
3253 ok(hr == S_OK, "Failed to start up, hr %#lx.\n", hr);
3255 hr = MFCreateMediaType(&media_type);
3256 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
3258 hr = MFCreateSampleGrabberSinkActivate(NULL, NULL, &activate);
3259 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
3261 hr = MFCreateSampleGrabberSinkActivate(NULL, &grabber_callback, &activate);
3262 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
3264 hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio);
3265 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3266 hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFAudioFormat_PCM);
3267 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3269 EXPECT_REF(media_type, 1);
3270 hr = MFCreateSampleGrabberSinkActivate(media_type, &grabber_callback, &activate);
3271 ok(hr == S_OK, "Failed to create grabber activate, hr %#lx.\n", hr);
3272 EXPECT_REF(media_type, 2);
3274 hr = IMFActivate_GetCount(activate, &attr_count);
3275 ok(hr == S_OK, "Failed to get attribute count, hr %#lx.\n", hr);
3276 ok(!attr_count, "Unexpected count %u.\n", attr_count);
3278 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink);
3279 ok(hr == S_OK, "Failed to activate object, hr %#lx.\n", hr);
3281 check_interface(sink, &IID_IMFClockStateSink, TRUE);
3282 check_interface(sink, &IID_IMFMediaEventGenerator, TRUE);
3283 check_interface(sink, &IID_IMFGetService, TRUE);
3284 check_interface(sink, &IID_IMFRateSupport, TRUE);
3285 check_service_interface(sink, &MF_RATE_CONTROL_SERVICE, &IID_IMFRateSupport, TRUE);
3287 if (SUCCEEDED(MFGetService((IUnknown *)sink, &MF_RATE_CONTROL_SERVICE, &IID_IMFRateSupport, (void **)&rate_support)))
3289 hr = IMFRateSupport_GetFastestRate(rate_support, MFRATE_FORWARD, FALSE, &rate);
3290 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3291 ok(rate == FLT_MAX, "Unexpected rate %f.\n", rate);
3293 hr = IMFRateSupport_GetFastestRate(rate_support, MFRATE_FORWARD, TRUE, &rate);
3294 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3295 ok(rate == FLT_MAX, "Unexpected rate %f.\n", rate);
3297 hr = IMFRateSupport_GetFastestRate(rate_support, MFRATE_REVERSE, FALSE, &rate);
3298 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3299 ok(rate == -FLT_MAX, "Unexpected rate %f.\n", rate);
3301 hr = IMFRateSupport_GetFastestRate(rate_support, MFRATE_REVERSE, TRUE, &rate);
3302 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3303 ok(rate == -FLT_MAX, "Unexpected rate %f.\n", rate);
3305 hr = IMFRateSupport_GetSlowestRate(rate_support, MFRATE_FORWARD, FALSE, &rate);
3306 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3307 ok(rate == 0.0f, "Unexpected rate %f.\n", rate);
3309 hr = IMFRateSupport_GetSlowestRate(rate_support, MFRATE_FORWARD, TRUE, &rate);
3310 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3311 ok(rate == 0.0f, "Unexpected rate %f.\n", rate);
3313 hr = IMFRateSupport_GetSlowestRate(rate_support, MFRATE_REVERSE, FALSE, &rate);
3314 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3315 ok(rate == 0.0f, "Unexpected rate %f.\n", rate);
3317 hr = IMFRateSupport_GetSlowestRate(rate_support, MFRATE_REVERSE, TRUE, &rate);
3318 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3319 ok(rate == 0.0f, "Unexpected rate %f.\n", rate);
3321 hr = IMFRateSupport_IsRateSupported(rate_support, TRUE, 1.0f, &rate);
3322 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3323 ok(rate == 1.0f, "Unexpected rate %f.\n", rate);
3325 IMFRateSupport_Release(rate_support);
3328 hr = IMFMediaSink_GetCharacteristics(sink, &flags);
3329 ok(hr == S_OK, "Failed to get sink flags, hr %#lx.\n", hr);
3330 ok(flags & MEDIASINK_FIXED_STREAMS, "Unexpected flags %#lx.\n", flags);
3332 hr = IMFMediaSink_GetStreamSinkCount(sink, &count);
3333 ok(hr == S_OK, "Failed to get stream count, hr %#lx.\n", hr);
3334 ok(count == 1, "Unexpected stream count %lu.\n", count);
3336 hr = IMFMediaSink_GetStreamSinkByIndex(sink, 0, &stream);
3337 ok(hr == S_OK, "Failed to get sink stream, hr %#lx.\n", hr);
3339 check_interface(stream, &IID_IMFMediaEventGenerator, TRUE);
3340 check_interface(stream, &IID_IMFMediaTypeHandler, TRUE);
3342 hr = IMFStreamSink_GetIdentifier(stream, &id);
3343 ok(hr == S_OK, "Failed to get stream id, hr %#lx.\n", hr);
3344 ok(id == 0, "Unexpected id %#lx.\n", id);
3346 hr = IMFStreamSink_GetMediaSink(stream, &sink2);
3347 ok(hr == S_OK, "Failed to get media sink, hr %lx.\n", hr);
3348 ok(sink2 == sink, "Unexpected sink.\n");
3349 IMFMediaSink_Release(sink2);
3351 hr = IMFMediaSink_GetStreamSinkByIndex(sink, 1, &stream2);
3352 ok(hr == MF_E_INVALIDINDEX, "Unexpected hr %#lx.\n", hr);
3354 hr = IMFMediaSink_GetStreamSinkById(sink, 1, &stream2);
3355 ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#lx.\n", hr);
3357 hr = IMFMediaSink_AddStreamSink(sink, 1, NULL, &stream2);
3358 ok(hr == MF_E_STREAMSINKS_FIXED, "Unexpected hr %#lx.\n", hr);
3360 hr = IMFMediaSink_RemoveStreamSink(sink, 0);
3361 ok(hr == MF_E_STREAMSINKS_FIXED, "Unexpected hr %#lx.\n", hr);
3363 hr = IMFMediaSink_RemoveStreamSink(sink, 1);
3364 ok(hr == MF_E_STREAMSINKS_FIXED, "Unexpected hr %#lx.\n", hr);
3366 check_interface(sink, &IID_IMFClockStateSink, TRUE);
3368 /* Event generator. */
3369 hr = IMFMediaSink_QueryInterface(sink, &IID_IMFMediaEventGenerator, (void **)&eg);
3370 ok(hr == S_OK, "Failed to get interface, hr %#lx.\n", hr);
3372 hr = IMFMediaEventGenerator_GetEvent(eg, MF_EVENT_FLAG_NO_WAIT, &event);
3373 ok(hr == MF_E_NO_EVENTS_AVAILABLE, "Unexpected hr %#lx.\n", hr);
3375 check_interface(sink, &IID_IMFPresentationTimeSource, FALSE);
3377 hr = IMFStreamSink_QueryInterface(stream, &IID_IMFMediaTypeHandler, (void **)&handler2);
3378 ok(hr == S_OK, "Failed to get handler interface, hr %#lx.\n", hr);
3380 hr = IMFStreamSink_GetMediaTypeHandler(stream, &handler);
3381 ok(hr == S_OK, "Failed to get type handler, hr %#lx.\n", hr);
3382 hr = IMFMediaTypeHandler_GetMediaTypeCount(handler, &count);
3383 ok(hr == S_OK, "Failed to get media type count, hr %#lx.\n", hr);
3384 ok(count == 0, "Unexpected count %lu.\n", count);
3385 ok(handler == handler2, "Unexpected handler.\n");
3387 IMFMediaTypeHandler_Release(handler);
3388 IMFMediaTypeHandler_Release(handler2);
3390 /* Set clock. */
3391 hr = MFCreatePresentationClock(&clock);
3392 ok(hr == S_OK, "Failed to create clock object, hr %#lx.\n", hr);
3394 hr = IMFMediaSink_GetPresentationClock(sink, NULL);
3395 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
3397 hr = IMFMediaSink_GetPresentationClock(sink, &clock2);
3398 ok(hr == MF_E_NO_CLOCK, "Unexpected hr %#lx.\n", hr);
3400 hr = IMFMediaSink_SetPresentationClock(sink, NULL);
3401 ok(hr == S_OK, "Failed to set presentation clock, hr %#lx.\n", hr);
3403 hr = IMFMediaSink_SetPresentationClock(sink, clock);
3404 ok(hr == S_OK, "Failed to set presentation clock, hr %#lx.\n", hr);
3406 hr = MFCreateSystemTimeSource(&time_source);
3407 ok(hr == S_OK, "Failed to create time source, hr %#lx.\n", hr);
3409 hr = IMFPresentationClock_SetTimeSource(clock, time_source);
3410 ok(hr == S_OK, "Failed to set time source, hr %#lx.\n", hr);
3411 IMFPresentationTimeSource_Release(time_source);
3413 hr = IMFMediaSink_GetCharacteristics(sink, &flags);
3414 ok(hr == S_OK, "Failed to get sink flags, hr %#lx.\n", hr);
3416 hr = IMFActivate_ShutdownObject(activate);
3417 ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr);
3419 hr = IMFMediaSink_GetCharacteristics(sink, &flags);
3420 ok(hr == S_OK, "Failed to get sink flags, hr %#lx.\n", hr);
3422 hr = IMFStreamSink_GetMediaTypeHandler(stream, &handler);
3423 ok(hr == S_OK, "Failed to get type handler, hr %#lx.\n", hr);
3425 /* On Win8+ this initialization happens automatically. */
3426 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, media_type);
3427 ok(hr == S_OK, "Failed to set media type, hr %#lx.\n", hr);
3429 hr = IMFMediaTypeHandler_GetMediaTypeCount(handler, NULL);
3430 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
3432 hr = IMFMediaTypeHandler_GetMediaTypeCount(handler, &count);
3433 ok(hr == S_OK, "Failed to get media type count, hr %#lx.\n", hr);
3434 ok(count == 0, "Unexpected count %lu.\n", count);
3436 hr = IMFMediaTypeHandler_GetMajorType(handler, &guid);
3437 ok(hr == S_OK, "Failed to get major type, hr %#lx.\n", hr);
3438 ok(IsEqualGUID(&guid, &MFMediaType_Audio), "Unexpected major type %s.\n", wine_dbgstr_guid(&guid));
3440 hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, &media_type2);
3441 ok(hr == S_OK, "Failed to get current type, hr %#lx.\n", hr);
3442 ok(media_type2 == media_type, "Unexpected media type.\n");
3443 IMFMediaType_Release(media_type2);
3445 hr = MFCreateMediaType(&media_type2);
3446 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
3448 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, media_type2);
3449 ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#lx.\n", hr);
3451 hr = IMFMediaType_SetGUID(media_type2, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio);
3452 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3454 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, media_type2);
3455 ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#lx.\n", hr);
3457 hr = IMFMediaType_SetGUID(media_type2, &MF_MT_SUBTYPE, &MFAudioFormat_Float);
3458 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3460 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, media_type2);
3461 ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#lx.\n", hr);
3463 hr = IMFMediaType_SetGUID(media_type2, &MF_MT_SUBTYPE, &MFAudioFormat_PCM);
3464 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3466 hr = IMFMediaType_SetUINT32(media_type2, &MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100);
3467 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3469 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, media_type2);
3470 ok(hr == S_OK, "Failed to get current type, hr %#lx.\n", hr);
3471 IMFMediaType_Release(media_type);
3473 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, NULL);
3474 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
3476 hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, &media_type);
3477 ok(hr == S_OK, "Failed to get current type, hr %#lx.\n", hr);
3478 ok(media_type2 == media_type, "Unexpected media type.\n");
3479 IMFMediaType_Release(media_type);
3481 hr = IMFMediaTypeHandler_GetMediaTypeByIndex(handler, 0, &media_type);
3482 ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#lx.\n", hr);
3484 hr = IMFMediaTypeHandler_GetMediaTypeByIndex(handler, 0, NULL);
3485 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
3487 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type2, NULL);
3488 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3490 hr = MFCreateMediaType(&media_type);
3491 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
3493 hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio);
3494 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3496 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type, NULL);
3497 ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#lx.\n", hr);
3499 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type, &media_type3);
3500 ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#lx.\n", hr);
3502 hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFAudioFormat_PCM);
3503 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3505 media_type3 = (void *)0xdeadbeef;
3506 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type, &media_type3);
3507 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3508 ok(media_type3 == (void *)0xdeadbeef, "Unexpected media type %p.\n", media_type3);
3510 hr = IMFMediaType_SetUINT32(media_type, &MF_MT_FIXED_SIZE_SAMPLES, 1);
3511 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3513 hr = IMFMediaType_SetUINT32(media_type, &MF_MT_SAMPLE_SIZE, 1024);
3514 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3516 media_type3 = (void *)0xdeadbeef;
3517 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type, &media_type3);
3518 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3519 ok(media_type3 == (void *)0xdeadbeef, "Unexpected media type %p.\n", media_type3);
3521 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, NULL, NULL);
3522 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
3524 hr = IMFMediaEventGenerator_GetEvent(eg, MF_EVENT_FLAG_NO_WAIT, &event);
3525 ok(hr == MF_E_NO_EVENTS_AVAILABLE, "Unexpected hr %#lx.\n", hr);
3527 hr = IMFStreamSink_GetEvent(stream, MF_EVENT_FLAG_NO_WAIT, &event);
3528 ok(hr == MF_E_NO_EVENTS_AVAILABLE, "Unexpected hr %#lx.\n", hr);
3530 EXPECT_REF(clock, 3);
3531 hr = IMFMediaSink_Shutdown(sink);
3532 ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr);
3534 ref = IMFPresentationClock_Release(clock);
3535 ok(ref == 0, "Release returned %ld\n", ref);
3537 hr = IMFMediaEventGenerator_GetEvent(eg, MF_EVENT_FLAG_NO_WAIT, &event);
3538 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
3540 hr = IMFMediaSink_Shutdown(sink);
3541 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
3543 hr = IMFMediaSink_GetCharacteristics(sink, &flags);
3544 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
3546 hr = IMFMediaSink_AddStreamSink(sink, 1, NULL, &stream2);
3547 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
3549 hr = IMFMediaSink_GetStreamSinkCount(sink, &count);
3550 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
3552 hr = IMFMediaSink_GetStreamSinkByIndex(sink, 0, &stream2);
3553 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
3555 hr = IMFStreamSink_GetEvent(stream, MF_EVENT_FLAG_NO_WAIT, &event);
3556 ok(hr == MF_E_STREAMSINK_REMOVED, "Unexpected hr %#lx.\n", hr);
3558 hr = IMFStreamSink_GetMediaSink(stream, &sink2);
3559 ok(hr == MF_E_STREAMSINK_REMOVED, "Unexpected hr %#lx.\n", hr);
3561 id = 1;
3562 hr = IMFStreamSink_GetIdentifier(stream, &id);
3563 ok(hr == MF_E_STREAMSINK_REMOVED, "Unexpected hr %#lx.\n", hr);
3564 ok(id == 1, "Unexpected id %lu.\n", id);
3566 media_type3 = (void *)0xdeadbeef;
3567 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type, &media_type3);
3568 ok(hr == MF_E_STREAMSINK_REMOVED, "Unexpected hr %#lx.\n", hr);
3569 ok(media_type3 == (void *)0xdeadbeef, "Unexpected media type %p.\n", media_type3);
3571 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, NULL, NULL);
3572 ok(hr == MF_E_STREAMSINK_REMOVED, "Unexpected hr %#lx.\n", hr);
3574 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, NULL);
3575 ok(hr == MF_E_STREAMSINK_REMOVED, "Unexpected hr %#lx.\n", hr);
3577 hr = IMFMediaTypeHandler_GetMediaTypeCount(handler, &count);
3578 ok(hr == S_OK, "Failed to get type count, hr %#lx.\n", hr);
3580 ref = IMFMediaType_Release(media_type2);
3581 todo_wine
3582 ok(ref == 0, "Release returned %ld\n", ref);
3583 ref = IMFMediaType_Release(media_type);
3584 ok(ref == 0, "Release returned %ld\n", ref);
3586 hr = IMFMediaTypeHandler_GetMediaTypeByIndex(handler, 0, &media_type);
3587 ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#lx.\n", hr);
3589 hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, &media_type);
3590 ok(hr == MF_E_STREAMSINK_REMOVED, "Unexpected hr %#lx.\n", hr);
3592 hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, NULL);
3593 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
3595 hr = IMFMediaTypeHandler_GetMajorType(handler, NULL);
3596 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
3598 hr = IMFMediaTypeHandler_GetMajorType(handler, &guid);
3599 ok(hr == MF_E_STREAMSINK_REMOVED, "Unexpected hr %#lx.\n", hr);
3601 IMFMediaTypeHandler_Release(handler);
3603 handler = (void *)0xdeadbeef;
3604 hr = IMFStreamSink_GetMediaTypeHandler(stream, &handler);
3605 ok(hr == MF_E_STREAMSINK_REMOVED, "Unexpected hr %#lx.\n", hr);
3606 ok(handler == (void *)0xdeadbeef, "Unexpected pointer.\n");
3608 hr = IMFStreamSink_GetMediaTypeHandler(stream, NULL);
3609 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
3611 IMFMediaEventGenerator_Release(eg);
3612 IMFStreamSink_Release(stream);
3614 ref = IMFActivate_Release(activate);
3615 ok(ref == 0, "Release returned %ld\n", ref);
3616 ref = IMFMediaSink_Release(sink);
3617 ok(ref == 0, "Release returned %ld\n", ref);
3619 /* Rateless mode with MF_SAMPLEGRABBERSINK_IGNORE_CLOCK. */
3620 hr = MFCreateMediaType(&media_type);
3621 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
3623 hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio);
3624 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3625 hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFAudioFormat_PCM);
3626 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3628 hr = MFCreateSampleGrabberSinkActivate(media_type, &grabber_callback, &activate);
3629 ok(hr == S_OK, "Failed to create grabber activate, hr %#lx.\n", hr);
3631 hr = IMFActivate_SetUINT32(activate, &MF_SAMPLEGRABBERSINK_IGNORE_CLOCK, 1);
3632 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3634 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink);
3635 ok(hr == S_OK, "Failed to activate object, hr %#lx.\n", hr);
3637 hr = IMFMediaSink_GetCharacteristics(sink, &flags);
3638 ok(hr == S_OK, "Failed to get sink flags, hr %#lx.\n", hr);
3639 ok(flags & MEDIASINK_RATELESS, "Unexpected flags %#lx.\n", flags);
3641 hr = IMFActivate_ShutdownObject(activate);
3642 ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr);
3644 /* required for the sink to be fully released */
3645 hr = IMFMediaSink_Shutdown(sink);
3646 ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr);
3648 ref = IMFActivate_Release(activate);
3649 ok(ref == 0, "Release returned %ld\n", ref);
3650 ref = IMFMediaSink_Release(sink);
3651 ok(ref == 0, "Release returned %ld\n", ref);
3653 /* Detaching */
3654 hr = MFCreateSampleGrabberSinkActivate(media_type, &grabber_callback, &activate);
3655 ok(hr == S_OK, "Failed to create grabber activate, hr %#lx.\n", hr);
3657 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink);
3658 ok(hr == S_OK, "Failed to activate object, hr %#lx.\n", hr);
3660 hr = IMFActivate_ShutdownObject(activate);
3661 ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr);
3663 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink2);
3664 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
3666 hr = IMFActivate_GetCount(activate, &attr_count);
3667 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3669 hr = IMFActivate_DetachObject(activate);
3670 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
3672 ref = IMFActivate_Release(activate);
3673 ok(ref == 0, "Release returned %ld\n", ref);
3675 /* required for the sink to be fully released */
3676 hr = IMFMediaSink_Shutdown(sink);
3677 ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr);
3679 ref = IMFMediaSink_Release(sink);
3680 ok(ref == 0, "Release returned %ld\n", ref);
3682 ref = IMFMediaType_Release(media_type);
3683 ok(ref == 0, "Release returned %ld\n", ref);
3685 hr = MFShutdown();
3686 ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr);
3689 static void test_sample_grabber_is_mediatype_supported(void)
3691 IMFMediaType *media_type, *media_type2, *media_type3;
3692 IMFMediaTypeHandler *handler;
3693 IMFActivate *activate;
3694 IMFStreamSink *stream;
3695 IMFMediaSink *sink;
3696 HRESULT hr;
3697 GUID guid;
3698 LONG ref;
3700 /* IsMediaTypeSupported checks are done against the creation type, and check format data */
3701 hr = MFCreateMediaType(&media_type);
3702 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
3704 hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio);
3705 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3706 hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFAudioFormat_PCM);
3707 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3708 hr = IMFMediaType_SetUINT32(media_type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100);
3709 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3711 hr = MFCreateSampleGrabberSinkActivate(media_type, &grabber_callback, &activate);
3712 ok(hr == S_OK, "Failed to create grabber activate, hr %#lx.\n", hr);
3714 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink);
3715 ok(hr == S_OK, "Failed to activate object, hr %#lx.\n", hr);
3717 hr = IMFMediaSink_GetStreamSinkByIndex(sink, 0, &stream);
3718 ok(hr == S_OK, "Failed to get sink stream, hr %#lx.\n", hr);
3719 hr = IMFStreamSink_GetMediaTypeHandler(stream, &handler);
3720 ok(hr == S_OK, "Failed to get type handler, hr %#lx.\n", hr);
3721 IMFStreamSink_Release(stream);
3723 /* On Win8+ this initialization happens automatically. */
3724 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, media_type);
3725 ok(hr == S_OK, "Failed to set media type, hr %#lx.\n", hr);
3727 hr = MFCreateMediaType(&media_type2);
3728 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
3730 hr = IMFMediaType_SetGUID(media_type2, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio);
3731 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3732 hr = IMFMediaType_SetGUID(media_type2, &MF_MT_SUBTYPE, &MFAudioFormat_PCM);
3733 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3734 hr = IMFMediaType_SetUINT32(media_type2, &MF_MT_AUDIO_SAMPLES_PER_SECOND, 48000);
3735 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3737 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type2, NULL);
3738 ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#lx.\n", hr);
3740 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, media_type2);
3741 ok(hr == MF_E_INVALIDMEDIATYPE, "Failed to set media type, hr %#lx.\n", hr);
3743 /* Make it match grabber type sample rate. */
3744 hr = IMFMediaType_SetUINT32(media_type2, &MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100);
3745 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3747 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type2, NULL);
3748 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3750 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, media_type2);
3751 ok(hr == S_OK, "Failed to set media type, hr %#lx.\n", hr);
3752 hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, &media_type3);
3753 ok(hr == S_OK, "Failed to set media type, hr %#lx.\n", hr);
3754 ok(media_type3 == media_type2, "Unexpected media type instance.\n");
3755 IMFMediaType_Release(media_type3);
3757 /* Change original type. */
3758 hr = IMFMediaType_SetUINT32(media_type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, 48000);
3759 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3761 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type2, NULL);
3762 ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#lx.\n", hr);
3764 hr = IMFMediaType_SetUINT32(media_type2, &MF_MT_AUDIO_SAMPLES_PER_SECOND, 48000);
3765 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3767 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type2, NULL);
3768 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3770 hr = IMFMediaTypeHandler_GetMajorType(handler, &guid);
3771 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3772 ok(IsEqualGUID(&guid, &MFMediaType_Audio), "Unexpected major type.\n");
3774 hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
3775 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3777 hr = IMFMediaTypeHandler_GetMajorType(handler, &guid);
3778 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3779 ok(IsEqualGUID(&guid, &MFMediaType_Audio), "Unexpected major type.\n");
3781 IMFMediaTypeHandler_Release(handler);
3783 hr = IMFActivate_ShutdownObject(activate);
3784 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3786 ref = IMFActivate_Release(activate);
3787 ok(ref == 0, "Release returned %ld\n", ref);
3789 /* required for the sink to be fully released */
3790 hr = IMFMediaSink_Shutdown(sink);
3791 ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr);
3793 ref = IMFMediaSink_Release(sink);
3794 ok(ref == 0, "Release returned %ld\n", ref);
3796 ref = IMFMediaType_Release(media_type2);
3797 ok(ref == 0, "Release returned %ld\n", ref);
3798 ref = IMFMediaType_Release(media_type);
3799 ok(ref == 0, "Release returned %ld\n", ref);
3802 static BOOL is_supported_video_type(const GUID *guid)
3804 return IsEqualGUID(guid, &MFVideoFormat_L8)
3805 || IsEqualGUID(guid, &MFVideoFormat_L16)
3806 || IsEqualGUID(guid, &MFVideoFormat_D16)
3807 || IsEqualGUID(guid, &MFVideoFormat_IYUV)
3808 || IsEqualGUID(guid, &MFVideoFormat_YV12)
3809 || IsEqualGUID(guid, &MFVideoFormat_NV12)
3810 || IsEqualGUID(guid, &MFVideoFormat_NV21)
3811 || IsEqualGUID(guid, &MFVideoFormat_420O)
3812 || IsEqualGUID(guid, &MFVideoFormat_P010)
3813 || IsEqualGUID(guid, &MFVideoFormat_P016)
3814 || IsEqualGUID(guid, &MFVideoFormat_UYVY)
3815 || IsEqualGUID(guid, &MFVideoFormat_YUY2)
3816 || IsEqualGUID(guid, &MFVideoFormat_P208)
3817 || IsEqualGUID(guid, &MFVideoFormat_NV11)
3818 || IsEqualGUID(guid, &MFVideoFormat_AYUV)
3819 || IsEqualGUID(guid, &MFVideoFormat_ARGB32)
3820 || IsEqualGUID(guid, &MFVideoFormat_RGB32)
3821 || IsEqualGUID(guid, &MFVideoFormat_A2R10G10B10)
3822 || IsEqualGUID(guid, &MFVideoFormat_A16B16G16R16F)
3823 || IsEqualGUID(guid, &MFVideoFormat_RGB24)
3824 || IsEqualGUID(guid, &MFVideoFormat_I420)
3825 || IsEqualGUID(guid, &MFVideoFormat_YVYU)
3826 || IsEqualGUID(guid, &MFVideoFormat_RGB555)
3827 || IsEqualGUID(guid, &MFVideoFormat_RGB565)
3828 || IsEqualGUID(guid, &MFVideoFormat_RGB8)
3829 || IsEqualGUID(guid, &MFVideoFormat_Y216)
3830 || IsEqualGUID(guid, &MFVideoFormat_v410)
3831 || IsEqualGUID(guid, &MFVideoFormat_Y41P)
3832 || IsEqualGUID(guid, &MFVideoFormat_Y41T)
3833 || IsEqualGUID(guid, &MFVideoFormat_Y42T)
3834 || IsEqualGUID(guid, &MFVideoFormat_ABGR32);
3837 static void test_video_processor(void)
3839 const GUID transform_inputs[22] =
3841 MFVideoFormat_IYUV,
3842 MFVideoFormat_YV12,
3843 MFVideoFormat_NV12,
3844 MFVideoFormat_YUY2,
3845 MFVideoFormat_ARGB32,
3846 MFVideoFormat_RGB32,
3847 MFVideoFormat_NV11,
3848 MFVideoFormat_AYUV,
3849 MFVideoFormat_UYVY,
3850 MEDIASUBTYPE_P208,
3851 MFVideoFormat_RGB24,
3852 MFVideoFormat_RGB555,
3853 MFVideoFormat_RGB565,
3854 MFVideoFormat_RGB8,
3855 MFVideoFormat_I420,
3856 MFVideoFormat_Y216,
3857 MFVideoFormat_v410,
3858 MFVideoFormat_Y41P,
3859 MFVideoFormat_Y41T,
3860 MFVideoFormat_Y42T,
3861 MFVideoFormat_YVYU,
3862 MFVideoFormat_420O,
3864 const GUID transform_outputs[21] =
3866 MFVideoFormat_IYUV,
3867 MFVideoFormat_YV12,
3868 MFVideoFormat_NV12,
3869 MFVideoFormat_YUY2,
3870 MFVideoFormat_ARGB32,
3871 MFVideoFormat_RGB32,
3872 MFVideoFormat_NV11,
3873 MFVideoFormat_AYUV,
3874 MFVideoFormat_UYVY,
3875 MEDIASUBTYPE_P208,
3876 MFVideoFormat_RGB24,
3877 MFVideoFormat_RGB555,
3878 MFVideoFormat_RGB565,
3879 MFVideoFormat_RGB8,
3880 MFVideoFormat_I420,
3881 MFVideoFormat_Y216,
3882 MFVideoFormat_v410,
3883 MFVideoFormat_Y41P,
3884 MFVideoFormat_Y41T,
3885 MFVideoFormat_Y42T,
3886 MFVideoFormat_YVYU,
3888 MFT_REGISTER_TYPE_INFO output_type = {MFMediaType_Video, MFVideoFormat_NV12};
3889 MFT_REGISTER_TYPE_INFO input_type = {MFMediaType_Video, MFVideoFormat_I420};
3890 DWORD input_count, output_count, input_id, output_id, flags;
3891 DWORD input_min, input_max, output_min, output_max, i;
3892 IMFAttributes *attributes, *attributes2;
3893 IMFMediaType *media_type, *media_type2;
3894 MFT_OUTPUT_DATA_BUFFER output_buffer;
3895 MFT_OUTPUT_STREAM_INFO output_info;
3896 MFT_INPUT_STREAM_INFO input_info;
3897 IMFSample *sample, *sample2;
3898 IMFTransform *transform;
3899 IMFMediaBuffer *buffer;
3900 IMFMediaEvent *event;
3901 unsigned int value;
3902 GUID class_id;
3903 UINT32 count;
3904 HRESULT hr;
3905 GUID guid;
3906 LONG ref;
3908 hr = CoInitialize(NULL);
3909 ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
3911 if (!create_transform(MFT_CATEGORY_VIDEO_PROCESSOR, &input_type, &output_type, L"Microsoft Video Processor MFT", &MFMediaType_Video,
3912 transform_inputs, ARRAY_SIZE(transform_inputs), transform_outputs, ARRAY_SIZE(transform_outputs),
3913 &transform, &CLSID_VideoProcessorMFT, &class_id))
3914 goto failed;
3915 has_video_processor = TRUE;
3917 todo_wine
3918 check_interface(transform, &IID_IMFVideoProcessorControl, TRUE);
3919 todo_wine
3920 check_interface(transform, &IID_IMFRealTimeClientEx, TRUE);
3921 check_interface(transform, &IID_IMFMediaEventGenerator, FALSE);
3922 check_interface(transform, &IID_IMFShutdown, FALSE);
3924 /* Transform global attributes. */
3925 hr = IMFTransform_GetAttributes(transform, &attributes);
3926 ok(hr == S_OK, "Failed to get attributes, hr %#lx.\n", hr);
3928 hr = IMFAttributes_GetCount(attributes, &count);
3929 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3930 todo_wine
3931 ok(!!count, "Unexpected attribute count %u.\n", count);
3933 value = 0;
3934 hr = IMFAttributes_GetUINT32(attributes, &MF_SA_D3D11_AWARE, &value);
3935 todo_wine {
3936 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3937 ok(value == 1, "Unexpected attribute value %u.\n", value);
3939 hr = IMFTransform_GetAttributes(transform, &attributes2);
3940 ok(hr == S_OK, "Failed to get attributes, hr %#lx.\n", hr);
3941 ok(attributes == attributes2, "Unexpected instance.\n");
3942 IMFAttributes_Release(attributes);
3943 IMFAttributes_Release(attributes2);
3945 hr = IMFTransform_GetStreamLimits(transform, &input_min, &input_max, &output_min, &output_max);
3946 ok(hr == S_OK, "Failed to get stream limits, hr %#lx.\n", hr);
3947 ok(input_min == input_max && input_min == 1 && output_min == output_max && output_min == 1,
3948 "Unexpected stream limits.\n");
3950 hr = IMFTransform_GetStreamCount(transform, &input_count, &output_count);
3951 ok(hr == S_OK, "Failed to get stream count, hr %#lx.\n", hr);
3952 ok(input_count == 1 && output_count == 1, "Unexpected stream count %lu, %lu.\n", input_count, output_count);
3954 hr = IMFTransform_GetStreamIDs(transform, 1, &input_id, 1, &output_id);
3955 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
3957 input_id = 100;
3958 hr = IMFTransform_AddInputStreams(transform, 1, &input_id);
3959 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
3961 hr = IMFTransform_DeleteInputStream(transform, 0);
3962 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
3964 hr = IMFTransform_GetInputStatus(transform, 0, &flags);
3965 todo_wine
3966 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
3968 hr = IMFTransform_GetInputStreamAttributes(transform, 0, &attributes);
3969 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
3971 hr = IMFTransform_GetOutputStatus(transform, &flags);
3972 todo_wine
3973 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
3975 hr = IMFTransform_GetOutputStreamAttributes(transform, 0, &attributes);
3976 ok(hr == S_OK, "Failed to get output attributes, hr %#lx.\n", hr);
3977 hr = IMFTransform_GetOutputStreamAttributes(transform, 0, &attributes2);
3978 ok(hr == S_OK, "Failed to get output attributes, hr %#lx.\n", hr);
3979 ok(attributes == attributes2, "Unexpected instance.\n");
3980 IMFAttributes_Release(attributes);
3981 IMFAttributes_Release(attributes2);
3983 hr = IMFTransform_GetOutputAvailableType(transform, 0, 0, &media_type);
3984 todo_wine
3985 ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#lx.\n", hr);
3987 hr = IMFTransform_GetInputCurrentType(transform, 0, &media_type);
3988 todo_wine
3989 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
3991 hr = IMFTransform_GetInputCurrentType(transform, 1, &media_type);
3992 todo_wine
3993 ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#lx.\n", hr);
3995 hr = IMFTransform_GetOutputCurrentType(transform, 0, &media_type);
3996 todo_wine
3997 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
3999 hr = IMFTransform_GetOutputCurrentType(transform, 1, &media_type);
4000 todo_wine
4001 ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#lx.\n", hr);
4003 hr = IMFTransform_GetInputStreamInfo(transform, 1, &input_info);
4004 todo_wine
4005 ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#lx.\n", hr);
4007 memset(&input_info, 0xcc, sizeof(input_info));
4008 hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info);
4009 todo_wine {
4010 ok(hr == S_OK, "Failed to get stream info, hr %#lx.\n", hr);
4011 ok(input_info.dwFlags == 0, "Unexpected flag %#lx.\n", input_info.dwFlags);
4012 ok(input_info.cbSize == 0, "Unexpected size %lu.\n", input_info.cbSize);
4013 ok(input_info.cbMaxLookahead == 0, "Unexpected lookahead length %lu.\n", input_info.cbMaxLookahead);
4014 ok(input_info.cbAlignment == 0, "Unexpected alignment %lu.\n", input_info.cbAlignment);
4016 hr = MFCreateMediaEvent(MEUnknown, &GUID_NULL, S_OK, NULL, &event);
4017 ok(hr == S_OK, "Failed to create event object, hr %#lx.\n", hr);
4018 hr = IMFTransform_ProcessEvent(transform, 0, event);
4019 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
4020 hr = IMFTransform_ProcessEvent(transform, 1, event);
4021 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
4022 ref = IMFMediaEvent_Release(event);
4023 ok(ref == 0, "Release returned %ld\n", ref);
4025 /* Configure stream types. */
4026 for (i = 0;;++i)
4028 if (FAILED(hr = IMFTransform_GetInputAvailableType(transform, 0, i, &media_type)))
4030 todo_wine
4031 ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#lx.\n", hr);
4032 break;
4035 hr = IMFTransform_GetInputAvailableType(transform, 0, i, &media_type2);
4036 ok(hr == S_OK, "Failed to get available type, hr %#lx.\n", hr);
4037 ok(media_type != media_type2, "Unexpected instance.\n");
4038 ref = IMFMediaType_Release(media_type2);
4039 ok(ref == 0, "Release returned %ld\n", ref);
4041 hr = IMFMediaType_GetMajorType(media_type, &guid);
4042 ok(hr == S_OK, "Failed to get major type, hr %#lx.\n", hr);
4043 ok(IsEqualGUID(&guid, &MFMediaType_Video), "Unexpected major type.\n");
4045 hr = IMFMediaType_GetCount(media_type, &count);
4046 ok(hr == S_OK, "Failed to get attributes count, hr %#lx.\n", hr);
4047 ok(count == 2, "Unexpected count %u.\n", count);
4049 hr = IMFMediaType_GetGUID(media_type, &MF_MT_SUBTYPE, &guid);
4050 ok(hr == S_OK, "Failed to get subtype, hr %#lx.\n", hr);
4051 ok(is_supported_video_type(&guid), "Unexpected media type %s.\n", wine_dbgstr_guid(&guid));
4053 hr = IMFTransform_SetInputType(transform, 0, media_type, MFT_SET_TYPE_TEST_ONLY);
4054 ok(FAILED(hr), "Unexpected hr %#lx.\n", hr);
4056 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
4057 ok(FAILED(hr), "Unexpected hr %#lx.\n", hr);
4059 hr = IMFTransform_GetOutputCurrentType(transform, 0, &media_type2);
4060 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
4062 /* FIXME: figure out if those require additional attributes or simply advertised but not supported */
4063 if (IsEqualGUID(&guid, &MFVideoFormat_L8) || IsEqualGUID(&guid, &MFVideoFormat_L16)
4064 || IsEqualGUID(&guid, &MFVideoFormat_D16) || IsEqualGUID(&guid, &MFVideoFormat_420O)
4065 || IsEqualGUID(&guid, &MFVideoFormat_A16B16G16R16F))
4067 ref = IMFMediaType_Release(media_type);
4068 ok(ref == 0, "Release returned %ld\n", ref);
4069 continue;
4072 hr = IMFMediaType_SetUINT64(media_type, &MF_MT_FRAME_SIZE, ((UINT64)16 << 32) | 16);
4073 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
4075 hr = IMFTransform_SetInputType(transform, 0, media_type, MFT_SET_TYPE_TEST_ONLY);
4076 ok(hr == S_OK, "Failed to test input type %s, hr %#lx.\n", wine_dbgstr_guid(&guid), hr);
4078 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
4079 ok(hr == S_OK, "Failed to test input type, hr %#lx.\n", hr);
4081 hr = IMFTransform_GetInputCurrentType(transform, 0, &media_type2);
4082 ok(hr == S_OK, "Failed to get current type, hr %#lx.\n", hr);
4083 ok(media_type != media_type2, "Unexpected instance.\n");
4084 IMFMediaType_Release(media_type2);
4086 hr = IMFTransform_GetInputStatus(transform, 0, &flags);
4087 ok(hr == S_OK, "Failed to get input status, hr %#lx.\n", hr);
4088 ok(flags == MFT_INPUT_STATUS_ACCEPT_DATA, "Unexpected input status %#lx.\n", flags);
4090 hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info);
4091 ok(hr == S_OK, "Failed to get stream info, hr %#lx.\n", hr);
4092 ok(input_info.dwFlags == 0, "Unexpected flags %#lx.\n", input_info.dwFlags);
4093 ok(input_info.cbMaxLookahead == 0, "Unexpected lookahead length %lu.\n", input_info.cbMaxLookahead);
4094 ok(input_info.cbAlignment == 0, "Unexpected alignment %lu.\n", input_info.cbAlignment);
4096 IMFMediaType_Release(media_type);
4099 /* IYUV -> RGB32 */
4100 hr = MFCreateMediaType(&media_type);
4101 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
4103 hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
4104 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
4106 hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFVideoFormat_IYUV);
4107 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
4109 hr = IMFMediaType_SetUINT64(media_type, &MF_MT_FRAME_SIZE, ((UINT64)16 << 32) | 16);
4110 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
4112 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
4113 todo_wine
4114 ok(hr == S_OK, "Failed to set input type, hr %#lx.\n", hr);
4116 hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFVideoFormat_RGB32);
4117 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
4119 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
4120 todo_wine
4121 ok(hr == S_OK, "Failed to set output type, hr %#lx.\n", hr);
4123 memset(&output_info, 0, sizeof(output_info));
4124 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
4125 todo_wine
4126 ok(hr == S_OK, "Failed to get stream info, hr %#lx.\n", hr);
4127 ok(output_info.dwFlags == 0, "Unexpected flags %#lx.\n", output_info.dwFlags);
4128 todo_wine
4129 ok(output_info.cbSize > 0, "Unexpected size %lu.\n", output_info.cbSize);
4130 ok(output_info.cbAlignment == 0, "Unexpected alignment %lu.\n", output_info.cbAlignment);
4132 hr = MFCreateSample(&sample);
4133 ok(hr == S_OK, "Failed to create a sample, hr %#lx.\n", hr);
4135 hr = MFCreateSample(&sample2);
4136 ok(hr == S_OK, "Failed to create a sample, hr %#lx.\n", hr);
4138 memset(&output_buffer, 0, sizeof(output_buffer));
4139 output_buffer.pSample = sample;
4140 flags = 0;
4141 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output_buffer, &flags);
4142 todo_wine
4143 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "Unexpected hr %#lx.\n", hr);
4144 ok(output_buffer.dwStatus == 0, "Unexpected buffer status, %#lx.\n", output_buffer.dwStatus);
4145 ok(flags == 0, "Unexpected status %#lx.\n", flags);
4147 hr = IMFTransform_ProcessInput(transform, 0, sample2, 0);
4148 todo_wine
4149 ok(hr == S_OK, "Failed to push a sample, hr %#lx.\n", hr);
4151 hr = IMFTransform_ProcessInput(transform, 0, sample2, 0);
4152 todo_wine
4153 ok(hr == MF_E_NOTACCEPTING, "Unexpected hr %#lx.\n", hr);
4155 memset(&output_buffer, 0, sizeof(output_buffer));
4156 output_buffer.pSample = sample;
4157 flags = 0;
4158 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output_buffer, &flags);
4159 todo_wine
4160 ok(hr == MF_E_NO_SAMPLE_TIMESTAMP, "Unexpected hr %#lx.\n", hr);
4161 ok(output_buffer.dwStatus == 0, "Unexpected buffer status, %#lx.\n", output_buffer.dwStatus);
4162 ok(flags == 0, "Unexpected status %#lx.\n", flags);
4164 hr = IMFSample_SetSampleTime(sample2, 0);
4165 ok(hr == S_OK, "Failed to set sample time, hr %#lx.\n", hr);
4166 memset(&output_buffer, 0, sizeof(output_buffer));
4167 output_buffer.pSample = sample;
4168 flags = 0;
4169 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output_buffer, &flags);
4170 todo_wine
4171 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
4172 ok(output_buffer.dwStatus == 0, "Unexpected buffer status, %#lx.\n", output_buffer.dwStatus);
4173 ok(flags == 0, "Unexpected status %#lx.\n", flags);
4175 hr = MFCreateMemoryBuffer(1024 * 1024, &buffer);
4176 ok(hr == S_OK, "Failed to create a buffer, hr %#lx.\n", hr);
4178 hr = IMFSample_AddBuffer(sample2, buffer);
4179 ok(hr == S_OK, "Failed to add a buffer, hr %#lx.\n", hr);
4181 hr = IMFSample_AddBuffer(sample, buffer);
4182 ok(hr == S_OK, "Failed to add a buffer, hr %#lx.\n", hr);
4184 memset(&output_buffer, 0, sizeof(output_buffer));
4185 output_buffer.pSample = sample;
4186 flags = 0;
4187 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output_buffer, &flags);
4188 todo_wine
4189 ok(hr == S_OK || broken(FAILED(hr)) /* Win8 */, "Failed to get output buffer, hr %#lx.\n", hr);
4190 ok(output_buffer.dwStatus == 0, "Unexpected buffer status, %#lx.\n", output_buffer.dwStatus);
4191 ok(flags == 0, "Unexpected status %#lx.\n", flags);
4193 if (SUCCEEDED(hr))
4195 memset(&output_buffer, 0, sizeof(output_buffer));
4196 output_buffer.pSample = sample;
4197 flags = 0;
4198 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output_buffer, &flags);
4199 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "Unexpected hr %#lx.\n", hr);
4200 ok(output_buffer.dwStatus == 0, "Unexpected buffer status, %#lx.\n", output_buffer.dwStatus);
4201 ok(flags == 0, "Unexpected status %#lx.\n", flags);
4204 ref = IMFTransform_Release(transform);
4205 ok(ref == 0, "Release returned %ld\n", ref);
4207 ref = IMFMediaType_Release(media_type);
4208 ok(ref == 0, "Release returned %ld\n", ref);
4209 ref = IMFSample_Release(sample2);
4210 ok(ref == 0, "Release returned %ld\n", ref);
4211 ref = IMFSample_Release(sample);
4212 ok(ref == 0, "Release returned %ld\n", ref);
4213 ref = IMFMediaBuffer_Release(buffer);
4214 ok(ref == 0, "Release returned %ld\n", ref);
4216 failed:
4217 CoUninitialize();
4220 static void test_quality_manager(void)
4222 IMFPresentationClock *clock;
4223 IMFQualityManager *manager;
4224 IMFTopology *topology;
4225 HRESULT hr;
4226 LONG ref;
4228 hr = MFStartup(MF_VERSION, MFSTARTUP_FULL);
4229 ok(hr == S_OK, "Startup failure, hr %#lx.\n", hr);
4231 hr = MFCreatePresentationClock(&clock);
4232 ok(hr == S_OK, "Failed to create presentation clock, hr %#lx.\n", hr);
4234 hr = MFCreateStandardQualityManager(&manager);
4235 ok(hr == S_OK, "Failed to create quality manager, hr %#lx.\n", hr);
4237 check_interface(manager, &IID_IMFQualityManager, TRUE);
4238 check_interface(manager, &IID_IMFClockStateSink, TRUE);
4240 hr = IMFQualityManager_NotifyPresentationClock(manager, NULL);
4241 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
4243 hr = IMFQualityManager_NotifyTopology(manager, NULL);
4244 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4246 /* Set clock, then shutdown. */
4247 EXPECT_REF(clock, 1);
4248 EXPECT_REF(manager, 1);
4249 hr = IMFQualityManager_NotifyPresentationClock(manager, clock);
4250 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4251 EXPECT_REF(clock, 2);
4252 EXPECT_REF(manager, 2);
4254 hr = IMFQualityManager_Shutdown(manager);
4255 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4256 EXPECT_REF(clock, 1);
4258 hr = IMFQualityManager_NotifyPresentationClock(manager, clock);
4259 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
4261 hr = IMFQualityManager_NotifyTopology(manager, NULL);
4262 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
4264 hr = IMFQualityManager_NotifyPresentationClock(manager, NULL);
4265 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
4267 hr = IMFQualityManager_Shutdown(manager);
4268 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4270 ref = IMFQualityManager_Release(manager);
4271 ok(ref == 0, "Release returned %ld\n", ref);
4273 hr = MFCreateStandardQualityManager(&manager);
4274 ok(hr == S_OK, "Failed to create quality manager, hr %#lx.\n", hr);
4276 EXPECT_REF(clock, 1);
4277 EXPECT_REF(manager, 1);
4278 hr = IMFQualityManager_NotifyPresentationClock(manager, clock);
4279 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4280 EXPECT_REF(manager, 2);
4281 EXPECT_REF(clock, 2);
4282 hr = IMFQualityManager_Shutdown(manager);
4283 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4285 ref = IMFQualityManager_Release(manager);
4286 ok(ref == 0, "Release returned %ld\n", ref);
4287 ref = IMFPresentationClock_Release(clock);
4288 ok(ref == 0, "Release returned %ld\n", ref);
4290 /* Set topology. */
4291 hr = MFCreateStandardQualityManager(&manager);
4292 ok(hr == S_OK, "Failed to create quality manager, hr %#lx.\n", hr);
4294 hr = MFCreateTopology(&topology);
4295 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4297 EXPECT_REF(topology, 1);
4298 hr = IMFQualityManager_NotifyTopology(manager, topology);
4299 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4300 EXPECT_REF(topology, 2);
4302 hr = IMFQualityManager_NotifyTopology(manager, NULL);
4303 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4304 EXPECT_REF(topology, 1);
4306 hr = IMFQualityManager_NotifyTopology(manager, topology);
4307 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4309 EXPECT_REF(topology, 2);
4310 hr = IMFQualityManager_Shutdown(manager);
4311 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4312 EXPECT_REF(topology, 1);
4314 hr = IMFQualityManager_NotifyTopology(manager, topology);
4315 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
4317 ref = IMFQualityManager_Release(manager);
4318 ok(ref == 0, "Release returned %ld\n", ref);
4320 hr = MFCreateStandardQualityManager(&manager);
4321 ok(hr == S_OK, "Failed to create quality manager, hr %#lx.\n", hr);
4323 EXPECT_REF(topology, 1);
4324 hr = IMFQualityManager_NotifyTopology(manager, topology);
4325 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4326 EXPECT_REF(topology, 2);
4328 ref = IMFQualityManager_Release(manager);
4329 ok(ref == 0, "Release returned %ld\n", ref);
4330 ref = IMFTopology_Release(topology);
4331 ok(ref == 0, "Release returned %ld\n", ref);
4333 hr = MFShutdown();
4334 ok(hr == S_OK, "Shutdown failure, hr %#lx.\n", hr);
4337 static void check_sar_rate_support(IMFMediaSink *sink)
4339 IMFRateSupport *rate_support;
4340 IMFMediaTypeHandler *handler;
4341 IMFStreamSink *stream_sink;
4342 IMFMediaType *media_type;
4343 HRESULT hr;
4344 float rate;
4346 hr = IMFMediaSink_QueryInterface(sink, &IID_IMFRateSupport, (void **)&rate_support);
4347 todo_wine
4348 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4349 if (FAILED(hr)) return;
4351 hr = IMFMediaSink_GetStreamSinkByIndex(sink, 0, &stream_sink);
4352 if (hr == MF_E_SHUTDOWN)
4354 hr = IMFRateSupport_GetSlowestRate(rate_support, MFRATE_FORWARD, FALSE, NULL);
4355 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
4357 hr = IMFRateSupport_GetSlowestRate(rate_support, MFRATE_FORWARD, FALSE, &rate);
4358 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
4360 hr = IMFRateSupport_GetFastestRate(rate_support, MFRATE_FORWARD, FALSE, &rate);
4361 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
4363 IMFRateSupport_Release(rate_support);
4364 return;
4366 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4368 hr = IMFStreamSink_GetMediaTypeHandler(stream_sink, &handler);
4369 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4371 IMFStreamSink_Release(stream_sink);
4373 hr = IMFRateSupport_GetSlowestRate(rate_support, MFRATE_FORWARD, FALSE, NULL);
4374 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
4376 hr = IMFRateSupport_GetFastestRate(rate_support, MFRATE_FORWARD, FALSE, NULL);
4377 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
4379 hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, &media_type);
4380 if (SUCCEEDED(hr))
4382 hr = IMFRateSupport_GetSlowestRate(rate_support, MFRATE_FORWARD, FALSE, &rate);
4383 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4385 hr = IMFRateSupport_GetSlowestRate(rate_support, MFRATE_FORWARD, TRUE, &rate);
4386 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4388 hr = IMFRateSupport_GetSlowestRate(rate_support, MFRATE_REVERSE, FALSE, &rate);
4389 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4391 hr = IMFRateSupport_GetSlowestRate(rate_support, MFRATE_REVERSE, TRUE, &rate);
4392 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4394 hr = IMFRateSupport_GetFastestRate(rate_support, MFRATE_FORWARD, FALSE, &rate);
4395 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4397 hr = IMFRateSupport_GetFastestRate(rate_support, MFRATE_FORWARD, TRUE, &rate);
4398 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4400 hr = IMFRateSupport_GetFastestRate(rate_support, MFRATE_REVERSE, FALSE, &rate);
4401 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4403 hr = IMFRateSupport_GetFastestRate(rate_support, MFRATE_REVERSE, TRUE, &rate);
4404 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4406 IMFMediaType_Release(media_type);
4408 else
4410 hr = IMFRateSupport_GetSlowestRate(rate_support, MFRATE_FORWARD, FALSE, &rate);
4411 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#lx.\n", hr);
4413 hr = IMFRateSupport_GetSlowestRate(rate_support, MFRATE_FORWARD, TRUE, &rate);
4414 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#lx.\n", hr);
4416 hr = IMFRateSupport_GetSlowestRate(rate_support, MFRATE_REVERSE, FALSE, &rate);
4417 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#lx.\n", hr);
4419 hr = IMFRateSupport_GetSlowestRate(rate_support, MFRATE_REVERSE, TRUE, &rate);
4420 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#lx.\n", hr);
4422 hr = IMFRateSupport_GetFastestRate(rate_support, MFRATE_FORWARD, FALSE, &rate);
4423 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#lx.\n", hr);
4425 hr = IMFRateSupport_GetFastestRate(rate_support, MFRATE_FORWARD, TRUE, &rate);
4426 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#lx.\n", hr);
4428 hr = IMFRateSupport_GetFastestRate(rate_support, MFRATE_REVERSE, FALSE, &rate);
4429 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#lx.\n", hr);
4431 hr = IMFRateSupport_GetFastestRate(rate_support, MFRATE_REVERSE, TRUE, &rate);
4432 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#lx.\n", hr);
4435 IMFMediaTypeHandler_Release(handler);
4436 IMFRateSupport_Release(rate_support);
4439 static void test_sar(void)
4441 IMFPresentationClock *present_clock, *present_clock2;
4442 IMFMediaType *mediatype, *mediatype2, *mediatype3;
4443 IMFClockStateSink *state_sink, *state_sink2;
4444 IMFMediaTypeHandler *handler, *handler2;
4445 IMFPresentationTimeSource *time_source;
4446 IMFSimpleAudioVolume *simple_volume;
4447 IMFAudioStreamVolume *stream_volume;
4448 IMFMediaSink *sink, *sink2;
4449 IMFStreamSink *stream_sink;
4450 IMFAttributes *attributes;
4451 DWORD i, id, flags, count;
4452 IMFActivate *activate;
4453 UINT32 channel_count;
4454 MFCLOCK_STATE state;
4455 IMFClock *clock;
4456 IUnknown *unk;
4457 HRESULT hr;
4458 GUID guid;
4459 BOOL mute;
4460 int found;
4461 LONG ref;
4463 hr = CoInitialize(NULL);
4464 ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
4466 hr = MFCreateAudioRenderer(NULL, &sink);
4467 if (hr == MF_E_NO_AUDIO_PLAYBACK_DEVICE)
4469 skip("No audio playback device available.\n");
4470 CoUninitialize();
4471 return;
4473 ok(hr == S_OK, "Failed to create renderer, hr %#lx.\n", hr);
4475 hr = MFStartup(MF_VERSION, MFSTARTUP_FULL);
4476 ok(hr == S_OK, "Startup failure, hr %#lx.\n", hr);
4478 hr = MFCreatePresentationClock(&present_clock);
4479 ok(hr == S_OK, "Failed to create presentation clock, hr %#lx.\n", hr);
4481 hr = IMFMediaSink_QueryInterface(sink, &IID_IMFPresentationTimeSource, (void **)&time_source);
4482 todo_wine
4483 ok(hr == S_OK, "Failed to get time source interface, hr %#lx.\n", hr);
4485 if (SUCCEEDED(hr))
4487 hr = IMFPresentationTimeSource_QueryInterface(time_source, &IID_IMFClockStateSink, (void **)&state_sink2);
4488 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4489 hr = IMFPresentationTimeSource_QueryInterface(time_source, &IID_IMFClockStateSink, (void **)&state_sink);
4490 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4491 ok(state_sink == state_sink2, "Unexpected clock sink.\n");
4492 IMFClockStateSink_Release(state_sink2);
4493 IMFClockStateSink_Release(state_sink);
4495 hr = IMFPresentationTimeSource_GetUnderlyingClock(time_source, &clock);
4496 ok(hr == MF_E_NO_CLOCK, "Unexpected hr %#lx.\n", hr);
4498 hr = IMFPresentationTimeSource_GetClockCharacteristics(time_source, &flags);
4499 ok(hr == S_OK, "Failed to get flags, hr %#lx.\n", hr);
4500 ok(flags == MFCLOCK_CHARACTERISTICS_FLAG_FREQUENCY_10MHZ, "Unexpected flags %#lx.\n", flags);
4502 hr = IMFPresentationTimeSource_GetState(time_source, 0, &state);
4503 ok(hr == S_OK, "Failed to get clock state, hr %#lx.\n", hr);
4504 ok(state == MFCLOCK_STATE_INVALID, "Unexpected state %d.\n", state);
4506 hr = IMFPresentationTimeSource_QueryInterface(time_source, &IID_IMFClockStateSink, (void **)&state_sink);
4507 ok(hr == S_OK, "Failed to get state sink, hr %#lx.\n", hr);
4509 hr = IMFClockStateSink_OnClockStart(state_sink, 0, 0);
4510 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#lx.\n", hr);
4512 IMFClockStateSink_Release(state_sink);
4514 IMFPresentationTimeSource_Release(time_source);
4516 hr = IMFMediaSink_AddStreamSink(sink, 123, NULL, &stream_sink);
4517 ok(hr == MF_E_STREAMSINKS_FIXED, "Unexpected hr %#lx.\n", hr);
4519 hr = IMFMediaSink_RemoveStreamSink(sink, 0);
4520 ok(hr == MF_E_STREAMSINKS_FIXED, "Unexpected hr %#lx.\n", hr);
4522 hr = IMFMediaSink_GetStreamSinkCount(sink, NULL);
4523 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
4525 hr = IMFMediaSink_GetStreamSinkCount(sink, &count);
4526 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4527 ok(count == 1, "Unexpected count %lu.\n", count);
4529 hr = IMFMediaSink_GetCharacteristics(sink, &flags);
4530 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4531 ok(flags == (MEDIASINK_FIXED_STREAMS | MEDIASINK_CAN_PREROLL), "Unexpected flags %#lx.\n", flags);
4533 check_interface(sink, &IID_IMFMediaSinkPreroll, TRUE);
4534 check_interface(sink, &IID_IMFMediaEventGenerator, TRUE);
4535 check_interface(sink, &IID_IMFClockStateSink, TRUE);
4536 check_interface(sink, &IID_IMFGetService, TRUE);
4537 todo_wine check_interface(sink, &IID_IMFPresentationTimeSource, TRUE);
4538 todo_wine check_service_interface(sink, &MF_RATE_CONTROL_SERVICE, &IID_IMFRateSupport, TRUE);
4539 check_service_interface(sink, &MF_RATE_CONTROL_SERVICE, &IID_IMFRateControl, FALSE);
4540 check_service_interface(sink, &MR_POLICY_VOLUME_SERVICE, &IID_IMFSimpleAudioVolume, TRUE);
4541 check_service_interface(sink, &MR_STREAM_VOLUME_SERVICE, &IID_IMFAudioStreamVolume, TRUE);
4543 /* Clock */
4544 hr = IMFMediaSink_QueryInterface(sink, &IID_IMFClockStateSink, (void **)&state_sink);
4545 ok(hr == S_OK, "Failed to get interface, hr %#lx.\n", hr);
4547 hr = IMFClockStateSink_OnClockStart(state_sink, 0, 0);
4548 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#lx.\n", hr);
4550 hr = IMFClockStateSink_OnClockPause(state_sink, 0);
4551 ok(hr == MF_E_INVALID_STATE_TRANSITION, "Unexpected hr %#lx.\n", hr);
4553 hr = IMFClockStateSink_OnClockStop(state_sink, 0);
4554 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#lx.\n", hr);
4556 hr = IMFClockStateSink_OnClockRestart(state_sink, 0);
4557 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#lx.\n", hr);
4559 IMFClockStateSink_Release(state_sink);
4561 hr = IMFMediaSink_SetPresentationClock(sink, NULL);
4562 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4564 hr = IMFMediaSink_SetPresentationClock(sink, present_clock);
4565 todo_wine
4566 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#lx.\n", hr);
4568 hr = MFCreateSystemTimeSource(&time_source);
4569 ok(hr == S_OK, "Failed to create time source, hr %#lx.\n", hr);
4571 hr = IMFPresentationClock_SetTimeSource(present_clock, time_source);
4572 ok(hr == S_OK, "Failed to set time source, hr %#lx.\n", hr);
4573 IMFPresentationTimeSource_Release(time_source);
4575 hr = IMFMediaSink_SetPresentationClock(sink, present_clock);
4576 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4578 hr = IMFMediaSink_GetPresentationClock(sink, NULL);
4579 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
4581 hr = IMFMediaSink_GetPresentationClock(sink, &present_clock2);
4582 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4583 ok(present_clock == present_clock2, "Unexpected instance.\n");
4584 IMFPresentationClock_Release(present_clock2);
4586 /* Stream */
4587 hr = IMFMediaSink_GetStreamSinkByIndex(sink, 0, &stream_sink);
4588 ok(hr == S_OK, "Failed to get a stream, hr %#lx.\n", hr);
4590 check_interface(stream_sink, &IID_IMFMediaEventGenerator, TRUE);
4591 check_interface(stream_sink, &IID_IMFMediaTypeHandler, TRUE);
4592 todo_wine check_interface(stream_sink, &IID_IMFGetService, TRUE);
4594 hr = IMFStreamSink_GetIdentifier(stream_sink, &id);
4595 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4596 ok(!id, "Unexpected id.\n");
4598 hr = IMFStreamSink_GetMediaSink(stream_sink, &sink2);
4599 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4600 ok(sink == sink2, "Unexpected object.\n");
4601 IMFMediaSink_Release(sink2);
4603 hr = IMFStreamSink_GetMediaTypeHandler(stream_sink, &handler);
4604 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4606 hr = IMFStreamSink_QueryInterface(stream_sink, &IID_IMFMediaTypeHandler, (void **)&handler2);
4607 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4608 ok(handler2 == handler, "Unexpected instance.\n");
4609 IMFMediaTypeHandler_Release(handler2);
4611 hr = IMFMediaTypeHandler_GetMajorType(handler, &guid);
4612 ok(hr == S_OK, "Failed to get major type, hr %#lx.\n", hr);
4613 ok(IsEqualGUID(&guid, &MFMediaType_Audio), "Unexpected type %s.\n", wine_dbgstr_guid(&guid));
4615 count = 0;
4616 hr = IMFMediaTypeHandler_GetMediaTypeCount(handler, &count);
4617 ok(hr == S_OK, "Failed to get type count, hr %#lx.\n", hr);
4618 ok(!!count, "Unexpected type count %lu.\n", count);
4620 /* A number of same major/subtype entries are returned, with different degrees of finer format
4621 details. Some incomplete types are not accepted, check that at least one of them is considered supported. */
4623 for (i = 0, found = -1; i < count; ++i)
4625 hr = IMFMediaTypeHandler_GetMediaTypeByIndex(handler, i, &mediatype);
4626 ok(hr == S_OK, "Failed to get media type, hr %#lx.\n", hr);
4628 if (SUCCEEDED(IMFMediaTypeHandler_IsMediaTypeSupported(handler, mediatype, NULL)))
4629 found = i;
4630 IMFMediaType_Release(mediatype);
4632 if (found != -1) break;
4634 ok(found != -1, "Haven't found a supported type.\n");
4636 hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, &mediatype);
4637 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#lx.\n", hr);
4639 hr = MFCreateMediaType(&mediatype);
4640 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
4642 /* Actual return value is MF_E_ATRIBUTENOTFOUND triggered by missing MF_MT_MAJOR_TYPE */
4643 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, mediatype, NULL);
4644 ok(FAILED(hr), "Unexpected hr %#lx.\n", hr);
4646 hr = IMFMediaType_SetGUID(mediatype, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
4647 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4648 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, mediatype, NULL);
4649 ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#lx.\n", hr);
4651 hr = IMFMediaType_SetGUID(mediatype, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio);
4652 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4653 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, mediatype, NULL);
4654 ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#lx.\n", hr);
4656 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, mediatype);
4657 ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#lx.\n", hr);
4659 hr = IMFMediaTypeHandler_GetMediaTypeByIndex(handler, found, &mediatype2);
4660 ok(hr == S_OK, "Failed to get media type, hr %#lx.\n", hr);
4662 hr = IMFMediaTypeHandler_GetMediaTypeByIndex(handler, found, &mediatype3);
4663 ok(hr == S_OK, "Failed to get media type, hr %#lx.\n", hr);
4664 ok(mediatype2 == mediatype3, "Unexpected instance.\n");
4665 IMFMediaType_Release(mediatype3);
4667 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, mediatype2, NULL);
4668 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4670 IMFMediaType_Release(mediatype);
4672 check_sar_rate_support(sink);
4674 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, mediatype2);
4675 ok(hr == S_OK, "Failed to set current type, hr %#lx.\n", hr);
4677 check_sar_rate_support(sink);
4679 hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, &mediatype);
4680 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4681 ok(mediatype == mediatype2, "Unexpected instance.\n");
4682 IMFMediaType_Release(mediatype);
4684 IMFMediaType_Release(mediatype2);
4686 /* Reset back to uninitialized state. */
4687 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, NULL);
4688 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
4690 IMFMediaTypeHandler_Release(handler);
4692 /* State change with initialized stream. */
4693 hr = IMFMediaSink_QueryInterface(sink, &IID_IMFClockStateSink, (void **)&state_sink);
4694 ok(hr == S_OK, "Failed to get interface, hr %#lx.\n", hr);
4696 hr = IMFClockStateSink_OnClockStart(state_sink, 0, 0);
4697 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4699 hr = IMFClockStateSink_OnClockStart(state_sink, 0, 0);
4700 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4702 hr = IMFClockStateSink_OnClockPause(state_sink, 0);
4703 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4705 hr = IMFClockStateSink_OnClockStop(state_sink, 0);
4706 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4708 hr = IMFClockStateSink_OnClockStop(state_sink, 0);
4709 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4711 hr = IMFClockStateSink_OnClockPause(state_sink, 0);
4712 ok(hr == MF_E_INVALID_STATE_TRANSITION, "Unexpected hr %#lx.\n", hr);
4714 hr = IMFClockStateSink_OnClockRestart(state_sink, 0);
4715 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4717 hr = IMFClockStateSink_OnClockRestart(state_sink, 0);
4718 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4720 hr = IMFClockStateSink_OnClockStop(state_sink, 0);
4721 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4723 IMFClockStateSink_Release(state_sink);
4725 IMFStreamSink_Release(stream_sink);
4727 /* Volume control */
4728 hr = MFGetService((IUnknown *)sink, &MR_POLICY_VOLUME_SERVICE, &IID_IMFSimpleAudioVolume, (void **)&simple_volume);
4729 ok(hr == S_OK, "Failed to get interface, hr %#lx.\n", hr);
4731 hr = IMFSimpleAudioVolume_GetMute(simple_volume, &mute);
4732 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4734 IMFSimpleAudioVolume_Release(simple_volume);
4736 hr = MFGetService((IUnknown *)sink, &MR_STREAM_VOLUME_SERVICE, &IID_IMFAudioStreamVolume, (void **)&stream_volume);
4737 ok(hr == S_OK, "Failed to get interface, hr %#lx.\n", hr);
4739 hr = IMFAudioStreamVolume_GetChannelCount(stream_volume, &channel_count);
4740 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4742 hr = IMFAudioStreamVolume_GetChannelCount(stream_volume, NULL);
4743 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
4745 IMFAudioStreamVolume_Release(stream_volume);
4747 hr = MFGetService((IUnknown *)sink, &MR_AUDIO_POLICY_SERVICE, &IID_IMFAudioPolicy, (void **)&unk);
4748 ok(hr == S_OK, "Failed to get interface, hr %#lx.\n", hr);
4749 IUnknown_Release(unk);
4751 /* Shutdown */
4752 EXPECT_REF(present_clock, 2);
4753 hr = IMFMediaSink_Shutdown(sink);
4754 ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr);
4755 EXPECT_REF(present_clock, 1);
4757 hr = IMFMediaSink_Shutdown(sink);
4758 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
4760 hr = IMFMediaSink_AddStreamSink(sink, 123, NULL, &stream_sink);
4761 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
4763 hr = IMFMediaSink_RemoveStreamSink(sink, 0);
4764 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
4766 hr = IMFMediaSink_GetStreamSinkCount(sink, NULL);
4767 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
4769 hr = IMFMediaSink_GetStreamSinkCount(sink, &count);
4770 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
4772 hr = IMFMediaSink_GetCharacteristics(sink, &flags);
4773 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
4775 hr = IMFMediaSink_SetPresentationClock(sink, NULL);
4776 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
4778 hr = IMFMediaSink_SetPresentationClock(sink, present_clock);
4779 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
4781 hr = IMFMediaSink_GetPresentationClock(sink, NULL);
4782 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
4784 hr = IMFMediaSink_GetPresentationClock(sink, &present_clock2);
4785 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
4787 check_sar_rate_support(sink);
4789 ref = IMFMediaSink_Release(sink);
4790 todo_wine
4791 ok(ref == 0, "Release returned %ld\n", ref);
4793 /* Activation */
4794 hr = MFCreateAudioRendererActivate(&activate);
4795 ok(hr == S_OK, "Failed to create activation object, hr %#lx.\n", hr);
4797 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink);
4798 ok(hr == S_OK, "Failed to activate, hr %#lx.\n", hr);
4800 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink2);
4801 ok(hr == S_OK, "Failed to activate, hr %#lx.\n", hr);
4802 ok(sink == sink2, "Unexpected instance.\n");
4803 IMFMediaSink_Release(sink2);
4805 hr = IMFMediaSink_GetCharacteristics(sink, &flags);
4806 ok(hr == S_OK, "Failed to get sink flags, hr %#lx.\n", hr);
4808 hr = IMFActivate_ShutdownObject(activate);
4809 ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr);
4811 hr = IMFMediaSink_GetCharacteristics(sink, &flags);
4812 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
4814 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink2);
4815 ok(hr == S_OK, "Failed to activate, hr %#lx.\n", hr);
4816 todo_wine
4817 ok(sink == sink2, "Unexpected instance.\n");
4819 hr = IMFMediaSink_GetCharacteristics(sink2, &flags);
4820 todo_wine
4821 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
4823 IMFMediaSink_Release(sink2);
4825 hr = IMFActivate_DetachObject(activate);
4826 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
4828 hr = IMFActivate_ShutdownObject(activate);
4829 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4831 ref = IMFActivate_Release(activate);
4832 ok(ref == 0, "Release returned %ld\n", ref);
4833 ref = IMFMediaSink_Release(sink);
4834 ok(ref == 0, "Release returned %ld\n", ref);
4836 ref = IMFPresentationClock_Release(present_clock);
4837 ok(ref == 0, "Release returned %ld\n", ref);
4839 hr = MFShutdown();
4840 ok(hr == S_OK, "Shutdown failure, hr %#lx.\n", hr);
4842 /* SAR attributes */
4843 hr = MFCreateAttributes(&attributes, 0);
4844 ok(hr == S_OK, "Failed to create attributes, hr %#lx.\n", hr);
4846 /* Specify role. */
4847 hr = IMFAttributes_SetUINT32(attributes, &MF_AUDIO_RENDERER_ATTRIBUTE_ENDPOINT_ROLE, eMultimedia);
4848 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
4850 hr = MFCreateAudioRenderer(attributes, &sink);
4851 ok(hr == S_OK, "Failed to create a sink, hr %#lx.\n", hr);
4853 /* required for the sink to be fully released */
4854 hr = IMFMediaSink_Shutdown(sink);
4855 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4857 ref = IMFMediaSink_Release(sink);
4858 ok(ref == 0, "Release returned %ld\n", ref);
4860 /* Invalid endpoint. */
4861 hr = IMFAttributes_SetString(attributes, &MF_AUDIO_RENDERER_ATTRIBUTE_ENDPOINT_ID, L"endpoint");
4862 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
4864 hr = MFCreateAudioRenderer(attributes, &sink);
4865 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
4867 hr = IMFAttributes_DeleteItem(attributes, &MF_AUDIO_RENDERER_ATTRIBUTE_ENDPOINT_ROLE);
4868 ok(hr == S_OK, "Failed to remove attribute, hr %#lx.\n", hr);
4870 hr = MFCreateAudioRenderer(attributes, &sink);
4871 ok(hr == MF_E_NO_AUDIO_PLAYBACK_DEVICE, "Failed to create a sink, hr %#lx.\n", hr);
4873 ref = IMFAttributes_Release(attributes);
4874 ok(ref == 0, "Release returned %ld\n", ref);
4876 CoUninitialize();
4879 static void test_evr(void)
4881 static const float supported_rates[] =
4883 0.0f, 1.0f, -20.0f, 20.0f, 1000.0f, -1000.0f,
4885 IMFVideoSampleAllocatorCallback *allocator_callback;
4886 IMFStreamSink *stream_sink, *stream_sink2;
4887 IMFVideoDisplayControl *display_control;
4888 IMFMediaType *media_type, *media_type2;
4889 IMFPresentationTimeSource *time_source;
4890 IMFVideoSampleAllocator *allocator;
4891 IMFMediaTypeHandler *type_handler;
4892 IMFVideoRenderer *video_renderer;
4893 IMFPresentationClock *clock;
4894 IMFMediaSink *sink, *sink2;
4895 IMFAttributes *attributes;
4896 UINT32 attr_count, value;
4897 IMFActivate *activate;
4898 HWND window, window2;
4899 IMFRateSupport *rs;
4900 DWORD flags, count;
4901 LONG sample_count;
4902 IMFSample *sample;
4903 unsigned int i;
4904 UINT64 window3;
4905 float rate;
4906 HRESULT hr;
4907 GUID guid;
4908 LONG ref;
4910 hr = MFStartup(MF_VERSION, MFSTARTUP_FULL);
4911 ok(hr == S_OK, "Startup failure, hr %#lx.\n", hr);
4913 hr = MFCreateVideoRenderer(&IID_IMFVideoRenderer, (void **)&video_renderer);
4914 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4916 hr = IMFVideoRenderer_InitializeRenderer(video_renderer, NULL, NULL);
4917 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4919 /* required for the video renderer to be fully released */
4920 hr = IMFVideoRenderer_QueryInterface(video_renderer, &IID_IMFMediaSink, (void **)&sink);
4921 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4922 hr = IMFMediaSink_Shutdown(sink);
4923 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4924 IMFMediaSink_Release(sink);
4926 ref = IMFVideoRenderer_Release(video_renderer);
4927 ok(ref == 0, "Release returned %ld\n", ref);
4929 hr = MFCreateVideoRendererActivate(NULL, NULL);
4930 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
4932 /* Window */
4933 window = create_window();
4934 hr = MFCreateVideoRendererActivate(window, &activate);
4935 ok(hr == S_OK, "Failed to create activate object, hr %#lx.\n", hr);
4937 hr = IMFActivate_GetUINT64(activate, &MF_ACTIVATE_VIDEO_WINDOW, &window3);
4938 ok(hr == S_OK, "Failed to get attribute, hr %#lx.\n", hr);
4939 ok(UlongToHandle(window3) == window, "Unexpected value.\n");
4941 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink);
4942 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4944 check_interface(sink, &IID_IMFMediaSinkPreroll, TRUE);
4945 check_interface(sink, &IID_IMFVideoRenderer, TRUE);
4946 check_interface(sink, &IID_IMFMediaEventGenerator, TRUE);
4947 check_interface(sink, &IID_IMFClockStateSink, TRUE);
4948 check_interface(sink, &IID_IMFGetService, TRUE);
4949 check_interface(sink, &IID_IMFQualityAdvise, TRUE);
4950 check_interface(sink, &IID_IMFRateSupport, TRUE);
4951 check_interface(sink, &IID_IMFRateControl, FALSE);
4952 check_service_interface(sink, &MR_VIDEO_MIXER_SERVICE, &IID_IMFVideoProcessor, TRUE);
4953 check_service_interface(sink, &MR_VIDEO_MIXER_SERVICE, &IID_IMFVideoMixerBitmap, TRUE);
4954 check_service_interface(sink, &MR_VIDEO_MIXER_SERVICE, &IID_IMFVideoMixerControl, TRUE);
4955 check_service_interface(sink, &MR_VIDEO_MIXER_SERVICE, &IID_IMFVideoMixerControl2, TRUE);
4956 check_service_interface(sink, &MR_VIDEO_RENDER_SERVICE, &IID_IMFVideoDisplayControl, TRUE);
4957 check_service_interface(sink, &MR_VIDEO_RENDER_SERVICE, &IID_IMFVideoPositionMapper, TRUE);
4958 check_service_interface(sink, &MR_VIDEO_ACCELERATION_SERVICE, &IID_IMFVideoSampleAllocator, FALSE);
4959 check_service_interface(sink, &MR_VIDEO_ACCELERATION_SERVICE, &IID_IDirect3DDeviceManager9, TRUE);
4960 check_service_interface(sink, &MF_RATE_CONTROL_SERVICE, &IID_IMFRateSupport, TRUE);
4962 hr = MFGetService((IUnknown *)sink, &MR_VIDEO_RENDER_SERVICE, &IID_IMFVideoDisplayControl,
4963 (void **)&display_control);
4964 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4966 window2 = NULL;
4967 hr = IMFVideoDisplayControl_GetVideoWindow(display_control, &window2);
4968 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4969 ok(window2 == window, "Unexpected window %p.\n", window2);
4971 IMFVideoDisplayControl_Release(display_control);
4973 hr = IMFActivate_ShutdownObject(activate);
4974 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4976 ref = IMFActivate_Release(activate);
4977 ok(ref == 0, "Release returned %ld\n", ref);
4978 ref = IMFMediaSink_Release(sink);
4979 ok(ref == 0, "Release returned %ld\n", ref);
4980 DestroyWindow(window);
4982 hr = MFCreateVideoRendererActivate(NULL, &activate);
4983 ok(hr == S_OK, "Failed to create activate object, hr %#lx.\n", hr);
4985 hr = IMFActivate_GetCount(activate, &attr_count);
4986 ok(hr == S_OK, "Failed to get attribute count, hr %#lx.\n", hr);
4987 ok(attr_count == 1, "Unexpected count %u.\n", attr_count);
4989 hr = IMFActivate_GetUINT64(activate, &MF_ACTIVATE_VIDEO_WINDOW, &window3);
4990 ok(hr == S_OK, "Failed to get attribute, hr %#lx.\n", hr);
4991 ok(!window3, "Unexpected value.\n");
4993 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink);
4994 ok(hr == S_OK, "Failed to activate, hr %#lx.\n", hr);
4996 hr = IMFMediaSink_QueryInterface(sink, &IID_IMFAttributes, (void **)&attributes);
4997 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4998 check_interface(attributes, &IID_IMFMediaSink, TRUE);
5000 hr = IMFAttributes_GetCount(attributes, &attr_count);
5001 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5002 ok(!!attr_count, "Unexpected count %u.\n", attr_count);
5003 /* Rendering preferences are not immediately propagated to the presenter. */
5004 hr = IMFAttributes_SetUINT32(attributes, &EVRConfig_ForceBob, 1);
5005 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5006 hr = MFGetService((IUnknown *)sink, &MR_VIDEO_RENDER_SERVICE, &IID_IMFVideoDisplayControl, (void **)&display_control);
5007 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5008 hr = IMFVideoDisplayControl_GetRenderingPrefs(display_control, &flags);
5009 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5010 ok(!flags, "Unexpected flags %#lx.\n", flags);
5011 IMFVideoDisplayControl_Release(display_control);
5012 IMFAttributes_Release(attributes);
5014 /* Primary stream type handler. */
5015 hr = IMFMediaSink_GetStreamSinkById(sink, 0, &stream_sink);
5016 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5018 hr = IMFStreamSink_QueryInterface(stream_sink, &IID_IMFAttributes, (void **)&attributes);
5019 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5020 hr = IMFAttributes_GetCount(attributes, &attr_count);
5021 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5022 ok(attr_count == 2, "Unexpected count %u.\n", attr_count);
5023 value = 0;
5024 hr = IMFAttributes_GetUINT32(attributes, &MF_SA_REQUIRED_SAMPLE_COUNT, &value);
5025 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5026 ok(value == 1, "Unexpected attribute value %u.\n", value);
5027 value = 0;
5028 hr = IMFAttributes_GetUINT32(attributes, &MF_SA_D3D_AWARE, &value);
5029 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5030 ok(value == 1, "Unexpected attribute value %u.\n", value);
5032 check_interface(attributes, &IID_IMFStreamSink, TRUE);
5033 IMFAttributes_Release(attributes);
5035 hr = IMFStreamSink_GetMediaTypeHandler(stream_sink, &type_handler);
5036 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5038 hr = IMFMediaTypeHandler_GetMajorType(type_handler, NULL);
5039 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
5041 hr = IMFMediaTypeHandler_GetMajorType(type_handler, &guid);
5042 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5043 ok(IsEqualGUID(&guid, &MFMediaType_Video), "Unexpected type %s.\n", wine_dbgstr_guid(&guid));
5045 /* Supported types are not advertised. */
5046 hr = IMFMediaTypeHandler_GetMediaTypeCount(type_handler, NULL);
5047 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
5049 count = 1;
5050 hr = IMFMediaTypeHandler_GetMediaTypeCount(type_handler, &count);
5051 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5052 ok(!count, "Unexpected count %lu.\n", count);
5054 hr = IMFMediaTypeHandler_GetMediaTypeByIndex(type_handler, 0, NULL);
5055 ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#lx.\n", hr);
5057 hr = IMFMediaTypeHandler_GetMediaTypeByIndex(type_handler, 0, &media_type);
5058 ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#lx.\n", hr);
5060 hr = IMFMediaTypeHandler_GetCurrentMediaType(type_handler, NULL);
5061 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
5063 hr = IMFMediaTypeHandler_GetCurrentMediaType(type_handler, &media_type);
5064 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
5066 hr = IMFMediaTypeHandler_SetCurrentMediaType(type_handler, NULL);
5067 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
5069 hr = MFCreateMediaType(&media_type);
5070 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5072 hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
5073 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5075 hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFVideoFormat_RGB32);
5076 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5078 hr = IMFMediaType_SetUINT64(media_type, &MF_MT_FRAME_SIZE, (UINT64)640 << 32 | 480);
5079 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5081 hr = IMFMediaTypeHandler_IsMediaTypeSupported(type_handler, NULL, NULL);
5082 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
5084 hr = IMFMediaTypeHandler_IsMediaTypeSupported(type_handler, media_type, &media_type2);
5085 ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#lx.\n", hr);
5087 hr = IMFMediaType_SetUINT32(media_type, &MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE);
5088 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5090 media_type2 = (void *)0x1;
5091 hr = IMFMediaTypeHandler_IsMediaTypeSupported(type_handler, media_type, &media_type2);
5092 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5093 ok(!media_type2, "Unexpected media type %p.\n", media_type2);
5095 hr = IMFMediaTypeHandler_SetCurrentMediaType(type_handler, media_type);
5096 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5098 hr = IMFMediaTypeHandler_GetCurrentMediaType(type_handler, &media_type2);
5099 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5100 check_interface(media_type2, &IID_IMFVideoMediaType, TRUE);
5101 IMFMediaType_Release(media_type2);
5103 IMFMediaType_Release(media_type);
5105 IMFMediaTypeHandler_Release(type_handler);
5107 /* Stream uses an allocator. */
5108 check_service_interface(stream_sink, &MR_VIDEO_ACCELERATION_SERVICE, &IID_IMFVideoSampleAllocator, TRUE);
5109 check_service_interface(stream_sink, &MR_VIDEO_ACCELERATION_SERVICE, &IID_IDirect3DDeviceManager9, TRUE);
5110 todo_wine {
5111 check_service_interface(stream_sink, &MR_VIDEO_MIXER_SERVICE, &IID_IMFVideoProcessor, TRUE);
5112 check_service_interface(stream_sink, &MR_VIDEO_MIXER_SERVICE, &IID_IMFVideoMixerBitmap, TRUE);
5113 check_service_interface(stream_sink, &MR_VIDEO_MIXER_SERVICE, &IID_IMFVideoMixerControl, TRUE);
5114 check_service_interface(stream_sink, &MR_VIDEO_MIXER_SERVICE, &IID_IMFVideoMixerControl2, TRUE);
5115 check_service_interface(stream_sink, &MR_VIDEO_RENDER_SERVICE, &IID_IMFVideoDisplayControl, TRUE);
5116 check_service_interface(stream_sink, &MR_VIDEO_RENDER_SERVICE, &IID_IMFVideoPositionMapper, TRUE);
5117 check_service_interface(stream_sink, &MF_RATE_CONTROL_SERVICE, &IID_IMFRateSupport, TRUE);
5119 hr = MFGetService((IUnknown *)stream_sink, &MR_VIDEO_ACCELERATION_SERVICE, &IID_IMFVideoSampleAllocator,
5120 (void **)&allocator);
5121 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5123 hr = IMFVideoSampleAllocator_QueryInterface(allocator, &IID_IMFVideoSampleAllocatorCallback, (void **)&allocator_callback);
5124 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5126 sample_count = 0;
5127 hr = IMFVideoSampleAllocatorCallback_GetFreeSampleCount(allocator_callback, &sample_count);
5128 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5129 ok(!sample_count, "Unexpected sample count %ld.\n", sample_count);
5131 hr = IMFVideoSampleAllocator_AllocateSample(allocator, &sample);
5132 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#lx.\n", hr);
5134 IMFVideoSampleAllocatorCallback_Release(allocator_callback);
5135 IMFVideoSampleAllocator_Release(allocator);
5136 IMFStreamSink_Release(stream_sink);
5138 /* Same test for a substream. */
5139 hr = IMFMediaSink_AddStreamSink(sink, 1, NULL, &stream_sink2);
5140 ok(hr == S_OK || broken(hr == E_INVALIDARG), "Unexpected hr %#lx.\n", hr);
5142 if (SUCCEEDED(hr))
5144 hr = MFGetService((IUnknown *)stream_sink2, &MR_VIDEO_ACCELERATION_SERVICE, &IID_IMFVideoSampleAllocator,
5145 (void **)&allocator);
5146 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5147 IMFVideoSampleAllocator_Release(allocator);
5149 hr = IMFMediaSink_RemoveStreamSink(sink, 1);
5150 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5152 ref = IMFStreamSink_Release(stream_sink2);
5153 ok(ref == 0, "Release returned %ld\n", ref);
5156 hr = IMFMediaSink_GetCharacteristics(sink, &flags);
5157 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5158 ok(flags == (MEDIASINK_CAN_PREROLL | MEDIASINK_CLOCK_REQUIRED), "Unexpected flags %#lx.\n", flags);
5160 hr = IMFActivate_ShutdownObject(activate);
5161 ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr);
5163 hr = IMFMediaSink_GetCharacteristics(sink, &flags);
5164 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
5166 /* Activate again. */
5167 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink2);
5168 ok(hr == S_OK, "Failed to activate, hr %#lx.\n", hr);
5169 todo_wine
5170 ok(sink == sink2, "Unexpected instance.\n");
5171 IMFMediaSink_Release(sink2);
5173 hr = IMFActivate_DetachObject(activate);
5174 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
5176 hr = IMFMediaSink_GetCharacteristics(sink, &flags);
5177 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
5179 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink2);
5180 ok(hr == S_OK, "Failed to activate, hr %#lx.\n", hr);
5181 todo_wine
5182 ok(sink == sink2, "Unexpected instance.\n");
5183 IMFMediaSink_Release(sink2);
5185 hr = IMFActivate_ShutdownObject(activate);
5186 ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr);
5188 ref = IMFActivate_Release(activate);
5189 ok(ref == 0, "Release returned %ld\n", ref);
5190 ref = IMFMediaSink_Release(sink);
5191 todo_wine
5192 ok(ref == 0, "Release returned %ld\n", ref);
5194 /* Set clock. */
5195 window = create_window();
5197 hr = MFCreateVideoRendererActivate(window, &activate);
5198 ok(hr == S_OK, "Failed to create activate object, hr %#lx.\n", hr);
5200 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink);
5201 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5202 ref = IMFActivate_Release(activate);
5203 ok(ref == 0, "Release returned %ld\n", ref);
5205 hr = MFCreateSystemTimeSource(&time_source);
5206 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5208 hr = MFCreatePresentationClock(&clock);
5209 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5211 hr = IMFPresentationClock_SetTimeSource(clock, time_source);
5212 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5213 IMFPresentationTimeSource_Release(time_source);
5215 hr = IMFMediaSink_SetPresentationClock(sink, clock);
5216 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5218 hr = IMFMediaSink_QueryInterface(sink, &IID_IMFRateSupport, (void **)&rs);
5219 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5221 rate = 1.0f;
5222 hr = IMFRateSupport_GetSlowestRate(rs, MFRATE_FORWARD, FALSE, &rate);
5223 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5224 ok(rate == 0.0f, "Unexpected rate %f.\n", rate);
5226 rate = 1.0f;
5227 hr = IMFRateSupport_GetSlowestRate(rs, MFRATE_REVERSE, FALSE, &rate);
5228 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5229 ok(rate == 0.0f, "Unexpected rate %f.\n", rate);
5231 rate = 1.0f;
5232 hr = IMFRateSupport_GetSlowestRate(rs, MFRATE_FORWARD, TRUE, &rate);
5233 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5234 ok(rate == 0.0f, "Unexpected rate %f.\n", rate);
5236 rate = 1.0f;
5237 hr = IMFRateSupport_GetSlowestRate(rs, MFRATE_REVERSE, TRUE, &rate);
5238 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5239 ok(rate == 0.0f, "Unexpected rate %f.\n", rate);
5241 hr = IMFRateSupport_GetFastestRate(rs, MFRATE_FORWARD, FALSE, &rate);
5242 ok(hr == MF_E_INVALIDREQUEST, "Unexpected hr %#lx.\n", hr);
5244 hr = IMFRateSupport_GetFastestRate(rs, MFRATE_REVERSE, FALSE, &rate);
5245 ok(hr == MF_E_INVALIDREQUEST, "Unexpected hr %#lx.\n", hr);
5247 hr = IMFRateSupport_GetFastestRate(rs, MFRATE_FORWARD, TRUE, &rate);
5248 ok(hr == MF_E_INVALIDREQUEST, "Unexpected hr %#lx.\n", hr);
5250 hr = IMFRateSupport_GetFastestRate(rs, MFRATE_REVERSE, TRUE, &rate);
5251 ok(hr == MF_E_INVALIDREQUEST, "Unexpected hr %#lx.\n", hr);
5253 hr = IMFRateSupport_GetFastestRate(rs, MFRATE_REVERSE, TRUE, NULL);
5254 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
5256 for (i = 0; i < ARRAY_SIZE(supported_rates); ++i)
5258 rate = supported_rates[i] + 1.0f;
5259 hr = IMFRateSupport_IsRateSupported(rs, TRUE, supported_rates[i], &rate);
5260 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5261 ok(rate == supported_rates[i], "Unexpected rate %f.\n", rate);
5263 rate = supported_rates[i] + 1.0f;
5264 hr = IMFRateSupport_IsRateSupported(rs, FALSE, supported_rates[i], &rate);
5265 ok(hr == MF_E_INVALIDREQUEST, "Unexpected hr %#lx.\n", hr);
5266 ok(rate == supported_rates[i], "Unexpected rate %f.\n", rate);
5268 hr = IMFRateSupport_IsRateSupported(rs, TRUE, supported_rates[i], NULL);
5269 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5271 hr = IMFRateSupport_IsRateSupported(rs, FALSE, supported_rates[i], NULL);
5272 ok(hr == MF_E_INVALIDREQUEST, "Unexpected hr %#lx.\n", hr);
5275 /* Configuring stream type make rate support work. */
5276 hr = IMFMediaSink_GetStreamSinkById(sink, 0, &stream_sink);
5277 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5278 hr = IMFStreamSink_GetMediaTypeHandler(stream_sink, &type_handler);
5279 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5280 hr = MFCreateMediaType(&media_type);
5281 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5282 hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
5283 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5284 hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFVideoFormat_RGB32);
5285 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5286 hr = IMFMediaType_SetUINT64(media_type, &MF_MT_FRAME_SIZE, (UINT64)64 << 32 | 64);
5287 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5288 hr = IMFMediaType_SetUINT32(media_type, &MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE);
5289 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5290 hr = IMFMediaTypeHandler_SetCurrentMediaType(type_handler, media_type);
5291 ok(hr == S_OK, "Failed to set current type, hr %#lx.\n", hr);
5292 IMFMediaType_Release(media_type);
5293 IMFMediaTypeHandler_Release(type_handler);
5294 IMFStreamSink_Release(stream_sink);
5296 rate = 1.0f;
5297 hr = IMFRateSupport_GetSlowestRate(rs, MFRATE_FORWARD, TRUE, &rate);
5298 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5299 ok(rate == 0.0f, "Unexpected rate %f.\n", rate);
5301 rate = 1.0f;
5302 hr = IMFRateSupport_GetSlowestRate(rs, MFRATE_REVERSE, TRUE, &rate);
5303 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5304 ok(rate == 0.0f, "Unexpected rate %f.\n", rate);
5306 rate = 0.0f;
5307 hr = IMFRateSupport_GetFastestRate(rs, MFRATE_FORWARD, TRUE, &rate);
5308 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5309 ok(rate == FLT_MAX, "Unexpected rate %f.\n", rate);
5311 rate = 0.0f;
5312 hr = IMFRateSupport_GetFastestRate(rs, MFRATE_REVERSE, TRUE, &rate);
5313 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5314 ok(rate == -FLT_MAX, "Unexpected rate %f.\n", rate);
5316 hr = IMFRateSupport_GetFastestRate(rs, MFRATE_REVERSE, TRUE, NULL);
5317 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
5319 hr = IMFRateSupport_GetSlowestRate(rs, MFRATE_REVERSE, TRUE, NULL);
5320 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
5322 for (i = 0; i < ARRAY_SIZE(supported_rates); ++i)
5324 rate = supported_rates[i] + 1.0f;
5325 hr = IMFRateSupport_IsRateSupported(rs, TRUE, supported_rates[i], &rate);
5326 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5327 ok(rate == supported_rates[i], "Unexpected rate %f.\n", rate);
5329 rate = supported_rates[i] + 1.0f;
5330 hr = IMFRateSupport_IsRateSupported(rs, FALSE, supported_rates[i], &rate);
5331 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5332 ok(rate == supported_rates[i], "Unexpected rate %f.\n", rate);
5334 hr = IMFRateSupport_IsRateSupported(rs, TRUE, supported_rates[i], NULL);
5335 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5337 hr = IMFRateSupport_IsRateSupported(rs, FALSE, supported_rates[i], NULL);
5338 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5341 hr = IMFMediaSink_Shutdown(sink);
5342 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5344 hr = IMFMediaSink_GetStreamSinkCount(sink, NULL);
5345 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
5347 hr = IMFMediaSink_GetStreamSinkCount(sink, &count);
5348 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
5350 hr = IMFRateSupport_GetSlowestRate(rs, MFRATE_FORWARD, FALSE, &rate);
5351 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
5353 hr = IMFRateSupport_GetFastestRate(rs, MFRATE_FORWARD, FALSE, &rate);
5354 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
5356 hr = IMFRateSupport_GetSlowestRate(rs, MFRATE_FORWARD, FALSE, NULL);
5357 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
5359 hr = IMFRateSupport_GetFastestRate(rs, MFRATE_FORWARD, FALSE, NULL);
5360 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
5362 hr = IMFRateSupport_IsRateSupported(rs, TRUE, 1.0f, &rate);
5363 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
5365 ref = IMFRateSupport_Release(rs);
5366 ok(ref == 1, "Release returned %ld\n", ref);
5367 ref = IMFMediaSink_Release(sink);
5368 ok(ref == 0, "Release returned %ld\n", ref);
5369 ref = IMFPresentationClock_Release(clock);
5370 ok(ref == 0, "Release returned %ld\n", ref);
5372 DestroyWindow(window);
5374 hr = MFShutdown();
5375 ok(hr == S_OK, "Shutdown failure, hr %#lx.\n", hr);
5378 static void test_MFCreateSimpleTypeHandler(void)
5380 IMFMediaType *media_type, *media_type2, *media_type3;
5381 IMFMediaTypeHandler *handler;
5382 DWORD count;
5383 HRESULT hr;
5384 GUID guid;
5385 LONG ref;
5387 hr = MFCreateSimpleTypeHandler(&handler);
5388 ok(hr == S_OK, "Failed to create object, hr %#lx.\n", hr);
5390 hr = IMFMediaTypeHandler_GetMediaTypeCount(handler, NULL);
5391 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
5393 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, NULL, NULL);
5394 ok(hr == MF_E_UNEXPECTED, "Unexpected hr %#lx.\n", hr);
5396 count = 0;
5397 hr = IMFMediaTypeHandler_GetMediaTypeCount(handler, &count);
5398 ok(hr == S_OK, "Failed to get type count, hr %#lx.\n", hr);
5399 ok(count == 1, "Unexpected count %lu.\n", count);
5401 hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, NULL);
5402 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
5404 media_type = (void *)0xdeadbeef;
5405 hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, &media_type);
5406 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5407 ok(!media_type, "Unexpected pointer.\n");
5409 hr = MFCreateMediaType(&media_type);
5410 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
5412 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type, NULL);
5413 ok(hr == MF_E_UNEXPECTED, "Unexpected hr %#lx.\n", hr);
5415 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, media_type);
5416 ok(hr == S_OK, "Failed to set current type, hr %#lx.\n", hr);
5418 hr = IMFMediaTypeHandler_GetMediaTypeByIndex(handler, 0, &media_type2);
5419 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5420 ok(media_type2 == media_type, "Unexpected type.\n");
5421 IMFMediaType_Release(media_type2);
5423 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, NULL, NULL);
5424 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
5426 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type, NULL);
5427 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
5429 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type, &media_type2);
5430 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
5432 hr = IMFMediaTypeHandler_GetMediaTypeByIndex(handler, 1, &media_type2);
5433 ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#lx.\n", hr);
5435 hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, &media_type2);
5436 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5437 ok(media_type == media_type2, "Unexpected pointer.\n");
5438 IMFMediaType_Release(media_type2);
5440 hr = IMFMediaTypeHandler_GetMajorType(handler, &guid);
5441 ok(hr == MF_E_ATTRIBUTENOTFOUND, "Unexpected hr %#lx.\n", hr);
5443 hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
5444 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
5446 hr = IMFMediaTypeHandler_GetMajorType(handler, &guid);
5447 ok(hr == S_OK, "Failed to get major type, hr %#lx.\n", hr);
5448 ok(IsEqualGUID(&guid, &MFMediaType_Video), "Unexpected major type.\n");
5450 hr = MFCreateMediaType(&media_type3);
5451 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
5453 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type3, NULL);
5454 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
5456 hr = IMFMediaType_SetGUID(media_type3, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio);
5457 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
5459 /* Different major types. */
5460 media_type2 = (void *)0xdeadbeef;
5461 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type3, &media_type2);
5462 ok(hr == E_FAIL, "Unexpected hr %#lx.\n", hr);
5463 ok(!media_type2, "Unexpected pointer.\n");
5465 hr = IMFMediaType_SetGUID(media_type3, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
5466 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
5468 media_type2 = (void *)0xdeadbeef;
5469 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type3, &media_type2);
5470 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5471 ok(!media_type2, "Unexpected pointer.\n");
5473 /* Handler missing subtype. */
5474 hr = IMFMediaType_SetGUID(media_type3, &MF_MT_SUBTYPE, &MFVideoFormat_RGB8);
5475 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
5477 media_type2 = (void *)0xdeadbeef;
5478 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type3, &media_type2);
5479 ok(hr == E_FAIL, "Unexpected hr %#lx.\n", hr);
5480 ok(!media_type2, "Unexpected pointer.\n");
5482 /* Different subtypes. */
5483 hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFVideoFormat_RGB24);
5484 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
5486 media_type2 = (void *)0xdeadbeef;
5487 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type3, &media_type2);
5488 ok(hr == E_FAIL, "Unexpected hr %#lx.\n", hr);
5489 ok(!media_type2, "Unexpected pointer.\n");
5491 /* Same major/subtype. */
5492 hr = IMFMediaType_SetGUID(media_type3, &MF_MT_SUBTYPE, &MFVideoFormat_RGB24);
5493 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
5495 media_type2 = (void *)0xdeadbeef;
5496 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type3, &media_type2);
5497 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5498 ok(!media_type2, "Unexpected pointer.\n");
5500 /* Set one more attribute. */
5501 hr = IMFMediaType_SetUINT64(media_type, &MF_MT_FRAME_SIZE, (UINT64)4 << 32 | 4);
5502 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
5504 media_type2 = (void *)0xdeadbeef;
5505 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type3, &media_type2);
5506 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5507 ok(!media_type2, "Unexpected pointer.\n");
5509 ref = IMFMediaType_Release(media_type3);
5510 ok(ref == 0, "Release returned %ld\n", ref);
5512 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, NULL);
5513 ok(hr == S_OK, "Failed to set current type, hr %#lx.\n", hr);
5515 media_type2 = (void *)0xdeadbeef;
5516 hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, &media_type2);
5517 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5518 ok(!media_type2, "Unexpected pointer.\n");
5520 hr = IMFMediaTypeHandler_GetMajorType(handler, &guid);
5521 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#lx.\n", hr);
5523 ref = IMFMediaTypeHandler_Release(handler);
5524 ok(ref == 0, "Release returned %ld\n", ref);
5525 ref = IMFMediaType_Release(media_type);
5526 ok(ref == 0, "Release returned %ld\n", ref);
5529 static void test_MFGetSupportedMimeTypes(void)
5531 PROPVARIANT value;
5532 HRESULT hr;
5534 hr = MFGetSupportedMimeTypes(NULL);
5535 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
5537 value.vt = VT_EMPTY;
5538 hr = MFGetSupportedMimeTypes(&value);
5539 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5540 ok(value.vt == (VT_VECTOR | VT_LPWSTR), "Unexpected value type %#x.\n", value.vt);
5542 PropVariantClear(&value);
5545 static void test_MFGetSupportedSchemes(void)
5547 PROPVARIANT value;
5548 HRESULT hr;
5550 hr = MFGetSupportedSchemes(NULL);
5551 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
5553 value.vt = VT_EMPTY;
5554 hr = MFGetSupportedSchemes(&value);
5555 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5556 ok(value.vt == (VT_VECTOR | VT_LPWSTR), "Unexpected value type %#x.\n", value.vt);
5558 PropVariantClear(&value);
5561 static BOOL is_sample_copier_available_type(IMFMediaType *type)
5563 GUID major = { 0 };
5564 UINT32 count;
5565 HRESULT hr;
5567 hr = IMFMediaType_GetMajorType(type, &major);
5568 ok(hr == S_OK, "Failed to get major type, hr %#lx.\n", hr);
5570 hr = IMFMediaType_GetCount(type, &count);
5571 ok(hr == S_OK, "Failed to get attribute count, hr %#lx.\n", hr);
5572 ok(count == 1, "Unexpected attribute count %u.\n", count);
5574 return IsEqualGUID(&major, &MFMediaType_Video) || IsEqualGUID(&major, &MFMediaType_Audio);
5577 static void test_sample_copier(void)
5579 IMFAttributes *attributes, *attributes2;
5580 DWORD in_min, in_max, out_min, out_max;
5581 IMFMediaType *mediatype, *mediatype2;
5582 MFT_OUTPUT_STREAM_INFO output_info;
5583 IMFSample *sample, *client_sample;
5584 MFT_INPUT_STREAM_INFO input_info;
5585 DWORD input_count, output_count;
5586 MFT_OUTPUT_DATA_BUFFER buffer;
5587 IMFMediaBuffer *media_buffer;
5588 IMFTransform *copier;
5589 DWORD flags, status;
5590 UINT32 value, count;
5591 HRESULT hr;
5592 LONG ref;
5594 if (!pMFCreateSampleCopierMFT)
5596 win_skip("MFCreateSampleCopierMFT() is not available.\n");
5597 return;
5600 hr = pMFCreateSampleCopierMFT(&copier);
5601 ok(hr == S_OK, "Failed to create sample copier, hr %#lx.\n", hr);
5603 hr = IMFTransform_GetAttributes(copier, &attributes);
5604 ok(hr == S_OK, "Failed to get transform attributes, hr %#lx.\n", hr);
5605 hr = IMFTransform_GetAttributes(copier, &attributes2);
5606 ok(hr == S_OK, "Failed to get transform attributes, hr %#lx.\n", hr);
5607 ok(attributes == attributes2, "Unexpected instance.\n");
5608 IMFAttributes_Release(attributes2);
5609 hr = IMFAttributes_GetCount(attributes, &count);
5610 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5611 ok(count == 1, "Unexpected attribute count %u.\n", count);
5612 hr = IMFAttributes_GetUINT32(attributes, &MFT_SUPPORT_DYNAMIC_FORMAT_CHANGE, &value);
5613 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5614 ok(!!value, "Unexpected value %u.\n", value);
5615 ref = IMFAttributes_Release(attributes);
5616 ok(ref == 1, "Release returned %ld\n", ref);
5618 hr = IMFTransform_GetInputStreamAttributes(copier, 0, &attributes);
5619 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
5621 hr = IMFTransform_GetInputStreamAttributes(copier, 1, &attributes);
5622 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
5624 hr = IMFTransform_GetOutputStreamAttributes(copier, 0, &attributes);
5625 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
5627 hr = IMFTransform_GetOutputStreamAttributes(copier, 1, &attributes);
5628 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
5630 hr = IMFTransform_SetOutputBounds(copier, 0, 0);
5631 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
5633 /* No dynamic streams. */
5634 input_count = output_count = 0;
5635 hr = IMFTransform_GetStreamCount(copier, &input_count, &output_count);
5636 ok(hr == S_OK, "Failed to get stream count, hr %#lx.\n", hr);
5637 ok(input_count == 1 && output_count == 1, "Unexpected streams count.\n");
5639 hr = IMFTransform_GetStreamLimits(copier, &in_min, &in_max, &out_min, &out_max);
5640 ok(hr == S_OK, "Failed to get stream limits, hr %#lx.\n", hr);
5641 ok(in_min == in_max && in_min == 1 && out_min == out_max && out_min == 1, "Unexpected stream limits.\n");
5643 hr = IMFTransform_GetStreamIDs(copier, 1, &input_count, 1, &output_count);
5644 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
5646 hr = IMFTransform_DeleteInputStream(copier, 0);
5647 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
5649 /* Available types. */
5650 hr = IMFTransform_GetInputAvailableType(copier, 0, 0, &mediatype);
5651 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5652 ok(is_sample_copier_available_type(mediatype), "Unexpected type.\n");
5653 IMFMediaType_Release(mediatype);
5655 hr = IMFTransform_GetInputAvailableType(copier, 0, 1, &mediatype);
5656 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5657 ok(is_sample_copier_available_type(mediatype), "Unexpected type.\n");
5658 IMFMediaType_Release(mediatype);
5660 hr = IMFTransform_GetInputAvailableType(copier, 0, 2, &mediatype);
5661 ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#lx.\n", hr);
5663 hr = IMFTransform_GetInputAvailableType(copier, 1, 0, &mediatype);
5664 ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#lx.\n", hr);
5666 hr = IMFTransform_GetOutputAvailableType(copier, 0, 0, &mediatype);
5667 ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#lx.\n", hr);
5669 hr = IMFTransform_GetOutputAvailableType(copier, 1, 0, &mediatype);
5670 ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#lx.\n", hr);
5672 hr = IMFTransform_GetInputCurrentType(copier, 0, &mediatype);
5673 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
5675 hr = IMFTransform_GetInputCurrentType(copier, 1, &mediatype);
5676 ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#lx.\n", hr);
5678 hr = IMFTransform_GetOutputCurrentType(copier, 0, &mediatype);
5679 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
5681 hr = IMFTransform_GetOutputCurrentType(copier, 1, &mediatype);
5682 ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#lx.\n", hr);
5684 hr = MFCreateSample(&sample);
5685 ok(hr == S_OK, "Failed to create a sample, hr %#lx.\n", hr);
5687 hr = IMFTransform_ProcessInput(copier, 0, sample, 0);
5688 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
5690 hr = MFCreateMediaType(&mediatype);
5691 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
5693 hr = IMFTransform_SetOutputType(copier, 0, mediatype, 0);
5694 ok(hr == MF_E_ATTRIBUTENOTFOUND, "Unexpected hr %#lx.\n", hr);
5696 hr = IMFMediaType_SetGUID(mediatype, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
5697 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
5699 hr = IMFMediaType_SetGUID(mediatype, &MF_MT_SUBTYPE, &MFVideoFormat_RGB8);
5700 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
5702 hr = IMFMediaType_SetUINT64(mediatype, &MF_MT_FRAME_SIZE, ((UINT64)16) << 32 | 16);
5703 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
5705 hr = IMFTransform_GetOutputStreamInfo(copier, 0, &output_info);
5706 ok(hr == S_OK, "Failed to get stream info, hr %#lx.\n", hr);
5707 ok(!output_info.dwFlags, "Unexpected flags %#lx.\n", output_info.dwFlags);
5708 ok(!output_info.cbSize, "Unexpected size %lu.\n", output_info.cbSize);
5709 ok(!output_info.cbAlignment, "Unexpected alignment %lu.\n", output_info.cbAlignment);
5711 hr = IMFTransform_GetInputStreamInfo(copier, 0, &input_info);
5712 ok(hr == S_OK, "Failed to get stream info, hr %#lx.\n", hr);
5714 ok(!input_info.hnsMaxLatency, "Unexpected latency %s.\n", wine_dbgstr_longlong(input_info.hnsMaxLatency));
5715 ok(!input_info.dwFlags, "Unexpected flags %#lx.\n", input_info.dwFlags);
5716 ok(!input_info.cbSize, "Unexpected size %lu.\n", input_info.cbSize);
5717 ok(!input_info.cbMaxLookahead, "Unexpected lookahead size %lu.\n", input_info.cbMaxLookahead);
5718 ok(!input_info.cbAlignment, "Unexpected alignment %lu.\n", input_info.cbAlignment);
5720 hr = IMFTransform_SetOutputType(copier, 0, mediatype, 0);
5721 ok(hr == S_OK, "Failed to set input type, hr %#lx.\n", hr);
5723 hr = IMFTransform_GetOutputStreamInfo(copier, 0, &output_info);
5724 ok(hr == S_OK, "Failed to get stream info, hr %#lx.\n", hr);
5725 ok(!output_info.dwFlags, "Unexpected flags %#lx.\n", output_info.dwFlags);
5726 ok(output_info.cbSize == 16 * 16, "Unexpected size %lu.\n", output_info.cbSize);
5727 ok(!output_info.cbAlignment, "Unexpected alignment %lu.\n", output_info.cbAlignment);
5729 hr = IMFTransform_GetOutputCurrentType(copier, 0, &mediatype2);
5730 ok(hr == S_OK, "Failed to get current type, hr %#lx.\n", hr);
5731 IMFMediaType_Release(mediatype2);
5733 hr = IMFTransform_GetInputCurrentType(copier, 0, &mediatype2);
5734 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
5736 hr = IMFTransform_GetInputStatus(copier, 0, &flags);
5737 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
5739 /* Setting input type resets output type. */
5740 hr = IMFTransform_GetOutputCurrentType(copier, 0, &mediatype2);
5741 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5742 IMFMediaType_Release(mediatype2);
5744 hr = IMFTransform_SetInputType(copier, 0, mediatype, 0);
5745 ok(hr == S_OK, "Failed to set input type, hr %#lx.\n", hr);
5747 hr = IMFTransform_GetOutputCurrentType(copier, 0, &mediatype2);
5748 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
5750 hr = IMFTransform_GetInputAvailableType(copier, 0, 1, &mediatype2);
5751 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5752 ok(is_sample_copier_available_type(mediatype2), "Unexpected type.\n");
5753 IMFMediaType_Release(mediatype2);
5755 hr = IMFTransform_GetInputStreamInfo(copier, 0, &input_info);
5756 ok(hr == S_OK, "Failed to get stream info, hr %#lx.\n", hr);
5757 ok(!input_info.hnsMaxLatency, "Unexpected latency %s.\n", wine_dbgstr_longlong(input_info.hnsMaxLatency));
5758 ok(!input_info.dwFlags, "Unexpected flags %#lx.\n", input_info.dwFlags);
5759 ok(input_info.cbSize == 16 * 16, "Unexpected size %lu.\n", input_info.cbSize);
5760 ok(!input_info.cbMaxLookahead, "Unexpected lookahead size %lu.\n", input_info.cbMaxLookahead);
5761 ok(!input_info.cbAlignment, "Unexpected alignment %lu.\n", input_info.cbAlignment);
5763 hr = IMFTransform_GetOutputAvailableType(copier, 0, 0, &mediatype2);
5764 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5765 hr = IMFMediaType_IsEqual(mediatype2, mediatype, &flags);
5766 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5767 IMFMediaType_Release(mediatype2);
5769 hr = IMFTransform_GetInputStatus(copier, 0, &flags);
5770 ok(hr == S_OK, "Failed to get input status, hr %#lx.\n", hr);
5771 ok(flags == MFT_INPUT_STATUS_ACCEPT_DATA, "Unexpected flags %#lx.\n", flags);
5773 hr = IMFTransform_GetInputCurrentType(copier, 0, &mediatype2);
5774 ok(hr == S_OK, "Failed to get current type, hr %#lx.\n", hr);
5775 IMFMediaType_Release(mediatype2);
5777 hr = IMFTransform_GetOutputStatus(copier, &flags);
5778 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
5780 hr = IMFTransform_SetOutputType(copier, 0, mediatype, 0);
5781 ok(hr == S_OK, "Failed to set output type, hr %#lx.\n", hr);
5783 hr = IMFTransform_GetOutputStatus(copier, &flags);
5784 ok(hr == S_OK, "Failed to get output status, hr %#lx.\n", hr);
5785 ok(!flags, "Unexpected flags %#lx.\n", flags);
5787 /* Pushing samples. */
5788 hr = MFCreateAlignedMemoryBuffer(output_info.cbSize, output_info.cbAlignment, &media_buffer);
5789 ok(hr == S_OK, "Failed to create media buffer, hr %#lx.\n", hr);
5791 hr = IMFSample_AddBuffer(sample, media_buffer);
5792 ok(hr == S_OK, "Failed to add a buffer, hr %#lx.\n", hr);
5793 IMFMediaBuffer_Release(media_buffer);
5795 EXPECT_REF(sample, 1);
5796 hr = IMFTransform_ProcessInput(copier, 0, sample, 0);
5797 ok(hr == S_OK, "Failed to process input, hr %#lx.\n", hr);
5798 EXPECT_REF(sample, 2);
5800 hr = IMFTransform_GetInputStatus(copier, 0, &flags);
5801 ok(hr == S_OK, "Failed to get input status, hr %#lx.\n", hr);
5802 ok(!flags, "Unexpected flags %#lx.\n", flags);
5804 hr = IMFTransform_GetOutputStatus(copier, &flags);
5805 ok(hr == S_OK, "Failed to get output status, hr %#lx.\n", hr);
5806 ok(flags == MFT_OUTPUT_STATUS_SAMPLE_READY, "Unexpected flags %#lx.\n", flags);
5808 hr = IMFTransform_ProcessInput(copier, 0, sample, 0);
5809 ok(hr == MF_E_NOTACCEPTING, "Unexpected hr %#lx.\n", hr);
5811 hr = IMFTransform_GetOutputStreamInfo(copier, 0, &output_info);
5812 ok(hr == S_OK, "Failed to get output info, hr %#lx.\n", hr);
5814 hr = MFCreateAlignedMemoryBuffer(output_info.cbSize, output_info.cbAlignment, &media_buffer);
5815 ok(hr == S_OK, "Failed to create media buffer, hr %#lx.\n", hr);
5817 hr = MFCreateSample(&client_sample);
5818 ok(hr == S_OK, "Failed to create a sample, hr %#lx.\n", hr);
5820 hr = IMFSample_AddBuffer(client_sample, media_buffer);
5821 ok(hr == S_OK, "Failed to add a buffer, hr %#lx.\n", hr);
5822 IMFMediaBuffer_Release(media_buffer);
5824 status = 0;
5825 memset(&buffer, 0, sizeof(buffer));
5826 buffer.pSample = client_sample;
5827 hr = IMFTransform_ProcessOutput(copier, 0, 1, &buffer, &status);
5828 ok(hr == S_OK, "Failed to get output, hr %#lx.\n", hr);
5829 EXPECT_REF(sample, 1);
5831 hr = IMFTransform_ProcessOutput(copier, 0, 1, &buffer, &status);
5832 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "Failed to get output, hr %#lx.\n", hr);
5834 /* Flushing. */
5835 hr = IMFTransform_ProcessInput(copier, 0, sample, 0);
5836 ok(hr == S_OK, "Failed to process input, hr %#lx.\n", hr);
5837 EXPECT_REF(sample, 2);
5839 hr = IMFTransform_ProcessMessage(copier, MFT_MESSAGE_COMMAND_FLUSH, 0);
5840 ok(hr == S_OK, "Failed to flush, hr %#lx.\n", hr);
5842 ref = IMFSample_Release(sample);
5843 ok(ref == 0, "Release returned %ld\n", ref);
5844 ref = IMFSample_Release(client_sample);
5845 ok(ref == 0, "Release returned %ld\n", ref);
5847 ref = IMFTransform_Release(copier);
5848 ok(ref == 0, "Release returned %ld\n", ref);
5849 ref = IMFMediaType_Release(mediatype);
5850 ok(ref == 0, "Release returned %ld\n", ref);
5853 struct sample_metadata
5855 unsigned int flags;
5856 LONGLONG duration;
5857 LONGLONG time;
5860 static void sample_copier_process(IMFTransform *copier, IMFMediaBuffer *input_buffer,
5861 IMFMediaBuffer *output_buffer, const struct sample_metadata *md)
5863 static const struct sample_metadata zero_md = { 0, ~0u, ~0u };
5864 IMFSample *input_sample, *output_sample;
5865 MFT_OUTPUT_DATA_BUFFER buffer;
5866 DWORD flags, status;
5867 LONGLONG time;
5868 HRESULT hr;
5869 LONG ref;
5871 hr = MFCreateSample(&input_sample);
5872 ok(hr == S_OK, "Failed to create a sample, hr %#lx.\n", hr);
5874 if (md)
5876 hr = IMFSample_SetSampleFlags(input_sample, md->flags);
5877 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5879 hr = IMFSample_SetSampleTime(input_sample, md->time);
5880 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5882 hr = IMFSample_SetSampleDuration(input_sample, md->duration);
5883 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5886 hr = MFCreateSample(&output_sample);
5887 ok(hr == S_OK, "Failed to create a sample, hr %#lx.\n", hr);
5889 hr = IMFSample_SetSampleFlags(output_sample, ~0u);
5890 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5892 hr = IMFSample_SetSampleTime(output_sample, ~0u);
5893 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5895 hr = IMFSample_SetSampleDuration(output_sample, ~0u);
5896 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5898 hr = IMFSample_AddBuffer(input_sample, input_buffer);
5899 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5901 hr = IMFSample_AddBuffer(output_sample, output_buffer);
5902 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5904 hr = IMFTransform_ProcessInput(copier, 0, input_sample, 0);
5905 ok(hr == S_OK, "Failed to process input, hr %#lx.\n", hr);
5907 status = 0;
5908 memset(&buffer, 0, sizeof(buffer));
5909 buffer.pSample = output_sample;
5910 hr = IMFTransform_ProcessOutput(copier, 0, 1, &buffer, &status);
5911 ok(hr == S_OK, "Failed to get output, hr %#lx.\n", hr);
5913 if (!md) md = &zero_md;
5915 hr = IMFSample_GetSampleFlags(output_sample, &flags);
5916 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5917 ok(md->flags == flags, "Unexpected flags.\n");
5918 hr = IMFSample_GetSampleTime(output_sample, &time);
5919 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5920 ok(md->time == time, "Unexpected time.\n");
5921 hr = IMFSample_GetSampleDuration(output_sample, &time);
5922 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5923 ok(md->duration == time, "Unexpected duration.\n");
5925 ref = IMFSample_Release(input_sample);
5926 ok(ref == 0, "Release returned %ld\n", ref);
5927 ref = IMFSample_Release(output_sample);
5928 ok(ref == 0, "Release returned %ld\n", ref);
5931 static void test_sample_copier_output_processing(void)
5933 IMFMediaBuffer *input_buffer, *output_buffer;
5934 MFT_OUTPUT_STREAM_INFO output_info;
5935 struct sample_metadata md;
5936 IMFMediaType *mediatype;
5937 IMFTransform *copier;
5938 DWORD max_length;
5939 HRESULT hr;
5940 BYTE *ptr;
5941 LONG ref;
5943 if (!pMFCreateSampleCopierMFT)
5944 return;
5946 hr = pMFCreateSampleCopierMFT(&copier);
5947 ok(hr == S_OK, "Failed to create sample copier, hr %#lx.\n", hr);
5949 /* Configure for 16 x 16 of D3DFMT_X8R8G8B8. */
5950 hr = MFCreateMediaType(&mediatype);
5951 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
5953 hr = IMFMediaType_SetGUID(mediatype, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
5954 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
5956 hr = IMFMediaType_SetGUID(mediatype, &MF_MT_SUBTYPE, &MFVideoFormat_RGB32);
5957 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
5959 hr = IMFMediaType_SetUINT64(mediatype, &MF_MT_FRAME_SIZE, ((UINT64)16) << 32 | 16);
5960 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
5962 hr = IMFTransform_SetInputType(copier, 0, mediatype, 0);
5963 ok(hr == S_OK, "Failed to set input type, hr %#lx.\n", hr);
5965 hr = IMFTransform_SetOutputType(copier, 0, mediatype, 0);
5966 ok(hr == S_OK, "Failed to set input type, hr %#lx.\n", hr);
5968 /* Source and destination are linear buffers, destination is twice as large. */
5969 hr = IMFTransform_GetOutputStreamInfo(copier, 0, &output_info);
5970 ok(hr == S_OK, "Failed to get output info, hr %#lx.\n", hr);
5972 hr = MFCreateAlignedMemoryBuffer(output_info.cbSize, output_info.cbAlignment, &output_buffer);
5973 ok(hr == S_OK, "Failed to create media buffer, hr %#lx.\n", hr);
5975 hr = IMFMediaBuffer_Lock(output_buffer, &ptr, &max_length, NULL);
5976 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5977 memset(ptr, 0xcc, max_length);
5978 hr = IMFMediaBuffer_Unlock(output_buffer);
5979 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5981 hr = MFCreateAlignedMemoryBuffer(output_info.cbSize, output_info.cbAlignment, &input_buffer);
5982 ok(hr == S_OK, "Failed to create media buffer, hr %#lx.\n", hr);
5984 hr = IMFMediaBuffer_Lock(input_buffer, &ptr, &max_length, NULL);
5985 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5986 memset(ptr, 0xaa, max_length);
5987 hr = IMFMediaBuffer_Unlock(input_buffer);
5988 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5989 hr = IMFMediaBuffer_SetCurrentLength(input_buffer, 4);
5990 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5992 sample_copier_process(copier, input_buffer, output_buffer, NULL);
5994 hr = IMFMediaBuffer_Lock(output_buffer, &ptr, &max_length, NULL);
5995 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5996 ok(ptr[0] == 0xaa && ptr[4] == 0xcc, "Unexpected buffer contents.\n");
5998 hr = IMFMediaBuffer_Unlock(output_buffer);
5999 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6001 md.flags = 123;
6002 md.time = 10;
6003 md.duration = 2;
6004 sample_copier_process(copier, input_buffer, output_buffer, &md);
6006 ref = IMFMediaBuffer_Release(input_buffer);
6007 ok(ref == 0, "Release returned %ld\n", ref);
6008 ref = IMFMediaBuffer_Release(output_buffer);
6009 ok(ref == 0, "Release returned %ld\n", ref);
6011 ref = IMFTransform_Release(copier);
6012 ok(ref == 0, "Release returned %ld\n", ref);
6013 ref = IMFMediaType_Release(mediatype);
6014 ok(ref == 0, "Release returned %ld\n", ref);
6017 static void test_MFGetTopoNodeCurrentType(void)
6019 static const struct attribute_desc media_type_desc[] =
6021 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
6022 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12),
6023 ATTR_RATIO(MF_MT_FRAME_SIZE, 1920, 1080),
6024 {0},
6026 IMFMediaType *media_type, *input_types[2], *output_types[2];
6027 IMFStreamDescriptor *input_descriptor, *output_descriptor;
6028 struct test_stream_sink stream_sink = test_stream_sink;
6029 IMFMediaTypeHandler *input_handler, *output_handler;
6030 IMFTransform *transform;
6031 IMFTopologyNode *node;
6032 DWORD flags;
6033 HRESULT hr;
6034 LONG ref;
6036 if (!pMFGetTopoNodeCurrentType)
6038 win_skip("MFGetTopoNodeCurrentType() is unsupported.\n");
6039 return;
6042 hr = CoInitialize(NULL);
6043 ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
6045 hr = MFCreateMediaType(&input_types[0]);
6046 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
6047 init_media_type(input_types[0], media_type_desc, -1);
6048 hr = MFCreateMediaType(&input_types[1]);
6049 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
6050 init_media_type(input_types[1], media_type_desc, -1);
6051 hr = MFCreateMediaType(&output_types[0]);
6052 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
6053 init_media_type(output_types[0], media_type_desc, -1);
6054 hr = MFCreateMediaType(&output_types[1]);
6055 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
6056 init_media_type(output_types[1], media_type_desc, -1);
6058 hr = MFCreateStreamDescriptor(0, 2, input_types, &input_descriptor);
6059 ok(hr == S_OK, "Failed to create IMFStreamDescriptor hr %#lx.\n", hr);
6060 hr = IMFStreamDescriptor_GetMediaTypeHandler(input_descriptor, &input_handler);
6061 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6062 hr = MFCreateStreamDescriptor(0, 2, output_types, &output_descriptor);
6063 ok(hr == S_OK, "Failed to create IMFStreamDescriptor hr %#lx.\n", hr);
6064 hr = IMFStreamDescriptor_GetMediaTypeHandler(output_descriptor, &output_handler);
6065 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6067 hr = CoCreateInstance(&CLSID_CColorConvertDMO, NULL, CLSCTX_INPROC_SERVER, &IID_IMFTransform, (void **)&transform);
6068 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6071 /* Tee node. */
6072 hr = MFCreateTopologyNode(MF_TOPOLOGY_TEE_NODE, &node);
6073 ok(hr == S_OK, "Failed to create a node, hr %#lx.\n", hr);
6074 hr = pMFGetTopoNodeCurrentType(node, 0, TRUE, &media_type);
6075 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
6076 hr = pMFGetTopoNodeCurrentType(node, 0, FALSE, &media_type);
6077 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
6079 /* Set second output. */
6080 hr = IMFTopologyNode_SetOutputPrefType(node, 1, output_types[1]);
6081 ok(hr == S_OK, "Failed to set media type, hr %#lx.\n", hr);
6082 hr = pMFGetTopoNodeCurrentType(node, 0, TRUE, &media_type);
6083 ok(hr == E_FAIL, "Unexpected hr %#lx.\n", hr);
6084 hr = pMFGetTopoNodeCurrentType(node, 0, FALSE, &media_type);
6085 ok(hr == E_FAIL, "Unexpected hr %#lx.\n", hr);
6086 hr = pMFGetTopoNodeCurrentType(node, 1, TRUE, &media_type);
6087 ok(hr == E_FAIL, "Unexpected hr %#lx.\n", hr);
6088 hr = pMFGetTopoNodeCurrentType(node, 1, FALSE, &media_type);
6089 ok(hr == E_FAIL, "Unexpected hr %#lx.\n", hr);
6091 /* Set first output. */
6092 hr = IMFTopologyNode_SetOutputPrefType(node, 0, output_types[0]);
6093 ok(hr == S_OK, "Failed to set media type, hr %#lx.\n", hr);
6094 hr = pMFGetTopoNodeCurrentType(node, 0, TRUE, &media_type);
6095 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6096 ok(media_type == output_types[0], "Unexpected pointer.\n");
6097 IMFMediaType_Release(media_type);
6098 hr = pMFGetTopoNodeCurrentType(node, 1, TRUE, &media_type);
6099 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6100 ok(media_type == output_types[0], "Unexpected pointer.\n");
6101 IMFMediaType_Release(media_type);
6102 hr = pMFGetTopoNodeCurrentType(node, 0, FALSE, &media_type);
6103 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6104 ok(media_type == output_types[0], "Unexpected pointer.\n");
6105 IMFMediaType_Release(media_type);
6107 /* Set primary output. */
6108 hr = IMFTopologyNode_SetOutputPrefType(node, 1, output_types[1]);
6109 ok(hr == S_OK, "Failed to set media type, hr %#lx.\n", hr);
6110 hr = IMFTopologyNode_SetUINT32(node, &MF_TOPONODE_PRIMARYOUTPUT, 1);
6111 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
6112 hr = pMFGetTopoNodeCurrentType(node, 0, TRUE, &media_type);
6113 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6114 ok(media_type == output_types[1], "Unexpected pointer.\n");
6115 IMFMediaType_Release(media_type);
6116 hr = pMFGetTopoNodeCurrentType(node, 0, FALSE, &media_type);
6117 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6118 ok(media_type == output_types[1], "Unexpected pointer.\n");
6119 IMFMediaType_Release(media_type);
6120 hr = pMFGetTopoNodeCurrentType(node, 1, FALSE, &media_type);
6121 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6122 ok(media_type == output_types[1], "Unexpected pointer.\n");
6123 IMFMediaType_Release(media_type);
6125 /* Input type returned, if set. */
6126 hr = IMFTopologyNode_SetInputPrefType(node, 0, input_types[0]);
6127 ok(hr == S_OK, "Failed to set media type, hr %#lx.\n", hr);
6128 hr = pMFGetTopoNodeCurrentType(node, 0, FALSE, &media_type);
6129 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6130 ok(media_type == input_types[0], "Unexpected pointer.\n");
6131 IMFMediaType_Release(media_type);
6132 hr = pMFGetTopoNodeCurrentType(node, 0, TRUE, &media_type);
6133 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6134 ok(media_type == input_types[0], "Unexpected pointer.\n");
6135 IMFMediaType_Release(media_type);
6137 hr = IMFTopologyNode_SetInputPrefType(node, 0, NULL);
6138 ok(hr == S_OK, "Failed to set media type, hr %#lx.\n", hr);
6139 hr = IMFTopologyNode_SetOutputPrefType(node, 0, NULL);
6140 ok(hr == S_OK, "Failed to set media type, hr %#lx.\n", hr);
6141 hr = IMFTopologyNode_SetOutputPrefType(node, 1, NULL);
6142 ok(hr == S_OK, "Failed to set media type, hr %#lx.\n", hr);
6143 ref = IMFTopologyNode_Release(node);
6144 ok(ref == 0, "Release returned %ld\n", ref);
6147 /* Source node. */
6148 hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &node);
6149 ok(hr == S_OK, "Failed to create a node, hr %#lx.\n", hr);
6150 hr = pMFGetTopoNodeCurrentType(node, 0, TRUE, &media_type);
6151 ok(hr == MF_E_ATTRIBUTENOTFOUND, "Unexpected hr %#lx.\n", hr);
6152 hr = pMFGetTopoNodeCurrentType(node, 1, TRUE, &media_type);
6153 ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#lx.\n", hr);
6154 hr = pMFGetTopoNodeCurrentType(node, 0, FALSE, &media_type);
6155 ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#lx.\n", hr);
6157 hr = IMFTopologyNode_SetUnknown(node, &MF_TOPONODE_STREAM_DESCRIPTOR, (IUnknown *)input_descriptor);
6158 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6159 hr = pMFGetTopoNodeCurrentType(node, 0, TRUE, &media_type);
6160 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#lx.\n", hr);
6162 hr = IMFMediaTypeHandler_SetCurrentMediaType(input_handler, output_types[0]);
6163 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6164 hr = pMFGetTopoNodeCurrentType(node, 0, TRUE, &media_type);
6165 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6166 ok(media_type == output_types[0], "Unexpected pointer.\n");
6167 IMFMediaType_Release(media_type);
6169 ref = IMFTopologyNode_Release(node);
6170 ok(ref == 0, "Release returned %ld\n", ref);
6173 /* Output node. */
6174 hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, &node);
6175 ok(hr == S_OK, "Failed to create a node, hr %#lx.\n", hr);
6176 hr = pMFGetTopoNodeCurrentType(node, 0, FALSE, &media_type);
6177 ok(hr == E_FAIL, "Unexpected hr %#lx.\n", hr);
6178 hr = pMFGetTopoNodeCurrentType(node, 1, FALSE, &media_type);
6179 ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#lx.\n", hr);
6180 hr = pMFGetTopoNodeCurrentType(node, 0, TRUE, &media_type);
6181 ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#lx.\n", hr);
6183 stream_sink.handler = output_handler;
6184 hr = IMFTopologyNode_SetObject(node, (IUnknown *)&stream_sink.IMFStreamSink_iface);
6185 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6186 hr = pMFGetTopoNodeCurrentType(node, 0, FALSE, &media_type);
6187 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#lx.\n", hr);
6189 hr = IMFMediaTypeHandler_SetCurrentMediaType(output_handler, input_types[0]);
6190 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6191 hr = pMFGetTopoNodeCurrentType(node, 0, FALSE, &media_type);
6192 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6193 ok(media_type == input_types[0], "Unexpected pointer.\n");
6194 IMFMediaType_Release(media_type);
6196 ref = IMFTopologyNode_Release(node);
6197 ok(ref == 0, "Release returned %ld\n", ref);
6200 /* Transform node. */
6201 hr = MFCreateTopologyNode(MF_TOPOLOGY_TRANSFORM_NODE, &node);
6202 ok(hr == S_OK, "Failed to create a node, hr %#lx.\n", hr);
6203 hr = pMFGetTopoNodeCurrentType(node, 0, TRUE, &media_type);
6204 ok(hr == E_FAIL, "Unexpected hr %#lx.\n", hr);
6205 hr = pMFGetTopoNodeCurrentType(node, 1, TRUE, &media_type);
6206 ok(hr == E_FAIL, "Unexpected hr %#lx.\n", hr);
6207 hr = pMFGetTopoNodeCurrentType(node, 0, FALSE, &media_type);
6208 ok(hr == E_FAIL, "Unexpected hr %#lx.\n", hr);
6209 hr = pMFGetTopoNodeCurrentType(node, 1, FALSE, &media_type);
6210 ok(hr == E_FAIL, "Unexpected hr %#lx.\n", hr);
6212 hr = IMFTopologyNode_SetObject(node, (IUnknown *)transform);
6213 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6214 hr = pMFGetTopoNodeCurrentType(node, 0, TRUE, &media_type);
6215 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
6216 hr = pMFGetTopoNodeCurrentType(node, 1, TRUE, &media_type);
6217 ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#lx.\n", hr);
6218 hr = pMFGetTopoNodeCurrentType(node, 0, FALSE, &media_type);
6219 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
6220 hr = pMFGetTopoNodeCurrentType(node, 1, FALSE, &media_type);
6221 ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#lx.\n", hr);
6223 hr = IMFTransform_SetInputType(transform, 0, input_types[0], 0);
6224 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6225 hr = pMFGetTopoNodeCurrentType(node, 0, TRUE, &media_type);
6226 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
6227 hr = pMFGetTopoNodeCurrentType(node, 0, FALSE, &media_type);
6228 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6229 hr = IMFMediaType_IsEqual(media_type, input_types[0], &flags);
6230 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6231 IMFMediaType_Release(media_type);
6233 hr = IMFTransform_SetOutputType(transform, 0, output_types[0], 0);
6234 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6235 hr = pMFGetTopoNodeCurrentType(node, 0, TRUE, &media_type);
6236 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6237 hr = IMFMediaType_IsEqual(media_type, output_types[0], &flags);
6238 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6239 IMFMediaType_Release(media_type);
6241 ref = IMFTopologyNode_Release(node);
6242 ok(ref == 0, "Release returned %ld\n", ref);
6245 ref = IMFTransform_Release(transform);
6246 ok(ref == 0, "Release returned %ld\n", ref);
6248 IMFMediaTypeHandler_Release(input_handler);
6249 IMFMediaTypeHandler_Release(output_handler);
6250 ref = IMFStreamDescriptor_Release(input_descriptor);
6251 ok(ref == 0, "Release returned %ld\n", ref);
6252 ref = IMFStreamDescriptor_Release(output_descriptor);
6253 ok(ref == 0, "Release returned %ld\n", ref);
6255 ref = IMFMediaType_Release(input_types[0]);
6256 ok(ref == 0, "Release returned %ld\n", ref);
6257 ref = IMFMediaType_Release(input_types[1]);
6258 ok(ref == 0, "Release returned %ld\n", ref);
6259 ref = IMFMediaType_Release(output_types[0]);
6260 ok(ref == 0, "Release returned %ld\n", ref);
6261 ref = IMFMediaType_Release(output_types[1]);
6262 ok(ref == 0, "Release returned %ld\n", ref);
6264 CoUninitialize();
6267 static void init_functions(void)
6269 HMODULE mod = GetModuleHandleA("mf.dll");
6271 #define X(f) p##f = (void*)GetProcAddress(mod, #f)
6272 X(MFCreateSampleCopierMFT);
6273 X(MFGetTopoNodeCurrentType);
6274 #undef X
6277 static void test_MFRequireProtectedEnvironment(void)
6279 IMFPresentationDescriptor *pd;
6280 IMFMediaType *mediatype;
6281 IMFStreamDescriptor *sd;
6282 HRESULT hr;
6283 LONG ref;
6285 hr = MFCreateMediaType(&mediatype);
6286 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6288 hr = MFCreateStreamDescriptor(0, 1, &mediatype, &sd);
6289 ok(hr == S_OK, "Failed to create stream descriptor, hr %#lx.\n", hr);
6291 hr = MFCreatePresentationDescriptor(1, &sd, &pd);
6292 ok(hr == S_OK, "Failed to create presentation descriptor, hr %#lx.\n", hr);
6294 hr = IMFPresentationDescriptor_SelectStream(pd, 0);
6295 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6297 hr = MFRequireProtectedEnvironment(pd);
6298 ok(hr == S_FALSE, "Unexpected hr %#lx.\n", hr);
6300 hr = IMFStreamDescriptor_SetUINT32(sd, &MF_SD_PROTECTED, 1);
6301 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6303 hr = MFRequireProtectedEnvironment(pd);
6304 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6306 hr = IMFPresentationDescriptor_DeselectStream(pd, 0);
6307 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6309 hr = MFRequireProtectedEnvironment(pd);
6310 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6312 ref = IMFPresentationDescriptor_Release(pd);
6313 ok(ref == 0, "Release returned %ld\n", ref);
6314 ref = IMFStreamDescriptor_Release(sd);
6315 ok(ref == 0, "Release returned %ld\n", ref);
6316 ref = IMFMediaType_Release(mediatype);
6317 ok(ref == 0, "Release returned %ld\n", ref);
6320 static IMFSample *create_sample(const BYTE *data, ULONG size)
6322 IMFMediaBuffer *media_buffer;
6323 IMFSample *sample;
6324 DWORD length;
6325 BYTE *buffer;
6326 HRESULT hr;
6327 ULONG ret;
6329 hr = MFCreateSample(&sample);
6330 ok(hr == S_OK, "MFCreateSample returned %#lx\n", hr);
6331 hr = MFCreateMemoryBuffer(size, &media_buffer);
6332 ok(hr == S_OK, "MFCreateMemoryBuffer returned %#lx\n", hr);
6333 hr = IMFMediaBuffer_Lock(media_buffer, &buffer, NULL, &length);
6334 ok(hr == S_OK, "Lock returned %#lx\n", hr);
6335 ok(length == 0, "got length %lu\n", length);
6336 if (!data) memset(buffer, 0xcd, size);
6337 else memcpy(buffer, data, size);
6338 hr = IMFMediaBuffer_Unlock(media_buffer);
6339 ok(hr == S_OK, "Unlock returned %#lx\n", hr);
6340 hr = IMFMediaBuffer_SetCurrentLength(media_buffer, data ? size : 0);
6341 ok(hr == S_OK, "SetCurrentLength returned %#lx\n", hr);
6342 hr = IMFSample_AddBuffer(sample, media_buffer);
6343 ok(hr == S_OK, "AddBuffer returned %#lx\n", hr);
6344 ret = IMFMediaBuffer_Release(media_buffer);
6345 ok(ret == 1, "Release returned %lu\n", ret);
6347 return sample;
6350 #define check_sample(a, b, c) check_sample_(__LINE__, a, b, c)
6351 static void check_sample_(int line, IMFSample *sample, const BYTE *expect_buf, HANDLE output_file)
6353 IMFMediaBuffer *media_buffer;
6354 DWORD length;
6355 BYTE *buffer;
6356 HRESULT hr;
6357 ULONG ret;
6359 hr = IMFSample_ConvertToContiguousBuffer(sample, &media_buffer);
6360 ok_(__FILE__, line)(hr == S_OK, "ConvertToContiguousBuffer returned %#lx\n", hr);
6361 hr = IMFMediaBuffer_Lock(media_buffer, &buffer, NULL, &length);
6362 ok_(__FILE__, line)(hr == S_OK, "Lock returned %#lx\n", hr);
6363 ok_(__FILE__, line)(!memcmp(expect_buf, buffer, length), "unexpected buffer data\n");
6364 if (output_file) WriteFile(output_file, buffer, length, &length, NULL);
6365 hr = IMFMediaBuffer_Unlock(media_buffer);
6366 ok_(__FILE__, line)(hr == S_OK, "Unlock returned %#lx\n", hr);
6367 ret = IMFMediaBuffer_Release(media_buffer);
6368 ok_(__FILE__, line)(ret == 1, "Release returned %lu\n", ret);
6371 #define check_sample_rgb32(a, b, c) check_sample_rgb32_(__LINE__, a, b, c)
6372 static void check_sample_rgb32_(int line, IMFSample *sample, const BYTE *expect_buf, HANDLE output_file)
6374 DWORD i, length, diff = 0, max_diff;
6375 IMFMediaBuffer *media_buffer;
6376 BYTE *buffer;
6377 HRESULT hr;
6378 ULONG ret;
6380 hr = IMFSample_ConvertToContiguousBuffer(sample, &media_buffer);
6381 ok_(__FILE__, line)(hr == S_OK, "ConvertToContiguousBuffer returned %#lx\n", hr);
6382 hr = IMFMediaBuffer_Lock(media_buffer, &buffer, NULL, &length);
6383 ok_(__FILE__, line)(hr == S_OK, "Lock returned %#lx\n", hr);
6385 /* check that buffer values are "close" enough, there's some pretty big
6386 * differences with the color converter between ffmpeg and native.
6388 for (i = 0; i < length; i++)
6390 if (i % 4 == 3) continue; /* ignore alpha diff */
6391 diff += abs((int)expect_buf[i] - (int)buffer[i]);
6393 max_diff = length * 3 * 256;
6394 ok_(__FILE__, line)(diff * 100 / max_diff == 0, "unexpected buffer data\n");
6396 if (output_file) WriteFile(output_file, buffer, length, &length, NULL);
6397 hr = IMFMediaBuffer_Unlock(media_buffer);
6398 ok_(__FILE__, line)(hr == S_OK, "Unlock returned %#lx\n", hr);
6399 ret = IMFMediaBuffer_Release(media_buffer);
6400 ok_(__FILE__, line)(ret == 1, "Release returned %lu\n", ret);
6403 #define check_sample_pcm16(a, b, c, d) check_sample_pcm16_(__LINE__, a, b, c, d)
6404 static void check_sample_pcm16_(int line, IMFSample *sample, const BYTE *expect_buf, HANDLE output_file, BOOL todo)
6406 IMFMediaBuffer *media_buffer;
6407 DWORD i, length;
6408 BYTE *buffer;
6409 HRESULT hr;
6410 ULONG ret;
6412 hr = IMFSample_ConvertToContiguousBuffer(sample, &media_buffer);
6413 ok_(__FILE__, line)(hr == S_OK, "ConvertToContiguousBuffer returned %#lx\n", hr);
6414 hr = IMFMediaBuffer_Lock(media_buffer, &buffer, NULL, &length);
6415 ok_(__FILE__, line)(hr == S_OK, "Lock returned %#lx\n", hr);
6417 /* check that buffer values are close enough, there's some differences in
6418 * the output of audio DSP between 32bit and 64bit implementation
6420 for (i = 0; i < length; i += 2)
6422 DWORD expect = *(INT16 *)(expect_buf + i), value = *(INT16 *)(buffer + i);
6423 if (expect - value + 512 > 1024) break;
6426 todo_wine_if(todo && i < length / 2)
6427 ok_(__FILE__, line)(i == length, "unexpected buffer data\n");
6429 if (output_file) WriteFile(output_file, buffer, length, &length, NULL);
6430 hr = IMFMediaBuffer_Unlock(media_buffer);
6431 ok_(__FILE__, line)(hr == S_OK, "Unlock returned %#lx\n", hr);
6432 ret = IMFMediaBuffer_Release(media_buffer);
6433 ok_(__FILE__, line)(ret == 1, "Release returned %lu\n", ret);
6436 static const BYTE wma_codec_data[10] = {0, 0x44, 0, 0, 0x17, 0, 0, 0, 0, 0};
6437 static const ULONG wmaenc_block_size = 1487;
6438 static const ULONG wmadec_block_size = 0x2000;
6440 static void test_wma_encoder(void)
6442 const GUID transform_inputs[] =
6444 MFAudioFormat_PCM,
6445 MFAudioFormat_Float,
6447 const GUID transform_outputs[] =
6449 MFAudioFormat_WMAudioV8,
6450 MFAudioFormat_WMAudioV9,
6451 MFAudioFormat_WMAudio_Lossless,
6453 const GUID dmo_inputs[] =
6455 MEDIASUBTYPE_PCM,
6457 const GUID dmo_outputs[] =
6459 MEDIASUBTYPE_WMAUDIO2,
6460 MEDIASUBTYPE_WMAUDIO3,
6461 MEDIASUBTYPE_WMAUDIO_LOSSLESS,
6464 static const struct attribute_desc input_type_desc[] =
6466 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
6467 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_Float),
6468 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 32),
6469 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
6470 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
6471 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 176400),
6472 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 8),
6473 {0},
6475 const struct attribute_desc output_type_desc[] =
6477 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
6478 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_WMAudioV8),
6479 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
6480 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
6481 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 4003),
6482 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, wmaenc_block_size),
6483 ATTR_BLOB(MF_MT_USER_DATA, wma_codec_data, sizeof(wma_codec_data)),
6484 {0},
6487 MFT_REGISTER_TYPE_INFO output_type = {MFMediaType_Audio, MFAudioFormat_WMAudioV8};
6488 MFT_REGISTER_TYPE_INFO input_type = {MFMediaType_Audio, MFAudioFormat_Float};
6489 ULONG audio_data_len, wmaenc_data_len;
6490 const BYTE *audio_data, *wmaenc_data;
6491 MFT_OUTPUT_STREAM_INFO output_info;
6492 MFT_INPUT_STREAM_INFO input_info;
6493 MFT_OUTPUT_DATA_BUFFER output;
6494 WCHAR output_path[MAX_PATH];
6495 IMFMediaType *media_type;
6496 IMFTransform *transform;
6497 DWORD status, length;
6498 HANDLE output_file;
6499 IMFSample *sample;
6500 HRSRC resource;
6501 GUID class_id;
6502 ULONG i, ret;
6503 HRESULT hr;
6504 LONG ref;
6506 hr = CoInitialize(NULL);
6507 ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
6509 if (!create_transform(MFT_CATEGORY_AUDIO_ENCODER, &input_type, &output_type, L"WMAudio Encoder MFT", &MFMediaType_Audio,
6510 transform_inputs, ARRAY_SIZE(transform_inputs), transform_outputs, ARRAY_SIZE(transform_outputs),
6511 &transform, &CLSID_CWMAEncMediaObject, &class_id))
6512 goto failed;
6514 check_dmo(&class_id, L"WMAudio Encoder DMO", &MEDIATYPE_Audio, dmo_inputs, ARRAY_SIZE(dmo_inputs),
6515 dmo_outputs, ARRAY_SIZE(dmo_outputs));
6517 check_interface(transform, &IID_IMFTransform, TRUE);
6518 check_interface(transform, &IID_IMediaObject, TRUE);
6519 check_interface(transform, &IID_IPropertyStore, TRUE);
6520 check_interface(transform, &IID_IPropertyBag, TRUE);
6522 hr = MFCreateMediaType(&media_type);
6523 ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr);
6524 init_media_type(media_type, input_type_desc, -1);
6525 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
6526 ok(hr == S_OK, "SetInputType returned %#lx.\n", hr);
6527 init_media_type(media_type, output_type_desc, -1);
6528 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
6529 ok(hr == S_OK, "SetOutputType returned %#lx.\n", hr);
6530 ret = IMFMediaType_Release(media_type);
6531 ok(ret == 0, "Release returned %lu\n", ret);
6533 memset(&input_info, 0xcd, sizeof(input_info));
6534 hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info);
6535 ok(hr == S_OK, "GetInputStreamInfo returned %#lx\n", hr);
6536 ok(input_info.hnsMaxLatency == 19969161, "got hnsMaxLatency %s\n",
6537 wine_dbgstr_longlong(input_info.hnsMaxLatency));
6538 ok(input_info.dwFlags == 0, "got dwFlags %#lx\n", input_info.dwFlags);
6539 ok(input_info.cbSize == 8, "got cbSize %lu\n", input_info.cbSize);
6540 ok(input_info.cbMaxLookahead == 0, "got cbMaxLookahead %#lx\n", input_info.cbMaxLookahead);
6541 ok(input_info.cbAlignment == 1, "got cbAlignment %#lx\n", input_info.cbAlignment);
6543 memset(&output_info, 0xcd, sizeof(output_info));
6544 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
6545 ok(hr == S_OK, "GetOutputStreamInfo returned %#lx\n", hr);
6546 ok(output_info.dwFlags == 0, "got dwFlags %#lx\n", output_info.dwFlags);
6547 ok(output_info.cbSize == wmaenc_block_size, "got cbSize %#lx\n", output_info.cbSize);
6548 ok(output_info.cbAlignment == 1, "got cbAlignment %#lx\n", output_info.cbAlignment);
6550 resource = FindResourceW(NULL, L"audiodata.bin", (const WCHAR *)RT_RCDATA);
6551 ok(resource != 0, "FindResourceW failed, error %lu\n", GetLastError());
6552 audio_data = LockResource(LoadResource(GetModuleHandleW(NULL), resource));
6553 audio_data_len = SizeofResource(GetModuleHandleW(NULL), resource);
6554 ok(audio_data_len == 179928, "got length %lu\n", audio_data_len);
6556 sample = create_sample(audio_data, audio_data_len);
6557 hr = IMFSample_SetSampleTime(sample, 0);
6558 ok(hr == S_OK, "SetSampleTime returned %#lx\n", hr);
6559 hr = IMFSample_SetSampleDuration(sample, 10000000);
6560 ok(hr == S_OK, "SetSampleDuration returned %#lx\n", hr);
6561 hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
6562 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
6563 hr = IMFTransform_ProcessMessage(transform, MFT_MESSAGE_COMMAND_DRAIN, 0);
6564 ok(hr == S_OK, "ProcessMessage returned %#lx\n", hr);
6565 hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
6566 ok(hr == MF_E_NOTACCEPTING, "ProcessInput returned %#lx\n", hr);
6567 ref = IMFSample_Release(sample);
6568 ok(ref <= 1, "Release returned %ld\n", ref);
6570 status = 0xdeadbeef;
6571 sample = create_sample(NULL, output_info.cbSize);
6572 memset(&output, 0, sizeof(output));
6573 output.pSample = sample;
6575 resource = FindResourceW(NULL, L"wmaencdata.bin", (const WCHAR *)RT_RCDATA);
6576 ok(resource != 0, "FindResourceW failed, error %lu\n", GetLastError());
6577 wmaenc_data = LockResource(LoadResource(GetModuleHandleW(NULL), resource));
6578 wmaenc_data_len = SizeofResource(GetModuleHandleW(NULL), resource);
6579 ok(wmaenc_data_len % wmaenc_block_size == 0, "got length %lu\n", wmaenc_data_len);
6581 /* and generate a new one as well in a temporary directory */
6582 GetTempPathW(ARRAY_SIZE(output_path), output_path);
6583 lstrcatW(output_path, L"wmaencdata.bin");
6584 output_file = CreateFileW(output_path, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
6585 ok(output_file != INVALID_HANDLE_VALUE, "CreateFileW failed, error %lu\n", GetLastError());
6587 i = 0;
6588 while (SUCCEEDED(hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status)))
6590 winetest_push_context("%lu", i);
6591 ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr);
6592 ok(output.pSample == sample, "got pSample %p\n", output.pSample);
6593 ok(output.dwStatus == MFT_OUTPUT_DATA_BUFFER_INCOMPLETE ||
6594 broken(output.dwStatus == (MFT_OUTPUT_DATA_BUFFER_INCOMPLETE|7)) /* win7 */,
6595 "got dwStatus %#lx\n", output.dwStatus);
6596 ok(status == 0, "got status %#lx\n", status);
6597 hr = IMFSample_GetTotalLength(sample, &length);
6598 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
6599 ok(length == wmaenc_block_size, "got length %lu\n", length);
6600 ok(wmaenc_data_len > i * wmaenc_block_size, "got %lu blocks\n", i);
6601 check_sample(sample, wmaenc_data + i * wmaenc_block_size, output_file);
6602 winetest_pop_context();
6603 i++;
6606 trace("created %s\n", debugstr_w(output_path));
6607 CloseHandle(output_file);
6609 ret = IMFSample_Release(sample);
6610 ok(ret == 0, "Release returned %lu\n", ret);
6612 status = 0xdeadbeef;
6613 sample = create_sample(NULL, output_info.cbSize);
6614 memset(&output, 0, sizeof(output));
6615 output.pSample = sample;
6616 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
6617 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
6618 ok(output.pSample == sample, "got pSample %p\n", output.pSample);
6619 ok(output.dwStatus == 0, "got dwStatus %#lx\n", output.dwStatus);
6620 ok(status == 0, "got status %#lx\n", status);
6621 hr = IMFSample_GetTotalLength(sample, &length);
6622 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
6623 ok(length == 0, "got length %lu\n", length);
6624 ret = IMFSample_Release(sample);
6625 ok(ret == 0, "Release returned %lu\n", ret);
6627 ret = IMFTransform_Release(transform);
6628 ok(ret == 0, "Release returned %lu\n", ret);
6630 failed:
6631 CoUninitialize();
6634 static void test_wma_decoder(void)
6636 const GUID transform_inputs[] =
6638 MEDIASUBTYPE_MSAUDIO1,
6639 MFAudioFormat_WMAudioV8,
6640 MFAudioFormat_WMAudioV9,
6641 MFAudioFormat_WMAudio_Lossless,
6643 const GUID transform_outputs[] =
6645 MFAudioFormat_PCM,
6646 MFAudioFormat_Float,
6648 const GUID dmo_inputs[] =
6650 MEDIASUBTYPE_MSAUDIO1,
6651 MEDIASUBTYPE_WMAUDIO2,
6652 MEDIASUBTYPE_WMAUDIO3,
6653 MEDIASUBTYPE_WMAUDIO_LOSSLESS,
6655 const GUID dmo_outputs[] =
6657 MEDIASUBTYPE_PCM,
6658 MEDIASUBTYPE_IEEE_FLOAT,
6661 static const media_type_desc expect_available_inputs[] =
6664 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
6665 ATTR_GUID(MF_MT_SUBTYPE, MEDIASUBTYPE_MSAUDIO1),
6666 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
6669 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
6670 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_WMAudioV8),
6671 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
6674 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
6675 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_WMAudioV9),
6676 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
6679 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
6680 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_WMAudio_Lossless),
6681 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
6684 static const media_type_desc expect_available_outputs[] =
6687 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
6688 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_Float),
6689 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 32),
6690 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
6691 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
6692 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 176400),
6693 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 8),
6694 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
6695 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
6696 ATTR_UINT32(MF_MT_AUDIO_PREFER_WAVEFORMATEX, 1),
6699 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
6700 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
6701 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16),
6702 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
6703 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
6704 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 88200),
6705 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 4),
6706 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
6707 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
6708 ATTR_UINT32(MF_MT_AUDIO_PREFER_WAVEFORMATEX, 1),
6712 const struct attribute_desc input_type_desc[] =
6714 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
6715 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_WMAudioV8),
6716 ATTR_BLOB(MF_MT_USER_DATA, wma_codec_data, sizeof(wma_codec_data)),
6717 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, wmaenc_block_size),
6718 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
6719 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
6720 {0},
6722 static const struct attribute_desc output_type_desc[] =
6724 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
6725 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
6726 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 88200),
6727 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16),
6728 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
6729 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
6730 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 4),
6731 {0},
6734 MFT_REGISTER_TYPE_INFO input_type = {MFMediaType_Audio, MFAudioFormat_WMAudioV8};
6735 MFT_REGISTER_TYPE_INFO output_type = {MFMediaType_Audio, MFAudioFormat_Float};
6736 IUnknown *unknown, *tmp_unknown, outer = {&test_unk_vtbl};
6737 ULONG wmadec_data_len, wmaenc_data_len;
6738 const BYTE *wmadec_data, *wmaenc_data;
6739 MFT_OUTPUT_STREAM_INFO output_info;
6740 MFT_OUTPUT_DATA_BUFFER outputs[2];
6741 MFT_INPUT_STREAM_INFO input_info;
6742 MFT_OUTPUT_DATA_BUFFER output;
6743 DWORD status, flags, length;
6744 WCHAR output_path[MAX_PATH];
6745 IMediaObject *media_object;
6746 IPropertyBag *property_bag;
6747 IMFMediaType *media_type;
6748 IMFTransform *transform;
6749 LONGLONG time, duration;
6750 HANDLE output_file;
6751 IMFSample *sample;
6752 ULONG i, ret, ref;
6753 HRSRC resource;
6754 GUID class_id;
6755 UINT32 value;
6756 HRESULT hr;
6758 hr = CoInitialize(NULL);
6759 ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
6761 if (!create_transform(MFT_CATEGORY_AUDIO_DECODER, &input_type, &output_type, L"WMAudio Decoder MFT", &MFMediaType_Audio,
6762 transform_inputs, ARRAY_SIZE(transform_inputs), transform_outputs, ARRAY_SIZE(transform_outputs),
6763 &transform, &CLSID_CWMADecMediaObject, &class_id))
6764 goto failed;
6766 check_dmo(&class_id, L"WMAudio Decoder DMO", &MEDIATYPE_Audio, dmo_inputs, ARRAY_SIZE(dmo_inputs),
6767 dmo_outputs, ARRAY_SIZE(dmo_outputs));
6769 check_interface(transform, &IID_IMFTransform, TRUE);
6770 check_interface(transform, &IID_IMediaObject, TRUE);
6771 todo_wine
6772 check_interface(transform, &IID_IPropertyStore, TRUE);
6773 check_interface(transform, &IID_IPropertyBag, TRUE);
6775 /* check default media types */
6777 hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info);
6778 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetInputStreamInfo returned %#lx\n", hr);
6779 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
6780 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetOutputStreamInfo returned %#lx\n", hr);
6781 hr = IMFTransform_GetOutputAvailableType(transform, 0, 0, &media_type);
6782 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetOutputAvailableType returned %#lx\n", hr);
6784 i = -1;
6785 while (SUCCEEDED(hr = IMFTransform_GetInputAvailableType(transform, 0, ++i, &media_type)))
6787 winetest_push_context("in %lu", i);
6788 ok(hr == S_OK, "GetInputAvailableType returned %#lx\n", hr);
6789 check_media_type(media_type, expect_available_inputs[i], -1);
6790 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
6791 ok(hr == MF_E_INVALIDMEDIATYPE, "SetInputType returned %#lx.\n", hr);
6792 ret = IMFMediaType_Release(media_type);
6793 ok(ret == 0, "Release returned %lu\n", ret);
6794 winetest_pop_context();
6796 todo_wine
6797 ok(hr == MF_E_NO_MORE_TYPES, "GetInputAvailableType returned %#lx\n", hr);
6798 todo_wine
6799 ok(i == 4, "%lu input media types\n", i);
6801 /* setting output media type first doesn't work */
6803 hr = MFCreateMediaType(&media_type);
6804 ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr);
6805 init_media_type(media_type, output_type_desc, -1);
6806 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
6807 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "SetOutputType returned %#lx.\n", hr);
6808 ret = IMFMediaType_Release(media_type);
6809 ok(ret == 0, "Release returned %lu\n", ret);
6811 /* check required input media type attributes */
6813 hr = MFCreateMediaType(&media_type);
6814 ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr);
6815 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
6816 ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetInputType returned %#lx.\n", hr);
6817 init_media_type(media_type, input_type_desc, 1);
6818 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
6819 ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetInputType returned %#lx.\n", hr);
6820 init_media_type(media_type, input_type_desc, 2);
6821 for (i = 2; i < ARRAY_SIZE(input_type_desc) - 1; ++i)
6823 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
6824 ok(hr == MF_E_INVALIDMEDIATYPE, "SetInputType returned %#lx.\n", hr);
6825 init_media_type(media_type, input_type_desc, i + 1);
6827 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
6828 ok(hr == S_OK, "SetInputType returned %#lx.\n", hr);
6829 ret = IMFMediaType_Release(media_type);
6830 ok(ret == 0, "Release returned %lu\n", ret);
6832 hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info);
6833 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetInputStreamInfo returned %#lx\n", hr);
6834 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
6835 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetOutputStreamInfo returned %#lx\n", hr);
6837 /* check new output media types */
6839 i = -1;
6840 while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, ++i, &media_type)))
6842 winetest_push_context("out %lu", i);
6843 ok(hr == S_OK, "GetOutputAvailableType returned %#lx\n", hr);
6844 check_media_type(media_type, expect_available_outputs[i], -1);
6845 ret = IMFMediaType_Release(media_type);
6846 ok(ret == 0, "Release returned %lu\n", ret);
6847 winetest_pop_context();
6849 ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
6850 ok(i == 2, "%lu output media types\n", i);
6852 /* check required output media type attributes */
6854 hr = MFCreateMediaType(&media_type);
6855 ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr);
6856 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
6857 ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetOutputType returned %#lx.\n", hr);
6858 init_media_type(media_type, output_type_desc, 1);
6859 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
6860 ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetOutputType returned %#lx.\n", hr);
6861 init_media_type(media_type, output_type_desc, 2);
6862 for (i = 2; i < ARRAY_SIZE(output_type_desc) - 1; ++i)
6864 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
6865 ok(hr == MF_E_INVALIDMEDIATYPE, "SetOutputType returned %#lx.\n", hr);
6866 init_media_type(media_type, output_type_desc, i + 1);
6868 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
6869 ok(hr == S_OK, "SetOutputType returned %#lx.\n", hr);
6870 ret = IMFMediaType_Release(media_type);
6871 ok(ret == 0, "Release returned %lu\n", ret);
6873 memset(&input_info, 0xcd, sizeof(input_info));
6874 hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info);
6875 ok(hr == S_OK, "GetInputStreamInfo returned %#lx\n", hr);
6876 ok(input_info.hnsMaxLatency == 0, "got hnsMaxLatency %s\n", wine_dbgstr_longlong(input_info.hnsMaxLatency));
6877 ok(input_info.dwFlags == 0, "got dwFlags %#lx\n", input_info.dwFlags);
6878 ok(input_info.cbSize == wmaenc_block_size, "got cbSize %lu\n", input_info.cbSize);
6879 ok(input_info.cbMaxLookahead == 0, "got cbMaxLookahead %#lx\n", input_info.cbMaxLookahead);
6880 ok(input_info.cbAlignment == 1, "got cbAlignment %#lx\n", input_info.cbAlignment);
6882 memset(&output_info, 0xcd, sizeof(output_info));
6883 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
6884 ok(hr == S_OK, "GetOutputStreamInfo returned %#lx\n", hr);
6885 ok(output_info.dwFlags == 0, "got dwFlags %#lx\n", output_info.dwFlags);
6886 todo_wine
6887 ok(output_info.cbSize == 0, "got cbSize %#lx\n", output_info.cbSize);
6888 ok(output_info.cbAlignment == 1, "got cbAlignment %#lx\n", output_info.cbAlignment);
6890 /* MF_MT_AUDIO_AVG_BYTES_PER_SECOND isn't required by SetInputType, but is needed for the transform to work */
6892 hr = MFCreateMediaType(&media_type);
6893 ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr);
6894 init_media_type(media_type, input_type_desc, -1);
6895 hr = IMFMediaType_SetUINT32(media_type, &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 4003);
6896 ok(hr == S_OK, "SetUINT32 returned %#lx\n", hr);
6897 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
6898 ok(hr == S_OK, "SetInputType returned %#lx.\n", hr);
6900 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
6901 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetOutputStreamInfo returned %#lx\n", hr);
6903 init_media_type(media_type, output_type_desc, -1);
6904 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
6905 ok(hr == S_OK, "SetInputType returned %#lx.\n", hr);
6906 ret = IMFMediaType_Release(media_type);
6907 ok(ret == 0, "Release returned %lu\n", ret);
6909 memset(&output_info, 0xcd, sizeof(output_info));
6910 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
6911 ok(hr == S_OK, "GetOutputStreamInfo returned %#lx\n", hr);
6912 ok(output_info.dwFlags == 0, "got dwFlags %#lx\n", output_info.dwFlags);
6913 ok(output_info.cbSize == wmadec_block_size, "got cbSize %#lx\n", output_info.cbSize);
6914 ok(output_info.cbAlignment == 1, "got cbAlignment %#lx\n", output_info.cbAlignment);
6916 resource = FindResourceW(NULL, L"wmaencdata.bin", (const WCHAR *)RT_RCDATA);
6917 ok(resource != 0, "FindResourceW failed, error %lu\n", GetLastError());
6918 wmaenc_data = LockResource(LoadResource(GetModuleHandleW(NULL), resource));
6919 wmaenc_data_len = SizeofResource(GetModuleHandleW(NULL), resource);
6920 ok(wmaenc_data_len % wmaenc_block_size == 0, "got length %lu\n", wmaenc_data_len);
6922 sample = create_sample(wmaenc_data, wmaenc_block_size / 2);
6923 hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
6924 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
6925 ret = IMFSample_Release(sample);
6926 ok(ret == 0, "Release returned %lu\n", ret);
6927 sample = create_sample(wmaenc_data, wmaenc_block_size + 1);
6928 hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
6929 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
6930 ret = IMFSample_Release(sample);
6931 ok(ret == 0, "Release returned %lu\n", ret);
6932 sample = create_sample(wmaenc_data, wmaenc_block_size);
6933 hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
6934 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
6935 hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
6936 ok(hr == MF_E_NOTACCEPTING, "ProcessInput returned %#lx\n", hr);
6937 ret = IMFSample_Release(sample);
6938 ok(ret == 1, "Release returned %lu\n", ret);
6940 /* As output_info.dwFlags doesn't have MFT_OUTPUT_STREAM_CAN_PROVIDE_SAMPLES
6941 * IMFTransform_ProcessOutput needs a sample or returns MF_E_TRANSFORM_NEED_MORE_INPUT */
6943 status = 0xdeadbeef;
6944 memset(&output, 0, sizeof(output));
6945 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
6946 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
6947 ok(output.dwStreamID == 0, "got dwStreamID %lu\n", output.dwStreamID);
6948 ok(!output.pSample, "got pSample %p\n", output.pSample);
6949 ok(output.dwStatus == MFT_OUTPUT_DATA_BUFFER_NO_SAMPLE ||
6950 broken(output.dwStatus == (MFT_OUTPUT_DATA_BUFFER_INCOMPLETE|MFT_OUTPUT_DATA_BUFFER_NO_SAMPLE)) /* Win7 */,
6951 "got dwStatus %#lx\n", output.dwStatus);
6952 ok(!output.pEvents, "got pEvents %p\n", output.pEvents);
6953 ok(status == 0, "got status %#lx\n", status);
6955 sample = create_sample(wmaenc_data, wmaenc_block_size);
6956 hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
6957 ok(hr == MF_E_NOTACCEPTING, "ProcessInput returned %#lx\n", hr);
6958 ret = IMFSample_Release(sample);
6959 ok(ret == 0, "Release returned %lu\n", ret);
6961 status = 0xdeadbeef;
6962 memset(&output, 0, sizeof(output));
6963 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
6964 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
6965 ok(!output.pSample, "got pSample %p\n", output.pSample);
6966 ok(output.dwStatus == MFT_OUTPUT_DATA_BUFFER_NO_SAMPLE ||
6967 broken(output.dwStatus == (MFT_OUTPUT_DATA_BUFFER_INCOMPLETE|MFT_OUTPUT_DATA_BUFFER_NO_SAMPLE)) /* Win7 */,
6968 "got dwStatus %#lx\n", output.dwStatus);
6969 ok(status == 0, "got status %#lx\n", status);
6971 status = 0xdeadbeef;
6972 memset(&output, 0, sizeof(output));
6973 output_info.cbSize = wmadec_block_size;
6974 sample = create_sample(NULL, output_info.cbSize);
6975 outputs[0].pSample = sample;
6976 sample = create_sample(NULL, output_info.cbSize);
6977 outputs[1].pSample = sample;
6978 hr = IMFTransform_ProcessOutput(transform, 0, 2, outputs, &status);
6979 ok(hr == E_INVALIDARG, "ProcessOutput returned %#lx\n", hr);
6980 ref = IMFSample_Release(outputs[0].pSample);
6981 ok(ref == 0, "Release returned %ld\n", ref);
6982 ref = IMFSample_Release(outputs[1].pSample);
6983 ok(ref == 0, "Release returned %ld\n", ref);
6985 resource = FindResourceW(NULL, L"wmadecdata.bin", (const WCHAR *)RT_RCDATA);
6986 ok(resource != 0, "FindResourceW failed, error %lu\n", GetLastError());
6987 wmadec_data = LockResource(LoadResource(GetModuleHandleW(NULL), resource));
6988 wmadec_data_len = SizeofResource(GetModuleHandleW(NULL), resource);
6989 ok(wmadec_data_len == wmadec_block_size * 7 / 2, "got length %lu\n", wmadec_data_len);
6991 /* and generate a new one as well in a temporary directory */
6992 GetTempPathW(ARRAY_SIZE(output_path), output_path);
6993 lstrcatW(output_path, L"wmadecdata.bin");
6994 output_file = CreateFileW(output_path, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
6995 ok(output_file != INVALID_HANDLE_VALUE, "CreateFileW failed, error %lu\n", GetLastError());
6997 status = 0xdeadbeef;
6998 output_info.cbSize = wmadec_block_size;
6999 sample = create_sample(NULL, output_info.cbSize);
7000 memset(&output, 0, sizeof(output));
7001 output.pSample = sample;
7002 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
7004 for (i = 0; i < 4; ++i)
7006 winetest_push_context("%lu", i);
7008 ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr);
7009 ok(output.pSample == sample, "got pSample %p\n", output.pSample);
7010 ok(output.dwStatus == MFT_OUTPUT_DATA_BUFFER_INCOMPLETE || output.dwStatus == 0 ||
7011 broken(output.dwStatus == (MFT_OUTPUT_DATA_BUFFER_INCOMPLETE|7) || output.dwStatus == 7) /* Win7 */,
7012 "got dwStatus %#lx\n", output.dwStatus);
7013 ok(status == 0, "got status %#lx\n", status);
7014 value = 0xdeadbeef;
7015 hr = IMFSample_GetUINT32(sample, &MFSampleExtension_CleanPoint, &value);
7016 ok(hr == S_OK, "GetUINT32 MFSampleExtension_CleanPoint returned %#lx\n", hr);
7017 ok(value == 1, "got MFSampleExtension_CleanPoint %u\n", value);
7018 hr = IMFSample_GetTotalLength(sample, &length);
7019 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
7020 flags = 0xdeadbeef;
7021 hr = IMFSample_GetSampleFlags(sample, &flags);
7022 ok(hr == S_OK, "GetSampleFlags returned %#lx\n", hr);
7023 ok(flags == 0, "got flags %#lx\n", flags);
7024 time = 0xdeadbeef;
7025 hr = IMFSample_GetSampleTime(sample, &time);
7026 ok(hr == S_OK, "GetSampleTime returned %#lx\n", hr);
7027 ok(time == i * 928798, "got time %I64d\n", time);
7028 duration = 0xdeadbeef;
7029 hr = IMFSample_GetSampleDuration(sample, &duration);
7030 ok(hr == S_OK, "GetSampleDuration returned %#lx\n", hr);
7031 if (output.dwStatus == MFT_OUTPUT_DATA_BUFFER_INCOMPLETE ||
7032 broken(output.dwStatus == (MFT_OUTPUT_DATA_BUFFER_INCOMPLETE|7)))
7034 ok(length == wmadec_block_size, "got length %lu\n", length);
7035 ok(duration == 928798, "got duration %I64d\n", duration);
7036 check_sample_pcm16(sample, wmadec_data, output_file, TRUE);
7037 wmadec_data += wmadec_block_size;
7038 wmadec_data_len -= wmadec_block_size;
7040 else
7042 /* FFmpeg doesn't seem to decode WMA buffers in the same way as native */
7043 todo_wine
7044 ok(length == wmadec_block_size / 2, "got length %lu\n", length);
7045 todo_wine
7046 ok(duration == 464399, "got duration %I64d\n", duration);
7048 if (length == wmadec_block_size / 2)
7049 check_sample_pcm16(sample, wmadec_data, output_file, FALSE);
7050 wmadec_data += length;
7051 wmadec_data_len -= length;
7053 ret = IMFSample_Release(sample);
7054 ok(ret == 0, "Release returned %lu\n", ret);
7056 status = 0xdeadbeef;
7057 sample = create_sample(NULL, output_info.cbSize);
7058 memset(&output, 0, sizeof(output));
7059 output.pSample = sample;
7060 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
7062 winetest_pop_context();
7064 /* some FFmpeg version request more input to complete decoding */
7065 if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT && i == 2) break;
7067 todo_wine
7068 ok(wmadec_data_len == 0, "missing %#lx bytes\n", wmadec_data_len);
7070 trace("created %s\n", debugstr_w(output_path));
7071 CloseHandle(output_file);
7073 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
7074 ok(output.pSample == sample, "got pSample %p\n", output.pSample);
7075 ok(output.dwStatus == 0, "got dwStatus %#lx\n", output.dwStatus);
7076 ok(status == 0, "got status %#lx\n", status);
7077 ret = IMFSample_Release(sample);
7078 ok(ret == 0, "Release returned %lu\n", ret);
7080 status = 0xdeadbeef;
7081 sample = create_sample(NULL, output_info.cbSize);
7082 memset(&output, 0, sizeof(output));
7083 output.pSample = sample;
7084 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
7085 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
7086 ok(output.pSample == sample, "got pSample %p\n", output.pSample);
7087 ok(output.dwStatus == 0 ||
7088 broken(output.dwStatus == (MFT_OUTPUT_DATA_BUFFER_INCOMPLETE|7)) /* Win7 */,
7089 "got dwStatus %#lx\n", output.dwStatus);
7090 ok(status == 0, "got status %#lx\n", status);
7091 hr = IMFSample_GetTotalLength(sample, &length);
7092 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
7093 ok(length == 0, "got length %lu\n", length);
7094 ret = IMFSample_Release(sample);
7095 ok(ret == 0, "Release returned %lu\n", ret);
7097 sample = create_sample(wmaenc_data, wmaenc_block_size);
7098 hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
7099 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
7101 ret = IMFTransform_Release(transform);
7102 ok(ret == 0, "Release returned %lu\n", ret);
7103 ret = IMFSample_Release(sample);
7104 ok(ret == 0, "Release returned %lu\n", ret);
7106 hr = CoCreateInstance( &CLSID_CWMADecMediaObject, &outer, CLSCTX_INPROC_SERVER, &IID_IUnknown,
7107 (void **)&unknown );
7108 ok( hr == S_OK, "CoCreateInstance returned %#lx\n", hr );
7109 hr = IUnknown_QueryInterface( unknown, &IID_IMFTransform, (void **)&transform );
7110 ok( hr == S_OK, "QueryInterface returned %#lx\n", hr );
7111 hr = IUnknown_QueryInterface( unknown, &IID_IMediaObject, (void **)&media_object );
7112 ok( hr == S_OK, "QueryInterface returned %#lx\n", hr );
7113 hr = IUnknown_QueryInterface( unknown, &IID_IPropertyBag, (void **)&property_bag );
7114 ok( hr == S_OK, "QueryInterface returned %#lx\n", hr );
7115 hr = IUnknown_QueryInterface( media_object, &IID_IUnknown, (void **)&tmp_unknown );
7116 ok( hr == S_OK, "QueryInterface returned %#lx\n", hr );
7118 ok( unknown != &outer, "got outer IUnknown\n" );
7119 ok( transform != (void *)unknown, "got IUnknown == IMFTransform\n" );
7120 ok( media_object != (void *)unknown, "got IUnknown == IMediaObject\n" );
7121 ok( property_bag != (void *)unknown, "got IUnknown == IPropertyBag\n" );
7122 ok( tmp_unknown != unknown, "got inner IUnknown\n" );
7124 check_interface( unknown, &IID_IPersistPropertyBag, FALSE );
7125 check_interface( unknown, &IID_IAMFilterMiscFlags, FALSE );
7126 check_interface( unknown, &IID_IMediaSeeking, FALSE );
7127 check_interface( unknown, &IID_IMediaPosition, FALSE );
7128 check_interface( unknown, &IID_IReferenceClock, FALSE );
7129 check_interface( unknown, &IID_IBasicAudio, FALSE );
7131 ref = IUnknown_Release( tmp_unknown );
7132 ok( ref == 1, "Release returned %lu\n", ref );
7133 ref = IPropertyBag_Release( property_bag );
7134 ok( ref == 1, "Release returned %lu\n", ref );
7135 ref = IMediaObject_Release( media_object );
7136 ok( ref == 1, "Release returned %lu\n", ref );
7137 ref = IMFTransform_Release( transform );
7138 ok( ref == 1, "Release returned %lu\n", ref );
7139 ref = IUnknown_Release( unknown );
7140 ok( ref == 0, "Release returned %lu\n", ref );
7142 failed:
7143 CoUninitialize();
7146 #define next_h264_sample(a, b) next_h264_sample_(__LINE__, a, b)
7147 static IMFSample *next_h264_sample_(int line, const BYTE **h264_buf, ULONG *h264_len)
7149 const BYTE *sample_data;
7151 ok_(__FILE__, line)(*h264_len > 4, "invalid h264 length\n");
7152 ok_(__FILE__, line)(*(UINT32 *)*h264_buf == 0x01000000, "invalid h264 buffer\n");
7153 sample_data = *h264_buf;
7155 (*h264_len) -= 4;
7156 (*h264_buf) += 4;
7158 while (*h264_len >= 4 && *(UINT32 *)*h264_buf != 0x01000000)
7160 (*h264_len)--;
7161 (*h264_buf)++;
7164 return create_sample(sample_data, *h264_buf - sample_data);
7167 static void test_h264_decoder(void)
7169 const GUID transform_inputs[] =
7171 MFVideoFormat_H264,
7172 MFVideoFormat_H264_ES,
7174 const GUID transform_outputs[] =
7176 MFVideoFormat_NV12,
7177 MFVideoFormat_YV12,
7178 MFVideoFormat_IYUV,
7179 MFVideoFormat_I420,
7180 MFVideoFormat_YUY2,
7182 static const media_type_desc default_inputs[] =
7185 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
7186 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_H264),
7189 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
7190 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_H264_ES),
7193 static const DWORD input_width = 120, input_height = 248;
7194 const media_type_desc default_outputs[] =
7197 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
7198 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12),
7199 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
7200 ATTR_RATIO(MF_MT_FRAME_RATE, 30000, 1001),
7201 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, input_width),
7202 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
7203 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
7204 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
7205 ATTR_RATIO(MF_MT_FRAME_SIZE, input_width, input_height),
7206 ATTR_UINT32(MF_MT_SAMPLE_SIZE, input_width * input_height * 3 / 2),
7207 /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
7210 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
7211 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YV12),
7212 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
7213 ATTR_RATIO(MF_MT_FRAME_RATE, 30000, 1001),
7214 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, input_width),
7215 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
7216 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
7217 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
7218 ATTR_RATIO(MF_MT_FRAME_SIZE, input_width, input_height),
7219 ATTR_UINT32(MF_MT_SAMPLE_SIZE, input_width * input_height * 3 / 2),
7220 /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
7223 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
7224 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_IYUV),
7225 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
7226 ATTR_RATIO(MF_MT_FRAME_RATE, 30000, 1001),
7227 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, input_width),
7228 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
7229 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
7230 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
7231 ATTR_RATIO(MF_MT_FRAME_SIZE, input_width, input_height),
7232 ATTR_UINT32(MF_MT_SAMPLE_SIZE, input_width * input_height * 3 / 2),
7233 /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
7236 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
7237 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_I420),
7238 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
7239 ATTR_RATIO(MF_MT_FRAME_RATE, 30000, 1001),
7240 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, input_width),
7241 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
7242 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
7243 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
7244 ATTR_RATIO(MF_MT_FRAME_SIZE, input_width, input_height),
7245 ATTR_UINT32(MF_MT_SAMPLE_SIZE, input_width * input_height * 3 / 2),
7246 /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
7249 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
7250 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YUY2),
7251 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
7252 ATTR_RATIO(MF_MT_FRAME_RATE, 30000, 1001),
7253 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, input_width * 2),
7254 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
7255 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
7256 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
7257 ATTR_RATIO(MF_MT_FRAME_SIZE, input_width, input_height),
7258 ATTR_UINT32(MF_MT_SAMPLE_SIZE, input_width * input_height * 2),
7259 /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
7262 const struct attribute_desc input_type_desc[] =
7264 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
7265 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_H264),
7266 ATTR_RATIO(MF_MT_FRAME_SIZE, input_width, input_height),
7267 {0},
7269 const struct attribute_desc minimal_output_type_desc[] =
7271 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
7272 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12),
7273 ATTR_RATIO(MF_MT_FRAME_SIZE, input_width, input_height),
7274 {0},
7276 const struct attribute_desc output_type_desc[] =
7278 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
7279 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12),
7280 ATTR_RATIO(MF_MT_FRAME_SIZE, input_width, input_height),
7281 ATTR_RATIO(MF_MT_FRAME_RATE, 60000, 1000),
7282 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 2, 1),
7283 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, 3840),
7284 ATTR_UINT32(MF_MT_SAMPLE_SIZE, 3840 * input_height * 3 / 2),
7285 ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0),
7286 {0},
7288 static const struct attribute_desc new_output_type_desc[] =
7290 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
7291 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_I420),
7292 ATTR_RATIO(MF_MT_FRAME_SIZE, 96, 96),
7293 ATTR_RATIO(MF_MT_FRAME_RATE, 1, 1),
7294 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 2),
7295 {0},
7297 static const MFVideoArea actual_aperture = {.Area={82,84}};
7298 static const DWORD actual_width = 96, actual_height = 96;
7299 const media_type_desc actual_outputs[] =
7302 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
7303 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12),
7304 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
7305 ATTR_RATIO(MF_MT_FRAME_RATE, 60000, 1000),
7306 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
7307 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 3 / 2),
7308 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width),
7309 /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
7310 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
7311 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
7312 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
7313 ATTR_BLOB(MF_MT_MINIMUM_DISPLAY_APERTURE, &actual_aperture, 16),
7316 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
7317 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YV12),
7318 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
7319 ATTR_RATIO(MF_MT_FRAME_RATE, 60000, 1000),
7320 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
7321 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 3 / 2),
7322 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width),
7323 /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
7324 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
7325 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
7326 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
7327 ATTR_BLOB(MF_MT_MINIMUM_DISPLAY_APERTURE, &actual_aperture, 16),
7330 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
7331 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_IYUV),
7332 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
7333 ATTR_RATIO(MF_MT_FRAME_RATE, 60000, 1000),
7334 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
7335 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 3 / 2),
7336 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width),
7337 /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
7338 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
7339 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
7340 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
7341 ATTR_BLOB(MF_MT_MINIMUM_DISPLAY_APERTURE, &actual_aperture, 16),
7344 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
7345 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_I420),
7346 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
7347 ATTR_RATIO(MF_MT_FRAME_RATE, 60000, 1000),
7348 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
7349 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 3 / 2),
7350 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width),
7351 /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
7352 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
7353 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
7354 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
7355 ATTR_BLOB(MF_MT_MINIMUM_DISPLAY_APERTURE, &actual_aperture, 16),
7358 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
7359 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YUY2),
7360 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
7361 ATTR_RATIO(MF_MT_FRAME_RATE, 60000, 1000),
7362 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
7363 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 2),
7364 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width * 2),
7365 /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
7366 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
7367 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
7368 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
7369 ATTR_BLOB(MF_MT_MINIMUM_DISPLAY_APERTURE, &actual_aperture, 16),
7373 MFT_REGISTER_TYPE_INFO input_type = {MFMediaType_Video, MFVideoFormat_H264};
7374 MFT_REGISTER_TYPE_INFO output_type = {MFMediaType_Video, MFVideoFormat_NV12};
7375 const BYTE *h264_encoded_data, *nv12_frame_data, *i420_frame_data;
7376 ULONG h264_encoded_data_len, nv12_frame_len, i420_frame_len;
7377 DWORD input_id, output_id, input_count, output_count;
7378 MFT_OUTPUT_STREAM_INFO output_info;
7379 MFT_INPUT_STREAM_INFO input_info;
7380 MFT_OUTPUT_DATA_BUFFER output;
7381 IMFMediaBuffer *media_buffer;
7382 DWORD status, length, count;
7383 WCHAR output_path[MAX_PATH];
7384 IMFAttributes *attributes;
7385 IMFMediaType *media_type;
7386 LONGLONG time, duration;
7387 IMFTransform *transform;
7388 ULONG i, ret, flags;
7389 HANDLE output_file;
7390 IMFSample *sample;
7391 HRSRC resource;
7392 GUID class_id;
7393 UINT32 value;
7394 BYTE *data;
7395 HRESULT hr;
7397 hr = CoInitialize(NULL);
7398 ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
7400 if (!create_transform(MFT_CATEGORY_VIDEO_DECODER, &input_type, &output_type, L"Microsoft H264 Video Decoder MFT", &MFMediaType_Video,
7401 transform_inputs, ARRAY_SIZE(transform_inputs), transform_outputs, ARRAY_SIZE(transform_outputs),
7402 &transform, &CLSID_MSH264DecoderMFT, &class_id))
7403 goto failed;
7405 hr = IMFTransform_GetAttributes(transform, &attributes);
7406 ok(hr == S_OK, "GetAttributes returned %#lx\n", hr);
7407 hr = IMFAttributes_SetUINT32(attributes, &MF_LOW_LATENCY, 1);
7408 ok(hr == S_OK, "SetUINT32 returned %#lx\n", hr);
7409 ret = IMFAttributes_Release(attributes);
7410 todo_wine
7411 ok(ret == 1, "Release returned %ld\n", ret);
7413 /* no output type is available before an input type is set */
7415 hr = IMFTransform_GetOutputAvailableType(transform, 0, 0, &media_type);
7416 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetOutputAvailableType returned %#lx\n", hr);
7417 hr = IMFTransform_GetOutputCurrentType(transform, 0, &media_type);
7418 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetOutputCurrentType returned %#lx\n", hr);
7420 /* setting output media type first doesn't work */
7422 hr = MFCreateMediaType(&media_type);
7423 ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr);
7424 init_media_type(media_type, default_outputs[0], -1);
7425 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
7426 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "SetOutputType returned %#lx.\n", hr);
7427 ret = IMFMediaType_Release(media_type);
7428 ok(ret == 0, "Release returned %lu\n", ret);
7430 /* check available input types */
7432 flags = MFT_INPUT_STREAM_WHOLE_SAMPLES | MFT_INPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER | MFT_INPUT_STREAM_FIXED_SAMPLE_SIZE;
7433 memset(&input_info, 0xcd, sizeof(input_info));
7434 hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info);
7435 todo_wine
7436 ok(hr == S_OK, "GetInputStreamInfo returned %#lx\n", hr);
7437 todo_wine
7438 ok(input_info.hnsMaxLatency == 0, "got hnsMaxLatency %s\n", wine_dbgstr_longlong(input_info.hnsMaxLatency));
7439 todo_wine
7440 ok(input_info.dwFlags == flags, "got dwFlags %#lx\n", input_info.dwFlags);
7441 todo_wine
7442 ok(input_info.cbSize == 0x1000, "got cbSize %lu\n", input_info.cbSize);
7443 todo_wine
7444 ok(input_info.cbMaxLookahead == 0, "got cbMaxLookahead %#lx\n", input_info.cbMaxLookahead);
7445 todo_wine
7446 ok(input_info.cbAlignment == 0, "got cbAlignment %#lx\n", input_info.cbAlignment);
7448 flags = MFT_OUTPUT_STREAM_WHOLE_SAMPLES | MFT_OUTPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER | MFT_OUTPUT_STREAM_FIXED_SAMPLE_SIZE;
7449 memset(&output_info, 0xcd, sizeof(output_info));
7450 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
7451 ok(hr == S_OK, "GetOutputStreamInfo returned %#lx\n", hr);
7452 ok(output_info.dwFlags == flags, "got dwFlags %#lx\n", output_info.dwFlags);
7453 ok(output_info.cbSize == 1920 * 1088 * 2, "got cbSize %#lx\n", output_info.cbSize);
7454 ok(output_info.cbAlignment == 0, "got cbAlignment %#lx\n", output_info.cbAlignment);
7456 i = -1;
7457 while (SUCCEEDED(hr = IMFTransform_GetInputAvailableType(transform, 0, ++i, &media_type)))
7459 winetest_push_context("in %lu", i);
7460 ok(hr == S_OK, "GetInputAvailableType returned %#lx\n", hr);
7461 check_media_type(media_type, default_inputs[i], -1);
7462 ret = IMFMediaType_Release(media_type);
7463 ok(ret == 0, "Release returned %lu\n", ret);
7464 winetest_pop_context();
7466 ok(hr == MF_E_NO_MORE_TYPES, "GetInputAvailableType returned %#lx\n", hr);
7467 ok(i == 2 || broken(i == 1) /* Win7 */, "%lu input media types\n", i);
7469 /* check required input media type attributes */
7471 hr = MFCreateMediaType(&media_type);
7472 ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr);
7473 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
7474 ok(hr == E_INVALIDARG, "SetInputType returned %#lx.\n", hr);
7475 init_media_type(media_type, input_type_desc, 1);
7476 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
7477 todo_wine
7478 ok(hr == MF_E_INVALIDMEDIATYPE, "SetInputType returned %#lx.\n", hr);
7479 init_media_type(media_type, input_type_desc, 2);
7480 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
7481 ok(hr == S_OK, "SetInputType returned %#lx.\n", hr);
7482 init_media_type(media_type, input_type_desc, -1);
7483 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
7484 ok(hr == S_OK, "SetInputType returned %#lx.\n", hr);
7485 ret = IMFMediaType_Release(media_type);
7486 ok(ret == 1, "Release returned %lu\n", ret);
7488 flags = MFT_OUTPUT_STREAM_WHOLE_SAMPLES | MFT_OUTPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER | MFT_OUTPUT_STREAM_FIXED_SAMPLE_SIZE;
7489 memset(&output_info, 0xcd, sizeof(output_info));
7490 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
7491 ok(hr == S_OK, "GetOutputStreamInfo returned %#lx\n", hr);
7492 ok(output_info.dwFlags == flags, "got dwFlags %#lx\n", output_info.dwFlags);
7493 todo_wine
7494 ok(output_info.cbSize == input_width * input_height * 2, "got cbSize %#lx\n", output_info.cbSize);
7495 ok(output_info.cbAlignment == 0, "got cbAlignment %#lx\n", output_info.cbAlignment);
7497 /* output types can now be enumerated (though they are actually the same for all input types) */
7499 i = -1;
7500 while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, ++i, &media_type)))
7502 winetest_push_context("out %lu", i);
7503 ok(hr == S_OK, "GetOutputAvailableType returned %#lx\n", hr);
7504 check_media_type(media_type, default_outputs[i], -1);
7505 ret = IMFMediaType_Release(media_type);
7506 ok(ret == 0, "Release returned %lu\n", ret);
7507 winetest_pop_context();
7509 ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
7510 ok(i == 5, "%lu output media types\n", i);
7512 /* check required output media type attributes */
7514 hr = MFCreateMediaType(&media_type);
7515 ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr);
7516 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
7517 todo_wine
7518 ok(hr == E_INVALIDARG, "SetOutputType returned %#lx.\n", hr);
7519 init_media_type(media_type, minimal_output_type_desc, 1);
7520 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
7521 todo_wine
7522 ok(hr == MF_E_INVALIDMEDIATYPE, "SetOutputType returned %#lx.\n", hr);
7523 init_media_type(media_type, minimal_output_type_desc, 2);
7524 for (i = 2; i < ARRAY_SIZE(minimal_output_type_desc) - 1; ++i)
7526 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
7527 todo_wine
7528 ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetOutputType returned %#lx.\n", hr);
7529 init_media_type(media_type, minimal_output_type_desc, i + 1);
7531 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
7532 ok(hr == S_OK, "SetOutputType returned %#lx.\n", hr);
7533 init_media_type(media_type, output_type_desc, -1);
7534 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
7535 ok(hr == S_OK, "SetOutputType returned %#lx.\n", hr);
7536 ret = IMFMediaType_Release(media_type);
7537 ok(ret == 1, "Release returned %lu\n", ret);
7539 hr = IMFTransform_GetOutputCurrentType(transform, 0, &media_type);
7540 ok(hr == S_OK, "GetOutputCurrentType returned %#lx\n", hr);
7541 check_media_type(media_type, output_type_desc, -1);
7542 ret = IMFMediaType_Release(media_type);
7543 ok(ret == 0, "Release returned %lu\n", ret);
7545 /* check that the output media type we've selected don't change the enumeration */
7547 i = -1;
7548 while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, ++i, &media_type)))
7550 winetest_push_context("out %lu", i);
7551 ok(hr == S_OK, "GetOutputAvailableType returned %#lx\n", hr);
7552 check_media_type(media_type, default_outputs[i], -1);
7553 ret = IMFMediaType_Release(media_type);
7554 ok(ret == 0, "Release returned %lu\n", ret);
7555 winetest_pop_context();
7557 ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
7558 ok(i == 5, "%lu output media types\n", i);
7560 flags = MFT_INPUT_STREAM_WHOLE_SAMPLES | MFT_INPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER | MFT_INPUT_STREAM_FIXED_SAMPLE_SIZE;
7561 memset(&input_info, 0xcd, sizeof(input_info));
7562 hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info);
7563 ok(hr == S_OK, "GetInputStreamInfo returned %#lx\n", hr);
7564 ok(input_info.hnsMaxLatency == 0, "got hnsMaxLatency %s\n", wine_dbgstr_longlong(input_info.hnsMaxLatency));
7565 ok(input_info.dwFlags == flags, "got dwFlags %#lx\n", input_info.dwFlags);
7566 ok(input_info.cbSize == 0x1000, "got cbSize %lu\n", input_info.cbSize);
7567 ok(input_info.cbMaxLookahead == 0, "got cbMaxLookahead %#lx\n", input_info.cbMaxLookahead);
7568 ok(input_info.cbAlignment == 0, "got cbAlignment %#lx\n", input_info.cbAlignment);
7570 flags = MFT_OUTPUT_STREAM_WHOLE_SAMPLES | MFT_OUTPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER | MFT_OUTPUT_STREAM_FIXED_SAMPLE_SIZE;
7571 memset(&output_info, 0xcd, sizeof(output_info));
7572 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
7573 ok(hr == S_OK, "GetOutputStreamInfo returned %#lx\n", hr);
7574 ok(output_info.dwFlags == flags, "got dwFlags %#lx\n", output_info.dwFlags);
7575 todo_wine
7576 ok(output_info.cbSize == input_width * input_height * 2, "got cbSize %#lx\n", output_info.cbSize);
7577 ok(output_info.cbAlignment == 0, "got cbAlignment %#lx\n", output_info.cbAlignment);
7579 input_count = output_count = 0xdeadbeef;
7580 hr = IMFTransform_GetStreamCount(transform, &input_count, &output_count);
7581 todo_wine
7582 ok(hr == S_OK, "GetStreamCount returned %#lx\n", hr);
7583 todo_wine
7584 ok(input_count == 1, "got input_count %lu\n", input_count);
7585 todo_wine
7586 ok(output_count == 1, "got output_count %lu\n", output_count);
7587 hr = IMFTransform_GetStreamIDs(transform, 1, &input_id, 1, &output_id);
7588 ok(hr == E_NOTIMPL, "GetStreamIDs returned %#lx\n", hr);
7590 resource = FindResourceW(NULL, L"h264data.bin", (const WCHAR *)RT_RCDATA);
7591 ok(resource != 0, "FindResourceW failed, error %lu\n", GetLastError());
7592 h264_encoded_data = LockResource(LoadResource(GetModuleHandleW(NULL), resource));
7593 h264_encoded_data_len = SizeofResource(GetModuleHandleW(NULL), resource);
7595 /* As output_info.dwFlags doesn't have MFT_OUTPUT_STREAM_CAN_PROVIDE_SAMPLES
7596 * IMFTransform_ProcessOutput needs a sample or returns an error */
7598 status = 0;
7599 memset(&output, 0, sizeof(output));
7600 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
7601 ok(hr == E_INVALIDARG || hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
7602 ok(output.dwStreamID == 0, "got dwStreamID %lu\n", output.dwStreamID);
7603 ok(!output.pSample, "got pSample %p\n", output.pSample);
7604 ok(output.dwStatus == 0, "got dwStatus %#lx\n", output.dwStatus);
7605 ok(!output.pEvents, "got pEvents %p\n", output.pEvents);
7606 ok(status == 0, "got status %#lx\n", status);
7608 i = 0;
7609 sample = next_h264_sample(&h264_encoded_data, &h264_encoded_data_len);
7610 while (1)
7612 status = 0;
7613 memset(&output, 0, sizeof(output));
7614 output.pSample = create_sample(NULL, output_info.cbSize);
7615 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
7616 if (hr != MF_E_TRANSFORM_NEED_MORE_INPUT) break;
7617 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
7618 ok(output.dwStreamID == 0, "got dwStreamID %lu\n", output.dwStreamID);
7619 ok(!!output.pSample, "got pSample %p\n", output.pSample);
7620 ok(output.dwStatus == 0, "got dwStatus %#lx\n", output.dwStatus);
7621 ok(!output.pEvents, "got pEvents %p\n", output.pEvents);
7622 ok(status == 0, "got status %#lx\n", status);
7623 hr = IMFSample_GetTotalLength(output.pSample, &length);
7624 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
7625 ok(length == 0, "got length %lu\n", length);
7626 ret = IMFSample_Release(output.pSample);
7627 ok(ret == 0, "Release returned %lu\n", ret);
7629 hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
7630 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
7631 ret = IMFSample_Release(sample);
7632 ok(ret <= 1, "Release returned %lu\n", ret);
7633 sample = next_h264_sample(&h264_encoded_data, &h264_encoded_data_len);
7635 hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
7636 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
7637 ret = IMFSample_Release(sample);
7638 ok(ret <= 1, "Release returned %lu\n", ret);
7639 sample = next_h264_sample(&h264_encoded_data, &h264_encoded_data_len);
7640 i++;
7642 hr = IMFTransform_ProcessMessage(transform, MFT_MESSAGE_COMMAND_DRAIN, 0);
7643 ok(hr == S_OK, "ProcessMessage returned %#lx\n", hr);
7645 todo_wine
7646 ok(i == 2, "got %lu iterations\n", i);
7647 todo_wine
7648 ok(h264_encoded_data_len == 1180, "got h264_encoded_data_len %lu\n", h264_encoded_data_len);
7649 ok(hr == MF_E_TRANSFORM_STREAM_CHANGE, "ProcessOutput returned %#lx\n", hr);
7650 ok(output.dwStreamID == 0, "got dwStreamID %lu\n", output.dwStreamID);
7651 ok(!!output.pSample, "got pSample %p\n", output.pSample);
7652 ok(output.dwStatus == MFT_OUTPUT_DATA_BUFFER_FORMAT_CHANGE,
7653 "got dwStatus %#lx\n", output.dwStatus);
7654 ok(!output.pEvents, "got pEvents %p\n", output.pEvents);
7655 ok(status == MFT_PROCESS_OUTPUT_STATUS_NEW_STREAMS,
7656 "got status %#lx\n", status);
7657 hr = IMFSample_GetTotalLength(output.pSample, &length);
7658 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
7659 ok(length == 0, "got length %lu\n", length);
7660 ret = IMFSample_Release(output.pSample);
7661 ok(ret == 0, "Release returned %lu\n", ret);
7663 flags = MFT_OUTPUT_STREAM_WHOLE_SAMPLES | MFT_OUTPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER | MFT_OUTPUT_STREAM_FIXED_SAMPLE_SIZE;
7664 memset(&output_info, 0xcd, sizeof(output_info));
7665 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
7666 ok(hr == S_OK, "GetOutputStreamInfo returned %#lx\n", hr);
7667 ok(output_info.dwFlags == flags, "got dwFlags %#lx\n", output_info.dwFlags);
7668 ok(output_info.cbSize == actual_width * actual_height * 2, "got cbSize %#lx\n", output_info.cbSize);
7669 ok(output_info.cbAlignment == 0, "got cbAlignment %#lx\n", output_info.cbAlignment);
7671 i = -1;
7672 while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, ++i, &media_type)))
7674 winetest_push_context("out %lu", i);
7675 ok(hr == S_OK, "GetOutputAvailableType returned %#lx\n", hr);
7676 check_media_type(media_type, actual_outputs[i], -1);
7677 ret = IMFMediaType_Release(media_type);
7678 ok(ret == 0, "Release returned %lu\n", ret);
7679 winetest_pop_context();
7681 ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
7682 ok(i == 5, "%lu output media types\n", i);
7684 /* current output type is still the one we selected */
7685 hr = IMFTransform_GetOutputCurrentType(transform, 0, &media_type);
7686 ok(hr == S_OK, "GetOutputCurrentType returned %#lx\n", hr);
7687 check_media_type(media_type, output_type_desc, -1);
7688 hr = IMFMediaType_GetItemType(media_type, &MF_MT_MINIMUM_DISPLAY_APERTURE, NULL);
7689 ok(hr == MF_E_ATTRIBUTENOTFOUND, "GetItemType returned %#lx\n", hr);
7690 ret = IMFMediaType_Release(media_type);
7691 ok(ret == 0, "Release returned %lu\n", ret);
7693 /* and generate a new one as well in a temporary directory */
7694 GetTempPathW(ARRAY_SIZE(output_path), output_path);
7695 lstrcatW(output_path, L"nv12frame.bin");
7696 output_file = CreateFileW(output_path, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
7697 ok(output_file != INVALID_HANDLE_VALUE, "CreateFileW failed, error %lu\n", GetLastError());
7699 resource = FindResourceW(NULL, L"nv12frame.bin", (const WCHAR *)RT_RCDATA);
7700 ok(resource != 0, "FindResourceW failed, error %lu\n", GetLastError());
7701 nv12_frame_data = LockResource(LoadResource(GetModuleHandleW(NULL), resource));
7702 nv12_frame_len = SizeofResource(GetModuleHandleW(NULL), resource);
7703 ok(nv12_frame_len == actual_width * actual_height * 3 / 2, "got frame length %lu\n", nv12_frame_len);
7705 status = 0;
7706 memset(&output, 0, sizeof(output));
7707 output.pSample = create_sample(NULL, nv12_frame_len);
7708 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
7709 ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr);
7710 ok(output.dwStreamID == 0, "got dwStreamID %lu\n", output.dwStreamID);
7711 ok(!!output.pSample, "got pSample %p\n", output.pSample);
7712 ok(output.dwStatus == 0, "got dwStatus %#lx\n", output.dwStatus);
7713 ok(!output.pEvents, "got pEvents %p\n", output.pEvents);
7714 ok(status == 0, "got status %#lx\n", status);
7716 hr = IMFSample_GetUINT32(sample, &MFSampleExtension_CleanPoint, &value);
7717 ok(hr == MF_E_ATTRIBUTENOTFOUND, "GetUINT32 MFSampleExtension_CleanPoint returned %#lx\n", hr);
7719 count = 0xdeadbeef;
7720 hr = IMFSample_GetBufferCount(output.pSample, &count);
7721 ok(hr == S_OK, "GetBufferCount returned %#lx\n", hr);
7722 ok(count == 1, "got count %#lx\n", count);
7724 flags = 0xdeadbeef;
7725 hr = IMFSample_GetSampleFlags(output.pSample, &flags);
7726 ok(hr == S_OK, "GetSampleFlags returned %#lx\n", hr);
7727 ok(flags == 0, "got flags %#lx\n", flags);
7729 time = 0xdeadbeef;
7730 hr = IMFSample_GetSampleTime(output.pSample, &time);
7731 ok(hr == S_OK, "GetSampleTime returned %#lx\n", hr);
7732 ok(time == 0, "got time %I64d\n", time);
7734 /* doesn't matter what frame rate we've selected, duration is defined by the stream */
7735 duration = 0xdeadbeef;
7736 hr = IMFSample_GetSampleDuration(output.pSample, &duration);
7737 ok(hr == S_OK, "GetSampleDuration returned %#lx\n", hr);
7738 ok(duration - 333666 <= 2, "got duration %I64d\n", duration);
7740 /* Win8 and before pad the data with garbage instead of original
7741 * buffer data, make sure it's consistent. */
7742 hr = IMFSample_ConvertToContiguousBuffer(output.pSample, &media_buffer);
7743 ok(hr == S_OK, "ConvertToContiguousBuffer returned %#lx\n", hr);
7744 hr = IMFMediaBuffer_Lock(media_buffer, &data, NULL, &length);
7745 ok(hr == S_OK, "Lock returned %#lx\n", hr);
7746 ok(length == nv12_frame_len, "got length %lu\n", length);
7748 for (i = 0; i < actual_aperture.Area.cy; ++i)
7750 memset(data + actual_width * i + actual_aperture.Area.cx, 0xcd, actual_width - actual_aperture.Area.cx);
7751 memset(data + actual_width * (actual_height + i / 2) + actual_aperture.Area.cx, 0xcd, actual_width - actual_aperture.Area.cx);
7753 memset(data + actual_width * actual_aperture.Area.cy, 0xcd, (actual_height - actual_aperture.Area.cy) * actual_width);
7754 memset(data + actual_width * (actual_height + actual_aperture.Area.cy / 2), 0xcd, (actual_height - actual_aperture.Area.cy) / 2 * actual_width);
7756 hr = IMFMediaBuffer_Unlock(media_buffer);
7757 ok(hr == S_OK, "Unlock returned %#lx\n", hr);
7758 IMFMediaBuffer_Release(media_buffer);
7760 check_sample(output.pSample, nv12_frame_data, output_file);
7762 ret = IMFSample_Release(output.pSample);
7763 ok(ret == 0, "Release returned %lu\n", ret);
7765 trace("created %s\n", debugstr_w(output_path));
7766 CloseHandle(output_file);
7768 /* we can change it, but only with the correct frame size */
7769 hr = MFCreateMediaType(&media_type);
7770 ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr);
7771 init_media_type(media_type, output_type_desc, -1);
7772 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
7773 ok(hr == MF_E_INVALIDMEDIATYPE, "SetOutputType returned %#lx.\n", hr);
7774 init_media_type(media_type, new_output_type_desc, -1);
7775 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
7776 ok(hr == S_OK, "SetOutputType returned %#lx.\n", hr);
7777 ret = IMFMediaType_Release(media_type);
7778 ok(ret == 1, "Release returned %lu\n", ret);
7780 hr = IMFTransform_GetOutputCurrentType(transform, 0, &media_type);
7781 ok(hr == S_OK, "GetOutputCurrentType returned %#lx\n", hr);
7782 check_media_type(media_type, new_output_type_desc, -1);
7783 hr = IMFMediaType_GetItemType(media_type, &MF_MT_MINIMUM_DISPLAY_APERTURE, NULL);
7784 ok(hr == MF_E_ATTRIBUTENOTFOUND, "GetItemType returned %#lx\n", hr);
7785 ret = IMFMediaType_Release(media_type);
7786 ok(ret == 0, "Release returned %lu\n", ret);
7788 status = 0;
7789 memset(&output, 0, sizeof(output));
7790 output.pSample = create_sample(NULL, actual_width * actual_height * 2);
7791 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
7792 todo_wine
7793 ok(hr == MF_E_TRANSFORM_STREAM_CHANGE, "ProcessOutput returned %#lx\n", hr);
7795 while (hr == MF_E_TRANSFORM_NEED_MORE_INPUT)
7797 hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
7798 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
7799 ret = IMFSample_Release(sample);
7800 ok(ret <= 1, "Release returned %lu\n", ret);
7801 sample = next_h264_sample(&h264_encoded_data, &h264_encoded_data_len);
7802 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
7803 todo_wine_if(hr == MF_E_TRANSFORM_NEED_MORE_INPUT)
7804 ok(hr == MF_E_TRANSFORM_STREAM_CHANGE, "ProcessOutput returned %#lx\n", hr);
7807 ok(output.dwStreamID == 0, "got dwStreamID %lu\n", output.dwStreamID);
7808 ok(!!output.pSample, "got pSample %p\n", output.pSample);
7809 ok(output.dwStatus == MFT_OUTPUT_DATA_BUFFER_FORMAT_CHANGE, "got dwStatus %#lx\n", output.dwStatus);
7810 ok(!output.pEvents, "got pEvents %p\n", output.pEvents);
7811 ok(status == MFT_PROCESS_OUTPUT_STATUS_NEW_STREAMS, "got status %#lx\n", status);
7812 hr = IMFSample_GetTotalLength(output.pSample, &length);
7813 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
7814 ok(length == 0, "got length %lu\n", length);
7815 ret = IMFSample_Release(output.pSample);
7816 ok(ret == 0, "Release returned %lu\n", ret);
7818 GetTempPathW(ARRAY_SIZE(output_path), output_path);
7819 lstrcatW(output_path, L"i420frame.bin");
7820 output_file = CreateFileW(output_path, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
7821 ok(output_file != INVALID_HANDLE_VALUE, "CreateFileW failed, error %lu\n", GetLastError());
7823 resource = FindResourceW(NULL, L"i420frame.bin", (const WCHAR *)RT_RCDATA);
7824 ok(resource != 0, "FindResourceW failed, error %lu\n", GetLastError());
7825 i420_frame_data = LockResource(LoadResource(GetModuleHandleW(NULL), resource));
7826 i420_frame_len = SizeofResource(GetModuleHandleW(NULL), resource);
7827 ok(i420_frame_len == actual_width * actual_height * 3 / 2, "got frame length %lu\n", i420_frame_len);
7829 status = 0;
7830 memset(&output, 0, sizeof(output));
7831 output.pSample = create_sample(NULL, actual_width * actual_height * 2);
7832 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
7833 ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr);
7834 ok(output.dwStreamID == 0, "got dwStreamID %lu\n", output.dwStreamID);
7835 ok(!!output.pSample, "got pSample %p\n", output.pSample);
7836 ok(output.dwStatus == 0, "got dwStatus %#lx\n", output.dwStatus);
7837 ok(!output.pEvents, "got pEvents %p\n", output.pEvents);
7838 ok(status == 0, "got status %#lx\n", status);
7840 hr = IMFSample_GetSampleTime(output.pSample, &time);
7841 ok(hr == S_OK, "GetSampleTime returned %#lx\n", hr);
7842 todo_wine_if(time == 1334666) /* when VA-API plugin is used */
7843 ok(time - 333666 <= 2, "got time %I64d\n", time);
7845 duration = 0xdeadbeef;
7846 hr = IMFSample_GetSampleDuration(output.pSample, &duration);
7847 ok(hr == S_OK, "GetSampleDuration returned %#lx\n", hr);
7848 ok(duration - 333666 <= 2, "got duration %I64d\n", duration);
7850 /* Win8 and before pad the data with garbage instead of original
7851 * buffer data, make sure it's consistent. */
7852 hr = IMFSample_ConvertToContiguousBuffer(output.pSample, &media_buffer);
7853 ok(hr == S_OK, "ConvertToContiguousBuffer returned %#lx\n", hr);
7854 hr = IMFMediaBuffer_Lock(media_buffer, &data, NULL, &length);
7855 ok(hr == S_OK, "Lock returned %#lx\n", hr);
7856 ok(length == i420_frame_len, "got length %lu\n", length);
7858 for (i = 0; i < actual_aperture.Area.cy; ++i)
7860 memset(data + actual_width * i + actual_aperture.Area.cx, 0xcd, actual_width - actual_aperture.Area.cx);
7861 memset(data + actual_width * actual_height + actual_width / 2 * i + actual_aperture.Area.cx / 2, 0xcd,
7862 actual_width / 2 - actual_aperture.Area.cx / 2);
7863 memset(data + actual_width * actual_height + actual_width / 2 * (actual_height / 2 + i) + actual_aperture.Area.cx / 2, 0xcd,
7864 actual_width / 2 - actual_aperture.Area.cx / 2);
7866 memset(data + actual_width * actual_aperture.Area.cy, 0xcd, (actual_height - actual_aperture.Area.cy) * actual_width);
7867 memset(data + actual_width * actual_height + actual_width / 2 * actual_aperture.Area.cy / 2, 0xcd,
7868 (actual_height - actual_aperture.Area.cy) / 2 * actual_width / 2);
7869 memset(data + actual_width * actual_height + actual_width / 2 * (actual_height / 2 + actual_aperture.Area.cy / 2), 0xcd,
7870 (actual_height - actual_aperture.Area.cy) / 2 * actual_width / 2);
7872 hr = IMFMediaBuffer_Unlock(media_buffer);
7873 ok(hr == S_OK, "Unlock returned %#lx\n", hr);
7874 IMFMediaBuffer_Release(media_buffer);
7876 check_sample(output.pSample, i420_frame_data, output_file);
7878 ret = IMFSample_Release(output.pSample);
7879 ok(ret == 0, "Release returned %lu\n", ret);
7881 trace("created %s\n", debugstr_w(output_path));
7882 CloseHandle(output_file);
7884 status = 0;
7885 memset(&output, 0, sizeof(output));
7886 output.pSample = create_sample(NULL, actual_width * actual_height * 2);
7887 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
7888 todo_wine_if(hr == S_OK) /* when VA-API plugin is used */
7889 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
7890 ok(output.dwStreamID == 0, "got dwStreamID %lu\n", output.dwStreamID);
7891 ok(!!output.pSample, "got pSample %p\n", output.pSample);
7892 ok(output.dwStatus == 0, "got dwStatus %#lx\n", output.dwStatus);
7893 ok(!output.pEvents, "got pEvents %p\n", output.pEvents);
7894 ok(status == 0, "got status %#lx\n", status);
7895 ret = IMFSample_Release(output.pSample);
7896 ok(ret == 0, "Release returned %lu\n", ret);
7898 ret = IMFTransform_Release(transform);
7899 ok(ret == 0, "Release returned %lu\n", ret);
7900 ret = IMFSample_Release(sample);
7901 ok(ret == 0, "Release returned %lu\n", ret);
7903 failed:
7904 CoUninitialize();
7907 static void test_audio_convert(void)
7909 const GUID transform_inputs[2] =
7911 MFAudioFormat_PCM,
7912 MFAudioFormat_Float,
7914 const GUID transform_outputs[2] =
7916 MFAudioFormat_PCM,
7917 MFAudioFormat_Float,
7920 static const media_type_desc expect_available_inputs[] =
7923 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
7924 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_Float),
7925 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
7928 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
7929 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
7930 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
7933 static const media_type_desc expect_available_outputs[] =
7936 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
7937 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_Float),
7938 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
7941 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
7942 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
7943 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
7946 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
7947 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_Float),
7948 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 32),
7949 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
7950 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 48000),
7951 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 384000),
7952 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 8),
7953 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
7954 ATTR_UINT32(MF_MT_AUDIO_PREFER_WAVEFORMATEX, 1),
7957 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
7958 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
7959 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16),
7960 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
7961 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 48000),
7962 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 192000),
7963 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 4),
7964 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
7965 ATTR_UINT32(MF_MT_AUDIO_PREFER_WAVEFORMATEX, 1),
7969 static const struct attribute_desc input_type_desc[] =
7971 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
7972 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_Float),
7973 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 32),
7974 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
7975 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
7976 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 176400),
7977 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 8),
7978 {0},
7980 const struct attribute_desc output_type_desc[] =
7982 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
7983 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
7984 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16),
7985 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
7986 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100),
7987 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 176400),
7988 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 4),
7989 {0},
7992 MFT_REGISTER_TYPE_INFO output_type = {MFMediaType_Audio, MFAudioFormat_PCM};
7993 MFT_REGISTER_TYPE_INFO input_type = {MFMediaType_Audio, MFAudioFormat_Float};
7994 static const ULONG audioconv_block_size = 0x4000;
7995 ULONG audio_data_len, audioconv_data_len;
7996 const BYTE *audio_data, *audioconv_data;
7997 MFT_OUTPUT_STREAM_INFO output_info;
7998 MFT_INPUT_STREAM_INFO input_info;
7999 MFT_OUTPUT_DATA_BUFFER output;
8000 WCHAR output_path[MAX_PATH];
8001 IMFMediaType *media_type;
8002 LONGLONG time, duration;
8003 IMFTransform *transform;
8004 DWORD length, status;
8005 HANDLE output_file;
8006 IMFSample *sample;
8007 HRSRC resource;
8008 GUID class_id;
8009 ULONG i, ret;
8010 HRESULT hr;
8012 hr = CoInitialize(NULL);
8013 ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
8015 if (!create_transform(MFT_CATEGORY_AUDIO_EFFECT, &input_type, &output_type, L"Resampler MFT", &MFMediaType_Audio,
8016 transform_inputs, ARRAY_SIZE(transform_inputs), transform_outputs, ARRAY_SIZE(transform_outputs),
8017 &transform, &CLSID_CResamplerMediaObject, &class_id))
8018 goto failed;
8020 check_dmo(&class_id, L"Resampler DMO", &MEDIATYPE_Audio, transform_inputs, ARRAY_SIZE(transform_inputs),
8021 transform_outputs, ARRAY_SIZE(transform_outputs));
8023 check_interface(transform, &IID_IMFTransform, TRUE);
8024 check_interface(transform, &IID_IMediaObject, TRUE);
8025 check_interface(transform, &IID_IPropertyStore, TRUE);
8026 check_interface(transform, &IID_IPropertyBag, TRUE);
8027 /* check_interface(transform, &IID_IWMResamplerProps, TRUE); */
8029 /* check default media types */
8031 hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info);
8032 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetInputStreamInfo returned %#lx\n", hr);
8033 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
8034 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetOutputStreamInfo returned %#lx\n", hr);
8036 i = -1;
8037 while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, ++i, &media_type)))
8039 winetest_push_context("out %lu", i);
8040 ok(hr == S_OK, "GetOutputAvailableType returned %#lx\n", hr);
8041 check_media_type(media_type, expect_available_outputs[i], -1);
8042 ret = IMFMediaType_Release(media_type);
8043 ok(ret == 0, "Release returned %lu\n", ret);
8044 winetest_pop_context();
8046 ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
8047 ok(i == 4, "%lu output media types\n", i);
8049 i = -1;
8050 while (SUCCEEDED(hr = IMFTransform_GetInputAvailableType(transform, 0, ++i, &media_type)))
8052 winetest_push_context("in %lu", i);
8053 ok(hr == S_OK, "GetInputAvailableType returned %#lx\n", hr);
8054 check_media_type(media_type, expect_available_inputs[i], -1);
8055 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
8056 ok(hr == MF_E_INVALIDMEDIATYPE, "SetInputType returned %#lx.\n", hr);
8057 ret = IMFMediaType_Release(media_type);
8058 ok(ret == 0, "Release returned %lu\n", ret);
8059 winetest_pop_context();
8061 ok(hr == MF_E_NO_MORE_TYPES, "GetInputAvailableType returned %#lx\n", hr);
8062 ok(i == 2, "%lu input media types\n", i);
8064 /* setting output media type first doesn't work */
8066 hr = MFCreateMediaType(&media_type);
8067 ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr);
8068 init_media_type(media_type, output_type_desc, -1);
8069 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
8070 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "SetOutputType returned %#lx.\n", hr);
8071 ret = IMFMediaType_Release(media_type);
8072 ok(ret == 0, "Release returned %lu\n", ret);
8074 /* check required input media type attributes */
8076 hr = MFCreateMediaType(&media_type);
8077 ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr);
8078 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
8079 ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetInputType returned %#lx.\n", hr);
8080 init_media_type(media_type, input_type_desc, 1);
8081 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
8082 ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetInputType returned %#lx.\n", hr);
8083 init_media_type(media_type, input_type_desc, 2);
8084 for (i = 2; i < ARRAY_SIZE(input_type_desc) - 1; ++i)
8086 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
8087 ok(hr == MF_E_INVALIDMEDIATYPE, "SetInputType returned %#lx.\n", hr);
8088 init_media_type(media_type, input_type_desc, i + 1);
8090 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
8091 ok(hr == S_OK, "SetInputType returned %#lx.\n", hr);
8092 ret = IMFMediaType_Release(media_type);
8093 ok(ret == 0, "Release returned %lu\n", ret);
8095 hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info);
8096 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetInputStreamInfo returned %#lx\n", hr);
8097 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
8098 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetOutputStreamInfo returned %#lx\n", hr);
8100 /* check new output media types */
8102 i = -1;
8103 while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, ++i, &media_type)))
8105 winetest_push_context("out %lu", i);
8106 ok(hr == S_OK, "GetOutputAvailableType returned %#lx\n", hr);
8107 check_media_type(media_type, expect_available_outputs[i], -1);
8108 ret = IMFMediaType_Release(media_type);
8109 ok(ret == 0, "Release returned %lu\n", ret);
8110 winetest_pop_context();
8112 ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
8113 ok(i == 4, "%lu output media types\n", i);
8115 /* check required output media type attributes */
8117 hr = MFCreateMediaType(&media_type);
8118 ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr);
8119 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
8120 ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetOutputType returned %#lx.\n", hr);
8121 init_media_type(media_type, output_type_desc, 1);
8122 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
8123 ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetOutputType returned %#lx.\n", hr);
8124 init_media_type(media_type, output_type_desc, 2);
8125 for (i = 2; i < ARRAY_SIZE(output_type_desc) - 1; ++i)
8127 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
8128 ok(hr == MF_E_INVALIDMEDIATYPE, "SetOutputType returned %#lx.\n", hr);
8129 init_media_type(media_type, output_type_desc, i + 1);
8131 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
8132 ok(hr == S_OK, "SetOutputType returned %#lx.\n", hr);
8133 ret = IMFMediaType_Release(media_type);
8134 ok(ret == 0, "Release returned %lu\n", ret);
8136 memset(&input_info, 0xcd, sizeof(input_info));
8137 hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info);
8138 ok(hr == S_OK, "GetInputStreamInfo returned %#lx\n", hr);
8139 ok(input_info.hnsMaxLatency == 0, "got hnsMaxLatency %s\n", wine_dbgstr_longlong(input_info.hnsMaxLatency));
8140 ok(input_info.dwFlags == 0, "got dwFlags %#lx\n", input_info.dwFlags);
8141 ok(input_info.cbSize == 8, "got cbSize %lu\n", input_info.cbSize);
8142 ok(input_info.cbMaxLookahead == 0, "got cbMaxLookahead %#lx\n", input_info.cbMaxLookahead);
8143 ok(input_info.cbAlignment == 1, "got cbAlignment %#lx\n", input_info.cbAlignment);
8145 memset(&output_info, 0xcd, sizeof(output_info));
8146 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
8147 ok(hr == S_OK, "GetOutputStreamInfo returned %#lx\n", hr);
8148 ok(output_info.dwFlags == 0, "got dwFlags %#lx\n", output_info.dwFlags);
8149 ok(output_info.cbSize == 4, "got cbSize %#lx\n", output_info.cbSize);
8150 ok(output_info.cbAlignment == 1, "got cbAlignment %#lx\n", output_info.cbAlignment);
8152 resource = FindResourceW(NULL, L"audiodata.bin", (const WCHAR *)RT_RCDATA);
8153 ok(resource != 0, "FindResourceW failed, error %lu\n", GetLastError());
8154 audio_data = LockResource(LoadResource(GetModuleHandleW(NULL), resource));
8155 audio_data_len = SizeofResource(GetModuleHandleW(NULL), resource);
8156 ok(audio_data_len == 179928, "got length %lu\n", audio_data_len);
8158 sample = create_sample(audio_data, audio_data_len);
8159 hr = IMFSample_SetSampleTime(sample, 0);
8160 ok(hr == S_OK, "SetSampleTime returned %#lx\n", hr);
8161 hr = IMFSample_SetSampleDuration(sample, 10000000);
8162 ok(hr == S_OK, "SetSampleDuration returned %#lx\n", hr);
8163 hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
8164 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
8165 hr = IMFTransform_ProcessMessage(transform, MFT_MESSAGE_COMMAND_DRAIN, 0);
8166 ok(hr == S_OK, "ProcessMessage returned %#lx\n", hr);
8167 hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
8168 ok(hr == MF_E_NOTACCEPTING, "ProcessInput returned %#lx\n", hr);
8169 ret = IMFSample_Release(sample);
8170 ok(ret <= 1, "Release returned %ld\n", ret);
8172 status = 0xdeadbeef;
8173 sample = create_sample(NULL, audioconv_block_size);
8174 memset(&output, 0, sizeof(output));
8175 output.pSample = sample;
8177 resource = FindResourceW(NULL, L"audioconvdata.bin", (const WCHAR *)RT_RCDATA);
8178 ok(resource != 0, "FindResourceW failed, error %lu\n", GetLastError());
8179 audioconv_data = LockResource(LoadResource(GetModuleHandleW(NULL), resource));
8180 audioconv_data_len = SizeofResource(GetModuleHandleW(NULL), resource);
8181 ok(audioconv_data_len == 179924, "got length %lu\n", audioconv_data_len);
8183 /* and generate a new one as well in a temporary directory */
8184 GetTempPathW(ARRAY_SIZE(output_path), output_path);
8185 lstrcatW(output_path, L"audioconvdata.bin");
8186 output_file = CreateFileW(output_path, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
8187 ok(output_file != INVALID_HANDLE_VALUE, "CreateFileW failed, error %lu\n", GetLastError());
8189 i = 0;
8190 while (SUCCEEDED(hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status)))
8192 winetest_push_context("%lu", i);
8193 ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr);
8194 ok(output.pSample == sample, "got pSample %p\n", output.pSample);
8195 ok(output.dwStatus == MFT_OUTPUT_DATA_BUFFER_INCOMPLETE || output.dwStatus == 0 ||
8196 broken(output.dwStatus == (MFT_OUTPUT_DATA_BUFFER_INCOMPLETE|6) || output.dwStatus == 6) /* win7 */,
8197 "got dwStatus %#lx\n", output.dwStatus);
8198 ok(status == 0, "got status %#lx\n", status);
8199 if (!(output.dwStatus & MFT_OUTPUT_DATA_BUFFER_INCOMPLETE))
8201 winetest_pop_context();
8202 break;
8205 hr = IMFSample_GetSampleTime(sample, &time);
8206 ok(hr == S_OK, "GetSampleTime returned %#lx\n", hr);
8207 ok(time == i * 928798, "got time %I64d\n", time);
8208 hr = IMFSample_GetSampleDuration(sample, &duration);
8209 ok(hr == S_OK, "GetSampleDuration returned %#lx\n", hr);
8210 ok(duration == 928798, "got duration %I64d\n", duration);
8211 hr = IMFSample_GetTotalLength(sample, &length);
8212 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
8213 ok(length == audioconv_block_size, "got length %lu\n", length);
8214 ok(audioconv_data_len > audioconv_block_size, "got remaining length %lu\n", audioconv_data_len);
8215 check_sample_pcm16(sample, audioconv_data, output_file, FALSE);
8216 audioconv_data_len -= audioconv_block_size;
8217 audioconv_data += audioconv_block_size;
8219 winetest_pop_context();
8220 i++;
8223 hr = IMFSample_GetSampleTime(sample, &time);
8224 ok(hr == S_OK, "GetSampleTime returned %#lx\n", hr);
8225 ok(time == i * 928798, "got time %I64d\n", time);
8226 hr = IMFSample_GetSampleDuration(sample, &duration);
8227 ok(hr == S_OK, "GetSampleDuration returned %#lx\n", hr);
8228 todo_wine
8229 ok(duration == 897506, "got duration %I64d\n", duration);
8230 hr = IMFSample_GetTotalLength(sample, &length);
8231 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
8232 todo_wine
8233 ok(length == 15832, "got length %lu\n", length);
8234 ok(audioconv_data_len == 16084, "got remaining length %lu\n", audioconv_data_len);
8235 check_sample_pcm16(sample, audioconv_data, output_file, FALSE);
8236 audioconv_data_len -= length;
8237 audioconv_data += length;
8239 memset(&output, 0, sizeof(output));
8240 output.pSample = sample;
8241 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
8242 todo_wine
8243 ok(hr == S_OK || broken(hr == MF_E_TRANSFORM_NEED_MORE_INPUT) /* win7 */, "ProcessOutput returned %#lx\n", hr);
8244 ok(output.pSample == sample, "got pSample %p\n", output.pSample);
8245 todo_wine
8246 ok(output.dwStatus == MFT_OUTPUT_DATA_BUFFER_INCOMPLETE || broken(output.dwStatus == 0) /* win7 */,
8247 "got dwStatus %#lx\n", output.dwStatus);
8248 ok(status == 0, "got status %#lx\n", status);
8250 if (hr == S_OK)
8252 hr = IMFSample_GetSampleTime(sample, &time);
8253 ok(hr == S_OK, "GetSampleTime returned %#lx\n", hr);
8254 todo_wine
8255 ok(time == 10185486, "got time %I64d\n", time);
8256 hr = IMFSample_GetSampleDuration(sample, &duration);
8257 ok(hr == S_OK, "GetSampleDuration returned %#lx\n", hr);
8258 todo_wine
8259 ok(duration == 14286, "got duration %I64d\n", duration);
8260 hr = IMFSample_GetTotalLength(sample, &length);
8261 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
8262 todo_wine
8263 ok(length == audioconv_data_len, "got length %lu\n", length);
8264 if (length == audioconv_data_len)
8265 check_sample_pcm16(sample, audioconv_data, output_file, FALSE);
8268 trace("created %s\n", debugstr_w(output_path));
8269 CloseHandle(output_file);
8271 ret = IMFSample_Release(sample);
8272 ok(ret == 0, "Release returned %lu\n", ret);
8274 status = 0xdeadbeef;
8275 sample = create_sample(NULL, audioconv_block_size);
8276 memset(&output, 0, sizeof(output));
8277 output.pSample = sample;
8278 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
8279 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
8280 ok(output.pSample == sample, "got pSample %p\n", output.pSample);
8281 ok(output.dwStatus == 0, "got dwStatus %#lx\n", output.dwStatus);
8282 ok(status == 0, "got status %#lx\n", status);
8283 hr = IMFSample_GetTotalLength(sample, &length);
8284 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
8285 ok(length == 0, "got length %lu\n", length);
8286 ret = IMFSample_Release(sample);
8287 ok(ret == 0, "Release returned %lu\n", ret);
8289 ret = IMFTransform_Release(transform);
8290 ok(ret == 0, "Release returned %lu\n", ret);
8292 failed:
8293 CoUninitialize();
8296 static void test_color_convert(void)
8298 const GUID transform_inputs[20] =
8300 MFVideoFormat_YV12,
8301 MFVideoFormat_YUY2,
8302 MFVideoFormat_UYVY,
8303 MFVideoFormat_AYUV,
8304 MFVideoFormat_NV12,
8305 DMOVideoFormat_RGB32,
8306 DMOVideoFormat_RGB565,
8307 MFVideoFormat_I420,
8308 MFVideoFormat_IYUV,
8309 MFVideoFormat_YVYU,
8310 DMOVideoFormat_RGB24,
8311 DMOVideoFormat_RGB555,
8312 DMOVideoFormat_RGB8,
8313 MEDIASUBTYPE_V216,
8314 MEDIASUBTYPE_V410,
8315 MFVideoFormat_NV11,
8316 MFVideoFormat_Y41P,
8317 MFVideoFormat_Y41T,
8318 MFVideoFormat_Y42T,
8319 MFVideoFormat_YVU9,
8321 const GUID transform_outputs[16] =
8323 MFVideoFormat_YV12,
8324 MFVideoFormat_YUY2,
8325 MFVideoFormat_UYVY,
8326 MFVideoFormat_AYUV,
8327 MFVideoFormat_NV12,
8328 DMOVideoFormat_RGB32,
8329 DMOVideoFormat_RGB565,
8330 MFVideoFormat_I420,
8331 MFVideoFormat_IYUV,
8332 MFVideoFormat_YVYU,
8333 DMOVideoFormat_RGB24,
8334 DMOVideoFormat_RGB555,
8335 DMOVideoFormat_RGB8,
8336 MEDIASUBTYPE_V216,
8337 MEDIASUBTYPE_V410,
8338 MFVideoFormat_NV11,
8340 const GUID dmo_inputs[20] =
8342 MEDIASUBTYPE_YV12,
8343 MEDIASUBTYPE_YUY2,
8344 MEDIASUBTYPE_UYVY,
8345 MEDIASUBTYPE_AYUV,
8346 MEDIASUBTYPE_NV12,
8347 MEDIASUBTYPE_RGB32,
8348 MEDIASUBTYPE_RGB565,
8349 MEDIASUBTYPE_I420,
8350 MEDIASUBTYPE_IYUV,
8351 MEDIASUBTYPE_YVYU,
8352 MEDIASUBTYPE_RGB24,
8353 MEDIASUBTYPE_RGB555,
8354 MEDIASUBTYPE_RGB8,
8355 MEDIASUBTYPE_V216,
8356 MEDIASUBTYPE_V410,
8357 MEDIASUBTYPE_NV11,
8358 MEDIASUBTYPE_Y41P,
8359 MEDIASUBTYPE_Y41T,
8360 MEDIASUBTYPE_Y42T,
8361 MEDIASUBTYPE_YVU9,
8363 const GUID dmo_outputs[16] =
8365 MEDIASUBTYPE_YV12,
8366 MEDIASUBTYPE_YUY2,
8367 MEDIASUBTYPE_UYVY,
8368 MEDIASUBTYPE_AYUV,
8369 MEDIASUBTYPE_NV12,
8370 MEDIASUBTYPE_RGB32,
8371 MEDIASUBTYPE_RGB565,
8372 MEDIASUBTYPE_I420,
8373 MEDIASUBTYPE_IYUV,
8374 MEDIASUBTYPE_YVYU,
8375 MEDIASUBTYPE_RGB24,
8376 MEDIASUBTYPE_RGB555,
8377 MEDIASUBTYPE_RGB8,
8378 MEDIASUBTYPE_V216,
8379 MEDIASUBTYPE_V410,
8380 MEDIASUBTYPE_NV11,
8383 static const media_type_desc expect_available_inputs[20] =
8385 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YV12), },
8386 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YUY2), },
8387 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_UYVY), },
8388 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_AYUV), },
8389 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12), },
8390 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32), },
8391 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB565), },
8392 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_I420), },
8393 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_IYUV), },
8394 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YVYU), },
8395 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB24), },
8396 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB555), },
8397 { ATTR_GUID(MF_MT_SUBTYPE, MEDIASUBTYPE_RGB8), },
8398 { ATTR_GUID(MF_MT_SUBTYPE, MEDIASUBTYPE_V216), },
8399 { ATTR_GUID(MF_MT_SUBTYPE, MEDIASUBTYPE_V410), },
8400 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV11), },
8401 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_Y41P), },
8402 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_Y41T), },
8403 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_Y42T), },
8404 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YVU9), },
8406 static const media_type_desc expect_available_outputs[16] =
8408 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YV12), },
8409 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YUY2), },
8410 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_UYVY), },
8411 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_AYUV), },
8412 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12), },
8413 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32), },
8414 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB565), },
8415 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_I420), },
8416 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_IYUV), },
8417 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YVYU), },
8418 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB24), },
8419 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB555), },
8420 { ATTR_GUID(MF_MT_SUBTYPE, MEDIASUBTYPE_RGB8), },
8421 { ATTR_GUID(MF_MT_SUBTYPE, MEDIASUBTYPE_V216), },
8422 { ATTR_GUID(MF_MT_SUBTYPE, MEDIASUBTYPE_V410), },
8423 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV11), },
8425 static const media_type_desc expect_available_common =
8427 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
8428 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
8429 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
8432 static const MFVideoArea actual_aperture = {.Area={82,84}};
8433 static const DWORD actual_width = 96, actual_height = 96;
8434 const struct attribute_desc input_type_desc[] =
8436 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
8437 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12),
8438 ATTR_BLOB(MF_MT_MINIMUM_DISPLAY_APERTURE, &actual_aperture, 16),
8439 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
8440 {0},
8442 const struct attribute_desc output_type_desc[] =
8444 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
8445 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32),
8446 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
8447 {0},
8450 MFT_REGISTER_TYPE_INFO output_type = {MFMediaType_Video, MFVideoFormat_NV12};
8451 MFT_REGISTER_TYPE_INFO input_type = {MFMediaType_Video, MFVideoFormat_I420};
8452 ULONG nv12frame_data_len, rgb32_data_len;
8453 const BYTE *nv12frame_data, *rgb32_data;
8454 MFT_OUTPUT_STREAM_INFO output_info;
8455 MFT_INPUT_STREAM_INFO input_info;
8456 MFT_OUTPUT_DATA_BUFFER output;
8457 WCHAR output_path[MAX_PATH];
8458 IMFMediaType *media_type;
8459 LONGLONG time, duration;
8460 IMFTransform *transform;
8461 DWORD length, status;
8462 HANDLE output_file;
8463 IMFSample *sample;
8464 HRSRC resource;
8465 GUID class_id;
8466 ULONG i, ret;
8467 HRESULT hr;
8469 hr = CoInitialize(NULL);
8470 ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
8472 if (!create_transform(MFT_CATEGORY_VIDEO_EFFECT, &input_type, &output_type, L"Color Converter MFT", &MFMediaType_Video,
8473 transform_inputs, ARRAY_SIZE(transform_inputs), transform_outputs, ARRAY_SIZE(transform_outputs),
8474 &transform, &CLSID_CColorConvertDMO, &class_id))
8475 goto failed;
8477 check_dmo(&CLSID_CColorConvertDMO, L"Color Converter DMO", &MEDIATYPE_Video, dmo_inputs, ARRAY_SIZE(dmo_inputs),
8478 dmo_outputs, ARRAY_SIZE(dmo_outputs));
8480 check_interface(transform, &IID_IMFTransform, TRUE);
8481 check_interface(transform, &IID_IMediaObject, TRUE);
8482 check_interface(transform, &IID_IPropertyStore, TRUE);
8483 todo_wine
8484 check_interface(transform, &IID_IMFRealTimeClient, TRUE);
8485 /* check_interface(transform, &IID_IWMColorConvProps, TRUE); */
8487 /* check default media types */
8489 hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info);
8490 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetInputStreamInfo returned %#lx\n", hr);
8491 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
8492 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetOutputStreamInfo returned %#lx\n", hr);
8494 i = -1;
8495 while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, ++i, &media_type)))
8497 winetest_push_context("out %lu", i);
8498 ok(hr == S_OK, "GetOutputAvailableType returned %#lx\n", hr);
8499 check_media_type(media_type, expect_available_common, -1);
8500 check_media_type(media_type, expect_available_outputs[i], -1);
8501 ret = IMFMediaType_Release(media_type);
8502 ok(ret == 0, "Release returned %lu\n", ret);
8503 winetest_pop_context();
8505 ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
8506 ok(i == 16, "%lu output media types\n", i);
8508 i = -1;
8509 while (SUCCEEDED(hr = IMFTransform_GetInputAvailableType(transform, 0, ++i, &media_type)))
8511 winetest_push_context("in %lu", i);
8512 ok(hr == S_OK, "GetInputAvailableType returned %#lx\n", hr);
8513 check_media_type(media_type, expect_available_common, -1);
8514 check_media_type(media_type, expect_available_inputs[i], -1);
8515 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
8516 if (i == 12)
8518 todo_wine
8519 ok(hr == MF_E_INVALIDMEDIATYPE, "SetInputType returned %#lx.\n", hr);
8521 else
8522 ok(hr == E_INVALIDARG, "SetInputType returned %#lx.\n", hr);
8523 ret = IMFMediaType_Release(media_type);
8524 ok(ret == 0, "Release returned %lu\n", ret);
8525 winetest_pop_context();
8527 ok(hr == MF_E_NO_MORE_TYPES, "GetInputAvailableType returned %#lx\n", hr);
8528 ok(i == 20, "%lu input media types\n", i);
8530 /* check required output media type attributes */
8532 hr = MFCreateMediaType(&media_type);
8533 ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr);
8534 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
8535 ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetOutputType returned %#lx.\n", hr);
8536 init_media_type(media_type, output_type_desc, 1);
8537 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
8538 ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetOutputType returned %#lx.\n", hr);
8539 init_media_type(media_type, output_type_desc, 2);
8540 for (i = 2; i < ARRAY_SIZE(output_type_desc) - 1; ++i)
8542 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
8543 ok(hr == E_INVALIDARG, "SetOutputType returned %#lx.\n", hr);
8544 init_media_type(media_type, output_type_desc, i + 1);
8546 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
8547 ok(hr == S_OK, "SetOutputType returned %#lx.\n", hr);
8548 ret = IMFMediaType_Release(media_type);
8549 ok(ret == 0, "Release returned %lu\n", ret);
8551 /* check required input media type attributes */
8553 hr = MFCreateMediaType(&media_type);
8554 ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr);
8555 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
8556 ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetInputType returned %#lx.\n", hr);
8557 init_media_type(media_type, input_type_desc, 1);
8558 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
8559 ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetInputType returned %#lx.\n", hr);
8560 init_media_type(media_type, input_type_desc, 2);
8561 for (i = 2; i < ARRAY_SIZE(input_type_desc) - 1; ++i)
8563 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
8564 ok(hr == E_INVALIDARG, "SetInputType returned %#lx.\n", hr);
8565 init_media_type(media_type, input_type_desc, i + 1);
8567 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
8568 ok(hr == S_OK, "SetInputType returned %#lx.\n", hr);
8569 ret = IMFMediaType_Release(media_type);
8570 ok(ret == 0, "Release returned %lu\n", ret);
8572 memset(&input_info, 0xcd, sizeof(input_info));
8573 hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info);
8574 ok(hr == S_OK, "GetInputStreamInfo returned %#lx\n", hr);
8575 ok(input_info.hnsMaxLatency == 0, "got hnsMaxLatency %s\n", wine_dbgstr_longlong(input_info.hnsMaxLatency));
8576 ok(input_info.dwFlags == 0, "got dwFlags %#lx\n", input_info.dwFlags);
8577 ok(input_info.cbSize == actual_width * actual_height * 3 / 2, "got cbSize %#lx\n", input_info.cbSize);
8578 ok(input_info.cbMaxLookahead == 0, "got cbMaxLookahead %#lx\n", input_info.cbMaxLookahead);
8579 ok(input_info.cbAlignment == 1, "got cbAlignment %#lx\n", input_info.cbAlignment);
8581 memset(&output_info, 0xcd, sizeof(output_info));
8582 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
8583 ok(hr == S_OK, "GetOutputStreamInfo returned %#lx\n", hr);
8584 ok(output_info.dwFlags == 0, "got dwFlags %#lx\n", output_info.dwFlags);
8585 ok(output_info.cbSize == actual_width * actual_height * 4, "got cbSize %#lx\n", output_info.cbSize);
8586 ok(output_info.cbAlignment == 1, "got cbAlignment %#lx\n", output_info.cbAlignment);
8588 resource = FindResourceW(NULL, L"nv12frame.bin", (const WCHAR *)RT_RCDATA);
8589 ok(resource != 0, "FindResourceW failed, error %lu\n", GetLastError());
8590 nv12frame_data = LockResource(LoadResource(GetModuleHandleW(NULL), resource));
8591 nv12frame_data_len = SizeofResource(GetModuleHandleW(NULL), resource);
8592 ok(nv12frame_data_len == 13824, "got length %lu\n", nv12frame_data_len);
8594 sample = create_sample(nv12frame_data, nv12frame_data_len);
8595 hr = IMFSample_SetSampleTime(sample, 0);
8596 ok(hr == S_OK, "SetSampleTime returned %#lx\n", hr);
8597 hr = IMFSample_SetSampleDuration(sample, 10000000);
8598 ok(hr == S_OK, "SetSampleDuration returned %#lx\n", hr);
8599 hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
8600 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
8601 hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
8602 ok(hr == MF_E_NOTACCEPTING, "ProcessInput returned %#lx\n", hr);
8603 hr = IMFTransform_ProcessMessage(transform, MFT_MESSAGE_COMMAND_DRAIN, 0);
8604 ok(hr == S_OK, "ProcessMessage returned %#lx\n", hr);
8605 ret = IMFSample_Release(sample);
8606 ok(ret <= 1, "Release returned %ld\n", ret);
8608 resource = FindResourceW(NULL, L"rgb32frame.bin", (const WCHAR *)RT_RCDATA);
8609 ok(resource != 0, "FindResourceW failed, error %lu\n", GetLastError());
8610 rgb32_data = LockResource(LoadResource(GetModuleHandleW(NULL), resource));
8611 rgb32_data_len = SizeofResource(GetModuleHandleW(NULL), resource);
8612 ok(rgb32_data_len == output_info.cbSize, "got length %lu\n", rgb32_data_len);
8614 /* and generate a new one as well in a temporary directory */
8615 GetTempPathW(ARRAY_SIZE(output_path), output_path);
8616 lstrcatW(output_path, L"rgb32frame.bin");
8617 output_file = CreateFileW(output_path, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
8618 ok(output_file != INVALID_HANDLE_VALUE, "CreateFileW failed, error %lu\n", GetLastError());
8620 status = 0xdeadbeef;
8621 sample = create_sample(NULL, output_info.cbSize);
8622 memset(&output, 0, sizeof(output));
8623 output.pSample = sample;
8624 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
8625 ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr);
8626 ok(output.pSample == sample, "got pSample %p\n", output.pSample);
8627 ok(output.dwStatus == 0 || broken(output.dwStatus == 6) /* win7 */, "got dwStatus %#lx\n", output.dwStatus);
8628 ok(status == 0, "got status %#lx\n", status);
8630 hr = IMFSample_GetSampleTime(sample, &time);
8631 ok(hr == S_OK, "GetSampleTime returned %#lx\n", hr);
8632 ok(time == 0, "got time %I64d\n", time);
8633 hr = IMFSample_GetSampleDuration(sample, &duration);
8634 ok(hr == S_OK, "GetSampleDuration returned %#lx\n", hr);
8635 ok(duration == 10000000, "got duration %I64d\n", duration);
8636 hr = IMFSample_GetTotalLength(sample, &length);
8637 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
8638 ok(length == output_info.cbSize, "got length %lu\n", length);
8639 check_sample_rgb32(sample, rgb32_data, output_file);
8640 rgb32_data_len -= output_info.cbSize;
8641 rgb32_data += output_info.cbSize;
8643 trace("created %s\n", debugstr_w(output_path));
8644 CloseHandle(output_file);
8646 ret = IMFSample_Release(sample);
8647 ok(ret == 0, "Release returned %lu\n", ret);
8649 status = 0xdeadbeef;
8650 sample = create_sample(NULL, output_info.cbSize);
8651 memset(&output, 0, sizeof(output));
8652 output.pSample = sample;
8653 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
8654 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
8655 ok(output.pSample == sample, "got pSample %p\n", output.pSample);
8656 ok(output.dwStatus == 0, "got dwStatus %#lx\n", output.dwStatus);
8657 ok(status == 0, "got status %#lx\n", status);
8658 hr = IMFSample_GetTotalLength(sample, &length);
8659 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
8660 ok(length == 0, "got length %lu\n", length);
8661 ret = IMFSample_Release(sample);
8662 ok(ret == 0, "Release returned %lu\n", ret);
8664 ret = IMFTransform_Release(transform);
8665 ok(ret == 0, "Release returned %ld\n", ret);
8667 failed:
8668 CoUninitialize();
8672 START_TEST(mf)
8674 init_functions();
8676 if (is_vista())
8678 win_skip("Skipping tests on Vista.\n");
8679 return;
8682 test_video_processor();
8683 test_topology();
8684 test_topology_tee_node();
8685 test_topology_loader();
8686 test_topology_loader_evr();
8687 test_MFGetService();
8688 test_sequencer_source();
8689 test_media_session();
8690 test_media_session_rate_control();
8691 test_MFShutdownObject();
8692 test_presentation_clock();
8693 test_sample_grabber();
8694 test_sample_grabber_is_mediatype_supported();
8695 test_quality_manager();
8696 test_sar();
8697 test_evr();
8698 test_MFCreateSimpleTypeHandler();
8699 test_MFGetSupportedMimeTypes();
8700 test_MFGetSupportedSchemes();
8701 test_sample_copier();
8702 test_sample_copier_output_processing();
8703 test_MFGetTopoNodeCurrentType();
8704 test_MFRequireProtectedEnvironment();
8705 test_wma_encoder();
8706 test_wma_decoder();
8707 test_h264_decoder();
8708 test_audio_convert();
8709 test_color_convert();