mf/tests: Add more topology loader media types tests.
[wine.git] / dlls / mf / tests / mf.c
bloba7ae8d6476bcb6b0e8e5a76b8d9dae45af3e80b9
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, 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 (source)
2016 hr = IMFTopologyNode_SetUnknown(node, &MF_TOPONODE_SOURCE, (IUnknown *)source);
2017 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2020 if (current_desc)
2022 IMFMediaTypeHandler *handler;
2023 IMFMediaType *type;
2025 hr = MFCreateMediaType(&type);
2026 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2027 init_media_type(type, *current_desc, -1);
2029 hr = IMFStreamDescriptor_GetMediaTypeHandler(sd, &handler);
2030 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2031 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, type);
2032 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2034 IMFMediaTypeHandler_Release(handler);
2035 IMFMediaType_Release(type);
2038 IMFStreamDescriptor_Release(sd);
2041 static void init_sink_node(IMFActivate *sink_activate, MF_CONNECT_METHOD method, IMFTopologyNode *node)
2043 IMFStreamSink *stream_sink;
2044 IMFMediaSink *sink;
2045 HRESULT hr;
2047 hr = IMFTopologyNode_DeleteAllItems(node);
2048 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2050 hr = IMFActivate_ActivateObject(sink_activate, &IID_IMFMediaSink, (void **)&sink);
2051 ok(hr == S_OK, "Failed to activate, hr %#lx.\n", hr);
2053 hr = IMFMediaSink_GetStreamSinkByIndex(sink, 0, &stream_sink);
2054 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2056 IMFMediaSink_Release(sink);
2058 hr = IMFTopologyNode_SetObject(node, (IUnknown *)stream_sink);
2059 ok(hr == S_OK, "Failed to set object, hr %#lx.\n", hr);
2061 IMFStreamSink_Release(stream_sink);
2063 hr = IMFTopologyNode_SetUINT32(node, &MF_TOPONODE_CONNECT_METHOD, method);
2064 ok(hr == S_OK, "Failed to set connect method, hr %#lx.\n", hr);
2067 enum loader_test_flags
2069 LOADER_EXPECTED_DECODER = 0x1,
2070 LOADER_EXPECTED_CONVERTER = 0x2,
2071 LOADER_TODO = 0x4,
2072 LOADER_NEEDS_VIDEO_PROCESSOR = 0x8,
2073 LOADER_SET_ENUMERATE_SOURCE_TYPES = 0x10,
2076 static void test_topology_loader(void)
2078 static const media_type_desc audio_pcm_44100 =
2080 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
2081 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
2082 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 1),
2083 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100),
2084 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 44100),
2085 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 1),
2086 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 8),
2088 static const media_type_desc audio_pcm_48000 =
2090 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
2091 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
2092 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 1),
2093 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 48000),
2094 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 48000),
2095 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 1),
2096 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 8),
2098 static const media_type_desc audio_mp3_44100 =
2100 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
2101 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_MP3),
2102 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
2103 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100),
2104 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 16000),
2105 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 1),
2107 static const media_type_desc audio_pcm_44100_incomplete =
2109 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
2110 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
2111 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 1),
2112 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100),
2113 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 1),
2114 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 8),
2117 const struct loader_test
2119 const media_type_desc *input_type;
2120 const media_type_desc *output_type;
2121 const media_type_desc *current_input;
2122 MF_CONNECT_METHOD method;
2123 HRESULT expected_result;
2124 unsigned int flags;
2126 loader_tests[] =
2129 /* PCM -> PCM, same enumerated type, no current type */
2130 .input_type = &audio_pcm_44100, .output_type = &audio_pcm_44100, .method = MF_CONNECT_DIRECT,
2131 .expected_result = S_OK,
2132 .flags = LOADER_TODO,
2135 /* PCM -> PCM, same enumerated type, incomplete current type */
2136 .input_type = &audio_pcm_44100, .output_type = &audio_pcm_44100, .method = MF_CONNECT_DIRECT,
2137 .current_input = &audio_pcm_44100_incomplete,
2138 .expected_result = MF_E_INVALIDMEDIATYPE,
2139 .flags = LOADER_TODO,
2142 /* PCM -> PCM, same enumerated bps, different current bps */
2143 .input_type = &audio_pcm_48000, .output_type = &audio_pcm_48000, .method = MF_CONNECT_DIRECT,
2144 .current_input = &audio_pcm_44100,
2145 .expected_result = MF_E_INVALIDMEDIATYPE,
2148 /* PCM -> PCM, same enumerated bps, different current bps, force enumerate */
2149 .input_type = &audio_pcm_48000, .output_type = &audio_pcm_48000, .method = MF_CONNECT_DIRECT,
2150 .current_input = &audio_pcm_44100,
2151 .expected_result = S_OK,
2152 .flags = LOADER_SET_ENUMERATE_SOURCE_TYPES,
2156 /* PCM -> PCM, incomplete enumerated type, same current type */
2157 .input_type = &audio_pcm_44100_incomplete, .output_type = &audio_pcm_44100, .method = MF_CONNECT_DIRECT,
2158 .current_input = &audio_pcm_44100,
2159 .expected_result = S_OK,
2162 /* PCM -> PCM, incomplete enumerated type, same current type, force enumerate */
2163 .input_type = &audio_pcm_44100_incomplete, .output_type = &audio_pcm_44100, .method = MF_CONNECT_DIRECT,
2164 .current_input = &audio_pcm_44100,
2165 .expected_result = MF_E_NO_MORE_TYPES,
2166 .flags = LOADER_SET_ENUMERATE_SOURCE_TYPES | LOADER_TODO,
2170 /* PCM -> PCM, different enumerated bps, no current type */
2171 .input_type = &audio_pcm_44100, .output_type = &audio_pcm_48000, .method = MF_CONNECT_DIRECT,
2172 .expected_result = MF_E_INVALIDMEDIATYPE,
2173 .flags = LOADER_TODO,
2176 /* PCM -> PCM, different enumerated bps, same current bps */
2177 .input_type = &audio_pcm_44100, .output_type = &audio_pcm_48000, .method = MF_CONNECT_DIRECT,
2178 .current_input = &audio_pcm_48000,
2179 .expected_result = S_OK,
2182 /* PCM -> PCM, different enumerated bps, same current bps, force enumerate */
2183 .input_type = &audio_pcm_44100, .output_type = &audio_pcm_48000, .method = MF_CONNECT_DIRECT,
2184 .current_input = &audio_pcm_48000,
2185 .expected_result = MF_E_NO_MORE_TYPES,
2186 .flags = LOADER_SET_ENUMERATE_SOURCE_TYPES,
2189 /* PCM -> PCM, different enumerated bps, no current type, allow converter */
2190 .input_type = &audio_pcm_44100, .output_type = &audio_pcm_48000, .method = MF_CONNECT_ALLOW_CONVERTER,
2191 .expected_result = S_OK,
2192 .flags = LOADER_NEEDS_VIDEO_PROCESSOR | LOADER_EXPECTED_CONVERTER | LOADER_TODO,
2195 /* PCM -> PCM, different enumerated bps, no current type, allow decoder */
2196 .input_type = &audio_pcm_44100, .output_type = &audio_pcm_48000, .method = MF_CONNECT_ALLOW_DECODER,
2197 .expected_result = S_OK,
2198 .flags = LOADER_NEEDS_VIDEO_PROCESSOR | LOADER_EXPECTED_CONVERTER | LOADER_TODO,
2202 /* MP3 -> PCM */
2203 .input_type = &audio_mp3_44100, .output_type = &audio_pcm_44100, .method = MF_CONNECT_DIRECT,
2204 .current_input = &audio_mp3_44100,
2205 .expected_result = MF_E_INVALIDMEDIATYPE,
2208 /* MP3 -> PCM, force enumerate */
2209 .input_type = &audio_mp3_44100, .output_type = &audio_pcm_44100, .method = MF_CONNECT_DIRECT,
2210 .current_input = &audio_mp3_44100,
2211 .expected_result = MF_E_NO_MORE_TYPES,
2212 .flags = LOADER_SET_ENUMERATE_SOURCE_TYPES,
2215 /* MP3 -> PCM */
2216 .input_type = &audio_mp3_44100, .output_type = &audio_pcm_44100, .method = MF_CONNECT_ALLOW_CONVERTER,
2217 .current_input = &audio_mp3_44100,
2218 .expected_result = MF_E_TRANSFORM_NOT_POSSIBLE_FOR_CURRENT_MEDIATYPE_COMBINATION,
2219 .flags = LOADER_NEEDS_VIDEO_PROCESSOR | LOADER_TODO,
2222 /* MP3 -> PCM */
2223 .input_type = &audio_mp3_44100, .output_type = &audio_pcm_44100, .method = MF_CONNECT_ALLOW_DECODER,
2224 .current_input = &audio_mp3_44100,
2225 .expected_result = S_OK,
2226 .flags = LOADER_EXPECTED_DECODER | LOADER_TODO,
2230 IMFSampleGrabberSinkCallback test_grabber_callback = { &test_grabber_callback_vtbl };
2231 IMFTopologyNode *src_node, *sink_node, *src_node2, *sink_node2, *mft_node;
2232 IMFTopology *topology, *topology2, *full_topology;
2233 IMFMediaType *media_type, *input_type, *output_type;
2234 IMFPresentationDescriptor *pd;
2235 unsigned int i, count, value;
2236 IMFActivate *sink_activate;
2237 MF_TOPOLOGY_TYPE node_type;
2238 IMFStreamDescriptor *sd;
2239 IMFTransform *transform;
2240 IMFMediaSource *source;
2241 IMFTopoLoader *loader;
2242 IUnknown *node_object;
2243 WORD node_count;
2244 TOPOID node_id;
2245 DWORD index;
2246 HRESULT hr;
2247 BOOL ret;
2248 LONG ref;
2250 hr = MFStartup(MF_VERSION, MFSTARTUP_FULL);
2251 ok(hr == S_OK, "Startup failure, hr %#lx.\n", hr);
2253 hr = MFCreateTopoLoader(NULL);
2254 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
2256 hr = MFCreateTopoLoader(&loader);
2257 ok(hr == S_OK, "Failed to create topology loader, hr %#lx.\n", hr);
2259 hr = MFCreateTopology(&topology);
2260 ok(hr == S_OK, "Failed to create topology, hr %#lx.\n", hr);
2262 /* Empty topology */
2263 hr = IMFTopoLoader_Load(loader, topology, &full_topology, NULL);
2264 todo_wine_if(hr == S_OK)
2265 ok(hr == MF_E_TOPO_UNSUPPORTED, "Unexpected hr %#lx.\n", hr);
2266 if (hr == S_OK) IMFTopology_Release(full_topology);
2268 /* Add source node. */
2269 hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &src_node);
2270 ok(hr == S_OK, "Failed to create topology node, hr %#lx.\n", hr);
2272 /* When a decoder is involved, windows requires this attribute to be present */
2273 source = create_test_source();
2275 hr = IMFTopologyNode_SetUnknown(src_node, &MF_TOPONODE_SOURCE, (IUnknown *)source);
2276 ok(hr == S_OK, "Failed to set node source, hr %#lx.\n", hr);
2278 hr = MFCreateMediaType(&media_type);
2279 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
2281 hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio);
2282 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
2283 hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFAudioFormat_PCM);
2284 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
2286 hr = MFCreateStreamDescriptor(0, 1, &media_type, &sd);
2287 ok(hr == S_OK, "Failed to create stream descriptor, hr %#lx.\n", hr);
2289 hr = IMFTopologyNode_SetUnknown(src_node, &MF_TOPONODE_STREAM_DESCRIPTOR, (IUnknown *)sd);
2290 ok(hr == S_OK, "Failed to set node sd, hr %#lx.\n", hr);
2292 hr = MFCreatePresentationDescriptor(1, &sd, &pd);
2293 ok(hr == S_OK, "Failed to create presentation descriptor, hr %#lx.\n", hr);
2295 hr = IMFTopologyNode_SetUnknown(src_node, &MF_TOPONODE_PRESENTATION_DESCRIPTOR, (IUnknown *)pd);
2296 ok(hr == S_OK, "Failed to set node pd, hr %#lx.\n", hr);
2298 IMFMediaType_Release(media_type);
2300 hr = IMFTopology_AddNode(topology, src_node);
2301 ok(hr == S_OK, "Failed to add a node, hr %#lx.\n", hr);
2303 /* Source node only. */
2304 hr = IMFTopoLoader_Load(loader, topology, &full_topology, NULL);
2305 todo_wine_if(hr == E_INVALIDARG)
2306 ok(hr == MF_E_TOPO_UNSUPPORTED, "Unexpected hr %#lx.\n", hr);
2308 hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, &sink_node);
2309 ok(hr == S_OK, "Failed to create output node, hr %#lx.\n", hr);
2311 hr = MFCreateMediaType(&media_type);
2312 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
2314 hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio);
2315 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
2316 hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFAudioFormat_PCM);
2317 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
2319 hr = MFCreateSampleGrabberSinkActivate(media_type, &test_grabber_callback, &sink_activate);
2320 ok(hr == S_OK, "Failed to create grabber sink, hr %#lx.\n", hr);
2322 hr = IMFTopologyNode_SetObject(sink_node, (IUnknown *)sink_activate);
2323 ok(hr == S_OK, "Failed to set object, hr %#lx.\n", hr);
2325 IMFMediaType_Release(media_type);
2327 hr = IMFTopology_AddNode(topology, sink_node);
2328 ok(hr == S_OK, "Failed to add sink node, hr %#lx.\n", hr);
2330 hr = IMFTopoLoader_Load(loader, topology, &full_topology, NULL);
2331 todo_wine_if(hr == MF_E_TOPO_SINK_ACTIVATES_UNSUPPORTED)
2332 ok(hr == MF_E_TOPO_UNSUPPORTED, "Unexpected hr %#lx.\n", hr);
2334 hr = IMFTopologyNode_ConnectOutput(src_node, 0, sink_node, 0);
2335 ok(hr == S_OK, "Failed to connect nodes, hr %#lx.\n", hr);
2337 /* Sink was not resolved. */
2338 hr = IMFTopoLoader_Load(loader, topology, &full_topology, NULL);
2339 ok(hr == MF_E_TOPO_SINK_ACTIVATES_UNSUPPORTED, "Unexpected hr %#lx.\n", hr);
2341 hr = MFCreateMediaType(&input_type);
2342 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
2344 hr = MFCreateMediaType(&output_type);
2345 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
2347 for (i = 0; i < ARRAY_SIZE(loader_tests); ++i)
2349 const struct loader_test *test = &loader_tests[i];
2351 winetest_push_context("%u", i);
2353 init_media_type(input_type, *test->input_type, -1);
2354 init_media_type(output_type, *test->output_type, -1);
2356 hr = MFCreateSampleGrabberSinkActivate(output_type, &test_grabber_callback, &sink_activate);
2357 ok(hr == S_OK, "Failed to create grabber sink, hr %#lx.\n", hr);
2359 init_source_node(source, src_node, 1, &input_type, test->current_input);
2360 init_sink_node(sink_activate, test->method, sink_node);
2362 hr = IMFTopology_GetCount(topology, &count);
2363 ok(hr == S_OK, "Failed to get attribute count, hr %#lx.\n", hr);
2364 ok(!count, "Unexpected count %u.\n", count);
2366 if (test->flags & LOADER_SET_ENUMERATE_SOURCE_TYPES)
2367 IMFTopology_SetUINT32(topology, &MF_TOPOLOGY_ENUMERATE_SOURCE_TYPES, 1);
2368 hr = IMFTopoLoader_Load(loader, topology, &full_topology, NULL);
2369 IMFTopology_DeleteItem(topology, &MF_TOPOLOGY_ENUMERATE_SOURCE_TYPES);
2371 if (test->flags & LOADER_NEEDS_VIDEO_PROCESSOR && !has_video_processor)
2372 ok(hr == MF_E_INVALIDMEDIATYPE || hr == MF_E_TOPO_CODEC_NOT_FOUND,
2373 "Unexpected hr %#lx\n", hr);
2374 else
2376 todo_wine_if(test->flags & LOADER_TODO)
2377 ok(hr == test->expected_result, "Unexpected hr %#lx\n", hr);
2378 ok(full_topology != topology, "Unexpected instance.\n");
2381 if (test->expected_result != hr)
2383 if (hr != S_OK) ref = 0;
2384 else ref = IMFTopology_Release(full_topology);
2385 ok(ref == 0, "Release returned %ld\n", ref);
2387 else if (test->expected_result == S_OK)
2389 hr = IMFTopology_GetCount(full_topology, &count);
2390 ok(hr == S_OK, "Failed to get attribute count, hr %#lx.\n", hr);
2391 todo_wine
2392 ok(count == (test->flags & LOADER_SET_ENUMERATE_SOURCE_TYPES ? 2 : 1),
2393 "Unexpected count %u.\n", count);
2395 value = 0xdeadbeef;
2396 hr = IMFTopology_GetUINT32(full_topology, &MF_TOPOLOGY_RESOLUTION_STATUS, &value);
2397 todo_wine {
2398 ok(hr == S_OK, "Failed to get attribute, hr %#lx.\n", hr);
2399 ok(value == MF_TOPOLOGY_RESOLUTION_SUCCEEDED, "Unexpected value %#x.\n", value);
2401 count = 2;
2402 if (test->flags & LOADER_EXPECTED_DECODER)
2403 count++;
2404 if (test->flags & LOADER_EXPECTED_CONVERTER)
2405 count++;
2407 hr = IMFTopology_GetNodeCount(full_topology, &node_count);
2408 ok(hr == S_OK, "Failed to get node count, hr %#lx.\n", hr);
2409 todo_wine_if(test->flags & (LOADER_EXPECTED_CONVERTER | LOADER_EXPECTED_DECODER))
2410 ok(node_count == count, "Unexpected node count %u.\n", node_count);
2412 hr = IMFTopologyNode_GetTopoNodeID(src_node, &node_id);
2413 ok(hr == S_OK, "Failed to get source node id, hr %#lx.\n", hr);
2415 hr = IMFTopology_GetNodeByID(full_topology, node_id, &src_node2);
2416 ok(hr == S_OK, "Failed to get source in resolved topology, hr %#lx.\n", hr);
2418 hr = IMFTopologyNode_GetTopoNodeID(sink_node, &node_id);
2419 ok(hr == S_OK, "Failed to get sink node id, hr %#lx.\n", hr);
2421 hr = IMFTopology_GetNodeByID(full_topology, node_id, &sink_node2);
2422 ok(hr == S_OK, "Failed to get sink in resolved topology, hr %#lx.\n", hr);
2424 if (test->flags & (LOADER_EXPECTED_DECODER | LOADER_EXPECTED_CONVERTER) && strcmp(winetest_platform, "wine"))
2426 hr = IMFTopologyNode_GetOutput(src_node2, 0, &mft_node, &index);
2427 ok(hr == S_OK, "Failed to get transform node in resolved topology, hr %#lx.\n", hr);
2428 ok(!index, "Unexpected stream index %lu.\n", index);
2430 hr = IMFTopologyNode_GetNodeType(mft_node, &node_type);
2431 ok(hr == S_OK, "Failed to get transform node type in resolved topology, hr %#lx.\n", hr);
2432 ok(node_type == MF_TOPOLOGY_TRANSFORM_NODE, "Unexpected node type %u.\n", node_type);
2434 hr = IMFTopologyNode_GetObject(mft_node, &node_object);
2435 ok(hr == S_OK, "Failed to get object of transform node, hr %#lx.\n", hr);
2437 if (test->flags & LOADER_EXPECTED_DECODER)
2439 value = 0;
2440 hr = IMFTopologyNode_GetUINT32(mft_node, &MF_TOPONODE_DECODER, &value);
2441 ok(hr == S_OK, "Failed to get attribute, hr %#lx.\n", hr);
2442 ok(value == 1, "Unexpected value.\n");
2445 hr = IMFTopologyNode_GetItem(mft_node, &MF_TOPONODE_TRANSFORM_OBJECTID, NULL);
2446 ok(hr == S_OK, "Failed to get attribute, hr %#lx.\n", hr);
2448 hr = IUnknown_QueryInterface(node_object, &IID_IMFTransform, (void **)&transform);
2449 ok(hr == S_OK, "Failed to get IMFTransform from transform node's object, hr %#lx.\n", hr);
2450 IUnknown_Release(node_object);
2452 hr = IMFTransform_GetInputCurrentType(transform, 0, &media_type);
2453 ok(hr == S_OK, "Failed to get transform input type, hr %#lx.\n", hr);
2455 hr = IMFMediaType_Compare(input_type, (IMFAttributes *)media_type, MF_ATTRIBUTES_MATCH_OUR_ITEMS, &ret);
2456 ok(hr == S_OK, "Failed to compare media types, hr %#lx.\n", hr);
2457 ok(ret, "Input type of first transform doesn't match source node type.\n");
2459 IMFTopologyNode_Release(mft_node);
2460 IMFMediaType_Release(media_type);
2461 IMFTransform_Release(transform);
2463 hr = IMFTopologyNode_GetInput(sink_node2, 0, &mft_node, &index);
2464 ok(hr == S_OK, "Failed to get transform node in resolved topology, hr %#lx.\n", hr);
2465 ok(!index, "Unexpected stream index %lu.\n", index);
2467 hr = IMFTopologyNode_GetNodeType(mft_node, &node_type);
2468 ok(hr == S_OK, "Failed to get transform node type in resolved topology, hr %#lx.\n", hr);
2469 ok(node_type == MF_TOPOLOGY_TRANSFORM_NODE, "Unexpected node type %u.\n", node_type);
2471 hr = IMFTopologyNode_GetItem(mft_node, &MF_TOPONODE_TRANSFORM_OBJECTID, NULL);
2472 ok(hr == S_OK, "Failed to get attribute, hr %#lx.\n", hr);
2474 hr = IMFTopologyNode_GetObject(mft_node, &node_object);
2475 ok(hr == S_OK, "Failed to get object of transform node, hr %#lx.\n", hr);
2477 hr = IUnknown_QueryInterface(node_object, &IID_IMFTransform, (void**) &transform);
2478 ok(hr == S_OK, "Failed to get IMFTransform from transform node's object, hr %#lx.\n", hr);
2479 IUnknown_Release(node_object);
2481 hr = IMFTransform_GetOutputCurrentType(transform, 0, &media_type);
2482 ok(hr == S_OK, "Failed to get transform output type, hr %#lx.\n", hr);
2484 hr = IMFMediaType_Compare(output_type, (IMFAttributes *)media_type, MF_ATTRIBUTES_MATCH_OUR_ITEMS, &ret);
2485 ok(hr == S_OK, "Failed to compare media types, hr %#lx.\n", hr);
2486 ok(ret, "Output type of last transform doesn't match sink node type.\n");
2488 IMFTopologyNode_Release(mft_node);
2489 IMFMediaType_Release(media_type);
2490 IMFTransform_Release(transform);
2493 IMFTopologyNode_Release(src_node2);
2494 IMFTopologyNode_Release(sink_node2);
2496 hr = IMFTopology_SetUINT32(full_topology, &IID_IMFTopology, 123);
2497 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2498 hr = IMFTopoLoader_Load(loader, full_topology, &topology2, NULL);
2499 ok(hr == S_OK, "Failed to resolve topology, hr %#lx.\n", hr);
2500 ok(full_topology != topology2, "Unexpected instance.\n");
2501 hr = IMFTopology_GetUINT32(topology2, &IID_IMFTopology, &value);
2502 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2504 ref = IMFTopology_Release(topology2);
2505 ok(ref == 0, "Release returned %ld\n", ref);
2506 ref = IMFTopology_Release(full_topology);
2507 ok(ref == 0, "Release returned %ld\n", ref);
2510 hr = IMFTopology_GetCount(topology, &count);
2511 ok(hr == S_OK, "Failed to get attribute count, hr %#lx.\n", hr);
2512 ok(!count, "Unexpected count %u.\n", count);
2514 hr = IMFActivate_ShutdownObject(sink_activate);
2515 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2516 ref = IMFActivate_Release(sink_activate);
2517 ok(ref == 0, "Release returned %ld\n", ref);
2519 winetest_pop_context();
2522 ref = IMFTopology_Release(topology);
2523 ok(ref == 0, "Release returned %ld\n", ref);
2524 ref = IMFTopoLoader_Release(loader);
2525 ok(ref == 0, "Release returned %ld\n", ref);
2526 ref = IMFTopologyNode_Release(src_node);
2527 ok(ref == 0, "Release returned %ld\n", ref);
2528 ref = IMFTopologyNode_Release(sink_node);
2529 ok(ref == 0, "Release returned %ld\n", ref);
2531 ref = IMFMediaSource_Release(source);
2532 ok(ref == 0, "Release returned %ld\n", ref);
2534 ref = IMFPresentationDescriptor_Release(pd);
2535 ok(ref == 0, "Release returned %ld\n", ref);
2536 ref = IMFStreamDescriptor_Release(sd);
2537 ok(ref == 0, "Release returned %ld\n", ref);
2539 ref = IMFMediaType_Release(input_type);
2540 ok(ref == 0, "Release returned %ld\n", ref);
2541 /* FIXME: is native really leaking refs here, or are we? */
2542 ref = IMFMediaType_Release(output_type);
2543 todo_wine
2544 ok(ref != 0, "Release returned %ld\n", ref);
2546 hr = MFShutdown();
2547 ok(hr == S_OK, "Shutdown failure, hr %#lx.\n", hr);
2550 static void test_topology_loader_evr(void)
2552 static const media_type_desc media_type_desc =
2554 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
2555 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32),
2556 ATTR_RATIO(MF_MT_FRAME_SIZE, 640, 480),
2557 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE),
2558 {0},
2560 IMFTopologyNode *node, *source_node, *evr_node;
2561 IMFTopology *topology, *full_topology;
2562 IMFMediaTypeHandler *handler;
2563 unsigned int i, count, value;
2564 IMFStreamSink *stream_sink;
2565 IMFMediaType *media_type;
2566 IMFActivate *activate;
2567 IMFTopoLoader *loader;
2568 IMFMediaSink *sink;
2569 WORD node_count;
2570 UINT64 value64;
2571 HWND window;
2572 HRESULT hr;
2573 LONG ref;
2575 hr = CoInitialize(NULL);
2576 ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
2578 hr = MFCreateTopoLoader(&loader);
2579 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2581 /* Source node. */
2582 hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &source_node);
2583 ok(hr == S_OK, "Failed to create topology node, hr %#lx.\n", hr);
2585 hr = MFCreateMediaType(&media_type);
2586 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
2587 init_media_type(media_type, media_type_desc, -1);
2588 init_source_node(NULL, source_node, 1, &media_type, &media_type_desc);
2590 /* EVR sink node. */
2591 window = create_window();
2593 hr = MFCreateVideoRendererActivate(window, &activate);
2594 ok(hr == S_OK, "Failed to create activate object, hr %#lx.\n", hr);
2596 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink);
2597 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2599 hr = IMFMediaSink_GetStreamSinkById(sink, 0, &stream_sink);
2600 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2602 hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, &evr_node);
2603 ok(hr == S_OK, "Failed to create topology node, hr %#lx.\n", hr);
2605 hr = IMFTopologyNode_SetObject(evr_node, (IUnknown *)stream_sink);
2606 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2608 hr = IMFStreamSink_GetMediaTypeHandler(stream_sink, &handler);
2609 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2610 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, media_type);
2611 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2612 IMFMediaTypeHandler_Release(handler);
2614 IMFStreamSink_Release(stream_sink);
2616 hr = MFCreateTopology(&topology);
2617 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2619 hr = IMFTopology_AddNode(topology, source_node);
2620 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2621 hr = IMFTopology_AddNode(topology, evr_node);
2622 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2623 hr = IMFTopologyNode_ConnectOutput(source_node, 0, evr_node, 0);
2624 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2626 hr = IMFTopologyNode_SetUINT32(evr_node, &MF_TOPONODE_CONNECT_METHOD, MF_CONNECT_DIRECT);
2627 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2629 hr = IMFTopologyNode_GetCount(evr_node, &count);
2630 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2631 ok(count == 1, "Unexpected attribute count %u.\n", count);
2633 hr = IMFTopoLoader_Load(loader, topology, &full_topology, NULL);
2634 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2636 hr = IMFTopology_GetNodeCount(full_topology, &node_count);
2637 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2638 ok(node_count == 3, "Unexpected node count %u.\n", node_count);
2640 for (i = 0; i < node_count; ++i)
2642 MF_TOPOLOGY_TYPE node_type;
2644 hr = IMFTopology_GetNode(full_topology, i, &node);
2645 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2647 hr = IMFTopologyNode_GetNodeType(node, &node_type);
2648 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2650 if (node_type == MF_TOPOLOGY_OUTPUT_NODE)
2652 value = 1;
2653 hr = IMFTopologyNode_GetUINT32(node, &MF_TOPONODE_STREAMID, &value);
2654 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2655 ok(!value, "Unexpected stream id %u.\n", value);
2657 else if (node_type == MF_TOPOLOGY_SOURCESTREAM_NODE)
2659 value64 = 1;
2660 hr = IMFTopologyNode_GetUINT64(node, &MF_TOPONODE_MEDIASTART, &value64);
2661 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2662 ok(!value64, "Unexpected value.\n");
2665 IMFTopologyNode_Release(node);
2668 ref = IMFTopology_Release(full_topology);
2669 ok(ref == 0, "Release returned %ld\n", ref);
2670 ref = IMFTopoLoader_Release(loader);
2671 ok(ref == 0, "Release returned %ld\n", ref);
2672 ref = IMFTopology_Release(topology);
2673 ok(ref == 0, "Release returned %ld\n", ref);
2674 ref = IMFTopologyNode_Release(source_node);
2675 ok(ref == 0, "Release returned %ld\n", ref);
2676 ref = IMFTopologyNode_Release(evr_node);
2677 ok(ref == 0, "Release returned %ld\n", ref);
2679 hr = IMFActivate_ShutdownObject(activate);
2680 ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr);
2681 ref = IMFActivate_Release(activate);
2682 ok(ref == 0, "Release returned %ld\n", ref);
2683 ref = IMFMediaSink_Release(sink);
2684 ok(ref == 0, "Release returned %ld\n", ref);
2686 ref = IMFMediaType_Release(media_type);
2687 ok(ref == 0, "Release returned %ld\n", ref);
2689 DestroyWindow(window);
2691 CoUninitialize();
2694 static HRESULT WINAPI testshutdown_QueryInterface(IMFShutdown *iface, REFIID riid, void **obj)
2696 if (IsEqualIID(riid, &IID_IMFShutdown) ||
2697 IsEqualIID(riid, &IID_IUnknown))
2699 *obj = iface;
2700 IMFShutdown_AddRef(iface);
2701 return S_OK;
2704 *obj = NULL;
2705 return E_NOINTERFACE;
2708 static ULONG WINAPI testshutdown_AddRef(IMFShutdown *iface)
2710 return 2;
2713 static ULONG WINAPI testshutdown_Release(IMFShutdown *iface)
2715 return 1;
2718 static HRESULT WINAPI testshutdown_Shutdown(IMFShutdown *iface)
2720 return 0xdead;
2723 static HRESULT WINAPI testshutdown_GetShutdownStatus(IMFShutdown *iface, MFSHUTDOWN_STATUS *status)
2725 ok(0, "Unexpected call.\n");
2726 return E_NOTIMPL;
2729 static const IMFShutdownVtbl testshutdownvtbl =
2731 testshutdown_QueryInterface,
2732 testshutdown_AddRef,
2733 testshutdown_Release,
2734 testshutdown_Shutdown,
2735 testshutdown_GetShutdownStatus,
2738 static void test_MFShutdownObject(void)
2740 IMFShutdown testshutdown = { &testshutdownvtbl };
2741 IUnknown testshutdown2 = { &testservicevtbl };
2742 HRESULT hr;
2744 hr = MFShutdownObject(NULL);
2745 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2747 hr = MFShutdownObject((IUnknown *)&testshutdown);
2748 ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr);
2750 hr = MFShutdownObject(&testshutdown2);
2751 ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr);
2754 enum clock_action
2756 CLOCK_START,
2757 CLOCK_STOP,
2758 CLOCK_PAUSE,
2761 static HRESULT WINAPI test_clock_sink_QueryInterface(IMFClockStateSink *iface, REFIID riid, void **obj)
2763 if (IsEqualIID(riid, &IID_IMFClockStateSink) ||
2764 IsEqualIID(riid, &IID_IUnknown))
2766 *obj = iface;
2767 IMFClockStateSink_AddRef(iface);
2768 return S_OK;
2771 *obj = NULL;
2772 return E_NOINTERFACE;
2775 static ULONG WINAPI test_clock_sink_AddRef(IMFClockStateSink *iface)
2777 return 2;
2780 static ULONG WINAPI test_clock_sink_Release(IMFClockStateSink *iface)
2782 return 1;
2785 static HRESULT WINAPI test_clock_sink_OnClockStart(IMFClockStateSink *iface, MFTIME system_time, LONGLONG offset)
2787 return E_NOTIMPL;
2790 static HRESULT WINAPI test_clock_sink_OnClockStop(IMFClockStateSink *iface, MFTIME system_time)
2792 return E_NOTIMPL;
2795 static HRESULT WINAPI test_clock_sink_OnClockPause(IMFClockStateSink *iface, MFTIME system_time)
2797 return E_NOTIMPL;
2800 static HRESULT WINAPI test_clock_sink_OnClockRestart(IMFClockStateSink *iface, MFTIME system_time)
2802 return E_NOTIMPL;
2805 static HRESULT WINAPI test_clock_sink_OnClockSetRate(IMFClockStateSink *iface, MFTIME system_time, float rate)
2807 return E_NOTIMPL;
2810 static const IMFClockStateSinkVtbl test_clock_sink_vtbl =
2812 test_clock_sink_QueryInterface,
2813 test_clock_sink_AddRef,
2814 test_clock_sink_Release,
2815 test_clock_sink_OnClockStart,
2816 test_clock_sink_OnClockStop,
2817 test_clock_sink_OnClockPause,
2818 test_clock_sink_OnClockRestart,
2819 test_clock_sink_OnClockSetRate,
2822 static void test_presentation_clock(void)
2824 static const struct clock_state_test
2826 enum clock_action action;
2827 MFCLOCK_STATE clock_state;
2828 MFCLOCK_STATE source_state;
2829 HRESULT hr;
2831 clock_state_change[] =
2833 { CLOCK_STOP, MFCLOCK_STATE_STOPPED, MFCLOCK_STATE_INVALID },
2834 { CLOCK_PAUSE, MFCLOCK_STATE_STOPPED, MFCLOCK_STATE_INVALID, MF_E_INVALIDREQUEST },
2835 { CLOCK_STOP, MFCLOCK_STATE_STOPPED, MFCLOCK_STATE_INVALID, MF_E_CLOCK_STATE_ALREADY_SET },
2836 { CLOCK_START, MFCLOCK_STATE_RUNNING, MFCLOCK_STATE_RUNNING },
2837 { CLOCK_START, MFCLOCK_STATE_RUNNING, MFCLOCK_STATE_RUNNING },
2838 { CLOCK_PAUSE, MFCLOCK_STATE_PAUSED, MFCLOCK_STATE_PAUSED },
2839 { CLOCK_PAUSE, MFCLOCK_STATE_PAUSED, MFCLOCK_STATE_PAUSED, MF_E_CLOCK_STATE_ALREADY_SET },
2840 { CLOCK_STOP, MFCLOCK_STATE_STOPPED, MFCLOCK_STATE_STOPPED },
2841 { CLOCK_START, MFCLOCK_STATE_RUNNING, MFCLOCK_STATE_RUNNING },
2842 { CLOCK_STOP, MFCLOCK_STATE_STOPPED, MFCLOCK_STATE_STOPPED },
2843 { CLOCK_STOP, MFCLOCK_STATE_STOPPED, MFCLOCK_STATE_STOPPED, MF_E_CLOCK_STATE_ALREADY_SET },
2844 { CLOCK_PAUSE, MFCLOCK_STATE_STOPPED, MFCLOCK_STATE_STOPPED, MF_E_INVALIDREQUEST },
2845 { CLOCK_START, MFCLOCK_STATE_RUNNING, MFCLOCK_STATE_RUNNING },
2846 { CLOCK_PAUSE, MFCLOCK_STATE_PAUSED, MFCLOCK_STATE_PAUSED },
2847 { CLOCK_START, MFCLOCK_STATE_RUNNING, MFCLOCK_STATE_RUNNING },
2849 IMFClockStateSink test_sink = { &test_clock_sink_vtbl };
2850 IMFPresentationTimeSource *time_source;
2851 MFCLOCK_PROPERTIES props, props2;
2852 IMFRateControl *rate_control;
2853 IMFPresentationClock *clock;
2854 MFSHUTDOWN_STATUS status;
2855 IMFShutdown *shutdown;
2856 MFTIME systime, time;
2857 LONGLONG clock_time;
2858 MFCLOCK_STATE state;
2859 unsigned int i;
2860 DWORD value;
2861 float rate;
2862 HRESULT hr;
2863 BOOL thin;
2865 hr = MFStartup(MF_VERSION, MFSTARTUP_FULL);
2866 ok(hr == S_OK, "Failed to start up, hr %#lx.\n", hr);
2868 hr = MFCreatePresentationClock(&clock);
2869 ok(hr == S_OK, "Failed to create presentation clock, hr %#lx.\n", hr);
2871 check_interface(clock, &IID_IMFTimer, TRUE);
2872 check_interface(clock, &IID_IMFRateControl, TRUE);
2873 check_interface(clock, &IID_IMFPresentationClock, TRUE);
2874 check_interface(clock, &IID_IMFShutdown, TRUE);
2875 check_interface(clock, &IID_IMFClock, TRUE);
2877 hr = IMFPresentationClock_QueryInterface(clock, &IID_IMFRateControl, (void **)&rate_control);
2878 ok(hr == S_OK, "Failed to get rate control interface, hr %#lx.\n", hr);
2880 hr = IMFPresentationClock_GetTimeSource(clock, &time_source);
2881 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#lx.\n", hr);
2883 hr = IMFPresentationClock_GetTimeSource(clock, NULL);
2884 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
2886 hr = IMFPresentationClock_GetClockCharacteristics(clock, &value);
2887 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#lx.\n", hr);
2889 hr = IMFPresentationClock_GetClockCharacteristics(clock, NULL);
2890 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#lx.\n", hr);
2892 hr = IMFPresentationClock_GetTime(clock, &time);
2893 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#lx.\n", hr);
2895 hr = IMFPresentationClock_GetTime(clock, NULL);
2896 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
2898 value = 1;
2899 hr = IMFPresentationClock_GetContinuityKey(clock, &value);
2900 ok(hr == S_OK, "Failed to get continuity key, hr %#lx.\n", hr);
2901 ok(value == 0, "Unexpected value %lu.\n", value);
2903 hr = IMFPresentationClock_GetProperties(clock, &props);
2904 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#lx.\n", hr);
2906 hr = IMFPresentationClock_GetState(clock, 0, &state);
2907 ok(hr == S_OK, "Failed to get state, hr %#lx.\n", hr);
2908 ok(state == MFCLOCK_STATE_INVALID, "Unexpected state %d.\n", state);
2910 hr = IMFPresentationClock_GetCorrelatedTime(clock, 0, &clock_time, &systime);
2911 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#lx.\n", hr);
2913 hr = IMFPresentationClock_GetCorrelatedTime(clock, 0, NULL, &systime);
2914 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#lx.\n", hr);
2916 hr = IMFPresentationClock_GetCorrelatedTime(clock, 0, &time, NULL);
2917 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#lx.\n", hr);
2919 /* Sinks. */
2920 hr = IMFPresentationClock_AddClockStateSink(clock, NULL);
2921 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
2923 hr = IMFPresentationClock_AddClockStateSink(clock, &test_sink);
2924 ok(hr == S_OK, "Failed to add a sink, hr %#lx.\n", hr);
2926 hr = IMFPresentationClock_AddClockStateSink(clock, &test_sink);
2927 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
2929 hr = IMFPresentationClock_RemoveClockStateSink(clock, NULL);
2930 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
2932 hr = IMFPresentationClock_RemoveClockStateSink(clock, &test_sink);
2933 ok(hr == S_OK, "Failed to remove sink, hr %#lx.\n", hr);
2935 hr = IMFPresentationClock_RemoveClockStateSink(clock, &test_sink);
2936 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2938 /* State change commands, time source is not set yet. */
2939 hr = IMFPresentationClock_Start(clock, 0);
2940 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#lx.\n", hr);
2942 hr = IMFPresentationClock_Pause(clock);
2943 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#lx.\n", hr);
2945 hr = IMFPresentationClock_Stop(clock);
2946 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#lx.\n", hr);
2948 hr = IMFRateControl_SetRate(rate_control, FALSE, 0.0f);
2949 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#lx.\n", hr);
2951 /* Set default time source. */
2952 hr = MFCreateSystemTimeSource(&time_source);
2953 ok(hr == S_OK, "Failed to create time source, hr %#lx.\n", hr);
2955 hr = IMFPresentationTimeSource_GetClockCharacteristics(time_source, &value);
2956 ok(hr == S_OK, "Failed to get time source flags, hr %#lx.\n", hr);
2957 ok(value == (MFCLOCK_CHARACTERISTICS_FLAG_FREQUENCY_10MHZ | MFCLOCK_CHARACTERISTICS_FLAG_IS_SYSTEM_CLOCK),
2958 "Unexpected clock flags %#lx.\n", value);
2960 hr = IMFPresentationClock_SetTimeSource(clock, time_source);
2961 ok(hr == S_OK, "Failed to set time source, hr %#lx.\n", hr);
2963 hr = IMFPresentationTimeSource_GetProperties(time_source, &props2);
2964 ok(hr == S_OK, "Failed to get time source properties, hr %#lx.\n", hr);
2966 hr = IMFPresentationClock_GetClockCharacteristics(clock, &value);
2967 ok(hr == S_OK, "Failed to get clock flags, hr %#lx.\n", hr);
2968 ok(value == (MFCLOCK_CHARACTERISTICS_FLAG_FREQUENCY_10MHZ | MFCLOCK_CHARACTERISTICS_FLAG_IS_SYSTEM_CLOCK),
2969 "Unexpected clock flags %#lx.\n", value);
2971 hr = IMFPresentationClock_GetProperties(clock, &props);
2972 ok(hr == S_OK, "Failed to get clock properties, hr %#lx.\n", hr);
2973 ok(!memcmp(&props, &props2, sizeof(props)), "Unexpected clock properties.\n");
2975 /* Changing rate at initial state. */
2976 hr = IMFPresentationClock_GetState(clock, 0, &state);
2977 ok(hr == S_OK, "Failed to get clock state, hr %#lx.\n", hr);
2978 ok(state == MFCLOCK_STATE_INVALID, "Unexpected state %d.\n", state);
2980 hr = IMFRateControl_SetRate(rate_control, FALSE, 0.0f);
2981 ok(hr == S_OK, "Failed to set clock rate, hr %#lx.\n", hr);
2982 hr = IMFRateControl_GetRate(rate_control, &thin, &rate);
2983 ok(hr == S_OK, "Failed to get clock rate, hr %#lx.\n", hr);
2984 ok(rate == 0.0f, "Unexpected rate.\n");
2985 hr = IMFRateControl_SetRate(rate_control, FALSE, 1.0f);
2986 ok(hr == S_OK, "Failed to set clock rate, hr %#lx.\n", hr);
2988 /* State changes. */
2989 for (i = 0; i < ARRAY_SIZE(clock_state_change); ++i)
2991 switch (clock_state_change[i].action)
2993 case CLOCK_STOP:
2994 hr = IMFPresentationClock_Stop(clock);
2995 break;
2996 case CLOCK_PAUSE:
2997 hr = IMFPresentationClock_Pause(clock);
2998 break;
2999 case CLOCK_START:
3000 hr = IMFPresentationClock_Start(clock, 0);
3001 break;
3002 default:
3005 ok(hr == clock_state_change[i].hr, "%u: unexpected hr %#lx.\n", i, hr);
3007 hr = IMFPresentationTimeSource_GetState(time_source, 0, &state);
3008 ok(hr == S_OK, "%u: failed to get state, hr %#lx.\n", i, hr);
3009 ok(state == clock_state_change[i].source_state, "%u: unexpected state %d.\n", i, state);
3011 hr = IMFPresentationClock_GetState(clock, 0, &state);
3012 ok(hr == S_OK, "%u: failed to get state, hr %#lx.\n", i, hr);
3013 ok(state == clock_state_change[i].clock_state, "%u: unexpected state %d.\n", i, state);
3016 /* Clock time stamps. */
3017 hr = IMFPresentationClock_Start(clock, 10);
3018 ok(hr == S_OK, "Failed to start presentation clock, hr %#lx.\n", hr);
3020 hr = IMFPresentationClock_Pause(clock);
3021 ok(hr == S_OK, "Failed to pause presentation clock, hr %#lx.\n", hr);
3023 hr = IMFPresentationClock_GetTime(clock, &time);
3024 ok(hr == S_OK, "Failed to get clock time, hr %#lx.\n", hr);
3026 hr = IMFPresentationTimeSource_GetCorrelatedTime(time_source, 0, &clock_time, &systime);
3027 ok(hr == S_OK, "Failed to get time source time, hr %#lx.\n", hr);
3028 ok(time == clock_time, "Unexpected clock time.\n");
3030 hr = IMFPresentationClock_GetCorrelatedTime(clock, 0, &time, &systime);
3031 ok(hr == S_OK, "Failed to get clock time, hr %#lx.\n", hr);
3032 ok(time == clock_time, "Unexpected clock time.\n");
3034 IMFPresentationTimeSource_Release(time_source);
3036 hr = IMFRateControl_GetRate(rate_control, NULL, &rate);
3037 ok(hr == S_OK, "Failed to get clock rate, hr %#lx.\n", hr);
3039 hr = IMFRateControl_GetRate(rate_control, &thin, NULL);
3040 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
3042 hr = IMFRateControl_GetRate(rate_control, &thin, &rate);
3043 ok(hr == S_OK, "Failed to get clock rate, hr %#lx.\n", hr);
3044 ok(rate == 1.0f, "Unexpected rate.\n");
3045 ok(!thin, "Unexpected thinning.\n");
3047 hr = IMFPresentationClock_GetState(clock, 0, &state);
3048 ok(hr == S_OK, "Failed to get clock state, hr %#lx.\n", hr);
3049 ok(state == MFCLOCK_STATE_PAUSED, "Unexpected state %d.\n", state);
3051 hr = IMFPresentationClock_Start(clock, 0);
3052 ok(hr == S_OK, "Failed to stop, hr %#lx.\n", hr);
3054 hr = IMFRateControl_SetRate(rate_control, FALSE, 0.0f);
3055 ok(hr == S_OK, "Failed to set clock rate, hr %#lx.\n", hr);
3056 hr = IMFRateControl_GetRate(rate_control, &thin, &rate);
3057 ok(hr == S_OK, "Failed to get clock rate, hr %#lx.\n", hr);
3058 ok(rate == 0.0f, "Unexpected rate.\n");
3059 hr = IMFRateControl_SetRate(rate_control, FALSE, 1.0f);
3060 ok(hr == S_OK, "Failed to set clock rate, hr %#lx.\n", hr);
3061 hr = IMFRateControl_SetRate(rate_control, FALSE, 0.0f);
3062 ok(hr == S_OK, "Failed to set clock rate, hr %#lx.\n", hr);
3063 hr = IMFRateControl_SetRate(rate_control, FALSE, 0.5f);
3064 ok(hr == S_OK, "Failed to set clock rate, hr %#lx.\n", hr);
3065 hr = IMFRateControl_SetRate(rate_control, TRUE, -1.0f);
3066 ok(hr == MF_E_THINNING_UNSUPPORTED, "Unexpected hr %#lx.\n", hr);
3067 hr = IMFRateControl_SetRate(rate_control, TRUE, 0.0f);
3068 ok(hr == MF_E_THINNING_UNSUPPORTED, "Unexpected hr %#lx.\n", hr);
3069 hr = IMFRateControl_SetRate(rate_control, TRUE, 1.0f);
3070 ok(hr == MF_E_THINNING_UNSUPPORTED, "Unexpected hr %#lx.\n", hr);
3072 hr = IMFPresentationClock_GetState(clock, 0, &state);
3073 ok(hr == S_OK, "Failed to get clock state, hr %#lx.\n", hr);
3074 ok(state == MFCLOCK_STATE_RUNNING, "Unexpected state %d.\n", state);
3076 hr = IMFRateControl_GetRate(rate_control, &thin, &rate);
3077 ok(hr == S_OK, "Failed to get clock rate, hr %#lx.\n", hr);
3078 ok(rate == 0.5f, "Unexpected rate.\n");
3079 ok(!thin, "Unexpected thinning.\n");
3081 IMFRateControl_Release(rate_control);
3083 hr = IMFPresentationClock_QueryInterface(clock, &IID_IMFShutdown, (void **)&shutdown);
3084 ok(hr == S_OK, "Failed to get shutdown interface, hr %#lx.\n", hr);
3086 /* Shutdown behavior. */
3087 hr = IMFShutdown_GetShutdownStatus(shutdown, NULL);
3088 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
3090 hr = IMFShutdown_GetShutdownStatus(shutdown, &status);
3091 ok(hr == MF_E_INVALIDREQUEST, "Unexpected hr %#lx.\n", hr);
3093 hr = IMFShutdown_Shutdown(shutdown);
3094 ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr);
3096 time_source = NULL;
3097 hr = IMFPresentationClock_GetTimeSource(clock, &time_source);
3098 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3099 ok(!!time_source, "Unexpected instance %p.\n", time_source);
3100 IMFPresentationTimeSource_Release(time_source);
3102 hr = IMFPresentationClock_GetTime(clock, &time);
3103 ok(hr == S_OK, "Failed to get time, hr %#lx.\n", hr);
3105 hr = IMFShutdown_GetShutdownStatus(shutdown, &status);
3106 ok(hr == S_OK, "Failed to get status, hr %#lx.\n", hr);
3107 ok(status == MFSHUTDOWN_COMPLETED, "Unexpected status.\n");
3109 hr = IMFPresentationClock_Start(clock, 0);
3110 ok(hr == S_OK, "Failed to start the clock, hr %#lx.\n", hr);
3112 hr = IMFShutdown_GetShutdownStatus(shutdown, &status);
3113 ok(hr == S_OK, "Failed to get status, hr %#lx.\n", hr);
3114 ok(status == MFSHUTDOWN_COMPLETED, "Unexpected status.\n");
3116 hr = IMFShutdown_Shutdown(shutdown);
3117 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3119 IMFShutdown_Release(shutdown);
3121 IMFPresentationClock_Release(clock);
3123 hr = MFShutdown();
3124 ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr);
3127 static HRESULT WINAPI grabber_callback_QueryInterface(IMFSampleGrabberSinkCallback *iface, REFIID riid, void **obj)
3129 if (IsEqualIID(riid, &IID_IMFSampleGrabberSinkCallback) ||
3130 IsEqualIID(riid, &IID_IMFClockStateSink) ||
3131 IsEqualIID(riid, &IID_IUnknown))
3133 *obj = iface;
3134 IMFSampleGrabberSinkCallback_AddRef(iface);
3135 return S_OK;
3138 *obj = NULL;
3139 return E_NOINTERFACE;
3142 static ULONG WINAPI grabber_callback_AddRef(IMFSampleGrabberSinkCallback *iface)
3144 return 2;
3147 static ULONG WINAPI grabber_callback_Release(IMFSampleGrabberSinkCallback *iface)
3149 return 1;
3152 static HRESULT WINAPI grabber_callback_OnClockStart(IMFSampleGrabberSinkCallback *iface, MFTIME time, LONGLONG offset)
3154 return E_NOTIMPL;
3157 static HRESULT WINAPI grabber_callback_OnClockStop(IMFSampleGrabberSinkCallback *iface, MFTIME time)
3159 return E_NOTIMPL;
3162 static HRESULT WINAPI grabber_callback_OnClockPause(IMFSampleGrabberSinkCallback *iface, MFTIME time)
3164 return E_NOTIMPL;
3167 static HRESULT WINAPI grabber_callback_OnClockRestart(IMFSampleGrabberSinkCallback *iface, MFTIME time)
3169 return E_NOTIMPL;
3172 static HRESULT WINAPI grabber_callback_OnClockSetRate(IMFSampleGrabberSinkCallback *iface, MFTIME time, float rate)
3174 return E_NOTIMPL;
3177 static HRESULT WINAPI grabber_callback_OnSetPresentationClock(IMFSampleGrabberSinkCallback *iface,
3178 IMFPresentationClock *clock)
3180 return S_OK;
3183 static HRESULT WINAPI grabber_callback_OnProcessSample(IMFSampleGrabberSinkCallback *iface, REFGUID major_type,
3184 DWORD sample_flags, LONGLONG sample_time, LONGLONG sample_duration, const BYTE *buffer, DWORD sample_size)
3186 return E_NOTIMPL;
3189 static HRESULT WINAPI grabber_callback_OnShutdown(IMFSampleGrabberSinkCallback *iface)
3191 return S_OK;
3194 static const IMFSampleGrabberSinkCallbackVtbl grabber_callback_vtbl =
3196 grabber_callback_QueryInterface,
3197 grabber_callback_AddRef,
3198 grabber_callback_Release,
3199 grabber_callback_OnClockStart,
3200 grabber_callback_OnClockStop,
3201 grabber_callback_OnClockPause,
3202 grabber_callback_OnClockRestart,
3203 grabber_callback_OnClockSetRate,
3204 grabber_callback_OnSetPresentationClock,
3205 grabber_callback_OnProcessSample,
3206 grabber_callback_OnShutdown,
3209 static IMFSampleGrabberSinkCallback grabber_callback = { &grabber_callback_vtbl };
3211 static void test_sample_grabber(void)
3213 IMFMediaType *media_type, *media_type2, *media_type3;
3214 IMFMediaTypeHandler *handler, *handler2;
3215 IMFPresentationTimeSource *time_source;
3216 IMFPresentationClock *clock, *clock2;
3217 IMFStreamSink *stream, *stream2;
3218 IMFRateSupport *rate_support;
3219 IMFMediaEventGenerator *eg;
3220 IMFMediaSink *sink, *sink2;
3221 DWORD flags, count, id;
3222 IMFActivate *activate;
3223 IMFMediaEvent *event;
3224 UINT32 attr_count;
3225 float rate;
3226 HRESULT hr;
3227 GUID guid;
3228 LONG ref;
3230 hr = MFStartup(MF_VERSION, MFSTARTUP_FULL);
3231 ok(hr == S_OK, "Failed to start up, hr %#lx.\n", hr);
3233 hr = MFCreateMediaType(&media_type);
3234 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
3236 hr = MFCreateSampleGrabberSinkActivate(NULL, NULL, &activate);
3237 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
3239 hr = MFCreateSampleGrabberSinkActivate(NULL, &grabber_callback, &activate);
3240 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
3242 hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio);
3243 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3244 hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFAudioFormat_PCM);
3245 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3247 EXPECT_REF(media_type, 1);
3248 hr = MFCreateSampleGrabberSinkActivate(media_type, &grabber_callback, &activate);
3249 ok(hr == S_OK, "Failed to create grabber activate, hr %#lx.\n", hr);
3250 EXPECT_REF(media_type, 2);
3252 hr = IMFActivate_GetCount(activate, &attr_count);
3253 ok(hr == S_OK, "Failed to get attribute count, hr %#lx.\n", hr);
3254 ok(!attr_count, "Unexpected count %u.\n", attr_count);
3256 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink);
3257 ok(hr == S_OK, "Failed to activate object, hr %#lx.\n", hr);
3259 check_interface(sink, &IID_IMFClockStateSink, TRUE);
3260 check_interface(sink, &IID_IMFMediaEventGenerator, TRUE);
3261 check_interface(sink, &IID_IMFGetService, TRUE);
3262 check_interface(sink, &IID_IMFRateSupport, TRUE);
3263 check_service_interface(sink, &MF_RATE_CONTROL_SERVICE, &IID_IMFRateSupport, TRUE);
3265 if (SUCCEEDED(MFGetService((IUnknown *)sink, &MF_RATE_CONTROL_SERVICE, &IID_IMFRateSupport, (void **)&rate_support)))
3267 hr = IMFRateSupport_GetFastestRate(rate_support, MFRATE_FORWARD, FALSE, &rate);
3268 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3269 ok(rate == FLT_MAX, "Unexpected rate %f.\n", rate);
3271 hr = IMFRateSupport_GetFastestRate(rate_support, MFRATE_FORWARD, TRUE, &rate);
3272 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3273 ok(rate == FLT_MAX, "Unexpected rate %f.\n", rate);
3275 hr = IMFRateSupport_GetFastestRate(rate_support, MFRATE_REVERSE, FALSE, &rate);
3276 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3277 ok(rate == -FLT_MAX, "Unexpected rate %f.\n", rate);
3279 hr = IMFRateSupport_GetFastestRate(rate_support, MFRATE_REVERSE, TRUE, &rate);
3280 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3281 ok(rate == -FLT_MAX, "Unexpected rate %f.\n", rate);
3283 hr = IMFRateSupport_GetSlowestRate(rate_support, MFRATE_FORWARD, FALSE, &rate);
3284 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3285 ok(rate == 0.0f, "Unexpected rate %f.\n", rate);
3287 hr = IMFRateSupport_GetSlowestRate(rate_support, MFRATE_FORWARD, TRUE, &rate);
3288 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3289 ok(rate == 0.0f, "Unexpected rate %f.\n", rate);
3291 hr = IMFRateSupport_GetSlowestRate(rate_support, MFRATE_REVERSE, FALSE, &rate);
3292 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3293 ok(rate == 0.0f, "Unexpected rate %f.\n", rate);
3295 hr = IMFRateSupport_GetSlowestRate(rate_support, MFRATE_REVERSE, TRUE, &rate);
3296 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3297 ok(rate == 0.0f, "Unexpected rate %f.\n", rate);
3299 hr = IMFRateSupport_IsRateSupported(rate_support, TRUE, 1.0f, &rate);
3300 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3301 ok(rate == 1.0f, "Unexpected rate %f.\n", rate);
3303 IMFRateSupport_Release(rate_support);
3306 hr = IMFMediaSink_GetCharacteristics(sink, &flags);
3307 ok(hr == S_OK, "Failed to get sink flags, hr %#lx.\n", hr);
3308 ok(flags & MEDIASINK_FIXED_STREAMS, "Unexpected flags %#lx.\n", flags);
3310 hr = IMFMediaSink_GetStreamSinkCount(sink, &count);
3311 ok(hr == S_OK, "Failed to get stream count, hr %#lx.\n", hr);
3312 ok(count == 1, "Unexpected stream count %lu.\n", count);
3314 hr = IMFMediaSink_GetStreamSinkByIndex(sink, 0, &stream);
3315 ok(hr == S_OK, "Failed to get sink stream, hr %#lx.\n", hr);
3317 check_interface(stream, &IID_IMFMediaEventGenerator, TRUE);
3318 check_interface(stream, &IID_IMFMediaTypeHandler, TRUE);
3320 hr = IMFStreamSink_GetIdentifier(stream, &id);
3321 ok(hr == S_OK, "Failed to get stream id, hr %#lx.\n", hr);
3322 ok(id == 0, "Unexpected id %#lx.\n", id);
3324 hr = IMFStreamSink_GetMediaSink(stream, &sink2);
3325 ok(hr == S_OK, "Failed to get media sink, hr %lx.\n", hr);
3326 ok(sink2 == sink, "Unexpected sink.\n");
3327 IMFMediaSink_Release(sink2);
3329 hr = IMFMediaSink_GetStreamSinkByIndex(sink, 1, &stream2);
3330 ok(hr == MF_E_INVALIDINDEX, "Unexpected hr %#lx.\n", hr);
3332 hr = IMFMediaSink_GetStreamSinkById(sink, 1, &stream2);
3333 ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#lx.\n", hr);
3335 hr = IMFMediaSink_AddStreamSink(sink, 1, NULL, &stream2);
3336 ok(hr == MF_E_STREAMSINKS_FIXED, "Unexpected hr %#lx.\n", hr);
3338 hr = IMFMediaSink_RemoveStreamSink(sink, 0);
3339 ok(hr == MF_E_STREAMSINKS_FIXED, "Unexpected hr %#lx.\n", hr);
3341 hr = IMFMediaSink_RemoveStreamSink(sink, 1);
3342 ok(hr == MF_E_STREAMSINKS_FIXED, "Unexpected hr %#lx.\n", hr);
3344 check_interface(sink, &IID_IMFClockStateSink, TRUE);
3346 /* Event generator. */
3347 hr = IMFMediaSink_QueryInterface(sink, &IID_IMFMediaEventGenerator, (void **)&eg);
3348 ok(hr == S_OK, "Failed to get interface, hr %#lx.\n", hr);
3350 hr = IMFMediaEventGenerator_GetEvent(eg, MF_EVENT_FLAG_NO_WAIT, &event);
3351 ok(hr == MF_E_NO_EVENTS_AVAILABLE, "Unexpected hr %#lx.\n", hr);
3353 check_interface(sink, &IID_IMFPresentationTimeSource, FALSE);
3355 hr = IMFStreamSink_QueryInterface(stream, &IID_IMFMediaTypeHandler, (void **)&handler2);
3356 ok(hr == S_OK, "Failed to get handler interface, hr %#lx.\n", hr);
3358 hr = IMFStreamSink_GetMediaTypeHandler(stream, &handler);
3359 ok(hr == S_OK, "Failed to get type handler, hr %#lx.\n", hr);
3360 hr = IMFMediaTypeHandler_GetMediaTypeCount(handler, &count);
3361 ok(hr == S_OK, "Failed to get media type count, hr %#lx.\n", hr);
3362 ok(count == 0, "Unexpected count %lu.\n", count);
3363 ok(handler == handler2, "Unexpected handler.\n");
3365 IMFMediaTypeHandler_Release(handler);
3366 IMFMediaTypeHandler_Release(handler2);
3368 /* Set clock. */
3369 hr = MFCreatePresentationClock(&clock);
3370 ok(hr == S_OK, "Failed to create clock object, hr %#lx.\n", hr);
3372 hr = IMFMediaSink_GetPresentationClock(sink, NULL);
3373 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
3375 hr = IMFMediaSink_GetPresentationClock(sink, &clock2);
3376 ok(hr == MF_E_NO_CLOCK, "Unexpected hr %#lx.\n", hr);
3378 hr = IMFMediaSink_SetPresentationClock(sink, NULL);
3379 ok(hr == S_OK, "Failed to set presentation clock, hr %#lx.\n", hr);
3381 hr = IMFMediaSink_SetPresentationClock(sink, clock);
3382 ok(hr == S_OK, "Failed to set presentation clock, hr %#lx.\n", hr);
3384 hr = MFCreateSystemTimeSource(&time_source);
3385 ok(hr == S_OK, "Failed to create time source, hr %#lx.\n", hr);
3387 hr = IMFPresentationClock_SetTimeSource(clock, time_source);
3388 ok(hr == S_OK, "Failed to set time source, hr %#lx.\n", hr);
3389 IMFPresentationTimeSource_Release(time_source);
3391 hr = IMFMediaSink_GetCharacteristics(sink, &flags);
3392 ok(hr == S_OK, "Failed to get sink flags, hr %#lx.\n", hr);
3394 hr = IMFActivate_ShutdownObject(activate);
3395 ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr);
3397 hr = IMFMediaSink_GetCharacteristics(sink, &flags);
3398 ok(hr == S_OK, "Failed to get sink flags, hr %#lx.\n", hr);
3400 hr = IMFStreamSink_GetMediaTypeHandler(stream, &handler);
3401 ok(hr == S_OK, "Failed to get type handler, hr %#lx.\n", hr);
3403 /* On Win8+ this initialization happens automatically. */
3404 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, media_type);
3405 ok(hr == S_OK, "Failed to set media type, hr %#lx.\n", hr);
3407 hr = IMFMediaTypeHandler_GetMediaTypeCount(handler, NULL);
3408 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
3410 hr = IMFMediaTypeHandler_GetMediaTypeCount(handler, &count);
3411 ok(hr == S_OK, "Failed to get media type count, hr %#lx.\n", hr);
3412 ok(count == 0, "Unexpected count %lu.\n", count);
3414 hr = IMFMediaTypeHandler_GetMajorType(handler, &guid);
3415 ok(hr == S_OK, "Failed to get major type, hr %#lx.\n", hr);
3416 ok(IsEqualGUID(&guid, &MFMediaType_Audio), "Unexpected major type %s.\n", wine_dbgstr_guid(&guid));
3418 hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, &media_type2);
3419 ok(hr == S_OK, "Failed to get current type, hr %#lx.\n", hr);
3420 ok(media_type2 == media_type, "Unexpected media type.\n");
3421 IMFMediaType_Release(media_type2);
3423 hr = MFCreateMediaType(&media_type2);
3424 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
3426 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, media_type2);
3427 ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#lx.\n", hr);
3429 hr = IMFMediaType_SetGUID(media_type2, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio);
3430 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3432 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, media_type2);
3433 ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#lx.\n", hr);
3435 hr = IMFMediaType_SetGUID(media_type2, &MF_MT_SUBTYPE, &MFAudioFormat_Float);
3436 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3438 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, media_type2);
3439 ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#lx.\n", hr);
3441 hr = IMFMediaType_SetGUID(media_type2, &MF_MT_SUBTYPE, &MFAudioFormat_PCM);
3442 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3444 hr = IMFMediaType_SetUINT32(media_type2, &MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100);
3445 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3447 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, media_type2);
3448 ok(hr == S_OK, "Failed to get current type, hr %#lx.\n", hr);
3449 IMFMediaType_Release(media_type);
3451 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, NULL);
3452 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
3454 hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, &media_type);
3455 ok(hr == S_OK, "Failed to get current type, hr %#lx.\n", hr);
3456 ok(media_type2 == media_type, "Unexpected media type.\n");
3457 IMFMediaType_Release(media_type);
3459 hr = IMFMediaTypeHandler_GetMediaTypeByIndex(handler, 0, &media_type);
3460 ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#lx.\n", hr);
3462 hr = IMFMediaTypeHandler_GetMediaTypeByIndex(handler, 0, NULL);
3463 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
3465 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type2, NULL);
3466 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3468 hr = MFCreateMediaType(&media_type);
3469 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
3471 hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio);
3472 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3474 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type, NULL);
3475 ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#lx.\n", hr);
3477 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type, &media_type3);
3478 ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#lx.\n", hr);
3480 hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFAudioFormat_PCM);
3481 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3483 media_type3 = (void *)0xdeadbeef;
3484 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type, &media_type3);
3485 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3486 ok(media_type3 == (void *)0xdeadbeef, "Unexpected media type %p.\n", media_type3);
3488 hr = IMFMediaType_SetUINT32(media_type, &MF_MT_FIXED_SIZE_SAMPLES, 1);
3489 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3491 hr = IMFMediaType_SetUINT32(media_type, &MF_MT_SAMPLE_SIZE, 1024);
3492 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3494 media_type3 = (void *)0xdeadbeef;
3495 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type, &media_type3);
3496 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3497 ok(media_type3 == (void *)0xdeadbeef, "Unexpected media type %p.\n", media_type3);
3499 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, NULL, NULL);
3500 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
3502 hr = IMFMediaEventGenerator_GetEvent(eg, MF_EVENT_FLAG_NO_WAIT, &event);
3503 ok(hr == MF_E_NO_EVENTS_AVAILABLE, "Unexpected hr %#lx.\n", hr);
3505 hr = IMFStreamSink_GetEvent(stream, MF_EVENT_FLAG_NO_WAIT, &event);
3506 ok(hr == MF_E_NO_EVENTS_AVAILABLE, "Unexpected hr %#lx.\n", hr);
3508 EXPECT_REF(clock, 3);
3509 hr = IMFMediaSink_Shutdown(sink);
3510 ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr);
3512 ref = IMFPresentationClock_Release(clock);
3513 ok(ref == 0, "Release returned %ld\n", ref);
3515 hr = IMFMediaEventGenerator_GetEvent(eg, MF_EVENT_FLAG_NO_WAIT, &event);
3516 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
3518 hr = IMFMediaSink_Shutdown(sink);
3519 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
3521 hr = IMFMediaSink_GetCharacteristics(sink, &flags);
3522 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
3524 hr = IMFMediaSink_AddStreamSink(sink, 1, NULL, &stream2);
3525 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
3527 hr = IMFMediaSink_GetStreamSinkCount(sink, &count);
3528 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
3530 hr = IMFMediaSink_GetStreamSinkByIndex(sink, 0, &stream2);
3531 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
3533 hr = IMFStreamSink_GetEvent(stream, MF_EVENT_FLAG_NO_WAIT, &event);
3534 ok(hr == MF_E_STREAMSINK_REMOVED, "Unexpected hr %#lx.\n", hr);
3536 hr = IMFStreamSink_GetMediaSink(stream, &sink2);
3537 ok(hr == MF_E_STREAMSINK_REMOVED, "Unexpected hr %#lx.\n", hr);
3539 id = 1;
3540 hr = IMFStreamSink_GetIdentifier(stream, &id);
3541 ok(hr == MF_E_STREAMSINK_REMOVED, "Unexpected hr %#lx.\n", hr);
3542 ok(id == 1, "Unexpected id %lu.\n", id);
3544 media_type3 = (void *)0xdeadbeef;
3545 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type, &media_type3);
3546 ok(hr == MF_E_STREAMSINK_REMOVED, "Unexpected hr %#lx.\n", hr);
3547 ok(media_type3 == (void *)0xdeadbeef, "Unexpected media type %p.\n", media_type3);
3549 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, NULL, NULL);
3550 ok(hr == MF_E_STREAMSINK_REMOVED, "Unexpected hr %#lx.\n", hr);
3552 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, NULL);
3553 ok(hr == MF_E_STREAMSINK_REMOVED, "Unexpected hr %#lx.\n", hr);
3555 hr = IMFMediaTypeHandler_GetMediaTypeCount(handler, &count);
3556 ok(hr == S_OK, "Failed to get type count, hr %#lx.\n", hr);
3558 ref = IMFMediaType_Release(media_type2);
3559 todo_wine
3560 ok(ref == 0, "Release returned %ld\n", ref);
3561 ref = IMFMediaType_Release(media_type);
3562 ok(ref == 0, "Release returned %ld\n", ref);
3564 hr = IMFMediaTypeHandler_GetMediaTypeByIndex(handler, 0, &media_type);
3565 ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#lx.\n", hr);
3567 hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, &media_type);
3568 ok(hr == MF_E_STREAMSINK_REMOVED, "Unexpected hr %#lx.\n", hr);
3570 hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, NULL);
3571 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
3573 hr = IMFMediaTypeHandler_GetMajorType(handler, NULL);
3574 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
3576 hr = IMFMediaTypeHandler_GetMajorType(handler, &guid);
3577 ok(hr == MF_E_STREAMSINK_REMOVED, "Unexpected hr %#lx.\n", hr);
3579 IMFMediaTypeHandler_Release(handler);
3581 handler = (void *)0xdeadbeef;
3582 hr = IMFStreamSink_GetMediaTypeHandler(stream, &handler);
3583 ok(hr == MF_E_STREAMSINK_REMOVED, "Unexpected hr %#lx.\n", hr);
3584 ok(handler == (void *)0xdeadbeef, "Unexpected pointer.\n");
3586 hr = IMFStreamSink_GetMediaTypeHandler(stream, NULL);
3587 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
3589 IMFMediaEventGenerator_Release(eg);
3590 IMFStreamSink_Release(stream);
3592 ref = IMFActivate_Release(activate);
3593 ok(ref == 0, "Release returned %ld\n", ref);
3594 ref = IMFMediaSink_Release(sink);
3595 ok(ref == 0, "Release returned %ld\n", ref);
3597 /* Rateless mode with MF_SAMPLEGRABBERSINK_IGNORE_CLOCK. */
3598 hr = MFCreateMediaType(&media_type);
3599 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
3601 hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio);
3602 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3603 hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFAudioFormat_PCM);
3604 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3606 hr = MFCreateSampleGrabberSinkActivate(media_type, &grabber_callback, &activate);
3607 ok(hr == S_OK, "Failed to create grabber activate, hr %#lx.\n", hr);
3609 hr = IMFActivate_SetUINT32(activate, &MF_SAMPLEGRABBERSINK_IGNORE_CLOCK, 1);
3610 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3612 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink);
3613 ok(hr == S_OK, "Failed to activate object, hr %#lx.\n", hr);
3615 hr = IMFMediaSink_GetCharacteristics(sink, &flags);
3616 ok(hr == S_OK, "Failed to get sink flags, hr %#lx.\n", hr);
3617 ok(flags & MEDIASINK_RATELESS, "Unexpected flags %#lx.\n", flags);
3619 hr = IMFActivate_ShutdownObject(activate);
3620 ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr);
3622 /* required for the sink to be fully released */
3623 hr = IMFMediaSink_Shutdown(sink);
3624 ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr);
3626 ref = IMFActivate_Release(activate);
3627 ok(ref == 0, "Release returned %ld\n", ref);
3628 ref = IMFMediaSink_Release(sink);
3629 ok(ref == 0, "Release returned %ld\n", ref);
3631 /* Detaching */
3632 hr = MFCreateSampleGrabberSinkActivate(media_type, &grabber_callback, &activate);
3633 ok(hr == S_OK, "Failed to create grabber activate, hr %#lx.\n", hr);
3635 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink);
3636 ok(hr == S_OK, "Failed to activate object, hr %#lx.\n", hr);
3638 hr = IMFActivate_ShutdownObject(activate);
3639 ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr);
3641 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink2);
3642 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
3644 hr = IMFActivate_GetCount(activate, &attr_count);
3645 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3647 hr = IMFActivate_DetachObject(activate);
3648 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
3650 ref = IMFActivate_Release(activate);
3651 ok(ref == 0, "Release returned %ld\n", ref);
3653 /* required for the sink to be fully released */
3654 hr = IMFMediaSink_Shutdown(sink);
3655 ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr);
3657 ref = IMFMediaSink_Release(sink);
3658 ok(ref == 0, "Release returned %ld\n", ref);
3660 ref = IMFMediaType_Release(media_type);
3661 ok(ref == 0, "Release returned %ld\n", ref);
3663 hr = MFShutdown();
3664 ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr);
3667 static void test_sample_grabber_is_mediatype_supported(void)
3669 IMFMediaType *media_type, *media_type2, *media_type3;
3670 IMFMediaTypeHandler *handler;
3671 IMFActivate *activate;
3672 IMFStreamSink *stream;
3673 IMFMediaSink *sink;
3674 HRESULT hr;
3675 GUID guid;
3676 LONG ref;
3678 /* IsMediaTypeSupported checks are done against the creation type, and check format data */
3679 hr = MFCreateMediaType(&media_type);
3680 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
3682 hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio);
3683 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3684 hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFAudioFormat_PCM);
3685 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3686 hr = IMFMediaType_SetUINT32(media_type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100);
3687 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3689 hr = MFCreateSampleGrabberSinkActivate(media_type, &grabber_callback, &activate);
3690 ok(hr == S_OK, "Failed to create grabber activate, hr %#lx.\n", hr);
3692 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink);
3693 ok(hr == S_OK, "Failed to activate object, hr %#lx.\n", hr);
3695 hr = IMFMediaSink_GetStreamSinkByIndex(sink, 0, &stream);
3696 ok(hr == S_OK, "Failed to get sink stream, hr %#lx.\n", hr);
3697 hr = IMFStreamSink_GetMediaTypeHandler(stream, &handler);
3698 ok(hr == S_OK, "Failed to get type handler, hr %#lx.\n", hr);
3699 IMFStreamSink_Release(stream);
3701 /* On Win8+ this initialization happens automatically. */
3702 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, media_type);
3703 ok(hr == S_OK, "Failed to set media type, hr %#lx.\n", hr);
3705 hr = MFCreateMediaType(&media_type2);
3706 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
3708 hr = IMFMediaType_SetGUID(media_type2, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio);
3709 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3710 hr = IMFMediaType_SetGUID(media_type2, &MF_MT_SUBTYPE, &MFAudioFormat_PCM);
3711 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3712 hr = IMFMediaType_SetUINT32(media_type2, &MF_MT_AUDIO_SAMPLES_PER_SECOND, 48000);
3713 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3715 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type2, NULL);
3716 ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#lx.\n", hr);
3718 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, media_type2);
3719 ok(hr == MF_E_INVALIDMEDIATYPE, "Failed to set media type, hr %#lx.\n", hr);
3721 /* Make it match grabber type sample rate. */
3722 hr = IMFMediaType_SetUINT32(media_type2, &MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100);
3723 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3725 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type2, NULL);
3726 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3728 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, media_type2);
3729 ok(hr == S_OK, "Failed to set media type, hr %#lx.\n", hr);
3730 hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, &media_type3);
3731 ok(hr == S_OK, "Failed to set media type, hr %#lx.\n", hr);
3732 ok(media_type3 == media_type2, "Unexpected media type instance.\n");
3733 IMFMediaType_Release(media_type3);
3735 /* Change original type. */
3736 hr = IMFMediaType_SetUINT32(media_type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, 48000);
3737 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3739 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type2, NULL);
3740 ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#lx.\n", hr);
3742 hr = IMFMediaType_SetUINT32(media_type2, &MF_MT_AUDIO_SAMPLES_PER_SECOND, 48000);
3743 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3745 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type2, NULL);
3746 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3748 hr = IMFMediaTypeHandler_GetMajorType(handler, &guid);
3749 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3750 ok(IsEqualGUID(&guid, &MFMediaType_Audio), "Unexpected major type.\n");
3752 hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
3753 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3755 hr = IMFMediaTypeHandler_GetMajorType(handler, &guid);
3756 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3757 ok(IsEqualGUID(&guid, &MFMediaType_Audio), "Unexpected major type.\n");
3759 IMFMediaTypeHandler_Release(handler);
3761 hr = IMFActivate_ShutdownObject(activate);
3762 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3764 ref = IMFActivate_Release(activate);
3765 ok(ref == 0, "Release returned %ld\n", ref);
3767 /* required for the sink to be fully released */
3768 hr = IMFMediaSink_Shutdown(sink);
3769 ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr);
3771 ref = IMFMediaSink_Release(sink);
3772 ok(ref == 0, "Release returned %ld\n", ref);
3774 ref = IMFMediaType_Release(media_type2);
3775 ok(ref == 0, "Release returned %ld\n", ref);
3776 ref = IMFMediaType_Release(media_type);
3777 ok(ref == 0, "Release returned %ld\n", ref);
3780 static BOOL is_supported_video_type(const GUID *guid)
3782 return IsEqualGUID(guid, &MFVideoFormat_L8)
3783 || IsEqualGUID(guid, &MFVideoFormat_L16)
3784 || IsEqualGUID(guid, &MFVideoFormat_D16)
3785 || IsEqualGUID(guid, &MFVideoFormat_IYUV)
3786 || IsEqualGUID(guid, &MFVideoFormat_YV12)
3787 || IsEqualGUID(guid, &MFVideoFormat_NV12)
3788 || IsEqualGUID(guid, &MFVideoFormat_NV21)
3789 || IsEqualGUID(guid, &MFVideoFormat_420O)
3790 || IsEqualGUID(guid, &MFVideoFormat_P010)
3791 || IsEqualGUID(guid, &MFVideoFormat_P016)
3792 || IsEqualGUID(guid, &MFVideoFormat_UYVY)
3793 || IsEqualGUID(guid, &MFVideoFormat_YUY2)
3794 || IsEqualGUID(guid, &MFVideoFormat_P208)
3795 || IsEqualGUID(guid, &MFVideoFormat_NV11)
3796 || IsEqualGUID(guid, &MFVideoFormat_AYUV)
3797 || IsEqualGUID(guid, &MFVideoFormat_ARGB32)
3798 || IsEqualGUID(guid, &MFVideoFormat_RGB32)
3799 || IsEqualGUID(guid, &MFVideoFormat_A2R10G10B10)
3800 || IsEqualGUID(guid, &MFVideoFormat_A16B16G16R16F)
3801 || IsEqualGUID(guid, &MFVideoFormat_RGB24)
3802 || IsEqualGUID(guid, &MFVideoFormat_I420)
3803 || IsEqualGUID(guid, &MFVideoFormat_YVYU)
3804 || IsEqualGUID(guid, &MFVideoFormat_RGB555)
3805 || IsEqualGUID(guid, &MFVideoFormat_RGB565)
3806 || IsEqualGUID(guid, &MFVideoFormat_RGB8)
3807 || IsEqualGUID(guid, &MFVideoFormat_Y216)
3808 || IsEqualGUID(guid, &MFVideoFormat_v410)
3809 || IsEqualGUID(guid, &MFVideoFormat_Y41P)
3810 || IsEqualGUID(guid, &MFVideoFormat_Y41T)
3811 || IsEqualGUID(guid, &MFVideoFormat_Y42T)
3812 || IsEqualGUID(guid, &MFVideoFormat_ABGR32);
3815 static void test_video_processor(void)
3817 const GUID transform_inputs[22] =
3819 MFVideoFormat_IYUV,
3820 MFVideoFormat_YV12,
3821 MFVideoFormat_NV12,
3822 MFVideoFormat_YUY2,
3823 MFVideoFormat_ARGB32,
3824 MFVideoFormat_RGB32,
3825 MFVideoFormat_NV11,
3826 MFVideoFormat_AYUV,
3827 MFVideoFormat_UYVY,
3828 MEDIASUBTYPE_P208,
3829 MFVideoFormat_RGB24,
3830 MFVideoFormat_RGB555,
3831 MFVideoFormat_RGB565,
3832 MFVideoFormat_RGB8,
3833 MFVideoFormat_I420,
3834 MFVideoFormat_Y216,
3835 MFVideoFormat_v410,
3836 MFVideoFormat_Y41P,
3837 MFVideoFormat_Y41T,
3838 MFVideoFormat_Y42T,
3839 MFVideoFormat_YVYU,
3840 MFVideoFormat_420O,
3842 const GUID transform_outputs[21] =
3844 MFVideoFormat_IYUV,
3845 MFVideoFormat_YV12,
3846 MFVideoFormat_NV12,
3847 MFVideoFormat_YUY2,
3848 MFVideoFormat_ARGB32,
3849 MFVideoFormat_RGB32,
3850 MFVideoFormat_NV11,
3851 MFVideoFormat_AYUV,
3852 MFVideoFormat_UYVY,
3853 MEDIASUBTYPE_P208,
3854 MFVideoFormat_RGB24,
3855 MFVideoFormat_RGB555,
3856 MFVideoFormat_RGB565,
3857 MFVideoFormat_RGB8,
3858 MFVideoFormat_I420,
3859 MFVideoFormat_Y216,
3860 MFVideoFormat_v410,
3861 MFVideoFormat_Y41P,
3862 MFVideoFormat_Y41T,
3863 MFVideoFormat_Y42T,
3864 MFVideoFormat_YVYU,
3866 MFT_REGISTER_TYPE_INFO output_type = {MFMediaType_Video, MFVideoFormat_NV12};
3867 MFT_REGISTER_TYPE_INFO input_type = {MFMediaType_Video, MFVideoFormat_I420};
3868 DWORD input_count, output_count, input_id, output_id, flags;
3869 DWORD input_min, input_max, output_min, output_max, i;
3870 IMFAttributes *attributes, *attributes2;
3871 IMFMediaType *media_type, *media_type2;
3872 MFT_OUTPUT_DATA_BUFFER output_buffer;
3873 MFT_OUTPUT_STREAM_INFO output_info;
3874 MFT_INPUT_STREAM_INFO input_info;
3875 IMFSample *sample, *sample2;
3876 IMFTransform *transform;
3877 IMFMediaBuffer *buffer;
3878 IMFMediaEvent *event;
3879 unsigned int value;
3880 GUID class_id;
3881 UINT32 count;
3882 HRESULT hr;
3883 GUID guid;
3884 LONG ref;
3886 hr = CoInitialize(NULL);
3887 ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
3889 if (!create_transform(MFT_CATEGORY_VIDEO_PROCESSOR, &input_type, &output_type, L"Microsoft Video Processor MFT", &MFMediaType_Video,
3890 transform_inputs, ARRAY_SIZE(transform_inputs), transform_outputs, ARRAY_SIZE(transform_outputs),
3891 &transform, &CLSID_VideoProcessorMFT, &class_id))
3892 goto failed;
3893 has_video_processor = TRUE;
3895 todo_wine
3896 check_interface(transform, &IID_IMFVideoProcessorControl, TRUE);
3897 todo_wine
3898 check_interface(transform, &IID_IMFRealTimeClientEx, TRUE);
3899 check_interface(transform, &IID_IMFMediaEventGenerator, FALSE);
3900 check_interface(transform, &IID_IMFShutdown, FALSE);
3902 /* Transform global attributes. */
3903 hr = IMFTransform_GetAttributes(transform, &attributes);
3904 ok(hr == S_OK, "Failed to get attributes, hr %#lx.\n", hr);
3906 hr = IMFAttributes_GetCount(attributes, &count);
3907 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3908 todo_wine
3909 ok(!!count, "Unexpected attribute count %u.\n", count);
3911 value = 0;
3912 hr = IMFAttributes_GetUINT32(attributes, &MF_SA_D3D11_AWARE, &value);
3913 todo_wine {
3914 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3915 ok(value == 1, "Unexpected attribute value %u.\n", value);
3917 hr = IMFTransform_GetAttributes(transform, &attributes2);
3918 ok(hr == S_OK, "Failed to get attributes, hr %#lx.\n", hr);
3919 ok(attributes == attributes2, "Unexpected instance.\n");
3920 IMFAttributes_Release(attributes);
3921 IMFAttributes_Release(attributes2);
3923 hr = IMFTransform_GetStreamLimits(transform, &input_min, &input_max, &output_min, &output_max);
3924 ok(hr == S_OK, "Failed to get stream limits, hr %#lx.\n", hr);
3925 ok(input_min == input_max && input_min == 1 && output_min == output_max && output_min == 1,
3926 "Unexpected stream limits.\n");
3928 hr = IMFTransform_GetStreamCount(transform, &input_count, &output_count);
3929 ok(hr == S_OK, "Failed to get stream count, hr %#lx.\n", hr);
3930 ok(input_count == 1 && output_count == 1, "Unexpected stream count %lu, %lu.\n", input_count, output_count);
3932 hr = IMFTransform_GetStreamIDs(transform, 1, &input_id, 1, &output_id);
3933 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
3935 input_id = 100;
3936 hr = IMFTransform_AddInputStreams(transform, 1, &input_id);
3937 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
3939 hr = IMFTransform_DeleteInputStream(transform, 0);
3940 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
3942 hr = IMFTransform_GetInputStatus(transform, 0, &flags);
3943 todo_wine
3944 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
3946 hr = IMFTransform_GetInputStreamAttributes(transform, 0, &attributes);
3947 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
3949 hr = IMFTransform_GetOutputStatus(transform, &flags);
3950 todo_wine
3951 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
3953 hr = IMFTransform_GetOutputStreamAttributes(transform, 0, &attributes);
3954 ok(hr == S_OK, "Failed to get output attributes, hr %#lx.\n", hr);
3955 hr = IMFTransform_GetOutputStreamAttributes(transform, 0, &attributes2);
3956 ok(hr == S_OK, "Failed to get output attributes, hr %#lx.\n", hr);
3957 ok(attributes == attributes2, "Unexpected instance.\n");
3958 IMFAttributes_Release(attributes);
3959 IMFAttributes_Release(attributes2);
3961 hr = IMFTransform_GetOutputAvailableType(transform, 0, 0, &media_type);
3962 todo_wine
3963 ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#lx.\n", hr);
3965 hr = IMFTransform_GetInputCurrentType(transform, 0, &media_type);
3966 todo_wine
3967 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
3969 hr = IMFTransform_GetInputCurrentType(transform, 1, &media_type);
3970 todo_wine
3971 ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#lx.\n", hr);
3973 hr = IMFTransform_GetOutputCurrentType(transform, 0, &media_type);
3974 todo_wine
3975 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
3977 hr = IMFTransform_GetOutputCurrentType(transform, 1, &media_type);
3978 todo_wine
3979 ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#lx.\n", hr);
3981 hr = IMFTransform_GetInputStreamInfo(transform, 1, &input_info);
3982 todo_wine
3983 ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#lx.\n", hr);
3985 memset(&input_info, 0xcc, sizeof(input_info));
3986 hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info);
3987 todo_wine {
3988 ok(hr == S_OK, "Failed to get stream info, hr %#lx.\n", hr);
3989 ok(input_info.dwFlags == 0, "Unexpected flag %#lx.\n", input_info.dwFlags);
3990 ok(input_info.cbSize == 0, "Unexpected size %lu.\n", input_info.cbSize);
3991 ok(input_info.cbMaxLookahead == 0, "Unexpected lookahead length %lu.\n", input_info.cbMaxLookahead);
3992 ok(input_info.cbAlignment == 0, "Unexpected alignment %lu.\n", input_info.cbAlignment);
3994 hr = MFCreateMediaEvent(MEUnknown, &GUID_NULL, S_OK, NULL, &event);
3995 ok(hr == S_OK, "Failed to create event object, hr %#lx.\n", hr);
3996 hr = IMFTransform_ProcessEvent(transform, 0, event);
3997 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
3998 hr = IMFTransform_ProcessEvent(transform, 1, event);
3999 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
4000 ref = IMFMediaEvent_Release(event);
4001 ok(ref == 0, "Release returned %ld\n", ref);
4003 /* Configure stream types. */
4004 for (i = 0;;++i)
4006 if (FAILED(hr = IMFTransform_GetInputAvailableType(transform, 0, i, &media_type)))
4008 todo_wine
4009 ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#lx.\n", hr);
4010 break;
4013 hr = IMFTransform_GetInputAvailableType(transform, 0, i, &media_type2);
4014 ok(hr == S_OK, "Failed to get available type, hr %#lx.\n", hr);
4015 ok(media_type != media_type2, "Unexpected instance.\n");
4016 ref = IMFMediaType_Release(media_type2);
4017 ok(ref == 0, "Release returned %ld\n", ref);
4019 hr = IMFMediaType_GetMajorType(media_type, &guid);
4020 ok(hr == S_OK, "Failed to get major type, hr %#lx.\n", hr);
4021 ok(IsEqualGUID(&guid, &MFMediaType_Video), "Unexpected major type.\n");
4023 hr = IMFMediaType_GetCount(media_type, &count);
4024 ok(hr == S_OK, "Failed to get attributes count, hr %#lx.\n", hr);
4025 ok(count == 2, "Unexpected count %u.\n", count);
4027 hr = IMFMediaType_GetGUID(media_type, &MF_MT_SUBTYPE, &guid);
4028 ok(hr == S_OK, "Failed to get subtype, hr %#lx.\n", hr);
4029 ok(is_supported_video_type(&guid), "Unexpected media type %s.\n", wine_dbgstr_guid(&guid));
4031 hr = IMFTransform_SetInputType(transform, 0, media_type, MFT_SET_TYPE_TEST_ONLY);
4032 ok(FAILED(hr), "Unexpected hr %#lx.\n", hr);
4034 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
4035 ok(FAILED(hr), "Unexpected hr %#lx.\n", hr);
4037 hr = IMFTransform_GetOutputCurrentType(transform, 0, &media_type2);
4038 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
4040 /* FIXME: figure out if those require additional attributes or simply advertised but not supported */
4041 if (IsEqualGUID(&guid, &MFVideoFormat_L8) || IsEqualGUID(&guid, &MFVideoFormat_L16)
4042 || IsEqualGUID(&guid, &MFVideoFormat_D16) || IsEqualGUID(&guid, &MFVideoFormat_420O)
4043 || IsEqualGUID(&guid, &MFVideoFormat_A16B16G16R16F))
4045 ref = IMFMediaType_Release(media_type);
4046 ok(ref == 0, "Release returned %ld\n", ref);
4047 continue;
4050 hr = IMFMediaType_SetUINT64(media_type, &MF_MT_FRAME_SIZE, ((UINT64)16 << 32) | 16);
4051 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
4053 hr = IMFTransform_SetInputType(transform, 0, media_type, MFT_SET_TYPE_TEST_ONLY);
4054 ok(hr == S_OK, "Failed to test input type %s, hr %#lx.\n", wine_dbgstr_guid(&guid), hr);
4056 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
4057 ok(hr == S_OK, "Failed to test input type, hr %#lx.\n", hr);
4059 hr = IMFTransform_GetInputCurrentType(transform, 0, &media_type2);
4060 ok(hr == S_OK, "Failed to get current type, hr %#lx.\n", hr);
4061 ok(media_type != media_type2, "Unexpected instance.\n");
4062 IMFMediaType_Release(media_type2);
4064 hr = IMFTransform_GetInputStatus(transform, 0, &flags);
4065 ok(hr == S_OK, "Failed to get input status, hr %#lx.\n", hr);
4066 ok(flags == MFT_INPUT_STATUS_ACCEPT_DATA, "Unexpected input status %#lx.\n", flags);
4068 hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info);
4069 ok(hr == S_OK, "Failed to get stream info, hr %#lx.\n", hr);
4070 ok(input_info.dwFlags == 0, "Unexpected flags %#lx.\n", input_info.dwFlags);
4071 ok(input_info.cbMaxLookahead == 0, "Unexpected lookahead length %lu.\n", input_info.cbMaxLookahead);
4072 ok(input_info.cbAlignment == 0, "Unexpected alignment %lu.\n", input_info.cbAlignment);
4074 IMFMediaType_Release(media_type);
4077 /* IYUV -> RGB32 */
4078 hr = MFCreateMediaType(&media_type);
4079 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
4081 hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
4082 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
4084 hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFVideoFormat_IYUV);
4085 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
4087 hr = IMFMediaType_SetUINT64(media_type, &MF_MT_FRAME_SIZE, ((UINT64)16 << 32) | 16);
4088 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
4090 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
4091 todo_wine
4092 ok(hr == S_OK, "Failed to set input type, hr %#lx.\n", hr);
4094 hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFVideoFormat_RGB32);
4095 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
4097 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
4098 todo_wine
4099 ok(hr == S_OK, "Failed to set output type, hr %#lx.\n", hr);
4101 memset(&output_info, 0, sizeof(output_info));
4102 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
4103 todo_wine
4104 ok(hr == S_OK, "Failed to get stream info, hr %#lx.\n", hr);
4105 ok(output_info.dwFlags == 0, "Unexpected flags %#lx.\n", output_info.dwFlags);
4106 todo_wine
4107 ok(output_info.cbSize > 0, "Unexpected size %lu.\n", output_info.cbSize);
4108 ok(output_info.cbAlignment == 0, "Unexpected alignment %lu.\n", output_info.cbAlignment);
4110 hr = MFCreateSample(&sample);
4111 ok(hr == S_OK, "Failed to create a sample, hr %#lx.\n", hr);
4113 hr = MFCreateSample(&sample2);
4114 ok(hr == S_OK, "Failed to create a sample, hr %#lx.\n", hr);
4116 memset(&output_buffer, 0, sizeof(output_buffer));
4117 output_buffer.pSample = sample;
4118 flags = 0;
4119 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output_buffer, &flags);
4120 todo_wine
4121 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "Unexpected hr %#lx.\n", hr);
4122 ok(output_buffer.dwStatus == 0, "Unexpected buffer status, %#lx.\n", output_buffer.dwStatus);
4123 ok(flags == 0, "Unexpected status %#lx.\n", flags);
4125 hr = IMFTransform_ProcessInput(transform, 0, sample2, 0);
4126 todo_wine
4127 ok(hr == S_OK, "Failed to push a sample, hr %#lx.\n", hr);
4129 hr = IMFTransform_ProcessInput(transform, 0, sample2, 0);
4130 todo_wine
4131 ok(hr == MF_E_NOTACCEPTING, "Unexpected hr %#lx.\n", hr);
4133 memset(&output_buffer, 0, sizeof(output_buffer));
4134 output_buffer.pSample = sample;
4135 flags = 0;
4136 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output_buffer, &flags);
4137 todo_wine
4138 ok(hr == MF_E_NO_SAMPLE_TIMESTAMP, "Unexpected hr %#lx.\n", hr);
4139 ok(output_buffer.dwStatus == 0, "Unexpected buffer status, %#lx.\n", output_buffer.dwStatus);
4140 ok(flags == 0, "Unexpected status %#lx.\n", flags);
4142 hr = IMFSample_SetSampleTime(sample2, 0);
4143 ok(hr == S_OK, "Failed to set sample time, hr %#lx.\n", hr);
4144 memset(&output_buffer, 0, sizeof(output_buffer));
4145 output_buffer.pSample = sample;
4146 flags = 0;
4147 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output_buffer, &flags);
4148 todo_wine
4149 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
4150 ok(output_buffer.dwStatus == 0, "Unexpected buffer status, %#lx.\n", output_buffer.dwStatus);
4151 ok(flags == 0, "Unexpected status %#lx.\n", flags);
4153 hr = MFCreateMemoryBuffer(1024 * 1024, &buffer);
4154 ok(hr == S_OK, "Failed to create a buffer, hr %#lx.\n", hr);
4156 hr = IMFSample_AddBuffer(sample2, buffer);
4157 ok(hr == S_OK, "Failed to add a buffer, hr %#lx.\n", hr);
4159 hr = IMFSample_AddBuffer(sample, buffer);
4160 ok(hr == S_OK, "Failed to add a buffer, hr %#lx.\n", hr);
4162 memset(&output_buffer, 0, sizeof(output_buffer));
4163 output_buffer.pSample = sample;
4164 flags = 0;
4165 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output_buffer, &flags);
4166 todo_wine
4167 ok(hr == S_OK || broken(FAILED(hr)) /* Win8 */, "Failed to get output buffer, hr %#lx.\n", hr);
4168 ok(output_buffer.dwStatus == 0, "Unexpected buffer status, %#lx.\n", output_buffer.dwStatus);
4169 ok(flags == 0, "Unexpected status %#lx.\n", flags);
4171 if (SUCCEEDED(hr))
4173 memset(&output_buffer, 0, sizeof(output_buffer));
4174 output_buffer.pSample = sample;
4175 flags = 0;
4176 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output_buffer, &flags);
4177 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "Unexpected hr %#lx.\n", hr);
4178 ok(output_buffer.dwStatus == 0, "Unexpected buffer status, %#lx.\n", output_buffer.dwStatus);
4179 ok(flags == 0, "Unexpected status %#lx.\n", flags);
4182 ref = IMFTransform_Release(transform);
4183 ok(ref == 0, "Release returned %ld\n", ref);
4185 ref = IMFMediaType_Release(media_type);
4186 ok(ref == 0, "Release returned %ld\n", ref);
4187 ref = IMFSample_Release(sample2);
4188 ok(ref == 0, "Release returned %ld\n", ref);
4189 ref = IMFSample_Release(sample);
4190 ok(ref == 0, "Release returned %ld\n", ref);
4191 ref = IMFMediaBuffer_Release(buffer);
4192 ok(ref == 0, "Release returned %ld\n", ref);
4194 failed:
4195 CoUninitialize();
4198 static void test_quality_manager(void)
4200 IMFPresentationClock *clock;
4201 IMFQualityManager *manager;
4202 IMFTopology *topology;
4203 HRESULT hr;
4204 LONG ref;
4206 hr = MFStartup(MF_VERSION, MFSTARTUP_FULL);
4207 ok(hr == S_OK, "Startup failure, hr %#lx.\n", hr);
4209 hr = MFCreatePresentationClock(&clock);
4210 ok(hr == S_OK, "Failed to create presentation clock, hr %#lx.\n", hr);
4212 hr = MFCreateStandardQualityManager(&manager);
4213 ok(hr == S_OK, "Failed to create quality manager, hr %#lx.\n", hr);
4215 check_interface(manager, &IID_IMFQualityManager, TRUE);
4216 check_interface(manager, &IID_IMFClockStateSink, TRUE);
4218 hr = IMFQualityManager_NotifyPresentationClock(manager, NULL);
4219 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
4221 hr = IMFQualityManager_NotifyTopology(manager, NULL);
4222 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4224 /* Set clock, then shutdown. */
4225 EXPECT_REF(clock, 1);
4226 EXPECT_REF(manager, 1);
4227 hr = IMFQualityManager_NotifyPresentationClock(manager, clock);
4228 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4229 EXPECT_REF(clock, 2);
4230 EXPECT_REF(manager, 2);
4232 hr = IMFQualityManager_Shutdown(manager);
4233 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4234 EXPECT_REF(clock, 1);
4236 hr = IMFQualityManager_NotifyPresentationClock(manager, clock);
4237 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
4239 hr = IMFQualityManager_NotifyTopology(manager, NULL);
4240 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
4242 hr = IMFQualityManager_NotifyPresentationClock(manager, NULL);
4243 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
4245 hr = IMFQualityManager_Shutdown(manager);
4246 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4248 ref = IMFQualityManager_Release(manager);
4249 ok(ref == 0, "Release returned %ld\n", ref);
4251 hr = MFCreateStandardQualityManager(&manager);
4252 ok(hr == S_OK, "Failed to create quality manager, hr %#lx.\n", hr);
4254 EXPECT_REF(clock, 1);
4255 EXPECT_REF(manager, 1);
4256 hr = IMFQualityManager_NotifyPresentationClock(manager, clock);
4257 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4258 EXPECT_REF(manager, 2);
4259 EXPECT_REF(clock, 2);
4260 hr = IMFQualityManager_Shutdown(manager);
4261 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4263 ref = IMFQualityManager_Release(manager);
4264 ok(ref == 0, "Release returned %ld\n", ref);
4265 ref = IMFPresentationClock_Release(clock);
4266 ok(ref == 0, "Release returned %ld\n", ref);
4268 /* Set topology. */
4269 hr = MFCreateStandardQualityManager(&manager);
4270 ok(hr == S_OK, "Failed to create quality manager, hr %#lx.\n", hr);
4272 hr = MFCreateTopology(&topology);
4273 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4275 EXPECT_REF(topology, 1);
4276 hr = IMFQualityManager_NotifyTopology(manager, topology);
4277 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4278 EXPECT_REF(topology, 2);
4280 hr = IMFQualityManager_NotifyTopology(manager, NULL);
4281 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4282 EXPECT_REF(topology, 1);
4284 hr = IMFQualityManager_NotifyTopology(manager, topology);
4285 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4287 EXPECT_REF(topology, 2);
4288 hr = IMFQualityManager_Shutdown(manager);
4289 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4290 EXPECT_REF(topology, 1);
4292 hr = IMFQualityManager_NotifyTopology(manager, topology);
4293 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
4295 ref = IMFQualityManager_Release(manager);
4296 ok(ref == 0, "Release returned %ld\n", ref);
4298 hr = MFCreateStandardQualityManager(&manager);
4299 ok(hr == S_OK, "Failed to create quality manager, hr %#lx.\n", hr);
4301 EXPECT_REF(topology, 1);
4302 hr = IMFQualityManager_NotifyTopology(manager, topology);
4303 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4304 EXPECT_REF(topology, 2);
4306 ref = IMFQualityManager_Release(manager);
4307 ok(ref == 0, "Release returned %ld\n", ref);
4308 ref = IMFTopology_Release(topology);
4309 ok(ref == 0, "Release returned %ld\n", ref);
4311 hr = MFShutdown();
4312 ok(hr == S_OK, "Shutdown failure, hr %#lx.\n", hr);
4315 static void check_sar_rate_support(IMFMediaSink *sink)
4317 IMFRateSupport *rate_support;
4318 IMFMediaTypeHandler *handler;
4319 IMFStreamSink *stream_sink;
4320 IMFMediaType *media_type;
4321 HRESULT hr;
4322 float rate;
4324 hr = IMFMediaSink_QueryInterface(sink, &IID_IMFRateSupport, (void **)&rate_support);
4325 todo_wine
4326 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4327 if (FAILED(hr)) return;
4329 hr = IMFMediaSink_GetStreamSinkByIndex(sink, 0, &stream_sink);
4330 if (hr == MF_E_SHUTDOWN)
4332 hr = IMFRateSupport_GetSlowestRate(rate_support, MFRATE_FORWARD, FALSE, NULL);
4333 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
4335 hr = IMFRateSupport_GetSlowestRate(rate_support, MFRATE_FORWARD, FALSE, &rate);
4336 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
4338 hr = IMFRateSupport_GetFastestRate(rate_support, MFRATE_FORWARD, FALSE, &rate);
4339 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
4341 IMFRateSupport_Release(rate_support);
4342 return;
4344 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4346 hr = IMFStreamSink_GetMediaTypeHandler(stream_sink, &handler);
4347 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4349 IMFStreamSink_Release(stream_sink);
4351 hr = IMFRateSupport_GetSlowestRate(rate_support, MFRATE_FORWARD, FALSE, NULL);
4352 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
4354 hr = IMFRateSupport_GetFastestRate(rate_support, MFRATE_FORWARD, FALSE, NULL);
4355 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
4357 hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, &media_type);
4358 if (SUCCEEDED(hr))
4360 hr = IMFRateSupport_GetSlowestRate(rate_support, MFRATE_FORWARD, FALSE, &rate);
4361 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4363 hr = IMFRateSupport_GetSlowestRate(rate_support, MFRATE_FORWARD, TRUE, &rate);
4364 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4366 hr = IMFRateSupport_GetSlowestRate(rate_support, MFRATE_REVERSE, FALSE, &rate);
4367 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4369 hr = IMFRateSupport_GetSlowestRate(rate_support, MFRATE_REVERSE, TRUE, &rate);
4370 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4372 hr = IMFRateSupport_GetFastestRate(rate_support, MFRATE_FORWARD, FALSE, &rate);
4373 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4375 hr = IMFRateSupport_GetFastestRate(rate_support, MFRATE_FORWARD, TRUE, &rate);
4376 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4378 hr = IMFRateSupport_GetFastestRate(rate_support, MFRATE_REVERSE, FALSE, &rate);
4379 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4381 hr = IMFRateSupport_GetFastestRate(rate_support, MFRATE_REVERSE, TRUE, &rate);
4382 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4384 IMFMediaType_Release(media_type);
4386 else
4388 hr = IMFRateSupport_GetSlowestRate(rate_support, MFRATE_FORWARD, FALSE, &rate);
4389 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#lx.\n", hr);
4391 hr = IMFRateSupport_GetSlowestRate(rate_support, MFRATE_FORWARD, TRUE, &rate);
4392 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#lx.\n", hr);
4394 hr = IMFRateSupport_GetSlowestRate(rate_support, MFRATE_REVERSE, FALSE, &rate);
4395 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#lx.\n", hr);
4397 hr = IMFRateSupport_GetSlowestRate(rate_support, MFRATE_REVERSE, TRUE, &rate);
4398 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#lx.\n", hr);
4400 hr = IMFRateSupport_GetFastestRate(rate_support, MFRATE_FORWARD, FALSE, &rate);
4401 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#lx.\n", hr);
4403 hr = IMFRateSupport_GetFastestRate(rate_support, MFRATE_FORWARD, TRUE, &rate);
4404 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#lx.\n", hr);
4406 hr = IMFRateSupport_GetFastestRate(rate_support, MFRATE_REVERSE, FALSE, &rate);
4407 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#lx.\n", hr);
4409 hr = IMFRateSupport_GetFastestRate(rate_support, MFRATE_REVERSE, TRUE, &rate);
4410 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#lx.\n", hr);
4413 IMFMediaTypeHandler_Release(handler);
4414 IMFRateSupport_Release(rate_support);
4417 static void test_sar(void)
4419 IMFPresentationClock *present_clock, *present_clock2;
4420 IMFMediaType *mediatype, *mediatype2, *mediatype3;
4421 IMFClockStateSink *state_sink, *state_sink2;
4422 IMFMediaTypeHandler *handler, *handler2;
4423 IMFPresentationTimeSource *time_source;
4424 IMFSimpleAudioVolume *simple_volume;
4425 IMFAudioStreamVolume *stream_volume;
4426 IMFMediaSink *sink, *sink2;
4427 IMFStreamSink *stream_sink;
4428 IMFAttributes *attributes;
4429 DWORD i, id, flags, count;
4430 IMFActivate *activate;
4431 UINT32 channel_count;
4432 MFCLOCK_STATE state;
4433 IMFClock *clock;
4434 IUnknown *unk;
4435 HRESULT hr;
4436 GUID guid;
4437 BOOL mute;
4438 int found;
4439 LONG ref;
4441 hr = CoInitialize(NULL);
4442 ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
4444 hr = MFCreateAudioRenderer(NULL, &sink);
4445 if (hr == MF_E_NO_AUDIO_PLAYBACK_DEVICE)
4447 skip("No audio playback device available.\n");
4448 CoUninitialize();
4449 return;
4451 ok(hr == S_OK, "Failed to create renderer, hr %#lx.\n", hr);
4453 hr = MFStartup(MF_VERSION, MFSTARTUP_FULL);
4454 ok(hr == S_OK, "Startup failure, hr %#lx.\n", hr);
4456 hr = MFCreatePresentationClock(&present_clock);
4457 ok(hr == S_OK, "Failed to create presentation clock, hr %#lx.\n", hr);
4459 hr = IMFMediaSink_QueryInterface(sink, &IID_IMFPresentationTimeSource, (void **)&time_source);
4460 todo_wine
4461 ok(hr == S_OK, "Failed to get time source interface, hr %#lx.\n", hr);
4463 if (SUCCEEDED(hr))
4465 hr = IMFPresentationTimeSource_QueryInterface(time_source, &IID_IMFClockStateSink, (void **)&state_sink2);
4466 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4467 hr = IMFPresentationTimeSource_QueryInterface(time_source, &IID_IMFClockStateSink, (void **)&state_sink);
4468 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4469 ok(state_sink == state_sink2, "Unexpected clock sink.\n");
4470 IMFClockStateSink_Release(state_sink2);
4471 IMFClockStateSink_Release(state_sink);
4473 hr = IMFPresentationTimeSource_GetUnderlyingClock(time_source, &clock);
4474 ok(hr == MF_E_NO_CLOCK, "Unexpected hr %#lx.\n", hr);
4476 hr = IMFPresentationTimeSource_GetClockCharacteristics(time_source, &flags);
4477 ok(hr == S_OK, "Failed to get flags, hr %#lx.\n", hr);
4478 ok(flags == MFCLOCK_CHARACTERISTICS_FLAG_FREQUENCY_10MHZ, "Unexpected flags %#lx.\n", flags);
4480 hr = IMFPresentationTimeSource_GetState(time_source, 0, &state);
4481 ok(hr == S_OK, "Failed to get clock state, hr %#lx.\n", hr);
4482 ok(state == MFCLOCK_STATE_INVALID, "Unexpected state %d.\n", state);
4484 hr = IMFPresentationTimeSource_QueryInterface(time_source, &IID_IMFClockStateSink, (void **)&state_sink);
4485 ok(hr == S_OK, "Failed to get state sink, hr %#lx.\n", hr);
4487 hr = IMFClockStateSink_OnClockStart(state_sink, 0, 0);
4488 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#lx.\n", hr);
4490 IMFClockStateSink_Release(state_sink);
4492 IMFPresentationTimeSource_Release(time_source);
4494 hr = IMFMediaSink_AddStreamSink(sink, 123, NULL, &stream_sink);
4495 ok(hr == MF_E_STREAMSINKS_FIXED, "Unexpected hr %#lx.\n", hr);
4497 hr = IMFMediaSink_RemoveStreamSink(sink, 0);
4498 ok(hr == MF_E_STREAMSINKS_FIXED, "Unexpected hr %#lx.\n", hr);
4500 hr = IMFMediaSink_GetStreamSinkCount(sink, NULL);
4501 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
4503 hr = IMFMediaSink_GetStreamSinkCount(sink, &count);
4504 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4505 ok(count == 1, "Unexpected count %lu.\n", count);
4507 hr = IMFMediaSink_GetCharacteristics(sink, &flags);
4508 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4509 ok(flags == (MEDIASINK_FIXED_STREAMS | MEDIASINK_CAN_PREROLL), "Unexpected flags %#lx.\n", flags);
4511 check_interface(sink, &IID_IMFMediaSinkPreroll, TRUE);
4512 check_interface(sink, &IID_IMFMediaEventGenerator, TRUE);
4513 check_interface(sink, &IID_IMFClockStateSink, TRUE);
4514 check_interface(sink, &IID_IMFGetService, TRUE);
4515 todo_wine check_interface(sink, &IID_IMFPresentationTimeSource, TRUE);
4516 todo_wine check_service_interface(sink, &MF_RATE_CONTROL_SERVICE, &IID_IMFRateSupport, TRUE);
4517 check_service_interface(sink, &MF_RATE_CONTROL_SERVICE, &IID_IMFRateControl, FALSE);
4518 check_service_interface(sink, &MR_POLICY_VOLUME_SERVICE, &IID_IMFSimpleAudioVolume, TRUE);
4519 check_service_interface(sink, &MR_STREAM_VOLUME_SERVICE, &IID_IMFAudioStreamVolume, TRUE);
4521 /* Clock */
4522 hr = IMFMediaSink_QueryInterface(sink, &IID_IMFClockStateSink, (void **)&state_sink);
4523 ok(hr == S_OK, "Failed to get interface, hr %#lx.\n", hr);
4525 hr = IMFClockStateSink_OnClockStart(state_sink, 0, 0);
4526 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#lx.\n", hr);
4528 hr = IMFClockStateSink_OnClockPause(state_sink, 0);
4529 ok(hr == MF_E_INVALID_STATE_TRANSITION, "Unexpected hr %#lx.\n", hr);
4531 hr = IMFClockStateSink_OnClockStop(state_sink, 0);
4532 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#lx.\n", hr);
4534 hr = IMFClockStateSink_OnClockRestart(state_sink, 0);
4535 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#lx.\n", hr);
4537 IMFClockStateSink_Release(state_sink);
4539 hr = IMFMediaSink_SetPresentationClock(sink, NULL);
4540 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4542 hr = IMFMediaSink_SetPresentationClock(sink, present_clock);
4543 todo_wine
4544 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#lx.\n", hr);
4546 hr = MFCreateSystemTimeSource(&time_source);
4547 ok(hr == S_OK, "Failed to create time source, hr %#lx.\n", hr);
4549 hr = IMFPresentationClock_SetTimeSource(present_clock, time_source);
4550 ok(hr == S_OK, "Failed to set time source, hr %#lx.\n", hr);
4551 IMFPresentationTimeSource_Release(time_source);
4553 hr = IMFMediaSink_SetPresentationClock(sink, present_clock);
4554 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4556 hr = IMFMediaSink_GetPresentationClock(sink, NULL);
4557 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
4559 hr = IMFMediaSink_GetPresentationClock(sink, &present_clock2);
4560 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4561 ok(present_clock == present_clock2, "Unexpected instance.\n");
4562 IMFPresentationClock_Release(present_clock2);
4564 /* Stream */
4565 hr = IMFMediaSink_GetStreamSinkByIndex(sink, 0, &stream_sink);
4566 ok(hr == S_OK, "Failed to get a stream, hr %#lx.\n", hr);
4568 check_interface(stream_sink, &IID_IMFMediaEventGenerator, TRUE);
4569 check_interface(stream_sink, &IID_IMFMediaTypeHandler, TRUE);
4570 todo_wine check_interface(stream_sink, &IID_IMFGetService, TRUE);
4572 hr = IMFStreamSink_GetIdentifier(stream_sink, &id);
4573 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4574 ok(!id, "Unexpected id.\n");
4576 hr = IMFStreamSink_GetMediaSink(stream_sink, &sink2);
4577 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4578 ok(sink == sink2, "Unexpected object.\n");
4579 IMFMediaSink_Release(sink2);
4581 hr = IMFStreamSink_GetMediaTypeHandler(stream_sink, &handler);
4582 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4584 hr = IMFStreamSink_QueryInterface(stream_sink, &IID_IMFMediaTypeHandler, (void **)&handler2);
4585 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4586 ok(handler2 == handler, "Unexpected instance.\n");
4587 IMFMediaTypeHandler_Release(handler2);
4589 hr = IMFMediaTypeHandler_GetMajorType(handler, &guid);
4590 ok(hr == S_OK, "Failed to get major type, hr %#lx.\n", hr);
4591 ok(IsEqualGUID(&guid, &MFMediaType_Audio), "Unexpected type %s.\n", wine_dbgstr_guid(&guid));
4593 count = 0;
4594 hr = IMFMediaTypeHandler_GetMediaTypeCount(handler, &count);
4595 ok(hr == S_OK, "Failed to get type count, hr %#lx.\n", hr);
4596 ok(!!count, "Unexpected type count %lu.\n", count);
4598 /* A number of same major/subtype entries are returned, with different degrees of finer format
4599 details. Some incomplete types are not accepted, check that at least one of them is considered supported. */
4601 for (i = 0, found = -1; i < count; ++i)
4603 hr = IMFMediaTypeHandler_GetMediaTypeByIndex(handler, i, &mediatype);
4604 ok(hr == S_OK, "Failed to get media type, hr %#lx.\n", hr);
4606 if (SUCCEEDED(IMFMediaTypeHandler_IsMediaTypeSupported(handler, mediatype, NULL)))
4607 found = i;
4608 IMFMediaType_Release(mediatype);
4610 if (found != -1) break;
4612 ok(found != -1, "Haven't found a supported type.\n");
4614 hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, &mediatype);
4615 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#lx.\n", hr);
4617 hr = MFCreateMediaType(&mediatype);
4618 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
4620 /* Actual return value is MF_E_ATRIBUTENOTFOUND triggered by missing MF_MT_MAJOR_TYPE */
4621 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, mediatype, NULL);
4622 ok(FAILED(hr), "Unexpected hr %#lx.\n", hr);
4624 hr = IMFMediaType_SetGUID(mediatype, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
4625 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4626 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, mediatype, NULL);
4627 ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#lx.\n", hr);
4629 hr = IMFMediaType_SetGUID(mediatype, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio);
4630 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4631 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, mediatype, NULL);
4632 ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#lx.\n", hr);
4634 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, mediatype);
4635 ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#lx.\n", hr);
4637 hr = IMFMediaTypeHandler_GetMediaTypeByIndex(handler, found, &mediatype2);
4638 ok(hr == S_OK, "Failed to get media type, hr %#lx.\n", hr);
4640 hr = IMFMediaTypeHandler_GetMediaTypeByIndex(handler, found, &mediatype3);
4641 ok(hr == S_OK, "Failed to get media type, hr %#lx.\n", hr);
4642 ok(mediatype2 == mediatype3, "Unexpected instance.\n");
4643 IMFMediaType_Release(mediatype3);
4645 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, mediatype2, NULL);
4646 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4648 IMFMediaType_Release(mediatype);
4650 check_sar_rate_support(sink);
4652 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, mediatype2);
4653 ok(hr == S_OK, "Failed to set current type, hr %#lx.\n", hr);
4655 check_sar_rate_support(sink);
4657 hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, &mediatype);
4658 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4659 ok(mediatype == mediatype2, "Unexpected instance.\n");
4660 IMFMediaType_Release(mediatype);
4662 IMFMediaType_Release(mediatype2);
4664 /* Reset back to uninitialized state. */
4665 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, NULL);
4666 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
4668 IMFMediaTypeHandler_Release(handler);
4670 /* State change with initialized stream. */
4671 hr = IMFMediaSink_QueryInterface(sink, &IID_IMFClockStateSink, (void **)&state_sink);
4672 ok(hr == S_OK, "Failed to get interface, hr %#lx.\n", hr);
4674 hr = IMFClockStateSink_OnClockStart(state_sink, 0, 0);
4675 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4677 hr = IMFClockStateSink_OnClockStart(state_sink, 0, 0);
4678 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4680 hr = IMFClockStateSink_OnClockPause(state_sink, 0);
4681 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4683 hr = IMFClockStateSink_OnClockStop(state_sink, 0);
4684 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4686 hr = IMFClockStateSink_OnClockStop(state_sink, 0);
4687 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4689 hr = IMFClockStateSink_OnClockPause(state_sink, 0);
4690 ok(hr == MF_E_INVALID_STATE_TRANSITION, "Unexpected hr %#lx.\n", hr);
4692 hr = IMFClockStateSink_OnClockRestart(state_sink, 0);
4693 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4695 hr = IMFClockStateSink_OnClockRestart(state_sink, 0);
4696 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4698 hr = IMFClockStateSink_OnClockStop(state_sink, 0);
4699 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4701 IMFClockStateSink_Release(state_sink);
4703 IMFStreamSink_Release(stream_sink);
4705 /* Volume control */
4706 hr = MFGetService((IUnknown *)sink, &MR_POLICY_VOLUME_SERVICE, &IID_IMFSimpleAudioVolume, (void **)&simple_volume);
4707 ok(hr == S_OK, "Failed to get interface, hr %#lx.\n", hr);
4709 hr = IMFSimpleAudioVolume_GetMute(simple_volume, &mute);
4710 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4712 IMFSimpleAudioVolume_Release(simple_volume);
4714 hr = MFGetService((IUnknown *)sink, &MR_STREAM_VOLUME_SERVICE, &IID_IMFAudioStreamVolume, (void **)&stream_volume);
4715 ok(hr == S_OK, "Failed to get interface, hr %#lx.\n", hr);
4717 hr = IMFAudioStreamVolume_GetChannelCount(stream_volume, &channel_count);
4718 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4720 hr = IMFAudioStreamVolume_GetChannelCount(stream_volume, NULL);
4721 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
4723 IMFAudioStreamVolume_Release(stream_volume);
4725 hr = MFGetService((IUnknown *)sink, &MR_AUDIO_POLICY_SERVICE, &IID_IMFAudioPolicy, (void **)&unk);
4726 ok(hr == S_OK, "Failed to get interface, hr %#lx.\n", hr);
4727 IUnknown_Release(unk);
4729 /* Shutdown */
4730 EXPECT_REF(present_clock, 2);
4731 hr = IMFMediaSink_Shutdown(sink);
4732 ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr);
4733 EXPECT_REF(present_clock, 1);
4735 hr = IMFMediaSink_Shutdown(sink);
4736 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
4738 hr = IMFMediaSink_AddStreamSink(sink, 123, NULL, &stream_sink);
4739 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
4741 hr = IMFMediaSink_RemoveStreamSink(sink, 0);
4742 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
4744 hr = IMFMediaSink_GetStreamSinkCount(sink, NULL);
4745 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
4747 hr = IMFMediaSink_GetStreamSinkCount(sink, &count);
4748 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
4750 hr = IMFMediaSink_GetCharacteristics(sink, &flags);
4751 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
4753 hr = IMFMediaSink_SetPresentationClock(sink, NULL);
4754 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
4756 hr = IMFMediaSink_SetPresentationClock(sink, present_clock);
4757 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
4759 hr = IMFMediaSink_GetPresentationClock(sink, NULL);
4760 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
4762 hr = IMFMediaSink_GetPresentationClock(sink, &present_clock2);
4763 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
4765 check_sar_rate_support(sink);
4767 ref = IMFMediaSink_Release(sink);
4768 todo_wine
4769 ok(ref == 0, "Release returned %ld\n", ref);
4771 /* Activation */
4772 hr = MFCreateAudioRendererActivate(&activate);
4773 ok(hr == S_OK, "Failed to create activation object, hr %#lx.\n", hr);
4775 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink);
4776 ok(hr == S_OK, "Failed to activate, hr %#lx.\n", hr);
4778 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink2);
4779 ok(hr == S_OK, "Failed to activate, hr %#lx.\n", hr);
4780 ok(sink == sink2, "Unexpected instance.\n");
4781 IMFMediaSink_Release(sink2);
4783 hr = IMFMediaSink_GetCharacteristics(sink, &flags);
4784 ok(hr == S_OK, "Failed to get sink flags, hr %#lx.\n", hr);
4786 hr = IMFActivate_ShutdownObject(activate);
4787 ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr);
4789 hr = IMFMediaSink_GetCharacteristics(sink, &flags);
4790 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
4792 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink2);
4793 ok(hr == S_OK, "Failed to activate, hr %#lx.\n", hr);
4794 todo_wine
4795 ok(sink == sink2, "Unexpected instance.\n");
4797 hr = IMFMediaSink_GetCharacteristics(sink2, &flags);
4798 todo_wine
4799 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
4801 IMFMediaSink_Release(sink2);
4803 hr = IMFActivate_DetachObject(activate);
4804 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
4806 hr = IMFActivate_ShutdownObject(activate);
4807 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4809 ref = IMFActivate_Release(activate);
4810 ok(ref == 0, "Release returned %ld\n", ref);
4811 ref = IMFMediaSink_Release(sink);
4812 ok(ref == 0, "Release returned %ld\n", ref);
4814 ref = IMFPresentationClock_Release(present_clock);
4815 ok(ref == 0, "Release returned %ld\n", ref);
4817 hr = MFShutdown();
4818 ok(hr == S_OK, "Shutdown failure, hr %#lx.\n", hr);
4820 /* SAR attributes */
4821 hr = MFCreateAttributes(&attributes, 0);
4822 ok(hr == S_OK, "Failed to create attributes, hr %#lx.\n", hr);
4824 /* Specify role. */
4825 hr = IMFAttributes_SetUINT32(attributes, &MF_AUDIO_RENDERER_ATTRIBUTE_ENDPOINT_ROLE, eMultimedia);
4826 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
4828 hr = MFCreateAudioRenderer(attributes, &sink);
4829 ok(hr == S_OK, "Failed to create a sink, hr %#lx.\n", hr);
4831 /* required for the sink to be fully released */
4832 hr = IMFMediaSink_Shutdown(sink);
4833 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4835 ref = IMFMediaSink_Release(sink);
4836 ok(ref == 0, "Release returned %ld\n", ref);
4838 /* Invalid endpoint. */
4839 hr = IMFAttributes_SetString(attributes, &MF_AUDIO_RENDERER_ATTRIBUTE_ENDPOINT_ID, L"endpoint");
4840 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
4842 hr = MFCreateAudioRenderer(attributes, &sink);
4843 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
4845 hr = IMFAttributes_DeleteItem(attributes, &MF_AUDIO_RENDERER_ATTRIBUTE_ENDPOINT_ROLE);
4846 ok(hr == S_OK, "Failed to remove attribute, hr %#lx.\n", hr);
4848 hr = MFCreateAudioRenderer(attributes, &sink);
4849 ok(hr == MF_E_NO_AUDIO_PLAYBACK_DEVICE, "Failed to create a sink, hr %#lx.\n", hr);
4851 ref = IMFAttributes_Release(attributes);
4852 ok(ref == 0, "Release returned %ld\n", ref);
4854 CoUninitialize();
4857 static void test_evr(void)
4859 static const float supported_rates[] =
4861 0.0f, 1.0f, -20.0f, 20.0f, 1000.0f, -1000.0f,
4863 IMFVideoSampleAllocatorCallback *allocator_callback;
4864 IMFStreamSink *stream_sink, *stream_sink2;
4865 IMFVideoDisplayControl *display_control;
4866 IMFMediaType *media_type, *media_type2;
4867 IMFPresentationTimeSource *time_source;
4868 IMFVideoSampleAllocator *allocator;
4869 IMFMediaTypeHandler *type_handler;
4870 IMFVideoRenderer *video_renderer;
4871 IMFPresentationClock *clock;
4872 IMFMediaSink *sink, *sink2;
4873 IMFAttributes *attributes;
4874 UINT32 attr_count, value;
4875 IMFActivate *activate;
4876 HWND window, window2;
4877 IMFRateSupport *rs;
4878 DWORD flags, count;
4879 LONG sample_count;
4880 IMFSample *sample;
4881 unsigned int i;
4882 UINT64 window3;
4883 float rate;
4884 HRESULT hr;
4885 GUID guid;
4886 LONG ref;
4888 hr = MFStartup(MF_VERSION, MFSTARTUP_FULL);
4889 ok(hr == S_OK, "Startup failure, hr %#lx.\n", hr);
4891 hr = MFCreateVideoRenderer(&IID_IMFVideoRenderer, (void **)&video_renderer);
4892 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4894 hr = IMFVideoRenderer_InitializeRenderer(video_renderer, NULL, NULL);
4895 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4897 /* required for the video renderer to be fully released */
4898 hr = IMFVideoRenderer_QueryInterface(video_renderer, &IID_IMFMediaSink, (void **)&sink);
4899 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4900 hr = IMFMediaSink_Shutdown(sink);
4901 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4902 IMFMediaSink_Release(sink);
4904 ref = IMFVideoRenderer_Release(video_renderer);
4905 ok(ref == 0, "Release returned %ld\n", ref);
4907 hr = MFCreateVideoRendererActivate(NULL, NULL);
4908 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
4910 /* Window */
4911 window = create_window();
4912 hr = MFCreateVideoRendererActivate(window, &activate);
4913 ok(hr == S_OK, "Failed to create activate object, hr %#lx.\n", hr);
4915 hr = IMFActivate_GetUINT64(activate, &MF_ACTIVATE_VIDEO_WINDOW, &window3);
4916 ok(hr == S_OK, "Failed to get attribute, hr %#lx.\n", hr);
4917 ok(UlongToHandle(window3) == window, "Unexpected value.\n");
4919 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink);
4920 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4922 check_interface(sink, &IID_IMFMediaSinkPreroll, TRUE);
4923 check_interface(sink, &IID_IMFVideoRenderer, TRUE);
4924 check_interface(sink, &IID_IMFMediaEventGenerator, TRUE);
4925 check_interface(sink, &IID_IMFClockStateSink, TRUE);
4926 check_interface(sink, &IID_IMFGetService, TRUE);
4927 check_interface(sink, &IID_IMFQualityAdvise, TRUE);
4928 check_interface(sink, &IID_IMFRateSupport, TRUE);
4929 check_interface(sink, &IID_IMFRateControl, FALSE);
4930 check_service_interface(sink, &MR_VIDEO_MIXER_SERVICE, &IID_IMFVideoProcessor, TRUE);
4931 check_service_interface(sink, &MR_VIDEO_MIXER_SERVICE, &IID_IMFVideoMixerBitmap, TRUE);
4932 check_service_interface(sink, &MR_VIDEO_MIXER_SERVICE, &IID_IMFVideoMixerControl, TRUE);
4933 check_service_interface(sink, &MR_VIDEO_MIXER_SERVICE, &IID_IMFVideoMixerControl2, TRUE);
4934 check_service_interface(sink, &MR_VIDEO_RENDER_SERVICE, &IID_IMFVideoDisplayControl, TRUE);
4935 check_service_interface(sink, &MR_VIDEO_RENDER_SERVICE, &IID_IMFVideoPositionMapper, TRUE);
4936 check_service_interface(sink, &MR_VIDEO_ACCELERATION_SERVICE, &IID_IMFVideoSampleAllocator, FALSE);
4937 check_service_interface(sink, &MR_VIDEO_ACCELERATION_SERVICE, &IID_IDirect3DDeviceManager9, TRUE);
4938 check_service_interface(sink, &MF_RATE_CONTROL_SERVICE, &IID_IMFRateSupport, TRUE);
4940 hr = MFGetService((IUnknown *)sink, &MR_VIDEO_RENDER_SERVICE, &IID_IMFVideoDisplayControl,
4941 (void **)&display_control);
4942 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4944 window2 = NULL;
4945 hr = IMFVideoDisplayControl_GetVideoWindow(display_control, &window2);
4946 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4947 ok(window2 == window, "Unexpected window %p.\n", window2);
4949 IMFVideoDisplayControl_Release(display_control);
4951 hr = IMFActivate_ShutdownObject(activate);
4952 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4954 ref = IMFActivate_Release(activate);
4955 ok(ref == 0, "Release returned %ld\n", ref);
4956 ref = IMFMediaSink_Release(sink);
4957 ok(ref == 0, "Release returned %ld\n", ref);
4958 DestroyWindow(window);
4960 hr = MFCreateVideoRendererActivate(NULL, &activate);
4961 ok(hr == S_OK, "Failed to create activate object, hr %#lx.\n", hr);
4963 hr = IMFActivate_GetCount(activate, &attr_count);
4964 ok(hr == S_OK, "Failed to get attribute count, hr %#lx.\n", hr);
4965 ok(attr_count == 1, "Unexpected count %u.\n", attr_count);
4967 hr = IMFActivate_GetUINT64(activate, &MF_ACTIVATE_VIDEO_WINDOW, &window3);
4968 ok(hr == S_OK, "Failed to get attribute, hr %#lx.\n", hr);
4969 ok(!window3, "Unexpected value.\n");
4971 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink);
4972 ok(hr == S_OK, "Failed to activate, hr %#lx.\n", hr);
4974 hr = IMFMediaSink_QueryInterface(sink, &IID_IMFAttributes, (void **)&attributes);
4975 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4976 check_interface(attributes, &IID_IMFMediaSink, TRUE);
4978 hr = IMFAttributes_GetCount(attributes, &attr_count);
4979 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4980 ok(!!attr_count, "Unexpected count %u.\n", attr_count);
4981 /* Rendering preferences are not immediately propagated to the presenter. */
4982 hr = IMFAttributes_SetUINT32(attributes, &EVRConfig_ForceBob, 1);
4983 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4984 hr = MFGetService((IUnknown *)sink, &MR_VIDEO_RENDER_SERVICE, &IID_IMFVideoDisplayControl, (void **)&display_control);
4985 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4986 hr = IMFVideoDisplayControl_GetRenderingPrefs(display_control, &flags);
4987 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4988 ok(!flags, "Unexpected flags %#lx.\n", flags);
4989 IMFVideoDisplayControl_Release(display_control);
4990 IMFAttributes_Release(attributes);
4992 /* Primary stream type handler. */
4993 hr = IMFMediaSink_GetStreamSinkById(sink, 0, &stream_sink);
4994 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4996 hr = IMFStreamSink_QueryInterface(stream_sink, &IID_IMFAttributes, (void **)&attributes);
4997 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4998 hr = IMFAttributes_GetCount(attributes, &attr_count);
4999 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5000 ok(attr_count == 2, "Unexpected count %u.\n", attr_count);
5001 value = 0;
5002 hr = IMFAttributes_GetUINT32(attributes, &MF_SA_REQUIRED_SAMPLE_COUNT, &value);
5003 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5004 ok(value == 1, "Unexpected attribute value %u.\n", value);
5005 value = 0;
5006 hr = IMFAttributes_GetUINT32(attributes, &MF_SA_D3D_AWARE, &value);
5007 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5008 ok(value == 1, "Unexpected attribute value %u.\n", value);
5010 check_interface(attributes, &IID_IMFStreamSink, TRUE);
5011 IMFAttributes_Release(attributes);
5013 hr = IMFStreamSink_GetMediaTypeHandler(stream_sink, &type_handler);
5014 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5016 hr = IMFMediaTypeHandler_GetMajorType(type_handler, NULL);
5017 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
5019 hr = IMFMediaTypeHandler_GetMajorType(type_handler, &guid);
5020 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5021 ok(IsEqualGUID(&guid, &MFMediaType_Video), "Unexpected type %s.\n", wine_dbgstr_guid(&guid));
5023 /* Supported types are not advertised. */
5024 hr = IMFMediaTypeHandler_GetMediaTypeCount(type_handler, NULL);
5025 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
5027 count = 1;
5028 hr = IMFMediaTypeHandler_GetMediaTypeCount(type_handler, &count);
5029 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5030 ok(!count, "Unexpected count %lu.\n", count);
5032 hr = IMFMediaTypeHandler_GetMediaTypeByIndex(type_handler, 0, NULL);
5033 ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#lx.\n", hr);
5035 hr = IMFMediaTypeHandler_GetMediaTypeByIndex(type_handler, 0, &media_type);
5036 ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#lx.\n", hr);
5038 hr = IMFMediaTypeHandler_GetCurrentMediaType(type_handler, NULL);
5039 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
5041 hr = IMFMediaTypeHandler_GetCurrentMediaType(type_handler, &media_type);
5042 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
5044 hr = IMFMediaTypeHandler_SetCurrentMediaType(type_handler, NULL);
5045 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
5047 hr = MFCreateMediaType(&media_type);
5048 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5050 hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
5051 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5053 hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFVideoFormat_RGB32);
5054 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5056 hr = IMFMediaType_SetUINT64(media_type, &MF_MT_FRAME_SIZE, (UINT64)640 << 32 | 480);
5057 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5059 hr = IMFMediaTypeHandler_IsMediaTypeSupported(type_handler, NULL, NULL);
5060 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
5062 hr = IMFMediaTypeHandler_IsMediaTypeSupported(type_handler, media_type, &media_type2);
5063 ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#lx.\n", hr);
5065 hr = IMFMediaType_SetUINT32(media_type, &MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE);
5066 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5068 media_type2 = (void *)0x1;
5069 hr = IMFMediaTypeHandler_IsMediaTypeSupported(type_handler, media_type, &media_type2);
5070 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5071 ok(!media_type2, "Unexpected media type %p.\n", media_type2);
5073 hr = IMFMediaTypeHandler_SetCurrentMediaType(type_handler, media_type);
5074 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5076 hr = IMFMediaTypeHandler_GetCurrentMediaType(type_handler, &media_type2);
5077 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5078 check_interface(media_type2, &IID_IMFVideoMediaType, TRUE);
5079 IMFMediaType_Release(media_type2);
5081 IMFMediaType_Release(media_type);
5083 IMFMediaTypeHandler_Release(type_handler);
5085 /* Stream uses an allocator. */
5086 check_service_interface(stream_sink, &MR_VIDEO_ACCELERATION_SERVICE, &IID_IMFVideoSampleAllocator, TRUE);
5087 check_service_interface(stream_sink, &MR_VIDEO_ACCELERATION_SERVICE, &IID_IDirect3DDeviceManager9, TRUE);
5088 todo_wine {
5089 check_service_interface(stream_sink, &MR_VIDEO_MIXER_SERVICE, &IID_IMFVideoProcessor, TRUE);
5090 check_service_interface(stream_sink, &MR_VIDEO_MIXER_SERVICE, &IID_IMFVideoMixerBitmap, TRUE);
5091 check_service_interface(stream_sink, &MR_VIDEO_MIXER_SERVICE, &IID_IMFVideoMixerControl, TRUE);
5092 check_service_interface(stream_sink, &MR_VIDEO_MIXER_SERVICE, &IID_IMFVideoMixerControl2, TRUE);
5093 check_service_interface(stream_sink, &MR_VIDEO_RENDER_SERVICE, &IID_IMFVideoDisplayControl, TRUE);
5094 check_service_interface(stream_sink, &MR_VIDEO_RENDER_SERVICE, &IID_IMFVideoPositionMapper, TRUE);
5095 check_service_interface(stream_sink, &MF_RATE_CONTROL_SERVICE, &IID_IMFRateSupport, TRUE);
5097 hr = MFGetService((IUnknown *)stream_sink, &MR_VIDEO_ACCELERATION_SERVICE, &IID_IMFVideoSampleAllocator,
5098 (void **)&allocator);
5099 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5101 hr = IMFVideoSampleAllocator_QueryInterface(allocator, &IID_IMFVideoSampleAllocatorCallback, (void **)&allocator_callback);
5102 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5104 sample_count = 0;
5105 hr = IMFVideoSampleAllocatorCallback_GetFreeSampleCount(allocator_callback, &sample_count);
5106 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5107 ok(!sample_count, "Unexpected sample count %ld.\n", sample_count);
5109 hr = IMFVideoSampleAllocator_AllocateSample(allocator, &sample);
5110 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#lx.\n", hr);
5112 IMFVideoSampleAllocatorCallback_Release(allocator_callback);
5113 IMFVideoSampleAllocator_Release(allocator);
5114 IMFStreamSink_Release(stream_sink);
5116 /* Same test for a substream. */
5117 hr = IMFMediaSink_AddStreamSink(sink, 1, NULL, &stream_sink2);
5118 ok(hr == S_OK || broken(hr == E_INVALIDARG), "Unexpected hr %#lx.\n", hr);
5120 if (SUCCEEDED(hr))
5122 hr = MFGetService((IUnknown *)stream_sink2, &MR_VIDEO_ACCELERATION_SERVICE, &IID_IMFVideoSampleAllocator,
5123 (void **)&allocator);
5124 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5125 IMFVideoSampleAllocator_Release(allocator);
5127 hr = IMFMediaSink_RemoveStreamSink(sink, 1);
5128 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5130 ref = IMFStreamSink_Release(stream_sink2);
5131 ok(ref == 0, "Release returned %ld\n", ref);
5134 hr = IMFMediaSink_GetCharacteristics(sink, &flags);
5135 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5136 ok(flags == (MEDIASINK_CAN_PREROLL | MEDIASINK_CLOCK_REQUIRED), "Unexpected flags %#lx.\n", flags);
5138 hr = IMFActivate_ShutdownObject(activate);
5139 ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr);
5141 hr = IMFMediaSink_GetCharacteristics(sink, &flags);
5142 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
5144 /* Activate again. */
5145 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink2);
5146 ok(hr == S_OK, "Failed to activate, hr %#lx.\n", hr);
5147 todo_wine
5148 ok(sink == sink2, "Unexpected instance.\n");
5149 IMFMediaSink_Release(sink2);
5151 hr = IMFActivate_DetachObject(activate);
5152 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
5154 hr = IMFMediaSink_GetCharacteristics(sink, &flags);
5155 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
5157 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink2);
5158 ok(hr == S_OK, "Failed to activate, hr %#lx.\n", hr);
5159 todo_wine
5160 ok(sink == sink2, "Unexpected instance.\n");
5161 IMFMediaSink_Release(sink2);
5163 hr = IMFActivate_ShutdownObject(activate);
5164 ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr);
5166 ref = IMFActivate_Release(activate);
5167 ok(ref == 0, "Release returned %ld\n", ref);
5168 ref = IMFMediaSink_Release(sink);
5169 todo_wine
5170 ok(ref == 0, "Release returned %ld\n", ref);
5172 /* Set clock. */
5173 window = create_window();
5175 hr = MFCreateVideoRendererActivate(window, &activate);
5176 ok(hr == S_OK, "Failed to create activate object, hr %#lx.\n", hr);
5178 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink);
5179 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5180 ref = IMFActivate_Release(activate);
5181 ok(ref == 0, "Release returned %ld\n", ref);
5183 hr = MFCreateSystemTimeSource(&time_source);
5184 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5186 hr = MFCreatePresentationClock(&clock);
5187 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5189 hr = IMFPresentationClock_SetTimeSource(clock, time_source);
5190 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5191 IMFPresentationTimeSource_Release(time_source);
5193 hr = IMFMediaSink_SetPresentationClock(sink, clock);
5194 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5196 hr = IMFMediaSink_QueryInterface(sink, &IID_IMFRateSupport, (void **)&rs);
5197 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5199 rate = 1.0f;
5200 hr = IMFRateSupport_GetSlowestRate(rs, MFRATE_FORWARD, FALSE, &rate);
5201 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5202 ok(rate == 0.0f, "Unexpected rate %f.\n", rate);
5204 rate = 1.0f;
5205 hr = IMFRateSupport_GetSlowestRate(rs, MFRATE_REVERSE, FALSE, &rate);
5206 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5207 ok(rate == 0.0f, "Unexpected rate %f.\n", rate);
5209 rate = 1.0f;
5210 hr = IMFRateSupport_GetSlowestRate(rs, MFRATE_FORWARD, TRUE, &rate);
5211 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5212 ok(rate == 0.0f, "Unexpected rate %f.\n", rate);
5214 rate = 1.0f;
5215 hr = IMFRateSupport_GetSlowestRate(rs, MFRATE_REVERSE, TRUE, &rate);
5216 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5217 ok(rate == 0.0f, "Unexpected rate %f.\n", rate);
5219 hr = IMFRateSupport_GetFastestRate(rs, MFRATE_FORWARD, FALSE, &rate);
5220 ok(hr == MF_E_INVALIDREQUEST, "Unexpected hr %#lx.\n", hr);
5222 hr = IMFRateSupport_GetFastestRate(rs, MFRATE_REVERSE, FALSE, &rate);
5223 ok(hr == MF_E_INVALIDREQUEST, "Unexpected hr %#lx.\n", hr);
5225 hr = IMFRateSupport_GetFastestRate(rs, MFRATE_FORWARD, TRUE, &rate);
5226 ok(hr == MF_E_INVALIDREQUEST, "Unexpected hr %#lx.\n", hr);
5228 hr = IMFRateSupport_GetFastestRate(rs, MFRATE_REVERSE, TRUE, &rate);
5229 ok(hr == MF_E_INVALIDREQUEST, "Unexpected hr %#lx.\n", hr);
5231 hr = IMFRateSupport_GetFastestRate(rs, MFRATE_REVERSE, TRUE, NULL);
5232 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
5234 for (i = 0; i < ARRAY_SIZE(supported_rates); ++i)
5236 rate = supported_rates[i] + 1.0f;
5237 hr = IMFRateSupport_IsRateSupported(rs, TRUE, supported_rates[i], &rate);
5238 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5239 ok(rate == supported_rates[i], "Unexpected rate %f.\n", rate);
5241 rate = supported_rates[i] + 1.0f;
5242 hr = IMFRateSupport_IsRateSupported(rs, FALSE, supported_rates[i], &rate);
5243 ok(hr == MF_E_INVALIDREQUEST, "Unexpected hr %#lx.\n", hr);
5244 ok(rate == supported_rates[i], "Unexpected rate %f.\n", rate);
5246 hr = IMFRateSupport_IsRateSupported(rs, TRUE, supported_rates[i], NULL);
5247 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5249 hr = IMFRateSupport_IsRateSupported(rs, FALSE, supported_rates[i], NULL);
5250 ok(hr == MF_E_INVALIDREQUEST, "Unexpected hr %#lx.\n", hr);
5253 /* Configuring stream type make rate support work. */
5254 hr = IMFMediaSink_GetStreamSinkById(sink, 0, &stream_sink);
5255 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5256 hr = IMFStreamSink_GetMediaTypeHandler(stream_sink, &type_handler);
5257 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5258 hr = MFCreateMediaType(&media_type);
5259 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5260 hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
5261 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5262 hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFVideoFormat_RGB32);
5263 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5264 hr = IMFMediaType_SetUINT64(media_type, &MF_MT_FRAME_SIZE, (UINT64)64 << 32 | 64);
5265 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5266 hr = IMFMediaType_SetUINT32(media_type, &MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE);
5267 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5268 hr = IMFMediaTypeHandler_SetCurrentMediaType(type_handler, media_type);
5269 ok(hr == S_OK, "Failed to set current type, hr %#lx.\n", hr);
5270 IMFMediaType_Release(media_type);
5271 IMFMediaTypeHandler_Release(type_handler);
5272 IMFStreamSink_Release(stream_sink);
5274 rate = 1.0f;
5275 hr = IMFRateSupport_GetSlowestRate(rs, MFRATE_FORWARD, TRUE, &rate);
5276 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5277 ok(rate == 0.0f, "Unexpected rate %f.\n", rate);
5279 rate = 1.0f;
5280 hr = IMFRateSupport_GetSlowestRate(rs, MFRATE_REVERSE, TRUE, &rate);
5281 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5282 ok(rate == 0.0f, "Unexpected rate %f.\n", rate);
5284 rate = 0.0f;
5285 hr = IMFRateSupport_GetFastestRate(rs, MFRATE_FORWARD, TRUE, &rate);
5286 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5287 ok(rate == FLT_MAX, "Unexpected rate %f.\n", rate);
5289 rate = 0.0f;
5290 hr = IMFRateSupport_GetFastestRate(rs, MFRATE_REVERSE, TRUE, &rate);
5291 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5292 ok(rate == -FLT_MAX, "Unexpected rate %f.\n", rate);
5294 hr = IMFRateSupport_GetFastestRate(rs, MFRATE_REVERSE, TRUE, NULL);
5295 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
5297 hr = IMFRateSupport_GetSlowestRate(rs, MFRATE_REVERSE, TRUE, NULL);
5298 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
5300 for (i = 0; i < ARRAY_SIZE(supported_rates); ++i)
5302 rate = supported_rates[i] + 1.0f;
5303 hr = IMFRateSupport_IsRateSupported(rs, TRUE, supported_rates[i], &rate);
5304 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5305 ok(rate == supported_rates[i], "Unexpected rate %f.\n", rate);
5307 rate = supported_rates[i] + 1.0f;
5308 hr = IMFRateSupport_IsRateSupported(rs, FALSE, supported_rates[i], &rate);
5309 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5310 ok(rate == supported_rates[i], "Unexpected rate %f.\n", rate);
5312 hr = IMFRateSupport_IsRateSupported(rs, TRUE, supported_rates[i], NULL);
5313 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5315 hr = IMFRateSupport_IsRateSupported(rs, FALSE, supported_rates[i], NULL);
5316 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5319 hr = IMFMediaSink_Shutdown(sink);
5320 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5322 hr = IMFMediaSink_GetStreamSinkCount(sink, NULL);
5323 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
5325 hr = IMFMediaSink_GetStreamSinkCount(sink, &count);
5326 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
5328 hr = IMFRateSupport_GetSlowestRate(rs, MFRATE_FORWARD, FALSE, &rate);
5329 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
5331 hr = IMFRateSupport_GetFastestRate(rs, MFRATE_FORWARD, FALSE, &rate);
5332 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
5334 hr = IMFRateSupport_GetSlowestRate(rs, MFRATE_FORWARD, FALSE, NULL);
5335 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
5337 hr = IMFRateSupport_GetFastestRate(rs, MFRATE_FORWARD, FALSE, NULL);
5338 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
5340 hr = IMFRateSupport_IsRateSupported(rs, TRUE, 1.0f, &rate);
5341 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
5343 ref = IMFRateSupport_Release(rs);
5344 ok(ref == 1, "Release returned %ld\n", ref);
5345 ref = IMFMediaSink_Release(sink);
5346 ok(ref == 0, "Release returned %ld\n", ref);
5347 ref = IMFPresentationClock_Release(clock);
5348 ok(ref == 0, "Release returned %ld\n", ref);
5350 DestroyWindow(window);
5352 hr = MFShutdown();
5353 ok(hr == S_OK, "Shutdown failure, hr %#lx.\n", hr);
5356 static void test_MFCreateSimpleTypeHandler(void)
5358 IMFMediaType *media_type, *media_type2, *media_type3;
5359 IMFMediaTypeHandler *handler;
5360 DWORD count;
5361 HRESULT hr;
5362 GUID guid;
5363 LONG ref;
5365 hr = MFCreateSimpleTypeHandler(&handler);
5366 ok(hr == S_OK, "Failed to create object, hr %#lx.\n", hr);
5368 hr = IMFMediaTypeHandler_GetMediaTypeCount(handler, NULL);
5369 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
5371 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, NULL, NULL);
5372 ok(hr == MF_E_UNEXPECTED, "Unexpected hr %#lx.\n", hr);
5374 count = 0;
5375 hr = IMFMediaTypeHandler_GetMediaTypeCount(handler, &count);
5376 ok(hr == S_OK, "Failed to get type count, hr %#lx.\n", hr);
5377 ok(count == 1, "Unexpected count %lu.\n", count);
5379 hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, NULL);
5380 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
5382 media_type = (void *)0xdeadbeef;
5383 hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, &media_type);
5384 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5385 ok(!media_type, "Unexpected pointer.\n");
5387 hr = MFCreateMediaType(&media_type);
5388 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
5390 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type, NULL);
5391 ok(hr == MF_E_UNEXPECTED, "Unexpected hr %#lx.\n", hr);
5393 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, media_type);
5394 ok(hr == S_OK, "Failed to set current type, hr %#lx.\n", hr);
5396 hr = IMFMediaTypeHandler_GetMediaTypeByIndex(handler, 0, &media_type2);
5397 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5398 ok(media_type2 == media_type, "Unexpected type.\n");
5399 IMFMediaType_Release(media_type2);
5401 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, NULL, NULL);
5402 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
5404 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type, NULL);
5405 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
5407 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type, &media_type2);
5408 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
5410 hr = IMFMediaTypeHandler_GetMediaTypeByIndex(handler, 1, &media_type2);
5411 ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#lx.\n", hr);
5413 hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, &media_type2);
5414 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5415 ok(media_type == media_type2, "Unexpected pointer.\n");
5416 IMFMediaType_Release(media_type2);
5418 hr = IMFMediaTypeHandler_GetMajorType(handler, &guid);
5419 ok(hr == MF_E_ATTRIBUTENOTFOUND, "Unexpected hr %#lx.\n", hr);
5421 hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
5422 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
5424 hr = IMFMediaTypeHandler_GetMajorType(handler, &guid);
5425 ok(hr == S_OK, "Failed to get major type, hr %#lx.\n", hr);
5426 ok(IsEqualGUID(&guid, &MFMediaType_Video), "Unexpected major type.\n");
5428 hr = MFCreateMediaType(&media_type3);
5429 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
5431 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type3, NULL);
5432 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
5434 hr = IMFMediaType_SetGUID(media_type3, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio);
5435 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
5437 /* Different major types. */
5438 media_type2 = (void *)0xdeadbeef;
5439 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type3, &media_type2);
5440 ok(hr == E_FAIL, "Unexpected hr %#lx.\n", hr);
5441 ok(!media_type2, "Unexpected pointer.\n");
5443 hr = IMFMediaType_SetGUID(media_type3, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
5444 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
5446 media_type2 = (void *)0xdeadbeef;
5447 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type3, &media_type2);
5448 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5449 ok(!media_type2, "Unexpected pointer.\n");
5451 /* Handler missing subtype. */
5452 hr = IMFMediaType_SetGUID(media_type3, &MF_MT_SUBTYPE, &MFVideoFormat_RGB8);
5453 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
5455 media_type2 = (void *)0xdeadbeef;
5456 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type3, &media_type2);
5457 ok(hr == E_FAIL, "Unexpected hr %#lx.\n", hr);
5458 ok(!media_type2, "Unexpected pointer.\n");
5460 /* Different subtypes. */
5461 hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFVideoFormat_RGB24);
5462 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
5464 media_type2 = (void *)0xdeadbeef;
5465 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type3, &media_type2);
5466 ok(hr == E_FAIL, "Unexpected hr %#lx.\n", hr);
5467 ok(!media_type2, "Unexpected pointer.\n");
5469 /* Same major/subtype. */
5470 hr = IMFMediaType_SetGUID(media_type3, &MF_MT_SUBTYPE, &MFVideoFormat_RGB24);
5471 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
5473 media_type2 = (void *)0xdeadbeef;
5474 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type3, &media_type2);
5475 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5476 ok(!media_type2, "Unexpected pointer.\n");
5478 /* Set one more attribute. */
5479 hr = IMFMediaType_SetUINT64(media_type, &MF_MT_FRAME_SIZE, (UINT64)4 << 32 | 4);
5480 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
5482 media_type2 = (void *)0xdeadbeef;
5483 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type3, &media_type2);
5484 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5485 ok(!media_type2, "Unexpected pointer.\n");
5487 ref = IMFMediaType_Release(media_type3);
5488 ok(ref == 0, "Release returned %ld\n", ref);
5490 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, NULL);
5491 ok(hr == S_OK, "Failed to set current type, hr %#lx.\n", hr);
5493 media_type2 = (void *)0xdeadbeef;
5494 hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, &media_type2);
5495 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5496 ok(!media_type2, "Unexpected pointer.\n");
5498 hr = IMFMediaTypeHandler_GetMajorType(handler, &guid);
5499 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#lx.\n", hr);
5501 ref = IMFMediaTypeHandler_Release(handler);
5502 ok(ref == 0, "Release returned %ld\n", ref);
5503 ref = IMFMediaType_Release(media_type);
5504 ok(ref == 0, "Release returned %ld\n", ref);
5507 static void test_MFGetSupportedMimeTypes(void)
5509 PROPVARIANT value;
5510 HRESULT hr;
5512 hr = MFGetSupportedMimeTypes(NULL);
5513 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
5515 value.vt = VT_EMPTY;
5516 hr = MFGetSupportedMimeTypes(&value);
5517 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5518 ok(value.vt == (VT_VECTOR | VT_LPWSTR), "Unexpected value type %#x.\n", value.vt);
5520 PropVariantClear(&value);
5523 static void test_MFGetSupportedSchemes(void)
5525 PROPVARIANT value;
5526 HRESULT hr;
5528 hr = MFGetSupportedSchemes(NULL);
5529 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
5531 value.vt = VT_EMPTY;
5532 hr = MFGetSupportedSchemes(&value);
5533 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5534 ok(value.vt == (VT_VECTOR | VT_LPWSTR), "Unexpected value type %#x.\n", value.vt);
5536 PropVariantClear(&value);
5539 static BOOL is_sample_copier_available_type(IMFMediaType *type)
5541 GUID major = { 0 };
5542 UINT32 count;
5543 HRESULT hr;
5545 hr = IMFMediaType_GetMajorType(type, &major);
5546 ok(hr == S_OK, "Failed to get major type, hr %#lx.\n", hr);
5548 hr = IMFMediaType_GetCount(type, &count);
5549 ok(hr == S_OK, "Failed to get attribute count, hr %#lx.\n", hr);
5550 ok(count == 1, "Unexpected attribute count %u.\n", count);
5552 return IsEqualGUID(&major, &MFMediaType_Video) || IsEqualGUID(&major, &MFMediaType_Audio);
5555 static void test_sample_copier(void)
5557 IMFAttributes *attributes, *attributes2;
5558 DWORD in_min, in_max, out_min, out_max;
5559 IMFMediaType *mediatype, *mediatype2;
5560 MFT_OUTPUT_STREAM_INFO output_info;
5561 IMFSample *sample, *client_sample;
5562 MFT_INPUT_STREAM_INFO input_info;
5563 DWORD input_count, output_count;
5564 MFT_OUTPUT_DATA_BUFFER buffer;
5565 IMFMediaBuffer *media_buffer;
5566 IMFTransform *copier;
5567 DWORD flags, status;
5568 UINT32 value, count;
5569 HRESULT hr;
5570 LONG ref;
5572 if (!pMFCreateSampleCopierMFT)
5574 win_skip("MFCreateSampleCopierMFT() is not available.\n");
5575 return;
5578 hr = pMFCreateSampleCopierMFT(&copier);
5579 ok(hr == S_OK, "Failed to create sample copier, hr %#lx.\n", hr);
5581 hr = IMFTransform_GetAttributes(copier, &attributes);
5582 ok(hr == S_OK, "Failed to get transform attributes, hr %#lx.\n", hr);
5583 hr = IMFTransform_GetAttributes(copier, &attributes2);
5584 ok(hr == S_OK, "Failed to get transform attributes, hr %#lx.\n", hr);
5585 ok(attributes == attributes2, "Unexpected instance.\n");
5586 IMFAttributes_Release(attributes2);
5587 hr = IMFAttributes_GetCount(attributes, &count);
5588 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5589 ok(count == 1, "Unexpected attribute count %u.\n", count);
5590 hr = IMFAttributes_GetUINT32(attributes, &MFT_SUPPORT_DYNAMIC_FORMAT_CHANGE, &value);
5591 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5592 ok(!!value, "Unexpected value %u.\n", value);
5593 ref = IMFAttributes_Release(attributes);
5594 ok(ref == 1, "Release returned %ld\n", ref);
5596 hr = IMFTransform_GetInputStreamAttributes(copier, 0, &attributes);
5597 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
5599 hr = IMFTransform_GetInputStreamAttributes(copier, 1, &attributes);
5600 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
5602 hr = IMFTransform_GetOutputStreamAttributes(copier, 0, &attributes);
5603 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
5605 hr = IMFTransform_GetOutputStreamAttributes(copier, 1, &attributes);
5606 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
5608 hr = IMFTransform_SetOutputBounds(copier, 0, 0);
5609 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
5611 /* No dynamic streams. */
5612 input_count = output_count = 0;
5613 hr = IMFTransform_GetStreamCount(copier, &input_count, &output_count);
5614 ok(hr == S_OK, "Failed to get stream count, hr %#lx.\n", hr);
5615 ok(input_count == 1 && output_count == 1, "Unexpected streams count.\n");
5617 hr = IMFTransform_GetStreamLimits(copier, &in_min, &in_max, &out_min, &out_max);
5618 ok(hr == S_OK, "Failed to get stream limits, hr %#lx.\n", hr);
5619 ok(in_min == in_max && in_min == 1 && out_min == out_max && out_min == 1, "Unexpected stream limits.\n");
5621 hr = IMFTransform_GetStreamIDs(copier, 1, &input_count, 1, &output_count);
5622 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
5624 hr = IMFTransform_DeleteInputStream(copier, 0);
5625 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
5627 /* Available types. */
5628 hr = IMFTransform_GetInputAvailableType(copier, 0, 0, &mediatype);
5629 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5630 ok(is_sample_copier_available_type(mediatype), "Unexpected type.\n");
5631 IMFMediaType_Release(mediatype);
5633 hr = IMFTransform_GetInputAvailableType(copier, 0, 1, &mediatype);
5634 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5635 ok(is_sample_copier_available_type(mediatype), "Unexpected type.\n");
5636 IMFMediaType_Release(mediatype);
5638 hr = IMFTransform_GetInputAvailableType(copier, 0, 2, &mediatype);
5639 ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#lx.\n", hr);
5641 hr = IMFTransform_GetInputAvailableType(copier, 1, 0, &mediatype);
5642 ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#lx.\n", hr);
5644 hr = IMFTransform_GetOutputAvailableType(copier, 0, 0, &mediatype);
5645 ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#lx.\n", hr);
5647 hr = IMFTransform_GetOutputAvailableType(copier, 1, 0, &mediatype);
5648 ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#lx.\n", hr);
5650 hr = IMFTransform_GetInputCurrentType(copier, 0, &mediatype);
5651 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
5653 hr = IMFTransform_GetInputCurrentType(copier, 1, &mediatype);
5654 ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#lx.\n", hr);
5656 hr = IMFTransform_GetOutputCurrentType(copier, 0, &mediatype);
5657 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
5659 hr = IMFTransform_GetOutputCurrentType(copier, 1, &mediatype);
5660 ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#lx.\n", hr);
5662 hr = MFCreateSample(&sample);
5663 ok(hr == S_OK, "Failed to create a sample, hr %#lx.\n", hr);
5665 hr = IMFTransform_ProcessInput(copier, 0, sample, 0);
5666 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
5668 hr = MFCreateMediaType(&mediatype);
5669 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
5671 hr = IMFTransform_SetOutputType(copier, 0, mediatype, 0);
5672 ok(hr == MF_E_ATTRIBUTENOTFOUND, "Unexpected hr %#lx.\n", hr);
5674 hr = IMFMediaType_SetGUID(mediatype, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
5675 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
5677 hr = IMFMediaType_SetGUID(mediatype, &MF_MT_SUBTYPE, &MFVideoFormat_RGB8);
5678 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
5680 hr = IMFMediaType_SetUINT64(mediatype, &MF_MT_FRAME_SIZE, ((UINT64)16) << 32 | 16);
5681 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
5683 hr = IMFTransform_GetOutputStreamInfo(copier, 0, &output_info);
5684 ok(hr == S_OK, "Failed to get stream info, hr %#lx.\n", hr);
5685 ok(!output_info.dwFlags, "Unexpected flags %#lx.\n", output_info.dwFlags);
5686 ok(!output_info.cbSize, "Unexpected size %lu.\n", output_info.cbSize);
5687 ok(!output_info.cbAlignment, "Unexpected alignment %lu.\n", output_info.cbAlignment);
5689 hr = IMFTransform_GetInputStreamInfo(copier, 0, &input_info);
5690 ok(hr == S_OK, "Failed to get stream info, hr %#lx.\n", hr);
5692 ok(!input_info.hnsMaxLatency, "Unexpected latency %s.\n", wine_dbgstr_longlong(input_info.hnsMaxLatency));
5693 ok(!input_info.dwFlags, "Unexpected flags %#lx.\n", input_info.dwFlags);
5694 ok(!input_info.cbSize, "Unexpected size %lu.\n", input_info.cbSize);
5695 ok(!input_info.cbMaxLookahead, "Unexpected lookahead size %lu.\n", input_info.cbMaxLookahead);
5696 ok(!input_info.cbAlignment, "Unexpected alignment %lu.\n", input_info.cbAlignment);
5698 hr = IMFTransform_SetOutputType(copier, 0, mediatype, 0);
5699 ok(hr == S_OK, "Failed to set input type, hr %#lx.\n", hr);
5701 hr = IMFTransform_GetOutputStreamInfo(copier, 0, &output_info);
5702 ok(hr == S_OK, "Failed to get stream info, hr %#lx.\n", hr);
5703 ok(!output_info.dwFlags, "Unexpected flags %#lx.\n", output_info.dwFlags);
5704 ok(output_info.cbSize == 16 * 16, "Unexpected size %lu.\n", output_info.cbSize);
5705 ok(!output_info.cbAlignment, "Unexpected alignment %lu.\n", output_info.cbAlignment);
5707 hr = IMFTransform_GetOutputCurrentType(copier, 0, &mediatype2);
5708 ok(hr == S_OK, "Failed to get current type, hr %#lx.\n", hr);
5709 IMFMediaType_Release(mediatype2);
5711 hr = IMFTransform_GetInputCurrentType(copier, 0, &mediatype2);
5712 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
5714 hr = IMFTransform_GetInputStatus(copier, 0, &flags);
5715 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
5717 /* Setting input type resets output type. */
5718 hr = IMFTransform_GetOutputCurrentType(copier, 0, &mediatype2);
5719 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5720 IMFMediaType_Release(mediatype2);
5722 hr = IMFTransform_SetInputType(copier, 0, mediatype, 0);
5723 ok(hr == S_OK, "Failed to set input type, hr %#lx.\n", hr);
5725 hr = IMFTransform_GetOutputCurrentType(copier, 0, &mediatype2);
5726 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
5728 hr = IMFTransform_GetInputAvailableType(copier, 0, 1, &mediatype2);
5729 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5730 ok(is_sample_copier_available_type(mediatype2), "Unexpected type.\n");
5731 IMFMediaType_Release(mediatype2);
5733 hr = IMFTransform_GetInputStreamInfo(copier, 0, &input_info);
5734 ok(hr == S_OK, "Failed to get stream info, hr %#lx.\n", hr);
5735 ok(!input_info.hnsMaxLatency, "Unexpected latency %s.\n", wine_dbgstr_longlong(input_info.hnsMaxLatency));
5736 ok(!input_info.dwFlags, "Unexpected flags %#lx.\n", input_info.dwFlags);
5737 ok(input_info.cbSize == 16 * 16, "Unexpected size %lu.\n", input_info.cbSize);
5738 ok(!input_info.cbMaxLookahead, "Unexpected lookahead size %lu.\n", input_info.cbMaxLookahead);
5739 ok(!input_info.cbAlignment, "Unexpected alignment %lu.\n", input_info.cbAlignment);
5741 hr = IMFTransform_GetOutputAvailableType(copier, 0, 0, &mediatype2);
5742 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5743 hr = IMFMediaType_IsEqual(mediatype2, mediatype, &flags);
5744 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5745 IMFMediaType_Release(mediatype2);
5747 hr = IMFTransform_GetInputStatus(copier, 0, &flags);
5748 ok(hr == S_OK, "Failed to get input status, hr %#lx.\n", hr);
5749 ok(flags == MFT_INPUT_STATUS_ACCEPT_DATA, "Unexpected flags %#lx.\n", flags);
5751 hr = IMFTransform_GetInputCurrentType(copier, 0, &mediatype2);
5752 ok(hr == S_OK, "Failed to get current type, hr %#lx.\n", hr);
5753 IMFMediaType_Release(mediatype2);
5755 hr = IMFTransform_GetOutputStatus(copier, &flags);
5756 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
5758 hr = IMFTransform_SetOutputType(copier, 0, mediatype, 0);
5759 ok(hr == S_OK, "Failed to set output type, hr %#lx.\n", hr);
5761 hr = IMFTransform_GetOutputStatus(copier, &flags);
5762 ok(hr == S_OK, "Failed to get output status, hr %#lx.\n", hr);
5763 ok(!flags, "Unexpected flags %#lx.\n", flags);
5765 /* Pushing samples. */
5766 hr = MFCreateAlignedMemoryBuffer(output_info.cbSize, output_info.cbAlignment, &media_buffer);
5767 ok(hr == S_OK, "Failed to create media buffer, hr %#lx.\n", hr);
5769 hr = IMFSample_AddBuffer(sample, media_buffer);
5770 ok(hr == S_OK, "Failed to add a buffer, hr %#lx.\n", hr);
5771 IMFMediaBuffer_Release(media_buffer);
5773 EXPECT_REF(sample, 1);
5774 hr = IMFTransform_ProcessInput(copier, 0, sample, 0);
5775 ok(hr == S_OK, "Failed to process input, hr %#lx.\n", hr);
5776 EXPECT_REF(sample, 2);
5778 hr = IMFTransform_GetInputStatus(copier, 0, &flags);
5779 ok(hr == S_OK, "Failed to get input status, hr %#lx.\n", hr);
5780 ok(!flags, "Unexpected flags %#lx.\n", flags);
5782 hr = IMFTransform_GetOutputStatus(copier, &flags);
5783 ok(hr == S_OK, "Failed to get output status, hr %#lx.\n", hr);
5784 ok(flags == MFT_OUTPUT_STATUS_SAMPLE_READY, "Unexpected flags %#lx.\n", flags);
5786 hr = IMFTransform_ProcessInput(copier, 0, sample, 0);
5787 ok(hr == MF_E_NOTACCEPTING, "Unexpected hr %#lx.\n", hr);
5789 hr = IMFTransform_GetOutputStreamInfo(copier, 0, &output_info);
5790 ok(hr == S_OK, "Failed to get output info, hr %#lx.\n", hr);
5792 hr = MFCreateAlignedMemoryBuffer(output_info.cbSize, output_info.cbAlignment, &media_buffer);
5793 ok(hr == S_OK, "Failed to create media buffer, hr %#lx.\n", hr);
5795 hr = MFCreateSample(&client_sample);
5796 ok(hr == S_OK, "Failed to create a sample, hr %#lx.\n", hr);
5798 hr = IMFSample_AddBuffer(client_sample, media_buffer);
5799 ok(hr == S_OK, "Failed to add a buffer, hr %#lx.\n", hr);
5800 IMFMediaBuffer_Release(media_buffer);
5802 status = 0;
5803 memset(&buffer, 0, sizeof(buffer));
5804 buffer.pSample = client_sample;
5805 hr = IMFTransform_ProcessOutput(copier, 0, 1, &buffer, &status);
5806 ok(hr == S_OK, "Failed to get output, hr %#lx.\n", hr);
5807 EXPECT_REF(sample, 1);
5809 hr = IMFTransform_ProcessOutput(copier, 0, 1, &buffer, &status);
5810 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "Failed to get output, hr %#lx.\n", hr);
5812 /* Flushing. */
5813 hr = IMFTransform_ProcessInput(copier, 0, sample, 0);
5814 ok(hr == S_OK, "Failed to process input, hr %#lx.\n", hr);
5815 EXPECT_REF(sample, 2);
5817 hr = IMFTransform_ProcessMessage(copier, MFT_MESSAGE_COMMAND_FLUSH, 0);
5818 ok(hr == S_OK, "Failed to flush, hr %#lx.\n", hr);
5820 ref = IMFSample_Release(sample);
5821 ok(ref == 0, "Release returned %ld\n", ref);
5822 ref = IMFSample_Release(client_sample);
5823 ok(ref == 0, "Release returned %ld\n", ref);
5825 ref = IMFTransform_Release(copier);
5826 ok(ref == 0, "Release returned %ld\n", ref);
5827 ref = IMFMediaType_Release(mediatype);
5828 ok(ref == 0, "Release returned %ld\n", ref);
5831 struct sample_metadata
5833 unsigned int flags;
5834 LONGLONG duration;
5835 LONGLONG time;
5838 static void sample_copier_process(IMFTransform *copier, IMFMediaBuffer *input_buffer,
5839 IMFMediaBuffer *output_buffer, const struct sample_metadata *md)
5841 static const struct sample_metadata zero_md = { 0, ~0u, ~0u };
5842 IMFSample *input_sample, *output_sample;
5843 MFT_OUTPUT_DATA_BUFFER buffer;
5844 DWORD flags, status;
5845 LONGLONG time;
5846 HRESULT hr;
5847 LONG ref;
5849 hr = MFCreateSample(&input_sample);
5850 ok(hr == S_OK, "Failed to create a sample, hr %#lx.\n", hr);
5852 if (md)
5854 hr = IMFSample_SetSampleFlags(input_sample, md->flags);
5855 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5857 hr = IMFSample_SetSampleTime(input_sample, md->time);
5858 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5860 hr = IMFSample_SetSampleDuration(input_sample, md->duration);
5861 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5864 hr = MFCreateSample(&output_sample);
5865 ok(hr == S_OK, "Failed to create a sample, hr %#lx.\n", hr);
5867 hr = IMFSample_SetSampleFlags(output_sample, ~0u);
5868 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5870 hr = IMFSample_SetSampleTime(output_sample, ~0u);
5871 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5873 hr = IMFSample_SetSampleDuration(output_sample, ~0u);
5874 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5876 hr = IMFSample_AddBuffer(input_sample, input_buffer);
5877 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5879 hr = IMFSample_AddBuffer(output_sample, output_buffer);
5880 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5882 hr = IMFTransform_ProcessInput(copier, 0, input_sample, 0);
5883 ok(hr == S_OK, "Failed to process input, hr %#lx.\n", hr);
5885 status = 0;
5886 memset(&buffer, 0, sizeof(buffer));
5887 buffer.pSample = output_sample;
5888 hr = IMFTransform_ProcessOutput(copier, 0, 1, &buffer, &status);
5889 ok(hr == S_OK, "Failed to get output, hr %#lx.\n", hr);
5891 if (!md) md = &zero_md;
5893 hr = IMFSample_GetSampleFlags(output_sample, &flags);
5894 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5895 ok(md->flags == flags, "Unexpected flags.\n");
5896 hr = IMFSample_GetSampleTime(output_sample, &time);
5897 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5898 ok(md->time == time, "Unexpected time.\n");
5899 hr = IMFSample_GetSampleDuration(output_sample, &time);
5900 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5901 ok(md->duration == time, "Unexpected duration.\n");
5903 ref = IMFSample_Release(input_sample);
5904 ok(ref == 0, "Release returned %ld\n", ref);
5905 ref = IMFSample_Release(output_sample);
5906 ok(ref == 0, "Release returned %ld\n", ref);
5909 static void test_sample_copier_output_processing(void)
5911 IMFMediaBuffer *input_buffer, *output_buffer;
5912 MFT_OUTPUT_STREAM_INFO output_info;
5913 struct sample_metadata md;
5914 IMFMediaType *mediatype;
5915 IMFTransform *copier;
5916 DWORD max_length;
5917 HRESULT hr;
5918 BYTE *ptr;
5919 LONG ref;
5921 if (!pMFCreateSampleCopierMFT)
5922 return;
5924 hr = pMFCreateSampleCopierMFT(&copier);
5925 ok(hr == S_OK, "Failed to create sample copier, hr %#lx.\n", hr);
5927 /* Configure for 16 x 16 of D3DFMT_X8R8G8B8. */
5928 hr = MFCreateMediaType(&mediatype);
5929 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
5931 hr = IMFMediaType_SetGUID(mediatype, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
5932 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
5934 hr = IMFMediaType_SetGUID(mediatype, &MF_MT_SUBTYPE, &MFVideoFormat_RGB32);
5935 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
5937 hr = IMFMediaType_SetUINT64(mediatype, &MF_MT_FRAME_SIZE, ((UINT64)16) << 32 | 16);
5938 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
5940 hr = IMFTransform_SetInputType(copier, 0, mediatype, 0);
5941 ok(hr == S_OK, "Failed to set input type, hr %#lx.\n", hr);
5943 hr = IMFTransform_SetOutputType(copier, 0, mediatype, 0);
5944 ok(hr == S_OK, "Failed to set input type, hr %#lx.\n", hr);
5946 /* Source and destination are linear buffers, destination is twice as large. */
5947 hr = IMFTransform_GetOutputStreamInfo(copier, 0, &output_info);
5948 ok(hr == S_OK, "Failed to get output info, hr %#lx.\n", hr);
5950 hr = MFCreateAlignedMemoryBuffer(output_info.cbSize, output_info.cbAlignment, &output_buffer);
5951 ok(hr == S_OK, "Failed to create media buffer, hr %#lx.\n", hr);
5953 hr = IMFMediaBuffer_Lock(output_buffer, &ptr, &max_length, NULL);
5954 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5955 memset(ptr, 0xcc, max_length);
5956 hr = IMFMediaBuffer_Unlock(output_buffer);
5957 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5959 hr = MFCreateAlignedMemoryBuffer(output_info.cbSize, output_info.cbAlignment, &input_buffer);
5960 ok(hr == S_OK, "Failed to create media buffer, hr %#lx.\n", hr);
5962 hr = IMFMediaBuffer_Lock(input_buffer, &ptr, &max_length, NULL);
5963 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5964 memset(ptr, 0xaa, max_length);
5965 hr = IMFMediaBuffer_Unlock(input_buffer);
5966 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5967 hr = IMFMediaBuffer_SetCurrentLength(input_buffer, 4);
5968 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5970 sample_copier_process(copier, input_buffer, output_buffer, NULL);
5972 hr = IMFMediaBuffer_Lock(output_buffer, &ptr, &max_length, NULL);
5973 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5974 ok(ptr[0] == 0xaa && ptr[4] == 0xcc, "Unexpected buffer contents.\n");
5976 hr = IMFMediaBuffer_Unlock(output_buffer);
5977 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5979 md.flags = 123;
5980 md.time = 10;
5981 md.duration = 2;
5982 sample_copier_process(copier, input_buffer, output_buffer, &md);
5984 ref = IMFMediaBuffer_Release(input_buffer);
5985 ok(ref == 0, "Release returned %ld\n", ref);
5986 ref = IMFMediaBuffer_Release(output_buffer);
5987 ok(ref == 0, "Release returned %ld\n", ref);
5989 ref = IMFTransform_Release(copier);
5990 ok(ref == 0, "Release returned %ld\n", ref);
5991 ref = IMFMediaType_Release(mediatype);
5992 ok(ref == 0, "Release returned %ld\n", ref);
5995 static void test_MFGetTopoNodeCurrentType(void)
5997 static const struct attribute_desc media_type_desc[] =
5999 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
6000 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12),
6001 ATTR_RATIO(MF_MT_FRAME_SIZE, 1920, 1080),
6002 {0},
6004 IMFMediaType *media_type, *input_types[2], *output_types[2];
6005 IMFStreamDescriptor *input_descriptor, *output_descriptor;
6006 struct test_stream_sink stream_sink = test_stream_sink;
6007 IMFMediaTypeHandler *input_handler, *output_handler;
6008 IMFTransform *transform;
6009 IMFTopologyNode *node;
6010 DWORD flags;
6011 HRESULT hr;
6012 LONG ref;
6014 if (!pMFGetTopoNodeCurrentType)
6016 win_skip("MFGetTopoNodeCurrentType() is unsupported.\n");
6017 return;
6020 hr = CoInitialize(NULL);
6021 ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
6023 hr = MFCreateMediaType(&input_types[0]);
6024 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
6025 init_media_type(input_types[0], media_type_desc, -1);
6026 hr = MFCreateMediaType(&input_types[1]);
6027 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
6028 init_media_type(input_types[1], media_type_desc, -1);
6029 hr = MFCreateMediaType(&output_types[0]);
6030 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
6031 init_media_type(output_types[0], media_type_desc, -1);
6032 hr = MFCreateMediaType(&output_types[1]);
6033 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
6034 init_media_type(output_types[1], media_type_desc, -1);
6036 hr = MFCreateStreamDescriptor(0, 2, input_types, &input_descriptor);
6037 ok(hr == S_OK, "Failed to create IMFStreamDescriptor hr %#lx.\n", hr);
6038 hr = IMFStreamDescriptor_GetMediaTypeHandler(input_descriptor, &input_handler);
6039 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6040 hr = MFCreateStreamDescriptor(0, 2, output_types, &output_descriptor);
6041 ok(hr == S_OK, "Failed to create IMFStreamDescriptor hr %#lx.\n", hr);
6042 hr = IMFStreamDescriptor_GetMediaTypeHandler(output_descriptor, &output_handler);
6043 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6045 hr = CoCreateInstance(&CLSID_CColorConvertDMO, NULL, CLSCTX_INPROC_SERVER, &IID_IMFTransform, (void **)&transform);
6046 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6049 /* Tee node. */
6050 hr = MFCreateTopologyNode(MF_TOPOLOGY_TEE_NODE, &node);
6051 ok(hr == S_OK, "Failed to create a node, hr %#lx.\n", hr);
6052 hr = pMFGetTopoNodeCurrentType(node, 0, TRUE, &media_type);
6053 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
6054 hr = pMFGetTopoNodeCurrentType(node, 0, FALSE, &media_type);
6055 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
6057 /* Set second output. */
6058 hr = IMFTopologyNode_SetOutputPrefType(node, 1, output_types[1]);
6059 ok(hr == S_OK, "Failed to set media type, hr %#lx.\n", hr);
6060 hr = pMFGetTopoNodeCurrentType(node, 0, TRUE, &media_type);
6061 ok(hr == E_FAIL, "Unexpected hr %#lx.\n", hr);
6062 hr = pMFGetTopoNodeCurrentType(node, 0, FALSE, &media_type);
6063 ok(hr == E_FAIL, "Unexpected hr %#lx.\n", hr);
6064 hr = pMFGetTopoNodeCurrentType(node, 1, TRUE, &media_type);
6065 ok(hr == E_FAIL, "Unexpected hr %#lx.\n", hr);
6066 hr = pMFGetTopoNodeCurrentType(node, 1, FALSE, &media_type);
6067 ok(hr == E_FAIL, "Unexpected hr %#lx.\n", hr);
6069 /* Set first output. */
6070 hr = IMFTopologyNode_SetOutputPrefType(node, 0, output_types[0]);
6071 ok(hr == S_OK, "Failed to set media type, hr %#lx.\n", hr);
6072 hr = pMFGetTopoNodeCurrentType(node, 0, TRUE, &media_type);
6073 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6074 ok(media_type == output_types[0], "Unexpected pointer.\n");
6075 IMFMediaType_Release(media_type);
6076 hr = pMFGetTopoNodeCurrentType(node, 1, TRUE, &media_type);
6077 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6078 ok(media_type == output_types[0], "Unexpected pointer.\n");
6079 IMFMediaType_Release(media_type);
6080 hr = pMFGetTopoNodeCurrentType(node, 0, FALSE, &media_type);
6081 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6082 ok(media_type == output_types[0], "Unexpected pointer.\n");
6083 IMFMediaType_Release(media_type);
6085 /* Set primary output. */
6086 hr = IMFTopologyNode_SetOutputPrefType(node, 1, output_types[1]);
6087 ok(hr == S_OK, "Failed to set media type, hr %#lx.\n", hr);
6088 hr = IMFTopologyNode_SetUINT32(node, &MF_TOPONODE_PRIMARYOUTPUT, 1);
6089 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
6090 hr = pMFGetTopoNodeCurrentType(node, 0, TRUE, &media_type);
6091 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6092 ok(media_type == output_types[1], "Unexpected pointer.\n");
6093 IMFMediaType_Release(media_type);
6094 hr = pMFGetTopoNodeCurrentType(node, 0, FALSE, &media_type);
6095 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6096 ok(media_type == output_types[1], "Unexpected pointer.\n");
6097 IMFMediaType_Release(media_type);
6098 hr = pMFGetTopoNodeCurrentType(node, 1, FALSE, &media_type);
6099 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6100 ok(media_type == output_types[1], "Unexpected pointer.\n");
6101 IMFMediaType_Release(media_type);
6103 /* Input type returned, if set. */
6104 hr = IMFTopologyNode_SetInputPrefType(node, 0, input_types[0]);
6105 ok(hr == S_OK, "Failed to set media type, hr %#lx.\n", hr);
6106 hr = pMFGetTopoNodeCurrentType(node, 0, FALSE, &media_type);
6107 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6108 ok(media_type == input_types[0], "Unexpected pointer.\n");
6109 IMFMediaType_Release(media_type);
6110 hr = pMFGetTopoNodeCurrentType(node, 0, TRUE, &media_type);
6111 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6112 ok(media_type == input_types[0], "Unexpected pointer.\n");
6113 IMFMediaType_Release(media_type);
6115 hr = IMFTopologyNode_SetInputPrefType(node, 0, NULL);
6116 ok(hr == S_OK, "Failed to set media type, hr %#lx.\n", hr);
6117 hr = IMFTopologyNode_SetOutputPrefType(node, 0, NULL);
6118 ok(hr == S_OK, "Failed to set media type, hr %#lx.\n", hr);
6119 hr = IMFTopologyNode_SetOutputPrefType(node, 1, NULL);
6120 ok(hr == S_OK, "Failed to set media type, hr %#lx.\n", hr);
6121 ref = IMFTopologyNode_Release(node);
6122 ok(ref == 0, "Release returned %ld\n", ref);
6125 /* Source node. */
6126 hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &node);
6127 ok(hr == S_OK, "Failed to create a node, hr %#lx.\n", hr);
6128 hr = pMFGetTopoNodeCurrentType(node, 0, TRUE, &media_type);
6129 ok(hr == MF_E_ATTRIBUTENOTFOUND, "Unexpected hr %#lx.\n", hr);
6130 hr = pMFGetTopoNodeCurrentType(node, 1, TRUE, &media_type);
6131 ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#lx.\n", hr);
6132 hr = pMFGetTopoNodeCurrentType(node, 0, FALSE, &media_type);
6133 ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#lx.\n", hr);
6135 hr = IMFTopologyNode_SetUnknown(node, &MF_TOPONODE_STREAM_DESCRIPTOR, (IUnknown *)input_descriptor);
6136 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6137 hr = pMFGetTopoNodeCurrentType(node, 0, TRUE, &media_type);
6138 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#lx.\n", hr);
6140 hr = IMFMediaTypeHandler_SetCurrentMediaType(input_handler, output_types[0]);
6141 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6142 hr = pMFGetTopoNodeCurrentType(node, 0, TRUE, &media_type);
6143 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6144 ok(media_type == output_types[0], "Unexpected pointer.\n");
6145 IMFMediaType_Release(media_type);
6147 ref = IMFTopologyNode_Release(node);
6148 ok(ref == 0, "Release returned %ld\n", ref);
6151 /* Output node. */
6152 hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, &node);
6153 ok(hr == S_OK, "Failed to create a node, hr %#lx.\n", hr);
6154 hr = pMFGetTopoNodeCurrentType(node, 0, FALSE, &media_type);
6155 ok(hr == E_FAIL, "Unexpected hr %#lx.\n", hr);
6156 hr = pMFGetTopoNodeCurrentType(node, 1, FALSE, &media_type);
6157 ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#lx.\n", hr);
6158 hr = pMFGetTopoNodeCurrentType(node, 0, TRUE, &media_type);
6159 ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#lx.\n", hr);
6161 stream_sink.handler = output_handler;
6162 hr = IMFTopologyNode_SetObject(node, (IUnknown *)&stream_sink.IMFStreamSink_iface);
6163 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6164 hr = pMFGetTopoNodeCurrentType(node, 0, FALSE, &media_type);
6165 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#lx.\n", hr);
6167 hr = IMFMediaTypeHandler_SetCurrentMediaType(output_handler, input_types[0]);
6168 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6169 hr = pMFGetTopoNodeCurrentType(node, 0, FALSE, &media_type);
6170 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6171 ok(media_type == input_types[0], "Unexpected pointer.\n");
6172 IMFMediaType_Release(media_type);
6174 ref = IMFTopologyNode_Release(node);
6175 ok(ref == 0, "Release returned %ld\n", ref);
6178 /* Transform node. */
6179 hr = MFCreateTopologyNode(MF_TOPOLOGY_TRANSFORM_NODE, &node);
6180 ok(hr == S_OK, "Failed to create a node, hr %#lx.\n", hr);
6181 hr = pMFGetTopoNodeCurrentType(node, 0, TRUE, &media_type);
6182 ok(hr == E_FAIL, "Unexpected hr %#lx.\n", hr);
6183 hr = pMFGetTopoNodeCurrentType(node, 1, TRUE, &media_type);
6184 ok(hr == E_FAIL, "Unexpected hr %#lx.\n", hr);
6185 hr = pMFGetTopoNodeCurrentType(node, 0, FALSE, &media_type);
6186 ok(hr == E_FAIL, "Unexpected hr %#lx.\n", hr);
6187 hr = pMFGetTopoNodeCurrentType(node, 1, FALSE, &media_type);
6188 ok(hr == E_FAIL, "Unexpected hr %#lx.\n", hr);
6190 hr = IMFTopologyNode_SetObject(node, (IUnknown *)transform);
6191 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6192 hr = pMFGetTopoNodeCurrentType(node, 0, TRUE, &media_type);
6193 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
6194 hr = pMFGetTopoNodeCurrentType(node, 1, TRUE, &media_type);
6195 ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#lx.\n", hr);
6196 hr = pMFGetTopoNodeCurrentType(node, 0, FALSE, &media_type);
6197 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
6198 hr = pMFGetTopoNodeCurrentType(node, 1, FALSE, &media_type);
6199 ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#lx.\n", hr);
6201 hr = IMFTransform_SetInputType(transform, 0, input_types[0], 0);
6202 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6203 hr = pMFGetTopoNodeCurrentType(node, 0, TRUE, &media_type);
6204 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
6205 hr = pMFGetTopoNodeCurrentType(node, 0, FALSE, &media_type);
6206 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6207 hr = IMFMediaType_IsEqual(media_type, input_types[0], &flags);
6208 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6209 IMFMediaType_Release(media_type);
6211 hr = IMFTransform_SetOutputType(transform, 0, output_types[0], 0);
6212 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6213 hr = pMFGetTopoNodeCurrentType(node, 0, TRUE, &media_type);
6214 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6215 hr = IMFMediaType_IsEqual(media_type, output_types[0], &flags);
6216 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6217 IMFMediaType_Release(media_type);
6219 ref = IMFTopologyNode_Release(node);
6220 ok(ref == 0, "Release returned %ld\n", ref);
6223 ref = IMFTransform_Release(transform);
6224 ok(ref == 0, "Release returned %ld\n", ref);
6226 IMFMediaTypeHandler_Release(input_handler);
6227 IMFMediaTypeHandler_Release(output_handler);
6228 ref = IMFStreamDescriptor_Release(input_descriptor);
6229 ok(ref == 0, "Release returned %ld\n", ref);
6230 ref = IMFStreamDescriptor_Release(output_descriptor);
6231 ok(ref == 0, "Release returned %ld\n", ref);
6233 ref = IMFMediaType_Release(input_types[0]);
6234 ok(ref == 0, "Release returned %ld\n", ref);
6235 ref = IMFMediaType_Release(input_types[1]);
6236 ok(ref == 0, "Release returned %ld\n", ref);
6237 ref = IMFMediaType_Release(output_types[0]);
6238 ok(ref == 0, "Release returned %ld\n", ref);
6239 ref = IMFMediaType_Release(output_types[1]);
6240 ok(ref == 0, "Release returned %ld\n", ref);
6242 CoUninitialize();
6245 static void init_functions(void)
6247 HMODULE mod = GetModuleHandleA("mf.dll");
6249 #define X(f) p##f = (void*)GetProcAddress(mod, #f)
6250 X(MFCreateSampleCopierMFT);
6251 X(MFGetTopoNodeCurrentType);
6252 #undef X
6255 static void test_MFRequireProtectedEnvironment(void)
6257 IMFPresentationDescriptor *pd;
6258 IMFMediaType *mediatype;
6259 IMFStreamDescriptor *sd;
6260 HRESULT hr;
6261 LONG ref;
6263 hr = MFCreateMediaType(&mediatype);
6264 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6266 hr = MFCreateStreamDescriptor(0, 1, &mediatype, &sd);
6267 ok(hr == S_OK, "Failed to create stream descriptor, hr %#lx.\n", hr);
6269 hr = MFCreatePresentationDescriptor(1, &sd, &pd);
6270 ok(hr == S_OK, "Failed to create presentation descriptor, hr %#lx.\n", hr);
6272 hr = IMFPresentationDescriptor_SelectStream(pd, 0);
6273 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6275 hr = MFRequireProtectedEnvironment(pd);
6276 ok(hr == S_FALSE, "Unexpected hr %#lx.\n", hr);
6278 hr = IMFStreamDescriptor_SetUINT32(sd, &MF_SD_PROTECTED, 1);
6279 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6281 hr = MFRequireProtectedEnvironment(pd);
6282 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6284 hr = IMFPresentationDescriptor_DeselectStream(pd, 0);
6285 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6287 hr = MFRequireProtectedEnvironment(pd);
6288 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6290 ref = IMFPresentationDescriptor_Release(pd);
6291 ok(ref == 0, "Release returned %ld\n", ref);
6292 ref = IMFStreamDescriptor_Release(sd);
6293 ok(ref == 0, "Release returned %ld\n", ref);
6294 ref = IMFMediaType_Release(mediatype);
6295 ok(ref == 0, "Release returned %ld\n", ref);
6298 static IMFSample *create_sample(const BYTE *data, ULONG size)
6300 IMFMediaBuffer *media_buffer;
6301 IMFSample *sample;
6302 DWORD length;
6303 BYTE *buffer;
6304 HRESULT hr;
6305 ULONG ret;
6307 hr = MFCreateSample(&sample);
6308 ok(hr == S_OK, "MFCreateSample returned %#lx\n", hr);
6309 hr = MFCreateMemoryBuffer(size, &media_buffer);
6310 ok(hr == S_OK, "MFCreateMemoryBuffer returned %#lx\n", hr);
6311 hr = IMFMediaBuffer_Lock(media_buffer, &buffer, NULL, &length);
6312 ok(hr == S_OK, "Lock returned %#lx\n", hr);
6313 ok(length == 0, "got length %lu\n", length);
6314 if (!data) memset(buffer, 0xcd, size);
6315 else memcpy(buffer, data, size);
6316 hr = IMFMediaBuffer_Unlock(media_buffer);
6317 ok(hr == S_OK, "Unlock returned %#lx\n", hr);
6318 hr = IMFMediaBuffer_SetCurrentLength(media_buffer, data ? size : 0);
6319 ok(hr == S_OK, "SetCurrentLength returned %#lx\n", hr);
6320 hr = IMFSample_AddBuffer(sample, media_buffer);
6321 ok(hr == S_OK, "AddBuffer returned %#lx\n", hr);
6322 ret = IMFMediaBuffer_Release(media_buffer);
6323 ok(ret == 1, "Release returned %lu\n", ret);
6325 return sample;
6328 #define check_sample(a, b, c) check_sample_(__LINE__, a, b, c)
6329 static void check_sample_(int line, IMFSample *sample, const BYTE *expect_buf, HANDLE output_file)
6331 IMFMediaBuffer *media_buffer;
6332 DWORD length;
6333 BYTE *buffer;
6334 HRESULT hr;
6335 ULONG ret;
6337 hr = IMFSample_ConvertToContiguousBuffer(sample, &media_buffer);
6338 ok_(__FILE__, line)(hr == S_OK, "ConvertToContiguousBuffer returned %#lx\n", hr);
6339 hr = IMFMediaBuffer_Lock(media_buffer, &buffer, NULL, &length);
6340 ok_(__FILE__, line)(hr == S_OK, "Lock returned %#lx\n", hr);
6341 ok_(__FILE__, line)(!memcmp(expect_buf, buffer, length), "unexpected buffer data\n");
6342 if (output_file) WriteFile(output_file, buffer, length, &length, NULL);
6343 hr = IMFMediaBuffer_Unlock(media_buffer);
6344 ok_(__FILE__, line)(hr == S_OK, "Unlock returned %#lx\n", hr);
6345 ret = IMFMediaBuffer_Release(media_buffer);
6346 ok_(__FILE__, line)(ret == 1, "Release returned %lu\n", ret);
6349 #define check_sample_rgb32(a, b, c) check_sample_rgb32_(__LINE__, a, b, c)
6350 static void check_sample_rgb32_(int line, IMFSample *sample, const BYTE *expect_buf, HANDLE output_file)
6352 DWORD i, length, diff = 0, max_diff;
6353 IMFMediaBuffer *media_buffer;
6354 BYTE *buffer;
6355 HRESULT hr;
6356 ULONG ret;
6358 hr = IMFSample_ConvertToContiguousBuffer(sample, &media_buffer);
6359 ok_(__FILE__, line)(hr == S_OK, "ConvertToContiguousBuffer returned %#lx\n", hr);
6360 hr = IMFMediaBuffer_Lock(media_buffer, &buffer, NULL, &length);
6361 ok_(__FILE__, line)(hr == S_OK, "Lock returned %#lx\n", hr);
6363 /* check that buffer values are "close" enough, there's some pretty big
6364 * differences with the color converter between ffmpeg and native.
6366 for (i = 0; i < length; i++)
6368 if (i % 4 == 3) continue; /* ignore alpha diff */
6369 diff += abs((int)expect_buf[i] - (int)buffer[i]);
6371 max_diff = length * 3 * 256;
6372 ok_(__FILE__, line)(diff * 100 / max_diff == 0, "unexpected buffer data\n");
6374 if (output_file) WriteFile(output_file, buffer, length, &length, NULL);
6375 hr = IMFMediaBuffer_Unlock(media_buffer);
6376 ok_(__FILE__, line)(hr == S_OK, "Unlock returned %#lx\n", hr);
6377 ret = IMFMediaBuffer_Release(media_buffer);
6378 ok_(__FILE__, line)(ret == 1, "Release returned %lu\n", ret);
6381 #define check_sample_pcm16(a, b, c, d) check_sample_pcm16_(__LINE__, a, b, c, d)
6382 static void check_sample_pcm16_(int line, IMFSample *sample, const BYTE *expect_buf, HANDLE output_file, BOOL todo)
6384 IMFMediaBuffer *media_buffer;
6385 DWORD i, length;
6386 BYTE *buffer;
6387 HRESULT hr;
6388 ULONG ret;
6390 hr = IMFSample_ConvertToContiguousBuffer(sample, &media_buffer);
6391 ok_(__FILE__, line)(hr == S_OK, "ConvertToContiguousBuffer returned %#lx\n", hr);
6392 hr = IMFMediaBuffer_Lock(media_buffer, &buffer, NULL, &length);
6393 ok_(__FILE__, line)(hr == S_OK, "Lock returned %#lx\n", hr);
6395 /* check that buffer values are close enough, there's some differences in
6396 * the output of audio DSP between 32bit and 64bit implementation
6398 for (i = 0; i < length; i += 2)
6400 DWORD expect = *(INT16 *)(expect_buf + i), value = *(INT16 *)(buffer + i);
6401 if (expect - value + 512 > 1024) break;
6404 todo_wine_if(todo && i < length / 2)
6405 ok_(__FILE__, line)(i == length, "unexpected buffer data\n");
6407 if (output_file) WriteFile(output_file, buffer, length, &length, NULL);
6408 hr = IMFMediaBuffer_Unlock(media_buffer);
6409 ok_(__FILE__, line)(hr == S_OK, "Unlock returned %#lx\n", hr);
6410 ret = IMFMediaBuffer_Release(media_buffer);
6411 ok_(__FILE__, line)(ret == 1, "Release returned %lu\n", ret);
6414 static const BYTE wma_codec_data[10] = {0, 0x44, 0, 0, 0x17, 0, 0, 0, 0, 0};
6415 static const ULONG wmaenc_block_size = 1487;
6416 static const ULONG wmadec_block_size = 0x2000;
6418 static void test_wma_encoder(void)
6420 const GUID transform_inputs[] =
6422 MFAudioFormat_PCM,
6423 MFAudioFormat_Float,
6425 const GUID transform_outputs[] =
6427 MFAudioFormat_WMAudioV8,
6428 MFAudioFormat_WMAudioV9,
6429 MFAudioFormat_WMAudio_Lossless,
6431 const GUID dmo_inputs[] =
6433 MEDIASUBTYPE_PCM,
6435 const GUID dmo_outputs[] =
6437 MEDIASUBTYPE_WMAUDIO2,
6438 MEDIASUBTYPE_WMAUDIO3,
6439 MEDIASUBTYPE_WMAUDIO_LOSSLESS,
6442 static const struct attribute_desc input_type_desc[] =
6444 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
6445 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_Float),
6446 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 32),
6447 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
6448 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
6449 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 176400),
6450 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 8),
6451 {0},
6453 const struct attribute_desc output_type_desc[] =
6455 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
6456 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_WMAudioV8),
6457 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
6458 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
6459 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 4003),
6460 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, wmaenc_block_size),
6461 ATTR_BLOB(MF_MT_USER_DATA, wma_codec_data, sizeof(wma_codec_data)),
6462 {0},
6465 MFT_REGISTER_TYPE_INFO output_type = {MFMediaType_Audio, MFAudioFormat_WMAudioV8};
6466 MFT_REGISTER_TYPE_INFO input_type = {MFMediaType_Audio, MFAudioFormat_Float};
6467 ULONG audio_data_len, wmaenc_data_len;
6468 const BYTE *audio_data, *wmaenc_data;
6469 MFT_OUTPUT_STREAM_INFO output_info;
6470 MFT_INPUT_STREAM_INFO input_info;
6471 MFT_OUTPUT_DATA_BUFFER output;
6472 WCHAR output_path[MAX_PATH];
6473 IMFMediaType *media_type;
6474 IMFTransform *transform;
6475 DWORD status, length;
6476 HANDLE output_file;
6477 IMFSample *sample;
6478 HRSRC resource;
6479 GUID class_id;
6480 ULONG i, ret;
6481 HRESULT hr;
6482 LONG ref;
6484 hr = CoInitialize(NULL);
6485 ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
6487 if (!create_transform(MFT_CATEGORY_AUDIO_ENCODER, &input_type, &output_type, L"WMAudio Encoder MFT", &MFMediaType_Audio,
6488 transform_inputs, ARRAY_SIZE(transform_inputs), transform_outputs, ARRAY_SIZE(transform_outputs),
6489 &transform, &CLSID_CWMAEncMediaObject, &class_id))
6490 goto failed;
6492 check_dmo(&class_id, L"WMAudio Encoder DMO", &MEDIATYPE_Audio, dmo_inputs, ARRAY_SIZE(dmo_inputs),
6493 dmo_outputs, ARRAY_SIZE(dmo_outputs));
6495 check_interface(transform, &IID_IMFTransform, TRUE);
6496 check_interface(transform, &IID_IMediaObject, TRUE);
6497 check_interface(transform, &IID_IPropertyStore, TRUE);
6498 check_interface(transform, &IID_IPropertyBag, TRUE);
6500 hr = MFCreateMediaType(&media_type);
6501 ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr);
6502 init_media_type(media_type, input_type_desc, -1);
6503 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
6504 ok(hr == S_OK, "SetInputType returned %#lx.\n", hr);
6505 init_media_type(media_type, output_type_desc, -1);
6506 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
6507 ok(hr == S_OK, "SetOutputType returned %#lx.\n", hr);
6508 ret = IMFMediaType_Release(media_type);
6509 ok(ret == 0, "Release returned %lu\n", ret);
6511 memset(&input_info, 0xcd, sizeof(input_info));
6512 hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info);
6513 ok(hr == S_OK, "GetInputStreamInfo returned %#lx\n", hr);
6514 ok(input_info.hnsMaxLatency == 19969161, "got hnsMaxLatency %s\n",
6515 wine_dbgstr_longlong(input_info.hnsMaxLatency));
6516 ok(input_info.dwFlags == 0, "got dwFlags %#lx\n", input_info.dwFlags);
6517 ok(input_info.cbSize == 8, "got cbSize %lu\n", input_info.cbSize);
6518 ok(input_info.cbMaxLookahead == 0, "got cbMaxLookahead %#lx\n", input_info.cbMaxLookahead);
6519 ok(input_info.cbAlignment == 1, "got cbAlignment %#lx\n", input_info.cbAlignment);
6521 memset(&output_info, 0xcd, sizeof(output_info));
6522 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
6523 ok(hr == S_OK, "GetOutputStreamInfo returned %#lx\n", hr);
6524 ok(output_info.dwFlags == 0, "got dwFlags %#lx\n", output_info.dwFlags);
6525 ok(output_info.cbSize == wmaenc_block_size, "got cbSize %#lx\n", output_info.cbSize);
6526 ok(output_info.cbAlignment == 1, "got cbAlignment %#lx\n", output_info.cbAlignment);
6528 resource = FindResourceW(NULL, L"audiodata.bin", (const WCHAR *)RT_RCDATA);
6529 ok(resource != 0, "FindResourceW failed, error %lu\n", GetLastError());
6530 audio_data = LockResource(LoadResource(GetModuleHandleW(NULL), resource));
6531 audio_data_len = SizeofResource(GetModuleHandleW(NULL), resource);
6532 ok(audio_data_len == 179928, "got length %lu\n", audio_data_len);
6534 sample = create_sample(audio_data, audio_data_len);
6535 hr = IMFSample_SetSampleTime(sample, 0);
6536 ok(hr == S_OK, "SetSampleTime returned %#lx\n", hr);
6537 hr = IMFSample_SetSampleDuration(sample, 10000000);
6538 ok(hr == S_OK, "SetSampleDuration returned %#lx\n", hr);
6539 hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
6540 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
6541 hr = IMFTransform_ProcessMessage(transform, MFT_MESSAGE_COMMAND_DRAIN, 0);
6542 ok(hr == S_OK, "ProcessMessage returned %#lx\n", hr);
6543 hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
6544 ok(hr == MF_E_NOTACCEPTING, "ProcessInput returned %#lx\n", hr);
6545 ref = IMFSample_Release(sample);
6546 ok(ref <= 1, "Release returned %ld\n", ref);
6548 status = 0xdeadbeef;
6549 sample = create_sample(NULL, output_info.cbSize);
6550 memset(&output, 0, sizeof(output));
6551 output.pSample = sample;
6553 resource = FindResourceW(NULL, L"wmaencdata.bin", (const WCHAR *)RT_RCDATA);
6554 ok(resource != 0, "FindResourceW failed, error %lu\n", GetLastError());
6555 wmaenc_data = LockResource(LoadResource(GetModuleHandleW(NULL), resource));
6556 wmaenc_data_len = SizeofResource(GetModuleHandleW(NULL), resource);
6557 ok(wmaenc_data_len % wmaenc_block_size == 0, "got length %lu\n", wmaenc_data_len);
6559 /* and generate a new one as well in a temporary directory */
6560 GetTempPathW(ARRAY_SIZE(output_path), output_path);
6561 lstrcatW(output_path, L"wmaencdata.bin");
6562 output_file = CreateFileW(output_path, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
6563 ok(output_file != INVALID_HANDLE_VALUE, "CreateFileW failed, error %lu\n", GetLastError());
6565 i = 0;
6566 while (SUCCEEDED(hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status)))
6568 winetest_push_context("%lu", i);
6569 ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr);
6570 ok(output.pSample == sample, "got pSample %p\n", output.pSample);
6571 ok(output.dwStatus == MFT_OUTPUT_DATA_BUFFER_INCOMPLETE ||
6572 broken(output.dwStatus == (MFT_OUTPUT_DATA_BUFFER_INCOMPLETE|7)) /* win7 */,
6573 "got dwStatus %#lx\n", output.dwStatus);
6574 ok(status == 0, "got status %#lx\n", status);
6575 hr = IMFSample_GetTotalLength(sample, &length);
6576 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
6577 ok(length == wmaenc_block_size, "got length %lu\n", length);
6578 ok(wmaenc_data_len > i * wmaenc_block_size, "got %lu blocks\n", i);
6579 check_sample(sample, wmaenc_data + i * wmaenc_block_size, output_file);
6580 winetest_pop_context();
6581 i++;
6584 trace("created %s\n", debugstr_w(output_path));
6585 CloseHandle(output_file);
6587 ret = IMFSample_Release(sample);
6588 ok(ret == 0, "Release returned %lu\n", ret);
6590 status = 0xdeadbeef;
6591 sample = create_sample(NULL, output_info.cbSize);
6592 memset(&output, 0, sizeof(output));
6593 output.pSample = sample;
6594 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
6595 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
6596 ok(output.pSample == sample, "got pSample %p\n", output.pSample);
6597 ok(output.dwStatus == 0, "got dwStatus %#lx\n", output.dwStatus);
6598 ok(status == 0, "got status %#lx\n", status);
6599 hr = IMFSample_GetTotalLength(sample, &length);
6600 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
6601 ok(length == 0, "got length %lu\n", length);
6602 ret = IMFSample_Release(sample);
6603 ok(ret == 0, "Release returned %lu\n", ret);
6605 ret = IMFTransform_Release(transform);
6606 ok(ret == 0, "Release returned %lu\n", ret);
6608 failed:
6609 CoUninitialize();
6612 static void test_wma_decoder(void)
6614 const GUID transform_inputs[] =
6616 MEDIASUBTYPE_MSAUDIO1,
6617 MFAudioFormat_WMAudioV8,
6618 MFAudioFormat_WMAudioV9,
6619 MFAudioFormat_WMAudio_Lossless,
6621 const GUID transform_outputs[] =
6623 MFAudioFormat_PCM,
6624 MFAudioFormat_Float,
6626 const GUID dmo_inputs[] =
6628 MEDIASUBTYPE_MSAUDIO1,
6629 MEDIASUBTYPE_WMAUDIO2,
6630 MEDIASUBTYPE_WMAUDIO3,
6631 MEDIASUBTYPE_WMAUDIO_LOSSLESS,
6633 const GUID dmo_outputs[] =
6635 MEDIASUBTYPE_PCM,
6636 MEDIASUBTYPE_IEEE_FLOAT,
6639 static const media_type_desc expect_available_inputs[] =
6642 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
6643 ATTR_GUID(MF_MT_SUBTYPE, MEDIASUBTYPE_MSAUDIO1),
6644 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
6647 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
6648 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_WMAudioV8),
6649 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
6652 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
6653 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_WMAudioV9),
6654 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
6657 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
6658 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_WMAudio_Lossless),
6659 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
6662 static const media_type_desc expect_available_outputs[] =
6665 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
6666 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_Float),
6667 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 32),
6668 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
6669 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
6670 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 176400),
6671 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 8),
6672 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
6673 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
6674 ATTR_UINT32(MF_MT_AUDIO_PREFER_WAVEFORMATEX, 1),
6677 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
6678 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
6679 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16),
6680 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
6681 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
6682 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 88200),
6683 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 4),
6684 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
6685 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
6686 ATTR_UINT32(MF_MT_AUDIO_PREFER_WAVEFORMATEX, 1),
6690 const struct attribute_desc input_type_desc[] =
6692 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
6693 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_WMAudioV8),
6694 ATTR_BLOB(MF_MT_USER_DATA, wma_codec_data, sizeof(wma_codec_data)),
6695 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, wmaenc_block_size),
6696 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
6697 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
6698 {0},
6700 static const struct attribute_desc output_type_desc[] =
6702 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
6703 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
6704 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 88200),
6705 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16),
6706 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
6707 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
6708 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 4),
6709 {0},
6712 MFT_REGISTER_TYPE_INFO input_type = {MFMediaType_Audio, MFAudioFormat_WMAudioV8};
6713 MFT_REGISTER_TYPE_INFO output_type = {MFMediaType_Audio, MFAudioFormat_Float};
6714 IUnknown *unknown, *tmp_unknown, outer = {&test_unk_vtbl};
6715 ULONG wmadec_data_len, wmaenc_data_len;
6716 const BYTE *wmadec_data, *wmaenc_data;
6717 MFT_OUTPUT_STREAM_INFO output_info;
6718 MFT_OUTPUT_DATA_BUFFER outputs[2];
6719 MFT_INPUT_STREAM_INFO input_info;
6720 MFT_OUTPUT_DATA_BUFFER output;
6721 DWORD status, flags, length;
6722 WCHAR output_path[MAX_PATH];
6723 IMediaObject *media_object;
6724 IPropertyBag *property_bag;
6725 IMFMediaType *media_type;
6726 IMFTransform *transform;
6727 LONGLONG time, duration;
6728 HANDLE output_file;
6729 IMFSample *sample;
6730 ULONG i, ret, ref;
6731 HRSRC resource;
6732 GUID class_id;
6733 UINT32 value;
6734 HRESULT hr;
6736 hr = CoInitialize(NULL);
6737 ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
6739 if (!create_transform(MFT_CATEGORY_AUDIO_DECODER, &input_type, &output_type, L"WMAudio Decoder MFT", &MFMediaType_Audio,
6740 transform_inputs, ARRAY_SIZE(transform_inputs), transform_outputs, ARRAY_SIZE(transform_outputs),
6741 &transform, &CLSID_CWMADecMediaObject, &class_id))
6742 goto failed;
6744 check_dmo(&class_id, L"WMAudio Decoder DMO", &MEDIATYPE_Audio, dmo_inputs, ARRAY_SIZE(dmo_inputs),
6745 dmo_outputs, ARRAY_SIZE(dmo_outputs));
6747 check_interface(transform, &IID_IMFTransform, TRUE);
6748 check_interface(transform, &IID_IMediaObject, TRUE);
6749 todo_wine
6750 check_interface(transform, &IID_IPropertyStore, TRUE);
6751 check_interface(transform, &IID_IPropertyBag, TRUE);
6753 /* check default media types */
6755 hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info);
6756 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetInputStreamInfo returned %#lx\n", hr);
6757 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
6758 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetOutputStreamInfo returned %#lx\n", hr);
6759 hr = IMFTransform_GetOutputAvailableType(transform, 0, 0, &media_type);
6760 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetOutputAvailableType returned %#lx\n", hr);
6762 i = -1;
6763 while (SUCCEEDED(hr = IMFTransform_GetInputAvailableType(transform, 0, ++i, &media_type)))
6765 winetest_push_context("in %lu", i);
6766 ok(hr == S_OK, "GetInputAvailableType returned %#lx\n", hr);
6767 check_media_type(media_type, expect_available_inputs[i], -1);
6768 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
6769 ok(hr == MF_E_INVALIDMEDIATYPE, "SetInputType returned %#lx.\n", hr);
6770 ret = IMFMediaType_Release(media_type);
6771 ok(ret == 0, "Release returned %lu\n", ret);
6772 winetest_pop_context();
6774 todo_wine
6775 ok(hr == MF_E_NO_MORE_TYPES, "GetInputAvailableType returned %#lx\n", hr);
6776 todo_wine
6777 ok(i == 4, "%lu input media types\n", i);
6779 /* setting output media type first doesn't work */
6781 hr = MFCreateMediaType(&media_type);
6782 ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr);
6783 init_media_type(media_type, output_type_desc, -1);
6784 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
6785 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "SetOutputType returned %#lx.\n", hr);
6786 ret = IMFMediaType_Release(media_type);
6787 ok(ret == 0, "Release returned %lu\n", ret);
6789 /* check required input media type attributes */
6791 hr = MFCreateMediaType(&media_type);
6792 ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr);
6793 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
6794 ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetInputType returned %#lx.\n", hr);
6795 init_media_type(media_type, input_type_desc, 1);
6796 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
6797 ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetInputType returned %#lx.\n", hr);
6798 init_media_type(media_type, input_type_desc, 2);
6799 for (i = 2; i < ARRAY_SIZE(input_type_desc) - 1; ++i)
6801 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
6802 ok(hr == MF_E_INVALIDMEDIATYPE, "SetInputType returned %#lx.\n", hr);
6803 init_media_type(media_type, input_type_desc, i + 1);
6805 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
6806 ok(hr == S_OK, "SetInputType returned %#lx.\n", hr);
6807 ret = IMFMediaType_Release(media_type);
6808 ok(ret == 0, "Release returned %lu\n", ret);
6810 hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info);
6811 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetInputStreamInfo returned %#lx\n", hr);
6812 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
6813 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetOutputStreamInfo returned %#lx\n", hr);
6815 /* check new output media types */
6817 i = -1;
6818 while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, ++i, &media_type)))
6820 winetest_push_context("out %lu", i);
6821 ok(hr == S_OK, "GetOutputAvailableType returned %#lx\n", hr);
6822 check_media_type(media_type, expect_available_outputs[i], -1);
6823 ret = IMFMediaType_Release(media_type);
6824 ok(ret == 0, "Release returned %lu\n", ret);
6825 winetest_pop_context();
6827 ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
6828 ok(i == 2, "%lu output media types\n", i);
6830 /* check required output media type attributes */
6832 hr = MFCreateMediaType(&media_type);
6833 ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr);
6834 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
6835 ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetOutputType returned %#lx.\n", hr);
6836 init_media_type(media_type, output_type_desc, 1);
6837 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
6838 ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetOutputType returned %#lx.\n", hr);
6839 init_media_type(media_type, output_type_desc, 2);
6840 for (i = 2; i < ARRAY_SIZE(output_type_desc) - 1; ++i)
6842 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
6843 ok(hr == MF_E_INVALIDMEDIATYPE, "SetOutputType returned %#lx.\n", hr);
6844 init_media_type(media_type, output_type_desc, i + 1);
6846 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
6847 ok(hr == S_OK, "SetOutputType returned %#lx.\n", hr);
6848 ret = IMFMediaType_Release(media_type);
6849 ok(ret == 0, "Release returned %lu\n", ret);
6851 memset(&input_info, 0xcd, sizeof(input_info));
6852 hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info);
6853 ok(hr == S_OK, "GetInputStreamInfo returned %#lx\n", hr);
6854 ok(input_info.hnsMaxLatency == 0, "got hnsMaxLatency %s\n", wine_dbgstr_longlong(input_info.hnsMaxLatency));
6855 ok(input_info.dwFlags == 0, "got dwFlags %#lx\n", input_info.dwFlags);
6856 ok(input_info.cbSize == wmaenc_block_size, "got cbSize %lu\n", input_info.cbSize);
6857 ok(input_info.cbMaxLookahead == 0, "got cbMaxLookahead %#lx\n", input_info.cbMaxLookahead);
6858 ok(input_info.cbAlignment == 1, "got cbAlignment %#lx\n", input_info.cbAlignment);
6860 memset(&output_info, 0xcd, sizeof(output_info));
6861 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
6862 ok(hr == S_OK, "GetOutputStreamInfo returned %#lx\n", hr);
6863 ok(output_info.dwFlags == 0, "got dwFlags %#lx\n", output_info.dwFlags);
6864 todo_wine
6865 ok(output_info.cbSize == 0, "got cbSize %#lx\n", output_info.cbSize);
6866 ok(output_info.cbAlignment == 1, "got cbAlignment %#lx\n", output_info.cbAlignment);
6868 /* MF_MT_AUDIO_AVG_BYTES_PER_SECOND isn't required by SetInputType, but is needed for the transform to work */
6870 hr = MFCreateMediaType(&media_type);
6871 ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr);
6872 init_media_type(media_type, input_type_desc, -1);
6873 hr = IMFMediaType_SetUINT32(media_type, &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 4003);
6874 ok(hr == S_OK, "SetUINT32 returned %#lx\n", hr);
6875 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
6876 ok(hr == S_OK, "SetInputType returned %#lx.\n", hr);
6878 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
6879 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetOutputStreamInfo returned %#lx\n", hr);
6881 init_media_type(media_type, output_type_desc, -1);
6882 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
6883 ok(hr == S_OK, "SetInputType returned %#lx.\n", hr);
6884 ret = IMFMediaType_Release(media_type);
6885 ok(ret == 0, "Release returned %lu\n", ret);
6887 memset(&output_info, 0xcd, sizeof(output_info));
6888 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
6889 ok(hr == S_OK, "GetOutputStreamInfo returned %#lx\n", hr);
6890 ok(output_info.dwFlags == 0, "got dwFlags %#lx\n", output_info.dwFlags);
6891 ok(output_info.cbSize == wmadec_block_size, "got cbSize %#lx\n", output_info.cbSize);
6892 ok(output_info.cbAlignment == 1, "got cbAlignment %#lx\n", output_info.cbAlignment);
6894 resource = FindResourceW(NULL, L"wmaencdata.bin", (const WCHAR *)RT_RCDATA);
6895 ok(resource != 0, "FindResourceW failed, error %lu\n", GetLastError());
6896 wmaenc_data = LockResource(LoadResource(GetModuleHandleW(NULL), resource));
6897 wmaenc_data_len = SizeofResource(GetModuleHandleW(NULL), resource);
6898 ok(wmaenc_data_len % wmaenc_block_size == 0, "got length %lu\n", wmaenc_data_len);
6900 sample = create_sample(wmaenc_data, wmaenc_block_size / 2);
6901 hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
6902 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
6903 ret = IMFSample_Release(sample);
6904 ok(ret == 0, "Release returned %lu\n", ret);
6905 sample = create_sample(wmaenc_data, wmaenc_block_size + 1);
6906 hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
6907 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
6908 ret = IMFSample_Release(sample);
6909 ok(ret == 0, "Release returned %lu\n", ret);
6910 sample = create_sample(wmaenc_data, wmaenc_block_size);
6911 hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
6912 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
6913 hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
6914 ok(hr == MF_E_NOTACCEPTING, "ProcessInput returned %#lx\n", hr);
6915 ret = IMFSample_Release(sample);
6916 ok(ret == 1, "Release returned %lu\n", ret);
6918 /* As output_info.dwFlags doesn't have MFT_OUTPUT_STREAM_CAN_PROVIDE_SAMPLES
6919 * IMFTransform_ProcessOutput needs a sample or returns MF_E_TRANSFORM_NEED_MORE_INPUT */
6921 status = 0xdeadbeef;
6922 memset(&output, 0, sizeof(output));
6923 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
6924 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
6925 ok(output.dwStreamID == 0, "got dwStreamID %lu\n", output.dwStreamID);
6926 ok(!output.pSample, "got pSample %p\n", output.pSample);
6927 ok(output.dwStatus == MFT_OUTPUT_DATA_BUFFER_NO_SAMPLE ||
6928 broken(output.dwStatus == (MFT_OUTPUT_DATA_BUFFER_INCOMPLETE|MFT_OUTPUT_DATA_BUFFER_NO_SAMPLE)) /* Win7 */,
6929 "got dwStatus %#lx\n", output.dwStatus);
6930 ok(!output.pEvents, "got pEvents %p\n", output.pEvents);
6931 ok(status == 0, "got status %#lx\n", status);
6933 sample = create_sample(wmaenc_data, wmaenc_block_size);
6934 hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
6935 ok(hr == MF_E_NOTACCEPTING, "ProcessInput returned %#lx\n", hr);
6936 ret = IMFSample_Release(sample);
6937 ok(ret == 0, "Release returned %lu\n", ret);
6939 status = 0xdeadbeef;
6940 memset(&output, 0, sizeof(output));
6941 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
6942 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
6943 ok(!output.pSample, "got pSample %p\n", output.pSample);
6944 ok(output.dwStatus == MFT_OUTPUT_DATA_BUFFER_NO_SAMPLE ||
6945 broken(output.dwStatus == (MFT_OUTPUT_DATA_BUFFER_INCOMPLETE|MFT_OUTPUT_DATA_BUFFER_NO_SAMPLE)) /* Win7 */,
6946 "got dwStatus %#lx\n", output.dwStatus);
6947 ok(status == 0, "got status %#lx\n", status);
6949 status = 0xdeadbeef;
6950 memset(&output, 0, sizeof(output));
6951 output_info.cbSize = wmadec_block_size;
6952 sample = create_sample(NULL, output_info.cbSize);
6953 outputs[0].pSample = sample;
6954 sample = create_sample(NULL, output_info.cbSize);
6955 outputs[1].pSample = sample;
6956 hr = IMFTransform_ProcessOutput(transform, 0, 2, outputs, &status);
6957 ok(hr == E_INVALIDARG, "ProcessOutput returned %#lx\n", hr);
6958 ref = IMFSample_Release(outputs[0].pSample);
6959 ok(ref == 0, "Release returned %ld\n", ref);
6960 ref = IMFSample_Release(outputs[1].pSample);
6961 ok(ref == 0, "Release returned %ld\n", ref);
6963 resource = FindResourceW(NULL, L"wmadecdata.bin", (const WCHAR *)RT_RCDATA);
6964 ok(resource != 0, "FindResourceW failed, error %lu\n", GetLastError());
6965 wmadec_data = LockResource(LoadResource(GetModuleHandleW(NULL), resource));
6966 wmadec_data_len = SizeofResource(GetModuleHandleW(NULL), resource);
6967 ok(wmadec_data_len == wmadec_block_size * 7 / 2, "got length %lu\n", wmadec_data_len);
6969 /* and generate a new one as well in a temporary directory */
6970 GetTempPathW(ARRAY_SIZE(output_path), output_path);
6971 lstrcatW(output_path, L"wmadecdata.bin");
6972 output_file = CreateFileW(output_path, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
6973 ok(output_file != INVALID_HANDLE_VALUE, "CreateFileW failed, error %lu\n", GetLastError());
6975 status = 0xdeadbeef;
6976 output_info.cbSize = wmadec_block_size;
6977 sample = create_sample(NULL, output_info.cbSize);
6978 memset(&output, 0, sizeof(output));
6979 output.pSample = sample;
6980 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
6982 for (i = 0; i < 4; ++i)
6984 winetest_push_context("%lu", i);
6986 ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr);
6987 ok(output.pSample == sample, "got pSample %p\n", output.pSample);
6988 ok(output.dwStatus == MFT_OUTPUT_DATA_BUFFER_INCOMPLETE || output.dwStatus == 0 ||
6989 broken(output.dwStatus == (MFT_OUTPUT_DATA_BUFFER_INCOMPLETE|7) || output.dwStatus == 7) /* Win7 */,
6990 "got dwStatus %#lx\n", output.dwStatus);
6991 ok(status == 0, "got status %#lx\n", status);
6992 value = 0xdeadbeef;
6993 hr = IMFSample_GetUINT32(sample, &MFSampleExtension_CleanPoint, &value);
6994 ok(hr == S_OK, "GetUINT32 MFSampleExtension_CleanPoint returned %#lx\n", hr);
6995 ok(value == 1, "got MFSampleExtension_CleanPoint %u\n", value);
6996 hr = IMFSample_GetTotalLength(sample, &length);
6997 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
6998 flags = 0xdeadbeef;
6999 hr = IMFSample_GetSampleFlags(sample, &flags);
7000 ok(hr == S_OK, "GetSampleFlags returned %#lx\n", hr);
7001 ok(flags == 0, "got flags %#lx\n", flags);
7002 time = 0xdeadbeef;
7003 hr = IMFSample_GetSampleTime(sample, &time);
7004 ok(hr == S_OK, "GetSampleTime returned %#lx\n", hr);
7005 ok(time == i * 928798, "got time %I64d\n", time);
7006 duration = 0xdeadbeef;
7007 hr = IMFSample_GetSampleDuration(sample, &duration);
7008 ok(hr == S_OK, "GetSampleDuration returned %#lx\n", hr);
7009 if (output.dwStatus == MFT_OUTPUT_DATA_BUFFER_INCOMPLETE ||
7010 broken(output.dwStatus == (MFT_OUTPUT_DATA_BUFFER_INCOMPLETE|7)))
7012 ok(length == wmadec_block_size, "got length %lu\n", length);
7013 ok(duration == 928798, "got duration %I64d\n", duration);
7014 check_sample_pcm16(sample, wmadec_data, output_file, TRUE);
7015 wmadec_data += wmadec_block_size;
7016 wmadec_data_len -= wmadec_block_size;
7018 else
7020 /* FFmpeg doesn't seem to decode WMA buffers in the same way as native */
7021 todo_wine
7022 ok(length == wmadec_block_size / 2, "got length %lu\n", length);
7023 todo_wine
7024 ok(duration == 464399, "got duration %I64d\n", duration);
7026 if (length == wmadec_block_size / 2)
7027 check_sample_pcm16(sample, wmadec_data, output_file, FALSE);
7028 wmadec_data += length;
7029 wmadec_data_len -= length;
7031 ret = IMFSample_Release(sample);
7032 ok(ret == 0, "Release returned %lu\n", ret);
7034 status = 0xdeadbeef;
7035 sample = create_sample(NULL, output_info.cbSize);
7036 memset(&output, 0, sizeof(output));
7037 output.pSample = sample;
7038 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
7040 winetest_pop_context();
7042 /* some FFmpeg version request more input to complete decoding */
7043 if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT && i == 2) break;
7045 todo_wine
7046 ok(wmadec_data_len == 0, "missing %#lx bytes\n", wmadec_data_len);
7048 trace("created %s\n", debugstr_w(output_path));
7049 CloseHandle(output_file);
7051 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
7052 ok(output.pSample == sample, "got pSample %p\n", output.pSample);
7053 ok(output.dwStatus == 0, "got dwStatus %#lx\n", output.dwStatus);
7054 ok(status == 0, "got status %#lx\n", status);
7055 ret = IMFSample_Release(sample);
7056 ok(ret == 0, "Release returned %lu\n", ret);
7058 status = 0xdeadbeef;
7059 sample = create_sample(NULL, output_info.cbSize);
7060 memset(&output, 0, sizeof(output));
7061 output.pSample = sample;
7062 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
7063 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
7064 ok(output.pSample == sample, "got pSample %p\n", output.pSample);
7065 ok(output.dwStatus == 0 ||
7066 broken(output.dwStatus == (MFT_OUTPUT_DATA_BUFFER_INCOMPLETE|7)) /* Win7 */,
7067 "got dwStatus %#lx\n", output.dwStatus);
7068 ok(status == 0, "got status %#lx\n", status);
7069 hr = IMFSample_GetTotalLength(sample, &length);
7070 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
7071 ok(length == 0, "got length %lu\n", length);
7072 ret = IMFSample_Release(sample);
7073 ok(ret == 0, "Release returned %lu\n", ret);
7075 sample = create_sample(wmaenc_data, wmaenc_block_size);
7076 hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
7077 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
7079 ret = IMFTransform_Release(transform);
7080 ok(ret == 0, "Release returned %lu\n", ret);
7081 ret = IMFSample_Release(sample);
7082 ok(ret == 0, "Release returned %lu\n", ret);
7084 hr = CoCreateInstance( &CLSID_CWMADecMediaObject, &outer, CLSCTX_INPROC_SERVER, &IID_IUnknown,
7085 (void **)&unknown );
7086 ok( hr == S_OK, "CoCreateInstance returned %#lx\n", hr );
7087 hr = IUnknown_QueryInterface( unknown, &IID_IMFTransform, (void **)&transform );
7088 ok( hr == S_OK, "QueryInterface returned %#lx\n", hr );
7089 hr = IUnknown_QueryInterface( unknown, &IID_IMediaObject, (void **)&media_object );
7090 ok( hr == S_OK, "QueryInterface returned %#lx\n", hr );
7091 hr = IUnknown_QueryInterface( unknown, &IID_IPropertyBag, (void **)&property_bag );
7092 ok( hr == S_OK, "QueryInterface returned %#lx\n", hr );
7093 hr = IUnknown_QueryInterface( media_object, &IID_IUnknown, (void **)&tmp_unknown );
7094 ok( hr == S_OK, "QueryInterface returned %#lx\n", hr );
7096 ok( unknown != &outer, "got outer IUnknown\n" );
7097 ok( transform != (void *)unknown, "got IUnknown == IMFTransform\n" );
7098 ok( media_object != (void *)unknown, "got IUnknown == IMediaObject\n" );
7099 ok( property_bag != (void *)unknown, "got IUnknown == IPropertyBag\n" );
7100 ok( tmp_unknown != unknown, "got inner IUnknown\n" );
7102 check_interface( unknown, &IID_IPersistPropertyBag, FALSE );
7103 check_interface( unknown, &IID_IAMFilterMiscFlags, FALSE );
7104 check_interface( unknown, &IID_IMediaSeeking, FALSE );
7105 check_interface( unknown, &IID_IMediaPosition, FALSE );
7106 check_interface( unknown, &IID_IReferenceClock, FALSE );
7107 check_interface( unknown, &IID_IBasicAudio, FALSE );
7109 ref = IUnknown_Release( tmp_unknown );
7110 ok( ref == 1, "Release returned %lu\n", ref );
7111 ref = IPropertyBag_Release( property_bag );
7112 ok( ref == 1, "Release returned %lu\n", ref );
7113 ref = IMediaObject_Release( media_object );
7114 ok( ref == 1, "Release returned %lu\n", ref );
7115 ref = IMFTransform_Release( transform );
7116 ok( ref == 1, "Release returned %lu\n", ref );
7117 ref = IUnknown_Release( unknown );
7118 ok( ref == 0, "Release returned %lu\n", ref );
7120 failed:
7121 CoUninitialize();
7124 #define next_h264_sample(a, b) next_h264_sample_(__LINE__, a, b)
7125 static IMFSample *next_h264_sample_(int line, const BYTE **h264_buf, ULONG *h264_len)
7127 const BYTE *sample_data;
7129 ok_(__FILE__, line)(*h264_len > 4, "invalid h264 length\n");
7130 ok_(__FILE__, line)(*(UINT32 *)*h264_buf == 0x01000000, "invalid h264 buffer\n");
7131 sample_data = *h264_buf;
7133 (*h264_len) -= 4;
7134 (*h264_buf) += 4;
7136 while (*h264_len >= 4 && *(UINT32 *)*h264_buf != 0x01000000)
7138 (*h264_len)--;
7139 (*h264_buf)++;
7142 return create_sample(sample_data, *h264_buf - sample_data);
7145 static void test_h264_decoder(void)
7147 const GUID transform_inputs[] =
7149 MFVideoFormat_H264,
7150 MFVideoFormat_H264_ES,
7152 const GUID transform_outputs[] =
7154 MFVideoFormat_NV12,
7155 MFVideoFormat_YV12,
7156 MFVideoFormat_IYUV,
7157 MFVideoFormat_I420,
7158 MFVideoFormat_YUY2,
7160 static const media_type_desc default_inputs[] =
7163 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
7164 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_H264),
7167 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
7168 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_H264_ES),
7171 static const DWORD input_width = 120, input_height = 248;
7172 const media_type_desc default_outputs[] =
7175 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
7176 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12),
7177 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
7178 ATTR_RATIO(MF_MT_FRAME_RATE, 30000, 1001),
7179 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, input_width),
7180 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
7181 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
7182 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
7183 ATTR_RATIO(MF_MT_FRAME_SIZE, input_width, input_height),
7184 ATTR_UINT32(MF_MT_SAMPLE_SIZE, input_width * input_height * 3 / 2),
7185 /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
7188 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
7189 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YV12),
7190 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
7191 ATTR_RATIO(MF_MT_FRAME_RATE, 30000, 1001),
7192 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, input_width),
7193 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
7194 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
7195 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
7196 ATTR_RATIO(MF_MT_FRAME_SIZE, input_width, input_height),
7197 ATTR_UINT32(MF_MT_SAMPLE_SIZE, input_width * input_height * 3 / 2),
7198 /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
7201 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
7202 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_IYUV),
7203 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
7204 ATTR_RATIO(MF_MT_FRAME_RATE, 30000, 1001),
7205 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, input_width),
7206 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
7207 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
7208 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
7209 ATTR_RATIO(MF_MT_FRAME_SIZE, input_width, input_height),
7210 ATTR_UINT32(MF_MT_SAMPLE_SIZE, input_width * input_height * 3 / 2),
7211 /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
7214 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
7215 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_I420),
7216 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
7217 ATTR_RATIO(MF_MT_FRAME_RATE, 30000, 1001),
7218 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, input_width),
7219 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
7220 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
7221 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
7222 ATTR_RATIO(MF_MT_FRAME_SIZE, input_width, input_height),
7223 ATTR_UINT32(MF_MT_SAMPLE_SIZE, input_width * input_height * 3 / 2),
7224 /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
7227 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
7228 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YUY2),
7229 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
7230 ATTR_RATIO(MF_MT_FRAME_RATE, 30000, 1001),
7231 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, input_width * 2),
7232 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
7233 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
7234 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
7235 ATTR_RATIO(MF_MT_FRAME_SIZE, input_width, input_height),
7236 ATTR_UINT32(MF_MT_SAMPLE_SIZE, input_width * input_height * 2),
7237 /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
7240 const struct attribute_desc input_type_desc[] =
7242 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
7243 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_H264),
7244 ATTR_RATIO(MF_MT_FRAME_SIZE, input_width, input_height),
7245 {0},
7247 const struct attribute_desc minimal_output_type_desc[] =
7249 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
7250 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12),
7251 ATTR_RATIO(MF_MT_FRAME_SIZE, input_width, input_height),
7252 {0},
7254 const struct attribute_desc output_type_desc[] =
7256 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
7257 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12),
7258 ATTR_RATIO(MF_MT_FRAME_SIZE, input_width, input_height),
7259 ATTR_RATIO(MF_MT_FRAME_RATE, 60000, 1000),
7260 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 2, 1),
7261 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, 3840),
7262 ATTR_UINT32(MF_MT_SAMPLE_SIZE, 3840 * input_height * 3 / 2),
7263 ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0),
7264 {0},
7266 static const struct attribute_desc new_output_type_desc[] =
7268 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
7269 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_I420),
7270 ATTR_RATIO(MF_MT_FRAME_SIZE, 96, 96),
7271 ATTR_RATIO(MF_MT_FRAME_RATE, 1, 1),
7272 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 2),
7273 {0},
7275 static const MFVideoArea actual_aperture = {.Area={82,84}};
7276 static const DWORD actual_width = 96, actual_height = 96;
7277 const media_type_desc actual_outputs[] =
7280 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
7281 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12),
7282 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
7283 ATTR_RATIO(MF_MT_FRAME_RATE, 60000, 1000),
7284 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
7285 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 3 / 2),
7286 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width),
7287 /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
7288 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
7289 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
7290 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
7291 ATTR_BLOB(MF_MT_MINIMUM_DISPLAY_APERTURE, &actual_aperture, 16),
7294 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
7295 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YV12),
7296 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
7297 ATTR_RATIO(MF_MT_FRAME_RATE, 60000, 1000),
7298 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
7299 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 3 / 2),
7300 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width),
7301 /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
7302 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
7303 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
7304 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
7305 ATTR_BLOB(MF_MT_MINIMUM_DISPLAY_APERTURE, &actual_aperture, 16),
7308 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
7309 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_IYUV),
7310 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
7311 ATTR_RATIO(MF_MT_FRAME_RATE, 60000, 1000),
7312 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
7313 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 3 / 2),
7314 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width),
7315 /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
7316 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
7317 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
7318 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
7319 ATTR_BLOB(MF_MT_MINIMUM_DISPLAY_APERTURE, &actual_aperture, 16),
7322 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
7323 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_I420),
7324 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
7325 ATTR_RATIO(MF_MT_FRAME_RATE, 60000, 1000),
7326 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
7327 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 3 / 2),
7328 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width),
7329 /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
7330 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
7331 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
7332 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
7333 ATTR_BLOB(MF_MT_MINIMUM_DISPLAY_APERTURE, &actual_aperture, 16),
7336 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
7337 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YUY2),
7338 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
7339 ATTR_RATIO(MF_MT_FRAME_RATE, 60000, 1000),
7340 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
7341 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 2),
7342 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width * 2),
7343 /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
7344 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
7345 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
7346 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
7347 ATTR_BLOB(MF_MT_MINIMUM_DISPLAY_APERTURE, &actual_aperture, 16),
7351 MFT_REGISTER_TYPE_INFO input_type = {MFMediaType_Video, MFVideoFormat_H264};
7352 MFT_REGISTER_TYPE_INFO output_type = {MFMediaType_Video, MFVideoFormat_NV12};
7353 const BYTE *h264_encoded_data, *nv12_frame_data, *i420_frame_data;
7354 ULONG h264_encoded_data_len, nv12_frame_len, i420_frame_len;
7355 DWORD input_id, output_id, input_count, output_count;
7356 MFT_OUTPUT_STREAM_INFO output_info;
7357 MFT_INPUT_STREAM_INFO input_info;
7358 MFT_OUTPUT_DATA_BUFFER output;
7359 IMFMediaBuffer *media_buffer;
7360 DWORD status, length, count;
7361 WCHAR output_path[MAX_PATH];
7362 IMFAttributes *attributes;
7363 IMFMediaType *media_type;
7364 LONGLONG time, duration;
7365 IMFTransform *transform;
7366 ULONG i, ret, flags;
7367 HANDLE output_file;
7368 IMFSample *sample;
7369 HRSRC resource;
7370 GUID class_id;
7371 UINT32 value;
7372 BYTE *data;
7373 HRESULT hr;
7375 hr = CoInitialize(NULL);
7376 ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
7378 if (!create_transform(MFT_CATEGORY_VIDEO_DECODER, &input_type, &output_type, L"Microsoft H264 Video Decoder MFT", &MFMediaType_Video,
7379 transform_inputs, ARRAY_SIZE(transform_inputs), transform_outputs, ARRAY_SIZE(transform_outputs),
7380 &transform, &CLSID_MSH264DecoderMFT, &class_id))
7381 goto failed;
7383 hr = IMFTransform_GetAttributes(transform, &attributes);
7384 ok(hr == S_OK, "GetAttributes returned %#lx\n", hr);
7385 hr = IMFAttributes_SetUINT32(attributes, &MF_LOW_LATENCY, 1);
7386 ok(hr == S_OK, "SetUINT32 returned %#lx\n", hr);
7387 ret = IMFAttributes_Release(attributes);
7388 todo_wine
7389 ok(ret == 1, "Release returned %ld\n", ret);
7391 /* no output type is available before an input type is set */
7393 hr = IMFTransform_GetOutputAvailableType(transform, 0, 0, &media_type);
7394 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetOutputAvailableType returned %#lx\n", hr);
7395 hr = IMFTransform_GetOutputCurrentType(transform, 0, &media_type);
7396 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetOutputCurrentType returned %#lx\n", hr);
7398 /* setting output media type first doesn't work */
7400 hr = MFCreateMediaType(&media_type);
7401 ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr);
7402 init_media_type(media_type, default_outputs[0], -1);
7403 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
7404 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "SetOutputType returned %#lx.\n", hr);
7405 ret = IMFMediaType_Release(media_type);
7406 ok(ret == 0, "Release returned %lu\n", ret);
7408 /* check available input types */
7410 flags = MFT_INPUT_STREAM_WHOLE_SAMPLES | MFT_INPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER | MFT_INPUT_STREAM_FIXED_SAMPLE_SIZE;
7411 memset(&input_info, 0xcd, sizeof(input_info));
7412 hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info);
7413 todo_wine
7414 ok(hr == S_OK, "GetInputStreamInfo returned %#lx\n", hr);
7415 todo_wine
7416 ok(input_info.hnsMaxLatency == 0, "got hnsMaxLatency %s\n", wine_dbgstr_longlong(input_info.hnsMaxLatency));
7417 todo_wine
7418 ok(input_info.dwFlags == flags, "got dwFlags %#lx\n", input_info.dwFlags);
7419 todo_wine
7420 ok(input_info.cbSize == 0x1000, "got cbSize %lu\n", input_info.cbSize);
7421 todo_wine
7422 ok(input_info.cbMaxLookahead == 0, "got cbMaxLookahead %#lx\n", input_info.cbMaxLookahead);
7423 todo_wine
7424 ok(input_info.cbAlignment == 0, "got cbAlignment %#lx\n", input_info.cbAlignment);
7426 flags = MFT_OUTPUT_STREAM_WHOLE_SAMPLES | MFT_OUTPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER | MFT_OUTPUT_STREAM_FIXED_SAMPLE_SIZE;
7427 memset(&output_info, 0xcd, sizeof(output_info));
7428 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
7429 ok(hr == S_OK, "GetOutputStreamInfo returned %#lx\n", hr);
7430 ok(output_info.dwFlags == flags, "got dwFlags %#lx\n", output_info.dwFlags);
7431 ok(output_info.cbSize == 1920 * 1088 * 2, "got cbSize %#lx\n", output_info.cbSize);
7432 ok(output_info.cbAlignment == 0, "got cbAlignment %#lx\n", output_info.cbAlignment);
7434 i = -1;
7435 while (SUCCEEDED(hr = IMFTransform_GetInputAvailableType(transform, 0, ++i, &media_type)))
7437 winetest_push_context("in %lu", i);
7438 ok(hr == S_OK, "GetInputAvailableType returned %#lx\n", hr);
7439 check_media_type(media_type, default_inputs[i], -1);
7440 ret = IMFMediaType_Release(media_type);
7441 ok(ret == 0, "Release returned %lu\n", ret);
7442 winetest_pop_context();
7444 ok(hr == MF_E_NO_MORE_TYPES, "GetInputAvailableType returned %#lx\n", hr);
7445 ok(i == 2 || broken(i == 1) /* Win7 */, "%lu input media types\n", i);
7447 /* check required input media type attributes */
7449 hr = MFCreateMediaType(&media_type);
7450 ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr);
7451 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
7452 ok(hr == E_INVALIDARG, "SetInputType returned %#lx.\n", hr);
7453 init_media_type(media_type, input_type_desc, 1);
7454 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
7455 todo_wine
7456 ok(hr == MF_E_INVALIDMEDIATYPE, "SetInputType returned %#lx.\n", hr);
7457 init_media_type(media_type, input_type_desc, 2);
7458 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
7459 ok(hr == S_OK, "SetInputType returned %#lx.\n", hr);
7460 init_media_type(media_type, input_type_desc, -1);
7461 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
7462 ok(hr == S_OK, "SetInputType returned %#lx.\n", hr);
7463 ret = IMFMediaType_Release(media_type);
7464 ok(ret == 1, "Release returned %lu\n", ret);
7466 flags = MFT_OUTPUT_STREAM_WHOLE_SAMPLES | MFT_OUTPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER | MFT_OUTPUT_STREAM_FIXED_SAMPLE_SIZE;
7467 memset(&output_info, 0xcd, sizeof(output_info));
7468 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
7469 ok(hr == S_OK, "GetOutputStreamInfo returned %#lx\n", hr);
7470 ok(output_info.dwFlags == flags, "got dwFlags %#lx\n", output_info.dwFlags);
7471 todo_wine
7472 ok(output_info.cbSize == input_width * input_height * 2, "got cbSize %#lx\n", output_info.cbSize);
7473 ok(output_info.cbAlignment == 0, "got cbAlignment %#lx\n", output_info.cbAlignment);
7475 /* output types can now be enumerated (though they are actually the same for all input types) */
7477 i = -1;
7478 while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, ++i, &media_type)))
7480 winetest_push_context("out %lu", i);
7481 ok(hr == S_OK, "GetOutputAvailableType returned %#lx\n", hr);
7482 check_media_type(media_type, default_outputs[i], -1);
7483 ret = IMFMediaType_Release(media_type);
7484 ok(ret == 0, "Release returned %lu\n", ret);
7485 winetest_pop_context();
7487 ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
7488 ok(i == 5, "%lu output media types\n", i);
7490 /* check required output media type attributes */
7492 hr = MFCreateMediaType(&media_type);
7493 ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr);
7494 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
7495 todo_wine
7496 ok(hr == E_INVALIDARG, "SetOutputType returned %#lx.\n", hr);
7497 init_media_type(media_type, minimal_output_type_desc, 1);
7498 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
7499 todo_wine
7500 ok(hr == MF_E_INVALIDMEDIATYPE, "SetOutputType returned %#lx.\n", hr);
7501 init_media_type(media_type, minimal_output_type_desc, 2);
7502 for (i = 2; i < ARRAY_SIZE(minimal_output_type_desc) - 1; ++i)
7504 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
7505 todo_wine
7506 ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetOutputType returned %#lx.\n", hr);
7507 init_media_type(media_type, minimal_output_type_desc, i + 1);
7509 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
7510 ok(hr == S_OK, "SetOutputType returned %#lx.\n", hr);
7511 init_media_type(media_type, output_type_desc, -1);
7512 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
7513 ok(hr == S_OK, "SetOutputType returned %#lx.\n", hr);
7514 ret = IMFMediaType_Release(media_type);
7515 ok(ret == 1, "Release returned %lu\n", ret);
7517 hr = IMFTransform_GetOutputCurrentType(transform, 0, &media_type);
7518 ok(hr == S_OK, "GetOutputCurrentType returned %#lx\n", hr);
7519 check_media_type(media_type, output_type_desc, -1);
7520 ret = IMFMediaType_Release(media_type);
7521 ok(ret == 0, "Release returned %lu\n", ret);
7523 /* check that the output media type we've selected don't change the enumeration */
7525 i = -1;
7526 while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, ++i, &media_type)))
7528 winetest_push_context("out %lu", i);
7529 ok(hr == S_OK, "GetOutputAvailableType returned %#lx\n", hr);
7530 check_media_type(media_type, default_outputs[i], -1);
7531 ret = IMFMediaType_Release(media_type);
7532 ok(ret == 0, "Release returned %lu\n", ret);
7533 winetest_pop_context();
7535 ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
7536 ok(i == 5, "%lu output media types\n", i);
7538 flags = MFT_INPUT_STREAM_WHOLE_SAMPLES | MFT_INPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER | MFT_INPUT_STREAM_FIXED_SAMPLE_SIZE;
7539 memset(&input_info, 0xcd, sizeof(input_info));
7540 hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info);
7541 ok(hr == S_OK, "GetInputStreamInfo returned %#lx\n", hr);
7542 ok(input_info.hnsMaxLatency == 0, "got hnsMaxLatency %s\n", wine_dbgstr_longlong(input_info.hnsMaxLatency));
7543 ok(input_info.dwFlags == flags, "got dwFlags %#lx\n", input_info.dwFlags);
7544 ok(input_info.cbSize == 0x1000, "got cbSize %lu\n", input_info.cbSize);
7545 ok(input_info.cbMaxLookahead == 0, "got cbMaxLookahead %#lx\n", input_info.cbMaxLookahead);
7546 ok(input_info.cbAlignment == 0, "got cbAlignment %#lx\n", input_info.cbAlignment);
7548 flags = MFT_OUTPUT_STREAM_WHOLE_SAMPLES | MFT_OUTPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER | MFT_OUTPUT_STREAM_FIXED_SAMPLE_SIZE;
7549 memset(&output_info, 0xcd, sizeof(output_info));
7550 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
7551 ok(hr == S_OK, "GetOutputStreamInfo returned %#lx\n", hr);
7552 ok(output_info.dwFlags == flags, "got dwFlags %#lx\n", output_info.dwFlags);
7553 todo_wine
7554 ok(output_info.cbSize == input_width * input_height * 2, "got cbSize %#lx\n", output_info.cbSize);
7555 ok(output_info.cbAlignment == 0, "got cbAlignment %#lx\n", output_info.cbAlignment);
7557 input_count = output_count = 0xdeadbeef;
7558 hr = IMFTransform_GetStreamCount(transform, &input_count, &output_count);
7559 todo_wine
7560 ok(hr == S_OK, "GetStreamCount returned %#lx\n", hr);
7561 todo_wine
7562 ok(input_count == 1, "got input_count %lu\n", input_count);
7563 todo_wine
7564 ok(output_count == 1, "got output_count %lu\n", output_count);
7565 hr = IMFTransform_GetStreamIDs(transform, 1, &input_id, 1, &output_id);
7566 ok(hr == E_NOTIMPL, "GetStreamIDs returned %#lx\n", hr);
7568 resource = FindResourceW(NULL, L"h264data.bin", (const WCHAR *)RT_RCDATA);
7569 ok(resource != 0, "FindResourceW failed, error %lu\n", GetLastError());
7570 h264_encoded_data = LockResource(LoadResource(GetModuleHandleW(NULL), resource));
7571 h264_encoded_data_len = SizeofResource(GetModuleHandleW(NULL), resource);
7573 /* As output_info.dwFlags doesn't have MFT_OUTPUT_STREAM_CAN_PROVIDE_SAMPLES
7574 * IMFTransform_ProcessOutput needs a sample or returns an error */
7576 status = 0;
7577 memset(&output, 0, sizeof(output));
7578 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
7579 ok(hr == E_INVALIDARG || hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
7580 ok(output.dwStreamID == 0, "got dwStreamID %lu\n", output.dwStreamID);
7581 ok(!output.pSample, "got pSample %p\n", output.pSample);
7582 ok(output.dwStatus == 0, "got dwStatus %#lx\n", output.dwStatus);
7583 ok(!output.pEvents, "got pEvents %p\n", output.pEvents);
7584 ok(status == 0, "got status %#lx\n", status);
7586 i = 0;
7587 sample = next_h264_sample(&h264_encoded_data, &h264_encoded_data_len);
7588 while (1)
7590 status = 0;
7591 memset(&output, 0, sizeof(output));
7592 output.pSample = create_sample(NULL, output_info.cbSize);
7593 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
7594 if (hr != MF_E_TRANSFORM_NEED_MORE_INPUT) break;
7595 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
7596 ok(output.dwStreamID == 0, "got dwStreamID %lu\n", output.dwStreamID);
7597 ok(!!output.pSample, "got pSample %p\n", output.pSample);
7598 ok(output.dwStatus == 0, "got dwStatus %#lx\n", output.dwStatus);
7599 ok(!output.pEvents, "got pEvents %p\n", output.pEvents);
7600 ok(status == 0, "got status %#lx\n", status);
7601 hr = IMFSample_GetTotalLength(output.pSample, &length);
7602 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
7603 ok(length == 0, "got length %lu\n", length);
7604 ret = IMFSample_Release(output.pSample);
7605 ok(ret == 0, "Release returned %lu\n", ret);
7607 hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
7608 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
7609 ret = IMFSample_Release(sample);
7610 ok(ret <= 1, "Release returned %lu\n", ret);
7611 sample = next_h264_sample(&h264_encoded_data, &h264_encoded_data_len);
7613 hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
7614 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
7615 ret = IMFSample_Release(sample);
7616 ok(ret <= 1, "Release returned %lu\n", ret);
7617 sample = next_h264_sample(&h264_encoded_data, &h264_encoded_data_len);
7618 i++;
7620 hr = IMFTransform_ProcessMessage(transform, MFT_MESSAGE_COMMAND_DRAIN, 0);
7621 ok(hr == S_OK, "ProcessMessage returned %#lx\n", hr);
7623 todo_wine
7624 ok(i == 2, "got %lu iterations\n", i);
7625 todo_wine
7626 ok(h264_encoded_data_len == 1180, "got h264_encoded_data_len %lu\n", h264_encoded_data_len);
7627 ok(hr == MF_E_TRANSFORM_STREAM_CHANGE, "ProcessOutput returned %#lx\n", hr);
7628 ok(output.dwStreamID == 0, "got dwStreamID %lu\n", output.dwStreamID);
7629 ok(!!output.pSample, "got pSample %p\n", output.pSample);
7630 ok(output.dwStatus == MFT_OUTPUT_DATA_BUFFER_FORMAT_CHANGE,
7631 "got dwStatus %#lx\n", output.dwStatus);
7632 ok(!output.pEvents, "got pEvents %p\n", output.pEvents);
7633 ok(status == MFT_PROCESS_OUTPUT_STATUS_NEW_STREAMS,
7634 "got status %#lx\n", status);
7635 hr = IMFSample_GetTotalLength(output.pSample, &length);
7636 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
7637 ok(length == 0, "got length %lu\n", length);
7638 ret = IMFSample_Release(output.pSample);
7639 ok(ret == 0, "Release returned %lu\n", ret);
7641 flags = MFT_OUTPUT_STREAM_WHOLE_SAMPLES | MFT_OUTPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER | MFT_OUTPUT_STREAM_FIXED_SAMPLE_SIZE;
7642 memset(&output_info, 0xcd, sizeof(output_info));
7643 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
7644 ok(hr == S_OK, "GetOutputStreamInfo returned %#lx\n", hr);
7645 ok(output_info.dwFlags == flags, "got dwFlags %#lx\n", output_info.dwFlags);
7646 ok(output_info.cbSize == actual_width * actual_height * 2, "got cbSize %#lx\n", output_info.cbSize);
7647 ok(output_info.cbAlignment == 0, "got cbAlignment %#lx\n", output_info.cbAlignment);
7649 i = -1;
7650 while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, ++i, &media_type)))
7652 winetest_push_context("out %lu", i);
7653 ok(hr == S_OK, "GetOutputAvailableType returned %#lx\n", hr);
7654 check_media_type(media_type, actual_outputs[i], -1);
7655 ret = IMFMediaType_Release(media_type);
7656 ok(ret == 0, "Release returned %lu\n", ret);
7657 winetest_pop_context();
7659 ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
7660 ok(i == 5, "%lu output media types\n", i);
7662 /* current output type is still the one we selected */
7663 hr = IMFTransform_GetOutputCurrentType(transform, 0, &media_type);
7664 ok(hr == S_OK, "GetOutputCurrentType returned %#lx\n", hr);
7665 check_media_type(media_type, output_type_desc, -1);
7666 hr = IMFMediaType_GetItemType(media_type, &MF_MT_MINIMUM_DISPLAY_APERTURE, NULL);
7667 ok(hr == MF_E_ATTRIBUTENOTFOUND, "GetItemType returned %#lx\n", hr);
7668 ret = IMFMediaType_Release(media_type);
7669 ok(ret == 0, "Release returned %lu\n", ret);
7671 /* and generate a new one as well in a temporary directory */
7672 GetTempPathW(ARRAY_SIZE(output_path), output_path);
7673 lstrcatW(output_path, L"nv12frame.bin");
7674 output_file = CreateFileW(output_path, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
7675 ok(output_file != INVALID_HANDLE_VALUE, "CreateFileW failed, error %lu\n", GetLastError());
7677 resource = FindResourceW(NULL, L"nv12frame.bin", (const WCHAR *)RT_RCDATA);
7678 ok(resource != 0, "FindResourceW failed, error %lu\n", GetLastError());
7679 nv12_frame_data = LockResource(LoadResource(GetModuleHandleW(NULL), resource));
7680 nv12_frame_len = SizeofResource(GetModuleHandleW(NULL), resource);
7681 ok(nv12_frame_len == actual_width * actual_height * 3 / 2, "got frame length %lu\n", nv12_frame_len);
7683 status = 0;
7684 memset(&output, 0, sizeof(output));
7685 output.pSample = create_sample(NULL, nv12_frame_len);
7686 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
7687 ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr);
7688 ok(output.dwStreamID == 0, "got dwStreamID %lu\n", output.dwStreamID);
7689 ok(!!output.pSample, "got pSample %p\n", output.pSample);
7690 ok(output.dwStatus == 0, "got dwStatus %#lx\n", output.dwStatus);
7691 ok(!output.pEvents, "got pEvents %p\n", output.pEvents);
7692 ok(status == 0, "got status %#lx\n", status);
7694 hr = IMFSample_GetUINT32(sample, &MFSampleExtension_CleanPoint, &value);
7695 ok(hr == MF_E_ATTRIBUTENOTFOUND, "GetUINT32 MFSampleExtension_CleanPoint returned %#lx\n", hr);
7697 count = 0xdeadbeef;
7698 hr = IMFSample_GetBufferCount(output.pSample, &count);
7699 ok(hr == S_OK, "GetBufferCount returned %#lx\n", hr);
7700 ok(count == 1, "got count %#lx\n", count);
7702 flags = 0xdeadbeef;
7703 hr = IMFSample_GetSampleFlags(output.pSample, &flags);
7704 ok(hr == S_OK, "GetSampleFlags returned %#lx\n", hr);
7705 ok(flags == 0, "got flags %#lx\n", flags);
7707 time = 0xdeadbeef;
7708 hr = IMFSample_GetSampleTime(output.pSample, &time);
7709 ok(hr == S_OK, "GetSampleTime returned %#lx\n", hr);
7710 ok(time == 0, "got time %I64d\n", time);
7712 /* doesn't matter what frame rate we've selected, duration is defined by the stream */
7713 duration = 0xdeadbeef;
7714 hr = IMFSample_GetSampleDuration(output.pSample, &duration);
7715 ok(hr == S_OK, "GetSampleDuration returned %#lx\n", hr);
7716 ok(duration - 333666 <= 2, "got duration %I64d\n", duration);
7718 /* Win8 and before pad the data with garbage instead of original
7719 * buffer data, make sure it's consistent. */
7720 hr = IMFSample_ConvertToContiguousBuffer(output.pSample, &media_buffer);
7721 ok(hr == S_OK, "ConvertToContiguousBuffer returned %#lx\n", hr);
7722 hr = IMFMediaBuffer_Lock(media_buffer, &data, NULL, &length);
7723 ok(hr == S_OK, "Lock returned %#lx\n", hr);
7724 ok(length == nv12_frame_len, "got length %lu\n", length);
7726 for (i = 0; i < actual_aperture.Area.cy; ++i)
7728 memset(data + actual_width * i + actual_aperture.Area.cx, 0xcd, actual_width - actual_aperture.Area.cx);
7729 memset(data + actual_width * (actual_height + i / 2) + actual_aperture.Area.cx, 0xcd, actual_width - actual_aperture.Area.cx);
7731 memset(data + actual_width * actual_aperture.Area.cy, 0xcd, (actual_height - actual_aperture.Area.cy) * actual_width);
7732 memset(data + actual_width * (actual_height + actual_aperture.Area.cy / 2), 0xcd, (actual_height - actual_aperture.Area.cy) / 2 * actual_width);
7734 hr = IMFMediaBuffer_Unlock(media_buffer);
7735 ok(hr == S_OK, "Unlock returned %#lx\n", hr);
7736 IMFMediaBuffer_Release(media_buffer);
7738 check_sample(output.pSample, nv12_frame_data, output_file);
7740 ret = IMFSample_Release(output.pSample);
7741 ok(ret == 0, "Release returned %lu\n", ret);
7743 trace("created %s\n", debugstr_w(output_path));
7744 CloseHandle(output_file);
7746 /* we can change it, but only with the correct frame size */
7747 hr = MFCreateMediaType(&media_type);
7748 ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr);
7749 init_media_type(media_type, output_type_desc, -1);
7750 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
7751 ok(hr == MF_E_INVALIDMEDIATYPE, "SetOutputType returned %#lx.\n", hr);
7752 init_media_type(media_type, new_output_type_desc, -1);
7753 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
7754 ok(hr == S_OK, "SetOutputType returned %#lx.\n", hr);
7755 ret = IMFMediaType_Release(media_type);
7756 ok(ret == 1, "Release returned %lu\n", ret);
7758 hr = IMFTransform_GetOutputCurrentType(transform, 0, &media_type);
7759 ok(hr == S_OK, "GetOutputCurrentType returned %#lx\n", hr);
7760 check_media_type(media_type, new_output_type_desc, -1);
7761 hr = IMFMediaType_GetItemType(media_type, &MF_MT_MINIMUM_DISPLAY_APERTURE, NULL);
7762 ok(hr == MF_E_ATTRIBUTENOTFOUND, "GetItemType returned %#lx\n", hr);
7763 ret = IMFMediaType_Release(media_type);
7764 ok(ret == 0, "Release returned %lu\n", ret);
7766 status = 0;
7767 memset(&output, 0, sizeof(output));
7768 output.pSample = create_sample(NULL, actual_width * actual_height * 2);
7769 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
7770 todo_wine
7771 ok(hr == MF_E_TRANSFORM_STREAM_CHANGE, "ProcessOutput returned %#lx\n", hr);
7773 while (hr == MF_E_TRANSFORM_NEED_MORE_INPUT)
7775 hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
7776 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
7777 ret = IMFSample_Release(sample);
7778 ok(ret <= 1, "Release returned %lu\n", ret);
7779 sample = next_h264_sample(&h264_encoded_data, &h264_encoded_data_len);
7780 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
7781 todo_wine_if(hr == MF_E_TRANSFORM_NEED_MORE_INPUT)
7782 ok(hr == MF_E_TRANSFORM_STREAM_CHANGE, "ProcessOutput returned %#lx\n", hr);
7785 ok(output.dwStreamID == 0, "got dwStreamID %lu\n", output.dwStreamID);
7786 ok(!!output.pSample, "got pSample %p\n", output.pSample);
7787 ok(output.dwStatus == MFT_OUTPUT_DATA_BUFFER_FORMAT_CHANGE, "got dwStatus %#lx\n", output.dwStatus);
7788 ok(!output.pEvents, "got pEvents %p\n", output.pEvents);
7789 ok(status == MFT_PROCESS_OUTPUT_STATUS_NEW_STREAMS, "got status %#lx\n", status);
7790 hr = IMFSample_GetTotalLength(output.pSample, &length);
7791 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
7792 ok(length == 0, "got length %lu\n", length);
7793 ret = IMFSample_Release(output.pSample);
7794 ok(ret == 0, "Release returned %lu\n", ret);
7796 GetTempPathW(ARRAY_SIZE(output_path), output_path);
7797 lstrcatW(output_path, L"i420frame.bin");
7798 output_file = CreateFileW(output_path, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
7799 ok(output_file != INVALID_HANDLE_VALUE, "CreateFileW failed, error %lu\n", GetLastError());
7801 resource = FindResourceW(NULL, L"i420frame.bin", (const WCHAR *)RT_RCDATA);
7802 ok(resource != 0, "FindResourceW failed, error %lu\n", GetLastError());
7803 i420_frame_data = LockResource(LoadResource(GetModuleHandleW(NULL), resource));
7804 i420_frame_len = SizeofResource(GetModuleHandleW(NULL), resource);
7805 ok(i420_frame_len == actual_width * actual_height * 3 / 2, "got frame length %lu\n", i420_frame_len);
7807 status = 0;
7808 memset(&output, 0, sizeof(output));
7809 output.pSample = create_sample(NULL, actual_width * actual_height * 2);
7810 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
7811 ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr);
7812 ok(output.dwStreamID == 0, "got dwStreamID %lu\n", output.dwStreamID);
7813 ok(!!output.pSample, "got pSample %p\n", output.pSample);
7814 ok(output.dwStatus == 0, "got dwStatus %#lx\n", output.dwStatus);
7815 ok(!output.pEvents, "got pEvents %p\n", output.pEvents);
7816 ok(status == 0, "got status %#lx\n", status);
7818 hr = IMFSample_GetSampleTime(output.pSample, &time);
7819 ok(hr == S_OK, "GetSampleTime returned %#lx\n", hr);
7820 todo_wine_if(time == 1334666) /* when VA-API plugin is used */
7821 ok(time - 333666 <= 2, "got time %I64d\n", time);
7823 duration = 0xdeadbeef;
7824 hr = IMFSample_GetSampleDuration(output.pSample, &duration);
7825 ok(hr == S_OK, "GetSampleDuration returned %#lx\n", hr);
7826 ok(duration - 333666 <= 2, "got duration %I64d\n", duration);
7828 /* Win8 and before pad the data with garbage instead of original
7829 * buffer data, make sure it's consistent. */
7830 hr = IMFSample_ConvertToContiguousBuffer(output.pSample, &media_buffer);
7831 ok(hr == S_OK, "ConvertToContiguousBuffer returned %#lx\n", hr);
7832 hr = IMFMediaBuffer_Lock(media_buffer, &data, NULL, &length);
7833 ok(hr == S_OK, "Lock returned %#lx\n", hr);
7834 ok(length == i420_frame_len, "got length %lu\n", length);
7836 for (i = 0; i < actual_aperture.Area.cy; ++i)
7838 memset(data + actual_width * i + actual_aperture.Area.cx, 0xcd, actual_width - actual_aperture.Area.cx);
7839 memset(data + actual_width * actual_height + actual_width / 2 * i + actual_aperture.Area.cx / 2, 0xcd,
7840 actual_width / 2 - actual_aperture.Area.cx / 2);
7841 memset(data + actual_width * actual_height + actual_width / 2 * (actual_height / 2 + i) + actual_aperture.Area.cx / 2, 0xcd,
7842 actual_width / 2 - actual_aperture.Area.cx / 2);
7844 memset(data + actual_width * actual_aperture.Area.cy, 0xcd, (actual_height - actual_aperture.Area.cy) * actual_width);
7845 memset(data + actual_width * actual_height + actual_width / 2 * actual_aperture.Area.cy / 2, 0xcd,
7846 (actual_height - actual_aperture.Area.cy) / 2 * actual_width / 2);
7847 memset(data + actual_width * actual_height + actual_width / 2 * (actual_height / 2 + actual_aperture.Area.cy / 2), 0xcd,
7848 (actual_height - actual_aperture.Area.cy) / 2 * actual_width / 2);
7850 hr = IMFMediaBuffer_Unlock(media_buffer);
7851 ok(hr == S_OK, "Unlock returned %#lx\n", hr);
7852 IMFMediaBuffer_Release(media_buffer);
7854 check_sample(output.pSample, i420_frame_data, output_file);
7856 ret = IMFSample_Release(output.pSample);
7857 ok(ret == 0, "Release returned %lu\n", ret);
7859 trace("created %s\n", debugstr_w(output_path));
7860 CloseHandle(output_file);
7862 status = 0;
7863 memset(&output, 0, sizeof(output));
7864 output.pSample = create_sample(NULL, actual_width * actual_height * 2);
7865 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
7866 todo_wine_if(hr == S_OK) /* when VA-API plugin is used */
7867 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
7868 ok(output.dwStreamID == 0, "got dwStreamID %lu\n", output.dwStreamID);
7869 ok(!!output.pSample, "got pSample %p\n", output.pSample);
7870 ok(output.dwStatus == 0, "got dwStatus %#lx\n", output.dwStatus);
7871 ok(!output.pEvents, "got pEvents %p\n", output.pEvents);
7872 ok(status == 0, "got status %#lx\n", status);
7873 ret = IMFSample_Release(output.pSample);
7874 ok(ret == 0, "Release returned %lu\n", ret);
7876 ret = IMFTransform_Release(transform);
7877 ok(ret == 0, "Release returned %lu\n", ret);
7878 ret = IMFSample_Release(sample);
7879 ok(ret == 0, "Release returned %lu\n", ret);
7881 failed:
7882 CoUninitialize();
7885 static void test_audio_convert(void)
7887 const GUID transform_inputs[2] =
7889 MFAudioFormat_PCM,
7890 MFAudioFormat_Float,
7892 const GUID transform_outputs[2] =
7894 MFAudioFormat_PCM,
7895 MFAudioFormat_Float,
7898 static const media_type_desc expect_available_inputs[] =
7901 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
7902 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_Float),
7903 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
7906 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
7907 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
7908 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
7911 static const media_type_desc expect_available_outputs[] =
7914 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
7915 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_Float),
7916 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
7919 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
7920 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
7921 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
7924 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
7925 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_Float),
7926 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 32),
7927 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
7928 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 48000),
7929 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 384000),
7930 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 8),
7931 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
7932 ATTR_UINT32(MF_MT_AUDIO_PREFER_WAVEFORMATEX, 1),
7935 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
7936 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
7937 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16),
7938 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
7939 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 48000),
7940 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 192000),
7941 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 4),
7942 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
7943 ATTR_UINT32(MF_MT_AUDIO_PREFER_WAVEFORMATEX, 1),
7947 static const struct attribute_desc input_type_desc[] =
7949 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
7950 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_Float),
7951 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 32),
7952 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
7953 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
7954 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 176400),
7955 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 8),
7956 {0},
7958 const struct attribute_desc output_type_desc[] =
7960 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
7961 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
7962 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16),
7963 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
7964 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100),
7965 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 176400),
7966 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 4),
7967 {0},
7970 MFT_REGISTER_TYPE_INFO output_type = {MFMediaType_Audio, MFAudioFormat_PCM};
7971 MFT_REGISTER_TYPE_INFO input_type = {MFMediaType_Audio, MFAudioFormat_Float};
7972 static const ULONG audioconv_block_size = 0x4000;
7973 ULONG audio_data_len, audioconv_data_len;
7974 const BYTE *audio_data, *audioconv_data;
7975 MFT_OUTPUT_STREAM_INFO output_info;
7976 MFT_INPUT_STREAM_INFO input_info;
7977 MFT_OUTPUT_DATA_BUFFER output;
7978 WCHAR output_path[MAX_PATH];
7979 IMFMediaType *media_type;
7980 LONGLONG time, duration;
7981 IMFTransform *transform;
7982 DWORD length, status;
7983 HANDLE output_file;
7984 IMFSample *sample;
7985 HRSRC resource;
7986 GUID class_id;
7987 ULONG i, ret;
7988 HRESULT hr;
7990 hr = CoInitialize(NULL);
7991 ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
7993 if (!create_transform(MFT_CATEGORY_AUDIO_EFFECT, &input_type, &output_type, L"Resampler MFT", &MFMediaType_Audio,
7994 transform_inputs, ARRAY_SIZE(transform_inputs), transform_outputs, ARRAY_SIZE(transform_outputs),
7995 &transform, &CLSID_CResamplerMediaObject, &class_id))
7996 goto failed;
7998 check_dmo(&class_id, L"Resampler DMO", &MEDIATYPE_Audio, transform_inputs, ARRAY_SIZE(transform_inputs),
7999 transform_outputs, ARRAY_SIZE(transform_outputs));
8001 check_interface(transform, &IID_IMFTransform, TRUE);
8002 check_interface(transform, &IID_IMediaObject, TRUE);
8003 check_interface(transform, &IID_IPropertyStore, TRUE);
8004 check_interface(transform, &IID_IPropertyBag, TRUE);
8005 /* check_interface(transform, &IID_IWMResamplerProps, TRUE); */
8007 /* check default media types */
8009 hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info);
8010 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetInputStreamInfo returned %#lx\n", hr);
8011 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
8012 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetOutputStreamInfo returned %#lx\n", hr);
8014 i = -1;
8015 while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, ++i, &media_type)))
8017 winetest_push_context("out %lu", i);
8018 ok(hr == S_OK, "GetOutputAvailableType returned %#lx\n", hr);
8019 check_media_type(media_type, expect_available_outputs[i], -1);
8020 ret = IMFMediaType_Release(media_type);
8021 ok(ret == 0, "Release returned %lu\n", ret);
8022 winetest_pop_context();
8024 ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
8025 ok(i == 4, "%lu output media types\n", i);
8027 i = -1;
8028 while (SUCCEEDED(hr = IMFTransform_GetInputAvailableType(transform, 0, ++i, &media_type)))
8030 winetest_push_context("in %lu", i);
8031 ok(hr == S_OK, "GetInputAvailableType returned %#lx\n", hr);
8032 check_media_type(media_type, expect_available_inputs[i], -1);
8033 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
8034 ok(hr == MF_E_INVALIDMEDIATYPE, "SetInputType returned %#lx.\n", hr);
8035 ret = IMFMediaType_Release(media_type);
8036 ok(ret == 0, "Release returned %lu\n", ret);
8037 winetest_pop_context();
8039 ok(hr == MF_E_NO_MORE_TYPES, "GetInputAvailableType returned %#lx\n", hr);
8040 ok(i == 2, "%lu input media types\n", i);
8042 /* setting output media type first doesn't work */
8044 hr = MFCreateMediaType(&media_type);
8045 ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr);
8046 init_media_type(media_type, output_type_desc, -1);
8047 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
8048 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "SetOutputType returned %#lx.\n", hr);
8049 ret = IMFMediaType_Release(media_type);
8050 ok(ret == 0, "Release returned %lu\n", ret);
8052 /* check required input media type attributes */
8054 hr = MFCreateMediaType(&media_type);
8055 ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr);
8056 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
8057 ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetInputType returned %#lx.\n", hr);
8058 init_media_type(media_type, input_type_desc, 1);
8059 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
8060 ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetInputType returned %#lx.\n", hr);
8061 init_media_type(media_type, input_type_desc, 2);
8062 for (i = 2; i < ARRAY_SIZE(input_type_desc) - 1; ++i)
8064 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
8065 ok(hr == MF_E_INVALIDMEDIATYPE, "SetInputType returned %#lx.\n", hr);
8066 init_media_type(media_type, input_type_desc, i + 1);
8068 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
8069 ok(hr == S_OK, "SetInputType returned %#lx.\n", hr);
8070 ret = IMFMediaType_Release(media_type);
8071 ok(ret == 0, "Release returned %lu\n", ret);
8073 hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info);
8074 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetInputStreamInfo returned %#lx\n", hr);
8075 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
8076 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetOutputStreamInfo returned %#lx\n", hr);
8078 /* check new output media types */
8080 i = -1;
8081 while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, ++i, &media_type)))
8083 winetest_push_context("out %lu", i);
8084 ok(hr == S_OK, "GetOutputAvailableType returned %#lx\n", hr);
8085 check_media_type(media_type, expect_available_outputs[i], -1);
8086 ret = IMFMediaType_Release(media_type);
8087 ok(ret == 0, "Release returned %lu\n", ret);
8088 winetest_pop_context();
8090 ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
8091 ok(i == 4, "%lu output media types\n", i);
8093 /* check required output media type attributes */
8095 hr = MFCreateMediaType(&media_type);
8096 ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr);
8097 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
8098 ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetOutputType returned %#lx.\n", hr);
8099 init_media_type(media_type, output_type_desc, 1);
8100 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
8101 ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetOutputType returned %#lx.\n", hr);
8102 init_media_type(media_type, output_type_desc, 2);
8103 for (i = 2; i < ARRAY_SIZE(output_type_desc) - 1; ++i)
8105 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
8106 ok(hr == MF_E_INVALIDMEDIATYPE, "SetOutputType returned %#lx.\n", hr);
8107 init_media_type(media_type, output_type_desc, i + 1);
8109 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
8110 ok(hr == S_OK, "SetOutputType returned %#lx.\n", hr);
8111 ret = IMFMediaType_Release(media_type);
8112 ok(ret == 0, "Release returned %lu\n", ret);
8114 memset(&input_info, 0xcd, sizeof(input_info));
8115 hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info);
8116 ok(hr == S_OK, "GetInputStreamInfo returned %#lx\n", hr);
8117 ok(input_info.hnsMaxLatency == 0, "got hnsMaxLatency %s\n", wine_dbgstr_longlong(input_info.hnsMaxLatency));
8118 ok(input_info.dwFlags == 0, "got dwFlags %#lx\n", input_info.dwFlags);
8119 ok(input_info.cbSize == 8, "got cbSize %lu\n", input_info.cbSize);
8120 ok(input_info.cbMaxLookahead == 0, "got cbMaxLookahead %#lx\n", input_info.cbMaxLookahead);
8121 ok(input_info.cbAlignment == 1, "got cbAlignment %#lx\n", input_info.cbAlignment);
8123 memset(&output_info, 0xcd, sizeof(output_info));
8124 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
8125 ok(hr == S_OK, "GetOutputStreamInfo returned %#lx\n", hr);
8126 ok(output_info.dwFlags == 0, "got dwFlags %#lx\n", output_info.dwFlags);
8127 ok(output_info.cbSize == 4, "got cbSize %#lx\n", output_info.cbSize);
8128 ok(output_info.cbAlignment == 1, "got cbAlignment %#lx\n", output_info.cbAlignment);
8130 resource = FindResourceW(NULL, L"audiodata.bin", (const WCHAR *)RT_RCDATA);
8131 ok(resource != 0, "FindResourceW failed, error %lu\n", GetLastError());
8132 audio_data = LockResource(LoadResource(GetModuleHandleW(NULL), resource));
8133 audio_data_len = SizeofResource(GetModuleHandleW(NULL), resource);
8134 ok(audio_data_len == 179928, "got length %lu\n", audio_data_len);
8136 sample = create_sample(audio_data, audio_data_len);
8137 hr = IMFSample_SetSampleTime(sample, 0);
8138 ok(hr == S_OK, "SetSampleTime returned %#lx\n", hr);
8139 hr = IMFSample_SetSampleDuration(sample, 10000000);
8140 ok(hr == S_OK, "SetSampleDuration returned %#lx\n", hr);
8141 hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
8142 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
8143 hr = IMFTransform_ProcessMessage(transform, MFT_MESSAGE_COMMAND_DRAIN, 0);
8144 ok(hr == S_OK, "ProcessMessage returned %#lx\n", hr);
8145 hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
8146 ok(hr == MF_E_NOTACCEPTING, "ProcessInput returned %#lx\n", hr);
8147 ret = IMFSample_Release(sample);
8148 ok(ret <= 1, "Release returned %ld\n", ret);
8150 status = 0xdeadbeef;
8151 sample = create_sample(NULL, audioconv_block_size);
8152 memset(&output, 0, sizeof(output));
8153 output.pSample = sample;
8155 resource = FindResourceW(NULL, L"audioconvdata.bin", (const WCHAR *)RT_RCDATA);
8156 ok(resource != 0, "FindResourceW failed, error %lu\n", GetLastError());
8157 audioconv_data = LockResource(LoadResource(GetModuleHandleW(NULL), resource));
8158 audioconv_data_len = SizeofResource(GetModuleHandleW(NULL), resource);
8159 ok(audioconv_data_len == 179924, "got length %lu\n", audioconv_data_len);
8161 /* and generate a new one as well in a temporary directory */
8162 GetTempPathW(ARRAY_SIZE(output_path), output_path);
8163 lstrcatW(output_path, L"audioconvdata.bin");
8164 output_file = CreateFileW(output_path, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
8165 ok(output_file != INVALID_HANDLE_VALUE, "CreateFileW failed, error %lu\n", GetLastError());
8167 i = 0;
8168 while (SUCCEEDED(hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status)))
8170 winetest_push_context("%lu", i);
8171 ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr);
8172 ok(output.pSample == sample, "got pSample %p\n", output.pSample);
8173 ok(output.dwStatus == MFT_OUTPUT_DATA_BUFFER_INCOMPLETE || output.dwStatus == 0 ||
8174 broken(output.dwStatus == (MFT_OUTPUT_DATA_BUFFER_INCOMPLETE|6) || output.dwStatus == 6) /* win7 */,
8175 "got dwStatus %#lx\n", output.dwStatus);
8176 ok(status == 0, "got status %#lx\n", status);
8177 if (!(output.dwStatus & MFT_OUTPUT_DATA_BUFFER_INCOMPLETE))
8179 winetest_pop_context();
8180 break;
8183 hr = IMFSample_GetSampleTime(sample, &time);
8184 ok(hr == S_OK, "GetSampleTime returned %#lx\n", hr);
8185 ok(time == i * 928798, "got time %I64d\n", time);
8186 hr = IMFSample_GetSampleDuration(sample, &duration);
8187 ok(hr == S_OK, "GetSampleDuration returned %#lx\n", hr);
8188 ok(duration == 928798, "got duration %I64d\n", duration);
8189 hr = IMFSample_GetTotalLength(sample, &length);
8190 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
8191 ok(length == audioconv_block_size, "got length %lu\n", length);
8192 ok(audioconv_data_len > audioconv_block_size, "got remaining length %lu\n", audioconv_data_len);
8193 check_sample_pcm16(sample, audioconv_data, output_file, FALSE);
8194 audioconv_data_len -= audioconv_block_size;
8195 audioconv_data += audioconv_block_size;
8197 winetest_pop_context();
8198 i++;
8201 hr = IMFSample_GetSampleTime(sample, &time);
8202 ok(hr == S_OK, "GetSampleTime returned %#lx\n", hr);
8203 ok(time == i * 928798, "got time %I64d\n", time);
8204 hr = IMFSample_GetSampleDuration(sample, &duration);
8205 ok(hr == S_OK, "GetSampleDuration returned %#lx\n", hr);
8206 todo_wine
8207 ok(duration == 897506, "got duration %I64d\n", duration);
8208 hr = IMFSample_GetTotalLength(sample, &length);
8209 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
8210 todo_wine
8211 ok(length == 15832, "got length %lu\n", length);
8212 ok(audioconv_data_len == 16084, "got remaining length %lu\n", audioconv_data_len);
8213 check_sample_pcm16(sample, audioconv_data, output_file, FALSE);
8214 audioconv_data_len -= length;
8215 audioconv_data += length;
8217 memset(&output, 0, sizeof(output));
8218 output.pSample = sample;
8219 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
8220 todo_wine
8221 ok(hr == S_OK || broken(hr == MF_E_TRANSFORM_NEED_MORE_INPUT) /* win7 */, "ProcessOutput returned %#lx\n", hr);
8222 ok(output.pSample == sample, "got pSample %p\n", output.pSample);
8223 todo_wine
8224 ok(output.dwStatus == MFT_OUTPUT_DATA_BUFFER_INCOMPLETE || broken(output.dwStatus == 0) /* win7 */,
8225 "got dwStatus %#lx\n", output.dwStatus);
8226 ok(status == 0, "got status %#lx\n", status);
8228 if (hr == S_OK)
8230 hr = IMFSample_GetSampleTime(sample, &time);
8231 ok(hr == S_OK, "GetSampleTime returned %#lx\n", hr);
8232 todo_wine
8233 ok(time == 10185486, "got time %I64d\n", time);
8234 hr = IMFSample_GetSampleDuration(sample, &duration);
8235 ok(hr == S_OK, "GetSampleDuration returned %#lx\n", hr);
8236 todo_wine
8237 ok(duration == 14286, "got duration %I64d\n", duration);
8238 hr = IMFSample_GetTotalLength(sample, &length);
8239 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
8240 todo_wine
8241 ok(length == audioconv_data_len, "got length %lu\n", length);
8242 if (length == audioconv_data_len)
8243 check_sample_pcm16(sample, audioconv_data, output_file, FALSE);
8246 trace("created %s\n", debugstr_w(output_path));
8247 CloseHandle(output_file);
8249 ret = IMFSample_Release(sample);
8250 ok(ret == 0, "Release returned %lu\n", ret);
8252 status = 0xdeadbeef;
8253 sample = create_sample(NULL, audioconv_block_size);
8254 memset(&output, 0, sizeof(output));
8255 output.pSample = sample;
8256 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
8257 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
8258 ok(output.pSample == sample, "got pSample %p\n", output.pSample);
8259 ok(output.dwStatus == 0, "got dwStatus %#lx\n", output.dwStatus);
8260 ok(status == 0, "got status %#lx\n", status);
8261 hr = IMFSample_GetTotalLength(sample, &length);
8262 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
8263 ok(length == 0, "got length %lu\n", length);
8264 ret = IMFSample_Release(sample);
8265 ok(ret == 0, "Release returned %lu\n", ret);
8267 ret = IMFTransform_Release(transform);
8268 ok(ret == 0, "Release returned %lu\n", ret);
8270 failed:
8271 CoUninitialize();
8274 static void test_color_convert(void)
8276 const GUID transform_inputs[20] =
8278 MFVideoFormat_YV12,
8279 MFVideoFormat_YUY2,
8280 MFVideoFormat_UYVY,
8281 MFVideoFormat_AYUV,
8282 MFVideoFormat_NV12,
8283 DMOVideoFormat_RGB32,
8284 DMOVideoFormat_RGB565,
8285 MFVideoFormat_I420,
8286 MFVideoFormat_IYUV,
8287 MFVideoFormat_YVYU,
8288 DMOVideoFormat_RGB24,
8289 DMOVideoFormat_RGB555,
8290 DMOVideoFormat_RGB8,
8291 MEDIASUBTYPE_V216,
8292 MEDIASUBTYPE_V410,
8293 MFVideoFormat_NV11,
8294 MFVideoFormat_Y41P,
8295 MFVideoFormat_Y41T,
8296 MFVideoFormat_Y42T,
8297 MFVideoFormat_YVU9,
8299 const GUID transform_outputs[16] =
8301 MFVideoFormat_YV12,
8302 MFVideoFormat_YUY2,
8303 MFVideoFormat_UYVY,
8304 MFVideoFormat_AYUV,
8305 MFVideoFormat_NV12,
8306 DMOVideoFormat_RGB32,
8307 DMOVideoFormat_RGB565,
8308 MFVideoFormat_I420,
8309 MFVideoFormat_IYUV,
8310 MFVideoFormat_YVYU,
8311 DMOVideoFormat_RGB24,
8312 DMOVideoFormat_RGB555,
8313 DMOVideoFormat_RGB8,
8314 MEDIASUBTYPE_V216,
8315 MEDIASUBTYPE_V410,
8316 MFVideoFormat_NV11,
8318 const GUID dmo_inputs[20] =
8320 MEDIASUBTYPE_YV12,
8321 MEDIASUBTYPE_YUY2,
8322 MEDIASUBTYPE_UYVY,
8323 MEDIASUBTYPE_AYUV,
8324 MEDIASUBTYPE_NV12,
8325 MEDIASUBTYPE_RGB32,
8326 MEDIASUBTYPE_RGB565,
8327 MEDIASUBTYPE_I420,
8328 MEDIASUBTYPE_IYUV,
8329 MEDIASUBTYPE_YVYU,
8330 MEDIASUBTYPE_RGB24,
8331 MEDIASUBTYPE_RGB555,
8332 MEDIASUBTYPE_RGB8,
8333 MEDIASUBTYPE_V216,
8334 MEDIASUBTYPE_V410,
8335 MEDIASUBTYPE_NV11,
8336 MEDIASUBTYPE_Y41P,
8337 MEDIASUBTYPE_Y41T,
8338 MEDIASUBTYPE_Y42T,
8339 MEDIASUBTYPE_YVU9,
8341 const GUID dmo_outputs[16] =
8343 MEDIASUBTYPE_YV12,
8344 MEDIASUBTYPE_YUY2,
8345 MEDIASUBTYPE_UYVY,
8346 MEDIASUBTYPE_AYUV,
8347 MEDIASUBTYPE_NV12,
8348 MEDIASUBTYPE_RGB32,
8349 MEDIASUBTYPE_RGB565,
8350 MEDIASUBTYPE_I420,
8351 MEDIASUBTYPE_IYUV,
8352 MEDIASUBTYPE_YVYU,
8353 MEDIASUBTYPE_RGB24,
8354 MEDIASUBTYPE_RGB555,
8355 MEDIASUBTYPE_RGB8,
8356 MEDIASUBTYPE_V216,
8357 MEDIASUBTYPE_V410,
8358 MEDIASUBTYPE_NV11,
8361 static const media_type_desc expect_available_inputs[20] =
8363 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YV12), },
8364 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YUY2), },
8365 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_UYVY), },
8366 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_AYUV), },
8367 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12), },
8368 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32), },
8369 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB565), },
8370 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_I420), },
8371 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_IYUV), },
8372 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YVYU), },
8373 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB24), },
8374 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB555), },
8375 { ATTR_GUID(MF_MT_SUBTYPE, MEDIASUBTYPE_RGB8), },
8376 { ATTR_GUID(MF_MT_SUBTYPE, MEDIASUBTYPE_V216), },
8377 { ATTR_GUID(MF_MT_SUBTYPE, MEDIASUBTYPE_V410), },
8378 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV11), },
8379 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_Y41P), },
8380 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_Y41T), },
8381 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_Y42T), },
8382 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YVU9), },
8384 static const media_type_desc expect_available_outputs[16] =
8386 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YV12), },
8387 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YUY2), },
8388 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_UYVY), },
8389 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_AYUV), },
8390 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12), },
8391 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32), },
8392 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB565), },
8393 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_I420), },
8394 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_IYUV), },
8395 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YVYU), },
8396 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB24), },
8397 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB555), },
8398 { ATTR_GUID(MF_MT_SUBTYPE, MEDIASUBTYPE_RGB8), },
8399 { ATTR_GUID(MF_MT_SUBTYPE, MEDIASUBTYPE_V216), },
8400 { ATTR_GUID(MF_MT_SUBTYPE, MEDIASUBTYPE_V410), },
8401 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV11), },
8403 static const media_type_desc expect_available_common =
8405 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
8406 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
8407 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
8410 static const MFVideoArea actual_aperture = {.Area={82,84}};
8411 static const DWORD actual_width = 96, actual_height = 96;
8412 const struct attribute_desc input_type_desc[] =
8414 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
8415 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12),
8416 ATTR_BLOB(MF_MT_MINIMUM_DISPLAY_APERTURE, &actual_aperture, 16),
8417 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
8418 {0},
8420 const struct attribute_desc output_type_desc[] =
8422 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
8423 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32),
8424 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
8425 {0},
8428 MFT_REGISTER_TYPE_INFO output_type = {MFMediaType_Video, MFVideoFormat_NV12};
8429 MFT_REGISTER_TYPE_INFO input_type = {MFMediaType_Video, MFVideoFormat_I420};
8430 ULONG nv12frame_data_len, rgb32_data_len;
8431 const BYTE *nv12frame_data, *rgb32_data;
8432 MFT_OUTPUT_STREAM_INFO output_info;
8433 MFT_INPUT_STREAM_INFO input_info;
8434 MFT_OUTPUT_DATA_BUFFER output;
8435 WCHAR output_path[MAX_PATH];
8436 IMFMediaType *media_type;
8437 LONGLONG time, duration;
8438 IMFTransform *transform;
8439 DWORD length, status;
8440 HANDLE output_file;
8441 IMFSample *sample;
8442 HRSRC resource;
8443 GUID class_id;
8444 ULONG i, ret;
8445 HRESULT hr;
8447 hr = CoInitialize(NULL);
8448 ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
8450 if (!create_transform(MFT_CATEGORY_VIDEO_EFFECT, &input_type, &output_type, L"Color Converter MFT", &MFMediaType_Video,
8451 transform_inputs, ARRAY_SIZE(transform_inputs), transform_outputs, ARRAY_SIZE(transform_outputs),
8452 &transform, &CLSID_CColorConvertDMO, &class_id))
8453 goto failed;
8455 check_dmo(&CLSID_CColorConvertDMO, L"Color Converter DMO", &MEDIATYPE_Video, dmo_inputs, ARRAY_SIZE(dmo_inputs),
8456 dmo_outputs, ARRAY_SIZE(dmo_outputs));
8458 check_interface(transform, &IID_IMFTransform, TRUE);
8459 check_interface(transform, &IID_IMediaObject, TRUE);
8460 check_interface(transform, &IID_IPropertyStore, TRUE);
8461 todo_wine
8462 check_interface(transform, &IID_IMFRealTimeClient, TRUE);
8463 /* check_interface(transform, &IID_IWMColorConvProps, TRUE); */
8465 /* check default media types */
8467 hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info);
8468 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetInputStreamInfo returned %#lx\n", hr);
8469 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
8470 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetOutputStreamInfo returned %#lx\n", hr);
8472 i = -1;
8473 while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, ++i, &media_type)))
8475 winetest_push_context("out %lu", i);
8476 ok(hr == S_OK, "GetOutputAvailableType returned %#lx\n", hr);
8477 check_media_type(media_type, expect_available_common, -1);
8478 check_media_type(media_type, expect_available_outputs[i], -1);
8479 ret = IMFMediaType_Release(media_type);
8480 ok(ret == 0, "Release returned %lu\n", ret);
8481 winetest_pop_context();
8483 ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
8484 ok(i == 16, "%lu output media types\n", i);
8486 i = -1;
8487 while (SUCCEEDED(hr = IMFTransform_GetInputAvailableType(transform, 0, ++i, &media_type)))
8489 winetest_push_context("in %lu", i);
8490 ok(hr == S_OK, "GetInputAvailableType returned %#lx\n", hr);
8491 check_media_type(media_type, expect_available_common, -1);
8492 check_media_type(media_type, expect_available_inputs[i], -1);
8493 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
8494 if (i == 12)
8496 todo_wine
8497 ok(hr == MF_E_INVALIDMEDIATYPE, "SetInputType returned %#lx.\n", hr);
8499 else
8500 ok(hr == E_INVALIDARG, "SetInputType returned %#lx.\n", hr);
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, "GetInputAvailableType returned %#lx\n", hr);
8506 ok(i == 20, "%lu input media types\n", i);
8508 /* check required output media type attributes */
8510 hr = MFCreateMediaType(&media_type);
8511 ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr);
8512 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
8513 ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetOutputType returned %#lx.\n", hr);
8514 init_media_type(media_type, output_type_desc, 1);
8515 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
8516 ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetOutputType returned %#lx.\n", hr);
8517 init_media_type(media_type, output_type_desc, 2);
8518 for (i = 2; i < ARRAY_SIZE(output_type_desc) - 1; ++i)
8520 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
8521 ok(hr == E_INVALIDARG, "SetOutputType returned %#lx.\n", hr);
8522 init_media_type(media_type, output_type_desc, i + 1);
8524 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
8525 ok(hr == S_OK, "SetOutputType returned %#lx.\n", hr);
8526 ret = IMFMediaType_Release(media_type);
8527 ok(ret == 0, "Release returned %lu\n", ret);
8529 /* check required input media type attributes */
8531 hr = MFCreateMediaType(&media_type);
8532 ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr);
8533 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
8534 ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetInputType returned %#lx.\n", hr);
8535 init_media_type(media_type, input_type_desc, 1);
8536 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
8537 ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetInputType returned %#lx.\n", hr);
8538 init_media_type(media_type, input_type_desc, 2);
8539 for (i = 2; i < ARRAY_SIZE(input_type_desc) - 1; ++i)
8541 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
8542 ok(hr == E_INVALIDARG, "SetInputType returned %#lx.\n", hr);
8543 init_media_type(media_type, input_type_desc, i + 1);
8545 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
8546 ok(hr == S_OK, "SetInputType returned %#lx.\n", hr);
8547 ret = IMFMediaType_Release(media_type);
8548 ok(ret == 0, "Release returned %lu\n", ret);
8550 memset(&input_info, 0xcd, sizeof(input_info));
8551 hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info);
8552 ok(hr == S_OK, "GetInputStreamInfo returned %#lx\n", hr);
8553 ok(input_info.hnsMaxLatency == 0, "got hnsMaxLatency %s\n", wine_dbgstr_longlong(input_info.hnsMaxLatency));
8554 ok(input_info.dwFlags == 0, "got dwFlags %#lx\n", input_info.dwFlags);
8555 ok(input_info.cbSize == actual_width * actual_height * 3 / 2, "got cbSize %#lx\n", input_info.cbSize);
8556 ok(input_info.cbMaxLookahead == 0, "got cbMaxLookahead %#lx\n", input_info.cbMaxLookahead);
8557 ok(input_info.cbAlignment == 1, "got cbAlignment %#lx\n", input_info.cbAlignment);
8559 memset(&output_info, 0xcd, sizeof(output_info));
8560 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
8561 ok(hr == S_OK, "GetOutputStreamInfo returned %#lx\n", hr);
8562 ok(output_info.dwFlags == 0, "got dwFlags %#lx\n", output_info.dwFlags);
8563 ok(output_info.cbSize == actual_width * actual_height * 4, "got cbSize %#lx\n", output_info.cbSize);
8564 ok(output_info.cbAlignment == 1, "got cbAlignment %#lx\n", output_info.cbAlignment);
8566 resource = FindResourceW(NULL, L"nv12frame.bin", (const WCHAR *)RT_RCDATA);
8567 ok(resource != 0, "FindResourceW failed, error %lu\n", GetLastError());
8568 nv12frame_data = LockResource(LoadResource(GetModuleHandleW(NULL), resource));
8569 nv12frame_data_len = SizeofResource(GetModuleHandleW(NULL), resource);
8570 ok(nv12frame_data_len == 13824, "got length %lu\n", nv12frame_data_len);
8572 sample = create_sample(nv12frame_data, nv12frame_data_len);
8573 hr = IMFSample_SetSampleTime(sample, 0);
8574 ok(hr == S_OK, "SetSampleTime returned %#lx\n", hr);
8575 hr = IMFSample_SetSampleDuration(sample, 10000000);
8576 ok(hr == S_OK, "SetSampleDuration returned %#lx\n", hr);
8577 hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
8578 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
8579 hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
8580 ok(hr == MF_E_NOTACCEPTING, "ProcessInput returned %#lx\n", hr);
8581 hr = IMFTransform_ProcessMessage(transform, MFT_MESSAGE_COMMAND_DRAIN, 0);
8582 ok(hr == S_OK, "ProcessMessage returned %#lx\n", hr);
8583 ret = IMFSample_Release(sample);
8584 ok(ret <= 1, "Release returned %ld\n", ret);
8586 resource = FindResourceW(NULL, L"rgb32frame.bin", (const WCHAR *)RT_RCDATA);
8587 ok(resource != 0, "FindResourceW failed, error %lu\n", GetLastError());
8588 rgb32_data = LockResource(LoadResource(GetModuleHandleW(NULL), resource));
8589 rgb32_data_len = SizeofResource(GetModuleHandleW(NULL), resource);
8590 ok(rgb32_data_len == output_info.cbSize, "got length %lu\n", rgb32_data_len);
8592 /* and generate a new one as well in a temporary directory */
8593 GetTempPathW(ARRAY_SIZE(output_path), output_path);
8594 lstrcatW(output_path, L"rgb32frame.bin");
8595 output_file = CreateFileW(output_path, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
8596 ok(output_file != INVALID_HANDLE_VALUE, "CreateFileW failed, error %lu\n", GetLastError());
8598 status = 0xdeadbeef;
8599 sample = create_sample(NULL, output_info.cbSize);
8600 memset(&output, 0, sizeof(output));
8601 output.pSample = sample;
8602 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
8603 ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr);
8604 ok(output.pSample == sample, "got pSample %p\n", output.pSample);
8605 ok(output.dwStatus == 0 || broken(output.dwStatus == 6) /* win7 */, "got dwStatus %#lx\n", output.dwStatus);
8606 ok(status == 0, "got status %#lx\n", status);
8608 hr = IMFSample_GetSampleTime(sample, &time);
8609 ok(hr == S_OK, "GetSampleTime returned %#lx\n", hr);
8610 ok(time == 0, "got time %I64d\n", time);
8611 hr = IMFSample_GetSampleDuration(sample, &duration);
8612 ok(hr == S_OK, "GetSampleDuration returned %#lx\n", hr);
8613 ok(duration == 10000000, "got duration %I64d\n", duration);
8614 hr = IMFSample_GetTotalLength(sample, &length);
8615 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
8616 ok(length == output_info.cbSize, "got length %lu\n", length);
8617 check_sample_rgb32(sample, rgb32_data, output_file);
8618 rgb32_data_len -= output_info.cbSize;
8619 rgb32_data += output_info.cbSize;
8621 trace("created %s\n", debugstr_w(output_path));
8622 CloseHandle(output_file);
8624 ret = IMFSample_Release(sample);
8625 ok(ret == 0, "Release returned %lu\n", ret);
8627 status = 0xdeadbeef;
8628 sample = create_sample(NULL, output_info.cbSize);
8629 memset(&output, 0, sizeof(output));
8630 output.pSample = sample;
8631 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
8632 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
8633 ok(output.pSample == sample, "got pSample %p\n", output.pSample);
8634 ok(output.dwStatus == 0, "got dwStatus %#lx\n", output.dwStatus);
8635 ok(status == 0, "got status %#lx\n", status);
8636 hr = IMFSample_GetTotalLength(sample, &length);
8637 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
8638 ok(length == 0, "got length %lu\n", length);
8639 ret = IMFSample_Release(sample);
8640 ok(ret == 0, "Release returned %lu\n", ret);
8642 ret = IMFTransform_Release(transform);
8643 ok(ret == 0, "Release returned %ld\n", ret);
8645 failed:
8646 CoUninitialize();
8650 START_TEST(mf)
8652 init_functions();
8654 if (is_vista())
8656 win_skip("Skipping tests on Vista.\n");
8657 return;
8660 test_video_processor();
8661 test_topology();
8662 test_topology_tee_node();
8663 test_topology_loader();
8664 test_topology_loader_evr();
8665 test_MFGetService();
8666 test_sequencer_source();
8667 test_media_session();
8668 test_media_session_rate_control();
8669 test_MFShutdownObject();
8670 test_presentation_clock();
8671 test_sample_grabber();
8672 test_sample_grabber_is_mediatype_supported();
8673 test_quality_manager();
8674 test_sar();
8675 test_evr();
8676 test_MFCreateSimpleTypeHandler();
8677 test_MFGetSupportedMimeTypes();
8678 test_MFGetSupportedSchemes();
8679 test_sample_copier();
8680 test_sample_copier_output_processing();
8681 test_MFGetTopoNodeCurrentType();
8682 test_MFRequireProtectedEnvironment();
8683 test_wma_encoder();
8684 test_wma_decoder();
8685 test_h264_decoder();
8686 test_audio_convert();
8687 test_color_convert();